From be67b37359d44a20055ae1ff75127d1cdede1b57 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Dec 2024 12:19:36 +0000 Subject: [PATCH] Bump the gomod-dependencies group across 1 directory with 13 updates Bumps the gomod-dependencies group with 4 updates in the / directory: [github.com/coredns/coredns](https://github.com/coredns/coredns), [github.com/vishvananda/netlink](https://github.com/vishvananda/netlink), [go.etcd.io/etcd/client/v2](https://github.com/etcd-io/etcd) and [k8s.io/kubernetes](https://github.com/kubernetes/kubernetes). Updates `github.com/coredns/coredns` from 1.11.3 to 1.12.0 - [Release notes](https://github.com/coredns/coredns/releases) - [Changelog](https://github.com/coredns/coredns/blob/master/Makefile.release) - [Commits](https://github.com/coredns/coredns/compare/v1.11.3...v1.12.0) Updates `github.com/miekg/dns` from 1.1.58 to 1.1.62 - [Changelog](https://github.com/miekg/dns/blob/master/Makefile.release) - [Commits](https://github.com/miekg/dns/compare/v1.1.58...v1.1.62) Updates `github.com/onsi/gomega` from 1.27.10 to 1.33.1 - [Release notes](https://github.com/onsi/gomega/releases) - [Changelog](https://github.com/onsi/gomega/blob/master/CHANGELOG.md) - [Commits](https://github.com/onsi/gomega/compare/v1.27.10...v1.33.1) Updates `github.com/prometheus/client_golang` from 1.19.0 to 1.20.5 - [Release notes](https://github.com/prometheus/client_golang/releases) - [Changelog](https://github.com/prometheus/client_golang/blob/main/CHANGELOG.md) - [Commits](https://github.com/prometheus/client_golang/compare/v1.19.0...v1.20.5) Updates `github.com/stretchr/testify` from 1.8.4 to 1.9.0 - [Release notes](https://github.com/stretchr/testify/releases) - [Commits](https://github.com/stretchr/testify/compare/v1.8.4...v1.9.0) Updates `github.com/vishvananda/netlink` from 1.1.0 to 1.3.0 - [Release notes](https://github.com/vishvananda/netlink/releases) - [Commits](https://github.com/vishvananda/netlink/compare/v1.1.0...v1.3.0) Updates `go.etcd.io/etcd/api/v3` from 3.5.12 to 3.5.17 - [Release notes](https://github.com/etcd-io/etcd/releases) - [Commits](https://github.com/etcd-io/etcd/compare/v3.5.12...v3.5.17) Updates `go.etcd.io/etcd/client/v2` from 2.305.9 to 2.305.17 - [Release notes](https://github.com/etcd-io/etcd/releases) - [Commits](https://github.com/etcd-io/etcd/compare/client/v2.305.9...client/v2.305.17) Updates `go.etcd.io/etcd/client/v3` from 3.5.12 to 3.5.17 - [Release notes](https://github.com/etcd-io/etcd/releases) - [Commits](https://github.com/etcd-io/etcd/compare/v3.5.12...v3.5.17) Updates `golang.org/x/net` from 0.23.0 to 0.31.0 - [Commits](https://github.com/golang/net/compare/v0.23.0...v0.31.0) Updates `k8s.io/klog/v2` from 2.120.1 to 2.130.1 - [Release notes](https://github.com/kubernetes/klog/releases) - [Changelog](https://github.com/kubernetes/klog/blob/main/RELEASE.md) - [Commits](https://github.com/kubernetes/klog/compare/v2.120.1...v2.130.1) Updates `k8s.io/kubernetes` from 1.28.14 to 1.31.3 - [Release notes](https://github.com/kubernetes/kubernetes/releases) - [Commits](https://github.com/kubernetes/kubernetes/compare/v1.28.14...v1.31.3) Updates `k8s.io/utils` from 0.0.0-20230726121419-3b25d923346b to 0.0.0-20240711033017-18e509b52bc8 - [Commits](https://github.com/kubernetes/utils/commits) --- updated-dependencies: - dependency-name: github.com/coredns/coredns dependency-type: direct:production update-type: version-update:semver-minor dependency-group: gomod-dependencies - dependency-name: github.com/miekg/dns dependency-type: direct:production update-type: version-update:semver-patch dependency-group: gomod-dependencies - dependency-name: github.com/onsi/gomega dependency-type: direct:production update-type: version-update:semver-minor dependency-group: gomod-dependencies - dependency-name: github.com/prometheus/client_golang dependency-type: direct:production update-type: version-update:semver-minor dependency-group: gomod-dependencies - dependency-name: github.com/stretchr/testify dependency-type: direct:production update-type: version-update:semver-minor dependency-group: gomod-dependencies - dependency-name: github.com/vishvananda/netlink dependency-type: direct:production update-type: version-update:semver-minor dependency-group: gomod-dependencies - dependency-name: go.etcd.io/etcd/api/v3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: gomod-dependencies - dependency-name: go.etcd.io/etcd/client/v2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: gomod-dependencies - dependency-name: go.etcd.io/etcd/client/v3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: gomod-dependencies - dependency-name: golang.org/x/net dependency-type: direct:production update-type: version-update:semver-minor dependency-group: gomod-dependencies - dependency-name: k8s.io/klog/v2 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: gomod-dependencies - dependency-name: k8s.io/kubernetes dependency-type: direct:production update-type: version-update:semver-minor dependency-group: gomod-dependencies - dependency-name: k8s.io/utils dependency-type: direct:production update-type: version-update:semver-patch dependency-group: gomod-dependencies ... Signed-off-by: dependabot[bot] --- go.mod | 124 +- go.sum | 339 +- .../appsec-internal-go/appsec/config.go | 41 +- .../appsec-internal-go/appsec/embed.go | 10 +- .../appsec-internal-go/appsec/processors.json | 208 - .../appsec-internal-go/appsec/rules.go | 7 - .../appsec-internal-go/appsec/rules.json | 427 +- .../appsec-internal-go/httpsec/client_ip.go | 126 + .../DataDog/appsec-internal-go/netip/ip.go | 31 + .../pkg/remoteconfig/state/configs_asm.go | 9 +- .../pkg/remoteconfig/state/products.go | 61 +- .../pkg/remoteconfig/state/repository.go | 4 +- .../DataDog/go-libddwaf/v2/context.go | 195 - .../DataDog/go-libddwaf/v2/ctypes.go | 206 - .../DataDog/go-libddwaf/v2/decoder.go | 239 - .../go-libddwaf/v2/internal/lib/.version | 1 - .../go-libddwaf/v2/internal/lib/lib.go | 49 - .../internal/lib/libddwaf-darwin-amd64.dylib | Bin 1566256 -> 0 bytes .../internal/lib/libddwaf-darwin-arm64.dylib | Bin 1436976 -> 0 bytes .../v2/internal/lib/libddwaf-linux-amd64.so | Bin 2136144 -> 0 bytes .../v2/internal/lib/libddwaf-linux-arm64.so | Bin 2030704 -> 0 bytes .../go-libddwaf/v2/internal/log/gostring.go | 24 - .../v2/internal/noopfree/noopfree.go | 15 - .../github.com/DataDog/go-libddwaf/v2/safe.go | 68 - .../go-libddwaf/v2/symbols_linux_cgo.go | 21 - .../go-libddwaf/v2/symbols_linux_purego.go | 15 - .../go-libddwaf/v2/waf_dl_unsupported.go | 52 - .../DataDog/go-libddwaf/v2/waf_support.go | 85 - .../go-libddwaf/{v2 => v3}/.gitattributes | 0 .../DataDog/go-libddwaf/{v2 => v3}/.gitignore | 5 + .../DataDog/go-libddwaf/v3/CODEOWNERS | 2 + .../DataDog/go-libddwaf/{v2 => v3}/LICENSE | 0 .../DataDog/go-libddwaf/{v2 => v3}/README.md | 35 +- .../go-libddwaf/{v2 => v3}/cgo_ref_pool.go | 49 +- .../DataDog/go-libddwaf/v3/context.go | 327 + .../DataDog/go-libddwaf/v3/decoder.go | 247 + .../DataDog/go-libddwaf/{v2 => v3}/encoder.go | 154 +- .../DataDog/go-libddwaf/v3/errors/support.go | 45 + .../DataDog/go-libddwaf/v3/errors/waf.go | 77 + .../DataDog/go-libddwaf/{v2 => v3}/handle.go | 137 +- .../v3/internal/bindings/ctypes.go | 113 + .../go-libddwaf/v3/internal/bindings/safe.go | 47 + .../{v2 => v3/internal/bindings}/waf_dl.go | 146 +- .../internal/bindings/waf_dl_unsupported.go | 55 + .../go-libddwaf/v3/internal/lib/.version | 1 + .../{v2 => v3}/internal/lib/README.md | 0 .../{v2 => v3}/internal/lib/doc.go | 0 .../v3/internal/lib/dump_waf_darwin.go | 57 + .../v3/internal/lib/dump_waf_linux.go | 58 + .../internal/lib/lib_darwin_amd64.go | 6 +- .../internal/lib/lib_darwin_arm64.go | 6 +- .../internal/lib/lib_linux_amd64.go | 6 +- .../internal/lib/lib_linux_arm64.go | 6 +- .../lib/libddwaf-darwin-amd64.dylib.gz | Bin 0 -> 682821 bytes .../lib/libddwaf-darwin-arm64.dylib.gz | Bin 0 -> 627228 bytes .../internal/lib/libddwaf-linux-amd64.so.gz | Bin 0 -> 862545 bytes .../internal/lib/libddwaf-linux-arm64.so.gz | Bin 0 -> 815394 bytes .../noopfree.s => v3/internal/lib/version.go} | 12 +- .../{v2 => v3}/internal/log/ddwaf.h | 30 +- .../{v2 => v3}/internal/log/log.go | 0 .../{v2 => v3}/internal/log/log_cgo.go | 16 +- .../{v2 => v3}/internal/log/log_purego.go | 9 +- .../internal/log/log_unsupported.go | 2 +- .../internal/support}/waf_cgo_disabled.go | 8 +- .../support}/waf_manually_disabled.go | 6 +- .../v3/internal/support/waf_support.go | 21 + .../internal/support}/waf_unsupported_go.go | 8 +- .../support}/waf_unsupported_target.go | 6 +- .../go-libddwaf/v3/internal/unsafe/utils.go | 107 + .../DataDog/go-libddwaf/v3/metrics.go | 140 + .../go-libddwaf/v3/timer/base_timer.go | 125 + .../DataDog/go-libddwaf/v3/timer/clock.go | 28 + .../DataDog/go-libddwaf/v3/timer/component.go | 28 + .../DataDog/go-libddwaf/v3/timer/config.go | 86 + .../go-libddwaf/v3/timer/node_timer.go | 147 + .../DataDog/go-libddwaf/v3/timer/timer.go | 115 + .../DataDog/go-libddwaf/{v2 => v3}/waf.go | 102 +- .../DataDog/go-tuf/client/client.go | 99 +- .../DataDog/go-tuf/client/delegations.go | 53 +- .../DataDog/sketches-go/ddsketch/ddsketch.go | 16 +- .../ddsketch/mapping/index_mapping.go | 3 + .../ddsketch/store/buffered_paginated.go | 2 +- vendor/github.com/cespare/xxhash/v2/README.md | 2 + vendor/github.com/cespare/xxhash/v2/xxhash.go | 29 +- .../cespare/xxhash/v2/xxhash_asm.go | 2 +- .../cespare/xxhash/v2/xxhash_other.go | 2 +- .../cespare/xxhash/v2/xxhash_safe.go | 2 +- .../cespare/xxhash/v2/xxhash_unsafe.go | 2 +- vendor/github.com/coredns/caddy/README.md | 4 + vendor/github.com/coredns/caddy/caddy.go | 25 +- vendor/github.com/coredns/caddy/plugins.go | 32 +- .../coredns/coredns/core/dnsserver/config.go | 4 + .../coredns/core/dnsserver/register.go | 145 +- .../coredns/core/dnsserver/server_https.go | 2 +- .../coredns/core/dnsserver/zdirectives.go | 1 + .../coredns/coredns/coremain/run.go | 9 +- .../coredns/coredns/coremain/version.go | 4 +- .../coredns/coredns/plugin/bind/README.md | 2 +- .../coredns/coredns/plugin/bind/setup.go | 14 +- .../coredns/coredns/plugin/dnstap/README.md | 10 +- .../coredns/coredns/plugin/dnstap/handler.go | 10 +- .../coredns/coredns/plugin/dnstap/io.go | 38 +- .../coredns/coredns/plugin/dnstap/setup.go | 28 +- .../coredns/coredns/plugin/forward/README.md | 17 + .../coredns/coredns/plugin/forward/forward.go | 11 + .../coredns/coredns/plugin/forward/fuzz.go | 4 +- .../coredns/coredns/plugin/forward/setup.go | 16 + .../coredns/coredns/plugin/hosts/hostsfile.go | 2 +- .../coredns/coredns/plugin/hosts/metrics.go | 2 +- .../coredns/coredns/plugin/rewrite/README.md | 25 +- .../coredns/coredns/plugin/rewrite/edns0.go | 118 +- .../coredns/plugin/rewrite/reverter.go | 5 +- vendor/github.com/eapache/queue/v2/LICENSE | 21 + vendor/github.com/eapache/queue/v2/queue.go | 102 + .../github.com/fsnotify/fsnotify/.cirrus.yml | 13 + .../github.com/fsnotify/fsnotify/.gitignore | 1 + .../github.com/fsnotify/fsnotify/CHANGELOG.md | 83 +- vendor/github.com/fsnotify/fsnotify/README.md | 81 +- .../fsnotify/fsnotify/backend_fen.go | 552 +- .../fsnotify/fsnotify/backend_inotify.go | 377 +- .../fsnotify/fsnotify/backend_kqueue.go | 295 +- .../fsnotify/fsnotify/backend_other.go | 205 +- .../fsnotify/fsnotify/backend_windows.go | 247 +- .../github.com/fsnotify/fsnotify/fsnotify.go | 91 +- vendor/github.com/fsnotify/fsnotify/mkdoc.zsh | 125 +- vendor/github.com/go-logr/logr/README.md | 1 + vendor/github.com/go-openapi/swag/util.go | 16 +- .../go-task/slim-sprig/v3/.editorconfig | 14 + .../go-task/slim-sprig/v3/.gitattributes | 1 + .../go-task/slim-sprig/v3/.gitignore | 2 + .../go-task/slim-sprig/v3/CHANGELOG.md | 383 + .../go-task/slim-sprig/v3/LICENSE.txt | 19 + .../go-task/slim-sprig/v3/README.md | 73 + .../go-task/slim-sprig/v3/Taskfile.yml | 12 + .../go-task/slim-sprig/v3/crypto.go | 24 + .../github.com/go-task/slim-sprig/v3/date.go | 152 + .../go-task/slim-sprig/v3/defaults.go | 163 + .../github.com/go-task/slim-sprig/v3/dict.go | 118 + .../github.com/go-task/slim-sprig/v3/doc.go | 19 + .../go-task/slim-sprig/v3/functions.go | 317 + .../github.com/go-task/slim-sprig/v3/list.go | 464 + .../go-task/slim-sprig/v3/network.go | 12 + .../go-task/slim-sprig/v3/numeric.go | 228 + .../go-task/slim-sprig/v3/reflect.go | 28 + .../github.com/go-task/slim-sprig/v3/regex.go | 83 + .../go-task/slim-sprig/v3/strings.go | 189 + .../github.com/go-task/slim-sprig/v3/url.go | 66 + .../github.com/google/pprof/profile/encode.go | 3 + .../pprof/profile/legacy_java_profile.go | 4 +- .../github.com/google/pprof/profile/merge.go | 4 +- .../google/pprof/profile/profile.go | 16 +- vendor/github.com/hashicorp/errwrap/README.md | 89 - .../github.com/hashicorp/errwrap/errwrap.go | 178 - .../hashicorp/go-multierror/Makefile | 31 - .../hashicorp/go-multierror/README.md | 150 - .../hashicorp/go-multierror/append.go | 43 - .../hashicorp/go-multierror/flatten.go | 26 - .../hashicorp/go-multierror/format.go | 27 - .../hashicorp/go-multierror/group.go | 38 - .../hashicorp/go-multierror/multierror.go | 121 - .../hashicorp/go-multierror/prefix.go | 37 - .../hashicorp/go-multierror/sort.go | 16 - .../parseutil}/LICENSE | 301 +- .../go-secure-stdlib/parseutil/parsepath.go | 65 + .../go-secure-stdlib/parseutil/parseutil.go | 502 + .../strutil}/LICENSE | 302 +- .../go-secure-stdlib/strutil/strutil.go | 510 + .../hashicorp/go-sockaddr/.gitignore | 26 + .../hashicorp/go-sockaddr/GNUmakefile | 65 + .../github.com/hashicorp/go-sockaddr/LICENSE | 373 + .../hashicorp/go-sockaddr/README.md | 118 + .../github.com/hashicorp/go-sockaddr/doc.go | 5 + .../hashicorp/go-sockaddr/ifaddr.go | 254 + .../hashicorp/go-sockaddr/ifaddrs.go | 1304 ++ .../hashicorp/go-sockaddr/ifattr.go | 65 + .../hashicorp/go-sockaddr/ipaddr.go | 169 + .../hashicorp/go-sockaddr/ipaddrs.go | 98 + .../hashicorp/go-sockaddr/ipv4addr.go | 516 + .../hashicorp/go-sockaddr/ipv6addr.go | 591 + .../github.com/hashicorp/go-sockaddr/rfc.go | 948 + .../hashicorp/go-sockaddr/route_info.go | 19 + .../go-sockaddr/route_info_android.go | 34 + .../hashicorp/go-sockaddr/route_info_bsd.go | 36 + .../go-sockaddr/route_info_default.go | 10 + .../hashicorp/go-sockaddr/route_info_linux.go | 42 + .../go-sockaddr/route_info_solaris.go | 37 + .../go-sockaddr/route_info_windows.go | 41 + .../hashicorp/go-sockaddr/sockaddr.go | 206 + .../hashicorp/go-sockaddr/sockaddrs.go | 193 + .../hashicorp/go-sockaddr/unixsock.go | 135 + .../klauspost/compress/.gitattributes | 2 + .../github.com/klauspost/compress/.gitignore | 32 + .../klauspost/compress/.goreleaser.yml | 123 + vendor/github.com/klauspost/compress/LICENSE | 304 + .../github.com/klauspost/compress/README.md | 700 + .../github.com/klauspost/compress/SECURITY.md | 25 + .../klauspost/compress/compressible.go | 85 + .../klauspost/compress/fse/README.md | 79 + .../klauspost/compress/fse/bitreader.go | 122 + .../klauspost/compress/fse/bitwriter.go | 167 + .../klauspost/compress/fse/bytereader.go | 47 + .../klauspost/compress/fse/compress.go | 683 + .../klauspost/compress/fse/decompress.go | 376 + .../github.com/klauspost/compress/fse/fse.go | 144 + vendor/github.com/klauspost/compress/gen.sh | 4 + .../klauspost/compress/huff0/.gitignore | 1 + .../klauspost/compress/huff0/README.md | 89 + .../klauspost/compress/huff0/bitreader.go | 229 + .../klauspost/compress/huff0/bitwriter.go | 102 + .../klauspost/compress/huff0/compress.go | 742 + .../klauspost/compress/huff0/decompress.go | 1167 ++ .../compress/huff0/decompress_amd64.go | 226 + .../compress/huff0/decompress_amd64.s | 830 + .../compress/huff0/decompress_generic.go | 299 + .../klauspost/compress/huff0/huff0.go | 337 + .../compress/internal/cpuinfo/cpuinfo.go | 34 + .../internal/cpuinfo/cpuinfo_amd64.go | 11 + .../compress/internal/cpuinfo/cpuinfo_amd64.s | 36 + .../compress/internal/snapref/LICENSE | 27 + .../compress/internal/snapref/decode.go | 264 + .../compress/internal/snapref/decode_other.go | 113 + .../compress/internal/snapref/encode.go | 289 + .../compress/internal/snapref/encode_other.go | 250 + .../compress/internal/snapref/snappy.go | 98 + vendor/github.com/klauspost/compress/s2sx.mod | 4 + vendor/github.com/klauspost/compress/s2sx.sum | 0 .../klauspost/compress/zstd/README.md | 441 + .../klauspost/compress/zstd/bitreader.go | 136 + .../klauspost/compress/zstd/bitwriter.go | 112 + .../klauspost/compress/zstd/blockdec.go | 729 + .../klauspost/compress/zstd/blockenc.go | 909 + .../compress/zstd/blocktype_string.go | 85 + .../klauspost/compress/zstd/bytebuf.go | 131 + .../klauspost/compress/zstd/bytereader.go | 82 + .../klauspost/compress/zstd/decodeheader.go | 261 + .../klauspost/compress/zstd/decoder.go | 948 + .../compress/zstd/decoder_options.go | 169 + .../klauspost/compress/zstd/dict.go | 565 + .../klauspost/compress/zstd/enc_base.go | 173 + .../klauspost/compress/zstd/enc_best.go | 560 + .../klauspost/compress/zstd/enc_better.go | 1252 ++ .../klauspost/compress/zstd/enc_dfast.go | 1123 + .../klauspost/compress/zstd/enc_fast.go | 891 + .../klauspost/compress/zstd/encoder.go | 619 + .../compress/zstd/encoder_options.go | 339 + .../klauspost/compress/zstd/framedec.go | 413 + .../klauspost/compress/zstd/frameenc.go | 137 + .../klauspost/compress/zstd/fse_decoder.go | 307 + .../compress/zstd/fse_decoder_amd64.go | 65 + .../compress/zstd/fse_decoder_amd64.s | 126 + .../compress/zstd/fse_decoder_generic.go | 73 + .../klauspost/compress/zstd/fse_encoder.go | 701 + .../klauspost/compress/zstd/fse_predefined.go | 158 + .../klauspost/compress/zstd/hash.go | 35 + .../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 + .../zstd/internal/xxhash/xxhash_amd64.s | 210 + .../zstd/internal/xxhash/xxhash_arm64.s | 184 + .../zstd/internal/xxhash/xxhash_asm.go | 16 + .../zstd/internal/xxhash/xxhash_other.go | 76 + .../zstd/internal/xxhash/xxhash_safe.go | 11 + .../klauspost/compress/zstd/matchlen_amd64.go | 16 + .../klauspost/compress/zstd/matchlen_amd64.s | 66 + .../compress/zstd/matchlen_generic.go | 33 + .../klauspost/compress/zstd/seqdec.go | 503 + .../klauspost/compress/zstd/seqdec_amd64.go | 394 + .../klauspost/compress/zstd/seqdec_amd64.s | 4151 ++++ .../klauspost/compress/zstd/seqdec_generic.go | 237 + .../klauspost/compress/zstd/seqenc.go | 114 + .../klauspost/compress/zstd/snappy.go | 434 + .../github.com/klauspost/compress/zstd/zip.go | 141 + .../klauspost/compress/zstd/zstd.go | 121 + vendor/github.com/miekg/dns/README.md | 6 + vendor/github.com/miekg/dns/defaults.go | 8 +- vendor/github.com/miekg/dns/edns.go | 62 +- vendor/github.com/miekg/dns/msg.go | 2 +- vendor/github.com/miekg/dns/scan.go | 11 +- vendor/github.com/miekg/dns/scan_rr.go | 69 +- vendor/github.com/miekg/dns/server.go | 19 +- vendor/github.com/miekg/dns/svcb.go | 50 +- vendor/github.com/miekg/dns/types.go | 14 + vendor/github.com/miekg/dns/version.go | 2 +- vendor/github.com/miekg/dns/xfr.go | 11 +- vendor/github.com/miekg/dns/zduplicate.go | 9 + vendor/github.com/miekg/dns/zmsg.go | 11 + vendor/github.com/miekg/dns/ztypes.go | 12 + .../mitchellh/mapstructure/CHANGELOG.md | 96 + .../github.com/mitchellh/mapstructure/LICENSE | 21 + .../mitchellh/mapstructure/README.md | 46 + .../mitchellh/mapstructure/decode_hooks.go | 279 + .../mitchellh/mapstructure/error.go | 50 + .../mitchellh/mapstructure/mapstructure.go | 1540 ++ .../v2/ginkgo/generators/bootstrap_command.go | 2 +- .../v2/ginkgo/generators/generate_command.go | 3 +- .../ginkgo/v2/ginkgo/internal/gocovmerge.go | 129 + .../ginkgo/internal/profiles_and_reports.go | 46 +- .../ginkgo/v2/ginkgo/internal/test_suite.go | 9 +- .../onsi/ginkgo/v2/ginkgo/outline/ginkgo.go | 3 +- .../onsi/ginkgo/v2/ginkgo/outline/import.go | 9 +- .../ginkgo/v2/ginkgo/watch/dependencies.go | 2 +- .../ginkgo/v2/ginkgo/watch/package_hash.go | 13 +- .../ginkgo/v2/reporters/default_reporter.go | 61 +- .../onsi/ginkgo/v2/reporters/json_report.go | 6 +- .../onsi/ginkgo/v2/reporters/junit_report.go | 14 + .../onsi/ginkgo/v2/types/code_location.go | 2 +- .../github.com/onsi/ginkgo/v2/types/config.go | 14 +- .../github.com/onsi/ginkgo/v2/types/errors.go | 9 + .../github.com/onsi/ginkgo/v2/types/flags.go | 15 +- .../onsi/ginkgo/v2/types/label_filter.go | 229 +- .../onsi/ginkgo/v2/types/version.go | 2 +- vendor/github.com/onsi/gomega/CHANGELOG.md | 95 + vendor/github.com/onsi/gomega/gomega_dsl.go | 14 +- .../onsi/gomega/internal/async_assertion.go | 7 +- vendor/github.com/onsi/gomega/matchers.go | 73 +- .../matchers/be_comparable_to_matcher.go | 4 +- .../onsi/gomega/matchers/be_false_matcher.go | 13 +- .../onsi/gomega/matchers/be_true_matcher.go | 13 +- .../gomega/matchers/have_http_body_matcher.go | 9 +- .../gomega/matchers/match_error_matcher.go | 25 +- .../onsi/gomega/matchers/receive_matcher.go | 70 +- .../openzipkin/zipkin-go/.golangci.yml | 11 +- .../github.com/openzipkin/zipkin-go/README.md | 14 +- .../openzipkin/zipkin-go/SECURITY.md | 13 + .../zipkin-go/span_implementation.go | 6 + .../openzipkin/zipkin-go/span_options.go | 10 +- vendor/github.com/philhofer/fwd/README.md | 9 + .../github.com/philhofer/fwd/writer_tinygo.go | 8 +- .../prometheus/client_golang/NOTICE | 5 - .../internal/github.com/golang/gddo/LICENSE | 27 + .../golang/gddo/httputil/header/header.go | 145 + .../golang/gddo/httputil/negotiate.go | 36 + .../collectors/go_collector_latest.go | 4 +- .../client_golang/prometheus/go_collector.go | 55 +- .../prometheus/go_collector_latest.go | 19 +- .../client_golang/prometheus/histogram.go | 268 +- .../internal/go_collector_options.go | 2 + .../client_golang/prometheus/metric.go | 2 +- .../prometheus/process_collector.go | 29 +- .../prometheus/process_collector_other.go | 14 + .../prometheus/promhttp/delegator.go | 6 + .../client_golang/prometheus/promhttp/http.go | 113 +- .../client_golang/prometheus/registry.go | 17 +- .../client_golang/prometheus/summary.go | 42 + .../client_golang/prometheus/vec.go | 2 +- .../prometheus/common/expfmt/decode.go | 14 +- .../prometheus/common/expfmt/encode.go | 27 +- .../prometheus/common/expfmt/expfmt.go | 76 +- .../common/expfmt/openmetrics_create.go | 2 +- .../prometheus/common/expfmt/text_create.go | 4 +- .../prometheus/common/expfmt/text_parse.go | 162 +- .../bitbucket.org/ww/goautoneg/README.txt | 67 - .../bitbucket.org/ww/goautoneg/autoneg.go | 160 - .../prometheus/common/model/labels.go | 27 +- .../common/model/labelset_string.go | 2 - .../common/model/labelset_string_go120.go | 39 - .../prometheus/common/model/metric.go | 31 +- .../prometheus/procfs/.golangci.yml | 7 + .../prometheus/procfs/MAINTAINERS.md | 3 +- .../prometheus/procfs/Makefile.common | 26 +- vendor/github.com/prometheus/procfs/arp.go | 6 +- .../github.com/prometheus/procfs/buddyinfo.go | 6 +- .../github.com/prometheus/procfs/cpuinfo.go | 4 +- vendor/github.com/prometheus/procfs/crypto.go | 6 +- .../github.com/prometheus/procfs/fscache.go | 4 +- vendor/github.com/prometheus/procfs/ipvs.go | 6 +- .../github.com/prometheus/procfs/loadavg.go | 2 +- vendor/github.com/prometheus/procfs/mdstat.go | 60 +- .../github.com/prometheus/procfs/meminfo.go | 220 +- .../github.com/prometheus/procfs/mountinfo.go | 2 +- .../prometheus/procfs/mountstats.go | 11 +- .../prometheus/procfs/net_conntrackstat.go | 4 +- .../prometheus/procfs/net_ip_socket.go | 46 +- .../prometheus/procfs/net_sockstat.go | 4 +- .../prometheus/procfs/net_softnet.go | 2 +- .../prometheus/procfs/net_tls_stat.go | 119 + .../github.com/prometheus/procfs/net_unix.go | 14 +- .../prometheus/procfs/net_wireless.go | 22 +- vendor/github.com/prometheus/procfs/proc.go | 8 +- .../prometheus/procfs/proc_limits.go | 2 +- .../github.com/prometheus/procfs/proc_ns.go | 4 +- .../github.com/prometheus/procfs/proc_psi.go | 2 +- .../prometheus/procfs/proc_smaps.go | 2 +- .../github.com/prometheus/procfs/proc_stat.go | 7 + .../prometheus/procfs/proc_status.go | 29 +- .../github.com/prometheus/procfs/proc_sys.go | 2 +- .../github.com/prometheus/procfs/softirqs.go | 22 +- vendor/github.com/prometheus/procfs/stat.go | 22 +- vendor/github.com/prometheus/procfs/swaps.go | 6 +- vendor/github.com/prometheus/procfs/thread.go | 2 +- .../github.com/prometheus/procfs/zoneinfo.go | 4 +- vendor/github.com/quic-go/quic-go/.gitignore | 1 + .../github.com/quic-go/quic-go/.golangci.yml | 21 +- vendor/github.com/quic-go/quic-go/README.md | 205 +- vendor/github.com/quic-go/quic-go/client.go | 4 +- vendor/github.com/quic-go/quic-go/config.go | 11 + .../github.com/quic-go/quic-go/connection.go | 358 +- .../quic-go/quic-go/connection_logging.go | 173 + .../quic-go/quic-go/crypto_stream.go | 49 +- .../quic-go/quic-go/crypto_stream_manager.go | 51 +- vendor/github.com/quic-go/quic-go/errors.go | 2 +- vendor/github.com/quic-go/quic-go/framer.go | 138 +- .../github.com/quic-go/quic-go/interface.go | 55 +- .../ackhandler/received_packet_history.go | 104 +- .../ackhandler/sent_packet_handler.go | 10 +- .../ackhandler/sent_packet_history.go | 11 +- .../quic-go/internal/congestion/cubic.go | 8 +- .../internal/congestion/cubic_sender.go | 2 +- .../flowcontrol/connection_flow_controller.go | 10 +- .../quic-go/internal/flowcontrol/interface.go | 6 +- .../flowcontrol/stream_flow_controller.go | 22 +- .../internal/handshake/crypto_setup.go | 69 +- .../quic-go/internal/handshake/interface.go | 26 +- .../internal/handshake/session_ticket.go | 12 +- .../internal/handshake/token_generator.go | 2 +- .../internal/handshake/token_protector.go | 20 +- .../quic-go/internal/logutils/frame.go | 50 - .../internal/protocol/packet_number.go | 68 +- .../quic-go/internal/protocol/params.go | 11 +- .../internal/{handshake => qtls}/conn.go | 2 +- .../quic-go/quic-go/internal/qtls/qtls.go | 34 +- .../quic-go/internal/utils/byteorder.go | 21 - .../internal/utils/byteorder_big_endian.go | 103 - .../quic-go/quic-go/internal/utils/ip.go | 10 - .../quic-go/quic-go/internal/utils/minmax.go | 36 - .../quic-go/internal/utils/rtt_stats.go | 23 +- .../quic-go/internal/wire/ack_frame.go | 67 +- .../internal/wire/connection_close_frame.go | 37 +- .../quic-go/internal/wire/crypto_frame.go | 29 +- .../internal/wire/data_blocked_frame.go | 12 +- .../quic-go/internal/wire/datagram_frame.go | 25 +- .../quic-go/internal/wire/extended_header.go | 70 +- .../quic-go/internal/wire/frame_parser.go | 85 +- .../quic-go/quic-go/internal/wire/header.go | 168 +- .../quic-go/internal/wire/max_data_frame.go | 12 +- .../internal/wire/max_stream_data_frame.go | 23 +- .../internal/wire/max_streams_frame.go | 13 +- .../internal/wire/new_connection_id_frame.go | 49 +- .../quic-go/internal/wire/new_token_frame.go | 24 +- .../internal/wire/path_challenge_frame.go | 15 +- .../internal/wire/path_response_frame.go | 15 +- .../internal/wire/reset_stream_frame.go | 25 +- .../wire/retire_connection_id_frame.go | 12 +- .../quic-go/internal/wire/short_header.go | 17 +- .../internal/wire/stop_sending_frame.go | 19 +- .../wire/stream_data_blocked_frame.go | 20 +- .../quic-go/internal/wire/stream_frame.go | 50 +- .../internal/wire/streams_blocked_frame.go | 13 +- .../internal/wire/transport_parameters.go | 138 +- .../quic-go/logging/connection_tracer.go | 16 +- .../quic-go/quic-go/logging/interface.go | 20 +- .../quic-go/quic-go/logging/tracer.go | 4 +- vendor/github.com/quic-go/quic-go/mockgen.go | 11 +- .../quic-go/quic-go/mtu_discoverer.go | 170 +- vendor/github.com/quic-go/quic-go/oss-fuzz.sh | 6 +- .../quic-go/quic-go/packet_packer.go | 11 +- .../quic-go/quic-go/packet_unpacker.go | 23 +- .../quic-go/quic-go/quicvarint/varint.go | 43 +- .../quic-go/quic-go/receive_stream.go | 187 +- .../github.com/quic-go/quic-go/send_stream.go | 213 +- vendor/github.com/quic-go/quic-go/server.go | 42 +- vendor/github.com/quic-go/quic-go/stream.go | 48 +- .../github.com/quic-go/quic-go/streams_map.go | 40 +- .../quic-go/quic-go/streams_map_outgoing.go | 2 +- .../quic-go/quic-go/sys_conn_helper_darwin.go | 4 +- .../quic-go/sys_conn_helper_freebsd.go | 4 +- .../quic-go/quic-go/sys_conn_helper_linux.go | 50 +- .../quic-go/quic-go/sys_conn_oob.go | 8 +- .../github.com/quic-go/quic-go/transport.go | 12 + .../quic-go/quic-go/window_update_queue.go | 71 - .../github.com/ryanuber/go-glob/.travis.yml | 5 + vendor/github.com/ryanuber/go-glob/LICENSE | 21 + vendor/github.com/ryanuber/go-glob/README.md | 29 + vendor/github.com/ryanuber/go-glob/glob.go | 56 + vendor/github.com/spf13/cobra/.golangci.yml | 29 +- vendor/github.com/spf13/cobra/README.md | 8 +- vendor/github.com/spf13/cobra/active_help.go | 13 +- vendor/github.com/spf13/cobra/active_help.md | 157 - vendor/github.com/spf13/cobra/args.go | 4 +- .../spf13/cobra/bash_completions.go | 27 +- .../spf13/cobra/bash_completions.md | 93 - .../spf13/cobra/bash_completionsV2.go | 2 +- vendor/github.com/spf13/cobra/cobra.go | 15 +- vendor/github.com/spf13/cobra/command.go | 118 +- vendor/github.com/spf13/cobra/completions.go | 91 +- .../spf13/cobra/fish_completions.go | 2 +- .../spf13/cobra/fish_completions.md | 4 - vendor/github.com/spf13/cobra/flag_groups.go | 86 +- .../spf13/cobra/powershell_completions.go | 10 +- .../spf13/cobra/powershell_completions.md | 3 - .../spf13/cobra/projects_using_cobra.md | 64 - .../spf13/cobra/shell_completions.md | 576 - vendor/github.com/spf13/cobra/user_guide.md | 726 - .../github.com/spf13/cobra/zsh_completions.md | 48 - .../testify/assert/assertion_compare.go | 28 +- .../assert/assertion_compare_can_convert.go | 16 - .../assert/assertion_compare_legacy.go | 16 - .../testify/assert/assertion_format.go | 32 +- .../testify/assert/assertion_forward.go | 59 +- .../stretchr/testify/assert/assertions.go | 207 +- .../testify/assert/http_assertions.go | 27 +- .../stretchr/testify/require/require.go | 65 +- .../testify/require/require_forward.go | 59 +- .../tinylib/msgp/msgp/advise_other.go | 4 +- vendor/github.com/tinylib/msgp/msgp/defs.go | 4 + vendor/github.com/tinylib/msgp/msgp/errors.go | 9 + .../github.com/tinylib/msgp/msgp/extension.go | 257 +- vendor/github.com/tinylib/msgp/msgp/file.go | 4 +- .../github.com/tinylib/msgp/msgp/file_port.go | 4 +- .../github.com/tinylib/msgp/msgp/integers.go | 59 +- vendor/github.com/tinylib/msgp/msgp/json.go | 14 + .../tinylib/msgp/msgp/json_bytes.go | 52 +- vendor/github.com/tinylib/msgp/msgp/purego.go | 4 +- vendor/github.com/tinylib/msgp/msgp/read.go | 45 +- .../tinylib/msgp/msgp/read_bytes.go | 33 +- vendor/github.com/tinylib/msgp/msgp/unsafe.go | 4 +- .../tinylib/msgp/msgp/write_bytes.go | 22 +- .../github.com/vishvananda/netlink/.gitignore | 1 + .../vishvananda/netlink/.travis.yml | 19 - .../github.com/vishvananda/netlink/README.md | 2 +- vendor/github.com/vishvananda/netlink/addr.go | 1 + .../vishvananda/netlink/addr_linux.go | 98 +- .../vishvananda/netlink/bpf_linux.go | 24 + .../vishvananda/netlink/bridge_linux.go | 45 +- .../github.com/vishvananda/netlink/chain.go | 22 + .../vishvananda/netlink/chain_linux.go | 112 + .../github.com/vishvananda/netlink/class.go | 58 +- .../vishvananda/netlink/class_linux.go | 40 +- .../vishvananda/netlink/conntrack_linux.go | 612 +- .../netlink/conntrack_unspecified.go | 19 + .../vishvananda/netlink/devlink_linux.go | 897 +- .../github.com/vishvananda/netlink/filter.go | 184 +- .../vishvananda/netlink/filter_linux.go | 535 +- .../vishvananda/netlink/handle_linux.go | 45 +- .../vishvananda/netlink/handle_unspecified.go | 32 +- .../vishvananda/netlink/inet_diag.go | 40 + .../vishvananda/netlink/ipset_linux.go | 581 + vendor/github.com/vishvananda/netlink/link.go | 439 +- .../vishvananda/netlink/link_linux.go | 1087 +- .../github.com/vishvananda/netlink/neigh.go | 1 + .../vishvananda/netlink/neigh_linux.go | 85 +- .../netlink/netlink_unspecified.go | 54 +- .../vishvananda/netlink/netns_linux.go | 6 +- .../vishvananda/netlink/nl/addr_linux.go | 14 +- .../vishvananda/netlink/nl/conntrack_linux.go | 45 +- .../vishvananda/netlink/nl/devlink_linux.go | 118 +- .../vishvananda/netlink/nl/ip6tnl_linux.go | 21 + .../vishvananda/netlink/nl/ipset_linux.go | 227 + .../vishvananda/netlink/nl/link_linux.go | 216 +- .../vishvananda/netlink/nl/lwt_linux.go | 29 + .../vishvananda/netlink/nl/nl_linux.go | 346 +- .../netlink/nl/parse_attr_linux.go | 79 + .../vishvananda/netlink/nl/rdma_link_linux.go | 4 + .../vishvananda/netlink/nl/route_linux.go | 4 +- .../vishvananda/netlink/nl/seg6_linux.go | 4 +- .../vishvananda/netlink/nl/seg6local_linux.go | 4 + .../vishvananda/netlink/nl/syscall.go | 10 +- .../vishvananda/netlink/nl/tc_linux.go | 747 +- .../vishvananda/netlink/nl/vdpa_linux.go | 41 + .../vishvananda/netlink/nl/xfrm_linux.go | 10 +- .../netlink/nl/xfrm_state_linux.go | 29 +- .../vishvananda/netlink/proc_event_linux.go | 208 + .../vishvananda/netlink/protinfo.go | 24 +- .../vishvananda/netlink/protinfo_linux.go | 4 + .../github.com/vishvananda/netlink/qdisc.go | 92 +- .../vishvananda/netlink/qdisc_linux.go | 148 +- .../vishvananda/netlink/rdma_link_linux.go | 97 +- .../github.com/vishvananda/netlink/route.go | 94 +- .../vishvananda/netlink/route_linux.go | 946 +- .../vishvananda/netlink/route_unspecified.go | 10 + vendor/github.com/vishvananda/netlink/rule.go | 50 +- .../vishvananda/netlink/rule_linux.go | 159 +- .../vishvananda/netlink/rule_nonlinux.go | 8 + .../github.com/vishvananda/netlink/socket.go | 77 + .../vishvananda/netlink/socket_linux.go | 484 +- .../vishvananda/netlink/socket_xdp_linux.go | 195 + vendor/github.com/vishvananda/netlink/tcp.go | 92 + .../vishvananda/netlink/tcp_linux.go | 368 + .../vishvananda/netlink/unix_diag.go | 27 + .../vishvananda/netlink/vdpa_linux.go | 463 + .../github.com/vishvananda/netlink/virtio.go | 132 + .../vishvananda/netlink/xdp_diag.go | 34 + .../vishvananda/netlink/xdp_linux.go | 46 + .../netlink/{xfrm.go => xfrm_linux.go} | 2 +- .../vishvananda/netlink/xfrm_policy.go | 96 - .../vishvananda/netlink/xfrm_policy_linux.go | 113 +- .../vishvananda/netlink/xfrm_state.go | 131 - .../vishvananda/netlink/xfrm_state_linux.go | 236 +- .../vishvananda/netlink/xfrm_unspecified.go | 7 + .../go.etcd.io/etcd/api/v3/version/version.go | 2 +- .../etcd/client/pkg/v3/logutil/zap.go | 2 +- .../etcd/client/pkg/v3/types/urls.go | 21 +- vendor/go.etcd.io/etcd/client/v3/README.md | 7 - vendor/go.etcd.io/etcd/client/v3/auth.go | 36 +- vendor/go.etcd.io/etcd/client/v3/client.go | 27 +- vendor/go.etcd.io/etcd/client/v3/cluster.go | 10 +- vendor/go.etcd.io/etcd/client/v3/config.go | 9 + vendor/go.etcd.io/etcd/client/v3/kv.go | 10 +- vendor/go.etcd.io/etcd/client/v3/lease.go | 20 +- .../go.etcd.io/etcd/client/v3/maintenance.go | 26 +- .../etcd/client/v3/retry_interceptor.go | 20 +- vendor/go.etcd.io/etcd/client/v3/txn.go | 2 +- vendor/go.etcd.io/etcd/client/v3/watch.go | 6 +- vendor/go.uber.org/automaxprocs/LICENSE | 19 + .../automaxprocs/internal/cgroups/cgroup.go | 79 + .../automaxprocs/internal/cgroups/cgroups.go | 118 + .../automaxprocs/internal/cgroups/cgroups2.go | 176 + .../internal/cgroups/doc.go} | 11 +- .../automaxprocs/internal/cgroups/errors.go | 52 + .../internal/cgroups/mountpoint.go | 171 + .../automaxprocs/internal/cgroups/subsys.go | 103 + .../internal/runtime/cpu_quota_linux.go | 75 + .../internal/runtime/cpu_quota_unsupported.go | 31 + .../automaxprocs/internal/runtime/runtime.go | 40 + .../automaxprocs/maxprocs/maxprocs.go | 139 + .../maxprocs/version.go} | 10 +- vendor/go.uber.org/zap/.golangci.yml | 77 + vendor/go.uber.org/zap/.readme.tmpl | 12 +- vendor/go.uber.org/zap/CHANGELOG.md | 351 +- vendor/go.uber.org/zap/CONTRIBUTING.md | 21 +- vendor/go.uber.org/zap/Makefile | 87 +- vendor/go.uber.org/zap/README.md | 47 +- vendor/go.uber.org/zap/array.go | 127 + vendor/go.uber.org/zap/buffer/buffer.go | 5 + vendor/go.uber.org/zap/buffer/pool.go | 20 +- vendor/go.uber.org/zap/config.go | 88 +- vendor/go.uber.org/zap/doc.go | 60 +- vendor/go.uber.org/zap/encoder.go | 2 +- vendor/go.uber.org/zap/error.go | 14 +- vendor/go.uber.org/zap/field.go | 194 +- vendor/go.uber.org/zap/global.go | 1 + vendor/go.uber.org/zap/http_handler.go | 44 +- vendor/go.uber.org/zap/internal/exit/exit.go | 22 +- .../go.uber.org/zap/internal/level_enabler.go | 37 + vendor/go.uber.org/zap/internal/pool/pool.go | 58 + .../zap/internal/stacktrace/stack.go | 181 + vendor/go.uber.org/zap/level.go | 29 +- vendor/go.uber.org/zap/logger.go | 164 +- vendor/go.uber.org/zap/options.go | 21 +- vendor/go.uber.org/zap/sink.go | 101 +- vendor/go.uber.org/zap/stacktrace.go | 85 - vendor/go.uber.org/zap/sugar.go | 200 +- vendor/go.uber.org/zap/writer.go | 23 +- .../zap/zapcore/buffered_write_syncer.go | 31 + vendor/go.uber.org/zap/zapcore/clock.go | 4 +- .../zap/zapcore/console_encoder.go | 20 +- vendor/go.uber.org/zap/zapcore/core.go | 15 +- vendor/go.uber.org/zap/zapcore/encoder.go | 30 +- vendor/go.uber.org/zap/zapcore/entry.go | 94 +- vendor/go.uber.org/zap/zapcore/error.go | 28 +- vendor/go.uber.org/zap/zapcore/hook.go | 9 + .../go.uber.org/zap/zapcore/increase_level.go | 9 + .../go.uber.org/zap/zapcore/json_encoder.go | 263 +- vendor/go.uber.org/zap/zapcore/lazy_with.go | 54 + vendor/go.uber.org/zap/zapcore/level.go | 54 + .../zap/zapcore/reflected_encoder.go | 41 + vendor/go.uber.org/zap/zapcore/sampler.go | 47 +- vendor/go.uber.org/zap/zapcore/tee.go | 17 +- vendor/go.uber.org/zap/zapgrpc/zapgrpc.go | 18 +- vendor/golang.org/x/crypto/LICENSE | 4 +- .../x/crypto/chacha20/chacha_noasm.go | 2 +- .../{chacha_ppc64le.go => chacha_ppc64x.go} | 2 +- .../{chacha_ppc64le.s => chacha_ppc64x.s} | 114 +- .../chacha20poly1305/chacha20poly1305.go | 2 +- .../chacha20poly1305/chacha20poly1305_amd64.s | 11503 ++++++++-- vendor/golang.org/x/crypto/hkdf/hkdf.go | 2 +- .../x/crypto/internal/poly1305/mac_noasm.go | 2 +- .../x/crypto/internal/poly1305/sum_amd64.s | 133 +- .../{sum_ppc64le.go => sum_ppc64x.go} | 2 +- .../poly1305/{sum_ppc64le.s => sum_ppc64x.s} | 30 +- vendor/golang.org/x/mod/modfile/read.go | 2 +- vendor/golang.org/x/mod/modfile/rule.go | 113 +- vendor/golang.org/x/mod/modfile/work.go | 52 +- vendor/golang.org/x/mod/module/module.go | 2 + vendor/golang.org/x/net/LICENSE | 4 +- vendor/golang.org/x/net/html/doc.go | 9 +- vendor/golang.org/x/net/html/iter.go | 56 + vendor/golang.org/x/net/html/node.go | 4 + .../golang.org/x/net/http/httpguts/httplex.go | 13 +- .../x/net/http2/client_conn_pool.go | 8 +- vendor/golang.org/x/net/http2/config.go | 122 + vendor/golang.org/x/net/http2/config_go124.go | 61 + .../x/net/http2/config_pre_go124.go | 16 + vendor/golang.org/x/net/http2/frame.go | 13 +- vendor/golang.org/x/net/http2/http2.go | 72 +- vendor/golang.org/x/net/http2/server.go | 294 +- vendor/golang.org/x/net/http2/testsync.go | 331 - vendor/golang.org/x/net/http2/timer.go | 20 + vendor/golang.org/x/net/http2/transport.go | 706 +- vendor/golang.org/x/net/http2/unencrypted.go | 32 + vendor/golang.org/x/net/http2/write.go | 10 + .../x/net/http2/writesched_priority.go | 4 +- .../net/internal/socket/zsys_openbsd_ppc64.go | 28 +- .../internal/socket/zsys_openbsd_riscv64.go | 28 +- vendor/golang.org/x/oauth2/LICENSE | 4 +- vendor/golang.org/x/oauth2/README.md | 15 +- .../x/oauth2/internal/client_appengine.go | 13 - .../golang.org/x/oauth2/internal/transport.go | 5 - vendor/golang.org/x/oauth2/oauth2.go | 2 +- vendor/golang.org/x/oauth2/token.go | 7 + vendor/golang.org/x/sync/LICENSE | 27 + vendor/golang.org/x/sync/PATENTS | 22 + vendor/golang.org/x/sync/errgroup/errgroup.go | 135 + vendor/golang.org/x/sync/errgroup/go120.go | 13 + .../golang.org/x/sync/errgroup/pre_go120.go | 14 + vendor/golang.org/x/sys/LICENSE | 4 +- .../golang.org/x/sys/cpu/asm_darwin_x86_gc.s | 17 + vendor/golang.org/x/sys/cpu/cpu.go | 22 + vendor/golang.org/x/sys/cpu/cpu_arm64.go | 22 + vendor/golang.org/x/sys/cpu/cpu_arm64.s | 8 + vendor/golang.org/x/sys/cpu/cpu_darwin_x86.go | 61 + vendor/golang.org/x/sys/cpu/cpu_gc_arm64.go | 1 + vendor/golang.org/x/sys/cpu/cpu_gc_x86.go | 4 +- .../x/sys/cpu/{cpu_x86.s => cpu_gc_x86.s} | 2 +- vendor/golang.org/x/sys/cpu/cpu_gccgo_x86.go | 6 - .../golang.org/x/sys/cpu/cpu_linux_arm64.go | 9 + .../golang.org/x/sys/cpu/cpu_linux_noinit.go | 2 +- .../golang.org/x/sys/cpu/cpu_linux_riscv64.go | 137 + vendor/golang.org/x/sys/cpu/cpu_other_x86.go | 11 + vendor/golang.org/x/sys/cpu/cpu_riscv64.go | 11 +- vendor/golang.org/x/sys/cpu/cpu_x86.go | 6 +- .../x/sys/cpu/syscall_darwin_x86_gc.go | 98 + vendor/golang.org/x/sys/unix/README.md | 2 +- vendor/golang.org/x/sys/unix/asm_zos_s390x.s | 665 +- vendor/golang.org/x/sys/unix/bpxsvc_zos.go | 657 + vendor/golang.org/x/sys/unix/bpxsvc_zos.s | 192 + vendor/golang.org/x/sys/unix/epoll_zos.go | 220 - vendor/golang.org/x/sys/unix/fstatfs_zos.go | 163 - vendor/golang.org/x/sys/unix/ioctl_linux.go | 96 + vendor/golang.org/x/sys/unix/mkerrors.sh | 20 +- vendor/golang.org/x/sys/unix/mremap.go | 5 + vendor/golang.org/x/sys/unix/pagesize_unix.go | 2 +- .../x/sys/unix/readdirent_getdirentries.go | 2 +- vendor/golang.org/x/sys/unix/sockcmsg_zos.go | 58 + .../golang.org/x/sys/unix/symaddr_zos_s390x.s | 75 + vendor/golang.org/x/sys/unix/syscall_aix.go | 2 +- .../golang.org/x/sys/unix/syscall_darwin.go | 61 + vendor/golang.org/x/sys/unix/syscall_hurd.go | 1 + vendor/golang.org/x/sys/unix/syscall_linux.go | 65 +- .../x/sys/unix/syscall_linux_arm64.go | 2 + .../x/sys/unix/syscall_linux_loong64.go | 2 + .../x/sys/unix/syscall_linux_riscv64.go | 2 + .../golang.org/x/sys/unix/syscall_openbsd.go | 1 + vendor/golang.org/x/sys/unix/syscall_unix.go | 9 + .../x/sys/unix/syscall_zos_s390x.go | 1595 +- vendor/golang.org/x/sys/unix/sysvshm_unix.go | 2 +- .../x/sys/unix/sysvshm_unix_other.go | 2 +- .../golang.org/x/sys/unix/vgetrandom_linux.go | 13 + .../x/sys/unix/vgetrandom_unsupported.go | 11 + .../x/sys/unix/zerrors_darwin_amd64.go | 12 + .../x/sys/unix/zerrors_darwin_arm64.go | 12 + vendor/golang.org/x/sys/unix/zerrors_linux.go | 100 +- .../x/sys/unix/zerrors_linux_386.go | 22 + .../x/sys/unix/zerrors_linux_amd64.go | 22 + .../x/sys/unix/zerrors_linux_arm.go | 21 + .../x/sys/unix/zerrors_linux_arm64.go | 22 + .../x/sys/unix/zerrors_linux_loong64.go | 21 + .../x/sys/unix/zerrors_linux_mips.go | 21 + .../x/sys/unix/zerrors_linux_mips64.go | 21 + .../x/sys/unix/zerrors_linux_mips64le.go | 21 + .../x/sys/unix/zerrors_linux_mipsle.go | 21 + .../x/sys/unix/zerrors_linux_ppc.go | 21 + .../x/sys/unix/zerrors_linux_ppc64.go | 21 + .../x/sys/unix/zerrors_linux_ppc64le.go | 21 + .../x/sys/unix/zerrors_linux_riscv64.go | 21 + .../x/sys/unix/zerrors_linux_s390x.go | 21 + .../x/sys/unix/zerrors_linux_sparc64.go | 21 + .../x/sys/unix/zerrors_zos_s390x.go | 235 +- .../x/sys/unix/zsymaddr_zos_s390x.s | 364 + .../x/sys/unix/zsyscall_darwin_amd64.go | 101 + .../x/sys/unix/zsyscall_darwin_amd64.s | 25 + .../x/sys/unix/zsyscall_darwin_arm64.go | 101 + .../x/sys/unix/zsyscall_darwin_arm64.s | 25 + .../golang.org/x/sys/unix/zsyscall_linux.go | 43 +- .../x/sys/unix/zsyscall_openbsd_386.go | 24 + .../x/sys/unix/zsyscall_openbsd_386.s | 5 + .../x/sys/unix/zsyscall_openbsd_amd64.go | 24 + .../x/sys/unix/zsyscall_openbsd_amd64.s | 5 + .../x/sys/unix/zsyscall_openbsd_arm.go | 24 + .../x/sys/unix/zsyscall_openbsd_arm.s | 5 + .../x/sys/unix/zsyscall_openbsd_arm64.go | 24 + .../x/sys/unix/zsyscall_openbsd_arm64.s | 5 + .../x/sys/unix/zsyscall_openbsd_mips64.go | 24 + .../x/sys/unix/zsyscall_openbsd_mips64.s | 5 + .../x/sys/unix/zsyscall_openbsd_ppc64.go | 24 + .../x/sys/unix/zsyscall_openbsd_ppc64.s | 6 + .../x/sys/unix/zsyscall_openbsd_riscv64.go | 24 + .../x/sys/unix/zsyscall_openbsd_riscv64.s | 5 + .../x/sys/unix/zsyscall_zos_s390x.go | 3113 ++- .../x/sys/unix/zsysnum_linux_386.go | 6 + .../x/sys/unix/zsysnum_linux_amd64.go | 7 + .../x/sys/unix/zsysnum_linux_arm.go | 6 + .../x/sys/unix/zsysnum_linux_arm64.go | 8 +- .../x/sys/unix/zsysnum_linux_loong64.go | 8 + .../x/sys/unix/zsysnum_linux_mips.go | 6 + .../x/sys/unix/zsysnum_linux_mips64.go | 6 + .../x/sys/unix/zsysnum_linux_mips64le.go | 6 + .../x/sys/unix/zsysnum_linux_mipsle.go | 6 + .../x/sys/unix/zsysnum_linux_ppc.go | 6 + .../x/sys/unix/zsysnum_linux_ppc64.go | 6 + .../x/sys/unix/zsysnum_linux_ppc64le.go | 6 + .../x/sys/unix/zsysnum_linux_riscv64.go | 8 +- .../x/sys/unix/zsysnum_linux_s390x.go | 6 + .../x/sys/unix/zsysnum_linux_sparc64.go | 6 + .../x/sys/unix/zsysnum_zos_s390x.go | 5507 ++--- .../x/sys/unix/ztypes_darwin_amd64.go | 13 + .../x/sys/unix/ztypes_darwin_arm64.go | 13 + .../x/sys/unix/ztypes_freebsd_386.go | 1 + .../x/sys/unix/ztypes_freebsd_amd64.go | 1 + .../x/sys/unix/ztypes_freebsd_arm.go | 1 + .../x/sys/unix/ztypes_freebsd_arm64.go | 1 + .../x/sys/unix/ztypes_freebsd_riscv64.go | 1 + vendor/golang.org/x/sys/unix/ztypes_linux.go | 269 +- .../golang.org/x/sys/unix/ztypes_linux_386.go | 8 - .../x/sys/unix/ztypes_linux_amd64.go | 9 - .../golang.org/x/sys/unix/ztypes_linux_arm.go | 9 - .../x/sys/unix/ztypes_linux_arm64.go | 9 - .../x/sys/unix/ztypes_linux_loong64.go | 9 - .../x/sys/unix/ztypes_linux_mips.go | 9 - .../x/sys/unix/ztypes_linux_mips64.go | 9 - .../x/sys/unix/ztypes_linux_mips64le.go | 9 - .../x/sys/unix/ztypes_linux_mipsle.go | 9 - .../golang.org/x/sys/unix/ztypes_linux_ppc.go | 9 - .../x/sys/unix/ztypes_linux_ppc64.go | 9 - .../x/sys/unix/ztypes_linux_ppc64le.go | 9 - .../x/sys/unix/ztypes_linux_riscv64.go | 42 +- .../x/sys/unix/ztypes_linux_s390x.go | 9 - .../x/sys/unix/ztypes_linux_sparc64.go | 9 - .../golang.org/x/sys/unix/ztypes_zos_s390x.go | 152 +- vendor/golang.org/x/sys/windows/aliases.go | 2 +- .../golang.org/x/sys/windows/dll_windows.go | 2 +- vendor/golang.org/x/sys/windows/empty.s | 8 - .../x/sys/windows/security_windows.go | 25 +- .../x/sys/windows/syscall_windows.go | 50 +- .../golang.org/x/sys/windows/types_windows.go | 198 +- .../x/sys/windows/zsyscall_windows.go | 142 + vendor/golang.org/x/term/LICENSE | 4 +- vendor/golang.org/x/term/README.md | 11 +- vendor/golang.org/x/term/term_windows.go | 1 + vendor/golang.org/x/text/LICENSE | 4 +- vendor/golang.org/x/time/LICENSE | 4 +- vendor/golang.org/x/time/rate/rate.go | 17 +- vendor/golang.org/x/tools/cover/profile.go | 266 + .../x/tools/go/gcexportdata/gcexportdata.go | 2 +- .../tools/go/internal/packagesdriver/sizes.go | 1 + vendor/golang.org/x/tools/go/packages/doc.go | 48 +- .../x/tools/go/packages/external.go | 99 +- .../golang.org/x/tools/go/packages/golist.go | 117 +- .../x/tools/go/packages/packages.go | 297 +- .../x/tools/go/types/objectpath/objectpath.go | 23 +- .../x/tools/internal/aliases/aliases.go | 32 + .../x/tools/internal/aliases/aliases_go121.go | 31 + .../x/tools/internal/aliases/aliases_go122.go | 63 + .../x/tools/internal/event/tag/tag.go | 59 - .../x/tools/internal/gcimporter/gcimporter.go | 7 - .../x/tools/internal/gcimporter/iexport.go | 35 +- .../x/tools/internal/gcimporter/iimport.go | 80 +- .../internal/gcimporter/support_go117.go | 16 - .../internal/gcimporter/support_go118.go | 3 - .../x/tools/internal/gcimporter/unified_no.go | 4 +- .../tools/internal/gcimporter/unified_yes.go | 4 +- .../x/tools/internal/gcimporter/ureader_no.go | 19 - .../tools/internal/gcimporter/ureader_yes.go | 10 +- .../x/tools/internal/gocommand/invoke.go | 109 +- .../x/tools/internal/gocommand/vendor.go | 54 + .../x/tools/internal/gopathwalk/walk.go | 308 +- .../x/tools/internal/imports/fix.go | 287 +- .../x/tools/internal/imports/imports.go | 6 +- .../x/tools/internal/imports/mod.go | 348 +- .../x/tools/internal/imports/mod_cache.go | 119 +- .../x/tools/internal/imports/sortimports.go | 2 +- .../x/tools/internal/imports/zstdlib.go | 11345 ---------- .../x/tools/internal/pkgbits/decoder.go | 4 + .../x/tools/internal/stdlib/manifest.go | 17320 ++++++++++++++++ .../x/tools/internal/stdlib/stdlib.go | 97 + .../internal/tokeninternal/tokeninternal.go | 28 +- .../x/tools/internal/typeparams/common.go | 204 - .../x/tools/internal/typeparams/coretype.go | 122 - .../x/tools/internal/typeparams/normalize.go | 218 - .../x/tools/internal/typeparams/termlist.go | 163 - .../x/tools/internal/typeparams/typeterm.go | 169 - .../tools/internal/typesinternal/errorcode.go | 6 +- .../x/tools/internal/typesinternal/recv.go | 43 + .../x/tools/internal/typesinternal/toonew.go | 89 + .../x/tools/internal/typesinternal/types.go | 2 - .../tools/internal/typesinternal/types_118.go | 19 - .../x/tools/internal/versions/features.go | 43 + .../x/tools/internal/versions/toolchain.go | 14 + .../internal/versions/toolchain_go119.go | 14 + .../internal/versions/toolchain_go120.go | 14 + .../internal/versions/toolchain_go121.go | 14 + .../x/tools/internal/versions/types_go121.go | 18 +- .../x/tools/internal/versions/types_go122.go | 25 +- .../x/tools/internal/versions/versions.go | 5 + .../appengine/internal/api.go | 653 - .../appengine/internal/api_classic.go | 170 - .../appengine/internal/api_common.go | 141 - .../appengine/internal/app_id.go | 28 - .../appengine/internal/base/api_base.pb.go | 308 - .../appengine/internal/base/api_base.proto | 33 - .../internal/datastore/datastore_v3.pb.go | 4367 ---- .../internal/datastore/datastore_v3.proto | 551 - .../appengine/internal/identity.go | 54 - .../appengine/internal/identity_classic.go | 62 - .../appengine/internal/identity_flex.go | 12 - .../appengine/internal/identity_vm.go | 134 - .../appengine/internal/internal.go | 110 - .../appengine/internal/log/log_service.pb.go | 1313 -- .../appengine/internal/log/log_service.proto | 150 - .../appengine/internal/main.go | 17 - .../appengine/internal/main_common.go | 7 - .../appengine/internal/main_vm.go | 70 - .../appengine/internal/metadata.go | 60 - .../appengine/internal/net.go | 56 - .../appengine/internal/regen.sh | 40 - .../internal/remote_api/remote_api.pb.go | 361 - .../internal/remote_api/remote_api.proto | 44 - .../appengine/internal/transaction.go | 115 - .../internal/urlfetch/urlfetch_service.pb.go | 527 - .../internal/urlfetch/urlfetch_service.proto | 64 - .../appengine/urlfetch/urlfetch.go | 209 - .../api/annotations/annotations.pb.go | 4 +- .../googleapis/api/annotations/client.pb.go | 456 +- .../api/annotations/field_behavior.pb.go | 2 +- .../api/annotations/field_info.pb.go | 161 +- .../googleapis/api/annotations/http.pb.go | 52 +- .../googleapis/api/annotations/resource.pb.go | 13 +- .../googleapis/api/annotations/routing.pb.go | 4 +- .../googleapis/api/launch_stage.pb.go | 4 +- .../googleapis/rpc/status/status.pb.go | 4 +- vendor/google.golang.org/grpc/CONTRIBUTING.md | 18 +- vendor/google.golang.org/grpc/MAINTAINERS.md | 34 +- vendor/google.golang.org/grpc/Makefile | 7 +- vendor/google.golang.org/grpc/README.md | 2 +- vendor/google.golang.org/grpc/SECURITY.md | 2 +- .../google.golang.org/grpc/backoff/backoff.go | 2 +- .../grpc/balancer/balancer.go | 36 +- .../grpc/balancer/base/balancer.go | 6 +- .../balancer/pickfirst/internal/internal.go | 24 + .../{ => balancer/pickfirst}/pickfirst.go | 80 +- .../pickfirst/pickfirstleaf/pickfirstleaf.go | 625 + .../grpc/balancer/roundrobin/roundrobin.go | 4 +- .../grpc/balancer_wrapper.go | 82 +- .../grpc_binarylog_v1/binarylog.pb.go | 24 +- vendor/google.golang.org/grpc/clientconn.go | 222 +- vendor/google.golang.org/grpc/codec.go | 69 +- vendor/google.golang.org/grpc/codegen.sh | 17 - vendor/google.golang.org/grpc/codes/codes.go | 2 +- .../grpc/credentials/credentials.go | 6 +- .../grpc/credentials/insecure/insecure.go | 2 +- .../google.golang.org/grpc/credentials/tls.go | 63 +- vendor/google.golang.org/grpc/dialoptions.go | 107 +- vendor/google.golang.org/grpc/doc.go | 2 +- .../grpc/encoding/encoding.go | 5 +- .../grpc/encoding/encoding_v2.go | 81 + .../grpc/encoding/proto/proto.go | 44 +- .../grpc/experimental/stats/metricregistry.go | 269 + .../grpc/experimental/stats/metrics.go | 114 + .../grpc/grpclog/component.go | 10 +- .../google.golang.org/grpc/grpclog/grpclog.go | 104 +- .../grpc/grpclog/internal/grpclog.go | 26 + .../grpc/grpclog/internal/logger.go | 87 + .../internal/loggerv2.go} | 178 +- .../google.golang.org/grpc/grpclog/logger.go | 59 +- .../grpc/grpclog/loggerv2.go | 181 +- .../grpc/internal/backoff/backoff.go | 4 +- .../balancer/gracefulswitch/config.go | 3 +- .../balancer/gracefulswitch/gracefulswitch.go | 1 - .../grpc/internal/binarylog/method_logger.go | 8 +- .../grpc/internal/channelz/channel.go | 15 + .../grpc/internal/channelz/channelmap.go | 9 +- .../grpc/internal/channelz/funcs.go | 2 +- .../grpc/internal/channelz/server.go | 2 + .../grpc/internal/channelz/socket.go | 7 + .../grpc/internal/channelz/subchannel.go | 2 + .../internal/channelz/syscall_nonlinux.go | 4 +- .../grpc/internal/channelz/trace.go | 19 +- .../grpc/internal/envconfig/envconfig.go | 18 +- .../grpc/internal/experimental.go | 8 +- .../{prefixLogger.go => prefix_logger.go} | 40 +- .../grpc/internal/grpcrand/grpcrand.go | 100 - .../grpc/internal/grpcrand/grpcrand_go1.21.go | 73 - .../internal/grpcsync/callback_serializer.go | 24 +- .../grpc/internal/grpcsync/pubsub.go | 4 +- .../grpc/internal/grpcutil/compressor.go | 5 - .../grpc/internal/grpcutil/method.go | 2 +- .../grpc/internal/idle/idle.go | 4 +- .../grpc/internal/internal.go | 61 +- .../internal/resolver/dns/dns_resolver.go | 42 +- .../resolver/dns/internal/internal.go | 19 +- .../resolver/passthrough/passthrough.go | 2 +- .../grpc/internal/stats/labels.go | 42 + .../internal/stats/metrics_recorder_list.go | 105 + .../grpc/internal/status/status.go | 39 +- .../grpc/internal/syscall/syscall_nonlinux.go | 6 +- .../grpc/internal/tcp_keepalive_unix.go | 2 +- .../grpc/internal/tcp_keepalive_windows.go | 2 +- .../grpc/internal/transport/controlbuf.go | 287 +- .../grpc/internal/transport/handler_server.go | 47 +- .../grpc/internal/transport/http2_client.go | 193 +- .../grpc/internal/transport/http2_server.go | 63 +- .../grpc/internal/transport/http_util.go | 24 +- .../grpc/internal/transport/proxy.go | 10 +- .../grpc/internal/transport/transport.go | 251 +- .../grpc/keepalive/keepalive.go | 20 +- .../google.golang.org/grpc/mem/buffer_pool.go | 194 + .../grpc/mem/buffer_slice.go | 226 + vendor/google.golang.org/grpc/mem/buffers.go | 268 + .../grpc/metadata/metadata.go | 7 +- vendor/google.golang.org/grpc/peer/peer.go | 30 + .../google.golang.org/grpc/picker_wrapper.go | 84 +- vendor/google.golang.org/grpc/preloader.go | 28 +- vendor/google.golang.org/grpc/regenerate.sh | 123 - .../grpc/resolver/dns/dns_resolver.go | 12 +- .../grpc/resolver/manual/manual.go | 4 +- .../grpc/resolver_wrapper.go | 11 +- vendor/google.golang.org/grpc/rpc_util.go | 333 +- vendor/google.golang.org/grpc/server.go | 115 +- .../google.golang.org/grpc/service_config.go | 32 +- .../grpc/shared_buffer_pool.go | 154 - vendor/google.golang.org/grpc/stats/stats.go | 12 +- vendor/google.golang.org/grpc/stream.go | 218 +- .../grpc/stream_interfaces.go | 238 + vendor/google.golang.org/grpc/version.go | 2 +- vendor/google.golang.org/grpc/vet.sh | 195 - .../protobuf/encoding/protojson/decode.go | 6 +- .../protobuf/encoding/protojson/encode.go | 24 +- .../encoding/protojson/well_known_types.go | 6 +- .../protobuf/encoding/prototext/decode.go | 4 +- .../protobuf/encoding/prototext/encode.go | 20 +- .../protobuf/internal/descfmt/stringer.go | 1 + .../protobuf/internal/descopts/options.go | 20 +- .../editiondefaults/editions_defaults.binpb | Bin 63 -> 99 bytes .../internal/editionssupport/editions.go | 18 + .../protobuf/internal/encoding/json/decode.go | 2 +- .../protobuf/internal/encoding/tag/tag.go | 4 +- .../protobuf/internal/encoding/text/decode.go | 2 +- .../protobuf/internal/errors/errors.go | 21 +- .../protobuf/internal/filedesc/desc.go | 107 +- .../protobuf/internal/filedesc/desc_init.go | 45 +- .../protobuf/internal/filedesc/desc_lazy.go | 51 +- .../internal/filedesc/desc_list_gen.go | 11 + .../protobuf/internal/filedesc/editions.go | 28 +- .../protobuf/internal/filedesc/placeholder.go | 1 + .../protobuf/internal/filetype/build.go | 4 +- .../protobuf/internal/genid/descriptor_gen.go | 49 +- .../protobuf/internal/genid/doc.go | 2 +- .../internal/genid/go_features_gen.go | 34 +- .../protobuf/internal/genid/map_entry.go | 2 +- .../protobuf/internal/genid/wrappers.go | 2 +- .../protobuf/internal/impl/api_export.go | 6 +- .../protobuf/internal/impl/checkinit.go | 2 +- .../protobuf/internal/impl/codec_extension.go | 33 +- .../protobuf/internal/impl/codec_field.go | 67 +- .../protobuf/internal/impl/codec_map.go | 15 +- .../protobuf/internal/impl/codec_message.go | 3 + .../internal/impl/codec_messageset.go | 22 + .../protobuf/internal/impl/codec_reflect.go | 210 - .../protobuf/internal/impl/codec_unsafe.go | 3 - .../protobuf/internal/impl/convert.go | 4 +- .../protobuf/internal/impl/convert_list.go | 2 +- .../protobuf/internal/impl/convert_map.go | 2 +- .../protobuf/internal/impl/encode.go | 50 +- .../protobuf/internal/impl/equal.go | 224 + .../protobuf/internal/impl/extension.go | 8 +- .../protobuf/internal/impl/legacy_enum.go | 3 +- .../internal/impl/legacy_extension.go | 3 +- .../protobuf/internal/impl/legacy_file.go | 4 +- .../protobuf/internal/impl/legacy_message.go | 14 +- .../protobuf/internal/impl/message.go | 12 +- .../protobuf/internal/impl/message_reflect.go | 45 +- .../internal/impl/message_reflect_gen.go | 146 +- .../protobuf/internal/impl/pointer_reflect.go | 215 - .../protobuf/internal/impl/pointer_unsafe.go | 7 +- .../protobuf/internal/order/range.go | 4 +- .../protobuf/internal/strs/strings_pure.go | 28 - .../internal/strs/strings_unsafe_go120.go | 3 +- .../internal/strs/strings_unsafe_go121.go | 3 +- .../protobuf/internal/version/version.go | 4 +- .../protobuf/proto/decode.go | 2 + .../protobuf/proto/encode.go | 44 +- .../google.golang.org/protobuf/proto/equal.go | 9 + .../protobuf/proto/extension.go | 88 +- .../protobuf/proto/messageset.go | 7 +- .../google.golang.org/protobuf/proto/size.go | 2 + .../protobuf/reflect/protodesc/desc.go | 23 +- .../protobuf/reflect/protodesc/desc_init.go | 53 +- .../reflect/protodesc/desc_resolve.go | 5 + .../reflect/protodesc/desc_validate.go | 73 +- .../protobuf/reflect/protodesc/editions.go | 18 +- .../protobuf/reflect/protodesc/proto.go | 22 + .../protobuf/reflect/protoreflect/methods.go | 10 + .../protobuf/reflect/protoreflect/proto.go | 2 +- .../reflect/protoreflect/source_gen.go | 21 + .../protobuf/reflect/protoreflect/type.go | 12 +- .../reflect/protoreflect/value_pure.go | 60 - .../reflect/protoreflect/value_union.go | 14 +- .../protoreflect/value_unsafe_go120.go | 9 +- .../protoreflect/value_unsafe_go121.go | 11 +- .../reflect/protoregistry/registry.go | 14 +- .../protobuf/runtime/protoiface/methods.go | 18 + .../types/descriptorpb/descriptor.pb.go | 1781 +- .../types/gofeaturespb/go_features.pb.go | 249 +- .../types/gofeaturespb/go_features.proto | 28 - .../protobuf/types/known/anypb/any.pb.go | 26 +- .../types/known/durationpb/duration.pb.go | 26 +- .../types/known/timestamppb/timestamp.pb.go | 26 +- .../dd-trace-go.v1/appsec/events/block.go | 32 + .../DataDog/dd-trace-go.v1/ddtrace/ext/db.go | 6 + .../dd-trace-go.v1/ddtrace/ext/log_key.go | 13 + .../ddtrace/tracer/civisibility_payload.go | 141 + .../ddtrace/tracer/civisibility_transport.go | 203 + .../ddtrace/tracer/civisibility_tslv.go | 445 + .../ddtrace/tracer/civisibility_tslv_msgp.go | 924 + .../ddtrace/tracer/civisibility_writer.go | 120 + .../dd-trace-go.v1/ddtrace/tracer/context.go | 5 +- .../ddtrace/tracer/dynamic_config.go | 9 +- .../dd-trace-go.v1/ddtrace/tracer/log.go | 23 +- .../ddtrace/tracer/meta_struct.go | 88 + .../dd-trace-go.v1/ddtrace/tracer/option.go | 192 +- .../ddtrace/tracer/otel_dd_mappings.go | 202 + .../dd-trace-go.v1/ddtrace/tracer/rand.go | 47 +- .../ddtrace/tracer/remote_config.go | 165 +- .../ddtrace/tracer/rules_sampler.go | 277 +- .../dd-trace-go.v1/ddtrace/tracer/span.go | 96 +- .../ddtrace/tracer/span_msgp.go | 27 +- .../ddtrace/tracer/spancontext.go | 70 +- .../ddtrace/tracer/sqlcomment.go | 10 +- .../dd-trace-go.v1/ddtrace/tracer/stats.go | 23 +- .../ddtrace/tracer/stats_payload.go | 1 + .../ddtrace/tracer/stats_payload_msgp.go | 80 +- .../ddtrace/tracer/telemetry.go | 16 +- .../dd-trace-go.v1/ddtrace/tracer/textmap.go | 211 +- .../dd-trace-go.v1/ddtrace/tracer/tracer.go | 89 +- .../ddtrace/tracer/transport.go | 61 +- .../dd-trace-go.v1/ddtrace/tracer/util.go | 53 + .../dd-trace-go.v1/ddtrace/tracer/writer.go | 16 + .../DataDog/dd-trace-go.v1/internal/agent.go | 73 +- .../dd-trace-go.v1/internal/appsec/README.md | 147 + .../dd-trace-go.v1/internal/appsec/appsec.go | 48 +- .../internal/appsec/config/config.go | 86 +- .../internal/appsec/config/rules_manager.go | 68 +- .../internal/appsec/dyngo/operation.go | 51 +- .../appsec/emitter/graphqlsec/README.md | 25 + .../appsec/emitter/graphqlsec/execution.go | 66 + .../appsec/emitter/graphqlsec/request.go | 69 + .../appsec/emitter/graphqlsec/resolve.go | 63 + .../internal/appsec/emitter/grpcsec/grpc.go | 116 + .../internal/appsec/emitter/httpsec/config.go | 24 + .../internal/appsec/emitter/httpsec/http.go | 190 + .../appsec/emitter/httpsec/roundtripper.go | 71 + .../internal/appsec/emitter/ossec/lfi.go | 41 + .../appsec/emitter/sharedsec/actions.go | 138 - .../appsec/emitter/sharedsec/shared.go | 71 - .../internal/appsec/emitter/sqlsec/sql.go | 71 + .../emitter/trace/service_entry_span.go | 158 + .../internal/appsec/emitter/trace/span.go | 67 + .../appsec/emitter/trace/tag_setter.go | 29 + .../internal/appsec/emitter/usersec/user.go | 51 + .../appsec/emitter/waf/actions/actions.go | 56 + .../appsec/emitter/waf/actions/block.go | 161 + .../actions}/blocked-template.html | 0 .../actions}/blocked-template.json | 2 +- .../emitter/waf/actions/http_redirect.go | 54 + .../appsec/emitter/waf/actions/stacktrace.go | 44 + .../appsec/emitter/waf/addresses/addresses.go | 40 + .../appsec/emitter/waf/addresses/builder.go | 243 + .../internal/appsec/emitter/waf/context.go | 160 + .../internal/appsec/emitter/waf/run.go | 78 + .../internal/appsec/features.go | 81 + .../internal/appsec/listener/feature.go | 24 + .../appsec/listener/graphqlsec/graphql.go | 43 + .../internal/appsec/listener/grpcsec/grpc.go | 75 + .../internal/appsec/listener/httpsec/http.go | 96 + .../appsec/listener/httpsec/request.go | 167 + .../appsec/listener/httpsec/roundtripper.go | 40 + .../internal/appsec/listener/listener.go | 31 - .../internal/appsec/listener/ossec/lfi.go | 53 + .../internal/appsec/listener/sqlsec/sql.go | 43 + .../internal/appsec/listener/trace/trace.go | 53 + .../internal/appsec/listener/usersec/usec.go | 54 + .../internal/appsec/listener/waf/tags.go | 101 + .../internal/appsec/listener/waf/waf.go | 128 + .../internal/appsec/remoteconfig.go | 137 +- .../internal/appsec/telemetry.go | 12 +- .../dd-trace-go.v1/internal/appsec/waf.go | 109 - .../internal/civisibility/constants/ci.go | 44 + .../internal/civisibility/constants/env.go | 40 + .../internal/civisibility/constants/git.go | 52 + .../internal/civisibility/constants/os.go | 21 + .../civisibility/constants/runtime.go | 16 + .../civisibility/constants/span_types.go | 28 + .../internal/civisibility/constants/tags.go | 47 + .../civisibility/constants/test_tags.go | 109 + .../civisibility/utils/ci_providers.go | 578 + .../internal/civisibility/utils/codeowners.go | 307 + .../civisibility/utils/environmentTags.go | 193 + .../internal/civisibility/utils/git.go | 104 + .../internal/civisibility/utils/home.go | 126 + .../internal/civisibility/utils/names.go | 93 + .../internal/datastreams/pathway.go | 6 +- .../internal/datastreams/processor.go | 89 +- .../internal/datastreams/transport.go | 30 - .../DataDog/dd-trace-go.v1/internal/env.go | 21 +- .../dd-trace-go.v1/internal/gitmetadata.go | 57 +- .../internal/gitmetadatabinary.go | 41 - .../internal/gitmetadatabinary_legacy.go | 19 - .../internal/globalconfig/globalconfig.go | 62 +- .../dd-trace-go.v1/internal/log/log.go | 6 + .../dd-trace-go.v1/internal/meta_struct.go | 12 + .../internal/normalizer/normalizer.go | 4 - .../internal/orchestrion/context.go | 72 + .../internal/orchestrion/context_stack.go | 62 + .../internal/orchestrion/gls.go | 41 + .../internal/orchestrion/orchestrion.go | 16 + .../internal/remoteconfig/remoteconfig.go | 60 +- .../internal/samplernames/samplernames.go | 10 +- .../internal/stacktrace/event.go | 115 + .../internal/stacktrace/event_msgp.go | 333 + .../internal/stacktrace/stacktrace.go | 253 + .../internal/stacktrace/stacktrace_msgp.go | 475 + .../DataDog/dd-trace-go.v1/internal/statsd.go | 207 +- .../internal/telemetry/client.go | 63 +- .../internal/telemetry/message.go | 45 +- .../internal/telemetry/telemetry.go | 9 +- .../internal/telemetry/utils.go | 6 +- .../dd-trace-go.v1/internal/trace_context.go | 10 +- .../DataDog/dd-trace-go.v1/internal/utils.go | 6 + .../internal/version/version.go | 2 +- vendor/k8s.io/klog/v2/klog.go | 76 +- .../k8s.io/kube-openapi/pkg/common/common.go | 3 + .../k8s.io/kube-openapi/pkg/schemaconv/smd.go | 3 - .../kubernetes/pkg/util/iptables/iptables.go | 11 +- .../pkg/util/iptables/save_restore.go | 17 +- vendor/k8s.io/utils/integer/integer.go | 8 +- vendor/k8s.io/utils/net/multi_listen.go | 195 + vendor/k8s.io/utils/trace/trace.go | 2 +- vendor/modules.txt | 283 +- vendor/sigs.k8s.io/yaml/LICENSE | 256 + vendor/sigs.k8s.io/yaml/OWNERS | 8 +- vendor/sigs.k8s.io/yaml/fields.go | 55 +- .../yaml/goyaml.v2}/LICENSE | 5 +- .../yaml/goyaml.v2/LICENSE.libyaml | 31 + .../yaml/goyaml.v2/NOTICE} | 22 +- vendor/sigs.k8s.io/yaml/goyaml.v2/OWNERS | 24 + vendor/sigs.k8s.io/yaml/goyaml.v2/README.md | 143 + vendor/sigs.k8s.io/yaml/goyaml.v2/apic.go | 744 + vendor/sigs.k8s.io/yaml/goyaml.v2/decode.go | 815 + vendor/sigs.k8s.io/yaml/goyaml.v2/emitterc.go | 1685 ++ vendor/sigs.k8s.io/yaml/goyaml.v2/encode.go | 390 + vendor/sigs.k8s.io/yaml/goyaml.v2/parserc.go | 1095 + vendor/sigs.k8s.io/yaml/goyaml.v2/readerc.go | 412 + vendor/sigs.k8s.io/yaml/goyaml.v2/resolve.go | 258 + vendor/sigs.k8s.io/yaml/goyaml.v2/scannerc.go | 2711 +++ vendor/sigs.k8s.io/yaml/goyaml.v2/sorter.go | 113 + vendor/sigs.k8s.io/yaml/goyaml.v2/writerc.go | 26 + vendor/sigs.k8s.io/yaml/goyaml.v2/yaml.go | 478 + vendor/sigs.k8s.io/yaml/goyaml.v2/yamlh.go | 739 + .../yaml/goyaml.v2/yamlprivateh.go | 173 + vendor/sigs.k8s.io/yaml/yaml.go | 145 +- vendor/sigs.k8s.io/yaml/yaml_go110.go | 17 + 1262 files changed, 131319 insertions(+), 46505 deletions(-) delete mode 100644 vendor/github.com/DataDog/appsec-internal-go/appsec/processors.json create mode 100644 vendor/github.com/DataDog/appsec-internal-go/httpsec/client_ip.go create mode 100644 vendor/github.com/DataDog/appsec-internal-go/netip/ip.go delete mode 100644 vendor/github.com/DataDog/go-libddwaf/v2/context.go delete mode 100644 vendor/github.com/DataDog/go-libddwaf/v2/ctypes.go delete mode 100644 vendor/github.com/DataDog/go-libddwaf/v2/decoder.go delete mode 100644 vendor/github.com/DataDog/go-libddwaf/v2/internal/lib/.version delete mode 100644 vendor/github.com/DataDog/go-libddwaf/v2/internal/lib/lib.go delete mode 100644 vendor/github.com/DataDog/go-libddwaf/v2/internal/lib/libddwaf-darwin-amd64.dylib delete mode 100644 vendor/github.com/DataDog/go-libddwaf/v2/internal/lib/libddwaf-darwin-arm64.dylib delete mode 100644 vendor/github.com/DataDog/go-libddwaf/v2/internal/lib/libddwaf-linux-amd64.so delete mode 100644 vendor/github.com/DataDog/go-libddwaf/v2/internal/lib/libddwaf-linux-arm64.so delete mode 100644 vendor/github.com/DataDog/go-libddwaf/v2/internal/log/gostring.go delete mode 100644 vendor/github.com/DataDog/go-libddwaf/v2/internal/noopfree/noopfree.go delete mode 100644 vendor/github.com/DataDog/go-libddwaf/v2/safe.go delete mode 100644 vendor/github.com/DataDog/go-libddwaf/v2/symbols_linux_cgo.go delete mode 100644 vendor/github.com/DataDog/go-libddwaf/v2/symbols_linux_purego.go delete mode 100644 vendor/github.com/DataDog/go-libddwaf/v2/waf_dl_unsupported.go delete mode 100644 vendor/github.com/DataDog/go-libddwaf/v2/waf_support.go rename vendor/github.com/DataDog/go-libddwaf/{v2 => v3}/.gitattributes (100%) rename vendor/github.com/DataDog/go-libddwaf/{v2 => v3}/.gitignore (71%) create mode 100644 vendor/github.com/DataDog/go-libddwaf/v3/CODEOWNERS rename vendor/github.com/DataDog/go-libddwaf/{v2 => v3}/LICENSE (100%) rename vendor/github.com/DataDog/go-libddwaf/{v2 => v3}/README.md (87%) rename vendor/github.com/DataDog/go-libddwaf/{v2 => v3}/cgo_ref_pool.go (70%) create mode 100644 vendor/github.com/DataDog/go-libddwaf/v3/context.go create mode 100644 vendor/github.com/DataDog/go-libddwaf/v3/decoder.go rename vendor/github.com/DataDog/go-libddwaf/{v2 => v3}/encoder.go (76%) create mode 100644 vendor/github.com/DataDog/go-libddwaf/v3/errors/support.go create mode 100644 vendor/github.com/DataDog/go-libddwaf/v3/errors/waf.go rename vendor/github.com/DataDog/go-libddwaf/{v2 => v3}/handle.go (64%) create mode 100644 vendor/github.com/DataDog/go-libddwaf/v3/internal/bindings/ctypes.go create mode 100644 vendor/github.com/DataDog/go-libddwaf/v3/internal/bindings/safe.go rename vendor/github.com/DataDog/go-libddwaf/{v2 => v3/internal/bindings}/waf_dl.go (51%) create mode 100644 vendor/github.com/DataDog/go-libddwaf/v3/internal/bindings/waf_dl_unsupported.go create mode 100644 vendor/github.com/DataDog/go-libddwaf/v3/internal/lib/.version rename vendor/github.com/DataDog/go-libddwaf/{v2 => v3}/internal/lib/README.md (100%) rename vendor/github.com/DataDog/go-libddwaf/{v2 => v3}/internal/lib/doc.go (100%) create mode 100644 vendor/github.com/DataDog/go-libddwaf/v3/internal/lib/dump_waf_darwin.go create mode 100644 vendor/github.com/DataDog/go-libddwaf/v3/internal/lib/dump_waf_linux.go rename vendor/github.com/DataDog/go-libddwaf/{v2 => v3}/internal/lib/lib_darwin_amd64.go (71%) rename vendor/github.com/DataDog/go-libddwaf/{v2 => v3}/internal/lib/lib_darwin_arm64.go (71%) rename vendor/github.com/DataDog/go-libddwaf/{v2 => v3}/internal/lib/lib_linux_amd64.go (72%) rename vendor/github.com/DataDog/go-libddwaf/{v2 => v3}/internal/lib/lib_linux_arm64.go (72%) create mode 100644 vendor/github.com/DataDog/go-libddwaf/v3/internal/lib/libddwaf-darwin-amd64.dylib.gz create mode 100644 vendor/github.com/DataDog/go-libddwaf/v3/internal/lib/libddwaf-darwin-arm64.dylib.gz create mode 100644 vendor/github.com/DataDog/go-libddwaf/v3/internal/lib/libddwaf-linux-amd64.so.gz create mode 100644 vendor/github.com/DataDog/go-libddwaf/v3/internal/lib/libddwaf-linux-arm64.so.gz rename vendor/github.com/DataDog/go-libddwaf/{v2/internal/noopfree/noopfree.s => v3/internal/lib/version.go} (60%) rename vendor/github.com/DataDog/go-libddwaf/{v2 => v3}/internal/log/ddwaf.h (95%) rename vendor/github.com/DataDog/go-libddwaf/{v2 => v3}/internal/log/log.go (100%) rename vendor/github.com/DataDog/go-libddwaf/{v2 => v3}/internal/log/log_cgo.go (58%) rename vendor/github.com/DataDog/go-libddwaf/{v2 => v3}/internal/log/log_purego.go (83%) rename vendor/github.com/DataDog/go-libddwaf/{v2 => v3}/internal/log/log_unsupported.go (88%) rename vendor/github.com/DataDog/go-libddwaf/{v2 => v3/internal/support}/waf_cgo_disabled.go (72%) rename vendor/github.com/DataDog/go-libddwaf/{v2 => v3/internal/support}/waf_manually_disabled.go (72%) create mode 100644 vendor/github.com/DataDog/go-libddwaf/v3/internal/support/waf_support.go rename vendor/github.com/DataDog/go-libddwaf/{v2 => v3/internal/support}/waf_unsupported_go.go (64%) rename vendor/github.com/DataDog/go-libddwaf/{v2 => v3/internal/support}/waf_unsupported_target.go (72%) create mode 100644 vendor/github.com/DataDog/go-libddwaf/v3/internal/unsafe/utils.go create mode 100644 vendor/github.com/DataDog/go-libddwaf/v3/metrics.go create mode 100644 vendor/github.com/DataDog/go-libddwaf/v3/timer/base_timer.go create mode 100644 vendor/github.com/DataDog/go-libddwaf/v3/timer/clock.go create mode 100644 vendor/github.com/DataDog/go-libddwaf/v3/timer/component.go create mode 100644 vendor/github.com/DataDog/go-libddwaf/v3/timer/config.go create mode 100644 vendor/github.com/DataDog/go-libddwaf/v3/timer/node_timer.go create mode 100644 vendor/github.com/DataDog/go-libddwaf/v3/timer/timer.go rename vendor/github.com/DataDog/go-libddwaf/{v2 => v3}/waf.go (62%) create mode 100644 vendor/github.com/eapache/queue/v2/LICENSE create mode 100644 vendor/github.com/eapache/queue/v2/queue.go create mode 100644 vendor/github.com/fsnotify/fsnotify/.cirrus.yml create mode 100644 vendor/github.com/go-task/slim-sprig/v3/.editorconfig create mode 100644 vendor/github.com/go-task/slim-sprig/v3/.gitattributes create mode 100644 vendor/github.com/go-task/slim-sprig/v3/.gitignore create mode 100644 vendor/github.com/go-task/slim-sprig/v3/CHANGELOG.md create mode 100644 vendor/github.com/go-task/slim-sprig/v3/LICENSE.txt create mode 100644 vendor/github.com/go-task/slim-sprig/v3/README.md create mode 100644 vendor/github.com/go-task/slim-sprig/v3/Taskfile.yml create mode 100644 vendor/github.com/go-task/slim-sprig/v3/crypto.go create mode 100644 vendor/github.com/go-task/slim-sprig/v3/date.go create mode 100644 vendor/github.com/go-task/slim-sprig/v3/defaults.go create mode 100644 vendor/github.com/go-task/slim-sprig/v3/dict.go create mode 100644 vendor/github.com/go-task/slim-sprig/v3/doc.go create mode 100644 vendor/github.com/go-task/slim-sprig/v3/functions.go create mode 100644 vendor/github.com/go-task/slim-sprig/v3/list.go create mode 100644 vendor/github.com/go-task/slim-sprig/v3/network.go create mode 100644 vendor/github.com/go-task/slim-sprig/v3/numeric.go create mode 100644 vendor/github.com/go-task/slim-sprig/v3/reflect.go create mode 100644 vendor/github.com/go-task/slim-sprig/v3/regex.go create mode 100644 vendor/github.com/go-task/slim-sprig/v3/strings.go create mode 100644 vendor/github.com/go-task/slim-sprig/v3/url.go delete mode 100644 vendor/github.com/hashicorp/errwrap/README.md delete mode 100644 vendor/github.com/hashicorp/errwrap/errwrap.go delete mode 100644 vendor/github.com/hashicorp/go-multierror/Makefile delete mode 100644 vendor/github.com/hashicorp/go-multierror/README.md delete mode 100644 vendor/github.com/hashicorp/go-multierror/append.go delete mode 100644 vendor/github.com/hashicorp/go-multierror/flatten.go delete mode 100644 vendor/github.com/hashicorp/go-multierror/format.go delete mode 100644 vendor/github.com/hashicorp/go-multierror/group.go delete mode 100644 vendor/github.com/hashicorp/go-multierror/multierror.go delete mode 100644 vendor/github.com/hashicorp/go-multierror/prefix.go delete mode 100644 vendor/github.com/hashicorp/go-multierror/sort.go rename vendor/github.com/hashicorp/{errwrap => go-secure-stdlib/parseutil}/LICENSE (50%) create mode 100644 vendor/github.com/hashicorp/go-secure-stdlib/parseutil/parsepath.go create mode 100644 vendor/github.com/hashicorp/go-secure-stdlib/parseutil/parseutil.go rename vendor/github.com/hashicorp/{go-multierror => go-secure-stdlib/strutil}/LICENSE (50%) create mode 100644 vendor/github.com/hashicorp/go-secure-stdlib/strutil/strutil.go create mode 100644 vendor/github.com/hashicorp/go-sockaddr/.gitignore create mode 100644 vendor/github.com/hashicorp/go-sockaddr/GNUmakefile create mode 100644 vendor/github.com/hashicorp/go-sockaddr/LICENSE create mode 100644 vendor/github.com/hashicorp/go-sockaddr/README.md create mode 100644 vendor/github.com/hashicorp/go-sockaddr/doc.go create mode 100644 vendor/github.com/hashicorp/go-sockaddr/ifaddr.go create mode 100644 vendor/github.com/hashicorp/go-sockaddr/ifaddrs.go create mode 100644 vendor/github.com/hashicorp/go-sockaddr/ifattr.go create mode 100644 vendor/github.com/hashicorp/go-sockaddr/ipaddr.go create mode 100644 vendor/github.com/hashicorp/go-sockaddr/ipaddrs.go create mode 100644 vendor/github.com/hashicorp/go-sockaddr/ipv4addr.go create mode 100644 vendor/github.com/hashicorp/go-sockaddr/ipv6addr.go create mode 100644 vendor/github.com/hashicorp/go-sockaddr/rfc.go create mode 100644 vendor/github.com/hashicorp/go-sockaddr/route_info.go create mode 100644 vendor/github.com/hashicorp/go-sockaddr/route_info_android.go create mode 100644 vendor/github.com/hashicorp/go-sockaddr/route_info_bsd.go create mode 100644 vendor/github.com/hashicorp/go-sockaddr/route_info_default.go create mode 100644 vendor/github.com/hashicorp/go-sockaddr/route_info_linux.go create mode 100644 vendor/github.com/hashicorp/go-sockaddr/route_info_solaris.go create mode 100644 vendor/github.com/hashicorp/go-sockaddr/route_info_windows.go create mode 100644 vendor/github.com/hashicorp/go-sockaddr/sockaddr.go create mode 100644 vendor/github.com/hashicorp/go-sockaddr/sockaddrs.go create mode 100644 vendor/github.com/hashicorp/go-sockaddr/unixsock.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/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/mitchellh/mapstructure/CHANGELOG.md create mode 100644 vendor/github.com/mitchellh/mapstructure/LICENSE create mode 100644 vendor/github.com/mitchellh/mapstructure/README.md create mode 100644 vendor/github.com/mitchellh/mapstructure/decode_hooks.go create mode 100644 vendor/github.com/mitchellh/mapstructure/error.go create mode 100644 vendor/github.com/mitchellh/mapstructure/mapstructure.go create mode 100644 vendor/github.com/onsi/ginkgo/v2/ginkgo/internal/gocovmerge.go create mode 100644 vendor/github.com/openzipkin/zipkin-go/SECURITY.md create mode 100644 vendor/github.com/prometheus/client_golang/internal/github.com/golang/gddo/LICENSE create mode 100644 vendor/github.com/prometheus/client_golang/internal/github.com/golang/gddo/httputil/header/header.go create mode 100644 vendor/github.com/prometheus/client_golang/internal/github.com/golang/gddo/httputil/negotiate.go delete mode 100644 vendor/github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg/README.txt delete mode 100644 vendor/github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg/autoneg.go delete mode 100644 vendor/github.com/prometheus/common/model/labelset_string_go120.go create mode 100644 vendor/github.com/prometheus/procfs/net_tls_stat.go create mode 100644 vendor/github.com/quic-go/quic-go/connection_logging.go delete mode 100644 vendor/github.com/quic-go/quic-go/internal/logutils/frame.go rename vendor/github.com/quic-go/quic-go/internal/{handshake => qtls}/conn.go (97%) delete mode 100644 vendor/github.com/quic-go/quic-go/internal/utils/byteorder.go delete mode 100644 vendor/github.com/quic-go/quic-go/internal/utils/byteorder_big_endian.go delete mode 100644 vendor/github.com/quic-go/quic-go/internal/utils/ip.go delete mode 100644 vendor/github.com/quic-go/quic-go/internal/utils/minmax.go delete mode 100644 vendor/github.com/quic-go/quic-go/window_update_queue.go create mode 100644 vendor/github.com/ryanuber/go-glob/.travis.yml create mode 100644 vendor/github.com/ryanuber/go-glob/LICENSE create mode 100644 vendor/github.com/ryanuber/go-glob/README.md create mode 100644 vendor/github.com/ryanuber/go-glob/glob.go delete mode 100644 vendor/github.com/spf13/cobra/active_help.md delete mode 100644 vendor/github.com/spf13/cobra/bash_completions.md delete mode 100644 vendor/github.com/spf13/cobra/fish_completions.md delete mode 100644 vendor/github.com/spf13/cobra/powershell_completions.md delete mode 100644 vendor/github.com/spf13/cobra/projects_using_cobra.md delete mode 100644 vendor/github.com/spf13/cobra/shell_completions.md delete mode 100644 vendor/github.com/spf13/cobra/user_guide.md delete mode 100644 vendor/github.com/spf13/cobra/zsh_completions.md delete mode 100644 vendor/github.com/stretchr/testify/assert/assertion_compare_can_convert.go delete mode 100644 vendor/github.com/stretchr/testify/assert/assertion_compare_legacy.go delete mode 100644 vendor/github.com/vishvananda/netlink/.travis.yml create mode 100644 vendor/github.com/vishvananda/netlink/chain.go create mode 100644 vendor/github.com/vishvananda/netlink/chain_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/inet_diag.go create mode 100644 vendor/github.com/vishvananda/netlink/ipset_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/nl/ip6tnl_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/nl/ipset_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/nl/lwt_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/nl/parse_attr_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/nl/vdpa_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/proc_event_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/rule_nonlinux.go create mode 100644 vendor/github.com/vishvananda/netlink/socket_xdp_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/tcp.go create mode 100644 vendor/github.com/vishvananda/netlink/tcp_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/unix_diag.go create mode 100644 vendor/github.com/vishvananda/netlink/vdpa_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/virtio.go create mode 100644 vendor/github.com/vishvananda/netlink/xdp_diag.go create mode 100644 vendor/github.com/vishvananda/netlink/xdp_linux.go rename vendor/github.com/vishvananda/netlink/{xfrm.go => xfrm_linux.go} (95%) delete mode 100644 vendor/github.com/vishvananda/netlink/xfrm_policy.go delete mode 100644 vendor/github.com/vishvananda/netlink/xfrm_state.go create mode 100644 vendor/github.com/vishvananda/netlink/xfrm_unspecified.go create mode 100644 vendor/go.uber.org/automaxprocs/LICENSE create mode 100644 vendor/go.uber.org/automaxprocs/internal/cgroups/cgroup.go create mode 100644 vendor/go.uber.org/automaxprocs/internal/cgroups/cgroups.go create mode 100644 vendor/go.uber.org/automaxprocs/internal/cgroups/cgroups2.go rename vendor/go.uber.org/{zap/global_prego112.go => automaxprocs/internal/cgroups/doc.go} (84%) create mode 100644 vendor/go.uber.org/automaxprocs/internal/cgroups/errors.go create mode 100644 vendor/go.uber.org/automaxprocs/internal/cgroups/mountpoint.go create mode 100644 vendor/go.uber.org/automaxprocs/internal/cgroups/subsys.go create mode 100644 vendor/go.uber.org/automaxprocs/internal/runtime/cpu_quota_linux.go create mode 100644 vendor/go.uber.org/automaxprocs/internal/runtime/cpu_quota_unsupported.go create mode 100644 vendor/go.uber.org/automaxprocs/internal/runtime/runtime.go create mode 100644 vendor/go.uber.org/automaxprocs/maxprocs/maxprocs.go rename vendor/go.uber.org/{zap/global_go112.go => automaxprocs/maxprocs/version.go} (88%) create mode 100644 vendor/go.uber.org/zap/.golangci.yml create mode 100644 vendor/go.uber.org/zap/internal/level_enabler.go create mode 100644 vendor/go.uber.org/zap/internal/pool/pool.go create mode 100644 vendor/go.uber.org/zap/internal/stacktrace/stack.go delete mode 100644 vendor/go.uber.org/zap/stacktrace.go create mode 100644 vendor/go.uber.org/zap/zapcore/lazy_with.go create mode 100644 vendor/go.uber.org/zap/zapcore/reflected_encoder.go rename vendor/golang.org/x/crypto/chacha20/{chacha_ppc64le.go => chacha_ppc64x.go} (89%) rename vendor/golang.org/x/crypto/chacha20/{chacha_ppc64le.s => chacha_ppc64x.s} (76%) rename vendor/golang.org/x/crypto/internal/poly1305/{sum_ppc64le.go => sum_ppc64x.go} (95%) rename vendor/golang.org/x/crypto/internal/poly1305/{sum_ppc64le.s => sum_ppc64x.s} (89%) create mode 100644 vendor/golang.org/x/net/html/iter.go create mode 100644 vendor/golang.org/x/net/http2/config.go create mode 100644 vendor/golang.org/x/net/http2/config_go124.go create mode 100644 vendor/golang.org/x/net/http2/config_pre_go124.go delete mode 100644 vendor/golang.org/x/net/http2/testsync.go create mode 100644 vendor/golang.org/x/net/http2/timer.go create mode 100644 vendor/golang.org/x/net/http2/unencrypted.go delete mode 100644 vendor/golang.org/x/oauth2/internal/client_appengine.go create mode 100644 vendor/golang.org/x/sync/LICENSE create mode 100644 vendor/golang.org/x/sync/PATENTS create mode 100644 vendor/golang.org/x/sync/errgroup/errgroup.go create mode 100644 vendor/golang.org/x/sync/errgroup/go120.go create mode 100644 vendor/golang.org/x/sync/errgroup/pre_go120.go create mode 100644 vendor/golang.org/x/sys/cpu/asm_darwin_x86_gc.s create mode 100644 vendor/golang.org/x/sys/cpu/cpu_darwin_x86.go rename vendor/golang.org/x/sys/cpu/{cpu_x86.s => cpu_gc_x86.s} (94%) create mode 100644 vendor/golang.org/x/sys/cpu/cpu_linux_riscv64.go create mode 100644 vendor/golang.org/x/sys/cpu/cpu_other_x86.go create mode 100644 vendor/golang.org/x/sys/cpu/syscall_darwin_x86_gc.go create mode 100644 vendor/golang.org/x/sys/unix/bpxsvc_zos.go create mode 100644 vendor/golang.org/x/sys/unix/bpxsvc_zos.s delete mode 100644 vendor/golang.org/x/sys/unix/epoll_zos.go delete mode 100644 vendor/golang.org/x/sys/unix/fstatfs_zos.go create mode 100644 vendor/golang.org/x/sys/unix/sockcmsg_zos.go create mode 100644 vendor/golang.org/x/sys/unix/symaddr_zos_s390x.s create mode 100644 vendor/golang.org/x/sys/unix/vgetrandom_linux.go create mode 100644 vendor/golang.org/x/sys/unix/vgetrandom_unsupported.go create mode 100644 vendor/golang.org/x/sys/unix/zsymaddr_zos_s390x.s delete mode 100644 vendor/golang.org/x/sys/windows/empty.s create mode 100644 vendor/golang.org/x/tools/cover/profile.go create mode 100644 vendor/golang.org/x/tools/internal/aliases/aliases.go create mode 100644 vendor/golang.org/x/tools/internal/aliases/aliases_go121.go create mode 100644 vendor/golang.org/x/tools/internal/aliases/aliases_go122.go delete mode 100644 vendor/golang.org/x/tools/internal/event/tag/tag.go delete mode 100644 vendor/golang.org/x/tools/internal/gcimporter/support_go117.go delete mode 100644 vendor/golang.org/x/tools/internal/gcimporter/ureader_no.go delete mode 100644 vendor/golang.org/x/tools/internal/imports/zstdlib.go create mode 100644 vendor/golang.org/x/tools/internal/stdlib/manifest.go create mode 100644 vendor/golang.org/x/tools/internal/stdlib/stdlib.go delete mode 100644 vendor/golang.org/x/tools/internal/typeparams/common.go delete mode 100644 vendor/golang.org/x/tools/internal/typeparams/coretype.go delete mode 100644 vendor/golang.org/x/tools/internal/typeparams/normalize.go delete mode 100644 vendor/golang.org/x/tools/internal/typeparams/termlist.go delete mode 100644 vendor/golang.org/x/tools/internal/typeparams/typeterm.go create mode 100644 vendor/golang.org/x/tools/internal/typesinternal/recv.go create mode 100644 vendor/golang.org/x/tools/internal/typesinternal/toonew.go delete mode 100644 vendor/golang.org/x/tools/internal/typesinternal/types_118.go create mode 100644 vendor/golang.org/x/tools/internal/versions/features.go create mode 100644 vendor/golang.org/x/tools/internal/versions/toolchain.go create mode 100644 vendor/golang.org/x/tools/internal/versions/toolchain_go119.go create mode 100644 vendor/golang.org/x/tools/internal/versions/toolchain_go120.go create mode 100644 vendor/golang.org/x/tools/internal/versions/toolchain_go121.go delete mode 100644 vendor/google.golang.org/appengine/internal/api.go delete mode 100644 vendor/google.golang.org/appengine/internal/api_classic.go delete mode 100644 vendor/google.golang.org/appengine/internal/api_common.go delete mode 100644 vendor/google.golang.org/appengine/internal/app_id.go delete mode 100644 vendor/google.golang.org/appengine/internal/base/api_base.pb.go delete mode 100644 vendor/google.golang.org/appengine/internal/base/api_base.proto delete mode 100644 vendor/google.golang.org/appengine/internal/datastore/datastore_v3.pb.go delete mode 100644 vendor/google.golang.org/appengine/internal/datastore/datastore_v3.proto delete mode 100644 vendor/google.golang.org/appengine/internal/identity.go delete mode 100644 vendor/google.golang.org/appengine/internal/identity_classic.go delete mode 100644 vendor/google.golang.org/appengine/internal/identity_flex.go delete mode 100644 vendor/google.golang.org/appengine/internal/identity_vm.go delete mode 100644 vendor/google.golang.org/appengine/internal/internal.go delete mode 100644 vendor/google.golang.org/appengine/internal/log/log_service.pb.go delete mode 100644 vendor/google.golang.org/appengine/internal/log/log_service.proto delete mode 100644 vendor/google.golang.org/appengine/internal/main.go delete mode 100644 vendor/google.golang.org/appengine/internal/main_common.go delete mode 100644 vendor/google.golang.org/appengine/internal/main_vm.go delete mode 100644 vendor/google.golang.org/appengine/internal/metadata.go delete mode 100644 vendor/google.golang.org/appengine/internal/net.go delete mode 100644 vendor/google.golang.org/appengine/internal/regen.sh delete mode 100644 vendor/google.golang.org/appengine/internal/remote_api/remote_api.pb.go delete mode 100644 vendor/google.golang.org/appengine/internal/remote_api/remote_api.proto delete mode 100644 vendor/google.golang.org/appengine/internal/transaction.go delete mode 100644 vendor/google.golang.org/appengine/internal/urlfetch/urlfetch_service.pb.go delete mode 100644 vendor/google.golang.org/appengine/internal/urlfetch/urlfetch_service.proto delete mode 100644 vendor/google.golang.org/appengine/urlfetch/urlfetch.go create mode 100644 vendor/google.golang.org/grpc/balancer/pickfirst/internal/internal.go rename vendor/google.golang.org/grpc/{ => balancer/pickfirst}/pickfirst.go (70%) create mode 100644 vendor/google.golang.org/grpc/balancer/pickfirst/pickfirstleaf/pickfirstleaf.go delete mode 100644 vendor/google.golang.org/grpc/codegen.sh create mode 100644 vendor/google.golang.org/grpc/encoding/encoding_v2.go create mode 100644 vendor/google.golang.org/grpc/experimental/stats/metricregistry.go create mode 100644 vendor/google.golang.org/grpc/experimental/stats/metrics.go create mode 100644 vendor/google.golang.org/grpc/grpclog/internal/grpclog.go create mode 100644 vendor/google.golang.org/grpc/grpclog/internal/logger.go rename vendor/google.golang.org/grpc/{internal/grpclog/grpclog.go => grpclog/internal/loggerv2.go} (52%) rename vendor/google.golang.org/grpc/internal/grpclog/{prefixLogger.go => prefix_logger.go} (63%) delete mode 100644 vendor/google.golang.org/grpc/internal/grpcrand/grpcrand.go delete mode 100644 vendor/google.golang.org/grpc/internal/grpcrand/grpcrand_go1.21.go create mode 100644 vendor/google.golang.org/grpc/internal/stats/labels.go create mode 100644 vendor/google.golang.org/grpc/internal/stats/metrics_recorder_list.go create mode 100644 vendor/google.golang.org/grpc/mem/buffer_pool.go create mode 100644 vendor/google.golang.org/grpc/mem/buffer_slice.go create mode 100644 vendor/google.golang.org/grpc/mem/buffers.go delete mode 100644 vendor/google.golang.org/grpc/regenerate.sh delete mode 100644 vendor/google.golang.org/grpc/shared_buffer_pool.go create mode 100644 vendor/google.golang.org/grpc/stream_interfaces.go delete mode 100644 vendor/google.golang.org/grpc/vet.sh create mode 100644 vendor/google.golang.org/protobuf/internal/editionssupport/editions.go delete mode 100644 vendor/google.golang.org/protobuf/internal/impl/codec_reflect.go create mode 100644 vendor/google.golang.org/protobuf/internal/impl/equal.go delete mode 100644 vendor/google.golang.org/protobuf/internal/impl/pointer_reflect.go delete mode 100644 vendor/google.golang.org/protobuf/internal/strs/strings_pure.go delete mode 100644 vendor/google.golang.org/protobuf/reflect/protoreflect/value_pure.go delete mode 100644 vendor/google.golang.org/protobuf/types/gofeaturespb/go_features.proto create mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/appsec/events/block.go create mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/ext/log_key.go create mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/civisibility_payload.go create mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/civisibility_transport.go create mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/civisibility_tslv.go create mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/civisibility_tslv_msgp.go create mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/civisibility_writer.go create mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/meta_struct.go create mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/otel_dd_mappings.go create mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/README.md create mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/graphqlsec/README.md create mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/graphqlsec/execution.go create mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/graphqlsec/request.go create mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/graphqlsec/resolve.go create mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/grpcsec/grpc.go create mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/httpsec/config.go create mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/httpsec/http.go create mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/httpsec/roundtripper.go create mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/ossec/lfi.go delete mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/sharedsec/actions.go delete mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/sharedsec/shared.go create mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/sqlsec/sql.go create mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/trace/service_entry_span.go create mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/trace/span.go create mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/trace/tag_setter.go create mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/usersec/user.go create mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/waf/actions/actions.go create mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/waf/actions/block.go rename vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/{sharedsec => waf/actions}/blocked-template.html (100%) rename vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/{sharedsec => waf/actions}/blocked-template.json (78%) create mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/waf/actions/http_redirect.go create mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/waf/actions/stacktrace.go create mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/waf/addresses/addresses.go create mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/waf/addresses/builder.go create mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/waf/context.go create mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/waf/run.go create mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/features.go create mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener/feature.go create mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener/graphqlsec/graphql.go create mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener/grpcsec/grpc.go create mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener/httpsec/http.go create mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener/httpsec/request.go create mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener/httpsec/roundtripper.go delete mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener/listener.go create mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener/ossec/lfi.go create mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener/sqlsec/sql.go create mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener/trace/trace.go create mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener/usersec/usec.go create mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener/waf/tags.go create mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener/waf/waf.go delete mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/waf.go create mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/civisibility/constants/ci.go create mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/civisibility/constants/env.go create mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/civisibility/constants/git.go create mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/civisibility/constants/os.go create mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/civisibility/constants/runtime.go create mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/civisibility/constants/span_types.go create mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/civisibility/constants/tags.go create mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/civisibility/constants/test_tags.go create mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/civisibility/utils/ci_providers.go create mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/civisibility/utils/codeowners.go create mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/civisibility/utils/environmentTags.go create mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/civisibility/utils/git.go create mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/civisibility/utils/home.go create mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/civisibility/utils/names.go delete mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/gitmetadatabinary.go delete mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/gitmetadatabinary_legacy.go create mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/meta_struct.go create mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/orchestrion/context.go create mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/orchestrion/context_stack.go create mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/orchestrion/gls.go create mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/orchestrion/orchestrion.go create mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/stacktrace/event.go create mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/stacktrace/event_msgp.go create mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/stacktrace/stacktrace.go create mode 100644 vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/stacktrace/stacktrace_msgp.go create mode 100644 vendor/k8s.io/utils/net/multi_listen.go rename vendor/{google.golang.org/appengine => sigs.k8s.io/yaml/goyaml.v2}/LICENSE (99%) create mode 100644 vendor/sigs.k8s.io/yaml/goyaml.v2/LICENSE.libyaml rename vendor/{k8s.io/kubernetes/pkg/util/iptables/iptables_unsupported.go => sigs.k8s.io/yaml/goyaml.v2/NOTICE} (57%) create mode 100644 vendor/sigs.k8s.io/yaml/goyaml.v2/OWNERS create mode 100644 vendor/sigs.k8s.io/yaml/goyaml.v2/README.md create mode 100644 vendor/sigs.k8s.io/yaml/goyaml.v2/apic.go create mode 100644 vendor/sigs.k8s.io/yaml/goyaml.v2/decode.go create mode 100644 vendor/sigs.k8s.io/yaml/goyaml.v2/emitterc.go create mode 100644 vendor/sigs.k8s.io/yaml/goyaml.v2/encode.go create mode 100644 vendor/sigs.k8s.io/yaml/goyaml.v2/parserc.go create mode 100644 vendor/sigs.k8s.io/yaml/goyaml.v2/readerc.go create mode 100644 vendor/sigs.k8s.io/yaml/goyaml.v2/resolve.go create mode 100644 vendor/sigs.k8s.io/yaml/goyaml.v2/scannerc.go create mode 100644 vendor/sigs.k8s.io/yaml/goyaml.v2/sorter.go create mode 100644 vendor/sigs.k8s.io/yaml/goyaml.v2/writerc.go create mode 100644 vendor/sigs.k8s.io/yaml/goyaml.v2/yaml.go create mode 100644 vendor/sigs.k8s.io/yaml/goyaml.v2/yamlh.go create mode 100644 vendor/sigs.k8s.io/yaml/goyaml.v2/yamlprivateh.go diff --git a/go.mod b/go.mod index 335a6787c..4df790d50 100644 --- a/go.mod +++ b/go.mod @@ -1,127 +1,135 @@ module k8s.io/dns go 1.22 +toolchain go1.22.9 require ( - github.com/coredns/caddy v1.1.1 - github.com/coredns/coredns v1.11.3 + github.com/coredns/caddy v1.1.2-0.20241029205200-8de985351a98 + github.com/coredns/coredns v1.12.0 github.com/coreos/etcd v3.3.13+incompatible github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf - github.com/miekg/dns v1.1.58 + github.com/miekg/dns v1.1.62 github.com/onsi/ginkgo v1.16.5 - github.com/onsi/gomega v1.27.10 - github.com/prometheus/client_golang v1.19.0 + github.com/onsi/gomega v1.33.1 + github.com/prometheus/client_golang v1.20.5 github.com/spf13/pflag v1.0.5 - github.com/stretchr/testify v1.8.4 - github.com/vishvananda/netlink v1.1.0 - go.etcd.io/etcd/api/v3 v3.5.12 - go.etcd.io/etcd/client/v2 v2.305.9 - go.etcd.io/etcd/client/v3 v3.5.12 - golang.org/x/net v0.23.0 - k8s.io/api v0.29.3 - k8s.io/apimachinery v0.29.3 - k8s.io/client-go v0.29.3 + github.com/stretchr/testify v1.9.0 + github.com/vishvananda/netlink v1.3.0 + go.etcd.io/etcd/api/v3 v3.5.17 + go.etcd.io/etcd/client/v2 v2.305.17 + go.etcd.io/etcd/client/v3 v3.5.17 + golang.org/x/net v0.31.0 + k8s.io/api v0.31.2 + k8s.io/apimachinery v0.31.2 + k8s.io/client-go v0.31.2 k8s.io/component-base v0.24.7 - k8s.io/klog/v2 v2.120.1 - k8s.io/kubernetes v1.28.14 - k8s.io/utils v0.0.0-20230726121419-3b25d923346b + k8s.io/klog/v2 v2.130.1 + k8s.io/kubernetes v1.31.3 + k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 ) require ( - github.com/DataDog/appsec-internal-go v1.5.0 // indirect + github.com/DataDog/appsec-internal-go v1.8.0 // indirect github.com/DataDog/datadog-agent/pkg/obfuscate v0.48.0 // indirect - github.com/DataDog/datadog-agent/pkg/remoteconfig/state v0.48.1 // indirect + github.com/DataDog/datadog-agent/pkg/remoteconfig/state v0.57.0 // indirect github.com/DataDog/datadog-go/v5 v5.3.0 // indirect - github.com/DataDog/go-libddwaf/v2 v2.3.2 // indirect - github.com/DataDog/go-tuf v1.0.2-0.5.2 // indirect - github.com/DataDog/sketches-go v1.4.2 // indirect + github.com/DataDog/go-libddwaf/v3 v3.4.0 // indirect + github.com/DataDog/go-tuf v1.1.0-0.5.2 // indirect + github.com/DataDog/sketches-go v1.4.5 // indirect github.com/Microsoft/go-winio v0.6.1 // indirect github.com/apparentlymart/go-cidr v1.1.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/blang/semver/v4 v4.0.0 // indirect - github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/coreos/go-semver v0.3.1 // indirect github.com/coreos/go-systemd/v22 v22.5.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/dnstap/golang-dnstap v0.4.0 // indirect github.com/dustin/go-humanize v1.0.1 // indirect + github.com/eapache/queue/v2 v2.0.0-20230407133247-75960ed334e4 // indirect github.com/ebitengine/purego v0.6.0-alpha.5 // indirect github.com/emicklei/go-restful/v3 v3.11.0 // indirect github.com/evanphx/json-patch v5.6.0+incompatible // indirect github.com/farsightsec/golang-framestream v0.3.0 // indirect github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 // indirect - github.com/fsnotify/fsnotify v1.6.0 // indirect - github.com/go-logr/logr v1.4.1 // indirect + github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/go-logr/logr v1.4.2 // indirect github.com/go-openapi/jsonpointer v0.19.6 // indirect github.com/go-openapi/jsonreference v0.20.2 // indirect - github.com/go-openapi/swag v0.22.3 // indirect + github.com/go-openapi/swag v0.22.4 // indirect github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect + github.com/go-task/slim-sprig/v3 v3.0.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/google/gnostic-models v0.6.8 // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/google/gofuzz v1.2.0 // indirect - github.com/google/pprof v0.0.0-20230817174616-7a8ec2ada47b // indirect + github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af // indirect github.com/google/uuid v1.6.0 // indirect github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645 // indirect - github.com/hashicorp/errwrap v1.1.0 // indirect - github.com/hashicorp/go-multierror v1.1.1 // indirect + github.com/hashicorp/go-secure-stdlib/parseutil v0.1.7 // indirect + github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 // indirect + github.com/hashicorp/go-sockaddr v1.0.2 // indirect github.com/imdario/mergo v0.3.12 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect + github.com/klauspost/compress v1.17.9 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/nxadm/tail v1.4.8 // indirect - github.com/onsi/ginkgo/v2 v2.13.0 // indirect + github.com/onsi/ginkgo/v2 v2.19.0 // indirect github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492 // indirect github.com/opentracing/opentracing-go v1.2.0 // indirect github.com/openzipkin-contrib/zipkin-go-opentracing v0.5.0 // indirect - github.com/openzipkin/zipkin-go v0.4.2 // indirect + github.com/openzipkin/zipkin-go v0.4.3 // indirect github.com/outcaste-io/ristretto v0.2.3 // indirect - github.com/philhofer/fwd v1.1.2 // indirect + github.com/philhofer/fwd v1.1.3-0.20240612014219-fbbf4953d986 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_model v0.6.0 // indirect - github.com/prometheus/common v0.53.0 // indirect - github.com/prometheus/procfs v0.12.0 // indirect - github.com/quic-go/quic-go v0.42.0 // indirect + github.com/prometheus/client_model v0.6.1 // indirect + github.com/prometheus/common v0.60.1 // indirect + github.com/prometheus/procfs v0.15.1 // indirect + github.com/quic-go/quic-go v0.48.1 // indirect + github.com/ryanuber/go-glob v1.0.0 // indirect github.com/secure-systems-lab/go-securesystemslib v0.7.0 // indirect - github.com/spf13/cobra v1.7.0 // indirect - github.com/tinylib/msgp v1.1.8 // indirect + github.com/spf13/cobra v1.8.1 // indirect + github.com/tinylib/msgp v1.2.1 // indirect github.com/vishvananda/netns v0.0.4 // indirect - go.etcd.io/etcd/client/pkg/v3 v3.5.12 // indirect + go.etcd.io/etcd/client/pkg/v3 v3.5.17 // indirect go.uber.org/atomic v1.11.0 // indirect + go.uber.org/automaxprocs v1.6.0 // indirect go.uber.org/mock v0.4.0 // indirect go.uber.org/multierr v1.11.0 // indirect - go.uber.org/zap v1.19.0 // indirect - golang.org/x/crypto v0.22.0 // indirect - golang.org/x/exp v0.0.0-20230321023759-10a507213a29 // indirect - golang.org/x/mod v0.14.0 // indirect - golang.org/x/oauth2 v0.18.0 // indirect - golang.org/x/sys v0.19.0 // indirect - golang.org/x/term v0.19.0 // indirect - golang.org/x/text v0.14.0 // indirect - golang.org/x/time v0.5.0 // indirect - golang.org/x/tools v0.17.0 // indirect - golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect - google.golang.org/appengine v1.6.8 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240311132316-a219d84964c2 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect - google.golang.org/grpc v1.63.2 // indirect - google.golang.org/protobuf v1.33.0 // indirect - gopkg.in/DataDog/dd-trace-go.v1 v1.62.0 // indirect + go.uber.org/zap v1.26.0 // indirect + golang.org/x/crypto v0.29.0 // indirect + golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 // indirect + golang.org/x/mod v0.18.0 // indirect + golang.org/x/oauth2 v0.24.0 // indirect + golang.org/x/sync v0.9.0 // indirect + golang.org/x/sys v0.27.0 // indirect + golang.org/x/term v0.26.0 // indirect + golang.org/x/text v0.20.0 // indirect + golang.org/x/time v0.8.0 // indirect + golang.org/x/tools v0.22.0 // indirect + golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 // indirect + google.golang.org/grpc v1.68.0 // indirect + google.golang.org/protobuf v1.35.2 // indirect + gopkg.in/DataDog/dd-trace-go.v1 v1.69.1 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 // indirect + k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect - sigs.k8s.io/yaml v1.3.0 // indirect + sigs.k8s.io/yaml v1.4.0 // indirect ) replace ( diff --git a/go.sum b/go.sum index 17ed95c36..c71eb1c10 100644 --- a/go.sum +++ b/go.sum @@ -1,37 +1,37 @@ -github.com/DataDog/appsec-internal-go v1.5.0 h1:8kS5zSx5T49uZ8dZTdT19QVAvC/B8ByyZdhQKYQWHno= -github.com/DataDog/appsec-internal-go v1.5.0/go.mod h1:pEp8gjfNLtEOmz+iZqC8bXhu0h4k7NUsW/qiQb34k1U= +github.com/DataDog/appsec-internal-go v1.8.0 h1:1Tfn3LEogntRqZtf88twSApOCAAO3V+NILYhuQIo4J4= +github.com/DataDog/appsec-internal-go v1.8.0/go.mod h1:wW0cRfWBo4C044jHGwYiyh5moQV2x0AhnwqMuiX7O/g= github.com/DataDog/datadog-agent/pkg/obfuscate v0.48.0 h1:bUMSNsw1iofWiju9yc1f+kBd33E3hMJtq9GuU602Iy8= github.com/DataDog/datadog-agent/pkg/obfuscate v0.48.0/go.mod h1:HzySONXnAgSmIQfL6gOv9hWprKJkx8CicuXuUbmgWfo= -github.com/DataDog/datadog-agent/pkg/remoteconfig/state v0.48.1 h1:5nE6N3JSs2IG3xzMthNFhXfOaXlrsdgqmJ73lndFf8c= -github.com/DataDog/datadog-agent/pkg/remoteconfig/state v0.48.1/go.mod h1:Vc+snp0Bey4MrrJyiV2tVxxJb6BmLomPvN1RgAvjGaQ= +github.com/DataDog/datadog-agent/pkg/remoteconfig/state v0.57.0 h1:LplNAmMgZvGU7kKA0+4c1xWOjz828xweW5TCi8Mw9Q0= +github.com/DataDog/datadog-agent/pkg/remoteconfig/state v0.57.0/go.mod h1:4Vo3SJ24uzfKHUHLoFa8t8o+LH+7TCQ7sPcZDtOpSP4= github.com/DataDog/datadog-go/v5 v5.3.0 h1:2q2qjFOb3RwAZNU+ez27ZVDwErJv5/VpbBPprz7Z+s8= github.com/DataDog/datadog-go/v5 v5.3.0/go.mod h1:XRDJk1pTc00gm+ZDiBKsjh7oOOtJfYfglVCmFb8C2+Q= -github.com/DataDog/go-libddwaf/v2 v2.3.2 h1:pdi9xjWW57IpOpTeOyPuNveEDFLmmInsHDeuZk3TY34= -github.com/DataDog/go-libddwaf/v2 v2.3.2/go.mod h1:gsCdoijYQfj8ce/T2bEDNPZFIYnmHluAgVDpuQOWMZE= -github.com/DataDog/go-tuf v1.0.2-0.5.2 h1:EeZr937eKAWPxJ26IykAdWA4A0jQXJgkhUjqEI/w7+I= -github.com/DataDog/go-tuf v1.0.2-0.5.2/go.mod h1:zBcq6f654iVqmkk8n2Cx81E1JnNTMOAx1UEO/wZR+P0= +github.com/DataDog/go-libddwaf/v3 v3.4.0 h1:NJ2W2vhYaOm1OWr1LJCbdgp7ezG/XLJcQKBmjFwhSuM= +github.com/DataDog/go-libddwaf/v3 v3.4.0/go.mod h1:n98d9nZ1gzenRSk53wz8l6d34ikxS+hs62A31Fqmyi4= +github.com/DataDog/go-tuf v1.1.0-0.5.2 h1:4CagiIekonLSfL8GMHRHcHudo1fQnxELS9g4tiAupQ4= +github.com/DataDog/go-tuf v1.1.0-0.5.2/go.mod h1:zBcq6f654iVqmkk8n2Cx81E1JnNTMOAx1UEO/wZR+P0= github.com/DataDog/gostackparse v0.7.0 h1:i7dLkXHvYzHV308hnkvVGDL3BR4FWl7IsXNPz/IGQh4= github.com/DataDog/gostackparse v0.7.0/go.mod h1:lTfqcJKqS9KnXQGnyQMCugq3u1FP6UZMfWR0aitKFMM= -github.com/DataDog/sketches-go v1.4.2 h1:gppNudE9d19cQ98RYABOetxIhpTCl4m7CnbRZjvVA/o= -github.com/DataDog/sketches-go v1.4.2/go.mod h1:xJIXldczJyyjnbDop7ZZcLxJdV3+7Kra7H1KMgpgkLk= +github.com/DataDog/sketches-go v1.4.5 h1:ki7VfeNz7IcNafq7yI/j5U/YCkO3LJiMDtXz9OMQbyE= +github.com/DataDog/sketches-go v1.4.5/go.mod h1:7Y8GN8Jf66DLyDhc94zuWA3uHEt/7ttt8jHOBWWrSOg= github.com/Microsoft/go-winio v0.5.0/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/apparentlymart/go-cidr v1.1.0 h1:2mAhrMoF+nhXqxTzSZMUzDHkLjmIHC+Zzn4tdgBZjnU= github.com/apparentlymart/go-cidr v1.1.0/go.mod h1:EBcsNrHc3zQeuaeCeCtQruQm+n9/YjEn/vI25Lg7Gwc= -github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= -github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= -github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/coredns/caddy v1.1.1 h1:2eYKZT7i6yxIfGP3qLJoJ7HAsDJqYB+X68g4NYjSrE0= -github.com/coredns/caddy v1.1.1/go.mod h1:A6ntJQlAWuQfFlsd9hvigKbo2WS0VUs2l1e2F+BawD4= -github.com/coredns/coredns v1.11.3 h1:8RjnpZc42db5th84/QJKH2i137ecJdzZK1HJwhetSPk= -github.com/coredns/coredns v1.11.3/go.mod h1:lqFkDsHjEUdY7LJ75Nib3lwqJGip6ewWOqNIf8OavIQ= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/coredns/caddy v1.1.2-0.20241029205200-8de985351a98 h1:c+Epklw9xk6BZ1OFBPWLA2PcL8QalKvl3if8CP9x8uw= +github.com/coredns/caddy v1.1.2-0.20241029205200-8de985351a98/go.mod h1:A6ntJQlAWuQfFlsd9hvigKbo2WS0VUs2l1e2F+BawD4= +github.com/coredns/coredns v1.12.0 h1:54YoUFOPewOgv4fybLISnbd5aSi7cQH4tFP2X24FVBc= +github.com/coredns/coredns v1.12.0/go.mod h1:sbfww1dS+4Uh0fxreDaqQTszOPc9qjVZ0CBuzLo304Y= github.com/coreos/etcd v3.3.13+incompatible h1:8F3hqu9fGYLBifCmRCJsicFqDx/D68Rt3q1JMazcgBQ= github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4= @@ -40,7 +40,7 @@ github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf h1:iW4rZ826su+pq github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -53,6 +53,8 @@ github.com/dnstap/golang-dnstap v0.4.0/go.mod h1:FqsSdH58NAmkAvKcpyxht7i4FoBjKu8 github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= +github.com/eapache/queue/v2 v2.0.0-20230407133247-75960ed334e4 h1:8EXxF+tCLqaVk8AOC29zl2mnhQjwyLxxOTuhUazWRsg= +github.com/eapache/queue/v2 v2.0.0-20230407133247-75960ed334e4/go.mod h1:I5sHm0Y0T1u5YjlyqC5GVArM7aNZRUYtTjmJ8mPJFds= github.com/ebitengine/purego v0.6.0-alpha.5 h1:EYID3JOAdmQ4SNZYJHu9V6IqOeRQDBYxqKAg9PyoHFY= github.com/ebitengine/purego v0.6.0-alpha.5/go.mod h1:ah1In8AOtksoNK6yk5z1HTJeUkC1Ez4Wk2idgGslMwQ= github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= @@ -61,25 +63,29 @@ github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCv github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/farsightsec/golang-framestream v0.3.0 h1:/spFQHucTle/ZIPkYqrfshQqPe2VQEzesH243TjIwqA= github.com/farsightsec/golang-framestream v0.3.0/go.mod h1:eNde4IQyEiA5br02AouhEHCu3p3UzrCdFR4LuQHklMI= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= -github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= -github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= -github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= -github.com/go-logr/zapr v1.2.3 h1:a9vnzlIBPQBBkeaR9IuMUfmVOrQlkoC4YfPoFkX3T7A= -github.com/go-logr/zapr v1.2.3/go.mod h1:eIauM6P8qSvTw5o2ez6UEAfGjQKrxQTl5EoK+Qa2oG4= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= +github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg= github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= -github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= +github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU= +github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= +github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= +github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= @@ -91,8 +97,6 @@ github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrU github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= @@ -100,25 +104,28 @@ github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYu github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/pprof v0.0.0-20230817174616-7a8ec2ada47b h1:h9U78+dx9a4BKdQkBBos92HalKpaGKHrp+3Uo6yTodo= -github.com/google/pprof v0.0.0-20230817174616-7a8ec2ada47b/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= +github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af h1:kmjWCqn2qkEml422C2Rrd27c3VGxi6a/6HNq8QmHRKM= +github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645 h1:MJG/KsmcqMwFAkh8mTnAwhyKoB+sTAnY4CACC110tbU= github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645/go.mod h1:6iZfnjpejD4L/4DwD7NryNaJyCQdzwWwH2MWhCA90Kw= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= -github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= -github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-secure-stdlib/parseutil v0.1.7 h1:UpiO20jno/eV1eVZcxqWnUohyKRe1g8FPV/xH1s/2qs= +github.com/hashicorp/go-secure-stdlib/parseutil v0.1.7/go.mod h1:QmrqtbKuxxSWTN3ETMPuB+VtEiBJ/A9XhoYGv8E1uD8= +github.com/hashicorp/go-secure-stdlib/strutil v0.1.1/go.mod h1:gKOamz3EwoIoJq7mlMIRBpVTAUn8qPCrEclOKKWhD3U= +github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 h1:kes8mmyCpxJsI7FTwtzRqEy9CdjCtrXrXGuOpxEA7Ts= +github.com/hashicorp/go-secure-stdlib/strutil v0.1.2/go.mod h1:Gou2R9+il93BqX25LAKCLuM+y9U2T4hlwvT1yprcna4= +github.com/hashicorp/go-sockaddr v1.0.2 h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0SyteCQc= +github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= @@ -128,9 +135,12 @@ github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8Hm github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= +github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= +github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= @@ -138,15 +148,26 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/lithammer/dedent v1.1.0 h1:VNzHMVCBNG1j0fh3OrsFRkVUwStdDArbgBWoPAffktY= github.com/lithammer/dedent v1.1.0/go.mod h1:jrXYCQtgg0nJiN+StA2KgR7w6CiQNv9Fd/Z9BP0jIOc= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/miekg/dns v1.1.31/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= -github.com/miekg/dns v1.1.58 h1:ca2Hdkz+cDg/7eNF6V56jjzuZ4aCAE+DbVkILdQWG/4= -github.com/miekg/dns v1.1.58/go.mod h1:Ypv+3b/KadlvW9vJfXOTf300O4UqaHFzFCuHz+rPkBY= +github.com/miekg/dns v1.1.62 h1:cN8OuEF1/x5Rq6Np+h1epln8OiyPWV+lROx9LxcGgIQ= +github.com/miekg/dns v1.1.62/go.mod h1:mvDlcItzm+br7MToIKqkglaGhlFMHJ9DTNNWONWXbNQ= +github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= +github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -161,150 +182,143 @@ github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= -github.com/onsi/ginkgo/v2 v2.13.0 h1:0jY9lJquiL8fcf3M4LAXN5aMlS/b2BV86HFFPCPMgE4= -github.com/onsi/ginkgo/v2 v2.13.0/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o= +github.com/onsi/ginkgo/v2 v2.19.0 h1:9Cnnf7UHo57Hy3k6/m5k3dRfGTMXGvxhHFvkDTCTpvA= +github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= -github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= +github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk= +github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0= github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492 h1:lM6RxxfUMrYL/f8bWEUqdXrANWtrL7Nndbm9iFN0DlU= github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/openzipkin-contrib/zipkin-go-opentracing v0.5.0 h1:uhcF5Jd7rP9DVEL10Siffyepr6SvlKbUsjH5JpNCRi8= github.com/openzipkin-contrib/zipkin-go-opentracing v0.5.0/go.mod h1:+oCZ5GXXr7KPI/DNOQORPTq5AWHfALJj9c72b0+YsEY= -github.com/openzipkin/zipkin-go v0.4.2 h1:zjqfqHjUpPmB3c1GlCvvgsM1G4LkvqQbBDueDOCg/jA= -github.com/openzipkin/zipkin-go v0.4.2/go.mod h1:ZeVkFjuuBiSy13y8vpSDCjMi9GoI3hPpCJSBx/EYFhY= +github.com/openzipkin/zipkin-go v0.4.3 h1:9EGwpqkgnwdEIJ+Od7QVSEIH+ocmm5nPat0G7sjsSdg= +github.com/openzipkin/zipkin-go v0.4.3/go.mod h1:M9wCJZFWCo2RiY+o1eBCEMe0Dp2S5LDHcMZmk3RmK7c= github.com/outcaste-io/ristretto v0.2.3 h1:AK4zt/fJ76kjlYObOeNwh4T3asEuaCmp26pOvUOL9w0= github.com/outcaste-io/ristretto v0.2.3/go.mod h1:W8HywhmtlopSB1jeMg3JtdIhf+DYkLAr0VN/s4+MHac= -github.com/philhofer/fwd v1.1.2 h1:bnDivRJ1EWPjUIRXV5KfORO897HTbpFAQddBdE8t7Gw= -github.com/philhofer/fwd v1.1.2/go.mod h1:qkPdfjR2SIEbspLqpe1tO4n5yICnr2DY7mqEx2tUTP0= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/philhofer/fwd v1.1.3-0.20240612014219-fbbf4953d986 h1:jYi87L8j62qkXzaYHAQAhEapgukhenIMZRBKTNRLHJ4= +github.com/philhofer/fwd v1.1.3-0.20240612014219-fbbf4953d986/go.mod h1:RqIHx9QI14HlwKwm98g9Re5prTQ6LdeRQn+gXJFxsJM= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU= -github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k= -github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos= -github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8= -github.com/prometheus/common v0.53.0 h1:U2pL9w9nmJwJDa4qqLQ3ZaePJ6ZTwt7cMD3AG3+aLCE= -github.com/prometheus/common v0.53.0/go.mod h1:BrxBKv3FWBIGXw89Mg1AeBq7FSyRzXWI3l3e7W3RN5U= -github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= -github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= -github.com/quic-go/quic-go v0.42.0 h1:uSfdap0eveIl8KXnipv9K7nlwZ5IqLlYOpJ58u5utpM= -github.com/quic-go/quic-go v0.42.0/go.mod h1:132kz4kL3F9vxhW3CtQJLDVwcFe5wdWeJXXijhsO57M= -github.com/richardartoul/molecule v1.0.1-0.20221107223329-32cfee06a052 h1:Qp27Idfgi6ACvFQat5+VJvlYToylpM/hcyLBI3WaKPA= -github.com/richardartoul/molecule v1.0.1-0.20221107223329-32cfee06a052/go.mod h1:uvX/8buq8uVeiZiFht+0lqSLBHF+uGV8BrTv8W/SIwk= +github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g= +github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U= +github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y= +github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.60.1 h1:FUas6GcOw66yB/73KC+BOZoFJmbo/1pojoILArPAaSc= +github.com/prometheus/common v0.60.1/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= +github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= +github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= +github.com/quic-go/quic-go v0.48.1 h1:y/8xmfWI9qmGTc+lBr4jKRUWLGSlSigv847ULJ4hYXA= +github.com/quic-go/quic-go v0.48.1/go.mod h1:yBgs3rWBOADpga7F+jJsb6Ybg1LSYiQvwWlLX+/6HMs= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= +github.com/richardartoul/molecule v1.0.1-0.20240531184615-7ca0df43c0b3 h1:4+LEVOB87y175cLJC/mbsgKmoDOjrBldtXvioEy96WY= +github.com/richardartoul/molecule v1.0.1-0.20240531184615-7ca0df43c0b3/go.mod h1:vl5+MqJ1nBINuSsUI2mGgH79UweUT/B5Fy8857PqyyI= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk= +github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= github.com/secure-systems-lab/go-securesystemslib v0.7.0 h1:OwvJ5jQf9LnIAS83waAjPbcMsODrTQUpJ02eNLUoxBg= github.com/secure-systems-lab/go-securesystemslib v0.7.0/go.mod h1:/2gYnlnHVQ6xeGtfIqFy7Do03K4cdCY0A/GlJLDKLHI= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= -github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= +github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= +github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/objx v0.5.1 h1:4VhoImhV/Bm0ToFkXFi8hXNXwpDRZ/ynw3amt82mzq0= -github.com/stretchr/objx v0.5.1/go.mod h1:/iHQpkQwBD6DLUmQ4pE+s1TXdob1mORJ4/UFdrifcy0= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/tinylib/msgp v1.1.8 h1:FCXC1xanKO4I8plpHGH2P7koL/RzZs12l/+r7vakfm0= -github.com/tinylib/msgp v1.1.8/go.mod h1:qkpG+2ldGg4xRFmx+jfTvZPxfGFhi64BcnL9vkCm/Tw= -github.com/vishvananda/netlink v1.1.0 h1:1iyaYNBLmP6L0220aDnYQpo1QEV4t4hJ+xEEhhJH8j0= -github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= -github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/tinylib/msgp v1.2.1 h1:6ypy2qcCznxpP4hpORzhtXyTqrBs7cfM9MCCWY8zsmU= +github.com/tinylib/msgp v1.2.1/go.mod h1:2vIGs3lcUo8izAATNobrCHevYZC/LMsJtw4JPiYPHro= +github.com/vishvananda/netlink v1.3.0 h1:X7l42GfcV4S6E4vHTsw48qbrV+9PVojNfIhZcwQdrZk= +github.com/vishvananda/netlink v1.3.0/go.mod h1:i6NetklAujEcC6fK0JPjT8qSwWyO0HLn4UKG+hGqeJs= github.com/vishvananda/netns v0.0.4 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1YX8= github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -go.etcd.io/etcd/api/v3 v3.5.12 h1:W4sw5ZoU2Juc9gBWuLk5U6fHfNVyY1WC5g9uiXZio/c= -go.etcd.io/etcd/api/v3 v3.5.12/go.mod h1:Ot+o0SWSyT6uHhA56al1oCED0JImsRiU9Dc26+C2a+4= -go.etcd.io/etcd/client/pkg/v3 v3.5.12 h1:EYDL6pWwyOsylrQyLp2w+HkQ46ATiOvoEdMarindU2A= -go.etcd.io/etcd/client/pkg/v3 v3.5.12/go.mod h1:seTzl2d9APP8R5Y2hFL3NVlD6qC/dOT+3kvrqPyTas4= -go.etcd.io/etcd/client/v2 v2.305.9 h1:YZ2OLi0OvR0H75AcgSUajjd5uqKDKocQUqROTG11jIo= -go.etcd.io/etcd/client/v2 v2.305.9/go.mod h1:0NBdNx9wbxtEQLwAQtrDHwx58m02vXpDcgSYI2seohQ= -go.etcd.io/etcd/client/v3 v3.5.12 h1:v5lCPXn1pf1Uu3M4laUE2hp/geOTc5uPcYYsNe1lDxg= -go.etcd.io/etcd/client/v3 v3.5.12/go.mod h1:tSbBCakoWmmddL+BKVAJHa9km+O/E+bumDe9mSbPiqw= -go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.etcd.io/etcd/api/v3 v3.5.17 h1:cQB8eb8bxwuxOilBpMJAEo8fAONyrdXTHUNcMd8yT1w= +go.etcd.io/etcd/api/v3 v3.5.17/go.mod h1:d1hvkRuXkts6PmaYk2Vrgqbv7H4ADfAKhyJqHNLJCB4= +go.etcd.io/etcd/client/pkg/v3 v3.5.17 h1:XxnDXAWq2pnxqx76ljWwiQ9jylbpC4rvkAeRVOUKKVw= +go.etcd.io/etcd/client/pkg/v3 v3.5.17/go.mod h1:4DqK1TKacp/86nJk4FLQqo6Mn2vvQFBmruW3pP14H/w= +go.etcd.io/etcd/client/v2 v2.305.17 h1:ajFukQfI//xY5VuSeuUw4TJ4WnNR2kAFfV/P0pDdPMs= +go.etcd.io/etcd/client/v2 v2.305.17/go.mod h1:EttKgEgvwikmXN+b7pkEWxDZr6sEaYsqCiS3k4fa/Vg= +go.etcd.io/etcd/client/v3 v3.5.17 h1:o48sINNeWz5+pjy/Z0+HKpj/xSnBkuVhVvXkjEXbqZY= +go.etcd.io/etcd/client/v3 v3.5.17/go.mod h1:j2d4eXTHWkT2ClBgnnEPm/Wuu7jsqku41v9DZ3OtjQo= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= -go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= +go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs= +go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU= go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= -go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.19.0 h1:mZQZefskPPCMIBCSEH0v2/iUqqLrYtaeqwD6FUGUnFE= -go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= +go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= +go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= -golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= -golang.org/x/exp v0.0.0-20230321023759-10a507213a29 h1:ooxPy7fPvB4kwsA2h+iBNHkAbp/4JxTSwCmvdjEYmug= -golang.org/x/exp v0.0.0-20230321023759-10a507213a29/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ= +golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg= +golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 h1:vr/HnozRka3pE4EsMEg1lgkXJkTFJCVUX+S/ZT6wYzM= +golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= -golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0= +golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= -golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= -golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= -golang.org/x/oauth2 v0.18.0 h1:09qnuIAgzdx1XplqJvW6CQqMCtGZykZWcXzPMPUusvI= -golang.org/x/oauth2 v0.18.0/go.mod h1:Wf7knwG0MPoWIMMBgFlEaSUDaKskp0dCfrlJRJXbBi8= +golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo= +golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM= +golang.org/x/oauth2 v0.24.0 h1:KTBBxWqUa0ykRPLtV69rRto9TLXcqYkeswu48x/gvNE= +golang.org/x/oauth2 v0.24.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= -golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ= +golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -317,70 +331,52 @@ golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220627191245-f75cf1eec38b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= -golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= +golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= -golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q= -golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk= +golang.org/x/term v0.26.0 h1:WEQa6V3Gja/BhNxg540hBip/kkaYtRg3cxg4oXSw4AU= +golang.org/x/term v0.26.0/go.mod h1:Si5m1o57C5nBNQo5z1iq+XDijt21BDBDp2bK0QI8e3E= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= -golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= +golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= +golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg= +golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ= -golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc= -golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= +golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA= +golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= -golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= -google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= -google.golang.org/genproto/googleapis/api v0.0.0-20240311132316-a219d84964c2 h1:rIo7ocm2roD9DcFIX67Ym8icoGCKSARAiPljFhh5suQ= -google.golang.org/genproto/googleapis/api v0.0.0-20240311132316-a219d84964c2/go.mod h1:O1cOfN1Cy6QEYr7VxtjOyP5AdAuR0aJ/MYZaaof623Y= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 h1:NnYq6UN9ReLM9/Y01KWNOWyI5xQ9kbIms5GGJVwS/Yc= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= -google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= -google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= +golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU= +golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= +google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28 h1:M0KvPgPmDZHPlbRbaNU1APr28TvwvvdUPlSv7PUvy8g= +google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:dguCy7UOdZhTvLzDyt15+rOrawrpM4q7DD9dQ1P11P4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 h1:XVhgTWWV3kGQlwJHR3upFWZeTsei6Oks1apkZSeonIE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= +google.golang.org/grpc v1.68.0 h1:aHQeeJbo8zAkAa3pRzrVjZlbz6uSfeOXlJNQM0RAbz0= +google.golang.org/grpc v1.68.0/go.mod h1:fmSPC5AsjSBCK54MyHRx48kpOti1/jRfOlwEWywNjWA= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= -google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= -gopkg.in/DataDog/dd-trace-go.v1 v1.62.0 h1:jeZxE4ZlfAc+R0zO5TEmJBwOLet3NThsOfYJeSQg1x0= -gopkg.in/DataDog/dd-trace-go.v1 v1.62.0/go.mod h1:YTvYkk3PTsfw0OWrRFxV/IQ5Gy4nZ5TRvxTAP3JcIzs= +google.golang.org/protobuf v1.35.2 h1:8Ar7bF+apOIoThw1EdZl0p1oWvMqTHmpA2fRTyZO8io= +google.golang.org/protobuf v1.35.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +gopkg.in/DataDog/dd-trace-go.v1 v1.69.1 h1:grTElrPaCfxUsrJjyPLHlVPbmlKVzWMxVdcBrGZSzEk= +gopkg.in/DataDog/dd-trace-go.v1 v1.69.1/go.mod h1:U9AOeBHNAL95JXcd/SPf4a7O5GNeF/yD13sJtli/yaU= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= @@ -395,11 +391,8 @@ gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -honnef.co/go/gotraceui v0.2.0 h1:dmNsfQ9Vl3GwbiVD7Z8d/osC6WtGGrasyrC2suc4ZIQ= -honnef.co/go/gotraceui v0.2.0/go.mod h1:qHo4/W75cA3bX0QQoSvDjbJa4R8mAyyFjbWAj63XElc= k8s.io/api v0.28.14 h1:7DXeMrQq+BJI6H7WtSMC8l1gM4QZWtWN65UbN+qZ9Uc= k8s.io/api v0.28.14/go.mod h1:ROk/G6/7IZf14AL1WkpZdq//5khE1EtLNxkcEpSXNFM= k8s.io/apimachinery v0.28.14 h1:n2l8jNNOmUUDXpa8ljHCEUSeIChby1BKyqoL0AtpmGw= @@ -408,17 +401,37 @@ k8s.io/client-go v0.28.14 h1:wfPRgz07MvLMxcHfN8kAc4Qcwduc4My25A3CBU7OqBQ= k8s.io/client-go v0.28.14/go.mod h1:HGfdb7BqkX4hRpNyVLHNQKWDU03W6a38LfIHD7QGJpI= k8s.io/component-base v0.28.14 h1:sJowHyRY166hBfBQ4cOKjkSvUo4bUdeuePtEOQfSNRY= k8s.io/component-base v0.28.14/go.mod h1:DgYlfHNvP1yeBb4L+UIzMsWNtOl0yqTk+4dGGc79H0w= -k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw= -k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= -k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 h1:aVUu9fTY98ivBPKR9Y5w/AuzbMm96cd3YHRTU83I780= -k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00/go.mod h1:AsvuZPBlUDVuCdzJ87iajxtXuR9oktsTctW/R9wwouA= -k8s.io/kubernetes v1.28.14 h1:Q0qoY+dKjqAhSrVSAebEMVUK5zfrg9Sz3I/4aHnOCaQ= -k8s.io/kubernetes v1.28.14/go.mod h1:chlmcCDBnOA/y+572cw8dO0Rci1wiA8bm5+zhPdFLCk= -k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI= -k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= +k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= +k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag= +k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98= +k8s.io/kubernetes v1.31.3 h1:oqb7HdfnTelrGlZ6ziNugvQ/L/aJWR704114EAhUn9Q= +k8s.io/kubernetes v1.31.3/go.mod h1:9xmT2buyTYj8TRKwRae7FcuY8k5+xlxv7VivvO0KKfs= +k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A= +k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +lukechampine.com/uint128 v1.3.0 h1:cDdUVfRwDUDovz610ABgFD17nXD4/uDgVHl2sC3+sbo= +lukechampine.com/uint128 v1.3.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= +modernc.org/cc/v3 v3.41.0 h1:QoR1Sn3YWlmA1T4vLaKZfawdVtSiGx8H+cEojbC7v1Q= +modernc.org/cc/v3 v3.41.0/go.mod h1:Ni4zjJYJ04CDOhG7dn640WGfwBzfE0ecX8TyMB0Fv0Y= +modernc.org/ccgo/v3 v3.16.15 h1:KbDR3ZAVU+wiLyMESPtbtE/Add4elztFyfsWoNTgxS0= +modernc.org/ccgo/v3 v3.16.15/go.mod h1:yT7B+/E2m43tmMOT51GMoM98/MtHIcQQSleGnddkUNI= +modernc.org/libc v1.37.6 h1:orZH3c5wmhIQFTXF+Nt+eeauyd+ZIt2BX6ARe+kD+aw= +modernc.org/libc v1.37.6/go.mod h1:YAXkAZ8ktnkCKaN9sw/UDeUVkGYJ/YquGO4FTi5nmHE= +modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4= +modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo= +modernc.org/memory v1.7.2 h1:Klh90S215mmH8c9gO98QxQFsY+W451E8AnzjoE2ee1E= +modernc.org/memory v1.7.2/go.mod h1:NO4NVCQy0N7ln+T9ngWqOQfi7ley4vpwvARR+Hjw95E= +modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4= +modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= +modernc.org/sqlite v1.28.0 h1:Zx+LyDDmXczNnEQdvPuEfcFVA2ZPyaD7UCZDjef3BHQ= +modernc.org/sqlite v1.28.0/go.mod h1:Qxpazz0zH8Z1xCFyi5GSL3FzbtZ3fvbjmywNogldEW0= +modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA= +modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0= +modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= +modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= -sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= -sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= +sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= +sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= diff --git a/vendor/github.com/DataDog/appsec-internal-go/appsec/config.go b/vendor/github.com/DataDog/appsec-internal-go/appsec/config.go index d6723703e..3cfed5bcc 100644 --- a/vendor/github.com/DataDog/appsec-internal-go/appsec/config.go +++ b/vendor/github.com/DataDog/appsec-internal-go/appsec/config.go @@ -32,6 +32,8 @@ const ( EnvTraceRateLimit = "DD_APPSEC_TRACE_RATE_LIMIT" // EnvRules is the env var used to provide a path to a local security rule file EnvRules = "DD_APPSEC_RULES" + // EnvRASPEnabled is the env var used to enable/disable RASP functionalities for ASM + EnvRASPEnabled = "DD_APPSEC_RASP_ENABLED" ) // Configuration constants and default values @@ -39,9 +41,9 @@ const ( // DefaultAPISecSampleRate is the default rate at which API Security schemas are extracted from requests DefaultAPISecSampleRate = .1 // DefaultObfuscatorKeyRegex is the default regexp used to obfuscate keys - DefaultObfuscatorKeyRegex = `(?i)(?:p(?:ass)?w(?:or)?d|pass(?:_?phrase)?|secret|(?:api_?|private_?|public_?)key)|token|consumer_?(?:id|key|secret)|sign(?:ed|ature)|bearer|authorization` + DefaultObfuscatorKeyRegex = `(?i)pass|pw(?:or)?d|secret|(?:api|private|public|access)[_-]?key|token|consumer[_-]?(?:id|key|secret)|sign(?:ed|ature)|bearer|authorization|jsessionid|phpsessid|asp\.net[_-]sessionid|sid|jwt` // DefaultObfuscatorValueRegex is the default regexp used to obfuscate values - DefaultObfuscatorValueRegex = `(?i)(?:p(?:ass)?w(?:or)?d|pass(?:_?phrase)?|secret|(?:api_?|private_?|public_?|access_?|secret_?)key(?:_?id)?|token|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)(?:\s*=[^;]|"\s*:\s*"[^"]+")|bearer\s+[a-z0-9\._\-]+|token:[a-z0-9]{13}|gh[opsu]_[0-9a-zA-Z]{36}|ey[I-L][\w=-]+\.ey[I-L][\w=-]+(?:\.[\w.+\/=-]+)?|[\-]{5}BEGIN[a-z\s]+PRIVATE\sKEY[\-]{5}[^\-]+[\-]{5}END[a-z\s]+PRIVATE\sKEY|ssh-rsa\s*[a-z0-9\/\.+]{100,}` + DefaultObfuscatorValueRegex = `(?i)(?:p(?:ass)?w(?:or)?d|pass(?:[_-]?phrase)?|secret(?:[_-]?key)?|(?:(?:api|private|public|access)[_-]?)key(?:[_-]?id)?|(?:(?:auth|access|id|refresh)[_-]?)?token|consumer[_-]?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?|jsessionid|phpsessid|asp\.net(?:[_-]|-)sessionid|sid|jwt)(?:\s*=[^;]|"\s*:\s*"[^"]+")|bearer\s+[a-z0-9\._\-]+|token:[a-z0-9]{13}|gh[opsu]_[0-9a-zA-Z]{36}|ey[I-L][\w=-]+\.ey[I-L][\w=-]+(?:\.[\w.+\/=-]+)?|[\-]{5}BEGIN[a-z\s]+PRIVATE\sKEY[\-]{5}[^\-]+[\-]{5}END[a-z\s]+PRIVATE\sKEY|ssh-rsa\s*[a-z0-9\/\.+]{100,}` // DefaultWAFTimeout is the default time limit past which a WAF run will timeout DefaultWAFTimeout = time.Millisecond // DefaultTraceRate is the default limit (trace/sec) past which ASM traces are sampled out @@ -65,24 +67,10 @@ type ObfuscatorConfig struct { // NewAPISecConfig creates and returns a new API Security configuration by reading the env func NewAPISecConfig() APISecConfig { return APISecConfig{ - Enabled: apiSecurityEnabled(), + Enabled: boolEnv(EnvAPISecEnabled, true), SampleRate: readAPISecuritySampleRate(), } } - -func apiSecurityEnabled() bool { - enabled := true - str, set := os.LookupEnv(EnvAPISecEnabled) - if set { - var err error - enabled, err = strconv.ParseBool(str) - if err != nil { - logEnvVarParsingError(EnvAPISecEnabled, str, err, enabled) - } - } - return enabled -} - func readAPISecuritySampleRate() float64 { value := os.Getenv(EnvAPISecSampleRate) rate, err := strconv.ParseFloat(value, 64) @@ -99,6 +87,12 @@ func readAPISecuritySampleRate() float64 { return rate } +// RASPEnabled returns true if RASP functionalities are enabled through the env, or if DD_APPSEC_RASP_ENABLED +// is not set +func RASPEnabled() bool { + return boolEnv(EnvRASPEnabled, true) +} + // NewObfuscatorConfig creates and returns a new WAF obfuscator configuration by reading the env func NewObfuscatorConfig() ObfuscatorConfig { keyRE := readObfuscatorConfigRegexp(EnvObfuscatorKey, DefaultObfuscatorKeyRegex) @@ -194,3 +188,16 @@ func logEnvVarParsingError(name, value string, err error, defaultValue any) { func logUnexpectedEnvVarValue(name string, value any, reason string, defaultValue any) { log.Debug("appsec: unexpected configuration value of %s=%v: %s. Using default value %v.", name, value, reason, defaultValue) } + +func boolEnv(key string, def bool) bool { + strVal, ok := os.LookupEnv(key) + if !ok { + return def + } + v, err := strconv.ParseBool(strVal) + if err != nil { + logEnvVarParsingError(key, strVal, err, def) + return def + } + return v +} diff --git a/vendor/github.com/DataDog/appsec-internal-go/appsec/embed.go b/vendor/github.com/DataDog/appsec-internal-go/appsec/embed.go index 9617fb3d5..9c2888498 100644 --- a/vendor/github.com/DataDog/appsec-internal-go/appsec/embed.go +++ b/vendor/github.com/DataDog/appsec-internal-go/appsec/embed.go @@ -7,14 +7,8 @@ package appsec import _ "embed" // Blank import comment for golint compliance -// StaticRecommendedRules holds the recommended AppSec security rules (v1.11.0) -// Source: https://github.com/DataDog/appsec-event-rules/blob/1.11.0/build/recommended.json +// StaticRecommendedRules holds the recommended AppSec security rules (v1.13.0) +// Source: https://github.com/DataDog/appsec-event-rules/blob/1.13.0/build/recommended.json // //go:embed rules.json var StaticRecommendedRules string - -// StaticProcessors holds the default processors and scanners used for API Security -// Not part of the recommended security rules -// -//go:embed processors.json -var StaticProcessors string diff --git a/vendor/github.com/DataDog/appsec-internal-go/appsec/processors.json b/vendor/github.com/DataDog/appsec-internal-go/appsec/processors.json deleted file mode 100644 index 968c53ddb..000000000 --- a/vendor/github.com/DataDog/appsec-internal-go/appsec/processors.json +++ /dev/null @@ -1,208 +0,0 @@ -{ - "processors": [ - { - "id": "processor-001", - "generator": "extract_schema", - "conditions": [ - { - "operator": "equals", - "parameters": { - "inputs": [ - { - "address": "waf.context.processor", - "key_path": [ - "extract-schema" - ] - } - ], - "type": "boolean", - "value": true - } - } - ], - "parameters": { - "mappings": [ - { - "inputs": [ - { - "address": "server.request.body" - } - ], - "output": "_dd.appsec.s.req.body" - }, - { - "inputs": [ - { - "address": "server.request.headers.no_cookies" - } - ], - "output": "_dd.appsec.s.req.headers" - }, - { - "inputs": [ - { - "address": "server.request.query" - } - ], - "output": "_dd.appsec.s.req.query" - }, - { - "inputs": [ - { - "address": "server.request.path_params" - } - ], - "output": "_dd.appsec.s.req.params" - }, - { - "inputs": [ - { - "address": "server.request.cookies" - } - ], - "output": "_dd.appsec.s.req.cookies" - }, - { - "inputs": [ - { - "address": "server.response.headers.no_cookies" - } - ], - "output": "_dd.appsec.s.res.headers" - }, - { - "inputs": [ - { - "address": "server.response.body" - } - ], - "output": "_dd.appsec.s.res.body" - } - ], - "scanners": [ - { - "tags": { - "category": "pii" - } - } - ] - }, - "evaluate": false, - "output": true - } - ], - "scanners": [ - { - "id": "d962f7ddb3f55041e39195a60ff79d4814a7c331", - "name": "US Passport Scanner", - "key": { - "operator": "match_regex", - "parameters": { - "regex": "passport", - "options": { - "case_sensitive": false, - "min_length": 8 - } - } - }, - "value": { - "operator": "match_regex", - "parameters": { - "regex": "\\b[0-9A-Z]{9}\\b|\\b[0-9]{6}[A-Z][0-9]{2}\\b", - "options": { - "case_sensitive": false, - "min_length": 8 - } - } - }, - "tags": { - "type": "passport_number", - "category": "pii" - } - }, - { - "id": "ac6d683cbac77f6e399a14990793dd8fd0fca333", - "name": "US Vehicle Identification Number Scanner", - "key": { - "operator": "match_regex", - "parameters": { - "regex": "vehicle[_\\s-]*identification[_\\s-]*number|vin", - "options": { - "case_sensitive": false, - "min_length": 3 - } - } - }, - "value": { - "operator": "match_regex", - "parameters": { - "regex": "\\b[A-HJ-NPR-Z0-9]{17}\\b", - "options": { - "case_sensitive": false, - "min_length": 17 - } - } - }, - "tags": { - "type": "vin", - "category": "pii" - } - }, - { - "id": "de0899e0cbaaa812bb624cf04c912071012f616d", - "name": "UK National Insurance Number Scanner", - "key": { - "operator": "match_regex", - "parameters": { - "regex": "national[\\s_]?(?:insurance(?:\\s+number)?)?|NIN|NI[\\s_]?number|insurance[\\s_]?number", - "options": { - "case_sensitive": false, - "min_length": 3 - } - } - }, - "value": { - "operator": "match_regex", - "parameters": { - "regex": "\\b[A-Z]{2}\\d{6}[A-Z]?\\b", - "options": { - "case_sensitive": false, - "min_length": 8 - } - } - }, - "tags": { - "type": "uk_nin", - "category": "pii" - } - }, - { - "id": "450239afc250a19799b6c03dc0e16fd6a4b2a1af", - "name": "Canadian Social Insurance Number Scanner", - "key": { - "operator": "match_regex", - "parameters": { - "regex": "social[\\s_]?(?:insurance(?:\\s+number)?)?|SIN|Canadian[\\s_]?(?:social[\\s_]?(?:insurance)?|insurance[\\s_]?number)?", - "options": { - "case_sensitive": false, - "min_length": 3 - } - } - }, - "value": { - "operator": "match_regex", - "parameters": { - "regex": "\\b\\d{3}-\\d{3}-\\d{3}\\b", - "options": { - "case_sensitive": false, - "min_length": 11 - } - } - }, - "tags": { - "type": "canadian_sin", - "category": "pii" - } - } - ] -} \ No newline at end of file diff --git a/vendor/github.com/DataDog/appsec-internal-go/appsec/rules.go b/vendor/github.com/DataDog/appsec-internal-go/appsec/rules.go index d2d672a84..29a46bf2e 100644 --- a/vendor/github.com/DataDog/appsec-internal-go/appsec/rules.go +++ b/vendor/github.com/DataDog/appsec-internal-go/appsec/rules.go @@ -18,16 +18,9 @@ func DefaultRuleset() ([]byte, error) { // DefaultRulesetMap returns the unmarshaled default recommended security rules for AppSec func DefaultRulesetMap() (map[string]any, error) { var rules map[string]any - var processors map[string]any if err := json.Unmarshal([]byte(StaticRecommendedRules), &rules); err != nil { return nil, err } - if err := json.Unmarshal([]byte(StaticProcessors), &processors); err != nil { - return nil, err - } - for k, v := range processors { - rules[k] = v - } return rules, nil } diff --git a/vendor/github.com/DataDog/appsec-internal-go/appsec/rules.json b/vendor/github.com/DataDog/appsec-internal-go/appsec/rules.json index 7912743b4..d05b1e629 100644 --- a/vendor/github.com/DataDog/appsec-internal-go/appsec/rules.json +++ b/vendor/github.com/DataDog/appsec-internal-go/appsec/rules.json @@ -1,7 +1,7 @@ { "version": "2.2", "metadata": { - "rules_version": "1.11.0" + "rules_version": "1.13.1" }, "rules": [ { @@ -1921,7 +1921,6 @@ "$ifs", "$oldpwd", "$ostype", - "$path", "$pwd", "dev/fd/", "dev/null", @@ -5849,7 +5848,8 @@ "/website.php", "/stats.php", "/assets/plugins/mp3_id/mp3_id.php", - "/siteminderagent/forms/smpwservices.fcc" + "/siteminderagent/forms/smpwservices.fcc", + "/eval-stdin.php" ] } } @@ -6236,6 +6236,200 @@ ], "transformers": [] }, + { + "id": "rasp-930-100", + "name": "Local file inclusion exploit", + "tags": { + "type": "lfi", + "category": "vulnerability_trigger", + "cwe": "22", + "capec": "1000/255/153/126", + "confidence": "0", + "module": "rasp" + }, + "conditions": [ + { + "parameters": { + "resource": [ + { + "address": "server.io.fs.file" + } + ], + "params": [ + { + "address": "server.request.query" + }, + { + "address": "server.request.body" + }, + { + "address": "server.request.path_params" + }, + { + "address": "grpc.server.request.message" + }, + { + "address": "graphql.server.all_resolvers" + }, + { + "address": "graphql.server.resolver" + } + ] + }, + "operator": "lfi_detector" + } + ], + "transformers": [], + "on_match": [ + "stack_trace" + ] + }, + { + "id": "rasp-932-100", + "name": "Shell injection exploit", + "tags": { + "type": "command_injection", + "category": "vulnerability_trigger", + "cwe": "77", + "capec": "1000/152/248/88", + "confidence": "0", + "module": "rasp" + }, + "conditions": [ + { + "parameters": { + "resource": [ + { + "address": "server.sys.shell.cmd" + } + ], + "params": [ + { + "address": "server.request.query" + }, + { + "address": "server.request.body" + }, + { + "address": "server.request.path_params" + }, + { + "address": "grpc.server.request.message" + }, + { + "address": "graphql.server.all_resolvers" + }, + { + "address": "graphql.server.resolver" + } + ] + }, + "operator": "shi_detector" + } + ], + "transformers": [], + "on_match": [ + "stack_trace" + ] + }, + { + "id": "rasp-934-100", + "name": "Server-side request forgery exploit", + "tags": { + "type": "ssrf", + "category": "vulnerability_trigger", + "cwe": "918", + "capec": "1000/225/115/664", + "confidence": "0", + "module": "rasp" + }, + "conditions": [ + { + "parameters": { + "resource": [ + { + "address": "server.io.net.url" + } + ], + "params": [ + { + "address": "server.request.query" + }, + { + "address": "server.request.body" + }, + { + "address": "server.request.path_params" + }, + { + "address": "grpc.server.request.message" + }, + { + "address": "graphql.server.all_resolvers" + }, + { + "address": "graphql.server.resolver" + } + ] + }, + "operator": "ssrf_detector" + } + ], + "transformers": [], + "on_match": [ + "stack_trace" + ] + }, + { + "id": "rasp-942-100", + "name": "SQL injection exploit", + "tags": { + "type": "sql_injection", + "category": "vulnerability_trigger", + "cwe": "89", + "capec": "1000/152/248/66", + "confidence": "0", + "module": "rasp" + }, + "conditions": [ + { + "parameters": { + "resource": [ + { + "address": "server.db.statement" + } + ], + "params": [ + { + "address": "server.request.query" + }, + { + "address": "server.request.body" + }, + { + "address": "server.request.path_params" + }, + { + "address": "graphql.server.all_resolvers" + }, + { + "address": "graphql.server.resolver" + } + ], + "db_type": [ + { + "address": "server.db.system" + } + ] + }, + "operator": "sqli_detector" + } + ], + "transformers": [], + "on_match": [ + "stack_trace" + ] + }, { "id": "sqr-000-001", "name": "SSRF: Try to access the credential manager of the main cloud services", @@ -8239,6 +8433,57 @@ } ], "processors": [ + { + "id": "http-endpoint-fingerprint", + "generator": "http_endpoint_fingerprint", + "conditions": [ + { + "operator": "exists", + "parameters": { + "inputs": [ + { + "address": "waf.context.event" + }, + { + "address": "server.business_logic.users.login.failure" + }, + { + "address": "server.business_logic.users.login.success" + } + ] + } + } + ], + "parameters": { + "mappings": [ + { + "method": [ + { + "address": "server.request.method" + } + ], + "uri_raw": [ + { + "address": "server.request.uri.raw" + } + ], + "body": [ + { + "address": "server.request.body" + } + ], + "query": [ + { + "address": "server.request.query" + } + ], + "output": "_dd.appsec.fp.http.endpoint" + } + ] + }, + "evaluate": false, + "output": true + }, { "id": "extract-content", "generator": "extract_schema", @@ -8388,9 +8633,155 @@ }, "evaluate": false, "output": true + }, + { + "id": "http-header-fingerprint", + "generator": "http_header_fingerprint", + "conditions": [ + { + "operator": "exists", + "parameters": { + "inputs": [ + { + "address": "waf.context.event" + }, + { + "address": "server.business_logic.users.login.failure" + }, + { + "address": "server.business_logic.users.login.success" + } + ] + } + } + ], + "parameters": { + "mappings": [ + { + "headers": [ + { + "address": "server.request.headers.no_cookies" + } + ], + "output": "_dd.appsec.fp.http.header" + } + ] + }, + "evaluate": false, + "output": true + }, + { + "id": "http-network-fingerprint", + "generator": "http_network_fingerprint", + "conditions": [ + { + "operator": "exists", + "parameters": { + "inputs": [ + { + "address": "waf.context.event" + }, + { + "address": "server.business_logic.users.login.failure" + }, + { + "address": "server.business_logic.users.login.success" + } + ] + } + } + ], + "parameters": { + "mappings": [ + { + "headers": [ + { + "address": "server.request.headers.no_cookies" + } + ], + "output": "_dd.appsec.fp.http.network" + } + ] + }, + "evaluate": false, + "output": true + }, + { + "id": "session-fingerprint", + "generator": "session_fingerprint", + "conditions": [ + { + "operator": "exists", + "parameters": { + "inputs": [ + { + "address": "waf.context.event" + }, + { + "address": "server.business_logic.users.login.failure" + }, + { + "address": "server.business_logic.users.login.success" + } + ] + } + } + ], + "parameters": { + "mappings": [ + { + "cookies": [ + { + "address": "server.request.cookies" + } + ], + "session_id": [ + { + "address": "usr.session_id" + } + ], + "user_id": [ + { + "address": "usr.id" + } + ], + "output": "_dd.appsec.fp.session" + } + ] + }, + "evaluate": false, + "output": true } ], "scanners": [ + { + "id": "406f8606-52c4-4663-8db9-df70f9e8766c", + "name": "ZIP Code", + "key": { + "operator": "match_regex", + "parameters": { + "regex": "\\b(?:zip|postal)\\b", + "options": { + "case_sensitive": false, + "min_length": 3 + } + } + }, + "value": { + "operator": "match_regex", + "parameters": { + "regex": "^[0-9]{5}(?:-[0-9]{4})?$", + "options": { + "case_sensitive": true, + "min_length": 5 + } + } + }, + "tags": { + "type": "zipcode", + "category": "address" + } + }, { "id": "JU1sRk3mSzqSUJn6GrVn7g", "name": "American Express Card Scanner (4+4+4+3 digits)", @@ -9157,6 +9548,34 @@ "category": "payment" } }, + { + "id": "18b608bd7a764bff5b2344c0", + "name": "Phone number", + "key": { + "operator": "match_regex", + "parameters": { + "regex": "\\bphone|number|mobile\\b", + "options": { + "case_sensitive": false, + "min_length": 3 + } + } + }, + "value": { + "operator": "match_regex", + "parameters": { + "regex": "^(?:\\(\\+\\d{1,3}\\)|\\+\\d{1,3}|00\\d{1,3})?[-\\s\\.]?(?:\\(\\d{3}\\)[-\\s\\.]?)?(?:\\d[-\\s\\.]?){6,10}$", + "options": { + "case_sensitive": false, + "min_length": 6 + } + } + }, + "tags": { + "type": "phone", + "category": "pii" + } + }, { "id": "de0899e0cbaaa812bb624cf04c912071012f616d-mod", "name": "UK National Insurance Number Scanner", @@ -9357,4 +9776,4 @@ } } ] -} \ No newline at end of file +} diff --git a/vendor/github.com/DataDog/appsec-internal-go/httpsec/client_ip.go b/vendor/github.com/DataDog/appsec-internal-go/httpsec/client_ip.go new file mode 100644 index 000000000..3761a7739 --- /dev/null +++ b/vendor/github.com/DataDog/appsec-internal-go/httpsec/client_ip.go @@ -0,0 +1,126 @@ +package httpsec + +import ( + "net" + "net/textproto" + "strings" + + "github.com/DataDog/appsec-internal-go/netip" +) + +const ( + // RemoteIPTag is the tag name used for the remote HTTP request IP address. + RemoteIPTag = "network.client.ip" + // ClientIPTag is the tag name used for the client IP deduced from the HTTP + // request headers with ClientIP(). + ClientIPTag = "http.client_ip" +) + +// ClientIPTags returns the resulting Datadog span tags `http.client_ip` +// containing the client IP and `network.client.ip` containing the remote IP. +// The tags are present only if a valid ip address has been returned by +// ClientIP(). +func ClientIPTags(remoteIP, clientIP netip.Addr) (tags map[string]string) { + remoteIPValid := remoteIP.IsValid() + clientIPValid := clientIP.IsValid() + if !remoteIPValid && !clientIPValid { + return nil + } + + tags = make(map[string]string, 2) + if remoteIPValid { + tags[RemoteIPTag] = remoteIP.String() + } + if clientIPValid { + tags[ClientIPTag] = clientIP.String() + } + return tags +} + +// ClientIP returns the first public IP address found in the given headers. If +// none is present, it returns the first valid IP address present, possibly +// being a local IP address. The remote address, when valid, is used as fallback +// when no IP address has been found at all. +func ClientIP(hdrs map[string][]string, hasCanonicalHeaders bool, remoteAddr string, monitoredHeaders []string) (remoteIP, clientIP netip.Addr) { + // Walk IP-related headers + var foundIP netip.Addr +headersLoop: + for _, headerName := range monitoredHeaders { + if hasCanonicalHeaders { + headerName = textproto.CanonicalMIMEHeaderKey(headerName) + } + + headerValues, exists := hdrs[headerName] + if !exists { + continue // this monitored header is not present + } + + // Assuming a list of comma-separated IP addresses, split them and build + // the list of values to try to parse as IP addresses + var ips []string + for _, ip := range headerValues { + ips = append(ips, strings.Split(ip, ",")...) + } + + // Look for the first valid or global IP address in the comma-separated list + for _, ipstr := range ips { + ip := parseIP(strings.TrimSpace(ipstr)) + if !ip.IsValid() { + continue + } + // Replace foundIP if still not valid in order to keep the oldest + if !foundIP.IsValid() { + foundIP = ip + } + if isGlobal(ip) { + foundIP = ip + break headersLoop + } + } + } + + // Decide which IP address is the client one by starting with the remote IP + if ip := parseIP(remoteAddr); ip.IsValid() { + remoteIP = ip + clientIP = ip + } + + // The IP address found in the headers supersedes a private remote IP address. + if foundIP.IsValid() && !isGlobal(remoteIP) || isGlobal(foundIP) { + clientIP = foundIP + } + + return remoteIP, clientIP +} + +func parseIP(s string) netip.Addr { + if ip, err := netip.ParseAddr(s); err == nil { + return ip + } + if h, _, err := net.SplitHostPort(s); err == nil { + if ip, err := netip.ParseAddr(h); err == nil { + return ip + } + } + return netip.Addr{} +} + +var ipv6SpecialNetworks = [...]netip.Prefix{ + netip.MustParsePrefix("fec0::/10"), // site local +} + +func isGlobal(ip netip.Addr) bool { + // IsPrivate also checks for ipv6 ULA. + // We care to check for these addresses are not considered public, hence not global. + // See https://www.rfc-editor.org/rfc/rfc4193.txt for more details. + isGlobal := ip.IsValid() && !ip.IsPrivate() && !ip.IsLoopback() && !ip.IsLinkLocalUnicast() + if !isGlobal || !ip.Is6() { + return isGlobal + } + for _, n := range ipv6SpecialNetworks { + if n.Contains(ip) { + return false + } + } + return isGlobal +} diff --git a/vendor/github.com/DataDog/appsec-internal-go/netip/ip.go b/vendor/github.com/DataDog/appsec-internal-go/netip/ip.go new file mode 100644 index 000000000..99e1e627a --- /dev/null +++ b/vendor/github.com/DataDog/appsec-internal-go/netip/ip.go @@ -0,0 +1,31 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2022 Datadog, Inc. + +package netip + +import "net/netip" + +// Addr wraps a netip.Addr value +type Addr = netip.Addr + +// Prefix wraps a netip.Prefix value +type Prefix = netip.Prefix + +var ( + // ParseAddr wraps the netip.ParseAddr function + ParseAddr = netip.ParseAddr + // MustParsePrefix wraps the netip.MustParsePrefix function + MustParsePrefix = netip.MustParsePrefix + // MustParseAddr wraps the netip.MustParseAddr function + MustParseAddr = netip.MustParseAddr + // AddrFrom16 wraps the netIP.AddrFrom16 function + AddrFrom16 = netip.AddrFrom16 +) + +// IPv4 wraps the netip.AddrFrom4 function +func IPv4(a, b, c, d byte) Addr { + e := [4]byte{a, b, c, d} + return netip.AddrFrom4(e) +} diff --git a/vendor/github.com/DataDog/datadog-agent/pkg/remoteconfig/state/configs_asm.go b/vendor/github.com/DataDog/datadog-agent/pkg/remoteconfig/state/configs_asm.go index ac7a918e8..00b377dbb 100644 --- a/vendor/github.com/DataDog/datadog-agent/pkg/remoteconfig/state/configs_asm.go +++ b/vendor/github.com/DataDog/datadog-agent/pkg/remoteconfig/state/configs_asm.go @@ -49,11 +49,14 @@ type ASMFeaturesConfig struct { Metadata Metadata } -// ASMFeaturesData describes the enabled state of ASM features +// ASMFeaturesData describes the state of ASM and some of its features type ASMFeaturesData struct { ASM struct { Enabled bool `json:"enabled"` } `json:"asm"` + APISecurity struct { + RequestSampleRate float64 `json:"request_sample_rate"` + } `json:"api_security"` } func parseASMFeaturesConfig(data []byte, metadata Metadata) (ASMFeaturesConfig, error) { @@ -95,9 +98,13 @@ func (r *Repository) ASMFeaturesConfigs() map[string]ASMFeaturesConfig { type ApplyState uint64 const ( + //ApplyStateUnknown indicates that a client does not support the ApplyState feature ApplyStateUnknown ApplyState = iota + // ApplyStateUnacknowledged indicates a client has received the config but has not specified success or failure ApplyStateUnacknowledged + // ApplyStateAcknowledged indicates a client has successfully applied the config ApplyStateAcknowledged + // ApplyStateError indicates that a client has failed to apply the config ApplyStateError ) diff --git a/vendor/github.com/DataDog/datadog-agent/pkg/remoteconfig/state/products.go b/vendor/github.com/DataDog/datadog-agent/pkg/remoteconfig/state/products.go index 96f635df6..35974c5e9 100644 --- a/vendor/github.com/DataDog/datadog-agent/pkg/remoteconfig/state/products.go +++ b/vendor/github.com/DataDog/datadog-agent/pkg/remoteconfig/state/products.go @@ -6,22 +6,45 @@ package state var validProducts = map[string]struct{}{ - ProductAgentConfig: {}, - ProductAgentTask: {}, - ProductAPMSampling: {}, - ProductCWSDD: {}, - ProductCWSCustom: {}, - ProductCWSProfiles: {}, - ProductASM: {}, - ProductASMFeatures: {}, - ProductASMDD: {}, - ProductASMData: {}, - ProductAPMTracing: {}, + ProductUpdaterCatalogDD: {}, + ProductUpdaterAgent: {}, + ProductUpdaterTask: {}, + ProductAgentConfig: {}, + ProductAgentFailover: {}, + ProductAgentTask: {}, + ProductAgentIntegrations: {}, + ProductAPMSampling: {}, + ProductCWSDD: {}, + ProductCWSCustom: {}, + ProductCWSProfiles: {}, + ProductCSMSideScanning: {}, + ProductASM: {}, + ProductASMFeatures: {}, + ProductASMDD: {}, + ProductASMData: {}, + ProductAPMTracing: {}, + ProductSDSRules: {}, + ProductSDSAgentConfig: {}, + ProductLiveDebugging: {}, + ProductContainerAutoscalingSettings: {}, + ProductContainerAutoscalingValues: {}, + ProductTesting1: {}, + ProductTesting2: {}, } const ( + // ProductUpdaterCatalogDD is the product used to receive the package catalog from datadog + ProductUpdaterCatalogDD = "UPDATER_CATALOG_DD" + // ProductUpdaterAgent is the product used to receive defaults versions to install + ProductUpdaterAgent = "UPDATER_AGENT" + // ProductUpdaterTask is the product used to receive tasks to execute + ProductUpdaterTask = "UPDATER_TASK" // ProductAgentConfig is to receive agent configurations, like the log level ProductAgentConfig = "AGENT_CONFIG" + // ProductAgentFailover is to receive the multi-region failover configuration + ProductAgentFailover = "AGENT_FAILOVER" + // ProductAgentIntegrations is to receive integrations to schedule + ProductAgentIntegrations = "AGENT_INTEGRATIONS" // ProductAgentTask is to receive agent task instruction, like a flare ProductAgentTask = "AGENT_TASK" // ProductAPMSampling is the apm sampling product @@ -32,6 +55,8 @@ const ( ProductCWSCustom = "CWS_CUSTOM" // ProductCWSProfiles is the cloud workload security profile product ProductCWSProfiles = "CWS_SECURITY_PROFILES" + // ProductCSMSideScanning is the side scanning product + ProductCSMSideScanning = "CSM_SIDE_SCANNING" // ProductASM is the ASM product used by customers to issue rules configurations ProductASM = "ASM" // ProductASMFeatures is the ASM product used form ASM activation through remote config @@ -42,4 +67,18 @@ const ( ProductASMData = "ASM_DATA" // ProductAPMTracing is the apm tracing product ProductAPMTracing = "APM_TRACING" + // ProductSDSRules is the SDS definitions product + ProductSDSRules = "SDS_RULES_DD" + // ProductSDSAgentConfig is the user SDS configurations product. + ProductSDSAgentConfig = "SDS_AGENT_CONFIG" + // ProductLiveDebugging is the dynamic instrumentation product + ProductLiveDebugging = "LIVE_DEBUGGING" + // ProductContainerAutoscalingSettings receives definition of container autoscaling + ProductContainerAutoscalingSettings = "CONTAINER_AUTOSCALING_SETTINGS" + // ProductContainerAutoscalingValues receives values for container autoscaling + ProductContainerAutoscalingValues = "CONTAINER_AUTOSCALING_VALUES" + // ProductTesting1 is a product used for testing remote config + ProductTesting1 = "TESTING1" + // ProductTesting2 is a product used for testing remote config + ProductTesting2 = "TESTING2" ) diff --git a/vendor/github.com/DataDog/datadog-agent/pkg/remoteconfig/state/repository.go b/vendor/github.com/DataDog/datadog-agent/pkg/remoteconfig/state/repository.go index ced2a3db2..031d20f27 100644 --- a/vendor/github.com/DataDog/datadog-agent/pkg/remoteconfig/state/repository.go +++ b/vendor/github.com/DataDog/datadog-agent/pkg/remoteconfig/state/repository.go @@ -3,6 +3,8 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2022-present Datadog, Inc. +// Package state provides the types and logic needed to track the current TUF repository +// state for a client. package state import ( @@ -300,7 +302,7 @@ func (r *Repository) getConfigs(product string) map[string]interface{} { // // The update is guaranteed to succeed at this point, having been vetted and the details // needed to apply the update stored in the `updateResult`. -func (r *Repository) applyUpdateResult(update Update, result updateResult) { +func (r *Repository) applyUpdateResult(_ Update, result updateResult) { // 4.b Save all the updated and new config files for product, configs := range result.changed { for path, config := range configs { diff --git a/vendor/github.com/DataDog/go-libddwaf/v2/context.go b/vendor/github.com/DataDog/go-libddwaf/v2/context.go deleted file mode 100644 index 627f4239a..000000000 --- a/vendor/github.com/DataDog/go-libddwaf/v2/context.go +++ /dev/null @@ -1,195 +0,0 @@ -// Unless explicitly stated otherwise all files in this repository are licensed -// under the Apache License Version 2.0. -// This product includes software developed at Datadog (https://www.datadoghq.com/). -// Copyright 2016-present Datadog, Inc. - -package waf - -import ( - "sync" - "time" - - "go.uber.org/atomic" -) - -// Context is a WAF execution context. It allows running the WAF incrementally -// when calling it multiple times to run its rules every time new addresses -// become available. Each request must have its own Context. -type Context struct { - handle *Handle // Instance of the WAF - - cgoRefs cgoRefPool // Used to retain go data referenced by WAF Objects the context holds - cContext wafContext // The C ddwaf_context pointer - - // Stats - totalRuntimeNs atomic.Uint64 // Cumulative internal WAF run time - in nanoseconds - for this context. - totalOverallRuntimeNs atomic.Uint64 // Cumulative overall run time - in nanoseconds - for this context. - timeoutCount atomic.Uint64 // Cumulative timeout count for this context. - - // Mutex protecting the use of cContext which is not thread-safe and cgoRefs. - mutex sync.Mutex -} - -// NewContext returns a new WAF context of to the given WAF handle. -// A nil value is returned when the WAF handle was released or when the -// WAF context couldn't be created. -// handle. A nil value is returned when the WAF handle can no longer be used -// or the WAF context couldn't be created. -func NewContext(handle *Handle) *Context { - // Handle has been released - if !handle.retain() { - return nil - } - - cContext := wafLib.wafContextInit(handle.cHandle) - if cContext == 0 { - handle.release() // We couldn't get a context, so we no longer have an implicit reference to the Handle in it... - return nil - } - - return &Context{handle: handle, cContext: cContext} -} - -// RunAddressData provides address data to the Context.Run method. If a given key is present in both -// RunAddressData.Persistent and RunAddressData.Ephemeral, the value from RunAddressData.Persistent will take precedence. -type RunAddressData struct { - // Persistent address data is scoped to the lifetime of a given Context, and subsquent calls to Context.Run with the - // same address name will be silently ignored. - Persistent map[string]any - // Ephemeral address data is scoped to a given Context.Run call and is not persisted across calls. This is used for - // protocols such as gRPC client/server streaming or GraphQL, where a single request can incur multiple subrequests. - Ephemeral map[string]any -} - -func (d RunAddressData) isEmpty() bool { - return len(d.Persistent) == 0 && len(d.Ephemeral) == 0 -} - -// Run encodes the given addressData values and runs them against the WAF rules within the given timeout value. If a -// given address is present both as persistent and ephemeral, the persistent value takes precedence. It returns the -// matches as a JSON string (usually opaquely used) along with the corresponding actions in any. In case of an error, -// matches and actions can still be returned, for instance in the case of a timeout error. Errors can be tested against -// the RunError type. -// Struct fields having the tag `ddwaf:"ignore"` will not be encoded and sent to the WAF -func (context *Context) Run(addressData RunAddressData, timeout time.Duration) (res Result, err error) { - if addressData.isEmpty() { - return - } - - now := time.Now() - defer func() { - dt := time.Since(now) - context.totalOverallRuntimeNs.Add(uint64(dt.Nanoseconds())) - }() - - // At this point, the only error we can get is an error in case the top level object is a nil map, but this - // behaviour is expected since either persistent or ephemeral addresses are allowed to be null one at a time. - // In this case, EncodeAddresses will return nil contrary to Encode which will return an nil wafObject, - // which is what we need to send to ddwaf_run to signal that the address data is empty. - var persistentData *wafObject = nil - var ephemeralData *wafObject = nil - persistentEncoder := newLimitedEncoder() - ephemeralEncoder := newLimitedEncoder() - if addressData.Persistent != nil { - persistentData, _ = persistentEncoder.EncodeAddresses(addressData.Persistent) - } - - if addressData.Ephemeral != nil { - ephemeralData, _ = ephemeralEncoder.EncodeAddresses(addressData.Ephemeral) - - } - // The WAF releases ephemeral address data at the end of each run call, so we need not keep the Go values live beyond - // that in the same way we need for persistent data. We hence use a separate encoder. - - // ddwaf_run cannot run concurrently and the next append write on the context state so we need a mutex - context.mutex.Lock() - defer context.mutex.Unlock() - - // Save the Go pointer references to addressesToData that were referenced by the encoder - // into C ddwaf_objects. libddwaf's API requires to keep this data for the lifetime of the ddwaf_context. - defer context.cgoRefs.append(persistentEncoder.cgoRefs) - - res, err = context.run(persistentData, ephemeralData, timeout, &persistentEncoder.cgoRefs) - - // Ensure the ephemerals don't get optimized away by the compiler before the WAF had a chance to use them. - keepAlive(ephemeralEncoder.cgoRefs) - - return -} - -// run executes the ddwaf_run call with the provided data on this context. The caller is responsible for locking the -// context appropriately around this call. -func (context *Context) run(persistentData, ephemeralData *wafObject, timeout time.Duration, cgoRefs *cgoRefPool) (Result, error) { - result := new(wafResult) - defer wafLib.wafResultFree(result) - - ret := wafLib.wafRun(context.cContext, persistentData, ephemeralData, result, uint64(timeout/time.Microsecond)) - - context.totalRuntimeNs.Add(result.total_runtime) - res, err := unwrapWafResult(ret, result) - if err == ErrTimeout { - context.timeoutCount.Inc() - } - - return res, err -} - -func unwrapWafResult(ret wafReturnCode, result *wafResult) (res Result, err error) { - if result.timeout > 0 { - err = ErrTimeout - } else { - // Derivatives can be generated even if no security event gets detected, so we decode them as long as the WAF - // didn't timeout - res.Derivatives, err = decodeMap(&result.derivatives) - } - - if ret == wafOK { - return res, err - } - - if ret != wafMatch { - return res, goRunError(ret) - } - - res.Events, err = decodeArray(&result.events) - if err != nil { - return res, err - } - if size := result.actions.nbEntries; size > 0 { - // using ruleIdArray cause it decodes string array (I think) - res.Actions, err = decodeStringArray(&result.actions) - // TODO: use decode array, and eventually genericize the function - if err != nil { - return res, err - } - } - - return res, err -} - -// Close the underlying `ddwaf_context` and releases the associated internal -// data. Also decreases the reference count of the `ddwaf_hadnle` which created -// this context, possibly releasing it completely (if this was the last context -// created from this handle & it was released by its creator). -func (context *Context) Close() { - context.mutex.Lock() - defer context.mutex.Unlock() - - wafLib.wafContextDestroy(context.cContext) - keepAlive(context.cgoRefs) // Keep the Go pointer references until the end of the context - defer context.handle.release() // Reduce the reference counter of the Handle. - - context.cgoRefs = cgoRefPool{} // The data in context.cgoRefs is no longer needed, explicitly release - context.cContext = 0 // Makes it easy to spot use-after-free/double-free issues -} - -// TotalRuntime returns the cumulated WAF runtime across various run calls within the same WAF context. -// Returned time is in nanoseconds. -func (context *Context) TotalRuntime() (overallRuntimeNs, internalRuntimeNs uint64) { - return context.totalOverallRuntimeNs.Load(), context.totalRuntimeNs.Load() -} - -// TotalTimeouts returns the cumulated amount of WAF timeouts across various run calls within the same WAF context. -func (context *Context) TotalTimeouts() uint64 { - return context.timeoutCount.Load() -} diff --git a/vendor/github.com/DataDog/go-libddwaf/v2/ctypes.go b/vendor/github.com/DataDog/go-libddwaf/v2/ctypes.go deleted file mode 100644 index 6f2adccdd..000000000 --- a/vendor/github.com/DataDog/go-libddwaf/v2/ctypes.go +++ /dev/null @@ -1,206 +0,0 @@ -// Unless explicitly stated otherwise all files in this repository are licensed -// under the Apache License Version 2.0. -// This product includes software developed at Datadog (https://www.datadoghq.com/). -// Copyright 2016-present Datadog, Inc. - -package waf - -import ( - "reflect" - "unsafe" -) - -const ( - wafMaxStringLength = 4096 - wafMaxContainerDepth = 20 - wafMaxContainerSize = 256 - wafRunTimeout = 5000 -) - -type wafReturnCode int32 - -const ( - wafErrInternal wafReturnCode = iota - 3 - wafErrInvalidObject - wafErrInvalidArgument - wafOK - wafMatch -) - -// wafObjectType is an enum in C which has the size of DWORD. -// But DWORD is 4 bytes in amd64 and arm64 so uint32 it is. -type wafObjectType uint32 - -const wafInvalidType wafObjectType = 0 -const ( - wafIntType wafObjectType = 1 << iota - wafUintType - wafStringType - wafArrayType - wafMapType - wafBoolType - wafFloatType - wafNilType -) - -type wafObject struct { - parameterName uintptr - parameterNameLength uint64 - value uintptr - nbEntries uint64 - _type wafObjectType - _ [4]byte - // Forced padding - // We only support 2 archs and cgo generated the same padding to both. - // We don't want the C struct to be packed because actually go will do the same padding itself, - // we just add it explicitly to not take any chance. - // And we cannot pack a struct in go so it will get tricky if the struct is - // packed (apart from breaking all tracers of course) -} - -// isInvalid determines whether this WAF Object has the invalid type (which is the 0-value). -func (w *wafObject) isInvalid() bool { - return w._type == wafInvalidType -} - -// isNil determines whether this WAF Object is nil or not. -func (w *wafObject) isNil() bool { - return w._type == wafNilType -} - -// isArray determines whether this WAF Object is an array or not. -func (w *wafObject) isArray() bool { - return w._type == wafArrayType -} - -// isMap determines whether this WAF Object is a map or not. -func (w *wafObject) isMap() bool { - return w._type == wafMapType -} - -// IsUnusable returns true if the wafObject has no impact on the WAF execution -// But we still need this kind of objects to forward map keys in case the value of the map is invalid -func (wo *wafObject) IsUnusable() bool { - return wo._type == wafInvalidType || wo._type == wafNilType -} - -type wafConfig struct { - limits wafConfigLimits - obfuscator wafConfigObfuscator - freeFn uintptr -} - -type wafConfigLimits struct { - maxContainerSize uint32 - maxContainerDepth uint32 - maxStringLength uint32 -} - -type wafConfigObfuscator struct { - keyRegex uintptr // char * - valueRegex uintptr // char * -} - -type wafResult struct { - timeout byte - events wafObject - actions wafObject - derivatives wafObject - total_runtime uint64 -} - -// wafHandle is a forward declaration in ddwaf.h header -// We basically don't need to modify it, only to give it to the waf -type wafHandle uintptr - -// wafContext is a forward declaration in ddwaf.h header -// We basically don't need to modify it, only to give it to the waf -type wafContext uintptr - -// gostring copies a char* to a Go string. -func gostring(ptr *byte) string { - if ptr == nil { - return "" - } - var length int - for { - if *(*byte)(unsafe.Add(unsafe.Pointer(ptr), uintptr(length))) == '\x00' { - break - } - length++ - } - //string builtin copies the slice - return string(unsafe.Slice(ptr, length)) -} - -// nativeStringUnwrap cast a native string type into it's runtime value. Exported as the struct reflect.StringHeader -func nativeStringUnwrap(str string) reflect.StringHeader { - return *(*reflect.StringHeader)(unsafe.Pointer(&str)) -} - -func gostringSized(ptr *byte, size uint64) string { - if ptr == nil { - return "" - } - return string(unsafe.Slice(ptr, size)) -} - -// cstring converts a go string to *byte that can be passed to C code. -func cstring(name string) *byte { - var b = make([]byte, len(name)+1) - copy(b, name) - return &b[0] -} - -// cast is used to centralize unsafe use C of allocated pointer. -// We take the address and then dereference it to trick go vet from creating a possible misuse of unsafe.Pointer -func cast[T any](ptr uintptr) *T { - return (*T)(*(*unsafe.Pointer)(unsafe.Pointer(&ptr))) -} - -// nativeToUintptr is a helper used by populate wafObject values -// with Go values -func nativeToUintptr[T any](x T) uintptr { - return *(*uintptr)(unsafe.Pointer(&x)) -} - -// uintToNative is a helper used retrieve Go values from an uintptr encoded -// value from a wafObject -func uintptrToNative[T any](x uintptr) T { - return *(*T)(unsafe.Pointer(&x)) -} - -// castWithOffset is the same as cast but adding an offset to the pointer by a multiple of the size -// of the type pointed. -func castWithOffset[T any](ptr uintptr, offset uint64) *T { - return (*T)(unsafe.Add(*(*unsafe.Pointer)(unsafe.Pointer(&ptr)), offset*uint64(unsafe.Sizeof(*new(T))))) -} - -// ptrToUintptr is a helper to centralize of usage of unsafe.Pointer -// do not use this function to cast interfaces -func ptrToUintptr[T any](arg *T) uintptr { - return uintptr(unsafe.Pointer(arg)) -} - -func sliceToUintptr[T any](arg []T) uintptr { - return (*reflect.SliceHeader)(unsafe.Pointer(&arg)).Data -} - -// keepAlive() globals -var ( - alwaysFalse bool - escapeSink any -) - -// keepAlive is a copy of runtime.KeepAlive -// keepAlive has 2 usages: -// - It forces the deallocation of the memory to take place later than expected (just like runtime.KeepAlive) -// - It forces the given argument x to be escaped on the heap by saving it into a global value (Go doesn't provide a standard way to do it as of today) -// It is implemented so that the compiler cannot optimize it. -// -//go:noinline -func keepAlive[T any](x T) { - if alwaysFalse { - escapeSink = x - } -} diff --git a/vendor/github.com/DataDog/go-libddwaf/v2/decoder.go b/vendor/github.com/DataDog/go-libddwaf/v2/decoder.go deleted file mode 100644 index ceaf2e2bd..000000000 --- a/vendor/github.com/DataDog/go-libddwaf/v2/decoder.go +++ /dev/null @@ -1,239 +0,0 @@ -// Unless explicitly stated otherwise all files in this repository are licensed -// under the Apache License Version 2.0. -// This product includes software developed at Datadog (https://www.datadoghq.com/). -// Copyright 2016-present Datadog, Inc. - -package waf - -// decodeErrors transforms the wafObject received by the wafRulesetInfo after the call to wafDl.wafInit to a map where -// keys are the error message and the value is a array of all the rule ids which triggered this specific error -func decodeErrors(obj *wafObject) (map[string][]string, error) { - if !obj.isMap() { - return nil, errInvalidObjectType - } - - if obj.value == 0 && obj.nbEntries > 0 { - return nil, errNilObjectPtr - } - - wafErrors := map[string][]string{} - for i := uint64(0); i < obj.nbEntries; i++ { - objElem := castWithOffset[wafObject](obj.value, i) - - errorMessage := gostringSized(cast[byte](objElem.parameterName), objElem.parameterNameLength) - ruleIds, err := decodeStringArray(objElem) - if err != nil { - return nil, err - } - - wafErrors[errorMessage] = ruleIds - } - - return wafErrors, nil -} - -func decodeDiagnostics(obj *wafObject) (*Diagnostics, error) { - if !obj.isMap() { - return nil, errInvalidObjectType - } - if obj.value == 0 && obj.nbEntries > 0 { - return nil, errNilObjectPtr - } - - var diags Diagnostics - var err error - for i := uint64(0); i < obj.nbEntries; i++ { - objElem := castWithOffset[wafObject](obj.value, i) - key := gostringSized(cast[byte](objElem.parameterName), objElem.parameterNameLength) - switch key { - case "custom_rules": - diags.CustomRules, err = decodeDiagnosticsEntry(objElem) - case "exclusions": - diags.Exclusions, err = decodeDiagnosticsEntry(objElem) - case "rules": - diags.Rules, err = decodeDiagnosticsEntry(objElem) - case "rules_data": - diags.RulesData, err = decodeDiagnosticsEntry(objElem) - case "rules_override": - diags.RulesOverrides, err = decodeDiagnosticsEntry(objElem) - case "processors": - diags.Processors, err = decodeDiagnosticsEntry(objElem) - case "scanners": - diags.Scanners, err = decodeDiagnosticsEntry(objElem) - case "ruleset_version": - diags.Version = gostringSized(cast[byte](objElem.value), objElem.nbEntries) - default: - // ignore? - } - if err != nil { - return nil, err - } - } - - return &diags, nil -} - -func decodeDiagnosticsEntry(obj *wafObject) (*DiagnosticEntry, error) { - if !obj.isMap() { - return nil, errInvalidObjectType - } - if obj.value == 0 && obj.nbEntries > 0 { - return nil, errNilObjectPtr - } - var entry DiagnosticEntry - var err error - - for i := uint64(0); i < obj.nbEntries; i++ { - objElem := castWithOffset[wafObject](obj.value, i) - key := gostringSized(cast[byte](objElem.parameterName), objElem.parameterNameLength) - switch key { - case "addresses": - entry.Addresses, err = decodeDiagnosticAddresses(objElem) - case "error": - entry.Error = gostringSized(cast[byte](objElem.value), objElem.nbEntries) - case "errors": - entry.Errors, err = decodeErrors(objElem) - case "failed": - entry.Failed, err = decodeStringArray(objElem) - case "loaded": - entry.Loaded, err = decodeStringArray(objElem) - default: - return nil, errUnsupportedValue - } - - if err != nil { - return nil, err - } - } - - return &entry, nil -} - -func decodeDiagnosticAddresses(obj *wafObject) (*DiagnosticAddresses, error) { - if !obj.isMap() { - return nil, errInvalidObjectType - } - if obj.value == 0 && obj.nbEntries > 0 { - return nil, errNilObjectPtr - } - - addrs := &DiagnosticAddresses{} - - var err error - for i := uint64(0); i < obj.nbEntries; i++ { - objElem := castWithOffset[wafObject](obj.value, i) - key := gostringSized(cast[byte](objElem.parameterName), objElem.parameterNameLength) - switch key { - case "required": - addrs.Required, err = decodeStringArray(objElem) - if err != nil { - return nil, err - } - case "optional": - addrs.Optional, err = decodeStringArray(objElem) - if err != nil { - return nil, err - } - default: - return nil, errUnsupportedValue - } - } - - return addrs, nil -} - -func decodeStringArray(obj *wafObject) ([]string, error) { - // We consider that nil is an empty array - if obj.isNil() { - return nil, nil - } - - if !obj.isArray() { - return nil, errInvalidObjectType - } - - if obj.value == 0 && obj.nbEntries > 0 { - return nil, errNilObjectPtr - } - - var strArr []string - for i := uint64(0); i < obj.nbEntries; i++ { - objElem := castWithOffset[wafObject](obj.value, i) - if objElem._type != wafStringType { - return nil, errInvalidObjectType - } - - strArr = append(strArr, gostringSized(cast[byte](objElem.value), objElem.nbEntries)) - } - - return strArr, nil -} - -func decodeObject(obj *wafObject) (any, error) { - switch obj._type { - case wafMapType: - return decodeMap(obj) - case wafArrayType: - return decodeArray(obj) - case wafStringType: - return gostringSized(cast[byte](obj.value), obj.nbEntries), nil - case wafIntType: - return int64(obj.value), nil - case wafUintType: - return uint64(obj.value), nil - case wafFloatType: - return uintptrToNative[float64](obj.value), nil - case wafBoolType: - return uintptrToNative[bool](obj.value), nil - case wafNilType: - return nil, nil - default: - return nil, errUnsupportedValue - } -} - -func decodeArray(obj *wafObject) ([]any, error) { - if obj.isNil() { - return nil, nil - } - - if !obj.isArray() { - return nil, errInvalidObjectType - } - - events := make([]any, obj.nbEntries) - - for i := uint64(0); i < obj.nbEntries; i++ { - objElem := castWithOffset[wafObject](obj.value, i) - val, err := decodeObject(objElem) - if err != nil { - return nil, err - } - events[i] = val - } - - return events, nil -} - -func decodeMap(obj *wafObject) (map[string]any, error) { - if obj.isNil() { - return nil, nil - } - - if !obj.isMap() { - return nil, errInvalidObjectType - } - - result := make(map[string]any, obj.nbEntries) - for i := uint64(0); i < obj.nbEntries; i++ { - objElem := castWithOffset[wafObject](obj.value, i) - key := gostringSized(cast[byte](objElem.parameterName), objElem.parameterNameLength) - val, err := decodeObject(objElem) - if err != nil { - return nil, err - } - result[key] = val - } - - return result, nil -} diff --git a/vendor/github.com/DataDog/go-libddwaf/v2/internal/lib/.version b/vendor/github.com/DataDog/go-libddwaf/v2/internal/lib/.version deleted file mode 100644 index 71bd5d9ee..000000000 --- a/vendor/github.com/DataDog/go-libddwaf/v2/internal/lib/.version +++ /dev/null @@ -1 +0,0 @@ -1.16.0 \ No newline at end of file diff --git a/vendor/github.com/DataDog/go-libddwaf/v2/internal/lib/lib.go b/vendor/github.com/DataDog/go-libddwaf/v2/internal/lib/lib.go deleted file mode 100644 index 93f41dbe8..000000000 --- a/vendor/github.com/DataDog/go-libddwaf/v2/internal/lib/lib.go +++ /dev/null @@ -1,49 +0,0 @@ -// Unless explicitly stated otherwise all files in this repository are licensed -// under the Apache License Version 2.0. -// This product includes software developed at Datadog (https://www.datadoghq.com/). -// Copyright 2016-present Datadog, Inc. - -//go:build ((darwin && (amd64 || arm64)) || (linux && (amd64 || arm64))) && !go1.23 && !datadog.no_waf && (cgo || appsec) - -package lib - -import ( - "fmt" - "os" - - _ "embed" -) - -//go:embed .version -var EmbeddedWAFVersion string - -func DumpEmbeddedWAF() (path string, err error) { - file, err := os.CreateTemp("", embedNamePattern) - if err != nil { - return path, fmt.Errorf("error creating temp file: %w", err) - } - path = file.Name() - - defer func() { - if closeErr := file.Close(); closeErr != nil { - if err != nil { - // TODO: rely on errors.Join() once go1.20 is our min supported Go version - err = fmt.Errorf("%w; along with an error while releasingclosing the temporary file: %v", err, closeErr) - } else { - err = fmt.Errorf("error closing file: %w", closeErr) - } - } - if path != "" && err != nil { - if rmErr := os.Remove(path); rmErr != nil { - // TODO: rely on errors.Join() once go1.20 is our min supported Go version - err = fmt.Errorf("%w; along with an error while releasingclosing the temporary file: %v", err, rmErr) - } - } - }() - - if err := os.WriteFile(file.Name(), libddwaf, 0400); err != nil { - return path, fmt.Errorf("error writing file: %w", err) - } - - return path, nil -} diff --git a/vendor/github.com/DataDog/go-libddwaf/v2/internal/lib/libddwaf-darwin-amd64.dylib b/vendor/github.com/DataDog/go-libddwaf/v2/internal/lib/libddwaf-darwin-amd64.dylib deleted file mode 100644 index c0c731615ff3502191c4708d1db0307cea456b3b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1566256 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%0Abk0F`ZvX<9D^z*BHiJto;$!1Uv4HI3 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�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%0APVZV-CRa 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 diff --git a/vendor/github.com/DataDog/go-libddwaf/v2/internal/lib/libddwaf-darwin-arm64.dylib b/vendor/github.com/DataDog/go-libddwaf/v2/internal/lib/libddwaf-darwin-arm64.dylib deleted file mode 100644 index ef81c347ca75447e38b318d88b5dec10c1bfd40d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1436976 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
4(U-d&Mq4rlAVk{ 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 ZSYPb1sx-B@T_l!gowLiF^?%~-e*m@s2k!s? diff --git a/vendor/github.com/DataDog/go-libddwaf/v2/internal/lib/libddwaf-linux-amd64.so b/vendor/github.com/DataDog/go-libddwaf/v2/internal/lib/libddwaf-linux-amd64.so deleted file mode 100644 index 7f3b25ae605be2e8961b137f100aeefd41b28e93..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2136144 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�R9&65oY~Sp2^@M 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 z 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�nuYRk2{b(O@@ze`_-=8}$z5i-* z=FUQ|TSps~8GUxH)^lWG>}h#-p6^@!$ob#fxUR_OUrk%Ue}>vO`uyHEs4dILulvaT z?i-f%8g|3_zQZmXJ*&I_UIT`u>qCbzBbPAX=?q%&T=S#V8tWRTXHSQGHH%?w0E zp*3wS37)or2qmQU^mdL3SPdCah_?)adB4w|J;}@vtf#;8zV9FNnZ4Iu>silw)^l6W zx|NB2s5bL_(NI>zbA7DhSq@E`;GYu{l~uceV;cHizFBF^x4@qjj8%7$z6DqZ=tmRJ zYn4Se(SM$0@a_S#vFz?RWz~UlV_84-%%%RxeDIWzfz7iq_fucyxOZ-%dhhHF)2qtH?4S4x|93!m~V zbUpe0@Tzoy89PmbDRoF}BUFdr6skkzd7EC}PTIFkv38|!FI%0o8~WKS_x7Bf{OuQy zfx|X%NHI+C6Q5nxYM#EbUT8ac+-Kg2oxbwb*rd;#xhmFCuUeq_xX-kzCTpvTT!QDC zIm!mXFAx0I;2$3!gU3U9PV}zm+!OdhC(*TUAPXwEGfwc~cXwqaxzVF0wW-0RnCeoX(I)r6I%S2&rpPiY@e-xa$tvyL+6n_#|bzfOA+?Zm1Bxgl3NN7%hK{ltIsDpx0+h zxtP&%drZpWKTuZeTPd`0lqZaoiIsBLr;N|Xd}cOf=SW%F6{=Ipw#F!n|3jA{8Sgov ziS(n$5Of=f14i2oGxG%hTmB6;`fRb`)A=`rlSb`EHabA;h8-CaSr)rN+-tGOuh)BGXyi}*uQkL1llZZokdoA{4W z+ZWezFJv8ZutyoXsX%-dWLW6-w)BU{Iqwz7x!8t~obN`CBjg;J6*(8W2W5SNUwj#G zNUYH1dp7NBqJ3TPsK{jn@-1?yAU74dUD=KNRa6D-%4el4vTK5OwX*PrAKr|UvZTjS zHb$4}3SFkVI@I`5+ESs*H2N`7gQ?5oEO|%nDtLFnn|1ngA2{S8+q;qNI%K;7I%Jbp zNPG4OPb1S(Mr1k>7+rcfk>e0Nk>e1&BA)Y*=`LhC9A*pUD}nih&a2@*jnG`)|3B0B zqRY82%1*sj_@D$n*sbw^(ceO!J4jzeTh~HQ@iBxC#K#EdgVM|J!HB+xFLHsC1)Kvq zAB6OL9ef~qUi=Hu^TG$>U#R?t^t_}A9~{v6Af)Ga>wF;TA>H0fUxu&I!{7{@8w?3_(&MvmRG=J87IJ4ue5 zyDc_dItP5YvORj)uM#tsv1w@j_ek<5z~HRg@cIu%)t~c8^+%O`Q7^kBs{U5$SDenp zA_t1i*{1#9qQ55w-(|hn2VYT%-v-y5p2F9W^X(m5T#ImwZc0_#m!`8mu#k0O_#4`q zun)c>>zH2A#^;mo$nqYzOF36fAGAD>veM05ujtJKS<2oM^wZDcoG)M(Js0ldoN|le zxqp-5b)(m1{Jo2Gp_km7Eo;p}aQ~KINR;&6is2_}Z{M14Rv9ZkyJvmMWQDtT85_kb zFG*Wcm`Attcx>{WZ*5L+mG6qHa*2G8Zd))uBkSQ*-|Gp?FTeHR3$m_t6TB&LuM}HY zJHDVSilH4X6Pz!YiPuX^YZJW5-ce8c2M_ghN_z~>7sA`KpY%|BP7u@gQAb6|4KIba zP4JRDUfOooUCNHbv+MJ7z`u6wv+H-qRMOU9`>ZRJ4Z${yu0K_{qe%M3OWh{!QDd#m zw%ol59xvqz=^N$Aj-@W4fl1N&OI0eDhIla=me8&A8&R?st#vr(6 zRld1DTVj*?(o?jxv(KA~@)mb;M?j7AA>aGwme|b9KgxPR#_Z4AtE`^G$a?yC;sPpn zMESPn+h;$Pe|XED_2{kVQ?7z1%*sX!Hrm}W3adrh)nWBSz~UU^a9F-mTP_bPZMlZm zA@I^*rNuaNC!tg5ITAyF5;r85m-x~T-aJw4Z<|{90xK#z=4WL=j7);ndY%itjrf!xx|B5OC;?Kxch>z%pq8PQLxll?&ukXRb$z5oJHc#dvAYs zkhNQji?_ZyXrKMgAiNgHcHK5Yf32Oa*vNJk#YWKVaCVUXjQ;_4XkBp|OUS8W)LITAZgOoc_>W+IT3oc|GlF%Pxv4UldioDzdy6 zUWh2)5mmk;s(fE$`5L``Z;W1l+7~17Pn#HtziVOy{-=EPTKzSl@>LP#x0$LU%45GG z%hShFew#N=ufH#RORVB8&$@kI6kv3EEn#O5*O1r03 z(^J2_R8RF9N^C0S!}V15l%Sqc_~!mC@d3Vv>nW#NV!M|#(NjB=NIlh`64X=K^OYOX zL)+4?$_m&!?pSOIRBX?cb?V&dQUm{`akob1ROOrj+aS0$Pb#rluI4To)j8P7_bbrT zZ?#YMn8&e}KvlblH~4-_`ZDfk`a5xmp7P-*xTrvM-8Or-jj^wDP;|SgW3s1uu)6`zP7bCKJW)OgP&_?@M1FN5Fi zaQx=SkK%XE_CLdKKKNB#2ES=R`f2!8j^fuJqTe=nHw?cw!|1me{A3xb=?WmX3ba`Zg8a8;0Apq=)+U ztKqnv3&Slf#*;xl4ZrcuR>3bFJ)fP14>MkAm3}RlrQ??r)g0nj6){$Cp66or|Hfp7(1h2bVR}^mbQS0owi7ygxfmj+r_rR z@36<}sH|mGjw$P=X!mAhxq`ONFfnNBlrzP)7V?#hVe8V56pK$jYU_?(YU`9&i)~+^ ze7LP^87S85YHC-p&3#k}Y~y>ltt&hXT++nW{rTgMBYg7C^TnD^Zd$1MJey*Ky%-rYJA8yrr-))h;ZxEh2=&$0-Tp8(0?7T9< zUp>^K`GwnZmIwVp@7z}hbLQ&)YF`kRjF~jK>WhMic@Z%OZV#uQp!ThTYsK z{-N9T6|IdUa9qg!=(q#_CK8U_v^Bq0;LL3m-+mO%&LEsa)T!aKGYU?}ln6c+d^A66 zqVA`u|Dxex4z)*}8i_~RR8MVKdvd%%KkZN}hlMR>+`+KpIu-3cCfD^c(E@CZ-f{7qTs1X zk-T_H8#`?~^z0sO?Bu=e)j{v_xAn2pUBSK!wbPXp+0LR!ST#Cd7w;JZ*3KZTQ9g=- z)sYmzM>#ql9SZsD>c48ZjFeZCBXLPfjwp|eX?&Oy8gCRul`o1aUlmzC#K$?I@kU2f z`HraaeUarwo&I7bEmZWO+OCBkeyGqW{jQ@)Dm6FW(VazBo8u+-45ZU;TPy z{VMUr@bYQXBk(_kj7a@8q4Gsh<%^=qS4EaT6dW&aI}|G45mmk;s(fE$d1N8KSZ{l{ z4K4g_vF)*MvroNCx1q|_nhl+CMbL)Mj}6+;)ZY}_{*!#G#;~E)k4M?iKVE7>3%3{B z?x%dX4edM_w4s$AZ0H}AzyZF8+tBuH#kLcqi48SfjI^Qs$AdPsGfy8co?3?AUNE)~ zs*iWXwx%8^9vLr=jCa;Wj>p2sJGVX%9PiXHKW1N%67oThnaXURYP=)m(%%QSotME) zA5&D4Pianx_K%Ofm6~u_|2P%gWK5yqwl@s7w1iLek2RdsTkzQn$EH_eaGayzq@<4E z)Ph}P40h}-8@^-M80;schsIzZ5r>rVp@vg@>L|V96Is&`IldM@K^t4gD{b1?nwYYN zTP(O0eG1$P$HFbLFT-*BLpW|_;kel@!A*RRXxyslBU4A=h};L?Q%8JYt<8O@5ppkM z0taJF@n7pGuZ=6xiZmGFgJ>|gn=s@@YcO1C5k80+n%nW=@ITsQen9dFZs}D~aH^u< z>>LA5_ZV=NLhrt!v3WrsUuwM2n>NA=`uOtLTh9~o4daFI@#O~SEwL7@P3O`^d10^h zlJR9pocQ^d##*FodJg!xR*#LJ9xu@FbIusSPmdQId+Qi6(J=hN;{|tw^TUc6qxf~l zUJ@_J##f4t7ihSB3EXyG1~*;r1Z8^^H(l=>d+Ux!+`{#aJsh{aVYsb`{q%aL2;9`W z$EI7j-ce?b&`pnJ9D8dW@z*fAg~u`s;5MRn;%AQ1tt{>z>z%dWRP-ruDjWl+)JR?n z$LYU_D~{k)7KT%r^%HRl%JAJ$GCea=9{XlS$aIcA&X1Joe~W~Xc1R7FWLt_N zVT`Hcc1FS283m&w5=Mxo-f%qBZ$#puUK@!=+O-jF5g4MkBVZIo!6=G?Q56Y8=rN$j zUqY zAMQIAW)|C4k|w_6#`BTBW9O!z@8}-K*+)`$kz4BA&g_Jzd2bJ*#zk*8HDhTe==64AR@K(UY}dvd%q_4vz^v zTg>f)nP#Pp^(KLwoyCg}F;6YA7>$NI?H-2?L-OW!*gbiC%K--K+XJSh>=EQ&%7@c5 z_5NbpSHRmDqUjy@eb8w}bC9M1bC5@S?<=-7k?+_TG_9Vik2RRHm$J?|#kS~q`$E!| zQeI)+Uh<^QF1A$>XGuG4^SsD8Qi{w^lU|e&r1OlY+%{#~t${!5^%s&}LHXbw{NTKP zyQA2)i!`BmXFzy(bZvsb>g2o7o%wtXuS)x+cr}wYB@C~^^kSQK_Kh;pv*SbX)$!VS zT@bI;Pk`5sTLUlZcr}xLXB1uvX%Fgn?HU6w6W_z}YM*r}UcIE9TQ^Ft=4*;=F76{w z!zcP?7`^&t2JzapJxH%Dq5dNMGf{XsN&B*n*Mno=mCg5Xyp$Q2;+0BTR~TNssXD#d zV?5bm^hzUL`ryQtAich+X7wd~X>8FB9Lx@oK;FQoMReyE6>0 z=E<5oZcA&K>G}QYQF-i3)cLC-NU!%zx;`MiF$ymyX}{L-dSmEPdCcZ}I9|%6OYur2 z?K5F`^~P)TdOoc%-t&BrUfYDP(n#0%>wzG>ey`(|O8Wg#cvaepZ9mlU`n85vjr+cwTZ!Jtmh<#-*<--I%R<(Z6&jp@A5%~CIb>44`6IV&JatrZZU}rA zacB3xQ>HnWwY=mjJny#MM!tct^-1jkw{4w{-wR(ZXp}?4Xxhbdag?3U9rV`p1Dov_e=KqM(vX~2G4+${qRb&(~FPMl^Ijx zFJ`@+>>(bQkTsOVKCC;3mpyJbPOi(iSl&}-Rra&4v&;WZ`3n}#J}O|{T~1X^gPZ|m zQZ8&?G{3rGgMqVqvTj+N@?GVe@}%_!{`{ z8YGQ<9*K&fZkEv9L?f!uMjqa>*i~kUJRh^WPJ@QiSwYaHu zKQtKXuB5EnKs#77sIbP>p2j+mBK4e+_E?lFyK>c}t^&>|*$h7Ri_3bB0LRXHLC2Yg zwl6&m)+(j@DC@DSsxsxwrtaX`8&+Q?ca%3H z2j=>MAz7zbvo&RCCwpZ@F2225@!rpxKiS)uqD=Akk}rHe|M_pq8qMFd%%#q2V8-; zP zwT-0jbp-}O>8za_N&m4c@J1+|^?4)dPr3sC9ZF9NOW)!O{3(>qTEmh2Rj$DCP&(@w z-S~+idC};1zl-xxJ6aCeLJuNJKOIE-eN@pFxNdBs1p>)=(jHIu~3e<(tSz|Mj{`suHBcXKG1&yRH&I(k7($m7y=VS#ohSFJw z<&LItT9!uRbsCLF&wrYf9UMdLJLk5^p5*&hvkx0tsWwciGgp0mQO)obH!4*HL#u%u zz($0h(J20H=-kHO;c7_UtT`YSEJcH5>Z+WC=fqKn18V^eQrZwPC?Pu^nE7=N5Jn%>M8oVxN&|#}*hv@5d+pf}iRCrf-)IC1LqjGM?WXB`q?Y|6dCtf_dJWESleU-a znejn6D|`mO5Ly-p^SZA>E+rx}gJ_CjAq1Rw?&MbT(Zm?5S2p`%=yk5SlBT^&w|+ ze?iB;otVU%YZ!ZsLGwqVXkPdOw`~seJrqXs_V2rGcjz?#&Ob@>%1=S_LTFy5s zBAVCxNAz)!*AJ6dcs)H#AG>s#%RVxl7TZI5cnluDtR61SuB>(2K9KV8_O$<(={!ZJbN{3Nn9l3|m+0I-o>*~| zz5AcgdAm+$XO-KwV3f|=!q1`ZCJ#E~c_n23h)ZmYqO+53E-xk9+;6qoeTe<>^@XPtdXOpQ7U# zV^H>+*SKw4EIWN%iNA~TgOuNxVNznRO81GFE-<^NFMnv{QA%EW1~*T!qslu&6lC$ zU&s^U$J8RXZF3YID+}GWpXhXa^<9ZC{>u9y=Sz*8E2hVHv^d)lw@uCpmRL_EaNWcx zQaJxW^pSl38Q0^gqXm4m zI1TjBWT^cReGd#dgSgU=sqF_%C9RM&lTx|e{c%&Lz^d$Y+qy`T=R&@}%5yYqiG|$C zndg#6`JLPLMeFoU+3V!49_{J#yJf8hQd>ElqG;g*=;De>@) zjH~5*xL{09^%dNroVy!b`;e*M{oC-AJ^VOh*;g@=ZuH$i*@gTv6=kGsD86(LF+J{H zaGcc7w+ZJxlk$zH-OA9x!pIOv9|inr!AaWV)^);;{~dHKxEi) z#HpRJTx}TonMv&>-Q-WhpEk&vF?5ybwX3;CP)U?JFB+5`=?@lew?F9IejRD6(P1K2 z)w>>@C;ih;pA?&^hi5mjdy}2B0f*Sj{Bj(7_-`95Cco^D%2ulzRt_Y zkHp7??x~!s`fQHiK5k{oZ_H&z&RcN!H|3vxW?TN-DNp57&XMCxtsA)U7wi3f4=1cy z>RZ2swFuAtx_SLOM%5v0yyMo#Z0E{-jcFgR?U}#Cn!MnlJ&pMv-_x_=x3S4H*&jdO zmELuYMd>ygjCD7b1xfT2~ zHl(a{fQR6F$n}_w`nr)7&QdUIbQC#B=WH60MWLgEGlrzUs~L0HIg1T>+9>oAdI+mxRNe1RLA`IyaKZb`0%K5MAUULL>F@rWfkZ*fIWE%oiDz5-(UmGkq? zqqkPAp^ggT-Ieom&r5%mQjbYZSR zHY@lvflssG1AW(O_{8wO{JhY64tehdr_=DAJyG#kU31_qtAA^`vO#!H%9`khU^~pT zBj-GR^D2AU_wrAJ+o50i)^7zjY1bKGm>(28HumiPnzCWGJtlbo{7S&D7T(DPzvX-5 zlIy5*53~y5CiNVko=*C+g8M0?Zv@W+Jg1Yk2G}TW-))pzvsBqoLRk}dO5aJ@3jTxg zVbRK3b(#yki3@JDcPR1cHf00yrqQ?mcjI12XU;1JRL=l5jB~jiaz=^RIl|O7o`b{QeiKlZp+^>z8lc zoc~bDr!|`6YZ|QOe`}o0 zZ%%n~qiIfZW1VW*4gc)UDF18YnVXuDns_&<);df3quBA-24DS4>rEHG)?=AvNuJ8t zABP!t_oMe(&~NZiX$^dmj$Y0{@1`r0x>9Cwz8GgE^%^Y>IT!tEY|c*O*N5)AR`L9f zaZUg4x96KC1ZBo~$zccAOm(W?k9_tTr-G}+aRPiF z{aDABbCu&a$HS8F`&OFXM!wWAB|+^@2`GC-{)Atd19ix` zJYSiZRHyZ;I>n#Cy(^lH)Y>$K^I@&NKPrYD_ZgQ=L+J0)0AQoaPYu^S`BfHzH3WgHkSowq4k* zcrD0}$Ye+c?Q?vMB8MV_Ka5inLh|;3@k+-+^u`UeJxNWk>lNJXJOoylXj?KV4|EWYaehzLp!pG z-+sd)aFOz-un#R0l!bCWcNb@7K@W!&I1-0GgB@LCFx9QamWsU#e%gZ4T*spOz*lHk^Y>wNfWe=NEq7xhtjOMgF;4T*g$7p628!YAi4=U{ zeq#({A~|!;xwz@?%soKorZ(oy&>sW%x*yP2>69-}MNakKj`)8)Y6;zDat8 zAx>LkAbLpnO7u<%WrMmS&i758rH`DHukXF$#v1xo^5Fw6X3RcCeCEnwRXc;df0ACgYLJW45xB&_!_-P7ki%n8Z9zisSgj;U~oQ z9GIY#6~R+(Lt+dL3L3~6&pu!cHcQ5^x&N>~_ikr3XcOxT~pVa3Iypr)hSw8|ZL0Mc&Eb292hUg)6 z$eP|6vpO64-!i<=^5m0)IS+O=I#}CcS1S|p@SQ4DLq-*JVw?$`Exz3H&c;&irCdY1 zbIEtN8soc-dN#1?@3-6r!SlyBS2ippvE#ug-5_~zcQqz#DR&%eHa&FH1 z5A~#)vK}~nT~pG4dFZC}>PPbnV#P)`ulJ(|-Y(vr|D0O!LUy?+`F8xebH>>|6aL#? z++e$LTf+)NystogU@)I=ugp5!5NGo=DCaABBu^>tN@@prjJ|yGb4QWSLixM| zPeX2eWkbrBl(H7i1w0F_pNH0a%a1kA|2V5>z9rsz&KRGUX^728OIB7*WIk#S-`+tM z>sce^F~^L2KZ9OKh0eq1pwsZZ_<6bTbxUePKIf6num1SJdO!E7JP*x;Rzf$8R^^E+ zC+hU-vi!)_kFG+GehOw>93~r^L5|#~u7S%H#1_ zyBlqWgxv@EPk>(C<*|*u#+i;>=vS($yN~kkTDXb6jo-Zjn%J&=rD6Vz_J)HuY;Blp zu=(aev(j0wG}uV1Q1ELFR^Pm9UTLr<)HU3}w_N>OKIJS1i|-D;-JYXVMDv0Zb}nQ}(ua6l>R=Noj}E;M;3?O4MB_4`c>>Enl>YwRPt2iNd_X2qWdTc`h>F~E_=dVY4&gzn-)oWlO(@%%;VdYdz1 zg;&;lTor(Wkn@yRLFr=nB+#sptJ-=sdl zrHE%I`4)gjTzdRS-7d-ufS=%5i2o?hawahNO%3no3Uu|rqT}SyHz_yvePtJVwV<%hr zCivy@e^k#WIw+L46P#w#wwzfp$(htE{UNy6CpRTIUG};@{8Nc5<@zPCANo&z>g11d%m9l5Rhf8qdTj7hn z=2*S##0<_5*UF|Cf@R;KtnlJdbz;|7ff2nf_0$zFZ11NZB`%rs-^T`v$Mp^tD8c(S z?3_bzr_gQqvEzq+xNq>#bKS(!M!%c+zC!!{z2i9(cMTSQy=$cGDf|@C6Q_nBKb~{c zJ7}KSG4kyY-tD9$^0$}sw^hHp2>w~D8Z7gzZP zbCl6<#eAD9-!h-f&$;iX>qBkGAw6Bv8FzYR+!<;c=`$pqF{N3?lzO_Ebd6USQ=XDB zrJjBYc@%q|bK&znncefw$(ZsGX)>nFxo}HQW`|iz^OB~GDW96Cz1Q$=B2PiRs=XKU zu8k?#*Jz^OYa~)Wpe&XohY+`5C8{Z#1P3$c8#KZaDB8HcZjo*gvY`S|?~kQVbLQCen@)4||Ss^{(sd z?tM9B197(Q1L%9fse=Fh8ztr!tCg$M;%Kq{Y|`o}XN4zE;DhhM*UoE%YC`0 z;pw^1`z&LWJ@EEgX!kaBe~0+sI>sv=eY~>Z`&(_<4?f#yg64{OVzT<+^Nnd2?&(Rb zj88TayKQ!5bd4LQbT1=@Jf3?yB#zuXZ`t|m1(9*&&iTPO@->t(LR%HuE+dYdNq&X= zo%5Ij(&EU(BIdcyXUjWr&NGpa(BbSG4Rb=cuUI7-MZCQUmlw*vGaQP zsCs8?ve2THcA4NKVlCaBjIArwVEnli9y-8tb_VsLuZ0g{wYaC%-{RmInlm2K?g9|} zW`M7WSSEX~%G?HJ@iXM_BBp{*9A7#?S!@6|i4QSmjQ4^=6Y;^~-1J3T$X7E#S+Rz^ zBJ(2edw901iFs>EG8PdpjnAY#b=YWhy4IGX-=i&z?@F^W>SiM+^^EPdz&A&*8x=Z# z+zYO+^PD{^7{3+#pViX9ANju>ev#OH&5z@f_edO;ap4+xM{r6IJb)*3Tl4T%o11!S zI_z4kUf_TeadWfZjr?co^vclEO#aTa(RjVwMJaP1ZiA)nA~17lTdr!%d!KP|P=`$R z*8)%Slrk22k30j+!Bvb?%JOJ$#lPS~(f`!BFjr~6D>uIVE;$!J7oC%<2H$hlnew? zs~ozns?~MXz3@^3GMW3}VdCX?_2ikYjcd!D+gs^_81z^xva`E2Ciz?N-C2D8$LMF< zL-8xE&rVD(({+`9<5pXlKJHiMuQ;DQ^-?|4GDTS>i#A@XgU@o&Q3dFzlf*sz=qRxXZ=<7jqoasT zcZ+Q}gO0iv9VK*>KDMpfYRi3aPb2fEo?K|n!EDJZ9(tBG-qW+-@WkYN(dP#2fSQ1A z$v^KVPVCg^!rqB_+2`dh4AJ>cowo5=^Xr^%rfd+pNni9c4ia52dS5HgyYxeWVnr`m z9PxcA8<3gqevx%>C_pZ=7~2*g|I5&|dAiKJTC&wK}>Y-aHx~{|Na7G&=>a2haL z9TM}|0&dbq19u+fqT?**QWgoWUBnPqBTI$oQHevBex&XgmHEkaX{wbtgDGNPlK8q3 z6Vlt1XSzn&AnWgBTrPcFSh@KQ$rHR|i}S%ZbEoKd)?pFLV7@5O!dy-tu^i^u9j{Pd zGd>XUp6C02%J`Z*yEhjM$()bSy$D}vAn^2YYj$;hNy)DU{rGCWZ}$w=PJM%MRW31w zTOZH4m{X_BvNmdWSG^LvW6K3xMPVHn_*9*&u}$FY>o?A;J8sERcG$&-kh4tU+y5f| zglW9F>!h)|L8U(~US>a%+#gFUN;?BweCQ{LvklRw?-IAJHcZuGLfloiDrKW`ZY?_X zgX@%i#A~}ZOvtWF**Wo?tf?^J!wb!dh}#*Brn=z0fKz;bM_(Qtr|g(X{br+cvD@HW zJirgVTzZf`Wge$g&WTM$_m*In63HiNn@F=5mBpt>Gf}RXGQ`ESyiW4ENjLLd=FW?? zJd!sE_XKbyk9_avo7gSs4+H;FkHC_9U@gEU?o_Jbuf-6FD1tvI3UQlK zsf*a&MtD8b$Q&HFSt)Cu;#`zT%<~oUIj&H;V=fjfYU2GM?*-T${7(L-%DyP>pZ;OP za$pD?;imxOvrO)`RD^Z{i=VVl_+0X*gS+70%snSTJ0W+?P4;o=$c{za6~`TP4(4r$ zX(wvw%SmVd)=du#UU5^paZ*=};i@j+`3I1n@bV{FH}Vj3QUaqIJfts(t9pbEo56+H zyT33gNCRn`_z5O_4M~?hSg%4u3ukEgp^2m^SBZU`;wuG?g*yy|Zqoj#&~rBQz%SJ3 zlVaqo_%rxCw8;St-V>PuhYT2O!I4!YWYT6HC~dk(cela zBkf3`4aM_olT1~$%!|@afk%3=CD=zHc*W!|!MBro1)lJvDW)E| zbHk6mkbV+670+>M{Sl-0RTF(sLm$-B2SV3eVA_ERZXWzV=#c0aeIYdMg~!E5GwU!* z_-=t`{pfZ(|NY3CtchyIZdj0QY`up634CzwvGc7p#MCvJmA$)TxhH|N-T3UpG`gjY zGvVb@zL#MKL42k~25#LQ@FOgXHWGz_suaw2SQgEN)?+r@g<@OlbLwfpR z*5jh5MPL6@x;i1Kt838HqOa3|Coz08@{oB(J$GB0vg$k6$~pm8kLc{o`#*PXgT+#( z>Ad$J+I~5mT{Eh)+u;2+^hBHV!(mOQAycC|yDg-%YlAww4V~SFPHRIp+cbV9-5J!` zZRoT%U1yU=A#V`w0B|LbeDA0H7&^O6*V*7^A$Y&X+{5b&-z=-tL$q1ur%6ewcT7cPyQ)!5Kqmx1qDO_SKH+Y^{CKI=hK^ zk44<|8m+URBwcj&XFr9`eo%BaFdhx+>^9c-X*wHURnyt+`03a!Xk#tiEjpV!nL;}I z0CHjZyz&w{8+_64`0u*TZnJ#e`I690+CLR~&W0YMvxPpQv$KLayA7S)rs-_$9^9bK z5uN>IU1xt?*Vzr|Y|+1>vunovXdbkQ)Y%6MUJCIA^cS7oR&y}rr5{iRUBGj}OB&B~ zptJX)v-yS&)Oe|SjBlk5r#%Jyi}#|hJ2ZXWb~Ug{b~)`*kML|p2ReCgbrR!ncv)!^ zIP`UC4(ZvXOZ}m|4m~e=y3OrS?2=btgwh2c>_l65dGuME;CPR;;ab55`Oxu4M_(2W zx~xs=8M|FBJGz+uvXqwUZ7ZFjj)~8jxh{JNZIyl$I+Q{O(aE`c(a9YWYcrLuk@nLz z(aA#B8t^Nbq1cP(s`i_}djMTr3hvokL_SQVvvoR%Y}D+nORDb>J#PXR^f2Gt3%FAf zo)A4;daYt_M+et1W;g4wkk2+NJSg+7cK-W`IaQFi5*;jjiVv*eJAl4DgAU%qUhk5U zIWML1USf!?lR2B*D&a*-X$HJlf)4io5B2ZXPu9O(%$uLfMmGts=DzdPx^(nU9sIhy zxOh>iIi{`ttCsC4Or?Kat-PI$h(G*t!GQwpX!j&CGYaiftoy)Gc|$w#D#W?zVgj+6w;CUX6cs z+@+l+@G{e`^fA6!C}ZWD@TvGr7TPFu6gqtc{7rl_lP4UeIR-ib(?lMDDSQ?3o3#44 zYtL-DOnsEK@-0-K_-JO6(9XFSdX5RtB4xlMhH?e)^QZA!tl$=_`z_KQ3$SB_4%8Lu zbFFO}E~7rC;9()p<=Q6vQ9ye`KB4rvwDq$2ffvdzK9ELR;0ygict~34Iq0j8uA5G0 zov>Ma4B>UL74W*_PfyL0GSR#qg5ihfEY~>g?n`t5J{kI@Ueho5WV$Xe&C`6cHjR(3 zQS8nj4?Akn2g1Vw4?ip(zpX739&Wa=MgyH7{#mZ38)AG-@NgwO9D`mc552ZbqYcIN?EmU53MXUecM`1SS8vk-HXddHo2R^JHevo^xevdv}qv;mG_g4H6%aZ*hvX?)UsN@1d<( zdK2Cn)XOcKF6E4r+nls~L48B(d{2Yq+f2;u9P_PjldnLH_0KaXi~Yo(=7Y=g;IbE7 zVu{_wpvn(`OC7u{b)7NB`=tB~c)g2yWZg`rV(|CUUOVkY&OP*pXEtzTjkLs<=K?zz z|2Oz6Y4@|hnTTFt&Zabr_NPFv=b%px-;wSa!bR#XIC29u1ett-WQwcZ~4}bzc7b(vR|c}xn=NkF3x~fVk<@8oaOuVv?-px8dl@M z)stjiP(xpBZFmegGUht~uhdhASB zGvU!@+M1y%U9+jTlrp8@G#j`M+AMuu0xlVpi%~3fTllB0Qdy@jYavd-A4kYLz`i5w zdUq~)!}Fbl4!~ag8|updzO*fepUC<_`Y%&p;j@T+75SM=dnN54X?D``v~;ItuSG9O ztcpHfoGtC+Utr06uh=)iSKdWm%G$h89@Y*xa`_hA)12ZEo|C#x5pNY4k>?W16##z| z@Fj1t4$Bb+PwJCzcG9FBQqKt)o5U*dX40j88RucM;sq`->-ZY-32ezLZ4$V({EA7- z)zhU-Ii!{F6Z}JU9;6Lp)tN;)d! z7&ZMBri0qTbL`Rg+4q0!i>!P-0w@W#6(Lr?43+SS~L0y!0sV-{Ut?MGuL#^<8tLR0O z=pu7S7qx|Skpmu-z4;+sq%a3Co3>lH6WN-ocO~?At zM}xXP`a8O29%G)LEEgI~An&6|d!P3--2ME+THaD<@CIvi2Fcf?8vWa(ZfI}~b**FF z)V~c?yl6xpSFkoB-ZZXG^s&G@$sOo|i_l<1AK^RYK?8|#i|wKB+QN0wT6iN&7qyL{ zi`wGpD@_-5po?BW7wy$_QCqk!sxilo>LTblhAyIybX{b-L>IL&NA0NqS9DPuveg#U zMOmVY+E||()HNneC$))A8o);i(@AXu;W{ZSpFgOR+K6*c3D?Q!r#9re4H?vYk;A%v zav-0`cbn*mkbXK$8nW4jej?qe`CFo&a!E%&wduM?gQe>ytqlTObb;`GD37k6+Wvul z!uK$j)&f5l_{IDLmLm+F;3MDcq*?TIXb{p*TK!|_r?wJ3?_ppI+**Fcq~+@AxuoZi zR>Cj5&ci|dbV;4Lqxwm!^B?J_GsEv3?=v1~JvGziO@+q8#A#yKr+7e(Ie$0fYk!8* zJ8ZQ2Z`ab|&ddG8YgtqKD(g=7@Pj}0;g=2MQ7^W`pQ2jM3l0ivb%vSG5*;Y>C86gE zbOia&TajhSuc*1_ds(v<`raSHC&T4Eef_}}!6%2h>EH7u{GVc->aa0Jt0#3<(7#*9 zxkNU@cNec??%Z{u*Cch?rYS3(7Ya-%imkMWesEogH+hDKZ;)?tN1)7MrQjQ}R^z$i+Q z{J8z%tBseE}t||^c%I5C}kJ2jDH@DT$*k$f)_*Pr6>^qbN&+fC7IZN4f{I8?zI?8&gCZhA= zwX%YHJ+Nj|U%KgFgWzm^#L$Rb>_hIlO4$!0IGe9Iq~To(Uo8jM+rf1r|FQfRn_q31 z*BYbYY$I+XIL9;3e~x)3Yf zySeSo9($T)!BW1Js_x@4N(*~*t-c&J#%jGn*^f*mu%E+v1K%^wez=`-e)PpE^V#R} z=aH6saa~WwiSOl;Ub;HS&khIaF}>eQn4|O_2S;nh+3)4QW1Q`n3!lZl?0k{+ZF$e9 zz1q+O{~n$7`vyO}G@JK0L!9rON%al&@mm|P8$GAtYvRu5y3)ED?9il@-)U`~=>vns z^x43qEe*Tb50^vRb7?zkOnnu4`{DcZcY_c87BBWLm$p%_4}G@ZL7RjgCi;T){|W33 zawzI`(}$M@^~UfkS6GPyURLFir{;S8aCxiQ(Qn)8N^D$)zn-u6ZCV^wJHoq#d?l*{${++qb zH*a7~R28Q=DuL53E zeJ1uq%KmwIo=QC(@cO&)IJ?Y`D_jj66O*L-C01`w$(b?b{-)dV*8V*jw1o{{9*R zV~jNB2{#d^8>cKBBCUCu+AVv!zE3>?@cQgyw+=C=-e+1SI41!o$zKVLJ_4q|?uWJ& z#w33`yjJ|!=(&TpT=-Z!cQBQt6mKRx(QN$dk^{!%p%&v;hYk$i>{T{@ zZ;9zvC2)%UZC-Sgj1BFqufTuZ-wjRrIe*s7dnWT9(v~W0n2fXgp>^VG%e|MQ)t5hk zR(by$w0b2-tK9!fS_M9eq}BVpkJ9ST(CR8^br-Z+{7=*BLul219rGAw(~Z5mOqv|d zw8Q&fa0XsO4o?}(p8j3@bUED584r_5Z`l=;!+prWFApl7U(HZGKRXzd!xs$(&(D9N zcy3KMV&yXzcyp!`yhQ^k~8>pvU_zQZa#476x>)A{7WmljDyZ>IkE3oiO%KrY_ zU4h|zHPElwRAT+Pu0X*?`w;q;7?{~FJUaYkzL)6bzTpb&lX9ym_l>Y}Umv4fi5hsn z0s4Pg`sE7x1^sxP(c3@M;4z^K`ll$YQDP6g>U^P}ecLT3d6sl^WB(?Lrym_Fesymi z=R03dAETdyw$i8fuT=K!tX<~q1=dOSWYx@3cF4P?Lz10=M|hWSJAwZ@%8Jf;n16-! zNF6JK{fwS{-jsH|rf0RY2z6cClEs=F_5ioQD+>1~iGFJ~KE0%cJ#aF=yzi*X+jN(5 zt_59D%^JC0_CmH8r!TVbttm^{Yj}tBIOhvV&`@;EkEt))=zL+{=FfS_H?)a0E~1-i z2h|;M5dn;1v2Mvs}?^&MDHpo2LzNZq~QX!YCv3X1NwO8~=OBfr`(0 zU5`DyB+q#DkoD|O^K;qfpUeJz=jItyYZ*sw{y zpMO@_v2XKNhlc)hoVOpGo3K}@tn>NvYSn{Y51hiD$y^=u-S-h=a^~j(jDPow?YNn~ zC_xu9p7NhU28BOatFPsi^HSiY0Ou!ad2`5{&O2iYKkHYuye-r#^Mo#N7FspWEceQ~ zAL2gULf^l+lpWRBkBrtwj$6O^^577>W_A77pt1+1C?=u)@K0U)UW4bdnb^3VfN|~sfdj>o?L!&#zXd39pf0H;_I((o^O`C4{ zi2d34WoE_xwCIgVoCz-cBD^8IBJB`fY35zld8F$+BJ{0*2H49H{EUt$0q&bOt`6ZIjli-i{fHr}?_ic}@Rf z@QS{z{8!eyV;3t*6>r}QS(+>euL*CX^B3)-UpE;><>B+J6={kiwhDg=Ezn<@JWQqD ztUnKHJS*R$dG;CBpoh~m#IyaZL;ob6Z2@jb&T5&z2$!>I$XWFjK{@-XE@w^1XHd?j z`EJKQ5LuT#ZK9tJ3C^6wU)`qcujDNLk5>fO`uAe@`*T(8K7sFXhlY&3FWjyMPLZCu zF?~pQ54f5?&<`y&J~zW7=s5@c9MW~6Hf2*!9X!stWVN!NF$*7GXe@LQ8i&jBGwdNB zlP;`D|0KG=FNp>4g2+ss`ELy+-f4|~@I4KFYc@KDh&2Y->%6ZXJS2|C`9OhI&iS9K zDuK7jceHrz5c`M%_v-IQc;C&lA6sz-yTcrVuaxft%<*QRkJr*pO~+7Qs~V&6=>fg| zXQ}_l{%MT|ur;aZU4j4mjcbR#bzyk_p^bBf&Y*wagGWRBBDzInNc5t}kLVVWC6SL2 zIRb_m8IrL?I(WE^+=&2w62}~v$(W3^f91WHbj!vY@U6c-B>mz=$JoIY0fjd$nvTI< zY4~Ph`-EN&$TX3mDJgPY&S6n(zTmi7y-Gzn;o4dc7x=Zio1<__F;ote%0H z_mJ=UN8Ure>s0($@m*h&@i%v~B_OXu z$aD2L&QdR$cZu&>t^2Okm+@V{kMDXw_g!0}eAff`t|xxTSUt>l{oszE@48?2U3cle z>tEkdcU0lKrsKQzrBp6OM~(Qev!PpGO8e4xHwS&!7dMakuA)0k#5MZyUHflU0x9^e z+W4FFcg5$!C#&4_$`TWBd+~!i!{A=2!xcN%4?lXbZ{pL|;>YI}jrWLetHh2+2Br^r zH-Bx&QZ;QzQGGo9CBU-7%s@rm1$xHGk0 z**C;^Qv39o+n zFIL=*J^jn2_H;k=-xX$0f6Us71K5RUbUGZ+?P<7w>H8nry=~|&v3o-MCTMv`w|gyB zLA&Rq9njL(3tjua9<+OhKGf~rYV02Am)JepEc&(Pe`@!jg|ts-5pMU4*u8Lm7_puI z!0w^HFSUE%dm8-yq1_{2gx%x)f7R{*FWT1H@RkE2;lGz5}$n$ ze6L!+pvP&ktrCYysLWsc#o;GDM3z!6DBi?})gi-USzeWRx9Kg_bHz#3GoG0DxRZ+K zC&Xfqxxj90THhvo@Yk1kcVRQdw=f0cVvC=LsFo zSAY}3=eIhXvGBP|ha~#NlupMJTeG}< z*zx{1RnJ=|RL|dMsGc`YjMDK==-9CdI{r08$H~5_(D7&3#~(n)kgxPZosOMa`y>6h z**YDSFIDD$bUXAWb|mMy<6k^)>N9v0r%J4f{c7CP)4Zv2NegE#_h#USo{{~P$}!o4 zEM-3A|2)3{KU3eWfdiYcv(VzeF3zK7jMi*WTeG*QL!VjkRj-M-Q*%P)(%!9)ENR~K z=#rLvrA=Z)Ee|Md&WY7anyl&4s2BMc8~6dVybt;dZbigaG`X0Jd|icYBP~3ye~i2)m&H@Sn5mty zkI`?u zk0QRQ?Adtjm{ z9be|YyPaMcCl%qV2%Hnl*PWz)yu@?wBW5VEn>708yXY7xQ^oj8+Otou!_;Td_T4x` z{csok@Mrqr9{S<%Xg@f{=!ai^oqqV(>iwnk!wkJ2h>u41!?$SjeN*U%yA9s^q#tGk z`=O0^o7N8+y(fkB!zABrQby~atF*bjzupk+hmUC6i}b@Epoh?Zav1&p5$y%0(B3^l zcY!_0_a8d!9U;2Y_8pV4G4w(6L3DMMm2*3YE5iShrl`waRyWc&8S<>WoWk7Dz8S=u z=;s%iW8nlMO-8Dd_w>Imz2@^ZwfS?>MNcf>_6GB z{5bu$gZbZIo-leoD{^#2W&Sg_aaSHV5NBT`-- zhRUTf&VTAn<{JK0pKJJT%1Y%{`f3^Hm-4M?8RIq1+^C*7I@eH39oft^NS)I*t6q~; z32f5#wqE7C_q4i0lUK&A)k*YKa-`h;n)XhfBt;}_s)S~eOlEF@m25-&WyK-rOE z6nPG|dA8o>MCOCV=Xfb=oTvX_jE5Mpzj->mM7|FjT!FS)Wc^3XA#HaC8Vpmq%<5HL zD~E4+ydt5-e+WPL&O~UnRpk3B=3%e$rxIhk038cxr^xaj28Q=N3D2c-=H;i+4ZB1i zUq&~i<3CQCRSmvpV0h^B;PCCQSstmhWDKZAJMh) z{a^75Lb|q{7^C;=xvZ-}3g?AtiS8Tc-|b0=_w2SsN;tHVjxb;795 zzRH(10%xkP2{=Rl4{c{2A7yp@|7S8RldzkWMU#M)Bq(YDAqC2WxP(Qig8M=g?Kgnh zDrm)}B&17Nv`&d)!EXs*Yo0-HfhcG#Am7$lw1TLuOTP|a>mdCjxj=Pu`-?VfY)x!6T2i7gS%rcizZxa{(r$5jvan!k$UoSz5Ge#tl5H&{a7 zWfy6wJ2^arx>dIJc-N8IyCC>Sh##F(KE3I_LSxrbjdh^i$DdNS0c<*|r!V!Wjrl(| z%*D*x@0iaDe_!@|oWJyF0{LPR5*w~6uUww#XRkIsg=5Th-J7m+)htSwmCMZ3EewLs|X}w;; zIi~^O>vMd6f1|(J+bGzm4#A8y(6mf!XnTOk@2C@>P0C7te{28RQs(IKHgh!KBy;o( z^=pp!CUgxy*&d6rrNc8UKSdGn#h%=%Pn(=Ry+qrJVL0+ufhk{Oj?aiyYJR|tEcnfO z%58u?Ubw6^4{gF`g*@nRewL{2DOV7eb2;%j(}>fVO1#cx2tRe5dcf)#m#y-|+h% z^4(wId4J(2``jS(W&LOKuXZx|KYed}*(c12kDuaq^xmYr^xnNZlTBB)4EOz8T<7o; zF6vny+EDBa8#F3Y4jf3&z$A=6@hI6z*&BN0s2G+KMci#W-b) zE9dzF=leN)D;P4+lym6QL;R=0?^O2|{OEU~Kdf@#Fx|niY6}jn*LVlfg-a6bw!{mk zSZ!rk=Tpq1&bz=_)#KN6hM!l%);_O2&7?~OF_w+59xdv-r7qtnbpPQ*}Mn zT-Si`5pY=gx?4_d>O4S=VJ`eaxcM1nq{}ZOPmJ)PGxd1!;UBzLpVO_rW`@5$y|w-I zf35G+!vE#K<9*#v!dLH%t%Ck|X>KdLc0YBfuVuXZ`o0(8Gd}oD0({4Fex)BiU6{Hn z0M9VjEqO~hITsFn>cGM?Uq7(9JYkpCx(kQyKTz%OJ4)-=Yy%n};xotNZ;6aEV!6rw zrY%eRj*3q8ZH|;Du8XYc8d^hq)yLaAg}w@E3|Bk8*=w5C(dQz3@)OAan;Xgv#gBE$ zkNo@wGrGM~esl-tQe)%VGC$wUy)@XA^kuK6=to8+>Bjc zk$$dPfDTPR?wDv)){R3ZWuqUg!e#<*7;!2wVV#T`>v`W`Y}~2HFW{mzcSp9gDBrUe zBvvzMo{6opAwrz=L7r)>t7yZ{uaOr17VRtka_H;iOc;-Sg!f~BUn8)G+1Er?a5m@) zba-rO!x_V+;J(hlI+yE1e7E#ioOrZg{swrJ_+Qm&#Pjg38s7~%*m+gxxo2>H5Z*0X z8N_uX-$`FBU2TMx^4-m}S3&sz=Ob$^)=zbd*N-$dE1!uqZ!L59jCT%!|IX}D=)Cm% z6ycw&Ky4D&f)d}?dPx&9xk{BMquOAdXMXrb6GE=b(`_&rQtgs0dRn(?%Xe13~~ zeyxS4DdC^1jPMN|+r_t9#YK7W?Z=c6z6n3?bILCTKPy%T^M#+n>r(J~F7Nc6@LG5( zeagk_+nn!qf8Ns0`Zn#{Oc}LvGJLl9!kMSp_*@`+eaJ^>DTnpEYb@(d5^E!X8kZ_(ed&0?l7v1gK9Npd} zl!T67jr>g~Ry2p72@OQbd#sC22bSBrhXOo1GRcV54+@xiA013g1o*7_>&Ww*(Un}H zUHVu>tIm@lSlQ_&$CO z_)*rvheUhO-Hr>O2k36gu(VODy3Hf5Gi_APgG(;UNjB~g9j~FUNB+mCjQXe8a=D=( z_N?GDZ0lIgjh+{sO`L}Ricyh+rDLPijShKUmH*17YRXh~oo7}I{RL;k`11qnpSm-i z?$3`Vci+VRgwT&Sv#tP+M=zy@GS6f^~r`#}}2-i*#MVxd>j5m|2}onB~mdjeZiRf`SiF64J# zWcj$WjW2`5ER7q4Pm`FY+#V0TRSnJ8tzCB@cgdd*%BHeP-2@^y%Wa!rh-f zP4v^>U?Mu3>RCAS!OQC2Sa+xDiePtY<}3JXxNeaV^igwH$Gp{lQV?sHj&9(@ z&IN$MOkfcmjGuTA{sZRvV}D}EC;jB{v7zyu&}SI;v&la6y(>nApS-)RF0}LG1X~x9 z?gO2Ckv;tE5H$Yq_#ci5m0xJnmcF(01Mp%X^Xv9!KYdZ3)SuaY_yqBMW%MV3ewBc; zviFxG-)5ZOHS{s`E*Z0*{4){gWFI)B^BT3!EqjgVZ^L=tG;9DX(bQ&nx6QFuQJfP^s>V%3Sx~b@ttNF`I%Y%cLMk4_WnqAkb%V2 zp(`Gt9j!l(++^E6N}0Pzm!P?2{&{8$JHi%!I{Ql!b|o!CW=rq!zdPnN;8E?ra@3yf zy+YE1_M)%XCHKyc#G#Y)-uZEVr_Bc@kvo&QzgzkMZG7EzO` z5stjuFC-jW3r-0?>%q?A~@{iESU^%za^E2pRN6c4?o`0(gmZk#B#4xi9Wu?ziJ-(|md7 zehuSu=e{j2rZMODGWX-K1rNL&nsjW%IoOI1UWAO=-ktsK*c-4B>%23`YajEi`K>@t zkF4><2p*0_SNJTu;2!i;!F(TcJbzaHDB+CGAXy+?z59repRt|K+E{0r8phVKbdJvYHupn{~j;qJta9gv5W<&ii}WBf+?H@M{MAsXOXM z8qi|l(wWdw?u|o3TNn7&B|nh7LUQe+JR`VUOnF2e0$J*0Xmw`T1D}7^TB~v z3i$^IN?5y;fCI9jSEL)Gw0^If${Lt)-O9Kc_@8w7o&#EA&P+(!kxRdaJI!`w3+Wm)9ROo(qQ~7N6DLgyH8dULL*H7ke8&%gO|DW(O4) zo3hv-*7EznuP<$vV0Wn_CL=(cy=22`_Iv***@$WXQ;7#Ruc5r+c7&VvEig>k^&;46 zweL)OZpMO_bAZFj*`r78PBUT`P`B(x0dzi%KQhS|yFVeYqJrO7Q+%0X(WwQo*Su!Zo@zM-WlV~ zKfxy(t|ZRL*SBFuKO-hz=Rsmm#WU-exA_V9L3md3&<&$1Sm$Mx5%2byy~nDK@AUm^ ze1{DSKG-+>E8gwKmSsqvVJx%Gm~YO$!Pq6cOUZ&8MvVmCE{(bVoUE=s^Lk?2##ufc z;bGtK0Ps+{n$Ck7w!iC0)xChal~=FIe}%P<_%Zj9k-@J;-^YdoV@=qDx59fPLrTYr zZyuS1T+;gU-;t{$k*mWT-ddg*S|z!9YroJ<$Ro+s5BmI@a&B`u-=BBL+cr?AcxLa@`D{6~84t-6&l! zM!LEizn?kHV82JR@+(;R4tlMYD8wO7jXFsWJoIUW-*aRDIykR+G77n`j=f)e>qVEJwvS;Q;%+Yjk zLiji-@qOa#`>kl8ult!3Z@l5;j^gYo*DBtS`+qOq&~AS{?Y~jeuO-f&`r5`D9)$kf zIlYlSi>@?RqN$s>7k$YmBQ(?LyW%gRXW7-dg2%9Yuv%lPSkf0{EUO2YxzdFZSr4?zH7WaICKa0no;St zuj)GVyb)X%e}JFXdNv?@CC|>`TD)+mo}o`(#_5It zbEJ2AE*T>}As#W%^W5}YYdx~bbN?Hz^ZDuf$i5_NzyEe(?T9~4`LU;58Q16qt@@FZ zYOlwC%kvyhS#NvdKWlh5h~HqRjAtB{j#};Ls1=-9g|F1oOP^+J(o2hw>58#*$EauM zrk1YyTdU0EeBd$iXRXRi&M)e1oEJggozL@YJn!!3+8S%2J=S%TjLNG$@1-wY?zvx? zX50b)owo86&W~hmroQ9*9jP1=(t8@}(5G3;zRSPX3#)+tZ)>El;`d~|S1|OV-umAg z?%Ml|`s2%>w9XUSWH9KhO()!k&qY?+#CIM?Ne#zhEwjsS)ek}LC zrC)umevRQ<>F<9Z&A8C7SFw*yvVYrO^*k*+ocFHIbgriz=}S60#_A92T=jFyDRw-L zi4I5Jop2VqhWrNWt-4af*?jM=c~A4yWywu=iUBVfb{h7Z?Y>>x=+8>d+`RG63DY!} z_W&E|Ez(8mupJ~J@1+YCA@6f!Bjy`onDVR`z`wM%TluXqyf;Slr~UhiZxX!Ju4}(4 zlI;Y2556lq%EOkwfiv9pvks|d?X7XRzG?L%ei1SqeibS7o!GuIjxwXs1L@nx+Y>|B zNp@z>Jv)>j`$}K*gkI7Eug1PIui3uRFc@DVdYJm-`YKB8b@oo#SO&tkEE~&2R~KyY z$Gz5Ye3{1Rj!pekzoqA`Wel$FtbV7^hV;df#9(YGFqB>>*xs_&S6Si@#y;j+_CtI9 zYM)7>-0Uj%GIJrm{YzrVwH{wfyRx?@UlMP&x9?~EWH)#HJF6)pJGgAm2azGEWeKe1 zQ^P+WV^k)S-$44Icy<;2tVT`+ksXilP5tg`P4RAhSI2h|bb^!~-Pjvr?}ah?7%%5C zXLZbK#4AQ#J`BJk9m-yGW(V$ZMR6U>(Ffx z!!@i&ml9j>2r%)=*l82&_$a}*!tqN?rL7g?_)0$-K5BLUHcK*AV7tPyHjRU3;z8HQ#Cvb3c9c+Vz>MhqLMPE9$d&6t;HPuHUP$ z#ik!wq`X-EknH#J$<|>v$KLQk{hu- z`yO~M;_taG@`KW`b!R7-viav_qc?R$55s?uN15DJ{;}gEfeWtf ze-7t5wzvH!H@r3&w*2@Ye}25&pRYY+S?99m!w+HL>oiJ@kiUp}vq~>hT>--wrh1}$ zBOK88<5lN5LoB;mAHFT+J0IW4H+uu$M%O^IQ?`!P_tv*RFk(5h9VuTjCQ6&KdrbUn z$z@s}g_o?qGk%2F0pbTrs5daSM~FNTn`Lj6tu=sdi!6jE^|E}2Pr&PJdtX|(?-ts^ zcYhdrj^v`^2!4tzJ+iL=ep3)TGTn&9(VvTn!!03xQ$7{hx&&7rz7)y2Ie#@Ozw&41 z9m4-08%E7)*{hNpf~-4aYg1bfNd7Z6=@PF|UUs@FXd(qYcP8zLem7cr?iKhf(=1!V z44y}a6>KIJa5#IAXBR_zw`1e`${)y!4xR$<$DYJmi+%E&bGs2A?B6;zu?KTdRyw9` zEqoEb&A2!@d;H*4A8_Ys_O_<-kBn{D!273-*rXo*ru{DjWAMJ%r*jH6U);yo{1ke4 z_f+-}cP4%bp19K2qdprQc`bXIyD>ibfi&({-ZLtXQqMK`{=4&>HL=AXZX7V#@uEx3V{QRQB=zvcKW8dQbX?VW$i-BAp1vZuV zWQ*1W^QZakc?xC{56inEJAU)LU^4qpxR;Mrc(Mn)$;B_V7rc|NDmu)!xq|2NSIM6S zJnoUNN;aNJzsL3oJw~Y${9R}Ho#*&AyW^~2oQLT5=SG1V48| zzXs71d3Lc+OSZvJuv-Sc!p4dXGa0;#a$kfUQ#MfQoHlVhwrOZW_N%J$eC&sT71iba znj(V~1EakIsq7u-A3mmdK7YR^!Kj+{8yhaM+r20l3lbCQZC8Hy+*dikTf!aGFRzC)Qm)ObrW-h;tWe?s5SL8r)4-kEOTu)lPyVzAP0D=_2i+pPun>)5wj z&9}z4hzIi9vEcFX#7s6RRyOXkM~pc0|%#r<0kEH zr437eMwbqtYvm9(W$DuRot6MAJ7%X_2>JhT_BkU$tDRVfN4wj4mN)LIp|DvOe%RH8 z<#XC|1UT)9R2iX#uulC zo}fR{2{x8r+ay`C5&YOdel+p*`OcoHIRk|!$>CCTTs;$>R8f8-_!W(6o~|8LJHQye z0hlcvK<+MJX017i$KJ~M>W$6#k`i8td@*>o(1S03p$_3oBYH;y@N9%9Dkh~mA$dpo z*B360LIa6k-@AKewo$VX|4A-q^yYni0rpSMFfFTCUcc{NV!x9b5=-O1Ognes@^``a z+T-``&dD-rw*KSZ-RBm>t=K}#?~swcc&&vuoF_}aB~#YHPrGprpzvpUkAzXT`i$XK zW!uM$V~*D{@B6`tEMMtZ&3iZG)JpJVB{(v{$GI3~e;AXPk+yg(d5V&JzR-U7kz}Y* zwqQ)RQ(MYbv98kjfx^ix4~#Q8zkOF}+5e8I!sqZ1G_xN4eqBO0aw;b`to-`B=1T61 z;h#_OtOq$KAM#yy&z7o5 z{9VXZ=|8tIPrZ3A+R{9UW=vqW<;Q+=3$}^|#vV@ag|dK2)q(|MOkgr!G;^8}n-46L zfSF4xMcBWaX$9JTUH*FqcZIhN;IF%WYxdv&i1pPQ`(a}_3?xiF2%yx97`Sa3IXNQie zpu-KwN}u}gA0MlN9%PsN`V-yTcF72OM*Nt)kNybH1^a`O;2&$yW#AtNcs781AqH#r z@qZT&mwZmx<%5?V%I&F?>kY~+3!N* z{GY|Y!T%8ckM}WB-Z=vumw(}_Y-vr{lcYDxep8ZU>&-7P*6;D|Vt$qli@vDb`OK4S zn!46=%ih+-){(+|bFSyzOTfFIbMMw)fo>p~J(Y79f5JQI=#TTACC7Oud!Vk}`USsy z#)E$_9 z!ASU_XNqZ8d+u1G4y>km`XO7J+b7w4N|~oAJoENjb)DvvbM1I8T!sOc9=wyzd4&U) zrNAZNsaG&*{MfcFyKQOwe}iAS?UxJ;TJuT0=UF%gEsm!?$$<^Xu43?R7v<5DzFdXu zszGk4j{C5i35M0^v65YL&~scER&@Zww)B?kz|adj(cK`Pd&l6~AVohK!yk$3a&@u{ z$}0ZsTws^k)wpBNSjYayn8hnyn?h|H-C{EQvKkpF__%hu_ExDIma^SNo_j0`R=-A_K)I3f8j%|-)-n{m>?#`T@ zAV$AgPt2BnNsK-=k1t$%T=^O8W!n9kGvJc)#$pjb6c3LZ&*^O$emt`}1X8d0VHOIpC1^*4s0TxW;cW`ZHUVT6@ zTV)npT4KH>=UqGH9}{g{{ukiVym!H$(;hD8(bsl1Gy3et!io;dSaXTbjsGsO+Uz-4 z$r{$+{D#(h4zylP4!?(es$`L!KXA^^*uUD@s8P9+1^9Y@2E5=++Sf3PJ$B;G3k9axz8%kJ*-386a$5o7f;{flDARnwb zarPx}z0+FTICzV^CY|_b2X9;NOSs`A^P@W5^$k4g3kPqT=VxCB^Ydr=W9>iqZ_8f3 zan7%RDKbyvNbOY6Wa|j*n|H^AP0A|&2=M-u2i~C$;Qil5tmIkh?E~z9XY#t%b^p@R zKa#`i+SYAS_c~AAzv-avXN{O-_xv_CXwBQA2gr+qtx2|v3TIqP+l=cXr|pM4ZR^_# z#Eb2>VccgM&xe$!2K*c=QN*I(*i` zqix{Pp4NB-{#bY{S3UJi zq%C(`(jVr)$85fLs>S!_Lep9|527F9dwZde@n?={=6fHo$FOvdz3yql_gc{v^5Bc? zx4+%&EAaBYiol8a-an(O8F}sbUK4WG%l9mrrq3?lixe6$@x925PN7a?8Sj&qTK3zl zw`^ZQ60wr9>F;-a1N%6a7u%I=|CX)4n{RV{a;MD^f0uQ2Q<;zQo}pZ9{*m&B#ze}0 z!7p=N-Dvp&Y+u87SRd41gspc_&(K859qr2XV1C#JCUM`8&YHZ?zl%JN&oxZpdb@Ky z$zY!GFKi>5mb zLM^#m@hR*d$(XZcBkvV@8NJc6u}(!t!M1MMX0flw|H2-F-HKbX?XK|;6#q769k$6$ zO_A`Uk- zJar&(f!L9cu}83&cqHYpaAS#D#j+6xl5amHe^e_KN$NJdy{gyvUVpP%7+Zk#m=1vE#%Nw>}q!= zp%YH`r8TS~rZO)X+9Y00&x?6Jlb8!^j+R`^^CvD|J8R~si5J-CZe|nTrg$~^4zkhj zQfXT;bBV;VW%~Lz?BmR)#KaGXmFvIaL*&-G$OhL}auk31SI}i6=clduz*o87y4JIP z;iL35NSvG2KAT;e1oE!>#}=LLJaQ3sv?0t%AwEIvtHiE%=8v%#rzgY?B@;`{oPJ#1 zTe|ia*<8GPQCU$`ME`-?p^}v*#%lpUo}d$y=N@j-WBa>w3lb@>zVsR z&e71^zv(9)R(_+hv7rg*M#9gDGQctfXr=qkUCG2~?%`IavUy3#(hF~ULC z!6lCG=Fe3B+Z-Fo{|2fD9&{lHVi=~wwCA7wp0?M%kK1h``7 z*~sFF9k? zI2q$98e=`Q)c|en2fm*|Q_~r{&TG5ew`BSA#8So+j5|gFgOn-6GGn_Rcn@(n*!Kg# zqvAB<6w9_aFLP>qK5L47l22VYM-LmC$G+cdOnli)?E8)7{mqmfJ&GvNy zuZ=tFu%{(W#$U=D6ys0OSsxA1NUpDR`5fk;o;guJr1QugSwMfH7e91a;NvIm%=yyT zwD*1O0T{&|fG(kI;o}c`hX#UU-H2msj{jd{;Gguw{}%@7>-qU!Je9pzG5t|s>?c-2 zdsOVWP&*#Ni#H{}G77)4@CZJ2Gxy?`5psb>!6)lE_l5f+p(Cl$a^<&&p9Dt_8-n&b#_SfDZE!)e-d&1hVQ?A4cue7 z&{b~dA^1gXdN2lLToV7hQ$DgMra6Kq=hxo$&}Evdx&-Fy6l0$H9NFH(qK}V(;no*g z)5uvGD|&#RIyxl=*)QIMy~I62tC4lb{};b8Z3a&59a`wnqUcaz0zMZ1s8jx)Zr57y%3)7eVEy_#8N=oZjU~yLSGA8l8I0qDHtp}-dwkg@_VP&% zM6PxH$r)kxTvXPo-hG|&S9QDFu6N0j%PJ<@^%kvPa#_jkTz}ixRE3;Z-F@23!w%|h z+qdYthc2t=Y1dKxkkdDG1AXsn^ZiSFzlyq7^HU61>~*6u{Nx<=1Wp~*Fr~%r?8e-e zWywx7tw}aO(|_rx$O>%T*h;tfQ<{pp;pg=49#g&c4pVYWyd;PZaLfE*W;XOGxpoKN zM;8-2wN_c? zRr&Dm;eAIw{5yGGMJ!B^az9WRXxsgU1HzlXapPwqpT;-d!t>jZy=Fq+9mDb4EW~e< zhu>!6B}Pqv{894pCRu(PXI~0_8|@(s;I|ohZpHE=$m}S7o502RtMS`x|4w|Fbhj#C zbqRG_{XeRGXVaP{a<6ej$Yb>uZQ8z_l*NMA1mL!Xy%-I^b~<^26jzY=sn1Nr_anZV zj-O^0uv4D?>CB&eHA$yp=U^QsKgCvjHJqUyUYn4#xVtZD@kD$zxB0GXdeAqZ={9^U z#rRtu#LrTS&*e7X4fr_5n)C6sJV+kn+wkQS1ke zw}~niYQgnQU3sP)L@|6>#Huvcd6%^wNe##Mz_(^xVDsV^$OFv1Vm`z>g)6n6bshO5 zz8BvS&k^rY42pP<;!wmZOKxBCR?h3|4u}`kBHP77i*EnyfcU5Qkjn?eH}7o23qGQ~ z=ii)bipNy3$Fw9NtzA5dY@=_!X;e0$!-^+mtU=c!#yJbU(&kAS;rCf@N#EK-8)xi< zCary%i4CuyXVwvKf?l*)b1xid8&BfW&HrUQi4`M5e}?Wt&)yJ>tsr-W{Cge7lVrBU zlT??dHK}}m<(`1174ITCdqnfZd{{E`N%H7$@1?s3b&u|8L;6@ONJs!K8?&Nr&FBR=ic z^?T}q$F{2Ld(;Kb+L`1Zke4Vsl(Xk|R!`%+*U%*u7qCRWL-e;g^f&3p9r+H;LFbsl zohSUAcA;~#&%Jx|{-h0^PN=K5-S_*9qpREdey?q>Tb@pT6_2)ub?#n%H<9BZQV5+n z{j>b?^ild=JHLDn+lROTKaTu4vwmA(-g+TxZ@!m(PUZDoD_?%9{mmR~cjQ>B*?`aW z8-Lrk^|t}Pamqq|kM&{A`N7t)`$cQ$Z1D}m{35^NFZg0>;knWq_9$1*cHT*kfQLn{ zEFG);!1WuDja#tGl$9gr>^Qclze|2y*Dm?;bGUGkT>f3es9X%a)M*~IPxl+lV{~u= zd$^sog1?XST=I*J4ZXs;UF)vkH<(LjozQA7_g&L|E}xAsm)~^m(2-}*ml>1K2;EFy zHI9d4BMPf>trL^S`USqxA2kg4ov8 z@r`#=CIx@5Vs+HND%RE2j@+q2?%dA%YUIuaNA6T1cV_ZTa_9dCu6Xez0uMVEToL_p zu7hQdkuEEJJ?&7uM*CYzz<-TBfLyoyM_lh=ZK3gHp(Ff_JvQF8yyg{s?GEL|Ti{=` zTz;r*>?ZO>5gYTxjOuTNZblxeE{mq%)rxu9Qr_RviSih`=yWPPzslc|ujO=}du=;e z+-skYbSL@X2k73NBk|jPzF5}m_{KDzUwKSCoLDKYb&f_QIiW@Ob3JzX?!1#-UgZ*< zaw#2@OK{2=ter0V8@Pn-CHUPad&3i5LqEfREdRY5EBFNW!mmvE?|*xN?Z5Ba#q!^; z;QJv-M#>d`jxWpQ-^es72lFqvJc%{h>3T*xqde_kN5meI7`nAhJBvK+6s)n^xhc(V zr;P9WP?ry$;QHYY;V(^h=3MjrH1EE}?{t1Dr}rxRq;oAfq-FgL+Y4l6DBU{m{o_FtXy?~$F54Y_KYrhYBOQ^5RDeu0s zWIJsw=bc;U11BgG@|1b%1Z65bWq#w7(fFTeQ$EnuhR6MsAHh4V(bazQIDzeQp3CpA zXKsH3o$c>>@?86-yzgoq+mUj*DNe$zOZI>wKi}=c2gT`W#`9d|^sV}8)eUaE@gX^4ojUbQ`xf24i9U9apVqD4l?VN)Te{=EzZsQ^A@TNe z2m68C^8Gz^X}_Ac-}sR&{8ns*+g{%`Wl9q4GK$%1^{w_-F-F;M-EXx<)Vye|b?|@f zwU&K9t?6^_)!)Y$%RQD%%Lv!=OygV1vxvWY=(pHET)DK*de=R)MDLJ0M|<-RAC}De zkau3Y&|g&+9YcGezM!1^t5^Mryb4{2_Z;R!<_!ps0LJ2}^1)iRZ`Rn-gR~c_LNVFW zQ?Tpb&39hjyG?atSGQvF9ecWTN%@;u4=euc8P}$JYe)N@XfysK>$4A7yRSh9I)QE( zB_Br}vR3{07`qPoCHY}avGdBX@2P*nKi4li)Jd*yuahhh{OFezb3uRBA{$(tQ2jhn z%*Bv*oS2Kk6USVX1LsQ>Z{Z(L&Sc8_`nlVPgWc!k2YVSG?>6j% z;I8Gb-;7P6&3UWy|A7DaJ#>8ZJJ|=(?9ufOF> z6s`23U-Bce=j4m=IcHdVP7L-Oy~a5bk+_Y&ZTyH2d;Rkk9+sZo>_<%S!0_&q!|)jo z44-KW!|i9bhv7evkzPNd)i!-jKqt5KvC+04QFej@1}kv+*6`|H~`zg&LOnHaEa;#P2P?BEG+R)>-lq%70yl9Y^^)>n9nU zu^D`BHg#xC5-IPtu0Gj_h2bj=y|A}u8=;FGKjI|f@h8e(_=4YTz}Hv5p_8d^>;3kA zB=u1~!%Frexjw@de_={P;ybp#uxy}wh5pcU=qd91$w#=S8~Y;S*y8-X@}u}%L`QLd zLM$=lzbD?SSH5`XKH6-&$cVl7tZcVV-Z5xzsbEQrQhbJgp5m11w69V5l=vR`X6+ka zL>YY}T0Ml1FCBiE0bh(xLXQ4?nwjQ*WO<5j>2jStu6?}!7=+$Te)~Xga2&ng;(g+S zti8Cl@rE_nt*pTgI{L;j9N&eTm{JhqO$)Y8!hLEAH$&JLaK z=;+5f;fn-^77kr9w8<=m1i~Z+ZyOx`{(2zeiK|?l~jOj!Jf~GjdoqKvFQ6OzL$-~ zn;)P*&)hYDckPg>vQsCU#0?M&(={{$_^F)EyM3L#_r=5~`q*oxeoH4-`^s}V3)!ps zkFuVqf^TS@k#K@GzJkX`x=uE4(tP}`Ur706YpA=FF<*mU_ZW01J;`m?TW&4ou*Z>C zKQrw1;}Ck4+m9lrAICiXh^Rfrpf#y?tnc%@2zymEdtqH%%&}#13lEb$035Fa$Lqmy z+1y=O=f;GagNB)c#}nA{w`t8WnSB!Aglqw0!P9p8jR&>I)2t5gbjHm#p6YvB4sHq&+f zj7`;p&okEp$0ePEv9s8xHjaI2+sLoK#Mfhy;*dLphif1Cr|>w}h6lb6i}vp68hVAb zncxwN%a74!|8)oO=!kB&&u9;inVMT@)SaXKz((_=IcjIyve(rQ&nW60x|#k+CN#p^ zv=6u|v@5&j<Q z@B_0KrKzrv7#7Oq(kBDIh3e>zeIqjw|Id*7%!TCk)AyX295Vu?W4mYh&9%esCtu%a zGbxLBm}h@tp2fb%{q)%z2dF-4pSb$mHhwFSc(f?}e)01MOtmN4+7cgYzJGfca|i2{ zP1yf3WDCJgT&-!tYXt@)Rg%asaz^vfs8_8_d<4ybCyXYXdp6gL}>W!4<&QpNy~R ze8<;x|L%!%417(=JCZmPLi1teKjUl&%g@A_5a;1%sy%-H?xH)5nysJRzdMh)NbQ}n zIHfmx=BBdG2VM}J9*n8K)z=v2E%cRrik2^8E4ed`ULTE-U!tn#$}ySvmK1B;bnR60 z(4b_qagBkmHKSo0wmQ}2u9a5OU+>wI4a66@eC!_9F!s658Swc5;qUilKk`~^4b1C7 z~!yrZ*%@fKK^xhZwYcseAsIr>&w`*hu%ID z+RlGd)NMCsLX*GhNpw-?Jm@rd-J{4JH-FW;)Ro44E%^tu=dc(b)j!W)WuFIK%b8H_ z`IW!p{K~ED=h9g`IuH8Aw|v(5m0K8-fem&0Fns~kyk%r1C2gR`JBOW2c39FX!P zX`TY)m)d~L^X7`WfOwOCHCNO>JC`|%FH-At&CNuD!tQg@Tv4(=xVXECTtb}Lo8In>X8OLrTTAY!9mwep&uFGxtK3oCpDcIO zVsPkRI-{BT+UAa0z`U$%KDRizVK2Pxx`WuiDI0g@Vaxl+m&wPbxf9(ecbIr!%X!Xr zo~f4eoNXG=oaI0R=!I6EshNHwmIAyKQ+w=b)_mMYflCf&IhVk%YT>g1WW!9WjYO-B zmb2n*`f~HRS#@((e19KxFsH)lDC-#UjooK(W)XH}gY!c6z*8$n+2^s;S~T4HJir`c ziuRXZXo|noE;xaYsE2J6ck3&qzTo+sJ-LsyYLQVhn7#SM$eiqKV%GcHeJSa0Sm!1k zBsN@rsM+|Tw2nU!-x`&{86;b5TFqyDkwv_r8*7-#xw+VLtXz&c;B&gKzm+%d2>PGS zE|UB%>Gt08^iTV)h`vPo^M2G6U|rG=zVkjfavtBvzIY8V{tov=UByHCTYN|LmhgSR zmuAVcOnmLCFEQ~wVgdWE$n>Q*l);~h&eC)Yk4EaYyJRt*u0tg2l`vipTC8C3gdd& z=jCer<2dg<+I1zV`IM^)T__{_w7g@j&xy|{Bj2!-yY4E=$gW5%O+EVkG@aw|Kk#+@ zu3^DE6BwHCiU9m5FdDoecimj|UHk}mMqje|(bt@#A%4_^f3A+_E{(9Pfqb8#zcOCV$J--vi4(ITdW$B#vwXncQdblui+=C7&b{sr{k{afZsZ%mKf<+J2*v*IP;mtE0|#A`eAe@m-xQ!Sk%<3PMd^EKU>uho1zow?E+i)M)Nv-APc zj`)Mu1C&PK?wKJT1ABJvONBUien&gZ7-J1e$Y7{?Ad{-maXFb-=}4pE$mVha13M^+o=y zV$FfRxBU@zE}dI!Tcq&R;wjWIj4@gL0-myGE~d|Jz3QjsW1R#)#un%1k`&zDdc*Ot zj;2j`k@#lIzIOX8w>;)XJnT&;mt+QQi5G1c5O2;Ud2KF!B-UDPF3Db$anEk*?vx*P zYD@VkZOZ$d^77Z-#aX_0u_yTMUl+vYa?Y>(#vdVj%D`dKp{_Ykszck+VQgc@32aA; zkb$xtxpSR^PToA%jt@6m{?|(ToF|<yh8J~z2mdzRHw)P_^|wsmLI}Bd+sb} z&iLM%vo*okAKzup7;ox-lk4+W#4WS8J%UW%fK9BXjZJLpNyatJ8JFb`eioShx6j%O zTfDBtx3ZSDTp44PGYi-UjO`!3V)=-FQ_$W={H!llysbxQQ;t!&2)LJmQ`Y?a+80|! zeQtgNYaieW^moP-k0+ZmpJOl3pUESz+83L^dZl=MOFtHR`eE%Y57UqJo__qcgMK{6 z`zLMNNHOnAerx;p@20MXHJ6)i{=EqHCDl1I?2DD~P4O)M%d@Gw$k`V>>!u!|z$$xR z@R^n^yt}2}Xn(nFSGMi)w_*!lye@HtRTu3kx1Q|Eb6@FU@xr;lLu-ENT*WWapBL@^ zT&DgEy2`BE!aMY@2Jo^<=-hy`T4+^k*UPcl#3Q z$~FCnJleA@$CuPy0Jo;R+rbd!yTR!WAako%vU3DA?`_D_a)15bi?&yTd}NoNr@ zt~6q&(2imPv(?9;&|UqCxAZgM?dK6-b;Oo$33|@=oQ)Z3oN@u@^`6hUnT4F6 zIi7Pg3plU$kJVfK)8Dmd7XIka?@l)!M)?<@--okPhBn6!Eb!3p_hTofU)AZ-FZ}ik zhkmX7{o=vp+3o4~UHGDbUuf`dTaH?7KjpXDzLp$5!^OLa6A<0a<6d&J;6__+-t=~- z-g-{VK;94e-YYlBm2dfBe^34QF+bSkQxrc|kxXtx=_l|I=@vy!%-%-IDKF3c{8Zk} zBi)1RMCZO)M|1SMC;3Ku7Nn=R<)5J+UYYW1%1G{(_Lu%;@2mM0&sGxWRKQs$lEKH` z!p{Nhyg6UEZ=MtFm8`bpXG_kPD$X0-CYd(P&ck5wS#r9S~ zD}8R;2kAY@ulp+Z@*f%E$UbDFWS?}~+knNn_3`u}z}$s5ywZw6yUKx`Y+=jLc{CR{ zQvMOH(X}d1<7dsMGf%Zn+}lLH8^kwR{9HXpbKqWoPw+>#C{a89@v-kxUNIVhVz}`{@Ipt?MliwM%nZ@sPey8zct)0T&E9)7yD(hK>^Ne#GQrx!b$`meJ1^I9U+4J_d)6J>2H5o6)uCtUhSEX7 zUFk@z=()n8=N5ff^z2jY+i*J{km&gp4?PF|19~pcZBNhlFut~Z5Itw^Aa;VjiKgW< z6f9hNp2xU~J}0-iLz7X5mT#dh(UNHS34Vg(?UY^3brnAshFiIQoS%zp;(^9riw>>=jc;KnH5W%w_F8} z_Wm!{y@J!NFG@Z*vY(ts;x9GSp}16itGLtaC@WcCLClHlIP1jY`SyCgb#d9X73dq~ zP%N=%p&+(eWs&zUvR+nB`MX#fh=v~Lxz^pQ$XB7dj_>^U@Y>R=YKJ%Dwerfk^A$h* z@8k8L!R_bk2lTn4`ATEHESW#Jz0Ch1u=jo1ex9zQE_a?*IIzBjvcKZm<*AaRbKllH z`9mo>ul^T7%Vu*i-)<3q{nCcr(+=$ZRsIU>9?mZ9+zdM}e|_dZfZe_hVvDorvuIy3 z$c?=aPk8k;2X=++VV4a&5)QS8T@MfJCOfc8qwGYkU3?VYro7XlV;X!Te9Mm7FuTct znfh=dnN(u+*Apu;zq@JSTX2L0vyYjV1rEM7(%uXQX4pyE#bYDyPP!H-9NHe=cEjV^ z_Cfu<*M*sDU-9UeZ!@kJ+2iHXbkvbaTdB*%w>UNz(dlcH{hI5av)|zB`+jF0>4x9^ z$^^43R>r>$~Gb!!rM+91`&AU>vDd^u+ZmJG#@fIWV09`OLg z=9ds7Fh9@p-M|jM8;X5@N+D~%@r;rDulN0rwdPaX_tJ+(?1ArM1Al~mKFXY9U))$l zKVRVbH(f-3so@_|PJ6}C2Wu2}$Js+MgPiuWc&;<4;=~z#eP1GL$|Tm7-B@FGr@bD) zvZwiVVFGd7UBid`U5Ib%96sXj6mIhS$w842&M|_-E^}@q=PhM%E@@5x`1pT4rrMv` zl;aQPF|1|4-NS!G; zkn_>*=bXsWu14s&JkA2?W`tfU|1S9*PHVb}XUZ$T3|vw>(XYCmH~Nz{b^3iyodZTC z(WdHrMf=vNvmbsF*^M8k-XeeSxtGevQ11Yz-oD{7>W!>X8yVqato5Qd1kLD2K64rK zyT^%v+exfY1UyrojjMt4Zxe#~Kj*iKv8<-;eSH7%3?uY+%1FoUa;j0;=;zFG**dUQ zX#R8_U@5pM|BUcE%3R6zfNnL-^yJnym?!0VjqrVAS0nZn{Gt(G%v|Q$#pSQgw&P1W z!sUnQYhxyD%NK+Fos7U1FRrJaYX5akZ0z+-|FG`uJOx$$=}mjNx7OrSE&(4d1}`Rq zACth7iP#<{nBYxF_6LpSFX|KhPj&n;kAQzA(67#;-^n}KLfyE}*SVKJrV3b{d7jQk z(*?G(rr)cLf*Ez0<#3%;HVXpG8btMn?r}ytZ1ii?1FCKq9 zH@-|h`hLCpExzhX!>j?XRyla}9p-B3_rbS>w8aw&$*V=2S}`_*EMgXQ9qhGo%s3}z zap@I7bNLzM9ZWK?l_oc^Mw~XsS}S2knQ}g3DP&CJ8JlcHf2h8F*YR|fi;%Z#qhnL` z^26ES(24kAoLCg`L$|$yU&U)WYD4(&@)piOu=w(e;EIp-6X=JZ{&WJioh{f3b_V`N z!9{C@&A{YOzqNUGD*nb=XvwwLpO^aR@^s=H_Q1o^uJhqXNDKGqCEk{X4xY|lXCs!# zy=*Rz5zok;=-6Y#Kgf^n#xM0H{$U)kI2F(qF*&>XIp=;J1!v{IFX4H0(qEVNdnbc) zY?0^l?rkbzt=Aua=V<;1@Qw6P#Xr2{#6PG$eaAUNPTYeXbCO8RNzSSa;+Fa~6e!Nq zihD?J$Oi6zVXp1C2kq%d58qzvt1SLHKEkH6j%|Df^F|J;SlPgq7>7;Nli-O@>a6o5 zi9gD8Vw4i;Z>B%7zRrnJlD}UuN;y8xzA$ostytQ$vPH|W34D1YW4MC%(t|(3$Bm4e zCfGiXd_3&HRPm{=VNa|*{=n|)WTR&5fd_U^X3nC#F9lu|j!*6#pLJs# zsMm^5YJgYF>`~A(Gm*Ga;#2bEJH0Bar!nfBq0KQ0wDUUt@QK7X_oq(-iCNJ2H8#P( z8|N^CGa)+bbRXxd8lW z0)Mb4#J0n4M9r?o@Iv+q5Ieb; z*h$GSmnSLa+Z%gT*TblMk-mzrA0;**=;1y6;XU&m-h&(=Poo`sbrAZGbKZ{TESmKG z^5nnuTTxA$%F|d2k4aF;OpBr9feq#buPn7%W=;VR%*?cmfi zZ`wR*6F6n^+~rAb%w!avo(QZL!jnX2C*nzM<0b_ojZd&?#gmAe^v-`XPx>culd`L} zjlEh+fA`Zr@0q_H#b2$boR=@@{@>$E9mh?ozP5bnDEhHGuaY6cYsnDd^iA9gza=wW z+!pL}z-{4$CFR5kD^5zX|s-vX@Xdqc zkrB~!QXLe^1_k14x77cF&mbLKcAo#N7&o&Le z$2$8pp1U+my_Q~~7=F?4Yxn}PPC~;&z$NYVl3sBWF%yD=#wR#8Ov&_CLcFK1>doR@}me=-_AaSWv$Q@oz`->B)^ ztXrtQwlqA5xoC-@>}Sd3$KHvzinA&P_S!Fs-7eM%SuEb0z<&zgjwAjupZH77<6h?b zy)WZ6nzxUfdApQvKVr@_*P}Kl@G- zjLP25{oCj+yxdp{oVE5ogLl%AzI?-8mtQX158tfx+w|1H^CR?EXUavnmR|MPMy-W^ zZytnq$cDBRx>H-eEZbhTZ%BMush(MOs8=jIR0(bATh}hCYxn(~XJcFPcSb+!$(VXE zw%&}f4`V$A{VW;%jB`q&m?=~&45A7=Lq~`Q&ej$VpF1n41Cu<%l2}*V1a#mj}ILWJBZHO(|ROp z6!f1!K4{LT3&Mkxht9`*{^^VYbH^Fr#K0Dr(N^EPjo8F!e_&30*j#KLrL1MNx5Qn` z3_#~w2@hm_HLU`?*FL3D^sg3q)O}rn+2aBulvEJR@3~63u?;Iv@oI7u7m};E$61AD z(r?J;%JbE~7-L?|^FOhd{wm*t%f}@eUvA#V9#r-*jzdo`%|^~*)0xl|->Ci=ozFKv z#4nyT2-(?bytx+{w+}h3v#sCddGSE@pZA7-tBg>b^Hh$EHpmg+3*DT`cnZ;(vW<=J zflH!;alo=(;H@>flL@*p;Ja)BhnCnvtjJ^Wd&#PJs~u#$O75 z>I<>ulG8Pjb-;X{)q_8c<(a$pUi- z`OeRJ(g@|SpLNv?->x&)1oM?QBa``3UcZ^trM>NWXBX;>xjUEe%w!+(BA%^fF4wLd zZEj?}p?uEK{>Db>v(5dcKmC3lY+9L+-e9izuDLZ9pEli}(NN02atK&4;N8bJDSmr3 zdO-!exEh+&Sy2J_N-cDLy6AwimFNfyp-;tpmjP4d8Pc`*t={+KzG{ZC>ni4cA@!Kl z6ZI!z(?X6?kLIj`IwV)e0c*9PdL{rTl|9;~Y#qADHNasau+qL=mDM*IOOQF&IQB4( zWz3WMx@w=XOT40+SzvaD9>hBmp@|;Q#5mxlJiLNgE->qMZlM`~CbsZA{N#5y2XD#p zr+B}ZchygiHj5p2<{)ah$IVoIc0LV2^=0_?yPiw;{;?H=Txpw)cnmr1xTwQ;gfvelYX zStt_EiXh1QFvT^Av6h( zs~4{mJ*W)2kN9Lxq7l=W)o(r1JIR?z2J&SbJedC()H`=t(3EbYc3*DOZsmA#&*PH{ zV$(ecOyskkoz<#1WXUXB-$-kC1-_^EQ4d^7T(|%W!R0*QqdgpZ zyl~MuLEP`5e#MtJPGO(_m6suxFGW6o4>>&r-Gg&^{hck{L*tNMCOsh0`Iju!b3F^V z&wwNEEjaM5GRoL8mKLlSFxWR2S1wET2Jr9IA-3%}o-Uhm zywHap;WLjU%g^W7=&_H>rX&4I^~47m`CEGWnsT!&J2HDR5*xN+fAyYUobH@oT*6t# zI>R^)Oxg1RpYnw>fL{QgXmNsJ%H|Q}9An{1SyB+2v(AJ{3;zk+mwnl_eSdvl0e!-! zQs}ebb$m0v7QVfkG6}%OwpkgW<9sK5Y#cB+k-tH9@OOR|Y*Mb!Quc`--{f+O^NV**>5%1`j1hE>XCg>_bR7xMfo@BPd)u`Y>+&tJ{qslH!9y&))Z0RmNhDG%bJ;tXB;|10lZjvTf91G3I>dQm*(bT zV6g?7+{|^VA6q2lMgP_0RIZ?WD(ydK;dy(1h=o_>oxrQ^;C&D9zbACi3wr2{e%c2= zg+C;nPWtJ-UWTQgPXC3WGa_SEI`-;fLf$88-nrJ)!dx7N`?OVJgjgJuJ#9q6EcYNLaWN3W19^CR=Jep+DO)CWF| z?wO1}x0L^@7;6kTAK~ZaB~f6ac@!@>;_wnLk6le1i{9rj|1OWcd{7II6%XM+$5=M- zt#;sB!u(YO-)!2f0uRdROSOZO)yxHYNc#Vkt{d!Q>$*W=@+P1c3hvT#2hwI1_ig3Z z0G=10+M?&K#9#Im{5-;3g~697yh{371?L>M(sfybyoZmpe((h*dKtQIg82{T?BEdi zJnM$KA?Kr0@@{bF7M+qh>xUs5ygDUwez4qc>68bhQw}z)JoU1bZ#^Dg7N6hARQm^M z&(bUVo>;H^S9Ho6#uf+!V>xNI4%FOl`jd`+Ge2QKvrZXD$FX(F6FRMI^}lyGLw2bqI1b%o6eIP)Q0#%om2KmJDrjo_mr;( z?_8Zy-)Jn-DK(D&Upggmixxb==T!Hg( zft%95Mx&33uJyfi6g|^?eDXCq#M!~v-}!GsHtQ^`8}Z^O)qHw>f&r-9pV=*m7ee#x_y}SbRZ+J zcx|D<`qOV#5wjHKdvom=b8Y#l^0qh`G`o++`_q5 zQEb@ey_r*^@C1YSDs+|n%Y@7DqA2=IJ-ByPC*zrQw2j`DAJI7h^E;apxxNQ`=xx;b zDeV_?ZcU^Y?||cN2YlwI$gbj3O2@{*o!j0@Fh7M><8i-vTOQ?^!>S%#n#{7yrl&g7 zN8s9nKHBRgbSU~L+`o;uwpp+E@@N0imw)Ul=7M$U+tAh_+s3GP|AyoK|@UZK6`Is0pC7bDb%d9F=jy@9PrcCghv6Ac~S;;R&HO~a3U zEA1YC9y|u#htIU*nOwZD!q)NMJ&nqv^r>o)Z`bo&3-6yeN_pV9ntyLU%bk7>v*;2i>FNcR}4fG;; zALZwiU&*z5dVOU@_&Cz>2?_?&{pk(pjFz7}9Y1#k_^cd3*hV)FK*zX_{|K>ySMg1N zJkn9WfkUv9H8ZHQ#n+wQ;A34~fqcp&wnOnY?}C4&z}G!T z@R!V2G4VEy)EkEe=0Zc_2?p_?L$KFJu=%TR!oe1sHuy-ai;Xu$!2TlU;6mo&0_Nm= z@TL&FNeHFYwvW?k>l6QbPwb`myr(;Uao4wbvN)a8vPH|Qoj9G#9e>)E<~W_y@N@Xf zwEob%Y{B=6Fq~HH#OYKKr*jjy06bg8=`_4*`_mp_9v3oR*PlkcmfbEF_$WrF>Lf8b zYq9IPzBD&RN8>7M;}0(6A#_M@r3wth6lk!g(5d0kp?eTEhEejE-omB}T`lhaBon zq+a215-~bceQjfOPK?7^6Q2e?Z6QvlhBzJJlj3w9X%nY&E%+m!pyG61f$s_Tw(>s< z{$R;`WY>qtIMGbPdSrUJcvvUsr89KX1^Vd<9R=WFiLA4Iq13F&mJLUC7~$Xo+Eo9g ze^@qd+5wImeaONrXy6OQs331kZo(%CtYo7p-kT75@KAi&ulR1^&|h2@VE<&|`ls&P zOJCwYGV-&!o{zuC$gf-K+q9FuWkLH%rx%*to?wk$)#B^9n{{?7d{O*IXOtY~XU7_* zhVOeQ82i!qPNCpksuw4PvZj zWFgx;BHID>bT2tGE9|_DW>U?h$}iiw!d{`hSqVNrPhx`#!r!VL{#FJ2)t}*qI2`^4 z9b5ha*Esx*Ga<(had`CG@MXzY!hJb1Iy&VHombd4g5_y0FRL(ZJX7 z18|TyKkmBBquh4_A3@0}*V1=6XWZ9t#;v|5lcQ5`XkM#;!b^Z=OFAk$5z{% zWe;PGYy7ea1|KmxwFdH^o)XDBQ)em39gVc1bI$GjR_sU$%NC_)(MLsY|FGo7in@N` zwaBg7=S3TDk!Pfqc8nS$d>jA!Rp+(-J?dP|I&$l}e_Y6ZdjUF!eKv0K8szEmKeOe!zdh6K6NvAAXJ0;n2hbNJC+XYFB%SM<(XX+F zjf6Gq(umfupSeDdHKsMJdr3Y8?ksPbCC}93YkA(*%#~HbH*<_|+mcLu)tzG|FREq@ zn&4oxUpgEzEdDh4&_EUajqYccWiw{^T-Gz*YWZ36dlP<^4b7P=cf(U9*Ug95ed{!P zpKnE$Gb-R|@Us1XGa@g_-iE*XM&!Fz^aEs>Nzw~MW555M9T%Z-1c|k1{5pP7vy4LN zW{Qc}f!}bDn24d!jn>pv^wCZX&?_EKME+BDtVKq2;;ZJeAoG^b`mAJs-!R?g1v`O3 zelsy>JJBEcKk08D>vJ;w`2Nj)$#;Cg_DjBtJx6||5&9B6iEbD4OW+5j~yBbK_h7njpWUr+rk8+O zi8Vn>ta zP5+IP8vEBwdh~{p9&t2B;jb^?v+~jnp2!`Hd6OfHmtuczLl$qPZSB3?vUo=H5BkO` z*PN$EX9M>#o~0+gKwQEM`n-enG9Fsh+F5fdek=4Z8M*EE+$GBX6~gA}OGT!jZ(mwZ z+2TFgZ|u*x4z#@&-w|XX^dGyg%bdPu98vs3x4*vSud~oT15(`~|8sPCIKEZeegB$wDjmL>~V8mw{vQw@T>NlpFX<071-Rl z(>|#3A5b2jtaz>g@Jb&%(+}@VhKHsgYYjwS#9t;;xFQcSd@tkrVoM)?7oPh*{I`*{ z@%Ak7YGe%fQg2?(x$knDS7%zhTDHlS8!oVTdtf-S2C~*&;C?uAS`1l6ve`23w6%Ny zhOth0ue0-Wke%*f-5f$!`vY`T(+BSjv99Z(|3W9%Y$x`XYVSx(AE-+C!-~R>Mml_V zzQuQ8&@!cWNj&Rk!Fi_a|!TAyK-3<$~ zCcNVCT-{SzDtXD_xspX<-zkY?5#QDX{JsR9tK2eK@Lb7tJ2=zu!FRRy9Dq-L3h#A! z@PUyw50>5VQ)pWFl3ezZ!;?M4BK`Iib6Jdjwca<}Vniz8aa#A{#nR=Qfbl2rM-Icyj8^2g4otv_Lm$PmsCT<{paDu`&dKWym+J~n+XngY~q>2x^lUWv}7~UkYuwU^fSz%pS=0=kKxHa( z*~P5aX{_5a*6&o-aVav-6l@H3yj?lEk7QGqcgu$-16-@j;s>lT25IqwwNcxrZ{KAm zdX{Y~GROgR{wABBh_^eV>sEOuMby!wA1d$1pylj5R$d4?4i)nDtE_Z9GV;UWNB--T~m=jW__`37ju zc5N=SZ~HKVXSF?u*c|SBu;QbhMh0;8%4B>B%aIdH(RJRy?lA{@g3eMr#90U@8mI7) zxV|Rm^qs>wlzn2|=P2z~JMmFf#3+q!&ailG9=X5PBfl1M=B4pzub=h@lNl+=$)LSC!2x7(Zn{Fn<;ZR z^PZ8u_f&1S^Ad^cUJVn(Z!q%+z|T+7+WO6;R7%FPz+LjRWK%fL9(LC@_3f6_atq_ zz;h@2Lw3U6Ib1Y?E*%2*dC>a^bFdYwaL7BD^R2;_&eDos_=xqxRtonc!TmkhaqFYV zJKn59XNgB40Ovmk{)z zas%IoDD(9QdR75GARWj@{`A0voB1nao<1DEYB+cC%-K0~)$rAy#%G)rA25C!xFRm3 z#kB#S%v@=m5%+Mb>fx_4RC*0QkK|zB&Uo-{je)f%Jc@4+H)+}K633z3^pDc6pRuFQ zb*8XiR54dmk!SMxR&A7``xWqgKDwZ6dOM+!0@n9z>dyxMqxqdWKQ9*KyAWgYJKqJ_ z7d3yf?dc4($cZT^VD6?qDg605HUXRF#eJ8@J3sFos|07_gXR3rfkz*?`_%|}Tk((bSo@9k2igC% zhg{0Hl84`6oOAIpo=3Yav{~!O{L`>gZ{#@$4Juzt1#7jKZxnYNqHb@S{O{n!s+)IY zz_|U?*>_n9eJe-8>rL8sj@-S$g5i-3z|8(tRKuAV^HCHqKFQ4ojoANO>;vUd-@JPl=MZ(4!vc60uMl$B+#PTlPOpU?j)%Qk(R z)nAcee$tAq+fRERo&LaE$=St`n>(N1b1OOc&MK^qJecy{o^SGhYH1+SJU6yy^cU`p z)X@H$rmrEVZquaHz@U|F>o-lpZqT558_kr4lRdtMQ#_|MNp+`YUfN&|Zn%KoGx_VkXw#(0r)6Gx`2~NurR0LY-f};` z_woDn3)*hE@q+EQwDG&0-;$BfU79_z@lxZy9hcrX@~KPj8~Nm=H{SQ>OO2O4xuKH3 zfyUP#&*yIuaFqh{2s3a;C`XU>8_D}84tuk^iIy4m-IK`Zl_ zbK!ONrH{Y$5%rU|y|~B!#Xw{b-|YJ3yL)_RS4VE<+p>ob>^Yn7{|>(L7bLH|1$-?5 zPqS(7qv+zdemNw%XS6wR%SW-_?a2pMXXkhBc^2Gp&(`KS&0CgUGJo^Z#b5o!(x<_X z@9e=V^T7{mZA$@jnXI{F-jbQiUCgDA_Va;{wY*vX3s!?)&0R9E=JAbB-%x+rqy>?7 zzPa>E_eQGd_p8PCMCxhFlT;Erdx39d731i@F3>%TR)k+d9is)!?Vm+>b<^|e*w39%%p~2 z0RMDPYQt-0zlLv`Cp8G?bAGgC>Ea*#V(IiN-&$HSQ+BpzP(vzoadOhVk;SI@BX1}WNqykgOW(ZEzcOhc=bwzFUuJb=y2sP-P2;47 z=I{M->1O&EkaR)ptI@ZXK97H7nc2VL?DPFAr+ZR1pM0->!)V6) zE8u#LF;&u5swb(T3^<-MQyX^t=vPZeJ-2D;$9!KlbMw;FD}TN8Qe$w#9O}MF9|cBI z!yM}E_MQ^0g*RVpp0xQEbMWTH;OI^M%3i&A^PE>N-Avr~<~fu<13t?rpTl4MRN#8G zjQ7(vPyK>#cw2#CG^8LS_=8mw%04NdP?h74 zc0jLNpw|Llazlsc6*xviuVwHE!TKKU$@kTj#g*$^v3KXf4}HkJ@cc32i-|n3KQ{Op z_89TGAo(=J6Ay2+Z2e`AuosOh~XF%cs}cT@${PML&w&ykp452Hf6{B z0^?8|fN*KwkCBe8IW79siza$eM)YZL*p8hu!<*JHcZU%PvcGA(?0h8CCYz8%+nn{uaUc9C_630iQ zi9Ng>AB~DL(3^6NLO<`~_#Sv9SK)hLpzH6+#4nlrH+Oo>NDw^kuzU|PqQ7A*5$HjA zV=C4d;VNS8{128)n2LPl_UXqCEZan1V|wvQ&aD$+cnTQS*tTK8kjq}#4h$KVZ8#(P zYv5=FXLowMksvXBHXP~rQrP*4TzviLMU(wLExHcdKns7+W1;lOpy(I*{9=oK)1rr; z>KSh)SwZJ;Rz2eKN~jmiMHT>uiTb44aGwjI{lqn;Hnz*=C|&aKf^GP~tgGP+d^NE5 z*2xM)1IRI=%_`&zS0597)gtG2Ko3D=wIDi);=7U)bTL12c9C>3XmYW24nA;^b%sJa zl9d9`-6^y$8A<1U<=FmjWUenJR%uZrZRJhWQ?7{=nW&u>H@aL*dL zbp0G#*H7t#u9krZ(bb9ce6=|o+Pa3h-w18ZKySj%c#N(ea&-M=9{(bpJ(b`;B79`^ zq3bV1rtRxo1HYvco^xJCyUHOQ+V^$uFV*;ppocm+n-NKBzWji&wmZ*2jMO6Rs3@`!;7~-TIQ9 z&t%-k-TIPvz{${pbV~67!6Z5o9EtPPJ2%k?({OZlVp}+S4uVsk@3$*P)Mi?`T^c(3 zTqmyT#C$^(=Nf(6f3fOz6*L(fR-}m|o;03p4v#;vRQfDM@!yDyKQPicQ zXC&z8-RDaAE4KW@Xp)mV_p?5fcjp7*YTUab{~+GMnvuO-z7^kMyWTjJP<**;Gm^coW?d!P30*(UCh(cZx)|>GH%K-YuULg$TeuD-zqexe zR@OSlTpyR#&*g_{%LUUo3z$u=v^k97uFuGoc4GO} zZ^^Ga`;cF=j*(yOzI*3NOO#*VaO79<3DI*=mv5Hswx0M!P0WqTF|LN>QD%YNriH}x0V{eiS%-)i3_0`)yqbIFP#uzUfFY}^vgdn~d z_If|@9`Y0TbGLk9-*2aUX`&xj$LRcteZQUL3;AJcy>H~#2Y27Nk6w6E ze+nM_S$fa$`1cHA0{%Di?-zf3EdSn+_Wxe~-8SOH{QDtb@6Er5vHnh^>;3=yo4l0H zIr9J4`1i%o(`WJT`d9kq-;c8PUH;8}W%2JXuIXtn>&qS^`)~#PmV79kx6yW@J?55I zdfH=rN!(+y-4pg1M(3U%*mgA6ufu&O81#PE4|=wBEo~Y2Ldge3dd`8XOzhg-XMV;+ z?mQD5C1&U4z%lpB#huI8D=G?#$$4(y4_2n~)41ym8(l>PkQa^?ApHcoZyZkJbzf66VKTrAd zcKI19e~S78DSw>u$L;cL$}1j5$7MWe2506xYd>gVFR55Wy+wAt49e%-iw>&0`s!@G z&AO)#`wOy%rS}b@j`C!`b1>c#!glsO5BbcYyJ^d-6-tXP^`l$DILcOhS zd*p%Y-QMPedOvsD>!aRAr{0Nj`TqnvoWXpAfLHkI)|bH57FNp)5-Oc1YMOuFJ(5p zEK>RTfzFKnl#io)oLzpO$_uEEyi}1(d9Gc4ugam546O@fN%9t2cILY%za3l5kD<>> z$9`}Z@HG;@B^$wkt7Ox)&%}ir-J9|*d0-^tyhD5Mg0n>1Llxg1&-QQxo+jIa+PQ{y zuKe`)?Ob(&b~+N;DHS~AFFPJQ7oMP<_Y&F}CwN#d$7|=@6SVVlr=6fhKRxr=CF1ba z5js0NmfxlM;3wR%>dNLDp{d00PI~#Mg|k7xDEQvx{ss5W2K3u5yHB!U18&t#^npm6@7^{jUj=#ivD5jH_s>P&N#k!7b`=v@SnwwLPl&H5 zUp(u7MySrd7odi`@qbuPK7ZnFzvsl=*3?}e`weA^yY1^P4qvv_=NR{#DDfT(@l)+F z;xp;+nMcrHWaHA>Tg^I@oz>Py(k;6}s{_YI;CPunTY=*@4jdbSW1Rzs=8>4^PQ^F& z?)RDXM~AY%alh@CtiA8tr;geCtat9-H=1**#C`Pp`hIb7%%uHnBMU#1zV8o^K6Q|> zwPB0dj!kASe>y9@;UGT6*rXI&c|6-!(=oO$I~K7u`5kOu>6Y!wwZ*&$t-ajK_C?Mo z%l7pf?0>S$$o5sq9Jj+aWSf$`YOnMf_=ath8WP>|oN49Q^MiBQu_D;FWSg;b?7f3u zYr2(V@3ZVxMTXHK+izZlQP_wLt^ga2PiG(KiH?WCZ0&tZ+I?4~2}F$L5uH_Z;tN@o=C zZW_;{`;pt6I@nIg+r=L1{JQOS;P;$-_2^gu<)yrzioWmXyFA*L&CPAIg8sLYlSHVg<|d3EM7ru-z@1*Xy9Ky8i&Cs~X;8TiU* zM{p(6zu?fXV6Wz^TkuT1STM_XOLc{#4s82*^m8%)hp3yynZ58+PurT`a^|-l zcvKdm4cS?w8?^!V#muedC>y#w8@yaXJLmBGChfdW`QI6D^y+hB=ZpzNHuLV%u}0() z#zi73d?d_{v*B9-vu4F5jQN=qV+?szT1N9L`=4ySg3q2?az{a5zN=@)gwGWEy_h~$ zfm6{E_!^_RT11{7ou_pq8DsR_X!hFkc%BB_e)=fq?qRZJlZ}tHTFlru!JA<`SN_kUf ze5~xSs_Vis&6(%fv_DPba()HlD&Y7KII@gntKZ<&XT?NcqODTiYkY2>i<0S+b_J8> zw#`W+2C7LAJ+0CxfKmI7}w?`3-tEowf`roDl*t@R^%FW|dD{NBvpKeK); zevk+&?RCLQ|DPLH#&uj+Y14ugn7d%5{^wfjz~HXYLO+Q)-jr{! zl{(_HMc4!culy|DqTIEi_0Ff4=zow!j6vy{H>B!($#>*^Un%zl`H}*WS%U+_XZfP1 z0RuKYD<9FU!NpeDFv{RZEk=zI7C%xO6{piiiu^?F9L6dOQPxO42({CKeX`wa6f_D4 z>@Rx1Dffm{a)n0qe_NW7s^8qv*QXYNALT60GmOs5o;9sIjkBq{pEmTp#(ccFJV<+z zG13@=J6C@OubQv3n5%T=3SU`rP}}pf`y}Avy*ocT0}=k+dD@sTPeI14dD=vM&CiHl z^D_^*DALCqiI+BY%~5)X?xxZlN&ewH?znjmeb8VQe7pu8n@>KvA~UI@3V9=$F=)TB z_Gfs1KJtii9qp3cpEaUffzq|`H=D5&d=!x5W)ZSc2fi&IIA;T@b2fFf4<+;4!S8JN zgU#1dI#jm?7^j^qzLM0jMtc(d1c*Un-C295`0!@KSSMffFVTj0iD+{(eeLA?GQKV6 z+fv%e1s1(a29^T){sQ%NwpQ%4MP484|4Qds@Z1PIH!;pt*u6V=FPv2yJ_{dnz=z;s zJox-oIv1xyGVKdmz&+NedFZs6eiTi&_y?d_ZkB+9pce!-ECbN<8neokNC^UnSL#$MmQ&G+%w6+i05UoZ*%vmdsh z{#LFU$-qs-m`6r&MguQfds0!PZ4`N?Q;bf-bZCpdaHCl+F1-lL!3*UFjuaofUT%0#}N=!$)mG3T-In?lovn@pf*E-Kq9kdj76D z+xJgnQCywypg3ZKwftjz82-$>sBGV57cq_t8IP0ig*Zy>iF$WvctRX4F;?u|%T#{B zf6HFiQ&;q%3pL?4m8cu4okTroEP7CgwJAMF@^>TaNW4-!z8%=48*OBaZzS9icPDq@ z=#IFcCsFU|*8RW9oFw|mNe={1z|rmR? z`LwU|`s4EH7S5)6^XVT_)|*dfAE1q1e7ck}mrs}3_V^xrx_007U3|LnZ*hxH?>KT@ z4?g{uXKX&*w)gtf2HNQ6(Z4t>qaU!nXwdCb!W zV#Zc8N6H3r~g?xLvd6~iU}W%-D?J`(P^ zZ64*U^R1GBeJ5}HU6v1DSg&tOUQX)@PdI^3A^|#@^F1 z47dvU)i><}?EFy5pZOR(Ja2$#*1k`%-0>gTNg00JY$wt^d*;p1{VSWmdBNmBq2kO+ zowy@EF=IveI2EJ&jwbFX--$cQChlkvezga&FDZX5GOYB9Le3HAY{$<7x#tu4f|T(m z-Fh8saXGeD+y5Eg4rs3N)A-mQQck|D=|=|HG++dTcYNN~lFMPONnXB;=rzP{3h&CX zAX<=2<;L|YC)X?N?Xwc%9F=pW+KF)#Zj_g#9l6@WxFxSE56bM%i0jq9kBwkg4KyqN z=u@E^$sKnxhl&f=-euEGM)Y*(CNZuzejJ)@`zLAkC~LC&++?Voa|Jluv9a&Y5Y5Qn zP4qI0XVH%2JC|;%;DdS4P18>D4TIlOXlEw$+yq@0%%5oahvn@g_c=01m4&n3XZSto z#cGcn3twUW_FZ=3{7J&4$)9Ln@$O@oPtAq(%)YS9+8@%QKUt|S;_Xk)Wgm2<&taYSw^BZ}-+5d|bPd5)-nM^!rHTpsg{kPM$QS-pWRXk@sI3SjF#E3Lf zjxIbY3XIa3HUQfOU`ifi$zv_9ZBBAOxUlwAi@)O2-+rbMNh4pj@W$Q6zs{){6W%|B zJ6nlU_I-6qr;k`;$+-A=Jy&AIE~iCvW)QD1cS>hD--*X+@6xYi>MJN~gI^qA4(7t| z@WWqLabBSF^}pil2Cq1W=inM^e;yw~rf9eB5KWIxXPzofBcDC@qo`bWi0Yhe1<&Gj zWxVfgXVre5hOCEvV%ayN<>_qHasBiW_T z{wKnF9Xj?g-!texSYqooE}!m=hmFuxA|6T{JXCN-!hCg}&+}a7s|Eg7n``InJO32o zV|bohVBc@6{fjxWbSNJ(xnas@GA;Tm_?haAL7%F~WnJXjXD9izY0Wu)e!y4Q&TsGW zS#w7{;c09ic*^8mBA(KC7M?^iC#!wh4HBa$nn`Rs*_ylV`*uY4&Ey6bpLOLPlRBT} zKO$ehsfOa_ebJrR_LWn~(ivG}+J81&OzgZBwkQ7`8DK%Qaf$z*`+s@6o%sQF>2>Zc<oGrK8yAjvA2wc~04TI-5A}Y^6F1!3KeFLG-7Vp1UNab+Ed2Sz#^JOv1v!xNQu-{94~Udcp`9IOp~gE4 z-#fvp{rz|FnI?}XEEom5ajK6o*|;!?i+hzZYrI2&JK`C-O8-WsPju37u>}#%cQ-zRA>in%K?{`6~mL&+>aSxO^Yk zwgOx}2rg^D<;~!-8eCR@OY(`u9t4*);BuCEZ*w)ctOl2r=IWDJ2`IK9up=?Dj>Bcg|P#Mfmqz6q=2 z%Rl%ezI+_N?%J39CRs^*PjMYTV}F(mC)vp^+c+tWdEi{NMQg=g!}k5??i{jLF^6eZ zf8x{YtUZ26^uHd{o_uV)q7@fr@k%4w%Kjc=UDPDl7mx|k9(gwqdEbePYb7>M{Foe3 z6EuhK6Bk#9{q;A*#kD~fDa>y>d4cb6>CZ4-HVlLCYKb-%E{hU+1kq`$Mad=J| z?LB%;&s;$jU&lXmmK}p9yM^)^CfY4NPPS}-&)-EZAo-EXW+8fcoBnD&CCwFeX1JEW zy1^SKRl=WU!JmGFd=uJ1-Whn2D{r~6daey)Grq}M6RrG8-U@mw`DfffU~J-ll{GO2 zr+mC{JrEpM;6Ly+aISJoE&`u3tT{-FCRuaPhivji>PQ~I=fT=r9lh&K_9QNzqs_V zQ1jIXeFPo)sBq|G>Iq^t6VJ;ZnO@R^HWTSZw5gcQR%kOFol*07BmFlKvw4R@FE)M3 zm(`BhblbilqL@wY8)E*a@Td8-=s>sycklm5vM%|59_`x)O=ro9Gr=Y?M)H(3C&)ir z`OcDm)DH5`FRgaE<(oHt)YB&o9b&hyc7$bjyyWqoc1!o2c!Lj_^1{b^+AUw8txCtLI6G_n`>>0XutR#Kmic#qN{#bnZL2L~*jL+l@K{$wz zYwfe-rx*Godm`gRas%sIu?^Md8tZG2XQWGA>DY**Z?EQgFMM6GE&eVWQATvq$+rHz zly>wk1Rs!%C}jKn9Ft>NHX_B+{4+M9T>9$Px4Fv_m^4oDm3(;i%gp}@{BuGjJ#9p9 zASaPmrN{l>*PvgWhm9mg?y`*XO`O3ff7#Gz&d2fPD;bM)v9DmmNwfzIA?64Fb<1um z9e*VEnQLEA{GRqc>6=Zm2fZ`G$s2x84Bf)A2fc@HfW9H$nUxbr_Mk$_^3dmGJ7wNx zxNS!kmd8$H50ZaG9=0IGxNSm~e6cg$l8x;^cu<_%!X|T>K|IRO;X%45d$AwB%6v%H zHWvn(WvB6z$IFB4W*TO*Y&NynZ~WQtY4r818AjyaVY?YhPPTT(-gp(Xqnqu-kTXC3Myby~%dd%KPAl@y~6$vD(9S zGn0AqgDai8i4K$b-?j~8zz@vmQ_tD*hx=Y@fV2N)@&3lGo8YVBr(SYd>l=go$R9O3 zwh3rW@k;0x*7;xMb48Zj`L(l+RJAeD`6kg8@kPoWy87q?rXr8{z4vJ*_dkj^G$+%KzpBfTv3uchP3Eg4%`~UPxxQs z(OopkkMO87hT^C_hBaqu4C&DnU{yOBgUvJ3qjA3dhBbz?sGl*MZjGTk22p(4!0rQG zT7I*af?wgo@|$H2(M3CJc;}u$T=d-Mi!nT&UzLyk|DX1&vT{_xH`?I?$MdV2_XG3a z;#bxCEJ^d=8z}pd8Es;J`W}3GKR%`**4rv%%yw|AxWz@_x_5roRmhG(cMkXsF&6>q z|AqS|ss3}-xQ(8ir;WS@xnt zThm%>_M%tiXi39&LcAmdeCj9B)-;CwRCV^rAC&P`pJL;732g>*k&TXHV|sx1vN6r; z!^Tw2yAU|jIcE)R-p#XRV}kAy*ZaI5+V;TS{`it{B-;*uinFf(d7qglt^2I6+52u2 zdXCOZH3#mUCvOk1?>xb0+RBe&>ts3~wPRRcq^;`NV<+^U7s-(?V5hbH9z4vMb6?{^ zBb)~xQ#-B5=-JqY^WYD%E9vY>`q0>4+jrOS-oCpAnH)dP=dpuZxluMCd9t%M`4> z?11d>yYtQS!pym4AC>?0aONPcKVt)*39VM*K+0an$^(o)( zWAU06J!0|UjOYRK5cTCh{3-UgjnJrQ#q}TF%{RyMAFgM=R$bSBxG!67dK&qQ8G~qA zYkC#u&uz@lvRvJ^1r%<#W+n62H01`R4J&Zy0AaHbU`C?c;M9+p+}z?>72Ogzvk+Cm0@d z+IUB69K6fkZpDAFrXS#);yMz)bM5Pi>-qlYkS`)4t|Kyt)EBOWtTiH%P>9zB4apQdhh;oq4HYpVGX{242mP_9^k)(;Rp; zk0YG=Gg*gj{Tq7KKgFq^*q=S0$J!lS{?L*@L)jLrJ@xb>%{Cn!vSc{&odd7S2RN^9 zX=MB_0{a;|YjMZ#q|^kDI<+`f4h_f&WDEY|zHT%+?T+M5fG-bSub zP7c8+z9b!8{@=&DhwM?l>wOQ|Qpyw$q5Xd@eB!%mn>`~@p7<`dL-=6J?eMd0{8r}L zXIk}?2ZUed(Xu^uony%lsapmbep26gG1KsEQk&cfOOE>P`YtayhDT;v{JDp$awG7b zNLIO4<2#P5GJ|(oH?FL5InRB`DrL~}KeONbiZim_`^|Xz(A*{BcRYAxpW?o2&UCS_ z^tU-y=Oe#bo#qR$(#^Crqc zZ_|b!naOuLcOfJH$fjnXuZsTSll$Qpm>N0UV06aHPeC>uf?S_Qp4OzW>~gN}pVqMd z!O520+#q+JdZdCVo zW{f@_{Q`Y>!fWUwC82JUcZ8*%HF{S}bYb!jDw(j8`R&3LGWC8hHvAOslLB9lyk*;s z+rd}sX~rqYv*GmlSyyBuTcZaQ%1=`EV-NQdv?kb(w8Bc}NXB+;$SXN-?{Z+NL`;b{|EzZ`h! zMQ>JYF7oml4;wEvy?)wD!1!w)GXKW9jT0@IpMAf{d)NUnU zd9Rs(EpdFix1_LCzYB{CL)LR~VXO6wzQ%XT&wrZronofXwQ}6=yKDyZdj&qB(}}OV z9Gb@7Ho2eW!y?)YVy_i#Hr;4!6>Ua~dWh$*&@T6S=F@uN?`mt})ezna4){3?Xc7cF?NnIJz4;q%8<{Sr&B>8?+I4t}53d-cn6*L$AZ z9el5~zAr9p;<@WR_|J3jztZ|1I6qBz58OeXMJr2rFZd?|znh1;=3x9GnIF-<*l@yhFLTj!cWfsFq4_l?)4a{i(CJK{1nH631Ul2^cK!@yUA{_(HeEg16OnbPS8jyr)% zb+xbbqfh(Jq9pc{e(Wb^Sasvoo`~;kZ1~V`He-}O&_*LRzWvOSNOIt@>1DV7;5Oq6 z$t(W@ni4#9%dW%TnN^TO-K(0xA-U|fmKgg;og@KpuYXPs=^I*|8& z02cVv`ljll2)z5boag$5@oNu1G1=Jqnzv^9DB9b{bN!p#KR=3CFwW$5omt%FKidzU zskZ+U|5JS39?Hoa8)jeHUDAGDxQ1^>5uYR2^{vH^IH&lOyEv3XNB0ofccR&LjMv(g zb4GUn_2=%80o)Li}3Zc?=rzBXP3^zjZ8QB-^g?43|x&s+jZOccxD%15pO^@EU zE57^@;2VeDpxlC%@A5ayi1si)ex7f@?{zK}q>k$OIG2&#=b8b=$?tQYWflIqI`{X3 z)6!A?l}5jflQORlL>j%1PxKK7(!_pp7kedSRV9~2Ar(pmZf|npND0T!8{%K<7b!H^uEsteh$GQP;l{y<5STo6=EuW!Lk7wOvM1Dda zb-nzLS2_O2!olacSLn0Ou#RxHrZX(zJ>KJ9p`pN@rM_Z_T4S*Hz4C9&;V)=<5t?taXOv>#)zT>Mfl0 z_CM}9*H(L+VU;m|x$WGW!kquRV+9%+H*%bF?`uZK!av7noI!sE=R{v7|BKdSrDV2^ zIpMaoM)>RGs5zH)zn%ZJZkJ#u6A#^f)%iA0pBcB#jyT^gxSQ`S{*YWVJ&XUf&sp+c z@SJcX^4=A+)sDZt+BI_m>&LN2j-~C@yxU>5KO}lLWom!*+jje&(K?$N!dYHc!Hu+e zI{0s2+wHf|#$Dn+VvlU{TDc3x@5eV%GD#!!{WRtCke3xt?(V14XhZwyl@GalY({i7 z^`!eJv^#z;?IcsC_8;T@?X)A=$8IM*T1Y!Oi?g0tYhUS<+>{m#&@OBLtN2CV8e-jQ zEIT{G-&$lCsiUic6UzK44FNOj-KujQoE~D|-1&><+oFpXPZ!L@O5G|u#2d{^tb1+i zA8fvDH06;uADq7VqX(zAQorh#&A07(v-!5HY|CG~(4T4`KO5_{KT_{4A2LSOIn8^r z@F(B-i(l@EEdFqh&p=;FHDan$wPcCa@6>aeZ`=IQV#Vy+ZCq~Ll{L~RRGs{bmrO6E zuc_xeb6delHPdy@6FGbF^j7A|Ke+KW_Z!un`r(5XtUH0#Eze4`+j(R0gH}5`&wl2% zMT2X4^rdg@{cAv^bF%crguUx^Gdux(AP>K4KX(F=ANRI#=o-J7&V883z&p6-Em4P* z9PR_x?dUvKzBzQBc-)A@iS=wBW#K8U6PY<1KdMK~`0{-6taJVw$wSxK$$qzU6nAN{ z50~xF4?hE6l^&OeET2CU->=K@)hEt-Jboe(=1H&w&{h3^e&V)T^gQ|U?cnT7zLtJ` z>*q9@%i^=gO|aTc@#@qO{724ZSkdmJ*^b3V>ABDZJ7{Em+GG;1R$ed+e{7<+wT z#C!dOIS(7LV1XH#Dw!P_H>BSLIpnvcM+bv*;jdzc5pHFjYTvH`9-oi>%&3`U*%ICg^vr|*SNhsv z_a&Orc~g6WUNxA$7$14?lOn;>Tw6j~bnhw?zo2e;M|ZY$PG9lu@9jMJZ2YV==ImYH>pM#x& z{~zDztS9J;!$?H9Fp~*ZIz)#oO4A zZyUopf8-+Wsbo&-@WFKRRmxXWYg~4XwZ><&ua$ivx91w4 z${OchI<4_>tZ~7h^<9tLXs>Vi1*O^RyVxkao%w%%_LvEb`=NYn1nuCnZQ(}i%u%|v z@NnEaL!pf-=;8C?{1AIgBF+!$IoFyWbgP~?-)-${L!$GSX>Pl5Pfj-n_uk02=O%(G8>zWaSvQu12@fUM=5(d6G|=!#sX>{>}Tm&g6IgV(}iGWxnx?wmr&&Y^_Vb zuOW?`oT8)2;M>Q&ALs&+AoW&z0?o_TaPI{+PLmkQb!)(HDr>RPj+?6>zD07B+E%-^ zZZjG9SV!nB+8YdHh`~?VGQ?`x;!?j7R-9D{zIwIz+qHR#!6n{Z^22t@ckrxn&!Nnc zA0Bq(hn8T0w19pYg;I92fi?+wFBVJZAU)#_?=Ss@I$6C}F%a*wE z!jR~Bw4<^MDYNOiCvJTfZqbF&8*`vp$?9#$)4FH%cw^o6M1s6@d6G5O0SRO6AlG>B zv3}7RYjJ};)-~I^$C?R@y~p{DgmFqv63@{%D=C+pDeq^;p{2yiU*JTeM5;!yi@V4+cdOI@T&Y=c*8tAhq&>6MzdZkCJ@as`~>fg71N~f7)gwI)O z&-d4Or}ez=vMZUNnatA+>=#!=m^X_TiPs#$UXcjTj0AY{fkki#o)f|H9S4?+`hX?H zf+a0FmUrTPzarm)_HE?I-8q?qEPmjHwksXp_cvncd-4PFi8!>qX|_$cK$$#(6-@CLg`AzTCkH+iL)MMCb-FM<8o2aWb^0I}8o^cZT z7W#fp;};&Jduwc>r<6c(p*uFwHo9nM2%JO)o3S~P!GLG4#iNPwcgCy!TsZCo4x6UC z<47ML*z-;>^{>8#8^6Iiq8}gqz$3=VU*`8#``xm{qyOOdTb%C~Svcr!=YO6g_sCi3 zcAQB|o|pySQQi~(S>#?i|Lw9~}}OG50-8HZ#Yk;NLXbOxfaR-V|fC<7j+rhu2ded!%y9 zNFEt@R&itw_Ylr8&8OAh6YyO89XsamyM_JxMk8~a&N_EtGo5T?kBjiTkTSmy|48D{ z{EcR0p^-g)J2`E-V5MI@`!NQ^{w;#i3yaEd3pw=M>Se9~{HOqsiczbIbzyT?*IAg_C?X@q78j#C;`q z)Pbw4B;!jp{HD|v7d9}4Y20^LZD!9|O?~-&raWmz0-t0}uw*l*ea2Ey#=B(Rsr-03 z67fs^QZ{X8WKYJ|*(?yvWnNbtAvVIw*Eai{K}QV@yXZz^zyun^MhcO7>Wn&*%G5Z|yxiNopXy<0yyNNz# zqrX-IZ-*yy%QNQU6%BlU(>bPvlK{A?LC>ke#|}T0Lf4NmF(Dj(Wv$vWxLhmf1pRw5so8MgUQHScT~yZO=UPaNwT z;$vNiC$cb~lU$GwKP-bkr5V14Ja~ORyuJ)Rwb$C$xMQb;^HO-f_KT>)8^x=iabTL$ z1yeVV{-Onw?PufWLcJ>GSiBq$mLa`h(fvOA`I`eQL13v*fJJ<|-hrjG3zlv^J;=e2 z<;P;pVK;v6cJPzv7no+4R!%1I_G0KbI4iKe8u|)}zM>aIZi2q5ptB-qOEFH1pw)cV z0C!V1%*MV`MP1z?nCHtLH=Ffyhf_ZYO+6@E(29EK{$kct zIcutc@@LF+VnkCqZlXPVZOLC48!*1Q>>+Ht#`pr(mU0=fHy3J8tYTedRpndj%3V{s zgSypIzoM$Hm^`72#KRl7&+4||8c$?4c9%AIZ{%qCwyE&^oeL|Uj~X>^l^GlNM7XD? zV8LeYf=%8swcpf+WaGJ0@{ioG&BynnYb&?y`cCEZ_^4a!le$~RQXXVIq35*tipN_2 z_x79mJaYO#@k-sdh0Y^6HHSN9BwH^_iM?^DeeUv0_kcRgN8TWa?re*al{{rbZvme&I-d&=vNAU{g(3rcoI9{jyz zIOIiFUQcHq{|tHEl4t%EdHw%ba$|aQfh})8mng57U|SatxrukSY;$~h{Up|g%hv?Y zKO?WNbYQur4_LA+Sn#vpo#gco8f|%fyUtEtI@6NZhwkf^*AHRi>n*PbI1kC%Yj40P6^oVWMu)>)x*$!XF_YoXa7H15)BI=S&(-7>egZaK=) zEgieOt6M&QD1lb7+qGktPt+~Hx5A;-h3J;F(SiQcKFXn0bjUAiu6SqBD!&<`RnD6F z(k(aHx}{C4)Rk^IL$WV>4Sq6*E%}>$=EK($bj!=oEjdfyiS6FfEwT9yvFL+XE6&uc zeUG+W`FlCGRpE0J?~LM#)An6<6?nW7e9lC-oDpeX88`x-ZT)hT5xx<=*+s9ka}2!# zOAr0B4|qOikC%+|Y#;F4Zo!il{cphoy^imu*I(ycoM!pO&DrbFEAU+A(krm+;8`@X zj55*drh}8Lv%lO+yXo~F+Oueh`affCEP7>rRF)_Gk~#Xh1>cb9o%PVB^UmTmyxYh- z*}Qq~w!vY`ewlKYUaR=drPr(JPx$>$%8qA)6EAKPjn*2sn&gf41uP%ETieK+C0`I9 za(gLf{r-W-)#=73jqvTFlZ{VSW4H1nOXr&-zFf2wn~R?NInQsHmTkiCcb?zjJ@n)o zgfArZv%bfB_J(Zik{R^T)y`w)t=nn8tDXDJTPyYKw(}$2v$t@^rQPo@dCxPx3SI4P zw`AC?g1&5s(jPUin^xI4vV02{53u;q{yp6`vG=ek_T)oDqNh3YYVNe>byiWgO{_n7 z)}EmD-F;!E=ITa!uJ$L`5hZ8N>t#p$7cd(G!#{K;43+L_z;%r7y*BeCJ% zHS>FWPG%lju|LLG8@{2&1lQ+7=XTYP5i2!k+ys5wG|LF9eh~Y#+LbR!mN~qGvs25L zWa_AqEAz2YK_j;BA4s@Vhw(l2lYQTP~8{UiXH6` zcZ?3R;`WC{=Y7gqu{ZF1ryAI?<1b%E%`?#FCDueb0u-< z+*>%J!zbAS*@wj0(>o@Hze)IL73tkT%J;oc&2Re#5Zy3=C&(Wf_|*Uvj65Sg88L^|LTMfl0g;VfYz zYvus91lh88GQY~BDc!S`e3l{3%d%_BV^6ZzDduP=-|2hZ|Mk7yaeRT&qmT2B7^k5w zotd<=@3N`TX({wN1-iWm`gMJ=JQn{p@SXU8JOvtWt3#yRH`YP-l? zXP4URY{#^tsVc`Ws^BcviOx;++=d_XU%o3DCq4Q{{$J8&^X$#^p*6vI$V2XV$WdbV zYaN^54(x-y*Y=sLck%3;&32!4+1+dVB>F6%&))0%dT@}qzU6bFbAqcV*ZR&DPOP~d z5a*)rYq1_t)>puGlm0s_ZcB(3tK_3PNZ3<`8S$6RNmqe_5i)tyHeI! z5xIMFDa%VT8`OR}Ya%1bwlOT}Ji2@*bz8~HP(}TzGyk&3w_xf@|B;fVc}Gec{Hzzh z=_l=FdV}az`HnY3yBne1+0gE0Xtx5|odfN@5ABwdYxR9-_W-sR(eBcMK&0UeBNBr4 z^sW&a-N!r8?JoGG^030+W`rEN4M4XC;l-lcdgr@stZDJVL_Oy3jf$`C84ofYT1xaq zO>5Nst(-fMlSSuK74VogY*}uM_8)0O_P8S6XA|$|XAD{+$+b63C}Ry7!16Y*RKc4M z0FV2fY!dOwC(f@b9i0ZIT7^ znG?;E@+kR?jD}?RyZrSy8?nwEec-MXAFh1NAc$ zth`X6_&wWNxnrQ_<9oIpjlm03Ga9A>O96k?-n0&Xz7eSa-?H6Rc;BBmd$O^$u-Mpo zh^nZJjZ+47PaIuHEtFsMVD9=27p^=4yvWttX$sm|kbLM=2AJGM{whk3;GMx~7l6(%u@{7mpHub!Ct- zl1m&JWFP#*;+^o5b10t+KM`E^{xc-{CT)n9zW0FrjnmHfgM61lJ@KJzzPpp}boOh1 zml55_cj9T<160<9d*~{S`fBs1w0Y$2mm`OW!T9tW9`*x@J7 zm1pEPe(G;A?u2_T9WLiTY)rX%cj%*>7(X~)mK*t(BfexCs!`_8u#|ZD38?b|=NE zr$_IC{u2E~)vw^|o%2MvcJcg=_=`@b?{2@zOe^O}5I7d`XXyO(YuSU1312+NPo5j> zSJs(#3O2OaX0nCza_siP`80nkckBAByLIQxpB-xeZ$aiRguJJHvje)nX;5)&G0!)_ zm*<*BX9IWeF5>^q@aQt~Fu3jeXur(#^=N-8?HAB~koqZuk{k5B=1Teq^(`N1_dGpT zJ{ftY1lrX-2|u%Z?BkP@kkJQ54u4}1v^*GEJ_-3e75Us7&K}7gVdYgakXg*AiI4L; zr;u-x-}VoTFnM}@T{voD*tZ%#y?9b2Ufn-}V^pO5Kk)s4->g5#n&}^C7Jq2xyP-zi z^tSI9&5HNRU>&p;1oF2e2iE(u@gFsfTl37&@N$0Zu|ejWi-uS8|3Oc~@Cmit0|Bna z;`_gD$CS=7hvVy76%Vw1e7GHXSbaU7&{rD$sK3Sm=QqoTZX7z_=jm%1eT}EDGwJJ5 zPt9AI*&Fw?dF@(eKNW+zcIRQl~qgM0&Il9~$nr=G;6jx?Hj7=i-3}jp^@*jXYcuS+~SA&U*+oKE#S$Zo?9mQZ{;8CyjE?DU*&)9J(Ebu4&!|=Ba^eJ?K60Ve58#pNW57Sz$LmfXf)9Q_uI)_j;Rav#gA3&m zv-ZZzE@y3C#u~kpwR#CQrHdo1T}vO)cUogX;55F z{-4AD>SNIT=%>tO{B_B6{UV3X)gCv1K7I7xbmon+O$@C>TPWOySXYb@su;_oQ{?Yh4y*H3;o<0B^;9ju3 zp}3;$=aIwDJ}++{ZLIg1jnn=33XmJWbJY?vwqdX*7Qfb*-(KyF#9uKAe@AZm&JHs| z9@FWM(w5~fw$=#agcd#LPIFn_QLy?Oc*Zw0*}qlWL>Wc$L*K|kL01N>e&WASnJp_m}` zrX_yYYwQa69l^My$*P zXiff0^6fry_~>$zm^6E#M?ucT#OZx&N@o!{!L7If=0lRoGt;8qvVMm|4`3VBIqf91Mt@P9 zQ`?#7v0maXhZsld;YVsW8QRwxD1q)-FU=lg*LwE1MFY&R%G+Ki7L|8DhhJbTUauIo z?dXeb-zjd^`dUlBthe1ca|eajFkkI_>+bKH`9}Sfo@|U?wa}Q)o}2dAjiyC^t3`{Y z1^9~&i-x{HZg_ZM_JBZFo9_G9Xfu!V1Gmj}wE3tPe}4Mjt}~wOb7>QXrpVc zu$d>$Rjo5ux%8VjSLJ+D!u&L`w+HvcTUuu`*PO2o+!LRnnDHkjTQEPAbNH)8i{rsE_+Nwto?*dK11vG`$Y>F{1vH<=cQ1)$FEpC7 znaAvfp5|;~{iDcHdglY)%y?0R`#U?ckevRR_WBdd z(VwB;O0Dq(dU@#M#wuRTG!sMeb8_unnUeu@lx_?s8AS5J$yU%}a^ zBg;xA)gC7sjMlF9Be(q@)4uk%8|%nX4L$Xat1wsxpOTlQ0v$c3-yKFcS94Kk%TkKP zS>v?f-o@}Z`Q2<^HajkT3_kX5{P};qcWms2fqx&m=X1WCiB`UdKhclI9AeCFn`%$F zLO^!vEIF4Gw2 zx2$nEc{d-y-uQ@}w`?}$6?b&k`+8!%Tc~%7U9Up*rUyF1zv_lR(XK1_-RGGO{Clx^ z9f5u<_bKhm^a9$5FC2hgk;%LdLk<~^yfy;4Z6xyBsn{F(hYwFy zoSr8dTIdPauT8S{IoTc5-|xZs-II&L?N@RBMJ#%}Iwg{A8qMT#-hHSV|A7>9efzcM zddV_5kqeF}M?lTO2Pb-vV`>&InW+77yR}a~!2kD8++M_<=}l_hfo#;~?ccopcI~0Q z=I!`F;2Al6(O%p3{OvX5RAH{-obPS$W=&|EbADvUDaH)NAnw1+h_uQ+$NAV^?}+H5 z50GoH&W->= zcmKp9;vsA59+((}m#(fWX)f{_ouv!BkuuIIYU>tFjK>G_zF}hHDH|u1FGz}%=aaX! zu6|+#{CL{c#`<`CNTmFTKTBJg^U-rx zuE=!s$L+{%lDig!$!|iePMZ-M_n~ax#Ar{(ZZEx3|9`-FtMnb^rB?l0sb4|;8uCI6 zrHyLuhRw(aPltwE6mK|&|HaQ`qY03=EC~O2 znRq;(>}vRysc*^IerO-rUf){!dkytM=o{kK59k-VHmDQ$fH;cFu7~EYgZ8gw4P3)o zxEdb#HR4;!E#8FQ?W3)>2YUA5z7uSE|66S0g30A~ zQ)w&l{7LoF&>^x?4J$X6wU6B{{WL9lK5)o)$jXfg-c|N{=bg)c#?qeqzj&+84zg>n zPPNaUloKO4vj18Gel?Ih7#?f|SqU1XQrPs~Xts8JhV(I=LHKF! z_220J2K(8C;|9?K?R?Fm2kx^XS2K3AheGJBec8=co!D;nkYzWcy&iTmo~OTx9b>I) zH=Eo;{ti0w0rJIjIgfrxcC+WY>}IL9{GDJodoD+IGpCO(yBW`g|70JpJADW~*6cXN z?nlX6_9D0t4MgA*dMEm8a^A1uz2pm(HB(Rc?Oo@wggQ@9N3?xW&C%tR%!8Z1rT{u{ z<%DY~&xW@hL-Y6UwjA?W zJ~!-{E$P_o8qY88Y$_>+SNJ;Mt26X#e$kk*(3G7btKfcqE!~5C=Y<3CKy;7xbB*I|#!OOLL251x@1U$Cw9EMr~v-UZvf|4D+6%fJy0tH=$b^Vf6lH)0jo^cr$? zMl*a%d8PTuWMt!k#z^ikA_gRfv*23eleO#-Wt{mA=G!v({F|KDPW$NIhre55Y`qD8 zf!+9`eB>RtWwB@AmhH9G&8eptTR*Nfwr;8|YJQX7Z=oOf%t81U4CIVA#fo=Ww4^*H zIFcXCime6@EsQaF;IM|K^Ucl(c#B?Sc8=j*N%6i zocw>W_vZ0Y)%X7YnHiQd37ckRsY#%<3D{LoqEIG@O8~96fa20hklvaQwRJZtCLz`) zL@iM?mb8~3y|Bf`*{cdLStKZ^%8tsyuA(D*B}RU{x5ln&*6@I!)QOAZ`|qkM4G?K z=PP`^%;yiUMVf!l=S@Cu@R9$8^k&IjlaJ2)m1jqCMEY**{$DcMnUD6oPg(Pc?s;S9 zBRMWv_^rF5v8SO0E_7@+`$`Y{O67%cTYJc?LGqt*1?FpSk)*Cp8*}a+Vr-vk*P)e< zNeG@CAzyGg_Zm`OUpaMqR!aqPuAu6+kRKaF56^23m7M!im#r5&7j+KMXXW36@1<-; z74$c0uzd~wkG=DQ27E56kztGYzQ+6d%Eq->E$_2_27YF}?_ozlCzk%V5TAzhH=;R8 zweOIB!y(piw|m0Bj5o)h;>*oF<=c#HKYN}!#u5CmdPjuXy=&~bMBK;r!N{y#wzAXq z!MFswj^?tn&j%wjFzQg$XUM4;%z50r&Lc~9l%^RQI`%Hv(ZN`QjI#`wl)Iz&HIwxK zcgXcd>=D;zROMTHCfc>~$;;=V0-pyzzF(?=JrUSA{uGXnMm_z!0BmQuhAq=NTt(eM z!9;TtOk({!Jis~GdX^3Yr;kxf`wH3>e$VB50e&!xfY}A!*H$j`XSQ6!xaEgIP3UkX zx}C-%zvAoozZN~UVN2B)LW<=(#C|i#SR!_g zy>xI@Z8$hu500kWIGSH|Q>Y$Xk)0A;wQ}qRfqe?F&tQxYHu=mZE3c1L&%k7C!hhk+ zLdMr$R|!1jzZX2sUmeB&eDap54Xugnf!3aQg!W+3yx_65=&Ctu+({0y*Qg()y3^ya zZ62g9qj09$#+hF|tn;~?0Ck!H$Xio0 zXBBnURvj_?4b0Er8Q0tAhmG7BygTEyD_%bP)r!ipsot^1Wb57@?v+LF-QqDCw=l=w zF-P+xU^`MapY(uhO3fUdrRY4<>oc0LWm;zdW~~G-Krb)56gFhkUw+8sP$Jp%TM9-KeRXX4Kq0E$1|zEi>9xyVfdj?EkST~|k~RPML%j%V;% zbF+9#7j>|Z!X|3LWiO<>6m< z*oejj%BlAzyk9-B=-1}O(K*RKZJbdMHy_C+&8LR>X#6iY<6jmXzu&qpyVJP9n!&~j z$0x1r0ee2QAIq!$mieqrn2+jkS#x-lIXraYb7*nq@SibrKyT0-o*xu5hnMU*(Ei_R z4tFM*19Y=4mZr*~CuGTF#U6G-8x5>M;xi4{IVOT{iz{=d7JMI?QyWLoo)Ko>nU(mi zY$WnWtl(Xfch$#VEZ*u02sg9oPxZp|`?LJkxAYKQdrWp0Y>1ru^F2C%9N;@UP@`{j zsh9PQu62a(R(ROz|B}59I^bLTY4M)K@o2vJsnPk0KWIERs(tu?0l!*qwL#wGhs6KJ z1zsoD!-LF$dAyv=))P5~t*2J!r1(g+t}!@k?e~#d&;Qq-g(m90HMLP^L7%@XsjX*| z&ZF*4m#t^HW9uo&Jj&LyT(%yk569M{KK}hv_EBf|q4AaL47Kjc(3gP6H1eqQ`$+ZY zX-k%uHWBX0@L&~qpgtU%k^0G?AID~tOMhN)BJr7FG0$Z2jO0}N9r&lb5s?4SWIIu5ByeS>tPYXSnEn z#%niWr~VzjQ?a(7n`)0_J#F>-oIi~G2rY=I*MvTtj{QgTv)~a!GnXLC9+ew~ZUrk0X_qm?mfd>WH%T z_>IN+Q(M7z>AvN(BYhyq+!r(N#CNvP-xj++FZ~sxhZR_TngR8f3p`?TB9K%CKiB`T z{9F^;l1x?qlbG+e#Rb+FdNl^%cC`h&_*fIcE1jAU^QhsWb#dwh-B12CD;_+y9u4|p zY)r=Y$%iL6*70m#JsQpk9%8<&ta~PNxzozyM(r2&YEDg;GHSZq!gbYo()%~s@4xzS zWWCN9V&A`JfcL*+zaKju+0B)^<8Q$YHfuI+l!P8}6PLHtXlg^hX<~k( z9E|Dkd-0J~?1grrH;T{SdX>>M0(r86IVlFL4EsPWXTM9?uk6Cs9>h;(H@-k-MD}6r z|7X0W`dZQFvn<w?jjDf>Eo4-E-7~WMZS; z27Vn`Yw$yRl+S8Dt$bGT`4>K_wVr5eGY8NuE(Z4mll3vUmz@On{5I~@*tpP#d)USL z*ChLxxc3ZWuW_H4PNDw%;JVXaa-HI6n?@ooIrt#hJ!bbW9y|{?&9z{aT;3+r!$hZw zBNm-X4@=`5yX;hA0&IO@G(7BkR=&5<0UR|pltKU1@sKKw)hSBoa{he?Ly`%9*?14VSuSPay!xQBn4$e6E@)7&B1+>?NZMJNJdwU5m zDIIx9s1%-A;h7&QugeULcbVIO)AHDTsQ6$7F>s03wbr>mI6o{pGdxE4E#Oqa9P+{E zr?FoZVE-Mky{LSOn@a=p$mLz}zQnN~D|Rb!TiabY=eE`qu0Y@+Y3FF%9xTyzt~53|pmcYyO$+3JI=lWOU8Aj@KFd~PAf zm1I!aS2@o99brt? z`vd7kI%l~Fo+JL_oU^QoIcF)y*5AoFOAR*E6zLlYajR|UA@|znEQ+zzn6w9v(X->m zLr!%zxnTKkye^_`it1^)E)6 zf57J-{I}1}5yv^|-nb6B7Ie&E~G?V=l`+;=@il3+6zzgK(;Ou5y-W$ZnPq6)b zvFBK^>-@j;N&I{#IDWp#YZ$K9`}tE8uWZG~mm#}KvZH4|dKWos<^9`24GE2dy=Qv0 zVSF%=bN08%1410o2fO*+$hH6GJ5io$zt@N!HHrO4qAb;3So=izENHK^i# ziHYqr&_*}=EaWfy7Sqa~cX0kW_*lo(lSt6vB#$Ly??sl|cD^_ntNtIOy`4$qbL_rL zXOVuM+r@K=kKfH2Cyr11?|d(@4B&yr_*UbQ<`wi0KCf#~3|B(V17fEJ%z40hUNq-{ zv!=|U4t(0j|F?b-UDHa%S|`+{bYi;_*R+QBJ!9j~^NMt4DBo?n59d5jeQf=deU#XJ z#Ny4_;7uuc^Gm^<2Y_GKAmjbm{kY&GeXGINx6o0;Kj%5MA^p5uc@8);F0k;A{i%K3 zw69O#x_o8y>=)_Bw0}?Hx2|_@L;rW$VsEN5wa%M3%cIS7-qru#@ITppw3YfA)}EP| zjKpzkkEQ)m{xH^DbBfUsUk9&3;Prmyax>qp?jcPllQ*vQ`9Vz!^gVu1(?j}R>S=mM z-`}C$(?`^*x{{nYS4Q^^fveb`C%{Vkr3!4SU9>sS-k}wH@jPJ{R(#e(=l2 zZC|uveru7G0L`oM>p@jiRB1a~|mCH+Q=%`~LI##@^q- zx5=1^CADN@_47liS*QFT9j~x&UR(bBppc1NEPHxrj-?cpARu_#Y02Y_ZaQ5 z=Q`aJ+OIu)hl_YCH*r@U?AC)gn;8tOhmg~R_`bRk+xK~fl7nn8@pglVz3~K0e6!vl zb|L5)>qGsYP^Px0-A_N;r#b2T2g>VBo}=Nf0EeGWS*v1sNJD<8=F zJ+vEHLvIfrMy2whGv{av$-!wu*LrA6crqL1>+UF%EfH?)KLUhwnCW>;Z4 z_JGJ+uEI;9JLw)l&dc+NmlTgR?!ymkaLshrNygzIG3wns*8)B&PAYObet*gh0zL{q zt(+ErZW?xrmCjcnppf{Tg^J1=)l z2{uz_i17uRjrKh3mzBUTc)ri_dtP>#YhLg{Uwb#t>i*2jc%F7Q!I#X1_#croWzyR3 zzf$nM&&*A|`qz6Weq6Srfc8_1{zSgXl&!tb?c1w-U!j-Fo& z|J+D!OCNS|@x@nJyS4C3%V(6c!=vpT(L7{NkSFZL4JP)E)LtLHrCRURo~#h@LWL1x z8AETuU%=t6l$z;}mbkaS1uR9Yxx>h7g}m&ljQT3*?BN^0UcOH{d+1su{EMDF%;x$t zo-v`;I@fj&az!xA=lL~P;je;CeD`J-IH7i3fnDIfWQJmfUfUblAef6bya(`eVJ&<4 zU+F*3?*q0MGIz&rH4Ipa&lT|OO!AIz#fJYy+FoVbd4B5}Zo&0E&j{c;!t&ext#|9n z_u5lhzE}0#&^qLr{3%WXjx*dNdJS^+j$#bUsXKiVaMZP2;OMmX75DIE(hX*~Q+j2y z`fAG7mEZW!l$IIpkro_@|IQMh=Dg-)#lz*#aP`v!diUdBb1D9QUEXh|STyldVDr4A zcLU?we;%cYMk^mq0!`TQb-P3prniqK%An6hcAlVI#unHA*$Mrhb?p8x|CIfEn1j|& z^jv?Y>x?dFvfXQ>UkbfQE{f;WQwL%L*Sy}Mu=nRDwx(Ow{vFm7o95rTrW*e}j9t7C zIo@6YfAWJnp99_z`~OV%AG-f?YmWtgd4YbdwW^=i$NzTQ`N72hB2OHj|80^!KlRkU zwU%5hIk_L!4*&Zedj^MQvZnjO-$ciJ<||PiD86XIqo&k)n$FrZs7d+ux)SuxiJLr4 zXD=MwRF9AH=t(tm4v>2;ILYnTxy~Wz;Q+CeXW~OG9vYl>G!Gp^j$((02F{M>p%rJl zrW}O!C&D*V;F&4#%FY`;Gk438vK<;%4?Gj!@~!3)a{urQPfc z&y_wnfbVYwHe#>GyDXLQ2FWubK1K~@$&~OnxYo`2WsWD!qFHb1j+F(w(pmz{YgSc7 zD8QM}#qf`t`Cd#r;;WCr532FQH^%n!)yLomis=wP$g%m0;ylC;syV|KKe)!bgV>F< zmTF>V#8(r?vICs?LXt5io0s&t9^kIIjb?5p@5#qo*EE+p?pt$NlGeigZ8Mp}l&Y$b zA<(3%#VlXUz5b6OBHC&i&CAF<+4W;2(?{xmBN#ln{u zKlgh1sD1_?Rs3KL`ZeL};^{8VdmLYO@q$bfT>+mJOJ>wcJYWAOAP-EFVC~y!ID9RIc0`Fe+fE>3x8%i*5xU5n5$x9T|P&B31Y=RSOYBB zLu{`m4kCyxLH?O)Q$E~_iGd+kdccb>w_=$xYa8NXT(sWAqS!v&nSuE|b}b4U?{?yc z1Fg?fJh5^u{s~#87!=~j=V`3!-x+73Uv#o{%|8KO^)nd5&b}ClwB8B$b~|+7%yS`Q z8tuxq@Iv@-75{}FqFEChH!Zv{w{q42Vrj;7I=Jv=;Rt8SKP?2rhz&)-8Vtyo9xGvvmRTtu>1uh|hFF zgO8#Qc)=a%YuLij2Qn>vAXoBaGdOfAIivm%nM_`oa2n4&_=gDb`^AL|!RG@%D=vh_ zulIRcs8#f%mH0@Zhtk&nke()bA4pGompMOPaZSk4)$Rozk3);YZC&kt#=a9>4ZUif z?!5qf?+3m+72gx1tG$HIBA&9-&Kdh#bhW>>n=LzSU2Qjd^vT1G6~oHN5#pjIF))1a zP-Mfy%0qNt(bODQMr8@@k^4qAlb2&{CX!D<^tW8>Qj%p2mHAVnG;D-N@;o~Iaz~dh z$JfNt<*9SD3|!BXEV`Fkl&n*tE`Pz=6Ov`?Y+1IhPnXX)T9*A<^+AB835>>m!x#SO zoPIf$g1k5*Z&1?|`z$xjwG_I z4c@Q?dMkk6E4QGv4|C+%X!gD2xG}u&OzmgT(a9}^Y#SYzfj^7nPeJNyD+~UT*&@20 z1^gu6CZdx`$@l5e92kZ;lUuOTL_acyRwd^_Iw znCFHspTInl!2(`o!Qw1nAzAjJJx|F!Yo1FoTe!DP@a2U%%`dW68cA zOZH{=c2GA%`pm7&x5tuw{qv2=KIUo3zSod_nU3s>qan$@`Y(`2g?9Sn9==kJ+{;Gh zN%nOi@04S*8+?)6>#^mXCHvOQCZCQ$T>vBO&Gq=vDFZz}Cx>hGF#n$K`obx>M)=*g zeC?Bdaku{qCmHSH6_xOc3*aRST*G?A`>7dd>mJd)$TjS18rP<@c&jFb6f2X1Je3R- zFP1!we24!{$kT#;dHOW+;Q1JN`p?MIowhvf1dfu6iSl%7f;`Peo|<;d*QN9){L1Nz zks=N?7|nMinilTofUA}~W!-imuP#%LdEQanm&U68opHv>(+Tj+WO!139C;e`P09&O zp^q}gl0ytwHZfot$6Fso<*LTz%vZ1-;~H(rRne8?s&G&3_TMv`jBq_Poyjvt@p*7`CVq^9PfZW@fTQ#PV)G^tPbxj& zt&+mhS0a-S&h>@gyvG;Px~yhhZe~qXCm~0=I{87*q%Do{P#tiG7f4n{^X_K_&P_E| zm}S&}LZ0PP)8@kkx1}5<7h&U2{`}jqXH2JkOBVeE*yHab+fO%p z7ukM#*uNAYkN#HM&#`oh$5}t=6W6fL(iu+UJ6@m2>dm$Fi3^zTr_m>b*YyjdaABS2 z1#boC9N3}PDTmgT^e&fgrF+(p~1@TE-f_LtOokv^z67}=a6l~LQ$dR=GzoaffX zJ~yA|=2Hu(BeFig^+D)Gi8$VnL=O^<-<#xFZ1)yD$S+5Jc8xYY;4fZ4Q1yIZb}2*hj@0(cZ>X8LoW62#vk=9 z&)C3p@&;M4h4}XxLyP@)*Fop3|Bxb2)1%ml-a$8h3wrnqb~x#2TgKV2M%S%CSCif* z+k?(kb4M55zK1=7cS4cBd%`HcqqEiO?5=Z4lYIBrV88xzAgZ_ZB(cAK*3PAh4dVU0 z;56AFEWK^bn0}qDGd$F?_52fX-Ud9R4_Nv5N?cVQ?C8O5MtcW##J7P2x9w2yZ77ir9&;)+jn+As2`{a=LBrv=4Q^0Js>~(D;o366+RyTbLm@RV7 zH_;0mn0Y=S%pQw@*|OuoY~hdr@odc}gjr$MC&#lQ*(isNCFfHV&(8T2Fq<&$XgqtG z+;X1;&#sJt+4SSV%r$gCm|gM-VYY|!8H*2o0@_@t{nd|$_rdIt|C7_^TS;J6@d;se zQVh)Ar-rFRoBJmD!aLy02fu`lhD~H)9X1ho(Kl$n)${vlZJsMaU0F5L$qUwZ9@Mvo zw9kVqUXt5y4;>$K9`u|&-^ygRZ~Ht5ym~(`+bv$S+}T5J9@&p4wB>%Dr>%dS2}RF@ zkVQwG3B5q=h-7C%|H*adOz1A^jee3dp+k$#r7kS8o!UPKvGKLtXsmC&!LZJ*g7D}b z^okHRfj9YGxN%IAN#0kuwC>G<_(&XDoRyYU{`mJ8EqyXP-UT6G}g496mIZGqN=H?vClLo|V(Oh#zeAv`kYSoHoz6ke*$`oTJZY1`glp zTJb03Z$4wyUMJOGZ!((0)kR*u@%A`&@%$a=9ARrdnpbupgzjzCBG^2n zDGwOtEuRiA%M3ihSX%M9>9EJrVUMNL84J&AEY3T{=vZ&kzTlQxP~!KlW*q;Td>k8j z&gs+Q4L1$8`fNJEKAm@#(&w-2KC|9D-yd;j_U4XJeS^^-YmG~P;45scJ9}-t;&srQ zGI%zZHO;^8{yDo?m*9m@+>k@^lgI>DIFjQEn_o7bZF~2=Ih|ivdqdaf`A@E_AbkWU zxx)4OzQWzU3_Y-`#AMB~0=J=G_xzjBkG>~+rd1mxFQa*-8<=a|zfXU=SnF2KVwdq7 z`({(txA0S7oV&=ASVdd8wENy2F4YrQe~@?75BuuAF=-qT`d8nwk8`FK=t@|t65v** zwW3aw)~9vobZRDnFG<$udx8Odyz(jfbl@)hIQ2MvI?rm2=GuL3_@sS$hR6qIUEZki z7JhgK>XYY$i_Wv^^9;MsM?OWLnoTDoG#$xVXwAAoT#^FHR7fk)z)AOAaz`4qAO_|V~a#k7alea>zozQCydo=lL!9wZ=Hy=E?kcr<+ROG{se3S!aeA>aEW-w< zIjE0v#vMVfO#~liT|2(1=%o6UrO<-=q=uF1^IyEwToVu6?Abn(K5J9YjgJ2c7cw_} zt)4lX>y|tyNs0QrJz`q4Hyqk)J(djOd7JK+=jk2bJe9VBPZjsm+|b*hxl8(K&VI+D zh2Thw<|gsZ@$mQUI-J-7-R4tgs0?_1=XP)j*yjUh z6F4`#@Pj!y`9|T!>NEY%07L1_)V!`jW?{RmnbSI9s$a4MSxCt!BVBObMH|vRY+MR- z0gGMe4bnZH#LiYDAKQU+4;yZJ{!!ZfGi}Ae`3JWF=ebA0d6Qr^&D%7dF>U9aPXp&i z|4wjD2hPIrU z*5UoUnlqY~vJUAdvJOec{Fi_I`|y_ejCmI@RlVHqD)5N&tjpIJO$(@*ys4SB$SMl& zODhVOv!6LQ*4KWBy;_K8=JJ0(y8ObFBENKwS9n))QU2nu^IPZFr(@sMyIHKu8`R03 zMqdZvB@yflU3W(2z2Uwx^!lU5cI?XQUtM}7`^Nk*kiFt2`ui;H@1y?}vMZ++kqg&l+fLe36?NNYy;X;nudvQjZs)y zWQ3ogjT~|Z)((;FBP(z+&v#=B$ZwCH>zuxUvv_hp^>VHJ7x;#3Fv3CJQQf7*Yw@+I zDhL&Dej`5=jkCI)v+D`eP(6wKZl27E_#IOd;yiqj&&4PC9DI{Y@KG+tk6L!z|GGwg z)SAP7>OE-uza#gPeB?E!R{F`nX8tbs1dk2OtqdJr{?cXWBkyoszK$7nr-a_-w{qF8 zLYL_XN9JWv$0B`=vHfP?n?{Z^y61>dy5J-}DjG;V|E1>b!5cMyN$3Va^p z?a#%xuLZ9SY^LL?k2KeN@FmC_-js8v%WtYyBYx^dcNLD(_oH(^9EFbXawX5zN*CO7 zN}rE`;~Ob|IX&}LaQS#X!?dwZKEsbfJF*e^7~|$xpW%<9HtRLO;EfZULod06lg%OT zw&)y|UKpLjSh$JCd&i2K%AI^Q~@lh2vj(%53($@fIxd5?GG)0M_2+Si~aJ=cSME+gUEm?6bSoh<`b*)nj2#iP>$pCQ&?*J5R0vbd)*kc=@{AeL=xHdOSNB&EGt5OZMO0*O6H%-yp;Fw06zAKc?-YBJ?FePHt*q7 zu1j_uzT=n3Ll<(qyNG+;DQ~Wv_NUQSKKRL1 zcZSxp$I|otzDVONU!-N0FOsXbBiERx{GB(^-!jV=iL-oUt9*;2zDTrd`69iEFVbko z7b!0O`*QreOY!vxj<;e7<6=~=!2hkxgHNvQn{->T0j{FYc;&M@<2CJHI_ZDEV1mz5 zn{1DxuxZyUowj;uhvlp5!avtf?41`M-8R_+m)1;cU0OTM9EZ)E7(H(;{<^%skr=$d zh?3C6`v!&NC!LyagdacI*FNl0qkS9mYaEX+8a^-A;J;LD`!6lCeWz6yMew`8yN&!G zsrWBV3~i(iS2OszklgOdgSv{dc@w=!{y^>MIpaP3`R@Nh{k8m$s&~v78TA7e%x8Fx zo##HIcG=1{JJ0>a=m( zUjPTWm!I6 z5!UxA{)?6+e}d4lxny+9$8K|**3g8O>%lqstTeEm={!>o4RaPijRWYH9DdnV(?a$9 z?gZCO*22L-_0yj>KguV(-Z$~>it-8hb|H|gy!pa!#lDJ1Cg%D27+;aYcl@WtLx29~ zBkXgG-VNl>7j8a}Y?#s;*`Tph9|zxN5`Qav9SGl4hh2Gj@VChl?yu)N5pSj2$#;0B zoiE$EALDx~zEjSb+ODWCO&q^MH+?w>UCFOZKFG81KQ80hFDL1zl4r$RoSZlp$nS<{ zr+k8ERWsn$Uqza4;UnIkOTWrV3_Vyfdfq=%J7BXxoUIEv;NU+<}9#lg3&Z<4|Um)ciOAbrWNygDg7SZzAM04(G6YfkCex+ zmA2GRb!oVOy`XV*ilCim^R} zd=Bw@B=6r2?ny3P4n6r|WbruS{Z`>?+6G;fLd#?A+AR6dS{@r)TjJ@<=E|G zT0|3O)g2)d8$<^5`zksYcFXX5-j$xYf%_R;YokBqvnyjw)PA`|w^_JC;>+raw(0f$ z9=aXVqMGIld9Dq)ltb){&flhHz=z=pvT0iNCU3@OMy|j$ynhIKlkDwCh{<=>tRkJ9 zUJ3D7&YHQ%oh^A1E4RC_9ZEKJy=C}~K{eAm-M%W*XH<1Ehn>)_nQnx)Fc!&d(a%o! z)7JZokjNH$BBbT2Xr9r^rA@VPif zKL0Cnrxf|Tz?RQ5f&GHx$mhg5G?LG;F*?`%DZUPkutH>hi^M_rH$Xh z+nX)9a&}xj76*3mawQ%=r7JjbIGTUIT**MLoR7|Y9`txFba@W+SpvT*_B%OX6LD0w zgjm{7hNq(ai=ln-P4PkIY4O&>i{j(@om!-6(3?puQfO>)*`r3&>%EcY#C{#x@WRiM z^?4LOi^(w`8|RJc7-8r|P2miK5`#ShMyi7K^KlAKSISlZP zy_mU4MmRaVH}PKV_+GZ(>#GM)R#a%(`8JK*e%TPZGe!nMuhqn8`@o&OTrXpdTWuNg z*VyO4Ny+jW?m2ZK|NGAP+Ns3-TYNf<-%MN%1m<_ zG5p)nP1~ReFZA+e%w8%C?e1jnx`=yQQr=iu_-3}Xm&zq>t(Co$p6}mFMPnLM$S=Hr zn5vF!Y>miJ`1kr0#-upM_`MYET6?KC&{4CawY9u8b8dw%r@eZlS@qW?Z`z=puAPS8 z#oh?t335ks=G$uc|Cyz+G#HKO5!a+_}{a@*&W08{&^I-AAB#z z=6f1{&T;r&;=V-l)xL!FohKW?m;V^um)yqM%GT|N$F)&^tDgE>t?WO#ey4MV`1)HF z;Dqu*4z!QxX3n2xAE9|^?y-DT`-r6L{VDemxBf5OM}$}h(^|_YuOIEowDu9gUGaM1 zvGx(2;IO$QyX8%LAK?X$w}2!0=pkL4jnu>EC&N3%_q7K5`LF8@d}k4ZX@bvf_I|>_ zop`<Uc?>jf@vNWxA$A{;ZPnr0kWh!~_tY#2*?R){ zXAAE(*}T!=_w2_leqVc4@?1zK!bfBW8;Fm{CNp5XoOlKM%TNp-30XFoXdF#<%4;j9 z{wXuAMxSEfL{~@G=yUbf5Fb{+`cwe-XpO#jn~Y+@#YdbtIK|JXMxPtH6Wql^L=#!R zi?7j_7-uD&sFOG@kutPx%QmU0Vc=J<@UeFTw?M~$Ld*s%UrHz9^V;YF8f$>;mBBQ z{rYzLy!ZAaSHJ=coeR$uAX7-RE)eF-|gQD?-; zXUJY08&X`Js3M)&u0Nwm`v=t_a}VjyMY-W8oJ&qPb}mZZU!GU)RvogJ<&T&PuPQ;m zlO0y?mfN`~Pqko>!#?QPxyi=adE{Ow!#>2>m-4Xnoi%L6=V6fXi(Kq(S~K4uqiMfo z!*B&gUXPC-u+ctrH#|h^?B-fM2Zc;_J2*-Tnf4 zooUoOV4anwPw#_^;w9>6%gNhz-3h=ZPq4XnY&>j$Zz61VR>js%JD2&!=g1TsHD3po zJ9u8}UMCop#OJCrfWd0;DHhI8AS=Ovv+_TI z>#_6H`S-Er`QeX`kL#@Gy1cu;8aK~1@bJWWR-WKI7uxeYiFst%~){ivU3xlH0e;ahR{e|_|Q1O5fii@v|%oWuEsfqQL~ z@3GG-jBP`ELU;Q)hh2k=wQl&LVMcjlN9-7gIdR^P;i=K~i7kn}7u|b1IR{-$HPZES ziQmjKuFpf~auGY0JIJ>-f0XQsz;-D0pNKh`gTDRQWAF~qQju_E5I!ht?A*TaLMyi~ z{}&3!);RpMB;Lo{&N0UO_>qr@!?CwMW8)a_T08*XxmRuz56GFwyiV3$OB`V#*SR)TG0x>(EdR0dhxrdb^F$GF4Q79)xf!`i@YA*lj6^T zO6)bZ;76Q#9Q>mGJj?S!WBd5!^XNVn{Gh{N%klY$OZ@in)8f{+&W`O>J_d(Z=O^J| ztHo>oX-Hq+OJn-p@+tf7i}ys%I5Ore8^2=Zi0H~%Tb}D%Tk>6e$zI!?S88o_{xH~o z=yW4|aQ;xvc1+H8T$bE6pbzOplH2<@bCB&ywOn&qTOTy1c%0qnS@PXYe_lj+cB zmEZ^7Hd=X_lhbFO)-IQrBxtYXzj6NwE7(HOP*9}J#8KA zzyt%I68t?j8~6^n@#k=nqtyuD=VSTz>-oz?Z^SQ27k$eknH1GW<-g$Y&?3g8eQQ7O zI+rn(_zz5AOm$KIb(Bs6f8GUOuy}M4zC!F_i=k_+`|?gQV|{l+p9lGfCrg)Zf!46`TJdSowbgzoo#)8S9kae$ zz=6c|P1I){oQmyJIHf-KTm43T-|nJMAALRyAE>8~+CDyz7I1jLwMQb&$Lp^HT1@n< z691Cj`umKxd_1!MB;)!r_7yqcR~h&vU7(2nHz7;X(aj`7>cK+7I5Yce(x= z@ktvvPvM-bSNXp*9=#|0zm{jDBU!${rHc_Ggw-tXeRY|)xu4ZnHD@{PzhqPm&k=sUc>iTADh^r8Ez z^O>|Sa<^E04RoJ4^JMp#`vCORr16?QYj3M@S~Oj2T)$fL^Lq5mCpLR$+H7ay&RiAzVF-^{-Sf^N5BW!ksY5eooQ?W ze?== z+x-o7g);CZ!@bbGi)^J?*hz!J_ zax5Z0R6X~+!E+gbZ*wgOA09(|`XJ`AfjPd$x^|HB`3>Os2>kqYY_0S8juace*i8-xc&%&2 zjLI{os!oLV{Z1^|eBwW|u}LZRLC^m5sYo+83Lg>=&O+X16YH2sU6Ztl-?PT;E3E$z ze|z+^|GN1|^LAu`iCv`z(E}0{>Qkf9h*Dc%^wr zX2#kHf9WyOWB-ePkwX_9dXWF4N#a{W@EI72%rMcVz0BK%&1>+)1NiMoPnI5Lo&!%Y z+)b;=w+IcdR~~d{%*uH_!_Ie}f)D5{SK2bcrH8So{%twqTAb3ka@LDxOD{NGS+zLS zi@dAk9Dq72efiF>#lLbR&l{Zg>YjW{uf^X^*L2>iKGar!eYeDX=P6cR-b-bBBK|9% zaiXjD#YL-@LOrzTMMp2VY+92Qi`sB{lf{pTS=~L-mPWe#U_ zVT=Ee`XU;S`WIj8fG0en`<*%H=IFu8(i@d>BP8(pJ!a1d`#hl0cQy1`*?D~DNJ5F}xLrYziZhsmvL=?9O$+0n@NFgyQppX`9gTXN-4N`Aht?8`T3dDc4}E_@DHbt)uTme_4%#z1nu|%N8=0(e}D)y(M$B_VNv>XWd7$ z?&ZKUF@Jq>f7xj6dPn96rvy9o(I1Dw+VkJ*eI384C{88wmpzv6R3fgNDE;3E{aG|N z!DzYK*!rf{y_mVqBCf#)jgRMyB?TMDOe?m*3^@6X<@-7b9QwanUpf&M+NX$@`0d(s ziSW?cce=6PMCDT)9A_uQ(!|!6PV7g|D(2<_;yqORGO-`QeKz{pYWivYIq{}^4&SlS z+6&9}BfeJ;e@<+7Cibj}*sXf-mr882fHrekOE2&D<*G)%aMtqh9h)4Vq_}y_Vyw!^ zJBhK*N-|cpJCU(=GuE4}amL5CiWXz&EUxVYI*W^~{DgEC*X}>)%okn@&Hitx8!xs|Q$f6F!JgcYJvSE{+E#4djvXx(J6g4EN6TklGs3P%^H=hlF2MIddQGW! z%gPacZ_72s*afPt3zZXRZvw-7zQ17ag+`($M^tx4wg&E%l1FAFdvxm>db0YE-u<3k zizZ^X{XT7v{C96lgj#w&&JBMD?3`x<}*?L$Kp19%Ork>=6liitw@G{m5j)gWt07=~Q4Z+y-B)XJc^X z|2b|emUMg!Ze#yA3b#)+!nblJbjwvnlN?&6L{fyVbnjf+M z;NSX+M~nQ`#QrP(JQX-E=KQFD-;;n<;=E6{X1 z=e@j_f~`B%e;9v&gVcgOmXuO2a~_oIk~H~EfrW>Qqx zW*AfMV2_}87eZ$juqLv9c6+!t#3*F{TUd_Iu>6gRp^dJgMQc-5lMlAq<0m44It0Ed z&hplJi;Swp=)u~{QyUB0O^ZD;oR3OtYh${N|O81L2xuun{Id{>g!jmN&RJnxNM>DyZs_#N@u#S{Q$V~k%cG17f;}0+YVxaAD!vZy0b5C zrfxTMmSdQ`ix+}3#N_&~@)fpa8tnxOjVblxvEva7sQ8(BYK|zcNrPQ8F*dJBY~92H z?DG1r+KFTM?j}EkWQZd_Qji}D#M`k2LciNnU1OGgfjM6cKD1$5EX}gcL;CRHh0K0@ zaB1DXIl{sV%QjVlP1as}=ZwR_6WKAlCk*zVCw#!xWce~B*fQ0hY?(#!jal) zj*Hhkz}R{@za(BbD%(=GtW53pw&X)cCUsFv#S*}G*!QeI&6aJ$turF*J+^EMf;YqA zH48k$EgO(EfAFXOj40an6UcxUH+ab*5v_?U|GtUf+eB!@7X!ms8O*+a`)R;X=PP@x zai&;x8E2+$U0DG9FQ7hE0k~UGbxjC6`Fh!;wlLNU?Xjv>?M~UN7_07eGuAI!V~y6G zb!20IO}J>SC)Ke1D>ZC)x`tVDSUQVr9w`fb;tlIh&lk=o=GxKA-0zi(G|z2j7@N-4F7d$unw8d(U2cxO6?ThI_Qv z&2tOz$>`neDqM}t+`%L8T<2R(Yqu6-f%yM#G)g107qg3NDuAK!$Y9KN|)bn^c6xcMy|V19?76V2~Vdw!gK za%LEB^H+a1og6j4{<^!&&$i{hd+m{Ct(oKnK5T_rQ>~}wpmoDuTR5M21T~N7I`z*Z zW}Oy_&rcn7Li0Fi&tsN7k8Mfjq5cM%M;&|p#C3X(d1S)RKIXh*S5;vnPXBoF_PSV54zoPJCcB@>zOvvT+@x7VMkoG0E;Fi^Hp@AICv_DqBim#<|La~?kS12@cQR8P%XTV*weKp z`U=xc_Ch7-C3Vk7Ys2C<+WPsg z`BfLT+XL^xS4eogidX}3v{AbtXKGG4@z|`7YeK&bJu$xWbDULw()h~bo%e2kA$r~` zoK*d>nec-|SO^ZmQ=&O`H0Qj1@j0PPV4?kAP`sLU65sEZ4c2~Nd&GfqLX92@+-S?m z3B}p1rT+xE<^_)%B=A_P{r~~2A+xu6-;B#s3!o&WVl$) z`HFdrGwOSx9n~GyesnhZj+DPFm9g#Nb4^T4_i2nnGAK4T)Cit=sp8tuOU&asml4+g z7y17fzk5C2z`N{qyFIA^o#FL(h6g4g@8koLbCmB#wErjQ|HTcXk?ZVtp+&X#+p23r z-~BkU!O0DE5PiH8+QN6TCwd++#)|0{eO<*IL~GKaOYQo9ml6M}wS0y=s5+Nuv(Lgm zVvo`7Ho}=aYw9=8=vt6#dOi#K@e^^0n@srP zuRN!OT9KcVhzAtUs;Av<^s))?Kh@KdoKtOG$vW{F`DwlF8Oxp{Ban-JbpZYPz<*I& zmptvN;Ts|My=XBKar?^|bC7*R1^$4N{bl5SD=#*xDrjpJW0x+zpLsia_>uNVvvMRU zKd|d?(VJ^c2mn+qSDG<6-5D<0ZzL_%8b2x*+=q`KBqK zRnOvRJ}Xy}ez2>rgQxZ7v)aQxwTyO$e1d0{&q}asyUHkJ54TP_NPL_@@$H-|S$TKA zRzXa<2j3>;-6hZNrsvPF^6id)+^TN<9^crqaTqoGj*GJxa7giCEk`Gu}z)CHlY`>k1%^nv1JUy z_gOxS)S%tA=N;q8N}j#uJ6(G#cz#m2dPg<9b}{}_GuWTZ{7OCFW^WsQsrg=SqkIK3 zu>Wf;>o=pTf@6z|eN|<|Y*gRnqNaw~qO&`%k)P9Uc2D7jfcPH z-{?Ap>p8dOAqO73#OF78zahm4*H0v;6*h#`(9TonfU+Yvxd9GYcB9|4WmO)@dWO8L z8Nl%Xwwj$h-%2~rkZb&Da+BYRjcmP@mo>}EtF3zuZ+wRMZROgQjiS}gO|CxG_fyEB z#J=Qz`R&Uh%_9S{`N#X4nyu*ijRvuZ7=dM2oJfvEz(@Y=XiEK+3t>I+ml^S^8_q~sxOWCrL z*!4;!d;Sh~y;R~(cD;22+4X*RAAAj)nPtbpC)|+-@@b9X z^Y7bsy}tc-GP~Zni%-n1*YixgUGGfZ`=oZgiM-?RNyn~tn&S1qyI21SyPjt-cD+&l zj~m4cPlgw!!3zg9`G~t!43OR_CH}Vc2VYy8L!1ixk5G~9yXbwL=sM0Ct;VS9krqMyM}uF zqEB5DU20rG_@E!1a+jxLde_iF{&IL1x(|Cd_gZrk-w)n1EtmEex@)FSqFQN#0Y`2G-o^=?;THD_$)z$Q3>9QTrS7x}{N z$TsC4_bnto6PW4ubbf1`tAUlq_%zo9lQzCJ2jvJaA8NyaX9R~^{tv>Ttzn*`a=c93& zG3U&6*eZ!-)7;SSzLB$pSSsvu(t#UxHGFTGVT_toQ9gB+Hx>V(oYxfdF&TZv{3mQi z%4tB&$Mr_&X}@ezhVRM!p7d?q6NsO28QXF$G(I>DTWtgST?%JX1>{4T>GIB=xRT#X zQpN_*>t<~l-c+z;*xXr{RfJ?`>1kdyrofdl8$NK7&TH7O&a20cpKlr)h{Krp8nHOi zrEUT~#E)HH3(wfkm~x3vtA*Y)K5Ja;_qKd9(!3D*RvwXR=)Y8KDr`+SAVpi|->-Y?klHPz+1 zeqP41m5Vj6S0^;-S=FReZWFzuzP2uKtq?9fOl(mHI^v8?N18iRIO|%9zax7{t%IJ6 z)<8-Rj0cCR$%V3*cY@VFexlw^oh_+HHr{aU50}m{4`05+`wj0{45Ll;Rpqx$ToP!Rb@+xIreRdg{9NkTNxe(w z^q%p{8F&9Umkb|UIjrVneCw-bEjej! zDfb#KTYQ^2-S>cZm{FzYOzLL^S+|GC{k9R9FGXkF2)ygjBid|u({K9IHq7>RL}7Mw z49xU?4)_BvpSO$Of}!HluLIsUx-%L_^S*TdbR&J6*7Yi$)0(OeXHC_Ivo3GieZ;Oy zw2zElou~Epksi3%>La~TJR}j9qOpx>fv2&DC8Is3217nM_#Jxc#MUW1)|!s7@%`+C z_20<)SJ>;XXV+UekUnul0uDTMiP>V=7kK8A;6hshE(j027kjOB{eOuITBl>-!gr5> z3-Rle5$L6+pm5<>>vRF@lx)9e8pVY=w=CdWGzxF3Tn(RW7h_rFZ5$<+6%X_-T#en6`IApZaZdO74V15qDz)q%oifU$Mof92E$ zWP(wWJa5S-NQ&;}65f z!qQP{-NkEH-R1VL!rrx%@%HH@=p@opYQ}U-FB?-cT``;GT&v$*RJiKM5I^$@m!rE> zptp>m&sOx3Tks`nWPBTyD;YQ(@7-kkzr=l?*2qXFhX^*evN1;ZM%vfDZ$Emd{K};V ziC-A-^aFjc%b-pc=NHhGKL&Q+wqX~$7ZhDDXvvDYuVI$9GXHs(>d(`o0aP5(0f zT)YhiCG?8W_ipO=CV* zO^`@k>h^qt7*ueC^W2HrKc19AJ(yhlR^T^f=;hRJ4(xgQzE`gK!_#|HU1{4MzxEG% zWzRV4K3`}G_F4S(!?KIK@btTTWg8*xF%WQ%*;ct^81m!X2gAI-+cVrh3){zAk9qxz zv3o<}&y6Y>^*emwAFUR`E1#hKZ8uQ=`Z@F@jX0oT24%Y$R>CC|KpLP6Y4&Y;w zgCB|UCC)3xySER0HPUR3yd+eLy~6LFA8K2g85-|0w^{wf#CvzsPXYeAGs$Cq)IG^` zeCT?3W^P5n)DGxq7qs|cr7!&7F68=LUpTw~*?+cy-&9)f=&wAul7pP}!Ofl~b0PU@ zu7)=xnO8UWC$g77*J=#j$k|Vxt10+cieGj;>TgfJlD*sIb?&A@;_}K)#W#uP$+_Lz zK^)vii!Sn)Li?9sH_q^k-R5>>ZhPiP$%By*OMCHyn0E^}dI`4R#JLEbCi5&E502cZ zJyNWFBGd9G*B%J`2`pegvw%HJ#@E8ncn=rv=y`9+lQZyTE2wQ=nZvr9#>Wqwj=ig# zoV>wlt_=hB^_lp-7ADjVF^8o!R(rDLC&io?Gcu!XJo$qc8Xs(izP-lSZ8K_(4;Jwo zJKYZLEu}Yk-@WUB)3B|*%f7PGGpzACPfFuRBc*ZeNyZ1WY85l?Tib;ltq8m~jA4x* zfs@inTcOSJANWG*)4baVt>(TDSWOk&v74s>%W}aIn(@Pj#iw_1j-b37H;*(M*HT+n z&nYLd`1E4;*ha4>Wm`d>v39{h4{!Xr zJGF6?E4A?@#$3smyBIU_z#6mZ8s2!oGb}IzSc}j3@9~Ayr}z8OF{d)#U03_Uw-cAH z{bnh(>23lq`^TFRSjt#CM`SgYGQZMA#f82_@>MyH7qCV+FSm^ z($GHO)Zoh4cISu%A?E#Hifi1qGnb^oJ4zm$$v5#Sy#>rA#Js*KyG@Ds=s4D8TyHM+ z=!1Q{TsFsXy=CCSmKa|C0W~Zn2QTG4(=%?Hmv-CSW@CZfc3SPdE32^q?)lkJe=hvx zAZ@FC>Er8|*9PSIkAcB!e9H!!$J(o{&jZUcc*-|RjPM)uA^dmt8a>Q$*2TN_M%*dA zou6~f>*l}g#TCrCcc1a(V}Y){COplHEx4aPQhU$%%CeO^c_;s~u6dn9G8+xn{q%pw z28_RtLKZW9>adHg*v9diWKK&uRQY#wT3#B4?t{p&QTeg_VEc_dMrg z%#y`9oZpr4jOx=%mk7~Lwe8nf4h-w1OVlk0wc0Seg!h7;^9oB#+=c%gJ?~i;n}+~= zeIJ`g-+7OCZ(EKNQ=P&dVUclO=*Uage4c?s%e}|8WmliBBTQ0uP zZ0UiYUh=PI%P#nxbe#>HXNhkljHQ?Hmc#4n z(_OO7#>HQk+qPNtYa&OY_SuX${@1;TGiTd&BOP4NcE96#vf%Wtz184xXSQoz53QBjN%v=GGbheD=`}92X_PF*xD8!YRP5 zUb@XQ$Tnn#>aq&vl4D2fHBn#0SiNSrjZ0m;zwbG0ZK9pJbE5XF7GHR<{!g&~{}7&{ z|93=v*zns72dj;+Esx`1vWK;6VC}ZJk6yb5)-D&hl}!G3e;0hpEAmVC(HzRc#=IWz zs5B2bJln>R7#qFhq0UW}?@)EZ$^SiZEH-+{nou8`=9- z=NTVdg{CRm1}tKyY#(> zK6CiJl>V;4E}(IWPOd$0*8_jW2WQyu;g-JU8eIGMCfcaxS?%{K2m2lnZ>t19>unva z4f)^AT(<&?$IyEVK3MWVh0D9G6#te<=!?}0-5->o<5aj(8m)Q3r*w|IhjDZ>4t!ay zc^5EmjS)QCLHkXjm1~%PEAzh3(kF)nE^>LTamfd^%bt5R@8?4Ev(P0q_nC}K=h~XP z&WePe=J1S0;iPa{^`2^eD|(`@+Xwl6aC#@t=YqGocUm~I{(g9-bxpX!+NrI6ALM9Go!`>-U)xQ5 zkfZ+6&oQqbGq!Q$RS3c##525Aw}w{XyIpoLGOwZ5S4dmecVA?*`)F@m)tMm^SVlH` z@JSt97`)DG@fH(ZYs(q6_}Gkw8m z&e7|#LxvAu!RO@vYBqf+UJqPb>&_r=y6n&60&R6!q2LvwVPh@1_1dS5FjjP&Z=6|Q zN2~++?#j+*{Ziq_=i{5j*t!{0a1#05=s*9yVhc~o&P9H5W@f_Yqz7yL7o+!fr&1Hs zGw)gHI^xa2u||0JIqXqN<~=K#EG;pbzRCWv8~vkutmcpv5^N`Zf7Qy~p+(b20M`LMxi@ENE18wkd=U1iHga>g2Y0E)4}&p<@B#3}CD?M)I7oj~vsxYlSiI zb!-WrWbJcVd#$_HKXKiE$(%X{8)y8AJ|)}!m=;}Q;a%D;&IF*n&W-VOyAVFHh;wL% zR+s%d_z^>=GymO~qW1oX40~vTue}SI>gb}96C2$|rOtrAo$2#G%5%GZc%i?mWJuFh zA=Q{KEyTZdieOMalKOGLWHe(`d%yZ9vVrqT?E5(rd!Z}gVgv2>*!ZYet5Wc>m-Vj( zrmg7)bo!YadcZk@dhQLtaSORm!fs`h8%6Ut#(ekgJ@p0cjptYI9U zdTcxehdT~nI|I*zr}^wt)EBa?agyKXXU*788#fFCPiKOs!eN~=H@F&C3QvRkBI~{2 z^bGK}b|3ZU!Oe@gW`euj;EV7r6IuQA-iU>}N%8iB$WeG(GyvXqg15riU0J^HZt%I` zGIGR%yYh!eQkbba@xI!kfAuEAmU8iiTS6=IjvI`u+<3gWKj`;cxgrMDLru zHSglz&HQwhFMOA;li;=qo~Jea>98oCw=Fd`2=636A|==XOU%M9-+mj|xEVsXuR z=-13ybN`hmJLJ&YXBn$---OrtC*16p-DG3+bjxnC5x-X9tpBlF{89Ou+QK>OHrGiF zjq;DE?Vz3wZEmQ%8NV%Jhcn>M6J6%Eai8<~7o2N+P*Q5lJBz)KY*|{r zR?Y%C(bGCOo9M*mA^S&L-Dj{PVRJ>detOLk|4wWRimPjLV~^&{`ByLb{Hv}&hv8cN z9XWGlPcqYusq$Ucc(m^j?W!${chSxtncu1s&gEKpXQc1RZ171qc&J_W4&Rf1HGo19ycD$rXiq1g zSQV{!OG4Tj2&f}yDyb5{);xnzTZt0eehG5g22d--OKaOh0PUG1ctJoiD$MWwd7c@V zM8M1Me1EU=`(s`+^IY~`d+)W@UiW>CW2MIQ58gAg9XlGUuj^Jkg<>wEz7!KUHO`rR zje#0t2k*^FUfNY$gd8|6%!zWK}2jq5$?Hix<(( z_zP-RmC}xMwhZ(nU!C-`L6)tkk-6)8Y|d4ylKM5wyJQc=8++hIjljB|xsxqxo6}Qo zFo$lJr+y;3=BA1Qb5r%uZm*+q!ekGAALPvSi?RPK{;z_`RTl^k(L<`Mi6~z}XYbM)0!&`Mm*rkX>K4r7qS&b~a>-8ByC(8Gb5H zgdU>r9T-6zp2d$+15WNWR$n{bw_kA$*L5E)!`H@G+VBe-!WVeue8wEimTkufJP*#e z(XkuB8+)&|=iqX1hnQf0#k{fO)xPlgcG_u#_rv=}M`aK3a`B{j%$aCU_$ImxVt4F7 zz8u9qC>b<&i7{pg@+&;<<|W9ZMT}`p^YMMK^S++@pn0FYk7@tYKJGzp%7Ldx_Q3r? za;P%g?)kfENBxQ)J3L;q{aSBmCa~{eY|=ybu!hHUBYW%rTVDE0)*;GEALVy%Ub-@RErypq5V;o1OP5BjiI?6AKab_5mCVH# z@$@@+UvM<={&Ur--M2^DlYSW7a!J1Q!>EqwzRK1a{{ETGS93DII$s^J2^v2EPxTJ# z$y2K{|G(j>|Cw-Np6a~4Cr@3w@x(m!zN^1JPhC9t>+{q-H-9;v`t0Ga&r?eme0`pp zbK`NII-R-e%~Su)y#H_JsT(-ILv(Q>p4!B{Se|O~zc)`!W6WQ~Q@gJ^F;A78-ToN$ z5)qG37g`kWK#mWH*XE+nta1ITKs+}yZqSs>W$g=$oHhNG zo0anoogwibkL!6$7K4Z13GC7Lhn(VF-`SskcYe&fqj~oL@@Wn7fnh_L%qIIKlgS zfb~@Gzr*`c8AtMs4>*|B^|LHyQOr* z2k|$?>WCTiCmqrGt)BAC0_NsKI^uNZLwaR1di0CP^2h9ELyz0dWV5>T(=Q%J>yN(v zIKJO&93$vY<5-L>AXe8cILSD&BIAhi^8w655dEWTs<&knIV|!;9j^Aa$p2J<4$^&> zw%_r}r^XwF}3!aMJ@?dT`_9cgL^9}5E zdIuZ1->o*blpK3E$5FFt9zM6#wAJ;(RC5XK?Hh+JCws7|HkUb;uiAI^5K}tSJJ@M< zf2@$+@D>w(o@=IUj4Xr#Bu9F{CGQNDN@}Wu&kWW><)V4m@h}Pp1B3CW=%vbYI z|B!wx-G=uMJcG@c|LRM9sIS<5zl!P z23g0$PIq4LCdPoCsBdCG2X?#C@?-;ywG}8HG^c-f#x!^wvc-q7@fdmFN)SG$nk8Q4 z-~PlKnyh$?>6VQ@loZ1Md4hL3KKD-Uc-zNlg#NqRj>o`epQo5Xk0Uk{JuHhqz9Y~y5jTH z)@9g;tUS;UFY?O{DExXUa_-Ur{{N(soGa#azLiTl^%#B$x74O`Nqgf}Ci768WaF0J z4Ti{{U`>LYTk$e{BkVM8acAPk9JqRj;sLgDP4N7g@80tS4O#hiOUpCIk6>=C`!R6> zONa*;;lRgnIGnB+jo$AwUMsJP_FMKlFFkcAX$t?Q|QJ^Wu$uV+#N zyZHSezxQ%)PvrjFT&s=Te~aHW*6*~y>-<)Gf8|?pqiR?wpX7P$1@rk`&Sylg>(n?% z`4%6Y^W)_+hR<+5l83&>N6(+nC!ddGLL9{@!Y8#$JfekD)4?gl`?^YytKeh0mlJRE zvdg%q{B2#kjBnY;F6ATtX$l`*Z${=&pP77gX5BaVB=d>h%Zgk-KAtnW)3_G zFWSHM^t-qh9nUo-1|`sqlz&9poX&sc)V#(2H~C1%cJh(U*lL?S<-UXAI>8hDU(J8< zf-~t$bNf`Wo!1@hb5w$1)mG5+dJcc}NIrK+xtU%w6~9m>F(YrpcfZiPzhimFZew)szTAu<8qc8^4#{H9NX~I1ajj+8Q{9Q~ z+OoCeWDoaRKAcu`%XoYalZZ)}HQSD1O)xy$DR(wDV>oQ^w4079vy^O@&_OIFtLHBI6amR-|^<{7;K%Ktc^L{GaNd@nF!}?`$Mm|wTgwAX`ct&277Iqbh7VLV| zg~N9Vm;W?ky|rUtE}_lH__H^d|Y8-qC(Jo z*z$F?PT1u%7H#E!XSLyfo^SDxwLFK9I<$#=n5)6l)B*TkT`sddp>o3RDy;`(dp0UL< zHjT^BxXFW#j>%wr>tDT_oRSmNrQg*Zb#1rmQ#4e)UGSHxq1~-js|ucR;HSFh zB6CyK5b9Kr=Uw&Bg4U{EQorJQ>QtQ3-Qf7If=%~K;Qp}gR>$K!f2^Lx_)Yhyo<)Z0 zS&Uyp%-?f=z1ym1VJ^l;7$`7TKm%Vb1og>bkwo=y=|Fr_&n$0^d1J5RdZ6D>|K`QgaNQ4~Me%6WM6u~GIdH@)I_z1y!rGUH zMRJ&i8zIS43#mJ6}~stj8h7eVBC^if`L@1^Ies$JhVu z7Ox5JG)pE8A~S`UGjz)hDXG{Zh<98~?!}|u`sJ#8=He4@PQLs-w4vDA?=iQ~+URzp zd#vL7R=ZNV_M+d#)0Tc$^II{=_W6pO9Tr)~N~3$+5IsZNPUb^><~-o-_E8hY!1i&F z|6RX1S~uv&PV+E$l|enc-TFp1NpTyYOc${`)TeekknO+|-xMR11rC)lrt}8(@2j|n zeB!&x2z|z$ehA;c)?VxWDLI6agWd-gt+{lF1N@G~jsF&$!yUw^82)|yJ~(v}xIPh_ zF9r86Mc<8{`EH-LrS%exN9TPK^DaK~Ng=ty)eiPI7w^YGEA|=AdRF_I_9FZ2-86DN zQUhf_f5lw48X4Fb%^Q}@64?hBDqrIK%xumDM z{(EB-_T<2!YfcQiHGZCbkNe`Ij{$pconX!%q*q{{O;C>POO1Q3fe&u6*X1yL@Z+od zur{Yz=WFZyW$`VwI~&?no4cVOjrGc@tOK->M(#PawSEI0&e-+5u|Ef2QP4Fu@B;Zq z!PAW$8U2jkRFfAaKCua&v=*M!?h^0e?Bcyu1^jM$k+#5TzZaQS`DBy$pAl!=?4T|o zF}-lYoyk36&3b{}Wp9q{;_^aH&naeYp&vIb!0Sj%BPi6Q!nMc#<-d@H0EAMIs zu_9wGsAJAk0w!@inlEf$`I~8PHD}n{^OzAR2CmXSSTuyqE5bLyk(uCx=-Ei3ox|E2x7hTv+UdMm_l>PZcXnVad;Ms5oO!6PwO3_g`!u}g`(J#D zm=5|7&Nqrb(~p;aq#N7x$Jv(D+@5$9wa?(CVOL-HMjE^(9iB4?-ZK~;G6XywN^SN& zeq>>Ih%F0ugRiBTc0G359^>0mq&;Aa@6Sc~rKQH0F|xt22Q@}*a?!nrd7Vd0-~6); zKQ^`3vI;Kp`?9_H4KBxyCtS`Q!-*?8Q60Pu+&8nwo6GK!9r(KOwd_@aC-3fIt5aXH z)n&;BT;|dl?jIK4{cUTn+7hXQr+0yKY=i6i?ju(ptrL!$wC(=z$t%j(lQ+2rjo(zw z$2FMm!Q(TDUnT}=<2qn_g6DR_yXCLr+}*(MKZM4;#@O3#y_i_7VO^D8;*sV${I4U^ z1V@pJ-Yf6c(wj@TcOE)0x?sn;IMXv1d3zn#o^%oG1RUVe!F8vZ{aB;Mwch-|ufa3U z1=v&VWZzKUxp9l?g3JQ14vzDNnw<{f;D&WI6wo*EM2!vNz!!;u zpQq=Dt1ahQ-OnvB#<(w~z7P8>`_~to2k5Zk-aA?Q49?$X9%tmaIZO6u?)rq1FFNbd z(bd42jH)HNoqgRtOV(l4_Qgi~rOuMwirflLov_Y&4X})`V)JbnyMVFKu;wanjd@f?fI zuOYTpIRpXvisnD{&L5cUNH}T!KqB*K?f*jJYagv5 zSD>$Pb0zcF4nFN+-j)-aRK|X3tAlawlyxP+)X$r0{F+1k+4CktQkkytzYw_3{a(7=E@(fd~zGCB$+xiga?=V8L zUk0PPJlqRrSoqV0QJ$J;kthE)sLihEZ67korA%Db+?dF&T{5B=Y_ z8ybW+`u0!*b~yEz_}1JV1W(%9InM+>)Hv6&FGRT8@bjUXEew19o3%IT7Hjp+%VAC@F<^}$a(Qu z)B@01=GRX>h7Hw2p5}mf;!JL434(!W75K!`E^K`P?GLKz(54 z{sL<}`FtMijybHCJC3;p#sKrMlD$cA-NE^;8q*MPa3bv$9PTW7nL)URX))yq;Um+?Gb-b-d_c(!G>} zF_`(R;TZ?Gv<7~V%QJ=CD}tvs^u4>ubj|E`61!80eZ*vJ_IL*e;^=cPG}gv`ltWHY zaGtG)y-X~xwa=9}c0~2Ds2=v_B70wp-P5`*vi+NCNBf%OmEL-oE24vGUu)|owv~PD zQs!(6{cGNG4%zdhoT}dwdp>}67%4o;X+NF!hk5POU^OVbfa)v_GGT$(kXM}^lc=~AFzkwlzHGyZp z7G3ii#-er4*%scA6OjpC-Wr(~*1{U!XCwX5d3o>@^P;w5=H=O}5BvGiPoI^3+GAe+ zWY3F(c^L)1!Hat2`vPCjT=VlHx#kuxGD83Q8t(*o=it<9k)LKFM|}@@>Kf##tFilB zWg=%;I*=s;&$0b!=S;VJVh=`Z2(K}0zn1gOgU9@7_wbD9RQ6o?LbT?RE6C zC!J$afvx8V*BUL~RdQe<*P_q2MdY79@VwfS&qM7rfD?V81-0ShdD)bDpOtA)g9hK- zgKmez??Xo4wIp1(aJV=0I<#`zS+-qi6Sj;s>?guCyMAkml~>WY`1`i(MI89!^xe4l zy7A9D;T5VixA^+*N4X|jOBwAgJj)0@%>RYRJ{!=ttA=CSH!2@`7+Yd1w73viU?qJ< zuRp+b10A*oekz_5-81w%n|LengcIEx#yz$5`jK$655C+Ov1xsLwfxIlEdO#DHGgE& zie9_vO4aH4Kjwi1>{%|`p4A-gsqg)V^~{T`xr4QLf&(%7IPau<$k`K_2KFOlH*~EK z@orj!bo9P%@;Md}12@z-`cMb7XsZCrDc2c$itmHlEX|3$Oq%whTPBJ7!-?MtY? zC!6qvM=oAbjy~otA57kor)w?z&c`|^$6z)5b4hhZx9rjnS5!5s|GVj5J~wir=Xrta zw&CO-^Q`XaS=HC5L~kl*T@Pa4DJSnShvz54fAWspy>lu1kK2*5Jsy2+7X4Yd3SD>q zR(T3J7u2uv@C^HVbJ}}%Q_DClP}RhGCJm{Ty=M$H63T#2IYE`KT?M5@#*W$&W5;Ls zhbpMiF%X&`jieU+jbXgr1e(+35;$2n)rIj;gW?D!Cy-zXKb1e z&4ryyi);=a>fXMHyq>{%d6_57rM25Wex8q=ODn(PYKO7EoxBObp*>dLVfG@~&_4N5 z9JJd9+CL3FxUXfe8FU%-yP;RrVDUKzSu~SMj$e>#%BKl{`|_W(LDvb$k?)ar(?s4) z)c$q@@OF`-x6CnU`!eWl3Ga@?pQ5#0TBTav{kpEkk8&8kr@fb)q#41}(yhFlm!7iq zcjhgie86VvZG`x=IlcMqZyDyH|E8`tJgn8qy;2Sqz9sxp+ArRIn>;PziW`~ZQY*JA z)yl1s?Q~WNF=fa_?ESw*jzZT=4?IaWg@7MtC9^{^U z^BvHj{3gh!Gio9=V=}8|btglY@;^l18^u~{k2*N@Qr6`=tj{H^)5Y*>?29g^zwZpy z+CK3;t*x(^_<|MU*QtS78zVNsY{Ng0T1INuybv4emJ{3R5|B}&Yu}@Gdt~jmMb_TO z+9$I1QQM_>`*Pta>%QKRuw6Kzx(&jM&)0JAx&FSG^)K$V{;Eg$ChH&M)BX>`{CJ(i zT#G#~wmxMW`DNDrN3K(JZO@OaEw&0PH%@1ki??dukR3IdHQq(-(9Y~4v-}F`x6g+6 z6Qf?qde^evm61HI+L%19)m9#tr)xFqeK3;8wUG6m$9i|6PZq+D=gUXR`U)THHCHYd zXXJ1#n#-j%e*{@aYp(oGy00y8U)Or?E7H2A1>Rw= zfB2z@|BUs1__y|YpTl~es>hw%_X=K07B$ht9Uk_rx{;GSmVt$VA)q||P`o^Qw zQi?Oiy>0E)gX-Pr<=U&g%y-*7{=>_I@V_v5Z)MPLBXSP$)y@A?d$-yvh2NZL?{0|M zyF18r&ISJH-W~W7d$$?0cR#fL|IXeW557eAZjIqo`?n8#NCppLWw>PaYb*YRIS>!{ z#Yp@!d`Io~A6;=YJ^EWX<)-d2Hn5w0;B5x6Yo4L^eXicIbo#<1Y!HUgq<1o?Q@)w? z#HaVH?m1q$_=xNh$NvA};v=GoWB(t$_=ww0{tEABB^gI@@IzUByNmF(IG|N`;CquC z$DhY1*yH`J7axhftM`tz+f2J&Z+`S%j@QVK-gi<9*@CU*_`Ad1#u44ud>x#MzX$nM zaJj)pOaCyuR*hs2vO&BxkI7vVrN`?(dVDMRnu1QhM(1Nhc)Wb$2d7HLe#w%tPep%W zSHB&CDa2WiIulfV%I_i{+>M{UHBd_H)}GI5bd5 zog(jl7#p@ez3hs4=PtjZ4cpSh1yA47`AX9*);W9CoY$9p+Q!Zw87+IN9qfVfBMuEr z8)~dnt%FbLD_CvWxyQDno8QQIes`7dWk_JN<*ykU=qSZk#x=JwWP3&*<2MagvZuP- zwX|IjTq?D@}oXM z4Q}b@vt{4DdocCj9sa*DrqPUXw*~L8z{mU-KJNZ-logNZ{K3H_)u20wob?{>|I*1` zPy3npNh@-Vo1N3Kn=%jkc>f$=dAh@xwky}TARD}H+H6b{Ov@LI*f<~A?Y(iUhs=XM z1Y;95D{kfFwTF$qbzu)6mJa~WFKIdNVioZApZVzV} z`xk=?#GyX;sw3Vnf2`K^L+a9eL^}&SNww4B2i7XqnVN+D$}{4ojJ(3|-#pFmf8U@FQO&6`jlq#r`vGke zALjpX(Ty8_3(Pw%@os$2b$VbHZH@d^(ooIyIgZx9a<20BNk_iFVjkn@y3gA(kGj>f z?kW4I3)xU{Fp3@1K9$2fA*+q>Fh4=&q>y>si+!X9z4~GHEZv*K|58U{g3h#PAYTbw zxH+rP_Ng5No+W$Y{94oe`RuLu9)7vUgoK&%GnaUmfx=ACTzVe!S%YH+7#UBZ0T^p z%ZSkl|HKjM#=kKW`Y&Q1mCQT~{rfO95$Zb4e1Uy>cSK(|u|)!RbCCT-GUai-JUuXh zcchbr!l#+YC9egs=R{%`j-O`=ZJ?usP#Ruhg-zK|gQGNpX zH=R#j+`}KF_GBMgqu7V`Y}+=}IL?B1FS4_8ruD9mb!*4gvuGOUAKZ7B`Nw;`5A9`* z!V1A*?eIqV4RkN>)-ycjS zzKb>#TWKt>DoAW}n)~X#E#Yuqb3wnj?ta*)2YkZ_C4Sdv`3v(ka*g4C6@K{)w6)1G zpmR2K@;)`qq?heNACO-37tbsB8v4~wUUY8vYWmst!Xy(vWT0z0e!+@(^L=tTKEN)2 z`SR1cCtpx#PJstc9cZ+?O8dD*4u2Ev-%tCi9sRBLUx}PKzKJ?bYX51^%beeqSU+#k zIo%q^zKbrm+SfR`ex$gqMDx8{>7&crGNqr#>H~eu>f;sqIA^!R8p8utAHBz5_wg6{ zc)vw`oJ%~GVZQgfsn&cg-Q)D{yG!F3V196)H}qk0QOknm3Eel0DKu}Qj~_D*%~Nib z^GnZDEq!Pl@BMDN)knv3SD4|7WV5V#d%>(DhPhz*0O|}Gq0T3(<_FV@S~S)& z&NaG`8U^#{_a^$?M!$JguCLVZEY08gtIVz!uBOj)`ut15>abxZ=A3Ts`?ELn{)(a& z>c54Iiz_E2j7~Na8>pjM>S&Q3o7f)b&#j8H)@uQCS@F5`N{Fo2cGfGQ{<6q=bw2Yw zQ}BnwgU$D!o5{F~TH;5hn*GmDGyDD6Zo6M)AOFa#KGs;6SK98qPIlXW@oZAH{ah&yHBN?{hl3U_Wwl$=FHRlxtsfZ4Vb?lf%!~eo@Kt5Pz=mN zfO)9duQdX5>uLUxvrqf#Feem+!U>L0*8si;I706w7omR@h29@UA5RSf{xi(}!3g|i zef_zPzF!^wj3SH9yRzvc+Yx&IY`!xbp?xEYLhoIxv1FM24M!+3&JpUDRLNe@KZkxtIzj`=oGtHxyZyW# z|H$3$uRONSYw2rNQK+lqZ*A6vq{Gm$tR{0h%nxpACl^fLQc&_y0rMVx8*ex4m=$#3tt9DXOVV+nic zA=;X8EBhHT=6Wj@?>jyAv#7tL_kLE%yL)NF+RtL-(?25bNp?)T+=@2|$eRyF<;?9g>lva<`sobFx<>XWY;G z$`R4EVLYF}C!J61v+V2RXnc%pA9|;XcUE#ud#awZ`lS6#;HCJSLAMDlP~e=a?MBdhS+iHCS zG+rfE-bsU}%L+VyaW(o=U!}_-^F8 zvR{+uHAhPZJlCk|-$Zo71P{E|a3nQ(;ENgX6QlCBJVexIehb<8`%U{GRt5Lz;|Nc(0P{RYU2|)#7s+=56qdH4&b%58Ik}Mx(_u zu(4vh(cH=2SotjX$WaNNjy!yy(R3TnsD7bvU$LL>u9Hm)*;D^{elPfWbQ;&d-v)HA z6mah^Q)mNP-JmmIMCfH;{X|!NV4m<~JIzP&)0mZ$wTt|;TWge$Nj8@lVn^zSn zHtfMs{_LlZ)-8@R9<1V1{NqbQS(jZJdK2HO=tA_{D1O4+ETw(%5?y;3`jwA#`m%7H zYWCW6o)S2V>+(rP->p%;E$`mNyW$b@VOh^I_gRnI`C_sBN%n=IT$ev^NhROl^L>1a zXAB#2oCbvR`!DS2BaG6AZ7(rG9oQUW?MpMK*k^xy&fl8Z-+w7Qw(P~CW9vT^c%$oI z_S>RR#cv(f`cLHgZNDxGjlqU^dw{(Z{Mn^5DUt0p5BlAX{`xxh+c%4i9V_wWNB6lx z*4kjrPJ|mfpCPXjy|#?DZwoj==h4sYtBOL;WBV(6i2fh4`_I+&pBIJ3_T~D$T))@8 zo~`S*@I3a)vUyyeXJ0=<*T2v6@m#-(>sQ&=)45*ejQ4vq?y<+mJ&^0i#(gf&pKCv# z!1ddPGwwvjeOAo4@q5i=+^sK@vEH=;lE??U!JU;_fFAHRZKhoMLW+^zx8D8{Nohu+!WK!%Yx_Qlee?=6zyCe zY3EdU(Zc&D!;8y#-@*&#{sPrRXuPi%hm7}sxm z-)rORN3sumd3;@Q3b@XW!bRJ+ePo2H1s8UeO9WSOoPR4ceA~UmPQvRJF1Gt!E!u!i zRuYdOSp7VsYqC?8@hsDwSw?y8%{lxE8$G*q2x7}`p=Bj`6TTY;sRV}9z0oeHk|9j?dwyye(Rakn1!#-j_f&8nU6AJ zBV*$fWV6*+N_hStb9)=HNR?}KR+=~T)5oYWSB&qPa~Ud6Cl-)r4n=T$T;%y?{NmB) z@96dXxiQa=h&+D?`l?y$%~$(A_;MvMeuI1Jr;Qj7^&?s90R8xQM*Q#i-e~7nMq@0V ze_DA%^1+^luct3|XE!m(4u2|p%x(CeGdVX@ytHARu|qz#oFv8V;kP6fOLbP0v4gg+ zGyH40Z||cifsxBitmnQccwg%kJ5$Fq;p)hFu{RCGw|hE1-el${1w2T_{}AUVcJW#Cs|S^v z$(gK{A3*C9zwT0UnB4*CUFdWBGY1#lX`RV?R*_kImf^>C{$SP}3H};jv+aqF9g9yA za~?ttGqW!=Ke)-ZF^)KajnPeivN2+#w9e#pD*mkWbPGSSqcStPk1wM4l!054g=O;< zJrM6noH-xYP`-zfC*W)f&NW)rRXcV_H?-r;(}^Wb4P?F>t|R9yuM!=G{D}ODIgb2B z?D=X>=dntrUP}CrQMI^0d6K4U*haJZ%#AY#vZlzGI@@+t5xxm*jlsUyfmN>~rq0CH zmkhsR)I;ZCOMa5N4EQL52?kw~Gl$;%_P31&-zOPqp^&6Mr7~uEpP(N1TuE)-$HZ6X#PNCeDXAo_Jz?h?&~fNxaWLp%v94&;3K`wj76hn|{0b zJ&11~e%$Ne2bG+O(R<9y?~J9yy-sorS{lzBhx&NO$xl$lx$h(S-$|Z9hHF@tY_stR z|6Da`_ptiy;LQ9*^SZl`yEVS`d@rL7#l+mm*f&u_zX9Ka?ro=E#o1@L`t^v3Q9O}! z;7!D3*>>N5Vn-ZSzlnMC5~I=Lu;C~Jz5>onh=pDC^MG-G8}qw_eh0feO9#_d=@#}9 zavlxz-oa1Ub_4ivAeaF!BHvy(q}u4@-dJZM?ZL0M7hUlk_#5ZEt_+<=yczm?C^F`1 z#_VCtx%UjKr;qJh8FwycfS8O|b0%3`b@(fE<_EBhVC)qdJ2mri8GAWnAHmowh(F0> z-32r8shpRcAr{#7yQZJET23s-5+&Ay|($^oy4)-wnu zb8d&*2(@R&nK|qS!4h(|%ZR6dhi)$R{(*c7zv0M!{P*z9#jfnfhr5TL>CMbM^H<5l zXACg*uVaigjD?uGPStIduAz2}L0M-m{j_2yb?-R`A@}hNV&Vo@ah?WevB@v+J)Y5e z7xEsw0GkCd$L#;ghZQasf-}V5%{bY(8i)2ASJr`hc4}#hC0A+wJiNQa z!+s8Z)@Kwh3YWa=bimzJ``Tq+4*Ympz+t+*Wu?}KkM30@+q8P!PS~MBq zL&s^+?*D1}f2Db_MT?o>soMVw@qIUur@9q8zw(biW4)tzBYYSP|6rd_5wDoTf6c;uUxp1gGkuvu$iuTvZGoOz4#yR|l3p`%>ZMKrhC z72m1;ICsY4AB7SAkq0eJ{ME4fZS*m*pQkp5cC|)Y>o(#m#T&S0@rKjafv3>A?257c zLGaqwZ62ZhPkw9h3GoR0(JMdOt~kwMfd?iXt-B5zz@^9}h4|I;t1DLt=atvHC>UJhd%5)@0`9F;AUm#(t| z-{+%yI>+*3_y`ZFhimde(K_#!VF$n!!=yYQbq^}^lMh9kc%Twp$p zeEv-J_c!hv*VlaiJh%D53Zq5)+oauwe>-hIZMALtHRnhCrqQ++(DruPUP9aQ%e_D1 zV*G*B?jLuF84kypAI$f*EXd>fDCRTX2;GQ%asl{rQ=ZZCG=22;n>Iz-@9j6841H$M zepmISW{~zfFOomAuetA1Z|J=h-WCJDZ~QrhW?~=Y75s|(puS30C^o*Wk?W51FkA04u z809c|Y2#O1KRESD0FDz_wNmpxoNM9gIP}s)#?p^5^=E7Y z7-JH;$v|`ymw#`v!(99@dL%vu?a3L2qsw@h^B|prw=4I4CvhiLtX&X0oc7%s_Lj!Q zcD!Hf3S?*Osx>RnJ(24hT;FbLaMc&2J>30*Vi;dqbF@yiX)5Lz`(5nuZr9-L8CA#< z#M*Ff=+49vV%y=n=kTrbJ}0wJ>AcSzS3+&W&nlX9)@M@{aWg+FY+Ax@pL|l9iI7#p!n$8_Jx=<=yCB-gqam!qgak%jsGA zmP>0fm{_hs0S|SVbf#1J&+W5C8%i8I{txqQX5V98l(O=#zfY`uXlTlYj{@+ip((F_ zWFRXHO*#0H$Kk0hJ9E&KWa61d-1Cq6`A5F9^Eq_*@^22SpG4ev0)Cj>+=TjV)SZeS z5MMineW}nxTuqJD%qf8xI^%&{tA&i`dEi>&Os&lUhC#rPe)h2Xwma|W?ifC#z5`o?u*L&}*eLWov9T>?8S9Tu-;r&E;%Pf4H>I9&aITZf48cS6e;8}?OMc(Jpop5P zL%Uju0V{K*ZBNcL_U|T_&&TjFixLklCKB6()-*xuP+OkeKYHN9%sQ3cU(eF-rbxr{cyNsMI*7>9?q;Y?=YH| za4nCs?G(pfT2-^kK7ZIg+b)Imc^&>%!x?zKpBT-RoUQiHhU0PhgE_0Nf-_E3e`e@? z24`R>_r=(e!&%fBYx?Y8%zy0Vg&&l0}yJDz8B9$+qWR|r4Y!Vr=(O+h9$V#V>ZiFLqQ_S^Q$h0_HnE!Y>@;bMK@* z8*E0uNcb%y$9`z~t?a{UWlzm3)|0e4%+^eL1?dz=l!}oi;Z)1H$Q<7m->%5uk z&DhK&Yd7<}{=dPxzJUC-+Lhk5cvPKLtET}uZ#Q%F`nRd~5mT!tOiop_R*%-W0sZhc z-c_FbTI$L$HydX2uJooqM&6}93~mV3kVz$V99kHTUkEuTC)++VD+8Tn4*3yUPmM)5 zyac$E%cMLf;jQLgv_277^T5TWj4LmKi?fd5ttVjd0}F4-i{m_~FT&eW&NqtUt%sWN z!4c@SBeDrnR^FqJRPax0t@F~w z8!DM|Pqwi`a~q`-<(LJvKSb!nyx*o1wWH_Ui34hbBaBd#W|klud_tSnx*P~M{{Y-f zFw#FqJ8kTnQQFDjcRbI;(vFjB>UR(C3*OYk^awqtTJ$VfMbELY?%`T2O@9%r-;cmr zV8NL3IT#y>Gl;_I=6Af2(gVgl?A7Y;9o`qLFGRkZ`L^l1Ul023SJIQd-O%{S=)2iz z%L7FR!!w?=+D#5@i+r~oYd^h5`(K5BMB68hWyXuNC!5i-)i&>tTvLMIPBptqUFnu= zvlpFTvW?F6lTI0X_Ij5yvG#pueC<@%iO*iYhO^lZqkn6USi`!i#;W@JG5tw46Q9!F zD!LwmpXI{HeP0Yb)yP&hJZTm@*%4XmMDT0}o>#vBo{uB&>;}JwMEbjo{Ue6qxptPssV$po*h|HuVx@Xa7P=X2-?Zilx;JSaPhTpr|- zMZc47J~+?_e19X}$G}dO&N$vjcb7aV+v!2%E7?so=WREiF@5V1Teg%9RkqX>mi^c` zp)J+2sctmP=a7|SWy{#w8ssJJpx%#Vn-FY1_P}`0&Q+yrlIxekt0yh;b;E=<%;z~v zzTo#|$V8G2^z1ThOtOovCNIs_t#+bYCD*S;2H4I0%a{XVXS=en%c$1Fjf`~x&({zS zP&NFxy-$9*InLwuzHhQ`RP?v)eLngIw$Iu7=6%xB-Zun$UuneNHxpS*`{*o}yAz#@ zzJ~6Or`nNnW^)z>n~$%YO!h8 zGH*WiPq)j?SA5TfeVhLqk=qlvwj5hrJlD3d$4rW>TMg~N6If4s-J@+!r0qP~uA%LO ze(|+;(1zwh{G+Bn?MLM4MV;a1k>G0wzL4BC)D8i^`2CvvN8p83JFgv`Kyl~9q&%CI zG{`@kdU1+BFE7V0G`A?f^X#5+T|wIVhHJ?xH|=GzcJR4pvwm8j`11#g_a*t)(YF;# z#k=6$Sk+y5`;wz|(iwv23*XM|qo`U|e>y0?)N?jiqu1Nu!+^iJ-e`xGbk(d<{Sf$d1_DnNji=6C+REFpF*sc^p_eZvLL$4cI}DGI zekh;bF7|}ImMozE>46UPXvw%GTx(-r*jN13b>4%KJx=sw>z{+VmPGZ>>VFix%zVc) z-|NxwJOzWMxH&I~GdH`aDYhavH?h8x^(}WK*Gm3&Kr_-K2V$e_g5R0UJN2-;%T;d- zdeOB!=C>W4coK75iOxC^9n}ra!?XMW)-)$;NWF=?)zRNmn*gqoH_~FDr+Uy+7l8}n zt4jo-Oy+~1SyrN>If%;ijA`AftX#XoF+NqUUG zB(=-SnZJ6r9GbHIC276lA#D zeccD2i}FI*0xF!I&W?!hBNtkcEgv5mXI{(i5#NDH*{3E?oZX>y1{%8;0YPy{8KjUcC74^R)Ziac@9t$_Z-kKJEpbgK9T( zUF}xj<8hoZXi66H)GTD9TJ$0xH3`ZS*!LJqJGG;8n(M8xyxHHqJ=)eethF1xUU0a9 zK{lSPIn)zjyhE_@$gX+=eYq2d)W%a&M72S>@nL4-OU8cs&>%-b?PP2(6}yf7!w0F> zh&%8mZLVfa4cN`3{|EVB8ZKT@$onbuvD;NSLH41>Z`$^u8CLr#we7@3E7#s&9PK<~ zB)a)d4`|GP=X{6V++PI#yun_y`Aqi|5AAAPhh!gNAIg0I8y&Ey)`Har?`f^%Q*9+~ zK+mQ`_N&#%z>-yS_&=8YYZw3LuxGj*Y1?0N+O=M^{yp)bazYdz-s+z57oQyf zPV9Dhn|1?J18ejz>4D_)YfjS{Z;-LN&!iSBwy?okxBiBI8@883=GTq>oSK+OzH4g0 zi|#a$IlWwCV1Ml7S{E>E`j@f41AKmfHPQc0VoxrkCXDW{X0LZ~FM!=@fH9zUGWdHx zd;X2stv)C+{7>=Dhxk?l=w7YZxRXvd_P<(1EEqQK5BQdiTfU&p@Ik})(c@Xjs2YQC zDS`Q|<-Hqz=Iy@hX9oFT=!rbv`?=8v?HV!oESqk!*2&wH%DmPy4`tAp=AH8dn#%f% zwtLo|`0S<n%x zXnen+wU=WnQO%Tnk-6InO>{B$`u}6*PWSrL&o1U}FM98K=I#OJjGSD565sbTcdsyS z`(6D5366fX?abQ+%$w%R_<3Pd(qenwr0;Bo&dR94Fz+mfIfD6`1no|x55csLHPZS> z7Mn*O=Ms;j_0hU$eWGg<&p8dJTANnZW+m%T3-6k2t-~N|9n|j~^b0S6@23WmnEN}R zk5u4T=ImFyoOQdA=PQsEv~E#2SHfczR~N_gqK{Pa`4++}#V2d9-H1=JH;3x5V~bZd zz{AqvSJ>7=(3hW@8|;ZEUq{7OMtN)L8{rwB<1g3}#9szS_{$7yEeH4HFPtCWo4-gd z(7dWHK;9|lS@{2T=2`VEPc+ZJ29IB@3fH~D=VdI6zIPXMzY3!aUTsPn+UglWm zrf9#sE?4{I@61qw5$c}hM3!*j4~w&E1*E+0HPzlG_(3N0uQQDD@ax3m(`mxD6OYW_ zA6=mB{^IVftVcZZe0_V(ug}=(pB06In`oZRP;Z{svC#`E}T6v3(V8F5ItrG(qgoA?8~#sSDrq znvxH0Uu%$?of2pi{jgtWTw?4e{$NHW{r#ABd_0!|j_5wM0{07la=<;=-4tik0368g z``7T@h9050^PPr2mwj3>#e%I8Jinf{^j~;ezSc{wm#3?hchEDo=biza@JZyjTH#`u zc#I`CT+G~-Ag2{G*Qzc3$HvLUk|92S-LBbSpU>eo@D&;8z{pR;B0Ly-wpZ+#G}gVC zn7~}Ag_;zoJn({cJq)yJDB&53cD6Zw6=tB z#mKbm0OYHkX4RQvPA$1B$-=jY+(q0<1+gk#?!|L`A#&ITepd~*YsJN5cW&jsk66!| zFA=l)=(-cftR5)(e9S5}!YsUx)&%L~nQ*mzUO{M-XrM3aH-A?7gu>#!3d^H}GRsK%r!vvjF&bi@jFgqOwYL0Gl^H_qPBAu2J0TEpHQd&-^PtQn4kzVk7_H)QQYbDR``y=S$4cDB=*R?YQS9 zFCm|1x~JF9Day|QhsvSBdBctT`DYpV$~Uli6Lleo0T6G}Sar=uT&#Feehxed+V~l; z>;D-3N6)D-n76-vn{|c;X7icD$Nd;}2iULN&_`CorJ>@SOGCp8sar7afh*eo^xQ2r z9rdh*IC>Da6XN&};Nu^g=naiFy!mfJTibqJWN!ZsaZkng^CRxc<@eN_Zs$= z=i!+Ra}~c>_@?}C$wum3$|a(yCA9cv?B9e+G(3$m6e&_^;m8V!he~m|rc4G6m zMfRUm$EsChU7R<-yxH;UDS-sewDJ;TQ%SC)U~9PV+tmNf=+-mqwkRjVK4&7Iw$xt@ zv@1IHecG2&zUVx}HazTQ&*oa&C!DPaJ^T4DfAenI5dID4-QIQ!*(^SrFJ5BXEv{e< zrfD5Ybmo)CJUm^r5;^aw#7TWN2Qet_faXnh`{-J0?zIL>n4{>mG0>3aQgeDGxcYnv zawIf#_4kj{kU`zIjtC8*=Y<;g8ap(%nackJ?lt^BIL@(BG<6#|8Xe0AToVlC5qwk3 zn}hXZ&7n0L$Ffup3R+%MedcG4;R&X-H(Zx!t=&4>odd6Ymv;1y8+xiCzA>n}#?&m{ zjm!~kUu_#VZk~`u9jJ!t#|qTmX4ObJ|C`6!8ZJIbTiL9|LG~`?Lc6hz2ie17&y`st z+cx!j8|eRulH=#fH1mJWTxuFuUpIceYW1IePmg^lCYSv|)$Jv3;=$hM%IIAm_Ho6e zozB{e#0rIYdxanPrH>4Puj%~nAT-mm#n>@~xFX@pKQ6l< z=`-e(d40B-`D;Ep(*HdB@S7j?^QSWphtJIPOD}Ej>m`?oxNLlG?R{NM!4e}R98ztX z`OLu}7wtp8?rS5w5#6vHzUZhn{E|UL@1j@Xo&)+pKHk82trk9H5-(G;j`LE<$*76c zr(VW2J^uu-T6F-azb-$=d90&yW;>tk>F3b<7sDGe!MkXliYxngp12!YRvh9w_R=?E z=yo))H_GS89wj_&q_(K$Pq?rBp8TyN;fmADaB|;n;eIA~8r_%fuTZ*@(o0??@BQ?vgwcgy8VxP&7L!ARR zc6{Z_1mFLO3BcNTSj`xw(Qju9+-~#-&86m1`9PA7eNIDljZ-QvG+F|DyUDX&%{ROubb$Rc z6&)IzdRJMhG2>Hk{V=#0e6ra51pGV*UsyTE}-wT$2SIhKN$o*hd6sg zGT0&B%OL;4OK!vO;rAhEPjDy(l^XUhf> zj1L}DN<1#|$jyn^9hP!dNbT9wDW}hxY;XP(?9o}u4euW1-@`agBnO+>lp>u2?{Qtv zdC@)jj{1l@hO;Tem!}2hM)I`uyv1*bh5i^Bv63}tRXoeB-j*7dG1?7n?=GR1KKp>? zKy=kuef{|7qVJJg805WC;B(~&-W|ldv;mH{)DZt}y{~mW#ruEb{p56GjET(xKL&fY z9WS(%cp=4NG-99dKsSYs)Gp0=6}lt(W4ih=px1P4`uTNsj+qsU1rCJIMJH9OIxi&yKXK+_gei+|HRd*-&da#dA^<8 zD4jW#jeK&q^*rzKyxI{@N@dR7vm@`&UpY3==sRh=L%ev(OVlDQg^o7i*DAWGr;on` zS)}0vakw?uiQT90@m~on#rO_Hr)oC`e9gL`XWQ$}K5^T@vrgUi`M`V-8q)ez4mbQ& z%!%@*4x-C-l@#TN+2h`4U4!cto8QOW&boGBqdf4;cTDPowX~UrIg0rF?E{U_%dB$( z^jSLxyC(Fa+R(Ec{W>=@w~C{e4NbVU3!G>J4|W+Vy^=0r6-im)v>tFI=c*g2@?6UY5-Wq0XP>#tG@UL_oajDr3Q~dOo_%#&k*gDjh z@lN)|rU(0&WWTCxPyL<;ip_TB@Zb1P-eq5(iOdtMwPk?Je0!fTjSG?vfqyx~yqG1} z+FhJ+3C|M$lCC7VLO7NVFL?poK)#n~?o|poeygFC8pbNR80tt~Dj(XX%v%LM56yuu z{;gF*UrDc5exI8*(iYv-eLK86#PiZ!)A-%Sn#li%?mt8AF~9g821opob~_%=Tlgi@ z>$P`?_Sz!4XzRDYKgL81#sy{k*4`H%K0m26)m^(8eZ{?~yvMlqM8=i*S>Lfg2Ua7# z@`}R`f_2vk_<>@6T4UDv ztHk{5!>1DlhYy3p>RT~Cf<^dqjCTT$a78{>;fZY7!WkF;WAR1%R}T0BejW2~r}9iE zYgNj<8Q2$Uu=(UIy2$cx2P6LN4vR;7I%m`FasPHtJn8@+bJc#t$E~^0dX>UIwU&pm zM``VicgYC_r_7Jex7R#|HnOx|um&CQp$mZ}2i~E4v-QkDEFG`g8J?j!0itCNRtZ%@ z&x@ev8sOA`+L!dGCS<&|H;huWzNTJb+h3B{8 z#}%{x?ojIeg5Rpkt$IN3Ah%tQ>?)hkZvH=ZC-l!a70-x{5xNk1_QvEJ4~3p9*uzB6 zrR-P9(4b(^K2=Ekt>`%?;q6t)?+!Ue&+bLHb_emf2-hCr`%2!^I$E^Nf19=kTePjV zZQ4$a(6-&C$MZI{Jp|fL?qaW+(S}_@XF=>n&-f?j2(=>1$p5G_GQ*=BE73{D0HZZW z26pql(64apQ^qCQ72T%%*kLwgPcXHXg^AAbo@)%tc9j{Ck8|IRtYhJ7QUY0bAE#jpR%lqT{!hiJe2NchH8i{u8dl#H4FijCCOSsZmheL~ zEZh(c3s1E6u{dJW@U6#a7}><~$tjOiG<+>|`lWx@gg;CgYM%SZS14)I(o<)>O7xhC3%|E<&<|2p~{dQLXiB&+<4Hbk$h zBlqkce#MU==kN39dS@FJh)>OQ2>$b?e&6V9QIUu>f z4UI|uj`}rZ&#j^_+cxSzCU>Imy3ltGzj6fSQyK+7(AmC0tEL_MOpMwh-qX%5@t_tEt1=mdxxNbZNTw{PMcJ8C|v{N+T z_2#3ijP^z3oakDV|DW@dX49u7f3O}}3$6VO`iNbNGih6EG7*16X&iBYaYiWDkc>u0^dlz-t|q1_3`A+Dz~&0zef&wpI|6u{b#ZMIebp^Uv?o~Cx^m1NA4a~$h);CBz(jxxPz^6P8T}(D?4QTt3+Yz{MQrMRDsevhQe==C3*L$D0 zp2J)Kua$eJS`@R$(OLtX@q@jg5q$JNOaHNVKZ%8X%pi($T(6N zhmUc|4`ZPJ0sl$^{a-MvjyvN6=3?`Z1+RTZRTQq1eMkK;C-N0paHHdm;3GJTly4FP z=VoL|3(hLT|1q>G8h_#O^OKr^F$(h=(xdplwttan^eHlburyqk$+gCa-==}Fd#0n*>nH5aqO0E*?r{~beNwa!+-K47dELl_M*u7-6ilU_Ezm_t=QkK zef6j3C&@1?KV>KMBA!k_>@k1p^XSEC`0AvKNgj;q-Ra2bvQZ%e>x}6ggB&TAoZbyT zTaC^&m+Lk0Z>}1&Bdxv>T5~VDqq_|~I~94WneV^z&L3o?^v;M}5Do+%LZ{qHputmkxcxe?*%)zgzVAVuU_hkMteup>4tHL6*;O zq;>68Zms7{5jVJ5Jb>Av@1wUL2Lx=!t3T|5s!pyxjz^AGAoV`a*6CO$h{lhJ|CSV&KR>~4!$(x zoB4d-z;|8*mSRWEDj&Zq=)-Nn;)=fTrIx~xK|Ugi&ZiY z=kQ;4vDkL({oWB+g{)0|wZJWWf1xZC*(0K|kmq(}A@+vevd}>FXYG0RnKA#kJxZH> z%mbr1ixD|kzB=}+4gaPt+&k>8_>aKf4D{xVz$N$#9$?Q1US!j28F(&wo%rMPlLF|A zxuR2ic@5d}f9d?fw^_Pa0RXx&=gvChUpK047klHo0hmJd2-@)V2b2>0DbcDWnf#Kc>2 zP;%g5^-G*f+VV?7W3dg0?}#^@obRMY_)aP@dp6%`6yJFxtzPZ8m*5MA_XL?|)fjk` z@3-MSHoqBS@tfW3@%iX|E#O%Wc9c!{mt+IT!NwzdfapwmgJSe-8vr)h^BnA(;W5&U z#9Pb=Z>i=x%3BmKrZ}PwK1P-&kMV!Lrm%%0f3oDboNDAPXhXFvwbt!LQ<5HdgxH?L z;nDiP<_G5|2}hj&QF+BJ^snDV_=B+Due6?bp#$>V?r%@AzV}>mc~TC~=~`vsl%!W_ zOR&IIax-_<}7pt;=I(Z z?87?eILC0;f6DyhmwPaXPewVQ(!)(Bx;Hv*2iJ2RzBHtBoyR}iHxy*vZ=ECmfxF9_ zK`sC_EX9-Mt4#tYWKX;se2A@?HJCj}{toRyHR$Roj&utbly{}PdhJ2M__SC`G>-BANpj* zb%vRVz19&|Ibrswsef=M8KK|PZfs4qZxYAmk@ zV>SLV(F<`Pfnm_zF6OTTp3_FGd|R^7+)BLm6ySx90$%2_w6?FMU%oX?*D?ZH&#}w< zh9+_^T04#Q?b>PF^Z2PXMIOKCIS)N9O3zWdZVi2Hhb~n+O};9f3#c}8*A)0Q)*RL> z%hSuggl{MoAEIsLe1XsC3fiBA93cFdj2tk}Osf}OkND=4q#ODab=St!QF|Gfde>2# z!Wd)gsOkULtD|Pa@H8;I(wugzj+)y0d>ys49(B}&>#}EUk;Bhke zvJ3m%o7m@sE5*>l^Y4e7g&VUXxbau&0J2hRugmE#o}i5r2CQoz%L=evq-GuN7+@ z-Jj1I*Ymu*-ZIIgClnLz3}8dZ&yf6t95p<3@hTTFW)=7{*lRZ!=!T1_#nfBAF!28y zub=H-T+2P+E_B=RP1^4kjK=p3|Nb7|qJP=7u#Z^$dh@-uU2o2(AHwrf118VNPg@vg z+`I-_(fi-$nkAFdMrlkNvb}!;omM!#`L2k4Fl4t=7kNiAfZkQxwOl*ENBE>`vG;z; z^?iKQ-~G(Bxlr~s#SZs6YZg1#IOZn@`L~03JM0{{j7H{sWGppQIQMfczTZR0SX#SX zGpTO_zEE%PbmT?k^^ECZ&Kn9Nvj?+{eDS8gasH*9iO*?nJkUV= zG^4xEx%RoCyNPGY`f-wFLmLinJonL~b!o2=Q^?s6o+R(a_&D-`wf2V9cT49e=f+ab zs_r0Ot&zCm;Hct_&l4}W5SyF1;>?YWTh83*b`g6vJD)S_|BE<*$^suW7bGTxJ!Nb= zd&ZKnmL2z5chzVsW;`~3I<(D&9mGp0ArHFg+`lRCNMu~XC z<|>taRBQR}{hU=!4BPXrLh^dg?0yLyLNd#?a~vxLiwC%JflDz>T2l));4TNg9{`hJ zBo=Di-=WWT=J};n^L{xATH~gNX*^$y2sFW$2!i=k`Imi@{a#@{&wCE`F*5h#lq{6J05-XqcqMgE+q$O z*XcD~ThXQ3j^4eq@ghgF{86p%-@P++wrc!n{*+heu5~A+)wVLfIb%gn0X{ zF4%OhVOAj%s;`BApKQ+i)&IlXo5x30-~0b(G6FMM*s=jZLx@Te6s)Ku6)qD}mBp<< zrLKV38WyX9sAx5TbO{8|5iG5=mmqD;42v5m)Y_o*-UiVM;?i4t%K+YXCV{F6%M1$h zd%n(+93pVG-f(avvjE0;kE3mvKwy(_E_MK0qz6rFB+>a$=guL zH|F`9=IjbDW1bm)mN{#FkIWx^cVb9xq+4Z_kE1*`v>Q3FQiB(9U(9`r zHw+=U`&z#@f}bMBMR79Beul=A zdpWhmxY#pkC-Deo5sM%VTS2aO%_6ozm0}yv?y-z(@;OhU_{2AsC!hCVci~CI)_M}A zjn!;yOKIyT^kE_XD>c{`9ah_K#vZWZ+Oj(3D0+hYSIf)I{X%=Vd<>eXPcg9-|GZdTGx3JefN+hkeXl@tli@L*s*Y zTyQ-(l-GKLhp`c=VXv>Hts1|5b=R|xW|T#}8D&LFmrN+?Wjq{VybthfqhG!j*IE5o zSDvV(P0_VimmM2)YbcdHv@bZ3J*SOu-nh9=VbFqtKo(-9sTzUKn&fx4b zTen=+`P{a@$CAswWPUdiUrfAKL+YQO>Hh)ew&2J&|NHSKcy8?S5x9oN@OgO3%^~^P5)XqoJo% zOOqxaKrHw0kS~)f;l)dQBaGhpC%pGB+KT*-Pq7z2u-IJU!g>8WE4vvl{{A&$TXS7P zPIf2$TdEO%O6$pQeD+i}@w1*b=U{gDj-?%O-})JOb=V4W4&M(yY+uV2w5uLlxT-?q z^BVR>J@a`CGlr0t`>Gn_bMcwt^?TBf%9cl;@&ki4y*stS^6xAs2HUI!@bLT!h{0CO z|18!-74YlXN2|I$){4GiQVX!t@oSsW_SjSGtvmbhtMjDczwO_dW~9|EDd0PP)jyo_ zrLVwvaq18Azg)w9TZJE_WV2hmsdeIYZvjRheq)$B&A{|0rGzTRQoWCi7w&Il z*F|_100-;gV~#TpJj>O1BM`LKLl29qPRdcs@xEHmdsa%e`Gk9o;@D$`sb{^ERd z><@G?*U=NcQ`gZ?fZMira!4^76r(hnlDRYF?HSiP*4ouN7B3swb~bem?PuM&j7L{!nyXYDnjlu?lQP*2o_od#l-+H>`Q+ zQ>+3XdUVY7?CS@B>m&Y)Z^s3}vGgmlwmk7x26oTSm7DW9IV-)4eZ4F;ioO+Ki^#m* z&wL(@orc!5{0y{bI{TgY%m(4<+@2<$_5p7kG>|frkzSWkVD{Wj&&qde{&zxWRaIrrX zzrK8YW&&GF7^6^XV19Gj^K3h-f8(SL=zTMi8{%I?)j_-R0xgJmv%UCvH(U1*u1WRy|g{kb%{D#RsmYf5JmQL7l&&E0auNhk+z&QX-{RG^NUx+TO zs@#li9szfvH zSX+u?(Dbxn#<`SUzkvB5o1E&SkMB9+%?qDv&ySfsvg&etS#^r-t#a|x^R70w90#vQ z*q@`*iKz(xdyIX$jXg364^^GRIvt2UmK=!-e#m~tUc;E6V^X}x>~N*mNL&t_NyMR0 zY`>>nF$s74m^hs$NADTs@wF5YqcisDV=t{v@v}#N`BWeF=sxKCeZ-saEjBiPLA+1{ zf9lq{lPjBPn|N)>NqNK}R9#bu!>PIku$PWypEP3-PV;=eowlT#vG>wDVrxQM6o0e@ zI8JQB8B49$gxW)o+s{(d`w&MWEiBt2#q2sv`BZS;4DCA7Pw~@oTD-)6d?cm+&Pl|M zs70>upLl%Fj%s7`4$7LR80J}nLxY;z9)HQALGh<@=$~|BO(!4U(^Q2niLrQ%zB&EM zVjQZ_At*LQ_EpA~PvJ)m=*5iQ#%_&8k*EL8{1*+ofBlFpNdL%@Jqllb#fXsZ`#A9% z{qIcKBHm%qAM>|p|IhK|)P3LVPyg`6^yN$OG*ghh*#8Ar-{_tG&?uct5aVEvVvPD( zJBkrla_F(A^v;+gkDGCcPl+`O-Zv~bHP+~g6gxICaa#A8@GABwroP}gu}j@?OB?W= z-avh4ifuT{YsWSuN5)Tq*S`N<8raf2YooRQ4Oup!_F`*|70k2tz`MY$WHoaSoR)9O zmwzzF+TusPU@mEG7}7o1?>`}$N$_;;$=TYXd^n%UAB8c&y zmhK~tS9W;HG}-EB5d%Fte!v`uZ1M->gm! z{DZmHKunD@#d+SrGo9~ieWl{_A)DJ0Vkc-^Lp51(AN|>uYVC)wT-vc8ev|T}^ldV{ zQe*PcP-9JId@B6QtMjb>oNM-H^m6S9&CD;eKR)%RfB4vV*4F*>sit>)9p71f>QA5Y z!n3^nU40t8XLg0vr=|RlXP(S3=SW(()@%2v;H$B#XYj1OPvmu1JlzuJyV)miCZPuL zbEFL#pEX|Z?q{cacWa;LJgB706~>DAMD`?eKIet!)8_}x>zwd|Tz_#xAmPmQIo!`P zpJj*d6>iuww~^28YT%0|Oczf5JBT&tUloHMG!JEOC*MVMFuD}%X7s*jMF1F6_&(~j zY1;Vm#I4*TgX}7vH#E2yK3eo-pJ-5HDtrWdGjy$ZS|HvGt%ODf`O&o|HjFrxt_{l(WPU*5qB9Miq?o_G~x7LD8IDqq*}-XZsU@NY@v=K2lE zO@F6cwuYj2l1X&_GL`*HJdN~`KSH)tUt+V!ag2N@UE58_gh$80Z$OuI9|aHP_}<8d zDS3@YzSW%ZEP5t6UVKD$I60iMVf?Q2B(5#;tUxca3BG*iYUGy){Cq8XzW1qj5!ccs ze@xutstV)9h1Wr2Z^fSl+EU50%184j9=itqy3k)HoqPm7Nn`tir!AgRvPn7Rl|2G4 z>0C)Mn+li%Iy>?aUqI_8GSrj!VlZ=SklL1u?n!4g(AZ+nis+y&!Q{*dSsNoj2*+d3v}=&m;U4#Q}@Qbqn~R+Kc}{79jbjg?~-25X-9IAwMIL) z<*413D0E5f5f0a+`0D-&o{}@KDAhdvjBn-36Qh02v@HTIwNFIBYXNPH(Z)dbwvir# z7<@kL>3AoaNgt7Wg!35dR%20qF8Nj&n^DX^jT8PGiE@AS$N;&q&GFGVb>o-J4-H^$ zmi~+O%s$~=s^92SmyZk>NgABhc@opL-vb{#nHk^E%e@b~wb*3kj>!uTAVv>z;OEGI zL4(*vKK`e%cN>yBZ)KnH;zPkcB$?lYgKa@Rd2RezhAF#o9*@7)IlK35_XYRUp92TF zq1(wX8Sx?d_GBP2)!g4aiQ&xOBWdK*WKKnUXg+3}GU8!)2C=xOqiOF6)!ev6a$xN;4{NuDKR8B?#FtWj$cgA$&DD(HTkym>cU>UA2xO>aZbq4O7!BUu zTf|#WBTiKPLi~A=TWg0Pr_5&08dg0L8D&eP!jfIPiLXWnR7*dPyi7hz>?~v}ti9qB z@HGKjUN#mHVAL}{l2zWN ztbKo4$9!C8>Be?Yt~N_&Rp0Ht(0=~aAFJ(8Oz>@7KL_2_mL}S3lrpw!ueQeIxfJrb zWCYE%xmWp|SextEZ)oq48*U9XqAzb?tQ%O5kwVr8xJct!qjcq^l(QxYx<`Mq!u=Sd zTJ(YuzCZFD>jgYNYwF86-yh^zq4w>#*wPb)HmskMT*@^%=x1sJS_w)59P?^S8sW>P2 zi_OWE``}X|=-u~JCRffR_Q~vD^DGlzyJxZQVlIo;NpHLW+NSstib*NGyL9@}m-bbg z8Hbm>-;6KsYHT+BDjCD>YLDv2-%B(;Rrj%+R9Yh8cNwbo3fbk?ksLwZ)#u`Xk}cld^f zSeFkmFRx8*Izai90+z#G93cZ{Bd2&+|us^b4Zv*z5JZrLHZv*!49N3%(NKaqH z*#LU`7o_uxZRc!`GlKjKg9tyu76h9YX+>G~o2YaU4ZPU7>ZOydR z>2LWHR@?4OvD&r|m@VWN9YZ}a>HnGwb=~h~QCwa^>YF zUfBn!XP2uU&l0PifyqztQOz&;12A_3eqQ_%DrHX&a?hEb1$AK0>5L*(RTYq2h6^)53lE)Q=YLW(`Iu|{uR%J3*H_6 z0c~^ltEiuao1gOz_VQU9?Y2wTulG)PjTH}f!bNn5_00pF%6&tv@_C)g&31sZ8tM?v zx4CfE=)8+=Svcce6VCzKA${$Gd?P%Mu-on6IU76=ciIZB)Ycz?Uk6XCcqaQAmFpYH zRGsggXA#$XAGxl9fxa*={2Ka;Nwni9<~?*B9nFp0YmBbv|1G|8+9jAeLvmnu=h~@P zvb^3aQqD8_Ciy_`iSJgqiKp@9i85fCytm&Ne$08t!OwZtx1YJ->f1xympSj+^WMSx z1%hXtc?>^-9X0%amgMYw%ICp1oa2lE?+8|tmpXW!%kw-NrplK)@SV13e$kH%yS*B_ zO~j`YJ|r`Aqx>>#tpDBl4tYXwYSn+9C)smlzwY2l_*^|0yi#^^r}CdszNr%&UycQ5 zgX`TLuIt}A@7w(%ri`iB<)W1e}P z9e$i^>Ex=r8JktVGvA_xW6k=b_;E&tmM6})VY$|d*{%yHm%KXLZdZY;PPHqIcJ-%B z_;A*t`X#x^X`9xlIo3(bce~bXn~!zrN!+CNA-}x-FuEdSXmcJQFW;#08h`Lrm9u`$ za@sMDa^bE?YXf{;&AoeHe#C^`FC5VK%(;5*B}VB_|_v)bz;@4Q#!e$Up41*mHv<&upYx%(jdyLfIr%j4N$`0WSGHfDu$1;ggK zv-FI;8+-8k7vNu`xjnB0UKUF})hIZmqV#Q!&Aj}fUlFC@OQ1-{Xd zJDk{=vBGmL9=D=faE*A}UtSq}7Cq70zSR@%z45F(?hB{kai0{AyAU|Cc{$Mgt32*s zp(ARGaIdz_qP7=~BYtx#n87_eW@*$@|^K zGwlJ|`>N3iJ8OS7cz>LGgZ+79u_c#)$6W>MWq+0t+|M{!a*4%<8tnIyNeV8t_U6&Q z`V<>hVsOGgALIL%`z2TA&a`k~?w`tuKzp^vC@+G_F63W*(RG8(n~tD;YMaW`FSDF= ze}${OoVMojPI5+a8Wj94 zG*Ylex$KQ6(0+~KNd6srUq0<++V2CFBkUcc! z<$WwT&pvIzdDQ+!c(nS)nG|Io@jIQpaV6!u_^E$$z~j>YBhGR=;cUWLaMt%UIO{@N zgtO0x%j@85+hMD(YkJx9dzsbO0Pl9j*%7{TaJJV4LpXblxLCs3n(h{ylqD9NA;8f$ zZk!FIY%#yn;Vh5x8h*mr1>h`T;_Rz_>Svp4N4)2JWxh4t58nozbLQJzWPbT(Y{oZd zH8!xsl1Xesx305#(+=ZH%hoAZHco%{z7&0XNo&*FkyhDG;6pg+cQx=o*e+J5pmR(i z-xc4lNeOIdK*z&c+OQd2oP4l>sS^EjZH`f@{p3M(&fCx{KTiLfQjOs9g`5GTSUO?Bw{#Pk;b{XsD^|}O zR;o39bh7M19e;W3w4acl!&k@Dj}K||m8I{AKdSurmDYxPK5lJ#L z=EH8()AA<#Naa&Mc&}*eORcr%?`R$KRHStj@f@F}yy%lh_NXt}8J?Xv*!gJvPgGlp zyJFfwV?#F;zg5YNvW0$Q*xrZV(+f=*GP@AAws?t`P96DZ`h3e#OMak zQ^9Y97^Blt$)iH7%thGk-^=`ZnrAJ{fmw|II>vtn_7^)f2N?h1kEN{|%eWUa?u!`r zX6E5o#$IOv4LxL&mA&(#u}{4xJH;jEhgz?F>i4ZazPV^@q%{qj(kg7^W-eGvj_352 zZ)3+3XFpIriYWH2zP~@R$H?fjvuR<6Esvjb;J0Xx`lhx=Q~awGN6zo{uiDF=v6pdI zA5xhcsr%6N<3s4-43c$@{oXG|Ok-~8eGhYM7I4y-TeFy3>U$b_Pbx5Lryy!`|k|u zh~nP~pK*oG82sEvdRRFhO#axmH)!()62mx8Im{W&YWfhN56)bD$*d>SoU3}zS~DGa zKODc2)?(#Y_-eW4;`UmL+ql5OB^R`%5X@;Y%kwBK6$+u7(vXWnGweW&s! ze`T*d4R2!lLXFZh?b|NiWbh!1&gSs%(AmGWTJ&++heJ%=cFII+zy2=obf&X;lnJH* zt?uH2Av(Jc{#0~!+8zten>Si;CfVP(_x&-Hy}<8ubhe!G5I^l3swqq_)=eg zZTHplw$;}=$69^uOS=Wf-Pa7t=Gpzpr9YSc6a8s)_2=>*CQbglntk-Y>%;S|KK!gx zALiM8*!OQ%A4XSLeTdrMxcl%I%D!Ru;cq=ouJo9FIDKxHY-r>wwCyL*n^%b~V66dc zR^U0bS4ieauvduJI)*ML-<#9IUNtFd)0+tNM!Z%8dJ~7fjdu%)@mhfHL!Vl#pHp$nlmL{q+B1b;j8TloszQv znqv7ZdeHeI`?&lTFT-z9@}n7 zef)0mVgJ^k@v!{kPvaX8z1JG-i~WmiKaR5gkHHVd;RihnPOi+NJc<251*X^qf9!=DEuP%osseSg+H&hazBs3e(9lwo=~MpKl{QnlJlFk z-k0xLA>Lrrtl_0Iz~^k>Y=iD9pH1a?t9N#KSj&$g+&L5{PTsWc{|4a-6%1W67 zRq*8E`(*QV9X_Z5@LdT%?j!z)XqL`=Z-Xb+US-}hKHuivqCr=~uU^F*bmFFvKWw`v zcq8+(vyZQtTa0JIr{-XI32T-t z#zbpTzN!}PbHX2d2l~Kzf0%XBhjnQX8&hl8S(omZ2R{5>a`6L~&L*GuyNnCA=zn@9 z_dolrs${+S$jcdJ&Glnl{)YcN-k07&@eaPu{TO(RQD2F3(1$6Z9Grh5&Osk!huoGo z!0FhEK-oC>l~dPhPRknB-Z*r8v{{;zVhiq1C@2ce!m zYYcAxu|-dX|HhO)R@_?Vg4%Z%v;`lYtT(}j+NOHdK6lK^3gl3YnKNEaOajhx&Kk#B zW7rSfj_mv|ZfKeVa|5)+OA} z=A8#T2KlW^;)}U{%eE;RMZ6!aB_Fm$XUbiz`KH{}`d+vh!2ZMg!AfM5!#7;T{_qX< zhYD!bXx52h*I7P~(G>iov4is&M&jMfQ*&22&$K@E{12Jde&hJ+d=wqKW4rT`T(N^7ymVU_^?o3OQ+kLx> z2PhT}Iyrnl)}W8R47vM(EMwE<>DbWmFL|d3JCmao27d6^jlIbp!gT><$tw0%<=Gf! zY!x5s`?PmYUb<(I}UonHpO?)-Z2>$%}DI*1tOF43x# z(6N_&W!XP7R(!a>TQJT#G-G+3>sfICoT>f=v_&?hhIiD5`TdPK+nBrXG~gg7oXvYj z7=PWr`Xi$>$bCNgjQ!mePlEWH=rS4@ckQ9`E@UhRTE6+tK02<-S}W#WngVTN-`WQ( ztt0K7JAl_X^Rm+0m}k+v(OYAMqqpMYSJFgGNfS5l>VNyG>Q`;PRhDb z7I2j~sL$uCokl?j6-O&w}n?F!I7w_9w+ht%jcXkO_RY>^+Y?EF0PT z0rptoNp`~#=D#CV$RVO>`liE9@C!^{60{1@_H z;0cbK<_R_r?;4s3Ok!q)O8Ae};J-?J&CjKV{P4xGp;l}t`JO0dLEDvqgkl!>E(nC? z;sbBymqa&JOss%W@bdlw&m=!@}}_ zmYr6f_{9a#o{8Ay)}+jjt|OjA%}u3|n(C2J;Ld~&J(`7AF@sK z8tfET8Hq{WpIUzPgFU8Sy?D%3_l5z{#L@@oGORq znY>z4>c_}od8-5mejUDVe!MBolE+r^KacMuyP@mDx4v)7zEn#ddlmnw|6U#=&ea*@ zvCCZY*eo}X*GV4Jxt{u9$zyr8JoYjCW!@^uW1PFe|5^NYL;ntW>{WQw2I4d5+17Ow(+xq-(S{l_lW?E&EHkzgqqZz*Q*6y zR(79)@5FzQ&F2Drn_gzcfVgi&aBaXj-@VE{S0(;|Jbt z#TZb00nJN|OR_DsEW~_^RRj{6qm2`DOXYK?_yR@nP4c~y50U2JFTLK~ivQQZJgcfEOSlAuKP!;KbRhW7F^aHvUHw`t!hGcve31@BsD=%B6z{(U*Mox#(nY zH3gXh8xYaX!aKnad%gCuO!l@mTgT+cMH%dCjka6?-?-av>zCv|s&gJkzvP#G2{^I4 z4SR2!5wAtZbaa+s<`&7}THi+}a-IM#WiM{Yl6|l@$Ox|hCx_tGw)HbE`w*Hf-Cq;* zJvK`=EPgY;vD1#&MD3q`OP+?-SaR?l_NmNOvAeDJ7a-s5K+p0PJcNT2OK;Vu#lybm z|FYZg9q3?`3w|)VlWX}YPHF*iFY=HXyLB9Lk@QqA(%z%ALpq~}7*qL0;RG7ahAuXG z&n>MdH<<8z%DmB-F?ObngG+y8Ab}-4C*_21r=BK! zUXFs3Bh;N+;|clF@Tu&IOfUsI2Jkhi0zC@x6h`5Dr#V@K-(Bu=z+Y>azBEPn*STSi z0j6{m4&1(8ZwNa=_GA3(?q#pTCZYtmqW#I4Wu^JI8lj>L)^|bY+!p7Swm}Q-bmgbH zi~5g(`>W{}Jlp4Mxz~7ePWF`?7c)EMsp*{K!Uv4i?J*Ct!gq4UsktRtM{`u?Eg|4X zD3gA$656cu?uE!qYP;%p+U=J4m8(YjQ)g~FGCzCzS!I6l%H_0SwJXm>A@f9SQhS_! zPNPjZtPkl3+-oDpUK@V)siOH0w&%C-do9_%nfWw^XW#a)b|@>Ee?{EqWp9Ol7tcGx z#AD}}f1Tz%ZGp!$bJP%{AR#;m2a@fJGRS>{4VB{`o1D_4Y)#q&p(uN1lsyx=xV7Ck z_CSxI_RRpXW!?McHHFNbB>a+hbRxlgNuujmLx0Q8!B%%I`#<^72au;L!ngaFM`N%h zY@*H>HaGiP;PcjYFWdiVIljW(%ZipPnNWM}Mq^o%kHxgWpr# zHP>5v_Q%B4pzi2_>&s#XI(%Eluzy9Xzz?)##)c*D6@R*}RrUCXyxnTnQ`nt&72Si2 zx*uvyUemoS*$AKcnkV7!WyH~W!edew&p+9o5$u-%-%)7S_ilM2UG?q3_vE8;bMFZ- zKT_Er(in?t;UA{3k1j?R7=D=gr&;=J5Bo#}o`2tg?!o>1MglWJd&oh$YjglV2Kp{L zwwJMU;f&O>)u4VKHcD-OfX9F)@84NYj1O#SGd(74x>f$k^qYBrk7M_sk+E%L^zV8H zeimCfor9eA`A0l|*^{`P=U;%c!+azE+y?p~-`vP@=9V|TER*L)dEUlz(Y0Fi-6mbD z;(0|z**KodzjyRQe8*nm>`hlZYVA$3*Zbnf=r?LSi97KP)>`b>4|%@@{`(`!8N1}i z9{7!0OOt!R`D^6z+e;rF<=J+gF&>eZY3nS;M&rY{h-cV`?6SXxSS{W(_{6-D&>zq> zPcKhQWzUJ+?MeKSJS2zbmYX>^qWH8c-WGE0q@(TrY@$tBrjB@r%b!hoQ!IbBtnlH7 zJc*~ck9zI+Id$cUW!&$94;R0GD}CR~{`}^>r_%IekJ!G5;P>eB^kbbTVa4vt41e6$ zv!V^Y7mJrfXBBz{xU9E{tcxgXPWTt>YR2?b|KP8}E^uJ;eH(M`T)}3|RKin5nAd%| zkF<5z5@+ik_@-?#>oeJc?D^;9rXH04k$hYaX^yeKr3nr+U2y8*ow{*f@BLQ1p69aR z@w(vDdndu0Wto0|Ckn)0PHuk>gNOF|>T7O-r^|^4ex2OZM)@VO)r65% z8**g?7{aS!^ldQlWyk0n#`p}gY{H+T+{ga8Xvh;2>buPk`SCk`7MM<()dzF~TYgR7 zr+ypWk#|FHFP%_)?fN+p`n-?+HhOa{Jwk;=^TsY&Iw7=Vy&2D`2$>T9>{7v8i+pgH ze#eFfw!Vd5v5&KU;Vq1BvG5k_)}_o3{HV7}S>wd4(hzb?jQzPJn7&1FMPzs&@jCXJ z4TI)~8mr1e;h~R&)_ZT=5*?HiY95*!I#}b`+5(>b$9}+tv{!z>jJM)`h~~xKS^8dV z-G)}ROR|*OWzuunF(ds@Yun%ZgpzmnC{s)afAE~R6W2ks{S(GEGK_P=H0TSmkq`PJ zS!;~`HP-yU?7bzvrD+-Lr} zJf!nqeP4-;qW7Ktw11PW^P^E8&Sgz4C#QScvH!)leNX+?X=7*H<$$}n;7)SB_Qd)- z;Ja?H`0QMGo#E)6A})T}Inx{?ngma(Tq2T-^=;z-)-v?}vd@xV@j>3gGxbw*MLx)z z^e*e(%0ZHA%5Syg{_L}x+@I9%gO61%fFfi@orxZ2K72uaUh2}B=p*)-s6+R^dNyjo z?8pP!$2=Py$JyxE9`M>W59g=vqws~FhCDc)xiA*lOuXFyc)P`{fmia4P0jSpEgyPL zBOf9QW!-e1qZ`W!@5|+!;dt`$LzEktz^ALI#h$+>_%gL8@LE~wvD7siLriS9ua3EI{2m#c??Ik44WKER^^2J z1Bm?!y+|!G5`$m-Vd!Ez57#X5s+$bzXo7lySf7>1p zpE}I5gXmDv32?$0x#Y$Y>gX&xRw8rGqCbk^(4Y31@$iAEzMf77EhLw@drdhqXl3uS z%b-huJ;l~_jQ8&$K1AlK7V0@j8#yCL%(i3U*P%C=O?%|y_C3ls5W{N-eeTXa;*N!{ z`?JNu9}h2f5B<$Y7s8%5X@fm~8tpc0qz&(E&TNl`{~2u&OvS^$;mhRa9rG`aA7qUm zWBq6zJ7cc7sC`4{`LgG|lY8w0THDSZPzfAA>z_R6@kNXk=MmD;o9Ey&u%T(D&&aIA z!e;+O$5JxC6rETgv4g#}m^NcO%lt|;=Y28p4<(N)4yWdQ3AusC{wjCXOuikP;jhzt z(EQfi))}~T)9+y`XYRLNV{_zF#`05Z&ishn8`{Ga>ml+nW&H&cDxn zB)5a-d|3D3!Q?ri*U289#J0RRw)tFC8{ zTXn7Fd)8EzvDOGq1}-!-OYwOoaebBQL&x_`u1DMT{fk|nc;_|ZM;^`$&avxTLz(J( z(p8`52UdLpk6HEonD2+$um(G@;BC#e6O&+y1B)`jddvlD%>oP7n};n}5Ac0|V10ah za%DgMiSds==~ZQl$?3b4Ilqp4kNEO>SZ8{sa_FadEuKmD4Ox<-Zi#O`kNiVg`}Vuy zA@!WKWBS0Zqg=AVI^J7B*>f(KYUeoGqVH9Y1KaubU-d0@{M`QbnNHtc$+u5aruypF z8oLGK*TlVj+%A*Mqp~BWKU&9`K`rnUyJgLdnoGn)mQP%vea`eew&6TijAHF!PXEO# zH<_~Ix8e`;{FGi0^gv08k+;I z?=&_Ci1F}OS6M?!z}yoJc&p)jQ}6ZczIk?X<)2*deBiqN)OEezzHV&E|}Z7cF$4m^^=K1ve$uWa*7?>V=8Aj?`!P2JUwWK7!Gm&8Yy}9IRz9(Ru)o0gQ$+i9DwN@hJaX zfff0p45D=3cbgv6<2NrrIoB)+D{-(q-M~g6r00jWc0&=(4VMzvt+(s3$lySBvBIp7&I3N74b$Yy{_wf&zW?_H(7SBE8aszuJ9H7<+I0~xIJyYi z&fx{=B1}JabP+Y9Z950PH|HRDia^)QHZeEUo>}mC`L=#UZIqlZ{X}O!^{PzU_a7e5 zoGb0V|2gfx{~v+lvFIr^@BW>7#G`I%{VI>z$TNpW{jL4pWv6*>v;AJOBI~R9-We;@nMZt$c&@~&cA zdKBLQ`QDE)JT2$<;q1{B4cG$ihgRr( zwFW!pr->Kd(A9YHeCnUU^_g;4C@%U>kr&n1=jp3_zTO&Q)xCHFbq@=~!?XX`+T3E* z-LP@VdzJrK*BX82oz~imtyumA#6MRXu%#}0gEp9P)bVFsO?=mcH!u8k@?H#p_BIYQ zJ|9S5Wn;DI{dp7mo?5S!Ut>DgjSElBuhGz~{2JM2evQS%A}98E_)PgV z8s#&JeQaab$6E2*n6xCtw=>lG*i&`HO;>&m<l(D0wJW0Oz+{AHHEMb9M}K_ZsH#)uAu%y$YWga#Yo%n6}jh{76w>%NAHR zusWyR&zNocEV(iuJJS_Cf(_HjQ_8bdM^COCX7VWp@6Bvm(_eD`{Wx^Sj*lnyJLkJ_ndgNJ2>b8 zE_#BKUf`xT>p3%YqQ)E4naB~=ug*lo6C~$$jYpSr9^J<7x3hN*py=Byx4J?oEOG0&JcMXzG&G5Jr56AZ^neL z#qLXMa347ebgtn;PrV>DV4iI>PV8Sw9MRI4V#3xK!L`)c@G1E9-e%MB+vDOhTR7)w z<~gY@_#4)s zEVpRU&_H4&ZPGm3F!$t2&Z~A67Ze25W{o4hVsZAmMCkeNhkOH!veYMyxc?$gXbbTM zm7f9}C6u269Gx*g#e(mHD{@mfxKe%!EKAFxHAY!1Gi6JJHer_=?5TEvlS<90JnUy^ zm-2g*99nAPxQV_g*T-Ar^JuK;z;(Eye>=WE+3pEW690J(dPD7R6&-Ooz2h0JsM6QeCY>~V|vrJd8E+g(s->2}XUMkvO{PB_%Lkj{j34x~M7-yCDo(-Q)r zH_^$A{&{JzhIOqqrStl-Y2-Uc&+Vz^JObP$vD-7y*^FfTnixOdnyTyWXHa#c594HgXMfD!M&TrrgTg&_ivmz_!Z!^AQab&n?ByYRlFKjTML3 z=aeT#{ZyWq9sh$oF$3_EC;>O?(w{KDYX(1qXItNvfTy~D>};J0uGU?AuytIl2mWPg zEdxB`ju*^0Gu~PhpYJLgZ}g)Sdl$oBJ>kN>R~@}@FQP;niKPMIb z#aZ*s6H~1Hh;f+mk5kuuU-jV(>mJ`gY=rDR?FR75_uA96?r)Nec$#(JMeEg;!TvAn zz72YIwsk+I;_U0*Q(>)p>End^Z#uXqmy+h1l`k;AL~~3!&P5k-j&1IF>*t(~wpg~9 z#3}-RkFl53qf3{}xkK%=`wOhB&gVzX>}6v)L(=(?Xt(w^$$hW!otsv@%Kcd6pyK<_ zCl1Fop)t%+^yg&*(ET<-=Zbd+;u_CL=E4!N11aR9uxMUycoWtVxhMi#w+%4FT>9B9n-);W;!sQAE<*5y<)#}IoH_rlfU?wNIYzRWtw zk;j>@>gPw~7*Z^gTMCU}*;?f_%?``Pt)ARMMTJ&wp@OT7NmIxzRL!|UQ5rgJc=~Vf z?YGEX`6{_sIP)O)&SQHPU2SX*b;>CuK2AA>`olZ-2iLXa6lxe_Y*wD1YH|ww=l#m* z)2}_JP`~utI@K`+TPM|n>|o~<%G#N~rpxE(^f)6|{-Azg>F{)YnCsN^{&kg{W1L4> z8honq+@yZ~*i+&!XM0k2u4b<*;@c9g#s4uNN77$PR><~c z*U9Em`EGK_)uPzu12~)8LGG9$V(fI}CF*lZUZQ8=!*%|2xCbb*A3>Eo2S^Ao*;OrZQkde5Dos0p6k%qPS+Y*=t= zexl7OX?1E3JXy;EA$MZWtsVfBCPusX!-&0sW}m2oYRo8 z-1&vlE9_i6@B{ArLbYefFGM^V>c;7wKFxkI?ZU zYInbI8top#Tod0uF4LVyC^P(NZeXjKM~Ha+>-f%UdnRq~8y?Jj>}dPwJr~(+zsGEQ zM;@U{r|t0BjAO8x92!gbpN2hXvAgYN9--`xJVG`7%{)SCgU$}HP42y~#z04;vz?r9 zTb{9EzPXT&YYaa{R8GR@=SBBSjUn6#%Ag2|EGKYQwOni z+A})T#vU8Z936+3ogap0#}76ULoS+W>J4v?Uk!YG2E*?GTk^xWgYe;BgC|&O$q$S0 zqbYuS!yL&FYv4nw;q^lF2VH(A3hiqt#z5PyW zXo>O%;y-{6;|-moZ5b34oxhQIkJ#Z}u}@{c?H80h^9(d!ZPplUy;4(D_Q6#)pAL{_rQqkypxu#rP}#)HuO<-Y83g3zG+2p7OBZ ziDwY3GGK|%cFTV&finD}u7-8x^l2XNIlNhP7&>k*a_iiy<5xf%C0`b0 z8u8*iMyQ@OE&gi;?>plnxiM+Wjnf6^hKcAjCZOB+COVEA(RJK_zUTT-tnj*f(1En; zd_;G{SysE&XugwAK=bsk#7Qt?Hgl~#=S#&+K%QF@yvRInfAbvacyge1`6X?9KNg&9 z?7}z!Z$1B$Z$jpQb}Z+a@S!y%TQcD^pFIV?{TGxUfH4XR*IipJos#xB$psO+zJg^| zeWN|9FU!;^eFV&lsZVu{q#n_%C#Z87zoqxKSH`FI$`KwPMU`lW0)bR(q4o{s` z$H0>Z+w1rp-)B*WVBKlM!r%G@V~Y=+1$_bDZyvSvVBD*1FWc}I)LQVK{h|Y&a7>@g z*je|@!lnS&)A`-T?^b?VC+KX$(KK`t=t^31POj9mTli`2=^686c$;BdeiLPyhcVt^ zuOB{vdp%bh7EzDR*K|KBo%0a*H_^IpP_DiVwfiERC-+)ox?sND|D#rWt9VDcxKYIR zS_7Y??=PcFJg{J#=Yp{x{{J|75Y3GR4_a{cw^?xR;XSoOa=z2PX_W2Y*Uc_-Kf8tU zH~HCXZFqm)d3=&3v*~-M|0R@5Zxgcnf1wNhSiaYpT{=J6_N4MN0l++ME-XovW?|Q#wYyr+c5y9cYK@amLSF%Z%Sb;Hs`Dddwg4 zTexBv#)%Ajonx7 zhi4KOUweV(XF27|>Hk&SJM9t9^z7?A6W&zk5$e9&zSbQ66EQ+cxmVqT`PX>sy^gt( z8!q8{={oj&N9W^N;U~~lsg38WoV8iU{UE+`aHF;zVeRyxOgQStd*F7s*0^Bn+uu;H z>>H$aZbHYTa?TVJwcrH3Bf1IX25g!1ZYtj&MmAI3niua+G|ybZ4)2x1^C)~e^=?v( zz?0dui!lyx|Ans6BmB~Ad%tk#%M-*oIeXkb(X0r%XvGvhe403~*Wc!j^O_xAMV@!z z%hBcKk7IA{6xTrevODhTmGoa_TH_aRtvVf_ZjZgjr%krj_?z!*jc11+u)k4V`c`F? zlzNy&F1rBUnPrJ?$^jyB8T|EIreP`-rAJI#;yn08{nC>xc ziQl1IdcB8{KR&$2qU8MDiSDEl|E^rl!ld{69q^<0o_TVMZ|p?WygIg2JfT(k8z*&K48sR&5uUL8U^U2 z2J}3&nfM)G@B4(>&b*nL!n#bcbWwd+i?a1q9FQ55k0OVv+O6}r1;}ZB=D`eXeCy9( z<2!~r*4Z|`+RF#xCnr3pU&4di$8X9{DMor_o+#4QlN{dnRceYJIuapnv`&@hIzT z5p$%3b(re0=H?9Ms-J6(i)?vI=YRbaTiz10p3b(s)|xC~O^*Fl-!t0sx?`&zzxx~P zOBL|P#Dw!&=b_g!mpE^>V|Vp!kq&M1q2y-G9mhsiyq4s1*~o6E@0xcypZ+O()PFsE zYD_%#q!r@ThkWtXy<+wAwAKJnG}zGc7XhOhWH_+Apj&l@^c zXe5qK?!unkHFRRT9mj7vdrXpe+WH@CZ0-9}LtWWK@K2EKAJFLD-hXez$R= zF00Ri_W)xUNijxe9x-&^sBeiv%P-~R+{lpLr&z6>q&1<=tL#${81R|Kp| zV5!}*6aTA8kFmF>-zOe@v*FLQ!?`{a%(*tq24K2j?d$}Lm~Ne5oyyCknzY@6?!1Gp zU!GkJP4|SepzU|15;L8(HjOp*zW62PvBP)F=UD*04LxoN{k%VtyP9JS@iqA+U&YI* z^;+>$Q?SA5sCOW-Q@zxgf~`-4x(v=Xmtnuq8I~oV4hnWbwm11CSDfR|ds?#8U-)-; zr1gKXWT1i`Hh)xS@kbZ+`f8lxeSGKeSvy@YG`F84j;Ca)f^-Yc!bKLGe!$T;Za%9! zWe@U`T+{hkH_Gqjr@7XPxq8tzPao&_Ofimsb8`oNF2Vl$O!#>nnYS~3LN>KT{n1cy0VtTX5d9zj5Q|-zgh%2K+Sg zY>g(8So>! zmov?wVsKP#ud!+1Nb9ybC2*qiTr%g6D>imt>UH|(<=VlK`nMOE$y^_8cK`0P`ZvM; z#@)ZGDci_TeYlZ6%%TtSsn&iMP~6C-^Mg+8ykcTQj`Dc!-v^!Y)CTSu;0v4>@P6cR zW5Au~#U@*O4)z-*WG|k)W#)zdP!x9(HB;_bH4vcr|-L&csMooqH=l^{UK=O^yvRwYt#LIY4!c#^RMLe*iY_` z=>0!`&-aHHTPyqjf%jZFJ<>g1UPTe^$<^L-RuRoZh3n_-j>;(+v8I`e;M(%=iK-<&(BB9 zUT{0#jR;jeHZt_~f^*~d5KHPEVo4qHb`MwafA7*e;?FNVFMeN_Kw_6CKYo9&z}DRh z^0(~5Cv6w+{)6%!$RPPCJ({=aT+-9CWi9{j`gc9^kF7md{TV(+c|$l$uB%No5{oZ1 zLXGre8|!BCKO$Z;Xo1pP*lHCKo`z1@)&nbYHS_luH+>XuI zT6FKrQ?@h@HMT1DYZ88|e!H>zz*-~t34B*Gc|xLVZQXr-An_w;iE^8UYHp9aZOxJE zHp_0W7QR$*4U;{Lvc}}Uh`+@q&3L%6CO;klCb3?FznpIDejm7kqcvCWy(4~~XjILc zBa#!1`BCZ-A6xJJ1#!pDi#vSm-DjwqwX&&*dh5OaIYPEWA>dKARW?IY7gmp$fluSK zuAU9VZQFYIhU>u7wcu+!cpC@)#v%`m!9LV$^23S|;R9E)iByaT^-1wA8~2h42v2q7h?L!@*&l2^N6^+Ne0D7|wO|Rxar$L`$M?r62RFeH zv^x)bHt7hpe~XUGzx$SMe8(RC^BE^s-h_@tbRru)NByV&LeBI2QZp_Kwq%pxbKUXS zeu`eBcC;0ny$PA4uc^=I8(s_?om&?XoBb!~G&DD5t1MlUV(#8tV+3cjAK_RQ%%62d zsdON+jeQY)*kXM3>wx=P>J{Ja>}gZ6uaphdp6eBB6x$d2BYV1N6rL*4ZFn@rnm5(N zV~<0h8n}+9AZ+s?j2D8?hHCD|1ap3%7 zGyi->Gro@ahG#6!1~z>8X8mg{#Iqg-&M@Xz?X!Wh<;X4?U-jqrJQFVD&o3Ef8~1JW zr;2k{=`ZdffBm`*{#EJN1x=A%5M!D|)(f!jZ|2RDugnwWO_5zp z4?SZ|>-(s3&CwR=$aF7%1C5ipXQ;3AZ4uu|m*KJBsb|hNa8|9lQ_;t29Sl|*THbj*?;-MOgJ1_VOI(2N<-iyhDlKlH-qN!uw~zZ`6qnp||^Eo5fViYdgHjWXZU zp*Lz<9q%73UH0BAzFBf$OY23;wztmU+k>T%*1@h^K%>Y7H1=z?#5nM^_^^R2!rxi3 z?L}*Z$KO{XLu0eJ82i2$V_v;*+X(DZRxLq4@xL>r)6TIY?l zNpobQ|84Y4>8r-$Cq9ZfG7I}u+0myGk9KuRT8n7jLFTuQZ!Sscx%l1rm&6-+ZwWMS zX-axsBQ_zTdAjcDNw3=o&Fj7}Z_7q#UOhCgJNZG3l%J2-2+eDR<~2g|x-UF8{ycQ7 z2l+rg_4W)mLi1jP=6w#$dx`e;PRWngL-UM<`CHzD=Jh6j$R(_oZ$k5?r1UarUVch% zljikGeean|-t2ACya%9pKH4yYeWkKQG|!4X<ec9$L_bcKZ|qg{>`BE@V}3`8530O!+EWzgQ9dhCXp$2{?Z568j~94p zCAlqXQ)CxsgcaLSd#`LUJH!8dSC6?bH_f%=Cij`nzo&P|QZI1rmZg?}L&;Ka)LOFC zz^;}om9)Qc%TjHW-I}4jD=U2B$cdGGuG5@5OI+;j8K=a>ZlMnc`5hR9ZTCY4GLo+) zbpSMM>B12Pv9XQnni2c35lbCoY^~1t;RvG-@!+s=Prc9BT7MfcvunBp!xi4$#cQN@ zgvQ;9{SiKN#fnEg+>FujQVg4K4M`HP6@@j*)gs;J2Ycl5B+aqTu*kzxGwA# zOoO)-4Oe{7eRa2mVs+?CtMWq01E#&E8Q(hMP1}%s;vD=Hh;O~lifk{{ytWZK#pB2p=!`zg0qu zfy96Ej=nke(XAom*ExN$r;H8{Brfx=G-F!FG8NPMY4mcL;a^@0d~nc@z368pP$M5kAABJ$LHZU|Iv75y0NJb*QNYl%Xf(%Tk(R~ zBZ+IB*D?)XuRibuERIb+^X$#aGvu!bl%>M&718EVwB3r=YQ?oqSjik;or;#!NR>4cEXoJgSMd3^6G_ z<}0!|S|?0hk>h55Ke?A8P!I6C1pfw_HcuruFdJ>Dk2d zVLdK2d8dr#0_fp7Vhf3mn6W@;(=2kPyaF6zByW~o0&$DYwRjIa)w&Jot4iRzW8=|L z!7usXry6Sd#`S&+$^3Oq@D z&5g9XXT1Jsa?|fAhhNVX&3=RHqpX?9oHaEeCwv5*)_%1Op71w3YqI5pZSW_ra4$K* zz<1+<@8Xxi91$O&JyZ6%ng_@D594<)rud*EwXChkGU!c@A0j_zV#5mG0G(-^n_0?!*dFIrZR<-SlX-$)c)P|i9fj%J=QNqb)b|BCOYvVto7U(nsjUtm|NC7WpO zl*=w{#O1+rSZkND_SR6Q^*7LzAFOx}VwZ^P9nRVJVS@eZszgs?Ib6JyG!yRi9 zSrlHzS(8<~`~Rmk`6Kp-{}*fW5ImTBO~$x)ugU-7UhA&&n%qmdvnKz-^_kY>2Rw7H z$=%#*P5Ph(PE5(h<(YPTe%4Qg&x|J-`SEQbe=mQ$2|D3Fa(S?c`5an%N$6ST^x6a7 z-DSwaTD$V4b<={az~6fwzNf?x-rEnq^#6blM&2BE(GwG5_`;^zzOa?V^OrB|nm>_y z0N7jc3Dr6a+=bkFzzD{tq=t^)zsyPg}09`KdPr%U^Q{K;kzciOMG)2xL9@Q=G9@IwdeI1z)&6N_nk zv|?;oY#4DKh7xyjZih}=x*zF)CSr3X+$jdN_-@6auJ1NCq&U>k8tMaoib1`98T_fa zH{KtJH-C)olGvBZZ=$-A#K835Z^WatSusC3Ur(%nSE+Wzadd1_kZVj|_hIB45goxk zJCV%iH;C_OOVbzKhRgRvJ};7ACAWuC-+yM<2U)9P?DJR7pBsM-nk9dE$x7ph$*&l7 z9%P-F=v-va5+E*uX=eqGHM5&lHUN1}ape|~uSEV#)A=9oe;=EdtW}?hKBQJp_{ClL zn-pTN1x`gD{Dvo3Fh1~l_WPF2QU3Xy`Lq9P?>DL!@MF)%2Fc&wNNj?BEp)}E{~>lr z=qx^8OZ#hS>*~|Q9$efhCVl7FgX$k~0h^(XleCAwKFiwYH5OIiW(RzM{LL!gG|aez z_t5?*ZI6H_^h~Di>nMA>baum#frLND4hguXj2pdDa}%A@S>g?jp`KavLGcDg={iNAdsDIBLAxV-3>YgS5|yGbnqc)5RJ52k*JqS;_oi@k(zX(Zt;K!INp8uTJS4hu>Nke&%n{8f#q?W%%myfT3~mp@S|e z1m5;Q*^!UaWutd_)SDOn|EPQO_$aGn|NrSUf$k&-2?>FKCV^3t1{d~3(R31*04f8- z{b~Zt(n)ZM!bosQAkG*Fs8Jk7m@xrnNw=cT2oB70!*cJPAa023I1T}3#!iAFdp8LE zeSe;(8#)1W?(g^gur zA0);&SZ&ANSIb%Jq43Iw-NC`rjRuDeo>y-Kr3cnvFX;pSs3UGj@MVu61~&M}W~1TZ zLgXg(-I+%5Lo?mpui1MoeaamW4>-uVH3#+0JcHnob+S%*B9{&^8kX{3`=IBr{iWMe zI%7sXw|qDFkquOK^1d;)rKQ+%GERoZ9%7B^uERpst>VF|$-z;>nx9SGMxHMi`LpGl zfi>Nf0*yf&QDee4EvGgT9LnG`?o?e4N6=iO@Q= zr*){j93Eg-0J|&-c5)c@squwjzY&JrmJkTTPVQX5zQf>t^;t759+3u*PcOsEM)(X&DhGo^FsU> zHh$MYJ5z{psk6y*(^Y5oW5Bl`d}}Xqj5U(J#2!ff;A$^2Dya2YXD7E6Yh{Sl7CB_n@V&4{Vy|`# z-0wtB{dnYa%X7e0aX;BIt$ETuyC4c*`^|OJzjIF*UoF@+Yxy0Gudz}1(%Ka4-Ni|btJ40(_Pn=JmkC4w^xVX*4MVjv@|4W}N46H@p zfAD0Uc?aR~PvsAs=pBQt>)2#>@B?T=aj@O<+}6QIz3{)$wn66o(ud$-)vP1Qh_d(( zmXH1-WrdSAv#VwYysS?jWyOOl$iG^RjF(O@jJY{a#OEj+!GDpv5>rO9sPotDit-8Q&$<;Cm~3OGZ7PpbPFicEN71-e7obzSqZ6I^!28H!EBpD^ED z?(32)8V7HQoS`@lPyd?y1rHm#V@$sX`3&s1>*486%H|H0uWX=i<(;8r%JCq7lh$hB zH`te$r-R54!>D;?I(kwZew#M(6^KSfGvrT#zv#SBKi>=G&WsT+T>0p0W}>sQ-)z6L zpLZQJ))LC)Ts!ypO-}M2UTp-w9vYiF+oUga0*C19j=*8&N;LKv|D)+@5Oj6?#WU$D z2iZ3e+Ol}kKp#1zf=$<1w55G~+CXTFeTaMl=c27-?lf19u0zPXP}m>f#~+aV8MGB2 zp)J-t@f=6dT~nd2ua6rWJ|eHb=*ka`iI$Fn%W*vOioD( zbIKj1?_VFse;i*k^@~zV_cMrF@w4x3A%5ny)mM2xATF=%zK!^7Oqw#!==1{z(dTnY z=_|1xr_SdLxdojxNpbIBet{VeXwq_6wTF?)zwm#)_QW2(4?)bh4hr&m_x5 zbJfsMJ2Fmt>8x<>mgS7s&-)taM7oXWd?<9Ty|l(TY9RU|@6OmygLfx1*AAa5J;&Le zX7*T-{j_put;!;%5ttgQa3vf?%jG?8qd0m^L~JQpJa>G9Ts{Wu0CN+BmXF`Z+>;04 zdyMM{<1%R^RdVF~oY%Qa@LV*~h;O+Wyy>3r=rdf6_?H)4!*l%0kv+tXVH$Zqe1>a5 zPsJw<@{NQ>G`>$RMLt3sqKlm~4DUwK#u(1Fh&FcQdnE%TM>8wke^v}nhaEr1g2zo8 zi{?8*GtKn5JFWZ^d&|E|EB`K?Opm4$o!}e&Mmo_s-R`!RdT4tuef&1t%afFg zw!P^8|4rMA;B~jX9Agbf_<`h?^bP5O(lw+9O79SlkLVnAz;L2(a8~$?yB(DOZUXb* zgcoT&7xC??8sFtS*hG`}bUzPf=@%~aiwVCXF2~RK7+n%@);-eqdYm{QR&dnf3t_vZ|Po}`7NJs+e7dk-H|ZP z9UOw6-GNS-iI3fp=nmH6>zvt|)X)PPvGj!2bImWj>i-Y(E19qPmAu#dO7?4hBXYk3 z-e06SMAz?re~04lIvHnKc#bvK9_Dx$I=|MR6a6lm{a|E{=L5eJc)G(wdWL@IasGBD z&m(hPPQB>4R@{hk)MRCb=RA|xnicNgZ1lmM?0Y14J~ZQt`ui^A?1G+I`W|w<(FiW- zNxlWjO4pOl_at`QHuOXfG|^q(8$$eCopMFvr_aLv;?W)0W#k6qtiVgsNyzW4Sd32S zB4T&YT~)fXs-3%k{M-X1pT$4yj)wX2@h9|aD8MJK_<+x|zcD`G=}3G)2E2Hs{EWm0 z;OBo=_f@T)dS-mUt&B_k5v{6Ed+Ad=bQh4)>xmm#6Nz`lh?vwvj}B%MMtK|61dlExr@JcO{N@ zk(}1OBIS;sSIT{Ebo*+W~3a?RIVsi zF}_m*zogv7yi=TSH#p`UBHGhwf4`h^OVPI#cdBw$4v2ofT>2`zplq#wJqwH!@>_Vr zFct#iIpY6*#eWAM!Dw1--5s)#JWjbh`#B%Q7)7^{K^s2{Ka)RH_3DzW*n-)>gt>I- zyCeK=3C{=e8N|nI%Wm5)xUbWei)ZzGWH*ug>NfVV8uMMi*4UH_tEO8Szj+5sap0HX z=Yp?t(QvGLT8aa!qRO-pk5)qaFYt_gr&-=l?3wD5uV}3D`Tw+A`E<&wk2XFkS31ymoJ1lA6<(5p@IKx=%ts1`^|F`zGsG&e?_#R^U@ddUUYn6xE!*_!VmPS{{QY) z-K$~MReL+*I7bSvkM^nd57)hga$09|$rUXdoz~Y3ertX0s&zEz4BFM?MLo4{uC{2s z;7=WWe@nT|QSFGf)Sk+!AFFsD$J{HAy8i23bib|&*Oi}H@BBT%AHL?%VK|Zps`nV< ziKZ#7`v&slNY+N+G8b!QJ8tWN4S<-YX7W#mj2IG|FN)sE${4h#MPD9#Gx=U?YxQbLRxl;{BSl_MPMt zz;_{8ro7j6y8D4TyDmeQpkB0$cuw%{WdDskiNsEtavK@mY{~F8a9D<)={2u06m}xjVqE z?7kuHOF1<8T4K7d!ADTYnV|yC4CQlX=zp3O$KAIev@8zVi10UunfIqSFrI#CU5Hji zQv4*nmD$M<@% z-K+8X`?$?}8w4lgQtbD&%7>Qfi$%|DqP-u|jze)aTUuU#lhEKODu4Z+Q+?Dl}q_%eg*3`6xACitSNcPw4s{xr*xvRrm3lZ4D)k zn>jP@n6EX=yX7S-_wei=TkH*we?dD#!|gof4*rOC{1;C(V+QeupY=}pi5awszhAa9 z8+PcG^m!E@`4XCe*YrfCSAN)9#+<>r$w1GxDTatP=U~4+R{vdZ=rwz88}09T&EBw! zHMI3#;F<9?>l}mqUE(6A1loqyT;-o+1cySmXS^H7y9bTnZM=JJ-~HZdooS%I9_&s! zFXgw#Oq8UvihLgTkF#5&bs zryXRDcaU!u8^$*|Jickze&MOd?sNyQ(D+I;zO=K9FYS!+?Vz4DzBJ!4&QiQ1-dtE{ zjqgEsaGT&h%UMjpT_#;QjhyXirjMs9?#_h$rwDB7A6sSw*YjUAX0CB)Z!Q0|)|;3k z?bBZ6zhs!{e?z}lym?bwXswUucJ!!6G?&oNulcY1@fNSRB_Lg^srI(O(SEdpZ6E^g z=Uw2zuWD0GUE-%I&t2+~a?eDUlb?ln^S14wwTpSa1o@{ksK@Wnp5#9Q?Z`3WlAoT) z{p+2qHN_)mEz#ZVcdbVT661Y$p!8a7ro<-45rft-)a_MF+63&smHtZwhREHG9c-GY{o9h+l6G!(Pd6Q*RB! z&ivAXT`*m+!}&j{FTaRjJsj@mCh1e$yD3<&bb;01_f{CzrcMji?z>O-^S`M7&%BVC zGg2{{ZP=jZAp_n4zGR}F)v-_1njFO)H9nq;KI5PRJ$sgSzv7w7nd?@(7?@2_^`S{K zZ>RQ1s(ajKfQNrPwc@ zj4G4W*OHx&@k}~=q@TA&{nkCM8R)l{hM(zw6R{qeKi#3MI*fsJ=J35q-`n6hqd5O1 zp3tmV0(ioODvR6*bg=gCTwS>oeV+1}pDq*}6R0n<>4S%iR*V-Be2|hfv8QiHq zZP?kc9jwb1On9tM<#=Ao8NuK18@!k?ID(Z%-^G(w^8Ea8o7yw$o%YX>exlQx`%{fm z?<5yb=-d->xk&f?A(x2>G2abWJ)VdAI_@=M^?LG5WuBlN_A6txCbAjVL3rD=Q@qi- z&qDt1L#O15auHg&52Ek0m;)S>?^6FDys?u1(Y)~<{zvo1GX8hxjc(>?CeI^$u~c=? z%bKu{i9b4eAm^bIXv^fUw{?MWnjcOz>z(F@H$|5V^Fy^&#B)DuCc?jxK9+9I8O6^} zEQ{9t)OOL=oY$_sC2*x+(+7iir9JTQSk_1Roem;&d%*Lm@ z797kE+k@ju;BWN#L44Ia_>S0#d+^*%4mVG?{i3;-j>^gT+>Dc{b!HjvnQ&Sa zQgzxCSJOdo6h?Z>z7^LB=#zF@}$W$7nb;VK{ZlPs6z- z2YBfDMc4c^k$38w-k;ptH9yUL!05g{R5tnYaLzy%K2Mir_x>L3&t^Pk&Oqo{xdcnQ zo#N0U35x8mjn;k+RWN&=VChvo(Uk@Grd z(Ea3=Xj*VrAY1){e{?@XE?zLZr`GuCv)~sn=6^Q_?GbWXWf|_=qu2@}Hj^>rp&fwD zMC(cM9)G*)+<9mR85dnpO|IBx_6=G1BqKR6uVj4Rl!w+soXcQzw()$cp5Jc8!2I0q z4*neZTnC?3E?UVF!LI{;JMT`%zgW31yXT`_ROrrK*oV0d@7tZ&eDZ7qI`fHtsYgFv z*exIJ05czLN|*STU1y16&kgSXn#&p=c^m72yt5%< zc>VC25HTr|p>M2mR~bEOuG$piUgPL%1b6a&=VLan4ZXNc`D$59I=`_oZsS!u$tSUC z!ItqmAG3QM!;N6;MdWsQtcO?eVMfj4;~hD~_M!XQILkMkoU7UFvEsfWU(QS;H~qVY zH-p%f4e+u5xA|xL&tJ5>wI_L9!TT+=C;7jVc$FIdOZMl%=cO}O!B-UT>?JOsRp&m) zKf93_gnhSapV&43>|FE(#j5-WdM$%)BXKIgHRYO<`Bnbejpv9_!FE!-jX222nU8PE zKU;W?{Ihl65_fPH<18WeY$oHJ(qP)zc@(C->@h+Jwjg7-3>=$Hfj z|9=*9V72`+ZNIgy|F`6y?f<{ZKP#MPk$;x8YQ~-tpNwtPia(75_bIGF={M}}PUWBV zB2(mxcCkkD?A_xHtTh;&f3~P9JAkdjj5F{cYrie`>>A|mPGV|5B&Jq$G=%m3VYl3~ z9poU3q%}#%gl)Eel0Bj{gVHyj0PL=`X1nUBs+n%u3KKU-_m|WHxNuyPOiMn zl%Zof&mu#47m=Ztbas`Y%IOv=)IGjEv03*bADDx@}RM>n7#qOQ= z=qd7v!Hc+qa&E`7wt#$uduEdJ^?mjlGp+Hrp&!rD_<6pX_Yu4M`u4DS}1|!STmptGO-rdDUU5ad}zUa*7vyn%K zl-CzJt>(;)@aUvH&k*J>#u(R~{)H!-@XWfIqjj^&S~r@j8uYVcC$Qf@`;k0ZNBDn` zbyNzUh=%pm3DJ319ZF+2IP>_~WOP?_wI=!^z3QL9P`hi1X%L)hc#ZnGljn2bb0460 z{RloG9Y$wI=EKkXgHQb~-XA@GuH3B4&G^O4ugAL@a;tF(Jz~LIK3ZG zxhJ~m?7uoo8RfVX9%{PHvnPhTKA@jy{!)s568ZlOu)aN)pxvi4s3qSu_BVmQk|JZj z&a!0TbJCrn9i1;9a4mWJK-?Fd+%px|*~}fI4(^^JPi9pSzJj_-zc@h5_c1?y5I3>k zHPo$Et~U0kzh_29B}n@Z*W}t)`6l+_nL6( zE?qL!|JIrZ1Zxwz-Phb5S_d8c$IZJAMBvuJgB4?+l|rmxtfRianeVH=uk~gtH;}{V zU(bHQ>!A-?kGfl@X{N=GzK7p!?dOkiR)1h;4R>adBe9{qkQ~(by2kQ3a-ZSV+O~3L z4D56h>q(Ah?Apn`N!Z|ut#;g2_t>hG}v?e@eh}u`!0$1Dm=yUK zH4eq;dEh}U=vAA+^LpZ+|9~#KZidk?2S1;`FwBSHv;9~vW^PCBf@vFOt*=zpS8sED zrTTuan4zKY^`SD*#qU&w-p~Q=%ek}F8#8d5{EJsU8n>bh8-E_S zcaZbbVH;@Xb#w4Mj=XFo_;e=BU&y_N#_xQ-Hglf+z$jww#*?S5k#n0K@}AZ88eDHM zXaB)`Ik5k>Fc%)XW5s~G3~!o~y&hvzE|KHtEHAR2CrmfCH!b-4_?KoF+m*Mbkvl6U zac<2$|Aq0~EAHFHSt{0BvV1oma94*p-au$wE8`K2c3{QPP6~dfMRvw;tKlt&Hmbm} z{PnHW5uF7YyXfp7b99993!lx0dyRV;IBStfk$8kZQU2R zRb4&1l4q;=NWM(J!jkdlh2KlhSGi~!S;RO@8j)NAcRvyCp!LhJA4&$h!Owh^0fz>3 zD*j{sjx~Z0n`M)I!}gq57AlNIC+UOlye~fVM11K<@X~(hC&}d4w>OwPGjmLXJ%hbW zf}t~w_}IvK(%YuIpSFe<~i#+r$5ix+mnSmT0@Of z8)F<5jur4H_AV`9DWUqK~)b0;;Em(e)ThA2(nm@4)$|d_<{T5YyLTF zCSjL-Mc5%{u>SO}?n!qbi}no8CRT#Wel{BOjpJ^8Gbtmlt+SWa^Dx-a4ypdM_ZFkScQARNv+01PochAlMrp6=~r|zD8 zDm}20d2l2QsP}`12;X@DJ@eS-1zw#!JPu81%wDZYcwjcT-^yH}H>I|s133AwvsS{L zY|G+dPIYEp3SG6u});{dC-WPeWun9xj8EQ%uhD!BAay~KIw-h1Ngf{ z^SVFRqWP3lG_Q9K&LBryqM4M{9g1v!Q**F0ppzjKCtoa|2SsR@(*JcE^lR=@Z7a!S`*~Z$_7?|Hdxzh zRZqBZ(AOi_0E@syAdCyvM@1oR5Svl48@{CXt?&Rxm`Co?eCy#STKA%rPS(<_CHaAuz?J4>3HW{z{I-Cbw?-^pK9SE$%*hSlL}waH zX+v{T&3gyGCj#RQY|M@JL7j1_7JvE~wBe27Pd}pXJCJSIN=^P$Hr-gawcGvKJHz*9 zr@{CC3QmjQQ$?l5IyZdkJm%pvpXyg%4UQB`q;{I%CuKv8?H#O_?tDsREI!r$-{4dI zyYQ(Y;#1~&Jk6)tpS1YYpoFyg2#=a$>LsbZeaw}{+?_u)GN;X_<~pTQ^P#zZp6B9E z2?_n`#h=8N#Gmdd?8=|e6Rmrt6VJR?dRdq^*|76|3cTQ+0+S~lgI6Ah?(>it8_6^5 z;QvAB)z2C!VjX1jxdPm!qkERHcgbQ6YCUBV8@7q{G1lP@en?rZt8|;qj6czxdRaUZ ze-#g4-LGq9ymfp__8&%Q+89%YT{PV{Vejt82|LeBd6 zKZ*Xmh};%jlLwMlBA$MgLw9~?RCgy7fWvtDVZNsiTAx|0&wLyGq`vy-p$}P%GoRlE zeE4-YdlYb?wTT}-_z?COoh|Xu=Vr>9dI4oMHm$ok%v-aG1Fg{%bKX9JH!B9v%Aqu< za}#Ih<)1!6*$-I)5`T^@f&hN zkT*nnRQl8~55*^-xozho9;!Ls##pl0^TpZRxoThgmSN$!E(^~!d#qD)t@o3n<~s8% zbDbHU>npp>_1V_u2lV%BYx5nROOH17`1$sR*U&M&wYKdmYwucr2$`?A)8^_cyaz9i zB^SDVjbiUw?CF8fIP`)-bVY2XH3de)6L%O(&2{&i>%HYJ_XblYLvP~k-2dPjW^-&q z&bi7@6g=JD8^&!+X+u@ts;yd)a0^0wA?|b)GKXVy;{!R9!eX)D)=gx=&^Q*o4@{NY6 zLpbxC;odNHtdVGpHWEt;jLNACo=!`58ZM{ z&72F8R7d;T#*_BS_@OmZ`?G(=N49MtefTJ*K27wTN4P&#zB&P%oSMI>VIB z?*X>d_z5=Wq%pPu@gC?CAD2rptb$oIsb=aC`%lwS+icm%Sw@xiO%B7TO8MBx_DpqG z!4sz7r>ZIiw<~Ln?L%)dmaflx%$sfRU+=dK*p|L2Z@+Xc(FJRJO@__JCx(xmPY*t^ ze0uWfwWb64pKkBd>CRyMtgXH16-&fpf$_4H{0O5$-OK;*Gk&C(w?$y9{Yx(@V=q!LStQ7)V`sey-Bs*+393| zG8no1H~2uEZ_p=|;drR+6 z>5RzJfeC}_u`y$tNb#)<$R1$HQ+Q2kyfNqu+1(0_aVN<(tr-u$<0uoo$Jhezv1Dsn z7ukAAH`$u?4YKv4n67$%EB4m5Wb8D^j{taAe*X#W`PsMHob^YEF;52nN0BiBlupe5Bg7sjvezCrfrQ$+2(+LMaOBjwD>GwrsLzyMrO-* z08J+Tao*g(fL=!8sQfGHkKK{8-h=TMdiwK>dY+L+u4q{2 za4K&$maZKp`(IpV4SE9O*mfK}jeU%(Vyw|H2)=M^l(C@$8VbB(_sW*?G4m%HS_%(i z@1Cf-8OS+kEB9gk%fIEBFh1vJ$W76igK=KT81td2Pk=uPnu_Rp6Oz!!yU`SPhMF|h z2b$`G4Dg?TmWY8nif-BlKYHf7CztJm1|m9N8ak5f-A9ofx7pc?u#ea}Burb=ZTq*d zj^d1gU1(spNpHkEQs+#1>vM|UVxhOrVb^#?b4MsEf85#hvbV6YNADZCSK*v`*{xx{ zEFU`jC-CyRtz+p6$`w`0IJ8%2hwg*So0I1ito3a8vi3{yRTb+y=T)p92E6iEV}rq% zh9Td|rE}w-z)!UyuBv>!d=RQ1Swrt~PlfK-fWNGLi{Cnbq2F)lH|^>7U--T5ork@; zyJsc%lZ|8@bFTkt=XLnbPuUY}#1_48nBr`>YneLo8?LJ*#tgk-oqcei6j(2DrdrRQ zYH`-`60`mxKeSigB=a6w~!Onj^Aj?^+5-G z6*(T<#Q)8FbD!1NlEEQd;oMh-D%;j2ho|1jn zQATj|PIj~`%KEWuY0ebiTthiO^1=~5Lo6ET{OrWCo{aCr!!2eko}ao4V~kg`v3DBm z8?>izhUYs{@5IBKOdnHVwCZ*B2QfFVI>L3UvF*d(y3k6rKPm0#iPX=5k%6DVSU;p; zK7IuGm_z7hCmxRR9vx(G*J%&zu(9U-)Y<4T+FR#wx7jYvE@aWa=5*o!@Gq6|9nb$^ ze9sz_pM7t(yDEvOLBZy%AmdEBO7TkGh}H{a9}Hg?-BI&q-u2 z`;|S>_f*+^Ig^Q}`qG~0dgb=})>qp4)L+)$UGUP@uxbB(X*SD2t`{>7)cBiXW@6jPHMfPhS5&4aMKl!qxjaBcW%e-UjGf6bM z&z|J^%5J!JqDQYnRvxgQ=gJ)E&K&~pH_9H!$;&V*>*$NEmod74_^A@ZsIW1{J;;X< z=n`)uS4PCx<9~a5C1Xph&jY5;EoAmErbsuP&Ud3>t4QE%U9Dk@pZSQb-?gnXb6S9t z#hyTRmGAXHhES$A|1Y49d;vAIG2{xXz3K3up^PO(@3^zG30w`i`t-X(-ihw>5{$}? z^mRzV>31`ECz+Mk*E%0Mc0esBbnFt4u?jM1jie}aVXXp@t!SdQrn?W zvCT-D6cf{DQl1f0v4;Pv#P^epN;fiK$i&nAT}_{~SI-+@RF)!-hun1f-4@=xuXlsN z5BA0(Q^RB7_a5F!9}^Es0FEHRQQ-lS~4krbcFeA-*5 z=TuW)^Em_=KZN;I8O^8UMhWLQ-L%z~YqcYJl1YE_jHJ#5{Qd`RlyH7GAH8OOtb0Qx z^YBVl<@&dIetHi2c9x=JBt@;QXPA$v<{Ui0m^BB9F3IQKy#8JWF$De1J8a~i>;HwZbZ7bKoGj+It#;%1 zc645Nc5dWux@P95?JA27w660h_n7AYJfkw>EAp`ApME!;cMs`Z67;i=ch{bNH=lR+ z>s^1=$(OvFaQfX!-j(TH8tdc>-racm-6r16(7OxZBYSx_#d?>|?_IpRlXvQSHF1m8 z*tFF59Xuo7!qbNP@`fYia%=-PyKg_qy@b{s+NWg77E_ma+OcbFgJOvk&k*A zhORWKs-H9h{z2SbU~8JHyR}0*V&;Zgh$Uj*7JAso-Se7}YjAe>lN(Pi^ZlCp;(*bN zUX8qcz}(lSkY`5uM1~sPU3U60liXo%8%yV)kIhCleh}8Nf;^M1bu&80Y~IxsxHmAj zV@}g|A@=}Uv~A#Lec=FcFO*YzHtvvU(s;A78j#-&hZ*Zw`mgq+$9#FM<%8WdIm^l~ zvBi%MHd*^k*FS;dCss&4TMw}qM`%;LS+PRWr+&mU=`4D$I`2_lwzSCq?6Cf1{qN_? zS|#0*IJHj||8rV5sN-yw@Z7Hl`UkeXgXXyV`Tl5*`*i$y%Hgi@W`c2OvhCD4fe0L( zNf4Zf?&CG#B>Q6Nk93SflNAfIx!DFh2W8{E++T)_%?szzb*I!V&m@no^bLbJE5ma^ z!}N&$u|@vie%`N3lF?;TXum&x;2sV5c}@L8cdPC~9+~!%Ft6d-(nibJHB3M@(#2J443#oTaR_t!b-`;e#D2zUHd! zj0^cW_7M9|t$pPaKg`}hYad!aW9>`kcIA(^Fov5MOELJE<_&GJ^zi61!>JRw1O8&@ zSo-6+_(j~_D1HH++lLZ={RLh zTD#Ei*f!dKoHC+;(IyRc(QBX1UU@}>=E_OVv{Go$!8~aX6VYi4N1j!uC5Mnz&qIu~ z>Upr)s$R4{`-4L#Qb$oAefCvj?~n#tn4Z4*e0<{e>}b6fU(jgu*tLCSZ^x!ZUyJxX z2AWFYyXAF*a4(w|i)OG6`77FL+hXBJIRe`DJU(7DG#-5I;<@;Z8+yBy&$bR@DS1CC z=OdFG@DO4bH*|zrrp6N|9?~7F*ggEKjoglldt`U=eUxX~lbnLXc>WNEv67s;;*n13 z`YG2=`Bv-)Zx~M_M>dTQ^)oiG-hv(MmD}t!S7pb^&ztV*up14s`6U4B3;HMc@0{;` z=I!&1qf-gX*ElhMJy%zPU?Zr}q?vPQGZ?hS0ku5jtfjk%Wr^KEif-^YHr4?2(c z_N;&(oq8WM@e1?O3CuX2mzmGwT+q;Hzun%4EHc? z_uvP}xpQ7XJhQ*u9sJuZ=w8T4f-r;J5*9X~q6)%!Suyy7SC zsZ8sUKO87}_tOKOnf?QgM~YU&otXM;(TO7b)sD^uv>Cl-L-xdPJfGUa+LCX+C9ESf zOGjY*rjD@1(h+{ox@%*7xo$YU<`37}y~w+;j$q}T=*`%7mXEP?ggzU|q1#nQ_)O~& z*iP1B_n6NNW9SRE4ELY4K9z$qnY@#A;rRVx=tpxwOiV`&x`o#FWPF2?X>*_@ohz%; zz5-q=TSE(Zn5T2LAUcoV9`JIuJj_`pjh{OYv-ZiOX{#|RZ}M)l5B<#hx1!@eb4Hyl zw)zj=??LnljYG0fd2UCH&{-!VC>vXVb0h|NTaOAS zw`H7XXD9v{tZ77y;K68M5vO)8(o;op6c}Qc~yEw=*njX$Y>ZEV! zc4tR>I2UO)b1pi_vJul}<{*vhOyNvNbC@P>=DqfR#0YjYne&n2djp@7^b6rmcL#_j zu>B~XW>D>@Kiz3U_>JK9R1VO8gC<^~trlov9dZ9^OZy$srEu~(yuFS-l=Crcr{Oy_ zcjP#(qij6$?Hzw&+45Y;BMgH zV#+*-y`{d&6)5NT8}N#W_!=Vc!8_+n99`f~0KN1F%~Kt*x0X)S zHCN1W<~ouqru(|J)+>6b^tS2a8`M|k!;Eo$2^~;4F=L#gVzGbC^V#5r7;RHNs*Ga2 z3}n3gh?c+1x~oR}OK(&@hh@~&x!dS)_>R!T zm6wN>1@LwMOm|{KbCTH+y6e8C)57;N9)ln3gtkN*t*q;`PX?^;gGUEvV2a=ksnA9$ z-&)t=k6OdZ?Jylac$7INc;C#$ypwpoeDLVkIv^*1Cj0j`^peQAh2OLrOKXr>4q%8M zY-L|7f5d9OBYdC(oU3igq7`3QvZ$T^{~KA<{Va|4;>WcYw_9f#&MJ$BcHOT=WYH57 zqhwK+{i-F4${EusS#*~Dswsq-=ue?Ft<0OPl-j>rpiWZ z{T2GSo2dZW%29}tg8w5C9|;+*=g8+qa(T)o z;bC8iEn-X)&)%dz26uCOpMI9a8~caC57ovl)|v@xmj!FO_6W$$uSeA_SN+B$WB&r^ zsI{kI!ubPmYS7IhW0lNW!?Po--A2Z%Gn^Wyi*_P?A>P{R3wEDYaMcP9TIj3#^=tKu z^$~$5+&#~;2=4q*xbsu*x71rpy=L+{Xifc8_0h|s>o4S)bWP!2aD;pK5x9TE#8)Z! z#II%gs+WRq;ZEg0DIcG+0{9N{UTN&D+;QV!PBM5Wo|0ZRI!Af{@sh5{KKpEWv})+z z{qzBzwRSr7WjB#Ln#nW4YGE96-eX@tpT49$1D){oFY%X9rZ4oo$!Hs5d^6^YE4QfgkmSA0@(%lDsDh?F|n01$&4=+=X7A&Ym-$xpY9c z4%TW1e#t|ejdjA0xEBmNZ(OIJ_=Tq1Y{mYewg&E?cRBDo9a(K__|wtQS3iF^QMLhc zit2n%x@%(`@zn5tXy4U&y?et_#;Ew;3R{{BeXO(TW}E3B?7ZICkbbRE*@}Mf($Ubn zi>JgkEHsS1i>f?xvz>AE8MgEfgO`!7nz$I?`V>d!EPF5~`yShrJlVpYHHy^+{_2K2 z;#S3@qyrzL&K>B-N5Q4eUTW>h9uY)Nh~8)X(2Tj1Pe0jXA6TDKHY!JT1g9>hU%mL@ zkRKSu$7#=FPv-rDIn7TRQ_{arU$I@kNM9?S?`8J2JgTp%E19VJS_i7@u<02#n{})o z){(O(dQMci0-kj#=fyTn-E`Kf*4K&HaQWUAT=~W$<(|1($ustvW*eKJ*T{Q( zD(15`;EWCS8q57sxpjfi7&mmh<8x^4CL3#E5a%w^e2QKEAD(INBKnTZYkI{MIe}s9 z-JpYY;Ffq4m)=k06OK`FN$*;uXN+}mOk8~<=eG#Ayqmy! zS<0C1u_f29`E5x~3;5YcKSe7y@~ovdF=otX^Y6JsoV9sx#jG6eMQzv#e$W+)1+T>3 zyA!*6@hjY!DY(0_pWbUvsDB&0>=gd^uQTUM;*9N!IlroYZN`p13;0iND#_VNoB8}- zyuBo+G06O2Kh>H&M2u3FyF$G2b^OKUFQp;g7FRzD zet(aRyR5*)lP3yxyh5DF{U@&5@l@<1uMIE1H|N#fkG*yY^L1~E`AAp9wL@b z_bQ~jw8ph2{qTL=nd+df%4l6y6Gt$l&?pWFFBK2wq*vN1HTNb>qlaWL{tLiS(>T$z zbzj3VaFxij0Q4=IjpkP+6}dUb!gMX3p?04CYY2Or#bfHV@b&wgx$Mlc>UP0T6y^+2Z8OyPY8`H$I zjE~Tl;4j3xS7rjk$()$7n*WNsk*w4mcVF`n4rYP_jkz_;Hd?U1zD%-ae9mBCtL>`y zL$ZbV+IiC3m&TQxU4t$+UICxbyb$ZDwglT8lla04V@xSydFx-u>`TBQ^>@P? z#1}U5Ok+r|xH2bjU##~Syx5 zFXG%zt&3{=Ky&TR1!pS%$G5wdFDo-fN7j(a3cvS+%ij4`Xzd~P$A{>nXa=KkgVwEZ zTLwjtx9P2eM?tJ&NIww#Izj2;#^ke^3xda|ge5$Jx*)S2C)kOAU zvsk~2W7CovZ84RZ^5w7(R7_qz<5Qh_bS1M6cPbZAhuGll&-m! z=>*@ips7Y^N_MJ7XsQjIG{S3jU%N?L>`QlnU!A+~5tm!e7)p3Q{dE&}zG?J-Aooiy z^2QISB%b44kgiN&5xlK+AD$&r(oSfs~b^dvHyhVSs#;ZN-zZ~$@KlBg)gnEtJ ze!{}R)(z&G!oFzXV6WY|?F+`IelsTxYrwmFf&OugX*J01d-3(j5BTmT{D42k4_L+; zbWNPM8ocaWgO5tz;3Pxehb_JOOJLsz-+r3U{<3>>@{aHv+~Rv}NRK)1MbZD4$h>{D zD_Wn7k8>w768*C{MB9@4lVjb_JWb#G#Pr#=llZ`FWSjrBUSp-(q`j#9h!qPcc`RP2 z=hf1O=E?q-)~R)XKde}1y-eK)K3iAe$*D6gAJ@+Ow3d&{IZFFlOCe;Chc;Dj3*%`2 zO@3|&{lDWy=4o|)Zs#lcx!E@+Pn-Dtv}t1|I9#{boGy&yRye>*j&r*)E*Jd5Zg9rnSlXnkZn^_m~+J1vBL#{)mt-lz3y$Fw@9F{Yf4 z@`y(B{QuJYLq}QU_*R=oX|n%$nd#xw@4vkAa7POxV($1uRmX+1vNj{080`ijWWF~D!7@1l*O zit#z}dx!D=uJ#DHlk;|my zI{M*2uS`cbQS7#Ob_Me!ex3Ei(&cd`A0&Sfdi*SS_Cnqtf?qUJ-VLrrTN#vJOCL)+ zv=7%hw{Y?so<-JqG%j?GPO1}{Am(=yE?_F zbn?5!h5W*1Cq1m4c7;3k`=-7$pMK*f3(Fx(Uz*Lc$ovZDrrs2mL0aF_m}~7tKLnP} zxC~*POoG?WLS8h|{?It1xB~f65$=PRwu|m!&&#{45p`+e&;8+}<{XCmQ9_#=cXsW^ z)Tn+$_rVjBT0en(@9XTrI!?4C?Tm@5D54K<6r?1@8!M)AcB^6|ymaSDTV*pj*Ah4Un<}14Pb)Z>r==T;)PtvHQa zY-e3?OT9^q;Rf)3V;INf;5K{2lC*5TmoO)bnTy4|YXSc+jaZy^4{=0`dG~vCuAe44 zT_sM|;X&!{Y4yX|bDymaIIC2hpCO@-%{VC2 zpE3`Eo1F#j%0kw_8;>PTlYcgWPj5aGdk-GD?Ye|fZ(iDS)LZ?HQOs-ZF!p@);Ac2< zdr5C2_ZQUHUZsh+wF~(jN4=df8I^BPeh)CWJ(e&{@a}OA8Yws?eW)(5h68Jf<|gs% zbF&&6jGmip{iki6f7|w0&uK2|&x%bOsrecXym^Af9`$VVya)P?hE>LYjpHY(GtjD2 zV6Ho816);To>^~=1JTd2C(e73vK1HBr>PD7p3ArPYo%rEec_LV)Ri14Ivz?*hKEWg z62I0n$qjSA>Is?qRr8!V^yQ4TO^KteyfW^Kf`=3{FWF(fecv9|?K)W&$!5{GaDE;Q?CWyyOOv9 z@!nm~ieO-GG+|sO7#q6si6Q?+e;0D!qIjz0w?5p};mtc%3=Kq-Re_)LHF8@;^@8gXzH}Jor zzeP*pKSi{wwI@Ek8hX=QPlTq#pFHsNdt%b+UxGg@60Px0Yrd9pPf}(lWs2bQFT)q! z;{DsaZwbGDhxZ}9Cq8E~_7;@=Df@UY9-#VP@jji{w<7$bYI`B;emMPnoA14&7N@Bl z@fN|WvpM2@Bc3$*jQGZ0$_S35ck;9fc$*{B>8jwlBQef3JI!bqY>RibSFcFod{umU zY~K+c#wi_1`S<-jjiuN$@k0-G-Pp@m`V;UmCxRd5RrbM~Blru?^Sa&G7kpjkxtVAG z4qZwvh$cmwy0=MmWGANYdD>YQZU-EKBEx7H+wsh<^@V|4odqA^@*jY0NO(Uxppn`Bppj<6x*mVAH>jQ@^IcWxa0 zFA0w?o^eEUha%*(Np}~zbL%N1x~mS4F+z9jhl*d$J~!QE!RscVca5R`Sn5k38cLn5 ztS`wQ;%83L#LO^FEQlGnO>}XT|Bk^%Qf^^Zy<~U<4^J^Z^;b9*y>@_C^{WW_EQ40x z;8_d*C4+s)Ink%+RrKksSuu40^yx_Lk6p%Dp*)unnk)>r-+DLo>1XrEx-@6a<5MO7 zoJ(6CVDIB{WDkxvpl5taOJ|QX8l+=t&9`30{sg@uqTkE!mR^>db1^m`lSkBcf1hf; z|4R_xGWIZy&n$O&*K&gKpOlH%+FHK{{|vWtoPC7qrk7orqxx$p7tz}V%TwJImdXg8 zk8#ePxdh|7Za!&v-`r&^)!t?O45Oh5-@Mkbx#o!dSQ^u>zJfFLrj6}F?ADCKRdy(+2>dP@ z92h4%XF9R&8(DXp?-JSS$IjGe_wsY}hG{;wy!ZT3haavL+ONm!9vgbfy@iYT+Z&72_UFGWEOo zYZFFEUre~9=cpCbX@AO=+xY|^@X|qj;e0RnBv(YL`lJ4-Z|yG@cpcC|0NNU#?N~7f z|Fq(mE@d-u7@R8)!{gLRw`EjrVO&<53De?fXCgYK=BpjJ-P?MGI`X0HSI$J{0R%{|B)5zWdHi;jvH)_ZSkDv93GQUe;>IN8p+x9CTH|^kGSbrGw&|J zHhM2-q!)9Br2-uLvDLQ_+pu}Wt;a6GzqOcW9XzYH_3m6S;`U=h(Szap- zgT2P>r7u~`T|DD;eo_65i?(GqykS)Qiis)CZSh--?LooYWNa_J(S5@jr?I`}M&kzk zukMX~A@=;hjhtcEo<}}D;jw{nIv(vg?N0FEKo@QY=bA6hKBPMAarN{0R{OH+#5o5g zmB?<5jM&TmUp~7VdK%+y!2VoK%>NdiPs09O9m^SO;P1umatXe%#q4XaX*MioKmRiJ z+qbbn@01N1n&a7iy%Qa&-Y{ScqfR?E=xl7y)2K`QRa_bVwsOi%!uBj1bUgNF@-evR zUvU82a$N7hNhR3LZDzaau5$J5c(1W>(4u&V_{_glF7f=N5^U)5FYd*LJ`o#w!m(as zBV|6LOyu`pqkezHZ`R5-*2w-$?q>NTu`R@21z#hM0vYtG>{0Sjvu81F5>K@uzrTbhrI z@Z>`g%zL}RdkR>?fnT4wZTaH93*JjGRvt(&Iu0;59X4=1F&5qN`$nY~9P1oxO)Te^ z@tqxnhQKNM4R#vvH;FxPHF9_}GC3aqk$isDU!c?RE&@Mc;}h=<&v*~`yDa#WowSg8 z`|)X`<3!30?@{w!Ld|ZojKOo+R3^=*9RATdcwaoec%6aJ{zg8m1+3BI?9~$}CmCeQ zEY1-nV`Ey1zexTu%Z`;2-b)PZj6qNR8a&r&PekAIZnjmnGDiG}PcP2z*}!?#zV(cA zqBFkUO$>mC{e$dZF|s*f({eDrbjC-#O0j&;S(&ZNos2J=@i`eE^V6}CcYmXwvNsI? z?`^jzmk&AB>6dly{a|xWoV?RL#j?qovK9R+vKNw#DSFSQ@txYY1+96uQD1ON$)ofF z^C?_NE*BKS*P(|9t@&m9WXyl#F012VJo#HfV}>G=wTIfb6Z)GHp+9TCwwq__SH$n8 z{>cx|UdFVGi2me<-P2Eb(o%dofUWWVje4b%t?|mnHl1;Z)+2pU>|qVI(DX-b`#o1% zeq=xOvpl@F?6|n6*FawoZoR~WY78&Zo_hj)F#S7LA70>@)}r4z|Dwa)tR1s1lFt(;HpBbHsc^>Ap6&a3IY-tA(I=)I3;T5BS=fH#~M^#!<`Uv*t z^wDD{7XtAl**wdeg1uB@VBcz%xrg}-&!Of^V^KfJ&1cTrRm>5z)n(o;=UKP?oymWr z?Yy3TM#I8htY!M9b(3`-@n6tZHUCfb?|fV3^t1GD6a9(qUxdca*1r_>Z*158IsVQ5 zZKZz`pmovDHOz~-=Yaln|5zdCd}iL?yWw$Y^1tc#b#~U!=e@>7mzhb-=*+?W8h%Nc zYbkRTW!(SjT4vAT(7Q7e`kG~8lZk_%OvXQZjXOB>IxjM{0Xz2g>X_utc5q($4~ur1 zQ!M`zv3|*-l?A4)I^AUt|Hr2by*`+e1s#f>UC?Ga^zF{RcAjhsvOnrSc@)z`C)z6| zCnme1X=*dPS2QL2hG|;@Q8mj>T87 zn>1)1MPu0TOg~#+V2jrX{z}2m0)CX-UdpowKacQ+F0{rNowC*7V|x!hL2FkucaV8K z!us>Grx)x+z{$9c zGU8&8iz{~!L#cJic$PE1M(n*h%dil8uk5uEn{PJy`y%YU_1I|_W50FMmxXE~eo-C^kBi^BEP*LdoxUIO(#qRv9>wQ6e^I_e@|Plzg`oJo=S z8=?72>pFkm`Ih-}h+jb)Ga1`)=F7CVB6n*3bkdZ$*gU%IueG=S`{7Wkm-SoD`LDVO z9{dX_zKWRY-_7dj{+(i;vMO9T&AiX97?zV&G2HaM=868GIo&l?PoGS?0QmwG|MCX# zN}&;(`kx%>za_U1eHM|GR=kXSB8urc!t^J%5cQ_r6e>#0We~ z?zNqQhi+o(p{YLgAzJqRn*M12BRyIBAD!LO-p8hI_CAWuaK^e1D7U;X1|P7^xy{L* zGn+lhB=#HEvj1=-8v7^Cw>8Y*_sYk2-Q<3}?WRoRMF!u^(44V;|K0tJAH0BUF!O>b z-g^}KrgZvJ=>F&z8?R)dYGT}~f7{aCK;cNOQJdOpADvNz~wBk=9FwFWqQ(o%dQC@I915Rj* z&QsgKTMYQKgU24=lRenvp2RO34T`bnZuYf~9r;92D!Ng znb*QT3mCQ&$QNSz2zf96Q6c}=a`)VDd{cs5z+O(UwWo^*_AFp8Mz?BY z-y?md0$8(v)fjFo+HWN}Vb%%z71f^lbE-Z1Q$*h@@Ee>9MiKoLj0${+kupQkA5XPI zpH~mWp9PN)zJl!QO3;&=&^evd8%BSXi%+U|iO!O0&*bCTQFQtAiZMBJiMxM<7njjsxDvyn3-(fGRiEco(*uU7EeUOqNQdQmitJ1F0DURM}5o&|>L zAE!QNRn2_TbKudMM{VBb~O&*2h1`RT_I>>E4b8=A{Sv>ENos^*#e z-YtB~m-QmPtciCGm?ocZDWLjRntm~Ni&=nua#d>uR!UK$zm?7wm+12{o` zCLNl59lY*Zc-}SezCw6l0kR_>*%8jsz+8;kZSni3t}^-etML0*HKxcJke~3r`@JG+ z(_!d5yG`fWM?Xhjl-uT~%(wdZHvQQMPn{p`qx=G!!hLL^kI%72>*!-s3~@!>?gWuc z=^O4-`8oPD-R#pJ8Iz5%#V|%Y{Je*mf58bq&oYSVusOEn*?M%&fXC_V%*FKYusxPo ztRCo0HgpPn74ZCa{&%ouD;SUbc8Xb1jMB^=#KL25l)fX~;tpVLWnN^TFEWfEzN#@F zGhT!L&oDOp8{suJfINwY@5kZs9%T=cM{L_CjJcIDA1=QlM>-sHOpe9mdJne5LzAyz z426uPfH5g2#DAN)tAvZUc3Jat@i}mD0k}y2+Exj@6pIEjpgs9WbS}~HNZ)D7`&Smm zfu5ziEgjzRNYXUf>iw}auC0fVC0(h4NHf2 zJd$A6H|^@^@Xm0(QtG+F^@dT;>PJtjEp&J%u-#E*^d4Fn9qFrwHRbqjN|F z$$Qs4_!oT>%Y_7{Tx?azmv!3ZYtg3vj4;%Kx#Po()*)OeFoU*a15uY2nZ?Vc( zJo?g#No5stvCltH+S9cC`@Z0Qi1V16KD-y4ce7vUD?O}o-thI<^c&KRgiZtfq;lS@ z^#{nOF5CV}<}NR$znLq34q=dPj1Bhj4M4noIuF50-R1G>o9=WO%=lE~cV_bPL31*J{{jrJlmjfq>v4NWk z`8Y-}t`UqYk#SwlxFRrHStp6icjE2c`T<@APrAul;2=`oukz>Wd$4rIJ;m!TD(y^_9#jxaRuc zUn!&V`u{G!bzbw+tzGl{NY8%_|0uloX~(9k&2!_C`<%otLUucQ1_%7u315yww!|Y_ zVu)#t;Y_8KGofjT!_sajfWWji+lboxo$!U&H(HY7o z=dbZV7CG3_E7!J4CMCLq$|<6L6tP~~t~YW+lgK4ih`grXO}+Bgv;lJ!@HG$Wa|v^y zK68#XNZgcp&&`|2C6#;PO2$hc2hzXN80jRF!0AMAI{`UYV4z!YWcKu4PtPiWD_fSz2)<3YrZ1(;^}`uw=Erdu`MG7v895#M1@ap?GtRRL zJxkvOW=>o4ZowDKexJ_ubnBHTQ%hZ(o#(k(o;ziA5Aag`SG|+H#vKaN>%sW{!`_?6 zM{!+={#D&9y-0wBc41nAV5=LvVL*}%Q3GDIu!JRx?IZ&8l4t=kB6h-Jkg)7LNiA#| zaBxHtgh?{$#@HBxEloT>fl2ZJd0~m2#CbCokW5+<7=*z{EbjL`)m5Sq5(eUVpPAq1 z{h?2*tE=w4b+d1|mBQ0P4Lsf(njyC#tP*;#8Un^1?$DLQ)MUncsp9u3uRb1rkt3NViH06M}v^ecYP znykD!Y&!bhK=*bxa?tL3KU**QR;StI3k<}b$Tg9TfBk1=o%oVv9pg5UFR*G-M);h& zm~$_4iftenIki-uv(T9HSIoI5RFA2YIp4}d$6-$Dmt8?Dtxp5Z`utRq&jk{C&6p~d?fvwEm$_B?a|?J?>0;u%+*!ABfnzYRxs{>*&1{n8)>DN_s8V z>$u*WTs9$aAAV`<66YRs`(7B>@kaOYGWGEa2KGE&UCh4!-cm0auTgp^r!I zevj)5^f2BXj2FHx8C%}f7z-Jw$FZ`3LHBpP_v*14!pAD;+w)lXIj$P(!ER%<0{3&@ zb^DC*Y{X;qgoC{aSC3V~ScW}s@7+rJb9_Jlm&qD^Wz&O6=&P<=J*ZF%(PvJ|SO|R? zzgwV{?!Q0D?-zM~BlKA@7+UJ~d@aA9Bc`Zf>6%#tl#-t^2qhecUwSnZxyqx5kr{(c#6+0?HW zdI*Q_uVuZAJ8WoZy>Z%lsXxWI$ROL#m-q9DpDu*ASbrSj*3n0#*8Ji4M(E^7@~#Pu z!Fzoz_aW!dcWw@~+vb+99PcY1+7T@6=c6WO=da%XA6$1`^pb31_fQ|vcO7|eI*b9d-4H|a3{ zsXjOH;jSCOy8(CbuEG2k@q073(A!aXlk5)z-_PrFcc-_dH}T$A(pw_*mY~twDr8sb zL!8a|QD^>UMuo)nmE*tAzCR*Kvyk;>BJ<5a_WKGl;B;i_X~@)lHJQ43IJFIB44%zKUX+^s(sS}}T$8ozB~DIi z>K~DNSW^Yxo7q$Urv3g%M)rmN=~6dZ{4V$1FY;-eKausE)jLN29Ib!e zrGMU`e~!{WU3`jcjD1v-+ePk@@8S!RPl?%;Ps#6-&qzMSwjgoCX8uIpH~c-d?5`8R zR@SY-g>}E8ue(l%=@z~lIzltDC*!XZSx#Uo2OXLS$yj6fiv*_DZk72 z9KMIwi=n75T2{vWD?XBb z!cqgQ5BS7K{JnnQw?BBcAk$mXLsfEA`f0NKS#uwktRX*5X)jeA=ifr756n}%5__A- z8A<;pS2pk4f$V=aUTKh6&x=n|^L$#_%%A*tC1*JPUw-==ano6A)%JX|uve z2hB<6U&LpUJ^0USbAtCDZX`w^Xtti8#5L+2VDnD$n~pv`lbY@RHAgrP;^n>v4lf(5 zM2Y?LJUYfl`ZL3^eGtE=)%xZ$N^r8wu0+XNgKO0G#NGFK9L&9$v7d-2TNB6n&Yumg ze&n`6$oKKgmEeDhzP~cpkC@By&Dagr!GBz9V_j0asY9E~+LpbnU~$lFJD+yav3N4J z8lf5E`7~^)#4Ym<>iIpu>1@2a;cwDsV3!h=_K71y^veKqT1E`=%5Rn>a~8|*X~!Ik zD;{%aR)Qm=uX;AV?*ja-)i1k!)H8752Xs}L$fKZcZ!UFKieuN+}iQ#aW~BGzahyP>0Tqgi`Pdf-fZe66cX#$K@F|=+xFGGp~XXs|3Um@arEp_ z*1gaC1-DN0;XlNOrM4Yqt^(w5p=}HG+(hRuK$no;3$fkLMJF3un3i$Ooa{OZuH-xw zdn4y3zU}xn+H5;0J2-4CiK9}m z&Av`Po1c57$Fb0p{7)T3PbPWtS>}W`ib-~s$@tX5OEM=mO(f1*dfmys?LMb}*hHU2 zwKX}YHDtNFre-hkvRhcUBb9f6uAbtVgsCJM1|E!wWB-cM$skBSXAUW3U zk7@Th{NmS(Xj!&qAq^DD>zS;r@A5eppNE6k?q=$R zIQlL>tpLZ!_T_7)sS)(NiS$&dkxiqhkyK3mh_Ywg7jsjUSLZyVT->BR7pe8*jIg@b z+-{E4;B-6pLgSu@DEAsavD^~>?TS@0Fpo5eLc2AH!nZuqGyO`M0vrWn=3$ZCnc}FLEw7LAL@yLq}fi~6Wqo&(l=;Ke| zbRW0_&n_1{6TY!X`p6}kD{I6L7Z^FomjgYt#4DZgOI-E)A9H6m!5^kDkId(x9Z98y>NbF|)YtY1sERbS&vJl}TRm-tQ{j4J+Jh&eJvF7aWrN6wpuT(L(A#8x2h$o`V|E9zm76!*AChG=nwp*=E$Ju>9F_Qrf5Fdr&N1O5bHF#gLH~E? zrz0?A?_9G!^LgX~6F4$tu4cvx$XJS{&COV|^l{9;4f%-AV*fld-4yb}QuEKEbgaqZ z-n6oc8fV`ekL%J3*&pqesLC2Sf5zTbQB(KXio*r{l$|2S#Ndyu{dC3QSH@zShb{t~ zvBK}jt(e`y@2#9ab|t2%6kb)%H9P#MdJ^&9XIC7KbcGM_0$waelzphMu)vYr}WtJU@dV(kLMiK|r;JOY!V`d=I>MqaW# zv*q;LXQ`cr?9w{pPpADu|90AWanj*CF5Z9mqutha=koma|%kn5cfaPQQ!U#3!E0W!#)4g^R66{%^`c2|da}g~&o4 z;AhA}MaV)C{a@&kg?<<&3w0t3rS~8UouaPmxWTpWT8JY zM|jQIOUouh50~rBYG)ezrKj55$gtX(Ci3y8oLRCra!tyC+__oaBxpJ1Rn9dFHIg{9 zxpU_x&Y1(;6V!rSTa%O*Iif^04x!FnVv#f6u_eh@9OWcG1P0QC& ziRZ{tkXeaEGuASZ{~PpolKZ!?mN@(u4Xj0c(6Y|mrbLg7DQn%_!}~tQ`-*Jg0B$SE z8NHSL^CHhlzSCq2HuDH&k>rT}E8jyhbf~Y*YQ~a$N#kAXuULD6f4RPPdB@P&W7~F- zH)5=PF8_za@kz$}REMLieYYvWBkPd0Kf!NjXHD`+KaL9ED7|>-+n8Zx{tD{r8}^VH zV?s8l$Dh(-h_rY}IVX&m(J_aKDWy(VDRHHtvn1Aki2fDO>(%Fo#v^~P#j%ikQL+`g zPsJd21HOkbcI1oFO!8fjTdIjas9tIDu1s?~E8zb=XbGFipl9h@wADJmQ>!{Y5SfNC z)=9iKz9(-=na$rA{IajH+)?ivc%Sc=rQ>~@<|zk-4n;2bozM{XtRqHR_UYGvC3=9z z&|&Td9#XSz828B7$2b#*nv``CizQ>LibcEkHtyTbwKT3tEp@qfJ9)=jxt6LwI}&@M zFYNoT`Ti@uk3sH|9wmFK|uykN$VcTy|pdB#&+q zf6{B3KED}RQGFKImJhu+^6ozMFa5xgkwYwY{sg6c5_B!HW(B-D$D+&--;l37xnAZH zm}~|nU*SEZmW_;0pRYw0#uvHv2zii=<;fXYUS)CGt4e*XIr*ahljIC}R$w_C+u0(X zbF!uu@jIJ$O)x3HJS4v#DV?+3l+t`!bn-7#>#u*m!nId7wjCioW_=WXQ*|AuE* z^qIvuTjIR*ox``!uqRVj%C+j@&>3q1FOu73fd?38>=^dlZna~aA;TSIPZnH55BIYc zk-1&S+{i>;S&z!P=wGrVXoj}n(cxv`%+cF7U?^J0q(?op7FRNp7yRbsKz6lJu5 zQ^6y71TzJff=BBp@HjEmV*!u!p4RLt^T40T`=T@0!JVd4tyYPvws`g-w>XhoHWSO# z2Hxg_w_@<-dUDH#JDv>TD;IoC?HiGNMDmrx@RiRyXA|#~qr>Ai;DMazMF!Kx4u^aA z*iv8Y9p>H2yfV+7%oBtzWS(jIJTE`IaPb|;UP2c#j|I5rGLH+{OW-bJv=W0ZzX{x% z7_XS|iXJXn?9$OU4o3IbjO>F+#!*mn& zKzm)-K6J_c02ZPP$vnX@{DjXVdr0PDFCLJ+Xv}#h`VjlE-I$X-sm=NFlF*(MeMsi) zWl#F$H+@eY(Do$pliHqSO~#%~>e`c&fc0fw$ez@m_hCbP1y8e8%ZJpZY2RpaoEQ6^B_&m(# zd2Ia2*wBB5jsF}nc?U9(*xAL#E<7_IeI;m4(Cqsb?C4hP=%v(NylmeO+1w5Le$8L7 zxyQ?W4;;?KzHivvH|o!beP3)7a;EdC+4o6Cj4HxbkzVRv8~E&N@CaMixjVcYk9bMv z5kFKqx_CsK8t-Xj&GLTpuqpir8cN`u{tQktHNSxLEQ;y!3zWzjXUA`-jDCM@6+A;? z&czPwz{ZxQ`vvxX9P$g~u+9(Ej+^2S5|bxqaQOOypQy;$%GN!c!;4vGBI^{r2<7qhki%Dw z?<+-mgKB;s&4y-Chm4lIhfUb0>xijC$2?H|yp0|;%Azf=W9P$fRt3G~ppQ7;AMSlP zwyLI8>|Fc4?5*JZ`v&&OLh3V|yQi||(_8n}oIy8#z002_wt!fFerIrfBDGJu+p!a{ zV>|GlhTF04H78tU#}*h_uw~zv9Xlb+j-7xVJK?(Q*pZX}abHiwb=a{Zbvt(C=h(4> zrnt6R_LRUtc$&b|4m>4KRPa@yy2qt~pGuQ^%@Ov1+$Z;lt{I?bV@s*xTYo0F9zSZj z+;2(jGYcQk0g0P5?nP&)m*-PgTKohQtP{Q?zje=v5;@Aqhq|VpX^-__GCkB(ck0jz z=CVwT*W!Gwr(T&^YNiJJn<+z8VrY*LizL0=vedMqO`Hd^E+r*psD-#r%df_GZG7fB zv0*&1dqVcyiW+&gkasOEb<7&}tIC=q=uXGLm#npUaM^^m$;4h0OZ(O>%DQh+SLKe| zq^6qUM|RuhME4cF*U*(jPfD0L#$&lSXKmuj7d)2WoWstC6zby86PmRYGKZtDQnDX? z^2}z7v(;RcWchXV%oekn>4Xn9Gq?D6TklabgR}67ZBdrAJgPM0j#k!vnYo_~<{w`F z*_^|bW{drC;z65Pr}W*EUfyS=mH^)e-%3ozX7W6deZu|a74XgDuT1p4gMJ}C^VZ3d z3+ix*zf64QTkx6PoX}!LTFp*;KKtEBkETdkde`d@uQ7{&U&Kf-l+2hVRAjpWiDwdk^r~ z8?EdR+CVP!W)qig!M6Jdwq4Qf#lGvqc9RMYvHdI#6!-Bp$CpiLB))Aj@pL`t`kEec zy|#!ti6PW=+n=!K=rK~_As#IppJVYY3O+ZE_^*%8^I`b>+BNWb`rOs{yzd6_d0#L1 z%qAyU@aa-^9clxoHhlYw!RHq6Xy8}yI(KE2hkEmQQtLS|FN9Z*)Z|&N&JtUK*eD{1 z|5$*%LiEgcku%;!rmI}BWdlC*8RTbacBVULL~3@X_a6TK;(@w7;calqGa>sBv=dy5 zeF%AMGqI@uD9uP*vOzOTLi2RlhkVpd#l92LId%I^E$@AlwS0iRG>EUc82%H}k6Lr` z?8s0&1+fz)Ew^DK9jSDV0j}bk3*7cVSA2>I`$qtoA+*0F?ljC*={?|I_Oi^` z(|#7e_l?BR*m!5dcK7-%b3{-r<}P_T-U$hm0mp!ezhY$PheadDRjd|C^!XaGM`ChHaX?Z#nk9 zDcNu+g=5@H|&d|yJ4@~CN>kpUT5r|e!%}I^nHvtScB%r z1FOJ4-|tg)XL?j@p@OH2eUZDheUQ*ri``}Z`FX560mfz&nVfgfxW+uQY=ArJmH zfuYDV0-K${CLfxs1?CgOXl~)Bz>%{Vexc=^Ie=LJxkUSpJvEu{LZ87s)~o$n-!SM`u@|!EH5u06bJU-{tr9{C-VY7yq-#J$L93YV;uM zZtIeDKRbD7qgiR+5G+0HesfNky!+i>An&$HtexDiq|6!GBKCLWT}`h--YrJPRWzBm zvPQ;u>{p&EWZetMxgzh1tlK|XS@#3v%~8l6mXMutTezLl$idWY)BI-GDitkOLgFM6 z_l)(VA^SRX+1G)LvzL7wFjL1Fnb#F2?_NOuJwyIh2QqIEc{eai&20INvZQsM((vay zlyzTWEf#aK{rv$Q>ESX`+{Ce-bI3?v8-8sW>BRqCnRlBZ^X~0M=9QQT-L~NG9w+KM z8(cr$)bYA5^J-`0y@kuZ5Sh1NuqGpI(`8g{0C!?ZeU-D{5vxKO8HlO;)2_chW*#aZMgjV^=sgEbPu?_?*?(( zoBSI<{;gu~%h`P&a<3J8+7|GM?5p9~EwV3X6}_H9vM=^-(P=zGLOudH+r>v9vai_g zk$=~S-ClSrGH~d8#~;)s1LHT4m?q?4%^&pMl8_uMHvEI&R6qCd<0N>3rG0#&&zg~+ zzDPRiMJCq#FxHSv9FnP)gnXv8z(Zu>s6NC|AUpLW6N_B;kIKYjz;n1vTzEK4CQdeF z;)E`lxch!j?|~-d-1yIsiN`tqF`2j+UA8xwnEH1&BNK=GaN#nsjz2@5*hG9ocl;SL zakyN5V={5P7T*&dL-rsxE+4dPVK2$PO2yV}?4Krd9r1a6k^AOR=0Z01%bv?cHg5g9 zX}ieA$jGN%#1Q6Qnj9`0`@>}8c9D(easG$<;SAZh%kL-qmAI8Fd~hQoHb^|O_~1lN zmi?>C$(p}R?z4H>n}nZW z+j~98(5tWThwE}ZxiCG*(8)I>Ll2Yn_8>#QTOX34lZ^M#W#~BleSXjH*Oa06*bj=l zUQ5h{;ro*K#%6ojgiXX`rX)avc4{tMoO9UntwGVvj zs*)CSWfJl%;wrgJ4~W(&TMH^Gn>hUm2)&uIx$nmwj|QetyIlK4qx3I zziWc}^W77g`9)h4tv_ORZ^eJ>ilBa@gBYs6+T2SO{IPX+P%DT&VJf<##gPy# zYunqO`lsYER*`#@i><^uA^UIvzOk=jH&wOV1GUYBzEaSGok5 zSK_S4@F%fq^&@yMtMcnZbwe#{ti+Rj`bP_S1J<^=?0XAwYJuq{-fP!{0?|WuM|#mK z4mi;#9Oglbinx{=o8@ieS~0qYI;3{m7;2e3L7u@Mcvnj)?<8?z(a+a7Zc!E$p@SS5 zZt_m*TUE1pk8)7xlKkNeU->N^t?|k_D{{WfC9rGdJ}0>%PGr=tA2c|8&^)ukJO)naZMwe|5i> zP5z10Wt#uY#-x+zn$>Eg{dU%Is_(mN+p)zrssq}Pv!a6Lf#*+}qx>J62l!ZwkM)`4n5rxux{3STDRYNzeScNb zR$`DBk6NAXQf>ZxRcW7Now!tDN)}KXLF|J~E@gJ3O=(}r=UH>SEBHbGlJdKGC-5Ng zr-w!%htI;!o<}Yv&qyEPH-KgHK;CoYWZy{Mdn)fah4;+k9Vyzm=$+vIjGoQAZRN8H z|H4jnT~cr%^*Hc7wf%7Dtm??JnboR2Z#unIPMAlzo{e0wW}~|F^oi7WYVI8IZp~J8 zpnn>lZ%3`Fd0R~w7cqby3*0ZUnWfw({T7Z7_S6(dZ6v2BVoR=SuQ_gxXlpauKjeEA z->ceq7dg*7)Rj{HL!CYa8*z2iIPVE)cI(c*8Xdm`K34Jj%h2RW{1Ub0U*38bzKS6G zU;)*Q^tY9+cW5$aqt*trQop`I_#t;hL7i6g-bH>cPl05iS0ZB zJrR%5J|Emk%~HvCkWZ<5EBmJnct+6oERuL>D|_`f;7(Obw~NiPRPqj>-Tg&r8All> z@Q`kY1s`G;ZJF-wOy!vX_&CCS$%W30z(417*=~D!Ccrbo6Rgt*&kB;q=zM=;lHdHT zj5fw_s!6Ua-bKbLf=?XbovwGh7M|aaZZFSDjO4>MWlSBgXk|X@#7s{zxv)}`RCuUd zlYFCP_-RYcNo}n>Bl$)`Ti-M%H?72O@8I3v>fxPRH|OX%c|*v_`d89e&ycx}SEz=lE&KYbdTlraNa!%u6(E_c{(W+r5ta zOkl3r?!)k}+3vg1jAnP{9-%#(jauLAryr?RNkS7@x<9Quof$MEI2Qbh{XLv6o=`i| zuSIL}ToJTk2lth#yX9sY3U!7D~tPw;I*)-cYs0mv6Kc-{%GlKrgZDf3>foJGWZ z#=Lguv-NiT)K$^qXL9%pZ?P_#|1dd<%j0LAz)w=j_h;3@?RP$Gno+4fTQfy{E~zxp zvZ&R(ikiMkNiO5&_N9I*JUdSvI@&jUf^TA!Cn@-uy`(k2Z01Ymq4h_%S0&Z5509}< zsmt(-RP-k9F9SY{O)sRMg_flDGPMZmTfvi6jkV{(*YXOV$S8$}?dD8FpE`)F5cLH8 zi+r3RXIX0tdsS-irrrH~jhwIYyp4CN__Fk5Azy^wRH0XXm$(7B=R3a#PWatgM&|hJ zrE?A+hcC}lBm6$|Egk;h_c=GQ&KH57$OL~y2U?z_#|*G8hl0NXez5*MU6$QrzotD{ z)>p?`WsPqUgBwoMa+V4Ilw5{g*hm${=6&FJaJ|@y<*XMTZQ{?c`^tG|%>N^O{@Y#; z<=cJwb(J{5P`;hyJv$Ut%iS^ZpS#DV?4%!6qbcT!*p#1`Vw-l83uo}W?y}tF9LqR( z-cK~1*K>|#Y#7grh3Cay7th;D{@y>z^IoF=*5~CRZ>4vaz;`S6UONw2VnikpBPaI# zJzD-susjqueU8}KPru#=nD?c&8u`QIqE#UCS%@)kk%uO6nj-T{oWU6K&@9NwIjTvE zBRWeQ(ax?IqF7=kV*Jxi1=olB%Y;95hreN05II`*vEd86q31Z?jpqtSPxLj}+zoq? z*^8FD*N!A7Vxwx;V%#KdTk;^L5Ub%tU&eNSAQu@$;N@gr+Ig=CqJqI4NmmKeX z(Mm%>zm7NZ$zQ6&Cz(U;sddD@no*I;q7=UGqmIGID4U0x&oO@>hZ%iJi{%k`3}(%L zAeVGG{cRbm!LqX>9l0w?#(akR)2Qj~7=fPxI>>_mt;A0!eA~(x|HSWE%heLmztgBU zZs|*}mG4kPemgn?zdPvPl!6{d?Z>XZL-T-_Jd?tw^x$#wjPw%PjNC{KyMu9znUAhP z|D@2mV{M-KQSOH0=x4Ha&DJV;TJW$1#L#WsZSg+gbUWwub$5Em(Rz8w{KduOXw4x< zYtvIU|HsJXoxJBhfs^^v>wAGk7P7u=BDAwoIav5Aadv9inl^LUntK^TzSmGUnSIhR z-aNP|IaTrgh+d46OW5*TYD_3Y+Dv!-tcHEDL*jWuIfjG%HNTVJ=pAkP=J{seu?)G1 zn&a)Myq6;JR`dIKPqnhQi2IQqGJE@Wj5`mFw3_dsS4RwS$n=SW-Xeh8ROIb8>Lpu7 zL?&+ph8A$3AbVB<$2<7{BkF*gfnOCp^(ujx@Mf{$j8X?TZFI`nM-2@Aa;fhzg|W!x zn321rbWIWUbaOA|AI@d%A)PL!ZPzcA*)HzO7g}T8`OsJ@*M!FM`zj?xzoyqOdZF}X z+Ye2Y!mGHjR5N+>7pA%)ZyIS>O+8u@+A(H1XB5!7=u+ zZm0APdh0R88v*_rzf7M4*0k5<_RU!tNi1I+HezcNF;<>^!xUc`=iFiV%$xK*)oYnX zpLj*}+0g4pB0n5AE1fUWYqQyG-WvFx(okWtHqq;|z1iGnYwIiYX2iZh3`+xydp3M9 z)6&lVsDvK*?&A4u`nCC$vO`tMuG0?H)+#ZDt>AWu{vLk%m?2s)CU!CBBs+1L<1+u&zHQ}fjo+m}wn*SU#& zR%$s59+wfPx9mQvx9v3r9kp!clGOK;@_x5+=J>(!(dlNpP2|!7uD7gxaIy40a^5~9 zn%dKIqXTuJORd6qGMd`=ky%uAknj`#}3r(Q^j0v~hGqoIsB z96ObgRK8oNzbp3P>}Qp++I{r<)9zbBjxhYe(HZL1kj?l~XV@{4_@-)}zeOo|k+iW&f6s}~_bj0YY+H|2FxQ=z=VIPPn#~26TSZ<(j%|VN0>E8xQK65K zN?*=Nj4>Y^Y-IoK8UcU6mhI2|`yppk>6#q)|H!`XHHGLgMZ`g_GTE9M;d>{Zrj`=t z$sFdL%D!&|W+~8UBQUGwjA;~@mGc|(#4x^veIfkC!diqLoF$3T7i87 zEw-sbvkS&_`Hd>5=^(mZC2|I5n^s$BJkJ^X>tcIweFonpPqlGqC{I=N7s*pS${8*9 z1?QPF9cz`vme-W}=3?biOQ|_?33h&2gOg{QlBglUS)|ng`~kJThe!HaexP*T!J2n+ z{dw}mB{qM?9%UWzx#V`o`V)Cho>3LECyxK?_}&EQ*-mn%6&!Og;- z`YlE#xzzevzk1^@UYp#9D z;y-g+q_35AOTS`y_qHF=r%lQF;7qZ*^W>#q{7&w9zcaX#zJCXlpQU-nv;^0`$Tfjc z8+__NxJSm3ccS($(F!TFL;)euY|Hk!A`ZJxt{?B3GA7_mB`EHC^ft~*#-$Ssl z+%zmCM_JzKn2ygtG4|2FC=It!FQI|)Wu1Y6W_lIrxyGzFJlA;m`Ow;5=H4uaW6`cc z&L8mc5HQTL$1ifrcg|sfx%PVje2w2l=hc4adjY>oj)i>R^*wkA-z8_zGU&%Mv&@#F z6uAb!8?E0{`(5ng+#@t3&!q6Zg71P)nWOeQjL96g${0$OHip8rG{#8PpDFtveCL^4 zn=zyYk=)-rm*4qrF`nmp z8ux29WBGj!>*l-gvH-Li_<_6O7(NE!_afsukU5SZ`-xn;*VOSwX@*h~@p^D};p0PR zS>S0Fkq>r;WPze5=Nvu<&YUGx9;egoYZ)2ole&GoZIg(_G!rXf_WpIUyYu(N>;#Uv z8?e!i{W&-)rJq63YxL6Q94=%G%YsUeZG_v`3VmBRk1MtZ$H=o5`~f1%RD270M`GKZ z5#B1Plf0y0u~8>EK%L}l@}^H?r|199I`YL%%Kz|_x^H#7A=j+PTse{SlOlE};Ng8m zf98GX@V*xY^FQyrlAK_9=Yams^IyL5otwAz{?3A%E8ZC!My3AFGQPZbzW(0+Exo_@ zUjLQvo%S{Ty*Ksz-g|lPH$v~-An$1H4DJve!+^s!9S(cHdKnJr7CS|*lJnj@0~+Q0 za)|u+6=n7xk?-rI-^5sQopbfM6C=GJz=t%r+R2+Ws``TV8a4`&A#DWI{UIwfxt}))5vi{5vtis_m3^?KcixIpza?ppV?=0sveUy`& z%IcYwO6?-_iK6D)L$aMUQi;w&4pSzgr&@)aXX20hVZ*mduhLUmoX%DAju z@R;4h+6=mTp0&BhT)j5Q{}Fs?cx0TtjI)<<%$r<=QHTnd8)a{n} z!{7H9_xw$#2cZ$6kH?tf+d54My%z9YWP_gM06F`N^X~E)81JVJ%6h38Ug}U52`oh3 z5gMAz87#TBMFI=vYGwW-_6L13M_?rJQ-jGjvfF$wLVtxqf7;$ObS`YMmL8s>oflr!}es*4no(s&k z4c$3!ysvmrh@LxjdR`WVeWM#aCqd8u6L^W8_S7z7Hn`W=W1>I4M?DEy&+V*-I_7P^ z#3p~%9Q$D(YKklP+2*HG>q#=Vw_bBD&FTUdxuRd!2k>i2%3;CuWM@^%D& z;$zNsgnZ1M#gSL~n7?n%%!Xg-{^ix;Uv4xFT7(|FIv2mP^vB2%eul4E`d%uj1w$=! zD{Fl8TM@fV_MIW$`9$Wa8=4Spk-nkkSXU7?6T@#Fz;FI=nBV*;a<}kq!GlH5H3;bP zaSP|!5#-~Y-yRe#z7?@=7tm)*&PcH<7a;Ssf@}QK^s@-XP%8MR>xSz7Y2L5-KH?0B zjcOd4uqXu`UDm_7dcg2cOYE%dRgsMYd(4@&lfPMCzhcg7%EUQCMc$N}tJ}b5z%w=E zTYztcd<*gZbMP(nrkEGO4LE8tft$-Xq^1)(nBe72?y2j$>(B*ra-Id>ehd4X7#zQ` z-+xQ39Jy~h_fgwpXp-QMd^%-!3i!KisFIR8^nP^xQTz%1EIR(q&ij1)<>O=O9e-&W z{&I*9$kO8iBql)ikMWN91v2W03-~L!gPeykmM|P=6CV-6ane;d4v&qv9vnZ?6&G=B z9DkJ<1i^8(5re=vCODpmk0hTMgbhh0v!K<_ZA)q zZ%luJdDHmrEB_`j4BzZMh5=l4#V|mB)RK()(sevH(Q^4Y$z>s-J<82#m4aI;1Jz5e_wnvp?XDw=sQz~?J{0f=(~<>2)VjIm$y>+ zpIU-mY|!|PdhW>==>O0~soi3%GlO+LVjeI$9AC}EeoznHU#+h-7e7`T*RHkJrYqJO z+qN59jnoCjPI^k&mf`*N->}h(A8P(c?`Hl_k@)>FgT1xY@3Z``$$5i@dp-QmT-%h65#9>^uNC=k z$Ctg&gznjkYWZ3^p_+RoNZ2XC?W8qKi9$h&S8eVu;cRL&F&bBlkjjF?YbH~X>VTvSq5tuV49eI$Ek6#GSL zhIs}l4f7eN(4sWt^Q^=uW%I1a{}cHizTp*^9fAK6-W$#+~Jxk`{tZ@O4JjUVOOT-5u&xj8~`lROeRcGWE zhI|k%-JUMBQF2&!o@!|-WX%OHDZazdXq!3BAEBxqnV+~DPb70p18&F3p>jG0BsVgj zlX(>8l$yfR`9H{}0@!b6{l>m}=daox*e1Hpe*QQ1 z)&JsuXkFVUzvX{wBWQI)d#j=G4eA^?vao-DoAry|abG00jzje!)6pX;(U)yY7B6;M zZJrc-G7`Ih46-d(i(A``uK&clTrMbHXyFs=+@7yJX1F**1$Bgq#(z9L~3 zwVmza!xULPl^z|~){A}UV@ay5NoeZ=bRhQ^su|-P$<(lVuzIHL!HSvLYDJR7_1Ng6 zY9X$}=B~x28t;l%ZFZTLSd!6^*f?{k?NzVZ^5(OKYSvIaNEsvZ%A8edf?ei4LT?V4 zxANA@^NvQ&>za2k^Y(j=*apw_%?sVgyfSBlH8)S@eJLt@-b8KQ-Q#!GF-LejQ6Fw^cXRJfF>$}cO zzp{=?czunQ6eZ?I$ctyctt^the}UnlymD1?f`^k6+@GA_`>xIbdU0q_^(m1Uu5-|Z#4p|m?8V0`V+no97-h^8{`}|WJcsRrI%r*L zB^mqSi;CG2A6aiPTeEKhroThi{;v$vEA}U{NZ0s#PoQ1;p8P|!D|Bw~n$5t<;59kKPYAEsFZGMyH6xMhZH_;}~bg z%C0jbQ9Cn^kppJXWL1>1qvaE2yB43|uR3il-M4{w1yAJ)bLi}_adr&5^6Yqyv3ujg z`)-gAOJ0@K9+0y$=l8+cesrPmnhPb&bszG>0?{c{t6k)Cp<~S-qVZt6#)F-l6TQ)K z1NyMRFaAr?v38z^a5KCczqnD{L;)XpMrdvy_!L?doQC*@c~+I+b7=2;;}v|@QWszs z>j(1^nK+21EPoj_6YL-9+Ch1Qj@PAwfXu}qt8OzoRxS( z8#Rwr?_yp4-#Z7Lgm`32&H%4o_e_gByjuQuZ`Ww&NWZRL1Cp15?y${rq`%j;q_Cp^ zxjdg(7SRWelaHb41ZqT+3z@tKdG{sca;rJQF0!e}rKu_OT_DCs;)I;uikkClJvFf+ zU-hC7G+w0-#JXb92gpMp&yW^5AIO`p(sW0H1mnbEh6bIU(8w6^YNw4Bd&HOV9W$O;X8f|{7<6Rg+n57#G7 zeWCh9Lh%V;SBS0<$GD|(W+99F;T57g5L;=tun$Ysq~dpoVU_Dos!7^)iN)$Jn@P_O z(JSOkllld3bj3-BdYARV-Y0Y@dWD>6v0-{em%fQ!Vd$GTs#k=|W-`W&>J=dwSeG|g zqk*?7WZ>(ismFn%oMYMSy!*6u#dUKR<(Wve+aib+zf3Cjge2*uI|q8 zV0YN2*&XyVbPseHUNb>#2S&Yws<8U^M$Pi6Ga{&WV)I8*CtdQ!!fTdiU!6Cm)lks# z#;BJdd1KA2MRev<#1@d>*XG8jAT=kx4&1xz8UlAi*XW5a{~`?T|GoKg?|WhZaJiB% zPd;23(krgw%LZ(J3T*R%t;C#71hyh`Nq@|l!0Tqldxr5sxQj39?WNHF(7rkk!o>@X=MWf1E20*+ArN@t;u3#NUPv zFu(8qwF^WKz{V)DchGD<-$w3FD>+8P@#O^Wa67|g@LaLmo8!9l0g=IvP(xGn0jI7H z7&7>OfWNNwb<+oWTc7NM0RDom^+n10&<$80vO)T}b6}ohUWKBnq zSS(Hd03P_OwH|kQk^9z85q$xhcL*Mm`yGMpz^=ig6?h9gTKc&gsx+TNQt=ezjyjXX zT1!8yo^%I+z1Sv};hn}WE zS5u*{DbQISxtf_mlh}2fc=~=tZyx-$p4h zK0$Nhc@zJq4gS+wC%p)az5*}e1HtD_9z$YRP4^$|`D}e!yxjM|;YXTrIFUE6nqb|GV(bH%5i=>W+ge@E)&b?#5;l7kND zcDe&%r_0iGfaES6z%M=pdLUFI!!)7?$l9^hX}Z8!=tukuvi`zrtiR<3^(&F{MgHF( zCg+Fb|K#FT_!&ailQsGOVfLdgyRJ6;3g_+!$^Rm|E=G2(?~?x$;G6OOK1YM=1&<>C zi|i`(o(#W27yOa`4fx-v{2wm6${05%|A%O6a+vJe+9m(r7;U9NyMf7^z3d+q{Z8~y z$tCtfiymn6d1y3fjyZ40rK0P}I}>}-D{KS6Hh|wRfw=DO@O=r}(|>*VhW5lf_Oh{e zZRDwHwp@HU*V+@G_D80@&VBKbDWPpHb8OOafWC0m*s7YW=?bl!5i<4`#?A*nvge*> z?+I>X&xP#c_h!J4v|1ffJ5ppX8cDC0d6c`A+4SjadPQW6o4~jD=;XQ2TjTYvPwMX) zyr?_R93Eyz-#@4u&m15;bMoQFVLHzg`KSk;$r+{T7hQYyAK;l;@Eqd4XE(uf#$#I$ z-9hZ-!dtL;u6FA7a^Wo^!}i8oPBi~_p#AIME!T+yv1<#>v~=e!;LHOKpJ$w&c#A>1 zM^B30o6wemyfv5D&yZ{z@0WPcn;rMJJj))@`ma1f|CLYe?go+huxUj}E@UOK6e7dD z4X$&sMH_Ztl{^lS`EvL)Vl^@ttBZy?PqltMyl>p@d%OCy1V1r#G?&w_hxkOJUyJnX z`4{4Sd+OKo$Zl#$_0qegdmojjnO}719%=jr&(&peu0rGDlQ(=p_~X0IO_JI)yIJqN zJ<&fljJ`!j`=ZazaNF6wQwwY~=u{U3f5TrW9MLQBRPdm2BW_iMrypw)}%>em!DkA-7s!t2uvpK#g}6)-QGFReiIzkySl?m#Qrccd7{Mf?V z>-3(mn^|*(Il&{>6C;&_ADI%hI(1T0J%qoK#diPl7xROp{)t{ z)Rlj`qlG^9@G<(^TiV_<=XablRo1*|Q+D{u^Xs#Iu9W!5-_I%`Mv~reS(nTub*x|X zV;4TRk<^qYpOiX)c9*}XC?mHxEyJS6KLkukP10vYVntoc2hGCXJhtFEo@=qYJ0p1} zeW**?$ zTC^ZzYVoKH>Pcue)LiH%Umeo668JdPcu%_3(nK>q$z%54%DN<%yA*s%zY{a~s4yja zx&L|gV3YwMR_((kK+v03XRk7`G$_q z4LisK=6@NFn7wti;8Mo4DDmJht}PFG7aTh2CzFfMHJ3h8a{lDtufRUwLjG(Ud#B>< z%^&|hwis>CEiJDQ7tydG)Yf1q4nQ{(>nLd zb)og(6|^q?lX&nFidXNVb?$el@j9)?>$EQSUPaBH$$K~2X3Dh2X;TpAvsK)`Wr>J(% z3E=Ro8gpH>hgN+7wTG&&qxR4$z4p+mCM1K#il=x-CWD7=3h@ZM-jZku@ON`L3I zXs0{PdoAWqdb2(>oIB&B#cOSwA z_8>Mev(}S!6gdUC5>K_s>76R|bB^5Sr8khj65Cz?9y6V5Cs&U5&bh^%kqbZh3f~8f z9`C)|;?5i$;m({!ZK17&3+qqvH>hY~{Yz?u?RMg?s>cqPwYBfi=!lq@dq%}2-4pes zY1WiD<(|9y4T*kk#Cu6EsZp+=I;i->a{H`PoD1!@ZA@xhpp;Z6&U8s_H^(HUWF~XX zJT%^WikOe;#3Ynw^uD9_9Kpc)!R4ckp?_v5owAo5wd|pEib5RiY)2!bYxJ z3bi~f9Pg=Oa5)9oRf9{Z=j#HO8s457@4W-O9UAJ+C`R9$!990_%R9ki09c$s z?y`*7pCmHZ0`NLgu@h^cME?l6pt^8DeZZtP4Jukte>Z=`2;1J~J)GdV8a(I3#oV(m zHtC*eD@?OmVwHQ|?MscA5eJg0)d8+7HLCay@O+n!=Z`czPj`K+<5^o9cs{A)Ig;_K zQU|)GfaBa-2Doz7h}>_Ccqhq0zofC?IkE4?n#QNd&j6o|RpdO#=OSbi`TR^RLDs=0 z8|(TWys3=7De_#i=_fUPwX-(S)65zE1htDEr~c2G>GuP}$?T6wz|`G&Y1!{W_0%SZ z`njK@?{^oBk$uOIM zUFW*bVR<%1p2JSD7uhpp|Bi7TqUPdAuHVQS{y?o+k-2W2eI+vWqZ+S$({~PD z`{~zB@CviWXD#%WC#Om4<0`d+1b3e&@7yem?bJn#==Wm{&Q1fyKL~^Ieae#ShB425 zy*oYPLlPKEeCZbj>p4g`b@L^);(j(>p!2Fdwb*zur}1Ga}^C2j5iTiN6p z_O~`tBjq?|6?}hSS zZNvdcEz1D7v=Waxa(Vw*X{nZ3mdt^(oVWC!RiH-R!(6M2e>c!uO+0{%Uu})_lo1PH zQ3s8Nen!V?Jb2J(8#bkUxa~#A!j?z9NXk1?o4_efG@3vL-*PZ*E%1CZ%f^VbDSj-|69!Yu?*awN8gm1&hovO zvn7#O)2xByq;h|=t`k3LPNW989sRuLGpl$Qy~**(JFuS^HOS{PPm3whBX!8D(19Og zU!1@mb31b_P$N8dnBzS!s{@+k+D9vu_G93hI)Ck<`yBp3+!xuhY|V2#JB^;!C#hk0 ziuj9N&y;Q*^pw*6F0}`mpUK*KlFzy9bB7w)){L#n(Rcaj6nNW!_T_7~@h-10#{xCd zlZ$NMW*X!{hw#jK#(nW*s`6^tGs?wH+Oq@N6wc>JbTB9PiLKG8Jrn7PjKbbU9xptl zJuglG)p|a$#(&p;`#6O zK@RN;uk6QJ(_gFKYo))P#ngOAY9~_<%_TXsu1k*}PJ74wTAou`l+T~*9rv0iE)AUF zD=mvAzqMwZ`h1e(F5)YA?<#r-Snu)MUsZBDiq(X1mHIWYVdh}J6q{L#*($cP zD!E5!+{bxLuFY!k;WuFiE=K+dQgh@4=Y0|Rfm`^U`k3Am>54BBd((ifnz#e}Q{lg> z3P)xX>-MxPa*vCVYdgq!M6dK(3m0cd{n$?U*b!)fxKXVKKnFZo?Ar1PUAnGUb`zOM ze9%JIvPO~nY{-D}yquv+yVY?2yuBekk*{~|mT7}$Z6uz>Nw0ubvpchxwb1)S>lGmD zDPpW6Hz?EZNB5Cutdb;0dPHLKa zUAC)a_UVRe*shYoY*$Ixu9B|Hb~SbKKVCO`%60S#n5y>*nEE-r0vzTTtyjQ0Q$k(> zv?8+RI&$`eb_CWLz`Cp(o<1*MQ)oo!&FB^I_zlvT=sw|e_Cvi_z_sYJ2-*<;!_l7f z1?WL!Qh6so_nkGz<;lC@uhM!2)aktfG@VuN6%f3Kd~0M}=@rld&MXthYP|v~^!(F# z@R9Dl0{rv}co{p-N4u>hTCaewMkGrf_4V}%h`p*;fZ@CS0r|OSrauG^d=Osv0Q@pk zlly|yrsKKto4_E}umK8s_Y#a-7vd*=(V5x;#MHsW`58}U1zV@8+F2fLkrX4Pw)dlve&jvX>*O(8wL$8iRZiRnnUa5gqQT^7AHrDo=xC!U$PN@QKm zGb`tzrStK_qoQ_wXnSYS41A}YJrQ{e*_+i)Wd?SyZFfI4+S{}|GWne^mCcOq(|l+y zy={t@#|)m?&+6Z*+VhZa^R`V;qDQ5^T~n>DsTsIpV6xaLPZqA3xm6vMH{D#jXlte; zI2IfUQIbg$S^T518PrkEZz?1K8hY9QR_EW%)4|n9dQul( zntd2K!MlL_-X&)ISyfr`d-fc8B_(aZD_dKmrA_L{h)?D$@`?1%2k zj2u4$RyP7C@}ArG5)W$R_~rBdLc_BYI?{#q0*bQJIGanw0jD)Or`)9GJFy zeo=S2mH!LCZQfmnPFulA@k@czS*l$-KaSBe*a=;U&GaDiY^g7wc_(8QfBRR9Li^$y zUHjr?@+R09nID(_jGkMz;%8UvJpFR;qth=Uubjj-u{xq`rWYIK-M0?%7L!|9ynNdR z*-xXFE?B&#@Xp02@rUzVo5ZR+=MLCV&E91X%$`eaHk9K8t%Q$ak3w zKlpltvh(%`C4CJ0`)91L_3!F-q0`)Z)}D6VbL{kj5sFuOZssxHOVl@8$o_tgHJpS# zKW2Y_Mc!rk%U%0>A?rE0WZ~jh*x$n#FO+|yX!$pl)Gx0R8!OM|7`QtwE5yb+>Q|3V~FK}GLI%amk@zo7-zkBJz#kGZZEgnQ{2ls1m%o#B- zdEfzAZT7V<#DrvU4&&%5Ov9_$`c|{6)zLMIuVsn;SFnQQk z*qc##*pXeVC5iQCQ7d2K#*F*I?~#5>qSxi2UoBva`QYGX`jC9|H{@BK_Z5!Hn8KML zzkMIx8l;xGpWml3M=P~IRDES!XGR8DN(MRF&Ssf7E-gN#z+Xa6~MsQPvYa~j%O#=gx>zx5#0H5 zNB{KMz*6=ad>TF<(~ZwxuGKF0$nO^H;=+Dzlb*Abn(H-Xf8m z6#8BCdp;>Z+*6TKk^UF-giuVF&EHH8e~lJjlH{NA+-K{>4sa`<6IrADmipU=I#=`E z!WfoFcc=7;x`16me#_x{E3q7D1F4_9an51U`QI>E?9xvFS{W;TI4dx)?x{=)4p8nc z2L8mq6_4W6x5B*^8%RS7ddOaDM|!e4#506mSXDz_7$?0Pv{)}I{T`AzmtOl>(nk8B zdx-B`HhH|~FRU@ZUh*q1q&FfnV8?V_FmFf_+p(2iX|n&EyEi6{XUyZo-C(y}T;#eJg8<)%d(1^A@~Xk<>&CsN?4YOBV1OJtb=#tJIPLY$KX26urc^yRrtGr{@pE zMHV0*RGO{CXTpXW2lD^ zn>Xo!s9D62ddDuWC^}+J^4Gn!F^K>|sbe0M2rOnWUf`HJvt>B@SIccu7D=AAg&54^ zuT1hyHM_S<--gz5?%^|ERTkxP-xhr1xyTCApGM@DX7=uUc*qnJadpIoDd1D&IkDqR zY0uASBPWG-wr8pF#lqWUetB*#d!>VYVZ7e~;@!@3#_t1$2E5WHr+N0j?yi@3CW&J* zaPHs-_{CFE<&@|*j8JpZ~G{A#}sOxzF->S34EX43G~4|%004grFQ4P zlG_|eb~jL8VUg$nEyEx5rLrEep^6+E7|DK;_3(_Wr{x~KcO^cPBlpk~?@o7T8_!pu zf65sV8e8&?EdF0J_ECNpTnn8XV-NmsfyF;R;8Vb}(Np?o+}F%~4kfv5*PYZH-f?NY z$g$FMj`+%A3v~heyq3MRcE5XRQvdajWaC2*+@p-S4_cO7gNyKWgQkR@TFKQAdTIo3 zJ;ADi+=rW?qqm8r7CI7JOmB4L2WH*rD4cEz!srIu0X6wA(@sx$qA~wTw37iZykc(+ zyi7j^?K}+a9OK*(`U!k5L_24#*!;l#^Wa3evK=Y z_B~RLj?Bt zg~XQ#FU0=eg)JT$X?N+i z_}9f2FJ}XD#K6xj+#djTviGqum$dNSvY(8;_kr6U?CJ-r^#kp;52YWdz&?C`^@Uc1 zrb2ruv8@?-IrFtk>%YTXv0|$QZ(=VpaA(+#4BUm=jvBySciT}oU%DJ$_<6RY|9`|6 z3hqQMFmPw^Wx<`unZlb5+=bgs4LfZ(?6h94!~|#ed0|}my~1xrMhm~!m`COi*+S;I z58G@{Yati!rq&|))^6na@OKfrl}=oeoD~w|I@o_VdDtRnh%8%(KP~*M z=)U$sXia_>x|4N_tSjflqnr~`4_eL$8FL6@ihR`5I}!76lkb$+CO+|lRzkM){8N*|p%cvcZIT^i?)$f4PMhVyuf znq)U*0}JPz!Q(?U7_P3-vO(5$1M-2qkI+bO@XsKTdFZ{tRZ>ojw39!u2i&CinJ^a>d8}ohEX%Bv)xl9l1z+%J|2(U0RP#nfnL(--!8a{n2^u%%`Y_ zAm^aiRtvZmFze?AXWRdw?cL*}uCM(6&u1pcXJ(R+gj^t?L$GKvfQoWSs%|D|w;=%) zq!-=oCTQJGGJu9vD^^GX+9nx52eqt8+XSt<$zZHn=#p-`T&(>DqgJG~mwoJ)i?&S| zE`p*7it~HEJ~M-XLTmTi-yie%%*^L~J?Fg7Iq!4M`@Hv2{(LqV*^sZ!iNj9qYwc<7 zf@QC1%$|0m&@-dWpW8h_mT5j9CGm{X7NNx(%l`RC7<* zPkFEZ1F?}atC7Dw{MP##-k)n777{b4HK-VlBn?;pjeWiHYdnr!X$!VX-3>3Amb_3b zP5)DmENFjnR9)cO$g-xDoo%_N?%30NzxQVBGoiQGXK8&6GN0tw4kUD>KexUlZ&Z&M zqEA;ZwINGm`sD)GIO$o+kF5He|9(2Lv7fSy#99?EQr*WsZQs<>T-3kx$Fuo?;@@2O zFbbFF-8|(MBMZDwcj32~n`%s7W4f*sU!KCb!Df6No%kCM;sF#om+jL8CuxMV3#|KTfe8qd!5oeK)GlTgRE2{S_o%CAk zO)L7^4uYRraFh0N^`6Lz2>0^dvFFAaqsFaW?!7r?rUxD1=m!pC#u|q)Gj*kZJ+_uD z*fQroj16moO~1y%=lGq;Sf)8#mB*c~%DYx%v}InhyEWsIH(E>a+hsV6tYgI7PjO6f zuQ4-xve!(0D6}AzPjvp)WryZ>EYqHP&I-@CsjlYH_zQy;z7W}d4ic-^&HqI%BeUDJ z)_zxmFG2T89T{;$<=m@QFSrr={7u}c^-5XlxQZ2{#yxzkd2>bCTu*G;RdxNebCfX! zSERM=#g3%d|0Vb{yUp~9sg^M_jd5eQudE?PN%p$tvW%MtMmLk|(^YvBeH4~Gw!n9d zV$D02wZyh9i{h`H0?gM4=0(;x-?!H;c=m}W7Fa8CMn^u{woI^J_e9S!_X_v85b&P@ z{N30&=ivvgT~ryWnDlCE1vc{v{1Z#>sO)={-uWJea~L(jNK#F=HK9QdtL+n zd(AZ4KX8ySmaa9XaUP+vmb-}+H(0U4ym=9Fz2Y8kmh9rhJ}REoC%gDxf-N>t8@7tM z7cS*%tD>)pNiF%Z$No9EZ(^=ZxUw;3haCG`b#~9lEqVzjj(nK6`88 z8C@Rk`1DQSj+r=(|MT|>hEfV*Sv}^zI(;!(ULXOXlvT4;_y-adyUVu-`zF%D(}+q zlM^FYdHG5Ye)9CnD^|YTHhE=Vn{TDN?WmctDL5n4`VRi_3f5GR=MkQ6hdUB9(<8t) z+zl*>7<=>X`X3&5PW3%vVpG5uUR3aE>(Ujjwi{RMYOCS1+Z?s&=mQN|m(6Hy9T@uF z8#T2*Io@^mp5x79-afvI_eG~ZzvuFjQR9|QdZU%N-rz3ulNdCcf{$lHzW?MteC3<= zKJkXu(&RPI9iM#Qwd0}XCyx7A=TlaA+UDKiU%w4s)he^{q;fw)CvU8YhTmWf9-q7Q zzm9LZ=%wSS5A_`nMUNdnG=CrUJZ)25FFz{(y^H+!qOmQ&=`Ge20m|qFX_X6B>~32& zC$p{WlI^VpAB~(fe??~7f{CxTPUAN*1d$9!R^%?XvE_H@EN8E!B!0DyTEKY{ms(50 z@mz2m0>@KWW6x-9orPo13a$5)o9BY(Ab9G=rn4AYnL90gTrDtPcdaq{8Sditn(32e z`#kEjD&K()j)KdZpo1j7Ut5teuABYVwBOx1cx2u>4|oIDscqPmDyOb|wQb7ESK1Dn zX`9v%+puX;U#sFO)^G<>5WaKdkB%3XnC{BZujYo}1IL4`=irLh+SdJc?&-B1nzAXf_GP(#k;SAh9U_%^+BgT=(Ghot-+_ec!j%d>S;Qy zIO)X4>Pyh+!33Q~5_H;9h!#ihunbeHbY^ryhr&XqWLskR@#z&s5i| zc6rH?C^$TXj~U)}9Nu<(3O?q^l$$)F?@{<#RD7*^T660~vrZ&v$~eDY~<6G-uTYo*LWLKbrgV{@oFNix}gs;EXQg*u&Q} ztv139|Il#lHm7&%z{R7w`Z=r9f3X>M(}wIVV@7aK&ee{dhLH`|#vV0$1~#R19mF@c zZ}mgh#G*#e+g@YnUG&$1iQJP5P0sm-Z>y_u*P{#Jvljkx{L_)iCg<((tKt{lZO3x6 z9>yX=<=bu|_Pv+;pw6zZyS?M}N1v`ANYvlS9rM}LXH%8kzSB5nVc&gXRa0wWY~`Nv zCS%J4&iK!{;NuM)t8)f>R_6|uI* z`o9&A>*)VR!X^lOwf~UaNAJAw>it>lkMQ3M7X7P%17-e^cJ5(cp!oS5#w5G@={B($ zLvLI9v42_cw0*$#bep_WoBgyoK$}Cn6HL*)GY9ZLs_f@9MlW`26FW2bUBhoZ@g@2G zPVdl{-y<&`?JVPN#PA?|rPOI0bD2-H4&)g_kB_%z>UWp3YO9<7I-Oq}JhZ8-=g8Hw zd**ScF}U$mZ1ng1!c6tdGt)fv=pA?MSeu`T55LrbT-II>f6&v+%ggVz;7)Vf$ZzPs zQgHkl%7>lJ9k-2Qyw+mv5g1CRc{W ze4P1|Ii6@e;Pm<4LRUTpd|z1og~8cIx@X@W`9ab>1u6caxB34i#=p&Q*?E@g%@M&M zbd^buWtPV@3$Fl``xz0yT9k%C13vMt$(!NrQ7dfiFXg7gN^+19b129q=cq9 zMn(NWQ0)0K~ci#Qz$mwocV4#RVna0^|Sz*zWxQSbjsTD55ux)Q9D z^hta}p6GKoVD)Pp!UJ&;q zO);&$c6>k=^ShGuoL)w3-{BSOpW#gLQTV0LObr$BpU!R^Er_4pn1HXS2;L)K5wsZH zcauR5|5VN-xFhxWwnYQ%VU7(r+ixv0xql0NE0uliL0~tBHG*88KZmtkj?Yp2=v_Wt zj8AfXF8xaX^Wt-!TC;d-_q z+G|PWl4Y!E-)>dxPyoIx`TPNM{xb8mpvmFmEn&PL=x#@7a67uH=CmK$@{J&-j$A@D zBmF~#HM6+G^^1eOAIEI?iKp4{8wR^6HNmZG?%3M)1hAV@GuejSEvI5>S+?~6?@JTBpgr-f z0Ge^!x@hYHM^@;l>4+RPv!b`pLYK#%*m*Vlj`v5|qc5P{Do0xI5OaGTKR7n|q2}w1 z@Jv49S4|gl@1XhZ)-Ryr4#2zE{Dn_C@r~2xba*fK%(dPOUJhQ2jKyaz{Pbe08zAmN zG*<+UPhvCM;lSqvu9C3Y2``8wV0FY<))RfStjA@#r58j0JfQ!Z7-JuwREMXsoi(wB zIG1+d6@gzr4}6ZpLtitqJV)#OLu)Db8ocX@iYr3LZV7J9BJQQikr^x?rX|Qb*2w&f zEMvFodsr8onGEg+meSc|hd%7g@S%(Q^gsD*7RsJc@lwmJYn}d{(38Z_B;*U{s~BHe z@CxLKm4?q-^*D=(ZsgIyRY%?^S6F&tJce2BPj#o z^}b18UqU|o-WU-oF!HcNj)=a+eWax+#<4=4k^uz|RPTw)owy88oRJNShgxp^DYUM! zqMIG-hgWgGl;=y>K3%M{DsxP*tM;?SoTcMjno;NDsWn%a;8~)VbFR6XAGWm)TXR4D zEBV!Dp(*@tL&N(K->y7+ZJ(o`gXllQ`QmW-F1|SM)QvV@+`rlwQa_^Ou?J(DMc?|~ zIS|_{Iu}n??k>^#pY*%rhiz@c=BIie{xLS)2QN(a?f7GC;l4chq2kVHLw#Qktlz!) zx-P->`qV`98+3_Yp5iUiC1#7a7;)ZGN*T#pbkgkpUlacbpJ^H<&juLFr;%rS zppS$9{R!-3%kBR~LYBbyZM(la%X3Z3BiM;2OD7zS z&aD^>!7q)yYv@w*>)9FGT!>viz%!{I6v10QO@Di~pGk{?=h?Ja^pxL*K>@N@{SDy*EQOCw zO~|cz@5dJ22+k#^L|ey9SEb~Z;Hf=*8E`H=t;fb?*93Hj?YC5)Q+5GQTXq?S5n2F! z;UJGbMV_-N=&On6KH6IVePM%|?@iFxw^=Weo7+>2nLkM3F5k}>b!Etq0C1QyvSERA z3D>Txij^N&d#hdSyMny)VJBV8nd)}#mt7=Z0r#oB>^A1>-TTC}PX)Jnzl|7U_+#c` z-cOO=jQ1{+bNbXPBSyc7Hlgj38CJ%u0Q*1L#{!1Yb33$vjUe;1F2WdOS5{1ta$MlYZ^mRpM45`UCCV2{}=jfHESiQ&&uu+xb)05GhElxnh8Lw zS~E4k(2gB|uH?%ZLtWXIJMdFAvG**m_pf*T%*gDj#UDZ(@(Fwc!_UUV*P&u0<37Q7 z%ybSgc-)SeX04)!=2xC{DrUs!*~k19N8&ZCs2@6aM(}H~F8igICjR@li~peA{?VWO zH^hG(&~@^z@e};UZt-X1JN_Jg?Y#&4j^w@>8}Vb3mHqIG=uAKPH{v?J*0N;gGsur_ zbT#Fps$TWWN2TvyUbA%TT`NYl)vfqNTgL3^n_l2KZDzQ2BmX@-=Lc=eKCa#~an_-@*XP~vy}oQJ+S?7lceTH(q^-1%VtLwEOowmW&Dj5iv4|h5-`bC2n}_dB zcCxO{)~}PgzV4-crvKv&iZhq~`Nw~Y$B;L2o5fp?eipZum4AL%=i0a`zf#8ds5e7DP=MMKL( zFK5xvl5@~dAVEX@j3G&Dx2qg}yU~xxuliru#7x^JR`>vR3Il%C0sTJTXy>dd%4zag zHRG~;=z^{eqo*1hq+$XJM;e-&f^HR9*@?5!P3p9Cdapr4RD^_6MK7 z;lT(0?S`kqiI_+5H1(SC>0WGo?_qzfhHs{useMyisiBA2`;imm*n5-u@{bn0oPQL3 znVf*Whv9G9k8VbO*Rqzi{*(LB05WyBFSh2%xV*9bnb3{iy?3Kx8+OL?SFIkwdCClI zika9Hv#=?S#-^AJ{BnR_3g;?~$f6WuI{CqT(!q6R!@}3q?#K;xGll@L>PpbJc!uaZ zIR??T_=?S^cqjTEq<`ry?OEg<7-bH6A2oVrBU>~s_O6_r_yYYeWE?j$o&}6+K4ZP9 zE4F$>xCOdZf64XqY5G%NI`dKgq|x)|+Lmp&|8_GRTxEpa1?V6v9iwxwGgv#Ym0n8x z!w(!?wL6XQyT5jJ4URH~`ZpO}iU%;EXRXJ9mFDOeaU#3OCDD)mIq)U!t3QIx(==YM zz!vLWVRStp7`Uj5{&Wy|qP(*P_!fQXPKE*EO+UKY7{ZP@Y-DW(Y+c@_U*~14hq1SHa+JJ3k4bMg3RsHJxnP20hANAQ{x5hwv%5M zKC!TAK6HFkIl(!f=`Z%K0v;bChV|<1;!TTm2bcn`v(Jl zL;H#)-j|r?HV64wr9UyR#hs@%d~`Kumw=!8xrf-2rmNao+c~@0Kg$?O#vq(6!|d{u zIdrKp)Px+XCkD;}Uz?DzQDpo(z+G|y`+P*_P?sPhmrgTw>ujCku3DB~vDMf3@}oMJ zdKCD*mZ@AKnb?=oqTAsa>{r8H@*;^xNMGCM%!mkQ+H1<@s90^;6SU8h?)HZhE7xE7 z{>t@#bfy#E;fd@^*?Udn1v{=Wtd1KDzp>P@edA@u_Ki!w$a&>FJ{4x}rXqZcw;Oqz zzIe@;8)i>m)mmnL?R##%7hK54aBniEH?%%&>MVv z@L#OEB%HQ6#s%l0?;HYt(}2@qFXzTQ#(c$kFRk}K+OX^D&=rnxmEG7l)@K^K$N1&b z8Ra|R9LF{mKhiA|Ps5aTpBV(M1u4e-Qrew{O}U!fF^0q8;p{;$0&m=BdMYpG{De2v zsJjg~zYXjzr=7RqM+lejgM1#pf8~1Zi9hC}ocXfZ%BCwkY`Aab`fu-=7W$c)L)__@ zhyl!ZoCD^!0Kd^T%*Wa=|BiF?rdxpXAE$ro44D5Mm_I%Jq1IcSV{MrK-&x;l{eWC; zahT@=c>9(l*1YFyHi3Bx}2fgozBXKuJ>=f;Ad4^UwYta zU=F^7>lAcgV6K?KcY&?;|E?|V`R`v!4xle_w9-}fvtdD)*RO?*)UH8&^jhtuzzA61Kgj|m~ za%;E$h8#>zbim)l_eb_QIL7oRdv)a38gkh^me{Y0j^2ASc80u~_~xI+%q8U&xX)Yt zhmSX0{ritMoYof@pZG*l=KnKelHAB$cWT2l%AGIY!&pnPm1aabfZ`kr`R(KTWOJ;& zZ`B@^{n)}QxN8S^o@FB&8?2T8oH-tLmiW?^683jd=6@ZhQNcQ+r8krrBPy8GJU=iNMyU|Vl&wB^KZU3j^?I)hKmiLmg zI+x5jy2=)wm#tX2r-=2k1bN1okKM>VfILrqYt2!iXHL~WIu9LxKYboH27gq3OU+h~ z(XgI)p-lnyxj$o0<;#nJ$5J zZmvm0whGu-Hmo5Z`;BddD`Gk7MvZyyOKe2j8xHF1oqvl3lGu zX~fy^PIVjZ@4u$n(QvK!h04Eo<0tc09<~p$bDa9d&+YvZd^qT4?KkCGA;a8$EpgO6 zsvDr*ajk{x;%ngqF%)*bW!8aY&e^f`KIKmQU&hw2fwl)OHo`5$)i)7eUptZ*RMQno zW9=3|m){?Ml5m&1dOkQ3xC?jU)Vydb)xGej;B^xOF{ zbPdHq1^K;r8Zn{E7vFaX-Zd?e8)P2w(T9jvdG(@(1-vJ>@N~51Yq)Ja1>sE~f7#^p#5AhjgDdeb&4ko&QZI z@55!o?gH&(Z&;qV3v?>@Q9h4$+P{wf&y~w#3G?n|-pb|COuG*!`bp+Ixon!J?GSsd zXXz(B(T{R@l*1>B=*M-;TdbH$%|)6a77P?l4HT+4*c)Uw?Bte$rpmawTWRxlhGf;eRx8!TITU6MBH(Ch-y?iylY7q55*+P!@^ z?fMe5TPNCm3ZLR3`hs?|7SmrXidLV z>)rzAiro&wxQ3QrqM6{b@BG6X_PZL zz1%Aumm}9(S>%5AWdo@|rWwFMFcZl(jg&tTWECn}+NlgJU$3hgRQ_Ml#{HC|Z|wh{><2!w$N!QoZx!!&K3zk4gvRV< z%+f2cy>I>x=vDfv8~uU}z~(s{IgE2(^@!Cj{4uoFFD8s$~*TAs2iKf}8gVy7$WF1#7LT2N=CLf87& zch?4sCkKPY#QatqcBcBcgK2umQ9P^9amB1qO5vb>?SWUhXuOj^E+fPS*|BdMJb4#&^)^_QtxWhIopGH}RBS)yI>V zX-@_7)EsXmPIgd!yEJSG(2)x~=^n(}#7CWZL5>G+-W%AHnIwXfntkuL4lOwnZ59%iImSB zi9MNTk`8~yTvRt7IJmF_X$-DZd^xn)@67kj@fcYa{dd*|iruu;Pu$o5YrNJdp4HED zfZy90tDCy64x=jqEX&i%2ImwA?qi}ilmDd}+#A@!3+R_vh42{D7_uneOFcb1g;(le zPv2ciozcWMiC%K4BYS{wp!0W09Q+U*d|NokhfZ0m9SJ(sdOjP@qZ4q3&kkkVI?DNV z_CFUhExS;G;UCJW#_kP29b;i@appvocPr2Mc)e&?bSnGH1ay$Q@u!Sm?JpUJjbFT1 zvZ4tbe8*vwv{7HSd)a{R$BxtN$nTqZ>iS3VkB5Dy9@tZ18C&q7_PK#OYalwOvAOkN z^a1kfxuYf1Hnjd0cooJT*n?eX%Y>s3?3wW4Df|4V;ACawa_3ZjbbzspH;s~UBa9*0 z=38bPyBi#PuZg157L^&hb+2=knU5@Kzovk-bhlzG%J6Aqj1ARrk4Y`E_HOzSkN)

CGX|^CDtperg`;E;JVA`i#xvIg9Zo{K5Cyw-$UoYkUYEAAOO1$T;=_ zk~ab1s(Zxl<2>UKALZP6i#_Ev!(bBzKSTX_bTV6eCk^NpocXfIYa)(p;ge7i!wD?<3b0ilL~xQE=c*Q zl$}D^Dr`DwJa2>63VB~kIq66q>S3SH6n*)4e+_W#r(O-8O?)&So&6*JAxNGu_y&1~ z;JF9Mze64XJO7&A9nijsu}1l?lTW!bK3{-JramC9!o<5C+Mi`o!O=kVUc$Hn_fJ{Ijk z=RWz=G;Xas!;0UdYNQf-O8d57i>KiEB5hjGyVo2Y?EqG^RZ`FYk{_C{#z@;GF7yDw zuLiieSu^*sR>@%$-3kAV(w2Khu<)2SnYp zC%wXjeM0T$nHyT&tG$CR+Lb;-&hm(tbN&s~5pG=IHi;KY_@j2YPz%Q)-WuLu=STfCTj+59f#%Rxzd8teVv|!ht zDxEn8dID}E%8CVV!6^?sOaX4PqYI9@t90i9?j|$6#Xj2f0W(iy)u6l4J2;s(wZAkN zr{<<{fBZ4IoSFLt{IBN|`$o>3&v;zQm1<^$Tez!X^76oa6`aNLo8C7&>0k69*dAcr ziv~qgqGj3rv_|GIX82=vV0OH$;Gy!jagMG^>j1tHV2x;f#h|rC!0NVD@iXRcF~{@q zuPbRYS@!mw@$yr_k3FWH@jhmMhPHPm=$tVH_`h})>--|dcadP}wt0u+V(hK6!P6>u z0`F?6vzRmEUhq?sYYZ)>?12K-tHZ`+iTs)Pr%P&V9l{-4Oql}{;`0wM@7meCW9|Xo zn~YOycM0taR_?Uf#oL(wllU^K%(S3mEPXTo#ZSgz@C#s2@5qi;i=Tdu{G>eHE@QXO zw#hD|xZYoY%iZ8_F}fGJ<}ukw(rC~2F@ty3QFJm--9fgLGjmIZ>VNne`9$}!juvO7 zg`fq_^rc2PPg!y-t&Dq5GJ_eb!uf}$t!aIA+S*ph6}?-U<+1N=QS9$i>}7XDKW^Ub zOVl+}RoA3$V}9xtYg)Uft#4IXC$<^RdqxzKv4%R#GkTN5D47dPCKHo;CF6R5F?BPx zZpO7ZD=V~(u~p(PRlkRwSrN5!fZs1ci#DB*dvyRf3bviJB^s**rdk72)|L$xnsJ^j zez}TsN1~~d@Bz_PkUBMtTku}RnU_PfQw0t})LX~?qNUMWytcq7VPiP7j&^S2Jg9J@ zx;4}dQWrV5$Kp8|*iQlW@EZC4@b|lrkM77}^j{Zv;*J`7UHZV6eA$QTE1i1BD0c;O zyE0uc%K~QW^NX%*ZhdXq!>yMCqvvRMFEa86w0)SeYrs)gW_sv#U?e{{Iz{*wz$~47 zrov+g*r+}3xrt~Uw;-G0F;N59uXR)vUv7@>TeqrekTp?qn7Z7vckD9S4mrHVYgTy& zJ>X#zbDBaMLB<_qymx}{BmCYA|8U^Xn98``VJrjm!JRon>A+(YIEk=w#)7iGosv@b+n42joW3EZO8U&1@( zMO7WUE!tQ@nZ?wXthLt;ZPctXN}8!(%cq9-EqrQriuYzmKLds&R z^@*40dkt+spTSkkYYuJH@(I$H#^U2Mm+zJIsWOXsYF`!~7jxvD#^B~Nh3}IS<>sm! z@N&_Xl}0XGo<+QO^KtRc$A|nq_Ssv5y}jVge!_m95u0WheMucxI<)jz_P7gexi>At z*56tr`-a^W*u)yEaU}E#@~ey1n^{{;thuD@Yi6B2&-??kkvo(PQO7G7peNN!KSZ|; zz-OA#se{z7wc+=tvSK3osx2#s$qiC|@sn}hbSLGLGH^BPUpff>%?*zZ`#&ig|C#^o zG4D*sM&z$#qsH9Kn9n5}LyX@6Ukft+KPwyImzrN-HtYOcvXOBMK7kA3vQc_vQa;u& zR>9%`un>O_(neDPj_2a<;$5qdb%I+hZL0i*v|+=C{l#D6?OHp6q3Vj4c&V$giBHw? zTYO4*awYgwJ^0dCb>`g06J=T$pAWi6hl5|iL-^=S%-@PvRWnBMD%ph6Xjd`>ew+CW zJgdIIsOyApZHGRmoWZ+NBkc*^C7zDnU($}eOY$zo4&3QT5AB6_y#wz$4DWge-ZcT< zbr|0D8oW#8#k-bJt{dL<7Q9Qi8Xl)uNS|KuQ_ioRK_uU_x{pcKLUdX2yHS!&BCqZBI-IXsW2Pb^U-kYO`MJ;04u9?=< zIv!i19k=G<%qB5wB_EvHAb%vhEc*lG(gDtK%D$(Vgy~L4=z+(L$GCqWat}D1P8seg zisX9oL-BITW99Yzn)@G?QO@#c?--XAikB#T-Z-W>KA&?8@fqW6+w^MjCHAmsv{8hQ z&qpku&MOMO=wW>`_&ftFr?Q9Hn26QrZZvi`605O>r(!kU#I6jVi*}&}dX;Y|3ZaT87J&gKIwC@c944V{uM?%_NTV%)4jh zLo%?F4!lp^Bp)#wob%Ei-c%>Qu9N)3qFe7`sRm>!3kQ!1<2Y( zrj4IN4x?`kwAGFeK=@JKh*8vI&4d>pUb%kVu@!sXK^Nst!oK$%>3v7ajNM1!m;1qw z&d(hMFFU}`Ydr4)KbD!s-Z|Bd3GKs1E_=CWt#@!EI<@Afv2jmNq$y%_HKXI-!}vvW zpZQ)q4r;g!{p8ma;~Tf3KLk#$uyOKJVrxxed*l9+?BDpwHDyGI<&ACxo{F(~3?8N5 z2J-E3*2?3t*yav+>)*Yh+;ce*7kz!e`n#L)RA>2z?gswY^f!OleQJaLd(R$Ic0~Wn z_wfFgG>#WLKm2ao7m@rO_eK0y*Spv|PdSOJ6<71rLXOHD)?e}ueyvrEVXK}Vc>re6UE%S_w`p+6Y z0miF%xmxVuJAj+y;n{hk7I8LNbpn%&4C3gbcT>l%OC83!FwXDJ%sr=ZyPolPp`S%> zgZA8vQE`5SNDR=i?f-XI^1m%9ow+~0R}vBwB|isQZu*=aPk zdde@NzRI~y#4^;*Wa`c3<0_;M{dmS;1EQYJa$dImTW=@^tCDisBNFU-e3Y3Q!gm{v zF&^n&H|jU%xeeo&{li}xpE+!N)~6qz z=llMyQqyCvQHwQd(>Am&`qte&bJ2;qxgV+>S|*QK%lDt~pIijpYP~h+3H=uEWPcxS zr=3)2#{sQd+{59eOc~$H!C`VuKJ(jHMiDgXhMq-hT9=~f;WVfHP?G)%X;(brFfp|% zU&*J4|3oKqf6e-)9krqQYA0DQxz648{M^xr*c&~}&mwlonv)S0A3DVSxN1u}lj7>fJs)|XLglP|&D&)E zF?`;KcK>zrPV$=oZ6^86<>D{&8KY16)b7-8-k*!#5KDEM-)!f*_>CW3KgnE+BLzSAF!&Rv+L!F( znRjCu7JN8~YsC{T2cIp>h1@`)WV!C+;1ho2OYkuLpX6a{bBqk-)DRC#mS?Y?q53Mr z2HNKFX%pgfhP$e})bnP(sjnSZKVR{V~qAagXSEcw~K}StlK-d|2HpsQWTLBy!|L zn;Bn{-iXEPOVZmf9MBhX`D|HcvagE)yAGZYGnOmB!6EEj-V2Q9Z)croOxD{mn}>^k z2hkS-K1Y}M_;1j^%8>)fImkY!90k8bCd@GNYj9EvlaK{7dhyXML%B%X8=>*p)rl zR^5{vU2z@o{IMiSU9cq4-;bdg<{uqkz267jS?Gpt(L20ay!*fL=`PPF&fGCB`VGe1 z1%JqPjtezmj}Y(Lh^;_!Te_v-`jfEn*xl%o6Ud<$aDJjo&eWKh`~AQ!034(T_|d^M zC-OIBS0OVD`m1`}sH@iVA$;TX)l2_F&Y6+-9OTfsD1JBl?bt&M?ssKl{Z_Q!I6K+0l&6@k>+n;n<{h~q4&UJ}q9bKZi{x@S8mopB1FZ_8d z;~wxSJPN;mukksvLj#WNJ~z1wRL1jCEJHjf@NaP)t(I~@=-?X4a>oAHYTchmtVih< z^aH*NcSYb%zc-TK@t5i7f8a-W>Pa_t=MTe^bjfnye;QxpG#v-N8YU9|W{i!NPo!<| zRtny<2k2rit9IOhKyd_rq~IdnD!;$%)bjhOYyoARj8A3tTRc(zGnZjuTfoQY1@6#5 z=|jMacN*&sd;>1dl}H|{jC@RX8DP2}e}Lv?@!o|lOCFRyVzYO1%-BSk9cG>ON5KmdWga(exm?H?;&acARKtG)jNu7j;Lp)M0$5{X z60WiPgaluWzw?{1jPEl}@r*^{Icf3!Y~H~*tKcmg>8ptGm5yM%e7D~*zN-1m2O242 zTzaSdp-s1pOYQB4CVH_kXpgM^)^V=gUL*9E18>n-ll$*G8D}Bmi{nc4F{ZC6fuokj zIF6zb_%yiFJ>&Nb!%=cSuK5ON`_u3o;+f9NbGUQL<~hmzrg%V~!)@~b$(=wX&I5XX z6wAn@KOZ>Py4IQ&U(0KPU6g39SyZEh{d|gzIKUPRIkg?Deq(9UER1Oat$U`3hIktM$J8 z+p!Fle;IpZ^1Wn0a_^nITR`)Rt&ZPk{1JD7o&4Gb*h@!ZGqbSKxrk{tZT=VNAD^Ln z0yyL9vu?Rre57@&_Kmp1KCzbqVpz*m8DvBX4iu`wt#6=Re0jF;-*LrCqr;f3G<;xSf7v z&!|A2)LO=LUs~DV!Bep7mL*ma$nlYB(O7A-~({dRyZA zl+*Q|ryqQ7rDN&;7<3G66y0%2Saxmg0YhoV=DG2^v35TLE~fH*9k_THTCVct@_m-3Q4-GwaOA9AAI4@>_7y6& zKJ&kslgg>iEb5BSXl;BBoDzR^8mGnjAAHC2r4)uoFh}D8V~hUV!I~?`m>f35S4N!v z@1261#)mSFon9y5(YDH+1LSo50}|zApiXOTpnbaM(93M6SQdHV!#Ul2=F@z58M_wD!rh z=97HVm^Lsb;f*|!zV~jN10O1fAAKIa^!Mc9_#Ae8?lN5+zst1LVx6-$D$V8z{;+$M zSkSE(eMUNi_^AE6Cr;Pmi~X;R&w&0ODO&zn=uc-aID5v}KP~-oc@~)Mg$Fe9erl?} zWZv>6Teq1hbq02Ub@W*Ue6NGnuLvwH_8#HBZD4-W^1HTr9VzxYNy|#}Y{QQYFI`Bk zm~fSm9^DAv{0y*COi&vBHPOHJSKH9Z3yk#8(SL8xCr54{xy9Y}BaFK5kM-aG{jnAI z?*MNTPsX-PqWrT1tp6fon$}tO4rBgOjfLD2;_ZpC)OD~PGY=Z`OMS+)i}}C1%r#DB zH6G;2>G3o&o+HF@?1T0+#{bK6Ho3lEWe-Vih{z^r_1Q*eX1z_T-0uyomQi1RXoEe< z>=XFLfTx$WEC26sd?fLtxQe7N=>Tw+9w|NG|E@*9Bz`{tzY(3|UkyutdY3&7?L`&i zP|MvQRp96lyrZfyzTZ}ybyYKd2F4*iQ1xA-ZoAD}_`eRCX1?e%Va0vw315lM=0B}1 zFTVSI?BTtXE6izbbF!hh z^LqGph&@sly2cvzx9#)L>-kNd{1W^39B7A_sb`QA_HT4`oe5XF*Z_z+&w!4n8^!YgVt3G0RGGj!qddE=%x9qTiZyVC>B8BbURm z2OR8Q7Z@et?bCt7-NZHYD)#1|j1uM94^Xxgol4~bl#?8uK{>@gB+CKIZ1PkvuZ9IP zu4-zn{-^j|PqL4xT#&g0(3|UTHA>`vBWDtMoEsKodd5$Rda7~=^~?~kol@y0p;)$hHBi>-MPDn zHU-n`cuqh^^p59#Na#Uhn4|vq=q#V1F-$VLx*YVK=(m>k1p7|eF$dzdeY+m~RP|h{ zQ)JgE@iGP%V^Ezq+~fZ1Gu9t{4lwUp;+i!F)vu8qpLr}44zTeh+j*6>B%C;aJNiS{ zB$dC*Dsc|_hf->8gD+T-N%ngC&#ocj2F{Kxu`*`&2w(07=$Lit%5d~V%)(h3e+}zf zV~8>q+5QCM8h(2ik9(TYRnHtmNAgoIU*PY;_LNzMY`>2(fh-cF(a`TLFN6xdV6!gIn>`O1`Iz{aMn8e!1PVoz;bkA9E0f#nn4cKy|I9$Au3cX2 z4WlcdE2+)*k!x?>>I?55$yr6(6W@K37^Gi^Z27i1*;YZKtpg*85hK^9ZKsDON)>m8 zJ$Zn0dZo16$oJdf!8zDPs*Su*Bm4YE$XCv|Hoq@^fq&kMo$~hA*ozXJd4FBT^8oddty4!*U9e+BL)fxDT&Ejh0;$`)8gxZD$u1-~6W zREYf*dAM6=o(JGJHRP&sV;h#;dj|H&Iiu(o9YQ+)miYNe=4IJ2$BM@Ya{qcga}x{{ zN22etfh5Q6X1*G;#``kk-3ZP^+t8jJ1KbO3-$>gkm#ov|aNFxa&Kn@C${)6#p$N#acNY&i7b7l+>BwywX2Ha`cAUJtEa$6jT& zecl`z4nIrWjd*APdJ%jjdvYhWwfeyStgi^hxya$Xhz~j~zQyQz8Jf7;IW`oloms50 z#QEC!+n4M(*Ensuhfj*;#UGC_?j(LC&*J#ajtG9;^x4Z=Zhr7V_;OC4a)b9nH=>vO z7(4r@5WeuR>t?~r?8|Xtrv(?1vBE(%bS-#VRm9H$x8eO5RhnaVL}ebOANe3!=tuDG zb&LxMHWofZ4BBDM*9Yuhq<`^jH+E%-}u62EJkAri;Q3`1ZaQ__KlEhO#E>Az5}Kd^VeP@heBdPfA&> zvtOz_`e-gT=H#{KugVK#oZW?)vjgPcm>aH9EzlW&1T#dU6T8FzS?L|hNllH5?IcI_6vJ9Ll<}!&l=?xp{zjVJ@ zCplEw%w7<__NHXa&$GkaRojPLIA$;o#r!@2%@zdjvt`bQ(3oTdca%fJW1^bNAhfp? zJwiOQ2%cmOmoTmV0>Da`#R;`cew1i9$-8! z^u{9W4W;;o7V&!*c#uEt0P}DI&nnhZHQ%ec;jKJ((XQUlh8Fd{0yrthNiX=2-&!!# zIcd9H-YLIGA+YBBt-VGyKR;st4z|s&n6WAkxP0uYI~y3=bu+QevN!F;hM{#br(joW z1brZazm|BJg9iWqjy9{DInnK`!JL}=&sgi^%JaS5jNKJDp1_W!xcuR3MZ7jijK13`S`$oZhco%D1I`Ox;P-K2Uk-}TNPcqXiBEIU9GvXM zMIV-PtQ%fo@3XX?g&Wzc^j&xrU5I~+pJ;vWpsks-p>zAftJb({*tm09uD&5Zh#Lr409Vgu2l&wwa#j9DYwRbNbfeS5b~A?WM6ng?WF>5525o-?^9e z7C{5+uvP5EHf!=-F)71&qUbgUepn>?PGUcyxsjlP^HSc(TGQ;ijDB=pubnf8N1X+c zH_f%JhlwB2xDg2yn@Yy|u92QSL*B(ju*B;nle*S!De`ACpxI)s_^$8@PS^| zT_^lh{!W$Kywd2}#&4Ay!+*BVmN_Knr8xx{a|$q6otV=u>S?SxYe~*#TffZ1w$X9g zwviW6U(><2?lI2>=bx-!*(yF+zr*)m=as36HLU$twmBv=%N%2`U-Df>a`FGYdGAHx z#@c&qd9w=Gd@lhTbbf3W#BTr_`D_Bq%1a8dqiZkP3$I$f%nIMXb7WXLNODgqUFig4 z7oQT3>IXK0i|Uq>dpucJeJAVhW8TU7T2F!@wz){)UaRDKe(QZw|M(GWB6$W}d(>=B+)q3$wH1L$IQte`w^Jz_c#}en%$erwF!?j=F{|@M3EA&$a9bQE{ zKV+?jyB;3* zBr>&zeR!(r3UOAtq@A^F@*nrO^eM;QT6nAcl2;&y#fL9L7U(?iUB`>UU~@IwFB6w?&GE>w9P@hE$tQ6+*4diUmJm!bRO-) zn&H!>$c>kQb1!gS#JjWima<93_j;e4DN&w-(!`!_I%l-DLt9#_+EaZQIB8F1%eaKR z9DW`}`!?B`v_~<4%N*uc%HDYueH*6iWQtdUrWmW_zH=zPuX&p_^*P|6eaoto@&j6t z9LDkg+SZ+kwnR54nX7V!5Aq!D*GS?~<0aM(Uym7`4NX=nK9Tqxi}8A&0Jgx{3fxvK z{#?d)t-;&iW48nEPk7jE#S2cx`EnOL%zcZ$#PtQEq)K&|uj>}0WVp>=uuuN}tsSp> z{@g7|yXhFl`CI9b@Z^cmmh3*g@IZT<^wY@Nm3>)p`pVxu4w~x#{@8gzQmuTdzFuh+b(32dtW*= z?(8HoemBi!6JlGHl!J}g41Mtp5Xuk#LeM>!hWesESVoTO~jobUr%pEBHXc*X;6S|AwxQH>| zhW%IT=37IbPKR;f<9QiamlCfbeWu84$xrGtf0~Q$PtOGj78*--ihpQ^X@=Gyv!&Ap zSvyP6*(2zyc09;SW}Wo(+2+EN4&e1Hd)n8eXKP)ter02kFSDQTalUz`ZN8s-r<8-T zs>Y1_JvXxVqn)Z_)aUuK^iE)^xD@gBs>A4bJR{_Ll0NNYUo8F}0p1(sn`9r*&ia)t za;lM<*eAqok!u~UKAjinM7AhSTe95ZoU44XYD@B5KC1@iIT=5OZHvT*T812%%$~KL zIqgTD+jet!RTusf$!X~s1JLqD`jouDHe}nuq^Dd;yP|vfrBuEh`6AlirS;D|gkRBU z(hg}+zC9sJ9zQKh;`Y~HS($l1m!j3$!J> zeFUCYblJKE3-PtaW%i%af@PTa4V`^^xwA_+)?KCN!ln9q55M6FeC(o~FR_;rToq$e z@5qgo1G@nFigM{K0;Xz1`QO^e|PgAb{PHldcnRN`@cK+Z=cJUzKGbHf{rZv zzgp1;|Iyxa1&hbq|J|YXh~F#IfB$%;{a>}(<3H-YQ!u5_{_h|7ubN!ef#YQ*-fnn5 zHo?GW{X@!&@fI*x^f9?(>EEb!g;%kDwYud0l(U=vVsrsgVI6Da~l`@SpR)Yzr^O~Kg->?Kz9$+rmuU$ zbJ?0V4tkzF9$fnDao^(Cjz^EYdc5|?k>i!?4jtDzvuwHLit0YSRQPlItBf6-^L;37 znt!kzeY?Y~Jh=lJ?H>^zgU+`k$4~(No5nOQc!K{5^BNay;Ay$yweV*-YQ$FIL;%`JvPCOJgw1<3+i|uP!20(kq;kH750(q*gwf`XwXg-eU+&_=+xHn zu&eB#ul>|J{U2pJI1kX9*|^{<{4btx@R0}Y^AH1*#%D;5uMrGQqwXDY?|Zoe*?KzE zTJe0S)e9Vndst}utCZ*H@B@3M)GQusB*!dvqRB~(YzM9&>0%C+K=|eGI zH_-N4*80P&^=+*6!^B9wLcHoC=DzJhW0~-z_#R?1bhnM&w(QOo)T?4%hnUymL|l#5 zUSTG=>8FZ*TBbGS2TY&cPZj-C(@&z0F!5A&Kl`w+ zTGaE>Pe1*j@A%ZN!JPE8ZsHv=dX3m^@Uh!|r0vWTUU7`|y-@MH8+ls)$bNvn-Sk~b z-{tgeT?oHIC)=p?QGK5G*YckBtgoKu{e1L^L=2bun7}#~jrBq&vb$CoFTGKO-4#3B zLD8*uh_eUG(;hqJWs}>;|LR}glWisAz+%^>AiF&H08{Zvq~Q}xXD>Vozja2}sTUn# z?e!%iweOS8@CEwYR)0;`Hs^&~jkML*7>#DP(dgjg@(yFvEzBTKCPIy>p;j=ei#t8@zs`-J9cVK-}@sQKj_WN*4~A2&Ej z9(TVV*Dqc3*>i4WJ;Oh=Rt-IOUcyZB>54=rI z&`b?^c8kDUDR^5%IoG1|ya#WK;33u>=f_(Iwr=T!>Z26ci;q~eCp>J&2O|5Z@Kw$C z2~Qi-bq9;qckPpAxMt#r@B<61@L2Rp*^^{HAK(tPkG#f^Y-dHRjZ)y#KQ8VAs01$+ z_yMX+&p|)`HFKYX+Co>{jap^p>w}bl0@`A5jp1$n%=xYZstyzD)-B$J?w#8+-qUZ-*Js&{?2PUoZq>|n&HR(d*Rmo9!GaSG%Z{U zztY{$)i?6j<|)?^M<$<%%E%9t9AALAKI<`Js&N_yieieL!=eKFQ>R-V#u&U|+e*AZwF_o)aW|y3h<)T<9OF0#@6j$TMK*haRfL3u#ZZdA>EZ5qeVFMFnN& zE^{q#r7gS6r1O-4CmI8>g%g>}>G>UoF33ID1l^0~*_&tfW49IE&qg+BPNkH$*Udxm zSo!2Qv^E?55VPsIpK}Itf0Kgm0-(*ox7mUCRBJ$QAoY}T?LOWybY z%XM8RF8BAKZb;Zl5EJRylU{Wkf122E-oj=w{6DI1x+_BxFD9_H+whaahw+-SgijX9b%=xMwE zCS&*2@F2myg`BQQ*q8H8u-BUP!UuOicl|fG+OnayvCthsiJLdESFq1qnPWo(!22M3 zmAQ0{&%UWorMES*eyGU<9>VvZV5;k@gMy-&akN;FSTn{^?yqH_$K zzbQ!m2hH05QLeF=oZD{2!*G8+5Xf#N)m~Ou(8&2*A1OHYj19&Z-o?Ogqp;sNknNT2Gv z4O@nILqBU%F+$!8&5}Uw>>is}B=Ay`>*$%u_;xXtBF19#3lp6c-Ebaf6@H6vh5Ni- zub6Zd@#tei9>zA0kM^=l(IMIy-z)58H*p3?JfWTONu~;x+V_;;TN6AL1KbIIENnqG z?a+tx+__VY>9=s!bh2=_C?_2Fl(;J+m#T0#f#=z{Lk4DZ-sANm#$3o)rRzrNtB-qX zs}`Geud@Fwzsro%;0kmKUxEgg=lu!Y4G3?*vJl)!4)hWOG>?61_tXjD2sSI>O!o!J zpZy%4UjUcgz$FG;F28bJe!AoG;11+djIm1o2uGODW!#4oU_TJzUGS$l;abKsg)y9u-Z!!~1+xa8f*G_f9NFWL zyavzDRnSg(0%pQbDms8*_6#(qH7nj_%m zKG6VXpIc=-raAg2=$;U7qzOA&lfx+Cj9m8cd6#iEycgXfz??teo!#GEW}Tn2>{W-5 z%VT)HPWu-o)*`&Xg%(m;5Z@mpVngzMQ`n!H?%FcuX>EkB5Ahxy@w6Q9H@x98`fV9t z@c(VA{oP63v4*pFi=5l9oxR%Vo&%qjURmaBxORljw2OYB(KF~b&zQ~u1L5G2;BTjV zYWh7J7sGjvaM4727VQo1>(JE>l)U_jcbs{!-%XJH zXZoe~yBUdhobR#Ub*Nry{M}`Vcd`$u&Fy+uUToL9H1Vz)`%|_4|8inn^f!Tb2auT> zkL0HxdsKM}y2b!!P0J7ygRl`5zuM(|_FZ6QX`)L`)y4wifP4;2YX76lc^XYw&n|%>6 z>ypDirrxKadH91}{#nZJVqGR>n)>eIza&3UjEDHaMsy$bZ_DVX;Sc?m(6GB2CMC}H(p;{-UdG^ zGwT9VY+89FxO|K)bCR?oI_dxan0xp5sH%JKfA1Lra|xH+A)u3hZ8H|;J4{rz!sk$sd?y`MA}*+HES$~Zp3#_q=U(w^d;n<)1R z{!`YJo3YKWKt`te?oHD84(3q3l=D)~ntLOYp`X7iw*=m~P!3v_O{Vg)(Pz7n@yvsZ zCRlpm%=Au%Yfk&VQ>f0}0!(xlp!YvTwj{JNkauNA#_mz9>H9;y#=3-i5x< zhwb#O>`%<;b)|0wTm_>Y=!3$mvfHHNb~WQ`wliN%waYwGdjA5wB>C@t=4Kj8A#J3} zexwe&ETO~pQO-jj$6QgFpM*!F*YD$yoZ3K8v=0LQaSx*#sZwhXanOxq;#^EF1EX zgs;M)CG2C(4ferfy{t(ViM}Kc;HhqKQ~exQ&8PDcev@i9IvzS??|0iA%GSvzq4MBT z>lJf(769fOkZ~Qz%>wG^(43t0fDZUzhwOR!d+~Zp06$k#DRL5;QoRBC^^s++1qRer zMVTu2V9q1vg1OjqP1tnnC#}z~q8{Zj5nWU|?sZQD_ z+TT=P_+oxBxW#W(zeF+z+)8eG=Z$H%U{0PM`I%IwHUAG&u8*-f~b5(tnz}cb)Xm1B}K6qSJjLXlsDj1Xe5><>#ehD9b z2?yh{=r+msYVQIa|1hy0qW^yE8{;icn+eU>pqVRyDgL=>va^fq%#)!rwRxNvo9bT^ zyLgyAL+~lE_1%ADSeuC*t97p&t{pEH&1h?a*IDBv2UA0b&4@IuP75`C+K4s1pBDYv zkzu7@%QQ>BcBxs~^u9?v!_D}Y=i_I-34ilE{LXXPdom}4AKF@1djtPm5pdbF5gAYa zr7yPI|1vXV|3X(iI(I*MLq0TPxN>q-bUMq)ZI)q{8VkNYv-jBbUFL#EW;(x=@OAD4 z2m4u1MyIX_0!LSxvA{`vv*(4{iFqi5o@x)|l$R=Ro$!3&8Sv@n{5$=x zqDGFTlUDT8JbVe zWsP$Oern~q_`5S1A0D;H0}Zvp|Bi$MQ`jVUa^yL1>wgI=DN)N z78hO18Gi3Rwov~ajjpk-f;9_Wjiaa3gToz^?fLm*3yT^ZW1ZJ$E^=OLo1*fb$1ht^ z30$4iS~-f?$hMnTO@9a4sbl|?)>1Bx*;s2YD!H7Tm!GDrqjB`2`q|Byj!(J9hA&&U z&~dG8k=pf5T(hw9`bu~0P|nTcne~q6>lurqF=LVAhpw@nYnj_3r#eO$15eSn-l=OA zvPR~nUFtD1YhC260-o0Ry`lCiy#5C5kGSVdUdg;O@u{=Snvx#7-G@)f7aC(MC<9O9 zp)ZxuS)i)tcU<>;0bNA>Iry1I)90cgH&0L1S&&1W@s5SWfCuDr(Ak}e33wA64<7gT z_^#LX^~@90L5?mre!mq@O18b{vi#tl0=KoEl>WJ|t#mNP*2bOSt9IoqK*5VH`FoKBHQiLt$MvX+l^a@yJX!L znKNB@c8jN2+nUXI^`H52#Q#3$83Frm(UzWX#j@OFX8@iVuPAgFW)wDy@mQ8 z;+lhOY2f-Q@0B;kd6jIR3H4?lc@0WEnPp4Rk@&xFVK3HKc>i&+>yD}LtK`RqO{3T+ z?~}~Xxt}H17X=+NM=X-8Di;lX+P_jUMx&YEj4|35cC#nOF)An1V~z<(7x!G@U+MUi zk?FWBcZyN&&uF!g|J;=uwC(HI_NG0{_gl`R$~AJI`W0nQp}&YLU*NIh2V=cWF;A?+ zARBT&Hg?$mnk0}mhP zn*{>UQ>`mnGN!?^D8I?SxuEIcL+Njv+xoy{f2@Kt@Q8ILPA50~extGF!O2GK+w4oy znA#paw{_*c)S2{hCjkubEl+ZHX+_?J_s6Ij$zhp+MBL$12|u4>LhmtJ;eID@`< z&0WRi{wQaoCUbFS_q&asWnO2_S+$)pR)P-_=Q`pB_@QpDRlU8uE<;EE^KRIzFs)v(`{>r2VKFla@puL#126_%lW^Az6ahr zx0O1+RXA=)TLo}ryipG|w&y9gRORaZktLK<8(sWAKL1wWdJFJfj2>Tv4qpJw z;rtiUEInTHujjXF-B{(Hro4Rg(PihhepDQ1kIncUI6*d>DJ{Tqix1$&+UHvZVTt$hD8Co;_ux-k}C!(MWi8F3}cV>8EkKC89m z(cx2XC(8m0t!pbz*73s|W4*w$dyTErQBJ%OdC3kuY;0lwmlZpvxUUKHA2|N5@Mb$O z&I*qQM!?+~6TTAPSm46@Zx!yfS@6rV;Pdyn>D5ngW7X?;=Ej&=i0|{>#2E^S=egls z^ij4|C$LJDJvNYdwv%V^wTXS^G1gL|)pl?&1lmrs_LwW4Epn4BX--*@ylZ*4KhZvKj^L8#Z7+-F9`TOU#9;UC``CqvA##nvL z`K=CvZ?T0;beh&zz>!by$MY`DV`Tp8Ci2$h5;J4V2^QHME>DZG;x1zgXGtf{*H z_j=B6g9gQGI3D;M=V8ZKzhV3qeQAwU@KGO3 z`XD)zfS1uWj_*JCpB)~tmb0vrV^@1Wrk!Va_BUjw=tcadZj7Z9|AXKE-d3Cc*)^O+t5^<$9FR+ixq1wG zSNZ$#K^Mh_P1oAko%HeFfX`U=1g7W(~F4vxboH>p^Em`R(%pU8;R;xW{WHgzass2nbADkl-hh_x}4{me)sXp37 z{E8pBXxNR+VGXSm`i z=JslTH!-7H|Nr-s?0=eGV8zW^WoZ8$>~qOeZ1DxI1zt;@R+|3EV&X()?eKmVNIj|Db~_z zsaLTaMeoKfICT@RAbgxT>zS??zH2!1yBysq9@n@}or`bPd91%QKKy)u=k1KUcD}!> z6&+r8hv4QUy*7QPPvj4pW6A%9+US2#w$|Pp(etSdMNtR!rR@CjVYA(-w*Er7EzDPo z=uaK=QlAO_IL|MD-1WjEUirkC53RSk=S(zR?sf1;2e|S*vmw83Jh=nlk>8B}&9>q{ z1&E7u_Z`OWtAhT6raN5R;ER5d@d=;gK?sBQ$Q}IG{q0=qX|Kobm{SFfR?aI53a*Z{ z=E!3DTSgmi|Bbw7loP*<=ekd}g6s(7$Xz+)1LK+vZ%O8qOXh5t(smcRvzlib4>=Yx zKmRWBigM5KO!bVS9^qmHS4;o%jx!7_`5LW9f7ump=7Oi)@OC;pJ{(>jfh-w`EU~q{ zF$6z_vG>~EA9v*M|5ZnR6aP=xhx+=6f$MNUCtSyvkLFkA@D4f*&C>e++L=0+TDC(0 z-(H#V$hJP#Bla|vg}R9;h+oNXsS$~naJ`Rf8P~O3gUWThX6AZqxnB6KmwBuUJoYX% z+G;pUyWp{wnR*_A|5Ts$6yT@oH_6G}M-H?;p7&3g6pUXG7SAz< z_ypszY3e6FA=VDb_q3wVZI&MWj1fCyH#wfxER8KPA_tK(McAA=zY+N{P}bP8b07YJ zp2_~m(L5vcF#9Ur%HzC)!f|7ZpbuZn%0a`3>=}wY1W)x>kSFMw zb?gxr9YXuaEy=0b#G1or{qU%@*R;FLAKS~B-k${*|1vcCi?Q}`!L#Tj5BY13z>8b4 z1Af68W9w3X=~D6??*|Vp`H&Bhit-=1cEyARm56#K#RXx`bwpJq(*Tf}Yl zelK-tuO)JJV5PlzTTh8{;2No!5Ks zN0#-l_egE5Ay4jM`xsw3?fB2dcR6ZT&3J?J=#?LAH1Vw`;S1HJF=FHImK~G&?}rW> zWsA@c-LKO9m5KWYEgK~dKf`?ZKoex6tJtnb)Nx8_>Qp^GBuFdIEnJKikC{$X4n?CTx8x3l&xXo+uLLMMvm zoy#*EIJc7wh7fJz7%G)OhIoe?GVM!7KdM+@S=V-OgEMiTOf; zK3c>J_Ut)(!I`bGakF^kFAaiIUig74$PL2S?`OXA9b1lj7_hX;j>x}I_7%#iT*F;P zWF>Px`He0E?ia&%Kl2*Ljwx;Eh8TN$w@8kr;CMUr{%$X})!Gl{tI_H#aGQ-R%(3RG zj?u_%hp|hrER_8H*#zu!qwR^z#2l}awby3qT%vbdE^D(Po1;8anfcOB=+8>d-?)F% z*MEOvX!EA2v!8uG*V(*q%Vh`N&%@WSc+*?&k7jNTjbvLn>xscp&Mzl93&^J!T*moq zk2U_G{prhd+R<0B!x#C>z}9y zsl4jZIg`qjSeMV4w#ZJ-eA^sYlGomE4{ob99S4zjZJvFc4+noVbLRE`UW2X9H+A&g zQE0rPvzh+{e2>q+1=uWx?gz~^*Cytg7OgYpOvWs|`^7rZ`iJ+cW&a_0HcGZ~i;@7bC| zJJw#(C4Cp-8#n8EniG8JyM_n4^j!hpy~Q_wrO!{U{X$fB;u2&?O+|U>t2(bdzxhI) zT7OWz$n}2Jt23Ul5wg`6WZRY>aK9HjB#ynZ-Tu!rciF!XEoS^Z_F=x)YRH2IU;OIZ zO(C_Rwo>i-SrytI<>QtHd?TAzx5II1{C*4z5kx97g>|NYr^V~^IW2i zQ`7-oy3|htJK^+yHHErpbJxIKFElDTJ3w7Klk~FB;Sbrz3|({p*xf)K7eCLip@%=>`COh~&2vkx{wB+ktK(NC zVKezSgeD@?Y_GEUnMC}W9j-kdDt#Rmn611di z71#U6SB0*ozxw|q|Fyne3r$Ivi3iQJ)_kooe&`voZmIp%CNf>|rTX5)_oDbXm0icT zs>6Xk6b$uDx>3(sc~^*j)Hg$tGzA?+cYt^K8jjEZ9Q=Gce0>`>#I4v5%(0*HV-qLl z*SnFwz%f!Z!kGGV#;khSQ@P?4HtcEO2LD7VWAUk7*rhRYJ3Ev8ThI9TE;f1s=PhJ5 zM;ybQL3DS2_bK-CF<*EMnNdc3oa|l4F!cIzb43ukE_0YGu%#E|0od0f~m-XGxqA;l(0Qpu+PfQ+E;AQ)vyKTa;@gS z#!~UK@8-Wn+5aF1VeNS2A?qygoo~q#{>VP)S#_wKWRB!LeCjI#zbYfT6`wqhuJM}* zKB?zB2Ry<&JmQ5%ycsSZIZnJPpYTJmZu*1~i9iREZ>oC@_CW2k2{|R)NJg2gLr7-o zy$LQKr;PlNZ}Lns;w^9|dGuH2cR%Buo!N=9feo8(SP=6s$1gX#Ooy$Sm6V7*uL zU9S1wU#7GvS3n=nWH*#U=aTE9P3Z(nwtvPSlARW!pIUE_JX_Ay1QsdXJB9Dm@20yo z$NRvhIX*wjvSlvVFiBpsElu?0;bdQy$cDLnM%(lB<=4r+T&ljn`&M5r=%_?rj?W)t z2cVOr8&iE5mF&ys=}QmriI4PjX-wYan7W6tH?+_!<(c(e+@A3F9iMM!4vNo{a;i%{ zvP#($;JFW6Iv#F3 z(ywNec_;d{9346fe#4)~SrzK@#ceZ>^{IW~)l1vWwB1U3A)cu{jYG7S(AWNu3!1~1 zG{rT~@cy^jOZqlX5C?I5{t#=tgWJ?TZ+CLcYPXkhyBM?Dp8be3e1fs6{a*UvrfrS6 z9-5zRUOL(Nv3jmMwb`mlc!c-mF@aO38p+S)Fsd`9@j zOlf-Tf-NdwZyPL0_AskH+To|8@q9ARcYd$t zP#r(*CFn-i^&_9$v|E*IcLVJf*DmW?PP+lx?KEA!%WEfg_0#S$+I7?J#PsxFkapM5 zZh&_CW|c>=|6C4ij<+Tl5y}33#-n=I|6kPm^<=&1N>|@3KXn_KN2s@NmMz-zoM>(k ztyyaa_Rxt5!aZvSFUU`=bwSher5<)0p(jk^7vf{lApXk>wt(ngwC@D>uiA|1#8pQ& zfcMe#f49xZ)HjM7C7+dV>L9t5cy6=i-g@sfd+eUBJ+nO6a-JF6hc$)9^GtOH zOk=X@-GH5O92xzN-R*M?cLfFeiKY?R*)lxL2B}Cf@Dd-o2E(lGB3#s6gbVBo;i5SS zGs%N)__GK8?7hIBI=6v6BNL<#lRTP)+l93j;3j{Q;3YVnys)-vSn;>g3p?rCV3^&? z`n$%*8Sy@iPkQa+VDJv({s0bHzIQKz!Ty#J;dx0Ig#I64ux?Gwp<^EbgOj(3XJ>JK zMG^)tNJb6`ohTOVkkc6XHJEPxK#W3)ZbVb3k-^Q($7_=^M6~0Ab{@xXG&e~*TDwer zBU$^7saF$x*8dg!9oTw}_#FXd0Z zRq(nokt3{ibs`RGC-F9pmM!_t#!-vF%QPq7xcE6QA3DXAV@z>3rZ0Mc@4i+yc5*M@ z_RUG;!gn@iE>bx+zjS?befktP-+Y_0>3lbB`MAk_l<%kf+w+l=NtuV8xYeJ8ll0zp z$th%%G={d+25}PLBY_9mgqlOjCR855V&-nL8)O%9o=+R{ zDe{IbufGSH@MBw!2|PF>HO>>@DMS2rCO&;|Kh>6Uo5-JVe7*^vC)YkJ@zvr>tGOZJ zv&d#Wc;RZTRc42G#pAncEASQGfNvOohP8(CS$yTJ&0&;~tHx=ai`Z0U#G0^!n<`w< z}C$cKyPydRbie?PaCY^c+`131hkMq2ZZY~$0He%#!{$-D}@UYL742^^$jBwPQx zbC1E}9Bg+U!wwv5^KKA~FP0O)*pd@T7`u`%PT79}U|c7f^nSDrDtq^sY(I2HqHW1K z8@_8h^Uop3h(Ypht@i0MU%Q^zs)Sy(E~0%a9}se@h(0Jbszvwo!()yO>?KCL?7D=V*c#uHDZ7-j zp6>0YOb`CTA^Ja&y=KsJPrQXa{SM!gNxO-h>b_sHj=yiHkwNazKqql?eZ=RJ>)Gdt z6EBQ!)W!EF?PGnay90mtKKjVqG`okj3eLdtdCrwtc|x8aYAi_A`y=WkX33{~N%9Z0 zVl$=qKNCFH4EeBrmfo^>DX9%2__=S$-`6X;QN6NJ2m7doz_a3I!NEkw z9LdujWPA|t^}peFk#C`OgmJ;QVB$}y9qd~`Kg+iuAC>sKmikk;({uSK=0gV;`^O|J zl`&{b_G}P*Haq^Y ze3?mqyU}N-_}y`DqK@tY|7<&ajUt2Cd(jMw9G5ybu<|q2sHyYnp5y+A zpDED>ek;k5AGrLd{rH$ToV4uJi}=TV_MbnN=Kp@K{*P(?|3=q*5{+I09PxSkE~Z}`I~MI$qMJmQqMeV^ zO?M@6k@Ab3jsDMdQwpZ<@a;c@>G!|?|7)1;XMX!pFn#_bo@-D2;ra(Gn`{kN(RXE1 z7La#ys_6TK_zQj*O#eTnuKm0dZj_V$BzvyQSfiSauGx{S?+91X|F5o2(7$MZ5_P{X zU4UGwbS3PL9h}q1q{PZi^0g#=50+)(H}tGq&f*zHul|NN; za><1`>Q~YR`Xu{G^5FRV59T?i@4gP3CgtBt%ylF;wC2w|+M3@D_92{1`Vekq-+DRi z%HBC<#cAAM*}OZfi6t2~PoTPGjL)2lpF9N4)|?AwH|IoF4cZP{LqA?#1ZCiD{P zdD*el)(on8o%K89O9EdB{kpeIrU-NVz4hVW%JA4mo1vdTuC;6 zPI9iKdD4s6SemoCm^aB@p2}L6Yi9b0FgkzTJ>wRs-|pe=U_E}J`xz(tf9f23clGgM zB?0FB>CF4rV;7?$`Qlt_+kH0W1o5Dcvr{W|uXE~*K*jY)NIu%E7 zcP94qhvNvG6Ul3W{{VS`pU?Cay;Mj(M(9H^h+22R4yh-m!iS&D`_imk#oCPdCY5;cyo&*hlm}awN z)BDJu?0uiH`e<_lcETL;n;ykK)?**(8%|ut<#n9x=``-$NB>3;Z+XS=5#(%bj$FxA zIUU}kj~?5IKq2sbkNz#-=dop2dlrt;znl4uw2iE~avVM<@cL8Y?k*obGN`;19+zRA zaTubGGIKeh@POt*zop--t^BMoxt?)k zuKa-P-8&Awrq&LB;IZQ6HuH>mYFi)Ii)p5t{fUCxgD2xtqvvZ5-431ffD7^JcTA(i z0Sy-6`^tp|TbX0m5_>vs<}Di-tRbxzMqm?IiBQFz^1p_oeAUrT_#2EFS6wlC`BygiK1Hs*wDhnO`U;!==cG$^A{P(FwL!5zLBxLOw7x>jOk_i&DmJH<|oJWJI3U(rT1$Or{2BHn108Y z^h{$?I~vm{+em9n9`d=X?hMz9+pc=v)$Xwkx5iXvl2e;lBjz9rG`@Aj6CGIHxLJM` zM_pZ)3ErK|o8_7kVI;+V>Re2J(}nBSW1@zn=@ac{}p5mv&Vjv3@1Qudt7$uIt5n z#!Ye6dAr)tZRFXN4T&%1gBYE&cQ3@RvH<^aVr@>oP;Z*U=WTI@d+bI;GTWm29@bvT zw{r}d(fXyp76(_H``rYgL*H_MMt*w$?F~Uo>`Tuv`UyP7vv=IT;oRPzM5axvM zci{`P*(ZE|ykq>O{(^!_zoeXJXPORqMj8W8(pUA%V|VuT5?3G_Pc&kTF0|&_0nPu$W`+no0 zcKQjug=>IEE&G7{^y#t&J@bSgs4!xJQ<>to>9^u}S{S>|P_KKeGFs;}cI~y@{e2%e zP0>yY50$j@8*Fgm(bvoGFdm5Iy&i!xh`mqFdoyGV23+O|<Ovq|YMg6CT`! zEgK8jjF|Rs_5gbqu+O2dVV)H=Opoq_KKDbP4)Bno8MT33l#s2WQT{uj(V`s*+Lta= z9m0ulTZ`{`SH9-&iZ%WFy;=8<@ke5e<2LAtSeO3S)--PuJrNtW_}lNqcZ+_SlJv7> zer_3zGY-A~Mi z&WG`gGGd;qjEK>8-8s)h?rV&Q$IrEutHEy+Yg%WKFEzRj4S81b?5s27sie%={80CO zMlAlMz4X{o?9dnJ%QuX3#P-JwV%FPfNBwsYPt!|VeJ=b%^p9Nr5yLP#4a4j_<~Ae5 zFh%N(qUn{C>7ky!7o67FJ}0Q>DQIiYe+?aA4v&w@fP z#k%e!cb{Z)CHtIv=9{r5TXz3m)km!B@2OA!73cwVu7e>Ed|To*U_7S-C~0 zzv8?%$XUh|z0-)CavQNP4(I(G*6K%=gJVZD zzQ|S@T{JtSJsgSwKYb&6UEbh(=~s72ZPoO@pZyQ}7=z;QpQqj4r{;!w?qolk=?p$hEVU0@ z&m@-m1Tod$BbHh*)t@Jp`uGGRR@L~I_Sv7xX?I{V6cy&SJBe}6Mh+3v63O3ZL`RpK zQTZ8EN4E!``X`h(_BGG+Tw+9y0S8Y8w7vuSzZ}{h!~J3I3!!6n+e^On1lad_H}k>! zY>__tifmGx33+J#0`d;Fzqt@@E!YU4uvIf?o|X&k*1=7iFrr+(suK`^DS`oXwG{40lkv)Oz;}=V4q^9uuw2fzAR8{n0rK zjHuIze~7(`qC3%u@(Bo!W!T;wBZfq?z{%$K;!~UOy|>Uu!Nj00(PquN4@7JkMHI>^|xp%xA77kFjsh;xX}-`_-#N{S{d-nCGU^hGfBM#u-J19G}2>)AZAlr#tej z9OafCnl-ev=cn)lbaH$v@?CkzP4tpQGr8gOHJ1O8^%~A2Uu;J^l;ql|gcp^BSx@1149= z(QE0mshDEz<6t~@WfNz}^_uq*I(moR6;0->*XD(f@=Rs^Lsx8qarCX{$yuefImWbO zZplDxiG6)bkK?H|>=+*%LnMZe79J|?z0)6A$Nug9IsQoBQh!AJ z*Uz<&|8>^f+43`%=D}~SG^6yXVMdAYh5WVfmBQ8fB(5Gv;_9hO%nP`Z4^Fr`oy66h z_5`j@7sg8b>}%?~#)#bwzU0R{!5B{Do4b0hL2f}G%2SYw{jc-6XM>|=TW;{KrUcG@ z2&_ck$AQ;hzm~w6+JDKBz?txsf{oyE7`Pk(E|Rwsfam+bWJZVoxl}B&;3s&!g^lu8 zVD=dAp&{RK;I?%H@`iEm$B%{YJFGhViYKLy*pzLGefp@g$9pIIdYNJaTG>;``Py0w zohEwf0k^`d_R=?B4c-_->(%U?fp?!}EGKDGv@berU1dZLWg3zD@?s@lJGuIh#ymC& zFWryk{zdAqC&y)z%@y#HCrxcg#&xXnbz#><QS?{wCZYkyI&j5#QK5jkh6Ir1Xy z&%;;zQ~W6J;iG)pKFa5*NbG^yh@a+njg5zHuKQ|NhRet-%SVU8XQI1z;Tz=zdwaMs z)U9GDoc0ofK_^=`! z_(F-#UObmR1lgm0@N|6Ya{Q$8@RR-oU+x>k%lR99lkEXOK@^w^Be#k z{p>~4+Qd7+khx6u$a^ozJW34bZ)vX+7>?LKF}TMZ(eEdB(@%ln75HC&$5=AXUw25b zs~Nvw75uY!)2e5>s%_~O95Pql%Y8;*J7d|fYEoCmA18K^BRE6f$!{zF#U$#P#2$q* z_9fJ0{?F?u1djIALl&u?@$)7GCl76olpFrYB!`iC*~3E?mAQ-+lZIyon~nLa4%6O* z;r8ItQU21ktR+=s;|pgmK_SnN*fYWvd^d~l?1eAnHyN&a^}FJ1`Jswsjhn`swqR5^ zFx>URO&9lt)L%%9V`1HrF8l_Ww!-K0tNE@Rd{tAfoV;O$Huf{|u9`hW`%ds*eKJM{ zmT-S1{W^;OZX~&vuFUn9#?RST>>!sBGBxj=`x7x){apLtjmqJif&Iq>FD=So-^Ora z`tLL&i_S+a9_jNSXW@+nFD3JhJZHp?1x)72IpMiHi-Ol~Wbv_w%*e5%p1gtQXN7M^ z7H4T1G0DQS@H(C$#rRp@UP~FxT^_^-(>=_L9m~@5yl@H6`5@dql4lcak@%kzZB632 zd`aEMXsch(^1>5&c1F+6@azn8rlxVBc)t-_#9G!n9{GE)OYG=e=r8n=zpIC~n{3Vi zzJ$d-=zKqPzLS_i%ZDDQ?LyaBYXvHwPM>?IV}NlEpJcQ-(Bq2BQ|yTH0ao%m2tTM! z@0F&vFIjf>WB#r_%Bh_L(5>1zNIOmN(-YuVYevO^0RNp9AG@L3iSvts`>Cs+y4DpM zUiL@F;Fs8Q(6ewsJWu~!e7o76hzEC=;|}&6Tm7t)JPO!M1KvkEth0O^Ms$45eKc;?kUu7)Le5tyNb49FkMp_x)yc24#@z6%bvaIg%F8Q3_Wh}LIon7*? z;17*Bpx5Xx{jp4B&usMA417vG50yteW~K$Fp66uemPgzTAz6!t;*8b6^T)-Hy`P$)-Un?F&GFyA!RTVWKIVfiL_fXvVPB79O$ZyU?>^Q<8*00V z)A409j&{~Ude4+Ik8%XO%x8S7c6IgsxjcfMYte}IE7S+-$pz&IG~)wY4<5bs>{s}6 zOQe{0vfFC|#a%mX`3HO956#QH_2I7iTOMCnb<6I1l{2qyq%&9q+@)Vm;OFV-$M1~) z(gscb{4UOwJeROZw^84#-j`p4WrY)hpMk7?_#D4{x${Nc;efTH$ zZv4-gDp&B>_h%k-kprW}6Xkrs&>QTTJ&gbHWbx-iy|;}E^&ku6AKlKFkKxl)j9nkF z&>4QjGA*vz_{C^*JkI)%C;H?2kUQWz_1yy&kK~4T@cbnFag5*l%smE<;bWwqXU;Gu z18=9_#BV&3{3B`2k?cBeyW(xN&*8QW{%BEpc{I+LCmfA0{tolnW4EP+PGB>ioUw;74)z1o+;_XSm@fqM)1b^>;+1Py= zpPTj>#LzJX&`8h0b6eF%<#igc?DKqFq)FI1#s%eTWsNdC`Ff*EYtH?dSv4r z`7zHh#?uqj&+9{le0TBxbYpB#&-9*r76(-}fDUhJ!C#L|tvXk6XawzOe*1E{@yeWc z8aExSV2?NQ;XVAxtf3uz+m?Rta7$C?sPV=tM_Y_n_O+CCzRdNj#0Wdg;lWd^v$2lc zFCE$Ua&?#b?0U)5rTKu%kr5QV41C6q@5-WA_|1r|d@GJT8%^wcMtB6^`=2OAoZ}1TP0(Fm@lc+Qff? zT=tqH5Beu1HFy|2QFiD&}+I5%HAvk&el8X$l;v>c)!Cv zeu1`h>huBc4Zyt;c)!c{oV9Rpr|CG@$+I26{N+O9l}=#Y0?apXy$6_o&+fKtSi#$g zT=&qYb-zu(JEgzBV)4Sr@PCqfYT&omg^mNS6#O_3B_?>b0>3lJ+7lDj5Sv{QX|fvw zr|ggCA8R)wCI1pF>0Z71kRMn?k=dv1*4iUdqVdqFr_9L7Lq@EWclt)U|AhVVZHJN1 zPXNE}Kg<5e4d0K>IQ2_2l3#CZc|tY=^nDm!%H@A+=HAy2C|4r3-t>{#$UVowH|^wg zCAXoYcGxKSO^+al6W`>9{nr><4nTip=9vEN;{|JHSh}hA473k_oCMD?c(k|Jh{ z39io4UTpq#A@%(}zHPFN>Gu~T@|V=3dn)aUw_&~)Fp%Spz;*b?_9BZq?798Y;m6?X zZeT3DzZ>vJq<3S`=tl4_Tca7B5q&XX`)K}#PbSjJyOgeO0`_MquWv7>tZb?>JHA%@ zZ>{jj(dYaz!M_){9leIWUzym0@i=vy;=9@O?>IJ75&GB58g9ci53M_#E)?0^p2xc(gC50;{TH`~S>JPFT6!Qn&aD>m062Q7XJ8M}41 z%R2iQi_cFPB>R=vkC8x~C@poyGzttbLxdV6{kzBm9B~sZNpE{Vf2Y8>2 zZj)`&cZ|6kHp$y>Vv9m6?>^^`9R;SMvG<^{_kpK)LGc)qGRe2>b_AJg^%uxTS4>_6 z^lAZofp0KCe8OUrwfBmK9bL>{0&C!lS?@I-dW&*vYnOI48AjkRw6-SQ7OWW39GP|1 z)b_j5{h?~Z-e16T$%Vh#Gkx6|{#9>%qa$DOfuBCU`p}Qr5Be-IZE5wN?y3oVrt5ud z&Y|@`>iY7?p}~J0Vnp;!#VDQYZtw2~$6e^o8<>mjF^2|bL-+qipMKr&qprB&2s{rS zhdp#R_d^4ZW_RS@aDEu6VT|k{T!*gO(e;Lr7Pt#L^xx?BmjhqsKYa$4J-|}(PI65$ zO5aF+Jcobdxh>HW*;n6|9OG(0pVrIY%=7Q zZ0EDoBiVEoI8ZJkd6k8n>Om&gUXWE;0rvDR?u8CDPbmJ=b6rj1W%}rD&^#e4u)PSI z#-8Pyiwp|zV-IA8uc5drt6^f-JIG*UcA%U(vf-_#$(OxhOkrF5%Tt2)fj6~_Pkd7q zIr)Nhbu+4*?jUyIYca}}+4KAFQrp0{>>EaOE`7#d7u!$%ri7fy3e-WTlD!Ez^PDAT zo`+r}XB4O7p?~H4zmypIqttT(xSm2r&$N#`_?|)t zX=j|>l#lFt9hp%XZ#-1nZ0z>qldS_UqCLs2z9(-8<))7g#;8NKqxvj+*NOhu`Ae4U zT4E;GE8SuIHQAzH!C$=PGR7t38FXXW9QbzRM@*IJqyNsws-vp=z(!A0wpo69elR7+ z{_xdvTYG6+Yx<{56A{z-P&p`;zw`ar@CD;xx$T*qi^;hg^C z^znPpp26Ir*OKWugJk-c56Sd3;9uj{nJ(&ULZ;{RA9y)oD`ny9_?jihbHZB~zw|rt zcj39n2Ysh+R3-Ya=iz+uJ1lhw!da`2URyZt-l3X^oCXMtV8dB zE6XN?27K?VPS}Ld;l(zg@NLzN?b(SvIM^;!-Ktmh3*Rm8#TS1=vW~i&n0w*tUEBm; z-wC}O=NbE|`k(BMFCI+W-?fbdcOTI9y83@i+p?h-xn)B)9%`)vcgVhH_Y0mmVby&L z?G0|D;i5L`?*7MZWYY#~uDe=kqxQ?#4z%&zL2byk5+A8e(Y<&{b7a}Z8gq)5bRN28 zvtQsP*9Be@-iBMel%%61FOA2ioZ=;mjx0VJIf#$4gDHF41|6M5&ZqbY85KK*46Q|m z*4eQ&kvEe2UgU&#`RYxx>q1?1_$s{cP7$%gloIb{8OfU4v*RAGrR1(f`Bvb)TjGgXwZ? zdM@+GvHv5SiIx&{nVeT9=~Dch!kNk>~8C7F_Bf%>^z;OIZGZruAH^n6PZ27a+`>za*^p%(~*7X+1mh+g|0p{<% zKI(YsIpypTUyTj;StpV#y_I>=i`d3h$@uyf;vRZuIomXMIx`19_>+#d-aIoV-(l}q zu6!duYVQR8d-y+v>jX148XrG7x=V>k@Ex(|`LeDyw!|MbS4==xdHT&2J?Q-XBm50J z$t~gehPk4Ma|0YNwC2bA%oVelFZVvXjvT$tz)ox^lk z{EA3l{F@7j7nyT_`q29U$205mnP>aa5Me=dH*ibJg<>|M^iWZ-Y=mvse^eZ{5`Q7r1<_T_sc7MVF2 z`KLdkA8K3u2vIllgQ-2k*bl?~eyt-hX5bj{1FQY4d-d|Ji2q~R?{ep~Xi3fL#!Zf2 z6B8kNgI)~y0J!3pa)iHi4>4vucV@9>W95^~3y*!si2UtK#+EFeH4SyF@G+*%Q=%ox z&0BN2>ClOPqb~TZ*Pi7wkXNa?8dVq16LmFhK1_bCEbQ&6)a97M`WNt+LtReF=zbsl z72PVfr4^b}{h8eN^UT%IwCOi4H+vt$kut z8!?L5$gXg_4F1QbgpTYqI9thKy!ZQpXRbR}ckie+#j(LN=PFrCvv5IPzvSAA?-YA* zqnzcToM_53EE-n~N8L1hSj_qQ&_}PKhu*+vyq+Awm8JgJ*x|WB>3Y_pGs`mYPvA?z zAHG8Q{v5o!KhIy9gB(yjtnniUvVA9~8e2M&a$pa<-UCc)iRXcSr|;ppR@8`c(lt*3@DclP)+KTM3xVU2B% z#&+Jm!iCHTUCQ}HwmetyK4U>unz^9KOCDul;P>9K>axPySE>Cyl->3Gck>D0&miw+ zpc`1QCphCNzI~c+m-FogzTLyO&3yMye5V}JWu`mO42*ZNH+kLJ_*B`}Cy?o0?v<-h zeL6#5)JMex=)YjUbx{9y(ng3jT(se(jcVEujtXdJ2<>RBss63IsDEL;eTr}A@@;@` zJNUMS@2=xJ<+_#(PW7+#?68tk5%>R*?B5~!ay786 z=An@&eU`2J1~6KN4%&a-$Y9Ns{QKX|FKQf`<^58A=0TftPW|h((Wk~A+*UV&?bLdWa>Fd~+o0%`@{SE60dpQ9t~A%;dN9{Kku(r{z!nPoC!yODWv+Y`!7V zNtcaB&u^{gcM|(Wdg<;# z_oFCdJtrsl5}wx#dgtU_jCzJ~9m+3_-w=Lwez#KY7Jdfz@u$vjJkY}P=6prT`{~K6`0dia#kbzX|3|~gxO!spvTrxGC}*11PR1t7UZ1?q;`$I} z&E)@rH_f)i|8jn7cT*y6NV5Nj^g}U8kM}AjDJ#5a(YdV}hsK~b&)#NinUws0C0F@e zQuXP57ChkPnS3gW70`E|;wrrAUVAZg)p~+_Es1;9-;+2NKc=3gbZIkvO6k%@^>69W zw%FK2o^sWDp?&+Xw);wutxJcs4e%b@qwOfyl)k&i`ZletPwyDxkz+2sX#T=`ctdNf;)@WuVJ*IZmy1|$ISTJNhZ_s@O$GUPy~D5-Ik%|= z{av_}vtW=#8ed@+XA+L}M+$P%7I8LO+a-&zH|>?BJ~zCGo=#_djrhcS6}vTu*tvC_ zM{@8kqx1l|l-Hw6`rPH%3dX%VZR-^?I)IH<`l8Q>6nw_o^AU6mRL|Idg%O#CudVD; z#()o<)6X|kCavGr2aV|4#qfI_e7VCGLsi79S@m!Zi;wx!U;I z`3>QR?b(@TUCqv+*45TI%(~h;M_Jb)of+0OtuxcQ4(-gcuERRBt*fIm$GSQ@bFHhZ zGtauZJ4ajB^v*HXb$DmKbsf<;*1C@D9LMz%ewXs|@N@8U@>|4wR51zCquQ4c1ch|3H2=LcAyCqLQB4d!qk`N>wA*mcec{!Y(B<(-$@SJ62(FspOS((5|&?!3M; zXVDFvS#xge%$QZ#Ic)6g&a|wmPP=Rl_`&!5 zON<$cGkcrOx1CRI-Pn zmofFgAFVc*Vu`Xj3$=gcqz&5+P-Z*N?jn}JWWD+s;-WR?USb@245OroZ}pwliu#^2 zm^Zns`1D@xciPASY#OD8(X#NB7ZU3uHtrSc6<=a(+06dk{$gMVZnQS0`2BamO&MdD z2t3yz1J;|tZNeGnqXY#9(LVn6{_WU^tmW+*1^o}O#ygTd4M(~EYTZ{?{w!^jPh}@5 zrUf|G0NcsrggHVzdmHXuX&R$k+p&{oUFKhDjE0vA3IpIff}GvODVUjTZ23d;R3-UnL)ZcKG)iOTlo* zO(C6a)uO%@3=}&3orUAJ-&Db`&}npP?j;z$nv1_r=iB|lA3I-9OgVDW`j0$2&41Z4 zJwdVGoWbyb^hOjzfNbiX%EiH+ic`(AV)5H z*=1{%r5h_Yuy&yJ>@33{n=%}~E-?1Y#+Jq2)R_;`H&z@xdc`ExsTTjje$MZe?_4(G zfsOv?e(2OdKkd2E*s=pVa{EXlwjF)KI_6f+s-LcJ6i-wH{oKX9XlLh0_No#a=^#F2 zEpSn8z5T@C=$X!ZH5wj_K1F>hzkO9nR5^m;He3Ij(7{r2hlBftikVi9rAKBfURrSo zxcuZ-Rhtjc=7Z#m?t7lSw#cg9 zwZ`OJwRzSIsZA$qpgHV|%VXbds?AK=RNt&Q3*!(SY^Tn2o(pH#dl&XUo?^~$?x9~< zIru)XF>=D6XY7JS`hvuM>yN|z+k z2|8GRvvPWWa?U=-sD%CNIBX28MZYy1Ax}5zq~!?paY#&d&CHp zVgo+7&>w2Jqdasqb?mq09lR5Nf78fTD;Cm-wk*sCZju>q5YtnDk9L~fh)v`>{FIxO zA9Gwz$F^4d{XG+n-QThHzl;tK=Nqkq=cbPhcC!b3@1>(}>K@j7t?C=fJDvBlkLRkl z$v&>%ykzuEh16X=3^|Qns%5>m&Mnz*40Mw_uV{C>HI~;#I1Z-jx*Xng*mL^T4+nkF z`ow`EW4HEkUBm)8ja=eM9N~g-NkSDHRyi&u;)LFfnMnOo8UzM`%EJ^*UUbs_Z=<9fSq??*0V+$BZG6G-;EVU z+j7=qkCt=p8Q;8z-50i{2lqZgOeANUzl=T5{YY8oQLam{0h-L={rj-54CC(a7m}kw zV-PJV9wW$i%N`*|@gqi5@uIR%E-p9qxMCv}lWKInTPr;IJ9B`m@^aL`V}d)nxU*)2 z&YAi6Tvcz>p3B=0>_sPo>2Y>;f*zUoVe{sOOMu%A7R}@ZMUSF6ePgih=^8#ZIB!BC z2I1`_><+*a{lH%TzY6RWpD==U-T-!Qq9>jLcHabM%YfY|t{Z{fOTcZwJ|gTkhX=cX z8}Ua2f|v1VS?8!V3AlBbBl?vWsAfE80e;#H6$7s-cy~T+s84T$BjINjbX89qS71*F zKf;UflfsS5{AAqh1vgv3LlD_D$HK#C3lC~{CG8?hfPYT-o4|f0{EVwCJ*auSpZSL>>=1<2#67=fmZL!v98!6tG^G!bL3xMY3PtTMxm zX|fC6rd$udSK+_r;lY`ECpTZacg@C`d)It(rt#QgGmYWR*Y0PHDSSnxH^f;gvV(V$ z7xWsF^EFMkyUHBv{=DgM7jb=zb1OrQt2Y|bcaz7Bna zCX?G|X7lgExy_ONw;IGSk9BL0!R!Ox;Cjx}@Luj}XC1JAJvc1Fmf1hqD7^-_8SG{5 zT$@9wq46;b#7)cpha_q)UmtDZ@N>dsEq zJuz8#hufH>`m?D&i~6&Y_5aal#5&>c?bK07+5OCm_L2*u*5WZoIL!GUuio{KbM%e* zqOoN(zvq5*e(SURp5Z5&QY?_ht2I6kWBxYv$*va7$~G#)+GEYFUZpQJ?0-D>P~tqUfiDu0Eukf+yKW zKz_aOANQQw`i`wRA|85)JygBOoSnAOnd_m&AhdcFe(P%csK7j6dJk(;BU$r*h5d08 zSy$YoH6iwjU+0{)3SF}}lXa7Y>gKfp3WP)<&=7o!n>T@(r&8uT|_9 zAWk6W1*f7{2YU^wGK>L(`J0;X?Ct`c}*yQ*!2I1b|WC_3>Rt?CCz` z4i#Qb5Hl_qkcDHK=H2q^ALV%`?QG=#ZTv>j2M5nrfJ@?rR}6s1iMDj#%e1ZipasbL zg1URy0|iZG`Bx46x+8xsevlQ%hm};@jleu$xq|*?62m)wL}sv@xZVluhtzqnqQMs4 z+lLqnmJ%a8p?>L%Cymk5CouLJ#;vk3=)QpRo@~w@h9*3tIAfXk%t_RxeWNpMqkXa! zCxN#B?^oQhqN{8ua)x`JWqkFH(yl8R2YYXPiZgkUb*zo#JDR}0&ZX?@q|L5>qW%tO zuN%B}KzoYOTgrQAWyRn!Z!&h3OVQv`W29@s>0u?}7nRlfot&qo=SySpX<8FKLQd}| zD@HS4mu;6Ny}KnLXR^Zge_3)SFMRP{YUPAHgYP|crbN$?_*CKI82x`3`H|9<^4ExN z?y~C14rk8$$2#)iP3!P$*?kY^?0J9e=BIz3H_vSQy!YSVzw@a-zAt(5mv5YT|4dcv zeaXyfa1;P0z2uziL+jO~7qC$w0U9 zQVfa-VB3VCHGoCY-Ee8UnNh44s7Y_!w%cHAD`mB6+ayT9R{#kbhP_Y05p+)u2F35>U5 z^_5Xije(bZwh`-6Jb7niUOmOU`sI#vVxOgTnaC>>m=`rjYenZ^7mxzmH;FHI?hqRw3=3XiNd{)do z>idx~_egU_%suY^rZM-(uYb(F6X+O))_8_v?xhiP&rbbC6N{M3q7UJH5ZbUWPk*c% z-9dftgg$B+6Nl&k+D%d#@F1T4XCH4Q?%uTSCgyG{^k|1pqVr}U`JRru7v{YVXvDcW zOnZHC_ZSz=N&K&|tLx0k54Sx?XRZ3z*tmP?R@}X>EAAfkt&Ys0AO1t{2JMNdW)AIv zH){Uv;`;Ngr}e^Zq!G4#VU{pW=h%)S#$6)kj3gm1CnGPXATOtK?%jZfAaa)W*9s5Q zh><)UtbCMTIlckSqjCbY_4r_8ZY}-f zxb@y<@s=X?wd96Elh_kADG!;i2E3?1_CkKx?i+_MApV%;;KE{b|0Uo?{cG9}Kh)ai zGRxZM;_zut6mc5e)xR-vwa?`N_P8uYwku+vO9kKHqc^ew8CvCO@1D{PK~~y;%+|^K zImp!TlDRvP<$~B(A2f^+Kd4wT?N^TB^}E>fGD~OT47JVo5$C$tH0JrtvGa&+mf+(Y z%opg-7mT#2Zpt8z(8&1TO>aKMd0EPL7Wrxq-63Ly_$Ja8WEX;4lqA3hP){!iFJWpJk^V?tMv!=`Yc666U#Z1NS8f{(hnn@)>s04#~@JaEdLKj5~3=G=oWbXxoY z-^8Ev{_Hu+PSOry^WHv0XSMQwC^2}k6BRp6XS{T%*ALJ12S%<*UtlJC5d_~7;BJpzAf+I0%sjr#KQsrc-)@uoKRBC~6pH$g8&=%MB8x0Jtgb@3nb@#2598^-@)M!$@#Dih#(_Mhd6+<*h9Czkz4%N#^%tM9tFQUaPT&7r ze1?9B&ZmN}*Ua1bd+`Edti|w|c;G4zI0 z%4=bWy#rCza*aj9m`&KUW4dLHBP4+)-SaU&b? z(-J>O3tYpwbkcQOBRtNMIpA@^yIB5&?$eOk+t?~T*}4Fm8L@uCdhyNh)0^O{H^N_U zfX|k|ljr;4yB1HrfV5-ysjkXX_0!z6^kVwlpwFcPMBjaR(+5_}HI>6N>~%?jtBX$C z>-;J^#$Gp&`vrUxwddt=eyrwTBhR_^+4UaNJ#s=1K8C@?O39<=(}UgnXn%cS+A@PntnYiU;^W2%0BNNwdznVLZ! z|H@$nu2-28`eqmBA3#eF3A5X6M#IX-b#4l=TYneYunA1FXsY(ohDGql$rhcluim;Q z2J*<$u;z&5(fR&UH$`I9+rlyGH&EB_@KZU;`#!$Y9FQ$I{46oB3anDU{JfC`67Xg~hK%xNPqKNY_Y&aOum#2;SkME3fUZ2SC*fu1SF z_=YO(3NqLB9J}~Wa-dpvK6uz-Xhrvp&}$C&$TdA{kgG*=BbQy)d_DHNUshe#JO}*} znQ!DA(`e!Se$pQ;zd&ah7;~2_u+GuAyq$I9>xO!IhT$`HeKuH&+=-88$q(RVpF_r< zOCF<^{h(Q~*T%t5e^aG6Y(ss!;g?;|K71~4Xgs=R2L6cS&4$Z2$2G*mJDT>gH-xMI zHgmr)O};%ReKvm(n?1aw;b^MS)4A0^_J$&b^ zxOZAB>${@ul-`4_*o(Kni~V5*-*)4FA07wwX*xcgW8B+%IWr0!<uwBq?7hi<`b0%F+ zi!HM|lNd#!v!+#Jr;Q}Pom@FHvl~9z(lldivooQlB?bLG6P~tfOXKTJwz17AKkD7E zY1IYYipQAEnm{{w9bs;%E~P4GReHD_Y$ocnAFUd5x*Xe>Y1+@Tlj}~NgO@E$do!8~ z`pGt8Qg1L?uPE$ zsgwHh7Wz`_VB!JNg``(+L5@hJF71qWl4w(VP@RI+cgLuWtZxwyMl>Eh~KTS-5cI=gTJim?S9-dF;*>UEC#!q9)zB0GQ z^zjU13h|$g)`9)4Q;;?PJa~%o)_k&G1mAfxwA}^m2v5v6LnSXjH>J?b6K{k{_CYhn z5t{jR)r97u&`dqo1m?RBnn{3Wc)y?YM;%={>%f?sv%uF}?LdF)43!LlW`;mBL!p_S z=r*F6CD6<;Xl6Khyi~QVIWum!MKcdoeU1MKeKd0rIh-|$64g`nHL{JKZ_%G8eVj2( zUl%fFvPX&zL|cV_4DFEZL^M>y+|at+F8U@FpJyk0gV>msd@k(LeQFl%2OC?F*F`gF z(9F&7NK5aqcuxv+lIlKkit(mDwYDeznuc90lXqlnBilTf;Q#5-nLYn+9F5r(fg1et`T8=$F1ri_p?+ zuA&{2ehSl0s=J>4Rp0J{z77rx&+{s4o{tXHu+Lk4uKrh_*CLm(o_Mr|aaA2XjJsrz zTe)IO9R+R>C-rKuWG0w018gY(V{~5bzgfO|;zf$dqqD`F(3R}_QQ8#!75o&NKi7+1 z$A1n?G^OJPCpC3Q9g%0sOa2zQ;wkXp=>7-khx+C$`llSx{#MFX94};n?cxWMBK`HoHIlK;kFVAl zYUF(&#nbcZxYPJ**zENM5qy0Cxm2-nPU9-yoV!TsL?U!CW{*ORx} z{KAWq%qQV$6l0_Ksy!Gdz*qD>3tvyr?jBo4U`(oKn&JcsU#)m{@QMt0#Xa=7V&4g0 zStpLcSH*uG<9_+%X?#^I&M>})`LoWg?T@bx+qv=8yqGf-pxOTTy5l_f+7zMHCTKM= zLaSvFeEn>5lvWc1o1s`eB}&kTNq!D z-gp{c6TwX3>$O}p$D{Zyuv=h3F;_DZ9cAPm8#aE4?#&kMoq*cS4gs)!kAd0V=Pv^qdiYO+4ujTa1 z$Hs)eF}_yAM|Xj*s%I2m*I4`}1KXJqIC<*~zxYCUogH5tc&rnQeUCoa=g#-r;S;Qx zu}2|-v+T<_AI^GXaP|>!_Ov{jh#VW|7S`GsXJU%GPvdP;AKrFE@U{@VmA9ZVH%eND0p zW0@U;w?8-$#@lxAwz?nQewY2-r{{ONTbS#O!CcjI*SIj|{*Ehh=f}p}!{@==W6);d zt6|$}EatA`ndr8Yt1wsfZ9RM@<}Rhq%3GLg%_-9V2kE1j8-4Z~&!U*CXUeNT=IXgH zSJ(bL;R}=_e$XFtZ;JHU@T)%pb8Un7PfqgmSjS zoLc|G=p0W9nDEJV@=|@uZor>|x(E}uN3lveCz!sYA68j9XG9mYFcGX0CZ16iSXHI6 zEUZcjVyixj~=;F)pC(+eLu8QMrM0CRMa4$MrA^DAO)VD8l&b9iojK0-g zbH$cuXPon;_hEyPE?EEDKCF5vstdlNXQZ3Jd}YlJx#CQ$Y6o*P52LvBy!LP-XJ^Lf zg3t2o4O>QFS++5yk$!SvBhFlHmo45+Xt9NLlllg*&d}A!iQJGbI|`9CetR@h2d}a;Rh0r9;x)QAwLmGpTPe>B)x1e zZ&yuho`@d#B-cyP0kOG^WKV(g$^GPiv`%Y$=#jG*5MLiX(%^mqdgM^_$cgBY2eH*k zk9-h4@-p;D`Q9C^ddgb&m+j@5D*Tb+hVGH0_dYb`qplq)=7s`H?2FBvHqm`YR+|_!%Am+jCXog2)})V|N7R_UG+Ws zYf}VQMd!yj&-65Xr@ALa=AZ{3A!{B`el56SAm7&x@>n=(A56?s@>Ki^*#H!CM}Cdc zTk!!ZsiXdqQI1j{*;Z6f16c=EHZzOTNX`!f1F&n0KVQ|E)XB zJKEtLqV@6bgi1!gqx}k_13zZ3`U7BHl#hs4Sb8hhrLXkqtq(=@);&B^n$hqTwM+T+ z$I$O<|2u6B*#@6if41~j@)|^5Hu}Qkr)SF3hK&Mc+^S+Q#4<{)7oJW5ce@#zL#yH}8*CGpZ0EUj#HA_l@psujU$JbO zHwIfRnxl^LH5A{!iLu)RW=3(;qPrA}|27a`rGfpF`^A6Xjqu;X-oaCzrcaKM$5j!m z^~YtLVQcNf*o*pMY{b_3*JA9Cx1XM;7RDl1s2<-U?m%@czCuIlujkH#ua>+DzDi#0 zkFT3mP6S^iuS%EuDrKmwAmbjz*9YNOq6y9%u<$ji6aI|*KAn(n)X%-g!!)ufg0I!g z!9JakF^|%RaQ2y(p#fxwg<4OJ*j!KP8R_OTKl^Z&xZg4;%KI=)r@9wK<{Ey{7LGb%aMTNq(w9B8=vWJI|fw zN#Ye+S5cXZ=CQ|J`Yn9(e(_lNL^Ibu>?DnB2*=+)jhz+^gPmWuurnp_278j_zZB&S zqJLrMF|JMj-lu=|VduL%Q<`FUh1#S1nj-qA*4MP|{#$F$H`uxA{I+M|f%2M4UQz7S zGv#@NaeT$X&J^MSg!NCQy_B?3>{QyQZrYzW{g68J;U+xF!cDGETXjncc=JC3H(76; z0&bpS-NTjTvDQ~!Ku+wy<}=CUd_@C)5@g1%%Q)+mb=TF%GQuy}g(c_ff7CAgV&uLt zvhLc(7=GM!*L~S%uDg1;|0H%{#WeJ0hSywO{nlJhGIkwz*!)_14gK2m z{OV_ocaZj;0271go7#I@mLb0_#Y$v98!^Js?MhD2_GHpG(N5V=9Sc3VGuT7f!TP*0 zu)wc#Pp-YhSbu`?E5q*9O4`vQ!Fud(hu{IGix^>~In2JfUw$r}j`dyShxCAW)T6BL z+RLk^*@uVqdD))P3ASsU>l8BZx5!WX`sDwiy$@5F|9W0S8sV(c-A9@ZWCa)UMH9Mw zU7X_#`J#z2%S86y?IdCH!IEn<0^h|8_zwA`ExuwMjz#-hwak% z@mqH3V8`Gowa~4LygHcIoN=(-&$vtHI~2s%He#2a#s6~p;N#k*_xa){Zg1-i4P*W|GYsTc)+<)p;3l(cw=EcrN}EY-jzKv~|qcs7*QzU0Za? z`9Xbazq(J$I&(XUj}&} z?MLa(?npl-@ZS~bN7L({zta4adkf3?ekR}B=_{@6MxW*JEY{Af zy2{SXp&3?PwYD3J<^5@TFXf7!w?fZBXxmGBMdLr^xp?bcc^{4ClfiIdx%6z|y0Ba^ zm4xTQa!+J^S2%ux{uPe<;05|0i{rZgYjE5(?o1rt^a*iXdl%Z_S*_>8a^fplSl)GR zEVpo+Jj5e*g5|rwa-BIOJlB~7r|~@5!gKE#c%B@C=gEQj7oEoQeT-)m&&8XzRxul*SBzg8rNml8SOsw?#IXVhxeb2>+O05&zK7DIRn?xC;Ib%J=)_A%{Ru_ z^nc1Tjrn^q*j~hZ)0(q4g6*xr(Dw2OrZ0@a^n||<)9d-Is5ReHD}RjtZ$d@&*j^tGP*5{$G!)> zOIKXXn9BF43=Ee%*?~SQpRU3PzRSm`m3Mu8N`FUvx`giz=B?x;$(flEY}Ys9F@H~N z7oA73ojA;AVY}*h0=v~l@ZjV4O`Qwd`}=@3{UA!uVIMI05Zncy2xEI9afo93R5#hir|mY% z7G3wp_n-4ze17?7J_6sdal65H*|}xozES#lT6itF1Din(_G&-*`$6_{D=t_)_{|U@#&N2m9N_!NA`=6{Q(`cHvvX_9psFI{1%bFi+gkeb zhuGftsEiofyXf-Ulp(*tu-!d9@HF%%+Wb$h($k~*Z9DgUILP?OuPu{tk^CxIM83|F zRr}f9pN{Ic2Y%g$gAYaZ+p*BBY+HA6l`odHzD-@Em&(^!`AH6s(rSqP&!Nb(s4e~k z&)x?I?|p0V)LzEQiQT;wyR#$W$1Iz31vscROxc{v>D!O1&(n5=1IDMX^^%!_I`TO}miuraB_>#36jeqS#l@ z|0wop?ONEE#WS_F1v|0!Zhe$aTh9L4*nVzj?ctO3^HKW2i5))3Jm{d`qIP)Ah3I;= z=0Y8P^Y@$!)99b&^pE9t&HrWmSD)R@HEL(Si~pj}sBONId+~(l;afpyL%7!8=5FzW z$o`60ds=^-{@J!D&k6gEN$#zOmxXQXsex_Kw|K!Jt`_ZUT^jzYIg=HcGd1vK(dmpo zhf1dWSvokF0ZnpluB9t?MCvZPe*w?1d09L`bRV_1zxb=Ly&b*$rRZ99s`v$IzRFc? zR2lv4?I*2$>Y46K$ya6F)aXgMWfXCF#>J@0Q*kMf;E zl+&N@{N5^?y(J7_qifN^XJNC}pkF|?b%NF9V6!kf zy7nCWm%kpT{n;N6r!Sjz4xG01)Q`sL$KF00r|Uihr)?h-rx*SWak{(sljHQ!C!;iT z8mE6opZzUy`c;+D52wFJ8L>G1Z_uA;^90veoPMAC{y06EarwA7-SNw_ae5N;DcY*% z`f+eN`5g2zf@e{j*82GW8k|1I+Ib&do2;LI47}EvFMkPM?|$pQ53l!9m;b|SVpa9q zgC==KczqB36UA%cwD9`tT%&k>2mfR7`X9OfTjBL@o`~|E(|FwoPmAL9Zs=S*;XSVX z@p@8Z&YTOcUALVZuRYZLTzK97;@NneBfbHTSjqLn@On7qsGr>A8^!CdlfFM*SMuzW z;Prd#yY7$IZ%6iGH{}Yi&yK}kcV&~|F}W7H zj;0??`rXKztBH#dTwezgdtljAPl+m(}Z^o5-n|za$>)qeKaKZO`B{BSdKdFR>jXa9 z{LP27&-(P&G#-yv1RkZ|Z&2{=M3bw%+`8VI3jU%^uDTcV352 z*!9{&x5wH;C!2=y-#jmDub6A~?N9yhVP80QeVny_JGPu8%6XVGr3O=$zFkFmFS9mo z?du~S?J4*&<=AO6_UxnH@2;}y5c~d%ykBSSk1wDc#opiB7kfY2?&Vf}k^&Q~`kZbv zKDFCbZW21;oye^<#7JozX6;?r{x!a-8N~gd@crUQ9u-{gbf2C6ANr*)i=_V|SMQ=T z;{+_=+4l5gw#95%%baLu-jq#beRyKHeUtQ# zcy;x>%d+NFBK!HnV>@A9FEM#ekMkDJJ=o0ey>Ao4fnR9vU}Eo#W>bs-G6M;A`I;MnM&=i?Z?1iSCwGFea^uaM zvr-MMTuN-2pD-WUd&Hc;pVt=ObqIfTy^A;N(qG^?=XUsq*v8Zob@h+ zA0kFdJ2BrwTiN$7e~a;EZm4=7XVIi}_3SlrPqrDkoxe76_tFO0xDx0G2R?hmit4Jv zUmRZjknAn()cJ55Yq?zSYC}F8j9&?RSa%=e{ZH%-TZp-{ljlm80xzFNy|wO3P~o27 z-hAo^ZyRV#`d8|SZ`$NmokzkL1nEQ8&)rVWmwJ5wV}b00zlinDX*O;w#Qun1M^`)c zH1)%=>%Yjn_yY6e^URZ5nJ>4%I~MqvKUNHpOSbdK+fmE5Y&kxlZE39?!uS z!!YKRkx%SA-m^bEkN3X7e2vawV^YH&=J2q{9R3p5=p23(I^*E2)Vr7q!cO_jSvbX9 zzm;@)X5BN#4>8xh^r7%&%hcWtKYdUb`D1?%^xa(=$K18S(*{^LmOMnf%yiqcbUv(X zyvETUTWxxt&GfBizCSmhoAYh&JMcMwIKFq;efJ)i!~aK^f3mBLtG;iY#!TzDS1@14 zRo~0KV)Y~w!rWL-P;Bk#z4@`--7%>x z^J?rPjDHPtC%|{!S3LeCY!TMGeB)o>^nUkzP*R?%IN=U>RZG8yH?-qX}XJiqW{BroGlMpd6jvr zd={3`2NxIl?;ID$xhnQ9gYhm86#H{}3l9`i-`TxaA4n$V-kLuwUzI?`4D z^^tD)VM>>1s-1e2QHSfutBJN92Ybac@&ddkx&hR--jPzs7UCC7Vuxu#%EOq~E zxGjZh%M|XXgzsnSJ_gS{x*x~;apCvVbw$ z;_dX_lMJs;foG>Or_%UtG<1*-whwIhBm3e06MK8XSYwhsE3P49y5eCBVxO>Lq?=X@ z?jSa-;1Oc$GH31`V9u?oF-9)38Cuuv(f+p}`}gj6KlIWa^RgRG;!`OamF{o{G+wG$ z()eTCLQKf=`Jb+b2e-J835r-35}(D^+>%2cF7}E!$dfo7#KvWxBr*TRkf_h$4Goh*#vhHW3rC#)^PS# zqtB>(lNeg79@IaPi76z{u;Cs|A^N#B7_YY*Va6P)K;O?$lT%d4e6j)65TTE|k{J2(6P zyrk25BDm0!M!J*qcLsKMuMN3~K9@}7Wi0f~494%H@;{8dK4YM#MgC64K#%|06l`m@ ztO~{C-o(0qbng1WX;X`+V?|#b9d7k`A$6FfxpeWa&vZUp>~}=Y%E^IdeI5545bgTd zTUcktbB0R&#%lP_ZpOHsy3QgdSqC&7L?9B zUBkId{Fe{X$x8~5F`1)P?rx2b=C_v^bgqujj?aldKr0JnM<4U4hJvv*^G>ybVfd$- z+E2RX;s%``eeJ%`2H}Ji3y*g*T6#BR%inas*oHXbALj9XJb4|v{ubza0d#&d^nMd` ze#nK#y~pAUviGs zt$ZW@#Iw$^BEJ%i>Hnv5ta2&qzw;ccY%BlspJVm?>;C7SWA*#1KmIvZfBHV-_P_WX ztLfG_{dMP9O}OskpJTP2e$*LY|96hn>2s|9Fy}8j$7(<6#moNQ=U8Q1WBEV(9IMCH ze6V37zeo9nbsOR?(SNf0NbfNDSJxnJ1EIciT*O~q!sYXlF7-P~>{(U-f+9`A^VY}9j zmFDpo#A`=3434tbD<>+rWefz7g@#F@S zCviZ#$dh=sT?_HUaE_uZ&e@TiQA2sO%UXAq?sXe}7x~zYu)|q2q{rcY|PoxL1Nxhx@P?{yPr2m4o1KJvn-xC1*z z6ZVEW#z6b)qTeeow?~86Fuv_>gY6W^@%rM?MlUexR!G> zt-LJ%`b2kI0XEnVLiiTmHSHjNg$85p7{FP3jP?2B`q}sE9KGOP@vK3tUkzmc-vG`M zv$=_}#eNVoV63Q}E?V z#qV1Fuj6_>*R5P{;`$u6>kM@9>cKAUpCnyXC^UdRObz4^6G!_O&5`P-F@a0CKgqrK zl0sL-^~|w>_5|#M3Cz9ACw$5%8I9hVRekS)<=;g{y9rw-`FpWpXgmhZCiW6%Vf9d+ zXc>RAO4%k4az2@2x^o6BG2R^&9jn+gJ97O-{~+FxzVj*%M<)#PcZBeN#f}|1V#`&W zpck+adpMVMlkK0UH`~70jSX%`8Fu;T{W9pN)RxwDgz>8Yqn}vy#qI^R`1%A}LVcbs zp{odf9OY~6wgC+*bG27$K*NTghy9T^i@!x|?uU7%G`Y-0_M^Jn8JmUl1=!>c?X{mb z-bRJZllulZQz5&xExpTR9xNX0$$gUhYIAg#&d(7&b__OiOVK$y(Vy)D8`FcVKXe-1 zk+bQ|++d#3;wFZD2D+zsWNh6RT@|joH&S=rJ)P~%YFLTB_#Dp;k>@kSGx;@huaL4b zc&_}~(OGjCE1hk0nE&nfuosVct3K}juK|8*9x-o%Ir3}Od4OXArC{SC`g8{E5^mc# zFGT(E-BtLTkq5ruU`cu)343-o-&NZDQ66ojx&3@boP||y@Gt>W!+2pje~}zKii>c(r=HmrL(ssJ@7td zXR;2NZmZdNYN@B^_q?l>U1Mnk7pRk)yxOnC-tgRCBV7K1^78KKiPP$9sYfu+)8YWXWS`H%-tdd9$mN-ywa!F4 zeB9^>=7E*)>O=R0v9f{jspUQ$?9jLzhCa?eCgJh;6JvLrI5qTxg@-Ep4Se)F=pXfQ z9hi8E{?XaFs*^BH=bdC@tIEQLp|}Wc@Mys=v#j$7a=;wzGm{N8fphALv7;6btg+4^ zSU%eK5DVLMt{(XWd8WB8ds7EjF=^&+gZ?nHE*CF>{*t~hn>g5 zYn`F-aqzm6eiB}H&_`;M=5f=(&?M0-Hmu57V6xg*%6X2W57~aQsJCRgBJ7Rv*rp`g z9p+s*|0Tz*&n{T88S(o;joG-&K;hAbbw$`I| ze~v|Z(Yc`@;h)cucPrsR{S z;}1fqTk1a8V51#z{QA~!=>IOpM9(ZtXS_!-4<*-Md3o=KKDi&-Y9&TYJGdcS@<6jy z#Tvgcf%o(rzVfbhO$=Pbcd~bPfY7@xG{e0J~W?#`Sqo`)|_CFjWm?%h+HuDJ9Y zs+S+I_68p@;alQ=oGEA<0M^>vfBcrwlA6!jYl2TmVLHG1BdYV_oA)|%_CvGa4b5>IfXF;e@dSSP9cG4(DSU<`K* zFo$>C1g28g;AMmTPR7wU!)RE|y9FlLc`ZB!TfLX^ytMsY_KP4d&h5O+=&^IIUGOr~ zUrXGVg!k@S8$@R4x`bG=X7#hq&B*IpSvMcdx7Z&$F0=U){%K~f#x;1Ar$=#+vKk^{R(80*#E>bR^5);CHN z-(mD1_V_S9`J}y${5x*)v;^-PG2g!2kp~nmp;mw zYFz0=Pa;tJ?MA<{z8@*8k+Mwmqn*geiidV+Rlff)^X+v{xGtrcqi-)mc4kjc<#?{a zD;W!DZ4vd;+?ht5Ji`YJTbN%q7HsP2xWr?veJ~zJ?JJCi?E3@5cER7qUA=kYj5V8v zRTvkKE#^GW2B!>ng!X7{-Jn}&_MddtMVcYWzIyRCG@lhRpa z+7Hk{T{`ozNt;XDhK& z`r1SPs6C&eJ$5ixdhRCVkD^Oj)9XT)P0<{hT;=TUq1^Uik@jZ%o!iS8`~&rg);Eio zyB!yY>wDKd&h8Vu(;U~lzJobZy$3y)cHYU{tLZl%#>LEsP2?NA7A&+IQ$@F4`b7Pw zJ%L{OuN6NE_1`MygXkl6J}7MkG~s||%IK#jpv8RXEe={-#dRihQUU#Nj#)tT;$xl^ zGf(cnf2%c5uAcebiQi|QyvVrEW}e)@Joz5;+m@{Rj954(Ei_a^qe z>r0>6ZKY$L+z^>3!jo)hLUo=&yMv4+vD4-n`KGKSzr=le6*PQ^~a9cXW&|S<;m=e@S%R!w&EA(_YCh(K%Dbd2AKTnbpj3 z&2P;a>0l?(cg}To$)0Ru`{+%Ip<@FN!aA31M-FpzTb>!$RR9e>1{Sz%8Eq~z<%tWk zvBj7fZ3#yA+W4O8151hhhAz`pw4!cfCbl8F@%Gwjm)CAgv-V-61txFq-Jn<^E?Z(- zko|AR@h8YLQ@X~nXZr>Ay>;=-iLO$bjlT!y>^%XmmCmBE(Ys7Dxhu%tq0$w`(Q%Aj z7d-Sz@{^vLZlu-|H}U9A>~)h|XM^uG@x5e3eXnOB*76IP=Lc7Yd7S)VBwKIV##tw1)&q>jj>B?kvBe1KTdcMx z2ITXpSnwBcwHt}`_{Oxw6AxEsK&n5rzhrR%=j>9~2N=^XTYQ^0F1~H3F|_{A@R$`V zs<-_L`HME}-@GDk+cvK3nb~oR4ZTuw7v(s5OQ}zCS5YW)TC`4&qJvIhyu-dE+P{?& z_~$(K2E?V*KZ4)HM*N$SImcRiTl=4Xa1yN2`3I8=dsA~LCqSDkXmfR>ziaW6a1rnI zIP_UTeqHF>ab`U2N?{(3?pnlH9gK5yy|}V&ql~7M)kJ#fyTCc#vp+- ztZjFR#}*}frl}6))K`6Bm~rT6iGh0R{6*SdOTVbE7OlMD#J;tS8$-<9CTuCHR|n}X zpZM+Qc}An8(b)k}l>j>4%obaqc(ra54R}CL4dkZy2X`Tj>+JvPgG4-m_LR z+woDJwdHZ~_3`+b5exFDJJPlf8#mdCE}J4Br8E6^BoE7fP4?HHT^qJ_FC;F7&Lnsa zp9nAGd{;a=H1i{K0Xh_Qxf46_zhhUb8#hs?<2ik@A0vF0sKDeJ>U00D_P&p@6KY5cidNY;KU$fWCpe- z+3yvLrIr5K4BhWSr%S^Ztd%-Dm@BR9d)$XFQ;}`VEOeFx(zRqEzr$;Y<-xvV@$_s@ zOFTR#&rJ0>cCX%;y!+vePV}5YXnJSd=q|~bO=IP^mEpUT|9<9cC*$KsKhc?S(uwww zR^wRcpj__72Rfml6^z$D#^)z{^1Jhx5Qf7 z-C>*Nc9~-mLUCh!(Yh1o+loh|x_9%V4m;F-2W?VJ|8nMxd}Ul0$j>9yH=FVu*O@+viP)>28)0m}oBq9-Dc!oNgdVKhVFT; zvQiDBr7E3t`WE`N^G(o!eKH&Uh_xrfyku`kv}$wP+eq`n%j^s1_6<>&k$WYyb;?c-eaZbH9_t@m61 z{Fl}HbCG)gj`1v`T>SD{JkWkI&#Rd;jJH+)*TVUpQGeBa0d;>5JFb^8xQlNk%i@Pw z<;CAsx`E}JLq11{#~?i<)+hADSLDkd_6hBpP&020vU4VWx$bojj8M5l=_hQ)KA$;s zR>JQ3^x!XQ)2p!~#$WX0W4~lhc<~+U0RM(AfAX6h?&mO?ZrA-G?(IhWtlCq9r`iXYqx6l*Gh=`;QgzU~rjvuG zmKny>=rgW!_0BMj1YOUy7fAS(Vu;t6?jNF8L96a(@yEbr9iitv!P$nupK^CRx{lwTQQySw#MlY`RUAYOZZ3U+-mLnaUAGmq zy=Hn+n$`&tEq~|!?d|B59@Wo}moj?)Dcr9XW-wo(WvE}HZC9RIf1?{oTwhXBsi`p&`waS=<{#TGQ3n&N0kCo~>qHo}zv2*zR_+r{oF7I%pf{ z-Z=)oMSAHpmJezra^8>u*R5ucm~?Y<%%d)Wu_&cRKsMtKu2C)@V2v^JjhQOHXG{a#&||7VngO6WP?dX1Y&ZA32+I?|{>5p}c?8dY>5hV-EJu z8S>>D;P1)7Kelubm^B!g&W?gwmx!!ny~{U_%J1IEoQ>`S zD5GC9**l^*8}k3pqJN@uMEPr;MCZuGl%+Xi#kb&Ur@!sQ=AoZk?3Z|4$g0JeUovjj z+Aiaon}yH0!J0(N-I8z90{5#vw8`;+r#t>o>D{H!uj_qml+fc3=u5kuwMlH>)p1GI z{)001A1vh?-EXGO9pm#qbpHXeQ%^hcEc|+V1>a=RXS2w2^2(^s5$o^tp?FV{Xvij? zqEX0riO6Y5%=={Ke+qPz>hE1OKy(BR#kr58BZ-cV@$FLLAk_@o^_hnm^ZI8C`qmEJ z@QPyAdBih{Ennq?`cB*Gjhc7jVUq2?MBmi~3jDRmePLhanFm~>J!^{(Enl044rci* zCp%D$jih*dKMv z>M#<&pO!k#23$>f+MhxC{SNZYAYT_{db{p9a0_dZH~GBXpU0L`_iaye9yo3=4_F_o zatvm@jIsKL4SAn&if7F1=IV_*4TrB7`_cSi#uPvNHi4M(@e9hk6RN({ExBO@d;e}s z&8T0^{FA)g3STg*%9{&EB0I8osMc1~vX5t3RnF#G@}^!RYi;x^7vCFqSf4%BTN@ouDhDBr9^);h+shm3u`jpUd2ZL>Q_ zJDPfs5vhMZ`dcCSU=?jZ7fVvRqWMPiyAVBd+_&#@*@uSn)c4@B8~Ug`0`JU1*V=?0 z^1}RHYp=7gQ+d`!+NwIOK5XR14MjFh4(FloYcJ0CuVL&hpZ3T+@i88=v6aZDy^#ME z=8!hV4cTkJQH|>n=1ta$((dOuGozONa%6Mv1btM;KABcx+G%X-8CwTq>*o6+#o{_glt zyp;X)_=a}IYf%#T$2IS#Vf@RNPrLJqhH+rQYMv?0AzhKLj$MBfba*55cms4<0)5U0 zkLLNI*VA}N`j@TroK5JKZ_t@?NR&sygLKC1`ZDM>Dr0<(vH#QxY$LXTVZ2@^y)S$= zw>^zDEaJ;Zmh7v)&1l#%3L7-n;gnfJUii1Yl)e5!%P0R9s~$$fGhDr*OZL3zjP2fg z=K4>qW6t8ADEUA<4*hg{1>?s2-hZhXUtiCdtzpcTK#xB9?m_lDEGb{o{Z#o^yMHy* zQ+1GeXJg(ynLMPvhOyiPZ_8osRctBnE4}hr%-p~ar@ovy^8oaxv64-WGqLw~*&f*F zHSKNC7`EI2M~|=c+dF5qJy~>!W-QxN8Mf&yym+Vq;Zq;A%m9G8m zSm)b^W>-0X$v!mjCyw#4g9H8dp}kk|$@ZcBvEb}|Xdi!1MBIPdo`^A@{_FNcjDPGe z-xHC-Hy^eqVmR;qf9;7lwh?)4NP2y|EvZXB=-t?K6vJ>9cKez5#N(?!OPns=5T_`Q|?`S(OD zWIi3jhpY-Zdik41_wKQF_#V0*KFB&-%?=-QeY><<^xmSZ`niqUR)e&1j&I7*ryKJJlhUYr%hwiuG86w#EfZkAtiJ3ev9!mn1{2 zA-(A1@4YAD_m7Id{LkJKabwK~8*boN!Y_=w*#GIj^X-Y4#Cz#4|9QzdWgc|Pj0VX( z`+CE2Rx-YjN*|SdE`%PA-uL1A=mx%QsoypQUm007xNz z<783k=Y`)3$FI@@@_@e)Otr9S2typej(y>$+I$I`X}%#9(!2z<*dii zZ>8AmkpW9ex!>}CdN1WT)1E%yi`Du+?b;Ym_N=CiGRmx`?659t50umA(K$6~EagSYj(r}M6+iq8d(E}f5mt;D_i_5TgSCk~ z)@X_-Q+67~Pf8LV^FR1V*gmRfS~uYQ6f3@x^wT^u$+wXDIgpnnJG$s!>4cNb$A>Sb7%J!NWDO>rMl28Bj+*AK3d;GsyF&c<%?(QM4 zOv*mQoQT>q(y(a|hrH5$dELfl{Qruom#-Ux{BRY&ntSfjv(ABjdeja-)!b|+P1Rsy$7iX7>|P<(rF1SyH}mCY^u7>%A8Y&i5p9s|%d&Yz z>|geX-Agtw>215LI-YI&%HsJavVAcgjvS9mb|7pT#n{?fShKrbKK}8P4Nd2^qg%)Z zH0{o?4af%VsqMdg{nOnoj1TmkdmMUK|Ch7p{WffeV2L{%<2~7ZA>;YGvElew8CQhu zYl^|~DE(rs+hJq-u(1l}^`>ggUh~4_7v{6@kGu%|UmWJ6$F4W6cpQM}?f4xKFnH2bTq%UJ*PkmTC zmbBR(f5*G#v*kBD{Ejy+4Vif6y3xxWj|JZ~o^1-WzvG4$WLNNFt0nGK&l{wjeM9>@ z8W*3L*5)I9Iq7rovyu!_v10W``I;2rUnRP3#m3_t=%|(AUNH|} z<9PfYt@XUT3yn%_;_xTpyyIKI z5T%(M8a!3+W8eMD#YU3SW5=}e+rpY;?0dB#wD+{F=EPSLk@b_1`IE8LrdVq&)t4HT zUGyn-rKhtaYc7X#!fP&Dn!~ctZrN<^%xM_Mdh?q+lbvH`OK3web(7z>`a)~!>W`JQ zZD(AfZ!z=9V>hO7=Jv=9v@etO*J=NDUv| z<|fTd`qx7qALRp5jZJPV{JV68t@1GA*gDLUn_!NfSKVt=w!$|`m)k0XJTEnEl{2_6 z9GO0!y%+9GGp=$k?VCjzhv`qrQ@3$19#Oj6RvE|tH+kMV%9A^U{2IxxP%_?6ZN#G_ zpP@|`RGn8+d@X^}IcTFn)54K7#SMQf7|MGaZ(%W;> z=V#`7to1s(In@y@H3BEGT)^C`QFKzN@2XtEh1(ZW8?7M zGcE5uvl99#xks{#nbD;+(<1uM$@>iWH2zuJJD>x%{Qs&oM@JCu*kq#A>5 z=J~WRT`zd%!V#ip`Sj)PH5#%QkE=-kJNiX?~>S&r#}36nWLu{SjN`MsshVOdsd_vu!>kki+beo8Iv(puFII}OgqVXckv z)cqH^_Pu*2{B8ly#DjW{P8cB?KZM*QKY%0fRMy7VYi&-p_j>>uA!qxxrh&kPjuy0`l^UB{);lDqm1WXGI<{JdJpp?HlG6S6YRTks|T8w zzrj4tV}1uo>tcSpMk~LpO8McIlb_=HB@79tT|<5HnA3$^i{~WGFDi1lT_Z<~a^=sQ z>sp>PKd&dRvYdSC_)g~+tYqApn9rrB41b|vD7Nd-cI479o`^5?^M_>2kAVYV0Q|#R zH?LesJDTJx1)mhYC}zK6=QSaV3A>LVr()l$H%)Ypfu5>MkR6-wRbmb`yfTXQer$kG zFh82mpRGLb@$Sn5neU7|93EGyzIR8yXPrUcxAA=)V_0G{rbg?MK)iuyKH8(?r#{GL zNp9-WSN0w!YmuI+d@v}0JmoI``rUa(yzemi6<8P%uKx*a1^QljzfHdd$5U=~oIizi zbv+BQt`@@AQuS9XaP@-~cQVosI=d;_{&v1qpZt+L)eq=84aez+Ozfqx{m>Shhh$&n zLHncMzpU@+2kU$KLEoz%B$w1il#dmesto+QESf5UvZ>qIga2B00sY~Ck;5+%+s?Rm1 z@AvMs{FfvxF9DZXOT ztDc7`OMM%QPrdiduzVBi@S8c;bItX$^dI`;<*!M0PYlc(-@CyD{+7eP6z_Ewx^gwR zE8ZMr-Lf58I0T*^whdse+uieNR}=IlK2r-#l^MG}Q-jZj$`J;OUpbM*o$SdDTXIIS%(r|b7vWTrO(uwD*UDzULzbW97z00cugkw6%=n@9>&pXc+PFy`@m6T z6?ZlK<_L6INM0TEQ6~IG{6{!i4ZkVizi@Q6!;`xvf}>u>ry4$EryL)A#yi?>;izO+ z{MFrF@_L1D<_z`ZZsQwaXe()};WxEh?G}b6oPnWxnOg~9sD1eeFxB!+!hbo8rQ$d0 zqx&N~s1Y8d{!+WuM>?bG!*nFcFLuVn%b27wCbGGKi@AA>%WlfFV=LHAIm+M8yw~{Z zzxuis{AdKfKTH=up10&A*7h6Xk&XP=Z{t&pNjc^&Y#@?>&A?Llf7ih7sgkjt&opQg z`{vE~ww^ussE#)){S&dpA?wb5KlJpPCD{!R7{-VPIp27jV_5wrGxL>9^fH|#b18Fa z%^_oMW43YmRqYv^yMY+55P7=_Md?F+UKMW_L{k(G~*-fhecTw(Y#yM&jkzVq_kTE0_1ZKj`^SmzL?hQ~Rr z4I5$0BU=oA9cdDVdvblu(`wpeM>Y!m%vRY1jl3}|Y5r<3v=j`T!5H0y+*v^$5Aw~X zJLFHKb1jnspO-uo-#zvDO!)hs%}Sm775lzK?;YJ!v4!FPLab%d*@MPh$KC0pTo;&g zGbb3Ak9+i*Pp_iv$4Q$yB9;D2@h!$jy$N3GJQ3O+o1cd?VSbY7#;f z;%OQcy@mcGOmD@|Tk++oZsJ9|i;-DNky%A=H$kh#&|4|=rn%{$&FY`^oSUeA^^m7k z{`-`F+v)aZQGPpef3Oq366)SWUcqJQqwH$SXy)g!P{|MRCvJ^--x~X#eU%z-WE#b3 zhcBkMzsP_4h$MFdWvUK}%a?h~tjuT6S4#gd z(CZ|#p-))+Quk55NidMqbNOu`ueps~j4k$y+u-%yL5yp1*#EQaKa9C4qO)(tJo}&LPGWFY%i-Z|a}A7P%uVvpP7( zOLJ!eJbPQbF=-g{=0)bsSMiITNLtA@JHgYv@YzQ2bPN4D6g;)C4B0(S&%x2X(CZp- zbPc%G2#(I+{yM&Q>U-wJUU&v`yrdBvUBrLo@f3XKAbA{yM+^m1qxk6MzA=KSYrxbs zqlb}aR^?V`Qu%+Cd`FS*a4_{P@(97JTEXTOLE|r8KE$oGYoPH)(KuuG0Q9{R z`W9xdF^9V!B%dYtA?-x|Y=bYl%wcVI{ExnhpQiZfTgX(~%;B?sHRrPWou*Ow0B!#P zww0H-A2A5IJ8p=t3m*O^_SKj0gMZUD+^uJd!_>rl3XkLIxcM5Fvil~ED8~-F>D|zz zA<%ivQ-gc-eADuYBX;ndIKP&!jGh@hdzELBr#{Gv`sUhLhaP~PWFYpE82{Y8?5Rga zm8@t-zD~m?sXVGabKwZd+>*6})!-{~wlG4nJigpV%fKF`bN+e!h{UR;-OoWQD(?@U z3fsknBRYqVbAAFk7xahdw6YC94$fn{I(iG`%4U26`s~Zrx5a*q&;>g@&`6BYpp~+36XQ>0(W1IA1XTSN%UBiE4zRf-YNZ{o-tEBbl#yu zdD2$d`<}{Xy^B2|iW{&VePAbgjhp&-@y*4r!O|ZR(N$!BEZbPTYzB3Z&9Robs656& zga1SxvN!IGC@sT~>hu+Z^@jb?;Q?hxF{FU{s^bpJU7#`G-lkbv_gTIuu z2Gg17>05)TV1HdXdre+j5|;O4eY{V68c&m-#ly(6E%IF<^BNt# z=LP131Kg4fmw*gbeG&V!pf_YLEB1IMGTkBi&k5hK^IkFd7pXs~r+9c*=Hu8$Gu^V& z;On^miJxt{eKun`fmr_ANWU|ZUnaI6?NzZ)9+Kg38vbbdQqFnU%yY?0@GJ`-Hc_Yk z{(pAXOug7v%Fy4wk{hPY=z8UCxxJ~XOaE_-&k>{IPuPmDLoes*U4$F=ECgaW#znI z94Y@z>eWaZorCZXyo)!-T%ol+KWlwpQ)MB3{o2FDoXCyMx0HG-Pt{v_I{1z=6Vf%m zg0#Vb4c;}-8J|TP!eepny>iig44RMN(&U{V*eYwlvb!%X=<&J>dSn;aLVNA-h?JWQ zm-phho|%+!=eUBNbX!u}g3ye0E_k53clm+Uc4G%L-`4fk@@M0F3l3;q^z?C;2G))6BT2x|OlwDO{OG6LV7LtM%g35-^+NOLczE6rVozb8YHM7< zo_+e+M~wa9e20&3!&~|IXuf&h+7UC1{ST1uQEd8uwhe6?%FkR`z3uW*#{Lm2iJ!$j z<+oNC`zxV&FbU`0? zV@=cK^LToFDf(P}9)HOP8+I)Ha9@z5tOAR#*)J@>mcm{bV!h~`r4*xPt+2(*7_5h< zTJMPMMSMh;V;~qn`*W5Ln*ZdueH$xo@!=Cbr1KCw0$=AqeD5^}7B9=`esNsuM&GiE zZXfSFU|WT`>-B^$rH?8ex$AZIIl6r-(eqxbXs%e`YVP>J7#SiSk?WZa>F(u&5_3q` z6_+rp;`NH|C&smH#OJ(IJ`iuPM)PKzIkJ&?IdS$dIKz`9F9z|S`o%O-XQ_->6E zKg;)eIpx2&QDqy*IOUY>qFmOm-4&Eu^jdjy(Q8wi!TlsV@9ez0nR#0E!Zhs4_#2P+ zw0v2zKkFiywp3r%c=SE?*Jk$GDi?Eg^zxiKxSy#_FQRO8nNj%XTIIIVZm((Y%m+{M z9K;x>ukz?KgZ_a}PxgWZP4Jp%xoKwl6^Dg$vd^9IeDoE+*K^ik&v-sC{R-JJw4Xq} z^eUr_`KdC*bN1Q(A93#Fp~rXau1gzaL~-)r9vRYOEUy70lXXmuhk~t zw{?=BEnW$V2~gXF;AIqzhE^{2oMuMxcp;kfMv&9r38q@9R%=hsmjrCjBvEVRHUotD zy+6-069z=v@Av%i{bOFwJp0+#wbx#It+m%$+n7;F8!pZs-LY}IX(KK-caRqvYx?$j zu%p-BR7Ku-`tt(mF8UMTSw*=ZJ?&wo zQ|_d6%GHvdL^<8Hs`c#4D2?1BoX@diuYCfi<90q@M@Q1qO1aO&=E=&ka9TE`8#xD- zo}@QdpYx2L42-p_|oW% zXP;wS@MB@?HH1uNklb!LRj!`%se?kCwVIQ#q(_9eA;Q|$qCLi^P~pL`0h%`(?LCDd@D{h##B-_x+dZxShguv zzlhPrIMn9Jea$k{@NJvvQ=c5h%w0T-*$1FkvR{i7famOov9ZMa2~4OzaV&Y1RX=Ys z%UXR<9~C18ozNJ`=o+I1BjOoQx9W(GGmk!W(zePgU%Y-N<)o*QEU11-mMKm)#)#J_ zKGPVZ@|q*TSK~X%9CUCWlWebQ9jX1|C#*cyxt;RlMMs!$SHI%$63kby-<3PY^)G== z-a`2w!*^I^#}CzCfsI2m>8k(KdigeUBjpRAJ3hv+ku$>vo@!^ge4*rnB(YxzZE=HR`Xs)Il;3%b}yWD&X^W_({8N4iT+?qiC!t2@|F(p zm!#(r|LVrjh@vt_YFEIX)5Tiq4}#YgymU?}JA%xh2Ri`OQAEG2eh8i!!R5e1@M0e; z%5`M)dx-;k;=2WJ)^Sl5W%WHDdRoIB!kx^CIfp+o!om@Kt2obCbc8yyfm<>8Pt=ob zj#sdoMf%M{a8(~HSP14N#8=(h6J1mWEZqDGfW=&XpU`J7<>KSkcoZY_AZ2ZQ(=)th z#7u0u(#j4+A9wmE`5Vw_C)Ly}ce|1r^K7{vSbfpjwblq6poxod+|U^2Q2t)vVdb^t zWx)o!*Mzm7ZjPmBthJuJxz>6Tu4^q#qmISYv7}TsusWa1Florw+PKHsy`M76mssVj zv1U>}%PhagX2x|HT3hN@_oP$TEOxlSOJmU(l&2#fKYILw#S5!W!)x5xZO7Ll{yh&F zOZIN0SFEnP7#g0&U2QQKSa;RmN552;@b3g1GfgHQrOpuuMw1L#N>6%dDQ9DWi9|7HYa3)8ZuJS>>`u&1nb7z0N+pL?5ghw?ebz-{1J z2;G8g6O#Eq3%cNgRxdwV`&tHP2)ak)-cebN9@f*%`)2S`dJ=2SGlD)7&jf$Oi5ipqv z?=>z```RtQMD(!=dH=(qIno+DF-M2SKHa<_bwjiCGSH0OnpXoKH?99pe4(AxrM~7) zF$RR!nhQ5=&j}e_Uew0C=z~(2E9Sw#B*EwT6(aOGq*UbJGk>tFbVK$p>Fk2araN;&pauA9W-C- zF}@D(Um_cU^!_^JAMX1LqEk;(EVBS@A7pGU8$Rg3?hySK4c1*{#KbZ0LQ@|s9LO+n zwu5+5!c&b?v4S*ipFO>CJ2v|+^iRa7iR6Ks4Scr&*G-H+4}58bf1+%W@=B-K!+5`r zURiwl$+n1ThBuOioFUz~se5AI!M3`eeTBG1&Y<@65PjQ@AGnt_yXnzyhwHF~G_bS$ z8}~y*%r;NHW3GaJ>dw1FTf&bE2RV!3%#8M=OO~8^4mh_ie^+zTO_r=G9gJjE&x6Ak zrqoOgry%bp-&7S|m%qc588^k`)v5pMguE&n>bSf*k8)F~vpWCHW*6nKW9rj+-j&2R zxyrEQ)2Ya%TU%G>NH$F-PO@avk+dWEH2I^-@QeADeA<1Ad@3EBDWBdnsV(WJ-as;C zQc}DT#XtKL8Eq>v8nN0uFRgs&$!}mExEbB}HI;X^MQx+2|Mtq`Iooaa>hrNtevEI| zaQ|5ccvEuBv1}dBbB`HgN(^J!ORucTd7FNrpC9`TW7PaJKe{9Q{rq>E|7IKA*MqI$ z_L$tdJtnsjUug#C1d*-q>sw=e*ovIEhdJTA;FR?2X&)&aU)GcIBk#%92N;aq%~LpX zI@#4lJFZh?*I$sooIZ7&BD*G$_f*;SY4Qq}1N8NT{F^;3sC4>tQaXM5snY4w7M@9z zJ4r^hWlvkJbjqESPPqq_PPr946{`j%2)2`U&gC6LcIG;3uLln;8;dk_=EJZpvSLn( z4r{+`G1uq`z9S1BSnIaKZt)G;*BYQ1o%|+&1I7>^o+>{bWQw$)k8h$Ys!R25qO6bq zH=1R=?Df{3tFs!FvFKE4Q1z;8yj(Z5r!!Vg`Qr6zZK@x3p1N~X`4j0%9ejT%R_`vJ z;-NaJw>P0~*11`?c%HB7cV0{e$%3bEpq_ZY)joDMCcmEr-;b<>{Au0&fI&Cxq#RdpSyQV^5-$WweW;fiElg)KYDMBC)@_@v+VFJ zzR;Ut&5!cOVI(+$>uL9$w1=ezMK?7cC-_707Zxpk1DVbzn869qU4T>R0hR!qJKZK1njEwFg^sQkk%4=OIh0A8KP4PvNrqQaDt` z;!zUIeAT|)5!<&VzeWg>?*-{=RZ?56!uS7Sd z^Fz_?+B{=G_F0vmbLRnR^RPRe%lW{3Y)P-=E^+sAVpA-y4qrRoTl|eFoy}z_N?RJf zVEMA}_olqtJbyH?)0g|g=S}%t^V~FVvGR_b@=kMEmQ{A?l((Dped?6oHoK;DH5Z(< zt9eYi_lc4}aSt*uDa}JhH@HWMz3Min_X!u@_Ht&n#xPnxq`&f;c^>Z%yOJ3 zsGRv9{@AR;X$<6HzcM!l+X7&EQXMI$)G;!ljxn)1Qj7ruyOp`-TvUb=>)5P*j6S7~ z^n^OH6aI4_u-PZKQrWv)+~H!C4;mNC#l4Dh)z zTu{AE;FSx!Y^0ZsKauxq@7bB-+MUaJy07-!(TTJ_Fvq?dJB$Z>?QF*mTU=+di*@mNX#Gu6^v%S**o$i) zN($t{v(;X0M52w@^hRBQ=zQ+AFEJvbCAsiWoUtvc=WH%b{aOJ|a%aXW`OO&V{%&CL zCh<8A@O=9P%SI+&{x(-$;GcwlY1WJEH#?2pHh9Z);>#%iQl)7xyvtkM_(k1ZD~ol!8;;LP=kwN|_h#Y!bMUxa-6Qo>IOAQ*&m4JF|pG+MDNtH!W*!2(QOB zLT72uL!%EZ^hUPveh5CblezW5dv$f3v*^G@M&!eGY@3-6(=G$r)51K-&(&#r=+)lI!vl(mbJ%HYdy4)=#~K5@ z)1GP$v>AmOR}!{Hv#~X*Vr*`{&m^yS^XK0{cBsRq2%IUAtt9WlpOOx2C11xU0~-Lh zEqg%;c0Xmjmpte&Z3RjU%CuqwJvwLMZ04!Nzz&J`xzsIQ0zP}lUbB81<$h_|?M_We zTUePbU#q-jJ6|&v<#SG0Ng462$=Ddh?IA<2Qs&RtL-I8J6fUq4OE<~m#>S`w8>4-% zsBE&Q7yKw8mX(k92I^6atX{jTtL5yXfN=Nr{%F%1%uCbZXsh1u8;CYNbOw7gd0Xs8 zvA#*hKKzog?RDU^gLx`=9Gi#5wq?#skuA9^yZWO^{xJC);2o=Kd_(%g1Fw18*I$}f zWZMkxIUZi3rsvnKL(WX!BM%p%LmFP^} zsJcs9*4!Mf%c;90vxZ7ljD zcJzO|%GkCC|Jp=<={tdUqMeTEH;s*sbJ&Skf!%lNT=2{O(q7X4C;rl!cg=YreUQ(& z(-!k*$j6WWLTE2zdY|~P!ht=+NA9#+IM6|Shdbm&;|%?LZeVAGqzK@T>c0&NQ(hm+#!>YsiDoTJ8Y;{rs;7et*O! z3m=TGR{pyj>5cAJ%4d~CjAh*q8;fMKe=dN%!(Z^)=D zV|^>@we<<)e){nS>s5FL-&&M=uWi|;%h>-~jb(k@F=x^W z)W!M3qIuXpmD2~=HEAz7`YofK^VGD^f0P!7?9QU?z@&~f7t*|v&r2Q4SzBiR;LYSG zDIQJVxrbs}?hf0seBOKLkDdN(VvhDrw)=kq{p!Yc6nnH~d5!oF@%{P{vu0}VK?gb@ zUyJ~7F=+>N$|ig*{(1AV&t;#+rvFT6HhxaxgO?=bI{d({z4_hXJqbJ8dH3d--}P>OuYT10UWbi6?Yuni+R0XV-mULzt@6D0!Gp}3 zJJBj1|K1-fk3Q}#wck@{mFL|o-ybW_dn@DG?wAnn-h)mIcx>5e?0%m8_haDV-48GG z2r?aTfCm~-ytN@XfD^00BjS;pbF`Sb-r~5m4WAfK2>2Pm*I}DDEdU)8e#w7+#;4KN zqYfi&{hQj)(+4Vk#2f*$&KD+)9#?r!IPOn)CqBmVAKbybix0HyFLU~5^KSVQX7+c` zwtNqz^Oiqh_Su&0rRtj-m^3;c8%FLy;!cR1E;n+|(QgqecWP1K9O`poU#IZ~CKm-X z=JF|)R3Zcbj|E;nq|!ANw`S>TlFUH6koqjjf34|Yo813ln!KK9A^9mRh6 zanFmt*InqBjZ9Vi-FuPW$@|*)yK%AUA03RpcUYjAGGS?Y#wtwV!COjqkgnwJ-g5 zv}rW-E=)hNT;8I#No7S*Xuuk;MQ`Kl&c?gw*)M5NbWk*2b&KZ2W5YP7=Zy&ZbgfFCh3uIjxnJ`Zc*k*M2w2Jna1F?k;5Vb<5o!Bw=; za`ycJ@vY)xp;`VS=xPhRZsxXVYdULAFc+*7_fPFL;0AjqdnkLW_E7a@VGQ0wum;BQ zJx8#XkDu(0YcufEg_qdNT3XEe1H4=C%Lo?GC-j18!pY*>jn;$kGR625KUD!A#{Qys zHU$;(6U%{?8O!d$UJ_qtt|P(kVYs&je!se7D>36Hz&FBE*C(dGXu-@)KQ*3^VkU#1 z=nI3)b#WT70)N_#I${jft-81cUWvU``r2alr=gh1ZS?&aVkWa!ox}&7L%n~O4}w;o zmJcHRf5Hbzhm?+POS-Fn&BKiE9-pjzf-%+>5^;z->Jb8{bPr_Yzy$FXi46RkGIr!6J+VeT2WWyaY&N7|P4{23o4`u}_=+VoB6Be3vef3{nEkYpD1 zTl-Pp5PoI_>oiu@{ESXx8~*MdZ1wTy$|l@_bd7&MelvT!8M|lh5-WC3+IgZ;C&zEz zHDJYWUPqsHC7qD@LRSGNWVbT$4aja~F`vuHq}!1De8B1l^h5nRY@aYqXTJyEH1X7= zT>)rU@8w2e5^)>K66DWWlqq5E9G3%^n6HbA`xZ@E(`H*%Dqap>7Y9$L8GFHnucv+4 z8f3D$v;mDzlf3HST`(c4P)*D}!vJ0H}Yr2MFFgQq8TnNdbvSF()vER^e=-&|w;4s6 z?+fYMz1-o_f$aM81L%j3|7gKse5jTFJae{!bCtvP@zeCaG5!wC)Vty>TJw`L?HT@u z27k1`dUqzRANpoY^Yi~LWQw?-rSqH2Ju-ObCG_9)owc1jcG7LgXc6AizH*cced6Pyvp+(B0bFQ11k3-;%X!-YJb6NHe&gDGH4zf>3_B+6R zq%F4>1-Mscz{`5M=@`DC@cS-g#JJD2bWtVg$TX~X@jCj>9RdRl;GBDUL-X8x=#1_3 zdam2@z~$H;A-b^-yHM4mJz_Qg6ZKq9-V^m)YcxLzdM?p-(IEJ_lk{BBx6|sm)({i- ztMptg<0!)#^YJ{Lp6mIXll5E$ylcGDbGaQS^jurnBifN&1iyUvG!(;`Z?QjZf5li9 zM8~~Y=b-3-Qf$P@f#+&~=Ysdzor|s~c=m+>FY;I!u+BZm9z{%C?YE(SGumfs-TsSZ zcb+R*7r9+?eeehWcl-9+ALEnbxX{z$H)h81>o7cL8?ycc@Jzl5MRw!y!*3S*@6;UI zGrQ0i4QzVElGiJEMsD{;-pJ6It?VczQ)LI+$}bGO{u#XV1Y_nVaQZ3aWaRCc7M?1O zOJ=YTU0{6w#_y(amuy|&^MvD0Te?ZFjvdk2($wH##_lE$`=lohmwfaGWx&*}Js+4! zwyzt7?vC@xkl`%)7&@(e>ALtBR$u79L}OrHobYZ#@+h*-DhKmHU6SwqiTt9KIQ)uK5UJ@zj?7A-HBi05uQ|oC-u++>5xR*-Q3FLQQpXoOO&SjkquiNHj`PwJ6y*48^{v^@7$E*JhwgL3?ni99I5$7L1K{p{8 za22#EKs+b$6kgJ_uez{3Qr`}r?FzVKZTFI{cGYI@bk4J-$0Kf`=161IxA=H+R~mt{ zNUtKj7<||LvIjXk>Z4BO%XS%&iF{XEhpSyCY&yU>@z|50$?=#%bFjM;pUqk9q8@Y( ziv1JdsrC}v66_`dJLCeBRtpwdXT54~vWxS!tY8M;)%J4WatOIg`Zn?1)!gl&{dg4L z4`KiEI`(><$VBfWAMKG`gl<`Sw-1qvKIAUN5Z`o{VmIG!p{(M&a95YRjyQ__^4YZ0lTX#J@zF}xno@UR96Z0*bYWN&kvnx*1ZI{Tu7Ss z;~wUumFG2MRL}jfdTuyvJ?Bz}waj@HG|zEkcp~Fgo7Vfc!a0H=xc?yeboN!h2AWO% zij7x9{h>y0`#lql$ieyENbV)@rZYC?_)3lTKV&H$H+Joc^ZQ+Vy@~UyJyCIfd#P`x z&HF0nP{l_D$AmLYony8LHtF!L@I)=6yfwmk*&|Blzl(bd-{NdbKCt-37T3;Y4&jwV zTjrrZN`@95!4|HT_;|wkD{E@PvJ=OSg8PJty-EH&=9~l9!V>&-CP9ydo4ckpG#8P# zm$uy_4f77ZGSOGrU)Y@0laL1ssbiO&agx82{6@_^VT@VVtB>(BI|p?KuuD;%=aK9C z9L1hen=@JU=i73+HZf14qX82qjbIz{-hJG?AUy4$E+4qqOAO3i!L?u9SBjjDEv$3p z+zs}@GVD=hPm=3d@GA6`Gu}GXO!KLGJ}1+c+0g0(`?;gU%+Fmy>>&ig%ZrPNj58WlS ziSa+hJsTmur2}vC+iYXt;BEMSF!rIlgy0o`!GL%M-6d2OTQ6nYr=7T7O2=F4<)WWj z>&3+Bu!Yk)OMaO2zqek_{|DB~-PE%~>-77h&Gn+Q**i%~#PxEcJ-A zxxqg27XQ&*e?D*aXun_{ShsFL9W=yyhIgyW%YAY6MzPj`y>-VWA=bGu%-Fh`JzZ;I z|3Yu%?n{kUV4N1MO%6nXRXw!C=QN5g1ujnAb@V;%;I?O&cO7lwuA__Ti{3W_)85Hf ze)U~Pw=-YmmS6JulzH%SY+bPfs3)FE3qH&B&@Jf4zyZ!PqVU`WjC(z?dFxZ@ZwcQ^ z>e>UpwDySKLZ2HliSNSRyO#CrzIWon`Phh*Q@(f%{x7erZFY0-z|30jlkSlpm~mFC zSR8Km{ zpU>WT8-4)XhftqPY-wQk{B{>SL#RBOi4~ z!GW~uL$?nL%smJF8{Y!(Uh98m_d8j88Q|qX#?%MzT1=h2x#-P++2QlCsmGS1%vRUl zH^PW~deNLfG@vWUs|1%kDoH%OJ*C(K0DhR*+=;n$1QDpnRntoRX6Y+nv9KeO|T6b)uugYHDlVv z{aKvBRoAgMx)=xh-I!0w*TPuds&ND3923U6H_YTM@8%q6f>Bh&oB{jdP-a$<^d2r? zsPmCN=5z}&jYJm&&k*mjPZ11zu>(8u{1t&9Fm-+uXj8w`hq4EJ{C8D%pj%Qo!ShOf zSJ4-hze2P=2AfP*t^8t*J)O z<%SoSk1o-Z!uij`wq>4GYjbMRDa}PLs=S~f#~eQ}7R>5Loq$;>_gtB9ios}C@7Kd< z6Eb-sd_DvJ1mC$2oWp!gZQBa&T>_u^8S~U%>hvs?y*xHNjbj>f#K*n>Pp&aM0&F+h zJk?3?%`XG%?SqbGk2yv+zO>`1oZRD%ffrdnW8QqK`P0p%#gExXH-5uDy6bafz5(nS z*HLyfazqI>8WpT%JN16z809%Pd1T{DS9#m^*w3r#z(#TpXSjMwmg%QIA^MX-f848# zYisG#e4h23TbMro^lLu#3Qm3K3hty&we;x`$Ee1o^l8taW1xyY{f>LIU!YHq*he*f zW*gP@8GZUU`owx4^A5aPls4mi>T{%crY0vhE;ajfPE|L3*$A$vPZ!fC?ae*tr1Hm) z^6xFGTX5bM0AZSg-dHlSO6TCe1;4;i~Ynm-T&^bzTAu zO!`xFQQrvGkE6M*mvuM~`WI$h9)T`strobP=KW@y|6sw*q_g9&IiHVj40u^s>l)Xx zrFcUfbiN)rsH2X3kM-F8Q1J%sy>;vh(6DX9@d{p1FxXT_+AqLa=^NG~!^j8txm;s? zA$>bYyJ7mEc|ZK&WdZH0hi>EkY5H!pFBQzT%Yz_Xx2uV;MXHMO^w z(Pwzw8qtxsJnlmOif?<3fqjSUI>b+h$RmB3POgdO+( znmSq5&-(lMCi|=qbv95w$&t~eI$Yp#M!*PspYN)7=7&b0fO@NWm!6}Nv_zTnJERM* zX097-`tR=^Z~800D#qjD2VAX~Ieb4Kywh6Idecw)vV58(qm_QhIFR+EODW<12iz5> za|6@oiTPFDUz|N?;_Xm5@)wfV8Ox`1$po*QlCK*)dXY5Q5{SQym+uDW|CMy5eUqQ` zN?KPJ@l(6!$DZf%l<(OLezIjhkKZ(Y(g(;6K=PvUqf;?uMn82*Ka|5y={i%>a~x0U zHz)I(#814o(y@IhQa#dD>0R<{9d$@=kjiiVcVhS80K=4zqfPOABlsq}1C>eS+m}&R z^YPy1Xwyi(E1%Yo@@Y91Oyt`Q!1A1ahJ9^Y$(^T3Yd|@#;>gJzxt~0J4QqXAJ}2~ zqD1E?{&2#*@M{!%I2Lz!oo#@%u!sR{BmPaW{6=G-44JkC8QPa&%+kE9$L`b^RkvUZ zZPg7g-HL4TF1{j>+{bOj#xVO<`*k}msT=Oyx)*+0GD-asZ+l(R?5)lU&WoM4t%6f6 zI;>jhL--#h=2(>S$V#8**G-3)#}9+``cv7;IgvAsj!Ogs!J=0(4CN}2b6lJ|i58Dy zE;I+PBMWq(k9klqKsSHyY6G2zh5v%H{E-xs`zUv6)K<-y756bP@9UalGi}F1)NkSo zv`Td!=8g`P{n<#x(L331P_$inMVnlsH$fYi6YO)Hob@`F%a)_#_ol7xEbhF?vj;Xk z`UB3&ALjSNi*p}L4&+uCk^2rH3tw}x@1Sq>>|)7)A?(9ipk)Qb3-F14@)X|wfW9d9 z)4TM|{ElzBWSQUcu6!Z%NuslzX5Z6-%gG;gSaZG~8Dx<8Hv8RS*E8ZgmSA%}+3V_*YBNS}zKytXXWIfnc=zV)<7SL1!E8T!67`yJi>}cf38{f&&&%gAJut}q z(JlkN1HD2gdWC#o<;Ewj&;}iZ2G^CspRX)4bqp81gw7kgaC8f;_2{?2H_7XSPeX^b z#_+F3-q_FcnoZHByU}l%c=Cw@JV^~sVof|t`dai`^^83?W{aGkzTVPXO$N95&B2eS z@9f!uMr1>H+@X9Y^jpMYrXK2k+>+O+n?A25P5FJo2l&0a1ylO+2htB*a~=L&3mG$T zSaaeY0w=gA_zKTeR{!JWZ;O@x4dvDUF(zL98s9wY4j6M@yq0V|h>oEGJ&l+B6S;2v zJ;>SH%>6bk`1vO)pBB7^`tG^)_S|;7DG&Pdr5G;Y+7afsg1&}% z`nFhOtN;eXsZX$u$8xb#k9dpdni1e^7IEmZiItdxpX50FB*!xs6QIMx@mI!1)(cOH zA3_Mc3=ubVv1pX=@_C!zel>W>Gq90%!OI@`DqQ(Z{}%S{1Ehs$J2~J*ug>`&c?H8T?Qri9l?~>>LnbzZ6{l9qH8ha{j-&{C4tnnfbDUm!FdF zH>9HzdpZA~zv*8>z8xwDTrVac<=@T!Blnn4-!DiP9L9pnoaK0skH;Rk=2l>M3$Xka zFufVr-ozTYF#xPhI#Gem_(uGEd!In|aM=72aM}q^)SX#($x-eiJ~s8TK(uyPpu{$; z8lP0|LvaKj{b@tah0x_P&b2()Nrd1*g6Ns{5Q}IweEQA&znT8@f^U5@k+p%d;JpOB zbt(JUIO5Vd@XHT@YyCg8`Sq=D@9g3VTYYm7IG5uG)rCISY1kWkiJQQgGa+2?7dyjt z?NzIgfhswRyZ~7ZS!hR?^Z#MySsHf1_)B0fY1*?aC@t=V&;0m4leR1?fbZ$ZzI;V5 zG}DdE<1u0cL7N7`=)}O^mu&~Gh!~qn{CP&n2W9VG^oPvKyl`~CQQWNljKHRjJ-3{@ zytpr6(WQ*-mSm%d_?n(_aHfYohLNQXj??)EvDd(#SH~Oc6))ug``ba{VSa{h}#5%jtT4%p|&RS=ig~Oi|`d35yb4(o0@nk(V*mNs=x5lJ7_(#Si zcxznqxGQZBdY~lu9>vAjGu%7S0^Qq#to8{yls%UdSC8jW;HsU?VKM7QtC{gedns^@R3=^M8pJ zhS+zwkG;5nGl@jFEcp&Lp3mF-4Zx)%PJdn;GS+;v;2Em!|(DQf~NMe zj+0m);No4gIor7cxb-B^i2sj#JG92r&Nu1Un<~e6Y-5Ol`{>Def5Ep^COvSPbmEP8 z-V40#+fK>*GT-RWlIglu-;5;hSjJXJ>lbH5b1{FO`p;tUJ{@ zA0I9qF!SL2h*Rd9NcYBACi}XbJ-=KWc(LtY*?^@CmVSknKp_82-gZmcV1qZ=YaQN7f;}J|`gB6;? zyl^(#om_XxgQ-U09DXK#!vhgpmomdViZk{XaC<+$_K&0sA$CB9Q8a|Nzl)v(v%Qtp zdj8L!B5%!cp&34D< zfb*BkUdAtc+cnxKJQe5c71sD0sq577e_*vYH2&YKz0=^_+*8KXNxsDK|2yx(xi?Q4 z&#y^O9Q)6e51eZ|CEqsE6UY6s@_}VI)E&b?V>;oLXrM+LNUvDR=$y19om zkoFFGpVQSX-G_N(D_6DbKo_dLu2pu%ak~Ec$$ed2ZS^%Z*4G}<%`BIH zFLeFeq~W8PS-%t8G z7W#6YS*PKDn5PfC)cHmo`>y=vI`ljje?ZPw?nXwu8$MroLhO~2XVbVZCWXFMNPa|4 zaZcxaRPUoK8EF{rD)$<5qO^-{u;NY+r`+jc<-b#LyeW!)OS+J7xdXm+7`*=(0m;Yc z9cnbbT`^l0#io}$T=wMD(QzN`3i=zGESn+h(fC&J#8lHyd&wwcbk7|8T!~>Me&Ox( z6^-N7T#(A`->kKY)T!CeFXjIP6G73mR=$YeNi|1 zkWM@N1ai0!ICb*g!+QsOfv@s7dK12J4u}3Ea+cagXO6z5MtYxrq(56&qo?*K>;JMp zm!8re;jCgqg_x5T?s!(eguiCIDDEs$UzIKxZ^;J6u~>wO`ejqsv&Pa{5d3j{nBS0& zj&i-*Eu5bU&R-6GNY0GQ=Eey4))m%0&XTWsXak%z=TW-3)ZdJV{1@LfuV2#7?HYkz zS&C)#C=podHietVK7gOAcW+ZkJD-y4hk^yRxI<9OK{!%KshbBz01>|pK^JZ59F z>%%q#Ki9$#YcN8-G|p}BWqr2(wa|YETJpi6LcerxPGDC%%BWEvoKb7s7txpf==^gs zS$j#|nib%K*0*$Wiov&JEcaJ#P+r~tmJwXdnl5IYFD9?jb~b7(hW`=L)Q^I}XrbZ? ziz#UZN&k9bUUFFxEezl6L4Gjpdcp$u-I9twS{Qhj&)g91O zjn$cq?E~Xoh3q9Ai^`*OZ!+_dz5^e2CueR>+RkD99pSrTTFO3V4f31hlL$WS(Be$y z>fQLdyq5W_8*9vXowN_%x&pbJ_%x4s!=0?d2z6*J7O)n>oTF$hMow9aOIWk|rZVxh zcoX<=y0w_iS~SqTg%Z|ch_z^={%+Rd!@lE9oJ*K%F~nR+zo~h8&V-llZ9Vxu%wykM zfSi480Q~X4l|P8xb9S(WHGyr!wYjss%jU5zI~mjc;7Bk1&SM_xxQmbbLxX+b;e2Sy zmEcJ&bfuAdK3b=(ZLWew%!8(I&u4!g@}lkraO+Hfn`oHeCK^@*+!AS+bnt@38!@`@W7b_Aaj3rze$ox~ zf$MW!=n@!PE&iu{z-blqHi`Fg;?K+m7hN{u3zA3c0-J>0E|(FhrG3R!sN~)iGfrYA zHYfZNY0SI7w$|EM=U~&h<*{=I)=Y=Fu2O?3q<>l0>_sPRH}A-TuH*k#BDESLr64*|}qL@$sI`d;D7u>&xJ5?Ufq&77)*awbu(@@(F%k z+Bf9il?;xQvu0SUH7W8@zo4;MwyfJ9vIPv_Z~?fuiC9R&%ir^VKjTiOJ=MEG^-@4s5^edv(iSne^K8MowA-S^kVP1)((eS~|$x-*UTz36;m@%e-3Z{K|A5+u-&EV&v9!!q$9U1x7cj;Z_~H5RZ5O>X$gh0zeLlkZz4C5eZ7ll1YUIf$ z!bPufPrJr!<@RnHN_W`J`%pRTBvfuE zw7d5T?7eo}+U9{q3C~LDzmGXwl7Y_k0nW9Vt9{6#vRx#WT~l|hYzZCyO{AA5e7jq; zpMDu1%?OJh(7CUTepOPJi?qtI*rU)NVmW$>ZQ04Xd#RgxOdTipH7{9#4^Ok!WJYj@ z_}CjArp{yyX(9S(qmTMlyOzC;av#Lf?`AGtt8Q&eTJ`O4fou`%N&P#pO91ZGYkBs< z|9fP&wsPf@$@C9f6%#JGwvqiyYpTM1j*-EoG5FY^EfLz9?)bJj2I15@-NgK0PBaJ8 z*Gvr0STmumVCSuEF8CbT1G#rjX!Cs+Ur5FJ*nO72;gmQZvzW^pZx0vgyjixFvcb_F zthgG}IRnmNeva(3;l@Y27-&m9`X$9%*ly41ulo*u3+Puv^Nq-A!E(jDmTx{bva5J6 z80oDkLocrVT=>Gh&CTe!BZ|o-KlD%eeMVcNKLy;aQ!YCu%9Yda&Ct&C790L^nM3h( z`X0|OTst@0+kPJV5%hIzIWbapfES_p@VvA$pa0u=CiCngjWGp#9V0z`+^3v;@S*pX zR#&%mRaUoc#KvPWw%zax#0yL6xAR{zvpHs<}r2yO|Jp zvYoZ&<-h6sP8)}@YdbpGi0r+_Xn&V;m~QNSLfA*-pd-I|<2U?m$dXyVILq&pjSOW& zQ;o<~_#LXxk*VzAq=zoD?o^UZ@b=Q;elI?(53HyO>nq1V-#j*Ou^q z2exDK4X8-D-va)%sYYZudgS;Rd=8`d2J8Yppl;>W+0#qpRlYLiC$I8+ z7>RCEJbKZ4@nowevlcG#KGBVCdJ=TNcP6|!G*Wq@!;M$G@Ld~L+#goV-AZ_~B=AOK z9S^Tj$J%hBZ_njjJYC6Pv}vQmi1^5-G|>gEJH^|cgdBg>v({QwTtS_8Jj?rH@@kDf z&6%(p*@x*C6nk84pl+WH9JwPt&n_jT4;bI2IFU}$6}Pw?yw+VZeVnxhgWX>U-;3F+OB~7l zE#G3Tj>v8_n3LD<=RBSLp_e{I?c>p>I5)T|@%x~EbRAu=qMVhUg&r zCHkUuKMNYR78(}be@38>^(8wF!C2!txWovAISV)ftmEYc@9w+3kr@k*H))<~xl2Lq zS59xp>0^E^*(0fc6aJz4CcH~};DK--G|-7ILOh^(mWQsQf;FjqCLh1HUg~gjW~BFS z=tc?O1)mD!5b>X)p|x||{dJsG6+pWs-{kRM_NpfRg1+=}mL8$ZpP?l`zJDY#P*Q&h zelNY>Ga}LVjP|}Fp0^v3JFwAAeV~Te$gCII<1ES4ok(YLFFKDF_PTm>)Nimy_au3_ z)7as^b2$D2ydR!~u3~ImyK|(gQTVAn$4&nhV-Iy3JfrgN<(`tK_DBzJ?UCl1TaS$;=)x8x9&m{Z~Xp!mTy@vXKvz2WydC% z!4uYm;QzADwCG4YMo|GUHLz`4;c(4QO#v6NbrZeO9IgpP7l~*1GVMq;X~)ITh=v&L zXt~JZAOBI>;k@t!?f4me7VXg5irQ2A>!BU#i;X}IbfXU33-7O_2Uc`;ifC^|w4?Lj0zlk1i@rnn-1+jh5T-R}43mvQWLHV*3U@veGT8uoQ zyTOaKhxRz?n@6%|pF>~tZ7cc;t!w?4p6YFUI9tf;x&U5aim^=mTsQ6Nj<3V?3q!T_ zT0fs4zxA_*WcTIS%B{aVw8xjoG}1DDPq)PwFXOUQRzuUqSjs z--@NrEubB@Ne@zj1=y&&Y(HG!vTwSJ@>MqIpX%B;=bV0nd#mb!sbI1RzFB?y^hd)3 zpFlUCIRagPzGg!!i5&r~vinn@fqk!)vEODl-mv+hzy?Q(x!>;O?CwU}>DEG)xfW)y z7GQSGebhNwYa#0&-ba1lP<$W#_}NLZE42(<>L3~_r^Iz{oPA$}?=_-E2Yvwp^y#ZSfkVbjqM z#O-h6^htC{G)s4XCGrEOuG{72TFeUOO&DwvzJ0>{&ZJCCCNuBEEv>Cv@ZQryd(Pu= znQUSc=SVv(d2HN|tUcl`(hAOg$n;mLc$j^a@8#@`2LC1VOvQFqeHSi@-p1wsO630v z;__4wlZUvZHONnC2Y^Q=dwq!`vtM$G_*>o2RBO-d@8&%ZT00$?yaK&s9<=0d;|H6t zH_Fr<4T>Sv&%4fs7L)f$;ns zN6Ff|%sl~J31=I{9{TKD8Q72myw%6?gWr2EZtGlk_k@M&`%Tofo_nojuM{bnFfGh} zEI**5v|E9G=0WLrX+!+-UfSHp9wV9hUyeqb;CTkJ9NCRt?!pm2SO3k?3%RFo{uaA) z{*J2)8dXktRpwdpcdsZ63q}_)E{!Fhw&Qvh^;<9|{?9V$df3m3L-a#^H~ppWuEec*}T z+LIbb8cB`wR!MJ})L(~R9D1;=v$ZDRiDyH9B3Gvh zp6~K}fT!eK(Pz!C=D(0T)@0voi=~BtDKxP4T;3<~%jY+qUnW1-)i=i zz4U#?A6h8BEzN|f^!yhH7WDc27)um-HglFsR-u55fWBCF2m^00r`j-K2iElFT zOR>!0lZ0OYr(M49D!V*ZE=~i!ToKDc11 z;qT)22{McK;o7ZQBkS_vg&r>1isIP6m^s2Hsy~l4;X!XgT#l|?;C@i}f0?(9{b*q7 zWk%a(@=2e)6`yRyn|+5ltjWBK^I$qzt?`og^d6-4c`mKhks)K0eEWqo+f{li9A*25My=XU*#g6SqXdM zByg#PbJ4)w^5tuJHu4m|)Iw~hTAmG@aiqhq6!MGr;cWWQk!SVcQ^x9~AKFt_r&AX? z^0IWJFaQma9LhK%fi=0|2Hp?+%(@rqLul6rz+HKV&a$|l^u;yhVb!yibl?7!?=>Qi zHPCJY@fFHR?@RVZW>xya^N`zb;A!s1>?scV;~j6z+=EU|GUp#T>yXdH`}WkXA0MCd zWIgz#dt==bjMj$ZrSEA@3sw=kihE`^+FkuFJa&5$&gwI>Vy>E$QaAkh= z7_u0{AF0#H7((ertHBsnCyXJRF_d$kp6);T@P|e?4}N;?w0GOm zhQ_j&@#0IJ-LS&aTa?YPY^K#@M}e zm9cvjcjvC-c_(LJ?e^qG^lkl%;c0&@{5eg1SIs%OzB20ks``o@R(+f3|CiyMH3a9k zb98Q-&EA53o_7Dtd}3p;2nVYt-$$3j8RG7ZCB{G{cSp_u@9O_b9DD3;@sWH*dJf^x z++?G5E_31;EJdf}>@Ne4`oJTNM|hOY9N-hpU6kNalF^#S9ON?x;t3_kNe_U$;lbYU ziSHuwYfZ8icAGLCc$Rr)CU;ZjdUXD(JV*I<3;F7qC*hejN8G_jUAye??C81Tv`x4s z{f^-ITgqvEK6Q)>YJN_gn^m#7(VT2%ZZt=lo5QiWNrYwZqcNO4GkXY@D@<5&PapLk zM+YT8Ih`wr*2M988F|_#qUKf8>5?NaQW=Wq^N8h{3x_RcE%Jd@Ry)BFw$t0-IN|Tz;_;Em6#q#3m1GIY zUuDQ4u0zq6-2-P~XZ+pio!rxf+ zQ{TyDjJwLrJat2PWUpLFy&mf2PUCrVM;Jx2*Riw5tbsa%bj^9`d6qM*e_OQS z5)0UF`u^w)a2$D7t+npJ$l|~FpST~`k!4@+2lii#&GG}gj5T~IYdE%cWA;Ja^zlzC zEuR06Jk=Mi%@+K!e9*S~m_Jq?b0^=RrSwnfKKxj;p5tp-X>nhc+sGsSIh8V}`mi|h z_j7I@r#Qxu@E`{=_V?bn4P0B-T?! znR_U&v~tQ6a3_lD?uUo!rOqHSxg{UgEl9Q@H``JgC4b_a>#t+2y}){}9keZT!Hd@p z=9+r7r7MRo97&9uN4f9q4(|83lC?03vLnwhia%$sS-Nuc!i~f~n7^tqNB`Ghr?zxu zidp7Nm2-`ocE`EHr+<&KOB2eT=`xDD&GKW-yz54epEip8Ds#tWDbw$al}Vwkb(B+k z#JVazbEHxHd&+678fP{0qp_|dZqijNZRiwIx?W&i+c?7tKtJR2`&(=SH5WnFlr~Ri~Gq}aw{?txN$Fi+sj;N4T>iH`Aqq%r3Y7LvA*TwO537|D%VMyGniNI zYiSmpUv2gq{n+;{+1ivD`0t}mpsb|ub1uN>1AcbOs_KglIs~}%0PClEo_63nM1Z^FS0jo9Bx}y z&2u}?0%HBNyjh>KvC6h=ZgSm%hG`AlGvKVA13bX9F-hq3ooCptotwWahxu#ob+|p! z*Wz#G0Uqt!e@Gp~tT5~7qYmO#oVJdKV|5Har4G(M4zupMADtcca?gum`1aCQPd@uO z@&xu&)m5($XO7=oc+usi~Yh(+P}Qz!$-D zHoELN^b@{f2(C`@Js)fT5!x3FD~P|UwnE^S3w%kEybAuzeWkwngIDXD3#b#j=~lt7 zf<2`Z_-PK3`M(SJdFZq7UvPuo2hod|a4ewDr{aV7y)tmYMV*q7r1MV1h0WL-sPDR4 zG!BbI7)U?YL7(%OcPIR>Xovbz4L%7!bLsb5_CwuO?8QE$8#zL;CE#;|8tbuJkDGQ+ z;_bEnIDyAk>10&L^ORLy+2}-fir2Iuuh@}W9PmEF;DOG7E)5S1&Y>=NTk$&7`^s(5 zi6-Xb*(JK~H@klm`V8r0q>sVJwH>}ietRD2CQV($*+y$RJh|xOv)>zRQd!Zaq4Mmh zE9~iwDqD6uI-{4dhFEhKfg3HXIoY;2foUi6Bp8cc9Hx$5#w`7YV0;jIqP|4nFY|#> z?VL+Z|2^3*m0~B?8{PAJY)w2ad-oU2VXy_AfX+5_hQvIkjiar@tnCtF_T`~pQ(sh; z_?XvjVGXOSb5({}PCPD`nRLxUmUhPUExU5RURF-jxztazbS~Ee3+-#txr|TAB1Ws# z#!=4Awq2jvn62p|2XhVEHT3la1^~^x#imySIBO{1^69{Vntbde|j8=j4A9 zc@lL%drdf{2X&{e`uJh&`3Ihs-XrTIJ<3+(_C#5o^Nz37d;B=2_m~Z>m%WyOozHOK z7h+yb8JBsL-a+#zowm}$;Dl524ICvm{*pO+mN_ek%~``(YtH)7X(Z}6WLG2ohR!cL zftjfb8H0`q9PYjI#GDDIGE=h6c@ti_z$@8^w=j1u+LXS<3H+qXcplgU?9ww?I*cvI z=7P~d<|nSliR&KXvi>dRJc8@w)B0|lcf2VVoz_P74;)=MYs4m!Jx~0obkg^6U$|(i z&YoC<+ul0M>lQ4aHQ2mo2Yt|d(?;FgL!H(0nd^edqAN+&Z<%x@J6Hx?!LF=T^!O#l zD%#Sibw(Tu4sap`(Bs+Am3r_-YtjdN>SOd+ef-Z`jyKh_*NOhr(@!V*Bh!X(RDJ&v z;RktSOGf#2w|&!sI=goe8aN*v_jz^qk2oLOfkEnPUuf!qrBl8fI&>NIh!{k-&w)Ob zB6rNjuHEKO%NWf3y6=*E1mD+)H~-QQ4rc#d98{UF(!a%ZMvI9{_B3_gGK{mF>y9_w z%=0FG!}u>cu5}%k_u}&zf}a!b_slWLMJLA&Ngr+5CLaK&(!eG7nK4f6M2*FU|2xbB zI+FIOz{`aV3p^RIKb-Sj!wjxzKt8}0oAcMgD%Lsoq?vY|TIZ$=fqulzo_E#TGtfhh z>~Dn5b+C5Nv9ZsgH!;A0wa~bJN3thn7<|sEq+l|6)_zogZCTa`d7Pt-_ET-SqmJS1F=Ls-ROT{`IZbD7GuUG? z@v$1leSlWXnIv@F>En%U6~j9&c_FE8!P3`D1DV8AbzPiwwbS_Sa~^2^JnY>>`zzsD z=G~gS0iG`sKu+p&tZf#3+5xV0gZE6v`pRHwK>P#xr^fJq*k64%sqTqcS(WAh!HQJ34y7I4vobuPi@%gPVNLDJSQ{kuJiy zdj!3ZiTgfc_6q)2lCRO_ZGU=<5t+;XDq!TH-pUN|l;ovPtd-p^>UYzRi>QB5O=Z|u zo3r7^+&}PCl`q`zn76G2f3OZ{e*k?PvS*=a$HVX@q%V{0q-2uq*v1B-2LaB>=3{S~ zbW>$Gx#l}z^ke-yurIx5A?>sNBx}{vzKwRu#-JbL-ragfU3&v*n!~)Bg78}S8;wP4 z)%Q)#qoqT%aX;oajrK?2Ek)<I`MbR7WLpP#&O}&oB1s|k(yScj{gq{Sxtx$eo zg1`70!C&W@8iV?!dgA4sBfXIyJX#uF{pdsZ6_k9SvlCNi#kt5n@D7?0*#vz^nKIa< zvo#;(J@7G=33XKMMP{TA1?g5lRNi;i?7)lQQ#JSi&FN=PdUC!kxzTxR%7#y{nJHr) z*4mQ0=1F!B*atL+`@o~TRpsGG8fy@K)&)HmTq+qCW7?*9gzh(bC_9%qoXQ-E_pfpb zPpZT7ne(Oe;kSQ_Zqxs2S6%zlHB-YYf$M$r8@pCyAqy^o$(~2;VU4%*^Jt;Y`c~1t z#%HWD{Guz`gBIU0*wg{-R~_aWdC>dh9X~G(EG6H+F}@_$iHmiTPW$VDWv6Xq<2=@c z*37(H&)i_G5oiBm;s$Dsyo0@u516RmWj1HyWz=ixg>F6u*R#H_W1TNzy-QcL03G;nQwMJ9Iw|9%jOKjN zQPIO+2lgiui^yTcA`01vIb+Knm92`#BREeBjL%`TpOwK)#wMd{D#XskE5} zEg{y>oMC=v7C6ZKsI8%~Q1=%6)!<|OUiw`}ovWnpUH?yhJFcERl?4LLP(_mB8mePRotDdFc8S+MBCHU9K+O1~Z zsuyQ&=qDZubYH&1{#@|WfxS*0xVa#Po0XzH!cTBhJecAU9lBu=^N^scONdLPvHr{) zGy23M#~8cayfeES{hapBZk@^UJaw;1d*5sN@Z_ek2JC4=ahbI)&sSeQ@CGng@SERe z8w2RNPKwLSn9aD%n|ZbXPwgLN@EekgxuedEKU_!r;qla^_s#54m0P@~Jx>Q^WShbH zrr!;JD*7pzszNjYSSIc{DQV&lPL8GZb$GTEzY*ctzw;Dc#_{b)>R{%7TzeuOTY=)5 z;BO@O6hL=;?7?4f??^nJn)vzn|L7d;dBnl`UK(p5ow>+hPBOvMEHft74D`0r=d<6N zXEdGoZ}t+~*?rmB#NrwjT#FCK)Jos1dBmRe+HyZod*}p;#Yg;sHuXGk&5hJ~19e|d z8`sg+BG%i&0BxJ=?QUQLeJ$2`Gq&vL7}HF@%cW{^C#I^(bA=!2` zP`=}fmG6zC{2uIue^HN29{{hOq&~qz-%e*QS&JQSH#9=^zfJwVe5>w0U@lmj@THx4&f?UTK)?DK9xzcL}KeKU05db#b_OvhMH9?qAGUH&Lf)yT@6< zKJ;a>$9tW7V$`P2+};^G*d&;%JbXu!WM$di6YJ1(XDr{Xd_OccT%>hVNSlW#D|@E* zp+hS7Ys&3kF)J+lq>b3Ls$HeGol@V;y2tfTg<-2ty2Iu~pZr68$_xhRlb1H-R~fZu zR6oL)Ro_pkFE62gms3XL??nDV=Ue@jsqdKSQ5>dmw#?+4d8*vg>IXP=MhxC9q$`e( zU_Bl<3*NH*isO>O{+>!+>_E^LW(QL%jDXq|OfJN(wjkCnHag2}*v8(2{H*#vtwK*v z-I_=7kgDILcQG3?#dB2M$H=GoPNUuf@IW2VpiXFz_=E$@iEQT7?-X#ifPA9ieryR6 z>C)A|E?@`!^hBNf!DPCpxN)#U?*wXd(;1h-tx5PnzkTteb=P-z-h@Wi|5W*9 z_$P6$Im)aP89P?D0bYIG+2*%m`F=(p{+?Z%bf)S%cjgVO0gr3;dIREdD%nd8fP>t< z+1~`8BmQWWo3kkPgL?QK7j_krP3(@eF8D!z5_ch#*o*<4A(ge(H#-MszbAcaojtwl z8{FaHL+;OVq<1Mkux~GV8qR?3U*HYY+&nvQA$4@xGrPWp-mCV^`hL6imE)@x6fu9= zXZJu;WE(XD`S~2mIk{Uwy72Mo8=LE8TXl}n`V4kGqAMQCh)!grjBD(+-~L?3#H_2k zM-bDM`X=)&WY22cLAvUdzm#o4*46pcP5ionM)nRLw4^dw_Fl$7_lS;53R*XqWBFi| zvnyVg>|LFXbY!#AC!O>`y0={gMr#J+&A|>y@`aPOoY<5lInvP6Wi%=VN*;HU&4(Y% zLY|us4_w=03{2AfbbQl(wvjPy8Y6xnO>tDy%A%!DmQX&8HhPFlTYr4zdo5Fp);j3n z=as5It+CtDaf#Nv!8p3fW288FV%N=>?;RuESjQzb@a%s;m%L-56PXK|%eWMS&xs7? zeylt!emt-`H*D5HIn5Qm)BPRj|CBc^rqe*r-=8nLPTprCyY1n92|795>-8o)w(vpo ze=-LfUh$pvoSp-g}8_5K`;BY#=u^x7zq9JVf%j>1L#{8J;t2qz0YPe zUWxsjzHeN`y`g*yVwZKMac1Lu@b}SD!+!^MS$~^t_+O;V=lF93?J12N*rAT*Zs2#= zpS!U`{Tom1Gqvy(JK#SJyrY#^vk0DM&jV{4*A;wdgW3 zzwey8x!?UIusyv=$e-`7mE8L~``h3C_HTdtJA3bQ_BlJnAI0Y+Pk?b^{@eAM0pmYMZCfHus|)b|QA&5VpgGVLM2|xe};Bzg#6u!{8RE`=l$Wiab|Bfa>_t{H)nVX6)$Lgg2}y&naCaz2&$bOL|j zarkB~X? ziwiDj?7wR!=9{xH@0^YK=N!yKFT~t-E}oZrPWTM*Ww>|nKzVRwC+1W#pOw8yMesiv zr;Du;XE5Jix|8#K9ihaMqdhkOS@3-Tbr$`U?xl0^hju+8XTq$#D(YFzCr3~}hGOWX1FLP;`Z!C!H_^)CI%64|R z`A=vE$`?CA8(>p34@%E%OQAzJ!FVCu8&gB}6kiz1NF$eiucDbbv*5PJ$w zKWCf!^55aU>uJb47jw347sa>4V63J+48?TE!~73-uy!Df`18ekB@r{xjM$7aXj@*xilAW!!&} ztT|vzF3*^mk9jcK_rO7Lj{E=rQ1(UFA!fXc=hAO{=#uEU7+6y&&CB0eh&2`2Kc0&< z|B`cqez_l2>f*+aedW04=L_A?pP9FTkGY_FLL<>}lxVj_1HUjs7TpB|1u> zL&gE3vjoS=faTslxi6!1K5W9Ay#&t|yRXHb2E^=FVcU=PUDA~g9k{n; z#{aF~c=fKlX*=6tUn$n)u@+n*`NMMx@U_s1cN}l~A>!pmJmaAXe67A>SGbP>v1aXR z@YZ+%p5ZhX_b|YYZ{Qt3hY|(heX_E?EiqWmwJ+fs5AKW2sB_I#*w@#o>OAw}u+G<@ z&egDcCF*<+>RbXlN?=nl@{4^d@l54H{Jvv8>YB)(D)!3rCvc6TBEXnHWaK+PkvCP& z31XMXxw@@GJeB(_gr7R86YfcBN4ssqe#bi0MRe6*A7XHQ*-pHN_J-rH$-8}n-s#XK zyy1p}@II3E+oQSII^>gnFKY?n8zn(^xNkbQFnChtg>vrRhB@y4f^W&QJ#Imrq))EE zy2wL#9-lmiQs(Gx-Qj;ij@KRJ*~ewrcPH_zWa+zEcffcXbqe>G;XePLtwAX4wTtGeMP_E?&(4QXMv^s)##%e(f13mhP(&y2lrO4y&UH? z_)phO^^GSQ@%KH95oEnauAMEwJEMiWuqa!zygt{SA?GQRp2-bMOJ$lZsr zjFjIg>n_-bcjk2$jEk@iCH4Qp8P;8{gI+b$kWq-NplV z@7uUC=-Q9{#XrK|_hc<|))(d-lD;tOzInUw?myYX_%Zk!o);JLUJB0ZFjmgTSOk4! zne?0IWvpU&wD0(X$IxDf z@qDN^k-r<`6gdyeTJT=jdlGvLXD8Yp{u`V_=HmVsdCm)BX?TzLQ$G#YSpfL-r^Yl*3Hua304@c;VFpTPO{k8$4pIL^Nx!+BWVKd^S+iwo8? zzVzi4{WwpD>%XVQ0*GsmpfD}aPIuLn>!cFyAgA+pXpDdxii)Z zjum}0nmaEKbp>4yq;yum#xu>GcctW>N7;N$LF(#aHP#StKacDQ!@4H+i09*)v)i|| zT-q4zA$zt0#5l=UihC2I{pI=jlO9@eXMizu369G%^qtPV;8dP##_O#K==fvAk#4MW zbfS&x@rP@Jt4k7#u9ChkYb|K|H>Dl+%KJ7UeJ!0WHJJyv?m0Q=3cfZ0f_`1blZ6$RN*B4Uz zJ30~faqR&6J1*%G+xXf+9rnD{r}n(nfxpmByo)>!Yqj{jO!oCxg8Ne3&sp-mgYyDB zZ%N`?J@VBdpKx#oI4Hq$p=69xioB(`@4&^Lsfar=?m3L}*^RiiEOBQSWN=+&$pYw+ zdmuY;y$sie4_pk4b8Onra6hT|*{#~oa+i12V2$RhI93M^_qGPh9%+r<-PDa^havyl z@OysQOwm6`{lKlPi!~p{bM|HaDEDVd>^r=44<2`gJZ@bdGNrh`V$yln-zli8y z9~_mv5SQRtFW2Edee}&fw3$5rxc?xYageie*+E=mLVw#`^h0?U=>@$V81wvG?s*cu z*cTAyN513FV6FBixF-hBq3XmvPV=t~jxUfHf-&h0(;$zu3vg}-(^dw@e~st<<9U>_ z#`F`Mdym8SPhF3b_oPbP%9Zzl;< z6!NV>{?`z{t8$?mF^Xkck-iafFNQHb(JSdIrR-Ot_iJoGnv4Su;@)a`HaEp<46Z#n)q_>ShLLD#fYpZNsZ)%Q$W zX{YGfmg&7~bw#Q6sx1lc6XNy~+x`#ycF%P1k2#Uxr^9Q0%ey*Y%PiRX7Si`3zK8Vy zk2uese{; z0)ERF8ROOa`%-1^kg~sjQP&q!_-VmkU*3iGaJFIHeSVkBqr{$-V*9F#(FUi|j}@(3 z(zRXZe`0x;j6+2p`kyWOA2JV$F!bZSPcvlBcB<_a4bi8@j0=(Zl^-L~#E?7Ix>36PQ zQCgLA;l={Q-EGi^XK*3@%xD{nY_`}1?fvs-Xrjbb>Jv?bbi?G;tv>ib=`&bmg`E7$-A*I-vbvda?K(Ae6HEOE1^Tu z_D+hf=lt)f{SOwW+CcgS#z!F!e~JCxr#MKxCulM9&Vel2@Kg-zm=ndYTR$Jguoool zql?4)a=waV)v)c$c;=MEvbTWuU>q*-`F&E4&<6{fHGYjL~p@YeSujz-{iNAlx4& zHeH5$a->|;E$k=K9&a>?-7=;-{WF^7y!b4h{VRSTz9?%3E_Qww^_9LaWy`TT?2VG~ zz~t9(9SnBd0y_jJfq7gl&&0+3CE;Emth-&g=bc3JEAY`3QpZK*=<73OfA%eXs3-dQ z6QZXGHg{lOP(8SG81E7a$5@^BCjM}KEylu_TmFT-Z!aZZ1NlFJd`Cxg{aAE-g7W{7 z!ab1JW89mX`sau)u}2@5_9#OQDU$jT|^_z2W4{7+`!mzF- z?KsbGOElNPPSo}BVAt%hu6?lUPf^#WFgAg2>@K?JgW=dp+G$tVPEq}(zOpAP+Pj_T zS_u0(7eXh-@wtc#;W+z1iNw8(`*Xr}ubYi$4hA!!AF=NIE@{v3c-!po9=>WhzH4$= zZY9dqQOs2m6A$ye?UT3wgo!{nDR3@2$HP^_YP&4@>_07iZ+Z=UwDq zjr>O!q^|v9AM3aCWek_*LVPs={UVd{$M9Wvk3&w{aNY5@A1n)=3fDES$MZMt3r;MR z`AA+OI3Rhk7kt_3#N1n|`h(_!=%>p+o721sKDj)R(|iqZ>3Q?kU|pzec_P{Tci?)3 z%6n<|WmhD2mJ;*2W z%l|c}`6%MY>e_j0uCK@|6Zz6*^YD)770o?3F81z|`<+uZmnI6z+LgZLZzr1fLaqeI zzyK)z1OS5T17EBkZbu1a7XA&GG^`Vivl$Z zkvWO3{9}h++nB(9Ydj-W#_%sLn7;2Y?kRlv(sTD6o^sv(pMN=T-_LO`_X|67_a)lp z{tCPc=)dRh`}Zn5FZbNU{$I>V?*HZdoc(T}`r#>)_aB~;hrj&&{qRkkGqD~yqZ#9k zwQ?`X3(ze-^;O*4^?UHSInbFSzKu1I0z3;r_Gli$7-!D69+>wA_7Kat_n{j2;gk>W z$GeEoZ{!)>GqFDc^NlIFVL2G9h2IyrMBxtL^ z)8+p?aIwNa0IpQ{N5C}-|08gR!p{NsDEw34K81e_Rz{x4;@_z|jtnf>~l?uNK zT%+)7z#R&|0ofr0^FhS$AEhjz7@Dn;ZFh|QMd*;IW=AWZNS9}-vL~ya1(Hi!Y#lZ z3U2}KQTR^aK83dfA5pjiI9ZS`|6br?h3^BdRQQX)H41+TxI^IwfO`~v7`RX2uK*uW zxCb~nEnWWCfQuFG1+G;18^ARR{}phD!ha3iqwu$Z`xO2z@DYXkfRoeH<^Mf!vBEz9 zu2lF(z%>g0BXEbp&jI%+{8QjQg?|QoMByXA$#c`?{}Q-Z;g^6b6@C@CM&Z|hI~0Bc zxJTi)fcqk>P965s7?>~&RNs`u@(^P#< z2ER?Une}VBJ(J(2Ho~7iCxh=zw`AJ0X;TtQNa@d}mL!%q)1S>`|K^5F`!_dcw%_K> znf7mP&9rB8+ayeL(x2u}X8(fH7bU z7z4(DF<=ZB1IBX8(z(imG`)bD3N7pCk=*jRiSOo`@+dP=yAjft` zYEQcFK}6owp^+}{T^VIU#(*(k3}nfGzEM^G7PXACEGnz)+7|u$Y}=`A(Z9{E!JAui zq<a@+GC{b(c|zlm8siA|2|Wm(U3M?>o;ENHJ0ju zcZ{EQK0DmLt~VNS|6?3v>}nc5%SMuq(NcfSwf-HlJcPV!-TL=XmowDfp>5T_r5wgX zU3MIO+7|uW?2N-=T2^zYe~%QOx=j5$ZQ=0#(q-!3!&_=vyDn4zPD>2$FI}eoJ-nq3 z)UM0czeSSqz}&z45v^PQ9`15~cZ)5jF%U7Z^<5ItnHvAP?{}GPfY?ZvH^2ZpUD3@GEFI5_Se!jti^9UOOhG9H4Y z+3(7A`P^}*pWDS9 zclCDit~{6Sj=TE0Z$8fL;_TseadIx*>9KEPz!)$Fi~(c77%&Em0b{@zFb0ePW55_N z28;n?z!(@i4Dfm>uZMCvV_t`4%<{Yr%jqMHv$bdJw6s}j3>X8(fH7bU7z4w_z$Q|h zEnYap`q-WilYYaQgcu*jhh|`+`@?ok27XU;KCJ$k4q<#4ADRL42hE1X%dzGUcD^(J z)eOY-U-KW$p2feo{$ujyKbisa2hE1Xleqpc+~*_K&p58VCU5?(88Cm)Y*_p=e=vX0 z446M?HY`4vKbSvg2FxEc8x|jY{$TSL^B2v4&tEKEvo-eOi?6?PI%8}9vEBaGe%5}P z0rLmV#@LJJ)_&H0ngR0%&4%@7^9S<>&4BrXX2arx`Gfg`X2ASGvtjYU{K5P|Gcely z!PYBvYgzmn?fz=^nZIfV%pWux7Qf6N%pWuZ<`0?;ix1`x<`0^IvF;DP`I|3&tk>V{ z*WPUL-TYx<`-8>1c+IFn<_b{$S(L z(bXOky?>ZLnm=j=CVGFc`fG2n@ss(3`GaO)wE2Ubzjf&4BrXX2arx`Gfg`X2ASGvtjYU{K5P| zGhqIp*|7L9-u%I?7n*--2F9CzTYYrvj{W#;@oIdvr}a;3PtAb&gJxsw$7^d(YfsI9 z`GaO-`1`kwmqwOv^Kau@GhqIp*%6Sf5^@sY(AVFf98M2pJrgR`GfUu-8y!@9Buw-_LzTa2FxEc8w2B&#q%@sWBz0O zXa>w5G#dls3G*}B4Q+xoY)w`RcnL9;Rbu2TZ-tM3OaQlsQ z{PsJOe2q1GM;m|R&7Pt52cJG)dR%^oT3_7qP2SFrngR0%&4!Ja%pc4j zGy~=jnhlE&<_|;b4>legT0YG`&n}@{1LhB!jrilsY~xF|`K|r3 zYroOPpZUZ1YR}Q;UuI7{|C;FiaiZ7X`b)h2;^WKw$@tU^n7?Q?;?F;P{8_s3s~IqV z&}>+L8*YCXYv+5Py`0XN`Shi;JmZnhKh)*1KE_<%iH?VwAJ)fsqVql6^*6rle5)B4 zZhtfVnr$23O*DUq8*k&vk2OBWd;P{*dzifzpEU#K51Ng!f4;VOo7tWt%}2K7ael_! zUw!E;Khk)#+m|gLBVE6dE-x-Wqusu^^)dO(cxrqYADRL42hGOVA3s`qT6<~+%pWux zL*Ku7yu{eYe_VN=zPRaUyZpHJn*8wkv+-;EY6i?7G#f*I{xE(s`5o!=(MXp!(c9a{ zw=aFX@i)=xYwedA@5UP+Rv&9$&4BrXX2Zsh<`3o%ngR0%&4$GX^9S<>&4BrXX2arx z`Gfg`X2ASGvoZ1FgRP&9ulBe09AE8e@!8r_GhqIp*_e3eYioaNf6ajTgJ#3xf%${^ zgJ!_|L9^kH4>o^_$5&kcGJc1b-?;5z^41=j0rLmVhW~tFd>LPw0rLmVhV>uw2lEHb zK(_v1<7dsL#g}aT$?}^&X$Ho+KUjR!t!eRbtoyUsZ~m+qFn`c&jQ#jF(a%?0f5ztT zDIRKnfZhHgJ!_|L9=1;!TiDeK{H_fpxLnaVE$nKpcycK&}>+I zFn=(A&w5G#eHl%pc4jGy~=jnhlE&<`3o%ngR0%&4$GX^9S<> z&4BrXX2arx`Gfg`X2ASGvtjYU{K5P|GhqIp*|7Lv{$T!~88Cm)Y*>6Se=vX0446M? zHY`4vKbSvg2FxEc8x|kTAIu*#1LhB!4T}%v59SY=0rLmVhQ$Z-2lEHbfcb-F!{USa zgZYDI!2Ch8Ve!HI!TdopVE&-lu=rs9VE&*PFn`c&SbQ*lFn`btm_KMXEIyb&m_KL+ z%pWux79Y$X%pWuZ<`0?;ix1`x<`0?y^9Rj_#fP))5B7c$^GD6V+4e^(U$=(ENAm~s z2hD)_gJ#3x!&vhN8*iEaY6ixd|C+tJ^(_9HKbSvg2FxEc8x|kTAIu*#1KIk+Cany= z&o}%PbGi>V5&v=Z`Q$l$EtQuo z=K68}j_Xe>UqSZ9#cbbDW9FCb_m#)_S)Toa^{*v{X^~VTgZRTHuklr&puy% zPG^0-be8vF*5_+qmS@cV!s*%SXMKh&Q_lD^LU%fi;FovaC z+5h$8{T8E0!B>+|7-G#=&h*>c{DEF~@Vx&*?tQ=i|8bjVtf7CvG~|pY7pv zAI>&E>-Xu4+y7YqNVgx?hcVm7nB^J!f4MyvbNP(9e8w!#_A?%Cc`k3LG274BS02k}i@CgP^-Z+=+@G_pf41%6 z%kN9~)yJ1VZhTh@`3u|6{BSyBzF&mX8L#!6Pg#Dr zvG07x<;UfRukU4xeeKEmc|Ff(Kc^4%_>J|mKXCmRb9?yGxjY|c{n=tJkM(gn$3ITz z{EXwubABK8*~jg{{^P^G@_p%Cf5z-@tdH&I{477(@xqw#Hg0`=@|@1`mi@_aW`h|Y znS8MSFlK+}^h|Ar#ySHDssLk34o>2ukNM;|Jx6CA4E59{~IkFae({h5q1AHM#`{^OHp{XTzV z{XTit&p5NTLDuopS6{Z@C(ri!;uY)n$#eY;8v_%W0q$?i1^1_+mS=s8XOlq-2(x_L z_(JLej<2kr(>XuO$HlCV%VT|<&iPq>ItvhHc}fnLUzTTo;ruMm>71YC8FPM4kIN6| z_vt^61o8;8KDLL`8I!tz(;2h8uRKoY{H&k-X9{Itc}n*7FZM6a&-&S4eDc0@*3X#v z;`IMQ1*{>=@^S6w{G@(>e{eeU>(e)x6!_#hopCPdW61Kpbe8A(`SNo*+sFD@p3@n# z{5f>MC-3t&Qa7Oeefl|_aUm7J{IYyL$unem#&P-K{EWH$bLjxf7g0L*PnPF+NZALp z2dDe`*9^`;nC+QL>Av$(w)Xq{lkFq(y!`n1=lc2dv%Nn3tdH|^{Vt#k+#gt;#J%Uo zxbj>-&Y!J4(^w&4*3aVwpZ_!8q~7a4apO6c$M$pli))WhKkM_!e})V!AWSge_`v0{ zd@%`d{aHS)zj3^$;=Jw4<*_}ikNuD3Ug`Ob34Ak>_|r;sf~n z6SBXQGEni98Vu0qlc(Ya?P2+$_J6*< zT1f@6J=ykO*2kFZN9GJ@KTaQRKG|NzY!BCm<^PE?e1*w>;Q0r%XTz}@1*Ux?OarLu2 zw;$URcfFMJb9tQ3_4CQ|_}?cV*MC?a+sF2^Jf|~ed7pk?eqZ`fuP4W~pXIqd*nZ}N z^RqnH&nNFoXZ?)h=J&~;&Y#`9bzMrp%@h7x3cGxZE{sZWJY4-u)T7;Xrc`q9=E;-c zQrXGHk^G#LVRbJ=@{aclQyE=5J%6kyl$@E8cjdZq_Oq#s?mX(sb8)pZ70}!`_|cSt z-@Fsqvo&>r)2%~vPKnOw?@5(clKP&P`fg99UzEbG-frB`{>`XB7q@n&a7x_1jDZnl z!1V)HD94l2W7#K?!2QlVB5<1GeSb6&MHKrs9>jAdsviU&s;#N7ZYo^gP~CKU;g;H# z*7{9Ng%wwoFDk#Pu;kK97cW|T#iFGZixyp3vGj_oFI~F6=C+FJ#Y>h|ELnVc#rE2* zn=7_Ek&3G-mM&RRzO*!0*|533sdiAE!HxAz8*5uWP?#$B#v4DBDlNF~nrl8#Sdz+H zvABG3c}3Oj^=(kUc+s-OS6<#yv8c2#I$r1w20?jiU29uQTXjuP-n6N$w*2;{PnFkv zs=i^v<@Fna@(tUXTDLU@;nBM4*1G6OTT4*hQrl21$*EtP8`>bXetlK#*7dcU+p3_j zp%!VIHdMD&2j#VORkyWNH`Z3wZ9ra!g7W&NdgQweUqN|W?N`nb}-xrfoo)^ieM0B|PZrtO(_ofCQl22l~8<)88&_W!017k3k-;I0R_l(qu zz@@wV$QFJU;lGT@T)G=qxoFME8p2)naVHU@^Rxv z_wB}wl3&J_oL|;WrHW2}`%4kS?)%XOB&rYd|4F1t{?za_SoHDe%zEnkxGOPI!e`Cf zQu$r^>sCc0YWIEr`=fmBKbJ2)sO>-T=_tSZ?)?2!1Ev&YS`!4@Q~BMv*^N`%zZngH z*a#V0DcHlZeHT%0WLrD?XdgqL0)Mwm*34ZI#cDBAWeT< zKKK0%BuWdr{Ew&RA&;l>ANz&#tVoN?=XCxpeh5V_fA=eeVN&-i(R^of%6(kByZnyF z??YObKjYOX|BP3o{6{n0ZvcPKQ2rCYDhkU#@vA6*2-H7UzB}~)@I#l+`42n6)Hmlp zMETvk^7&&?`Gt;{)8s#j1rslEVK_z8;nThB_ucT|RgCKLPd#RPz7; diff --git a/vendor/github.com/DataDog/go-libddwaf/v2/internal/log/gostring.go b/vendor/github.com/DataDog/go-libddwaf/v2/internal/log/gostring.go deleted file mode 100644 index cf85a4b93..000000000 --- a/vendor/github.com/DataDog/go-libddwaf/v2/internal/log/gostring.go +++ /dev/null @@ -1,24 +0,0 @@ -// Unless explicitly stated otherwise all files in this repository are licensed -// under the Apache License Version 2.0. -// This product includes software developed at Datadog (https://www.datadoghq.com/). -// Copyright 2016-present Datadog, Inc. - -package log - -import "unsafe" - -// gostring copies a char* to a Go string. -func gostring(ptr *byte) string { - if ptr == nil { - return "" - } - var length int - for { - if *(*byte)(unsafe.Add(unsafe.Pointer(ptr), uintptr(length))) == '\x00' { - break - } - length++ - } - //string builtin copies the slice - return string(unsafe.Slice(ptr, length)) -} diff --git a/vendor/github.com/DataDog/go-libddwaf/v2/internal/noopfree/noopfree.go b/vendor/github.com/DataDog/go-libddwaf/v2/internal/noopfree/noopfree.go deleted file mode 100644 index 98dffcf05..000000000 --- a/vendor/github.com/DataDog/go-libddwaf/v2/internal/noopfree/noopfree.go +++ /dev/null @@ -1,15 +0,0 @@ -// Unless explicitly stated otherwise all files in this repository are licensed -// under the Apache License Version 2.0. -// This product includes software developed at Datadog (https://www.datadoghq.com/). -// Copyright 2016-present Datadog, Inc. - -// Package noopfree provides a noop-ed free function. A separate package is -// needed to avoid the special go-build case with CGO enabled where it compiles -// .s files with CC instead of the Go assembler that we want here. -package noopfree - -import "unsafe" - -//go:linkname _noop_free_v2 _noop_free_v2 -var _noop_free_v2 byte -var NoopFreeFn uintptr = uintptr(unsafe.Pointer(&_noop_free_v2)) diff --git a/vendor/github.com/DataDog/go-libddwaf/v2/safe.go b/vendor/github.com/DataDog/go-libddwaf/v2/safe.go deleted file mode 100644 index 22c155e90..000000000 --- a/vendor/github.com/DataDog/go-libddwaf/v2/safe.go +++ /dev/null @@ -1,68 +0,0 @@ -// Unless explicitly stated otherwise all files in this repository are licensed -// under the Apache License Version 2.0. -// This product includes software developed at Datadog (https://www.datadoghq.com/). -// Copyright 2016-present Datadog, Inc. - -package waf - -import ( - "fmt" - "reflect" - "runtime" - - "github.com/pkg/errors" -) - -// PanicError is an error type wrapping a recovered panic value that happened -// during a function call. Such error must be considered unrecoverable and be -// used to try to gracefully abort. Keeping using this package after such an -// error is unreliable and the caller must rather stop using the library. -// Examples include safety checks errors. -type PanicError struct { - // The recovered panic error while executing the function `in`. - Err error - // The function symbol name that was given to `tryCall()`. - in string -} - -func newPanicError(in func() error, err error) *PanicError { - return &PanicError{ - in: runtime.FuncForPC(reflect.ValueOf(in).Pointer()).Name(), - Err: err, - } -} - -// Unwrap the error and return it. -// Required by errors.Is and errors.As functions. -func (e *PanicError) Unwrap() error { - return e.Err -} - -// Error returns the error string representation. -func (e *PanicError) Error() string { - return fmt.Sprintf("panic while executing %s: %#+v", e.in, e.Err) -} - -// tryCall calls function `f` and recovers from any panic occurring while it -// executes, returning it in a `PanicError` object type. -func tryCall(f func() error) (err error) { - defer func() { - r := recover() - if r == nil { - // Note that panic(nil) matches this case and cannot be really tested for. - return - } - - switch actual := r.(type) { - case error: - err = errors.WithStack(actual) - case string: - err = errors.New(actual) - default: - err = errors.Errorf("%v", r) - } - - err = newPanicError(f, err) - }() - return f() -} diff --git a/vendor/github.com/DataDog/go-libddwaf/v2/symbols_linux_cgo.go b/vendor/github.com/DataDog/go-libddwaf/v2/symbols_linux_cgo.go deleted file mode 100644 index 46b4d95a0..000000000 --- a/vendor/github.com/DataDog/go-libddwaf/v2/symbols_linux_cgo.go +++ /dev/null @@ -1,21 +0,0 @@ -// Unless explicitly stated otherwise all files in this repository are licensed -// under the Apache License Version 2.0. -// This product includes software developed at Datadog (https://www.datadoghq.com/). -// Copyright 2016-present Datadog, Inc. - -//go:build cgo && linux && !go1.23 && !datadog.no_waf - -package waf - -/* -// Needed otherwise cielf call is optimized away or the builtin version is used -#cgo CFLAGS: -O0 -#cgo LDFLAGS: -lm -float __attribute__((__noinline__)) ceilf(float arg); -*/ -import "C" - -// Required because libddwaf uses ceilf located in libm -// This forces CGO to link with libm, from there since -// libm is loaded, we can dlopen the waf without issues -var _ = C.ceilf(2.3) diff --git a/vendor/github.com/DataDog/go-libddwaf/v2/symbols_linux_purego.go b/vendor/github.com/DataDog/go-libddwaf/v2/symbols_linux_purego.go deleted file mode 100644 index 223c500af..000000000 --- a/vendor/github.com/DataDog/go-libddwaf/v2/symbols_linux_purego.go +++ /dev/null @@ -1,15 +0,0 @@ -// Unless explicitly stated otherwise all files in this repository are licensed -// under the Apache License Version 2.0. -// This product includes software developed at Datadog (https://www.datadoghq.com/). -// Copyright 2016-present Datadog, Inc. - -//go:build !cgo && appsec && linux && !go1.23 && !datadog.no_waf - -package waf - -// Adds a dynamic import for libm.so because libddwaf needs the ceilf symbol -// This mechanic only works when CGO is not enabled -// -//go:cgo_import_dynamic purego_ceilf ceilf "libm.so.6" -//go:cgo_import_dynamic _ _ "libm.so.6" -var purego_ceilf uintptr diff --git a/vendor/github.com/DataDog/go-libddwaf/v2/waf_dl_unsupported.go b/vendor/github.com/DataDog/go-libddwaf/v2/waf_dl_unsupported.go deleted file mode 100644 index d8966fd7c..000000000 --- a/vendor/github.com/DataDog/go-libddwaf/v2/waf_dl_unsupported.go +++ /dev/null @@ -1,52 +0,0 @@ -// Unless explicitly stated otherwise all files in this repository are licensed -// under the Apache License Version 2.0. -// This product includes software developed at Datadog (https://www.datadoghq.com/). -// Copyright 2016-present Datadog, Inc. - -// Build when the target OS or architecture are not supported -//go:build (!linux && !darwin) || (!amd64 && !arm64) || go1.23 || datadog.no_waf || (!cgo && !appsec) - -package waf - -type wafDl struct{} - -func newWafDl() (dl *wafDl, err error) { - _, err = Health() - return nil, err -} - -func (waf *wafDl) wafGetVersion() string { - return "" -} - -func (waf *wafDl) wafInit(obj *wafObject, config *wafConfig, info *wafObject, refs cgoRefPool) wafHandle { - return 0 -} - -func (waf *wafDl) wafUpdate(handle wafHandle, ruleset *wafObject, info *wafObject) wafHandle { - return 0 -} - -func (waf *wafDl) wafDestroy(handle wafHandle) { -} - -func (waf *wafDl) wafKnownAddresses(handle wafHandle) []string { - return nil -} - -func (waf *wafDl) wafContextInit(handle wafHandle) wafContext { - return 0 -} - -func (waf *wafDl) wafContextDestroy(context wafContext) { -} - -func (waf *wafDl) wafResultFree(result *wafResult) { -} - -func (waf *wafDl) wafObjectFree(obj *wafObject) { -} - -func (waf *wafDl) wafRun(context wafContext, persistentData, ephemeralData *wafObject, result *wafResult, timeout uint64) wafReturnCode { - return wafErrInternal -} diff --git a/vendor/github.com/DataDog/go-libddwaf/v2/waf_support.go b/vendor/github.com/DataDog/go-libddwaf/v2/waf_support.go deleted file mode 100644 index c2fb14090..000000000 --- a/vendor/github.com/DataDog/go-libddwaf/v2/waf_support.go +++ /dev/null @@ -1,85 +0,0 @@ -// Unless explicitly stated otherwise all files in this repository are licensed -// under the Apache License Version 2.0. -// This product includes software developed at Datadog (https://www.datadoghq.com/). -// Copyright 2016-present Datadog, Inc. - -package waf - -import ( - "fmt" - "runtime" - - "github.com/hashicorp/go-multierror" -) - -// Errors used to report data using the Health function -// Store all the errors related to why go-liddwaf is unavailable for the current target at runtime. -var wafSupportErrors []error - -// Not nil if the build tag `datadog.no_waf` is set -var wafManuallyDisabledErr error - -// UnsupportedOSArchError is a wrapper error type helping to handle the error -// case of trying to execute this package when the OS or architecture is not supported. -type UnsupportedOSArchError struct { - Os string - Arch string -} - -func (e UnsupportedOSArchError) Error() string { - return fmt.Sprintf("unsupported OS/Arch: %s/%s", e.Os, e.Arch) -} - -// UnsupportedGoVersionError is a wrapper error type helping to handle the error -// case of trying to execute this package when the Go version is not supported. -type UnsupportedGoVersionError struct{} - -func (e UnsupportedGoVersionError) Error() string { - return fmt.Sprintf("unsupported Go version: %s", runtime.Version()) -} - -type CgoDisabledError struct{} - -func (e CgoDisabledError) Error() string { - return "go-libddwaf is disabled when cgo is disabled unless you compile with the go build tag `appsec`. It will require libdl.so.2. libpthread.so.0, libc.so.6 and libm.so.6 shared libraries at run time on linux" -} - -// ManuallyDisabledError is a wrapper error type helping to handle the error -// case of trying to execute this package when the WAF has been manually disabled with -// the `datadog.no_waf` go build tag. -type ManuallyDisabledError struct{} - -func (e ManuallyDisabledError) Error() string { - return "the WAF has been manually disabled using the `datadog.no_waf` go build tag" -} - -// SupportsTarget returns true and a nil error when the target host environment -// is supported by this package and can be further used. -// Otherwise, it returns false along with an error detailing why. -func SupportsTarget() (bool, error) { - return len(wafSupportErrors) == 0, multierror.Append(nil, wafSupportErrors...).ErrorOrNil() -} - -// Health returns true if the waf is usable, false otherwise. At the same time it can return an error -// if the waf is not usable, but the error is not blocking if true is returned, otherwise it is. -// The following conditions are checked: -// - The Waf library has been loaded successfully (you need to call `Load()` first for this case to be taken into account) -// - The Waf library has not been manually disabled with the `datadog.no_waf` go build tag -// - The Waf library is not in an unsupported OS/Arch -// - The Waf library is not in an unsupported Go version -func Health() (bool, error) { - var err *multierror.Error - if wafLoadErr != nil { - err = multierror.Append(err, wafLoadErr) - } - - if len(wafSupportErrors) > 0 { - err = multierror.Append(err, wafSupportErrors...) - } - - if wafManuallyDisabledErr != nil { - err = multierror.Append(err, wafManuallyDisabledErr) - } - - return (wafLib != nil || wafLoadErr == nil) && len(wafSupportErrors) == 0 && wafManuallyDisabledErr == nil, err.ErrorOrNil() -} diff --git a/vendor/github.com/DataDog/go-libddwaf/v2/.gitattributes b/vendor/github.com/DataDog/go-libddwaf/v3/.gitattributes similarity index 100% rename from vendor/github.com/DataDog/go-libddwaf/v2/.gitattributes rename to vendor/github.com/DataDog/go-libddwaf/v3/.gitattributes diff --git a/vendor/github.com/DataDog/go-libddwaf/v2/.gitignore b/vendor/github.com/DataDog/go-libddwaf/v3/.gitignore similarity index 71% rename from vendor/github.com/DataDog/go-libddwaf/v2/.gitignore rename to vendor/github.com/DataDog/go-libddwaf/v3/.gitignore index ed586868d..e9a06fb77 100644 --- a/vendor/github.com/DataDog/go-libddwaf/v2/.gitignore +++ b/vendor/github.com/DataDog/go-libddwaf/v3/.gitignore @@ -16,3 +16,8 @@ # Swap files *.swp + +## Ensure WAF static libraries are not excluded from vendor folders +!internal/lib/*.so.gz +!internal/lib/*.dylib.gz + diff --git a/vendor/github.com/DataDog/go-libddwaf/v3/CODEOWNERS b/vendor/github.com/DataDog/go-libddwaf/v3/CODEOWNERS new file mode 100644 index 000000000..2e4d479a6 --- /dev/null +++ b/vendor/github.com/DataDog/go-libddwaf/v3/CODEOWNERS @@ -0,0 +1,2 @@ +# default owner +* @DataDog/asm-go diff --git a/vendor/github.com/DataDog/go-libddwaf/v2/LICENSE b/vendor/github.com/DataDog/go-libddwaf/v3/LICENSE similarity index 100% rename from vendor/github.com/DataDog/go-libddwaf/v2/LICENSE rename to vendor/github.com/DataDog/go-libddwaf/v3/LICENSE diff --git a/vendor/github.com/DataDog/go-libddwaf/v2/README.md b/vendor/github.com/DataDog/go-libddwaf/v3/README.md similarity index 87% rename from vendor/github.com/DataDog/go-libddwaf/v2/README.md rename to vendor/github.com/DataDog/go-libddwaf/v3/README.md index a3a94922b..013b663be 100644 --- a/vendor/github.com/DataDog/go-libddwaf/v2/README.md +++ b/vendor/github.com/DataDog/go-libddwaf/v3/README.md @@ -6,7 +6,7 @@ It consists of 2 separate entities: the bindings for the calls to libddwaf, and An example usage would be: ```go -import waf "github.com/DataDog/go-libddwaf" +import waf "github.com/DataDog/go-libddwaf/v3" //go:embed var ruleset []byte @@ -15,12 +15,12 @@ func main() { var parsedRuleset any if err := json.Unmarshal(ruleset, &parsedRuleset); err != nil { - return 1 + panic(err) } wafHandle, err := waf.NewHandle(parsedRuleset, "", "") if err != nil { - return 1 + panic(err) } defer wafHandle.Close() @@ -28,13 +28,15 @@ func main() { wafCtx := wafHandle.NewContext() defer wafCtx.Close() - matches, actions := wafCtx.Run(map[string]any{ - "server.request.path_params": "/rfiinc.txt", - }, time.Minute) + matches, actions := wafCtx.Run(RunAddressData{ + Persistent: map[string]any{ + "server.request.path_params": "/rfiinc.txt", + }, + }) } ``` -The API documentation details can be found on [pkg.go.dev](https://pkg.go.dev/github.com/DataDog/go-libddwaf). +The API documentation details can be found on [pkg.go.dev](https://pkg.go.dev/github.com/DataDog/go-libddwaf/v3). Originally this project was only here to provide CGO Wrappers to the calls to libddwaf. But with the appearance of `ddwaf_object` tree like structure, @@ -99,17 +101,17 @@ flowchart LR The cgoRefPool type is a pure Go pointer pool of `ddwaf_object` C values on the Go memory heap. the `cgoRefPool` go type is a way to make sure we can safely send Go allocated data to the C side of the WAF -The main issue is the following: the `wafObject` uses a C union to store the tree structure of the full object, +The main issue is the following: the `WafObject` uses a C union to store the tree structure of the full object, union equivalent in go are interfaces and they are not compatible with C unions. The only way to be 100% sure -that the Go `wafObject` struct has the same layout as the C one is to only use primitive types. So the only way to +that the Go `WafObject` struct has the same layout as the C one is to only use primitive types. So the only way to store a raw pointer is to use the `uintptr` type. But since `uintptr` do not have pointer semantics (and are just basically integers), we need another method to store the value as Go pointer because the GC will delete our data if it is not referenced by Go pointers. -That's where the `cgoRefPool` object comes into play: all new `wafObject` elements are created via this API which is especially +That's where the `cgoRefPool` object comes into play: all new `WafObject` elements are created via this API which is especially built to make sure there is no gap for the Garbage Collector to exploit. From there, since underlying values of the -`wafObject` are either arrays of wafObjects (for maps, structs and arrays) or string (for all ints, booleans and strings), -we can store 2 slices of arrays and use `runtime.KeepAlive` in each code path to protect them from the GC. +`wafObject` are either arrays of WafObjects (for maps, structs and arrays) or string (for all ints, booleans and strings), +we can store 2 slices of arrays and use `unsafe.KeepAlive` in each code path to protect them from the GC. All these objects stored in the reference pool need to live throughout the use of the associated Waf Context. @@ -127,12 +129,13 @@ Here is an example of the flow of operations on a simple call to Run(): This library uses [purego](https://github.com/ebitengine/purego) to implement C bindings without requiring use of CGO at compilation time. The high-level workflow is to embed the C shared library using `go:embed`, dump it into a file, open the library using `dlopen`, load the -symbols using `dlsym`, and finally call them. +symbols using `dlsym`, and finally call them. On Linux systems, using `memfd_create(2)` enables the library to be loaded without +writing to the filesystem. -> :warning: Keep in mind that **purego only works on linux/darwin for amd64/arm64 and so does go-libddwaf.** +Another requirement of `libddwaf` is to have a FHS filesystem on your machine and, for Linux, to provide `libc.so.6`, +`libpthread.so.0`, and `libdl.so.2` as dynamic libraries. -Another requirement of `libddwaf` is to have a FHS filesystem on your machine and, for linux, to provide `libc.so.6`, -`libpthread.so.0`, `libm.so.6` and `libdl.so.2` as dynamic libraries. +> :warning: Keep in mind that **purego only works on linux/darwin for amd64/arm64 and so does go-libddwaf.** ## Contributing pitfalls diff --git a/vendor/github.com/DataDog/go-libddwaf/v2/cgo_ref_pool.go b/vendor/github.com/DataDog/go-libddwaf/v3/cgo_ref_pool.go similarity index 70% rename from vendor/github.com/DataDog/go-libddwaf/v2/cgo_ref_pool.go rename to vendor/github.com/DataDog/go-libddwaf/v3/cgo_ref_pool.go index 47cb6990b..9de4c2fbc 100644 --- a/vendor/github.com/DataDog/go-libddwaf/v2/cgo_ref_pool.go +++ b/vendor/github.com/DataDog/go-libddwaf/v3/cgo_ref_pool.go @@ -7,6 +7,9 @@ package waf import ( "strconv" + + "github.com/DataDog/go-libddwaf/v3/internal/bindings" + "github.com/DataDog/go-libddwaf/v3/internal/unsafe" ) // cgoRefPool is a way to make sure we can safely send go allocated data on the C side of the WAF @@ -21,9 +24,14 @@ import ( // we can store 2 slices of arrays and use runtime.KeepAlive in each code path to protect them from the GC. type cgoRefPool struct { stringRefs []string - arrayRefs [][]wafObject + arrayRefs [][]bindings.WafObject } +// This is used when passing empty Go strings to the WAF in order to avoid passing null string pointers, +// which are not handled by the WAF in all cases. +// FIXME: to be removed when the WAF handles null ptr strings in all expected places +var emptyWAFStringValue = unsafe.NativeStringUnwrap("\x00").Data + func (refPool *cgoRefPool) append(newRefs cgoRefPool) { refPool.stringRefs = append(refPool.stringRefs, newRefs.stringRefs...) refPool.arrayRefs = append(refPool.arrayRefs, newRefs.arrayRefs...) @@ -37,61 +45,62 @@ func (refPool *cgoRefPool) AllocCString(str string) uintptr { } refPool.stringRefs = append(refPool.stringRefs, str) - return nativeStringUnwrap(str).Data + return unsafe.NativeStringUnwrap(str).Data } // AllocWafString fills the obj parameter wafObject with all parameters needed for the WAF interpret it as a string. // We take full advantage of the fact that the WAF can receive non-null-terminated strings by directly retrieving the // underlying array in the string value using the nativeStringUnwrap function. Hence, removing any copy in the process -func (refPool *cgoRefPool) AllocWafString(obj *wafObject, str string) { - obj._type = wafStringType +func (refPool *cgoRefPool) AllocWafString(obj *bindings.WafObject, str string) { + obj.Type = bindings.WafStringType if len(str) == 0 { - obj.nbEntries = 0 - obj.value = 0 + obj.NbEntries = 0 + // FIXME: use obj.Value = 0 when the WAF handles null string ptr in all expected places + obj.Value = emptyWAFStringValue return } refPool.stringRefs = append(refPool.stringRefs, str) - stringHeader := nativeStringUnwrap(str) - obj.value = stringHeader.Data - obj.nbEntries = uint64(stringHeader.Len) + stringHeader := unsafe.NativeStringUnwrap(str) + obj.Value = stringHeader.Data + obj.NbEntries = uint64(stringHeader.Len) } // AllocWafArray is used to create a tree-like structure since we allocate a wafObject array inside another wafOject. // wafObject can also represent a map, in that case we use the AllocWafMapKey function to make the wafObject key-value-pair // like objects. -func (refPool *cgoRefPool) AllocWafArray(obj *wafObject, typ wafObjectType, size uint64) []wafObject { - if typ != wafMapType && typ != wafArrayType { +func (refPool *cgoRefPool) AllocWafArray(obj *bindings.WafObject, typ bindings.WafObjectType, size uint64) []bindings.WafObject { + if typ != bindings.WafMapType && typ != bindings.WafArrayType { panic("Cannot allocate this waf object data type as an array: " + strconv.Itoa(int(typ))) } - obj._type = typ - obj.nbEntries = size + obj.Type = typ + obj.NbEntries = size // If the array size is zero no need to allocate anything if size == 0 { - obj.value = 0 + obj.Value = 0 return nil } - goArray := make([]wafObject, size) + goArray := make([]bindings.WafObject, size) refPool.arrayRefs = append(refPool.arrayRefs, goArray) - obj.value = sliceToUintptr(goArray) + obj.Value = unsafe.SliceToUintptr(goArray) return goArray } // AllocWafMapKey is used to store a string map key in a wafObject. // We take full advantage of the fact that the WAF can receive non-null-terminated strings by directly retrieving the // underlying array in the string value using the nativeStringUnwrap function. Hence, removing any copy in the process -func (refPool *cgoRefPool) AllocWafMapKey(obj *wafObject, str string) { +func (refPool *cgoRefPool) AllocWafMapKey(obj *bindings.WafObject, str string) { if len(str) == 0 { return } refPool.stringRefs = append(refPool.stringRefs, str) - stringHeader := nativeStringUnwrap(str) - obj.parameterName = stringHeader.Data - obj.parameterNameLength = uint64(stringHeader.Len) + stringHeader := unsafe.NativeStringUnwrap(str) + obj.ParameterName = stringHeader.Data + obj.ParameterNameLength = uint64(stringHeader.Len) } diff --git a/vendor/github.com/DataDog/go-libddwaf/v3/context.go b/vendor/github.com/DataDog/go-libddwaf/v3/context.go new file mode 100644 index 000000000..509f7f0cb --- /dev/null +++ b/vendor/github.com/DataDog/go-libddwaf/v3/context.go @@ -0,0 +1,327 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2016-present Datadog, Inc. + +package waf + +import ( + "sync" + "sync/atomic" + "time" + + "github.com/DataDog/go-libddwaf/v3/errors" + "github.com/DataDog/go-libddwaf/v3/internal/bindings" + "github.com/DataDog/go-libddwaf/v3/internal/unsafe" + "github.com/DataDog/go-libddwaf/v3/timer" +) + +// Context is a WAF execution context. It allows running the WAF incrementally +// when calling it multiple times to run its rules every time new addresses +// become available. Each request must have its own Context. +type Context struct { + handle *Handle // Instance of the WAF + + cgoRefs cgoRefPool // Used to retain go data referenced by WAF Objects the context holds + cContext bindings.WafContext // The C ddwaf_context pointer + + // timeoutCount count all calls which have timeout'ed by scope. Keys are fixed at creation time. + timeoutCount map[Scope]*atomic.Uint64 + + // mutex protecting the use of cContext which is not thread-safe and cgoRefs. + mutex sync.Mutex + + // timer registers the time spent in the WAF and go-libddwaf + timer timer.NodeTimer + + // metrics stores the cumulative time spent in various parts of the WAF + metrics metricsStore + + // truncations provides details about truncations that occurred while + // encoding address data for WAF execution. + truncations map[Scope]map[TruncationReason][]int +} + +// RunAddressData provides address data to the Context.Run method. If a given key is present in both +// RunAddressData.Persistent and RunAddressData.Ephemeral, the value from RunAddressData.Persistent will take precedence. +type RunAddressData struct { + // Persistent address data is scoped to the lifetime of a given Context, and subsquent calls to Context.Run with the + // same address name will be silently ignored. + Persistent map[string]any + // Ephemeral address data is scoped to a given Context.Run call and is not persisted across calls. This is used for + // protocols such as gRPC client/server streaming or GraphQL, where a single request can incur multiple subrequests. + Ephemeral map[string]any + // Scope is the way to classify the different runs in the same context in order to have different metrics + Scope Scope +} + +func (d RunAddressData) isEmpty() bool { + return len(d.Persistent) == 0 && len(d.Ephemeral) == 0 +} + +// Run encodes the given addressData values and runs them against the WAF rules within the given timeout value. If a +// given address is present both as persistent and ephemeral, the persistent value takes precedence. It returns the +// matches as a JSON string (usually opaquely used) along with the corresponding actions in any. In case of an error, +// matches and actions can still be returned, for instance in the case of a timeout error. Errors can be tested against +// the RunError type. +// Struct fields having the tag `ddwaf:"ignore"` will not be encoded and sent to the WAF +// if the output of TotalTime() exceeds the value of Timeout, the function will immediately return with errors.ErrTimeout +// The second parameter is deprecated and should be passed to NewContextWithBudget instead. +func (context *Context) Run(addressData RunAddressData) (res Result, err error) { + if addressData.isEmpty() { + return + } + + if addressData.Scope == "" { + addressData.Scope = DefaultScope + } + + defer func() { + if err == errors.ErrTimeout { + context.timeoutCount[addressData.Scope].Add(1) + } + }() + + // If the context has already timed out, we don't need to run the WAF again + if context.timer.SumExhausted() { + return Result{}, errors.ErrTimeout + } + + runTimer, err := context.timer.NewNode(wafRunTag, + timer.WithComponents( + wafEncodeTag, + wafDecodeTag, + wafDurationTag, + ), + ) + if err != nil { + return Result{}, err + } + + runTimer.Start() + defer func() { + context.metrics.add(addressData.Scope, wafRunTag, runTimer.Stop()) + context.metrics.merge(addressData.Scope, runTimer.Stats()) + }() + + wafEncodeTimer := runTimer.MustLeaf(wafEncodeTag) + wafEncodeTimer.Start() + persistentData, persistentEncoder, err := context.encodeOneAddressType(addressData.Scope, addressData.Persistent, wafEncodeTimer) + if err != nil { + wafEncodeTimer.Stop() + return res, err + } + + // The WAF releases ephemeral address data at the max of each run call, so we need not keep the Go values live beyond + // that in the same way we need for persistent data. We hence use a separate encoder. + ephemeralData, ephemeralEncoder, err := context.encodeOneAddressType(addressData.Scope, addressData.Ephemeral, wafEncodeTimer) + if err != nil { + wafEncodeTimer.Stop() + return res, err + } + + wafEncodeTimer.Stop() + + // ddwaf_run cannot run concurrently and we are going to mutate the context.cgoRefs, so we need to lock the context + context.mutex.Lock() + defer context.mutex.Unlock() + + if runTimer.SumExhausted() { + return res, errors.ErrTimeout + } + + // Save the Go pointer references to addressesToData that were referenced by the encoder + // into C ddwaf_objects. libddwaf's API requires to keep this data for the lifetime of the ddwaf_context. + defer context.cgoRefs.append(persistentEncoder.cgoRefs) + + wafDecodeTimer := runTimer.MustLeaf(wafDecodeTag) + res, err = context.run(persistentData, ephemeralData, wafDecodeTimer, runTimer.SumRemaining()) + + runTimer.AddTime(wafDurationTag, res.TimeSpent) + + // Ensure the ephemerals don't get optimized away by the compiler before the WAF had a chance to use them. + unsafe.KeepAlive(ephemeralEncoder.cgoRefs) + unsafe.KeepAlive(persistentEncoder.cgoRefs) + + return +} + +// merge merges two maps of slices into a single map of slices. The resulting map will contain all +// keys from both a and b, with the corresponding value from a and b concatenated (in this order) in +// a single slice. The implementation tries to minimize reallocations. +func merge[K comparable, V any](a, b map[K][]V) (merged map[K][]V) { + count := len(a) + len(b) + if count == 0 { + return + } + + keys := make(map[K]struct{}, count) + nothing := struct{}{} + totalCount := 0 + for _, m := range [2]map[K][]V{a, b} { + for k, v := range m { + keys[k] = nothing + totalCount += len(v) + } + } + + merged = make(map[K][]V, count) + values := make([]V, 0, totalCount) + + for k := range keys { + idxS := len(values) // Start index + values = append(values, a[k]...) + values = append(values, b[k]...) + idxE := len(values) // End index + + merged[k] = values[idxS:idxE] + } + + return +} + +// encodeOneAddressType encodes the given addressData values and returns the corresponding WAF object and its refs. +// If the addressData is empty, it returns nil for the WAF object and an empty ref pool. +// At this point, if the encoder does not timeout, the only error we can get is an error in case the top level object +// is a nil map, but this behaviour is expected since either persistent or ephemeral addresses are allowed to be null +// one at a time. In this case, Encode will return nil contrary to Encode which will return a nil wafObject, +// which is what we need to send to ddwaf_run to signal that the address data is empty. +func (context *Context) encodeOneAddressType(scope Scope, addressData map[string]any, timer timer.Timer) (*bindings.WafObject, encoder, error) { + encoder := newLimitedEncoder(timer) + if addressData == nil { + return nil, encoder, nil + } + + data, _ := encoder.Encode(addressData) + if len(encoder.truncations) > 0 { + context.mutex.Lock() + defer context.mutex.Unlock() + + context.truncations[scope] = merge(context.truncations[scope], encoder.truncations) + } + + if timer.Exhausted() { + return nil, encoder, errors.ErrTimeout + } + + return data, encoder, nil +} + +// run executes the ddwaf_run call with the provided data on this context. The caller is responsible for locking the +// context appropriately around this call. +func (context *Context) run(persistentData, ephemeralData *bindings.WafObject, wafDecodeTimer timer.Timer, timeBudget time.Duration) (Result, error) { + result := new(bindings.WafResult) + defer wafLib.WafResultFree(result) + + // The value of the timeout cannot exceed 2^55 + // cf. https://en.cppreference.com/w/cpp/chrono/duration + timeout := uint64(timeBudget.Microseconds()) & 0x008FFFFFFFFFFFFF + ret := wafLib.WafRun(context.cContext, persistentData, ephemeralData, result, timeout) + + wafDecodeTimer.Start() + defer wafDecodeTimer.Stop() + + return unwrapWafResult(ret, result) +} + +func unwrapWafResult(ret bindings.WafReturnCode, result *bindings.WafResult) (res Result, err error) { + if result.Timeout > 0 { + err = errors.ErrTimeout + } else { + // Derivatives can be generated even if no security event gets detected, so we decode them as long as the WAF + // didn't timeout + res.Derivatives, err = decodeMap(&result.Derivatives) + } + + res.TimeSpent = time.Duration(result.TotalRuntime) * time.Nanosecond + + if ret == bindings.WafOK { + return res, err + } + + if ret != bindings.WafMatch { + return res, goRunError(ret) + } + + res.Events, err = decodeArray(&result.Events) + if err != nil { + return res, err + } + if size := result.Actions.NbEntries; size > 0 { + res.Actions, err = decodeMap(&result.Actions) + if err != nil { + return res, err + } + } + + return res, err +} + +// Close the underlying `ddwaf_context` and releases the associated internal +// data. Also decreases the reference count of the `ddwaf_hadnle` which created +// this context, possibly releasing it completely (if this was the last context +// created from this handle & it was released by its creator). +func (context *Context) Close() { + context.mutex.Lock() + defer context.mutex.Unlock() + + wafLib.WafContextDestroy(context.cContext) + unsafe.KeepAlive(context.cgoRefs) // Keep the Go pointer references until the max of the context + defer context.handle.release() // Reduce the reference counter of the Handle. + + context.cgoRefs = cgoRefPool{} // The data in context.cgoRefs is no longer needed, explicitly release + context.cContext = 0 // Makes it easy to spot use-after-free/double-free issues +} + +// TotalRuntime returns the cumulated WAF runtime across various run calls within the same WAF context. +// Returned time is in nanoseconds. +// Deprecated: use Stats instead +func (context *Context) TotalRuntime() (uint64, uint64) { + return uint64(context.metrics.get(DefaultScope, wafRunTag)), uint64(context.metrics.get(DefaultScope, wafDurationTag)) +} + +// TotalTimeouts returns the cumulated amount of WAF timeouts across various run calls within the same WAF context. +// Deprecated: use Stats instead +func (context *Context) TotalTimeouts() uint64 { + return context.timeoutCount[DefaultScope].Load() +} + +// Stats returns the cumulative time spent in various parts of the WAF, all in nanoseconds +// and the timeout value used +func (context *Context) Stats() Stats { + context.mutex.Lock() + defer context.mutex.Unlock() + + truncations := make(map[TruncationReason][]int, len(context.truncations[DefaultScope])) + for reason, counts := range context.truncations[DefaultScope] { + truncations[reason] = make([]int, len(counts)) + copy(truncations[reason], counts) + } + + raspTruncations := make(map[TruncationReason][]int, len(context.truncations[RASPScope])) + for reason, counts := range context.truncations[RASPScope] { + raspTruncations[reason] = make([]int, len(counts)) + copy(raspTruncations[reason], counts) + } + + var ( + timeoutDefault uint64 + timeoutRASP uint64 + ) + + if atomic, ok := context.timeoutCount[DefaultScope]; ok { + timeoutDefault = atomic.Load() + } + + if atomic, ok := context.timeoutCount[RASPScope]; ok { + timeoutRASP = atomic.Load() + } + + return Stats{ + Timers: context.metrics.timers(), + TimeoutCount: timeoutDefault, + TimeoutRASPCount: timeoutRASP, + Truncations: truncations, + TruncationsRASP: raspTruncations, + } +} diff --git a/vendor/github.com/DataDog/go-libddwaf/v3/decoder.go b/vendor/github.com/DataDog/go-libddwaf/v3/decoder.go new file mode 100644 index 000000000..2e68f7722 --- /dev/null +++ b/vendor/github.com/DataDog/go-libddwaf/v3/decoder.go @@ -0,0 +1,247 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2016-present Datadog, Inc. + +package waf + +import ( + "github.com/DataDog/go-libddwaf/v3/errors" + "github.com/DataDog/go-libddwaf/v3/internal/bindings" + "github.com/DataDog/go-libddwaf/v3/internal/unsafe" +) + +// decodeErrors transforms the wafObject received by the wafRulesetInfo after the call to wafDl.wafInit to a map where +// keys are the error message and the value is a array of all the rule ids which triggered this specific error +func decodeErrors(obj *bindings.WafObject) (map[string][]string, error) { + if !obj.IsMap() { + return nil, errors.ErrInvalidObjectType + } + + if obj.Value == 0 && obj.NbEntries > 0 { + return nil, errors.ErrNilObjectPtr + } + + wafErrors := map[string][]string{} + for i := uint64(0); i < obj.NbEntries; i++ { + objElem := unsafe.CastWithOffset[bindings.WafObject](obj.Value, i) + + errorMessage := unsafe.GostringSized(unsafe.Cast[byte](objElem.ParameterName), objElem.ParameterNameLength) + ruleIds, err := decodeStringArray(objElem) + if err != nil { + return nil, err + } + + wafErrors[errorMessage] = ruleIds + } + + return wafErrors, nil +} + +func decodeDiagnostics(obj *bindings.WafObject) (*Diagnostics, error) { + if !obj.IsMap() { + return nil, errors.ErrInvalidObjectType + } + if obj.Value == 0 && obj.NbEntries > 0 { + return nil, errors.ErrNilObjectPtr + } + + var diags Diagnostics + var err error + for i := uint64(0); i < obj.NbEntries; i++ { + objElem := unsafe.CastWithOffset[bindings.WafObject](obj.Value, i) + key := unsafe.GostringSized(unsafe.Cast[byte](objElem.ParameterName), objElem.ParameterNameLength) + switch key { + case "actions": + diags.Actions, err = decodeDiagnosticsEntry(objElem) + case "custom_rules": + diags.CustomRules, err = decodeDiagnosticsEntry(objElem) + case "exclusions": + diags.Exclusions, err = decodeDiagnosticsEntry(objElem) + case "rules": + diags.Rules, err = decodeDiagnosticsEntry(objElem) + case "rules_data": + diags.RulesData, err = decodeDiagnosticsEntry(objElem) + case "rules_override": + diags.RulesOverrides, err = decodeDiagnosticsEntry(objElem) + case "processors": + diags.Processors, err = decodeDiagnosticsEntry(objElem) + case "scanners": + diags.Scanners, err = decodeDiagnosticsEntry(objElem) + case "ruleset_version": + diags.Version = unsafe.GostringSized(unsafe.Cast[byte](objElem.Value), objElem.NbEntries) + default: + // ignore? + } + if err != nil { + return nil, err + } + } + + return &diags, nil +} + +func decodeDiagnosticsEntry(obj *bindings.WafObject) (*DiagnosticEntry, error) { + if !obj.IsMap() { + return nil, errors.ErrInvalidObjectType + } + if obj.Value == 0 && obj.NbEntries > 0 { + return nil, errors.ErrNilObjectPtr + } + var entry DiagnosticEntry + var err error + + for i := uint64(0); i < obj.NbEntries; i++ { + objElem := unsafe.CastWithOffset[bindings.WafObject](obj.Value, i) + key := unsafe.GostringSized(unsafe.Cast[byte](objElem.ParameterName), objElem.ParameterNameLength) + switch key { + case "addresses": + entry.Addresses, err = decodeDiagnosticAddresses(objElem) + case "error": + entry.Error = unsafe.GostringSized(unsafe.Cast[byte](objElem.Value), objElem.NbEntries) + case "errors": + entry.Errors, err = decodeErrors(objElem) + case "failed": + entry.Failed, err = decodeStringArray(objElem) + case "loaded": + entry.Loaded, err = decodeStringArray(objElem) + default: + return nil, errors.ErrUnsupportedValue + } + + if err != nil { + return nil, err + } + } + + return &entry, nil +} + +func decodeDiagnosticAddresses(obj *bindings.WafObject) (*DiagnosticAddresses, error) { + if !obj.IsMap() { + return nil, errors.ErrInvalidObjectType + } + if obj.Value == 0 && obj.NbEntries > 0 { + return nil, errors.ErrNilObjectPtr + } + + addrs := &DiagnosticAddresses{} + + var err error + for i := uint64(0); i < obj.NbEntries; i++ { + objElem := unsafe.CastWithOffset[bindings.WafObject](obj.Value, i) + key := unsafe.GostringSized(unsafe.Cast[byte](objElem.ParameterName), objElem.ParameterNameLength) + switch key { + case "required": + addrs.Required, err = decodeStringArray(objElem) + if err != nil { + return nil, err + } + case "optional": + addrs.Optional, err = decodeStringArray(objElem) + if err != nil { + return nil, err + } + default: + return nil, errors.ErrUnsupportedValue + } + } + + return addrs, nil +} + +func decodeStringArray(obj *bindings.WafObject) ([]string, error) { + // We consider that nil is an empty array + if obj.IsNil() { + return nil, nil + } + + if !obj.IsArray() { + return nil, errors.ErrInvalidObjectType + } + + if obj.Value == 0 && obj.NbEntries > 0 { + return nil, errors.ErrNilObjectPtr + } + + var strArr []string + for i := uint64(0); i < obj.NbEntries; i++ { + objElem := unsafe.CastWithOffset[bindings.WafObject](obj.Value, i) + if objElem.Type != bindings.WafStringType { + return nil, errors.ErrInvalidObjectType + } + + strArr = append(strArr, unsafe.GostringSized(unsafe.Cast[byte](objElem.Value), objElem.NbEntries)) + } + + return strArr, nil +} + +func decodeObject(obj *bindings.WafObject) (any, error) { + switch obj.Type { + case bindings.WafMapType: + return decodeMap(obj) + case bindings.WafArrayType: + return decodeArray(obj) + case bindings.WafStringType: + return unsafe.GostringSized(unsafe.Cast[byte](obj.Value), obj.NbEntries), nil + case bindings.WafIntType: + return int64(obj.Value), nil + case bindings.WafUintType: + return uint64(obj.Value), nil + case bindings.WafFloatType: + return unsafe.UintptrToNative[float64](obj.Value), nil + case bindings.WafBoolType: + return unsafe.UintptrToNative[bool](obj.Value), nil + case bindings.WafNilType: + return nil, nil + default: + return nil, errors.ErrUnsupportedValue + } +} + +func decodeArray(obj *bindings.WafObject) ([]any, error) { + if obj.IsNil() { + return nil, nil + } + + if !obj.IsArray() { + return nil, errors.ErrInvalidObjectType + } + + events := make([]any, obj.NbEntries) + + for i := uint64(0); i < obj.NbEntries; i++ { + objElem := unsafe.CastWithOffset[bindings.WafObject](obj.Value, i) + val, err := decodeObject(objElem) + if err != nil { + return nil, err + } + events[i] = val + } + + return events, nil +} + +func decodeMap(obj *bindings.WafObject) (map[string]any, error) { + if obj.IsNil() { + return nil, nil + } + + if !obj.IsMap() { + return nil, errors.ErrInvalidObjectType + } + + result := make(map[string]any, obj.NbEntries) + for i := uint64(0); i < obj.NbEntries; i++ { + objElem := unsafe.CastWithOffset[bindings.WafObject](obj.Value, i) + key := unsafe.GostringSized(unsafe.Cast[byte](objElem.ParameterName), objElem.ParameterNameLength) + val, err := decodeObject(objElem) + if err != nil { + return nil, err + } + result[key] = val + } + + return result, nil +} diff --git a/vendor/github.com/DataDog/go-libddwaf/v2/encoder.go b/vendor/github.com/DataDog/go-libddwaf/v3/encoder.go similarity index 76% rename from vendor/github.com/DataDog/go-libddwaf/v2/encoder.go rename to vendor/github.com/DataDog/go-libddwaf/v3/encoder.go index 09cd732ea..dcf6b4882 100644 --- a/vendor/github.com/DataDog/go-libddwaf/v2/encoder.go +++ b/vendor/github.com/DataDog/go-libddwaf/v3/encoder.go @@ -7,11 +7,17 @@ package waf import ( "context" + "fmt" "math" "reflect" "strings" "time" "unicode" + + "github.com/DataDog/go-libddwaf/v3/errors" + "github.com/DataDog/go-libddwaf/v3/internal/bindings" + "github.com/DataDog/go-libddwaf/v3/internal/unsafe" + "github.com/DataDog/go-libddwaf/v3/timer" ) // Encode Go values into wafObjects. Only the subset of Go types representable into wafObjects @@ -22,6 +28,9 @@ import ( // reference now or in the future, are stored and referenced in the `cgoRefs` field. The user MUST leverage // `keepAlive()` with it according to its ddwaf use-case. type encoder struct { + // timer makes sure the encoder doesn't spend too much time doing its job. + timer timer.Timer + // For each TruncationReason, holds the size that is required to avoid truncation for each truncation that happened. truncations map[TruncationReason][]int @@ -35,11 +44,32 @@ type encoder struct { type TruncationReason uint8 const ( + // StringTooLong indicates a string exceeded the maximum string length configured. The truncation + // values indicate the actual length of truncated strings. StringTooLong TruncationReason = 1 << iota + // ContainerTooLarge indicates a container (list, map, struct) exceeded the maximum number of + // elements configured. The truncation values indicate the actual number of elements in the + // truncated container. ContainerTooLarge + // ObjectTooDeep indicates an overall object exceeded the maximum encoding depths configured. The + // truncation values indicate an estimated actual depth of the truncated object. The value is + // guaranteed to be less than or equal to the actual depth (it may not be more). ObjectTooDeep ) +func (reason TruncationReason) String() string { + switch reason { + case ObjectTooDeep: + return "depth" + case ContainerTooLarge: + return "container-size" + case StringTooLong: + return "string-size" + default: + return fmt.Sprintf("TruncationReason(%v)", int(reason)) + } +} + const ( AppsecFieldTag = "ddwaf" AppsecFieldTagValueIgnore = "ignore" @@ -49,16 +79,19 @@ type native interface { int64 | uint64 | uintptr } -func newLimitedEncoder() encoder { +func newLimitedEncoder(timer timer.Timer) encoder { return encoder{ - containerMaxSize: wafMaxContainerSize, - stringMaxSize: wafMaxStringLength, - objectMaxDepth: wafMaxContainerDepth, + timer: timer, + containerMaxSize: bindings.WafMaxContainerSize, + stringMaxSize: bindings.WafMaxStringLength, + objectMaxDepth: bindings.WafMaxContainerDepth, } } func newMaxEncoder() encoder { + timer, _ := timer.NewTimer(timer.WithUnlimitedBudget()) return encoder{ + timer: timer, containerMaxSize: math.MaxInt, stringMaxSize: math.MaxInt, objectMaxDepth: math.MaxInt, @@ -69,13 +102,14 @@ func newMaxEncoder() encoder { // The returned wafObject is the root of the tree of nested wafObjects representing the Go value. // The only error case is if the top-level object is "Unusable" which means that the data is nil or a non-data type // like a function or a channel. -func (encoder *encoder) Encode(data any) (wo *wafObject, err error) { +func (encoder *encoder) Encode(data any) (wo *bindings.WafObject, err error) { value := reflect.ValueOf(data) - wo = &wafObject{} + wo = &bindings.WafObject{} err = encoder.encode(value, wo, encoder.objectMaxDepth) - if len(encoder.truncations[ObjectTooDeep]) != 0 { - encoder.measureObjectDepth(value) + + if len(encoder.truncations[ObjectTooDeep]) != 0 && !encoder.timer.Exhausted() { + encoder.measureObjectDepth(value, encoder.timer.Remaining()) } return @@ -89,24 +123,9 @@ func (encoder *encoder) Truncations() map[TruncationReason][]int { return result } -// EncodeAddresses takes a map of Go values and returns a wafObject pointer and an error. -// The returned wafObject is the root of the tree of nested wafObjects representing the Go values. -// This function is further optimized from Encode to take addresses as input and avoid further -// errors in case the top-level map with addresses as keys is nil. -// Since errors returned by Encode are not sent up between levels of the tree, this means that all errors come from the -// top layer of encoding, which is the map of addresses. Hence, all errors should be developer errors since the map of -// addresses is not user defined custom data. -func (encoder *encoder) EncodeAddresses(addresses map[string]any) (*wafObject, error) { - if addresses == nil { - return nil, errUnsupportedValue - } - - return encoder.Encode(addresses) -} - -func encodeNative[T native](val T, t wafObjectType, obj *wafObject) { - obj._type = t - obj.value = (uintptr)(val) +func encodeNative[T native](val T, t bindings.WafObjectType, obj *bindings.WafObject) { + obj.Type = t + obj.Value = (uintptr)(val) } var nullableTypeKinds = map[reflect.Kind]struct{}{ @@ -126,12 +145,16 @@ func isValueNil(value reflect.Value) bool { return nullable && value.IsNil() } -func (encoder *encoder) encode(value reflect.Value, obj *wafObject, depth int) error { +func (encoder *encoder) encode(value reflect.Value, obj *bindings.WafObject, depth int) error { + if encoder.timer.Exhausted() { + return errors.ErrTimeout + } + value, kind := resolvePointer(value) if (kind == reflect.Interface || kind == reflect.Pointer) && !value.IsNil() { // resolvePointer failed to resolve to something that's not a pointer, it // has indirected too many times... - return errTooManyIndirections + return errors.ErrTooManyIndirections } // Measure-only runs for leaves @@ -144,22 +167,22 @@ func (encoder *encoder) encode(value reflect.Value, obj *wafObject, depth int) e // Terminal cases (leaves of the tree) // Is invalid type: nil interfaces for example, cannot be used to run any reflect method or it's susceptible to panic case !value.IsValid() || kind == reflect.Invalid: - return errUnsupportedValue + return errors.ErrUnsupportedValue // Is nullable type: nil pointers, channels, maps or functions case isValueNil(value): - encodeNative[uintptr](0, wafNilType, obj) + encodeNative[uintptr](0, bindings.WafNilType, obj) // Booleans case kind == reflect.Bool: - encodeNative(nativeToUintptr(value.Bool()), wafBoolType, obj) + encodeNative(unsafe.NativeToUintptr(value.Bool()), bindings.WafBoolType, obj) // Numbers case value.CanInt(): // any int type or alias - encodeNative(value.Int(), wafIntType, obj) + encodeNative(value.Int(), bindings.WafIntType, obj) case value.CanUint(): // any Uint type or alias - encodeNative(value.Uint(), wafUintType, obj) + encodeNative(value.Uint(), bindings.WafUintType, obj) case value.CanFloat(): // any float type or alias - encodeNative(nativeToUintptr(value.Float()), wafFloatType, obj) + encodeNative(unsafe.NativeToUintptr(value.Float()), bindings.WafFloatType, obj) // Strings case kind == reflect.String: // string type @@ -176,7 +199,7 @@ func (encoder *encoder) encode(value reflect.Value, obj *wafObject, depth int) e case depth <= 0: // Record that there was a truncation; we will try to measure the actual depth of the object afterwards. encoder.addTruncation(ObjectTooDeep, -1) - return errMaxDepthExceeded + return errors.ErrMaxDepthExceeded // Either an array or a slice of an array case kind == reflect.Array || kind == reflect.Slice: @@ -187,13 +210,13 @@ func (encoder *encoder) encode(value reflect.Value, obj *wafObject, depth int) e encoder.encodeStruct(value, obj, depth-1) default: - return errUnsupportedValue + return errors.ErrUnsupportedValue } return nil } -func (encoder *encoder) encodeString(str string, obj *wafObject) { +func (encoder *encoder) encodeString(str string, obj *bindings.WafObject) { size := len(str) if size > encoder.stringMaxSize { str = str[:encoder.stringMaxSize] @@ -229,7 +252,11 @@ func getFieldNameFromType(field reflect.StructField) (string, bool) { // - If the field has a json tag it will become the field name // - Private fields and also values producing an error at encoding will be skipped // - Even if the element values are invalid or null we still keep them to report the field name -func (encoder *encoder) encodeStruct(value reflect.Value, obj *wafObject, depth int) { +func (encoder *encoder) encodeStruct(value reflect.Value, obj *bindings.WafObject, depth int) { + if encoder.timer.Exhausted() { + return + } + typ := value.Type() nbFields := typ.NumField() @@ -239,8 +266,12 @@ func (encoder *encoder) encodeStruct(value reflect.Value, obj *wafObject, depth capacity = encoder.containerMaxSize } - objArray := encoder.cgoRefs.AllocWafArray(obj, wafMapType, uint64(capacity)) + objArray := encoder.cgoRefs.AllocWafArray(obj, bindings.WafMapType, uint64(capacity)) for i := 0; i < nbFields; i++ { + if encoder.timer.Exhausted() { + return + } + if length == capacity { encoder.addTruncation(ContainerTooLarge, nbFields) break @@ -260,30 +291,34 @@ func (encoder *encoder) encodeStruct(value reflect.Value, obj *wafObject, depth if err := encoder.encode(value.Field(i), objElem, depth); err != nil { // We still need to keep the map key, so we can't discard the full object, instead, we make the value a noop - encodeNative[uintptr](0, wafInvalidType, objElem) + encodeNative[uintptr](0, bindings.WafInvalidType, objElem) } length++ } // Set the length to the final number of successfully encoded elements - obj.nbEntries = uint64(length) + obj.NbEntries = uint64(length) } // encodeMap takes a reflect.Value and a wafObject pointer and iterates on the map elements and returns // a wafObject map of type wafMapType. The specificities are the following: // - It will only take the first encoder.containerMaxSize elements of the map // - Even if the element values are invalid or null we still keep them to report the map key -func (encoder *encoder) encodeMap(value reflect.Value, obj *wafObject, depth int) { +func (encoder *encoder) encodeMap(value reflect.Value, obj *bindings.WafObject, depth int) { capacity := value.Len() if capacity > encoder.containerMaxSize { capacity = encoder.containerMaxSize } - objArray := encoder.cgoRefs.AllocWafArray(obj, wafMapType, uint64(capacity)) + objArray := encoder.cgoRefs.AllocWafArray(obj, bindings.WafMapType, uint64(capacity)) length := 0 for iter := value.MapRange(); iter.Next(); { + if encoder.timer.Exhausted() { + return + } + if length == capacity { encoder.addTruncation(ContainerTooLarge, value.Len()) break @@ -296,32 +331,32 @@ func (encoder *encoder) encodeMap(value reflect.Value, obj *wafObject, depth int if err := encoder.encode(iter.Value(), objElem, depth); err != nil { // We still need to keep the map key, so we can't discard the full object, instead, we make the value a noop - encodeNative[uintptr](0, wafInvalidType, objElem) + encodeNative[uintptr](0, bindings.WafInvalidType, objElem) } length++ } // Fix the size because we skipped map entries - obj.nbEntries = uint64(length) + obj.NbEntries = uint64(length) } // encodeMapKey takes a reflect.Value and a wafObject and returns a wafObject ready to be considered a map entry. We use // the function cgoRefPool.AllocWafMapKey to store the key in the wafObject. But first we need to grab the real // underlying value by recursing through the pointer and interface values. -func (encoder *encoder) encodeMapKey(value reflect.Value, obj *wafObject) error { +func (encoder *encoder) encodeMapKey(value reflect.Value, obj *bindings.WafObject) error { value, kind := resolvePointer(value) var keyStr string switch { case kind == reflect.Invalid: - return errInvalidMapKey + return errors.ErrInvalidMapKey case kind == reflect.String: keyStr = value.String() case value.Type() == reflect.TypeOf([]byte(nil)): keyStr = string(value.Bytes()) default: - return errInvalidMapKey + return errors.ErrInvalidMapKey } encoder.encodeMapKeyFromString(keyStr, obj) @@ -330,7 +365,7 @@ func (encoder *encoder) encodeMapKey(value reflect.Value, obj *wafObject) error // encodeMapKeyFromString takes a string and a wafObject and sets the map key attribute on the wafObject to the supplied // string. The key may be truncated if it exceeds the maximum string size allowed by the encoder. -func (encoder *encoder) encodeMapKeyFromString(keyStr string, obj *wafObject) { +func (encoder *encoder) encodeMapKeyFromString(keyStr string, obj *bindings.WafObject) { size := len(keyStr) if size > encoder.stringMaxSize { keyStr = keyStr[:encoder.stringMaxSize] @@ -344,7 +379,7 @@ func (encoder *encoder) encodeMapKeyFromString(keyStr string, obj *wafObject) { // a wafObject array of type wafArrayType. The specificities are the following: // - It will only take the first encoder.containerMaxSize elements of the array // - Elements producing an error at encoding or null values will be skipped -func (encoder *encoder) encodeArray(value reflect.Value, obj *wafObject, depth int) { +func (encoder *encoder) encodeArray(value reflect.Value, obj *bindings.WafObject, depth int) { length := value.Len() capacity := length @@ -354,9 +389,12 @@ func (encoder *encoder) encodeArray(value reflect.Value, obj *wafObject, depth i currIndex := 0 - objArray := encoder.cgoRefs.AllocWafArray(obj, wafArrayType, uint64(capacity)) + objArray := encoder.cgoRefs.AllocWafArray(obj, bindings.WafArrayType, uint64(capacity)) for i := 0; i < length; i++ { + if encoder.timer.Exhausted() { + return + } if currIndex == capacity { encoder.addTruncation(ContainerTooLarge, length) break @@ -377,7 +415,7 @@ func (encoder *encoder) encodeArray(value reflect.Value, obj *wafObject, depth i } // Fix the size because we skipped map entries - obj.nbEntries = uint64(currIndex) + obj.NbEntries = uint64(currIndex) } func (encoder *encoder) addTruncation(reason TruncationReason, size int) { @@ -390,8 +428,8 @@ func (encoder *encoder) addTruncation(reason TruncationReason, size int) { // mesureObjectDepth traverses the provided object recursively to try and obtain // the real object depth, but limits itself to about 1ms of time budget, past // which it'll stop and return whatever it has go to so far. -func (encoder *encoder) measureObjectDepth(obj reflect.Value) { - ctx, cancelCtx := context.WithTimeout(context.Background(), time.Millisecond) +func (encoder *encoder) measureObjectDepth(obj reflect.Value, timeout time.Duration) { + ctx, cancelCtx := context.WithTimeout(context.Background(), timeout) defer cancelCtx() depth, _ := depthOf(ctx, obj) @@ -408,14 +446,6 @@ func depthOf(ctx context.Context, obj reflect.Value) (depth int, err error) { obj, kind := resolvePointer(obj) - //TODO: Remove this once Go 1.21 is the minimum supported version (it adds `builtin.max`) - max := func(x, y int) int { - if x > y { - return x - } - return y - } - var itemDepth int switch kind { case reflect.Array, reflect.Slice: diff --git a/vendor/github.com/DataDog/go-libddwaf/v3/errors/support.go b/vendor/github.com/DataDog/go-libddwaf/v3/errors/support.go new file mode 100644 index 000000000..79fbe1da3 --- /dev/null +++ b/vendor/github.com/DataDog/go-libddwaf/v3/errors/support.go @@ -0,0 +1,45 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2016-present Datadog, Inc. + +package errors + +import ( + "fmt" + "runtime" +) + +// UnsupportedOSArchError is a wrapper error type helping to handle the error +// case of trying to execute this package when the OS or architecture is not supported. +type UnsupportedOSArchError struct { + Os string + Arch string +} + +func (e UnsupportedOSArchError) Error() string { + return fmt.Sprintf("unsupported OS/Arch: %s/%s", e.Os, e.Arch) +} + +// UnsupportedGoVersionError is a wrapper error type helping to handle the error +// case of trying to execute this package when the Go version is not supported. +type UnsupportedGoVersionError struct{} + +func (e UnsupportedGoVersionError) Error() string { + return fmt.Sprintf("unsupported Go version: %s", runtime.Version()) +} + +type CgoDisabledError struct{} + +func (e CgoDisabledError) Error() string { + return "go-libddwaf is disabled when cgo is disabled unless you compile with the go build tag `appsec`. It will require libdl.so.2. libpthread.so.0 and libc.so.6 shared libraries at run time on linux" +} + +// ManuallyDisabledError is a wrapper error type helping to handle the error +// case of trying to execute this package when the WAF has been manually disabled with +// the `datadog.no_waf` go build tag. +type ManuallyDisabledError struct{} + +func (e ManuallyDisabledError) Error() string { + return "the WAF has been manually disabled using the `datadog.no_waf` go build tag" +} diff --git a/vendor/github.com/DataDog/go-libddwaf/v3/errors/waf.go b/vendor/github.com/DataDog/go-libddwaf/v3/errors/waf.go new file mode 100644 index 000000000..a991bcb9d --- /dev/null +++ b/vendor/github.com/DataDog/go-libddwaf/v3/errors/waf.go @@ -0,0 +1,77 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2016-present Datadog, Inc. + +package errors + +import ( + "errors" + "fmt" +) + +// Encoder/Decoder errors +var ( + ErrMaxDepthExceeded = errors.New("max depth exceeded") + ErrUnsupportedValue = errors.New("unsupported Go value") + ErrInvalidMapKey = errors.New("invalid WAF object map key") + ErrNilObjectPtr = errors.New("nil WAF object pointer") + ErrInvalidObjectType = errors.New("invalid type encountered when decoding") + ErrTooManyIndirections = errors.New("too many indirections") +) + +// RunError the WAF can return when running it. +type RunError int + +// Errors the WAF can return when running it. +const ( + ErrInternal RunError = iota + 1 + ErrInvalidObject + ErrInvalidArgument + ErrTimeout + ErrOutOfMemory + ErrEmptyRuleAddresses +) + +// Error returns the string representation of the RunError. +func (e RunError) Error() string { + switch e { + case ErrInternal: + return "internal waf error" + case ErrTimeout: + return "waf timeout" + case ErrInvalidObject: + return "invalid waf object" + case ErrInvalidArgument: + return "invalid waf argument" + case ErrOutOfMemory: + return "out of memory" + case ErrEmptyRuleAddresses: + return "empty rule addresses" + default: + return fmt.Sprintf("unknown waf error %d", e) + } +} + +// PanicError is an error type wrapping a recovered panic value that happened +// during a function call. Such error must be considered unrecoverable and be +// used to try to gracefully abort. Keeping using this package after such an +// error is unreliable and the caller must rather stop using the library. +// Examples include safety checks errors. +type PanicError struct { + // The recovered panic error while executing the function `in`. + Err error + // The function symbol name that was given to `tryCall()`. + In string +} + +// Unwrap the error and return it. +// Required by errors.Is and errors.As functions. +func (e *PanicError) Unwrap() error { + return e.Err +} + +// Error returns the error string representation. +func (e *PanicError) Error() string { + return fmt.Sprintf("panic while executing %s: %#+v", e.In, e.Err) +} diff --git a/vendor/github.com/DataDog/go-libddwaf/v2/handle.go b/vendor/github.com/DataDog/go-libddwaf/v3/handle.go similarity index 64% rename from vendor/github.com/DataDog/go-libddwaf/v2/handle.go rename to vendor/github.com/DataDog/go-libddwaf/v3/handle.go index eb8da0e41..8c37f90ec 100644 --- a/vendor/github.com/DataDog/go-libddwaf/v2/handle.go +++ b/vendor/github.com/DataDog/go-libddwaf/v3/handle.go @@ -8,9 +8,13 @@ package waf import ( "errors" "fmt" + "sync/atomic" + "time" - "github.com/DataDog/go-libddwaf/v2/internal/noopfree" - "go.uber.org/atomic" + wafErrors "github.com/DataDog/go-libddwaf/v3/errors" + "github.com/DataDog/go-libddwaf/v3/internal/bindings" + "github.com/DataDog/go-libddwaf/v3/internal/unsafe" + "github.com/DataDog/go-libddwaf/v3/timer" ) // Handle represents an instance of the WAF for a given ruleset. @@ -28,10 +32,10 @@ type Handle struct { // time with their own set of rules. This choice was done to be able to // efficiently update the security rules concurrently, without having to // block the request handlers for the time of the security rules update. - refCounter *atomic.Int32 + refCounter atomic.Int32 // Instance of the WAF - cHandle wafHandle + cHandle bindings.WafHandle } // NewHandle creates and returns a new instance of the WAF with the given security rules and configuration @@ -59,16 +63,16 @@ func NewHandle(rules any, keyObfuscatorRegex string, valueObfuscatorRegex string } config := newConfig(&encoder.cgoRefs, keyObfuscatorRegex, valueObfuscatorRegex) - diagnosticsWafObj := new(wafObject) - defer wafLib.wafObjectFree(diagnosticsWafObj) + diagnosticsWafObj := new(bindings.WafObject) + defer wafLib.WafObjectFree(diagnosticsWafObj) - cHandle := wafLib.wafInit(obj, config, diagnosticsWafObj, encoder.cgoRefs) + cHandle := wafLib.WafInit(obj, config, diagnosticsWafObj) // Upon failure, the WAF may have produced some diagnostics to help signal what went wrong... var ( - diags *Diagnostics + diags = new(Diagnostics) diagsErr error ) - if !diagnosticsWafObj.isInvalid() { + if !diagnosticsWafObj.IsInvalid() { diags, diagsErr = decodeDiagnostics(diagnosticsWafObj) } @@ -86,14 +90,58 @@ func NewHandle(rules any, keyObfuscatorRegex string, valueObfuscatorRegex string // The WAF successfully initialized at this stage... if diagsErr != nil { - wafLib.wafDestroy(cHandle) + wafLib.WafDestroy(cHandle) return nil, fmt.Errorf("could not decode the WAF diagnostics: %w", diagsErr) } - return &Handle{ + unsafe.KeepAlive(encoder.cgoRefs) + + handle := &Handle{ cHandle: cHandle, - refCounter: atomic.NewInt32(1), // We count the handle itself in the counter diagnostics: *diags, + } + + handle.refCounter.Store(1) // We count the handle itself in the counter + return handle, nil +} + +// NewContext returns a new WAF context for the given WAF handle. +// A nil value is returned when the WAF handle was released or when the +// WAF context couldn't be created. +func (handle *Handle) NewContext() (*Context, error) { + return handle.NewContextWithBudget(timer.UnlimitedBudget) +} + +// NewContextWithBudget returns a new WAF context for the given WAF handle. +// A nil value is returned when the WAF handle was released or when the +// WAF context couldn't be created. +func (handle *Handle) NewContextWithBudget(budget time.Duration) (*Context, error) { + // Handle has been released + if !handle.retain() { + return nil, fmt.Errorf("handle was released") + } + + cContext := wafLib.WafContextInit(handle.cHandle) + if cContext == 0 { + handle.release() // We couldn't get a context, so we no longer have an implicit reference to the Handle in it... + return nil, fmt.Errorf("could not get C context") + } + + timer, err := timer.NewTreeTimer(timer.WithBudget(budget), timer.WithComponents(wafRunTag)) + if err != nil { + return nil, err + } + + return &Context{ + handle: handle, + cContext: cContext, + timer: timer, + metrics: metricsStore{data: make(map[metricKey]time.Duration, 5)}, + truncations: make(map[Scope]map[TruncationReason][]int, 2), + timeoutCount: map[Scope]*atomic.Uint64{ + DefaultScope: new(atomic.Uint64), + RASPScope: new(atomic.Uint64), + }, }, nil } @@ -102,9 +150,14 @@ func (handle *Handle) Diagnostics() Diagnostics { return handle.diagnostics } -// Addresses returns the list of addresses the WAF rule is expecting. +// Addresses returns the list of addresses the WAF has been configured to monitor based on the input ruleset func (handle *Handle) Addresses() []string { - return wafLib.wafKnownAddresses(handle.cHandle) + return wafLib.WafKnownAddresses(handle.cHandle) +} + +// Actions returns the list of actions the WAF has been configured to monitor based on the input ruleset +func (handle *Handle) Actions() []string { + return wafLib.WafKnownActions(handle.cHandle) } // Update the ruleset of a WAF instance into a new handle on its own @@ -116,24 +169,26 @@ func (handle *Handle) Update(newRules any) (*Handle, error) { return nil, fmt.Errorf("could not encode the WAF ruleset into a WAF object: %w", err) } - diagnosticsWafObj := new(wafObject) + diagnosticsWafObj := new(bindings.WafObject) - cHandle := wafLib.wafUpdate(handle.cHandle, obj, diagnosticsWafObj) - keepAlive(encoder.cgoRefs) + cHandle := wafLib.WafUpdate(handle.cHandle, obj, diagnosticsWafObj) + unsafe.KeepAlive(encoder.cgoRefs) if cHandle == 0 { return nil, errors.New("could not update the WAF instance") } - defer wafLib.wafObjectFree(diagnosticsWafObj) + defer wafLib.WafObjectFree(diagnosticsWafObj) if err != nil { // Something is very wrong return nil, fmt.Errorf("could not decode the WAF ruleset errors: %w", err) } - return &Handle{ - cHandle: cHandle, - refCounter: atomic.NewInt32(1), // We count the handle itself in the counter - }, nil + newHandle := &Handle{ + cHandle: cHandle, + } + + newHandle.refCounter.Store(1) // We count the handle itself in the counter + return newHandle, nil } // Close puts the handle in termination state, when all the contexts are closed the handle will be destroyed @@ -144,7 +199,7 @@ func (handle *Handle) Close() { return } - wafLib.wafDestroy(handle.cHandle) + wafLib.WafDestroy(handle.cHandle) handle.diagnostics = Diagnostics{} // Data in diagnostics may no longer be valid (e.g: strings from libddwaf) handle.cHandle = 0 // Makes it easy to spot use-after-free/double-free issues } @@ -190,32 +245,32 @@ func (handle *Handle) addRefCounter(x int32) int32 { } } -func newConfig(cgoRefs *cgoRefPool, keyObfuscatorRegex string, valueObfuscatorRegex string) *wafConfig { - config := new(wafConfig) - *config = wafConfig{ - limits: wafConfigLimits{ - maxContainerDepth: wafMaxContainerDepth, - maxContainerSize: wafMaxContainerSize, - maxStringLength: wafMaxStringLength, +func newConfig(cgoRefs *cgoRefPool, keyObfuscatorRegex string, valueObfuscatorRegex string) *bindings.WafConfig { + config := new(bindings.WafConfig) + *config = bindings.WafConfig{ + Limits: bindings.WafConfigLimits{ + MaxContainerDepth: bindings.WafMaxContainerDepth, + MaxContainerSize: bindings.WafMaxContainerSize, + MaxStringLength: bindings.WafMaxStringLength, }, - obfuscator: wafConfigObfuscator{ - keyRegex: cgoRefs.AllocCString(keyObfuscatorRegex), - valueRegex: cgoRefs.AllocCString(valueObfuscatorRegex), + Obfuscator: bindings.WafConfigObfuscator{ + KeyRegex: cgoRefs.AllocCString(keyObfuscatorRegex), + ValueRegex: cgoRefs.AllocCString(valueObfuscatorRegex), }, // Prevent libddwaf from freeing our Go-memory-allocated ddwaf_objects - freeFn: noopfree.NoopFreeFn, + FreeFn: 0, } return config } -func goRunError(rc wafReturnCode) error { +func goRunError(rc bindings.WafReturnCode) error { switch rc { - case wafErrInternal: - return ErrInternal - case wafErrInvalidObject: - return ErrInvalidObject - case wafErrInvalidArgument: - return ErrInvalidArgument + case bindings.WafErrInternal: + return wafErrors.ErrInternal + case bindings.WafErrInvalidObject: + return wafErrors.ErrInvalidObject + case bindings.WafErrInvalidArgument: + return wafErrors.ErrInvalidArgument default: return fmt.Errorf("unknown waf return code %d", int(rc)) } diff --git a/vendor/github.com/DataDog/go-libddwaf/v3/internal/bindings/ctypes.go b/vendor/github.com/DataDog/go-libddwaf/v3/internal/bindings/ctypes.go new file mode 100644 index 000000000..ba21f902a --- /dev/null +++ b/vendor/github.com/DataDog/go-libddwaf/v3/internal/bindings/ctypes.go @@ -0,0 +1,113 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2016-present Datadog, Inc. + +package bindings + +const ( + WafMaxStringLength = 4096 + WafMaxContainerDepth = 20 + WafMaxContainerSize = 256 + WafRunTimeout = 5000 +) + +type WafReturnCode int32 + +const ( + WafErrInternal WafReturnCode = iota - 3 + WafErrInvalidObject + WafErrInvalidArgument + WafOK + WafMatch +) + +// wafObjectType is an enum in C which has the size of DWORD. +// But DWORD is 4 bytes in amd64 and arm64 so uint32 it is. +type WafObjectType uint32 + +const WafInvalidType WafObjectType = 0 +const ( + WafIntType WafObjectType = 1 << iota + WafUintType + WafStringType + WafArrayType + WafMapType + WafBoolType + WafFloatType + WafNilType +) + +type WafObject struct { + ParameterName uintptr + ParameterNameLength uint64 + Value uintptr + NbEntries uint64 + Type WafObjectType + _ [4]byte + // Forced padding + // We only support 2 archs and cgo generated the same padding to both. + // We don't want the C struct to be packed because actually go will do the same padding itself, + // we just add it explicitly to not take any chance. + // And we cannot pack a struct in go so it will get tricky if the struct is + // packed (apart from breaking all tracers of course) +} + +// isInvalid determines whether this WAF Object has the invalid type (which is the 0-value). +func (w *WafObject) IsInvalid() bool { + return w.Type == WafInvalidType +} + +// isNil determines whether this WAF Object is nil or not. +func (w *WafObject) IsNil() bool { + return w.Type == WafNilType +} + +// isArray determines whether this WAF Object is an array or not. +func (w *WafObject) IsArray() bool { + return w.Type == WafArrayType +} + +// isMap determines whether this WAF Object is a map or not. +func (w *WafObject) IsMap() bool { + return w.Type == WafMapType +} + +// IsUnusable returns true if the wafObject has no impact on the WAF execution +// But we still need this kind of objects to forward map keys in case the value of the map is invalid +func (wo *WafObject) IsUnusable() bool { + return wo.Type == WafInvalidType || wo.Type == WafNilType +} + +type WafConfig struct { + Limits WafConfigLimits + Obfuscator WafConfigObfuscator + FreeFn uintptr +} + +type WafConfigLimits struct { + MaxContainerSize uint32 + MaxContainerDepth uint32 + MaxStringLength uint32 +} + +type WafConfigObfuscator struct { + KeyRegex uintptr // char * + ValueRegex uintptr // char * +} + +type WafResult struct { + Timeout byte + Events WafObject + Actions WafObject + Derivatives WafObject + TotalRuntime uint64 +} + +// wafHandle is a forward declaration in ddwaf.h header +// We basically don't need to modify it, only to give it to the waf +type WafHandle uintptr + +// wafContext is a forward declaration in ddwaf.h header +// We basically don't need to modify it, only to give it to the waf +type WafContext uintptr diff --git a/vendor/github.com/DataDog/go-libddwaf/v3/internal/bindings/safe.go b/vendor/github.com/DataDog/go-libddwaf/v3/internal/bindings/safe.go new file mode 100644 index 000000000..8106913ee --- /dev/null +++ b/vendor/github.com/DataDog/go-libddwaf/v3/internal/bindings/safe.go @@ -0,0 +1,47 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2016-present Datadog, Inc. + +package bindings + +import ( + wafErrors "github.com/DataDog/go-libddwaf/v3/errors" + + "fmt" + "reflect" + "runtime" + + "github.com/pkg/errors" +) + +func newPanicError(in func() error, err error) *wafErrors.PanicError { + return &wafErrors.PanicError{ + In: runtime.FuncForPC(reflect.ValueOf(in).Pointer()).Name(), + Err: err, + } +} + +// tryCall calls function `f` and recovers from any panic occurring while it +// executes, returning it in a `PanicError` object type. +func tryCall(f func() error) (err error) { + defer func() { + r := recover() + if r == nil { + // Note that panic(nil) matches this case and cannot be really tested for. + return + } + + switch actual := r.(type) { + case error: + err = errors.WithStack(actual) + case string: + err = errors.New(actual) + default: + err = fmt.Errorf("%v", r) + } + + err = newPanicError(f, err) + }() + return f() +} diff --git a/vendor/github.com/DataDog/go-libddwaf/v2/waf_dl.go b/vendor/github.com/DataDog/go-libddwaf/v3/internal/bindings/waf_dl.go similarity index 51% rename from vendor/github.com/DataDog/go-libddwaf/v2/waf_dl.go rename to vendor/github.com/DataDog/go-libddwaf/v3/internal/bindings/waf_dl.go index a68eceb30..c50d3c6f6 100644 --- a/vendor/github.com/DataDog/go-libddwaf/v2/waf_dl.go +++ b/vendor/github.com/DataDog/go-libddwaf/v3/internal/bindings/waf_dl.go @@ -3,16 +3,18 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2016-present Datadog, Inc. -//go:build (linux || darwin) && (amd64 || arm64) && !go1.23 && !datadog.no_waf && (cgo || appsec) +//go:build (linux || darwin) && (amd64 || arm64) && !go1.24 && !datadog.no_waf && (cgo || appsec) -package waf +package bindings import ( + "errors" "fmt" "os" - "github.com/DataDog/go-libddwaf/v2/internal/lib" - "github.com/DataDog/go-libddwaf/v2/internal/log" + "github.com/DataDog/go-libddwaf/v3/internal/lib" + "github.com/DataDog/go-libddwaf/v3/internal/log" + "github.com/DataDog/go-libddwaf/v3/internal/unsafe" "github.com/ebitengine/purego" ) @@ -20,7 +22,7 @@ import ( // It uses `libwaf` to make C calls // All calls must go through this one-liner to be type safe // since purego calls are not type safe -type wafDl struct { +type WafDl struct { wafSymbols handle uintptr } @@ -30,6 +32,7 @@ type wafSymbols struct { update uintptr destroy uintptr knownAddresses uintptr + knownActions uintptr getVersion uintptr contextInit uintptr contextDestroy uintptr @@ -38,52 +41,43 @@ type wafSymbols struct { run uintptr } -// newWafDl loads the libddwaf shared library and resolves all tge relevant symbols. +// NewWafDl loads the libddwaf shared library and resolves all tge relevant symbols. // The caller is responsible for calling wafDl.Close on the returned object once they // are done with it so that associated resources can be released. -func newWafDl() (dl *wafDl, err error) { - var file string - file, err = lib.DumpEmbeddedWAF() +func NewWafDl() (dl *WafDl, err error) { + path, closer, err := lib.DumpEmbeddedWAF() if err != nil { - return + return nil, fmt.Errorf("dump embedded WAF: %w", err) } defer func() { - rmErr := os.Remove(file) - if rmErr != nil { - if err == nil { - err = rmErr - } else { - // TODO: rely on errors.Join() once go1.20 is our min supported Go version - err = fmt.Errorf("%w; along with an error while removing %s: %v", err, file, rmErr) - } + if rmErr := closer(); rmErr != nil { + err = errors.Join(err, fmt.Errorf("error removing %s: %w", path, rmErr)) } }() var handle uintptr - if handle, err = purego.Dlopen(file, purego.RTLD_GLOBAL|purego.RTLD_NOW); err != nil { - return + if handle, err = purego.Dlopen(path, purego.RTLD_GLOBAL|purego.RTLD_NOW); err != nil { + return nil, fmt.Errorf("load a dynamic library file: %w", err) } var symbols wafSymbols if symbols, err = resolveWafSymbols(handle); err != nil { if closeErr := purego.Dlclose(handle); closeErr != nil { - // TODO: rely on errors.Join() once go1.20 is our min supported Go version - err = fmt.Errorf("%w; along with an error while releasing the shared libddwaf library: %v", err, closeErr) + err = errors.Join(err, fmt.Errorf("error released the shared libddwaf library: %w", closeErr)) } return } - dl = &wafDl{symbols, handle} + dl = &WafDl{symbols, handle} // Try calling the waf to make sure everything is fine err = tryCall(func() error { - dl.wafGetVersion() + dl.WafGetVersion() return nil }) if err != nil { if closeErr := purego.Dlclose(handle); closeErr != nil { - // TODO: rely on errors.Join() once go1.20 is our min supported Go version - err = fmt.Errorf("%w; along with an error while releasing the shared libddwaf library: %v", err, closeErr) + err = errors.Join(err, fmt.Errorf("error released the shared libddwaf library: %w", closeErr)) } return } @@ -91,7 +85,7 @@ func newWafDl() (dl *wafDl, err error) { if val := os.Getenv(log.EnvVarLogLevel); val != "" { setLogSym, symErr := purego.Dlsym(handle, "ddwaf_set_log_cb") if symErr != nil { - return + return nil, fmt.Errorf("get symbol: %w", symErr) } logLevel := log.LevelNamed(val) dl.syscall(setLogSym, log.CallbackFunctionPointer(), uintptr(logLevel)) @@ -100,90 +94,101 @@ func newWafDl() (dl *wafDl, err error) { return } -func (waf *wafDl) Close() error { +func (waf *WafDl) Close() error { return purego.Dlclose(waf.handle) } -// wafGetVersion returned string is a static string so we do not need to free it -func (waf *wafDl) wafGetVersion() string { - return gostring(cast[byte](waf.syscall(waf.getVersion))) +// WafGetVersion returned string is a static string so we do not need to free it +func (waf *WafDl) WafGetVersion() string { + return unsafe.Gostring(unsafe.Cast[byte](waf.syscall(waf.getVersion))) } -// wafInit initializes a new WAF with the provided ruleset, configuration and info objects. A +// WafInit initializes a new WAF with the provided ruleset, configuration and info objects. A // cgoRefPool ensures that the provided input values are not moved or garbage collected by the Go // runtime during the WAF call. -func (waf *wafDl) wafInit(ruleset *wafObject, config *wafConfig, info *wafObject, refs cgoRefPool) wafHandle { - handle := wafHandle(waf.syscall(waf.init, ptrToUintptr(ruleset), ptrToUintptr(config), ptrToUintptr(info))) - keepAlive(ruleset) - keepAlive(config) - keepAlive(info) - keepAlive(refs) +func (waf *WafDl) WafInit(ruleset *WafObject, config *WafConfig, info *WafObject) WafHandle { + handle := WafHandle(waf.syscall(waf.init, unsafe.PtrToUintptr(ruleset), unsafe.PtrToUintptr(config), unsafe.PtrToUintptr(info))) + unsafe.KeepAlive(ruleset) + unsafe.KeepAlive(config) + unsafe.KeepAlive(info) return handle } -func (waf *wafDl) wafUpdate(handle wafHandle, ruleset *wafObject, info *wafObject) wafHandle { - newHandle := wafHandle(waf.syscall(waf.update, uintptr(handle), ptrToUintptr(ruleset), ptrToUintptr(info))) - keepAlive(ruleset) - keepAlive(info) +func (waf *WafDl) WafUpdate(handle WafHandle, ruleset *WafObject, info *WafObject) WafHandle { + newHandle := WafHandle(waf.syscall(waf.update, uintptr(handle), unsafe.PtrToUintptr(ruleset), unsafe.PtrToUintptr(info))) + unsafe.KeepAlive(ruleset) + unsafe.KeepAlive(info) return newHandle } -func (waf *wafDl) wafDestroy(handle wafHandle) { +func (waf *WafDl) WafDestroy(handle WafHandle) { waf.syscall(waf.destroy, uintptr(handle)) - keepAlive(handle) + unsafe.KeepAlive(handle) } -// wafKnownAddresses returns static strings so we do not need to free them -func (waf *wafDl) wafKnownAddresses(handle wafHandle) []string { +func (waf *WafDl) wafKnownX(handle WafHandle, symbol uintptr) []string { var nbAddresses uint32 - arrayVoidC := waf.syscall(waf.knownAddresses, uintptr(handle), ptrToUintptr(&nbAddresses)) + arrayVoidC := waf.syscall(symbol, uintptr(handle), unsafe.PtrToUintptr(&nbAddresses)) if arrayVoidC == 0 { return nil } + // These C strings are static strings so we do not need to free them addresses := make([]string, int(nbAddresses)) for i := 0; i < int(nbAddresses); i++ { - addresses[i] = gostring(*castWithOffset[*byte](arrayVoidC, uint64(i))) + addresses[i] = unsafe.Gostring(*unsafe.CastWithOffset[*byte](arrayVoidC, uint64(i))) } - keepAlive(&nbAddresses) - keepAlive(handle) + unsafe.KeepAlive(&nbAddresses) + unsafe.KeepAlive(handle) return addresses } -func (waf *wafDl) wafContextInit(handle wafHandle) wafContext { - ctx := wafContext(waf.syscall(waf.contextInit, uintptr(handle))) - keepAlive(handle) +func (waf *WafDl) WafKnownAddresses(handle WafHandle) []string { + return waf.wafKnownX(handle, waf.knownAddresses) +} + +func (waf *WafDl) WafKnownActions(handle WafHandle) []string { + return waf.wafKnownX(handle, waf.knownActions) +} + +func (waf *WafDl) WafContextInit(handle WafHandle) WafContext { + ctx := WafContext(waf.syscall(waf.contextInit, uintptr(handle))) + unsafe.KeepAlive(handle) return ctx } -func (waf *wafDl) wafContextDestroy(context wafContext) { +func (waf *WafDl) WafContextDestroy(context WafContext) { waf.syscall(waf.contextDestroy, uintptr(context)) - keepAlive(context) + unsafe.KeepAlive(context) } -func (waf *wafDl) wafResultFree(result *wafResult) { - waf.syscall(waf.resultFree, ptrToUintptr(result)) - keepAlive(result) +func (waf *WafDl) WafResultFree(result *WafResult) { + waf.syscall(waf.resultFree, unsafe.PtrToUintptr(result)) + unsafe.KeepAlive(result) } -func (waf *wafDl) wafObjectFree(obj *wafObject) { - waf.syscall(waf.objectFree, ptrToUintptr(obj)) - keepAlive(obj) +func (waf *WafDl) WafObjectFree(obj *WafObject) { + waf.syscall(waf.objectFree, unsafe.PtrToUintptr(obj)) + unsafe.KeepAlive(obj) } -func (waf *wafDl) wafRun(context wafContext, persistentData, ephemeralData *wafObject, result *wafResult, timeout uint64) wafReturnCode { - rc := wafReturnCode(waf.syscall(waf.run, uintptr(context), ptrToUintptr(persistentData), ptrToUintptr(ephemeralData), ptrToUintptr(result), uintptr(timeout))) - keepAlive(context) - keepAlive(persistentData) - keepAlive(ephemeralData) - keepAlive(result) - keepAlive(timeout) +func (waf *WafDl) WafRun(context WafContext, persistentData, ephemeralData *WafObject, result *WafResult, timeout uint64) WafReturnCode { + rc := WafReturnCode(waf.syscall(waf.run, uintptr(context), unsafe.PtrToUintptr(persistentData), unsafe.PtrToUintptr(ephemeralData), unsafe.PtrToUintptr(result), uintptr(timeout))) + unsafe.KeepAlive(context) + unsafe.KeepAlive(persistentData) + unsafe.KeepAlive(ephemeralData) + unsafe.KeepAlive(result) + unsafe.KeepAlive(timeout) return rc } +func (waf *WafDl) Handle() uintptr { + return waf.handle +} + // syscall is the only way to make C calls with this interface. // purego implementation limits the number of arguments to 9, it will panic if more are provided // Note: `purego.SyscallN` has 3 return values: these are the following: @@ -191,7 +196,7 @@ func (waf *wafDl) wafRun(context wafContext, persistentData, ephemeralData *wafO // 1st - The return value is a pointer or a int of any type // 2nd - The return value is a float // 3rd - The value of `errno` at the end of the call -func (waf *wafDl) syscall(fn uintptr, args ...uintptr) uintptr { +func (waf *WafDl) syscall(fn uintptr, args ...uintptr) uintptr { ret, _, _ := purego.SyscallN(fn, args...) return ret } @@ -211,6 +216,9 @@ func resolveWafSymbols(handle uintptr) (symbols wafSymbols, err error) { if symbols.knownAddresses, err = purego.Dlsym(handle, "ddwaf_known_addresses"); err != nil { return } + if symbols.knownActions, err = purego.Dlsym(handle, "ddwaf_known_actions"); err != nil { + return + } if symbols.getVersion, err = purego.Dlsym(handle, "ddwaf_get_version"); err != nil { return } diff --git a/vendor/github.com/DataDog/go-libddwaf/v3/internal/bindings/waf_dl_unsupported.go b/vendor/github.com/DataDog/go-libddwaf/v3/internal/bindings/waf_dl_unsupported.go new file mode 100644 index 000000000..9745bef1b --- /dev/null +++ b/vendor/github.com/DataDog/go-libddwaf/v3/internal/bindings/waf_dl_unsupported.go @@ -0,0 +1,55 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2016-present Datadog, Inc. + +// Build when the target OS or architecture are not supported +//go:build (!linux && !darwin) || (!amd64 && !arm64) || go1.24 || datadog.no_waf || (!cgo && !appsec) + +package bindings + +type WafDl struct{} + +func NewWafDl() (dl *WafDl, err error) { + return nil, nil +} + +func (waf *WafDl) WafGetVersion() string { + return "" +} + +func (waf *WafDl) WafInit(obj *WafObject, config *WafConfig, info *WafObject) WafHandle { + return 0 +} + +func (waf *WafDl) WafUpdate(handle WafHandle, ruleset *WafObject, info *WafObject) WafHandle { + return 0 +} + +func (waf *WafDl) WafDestroy(handle WafHandle) { +} + +func (waf *WafDl) WafKnownAddresses(handle WafHandle) []string { + return nil +} + +func (waf *WafDl) WafKnownActions(handle WafHandle) []string { + return nil +} + +func (waf *WafDl) WafContextInit(handle WafHandle) WafContext { + return 0 +} + +func (waf *WafDl) WafContextDestroy(context WafContext) { +} + +func (waf *WafDl) WafResultFree(result *WafResult) { +} + +func (waf *WafDl) WafObjectFree(obj *WafObject) { +} + +func (waf *WafDl) WafRun(context WafContext, persistentData, ephemeralData *WafObject, result *WafResult, timeout uint64) WafReturnCode { + return WafErrInternal +} diff --git a/vendor/github.com/DataDog/go-libddwaf/v3/internal/lib/.version b/vendor/github.com/DataDog/go-libddwaf/v3/internal/lib/.version new file mode 100644 index 000000000..7df3a13a6 --- /dev/null +++ b/vendor/github.com/DataDog/go-libddwaf/v3/internal/lib/.version @@ -0,0 +1 @@ +1.19.1 \ No newline at end of file diff --git a/vendor/github.com/DataDog/go-libddwaf/v2/internal/lib/README.md b/vendor/github.com/DataDog/go-libddwaf/v3/internal/lib/README.md similarity index 100% rename from vendor/github.com/DataDog/go-libddwaf/v2/internal/lib/README.md rename to vendor/github.com/DataDog/go-libddwaf/v3/internal/lib/README.md diff --git a/vendor/github.com/DataDog/go-libddwaf/v2/internal/lib/doc.go b/vendor/github.com/DataDog/go-libddwaf/v3/internal/lib/doc.go similarity index 100% rename from vendor/github.com/DataDog/go-libddwaf/v2/internal/lib/doc.go rename to vendor/github.com/DataDog/go-libddwaf/v3/internal/lib/doc.go diff --git a/vendor/github.com/DataDog/go-libddwaf/v3/internal/lib/dump_waf_darwin.go b/vendor/github.com/DataDog/go-libddwaf/v3/internal/lib/dump_waf_darwin.go new file mode 100644 index 000000000..b0ec8e102 --- /dev/null +++ b/vendor/github.com/DataDog/go-libddwaf/v3/internal/lib/dump_waf_darwin.go @@ -0,0 +1,57 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2016-present Datadog, Inc. + +//go:build darwin && (amd64 || arm64) && !go1.24 && !datadog.no_waf && (cgo || appsec) + +package lib + +import ( + "bytes" + "compress/gzip" + _ "embed" + "errors" + "fmt" + "io" + "os" +) + +// DumpEmbeddedWAF for darwin platform. +// DumpEmbeddedWAF creates a temporary file with the embedded WAF library content and returns the path to the file, +// a closer function and an error. This is the only way to make all implementations of DumpEmbeddedWAF consistent +// across all platforms. +func DumpEmbeddedWAF() (path string, closer func() error, err error) { + file, err := os.CreateTemp("", "libddwaf-*.dylib") + if err != nil { + return "", nil, fmt.Errorf("error creating temp file: %w", err) + } + + defer func() { + if err != nil { + if closeErr := file.Close(); closeErr != nil { + err = errors.Join(err, fmt.Errorf("error closing file: %w", closeErr)) + } + if rmErr := os.Remove(file.Name()); rmErr != nil { + err = errors.Join(err, fmt.Errorf("error removing file: %w", rmErr)) + } + } + }() + + gr, err := gzip.NewReader(bytes.NewReader(libddwaf)) + if err != nil { + return "", nil, fmt.Errorf("error creating gzip reader: %w", err) + } + + if _, err := io.Copy(file, gr); err != nil { + return "", nil, fmt.Errorf("error copying gzip content to file: %w", err) + } + + if err := gr.Close(); err != nil { + return "", nil, fmt.Errorf("error closing gzip reader: %w", err) + } + + return file.Name(), func() error { + return errors.Join(file.Close(), os.Remove(file.Name())) + }, nil +} diff --git a/vendor/github.com/DataDog/go-libddwaf/v3/internal/lib/dump_waf_linux.go b/vendor/github.com/DataDog/go-libddwaf/v3/internal/lib/dump_waf_linux.go new file mode 100644 index 000000000..c2767fba2 --- /dev/null +++ b/vendor/github.com/DataDog/go-libddwaf/v3/internal/lib/dump_waf_linux.go @@ -0,0 +1,58 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2016-present Datadog, Inc. + +//go:build linux && (amd64 || arm64) && !go1.24 && !datadog.no_waf && (cgo || appsec) + +package lib + +import ( + "bytes" + "compress/gzip" + "errors" + "fmt" + "io" + "os" + + "golang.org/x/sys/unix" +) + +// DumpEmbeddedWAF for linux systems. +// It creates a memfd and writes the embedded WAF library to it. Then it returns the path the /proc/self/fd/ path +// to the file. This trick makes us able to load the library without having to write it to disk. +// Hence, making go-libddwaf work on full read-only filesystems. +func DumpEmbeddedWAF() (path string, closer func() error, err error) { + fd, err := unix.MemfdCreate("libddwaf", 0) + if err != nil { + return "", nil, fmt.Errorf("error creating memfd: %w", err) + } + + file := os.NewFile(uintptr(fd), fmt.Sprintf("/proc/self/fd/%d", fd)) + if file == nil { + return "", nil, errors.New("error creating file from fd") + } + + defer func() { + if file != nil && err != nil { + if closeErr := file.Close(); closeErr != nil { + err = errors.Join(err, fmt.Errorf("error closing file: %w", closeErr)) + } + } + }() + + gr, err := gzip.NewReader(bytes.NewReader(libddwaf)) + if err != nil { + return "", nil, fmt.Errorf("error creating gzip reader: %w", err) + } + + if _, err := io.Copy(file, gr); err != nil { + return "", nil, fmt.Errorf("error copying gzip content to memfd: %w", err) + } + + if err := gr.Close(); err != nil { + return "", nil, fmt.Errorf("error closing gzip reader: %w", err) + } + + return file.Name(), file.Close, nil +} diff --git a/vendor/github.com/DataDog/go-libddwaf/v2/internal/lib/lib_darwin_amd64.go b/vendor/github.com/DataDog/go-libddwaf/v3/internal/lib/lib_darwin_amd64.go similarity index 71% rename from vendor/github.com/DataDog/go-libddwaf/v2/internal/lib/lib_darwin_amd64.go rename to vendor/github.com/DataDog/go-libddwaf/v3/internal/lib/lib_darwin_amd64.go index 8106353c5..168685692 100644 --- a/vendor/github.com/DataDog/go-libddwaf/v2/internal/lib/lib_darwin_amd64.go +++ b/vendor/github.com/DataDog/go-libddwaf/v3/internal/lib/lib_darwin_amd64.go @@ -3,7 +3,7 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2016-present Datadog, Inc. -//go:build darwin && amd64 && !go1.23 && !datadog.no_waf && (cgo || appsec) +//go:build darwin && amd64 && !go1.24 && !datadog.no_waf && (cgo || appsec) package lib @@ -11,7 +11,5 @@ package lib import _ "embed" // Needed for go:embed -//go:embed libddwaf-darwin-amd64.dylib +//go:embed libddwaf-darwin-amd64.dylib.gz var libddwaf []byte - -const embedNamePattern = "libddwaf-*.dylib" diff --git a/vendor/github.com/DataDog/go-libddwaf/v2/internal/lib/lib_darwin_arm64.go b/vendor/github.com/DataDog/go-libddwaf/v3/internal/lib/lib_darwin_arm64.go similarity index 71% rename from vendor/github.com/DataDog/go-libddwaf/v2/internal/lib/lib_darwin_arm64.go rename to vendor/github.com/DataDog/go-libddwaf/v3/internal/lib/lib_darwin_arm64.go index c9d286308..eca7b6552 100644 --- a/vendor/github.com/DataDog/go-libddwaf/v2/internal/lib/lib_darwin_arm64.go +++ b/vendor/github.com/DataDog/go-libddwaf/v3/internal/lib/lib_darwin_arm64.go @@ -3,7 +3,7 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2016-present Datadog, Inc. -//go:build darwin && arm64 && !go1.23 && !datadog.no_waf && (cgo || appsec) +//go:build darwin && arm64 && !go1.24 && !datadog.no_waf && (cgo || appsec) package lib @@ -11,7 +11,5 @@ package lib import _ "embed" // Needed for go:embed -//go:embed libddwaf-darwin-arm64.dylib +//go:embed libddwaf-darwin-arm64.dylib.gz var libddwaf []byte - -const embedNamePattern = "libddwaf-*.dylib" diff --git a/vendor/github.com/DataDog/go-libddwaf/v2/internal/lib/lib_linux_amd64.go b/vendor/github.com/DataDog/go-libddwaf/v3/internal/lib/lib_linux_amd64.go similarity index 72% rename from vendor/github.com/DataDog/go-libddwaf/v2/internal/lib/lib_linux_amd64.go rename to vendor/github.com/DataDog/go-libddwaf/v3/internal/lib/lib_linux_amd64.go index ad706c068..97d24c621 100644 --- a/vendor/github.com/DataDog/go-libddwaf/v2/internal/lib/lib_linux_amd64.go +++ b/vendor/github.com/DataDog/go-libddwaf/v3/internal/lib/lib_linux_amd64.go @@ -3,7 +3,7 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2016-present Datadog, Inc. -//go:build linux && amd64 && !go1.23 && !datadog.no_waf && (cgo || appsec) +//go:build linux && amd64 && !go1.24 && !datadog.no_waf && (cgo || appsec) package lib @@ -11,7 +11,5 @@ package lib import _ "embed" // Needed for go:embed -//go:embed libddwaf-linux-amd64.so +//go:embed libddwaf-linux-amd64.so.gz var libddwaf []byte - -const embedNamePattern = "libddwaf-*.so" diff --git a/vendor/github.com/DataDog/go-libddwaf/v2/internal/lib/lib_linux_arm64.go b/vendor/github.com/DataDog/go-libddwaf/v3/internal/lib/lib_linux_arm64.go similarity index 72% rename from vendor/github.com/DataDog/go-libddwaf/v2/internal/lib/lib_linux_arm64.go rename to vendor/github.com/DataDog/go-libddwaf/v3/internal/lib/lib_linux_arm64.go index 7aa8c1bdc..1f2e50af8 100644 --- a/vendor/github.com/DataDog/go-libddwaf/v2/internal/lib/lib_linux_arm64.go +++ b/vendor/github.com/DataDog/go-libddwaf/v3/internal/lib/lib_linux_arm64.go @@ -3,7 +3,7 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2016-present Datadog, Inc. -//go:build linux && arm64 && !go1.23 && !datadog.no_waf && (cgo || appsec) +//go:build linux && arm64 && !go1.24 && !datadog.no_waf && (cgo || appsec) package lib @@ -11,7 +11,5 @@ package lib import _ "embed" // Needed for go:embed -//go:embed libddwaf-linux-arm64.so +//go:embed libddwaf-linux-arm64.so.gz var libddwaf []byte - -const embedNamePattern = "libddwaf-*.so" diff --git a/vendor/github.com/DataDog/go-libddwaf/v3/internal/lib/libddwaf-darwin-amd64.dylib.gz b/vendor/github.com/DataDog/go-libddwaf/v3/internal/lib/libddwaf-darwin-amd64.dylib.gz new file mode 100644 index 0000000000000000000000000000000000000000..c2f1a35127b8d0f565b2471450213567c02bddc0 GIT binary patch literal 682821 zcmV*AKySYviwFP!00000|LpwbVRxdBn@r>6;K?A8&*>&(MS?O z)Boq5Th(2?#F2U5dEWo`_gK#Z>8iSQmvhhZIp=O~9sj&H7a<`NA(VplvgVtG zYOS}67FBzF*H-tL-{MDjJ_j=6_k!hnn~`5m?E4#UyV1Mo_N7a!mw2mF^DF%&&(CGK z&#>f|L>!ea83ZcU`r2#f`V!&`15&9pd@@X_=64Z(hlHFIwcgZRL%(UBBqY+m_y*Cckqp z=M)N$i{F1={TSbAkWYEpoU%pJE}u1<=VtO-(D*v(KGXP@Ves;zMK|2;O{i!3{M!4W zSbmw7^o&3LoJhB%eof4;of!E&!|TKDzpr0eJNF4@K9(1y!;Qb`@6C2*$LewYHQsBI z+nJhQo8><9d+N1lk$2gOCD&ZP=+0|aRHwK`_1CYwX6gCYufFBRYY{@@5vp|< z`L_KOp$m=sw)cmlRR_6Tu)NUDQ&3A5LfUB~P-BsR1|WngEp1`{hGZc$Gz+0d)c3V` z=m_*-a^n#~BaCv+uK0SuWLmOv%bd?w-2UXOM=mgE2%qHUAtdC(Z=j_xKJy$yZp|yt z(te;&Q9(BQdaSQ{1#3O~ciosV=a(21VCg4Y)1$Lf($8L9?Ok%~`Ip6rh7dZ-C>Otc z3UcKmG}^dd)_MwB|9y(;$Lq)I$Lq)I$Lq)I$Lq)I$Lq)I$Lq)I$Lq)I$Lq)I$Lq)I z|3g<5CZCqgE1O$ZRW@ffzV`?g5W=KWBE6V&W3mU6omx*JLV=)IcSR0DGI>GkjYb=? zFa=34&K`%=nOIh*EtgeV%RW)pjK<{dA{!=IMKbBudgih0YBtEEOUt_oA(_@R zDS@c>IoukIMx)UVNeoT5;Xu&$dx_@CBpR)B$Rw&QzRQmEhcI2xCe!C^ta8-v5Li`~ zG-2XdFS%R9x^{R_)2NRUN0zfBz9x3dzHeKHkmPS!CQtFL7wcXW5R%k8i)9kUv}%L4 zbs^NGQE`9f-65$JHcUJXGVz7=VN1^!NAhu-dWp2k?sl2_!rniX)vgtgx4%TEyUHH0 zufw*o+O;ku)-@u86neW0tD86UMx&Ve8nii|A|%l#HgFPp7b@xt?6*V%4eXJ7pD!Pi zgZkMrX_wp|c%8DkSnDd)1n(D^uIkZ_uC^onV{s&s=v3BRi9Er+)Ap{mBXM4^OdOaa zwN^l2meoxx4zQBT#DM`Qkp>!jqfvR1U~mp zlGFtbg|2i->e^CF4ru;ISj~gJ13*E>O9!;E4>J<_iZN-`+^g(J57kTbavKip@SZJ> zgz-B}!kG5MfgQeMtm7iD^hTp`axSfx=yZqdp3L5fb-!bk^tU>!^roV$u6AHr=D=>7 zuOqUiHyV}ca~;que-9L4bp5Ah*B8e#Na+9jzPJCc?yLVtSn9(nYTFcR$@2Cz)~>Q4?*N%}%cNK9tYTfaq)7>U;{B^dF_ssBX8ff@*~g!O zYWz&|`0PmccX9oVX-%70x600nx<8n~2o+cyjYhG5%f1X&&$=8YDRfI)215D}YXcA_ z2eqI1?1<^(X)-yX&`V`nU91GUyq{QVQ2~|MEzumAbVD7wwUF12^eqPW$)qFV83ua3 z4Y%IkW(?6_`pYn@P+&KvPp~?9tFbyGO4|JGnb`kLW_4D{4t*N-fAnq14nu!mh+DJX zo{qs5h^nluZalU|%66g}^-phuxZTxLJd#i3Pj

X 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%0ACF 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

X!&{sd`EA*_4cPx||Kb7DsW<9@bLXo06na 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 z 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ⅈA^R$)`V&t88==3`7*i)M$tm@fUlBQNWGp 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�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

uwgfM+1B|LV@0K$L#K>ei(xlvgPga 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ӌ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 ^n&;65l?n&MU1gj0ag6IC} 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%0DADdQ1AOz<(kf9ZlSR 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

XvN_iQmdA5+-2Zii4uq$SaabxSo~Agce@Y2r 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

_auh>)*y+gB8|7-G1B4vVQx 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 CGR?{W literal 0 HcmV?d00001 diff --git a/vendor/github.com/DataDog/go-libddwaf/v3/internal/lib/libddwaf-linux-amd64.so.gz b/vendor/github.com/DataDog/go-libddwaf/v3/internal/lib/libddwaf-linux-amd64.so.gz new file mode 100644 index 0000000000000000000000000000000000000000..d858a354a8a4cea65378d00a4d0c26b6d13d745f GIT binary patch literal 862545 zcmbTdX;>54);4?`X$Ro6fQT}P7@1@e6_JprsI;LmA}T6KL>kdn5=fdM5{R|}3P_ky zfkZ?^o5`sOkw`=Y5~etUN+duEf?z-jA(WZE9Z#R8uluS zw4eU<<4=?OX;Iy(gP(NNb3SG-Up!~=rTj3Pz<*uH4One+BG+N{@%J0opL^5Sx7nCD zVK)A>Y}&3qf@FkPPkjmSexAWRJ@ z)k4k06jzuaZ5rrs7rRr2e>=IX%LC$j^&AT~^HH;z(Kn~*f%$pQ#T_* zOZPrhYc!;}>Y6{VAvNg_&8o&#S5?KEF&Kxj`=$8%iQisSBn_7st3Jn;9}B7Cea4@( z_@=Dv*7PQ}em}E{wyIhFX#JTxjrs@M=!8kX_J^A{%^pc5+?;hX;vJgQ98{icCIu+X zn=Sll_XbIJ>I;KoRiQJwhOCm=y{Ys)lL|e8QQk??0RkOc0WBt$%t3S9MqAh8T^`qgN&9TW|BVOQS@*u-b{dln5h<5aDmCnp9^FXN_K~rWgoFo=EvDPu%cgrTO(e(cw$*5o0&|-T zzAmL%&sv_s|1Q1n2_v6l+{ed~h6-*fC6R?6U4IT{y-x@lf1VieC01vacVGOM!Fa5l z(l5?TeGOX8@l%N#6Dfz-1bunG&p_)<&+Ti!)km62?qV-U)c(1e#i9?+XN3;4HzU_` zP4p8ChxB)tnO*84ecy@gjsNg?LOt8tKCDqE z*L1}v7I)0cAwH3*q>26N(;rYyomiJT`g5l?{i1`{)B{(>if3VEK*Nz6o5N~aawm>@ zcRl@MQot+vqgURy<=fo})tT=Yr>D`4pS`(X2S)AJsfW&b$Y-5;#K=tp9%ZQZLCw%| z*593utEwiE%+#lBarnmI!wK3`K7ZA)L-=gp#Odxx@s|r1N`lYK6qO9TitL#;ulvu21y7NX zGk=^qe#%dL{~h+d+eb;dp6*eK&hDteT$kB;xf zPdp!BE_k%$?im?IstM4KZ%XJ|HJ)=PBVAAb+tud%*Ltx$`rDOX0w32JgtkV`oFbIa z|EN4>l_2RfH8HC_ckX*~icU())(!EG>8B#OAC?q7_+??1VC3bF*3YYaPAgA+W26U& zU5^*LY`A=}$E@vnnJmUZ0e_r)?*nNq2>+gXZnL@hR zUz2d!$rN9+Rc=d$(__zWe=k82N)s-IAGWf3`bb9#gxT85Io`!T+&oa1m73i8oql6u z_-}s@#a|DncmBeIb>0ztzjC8ZDV@v-yA5(v-&fa50 z)R6URpv1Lx?h)rdc8foTid>I(ns^)yjSuWUtgWcIjjl)i1~d&SgbPi}p#i7j!B{Q~K_-HsUOK7G+EZDDJvY!y({=kC4- zKd%OrzP|RcugDogND;QD?TquiH+m^{j#e56z}RwE9hWct|-{_ zTzY#`1pF^^Ydm_zxm3|s`!A%UlS`?F%%Pa)6p?uxlbaYbqDM6d?pHAl&SjzJIYoI! z7NDbvBVpA#<5|*vqb@1;Wre8b#7K0PR6G#lB`CQU=M%+hZMrjH-LbhKMW=02mKk3- zkTc5b90JqkGP1o1i`b#iy@;NPw$O+!8w=^VeVE1!nIR`l_Knxc2{RPhF(v9XLUe(* zUPgA{fOxnl4TofBKdOKZtrJ?g;RRJ~imH^}O{kP7gSyRyIHH3iFKnbC+pAEqswwVJ zTWqfAHoYkDl2XohIO--nnd9+3qo>n-ts&ly`Bx#uXDTtv>khHYGSH2|F4~U~D)J^P zp+l?b^EpO&q9C$GZx}iLP#uAxSW**7{AxE5JMr=iWD-{_N^;8;-2l^}+z5gy--d;p z1vp|>eZA@iZPw6ZcSC2dL93=kP!O~{AD^um{eGWzbaFlN$t`Ib62yM8`u6AkhMf)L z_@?jekS1>RdV(dr%sjs)3%|=#7he9ocMWf}|79;!u3T4H-X!ymUnBoRVN|}F4sU;J zU`;^g!`7^guHQBy>+#!?JCVjz@iza zH!Y`{$vFG*fo%ANIhsza--cboU4ujYuK zEP$o(7N^&cQ3vS={3#R9R4&hT%2aI7WNIMabUI9lQXk^i>_l!1>caj)FLf$gkRwm( zZKQXMUC0>hPB_UBg$HAI3aVUpFdj&roD_#Q=(Xg*i~5|}tS4LvI{pyhgPv59Fg$iV zpZlk*DBDXL*Zr9tn1zl$G=f6u1PH1sbLF`rI~?&KoCqEAC!fh|9oJ_U;`AJv6PkN* z#5r>LmzN$my>8X8XpOwE-Fw1Ky1ZUoROlPLn>eZH@#P%<(ZnI*g$u8p+o!06u~Nf6+nyS#PRySpnd+_>Nqb!mB78|q7cl~kR2FkYhlBQ z&J|VaJW)}g<Yn!m=0nIe)K1k6Zm53!%>O2ch94mqL9U$A= z4jn_WA7&SNV?q_q?9}YQt7v$2OI5a)*W{f+U`;H_EO=;~-i7QyZ(EY*sV)cjraRjP z3E?};fP*d6IlWhO@}iRlZJXbS5}|xccH+h81@)Eo<{PE?0c{>Q;sO+V4RW1dbsJCw zDYVz0eAg!UAomV*$XdU;<;f1fN>KOyHU*9tfnuLmI`OMYfoksdK6;;lxm{^*$TnhN zf9rB+Ow{c*(zhK;P3hp2<-sP^gl>WUbxL~{J2OyiNg*zP7uKfX^ia*mn%i+ib84i6 z_Nfn|*f;h!XmvwAL&mr^Y1I<}Lrp8#I6brGs+3N1>ieR=T=aJx@W6+_1cj6|`ym4^ z;fOW%Y?s3>=5FF?V!4QJRdd{<9Lfw3`EdaPe&d;sE&jh?y@p(2%h|*a^>GG@Ihv|S zW#@_J!f$;K2iUkD_UYj4%D>j`U2u((=HLQYPn<3q1Q&mx+QF~eC^g(rNLCD~S5Zev z+Fxt|Vk@Kh34qXsvw44t+Hgc8Sg*DMr?;tjELBT&B4*(I>V7y9uw50j{6Dbvev(jb z7O9c_Od-0!=vtX~F3`)O<{ZW~icgjf-@0>%)Vvh|-+u7!;0)E7gGHX`>a?8LuGP^p z>XP2-Y_B6x_(_0*yxuAOO8YuATxrkQ^j~IWDSwB$50S?*%PpGg5)K>*urWV~p1BK< zEkdljji6U6y9JCJ6d%m*T@KBPylA*|ShN9Z*P`1>F6N(kACqgkIMvw5$(F-`7D4`p z{x`TW5#Ay?;D)T$Lalxxn&&kG_#Ddl9uEfp^04~U4N98rknD~-JMK+U;GgKLqHJFZ z@ie@l*3~!cSV`R8Ni>@<&dah^Cq*Y^dugSY8=I$>i*7+~tJ&|t!63BYthKp6P)@lap7KLEgG2xmaD@SY zXFp^Hs0WZ7%@$Y@Cr{A(ekRw{E;YcY#+LI=P^_ah-cxp*zjI+N^#~kRv+4}SdA6Kg z<`XmPYfBmSV~d+3nk5Y2^)lazWt(u+)8LT%gy4s)^Pp;RNB^)Ct8Uk`ofmLipXbjtXa>%3P)^+o*^@Q1MPC| zdEc*&+X2Q7>2j#f#s3)lk~`ZFvB(VkzKB9R0xzzm;Pj}?X3a}*#9du7ze@XD(;&bK z`}_RK6*ioM0@hCACKP)i^~;|0KvYWpV8fu+RuzgBS{v)m0i2D$(eBOKC|w@^8gO<) zb61^a=C(U~Ep<`vJ!>sHm^42UC2};onQ@D?rsFNBx|!=_$H@ac2X7?X+j9=`J>FN_ zxxY26vF`)Mn(fBYazkSP`HcP0JQO=4yKwpd+c+x_vi%3#<^O;ie;t5Z!FN#QKCF&w zD+)Yh%aW+twj$s@J*1QW|7Yy%a%PiOdR;@T)+ak`#Rte|Y&i(zw1!=q9hibvZETUf z`G>U2J2@YqE^?(k6L15*ur+YMEo)Fa_-P8!1on+-RI$M=LxTT>Y!TB)i>f$avSqY` zf+{W3X;%Kj+rr}_JNL&%`i2uWoFl?N;?IlL2yMnv!#g<5x$ulDK%Ed6Yo>8#AZ+pv zw!!y{n<=SMj*6_g%0-rGWe&6y2DAiMX9pe;bXsYaX!Z1tFI)b9GBV0j24isWmzLvYYqeS#G*C~(k&J99NR+{;o$5v%=Pr|xfOXChrno3vme6|Ij4Mnp% zsLT1qZeKZgTf%3}M8LJhknUOI zJX2h1eQH6T2o3i;XhHZFj<~6ec1%!J0(GzD=>uC5eS`#I|FC!1Nyd6t>2ef%9vIqo zY%v+({yU(}I*#{nZ}3S#-s(AIA17C7KI(swH)Q(Nz2Y|155SiPGqVGC394`n?bUUf zJ5cv(hG$w-1@v;i2$Y}x!>Xp0;hoac&=CqU@(6fW;SI_o0q-JE6X3b*g8Rj5@Z5{k zYoerZ{=B$+^pxW`FG}w#nxhZ=@?v03D0X&sp--aa|3Dm50el+3c>heh%8jh>)Gm{T zV%P4+>?4n9F%hk(;yb`a?(7v*^WGVX7KxVz1ybPk_>_rIG`76bo%ksrmQV zZzyfp@DI>=^R@2cC^Tsd{2=YW0gAB=3lB(W`;h=H2&(SnvI)-8<@82C;z~y-p9T(Y zaMNWSONLD!rb-QkKgd>EyJwbAXk+7Um?y&FsM;73Fdy%NHj3N?^V75-02xLqJ6A-5 zJ5Gjx@F8WJpsF;N9SnGg`U<#p+SsQkjcgZ%7zNL*HE_Bit$@;oY5Q@=MmC|3ZY95y z#0eAl7p5>JFyM|?MTMo%p?zfgY}R=&BQXr#T>{s~&h>49O&KMdLVg`N*Z+Mwmp zv1@^6IS;E31E=v1v2(!}skH9}k(vmOJ9|BKL9aV1g*%urs13q65us>%_d2k$GH&?~ zf0#{Q!g-e~S_wTc(u(uH!8qrU*R?=zLE};2F&;h-!aR9i6nHiXxOt@x-=P7VWOFac z-Y%x-oo;qb4d%!L2LFTlYUi5P-&6nVs*X#Y*~{6Kf|m&Z z_}PIsp>99&qu|jQDWG@Mf9O2|9<2^hNSv-u?Xh7(=OFbe4&(b9sJmc?kPD*0_8}ll zEr&Q=r%?FiUoI#}I3fyOUV99c@^FwjXoO_&WO2E6KRht?7 zt$hXCsj!EXRnUp-G-5nG+ts;_Eq@VrQta{VMfxbqzp-~dh4 z?FC8ic0u{wxIKbSRIFNO>^Jy0>!s)avVfoev4Fh)BZ%p4Ba+s+FarPq=KYA#{bKwd9{eeo`*_ zf-)4cty85Uvn@vWOzA#+HkW#M#1`&f4Wc|xLQ}$KGJf30M%8AoBInK+8#>vk?6MRo zC(slR-W9-ayLjkoLW?VMYy&e-5@^jh9<(W!b_0iTK6puQ`@=PFT;K$*Mn{-W$+4bvT&@2amu2a3VptG=Htt7}?_Uq$L*{@{JueqXdi{5t;Jvy7IcK*^&8Qxho~!d33Kg)Oo(!%?qS zYuraq+evQkN_1*t3(7v3m6?xC6X`nBI|*(*IjiLliq|rN8I!xmpFP5Py2s=SbHa(w zl)D{eHj#=4$JUZg)bDhZedVKC7t7^#LE!@bugUxIIilUja<ECC0AxxcH(8KZ6EVn2iyFtxh;?JBV_{^SxJ!FgNazXq1uFP<|6(q<#E<=$t z_UBYGqIAfNzgy0yo(Oh$8iElYgOM%4VZ`zvH-T^`vY2{a_Sb&=RpsKh{??4D=d%Y! zNm;!I)A8_p;8RU)WM48hy0XWIuGjFg4h|QULb`7a0>k=hd>c%MB+x_NT98rRJ2*UL zrN?A8yJk18)6*jRL+zPz8acd__QP4Z^VSGNGS>D@V=UI0+)IUW!x=)r1VaezFY$N#$DlF zQXV5~8t>Dti=J%!11~6luG)pzai-q9JQE}odeu-AH9tLVROQJRxeE!Gh62CvmOky2 z%#p0^H&w65pUCvC(f@R=y~yhln9YxDVQ$4HK8sryI}in*SRlzqrzMuv6~8Cl7`qUj zn;0f2v|(B4_fyLVdQ_v}xU?Sq6>P}pY&}G_s8r@tJ%?>oe{sW@;=dpr{B^XN-J)ua zu5CnkSEK)Y-If1(FX41}VXHp6zew0vH*~JQyLV%C|IhF`G>++E3?_>*Z*icSnM+kC z5`8k`zpiCVX&p__9JH#ITAX8P@hqw%yItB~itMqO;6|9I>>{7`zAjoE`AI5@6xovs zTfL?ursD2K5ets14{#e>7xY0z0}f;=qdD9gsojsiX%^QNK%^M@tbx*e^k)**Tlk|}CfHWhLli(V5mGusQ>I>YEGB^XyCc&9OMW?&9 zfaTrw8Js)eB_0#1{} zcie~PGo}lfQhU()FZgC>dnay8rSr~oxlUHQ3)dESEBwKQU$qyS94CzInejbE;Y>x+ z%ocEYeI_dvorYtgVmPEdYJ<0ur)SJH?_xV8yz0k~wyOi)ih(8CPR~N}5~fxqZ{JuF zQqNV&JEnK`X~Sr`!Ss8a=OXeEQhA>%+tpX?J}R`C4$nJBhTd#mIwr86HslY*8H!z5 zv1RfOX|aNdaP4z+>R4Z*5Z=Jlf`XKu_piF1yzWYV-F4@6*K$s*D@K~F_`113yK?_(69)`56-o zBeNF+J_2j{6Sr_Q3&&G(dIBWikQQv8Nw_>opowY01$^V1wCj|nm|geEaSisP_jn}C z#0?tv{-()`-ytcv{Z^7qxO$GOpF6gm z^SGu_ZP}tPT`eEmLgx_5(^EG04MNL7i3L=Us6sP%tzv_5$6V$r&cI{C!e zqCk{XAedL@J+5^5wwNtVepvy%!X^b<$<@XZoS;M?Yn;km-ZLeCnLw02z1CXisY@dc z6&Xt?_S7kis6cV~BL!PsXmMS7-G=&`Rk~Xl*B3KyNMd0t$y5fLq-g*5UX+;v;cYY5 zY!Nvo{$|c9V{}N~sQ741yT$d^a_>H_f#j-O;RFO_$8DL`czoN+mJ-vw$QtvGP@EoS zLhb~d5~tU>kN-(?oSPNDg4NynSlu|Ao+)+KD}|bMzH<6Q!?;<5)e@QZKV5go-@^Vs z$3BY1&_NT@7yXb#iTe2`M&9IZ=ID8h2+$%!b8i`;(t3Wsn6URMh?W)RFP>tW=D-}i(4rp%ud z2M=&}jz0%Q$<%nTv6DoTP0j6^Gjt}k2kXKRE~E-ua_Y%LlJ{${KMnP^MSTH2+)VYj zcgg#Vgx@h4Gv&jQ6`Hp+Qv=owM!^2bx8OYc5V|yO#vkBOdk2E=Y;E`Be!Yj(84A3k zf<)lFSu)dK_m(f)G!S#l-BEX_ZeyP0^&0srCvBugxf$mjb;g&i^Oe66aB#JY)WTmB z9Ex#_A{)1&I4!iG*CO-l;=07M(w=LKv`65=;xiqsWpyn@^gU4^4xK90#@9o22l6EQ z{b6mjCc`I3>9obMfgCh_eXHEeN?T2l*I7+bhxOeI?ABoZ@Uq#00eHQ}1u8W!ner(@eSW;HzJa@ z%~}@3xF zryGEj^9?S311|m{w0TqrSRil45Y$Z_vlZS%cQtz_b36T5UkyXC2p5lrw~pS6^cX@` zBfcy2H^G1N3U(wu=m-EI)SdnKG-ZfM3eGd4jCo#Z@b-=0=#|P|S=3qYo`Ws2Cv9Bs zz86u9nlr@kKWVML517^k6XoTCsrOx#XPDs+aUK*1^YMDX$IqE`BiVWz+4`)W`?Bob z^0O{#c8BazJmjYZazc7^r*Y*D>Ll@%4lw`RKrLuOa6cPfNJ-Yg@wVc4 zmD3%n)XMPjfLvwGNWfW73h!(ga|?1VWe~H9dZs?oV;A#ENCPT1Fof7UDclC1!wuWapQYhcj#PtQ5My>!v_;*ERC%OKQ4iiLzY~|>Ii(b>)-2BO@psQ~ zfFu0+q@w#~kqYZey=G;_-Sfj}dz}jycIN(~L+I+b6Mwp=tVLooy;8Xwex9cd_aQQ7i`bK>UuzG&k~tFv{xKt)`kc6XiKRT< zYWkEz{fs6l%BL?gs+|)OR4ZV`pB@Bzx!i=l+mk#qxL5wuryK8Oq!QXC7&MHY! zx2Wjcy5grH)B@4P0)fGlmwb!G7xso%X!;>RtjAe$fTrR8-qozjux^)b?~g3-%H3Ah zsRri4BI{ZYnkeenqjlG7Vzc%Pj~z=#UyUdfVKD10tnrNokRIAyfaaC0yDnvaTN?(F z-W|jbdxjAQd~i!`lRMflBWEskVend~=RP=IP#Gbtj9`wKjRfra9B`F;RkoG-$fWjB zqhwAWBvBk5aVR4+ysoKzU2~pR(KLzpd=B_cMZ}-*z%iq0S87&S#rALJR8~mF3Ke;W z#iAPM`*30ze_}iDwf4%;_Xow27_a~qcrY_~4R>3gXx+Cp9CpMAs;`Et*^}7zb6m|~ zL8Fy;!H_*bxHiF{S%CzjAZDWxDT=Psr2Y;qO3$gy4!;R~@PpHLo)Uq%gD0BnQ1XG8 zohIxcMtbk%4MeN9Iuzk@(VL&adgI@BJqQPiHE2B{0%=(i_?nYw!Ul_lx3xsPKW(}e{5^x&a z_5|k{23y=RX87lJMsScR>x6mA9(YZyKcwCpqId&!IhKU;kHy8Lx=Tgi9&O@)$QdsZKH3gP9X>E> zn?*O8u7h6dX}5du2LYSpD)Ob=t`F;)3&UYKc2Zq%uWu&U?p?do)gyOlz@w%y)X>v%K9J>pndzqMV#Z={izIaEEmn&nfS~oiF`HZ8LdE zv{W!xz~sYhMmgl~2j8ID+)h0gUi5-{mb}cLBm%|Oaf{B;Lb0*@w4&w`z z&AgO8OGd=y=;z63=7YVfg~b=6=Td(*w<0Kl-KcXUmfM+)G1;OgMv{Ed#d417Yx-;E zdL-`@!;6U5WiJsi113!`^lBC|!)>SIAm7}Y$gYYVHDu!Z>MZtyV^Z}Ap4M(KY@MlJ z3wt%LO5#$vvHA7itF3X&ZO97FJa+jF>4hyw#D>IN)jEMxvkpzz0I_JOZ)n78)urII zgs9j!^E?5b0J;UTSr?|BY*+UPcgO`oZ$uAiZoaP`+5HKlssce~{4;;Z=@y6*>R+0t zC~rA5!6^7?Uj{Q#4q9^`JQKu-`Bk0dIzTz+!~(F1|>A!qve}w3b=Qv=65sc8PuC?$Z_+#6utMv z`z(vvM|*;~&fk_x|0U<}V8wgrUTKsj2i>r!npe0F7i{_5NUt@4C z8GSzdL#&=B`yLWEB&TFSQed{%F6~CyK2QnI5jIWV z-9^+GN-ii8~C%Y^+bryM@yWyU)6tvTPI6X{l*cRLv zlclKliUZX*;{ivI=`&9@R8xb3`|SP6)nqCZR0z(&HgjQ0udgFR{_9a(Jgtk;bDt0a z4|kR5&`gJ75q@cX(oj`rr|N2^w`&N!6cWh7W2PBn4?xMpVK10myKgZF!(zgFP%ch3 zLw<8}ljiq=W2VTP>iwB?L3tQDr0op=1feKpZs0sFeeNDw-=-REo(7FZH57VyiguF@ zY;N+??urAx_pYO_RO#l5w&Faymw!s!JbES5$KwPIgWGc=lQpI=RB!O+m z0@g)p9?)IwzUm&R-1Oqu^zva5jPuk(+yJrx`TeKA0&EFV!44Xz<8qXVzg!i05u?j^ zx-j-8&lknc-_O7Y@9>NORfrVy)3CaTh|{1_4XUUk`JlQQ2=-_`Oe)HvU{kWs{dUDu zsHT*6&!H3a4V>EmF>WzI(q@GZZmRuHx&J@AkkuAQuAnp$|Cy9T>wZvIa|`UPg6b;i z!nu{u>x|{p^ARkO>gR5DQQ+y_Jv??T503u}5_`q3aTzrR1G&GouyT4H0slQAd(koW zWM>CWl*1(;qMew_Gv%Sc%kREt?UU#_D#&V&FQ=9P2Eg7e-)4T3xs3C6jEsrH|J^bD z%#%!||BV|Dt#6q|Uq(9Z~r01(33|FA~lf5Oy?ZMu4P5{%6=zhtP z32;~UAEUuu5x@ajJ3Tjmx_b{}bG!#^$*Y*_@XuUDPI39Ynx9&* z(s@D(@5TxZqz37XNUiUz228z-qZ2Er__{&LSuA0Rk^;6^n9A)e2yw-rOtR3zsj~it zXm3ZaLl=FtJ7h1H5LZaak@pGkO-j*##AXUfCt?o_Q^+3(>FA`0_+$=m(qve@jxW=F zo`@0{e0{r=0-RvLO_fQR${k)-JB3r2m8ljGH7P6DMf%*^kHsjB@khd;j|59lGX3i@ z@6Kc1Ugihe4$k)RXN5RLAmmi4YIvm}f3>0NnTHlA zNYE-XhJqAW*vo>>-7o(5v50=|3`K3?sQLST@ez1Fy8JN~-=P0-!bawlS-<@-JqrYJ zb*ir$s1b#cy^?dAdrvA!NnDJ>H#?4gO;$|;W|w*u8h4ka zL|$pC^avEQROljbYMpvHAE_+=idl-#XP(FZ3^_?uIi|?Hxa!eN-UT^574o33eBz`2 zX=W@U)I7ilKDZ*_AepM(uSGQW$`3^64`QSix~+Q(x!P8pA+ zX9b1?PHnyYOT)ipPPVFOf&MP!;cEi^Uipp&Km5g@@qowtvS3ya zMq2BRk9#KhH;Ymw>yRbnPJnC$Hb!hZT z4(aN-Wq<(;Ip16(3WZ}!3sS-(rl`dMzlSSPm(2e+R zGmE#0sNWJ&EZXj=I~2D`;PhhhciYxa0i&mLK_5dR@YDRwoP$j?pYg^}D7xRG-a}gS7A#7LUMB2O>Y@m2}&QNpeM(EH znrAUo2=yL{vPf3?f$1>uDXPVM{Z`fTGu|sT+Yf^+DLd}O?>Tt)dGc_+nJ8dS7WT3N zYeLqamhyf0Z!9fnt6GzkSlDwNj2-kGU5x0~;SZv)lT6TO+Dz|P(c$Ro=kjd=M&o2e zHgBuJ#DyFUbeN`}t6T(iuM;mtbRduFXA>n+9`>B^27k73H>Ed=@En=C)wsnVh=;a#}51j}TnU$x!JE5*3bj!ES*H zEu|nElOD^WEozClLfblC^8_N5s>0ybm*xzb_gjBZ%vIzc#5mdztXL^CJp%DgPhIjV z$)i1L)f5N;V_Owd7{oVgx>ZvvC%AF^6@h6%SOCgI}JQtX{ zg>V*@M$#mZ@c?a4CSf5yTX8Bpl}0a`I1P&j)YN2}p{ygDcQt01U%n2IdGR%UGnnDb zGvc#%d+vf!e9q29)M%{0I?+PHQqKL>uI*4b$d7H|`k}D@lHA{I{$Y-UMO)rNy{KGv zUBe+S`~H#S}hYc`7KD4Do`}C-KbZRB0q}1$zPP z5tU$@O-Pa)T%-Bd6xXN0qGiu@?&Yyu?}o15K`U&iA3l$!4;`^$U6CBL=FJ&nFGMDs zy9%KSXA+xl++Q~f`2scbEPCYUr?x9RAf5JEMy#UXWzA2BE#Dfa_9^Odfpw$IKR`Y& zyS5;U9;z*QCS&i`B7zkxTiDozen(Ky_B};OEb=}A`@dqEB7t|Y_(aEy0x#zC=-O?4 zDKo|b;}9MSUfi{$fYKDTK1Z{Cm=0Tosl3!onxhrgw*`xkTzKyU))M9KnRw+YaE?x| zSdJXBnaBZ}f1F2~3+HVaH-qsn31vvGKG?|JlQX1d2 z-md!yQlmROFc-NFmP5EO z7J7w7=D?NIn?3x+brRJ<5@#OL7DbBB9ZA}u}rQ%(pg3x83$0}`zzBu#!; zgVpQtXHi;aPv?l!#?EeQSSFkJTGvbqlkFa(zcsL|DIxg5Rxg<=sOQg}g`*FhQ09o& z^C&wKO-Dh;_D>S)U43bYgKxuOu-=Soph|_9BE2hERM@1h&mCe9J|V0Y8!H^Lg^f{8 zSr%zXD@yZ|dx3zlLuHO2Tb%5mf~E?n{3dfHB7e!;iin-{-T2lj1Ar_kj1Bpi(C0)SG@X~hy{tD*c85}seBDpcPxJyQh2R32rhe1x~@EB z>dm03yntQmIFk+t=*iSOyUlk2?B6bmtKLffB`5qo zMvz$(yRwD1pT74r=>Lv^`ZH^GcrJhmA)fozVi(E&5NOtpnZRctiap0nw`W&0%*ev$ zD0f%Bp}|Wa`C&fq!gR^s-fTjuWCf~bkj56Uwt?P-&-#N?W*oF!kcqD|Z%tDQ`K^|` zpIDDlA+On>;p}$Ga)$EP4%R{P8G464ByQ$HIq`}?PWj-4LC}5c*=g>F{wwa+sKCiO zZJVmL&(fahhpqsfoIiS2w2jb)u|`fmTCKT%#raPDc&Q+jZ74S)<@AIpb9(mxqcs(M ztmsv#fG|JJb5YATOt{q+P&$knHL)zm1%&Qd| z(8oQv2^O(k)EwGE39CI+wAtOQ$lD=|hv7so1;b;0v5^pLNuB#!H0#5Z_Cukmy{WBW z5zGVVvbdv@9X~FDUchi$a2rAU@Tc=PfJwuepB`zO4QK<+r=9zUHAmW%HMt}*af6z} zd#LvN_~sCLAGfsbZ}tYY(f<@fcTC>aHf?KLkL{TL=$g9Hxb2g-27h!=r^crS7}nSY z|LCFDHi9>+p5{%1=hF@|jRjNvzbnq(+@{Y@^!?%g`?G*o2DF{;hU^)?7T%y=^ZzBK z^uZ(Aeo3QPLnoWy1Kitn6>&ehnzfBwsXa!dAKkxo_=f$7*h|X2TVUTS3oI) z)YxKWc%0t5we-cZNrC=zir~DG6xR?c>yd4W%T*?#tse?BSETzE!7G^9JN$N-%cRAk zW4p4j)(F@_lGg5m>7^=13WRWhz(Xdr!cn-}Y9nS(iat4`%t5U|H>=yk# z@#SpIGRcc|!hTN7pGpjsahc{}TCfyx841Wxx~JQxD8*aoX;48sWjFjZislIyzhc@U zbE*2*l}Al9B6GC&j6l9kH3#uo5zwvv)UXrqsYN9BEZph5cNv6li(e0U4{*CO>Bg-t z-s&g7zD!nF?}7X*m87}E{tE#BJ~ z-qu&K7VF!9{Uy<|kNu$Gqii1E0jIvrmG4qlLU^_NN7fqFm8e3?nt?hgzo7rg=gf(W zvA8T6y~EX!iW|0o&7AcrAdgT?4R{kqzN--G>E})fVxPzT#P`m86unK$U&~OM3t&-W z;Q5e{5mKu1R9rGm|C^h)ddv5*OyC-S&r<3l7%PPRHTbHx`aW0cWnM7mG+`_QY1zSQ z9yG!Ko}*m!rRV!mHe>LK0ZKf7V&FYQcs}Wy$x5eM?NYm%f-umhu4|aDIZth|WPMu= zUJtscdIGh-BrueET;2hc*hqT1Sm||LBbdmVn9gJ|qE=-(Wld`?{9)=+eG75{uL!vn z@fN|4B2E3FFmSeD_<<>v*P($>-zt7lV>f7WoSLan)%WE ze?q;KZvZpD_SCD+QH57&WlGGy5LTGl61yFUs3((>tUPL3U<%rSGQ%GPJ7m)hrq27Q zjZBRhO0sFI9Wnq$m-D}~lvW+C7{m@*p6Qf7VSD?OYF!TjR%xMvnhnZdOu!Nx6~P1 z^@kY%4}Ob1+@(BfE21?iua4cRgUa}55 zUlq*{=T8?Xx29VZ(9S@TEa6VigYZyYaF4(nh(^O!R?kJ)VX8f9$6?giO(LmX9wNZz zBP`|oBbrR(D4IW1-=_3R)Ni3=D35f6>LCm28jJ-zdk~AB++yJg8w|PugomrJ>VcR3VSnqiSvBRl(WKD{4c@bd|{B#nr*~QFKU?F+C)Cu;>=IRaY5mHQsIT4MK%YclDVzaN83_c6SgnMjIqF1SadE4jZXxIoAQ z#yDL-OGvjE+jo?G+|vNXJA%<Mh$`}a;ptJVF=g_c4-Wa6!aLRm0*rw8K ztRjK^6l>mmX{m36XSLHJcpZjtn~!gt-s+`3UrFc3Zdd6cOCGA%(szzybL1zA;vu#` ziC32>^^6eLk$@cK1gx@xS$q|q$fK#Za(h`j6r~U-TEThX4Y>L(!M1S0K729=_9z)+ z1!D2)8i6Vt_PB2zDH!8_u;Q&6s(=b_g3zo7Qm7$aMQ-ii*F z52^KgE{>hfQaT5D2Z8-iEF={GO=h9#*80CGDT;7QI-H;d;FC%$`o7V=qZr2=4dwy^0vaK(0+lf#s6}zgH{bb8P1}w;|aGln6&i(VxP7~0-`YA zq1LupYx*`O&-9(F@RrICwrE#aLvQZ){gO#aI=3GR*Rr8q2gw~4w@(NGiD@myL<98> za%cF~5^hDd#rdc}Ym00Eb-%Zg9M+#R^C1KFb0y^uwq}v)YBuXK5FX14AdPMh!0?W& zLTQp|!W%S9cZD8eN>%@om?WaFo;c1kN2uV@h0p5#%CWGU!cz5+S*RwY?C1Eh08Rb*w6s}u+`0r01Q6C+)WIR_bxH-kst ziYR>=tVT~~YYeF0f#-``02vDu`qznA^Py6RmxZLzwhjyCBfqAz43TzNnMT93;4^3e zZzY-HB=vHE+Y72JTeBCCopf+(AWGkvI0jWfAo-c$H(HAqO$BemT#h%_vO?uzFUmTwf4gLWqWQ06ozU z0e#g2)6;KPQq~^}f7NA!d>AS4#Rzt&A?fkNU$S_XAd^}A#mzf09V8_zl-z<($eG3> zRxpxAb1iZ@NM1FTvK3hj$V_80m4{cK7ilcT3#J2GqZPfd+6b|{#)^Oohma+R?-s^> zkX4J9QuhN+5GQ{(gJYrC7Ct^tIsvf(3955}LU>E3D8%3PAx8(@&n9BN{Tv_ zLpqN(fS6#Qi(I-7GY0@Z1qhz6iG9HGEmEg$;S#}ut!mn*2yhr+8s0t( zJxf@CNb5f}bS>bsMEOdAQ$E1AMVrb3PRQ~~rmgI%H>J*z{(mHVd0Z2B`u}&g2klyA zTh~(S5s^zojY<^}%#Eo>LT!#+Gxt3TB457 z@c*~RI+c6woDiZ9=#jC`E>*utR^uegsR^!Q)yI2I+z@R>L$lb#%G= zDB7uWp!BF<+?wx?ecPIv(G#Ee(+(t8V2^BTJR2getP`=eoc|=V}mf6E?hBfNe3PTN|&3$zq zoRw(+>H?{re>taBuiA-+f3tas`pbt@a3k`Lnbg5(FMFddK8rU+vAmAYXpM|9zU0`j zTa~t__!TZ@U&K~hajS!5_5Zz;5-7X6?Pd_2a#ysCTP)c0Ca=%dp7p4BZnMW>i$4Mm zn><_8ztgKjT=wuUqk44N5H|1J(N30I+%gkcjRg2NzR(j;JehN#vM?`n-3lQ7+VaCv zRn$ip z!_k>`f5X7PJRIvC!6wd9-naR7UaI*31j;q9Y%Kf2JVUPSFK6>caUb4jjAQ+q#J3gC z;Ysss*om=QMXf4)d`mDF3Bc2s5yksI(p2{hwg4v772v{^%~TQwC*eWv?Aqrq{($Ue zUhTT&Z$;^MR$wtMU=3Ys5w#kWa`8JL$>`q=N_7pk_j!db{d~9TD*yK&I@L(Us4Ee3 z5iJ8@amKfiJ{rmF`ddC&iE>_69D5H(ML4G&p;ok2+^?E{J^xU1C_@J@Z+Ztz@(S#u zpV?a+`ADdV7K50TSd_fZi-D~M9on&*u3XA_oXWXx^LzS62RVP@HfyP=PC`p5AJaifiQmr72OS%mFYZ?5 z-AIUI{cKzm_ZVgnAC4`ZsOwW2A5X^e6u^7Ssz#Q|K<5uU=uKHpRq^lV3vogSB0`95 z5@Xequ7g$U0Z+2YFgE>a&G^;w%dD4V1O8JN%*C{}OD_con#9Pu zetLRz+c~M2COjj`W&U_dhY5uw6qhtU_ry9rKjE<$B1X39CUaMr$rP&x*7N#Gf}1`s z3q1JStWA~9ovv#kWQl9mBz-|` z@*gi9S!{e8C!oYbC^&SD+iEiC9HcFKjcTqbLkjg7gx;QakNKos6e~mv4Z7~_D z+=f5g5k#@xZ%2JMe7P_lQE?QuB=ru;y0c7TBqmoL+i3S@ zur%VANdeT1GxJJC2Evh=gw-gv)6c~T@p~Qwb3b9nvS+FP+BR|^qyF|bAIF+1KI3a9 z*lqKMvHl2K)yUz4{=_RC_VF+gvqo{Vr5%q-7qx~;Csjd*(L}7^2TWD&@Zq$~6l^pZ zLQ`?Vcg@s}_Zwx?t(0la#kTvl2ox}%PJU?x`9;tAUA$Au$%r$h<5@d4Q!!7zik-M8 zR->u|&WIDAnC5d+!Ar6#9det~#K+d@Jj8R4jEzXcv%o6#w6@acx$P2lEwBwI7?&aL zsTz-Hdl_-7*5VrUSWLTEzGJ3xms!uaRle8rwfysYGW5*>c>dV60{M2&T0DfG^zFBi zWnwwLU5Zt`IWxxrgWV~sWP+Vyx%Jw`ZKgah)K+UOeahxBx%^n~EX6_FQLq~#wvO83 zu?trw-Ausq@P9=n@gFu2F>0T)0n)8`eb@&eFZA;Wy85miV@&i6L`%Dk^W#2;Rjioi z^5v8^V2W=AFiH>BK&RFbqyF=0hEa?&u0%>W{q=Nf#E;vi#u*ob0UbP|DpM`S-zA}z zrE}1KprXk_Ijv5j3-c{A1(Wz^vb{n4g_GM{2FzMwb7Uo)Ihd67qLmQ@x^Df6+viUt z;W9)3Lr)?d4s@o;>pT8wl9hXWZJJi6Z@KuMky>c1M!-e9GfKg&fpB}cXu;j?N9wOp z-wf5bX>p1ZbVkGZ$Nd=rP9#200@~@t$XROXbpj()J8V|?CQHV*%;!p^f)xY?L zI!(t5O}y|L7bl5KSPLP$(6pzi{4sHVk!IU854qqUGQt@^WB%-j6%B zOIk}GD1P58zHP*=aF1~N4`XQ+%Sj9*daPLbHO+ec*pu_dfYITuHEafv%vxLvV@#vMT{9m3#mOsS5gs>xm zqzrm{R4BW1Ue;K47it{yM$cc0`A_bo1k!(hR%xgh@a5Vid75D7qB=A^30l>NhV~G8 z5rR+s_q)Y+_dinnHWS+5-8!m5Tm}n;#+o{y0U<>^X*R`RPq`DlgT?9>+vK{3F&GLS zc?(JZYHNLxx~v&YV(}Adv!)qUVUJBL+Ds+kI`s36rnJsab(4riD2?FrO7(>6OUn3F zQoOC;gcrDRtmipfIzobw1I(%c#WZ9h8DOPb#c9}zrA?yhy+$z>aZabBdT7iPHtzo< zCH1Zv7g=*dAIa+dvy1s{um=RWG;47fH=ZkPvIKXKClqW@;pP0-?9Z_qR+8!2d7dCF z#8w$p!)dsKVu?zaOiRWVp+&?PB%;;QdVaBhRfGrFQxPxJ@WRaeczmMRjHOUoz~bt# z#FWhQeOvcnrX-P0qr5Bkec_;?>0ENaQN}KQ0!%ltsPB(*YBySKI0dW+MFz}Z7vt1> zK~$-P#{jp#wOk8fUhJ@c)*OFVbZqwwNX*M(1DBg`_(1RnaSn?Ua*?Oer9H`Ie6Bv?zj)cdgdal+l z6ofx%wk_(zT3ahqjfV+2S~r;s+~cF;*Kk58<^;u3RhmiPTo!%M_HvaQKJ&Jjlf=cW z{PwnmfHrWqjaqW&mVJ}-A&C4APXt`YzgjD-F>RwbgB^-A=eHSL@Eg7pxxMq4)3%f? z<9li~c-|b7Ti)8y^d>fTWWM;6-%NhCWnvIBp{qTZ@oiZUv$<;rCUqt1&s11RTl@$7 zJe#ixnfIjx+DDOA>QacP<476`#H*YPgUDSo@7Z7QV>x$Uc%+`h?x`fhkPB|f#weDM z+0W*Qx79rqLx|^lw@CC(1_9z7&AxguUMS#%sHTD0cyrPcHMNKL`I^D|k0zGOs~sA@ z?Uw_bdabNv{3mSY%(l@s?Th6Ew-+Ru8PydSKk+B7r=0L-h{<$}QA`pb5Eo}v!jK3C zNth+!{UNDzjY1KYh4hG}zeiUi$sePVDYeMNda2fajE|;#r!ZB>0#FV=jlymctD`U5 zv@`1#uo;rFc?AIkQKh#%Ypjja$Gg=0nHkHI)dwEC~;xt#Oc$4TXkKe#3n3cTF_ zh(9f9zTGZ(w?Q!Y(qIrY4NL)|S#0izRtEPNUAm=Hn>X|EUs<}h*Q1|Qq#+HVg1o$ z%|O8WR!LG(M-I&eZHCm}#tM;mTF(O;RSnt)@XxWe<7#3$;6+&tukh0|VW(^nW*A{s z*pL&iz@lm_^09@_I(ueCV}uk;3+5T;a$9TbMc=f%G0zr%cP%;kV(dSQ|2yiZ3137# zuPc2%@1=D>XkI!hiGeE%Fp{hT=0FjLx9U+ct3aY3AkOD!Z?i zs&QT)KFYT>WF)Hd?jN2(eZgx~XI5{ZxXv4*J?uFBz1`{xNu@X~;TZTX1e{unD82QNspkU@e)voxx~ zZtcUXE5EZbHtTDY?aE2fy{*r?H~cO6abamz(&cKK^_(!7*gu@jJ$FZDzHB4xIo}Ck z&T>&lB=Qw><=`i#j$=ZMBCm5%yzyW65BF?eTrg;hT0g$q(xD_mYa@R@eN69Xcd%X` z?nGo#x-qiLpgORpD3$vo|LjI~Vjrn~os)4t=gT&j{gxJ7u(|A!A6w#CZ$4KUsZLWY zsdLxyGlpsYO8@Df(|6~Tgv4=QmYfda;+o{^IO7?*^|Fde6(YT);tS}Cd%1NZxeS$< zt_XL@^7jwwG#?6~wIEILB~SB9Sznginz=K#|KWE+5P7gK zO^EE3Q)L5w9QwPqoDfBaO;;gSX*?LLQ;?l2Q`CR$q1loD7TKL!$@%P|{h~$J>MT&` zqw5Q~va4e593q>q7R|#3)tQ4XAx!+YH;+yGU1S?gw8?!$SZGw&wd~>>8gf&ND>@e? zC^GAgUQpfL5igAHak5Kp%RXgwLqc71t$M{rQxz#NbIMJOx!}WCA)FB_sAarP)C>iXq3+`WOchtphdj}< z_u73utnW!8lDd_aNK7*mAtDyhky1lwxr{hL;i9GPa{CeWk9J?ol3e!*P zO|PMsi8?XPdypS-o#f`{PwZhMa`|1V1GUN&t zJ)LVjBbwb-*X;_;tl0bH<9Z>{I10h{e5Cc~xFX{S&WAgS+_sv;R^Q`7x^dCD*1@}q#*B$S0sh^Qhi_Pf5w9!ZWhgH z>%3`#52LS2J4sYf3A_%rU2LXeOB?OaeCd{RW}D15I;gJE&S3QuvK9BL^@-jlmAN*X zR0na6ggc7-tljL^`-cPRNmS!By<*F`$;2U^ZmwcFY(02`hkXRTnDK-^$c`ReoWX{7 zZsP7Dj-s(kzA78-!;y+CA)(UyWBiFKv2!mR~tYn6rZUrjIeYMLv%8Vgmd$Y%U1&Y%u) z^{OYeN>Ux!L+ipu9V^_;Zrm@nqEcAcHM6tcwaq~syuYFNfC@V#jP_`3?RH~?{peWA ze)+_q2kfH~f}Mj5)w@&!HtK(-en4lszNZIOgp5{=!zGH9L`>YHBnT+`ZwwYoy&5**HuWakn@;J78*a*$HcPD1mk&Lx@cS6)@i{V=UhPdV zhV@dve5K#7UQw0zHKEh!-4*9l=XS&y(}c~biYna4B>dom*@9VID;|}CJ;Au*iFOm0 z6se9kzTLSgO|8EFO$Za-(rp=W@VM77v40HP>}T(?yMwrS-M;I%zie>qR(0~msrrzv zB=j6yO0F45wei@3gDllbnX}spH(2~keNpT$`zUjVh3PdFr%*veDW9?NR?GZZy>eMs z3zjRsQ=`)F**Jz9icCsXYvOj=DUTRFC#_AqCeQ6D@|r zUc2@<(O@5aLblyDa8-L&^=yx30oPvgppbiqEBx(#4D;o%57!OAOMI%d^{_%1QOOsn zJ{n$sxfC|XH~#De-q!|auGYV7>qbB|H4+c&-{+FSaBAZ8|QXwA4onM0J#-|*@^E&naZB6zP`On07M!6ihE6X=vIhv(utThNmS619 zk?-JCSPZG~9-czf4#%Ro&DbvkSM_ter=~i!VwKZ^I;O=sZaPDIQ~*&Qg!oH?WNZBO z%j~-Fqyby;a%!?{so+|4E&Hy_?*0}lqj2p%$FIdYy09vkE3vn)Rj<_fTDb^Y#%&+c`fh+zV{b|f3a`$*yc27K9oU&Sz{nm^C~ zx8HR@HE_e{DeH&8T8EfMgnweHPmF4`Yp|e1)o=#)X{5D|Pd8GNiMj#zK_BnF@$?i4 zcAW_VY4igJdI_v2I8r>or#>a@KEP|@GgMQHN5{`bylp(rY`2NuBIu&A-uk&+Nu+vw zkF)WWPm2fSTqt6nzCqYS?27knVWTNq_7nFU?%`PZQ}%o-ZPJ(vH<e{LBzo!IlYIk=hvYu#v(D!-xBQ|wxOLFK6r0?cCsR^ETuB%(8c7M zj+J6Hz29Xp>uxgNm^yB_R_OGLyodSc09g@IOz#0i9=;=boae+$;|KTaLx|70`sT`> z=?_l~S%<=?P;2rMwI3(TuO1+|u4c-l`H-*9SuDh;XMjX)Q7;vBn*Vyz*zfVQIUjfv z)UWku*p0Kx`fUNOJP(_*l4>rzmE%D53qmTU&!(nW^uOU_GeCp2C+X^(B#%XZR3H_8 zDAjwhlG%3W1-smZ&HEgiw+n$5b%q$e^t;#_Lr?1ab_zYk`%R#Jp7)z+`q^0(`Z~vV zQ)TaXEPmG9OdXR1$}oPAFUW3>5Chb0D-cdRJ+w@~#fM z-z)^JnNLx#zkaiZ4?vBsXvmFM7u-J|MjzzsReA|PKfPY@^P?j53yiFWiUE-Q-Q$!1 zF_u&3mz`n@N<{XiRQi`t8(XpL3l)2Y_l#H*D1HP&)2BVHW@ zq_-fE#XTIYn$qVm#t>hk%KeWw28v}M`ig;KHg#)VDmT5Gn8RHuN!XTOIy{T8d$6f5M{hQh@C;8x-J#$mQ6S2n`!JG?tmoh(cTM4s&?0G)V>7RRMitdkQy zYo3{oZ3=8j=z{P|e_Ya3K|Astxo^!nV z>0=Yo>a>A7`*g13CN|MyxS1&Zry&w^*6`K(8pqfEOfgpCc@)A0V3w7*%yL9yaRpT_ z-f$~zUG}CK(er+%r427ZvRWsJq2fWP19ylhmp7LW>L{~2#7?@z2s?;9$LU0;t`*^=OeI zW_U@mdf{;XlB^p}3%f{7R>00VGL=?%n}aDyX77$niWMe%WOl=7(cb=qf54`9PSE=z zlCy_|eUuV(GReCs`&P#qL9U=3Y&j5JwBldzAs^!oULykHGyl0w4PPn143y0~qE24k<+fYbWhL+U@RkF(Auje+EOm z_S!^y>2dLnz31xgT^I#t=#2fO)kc=GvKTB}k>G46O)5NrJ8Sz3y5ie!x-E&Th+_}vY;Y3l#uC~n>% zKvUq@j=w2=Kdpw>u(j!NCGQI!#H>dcpW+{#;^m#1=5JTvk}<=vvBs&O8l4TX3F#8>DS3gW#Oxm~rJh51{Z12t?RKNJE) z4Yqw891&+r59{+aU9E}AyU#eT2!8oKLnF+xymo`TL&oJy1iOd*TK z4Ho5B2=gh(!JPkjvpEm$endSzChJz=F=4q7%4KscsM`@KqMXoU56YW6?$`);J>+%N z-2*#Pgy+FV<|4v-yG3>*z;E4b`YESkqX+FoCADMAE!k0&vk_R`+0CL^3>E{(NJo0L zXo85l)^EMUPkJJ<0iB6lceiyq*U(SpYXv!34waDzr{F8$Jw;TX<9G~Hi@(&=W-n3C zV)PaC0k?NIKLKv3;X|}yHX5lQW{&r~zdp=yuYb#sn8GfZoz-ZM0GXEWzxbbOgKo#K z+ML&%mc}x_tcm?2x5`S{CM12-O0iNiCmARtK+=&>UGF9uKM*!&8hv}^VujPUH3u@0 zPsbgOx!pE_>xGRGVdmVn)3ZdKn8bHK#oPYPIUi!L7{0cg@?JT#~yOpr=f!1LV}<{L|hsc#%B9@oER-*|$#U>kS!0Xw!`HlN+x znVP2lJ4ZEMF@kW6xwctKAsNN2YOG<(7)v@ z8OePCn0eGHw(38`rxrzkgm=QrG_I<O5` z2RNUNtWRv721o5@($0Wg$ZDFQ2pWHGRbXPy8H>HwR@;ZGi%56rcDperBYTT@MH1|sWj5k>>_lHF8 zj}pgp?kAvj)VlHAt!}fo*PLeFabHWsFC^z2y|&TT3M>)~HDxjXYL)VYCWs+Rg_t zUkpd+35F@p(J^`U7O-OHJ3_jm;Oy!DJ^LzWpX2K(%oo6wJfPazCs)RBD>v4A?F!en_ZPodkUrLKwX&=T-#1R~k47idhy8N!^F6urSj**(SV%k9eftR|guJ9Fz6aBP#N z5blZiv*%6C>}UV5A7%3rSS2))!{SPi+|!ne8DJZ}g8zr>c~7!tzRe`Ic{|K{6-D8S~Dbeo7y7Gz5#E z4@YoMQOEM0c+;|ysE-cKw8rHJq>gPt)FVTKGeSN&sSS#E0TEtRT zfdzTii3*whwOA#Z1(LG?(&tBtyHr0s)SciX2KAD+8%pTBH2YjTb&1`;J{+)xw|L-o zD|TvL^d8|K9pUGqjBu68DHdI@&`QExO@*B$vfhzgdB1iSpARP?_r!$v*^{?NZQ>?& zH%`cp?07IRaJ_&X0HTG|6Mml-sUsj<7BqWR=^0H~EGLmKH^*SL}*mz%f+U`?Zy-OM6DF%H84JtWwd5l2c|Kr}DV+U# z2OI#h2%f`4C}+zF@m-tm3UQM71u$-yyS$A%T@pT$JHZvE2ooTd8pe|M*>RwIhN_GA zt6_%3tH*muVH6|tyu0NyZ#|oda;t=!FEa@nx#@6{(zencvmH4nQvWV zNfJ`jA>a*H#?xUkPYp6`e?u&p6(G9ycV^XHKGM8@`wUYfELFo#Lt)HY4su`%s+FS2 zxsAJ85;Bsz7HK`ff8LOtU|b_?&QKI|Zi+Wzw~b>#eMZ4af!rEi<=!b-kARuk*e}Zy z7#YfT(SAPo>|I++h$dO5T;j1%>qQ+;0b%lXH`=N1gvrb_Yi8QxF3)r9f?VFnzxkLp z-rA7}TOa@o z;~^uYF2z>TfzvvzxZ^2l%(Zswy3){q^!KM?;wk zu+gNZ#}`yLM8t{2n%u2uFMYoipi{?P-kDsamZO$^swU5+P*a#9PQxGRx1K`rC#Ern zz!_HOm%Yh)VI=#W7q8LE%ir5QC*b&uJF(z0+qIJF%ReV}BzdSgzaIqaRvs3XtLMVH z7y(QvUjOi<*$w_iec_E~eeO}y=~`aHujXh1y@7n93cjy|3m`oI@(r$fX zeq`4>3F^5$BuoBEg`kwl#i~J_wUTk$Em~@5`z_s4&p+(eaIu1^RIjL!CnEA*fp?Hr z2`^-!$ATV9obiL#aF7Lx@*Kz`O)@n@JTQFP`7a?-e}ta~Uup@U zcMTHTfbvf418i=={-W8|ng%i|i}7kyBOz{SWOg<{JxoO{QcnT#)pEj*?jpsPXj@G{ zrR{rYI0qlj*Y0P_H<(+-gENq^VCQhc{TV!g40;r^l{p!T1DKb|-cOm+{KZKO0G*E? z7JZAAYbXfrMse$L4XryK^yI_QThUj=6ci9wPmiK5> z{)|uA36hEB4OhHA{HZ$J8fpe9oo4E2g=6~@b)M;c8)QK5lJA+=zYWd+k?l=Zhl186B7+xV|HftSZOIfJKs4(@B9;AsG_;RAUXsAh~A?r8tEE`G8%3qg2~BSF8dQT1MxEbpw5XdkjfXd-x?sw zNrj_btG@vc;GN;r-*hqJP88{2n6_dK_N0DCobW!HB*yJ^r3WxeD+bV7SPK#0;|HDK zxPfA*%sn(8JPx3M+<42HDp-^{vEu zkh5Ra^x{LMZha ze5~VWv*mp)>d2dT@R=Ys%0uc@ozv^xEg%sG{QP(z4*QA)E>V=?npPW zlX`0+{D&%QZO?R*WTN?Yc`bB3EKDDuLT~%1ZCouR>VB{$nB@ULp`vdt$=JYzrEYFGx07r2YiIVh~#L zFg)!q;b8xIbhcPQ#6ztVt;zxNdPO=$Kg*hsoQ1~M&I-iLi0+&*+>)_=r`XJP>qa&T zHPiPyVG30YgY$1tEaU!vnk5-uhrLB0%L|S4bf#obeq+{uyN)j?WefIE=9XG?@2G#f z$^0I$^diLU%F-!c&1tPSc|SJOUqJ${1?)|GTtT&9GID1V zy?{H9wHmkX@ya)HZxx@Ay>8b&X_{h^VUWT%fiSdYCwbnr8=w^R^Qp!eRFx$1(K?nV zMCX{Se_F)@R(2x@lXZX3Qxk&(VYEZxcfXRo1L`!6p~`)&-l-NUSafzlK=?f2PMPTS z=v@V&8|gp?nJESYjzmfJTU@Z+cJ1m9XZh{0jlz$M{jl!l?fmW+2DOrzBnA-k-KVD! zQ#vv#^w)&|ZZGgL+sxgu=UyGhjs|^juEvbT0@vOP{3@h=09v|?#E3OWqID%=*DJ$( z1KoTLnQ(}^ypB5(nG`1!4sS|T#7phSgyAKb3aO_w0)^O#R+3nSQJ5EU`7+hrtBq&* z8AdUfC_-r)V-)8;`%0$wWK_vO-H5&L&NsE=c;F9`0>i2iRq70M-yv@z;66>{vhxpt zTYS4CUi|{hrv*}$%|uf9rciV0uBWg$>;nL)V>UU}qC1QSJpp^fj{$TaqBC@cWqgIa zPW_-N53LUB#_(l62KXG0T#4_4a7#g5k{uCN^D*QM2U*3mfn|uvV(6cJfk*&?F&MeB zv~z8yF}KdJi_gWEUyM{I2qR#wj6lD@Z?e!zuZPvKX^^%=1d20%`pSTojN3d=W1}3r zg}s@}?^YT2LOJwP-zoF#y>8!24;thhP!DTCxSBJ3-if zQkn#4Ymygo=T+kBBQatbp#M3Q82_isJp)e_hPoKCm_B71r=nsNcT@4}8JJ}0SbQ1n z9wf}QT4g+pLKuy%yaI&`>0bJzDQsEv?*XvZh$~picTuRHR*Q6~>?Rs&`|;PN8`;Bb#64<3$#uiSmLvR`Xh833^g!wp#gnbH zKi2*WB=9uJ@f#1S?vK)jfq474bHWUI4?y+j=)6oc5U95m`D#W-|IBCKj*&OKhB1`$ z;=346>N&?}fp$Y6EmUL)n-hfqaMnX86OkIwsBTC>JZ}Yr{vI7Xt7GUqI1I1mc#ko(p_c zZFamc-(#?+IMf5Si2q@3O5@dBixJUbVh(Vc=0&2;8tbtzU7j`U`FrAIQR+s#Bcuq^ zk@_Pr9z;&evCxyj1;V6lN$$8%T0GW%2l>GxS^F985!hYf(CzkW%w>ECs;f*D3qE@G#^_Jk zpsg|wt4*i&Z@uLUbKLlL8Cgl2MMkIFN>62OT0e;-E)|;uwsyn)ySHoLLn<!JpEv>NmVt zcck}k=u%c%I4U2%AvrnNbQ@27+Uxh zlGX4ex`6eZ6m{~0^WNLH{Z^?ox#Z!5Z&XM7PoGm&HYnqa{~XRuRjhedkSIj;p&t*G zJO$;RY2j0h5+MJruS~VDPIp%I)72m9_>m}ibcI-(p~FLWcKeRuw)UOk3AB+LTV1KT9PP!9a$kQjSSGbp;!$cBbWY$#+@Vc+6O^V7 zg+Sx^@ILk8%@9m|sWRcmI)A06i#mux$zfxz^6|zAh`9M(YhsPm{cl3`LEfey<{*ab zYG1{s&c|aO1gJ;`{GM*d&ardU;8xU+(9Uzf#k6=PYxVZ8%}&fsv{X_x$^%1p%jNsJ zBJBGApoY%EM8$fTyrJ$N!o*#Jy0qDCgVKOVc>7oSN>`{^nG{uJ8|P@6VyO=nELL;j zNwW++H2nhau^CjL`?No^6Fm`CWKx3qRfJ6(CP93Gfv_<(ssa?eY^_+E?w#88PBO;N zBDlbkHS4%^a6`O{&|VC3MD2!MN`3$jqFT6HMeFkyCn&abF3Z4-qK1t>Nmmjv9*br% zTFUk7`9te&F%S}IrivS_8p>x@87a+#HSw7s9sb}E3CEea_LLKcGT1RL&xPg~ zZ?&};rT>*kwNjXc)gpP(knU4>`l|Mb>P9}IZsTn|2E}gc!`L70iBp(zu-@?{joY{v z&@k8tCQg`ycy1k7=|QkkYA?*5f1`~m)Ka8kw3j|Mh@n%u6__r^=Of_x*{}X~3VjW| z8Hak3)l(r$4`HLOAvtLq5XUlG)7#qk0nD}eJtXUgFcVJ*o95mWM_WtTmjT2d;)v?p z-t-Fj0bzNywW{w@Fj0=O{SQR=bNGe^F+*Q>JM0m5K8nqAdCsaLkm`C#s?-g;?)el( zf_uz`{D$o`gFYn4i7$o%^hJX@!#?-DOMC&GYgzU7&1S2~b-R*El$H*J!!lE>VswMu zCP?5=CZuc4>arN8%bUx!NTfZmtlEAQ($la|)ahocf3Zcd=o0TlS`putfi~f|?$>>ljCqr!Y;LViHF``cV(VcA@{bb%Y?$eUS zk=)1l9hWpClzu)?`Qq`BdWT7YbEc4TXwIYW>8-u z{(2?!yE(K%NB>Db&WVp4(%i%iOajm8mD68%R!C6Q@P% zDZ$~~ZqG;-Ct)I`S&j}*%D%i?R>?jN#!*xp{xXv=PMMuB4%1LMu3*-f>_SDFi73cu z6)o;IuAxu?&&P_a$je3=R{|AHe6HeVBO>mFTzV;c4-`v=)J<#io-*sv9&lLtdf0Z5 zWliQ{@8Ra!t_EAwa;TJW$2|-s2cF8h^;y(0yO-VtNnrO{vaP|7;aC499kn*L2gJ> z$!JZhConRt;o$Zji}M5Ty2Db0ujbZ+o`1hJa~-#^+0ZDMstO6#?-T?r|KbMf*F6>U=f4FNiv5G1ZOisT(0yq*fD=M zg^93kNHa#k$Qc1dCGL{1Pw3x->1g|O478B7Fug{>ro6u@Csi@J*V%=^wUlGxTei{Y z*Cite)KUPf5?{ceiG;B&zU?ishImf}Fmi8m7+o?e;)qh;;ql$Yahw%W zq!?XGrCvy{FjTmWr+6ihM}vB1fa1>qC$s9&&aZEc22=5O{}3RPn2Np}#`O|J#5fP7 zd!yg9l|RCN06dAkEiLRqJNTrID1{b5qJ7Is^dHwvdsoAZ12a&a1?b<3gNFtJh(y(5DsuG$2j zrTd}b5+5`uGi6IN9r1s<#jZ~*jvHI%vwp3Vxn3#$!SU$Rl50fE?Mr8Q;}qDa7@NR% z`yaY@H)}!2i|q=y^l%HrYOF=7bfN$Q7>WhR;kO2?ic#>CtOs}eqSgNhO8auBb@pzt z8}Gnf)U6NVe%|lU+2if%RGXA%y4%#pY!8ds+(Pt59Pq~&$-NnieTyxinEPV^^vr}r2j9}(8q1({fS}#U)@8d zhA+e%qotlgt20~}p7#e)>D=deti!uoI<~$^qXPX6ZjiWS{1gjub6ct{1jhrIGO)7G zq1je+6C=e;7~Duz=GgIhE9T2y*&!l;RITBTu7~B(HTGnNI335>$cF-ih6g1>A?g!`l4E zBf?%8?om<8z(JMpya=3D5ElypfV98j1Ha0o!Q}v<)o{dX4||fofpbTS7gXo^ArdyD zqD4RyIp8Ja9TwJJiy>>kE1yP+m8vz@N$x1T-t}-jJK#m=|2?S7siq&4>#K+ER^@0N zmx3_-iFRp?aI1pWa;a&?y!+=vh$39zn;T-r{(}V@dV%UdkTB%i97?beMO0kNn?K>V!2Urs_)w3Yw!UB`#+Iuj==+s|)RO4KPu_eiu9)*EZQT2PyZ%&8z9=}$QIwU#x$(wm ze7y>WMjp~!c1|p;j-mI!DM`%D4C10UG@euawj)kG5~Z&Q(X#{*KN_J;0C+IPLgs6R zv$+e9FsJR@Q**~sRHuWGA`!oNH>M8Au*PW^UXbJXO^yD*;F;D4Yu{-$D7W?iAlSti&2G+YR8apN+n+9PN=?Lm6l-K*7j`$NK>?fO2^^ammomd2K_f6~sYxYIPn5xIfl_-hmGWyJ!`arKmz> zkFdsNDB|v)?_!X7I5Dse^Sp|-WgEor{~=Q^;VU$2y~&uyp}3V-U>A(OewwXkSKYCN zNQY4xL!QmCJqUa}*X~{+hU%wuJg6ZL;An*N1}f4#1Q}C~!7R;gEa zW~B@NJli-~W*Q0uvpO7%SLcyjChnCC6sHkdJTP^aemDw{=eyYRFMAInL$9zVlg3$2 zvgeggLut9$Ia!=UebJYuo`M_ez$Zi6qU(dHT~69m3?q^_FoY=@)Kdw!v!z2$AC@uI zzz0&XZa9@R`u31LqlUY$Qu%Y-je+{;zGKsveW(&+BgIpE9vptF15cN69H?0w4$lB1 z(MBJzI&aqm?jI#-nRo#%&AM`76zp_)e*U!RG0>y^_@M;$o7-*cxZ_|T##l93P1e#G zTG|3-IouE%tKK0^E-oL=NHD&MS~CV_pl;daZPEn(40^hC11U}MtoFv}gL+q0$#m+} zO0i`qOn$s@sx*2~;j|1J_~poFtHg5OxnCbjg}F}G@NYmY*VR(-3IaEXvq_(+l96{A zfp!0w`$oUy^5m_Avrw*OR>a<^{wtTznbPq7PYJs`1$Z|PV{l>(GUgK`vHI-k5IV5yU7R85qt@IcT+y%F zQ`W1qDj6&0D4zE)_AqqG16-a1d>~dQbieOgwwz;!4k~1jZY{a=eKrC#!S`3nA8ypK z5PFjPG}@p;bV;2b=C5>UtIDon{P_=fAnG~TYvkjft{D^Lt@o$&nA!ES&bwVHUWfTC z#d-V_#ddolz-9Ffv9PW?WM|?W;mJ@OmjKl4SVqmTq17jVt?So_CwV1m$-UX5-m^EJ z(0AB!a0HTiYm333E=JmM(gb7vvxE%H5D;uC1QdgI4j+ROO+~6#=k6szX)#q7FF@=H zpJ1w%x{9FexRL!a`}1WK#xOjm^;8Ja6M*w=J;D1r5gr&gcY-{x4sp0`t0>>I5RNN0b{3AL*kInqyAV!+- z3-o>)K-a*jjRyqCKsGqH*~j13WO!-nPqJ8o+=Th@X&k7xAvKD|X)bJMCc`mQRQ0c@Spg1kvTC1Of- zKAtAAyLcqmRq|XScQFCH+lrn?nw{%y^$id)n~YNEgP+n&5w`WTttC*jm9<+AhtPX5BvaX6{ImF? zH(U@;@FAeY(-4li;5>$zqK=l1RIEkQ3Hpy64L%%VaXn!1=7G`q`_WYW<1`dQN#_FY z0jfhw;mkfNW3LBE{}%A=A5w!PFj5_-{wo~ba2%7+Ct;j-vXPjCBfO_V38E#(M1rAb zOO!X2<+t0fz@jF=sm=#&{>O!J{j=z07(I~=WX?r=QW(;}*rnPRE>tpZkHTqMtG4H3 zGZ7$8Bj&|wM#|$Oq6I>vifS3Y%wOntorU*Q#J`IH*G8Lnqt67wky2&Fk&{6E zBx^#tV#EEzlZg;V3QnKpuSv|h0a>nxSl59aVwTm}g@X>(1ipfa^H!@)U42l;PsBpb ze=7U9NEitMwC=jQl2=Hoc`vq<#Fjc?Gm?S5%XLH*6Jg5oDLHI4Kei+HsEBt z;SyV6BMN_jTE8(?IU?#~g*58ghe1fif-VE4L_He;7p)koIRZT#wD3vk)SW`ssZq5x z#AXQNxrqEIM|*V+%9sZ1!l)jOU0omJL>Xq**1cDmbD*or?uHo4iN$Da%5Z9;@KUcF zJ==qPB+6o1E76Mf9E|lRAhOeeo%OIJi6uz*ZBMwJhvvv2;tl4DWTmnkgU1DkgJM*# zw4;EECjwG44-F;7TaJ5G&c&EjejE2Y9=hP@Jt{;W+J%m^4+g+AxvTF}7y_t7mdgM( zt1EG;j@;)mwASC;@qRUx#8>1bVPhmADh;WGujM~Bm39-GxKFskc*U0c(1w#xbj4{~ z&dDiE^!~c-R`zNzrLe3@U(8GVX-y8`G?nwfP`cI+#U%o*WVtjT_fsw2WfTI!)py%4 zpWTqF$mA~Ns|(nW(S(N$`6T;h_!(wqJx=ki>0FsE%)m5m4cxg1?>E7EoO7pP z-2Tb*pOcEMG{5{ev~V_|QYsHRz7Apb!;b2{BYUR!y&y2@b?M;nU$|pfroZk_d)G#w z060gxKW1}=gm0SnyU=o7ruxY2P|_cpD1e$rsurb?11+%P2n^CVmy6%xG!xqMhE|WR z`6{1+Vc3K?HP&FNDCy&`8gN3=2hp}0q}d7Dp@@B!mSNn{nTjqLya5>~!8<`XW)adu z7fcl#kyFins4|Qm#9Mon+pXFNp?nWhwHV1b&l9Ngxd_D5TbT@&;RKprj+#2wRrjD; zb6Gk!kns#nZp`DXHpGy-U|W1KBxiP`z_(rP-L0y)%AMjD11-&w`b(*vQs>R0;6ta<@68TSuQ6L-O5dI!#U z7#dg7I2a!Vub!GDwCdM`9+z+5Y>_-il>)41^Zz61>*JcL`}b2q6x7|RMB>9zGeokL zXsF=MZQM#~Iu($NU|(-DQtw)Z1jyJ?QCB{ZqEbFE6%_$xsTnF`N0^90G8KvPfo;MZ zLb}5S?rb|d=Xafcf84KE-NAOw=ktEJuIqh$J_tqF0S^zK#Xm^96VkAL$Nv}AZVL$d zvIOT>4qX4a?4Q}AqR4cWRbaSL-f`vY2C(jJx`SDN9+U`#{oD~UNfqgnt3CwW;RdwZ z^?CXaP$v0%a5H;>pyF*;&fK))j6;6TBBa`$>$|TiOOD85^*Ejt4nbPt9wt}|#-Lk= z-OB#X8jad2`EkahLfL`#5igr{P~#`bkGk`fg7TY=@t9mvU)qrNyRYn4+(rIF)kY7_ z-iD)m7eOCi^*`Z0g=4U2jq6i5cHdLvI5ff_bG~xY-$W-IuMv{47Y91jnB>S0q4tme zAuQ3IFjI2~^GIR>fpfV6C@BlaF;Cq@lNtzrGNePr-tS&Cq{;Yax9Sf?f#AeB=5F&G zGwq-8*?!qRcjA0*eNo{Bh#08&g9K+lF!WE%$M+k5^0xe_-Df)=j)S_x-3#!4S4}M1 z&@sH@>Q%?B^px4|KipNh*|UwSESu&)X#Q=|KbJI2M@;5;R^nO=&-_Hy8}2mse!;hB zhy3N;NB)@q1y0vb#{mTmJc8o=wo?(BJueF-KfAw^>p#?eV?L%RT8}fvAn%&#Q0o-7 znPoR+r@1(NN>TSA<@*Q^FCb)LI(gX9Gu)Q!=w`T0ECCY|Mm-ZW65qKrWA5LLA&Usf z=xLpe0HCt4q5C`HP80jBqd;QHafXQ$OlWfvUm^sBR=Ar04?j^e&X|RGMwy+FuhrCzhy%N8xML@XMBE#xRnuXU04FfP<@8{QFa8?kAj(B zyZT6(!0cD(lRfieAxYpciSM_G;(gwS2Nj2BJlbpeoo#+@fXo#M4X?bDR}b~*u1MzM z=pETH3UwV9iY?pA<6N=w+^@1l`VB>eSCz++iprzcD^DvWsOZo-ma2r~Y~$BxDwGqE z@>7vU$e`IDJ5%AJUQwjor`#7~M*=~YzFG2n`qBeH6u5K(ZEOMJ6Mq7tA-{x+69~2Z zrh9`@iQgKB7VZZ%aXLOnc}I=}hli!mE}Y2kJCZh6zgm!vCcDnRP3*ASZ&e!ChXQ6~ z9(Jt4KuS@|M2Ndv04!e5ZmWXp*tF3xTsYP}J^S6jxWOI^zO);=w(|nqXtN;I7eiiB zpiRgMdMe%}rueRm!&Omp<8c>>%)JAGa2n=Sl7jB%o{eyeu>pW|wk3S_$)ft}#uMxq z7|i(1FqV~|(cu(yfcqeve3b&#p7Ol;M=egRg?&tZeJj&=*>sSHxmOwlMdZ0K=fqrE zKejI{Ziwd(bZ8wOE8cn~qA|?ax4feYEp|4FsfN|R%R?2*hqNjG86|os);!v#&+PE- zgV6aC^H+hQ0j-F5DIa~VXSTrfFeaD2d;@(7hv#>&Gf>!?uH!O zB;IQH$uW~1kr-!)gk`;k*LtVzM{!a6H0yBd%&%_cH`*WKKA4m-8UjG@Z4CBPzBPFr zU)|)zQJoTD3bhAk@>Os3g*nbSM?;QW!oO*PsKLen%tm2NG)Hi_AD5nfu`m^QT`thl zkCBqit99LO2At1T;v1ERGqfhFpdyR0KeC-k9YLqZlsO)!7fp8y*KQQz&`Rd#yjEEU zJG3ei4^fw1G$#9fV@4AGG!N-Mzot^pD!cgnBvy7r(%^a-KX=$f#Pf~j5xG9_0`_mb@?j;UI z*icX6Gh!|{Gj&r9rmA_*RXLtGjOx^j#!S3tOnF?7N#Kvd{UlPwi&YC%(=g7Pip35n zCH6;wI91+Ce^8h-j0g%F;<*RYpu6nnu)>aJ2p0;Nw)M*}fz=kYw{~RiB@fDvs@i@` zNRPKFL_?yzvtJ%Z;tBbeVmXQ;+f;ngxYrK`G!gN9PI{Z#okEE@Dn3eCC zJyp8g8iGq{D2-il6SC}AH{&`~)2)r~^Eico&CAE;4a6vF3|u=#6hZD?yS!xZ#ynW% zKFv;D;D|#-{f%C{7 z7s7F{>H(i{I}G&BwwR2#g&XfvxDhxyy6j0}3uW^<9mApXnQoz(zlG)|93zhWn=Hg{ zUSZ!x{+GZwB>5?Ou3R;;+g>unGZ(WP<4P`^{JAHo&B{w|w!&hRk3qXh>Vkt!z+j8; zBO&m)k_D(^8e8QA(_8CHBg92n4-2T9nC@0Ry&6~|@{B~AP$P=9`!0Wako>W`>}IQA z8d*}LJ){(a&!j>nr)D^RJk7=;8szV~PEDbvf`H;&@I^Q;jsxq691A}oiCAYE5ctgD zt_6`*p1%Aq|HKd!$xnaW3OrekwLfiAlR*BNM#0s~`H z9o9b+9c4D8*uHxjuj9ERGbl~uQ9%|E+n9;&UwR*2V0T=v-k}@;r{%lPG}E&W_r+<# z;0A@C$RV8j5Zzk;z+r{8LSB%)u+=8xnp+!r(_VQ!SDZe;HxGz1rzCfQ*iF93t8hM->zE*}MnBu>6Dn;q%z!^gFV~TuDQ{G5cUgCNu*Q$0y0z?J2km44~(9w){*Z38NMc)l-gY z$jgdbS$7W-!W`ZYovaj1&oHvpT;FyKHuK*mQNmevKNJHa$d>Um>Mm4KQjO&) zL4%DH(4!zqTXs>7Fmz8%BSd6B@T3qy_uSLtV&}-G+E(m09r8lXn#&eaKfNrysdy8N zbqN_EC{^#uf5zkm3aK41RbJFyX|06MTNMU{FKIY>Z>ykd7`g6od8t`3IEbDKbKU_@ zT6R80wEl?E5>WLdxEbWg3{p7aa!C*w1&wVB(tj+J4wKUtf%D-qcfk*p+k);7gxbiQXM$QS^02Y652Z-1NeGu{9;e~3YDO4Z^h{$_kDNObijVdJ>A%uAA60b zl_4NRY4~B1;dHQuu5-7cXB6VGN73~F38khaoF%p@hDFF2I;m8&{!FBn!&hA-k!8U(FxY9c|{q5Xf04)@FT-3R{>ABE1%e~+}f1ht~@w!7DAv+76S<|pV@ zh5UzT5^ZR4dbz-@rAS*nE~A3cTYfX*O2u||9U_`=_!8ZpqShN}SZ+#@dulXZN@&Ts zPv%=D-!6vWkO|j@{5A}>!ij!`**nUytO-MjLjqHV110to{(yKPU+4mxdkBVK@16zB zFbe8GCO)t540(Cu9eERqiRqZn3M1TpO{}j(Nn)5Y3NVZcd(mRGU*sQ9AQ=2pZ>7VF z6NfnAP{{t#tEte{xinV32M0$V|IL3j#B=uNfY+`3X%GxI)S}@fnuLx_NZPB6M^K+| z6;Y%5BG+lcEr=Qn1_UrIS_p5ovt#D-2E}-;(PT`&TbQ3d$HPzG_yR|jg-L{F>hsSI z%0EH?V^&Dqzq2gbF z{x>vH-yHR%zsOk%k3y7tLI?RbB1Sz7FSdKZKL^?NDz_g=i{)O$e@%KOn&N(j?xukQ zj6C@A?}q#ZRM#yH%=_F_lej9C1izI3gs|Axb3wPzM=7^oFE3;L0sj8NsGOamCnLx` z_>pn8zxF9`mz!7yP(2lmD+2pfI?Uy9h`uLcr@#9v=8O@73NIXZmC(KjcNAU$f1D*w z^(k(ar1roTp@Fr@ggq7J27{b2-*t%3^GVVzI8l@ad;)?H^7R|N&mvPtSWTcg(pkbi zdBVLlp^%qup`QHEEbelwaeBA2+ph0E%?6>%hT(rHf)V&McfGX^OF9w?!W$u{eCi>d zI-nN?dPmy)=>66lE4LgHGn43ke`Ls7N0i_coro--kHh-;pM!~Cx_;_6NThH>j{$nx zVdrnAHO^=OTe+NYdHo&xN6{hHQ!ybE-2r$l+0UwE*f_o`Zy?%nr^|5!vIrv^VkeA( zVT*9Hqzyg@ehw7Hk;3Q&5#s!U?P@fgFpTy_+?2hbove7XTRp=WJrF%~f zaVb^zuKcammLEmJ+z1@AumM0|CxRC~=Bt>v^EXSHa^ZUV-8AJdKpfI-h?V9Pb)RMvk-#W1;n0@g@x6{)enfimiSzd! zFHR-!y1C8(h?G(PuuH)FncvDMJ4~?gno!zRfF_zK*ZFZ`K|fRhwT45M{Q5@o9+no) zAxsAzA<}f6jZts&GeLac;u@iF7#;rTkxO?HUSx1dB< zP2DrCgXn-)X)b=bd7o9Zg#7m5F)EHP%zp}#@%let zDV7Paw-A7wgd|;`C4s@W)AgyC$OhqVyKC@6rkb) z`vJth04OUGr!N_YH^_!o*!!fhaQTX>iiAr~eM_ZtiwgHBOJgJ{?!%~f8bB)hhwPPg zcQO~^$Yn8*41d&aYz)C=aZ-P*Z>neIBJMpr1k~$sn%%I7z_i2#tK?3g`M24Ik7Q0&*<`mux}bk>6Z1UZ5m4kMFwa(?NrS= z74Od#>?zo$ICa@-j=t%nr)S6m>5*;ZQ2x4;piM`43$WcNowh4ESbxwd(p5cBjM49? z=Lg@Pn5a#P6RKZ^%AQ@V?U*M|DcUNp=w4J))xEKq7JtTDDzmr%)#Z8( zeX*s&NfR;LR>^VC@~xt8`5^wbT~nLc!wqM$+wkhmMvCrhS=>#JYvbuJi^&(PpZElG z(wzK^J8cQ;Vn$|V_DNPSDQ)}!Q)9QCzMY^6qB9c79kjkHa{+y7deb|G)@ATe{q2@9 z1747pfQ>%?wrTNw{P}r`!Z1tq^sx(TT=C@o?KT}hL|^C>DOc4^2{7Gr2k6gsW%tup zw~P2cyhclSy|_)@_gjBrQD0f0>4sbL!Xx4hc0#)6Wp|H=O*={kwtaiDi(vh2B=fPI z+9K}cLZsK)#aXhJg8poxmaK_N_o>r5R%f-COxs22tfg`C*V7sQB7Up*Nsn#BeHng9 zay&+}CBK&wXQ@5f!OHd7uj_w}2_Ox2Q%&KwtR-(Y|B8s1#L?D_BU6SCV_w+OwV?H-Qx-eMl_N`-jiulcnV>4RK(cx5!MU&-o z4cbK{5(RYKhN5t0)@03gaq*1L&5fmEV{N9B3n)W;};$CSKcig#5Gw4ZZIuv*+^ zaVh)RW^Jh{d7Gk(6%n_+B1_3-F6q6t?>M!%+&RBSyPi`kI#`iBHhV&lDW&hN0RE<1 z+_uQ4>Zi}UVVKLzxKuwZ=2Z3%QtpKRiy|M(JS&#(37 zu!H0&HqCaqxi6Es(qLS{oKtbz>`#1ZI(Ifdh_6L#O-T?hpi{5ruTIr^{t8sC!$$9^ z;OX;Y`D>NU?yV)Ez7Old2Fa7M-}E9h{7Lf8&dY+JGEZB<@CduiQhh9~;Tqpf>&$`CRwOp{C@X z!LkWN#Mkq)=J^r=xm^_Rhb)oM$BW4AlH!;j^E7660P_lRJ$?+yd_7sd#T8!_VIZAM z0JqO3HV1TVTu1-vB$Ts#ZS=>*q>Z9p(L6)pGC4g#%8D32Q+>ObnYkl*sJ^Aqi*%Ka z`2+N&_<(&H${bOe(jf%8NIY3mTZxUfcl3lQb5a!k`l^N`%iXF5g6`KP>7tL$=Go7R z#T{-jb7(AYQ0MSr%G?9SYf*_gzt_5Y*->l)ij=pT@y}}OQEQ6Z_nYN8{7hY9&)I9~ z4UvgiL`y*^y8&SlaD_kG)|uq>#WCNO8N->Tu_V5k4T=(UOqrBbDbJWEm=R%SUh$k>qjM6TrIW^X4G&KzxcxQ4M5k$K`{-oxASo!(5^6~hk@cVqWYn3A`OpY~;D{bd)|EJT{i zviQjMV~**}c@-Zj{itWK-us>+ED3z?ELWAoXwrZjno%=iiffPhbYgs^J=+Jg&W(*AYyS} z$x!N{U0nUBGkKEsZ3~Q|1{v*5{~yRVWym0;RIhtJXs zV+SIKuC|gETSGZrsN)0lFLkedag6NY(isl5M{}AvX=&Za2eTS1M$WUCbUMJt z1`&^u#a@;RVV9tJ+RuHLv|W70S$ZvP7Eil2`hry3odla{Cpks2=IBQ_gUM(Scpv-%YTKT1jRE!PoLe zuefZtw5FZ>=Z7@59)g`_wGC$H*~HA(p#e|Lh7Ctz*#3yA(ju(RGj|lTw2i-JD*rBJ zGtq^xKZx8DBSPzE@Va}QGx1L*$Vbc$lpM(hK8Q4;Gfl`4r_*c7h-}8I;p{Bl>Tk8)ox<;x4@BdsrxS=ZtLTF~^D6WdvCxr+@X1HB`Yt${+;PMXa99$Az=0mrPUH zl@u9Bq`H3z^7oty`gwxl zBKrdV76Q?G|tfRev-@L)e+yC!Tw@t!eXtazzl}I$xBhf)^3E~U%sw2E5 zyp_ztT%n(8hl$uCsc=lpTHcxnDB;u4Eg8~8W(2Bv9921#Z|k|}N#>YLWVh*cN5dGBuN9NW)Z6~#TD2deT- zq?!QC)3h@NB%hoPiQ&}R7hDK;5U*g$27anTz@102S5G!3Sb}#aucbTJw2)clG0IKc zhrXr5q;c6Z0L!e+bUmPO4(B~gUu3y(C2}jP2*7DHLH5MV<~9=@*ypKbw&1aH_qjlE zSMQHU`H{bysBK2tGeK9rN2A8PT+Vz<@&QGO zMUomI28p&6xpL9x8=lpI-c0qPZHIS>4RO1}rNxp@&^@T9m zspMwGGml6tyy8}@TC)zgoO+Su&k=Pcf&8B+nE(tynu^QY@<;iG9VLfJZz1*eA1H1nt;~5`Kb4KlCoB@i8%f)N{33vLUCmk1 z%6pw@sN~X?9<{=b0B!b?W;KeU+=wr{0#rox00Vt^K;lpe6>AbcV`sQM(M&Kt3G?5@DhuVB0yI^zDj%jk)T#%B7uDS9K^REwR~s*`O&;V)8m;CbN)0UV*>hJnozD5)t$T9y|2(L$wq5= z>@@09$CLz`;-8-yKnSSsVuH~S(kTZ4&VR`aZ?mqg6LZ@DZd&n`nenrYHI;w(ZW~-Z z-VpjV^!%#sn1%GH4bs(2Ja)|3!vsj1Q2_H}xXocrOIhlA)y)Y^mPO?nH=ZWj)ug~wRY1xeOzDC3{uO3 zS#SZV%SPX$zl_G_{q$hf>-w!-X+zt33mk;<4E7`m_1grznk8ycPgVZdE|M?veHyGU z!8T`lyds)^HgmQTf7QPIEsJrZF9hH*YzX-m0u}vpNKq!YIX@xicS9J0)f68+rB>9E zalm}8ENnIN!3#25n#ymHlzKlAIz*6sdEb=#qkOLeRcKqB9|lVQbO%W9;_>xY@yW)F}d<@S!E4+K|EWM-A7Ii|kUrIw8=FUFEz5p8NZ~}6K8(T}d%zV) z>j7OZ?RPDpf9*;i$(^D2!KA$BY^@^c(OP;4%LZv|ZlnD!4+5mh zQigHI&^BdDy^9RuWk(|ER+jZA?qdrY5X6@fj6rl?3UA5J=K66vQLcO$M*>-YJGsfV zw5kHE8&GAbiz5E}NV=>?ot8i@L*Of#>GgOMaSZz3J+H~EDXX?wnti^+tQMz{twuz$ zLjdZGG+NL)XjZ2AJ*74I4pziQ*?7$zIk2LstmorEeHHe-y*DS4&V@>)?PbKNnXJX> z0~UM;1j~1OMDjU(zYUfrrfyEsaYLyZw6g3nO$PHS!8gSonavNj13YNVF3LQi4Cg2p)YMzpHTm4u#5_~6>dH_}2g|1y z+si#iwu=8|{m6$t2|ExUAFQ)s#JR4GJ8X{C8@W4N7^v`$)c!uIpFFi_o4t7BzC3Lgw1g7uo3hL$uOXal7-$4x8FiJny35Bdw@j$!YMCsbziM|3 z+twKY1{o}Lhr$HyJ$m|vBZJv!Xcr`8PFIVs!C-m`+C2e8$}co*zquU`T#%^mFYCTq zM(+Sidj}70%jR#1-vDNs$*ybBi~ymQh3c<#$p)w>ityt=(ilZo0Q7m$5fnPxgO1Zahf=A27K;1uF6)-PX`z*@v-R9~1)0+YYv)tbTe zM=7_vcmrN+6g!gS|HU0bMiwJ{sT+u>s5a1pgy*M*^2BaYZ0AEWk;9LQDJ$c*5f*IB zS1szn$|B^D7}TH5tQYGq-5BSe^=Cqlny&|s(4*tKUb2zwzjyB}qp#wV8@py?Fb~`K ze@*u^OxA2Q9rG4#F+GJM8`&cH+{dp}#yg~{JX#PuQi0+wY2N~IQ9AT1jASs?c z*_9ru+TtP%vIA)rO}L`Nyz`mssl~Pt4^#4F`BvTtaWBp$-wsHorqcnvOHJ`ueTYcSD8(YJ*%Y6LsA25ZJElP)z6)2Th(Q`zOhG{B5S8H~nb zhh%`BulQ=W>f(!4!`iGWAY?fbKKg#@RC@LX`32gC@>Gt}Dz`v|dg7^`%lrVGDR1#f zl#6_Afy%j7=Vax`7H25Cn&SQC^R2PbHwdhgwAD@-C?RLR=*t_)yn)0G14QA^wA(D@ z;Y0nI!_c`a*XfeBm`*|}$thF%bB9p4cRg4$MD=}F;uw|ML_Yhnw+HV$5h}O6#QW2B zy9KN80NJZR@aNfWSow!4{x$9Z_Qd35Mao!wjfnF~=yNUh1WWf7&R~aXY+P0~@NsDF z@G)V7OiQUKf3gvX;}j~$>OwE*im3z%y7NlQ#wsK7j;2b<>`5cjTBn+ zAfr*I7Y&iYOcc;nbp^lcFv!#4H8J9S zZWlpj%41m7QCYzbii0sxOD7I!(sbUOtQ+` z@p|D!6SHbi9SQ-mxL*Zsd)Abkr#1oDL63t(W9#Q#@ z?uA`mgNa2pBWpwNE^QC7teYgA$b2$}8cf|s3gm&tiCzLS9lS9pgV~8{72*);VcJG+ zxYP)|9?$yvG3Ozr%3eY+eC3iUM!DUQ+E0JT;~TF_={xx%8>2Qh8RfJJzeuzrve)5dO!NB21&QA@)&yY(!zMTRGhbSF zkB@;Yp(r}V800{!S!#&jDF>IZmI)iU45p!omtVLWuvWK!s{&enR;I6Q8XJuI)>Nig z!TjrzcC>QP7(zrE@cpe22kL?=hbhrOl_Ie3!e#ujZQ4m%j0(AJ@)vHSbT=m_`F{Gn z4^{=XHTxvGC#W22!K&-eJhqw-KhxVR-fV7&zS0rYROJ~VkDE#Y$%iI> zv+0;;iCX4#+L!HyqBDOOx6c8LR)SgI@M`{F`b$rK+(uO(nGWdGys$kd#Qsrd_cvZhL~$5pk7tdi1gDyvENPB2m~a6S++LQ zKkHN1sew3lxp0vF#Gd%=rzQ3lO3sHTKk{{Qwjwa8fwphg3 zyz#rUi&-1l*%y+vAX^e3e(sW(SEM9iK@onBh4Inj3{xXLWy6s` zUE!YiZKiYIeVX?V+&>GM012k5CM2e)auU2=1D7M9{nyGU$9 zh52qr+93T-uRLqc^HcqaWmIJ#l}J?%pdNI~=|OvV$8K&DGPgWjcG_IurMyQYPy3tZ zx2xY#{)oLwzfW~o+J*n?F_O>Qu#gTCo~l|%{p9S+fy5{E+8V;;Qd{^XxdS7nd8V$F z&u9D*Bh)j9Bd^WU3}&Zas(0{Sw%H&6S_^(- zGg2*W3?DqoH;N=*(eHb)Fi=(UgSR{b2ZD@B%NyM_Pd~=^zY6Pyj zyOs)OuHw5*HpnCqz_%pL%F6Ci8GI12+?Nw5Md6m3Ktm!?kP1ES5N-$HL_K1CI7o`- zxt+L{-oy)J$sdFfKyN0B<8uBJwZiIF9|-l0N1GsSVL%ivYo5)iFAdqPeWOH<_=3jMJ2AJlqFE<30 zRjv$vl!;ZWKa+aOESl7`hS`X(CoMjn7Q#3V)S>8&VvmUWtnash;=hrf^JW>R;*Xkq z?5{e6=G2H)ux0sPlis#dybZ3-lg4!U7M|>4gUuq02eR>~ zlnJ!((u<^#`mKO_(ptzp@1a0QT%Ks9%*H2<@=XT9oB<-h-vtzqT&fz(F0PvyL?-!G z4b`7=tQ@O4*%jMQy5jlyfz+q#C)J?KrZL~NJPc%0QH-pZMU($=RW~_%ypr2@$7 zz6qn?`BwEWvu>=qTJe@HA5;k_F_>KeEadEqIj~L9!5G9zj~sOK25}I*Y6CYnD{Ed4 z8c$68_I#&jf->@GTCl1bR3ZfYx6Wzwh5A0nU$SC9v5{FxDM_K+1;`n5T<-@F^XrW@ z1o{cL1N}1Ei)r_k7Yhfej(5pGzoEHPG~Q&?Api=r{>qKWxy)~PLAk}HwG``kF;|7W%><4C)mx!1Oq8De zt8)!t$0-m3nHwTo6`Icf(AA+I57G)`>S$BRD;g^hzYedW6zE@A6%vy7S3lbVpHvRGEP}8!Zh&DjKT}xXos4qoSCBNr&8lp z)N78!Z_(I&1ij^j!k^oOJFg| zD`)>2B2+N}X8#x1ymGQ4%`5^4(*INu1uF(p<5fGqImE|JU_Z?sBuMHj+WIv0F3f$@ zUCBdKdywM=EynHBJg?P_8zhEg?V{N*-I?!>Zl<35Y_yT}O=MKFRAafzK>L-;iPWu% zGvB3bA=@dUKaXc;{2(V0|FNyeGoA6Ks^#5oP2VVAD8{#JII?izTKO90+pGBiR-j)J z8r%AGNAg%zv6F~7^<4_AHmY;468AvVW(v@+plf9?cdC^#7tH1dP>*{|$L=a#VltTC zXAfuMF!W1`A3c@+Ss=t+j6ty^_oe}}r66VS?wvd6a-h9$U|liY$1Dotw=#NEH6O_7 zgjG(>mj3V0PC4UM(-RMvmeJAo$y1hge2F~1=T@y9;-pFozHD*>!9D zl#3PQT(VZv2jujXK$CVq;=jJ%nS8T=UR4d;*@A-gQ23&)F8)r-;&i$SQJRRv+_3YB zh=e!AV(h{Q!U;nGxv;%_GOXGPx)8KM{LCjB73KNT&TrM?I=wAqxo-bVIEzaV(KVP8DH5wD)tJ8JFhW45djGL$vW`N(?uMaciPiAS znqmzU8r{kElV(>A#!rG6U~*xW5k0NqW)0Ej5}R{d_5{*7pbF$Ya5{_W(lYNNXq$%I{iCW&yWjg0++96I5P~6)R`(_TY-#ZCW z&5A7_w%d?SN9g#GZHroyH}S1Valn8E_ZiC+Mr;R-Z=yA{=)c14+2!2&@vxW(Mn7pwfGO%NV5P9(%c zY#R8t;oxpnK~v-)3Ro79l6;l?ljKL}cL7w%{{}YOS(=0zP&)PZ98HEIe`Tp72uLV2vji3M(`&M>-&oN8B2>l zAa&+d@*x&=4tC5X1ePn~NGKZ!YG$e6lUE%%*1e!M3<`|q_;-cd$mSTOUv40)L_IUhs;u(*~IV}F~I3$KpqL{peQ zdAmnVc42*HbKEd?l+dan_zskR=1b_u{pu3edP}Pd%~j<`G0>PaG?-~G;y=&6)Euf@ zls!hTamiPQR-5reHhjXys}SX>}8f+_~)WVLChVpK7joiWb$3+QmNt-44F54YtT&6h!Jp>QbIp^e3Az5qk2{&#xs=g*4s3<1MNDHUgeWN*I?c zt2Y|bviLAITtMLmUaT6#ofg!%)V`DbWu>#1TX1LZAa)rl&E%`p%943hEeb8);y!7f zi|4X;0>i-2wOwA^-qATr1K&ztkbl-K>}D=-v$k}-Y9x08oLSqgPqI|Ojm1s_P!abq z>2KaR58Y9D1VfV)(91TN@Baqqb&j>K>o2}Y8mc-4BAEg2A9V{UBM~In)69Mg1-4!k z?<=kSr-3}jFj;XzH-fv{+3H0NE&&K6?jftgfnGIMcqxuKZ`HWIg)i`L1ey#3X5}6z z3Zx(uDg=u`6L9MkD;!^o5f%U;pWEgM5=Cv)(&$CPh(f|nK$%kTHU zu&*K)BbL^{W}}6riX93_l@Dc`T{(t={O_APM!)%nZDmMD#25mstw$}k3AC1q@+0e< z1YOgRGZTz5GMgCh2fPsua#h(KGr3qt|%OCdGdL&7#(5*>Q3&*HBJGPmwmT?bCmBSrqlweS)D*Q z>6t(gMj>Y^AEXSzym}#OzHP>8#7iIy*4Uw*B* zf{&4*r0GvSSURTdTWuF#v|E2jr5GlC*eB*rwTtY;JUAE53nCfHduDHrlU}_c#h+;{ zOPb3ZT5F#O!xjHpQPv_5&}*m#IXQTYb5H?Y@!lah(>=pM++53Z7uGb-S{$k`s)+LA z+rVf)2dFf8V7D28YDKzC#5M)um;A(iaxk$XyQ;t9acYlRw3ItrleF|vm*9^6Ym~20 zkf9TZqAh$Y;_Byr1U_d-42JY1x_68ixbW)Lw(-gnMX?L%;FdiNbUnr;rsWvNrY5S& zYg~V1|6wWba&6BI&CO|f_?A)_t^BJla)=_{d;1#Eg9=*)AD2Cg8^V>MS?p|3%wP%YtAHjK(%?E-)#K2W`i>@vwD1A3ua&)OvWcxWci5dEYS_ zX7Ze|ZMbnAHMnDLQHiH;7?db#Fk$GH#0Z*+|Co{i#9bhDS&Q)(d2wbq1{z8CA!P#X zzb1W*k;~mVuzFrZgXaqYUkMN|{jQ4gf&2rLX_M(GR7dAmU2uN@f9X;|d~&)scGCyO z@V-&GBsRU$n8;hIt!o%Hf>qlN86xnieI~Qk5u+?ZJWx*n(*7lA?`5e6ET)L2;H=EY zg_GIUU|V|;5UL8tvKhzjwl0ZYP^+FKJ`F{-2>wefyxI%KF2%Sl~B zTjQZi!jHXd_B+lQWtG9q5q=V0D8U`tn8QaZ;~u-d`M+Yh(4Pn5OADdq=y&eXz$Fbc zr}o%)`|}ikGX{H7+oWqr8`$h3d_3_dIPOJM3A-I;J$Z^^h$`>N3U&VSs(}I1J!{Hr z^O^sl9}@EH=pocceKCG;!gyih%f^41Yy9dFLor4EyC#Ic^usRT8P5( zdDcdnZ+0h`?NHB@6NPPDoPBvH^{6{PAj%WZaf1Ls2{mO#C0pJwY9w?(WaN)dJH;=26)o)ltN?9bR4K8OO)Lsy%o}u*uh@AK8WvUDNxk`@jsf@ujr4gO9M6Bp(i5Amq*J7 z%O3;z%|{Yb-6(K#u2#%aR=B7!e{|YPq0_;q5S~R?tEaJ_Bl!>*23dS=Qw=J%&C(A0 zp}y?K(z%Qlc#!IVf9RpbH z*)Tgj7bMOn%hlotQQoNB%i!;ERbceTFQ2l^Zc#Ae?81>5Z2o|~f?hs4W zWYK=}tq+jrV-gh+bd4IdKIx5PXoE}FpE1}IxxsPMJR#VZc;IA6@cmTVVHYm?`y6A4 zTlZ*Ro)MNG@|jJZHP?M{pghU9W{|$%!K#t^qOSS=`urEGg4-@sJrSAygjSw>gxvGL z-a!bb@&r*ly%fAA^Pc_oHBFC~qJ=?bQJFfM8M`C7A9tZ^{%fjT&cQ<2=wSibB%T#&$9)MZ5{&9NP8m_sO?WSR1H zRgtG^G&>0R$yBDIULof8l?^0YkYMkYC9OW_@<@!$D5=s}i!u9w@5dBQZeJCey9-5k zOd>dSB#;$`zLYut)rjcX_j;?PVyvJEBmwZRI+1z zf@}f37YovwkXvyrY6&zW$L*&jzjh*|FTopi1_Mr*8~W~iCW4-*$m$2&x|I?c0SbC56Md~_WWyM zrOHrgqwpRL7wNDOm7|q@k1>%6>XZ00JrI8LGkj{YY{q`e#1=!KGPCYVAT_T~H$YR~ zea>K;$<=@0SpoAj0eqB|QZF-PF6E0h6WSSRmP#-z@i{oiO@F&d2F@EpmWw~z9Tby4(e_!RBOxJg44%^9oB z(ZDW>J5aVBh8sI9F5&EzI}M4G62sqcCd`%?G&Gzt9|3?jgX57V;EJ1l{MLEo;=aj) z#AjX}-U6&BLm#6?GDn5+mCHq%BS)xXl#05GuTZh=JI1r)d~L(n4Ac(0FpQl89(fTd zPguaSQT|_EpQjNjUP|@^e|hZs#Rk4~`-zM6*JYJ6g)HDE`ZLg6D;W!*vPbOg!O+=RTVgSpoZPf>6pxZjOEIigtj=s zPDYP(3HARIJg{-e?D>WOVJd!nBg`&m9Wxo>L_^${?2=6(iLxE^Lcus{MsKfI@dF{E zLQcWM!kMk0(_{GTz@|8B!9SiUjRhnM;ksFJj++)l{e`HH#!SB)0Zet{KfQ^)Cjnwv zK>)}UsK?^IvH{dbsH91Wqiaidb9*uM;yl&i{}>oxA|vS74EUAOfhE%fY5FH%8^Vl! zwW=j`0c}UkEsXd&n2Cn9Te-z$0w42)C=c39i`VtmCrAg$<6IH`@_FtlL&(pbPx2$> z&nE@pI?ts;rNUt=(X)*~bPC+SWPLrJ-_$NE%I}i-bEh1!!CV#c z#|S$;cjd*Z8Gh}Pp6^^(`|t(kn+pND`$d7fX!<-MIx`eL&4y~YMtyDl*-5*TcG6#m zCc#*_ktg7x;4K+-7Xw9y!#TRbF^gSbt^DTgC+#r!ly>2veq6>{d>g7qGJ{*nF+cVh zX}O^6G+=*5ZAh8ROkW!^k*Naal0}FT%t;tWr(%}Qj=`c5&?wW6YZAGSYafoVjZhZB zL?^bxOtd>AWd-wZt9mp$uWpKnT9mpeN{gNbyR07%`?%`-0|-(d`?7*nzo3zhfgp8y zRRVAPy0`hhs(@BwD6DAiJ8i) z`Gw#Ipm!^1EsW=?{EBr0b!RnBnmrjD!r4dC->feQF^9W9%37YfHEicm>2})$$$7Ru zVhU^Oq3eH>pS8^Td*%VnV9hZ{@MTh-@tX8-J$1$j;`d+8Voi{C&)>bXbZ=_{w2cPp z8>wH2eOExt*`iMwB0Ov5(VZ%jTVD+$Ruk{6vj zSXZW5_zszr=I)^#hNG!pxR;g4w%a;_v(Eo=y_P@PZQ9wl_5*eiI+rp1bDJ^U z5~n$<8$!8uF4hE?Iz#$Ow$0;Lv>#l~6b0{&3_5E(YAxJC9nJzQ6ZB z_W7_q=Q(xX_c_;f?stckKLL^M&1Q0iq53IRUH&VT*XtFuAi!~0wbJM0yM54HI zzk1K1j2PSEfP#(K@5@P+A$=hJOmN2k1Kyn8#}GWULGjyuA%3j+0$U@omAKl7Q|v3o zp?bwD8o>V>1KX`gx1EsN(~SE7llVa~2H4!_H|-t|+pT3ffwDrWfQq+<-!1TL_N(xw z_D$fx+5|LQ{TQ1!&U0yRIkLx10B2iW_q{k6sYk6v z1r)Z(=1+J}q3gTq=g@5H#Qt*Bw~y|YTzgjIrY4cM6WN=E_sAL$R+Z{5Xsm-YNKSpY zrX|*+Bch$DczbPACnyXF6;+q{+CMjr?IT%+x?)|QAC_sw706!xXXRtcW4?hl`G#P) z7RxpZyFuFv1I77n#U4B9ThdFa+t%yGC+0(&i;6wPWBanjQ;5#8Q$ezRn%RF9tPf!D zTOY-?>4En46$)r&Wj#||6>7g7cN_`wY{gm+WE_dTy}5RK6elp=c?XgV>7PKY(L{d@ zXFgmqf9d9PJTpb@<;e(arF27QN4Qo(PwEya{}9x##Te##gf{N;m5XU!Q+B*1;eQ3zL9;FF~crSsw^8jK|fiYuNRD%wy`(J4UY z%t`xf2Si71zHc7=?IU0gAJd#v*PfJ+8FkVV!vs9x3k*&c_ik6a7nyW;AuJMjxp4@N%dR>i-97zA`&`({U!vj!Z?yjfC6-i1J(2?>FLbeRet$F$~1ZMS%6p+?;&+xC6 znU$RowzLD>Od4Oxz+XF4r$}aCl_J)>7wAOsn1{(#1pdUV0`R70)a4DGIHjg@>+C5S zX7jtvzAZRaKcG(nzb=?k=73%w;7sdneSP~F3Z#9w zU#irujpo7A`0rG(f;vRj0;Yb!^{};Wm?F@1Ja?jke6Q0+C@}B>`F_UC5t%qNw_eOW zw(hv~HbtYWTg%ZKSqqS*0ZsAV`c-Lk0&n-Z{s*=hNB#3OZh1_BSP}Gz}2IfaWYU=sn=sU(>v2=IeKW?7M3bt z2gitO6%Sl3gw3?$=>~ZJFJ!i-sjtteXfIA+$qhH)P{T+UvC5K;@Dk{=z^s-hm*5a- z;E|TRW5wURa4zpdC_q6udvqZ0wgrZz8=4xx)QGitQpY&A;{vXZ{j?vlU9B1ggc_!m zez*drWs=>O?(M|6GD;^cl@rH6?X{&65L$6hSr{p(cODN`cmI04dGZJpl(fKo%baaT z6Bq_$bnJ6;-6lY*R3+xPa}w8*DH@$~dO(p7@UKw0{lKSYT4+q@=LLN{z_EpwZtQrF zI&aTI`Wp=oNdtf8RP7_LD;&KyX#-s2%GO8ge*|}cc#i$FH?vmz6H%)JKzIW6J5H=76v@fZaqb2#%%2d0H?1NHUodjrvS&(nxQmb z(^LFgo9v*cfX$?b{a24;O5}Kep$QXrYTao~$|u3cRqn5e0G)$C9#soex7PhQInCxL z!Exseq&fO%+NGP>J!Jk+c&6LE4PdGlD*`yg#3cbhi|gLQM;nN8KCxr{&;LdFWm}u@ zxcT-AWO)mKuL5YH1U%-5b8tyRid&H9J-5#V^KU@-@$PO90ENbsAIL*2Py!{r&)5T+ zo56r0qxR8-PXtP#41v*o4uhE!mAYWXxho#5suCz=Tk*~z3i%IkPNpKCR3KRhbR(`> ziG9?7WEAkblHxGA+8s{e&5vo)<+$HAa$`iQXy%E=nQ>qYZkC?Er1CW&qQ9QW&%l;1Qbm;)4fJ2xJqWdH`K1<+CUBo9Zff55Rl|0})(~}KSaz9s9_j1Za3Yw zrt!jcdJRjrjY!VmoXwYWFAo6vOeKelAhQ55yG0p?yMfpFY<>_>3fMGl?U^sleIa6T zT^D#J4!FzED51zolPpQ0{^x7G@&W*FDG#|yfK zfoNySyU-5S*J;CVUk#cg1DkGlo5lo&_l3Xp(FLf3O@PY9fXuvldgki`8~Z43V>!HyU*wuI4qVbfu%>f$=t!m9DuW+80R{HT=F^ho4Xcijux7%<+(uj z>SRMcKHwft!9DH`bmw}2xx;ldw1Jqm19nxdPwra*a|>{5P_CiqajtN3iob-X0jc=- z1;82l$isBxaJG7PX$&k58r`UswEtEiBA{ApfB^&%%dKVwRoa>qkkI8W&rdu>tCM%i*F^69-%=RJK(Kg8lYdv zdM69OD|vE*gO1(7P^pyhZjEyk5vUN@qfyRzG6vnUw6x&nw%}Irb`=YBl_8gz_R8gc zt?!S{UXk2y#E)%`n1;-)cR&2`DUZH>$XvNB|JFV=uIpp7I(Ap~>jk~J=e>z>$arD< z654|y2ik_ZLIEa`mIc91)(f-e7V%y0Om5cK2ko~*ADStk-$1>m*HTY&=cWz8SjUz3 zTm<9$2>M%!JCn~EW_kbHs})MO;^wwOisOQ*b{v@mpwUoJ%av9!v6igX^uukt$QD69 zV{Z!yN?}B~uZ4T37cS8cRUI*gfWbS9y)E>pV4>sU{m8W>t8HSKFZ&Ln584zv^$cMi z<9mB+*AEK3{|)zsp_ky^F}|`p6+*dGs5*Ff@%`xqb$wq8>&_tDI|{8Wbj*m-8KH{u zZHHe*_)71bNKeb{$XeyV&>KQb)F?Bd@jfUF&P0M*5gPA>4#I&)<-!qGZ8{_45$H)F zfgWf&JT4ktBP7rVZG^|c(5FHIz0gp2TpT)5NT46|3^gcZ&b^ZYucAl&6EbJtnSo!% zpby|xv?!wy{U|`ZDn^vw$W1TQY-BFN7Y^K!NwYZ%uX={E9+`^;9!?L(}s_~o6)XUT`_94)8g*~5bEIhUVx7<><~eA6-EvGz9q>7|89*2o9%7oP?d z?u>BmZC)svDI?&Oa^O6#j~!PsCHr(GGX0c7{c3BuEcqnY53^w-gVRI(X1)rSE>2`&}mZL~1=-%5S ze^$k)yMMyUR63}Qd5?>;>uQ&W!44S1zA762z{Zo^|Ic8(b$3qz-j2lkbbniN7g1+U zw%$-o2GE03V@oPzL(KSw?|jD*$}Yxr(Xm~1%J*ng6Cag=rTiWAE_Nc7z^~@8Ip$r6 zhjb)NP}~UlutM(H3?fyFoi*1q_A}3kxR0QuOTpFWXwoH{P=kG7UdrAzeJfg5uPblx zdlAWH)NYQ8bHT`{$jQ6?S(H+lMst4iyOazSIJ&jOf2j~{N)17-QXTJTH6IF1=<0A=X-{jKkx(FrsRXIz!4o_MHJ zl>~)!C&jUKkxwWkk*_04HrEvzo(nactRBA!xhaV0UV)51J35!iHR(c`40hu zNDqpxajkj>n41b@a1gL+b;bU_FE}}1hP&<|C$70qE{5gI`q|51VNz3SQ(CdDn4I-K zt`NEc#-xm{)`_o{-%F1# z=O21G{9wzMUo=xu=x57SQIJqvUU{S7t^7hZDPl)yP=aitot*DI`GhX4TmFi9;-lI7 zEA|P-E^IZvdI?1;iF22dVS>0zGZyKZ!+wQN(2pNjnq=RNsVI;aq=3~G3doib?D-$_ zx0e+}-8)Yz9UL1AxlLB58M_YE_{PN*$?uPRGSsYqWG2El_YO_(w>VVse9R9E2yO}3}3 z2~DV*&9n!UWr@}f}wOjpz8~rr~CA;WZXHv5pHjV&2v{-y?tMK3h_fPcZxbD zVEXLXhk67nLG0vVssjAf4h^{Pb(=U*ID4y}(;pWCopjE~X2Mbn4 z{_qJu^D}Gzs|pwRW@Axh@th*VdS1_GEr#{NB9#Ia>8{#TRwd7nsHVUP(Hd6hVqnP7 zC4q9d+ovj~g>GceXY`GF|niZBEivtk7xjC(HT6x_zM*V`?S__qX+K4v;949JMp)Dr5M(=(i<4=mgZ^ zlX*SzRhs;vIYl|#svPG#{wq<@&xJlMz`nQXYf5UIjGL;4Sit{_Uo6g@| zd|J5m3au+H<|M^&3simozFr7cY!AdObVpRSv#mH0BYv;ap}~YtE$ypl2&w|~?6S;E zsf!H>HqMmu7Z~?kF7JJzDM102XsPV&RWpOYu`j0xiPm|>Hdp`M@zX_@IV){t;5B7` zvzoL$Hyh{lQ#&vqsUnu?q8eq*zm(}3;a3j$OB#519VlAJ+On`B{F@cJva(+ni&Vb3 z8=Ef+OOlsF|Mbr2Vuz8hxZtD6n!}Kv-Ve*DS$e%6ZdO~*E~@Ctwb3A4@98cQ3ymVf z0Zmct@N&uI{jf254_}x*RecY?(4SA~9@WB?P!8A;4;`F{<_d|*Xfj!%2irTQFH-D? zALe}=4oioT*mCFve3KecAtYE2FET6K5v)N|KitT}NEqLh`zdm_)n;c#}x~TjejxaJ>aVBuB=M4<kAOI?bt3bl$kiEyS2qd*7z_8v%!1)+c}~e|P{&NODUvy%$``uOC_2iTJ`!q*5tC52=c@j{8(r$iD0zS*_4nek06p@e%{2LTNC} zZ~UQJjg4S>AvzB;MoqYG%O@QpEnT=bjH~S^hhFA+nlXXz%RGfvwZXIoW}j+>RQcf~ z_AQBBgB0aw)vXFiP}!$gQU=~rN$r4=V-R4bQCsO zVa%lg`C+dCN`9Epxz4ZZVs{JL2M$F@u3Gx@39c(^SfSUY4{Y?J?6QxsFW7P^=ZB@t zaaM)pZ?&;Ww@%yW*`G!OCQms-g_OE^!-eI$KMtbA*m&O6g|W=!6z9DP;4`WppB;aW(dcCt;k!>5p=OXasvUn>&$+nzFunruOg;(iO50Cg z@BKP*|0%n+7Z<osh;G+!(8{>+c^}bd#3#@8v#5Hqfeu&Z(W-e5s}sAM*g)7a|G*}~$r zj?B9OfvMPP-cZ}W3FFzD2a==P)H0LK&@cv?y5nFrOO3iIVar_0ey-+$TC39AWw4l`pAuItYQ0yX0jhbxU9^TFq@z^Qm;jbLd6J0kk_zc%Ts~d z+gUe%`;KcChwV?grUK9ss96I?&)18~*{p-89Fo;rvQ-I{N5Q(%C zy0fbKbBb{G&3{B})so^f!G+>>`B)MzACs{}dNcFtXH?5DMi(W3&zeReNvnC|6Wu+LuY5R8DrWUa^HLM=ATx9(D)%)o()O4p=@ z7`)cw8~&SCgNsGETXW`b6{K*leF%29N9!ebp~n6^<;?Fj=^$->4bFJMhbgO{(5b<# zdev9pq!(W`OtSjJC_X#ANSj#&{>FV*kX)p+uB3Ykrbo8qaNFRt zCgf%SE6Su_ z?CRBE54O^tAUfVwho|6ok@VQ<+FNh725#(VE5edY`hUW=pkYyLRDw(2Y$O{<o{5hju0PTB&DVO0tF}9dV9ic)dxlea*(;?}C7Sk82x|@r|9#IB_smSvb|(1uJ*f`wl9H2w zLa+EmSL^&+)s*R*J}b@5`ZQ^e(0EzPG3!8`*NW>rtxy_O=NQ2F z$0<&GfcB$034AQJM&}i)0;feR$=u^ez5w_45$|Lajs33Ls;H$ix5$DU&oJF!TOa7g zgbba##q{h$6~)V{|JLoUm}%z33xy!s+9l-1>#rD?K=Y#d8!l(ND-@Y>+$j&6r176w zZI5h)ZKQy~^QCwK^thLPbQ&RIDb1Ls*#XF{v4aeT zp-C(i*BUXFe}nX^Zyg+v$3%aVO@f`oZCYMNUmYA>UU|->l7nY>aIuWHNR^TjU%$x% zs~z&?PMqSd(lmxV*5)AL(0pHRHCU8_>%W%OlCnFisu$d#*uj@bC;1M}wQVpE_yoV9 zCb%G3E~ws|lY&%JVVr+MQvUeSaQeu)LH{-8KNJ3qf%Wm_g7o3fCLAB!=xy~>J-hN7 z<6cOVBTH#U-(m9na7}#r-jK~LX0VKY0@OvO(#%Fzc^b5SWYUV+0=bR2H_aH+Rw5Dn zawav40544=)YjBCsi0oPaa2#RzMez6N@OsrtB6uQ9$=i#UHvcsE)(EbK?Ebt3D+vq{@2Yu=+|a&pLGmLjqgkQM1$=QT zW6v{Gk8bQdC}Zkg8qedbpFZ2;Y|k6N&lTk`5>+Bs<1~DkJQLmLk|;p?@HJ4j{J!-E zP9?cp_L-y%hainhv4gV+mioe30j7LtIn^hn0jDp03pTK9j>XKI$CPqR7)-5oX@dP8 z>O#5KqE7X@#z$xDjzWeOyh&ErYPP9b^IZY_3vL-vN#ac|?>8QglGJExR^r|-UV@&0 zc3NZC`5Ln(^f&~B7J3;as|fKaW)z5hbxB&EtH8i@k*kqp`Q|p@i6GVoFOHQb=8w#G zJwsl7q?>q^h=8e!rg_kv5>d#*7|G=RB%Q9F-Ik4RUq<+l$r>Bq;h^(XE}MA!Sm>gq`K&Jw%_pX_@3mqgh_vigJdM2N^N0O#;Xa%#4DI9i5_^l z1M>>z54ZJgaZ!kgX3r_mkoSr0e)H;?FtR4$!{`lLK7Aq`EV87roxPcMbpvfD`!o2> z^GW#Yt196{!NeTpDaI?TD|woC)O%7N>i7Ke!Z5_j6T%$dkX710eSe53e_i-V$zedB zk*SnfDWyJZKnqnKb~wg#+{dQo{pA%^^Crh&(lU4WP4q#qP~8W2*?4A5<%^ez%TlE{ zdW$Ob?y{OY&p<6WduLC|H0L>x3f}ZW%C!;u!S9zHOXe4@vI9GaFugPvS!pX1%V+Fy zqgX6(T^GMGCk^w_Zl9Qx#Z?@>daCd8u|i2cq&TkiFz{)*SEFhH=;kqIstjhTqvU2h zN~~$)ilBjQk$+b3ZGwmBJN>a!oLL*Ev&VjZu54!$sbo(gu@&SPYvgAyuKVx40;{>gwcKZuu$uSS)Jc26#P2Rnd&e@JP?ez>94O@_aO|Fq#DcbF!d7MGkzwSHF^si-!ICx zqJsUs6k8O)r-pvh`-MB_{DhC5L>MZp-lKxgDivL+w1+7#azj4ue z{SptR7)?1j{E`sG=o+xaN<5@emmD-ve42LC;4)AVQT5~ZZAjBl+gaq?+~wkH?v4T- z|0)iiLcI=Kzb$d*4A?}plAyQ80)I`T^rih++4Z0ddn${!tUZqCC#t>%Km8si{dgpb!gi+^C1}H*c_s(<5B)TSFRa^GR0>NQyk)H28iT7`s#v5@m z#t@YuKhQWQfEnRa^;z>zxw$OH`FDC&`T{dGD=-EqukABcv<%2^c*P#2msAZ)$1?Zeoed<<CL@D;J6DR^{Ee|6Mcx3hLOUhEFUe-`kyJixl+V=Z6`3aTG~pmvgNrl;p=I+&BK?s zWqaFl3AcOvPqG4K{QksCXXc{uS(K{HHN;J=AvGK5*ms1V=nzQKnBLZW+#k)053qoU!YbHWxvnfK`vB=c?Da zei$ZqZ)52~nB@d)I}**$=7YW+QLP#VtsMyPugwZvhsecWm$_~*ab4?1(}X0N_wK$j zxGEENCegbuHMwJ;3z|{CjqNiZom>^VlW>ZkZ%=<8)W5L0fbq1w(J81uWmTI0p5c8^ z9OrZYc(@2|=vM{w^9;EGroYl}4(LNnzxL$4s&&;&Xs9yIhuXJaeqQ^x9Zi)G&2I&L zI=}z1;w1e?%sCwQ$6*Sb<%>55J+*1E?8JFgsuT94bTIfc& z-@i>Dp>05NYt8kRg8#A;zVR90^4Ct5{m#G3Mz^5=}t)_VWvAEq(8oIRzL zeXxGTR}umHn;WX$Whd{vof>}0V%f| z(4izZBz3}-TwYz0je^ZE;V9XOumwPrY($)IdoCfQ-3c0Jn~JIjH#+96@vzKX$4n|= z((^_TwFcx6alPV0rf9zR`-JUdn?sN<1#EHEe&&R&C~)5-;|0-|- zf;S`gB5qFfFp;l{uQ6fsTGo2K32*3Me<*A5ki=H*O&XwnwR0p%wy8{3zsDKNHvBA? zTIE`rfG>3c!4_W<$u1-t+;d@YiV@qBSk0T$6JxLk63bEWqW6V!$FdSfMQyyPkEn<% zU={!7BZ?h2ZoM&UFDziZ&k4K6ph_BO6-a_vTD>_Kv1YNM$NrGs+p}vej2MAHt`zWF za(aLIvZU+(qE;%5U(xIlWDPyj#a123Rz1Aj7If!G!Te<>L@Jv-lJ^VVkf0JwRYR>e z%7HSWl>fx|?-@2Bx9|7jQA>y-Bf4_Hl0_~T({Y#OYlaVs~aTVWK6zhs#w@cfq#2YHGOg^y&ECc1CB}kq#GrA@~JsZDZBFI4R$+5EO+EI~CZ#t!oEhC{ty#2vzx^z=m4gl4d|$%g}CmHr{1bJ}3X(o>1I zc`*1No@!K$!5fQpe{y(TU6OULG>)b~Ovh;+U&YqtW&SV%M}o_#R(XN!kL-l(m7Gowuox}jxkUX`ros@hrl6o)lXlWp{R*QY#>{pu^Q?N!4E4u%j3;1ET z_#CA#sJ--;I_J$h+pxrWtvbo|1i$mz?Zj*ovJdlRSq-NPdt!GtZmWJTw|Hahj)U{9 z^Ol&_nQjD$*nJdDAAkV1RRvhQ?aeY_LKf6Xi`Zla%HQDsU|t81KE+@<-dZyYj&aD( zFIR_pBoEyT<|{pXGH%1*)R^gn?>ZkX!u6b=DeWmGwLg4(>Y)4NLWFPTB~jY`QwsNh zieM3Om*!w4?kPf(gt!qg%|afLr)>5M23T{S#0ERmnLG=F?*P#LmhP3(zRxRV6itdr&AjEqsT7q?2uIjU&BA`i{(7AJ0#Z(nr!KStt5!E(+I}eA&W_|O zSM8T>{EFc)_O?!#!N!kZY4oeKEl%wGjGFY=B9-8CeZ0)#0wb7h2T?J+xL_>ZqFWa1 zWdK<_jrh{q5`j^0nE$HN=SC3|V$=Kt`#e%I|J$p^Ze>S}y)TcSun8gz)wyTS`rHtr zbYy6a4w6jj5Ax+|sz0?huzVi^c2oG+VhI*rRbl)a@zv4HQ6{ZiuQB=-NsKu=pGAK7 z_rs0ci;Dzf?7B#jwG5Ja?EFJWZMM?ib{ER`8TKSEzrL}J;WzP6wR#z8G)iY`|7kg8 zkk#P%XYAMN-c~>U4t&-UPAF^^G93M-8mu>3@x@rx+p1}?9?vf4(T=YhCG4D#nz{e( zVeQH`5u`j&P#j#qHcm43XSva7@sl%GvG745XD|gvk+7v z!BYJnmu$0-YHuL9&zyt;So)vt$fR18v-4{#PQevBcoX-R2dbsUo2&nFcs07e>Y1c) zRh?@gYpqr#r&>1H(ku2YnB<#nu3nM7P#_XMy?e|lPGoai3;yU^S#W#| zEx7Gvhu&{bK5YTujVp14yNcitynPcTC2phC*rgSA~ zEomv)>Pv+PVUV=+Huro!L0Z!jOxBNcdG-byiwEvs%Wwm~N$qf`OU6KVNjmh4ljd0U z^N|L)#u|hFf#k2WW=SRo8~-d|2OMXIO3DQtaui6_9(OLCXcAg>knB{Fy|Fqf#0GC=`#n?yR}p_FgDZuG5awoYjQ1_Zcfx!Ikm<d)P>(7Z?yHbMLQpx)^oj)w#;8ACuaCe`(KS!i9`gm z+OeGxM}%1O+A$)Uy!*U1d(OU{I3ggGPhV6_kgrPj32`=BdkvUI&h(0C1}^LRkm46N zYZ2a8)=bgo>2t~TH?rpsMx%8oX4O{SE9%O^zi6Em|B&qC4b#u-;)iwLM#b+U*8E+@ zk4T`U_RpU$kV-1P3hkyZTg&KfVNc*6-6T`l#(7zjkKj)J;X_1_&bbL(LVI9%ljqR- z1Dj|%>6j2_R?wpyYho$d-9k#gSn_A^O{}-Y7d17H=c79^qrsM4^cx-8ma_}h${-xo zUvyLlaJypzJLL-5ow2~(NC-BU-pDezM0@BlNm(W*^rw!5H`*c&oP~kYI;sn%-VmvE zxVz~WInU~0<`7U3tzq_B`%aO@J~kMu2Fz97yEFU4zR|v09C6CMD|o_lP5!rIgojQE zS(hTtyKY=5U&QRG45prGBtYMp}P`gbqz@02A z>(g!5zSm0)b@(u$B8ejd0v`(#wk~~x6uh0>498xY8sFfnqHglm_>-7*+_(?>C_Arv zIbO|_Pn5u7`sXnu>G2_lclx&()mYM6cyr`qzPiSbJztLx%sh_S-f=dfJ1@N#tP^o0 z)z;0LuduxGKDVfg))V}=-y&E3SQA6m82xL4{)o}(#`wlM5iOq4xh+b^w|QhpTwBjp zTqxo|VQBs-H(Y#cIk|;f<*+ul1^@7}?cu2(B>~?}HzVx#iO|x>$8Vph$bYWda>xiO z*2Z{SWC{u_k~&EcFC^GJ(7yS!JH;S6GqD{D^(TDVAW;8-)#VovyP8i%cKLTM5L5mcC>HeJ{%EI!mTMtI#hbueJc2Rkq%UhC)rD8??zqO; z2e~#mfuKI`*FiZKls9_KYE}FlE4m15Wc%HI*Xl#$R^#zN zYr+Q7pP`HuJ$othA!bVj9P#@P|G5~kBJzX@Oyqp^r%F087ySoB(n)?JOQdswTBIF} zyA;`Hy}F7UX(esBD(Da1WI`XsZfTMJk`&yxa_5eUN6lkPfx-oEn|+hv^6>LJ5N(RQ z7T&~{X;6ny$4IX*H0DY<&oLsGP zgTCvZ{m0&Ik`KM{FXX}nU8z0cY4Q!yS#9rzm=)sK41r&lN^D9sn1=i-o22h5lFaBU zk37M%j;;53_Z@Am+ryS1B_1y5Oz6TvaNcJi{NfkhT;GJ0M(-7#wYV)gEvIJk==+3s zJG0KOb$Mv?(0V*~{Tsg1I>M-5cuvKWReHXcqQa;eykA9A&&yi4Vn+TtccqI8m!B?t znsl`xt^A(kp(bwWMCq_!^LAv2y#kb`;Lh(GSRL|2;x1mzQ|B{hJugM`K?ncMul*$h zMEvk_?F^|C)?OAQo6bYj@TdrF6kCDzw>^pU9|(}W;0nDjwn@R#-TK}4%HM$!D{P^b z1*dKvlYssWnQbW+IzM{3c)jz-<=V7?B#K6GtccHJ?K7X-53H$Bsm0*l{4BAkgj@Gz zB9r?1=1NF@_vu79*G5z1`a8_#abu<`OXA(XZ>mHT-fp#>*4GcN4nfpoMqZ>z%;9ke zKaOYSsL`Psl65zTsrgde6z?ZMgi>yMI#B=H`IANHs4#`cVg5w0_RXHHl;BtEgqV#6 z{iYa75AQKk&wmp#>6ilm(kXbGr3JR5jlug2lK&;8E7EY7{*Z&`@6q2C!ee#D)W&4N zU)*8tRu~ur11$=F)iuPHxrrV>$q>PHpMGkenrk!0{(Ys)$v@4Ev0L?;p1O0yBrKg5 zS-IK>$B0UoirFL)DRxsp^&g?Xd+XGv54wL&7m>`r61iMBT2jjtp@G2DEzwBZ_n8tz zlAp0+XQ|jKrTSKH>Zr83gK0k;xxiFFt3=kNhh;{P!hVwRDFt1XWQUu_@f%hj9AVqw zoypXa%WBGjt<;^3R4y0vX)C(X9*cirAv=wlHI~$Elz&WRsV=UiUENuu>0#>jexbeH z|A*4aQcB?jMQ`iN0#GkL18w#Z=HZIp5bHbU1O4E;QmHzT4`s?gt3Lg0w$Svsh+D4> z(Q!1M+1Jl(%b+PdE2D;w(kKVMQ<|Thm%S(1=xe=?)^^nux}-Q^bz&NxUD0*Qco8V7 zO&JvV{iz$L5VzpBA`yY7CRSMa(&^jTLKR8R$|{KQmM9_<@@##%cETe|HJu5bo#*9q zoOLcgHMyEvSlxteaAic%$|WymIo;Za#)}0S2%J84Gt_mw{n^JYab;CdGP35i6Ue&+*YM}F%4IqH15FZXwHaB-95`-^ zEyl&x4Ow;g$OXhP2`~5_Iw^DCe=L+ML?8RFffvx*ilsIsHhjm)riWQ_`DIs+Ws5|I z3$BXiTt|<#7cI%KID`T!pUyi!!PsvY$EWi`pQ^$8%=Rb8g0Ltz0*qjSSqQ7(5*LVl*=_)6m zV)B0^Xd7Hyf{~i*6_gKb50iUQ;2(Zxm^wK9%<$`A`7>>Ed40jk%GpZGGx2&1@p_@6 zunj*tD;+MfJIY=Ap*hqPhw$EJtj(F>nrHs&Q<#m8$_CGb*$dintNi4=h##qrBu>=2 zq8by(ErRx~EY&L=HIC^iBWbpuk(rr~>lUZ6FmIfbK<=8390hsh^>roW+HWiOwg$eL zm#0hUg`HwjrZNsW88$xdlbZRFEjWXIA!sJT>D9$C8hsREpuae+KJe*Bk~H(G?j8aC z5s4%_1$O67kESzW;L|t%xHQfcjFbhQw-;1@BR8KHDsLc{o6$0!8Fa7MWa{Wu?@J-c z`GcO=BWe5YL1$rSR{#phJ)jpC3eh0^M^sKgS|Fb?%B=B-Ri00fdHU2-IUKv_OhFCq z`wM5IyZ0bx0AIrUtY^^8!&2kBrxu+*Oa1UG47N`mOvkVv%eRhxkXQApPo~fRAkKP{ zb65(B6IW36MY6JR;b+rkV}n8k+=mM=&h%om*ijajS@!i@$N)J%#U)S0}`;MV(i z&NYMEn7=}548FbOD#R?z=U)AXXYgtTJJFL~qWn%ebC6qn#Ksj<-e=g6jsr=_>H_bU zne}kqe#fB9z~uSBxBT?Th?mrft}~b|T#GMZ9XXWncOAEJyMwP^!n?mQ$&6bAciMN$ zD`HR{Gp3v~eyo=!I7Zy_R|h1Ip1g!&2qSoO<7@LKZ$ZI#LcBiGB3$>Bq z4rX(gcR2LU?89H(@@J-A>N&Z5#2Im9Rrwmfy5q3sL&sN$6^kBBe4cggPYa*Y%lw03 zyf}FK{J`;&BL1Li=CS3Q_!=%;_gC+HN&2w43tz#>z9&Dnw2e<>3c3Bp?Y;Wv?9SY< z@_7>MH$J`#i&n2{v#OR*|GnfN3n~wt=(LZ8U$|>He=0`a;cukOZt7TbL6Re#6`i#N zl@o@ajp!>he)-6rzAS70gZ*3T$YMoxqG!&^6VAWZRDvV2q3X3t3H4sz#VGwXYB6T` zMxRv(&CiXv#%Qm;dg=ZmK;MbisSr!I;w)oUa(?L2z^SJ;#~%S@&-|J2ImX)di3L9a zH{MHz%pZ@mGLG*bWqJ8lIK+K4Eq97z1%I@Aq<+&w;x;De`osb23a)@wSeh7y}}vFVlZi5q1zw)r&uhu{~||Sivjj{yzX`K$yR=%Pa}SRu;Y^6gSx% z1<2KWw}fGWmvetOcIx6_IBs~0yf7=3|+7IJnNl3Q%x!2VX+x-cZPesMuK zD*R-1DAxEr4n(z0quMZ}wR;rU(rySH3`4f5tqQ|D(^57QgU!jI*b{8t3c>Z@zQERw zz763x+EMHa$H|Vpf!t0OSkTD@Eb62uhGBgt9oW@L9~FknoqRWkA)&JinA};v5sIA7 zI#AkKzZQz^oqbn?;Y8<_KvanDvM@{taRC`2`teXyg!nEE!;TP{6NbGZGBpf`L$s}- zI2WQV4a2RFEbh_wD~XB;y9n4tW=RlMvEUs+IL0P=15qvJ(!2n^qNP?Gz&E!nBVc4J zBRPPlwyLuMm)e@?L0Htz9A&Nk?m&XSZ%zQu@YjK2e`8z#U*)d>Tl|eN0sNf5krlv) znL04uG)4#TEK>vKnnpqZue89erV$^&&zr`)06sk64`4|9;A?@{*xsxU#EJG}3Ah<3 zh6ah~pzj{=xTgFR(3G=XML-pqX$Fd!{~80ES+N2P(OT6Rn60(0FldF=Xafqo&3FUn zyv-XvNb>m_xa=cp4czegU*Lq%I=%(Pv}pc5;d}ZL6$Dg}Srml5v|j>CRdr$zF01C$ zAS}>asXG1 zwg-xRMM4iOY9r!%AjMzZ(;bKXy*6~mC4aTDJ5~j#`@3Uvz-}8bJ6LS$j>2Fo(3#n( z-KOq{4-Jgzf$C86RCiQ&(S~=&mWO0qcMRzoIK4Y&bhTWZagU1W-BI05o!kR^yNQ$@ zIM_{$?}4Kp_@oCu*G-J*fy>>*upYS4&EkAWcQLX%hIe0h_Z<6KtYW|_=5@py+gLUO zuG>VdH=;y61L_^(gf|)-4GOT%TO9MoW^Vyhds|&MmIqmuh?Tc7P6 z{F(U7ANWhFVo0El3mA&21F)U6nGA<0WE8_F77P?Jag;gcvra&r2droAdj{V_@8ur@ z(BsE|J3ee00cq6g8esuNHog6+BcP62X4#O>wiHIB`^ z>77E@JewNh#uD2~21GmZ*d-nLiWSctbBaqkPV3@=jthFgoo`AbN}#8;(@s8>v`s4C z&YsCp_yw+xc44ngCb)3e)*YB6wDB$+7h1jxnTjZMAx8-YHY&y(6$h2@L=}l@7*MK; zN>waYdjjWFW2+M*o#AtxnClD!_Bh26r#Rqz6d0!&=QZSL;nfSo^NZPK9=45s*c4?e{3~JpCHV+pPW`x4E{r51(W+w)Nq|q~Dr8JVlXPBY2wf z+l~mn%VjL?!-wd4Vqd;Omy`NB_UT4VKVIWjD|hA2ZsH zexL7dDXJrQVr$V5!3)}|3GeZ}ZM|;2!!z2+OYiVZQ#QWC_XMY#)C4DYfx! zzWbTrgKzSNXS?5gi>LgO zn|#X4K0yANVdJ@9{mabxwJY$G)zm_H|5tUF3bhr@!t46uoYwy~8VC?|iHeKli%0 z@D9K6x;Xw0AO42e_YRML!v~o9hOy}_KKG4~ytjCrRdMnSW71nZ`pwQ4-{kpkYG>Z$ zZ0OR|Kn1RZqewJtJ0k`!V zZaF?5Y2^|8=ttox5qw-kPhd@ixc;58G2*NPSn@@1`2ZgGr8#u~&;Bw3h#BBsHh_;C zAQlbas|Q#eHw^d;nDbR|+CW_W%8Va~ysv%t4#e`WeOC@d&DSpi)Bf$w9f*DZ7BdE7 z?Ki=3-y`{3^UOfZ{dO1urQaF(-(%BvA)~*?rSHVr@3DWNI66={Jn+B&kJzGSU;tJQ z3_$(B0MGlgF3&ro8J|esL@^%4f`A!JJIzqYI`3rI$vObnm>9vuZT8^lLzD- z`WyaHS0I+OT0#niR1hjC7&t`YEQw=(JCl6539mzM`4RtDPhgO?ju1;BMFh`ttnDNY zkl6J%G`R2M_2vKS2K=h6CJd*Ld_um3x0S>`5Du`O%qM*$!%EVvut6WraE5%7*`4Rx9$mSC(;U8)j00Wyc`|l(<+V&M z>fsnF{Hw!wx=<^^c)4A<*qtwtfeXU59fz`%}Zf?ek=F#aK5iqU||@a(%Kvw#!t4MYg--8)BLwF;C#Srwl9oN z3o2m1#$d58jBgFzY6CJuwM9J~^F#HS4>{I`%EX8Gj!<#3E3Xfgm%H$j9{6&ocBl&< z8D?Q6gstX4^+WEmuKdVDAyd2Z(GU9pIS;#|yYfX3cRc(s-~Vt|AgQak)JsY3+6`Fk z0XKBDocT$Q>YI8Y`_VzbjBddjdf`+zv$z*Vb$<(}>+UY>g%jPy>|PkvgJ<+oM)&vx zIMu^A@faW4Gkoo1yr8Eau(qd>{}|ubGi20be8gitfklsr)LzQ6#~uf+dcZBc#I0V+ zj$V)4Sr6Qkp#{`@6M&W9+__J({(5ZRNNRe8so%6?3DajvTxD{O6op(SI`~nWh;`tA zUCWT-lwDn-;)?xApxEIaF0slHa?*j5j$mMn6sgiNLG}RFNq44-J+foGifE++FjH|~ zRZyyg)GMgBjOI{Pl&FqawG&X_0q3c&J?I*s%QpdN?cuRXP_bA{+U}n*h52pxf>%0% zH+{qxNj>39$0RK{?Ni>MnNgqeTrXMi1uypc5y;S6r+vXQ-S+4&c&fMm^-uU^?}rb5 z!uRimE6EnW25fAgA$#jUUSt!`TGr@W%4 zG5Zs~ zbw7UO^)U)?<$d1;-}0mnI>da-OF!_h{+4h5pe1np1K;ak^XR@EwtdZW`}&XlH{Z}# zOZd{Ur>|D=1wYkSTllHtT3;Vv)Q3jOM|{SIA?Nz>bszcwyFWB4`|)!hhD`6rC-+NZ zKzW3b(VtgEgh%z~*CToX#r?(5pOppu9|ex~H?~CbTm8fHBY93_FQ7hB-1tdph@Uweo`_%sU+aor^eyW`Rz}`SA5QMKl1}terDu;&Ubwl zGU9U{{dq5->~qohld{ADFM7ahpD!a|;g?3~SA5Ht;mKd|8(;bX69yPJ2JpNAA+-Z| z^?+VL{8!@8PfF5Py@1soaKl$S6kx^=#;Bh$|A#?9!H>b&KjZq3X5!D7^q;qYqyKRi z{ERFA5xGC3_-9f5v$Ejlm+!7-o3)-l{p!x1d-t4R4yXp4`WjP_ub8nQo#*3DEjU*#|10jdBNgD`j$;jD2*v-6GuOgh` zTG4t!ip|L0NJtm@#X7IVxG}IA>D*DYDvb_HC z8p2wq992cw;@r%DG%w#-)r4AIj@eAuuV)f4%v-M8LYUk_AGw7vw6*u1|$HzBc`adS7}O1Ji7cM;ZgH=}C_i+cFh?j|JnG#2kBRQJ?t z>j+aHGg9jalOC62w-VAHw^%syq;JtqLeA6j@@7KO(-sTcd&}bOgya9vFK;Cb{ikMp-%iN= zK#$)>$mpjgR1$`Mq$XDqVj|?Ojf9O6YFZ`Xc>jUd))1mTR&!SoZhowmuOeLgM4P&b zkou`nSV=hhsb05@?Ge;BzGv1Ga=w!}s|iKlc?303#;qru{9k>-Izq{R)a**a)SpGe zO2U-?69-okGJX+zR}%L8Dr!~|4*n)~tRx)$?O;n_eIlt*s|jmIliannZ;RI69Wv6t5x-8ArnyFg%%rRh%}FyzABx&P*h2%WA@y6f#b%Bb-ekJ)?$@ zIEjqZ8p4%H)c*8V!n(<1&e%#=luEv{YY53x$QV~csGdUlscOR1sbp-fCQO=6^4cas z`gHPqbUOL2ucH5twKsuos#^Ppe>kFcS1B#%imq7(Z98j6(d7eQ81VjV{uZWC_A}Zh7dxy#QegEJ8 zTkB&j`s}^WKKtx>|9;Q&oD;k^ljtY!B$zvsuy(&q^lNt$oPL+2Pu@+i_I+Y_e;dK_ z4~TxkW`gw}kb%H^ACk87wh@f_h?wSYCYbaQSx0aFm>AyKNO0_9@(yLgb4k|vQw0B> zOCAC)&m~!3e@*cGJR1AYJd!o$IKdzDhy<*kPplKaB=~+lX#xB`pP1e|N-${wv5r4V zuzUec-MN66RvjkzdI7P{I85-|LYg{lAu&C1m|*@wV*UCM!4a1F!$M-(cZgujB4S-| zh~R@oGLuVEba4dUP={y>x)!(qdx0 zxSwFk5}G<^2{E16Pq2Oov98}w@I6cYeF-uBu#aHUQes`Tk6`&yR^O$>baWrV*Gq}@ zjeP{qEo1dvMoh;(C78dASl4_?@YOORKD(dbyoVmqgNC0(l&ypSJQhYttO_^TL|7;O|09u5bRw|@A-N)F)iOhaAh^I zPTfNA)*6~Re+@Ccx`klt8e*Neh2X*(TEZV|h-v&5f|u74>$oihE7sD~t!s(tm(2vn z))MQX%>-lD5##Kw1e4a$t8cC&rnff}ELumbGd2@^$x^>xM@-W;6O3L@tgme*cyB#1 zezcij;d){mx0zt=dScwOiD2h?n)~p2Vj52mtM$Zsb_2m{8;JPJMuKS@i1_tJf*Bi# zcyJ@ZyYci7HxTj6272 zS-+PB5BwQJXb-o?UmkAHZLvoQaFiIPC1SoVeOw~e>7I^%&pvZ>qWF6fE+rYB(Bt={ z;+wYaEdsDbxZ~{v92fq^($*84(gCM*?Otz>_eA5H?eVf+f3+Q^>dSzA`iyJsuq;LY zXL<6s$;@d4 zc)}zeZG(?Yt@gITk0!&+cG%srU`{(6YGwGbEv~i7{!d%H(%Lw^J>F{F8Q9V~Yesu~ z+1mJfJDhH9oZSwWTZ^By#nsm0+O`bX~?ND?ZX0Hd!%AFr6sC93lJj0vt<7UtEB*35FR3csfzPtq9ALjN|gLIms|8 zAB*(Ht9dx1H@sPhP01T+>(klhbf>k73DM|u` zxc?%+BM-Dk)dTHstfzZBw|9xIwm@yhN*#uEdRvDnbUCde854EbORQH2u8@wvG@ZC# zmo$Ser!6eF^Uuo(2@kZ#`2k!%bXOOBh0x7T%Uw(`%sQQ5IxS`$5qA@D^Pkm2STcaE z!_xSBANtjLyiK-|wR)V@y_vvVQ9saQT2jkb^q8O2@puvrCW-Iq@kP?OxIg~rO^H7i3WrUJ z7Yl{c*@p9l!jIWciNKXMvvj}Y3vaZ4LkFz7Q~V`g_~fp3+qwwPcF4NaMR>ErMiDq^ zO+S(^{A{%@&lldXwE*VY(r4rg>uuIw^Mvnd!tXZI;XGkd7whaiVNDlW%Em4~>VTyM zrkP!Z-358q3WQ$^dIIyiiepNXmUNvY0Nd@R(WUs(J{&mEt>d*4%qVVmvIJ|272w70 z852tJMtAYKQoP;W0&MGUe7{6E)IIO%65+{`Qeat$c(f#GQmMGGH0ia{o_`urnESWK z-Tm8hf4x3HpB9UCcwiW?hjF&ANhikHD)<~ur#^rmS$n9A!}u`aNJ;gvRN3P(qi!l;f<8^bt8nYjHYeFg$e0~CC$Q_bkm$> z;aa)^?8-1rj0oRkSkDg?=4E#HJ|_H<+4ZZKaH2)l{+RHt$@oD`*lB9<<#6GcDgD%N z;mua2Z-)uLW$Uj-#3yr{z@{A27ej?Fa;%Go3P0YFzF@fUQm$$BaN)Vu>3<9p7q)Ku z-f&@0JHx^e!r^wCD0RB?Bi+Pd!mbYQ>wsT6i4%tj6ABGiMhJ%s^`}M%CkodHz>H#= zGO7o??b#mdb->PE-PaBiMwkCafZy*H*A5frI5Ms@3oln1=f#9?rHs#;g|F^6Txk|A zcv3!z3BP$}(Q*{=d`x&(c}W14cxia0mlDlW8V!HzYxm7iVT<2%u36YU!0>squ=xS~ z*`dPj2c`?a4-c==eG?JpJVI|cP$Pa55suXSst5Kz+HrQX@P2)}XPSl4Lxgk9!rCFi zkrBd64Z@)j!t5sfe?|xko5Tsjgk?=FfE`Vyy%FI=ll6m$@ZwPV+}DSSpTvZjLurw7 zhKgs03iF0uqAV_IdNC#}j~4t875)<~1*XTu9gio?jExb1S&x}s7%r@MEbq)?!nco= z08@vH8y-)3YxsNt`0Ssi&mPCO{~Qh+8`<&v-c9{+FC5U=^#V}Y+d_b2VIA5X|QBEIrxKhvbQ2$@R6_x|)7IHks_TfcAD zVnF&7fqX)yl9>Xzq%%zs$nD=$-nWU1*@9k8cWheI}8YITtS zC$q&vHe9=-)u=Ay<=j&Q__eh-$%b)lJC5suCFZnqHjKNo)m9sscIN~gFsFlgnhiTU zTp+-zPU18h_I7Ty*G9Hm#YJ7P$11+nh3vOJt-I}al-e3fZhhZPd_+Hm-1^<6;w1NN z-xcbf^0Pqhql0}>5PueK@g*$A7#%Q1Cr(YoG{N-mL~LPisjUzV(-W~tYyo^OrjJj= zPh!?{iFhut|Bd$<_=nuZqXL<)yFhO7PqwZl$;Sk2BX1GldtLe!0l(@x0Mmr@PX#O! zvi1nrBiw!4H-6He(%~GjaXams2IFA^J~T)-uv`MLB_aKX1RPA@dHAQA(w`-W*{(mg z%iGMJ`%%IX9q>%jT;1h#EK8>Q#wg?eY|nj}V4e<`r_+C$hDD-&R~j}XCZ9;d&ctOp zU~IDfL>gX7*1wZNUQd3703R9d{3Z=w8S+o0;rWz1fjKGSi8LHB8a_+INn`S!G@Lc2 z0#}Xc%hT{|YHQ$~)Z|@h_$W0MSe}~xQ5v?TrUQpk(?3kZe`xUM)b#h$@N!z#t~9)# z7P;;FLK_mv{KTWF?Ur03n9w5cyS+r%Ys&j!FA*lT>iGR$BCN{F`*tr8&bR%p?W|9U z@JG3LY%dYMbG~-xjPmDC*YwL-T-cRWYEpOR+Vx;A4T2D#S=j%!C`+JG-(|TeZyO#*l zHqg|MH;~-jdx)@O1F?R%hX_Bi)TcL++#h!nVdh3+eSJ3(wr^zgcO%JNv6~3LZY0*r zyNEDj6HQ&PiR2#GMTEVZh;{xhB3xmq&uu2TlXekd_GV%|zmo`iHq+D-n@R4TokX~{ znOMi~B*ME}XzJ1}B=?h@L^!a8SWoXD!XGSk!d8-dat9ISY$evOb`W9zR`xBCtt9u$ z9YlC?8?k<|g9smPW7KjR$vwD(2uHRN>!&-2Fm5~V>WSM48-l6Zc~8&UPS^;2u$_FH z1WepVI$k}5!Lfrx|J!+j zZJ(1C6MiK4@DNFV{zrnVhe*oL=LxPHCLJ%HC)jv|wBCE3;MXsRe#3c!Cyo-zT;BPT zh|?|*Z2OY5dg%he>0?B{_&mYIW9;%P$B8)p0>QH5q}AvP1n-|9`mN^)=A9t_1K=MVtnC8g3D)#@xn!dC(aS^%teB+=Sc1!7YW`vN5u0N2xgrl z;=ZSju>A$PjLAh5uZFy#H;7XrG#7IYfB}LkJcps z>k?kqZ8PEsd*AMgey_02h;8xr?dZOFm(cmP_lP?RCAaLA8+2Ht0~YBzAMb@($?aaa z8$YzvA1=dBEjt5KTbUO0#HcpL=kLZ_ZS~*x!h3CBAi&~w;vc>6b-PvK z+Svnd=Ii&AVRk;@vJw7XKaeYf~l&_s9M$<4hGF=F*g>TGR0AHs{Id2eGVO%ZonDZ=ZJhL98-&e7QfKy|eYD ze%N=XY4!v7BD84X@d_7yBHSw@IqetWFLOXGd$tL^!)708dm4G{nC%G>{+j? zxYA93!HdzwR|)W2_ut6X2Qj9s5+EzLA=nj7xPI(#te{ z0LGRZ{^*Z0<>_Da$Dz9oTl(YL-ECL&$E%3W~9>nKf5jg5iep1CLZ}K@W&UrshzSYky0~BUFt!r~YhZ(vmmiC_R zUu}Quiv?oZp}zQ8OdBoZP~v}DPnGeXy9}dcEbAm5?2G*t@z=iiq^o$c3JbgL(E(4{ z#YKHFs=M)A6%KdT|5$|+-OGU2OH9lA;?*AdcRX0rqs3GYj`!?1{eH~p)%tfg7MAOO za${xr48lG`_rv{o@}5@5@5jII)t_`@#=Ufp+IXKh?|xjkuhp#kvG^~BC#o>rVSlL# z^PGmw9(?X>yWE2xdmH~PV^kk2FuPCITp6qSh)>B_-$xuHV+#xK?2`%{?vp*SFMjOP z=}Hw|chig0-NyZW@xEJJ&=()O4X3NH)Ga<=g;j3j*eYyui|=}{+by2EAD_9!1^45S z+xUYUC*7A5_`IG?$Q$HEVxCoqQ3(&PDZ=qYaYrF$rWj5ZVr;5me<9w^6u&FPq&o~> z6=F-9``#+V+wGFyD8$8f#%YE4_g&()LcC)!?J2}$tN3jp#uf;#6q2I_hUrE4w!rXx zAubdc4i@5Sfnir6p6Z$kOzfKeR3Sd@n)Q2EZ0wp2eAYGnYFB*SHS0=OT4ZoU7!*8V0@SABgJUeY10X|8m;U(#G zv)+`U-<6A98I8co%$%dSIGd^8nv2VsVc=MctRuO2!KB}ii^--iaLtr;C>I~K)UVFP zqLyLcjaFF)bFr(HepxOKw5kWzWtsNp;-@VA!d(2G)dc*IeaF6BJe~730lvF~w&lVd z;@@~&Kr%T3;zix*v_fNvA-dpR2m^rnf~n3gO~$;P~7FdHY5 zjk~gOHuJHfFYzc4T9IR?)U>e4Vu-{!M^BIFbk)NlgDZ z8>bVu2*5nUM`V6BP8*XKXJcoExG)=6GOp?7XXEKsEkDl2tgP(0*%+H`{5TtLWgF*Y zV@`GfE9)nb^bPmmP_zrQF8Sl2fXN(!!+RP$PnK89p^B6OJZ7;rQ z#R?ij21f)EK4+c!ng76Yv|+j}q{t&JHZpbzCIiXI=6r0i%S`H^!j(C1FqM zkz%ZADIO}up_a`@iZLqt1#++$mva`8W5rmXYuaCo-&(gmUX0auy&xPd#v5Id4;JH8 zzPOof%yqE zxI7^n_%xyC>w4@=On+66iF)yMJzmw{aT5cYZuu>PYb1?*iaK+d4)Pe?js0#x60ji2 zJS7#MB~2EA)5gr#Q*qT;7U!y6fv%Zj2=06EdO4Z#-*L+_o5#1dK^4 z{vsWVl2+5Tlk%8;$#z^DK|VB!Kr)13sG#Z)E^v*eU*KIHzjfRP^@toUXNhP{X2BOMKSKL zSHzQ1y!wcEY$&Ea(iiyd5%Fjf&OS0D0hkc#|8W%W4Q%mp1QQ3{`B?-L!zp{Cm=V^0 z8o_sePuU&C)xXp5C-wTBQ7ox{O#t>ZW^at)+eXXy7{)gxUy5RKQ|kB_W;ThJqL|$z zZj5416YZaQO|<%po9M$=G>Hd?Vr>(x;-)6r((O&OCVQG_@9l5eCjzsF85cc8uwd9W zJ@CilEtWq;FyX)GWLQ6%7-($gXmXUEw@(oxjozGl+1N{fy+nUez>lQOc>xo2m&u>5 z{UYF3(&n;&$v3X~(HrP(*dyZKI>T%cTXo5EM0~4D9xGz1KvT90`Zq;0Gt$3X6x}yp2@~D*)4CZ-xm{r7ZdW%C165wGct9~v=FpecKW%<)Ei!@^?{GDjP+LQGp^!~%WJBqMg{ zJG^4VqU4N8M$Ak}nPtR*6#Yj=@?}ap;I|ar{bJ3=Rhi6NX^`siZ@cHUoYeN1mO7u@uf7pM9Wx| zaL;7gteh9q@Q#@CM=Dl|KPCcmjh((v#UI9;?@}=>HS_aSd~~ynC5gb2MDcJsRwmvB z983Jmv2@H&%Gr>P?MXTF)A4oE4iWe`wO~^^mZ#;+O~>K1%s12VecGJsW$Z`M2X;@CuBr_r`J4YN~oW~54K7G3TWY`?$;q<}Se8sP9!k!9 z+kn%_CBPd7n&oW@8E-vr`FGxpUl2U_3c0a{uj+xT`up}KV_9<7_&Y~ib--5k&e1{k z&e1jY&e4NdJ`(QzR*y5nMDcnZ2K++Wtxm@lowza`uO#HmO2>kP%vaK} zR;1ytMDt7OcqLIkD;?7k>w#yIe$Y)y$K~YvfQ5$ElhW~g%2YBd9UmJzyqJz>(`h*` zrvLNio{*ytkXyecp9kb+YPdW8E`2tpB>>YBvOZ44riA2o6Upv`A8-FgS_U>J0h^OD zuO#8~q#p6UD+kIm-_)V%`f8GIcLgWt z@DcF?PwI>lbeN!P$*D@FXSOIa@BEuqa~5$6T{QW3uhhvH{ZD*LIMcH;@6_UrXZIV*_ICE$`! z$m2Pm=v*^IyeUX;iugmIC(f9J_`9wt(@4e=f;q&;+PFp_3j}r?Hi>6yu_|*rSz3#=t$q^E)?!-Q@5$G-_@;fI zGqt#6etdQfw%nC5vj%7HI-hW+7FRpBTw06I3yhm&S+C za-OKg*Y~viy#{CQ6Zh6&+Fu?xS&K~$)681@;4n_9C1;&E>uNB*qUEw0tdNYq)Znbt zW_c~1b!A+x!2*~5L=Dck46oPXva7}OwHVb$|7!5i*2<7)AR+i{}k_!`Wv>INLH(q9hZ=PLd2Ag1)y?+D`KzWQZBjFNN4 z2XRR?Jr~5)emS2%f=T_m{PGCa3=p3QV&j0P1Yp}kkDjc>guiv4Q-k0BmUHP5ObKKj zdj#78`hAaJ4R&O{Pgb?T z3ryApZScEkJ6X{NTUybB?NnCgvNrfRD<7DdojI=!R%E|V7PP^s9J&!+y(4o; z8$6#oK?h82lewr3=Cmn_*YS>c6?J%MF##s&^c!@TqWcSOwy9|Kt=|{wj4cG%LJY?R z3iFQ%SSE-+31qd<8aT{?$Aosb?Kdsa5@>1gqFo`-SMwO!29F zyqjfQmybhPX>0OvJ}c*ge2mM!Z%#foXQ#iIkKeNOFXiK%9Q~Sn9L{MNn~zDY#ozOA zqTN*TTt5D2Pr2?jbDvfDSkys$E+1cZ%=tMFmpgX2nuqr~4>*yBH?3LUJ$;G}n4)X{n-0r#1NgT_HWK}M0XvBVOw{Q=5b&O^<3<5Hb#7p?kh)&L zOriJnbEE($$n@jhLjDb&HuxkF_#{z3J&7z!)W4WS)+PFYSCho)Nw?WVYZx%sqO1s4u^j*RIt; ze)jsF?!h_&tRv>v({X}~O#;5t>z_==@A|AWX_%D!5O6M8|8zRW7lf(COFf z@Rm-$R)_a=-LGFeLefVGI8FWze5RwpuXUxk<=^<-288z*@W*Zgy6-Wtc9kf*t(lvr~iJr#{XTHf5hc)e@g$qmH*rQ_2HW4hR4DUb-m2>(Yl~H7&8|Q?^HkB zT-O+inj0Ep=4dP!iJ2b@#|E2=hPzw_3?DM2J1X3gc~~eC4L3HJ!#tzi+!!$zqqeaj z8Vl40qcJo#g(AUNW90E0p}X(C=SJAv5PA&S2t0^RQS-oHxIR>8jy0NtwL_c3k&t;v zb1XC*;f7(s`f#23(a;EUV}p4}u*n>1h($)=Zf~eASQ`t~-HT53%_yu7*VNTL793a@ zjno!4)(mWp*3yS`t!-+$QOM0?R$e4DC^Wp6`JewX7nqx);f6uxy3oL2bA1et1qZ@< zU)c6H>wUef_f_BhXlTS^jgh*0RjEp<&_=qvO5c(F`bb`BWN)wHs~)MiT&kpvtaA5t zYa{zO{BF7TNX1(zc}G?|yqa5cEAmL^fRPThVq~SHR*aN=RaLf;f1^d$gd2j95rONS za-SSAMr1g^|d1RH_BaQS*y`}!uBUQyGSE@WoRcE?9ckxDg_zfOeqB%XPVO$tv3{TzF6<*)6nTl3gyRe^r{#?k}gpW3~I4Q0ZMB zd%l&4axOe^VW&doG1Ve7;pBo=NRlmd=q1@hDhNkSEx|bd=$xihRPO+P664%`bM_MbcV_n)xxf+ii-;t^V2CRTl{noWShk*G2ypS z;iS)#ZBBay7ak^59~BZEQQ78^SxlkxPqr(x_hmZxD3Z%1SwoTRU@elJRy!@zX{Vzh zJMHZ0PF`J)-AC{9$P%rDhpj-_ zps7swqzd+zR!_B9>9SHScG?}PMWU@!Et2Y?!b8`gYLV$8Q!T28-N0I)@>NNNj|xd; zF^?)yp{V6d_-QFNA6*}6K3k4zxg^tAxkg7wb!c=!sZKj>mg;0JSDmuO#e~yOg__S| ztnR9ltsPaevzWwYo+^3h3|A#yPf6Bj1tlN9#yUdv*ep!&EFK?S)vAXzfiG%Rv9kV9 z*gRAfJMBhQu{&H$I9V3E#%n6Rev8wwd7mvwIxY%I$cz5_zg=XPvNcAgp9jksei#03TE;N;G7p$c| zy0*Dcn4n|elUNx($xm0m-(sgr&TnC3;I~M0m!?8xg3f3vDyU#1>9@!VyQb3hiNsr@!>C*RE-MF>SuyZLw~tO$JOs( zJEY%fmAT+Cnf8O<$(DfMsd`w9b+q5fmWN-m(}DF%GF{?+kIiZ4g2h<F({8HN=nSiat_>NA>j$IC}TKarCMceWbn)mBsyzDpWc&htr`-foiW?u5ed7ssipx zNV2bQpvs|YaI1m7QeUU!MU~P|@&??p3su#QN>uj_sG3q8a5^eHzG`?Ka;4JOS*1AP zl^m6UeqOgG!7Hhn*Il7OmAr08RSz(ssdhYTr#t5Px#4o1!Y2t^vr^`VAAvB3xg0uR6!>=|kZ*3^dr;el>6G&U3r z3rAwj!FqFSaC5_>6vrX@z)j*%7pf1%LJvOt=aic?H_hG=+DL#WOiZit~% zpI)8%_Ufb}6p1uOAPo!FHwR-B_JpzgocNsu~0+oI=e6jYiZ}1 z|5v126O4ws4sL2f)1c_k`aflhH9i_@2>&A#DWm{67GhYqIZ_{}3)ME(g-{!fUJqWU zJ+VlzAv&-zG9(l+qbV4Ph60VlLXk+gE)+#Ijn|o@wZVplP=vzvM?)h5O~Ke;1Z(Ly zqkiBmI6D#?(luBg9?{%T8|_-#I0Owf(WY_~6&2Zwx)l`{buTI@DlIB2>QU6wUSzl1 zyV;BF-R&jzQhS-bhrMUFqHgwX-MSTb>)x%TTWPnlZaup7EG{ax7k4WzF794jQe0YG zR@|ewXZND+_U_%f7kBU8y`+0-_p*&i6zMF+8UGP=96-lmyBC}n_ zE%$~Zd!zxrYAAAFpGGq&UbiG`4oU}ZBMhp~saAO1)wf+xHO1>-A-}iMtyWh#1~@7- zx1X+lN+JTXgK-8cJEARig`SHR7lSw!7duwzSz+aTLPe29Wqg8C01smqG>gs0c2kNL zT%2n#!ElM)VrN*{!j3|_#iOu9xtzsR#sO>=&KBtLZMS*oF=V%SC=j87at4k-C`+(1 z!FWiy#-O>=&SFlL73pLLshxo#yJV+$!Y;|2EU5I@wtH-GUSQ#ZVj{cDp}g#q$~hsR zF~wzNWI=Us(C?vjP#FxjYpjnb=%?2-7b8@fpFP}X=Yq2=)>C$$CQ|@ywW}0VTV3=# zm8>#-fMiuU=I7wr&S;Y4vQn5ug~H)JgY;HE2l%vWC68=niK<8C$esXYK$^c{dCnYU zCu0>d!?pArWr+;lN-FD3i4P@3{VEeG=KvHkOMV+84SuKH#$msU!+x3JeVdC4nI5lH zP%v+mDeCgr9WL=^fPpCq4aj`3|ACraouM4oQ=rVLh2+;5a%YT5^{{4nWD3z#kIK_jj_v&%kK5%qWM_gcLRDcr zL1Fubs>nV&gX%UGQ|%0+s~pt(DQQzR4#YKyfpd*5G*#1B$v&ofpy-_8ammmBa>UL^ z5hv=J)lO%HW|g_%7~QVWvNV~2U@BCO*i{P1t@eB-WDeF@8Y3G%Nv4aAZK8e)Q$P4Q zJM&u@Pxo6?CkN#|2H5>J2D~k_Tls4A+sY*lxMc>hB|pdAvWp8Eb7+dpkv7HoPPVH2 zPW}L=?BNibZhRDJs|;x?3~)1D1O?nQ(Pg!9++9vlxQFR`{G4pjJ%Cn1@h~jU_eQ^> zGH9+a9Rr2hJ_fE?V|^0s6DsI6MuI3(RwQqQ+v%=i8Z2)`aW@K@B}Zi?Dy1sN0RC61 zL}g#M3`wp~Dkb!mG@n+%uxoEg3sfl;9`sRsUQm3_RBEbJLD98YRy0&86*Q;ptEzIl zpg8ZBDzreQV zbgLBG>Xzd=>Xs_f-+_DDECUjJyYbZ>$M)jfVdbvf3!VbluciHw5cP{38_CmPcd3Sg0!; z4I}ViufGk71e*r;dYA_58y^crdOiFnOgAjlP}dkKjD)%sGM#i&*V+6* zrhIcGG)Qh9a!;qae6xiD-w+4wmHh%0E=M2|8WI{(6N&^_#cw3ng$4#{2L=O;0|!P! zF>9wfeuva2P%Q;0zlenD%}tHrhFB=1j0Vk3O^uOQs16muhR!iF*K(Vq zpSMB+8iq21ke1*VP~#qm>KAxyPR-$&G>vX$1nDtuXW-2@Po+ z7LuFm|GV~_Rya~fpB&&}egkd6bqc^tJB`gTb2MBRDhLf67^;m$5w64Vf=DP>Ul49W zLugPi79K{k*2M;+TTzj{S6xkyUiNOq-Fw-CMMb@O6_%8OvT6#IWp`hWf!R8|p<}0f zTch~7%3a}sBD<6dpQ`w1Qnka!ZuLri6~Cl;9V`Q!TP>vC6Vl9vK#JB0%lD?6+#{D`pl8T7OHm`cvhH+{Rs%D^rMJa!9H z{!(<*17oB8={ciNpC9#cGI zcgjqG?Ns9+nWjnX$hS)h1JF`D(dW;nf0FuTXj zl;|FgePyPiw98CyWanpwU117K3ac5OW?06qFioXh@hBW?GgPjq4CpH=$Kfhh+OuQD zuBbi_7jab1)$MXGDi{W~``Gbk_em7eQc=#8?sanof zF2&h2#s_L<^`#g58T31<4ZnjW4Us1Vbr=@mbl3(y?aH+sY9*vz7TIMx}fb+p2xc_UV%tsi(L+pDEHALblj#EYTj41|dU|VteoSr7K>c-fItSvFlFLEQ=1QNVitEl@Zm+6A>hGovarvsMG^xK<;m{ma zO7Ci~QZ0G40qEn9E2|_g`Z&}+&HSGl!-rUV>buVVmBt@bJvQl-z!RQT@RvZD&Bqy=a#neJZI9DS=P1=0poO96K! ze5#|j1fS1c8BqHuUJZVSH=sKDR%3wV@b;4=4+0g{JxaRaA(cY^V13izAY%dluO#3x zrmHUqH`I3>jK85`ASx*E?;C;|91@I#W5L^$^IQg+1_z@d`z<>8UgoCSdzd#*KIbKY zaMShpz~+Y9dpbq)nb*(tM2bio8-n%W*a)6v_}?DW?Y76xesQI3I%>kdc zBH*GkAyD1Np-T3EC zZT|~92}B2Sf)e6-{g8Ci`fy7lq&|H@!Mad{sl6k;dT~{`MyZI@5Q~iHWv&Uc{iNPH=1=I%X>+{XA!QrUcQSCO@1{=(c4fP|; zHKDjQh&y@(nWI%OY91JlL}TU~ou~q(qXp>t9jX4cDxmgtR8<8y>SqZ~ckkPxK9@`K-kKsSfeJ@O zABjaO990zom*SHv174+{%DuF1`d{7Zuhq}3^%?0^s;Yd|Bbn)KO+IWX*8~H!EcJ);%nP1m+r!H>G8(Hc0kF0X2 zTAp^!7@s%BiU0^HxZj zyRTdB%_kzgFV0e#iHHwV+zsryWQ>(ZsvWA@Pw`g5ZW#v4JQvT)0W zg`osHSEJjxdx)K>(U~iS-Qs5y(&G2UJ-vL~#f#Z#oZP94`;gff;G(qD$6dUboks4Z zF*}Xy=jIxXlT?-SQ9rlZFgGrHT=*E-j5~Evs7lEu=aq~DdYJc!-6LDLDCf2t8>5_z z+bRshQIZ*_m7GXgB<|tGeY&JLyW~WYb&%qZTX~$^-%E=7d(r1`e+)avt#*yUP`i(t zxqK3PkWXTS+{ZiC=V!g`XXYe{`$eq%wCs$YRc(G0dAORK4wQ?TfN0Sk zZe;SPO5DlI$_+fsA&VO|WQ(dXiw$!)letq072JSB>8fmFR9v<(3@&r@EZY?B*2T8&Y#5~e`662Z{4|fOiD9jIx8%!*0s;d^2JB~3*>u2U0ZYNVY zmsf2T#>H$FZW*$0XIC$5y(Ihbdj${jZ;RpsU)Myo3r z31zk^kL=`pQ&BnJ^fTe)?9(Z8zR4M;pP;S((m8<35a<%tnH8N^atD#aSeygKU%XTkMP)S!7=Y zH{nR!gj2!jpr4aG&ioYaP{o`p{rOCPM1{&pp3F%ex9D)nr!hw=Kc{tePV4O4XNnE3 zpLZ~2esKcm=LC>hdALP}D+nkLZKYxHvqks`xUS;<(H zqq>^=C~);ID*7mjDxuObAixYil~M)$PidEPfJYkO@M%hgM0;LzPOq!|gK5ie`?p%NtmYIZWN}t8zQ!O2+_rqyd56K6hoD zI-;*4O9O7uM0#AC6(1$Kj4{TIPOJq=Ke@Ql>>P02niTLlWDox8b9gn$3$NsoypmiY zsgx*IR5?@@pq!RUN(kYlAcGgogX~FAD-^~SC0TQ80~n*MP-K_8HyGHZ%$oKkZ7W5p zDpbwqa)DBCP4a4Phj&1rpF|5(p()j1{^nK8LCmf7F>?ruzukjCl|ysO-Trq@S=%_I zDO?}wT3d_e2JQx5XKrkw@U52_5B9354>ml?ja0+y!h^!G|Fe~<8!bqRL>eQ^Dnb!l zXQ<4);|#~t7{zToc7E;u$KYRJbUUGxR z<=+Su+zTy+$_kjRpd_v?z${!1u|Tl4HWa-y{+Il^8Zgj4$>wV^E~2mYD^cqXCBX8yX`+Sb^M0 zthpgflLI%B(byboYL5NSW;5C#hX4P&3Ci5iXpS+6AH~4tfnA4$z;J$m)rq~ap(<5A zP2#Bj7GEnUa{R50N~NF7Ai1M*fT}sPn;^fRI&Ce>&yvMjJg`K@QB3UH{ zVY$bVWVdiDjg1*(?D;(A;f5T3gPpy?;IVTHjKtrHV4mudhv5au!>S{32NcP}d@m%A zpCM+MTZ3duQRv?a?pJ4*&d$7WA(F`?D6|JthQ2E?NGTjhjuun1Xk`~#mqVO zxCMt{SqtlFimth@6a%CG4{Pt*-^Oued)Mpv6qx+tHjtrcmojl2(y>niD3C~l)eNe; zWW{#+w16gw7z7wxBrBGm&;I;s|EmG&;*66sFRV655ckX4Yp+W$5gge|1Y`CRu|f#K z4^UgqA#X!|T?jGCSB*94IywIf+FRZu=UjElUmy zl(Bsr9&9Tuf)$IV&$8rT=Cg)9j`4*TXx@{pk;uhu)&rpavL&MP7%Ay zsw(eV@nSG5aXd>dF;VR$8x`Cy4tm&>ru=4zOWVn`^SyY3D{rbsgPBWutGlbi~u65^m!&qv|Ri*9$Llc+&7*AUszdq z6<)3ZUIZc}0R6uD;tM4Uk!p|@s&6jFwo^=>cZOy#NvB3ZSXQG+o(AA7Ya-E04a%vE z1m#G;Y<9u7DXRW zT%mjJ3UgHnEGTVe1DL4N>6IId$DgZeaIK&I?o(xUcZ>DIVy3R^eKlCDs>^z>rU3@2 zVzIf~?`m~$OEla4ee)rp>fQmWCoq^t2>OfmE}P~_v)VPAN6@haQ^!ru_MzS7#Jx#9 ze_5|)O|@Ll{`;)6YF>5Np#1Tp<^DrwdjC8>+~5CJ-EI%y_e=HbLVelUy?$s`^?lP( zr(dY;#;Wb+JrsD$sxZ>pQc zQm!?6jPL7*hsEl4dvrg%erRMV18cnL;4^;DegV@h+Nwu1_xH_f&}bCts3N4SH>0!zkv!sS0-?gPhF<&@_>kQI~iMy2kyvj_k#un~8 zyq^(gwQ{U5=N|t0puK8^SHrYO18x?05Dref3xc9CYbIJybTX1J?gU3`g2_%N@};g5 zkS|1;W`(a|$aLaxEBMHN3rg+fLQnT{u(g~Y%0{1yy-uGOPB1kLI_g`^7pU%|I|ABh zFpV~)#&?ZiQ23#NCF(@vfmgU`Tt`L;AZ z6BO?qcw3azqi)Y|$V3d)vjV$C1~cmR$`N`gT+Lq2V)-2>d@r6Th3Ll3ESz?RMc;myt%OU570*doYPUS8Uidr=GHg{=(z$*F``f_mK;ZiU! zx4E!g5O5CkwNTU|4lCt$Is}mp(Tz(`JE695WD+=r;edb#klB#axR^NwRA$l*FMx1H z9racgZI!iXtDvYwdz2Ot>Ixy=*FaYdss)7O>2`e=-3|lH4xA7RFOCq0REg!4GlKdY z55B`5;zp>aP*J)Jomm!Ptj1a_T!70n7Yz zJ-R8FEb>UG3)FOlapI1UkOId-%atZO#}<*vK_0IXcHYYy+Icac7p&$A)QJHgj{wLg zSd&pkMH@qge*rgfg6v7wTb@_G@5w;!d-9I)7*G6p5jk+dwfIjw=@1^zz30*Q1_qw7 z&=UyZAt^k59G~?-vRcS?20hPf-)9~*lf2qJ5fGmBfzMqU{-EF*ct!g{2G4+N6O>LP zIBUnjV<5IFHLi-xbVRuagxg|X)i0*wD>X=6p$7S6B1F>xt`5St<}?-SG5k?yRN8@% zQD)-Ic%(+-iO7Un#4E0d{5B8^Qn1@pH{HO*B8~;RbyLC%^>$?`Wz2~ zP}NiU0%q5&-WEwH*)s<`9ARyGaiI?1=|ffIEuW4LIS&_6Ove`&0(b}c)%Dak*V-=1 zVp5H5Ivh?X*&tQJ&AH+3wbxru9U8 zJ6GSF{dKn5ZI)->9YEUbuHMwMT>wMNdb{mx>ecPh!1~Z^mYo)Cs;{oUP~F~-KYjDv zZ~p76H>ZF7^|xvuT&v3J#qMsQuIkmiUd+^0)9ji>bydG^zE`$h%@?csw%#mSjJsdW zo14X|nLpANJ;L4h^-@f;^UlE~!95v1OQ)j<%f(sI>4rbnQs9sOJ%fcj!g?;t$!93D=jF%6xF16n*s!jb$y;#p*f0$%$X=Opr_?;uv z-o_!}Xv*NutL1uDFL%v$cY5C_e>G`szpS=OJIPbA{suIhPbOx10K&umq%|~{tLtJc zK-$=$9K)ZD?M16AahK!k>#@Da-*W5nKwrOc-E9ulfY6e2!N(g)&Y_%^@~I_qF^% z-(p?B?JGu!KKLBFoi88E(r!yQiiN4OysRzi2+P{u zqK~i%2peI9?VSsl?q!0$*{j%|T)Rc|WEl)C&!N@wZn8Xw7SV(~m)(v%FRYV;oaMX_ z5}rkj#ja!f4q1v|IBP)WBS`hE$3Zsr7W<9GS8FpH5xw}MS<6@wpe#(D&A2TPt(Lcf z#m;GS=jC^B`2b0q`Jriy#5>j()G?ow8FCyCIPWrz-;$&sBjF!?7YH2ATt2LN#|Vqd7)#T zQ5T#q24-=GJ3dRCDS_%D%W`ZDT;`##VvA*zv>Br?nRg;BrEIkZ{k8zMkpJ^A+F?j%CJM`Ks_j z;s?+#WH#y>9B5$#0Q8HOqkz&!Y2^#t)ug$JRLbKZ@+@^cR!ae+@lhKV9C(n;0cY@Y@^ zGEE2JD$0YpLw!3`gS-0s`&tbbFPm+Ze!t)BRaU>Q@2bf{O~8(O`*^!+9;)rG zzHOc!9msD(>kk+P9-Ebu@PoGu%8%&ir|^_A-HugHfndbY3lhCL8zTq zoBH9Q*>pDR{cf>}BgJlcl%X8{??3;jzEGWd7aypO+AjXltZzY;Z?omY1!`-IdHt{#%NvwCBcBtBP zqU>hdS?%we&0^N6H@ExyX0?-$pRZdi9|3?f$#*Xyw5NoN(9}Lo21Vr&qb44q0fs9Rk*0O4L8Y%YE@%o)CjswNtTZ< zFdY-;X-W8W$W6p@oQxtv9);f)BQfHWKBxK^iRJd>9vB}b+k}UfIGszAp*yktfZVa+ zb`8pH;U-O2zN$>uBJM_ktz{T8`UC+tXVG9{ouf^WFA+29!f^|jGg*xJ5h~4O7CDLx zUnX;8d^$aVB1fYlH^~Z}Y3vF4KC*ELKwgM*T0cvLf1 zJQ{1hZB1grF=3yAP1G^hDAkz?|?E+m{i|_9I0P4Uam)GOAi5_tFyMXmQ?K zQ_76N(!?^jS~z1%XqC;FRD>k9D5fny(&pZj_?xjbBQ?n)`_3s*$Rl}h=z<&yhJeda zjf;SUgjI(I-=R`)_*orqZ3lVldYMNQE>!yo%(m#Q9B+3Alym2W;N!lIF6PLllORNr zsH{btfg~rJz+v5Wu)E=4(T|I8T()Kojk03~b__Y;AXGRJskv^cb^+8HsfbP^MhA!U z2M(XJ%WxD1S3r!HUD7|r|LTMucbJM@8B>OG4q}oneM_fH%#e`%BoY)| zC!{*-q{7M>3tr^m5Ps-elXGib9*{D0!a+>V4tKM>>b!hXdp_DdnYy0TXOF+%CmGTe zG#^PcH}l6X3RwEUe9?h)A-s9}c*Zg>>K@AqVAtWXpnKj!zBGAE3LQli%k|V;8#`3}@gYlSV8#6j=L>TGgxWc2%!>u+_~wK}&*-55b-vPBD$L@elMNAZ0l;B1C`h zr{8@2!*}0&`s5GwlbiI(=)3M$XOB+(=1ukJRPQ%$KK-Wu;=6A?)tpa%7k;n#MZOM~ z^ZR%Szn5P<`F;4En26<;b3O{Phci;TilkdLzx%0ejZfzAe z|4hbnFqLlA*dYwdWj7|KmD~Nr7sP=M%jw&RpJRJ1XR&!P9*qb5GL99l>|c$G z$NHJ;sd2^@@vm3m%P{E*!4XD*FfKr{_DYeL^vYNaK*lAxD4LXMoru*-CvlX>I46Eg zI6IxVI4yX>J!M)*u#1YgSQC#T`5L+>vIc!_;ylphpwZRXf{0Iojqr@JE9isU;YKy+ zL9-3kfCz0+;IN?9hDd%E)Y>?*LFolxC$BRyNHcQ!AyYMhD4L`h&4ym*QPl1+jp8d6 zFP#Q8Xfg+NVGHI8mIYi-DYiLX8i#jOE~U)*p`c?eyq)&)g?U~;_jk3-4AA7J>ljCT zG?EIJPxMrnE=~w0l3_tWiUBDZGIor`PijZ4S#-pK9e|7uI1>yhPOK;#Zc>Ln$Pp-t z7S(vf_nwsjc}s>sf8*nDA%p0s+e@MvhmoNu5Z-XgGeCrUFd|rM)D_A+3=k-95>2as zV+r7Jnlct>ls6(Z!A4;dk*!)NPMc)p7uiVr6D686I0%xLSFj~R(318_y)l`Num;VPU@?LYPJRONd?OGf|Mr|AQp6EOLX9ghL(?Q10-oC8K*MN zf+{?58i9ILrbFE4SV;xx;v8_qW;p~+j#=+w$`Kc3$nZCscq7rz zJFMf*PzYe6msEBlj*NJRN805K4>%UX>zA}5%%Bz)K0|KfiT=;xL42Zu9$mre08^tw z=I>Ypy0UA4{kl&DzzO;p560I4+{>G-KnYh^VvVfa=#tMYDg#R6$SQK@#QcxQBPz)w zLSQ3QJT}h+%OxXj0Ox%U1CsnjHEv?oP>ksptv0nQ{=Bfn3Rx?m{i4fZ3G4eLrO0_Q#MQZkCjdG)-0J@?UPDC9FJd^S-&Lno7whRXUe%r@9YMYB_2IpsstvvKvP z$vjkzXY1jKS@xyToXSA$MESE8D8r-q#g`GWOXPn1|01u@u?T3F<7Fy_t>IV>E*Fq) zs!=|@N{ge}RA9DzbytIYqQe@`N#?FnyXg)RRu+s+pOOQ}IF+@KoyuHZFpDLGM8Rh;wQLdN<0HK`ZdOKMa zL~_4hjwi*~R*$cx7~AIoy&okxO5%jRzM7bc5qa;|SCeY&s%K_0k$Z23s$4ZcJT$Z2 zV_T{R&U?XG!H-<$lVzP?la^~3speX~|sy;{}tT1|Gx z-NRtN*)Co-%D!II-#4q<>Uv+#?)FV}dB0xWO7`h>v)L|wX#&!}8BO$ycws=KmJn1mBLaIQJ1P3E!Xu<;nh`DwQ7C{Pw3*F9l_0V z{VI${Z*MPN)KL($RmWV`N;Vm9c>_Lv?7)54G>;-$o0s*ndRT9FkAC(6nUo@BsbWph zPFZ95;Rkh7yY<`3ss8JSdb>R+vc&cqCb00+HxIA6U!AQty|3nPw#{tQ?83-YKP=un zY!)x;UGwH)|6;kAyh#GBcAwcX!08~JhftFy)YP5333)O)jC z+^)J`oi+0}^=`judT(Ad^`_apsrS3P^=9!8nP=bpZOi1ln7?_rdyo_JH}&@6+tXFE z3zvNSefZ7aUcGPsZDn8G*n$!L$xnNXo5`17e)XoE-+uFD7~0;v`SMM|=_g1=)fNn171E}g=M z`(d(dm(g(-RbDGM9UL6Y;#->JgLHD_bR_Rq+^zg2pxUR3E4vl zQZmuD8FFY%<_Zp_?4BH9xJ2Bxi9|VW4Vm^pHky1_4c63zXX=a%6M_-Vl15u&W2h~q za|O2OGH#|2pE=Tp3I@q@i(SLw(;#*TO&Mbq`xOH*Y`Q+Kq(t(i$??%7{%AHun*EQa zf=-K5G#p}@ZJZskYZ&_GZ0wuk&?k#XByAaO7DTrgbTP)V39}4?mJB0H-jKzi;Up;2 zI6{vcgQ&~Uoyp6_c!?S|zIPtCP~z;seNBTz7%7=0PtcY1In`$;RUkd{B_n0ZiYYc$ zq{J0z4AuCm**giXk!eOs9XCz6OJ%YYFGIp&CeawGHG3!aK{$*oo=+Q%)FOCP0W@^#~jizrdCMyFmTGkNj70{ z9+pA|OR9?ngt)1^l%CJ#i( z3ape0Gbi0+Ev<037nJel*hzgRBE)=xLnr7F89)@ zfh)`vm}V%iaU@MShAT&`nZrBI8r)Hg77jA*$}?AVYk`C-|OQT5mBF~NYvx<@oZ%MxrrVT9UUVm$HM*fDMKja zizgr5vx5wSZJcQ7$dJ*w&z1}Ky5~E=n~cC*#ABpadG4^!Bu2~=f*!_P7F8Ic*{$Vd z@$#1PkPM#pk|+7XL&JC+dBQV!mWbio6T3-xF?e>jzH|c>zN1t7oNU?t_#*m^V|Uvi zb%S(h)F8J*+AapUEyiJNZ_Ol>Q?w`Li~TU%rtT^;&()B?-BCX6P#M>;x#Z>^j3_by zXXbfzSn5O{_1k7^iJla@w2C`23A7}c*L+ zoRyX{g)?R-0=Vn^;9RM!afOuhhN+m~VwKM4qxEv$%%@@e?QELaezR?`$=>g0cc)=U zeb}#NyGJIJfbr&?S^W@@aOZZj-aq_&1k!eK|FB%#ygr@H)Znh!tiNv>HEdqi(PQ$b z`eiL;dSPU}+^=r2sJQi}uH5?mp;_IkqFz*f(d^zajCXsTnY3mwVf~DM{9^i+e_YmB z^MB7r{=ROn*V#0+WNf}z?{@3^!?0}Zu*yf3E7C#sFA3)UUEN(Y-Tb1<*?g`x`l`iq*aV+K=vARn~}cFsCVeY{`EQ?7n(W9;sFyW2GNy;Otf&#IkD)M9m`R_jh& zn1$I{O8=r1?Pk4S&DC;U&)*w(4i$T6bYaH{lmYZ-yyBd9eRHG6%Vl$0FFViDktFk; zJqkNz3=Xf+_{#lHS^lATYqo0lFDmp#;ZAg#m(6O|S+5TD-Lv(*Y&@%1cZ*%KeW+(m zOnt3rYl+1pgZ2G=v)VmQdOeKGa(`Mey4aMp3wPY)gG-XGSo5a%bQ~LXiA&Es6j z+zw)X>|!O-F;j}Bkx@PkAISZ5kX=mk(heU@due|#G^054{pXiR0plR18N@^iCM6SKBv z6`*@Lp;WSkJHd-jhpav?ve@rOP!;wcws7$uVydJGLen9vQBi5E&0!GhVxpJ59s@Vhd&@rBvbwTVa#-TYEFLb)vu9bG*o^!D$OW4-YUQI?DA;B3N0qoE zluCvZ%ZoXTZ|DVSAom!5yrFblRFMw(AdU8xmv}f}?AHu)GQ6Q0l$W7PMEB?t-EIhJ zPRXL8Q0BIiwsJ6|bG%PUii~3}77vbC4Mq<>MdCT~KfLvLrA$!r z0F+1pCF1}=g^NWqto?+;VAn>4peLTnjaVCwh^5UrcsV%2 zsNUDDLn8v8_u8ewBB-r{=~}`r~0Ud{2@P zJj8`Z6Y9xj_B7#mq~M-RGJnpMpBGkws+fgRW+?KRJ#QnA*u&$8^L={H5z~5J7T&~I z0ESJf#i;-1YRhfC-AGoJ6C047-{b}sf|Mwd;Z0foDna$rfXYGLW;`Oe%uOHYYb^;v6 zivI0Db-%i-Up7|(d7gbV@2P&htG`!neJj?YqP~4muU^$^+w5e8^R5{0U3C8oo%jdm z{y&=rSZ6&fni*2LFt9ZNGd6Rz`GeXYcAy6d-dC!8p?+NyDmDzRH*qdlw1dICnJojD z?AH6;x~GyveKe+3yz|k+qcxK{-efiaC!K$}gCnN2eyE0H)65r}m=XJaWb1yjtO8J% zodwWXQ1bkJd>*lXyTkkOCna6z+oS$b&2FB|)~i*xw$<&E#lw3)c=_2oQ}Q9tN-D|^ z#vC#C=ubaA{p`O_KRx~Q6aDF7^1fLtmya?aKK}7zHNLve1$bk@C(kNMXVs%_!Rzq0 z3gG=(0$=H2m<~*9!RJ);>x6f5EZ9#WN&Z&9thckx;$f$BvXy;_Kyh5+3Gqk?qWHNP-iev*5&cDD==PYK9q2xVSFS-|@YwDfSI0T!XvWm*m*)JrKJW*Ctqa z$c|+Xk##jY5mB*a2=K_d$}9^Ki+i2`TFaV+z%26pjqAr?*yy2&`-(Ci@WE$t${~o8 z`7J}DnNc;6*)+=By0Jw&1^1p1@@hGVZcU?G6TOf{#%1X*v#9?ACI$_&W03ATi+9)Z z-EMn*A6ph;*efjy7Kxi9 ze&^_dA<79AphIHicw;$YO?z%N9^YB2Gw9?^LFAZi8q60jW zo2RtKCz>oN#9WD^mQT>Ur|vvp)Cf*{NZ!~TWTc^d;3l<@9-%?`lC zy6ip%bJ3&m0p|$-^L>PNxE8&^)nZDrr+hS@OHP#WB&0<^aY*WWj8kJ=~BgJr^8A<^7zB_c|H=}Tn)`&d?lTE?^r`J^IRD>NUzOMnXij! zI%rw>01^dq;xQjh@_ecUC|2=$TKE|grN*`}7iOv^CUu3fc_oUq03Z8fJIOCpJ|3!R zYKN)~LWRWd6uEMLp71^TfkrLm%D!OXBCm$&bB9T!8ry*?ivc9PPp9MX)hvp&VftK} z@3ynWLaGH`tvBH2>FxTK{gTZ#7TMLn+sZmZ>Dwg2JC%lUSFx?P{@HutpIKGtW6sO#N^gw1~W zj^Ra+b5+mh??BUoY-_zCUbe02ZbPaBdcTuYrB8oor9T0qZX5B64~OsgzUd{n%3~$L zaGG9BOzI7JP%5{hu^qe1w)uK&#Vg{|$+&fzo1vtrwkNJkk;Wff<$pQWlpP3YYcBF) zEW@fb2E3b(Mlsj*I=wLNGJh8S_cAZ?BgNg`tm)&1gsE}YxfQz`t!F|~lQ*TiB(-WP zvoWAxM#uh<5F?ckxk}i!CK^%`A)`eKpo!epv92t^vp%B2%%K=E#8X*3>y`>L&XQqr z&*CYea)~9;gcE8Ijy{)lxF$+c_vM>Q6D6rhP1k)NVKLPSqbM=zM)ulMdX__CkLcUB zq*k3EF&ZH;>OpA>j^>JRert3nd}{En@~`RGkA9Bm7pn5je#F=mQW9@~k> zx8ACP!VfbouqT6m3r|YQfhLBSHsz^16Q{b*K-u^<;72X5W}5(h6C3lTbnMcOKpd?Q zO$>N6ctzS?F2C3a{`VqRv-ZP9NCMyYj?Zq1I9!ao~rnb}~a0;5b zN3N9Mc-UaMIgpW#_5yAU?{k-PV{%Q>t1jWGkpbC)289w|drD|*0f$}0?5T6GKc1G@ z!=1%wSWby7iuIN&8D>g?y&&F89Sgg=L{RBi-|aZ?Lk9^i&nAi%NB>2E7_T79yFf@< zkh5IaI9SM|TM`xL@gey{IEh1>0x}{&<5&!RFKUY<;K8%u@iJn1sw+K|M>w2ANi!`- z(o-MHe4mk{Z>e3gCvh-f6p*u!6y^zU@TQc+s#p(^MU7Ao*GsQ$Q5(>*0PhSl?TMn2 zPYRDLEDQ!XV&sZ=emo!5z94mrI(uKjeGAutu_e90$|8A92V;618LrdfQkh91!LgXV z$D>2@nLCogV`r|ei|0!8HCF*c2*-Tw4kR<|@JVlR(yUnZ1i3! zJSuu`&pPVYDxELud)2?I7vFF9-!D{uQ{UY$TF1w|6fP|9UvHXKqpoj6J2PoiQGdT# z{J;AsMB6eZ3cnhJ_vhDzxW~(h=?Cok!~MPf^l|rdXTEPbyLIQI?J<4zpfmqyt19V$ zt`@78>+c)&a*XT_%Apu~wyx?|^S`FG3_kv2X$6n>@y`q2NJ zP9_vFKdxVXyIWbNT-O#T$2Mi@TYlWK{4+Jp(#HIAh0FO=`j*G`P`NA}$`_No|Atxn z4ci{m_AXzg#o+Rd%?r8Qv6F*zF8?nUF2DKq*J4@tuXoJpk4n~V{%LvI_2GH=@h4&a z_uFPJ8ksiRH@p@%o!G<{Ee}yKvwiQiLk8~g;%}PIKRrA9M1QJob`NU5ygS`*Rc;w{ z%rL#mOIu82uo$E*0UvuH#<@*>I-aEc$+3a?7?%5i>NW}0%WXK@;UeDdZj0~BW1g;< z>m!dJ<{Zb7;pQrr*~S@@aaPV4KK9b0n2!5pOwyj@&)jsN{*-ztu8^;j1j%^zqUcrXnQrU@_Av_ol-PdMZxb;V5H1fK+(IqDIvL&$Lcb*xEq6RIA z#-^*W(#zJ}&;o0i7EIUnECF9K)%4gEoWzMIw$72_n`5!aeGK?=3^14@WR9^(^w-N) z!E#PVO`IdWiw%cyxtK9{kralAsj^7@EslRfrY^D*YZ!WXty^B?HtW$1ZIhU=i~6R-SV76N z6Uh*PuU7Qz;Z?vKC7}R3pGI zHJs#mR$j+mXEnCtVvt^|v8&wFPxFbnGFN>wJ=pYR+mMYX6Wj`{JF02^Y&=wunE@Ge zzP_5MaP^h+b0}+ytJGy}(=*E$ZvXW~6)*-P(li}ALq`A9T*Q9nshOD68SD#gd|{P) z?gsg!yb_20l~KhsC6+*%LP|TXa;pHdVJs56K4aV0GSvOWObPj_E==x<;peKlm>QF* zs{GT~sc+5>z01S(U|lbpZDiY<`B`V9pM1G~==M5`ZRdl(fBNY6ZdcE~7hotN>(ifi zG3?ez!%t^3)!*MP#IcaoyZZZjRjaH0a#ydy3|0;97T+_Bwc4KN%|90NpC7&6TEtAo z{n7@wUr8=mm0pisyU19rAO0r?z|ST3K0S(kZkwGuj%uH&s;a8LsHHk~(nTdt6!LUl zu9x+0v24_G9frB}{>8FUqEKJVVwP6q|KlkcyI$1u&aB?X3ItR?czag zn(cbOnKf#;J3oqOV$^MGNsrwrhqAcI*tYKlmD|ibCt4yv<#al@r0FfzBS(2n8-XX< z7s1E=5L$~w9rjNYp*~R5VF+#ZjpF)YWW>HM#w|mjjD) z0k-GJQ&9G5?3SA5Ese8M^XaJ#UC9K-2M8<&$3ZAN&9|Ip`Kzhc*97nD9Pv8*sz$dP zfG)7NMC(F7g|wmR+@DkI=3+5LIB<1^)u3L=-h{f-g+=%xUtR(Ao^TK{A7u`$v%2IK zvDFVCI7(zZM8Bh;g1QPIaTL=)u6OC1fHF6l+*o38Gr%$xY&r&0(FKQOT?kB*X~3}* zc9~2bQN#DYLA+}a?;7-(22fx!V7mj8JA~+1i~Fsa7!WNwA5T@Zr)9$vi0g45do(>H zM~=F^gyss1Mn`lw8p(}4f$5jP*~|fr8QU@vumUEIavap?AmSK373qGmqy(#BUA45O zSP+%PjBT~Y{VPb1@ywnVoGLVlw3JE|9?~D?A0;~IHHlRch|Wb=j%L=<|7r~a9s+#q z2(q5%#$sQ!5Ym=pG>faiqGPa`kBxD$EP2FMfa16qQtNwE#mPm}sAUW86^>Ks3$uce z#erZkKnCoJxLk)RuS3VJ>ReUrZCc#%7F{*K4f zA#8^db}YHV{0GO68JI?68{3gH!fL5@6I-_9v%~S(;rQ$bhZ2E$>^?@WE`1a{3l6E2 zD_o@WrIZhQkRyl6v7&LMeEth(P8GtbM~OVrwz ze^lvYBH0>FrFN)N`&{y5!~YL1%^*{UkfxUOoaWCY16U;U7P7RA65Zhix5Y6G4aCE z1^dm}Ut453c>S#KIr`?^nO-sE_VH z`Dp&hN3Rvpt4c&l+h3#=d3yT8q01ps=xV*GXUli14-SO=C!)BnAYp~1U##ZM4`*tz zt+sz(E*^36qH_@{I0l$TLHQ9%&fh5zZliGCEj;V|_>1jl+{ zNu#myJ)I!TO^DSF2M6Btf;W8(KjnY`TWn04R!hycS@-&a-Ke$EEao*K69GUX6#-7l zceLg^TEmFw6dZ}hQzJgqeQ3!(9l%fynsh_W_p?Srp{aq=>`FDCN}7mloe?fWriZ4y zRm+}JLyTyYo|;d6U9@s)prY@SLn^Fk0bQC${j`r22od=aJxUWWMZKC@FhbhHrz)Zj zDIBx77-ONYln+>BB9?LlM_7#msgdwuoGea_qgxmb$T&&o5716RU`U(sS+pIN1`<=F z^N4l5hC@NY0L@{N1%uc-vl*D~ghQ?)iqpitptSZe_625hK${poLs2&%A-1R$Y+_M+ zcx;E~!tM3)i1ebS+EE`yMOZW#k|By{8?k~#hi|Euwxp6+5^pW3m=+n41)NyGwk3$f zX1&-AhJDbX+5pf&p4r?PB-Q**Qt&OJ0h`BOV8Is_%bO)-#O9)MwImf;YLYB60gJ%b zBI&ZwY&N>x@Etq09WEisA7zY7&?6)$K`_uIQL_!rm}D`16o@C$qKtTs2+RQZ&Z#cY z8~}dkK~P!~G~#-F3*+f15tB&L6Xeb(M22dv6+N-TwC2tWL1cK9!%TokO?$3_pwxMm&g?<}nN4vuTVs?V$xB z<&*?e8+9T8MF&tscapmjgqYGKY!HD61&fx)6;-x55fch&zgxo+!Bb2!O_U2lt4-k4d9`&eL`nf0wlwv?s2DkKBT=k(LI%w zJ|UtMuZ%}#<#{1^{0<&5zbA{y_cCqpGG<6cP>N^{(pW~j09FWpE)dycWcQR_cs}m~ z_C!fe3Jsza!{6bYgi`Pr+C2%?o;8Bc=t;|D0pfGl<8Xq4+)z~PVo|Zic8E|!WFsXv z69tb4*L&CiFHuZsS>$6on3DaO`imGPQw{U7KQYxjpfb4} zPRCxdXX2_=I*R3seKek!me*Am#tQzdoSBY|iwbi!c5+STZ7|xAt^&z!6*V{{)1%&m z>vZZ^x?Ydfbq>db51X0z%L2`E0ucBwAQ_YXB4{P@xQ+3w#}y5smtcYrg^0% z&BN@jR#)|EF}tgqdZk>w-_+Z?-KJLVUX{1?X0cn$)O;_}50LnW0rR$A%sY!+=hb?@ zoOian^+V^b*)%7e7yDgjwSE=QFIYUBYrdEh`q`fE{f33bYO$-NVc>DS!ZB**SjzTp zwOaRoHg2|m^3U7T{@EoQb??7Sy#5~%=dNZ=XV=_6tT*-Mb*y6E&DH%(?KTJS|JP$N z!xzU+wJ(38R?RE5Uu_q+tA?`ba3$a zKIyDq>}qkdete*9zi(d0*O^E%wtruCR{Q%GQegJ3-}C-;`1PS?`u#J!J$Xnj=;9yE z<`elt89BlQ9HlKExQN;Pe6meJix`u4rC=#h8y?j7ss;k_1aS9_IY-po56(?|U_2aZa=n40toLB442GxOXPX;C_J zoK{39|DRvbw!jo3v6=3`bIXW9(g{?EPGD~n6O&n>!ZX?y5RgNDXsmoX5hg|RMWIFpYf?dVPNxJ6iO%DI;%QUxWMTTEpmW)w?{J9G9U+(nq&Av#&DfGrs^Dp07FwTp zI@8rXVpsAQkZB>VJ?eGl7KG}M+FEX|5#H5|M2~4kl9gaGLpvLPmU)P2YMm_!m5$j& zK#Fl0&1)1YdlczjIBrkDf|q25Ft418_9B4dQMWjW^U8q2vvTPP{M|>yN29NV?Rd38L?v%dEj>+V(OR zOVj$4A2{Ucj4?79v68kxW_w-;vz;RU#!hV0LI#&UQu)5-6giqP-BQL6UTK!Ci)9IK ziFdH%$y-^GTNt@8ydYdJW7<4gD>WasB>V+t)v-5liP$1sB5El|dzYio!cofQ zSZ_IWFs|39YoX83LsLUfWIB$K(=lZ_776aWK%r5HiajOG1^0l1fp7%=JElxWI<7M@ zj|FK4A-N9evqSymfa{KsT$kxspd6zx$-qPkg45S!NcVGGt+~!(6ed4(P~j9PQ&N}9 z%g@n&;c^R2?ih`tTHYfN@sSc2DLmF-N2P$HQoxn5y1}DR7cC5Hv4S^X(Y0~330Gb) zSr;}6)v0x`;f)afjkRouM!cMo*#eukPoi`Lu9;`l^J(rAG0%ATCNDiCJ`sVwXNl=q zU-+JgvHS@a$%yJH(edYnV+xULWgFzBnbT9A6J`+%tfJ4ri0v^Zd6I~{i6sq~X=$1d z2TN$mhyxsW5*cxNl-syVn%MdbDp?Fhi5hmQ*vLl_HIpw}n%rgTi$8|x!JBDOji&jP zGPb;`rt&>%{_GzO4rQOv2B$8jsV&raJW^xZX*DHd>x!wGq!(&p(xH-uGm*PrrJ2kj z%9^hWpHAKxC#3sqnm?nVL6Nvd^_sg*3-Pl`&w|Vw5*ArZWjYXoycpZ(G8`4t(hkDa zlt_V9X@|KInQ>dFtS&a|S0bi3kjZBO*BuI$2kX^LDt0@nU(Y*t%?}-6+B@ogL7sb0 zT^$f?m=Ee*M}7Mb^=)6JFPrVIUa3L7s^^P(Ri!W1o5k&7RWH@Wre5vtYIRw!7B`D( zy1rYiZeQ0bK(KmK^+kv=-qp*+>|Y@6+nCV`Eyf4h)i!u&AGbEI)}0?d|E&7#zdJX} zb-g>p{BQqF&BhVsf3jS@ynphrS^uq>?Vjk*PCq^U>@;A&!vzZ>9KNbIH$r1?PVXKb zP&1E)X1pQ?QF!m$W>*C8YgW6>Yq$7EqgHEV`A25|H|jBd@0^~Vc2t;awmZpt{Jh$! z&f>nl6%n}_zEbNKf19-d?)F27w_OOdY4Z2=gAzb0QG}Ai^7nnSc^%;>;fb*b`CSoq zfW)1}{HVf?k^0qQ{)p9&IgzTx@IQ~9x0{=Hl2<NbjMP({MjS1_GmmQ z%=7@ZGxI#wD2vZk{-E6{cq)`jcg@dBnwYTokj?&3GvVpk)_ddYBr@B&4wl(USreL=u~yiV}!3z<0}jYgGE)Gs(a&U>l4Xq$B}ajRt_1W?WVgv|Oi~o(O6G}n z>5^+tkPH;3v0RVs)2tTv6=dwYEbc30qHsvQy(k2XCzKyay75^XZ-35gfIQn}>@re0 zmBIW2}ei}1pdyN3Nb@ZRChOcaYJpZ^>DdiGi*FN06RFr{PQ{ zQW&c092qC!Eh(^`<~H>1jyI1(6y)Hm9kz}z0<)_?ha&TF!1^(Jk+2#tyHw-3+=A{c ziwJr2UGDgE9#lp7tQ2GF&H!wY8$AHN+!Ci`LmGzS69pEwDcq;HcCE}hzIDmF= zx}?DOWv1|b5H=sco~Oi98|Y1`V}Ejn^R!3a4DxM!rwCP|UPWLzcZb$Mk8&$ubwn&; zY^BZ8Q*I}cObn)WIKFafkWMCQ5a6~N49ck*S{b3PR!UA@)h4k>Ex4Pb)7o*ET0ZlJ{@0-Z91uj{ix$krv=M|>x*ja zs=T-~)2c96*KPLB^>lp2VnO=aV*n)h_oH_pNPcceEMIqacbn!_r(PZHv@ITuG3Mb6bu6sASmwLx&de!bWc8mL_^XhJ~Yz~&s_sYxKyH$zD`h!6@G8hzXTzoyB$8`9%oh(!&-X}PY$F>W;E^)O%5%VxHdA?oZ*f1;m$P8U~r4~E$!Ez-vxRTBn}HkGIC z)@pw!$vJpKa@$f6he@W$FD@oWkyD!$|IGBWaq-qjBnDH5v$SMzv2t((zv~g(1}EDF z8|6(hxM(sYMV_L`!PdP@$3m^RC}8xE`2Y~2(L(5yy5)X6&`<@%r27_?lSSTyTa|Jm zZ5)lv^jx7B(tLGktYI4MrA9-m$-L7PyJ{#yO{*Ta3gAsI2)O+p;#PO+Q zNQzLaK<9-DRzpeY!r>+rW=a#XpyNXZ=+l(sY6J{APK92mGXqy>@c9~j!t~LPVtC8H zv^D!!rxgR-QM@yDU=c+LWkrH+tW1N3#gWOg*vrheL3HB=Tc&ZjJ)uSmtvi*>+!AiA z@s8GJc|nZ2vK<-7ZO1h{sxY7(~UB+}1 z4kHe@LA&@r1^qK4Ta?_E&NoZ6izUd(ion{k*RmKBEsjLXtKLdAnI%Wu64hj>6SpZM zDRNq@k;oZKN4BLS+mak^VK!}sY@LNx7#(D#AlS*~PREKYbX0`raAVnI+1!^Is`s1) z16nD$T2vb0z>0uUEb&TMoQdJUYC(n+f=nH6T*qF=VLx;U(s#&q0`DCm-VQ&E!*J-x zNO3)h$O;pPWqlypC;FbTA3BH!hdahGv$^gJ7Q>= zEkwCr8W*!K<)3quOiUD-jLVY2Lh>(J!g->iJfFb+yddOKCS~78O+;^*??>H{7zsQr z_@0G?hrRI#(ZUR2Nw1OL#eYS9#HX?!wF5E$N;pS-%(#@X1aF8Z ztJRY)>WLfkOlO`fUmtG5*&kKfcPh2%NpTZ;lwm`|I@{_gzORAeI zmhdzSDc`FI09{Z`Rwp-Q7Y>_UdZAx|Kgwwti9XP!TO| zSI;(!fCc}TB5~eZ8H9P^*&?8XXMf)>Hcba+U3NM%8ml{t)nd1(m$5QeZC`J9&HZ~ce_Rz1 zK&!lolh8&@#;!0{Ky*4P%v7Ae$H7?ZCZz&7F>5%Pzl zHOqO8q(T$Ctt~eT7n-I4L+4I|w6hr6PReAD#w1e$pffoT%r0EJ2G(dCm!^v;pz9-V zFT#Hc=A@*dfdSVzfXr^6_-@gN+1W=U(8FP(s=IVBRE%te!_kFhKcu-LDJCUqi&Cw6p1b$b$e+<%RuPpAuTg9S483?gT<(uq3y9W8d+i~C7Ck= zvS%0@GN0lfkTPD2P~M^nv*^HV;sm579$Nhb$1&#gw%2`0cDl}&Ei(HWi*mXu8k$6+?Fx{Iz|hZM8g3Becr1s!9baSM|pQT zwiE#yCxk~5^d1jHpCGUiR7nu0LxTt*~s2ifk#`U8!KoFDbN2v{q0KDT4Gp@X;G;#SReRF#+*H zwwHWNl?MJAVWj7^?~^Qsz@zx5X-M-g2`PyBW##ADi+F;2J(4p|aIf#9fnnq6an*pB z84x`$aSvJHar$~vt9QVFHkYT#B@~a*fgtmktKTxp9DieRDCk zor}E4)gXM04f4rBQcvUPA@bc6MfkdEPd_5r{e>E)&#M@Hki~X&7Rc}^st8Y`!k1`|o+h)^w*euqY zFkQTx+7n|c|$KjnO}5lJdQk7rn~-et94)i;7n|F*5>&7+Fa zYSwm?3JRa@myMFns%CS*?c4T_->)}KXLl#HOwF-q^bwNhj&|m+SM~j3_E@?Tvlbsc z6wAeSrxrJ}_3CDEd-||hzn9l?K+He)3wgdpw3HvS-$!|_ayv=wMVVe4vl4~8#+f@c zZu}P!x4)I9cnomf(?S<;^#}(pNiJEm-VO*c zL>ALU(yqxeH0af1h#?|&*@bI*!8H-dFbpCu)Ou#Yj%HCLBvsCl?Nq>mpll z4cgIEfNRtun%EKz3!-fdWS4cT&H=zkRyFoYO*Dq4k44j8qrpC!qy}Ap&@ogZP}lL1 zD~;_SmIdlVjBnA#%*iRoft>KDb@(%iA(f!EBR5> z$Hcrt%fBM4mlx2e+aut;SCD~NBC-d8%S|73T@tzM6Ap&M2(A5y@IyJIv1qhyVH(LH zYVEQ7LIo!ou`lGHfHAFL6HDxy#dv5bzO*C{*%J)L=k_d$T{H&|^mf!I#VB`z2ni=7 zlN~39C6>ezPGoVNS_~N$D$fF4Y}RY@T|nn~OnpZ?pHnJoBGa8yF&Z=A(aQ9w7}e6~~Ua$uJXeD)yEN(oWE*Cmu}?xW7-$Q!IV5z<(je zb!i47$~i}jL!+rDL`G%@g2kOdc24k)%ZM&y&EWX32#2VImjhO0a`+v|;4b$Oo}1X= zgdV0K&qZbs77LCp2Zw#e5f|=YTpbR7$J@%uCr;7Tl7HBhsj2A7m{lO0D@I-6w_$_} zjQfS7l+=^|;$<8!2v-fL-T~(waNg1M)T4$p>S|~sMOGskbru+&#$Hddt!LQvNT@su zOW*5@owe7O3&H>3@j3YuqS)b3Jl_VMOn*;jhwqPCO+2hQQX8;;Cewt;=zEf!ThFlT zS!j7^2~Q3~_)yBpis|Cr#llN~4B0aB(e88lS5ZECww6AZKqJo=1nG>qE2S2S+lURy zV?^=Hy`EZG&%42+P4lI=jy!G?&)UK>f_d?oz@-bER%t9C9f;0ma5;?)rA7^kuibNZ zI-HJ+OZWAuvm)e)V+qVV^F#QS?*P*~`A9@N(I`8%)=bsd7XPiru0m*!oF$xol*E{s z=hb-F+J4oQnO+zrG<%pS22+z3CJYHhJ~frlcxr0AnK}{Jh_t3%4aC92{dqDjOcl-( z&_@_GD32^-Dv`gdZ(pfz&f3_U zZ_fTI5|Fd+)Wv#tx0tERdbg=p>T3VW{h zt69Cjz1to2GRfh8k10B8xm5e`Uu$?>u2;7Q*}eK`+qroJ?q&4o-0yeI4+q}+E#=E! zyZ`6^eAPYs>i>4X`Rlje{@?H3eEaQb?>GPV&Bt>3<9PbxH@}k8zlx`S_2wI*)jxgm zhhJCU{a3Gh_SLti|F0MGn_llXy?+*O|6Zc~TjBMG@cWo^Pni8XN%jQShyUzzg6{um zhW%Rs_GA0zDj&WXyEis3{`Yd}-;SgI@aE!C2t5mkw}zk}e^Qb-+G!&#>32|KC%;>7 zC5yhk->Tc)Im68KVr(yt`S8>9!hAh0Vtdu)co+*^ZL|rvYhwnNKclnZ$Kf;3O$Tog zFnnN0y88&#O-aY=NIG6ckz*y)Pt(k)6A~mbWooEN&6i&ocPtJ8{-w%_s@4*=H(3xFds-Tt71xt+kpa z8%mK~jbRJHZ_E z7^IU02SBrbu}J_a800P(GD+s5+=Fi-16-SB?S5!rCbama1My3TL()>07$N;RJ7jB} zBFxC!pxN3CijpiUjgwU?gpEKA=6I!>1gQ{c1iJsC>LTw}Nia3W9+?)|7CV zgjA-{hBqAzh{K~=g6C{dr$HQPI>&SXhczq5WIYGGn!}Ejhof2`DU1d{I0e>0N*7H4 zt8nD7oT1JEN<}Ray5<7K7$_t_)p!)tT*#NJg+xJ>K%XOph0)DKm8E+bxFR?v2RJ4N zIMCM|89s-TJVzgmJ0fe8G9d=9Hw_Mqs;ltIR9RWWOhA1kjj$3RK+wVjeg-&op(o2l z5Q36HNM}kdp^mPj0OC)Cp|XTo6#=_w0Si0z$Qg^GnFbN)Y!YR3Ri}uw>8> z6?7RZLC29$_m^l9O4P3s4j?kDOEw88r@C8!I?SLR&rPR1Qm_?9pHo{AIPcPgWGBCnw1v0cv6G^Neo87 z1)d`?1S07)NhcYn5j&E}!Or*0Gik^$eKoSbSPsmI2L(tJyz1B_PecO6@>r!@E7t0T z^4Mk?D0vf=l2-Uhmf=2MtdzY{ZrGbFc^it9_9_joZ-j;l`NFtY%vXzL?Rw?v;>0UY z%+z0|FKuOdx{wcyZif6%LyTroiaq}dax+n=+vTxJzK|c*1wjsgiR=Q-Yrsf*?&fZ_mnMbX41cq*I)F0I@oj5YZ#rdd+p=D7 z*?44G;*`({eG6V4b7pSAtMD;rwylkhp0c)$VLf(=`a8oPoQm2`x7k9s{?oE<^*8;E zdb5qqdlnPwPy47F{tp!#N9)%4ZVm8oV6?Eg zQqBiPXU4}1)j+8@RjkwcnM%EXj@!RC&7s}v5r;>zt`l>HhSRodH>d=<(rIuEfO^8q z_y||kOB(|%K!6Be<|W7w{us6YP*^sNF{)b_$_;on5n(aefM+ zjbiMebgqqz(@tn@7aPZBr@#hCY3zZWLi+`%T2(frP&Pnj2yA6!`W$$El{%u4(hAX3 zsHH-Qs2?2^fS3g2?S)ZU1p^w~1yu!TB!8Fz(i8=j$wuZ6$iHqHB|^GYqv`+`3*BYW z^;ZJ4N43B!4Pt`qQVP?^Dac->7*vZeE-57B>d?VO)?F4@T5)Lb@*o4J7&v(NKXV9y zbGV?XMHZ?>9DHLmTi~J#nWCsP3nRT6h3G27Lh2I1$P_VvpM>Ec_iMEx-JyV#BL}I4 zgVe$Su;Tz&a~qOAki+3Ad@j`xDl$+gT@9p|fkMTAivl4T9TW{8X}@!Zp@VMk6Q+`FjVN`1;UYV3b@A7?U&&5^juZ zHJS+}jMOU0E@%4x`paFeFYau}Zm5~2G>QpWf8CnQ+5+09`UJ{CE+KlH6r96j==x?@*FA z+@O+iEulZ8ArhImoe4xoXgFibq>~juOi?DnO@CxuYYcFhf*H@8d`Y{6gG_B8-eYx^du-t?sYt=`&re)GKrh74ygK&bO^>C{(M(e4$20;eXBnO5=*axL&R~txbSSyJM5~1TU2X zyCatxq*c&TwOcUILvuKwdetk}bTw9`IZ;g-t5nt%3pJXo*QaYVWV;cSVh#@*msC5h z%~*%ECu?>d_G6~ixdXDj!yRd7v`<iW)v8IObx0WHUW1iXyr6gS*YX0AdVw2SFTf7=>9`4g8`4u zAS%f?fJq!eLNLT(aM)uo2WMcxF-%`ENH;JC8bFTG+B8m6&;o@(hFX|RSU_Ymgz0jf z{$hR|Pz$8%NG})+-I>nh)pHGA02*Z63hr5GlwVO(G{4YamXn0HTw^sF@o(S}>0o#Fxah|+Ul%sKqZI2?PqK6QD&o`2-9e&oP9 zaHL~gs{nF%`SK|AeDKWYAdhgQXdHbXj!aFRj}H8zxON%PqM9jyaZ=#Mg7KOHeh4`& zU@9Ei@+tskN*k%IhAjzQV{unAE;$&194@}x#kb+<&a<{a+N<+%h%<^HbY-A&D$q$2 z$fE>sSOWM#frgqup&)Sm3&<3SFy_ROK?(T63245HR_NUKV}=~_q5?p20V<9Ftyn-A zS71;D9FhgPXu<|%0DS|Monqla_$CYFeGtn1hTR%6bJbCx@?rRth2beOUKv6HYhLxk z_cY?_>1mzU14$*|4<|6JBCGp1E})4n*C~|CbzbTM1e68SJBu?sYo}N%6fJdHE0E6W zbPSqDQuiliP%tE{@H7Pg9}~|(X$(#Q*U>Y>P&blc-QSY1+LQgR&fX%(F#&&*@Kcac zi2g$yRz^AgrZ<9NmNwHyqc(F5;}yVt4Y;wh8bJf&UTG3=l;aXz1_|p0mBbqG4oI#@ zUt!~lKBjar_YAax+Vd3dPIkr}&Lm~T zwNv&8#hf{ie;{rTWNf&g>i;2KjN2lXNk(morz2uF(2YnXhbfsz0B?iIZawECBWdmM zL_>BwnH|!?ltWIO8o+*s+c`1l=y_}!9>}?wiKDvb~?kk z@zH8wLeB)N+^R5DDAx=5=9%XnDW_K|PLwO-^Rkf(1Y*{nvOqV6j;DN~RHzpyUZ!!c zR4dTRcQ=HU9d>1gDb=DQXkHHxx=2HpHD7iqEf@!O3hN&rrsVNo&S_2sogZKf1SRR9fAPWZtG-)7B15z$@ zC>Wm94D%Tb7A&ma)r+Y9Iy@^FdX)@P;wo=9S~LQAy8ty-LYW3Y{}2`ukQbv&V~{U! z+|sk*DY(-@T#!Ngj-_A|1|vrXOf>_nmjTbqpo_p9*mgN02p8CXliC9$qbI&$70-YK zV2(t-uNip^+(-tw3kJDsCg3FIq6l)ifybD9Uspj8A7KDmGXSkww()=X#WDbB^pPX? zVgQpec>UWU{g|{tX;llnsb|8G4cq8?+bnB%ykVs7hNP=y^m$Zg{v0AXTo-V*z%;io zIyWc|Fhy(&lmkK!wGB~Dn3N?j-K?U8j69qLKn1G$$j>2t38q5|Sf&(^yeesjs=hj< zQ_#%efGcyzzVe_kb%ot3rc^mhMmfyfIXt(*0JH!~!C|D&fzIOLY$Km%8ki!?A`7S2 z6q0-g`uWJ~1uR~XnFA#s1pzlIz!1=RHyZKWMqUrBIfpAibgtc zIJ$GNRk$M<@cuUZT!H@A22tEK9<3pR%4Y_Zk31b>_YC^>AwcsP78*^@jD(G2@^eg2 z!wO7SA1X1|A~Z}H)!-6_RXCb3-iC2228eY%B(UqcbI1ncq z6fS^)6L41(pgs%0euQHzVD;rKz?=|({RpI)s*Z)UWy;`CVu12Ph$aNB%Z4>8Y`8FE zt*`kk&~I6=@3T<;%-Xy`xWxjlS~kEYP>}&)O9suF0#$$jECphfaNw0e38yYY;?)x_ z60I4Do4O3^;7D+~BwC3Q!p9P#P7)HR5~Z1h{;>q0Q9>S8Mmeej9aL$@5ip5g0=<#Wk`78UZqes>T6Q-+`_@?#dFFMTvMx7-(azdl|=Lp0ZX=ij|{ zBqNz&1K#hZTvo)|_g*(t%7tmKR#UY@JP~Q+%2S1@N_F!b$|k-C$_DQ{<-)L6tNH#G zSX-~ol*hb!A#X~MQ^ORkdc{(yKm*l6VI2*XX{cHuUf7s(y<#psQ=s9Rr&7f^n2uOS zVso|VjnOKv>Xj#Qv0}Zrr>cIfUYOoZQ~%{C-!GK8*D{DR<=V{jbfpUQ89luo&;mBv z-Bk+>8SmVN;HIh+@-qchlPsyJRSLz4g)*B<(q5YS`Y3Qhfbx}@(NcjLGL|$tQ!M58 zC~D^IWb5=Y=Va0B8f&W0dL30Yi2UOjn9!b-+-m)DZIko_-?2Tq zRB&P`oySL=ERRPrdX7F48^oNwDHFipg&xk3v&P9JZSF>PFBWw9Fef{ye;LR`;x@PK zxZap_lCg%p6<(*aL-S>Y%*2yoI2{>@FDzyJv-xKAgp-cj8JekC3L(S1D}#`;S^yA(8Uu1b+;REQrP&I2ruksPkhH)!(D>L^emmfkR#&Cci4j>4*Jr7zGD} zHFZ(p7_EL78p96Q768%OQNVsqZJE* zMHZEc7WWr`$+Q}njMO^*rYLDOBK<4^k^WXKq6yH9KA|`+3Jy-|1MPB9DWlVC<5N^q7R{6Bskh-91SuKf6OX#yM*1UM!rAJ*C*Tq;pi(1%o)b|H`Y;E?9>m|MG|hz&7J8N++W(l}7T}=@ z6xjmFt^kNkpv)5v{DvI{?O}WE_#T zc?b}A)FB254?it593c4RLI~FthCZx$DOpjVnQ?9@aI2tl8z>p0BLSDkuS7+p{A@fRtNgM)*2FgNi!XV@Yx)*q* z*F+0hB7!ms+EN=AHOqf^VLIXoz|~Py0O9B>a;UJnMgbt z;aVOjP8nM|Dcw4VxNb%(0BHpO0vwCTMs-3W8r^>}A`GdR+>v41N%%nZT2hl%4ceS? zaXZ#SxuHlbW>YTfCVHra*7nUzPZz3vr%=*>BD7)w4slCYI|0~G+{9Nq6Le0<7b9Kj|kZ)wM zfkJt#l2>W2_F`(}`ZWJFGo`{PYwuYo&NES{#}W~$){3-gYO05zmA_2$E`7?Bfof%@ zUMx3MgeI$%jdNX%P?!v#GdJed>eRXbt6!U}RO?iqEY|2Oa%UhnH0tHC=58XHqiW5C zs`whcqBpvmDE^Y=ZRzpdLH?#2vpir|tL2I+EGh=EM3K^bnPW7QHcl4GfqHeb8m)T8 z(4Pxsh}Nsh!ZWl0s;w^->wdYQc_&<5Iq2lxU+SoeLJL`G$E!28v@Vo)9h>y3-k1v7 z8C$5Mt%K$%&&Be1q1u3$)08(oT`W)3OebT$_fafQ&(s6v&oow1XQ8ff_K+nq#SSef zWb1*3CAC-1o1?E89z?BpdVy^2s!QMD2`4j@T@nhn9^G%Xy#5VuJo>#y&{CD~BN+-}J~YU*NK6n@vq6YW1cBuU zf&>{hLXt3QVPL*7V1^ld;#m-?K|yp60J&hgHOj2eS2jjDmt zpUU@*C}#|6oJLS61sTpTJaRRh9SO8y(*h(U3`j`t77(Ip;Xs@-gaxVuXyaoRAM;oY z2uxKvII!N*t7yP6vjOFSItPP}IRnI)0ei_XRmmLq2jfA(kYO=kH5h1D3`UI%z+(nI z7j44HTn-T;ux>Ho$bijYpp`PIiyw7xtylmN6xN6!VHyMA*-9uBNnn9mfdv9`9kvBF z`Vnd&(K`T&UI0EXAfGQZQl6n!;E*ALMt%xfMkyedcq`QO0nmptvCRz@C<<&mIuKwS z+cJf8J)8m>2)0|u*6ond@RZ2igIM%~1{+1v&S9bj4_*hZyLxIL-a$Ml42&I(1P72H z=-nenhn!~+O7~G@;Ly7a!(A72J`UqI4qaFtfo2b|*c{Ll9@Pjk4!tW53I+%Ff+Gjv zwlqds#z9LrEK*3OF-giH%FZ!K${pjUr860h^G0Rn(7y+>RZseIbfP#I+8k0e98xqK zrxQnA&oS%CAz>nbo-*il+nC_?1K9)lPVicVX&~TlNR6SpB*0k_fK>@F=LO_q1WJ4X zwy*#iMT9l8LO?22fGH`!loT+E7U*UPcWx9DNnrFv0@X(fo?w_05OBiP)7rve00J=yS1k!8{2+L(;Z`UGAxn=y5Fg+ouzoQm zEnK5zk8Nh{geI?I(BVw&h8PTP89+k3ABsQF>f}JVOAQWUCLvE5K)VChY6y8b;O*!m z0MM>44T;lV!nIuDWS8M6jBYV&4@mKU)vdAcV_vDGQY@`NqJ>5K`tQxWg`zO=dQ%~O1*0${AO=qyS@$vETEvL{KOY&RjOd2YBdfwloVQL8drE!`n)IF_r-@rjFKsFgdFWLu&^oex1 zv|DCft9#{oQSINVNP;@sI%uX^GBnW1`c%m-*NgSd=8fu1sgNt?$)w@|4KIV6u7*#Y zv4!TbPYWRTwFU#!E0ro63wc8U&8W{bm;xpA0WYwPPfwwu~mdq-#2ite7?NHi9=6O_oP3t|DEbRqIS=5W_u?GD*IYb>n{k=<}h z&7wg;HD0`Nhoi-?#*f)ws0*6Oa!NZf(5z{hPW*K$5De*=tDrC#e#nDD8iyMMQ5G;E z{XYlDA=vOri0w!5!XW%@%<6Mw`CzLWyg%M_7*Iq4Nq!7-`w1;2s`Gh3uGK=qS{FDY zymFz@uf5h8)V>)^Hdz#spnzyFC^Rx#Pdqcw!Wia!7$oJGPO0>hl;JtTQo#GbOonld zmS(UXVvcYj5{ij@sNm>k1jPTCYal?-5`uTB%BR72O~6D~82+nXfcI;hp+XGVx!$H7 z(&?KWg2WB%pH$`!p&adF%OGQu(Bd0*Dg>?25NDX|$DBWa`k2q>DrvS;(D39?zX5yG zhQ*W3L9pe}_k@kD%HIWM>y3C$2=rGQ3kfM50mmzd;9#~s+VI)cnxSABNDlEF-q62+ zzJCM@iTU}UnWoo5q8u9j0u%ZIQ~2g{GH8r>QyNfYtaw3jg$xciQ}_+SDFHb! zokX63WNHd-yl_5nQfLQgP9S%rZU?xwG37N@S}tbywFnEGT160wm&j5DDtQ4Cuz<6j z2&cGNAmxV!jwY3Y5iD@nB5JaF5k&$IOpwM?2?#(5#8?0uD4_ZyV81F*n2Hqm0V$AC zfxHqRvJ1$s3e@QWt{Wm{^k+hPZ{fh@FsRT#MijD7^7BGVTpt-_US74T3Tf7R? zX9Ca^0jVwFpjV*J0s*?Ea6w;yAD)1mmO%4QXyN)ckp-O=MtA~5U6lTA$QWYj4Z9(! ziwM}xxw26{s4ZtP_kkofi(6w>mFW-)MfIT5Yv{R3phzVQ3nk1QWDq$pm>v>*F9|fM z3}UK0D4~Y~Wq(+&NLa5(KujeXVG>26gffx@+)P43O`_K;`)z21qTdh&4MEcb(D;&| zgh_}VNzC?0xIIYB@2C<)Pxc!NtuSnR!zen0sUh%xV2i-dg}sAxAP1_MOVYu2Bhsp# zNPv@oLPA$Fpngb~gSMavLaMp|2+2T=9H@wDz!j7bWERRln))0W9!3eFE{a$@n%1R) z&Zu?G;AXNsMxZSSirZWmd#t!Ea>j&!YzLw?22%u512hchs)_;bWNcGhaN%Y$wxlF? zJJkPrC@B_zioiYqu_4J_8cM~JnK^d?O;aGghK4gv%#LR>c0hZI3EPwoBVrNHu)V9MR!65PH;{Isk#sJ{sWv=Uq@22vW=gc7 zQq0r18U~v5O5@bmcML6=o~uVjy;{L&k~ZF&gFDseXf3;n+5e;Ww9C>A;j!sym?AWo z1^Z-ppbOAgU6&Xar#YidMpV{x8{amE%Mp7POiZKU1QI-4V&OmVUh@3d*z zc%{10tL6)NnyD44%e;v~xvmMwbA@)bFfmi|stfk4FJLfXbB(Q{0eBfhFwiR+Kt>cX zl8D#C4joJo8NCvMX25KGy9E3qo zo29~lG=&}0$bc;wFi^r!D%3`xp~)~O${ct|K#-n6N`e7a&5$-Sw}D{-u*o*spr(Tn z1+_sy04M=F1qPynKqEs-gaW6;P^K`wmp0So3DZCp8^>=aG%CSP>G?!ErIjx16pA4Z z6EgH6z@4>IGGUZ{jKmKJ5dtP;phsv5ri~d`RsU#wQV_fd-9r(mmjuvFs4i>)B_g45 zYqkvPLQdiUBt8HPkuA+C0*(n$6hW{&)A$8-P(hSLszgEAlLD9{g=Sp}rF%+(V}VU_ zfHOGcZFvwKg`mczaNzMcr1v=pq#Wj_9Kdl^4F<6=U?mALpCB3_44OV+UATY>Z5x_2 z${4M7s}?cc6%nQ@qAM0uC77(|V3Kn1fH=^39QGgF7RKI8L!}U3juVt4yXQ#Vcnad7 z(5K=!H96GXIfN&HqM*|TXNGQmdW*e%Zded;R5Ky%g62}bd1c53^U^>Eu#+Do6+HwKS zITzC(E_~fxa6Ymqv9q?Rme9QbJzl~%7*e}3Xmc12Ls%4iYtXa-4^;PuFcuD~BhAME z{{z}k5`-p+^Fe~wB*PBe7#v;Tz*ta121=DoA*c*NNi>Ms2?P$nm_Wdhc1l1+6!j5A zfKp+23x^>u1cC}QAS9roG6kvAlyOhc&qxU>lXOx+=nJL7x){=hWftUeJO?BspCm3Q zRRtLqMryA78FJ#rt4*`HS34Qf{f-zI7K0I0*Vq|@oSNfbXqnM?6dj1T?b?~4Bv+L} zY~GF--o!kfOL8MXlo4(YHInY;bS@-(Ygm*1Tp&7vUr=5$vao7U zef_Fr+#SqCv$2%zQg)$P@mM9VHB2?uCoop5j?EP7eF3dcG(G9{okB;?`57b(6 z>Xk~M5}$+;FW59G8d_OqiXG85|dul%X{Qbdd=7zg?g@9n3yMYXj~VcnOeCd--_M} z%9wD=oYJHp+C{*HnF03`)h7yd;cY17=c=@7aas$jvN=jeAvfuj^QA&{0UD_^Z{AGB z5|uYmt?tzuP_A0>^g?AkK%;FojWU~#E_qXFnOs44W*X*fs?=K1*?83`B@7|M z=xQ#gx2C+)D%Isv#d4*p>yTVA-)OirIyp^C8r=bE9LU1L2Id4)m2$COsV+c%8L_28 zK$SQ!BP^CxeO8_*R3TiTzN}uIDJ&Z+6$|D1G8Lg^s!FUEstev5_iFXh<^^xG(sB*T zqrxU{tPYceMxU;>u~;9Q1iNL*E6;ek%jwP3D^n_tb0qqJ7AaMyk#I-S_8cocrr}-5 zm^~122kp!rWby^>%4qtiiVH?C5kWF(uUZDaIjSM!0Vkl=1ZH>^0!_>qCu+RWoe#x1jPVEMOYLxj3_=AMUMmmBFs){btKp` zF*~cb3A6wMeVG9?plTMBF7QbP!8~QS+AxcTBq77Yhat&e5XxZ=>KR7{QKkTV1z$O6 z6fqZk4=@H9JZ>3~>jIEKZP=dKArL7-2B-!0G@2Hwut9y( zkA-G7Fagg44Z=$4327UX+;$3xu9Prki|)d3*vs*hHi+X!eH85%fg(mYECibZG-DiS zk%l0`#7yN8L>DFmy-^S-U_!tRj{@Zf*Q9P(w83?NqlqGP!mAb>3sfk~SS?53I$(rF zVLpJC3Y3h3DN~a`x=Fx%0Q>{A7&ugNc@SEim~ZAmUCePX0yugy@LQ3aTtnmoWDG35ME%U!)BNRbjV>>$N>=Kki6kQv~U#L z9E2kdWlauAeGb+DhkF%=VHJm;2X}Oq#^DppVSLLm1ID26)J{WgJLIfs&De zl9Z7*)z;5IKuX9YNZj8gL}n$xcM`XG(8s|^lPRd7qC2Nb3zQG8!EG6yg=x2diIRZ8X#(>ROsYTofZ>Ol^4$hYl0U61RsFYq)F_MXd{>4DETstSS zQINKEiy@wr6c^bcN+j)cTo)B-o1-qs83Sn;J12Q8LrF33I*`aXL)zm&OGR-?I|J>z zSv(sCH+Ni~O{dApBnOf_lFp?aRR#@bGXr)*C`x3bP>M3OL^|mLO(xt-Y-pHV$5pk1 zE}7QY87GlUrzsa3?&)gVJ3D){Sl8&Jt5<`TPkwES4f ztJUUo)K8(9S3??%tTx~9QJAS0bkeW35;~zTOv~xyQHo4frYKgSfkLG^p;Gqb)O4X* z^hzp+*L0Afm(e~kx|unHsM&kxrJ1LKsyj5KXQ812ChBw9h>tU38W~=GgI69a z))y!jHZD+3Z6Tv;bX;IT@_yWOv0Ts9j}M*I7S>IeMm?dD+VN6l;}QRokFvolHM%FY z@qa~0+3m>ZS?0?NlezJ#H&w_@=BthLyf3h1Cg9Zr8ogGnO;eS1sv@O*FSPSHy1DLx zY@RLzmel$JOKP;x(;7v}^5x6tF=ofj{kCi+1%fnMsg$T#u2a4+R-E!ms#u9vC}UGD zTC69_bu!itYssxqY2Ea{M#iq44P(n4(9+_kHA`)C!;qt%&9)78RQ zQCDw1B7Ch@9na+pb+~Sf*Qaa5BV3y!#FLKh0c+veg2F%ww~ zjV#B8ftL*xNIS&@c<5oYXpE_K0%i>0l?Tl$crvu2Z-Y*a7IIYuPy&@t3cVSPP1ALj z2s`j;(3BJ{c4iB-m@t=XOTgSD{2-)Zn1lg43%BBxQLA-P8bN%PfrO&D5^p*ZAiea!E|`wf-PX$U>x043Y3zjwF9GOcr0`D z7dgb-IG7h4K2%)GA#=blIcAMj{R4jni83f;L~i>5LPHs(U!kYKqxd>Z9&Dn7HJ8?6#;WZpQaMS zBGChs5b~8-xWQ%N_@Hi_k*Je#DY5`|6}5S6a43>VL3-B7P%N5pb*Uk2*Kk1=kifHi zUWj&qSd^O_vfCFZMn#82F6$=KNq1zqI4PZs=UgWzPD&3(#303O{oT=#ls!VWI#`Xq zP=yH^4FitrG-Raa`5{RjQ2S^{ctE#Wk|Mwz*I%sI33q`Fo1me17Y#Y_WFl#c-SJ-w zfnwZV?Hb>OVP_R-bXucs(Upqp|6YE9i7$#QNB zaLf}zn6moF&sQuTt8*LTWTB0!#A$noD0(Wd{f= ziz{53RzHhov-zds=-ASw-e|FJzKU74 zZ0^@HX`>2qu1-fBr`a*PTV;<{D_&lAY?gR|C8L2Q`M{FFz9mC_OGIGFi0`y)_*7_> zF4NTT6WHgKhwVj63OA5w8pQ@IT%&X`m@bs5eS7v?=FRi;-VC9+vb%TQeA&~yVKX1D zh25IHtZJZndjYJe-)MBEI<5B08?Au1R4&vh$rB4KsMXzbu2B+mIETPi+?L6hJ)Ch? zCx^hKAF_pr49xks>9WHZWeleyBS58@QYEV;Ht5)uV97grA;Xa7g>sfKpfMm42ql#Bw2>cjkN;A1p!lr?!PKTK$79G zhtt~xL6hO}$S|GFqTu*o0-HhShS@2ttp#UT23jmj0q_PI4eUi(3X)tJIL)|5(J*d9 zVmAeeU7fP3iUp;LYn-QzCKjkPYNS+=qK?&-=)1s3TEn54#=6_EJhnp;8d%b3VCgD= zp$)>|$jl&a%TQ84;#CzLK`dZvfi4QuzRoEyR8kytbx>M3NbhKG*gVysyBO!_1e~M6 zVF&CBrWzvEK!5c^FqZ-SrRgqVlo+7gOROnV8doM!D#;P~kPCnSN9nDJ^QHn=&kd77Yk4(01cNu+xM3d{7G;y_tR(yM?eo|0N68XB(Do zuzS|$CI`2JBP-*ubm6T!ljUd*a%i-1XfSd35^_+sH~@`YtMqW-8F^Gwu{dCT+y+%W z1soPEoMC&#(Hh_>Xy2kZ=1Al?I(;0%&D@cxFl;YCiPwG_E(#Rru5n~{9MvwznJ1ue zCm^XUK&%!)eWD9APz4%S0)12wggjFa60$+*ni?aDMHZz-7;O{*a=h_?3t|EDXRbe> zPX*Bm;i!HTJ*dhAsxr0E%y;Y(oJEZ18w#K(Iwnz&M{KZ7&~_Cza9AKzixiMoD7FP8 z-GswnbHPA$VaCcCa=Ea8b|CVL0T*!B7Erkm;PZoWEzp?~xFrfW=m`MpMAqiU-?<+P zG*h&AmuXNzZCXeNT@+nryO?xvA%*91gVa)IrVH1_Y)Cs!s-!)Jc8i3!Mhuh}RlWe= zC1GwNaa~BnTtdlB2GPjC?OCF(mS};=uwl380#QOKS)vstabK2zMaq8O=b||h#sW@o z`U6o-#*$Epknn+#HeT7%H2^F)WB_u-4S6L9i)TYyk%q4Vi)YO^ac$UUpnC(BqI5yq z0jEp4TtX)oZ54eHfIowdmdr{=m==m|Aw=elC!!-Te5P1-$j+(4VXk@MT^!IEm~i+Xk*c$Ek%poZ?^G?qD6NWEjr*di|#2}^p&DT z4-_r>PSK)AiWdFEtn>4tMNbtidcJ7Ui$#n6t7y^x7A<$xdRxLWHYEiUmQL1W@TeWDsYSFu^7FDViy{c-_(N&91sao{XdW+hs7X3+m z?~FxvpJCDAn=ImISajhgi>jwvbm^HEy>O;Q8_%-n=`9w0dZR`Aong`T%@%cSv}o-X zi!R$@(PQtk=r?Csbp4D)zuRolrn4=|Y_RB$n=E?WIsfndoW9Yb|2@N^jax0+velwb zZMEqATP^zLR*Sy7)uJD6wdnD!7G1a%>s-3kqARyr^oy+)?c8e74O=a`WvfL`Z?)*R zW*fI}vnX?sMSs4?qHk=oXz4bKwq0b=_b#$%`8JC>)$45*^=-3gdYeTXwpn!IHjB>O zW>I1r)=8^vY_sUxZ5FNGX3?qJEXr@Q=(KGXU0}BHk8KwH{9=nr7h81G#dsaLboZYl zFR|$N7hBY6{=WGVi#A+h(eg_zdfz1$IhR^AeW^ulRGThw8Nsr4vSXpu;?Q@EV}+0i(YlL zMPItgqQ|bb=-I0+I`1lrX0EcRzSE+McUshO#sA%(U;SVHIr0DU&m%i6`rdUGefvs_ zK6#x*ckHm}^VeAP$7?OR?ZXxwy#vd}&nY`Bdc}tzuUHqBT1$8Z+n0%ub8W+G)}GJ1x3wC${mX%Pm@Uxkaa5Zc%N!Mc>*W?Lz1*U!F1P5w%Ps1@+@gyD<7Smz2u_V+29{$XSZK8JA2;6 zyJqjZV|G?Jv$Nm$*6gfW=gWWEHT#=??wWPSXJ=QB&(41JPrGKfUc76z@7J@ls~l`& z)j7LnXREWb$NzeEcFE^<%^o?kYxb&(W@o=~`0VWcf7&(s^*d%~FS&Tv?AzZuJA3V; zv$I!RyleJrYiDOqeBbPB;MQHU$KPkslCN3Re?OKBf4*|RMSpGbezTvWAFyc61Ni;o z2Q2#P1B?4yfkmhM7{71( zu|?4zSoHqyTD11T`E?ib^UWVy^wf7PD*VKv*F0j;O^;Y~?)NN;|InhRerVCTKeA}Q z$Fc6=k6QHFhb+4JA&b8H=k$1JkHW6|N?w%xwp5_1Mg~~&Ud%ab?Necy!Y@th!Y@wwcEi`3*Ub$la_kZVSaAgbquzPXqUS_^)Q+Ep;+tWfH z=xL!ue+#|7w}o!##NTe}ZlOP~Xra1!{h6K?`bAF*UA?k}rdIC0y+b-%D7E0bzr3=A z20B~l-Q6v;KGH(BM)&+Vb1(1zpZ+<2FW+-nq=k-qu!WXC*h19@TPXfu3%L)rQ2xOd zI`^R#TKZ566(4G${)bv9^-v3~eW-;vYoF(0=NMa2tb66+%v3I4nDWXKr2=DG9m^|m zZ>nJLd;Lyc$uDNTb{4Bws#1fCUfwtKsP){<(~DV`wGC+p>P2q4y)%J{Y1asBWg52L zi~6o;vFueh+nc7Vi&}lSS{N^GTI}jC57OSMIhV~1THD^+U6^2DMK zA_**38Uk&L*`a8qvgk2dp_L`f#*-N9P?D6p<Z#-%>&RlTXjew?ZA+U=9^!q{SVw!M>A%K!FdRr8ZM7yo?cMZD~zlTlDSCF3(K8jG%WUOs`rW%wjHyDr)iBwcroFPhxh(1_Q1!+Ni~T0nh1D}&d1A4*M%JDz7whTbqHjj+y~6+`yA|Bs zU;gc~L(Gf)>^a>3Yo;%kT{Y@%?(9f<#W)i*bWVN#Br%=a9GhRun-Y+)Yh}SFC z#oia%=SS8tc!I@dDqZH}Z+vc1V?3Z`L0|46v0jsLsqCO$tk2XJcW$?L>nkB&$p3qv zXKj(uqU%jW>h(pPwoGVgotbJOA1#*i#qz{r53pS&moFo5tQ~nGlt~wLD7;XsFM7m# z)0MGBC%CL*_q)$xcE53Jk5ngWiy7KBwJ)oR^~sn0!37`CY}ZBaqOFbClH-evK3mba z!`lY7wU}{^SL$MBT&2m2*(F{9?LnQ+i#qr?^qJ;BTZ{Z4Yi}IOV($hW&gf~e;cBH` zS?o#EEj0$t-c(n&gGGK%&&ybswWGdC3@^I)0^?)RcfjG|rb0<-3c{kl;$^MgtDh^2 z-M0U!xyaA8x7!BEgp^cF7seO+m8|iVi#<)|3e?5!T$?E)=bjn(;OC#)HQV(;{9O8m z+1XD$xoh^D&+VGM>bYIB2Ye7er@diz_JSvO&0hc9u31sckUI5de59wj;J$Ms!SBeaxlRWb+*EEh;t2wzk0JB$2h-M zdu67ctBmKg@Sb|3qdHTr7pDsIt8_L9VdgFTYayaM5k2=RqWzC1y8gUZ(23DE)7e*D zL-gzadNnZC$LZy{n_Ev#YCXMOSxMPgn1XwiRqe`-+Ygoh!OltXR>#qGv^KcUw2>Ztw2s z?(FXBUeVp%-P7IM)7Ha!+Iu>BI(xc$R`hiD^z`)hw)L{!_TG-(&fc!x6}{cPJ-xl; z``2QYd9zewq5i4yQ2*4JsDEl))IU8o>Yo}P^{+8TPru%MrQX1X!GrY%ZhG`Ny@4u! zyQMa8`u=}eqc-r(8_&8}eaY7BHDV&CVT7^MEP4jclWQ}Nc7x=`yKhMt?Hv{ zdumPfMXx2I*AvkjiRb_#I*^Fe_q>aU4kMx^L=+~Xr9^Zr5p@xf+Od^H6eFSmB1#gG zLqvjzMu^BGq5=_35Yaj!nj)h0MD#u)dOs0eNJJMA(UnAWH4%M;h(1n4w-C{%i0E@f zbQckQMI8+hJwQa?BBCD=(JTHx+~3Vj_W9Di?DuWHeg9&U{eOgrxTtsJa*TE6jEH`2 ztTI!s+jD>Do%_Sag14^m*SUYM*!?t{dzn4)qI+6zy32a$+|+(eSMa^@z<}HI6Yu@a z^|!}<_{b^Mx9sJMd~cn5+x<w`_I1T7$UO%c!cj8zIpv2M6~wV zzc>Ac+b7zae#3XZc+-;K{IESa=)Phf$MyZ9y2t$FvDf*&S^TVxh>E+`H2vlic6_4g zH{W>hLruSV&+mOrDWJ}M=f}Qp-t;wfC%a@OOP)Et={JAu_K!FH=KWr{ zFmcDvhSr^Z*Q@t24rhN<-2+m+ANK9hM>eQ?LEw_@zCG$_?NGPbza7@h35q$oU5E1?F!%z8+VEPgD?D)cwZ}1(#d!JR$nxiM*()0)(|G@c8 zkKn`&15J-$&;73+p~mx%N4(c}1Z~Hv`&jpJ@ADnOsb5m#{K+x)I#EBiQr^ezgBjnjXQ$=bg~>2-5i*?~OeEw&DBt_F$U(cm11G-f?jIi@qbf z`PhTh_OD;zJF?GxL8VIfUUa+f$ZmY2dai%?hGo7ZyWt8I$8Ub}7T=Mr-TyU2blwks z*!0NW{ex{ykL<3CQ%#R-&*S>TGfbUzk+=Dd?8B?nH#pzl<~y<<-}ojX`o?$f@g3O* z4ps45xnrmA$S!%Oy5F97=mWkZqdV1oZ|OZBY9&WU#;%X=iYvt?})pe zRo`;*k52F%@s=ah_`ENFjPHndm3oNizr>EFM|}UG=Qlm#D-Zlh(<5&3yj!pGlVz{_ zitmUoJ3)Q$oY57&BmU2}PIdll==UA*ct)KktKM~v?})9zR`p!IV6E?ni}$PXe9K*D z`Hr}wuw2FQxxf03ICPhKzASt1H<}*tTORsQ(<8q7sn`GFo$c1=t`6)g?!kN2$96r{ z>Klm@A6EN$Q^(o9k+}4_!-**R(tr3y;`?{1``AZblD?7n@;g_k>-VR}`$nSWZngg8 zs}Jyv#P4rX_r2S1KHoPIx16NzV~H=eHXVtF|9L>ukvN3zYB~~ojzi#&DslYk2ma|B ziB+rA2cLWWjlPliREv6!9Cc#EHxk=_r0$0|fAGV;kvJl$w*UCq5BNsnl8aS+bMu)K zzLD7QarIogZPzD!Bk}bim5=qUw0$FS*;`e0c-K3=-*hDQ`}jMWj>PX)t$6Vr-`w!q z|Gj8m=gIO>mCxL}_A9;-dibO2xjDGvH@*?->{Idm-QbbF5wgFb^6Fo8-Q*jgfBZw; zPcB&f6W<8^_ATwIK6~gU-w3UHNZoI*`OdAr5qf_@-A|6{>Gh3}I9RR!lRN&S=?HbS zysGI4J;`5aIzoGnPwQt?e)8;(?(vP#>%Q;?BD&5V@Qu*#|EQjWmp|}=Z-jpQQI-E+ z`rcpqMyR7jt^e%o`Mwc4?;v&mIcLKqz7aa~L3I#Y4!PPlLaVM;_r2d)NBTzSv;Xr} zBC@~oW8Vn<<0N%neU-I09U*z#6HQ0xw&&ezpG&mAt#9O&`#7(*Emzm|4HrJ+8@W$^ zTYbfgk&pOB?t)h!Z(XN2H zUXHlrQs0OUJ*nPbanIep5&h0DEcIMCNBBncwm+!z=jPYG%QvD2YDj$iH@(Mt|g z*ZX~M9`udq4PQ`kdFx+4?Hkdxx2XHf@fWOVI-+s+siq^k<@#++M|98e%%85F>sxE%^x~OkNAAPf`zXE?b+&7~4IVw*MzrV{jqN~nU_tgVF zAMuUoCtux5M2FRH@{MSEi;Ck9*Syy^q8Hw%p5r(C^2@#vz5RYQ8c$wwpl?Js-EydU z{+_k6>4<*y*RiG}`rTz`HXYH?Tb}-8>i$n?j@j|Uz1jBlhzPE_}?bKiQHZ=~7B)Oow^w;|t1U-;jzBBEDC_Vp+$wz!6ooiF~fm7aoy>Fy99HsX2?ms=@8|jBFbv|F*{|VnnA9tQQe-6L# zD@{lGFK_rx(~&;;POs@m?>Wx@`I>$rdgc1p`9}H=Og%UMlKio6q>p1N-}u2HZ}pAz z^m=u_ed367d?WqNf2i}Y?a!zAMmqg=Rlj`Z{jcC^Zj3i zd?UT}AF56~@V=A%BmFn^9J%MIyL=;k*e&Whz4wM~zLEa&f2ch3nlA;Kj`SIoKQ|re zuHf3HBYnjSKYw~SamZWl-RF7!_{Hje^2JMD;fsLtn93(lPyX2#fup)rUi8H$9`;4R z*{I@m-K9VCN8m_x|GfCi$ND1h`)k$uf4J#RUj+U)t;YY@dynx&;DU@g4?jNeJzoSa zIzXMzFa78(z6iA4rH<}`2fpBoK6d=Yr*X!ZWvZ@JnRfgeAuuG24k{`961 z$bPo7X$1IRwl|Hyp5xyhSDzYT_xd7mQz(2%PjvRS&*@ z=p()ebbUhIH$L>WZN3Q9ma4kxofrJx7lDn-)${R#Pb~LEU{grN{RsXsUj%+XtMa|K zecjsF>U_TTb?5scu<`XBL{zyU$*61y*mHL&spt@%)m#~edcqw4*MeW*eBF@PXB2? zUu2dJsQ15f^k!jtbuJXG&hv$XvPo?@c4qqz|%j2@xILS@1<>=Z&h~dEwa4`Xckx5h`AX zF0J??b4f|XG+nqu1~n>9$#c`{2w)LCmr!KUu2GatIEeN+#dEt=9j-$*ZZ?irhSpw?>?2# zAMlAOUu1S%r|PWksh*~hIpV;ln?~m5FMg2K8fhkoXNd=a~HMmC?j-fRsD&=@ zMeHr#SNpT=&S!iP`}p(fx~?9zzb|5s9;fGX`d9cOcJRB^`SyaVlOHK6Z#NV&6DV z)nz~AC-@@v@VC{@ItRYl7qNSms_lGs`CYz<-SA`^5xwujyL=HlEuroY-%hssBKDas z_1xL;=UaUdyX9l*{^pKXeG&WIbt>+66)*Bd>}v^??>&6ydSAruzE7P$PwzU?7qMF( z)8l#k+kFxHQbZkB+pA7!8nHj#+1)f^%in+B*AMwxspYEPeO-6K|55LK^7#FIk^Jz} z>Un+J7jE}OGJA(QpPyLylrNI+IzZKlN1b(nFOp|GtLOhe`G_x)zqnF;`%TAkUnJlD zSv5XCt$xNA$@4y-&WF*ivwV^K_0{UW*Dk;1i{yq8b$@;_KjVw!kiPGo-64FDjDA#& z^D!g;;fv%zwMRYQKl*)NBwy%J-}|=lr+ksze7ib-R<7RP7s=Lj>iK*4r;cqJ$=|*B zV$(<#!^@gRa?d#a_+))u58v*KWVxvJ|84($t1pt7g1RnFY5$ook|#c;^6*IOk-kV? z{4SNJ-7~Pm7s)pq9#-q$aicGi_x)ML%X{Q;UnFn%j=C;BbBX7RHg2YuG7Dc zsNjxZNcRXCr*N&11 z(G$^GtcZw+7TxMrZ$b307DS8QSBn;H^-i#AlwfsM5}mMmXQQ)Pl+|~=e(zuBem-~Z z%(>5*nRCy~o#${`d~wC4FCfQP)`O@JY~@XEqro2osc?%9Xz7lPZ}+qN^M_v21t0vX z?^VgGKKU~9Bo^_Q^}J|7(-8-{FF2Pm6?AfCaobC~I(b)7gF@jpWbW%+EU)RmnC=gv zS~-dEp&b97D{{r&aiHx5YW=&u5&QW7l1956s1?Qcn>N@y50qD6wio+0$XH4_c?Ef2 z=~*FK^7aeX(&7uzO39%iqsUAkmGr)%uuE`@@QTpy3~7l8q2EtOweCi17Q8&zTTs$9 zdo&r$>I#X@w`F`MC~3WTc~qH{#YXsDMc={w_6K4h_|n(Q0=t}%aH5Dq^iSg~{tZ73 zOtNsVZ$sYg2dD)l1>Z3UyA;;G#wg;xTNo)R^cP&@@}10^dlmSdNg;38?>dR5&lmH> zhH0<1rAzv*K(3GyzLR2PdD}YYQJ}>J5+TEU^cA_Z5gT{{_F6SF+xw>oxui_9L!4@a zBL?`|W#hZqwwJeJZ=1a<_700~-d(b@4woP08DnoslTatKYS~J-$f*7tC7eWa?ln3E zA%X2Cu(!Cl>XNz=XTSbq*nk2f02%2(q7frM<0Y+`TWmS7V4gUZiLp z@=-dIsysB@9j3T%;)FyW6@-&G`j5o&?SU>qI?fXfaVmQ5|1JCy;E=QxSGb<%(cFi{>I1KL0rnyDK< zuDxjo4ybzvuXFH0m>fW{G@;KD@|z1#VkaGMHyA}OGi2+WjiNuslNsuvMyEWH48Z4B z{9d7D?t3l_wZeYsyTbC40ebxlN#aij%{pM0ahcs}Ls9V=ekxSk3Rs$B?Z1W(U>zGL z_Dy3C!7(jrUbm&!vH)8ZpP^ZdDh;6ITQ>T)E3qMf)A{w4ch4^qnXiVAgMz1aG-XtG zAEM=fd3_JKZ`SQ^Zwx-*bC(nf;SLYB@wufgC|%LdTV=kUzd*|)?ih(+qNb&geN)th z%uurzubP$iA@2iS^N0!W z?8FK@-FKuw)Cz8MNKLh;o45n!lvuUN$+^3}-XtESQA>eC?tQe#FT{58c~CrF_+u7z zZanzxaXtCWe{p7Ck$7RGHsuAZ--5^2_Lc$U!`%d@qoB=^4XJK-jnkMg<3_GEfSQ6l}RI*7yU!0m)R>>Iaub zfSn@N&Fil-OaS|Ux5rE;FNh!eOY0Q0yRHdSrq)GWuNW##%V^&b3-w!E^Ad&`oUz@# zoXW(L^*NtBdI29K2s6FblSrlXE`jjh^y5YkxgT!K{ zAVXDxu;(Do;F$p4hhasfo>p;Ki8Ttsc%HJWgB72D^cG3j(@6X4~1AMR~HX|l#K@rF^CxF_!^pN2$ z{|5s@w<;{3qic!k54WMUl|@~6MmSkh5dAsrK-=f&YoR^nI+>a8koOtW;%5)*-HB3A z`+3tLuPYK$i^J;8WM)kKvXxVWXG5z9TH#&Ad~ts{_YT`LI&7Bn^}E&5MGeITdFiZ6 z3gSbnnqvpMr9ok#RhAqMf##CpWH$7hleY;s=Hxb6%46pgjz$zVyeROMKdAA+0LfGd z=iq5Y65^B@VqzWSqOf_m!s_Hl8wdAfn2$wKL0UYM5vo^_7RwfB1x9X4i< z2i7^&7H$5kK9jEgH)(vgS@)3Fff+va_aSBTuXxFQtSdg{Y-Lzr+8Y!69z{r5+v#cp z7o{O6QyRIyM$*#=QM;Kw2_&QRfq>#qYhf<|qpysT1MA-tMduW1dNtUkN>kc3=A(ZP z_lU?W)qL-{YT723S#ox*JmOt2#COZedf(5L2!FJu>#cXF>J1`VQxC5=gqf@3udTQi zw{>0169L|EMqg%i*aInPo5Qzy{WMqshxL-vdh1JsfExFQ@eLaZj54Mxv_tEy#TlWZ zS{_5Q*UR#uEk7Jm^%@qr{9;U2-SRV95=)$YW1enT_r+Xq7&U~2w!~OR-~BB*mN7-m zr|$itsCnQf9=x+y?>~+2W~94uH?Tws(7X`9aCPm|gtRb9?0UrS6v&uv3T9{g*V!(! zB&Ud`kTMN;;O4|I-3TKpkue=kS*Ewv)w2q1iA4?yDkl!&yD^TA1&$O*5J%@sWr!wX z{KFrQ#0>{*&rEa#YUL6GUA)U~l{OyX#oSeu7bKxTkHN36WLh2XZpERZr=&s1 zz6>fED|6<}Ht}^X=$s(5qs^^C9GaOd(_!05hEL5!)>Ls|8ju23TOp<~T3CkqFgaUg-REj$z_>55n$Mn(u5fI0s zx{iAFg9CcW5rYWMjei6ceV^X69jC_+ZE1|`n?KNzhSHs+&hV`^Bs_>IO*)eb5FsLn z!Q-uXGlj_~1SXV!bK6V*mz2?CbgJ|(IkPIQU#&1uC{cFtIM7UNG>Uxk7Vk?16O@e!{}^+X`rH0(2i6gM*^ttSVGfz(zq9Z z|6BU?&k!s}Xb;trAIbOh^^l(ZG`9AzCRH3uKXO+xB3os6h*eZGX>LEDr*K$TR zjUXxbPnQhVdn>MGWG^q49EdCVVRvUkE!jKOO6k}yvm1R5Cu_B zC>gwR`z(jINC9WvQr7{k9z!xaZ5*k3u?TrujZEggqlpxrt?3yZl@op zo|pBjYY(Cx=(JRCouR*^9awIRa~D#?2}313UyjVax-pcgseE!U8yE3Q<}h560r{^n zCuAw(=}TqtM4Qm1Mcx>bt3BqBrP;ig3S7d8%pqLyz1;|F%_`@Gn-vXTYr*SI-$9z~ zcUzC#a#|!Q2M#usSD=R3L>st$RUGKdffvenmMT%R=0LcCGnGH}J+ce{7$)pRY3;)w zxQj3q`|VcD(+(V*g*7!rXmLXsH-^nz^-KvjYDl;8pH2iwLvQliYZ|v%y#OLt;z5Vw zp9G_01W z`*Ak?$o(j5;;3mwoPHoaQ*OONocq~;SxZ*mwo?KK>NppEU6Rx}gWno!IEnN2FDKi0 zGggMAeVt6;F5z4Lw$H!+oWMO`xdc*i7){UDO8zOLW1}tqc0jF0t*kbK%z*Lr?2Q)1 zMY{sx)y3Qs1+I+ATk?twf+F7MlPK3QsmBTpPvDwvi)#-QOv=V3hqgBe#uX1<&R*~& z5{wIfujtY^-oaByd|T+X zD47>yulr`+oQCeeB+;yGtOpMj0_?_Hc;VNC3OB7fQpwErNHw@SPTRaF&wzB5Gkg1r zW^`i}-EAv#mc-rTu?qbqbB1sgk`8}b9Ae+e*<+`)Xes0Q=XE6?%5fuPr$n#3_S8@N zfkN=vH_Woy^rXz$x4n(1yu@&M(s(F4Te7#L{<}XmTD?}HhTE;hQ#krN+QrkyOH>qJ zplfk#S@M&^3QYF z9}sk5v(~C>jStQD4M!h^p-N<~8RQr8!>iXr&wjtEEaSte<4<&ZCxLFJU5F-%nqiX5)rZXVE~7_6&roLN6!Q+QPhebU->_dL<{80>tV-)*H{SG6 z7XCc<=5cpoC`2}Lrto`}>w{gLjEci0lVt)h=npg3_})1_SR_kr{jJ9oIRN|9^CbB$ zI->&?@CvcPx$GB1%eT9hYoYNCa# z0PKPp1JVoi{K2kT6g2qJIh=69%Rfi3Pcv_Y47M#*>gRK{Lk#N@gdJslSR;a=cuFCE z$EQYRt{Z~i&$a~`QNR*SWfwtxYl2Y3Nce4Tr6W14|K(Fxr1M(nnaY7ZOM$o(!366w zoq|c1;0I8I`?G`D6AWX>8O?l;U2ljsAZS?Q#3s&98tRg)8Z^r3YzDy2=>_$D7|o-X zX=^3N5NigNohH}pOQ&a?`KS>1s-P~HyOBrpyUBRTcbivw>kg9l3{PJOm$pZX2Q~CV z3Cqt?*+HO%$HcyeeNueG3dGcZx8$*L!xKEv5LDD|0BPlKHoW1M^#TL0NjAK$fU)cG z&!?tfnQF;uM|`5d2tp=NrM;H+t`h*BMZb=Dn-_5u;h!9(^NWwrmxpkw%ACIZWaP%1DV7(6jj{_EyvTv{j z4G9(*FtqSC4=0>bFN7$$>PZ2A+COuv7ev1U0<J&ua@V#aG}fj}L5~ z?AUS6c|`nJ3rK;CejP^Wc_1fg`r}C?;caE%v4y@n1GRPz*srVpoDcXPWie)biPatY zKttp3st&^8_w=)fKgbpT6`91p7k|5p>bU&rI$KlN?kv1kYiT!i{M=o^eXbg7yx(Sh z!F_`+aH-iB=3i`JZv6zT5U&uMXF){}?$5bA!1bSx*1C{sZ^25RX-_^~Ka>FX*%H@) zJe`RKcd}LUnLJ^n$!?=Lr^rD)C~2?Zl3y;72!MXvrDt#wj)cYqfb0Y0ti0Ih9f*7G zLeTeZ4Hu}!)%}5oLgOrY&#=Mu_yGEp@7za_Z7x}Xt*+wRzI=%XgXJw?Y^&ZZ4K%LG z5Kg|_+3_HG+>gO8z;c2L+$Zjk-B0kT1R58ryM(pRYJGtZ3`Xk}UkjU$KTjU#NWK1PoFmaO_<{Q( zU4*_+>XTmzTmBQ)gVDIU0b5mQ9DVkgEs?&RtiYr5Z;-9kvhPsRc>BXE=pBoUK!R5h zW`Vat5gO-fbYg=(T!F^@2BMp9%)9Uh$1>FxaZ5qs!1eieL$T>t8L$%fJ(urhFdO}a z%h<&p%q7A`@@0`U+I!{cJ^aGV^wwn>8FB)nRV7!>4V@t1`kCut+FJp7Xx!m>&$iVr z3L58_b%v$anFP=m`y`9xM>qO+0{*p88i+rbc#Z->>)JHJSv*! z!1;!ap0{OtRLU&v$zXK8LcW-;mOAohZ2u!5oCcHqrvuW$vAr>}~*9DLa>BI`1D%$Ka1>v%#FW#fBM*x{-{@z>l{U zUNAi%_V8yN6*Tkxp%i&yI%`OeZ&VUU1D{pK3f46S;XZ5#?EzO#maa4mM)cV1ua2%8 znuhf(-KdF8y!ss01I!xpA6vlD1C?~M`-00;UI4cYAKY)Q(qut1qllNhxZM|^bOhWB zDE$e)`+%-@ipz&WEwaZ`TsOVhWT-fk+l{MRhUE` zV-}?7rtFPj)BSr<0+@C{t+;L{4gk24{7=>oa z>N!Yelt_N*8BnA$G?R*F<3B&?nLfx)htkDsycZEM8;RRRQ?TnsivL7P=o&rwAtDAgXerKqV~Yw6dU&-aU2K%zIjIKC+0Ojb#{r zgUaEf7$ff(35uFKV(O>dvVL*C;-u7q$1mLwKSpf9>YvCpYyzVWpqa?=p1YPe>umQx zYJ(aag4uye*YErwcL{FL%=-DWE0pkkbbCj~VCNI-0?kx2oDtxYVLzW_0}>Nk5A5Gf${Dia1&YxZ0wdCGiTd~JN6849Bhs6e^}t`nwf!xBAAx&MgtYF>Y!qf}*Q+_CHKBK&L&dixWCEG*}Q@6h6 z4^A#1#860ydqo1hpiZ*63chm5>gRf0=r=l#R7iBcA&)$hqJUTJlcFHuf`=;CSFu~O zm)?}X-3SgWwz+N_pyII>-8>xy`uBqSTvgmPnVo`sOC#Ag!P`!E`Kr>4SVfiRoByj- zdvX>3m-2h_XFO_bDxo!J7xGAK1kmfv(GZ=<=cT8~aLA+M2IF>K;BE^|eA!H)a3+jZ z=m<2kC!0LApxdeUL5d(bb-I?(x@tQ}8LVq3alK5hIS2(R+Eq3bM^(rtE0L8z+}mBr zfrB+@o^>Ye{RP^sS< z^?~a&g#s%q-dV;~aPvk0>D`fv7M{VRKo!1}Yxv1QGn>lcXpjD@VdY??t>7(2C<8CZ7y0JBI_ ztiP&9IJ{+^3H7qvsv`3EFMRItR&U_EX;W%M16@-_o{hunM4CFEeIh-mJ&)y!)tCIL zR@n+adX!?Y)EU4NPII-}bnOhGG|%+2B+}%#BuVZp9wRnxwh|s&u1!vw*NyV%cx6XS1 zRlsj)0lyecYE5cs>S0c5pa9TZ6|Baf(x&oA^)TsA+U@HKE@AagSyRLn)Z8??coV-S z1}9u$7@NMqo}p(0F9*p}mVp6U28|KQv1YtO#&m-t8EPqxY#?Ju!L9NYf`p%>md3w% zY3W2mEkKdq&F$`sc_Ys?vbor_`3{6L{zq+87o6seh0vW~LGK@_TwDhKJ1BfuLiIut zh49%iIK&CvX4q@9&t@Hoz(UR=M)5X`$0!XU`>adR?o2yJt8|OG zH-o2)g|2^$>HoRRz}pY*Xqyqe)fYyWqjU@Ych|pEtc1t8KVCIE&kh3@8Ry+AF?Va`5gV>uL(PVp-XAFzj`#J|t`J()e&=WfWmNatss2ao z2(l=H3Ta*u9F>L?a$>lNk=F4LwgQ!a8vl z^m!Q`1(_t+sM7I4ND4?hGpcW#-m$Q+ldtm1qI>7V?Q*A#*_m?7c!e)xV=<@G^Z3!_ zEU~_KRub+X{C_Swr>#K@9Bk*N(RKBgHC!`FY92`bo?y)+rJR71z)?A5ht8+Vy1O); zQ+;irCMR57sm`LQRh``Bquo9o#>>NoD8#?S$4b>JAg8>q1GOS?*=sb3YEV9xDSx6} z{r@x_rouAFD5$Jo)V*sPT`pCYsQcyiHE#EvlLKEJ(#YO)irUN^WMNYAb93`dASBJD}W{tivm{pnv zzDeI`0C_R|woB;KQ;eEd511rAcHusMd)*6Ud6u8~&F^)hEvx0Lw=*1v1+Gf0#)h}9 z@h5oxoOX;vaoqU~? zMJ<>Gb==8x+0%rWnfXW^7Et+RQ^ih=M{!4mcx~CEgn3~>P*!pkg(W-k{|L?(j%P_ zi$b(hSOvkxSt(O4t0<5=0r^>+6~6_qAAN6Dt~iZ@7;95_N#Ajuw{}vYDrSCgkYV56 zIq~;_OyaPpQ3HLY0dD6P(kA9vZ!F1jV@K0rr?QH8&Fl>{6Pu^WrS}weym!AR!ZlW& zXY&?Z_n*tTF1ut`!$89*;>{w5CgX+du4hJFk3a5(>G;>%GdpBfV;XbPfBJvPsqQ?M zKm6M%BV@vR!75B^LR$`d*gKO`Kz+pZ^ybU^{phX1JiR$!*0W>r-VZxJ^^3jkVKU|W zhh(?DZ5W^%EpqRDe&~_g%MvuhlCqYiSUWnCwWRy(qgyscU^nuZHm_HH8vBj}oiOm) z;M^SE?q>eQ&JA6zd-FnzWW-7~Xc|y>JuMU~pHWRtHEOp08vR__lsj4P*XvK};trht zQC8irH4nOA4<)JNa})=^yQTk&W^;LNSoKnx_Z_FEWy(r$0TU;}g^YR5$Nl^PLfRSi zCpKLY%VJHko=#2dU!z;>hW?`w7qO9+1>y2Pfcv> z-A9)o!UmI?#sEn7W$dU+QtmI}P*=r|K8dBSfqEcrp>{zz=aTHxY036}W#r21_aZqT zMH-A%b$vT$MBAlYr51rjGQalUd@?a)_qQ*x^zKxW6plhf=Pb9=^BG%XOXkULjjj|s z3Q!^quCo=^3nzaL3zEs30#D7|+&`q4TaN9!O$VK7-mk##YoGf<$>fC$C%KRuUUuVTc#pW~URCHaVTm2q#h$2wA|H7R=^D?~}u8U)aWfTAiAear`iw{=I^9A#(8Gx7vbY zdq`5UN;oa^x+tD1Nxj9jNR@;Fx7d$i5p``^g_nLgJ~-uKtuNf;7t-hD4tZ}B2EQaa zy9m!dxu>)0pm-7={FJkxi((!qxe=dw#&YDX>)AOkGdKe<^7+v0o?2yp>@9vytT5Pb z>mk{LR@?lN%K>^_(mUJmN?BeUMK|Qp!Ku?E&6`+@`fP0coEwr*b>)i>l8QT??54XH zY*Jpo@~j-Nv1jnhdQXl6+6lp3yJkIj9vE4;SD4d!(-M-O8(c!vviCM5fAS;$i!I4B zNppIqo-3lAqy=~_f^D|w?4{q!G!gQ)w^C&U-}~Ne8E5A65OJBjV-|T{r0lG(@9hCX zsUuNRPg1@l^1PckeYp+cqq=*%Gk-Y72c80vodveeO%NvBxShTHa#Sq~iDro+oz$=j zaw>Ad2E^afk6J-Rc{{J#{u9?KczS(sR(;j6H>9tFm@@pQ*GmV|k2}5>y0-6aPohO- zD-on|WKg>}Hho&bzCpLyWqf@R&pi?cvyk^eE5|!5Zn5t-KSeCvCq=1*WZfVAbCape zUovT~prFtfN4#2YMLaGa^7GcPXtESgC>M9EwBw+&qpDQO>XmZZ(8zohP>X%{Nuzi{ zefq@ERWf3$Ii`|^LY3&rO<7W<|MVV$-JDvR^Qn`!?%Ab0fqt5!b5w|(Xr=gQ+-|~l zT686M#v@M}le;%w&3Uot#UAu7sfkwJApL(*yVHTTn$8-$SQSfMV1Jv`6kFf~(k_UD-^aOH?D0QC`9<87H)O2zgTbwbf#1eIF~quLd_U@P*Cwt& zv+rJz?!v3=8g@Nkr$7I!MzwB3@bfUB6c%UWS34PQKV?X3QNs zt9-AoLr=ThtgmJ`Vv2S3k9`=uVXK!wP~&~)9HzS$Y>n^Y+DS9n8trhYqa_$=U6Xc0 ziEK27?&9HUY1#%qY{qf)ayZojcAlCp>=XE)f_aSh6Rlg=RC56eLHmnZCHv6nd)1 zw0UF3j$FqOD~JV91sLw%MoflvKbh!1{mYaM_b}5ZVckyA%24rKyUJC3;dY_+Pj8eC zw0Up#Q94~0U;{7|!OE?L+q@rs=jB$?y^-?md?jnf0_pQbfWp`LAf&vqo6geGOOG|ATw>hg^fSHbd2v!B{ikp4#YAnz?dJ1pWhkyt z=_amadleshlgLoTC7pz0R{jWjaRHf+-$echNS$i?Hdo7{p>NL1o!*OP?r(PJpIMSo*_zy6oq zVE4OXH@!O!g}VU|!L{%Oa^&oLqGyGUb6-gePTu>D_T zM;ODfQ-)gy%Qz5k+;Le1zxr@$`Swy9%VcuLk5ht5zRdJs*Y=DF(f^G7k6se9by*s- zw2!)RYQE)F6XIdjW8vquqh1n>wo@M-`LEL#UHq1}GtMd_$(5fM&DI*Z6p+Wp8}(_+ z)(vSC4&V4dZZ4PmpRuWC%{2dZ{xElTI>*=5l~hOd*wF-{^bL|rRD1x=uRQNO!fjIiKx#~bO z!dHGhQ~3Z3&`Ef!sCtS>C^_hV=BMc=^!{u6p`4H+kCp10!wSD*;o>7#m=|m5PE-Jr z{hCP+C~{XVJt9#$u&MOsLQ-0NJi<*$I#oh_ykxB?;zb<4`uK=!Fev*UY{!a7Ke$FK z{Mq~`@(~BoH?OjbQt(D?@mCadZCt19JgvkuBby45fblE>rGg`{HktDYlAzxYUL4k)Yg)$4D~8ful{B}wPyZRj{B^$N8^3NmChCZ7!Qzs@jORW*~8=K$XSt-AW0a%Dz0G za8DY^WHK(4Rohe`g~u$-e{DcPyZsXXue+c0^hcyJi6&`Es=AaTxy)|zFS376OMqv? ztW_2n+}W~gM73r=gl;QNaN6Zm&idxcikdw^kfzvgb%>cgY?^kE!xV9wZEllok<3=~ zd78O!<+1&41(=<7zuJy9Ph5c3=oLh2g!uQA48wze5$|(xn}L?L2){B1lVb+v-ni{j zATfV}^x6;U!!H`fKpC>Z7{A&?8dJN`0`a~}y?(mVQ4_0Y7hmRhNSDB3SwLPbbe5*MI2q={L|~3~lL~cD-ZzA*xc%T@7RUcu?u+>SxPu&$Q56 zt(h*{Xa?BmWk;C~!FEwazzjP(qHcw_%%!k0Ah8saq>a|3eMpj*;h?!}UBa061+Alp z&dgJ)`-fqPui*K9K_wN>4PHhrP_--Uy_ZLu9vqVIbf>i8`CGffw^Z`(&TS*sX8GGl zE9_ z7*vh-Uh)tElt}5-_K$C8PWWCGWuz*rSHOlC52f@oCm5r=65S^saAV*tCm~x;^xB;6 z!eghl|5MfbEl^Va##&Wl)boTbpT9(f-lFA#(Nb07uvSWOPfvY!U^Js&FF1_5+QgVs ze$i zwh6J`Ice@jvEc*bA!Wu&h(fRMn6= z!D4A5-!qej5P1>g#nhsFD`{Bbk~-rSlz;vGq;+g1<4C%;Co8J?bjfbk6PE$%ydSg~ z{J1lL$XyJ#aKaDEI7@#GmPef>em!R^3*Ki>jw5%SvjQ(fF!7lyQ`J~<9aheC^9y8U z4@GHnqs^VdHH-RDU(V=KKm>m$>SB0i+}FyV^-+1}dcGs+u5CLB>A+p)3hBl0k|mA0 z>s*PJUPZo@f5xWcSkY}jbG|B zxx?$)x}FPN@%CU?nT*`6_FjQ&rSnJb23fw)n-1sd+zP@NqJw~KY^%ex*>iJMQQn!75;TC>kS zA)a8Qau+o}yZ#z^hUnt&q}fPNb9F0_s`+5Y-I;QLq=`05EIeubjJC#_tzEdj7*#j( z`yIM1T0NPnGiY{ojn+0Q&XBwaeV0eHttDZ7>tMGZ43_AIQxq(I!mI9jd*CtU?yZgO zh5NXH20QskCZ+3qb+k?%lrDRuZvqzh)Ni;@c>xYA{0E22x@{>JZx0j`_)hIv-yVGB zNh~P#`vvb}w#LLrhC5`m1B^5w-SA;nPn`az zL^4cpDabDKoM7`tz=8RT!_hNDSv;H8!tf*)k;nEV+W`kxW7o_WS8S=-8`JZ&zqhgA zh2TrmY8M3)(SxWgxr|bT@ymm!uAD*7#rY;v&xxaW|9tV7$~^yh+hxSgLJ14{hD$Ii zx}X<^Nr9UqXqW7UN;HS43Y{xyMwRv5rXP`v-S2s)lpnOO#0dPe^yqpTEApv&`AyDmty9 z9?;W4K56W6VH;h#Jdcs#bOx0MZSKF+Si_q{c&Y60o(Ptj-LJU_RUT!Y*Ku8sd@G?V z4GQV5`0s?R)T}bNS^)dzzLmVWPua@q0b5o6tPHH`?KWq*C8bMOw&QTF+zPF4_m-LE z%x~4q{{?ThXmKFkwgb0Y>np{-)>`l&uW9Y8zF<2T{ zbUE|?QEt||e*P}to7jO!B@+2e95t1Cu6bk4`nWcOadPGQH=3S(_95{E!n?Z%RW$4T z4u+LqrX?N_&N$zDnqX&nC*v?%Klh0Tp*fpjwuiB;B-L8bx(K??JHl;#MaQ86FB*l- zX@9vA^<5tPr0Zg)lb0|(JeE&z|LX0#)N3n+5wwpYgP3iWLkgK|T01xMo1?woM!!Cg zSr7MqD~i=C*m`*I_9jNyhgo3ZSCOb45r)e?s*q^%91g=s%&j`fd=T|}aPaSTU`PUv zP?7*+4yCehGyMwsSP%ZK`cBv~pYYDDUSXK&dw3Tt-Ti845BL^-{p&P)arOKF>RR`Y zZ{*2>W!4uTN3_-$xl*>H&_IDb(M20s?55xTkM6?@js%Mz@)diL&S9ALXlD2|nai|q zhvppl)Ah(|hoL+uGti=~UF3pd#GCGBch9A8PH290cCf4A3(`Vlf$gsx7(Q?;6Uuzv zmZnZA6*2u^RIM;Z+*gWi-ZD`cUOMMS5HT54z;gs)gDn52*l2nc{VQ-bp413p7Jt6NXSQ%{0c{nnn+W%Vz*E@8U$=111{@gmBmwhn<~3dA%8C4_TM#mHDfkD1zxlZO z_~ZKb3n83+{4g^{Wb(3D*!vMYM>b#C@eAwWYel9a;e0Jjo&tudx^5G>IsdC48^ive@>M6Is`UYphWzCP)051+EVHe)ZHLcwC^D z6=C!`zY)7i=SDGb{ew1`8|+{PbcWeZ5M`QYl`oBT3bw*Q6Ms**fq z8oaa53Q(k1xwtZ1j`f$s!N~y>N)Sz)+Wa{)&1iF zC$%QVDb3>o0cPo*rPs0P;}9viYQaQXX$7JIw^_4r+o8G0ZL+;5I>Sy{RTdogEKIK_ ze}8cHT=yfh9A4_A)?e~`sWTuz?fRzEVbrz3R-B8%lXBFy*fw$*5vXRf4E&*fa@gWp z6r>n#D}Cr|PP#`sD!>z#f%xt9)JSRF)Tw;VgONHweX7<(hXdE4%~eaS*6EbLcP7V| zD@FM$z*MowUd%5OB@lOP63Gu4ejAxS&uZ{j1E)Mpw_Vk)a+;7XM!Dge)uK4O51L!a zJPAuTg8y@V7eryamE}ikbaHR6yWXJtuL<7CfPu@Kp*Vi{AJ`x2ZG-y@(&7BNWHhsJ z>7l-(i~l_cPF$KrI5J+n18v_#$+&cGQ9W~&drQ5Rs256-3{U6J-1rs!6dpG?sLUEo z1pm`0R^U1zT5Lx0(&1x@^sA56 z-xtG>0x@0$t(eCjK6+x)y2(INhlC9+UnytAWYh;B22&1z2s8f@QwW`AgJtf{o3EW@t1(AOUmiOzYq6&#Uc-m z7CDE@rLy0t?YFq>L^K#1S%>-NTfZ*U&u)z@v#|0rlt|dV={RmBxizqgL#f`IBZeQY zo7YWP6R*hAhyh!uuZJ6uw6^&YPjkR0miK?Eqe0`U-FlBQ+>Ue}@O0LQ!jrE(;1f4L zVpe(xjCYOy`Dj%>u`l7Y6QmpAGghgUtcvT1GBD0-3NU_h*x68IV2pDe^FybMtLk~t zGA3z_sa}2WUeFB=GpOvG>?ClDHt-i51Y|d{RzGXES;bqhfa`u!frQ~%lU95F!?xAI zE$mC?%qW}(xa><e%-ikX;Wh~N`3yShsO+GDDtdAZCgXZ9so z>1@Vuaz!5A3?c5Kz```4TDZU#g0*VOdso+b=%MlMw>942HOlHUJ=X}{`1`lG7$-0f z@~!gxZ#`pn>6rdU@?@P}7ehjKwDGQQMo#>mG!+kX`?y|BMFCa)M9ndFBIjt>u_^g9 z1QH&Ruqb3yq1+q|`MsUPQ2oA5Ls;d1<7J}%zwEiNs9{|E!g$ zM>rNLXK}&X_GTeXZD{|2uh%^A>HhLFRlPpCh03wF%1K*P&R$l1Kck+%zxZXag{l11 z!?o~f5;3N{bTjzVKpbVo-@|8XB+k>*HfHZ;S;MMzS@;gXHxW%=(JuQ+_XYiF>H--qq+NeZ zvkZ6DI!Hw{EtHK(C%T6=`D-s6Kc0;WuQpE8$oPhpGYJ}Q;n50uxS+aN+Ro?}-Q?b$ zaT0#7#dYT5xMEtr!8CKtpzwy-ltJ*bK2sV~E)J{jmG!UV`_|QdH|bXJ%uRTj#Y3xK zfA~|qg(#mlP;v-(PO{90viUwIkA4!7$RWH?SykkfyK`E^=p>9DIO6;adTjT-m|ySF zIzM~8ek_CS@%H;mmY3H&ZfNMG$JMK8lY-ADfBleQU)_DT3nY;amNAyihQ~oGzEUh* zz4y+A&f30?qBMVLwzxO)ichr!hsXOaa6#KF+XtTcXwu~Skl7L2r#js`8dQ0dLM*e? z&AG@l75u~B(^WMG$#JV+i}`N~r3rbTchq_VF`@Q#r!4ME$13o-qF3~G#y;PAuUm7P zVMofb(@c*|)c5q@nJ6J;JqA|zoQqe+tnre^paSpKjfd;AO^v?6>f_sjlfk_#35Iv7v2v*?nDUVzdPuFUPF@kE!>LYHIo3hp!?iU8PA^ z6lv0=NpB)5DxpKD7K+ph7?9pUx=K@OLXi-92_RLa3PR{5lt_&vh6oq}ge32|>-+hw z_5Lv{D>*rHX3p&M>}NlF&PwZ?eO<8kw{s|ilgO5Z1#wF8B)Mz=t!@3WZ2XF0YOSxXaz5??_|{S6 zpO?74$!C)XxGwab?X4iBu?RU_uwh{>ST;@|T+CCkUdmpDG4f)g?dzn1PwDfF$+k82 zUe%vSMQ;ZVgZ;?J&+?wFwowOG^6}#s6}y^m>%Kk15dE{Mvn!w$zHVCO*Jo4|(;7wP zPHK0foq6;;-@5^Bw|b0ZknlTTkRCi(a@9haaoUr2_pFOIT%MHOl=0pSTQz_?zqxkO zy5`&mNj{x>o`wkpU@%j$rFbWO1OG;}W%bCUzMbMb5lW5-<}3~2ZeAU&GJffpI9DCK zsGbBMRhxg_A~T}bqdVl|68NH@NB4xiSJ*Fw!HH1B5`6}^8KjX|%cAdn9^L0_$wL;a zlc9|TqLGyZV|-4$@TyT^87VRh?E^hF!awHR$v40Yw>X*4Sqp;mU?ewpkhUOf)&ozJcSK2<;oH|kGBjwvS99_Dhr^uJeL=WwqGC^FG2#i!NlwSTl$)nrv1)vjKcQ2CtNM7Y1b;PKm4)vJB+h2Zr=dA zbhjSt=P5fRUG?mKH&AbUp_nZ8OxuJnr!5^dcCmH!1?utl$JFAtq?UAs%L#RT-c73s zgqPyq@I&|TkT+4yW}7|FV@TtivyY<59RJQ84u{S z=ij3yLxV%ZosIE)Evpl%oa-Hmz}Ps|9txE?KuM+8?2(Cf7|Ds>rt2CJM)D@=W^b*^ zv(7Ea^>*hEa@Ee`&HqefC}Ui@&5AEC2dYkl9y-glRdmG7+52jLD`MiUwRu~;P!OIv zw zg#Lig0Gn%{#V0^+J*Ye_B_+xW4|n@9)?!s(`74Jo)CS*qhTxCLn9KU}VY>K4xn&jk zs&g-!wWW9qfdF2c)Qu+PYNl@&FD1^gS}bX_XlIfNxyDtN|1i&4sI4yauC*7!NjUFt zbH<@fqZ;z*TtW0F+T-C+fhS886|&>loJFDR^;25*O+1fxeGShpMxb_{^nv*B9k%2` zje9W8&z?~PPf~HNF71EbO)!n^bkThz{a?f5ej@7<&vE7GgvqQz}is?_ftB;+m&_%6M_bJqm?Xmn3p z7b^ZZ65{;iAT~E#da?v~HpOQlBB7wV$@g{LDI#1bkMF+0xg`~$F}c4t=EvSf^2zcq z1Pn>-bAqQ{Ogl&6$|l|eQ#E!$^tjxvx83oY^3l1!!`Dx>0H$AVJbbH;e%FMlO7hB- z##vcA89RDT>v`GF&wn=_6>mm0yqMIQ=K;o`yrkG$AYB3+uvC`W=Fy#*TLapEQW0|3 z#Hp3sQ0@Q~FLR_lE~oLzevUNoRQG?A>mAtT$21F^SZX%{*=GYcb$=Yv1U}6PTZv&a z@-T4}H}ZpNAygbI67WW8yKz&TVBzXe!kpXns{Cip7eTSymZPm3ORu8}8^q_ItTdE= z*EPtk85y&A>C~obe>=cwO$0_cQ*i6$+e)pwM?JmwOjhT2p*I7BQ@^}lbQMM=>-ZtQ zzAw3*Sp5_7>cw}_S(~KPBKKsr$S^7~p>>@ofqX`wtVN7%Gud9f@Gx!s^PjL{gSQ+Du98@Z(kN2_(G5> zhQm%4GowD~R`xIw)Sv34Rz$K9LiV$U)OU{r7n)P=V#V(P5Lnqk2bO%%JcYF13WF4gW_-a&PjiVzkRPvOE;Idt>mp{7V+%&>=7P(^^htL&S1 zz6X#ll*Z2ftR-%;IC6S}59Bma968k+2t*NBeN0_RJ4N_Qu?3j8v6>oxIFo5|s{$g4 zZl>;CvZ-<^)8^C?qaQ{n~cvo&U3xdiLeip|$_lZ`L7n0bMEFUncR?3}dhfhyhNH8#pLR9!ge zuX*nNQ^#w(xCo(p*heWIE)KitapO%l85U6CTCx!XpptX-En@J&8dDFJ_WAKU_O-D3 z!mQCpYF5Q4!Fv1cHreN=t*&X9)-;$8ec9=QDOC`C*b&^=A^V)or~3W!Vk+(ey7l?m z8XH=pVM*Y}T!_&@Y-_|sgi3HP4|)z!AICP!*h1J-^iNr)oc+?8=X_&s z`h>%Wg7hjpKO50PSjg6t?*5+TvUD0}!)xZ8)XKhcVwZ5oc!`4;^eFMp-KG52ypnqd zsjb}`YpQPtMSThuUz$8r8&O$keYPX9tDWp&Pfll!gV!4_?P{LVk_4!73#v~of6MJN zqYsy^5$>$>`z-kwR_Ug5qUSUs(wS#9TL{ScrKQO(s1GH?t?g>$L~9v#_5>t1(R#`8 z@W*B`7h|i{FMC?XiDCl z#?ks%SJuy9DY+Gi4EK6aQsxs8sY!S~6=y-FeHGyDZZgkLTLarZN)Nn~eUH2(B5K&nBO>tab zXZKlJQU4axD(WM6(Pt@dKciKckMtuAFoRrmlw5g7bSoj38lsZUfS$u2#j5_LdMtHr zC)rONmigF6EsQ(Pr?gU6D#3B5ajlP$?5`iL>MhAJ?+g6UCSLHyH!J_Ow#SKnX^mQ; z{i_A_$+XRieNsd&%ybY?bZ7D)^tL}az+@3 z;6jkuT=M|aj6|HzhNj#U5WFl6!h^L~Bv@7?mm-l{IxZy7hx zjOs0IdILzer&|uk!8o;vadg`%_rwVw!QtRL<@&5j%fVdXo)0kFBuI5vsZA8nazE2X zhKpM2j5X=MN>Gm2=%C^%>*aUh2|*&}g0IThNyjeOEPLUcmywg>z4POr(H-s#d7R!O)K6pxsVC(#4aomV*!d++Mhn$#E_n#utH9-GxPs%|+LJE%YKC z137>B9QyMuX@3F0M30~4ju-%*_bWPU)Z9t+xSKzhHOfSi3CZl9nIRs{ZQ7U;1`60J!qVRC>NBU@%t7fVpOz|c8t!i^{K38eB)g5 z)4XtXyZ=@(+3mzhZMJb6UoCUJjYQGaw#mhyfgq?rG15yZajpkyL(6XEs*R8f9~D^V zt#w?59bF&e18Z)+G~)$So=)1q$ut27cYWG+BbQS-C(#kN(pHj9TY?CWsy6^d6WPn& z-W7M6Hs@qN9V#B73#Pn&Z0-(tY_x!;?!QEcftR3lrKE+Uo|iK^s_p#=f6L+eu{z3Q zc>*mvE8>spyyqo>ADbF;EP;U z8BnBY%i+cth`Laq&ni7DX5!6~MVH(&~R06B8jIoWpUXzNc~I(8+# zwp->P@>Lcpp@vZSx6J0if5Xj7lPw=u8H84I(~J0eQR-29ly6I`S4T+f{V2JHR(!o8 zc`Zb<5ZOFfTsw&U^A?G3?XthN{S<@$#4@B3-e1D$z_0!reOa`4LqggytmoxGu#l#| zJEG=@;#olS`q`#M5xs@F(!0fPI4ZLcg}GN!w&mLSgWr@c+7iC}QP)e-*dv7CQZJuv z(Q+ERgPgK7p4cyXR3CAj6S}q4T<&J!G_fx}y&6yA16a6+eKc`D|WfG%AV{Qb;_F&J}$|4XwNOoK2QaoOfmh z1P_e(O|Q#75?~$g^nL|EBRL($S_f8@7>}CBFG%S}+yc`GJC=+9*X-(uAJfF)C-ysy zmkOZ}MKCQIW$U-k1nz+(#xfD)!L<5WZfyXR2neF6jrCZbJ&R*}n=f`grZxwawoVyi8`@@`*cu-uLn;F@HviP?s`OQ`q zDKXqbOGM23c&BQuzF=I5#cp-e;KArNmOJjDbu#rcWPBf66!v3qL-ob+%cYaf6vyDoDWp4@(Nk(2RrF-J%KdMt8j2M5 zgeu~ih7GH?^LP^Z59WAckfL)$0IY(_ztN`q+=DJlOebC}@u1ht$k}@cP0)^6bA4d` zh7`IFzDl&*&t9O!Z; zJ92$j@`x(niEIPh32no^m-$8}j4I1&{G_5I?NFEhU!}N!m_uOJkXoiz^dX(xvda@9 zNN|2Fn;fPqkM12RIWO@N=&LWYpOS~>B&{TvqXDMFPS9;A$DhHGCukcbMx56%rPL(S z%dH1MBXt|VYh1H-Em0I*TvQdtkaGS`?dT^R7J}c;p1J=rq0XJ;+H)i`4?3!dEO%41 zl-k!?r(sM_is>Fg4bt~HdzE8!h7b+vjd{|?EY;rz>%R6S z%ha&&)^78?_iL249Fr+9b^3<*Ge$YF-dD9w*eVHd519Y1XLW%n_{@+bQ2p)EbK*Z> z;&ZEpt_JahfEcT`Uq4{c~^ro)gKsS-OI@YbLLy^E|oe*TR-EN-IAbpoR+kNWD#Y&;Yxkj(h#p-^~ z6pr)1KcLKaA)DGYEGUD;$NRF@38%5TEG--Zh=!}v;J7fq>z0fg&8TMJO#&qk76+`Ta@92%vUGkaXdR(F2vXWoy)y57m8Q zX!UxnBZ{GhwH!#0;SN1eb@&?(f6N+M{p6=^f zv+^!H&e&$GHd=^pUEcAp;Vp1$YWyqO0512`TmW@{@l@Pf?G4%#ui+IwUo$5m`V6T6 z2miVo2^^@JNtwjj%5oIF%778SdcL!iZO*>a?`ej-i&Kusm@QrTJz}UlZYw*!iVMs* zO`QFvW4Fh=B~Wc77zh8ZTx=_Qn-)@7(dB}C^Ori{D3LfTM$RbG_D`K%ABc~W_`(0& zR+d{uy!uU44X?2mi_YbDwz4A#0ygLx$`JXw@pY_jup^6Q>fdEi;x9@gxbTX9zNTo> z>^F~QOrwj7WB!}puUKwlI zAZ@pPX6sbNYfDQL8W*aK9&N@eBbsexH@Rs+Fv3^Qr&t8ogmkt#fsovr($8R>dP#Ak zZj$y4IjlobPYOtxHP|A(+&z`DPJPSu6ltEOSi}33R&6oNU@KcpL+qEM8o^qR!0m5O z&eiblpEnG(|6|EoFB^g`+<}5m10DQswU;=SgA40b7MG7s#nwFirA>leEa>uxERFLK16daa_xJg>h;xw&h#<$zA9f6cv=C>T6nmc#&RM z{q0H=&r`PQH%ZsY;LC|tH%O4&DvjrC)%X26b+x}Q*&3~$HZzO+Hm2OKlJYLocw_Y< zNK}0H__D3hr~YDxM;pmjDZiDJx{V<$)o+sVZ&g}+2c(}h(#vktK5a~Swf~M&-1HgGqIQ_R@|hT`{`uAA zk`wb9u}_J6eeGBaeIDjp8bjT^g4M$WiZS102T%2z!Bab~DpbGp1<}}vU$ZbWjzz`E>Rqk*oNbcdR5yK=>pWGO4ObPdD`<8VQR3lbvQv3sk z0-DUcKU1p1TYaB^`OIM%)tF*yzd#hve9F`KIGqSUvGl$Y8FPJPfSy@L;TS?t8UBg9 zr+Q6F?E3ZcyEn3V?D!u@md5a!!Qg4|v>%`c_u_`1NR>5-2^icquy(uW#!s!Igb0Qo zgwbEuXh0U7Ma>;=_{)s%R5(c2Y_FMXBcDDFL`I~(2U z@NFOa*hVtG)FFE5K_F3{YW*U6DI<(_|7V_SKE#|XhXd##? z`+M@X?UlbU5H{O8WoatDw|+jU8H2vrIg2lQHnQ)m$-6*4K!rCZ%zkb7Ur~T(q^|ab zE7!&2%9Hzv#>dQ-640GKuWU{|NOqOi$4Qa_SM001Ca1q$Bu!eJV?0j z4>_BPfNI!!W=oFPz%*32=qsOq|0i=a+zS!5l(0PXmq{=d zajQW!HpL!9a!bH8zIO*~!9`#id7~YRX1&q4b2rFG(9?4WrGMLs?@}2N2k|@K6uIdz zjge7KGV~6^EdS}|A0CoC{7J^HrLedt6Yfvq9U&tUp>m=a9 zIlC-=q&>Z2DS_MYy|l?;S*a9RrR`}063%No&uMYUejay!iftGI%mJyw5BGcd#MOg+!DJ|q2B z!=AzOGi^~qW6tg0$-(UGsFG2c(J;p33-S$eACsE>AAE^DxUH2?57T=36r$h_6yUBV zLO`@zmd1#r?sE|wvyDN+5A{hLvx~2;UK1Q}hd+5%@yx!%Jo{4J{QEsS8y5J1-8(m-B2LT7DLXqpsv|sO zWO^$*;t^B>e`+^tMm2z-&4X3TBG1gKBVU*bpG3gN&+M^A3_HWe4?VuSaqGe~uwub~ z8^lawG$fo8U%_asvpXSI^4>&>BC?=P5ki2KURuffn!XNPBK*+u;s|g?RpgZYyEsr0 zyBGT|^duJd`{E@R!wfyhZ!W~mT$d|Mvk$^QZwZcY!ZaAkGf!X#@wk7>6=d)IF@zj> zCvCjd1PQk~+1YR>!89mp3usvQ6+~cyJw*k<2Opn4vth0?6B(^>O{s-NQb!LG>Yn%a zY9>_UfwB1ts9O&r*5mi)?mX-4XKDE_NnMG!`;Sj2^kdErTpu7Iy)m*BqvafV6;!4jKU^UUNcD7P%_Wvt! z4^@%{d<{ZaEv5f$muDUbgmaIn3n`kt{OwlXPS;}Cflz_&vrcNV=t1he7G!0I2UkE8hOpo zhcn>3^ni={gG}@_OP1cAJHp4TIVp4xkAx9XY0{CE`DJNQxFu?eYHU`_mXkmEz0JU% zO?seM;Yaj3vnAr?CaVkpQ&QIVh#n7V|72eV1ymaB@k=B10mSK$NI^yAuyihKsth4@9}>Rq+}=(+#XLN2(Jd_QBp&)z z7ob?iNXn_`#g=N^0IfwVatk zE8v=iMkH2JzVyE8-Ho&Gd7i57)qS{Dj8j`g2kQhTAyiht{)BhH2cC!6(6qK>2Fb^{ z%Scg$aVp6EBVmDHy>7Xal^_Ew18H4l?UNyJ@rQ?9?lEZ285678?Aw@&IF&|;Fi{Or z_`G$<;6-(|KB&`K4wb!M6j1#zTa^l2-=I5NsDurAk`VgxNEKW5`T|LVs;bL^RD;{R zF?oI|g#lFWI<=Dxc?@$BDwSp$_J`Z7Blg;U1;TAW$lI>E(5S!Plry22q|kJq7dNCR zkIr=e>gQA}4TuXhTX8Ax*M{d!E+(_Xi}bpmvEJ!h1Ua4gi@s@NY{z*Hr=sPFOCMp! ziJ#u^V8>;G>WgYu)8Rc(C%KSxoBw*RVtx$T9o6q{zgzVZR2U!XqgnMLX`OkdIy|t6 zN5d4(XOUhiIkE(E;uuHmyqgErTeSKkBr(yUdpewO=(77ip>{H|>S-s8Gx(amG09E7 z85zs?=9I8A-FMUpo3sPh9w&)PZsSPpr2I;oLreW1L(QC zFh6PzhFqVoV|BhuMQNniwi*BaCD9x;M>Gf(=e4~+rKs~3eEf-O`hxAnX35nEC(8b> z=o98%BjLas$7mmoY5he`4o~vPN{F~Xupz;qhXYyHr@-b}`P$-02_X-6G`e7TE+q`q z8879-Fhhd{+4ONL!P?IuxlVESKl*VXQ+a-L$EL7&s?}*f)k_xC(_|DiG3Ks^25r+M zMkYuGgqn4sQ?t%k^j`hn{kzl)p26}Z2qBUtyvS2?Nd<6xLCB#X5xpKgg2F~vcE~PB zvxu0V-NNC?7ceEywv`3a9NqmX4UjU;T)#;{5bYmir*B6E_kbwe(L?2d9Y)YISno#0 zex$(6_`SgfQL4_&?#34auca@j(=e+ho5~FhdX~60sy;zFOK8!Mw=ScxB9#{Yyy4AZ znDO1gagoh>&LG3=nmR?&-RYB0sy=cd1L4A-6O;F~_&jZDzUOD+7(MfzUejB2=l5*W z&_G>G=Ys}S=U=v(fanw0Fpx*kAV#Ep!PIcG1W8CTTT`{#6zek(ht$T5ATS%1d zQF+w(irR(s=xy;5B<~f_X=_nvJJj}2Ecu5N`Z)Z`<7nc`tAq@`y{=<-QDxrryR}J` zx~B&{V!Q>(M3#$AKf8lntIoflqerGa75P>zBB#JfMs=YRc={XuR}|n-1WhLt@b>y^ zd_{8E*j_#THHv!n@okX)B{Lu1nJ8FnXF=_at4JM&~3 z0KnxEc{C*X(21S9B|E|->4ep?;eNTrS%9;-=zIMT2P`gDt2Xu)02(e|D!e1P^PsVg zPhX{boL=C`zEs0+wBZ2%$y})zb#L=J=xy!((NoLkApNi6P9l=NhKzj2y`9N8M(JNG z-Gv-EoR$itAff_i;!}|RgMzmX%8~Ib#pr5-MbmTA!+5Y_%s7|y0x`gE)_ZKA$o)Vz1m;7|jGXfwQyW-p|GrL0{SNHOoK*z+&xzxCD<^$0ho)W$bYmlFZMgj zSpP=#rg?G6Sw?oAq9!w7AXpT%vkkV`c(~t-je+Q~EE(C;c~f#wm#489$jA|^bD)J@We zJer(MIT4=m$0WuJDUZi$;O=uQLigh}9=@6}-`>*~wh*t32Xz|?TRA*ynmjfXHtAot z1W^ry%h00=0Ayx_aq|7X)UUvXJNkz8yyl4o4QUSa2oFcVuYY$`joJSf{`~uQ$SfQU z%g}wFomYAgqXEvG_z3WE+y`L6jhoW$@C~%%t5JX<31>R=2*v^XZp+x0Ti82iR)}Ljmd_Q+WXwNBZZdhSAb5k?ZH0%W@Uh!@;=9;tjo?Q zdYGh~2Vi~Z?6lQ?pgYtlI=V0sVjz6HWQ~J`i{P%*<*vjyBx(eKBYliF{Nc}6Z{)GM z(r-aGBGo%!DpwNqg_A-(M4^YAknnJPzcMZuH1u=BPZCuI%MdV2tt-PPXxt9DZ*0Dc zIV;@EX+2eX!~`jqeK3BnmlHDM_V>9Vz%Z_;h7X@5S->|EnF+5fbwER2&LL71QGH>I zczE934GZ{lHmj!F0vLVaS&MQHGkUB>hdMa$zp6QEg4*Apm1fLrJ;ZE-&InV|4e;;j!~y^RI9Vw^==|`bt)Pmyw!uEJqC! zg#g?5+OUkv{Va2i@^JZMfNu|4u6NoehIjNH)bLqz_0cl(7ruEuyJDI3Hmp&I6b%0~ zy<0RtNrvS!b!eRjg~xenbW4TB0z<#O{#3;gAl%y;X2=zII5d9?FZ+HQ51q;lC4fF!}5Q_V7=Jb8N09m*Cr~kpn#NLs=Q#vt1KIm1f6Y^W8XomE!@Q>3&|& z^sem#&aG~4=(Z$ZUyL(Z9b3g8Zb3dEV$%X=Z>e7l#-k$8>Yj*U;^_&Qit6=b@grX< zRNAGKx%FiW>5xOV{8X}*4Q^slYIM`bWRpG9ZG!z@ld*hb6zdx8!~L)aY^~uk^Bsit8XhocD>#ouWkxk=7R4(KQ9XSn8gi0r)7gEKIzeyDE`cmGtx_W zJ&i?8^jn}H69q>J=_q)Ocr8?TD^dp(#6>>zk@QO%(Fw%z=hry@=|2gl)9Oe=s;3;ilL4M4F6ZKu^bp>mU31_6k+|X9S>CMol zVgZiAUql1foqOnbAbJ>~NgnVRIvKi}fX#W{%7g3>Rh3zis|Kz}8L}5Fk|n3&<2E`` zD`CXkgnz{dlQi<_%C1JHPSOY>?M{gv=|YZpk^2lVsm8Uku-JUAK6*rTkJrgyo-xN! zj*6o(0S4bBSfpltI2t!{+x0a@|5(BjSe2_%-~WnqSceRYF`z}}UONTr28c>irVl*M z0MdA^uFA#dr62IC|P1 zqQbg<8T1Q{%e6Zn)*m0S;sFEwzd|h|Qn-Q)BzN^AwC8ZjWp|iKW6pI(>FfW@s3l|p z(UX2e@8|FQ(8%*7A2wS;+`clLh;PduHPekfIrKPMF%G#s)3)&UZ=~fo2m^ms*(o`$ z7vXB8DTTkL7ZLG0@(@P5Kyr0&x9v}TdSxc>)6Rt0Og*fp00q}J5@#o^{GB~#Ou9gN z>@u-!yvL8j&vZfr07Ld89d{qXdkrHPR%%pXU6*j0uakWl5YF)W--2^5W<+5JBoqjN z32B}rgOIB;YU$XoX38QlCxd)>8L*%Wq_N`R@q1frB*&=Y9a(`)y@;rI)UNS7D@nWA zKUqEC49;HNrI%%ZA6}o%^!$djDZG9gzQLJI*Nf;}nxBR4$DDY+QTDk<5XIqd?)_B+ zA_}#~PNSUvozNYP3kKY*bHaionA;!Pvwkg1k`iMO;jAv{Ro2CUli{_Wiv{kjU!9_C zVh<;Y`e&FfA^`M1FCVURmmq|zzOj~*xUMy0qv&a&3b=gCg6}tgLy;=xitfasWoPCG zvqzXnUU0wZske$FJ$`zammy_dfPNG~4PFHnq&kNio#6eMJ}3`z4z?IPw|QsArqADg zb%gP+_F}tcQGhP*uhHuMk9#FT2c(?eJ>JyO&X5zQP@lb_#m^_cCe|7!*zPj*le!lR zFGysaKh6=d9>Sj3ar|kmU-Zi#BOxfCs2vKLXtr_+(WFn4{{&(6{)Fe2)-wlw_vg^N zIW=$QKfhZsF=g9kl2N^Q<1 zyYr0n#f*%$*O?8jfVK`eugqN+g^d)s=iC5N57Ot)dHWmt3nIG0ntGT4=X@Mcsm}vg z*6q&nAIyM`IIc_U;z5)v6B8AqmHX&=UHXov?2XzuogFN&-N=+a#p? zr|eJXErZtA{uuOfT16VB>>80SSgD%)ApG~)bHCYJNmHQhYz`kI5)e(Ir7_K6cMM


X?mT%2k< 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

PpYH8~KV%}Q%lL@mWY~UoZ_Fkln4DkX4 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®dD)PWtRq8S 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≷PS=ur$enfEw#h>A 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

ZZHG=CdTFLyCHwjB^S8WeG9oyUL*Jv%!qFA^Zu# z%f?3td)8QLuY~a_%O-h*v9XFXa-6Lz-t5>v!g1PY>)<$@V>2Sfvbox_sZV1Sr{g$V zd^L9kB9&&LBDr*jt-DC7eDeckN!oppRF&?q*K6VA*t$4Q8||GNtGFDF6XsP_eq$)v zG{znO&cklqI}^){LWQBtOg0?f4O*6+j~6F%k}_o}QmnOWQ(>y%s1@(as#J|#ISx&z zm6Yo1K2-IhASeC{$S9anz z^-3W;bWp;_)!hSWgx3_1*fVQLo?iq*{NT?btlfqbdkK=)j0e@#-D-MQP?&A68GyA; zaQ>TK&E8NJs&$BzA^T<|bLyc+FO0nJU?cBwuLVZl%SXe=`#UpW=(_LxZTxf{;e z9(N{si2Bl~fIXhrf4=$1Y*EK?_IPTVZl4KWp&4BlFuHTIH#_6sW1;*jipjr@zaIZ? zYYqQ0&jbHDo(2D=Q~n(f<=;y|{L5$jo6h)0pVprYuG$wy<^+XCTNv$uZMR@hrX|DSJf?+dNBw?ca|r#@aEVsFpC7_hhOTfyGU zcCfdh^yzuWLhP+Sz1QyeIon%98xK*dB)`2GGXK{~zR?E%aUt26O$fnCU-~oY)K+CC?@ptII+Ygc6thq{1sqMC7!LhpxMcHi9O-9!ciZzK0o2R(XIXmVX6ka!3T4oG1jEoGeV{)ZssP ziR)QU#1Tm|c#c!AnMJ$lL$=TdKXbESUuVG{Sr`cRc^2${SgoZi@FD&CBh~OU4up)G_@1@k5Q&Tj1QDC1YAfbn1CRw1k&1yati_ z#o~}|9B{=dqnq*$AWfPM6-6fq?J}+H6x>~UP{(o7gngoNX#>y_j zU$xv{LW(_Re+en}cinLkK7uei-bPsir3!o1Q?~#w*cLNG%7d^gf$_z#CIxmSjAy6L z76eY6JzNm9D}l8Qp{IpdhYMk6Av<+;eF01c-1!&Sl|XN*Wp35GWdV$a6E z8*;SQtB}^sNQS7lbikLS*q2IhF4<8DHz52uTTX&xII{^U?Rz6fRSA;kvje8;q>OrG z`Wz{D8cL9myPYCJVu)bp*Lf)-s`!X5-+QdfSI)Jx==m9rYVyt6>3!Bp*t6wD_;YpjEg=W^{V*gHzq{=n zfxLBE4zMHqb`4=i_-(7vwcLJk9L^4HDmjTz>S0A%#M=-)lZ&nI!`Wr^qKr~$y`NDf z3Aecr9=%A!JH?C!tFvKdXErA!;o~HKykx2uoGaL-LgAS?9LI?cPuFRQ!<5{9T$yEs zq}W%w`%3u!aw|S8IzAFaWkx!$PW{+R=;vcgt?1aGlkoj3B>Dbw2~VjMD(vq=#dk>U zdvhW;tXkingUO$GB-?Axo2L>)Oeq>0-g5_d(VA#eK<~+W!kLalPap zWv!+67Jm__T3d>J6yD7}*-X@XZj9iaq;%lAwQ_v_cVwRn?+vlfC-03p{@?iP*=OH@ zt+UTgm!A*&+?vvQ`~1teWKOm14zW+=sepYBxB={Q&^WNq!Sv~8_Jr7HZ+g%0`8nHX z{jp}EesFy>`;4nT&;0zU>8GwR{gm@_=ASMZ8)ARDv9atg^~Yb&{@xnUI{TZ~<9yiP zt;wyoze9H?bLz>@LhP?YX~6#8y$f-4=wW&f|VKGUv56Mz zX*A4-f=ZG$si}GHUmi3cx@R==B{5&?MhE6Yqj){>x;DyQ&E`YP0|E?4egRw)nj~fL zppe1#LN6O^9}+0z*9sNwf{XYQd}t9L#s`Y{6FPUCh`)vuGp)B>hpN7hQ%%ZZLwh1uEzSOG?vX?Mnr@20X;Df5C552rTU1HJ-lAK$S200#&}d1E_NFj$}^FuJaPtb1??kFa0wNu&<#H)@)_LzQKas zHzN?NlLh+>3-($1^f%kQ#5I$Rkk6zy$~5nbnD>{0ybovIZ)4u`>C-P$?{?<>7J5U} zyg$nZ*#8{lJ%M>oV&0SK(-WxoiD3imjkhOr>ZjX62H0szhYYYs%TyR(2PH8WU}t`U z2iW1azyLdQe&&X(oS| z&%!oo^Pl;Y$-|Rc3jci+>?eygk>q9c3vC8<%QZo>pKGsa0nTL+aGri^ zGN;bo#5ndI!{EQB2RL@i)xa@yD{xGtPyc(fm$=Gez*oSM5iuvFz6dc$4Iy#Jed*9UojgL!|Kd4G>SZJ^!@nfI6Jjkh%KPck@f zd^F(wFULWvb<1H;K5C7AqNc~7*- z&&l7hz7kgI!0OX8M8}4uK}C3RtyYA8X156`Ygl)vL2c><$Y8x3gHD18P?fn>H_*>; z)-y4)rhqKl-jP8Qpeoa5GO`I!Bbxx_*aYaiBVj_}4l7K6(wpj>F+3;XWzc<@U|2Yk zO)VgKWD=66g-k813Yh?Xi{m&8E&dSomL@=vGH$7)XbT*UBK(ykFR6vkJ;Zk2AsIC0 zkkX#b%<(P>??V~8t)|0BnaA!4x!aMvhMjiem1HN4uLU1dcXP2OLQ`8*e}ak7y*(gR z#*Rql)JYpzDf*rj!dcS-r6~OhC`J87Kq=}^pDwBP64z?~L})j9udzDN8*C{}qFD9* zubPRvG5LGqlBy3q^m5Wj>SwDywHCExaqayxP z%s6Rv9+-KZSan$En{z8JhdRV9;?E?!pX861@F5X@Dd97cTwE@h_6g3Ryf%H9K=Hcb zD1m>sh^CFg9Fd0^MFYa4mrm>En^i=LWwq!a#%V(lu9EO+_e?gs7>68{f@srmR2#2gH1?jzcd%0cI;1>WETEfJxM66 zheW1OkE;*^iul(NwzN#Gj>{?4Kq{4sv}x*BD~W-?P^a%vSksf$%!$M`M^(Y zy&sO0;uUH^oi}Vcv%mW4|8!jF1eMMlb<$J*qM4|7^^CgT9ytydN!Yr;O4|sqvK-;j zWe6{0OD14dwLTt_|UxgIIj6B~4-XR&sDKCqIcgo(I*TPO&a~=R_2hw)Rwz(5# zGzaAQW;CVrBvH1dhk$1+G%Itfnh>_kg+2Hq;^=Fqlvw2(kYX6?i%)1oELub)c`^N% zsPVa+#b>B5K9Ai2@#&ZsYaNIr7ncc7ZPo>&a5X3bP|y{ZOZW)M?=4hV%FB64hBYQa zX;-LhEK4EoU6^Bmgfl^%#nIG{HfX+eH1)CfLUQq3Bn!gYdNL|oRK}+BNVYFPvbOWH zOBpZWCX}%o(HiCUl0lhvYf!7u%)BS8&EzKB#;N6{Cnyk(pEW2%%kzTJUA6LU{Ys1F+HsA0_!|WtP`Pyhk#f5gczp zjbSgdW^A=&{b0!=maGFo;Wb#wd8An1u<4O(U6G5MgthH?=O$a8+4PZpXlT@giqWr^ zB?}eS@`ftj))~pxrS6X5=Ot}-A+iaXYR!&aoF(hPFk$WW8A0D0_N`{JK_nZkrXwQW zBRC%hdk0IgW_+V%-AF~Bh-B*mB)37PS~l^Glt&0MRU^5$gc^e+!y=78vK1+29+{3ITs8GOY5+(!x^vm?eZhGM1S27;uruVegpZN@90{M2 zGQN@cW8eWB>08~#uy;$iQp(sT^3_&TlO*IGlkkl+X@LzZ)PsY=*>F2@Y$%G!o$J*N zU4vSOK_UGoA|#;9mAjjXTHh^P@5Q%2=wmD15FpH4gxP9PyoPOR85c?zNgjk0L$_f* z!VIkWffjXpaKUaK+5%y|9ttJ8Fjp(luipkGx^8IfH51nu0(>chGMWl^x+BHF`C<|p z1y@T^_=rW}hhbV2(pePN42|8kdL6WGZBiM`e~S^Z{i0 zT5$X)j^nI+qv)viB3xV|;%1>I?WuEC?6C-I2d4`ahD|xNnQprp$pb5LlDS+=)SE9& zJ19f`nUl<^FMU88akfp+azo0%l@FdESv%ATmp}tX|CkG%u{{X^E?SbSE6iuQczrkOXGw%7->gy(p`b6gOQKjX6YBH2gzRCzatmGHpe;dg^zg>5Hk?yXJB}ksiVMnwJm=n?;WHGH81^N5cE0 zj3$w{aH8ppX@8P3z7@#^mfmKeA~&53?r-ZGQsTmj8QFly7W*eO!Xo~{-7`2RQsHjs z^TBaAi16nmKL_F66!3AhYFJGTm|8SA$F_!k7S>Wh%%((kYr9hy3$MBg1fET=#Gz8 zjf@VD2&+cE+TKjmH#)`CJ7?|HMXbHb8mXffAZ#x~cuisSs^ki!7(N{AuS#ZoA5oRO zG`IzhmktJwUwN~}@v$Os+&;La#%f+fV|8GhuQFLbIBI3`)?j}_wJ=sgwT#7O;Sen@ zbqM0}*x=Z8${J{-+Gr!SK`4D28maNDjoRREqayhQs7gvd2*%7R=2(PqYM_m3#otG? zQO8)78PG;u#EP*V;Vzhm=50n3G*U;?%EW$KP(?zUcEQcmG2z~Q)d*|1jS(F+y6{J& zLB$JfgP>7FYAFV<1q_C^2U~8h#!I-736ycdlGOlh z*8`L0M)HugS8t^4)d8TQBMU5wUFFfGxJ4dXvJOxf-Vpds_KjVTGD44VBGy6sv|2Kq zkg(V8kmMx{8!xb8Pg{RrE;ROTiw|SNy&>&L__E^&?}46uy_B&JDS8Kzt&8CF&Ehim zosiG65ttKr!c=R!2|22o8D6Un>P9H~#bB=))rkKJIjZ$@<>Ae8GQO)B^YElHT(9Bv zpk!*aw_yQu?gT00d!*<;pkxZdz^wz$wq4q{L-cm3J|ZLlit=$YQO6_&fD)~JN|7RA zONod-3Td4dFNo1JeK_0ClfK_Z@MKhW3p}|#8_Mu!Cany&w?G-bGCOwDG&iDYI>6sF zwP#1A$-ON_!OWs?yDthjm-WB1V_`&+i{}bYtqEzKz8%s$9q((NS{6w-jaCz8p~9lI zOiL&>j!;fv6$nI)R$I<93Ew-i7-zzQFVzHVSs|lMBl7NT_-Vm&UqRcuf zS3`g$=l?m+ncMCrQF-6@U;X%Dv$JQ;<$0d-oagdA=MD4J%I>unKv$2TPISO(0L};xQs<<^dbwI*+3F z^l}n^6ong{^1_5X7C(@{#V8z0AZ4Kwc^VKty6|&4s{@|IqI*RAk%Uh(qqfqtXG@ai zYU+q}i?$66L+Uvm(+ceD%hR8xzGqpr0cu>sZV!AyUzO_jIgmVS9m;T6CazQzmptu= zg<_DB^B59*EeJah?qk#bnU|$%|9jJI+Ek-;f2L)$-gad_PQB(IJsYj-F70xSDQZp- z^>{C~#-!S-^CTAb2;i+EeqY4x)ZI-x8qu_7cdDneL4wvH#g%s@Q|?G{ZT%1m+jab@ zk{)#Yze_;J-+Ps={j+fdlhG!B|f#l`ov^zrG zyMCeWLr@y0jF^r*zcPSTi5(2%y}>(^lpz#ubc?tN$^Ht&Z$V@W95IiS>3k&`7swML zzkz1@MRo}l^iM>#AX4A%Y~@2A$N!51CxKDj@V14z!xBD3X5@KsqfmF18R^aQj%^HG zX!M_UCYX;%OvF?2XtS3C24a4tai>@OLf)#pjF!lOwd1zDK(swHOq+r58}zS1+EiUW z%)(TVt~3QH+h1}(D-wossqzu*2O(jT-j;j~H0A38DqmN`pWryI(vqMdS`g~%@;;^D z-DcCdLNynO-QQokk*?2X`;pkv$t+APx`pakyR)9R`YS|6(do?yLtU}xm4uM^&j{QJ zlzji4KM#4f1kdw^mvfvDc|AdhmSd+OB}9L-H`Cd@JUQB}FBt>9!5rvyk-hr$W+_hp z6JYfoM&ZVJcBkJM3tZSEJhepQFGTi+YP8oLw?PAJ@?NqaPwqzoYP%Nmh6Vsu_;186LQ1_)LWThmqp%kd#@6%e*(J%TEzP zrQe?}+#tgioVzvm42i-K4D0Csez=?G1de zwpGf#*03Vj*K&$tLGWE-o(4o9856AENev~)Z<(nc- zB(D=Vv<@lD*U&}cJqOJEHArzCyVP7H*1eauNW6P#4~s<2rLahdKhhV8^0BZ;Ja=jL zC+RjP<^Nx0Cit4}GylE~ ziyHVgJUx$^PDz-6(9Jz&TF0roIy-g2?RGp}2<~N@6GT11C++|H{`}13O@3ZH(&T6B zJ8ArMjqHJ+Y7y}B{!4X!Zn_%y`9V?l{A^6(XZ82tXIVC5XsM%nhQ82OXXr!+$E_UO z6+`uJBa;|P`C0#oLvh|vRFA2t@_m`+s3SSMlCbYb4}V!|ax-~5ISy@L zX53D79O)#IJcrtEvkUt%{wXfk+Z@{f-0Y9(th}bs#>!3lR`gcJ(g_z90xMrA0#>%D zpN#@m_ATrw?3jF4Ku;Q&MF2Y`d{n~wy)|@MQUBSSr-FbzAn+m!xdV-lQ{X z15zd|y95}NTL=u=p!%)?2F<^udjoqjL~U-Z??BPLLgYmk$N7Zn_dvq2!`P$j|*BHkUqM}Env zL;A4g(VUaQk=b(e4dj{eA*U^GkReGSMSK?IIrASDI?)iLxe{LIXMn* z4}anmqB-DL1S+sMCtlAf8z+uZy4GMbjWT{auFSoZvXFXB7>g68xP)p>V-kr(Ii~>PIR{I2 zkr@bXRUJP(beFw+FJ11mzKjp_wLETE69nU3swb7U7lK+GQ@AxE!1 z-^PPxC>(rGdru#n_Z6Nt^rBhGYuanw+k<&N?0*O0K#Pdq6>+dWImBr2rZIG(cD;=;)%vTnnlU}FrDQK~A`)BL56QDykbHw% zs6O28JX#tW=>U?Cyykv(D&v}Q< zG+m5GrHSzfZNc}|FC_=GiAnd3cNfpq@(g}g0l!~k_!@sndw5H$C{Of{{mduNc_(xjKe7#$!Zf$qAl?stpItft*|G`E!p)RHjo}HwA z*e-KWKLd1m0@ zrpC0u!?N>w2t54kJaC4%3-rLlm`lJJDm$-xXQ-Fc9(XvN@$H!gB>UGi+j0%w433*y znUY_SIqmAXUB-VyS6QLnpTtj5--pUqPx*!5n`R_6TjsP}7VqsLzwoSs<76W^Ub2gn z%^N>FG#@FGoh)4tp}!Z~e`l$MTs^fQME?l}+2m|i{>HTOKD_^5EW0qP(u*783deCt zEJS|WRbg5%5)17?;VlUWQ_CF3#lHdbz?i>A zM0+AnI~SkKTbYW=l5Ki|&nMKi*>e?va!K~Dkyy?mElW{}l)+)zc02&P_qI?4&_BLB zHU9r=EBi;5t@Y^psjd=5a_czu4?R9BtKiaw%wZ`T;*Z{dImW z7y|sn{r+S5gCW=chw=wo51b7%hptZ$^^1eK|C9W|>CeslLAKk>A8h?sTK?b*p@;mz zn*zgs^waYP>jwiX>xBQi{J}YW{?GCUV?I5b{J|6dognJ1pZAEH@KCo#}-|h|PTQluhgzGY`EJFEr$s+v51zCjWMt%1zLIslb4WU*DK6*`BB4L#4 ztP=^aaRVcF{4mQU7%e8nUjLb#PWYphPIv;+3BX3|&51w%tr>-`M)Z;=EvfMHZc-!P zF{z-BDldLMj4D(CA=uSyU=VEn*vWD6Lgn|8=3zHQNIQ$tI!DHG%!P z4#}Ykr1*El?@3NG#2?|hq!`S|ax>Ym#!5EmWEv2UWOPsKDYlfuRT(Cs3o~qlcE%@V zq-Gr|x;1f(fhz+lY>5XQv{V*SbI91cXgVrDSXyFtnd1iZ49)sjYMfhZ&m0?J3=!z;kejiEQ+BHsnZLhKRcDufG zVF?ZVV}hvrKFZ~K$ZzC8euJuqqy)!#W{mA(nS+JX9xuPdbXG^poOVs68G#FZV2io# zG1C&k5!#~e;*YlcM({d&@U*w=*7~yeBdeb}^Uea@nLo&!`Q((vC@W=Al9aNrhI0`c z&L#FR^Kf%G7s;G9!WzvU+i3RsBL_m~YJ<{)gI#4cdcwDLov-M&i(8Ysc)84JS9Q}x zEBo*T%RXoq_n5#CA`QR|i|9_dSj*PQ-9*XF5)@_g^aONUGSd?X&uUF)#Yhys z#*~&Kv+JW|PMcuFx@Wc0?!Skc9R@qzFWFm@X~e4@O=AdsMNePUOM>rM4P(lV;9W?* z#>S95lObCmm{rPxS$Ged0axf+8Gi(PqDmsrie!&bgM^pIg2PQF4KLXXYk{{{Ru{Pp z%0K$PP`6h*&z7Ii-}aKXe0cc|BzwFs^WIldL<%(pcIcBysCe9#n^+#}Qgl3Bh|ZNVr;SM_!+SO| zykBExC1!RK5}(m!R-%SwB}!`ji3F|%$V{ctO!pDSaKV2mT=pNOqeNC{tXSlCI znNJ9*h~7&GX@c`NxJWFRTLBwsd=<*Q0CAt{Mhe^CtH2(fy1VEC{O9*`ITVcruNQHX zzl3Og>3Ra!-v>OMK@W=V4IY^!R7WPToxxq)pZ`wU{rSPo+UDe29{TBr$-!O{cAZQ1 z?%cHfgmCu~&v8E7!iMY<>H^7QM#`*x2(Lzzi{WOsq*Rr`iC6GM!tGuhQh}Pat(C; zZI((+a*CVanx)~sis;RZSGNEUe?ocak8BI}^;IbBmni)uAZJMmoG*ct)w2yIO8B7q z!MnK}YKBYI*oh14;bJxU(m>HS0sN&{pKyrsM0M4Bxtxfbjk};~h=%L0nJ#8l%kCX|+2OlM>d;!M^eGqO|_y5enb{E0rc@oU^6+!Pb~WufM&ZqCBS+kT(hoaOjY(^Lo7)%suK$l#ndJUu1dN;|$D zcQj==Q1evhkCH3zLLLxLIRqy+n#b&=#7e3l>#FF-4@7I&!F5}laBy7=zQKW+5^hp+ z-{~|@$5dP+&bVnAb`YGa?XU0#J5)Qm&pPUkqs5G)?poPVckH$>_JQ?VwI;luaC1l* zIIoj>2UYZ;`o~@nVc815bRA)tkYSH$UIA{hzp*L$SK0$Vbqc5*E-9-w!HEC}LHE9Z zYuNzT(x1IT_4`PvWdu;zAloH&&}EtT2JcMoteNVz46yEtss7&paIxZ&E3X9d8eG6EVemVel?I7G!#(ZeFLToK`L*7`UAIDjA2!+X=!lMA^3pYE| zr{850CmLfLoXTrqB*Dxk?nj8kkUYyRdj8F}y(2}LMhLOxPlf6bS2`Am7doee09MGh zzHO!pN9ouqFB~ASff59Z&T^Fk(;yGH#&ENgE#l0h9GV!9a|;RZrSs1lH$BVd?;258%6g`5~^QzQL>d* z6pLglA~9(k9C9kGx|nJ!I^fZ}-#S7?vK7ugRpobbxo`(BM6ZJ*?{xJr>%CkK$-r3M z__)q8K6EII9}=ayNcu~NPG=$d6kR1(8;dtAqAXM%h6)XfMTk_{Gm8&U)3Y~{qf~gx zvmHoY%is*`wApU6tWOedEn6L|Ihc{D3$u7m zyBIRUBshd};*EE5Ic5y-Dsl#vkb09PlT&WRmYPlcKM%x5u zxSQiF_v}FMJyG@*Yrg?^CVm*FKu>Je_yYe3iTZG7rzO;cT?W0f^aZ!SXJDkEJV_yNaD3ghcDOuS9>d78!W{v8NW_gu9&2{(JfBcq=#PAL{}Ao+ zuJEK@ywxB1YUw$EZjnpfUZMKUc4tdz=ystRX21qGFEE;?pMgCPHWx$uiS5mgoOW=W z4D_PkzH)G!@0yKNW`*cJ7WSorD0xxow4lYJ=Ev-Vr z?dl6}fXfqF6n{kkEKfeAQqf7Mp0`(zS%1t{QksDIm3sv=gR+AU(#mJ(m9LE7B2ZSG zP=EF&JP{(Iz;PnKRSbWg5cwtvS0QVnA=$NZ7uapL!%0yG85zCU&xzr!PMZ+kV+M>4 z2+`eV2#G%l<2s?X@6a3C2NFLkA7KZQb4NhE)3Ocf^7WLq2=|pTu0+()s)EM~;t}ra zt0*MU7UPeIKTHbHWt=esbRm`cJnq^?*SniJ55M@C2N8zSGZQO0m-1h!M&(Dat01Z{z$K#6QZ{| zI4*uSSllg!gl}`Cw7AH@T3qgcWA_-%B+o{W*ND%-ap79v9hGq*;?J~AgExif2>1@7 z$s~}<-3A^)Jd)r)+_Qwg++j+%5c#u<%3HhoRtpn@D18uj=2~!Zq2f><*kh4r+g~k2 z_Vh`P2<9?bxIWLq)s_i$hmlfCmoN3>g`Gqjk*q(g7i9oNlz5KCDP3gdH664Ld00Qzz479leEBt(_XzGTuNW>s1Qy67aVoyi2sO@2#= z=2&rR`lnse=2H7@82L_;CRb5OBRk7qA5B*!UU=jr&vB7mLUb}Dn5sJH%(#{v3{x2I z588Kxm``|4*Xte`R9Ca z2$G{UY_bLI?*+$FB27WKl}&=sr|tDTRj4pE+Z*^$u=NX}dOLk@F^X;zqPQ2wm2A@% z8lAMYf)wS&GlY~z+G#fxY8qX`r*sqBx>*U`gi*HF^P%6g#)azo_69!qD3TSux1rzA zRwH+xpx?G3+3yyf;^MPUP{Poj9YuH#ina$wA!YnkNS>7^$&=g&@3G{`CsgYqydqgAr;|M2)~DlKJp3G3YBRu9eQ6$j;^6P*VD8(R}%xcMQl?gPt%fX zky87FQ7Q|`wQxy{XHRgr#5bd&6aJDIlg}wabxzilYjQF|eMAzIJWZjm5PsXZ@3ne6 z68uUBDCO0$G;!iojcuJdZ zHC#9LNJF|kGSm63_DHcaS-04+`qyL#QFqGk0}aIeIcfT!43RBDH5lF-cmYoBrvj-c zltl3poyqg?Iyw*gnDaDgrpSJG6P;(lUb+x#E|4n}?rQ&0!-8Sy_itG(t5^r?%U{_OJ`rob| zSQ{M!R^Q5$GN~IX^iixF1`6)KjuFE0h19XQJ}(-BMf0%-kJ*Me*|KNZ5XaCVo~sY> z=eB$!jPrMVH|xi?wDn_`vpavnTtEJiBCcuc$79aa1-4X(-0x%>9FDA7%S_x4gy?^9 zHtX}W&H6-mHyEHCdeyQ#ThcAhs>8bFc@ACo-;XiN^W1oclUbghHRytN&}laa&u!5S zLi_<3gZ@HBQpF&Bd9q2S*7C!J?%TJ-NH(SL2_TzTRb69wIIE0He zE4zQa$)MqSsACd@I@}I63+8vZUl8U)qov=sCh7OOWc~hCs1T4bJ?ZzYLgY_;_eucC ztLa$V9Xw*XE9gY>H20)yoFxoGV}CKn&C^oj)cK9j~|8jQ9WvlOZW>^bP9z}xr9eQgn-sIA@VkmX=_6C zoLO9ol&MY$$8GyV$`W!3UXZ~3*m<30PC7qv>%z~4Y6#9y1K?aFL%>KIuz?R=YVI{&lQBhL~ zLE%nEsj#*g@f|4K;FLUHEUFi(iV5GT06w8 z_+So_YpKzwavvo~J4`qp$!jUCLgU+kj(iBA=-$wc+D~-TMt$esv@FyVtVVJzHRsgL z@DOSZ{Y`rr$+dLKsvF=j)Dx^haxJBX`d|M}5ER`T?1k{h1OiVf@ymIT4LpnCdTysJf1F5SLu;cW~Mm5jP>lb%zE^Ff6)ysEjSh+IiXl z?HtXm_0@9hr`w6R$)IYnLDlib_>oS@(2WKOZ%1JeP%dO&%WG;u4fn~RJ5`;fi*X&9VN>co>I)7IJ z3?KiJ1nDx~+X5NOHv)KT*SWA_V$X%;!#CF}arjmU-}Fn7npFPPP9n+c-K@+7pMVK9 zmVMj$DCELQS^OOlGZ%JzzbzLwmbEgQwaHFU)H7of-q;VhuvSZ@)et>0*FojC3wEB-|K$F?jnGF z%|vbgd8e^pTKAw-<+HQW^Pof12=eS)G!)?@=tLXh+mJH8uP~Gwn;GhZNE0I4LdOyA zq?J7liyw?b&;49!1swF;Pf>hV@?!N57FD7zS^1q8?D?HV{s>|CEqN`_NCrvhA$^h0 zxSvmw(ies48J9NBNbIz5-v>V|wIY6x(wf+fh-2*c>|qLvDhPq9!`KR?UQT z(X0&;4y=O%r~mc2X*Rbmxd`zwkYT?2xm!hV4apl2P*j5 zrz_5D#qi1eh5e>0IoC=>aTGq8FN8OOnv47J=S4f|cuwq+_)k#y^Q>Tgvc2XLs(D`p z1VKnWB0EE0qwuLLVO1^1;^9JdzY4cdJ%g_(3%wfiN!GFw{|z&pk8PC-;w@DhGQ9p|Hr z_yE=ze~TDya!5E-BjG^I*x|Q5fOo0~s&ctWP0p)0p?X#g9Mgm3Pz#c0#k4G>gkD8$ zUr^n%_SQ~fyW?xfyL34sX}5@V^n8n$ddXd>H;7#cH;eVX3&6d$7G8fR(bWX>FGvv8 z{Za~^SKpr|VgDM01M5Wmt|ZUNm*nMnDTk(C9VNk^AjS35J#J%j+OcTb=Csm1?(R3I zUAza@uRngsvCV03AB4qgz#ccJ-AwEIz^r;rde!fK&_mTVA3)V!qw1xs>gPUicXI)l z@bLM({a%F}+o`6rA@O0mWTDjC?kwPgy+wIhfm^-xZ8``2H6r#ExCOU=gIDP1EU=d! zOIN^PFHv6URxdY8Pc;f>84cwjIk2vRH!m?ja$pU7wXSz)&j7YQ=vF`5#VSI0GE^k= z%dnR$M)GZLtMn`BrICDFp|xE(1s!#9kK*T2mu&1L>aI<>To>o>vwZpNGd;pnfG3*A$~5l=8>*6hdngPx)S8q;w(MHB+h#*mvOpHcFib4; z9W91$6PD}-LCM<#HWYoRN}qwO%-P*No@i(io~R$g6SX!)?>>`)CtAP~>TG~(?>=Li zP>cWy8)Uo0vSB8k=xH0CXl*KTy!poFBK zUjTR_PnENikl-SK5_zh!>6f{HB=S_{&@VRwkjPU-9fzO%1zyn^qYoczRYPC>EZ|2p}Sco z?;o9n#5W~lhyKoNOInX*TRv~ME%gogsm30_iDsWM;6xx+GR&PG47H_fzAQbHWT=&= zJG{Jg^K!Doi<+YqXKaS$EW@z8ml~Ffx=8nrwxiO7_NAoI{ri z3r!U3r{g=i#S>j7*ziOnt@DaxPIGs4UfV2NPGgphrMWVv^`C3)U+NYw6#7xTrY}>c zw*5|)06cG`t%a!44Y25P1}r*u@_1LkqJ23W7oU|3EE<#=ueJ7bv61K7_LG?LRXSe3 zZM^>PJYGGY5gHcfop9d2HNMxZ@qL!TF0|_kOO)%A3$=b}_#q@O&qHz+Y|-%HFW3&3 zVd?OmdjQ_^Gb6s-9lq$66nxRN3_HGPdb$ro{dz;Urj(b_2u%Ht3c2 zWxynOncsr&+T=Xs=NrEZFe!kKCt)PUT2P_UXDp~t=s^P}wD7)eAws8k1`#^S+aW^l zr9gy&b1ZmJXkL7m!wwBPmJAIF-Y#?6&vi@&eygzbv8Ig zPJ-whXs_pkOKcFGkO|RQ0uY@ky#b=LsB4JM%PA0@aePWQ|KhN9^Y6(R9c*HBWE(~Y zLt3qWM-oQI+3`QbXT)!XnP)Hq;lnx~kl<@Tcn>OSK=r2_-N1JmmgH(~1HRL+*hOvH zsgkn#DHFpZ$*UQLXG`$%>#3;Jf8r2}TKy&4lGf{~@__6q;|64hYQ=E9Q}S#NebpK- zjS$*rT?Ub&=>0l^6z9Xpvn7-t&*QE2P5)hSJ_Pc3hO>ithV{7qdxfW(r~%-!82~vl zr=8Q|`tKdv6dD#^&2gN4{eRsA2?@~)QqT_BGROAQvG&Jhgl@6_e4e>UbzoQdXLh2R z3E+va^J$ZSO#0xX8H5l!3gE+Uz5@y%iF|+ihLHFjSw_?UEBKuse*?a}`q-cKbu%-& z$940CzkC<`&X;!lPPca6wKhBNS{s{bvEDtvbV7sUKgmooU>m4uH#HL+nB<+~W`pCR zqrj#bmf77_@f7&Z#h~;qI&R=EQMle|2k>Ou$5_yvJpIq@*&*?JU8(jg9qw#b+HmRo z=$m%lDXiV4_O<&$mx<%+Nc7yTpT7_#JkOeV6D)4V7@3h zt9SAAO_a zkB)Q_^3r!k8XfEsY1C#QjaqC-qpNkK(f?2QqB0x4$oD_T7nSV&4)CHsziI+lB)KXD zUKEJ7+u=o_SG#~0-TrEq@FMZmF5pF@UQLidv_05M!Y8_f7yW|gI0&}(j4qnQbDaAA zn`tPbk@WfI^ylZ$=YM^Zp^JtNb8wo+z!&k&{{ei_Wi?&kiw4znfiH5@bb&AW>Xk0= zMY~`5KKP<(GZRD|_*)j$&CTx$Uu28#cJLM+Xh#>hEO)1!dMwN2`s-Hsmd*CYAJ%hO zN1o~=k_=yw;yPUmCRrYPqiP=HvhrDcw$R!e|4ywfmzBp_VX;*9Vdk=)uZ3KewAspK zm2Zb!*3-4_ZttRw0vc#peMcZlgvb(yk;}^KOhyAS-*qjdmXwWoY-{{GNU3GxSJ)UW zG|)}nS!$aN4Kxz+t8?6tI}Hu?Hv0--z3?_U3%K%HXfAX~{9mAfeFg4jJ=p0h(BVN) zLWn$V9{H>zgl6ODmn_PhQ$Ux)VQe|{*6QowC8Ba;fs-wY-in+8O$^AF6~IwoV)(O8 zk-RB+)X*j7GAQALkkpR{u*#Oe?LM{yN>~-;8w=cY0Ti)RkS!~;Wt_9B*|*BcSsgPk zuVxVgc{Ot=rX`SP=b}{m$CDZAg~ClvO{WIan9xsx`X zKl@!0M>{&)Jzl04(CPY^ZpNu~}uFGx`b>GzX~_?;vjAXH~b@=zq-lr7?BvF%U* zeWchwRvMnI^8m24G8Wi4= zK;hHl7iCL09^c3?Pc=GlXwgLa5YCW^?iDIrko>xB4Z^c3Xp<;>y1#_|5} z_(U$}ZT1ZXEg)3iR@1%(06_j0B;N)AAph&AO`~L&WPdr50~K(MksMe<`T8%m#nN}w zhqt$V5&mSQx4oW6f^WNokD{XO$g^kBFr*APPbxYJI=01MvaM{U`r@^n#NebRqUheB z&&yC>O`aa9siGb?jB zI_<(8cP+eEsCIq*lAEJu&b>~KE7^5>B-i=lrfBM@|Y7Q=7=h9?kLbBWK z#am%5UkGvfwe(l<&NJ%EiXL?dIynx&>rq;h*58Y_B843t#~zjJ_2KoegZ)(%gAuOX zt%Ill2-K-A{S5h1}o|9ez z>3;iVFg(E^&x(P77r)d!i0ZNoyMPaYlxYUYSZEfh&K4MT8^E7H{r|+Zcg1pYsup|4(xKB(7^@9 z2)!H35eDxvMt9i;b9BL#+K*{%VF&_nLgW>WyridV8Tt zy^YWxje18I4Bhcj^9S^u;Qi7BQVLf0zQIGd3mtib*ow!=umN+BU65({1- z6v3Vjp-3r(kJV-HvG#WOSib;1=9ddap-Q1>`8xX=w+|^%4h9Z4OSr*EsmbFwu9(yB zO2#MDFC)2Zx$)N^WmZhW00(Ig=W;-HHm{l^$z$6W8V91TT8C;exBGe1G@E}@nrZg0=X)^C);WiQ6eo@Th?RP=+hHn`N zf9#KZ6+9PAKW71bqAcHl@JFPqR2u;KfaIrRsgVpuVE}()*o7}Y+m&4?$)P++p5r!- zOwIFF_&MWCzPBRFUTNcyn0kQZmB+k9ht zu=$Ry=p^cOt8%}^Uq?8w1I}jtMv`wsNDh=r@~p8)4&@8g{ycD6@ijtq3}Jtzs7&J7 z{VZPkxlU9j)6W=P1C=XVS44d>8Rf!XLIMgwNmT-WdFg+V^6;7Vx;Rfl;KqQb zWznTb_Pdc>>JH#WmLG+{S!CPNe(lbd(qJEvGzL677RIShEDsGYFXM#A9-=<7r%`x# zFUN5r+2NDtmznubAO1qZ`=Az49)pw>yoe`O^z|vfBqG@%d18xQ;ZuBQw@4aGw!yp! zpW=n+Q?%>PF>Q|8G<`_HMbwMEH-NVyIkXP8Im!M~Brk9W_epWc(w$8j7SUe?4~4Jd>tZNO#TVg(}_^+u9!(G zvS}G*I*&YC5PoCfXWDQ^NuN-CTQQ1m3l#rrCn&SfQl(1 zoL3>zBH}DLumiUgY#Q$lp8L@LO;oN=<|Em^A(UZE`DCB9oBYC97J%~OCNF+h#3xd{ zQg#5Y0w;yyo$AJA;L5Q*z^>-?4A#NE-B$*#+&s1sbAh#|c-?xNE2r;V*7q?Nvu|vV z@`NSpVadw=E4Xs>p*sGbY(LEU?pLiFzNoroCO>7>oKymOmjveTnne$ z;`JLk2?_Suzz6$5yk8T1I3B=>l9)C`RD1=zPz~reeH$?QaqJf1sTlL}irFAbiRsh1 zllPwrMa)NT2AfCs^1fsT{2pdm4A{ZU_A`T*w;L&|8DW*#@Kf}9_)xARgy4_Z_8jj` z>dhx0uaWP=RqrtD&jxT5i>c^IczuixEmM-0W^0)uJ|VUp5^C^3RS}^ zM3|j)OufR(5k97Rms3CCBe4Fqbmbdf2CKB{+&H+)5A#m-nkeS*W_JIrYZ0pdgVwS#Oi zuMkd{e&7$_6_)j|{ke;rtM2>pslFeTMs>s=Ad3m@Jg)DZR?mTl(0C}UDJgZ8(4h(s=s~()nn5~Ro7Ufpn~}nH(y&J*dnH^|ej1{4YrsXXEu`a+ ztLU)R_ZEX%hewKQ-!q`rOWC*IPXo1%5-hHjFxC32&)C#D6vk05!L~WFZ~LI736;-) zS}*xCsCD{Ko%454>non=Uab$$usb7zScHy_K5*xWY07}Bndy#Xg^rJu-7ev(b*BmO z;kX}v?vD}(*U|D;xQ^*=j*Y~fFf}#wvpIVBwD}~)p0u7eb@%J1L3hXCWBoq(*hs4~ zBXo><%GdlwrxC_aOheZ*4NbdbXlV7crJ>=uuA$-i_tDUdqE*Z2aPbz<)t7VNU@iGE5CLjZ9rppZBL2a_K0X}MPhe|sG_^?k_=%`ff23;%D9@447 z;%hH2rCNu!%TzIy1ohBrs?KO1cuB6M(+Pf~a-+TtztL{77pQotb*n*lgJg6Y(bI!? zla}Uk=GriNX<9^Yzp2%!&gvea1EIND3m`Q2-XGkYy6;>Tnv1Z|+{s2OH20?Ll@-yA92K_*~baxyI*=(A>{yEfe#SLvxIf3k*X3UfgA9uH=dYQ4{y|e81>-iAT+Q+6)@~ z+m{wJn)Y-LL8Bi%4XXO#Kj=ZD+P{FF9`dvvk2?)gQ0vq3VV;Q1zuo)jwxd zzqIB*5|1i)^1H>Oust4ydx%H9{lxc)N3DP2e>)y^=RKW7t^4)2#iM2i@J=%%B?rnR zIe?Hns}#whv3f*morov0h*SlVm**p83eQ+R$;qNrUMCCBdI`e*HU5$VNEtmgcAQ8! z6qE4$P1+#c1r>&JB54%E38xS_pvR|181box5r4Rw_|#Sj9}D1}q-=Ho9})3KNEy9* z^Kn9Z!-6fF;tP^vQ!1SHbe|QQ`kd;7TUl%hN?Zi7DUrpd3V4o--vKwF3`MfPBA__S zp;>=xz;k%fNJ*aGs>i3~S!U--*;c4XEZ9p7Z*>Md-z?lG`^%y+;jz=uK7D(u@bIsp zDWN1*vP+T!Ym)KixM`X)ek2MvCnm|hkqPX45rrEPl*p2&d9lmuITG57irPf}T@edj z&k-T=W1i!Da;Qu!Y66wYA_hjt>Os0@EM_6A$_;$biRAm-qC9k(GN6hz_^~?mK8PH= zB*Ni5NRmUb09F}uN3WJ^pc(4a3{ay2yGcDUZ;q&WPc&% zDZwIdF*u`R10T$U(3&2w@X0Lh)ep&m4feQ~%ZP8aYgeT1XTYcYav&jwwPQ9PX{*r5l? zgr!fyig?~r;1|({YTy}I6z4wKJv8Uyq;S{3p2A%|T>CPN1h!T{xT_Bfcl9cXY3GTG zufXY(i>*M{Y_F%ujB%aCVGWY9dIv)?uoDZTPt89%l&pY!4;^X%Zx!3VLU*pE&H6kV1h-nxn87XB zGC9b4Ho|zuT&FlH`ar0LG{50G!9F_Ob<+3V1}{T0973*L!d$26md`|8qDA@C&0$~# z?Mm1^u-o*ZsLQmEx=aDwr2h1mxm*Ar2KWOz>1ICLaRLAblud_d1hJfAxY2pNlJj>N zXyjus4BbbHF{DEcAQ4Ca@0+R99Gs)W#vg7Q&|xeCI;;Vp1Kdim?}Qn^iZP%=jUC|7 zDY1U}WY`6(*87v=S5N$k8qN%TKgU4d-)ErXa}0F+zbX<2w%|L)uSQz;NTp#H0GfYy zg$2!j+<@laP+>yzyNF-C$8nrG@y@g(U?8rQwU*<|xE9+6Fu`c+^dnYVB}QAHKVoeI zNQ!GQYHTs6@s?4jz@Wz8A2H%uH~i8hpB2~o&QxM9L+3>aqHdd$a^E7tC#a>FiR6`T zEd!Be*uSJcba$?in+kUjB>3xZ+tQVP@h0Ah@abfbF;xg)>c?P9tWfRo(sf{HKwh35 zkmpk`cIAag8GjB6pCU-`okB|BMeS!I*($aj3Pj0@PZ6HA4u}5k!~PBak^_|5>tsXF7 zwzt+_#7*rPe6TOT33o>mM9ZL$ta=)wX;@P_$iT1!QSh`a<1Xl>NX$EelSg zYE!Xt4}sH!Ad^F_+kb*;9~EUt=C37X&KgNsz6mL}m9yi}?fWVHYec+N@*G~YQo{4s z=(m9*xirtbb2YR-d%7Ug2A(F+8D_J9XR3UPTc3|A{ zb&H-2;4?|>d4;+V*tj!uDL=PL4twsrQef3P?Z2)-F@!Fh>HFniDC3 zha|a*(o$Ychb>o88mRYD8NyqHn_|>K6Pu?n=`uWC#WmsYxy%Ws{`;NuZ#YO^S-wfa z?FjEtcR;!2o77`hB?vT0<)c!4Hk?RRMNdM`_po_6Y&Wjny-1nRXTuSq-uGAi8kOan z)YVrd2)LIck<3zT@=~`tF`OV;9>QC+{+dJ6FAoKp%t`Lexv9Nj>gAas38Mb;j-KSP z2Bhv-vK{5wE`;v^Pi3cw-xV>Dlslb>p@J00r?^R`WQR_mU=|;+ZJi?2z zeR$Mwnti`v8+F3XPSMjWggdFxAdeBM`?ojnp^Fi2Lv3-kcc}cNGx%irC!OUDj*9*g z{zR(-dP(x7NSY-Sn4 zrxDqS@RDq#xJLgsmF+B~Jd#g&qO2@#g1>kPuXH0kH6OIj)MBA%YN=2(wM;0Qdb?0G zb%9XyNI6)Fk5sacb?jpk`-riRR`#)veH>;V91kCEp5x{=KT^zdoMUp+BUiFbQY-UN zv#a0pU4m7JV}*)Xp`(>jUNfW|nhJXT5l;(#;9gF4w~>kMui82D!eD($`#%KwYC3=#|XNfl8uQ zV~bg1udv4E>E$YOq1=3{+)r7#&Fi6DnO?4@FO-{Qm7BuK5mw(=z1%(l%1yA!UCzp7 z{RPV9>*cchLAl{pxpVb){|x1_E8X1OW|vUu<}SYs7Is%IEzs;b$9M&Qte$fY=Au%KeH->7#nN zmj^+)C#-U-Sh>@%qPv26xexQ8-2GO$U$S!Y3sCM>y`1xWD0hcd?gmz_&p)7?PcL`b z1yD}3%3Y(^$I4x%m%DK=lq<2yU8L8y3Ca!7%PqSQ%AIGG>&?pD$;u@jW96P50_AwC z+|kDv{aCpJdbu4#psh%!v2Q2Xw{`kkg%`tH>-D!JW%R?(HiYb_546+lb(OvDw7vcud;Op6^_OUA7k$09lfX3%%7ka=vt?(_(ArKv z>gLp|M<$3if&I9O{`fQYV;%kRJo;lk`*9BaaT5D+|8Lx!nkX`SgD_pfz%PCcuITuG z_fxa-)K&C%{IUA4B6elOIRg{KW`BXVR*dkmlw&@3 zBgOT*6>esgDy|Pl!qXbVbwjf2{uQ)?B}^-mD>k3a4vzt$5yZ(45B^Up9MWP zE&V~!^PzJRM3rWp1w9|P=sCVHjh^@QM9&);JwIEa({u1|fS&%dq37*Oeo*u*>6ajC zV&+-U^NM9AJ-@spjh_9M^+3<#4+1?`FW2e0qXOvp*@I_6Pxs;<6g~F~38Mb}hO?k2 zdBCLSABU&WbN>T9(6jLYpr?PCPS0hJ06nW7I175lfoeSOFz8py#2GNzYsJ)9Be2>Vcjwhk%~0B|1IF zuL63m51j=)%YXfYqUVfW38D^`&PIO*O?u`GP1m2np7duB=vfug>G@?j)1Se!pl9*D zKPYHxW`d~8 z#IvC1#Dyk3?-`s%&tVIDpr>;o&~xA-ou1MPpyxODodrEBfAxc+=N+yDQ7=PhLC+KS zn)DoeK^i?jxVHy-zJ4#zbL)LNJrm1-o*VBy3woCR@&`rFe$E6@Kb&$F^n7K$NzWbU zrP1^0`908c*?gd9Xn{`8zds1{oIn38=y`bF4~m}kjs#I3^`8Yjm)v90b6H**J#W6J z2YQab2k1Hc*E&6KeE{hBqkGPRp6l-ZLDBO*K0(y+zO$g`m|vOnylhY!JmW+U;Wd^FDCxJzc7b*e~Pc+OB4_1p(?L(R}zm_M)yC5^o~a>FBgwivi;9T z^!?8@EFP`AlKszRKPf%ecXgF%x-tnmLa`C8;?SHP+_di#&cvN^L`=3jHQhJ_f?@*QZ zXI+W^ToK*>wDtC%D=z0hm$UuP2lf5WBIZArU&;RGeLpEZUuf%4m3wAhiT_*{-T#EW z{pYgF`Ojr+|8s@D|M?{IpUbXf|MT9Tl%8B`hpHscxDx;QKy?2zrMLfl;Bx-+0k;3S zT;Km(#r)?3SF-=PG{?V9jfwZ&XwqSUv&Soe{VhSyPTf)vHi~n^!?Arn4b4t$^PeEKPf#IUFuMk zjOkYrkM51`fA;GgkM6x(JX*r`KkwJ~KObT7XvvlAf8P0%($jFULsfQ8yOMZxPjvs& z+B+WIbGdkQ58MB|Pv8H1n8l-eu4MnS;3uW$-ve304a zU01UIdD~A)&w=MVROLwamDuN<(fv844o?FOP|$OZej1w(kC&OgdB@HRlPrp7eb%qRDlh!FA%3x7Z7tu zIaolS=G;?2ZzX4C$Vw#7`nbRblt1n1Qp^4B-AEoeeYp*MuD$f29NJCV87VUKT3VN- zgkH^hjsUmr?NY<9u){zeBMCR|>!MFGEz^9Xtj z<8esIX2;BpWi4LCS{z4;%q1;uV=WFQ3I4sT#lLMe^l=^nk`fS3q;2*2zA%zz_q=Ux z^lmLn-yvv8N(+det%korxGv5{ z+54S!$X@H7gyf;0t-qv(hxGhjy1m+MW0e%2N99x7-JvCw2v?JeV(`}^d1%S{OKSXi z3k)`h!jiSxJRuFO`xAUo>|R%V74%u$i*>g$ZRuhgz{i!Fu1f*(f`)QGbnL)8=)05J za7K%5K>7JD-K|VpwKn=t_K<7oL)jx2(@{N&lzd`$ml}STjp`JV@ZD}Us;x?g+AIFu z#@$Np@kM0c56jlmlMD6>@~nM7w*f&OZ(e&r4c~;Y zfKO-dQRYud0pVW@_#)E!9`pV(?F;vF8&F1ReVKVC+Lylc9rE*tzJ{MueJ4_VGyBk2 zS!4ssg`E+7;j>YF|2dJpkF<#D`#C9T+ZEOKuO#6YyBMeUPXFinx))J>-+o5Z_nt*e z-;chE=*ur+`aXHBrf=ru^&PV)s_(d+z4ZMq>wnPq#6lZTKL3jK<;b_a^~H_x{(+5A zSe8y-S*+u;{JhwjRx}LRYvIPX0RZ#msq2xw3T}LvI>ucH2XTE?8^W!qr4AYDka!}| zokri!bHL9N9XNrW3{Yi8YK`X{5?d4DhHdmTt8nCd@O#U!pVWXA& zVZy@3Wb%g@3ma|Z4+|DH4k3ReU}0k#`6Cev8#9ocoJie;=(i$!z2{HiB`zG`#S^Xb z<*9hSJk#pT-b48m-U1&t+X~_R{zACaPp$-;xe(r8QwW#V6vCp0v_e>PB8?tv@&fs< z@PdsOE37Viy{FP;uZHD==)6MrLd?~z@1}3{-BQ(e{A51wK7{w9tSTf{bwXba61#<> zt9abR2SP?9p6*2SD@$g(HQ>Uvym+#8fjreVU!J+85I!CtoxK2`@B?S|;X=47Wn1wjwGgfvI`A3#?@0bB z@~>9^#arO2YhNM%UH*!#5U%>65T0);gsa*MVPSV6JRB~BhtC(nN7O>NjG!;kdarh#0;%-`5_^uR;fbaWk^Bla(SHVwEf z3csZ@X5uHc#2I`n{*}J*Ner(nYUzln$25;lAhr1dzF2nnsfo~MDRWVObhQKeE+T2# zV=gkbTa@uxDWJ5HIDOw?4mytE12mi?dDdc=4Jb>h=`gNE^0a5xM4i&;tEp3(;G#|` zi0kaYCHFDFV}X+BHPq%s%wJxWERK zuBwQ>!#z=bzZgeJRxhCX){v4Ts-yaDB?-T-W}H51_>c50TR`>wr~C5yE?E$#?_AQ- zlUK*-n;F&j=Bi%$ni=(!1x(-N!T&+uv-530sR^>aoH-t+ukPO`#`ATl%l5N;=u1xYCMQ6jkZAA<2?p|q(JLev$sZ=KkYFNzn7u-R znfzh#3JDhSM}k*Kpr}NzkdW9bo-nqzFSc3XhE6(B zuF?dB8_ojSfrGr*mbsdQq)-VxzJj>yhC&WLUK#P#^sKGy<}DZDs^rNR;i_9F+X~_N z!-a79!9sZcn?kt!WFcIoFpqrvU?B`2ErhG83*q6Nh4A>vLKr@Ak%Q|pCX@dzpRC=b z3!V>%OD#(=kh>H}a~BAB2NF-U^77O)B+pEXCjm#3c<@{@X?jl~TwY%YR~;yXhYuCP zK)!;?6&f1wdV{HTTMkPv;ELl6FVPwK%Y6$S>|^@6mWRW2@dFUBpMNAK_5^aiu_lrxRTHUV3=ng9U3)*C#wMKU7m zt(f@$!qq6NPO$rVILF^(MiAYf*po~5547;|c5ZZkqR06&y9Dgq%Hy3p{x`y&_Yf}m z5J^koKe@-_ugMbTDi=N9HKvQ7M4OUn03=XLd7^ZhKGhjiiUz zxXRB7Qi;uN74UiGBuNvyRao|S16zMiGV%5*xT&9keZ{owL+!v2VqkN%`5yEMLw6!+ z3X-2QAUwl60I3zoUgtT3Wb;HM`gaPr31!vuVz+tq=Cor48G5A{d!?A-Qjl0-CXVGptvz1+(k$Q!0#;o3 zjLZJ5d!*(s#T?)sK+IIIH+U|%@R_iQ$3a1wLT?`R*pkb}+jqh8Mct|zE~3U5UM=7$ z+Ib?*t-_26Zl_Z!i7Nh520g7iX%f)T>GAuJA0k;W~)34M;tkgZ351hT(J&}Gyk=(LO zs@-tdpQ4%td{PJfj)745VK?nV|6X02MQwQdgt(Xo{7L+AHFyW{B|`;#s&Gr`4B+lhXEb5YMFEG2ZxnD2 zl88UZblK0svhDQSm>!$U-U7=$HUQAWe{5y`qZ;8uLe@zEHwjs7D9~n%x)2pf9=|fi zsC$khbRakJxQY*)Hqs_dlLb7Pn0c9<9faf;q)fpchGoBqbtRvr6Lo{yr=wd0d>Tov ztx9v6cBiznrC&- zvcC(TCFA&PuW`JtrztWZgYDC=sM8_AURm&aW~O4vR^XmQh$$1&^znWD@7egi`uE!S z*6v3_TA$Un5ebbRmT;Vrvk$M;D(R2$P` z$M^aFY0F_u$Na!XmbuDn z!)T}#WY10kw`4a9xLx6CS}@{lpC;FGzJcCiB(@ph2KpU%IbRhfT}5xTU_Svjy+e0! z=-IfxWrsL*BV3EblP34|+09z~g1)uWb_$ZoB_o4?`*YqLx?^#{b6Sw6UeAkFJ5g2> zFRG@ZJG1@Sd$w@UH+5KCsN|r}JR<3XKtC*`2Sd6tI<8 zqqAJ~+@$~Nb**x4h;F{5l(AdVTBC*w2 zlW+9pLeR-anaTGKOmg={_g&d+<#> zPHJ|h8QpdP2T|5;dLxjin&9T^NFbLv1CI?=hV#5+U|&v4ssf+HUVI@)!+HBfD4t_y zm)ppCkb@u3K=$2m(-AU}5Y=_XBYDZ-!WDd0g{yoI{N*1E0EDVYCXJu#RW%WS;+#k! zUTinQ&F_!}E^g-n-z9LRwSGaq!{EZ{4zDeA2c4iq>}S2IehmQJm}sDX9|iz!`kvbJ z1y|M~+9_UaH^a>Y=Y$_GHahU$^`}550P8!z5ddKMjdVFu$xlj0Vuu-SzTN-;ZVfc_ z8xJ}mpv6@a0LV~@)>i^x0L-!4cfd_1vP2RqjRGEyTLVgh*Z@^OhbuXM*vOUcXym1I zL0)Ze;cSO@M4-VeHcaMl2Nwt%Iq?+ak}A2<9i>#$I}AMOUs~XdSv)h@f$LapNv+AH zykr;T`$+%2iCpQ)*<5KY!#ri+vEAXdh3}z^)~lcafTE&UDNSqdWilpnrL_%F87bRw zvy)3*(m4t?zNRgudC4BWF3$fII`C*-tsn&@I}(FN9@_9e@ziKOa4JDOHCsqJ95p|cj0HTJ7b}dRhgDVON;}RM&xllMf}4-BF9zIVAoUtK zT*Z}koO3_It?y_60C=9{N>4X%rQL73J)yrED5pzs(;w*1`&uPtxcL=2bbLju5-0Ti z+(ZkOZ6dyVeFr_@uzWKBz$riX1Xrp~h8unf00`YhtE4TIx(A0AuuDI=gyr-@oA?+f zp7wLv?=R(9Y>*!21E-S3hS@04kRT)-5KqlUNtF)xG3z=N)Ew!$DYU9vRh_tnD?QW5 zm8zxgVWAU*3r+Ep6j)wInBwD{c*f7IS6O49(n4RyrM*Y@^MZVq%8RNQZhnn^lJkJr zkca{egGiO)nb~~cOfsJot}}c>{;*~HOV=5{fG_%yY|cf7R%CC4;$XU2v=Kaq+}xK5!y|>0Zm*YvHD6>E4y!NZWgWwD%CJ_q_w?OCYFua})tU&7)=7qkr^q3%eu69Qo?PS!?IY{ZQw?EL=_!9{M=30?q*iuV zJmuGW_;(^r;6$<$eq2L($Old)xRPo)@ziWr(q1|Oo@Y--n2^1(=;=@?V56z@bR!*Y zF#IIDq@&HV+==%`E()A+!_G606Hg@affIwsKnt8o7Ls=8ZSqNnqHPwB;#EI;grafv zAQr!Q)z91O;0ANIs%Evu1cDfQ+-mNzzbbjsvigNzq;P9TpvTv2CZ0|r`4TL}F z@jVGrADM7W=c&ux30SRxZ~|Al!|(K_>k-!JU1Z?J0CTMIcol%+T%P*Z%@KSuSGuFY z=}nK+c4{^W?oRKWhL|diycjTrQdL#u#SZh@g{<@-GFOOTlVh>Ht24$_XX3?xIaJ-P zs#(!jgi!kM&oe^H=?X+8jaIR?dLs%OP@A;;z=oenuKB` z222R|L-r;p8jQ?BT++bs4TW1+2kjkj(^+Z|!;v9?a6gwckoZOy9*87{t1)Q7*k!MP z;&wLT(@6~el*Qop4O$GIkMKp5wS&dr-_db=XIu#0VEB;`+yOT|LYg60p@poz^TqZ^ zeI~eh0j-ZSK;NB_@Vi70zsn-w_rcJ}NcbJh!Y`}B3^!XD_a_a|#~GpTP8xjOYqY@Y zS*r)#qIIDIATHq6fY^Zh3FsYg-=%)$6!9~Mdj{NSCpVIXnu!?L$#akL_Tn85GS6V%?C~=yONGY+H8z(vv?SF8XP_xO6!gbcRik0`#*_y z#|>J%+fQy1wW`>7N5Wj{C(JNw;KtvOz(cHyu7_xRdtHxj3u5D&_s8Pfs^0PK6E?4? zg&S`o)w}wPYt#FTYxn4J?G7!j-4hxRiEHK_aqSX_#IZX_99ziZ*it=?Eseyn<)P}H zaqQz>aqOMT#<5RKY&y5*q3}8_c!d*V!`4GRBGsKFjKy5@eMPQQv&lf^lMXZK4t-)~ z(iM+@qX9A;AkoX_BCA+?oeNjP4LLEfEB5&kfavoj&GXXex$@6WP(B|Q`)EqzzL@8K zk!-1(*R%Zdth`dSFZNNCr^a=veLc_8&GU9)w5jq5-;wAyu5atK^gz6E*0S*seu=_8wGrofLB|2wMxL< z0=}T!W+7cY5Si_gPCogME>#=u7$g`qqo+b7d-)KIxS+08Ek_rdTGY97l z0WrV-MxPJiaWldl{AcI2t!0E;l=+qvAlQ}SCwLr0Vyn40d5&zJ?KL5>(j30gg*$n1 zr->K8gf9Ep;>GjjneR}0Q@1M%Um%?#J=$rYJ$lxPaHW9TQQ)MJp10qutTm^ATY~0K z*xaYbgCNHh`R`q-a^RN+(5pZFg7XZ8OCMcb7@TKW0pjitwT~|{0RYNZTNnitG$oN1 zf^)3IHA0(Z`u#);`aJLoz`jqz9=zPy$M4TD}mvHbBBtCufD*jgCO zwLT4+EidV4Im-rYNVaU!(d)Bpz{=1YDEiiwo+8pX!q%!>D`>V9>DY&~4lmQOOQIdV zH>SgLiyqQCoUcRYYR%^A(3_&o&Y;aMUh4J~#Wp)h$BrefAlZ_kV~1tgfQeyKiCE<3 zfM&}e9gw5}Ogf-zLIlt~fdE{q2%v3(256kX0N+i}0N+Fb-%`M>o)zT&>42{_K)nvw z5e4j|fPxjvL9->O13uRPTXn!cqJWQB3oAXK+446X@Qwy}LkIjO3ivGr%q@BdG+TbH z12$`bjXIz-3Rq78i;6UUIqL$FEtBrKq&lcY^Q&MU~VS0qM+rC z@yyQ#bH`~k-x?oJbIbT1G_8~-84o(mHREGxJ`qFH8lgEhMnUic-gSnX+zw{pbtUdWL`@1kM%J2JevHX;Aec4~(9kKSe^W7Nx`^z}W&v8er z{k=4BXz!G;Oy0a24^l|6OG{dlmDyp{r>0B5Maa>9L|WSZ`<3H5!f7S7CNAd4a{H^irub}uBbi7x? zm+SboQG5x-7XScOMDfch{vjQIzlL9;<8O`PZ;Q0QGK%+5Jg4JxH2gFje{B?h9mUTD z02D>>4^e!&j<;#}6diAl;w=&Vmqzh!eeO%+(RX8QKSz7dT5X@it zxQERg2kF?Pv1}4%(y?7*B9pN0G4wX9c%X>DBa^W2$7tAZ$JjtWBwLP;(Xa={*nov$ z4~?O7s-;EC$P92LXtwOuVO1K;ufzTog?&O{+!I9)5!j=k+47+ddv^@G;cw}%-;Igf z@K?3g$h7ul9q>Hq36d>d9k5}H4VW1~q=5OJ$5&M4nnAPW86EVb26{vXt%!mOHPE9^ zGtd$pbn6&43C`0&XiQ`h%#UG{;MMLR;5-j{*d+KS9hyCc&D6B11q$ddl6{14AIg3$FMtZ(a~yV{0}1kILHI^d87 z*rx+_MFG1hVDXA4K(nP*2Lv?0CpzH2qW~WTrp5a2@6v2QIr6I>>y^>ee^;eZ{~aVn3@=9gw~r(|`y%t- zzj?o}^~&He%!4mVV(XPrJ=QCu`kZsWHYz&j`OT=<$=H95>TAxOofkXjp8a~vWbyV< zbYe3iFEZyg=jjuhn@07VbIbhTp(Ae*H)FHJR;l#m>pzcrAwCu91{q z*cF+0)wy(j{}|bGGW*Yw@%;WUvIjp4TtAYGeZA6y+vvWzCB<;FjEtSnsu|JwY?Rw9A(q>+SM~Yq zfebRAori*!y%~{lvyW84A=&b72Bi%Io%W-Q_AfKyXg6D4Ak}!bRav|l+WauX2GA$2 z$XqH7(d{Erwj@Ivy6y}XG@s1ShVIIYNYH$UwLCT=7;EQF9lKD&x^%1~ighw- zQp&W9cxlIF^tpx^kP(%(UqTqcQwe#_@Y#cwY`^3yO6>qhk4uXZ)T+5gC_7_$3YR z>45t8;MbnsC%4uV+Z-6^u89Y8S`TKJ@<+}$UjQg7p;Fwj|}n;(zQkFhIC5( z{M-ojeRFl{h3P#Ott->DMeBX(Y@pwhPG+0);}=bA(RpjSHdq&EWl_2|SZ7CR8 zN7ESoP@0CXkK*^F+2WmAwT}9Np;A88Q6EK6DgPv>t@9%bYy%2%npSV>_?I>Oi#lG4 z;y2S)De6&*+MuJJ*0`?GQIAErJ|5|7%(DJLioZ+8FVgUNI^G$@&rQ>p#W8p235vf_ z$7gByt9AUyD1H>h=K}zi#V@OyE&X)7LBn^aYWN>gBlzZ2g3pWJ)>uRFCsQ^2!BmFd zuj9Xp;&)NJBcA`VxMlrEsWzaD$82W!yJk8wyaCdg;S*hu%nX}O)0yEfNI}Ohy3~-T zSyiL+K^UD64v3o%4zK}br#F5+cv~u)4-R1SK~kg%$IJ&w!Xv+6^FjRk-s^d1DsAoI zW=lW4|Atf>FeBO0F-+HQm<<>;{f3dHB;Z_Cxkj=MAEvLvhcV1?9dj^>Im9pvDTel> zZkP=yM%I&!NS?KD0F`G^CzWTGRNAz4ci!jJEbnvt^>**Du4*6jeNPE^W)CQD28<|NJ(bKeM-IGE! z8`(iMd;J@#*~g?{)21#pB&e#|_wSo~lQsQh%ZJIa`u!`}29!rPGX0P|>sQJ2TeMrB zYf_cx?l;i-y`SULpn>X>$oNcPe41JzP~0aepX&%XSRUn* zK@vEP&wZESGdRkpv0p5o_I@^?TpQ)Hryu3hee(rXx%pnIPw_^|XDiJax|Hzw<^<*Q z839j^;qyL8_d4TbGIroyPe1DAUbEcf~L5xp* z3k1rojE{?e-z|&snMo4HXnba0hR>8JA6p!s;iQJ-D4z>SluwzfNmWKIq52dsJ_l&d zP>%4~-az>rO|k(cHHObllJG(qlkaKtCU4Z-NadN7u761d%+g{f6lIC~q83CSLu$1nSlQL`rsS=u*S~U|e1y z2_BJgS+Vqp{$NXa`0#XmEOKUj!M-@qvPA7m7_J{bS}3w!=a z4BC{>yXhH`O5q2w&pV~59eq4sMan%bX9!ygx=% zf2v7U7T#k3z22we@g;imimmimO&k!inoyw4gzQbLS0QOIpS9nGTlj!#S|Cro2H_?Y z2+e}!6$Stzudt3r^0S#JtB%KC@_}b{v5 zyG9kyEd9i0AT!P>RU-Mr5T4^I|Hhq`FV8&92fi_B?}wgL{&X}MxNx_CS6f3n=nIVD zbl(0I+%(q!zI-t5=Y}B~RTJBrR%1VxX1B z1+BaoY(@5fCyb;SVKd1V@C*SzVioXe`f^?-no+XVJvjdTzmUDFLuFkCJ>Lurd}l&x z1;YE0c)C-N%|EbL7K4;YK#-i(`La2{i~dF)H}Ne8o!NUxvoX(y-vVupuN!WGHsR~W zIdEWd-5fa3QP;?e6`d}7y{7@$FTnEYs;Y+OvGYllLtUz>OnW%SUYad`O|St2EdL9g z;&|D`$Mj+uyQriWH?xb~?DsQvahP6Qve1h&^kO%=xJWPl%q~=VQO+*<8_31|>>`z3 z%wQK+(Tid1;s$!rWTqE0=*3QUG0#A!RMIRmE|miv9cr_so`TAF(oJdBJ~A-Bpc!wn zj9Dz>4zql9GGXa>(RLM%fd87=K3BaLMoWf>z##xa_4#zZsf zS;luJ8&JNa89tWrCCk`GGTx^d#tW9*^O9Agh$tUYA(u!q~oEvarJ zeH;^K593J22Q;J69BU63iH;CFMKS=*_>C#n9$qCGXIe?dN>i*oJVG*d(TwSF z_HYx)_-~q#5N8ibB;!?@@o!_SJsdC+d)Uyb+XHv|;!kpo00{E56tfM42gaRuTB*2) z+|ulrq8Qv4=1Xg*v?{2zLk*v%6M&xhkqQ3+-r57-Y;jp_z~D|s(yUvpr2j31bS6pk z(1U?zjkglYyIVTc9`DceiGTM;@V{*7bH0P5L?l^}WJeNbMW&~1?-|HE2O`N~RhOs@ zz2--;=OZAzH~zE}dyCt{;oa=?2<6EBWWeL?62Q*wT+lp@onc^ktqYR5OA(Si)dD{6 z!0pQK|D6mtDS2FZjeCM%_f&gs5ZlIjZVZ~}9-$tZ*P(Jhk~sr{`GN3I$+exs$>T_I zx0RL5?s49RyXWx)@~q4*2$YFWv32S*be%eF&ehR5k@9akCu-`1WKMLU69UEYbe9^+ zrxB(y{vd-PNS?Ku6nXz?HcP5~p+i-Ey)PMDkzViryHC9y>+Gdh(Z2sHy&5|pP};p&>GcLFvi2#a*KfCUsLG1H{|mifnMmJ7VVZS9U*gQ` zJXT)a?y_HUKjL);mBM{Q#V?79elF+)nu^zSK>C|v8DOW)3-}CCax1kw7bvfBXHq4v z5!=SPZ%4D}n`L=8&~mV}BzPTkRucvN9CiV!;I*29HE}(J<-Y&`;Od?_&H}&yivGbc zh1*m$T#e*eFSbLVyzXJzu4LMNd{tE2d-hUoSF}@Y3rXp%Yr53XtRK^M4k?mZ%(T7v zmmR8-v?m$-@5b*FKcej&MB9FQ`_y(v8`HKlUfX;2MYK(!+72OBIwPF_p9uMzK83^q z6bNN{Qey8*6{~?-eRvyL2e(0>%ylzeA7#4UH#VxPc@Nb!rH$%3fRw)9)1`*EAJaA5 z3V~AXVY;4{J5=TGb;;mA({t^Q=((Ke`LFsu^?bIKj`(L|w6sxM2yl`Ul>6PoshnfP z*0G+s+Ms8L%7=$aPCtj8OxuZl4s%#u#-{7>%2uP614L2;oq_N!vi>7$d$owk_#~4t zZA?_g&+4d*RV`G;ASs>h?ovZ@e@w==Ns;w#CgU5MJ5=T2-N~0bf9HR#=fib<>N%;U zm!AIm|8qUxX@)@g;K?{Wt4Bxmd~7$>b4@eVvzU~wDY~4Vw~`{+tC^npQirMx-}S%N zGoOj6+_0NS7j#Gyg1T&%exR~Ff~27*et`POR-9jvVVzj+caMSvHB31;p;~Mm>rM}6 zGKpY;KRnclZ_o<3leFXsf%tAb(L3Ti_X7lq_X)aVQI6zk?~IB{G=CSBXfb6o>sC_o zk56`~p}T%eqHI!RKoOJZ+Fx|2O3TiOME@&&;I3Z!?7I}vCvYjM&#&wLf7R#SOAsh4 zS4H$G9~sqW;#X9kDU{8usifq_CoZSYKvLxUCzw9TxIJJ`>N9?quFuGW-&1)qj~+PaC;Fs@M>8P~ejiSC;u~1LyWi1+dh*c&@tx>n$};OB z1j@X}sX%2&p0+$ADp1l+D$pQGXVzd+a>c4HHFRem0v-I`GwkRAB+oi~fegh}+WEhm zI@F^Fln-l@LC^Qq_Vc)fZr08E2e1LLS{G>HjWIt9k7UA6}>o~%7 zsO10})9N0GvYL=RP@Kf$xwcRT0DzbBG6@VJ=}9Y+p0@G0mCtJA?FWj+^0^w% zm}>VxAuEXN!Qv!@Ia}y6>iFA}INB)z&S^(kP2o}TNxYPo#!t$#A~BGN#1pMZ3}hmC zP9hQ;T9N3_6y$M9ytqBci{G^J;`U5ruNL6E23~q@0+JHx0fp`ALfd>fITMM2241>7 zb3VQ`vtd4VWGeHqklC1r*JifzI4=|7T9j3R?1xsHv;E<*^Z@E(e9Q4{KR>3$J&1iU zNw9YpCkps!n}A#6jx34WZyue=4s;jSS?SLAoHT^z*aT^HrmMW!eJvcF3wUXbRlpZW z|6J0~ko4>Xlyw1#6`AxiL}>!1W$EWz=$3SHh#84{QS|&RGNpgfA8jAu79_S0EJ{Ln z|B}$~JG#^*p%)9f)VTaMn!jsF=wC{Qx+L^Z?VBB}zV5jClucc6&!Z#pY-X$vYelk0 z$ySxRnq*M!_sm9HcegA)_0I3MXQGzJ8p(Zs$fe}o0zveEh8efDdh7^Spul&tQJ^&u z8S0RM%v3YuzcJJ58LS)(CIcx4$?HpK)0+(3;# z5HccpYJb7dMqi?BcVWeacL|cKTA4K%02gk8zQG*yO&4$|H|N6It7G>^)EZIQ1v5uv4I{vQXBJrKL>rYWA{Ix??$9nte@NgmP3>E!=|SIR*~;T%_>kEba81*z-#53M}hqCd4M^=3IcAJ838Vf?e^P z4KfMtzF(wk81{hLx4e?M(VB|J)gK=M=3`{~H3 zT6+=Mcds7c@Fsc(hJ*U~G`J(gk>#knPk-u^JJ&b!zU`i>q#VuHQ}#%OWx0;6~Ek2V2)rkpxl z4~1%&PwMdYhrT(+A1OM=5L?#hU0?_mN18OmHff+untr5LCcRg&JoPqAq+1J&q+bh+ zv}3e(4*G5#r{>h-Iw%BSem&>Cl@uqLQ*v`I;3g>4!o2;^_pC8DrwzJVa=lYv-tL?V zTm^*-te)JQUCc=x7ngj@}3FZ+J#Cly7FzK=K@u zU~h1*L-Jyy1E0=1rdIK?Fs?JVxys;P4tHb1)Ly4esgC zw{~zhQfrBC2_eIw@C3nr%6%gpN~Z;U5=pKeTN9xh=*M^u<$7-^hR6fo|m6eIqzg-KkhE$pzn!p9=8&od?w_fkK)9{mq4rW$776H zi!uLmeCgEVO9RR}KsRsNj4aH2zz(Q>7CwJ{B+U5e_akeOc(PlNXD&vwUV{J>Wg+oI z=a0o0ejtr8;pOyv7b#Wh&q*F&uPqs9-(PYAp2A_xg@qp>KduUNFPuUNEAi$!9USqnyWU8;($9QNqkVOb>$ z99yI*@%$wlDPrGW(v0M%V)S#^Bk=+!;`n&+B#Rg3_;_(+G+sD+#*3*WUgWZP(L6pj zUPz8{ol<|&w=qTlu!+OMxX#c}BLEV)F~Yb`d(?B1JiOQ(0mWrVbIkS%iNpy^;sjo7 z4(&3KYOGR!djMBJpj8-X^s^yFq3k{xC0QvRy z3L-`=mCkB!g03oje8rcY$P+Znn3Ve2eg|ID5l0ry#N0><&t6r?eums?*-SHjE6%!rMr6$h=&1pl>q8 z#{%8oHleJx4-LdC7GI6zp?|rGn%FOppEhI(&-(U}wApsU(R;v;l;^9@MOHz9kI+at&Y#_T;DJ4Nie zSbxy&^!8IL#C9tzJ4g?ssug73z^i@%*YNfx_e~DyOL9WraA(fJk`pdm5vR{wZ$>Il z;-_ye^xc!%&8xM}oP%o>-q0TYqfYyFHI}ybcGcmXXNdGOE{6cPoN6*lch!4S9WXCI z3X_^3^c5K5iWe9h-bCojH}&0wi8T=~8f(Ku+bA%SMhc8tD<;x_1N!Ewj+_bywJrzD zuW)$hs?b+#qMuI6sdA8^xu1i1jSlF`H#%}^ozN9dp=W8Mx4^KZ z5~%@XZ;C9GW7nV59!Z?mY;qiuhu$zI#wMk_PAS!159NQ6Ap!C2ol7buC>59;(mbof zUg5+6ho%-s20aIbIw~qA*|i*W)ev=l-(2aQ)K*@s=yckn_9*3>rQ190F`D7q zI~{nQS?gh3x|DC`?9~#nM4YO1$E!1 zKv%5;lYjFnD56(Ar1Dg$nATG7fIb$C`DU13OIpQ=QeG!#uc7y?o`d-{IImNJu@t0ytJcdtsF@?JQ-j0v zNZBQo)V=n!xcK=aWIa9ReAD|dAwS&K+XV2tTZC~j*={w{EWc~ePf-_cbCDLbHoYr zkGP=lwE%^SVHi_CadaH?rE@ulOD2V1+~SfSAi#+l@Te2!A9X=tp9>1zF5J!K9EO`$ zs;cVrrn_*xK;~d~s;ZhV&-@v$2J_@0#k^YKGBopIm65maTKfTMAp9l57m&RQmbFHE zNMmq&gk^43RUObbz~Qwzya_z^^I5ID>gUB) zBiwu!JwMjp&DSe)p>IecJ%lo+7RsEes(EroV$6BWUYmdqxXS(RA-r16*DEBOf}AnNv$D z807FKk@BQ+QhXFEu5%+vkku;sP2ohpD{N-{{TM(7(rrvfE|ypU9AUQ((0msE;=Bl(Z%fASxhCjHAx)Q8|| zx|Stt&duLa8_6ZN%7p{r!5kjV%ZpT3c@2;2;qz5=z0_tc`p#vqUi)pnJR~V!o|?qG z$jiJ~VO}6-Br!KqSu)loKVx=EW1Z4nW~V*gi6pW81gA7SPoDWpP8!YG50^|2|EkCO z%OyW-=A=QS28aES1LhxcLE+ynD4cfT)13Vz6{48G{_cLDI zuG5ORl&ZDwJEh^_0FN8V2p8W6L(@=d(--~QWve-{SfXe;uL?mvvEm0dT!hz0C zBu{(s>n1f@RmT1`nPw-U8J2_qdO(H0e?s6HrLYHwhn#|-6v-*s>{Y+v^p$5v0Ab6S zlMq~lHfLw}{n+*j;Z6Pg{i45L6~gEII1mV>LSN1LwqFAP))203>xy#3!1{lw>N>FZ zyYdQm_#(W+^2X3hDrNRL0Hx~Q?(CX!KScGk8AHXG3x)9UiY1j7p)JKjOWsj^5e{^< zUW7JRYq|faWcNE4q0O>n=p~hwvfNGoit0fR56||Cv$9V@0ATr_O!TW&_!#^>+H{fI zMi!Liepps+0)WGQ+`>L&qvzvFE)cfTudUz;F7Tb16Hh`;>_~7A=EM%@NyAlv?}s>` z?-(am!hn)IzL7YhqzYUYP@vdg2z)n8JUKk60#^qbEMh}uQXQ@pPZ|R!2hlXeBsS!d zwDl)}4FK7^1=j|?OJ0An)Bpf0F;r|Yb9fgQ_&$+ae;NQY;F7Air2Q@R*@v^wwGhXb z=D9k%1{&&G>fTH6jCijh7ryuFK2;KbI%)q_GQ^kWMuM?b$#vbHADhuETh zZRErTD;H=;aV9l7us;Qu0myBx%H*KKk9P#ZR`Ha>LLj2U-H8i{vj3AK=95%-phb4(OiF0VDYbS5Zo(xn<{| zqp>-V3muKDU@lD}%H{$yM=2YOx_V&|sm~X$2q z(sMS#7Wx@92Ts{=4C=?VbK8uxp2|i}>_{p;iR6^E4E`Gpe%mofj~3zRy8A(T{&~9@ zmOaY;GJ5_Nv`o{=gnu8jj6VkHp$Xxaf|m4Ske-y{!1dyZ2C?maSpES3AZRfkgP z<5378D`G1u;^g@aV%zLB53vf?x4j7faF3=}onqTl?jfAmo>?@26D!{2#P%U@)6s5H z%krZTj3kxr>L!ZmjhAnv?C0uqKct1HABA8DxqORWPB;ny@$8{rb*n0(UJz0PNf~ey zg3wx8NIe1p{Vn;iNTGCAD0BpZPysD;>L`|4N>ab?)Kdqt)Q3sxflfl{?!%C#hHB`g za2V3wG*{X@p5{ukXI;=T^DrcX7KHvti)0gw+es&0gq2%(KPE~bg`{SPXK=!W@ zZba$TtJAXm^lO5c1|=Tn@c0QU!nKt=uH|t(Dz9-D^YF7h;)U4){OlMfUYw2V9a#sT z3cBDswfx=_+5YB0t_wQr1?a49+2b%AqQ5UTp_Y0ccknHHU4|XPz)F8F@Efv^8gt?<+mBIU)Zs*>nfTPfIgtxiF>72ykfOH+1Dcml$W zLQ*vfD4FgQgd4N>@GVUU2f|6@Z?2^Y2M}(hXtmj92te*ur8Iv>aJnOtPS;A|8yD#}Ju8`RdM0%k=Z zYqI1F%xWwm@q%KN7>i1TU5R2Kvb)0hOsB?vO`BG+>BTnvRBN;b18qveB^zwTfUQPR zh=?-lDl7(*z$Q8W=Y7x2-V(h1KcDaOeSSVZWM}5gnRDLTd2i=Egl@7j#;6}`e98C7 zI6)xlk}jhCEsQT$H|P(20Qa8W2$=HkmwdPKGjqF$w$YLTZ8S{XPtU^(|5Cr@r}6 z^thNVqCPeNgPHXh@bapQ6lzmwg(WOAr-gXitc2q8&}1Bcxhy^KI{dSwE}I4L;B1kf}qf4O|t5#AZqJU9R8vv{U1l+zK+NK2ijpgVIs9#h<~@_ zKQzpktU3jS9%H3eg&xyO?;T>nf8ri3XBScHEePcrD`LUfNbEZ#zgI9Iuhxh0XU%{R z_n4o#?(9<3#xNeE+%kYiqz|bEcAv4Bn5#!*rDt)J!Ay7?LN@{Af-j~DLU}D7xV!iy zZse*Uvz9bUzG~dtwknsX3-gFp-9%JZgFfLHe66~PXwDYd9&iVUR%GF)G%u+MO^o^L zXn<(07Gm#o|Gs98D7eSTYKcwSeC9@CsaazaB;TuoAh^`kHlnpQAuK$d`WYwT-d`H< z9OBR1ce=DcG+@%=)9IZ&K~rNhdl6@K_S+ za%mklApv}X#<6-=X(%(%zoF*jxcrCRB`)p094pLAR@WBF>O(}KpXf&i@RWPcJF>T< z0?(H|3b&7(0t$2IfW* z(}3qh@QGoTyk8FSxuHKEpZ^*f1)s&A{V(9N%f#o*{{KJmxog{L@cI0<)8ex$37Oi_U^K}>_d`oM;Z)nnc%2-G{+)%j=0oEb4p!) zrqKI4J>S8zaR?&?3hmPiN<~4T{d&zmBFv@Eb@>_3Ka{n_RzeRF`j-CDjiNxbs$5xH zoD0_zmxuyUtMZ7Sx&K9IJMp&X$#f5)r;_PQTWL}3Ke7?2=yOFX`kbhfh<~3)m+gDp z|Hn0}+_qAa)tf8|?IZqu?#x<3_Y(DNX!1o!g7sCs&Pwe0gzoX2Q0$etlAmw=Ai22Z zs}`o{ls3C_td718(VgK^-8oq<_3j*7XpHRLnJMo*iYeuN`o))EwFW~PT2qkJB;TJ? zxJcfslP!yk|44SHLW5*lJ3xQymBxQ0y9-l0v-c9QU8cL`_F$SU?j|jg@t>UCPFh6c zKSg@6Q*I9y$ljCU>anusVI+Gvlt<{WVn4Prm(T%atZpvw1F*nPS9Bsx+K3Z zWdC|yolVq5T}1sEM{>q?=#l0l=GjIY(kIhD+!|rh6hTq%?{v{mWmH~(l8ps@&~uTC z9t-|ONIJg~8oKO*?vh@Iv?491TspQJWL`!NFvTG6WGSRQmC^Pzh}^mC*8-5?YDPT=gWqKBmqX@`UT3 z_OI4I8>0FrsG^{Jq8`fi&k4CB^v{#S8K>1h8x+;m$eOtd+Nsa%=K80jrrIXBs|_`D zX$q>L6`+QGcN8@go`-T1j6EeXSGC_%g@{ng+^TJ zTt!`#3)FIW1hwo-pccpNLoBq-fOu-q@qGi`fg1P>S7vHE`O&ZLHMGmylS;g&(pIJA z?+z6c@1eo`-Q~5iIz5L3()Mu9h2O<{Eb$lC_zPZ>731`;d3J)dn3}xasuQ5U*LZBS zov=>Nr^cwdjZrCdS-qk)>Ks65JxjhZhBgiWIwuJ}1DiQ~rhhZ|WG?~u7#|;qfh266 zh6`Uv1dGc6OZkw`M77rHyzalU7Sw z+65b(poYH`x)S7>Hxib-?_LI)_d(hFh9t89EEn#nL!b||$=)~MV@-rEX;IYbPQrFz z6{S8x-_?Kp^9&Oxin=_Ps6}~_wJ2Ab=Bxo+riTeDv=CJrKt0_rpys6&;vYZ3x1O`0 z$@^R>2yOpi_Z39b2-nc8L^EFTLkH60HYrmGO-|Mi{k*xqkY^OED(x#O6FuK0T2UDX zik1g7VHKolej6B~bv!xUZ-LMf~!^y#$Rprt;4aXM17J^`?v=2{%ABU^Xkruc0%F?AfLl;NkrO+O- zS9f?1i}Ki==JQ^utgV+wm$wnx-YeafzUEXfgX?b6esV6!{wEo`gLosN=WJOkDTU<_ zPy6Kbrxh{c-{BeK%t;C*5=xd%6#E#$hj4_FtX{9J1S~*D`&@UM;HU$*`E^;>xQ)-O(Wu4F`I*Acf@QCBE1+U?MDlUcUW9K z(WTwPrw z$3uwydaLBS4OJ|xMmLk70nzRL$U7`P)UDVDR=$Or?x~oj+Yg#<8)&-yv@7%~=iu|TjanQTxL5viCVanu(m3xmq?ekg)WT8=iZ>VM)m;_ye9RWIE`w4?Z*tm_eZ*>wo-?CLjYVmO%k#XuHGeiQ^Yt(`P-_-0XHMCvf_bc-UT>u7~Ec1q0fk$ z01Te?nS)1;#|d~@sKJ%Lm^NqevW z45ldv7^$_>dwg!+J3K!AW)JbQ6e3+42&L;|N`{zh->FFRdR+EFY5h)EP7MDDhl#9} zFxemQSV{Jd&;<$m595d(I1-87Le#W(KvY$1t-5TVsIAkZ$HC<>hMz=Z2WC&*#R_ehGl zG9+R7gRgLcye_wYmL`j@$2&oGB{)HJx&5;O**hezo*-*C<}ihZmF&-h#m4#53jN$= z|5#c-9rR%uR_JkM><0ix$!8S>0bqF|crG?Zd`sSrljsHex-{SGkZv!j(2L(sB>4K? zQ3!rGO7P*4pg8`2k>Dp455am!q=UpX9e>Y6r)>zf}6-U1P`YJIvxEdXcvCv zpS<3KTHU!V57vb3S!hwqT1l2d?{6ZimW8XZtA(hp8kxGRGF_4-Q>V>Et8>FLE3tGq z+e8=bcTtZ;HY(c~{xYz=VEM3e>bR)aQ)~p*N?+|{rGp{`q9-ZSvU5i2!i`O za|y93YIQ?!by}1@7ieiY{HS&BVCu^8vZmy){Qa{3UsBx;GIj^99xd;VTsiSSAs8VPf!es)zU1gew_|vcsjo;R| z-wC#1CkWd~sDGWCWDb5tR5am;nn(P7lJ8v%SzTuV%|1y%f?hf@yaQQl;v-$ zx-u$y9K`;PwEiZMJL|`GgO(`y=J4zMeWbsa(7nN#Vj}S+t;=1#((N@sTl%lM6D8Hr zqoYWw!KkGA5~2M+E~);;CDn(9q&gU~==aSkWMW}Fg1AMD0TXZid3d+A$AWY~~)H5*Z{URoy zE?}XnWAP`|O6Vk6J)5W#wiESinOgB8ZM#ARnT84NRA`3_BxbwI-{xK+tA!SzhDl0x zC$V?B4}|g)kkIH+-0P*hzeMXe2Q&8x%&~ihc;mkEorY=FDm(HgX28ilvBB}^HIgcweH^PYi z?HLOsqI&8>xr)69UGq~=r#}?a=|T2~#u|bg?6XOPW^CuqYR(+$l1@CWeH5SK14m&f zse~S6rB*N%@1H-!f@Mc}h+9!xYDCaTnB;SfOZEV9r={ru!bznMm|+oZlMS6Yo+b{^ zc>hl>`hVVqwWbwxJH7-O{-3xvC13YgAfVMmRu`8NdXT92QJr+fZgaN~d|l7)GB@w) zeTPi{&%1)KtrGn|naCK@;{8%)nT2TS*Y3{{2u*eLl~_eWmo$2EWUXWrzt75~_~Pm; zSzT?Dy~C4MpIxM-%{09~cEdm9>6E?0VafaYd4k}gCuHxxB$@40=n=g#)ARxTOH}Bx zCWU%hi0bK-SqJ)nKG&c1WeC#Z{jyq;E34P%IV5XIE|5`rm@tQhsNB84K^XP?aO+sD z%fqWWG@1ST+}|Nu9k-hoTZvZ3U#Wu*q|Ea}6HR(G-9y-!tS&BeNY?8Mpo5GsVb@wr z>sy zRk@)_BjTNFvgN%;39aq~!gygU=-WFD>JFzE)cv6N6;{>g`Zl5eB<-OzBK|X8bni$I z-QA=;R6x8D)VCKiCHqilR=hn#dlY)eWglGm9sK!$X|{|(vn3><%@Xgwb%JtP6ICu> zM&&XW9ZkPR<+22btRZwZ(xXegpF5$v{AG(`?{OExa6rFoAhVn`N&4l0p6iTp z`elvhYM0%U<@vn})PrHvFRMYn>;w{yJZ9*Z9~t^(KkAn?QT>v$xw@p0tC_c+HN=Rv zFpE%U69#!eHR4KU1Dey+VO8jZS%ltTBlPCnFkwZgXd<}ow2*)pr)LVOT+g&{RbW!> zsQM*Q7uAg7qd15AC?>|!&j@|flA54z%JkpCinLh$p9Nal+`mQL6&YZfg1Y%eoVqD@ zjZ`;(`SED#=HE`EZ4w$$>=CYQ%Je`?+m!7c(uVmHu}nYKveySQhM25YV<3#L_?JG* zSA2yw0sR-#u(u~w_73w1!~%tWZUiCt`uKk*{!njfoBuMjO~d3%bjN-EKdEiX+Ps*y zIb$ZS4smh;0BmTRvr-c2D^c52?8l?prZP6nwawY4wkh}beO+x6C`-S5PolP2bNDol zpvV3%ID%{m+NR?lNY`(E4CWs?Q>N0m*4JRUj$uygeH(Y+|})J662dgdSbMo$)+UTf-?i-dRu6Ru9D zVcu_Qm=mHJ<`wb&sW9r7%Gl3Q$NG+e!g&4i1^fUgmtay)-yZrkA1i8>wV@9Z^aa{) z`obp2**imXllRxz2SLB=QN|9K`ehG_+~98`j1|L$qrcxl|84F!SDm0-_JCG!4(N>P zq6R`!2+a)L$Mwra^+X*ZFnW z2pmtT2@dM1QRw}hirUhKLHnjo%(&@yKWL;rEKLQV-QN^Cv%FUJ1}fm$B847P=rEpd zvm+IZgC?v1X(MWNC!rk*{X}2djl|pnunU;LB2s%1!m2rej*DjxvCwagOy6!kjvn}9 z?{z=I$I-&av8*X{PQrN$70~7;g&raFfI?5{=OvG)2FG(q?|K`$y}!lf|135hS!#Fk z@gydL{Pmh47W&OLu)y>&=_6v@Phl1BF)nR&maMHS-CBi~T6Il+pT5PDArLkF>_;UG zm73X^B{uvw5C1K61WHN;p=K^#mEpe?jzCG3d2a(qC;U+>2!bQ9p#i6BJZv-{w(y6Y z@ejMqhdt(xFi=Tg18xrCFIdF57p$Vu&L-l+y!eL&=0jrsC^LUlh}dmatlOISH#eH? z>Up<~@eiBKhi&{}SNy|n^P$ck4#YncQjCYz6ntn)iF=r9J}lr5N&Lf7^WjqdurmH( zmHBWZe^?*?u)%!T#2>cBKkPIgcAGyi6-M=2F?AqMp;Z>c_Y>wK7*osa@3|+H*J6Uj z$9nqvJe5thzsKd3qBfu>K&^+tLgVv{`oY-#Kkvo0S7>#oOMA7(RNK?r@Rbh9*J`AU zl}itx^Npyk&T?t(V+}$yeTk?~@@)?LB;QyuSzr@GB>gYTqfSL_s5SDEd!=|Rrg=42PGs?}0?_3r z=NK@}7ev9O&XwtV#J}J3IDYw2GhD0H!tmWWS^9&gz}hIzvB<``AI3QT#LP@q&yxrnt*JDsG1nu`{QKQSX8vrE zji`k-MJ-U&r52a{h&wxR{g{gdh5J}(mh25c15b!&2zhq!-WwXDgrg(j?38?GrNjuw zf(k`75Dp3&AYgp_izbtBZb=}V8}fGtYXvj@)vsHgj4%wteV;Mrq90>UxuIkn9HC^q zo}gr0e$@~QZRJ$R^T+@9^V<~l#g-T`qKpN4szQCxzhCl!`p_$_C_-{{S}}Vi?~Fv-MNZIx9|mi}=+kfJjhWirMwWysvndQuFsOy#a0D3 zZ|UzJjPk-q#z-{GCe897fj+0t=6zQ{ z-_u;$tFTZc`DaJzpC|izJ8{0-Fg9QhxGyZ19`M2id}0IN4E5J;K<~L9V?*2+rFmgF zjka$QjrMuGJuI^Nk&gg{r{u>11^gAzoMd}I@?|5?ezz3C^mIik_wY_TBGX~HeK?J% zFXJ2PdSV#Zc$i|EY~Mqur$&1G@5u3elJ9D+?=*1X-B^gt`(^tVl5YT=f1bwBZPFB= zB;BF`|9>X=TCmRIr|3gdAI(A5I52`W{*}NQmt8r;;_5f!7oNaef6svI-GzDBpNz;H z?M}!XJ@SJgMpREts9jOF78<_EX384dQdbYi-T=bp=!j3h$3IPIukrQH{2@l@fzS@D2NST$-d$GN{=WNJST1EcMpm5` znIdxB2XU66ZthBK!jE_Ib;cN>d0Wp^V_TEP$bk}+%=vAYA?Ih(Mob4s_erW^KQ2r2 z_K>aN*om9+KMXINq)68uS7?~D>(@yBOJRv>|2Pfv>rW11Nm4@BBiYjR@L^f(Q0U7* zz@f3V#M@>y6eag$SxG81ekOWqLnrEY9NkMhPgG;6oQ#bY~jML~!w{<00wpif*E!Dz5Hf@t5vKoFpCIV|K9Eb*P5R|o@LF|~J{5mpE~<1en%<1d%Sb}5uGw9|gYa=XpGDQ$VXNB;dx}-DsY>E*5-3rg(DwqNke{1N+!2mK= zK(DEeFwk==h6F)ReGJE=|7~4_1sjbP2afT-H(|>o`W$HaP7QDQB(z*>w0z~5vG=jM zNv|3bgy2U)?8ZHC<5PYk_y;jM_&2H}EckPN9XeB{0U)BS08@2IBT?5>=-OX#i7eF* zx8jdNea&A5p|8j$y2lgM*+|r?JiYVr2+L>so!FM=i8Z$hLO#>4`)fih>(`GPUDJd5 zn=|>DA}Zd)2w!j?Kxl37k78`-&kqVh@RuOPo{YQubGYj@Zm89r`bRHEQ|*I4iQaG2 zUw=6of(^Pw0~2P$yW(zOiy!hg0VmUEa@>6ChrdksWh2l-%R`q2$G~s^o53ML5P}0j zw43S{{nnScQ)(f90s0`utwQrwzh38uSy$JDCI#PuKK2Ucm}|J}*o_U$NOn~pKTh&* zU<&GG{N)CH-Hjqg%EvDmNEu7iHF^3~elFR|rFG7l5&3-Q`D6KfjAWk0s5`0z=Nl&yUdNRwI>;azcnWr3-}vOG6v>6QRfia+>NOn4_Syd@kQ-8+k$7; zJoO_HSAvPe+h!wLYxop&*r5;lL?LvJc|&W44)u~B1Kjv6wRr%aOthQ`vn}JHFJknS zjeXI8KBi7Yf1s79tvFIuBD90ukVRBKA58&KD`7y*&xF~QG0@4C3q>K|&oT1iF?9Jv zHq3Pg@y_-)NU#F<1wru679NoVaowXtoALZa5Pz*OMn&`61{m8aaREAG4+>BX9-$1i zDk=g=QMHXH84Ha=A?knZBpzY5daXNGHL#(&sdLCk zt3QYdVdJlAfW@cXN~pFJ9%uUtYq$d z^Ui*LwIqnr6A?V80l(fTy3ZjhPoYr#1;D}Mr6~g0s}oJj2Q_YU9So>%yXZcjsLc%s z+`9T9#zGU~?4`Y*5Uu%1#Ee#pOy;l0Kg|vJr>^l7V_Po(qI(}F&}u`_&A8{4FiXbM7!>p|hj*1d?_3Fyn+wv>CHrLE64|d6;dv4#~P;6Oc9Z zWk|VU#`G&|B23z>;gs4%$@f>j$(~P3gJ}`($?-ggi+E33`LWVG4aS}Bf3cU9OK-Q~ zk)x9T6+sX>@C#Pba^H%(?sVU~;sHW&Tpj*t!;As)czKBC7MyP#wAL@IOyhXFG#xNO za&atYrNdZC^UybAO&0{byA1 z;lDqjIXu=+y~39#f7>`g*qV+^Hrx3#33#o1@o}cV^Lz>}TUz>6a2MpcGy%_lDcI=G zi!jz#R496EL@O%9Y%;B`0C6zi3f$BytxE}hAKe}QSUyu7B9BgJCmNy?=1sI#TxqmsPL_2*DMUl$>*xI@72t}m`S*LO ziQ0-p5%9yGSad$~(Fp598slOEs81hU12>^pLzV!Dj;sM$f(d6J9&aTEcc^tJM;9gS zpKVzKI%6+bonA$~vacwYD`o}yv(S5yRdja~b&XAbVoijFUQeVil&}0q_||&9CZlI+ z6OyujzvO>`rxhBtUYdsE=QJCKUmG1hu#29HHWX~R#)3Ia;4Hl&Nzc4*v!=RLGd1K~Bm zm(FL4Q-zvV3#gZp?}uliSjmNF{@s%Ac}xLCH4KZ^`n=UB7chZ(*%6mWM=Va(>KfoQ$e5YwEh$O7of;~#U{%@BxDAPT1 z`_VL6+!Mb`rz2sPPFQX~S|EFe#norY+G0kgV*X|*zm}+ep2@jgu@9`wj$XDW}-cUeLMTuFyle za&v|N!hQnSyIn(kM-Qef@^Rsr=kfF5%?hbFC_qR<`?8bzA&Jpo3Q8=93^-()B( zc|#d|FSmD(glyceyASj670BK_A`C4T2AL7ElX-LqG+YM}afvT*-&G~d&_@4nE?^_(Enw}PK? z4e0ydAm8)mKa9-x{L|mRJl`|AH+3@4^?WEdYTz8uEg?Y&o+Ao^zIHsOEgG^(u}4;S zOWu=lu=<*N@}%3bw3hyt=Mu9IQ~v({@;20(jJRES5o!H9!%;CE-G3@)cO>LnyX?a& zFH>kZF5fQ9^X)FeqN-sd-|nsG`j2|`d^PPjDuvISjOx)cP0LZ}bI9*p6`N1fj>~FV z4vN@EvE{eiotlbLJ2(UT*tFD8-ByD3!Bw}?1l8@Pm7vkU;>k4{SW$Jy%BY&-xizLZ zG$knx4WJABSuo-;=$~I1)z^NSsH+@(FhO5C_#o(Or!|opxU%t^LBmACYj5P3wBbLN zWE1Je9#b2D@fju(zCbrM4#t~Ek1UKgk!(pOlJ#4dNcG%AYDh4V8WT*Urbx_0YKa&o z((6K^iDUs2>9?j)^h+VpDDnz1qbRhFXsvBgaCD4G28Z*Y368E9INCTkIupRL{D&EF z>OVBm3x1X=^r5OJO1>LUpy~|W1dC3<`i7aRT3zFpnGqaybyjXh0D$y;PoWvnXwYIg z=;NFg>l0}4wG}{i)~Fc)7}A^ZW&TDF4bnZH-sT$tt!uNvDa`G1arw6$@7F~Pm^8BwzaH zj0OKYO%S*Sv2(-n17_nc%*zl(ntUDo&H4MoSGHn)I{>zj;^p(8yj zZ-_Y_>v$6jbPu1g`q7pW7=!e?u(bZLAPAx5L>vFt7rx~{-d!FW$bliu zF~oqIB|iwqj-uQ%908|rW!{xh_wk)Up3QKOcmtVa?@@j5O}H$wL=XFqYC(sVqzR3p z=aM+_aQ*TKbM&3TFKv3^avr5ASRPvl=fv2~n&kNth8PR}6h0Ct%EJobYEeNTVR+k5 z%aj6l2a2XUP#7|qGAJf9WyL!tQ(9y0K!LjhEeYy9)1H`j?mFyKLF6WDROZD5cEH+uv@p9H_2hhG`+>$e_3 z;CTm2ZpVPU;YMuj!70y}Qgoc@DOze=G@$zs$VTq4B0(3)`tdi=;BpbLXU zG!?UZ4njYVV+gU7$N*m!dX*1Ti!?-e0 z>$q=Q!_kbx090K*-%VZ1<9_vAKEu?uP7wrQ%jJh@W?OE@2;WVQNkSh^i_aZ8&~Laq!iuHM%`kM_ z6>U{GR1~$Dk6qq-RMA?wGd-G*wS&-r?kR$W1|95*DserC(063o=3qD2^qIFsSa7$_ zFa_kDo6U5ibvGO7My3?&qG6{0avPpP6eqskzBNsV3avvgq0stWn;__GZ;7y=yAn%^ z>yO=xIbOW$oaC-O(Dj_;u0dU!RwTxHKhcD}JE3Ci7ezBSwEz8em)inIAXZ6t-oK?&4*PGR5Y~Bik)93%d zOf=yWO3FxCpoiHOSdR7IdF z2{TkAINQqJ4m0aPp?!Mq3eng`S(Qt?RfU4&JBa@3$^w_a&r`y8(G?bO?a+v|zm%}! zk>u|V`h-OPrb7Gmfjc6&4Z?rey~U+o;^>Itgf}`uip`2 zp?{j&ABuT3?&$W1tKxP)Tot$Z;Y;ch$)nXL!kH9ucYHGfU>54RMlLkR6w#Ww&igKw ze6H?t(E)xym40L}U68ePRVL{!&couDJodNWGwU=#zJsD5=%L#qEchQ0Q}PXcvitU^ zKDkR#uO!-YthQ9w=d0BVxWw?|m$P2!#X^qM#do3zNJu!XhZI0~yg$=KF&IfX6w z(>J29$DTzB>;08UVW}ce*mu^9LSeSsjqTXp7BET$$u|_Oq)>01CF8k{sMTF0fW=NZ z?fjy~+(xq_fqWcToT@A6Ppk)fP;Xfhh0n_-eB5~n@TptE;bT;|>Wa(1SX~t>a0S1k z6|VS&HU8qO_sXP!YMpY=-<$r2*D@ZnLAJnOb3F|z(tm~G8S z79%!8j6A#5u-~1U#)rFR{Cy~?NR_zl_!Di zw&C#}oH_OPFGtQZV)>psPZ!7cfO;6?(0fnAq1F^Z&}CSH&qy)i!C?R28l}HqoAh_$ zdkOS6@m8QeJU{B7Zi%)3MUwyfmPG&eEodKlXYX1ahw#E1OoZp0jOXg5z}4q*gnOR* zMhO4&uMpuE{=!7~WJLJ&t4Bfj{9B@2-6F*87e}r(it~Gj!PQMMu5L8Bx-EgLXBk|r zVuS$Uqu(5bPm2l9-(Q{p&s{g4mY-im{6|^ZxQudj^xB$qoxs~Iz}x3z{kmTm{l&9% zkOXiWoWatzC`*6uW|O5;j3WQQ`Q*&UaF3er%w?l!4C8l)dGevYBG+K`1yNT2rzZ~c z^R72BpPxE{)iXKf*Zl4qVg4nq`%kSiF@FVOevxMs%$JrWvHHT!FxxurbQ(kZJ>rP< zvm4jc>MlH2CTSggN0(aC;Ef6l#s9j~5bs+q69vp|8RYs_GGnT<2uGTg-_6 zZOMNG9%pw2Z$zK`>)@o zwczh!!vl3|a_~6k7to(tZUX&j7&qv?i!uH=vU+7xH=U;b!zQR5f=J; z;`$Y*_HG*-+{2VE2@6Sw%nvE2dx@r`P z8eU|`60HTWt?!wJsP@baIrH~nuu?sT(COO^>p&b;EW6Y7&5I(;AT^L07J$lc7n!VR z9l>&ikA&Hlv#@?qj=^&0PBxRp%T~s*+?xwbmb<0ubS!6S_(m)@rw#$s^rQ(O83AAfW`)4N@`$c6BLTRlLcDZW+U+%jngAH zibA=$OBemPfx;3n0rU*&HxfYO`?AFM_5O}9(_hIq=mMn> zPXMMWF^A*n)d*oE3S0)H8ID*tM_ zHp7M9!jt*)xO1r!bDiNUVyJ-dv;#s>mC-wX7-3)jrU8Vcd8WnBbM?i?nf@=+NL`jP zVxF~rQ6Sz{3&V816Fgg4FjS;@B!H(qaG_C$M@GQvzCB@eFUsE?d@@;IxBM`=zHd#^ ze{M+Be{SIV54ZM=e2Hc}3?#a~8<)}bJ$h|Tx<1|dUT5@|w7&Z-u_eRCRYsesGODd% z4(V`o;h%m3Fe)a~6Lk|u1V2Y3;LnY|=P%&zS#Z&Lz+Z^GxR!6|p$2T*+~?yd2-*#d z`1g8BNp@GLDhfaUe$NHL4MMzq*issW=YvW4uce9kucZi2dneXoB4b~R1y+t5^_cpP z)2_tzfFHi1)$yY}CbSzIn`g#b4D}}tJP44frI94+Gf2{uL&jTq=35%>mQrY+LQfHG z{GU$Y_679sl{^J{0e{YYjV^n?LNQ7r`EJHy=6%YvVbVUFN?PIsRhVe4AX@YpIq8Bk z|8Qu$><#3)?ER9j$=K^nhjmgaMk6Kkfd24}xHY88aA94TWZzBE$@K~Ox)nS$RxuPm z{haF~j1!L2f7p~rXFKdW-PYjeXT|m#IOtBIYCV|Zh^Nm;-e2O;&)Gz)8X=MlBgqNt8sSu16-zsr*iG*}Gwj+1_5z|?fUzLt|Ngyt#s zwv|({$k+B*k*_ci)%g5wKaKOev^jW z>G}>=g!Lh7iB9^ds`PfAG-X9-T$qqQ{(t!tt){) zR=7swhjX$PIh^@!t2$21t+{-Q(zTa{nf{zTO^_DvHfAPe5}TAstO5VhVRI*4B97|> zLEz*;#nT~L${hE;t$UN|ap#~8>3v?dCMLffc#mHczk zP=b!ctvg*mx*&>F)PWG2?<|Ngenf|~8P`K!o9En`)|cQ-&snhrDs-kGNUx$-xSXOg z*1`4u4(>vxyS z?SrYL<Dpe(6{NdmEiGW2R7W)9B;h{p zP1MUzM9)#?gBOcc9J(>+s-!^^byGK|e}1UxusrR6S-3Z0;AGlC$%or+QB>N0`e6b5 zuYjm*d4gZ0%JvS)8yY7F`bE*f;~^Q;S+hV(>*FJLZgl2p{5lnT3Wo@J)3An7AezWl0vVv!ldaUOVr#g$}&hj zu4PA&O_VYh>qrI_%ct|3uVdVCr;r7u215EAqCx=UjFTee4% z_qS{Nvimi*iR{mMAYjQK4uV zb`mJIBhn?Sf!ktxZm+b~xlvlYZzR4I)fvTixhy@Kz##I13z3r1KM^c}-}V7%{e%=F%lQ-^|FE(3vmeIa zFB+}Hq*kH$R) zb{$V(jqy)*mrOIZ_d0+)yzTWa+Uc^NjNR@T zM02$CO6y`|=8#qtHh`YjBCCZ>ggQE*PtqU<3ejoa;ph@w8maG<*2&!@;LxLQf%fm{ zmes;8LLEB3)#g%5yUp4{q)VYUgk`m`hfv3W94PGJQP4u2P*GM(!-U>oajInl#q?$? zlF*fS_F1pSRf^0wNIVRJCEe5q0EF^0*??GJnSHN&^^r}-r4JJN5QuZ z9eby)LhtO$T&)BuZbTy1x?)uhfQWUXY3)1>r-yI9*H0Pod8}R$6PT3?FbxM<>0hYd zAPvXZXumHL`R*TgA7@)`M!tJv$tZmHT44g;U6jOkS>>bbZ%yPvR+?p&WT>8qK6-v+ zNNbIutDK)`@0JxN*t?ZnbFWO$+@}|U<_?1rCEu$dz9(RaG5vzV2n+rp#Eg`l=VwH? zMtP8EGdA2DX8LPS1MeRAs|XY@`x!yV->*=BXC@x8Iq}_R1VL|}8DYUcD}tb(`Nkj% z{zef5-rsFTf6+Xi+R0(2KlHR9V27q1^U>3>ez!b@{jP_8mq5P@6+91!v7ijUehI(k z!mlUb*9`de(er{3yi5^<&^WBMjyu&cHD{-RAjy}*llTxx-xP>Zcfq$A&3gaG2 zneJ5hf!3i#W(P^xKl+>q^X>PX8GI`G5v(sgBf^4@L3g0U1b-qgQ0JMU!OKsxXjQB*88UFd`41>q|uQq)BXoI<= zuO5%0<*ud2*_PW-w772`CEBp!8W1g5=cR84&+qGsRh9v17*e#>cC5W`3>xM}1A5&B zN%?(f$R0QI`)-;cWJNSg{(f4Gr-G?EB1(cVlDCR zs0XnB+bRl*J>oegt8?&e`gd%o|7}*Rs@@rLU>>fnQZ9xy98#tayCo`yJ7nt15x@Yz z^syf9w+kD7I~b3}JdWshcmlvHcmu{{75Rw`zMm%LFPY<;9ydOsZbB9K$HY7P%reCK zRTvR`JRjGbOL;^vJRv@ygs3+ng0K3MBZ6B;Mg(7iw);c5DAr7nz&Q2Bt0PQW+~$xn zV*pva8x&hm$N^Bk99~Y-ZyDxL$pWZkY6Bc3mZ)goFZn*^P7zpXK}uYbR4>-sQ4fap zbP3k;1D<2XA+6!<+` zkQ6?A%@>Q?g5^k@Y@mjeG2_Nmfxo@ z`66AAz1s@V8|k|N>#n|<$4g#%7Gh?DSuY+2_KRH6NP4*-z9O{beHu{@?SqGec>5f9 zNuO!P^W87F)Hyt0|1r;hoEc%E{lq)_uM3gN_Mu$){`XL>?Ba6e-LvB}4GQCO{qA@y zS*|P+N5~ZgQyBmSI34v>n<&H`Nnu<@@esYXCS8vnZyR>QcwJMRv`lNTP_Tcu z+={1f#TWEA|9z=oyfFumJ0@`;zH3C6iS zO*O{kC!6#Ay)oavUpZpFHL>|teVh4KCeF7qX}*<7^R4`<`BsiT-;KsFgX>bU2va}p zLP}O^k;>`x?b6~lDN~faEe0VRLVP!wgkY1V6vps>mVy5t#NdJ51!~Ho;;8oY_=mP8 zJm7b%UU?Hq;QuC)$p1|wk^h^%9RIRfI~xAwK+Vz^|5tJTuZr@23qk&`Au;~X=LJ0t z=EsQzoHeF1Ri+!4a<+HYBhOdxlOHz96yZVqyWI z=JvxFvPd$r4C4KWBg-V*sm6L{;_L8uj<3PI5%{W!;p_DD`z83QOvG1Z622;v@b%^N zE337m(XSk+*%-x_vw;Mh4F;wvIi@P3m^wcXG1X`!}pQqUz40*+kDMEmw#!#ru62w$k%-FKBTPd zdriu!LCRVvk3w13T^`NX1gz^93EwVX^NhNk6V&MGu zQSN(=#BrbPVw3yE&N!XTwdkR5#C_^=gwfDFCX9Z9FuH<_0;5YWOX9wV$9!3q^wU?5 zzuXlPeZ`j1UK^chpvg{zixujupQB= z-x{yS-A>w1Cf4JAjo9Cj9zT95FiXbMM4R4e`neZ>H&%$-i00Hpv&Z-rE0yP@nI$F0 z-hkywkgjL1^<~T3bMM|DyxgL%pucv^f_x{H41i_H46Te6JeoOqx90+X7J<$ zUcYpTzA+~uo;T`-xVv)@oi?5;52N3bDhSb1#uIP6B+T?}y$1JgjwZ=-cN#rNXonuo z5zVw-;EX2^rh_2lrP-sSx+r=7`qksxITbmRLzj<_*Fc&0i<09^{|+CSrwA3& zemn^HFm9qr+ONsqGG}!wyc_)7m{ps=&oUV?v2znA)^Y$Q_FU4$CK~6_P0_Qy#(Yj( z9AQ{Cu*a~hx6OSl02U?>(*nwW=DbdLQv+wwh(C|x`k1ZYyh zl?yNCH6wWDtX9P{E8#m%`UQ%By+@tC&kQL*q~dNxavmpYD@s;%jH4wJ@pC|-pA&8T zU9a%8kwZ4YsHFcO&$Msiq4^fz?Mp_6=Kp&t@;0>6Z@KTASIGG86*$|{g5zw<0-Wvi zIirN;ugJ#GJWSS1iK&UD44Wx25AsaS=nSXwl$fr0I5$&<`uBUj8$2*&L_KtRQ17(G z^5OnI1>{nEKHPuX67u1mwqd>Jcwq6JLb$sJw=g9E>z3ok&~Xg-``+?zp2u+Ndwfgb zRma(uQUunR*`oj}#RkAKiZ$_}sUlJ3F@*Xnv4Who8mp(_+H~6Giih!de2N5+{y3a8 z%*&_EmHdGotz6~jYm~o=%klyEL$#VA#?(3x+_Y}v5Qya6?z7{oQjH_oU7<^y`MX26 ze4Wx%xP5?^rZTF>7fM9sgHrjRRC5UY+wfIIn>g;i3_+oF0IkA}eAkcKT8WUTLx5h?eeJo*~FoBwG48_{)(+ zH0>pvv*TQuI`Sl|V~j(}bl9X!c?=0S&NZ;!#pm2*(1A?l0-|E-x=bG~Bmvw}X5gFW zL^}vk>va5iLn+@Dr0`Qv9Q465;@{_cKq$7L33mxg)*NTNwZ&OP#hKu7X)Zb>Yb6#!c|9*9^TSB`ufqzkT;i226>}!!ynV<2j%v`G+9$}M6%U9!j9PYN*jU~2!b+g zK&BmX`_WX{zDJSf9Vc62XWn%xQqkwK{Vi!j=LNA-?&yCFGQh>IUTLkylj85|l-m!d z^ctUTK{J{#g(v+QKmL zwucFQQ?Z}&d|+5(ikSps6dpi7l|s?YlVs1?54uaf)_H@*Ie53W4`Mz3QF@MgCEq?j zVpd6%Hka9C@2>2=9il>CsEsh@9;c{Pc|3EdMftI^wumX&heDSq^pMN`>B@@~+M|rsu^#d`h4$p{ll#92S&HG8 zqyLMjudl9QIIe{JTj(vrJq#{-L{V*6T75H~5$Xg;Wr1okIZ5Bavvi@MhVJO%9E)Nf za9@kX@O+QOyZT*`GqKS78epM~={)813oP`GAKT`l|3CKLK0b=->>r-V8ykYmfC%eL zC6TDX*F;gX0+J9xW7El!M1({(KLV!)!gv|3f*O}R!-3y~8a2aR(;vX;KbIh{UTV>-Y&^9hZT1e2a~B z{8OCCI)3%N1F?>~*CuGkMU!@12r%wELv|e!o_-jlvKKX*yTfSYY89668AZ{=gpcSn zsLwv#XIR>xnKQ%ozflxgzd!|?>;(5nFDul24u+l(9VeLmem9LeMyJIbX*CAo~bC3ctCd-to zK&a;Ggj~6i>wSTh{3H>Szmu+3p{|5|rbpWmL^`xW{^S(+M})gQ_3EansTA*{?;e2S z{X~M|{VVpOZ=K?O4WoGf)TDUdqdU|W{tW!W*tG`>Q};+NUGRhPm7cplWI?m0P4A%; z1GeX^UVvQYm)cg2-OpN( z8L54l`RWq;nJeOb&FbAhp@kCyPrxY0wdlWr@keQs27Q+)ICQhcf%U#zT(nLvqucpq zw(a~3YdhE0_8Nw@qr1s_w)|mwt7%Hk$8^a!pnl3w{r-gQG*2RIsjwu8X(Z=ktmM(Q zlUY`SY~a9_1iQUzvfFD(cKc(AM8snWc6*jiSBebJGK*eVsX+R<4Opoyr7HaIn>Y>| zo^qrF*r~%*{*~NXos1l2YT;9Su_O-eI`o5F>L|-(C!PdI%uG zycKfbONso+2`Pr>WPPKfRw4&6*@DAg=3st{{j^=5a@wjm{AD@zpWv&90$?8l1uJxS z15yI)L~5bXy)5xDY|>hy{KHlm7t|foMT+86_eW2ISw|#s5+kq$mjeEq!0g`8l@T!+ zDD<;z^+m3Qb|WkgoLRW#0XH3N5gNlNE5-vGsdolcNln|Ip>J2`f?_&qHe8|ZWgEMF zN_*B*qQ1)vk-_^EAT974fOs<4^#Ic{k?d(Rcf~MB?fXkFaAuhaUTKo>flE8dlxIMk@cj zq=0;^rHZk-b}2vrqy#|*gKkj{E)ioK?<+wH60wyh=@ym_l9ZR}L~2XZ{E5oLPNY0u z2*p!|OQaL|L&MDCDKkW>y!5e>DR+xhRFBBykc}z&1{gq9A@*_=ob zE1V*c1L`AP1)O zYJ)g`sihF7wgC}O13P5)4yE8`_KH+wgA>Sx*>imjNiakIP9PcfL9~B375=(e4H^7( z3dOxKp>E~B3dvk=A(=%K$@IKpBAIzB0LHuqFy_K6Q_Kc{F_Y3@%*AOiX7tycOw7_gVy(P)xTMsSBjxr|T}bR_!J4tCLpN3aD;83@Zo^7dsR>I^AcPnx zlTcT{sMi@F$f&J^zP7B~W*q(^2lJcluw-2dEZK|0UzB5iA74ERY-mMY`VHy(eHU`| zFDOBz6DdI$N`8b{1`z24CK|nf{?UEd)ERCuO?9Z&Y91GKBkDA0IBj;w+ zmm8F2_h#9%hH}UJ!&>Q^8HezJWhpRBqERyL?PoSL>DO~}3*rpqbLwN#@CSVFJ;MYb!qfNVP+{$z9?Y2} zk+_?ANBr^Z1w&DAn&BxkP++55c(xtqw*%VvMR_LL_+&;3+Q2RY3sVgn+8Aloam&TT z&>iZQ-@;L8+W@eueG!&PUlMv?*E(VO_&koA7M!pTpvQH-J_9RDN-(J^VMoNAyk0{l zb4#a?z5cz~*x#44u()i4K2PwU$(s`y2nqG$AsC3wnpOoE=MxK?Sm(o{l4LL{{W}qf z%07tp4_}W@uySijIzGY5qH@3|zs=$}IapOrF^WX?rehR3xNi@moQ;E1iUFkD2l^36 zs5Y9aeXfs%r(^~>r2M@Mf{e2u2<|>gA;{%l1wq`x-Bn0kc5NyKc~8o~AZDdPDp$f& z5D>wtTc&R89p4@lDNKPPjFtz#`x(U|k}!F{?og+_0OgQm*M3=;x?dU(n!~~?<-lh` zpc+yKmz3c4s*)rg>B;UjaC=oL!y^XZ5m{MMn!qFO?xUoGo&*xfNq~{RK!}-CY|ta- zic~xTQj)+U?9(^HBa&+`;1MbR6AO>P3rxWyaD!AlLWgWxQa(Oc>#3Y zqE@}!{9AJMF1QSlor&^+i0m{g_`R#2N&j|tcawMR&kN_{&LlpOIsHM~@4>2atjs8< z-^=7t`gaK;Iqze|!`V>E>6Z}1+4OakV56!6E1psm2>H&JgT7LU9MQ{D;!`o%4J#Ru zR-{xEA{Q9C7wi+BUV4!3>5OpyV=1`M!7SrV^ZN`l^Z*f52$A(1BDaf}4V~_bG4fP4isC zn)rOLgX7eV^e^!YmhL?7XMKj2eFm4PVRRS$qH74psgrrb z&{X=@3VOwE`qxkCU+)c}FntFityYY{2rEWlw-JX-Z~7y6b=HH(=M+n1zj32OTg_!; z;a6lOv+#dw#0~ArERNIu#zL=ITXi}8p36#JyO;46i0oR3T)CgNF?f#CNHTMsy;|)( z-j>VG_?+H^%yB62zTs~ir@g^*oIaV2+-g+u4#y>*Cg#nz9Dxo@K9otnR+s2kqr01) zrHkgrN9aIM^5?m{EqA_5=MZ_9{#B)4r6XI+q;EWE;aAiLC6A92aTD~qQCYs2O{I8Ob;(YT?#FgW@C z(gyU06Y-StDUi5-)6ux0ZaEe=v|A0c@QU?9>Cb0g!WKipC5fOw)p(6F)A@G~X3sK_ z4L=b&1!aUFxW`^b$P7t=V96hRk)0VVnRg;?Bm+?f3YJ9viP5udWrU_589GoIAqX`x z%Lpw?##mWpgdS&6hb&O-Sr#=IWYwwR=6^3tRuj7BzxyHX2cG6r=s65(tivxL&%zIY-eEKx>i8H+Ql=}(psdb~fgjL;Rk0Pi=S z7`Tkkp(AlaYm3wCW=ADu&Ar)XIQo9jlwYHtCFP}uARg3^U46c@Az>q>es7;p_YCYZ zcNOci|v+28-qi+zT^4*4gZ=Y)5*1mgCdJ3N%*g`YhRd8OC<{P~Pj zptD#2bHtM#uFhv=gsb-e?!Ez@jI5!LpoZe{lZNgK!~FDV6I>tu`Pl%~g|UIOxP9bb z(*Wgo>b8M!t*OsuhfpG3^!9k%cD~GxqIQ2hR7<4If4MB%%u%b)%(0vu)o-BTqWa!%*l{tTJ8oj9ME>!r zFI=0-?5Th^G^Ij%oOSDSAIOJw{DJW_(XPi{iwKbo^ye(S2a!jh*# z*%qbWQ)~tyzx6*>rR^1`8h*)gTN}+c#@Ho2jdNKcRLF0AWD5ht31$;=G;U_*R3POo zu9tm3a&97C{h_1w_4`(5oblwu?fS`-qj5ulY(4bky5>O~cc=R<_iXpw?t5mpV$zp! z>W`p(njfV>%y7yZ zV`1O)i39AL^N++$ma;r8&Z+}m^VE+L15pcSa-4fLZ&vl9(*4t!EJGl8%>xMF>E$;v zvClmaH&Vct`^-%@7=DRePMP@D7UR9-M4=3vKvvLgmnY zH8`W+U)cJ+kTwUdwndo(__?iNUuWFVmL=L~zRc!JY|XdO=JRO3_fZY-A#J&X5vS#0V3k^Tkn94Yu$b$ zTL^rb$MnY&pT$i&xUK>l9o)QqLkFURGZQjOIuE69hUZ%xajN1vt^F{31?-1cUux}# zD_}pIQ!v1Oc<;e@2GQGpZ=o7kftfKyT8!_CYR%_yLmSlw?1NS(POFo155^6Bu%4@Z zlnbw3okm-~OXqJ>Zt5hxoy#U^=cm>rZ5eEvB=p%=P11(l87IaCiAkDUetPxqSO&|` zORPx>u=;m{2daPfW#%L;-<&x~H}8uZ+C|}kCn@%YIZ4eqY?3adt^b_EaoQ_6sgv}4 z4x6OcK4C|ce_~U=loTOi7vq|D;Ym&`z+LPId3e&v zNt!XpHc1=ye$^!T-pP=x!o(!)A9q@l^qos!l74oPHAzJjT_qIO3EaiWp#3s8aMPo zdX_$l&QRUnxS@*{0Mv@uzJ-FIEvUD?&SvRtKb@s@{y6XZjDGI_$Yu(D@goalpSTT# zhav}cO(iSA9sC>p2*c}AUukES;NUghYXE1jH%lMAusd!fQ3pIRAdZ*!GYfDo9U&l^ zn|H?z^_@L&L%Ypjc=_;57_&dl3xRsmRz2H3KrS)B*E?Z=g*}F$o|70L{b&v_H!;9> z$H4%L%>nj(WDbxvHaUK2FF6?l{L4piL%n=Y+?ok(wTbKT%uEY>D3N9hB+IKmk6XF= z>aQAeQ<*HE{~XNo*+O78*gm?dkUv+l;Ur1kx}6eqLe%*Ijv9 z6BsXs3H)J^HG!|f1pbB}U;>~2EOP?)wI&SdDHHgo4=M0HH1Gu8_?bC@!~56-E~Tv< zeKv0jqoiPE=!^cwC5g30d}htz&R#Z$UGH0SxSzAl;e8)`l@NaCrx`+cZek9XU2$4- zxOxoCVM(DihhKuz;tpKXFfUb91i)^oWpnGY!1iM*6ZSI zsoy=F<2I-KHw%${?%UkAx^KA|kzPreBq>^I2^7Usz##o(lW(RM?-V;*_7KVu0tloqoR4eHSyJ4fOtJ zQ3-hRizbL6X~*OpO#XpMUo4N82+*GSN|90}BH~#kh?4CF&ML z4=0TEgfy02>05!6yB(6UNJReLk<~*`u=d4Z&bjrTMty=rUS>%`y`6%;9I)bt*uPo8 z!56Ppif;uQ45SZZWwt|B<|S_# zhFga8>tH}|zYc(1yKR-6emTRsVHEq{;U(e=Au>Bc`-Zz6q<4EeT)?5=Tji{nmMZ*$ zKKdX;JoU0t?U0DCfeJ}(CpM}aC^9aFO3AdtP?4+I7L`JOjymKpsx`HXN6D@ ze4bL!Q!fRBjEZLejqaP&dwxmZ_Bs(Mkby`yyO|b!C1clj>Q|-b9}LK~e{6T0aqZ7% zT>HSLzjrs?bY?fue#d0EX@;e^X+{Jf!UUPsIUhm_%mQi;l&2)F{bYCCh2z39nxO! z3f6|y>GL2|9d0^FzlDWI(5F_5o}ug5*Pv%3(n??Xvca77HdXI490xzp!TW~N%YCEh zVD5Y(4t%+QpP*L_9_1wfZ+q17PsELrt|$K&PNa;cTdGX<;jtg#@QEB8^zbYsZh{cN zAcy^Q$)Gn9$?M8(A{zSvRSUw0vazdO5~_Mob24weMG`8HW7k$;`A{gewm(NAhT1W` z&%oh*In#neO6CfWc|u1f3rllK<_hye2j?PTNec>W^A71m#$*RnQJL$I_#PDeu83V9 z3U&WsmaI$LPuzki6?Y25aOV-XuyjgsCk}dxA%z{2qsX<}x7)190@YY?SD)%L^bNM&sC15`;_hGPOiGM4hGNW=uUgefAN3pRudw}$OMf3Fpllt*q@Trt z{dyXRi$_>}S+P5|p7#!sl^+&6WaWWkQP0E1I^6N4MD7_VvNa`o zawiJw<;dU5R}V(PB?cN(8`3XB3LQv0acn`Z}B@{p3#17l?j zljRWC@LT4eibCkSXO%>J&H7ns`S8Fe^#oR?I_LldG{&T}Hep(t{7E*O;z zZuhz^FOx8uL#`g*1ljeN)Au(BqyIZtR{F8BRD=w;1L`Ah7C=p5#n&7N`F^IY$W8>E zyL!Cquu|njMyO^Gi?}|^9`l-vwr1Rh5OKZNin#u)X3!BVT=Jftp9r!>3f=K*LlA6T z=&iA`y&f~8eN!`VtZ3gik}od8qJ1|)v~LFsd+qp|uvg?i&Q~vjXkT2^4iUc7gE_@! z@>pN?f-`VXDu(Q_&9>~Zmcg0v+{23o%pQBois$x~!xN657p<1Gr+EtR_6tw_32Y8M ziBRHSu+I>QipdTw2z-bT2Tm^+0$0JVb%ORIJUt1jD1AX^D6CFob@mdG-xH_y8Cbai zlRS1j%-c!f(p-lv?wi6QcOtGEE7vA{uh-iAuGiXpuGfAQAOFa7K7LH$M<6EDUDt0I zaPYPcOmB&yxdn*ry`(gMyOOba-_7j97-LH>0m zwtaf>_PFttap;9=&!E&ebm{y7;?QSB|DA%+*FS0oq3@H0sr#hybD|3`hY0jzR9jVU zu+mgP=xhEFH*kBEgEML3R`wbOJ$|)UdRcL^qgKds9wJU`R5?@Uu+Jh%p%l>n-S_C=$D@?KD~H=`1Dul9UwgYNh{Ak5uW}t z{S(zOneph7J?gyoK=o5|=bNZ06EBfj5kzXEuwu7>doHG5Y|97yaWN#=S3b;f*qBmW zZe@hO2xn?{$cCBBaEqdOHBiE$hVl$5X-pPH2L>@{BARmMksW=fqJ_7=`q~a2+ z4AR`7?W7B2z-8s^x8o9RA6Twg#7Cqcg}9LV{!JC_S6%7MyCGeV0*O##snly zOk1d3fyf|4o@L4J+l9KP!Rs1BL~cYucZJD%A~86uPe|$$hfvTLQXd%3R=4_UKG4kq zb%VbRN#h~;&%92ko9y5?x02`Y$&v^(@?P%m;eA_>0+DXQ>f0T$R$iz(0kKatPNdu} zYTa2Jm#D|Gs1*6zL==2W?Kced*R}Mm-d&27s&WM7Y<~zbVm-X1%v&MUy_I8Y+9p}K0{Byc@-jq%Hbyl%JPP~kI3AdN9kS~fE4gV~ zAJv6e@f0Fg+rml;${-NQp0C=@xF~$bv_^QpJ+iV?#I8ZUqfqEA4gW71Dv=%?C-pP4 z;QeRI=)Gn-P+)`i+?06#2orwaG5t(9kEe=~s~nSd-%*MOu_D7YqpbH$wj|n%!e~w+ z8r9vgOXhq>pzxk&6?V0I^Xa1o&Ie;#Z4*on@iakkHKleHQasH_k?SFGm&mISsjWw3 zRx{+f`@n$M2wAf|;1v7}TK!tVTwJ}N4qOzau{774Y6$iW%|7a7`8NG@v^{5u%6fc9t> zvyv*XCaDMy`4P+Iwuozje}h%F@5d%pdX2~lb&jkQIgk99$sPQdG9NhZ;vRsN-$Z^&wpWF0dsT?;ReyMb;~>O0 zb+)y8AcUny$`3*ES1n>7zmtM|KW8;x#hN$SuRJe{zNUQ{i{ORLwne}t^S{-)&2d9J z#HSCzS^#VH4Ghk9y2*|-ewaq2R5+(u>S)7py8akBTitQPz`+W-9kS#t$UM+X?AMQh zpCnh05SVqG;w+P|4bf|rDa8)tYWKMq+uA26u*-Xg#k9uO;RiBVug3mVz{x~K3fv$N z@-^#MGyAjK-_I}lmE;O7_%%T0a59Ch6OpL?G&~fEYCi%?Yutz!zsD#Z95ge8wQ@yAD0Mjsh7QQcBLx5_pCw_fYs(B?7VJcrcH8H%Q7D zN%<3-WFIG!Lv)tM(ODjmyxv290DuR30|j{N7O0C>oBM`OlY_P9R;b(#L}yXIHwW1MMZw5*PgR&yL&p;zjI z=|3ar|1P(+kg8#F>(#3{bCxe*r!Z_3S5znR10wWr+zgNiR|+ zsRv-wS?o|hHqFQkPQDw78?CASApaL4BE9hNgHZca=7}J+(KgRc4$=3Z3`L{|jg6qO zTfMiUa8EXV^VL7H|0H4MUes)U8jM}*7EZ<_re1zsA1kN3SVSZnkxIw(V9oxtoQ8`XdNw_8g0)fgzZNi8%>UdUHwMxt z-o+$_$%!e#>g(OHcHTQ!qU%7pQ`Ga2(TY0`fsegk{cfolrS}SGwrx^|u`W!%8XK`0 zd`Jr_+6XFVQ3UbPfwjyCese$$i+nj)W#FPt{c_0_TbPSUr#=RePAR|B%FXSh`$`Ox zs6Lqf?e31bNp!k0Wj#Z!C%`_yh$;?4y7CMI5no6mo`^)`sD4g^R1}e1AtA8M&Q-y( z96b)?YV+NF5)ui?75BZ9N+59$*aQ`blTPK2xPC-|??sb3;!FL9cKflvj~AX^1Y2^a z@Dy`DgeB7wcr`p9B2fsMkOPLd6u7wKs<)|tlN32BDRfKng#sZVFoCWw0j7aOwF?cy z@RWTi5j8`p`U-nI0^{!qVfFd3RvwXAP2M4Nm$n&vf$d~J1!NUhaByhJiqAoJlKB#u z7yTBc;;jJ**906~WS}v=kbaf+T~@3rM5WQyxuA&sotVDC=Jai6nbR?{9gMXKhm@R7 zkPru-H0JiPbZrBHboiQeAyE%NsM`Y~G1Y;_dqUnyAX6KG#&{yg)#)9lg%kP2bQtF* zhrq(lt+xpF+)g3z3nmydGsNmPCvtt@Q*dypC00udeV4%r`A#+!s|G4hg2|6|ubq$N z&)G>nlHY-mI3|(L5&1yHuM}_+i7^AQ5V*uJ3~gC9BS-}+ai>uCD9D{JA}RBtI5=Bm z#3aAHitR>JOCYmXAu@YKo2QXO!5Wbsi!q+}iAZsah)fj)kr##y((gyg_Z*V)edb-H zkQn*fhXr%ab=OZ7_3NmFFb|`c&B%fLTLf&Zm&hTt>?-guVluT5`?v5ic}&FQ9w!|V zco^Yf?s}QZ{hSb^8kt&x+ozV(b=2l*K&yMt`7#cs#AAoeLKS8>6N(&v#!x78mA4Op`hc5XyPG)2bqp(`;?@1@! zYG$Ncdri`P+YRLo7@!-~wM(qszyETqg@g_JA`YsmG}$cT@zGRQ{TFvGxscM`M>ohEHV>gE%* zHXqZ5>ER?&jt!4fB0b2z4%r=af1cTA=un3zSlggBJj}34&z(sZ>Hz0=ZB$aOm4a0c z+0`c0F*CC#Dg}{4BA$>$tI562Pk(gREi&+RodZZ|xkfg{Fne@x9cA@SZ z&>8_9PsB=9p-eXGqG_L?`Y8Qj9M~psA#z0)sEe+ZgL53FQs~=P7Sc;#KP(H$WDC9e z?74~0U+6>TChcb`21dJ$66qd5pTuMbQih|zHs3MWk0mh1Op=J&M z2AlpVK>poi5xGP}T6{+(*R{TEMDma^Lqy~Vg=lmh{_952!ra2JJefQy%4A$IQsgL9 zLtr?f9ZXETtc)wx*7Ofxr9An0dOL)P9L1zx3N97bmeOq%T@K3?5l_8DYC{sKZIH=+ zkFdJ9*d1HPdk4$PgAQ3)3g>M*?)X9?i$#gt?>yob9`kT>g{7WVM}(!7g;w&hhimh! z;3Z;6NUnp`V<U+1Uz zUnQ67y;Q&JWd7H3oBvgEslKaa*Ms1H{YX2Pu2+NoE8-}*0pDGE*g{KtD)7Zm2 zjSG^V#%@G9v>&h%uk~!dpWSpS@k_Vd3+$&6@{c_#Opo=HP@sF&UZm{xZ6$->k=*>z~)<#aa*Tzn$aF}bJN?wI^iTMrw` zqYmxO1Tj`OI31BPD`Y3?d>)j|nTB3=n*K)beU`6rWP%N=EG2%;)nob_<4J#G_bK=r zyA%FKnVdjMrGsrbc9HIo$N@BVBO)E>?c{4X%tX2i@f&R+8-Gu}iVpO5+pE}^2-$!- z6sRbg;N5JI@();P)M>n%bd4$_+E8E{#a>y6Wa~F0r8b0=QBWpjG$Iq)n6utH5h*u< zquzmyEmF||+W!ICe>73#0+A>yaxsYh;qE?$!k=X0?2(9^W4e!Tx5KXG#heMc>eWjx zXQ0b}6M(Mt^SlOpg1tyt9s;(>UCn$Hbq!{ zZwX+8;j%KfR8|(1>w>53Gf!DeAB6pFV{yk9ZJx#{DHG~ zc>GJ&;hDl}R6^BECsI%;QYy;zvsjV2V6OheAwwU8{GqW_Mu?{o5xGeszEu*L(~N@G zjC&n&vgWg}%*Maxavb-@NAwt2%s~)1_%^4I&SJjav%`Caq|8|+v6>7fzs$>z!?mv> z-V70osh!_p_5`H7#tNm!s7eZEg@#OA5=P&yS%LAm&kE_K+WdrB0a)BeTYoEZ1m$l8 z5gx>-Qgh0-bsq+X0=j}{)hDP@FSHpJ&Su?37(wbobPh(O;uE3nnBBf`i)CM6%qinN z^V{NbyDJm@c-Hp*E$Gp{DYodg>Eor~?@sBv+RZSOjFKcB8{}VCkb;7gX@L z!fwy9><<-o`vX0mfuB9b+))sn)}?NKmhqvEFbqR`m{0Pddg>V&s-(F%5lq^p;7d>$o_HE1G6!6mm`p7cO27DViHws}_Z^lf1>)iMPj#Sc2s zDOPa-OMqnvK!I4zF#6l}BZ8{5+l+IxKYPJ& zq|Ayi-q9H29c{z;ZGgwl`79HUJreIqyQCT%DrTK)Bog5ZE6+ zO@#oj9`70;Kq`PBA8fWHO;x zBE=odfyk?2*SvhsTZ$`8{mTZ zc_T-Ecju$=Kc}07_lyZyzL6-nhVF3shzVIf83osb=!fYjxMl?p3;Z?_*ca*UAS+7? z>B-VQ40Rl!sw5(_nov+~lt{nYPzDi1g;=>(eeX(+(?zJkC2agT#y=pSVA?zhmd#zt|oO>Cv27J3LtMIktZs2Jx^0k$1N zQT&GO5Q^ZiR*os6aZ16P4P4ZvyAbh3G1-mDW~iEqNf&Y*slI@od5l!wbbp}kBbaQ{ z^MSJah?{If%Ags_xTqY6dGC>em4-e#HUFU~B)Ou#DcH406zcY5TNOjRSAjXe)#=^m z_8;dL?Le-b3;tmvf*))V!Ru=o+q?d{IYx=h3SqJtkzOhIm}%meb6%f;h-ZaF=B<** zyv8<96UQoTc_JuS<8;Szig{l#R>1r;RdfqtPO&g-5IrU_`3R9#8A6()`i~Kr-JFa$ z$Nm!|Wzt=JHdP+MJJ)`8WpK*nTz#bz+F#GgZH$17a~=6N3CL)rZ+Y9feTD=Uj&?YV zNlgjzZ{nf$7ipEqLxo_6hM4NuPYXCnnb+LrY2qca(6XhNR^?N(C};3j3km*eIa8sR z?Fzl5_(Iw?W>TJHs`Cb@^D{x6-)d9mcYTz3d|Z08>#NoIp-i3cTQp9)Fg1ADcLwO< zeT&XvrscjVrY2hJkX?Pk@)+Gv{Jr1Eyj=QG>M>DwB;%N%&uN*L(;4!^5_6{hi;jpa z`sA*4l2El*cJ(bRfb;cp^#?_C$<#V57U5i6)TWP>UES5iP(QfGvSop9vKy1_dchRt zoa}a!?WUFauw`XNq#$8s29NJK)5wU!rl#}%f*jbxL8z?9nQmg9?n;`NSEwIdz_gub zJ?ZhLu=^Dvas-opq}=9!ggu^5PuQFK&$q|O$`X;;XRAaxV0f3N;M>41p)QA>f?}lz zpb#n33z1S;LVKi2ScLaH**N>T0TzOfNx7Woe2`mB`A2rI<`DJvEu? zl1!O8MBnZ+Id+*MaN8oDX{cI@&QAD|A@O3SB#mjwh!WsH2w_ zsxyDjZa4M!><)V-r7u7G{%u;SNVi(;FW`{Br*q-W5N6slvbvx$m@}z98yT(o7${L@ z9eP{2)Y%Nd_cmZk%VUDan~=F7wR(HqO-eZ$Pu z=qO8#4(T^b$|8rPED^E4e`NI;C|Db=4CY*0?+NLbV1Iw-!tcrCXmV5|hue~mA=^15 zQNcCZ7zeTH2^6qIJW}ZtN<1N9Sfv96b6@Ex;OMDp-##G=)?*Dg8Tu8>ZG_f?VpAO~ zpVq1F{$1P_0w&%ZH|*`_XSDw_Yp;HOll{6Czf09G5b1$y@{m&DoZX82q5Oms5$5mK zn=$EMOLsc8?>WZOK-XGKy@D}4x34YWQ1GmZ!alg0^LfUFL-wd&u3-5i>nFz3o=@FY z)Mubz?)~&yuu5i|xf5Txe?NrDF--b|)r&+NtQ|&IFe0^4s@c^RV#Vjwv+3Hs2I%<0 zn0Oqra!av;0{c@)J0u+dlA{(#-Xjo@SJVaA2eGY)B^CE&TkS+cNR9t`3Bs*9=f&ZY~&6dL>}{ zl_N6gl3ec!PtRlN^Y&qOGMCvS4se+r1DDw(q0hj|gklIuW%+-NbSv`~J0KP%8~gin z77k$yth9gqE{Sv{Nm=Pv8Ry-&;^g^B|4y8r?1O0ka4P5Lh~mui^Oj;!rl)yj4#(l3 zR4mHM9S$=fB-KaOW%|f$4u#HyL&1jFrJ^1rtZb#|91+hdL?QZ35Xn*03fz$Df^sv+ z<(6WH_3(7Em;bWgFcywt5*MJawq|ldCAl&A3bZDw?7EH!PeIBa*=a_EnDsSTosSqM z?`oA_QyOMUaiRJ^G*y>r{(JykraybZk0jES87UKy5kq^}|WrYOg~K%01xfaiTG^S4gg1-aU-a!R8M;vfx}~dzp|*ZoW*Y zBEQS~Dg<}?C+y@H#$pyYp|036RblcTL|M!U#aei;11mF~h{z#1_}DO+o-a^HSR%8R zAu_98cc!k7Jm{+%5K9b`Heq#z*u;BBVr7OCx#W=dJZ-NHUxHlG?}fkyj^mnmM0}0( zo{I|gytxfHxM-L}4$*NiL;MxUUmN1Q&y|H(e7&$*%H^&flIKIn2w~Sc-rz~dgCFOly#X{?Ic7lr}&-x^ha!K(uXhZuA zLndAN88Ydz@0S@FtWqL_^<+6cTXFbM4(7Mob9&k(VP!84A1cRw16-1K7*f$D{c_p0 zaZ#>BHtAy|5|Q$wmevkl^e#l+)dx>u9^Nh{$&ymMlLGzoJi_YPq8pO*HUO5J?UWTy zp|+M|T*Qj62`MuiZhF7zI5^orMPa1WHp_vS?*SB~3hHf8vyoJb;NHyHh)f~6E{kO$ zyCFe(7Zp`wqf`{tMnU3H2knMRyER~;Zd=mz--SpA1(m<1B1!Tvxz_4-FK_Smfkd~+ z6%hh&@*Jnp%>#GnFk0dXdCI;_zQ4~CDI!IXvLO{a5ZMTiHyn+b6+*5LyjN+t2FvG? zTpg(+{E$nI5aM4y5CS_Pl3|1IJ}S+{sZOa}tlU!Ulw2S9rr_W$#lsNUVSfGN;zHlu zGF6mbfWs(K7Mt53tR8Ze`}!fJ!ZTstStz)KN3Kpp`hENLK`h>EgFCjK7oG`~M%=>c z_3pRmHaSJ`s7<_3H`*|ax(z~LlwlZJB^AWLE^nno+9dLUL_AT6%xaX#>=kO>VyffJ zULh&78g0wxnXvw%DJ1l{>Pl!oy(bLge|WuKazz)60H^mhFrd24mqe%ChxHls_sL+% z=>SX4mDcb2WtQO4_bCJ}qYJI|1WSePV%O*EL#0TM?qt+95B3CQpQWlLeNfzr)wwP;lM4k8MtLypNkuMxFJPf5pL*X z^fUjZ?*ec+aD1Fv9gG|5RnNxL^K&sV5a~w#{=(`zk>3!7Vf6OHmzV2~1AAUT!pe7089gAcq~Fs|aKK(kzZ6!sp|Ys<8f3>B z6~glG!$~kxl$EJYS-E9WCk~Fd9yMQFw&}UMA}_ZhVPzC&kD3-7mxal8oPC=ElMcjh z#M#oMy|QxGq#l`Xl}Vo*oKS$sCY&uzP*J#T2oATMi^E|T4z~|M;ns6y{xBk2QMlbD z@g11ogu>w>iEl-Guf+EveiP!~Md6kr%paEcjp&V;6%AL8f8^s|Az|hFn15FiR_?_7 zE{W_$;e%I7WxJ8EvJ>&!5#Y%yQCTMvR)#g;UT$94wc_o^R{!F!SXenI*%Kzmv9MB_ z)Pt4V9O!N9`LM9kJE@Z@RbzLcaQj)f`L;Q~xv_l*-hj)ZI2^i6;v*6tLSrK+9KHbY zhY^3A&g$Q7v%N88wl}8Cc8iASdH-f&P;0CUu`*@SPFe9z>ZC6-f)!~}bVe}eDk(U` zMPGy}mvzX(%1sj4E|tB5!`hX&>@fX8hQjPu%4J(*VWm#rK?w7`(}L$YC0u~lUnct0!t;oMWgh*{fBDGOZnSs_?4`b(((kXi7A&PINa@R!1Oyz-zqQvh+;n2A< zADOO56H5`1n=v23;m}AVtZbJ^8xmG_OJ$vOx1}vgsAQ2S<~t=S53QpS*$FL$m0PDP z-igkc+0sN#<~L%#OXfe7`Arh}0Eb&gAo}@z%(uz>x|!MDiG{Rvxunbs$^22wAC>t7 zINWk64zIgZ<~vZf+$`~jF`@mSaCijf-;w#xvA?}Sa@9tJz~vMVlx;(6ZEtx8E~7ix zmGpaITlE_BZ-A3q+Z$V`p zNLaZQm2G6g#6H=Dson0~^BXw}M7JWil_`_@!XIaA_nj~d)SOs30mB=03#$c0;;7?* zTUb3})MR0`canj^pEywdMidju<|f{9&(rs;4ocOx?fGyxo_uaF#pZ+3l&_7yJw#}X8Y}@p0)weT!eXRrd zPwOq+Uwt`?D(}}+{RtHR<&&A2VKh0p{m1fOS{D2zB2pGP)t>$_&S;u>+9} zpr%JGHGKn9(L2&q^cjV=L@wfMq(>+svm-XW{I@ya)XF!VTE{^z$Kcf3AUxYDldYCs zp52VVXfDcf}6=Fro_=8A5^ z!pfs4e6Sq(`}t}NZmpuQR!>!KqXYpUif@H> zq~9Y@@1YNHVLhpCOSDo%6$pY^SPchz|QO*-j4%WkM$y zL}IZ1pD>V8DI(%&mXsej%XT5+Yhv$XR%mX6O!}>m!i}6sK|-~)IA1*i6~&RO%X^Ks zDrt|9TpLV%EyCWvKdG-B27Rqd2!KD{74}UABDx83;7ji%W)eiRL=MPgvs(9q0!Y7> zlvyFF0?XuM^A%^6g{Z0&((|Z(SQet1^E2Vnu&{a)oC1R9eWot0PRWj`P)1anMcmYN}J;g_PRHuhy%hoTUKA`RX5IV}n!_(f(>a{ix*A zdly?zZtBv%Pt&F8t%SNK?cJThx}!?j9Q_f=6)}}Q7A88;>|3r~WH5#AaEiircmRbj#l8P#w_%)I-y7OM@rL6+;=q+U4yy5Ai>F%t;z1HI0HzpfSt80+IeMP0wMj7mUru3uTy#`XoBa+Qd?P5Z8+J$yI`h{g1^oM907RJtqk*Lu&_2Fv$ngYf)IgSaKa+Z~+K?B9A^|noB$Md?to5(t(t0JD1uk zX8yc>Lz;g8)|_%?GQR;neDnNQn+}x6bf99>W#jM5ULXL2si!Q41Dox!;r)NhRDxz~{+ihE zq<3;0V^5Y{p9@b<1fA!YL{zqW4raM~U&8LWx+`_}{M=7>&mTA-Au${KPq0v(X%ab* z7Vq^>*&jU-EB~%Bk$xIJEvgC5AgTSOI~yz?MR9@ew#b76TaC_N*yOfdyKw+Tr!SF5cS@Vf zH;#@>(|O)vI?p~+=Q*T1)KAZ0x}oc!EKEHpyY?--Tn>CG1pX5$P^2ER&pnwuWIbh{ zX7@S78WYeTW(Ioh3+-uLQ^;VsI}ooky0Q5Zme`lnYgj;OT(~&LYo~d&S}}X zEZ!xBZvc!*_c)L;RYb1Vg(4zXBY&#{le-<-Y*1h?!sLBnr?aUU&>-HS;(4j;-g{38k_@WY#BMCzHgsH~(vKPFW zNbyDWtg_Iw;0SeEa7fQIGESWq9H%0Gn*)(O(%Ah%-G9RF)82!gG*)mNw_p*bdfQHU zYy|sz3Ku+x!iTbv(T>S+?EkoLMlfd!h{xC#+`UsK8*%ps(}FoF@`pM-WxJB{Gg%O) z?Akk75T#w6lZ9bJc1{+CP1)Ir{jGhn>jU3j$+gv&E0It2^Ci9&_Pfd+o`2XK{<<>L*^?2pJS5xuI>hQlcUb%YsspFOX zHUEoO{>|~qd!Hroio?u~mH;ag;Sun=Z2VcE=+770{o*-8oyM z`)7K6GNi1HWHBiog2KKSYl+c=b+OFMC z|4A;0?LKHb-)b9YZSQ4m?@ej@N7fcuZTnfYsy zRi~|eY@qht3sTyv3zF@-25R4)+P>M={@_6EpG$3DZ)<-b@w_5?-a_@^1-9os{rZCc z;p{W?2x8(Pku_8*)Uy`E4HR6{L&4Mcs2~Q{MCso$NDk1FP+jXTNqH&6SyJR1q)$5i z`wzD6-wYkCq5Y}PK28PvrACh9^bzUuSo3(?plZl9RcIkZ2s$XXtMu zWlaMIYpQ{>uc-^*miO0W-p}z3?^kNxZ}CH@z4D>toto#voo>_z&jtTV)BJDNe{`hT ze+6oK}c>{^wi$J5hV3GueO7WAuc$Qye&HDnFSyW6PDYzSPbg**9Q) zH?v-5wI~N-K36Kj@+PjXeJpNd>`xCpM%TyZ^by--3dchqGm~36{-O zkHrl=l=8q!&+0Q+lO}!FK-C>LTj%pxe=yJI%SNC4eC~XOozITZ_VfAgk7k_D%2X$u z(MF-w|D0E>^Z)#l_g`W5-*kS;`Jd7M%|I*-l!xacAo1%0f*_X9*JAPcBV`&e5uE`X zh{P>=%0hasdlg@{K~koPSmBW?>dnIhJM=R#$w#iZHxDarhn`y&LS*X{Vf8d8a&>tt zCFNF8A~%VWa<^Ev3%jlso^8cs#0QcxQX<1K{Bo;9A~!kYz&39V{bGu+`c~(Z`kS1{ z)s2KHaZlX_q3$JyL4>+rWpSLRF61j}b31wMCqV6B>1RkR+lE}c@JtJ^X(&h(R^RBP z-$1#wx^2GcZ52+w&F$on@?8f~u0rH-2MWZzIf%>E;X&@?il z4Uxf!d{;z@1G%;$VM-6Msw*%@gO@$wK2;v= z(R%}(cXs)A9f*kL5GRXBp{x75@Gl)=78~M_E=1f8V7ezQdN!2HbBn_2`Ob>^$DQ!J zlbt*aQ5l8^yVciq$U{Aq>j1t6zAg%IQ02c54Ijw>arI z5ox0n{!E3lEsOVlj+7Z9eKEcdfe%>`k!z#(OnS@v;n^bkot8h@{vQ4Zxyq~pz$v2a zV5006*?`?JPzM|6h|Yv0)88EWV&p3G<|6WrJ`O3jS|aCQB1gNZVqI)QE{E`J3)RjL znc+a>aSY%FoLI)!Xi+bk+yU4dk6gDtN%Wx?;*O11{iRdm&)d$XGk zYy=wP2}!QK-YJl9WXT)jH%;LS`^(As!X(#TA@JhY(1lfJ(1n$Qk@c!PlP)ZiFYJ~x zI3X}8Nf@?Y%gy7sxeah#JeMB)2PM)alg;Y$xPXK3p*br8At5lB?y@^`lkBQ{g}QrK z+EPRcE*96`2=O2P=w&&uo<@^Xx2esu%AzW79*C;^VM%$yL5~USH%3+ulSnu6w-2if z=1g+eSBd&0M10K>nHRx+qf_wD%jGzkoUo-KYVo{I=8Q^H~H<- zxqUsW>#V+B#_HNH3sd{0@wL%~mqG09F9$I1I_^)JcgtehR*;c}4z113>dLIUDXgw9 zS*)((|C#Ymr@-$zkbO7F?<$dgi^47!h_zi>>a~UU+nBnkZ&}qFPTnhz3=!})e}D*{IG1p z|Kf-L3-QDE+^2^hpw!7IeNF;Za2-Yy*Hv1{J$BkGv@0)1L#{m8X(yf-r6(j*IWf0 zP}iCqKt>B{Z#zT}@Ud;kwOx4XH;lxAVt_oPOc(VW6r9c@B1duidT98@=ZR>*Nc9DX z4`Eju7N)jQ(eQ5&=zi<(8RdR!6upa3snK)wi}k(0R~m?UhXSoU4Ca;VAUi3lo^cyJ z7Va16nJbY?>6m5ysJktvm_uYIn+h9`@E-NN&wB^5*QdPStKj{fAFC{3Vp6WYa%ITLK*x$KuhDE?; ztdq$8|A)MPkB_2A7sm0PT*wdzHBrD(PzMQ`AY!7R83DG}0wFV~;D8rUl#3$t&tu)LyM9WkqiYF`8ODRz-n=9mHM%pLvhF^)TLU)^98Jm+J1 zCU3-fmLz`fPj|5I4X}SAMn*glGUCBP4MMr;+8r)= zmDwfNaA|TVR_aVVN1rx<%aEIdxD2V(o7A+;y*wu#Ta+znfX#Jg5F8IN+3}j|h6q@x zvw|tzbD8Mvu<~zK=-3ow|)TOuc)OFd%2gC=MKfrtu zgu*V7v8j8^n9K@kBWe=sx7$NJw-dt=k$frIFL9SLnnCt5hI4UBeX(s=7NKa_X${q^ zk>te|(e7dDg!_~z&$NklmkoKJ1=d|{#y-D<$}|a;eJy&Y<_Vs1Ubn#0)=SyjnBb&p zxEXn|Qn>CcD1*!H@Dja$I7}&&=#^)Mj8gHIg!*OSLddrhuMZ!-lv0|SpN)JWk}oxs zT)+1yXomMf>D?{7NOIfKgUf!KP{X&{9ClDjQ*a<|kBn5rqN8@-%6UzePPJlOV@`PE zttlL1fckW&MAC=WXTDxDOlV|KnFN9LHWFFVQ2`T`A(}N*hSo3gYqKS}&Me9I=}Hw= z>f0)m3De7(7WuWS_(oW6O5O<3cYEW>A=yS)#MHN7d?(~zJ46r}A6#a}$}GRy-Nfdl z!x7m6Bdiapk;)#*ScWZ9YBhN-XB4wPbk%-s9#%4URu2=x3U~z8*|2<9ej=oK)61Hw z{n|th={DH13E4GoNd(o%V+o+@WnJs9VW6(c7v*Jz0ISpler{0ng~NJtWe>&5jC}0d zgO$v(>R|##&bAcKaI8$bsd|{8w(sbr3>D-)N&zo3N3jOVCA9W9M z**&&plSJ7iNaToQp9qI7D;T=Z#w3_pKYkMkgg(FLv~~;fZs0k5dGg>lg?|1_Ob=jE z^A@(jeLFqJ!~ez0OvUuON(;89VG?qmmh4MywU=Y%Cbrc?RQ8F8%C?B)6G<)xk%1x~ zQzjuiS`T#hT*`Fb|BS~=C+@E%*ne9j`x4vo!^oS?)AyQ@3}`C-_nrxH$uv{I2k(j zcTi&_vLuBH#S0oT>E7peXJKLzM17DBd9XiPim6L z{_x9vlqUK^G??dvpKhddfc&%oXN3jjX36C?Qel(iRc1H}5WUpI>*yG%)-BGWgD(5w zWuqn17aq!;-PF4d@galj^Wo(Ok+(;PyFLH7Dkh~i^_f-4I;;B3IlP%y{||UGC+DW; z2Q56aBStrMX=b(N8%9SuM0=NrD!L^5AtsIOQ$O59sY_mFVWjM0etst^cUqX}Nj_B{ z9d3j}c)~HMN)zp^u$oVBrb>^nh!92xp zsSRX{QXauD2nWjbGnAXy!(wE~M!7TcQEnOz+@wD#!T}TC%C#lD(0wV!0f&AL<6!M7 zv3#o)liRE0M{J~SF81wo-;9;IO6+a3FmfTuw_{Pcjf%dVOoxP$VypkSX=za2HdK}V3U-Mos#Y(1kKF`l9 zk}RxDetteA{JAsO3yGg6Iv~@pHUx^iQ?;+8hf2x=7D=fqk(B!uVC5YKl6t4WeOTG= z4a+EH^4ja%uTN$4h^ZA#6f~EkVh@G;ZWUCQFGMbtxxe9P5!X+d zFz$=ErvSmPFiWIMvUhqe(27(1xw>8UF1JlmRwT;DJ`v>cxbBMODWFrtmC>JxiTU9S zeb}Pw!?6f(Q;}N&aM3F-aeGM9T9aqxPy|^(^ku)#6V^mtgLZ zE&Mny;6EJerIK8`g3ZW+{$7cfL2tE{;CxH~AyOR+X$4bL^G(S26d;Ag#7l)GtPA-6 zR>bCSZOZ&@tVo`}S1Q>2rOf}@inzb)a%%Xy#`<_9*2hln|H}FZ05;xT!S!ffDhwR> z;|SuY=%ESut#5-Oy@ryVSJ6ZJ%cGATZ3Ui9SK9?o0poq-6qcP9EdK+1NXd4Iw7E!7 zByH-+_e=tDKG$sWT;k}+5*!^B#ZZ*w(RS8HlHOEfW>i-qop{3r^#yt21~sh)qs5zR zP=nJi73_E4f!n&%@!Q9b@qduU*S-Ti@nV)B;0HddVg&e_H+v~IZDtLFHRvIyzXmaR2|^7z?swTwqsGCkmv{cizWahaQ6lwgB;r}8RbY8zF&H{L z>o9q~gi@;Jlr!PcXM=L@&ed3{U#(u4o!Gnv^ zD(<{Ob=XQu|CMj#w}sz^EJM|y8nndeKZeO?Y?3y+$T6{Cuh`a?E}>UXxRe@G9A!lN z$LNWsOhLc}y8&OAM4${6B>MpgRUE)?&vEZ?UNFaP!uFtqO22|6PmmLgHM|2%OabwM zGga#0*L$gpbcY{@aTzeMMQg|8Gl^(Y!PmI0mwn+gNvTVMVHbKLBU2Ehg8j)bL?u)a zO@*Nc_Vi0>42E6kiBJZEp+kItR;l*^44vVp(gdN%FFx>T6;_5?#0O4SVN-`BSBE${ zpxg|LD6h=R$7H3&VjxW%B~XK8v2j#Dxn&kBd$)wWI}k3c%v(^>w9=BaP$*Zjl(43S zO!o5ntJrSpVE^qF?O&qC$sk8Mn`=I;&kp=rvuIR^dWeAg7L+lMd4wQrhD8N?P-E?dBDfAHDeF{BPsh&a& zx3d4l-PqgKjFrk}$Po0o=a&qwtu^SOS#0<3s6h?v$3w0bzWWay- zuf2&e>NjC$D;wD#wPX;4P>S}wZl_D}G`r+#zsq;fy<3!>L5Uoe?E5_zXl?!Z^7_IlAJQq>_o7Cj zm(tjo+z}WO#1pSb|bvzi=D(nyA86%5N}GHM`=WaOZ1WFb~&0FL?f3DOtNW&egd z@^T#8sl$5;HQe5e1EqjU$Wqdba!Z@Bj9W38!SJjy5zlV-<3MRhf76e0OZ`~JAxvg4 ze5*{rH{9JcgW+2V!#B)OZ3g?VbT{^HZpI33#v~}&4|pEcS<6E%zX7OUo75k_JVEuN z={*#a=M(X3e>&r(UrP3`-A+-N)9jKxekQo+_@&E(1K?LzKm77cXZYnJ-)QF#08$K{ z815ya6l!!u8JRtwhR#C_py(xTNH>D~n>7(lXf2CB-Ea`)YdDbKFJq?3lmAsNT zAs?m*f_Al509Eyq=jsjiD1*1@QXjvuhiZc~fp-bSnXypF=;!mhM=}220!&t7b87$2 zlgpaTys?ME8PK86q7*CeffRY0t(QbjK{HYxR7c;)$ikmE!{4V~l?FwAT=vuMzqyp^ zW*1vtA9a7hmyAmGZg)T=dzr4U=d0f>*?Zm1SgA@}uPxKQ=X@Kjuc*4AyvpNl^rOZ< znfNh(X(q3HjB?YBqi-~Os{`c@6LlR?lJBzuPrC^6V%1r(Tx!$F)bQ{TID=uk2X+#$ zY-K^>{w`uL?Q8VAB}uNef@8=9;19!k0c5-+d{#d}O2J3exF7mkk=WmXsjNTHW7Bb< z)R19@q1++y!~5Jp2KXqq)QSV8hU{{S73I#bigI~ACZ+iflv{2U1LgYD_2rdKrHp=* z7qVANQ0|Nplv`TZQCelvmWlFoiQH#X=T7aR-0dSv3{>!suqm^YTiM4F`o1NhZ%cV0 z>x%tgeU=zs(=NesomC>WHZ^N1+sku8Sg8-G7YTyUQCcOWo&*o1|Hlk4dOi)(&4gb) z<`85NhSA!2iTVGJy6k7&4KDe?Jk{m<*6m`#Tql#Z?5gKNAU4V8dAlXM=C-Eb+pH-J z-{AadWuEFH59W2MjwwCVr97C|;)s;x`AzO;*t3v2p1sdQ2#% zuo)}P-G(X9Wk2J-QX*aP{1xPoS_P+P?Uh)r-;KS2N=)i^yXB6LrO+ZQP z2uRJJ(nm!S&@6BuQNK>*#Vl&gaNOH-mcrS?(odqP`PwVFF_>GEBxSjUX>pzrA|zu> zE=V@pCC|5t@^W5?EC(xfxur@*UQ?+>D}p+r-ZP!GbBy|9O1(+Ftl6+{+4!;k0~U$g zXT`E71Qw{T)XGsq7`|8JqukPbtke~Y-axTL`qbG=7`5wvFxjQLf^b^shzv4pv%ST< zrq-`Mj?z^7Bewxon6W(5BFRNqwu<(>p5d{XLzfCJ(kI&YxsST!RVpK-Q$@MFQ#VWw z(Z;RO?UB|Ld!(;8hR>^17g^P*))q5tUe)4=l>1HYW>H=hQtx4JJ^wxSczyDu<8JQwHCHMEJhBJ_cWd>LT+y z)sL=c@Xc>=L@GFZ4I%Yi_SWl)+AUTlQ|2S6tms~dgk>Ik~DYhLe7QKC@ z<;bNtsWjFZ)UFNBkNIo*CA+%xGTmQO8XS)2G5Ag-A0F7^uZ>EjhrIM%W0)UmbAQcJ2ZL%j9_wtC?0)y8@cS`;O+7z^0S{_i z2fms{jtD`r`;qTC5E5^<=zdqE4a&`6d4`nQ zPs(-NFzEv1yA7N(H(`6ob0j<}opEc1f2?H=6yxnhIdZ-u zAqHFHJV^Q5F0pN{+^u_Oj(jneDhK!$nFAGtxp$_gMg24_mLn&akR#_uW;YK*b{y5n zj`J7UwOuslTdD zHh>(i>+iJZ?TyuM-`(F~Z}SOn4xEH<;fB>J{MUXvgmvq`(0 z{gCWOmR^iWNY8eo*KQZPzSFYU4@cK`V5R4^+YPt1JHS^~9t56iH)1kLuiVb7wzKsW zecNK$OjJFaNg@@9SsT7Hs`3t!NU=!EQ;YJ(>+wFnhs)`i+oSZH_SOG4{v(^#eZT+6 z$@Bkv{YP$E_s{x|%srp`k2Lvvsp|Eo_>Wvu#4Q!?eUR!uf|bl|%k=nb=|J?H@z>4# zB{ly*G~p!q^TO2lYds&a++e{zn&M9)$=9pRg#d}m7x8o^`;HEV9LG(C@f^nkrv z=dZzIok6CW&2`C(1g0O%7G&x_o|jxhU5&LhqNzCiUmJvF!2hYZJV^ zre*I)_U@${1}uvGqVC$N{mxnREfWfo-6THvfUQbV90}y<>Je^fFslbZeXp~rO+yoX zHs71rLpKlPuclYp@HSWl)c7I9TCB3TeAF|=P!UD>PVUI?l8{&h*Y+?95lOk(aEfMSx+U!0Y!Q`Pz;w&Ka_*$q_bE5s z8t%WFu$}_CpZhO^kqq6$WzCed4ypFSDwi+fF2i!^+?ajtsvlvW`(^^S&(&2)q;{_Q z>4caq?FY?r*&l&fu8?hi2bin^rM9@uO`gz0Bc*1O=jH?}TT1?m2{C)yyD7FZ*Mwwy z+cXB}``{iNH;m;^IEOw9nE9QdD{x!tjWJvhD^#Bz-$Pf|*#!3^l3Z(Mn6!j#3LPzHY7fWq11%UI zx0f#KZ!ZBF&0QOBW>tqbq2aNWay#31L_W8yM8gG9$Zx4t% zxxdl>dL8oX3wme*e&)yebiW_Vt#k+F3V@*tPk#>F$_>9YosGmVK#ZLNa4y!8NLjh8cf%+0VGA{!{t1Hhj=awO~RLrYTHLk2$bUNlqx3x_=9e z_>mMglySMvhDwtHNO=CUap&}x*)}ej|7;vL0RL$ocdqkP3kM45!E`K_mgv+kSIbYP zU#a|f);OIX7fYnJL@gi3pto_+zfiq?Tx`mv_>{Y^loZeIRDWr2yDE|D-E5qNJinSp z)8`a>+bywq{W=e#G%V+kFaH009`4NRzrTy}`2G&+`}-Nbzc0%BXV1gcvHjOi_X)>* z%B$4&v2k8#PvC`l{pOp~%Xw!hP3DJ>K@YXIfk}fUl5X;hNx;pdJ@H>#dnwcW_N4?c zO&psVz?8Bd8j2af#gbfGq60j3V0hm+6Nk50B6TI|&dYiXx$XyLz(HGk|K+j07aVwO zw_P@nKOAQJ`(_3t4wM$h_jlf9Njqf3W!#0|nY7z=d82zwY`?Eh+3#PDN#5_<#_0P! z5wg}X1MK(j)n^Ai`Ts3_RK_I3jB~X%1(WA@_faZ(&vYVhFC685jlJ(9tkjv*l}{NF z4QsG>a~dXdR!gM13Cp|v4*e`qgg_gVDSbO)?X0W1k%pzxK#n~ID(ap zB~aGAPn{p{sxa1-Z6GMVoz!WV^f%-%C?>?4T4GIw{!m29Z6?ns(c58z!?ObCI)0eu zY$-$QtJi5ifh3Odvcgz2$shD+l6BhE`~Z)n#iL315gPr4G5Ib06s>xlMCzO23@;*) z9(AHHL?|QsL#iXvZo-P^4;VQ;EoglRBj>DUtZZbEstf)U8$)NGF^2tp0}TI--@qcU zXB$jx_*ea@m!kD%xiW*y`kh>9BD2;?@(QygFR>&yjz#q7QpC+Hr53DY?pQiRz$85aAe!7m zvAmIitrlI}LnF?0CXXiqD`4`hiohzGxIz~J>@XqUui;`Yzj%RNI9K!NnlQ!z01r4+jra2h442g!c)%fSyqiB@`$KiH2hP7`&NrZ4yMke~?rLBPWLmr*@b%f)1~F%1`M4R8frdCFjg?lM+ro<1*Zsr1!( zE^&1>=&OT#pXlMD+WIIpR($#>zT)l{Z7}-=`}rqWhjF9g>+qbh4wg}|b#SlIh5}T! z*iylYe0x#Cim;{9Eby9sXI{b@ZMrC7jjH0W>UYW$R_!+z>8sWV#SL=+R(5$Myi~tN z^<2a&`sS>U_Sa{yGVRl}<5Xq)NI!oTNgt0R_yQRQNrsEc}rCPj4pJ7r6iQ>%Zmk2iNoX1BU$rBt-8QuPl;?NX~q36b~l#ex94gh~z;< zdqn%bWfx1NFKp2Rd7ge9Ym%gnAA5*j{YjdvmHV7 zjZ)65zMNO1pD*$JMvaO2jixhDM&Pl|7RkQfU8LRLuijt`h^Z;{1||D`&lD(o`X>Q*ZNe8#WYt#DyZ6S;9E2 z1zV7%(&j+9vkM(4cP9H)VM#G$OY$PWC_BNJofF#!qaZ%-Ts2=#fK|KGuxdwE3`etf zo)XdcPft0J#bxtYwXrp8*u6ySwkxsn%W)G_ez{J!YxjX&`xdZkZ%?pmS5@@4Yd6pN ze!I43B%2wR{q(Y_kgGPP@5V}ZhdenVIm6z#C_K_62Dru{H4wINNd1HL@|a=IT~o70lB-?Bfp*M{jD4%=>Up5S7e?Eu?szW)SY>shT>P6I3W4L6hF2e=g+HOla?#LO^4 zG;+5Tvi)>rzfH|lml68zNIBmCySP&b+j}7xJuzp5mZOKc%|5?}YUz;BsNSzW@)bY2 zJMgzCHTYx8{m1D)GTAnJ=XAD!N#-5-!vt`p#meL^509`DPG$>w>}%$OgCXMimGgjM zUe4ZDMs%5n33I}au-8aHy|s?gHLQPLjsNLK8Gp>V(#1q1GbWjXq0!_t_%p3`x`}o1 z26S=V$!y&pCsiL?n=a@c@7V$0Bb3sgJ^0XlH345erSt)z!^fnM%nn~MrSu})${s#& z&(dm4e0C-(wBEC{`e9FXts4{Hjg-<39}_be6t6C0lKF`Jqd-4lqMGWsDow!3^Of*k zsE<-}z_+81QuiZEsylq2^nvfa%I}B!D81L?eyGFuEx*r1CmXV4errBXQLfJfo#b+V zeJiCjqbA_HkWyMy*x?%mp88;oL%F4vfR711g0OlzR-Rp_M`e*uRnzB8etb3*zjORE zxFgWmoiE|e^O$X1<;@jffqk}6cV1p|Rhl3v8=KEi+TmO?61Ud6@4fGVd)!MgasD#k zT)Xt%`>H#f&j}sA;8{x3I((tCl#a&l%&%Ttz4TspH73vRILl_yU40KU#l*MkEF0Lq zv&IN~>RHML+r|DK1wga(^F(?ZA0E&`6 z21R8Yie{`lYw6zGmPd8?qL3$T<2rU7@UcJfqpY7G zCTKUEHI%)zXDL<7;O2tZ%@yqC)l3+cpRY7}{hIe$!h0=A>NOoY$d7eU%sMzWjNLTH zZd%#R&xS#-ooDo3xA9*0pMhT4pLnmYKnKAyMhCmkF#Qj1HpgzZvYTGs>l&liw|K9s zd9SOJdYug&EQocmf^~2c+{Ce)RqWRdy$Cv4!#i20-pxCis|Wx1p5~n}l7<72e?LA+*Fb;8TyOkE8dD;z{9-L!2>jwj zxKO!X+X5FMe(`s>Xyq3{xLC(8K8A}Gpei!Jn$#^rdni_>Ed~-hIqNcDAFXM_1a->M zYym&o&ggssD~s2kBm2~*p-c%o1)jTEjHJldCghH~f2f{2>SORvzH4X?)wU+J#|iB( z?$>^Na{E#J+nW>GU)!(!ks(R#_YCRRJ~$-aUhLQY<>dCi>)*a9q5VDm$DiE(uKw+D zLi>6B$DiDORR8wog!T*jk3Tzk{Mr4-pB-<%xc~T*+y4&QV|gQ{l&VTL>>PeXumExk zZp>#7+}W`M3)J{i{s0aw?t%v#UmGj=gKoCpZh{9KcN@$2gZ=D50X*P%+*r&X1la=% zJm5IpIDtQCf&D+2Jy^jv$mp|_hHYngikvr1VIfTr_)m#^9iEtQ)f@h4>?*AApE~nq zcP>ijcVhe3b5sAl>v+p#@OvNil(BYCq=7SYe7>s&v-$3I`KbFJk~}40u5TQy&-HGY z>#GO%P;HxsAm6XxB89Px z=bf!FI@_Lp4#t9f5A%`n&X&PN3P1TWtA{#^zLn&SjHN(-tCCm>@;#IR=XIP?y4gjX zll(plU@0-$rX_I_9+|aXD|x z@DAE$o6gNQdIrV#28A4zGyFtvSELi@-1x3{OXFGy`~O=v&lO#ks`q>Mi!b^ICe_SXLG z-%e@&Qfm9P3GK)AZ~sV2`-Q3Ps}kB@)4#nvrF}sL&!52=%czV5#!{ZZSkf{Q7|RU_ zj3u0&z*r_GFqTky0%N%>fw8=m9%n4R^BDiQkdd`@=`jfpHQs%Ocf=k%k(1H<&f z{%oOUO>F+AjDlAA^LVRg@?rjR=ED3PizLq9g8j+!2kkfW_5mHTJ9ztT_dxrUBRPW4zakeebcKZX{$mPGckK>8F9<@>*4Ir% z{!Y{~B5TAjf#(h?+KRo?-W@$m5Zv|NX*Wi4gp3Ba+ORKMkOhcZS0;};3#NTlQk?z` zmk5IJHdu%sxH(HGL+f3tBhqGaXG^lPTasO!T9&vYEGf<~Rwh6F2Ao}$|Liz@H-j}S z003_tJxqu=Rn85&)!S&47Hx&B!|f$}oUhKO-pWHVg9Ip9PtJL~p%C za2M!D#%>!Au&%H;P;QnZP+=2<)zep86+1|tGSGAEZC{a;+x8qs%n9epYs>k$@@{^v z{5~GM8GCz85~&Y*kf>CcF>$uOlO_m)HW4eO6#F)NGMz;c4KeIk_8YLTLfT&aUCDk5 zJ$^HI(NawIsvo%-W2oj4^mjplg$fHMa28jzRU(W0+7;j*Z5GMUJc-yuT47}ku&gjS ziMEOM576UdAOWG%f(hKk%1|Q76M~ZL4w|uiN6?1JtaZpz7PO!O=Nd4Hv}fwsb0X@* z8Za`2u`mY{H25>4v^DNJrR5au>^c?CA1h~JGOGp4 z86i03Zb`8>!P*et0!k_5Lma@~6mpk1I6PzFJv_zP;=W3&=Jqf9Zm>5QKuiT767sW8 zakhAFaM_nzJuiZS`A6O0#OqtAEB7YZo4QVs5cI#zkQe0oAh$Ptbw8L(B(lIFktJ4% zEU-yrNj}PVu0gpag;;j36G>TK3HQ}4%QK6Cj66OC6<}x@9@_+$CHft>@?&{c z3tQ41VY1sOF0p6D#q6DrPC1Zerp+@(n~==Ul8jF?6OB(NO;BiJlu>A+H+|_atjyp= zCf-jhGO>F?fBRE@=?@f{7;3~-T1C<)+V?KYg9FQm`sBluhR2x%K^30St0(|6i}t?wxf^Im^~MEx=ykzMm_oKWA@KkA#DGA=@poS@ZjAE;g@Xh<+2}Lr;_5A zkRFJMe3eYFBcEdV*(Km7ktULiJc(R}$?y|;l2p_9Be-5~bRNc)z+5z9(X|wdifhw^6F4L-zanpsH=*gSh?a zSpEp5oO-*bFTV^cIXfIDDZVe`QEUp*{T*3D0~My)h4UBJ1S&GC=V`Y++Q(4BGqfYi z9H=lY_B{BY_FzZWut0^$v-p9i{`hxJ&0xRvPY*u65i$c1=H*(viAL=`xEb-)YveL}i%? zd`j!rs29fDujam#O9pZ!U9cE@DcLjbOL?FUd?|U=;AiIp$*VMB^6Xsx(~{an=5Z0+ z^_pgwvFzh-DbS9T4#s4L1(VyY5%{{vGaYsbjyPL5X8Tps=_tiY=3^7M&!6&u%@N5m zd9D-X3X4dbP(lK-HHKGn_r}%g_EY-4YK49EE?l;lJg;i&jiep1{4Qg7eixf|y+js; zxc6{7L_mC#PzP)3&x|PaLSB>O0h>hb%a`OuJj)9tjhO!l(~9bf9SM=|u_$zHHjjK? zW=RY@FUH=@c0KU?-;$jpx84hZ=U5Ls2k-urz;pGxkHL!5l$`04;fR|3ST9e)WqPca zs%IYU<+~n4gzpbr|a? z9u+`O00uNyaEIDbGk;)J51mMifVaL7J*R(vK2J$dhSpDneENgfVlYB*T-7WgV1HY{ zeSf{}`N?bVSBI_c9U#8MnD63()cO8>XVQHCdne3yae3-|FYDy&=x^&1=Y4Kxl*Z0a zbYDyFDw`SkUga^odVo10oTeY@u~kT^@t z+OU2JfQt2K6D|;3^$qY_tV~{h8_?X4dh-k>5G=DviU%TZHgxNvh9{)gm01y`luHA9 zr-C$a!CB68FFh2c>iwN(ArXYL)#N!p;tZKQqZz**&-(huld!jf>WJfP2Zc=TgIKQL zuMRp6Ox?XFwol*qhHs=_JlQ`#M8f>{c^hmQ9-aup=XWDfzSG)okocf6$X)yNK~~?K zJjhSFQV02~Zex(qDKN-u&hSCr@J;lbcy>b|Ea_6s&-7B?PSki^8X#^sjZ1%y)vGLm13eSKO6D(iu!)@9 za>;RuQCX*`%+63U&TC2sLJ{1SE!@;mHYHOC-<}pryMP*3!NoGG=PPKq3Du9-%0Ydpj_nMBjBADPPCf-~9ZvsM zV%I*Ypc8w$&u_R%B2nz!YQkvaR__V_!mT?p1mV%PT)RnV3lGK0h_c%{sWfHkd*06k zC~#SCN!Ui=m2idvF-o5ECDK(!`qY!0^MpSYjAz++S~TrhVd-`F?RP)9SGeuS zMd+=JTWcI-5MH=RIPhJjSP&2w26oilXU1*n)#$C^jv5EKGi{;2JKv(`Yl%o?4e^}pl-Mzw5jJC&jvl_u%+V(y!cpBU>IOMHU~>&$%~ zI6Se1?NOJ!pDjqH-i~x3#W69ltGaV^b;$FkwuRG!;{66aIQZ~!9xyShJVpDXME8C@}=|mJv|9x!iFc{Na`8R#=>y1rh(()zJ9n^at>VN zEf1*^8rbx;iKK(Act4!f%#z}H4=XNzKeSXbOK$0;96Kjf){r8+a3@F3UE;!B9666% z&7VD-ws0rMP4J;UzdLoH)d!Gvjfq`pY+% zpznigxkQy4GlPAUdiQ6+-2M&@TRp8<$*js}8x&hHQFvpX`Pb_&!2|+~BxPeOJjnd! z#T-4l2JEO2Uw6zsz)UGs7afX%hp7i5t0v#VdiHjhb+FW@e$Ds(sd}j{{5w1%1NGck8$u* zwdS}ntLi-tO66J`R+vD)PYoS24wV2te)JJQw9u?+K|b{^DeBdTE$)i%VHtsh5PVWdF@| z1j?6~xx;`&4yp47^-I4gl6J194i@EAbJetid`+{PdqG`oXY%zpzOZc6mpv2J?~{G% zn}6;FpW{Uh1H`9s`z}mGrZg@-0m?lqj7iX^=g=PvJgcxoDk=?7mVeDbY4|gsS5*QO z&;2T{5pm&c{GWU2!1`BHtoN))MG4ofD%Fd=PSmMJ|9QZAp3oi-*#7gc`09W4U%d(a zw0{-nmn0;~GYciTqRM3t)@Dg$W|fNs9ppV6*u)mr;r+_$9^&mbd9oee9;+v#$UkSZ z%jb6wh0lzXV`WN6NH4l5&s3MK-w#KKJ?EVQ+Vu+seAw9BDIq ztP%<0D=YHZs~2i55(%+iNc%4=S6K0t6&7sjT=84czG>w%Oij5c(q?vNLH;MVH_~Qt z4|e&sqDBv;ls!RMo^641=Gj(>RM^-XL-2h;oIW!jlbMB>Yzm8%(zyLO3u+3IPm6ZW zq5J#CE6NpxSe{vh?QOMLm{e3@($>l*B2qEe>>iEf**0u{k3E`cgL-H)t=PV!HXW@u zr9>N^yFV|ReV0mV-Xy4|}mE_v0@D2gglkhN;AUNKIah1-s z@RIt(^D&l7^Wn@=uC2mKT?r=j!J>%ztA&i4%qU?4_I}le>3fmV5>x9)Mj4QElU@e* zcC2NQ_jVlde${|U2QK(@Sq{_higv2^-QP>Kiz96&&rqz)a45rtrrS$2GnQvmVp57b zGE4%Noqn-ki&)Ts*3T#bb32wxE3rHSYgt$+b>JOg+4C_3@i7=@6pN-U5_zCdG0Gn>QU)PFRjFlQ<#vZ?`WTbjEj(Let&L5|C76^JI+{E}8Cu_0 z29=l-g_jbvJ_1!&OBV3Glkkx4$0VRW@JW=a>vu(|*7m^w^_I@qV)R5(mZ#E_Uq7Ep zPq17!SG{5%rzcnc5$K6|jLxpeK2`d6&Z-W+(3?V6PVS8+=hpx%SFtiW3oAKpfa6vx zCd0ENWm1;t?O1`mZ6%mUSt}%EYL@5?Sg?|l0T8uW*nLZ+EGq`nul917e)j^v1pVnS zwLS$fCBRbtLaMx%3eUkye;hpS=gt97x(?3}4iEIF!;{b9QT=~NoulnvM$eI7MbEdS zEH7a#Ywqu*I8a)}IGkKMx7qBzDgh;LkD=u43?;E?2PQMB7-nH|yA_iewq^@z%wXc; z`qC2EG;%FwI^K?>l2YfukNu)>1;F~E8KHUrsD|MAvF2!0p z-l0mSZi&D+YpJrdcE+tf?l6{7NsJV6jv;|-aDAb_Qr1evN*utOha zTlf+%+3vp-7X(F9KzuYnDQyr7+QmoPO@gqR_3rW=bZ3{5{h}$rE|U`weZTx~^LCru zOF%xIoR%PB|B{K=W79whaQ_4pfDv&8U}EO_{F4+tmZmEJ>+%f+pwlD>OwjK{v$viU z(fIA4Dfm7ENq#Epbh|FMhbR7D3GkC|{s960;5!2d@DD|3V%$pMo@4=j^`C#F0RNlO zKU#p#`|bBj%76WwZ>u+c58Fx^oh&JDdy)$i)xZBf0shYmLEaNa|7ZbTS^NE9jnKim zn1dA=l?>K(Px2kV{dq%xZ~V{@;Q#a8xB&nA$w>k{`g#BX{=Kga0lp9vkP!P0 zP?7+@={rhO1^C6E@#z`l`5^(m?6Uy`_^Url5a2htV*>oH4|%t*x>L#5_wJ_*_xZ3@ zn6?UAC2UVba(@z%7ydAkS62K0lGD~WlCLw6{K->ENIqkCl*S*os8cwSuZttOKLN@A zC;;frmXj#g$x!{T7shakck#S6j#E~^sW)3VPT7AQ!>Ja)sm>TqLE4zMT^wn){tj^J zg$rXi1>vV(J;5ja=fCTv420HmAp3?IK=$*K0h5$B`vJC52W;K5-w#;+E{^Pl9I(MD zfQe6VxDWh?f$YEez(DqI1IJ_Wv#(u~gzT5?H;{c@9NE9zZyMR0!)(;h}q1ZLVcI!!eu{WCOwqtKJ!&8UWo4s3Y-l*HN1g*y= z_`TFK53R>(@Z005LhEsQ3x87Wo~~h|NsVV(tjWEeqF9p$J>yst_+9I{5UnrC@CI$( z?rKj?k-wi=<-~i&DybQr+^jOJ$XKFQHsprAF{_HcKGXIY>+{FUV12&OgU1iPuTOf4 zRR!YHmgrWMeIF-TRYD)ftSb6kuX>-)^_@$i1D?-$kK&lkF3fFqqIZ==K#gD!m6usD zqa?5Ox7d+=>Z3qWR#^qq__cms@UDhQ0#6fu^wG!r6i>89`)`f)-TZT89dpYxHx2qu)@<>r9kdmcF2$SyUJY zWzB$&!H=R;d%mBgFEOJ%U$N<1je~D;o$mhg)2m|#-(dUs;0t5P*60V{Pkw1EStrQc zBMJ`igYTmEqE!1S9C`awynb%w{QsjQub(j=8J;`W=!e}OZsj}w&x>`FnjdWT^&$1U zoe4I3E8#e@dU5J`50)>*a)rex(D?RWUgrOJLC+IM};aE_L)$(G-}W44sFSj3Cr2Y~r|r$tGUE zQg(G?a&xx>SzId0y;;THO{xRsI#n^?>;?<2;!;Jj4ckBS>=floMEMr8NJfgJ-0UK& zEbR7J?AzlmjY;}3GuZweY`RW}_Py>eCFNl?;^6rwAL&-N?1(}=z(KKoe0w|_Qx2Te z4|kqDC%?VpcHH{1F;6m*9 zxUDZ8qgPL2W$1OW8kxFRT_(0~mr&_`CQFZo=1e=kS;_c@8y}~ZsGFwuQZ22>KSP<+ zfR*8$e3pj>MR}D4la-yie@R9sKW2;7`NB#@Cu}qMT1l=oi}na=^v3G1i1Mm#On%PR zb*qy@Y&{bCarq*ijqwss&K+l|x^5b!sr0Fe5hqMMLF7Ye zK%g)uP|rfh+$~n@+lm^SO#KN|5VxsQk#76B%-1c>bq)f1~ z!O64MVmTYjx0x{+YQ^LZtC^7#(cWj&Uw0r&d8g>@=wy4cQ}k}>6zzSUu%t|~vcY0` zjvs77wJ=54N8RVC3$`=<;|XGUl{New2zKnEeqC5KlJX_e-Ks>o3qG8I%~8q^bVI)b zy4$QCETHuNFf!ZB#&O*jlosv5%H%nNfW$_|^OO?X+oM#gRxkMQELE3Ip}KgqVzWWU zHx=sLJzKz_at7rkjFN*FN!l(-9dE!VbV}~u#VGkftW3Uq6ny3$y}HT#_9#_f-+q>g zBoJ|~24da}#QdNqPn!)H(eB$8<>>^DfI0JyZH$;7^kizqPzY$Bn%2&xyw4Xzc|Xl2 zPhR65&o$Uv9}?WTJabfi2$L0Nb;LIQ@+%8~wYRDn+oH5_kNYD=^aE_@|A!5dwe)mo zpJ)R62wb&lf$!57S_MJyuCiG$@iZadFU(NhO(bVw7rDpl&cyC9oQOCr;85oXIC-2& zQOw79`hYL=FE;&SVofFtKS@t9tsS>Tr*jjX=~3#!4EE6Q`s#=D|@FM7OrP%O-2{!NsMyqdtjL8OV(f{Al=(N^sOEJHR< z+9uj(S|xc=5Iuf9gp}N4k(8Hiom2~70d;B;lz_y9CkM5p zBg+g6D&Uzud74iqnHa@qwJ#_wL+k5X9Fc&@ZINV1*50b+==6QZaY^yK2342()Elp* z0E_HwHo{%f(|FD0|MqZ~5wUQWDK-B$@h(mQlV`yd+lYCYYKo_~onVT^yg-h_(JA?z z^)$DrF`eh(;sG#sLIBKIJQf<^Dd17y?c}zMB&3m92}{E2F6KX-IMl zD*4dAWD7n&@(rhyhJT(OkGbJsL0$Uf`ag?;l3X3)b<6I)UawoGd*?b=>#;*{R8J~w zDBsxv;bq)CD&`)|qjM^XQND8xd!CO9Tx)Q^xsE;T;I5=DGCyAE406L^85Z)#gf8@t z(-{$q({b567aIBcQj^17YLq@3DUy%F$4vd!^G8MOTpm5!FJfmI`WGU0fE?|fMrrtb zlOU+K%rzo*n&S~WQ6Zio?nef7IBlx8`)pEB$F5=jn*(%a-IE-k^A!^m^!S|S#P}R> zOnVZ&5ba+qy;36kjo2KX8xD7!3Xkri6mr9Lor2VG2EB;ohjX8=S4z7liT=!5JwUoR zUNkK!MrRD$`lAPo(HW#~GCen(p4~DbzeD*J?hq}>^-ZX;DGFIs{p!_QqBQ*TD5c0d zCkkUE2(md`>P1a=+fe1-ajE07W|dJJ4}E^yIgm z^Np;&moojkFzf@w;JI++&CysA-UCM3-DR5%Reg@GgXeAFs`{C`^+O*>=AqU>e_VE&=gV_!i$86E^ zCA+qKtVGm=9jn655y>Z7b{V^1JNA=!*-;g^`hO%uvOX1yWOW9$;mQ1by30r1OGLTC z3{^&l@r?GWd%SiRb8h(xx>^QE>z{m(x_{Oa1UEf&AZI^V{4 zCQtSIL-jiQb1qAab4htN&v5P1B&H?hB}SD#{iCBwA3NEfN9{BZ$fMpJkVjF`zHixO zAdB{?ldh*UJc9A4mw%F+=Xh^Qp5xpYwYs!uXE7Dm_#biTPU5!XX?RQ* zHtoWs54Ro5z@|RDAr9fEctZk&Cvn@cVyy3_Td7`ZE~uB9doNyU?u5aDPLPl&56{E$ z@J-ma({1K_P5Y^++>vJy<&}9BkxX|H_E(;ohsp4O&g`aPxzfzOWX5zW9`hdi(0lAd zA%?MuA+RU3K@b9a0=IpYE~XF9lgJGsEz7gMZj!*6BL92qC-eFa7%FLG=!G6mi-f|d z@>_ZlDH~X;-iD)$MQgE=+1ZsXVB%Z{Ckf7G9B{VkZu~)%>kKl@ik~C==LASQAZ}!j zvw3JZQ>2*A#-qb5Gnpz?!d0n4NVjwlHSS`vx}1^ckfpo~pMQg35(MN7`L;UV9WDq$ z8FEG)a#^0)=YLzUut!1M_LWT>yh|LsE&LatQ&-*h#~cA_u~l%_xGN(ZXbxGX4%t6a zAhV@FX5o+t24ubeI%M0!AF}T}x{W;$;dKFsNqrOJ5Mv?D7EBE$WqCG~5A%WY`RwFM zc@~tLk%tw}I!SRgaj##AgeBRzR_*wMNs#3FHH`F*O)aD6$xSMn_wvtp_I)P#J~as9 z058?&2KZdIg{RR%jpHEOR(-2_!QZ1ad_fw6etRnP8+kzQA@yhQHrI#s0SJ5mmi_}! zRv6Mjk3>$mh^nT;5Im~^+5W=1PAPkXe9r~!UCr7}tT)beCtn{pmee{I@~fyfB{eOIHJ!*4 zrThUallMbJ_K5f2Ii@E{c@Pq%!BS49S!B8S0Z9|l* z(_W9#qCJc!^s97X6jZnj-v0RQDAg`7?pfiUpWVyBWV0H1jY(hZ*U{IwMXYRA6ml*P zy^MZuywM8mi(s;m>BQ~}F*zmi;2rlUhU)LG%@)|Q=Q@kNbrwaOMF*WlRJ+t!bWoCO ztu9}L2|r!xT6k@XHi*CWZa!Oyude_K0W^+j9+@vgTIY1Elv*)ywxV42cQ^L>ZJ0Ql zc+z6Vt!e^3HzbI|0Vhvk5CC0Y5X?e{ZyEaqq~v-ym#%M?NOjA*LH5ZdSLhkuAx$sj zEFb~(<`LPDB|##^4sSz=fEv$&v@mVSCk*wtOa3(NZ#hB+`uAV(Q;rJU4B^Eyt3=CSVgSjNJ0EHeSw8;gZLC_i$sZHdw!r*^t2O zH*ZC$!@DxCL_j{MjOhCoHSPt5`TNT& zFn=U@{wgY6azmAtC3*vF@+4AkOkQ|T!sJ~Ro4k#tADq0aPs8MqpBs}m87A+KA0V7tjE!Xwx z=joSx3~8c1oYV`a+84YMrCPpW(c}P(U2hzi->7F%-|^Qd)rzzU#(S5u_q37PD0qHY z8>;1MX|bH^U%wfR!4$E`MTRx+CXAp6ve8otl}{wCMc?znZJ_@PIS20=6If^ArC zLAir)pxkBw7C+yHdE~#OJe2RUA4QFCWHAB>=|Uw)1_2oxwF?r@D@eO!S5YI$;ua}A zxSkh{VmsEtF`z83q}k*iBg%K=VJ5s?#u(yp#sXz`US;@5nttBLgufj}uy3bluZtXW zDJ%1;FxiKd$rp?}P9@T#UiqCMH2U3Fa{;3)&lVRi43@ZI5VzQ4W%7Z%<5X?_4Wmb2 zipq0&Jmbf4tW382<2c3Sb9K*Y=B*iAukYW zzuJO)2f$A0Y|&*F=NgpnS{H9OIB5ocn|++BgLN==^T9e$ZpB>oUnTpmg#A~@{ zeu;sKCH(B`@6bpMg!`ySp34ixdT4|P@Iy6zbh9Rb#yqng>LGgn4zn&uJQFEuEKTE` z+PDz!KCfmCmM>Koyv`#Qe0w~dtOJ|Tf&5IK6<*zm8hcF%Rhp6aL8eY`4Zp1)$j0}J z;?8qGJ*Q{*jCow~*|Ip-AWPzGWyTOW_~6*m;V}KiDzDcG{}!9@Zz03K zNJkIH6bnzu-=SX1KoiLy@Une=9DL@-!)JaxeCGco_{<*!K2=7H6~A$&J-cg*#hppH ze;)F8c{0_r*?peuw&x&!mwU9+yDHn};pt=7QL&M$&gREb%nQ9u@%wIXVd+y8zZU|= zFqR21Q!C@{M|OV4u7TJIYd$++EjFL9sPtX%8_K0c zyA}C&xKE3z2OB~p4f%I?4u?B?G>y`WO>|@nc$?>7crX10(E2w9TL0``K!C(6C3E}aY4F|IV?E#MbxKs%KGOm}WMk|%z-w%sTr35hC8+2Lz@H|!qdJcJFj zi3BtYk?C)0IsnLj6O$u5K=mH=^i>@iKum|xA9rLJrR!L61(}| z@`w~?HB*$;T{u>63&mgZ8+GK|7wFxnKT|oweKZRcH&#V1awT%fb4($7yEMkfnG$zV zG{}uyseH$F%Bp-0YgtjC)N&kW%2E=3)*LXm=hbeC8}1r-bQe@>+q;+Rmtmy`Q~Iu|C^ts^9%uF0c=;!A)6K@UNbs`ul4N z7snr={`WI6@3+Dk(c8+I-+z+5zn)HR-RJ#m?WyyeH?Wn{58;|;n17)Gueo1E;Z@Sl z;H4*sne~i$PfDNZ)dulLSqIjXzw5Uca_T$Kryqgmv_IlM#6D$0X&DrROv;SAu)3d_ ztomstn6QE%PC2gTNwKpFSM2xSL#-Ryxs?s@ z9Q%D6`|~oq_IG3apue?W(`>83S|}KrEg6LcQV5TDtq{7NzA=WwTU7mnG9_l(!&U-6(jEjTZ5pArX5TDu)-#DRyVAD_fAubJPoB z^He=N2FwYpWZhgnSJlF70dE)a{9IAqP^OnPf)rz4C=)Pb1UZXCaw__go(Eh7{G6|x zeCC28A?PY&aw+p1!>dpr_tnDj#t+%>c-zz}C!gtW)W0mGU+VQQbLp3L`j;#xZ=0U$ z|>A7S_Ridau7`LuLAP{Z;N^vtkE0 zIJTo8poKp5rYEbG&7M6S+5cvg!@Zp~FsLh{u)khgB< z56Ih8fUp!$M?k%^NFR^DN`oc*#>Lr?IqqbE+?Xek%3ReJ^_P)v%n^3BOOC@5J|yu| zzLxx7xld(&W_#(zuedLr^9S5xmY=HrnIFqZj>AhHGx=-N@5F>BB759gb&@)ZA6vvp zj`pP@+=BQ6y#G#cYMEh0#1jI#9U|g;Z3yQhQr-ZEC1O-Gqo4CZ0t=Hg4Qa)BBB@@d zo(q?te*q!wYV6`Hh?IwPM$i3)iHx47Af$xy2xa9FO%uGq0ulG1)!Wv^ngo^M6M+h# zb}Evq*D2%K@d{pb9$}Zlg3}~{SpMmtwLHA#{G(b#K9I49d9EP;9`^+`t8AP*3uMu; zUd@~_tNbZ5-U;kvU1{^RqdKa`vZ;cy>5*qnwtb@v+vKnnwp2?)W3ZS z7Yy~s?>SrV8LY`Qx=N!fG#>~!sGdz#h9f6YG@;)`c|ko3eo_`#m{oprH>vv$C zmjZ@${_Wox)_L#IBoFfK;C&y&8s}YgNS=7k&zOTMnDwG&`EPz;%6UELc2h*+Y7~jo zpk4sCKuEty`you_UH?LR^i|y^|F@X;@+0r*Hu=9IdEyFqZPaB?8shK2anzPW`?=u$z6Zy)s(+J+N z!7q8#u)!~Ul+ksdklEmC)3q4=N}2P$p}*ak9;d%i?d7f*A^L+5f%f$PExd-ggY{zsl>>b7Sm_mkHjWRl=`B?-BRL z_d#6EvgvgS4_m=t)#mJSWr3yHldD=O{}yD=DH35X)2RmNUq^7s(-L_S<}Ko*;(@Z+U2%Joz&Y@O?Plj`9#9o`9N^ADAW&>zsxsbV`nI-KPt3We>s!#BpDs z)kmlrv2-*AL-;qK-Y#f?FHcdTuxv%+_Cn~Kw?BL75CGO)sOh_8q-{a?Bjo+|7?LOS z0sk4dA9e2)aF5X4I$a*tDR`SYUHQA{D>3?aF>fpRsI8c{i63H06s7I{fxDw|FKsK+o6ojb9R)Z-$rN#GMpD@UpO&*_>l=Cd>9NLj{M$)4~zdr`0!!MzY8BMDL)+_K2MIrhvxME;=^G0@ZF;(d|3A{ z!iVii|1Ny!vix*>*lmf!hmF?%;=^G0@X0zI9}uZtPt~K-W9+$PtkSqHYA;8mx(T-VP)0t`ZVPp z`k#mXx0wF-cB-Z+&Gf$}`rqrRnx>9aN2oS+xH?QtSFP$0HAPJV>!GoNQ)BI6J&%~} zSuyi>rz)R3!nDaHmzd+pjr?aHv5-uW{K864!gq+cEwQ{oTY^(`&RgJXm=i*lmVw<1 zL+I6b_d?|DwN&zwe1~0=at^EcVFKyI4@-_im39$#ifL_zM{H;QE}{F7fIn1EDxqJT z-G{&>HhCJEpdf#j`x-%BY1h;dD5pnsD4r70vCPK%mceD>rSyS|5t(Wg9i8s4y}g!Y zt)ioC$!>(Vh-qIKo`OR6A%t7h0Q8Pq)K}i5M?vMb)T5e+t85}(Y=v4lK^;+wf84iK z#Ggae{x+j(|5sJR4+{Kwe?Q3EuFCd|P;;WLt@IanrV)-|m2i7FBL(X9+nsN+g8j#m zm+*ot+BH|cCivfR@@s=aS`fTjpA05?w;uXzf2?<_Ch(=2$-C92d$;obNnp0oB*(Y> zeI;;%+$UlMH7SL>e?$tUvdKRHXSqJ*sD{WSgp(OI{R&bA-fk_yinlFU@b;xFJt=>O zT9zLOzYS9AJLCGups!1et0VZR-x}$kZKlsLcSRxO54cA|y`z)ku7-X)9=dkY-4G$x{Gd%Wqj>7y6#o5Y>+hg5?Q$O9GSf=DyGQVauT&J869sk3@4cRen z!p_ZrupfMlyjqgTPw7yt%9;z9A=l9%@ueM-LHDu%# zL`DeM247OPh?o;_C*1U>HSsiyAhPT_y z@OC3|(lnB?pAy3`M68H-S`Z$t&O?Cp*Vxz(qY++en}$>NBQk_OdL<%7R^S_g{~Z>r zb0+0~XCT}prhRS%>*)M%sLuaTQ(H1hPDVHnX~kI$miS}`%5nL7AX>H?j$mDImsv0rOl-9*BBQnu zcvejSu0vck$kF6Ek2RsH@GVK;z+uuan5(U~$%ZCLHSXOAvmb~>B#rA?SM{u`fZzyv za@BVve1To?ZnKK`iI${ze-LjlOPo|4aQ_8?FT{H0i~}(Wc|&RYHmm4pbAKe@?MPl+ z1Pi#Ioo=@}yIe(3PvOooHAV1lcOoLShy+GKWOXa(uG{!EE8ybv#So~kUy9=n3V4su zbTnCzuZmY+TPU2ybyD8i)RBZ7?<0O{Z;bki_~Ij!$}glED{_3q-~U7^T`pXUB6%{X zlggpKBf195u1lE`+d3Uz&?@3D#Bm4QtB`j~kFLS;YkW*!74bKqvi4^$@gRKkgml$b zT~`JF0ji(=9rV+`52l|&h930-N^5GqU^#^FJ~O|WY3~ud+e`}UAZ7V3NU-7=P`&j`0_+R&G;VgQ1VdoMNzuFS(uS28&b0FY- zn;}Kq@@yx+@y7XGTP+An0rzl$+_+F8s}`##!TH1+yb0}88L~7`WRb{SR>}W^dxHQe zT0J2(D+a%|TlGVb`xY0!aY44TYn#QLB@j=ZL>A<#qvFm_vL{E_`Mv1)Qp8^%e#!^P zzsr3p)w?gg6K+O^FMm$u&HVJs%Eu(!u0G1*Q^iT15brxj(=->qv4RbjE|6t;5~;|A zx;%;9gKzN%cR=_2^3g1-LbQK=%}4#3CdkVe^8YfKB0ulj(ywXGuBnUwmH`1Y>jdy> z3;_iBHTTl(AWwv#jzFI@?rRaNsOe}jN+f`flTP&fmJMgOza_<;-Hse#m`_n2$-`Pj zJfT&@N5pYo=oJg2XusrcNch<=j%x>$zxl`UT^s=4|LOA>L+>{zc+?aYv_G;H9UsXx z-dEJePGpGmYT--zA}2DDRM)yk8};bMD!F9P^O!qTNvEwuYC&W*6C}80(9_sxdKz8IT8 zerAMgBm9cH@10eftIR>-r_&%%Max{pxZ!pU#Etf;FQI6x&-qf&SmYm3DLNl?G6?bS+fXEgcgRy{KH zty<>se6v0AJS>t$R^$y@5w30lGtj$WBI+vPH=e^-lSC?@Ru!FCGv!R+gKdhx#2p6v zoZ;j*mS=Zuh2>P|38WktT6GTEsV4BtE+uK9&M#k&xUZzl-srS4 zParo!rEp3G{Q85G=80 zGdWgb&!s=Xe|gL$v&3Ei|0DVsB*S$EOYHNRYeZ&=eIfi`Bbvar@%b8DW_TBNs@nOo-?tqb+mDsyX% z(ORdsu8(+W+y@-%#CV|~vjtMkn0{_!pV!mR;Ddr)>*(h^_PJJAy^W3>udI)ImnrK# zLeBd_T2NQkHH-UnK`zw&s) zPOmsU5^GH1xTXVQjbU%+|HRc(bXM+qIdN~_cx$k|9c}DwD&1SF(r}uwJGJ`m*z}WE z^O*R}S@(}j@BNozH|MOk{*yQ7iBn@YrxR@KQUk)Fnpc6P@xE+}QDT^KY-{-Iq~nLf z`@sV=_`k7mIBmy&3>*efrG9scu1a+ad}+7n=;GHbJ*sKp%A=aryoSQTf=I?=Ycn_` zKL`>G*Rnq?;fs1T4dGDpYW=ZPH+_sqjR;%9TPe2V-2x7(^V#3+=7U!L6^9^ z@9NlHGd!UiEF4$CFLteOuR#30K_&aSe$ecyRsk9) z)cuD(_Q@i6EHm=hc6jWr$6|s87v0;dDbFl3LULn+1u2A^Ym9yV)kD#J{*B=&6kwi0 zEy_9fMm&WKe{p5Ry@sa{T4s0(U9pVm*1tW4c?#X|P5(glIKv-%)ywHdffVFjW#!yf zuvX(@n@E;sOa3l*u0WPqMSMUY)3YRUDIzO!(YOQ1yCoZup;{S~ji7pdtKk6j`gk_- zS6}yQrtu&J%PN~9^AzKLCIp8V&VrL9vdoI)LiOehPMLlKRrQ*5#B|?N++i}`bXVDr!z~RPJDd>QdvN!e=RJ`&^zIn z^3qE12!zz&{$B!;nrzg(?^%;ST=>3~Mm|rfWLK^1)g;_6`8D^`61hSk_ZFGXN9QVY zY1jB$$^Vt7Qy}-|3Bjp(#=vhXm#^&A)W(RukGqxJNPoOv8-0ZUyZx zw(39vJ{bG+Zu(&RbJa~5obtEp|H=J%s&3%@+3=-#f1>lrunsn#*XCz%%Fq7U`HUK5 zK4*U!k1zWDXun8S*^pc~nGXNQd35-#qP(8IY2=%8UnP-?1bLNBxiJM!_BF4u>75Q~ zMaa-i^C`z*XOw=eEK9;2Y7pVpX0JZ2!h0Xc-~>F`uI?1brIE#Vxz7^FY^$lqGoi<( zFCt6T%Ch2)axwj$WAytrU1ZT0{XnY)U-S=J54ZrRWR+ELXzo%`_N-S&$K?y8ZTsBk z!PetZgMThFn zM5MTYzSNH76*jF!{f3z=8|&D~@bw!qIA!d0>70O@W`FYpv& zfknmw>Ckwux-)il=gRu(KA^{b!Mn=Fxjh0IDv(NR;sk_Xsm+*xY5e|weEg?>WsDzJ zfHU^78vU{G3;ir*z$5z@qCTMiyh*)Aexvc-GZYFF>=*9NNJO*v-)<^3naefd~L@tER2$-TKkaH>hr zz2)iEBvN66dxtr2d(2_YGku^8k_yOXp>9$}_XUcRYmT8pbxEl6Rwe zmXV*Z1(5>N!UViebbQGi;05`{T4&9w9?rc$k}KCsWKpB!|G|BgKuQB5?hqY{XS6yY z2H$X-}SbFCpGzRij82G)j0;K+)V(5PBLQU)~4@J$_sQ zo&n6hQ&}gFIqRtYLR=w3x%E$D={rLap-{;EGDFY1S`fZOPwpv_#WoSo&q8Ewwm9w} zk_#`tE`w7ZpA{p3&Wj2l0|FxMLiiK5!MU-Cf1_gP*Em58y-v6I51+EF{_Usz@%0E` zw`~X?ty#60bKfY+OS43>B9G#)i}FqpYoepaGe*6zA_1Pq+@s>)xqT_*8z)c;sX*Dd z6ad+ZQt*?{$hfc2h`NLJ*E zI@%uv#i2YP;sp)rxfL<_cn8GqEiw3gt0ezoy+kS-DcE%U?iL-LiTJHZj>8nc7n=8D z;*uErzOzxnl>ue!61pu5>LF$K#h21;Ss~6*&@Cr7m;i7VtaDW*VivX2J;9E%#WNI1<|GggJUAR7altpUeO;v zmEYVKnTq;WY|}DR)34%W21Sp1KW6l?O#ge=#{-^s67i*ab_S=kT|EH4Gz@?*%?w{4 zph<P;o$`S=fknu|qdjbfTHzHCV0uR#*2ge@?e=9gXW%wh>zlh>b z<$8hK*hqC=z#q!N9jyc4kKp($0e=oJip8G>0pA!<_ALUkX83d963W@iLjsv#2LxJr z90YPDAkZFP6oD=T1gg>TrxEancmgcAvUngox;_yOgW=HpL>&4>0uD*OL2>9}Q&Zgl zICS|(40kTp|DN|z|6ut<&HDdLs{haU*Xj@Vd;dN9!$n@R{vhmT3w7=`>kl)TO`!0W zYce>cdAhDxH`0YA(8F)R9qTMaRum}D!lo}Zou0egXVD!uD~MMM)1Y$QC;H!{eWCkX(4@|737Vi}e2)`EmI6 zf#k=&+fDN0z(xOz{P?uyKSq9BT{9@{Us`i~`EkVu3_~u}|6cgPpz?#!2L;qG*&Q&| zf6A!-a}~v!V8mGZTX5*;k>sZ-7Ewx_CQmrbU^8?RTd<7+9Vb&-p-{4lxW`%ZrryCl zNdq1wsp?gNJHgAgKV|97`8&c-b4)HVvlPXYD@C%xisZt_XJl{+ca>Q)<9(CC{U~Z7 z`8L_4p^5kiew{WlPOZ-13?#)5&_CfB;E-c_sPOPg{V2Yuj~>NM8vCA=@fv&h={|N` zSKepT)b@VAc3k@D7Be{II`kh%Kjn00fztod&wuG>F#7pq`3ca^hUJ6N&tuC6rJwqD z82zk&=SS%06(NIDPIdhU($5)mW;G@MrJw)O&tUZP=&}=_AJ4ME=x5%tLFs4V4n{xo zcl0OL#}n{-5ao7AzpliFh%t3rMcgK)^?2qWZ{f`9432vZ>el(rwQ!ub@U7VyTr&T_ zsc(Y_5<%;s#^c=F* zwOjIc@oQZl>4m;(kzDwYD}z(IisD@8>RFLe!vTRLLAr4~s{s*LEy76xspj$n{6^`c z+7Q1{+Fkp$3%-8ntPP3y8~llgdnLSI^VF0n;UQ4A&W5)lBGpH|JrJ4I;9i6X?KnxD zz%I{UMe@XDBjNJ=@AKQWH!0_M^#iy(&tI9rb-5bZ<#|ZC_{LrhF3rt>lTrVPdG2`s ziSR@%&UxZ8`V3AAv*hLO3c(2{0|Xzu(QrQq z0|YzniGg5ed9P-Md;bV{>-xxBD!lb->|2}4do|_otX}Q4K26iY%lnz{bJSJg^CjS_ z(15TdyxDM7Xk@MmA!S8*#8sh@xhjN|Uz8iJ3Xjj~)zs7Ir-$gLOvwMfy+2aA7hH8) zdwN)jmy61oJ43LiXTbbuWpERJ5vy}4%9T{|{CP?Srwq9wRwkZi$ix?zOmxBNUcw$u zBxecab#QW2I@>i(ATNXKqYz{+kcLU)0)aeiuLYrG5|ur0>sQUiiAq6!9UK~!U+<$m zz7F1*%H1mK-fD@>BOB@77T^8LgLF?`2e(kALt#C(>6vNUxVRo!l3!Dg)q_u%!b-{b zT+;-3rQN0+{9Mx{@^d?c0iSJ30aId!955pUl42L}w~z$pTjeXuQMhd(#nw&rmWZ9J z8x#lA1UBk65COY5B&YWM#_&KXwj%Ee8*@R)Mz}ajBr9?yzviA8C*LZqB0eIJ8Cep! z5|I^oasDXqlBZR~-Adj`(Y#R6D!89qrzf2KehU*_Pw9Uj*Z;27|H@kixDP>c>Z3jFS|tCJ zUiYZ5ZCM6~C*E9^!8}$T;5g3PpTs|KAACruf70exytL4 z(mCCqoK;l?c^)jzWvK>>FW@taO~M@EVv)}*p2=qx{~Y0BHwqSmC=YrKNj^Y+vY346 z$sFgx%?Q7ZaCJ*fwT&}03MbVlEJDz!YZOjHqi|A6_e zWF|Im<2u^n&I*Fh9fMtC4I}$SSJQDga5BJh6~y|~KmaH9hx%wo);>++n*BEVhk_B2 z@__qnBp1(R+qsa>ES`&k#Z_$E;Cc4Ah2@RU?t|=+d40y%h5MF5%GeIjx2}^Q#q<|U z-+HSS(#CR-HrC(SuW4YN&)=btCs^iKPR|_6`<8&U*KcFlW35yu-U?0}h4<0{*mC

{Dl)YSUTCBc?*hKQl^xxCa!| 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 z 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�Og2YJ5c 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

?v%2_q>IvKYgb~5gGO6Nf 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

+ See changes to v1.16.x + + +* July 1st, 2023 - [v1.16.7](https://github.com/klauspost/compress/releases/tag/v1.16.7) + * zstd: Fix default level first dictionary encode https://github.com/klauspost/compress/pull/829 + * s2: add GetBufferCapacity() method by @GiedriusS in https://github.com/klauspost/compress/pull/832 + +* June 13, 2023 - [v1.16.6](https://github.com/klauspost/compress/releases/tag/v1.16.6) + * zstd: correctly ignore WithEncoderPadding(1) by @ianlancetaylor in https://github.com/klauspost/compress/pull/806 + * zstd: Add amd64 match length assembly https://github.com/klauspost/compress/pull/824 + * gzhttp: Handle informational headers by @rtribotte in https://github.com/klauspost/compress/pull/815 + * s2: Improve Better compression slightly https://github.com/klauspost/compress/pull/663 + +* Apr 16, 2023 - [v1.16.5](https://github.com/klauspost/compress/releases/tag/v1.16.5) + * zstd: readByte needs to use io.ReadFull by @jnoxon in https://github.com/klauspost/compress/pull/802 + * gzip: Fix WriterTo after initial read https://github.com/klauspost/compress/pull/804 + +* Apr 5, 2023 - [v1.16.4](https://github.com/klauspost/compress/releases/tag/v1.16.4) + * zstd: Improve zstd best efficiency by @greatroar and @klauspost in https://github.com/klauspost/compress/pull/784 + * zstd: Respect WithAllLitEntropyCompression https://github.com/klauspost/compress/pull/792 + * zstd: Fix amd64 not always detecting corrupt data https://github.com/klauspost/compress/pull/785 + * zstd: Various minor improvements by @greatroar in https://github.com/klauspost/compress/pull/788 https://github.com/klauspost/compress/pull/794 https://github.com/klauspost/compress/pull/795 + * s2: Fix huge block overflow https://github.com/klauspost/compress/pull/779 + * s2: Allow CustomEncoder fallback https://github.com/klauspost/compress/pull/780 + * gzhttp: Suppport ResponseWriter Unwrap() in gzhttp handler by @jgimenez in https://github.com/klauspost/compress/pull/799 + +* Mar 13, 2023 - [v1.16.1](https://github.com/klauspost/compress/releases/tag/v1.16.1) + * zstd: Speed up + improve best encoder by @greatroar in https://github.com/klauspost/compress/pull/776 + * gzhttp: Add optional [BREACH mitigation](https://github.com/klauspost/compress/tree/master/gzhttp#breach-mitigation). https://github.com/klauspost/compress/pull/762 https://github.com/klauspost/compress/pull/768 https://github.com/klauspost/compress/pull/769 https://github.com/klauspost/compress/pull/770 https://github.com/klauspost/compress/pull/767 + * s2: Add Intel LZ4s converter https://github.com/klauspost/compress/pull/766 + * zstd: Minor bug fixes https://github.com/klauspost/compress/pull/771 https://github.com/klauspost/compress/pull/772 https://github.com/klauspost/compress/pull/773 + * huff0: Speed up compress1xDo by @greatroar in https://github.com/klauspost/compress/pull/774 + +* Feb 26, 2023 - [v1.16.0](https://github.com/klauspost/compress/releases/tag/v1.16.0) + * s2: Add [Dictionary](https://github.com/klauspost/compress/tree/master/s2#dictionaries) support. https://github.com/klauspost/compress/pull/685 + * s2: Add Compression Size Estimate. https://github.com/klauspost/compress/pull/752 + * s2: Add support for custom stream encoder. https://github.com/klauspost/compress/pull/755 + * s2: Add LZ4 block converter. https://github.com/klauspost/compress/pull/748 + * s2: Support io.ReaderAt in ReadSeeker. https://github.com/klauspost/compress/pull/747 + * s2c/s2sx: Use concurrent decoding. https://github.com/klauspost/compress/pull/746 +
+ +
+ See changes to v1.15.x + +* Jan 21st, 2023 (v1.15.15) + * deflate: Improve level 7-9 by @klauspost in https://github.com/klauspost/compress/pull/739 + * zstd: Add delta encoding support by @greatroar in https://github.com/klauspost/compress/pull/728 + * zstd: Various speed improvements by @greatroar https://github.com/klauspost/compress/pull/741 https://github.com/klauspost/compress/pull/734 https://github.com/klauspost/compress/pull/736 https://github.com/klauspost/compress/pull/744 https://github.com/klauspost/compress/pull/743 https://github.com/klauspost/compress/pull/745 + * gzhttp: Add SuffixETag() and DropETag() options to prevent ETag collisions on compressed responses by @willbicks in https://github.com/klauspost/compress/pull/740 + +* Jan 3rd, 2023 (v1.15.14) + + * flate: Improve speed in big stateless blocks https://github.com/klauspost/compress/pull/718 + * zstd: Minor speed tweaks by @greatroar in https://github.com/klauspost/compress/pull/716 https://github.com/klauspost/compress/pull/720 + * export NoGzipResponseWriter for custom ResponseWriter wrappers by @harshavardhana in https://github.com/klauspost/compress/pull/722 + * s2: Add example for indexing and existing stream https://github.com/klauspost/compress/pull/723 + +* Dec 11, 2022 (v1.15.13) + * zstd: Add [MaxEncodedSize](https://pkg.go.dev/github.com/klauspost/compress@v1.15.13/zstd#Encoder.MaxEncodedSize) to encoder https://github.com/klauspost/compress/pull/691 + * zstd: Various tweaks and improvements https://github.com/klauspost/compress/pull/693 https://github.com/klauspost/compress/pull/695 https://github.com/klauspost/compress/pull/696 https://github.com/klauspost/compress/pull/701 https://github.com/klauspost/compress/pull/702 https://github.com/klauspost/compress/pull/703 https://github.com/klauspost/compress/pull/704 https://github.com/klauspost/compress/pull/705 https://github.com/klauspost/compress/pull/706 https://github.com/klauspost/compress/pull/707 https://github.com/klauspost/compress/pull/708 + +* Oct 26, 2022 (v1.15.12) + + * zstd: Tweak decoder allocs. https://github.com/klauspost/compress/pull/680 + * gzhttp: Always delete `HeaderNoCompression` https://github.com/klauspost/compress/pull/683 + +* Sept 26, 2022 (v1.15.11) + + * flate: Improve level 1-3 compression https://github.com/klauspost/compress/pull/678 + * zstd: Improve "best" compression by @nightwolfz in https://github.com/klauspost/compress/pull/677 + * zstd: Fix+reduce decompression allocations https://github.com/klauspost/compress/pull/668 + * zstd: Fix non-effective noescape tag https://github.com/klauspost/compress/pull/667 + +* Sept 16, 2022 (v1.15.10) + + * zstd: Add [WithDecodeAllCapLimit](https://pkg.go.dev/github.com/klauspost/compress@v1.15.10/zstd#WithDecodeAllCapLimit) https://github.com/klauspost/compress/pull/649 + * Add Go 1.19 - deprecate Go 1.16 https://github.com/klauspost/compress/pull/651 + * flate: Improve level 5+6 compression https://github.com/klauspost/compress/pull/656 + * zstd: Improve "better" compresssion https://github.com/klauspost/compress/pull/657 + * s2: Improve "best" compression https://github.com/klauspost/compress/pull/658 + * s2: Improve "better" compression. https://github.com/klauspost/compress/pull/635 + * s2: Slightly faster non-assembly decompression https://github.com/klauspost/compress/pull/646 + * Use arrays for constant size copies https://github.com/klauspost/compress/pull/659 + +* July 21, 2022 (v1.15.9) + + * zstd: Fix decoder crash on amd64 (no BMI) on invalid input https://github.com/klauspost/compress/pull/645 + * zstd: Disable decoder extended memory copies (amd64) due to possible crashes https://github.com/klauspost/compress/pull/644 + * zstd: Allow single segments up to "max decoded size" by @klauspost in https://github.com/klauspost/compress/pull/643 + +* July 13, 2022 (v1.15.8) + + * gzip: fix stack exhaustion bug in Reader.Read https://github.com/klauspost/compress/pull/641 + * s2: Add Index header trim/restore https://github.com/klauspost/compress/pull/638 + * zstd: Optimize seqdeq amd64 asm by @greatroar in https://github.com/klauspost/compress/pull/636 + * zstd: Improve decoder memcopy https://github.com/klauspost/compress/pull/637 + * huff0: Pass a single bitReader pointer to asm by @greatroar in https://github.com/klauspost/compress/pull/634 + * zstd: Branchless getBits for amd64 w/o BMI2 by @greatroar in https://github.com/klauspost/compress/pull/640 + * gzhttp: Remove header before writing https://github.com/klauspost/compress/pull/639 + +* June 29, 2022 (v1.15.7) + + * s2: Fix absolute forward seeks https://github.com/klauspost/compress/pull/633 + * zip: Merge upstream https://github.com/klauspost/compress/pull/631 + * zip: Re-add zip64 fix https://github.com/klauspost/compress/pull/624 + * zstd: translate fseDecoder.buildDtable into asm by @WojciechMula in https://github.com/klauspost/compress/pull/598 + * flate: Faster histograms https://github.com/klauspost/compress/pull/620 + * deflate: Use compound hcode https://github.com/klauspost/compress/pull/622 + +* June 3, 2022 (v1.15.6) + * s2: Improve coding for long, close matches https://github.com/klauspost/compress/pull/613 + * s2c: Add Snappy/S2 stream recompression https://github.com/klauspost/compress/pull/611 + * zstd: Always use configured block size https://github.com/klauspost/compress/pull/605 + * zstd: Fix incorrect hash table placement for dict encoding in default https://github.com/klauspost/compress/pull/606 + * zstd: Apply default config to ZipDecompressor without options https://github.com/klauspost/compress/pull/608 + * gzhttp: Exclude more common archive formats https://github.com/klauspost/compress/pull/612 + * s2: Add ReaderIgnoreCRC https://github.com/klauspost/compress/pull/609 + * s2: Remove sanity load on index creation https://github.com/klauspost/compress/pull/607 + * snappy: Use dedicated function for scoring https://github.com/klauspost/compress/pull/614 + * s2c+s2d: Use official snappy framed extension https://github.com/klauspost/compress/pull/610 + +* May 25, 2022 (v1.15.5) + * s2: Add concurrent stream decompression https://github.com/klauspost/compress/pull/602 + * s2: Fix final emit oob read crash on amd64 https://github.com/klauspost/compress/pull/601 + * huff0: asm implementation of Decompress1X by @WojciechMula https://github.com/klauspost/compress/pull/596 + * zstd: Use 1 less goroutine for stream decoding https://github.com/klauspost/compress/pull/588 + * zstd: Copy literal in 16 byte blocks when possible https://github.com/klauspost/compress/pull/592 + * zstd: Speed up when WithDecoderLowmem(false) https://github.com/klauspost/compress/pull/599 + * zstd: faster next state update in BMI2 version of decode by @WojciechMula in https://github.com/klauspost/compress/pull/593 + * huff0: Do not check max size when reading table. https://github.com/klauspost/compress/pull/586 + * flate: Inplace hashing for level 7-9 by @klauspost in https://github.com/klauspost/compress/pull/590 + + +* May 11, 2022 (v1.15.4) + * huff0: decompress directly into output by @WojciechMula in [#577](https://github.com/klauspost/compress/pull/577) + * inflate: Keep dict on stack [#581](https://github.com/klauspost/compress/pull/581) + * zstd: Faster decoding memcopy in asm [#583](https://github.com/klauspost/compress/pull/583) + * zstd: Fix ignored crc [#580](https://github.com/klauspost/compress/pull/580) + +* May 5, 2022 (v1.15.3) + * zstd: Allow to ignore checksum checking by @WojciechMula [#572](https://github.com/klauspost/compress/pull/572) + * s2: Fix incorrect seek for io.SeekEnd in [#575](https://github.com/klauspost/compress/pull/575) + +* Apr 26, 2022 (v1.15.2) + * zstd: Add x86-64 assembly for decompression on streams and blocks. Contributed by [@WojciechMula](https://github.com/WojciechMula). Typically 2x faster. [#528](https://github.com/klauspost/compress/pull/528) [#531](https://github.com/klauspost/compress/pull/531) [#545](https://github.com/klauspost/compress/pull/545) [#537](https://github.com/klauspost/compress/pull/537) + * zstd: Add options to ZipDecompressor and fixes [#539](https://github.com/klauspost/compress/pull/539) + * s2: Use sorted search for index [#555](https://github.com/klauspost/compress/pull/555) + * Minimum version is Go 1.16, added CI test on 1.18. + +* Mar 11, 2022 (v1.15.1) + * huff0: Add x86 assembly of Decode4X by @WojciechMula in [#512](https://github.com/klauspost/compress/pull/512) + * zstd: Reuse zip decoders in [#514](https://github.com/klauspost/compress/pull/514) + * zstd: Detect extra block data and report as corrupted in [#520](https://github.com/klauspost/compress/pull/520) + * zstd: Handle zero sized frame content size stricter in [#521](https://github.com/klauspost/compress/pull/521) + * zstd: Add stricter block size checks in [#523](https://github.com/klauspost/compress/pull/523) + +* Mar 3, 2022 (v1.15.0) + * zstd: Refactor decoder by @klauspost in [#498](https://github.com/klauspost/compress/pull/498) + * zstd: Add stream encoding without goroutines by @klauspost in [#505](https://github.com/klauspost/compress/pull/505) + * huff0: Prevent single blocks exceeding 16 bits by @klauspost in[#507](https://github.com/klauspost/compress/pull/507) + * flate: Inline literal emission by @klauspost in [#509](https://github.com/klauspost/compress/pull/509) + * gzhttp: Add zstd to transport by @klauspost in [#400](https://github.com/klauspost/compress/pull/400) + * gzhttp: Make content-type optional by @klauspost in [#510](https://github.com/klauspost/compress/pull/510) + +Both compression and decompression now supports "synchronous" stream operations. This means that whenever "concurrency" is set to 1, they will operate without spawning goroutines. + +Stream decompression is now faster on asynchronous, since the goroutine allocation much more effectively splits the workload. On typical streams this will typically use 2 cores fully for decompression. When a stream has finished decoding no goroutines will be left over, so decoders can now safely be pooled and still be garbage collected. + +While the release has been extensively tested, it is recommended to testing when upgrading. + +
+ +
+ See changes to v1.14.x + +* Feb 22, 2022 (v1.14.4) + * flate: Fix rare huffman only (-2) corruption. [#503](https://github.com/klauspost/compress/pull/503) + * zip: Update deprecated CreateHeaderRaw to correctly call CreateRaw by @saracen in [#502](https://github.com/klauspost/compress/pull/502) + * zip: don't read data descriptor early by @saracen in [#501](https://github.com/klauspost/compress/pull/501) #501 + * huff0: Use static decompression buffer up to 30% faster by @klauspost in [#499](https://github.com/klauspost/compress/pull/499) [#500](https://github.com/klauspost/compress/pull/500) + +* Feb 17, 2022 (v1.14.3) + * flate: Improve fastest levels compression speed ~10% more throughput. [#482](https://github.com/klauspost/compress/pull/482) [#489](https://github.com/klauspost/compress/pull/489) [#490](https://github.com/klauspost/compress/pull/490) [#491](https://github.com/klauspost/compress/pull/491) [#494](https://github.com/klauspost/compress/pull/494) [#478](https://github.com/klauspost/compress/pull/478) + * flate: Faster decompression speed, ~5-10%. [#483](https://github.com/klauspost/compress/pull/483) + * s2: Faster compression with Go v1.18 and amd64 microarch level 3+. [#484](https://github.com/klauspost/compress/pull/484) [#486](https://github.com/klauspost/compress/pull/486) + +* Jan 25, 2022 (v1.14.2) + * zstd: improve header decoder by @dsnet [#476](https://github.com/klauspost/compress/pull/476) + * zstd: Add bigger default blocks [#469](https://github.com/klauspost/compress/pull/469) + * zstd: Remove unused decompression buffer [#470](https://github.com/klauspost/compress/pull/470) + * zstd: Fix logically dead code by @ningmingxiao [#472](https://github.com/klauspost/compress/pull/472) + * flate: Improve level 7-9 [#471](https://github.com/klauspost/compress/pull/471) [#473](https://github.com/klauspost/compress/pull/473) + * zstd: Add noasm tag for xxhash [#475](https://github.com/klauspost/compress/pull/475) + +* Jan 11, 2022 (v1.14.1) + * s2: Add stream index in [#462](https://github.com/klauspost/compress/pull/462) + * flate: Speed and efficiency improvements in [#439](https://github.com/klauspost/compress/pull/439) [#461](https://github.com/klauspost/compress/pull/461) [#455](https://github.com/klauspost/compress/pull/455) [#452](https://github.com/klauspost/compress/pull/452) [#458](https://github.com/klauspost/compress/pull/458) + * zstd: Performance improvement in [#420]( https://github.com/klauspost/compress/pull/420) [#456](https://github.com/klauspost/compress/pull/456) [#437](https://github.com/klauspost/compress/pull/437) [#467](https://github.com/klauspost/compress/pull/467) [#468](https://github.com/klauspost/compress/pull/468) + * zstd: add arm64 xxhash assembly in [#464](https://github.com/klauspost/compress/pull/464) + * Add garbled for binaries for s2 in [#445](https://github.com/klauspost/compress/pull/445) +
+ +
+ See changes to v1.13.x + +* Aug 30, 2021 (v1.13.5) + * gz/zlib/flate: Alias stdlib errors [#425](https://github.com/klauspost/compress/pull/425) + * s2: Add block support to commandline tools [#413](https://github.com/klauspost/compress/pull/413) + * zstd: pooledZipWriter should return Writers to the same pool [#426](https://github.com/klauspost/compress/pull/426) + * Removed golang/snappy as external dependency for tests [#421](https://github.com/klauspost/compress/pull/421) + +* Aug 12, 2021 (v1.13.4) + * Add [snappy replacement package](https://github.com/klauspost/compress/tree/master/snappy). + * zstd: Fix incorrect encoding in "best" mode [#415](https://github.com/klauspost/compress/pull/415) + +* Aug 3, 2021 (v1.13.3) + * zstd: Improve Best compression [#404](https://github.com/klauspost/compress/pull/404) + * zstd: Fix WriteTo error forwarding [#411](https://github.com/klauspost/compress/pull/411) + * gzhttp: Return http.HandlerFunc instead of http.Handler. Unlikely breaking change. [#406](https://github.com/klauspost/compress/pull/406) + * s2sx: Fix max size error [#399](https://github.com/klauspost/compress/pull/399) + * zstd: Add optional stream content size on reset [#401](https://github.com/klauspost/compress/pull/401) + * zstd: use SpeedBestCompression for level >= 10 [#410](https://github.com/klauspost/compress/pull/410) + +* Jun 14, 2021 (v1.13.1) + * s2: Add full Snappy output support [#396](https://github.com/klauspost/compress/pull/396) + * zstd: Add configurable [Decoder window](https://pkg.go.dev/github.com/klauspost/compress/zstd#WithDecoderMaxWindow) size [#394](https://github.com/klauspost/compress/pull/394) + * gzhttp: Add header to skip compression [#389](https://github.com/klauspost/compress/pull/389) + * s2: Improve speed with bigger output margin [#395](https://github.com/klauspost/compress/pull/395) + +* Jun 3, 2021 (v1.13.0) + * Added [gzhttp](https://github.com/klauspost/compress/tree/master/gzhttp#gzip-handler) which allows wrapping HTTP servers and clients with GZIP compressors. + * zstd: Detect short invalid signatures [#382](https://github.com/klauspost/compress/pull/382) + * zstd: Spawn decoder goroutine only if needed. [#380](https://github.com/klauspost/compress/pull/380) +
+ + +
+ See changes to v1.12.x + +* May 25, 2021 (v1.12.3) + * deflate: Better/faster Huffman encoding [#374](https://github.com/klauspost/compress/pull/374) + * deflate: Allocate less for history. [#375](https://github.com/klauspost/compress/pull/375) + * zstd: Forward read errors [#373](https://github.com/klauspost/compress/pull/373) + +* Apr 27, 2021 (v1.12.2) + * zstd: Improve better/best compression [#360](https://github.com/klauspost/compress/pull/360) [#364](https://github.com/klauspost/compress/pull/364) [#365](https://github.com/klauspost/compress/pull/365) + * zstd: Add helpers to compress/decompress zstd inside zip files [#363](https://github.com/klauspost/compress/pull/363) + * deflate: Improve level 5+6 compression [#367](https://github.com/klauspost/compress/pull/367) + * s2: Improve better/best compression [#358](https://github.com/klauspost/compress/pull/358) [#359](https://github.com/klauspost/compress/pull/358) + * s2: Load after checking src limit on amd64. [#362](https://github.com/klauspost/compress/pull/362) + * s2sx: Limit max executable size [#368](https://github.com/klauspost/compress/pull/368) + +* Apr 14, 2021 (v1.12.1) + * snappy package removed. Upstream added as dependency. + * s2: Better compression in "best" mode [#353](https://github.com/klauspost/compress/pull/353) + * s2sx: Add stdin input and detect pre-compressed from signature [#352](https://github.com/klauspost/compress/pull/352) + * s2c/s2d: Add http as possible input [#348](https://github.com/klauspost/compress/pull/348) + * s2c/s2d/s2sx: Always truncate when writing files [#352](https://github.com/klauspost/compress/pull/352) + * zstd: Reduce memory usage further when using [WithLowerEncoderMem](https://pkg.go.dev/github.com/klauspost/compress/zstd#WithLowerEncoderMem) [#346](https://github.com/klauspost/compress/pull/346) + * s2: Fix potential problem with amd64 assembly and profilers [#349](https://github.com/klauspost/compress/pull/349) +
+ +
+ See changes to v1.11.x + +* Mar 26, 2021 (v1.11.13) + * zstd: Big speedup on small dictionary encodes [#344](https://github.com/klauspost/compress/pull/344) [#345](https://github.com/klauspost/compress/pull/345) + * zstd: Add [WithLowerEncoderMem](https://pkg.go.dev/github.com/klauspost/compress/zstd#WithLowerEncoderMem) encoder option [#336](https://github.com/klauspost/compress/pull/336) + * deflate: Improve entropy compression [#338](https://github.com/klauspost/compress/pull/338) + * s2: Clean up and minor performance improvement in best [#341](https://github.com/klauspost/compress/pull/341) + +* Mar 5, 2021 (v1.11.12) + * s2: Add `s2sx` binary that creates [self extracting archives](https://github.com/klauspost/compress/tree/master/s2#s2sx-self-extracting-archives). + * s2: Speed up decompression on non-assembly platforms [#328](https://github.com/klauspost/compress/pull/328) + +* Mar 1, 2021 (v1.11.9) + * s2: Add ARM64 decompression assembly. Around 2x output speed. [#324](https://github.com/klauspost/compress/pull/324) + * s2: Improve "better" speed and efficiency. [#325](https://github.com/klauspost/compress/pull/325) + * s2: Fix binaries. + +* Feb 25, 2021 (v1.11.8) + * s2: Fixed occational out-of-bounds write on amd64. Upgrade recommended. + * s2: Add AMD64 assembly for better mode. 25-50% faster. [#315](https://github.com/klauspost/compress/pull/315) + * s2: Less upfront decoder allocation. [#322](https://github.com/klauspost/compress/pull/322) + * zstd: Faster "compression" of incompressible data. [#314](https://github.com/klauspost/compress/pull/314) + * zip: Fix zip64 headers. [#313](https://github.com/klauspost/compress/pull/313) + +* Jan 14, 2021 (v1.11.7) + * Use Bytes() interface to get bytes across packages. [#309](https://github.com/klauspost/compress/pull/309) + * s2: Add 'best' compression option. [#310](https://github.com/klauspost/compress/pull/310) + * s2: Add ReaderMaxBlockSize, changes `s2.NewReader` signature to include varargs. [#311](https://github.com/klauspost/compress/pull/311) + * s2: Fix crash on small better buffers. [#308](https://github.com/klauspost/compress/pull/308) + * s2: Clean up decoder. [#312](https://github.com/klauspost/compress/pull/312) + +* Jan 7, 2021 (v1.11.6) + * zstd: Make decoder allocations smaller [#306](https://github.com/klauspost/compress/pull/306) + * zstd: Free Decoder resources when Reset is called with a nil io.Reader [#305](https://github.com/klauspost/compress/pull/305) + +* Dec 20, 2020 (v1.11.4) + * zstd: Add Best compression mode [#304](https://github.com/klauspost/compress/pull/304) + * Add header decoder [#299](https://github.com/klauspost/compress/pull/299) + * s2: Add uncompressed stream option [#297](https://github.com/klauspost/compress/pull/297) + * Simplify/speed up small blocks with known max size. [#300](https://github.com/klauspost/compress/pull/300) + * zstd: Always reset literal dict encoder [#303](https://github.com/klauspost/compress/pull/303) + +* Nov 15, 2020 (v1.11.3) + * inflate: 10-15% faster decompression [#293](https://github.com/klauspost/compress/pull/293) + * zstd: Tweak DecodeAll default allocation [#295](https://github.com/klauspost/compress/pull/295) + +* Oct 11, 2020 (v1.11.2) + * s2: Fix out of bounds read in "better" block compression [#291](https://github.com/klauspost/compress/pull/291) + +* Oct 1, 2020 (v1.11.1) + * zstd: Set allLitEntropy true in default configuration [#286](https://github.com/klauspost/compress/pull/286) + +* Sept 8, 2020 (v1.11.0) + * zstd: Add experimental compression [dictionaries](https://github.com/klauspost/compress/tree/master/zstd#dictionaries) [#281](https://github.com/klauspost/compress/pull/281) + * zstd: Fix mixed Write and ReadFrom calls [#282](https://github.com/klauspost/compress/pull/282) + * inflate/gz: Limit variable shifts, ~5% faster decompression [#274](https://github.com/klauspost/compress/pull/274) +
+ +
+ See changes to v1.10.x + +* July 8, 2020 (v1.10.11) + * zstd: Fix extra block when compressing with ReadFrom. [#278](https://github.com/klauspost/compress/pull/278) + * huff0: Also populate compression table when reading decoding table. [#275](https://github.com/klauspost/compress/pull/275) + +* June 23, 2020 (v1.10.10) + * zstd: Skip entropy compression in fastest mode when no matches. [#270](https://github.com/klauspost/compress/pull/270) + +* June 16, 2020 (v1.10.9): + * zstd: API change for specifying dictionaries. See [#268](https://github.com/klauspost/compress/pull/268) + * zip: update CreateHeaderRaw to handle zip64 fields. [#266](https://github.com/klauspost/compress/pull/266) + * Fuzzit tests removed. The service has been purchased and is no longer available. + +* June 5, 2020 (v1.10.8): + * 1.15x faster zstd block decompression. [#265](https://github.com/klauspost/compress/pull/265) + +* June 1, 2020 (v1.10.7): + * Added zstd decompression [dictionary support](https://github.com/klauspost/compress/tree/master/zstd#dictionaries) + * Increase zstd decompression speed up to 1.19x. [#259](https://github.com/klauspost/compress/pull/259) + * Remove internal reset call in zstd compression and reduce allocations. [#263](https://github.com/klauspost/compress/pull/263) + +* May 21, 2020: (v1.10.6) + * zstd: Reduce allocations while decoding. [#258](https://github.com/klauspost/compress/pull/258), [#252](https://github.com/klauspost/compress/pull/252) + * zstd: Stricter decompression checks. + +* April 12, 2020: (v1.10.5) + * s2-commands: Flush output when receiving SIGINT. [#239](https://github.com/klauspost/compress/pull/239) + +* Apr 8, 2020: (v1.10.4) + * zstd: Minor/special case optimizations. [#251](https://github.com/klauspost/compress/pull/251), [#250](https://github.com/klauspost/compress/pull/250), [#249](https://github.com/klauspost/compress/pull/249), [#247](https://github.com/klauspost/compress/pull/247) +* Mar 11, 2020: (v1.10.3) + * s2: Use S2 encoder in pure Go mode for Snappy output as well. [#245](https://github.com/klauspost/compress/pull/245) + * s2: Fix pure Go block encoder. [#244](https://github.com/klauspost/compress/pull/244) + * zstd: Added "better compression" mode. [#240](https://github.com/klauspost/compress/pull/240) + * zstd: Improve speed of fastest compression mode by 5-10% [#241](https://github.com/klauspost/compress/pull/241) + * zstd: Skip creating encoders when not needed. [#238](https://github.com/klauspost/compress/pull/238) + +* Feb 27, 2020: (v1.10.2) + * Close to 50% speedup in inflate (gzip/zip decompression). [#236](https://github.com/klauspost/compress/pull/236) [#234](https://github.com/klauspost/compress/pull/234) [#232](https://github.com/klauspost/compress/pull/232) + * Reduce deflate level 1-6 memory usage up to 59%. [#227](https://github.com/klauspost/compress/pull/227) + +* Feb 18, 2020: (v1.10.1) + * Fix zstd crash when resetting multiple times without sending data. [#226](https://github.com/klauspost/compress/pull/226) + * deflate: Fix dictionary use on level 1-6. [#224](https://github.com/klauspost/compress/pull/224) + * Remove deflate writer reference when closing. [#224](https://github.com/klauspost/compress/pull/224) + +* Feb 4, 2020: (v1.10.0) + * Add optional dictionary to [stateless deflate](https://pkg.go.dev/github.com/klauspost/compress/flate?tab=doc#StatelessDeflate). Breaking change, send `nil` for previous behaviour. [#216](https://github.com/klauspost/compress/pull/216) + * Fix buffer overflow on repeated small block deflate. [#218](https://github.com/klauspost/compress/pull/218) + * Allow copying content from an existing ZIP file without decompressing+compressing. [#214](https://github.com/klauspost/compress/pull/214) + * Added [S2](https://github.com/klauspost/compress/tree/master/s2#s2-compression) AMD64 assembler and various optimizations. Stream speed >10GB/s. [#186](https://github.com/klauspost/compress/pull/186) + +
+ +
+ See changes prior to v1.10.0 + +* Jan 20,2020 (v1.9.8) Optimize gzip/deflate with better size estimates and faster table generation. [#207](https://github.com/klauspost/compress/pull/207) by [luyu6056](https://github.com/luyu6056), [#206](https://github.com/klauspost/compress/pull/206). +* Jan 11, 2020: S2 Encode/Decode will use provided buffer if capacity is big enough. [#204](https://github.com/klauspost/compress/pull/204) +* Jan 5, 2020: (v1.9.7) Fix another zstd regression in v1.9.5 - v1.9.6 removed. +* Jan 4, 2020: (v1.9.6) Regression in v1.9.5 fixed causing corrupt zstd encodes in rare cases. +* Jan 4, 2020: Faster IO in [s2c + s2d commandline tools](https://github.com/klauspost/compress/tree/master/s2#commandline-tools) compression/decompression. [#192](https://github.com/klauspost/compress/pull/192) +* Dec 29, 2019: Removed v1.9.5 since fuzz tests showed a compatibility problem with the reference zstandard decoder. +* Dec 29, 2019: (v1.9.5) zstd: 10-20% faster block compression. [#199](https://github.com/klauspost/compress/pull/199) +* Dec 29, 2019: [zip](https://godoc.org/github.com/klauspost/compress/zip) package updated with latest Go features +* Dec 29, 2019: zstd: Single segment flag condintions tweaked. [#197](https://github.com/klauspost/compress/pull/197) +* Dec 18, 2019: s2: Faster compression when ReadFrom is used. [#198](https://github.com/klauspost/compress/pull/198) +* Dec 10, 2019: s2: Fix repeat length output when just above at 16MB limit. +* Dec 10, 2019: zstd: Add function to get decoder as io.ReadCloser. [#191](https://github.com/klauspost/compress/pull/191) +* Dec 3, 2019: (v1.9.4) S2: limit max repeat length. [#188](https://github.com/klauspost/compress/pull/188) +* Dec 3, 2019: Add [WithNoEntropyCompression](https://godoc.org/github.com/klauspost/compress/zstd#WithNoEntropyCompression) to zstd [#187](https://github.com/klauspost/compress/pull/187) +* Dec 3, 2019: Reduce memory use for tests. Check for leaked goroutines. +* Nov 28, 2019 (v1.9.3) Less allocations in stateless deflate. +* Nov 28, 2019: 5-20% Faster huff0 decode. Impacts zstd as well. [#184](https://github.com/klauspost/compress/pull/184) +* Nov 12, 2019 (v1.9.2) Added [Stateless Compression](#stateless-compression) for gzip/deflate. +* Nov 12, 2019: Fixed zstd decompression of large single blocks. [#180](https://github.com/klauspost/compress/pull/180) +* Nov 11, 2019: Set default [s2c](https://github.com/klauspost/compress/tree/master/s2#commandline-tools) block size to 4MB. +* Nov 11, 2019: Reduce inflate memory use by 1KB. +* Nov 10, 2019: Less allocations in deflate bit writer. +* Nov 10, 2019: Fix inconsistent error returned by zstd decoder. +* Oct 28, 2019 (v1.9.1) ztsd: Fix crash when compressing blocks. [#174](https://github.com/klauspost/compress/pull/174) +* Oct 24, 2019 (v1.9.0) zstd: Fix rare data corruption [#173](https://github.com/klauspost/compress/pull/173) +* Oct 24, 2019 zstd: Fix huff0 out of buffer write [#171](https://github.com/klauspost/compress/pull/171) and always return errors [#172](https://github.com/klauspost/compress/pull/172) +* Oct 10, 2019: Big deflate rewrite, 30-40% faster with better compression [#105](https://github.com/klauspost/compress/pull/105) + +
+ +
+ See changes prior to v1.9.0 + +* Oct 10, 2019: (v1.8.6) zstd: Allow partial reads to get flushed data. [#169](https://github.com/klauspost/compress/pull/169) +* Oct 3, 2019: Fix inconsistent results on broken zstd streams. +* Sep 25, 2019: Added `-rm` (remove source files) and `-q` (no output except errors) to `s2c` and `s2d` [commands](https://github.com/klauspost/compress/tree/master/s2#commandline-tools) +* Sep 16, 2019: (v1.8.4) Add `s2c` and `s2d` [commandline tools](https://github.com/klauspost/compress/tree/master/s2#commandline-tools). +* Sep 10, 2019: (v1.8.3) Fix s2 decoder [Skip](https://godoc.org/github.com/klauspost/compress/s2#Reader.Skip). +* Sep 7, 2019: zstd: Added [WithWindowSize](https://godoc.org/github.com/klauspost/compress/zstd#WithWindowSize), contributed by [ianwilkes](https://github.com/ianwilkes). +* Sep 5, 2019: (v1.8.2) Add [WithZeroFrames](https://godoc.org/github.com/klauspost/compress/zstd#WithZeroFrames) which adds full zero payload block encoding option. +* Sep 5, 2019: Lazy initialization of zstandard predefined en/decoder tables. +* Aug 26, 2019: (v1.8.1) S2: 1-2% compression increase in "better" compression mode. +* Aug 26, 2019: zstd: Check maximum size of Huffman 1X compressed literals while decoding. +* Aug 24, 2019: (v1.8.0) Added [S2 compression](https://github.com/klauspost/compress/tree/master/s2#s2-compression), a high performance replacement for Snappy. +* Aug 21, 2019: (v1.7.6) Fixed minor issues found by fuzzer. One could lead to zstd not decompressing. +* Aug 18, 2019: Add [fuzzit](https://fuzzit.dev/) continuous fuzzing. +* Aug 14, 2019: zstd: Skip incompressible data 2x faster. [#147](https://github.com/klauspost/compress/pull/147) +* Aug 4, 2019 (v1.7.5): Better literal compression. [#146](https://github.com/klauspost/compress/pull/146) +* Aug 4, 2019: Faster zstd compression. [#143](https://github.com/klauspost/compress/pull/143) [#144](https://github.com/klauspost/compress/pull/144) +* Aug 4, 2019: Faster zstd decompression. [#145](https://github.com/klauspost/compress/pull/145) [#143](https://github.com/klauspost/compress/pull/143) [#142](https://github.com/klauspost/compress/pull/142) +* July 15, 2019 (v1.7.4): Fix double EOF block in rare cases on zstd encoder. +* July 15, 2019 (v1.7.3): Minor speedup/compression increase in default zstd encoder. +* July 14, 2019: zstd decoder: Fix decompression error on multiple uses with mixed content. +* July 7, 2019 (v1.7.2): Snappy update, zstd decoder potential race fix. +* June 17, 2019: zstd decompression bugfix. +* June 17, 2019: fix 32 bit builds. +* June 17, 2019: Easier use in modules (less dependencies). +* June 9, 2019: New stronger "default" [zstd](https://github.com/klauspost/compress/tree/master/zstd#zstd) compression mode. Matches zstd default compression ratio. +* June 5, 2019: 20-40% throughput in [zstandard](https://github.com/klauspost/compress/tree/master/zstd#zstd) compression and better compression. +* June 5, 2019: deflate/gzip compression: Reduce memory usage of lower compression levels. +* June 2, 2019: Added [zstandard](https://github.com/klauspost/compress/tree/master/zstd#zstd) compression! +* May 25, 2019: deflate/gzip: 10% faster bit writer, mostly visible in lower levels. +* Apr 22, 2019: [zstd](https://github.com/klauspost/compress/tree/master/zstd#zstd) decompression added. +* Aug 1, 2018: Added [huff0 README](https://github.com/klauspost/compress/tree/master/huff0#huff0-entropy-compression). +* Jul 8, 2018: Added [Performance Update 2018](#performance-update-2018) below. +* Jun 23, 2018: Merged [Go 1.11 inflate optimizations](https://go-review.googlesource.com/c/go/+/102235). Go 1.9 is now required. Backwards compatible version tagged with [v1.3.0](https://github.com/klauspost/compress/releases/tag/v1.3.0). +* Apr 2, 2018: Added [huff0](https://godoc.org/github.com/klauspost/compress/huff0) en/decoder. Experimental for now, API may change. +* Mar 4, 2018: Added [FSE Entropy](https://godoc.org/github.com/klauspost/compress/fse) en/decoder. Experimental for now, API may change. +* Nov 3, 2017: Add compression [Estimate](https://godoc.org/github.com/klauspost/compress#Estimate) function. +* May 28, 2017: Reduce allocations when resetting decoder. +* Apr 02, 2017: Change back to official crc32, since changes were merged in Go 1.7. +* Jan 14, 2017: Reduce stack pressure due to array copies. See [Issue #18625](https://github.com/golang/go/issues/18625). +* Oct 25, 2016: Level 2-4 have been rewritten and now offers significantly better performance than before. +* Oct 20, 2016: Port zlib changes from Go 1.7 to fix zlib writer issue. Please update. +* Oct 16, 2016: Go 1.7 changes merged. Apples to apples this package is a few percent faster, but has a significantly better balance between speed and compression per level. +* Mar 24, 2016: Always attempt Huffman encoding on level 4-7. This improves base 64 encoded data compression. +* Mar 24, 2016: Small speedup for level 1-3. +* Feb 19, 2016: Faster bit writer, level -2 is 15% faster, level 1 is 4% faster. +* Feb 19, 2016: Handle small payloads faster in level 1-3. +* Feb 19, 2016: Added faster level 2 + 3 compression modes. +* Feb 19, 2016: [Rebalanced compression levels](https://blog.klauspost.com/rebalancing-deflate-compression-levels/), so there is a more even progresssion in terms of compression. New default level is 5. +* Feb 14, 2016: Snappy: Merge upstream changes. +* Feb 14, 2016: Snappy: Fix aggressive skipping. +* Feb 14, 2016: Snappy: Update benchmark. +* Feb 13, 2016: Deflate: Fixed assembler problem that could lead to sub-optimal compression. +* Feb 12, 2016: Snappy: Added AMD64 SSE 4.2 optimizations to matching, which makes easy to compress material run faster. Typical speedup is around 25%. +* Feb 9, 2016: Added Snappy package fork. This version is 5-7% faster, much more on hard to compress content. +* Jan 30, 2016: Optimize level 1 to 3 by not considering static dictionary or storing uncompressed. ~4-5% speedup. +* Jan 16, 2016: Optimization on deflate level 1,2,3 compression. +* Jan 8 2016: Merge [CL 18317](https://go-review.googlesource.com/#/c/18317): fix reading, writing of zip64 archives. +* Dec 8 2015: Make level 1 and -2 deterministic even if write size differs. +* Dec 8 2015: Split encoding functions, so hashing and matching can potentially be inlined. 1-3% faster on AMD64. 5% faster on other platforms. +* Dec 8 2015: Fixed rare [one byte out-of bounds read](https://github.com/klauspost/compress/issues/20). Please update! +* Nov 23 2015: Optimization on token writer. ~2-4% faster. Contributed by [@dsnet](https://github.com/dsnet). +* Nov 20 2015: Small optimization to bit writer on 64 bit systems. +* Nov 17 2015: Fixed out-of-bound errors if the underlying Writer returned an error. See [#15](https://github.com/klauspost/compress/issues/15). +* Nov 12 2015: Added [io.WriterTo](https://golang.org/pkg/io/#WriterTo) support to gzip/inflate. +* Nov 11 2015: Merged [CL 16669](https://go-review.googlesource.com/#/c/16669/4): archive/zip: enable overriding (de)compressors per file +* Oct 15 2015: Added skipping on uncompressible data. Random data speed up >5x. + +
+ +# deflate usage + +The packages are drop-in replacements for standard libraries. Simply replace the import path to use them: + +| old import | new import | Documentation +|--------------------|-----------------------------------------|--------------------| +| `compress/gzip` | `github.com/klauspost/compress/gzip` | [gzip](https://pkg.go.dev/github.com/klauspost/compress/gzip?tab=doc) +| `compress/zlib` | `github.com/klauspost/compress/zlib` | [zlib](https://pkg.go.dev/github.com/klauspost/compress/zlib?tab=doc) +| `archive/zip` | `github.com/klauspost/compress/zip` | [zip](https://pkg.go.dev/github.com/klauspost/compress/zip?tab=doc) +| `compress/flate` | `github.com/klauspost/compress/flate` | [flate](https://pkg.go.dev/github.com/klauspost/compress/flate?tab=doc) + +* Optimized [deflate](https://godoc.org/github.com/klauspost/compress/flate) packages which can be used as a dropin replacement for [gzip](https://godoc.org/github.com/klauspost/compress/gzip), [zip](https://godoc.org/github.com/klauspost/compress/zip) and [zlib](https://godoc.org/github.com/klauspost/compress/zlib). + +You may also be interested in [pgzip](https://github.com/klauspost/pgzip), which is a drop in replacement for gzip, which support multithreaded compression on big files and the optimized [crc32](https://github.com/klauspost/crc32) package used by these packages. + +The packages contains the same as the standard library, so you can use the godoc for that: [gzip](http://golang.org/pkg/compress/gzip/), [zip](http://golang.org/pkg/archive/zip/), [zlib](http://golang.org/pkg/compress/zlib/), [flate](http://golang.org/pkg/compress/flate/). + +Currently there is only minor speedup on decompression (mostly CRC32 calculation). + +Memory usage is typically 1MB for a Writer. stdlib is in the same range. +If you expect to have a lot of concurrently allocated Writers consider using +the stateless compress described below. + +For compression performance, see: [this spreadsheet](https://docs.google.com/spreadsheets/d/1nuNE2nPfuINCZJRMt6wFWhKpToF95I47XjSsc-1rbPQ/edit?usp=sharing). + +To disable all assembly add `-tags=noasm`. This works across all packages. + +# Stateless compression + +This package offers stateless compression as a special option for gzip/deflate. +It will do compression but without maintaining any state between Write calls. + +This means there will be no memory kept between Write calls, but compression and speed will be suboptimal. + +This is only relevant in cases where you expect to run many thousands of compressors concurrently, +but with very little activity. This is *not* intended for regular web servers serving individual requests. + +Because of this, the size of actual Write calls will affect output size. + +In gzip, specify level `-3` / `gzip.StatelessCompression` to enable. + +For direct deflate use, NewStatelessWriter and StatelessDeflate are available. See [documentation](https://godoc.org/github.com/klauspost/compress/flate#NewStatelessWriter) + +A `bufio.Writer` can of course be used to control write sizes. For example, to use a 4KB buffer: + +```go + // replace 'ioutil.Discard' with your output. + gzw, err := gzip.NewWriterLevel(ioutil.Discard, gzip.StatelessCompression) + if err != nil { + return err + } + defer gzw.Close() + + w := bufio.NewWriterSize(gzw, 4096) + defer w.Flush() + + // Write to 'w' +``` + +This will only use up to 4KB in memory when the writer is idle. + +Compression is almost always worse than the fastest compression level +and each write will allocate (a little) memory. + +# Performance Update 2018 + +It has been a while since we have been looking at the speed of this package compared to the standard library, so I thought I would re-do my tests and give some overall recommendations based on the current state. All benchmarks have been performed with Go 1.10 on my Desktop Intel(R) Core(TM) i7-2600 CPU @3.40GHz. Since I last ran the tests, I have gotten more RAM, which means tests with big files are no longer limited by my SSD. + +The raw results are in my [updated spreadsheet](https://docs.google.com/spreadsheets/d/1nuNE2nPfuINCZJRMt6wFWhKpToF95I47XjSsc-1rbPQ/edit?usp=sharing). Due to cgo changes and upstream updates i could not get the cgo version of gzip to compile. Instead I included the [zstd](https://github.com/datadog/zstd) cgo implementation. If I get cgo gzip to work again, I might replace the results in the sheet. + +The columns to take note of are: *MB/s* - the throughput. *Reduction* - the data size reduction in percent of the original. *Rel Speed* relative speed compared to the standard library at the same level. *Smaller* - how many percent smaller is the compressed output compared to stdlib. Negative means the output was bigger. *Loss* means the loss (or gain) in compression as a percentage difference of the input. + +The `gzstd` (standard library gzip) and `gzkp` (this package gzip) only uses one CPU core. [`pgzip`](https://github.com/klauspost/pgzip), [`bgzf`](https://github.com/biogo/hts/tree/master/bgzf) uses all 4 cores. [`zstd`](https://github.com/DataDog/zstd) uses one core, and is a beast (but not Go, yet). + + +## Overall differences. + +There appears to be a roughly 5-10% speed advantage over the standard library when comparing at similar compression levels. + +The biggest difference you will see is the result of [re-balancing](https://blog.klauspost.com/rebalancing-deflate-compression-levels/) the compression levels. I wanted by library to give a smoother transition between the compression levels than the standard library. + +This package attempts to provide a more smooth transition, where "1" is taking a lot of shortcuts, "5" is the reasonable trade-off and "9" is the "give me the best compression", and the values in between gives something reasonable in between. The standard library has big differences in levels 1-4, but levels 5-9 having no significant gains - often spending a lot more time than can be justified by the achieved compression. + +There are links to all the test data in the [spreadsheet](https://docs.google.com/spreadsheets/d/1nuNE2nPfuINCZJRMt6wFWhKpToF95I47XjSsc-1rbPQ/edit?usp=sharing) in the top left field on each tab. + +## Web Content + +This test set aims to emulate typical use in a web server. The test-set is 4GB data in 53k files, and is a mixture of (mostly) HTML, JS, CSS. + +Since level 1 and 9 are close to being the same code, they are quite close. But looking at the levels in-between the differences are quite big. + +Looking at level 6, this package is 88% faster, but will output about 6% more data. For a web server, this means you can serve 88% more data, but have to pay for 6% more bandwidth. You can draw your own conclusions on what would be the most expensive for your case. + +## Object files + +This test is for typical data files stored on a server. In this case it is a collection of Go precompiled objects. They are very compressible. + +The picture is similar to the web content, but with small differences since this is very compressible. Levels 2-3 offer good speed, but is sacrificing quite a bit of compression. + +The standard library seems suboptimal on level 3 and 4 - offering both worse compression and speed than level 6 & 7 of this package respectively. + +## Highly Compressible File + +This is a JSON file with very high redundancy. The reduction starts at 95% on level 1, so in real life terms we are dealing with something like a highly redundant stream of data, etc. + +It is definitely visible that we are dealing with specialized content here, so the results are very scattered. This package does not do very well at levels 1-4, but picks up significantly at level 5 and levels 7 and 8 offering great speed for the achieved compression. + +So if you know you content is extremely compressible you might want to go slightly higher than the defaults. The standard library has a huge gap between levels 3 and 4 in terms of speed (2.75x slowdown), so it offers little "middle ground". + +## Medium-High Compressible + +This is a pretty common test corpus: [enwik9](http://mattmahoney.net/dc/textdata.html). It contains the first 10^9 bytes of the English Wikipedia dump on Mar. 3, 2006. This is a very good test of typical text based compression and more data heavy streams. + +We see a similar picture here as in "Web Content". On equal levels some compression is sacrificed for more speed. Level 5 seems to be the best trade-off between speed and size, beating stdlib level 3 in both. + +## Medium Compressible + +I will combine two test sets, one [10GB file set](http://mattmahoney.net/dc/10gb.html) and a VM disk image (~8GB). Both contain different data types and represent a typical backup scenario. + +The most notable thing is how quickly the standard library drops to very low compression speeds around level 5-6 without any big gains in compression. Since this type of data is fairly common, this does not seem like good behavior. + + +## Un-compressible Content + +This is mainly a test of how good the algorithms are at detecting un-compressible input. The standard library only offers this feature with very conservative settings at level 1. Obviously there is no reason for the algorithms to try to compress input that cannot be compressed. The only downside is that it might skip some compressible data on false detections. + + +## Huffman only compression + +This compression library adds a special compression level, named `HuffmanOnly`, which allows near linear time compression. This is done by completely disabling matching of previous data, and only reduce the number of bits to represent each character. + +This means that often used characters, like 'e' and ' ' (space) in text use the fewest bits to represent, and rare characters like '¤' takes more bits to represent. For more information see [wikipedia](https://en.wikipedia.org/wiki/Huffman_coding) or this nice [video](https://youtu.be/ZdooBTdW5bM). + +Since this type of compression has much less variance, the compression speed is mostly unaffected by the input data, and is usually more than *180MB/s* for a single core. + +The downside is that the compression ratio is usually considerably worse than even the fastest conventional compression. The compression ratio can never be better than 8:1 (12.5%). + +The linear time compression can be used as a "better than nothing" mode, where you cannot risk the encoder to slow down on some content. For comparison, the size of the "Twain" text is *233460 bytes* (+29% vs. level 1) and encode speed is 144MB/s (4.5x level 1). So in this case you trade a 30% size increase for a 4 times speedup. + +For more information see my blog post on [Fast Linear Time Compression](http://blog.klauspost.com/constant-time-gzipzip-compression/). + +This is implemented on Go 1.7 as "Huffman Only" mode, though not exposed for gzip. + +# Other packages + +Here are other packages of good quality and pure Go (no cgo wrappers or autoconverted code): + +* [github.com/pierrec/lz4](https://github.com/pierrec/lz4) - strong multithreaded LZ4 compression. +* [github.com/cosnicolaou/pbzip2](https://github.com/cosnicolaou/pbzip2) - multithreaded bzip2 decompression. +* [github.com/dsnet/compress](https://github.com/dsnet/compress) - brotli decompression, bzip2 writer. +* [github.com/ronanh/intcomp](https://github.com/ronanh/intcomp) - Integer compression. +* [github.com/spenczar/fpc](https://github.com/spenczar/fpc) - Float compression. +* [github.com/minio/zipindex](https://github.com/minio/zipindex) - External ZIP directory index. +* [github.com/ybirader/pzip](https://github.com/ybirader/pzip) - Fast concurrent zip archiver and extractor. + +# license + +This code is licensed under the same conditions as the original Go code. See LICENSE file. diff --git a/vendor/github.com/klauspost/compress/SECURITY.md b/vendor/github.com/klauspost/compress/SECURITY.md new file mode 100644 index 000000000..ca6685e2b --- /dev/null +++ b/vendor/github.com/klauspost/compress/SECURITY.md @@ -0,0 +1,25 @@ +# Security Policy + +## Supported Versions + +Security updates are applied only to the latest release. + +## Vulnerability Definition + +A security vulnerability is a bug that with certain input triggers a crash or an infinite loop. Most calls will have varying execution time and only in rare cases will slow operation be considered a security vulnerability. + +Corrupted output generally is not considered a security vulnerability, unless independent operations are able to affect each other. Note that not all functionality is re-entrant and safe to use concurrently. + +Out-of-memory crashes only applies if the en/decoder uses an abnormal amount of memory, with appropriate options applied, to limit maximum window size, concurrency, etc. However, if you are in doubt you are welcome to file a security issue. + +It is assumed that all callers are trusted, meaning internal data exposed through reflection or inspection of returned data structures is not considered a vulnerability. + +Vulnerabilities resulting from compiler/assembler errors should be reported upstream. Depending on the severity this package may or may not implement a workaround. + +## Reporting a Vulnerability + +If you have discovered a security vulnerability in this project, please report it privately. **Do not disclose it as a public issue.** This gives us time to work with you to fix the issue before public exposure, reducing the chance that the exploit will be used before a patch is released. + +Please disclose it at [security advisory](https://github.com/klauspost/compress/security/advisories/new). If possible please provide a minimal reproducer. If the issue only applies to a single platform, it would be helpful to provide access to that. + +This project is maintained by a team of volunteers on a reasonable-effort basis. As such, vulnerabilities will be disclosed in a best effort base. diff --git a/vendor/github.com/klauspost/compress/compressible.go b/vendor/github.com/klauspost/compress/compressible.go new file mode 100644 index 000000000..ea5a692d5 --- /dev/null +++ b/vendor/github.com/klauspost/compress/compressible.go @@ -0,0 +1,85 @@ +package compress + +import "math" + +// Estimate returns a normalized compressibility estimate of block b. +// Values close to zero are likely uncompressible. +// Values above 0.1 are likely to be compressible. +// Values above 0.5 are very compressible. +// Very small lengths will return 0. +func Estimate(b []byte) float64 { + if len(b) < 16 { + return 0 + } + + // Correctly predicted order 1 + hits := 0 + lastMatch := false + var o1 [256]byte + var hist [256]int + c1 := byte(0) + for _, c := range b { + if c == o1[c1] { + // We only count a hit if there was two correct predictions in a row. + if lastMatch { + hits++ + } + lastMatch = true + } else { + lastMatch = false + } + o1[c1] = c + c1 = c + hist[c]++ + } + + // Use x^0.6 to give better spread + prediction := math.Pow(float64(hits)/float64(len(b)), 0.6) + + // Calculate histogram distribution + variance := float64(0) + avg := float64(len(b)) / 256 + + for _, v := range hist { + Δ := float64(v) - avg + variance += Δ * Δ + } + + stddev := math.Sqrt(float64(variance)) / float64(len(b)) + exp := math.Sqrt(1 / float64(len(b))) + + // Subtract expected stddev + stddev -= exp + if stddev < 0 { + stddev = 0 + } + stddev *= 1 + exp + + // Use x^0.4 to give better spread + entropy := math.Pow(stddev, 0.4) + + // 50/50 weight between prediction and histogram distribution + return math.Pow((prediction+entropy)/2, 0.9) +} + +// ShannonEntropyBits returns the number of bits minimum required to represent +// an entropy encoding of the input bytes. +// https://en.wiktionary.org/wiki/Shannon_entropy +func ShannonEntropyBits(b []byte) int { + if len(b) == 0 { + return 0 + } + var hist [256]int + for _, c := range b { + hist[c]++ + } + shannon := float64(0) + invTotal := 1.0 / float64(len(b)) + for _, v := range hist[:] { + if v > 0 { + n := float64(v) + shannon += math.Ceil(-math.Log2(n*invTotal) * n) + } + } + return int(math.Ceil(shannon)) +} diff --git a/vendor/github.com/klauspost/compress/fse/README.md b/vendor/github.com/klauspost/compress/fse/README.md new file mode 100644 index 000000000..ea7324da6 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/README.md @@ -0,0 +1,79 @@ +# Finite State Entropy + +This package provides Finite State Entropy encoding and decoding. + +Finite State Entropy (also referenced as [tANS](https://en.wikipedia.org/wiki/Asymmetric_numeral_systems#tANS)) +encoding provides a fast near-optimal symbol encoding/decoding +for byte blocks as implemented in [zstandard](https://github.com/facebook/zstd). + +This can be used for compressing input with a lot of similar input values to the smallest number of bytes. +This does not perform any multi-byte [dictionary coding](https://en.wikipedia.org/wiki/Dictionary_coder) as LZ coders, +but it can be used as a secondary step to compressors (like Snappy) that does not do entropy encoding. + +* [Godoc documentation](https://godoc.org/github.com/klauspost/compress/fse) + +## News + + * Feb 2018: First implementation released. Consider this beta software for now. + +# Usage + +This package provides a low level interface that allows to compress single independent blocks. + +Each block is separate, and there is no built in integrity checks. +This means that the caller should keep track of block sizes and also do checksums if needed. + +Compressing a block is done via the [`Compress`](https://godoc.org/github.com/klauspost/compress/fse#Compress) function. +You must provide input and will receive the output and maybe an error. + +These error values can be returned: + +| Error | Description | +|---------------------|-----------------------------------------------------------------------------| +| `` | Everything ok, output is returned | +| `ErrIncompressible` | Returned when input is judged to be too hard to compress | +| `ErrUseRLE` | Returned from the compressor when the input is a single byte value repeated | +| `(error)` | An internal error occurred. | + +As can be seen above there are errors that will be returned even under normal operation so it is important to handle these. + +To reduce allocations you can provide a [`Scratch`](https://godoc.org/github.com/klauspost/compress/fse#Scratch) object +that can be re-used for successive calls. Both compression and decompression accepts a `Scratch` object, and the same +object can be used for both. + +Be aware, that when re-using a `Scratch` object that the *output* buffer is also re-used, so if you are still using this +you must set the `Out` field in the scratch to nil. The same buffer is used for compression and decompression output. + +Decompressing is done by calling the [`Decompress`](https://godoc.org/github.com/klauspost/compress/fse#Decompress) function. +You must provide the output from the compression stage, at exactly the size you got back. If you receive an error back +your input was likely corrupted. + +It is important to note that a successful decoding does *not* mean your output matches your original input. +There are no integrity checks, so relying on errors from the decompressor does not assure your data is valid. + +For more detailed usage, see examples in the [godoc documentation](https://godoc.org/github.com/klauspost/compress/fse#pkg-examples). + +# Performance + +A lot of factors are affecting speed. Block sizes and compressibility of the material are primary factors. +All compression functions are currently only running on the calling goroutine so only one core will be used per block. + +The compressor is significantly faster if symbols are kept as small as possible. The highest byte value of the input +is used to reduce some of the processing, so if all your input is above byte value 64 for instance, it may be +beneficial to transpose all your input values down by 64. + +With moderate block sizes around 64k speed are typically 200MB/s per core for compression and +around 300MB/s decompression speed. + +The same hardware typically does Huffman (deflate) encoding at 125MB/s and decompression at 100MB/s. + +# Plans + +At one point, more internals will be exposed to facilitate more "expert" usage of the components. + +A streaming interface is also likely to be implemented. Likely compatible with [FSE stream format](https://github.com/Cyan4973/FiniteStateEntropy/blob/dev/programs/fileio.c#L261). + +# Contributing + +Contributions are always welcome. Be aware that adding public functions will require good justification and breaking +changes will likely not be accepted. If in doubt open an issue before writing the PR. \ No newline at end of file diff --git a/vendor/github.com/klauspost/compress/fse/bitreader.go b/vendor/github.com/klauspost/compress/fse/bitreader.go new file mode 100644 index 000000000..f65eb3909 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/bitreader.go @@ -0,0 +1,122 @@ +// Copyright 2018 Klaus Post. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// Based on work Copyright (c) 2013, Yann Collet, released under BSD License. + +package fse + +import ( + "encoding/binary" + "errors" + "io" +) + +// bitReader reads a bitstream in reverse. +// The last set bit indicates the start of the stream and is used +// for aligning the input. +type bitReader struct { + in []byte + off uint // next byte to read is at in[off - 1] + value uint64 + bitsRead uint8 +} + +// init initializes and resets the bit reader. +func (b *bitReader) init(in []byte) error { + if len(in) < 1 { + return errors.New("corrupt stream: too short") + } + b.in = in + b.off = uint(len(in)) + // The highest bit of the last byte indicates where to start + v := in[len(in)-1] + if v == 0 { + return errors.New("corrupt stream, did not find end of stream") + } + b.bitsRead = 64 + b.value = 0 + if len(in) >= 8 { + b.fillFastStart() + } else { + b.fill() + b.fill() + } + b.bitsRead += 8 - uint8(highBits(uint32(v))) + return nil +} + +// getBits will return n bits. n can be 0. +func (b *bitReader) getBits(n uint8) uint16 { + if n == 0 || b.bitsRead >= 64 { + return 0 + } + return b.getBitsFast(n) +} + +// getBitsFast requires that at least one bit is requested every time. +// There are no checks if the buffer is filled. +func (b *bitReader) getBitsFast(n uint8) uint16 { + const regMask = 64 - 1 + v := uint16((b.value << (b.bitsRead & regMask)) >> ((regMask + 1 - n) & regMask)) + b.bitsRead += n + return v +} + +// fillFast() will make sure at least 32 bits are available. +// There must be at least 4 bytes available. +func (b *bitReader) fillFast() { + if b.bitsRead < 32 { + return + } + // 2 bounds checks. + v := b.in[b.off-4:] + v = v[:4] + low := (uint32(v[0])) | (uint32(v[1]) << 8) | (uint32(v[2]) << 16) | (uint32(v[3]) << 24) + b.value = (b.value << 32) | uint64(low) + b.bitsRead -= 32 + b.off -= 4 +} + +// fill() will make sure at least 32 bits are available. +func (b *bitReader) fill() { + if b.bitsRead < 32 { + return + } + if b.off > 4 { + v := b.in[b.off-4:] + v = v[:4] + low := (uint32(v[0])) | (uint32(v[1]) << 8) | (uint32(v[2]) << 16) | (uint32(v[3]) << 24) + b.value = (b.value << 32) | uint64(low) + b.bitsRead -= 32 + b.off -= 4 + return + } + for b.off > 0 { + b.value = (b.value << 8) | uint64(b.in[b.off-1]) + b.bitsRead -= 8 + b.off-- + } +} + +// fillFastStart() assumes the bitreader is empty and there is at least 8 bytes to read. +func (b *bitReader) fillFastStart() { + // Do single re-slice to avoid bounds checks. + b.value = binary.LittleEndian.Uint64(b.in[b.off-8:]) + b.bitsRead = 0 + b.off -= 8 +} + +// finished returns true if all bits have been read from the bit stream. +func (b *bitReader) finished() bool { + return b.bitsRead >= 64 && b.off == 0 +} + +// close the bitstream and returns an error if out-of-buffer reads occurred. +func (b *bitReader) close() error { + // Release reference. + b.in = nil + if b.bitsRead > 64 { + return io.ErrUnexpectedEOF + } + return nil +} diff --git a/vendor/github.com/klauspost/compress/fse/bitwriter.go b/vendor/github.com/klauspost/compress/fse/bitwriter.go new file mode 100644 index 000000000..e82fa3bb7 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/bitwriter.go @@ -0,0 +1,167 @@ +// Copyright 2018 Klaus Post. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// Based on work Copyright (c) 2013, Yann Collet, released under BSD License. + +package fse + +import "fmt" + +// bitWriter will write bits. +// First bit will be LSB of the first byte of output. +type bitWriter struct { + bitContainer uint64 + nBits uint8 + out []byte +} + +// bitMask16 is bitmasks. Has extra to avoid bounds check. +var bitMask16 = [32]uint16{ + 0, 1, 3, 7, 0xF, 0x1F, + 0x3F, 0x7F, 0xFF, 0x1FF, 0x3FF, 0x7FF, + 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF} /* up to 16 bits */ + +// addBits16NC will add up to 16 bits. +// It will not check if there is space for them, +// so the caller must ensure that it has flushed recently. +func (b *bitWriter) addBits16NC(value uint16, bits uint8) { + b.bitContainer |= uint64(value&bitMask16[bits&31]) << (b.nBits & 63) + b.nBits += bits +} + +// addBits16Clean will add up to 16 bits. value may not contain more set bits than indicated. +// It will not check if there is space for them, so the caller must ensure that it has flushed recently. +func (b *bitWriter) addBits16Clean(value uint16, bits uint8) { + b.bitContainer |= uint64(value) << (b.nBits & 63) + b.nBits += bits +} + +// addBits16ZeroNC will add up to 16 bits. +// It will not check if there is space for them, +// so the caller must ensure that it has flushed recently. +// This is fastest if bits can be zero. +func (b *bitWriter) addBits16ZeroNC(value uint16, bits uint8) { + if bits == 0 { + return + } + value <<= (16 - bits) & 15 + value >>= (16 - bits) & 15 + b.bitContainer |= uint64(value) << (b.nBits & 63) + b.nBits += bits +} + +// flush will flush all pending full bytes. +// There will be at least 56 bits available for writing when this has been called. +// Using flush32 is faster, but leaves less space for writing. +func (b *bitWriter) flush() { + v := b.nBits >> 3 + switch v { + case 0: + case 1: + b.out = append(b.out, + byte(b.bitContainer), + ) + case 2: + b.out = append(b.out, + byte(b.bitContainer), + byte(b.bitContainer>>8), + ) + case 3: + b.out = append(b.out, + byte(b.bitContainer), + byte(b.bitContainer>>8), + byte(b.bitContainer>>16), + ) + case 4: + b.out = append(b.out, + byte(b.bitContainer), + byte(b.bitContainer>>8), + byte(b.bitContainer>>16), + byte(b.bitContainer>>24), + ) + case 5: + b.out = append(b.out, + byte(b.bitContainer), + byte(b.bitContainer>>8), + byte(b.bitContainer>>16), + byte(b.bitContainer>>24), + byte(b.bitContainer>>32), + ) + case 6: + b.out = append(b.out, + byte(b.bitContainer), + byte(b.bitContainer>>8), + byte(b.bitContainer>>16), + byte(b.bitContainer>>24), + byte(b.bitContainer>>32), + byte(b.bitContainer>>40), + ) + case 7: + b.out = append(b.out, + byte(b.bitContainer), + byte(b.bitContainer>>8), + byte(b.bitContainer>>16), + byte(b.bitContainer>>24), + byte(b.bitContainer>>32), + byte(b.bitContainer>>40), + byte(b.bitContainer>>48), + ) + case 8: + b.out = append(b.out, + byte(b.bitContainer), + byte(b.bitContainer>>8), + byte(b.bitContainer>>16), + byte(b.bitContainer>>24), + byte(b.bitContainer>>32), + byte(b.bitContainer>>40), + byte(b.bitContainer>>48), + byte(b.bitContainer>>56), + ) + default: + panic(fmt.Errorf("bits (%d) > 64", b.nBits)) + } + b.bitContainer >>= v << 3 + b.nBits &= 7 +} + +// flush32 will flush out, so there are at least 32 bits available for writing. +func (b *bitWriter) flush32() { + if b.nBits < 32 { + return + } + b.out = append(b.out, + byte(b.bitContainer), + byte(b.bitContainer>>8), + byte(b.bitContainer>>16), + byte(b.bitContainer>>24)) + b.nBits -= 32 + b.bitContainer >>= 32 +} + +// flushAlign will flush remaining full bytes and align to next byte boundary. +func (b *bitWriter) flushAlign() { + nbBytes := (b.nBits + 7) >> 3 + for i := uint8(0); i < nbBytes; i++ { + b.out = append(b.out, byte(b.bitContainer>>(i*8))) + } + b.nBits = 0 + b.bitContainer = 0 +} + +// close will write the alignment bit and write the final byte(s) +// to the output. +func (b *bitWriter) close() { + // End mark + b.addBits16Clean(1, 1) + // flush until next byte. + b.flushAlign() +} + +// reset and continue writing by appending to out. +func (b *bitWriter) reset(out []byte) { + b.bitContainer = 0 + b.nBits = 0 + b.out = out +} diff --git a/vendor/github.com/klauspost/compress/fse/bytereader.go b/vendor/github.com/klauspost/compress/fse/bytereader.go new file mode 100644 index 000000000..abade2d60 --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/bytereader.go @@ -0,0 +1,47 @@ +// Copyright 2018 Klaus Post. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// Based on work Copyright (c) 2013, Yann Collet, released under BSD License. + +package fse + +// byteReader provides a byte reader that reads +// little endian values from a byte stream. +// The input stream is manually advanced. +// The reader performs no bounds checks. +type byteReader struct { + b []byte + off int +} + +// init will initialize the reader and set the input. +func (b *byteReader) init(in []byte) { + b.b = in + b.off = 0 +} + +// advance the stream b n bytes. +func (b *byteReader) advance(n uint) { + b.off += int(n) +} + +// Uint32 returns a little endian uint32 starting at current offset. +func (b byteReader) Uint32() uint32 { + b2 := b.b[b.off:] + b2 = b2[:4] + v3 := uint32(b2[3]) + v2 := uint32(b2[2]) + v1 := uint32(b2[1]) + v0 := uint32(b2[0]) + return v0 | (v1 << 8) | (v2 << 16) | (v3 << 24) +} + +// unread returns the unread portion of the input. +func (b byteReader) unread() []byte { + return b.b[b.off:] +} + +// remain will return the number of bytes remaining. +func (b byteReader) remain() int { + return len(b.b) - b.off +} diff --git a/vendor/github.com/klauspost/compress/fse/compress.go b/vendor/github.com/klauspost/compress/fse/compress.go new file mode 100644 index 000000000..074018d8f --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/compress.go @@ -0,0 +1,683 @@ +// Copyright 2018 Klaus Post. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// Based on work Copyright (c) 2013, Yann Collet, released under BSD License. + +package fse + +import ( + "errors" + "fmt" +) + +// Compress the input bytes. Input must be < 2GB. +// Provide a Scratch buffer to avoid memory allocations. +// Note that the output is also kept in the scratch buffer. +// If input is too hard to compress, ErrIncompressible is returned. +// If input is a single byte value repeated ErrUseRLE is returned. +func Compress(in []byte, s *Scratch) ([]byte, error) { + if len(in) <= 1 { + return nil, ErrIncompressible + } + if len(in) > (2<<30)-1 { + return nil, errors.New("input too big, must be < 2GB") + } + s, err := s.prepare(in) + if err != nil { + return nil, err + } + + // Create histogram, if none was provided. + maxCount := s.maxCount + if maxCount == 0 { + maxCount = s.countSimple(in) + } + // Reset for next run. + s.clearCount = true + s.maxCount = 0 + if maxCount == len(in) { + // One symbol, use RLE + return nil, ErrUseRLE + } + if maxCount == 1 || maxCount < (len(in)>>7) { + // Each symbol present maximum once or too well distributed. + return nil, ErrIncompressible + } + s.optimalTableLog() + err = s.normalizeCount() + if err != nil { + return nil, err + } + err = s.writeCount() + if err != nil { + return nil, err + } + + if false { + err = s.validateNorm() + if err != nil { + return nil, err + } + } + + err = s.buildCTable() + if err != nil { + return nil, err + } + err = s.compress(in) + if err != nil { + return nil, err + } + s.Out = s.bw.out + // Check if we compressed. + if len(s.Out) >= len(in) { + return nil, ErrIncompressible + } + return s.Out, nil +} + +// cState contains the compression state of a stream. +type cState struct { + bw *bitWriter + stateTable []uint16 + state uint16 +} + +// init will initialize the compression state to the first symbol of the stream. +func (c *cState) init(bw *bitWriter, ct *cTable, tableLog uint8, first symbolTransform) { + c.bw = bw + c.stateTable = ct.stateTable + + nbBitsOut := (first.deltaNbBits + (1 << 15)) >> 16 + im := int32((nbBitsOut << 16) - first.deltaNbBits) + lu := (im >> nbBitsOut) + first.deltaFindState + c.state = c.stateTable[lu] +} + +// encode the output symbol provided and write it to the bitstream. +func (c *cState) encode(symbolTT symbolTransform) { + nbBitsOut := (uint32(c.state) + symbolTT.deltaNbBits) >> 16 + dstState := int32(c.state>>(nbBitsOut&15)) + symbolTT.deltaFindState + c.bw.addBits16NC(c.state, uint8(nbBitsOut)) + c.state = c.stateTable[dstState] +} + +// encode the output symbol provided and write it to the bitstream. +func (c *cState) encodeZero(symbolTT symbolTransform) { + nbBitsOut := (uint32(c.state) + symbolTT.deltaNbBits) >> 16 + dstState := int32(c.state>>(nbBitsOut&15)) + symbolTT.deltaFindState + c.bw.addBits16ZeroNC(c.state, uint8(nbBitsOut)) + c.state = c.stateTable[dstState] +} + +// flush will write the tablelog to the output and flush the remaining full bytes. +func (c *cState) flush(tableLog uint8) { + c.bw.flush32() + c.bw.addBits16NC(c.state, tableLog) + c.bw.flush() +} + +// compress is the main compression loop that will encode the input from the last byte to the first. +func (s *Scratch) compress(src []byte) error { + if len(src) <= 2 { + return errors.New("compress: src too small") + } + tt := s.ct.symbolTT[:256] + s.bw.reset(s.Out) + + // Our two states each encodes every second byte. + // Last byte encoded (first byte decoded) will always be encoded by c1. + var c1, c2 cState + + // Encode so remaining size is divisible by 4. + ip := len(src) + if ip&1 == 1 { + c1.init(&s.bw, &s.ct, s.actualTableLog, tt[src[ip-1]]) + c2.init(&s.bw, &s.ct, s.actualTableLog, tt[src[ip-2]]) + c1.encodeZero(tt[src[ip-3]]) + ip -= 3 + } else { + c2.init(&s.bw, &s.ct, s.actualTableLog, tt[src[ip-1]]) + c1.init(&s.bw, &s.ct, s.actualTableLog, tt[src[ip-2]]) + ip -= 2 + } + if ip&2 != 0 { + c2.encodeZero(tt[src[ip-1]]) + c1.encodeZero(tt[src[ip-2]]) + ip -= 2 + } + src = src[:ip] + + // Main compression loop. + switch { + case !s.zeroBits && s.actualTableLog <= 8: + // We can encode 4 symbols without requiring a flush. + // We do not need to check if any output is 0 bits. + for ; len(src) >= 4; src = src[:len(src)-4] { + s.bw.flush32() + v3, v2, v1, v0 := src[len(src)-4], src[len(src)-3], src[len(src)-2], src[len(src)-1] + c2.encode(tt[v0]) + c1.encode(tt[v1]) + c2.encode(tt[v2]) + c1.encode(tt[v3]) + } + case !s.zeroBits: + // We do not need to check if any output is 0 bits. + for ; len(src) >= 4; src = src[:len(src)-4] { + s.bw.flush32() + v3, v2, v1, v0 := src[len(src)-4], src[len(src)-3], src[len(src)-2], src[len(src)-1] + c2.encode(tt[v0]) + c1.encode(tt[v1]) + s.bw.flush32() + c2.encode(tt[v2]) + c1.encode(tt[v3]) + } + case s.actualTableLog <= 8: + // We can encode 4 symbols without requiring a flush + for ; len(src) >= 4; src = src[:len(src)-4] { + s.bw.flush32() + v3, v2, v1, v0 := src[len(src)-4], src[len(src)-3], src[len(src)-2], src[len(src)-1] + c2.encodeZero(tt[v0]) + c1.encodeZero(tt[v1]) + c2.encodeZero(tt[v2]) + c1.encodeZero(tt[v3]) + } + default: + for ; len(src) >= 4; src = src[:len(src)-4] { + s.bw.flush32() + v3, v2, v1, v0 := src[len(src)-4], src[len(src)-3], src[len(src)-2], src[len(src)-1] + c2.encodeZero(tt[v0]) + c1.encodeZero(tt[v1]) + s.bw.flush32() + c2.encodeZero(tt[v2]) + c1.encodeZero(tt[v3]) + } + } + + // Flush final state. + // Used to initialize state when decoding. + c2.flush(s.actualTableLog) + c1.flush(s.actualTableLog) + + s.bw.close() + return nil +} + +// writeCount will write the normalized histogram count to header. +// This is read back by readNCount. +func (s *Scratch) writeCount() error { + var ( + tableLog = s.actualTableLog + tableSize = 1 << tableLog + previous0 bool + charnum uint16 + + maxHeaderSize = ((int(s.symbolLen)*int(tableLog) + 4 + 2) >> 3) + 3 + + // Write Table Size + bitStream = uint32(tableLog - minTablelog) + bitCount = uint(4) + remaining = int16(tableSize + 1) /* +1 for extra accuracy */ + threshold = int16(tableSize) + nbBits = uint(tableLog + 1) + ) + if cap(s.Out) < maxHeaderSize { + s.Out = make([]byte, 0, s.br.remain()+maxHeaderSize) + } + outP := uint(0) + out := s.Out[:maxHeaderSize] + + // stops at 1 + for remaining > 1 { + if previous0 { + start := charnum + for s.norm[charnum] == 0 { + charnum++ + } + for charnum >= start+24 { + start += 24 + bitStream += uint32(0xFFFF) << bitCount + out[outP] = byte(bitStream) + out[outP+1] = byte(bitStream >> 8) + outP += 2 + bitStream >>= 16 + } + for charnum >= start+3 { + start += 3 + bitStream += 3 << bitCount + bitCount += 2 + } + bitStream += uint32(charnum-start) << bitCount + bitCount += 2 + if bitCount > 16 { + out[outP] = byte(bitStream) + out[outP+1] = byte(bitStream >> 8) + outP += 2 + bitStream >>= 16 + bitCount -= 16 + } + } + + count := s.norm[charnum] + charnum++ + max := (2*threshold - 1) - remaining + if count < 0 { + remaining += count + } else { + remaining -= count + } + count++ // +1 for extra accuracy + if count >= threshold { + count += max // [0..max[ [max..threshold[ (...) [threshold+max 2*threshold[ + } + bitStream += uint32(count) << bitCount + bitCount += nbBits + if count < max { + bitCount-- + } + + previous0 = count == 1 + if remaining < 1 { + return errors.New("internal error: remaining<1") + } + for remaining < threshold { + nbBits-- + threshold >>= 1 + } + + if bitCount > 16 { + out[outP] = byte(bitStream) + out[outP+1] = byte(bitStream >> 8) + outP += 2 + bitStream >>= 16 + bitCount -= 16 + } + } + + out[outP] = byte(bitStream) + out[outP+1] = byte(bitStream >> 8) + outP += (bitCount + 7) / 8 + + if charnum > s.symbolLen { + return errors.New("internal error: charnum > s.symbolLen") + } + s.Out = out[:outP] + return nil +} + +// symbolTransform contains the state transform for a symbol. +type symbolTransform struct { + deltaFindState int32 + deltaNbBits uint32 +} + +// String prints values as a human readable string. +func (s symbolTransform) String() string { + return fmt.Sprintf("dnbits: %08x, fs:%d", s.deltaNbBits, s.deltaFindState) +} + +// cTable contains tables used for compression. +type cTable struct { + tableSymbol []byte + stateTable []uint16 + symbolTT []symbolTransform +} + +// allocCtable will allocate tables needed for compression. +// If existing tables a re big enough, they are simply re-used. +func (s *Scratch) allocCtable() { + tableSize := 1 << s.actualTableLog + // get tableSymbol that is big enough. + if cap(s.ct.tableSymbol) < tableSize { + s.ct.tableSymbol = make([]byte, tableSize) + } + s.ct.tableSymbol = s.ct.tableSymbol[:tableSize] + + ctSize := tableSize + if cap(s.ct.stateTable) < ctSize { + s.ct.stateTable = make([]uint16, ctSize) + } + s.ct.stateTable = s.ct.stateTable[:ctSize] + + if cap(s.ct.symbolTT) < 256 { + s.ct.symbolTT = make([]symbolTransform, 256) + } + s.ct.symbolTT = s.ct.symbolTT[:256] +} + +// buildCTable will populate the compression table so it is ready to be used. +func (s *Scratch) buildCTable() error { + tableSize := uint32(1 << s.actualTableLog) + highThreshold := tableSize - 1 + var cumul [maxSymbolValue + 2]int16 + + s.allocCtable() + tableSymbol := s.ct.tableSymbol[:tableSize] + // symbol start positions + { + cumul[0] = 0 + for ui, v := range s.norm[:s.symbolLen-1] { + u := byte(ui) // one less than reference + if v == -1 { + // Low proba symbol + cumul[u+1] = cumul[u] + 1 + tableSymbol[highThreshold] = u + highThreshold-- + } else { + cumul[u+1] = cumul[u] + v + } + } + // Encode last symbol separately to avoid overflowing u + u := int(s.symbolLen - 1) + v := s.norm[s.symbolLen-1] + if v == -1 { + // Low proba symbol + cumul[u+1] = cumul[u] + 1 + tableSymbol[highThreshold] = byte(u) + highThreshold-- + } else { + cumul[u+1] = cumul[u] + v + } + if uint32(cumul[s.symbolLen]) != tableSize { + return fmt.Errorf("internal error: expected cumul[s.symbolLen] (%d) == tableSize (%d)", cumul[s.symbolLen], tableSize) + } + cumul[s.symbolLen] = int16(tableSize) + 1 + } + // Spread symbols + s.zeroBits = false + { + step := tableStep(tableSize) + tableMask := tableSize - 1 + var position uint32 + // if any symbol > largeLimit, we may have 0 bits output. + largeLimit := int16(1 << (s.actualTableLog - 1)) + for ui, v := range s.norm[:s.symbolLen] { + symbol := byte(ui) + if v > largeLimit { + s.zeroBits = true + } + for nbOccurrences := int16(0); nbOccurrences < v; nbOccurrences++ { + tableSymbol[position] = symbol + position = (position + step) & tableMask + for position > highThreshold { + position = (position + step) & tableMask + } /* Low proba area */ + } + } + + // Check if we have gone through all positions + if position != 0 { + return errors.New("position!=0") + } + } + + // Build table + table := s.ct.stateTable + { + tsi := int(tableSize) + for u, v := range tableSymbol { + // TableU16 : sorted by symbol order; gives next state value + table[cumul[v]] = uint16(tsi + u) + cumul[v]++ + } + } + + // Build Symbol Transformation Table + { + total := int16(0) + symbolTT := s.ct.symbolTT[:s.symbolLen] + tableLog := s.actualTableLog + tl := (uint32(tableLog) << 16) - (1 << tableLog) + for i, v := range s.norm[:s.symbolLen] { + switch v { + case 0: + case -1, 1: + symbolTT[i].deltaNbBits = tl + symbolTT[i].deltaFindState = int32(total - 1) + total++ + default: + maxBitsOut := uint32(tableLog) - highBits(uint32(v-1)) + minStatePlus := uint32(v) << maxBitsOut + symbolTT[i].deltaNbBits = (maxBitsOut << 16) - minStatePlus + symbolTT[i].deltaFindState = int32(total - v) + total += v + } + } + if total != int16(tableSize) { + return fmt.Errorf("total mismatch %d (got) != %d (want)", total, tableSize) + } + } + return nil +} + +// countSimple will create a simple histogram in s.count. +// Returns the biggest count. +// Does not update s.clearCount. +func (s *Scratch) countSimple(in []byte) (max int) { + for _, v := range in { + s.count[v]++ + } + m, symlen := uint32(0), s.symbolLen + for i, v := range s.count[:] { + if v == 0 { + continue + } + if v > m { + m = v + } + symlen = uint16(i) + 1 + } + s.symbolLen = symlen + return int(m) +} + +// minTableLog provides the minimum logSize to safely represent a distribution. +func (s *Scratch) minTableLog() uint8 { + minBitsSrc := highBits(uint32(s.br.remain()-1)) + 1 + minBitsSymbols := highBits(uint32(s.symbolLen-1)) + 2 + if minBitsSrc < minBitsSymbols { + return uint8(minBitsSrc) + } + return uint8(minBitsSymbols) +} + +// optimalTableLog calculates and sets the optimal tableLog in s.actualTableLog +func (s *Scratch) optimalTableLog() { + tableLog := s.TableLog + minBits := s.minTableLog() + maxBitsSrc := uint8(highBits(uint32(s.br.remain()-1))) - 2 + if maxBitsSrc < tableLog { + // Accuracy can be reduced + tableLog = maxBitsSrc + } + if minBits > tableLog { + tableLog = minBits + } + // Need a minimum to safely represent all symbol values + if tableLog < minTablelog { + tableLog = minTablelog + } + if tableLog > maxTableLog { + tableLog = maxTableLog + } + s.actualTableLog = tableLog +} + +var rtbTable = [...]uint32{0, 473195, 504333, 520860, 550000, 700000, 750000, 830000} + +// normalizeCount will normalize the count of the symbols so +// the total is equal to the table size. +func (s *Scratch) normalizeCount() error { + var ( + tableLog = s.actualTableLog + scale = 62 - uint64(tableLog) + step = (1 << 62) / uint64(s.br.remain()) + vStep = uint64(1) << (scale - 20) + stillToDistribute = int16(1 << tableLog) + largest int + largestP int16 + lowThreshold = (uint32)(s.br.remain() >> tableLog) + ) + + for i, cnt := range s.count[:s.symbolLen] { + // already handled + // if (count[s] == s.length) return 0; /* rle special case */ + + if cnt == 0 { + s.norm[i] = 0 + continue + } + if cnt <= lowThreshold { + s.norm[i] = -1 + stillToDistribute-- + } else { + proba := (int16)((uint64(cnt) * step) >> scale) + if proba < 8 { + restToBeat := vStep * uint64(rtbTable[proba]) + v := uint64(cnt)*step - (uint64(proba) << scale) + if v > restToBeat { + proba++ + } + } + if proba > largestP { + largestP = proba + largest = i + } + s.norm[i] = proba + stillToDistribute -= proba + } + } + + if -stillToDistribute >= (s.norm[largest] >> 1) { + // corner case, need another normalization method + return s.normalizeCount2() + } + s.norm[largest] += stillToDistribute + return nil +} + +// Secondary normalization method. +// To be used when primary method fails. +func (s *Scratch) normalizeCount2() error { + const notYetAssigned = -2 + var ( + distributed uint32 + total = uint32(s.br.remain()) + tableLog = s.actualTableLog + lowThreshold = total >> tableLog + lowOne = (total * 3) >> (tableLog + 1) + ) + for i, cnt := range s.count[:s.symbolLen] { + if cnt == 0 { + s.norm[i] = 0 + continue + } + if cnt <= lowThreshold { + s.norm[i] = -1 + distributed++ + total -= cnt + continue + } + if cnt <= lowOne { + s.norm[i] = 1 + distributed++ + total -= cnt + continue + } + s.norm[i] = notYetAssigned + } + toDistribute := (1 << tableLog) - distributed + + if (total / toDistribute) > lowOne { + // risk of rounding to zero + lowOne = (total * 3) / (toDistribute * 2) + for i, cnt := range s.count[:s.symbolLen] { + if (s.norm[i] == notYetAssigned) && (cnt <= lowOne) { + s.norm[i] = 1 + distributed++ + total -= cnt + continue + } + } + toDistribute = (1 << tableLog) - distributed + } + if distributed == uint32(s.symbolLen)+1 { + // all values are pretty poor; + // probably incompressible data (should have already been detected); + // find max, then give all remaining points to max + var maxV int + var maxC uint32 + for i, cnt := range s.count[:s.symbolLen] { + if cnt > maxC { + maxV = i + maxC = cnt + } + } + s.norm[maxV] += int16(toDistribute) + return nil + } + + if total == 0 { + // all of the symbols were low enough for the lowOne or lowThreshold + for i := uint32(0); toDistribute > 0; i = (i + 1) % (uint32(s.symbolLen)) { + if s.norm[i] > 0 { + toDistribute-- + s.norm[i]++ + } + } + return nil + } + + var ( + vStepLog = 62 - uint64(tableLog) + mid = uint64((1 << (vStepLog - 1)) - 1) + rStep = (((1 << vStepLog) * uint64(toDistribute)) + mid) / uint64(total) // scale on remaining + tmpTotal = mid + ) + for i, cnt := range s.count[:s.symbolLen] { + if s.norm[i] == notYetAssigned { + var ( + end = tmpTotal + uint64(cnt)*rStep + sStart = uint32(tmpTotal >> vStepLog) + sEnd = uint32(end >> vStepLog) + weight = sEnd - sStart + ) + if weight < 1 { + return errors.New("weight < 1") + } + s.norm[i] = int16(weight) + tmpTotal = end + } + } + return nil +} + +// validateNorm validates the normalized histogram table. +func (s *Scratch) validateNorm() (err error) { + var total int + for _, v := range s.norm[:s.symbolLen] { + if v >= 0 { + total += int(v) + } else { + total -= int(v) + } + } + defer func() { + if err == nil { + return + } + fmt.Printf("selected TableLog: %d, Symbol length: %d\n", s.actualTableLog, s.symbolLen) + for i, v := range s.norm[:s.symbolLen] { + fmt.Printf("%3d: %5d -> %4d \n", i, s.count[i], v) + } + }() + if total != (1 << s.actualTableLog) { + return fmt.Errorf("warning: Total == %d != %d", total, 1< tablelogAbsoluteMax { + return errors.New("tableLog too large") + } + bitStream >>= 4 + bitCount := uint(4) + + s.actualTableLog = uint8(nbBits) + remaining := int32((1 << nbBits) + 1) + threshold := int32(1 << nbBits) + gotTotal := int32(0) + nbBits++ + + for remaining > 1 { + if previous0 { + n0 := charnum + for (bitStream & 0xFFFF) == 0xFFFF { + n0 += 24 + if b.off < iend-5 { + b.advance(2) + bitStream = b.Uint32() >> bitCount + } else { + bitStream >>= 16 + bitCount += 16 + } + } + for (bitStream & 3) == 3 { + n0 += 3 + bitStream >>= 2 + bitCount += 2 + } + n0 += uint16(bitStream & 3) + bitCount += 2 + if n0 > maxSymbolValue { + return errors.New("maxSymbolValue too small") + } + for charnum < n0 { + s.norm[charnum&0xff] = 0 + charnum++ + } + + if b.off <= iend-7 || b.off+int(bitCount>>3) <= iend-4 { + b.advance(bitCount >> 3) + bitCount &= 7 + bitStream = b.Uint32() >> bitCount + } else { + bitStream >>= 2 + } + } + + max := (2*(threshold) - 1) - (remaining) + var count int32 + + if (int32(bitStream) & (threshold - 1)) < max { + count = int32(bitStream) & (threshold - 1) + bitCount += nbBits - 1 + } else { + count = int32(bitStream) & (2*threshold - 1) + if count >= threshold { + count -= max + } + bitCount += nbBits + } + + count-- // extra accuracy + if count < 0 { + // -1 means +1 + remaining += count + gotTotal -= count + } else { + remaining -= count + gotTotal += count + } + s.norm[charnum&0xff] = int16(count) + charnum++ + previous0 = count == 0 + for remaining < threshold { + nbBits-- + threshold >>= 1 + } + if b.off <= iend-7 || b.off+int(bitCount>>3) <= iend-4 { + b.advance(bitCount >> 3) + bitCount &= 7 + } else { + bitCount -= (uint)(8 * (len(b.b) - 4 - b.off)) + b.off = len(b.b) - 4 + } + bitStream = b.Uint32() >> (bitCount & 31) + } + s.symbolLen = charnum + + if s.symbolLen <= 1 { + return fmt.Errorf("symbolLen (%d) too small", s.symbolLen) + } + if s.symbolLen > maxSymbolValue+1 { + return fmt.Errorf("symbolLen (%d) too big", s.symbolLen) + } + if remaining != 1 { + return fmt.Errorf("corruption detected (remaining %d != 1)", remaining) + } + if bitCount > 32 { + return fmt.Errorf("corruption detected (bitCount %d > 32)", bitCount) + } + if gotTotal != 1<> 3) + return nil +} + +// decSymbol contains information about a state entry, +// Including the state offset base, the output symbol and +// the number of bits to read for the low part of the destination state. +type decSymbol struct { + newState uint16 + symbol uint8 + nbBits uint8 +} + +// allocDtable will allocate decoding tables if they are not big enough. +func (s *Scratch) allocDtable() { + tableSize := 1 << s.actualTableLog + if cap(s.decTable) < tableSize { + s.decTable = make([]decSymbol, tableSize) + } + s.decTable = s.decTable[:tableSize] + + if cap(s.ct.tableSymbol) < 256 { + s.ct.tableSymbol = make([]byte, 256) + } + s.ct.tableSymbol = s.ct.tableSymbol[:256] + + if cap(s.ct.stateTable) < 256 { + s.ct.stateTable = make([]uint16, 256) + } + s.ct.stateTable = s.ct.stateTable[:256] +} + +// buildDtable will build the decoding table. +func (s *Scratch) buildDtable() error { + tableSize := uint32(1 << s.actualTableLog) + highThreshold := tableSize - 1 + s.allocDtable() + symbolNext := s.ct.stateTable[:256] + + // Init, lay down lowprob symbols + s.zeroBits = false + { + largeLimit := int16(1 << (s.actualTableLog - 1)) + for i, v := range s.norm[:s.symbolLen] { + if v == -1 { + s.decTable[highThreshold].symbol = uint8(i) + highThreshold-- + symbolNext[i] = 1 + } else { + if v >= largeLimit { + s.zeroBits = true + } + symbolNext[i] = uint16(v) + } + } + } + // Spread symbols + { + tableMask := tableSize - 1 + step := tableStep(tableSize) + position := uint32(0) + for ss, v := range s.norm[:s.symbolLen] { + for i := 0; i < int(v); i++ { + s.decTable[position].symbol = uint8(ss) + position = (position + step) & tableMask + for position > highThreshold { + // lowprob area + position = (position + step) & tableMask + } + } + } + if position != 0 { + // position must reach all cells once, otherwise normalizedCounter is incorrect + return errors.New("corrupted input (position != 0)") + } + } + + // Build Decoding table + { + tableSize := uint16(1 << s.actualTableLog) + for u, v := range s.decTable { + symbol := v.symbol + nextState := symbolNext[symbol] + symbolNext[symbol] = nextState + 1 + nBits := s.actualTableLog - byte(highBits(uint32(nextState))) + s.decTable[u].nbBits = nBits + newState := (nextState << nBits) - tableSize + if newState >= tableSize { + return fmt.Errorf("newState (%d) outside table size (%d)", newState, tableSize) + } + if newState == uint16(u) && nBits == 0 { + // Seems weird that this is possible with nbits > 0. + return fmt.Errorf("newState (%d) == oldState (%d) and no bits", newState, u) + } + s.decTable[u].newState = newState + } + } + return nil +} + +// decompress will decompress the bitstream. +// If the buffer is over-read an error is returned. +func (s *Scratch) decompress() error { + br := &s.bits + if err := br.init(s.br.unread()); err != nil { + return err + } + + var s1, s2 decoder + // Initialize and decode first state and symbol. + s1.init(br, s.decTable, s.actualTableLog) + s2.init(br, s.decTable, s.actualTableLog) + + // Use temp table to avoid bound checks/append penalty. + var tmp = s.ct.tableSymbol[:256] + var off uint8 + + // Main part + if !s.zeroBits { + for br.off >= 8 { + br.fillFast() + tmp[off+0] = s1.nextFast() + tmp[off+1] = s2.nextFast() + br.fillFast() + tmp[off+2] = s1.nextFast() + tmp[off+3] = s2.nextFast() + off += 4 + // When off is 0, we have overflowed and should write. + if off == 0 { + s.Out = append(s.Out, tmp...) + if len(s.Out) >= s.DecompressLimit { + return fmt.Errorf("output size (%d) > DecompressLimit (%d)", len(s.Out), s.DecompressLimit) + } + } + } + } else { + for br.off >= 8 { + br.fillFast() + tmp[off+0] = s1.next() + tmp[off+1] = s2.next() + br.fillFast() + tmp[off+2] = s1.next() + tmp[off+3] = s2.next() + off += 4 + if off == 0 { + s.Out = append(s.Out, tmp...) + // When off is 0, we have overflowed and should write. + if len(s.Out) >= s.DecompressLimit { + return fmt.Errorf("output size (%d) > DecompressLimit (%d)", len(s.Out), s.DecompressLimit) + } + } + } + } + s.Out = append(s.Out, tmp[:off]...) + + // Final bits, a bit more expensive check + for { + if s1.finished() { + s.Out = append(s.Out, s1.final(), s2.final()) + break + } + br.fill() + s.Out = append(s.Out, s1.next()) + if s2.finished() { + s.Out = append(s.Out, s2.final(), s1.final()) + break + } + s.Out = append(s.Out, s2.next()) + if len(s.Out) >= s.DecompressLimit { + return fmt.Errorf("output size (%d) > DecompressLimit (%d)", len(s.Out), s.DecompressLimit) + } + } + return br.close() +} + +// decoder keeps track of the current state and updates it from the bitstream. +type decoder struct { + state uint16 + br *bitReader + dt []decSymbol +} + +// init will initialize the decoder and read the first state from the stream. +func (d *decoder) init(in *bitReader, dt []decSymbol, tableLog uint8) { + d.dt = dt + d.br = in + d.state = in.getBits(tableLog) +} + +// next returns the next symbol and sets the next state. +// At least tablelog bits must be available in the bit reader. +func (d *decoder) next() uint8 { + n := &d.dt[d.state] + lowBits := d.br.getBits(n.nbBits) + d.state = n.newState + lowBits + return n.symbol +} + +// finished returns true if all bits have been read from the bitstream +// and the next state would require reading bits from the input. +func (d *decoder) finished() bool { + return d.br.finished() && d.dt[d.state].nbBits > 0 +} + +// final returns the current state symbol without decoding the next. +func (d *decoder) final() uint8 { + return d.dt[d.state].symbol +} + +// nextFast returns the next symbol and sets the next state. +// This can only be used if no symbols are 0 bits. +// At least tablelog bits must be available in the bit reader. +func (d *decoder) nextFast() uint8 { + n := d.dt[d.state] + lowBits := d.br.getBitsFast(n.nbBits) + d.state = n.newState + lowBits + return n.symbol +} diff --git a/vendor/github.com/klauspost/compress/fse/fse.go b/vendor/github.com/klauspost/compress/fse/fse.go new file mode 100644 index 000000000..535cbadfd --- /dev/null +++ b/vendor/github.com/klauspost/compress/fse/fse.go @@ -0,0 +1,144 @@ +// Copyright 2018 Klaus Post. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// Based on work Copyright (c) 2013, Yann Collet, released under BSD License. + +// Package fse provides Finite State Entropy encoding and decoding. +// +// Finite State Entropy encoding provides a fast near-optimal symbol encoding/decoding +// for byte blocks as implemented in zstd. +// +// See https://github.com/klauspost/compress/tree/master/fse for more information. +package fse + +import ( + "errors" + "fmt" + "math/bits" +) + +const ( + /*!MEMORY_USAGE : + * Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.) + * Increasing memory usage improves compression ratio + * Reduced memory usage can improve speed, due to cache effect + * Recommended max value is 14, for 16KB, which nicely fits into Intel x86 L1 cache */ + maxMemoryUsage = 14 + defaultMemoryUsage = 13 + + maxTableLog = maxMemoryUsage - 2 + maxTablesize = 1 << maxTableLog + defaultTablelog = defaultMemoryUsage - 2 + minTablelog = 5 + maxSymbolValue = 255 +) + +var ( + // ErrIncompressible is returned when input is judged to be too hard to compress. + ErrIncompressible = errors.New("input is not compressible") + + // ErrUseRLE is returned from the compressor when the input is a single byte value repeated. + ErrUseRLE = errors.New("input is single value repeated") +) + +// Scratch provides temporary storage for compression and decompression. +type Scratch struct { + // Private + count [maxSymbolValue + 1]uint32 + norm [maxSymbolValue + 1]int16 + br byteReader + bits bitReader + bw bitWriter + ct cTable // Compression tables. + decTable []decSymbol // Decompression table. + maxCount int // count of the most probable symbol + + // Per block parameters. + // These can be used to override compression parameters of the block. + // Do not touch, unless you know what you are doing. + + // Out is output buffer. + // If the scratch is re-used before the caller is done processing the output, + // set this field to nil. + // Otherwise the output buffer will be re-used for next Compression/Decompression step + // and allocation will be avoided. + Out []byte + + // DecompressLimit limits the maximum decoded size acceptable. + // If > 0 decompression will stop when approximately this many bytes + // has been decoded. + // If 0, maximum size will be 2GB. + DecompressLimit int + + symbolLen uint16 // Length of active part of the symbol table. + actualTableLog uint8 // Selected tablelog. + zeroBits bool // no bits has prob > 50%. + clearCount bool // clear count + + // MaxSymbolValue will override the maximum symbol value of the next block. + MaxSymbolValue uint8 + + // TableLog will attempt to override the tablelog for the next block. + TableLog uint8 +} + +// Histogram allows to populate the histogram and skip that step in the compression, +// It otherwise allows to inspect the histogram when compression is done. +// To indicate that you have populated the histogram call HistogramFinished +// with the value of the highest populated symbol, as well as the number of entries +// in the most populated entry. These are accepted at face value. +// The returned slice will always be length 256. +func (s *Scratch) Histogram() []uint32 { + return s.count[:] +} + +// HistogramFinished can be called to indicate that the histogram has been populated. +// maxSymbol is the index of the highest set symbol of the next data segment. +// maxCount is the number of entries in the most populated entry. +// These are accepted at face value. +func (s *Scratch) HistogramFinished(maxSymbol uint8, maxCount int) { + s.maxCount = maxCount + s.symbolLen = uint16(maxSymbol) + 1 + s.clearCount = maxCount != 0 +} + +// prepare will prepare and allocate scratch tables used for both compression and decompression. +func (s *Scratch) prepare(in []byte) (*Scratch, error) { + if s == nil { + s = &Scratch{} + } + if s.MaxSymbolValue == 0 { + s.MaxSymbolValue = 255 + } + if s.TableLog == 0 { + s.TableLog = defaultTablelog + } + if s.TableLog > maxTableLog { + return nil, fmt.Errorf("tableLog (%d) > maxTableLog (%d)", s.TableLog, maxTableLog) + } + if cap(s.Out) == 0 { + s.Out = make([]byte, 0, len(in)) + } + if s.clearCount && s.maxCount == 0 { + for i := range s.count { + s.count[i] = 0 + } + s.clearCount = false + } + s.br.init(in) + if s.DecompressLimit == 0 { + // Max size 2GB. + s.DecompressLimit = (2 << 30) - 1 + } + + return s, nil +} + +// tableStep returns the next table index. +func tableStep(tableSize uint32) uint32 { + return (tableSize >> 1) + (tableSize >> 3) + 3 +} + +func highBits(val uint32) (n uint32) { + return uint32(bits.Len32(val) - 1) +} diff --git a/vendor/github.com/klauspost/compress/gen.sh b/vendor/github.com/klauspost/compress/gen.sh new file mode 100644 index 000000000..aff942205 --- /dev/null +++ b/vendor/github.com/klauspost/compress/gen.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +cd s2/cmd/_s2sx/ || exit 1 +go generate . diff --git a/vendor/github.com/klauspost/compress/huff0/.gitignore b/vendor/github.com/klauspost/compress/huff0/.gitignore new file mode 100644 index 000000000..b3d262958 --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/.gitignore @@ -0,0 +1 @@ +/huff0-fuzz.zip diff --git a/vendor/github.com/klauspost/compress/huff0/README.md b/vendor/github.com/klauspost/compress/huff0/README.md new file mode 100644 index 000000000..8b6e5c663 --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/README.md @@ -0,0 +1,89 @@ +# Huff0 entropy compression + +This package provides Huff0 encoding and decoding as used in zstd. + +[Huff0](https://github.com/Cyan4973/FiniteStateEntropy#new-generation-entropy-coders), +a Huffman codec designed for modern CPU, featuring OoO (Out of Order) operations on multiple ALU +(Arithmetic Logic Unit), achieving extremely fast compression and decompression speeds. + +This can be used for compressing input with a lot of similar input values to the smallest number of bytes. +This does not perform any multi-byte [dictionary coding](https://en.wikipedia.org/wiki/Dictionary_coder) as LZ coders, +but it can be used as a secondary step to compressors (like Snappy) that does not do entropy encoding. + +* [Godoc documentation](https://godoc.org/github.com/klauspost/compress/huff0) + +## News + +This is used as part of the [zstandard](https://github.com/klauspost/compress/tree/master/zstd#zstd) compression and decompression package. + +This ensures that most functionality is well tested. + +# Usage + +This package provides a low level interface that allows to compress single independent blocks. + +Each block is separate, and there is no built in integrity checks. +This means that the caller should keep track of block sizes and also do checksums if needed. + +Compressing a block is done via the [`Compress1X`](https://godoc.org/github.com/klauspost/compress/huff0#Compress1X) and +[`Compress4X`](https://godoc.org/github.com/klauspost/compress/huff0#Compress4X) functions. +You must provide input and will receive the output and maybe an error. + +These error values can be returned: + +| Error | Description | +|---------------------|-----------------------------------------------------------------------------| +| `` | Everything ok, output is returned | +| `ErrIncompressible` | Returned when input is judged to be too hard to compress | +| `ErrUseRLE` | Returned from the compressor when the input is a single byte value repeated | +| `ErrTooBig` | Returned if the input block exceeds the maximum allowed size (128 Kib) | +| `(error)` | An internal error occurred. | + + +As can be seen above some of there are errors that will be returned even under normal operation so it is important to handle these. + +To reduce allocations you can provide a [`Scratch`](https://godoc.org/github.com/klauspost/compress/huff0#Scratch) object +that can be re-used for successive calls. Both compression and decompression accepts a `Scratch` object, and the same +object can be used for both. + +Be aware, that when re-using a `Scratch` object that the *output* buffer is also re-used, so if you are still using this +you must set the `Out` field in the scratch to nil. The same buffer is used for compression and decompression output. + +The `Scratch` object will retain state that allows to re-use previous tables for encoding and decoding. + +## Tables and re-use + +Huff0 allows for reusing tables from the previous block to save space if that is expected to give better/faster results. + +The Scratch object allows you to set a [`ReusePolicy`](https://godoc.org/github.com/klauspost/compress/huff0#ReusePolicy) +that controls this behaviour. See the documentation for details. This can be altered between each block. + +Do however note that this information is *not* stored in the output block and it is up to the users of the package to +record whether [`ReadTable`](https://godoc.org/github.com/klauspost/compress/huff0#ReadTable) should be called, +based on the boolean reported back from the CompressXX call. + +If you want to store the table separate from the data, you can access them as `OutData` and `OutTable` on the +[`Scratch`](https://godoc.org/github.com/klauspost/compress/huff0#Scratch) object. + +## Decompressing + +The first part of decoding is to initialize the decoding table through [`ReadTable`](https://godoc.org/github.com/klauspost/compress/huff0#ReadTable). +This will initialize the decoding tables. +You can supply the complete block to `ReadTable` and it will return the data part of the block +which can be given to the decompressor. + +Decompressing is done by calling the [`Decompress1X`](https://godoc.org/github.com/klauspost/compress/huff0#Scratch.Decompress1X) +or [`Decompress4X`](https://godoc.org/github.com/klauspost/compress/huff0#Scratch.Decompress4X) function. + +For concurrently decompressing content with a fixed table a stateless [`Decoder`](https://godoc.org/github.com/klauspost/compress/huff0#Decoder) can be requested which will remain correct as long as the scratch is unchanged. The capacity of the provided slice indicates the expected output size. + +You must provide the output from the compression stage, at exactly the size you got back. If you receive an error back +your input was likely corrupted. + +It is important to note that a successful decoding does *not* mean your output matches your original input. +There are no integrity checks, so relying on errors from the decompressor does not assure your data is valid. + +# Contributing + +Contributions are always welcome. Be aware that adding public functions will require good justification and breaking +changes will likely not be accepted. If in doubt open an issue before writing the PR. diff --git a/vendor/github.com/klauspost/compress/huff0/bitreader.go b/vendor/github.com/klauspost/compress/huff0/bitreader.go new file mode 100644 index 000000000..e36d9742f --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/bitreader.go @@ -0,0 +1,229 @@ +// Copyright 2018 Klaus Post. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// Based on work Copyright (c) 2013, Yann Collet, released under BSD License. + +package huff0 + +import ( + "encoding/binary" + "errors" + "fmt" + "io" +) + +// bitReader reads a bitstream in reverse. +// The last set bit indicates the start of the stream and is used +// for aligning the input. +type bitReaderBytes struct { + in []byte + off uint // next byte to read is at in[off - 1] + value uint64 + bitsRead uint8 +} + +// init initializes and resets the bit reader. +func (b *bitReaderBytes) init(in []byte) error { + if len(in) < 1 { + return errors.New("corrupt stream: too short") + } + b.in = in + b.off = uint(len(in)) + // The highest bit of the last byte indicates where to start + v := in[len(in)-1] + if v == 0 { + return errors.New("corrupt stream, did not find end of stream") + } + b.bitsRead = 64 + b.value = 0 + if len(in) >= 8 { + b.fillFastStart() + } else { + b.fill() + b.fill() + } + b.advance(8 - uint8(highBit32(uint32(v)))) + return nil +} + +// peekBitsFast requires that at least one bit is requested every time. +// There are no checks if the buffer is filled. +func (b *bitReaderBytes) peekByteFast() uint8 { + got := uint8(b.value >> 56) + return got +} + +func (b *bitReaderBytes) advance(n uint8) { + b.bitsRead += n + b.value <<= n & 63 +} + +// fillFast() will make sure at least 32 bits are available. +// There must be at least 4 bytes available. +func (b *bitReaderBytes) fillFast() { + if b.bitsRead < 32 { + return + } + + // 2 bounds checks. + v := b.in[b.off-4 : b.off] + low := (uint32(v[0])) | (uint32(v[1]) << 8) | (uint32(v[2]) << 16) | (uint32(v[3]) << 24) + b.value |= uint64(low) << (b.bitsRead - 32) + b.bitsRead -= 32 + b.off -= 4 +} + +// fillFastStart() assumes the bitReaderBytes is empty and there is at least 8 bytes to read. +func (b *bitReaderBytes) fillFastStart() { + // Do single re-slice to avoid bounds checks. + b.value = binary.LittleEndian.Uint64(b.in[b.off-8:]) + b.bitsRead = 0 + b.off -= 8 +} + +// fill() will make sure at least 32 bits are available. +func (b *bitReaderBytes) fill() { + if b.bitsRead < 32 { + return + } + if b.off > 4 { + v := b.in[b.off-4 : b.off] + low := (uint32(v[0])) | (uint32(v[1]) << 8) | (uint32(v[2]) << 16) | (uint32(v[3]) << 24) + b.value |= uint64(low) << (b.bitsRead - 32) + b.bitsRead -= 32 + b.off -= 4 + return + } + for b.off > 0 { + b.value |= uint64(b.in[b.off-1]) << (b.bitsRead - 8) + b.bitsRead -= 8 + b.off-- + } +} + +// finished returns true if all bits have been read from the bit stream. +func (b *bitReaderBytes) finished() bool { + return b.off == 0 && b.bitsRead >= 64 +} + +func (b *bitReaderBytes) remaining() uint { + return b.off*8 + uint(64-b.bitsRead) +} + +// close the bitstream and returns an error if out-of-buffer reads occurred. +func (b *bitReaderBytes) close() error { + // Release reference. + b.in = nil + if b.remaining() > 0 { + return fmt.Errorf("corrupt input: %d bits remain on stream", b.remaining()) + } + if b.bitsRead > 64 { + return io.ErrUnexpectedEOF + } + return nil +} + +// bitReaderShifted reads a bitstream in reverse. +// The last set bit indicates the start of the stream and is used +// for aligning the input. +type bitReaderShifted struct { + in []byte + off uint // next byte to read is at in[off - 1] + value uint64 + bitsRead uint8 +} + +// init initializes and resets the bit reader. +func (b *bitReaderShifted) init(in []byte) error { + if len(in) < 1 { + return errors.New("corrupt stream: too short") + } + b.in = in + b.off = uint(len(in)) + // The highest bit of the last byte indicates where to start + v := in[len(in)-1] + if v == 0 { + return errors.New("corrupt stream, did not find end of stream") + } + b.bitsRead = 64 + b.value = 0 + if len(in) >= 8 { + b.fillFastStart() + } else { + b.fill() + b.fill() + } + b.advance(8 - uint8(highBit32(uint32(v)))) + return nil +} + +// peekBitsFast requires that at least one bit is requested every time. +// There are no checks if the buffer is filled. +func (b *bitReaderShifted) peekBitsFast(n uint8) uint16 { + return uint16(b.value >> ((64 - n) & 63)) +} + +func (b *bitReaderShifted) advance(n uint8) { + b.bitsRead += n + b.value <<= n & 63 +} + +// fillFast() will make sure at least 32 bits are available. +// There must be at least 4 bytes available. +func (b *bitReaderShifted) fillFast() { + if b.bitsRead < 32 { + return + } + + // 2 bounds checks. + v := b.in[b.off-4 : b.off] + low := (uint32(v[0])) | (uint32(v[1]) << 8) | (uint32(v[2]) << 16) | (uint32(v[3]) << 24) + b.value |= uint64(low) << ((b.bitsRead - 32) & 63) + b.bitsRead -= 32 + b.off -= 4 +} + +// fillFastStart() assumes the bitReaderShifted is empty and there is at least 8 bytes to read. +func (b *bitReaderShifted) fillFastStart() { + // Do single re-slice to avoid bounds checks. + b.value = binary.LittleEndian.Uint64(b.in[b.off-8:]) + b.bitsRead = 0 + b.off -= 8 +} + +// fill() will make sure at least 32 bits are available. +func (b *bitReaderShifted) fill() { + if b.bitsRead < 32 { + return + } + if b.off > 4 { + v := b.in[b.off-4 : b.off] + low := (uint32(v[0])) | (uint32(v[1]) << 8) | (uint32(v[2]) << 16) | (uint32(v[3]) << 24) + b.value |= uint64(low) << ((b.bitsRead - 32) & 63) + b.bitsRead -= 32 + b.off -= 4 + return + } + for b.off > 0 { + b.value |= uint64(b.in[b.off-1]) << ((b.bitsRead - 8) & 63) + b.bitsRead -= 8 + b.off-- + } +} + +func (b *bitReaderShifted) remaining() uint { + return b.off*8 + uint(64-b.bitsRead) +} + +// close the bitstream and returns an error if out-of-buffer reads occurred. +func (b *bitReaderShifted) close() error { + // Release reference. + b.in = nil + if b.remaining() > 0 { + return fmt.Errorf("corrupt input: %d bits remain on stream", b.remaining()) + } + if b.bitsRead > 64 { + return io.ErrUnexpectedEOF + } + return nil +} diff --git a/vendor/github.com/klauspost/compress/huff0/bitwriter.go b/vendor/github.com/klauspost/compress/huff0/bitwriter.go new file mode 100644 index 000000000..0ebc9aaac --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/bitwriter.go @@ -0,0 +1,102 @@ +// Copyright 2018 Klaus Post. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// Based on work Copyright (c) 2013, Yann Collet, released under BSD License. + +package huff0 + +// bitWriter will write bits. +// First bit will be LSB of the first byte of output. +type bitWriter struct { + bitContainer uint64 + nBits uint8 + out []byte +} + +// addBits16Clean will add up to 16 bits. value may not contain more set bits than indicated. +// It will not check if there is space for them, so the caller must ensure that it has flushed recently. +func (b *bitWriter) addBits16Clean(value uint16, bits uint8) { + b.bitContainer |= uint64(value) << (b.nBits & 63) + b.nBits += bits +} + +// encSymbol will add up to 16 bits. value may not contain more set bits than indicated. +// It will not check if there is space for them, so the caller must ensure that it has flushed recently. +func (b *bitWriter) encSymbol(ct cTable, symbol byte) { + enc := ct[symbol] + b.bitContainer |= uint64(enc.val) << (b.nBits & 63) + if false { + if enc.nBits == 0 { + panic("nbits 0") + } + } + b.nBits += enc.nBits +} + +// encTwoSymbols will add up to 32 bits. value may not contain more set bits than indicated. +// It will not check if there is space for them, so the caller must ensure that it has flushed recently. +func (b *bitWriter) encTwoSymbols(ct cTable, av, bv byte) { + encA := ct[av] + encB := ct[bv] + sh := b.nBits & 63 + combined := uint64(encA.val) | (uint64(encB.val) << (encA.nBits & 63)) + b.bitContainer |= combined << sh + if false { + if encA.nBits == 0 { + panic("nbitsA 0") + } + if encB.nBits == 0 { + panic("nbitsB 0") + } + } + b.nBits += encA.nBits + encB.nBits +} + +// encFourSymbols adds up to 32 bits from four symbols. +// It will not check if there is space for them, +// so the caller must ensure that b has been flushed recently. +func (b *bitWriter) encFourSymbols(encA, encB, encC, encD cTableEntry) { + bitsA := encA.nBits + bitsB := bitsA + encB.nBits + bitsC := bitsB + encC.nBits + bitsD := bitsC + encD.nBits + combined := uint64(encA.val) | + (uint64(encB.val) << (bitsA & 63)) | + (uint64(encC.val) << (bitsB & 63)) | + (uint64(encD.val) << (bitsC & 63)) + b.bitContainer |= combined << (b.nBits & 63) + b.nBits += bitsD +} + +// flush32 will flush out, so there are at least 32 bits available for writing. +func (b *bitWriter) flush32() { + if b.nBits < 32 { + return + } + b.out = append(b.out, + byte(b.bitContainer), + byte(b.bitContainer>>8), + byte(b.bitContainer>>16), + byte(b.bitContainer>>24)) + b.nBits -= 32 + b.bitContainer >>= 32 +} + +// flushAlign will flush remaining full bytes and align to next byte boundary. +func (b *bitWriter) flushAlign() { + nbBytes := (b.nBits + 7) >> 3 + for i := uint8(0); i < nbBytes; i++ { + b.out = append(b.out, byte(b.bitContainer>>(i*8))) + } + b.nBits = 0 + b.bitContainer = 0 +} + +// close will write the alignment bit and write the final byte(s) +// to the output. +func (b *bitWriter) close() { + // End mark + b.addBits16Clean(1, 1) + // flush until next byte. + b.flushAlign() +} diff --git a/vendor/github.com/klauspost/compress/huff0/compress.go b/vendor/github.com/klauspost/compress/huff0/compress.go new file mode 100644 index 000000000..84aa3d12f --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/compress.go @@ -0,0 +1,742 @@ +package huff0 + +import ( + "fmt" + "math" + "runtime" + "sync" +) + +// Compress1X will compress the input. +// The output can be decoded using Decompress1X. +// Supply a Scratch object. The scratch object contains state about re-use, +// So when sharing across independent encodes, be sure to set the re-use policy. +func Compress1X(in []byte, s *Scratch) (out []byte, reUsed bool, err error) { + s, err = s.prepare(in) + if err != nil { + return nil, false, err + } + return compress(in, s, s.compress1X) +} + +// Compress4X will compress the input. The input is split into 4 independent blocks +// and compressed similar to Compress1X. +// The output can be decoded using Decompress4X. +// Supply a Scratch object. The scratch object contains state about re-use, +// So when sharing across independent encodes, be sure to set the re-use policy. +func Compress4X(in []byte, s *Scratch) (out []byte, reUsed bool, err error) { + s, err = s.prepare(in) + if err != nil { + return nil, false, err + } + if false { + // TODO: compress4Xp only slightly faster. + const parallelThreshold = 8 << 10 + if len(in) < parallelThreshold || runtime.GOMAXPROCS(0) == 1 { + return compress(in, s, s.compress4X) + } + return compress(in, s, s.compress4Xp) + } + return compress(in, s, s.compress4X) +} + +func compress(in []byte, s *Scratch, compressor func(src []byte) ([]byte, error)) (out []byte, reUsed bool, err error) { + // Nuke previous table if we cannot reuse anyway. + if s.Reuse == ReusePolicyNone { + s.prevTable = s.prevTable[:0] + } + + // Create histogram, if none was provided. + maxCount := s.maxCount + var canReuse = false + if maxCount == 0 { + maxCount, canReuse = s.countSimple(in) + } else { + canReuse = s.canUseTable(s.prevTable) + } + + // We want the output size to be less than this: + wantSize := len(in) + if s.WantLogLess > 0 { + wantSize -= wantSize >> s.WantLogLess + } + + // Reset for next run. + s.clearCount = true + s.maxCount = 0 + if maxCount >= len(in) { + if maxCount > len(in) { + return nil, false, fmt.Errorf("maxCount (%d) > length (%d)", maxCount, len(in)) + } + if len(in) == 1 { + return nil, false, ErrIncompressible + } + // One symbol, use RLE + return nil, false, ErrUseRLE + } + if maxCount == 1 || maxCount < (len(in)>>7) { + // Each symbol present maximum once or too well distributed. + return nil, false, ErrIncompressible + } + if s.Reuse == ReusePolicyMust && !canReuse { + // We must reuse, but we can't. + return nil, false, ErrIncompressible + } + if (s.Reuse == ReusePolicyPrefer || s.Reuse == ReusePolicyMust) && canReuse { + keepTable := s.cTable + keepTL := s.actualTableLog + s.cTable = s.prevTable + s.actualTableLog = s.prevTableLog + s.Out, err = compressor(in) + s.cTable = keepTable + s.actualTableLog = keepTL + if err == nil && len(s.Out) < wantSize { + s.OutData = s.Out + return s.Out, true, nil + } + if s.Reuse == ReusePolicyMust { + return nil, false, ErrIncompressible + } + // Do not attempt to re-use later. + s.prevTable = s.prevTable[:0] + } + + // Calculate new table. + err = s.buildCTable() + if err != nil { + return nil, false, err + } + + if false && !s.canUseTable(s.cTable) { + panic("invalid table generated") + } + + if s.Reuse == ReusePolicyAllow && canReuse { + hSize := len(s.Out) + oldSize := s.prevTable.estimateSize(s.count[:s.symbolLen]) + newSize := s.cTable.estimateSize(s.count[:s.symbolLen]) + if oldSize <= hSize+newSize || hSize+12 >= wantSize { + // Retain cTable even if we re-use. + keepTable := s.cTable + keepTL := s.actualTableLog + + s.cTable = s.prevTable + s.actualTableLog = s.prevTableLog + s.Out, err = compressor(in) + + // Restore ctable. + s.cTable = keepTable + s.actualTableLog = keepTL + if err != nil { + return nil, false, err + } + if len(s.Out) >= wantSize { + return nil, false, ErrIncompressible + } + s.OutData = s.Out + return s.Out, true, nil + } + } + + // Use new table + err = s.cTable.write(s) + if err != nil { + s.OutTable = nil + return nil, false, err + } + s.OutTable = s.Out + + // Compress using new table + s.Out, err = compressor(in) + if err != nil { + s.OutTable = nil + return nil, false, err + } + if len(s.Out) >= wantSize { + s.OutTable = nil + return nil, false, ErrIncompressible + } + // Move current table into previous. + s.prevTable, s.prevTableLog, s.cTable = s.cTable, s.actualTableLog, s.prevTable[:0] + s.OutData = s.Out[len(s.OutTable):] + return s.Out, false, nil +} + +// EstimateSizes will estimate the data sizes +func EstimateSizes(in []byte, s *Scratch) (tableSz, dataSz, reuseSz int, err error) { + s, err = s.prepare(in) + if err != nil { + return 0, 0, 0, err + } + + // Create histogram, if none was provided. + tableSz, dataSz, reuseSz = -1, -1, -1 + maxCount := s.maxCount + var canReuse = false + if maxCount == 0 { + maxCount, canReuse = s.countSimple(in) + } else { + canReuse = s.canUseTable(s.prevTable) + } + + // We want the output size to be less than this: + wantSize := len(in) + if s.WantLogLess > 0 { + wantSize -= wantSize >> s.WantLogLess + } + + // Reset for next run. + s.clearCount = true + s.maxCount = 0 + if maxCount >= len(in) { + if maxCount > len(in) { + return 0, 0, 0, fmt.Errorf("maxCount (%d) > length (%d)", maxCount, len(in)) + } + if len(in) == 1 { + return 0, 0, 0, ErrIncompressible + } + // One symbol, use RLE + return 0, 0, 0, ErrUseRLE + } + if maxCount == 1 || maxCount < (len(in)>>7) { + // Each symbol present maximum once or too well distributed. + return 0, 0, 0, ErrIncompressible + } + + // Calculate new table. + err = s.buildCTable() + if err != nil { + return 0, 0, 0, err + } + + if false && !s.canUseTable(s.cTable) { + panic("invalid table generated") + } + + tableSz, err = s.cTable.estTableSize(s) + if err != nil { + return 0, 0, 0, err + } + if canReuse { + reuseSz = s.prevTable.estimateSize(s.count[:s.symbolLen]) + } + dataSz = s.cTable.estimateSize(s.count[:s.symbolLen]) + + // Restore + return tableSz, dataSz, reuseSz, nil +} + +func (s *Scratch) compress1X(src []byte) ([]byte, error) { + return s.compress1xDo(s.Out, src), nil +} + +func (s *Scratch) compress1xDo(dst, src []byte) []byte { + var bw = bitWriter{out: dst} + + // N is length divisible by 4. + n := len(src) + n -= n & 3 + cTable := s.cTable[:256] + + // Encode last bytes. + for i := len(src) & 3; i > 0; i-- { + bw.encSymbol(cTable, src[n+i-1]) + } + n -= 4 + if s.actualTableLog <= 8 { + for ; n >= 0; n -= 4 { + tmp := src[n : n+4] + // tmp should be len 4 + bw.flush32() + bw.encFourSymbols(cTable[tmp[3]], cTable[tmp[2]], cTable[tmp[1]], cTable[tmp[0]]) + } + } else { + for ; n >= 0; n -= 4 { + tmp := src[n : n+4] + // tmp should be len 4 + bw.flush32() + bw.encTwoSymbols(cTable, tmp[3], tmp[2]) + bw.flush32() + bw.encTwoSymbols(cTable, tmp[1], tmp[0]) + } + } + bw.close() + return bw.out +} + +var sixZeros [6]byte + +func (s *Scratch) compress4X(src []byte) ([]byte, error) { + if len(src) < 12 { + return nil, ErrIncompressible + } + segmentSize := (len(src) + 3) / 4 + + // Add placeholder for output length + offsetIdx := len(s.Out) + s.Out = append(s.Out, sixZeros[:]...) + + for i := 0; i < 4; i++ { + toDo := src + if len(toDo) > segmentSize { + toDo = toDo[:segmentSize] + } + src = src[len(toDo):] + + idx := len(s.Out) + s.Out = s.compress1xDo(s.Out, toDo) + if len(s.Out)-idx > math.MaxUint16 { + // We cannot store the size in the jump table + return nil, ErrIncompressible + } + // Write compressed length as little endian before block. + if i < 3 { + // Last length is not written. + length := len(s.Out) - idx + s.Out[i*2+offsetIdx] = byte(length) + s.Out[i*2+offsetIdx+1] = byte(length >> 8) + } + } + + return s.Out, nil +} + +// compress4Xp will compress 4 streams using separate goroutines. +func (s *Scratch) compress4Xp(src []byte) ([]byte, error) { + if len(src) < 12 { + return nil, ErrIncompressible + } + // Add placeholder for output length + s.Out = s.Out[:6] + + segmentSize := (len(src) + 3) / 4 + var wg sync.WaitGroup + wg.Add(4) + for i := 0; i < 4; i++ { + toDo := src + if len(toDo) > segmentSize { + toDo = toDo[:segmentSize] + } + src = src[len(toDo):] + + // Separate goroutine for each block. + go func(i int) { + s.tmpOut[i] = s.compress1xDo(s.tmpOut[i][:0], toDo) + wg.Done() + }(i) + } + wg.Wait() + for i := 0; i < 4; i++ { + o := s.tmpOut[i] + if len(o) > math.MaxUint16 { + // We cannot store the size in the jump table + return nil, ErrIncompressible + } + // Write compressed length as little endian before block. + if i < 3 { + // Last length is not written. + s.Out[i*2] = byte(len(o)) + s.Out[i*2+1] = byte(len(o) >> 8) + } + + // Write output. + s.Out = append(s.Out, o...) + } + return s.Out, nil +} + +// countSimple will create a simple histogram in s.count. +// Returns the biggest count. +// Does not update s.clearCount. +func (s *Scratch) countSimple(in []byte) (max int, reuse bool) { + reuse = true + _ = s.count // Assert that s != nil to speed up the following loop. + for _, v := range in { + s.count[v]++ + } + m := uint32(0) + if len(s.prevTable) > 0 { + for i, v := range s.count[:] { + if v == 0 { + continue + } + if v > m { + m = v + } + s.symbolLen = uint16(i) + 1 + if i >= len(s.prevTable) { + reuse = false + } else if s.prevTable[i].nBits == 0 { + reuse = false + } + } + return int(m), reuse + } + for i, v := range s.count[:] { + if v == 0 { + continue + } + if v > m { + m = v + } + s.symbolLen = uint16(i) + 1 + } + return int(m), false +} + +func (s *Scratch) canUseTable(c cTable) bool { + if len(c) < int(s.symbolLen) { + return false + } + for i, v := range s.count[:s.symbolLen] { + if v != 0 && c[i].nBits == 0 { + return false + } + } + return true +} + +//lint:ignore U1000 used for debugging +func (s *Scratch) validateTable(c cTable) bool { + if len(c) < int(s.symbolLen) { + return false + } + for i, v := range s.count[:s.symbolLen] { + if v != 0 { + if c[i].nBits == 0 { + return false + } + if c[i].nBits > s.actualTableLog { + return false + } + } + } + return true +} + +// minTableLog provides the minimum logSize to safely represent a distribution. +func (s *Scratch) minTableLog() uint8 { + minBitsSrc := highBit32(uint32(s.srcLen)) + 1 + minBitsSymbols := highBit32(uint32(s.symbolLen-1)) + 2 + if minBitsSrc < minBitsSymbols { + return uint8(minBitsSrc) + } + return uint8(minBitsSymbols) +} + +// optimalTableLog calculates and sets the optimal tableLog in s.actualTableLog +func (s *Scratch) optimalTableLog() { + tableLog := s.TableLog + minBits := s.minTableLog() + maxBitsSrc := uint8(highBit32(uint32(s.srcLen-1))) - 1 + if maxBitsSrc < tableLog { + // Accuracy can be reduced + tableLog = maxBitsSrc + } + if minBits > tableLog { + tableLog = minBits + } + // Need a minimum to safely represent all symbol values + if tableLog < minTablelog { + tableLog = minTablelog + } + if tableLog > tableLogMax { + tableLog = tableLogMax + } + s.actualTableLog = tableLog +} + +type cTableEntry struct { + val uint16 + nBits uint8 + // We have 8 bits extra +} + +const huffNodesMask = huffNodesLen - 1 + +func (s *Scratch) buildCTable() error { + s.optimalTableLog() + s.huffSort() + if cap(s.cTable) < maxSymbolValue+1 { + s.cTable = make([]cTableEntry, s.symbolLen, maxSymbolValue+1) + } else { + s.cTable = s.cTable[:s.symbolLen] + for i := range s.cTable { + s.cTable[i] = cTableEntry{} + } + } + + var startNode = int16(s.symbolLen) + nonNullRank := s.symbolLen - 1 + + nodeNb := startNode + huffNode := s.nodes[1 : huffNodesLen+1] + + // This overlays the slice above, but allows "-1" index lookups. + // Different from reference implementation. + huffNode0 := s.nodes[0 : huffNodesLen+1] + + for huffNode[nonNullRank].count() == 0 { + nonNullRank-- + } + + lowS := int16(nonNullRank) + nodeRoot := nodeNb + lowS - 1 + lowN := nodeNb + huffNode[nodeNb].setCount(huffNode[lowS].count() + huffNode[lowS-1].count()) + huffNode[lowS].setParent(nodeNb) + huffNode[lowS-1].setParent(nodeNb) + nodeNb++ + lowS -= 2 + for n := nodeNb; n <= nodeRoot; n++ { + huffNode[n].setCount(1 << 30) + } + // fake entry, strong barrier + huffNode0[0].setCount(1 << 31) + + // create parents + for nodeNb <= nodeRoot { + var n1, n2 int16 + if huffNode0[lowS+1].count() < huffNode0[lowN+1].count() { + n1 = lowS + lowS-- + } else { + n1 = lowN + lowN++ + } + if huffNode0[lowS+1].count() < huffNode0[lowN+1].count() { + n2 = lowS + lowS-- + } else { + n2 = lowN + lowN++ + } + + huffNode[nodeNb].setCount(huffNode0[n1+1].count() + huffNode0[n2+1].count()) + huffNode0[n1+1].setParent(nodeNb) + huffNode0[n2+1].setParent(nodeNb) + nodeNb++ + } + + // distribute weights (unlimited tree height) + huffNode[nodeRoot].setNbBits(0) + for n := nodeRoot - 1; n >= startNode; n-- { + huffNode[n].setNbBits(huffNode[huffNode[n].parent()].nbBits() + 1) + } + for n := uint16(0); n <= nonNullRank; n++ { + huffNode[n].setNbBits(huffNode[huffNode[n].parent()].nbBits() + 1) + } + s.actualTableLog = s.setMaxHeight(int(nonNullRank)) + maxNbBits := s.actualTableLog + + // fill result into tree (val, nbBits) + if maxNbBits > tableLogMax { + return fmt.Errorf("internal error: maxNbBits (%d) > tableLogMax (%d)", maxNbBits, tableLogMax) + } + var nbPerRank [tableLogMax + 1]uint16 + var valPerRank [16]uint16 + for _, v := range huffNode[:nonNullRank+1] { + nbPerRank[v.nbBits()]++ + } + // determine stating value per rank + { + min := uint16(0) + for n := maxNbBits; n > 0; n-- { + // get starting value within each rank + valPerRank[n] = min + min += nbPerRank[n] + min >>= 1 + } + } + + // push nbBits per symbol, symbol order + for _, v := range huffNode[:nonNullRank+1] { + s.cTable[v.symbol()].nBits = v.nbBits() + } + + // assign value within rank, symbol order + t := s.cTable[:s.symbolLen] + for n, val := range t { + nbits := val.nBits & 15 + v := valPerRank[nbits] + t[n].val = v + valPerRank[nbits] = v + 1 + } + + return nil +} + +// huffSort will sort symbols, decreasing order. +func (s *Scratch) huffSort() { + type rankPos struct { + base uint32 + current uint32 + } + + // Clear nodes + nodes := s.nodes[:huffNodesLen+1] + s.nodes = nodes + nodes = nodes[1 : huffNodesLen+1] + + // Sort into buckets based on length of symbol count. + var rank [32]rankPos + for _, v := range s.count[:s.symbolLen] { + r := highBit32(v+1) & 31 + rank[r].base++ + } + // maxBitLength is log2(BlockSizeMax) + 1 + const maxBitLength = 18 + 1 + for n := maxBitLength; n > 0; n-- { + rank[n-1].base += rank[n].base + } + for n := range rank[:maxBitLength] { + rank[n].current = rank[n].base + } + for n, c := range s.count[:s.symbolLen] { + r := (highBit32(c+1) + 1) & 31 + pos := rank[r].current + rank[r].current++ + prev := nodes[(pos-1)&huffNodesMask] + for pos > rank[r].base && c > prev.count() { + nodes[pos&huffNodesMask] = prev + pos-- + prev = nodes[(pos-1)&huffNodesMask] + } + nodes[pos&huffNodesMask] = makeNodeElt(c, byte(n)) + } +} + +func (s *Scratch) setMaxHeight(lastNonNull int) uint8 { + maxNbBits := s.actualTableLog + huffNode := s.nodes[1 : huffNodesLen+1] + //huffNode = huffNode[: huffNodesLen] + + largestBits := huffNode[lastNonNull].nbBits() + + // early exit : no elt > maxNbBits + if largestBits <= maxNbBits { + return largestBits + } + totalCost := int(0) + baseCost := int(1) << (largestBits - maxNbBits) + n := uint32(lastNonNull) + + for huffNode[n].nbBits() > maxNbBits { + totalCost += baseCost - (1 << (largestBits - huffNode[n].nbBits())) + huffNode[n].setNbBits(maxNbBits) + n-- + } + // n stops at huffNode[n].nbBits <= maxNbBits + + for huffNode[n].nbBits() == maxNbBits { + n-- + } + // n end at index of smallest symbol using < maxNbBits + + // renorm totalCost + totalCost >>= largestBits - maxNbBits /* note : totalCost is necessarily a multiple of baseCost */ + + // repay normalized cost + { + const noSymbol = 0xF0F0F0F0 + var rankLast [tableLogMax + 2]uint32 + + for i := range rankLast[:] { + rankLast[i] = noSymbol + } + + // Get pos of last (smallest) symbol per rank + { + currentNbBits := maxNbBits + for pos := int(n); pos >= 0; pos-- { + if huffNode[pos].nbBits() >= currentNbBits { + continue + } + currentNbBits = huffNode[pos].nbBits() // < maxNbBits + rankLast[maxNbBits-currentNbBits] = uint32(pos) + } + } + + for totalCost > 0 { + nBitsToDecrease := uint8(highBit32(uint32(totalCost))) + 1 + + for ; nBitsToDecrease > 1; nBitsToDecrease-- { + highPos := rankLast[nBitsToDecrease] + lowPos := rankLast[nBitsToDecrease-1] + if highPos == noSymbol { + continue + } + if lowPos == noSymbol { + break + } + highTotal := huffNode[highPos].count() + lowTotal := 2 * huffNode[lowPos].count() + if highTotal <= lowTotal { + break + } + } + // only triggered when no more rank 1 symbol left => find closest one (note : there is necessarily at least one !) + // HUF_MAX_TABLELOG test just to please gcc 5+; but it should not be necessary + // FIXME: try to remove + for (nBitsToDecrease <= tableLogMax) && (rankLast[nBitsToDecrease] == noSymbol) { + nBitsToDecrease++ + } + totalCost -= 1 << (nBitsToDecrease - 1) + if rankLast[nBitsToDecrease-1] == noSymbol { + // this rank is no longer empty + rankLast[nBitsToDecrease-1] = rankLast[nBitsToDecrease] + } + huffNode[rankLast[nBitsToDecrease]].setNbBits(1 + + huffNode[rankLast[nBitsToDecrease]].nbBits()) + if rankLast[nBitsToDecrease] == 0 { + /* special case, reached largest symbol */ + rankLast[nBitsToDecrease] = noSymbol + } else { + rankLast[nBitsToDecrease]-- + if huffNode[rankLast[nBitsToDecrease]].nbBits() != maxNbBits-nBitsToDecrease { + rankLast[nBitsToDecrease] = noSymbol /* this rank is now empty */ + } + } + } + + for totalCost < 0 { /* Sometimes, cost correction overshoot */ + if rankLast[1] == noSymbol { /* special case : no rank 1 symbol (using maxNbBits-1); let's create one from largest rank 0 (using maxNbBits) */ + for huffNode[n].nbBits() == maxNbBits { + n-- + } + huffNode[n+1].setNbBits(huffNode[n+1].nbBits() - 1) + rankLast[1] = n + 1 + totalCost++ + continue + } + huffNode[rankLast[1]+1].setNbBits(huffNode[rankLast[1]+1].nbBits() - 1) + rankLast[1]++ + totalCost++ + } + } + return maxNbBits +} + +// A nodeElt is the fields +// +// count uint32 +// parent uint16 +// symbol byte +// nbBits uint8 +// +// in some order, all squashed into an integer so that the compiler +// always loads and stores entire nodeElts instead of separate fields. +type nodeElt uint64 + +func makeNodeElt(count uint32, symbol byte) nodeElt { + return nodeElt(count) | nodeElt(symbol)<<48 +} + +func (e *nodeElt) count() uint32 { return uint32(*e) } +func (e *nodeElt) parent() uint16 { return uint16(*e >> 32) } +func (e *nodeElt) symbol() byte { return byte(*e >> 48) } +func (e *nodeElt) nbBits() uint8 { return uint8(*e >> 56) } + +func (e *nodeElt) setCount(c uint32) { *e = (*e)&0xffffffff00000000 | nodeElt(c) } +func (e *nodeElt) setParent(p int16) { *e = (*e)&0xffff0000ffffffff | nodeElt(uint16(p))<<32 } +func (e *nodeElt) setNbBits(n uint8) { *e = (*e)&0x00ffffffffffffff | nodeElt(n)<<56 } diff --git a/vendor/github.com/klauspost/compress/huff0/decompress.go b/vendor/github.com/klauspost/compress/huff0/decompress.go new file mode 100644 index 000000000..54bd08b25 --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/decompress.go @@ -0,0 +1,1167 @@ +package huff0 + +import ( + "errors" + "fmt" + "io" + "sync" + + "github.com/klauspost/compress/fse" +) + +type dTable struct { + single []dEntrySingle +} + +// single-symbols decoding +type dEntrySingle struct { + entry uint16 +} + +// Uses special code for all tables that are < 8 bits. +const use8BitTables = true + +// ReadTable will read a table from the input. +// The size of the input may be larger than the table definition. +// Any content remaining after the table definition will be returned. +// If no Scratch is provided a new one is allocated. +// The returned Scratch can be used for encoding or decoding input using this table. +func ReadTable(in []byte, s *Scratch) (s2 *Scratch, remain []byte, err error) { + s, err = s.prepare(nil) + if err != nil { + return s, nil, err + } + if len(in) <= 1 { + return s, nil, errors.New("input too small for table") + } + iSize := in[0] + in = in[1:] + if iSize >= 128 { + // Uncompressed + oSize := iSize - 127 + iSize = (oSize + 1) / 2 + if int(iSize) > len(in) { + return s, nil, errors.New("input too small for table") + } + for n := uint8(0); n < oSize; n += 2 { + v := in[n/2] + s.huffWeight[n] = v >> 4 + s.huffWeight[n+1] = v & 15 + } + s.symbolLen = uint16(oSize) + in = in[iSize:] + } else { + if len(in) < int(iSize) { + return s, nil, fmt.Errorf("input too small for table, want %d bytes, have %d", iSize, len(in)) + } + // FSE compressed weights + s.fse.DecompressLimit = 255 + hw := s.huffWeight[:] + s.fse.Out = hw + b, err := fse.Decompress(in[:iSize], s.fse) + s.fse.Out = nil + if err != nil { + return s, nil, fmt.Errorf("fse decompress returned: %w", err) + } + if len(b) > 255 { + return s, nil, errors.New("corrupt input: output table too large") + } + s.symbolLen = uint16(len(b)) + in = in[iSize:] + } + + // collect weight stats + var rankStats [16]uint32 + weightTotal := uint32(0) + for _, v := range s.huffWeight[:s.symbolLen] { + if v > tableLogMax { + return s, nil, errors.New("corrupt input: weight too large") + } + v2 := v & 15 + rankStats[v2]++ + // (1 << (v2-1)) is slower since the compiler cannot prove that v2 isn't 0. + weightTotal += (1 << v2) >> 1 + } + if weightTotal == 0 { + return s, nil, errors.New("corrupt input: weights zero") + } + + // get last non-null symbol weight (implied, total must be 2^n) + { + tableLog := highBit32(weightTotal) + 1 + if tableLog > tableLogMax { + return s, nil, errors.New("corrupt input: tableLog too big") + } + s.actualTableLog = uint8(tableLog) + // determine last weight + { + total := uint32(1) << tableLog + rest := total - weightTotal + verif := uint32(1) << highBit32(rest) + lastWeight := highBit32(rest) + 1 + if verif != rest { + // last value must be a clean power of 2 + return s, nil, errors.New("corrupt input: last value not power of two") + } + s.huffWeight[s.symbolLen] = uint8(lastWeight) + s.symbolLen++ + rankStats[lastWeight]++ + } + } + + if (rankStats[1] < 2) || (rankStats[1]&1 != 0) { + // by construction : at least 2 elts of rank 1, must be even + return s, nil, errors.New("corrupt input: min elt size, even check failed ") + } + + // TODO: Choose between single/double symbol decoding + + // Calculate starting value for each rank + { + var nextRankStart uint32 + for n := uint8(1); n < s.actualTableLog+1; n++ { + current := nextRankStart + nextRankStart += rankStats[n] << (n - 1) + rankStats[n] = current + } + } + + // fill DTable (always full size) + tSize := 1 << tableLogMax + if len(s.dt.single) != tSize { + s.dt.single = make([]dEntrySingle, tSize) + } + cTable := s.prevTable + if cap(cTable) < maxSymbolValue+1 { + cTable = make([]cTableEntry, 0, maxSymbolValue+1) + } + cTable = cTable[:maxSymbolValue+1] + s.prevTable = cTable[:s.symbolLen] + s.prevTableLog = s.actualTableLog + + for n, w := range s.huffWeight[:s.symbolLen] { + if w == 0 { + cTable[n] = cTableEntry{ + val: 0, + nBits: 0, + } + continue + } + length := (uint32(1) << w) >> 1 + d := dEntrySingle{ + entry: uint16(s.actualTableLog+1-w) | (uint16(n) << 8), + } + + rank := &rankStats[w] + cTable[n] = cTableEntry{ + val: uint16(*rank >> (w - 1)), + nBits: uint8(d.entry), + } + + single := s.dt.single[*rank : *rank+length] + for i := range single { + single[i] = d + } + *rank += length + } + + return s, in, nil +} + +// Decompress1X will decompress a 1X encoded stream. +// The length of the supplied input must match the end of a block exactly. +// Before this is called, the table must be initialized with ReadTable unless +// the encoder re-used the table. +// deprecated: Use the stateless Decoder() to get a concurrent version. +func (s *Scratch) Decompress1X(in []byte) (out []byte, err error) { + if cap(s.Out) < s.MaxDecodedSize { + s.Out = make([]byte, s.MaxDecodedSize) + } + s.Out = s.Out[:0:s.MaxDecodedSize] + s.Out, err = s.Decoder().Decompress1X(s.Out, in) + return s.Out, err +} + +// Decompress4X will decompress a 4X encoded stream. +// Before this is called, the table must be initialized with ReadTable unless +// the encoder re-used the table. +// The length of the supplied input must match the end of a block exactly. +// The destination size of the uncompressed data must be known and provided. +// deprecated: Use the stateless Decoder() to get a concurrent version. +func (s *Scratch) Decompress4X(in []byte, dstSize int) (out []byte, err error) { + if dstSize > s.MaxDecodedSize { + return nil, ErrMaxDecodedSizeExceeded + } + if cap(s.Out) < dstSize { + s.Out = make([]byte, s.MaxDecodedSize) + } + s.Out = s.Out[:0:dstSize] + s.Out, err = s.Decoder().Decompress4X(s.Out, in) + return s.Out, err +} + +// Decoder will return a stateless decoder that can be used by multiple +// decompressors concurrently. +// Before this is called, the table must be initialized with ReadTable. +// The Decoder is still linked to the scratch buffer so that cannot be reused. +// However, it is safe to discard the scratch. +func (s *Scratch) Decoder() *Decoder { + return &Decoder{ + dt: s.dt, + actualTableLog: s.actualTableLog, + bufs: &s.decPool, + } +} + +// Decoder provides stateless decoding. +type Decoder struct { + dt dTable + actualTableLog uint8 + bufs *sync.Pool +} + +func (d *Decoder) buffer() *[4][256]byte { + buf, ok := d.bufs.Get().(*[4][256]byte) + if ok { + return buf + } + return &[4][256]byte{} +} + +// decompress1X8Bit will decompress a 1X encoded stream with tablelog <= 8. +// The cap of the output buffer will be the maximum decompressed size. +// The length of the supplied input must match the end of a block exactly. +func (d *Decoder) decompress1X8Bit(dst, src []byte) ([]byte, error) { + if d.actualTableLog == 8 { + return d.decompress1X8BitExactly(dst, src) + } + var br bitReaderBytes + err := br.init(src) + if err != nil { + return dst, err + } + maxDecodedSize := cap(dst) + dst = dst[:0] + + // Avoid bounds check by always having full sized table. + dt := d.dt.single[:256] + + // Use temp table to avoid bound checks/append penalty. + bufs := d.buffer() + buf := &bufs[0] + var off uint8 + + switch d.actualTableLog { + case 8: + const shift = 0 + for br.off >= 4 { + br.fillFast() + v := dt[uint8(br.value>>(56+shift))] + br.advance(uint8(v.entry)) + buf[off+0] = uint8(v.entry >> 8) + + v = dt[uint8(br.value>>(56+shift))] + br.advance(uint8(v.entry)) + buf[off+1] = uint8(v.entry >> 8) + + v = dt[uint8(br.value>>(56+shift))] + br.advance(uint8(v.entry)) + buf[off+2] = uint8(v.entry >> 8) + + v = dt[uint8(br.value>>(56+shift))] + br.advance(uint8(v.entry)) + buf[off+3] = uint8(v.entry >> 8) + + off += 4 + if off == 0 { + if len(dst)+256 > maxDecodedSize { + br.close() + d.bufs.Put(bufs) + return nil, ErrMaxDecodedSizeExceeded + } + dst = append(dst, buf[:]...) + } + } + case 7: + const shift = 8 - 7 + for br.off >= 4 { + br.fillFast() + v := dt[uint8(br.value>>(56+shift))] + br.advance(uint8(v.entry)) + buf[off+0] = uint8(v.entry >> 8) + + v = dt[uint8(br.value>>(56+shift))] + br.advance(uint8(v.entry)) + buf[off+1] = uint8(v.entry >> 8) + + v = dt[uint8(br.value>>(56+shift))] + br.advance(uint8(v.entry)) + buf[off+2] = uint8(v.entry >> 8) + + v = dt[uint8(br.value>>(56+shift))] + br.advance(uint8(v.entry)) + buf[off+3] = uint8(v.entry >> 8) + + off += 4 + if off == 0 { + if len(dst)+256 > maxDecodedSize { + br.close() + d.bufs.Put(bufs) + return nil, ErrMaxDecodedSizeExceeded + } + dst = append(dst, buf[:]...) + } + } + case 6: + const shift = 8 - 6 + for br.off >= 4 { + br.fillFast() + v := dt[uint8(br.value>>(56+shift))] + br.advance(uint8(v.entry)) + buf[off+0] = uint8(v.entry >> 8) + + v = dt[uint8(br.value>>(56+shift))] + br.advance(uint8(v.entry)) + buf[off+1] = uint8(v.entry >> 8) + + v = dt[uint8(br.value>>(56+shift))] + br.advance(uint8(v.entry)) + buf[off+2] = uint8(v.entry >> 8) + + v = dt[uint8(br.value>>(56+shift))] + br.advance(uint8(v.entry)) + buf[off+3] = uint8(v.entry >> 8) + + off += 4 + if off == 0 { + if len(dst)+256 > maxDecodedSize { + d.bufs.Put(bufs) + br.close() + return nil, ErrMaxDecodedSizeExceeded + } + dst = append(dst, buf[:]...) + } + } + case 5: + const shift = 8 - 5 + for br.off >= 4 { + br.fillFast() + v := dt[uint8(br.value>>(56+shift))] + br.advance(uint8(v.entry)) + buf[off+0] = uint8(v.entry >> 8) + + v = dt[uint8(br.value>>(56+shift))] + br.advance(uint8(v.entry)) + buf[off+1] = uint8(v.entry >> 8) + + v = dt[uint8(br.value>>(56+shift))] + br.advance(uint8(v.entry)) + buf[off+2] = uint8(v.entry >> 8) + + v = dt[uint8(br.value>>(56+shift))] + br.advance(uint8(v.entry)) + buf[off+3] = uint8(v.entry >> 8) + + off += 4 + if off == 0 { + if len(dst)+256 > maxDecodedSize { + d.bufs.Put(bufs) + br.close() + return nil, ErrMaxDecodedSizeExceeded + } + dst = append(dst, buf[:]...) + } + } + case 4: + const shift = 8 - 4 + for br.off >= 4 { + br.fillFast() + v := dt[uint8(br.value>>(56+shift))] + br.advance(uint8(v.entry)) + buf[off+0] = uint8(v.entry >> 8) + + v = dt[uint8(br.value>>(56+shift))] + br.advance(uint8(v.entry)) + buf[off+1] = uint8(v.entry >> 8) + + v = dt[uint8(br.value>>(56+shift))] + br.advance(uint8(v.entry)) + buf[off+2] = uint8(v.entry >> 8) + + v = dt[uint8(br.value>>(56+shift))] + br.advance(uint8(v.entry)) + buf[off+3] = uint8(v.entry >> 8) + + off += 4 + if off == 0 { + if len(dst)+256 > maxDecodedSize { + d.bufs.Put(bufs) + br.close() + return nil, ErrMaxDecodedSizeExceeded + } + dst = append(dst, buf[:]...) + } + } + case 3: + const shift = 8 - 3 + for br.off >= 4 { + br.fillFast() + v := dt[uint8(br.value>>(56+shift))] + br.advance(uint8(v.entry)) + buf[off+0] = uint8(v.entry >> 8) + + v = dt[uint8(br.value>>(56+shift))] + br.advance(uint8(v.entry)) + buf[off+1] = uint8(v.entry >> 8) + + v = dt[uint8(br.value>>(56+shift))] + br.advance(uint8(v.entry)) + buf[off+2] = uint8(v.entry >> 8) + + v = dt[uint8(br.value>>(56+shift))] + br.advance(uint8(v.entry)) + buf[off+3] = uint8(v.entry >> 8) + + off += 4 + if off == 0 { + if len(dst)+256 > maxDecodedSize { + d.bufs.Put(bufs) + br.close() + return nil, ErrMaxDecodedSizeExceeded + } + dst = append(dst, buf[:]...) + } + } + case 2: + const shift = 8 - 2 + for br.off >= 4 { + br.fillFast() + v := dt[uint8(br.value>>(56+shift))] + br.advance(uint8(v.entry)) + buf[off+0] = uint8(v.entry >> 8) + + v = dt[uint8(br.value>>(56+shift))] + br.advance(uint8(v.entry)) + buf[off+1] = uint8(v.entry >> 8) + + v = dt[uint8(br.value>>(56+shift))] + br.advance(uint8(v.entry)) + buf[off+2] = uint8(v.entry >> 8) + + v = dt[uint8(br.value>>(56+shift))] + br.advance(uint8(v.entry)) + buf[off+3] = uint8(v.entry >> 8) + + off += 4 + if off == 0 { + if len(dst)+256 > maxDecodedSize { + d.bufs.Put(bufs) + br.close() + return nil, ErrMaxDecodedSizeExceeded + } + dst = append(dst, buf[:]...) + } + } + case 1: + const shift = 8 - 1 + for br.off >= 4 { + br.fillFast() + v := dt[uint8(br.value>>(56+shift))] + br.advance(uint8(v.entry)) + buf[off+0] = uint8(v.entry >> 8) + + v = dt[uint8(br.value>>(56+shift))] + br.advance(uint8(v.entry)) + buf[off+1] = uint8(v.entry >> 8) + + v = dt[uint8(br.value>>(56+shift))] + br.advance(uint8(v.entry)) + buf[off+2] = uint8(v.entry >> 8) + + v = dt[uint8(br.value>>(56+shift))] + br.advance(uint8(v.entry)) + buf[off+3] = uint8(v.entry >> 8) + + off += 4 + if off == 0 { + if len(dst)+256 > maxDecodedSize { + d.bufs.Put(bufs) + br.close() + return nil, ErrMaxDecodedSizeExceeded + } + dst = append(dst, buf[:]...) + } + } + default: + d.bufs.Put(bufs) + return nil, fmt.Errorf("invalid tablelog: %d", d.actualTableLog) + } + + if len(dst)+int(off) > maxDecodedSize { + d.bufs.Put(bufs) + br.close() + return nil, ErrMaxDecodedSizeExceeded + } + dst = append(dst, buf[:off]...) + + // br < 4, so uint8 is fine + bitsLeft := int8(uint8(br.off)*8 + (64 - br.bitsRead)) + shift := (8 - d.actualTableLog) & 7 + + for bitsLeft > 0 { + if br.bitsRead >= 64-8 { + for br.off > 0 { + br.value |= uint64(br.in[br.off-1]) << (br.bitsRead - 8) + br.bitsRead -= 8 + br.off-- + } + } + if len(dst) >= maxDecodedSize { + br.close() + d.bufs.Put(bufs) + return nil, ErrMaxDecodedSizeExceeded + } + v := dt[br.peekByteFast()>>shift] + nBits := uint8(v.entry) + br.advance(nBits) + bitsLeft -= int8(nBits) + dst = append(dst, uint8(v.entry>>8)) + } + d.bufs.Put(bufs) + return dst, br.close() +} + +// decompress1X8Bit will decompress a 1X encoded stream with tablelog <= 8. +// The cap of the output buffer will be the maximum decompressed size. +// The length of the supplied input must match the end of a block exactly. +func (d *Decoder) decompress1X8BitExactly(dst, src []byte) ([]byte, error) { + var br bitReaderBytes + err := br.init(src) + if err != nil { + return dst, err + } + maxDecodedSize := cap(dst) + dst = dst[:0] + + // Avoid bounds check by always having full sized table. + dt := d.dt.single[:256] + + // Use temp table to avoid bound checks/append penalty. + bufs := d.buffer() + buf := &bufs[0] + var off uint8 + + const shift = 56 + + //fmt.Printf("mask: %b, tl:%d\n", mask, d.actualTableLog) + for br.off >= 4 { + br.fillFast() + v := dt[uint8(br.value>>shift)] + br.advance(uint8(v.entry)) + buf[off+0] = uint8(v.entry >> 8) + + v = dt[uint8(br.value>>shift)] + br.advance(uint8(v.entry)) + buf[off+1] = uint8(v.entry >> 8) + + v = dt[uint8(br.value>>shift)] + br.advance(uint8(v.entry)) + buf[off+2] = uint8(v.entry >> 8) + + v = dt[uint8(br.value>>shift)] + br.advance(uint8(v.entry)) + buf[off+3] = uint8(v.entry >> 8) + + off += 4 + if off == 0 { + if len(dst)+256 > maxDecodedSize { + d.bufs.Put(bufs) + br.close() + return nil, ErrMaxDecodedSizeExceeded + } + dst = append(dst, buf[:]...) + } + } + + if len(dst)+int(off) > maxDecodedSize { + d.bufs.Put(bufs) + br.close() + return nil, ErrMaxDecodedSizeExceeded + } + dst = append(dst, buf[:off]...) + + // br < 4, so uint8 is fine + bitsLeft := int8(uint8(br.off)*8 + (64 - br.bitsRead)) + for bitsLeft > 0 { + if br.bitsRead >= 64-8 { + for br.off > 0 { + br.value |= uint64(br.in[br.off-1]) << (br.bitsRead - 8) + br.bitsRead -= 8 + br.off-- + } + } + if len(dst) >= maxDecodedSize { + d.bufs.Put(bufs) + br.close() + return nil, ErrMaxDecodedSizeExceeded + } + v := dt[br.peekByteFast()] + nBits := uint8(v.entry) + br.advance(nBits) + bitsLeft -= int8(nBits) + dst = append(dst, uint8(v.entry>>8)) + } + d.bufs.Put(bufs) + return dst, br.close() +} + +// Decompress4X will decompress a 4X encoded stream. +// The length of the supplied input must match the end of a block exactly. +// The *capacity* of the dst slice must match the destination size of +// the uncompressed data exactly. +func (d *Decoder) decompress4X8bit(dst, src []byte) ([]byte, error) { + if d.actualTableLog == 8 { + return d.decompress4X8bitExactly(dst, src) + } + + var br [4]bitReaderBytes + start := 6 + for i := 0; i < 3; i++ { + length := int(src[i*2]) | (int(src[i*2+1]) << 8) + if start+length >= len(src) { + return nil, errors.New("truncated input (or invalid offset)") + } + err := br[i].init(src[start : start+length]) + if err != nil { + return nil, err + } + start += length + } + err := br[3].init(src[start:]) + if err != nil { + return nil, err + } + + // destination, offset to match first output + dstSize := cap(dst) + dst = dst[:dstSize] + out := dst + dstEvery := (dstSize + 3) / 4 + + shift := (56 + (8 - d.actualTableLog)) & 63 + + const tlSize = 1 << 8 + single := d.dt.single[:tlSize] + + // Use temp table to avoid bound checks/append penalty. + buf := d.buffer() + var off uint8 + var decoded int + + // Decode 4 values from each decoder/loop. + const bufoff = 256 + for { + if br[0].off < 4 || br[1].off < 4 || br[2].off < 4 || br[3].off < 4 { + break + } + + { + // Interleave 2 decodes. + const stream = 0 + const stream2 = 1 + br1 := &br[stream] + br2 := &br[stream2] + br1.fillFast() + br2.fillFast() + + v := single[uint8(br1.value>>shift)].entry + v2 := single[uint8(br2.value>>shift)].entry + br1.bitsRead += uint8(v) + br1.value <<= v & 63 + br2.bitsRead += uint8(v2) + br2.value <<= v2 & 63 + buf[stream][off] = uint8(v >> 8) + buf[stream2][off] = uint8(v2 >> 8) + + v = single[uint8(br1.value>>shift)].entry + v2 = single[uint8(br2.value>>shift)].entry + br1.bitsRead += uint8(v) + br1.value <<= v & 63 + br2.bitsRead += uint8(v2) + br2.value <<= v2 & 63 + buf[stream][off+1] = uint8(v >> 8) + buf[stream2][off+1] = uint8(v2 >> 8) + + v = single[uint8(br1.value>>shift)].entry + v2 = single[uint8(br2.value>>shift)].entry + br1.bitsRead += uint8(v) + br1.value <<= v & 63 + br2.bitsRead += uint8(v2) + br2.value <<= v2 & 63 + buf[stream][off+2] = uint8(v >> 8) + buf[stream2][off+2] = uint8(v2 >> 8) + + v = single[uint8(br1.value>>shift)].entry + v2 = single[uint8(br2.value>>shift)].entry + br1.bitsRead += uint8(v) + br1.value <<= v & 63 + br2.bitsRead += uint8(v2) + br2.value <<= v2 & 63 + buf[stream][off+3] = uint8(v >> 8) + buf[stream2][off+3] = uint8(v2 >> 8) + } + + { + const stream = 2 + const stream2 = 3 + br1 := &br[stream] + br2 := &br[stream2] + br1.fillFast() + br2.fillFast() + + v := single[uint8(br1.value>>shift)].entry + v2 := single[uint8(br2.value>>shift)].entry + br1.bitsRead += uint8(v) + br1.value <<= v & 63 + br2.bitsRead += uint8(v2) + br2.value <<= v2 & 63 + buf[stream][off] = uint8(v >> 8) + buf[stream2][off] = uint8(v2 >> 8) + + v = single[uint8(br1.value>>shift)].entry + v2 = single[uint8(br2.value>>shift)].entry + br1.bitsRead += uint8(v) + br1.value <<= v & 63 + br2.bitsRead += uint8(v2) + br2.value <<= v2 & 63 + buf[stream][off+1] = uint8(v >> 8) + buf[stream2][off+1] = uint8(v2 >> 8) + + v = single[uint8(br1.value>>shift)].entry + v2 = single[uint8(br2.value>>shift)].entry + br1.bitsRead += uint8(v) + br1.value <<= v & 63 + br2.bitsRead += uint8(v2) + br2.value <<= v2 & 63 + buf[stream][off+2] = uint8(v >> 8) + buf[stream2][off+2] = uint8(v2 >> 8) + + v = single[uint8(br1.value>>shift)].entry + v2 = single[uint8(br2.value>>shift)].entry + br1.bitsRead += uint8(v) + br1.value <<= v & 63 + br2.bitsRead += uint8(v2) + br2.value <<= v2 & 63 + buf[stream][off+3] = uint8(v >> 8) + buf[stream2][off+3] = uint8(v2 >> 8) + } + + off += 4 + + if off == 0 { + if bufoff > dstEvery { + d.bufs.Put(buf) + return nil, errors.New("corruption detected: stream overrun 1") + } + // There must at least be 3 buffers left. + if len(out)-bufoff < dstEvery*3 { + d.bufs.Put(buf) + return nil, errors.New("corruption detected: stream overrun 2") + } + //copy(out, buf[0][:]) + //copy(out[dstEvery:], buf[1][:]) + //copy(out[dstEvery*2:], buf[2][:]) + *(*[bufoff]byte)(out) = buf[0] + *(*[bufoff]byte)(out[dstEvery:]) = buf[1] + *(*[bufoff]byte)(out[dstEvery*2:]) = buf[2] + *(*[bufoff]byte)(out[dstEvery*3:]) = buf[3] + out = out[bufoff:] + decoded += bufoff * 4 + } + } + if off > 0 { + ioff := int(off) + if len(out) < dstEvery*3+ioff { + d.bufs.Put(buf) + return nil, errors.New("corruption detected: stream overrun 3") + } + copy(out, buf[0][:off]) + copy(out[dstEvery:], buf[1][:off]) + copy(out[dstEvery*2:], buf[2][:off]) + copy(out[dstEvery*3:], buf[3][:off]) + decoded += int(off) * 4 + out = out[off:] + } + + // Decode remaining. + // Decode remaining. + remainBytes := dstEvery - (decoded / 4) + for i := range br { + offset := dstEvery * i + endsAt := offset + remainBytes + if endsAt > len(out) { + endsAt = len(out) + } + br := &br[i] + bitsLeft := br.remaining() + for bitsLeft > 0 { + if br.finished() { + d.bufs.Put(buf) + return nil, io.ErrUnexpectedEOF + } + if br.bitsRead >= 56 { + if br.off >= 4 { + v := br.in[br.off-4:] + v = v[:4] + low := (uint32(v[0])) | (uint32(v[1]) << 8) | (uint32(v[2]) << 16) | (uint32(v[3]) << 24) + br.value |= uint64(low) << (br.bitsRead - 32) + br.bitsRead -= 32 + br.off -= 4 + } else { + for br.off > 0 { + br.value |= uint64(br.in[br.off-1]) << (br.bitsRead - 8) + br.bitsRead -= 8 + br.off-- + } + } + } + // end inline... + if offset >= endsAt { + d.bufs.Put(buf) + return nil, errors.New("corruption detected: stream overrun 4") + } + + // Read value and increment offset. + v := single[uint8(br.value>>shift)].entry + nBits := uint8(v) + br.advance(nBits) + bitsLeft -= uint(nBits) + out[offset] = uint8(v >> 8) + offset++ + } + if offset != endsAt { + d.bufs.Put(buf) + return nil, fmt.Errorf("corruption detected: short output block %d, end %d != %d", i, offset, endsAt) + } + decoded += offset - dstEvery*i + err = br.close() + if err != nil { + d.bufs.Put(buf) + return nil, err + } + } + d.bufs.Put(buf) + if dstSize != decoded { + return nil, errors.New("corruption detected: short output block") + } + return dst, nil +} + +// Decompress4X will decompress a 4X encoded stream. +// The length of the supplied input must match the end of a block exactly. +// The *capacity* of the dst slice must match the destination size of +// the uncompressed data exactly. +func (d *Decoder) decompress4X8bitExactly(dst, src []byte) ([]byte, error) { + var br [4]bitReaderBytes + start := 6 + for i := 0; i < 3; i++ { + length := int(src[i*2]) | (int(src[i*2+1]) << 8) + if start+length >= len(src) { + return nil, errors.New("truncated input (or invalid offset)") + } + err := br[i].init(src[start : start+length]) + if err != nil { + return nil, err + } + start += length + } + err := br[3].init(src[start:]) + if err != nil { + return nil, err + } + + // destination, offset to match first output + dstSize := cap(dst) + dst = dst[:dstSize] + out := dst + dstEvery := (dstSize + 3) / 4 + + const shift = 56 + const tlSize = 1 << 8 + single := d.dt.single[:tlSize] + + // Use temp table to avoid bound checks/append penalty. + buf := d.buffer() + var off uint8 + var decoded int + + // Decode 4 values from each decoder/loop. + const bufoff = 256 + for { + if br[0].off < 4 || br[1].off < 4 || br[2].off < 4 || br[3].off < 4 { + break + } + + { + // Interleave 2 decodes. + const stream = 0 + const stream2 = 1 + br1 := &br[stream] + br2 := &br[stream2] + br1.fillFast() + br2.fillFast() + + v := single[uint8(br1.value>>shift)].entry + v2 := single[uint8(br2.value>>shift)].entry + br1.bitsRead += uint8(v) + br1.value <<= v & 63 + br2.bitsRead += uint8(v2) + br2.value <<= v2 & 63 + buf[stream][off] = uint8(v >> 8) + buf[stream2][off] = uint8(v2 >> 8) + + v = single[uint8(br1.value>>shift)].entry + v2 = single[uint8(br2.value>>shift)].entry + br1.bitsRead += uint8(v) + br1.value <<= v & 63 + br2.bitsRead += uint8(v2) + br2.value <<= v2 & 63 + buf[stream][off+1] = uint8(v >> 8) + buf[stream2][off+1] = uint8(v2 >> 8) + + v = single[uint8(br1.value>>shift)].entry + v2 = single[uint8(br2.value>>shift)].entry + br1.bitsRead += uint8(v) + br1.value <<= v & 63 + br2.bitsRead += uint8(v2) + br2.value <<= v2 & 63 + buf[stream][off+2] = uint8(v >> 8) + buf[stream2][off+2] = uint8(v2 >> 8) + + v = single[uint8(br1.value>>shift)].entry + v2 = single[uint8(br2.value>>shift)].entry + br1.bitsRead += uint8(v) + br1.value <<= v & 63 + br2.bitsRead += uint8(v2) + br2.value <<= v2 & 63 + buf[stream][off+3] = uint8(v >> 8) + buf[stream2][off+3] = uint8(v2 >> 8) + } + + { + const stream = 2 + const stream2 = 3 + br1 := &br[stream] + br2 := &br[stream2] + br1.fillFast() + br2.fillFast() + + v := single[uint8(br1.value>>shift)].entry + v2 := single[uint8(br2.value>>shift)].entry + br1.bitsRead += uint8(v) + br1.value <<= v & 63 + br2.bitsRead += uint8(v2) + br2.value <<= v2 & 63 + buf[stream][off] = uint8(v >> 8) + buf[stream2][off] = uint8(v2 >> 8) + + v = single[uint8(br1.value>>shift)].entry + v2 = single[uint8(br2.value>>shift)].entry + br1.bitsRead += uint8(v) + br1.value <<= v & 63 + br2.bitsRead += uint8(v2) + br2.value <<= v2 & 63 + buf[stream][off+1] = uint8(v >> 8) + buf[stream2][off+1] = uint8(v2 >> 8) + + v = single[uint8(br1.value>>shift)].entry + v2 = single[uint8(br2.value>>shift)].entry + br1.bitsRead += uint8(v) + br1.value <<= v & 63 + br2.bitsRead += uint8(v2) + br2.value <<= v2 & 63 + buf[stream][off+2] = uint8(v >> 8) + buf[stream2][off+2] = uint8(v2 >> 8) + + v = single[uint8(br1.value>>shift)].entry + v2 = single[uint8(br2.value>>shift)].entry + br1.bitsRead += uint8(v) + br1.value <<= v & 63 + br2.bitsRead += uint8(v2) + br2.value <<= v2 & 63 + buf[stream][off+3] = uint8(v >> 8) + buf[stream2][off+3] = uint8(v2 >> 8) + } + + off += 4 + + if off == 0 { + if bufoff > dstEvery { + d.bufs.Put(buf) + return nil, errors.New("corruption detected: stream overrun 1") + } + // There must at least be 3 buffers left. + if len(out)-bufoff < dstEvery*3 { + d.bufs.Put(buf) + return nil, errors.New("corruption detected: stream overrun 2") + } + + //copy(out, buf[0][:]) + //copy(out[dstEvery:], buf[1][:]) + //copy(out[dstEvery*2:], buf[2][:]) + // copy(out[dstEvery*3:], buf[3][:]) + *(*[bufoff]byte)(out) = buf[0] + *(*[bufoff]byte)(out[dstEvery:]) = buf[1] + *(*[bufoff]byte)(out[dstEvery*2:]) = buf[2] + *(*[bufoff]byte)(out[dstEvery*3:]) = buf[3] + out = out[bufoff:] + decoded += bufoff * 4 + } + } + if off > 0 { + ioff := int(off) + if len(out) < dstEvery*3+ioff { + return nil, errors.New("corruption detected: stream overrun 3") + } + copy(out, buf[0][:off]) + copy(out[dstEvery:], buf[1][:off]) + copy(out[dstEvery*2:], buf[2][:off]) + copy(out[dstEvery*3:], buf[3][:off]) + decoded += int(off) * 4 + out = out[off:] + } + + // Decode remaining. + remainBytes := dstEvery - (decoded / 4) + for i := range br { + offset := dstEvery * i + endsAt := offset + remainBytes + if endsAt > len(out) { + endsAt = len(out) + } + br := &br[i] + bitsLeft := br.remaining() + for bitsLeft > 0 { + if br.finished() { + d.bufs.Put(buf) + return nil, io.ErrUnexpectedEOF + } + if br.bitsRead >= 56 { + if br.off >= 4 { + v := br.in[br.off-4:] + v = v[:4] + low := (uint32(v[0])) | (uint32(v[1]) << 8) | (uint32(v[2]) << 16) | (uint32(v[3]) << 24) + br.value |= uint64(low) << (br.bitsRead - 32) + br.bitsRead -= 32 + br.off -= 4 + } else { + for br.off > 0 { + br.value |= uint64(br.in[br.off-1]) << (br.bitsRead - 8) + br.bitsRead -= 8 + br.off-- + } + } + } + // end inline... + if offset >= endsAt { + d.bufs.Put(buf) + return nil, errors.New("corruption detected: stream overrun 4") + } + + // Read value and increment offset. + v := single[br.peekByteFast()].entry + nBits := uint8(v) + br.advance(nBits) + bitsLeft -= uint(nBits) + out[offset] = uint8(v >> 8) + offset++ + } + if offset != endsAt { + d.bufs.Put(buf) + return nil, fmt.Errorf("corruption detected: short output block %d, end %d != %d", i, offset, endsAt) + } + + decoded += offset - dstEvery*i + err = br.close() + if err != nil { + d.bufs.Put(buf) + return nil, err + } + } + d.bufs.Put(buf) + if dstSize != decoded { + return nil, errors.New("corruption detected: short output block") + } + return dst, nil +} + +// matches will compare a decoding table to a coding table. +// Errors are written to the writer. +// Nothing will be written if table is ok. +func (s *Scratch) matches(ct cTable, w io.Writer) { + if s == nil || len(s.dt.single) == 0 { + return + } + dt := s.dt.single[:1<>8) == byte(sym) { + fmt.Fprintf(w, "symbol %x has decoder, but no encoder\n", sym) + errs++ + break + } + } + if errs == 0 { + broken-- + } + continue + } + // Unused bits in input + ub := tablelog - enc.nBits + top := enc.val << ub + // decoder looks at top bits. + dec := dt[top] + if uint8(dec.entry) != enc.nBits { + fmt.Fprintf(w, "symbol 0x%x bit size mismatch (enc: %d, dec:%d).\n", sym, enc.nBits, uint8(dec.entry)) + errs++ + } + if uint8(dec.entry>>8) != uint8(sym) { + fmt.Fprintf(w, "symbol 0x%x decoder output mismatch (enc: %d, dec:%d).\n", sym, sym, uint8(dec.entry>>8)) + errs++ + } + if errs > 0 { + fmt.Fprintf(w, "%d errros in base, stopping\n", errs) + continue + } + // Ensure that all combinations are covered. + for i := uint16(0); i < (1 << ub); i++ { + vval := top | i + dec := dt[vval] + if uint8(dec.entry) != enc.nBits { + fmt.Fprintf(w, "symbol 0x%x bit size mismatch (enc: %d, dec:%d).\n", vval, enc.nBits, uint8(dec.entry)) + errs++ + } + if uint8(dec.entry>>8) != uint8(sym) { + fmt.Fprintf(w, "symbol 0x%x decoder output mismatch (enc: %d, dec:%d).\n", vval, sym, uint8(dec.entry>>8)) + errs++ + } + if errs > 20 { + fmt.Fprintf(w, "%d errros, stopping\n", errs) + break + } + } + if errs == 0 { + ok++ + broken-- + } + } + if broken > 0 { + fmt.Fprintf(w, "%d broken, %d ok\n", broken, ok) + } +} diff --git a/vendor/github.com/klauspost/compress/huff0/decompress_amd64.go b/vendor/github.com/klauspost/compress/huff0/decompress_amd64.go new file mode 100644 index 000000000..ba7e8e6b0 --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/decompress_amd64.go @@ -0,0 +1,226 @@ +//go:build amd64 && !appengine && !noasm && gc +// +build amd64,!appengine,!noasm,gc + +// This file contains the specialisation of Decoder.Decompress4X +// and Decoder.Decompress1X that use an asm implementation of thir main loops. +package huff0 + +import ( + "errors" + "fmt" + + "github.com/klauspost/compress/internal/cpuinfo" +) + +// decompress4x_main_loop_x86 is an x86 assembler implementation +// of Decompress4X when tablelog > 8. +// +//go:noescape +func decompress4x_main_loop_amd64(ctx *decompress4xContext) + +// decompress4x_8b_loop_x86 is an x86 assembler implementation +// of Decompress4X when tablelog <= 8 which decodes 4 entries +// per loop. +// +//go:noescape +func decompress4x_8b_main_loop_amd64(ctx *decompress4xContext) + +// fallback8BitSize is the size where using Go version is faster. +const fallback8BitSize = 800 + +type decompress4xContext struct { + pbr *[4]bitReaderShifted + peekBits uint8 + out *byte + dstEvery int + tbl *dEntrySingle + decoded int + limit *byte +} + +// Decompress4X will decompress a 4X encoded stream. +// The length of the supplied input must match the end of a block exactly. +// The *capacity* of the dst slice must match the destination size of +// the uncompressed data exactly. +func (d *Decoder) Decompress4X(dst, src []byte) ([]byte, error) { + if len(d.dt.single) == 0 { + return nil, errors.New("no table loaded") + } + if len(src) < 6+(4*1) { + return nil, errors.New("input too small") + } + + use8BitTables := d.actualTableLog <= 8 + if cap(dst) < fallback8BitSize && use8BitTables { + return d.decompress4X8bit(dst, src) + } + + var br [4]bitReaderShifted + // Decode "jump table" + start := 6 + for i := 0; i < 3; i++ { + length := int(src[i*2]) | (int(src[i*2+1]) << 8) + if start+length >= len(src) { + return nil, errors.New("truncated input (or invalid offset)") + } + err := br[i].init(src[start : start+length]) + if err != nil { + return nil, err + } + start += length + } + err := br[3].init(src[start:]) + if err != nil { + return nil, err + } + + // destination, offset to match first output + dstSize := cap(dst) + dst = dst[:dstSize] + out := dst + dstEvery := (dstSize + 3) / 4 + + const tlSize = 1 << tableLogMax + const tlMask = tlSize - 1 + single := d.dt.single[:tlSize] + + var decoded int + + if len(out) > 4*4 && !(br[0].off < 4 || br[1].off < 4 || br[2].off < 4 || br[3].off < 4) { + ctx := decompress4xContext{ + pbr: &br, + peekBits: uint8((64 - d.actualTableLog) & 63), // see: bitReaderShifted.peekBitsFast() + out: &out[0], + dstEvery: dstEvery, + tbl: &single[0], + limit: &out[dstEvery-4], // Always stop decoding when first buffer gets here to avoid writing OOB on last. + } + if use8BitTables { + decompress4x_8b_main_loop_amd64(&ctx) + } else { + decompress4x_main_loop_amd64(&ctx) + } + + decoded = ctx.decoded + out = out[decoded/4:] + } + + // Decode remaining. + remainBytes := dstEvery - (decoded / 4) + for i := range br { + offset := dstEvery * i + endsAt := offset + remainBytes + if endsAt > len(out) { + endsAt = len(out) + } + br := &br[i] + bitsLeft := br.remaining() + for bitsLeft > 0 { + br.fill() + if offset >= endsAt { + return nil, errors.New("corruption detected: stream overrun 4") + } + + // Read value and increment offset. + val := br.peekBitsFast(d.actualTableLog) + v := single[val&tlMask].entry + nBits := uint8(v) + br.advance(nBits) + bitsLeft -= uint(nBits) + out[offset] = uint8(v >> 8) + offset++ + } + if offset != endsAt { + return nil, fmt.Errorf("corruption detected: short output block %d, end %d != %d", i, offset, endsAt) + } + decoded += offset - dstEvery*i + err = br.close() + if err != nil { + return nil, err + } + } + if dstSize != decoded { + return nil, errors.New("corruption detected: short output block") + } + return dst, nil +} + +// decompress4x_main_loop_x86 is an x86 assembler implementation +// of Decompress1X when tablelog > 8. +// +//go:noescape +func decompress1x_main_loop_amd64(ctx *decompress1xContext) + +// decompress4x_main_loop_x86 is an x86 with BMI2 assembler implementation +// of Decompress1X when tablelog > 8. +// +//go:noescape +func decompress1x_main_loop_bmi2(ctx *decompress1xContext) + +type decompress1xContext struct { + pbr *bitReaderShifted + peekBits uint8 + out *byte + outCap int + tbl *dEntrySingle + decoded int +} + +// Error reported by asm implementations +const error_max_decoded_size_exeeded = -1 + +// Decompress1X will decompress a 1X encoded stream. +// The cap of the output buffer will be the maximum decompressed size. +// The length of the supplied input must match the end of a block exactly. +func (d *Decoder) Decompress1X(dst, src []byte) ([]byte, error) { + if len(d.dt.single) == 0 { + return nil, errors.New("no table loaded") + } + var br bitReaderShifted + err := br.init(src) + if err != nil { + return dst, err + } + maxDecodedSize := cap(dst) + dst = dst[:maxDecodedSize] + + const tlSize = 1 << tableLogMax + const tlMask = tlSize - 1 + + if maxDecodedSize >= 4 { + ctx := decompress1xContext{ + pbr: &br, + out: &dst[0], + outCap: maxDecodedSize, + peekBits: uint8((64 - d.actualTableLog) & 63), // see: bitReaderShifted.peekBitsFast() + tbl: &d.dt.single[0], + } + + if cpuinfo.HasBMI2() { + decompress1x_main_loop_bmi2(&ctx) + } else { + decompress1x_main_loop_amd64(&ctx) + } + if ctx.decoded == error_max_decoded_size_exeeded { + return nil, ErrMaxDecodedSizeExceeded + } + + dst = dst[:ctx.decoded] + } + + // br < 8, so uint8 is fine + bitsLeft := uint8(br.off)*8 + 64 - br.bitsRead + for bitsLeft > 0 { + br.fill() + if len(dst) >= maxDecodedSize { + br.close() + return nil, ErrMaxDecodedSizeExceeded + } + v := d.dt.single[br.peekBitsFast(d.actualTableLog)&tlMask] + nBits := uint8(v.entry) + br.advance(nBits) + bitsLeft -= nBits + dst = append(dst, uint8(v.entry>>8)) + } + return dst, br.close() +} diff --git a/vendor/github.com/klauspost/compress/huff0/decompress_amd64.s b/vendor/github.com/klauspost/compress/huff0/decompress_amd64.s new file mode 100644 index 000000000..c4c7ab2d1 --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/decompress_amd64.s @@ -0,0 +1,830 @@ +// Code generated by command: go run gen.go -out ../decompress_amd64.s -pkg=huff0. DO NOT EDIT. + +//go:build amd64 && !appengine && !noasm && gc + +// func decompress4x_main_loop_amd64(ctx *decompress4xContext) +TEXT ·decompress4x_main_loop_amd64(SB), $0-8 + // Preload values + MOVQ ctx+0(FP), AX + MOVBQZX 8(AX), DI + MOVQ 16(AX), BX + MOVQ 48(AX), SI + MOVQ 24(AX), R8 + MOVQ 32(AX), R9 + MOVQ (AX), R10 + + // Main loop +main_loop: + XORL DX, DX + CMPQ BX, SI + SETGE DL + + // br0.fillFast32() + MOVQ 32(R10), R11 + MOVBQZX 40(R10), R12 + CMPQ R12, $0x20 + JBE skip_fill0 + MOVQ 24(R10), AX + SUBQ $0x20, R12 + SUBQ $0x04, AX + MOVQ (R10), R13 + + // b.value |= uint64(low) << (b.bitsRead & 63) + MOVL (AX)(R13*1), R13 + MOVQ R12, CX + SHLQ CL, R13 + MOVQ AX, 24(R10) + ORQ R13, R11 + + // exhausted += (br0.off < 4) + CMPQ AX, $0x04 + ADCB $+0, DL + +skip_fill0: + // val0 := br0.peekTopBits(peekBits) + MOVQ R11, R13 + MOVQ DI, CX + SHRQ CL, R13 + + // v0 := table[val0&mask] + MOVW (R9)(R13*2), CX + + // br0.advance(uint8(v0.entry) + MOVB CH, AL + SHLQ CL, R11 + ADDB CL, R12 + + // val1 := br0.peekTopBits(peekBits) + MOVQ DI, CX + MOVQ R11, R13 + SHRQ CL, R13 + + // v1 := table[val1&mask] + MOVW (R9)(R13*2), CX + + // br0.advance(uint8(v1.entry)) + MOVB CH, AH + SHLQ CL, R11 + ADDB CL, R12 + + // these two writes get coalesced + // out[id * dstEvery + 0] = uint8(v0.entry >> 8) + // out[id * dstEvery + 1] = uint8(v1.entry >> 8) + MOVW AX, (BX) + + // update the bitreader structure + MOVQ R11, 32(R10) + MOVB R12, 40(R10) + + // br1.fillFast32() + MOVQ 80(R10), R11 + MOVBQZX 88(R10), R12 + CMPQ R12, $0x20 + JBE skip_fill1 + MOVQ 72(R10), AX + SUBQ $0x20, R12 + SUBQ $0x04, AX + MOVQ 48(R10), R13 + + // b.value |= uint64(low) << (b.bitsRead & 63) + MOVL (AX)(R13*1), R13 + MOVQ R12, CX + SHLQ CL, R13 + MOVQ AX, 72(R10) + ORQ R13, R11 + + // exhausted += (br1.off < 4) + CMPQ AX, $0x04 + ADCB $+0, DL + +skip_fill1: + // val0 := br1.peekTopBits(peekBits) + MOVQ R11, R13 + MOVQ DI, CX + SHRQ CL, R13 + + // v0 := table[val0&mask] + MOVW (R9)(R13*2), CX + + // br1.advance(uint8(v0.entry) + MOVB CH, AL + SHLQ CL, R11 + ADDB CL, R12 + + // val1 := br1.peekTopBits(peekBits) + MOVQ DI, CX + MOVQ R11, R13 + SHRQ CL, R13 + + // v1 := table[val1&mask] + MOVW (R9)(R13*2), CX + + // br1.advance(uint8(v1.entry)) + MOVB CH, AH + SHLQ CL, R11 + ADDB CL, R12 + + // these two writes get coalesced + // out[id * dstEvery + 0] = uint8(v0.entry >> 8) + // out[id * dstEvery + 1] = uint8(v1.entry >> 8) + MOVW AX, (BX)(R8*1) + + // update the bitreader structure + MOVQ R11, 80(R10) + MOVB R12, 88(R10) + + // br2.fillFast32() + MOVQ 128(R10), R11 + MOVBQZX 136(R10), R12 + CMPQ R12, $0x20 + JBE skip_fill2 + MOVQ 120(R10), AX + SUBQ $0x20, R12 + SUBQ $0x04, AX + MOVQ 96(R10), R13 + + // b.value |= uint64(low) << (b.bitsRead & 63) + MOVL (AX)(R13*1), R13 + MOVQ R12, CX + SHLQ CL, R13 + MOVQ AX, 120(R10) + ORQ R13, R11 + + // exhausted += (br2.off < 4) + CMPQ AX, $0x04 + ADCB $+0, DL + +skip_fill2: + // val0 := br2.peekTopBits(peekBits) + MOVQ R11, R13 + MOVQ DI, CX + SHRQ CL, R13 + + // v0 := table[val0&mask] + MOVW (R9)(R13*2), CX + + // br2.advance(uint8(v0.entry) + MOVB CH, AL + SHLQ CL, R11 + ADDB CL, R12 + + // val1 := br2.peekTopBits(peekBits) + MOVQ DI, CX + MOVQ R11, R13 + SHRQ CL, R13 + + // v1 := table[val1&mask] + MOVW (R9)(R13*2), CX + + // br2.advance(uint8(v1.entry)) + MOVB CH, AH + SHLQ CL, R11 + ADDB CL, R12 + + // these two writes get coalesced + // out[id * dstEvery + 0] = uint8(v0.entry >> 8) + // out[id * dstEvery + 1] = uint8(v1.entry >> 8) + MOVW AX, (BX)(R8*2) + + // update the bitreader structure + MOVQ R11, 128(R10) + MOVB R12, 136(R10) + + // br3.fillFast32() + MOVQ 176(R10), R11 + MOVBQZX 184(R10), R12 + CMPQ R12, $0x20 + JBE skip_fill3 + MOVQ 168(R10), AX + SUBQ $0x20, R12 + SUBQ $0x04, AX + MOVQ 144(R10), R13 + + // b.value |= uint64(low) << (b.bitsRead & 63) + MOVL (AX)(R13*1), R13 + MOVQ R12, CX + SHLQ CL, R13 + MOVQ AX, 168(R10) + ORQ R13, R11 + + // exhausted += (br3.off < 4) + CMPQ AX, $0x04 + ADCB $+0, DL + +skip_fill3: + // val0 := br3.peekTopBits(peekBits) + MOVQ R11, R13 + MOVQ DI, CX + SHRQ CL, R13 + + // v0 := table[val0&mask] + MOVW (R9)(R13*2), CX + + // br3.advance(uint8(v0.entry) + MOVB CH, AL + SHLQ CL, R11 + ADDB CL, R12 + + // val1 := br3.peekTopBits(peekBits) + MOVQ DI, CX + MOVQ R11, R13 + SHRQ CL, R13 + + // v1 := table[val1&mask] + MOVW (R9)(R13*2), CX + + // br3.advance(uint8(v1.entry)) + MOVB CH, AH + SHLQ CL, R11 + ADDB CL, R12 + + // these two writes get coalesced + // out[id * dstEvery + 0] = uint8(v0.entry >> 8) + // out[id * dstEvery + 1] = uint8(v1.entry >> 8) + LEAQ (R8)(R8*2), CX + MOVW AX, (BX)(CX*1) + + // update the bitreader structure + MOVQ R11, 176(R10) + MOVB R12, 184(R10) + ADDQ $0x02, BX + TESTB DL, DL + JZ main_loop + MOVQ ctx+0(FP), AX + SUBQ 16(AX), BX + SHLQ $0x02, BX + MOVQ BX, 40(AX) + RET + +// func decompress4x_8b_main_loop_amd64(ctx *decompress4xContext) +TEXT ·decompress4x_8b_main_loop_amd64(SB), $0-8 + // Preload values + MOVQ ctx+0(FP), CX + MOVBQZX 8(CX), DI + MOVQ 16(CX), BX + MOVQ 48(CX), SI + MOVQ 24(CX), R8 + MOVQ 32(CX), R9 + MOVQ (CX), R10 + + // Main loop +main_loop: + XORL DX, DX + CMPQ BX, SI + SETGE DL + + // br0.fillFast32() + MOVQ 32(R10), R11 + MOVBQZX 40(R10), R12 + CMPQ R12, $0x20 + JBE skip_fill0 + MOVQ 24(R10), R13 + SUBQ $0x20, R12 + SUBQ $0x04, R13 + MOVQ (R10), R14 + + // b.value |= uint64(low) << (b.bitsRead & 63) + MOVL (R13)(R14*1), R14 + MOVQ R12, CX + SHLQ CL, R14 + MOVQ R13, 24(R10) + ORQ R14, R11 + + // exhausted += (br0.off < 4) + CMPQ R13, $0x04 + ADCB $+0, DL + +skip_fill0: + // val0 := br0.peekTopBits(peekBits) + MOVQ R11, R13 + MOVQ DI, CX + SHRQ CL, R13 + + // v0 := table[val0&mask] + MOVW (R9)(R13*2), CX + + // br0.advance(uint8(v0.entry) + MOVB CH, AL + SHLQ CL, R11 + ADDB CL, R12 + + // val1 := br0.peekTopBits(peekBits) + MOVQ R11, R13 + MOVQ DI, CX + SHRQ CL, R13 + + // v1 := table[val0&mask] + MOVW (R9)(R13*2), CX + + // br0.advance(uint8(v1.entry) + MOVB CH, AH + SHLQ CL, R11 + ADDB CL, R12 + BSWAPL AX + + // val2 := br0.peekTopBits(peekBits) + MOVQ R11, R13 + MOVQ DI, CX + SHRQ CL, R13 + + // v2 := table[val0&mask] + MOVW (R9)(R13*2), CX + + // br0.advance(uint8(v2.entry) + MOVB CH, AH + SHLQ CL, R11 + ADDB CL, R12 + + // val3 := br0.peekTopBits(peekBits) + MOVQ R11, R13 + MOVQ DI, CX + SHRQ CL, R13 + + // v3 := table[val0&mask] + MOVW (R9)(R13*2), CX + + // br0.advance(uint8(v3.entry) + MOVB CH, AL + SHLQ CL, R11 + ADDB CL, R12 + BSWAPL AX + + // these four writes get coalesced + // out[id * dstEvery + 0] = uint8(v0.entry >> 8) + // out[id * dstEvery + 1] = uint8(v1.entry >> 8) + // out[id * dstEvery + 3] = uint8(v2.entry >> 8) + // out[id * dstEvery + 4] = uint8(v3.entry >> 8) + MOVL AX, (BX) + + // update the bitreader structure + MOVQ R11, 32(R10) + MOVB R12, 40(R10) + + // br1.fillFast32() + MOVQ 80(R10), R11 + MOVBQZX 88(R10), R12 + CMPQ R12, $0x20 + JBE skip_fill1 + MOVQ 72(R10), R13 + SUBQ $0x20, R12 + SUBQ $0x04, R13 + MOVQ 48(R10), R14 + + // b.value |= uint64(low) << (b.bitsRead & 63) + MOVL (R13)(R14*1), R14 + MOVQ R12, CX + SHLQ CL, R14 + MOVQ R13, 72(R10) + ORQ R14, R11 + + // exhausted += (br1.off < 4) + CMPQ R13, $0x04 + ADCB $+0, DL + +skip_fill1: + // val0 := br1.peekTopBits(peekBits) + MOVQ R11, R13 + MOVQ DI, CX + SHRQ CL, R13 + + // v0 := table[val0&mask] + MOVW (R9)(R13*2), CX + + // br1.advance(uint8(v0.entry) + MOVB CH, AL + SHLQ CL, R11 + ADDB CL, R12 + + // val1 := br1.peekTopBits(peekBits) + MOVQ R11, R13 + MOVQ DI, CX + SHRQ CL, R13 + + // v1 := table[val0&mask] + MOVW (R9)(R13*2), CX + + // br1.advance(uint8(v1.entry) + MOVB CH, AH + SHLQ CL, R11 + ADDB CL, R12 + BSWAPL AX + + // val2 := br1.peekTopBits(peekBits) + MOVQ R11, R13 + MOVQ DI, CX + SHRQ CL, R13 + + // v2 := table[val0&mask] + MOVW (R9)(R13*2), CX + + // br1.advance(uint8(v2.entry) + MOVB CH, AH + SHLQ CL, R11 + ADDB CL, R12 + + // val3 := br1.peekTopBits(peekBits) + MOVQ R11, R13 + MOVQ DI, CX + SHRQ CL, R13 + + // v3 := table[val0&mask] + MOVW (R9)(R13*2), CX + + // br1.advance(uint8(v3.entry) + MOVB CH, AL + SHLQ CL, R11 + ADDB CL, R12 + BSWAPL AX + + // these four writes get coalesced + // out[id * dstEvery + 0] = uint8(v0.entry >> 8) + // out[id * dstEvery + 1] = uint8(v1.entry >> 8) + // out[id * dstEvery + 3] = uint8(v2.entry >> 8) + // out[id * dstEvery + 4] = uint8(v3.entry >> 8) + MOVL AX, (BX)(R8*1) + + // update the bitreader structure + MOVQ R11, 80(R10) + MOVB R12, 88(R10) + + // br2.fillFast32() + MOVQ 128(R10), R11 + MOVBQZX 136(R10), R12 + CMPQ R12, $0x20 + JBE skip_fill2 + MOVQ 120(R10), R13 + SUBQ $0x20, R12 + SUBQ $0x04, R13 + MOVQ 96(R10), R14 + + // b.value |= uint64(low) << (b.bitsRead & 63) + MOVL (R13)(R14*1), R14 + MOVQ R12, CX + SHLQ CL, R14 + MOVQ R13, 120(R10) + ORQ R14, R11 + + // exhausted += (br2.off < 4) + CMPQ R13, $0x04 + ADCB $+0, DL + +skip_fill2: + // val0 := br2.peekTopBits(peekBits) + MOVQ R11, R13 + MOVQ DI, CX + SHRQ CL, R13 + + // v0 := table[val0&mask] + MOVW (R9)(R13*2), CX + + // br2.advance(uint8(v0.entry) + MOVB CH, AL + SHLQ CL, R11 + ADDB CL, R12 + + // val1 := br2.peekTopBits(peekBits) + MOVQ R11, R13 + MOVQ DI, CX + SHRQ CL, R13 + + // v1 := table[val0&mask] + MOVW (R9)(R13*2), CX + + // br2.advance(uint8(v1.entry) + MOVB CH, AH + SHLQ CL, R11 + ADDB CL, R12 + BSWAPL AX + + // val2 := br2.peekTopBits(peekBits) + MOVQ R11, R13 + MOVQ DI, CX + SHRQ CL, R13 + + // v2 := table[val0&mask] + MOVW (R9)(R13*2), CX + + // br2.advance(uint8(v2.entry) + MOVB CH, AH + SHLQ CL, R11 + ADDB CL, R12 + + // val3 := br2.peekTopBits(peekBits) + MOVQ R11, R13 + MOVQ DI, CX + SHRQ CL, R13 + + // v3 := table[val0&mask] + MOVW (R9)(R13*2), CX + + // br2.advance(uint8(v3.entry) + MOVB CH, AL + SHLQ CL, R11 + ADDB CL, R12 + BSWAPL AX + + // these four writes get coalesced + // out[id * dstEvery + 0] = uint8(v0.entry >> 8) + // out[id * dstEvery + 1] = uint8(v1.entry >> 8) + // out[id * dstEvery + 3] = uint8(v2.entry >> 8) + // out[id * dstEvery + 4] = uint8(v3.entry >> 8) + MOVL AX, (BX)(R8*2) + + // update the bitreader structure + MOVQ R11, 128(R10) + MOVB R12, 136(R10) + + // br3.fillFast32() + MOVQ 176(R10), R11 + MOVBQZX 184(R10), R12 + CMPQ R12, $0x20 + JBE skip_fill3 + MOVQ 168(R10), R13 + SUBQ $0x20, R12 + SUBQ $0x04, R13 + MOVQ 144(R10), R14 + + // b.value |= uint64(low) << (b.bitsRead & 63) + MOVL (R13)(R14*1), R14 + MOVQ R12, CX + SHLQ CL, R14 + MOVQ R13, 168(R10) + ORQ R14, R11 + + // exhausted += (br3.off < 4) + CMPQ R13, $0x04 + ADCB $+0, DL + +skip_fill3: + // val0 := br3.peekTopBits(peekBits) + MOVQ R11, R13 + MOVQ DI, CX + SHRQ CL, R13 + + // v0 := table[val0&mask] + MOVW (R9)(R13*2), CX + + // br3.advance(uint8(v0.entry) + MOVB CH, AL + SHLQ CL, R11 + ADDB CL, R12 + + // val1 := br3.peekTopBits(peekBits) + MOVQ R11, R13 + MOVQ DI, CX + SHRQ CL, R13 + + // v1 := table[val0&mask] + MOVW (R9)(R13*2), CX + + // br3.advance(uint8(v1.entry) + MOVB CH, AH + SHLQ CL, R11 + ADDB CL, R12 + BSWAPL AX + + // val2 := br3.peekTopBits(peekBits) + MOVQ R11, R13 + MOVQ DI, CX + SHRQ CL, R13 + + // v2 := table[val0&mask] + MOVW (R9)(R13*2), CX + + // br3.advance(uint8(v2.entry) + MOVB CH, AH + SHLQ CL, R11 + ADDB CL, R12 + + // val3 := br3.peekTopBits(peekBits) + MOVQ R11, R13 + MOVQ DI, CX + SHRQ CL, R13 + + // v3 := table[val0&mask] + MOVW (R9)(R13*2), CX + + // br3.advance(uint8(v3.entry) + MOVB CH, AL + SHLQ CL, R11 + ADDB CL, R12 + BSWAPL AX + + // these four writes get coalesced + // out[id * dstEvery + 0] = uint8(v0.entry >> 8) + // out[id * dstEvery + 1] = uint8(v1.entry >> 8) + // out[id * dstEvery + 3] = uint8(v2.entry >> 8) + // out[id * dstEvery + 4] = uint8(v3.entry >> 8) + LEAQ (R8)(R8*2), CX + MOVL AX, (BX)(CX*1) + + // update the bitreader structure + MOVQ R11, 176(R10) + MOVB R12, 184(R10) + ADDQ $0x04, BX + TESTB DL, DL + JZ main_loop + MOVQ ctx+0(FP), AX + SUBQ 16(AX), BX + SHLQ $0x02, BX + MOVQ BX, 40(AX) + RET + +// func decompress1x_main_loop_amd64(ctx *decompress1xContext) +TEXT ·decompress1x_main_loop_amd64(SB), $0-8 + MOVQ ctx+0(FP), CX + MOVQ 16(CX), DX + MOVQ 24(CX), BX + CMPQ BX, $0x04 + JB error_max_decoded_size_exceeded + LEAQ (DX)(BX*1), BX + MOVQ (CX), SI + MOVQ (SI), R8 + MOVQ 24(SI), R9 + MOVQ 32(SI), R10 + MOVBQZX 40(SI), R11 + MOVQ 32(CX), SI + MOVBQZX 8(CX), DI + JMP loop_condition + +main_loop: + // Check if we have room for 4 bytes in the output buffer + LEAQ 4(DX), CX + CMPQ CX, BX + JGE error_max_decoded_size_exceeded + + // Decode 4 values + CMPQ R11, $0x20 + JL bitReader_fillFast_1_end + SUBQ $0x20, R11 + SUBQ $0x04, R9 + MOVL (R8)(R9*1), R12 + MOVQ R11, CX + SHLQ CL, R12 + ORQ R12, R10 + +bitReader_fillFast_1_end: + MOVQ DI, CX + MOVQ R10, R12 + SHRQ CL, R12 + MOVW (SI)(R12*2), CX + MOVB CH, AL + MOVBQZX CL, CX + ADDQ CX, R11 + SHLQ CL, R10 + MOVQ DI, CX + MOVQ R10, R12 + SHRQ CL, R12 + MOVW (SI)(R12*2), CX + MOVB CH, AH + MOVBQZX CL, CX + ADDQ CX, R11 + SHLQ CL, R10 + BSWAPL AX + CMPQ R11, $0x20 + JL bitReader_fillFast_2_end + SUBQ $0x20, R11 + SUBQ $0x04, R9 + MOVL (R8)(R9*1), R12 + MOVQ R11, CX + SHLQ CL, R12 + ORQ R12, R10 + +bitReader_fillFast_2_end: + MOVQ DI, CX + MOVQ R10, R12 + SHRQ CL, R12 + MOVW (SI)(R12*2), CX + MOVB CH, AH + MOVBQZX CL, CX + ADDQ CX, R11 + SHLQ CL, R10 + MOVQ DI, CX + MOVQ R10, R12 + SHRQ CL, R12 + MOVW (SI)(R12*2), CX + MOVB CH, AL + MOVBQZX CL, CX + ADDQ CX, R11 + SHLQ CL, R10 + BSWAPL AX + + // Store the decoded values + MOVL AX, (DX) + ADDQ $0x04, DX + +loop_condition: + CMPQ R9, $0x08 + JGE main_loop + + // Update ctx structure + MOVQ ctx+0(FP), AX + SUBQ 16(AX), DX + MOVQ DX, 40(AX) + MOVQ (AX), AX + MOVQ R9, 24(AX) + MOVQ R10, 32(AX) + MOVB R11, 40(AX) + RET + + // Report error +error_max_decoded_size_exceeded: + MOVQ ctx+0(FP), AX + MOVQ $-1, CX + MOVQ CX, 40(AX) + RET + +// func decompress1x_main_loop_bmi2(ctx *decompress1xContext) +// Requires: BMI2 +TEXT ·decompress1x_main_loop_bmi2(SB), $0-8 + MOVQ ctx+0(FP), CX + MOVQ 16(CX), DX + MOVQ 24(CX), BX + CMPQ BX, $0x04 + JB error_max_decoded_size_exceeded + LEAQ (DX)(BX*1), BX + MOVQ (CX), SI + MOVQ (SI), R8 + MOVQ 24(SI), R9 + MOVQ 32(SI), R10 + MOVBQZX 40(SI), R11 + MOVQ 32(CX), SI + MOVBQZX 8(CX), DI + JMP loop_condition + +main_loop: + // Check if we have room for 4 bytes in the output buffer + LEAQ 4(DX), CX + CMPQ CX, BX + JGE error_max_decoded_size_exceeded + + // Decode 4 values + CMPQ R11, $0x20 + JL bitReader_fillFast_1_end + SUBQ $0x20, R11 + SUBQ $0x04, R9 + MOVL (R8)(R9*1), CX + SHLXQ R11, CX, CX + ORQ CX, R10 + +bitReader_fillFast_1_end: + SHRXQ DI, R10, CX + MOVW (SI)(CX*2), CX + MOVB CH, AL + MOVBQZX CL, CX + ADDQ CX, R11 + SHLXQ CX, R10, R10 + SHRXQ DI, R10, CX + MOVW (SI)(CX*2), CX + MOVB CH, AH + MOVBQZX CL, CX + ADDQ CX, R11 + SHLXQ CX, R10, R10 + BSWAPL AX + CMPQ R11, $0x20 + JL bitReader_fillFast_2_end + SUBQ $0x20, R11 + SUBQ $0x04, R9 + MOVL (R8)(R9*1), CX + SHLXQ R11, CX, CX + ORQ CX, R10 + +bitReader_fillFast_2_end: + SHRXQ DI, R10, CX + MOVW (SI)(CX*2), CX + MOVB CH, AH + MOVBQZX CL, CX + ADDQ CX, R11 + SHLXQ CX, R10, R10 + SHRXQ DI, R10, CX + MOVW (SI)(CX*2), CX + MOVB CH, AL + MOVBQZX CL, CX + ADDQ CX, R11 + SHLXQ CX, R10, R10 + BSWAPL AX + + // Store the decoded values + MOVL AX, (DX) + ADDQ $0x04, DX + +loop_condition: + CMPQ R9, $0x08 + JGE main_loop + + // Update ctx structure + MOVQ ctx+0(FP), AX + SUBQ 16(AX), DX + MOVQ DX, 40(AX) + MOVQ (AX), AX + MOVQ R9, 24(AX) + MOVQ R10, 32(AX) + MOVB R11, 40(AX) + RET + + // Report error +error_max_decoded_size_exceeded: + MOVQ ctx+0(FP), AX + MOVQ $-1, CX + MOVQ CX, 40(AX) + RET diff --git a/vendor/github.com/klauspost/compress/huff0/decompress_generic.go b/vendor/github.com/klauspost/compress/huff0/decompress_generic.go new file mode 100644 index 000000000..908c17de6 --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/decompress_generic.go @@ -0,0 +1,299 @@ +//go:build !amd64 || appengine || !gc || noasm +// +build !amd64 appengine !gc noasm + +// This file contains a generic implementation of Decoder.Decompress4X. +package huff0 + +import ( + "errors" + "fmt" +) + +// Decompress4X will decompress a 4X encoded stream. +// The length of the supplied input must match the end of a block exactly. +// The *capacity* of the dst slice must match the destination size of +// the uncompressed data exactly. +func (d *Decoder) Decompress4X(dst, src []byte) ([]byte, error) { + if len(d.dt.single) == 0 { + return nil, errors.New("no table loaded") + } + if len(src) < 6+(4*1) { + return nil, errors.New("input too small") + } + if use8BitTables && d.actualTableLog <= 8 { + return d.decompress4X8bit(dst, src) + } + + var br [4]bitReaderShifted + // Decode "jump table" + start := 6 + for i := 0; i < 3; i++ { + length := int(src[i*2]) | (int(src[i*2+1]) << 8) + if start+length >= len(src) { + return nil, errors.New("truncated input (or invalid offset)") + } + err := br[i].init(src[start : start+length]) + if err != nil { + return nil, err + } + start += length + } + err := br[3].init(src[start:]) + if err != nil { + return nil, err + } + + // destination, offset to match first output + dstSize := cap(dst) + dst = dst[:dstSize] + out := dst + dstEvery := (dstSize + 3) / 4 + + const tlSize = 1 << tableLogMax + const tlMask = tlSize - 1 + single := d.dt.single[:tlSize] + + // Use temp table to avoid bound checks/append penalty. + buf := d.buffer() + var off uint8 + var decoded int + + // Decode 2 values from each decoder/loop. + const bufoff = 256 + for { + if br[0].off < 4 || br[1].off < 4 || br[2].off < 4 || br[3].off < 4 { + break + } + + { + const stream = 0 + const stream2 = 1 + br[stream].fillFast() + br[stream2].fillFast() + + val := br[stream].peekBitsFast(d.actualTableLog) + val2 := br[stream2].peekBitsFast(d.actualTableLog) + v := single[val&tlMask] + v2 := single[val2&tlMask] + br[stream].advance(uint8(v.entry)) + br[stream2].advance(uint8(v2.entry)) + buf[stream][off] = uint8(v.entry >> 8) + buf[stream2][off] = uint8(v2.entry >> 8) + + val = br[stream].peekBitsFast(d.actualTableLog) + val2 = br[stream2].peekBitsFast(d.actualTableLog) + v = single[val&tlMask] + v2 = single[val2&tlMask] + br[stream].advance(uint8(v.entry)) + br[stream2].advance(uint8(v2.entry)) + buf[stream][off+1] = uint8(v.entry >> 8) + buf[stream2][off+1] = uint8(v2.entry >> 8) + } + + { + const stream = 2 + const stream2 = 3 + br[stream].fillFast() + br[stream2].fillFast() + + val := br[stream].peekBitsFast(d.actualTableLog) + val2 := br[stream2].peekBitsFast(d.actualTableLog) + v := single[val&tlMask] + v2 := single[val2&tlMask] + br[stream].advance(uint8(v.entry)) + br[stream2].advance(uint8(v2.entry)) + buf[stream][off] = uint8(v.entry >> 8) + buf[stream2][off] = uint8(v2.entry >> 8) + + val = br[stream].peekBitsFast(d.actualTableLog) + val2 = br[stream2].peekBitsFast(d.actualTableLog) + v = single[val&tlMask] + v2 = single[val2&tlMask] + br[stream].advance(uint8(v.entry)) + br[stream2].advance(uint8(v2.entry)) + buf[stream][off+1] = uint8(v.entry >> 8) + buf[stream2][off+1] = uint8(v2.entry >> 8) + } + + off += 2 + + if off == 0 { + if bufoff > dstEvery { + d.bufs.Put(buf) + return nil, errors.New("corruption detected: stream overrun 1") + } + // There must at least be 3 buffers left. + if len(out)-bufoff < dstEvery*3 { + d.bufs.Put(buf) + return nil, errors.New("corruption detected: stream overrun 2") + } + //copy(out, buf[0][:]) + //copy(out[dstEvery:], buf[1][:]) + //copy(out[dstEvery*2:], buf[2][:]) + //copy(out[dstEvery*3:], buf[3][:]) + *(*[bufoff]byte)(out) = buf[0] + *(*[bufoff]byte)(out[dstEvery:]) = buf[1] + *(*[bufoff]byte)(out[dstEvery*2:]) = buf[2] + *(*[bufoff]byte)(out[dstEvery*3:]) = buf[3] + out = out[bufoff:] + decoded += bufoff * 4 + } + } + if off > 0 { + ioff := int(off) + if len(out) < dstEvery*3+ioff { + d.bufs.Put(buf) + return nil, errors.New("corruption detected: stream overrun 3") + } + copy(out, buf[0][:off]) + copy(out[dstEvery:], buf[1][:off]) + copy(out[dstEvery*2:], buf[2][:off]) + copy(out[dstEvery*3:], buf[3][:off]) + decoded += int(off) * 4 + out = out[off:] + } + + // Decode remaining. + remainBytes := dstEvery - (decoded / 4) + for i := range br { + offset := dstEvery * i + endsAt := offset + remainBytes + if endsAt > len(out) { + endsAt = len(out) + } + br := &br[i] + bitsLeft := br.remaining() + for bitsLeft > 0 { + br.fill() + if offset >= endsAt { + d.bufs.Put(buf) + return nil, errors.New("corruption detected: stream overrun 4") + } + + // Read value and increment offset. + val := br.peekBitsFast(d.actualTableLog) + v := single[val&tlMask].entry + nBits := uint8(v) + br.advance(nBits) + bitsLeft -= uint(nBits) + out[offset] = uint8(v >> 8) + offset++ + } + if offset != endsAt { + d.bufs.Put(buf) + return nil, fmt.Errorf("corruption detected: short output block %d, end %d != %d", i, offset, endsAt) + } + decoded += offset - dstEvery*i + err = br.close() + if err != nil { + return nil, err + } + } + d.bufs.Put(buf) + if dstSize != decoded { + return nil, errors.New("corruption detected: short output block") + } + return dst, nil +} + +// Decompress1X will decompress a 1X encoded stream. +// The cap of the output buffer will be the maximum decompressed size. +// The length of the supplied input must match the end of a block exactly. +func (d *Decoder) Decompress1X(dst, src []byte) ([]byte, error) { + if len(d.dt.single) == 0 { + return nil, errors.New("no table loaded") + } + if use8BitTables && d.actualTableLog <= 8 { + return d.decompress1X8Bit(dst, src) + } + var br bitReaderShifted + err := br.init(src) + if err != nil { + return dst, err + } + maxDecodedSize := cap(dst) + dst = dst[:0] + + // Avoid bounds check by always having full sized table. + const tlSize = 1 << tableLogMax + const tlMask = tlSize - 1 + dt := d.dt.single[:tlSize] + + // Use temp table to avoid bound checks/append penalty. + bufs := d.buffer() + buf := &bufs[0] + var off uint8 + + for br.off >= 8 { + br.fillFast() + v := dt[br.peekBitsFast(d.actualTableLog)&tlMask] + br.advance(uint8(v.entry)) + buf[off+0] = uint8(v.entry >> 8) + + v = dt[br.peekBitsFast(d.actualTableLog)&tlMask] + br.advance(uint8(v.entry)) + buf[off+1] = uint8(v.entry >> 8) + + // Refill + br.fillFast() + + v = dt[br.peekBitsFast(d.actualTableLog)&tlMask] + br.advance(uint8(v.entry)) + buf[off+2] = uint8(v.entry >> 8) + + v = dt[br.peekBitsFast(d.actualTableLog)&tlMask] + br.advance(uint8(v.entry)) + buf[off+3] = uint8(v.entry >> 8) + + off += 4 + if off == 0 { + if len(dst)+256 > maxDecodedSize { + br.close() + d.bufs.Put(bufs) + return nil, ErrMaxDecodedSizeExceeded + } + dst = append(dst, buf[:]...) + } + } + + if len(dst)+int(off) > maxDecodedSize { + d.bufs.Put(bufs) + br.close() + return nil, ErrMaxDecodedSizeExceeded + } + dst = append(dst, buf[:off]...) + + // br < 8, so uint8 is fine + bitsLeft := uint8(br.off)*8 + 64 - br.bitsRead + for bitsLeft > 0 { + br.fill() + if false && br.bitsRead >= 32 { + if br.off >= 4 { + v := br.in[br.off-4:] + v = v[:4] + low := (uint32(v[0])) | (uint32(v[1]) << 8) | (uint32(v[2]) << 16) | (uint32(v[3]) << 24) + br.value = (br.value << 32) | uint64(low) + br.bitsRead -= 32 + br.off -= 4 + } else { + for br.off > 0 { + br.value = (br.value << 8) | uint64(br.in[br.off-1]) + br.bitsRead -= 8 + br.off-- + } + } + } + if len(dst) >= maxDecodedSize { + d.bufs.Put(bufs) + br.close() + return nil, ErrMaxDecodedSizeExceeded + } + v := d.dt.single[br.peekBitsFast(d.actualTableLog)&tlMask] + nBits := uint8(v.entry) + br.advance(nBits) + bitsLeft -= nBits + dst = append(dst, uint8(v.entry>>8)) + } + d.bufs.Put(bufs) + return dst, br.close() +} diff --git a/vendor/github.com/klauspost/compress/huff0/huff0.go b/vendor/github.com/klauspost/compress/huff0/huff0.go new file mode 100644 index 000000000..77ecd68e0 --- /dev/null +++ b/vendor/github.com/klauspost/compress/huff0/huff0.go @@ -0,0 +1,337 @@ +// Package huff0 provides fast huffman encoding as used in zstd. +// +// See README.md at https://github.com/klauspost/compress/tree/master/huff0 for details. +package huff0 + +import ( + "errors" + "fmt" + "math" + "math/bits" + "sync" + + "github.com/klauspost/compress/fse" +) + +const ( + maxSymbolValue = 255 + + // zstandard limits tablelog to 11, see: + // https://github.com/facebook/zstd/blob/dev/doc/zstd_compression_format.md#huffman-tree-description + tableLogMax = 11 + tableLogDefault = 11 + minTablelog = 5 + huffNodesLen = 512 + + // BlockSizeMax is maximum input size for a single block uncompressed. + BlockSizeMax = 1<<18 - 1 +) + +var ( + // ErrIncompressible is returned when input is judged to be too hard to compress. + ErrIncompressible = errors.New("input is not compressible") + + // ErrUseRLE is returned from the compressor when the input is a single byte value repeated. + ErrUseRLE = errors.New("input is single value repeated") + + // ErrTooBig is return if input is too large for a single block. + ErrTooBig = errors.New("input too big") + + // ErrMaxDecodedSizeExceeded is return if input is too large for a single block. + ErrMaxDecodedSizeExceeded = errors.New("maximum output size exceeded") +) + +type ReusePolicy uint8 + +const ( + // ReusePolicyAllow will allow reuse if it produces smaller output. + ReusePolicyAllow ReusePolicy = iota + + // ReusePolicyPrefer will re-use aggressively if possible. + // This will not check if a new table will produce smaller output, + // except if the current table is impossible to use or + // compressed output is bigger than input. + ReusePolicyPrefer + + // ReusePolicyNone will disable re-use of tables. + // This is slightly faster than ReusePolicyAllow but may produce larger output. + ReusePolicyNone + + // ReusePolicyMust must allow reuse and produce smaller output. + ReusePolicyMust +) + +type Scratch struct { + count [maxSymbolValue + 1]uint32 + + // Per block parameters. + // These can be used to override compression parameters of the block. + // Do not touch, unless you know what you are doing. + + // Out is output buffer. + // If the scratch is re-used before the caller is done processing the output, + // set this field to nil. + // Otherwise the output buffer will be re-used for next Compression/Decompression step + // and allocation will be avoided. + Out []byte + + // OutTable will contain the table data only, if a new table has been generated. + // Slice of the returned data. + OutTable []byte + + // OutData will contain the compressed data. + // Slice of the returned data. + OutData []byte + + // MaxDecodedSize will set the maximum allowed output size. + // This value will automatically be set to BlockSizeMax if not set. + // Decoders will return ErrMaxDecodedSizeExceeded is this limit is exceeded. + MaxDecodedSize int + + srcLen int + + // MaxSymbolValue will override the maximum symbol value of the next block. + MaxSymbolValue uint8 + + // TableLog will attempt to override the tablelog for the next block. + // Must be <= 11 and >= 5. + TableLog uint8 + + // Reuse will specify the reuse policy + Reuse ReusePolicy + + // WantLogLess allows to specify a log 2 reduction that should at least be achieved, + // otherwise the block will be returned as incompressible. + // The reduction should then at least be (input size >> WantLogLess) + // If WantLogLess == 0 any improvement will do. + WantLogLess uint8 + + symbolLen uint16 // Length of active part of the symbol table. + maxCount int // count of the most probable symbol + clearCount bool // clear count + actualTableLog uint8 // Selected tablelog. + prevTableLog uint8 // Tablelog for previous table + prevTable cTable // Table used for previous compression. + cTable cTable // compression table + dt dTable // decompression table + nodes []nodeElt + tmpOut [4][]byte + fse *fse.Scratch + decPool sync.Pool // *[4][256]byte buffers. + huffWeight [maxSymbolValue + 1]byte +} + +// TransferCTable will transfer the previously used compression table. +func (s *Scratch) TransferCTable(src *Scratch) { + if cap(s.prevTable) < len(src.prevTable) { + s.prevTable = make(cTable, 0, maxSymbolValue+1) + } + s.prevTable = s.prevTable[:len(src.prevTable)] + copy(s.prevTable, src.prevTable) + s.prevTableLog = src.prevTableLog +} + +func (s *Scratch) prepare(in []byte) (*Scratch, error) { + if len(in) > BlockSizeMax { + return nil, ErrTooBig + } + if s == nil { + s = &Scratch{} + } + if s.MaxSymbolValue == 0 { + s.MaxSymbolValue = maxSymbolValue + } + if s.TableLog == 0 { + s.TableLog = tableLogDefault + } + if s.TableLog > tableLogMax || s.TableLog < minTablelog { + return nil, fmt.Errorf(" invalid tableLog %d (%d -> %d)", s.TableLog, minTablelog, tableLogMax) + } + if s.MaxDecodedSize <= 0 || s.MaxDecodedSize > BlockSizeMax { + s.MaxDecodedSize = BlockSizeMax + } + if s.clearCount && s.maxCount == 0 { + for i := range s.count { + s.count[i] = 0 + } + s.clearCount = false + } + if cap(s.Out) == 0 { + s.Out = make([]byte, 0, len(in)) + } + s.Out = s.Out[:0] + + s.OutTable = nil + s.OutData = nil + if cap(s.nodes) < huffNodesLen+1 { + s.nodes = make([]nodeElt, 0, huffNodesLen+1) + } + s.nodes = s.nodes[:0] + if s.fse == nil { + s.fse = &fse.Scratch{} + } + s.srcLen = len(in) + + return s, nil +} + +type cTable []cTableEntry + +func (c cTable) write(s *Scratch) error { + var ( + // precomputed conversion table + bitsToWeight [tableLogMax + 1]byte + huffLog = s.actualTableLog + // last weight is not saved. + maxSymbolValue = uint8(s.symbolLen - 1) + huffWeight = s.huffWeight[:256] + ) + const ( + maxFSETableLog = 6 + ) + // convert to weight + bitsToWeight[0] = 0 + for n := uint8(1); n < huffLog+1; n++ { + bitsToWeight[n] = huffLog + 1 - n + } + + // Acquire histogram for FSE. + hist := s.fse.Histogram() + hist = hist[:256] + for i := range hist[:16] { + hist[i] = 0 + } + for n := uint8(0); n < maxSymbolValue; n++ { + v := bitsToWeight[c[n].nBits] & 15 + huffWeight[n] = v + hist[v]++ + } + + // FSE compress if feasible. + if maxSymbolValue >= 2 { + huffMaxCnt := uint32(0) + huffMax := uint8(0) + for i, v := range hist[:16] { + if v == 0 { + continue + } + huffMax = byte(i) + if v > huffMaxCnt { + huffMaxCnt = v + } + } + s.fse.HistogramFinished(huffMax, int(huffMaxCnt)) + s.fse.TableLog = maxFSETableLog + b, err := fse.Compress(huffWeight[:maxSymbolValue], s.fse) + if err == nil && len(b) < int(s.symbolLen>>1) { + s.Out = append(s.Out, uint8(len(b))) + s.Out = append(s.Out, b...) + return nil + } + // Unable to compress (RLE/uncompressible) + } + // write raw values as 4-bits (max : 15) + if maxSymbolValue > (256 - 128) { + // should not happen : likely means source cannot be compressed + return ErrIncompressible + } + op := s.Out + // special case, pack weights 4 bits/weight. + op = append(op, 128|(maxSymbolValue-1)) + // be sure it doesn't cause msan issue in final combination + huffWeight[maxSymbolValue] = 0 + for n := uint16(0); n < uint16(maxSymbolValue); n += 2 { + op = append(op, (huffWeight[n]<<4)|huffWeight[n+1]) + } + s.Out = op + return nil +} + +func (c cTable) estTableSize(s *Scratch) (sz int, err error) { + var ( + // precomputed conversion table + bitsToWeight [tableLogMax + 1]byte + huffLog = s.actualTableLog + // last weight is not saved. + maxSymbolValue = uint8(s.symbolLen - 1) + huffWeight = s.huffWeight[:256] + ) + const ( + maxFSETableLog = 6 + ) + // convert to weight + bitsToWeight[0] = 0 + for n := uint8(1); n < huffLog+1; n++ { + bitsToWeight[n] = huffLog + 1 - n + } + + // Acquire histogram for FSE. + hist := s.fse.Histogram() + hist = hist[:256] + for i := range hist[:16] { + hist[i] = 0 + } + for n := uint8(0); n < maxSymbolValue; n++ { + v := bitsToWeight[c[n].nBits] & 15 + huffWeight[n] = v + hist[v]++ + } + + // FSE compress if feasible. + if maxSymbolValue >= 2 { + huffMaxCnt := uint32(0) + huffMax := uint8(0) + for i, v := range hist[:16] { + if v == 0 { + continue + } + huffMax = byte(i) + if v > huffMaxCnt { + huffMaxCnt = v + } + } + s.fse.HistogramFinished(huffMax, int(huffMaxCnt)) + s.fse.TableLog = maxFSETableLog + b, err := fse.Compress(huffWeight[:maxSymbolValue], s.fse) + if err == nil && len(b) < int(s.symbolLen>>1) { + sz += 1 + len(b) + return sz, nil + } + // Unable to compress (RLE/uncompressible) + } + // write raw values as 4-bits (max : 15) + if maxSymbolValue > (256 - 128) { + // should not happen : likely means source cannot be compressed + return 0, ErrIncompressible + } + // special case, pack weights 4 bits/weight. + sz += 1 + int(maxSymbolValue/2) + return sz, nil +} + +// estimateSize returns the estimated size in bytes of the input represented in the +// histogram supplied. +func (c cTable) estimateSize(hist []uint32) int { + nbBits := uint32(7) + for i, v := range c[:len(hist)] { + nbBits += uint32(v.nBits) * hist[i] + } + return int(nbBits >> 3) +} + +// minSize returns the minimum possible size considering the shannon limit. +func (s *Scratch) minSize(total int) int { + nbBits := float64(7) + fTotal := float64(total) + for _, v := range s.count[:s.symbolLen] { + n := float64(v) + if n > 0 { + nbBits += math.Log2(fTotal/n) * n + } + } + return int(nbBits) >> 3 +} + +func highBit32(val uint32) (n uint32) { + return uint32(bits.Len32(val) - 1) +} diff --git a/vendor/github.com/klauspost/compress/internal/cpuinfo/cpuinfo.go b/vendor/github.com/klauspost/compress/internal/cpuinfo/cpuinfo.go new file mode 100644 index 000000000..3954c5121 --- /dev/null +++ b/vendor/github.com/klauspost/compress/internal/cpuinfo/cpuinfo.go @@ -0,0 +1,34 @@ +// Package cpuinfo gives runtime info about the current CPU. +// +// This is a very limited module meant for use internally +// in this project. For more versatile solution check +// https://github.com/klauspost/cpuid. +package cpuinfo + +// HasBMI1 checks whether an x86 CPU supports the BMI1 extension. +func HasBMI1() bool { + return hasBMI1 +} + +// HasBMI2 checks whether an x86 CPU supports the BMI2 extension. +func HasBMI2() bool { + return hasBMI2 +} + +// DisableBMI2 will disable BMI2, for testing purposes. +// Call returned function to restore previous state. +func DisableBMI2() func() { + old := hasBMI2 + hasBMI2 = false + return func() { + hasBMI2 = old + } +} + +// HasBMI checks whether an x86 CPU supports both BMI1 and BMI2 extensions. +func HasBMI() bool { + return HasBMI1() && HasBMI2() +} + +var hasBMI1 bool +var hasBMI2 bool diff --git a/vendor/github.com/klauspost/compress/internal/cpuinfo/cpuinfo_amd64.go b/vendor/github.com/klauspost/compress/internal/cpuinfo/cpuinfo_amd64.go new file mode 100644 index 000000000..e802579c4 --- /dev/null +++ b/vendor/github.com/klauspost/compress/internal/cpuinfo/cpuinfo_amd64.go @@ -0,0 +1,11 @@ +//go:build amd64 && !appengine && !noasm && gc +// +build amd64,!appengine,!noasm,gc + +package cpuinfo + +// go:noescape +func x86extensions() (bmi1, bmi2 bool) + +func init() { + hasBMI1, hasBMI2 = x86extensions() +} diff --git a/vendor/github.com/klauspost/compress/internal/cpuinfo/cpuinfo_amd64.s b/vendor/github.com/klauspost/compress/internal/cpuinfo/cpuinfo_amd64.s new file mode 100644 index 000000000..4465fbe9e --- /dev/null +++ b/vendor/github.com/klauspost/compress/internal/cpuinfo/cpuinfo_amd64.s @@ -0,0 +1,36 @@ +// +build !appengine +// +build gc +// +build !noasm + +#include "textflag.h" +#include "funcdata.h" +#include "go_asm.h" + +TEXT ·x86extensions(SB), NOSPLIT, $0 + // 1. determine max EAX value + XORQ AX, AX + CPUID + + CMPQ AX, $7 + JB unsupported + + // 2. EAX = 7, ECX = 0 --- see Table 3-8 "Information Returned by CPUID Instruction" + MOVQ $7, AX + MOVQ $0, CX + CPUID + + BTQ $3, BX // bit 3 = BMI1 + SETCS AL + + BTQ $8, BX // bit 8 = BMI2 + SETCS AH + + MOVB AL, bmi1+0(FP) + MOVB AH, bmi2+1(FP) + RET + +unsupported: + XORQ AX, AX + MOVB AL, bmi1+0(FP) + MOVB AL, bmi2+1(FP) + RET diff --git a/vendor/github.com/klauspost/compress/internal/snapref/LICENSE b/vendor/github.com/klauspost/compress/internal/snapref/LICENSE new file mode 100644 index 000000000..6050c10f4 --- /dev/null +++ b/vendor/github.com/klauspost/compress/internal/snapref/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2011 The Snappy-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. diff --git a/vendor/github.com/klauspost/compress/internal/snapref/decode.go b/vendor/github.com/klauspost/compress/internal/snapref/decode.go new file mode 100644 index 000000000..40796a49d --- /dev/null +++ b/vendor/github.com/klauspost/compress/internal/snapref/decode.go @@ -0,0 +1,264 @@ +// Copyright 2011 The Snappy-Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package snapref + +import ( + "encoding/binary" + "errors" + "io" +) + +var ( + // ErrCorrupt reports that the input is invalid. + ErrCorrupt = errors.New("snappy: corrupt input") + // ErrTooLarge reports that the uncompressed length is too large. + ErrTooLarge = errors.New("snappy: decoded block is too large") + // ErrUnsupported reports that the input isn't supported. + ErrUnsupported = errors.New("snappy: unsupported input") + + errUnsupportedLiteralLength = errors.New("snappy: unsupported literal length") +) + +// DecodedLen returns the length of the decoded block. +func DecodedLen(src []byte) (int, error) { + v, _, err := decodedLen(src) + return v, err +} + +// decodedLen returns the length of the decoded block and the number of bytes +// that the length header occupied. +func decodedLen(src []byte) (blockLen, headerLen int, err error) { + v, n := binary.Uvarint(src) + if n <= 0 || v > 0xffffffff { + return 0, 0, ErrCorrupt + } + + const wordSize = 32 << (^uint(0) >> 32 & 1) + if wordSize == 32 && v > 0x7fffffff { + return 0, 0, ErrTooLarge + } + return int(v), n, nil +} + +const ( + decodeErrCodeCorrupt = 1 + decodeErrCodeUnsupportedLiteralLength = 2 +) + +// Decode returns the decoded form of src. The returned slice may be a sub- +// slice of dst if dst was large enough to hold the entire decoded block. +// Otherwise, a newly allocated slice will be returned. +// +// The dst and src must not overlap. It is valid to pass a nil dst. +// +// Decode handles the Snappy block format, not the Snappy stream format. +func Decode(dst, src []byte) ([]byte, error) { + dLen, s, err := decodedLen(src) + if err != nil { + return nil, err + } + if dLen <= len(dst) { + dst = dst[:dLen] + } else { + dst = make([]byte, dLen) + } + switch decode(dst, src[s:]) { + case 0: + return dst, nil + case decodeErrCodeUnsupportedLiteralLength: + return nil, errUnsupportedLiteralLength + } + return nil, ErrCorrupt +} + +// NewReader returns a new Reader that decompresses from r, using the framing +// format described at +// https://github.com/google/snappy/blob/master/framing_format.txt +func NewReader(r io.Reader) *Reader { + return &Reader{ + r: r, + decoded: make([]byte, maxBlockSize), + buf: make([]byte, maxEncodedLenOfMaxBlockSize+checksumSize), + } +} + +// Reader is an io.Reader that can read Snappy-compressed bytes. +// +// Reader handles the Snappy stream format, not the Snappy block format. +type Reader struct { + r io.Reader + err error + decoded []byte + buf []byte + // decoded[i:j] contains decoded bytes that have not yet been passed on. + i, j int + readHeader bool +} + +// Reset discards any buffered data, resets all state, and switches the Snappy +// reader to read from r. This permits reusing a Reader rather than allocating +// a new one. +func (r *Reader) Reset(reader io.Reader) { + r.r = reader + r.err = nil + r.i = 0 + r.j = 0 + r.readHeader = false +} + +func (r *Reader) readFull(p []byte, allowEOF bool) (ok bool) { + if _, r.err = io.ReadFull(r.r, p); r.err != nil { + if r.err == io.ErrUnexpectedEOF || (r.err == io.EOF && !allowEOF) { + r.err = ErrCorrupt + } + return false + } + return true +} + +func (r *Reader) fill() error { + for r.i >= r.j { + if !r.readFull(r.buf[:4], true) { + return r.err + } + chunkType := r.buf[0] + if !r.readHeader { + if chunkType != chunkTypeStreamIdentifier { + r.err = ErrCorrupt + return r.err + } + r.readHeader = true + } + chunkLen := int(r.buf[1]) | int(r.buf[2])<<8 | int(r.buf[3])<<16 + if chunkLen > len(r.buf) { + r.err = ErrUnsupported + return r.err + } + + // The chunk types are specified at + // https://github.com/google/snappy/blob/master/framing_format.txt + switch chunkType { + case chunkTypeCompressedData: + // Section 4.2. Compressed data (chunk type 0x00). + if chunkLen < checksumSize { + r.err = ErrCorrupt + return r.err + } + buf := r.buf[:chunkLen] + if !r.readFull(buf, false) { + return r.err + } + checksum := uint32(buf[0]) | uint32(buf[1])<<8 | uint32(buf[2])<<16 | uint32(buf[3])<<24 + buf = buf[checksumSize:] + + n, err := DecodedLen(buf) + if err != nil { + r.err = err + return r.err + } + if n > len(r.decoded) { + r.err = ErrCorrupt + return r.err + } + if _, err := Decode(r.decoded, buf); err != nil { + r.err = err + return r.err + } + if crc(r.decoded[:n]) != checksum { + r.err = ErrCorrupt + return r.err + } + r.i, r.j = 0, n + continue + + case chunkTypeUncompressedData: + // Section 4.3. Uncompressed data (chunk type 0x01). + if chunkLen < checksumSize { + r.err = ErrCorrupt + return r.err + } + buf := r.buf[:checksumSize] + if !r.readFull(buf, false) { + return r.err + } + checksum := uint32(buf[0]) | uint32(buf[1])<<8 | uint32(buf[2])<<16 | uint32(buf[3])<<24 + // Read directly into r.decoded instead of via r.buf. + n := chunkLen - checksumSize + if n > len(r.decoded) { + r.err = ErrCorrupt + return r.err + } + if !r.readFull(r.decoded[:n], false) { + return r.err + } + if crc(r.decoded[:n]) != checksum { + r.err = ErrCorrupt + return r.err + } + r.i, r.j = 0, n + continue + + case chunkTypeStreamIdentifier: + // Section 4.1. Stream identifier (chunk type 0xff). + if chunkLen != len(magicBody) { + r.err = ErrCorrupt + return r.err + } + if !r.readFull(r.buf[:len(magicBody)], false) { + return r.err + } + for i := 0; i < len(magicBody); i++ { + if r.buf[i] != magicBody[i] { + r.err = ErrCorrupt + return r.err + } + } + continue + } + + if chunkType <= 0x7f { + // Section 4.5. Reserved unskippable chunks (chunk types 0x02-0x7f). + r.err = ErrUnsupported + return r.err + } + // Section 4.4 Padding (chunk type 0xfe). + // Section 4.6. Reserved skippable chunks (chunk types 0x80-0xfd). + if !r.readFull(r.buf[:chunkLen], false) { + return r.err + } + } + + return nil +} + +// Read satisfies the io.Reader interface. +func (r *Reader) Read(p []byte) (int, error) { + if r.err != nil { + return 0, r.err + } + + if err := r.fill(); err != nil { + return 0, err + } + + n := copy(p, r.decoded[r.i:r.j]) + r.i += n + return n, nil +} + +// ReadByte satisfies the io.ByteReader interface. +func (r *Reader) ReadByte() (byte, error) { + if r.err != nil { + return 0, r.err + } + + if err := r.fill(); err != nil { + return 0, err + } + + c := r.decoded[r.i] + r.i++ + return c, nil +} diff --git a/vendor/github.com/klauspost/compress/internal/snapref/decode_other.go b/vendor/github.com/klauspost/compress/internal/snapref/decode_other.go new file mode 100644 index 000000000..77395a6b8 --- /dev/null +++ b/vendor/github.com/klauspost/compress/internal/snapref/decode_other.go @@ -0,0 +1,113 @@ +// Copyright 2016 The Snappy-Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package snapref + +// decode writes the decoding of src to dst. It assumes that the varint-encoded +// length of the decompressed bytes has already been read, and that len(dst) +// equals that length. +// +// It returns 0 on success or a decodeErrCodeXxx error code on failure. +func decode(dst, src []byte) int { + var d, s, offset, length int + for s < len(src) { + switch src[s] & 0x03 { + case tagLiteral: + x := uint32(src[s] >> 2) + switch { + case x < 60: + s++ + case x == 60: + s += 2 + if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line. + return decodeErrCodeCorrupt + } + x = uint32(src[s-1]) + case x == 61: + s += 3 + if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line. + return decodeErrCodeCorrupt + } + x = uint32(src[s-2]) | uint32(src[s-1])<<8 + case x == 62: + s += 4 + if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line. + return decodeErrCodeCorrupt + } + x = uint32(src[s-3]) | uint32(src[s-2])<<8 | uint32(src[s-1])<<16 + case x == 63: + s += 5 + if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line. + return decodeErrCodeCorrupt + } + x = uint32(src[s-4]) | uint32(src[s-3])<<8 | uint32(src[s-2])<<16 | uint32(src[s-1])<<24 + } + length = int(x) + 1 + if length <= 0 { + return decodeErrCodeUnsupportedLiteralLength + } + if length > len(dst)-d || length > len(src)-s { + return decodeErrCodeCorrupt + } + copy(dst[d:], src[s:s+length]) + d += length + s += length + continue + + case tagCopy1: + s += 2 + if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line. + return decodeErrCodeCorrupt + } + length = 4 + int(src[s-2])>>2&0x7 + offset = int(uint32(src[s-2])&0xe0<<3 | uint32(src[s-1])) + + case tagCopy2: + s += 3 + if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line. + return decodeErrCodeCorrupt + } + length = 1 + int(src[s-3])>>2 + offset = int(uint32(src[s-2]) | uint32(src[s-1])<<8) + + case tagCopy4: + s += 5 + if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line. + return decodeErrCodeCorrupt + } + length = 1 + int(src[s-5])>>2 + offset = int(uint32(src[s-4]) | uint32(src[s-3])<<8 | uint32(src[s-2])<<16 | uint32(src[s-1])<<24) + } + + if offset <= 0 || d < offset || length > len(dst)-d { + return decodeErrCodeCorrupt + } + // Copy from an earlier sub-slice of dst to a later sub-slice. + // If no overlap, use the built-in copy: + if offset >= length { + copy(dst[d:d+length], dst[d-offset:]) + d += length + continue + } + + // Unlike the built-in copy function, this byte-by-byte copy always runs + // forwards, even if the slices overlap. Conceptually, this is: + // + // d += forwardCopy(dst[d:d+length], dst[d-offset:]) + // + // We align the slices into a and b and show the compiler they are the same size. + // This allows the loop to run without bounds checks. + a := dst[d : d+length] + b := dst[d-offset:] + b = b[:len(a)] + for i := range a { + a[i] = b[i] + } + d += length + } + if d != len(dst) { + return decodeErrCodeCorrupt + } + return 0 +} diff --git a/vendor/github.com/klauspost/compress/internal/snapref/encode.go b/vendor/github.com/klauspost/compress/internal/snapref/encode.go new file mode 100644 index 000000000..13c6040a5 --- /dev/null +++ b/vendor/github.com/klauspost/compress/internal/snapref/encode.go @@ -0,0 +1,289 @@ +// Copyright 2011 The Snappy-Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package snapref + +import ( + "encoding/binary" + "errors" + "io" +) + +// Encode returns the encoded form of src. The returned slice may be a sub- +// slice of dst if dst was large enough to hold the entire encoded block. +// Otherwise, a newly allocated slice will be returned. +// +// The dst and src must not overlap. It is valid to pass a nil dst. +// +// Encode handles the Snappy block format, not the Snappy stream format. +func Encode(dst, src []byte) []byte { + if n := MaxEncodedLen(len(src)); n < 0 { + panic(ErrTooLarge) + } else if len(dst) < n { + dst = make([]byte, n) + } + + // The block starts with the varint-encoded length of the decompressed bytes. + d := binary.PutUvarint(dst, uint64(len(src))) + + for len(src) > 0 { + p := src + src = nil + if len(p) > maxBlockSize { + p, src = p[:maxBlockSize], p[maxBlockSize:] + } + if len(p) < minNonLiteralBlockSize { + d += emitLiteral(dst[d:], p) + } else { + d += encodeBlock(dst[d:], p) + } + } + return dst[:d] +} + +// inputMargin is the minimum number of extra input bytes to keep, inside +// encodeBlock's inner loop. On some architectures, this margin lets us +// implement a fast path for emitLiteral, where the copy of short (<= 16 byte) +// literals can be implemented as a single load to and store from a 16-byte +// register. That literal's actual length can be as short as 1 byte, so this +// can copy up to 15 bytes too much, but that's OK as subsequent iterations of +// the encoding loop will fix up the copy overrun, and this inputMargin ensures +// that we don't overrun the dst and src buffers. +const inputMargin = 16 - 1 + +// minNonLiteralBlockSize is the minimum size of the input to encodeBlock that +// could be encoded with a copy tag. This is the minimum with respect to the +// algorithm used by encodeBlock, not a minimum enforced by the file format. +// +// The encoded output must start with at least a 1 byte literal, as there are +// no previous bytes to copy. A minimal (1 byte) copy after that, generated +// from an emitCopy call in encodeBlock's main loop, would require at least +// another inputMargin bytes, for the reason above: we want any emitLiteral +// calls inside encodeBlock's main loop to use the fast path if possible, which +// requires being able to overrun by inputMargin bytes. Thus, +// minNonLiteralBlockSize equals 1 + 1 + inputMargin. +// +// The C++ code doesn't use this exact threshold, but it could, as discussed at +// https://groups.google.com/d/topic/snappy-compression/oGbhsdIJSJ8/discussion +// The difference between Go (2+inputMargin) and C++ (inputMargin) is purely an +// optimization. It should not affect the encoded form. This is tested by +// TestSameEncodingAsCppShortCopies. +const minNonLiteralBlockSize = 1 + 1 + inputMargin + +// MaxEncodedLen returns the maximum length of a snappy block, given its +// uncompressed length. +// +// It will return a negative value if srcLen is too large to encode. +func MaxEncodedLen(srcLen int) int { + n := uint64(srcLen) + if n > 0xffffffff { + return -1 + } + // Compressed data can be defined as: + // compressed := item* literal* + // item := literal* copy + // + // The trailing literal sequence has a space blowup of at most 62/60 + // since a literal of length 60 needs one tag byte + one extra byte + // for length information. + // + // Item blowup is trickier to measure. Suppose the "copy" op copies + // 4 bytes of data. Because of a special check in the encoding code, + // we produce a 4-byte copy only if the offset is < 65536. Therefore + // the copy op takes 3 bytes to encode, and this type of item leads + // to at most the 62/60 blowup for representing literals. + // + // Suppose the "copy" op copies 5 bytes of data. If the offset is big + // enough, it will take 5 bytes to encode the copy op. Therefore the + // worst case here is a one-byte literal followed by a five-byte copy. + // That is, 6 bytes of input turn into 7 bytes of "compressed" data. + // + // This last factor dominates the blowup, so the final estimate is: + n = 32 + n + n/6 + if n > 0xffffffff { + return -1 + } + return int(n) +} + +var errClosed = errors.New("snappy: Writer is closed") + +// NewWriter returns a new Writer that compresses to w. +// +// The Writer returned does not buffer writes. There is no need to Flush or +// Close such a Writer. +// +// Deprecated: the Writer returned is not suitable for many small writes, only +// for few large writes. Use NewBufferedWriter instead, which is efficient +// regardless of the frequency and shape of the writes, and remember to Close +// that Writer when done. +func NewWriter(w io.Writer) *Writer { + return &Writer{ + w: w, + obuf: make([]byte, obufLen), + } +} + +// NewBufferedWriter returns a new Writer that compresses to w, using the +// framing format described at +// https://github.com/google/snappy/blob/master/framing_format.txt +// +// The Writer returned buffers writes. Users must call Close to guarantee all +// data has been forwarded to the underlying io.Writer. They may also call +// Flush zero or more times before calling Close. +func NewBufferedWriter(w io.Writer) *Writer { + return &Writer{ + w: w, + ibuf: make([]byte, 0, maxBlockSize), + obuf: make([]byte, obufLen), + } +} + +// Writer is an io.Writer that can write Snappy-compressed bytes. +// +// Writer handles the Snappy stream format, not the Snappy block format. +type Writer struct { + w io.Writer + err error + + // ibuf is a buffer for the incoming (uncompressed) bytes. + // + // Its use is optional. For backwards compatibility, Writers created by the + // NewWriter function have ibuf == nil, do not buffer incoming bytes, and + // therefore do not need to be Flush'ed or Close'd. + ibuf []byte + + // obuf is a buffer for the outgoing (compressed) bytes. + obuf []byte + + // wroteStreamHeader is whether we have written the stream header. + wroteStreamHeader bool +} + +// Reset discards the writer's state and switches the Snappy writer to write to +// w. This permits reusing a Writer rather than allocating a new one. +func (w *Writer) Reset(writer io.Writer) { + w.w = writer + w.err = nil + if w.ibuf != nil { + w.ibuf = w.ibuf[:0] + } + w.wroteStreamHeader = false +} + +// Write satisfies the io.Writer interface. +func (w *Writer) Write(p []byte) (nRet int, errRet error) { + if w.ibuf == nil { + // Do not buffer incoming bytes. This does not perform or compress well + // if the caller of Writer.Write writes many small slices. This + // behavior is therefore deprecated, but still supported for backwards + // compatibility with code that doesn't explicitly Flush or Close. + return w.write(p) + } + + // The remainder of this method is based on bufio.Writer.Write from the + // standard library. + + for len(p) > (cap(w.ibuf)-len(w.ibuf)) && w.err == nil { + var n int + if len(w.ibuf) == 0 { + // Large write, empty buffer. + // Write directly from p to avoid copy. + n, _ = w.write(p) + } else { + n = copy(w.ibuf[len(w.ibuf):cap(w.ibuf)], p) + w.ibuf = w.ibuf[:len(w.ibuf)+n] + w.Flush() + } + nRet += n + p = p[n:] + } + if w.err != nil { + return nRet, w.err + } + n := copy(w.ibuf[len(w.ibuf):cap(w.ibuf)], p) + w.ibuf = w.ibuf[:len(w.ibuf)+n] + nRet += n + return nRet, nil +} + +func (w *Writer) write(p []byte) (nRet int, errRet error) { + if w.err != nil { + return 0, w.err + } + for len(p) > 0 { + obufStart := len(magicChunk) + if !w.wroteStreamHeader { + w.wroteStreamHeader = true + copy(w.obuf, magicChunk) + obufStart = 0 + } + + var uncompressed []byte + if len(p) > maxBlockSize { + uncompressed, p = p[:maxBlockSize], p[maxBlockSize:] + } else { + uncompressed, p = p, nil + } + checksum := crc(uncompressed) + + // Compress the buffer, discarding the result if the improvement + // isn't at least 12.5%. + compressed := Encode(w.obuf[obufHeaderLen:], uncompressed) + chunkType := uint8(chunkTypeCompressedData) + chunkLen := 4 + len(compressed) + obufEnd := obufHeaderLen + len(compressed) + if len(compressed) >= len(uncompressed)-len(uncompressed)/8 { + chunkType = chunkTypeUncompressedData + chunkLen = 4 + len(uncompressed) + obufEnd = obufHeaderLen + } + + // Fill in the per-chunk header that comes before the body. + w.obuf[len(magicChunk)+0] = chunkType + w.obuf[len(magicChunk)+1] = uint8(chunkLen >> 0) + w.obuf[len(magicChunk)+2] = uint8(chunkLen >> 8) + w.obuf[len(magicChunk)+3] = uint8(chunkLen >> 16) + w.obuf[len(magicChunk)+4] = uint8(checksum >> 0) + w.obuf[len(magicChunk)+5] = uint8(checksum >> 8) + w.obuf[len(magicChunk)+6] = uint8(checksum >> 16) + w.obuf[len(magicChunk)+7] = uint8(checksum >> 24) + + if _, err := w.w.Write(w.obuf[obufStart:obufEnd]); err != nil { + w.err = err + return nRet, err + } + if chunkType == chunkTypeUncompressedData { + if _, err := w.w.Write(uncompressed); err != nil { + w.err = err + return nRet, err + } + } + nRet += len(uncompressed) + } + return nRet, nil +} + +// Flush flushes the Writer to its underlying io.Writer. +func (w *Writer) Flush() error { + if w.err != nil { + return w.err + } + if len(w.ibuf) == 0 { + return nil + } + w.write(w.ibuf) + w.ibuf = w.ibuf[:0] + return w.err +} + +// Close calls Flush and then closes the Writer. +func (w *Writer) Close() error { + w.Flush() + ret := w.err + if w.err == nil { + w.err = errClosed + } + return ret +} diff --git a/vendor/github.com/klauspost/compress/internal/snapref/encode_other.go b/vendor/github.com/klauspost/compress/internal/snapref/encode_other.go new file mode 100644 index 000000000..2754bac6f --- /dev/null +++ b/vendor/github.com/klauspost/compress/internal/snapref/encode_other.go @@ -0,0 +1,250 @@ +// Copyright 2016 The Snappy-Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package snapref + +func load32(b []byte, i int) uint32 { + b = b[i : i+4 : len(b)] // Help the compiler eliminate bounds checks on the next line. + return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24 +} + +func load64(b []byte, i int) uint64 { + b = b[i : i+8 : len(b)] // Help the compiler eliminate bounds checks on the next line. + return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | + uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56 +} + +// emitLiteral writes a literal chunk and returns the number of bytes written. +// +// It assumes that: +// +// dst is long enough to hold the encoded bytes +// 1 <= len(lit) && len(lit) <= 65536 +func emitLiteral(dst, lit []byte) int { + i, n := 0, uint(len(lit)-1) + switch { + case n < 60: + dst[0] = uint8(n)<<2 | tagLiteral + i = 1 + case n < 1<<8: + dst[0] = 60<<2 | tagLiteral + dst[1] = uint8(n) + i = 2 + default: + dst[0] = 61<<2 | tagLiteral + dst[1] = uint8(n) + dst[2] = uint8(n >> 8) + i = 3 + } + return i + copy(dst[i:], lit) +} + +// emitCopy writes a copy chunk and returns the number of bytes written. +// +// It assumes that: +// +// dst is long enough to hold the encoded bytes +// 1 <= offset && offset <= 65535 +// 4 <= length && length <= 65535 +func emitCopy(dst []byte, offset, length int) int { + i := 0 + // The maximum length for a single tagCopy1 or tagCopy2 op is 64 bytes. The + // threshold for this loop is a little higher (at 68 = 64 + 4), and the + // length emitted down below is a little lower (at 60 = 64 - 4), because + // it's shorter to encode a length 67 copy as a length 60 tagCopy2 followed + // by a length 7 tagCopy1 (which encodes as 3+2 bytes) than to encode it as + // a length 64 tagCopy2 followed by a length 3 tagCopy2 (which encodes as + // 3+3 bytes). The magic 4 in the 64±4 is because the minimum length for a + // tagCopy1 op is 4 bytes, which is why a length 3 copy has to be an + // encodes-as-3-bytes tagCopy2 instead of an encodes-as-2-bytes tagCopy1. + for length >= 68 { + // Emit a length 64 copy, encoded as 3 bytes. + dst[i+0] = 63<<2 | tagCopy2 + dst[i+1] = uint8(offset) + dst[i+2] = uint8(offset >> 8) + i += 3 + length -= 64 + } + if length > 64 { + // Emit a length 60 copy, encoded as 3 bytes. + dst[i+0] = 59<<2 | tagCopy2 + dst[i+1] = uint8(offset) + dst[i+2] = uint8(offset >> 8) + i += 3 + length -= 60 + } + if length >= 12 || offset >= 2048 { + // Emit the remaining copy, encoded as 3 bytes. + dst[i+0] = uint8(length-1)<<2 | tagCopy2 + dst[i+1] = uint8(offset) + dst[i+2] = uint8(offset >> 8) + return i + 3 + } + // Emit the remaining copy, encoded as 2 bytes. + dst[i+0] = uint8(offset>>8)<<5 | uint8(length-4)<<2 | tagCopy1 + dst[i+1] = uint8(offset) + return i + 2 +} + +func hash(u, shift uint32) uint32 { + return (u * 0x1e35a7bd) >> shift +} + +// EncodeBlockInto exposes encodeBlock but checks dst size. +func EncodeBlockInto(dst, src []byte) (d int) { + if MaxEncodedLen(len(src)) > len(dst) { + return 0 + } + + // encodeBlock breaks on too big blocks, so split. + for len(src) > 0 { + p := src + src = nil + if len(p) > maxBlockSize { + p, src = p[:maxBlockSize], p[maxBlockSize:] + } + if len(p) < minNonLiteralBlockSize { + d += emitLiteral(dst[d:], p) + } else { + d += encodeBlock(dst[d:], p) + } + } + return d +} + +// encodeBlock encodes a non-empty src to a guaranteed-large-enough dst. It +// assumes that the varint-encoded length of the decompressed bytes has already +// been written. +// +// It also assumes that: +// +// len(dst) >= MaxEncodedLen(len(src)) && +// minNonLiteralBlockSize <= len(src) && len(src) <= maxBlockSize +func encodeBlock(dst, src []byte) (d int) { + // Initialize the hash table. Its size ranges from 1<<8 to 1<<14 inclusive. + // The table element type is uint16, as s < sLimit and sLimit < len(src) + // and len(src) <= maxBlockSize and maxBlockSize == 65536. + const ( + maxTableSize = 1 << 14 + // tableMask is redundant, but helps the compiler eliminate bounds + // checks. + tableMask = maxTableSize - 1 + ) + shift := uint32(32 - 8) + for tableSize := 1 << 8; tableSize < maxTableSize && tableSize < len(src); tableSize *= 2 { + shift-- + } + // In Go, all array elements are zero-initialized, so there is no advantage + // to a smaller tableSize per se. However, it matches the C++ algorithm, + // and in the asm versions of this code, we can get away with zeroing only + // the first tableSize elements. + var table [maxTableSize]uint16 + + // sLimit is when to stop looking for offset/length copies. The inputMargin + // lets us use a fast path for emitLiteral in the main loop, while we are + // looking for copies. + sLimit := len(src) - inputMargin + + // nextEmit is where in src the next emitLiteral should start from. + nextEmit := 0 + + // The encoded form must start with a literal, as there are no previous + // bytes to copy, so we start looking for hash matches at s == 1. + s := 1 + nextHash := hash(load32(src, s), shift) + + for { + // Copied from the C++ snappy implementation: + // + // Heuristic match skipping: If 32 bytes are scanned with no matches + // found, start looking only at every other byte. If 32 more bytes are + // scanned (or skipped), look at every third byte, etc.. When a match + // is found, immediately go back to looking at every byte. This is a + // small loss (~5% performance, ~0.1% density) for compressible data + // due to more bookkeeping, but for non-compressible data (such as + // JPEG) it's a huge win since the compressor quickly "realizes" the + // data is incompressible and doesn't bother looking for matches + // everywhere. + // + // The "skip" variable keeps track of how many bytes there are since + // the last match; dividing it by 32 (ie. right-shifting by five) gives + // the number of bytes to move ahead for each iteration. + skip := 32 + + nextS := s + candidate := 0 + for { + s = nextS + bytesBetweenHashLookups := skip >> 5 + nextS = s + bytesBetweenHashLookups + skip += bytesBetweenHashLookups + if nextS > sLimit { + goto emitRemainder + } + candidate = int(table[nextHash&tableMask]) + table[nextHash&tableMask] = uint16(s) + nextHash = hash(load32(src, nextS), shift) + if load32(src, s) == load32(src, candidate) { + break + } + } + + // A 4-byte match has been found. We'll later see if more than 4 bytes + // match. But, prior to the match, src[nextEmit:s] are unmatched. Emit + // them as literal bytes. + d += emitLiteral(dst[d:], src[nextEmit:s]) + + // Call emitCopy, and then see if another emitCopy could be our next + // move. Repeat until we find no match for the input immediately after + // what was consumed by the last emitCopy call. + // + // If we exit this loop normally then we need to call emitLiteral next, + // though we don't yet know how big the literal will be. We handle that + // by proceeding to the next iteration of the main loop. We also can + // exit this loop via goto if we get close to exhausting the input. + for { + // Invariant: we have a 4-byte match at s, and no need to emit any + // literal bytes prior to s. + base := s + + // Extend the 4-byte match as long as possible. + // + // This is an inlined version of: + // s = extendMatch(src, candidate+4, s+4) + s += 4 + for i := candidate + 4; s < len(src) && src[i] == src[s]; i, s = i+1, s+1 { + } + + d += emitCopy(dst[d:], base-candidate, s-base) + nextEmit = s + if s >= sLimit { + goto emitRemainder + } + + // We could immediately start working at s now, but to improve + // compression we first update the hash table at s-1 and at s. If + // another emitCopy is not our next move, also calculate nextHash + // at s+1. At least on GOARCH=amd64, these three hash calculations + // are faster as one load64 call (with some shifts) instead of + // three load32 calls. + x := load64(src, s-1) + prevHash := hash(uint32(x>>0), shift) + table[prevHash&tableMask] = uint16(s - 1) + currHash := hash(uint32(x>>8), shift) + candidate = int(table[currHash&tableMask]) + table[currHash&tableMask] = uint16(s) + if uint32(x>>8) != load32(src, candidate) { + nextHash = hash(uint32(x>>16), shift) + s++ + break + } + } + } + +emitRemainder: + if nextEmit < len(src) { + d += emitLiteral(dst[d:], src[nextEmit:]) + } + return d +} diff --git a/vendor/github.com/klauspost/compress/internal/snapref/snappy.go b/vendor/github.com/klauspost/compress/internal/snapref/snappy.go new file mode 100644 index 000000000..34d01f4aa --- /dev/null +++ b/vendor/github.com/klauspost/compress/internal/snapref/snappy.go @@ -0,0 +1,98 @@ +// Copyright 2011 The Snappy-Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package snapref implements the Snappy compression format. It aims for very +// high speeds and reasonable compression. +// +// There are actually two Snappy formats: block and stream. They are related, +// but different: trying to decompress block-compressed data as a Snappy stream +// will fail, and vice versa. The block format is the Decode and Encode +// functions and the stream format is the Reader and Writer types. +// +// The block format, the more common case, is used when the complete size (the +// number of bytes) of the original data is known upfront, at the time +// compression starts. The stream format, also known as the framing format, is +// for when that isn't always true. +// +// The canonical, C++ implementation is at https://github.com/google/snappy and +// it only implements the block format. +package snapref + +import ( + "hash/crc32" +) + +/* +Each encoded block begins with the varint-encoded length of the decoded data, +followed by a sequence of chunks. Chunks begin and end on byte boundaries. The +first byte of each chunk is broken into its 2 least and 6 most significant bits +called l and m: l ranges in [0, 4) and m ranges in [0, 64). l is the chunk tag. +Zero means a literal tag. All other values mean a copy tag. + +For literal tags: + - If m < 60, the next 1 + m bytes are literal bytes. + - Otherwise, let n be the little-endian unsigned integer denoted by the next + m - 59 bytes. The next 1 + n bytes after that are literal bytes. + +For copy tags, length bytes are copied from offset bytes ago, in the style of +Lempel-Ziv compression algorithms. In particular: + - For l == 1, the offset ranges in [0, 1<<11) and the length in [4, 12). + The length is 4 + the low 3 bits of m. The high 3 bits of m form bits 8-10 + of the offset. The next byte is bits 0-7 of the offset. + - For l == 2, the offset ranges in [0, 1<<16) and the length in [1, 65). + The length is 1 + m. The offset is the little-endian unsigned integer + denoted by the next 2 bytes. + - For l == 3, this tag is a legacy format that is no longer issued by most + encoders. Nonetheless, the offset ranges in [0, 1<<32) and the length in + [1, 65). The length is 1 + m. The offset is the little-endian unsigned + integer denoted by the next 4 bytes. +*/ +const ( + tagLiteral = 0x00 + tagCopy1 = 0x01 + tagCopy2 = 0x02 + tagCopy4 = 0x03 +) + +const ( + checksumSize = 4 + chunkHeaderSize = 4 + magicChunk = "\xff\x06\x00\x00" + magicBody + magicBody = "sNaPpY" + + // maxBlockSize is the maximum size of the input to encodeBlock. It is not + // part of the wire format per se, but some parts of the encoder assume + // that an offset fits into a uint16. + // + // Also, for the framing format (Writer type instead of Encode function), + // https://github.com/google/snappy/blob/master/framing_format.txt says + // that "the uncompressed data in a chunk must be no longer than 65536 + // bytes". + maxBlockSize = 65536 + + // maxEncodedLenOfMaxBlockSize equals MaxEncodedLen(maxBlockSize), but is + // hard coded to be a const instead of a variable, so that obufLen can also + // be a const. Their equivalence is confirmed by + // TestMaxEncodedLenOfMaxBlockSize. + maxEncodedLenOfMaxBlockSize = 76490 + + obufHeaderLen = len(magicChunk) + checksumSize + chunkHeaderSize + obufLen = obufHeaderLen + maxEncodedLenOfMaxBlockSize +) + +const ( + chunkTypeCompressedData = 0x00 + chunkTypeUncompressedData = 0x01 + chunkTypePadding = 0xfe + chunkTypeStreamIdentifier = 0xff +) + +var crcTable = crc32.MakeTable(crc32.Castagnoli) + +// crc implements the checksum specified in section 3 of +// https://github.com/google/snappy/blob/master/framing_format.txt +func crc(b []byte) uint32 { + c := crc32.Update(0, crcTable, b) + return uint32(c>>15|c<<17) + 0xa282ead8 +} diff --git a/vendor/github.com/klauspost/compress/s2sx.mod b/vendor/github.com/klauspost/compress/s2sx.mod new file mode 100644 index 000000000..5a4412f90 --- /dev/null +++ b/vendor/github.com/klauspost/compress/s2sx.mod @@ -0,0 +1,4 @@ +module github.com/klauspost/compress + +go 1.19 + diff --git a/vendor/github.com/klauspost/compress/s2sx.sum b/vendor/github.com/klauspost/compress/s2sx.sum new file mode 100644 index 000000000..e69de29bb diff --git a/vendor/github.com/klauspost/compress/zstd/README.md b/vendor/github.com/klauspost/compress/zstd/README.md new file mode 100644 index 000000000..92e2347bb --- /dev/null +++ b/vendor/github.com/klauspost/compress/zstd/README.md @@ -0,0 +1,441 @@ +# zstd + +[Zstandard](https://facebook.github.io/zstd/) is a real-time compression algorithm, providing high compression ratios. +It offers a very wide range of compression / speed trade-off, while being backed by a very fast decoder. +A high performance compression algorithm is implemented. For now focused on speed. + +This package provides [compression](#Compressor) to and [decompression](#Decompressor) of Zstandard content. + +This package is pure Go and without use of "unsafe". + +The `zstd` package is provided as open source software using a Go standard license. + +Currently the package is heavily optimized for 64 bit processors and will be significantly slower on 32 bit processors. + +For seekable zstd streams, see [this excellent package](https://github.com/SaveTheRbtz/zstd-seekable-format-go). + +## Installation + +Install using `go get -u github.com/klauspost/compress`. The package is located in `github.com/klauspost/compress/zstd`. + +[![Go Reference](https://pkg.go.dev/badge/github.com/klauspost/compress/zstd.svg)](https://pkg.go.dev/github.com/klauspost/compress/zstd) + +## Compressor + +### Status: + +STABLE - there may always be subtle bugs, a wide variety of content has been tested and the library is actively +used by several projects. This library is being [fuzz-tested](https://github.com/klauspost/compress-fuzz) for all updates. + +There may still be specific combinations of data types/size/settings that could lead to edge cases, +so as always, testing is recommended. + +For now, a high speed (fastest) and medium-fast (default) compressor has been implemented. + +* The "Fastest" compression ratio is roughly equivalent to zstd level 1. +* The "Default" compression ratio is roughly equivalent to zstd level 3 (default). +* The "Better" compression ratio is roughly equivalent to zstd level 7. +* The "Best" compression ratio is roughly equivalent to zstd level 11. + +In terms of speed, it is typically 2x as fast as the stdlib deflate/gzip in its fastest mode. +The compression ratio compared to stdlib is around level 3, but usually 3x as fast. + + +### Usage + +An Encoder can be used for either compressing a stream via the +`io.WriteCloser` interface supported by the Encoder or as multiple independent +tasks via the `EncodeAll` function. +Smaller encodes are encouraged to use the EncodeAll function. +Use `NewWriter` to create a new instance that can be used for both. + +To create a writer with default options, do like this: + +```Go +// Compress input to output. +func Compress(in io.Reader, out io.Writer) error { + enc, err := zstd.NewWriter(out) + if err != nil { + return err + } + _, err = io.Copy(enc, in) + if err != nil { + enc.Close() + return err + } + return enc.Close() +} +``` + +Now you can encode by writing data to `enc`. The output will be finished writing when `Close()` is called. +Even if your encode fails, you should still call `Close()` to release any resources that may be held up. + +The above is fine for big encodes. However, whenever possible try to *reuse* the writer. + +To reuse the encoder, you can use the `Reset(io.Writer)` function to change to another output. +This will allow the encoder to reuse all resources and avoid wasteful allocations. + +Currently stream encoding has 'light' concurrency, meaning up to 2 goroutines can be working on part +of a stream. This is independent of the `WithEncoderConcurrency(n)`, but that is likely to change +in the future. So if you want to limit concurrency for future updates, specify the concurrency +you would like. + +If you would like stream encoding to be done without spawning async goroutines, use `WithEncoderConcurrency(1)` +which will compress input as each block is completed, blocking on writes until each has completed. + +You can specify your desired compression level using `WithEncoderLevel()` option. Currently only pre-defined +compression settings can be specified. + +#### Future Compatibility Guarantees + +This will be an evolving project. When using this package it is important to note that both the compression efficiency and speed may change. + +The goal will be to keep the default efficiency at the default zstd (level 3). +However the encoding should never be assumed to remain the same, +and you should not use hashes of compressed output for similarity checks. + +The Encoder can be assumed to produce the same output from the exact same code version. +However, the may be modes in the future that break this, +although they will not be enabled without an explicit option. + +This encoder is not designed to (and will probably never) output the exact same bitstream as the reference encoder. + +Also note, that the cgo decompressor currently does not [report all errors on invalid input](https://github.com/DataDog/zstd/issues/59), +[omits error checks](https://github.com/DataDog/zstd/issues/61), [ignores checksums](https://github.com/DataDog/zstd/issues/43) +and seems to ignore concatenated streams, even though [it is part of the spec](https://github.com/facebook/zstd/blob/dev/doc/zstd_compression_format.md#frames). + +#### Blocks + +For compressing small blocks, the returned encoder has a function called `EncodeAll(src, dst []byte) []byte`. + +`EncodeAll` will encode all input in src and append it to dst. +This function can be called concurrently. +Each call will only run on a same goroutine as the caller. + +Encoded blocks can be concatenated and the result will be the combined input stream. +Data compressed with EncodeAll can be decoded with the Decoder, using either a stream or `DecodeAll`. + +Especially when encoding blocks you should take special care to reuse the encoder. +This will effectively make it run without allocations after a warmup period. +To make it run completely without allocations, supply a destination buffer with space for all content. + +```Go +import "github.com/klauspost/compress/zstd" + +// Create a writer that caches compressors. +// For this operation type we supply a nil Reader. +var encoder, _ = zstd.NewWriter(nil) + +// Compress a buffer. +// If you have a destination buffer, the allocation in the call can also be eliminated. +func Compress(src []byte) []byte { + return encoder.EncodeAll(src, make([]byte, 0, len(src))) +} +``` + +You can control the maximum number of concurrent encodes using the `WithEncoderConcurrency(n)` +option when creating the writer. + +Using the Encoder for both a stream and individual blocks concurrently is safe. + +### Performance + +I have collected some speed examples to compare speed and compression against other compressors. + +* `file` is the input file. +* `out` is the compressor used. `zskp` is this package. `zstd` is the Datadog cgo library. `gzstd/gzkp` is gzip standard and this library. +* `level` is the compression level used. For `zskp` level 1 is "fastest", level 2 is "default"; 3 is "better", 4 is "best". +* `insize`/`outsize` is the input/output size. +* `millis` is the number of milliseconds used for compression. +* `mb/s` is megabytes (2^20 bytes) per second. + +``` +Silesia Corpus: +http://sun.aei.polsl.pl/~sdeor/corpus/silesia.zip + +This package: +file out level insize outsize millis mb/s +silesia.tar zskp 1 211947520 73821326 634 318.47 +silesia.tar zskp 2 211947520 67655404 1508 133.96 +silesia.tar zskp 3 211947520 64746933 3000 67.37 +silesia.tar zskp 4 211947520 60073508 16926 11.94 + +cgo zstd: +silesia.tar zstd 1 211947520 73605392 543 371.56 +silesia.tar zstd 3 211947520 66793289 864 233.68 +silesia.tar zstd 6 211947520 62916450 1913 105.66 +silesia.tar zstd 9 211947520 60212393 5063 39.92 + +gzip, stdlib/this package: +silesia.tar gzstd 1 211947520 80007735 1498 134.87 +silesia.tar gzkp 1 211947520 80088272 1009 200.31 + +GOB stream of binary data. Highly compressible. +https://files.klauspost.com/compress/gob-stream.7z + +file out level insize outsize millis mb/s +gob-stream zskp 1 1911399616 233948096 3230 564.34 +gob-stream zskp 2 1911399616 203997694 4997 364.73 +gob-stream zskp 3 1911399616 173526523 13435 135.68 +gob-stream zskp 4 1911399616 162195235 47559 38.33 + +gob-stream zstd 1 1911399616 249810424 2637 691.26 +gob-stream zstd 3 1911399616 208192146 3490 522.31 +gob-stream zstd 6 1911399616 193632038 6687 272.56 +gob-stream zstd 9 1911399616 177620386 16175 112.70 + +gob-stream gzstd 1 1911399616 357382013 9046 201.49 +gob-stream gzkp 1 1911399616 359136669 4885 373.08 + +The test data for the Large Text Compression Benchmark is the first +10^9 bytes of the English Wikipedia dump on Mar. 3, 2006. +http://mattmahoney.net/dc/textdata.html + +file out level insize outsize millis mb/s +enwik9 zskp 1 1000000000 343833605 3687 258.64 +enwik9 zskp 2 1000000000 317001237 7672 124.29 +enwik9 zskp 3 1000000000 291915823 15923 59.89 +enwik9 zskp 4 1000000000 261710291 77697 12.27 + +enwik9 zstd 1 1000000000 358072021 3110 306.65 +enwik9 zstd 3 1000000000 313734672 4784 199.35 +enwik9 zstd 6 1000000000 295138875 10290 92.68 +enwik9 zstd 9 1000000000 278348700 28549 33.40 + +enwik9 gzstd 1 1000000000 382578136 8608 110.78 +enwik9 gzkp 1 1000000000 382781160 5628 169.45 + +Highly compressible JSON file. +https://files.klauspost.com/compress/github-june-2days-2019.json.zst + +file out level insize outsize millis mb/s +github-june-2days-2019.json zskp 1 6273951764 697439532 9789 611.17 +github-june-2days-2019.json zskp 2 6273951764 610876538 18553 322.49 +github-june-2days-2019.json zskp 3 6273951764 517662858 44186 135.41 +github-june-2days-2019.json zskp 4 6273951764 464617114 165373 36.18 + +github-june-2days-2019.json zstd 1 6273951764 766284037 8450 708.00 +github-june-2days-2019.json zstd 3 6273951764 661889476 10927 547.57 +github-june-2days-2019.json zstd 6 6273951764 642756859 22996 260.18 +github-june-2days-2019.json zstd 9 6273951764 601974523 52413 114.16 + +github-june-2days-2019.json gzstd 1 6273951764 1164397768 26793 223.32 +github-june-2days-2019.json gzkp 1 6273951764 1120631856 17693 338.16 + +VM Image, Linux mint with a few installed applications: +https://files.klauspost.com/compress/rawstudio-mint14.7z + +file out level insize outsize millis mb/s +rawstudio-mint14.tar zskp 1 8558382592 3718400221 18206 448.29 +rawstudio-mint14.tar zskp 2 8558382592 3326118337 37074 220.15 +rawstudio-mint14.tar zskp 3 8558382592 3163842361 87306 93.49 +rawstudio-mint14.tar zskp 4 8558382592 2970480650 783862 10.41 + +rawstudio-mint14.tar zstd 1 8558382592 3609250104 17136 476.27 +rawstudio-mint14.tar zstd 3 8558382592 3341679997 29262 278.92 +rawstudio-mint14.tar zstd 6 8558382592 3235846406 77904 104.77 +rawstudio-mint14.tar zstd 9 8558382592 3160778861 140946 57.91 + +rawstudio-mint14.tar gzstd 1 8558382592 3926234992 51345 158.96 +rawstudio-mint14.tar gzkp 1 8558382592 3960117298 36722 222.26 + +CSV data: +https://files.klauspost.com/compress/nyc-taxi-data-10M.csv.zst + +file out level insize outsize millis mb/s +nyc-taxi-data-10M.csv zskp 1 3325605752 641319332 9462 335.17 +nyc-taxi-data-10M.csv zskp 2 3325605752 588976126 17570 180.50 +nyc-taxi-data-10M.csv zskp 3 3325605752 529329260 32432 97.79 +nyc-taxi-data-10M.csv zskp 4 3325605752 474949772 138025 22.98 + +nyc-taxi-data-10M.csv zstd 1 3325605752 687399637 8233 385.18 +nyc-taxi-data-10M.csv zstd 3 3325605752 598514411 10065 315.07 +nyc-taxi-data-10M.csv zstd 6 3325605752 570522953 20038 158.27 +nyc-taxi-data-10M.csv zstd 9 3325605752 517554797 64565 49.12 + +nyc-taxi-data-10M.csv gzstd 1 3325605752 928654908 21270 149.11 +nyc-taxi-data-10M.csv gzkp 1 3325605752 922273214 13929 227.68 +``` + +## Decompressor + +Status: STABLE - there may still be subtle bugs, but a wide variety of content has been tested. + +This library is being continuously [fuzz-tested](https://github.com/klauspost/compress-fuzz), +kindly supplied by [fuzzit.dev](https://fuzzit.dev/). +The main purpose of the fuzz testing is to ensure that it is not possible to crash the decoder, +or run it past its limits with ANY input provided. + +### Usage + +The package has been designed for two main usages, big streams of data and smaller in-memory buffers. +There are two main usages of the package for these. Both of them are accessed by creating a `Decoder`. + +For streaming use a simple setup could look like this: + +```Go +import "github.com/klauspost/compress/zstd" + +func Decompress(in io.Reader, out io.Writer) error { + d, err := zstd.NewReader(in) + if err != nil { + return err + } + defer d.Close() + + // Copy content... + _, err = io.Copy(out, d) + return err +} +``` + +It is important to use the "Close" function when you no longer need the Reader to stop running goroutines, +when running with default settings. +Goroutines will exit once an error has been returned, including `io.EOF` at the end of a stream. + +Streams are decoded concurrently in 4 asynchronous stages to give the best possible throughput. +However, if you prefer synchronous decompression, use `WithDecoderConcurrency(1)` which will decompress data +as it is being requested only. + +For decoding buffers, it could look something like this: + +```Go +import "github.com/klauspost/compress/zstd" + +// Create a reader that caches decompressors. +// For this operation type we supply a nil Reader. +var decoder, _ = zstd.NewReader(nil, zstd.WithDecoderConcurrency(0)) + +// Decompress a buffer. We don't supply a destination buffer, +// so it will be allocated by the decoder. +func Decompress(src []byte) ([]byte, error) { + return decoder.DecodeAll(src, nil) +} +``` + +Both of these cases should provide the functionality needed. +The decoder can be used for *concurrent* decompression of multiple buffers. +By default 4 decompressors will be created. + +It will only allow a certain number of concurrent operations to run. +To tweak that yourself use the `WithDecoderConcurrency(n)` option when creating the decoder. +It is possible to use `WithDecoderConcurrency(0)` to create GOMAXPROCS decoders. + +### Dictionaries + +Data compressed with [dictionaries](https://github.com/facebook/zstd#the-case-for-small-data-compression) can be decompressed. + +Dictionaries are added individually to Decoders. +Dictionaries are generated by the `zstd --train` command and contains an initial state for the decoder. +To add a dictionary use the `WithDecoderDicts(dicts ...[]byte)` option with the dictionary data. +Several dictionaries can be added at once. + +The dictionary will be used automatically for the data that specifies them. +A re-used Decoder will still contain the dictionaries registered. + +When registering multiple dictionaries with the same ID, the last one will be used. + +It is possible to use dictionaries when compressing data. + +To enable a dictionary use `WithEncoderDict(dict []byte)`. Here only one dictionary will be used +and it will likely be used even if it doesn't improve compression. + +The used dictionary must be used to decompress the content. + +For any real gains, the dictionary should be built with similar data. +If an unsuitable dictionary is used the output may be slightly larger than using no dictionary. +Use the [zstd commandline tool](https://github.com/facebook/zstd/releases) to build a dictionary from sample data. +For information see [zstd dictionary information](https://github.com/facebook/zstd#the-case-for-small-data-compression). + +For now there is a fixed startup performance penalty for compressing content with dictionaries. +This will likely be improved over time. Just be aware to test performance when implementing. + +### Allocation-less operation + +The decoder has been designed to operate without allocations after a warmup. + +This means that you should *store* the decoder for best performance. +To re-use a stream decoder, use the `Reset(r io.Reader) error` to switch to another stream. +A decoder can safely be re-used even if the previous stream failed. + +To release the resources, you must call the `Close()` function on a decoder. +After this it can *no longer be reused*, but all running goroutines will be stopped. +So you *must* use this if you will no longer need the Reader. + +For decompressing smaller buffers a single decoder can be used. +When decoding buffers, you can supply a destination slice with length 0 and your expected capacity. +In this case no unneeded allocations should be made. + +### Concurrency + +The buffer decoder does everything on the same goroutine and does nothing concurrently. +It can however decode several buffers concurrently. Use `WithDecoderConcurrency(n)` to limit that. + +The stream decoder will create goroutines that: + +1) Reads input and splits the input into blocks. +2) Decompression of literals. +3) Decompression of sequences. +4) Reconstruction of output stream. + +So effectively this also means the decoder will "read ahead" and prepare data to always be available for output. + +The concurrency level will, for streams, determine how many blocks ahead the compression will start. + +Since "blocks" are quite dependent on the output of the previous block stream decoding will only have limited concurrency. + +In practice this means that concurrency is often limited to utilizing about 3 cores effectively. + +### Benchmarks + +The first two are streaming decodes and the last are smaller inputs. + +Running on AMD Ryzen 9 3950X 16-Core Processor. AMD64 assembly used. + +``` +BenchmarkDecoderSilesia-32 5 206878840 ns/op 1024.50 MB/s 49808 B/op 43 allocs/op +BenchmarkDecoderEnwik9-32 1 1271809000 ns/op 786.28 MB/s 72048 B/op 52 allocs/op + +Concurrent blocks, performance: + +BenchmarkDecoder_DecodeAllParallel/kppkn.gtb.zst-32 67356 17857 ns/op 10321.96 MB/s 22.48 pct 102 B/op 0 allocs/op +BenchmarkDecoder_DecodeAllParallel/geo.protodata.zst-32 266656 4421 ns/op 26823.21 MB/s 11.89 pct 19 B/op 0 allocs/op +BenchmarkDecoder_DecodeAllParallel/plrabn12.txt.zst-32 20992 56842 ns/op 8477.17 MB/s 39.90 pct 754 B/op 0 allocs/op +BenchmarkDecoder_DecodeAllParallel/lcet10.txt.zst-32 27456 43932 ns/op 9714.01 MB/s 33.27 pct 524 B/op 0 allocs/op +BenchmarkDecoder_DecodeAllParallel/asyoulik.txt.zst-32 78432 15047 ns/op 8319.15 MB/s 40.34 pct 66 B/op 0 allocs/op +BenchmarkDecoder_DecodeAllParallel/alice29.txt.zst-32 65800 18436 ns/op 8249.63 MB/s 37.75 pct 88 B/op 0 allocs/op +BenchmarkDecoder_DecodeAllParallel/html_x_4.zst-32 102993 11523 ns/op 35546.09 MB/s 3.637 pct 143 B/op 0 allocs/op +BenchmarkDecoder_DecodeAllParallel/paper-100k.pdf.zst-32 1000000 1070 ns/op 95720.98 MB/s 80.53 pct 3 B/op 0 allocs/op +BenchmarkDecoder_DecodeAllParallel/fireworks.jpeg.zst-32 749802 1752 ns/op 70272.35 MB/s 100.0 pct 5 B/op 0 allocs/op +BenchmarkDecoder_DecodeAllParallel/urls.10K.zst-32 22640 52934 ns/op 13263.37 MB/s 26.25 pct 1014 B/op 0 allocs/op +BenchmarkDecoder_DecodeAllParallel/html.zst-32 226412 5232 ns/op 19572.27 MB/s 14.49 pct 20 B/op 0 allocs/op +BenchmarkDecoder_DecodeAllParallel/comp-data.bin.zst-32 923041 1276 ns/op 3194.71 MB/s 31.26 pct 0 B/op 0 allocs/op +``` + +This reflects the performance around May 2022, but this may be out of date. + +## Zstd inside ZIP files + +It is possible to use zstandard to compress individual files inside zip archives. +While this isn't widely supported it can be useful for internal files. + +To support the compression and decompression of these files you must register a compressor and decompressor. + +It is highly recommended registering the (de)compressors on individual zip Reader/Writer and NOT +use the global registration functions. The main reason for this is that 2 registrations from +different packages will result in a panic. + +It is a good idea to only have a single compressor and decompressor, since they can be used for multiple zip +files concurrently, and using a single instance will allow reusing some resources. + +See [this example](https://pkg.go.dev/github.com/klauspost/compress/zstd#example-ZipCompressor) for +how to compress and decompress files inside zip archives. + +# Contributions + +Contributions are always welcome. +For new features/fixes, remember to add tests and for performance enhancements include benchmarks. + +For general feedback and experience reports, feel free to open an issue or write me on [Twitter](https://twitter.com/sh0dan). + +This package includes the excellent [`github.com/cespare/xxhash`](https://github.com/cespare/xxhash) package Copyright (c) 2016 Caleb Spare. diff --git a/vendor/github.com/klauspost/compress/zstd/bitreader.go b/vendor/github.com/klauspost/compress/zstd/bitreader.go new file mode 100644 index 000000000..25ca98394 --- /dev/null +++ b/vendor/github.com/klauspost/compress/zstd/bitreader.go @@ -0,0 +1,136 @@ +// Copyright 2019+ Klaus Post. All rights reserved. +// License information can be found in the LICENSE file. +// Based on work by Yann Collet, released under BSD License. + +package zstd + +import ( + "encoding/binary" + "errors" + "fmt" + "io" + "math/bits" +) + +// bitReader reads a bitstream in reverse. +// The last set bit indicates the start of the stream and is used +// for aligning the input. +type bitReader struct { + in []byte + value uint64 // Maybe use [16]byte, but shifting is awkward. + bitsRead uint8 +} + +// init initializes and resets the bit reader. +func (b *bitReader) init(in []byte) error { + if len(in) < 1 { + return errors.New("corrupt stream: too short") + } + b.in = in + // The highest bit of the last byte indicates where to start + v := in[len(in)-1] + if v == 0 { + return errors.New("corrupt stream, did not find end of stream") + } + b.bitsRead = 64 + b.value = 0 + if len(in) >= 8 { + b.fillFastStart() + } else { + b.fill() + b.fill() + } + b.bitsRead += 8 - uint8(highBits(uint32(v))) + return nil +} + +// getBits will return n bits. n can be 0. +func (b *bitReader) getBits(n uint8) int { + if n == 0 /*|| b.bitsRead >= 64 */ { + return 0 + } + return int(b.get32BitsFast(n)) +} + +// get32BitsFast requires that at least one bit is requested every time. +// There are no checks if the buffer is filled. +func (b *bitReader) get32BitsFast(n uint8) uint32 { + const regMask = 64 - 1 + v := uint32((b.value << (b.bitsRead & regMask)) >> ((regMask + 1 - n) & regMask)) + b.bitsRead += n + return v +} + +// fillFast() will make sure at least 32 bits are available. +// There must be at least 4 bytes available. +func (b *bitReader) fillFast() { + if b.bitsRead < 32 { + return + } + v := b.in[len(b.in)-4:] + b.in = b.in[:len(b.in)-4] + low := (uint32(v[0])) | (uint32(v[1]) << 8) | (uint32(v[2]) << 16) | (uint32(v[3]) << 24) + b.value = (b.value << 32) | uint64(low) + b.bitsRead -= 32 +} + +// fillFastStart() assumes the bitreader is empty and there is at least 8 bytes to read. +func (b *bitReader) fillFastStart() { + v := b.in[len(b.in)-8:] + b.in = b.in[:len(b.in)-8] + b.value = binary.LittleEndian.Uint64(v) + b.bitsRead = 0 +} + +// fill() will make sure at least 32 bits are available. +func (b *bitReader) fill() { + if b.bitsRead < 32 { + return + } + if len(b.in) >= 4 { + v := b.in[len(b.in)-4:] + b.in = b.in[:len(b.in)-4] + low := (uint32(v[0])) | (uint32(v[1]) << 8) | (uint32(v[2]) << 16) | (uint32(v[3]) << 24) + b.value = (b.value << 32) | uint64(low) + b.bitsRead -= 32 + return + } + + b.bitsRead -= uint8(8 * len(b.in)) + for len(b.in) > 0 { + b.value = (b.value << 8) | uint64(b.in[len(b.in)-1]) + b.in = b.in[:len(b.in)-1] + } +} + +// finished returns true if all bits have been read from the bit stream. +func (b *bitReader) finished() bool { + return len(b.in) == 0 && b.bitsRead >= 64 +} + +// overread returns true if more bits have been requested than is on the stream. +func (b *bitReader) overread() bool { + return b.bitsRead > 64 +} + +// remain returns the number of bits remaining. +func (b *bitReader) remain() uint { + return 8*uint(len(b.in)) + 64 - uint(b.bitsRead) +} + +// close the bitstream and returns an error if out-of-buffer reads occurred. +func (b *bitReader) close() error { + // Release reference. + b.in = nil + if !b.finished() { + return fmt.Errorf("%d extra bits on block, should be 0", b.remain()) + } + if b.bitsRead > 64 { + return io.ErrUnexpectedEOF + } + return nil +} + +func highBits(val uint32) (n uint32) { + return uint32(bits.Len32(val) - 1) +} diff --git a/vendor/github.com/klauspost/compress/zstd/bitwriter.go b/vendor/github.com/klauspost/compress/zstd/bitwriter.go new file mode 100644 index 000000000..1952f175b --- /dev/null +++ b/vendor/github.com/klauspost/compress/zstd/bitwriter.go @@ -0,0 +1,112 @@ +// Copyright 2018 Klaus Post. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// Based on work Copyright (c) 2013, Yann Collet, released under BSD License. + +package zstd + +// bitWriter will write bits. +// First bit will be LSB of the first byte of output. +type bitWriter struct { + bitContainer uint64 + nBits uint8 + out []byte +} + +// bitMask16 is bitmasks. Has extra to avoid bounds check. +var bitMask16 = [32]uint16{ + 0, 1, 3, 7, 0xF, 0x1F, + 0x3F, 0x7F, 0xFF, 0x1FF, 0x3FF, 0x7FF, + 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, + 0xFFFF, 0xFFFF} /* up to 16 bits */ + +var bitMask32 = [32]uint32{ + 0, 1, 3, 7, 0xF, 0x1F, 0x3F, 0x7F, 0xFF, + 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF, + 0x1ffff, 0x3ffff, 0x7FFFF, 0xfFFFF, 0x1fFFFF, 0x3fFFFF, 0x7fFFFF, 0xffFFFF, + 0x1ffFFFF, 0x3ffFFFF, 0x7ffFFFF, 0xfffFFFF, 0x1fffFFFF, 0x3fffFFFF, 0x7fffFFFF, +} // up to 32 bits + +// addBits16NC will add up to 16 bits. +// It will not check if there is space for them, +// so the caller must ensure that it has flushed recently. +func (b *bitWriter) addBits16NC(value uint16, bits uint8) { + b.bitContainer |= uint64(value&bitMask16[bits&31]) << (b.nBits & 63) + b.nBits += bits +} + +// addBits32NC will add up to 31 bits. +// It will not check if there is space for them, +// so the caller must ensure that it has flushed recently. +func (b *bitWriter) addBits32NC(value uint32, bits uint8) { + b.bitContainer |= uint64(value&bitMask32[bits&31]) << (b.nBits & 63) + b.nBits += bits +} + +// addBits64NC will add up to 64 bits. +// There must be space for 32 bits. +func (b *bitWriter) addBits64NC(value uint64, bits uint8) { + if bits <= 31 { + b.addBits32Clean(uint32(value), bits) + return + } + b.addBits32Clean(uint32(value), 32) + b.flush32() + b.addBits32Clean(uint32(value>>32), bits-32) +} + +// addBits32Clean will add up to 32 bits. +// It will not check if there is space for them. +// The input must not contain more bits than specified. +func (b *bitWriter) addBits32Clean(value uint32, bits uint8) { + b.bitContainer |= uint64(value) << (b.nBits & 63) + b.nBits += bits +} + +// addBits16Clean will add up to 16 bits. value may not contain more set bits than indicated. +// It will not check if there is space for them, so the caller must ensure that it has flushed recently. +func (b *bitWriter) addBits16Clean(value uint16, bits uint8) { + b.bitContainer |= uint64(value) << (b.nBits & 63) + b.nBits += bits +} + +// flush32 will flush out, so there are at least 32 bits available for writing. +func (b *bitWriter) flush32() { + if b.nBits < 32 { + return + } + b.out = append(b.out, + byte(b.bitContainer), + byte(b.bitContainer>>8), + byte(b.bitContainer>>16), + byte(b.bitContainer>>24)) + b.nBits -= 32 + b.bitContainer >>= 32 +} + +// flushAlign will flush remaining full bytes and align to next byte boundary. +func (b *bitWriter) flushAlign() { + nbBytes := (b.nBits + 7) >> 3 + for i := uint8(0); i < nbBytes; i++ { + b.out = append(b.out, byte(b.bitContainer>>(i*8))) + } + b.nBits = 0 + b.bitContainer = 0 +} + +// close will write the alignment bit and write the final byte(s) +// to the output. +func (b *bitWriter) close() { + // End mark + b.addBits16Clean(1, 1) + // flush until next byte. + b.flushAlign() +} + +// reset and continue writing by appending to out. +func (b *bitWriter) reset(out []byte) { + b.bitContainer = 0 + b.nBits = 0 + b.out = out +} diff --git a/vendor/github.com/klauspost/compress/zstd/blockdec.go b/vendor/github.com/klauspost/compress/zstd/blockdec.go new file mode 100644 index 000000000..03744fbc7 --- /dev/null +++ b/vendor/github.com/klauspost/compress/zstd/blockdec.go @@ -0,0 +1,729 @@ +// Copyright 2019+ Klaus Post. All rights reserved. +// License information can be found in the LICENSE file. +// Based on work by Yann Collet, released under BSD License. + +package zstd + +import ( + "bytes" + "encoding/binary" + "errors" + "fmt" + "hash/crc32" + "io" + "os" + "path/filepath" + "sync" + + "github.com/klauspost/compress/huff0" + "github.com/klauspost/compress/zstd/internal/xxhash" +) + +type blockType uint8 + +//go:generate stringer -type=blockType,literalsBlockType,seqCompMode,tableIndex + +const ( + blockTypeRaw blockType = iota + blockTypeRLE + blockTypeCompressed + blockTypeReserved +) + +type literalsBlockType uint8 + +const ( + literalsBlockRaw literalsBlockType = iota + literalsBlockRLE + literalsBlockCompressed + literalsBlockTreeless +) + +const ( + // maxCompressedBlockSize is the biggest allowed compressed block size (128KB) + maxCompressedBlockSize = 128 << 10 + + compressedBlockOverAlloc = 16 + maxCompressedBlockSizeAlloc = 128<<10 + compressedBlockOverAlloc + + // Maximum possible block size (all Raw+Uncompressed). + maxBlockSize = (1 << 21) - 1 + + maxMatchLen = 131074 + maxSequences = 0x7f00 + 0xffff + + // We support slightly less than the reference decoder to be able to + // use ints on 32 bit archs. + maxOffsetBits = 30 +) + +var ( + huffDecoderPool = sync.Pool{New: func() interface{} { + return &huff0.Scratch{} + }} + + fseDecoderPool = sync.Pool{New: func() interface{} { + return &fseDecoder{} + }} +) + +type blockDec struct { + // Raw source data of the block. + data []byte + dataStorage []byte + + // Destination of the decoded data. + dst []byte + + // Buffer for literals data. + literalBuf []byte + + // Window size of the block. + WindowSize uint64 + + err error + + // Check against this crc, if hasCRC is true. + checkCRC uint32 + hasCRC bool + + // Frame to use for singlethreaded decoding. + // Should not be used by the decoder itself since parent may be another frame. + localFrame *frameDec + + sequence []seqVals + + async struct { + newHist *history + literals []byte + seqData []byte + seqSize int // Size of uncompressed sequences + fcs uint64 + } + + // Block is RLE, this is the size. + RLESize uint32 + + Type blockType + + // Is this the last block of a frame? + Last bool + + // Use less memory + lowMem bool +} + +func (b *blockDec) String() string { + if b == nil { + return "" + } + return fmt.Sprintf("Steam Size: %d, Type: %v, Last: %t, Window: %d", len(b.data), b.Type, b.Last, b.WindowSize) +} + +func newBlockDec(lowMem bool) *blockDec { + b := blockDec{ + lowMem: lowMem, + } + return &b +} + +// reset will reset the block. +// Input must be a start of a block and will be at the end of the block when returned. +func (b *blockDec) reset(br byteBuffer, windowSize uint64) error { + b.WindowSize = windowSize + tmp, err := br.readSmall(3) + if err != nil { + println("Reading block header:", err) + return err + } + bh := uint32(tmp[0]) | (uint32(tmp[1]) << 8) | (uint32(tmp[2]) << 16) + b.Last = bh&1 != 0 + b.Type = blockType((bh >> 1) & 3) + // find size. + cSize := int(bh >> 3) + maxSize := maxCompressedBlockSizeAlloc + switch b.Type { + case blockTypeReserved: + return ErrReservedBlockType + case blockTypeRLE: + if cSize > maxCompressedBlockSize || cSize > int(b.WindowSize) { + if debugDecoder { + printf("rle block too big: csize:%d block: %+v\n", uint64(cSize), b) + } + return ErrWindowSizeExceeded + } + b.RLESize = uint32(cSize) + if b.lowMem { + maxSize = cSize + } + cSize = 1 + case blockTypeCompressed: + if debugDecoder { + println("Data size on stream:", cSize) + } + b.RLESize = 0 + maxSize = maxCompressedBlockSizeAlloc + if windowSize < maxCompressedBlockSize && b.lowMem { + maxSize = int(windowSize) + compressedBlockOverAlloc + } + if cSize > maxCompressedBlockSize || uint64(cSize) > b.WindowSize { + if debugDecoder { + printf("compressed block too big: csize:%d block: %+v\n", uint64(cSize), b) + } + return ErrCompressedSizeTooBig + } + // Empty compressed blocks must at least be 2 bytes + // for Literals_Block_Type and one for Sequences_Section_Header. + if cSize < 2 { + return ErrBlockTooSmall + } + case blockTypeRaw: + if cSize > maxCompressedBlockSize || cSize > int(b.WindowSize) { + if debugDecoder { + printf("rle block too big: csize:%d block: %+v\n", uint64(cSize), b) + } + return ErrWindowSizeExceeded + } + + b.RLESize = 0 + // We do not need a destination for raw blocks. + maxSize = -1 + default: + panic("Invalid block type") + } + + // Read block data. + if _, ok := br.(*byteBuf); !ok && cap(b.dataStorage) < cSize { + // byteBuf doesn't need a destination buffer. + if b.lowMem || cSize > maxCompressedBlockSize { + b.dataStorage = make([]byte, 0, cSize+compressedBlockOverAlloc) + } else { + b.dataStorage = make([]byte, 0, maxCompressedBlockSizeAlloc) + } + } + b.data, err = br.readBig(cSize, b.dataStorage) + if err != nil { + if debugDecoder { + println("Reading block:", err, "(", cSize, ")", len(b.data)) + printf("%T", br) + } + return err + } + if cap(b.dst) <= maxSize { + b.dst = make([]byte, 0, maxSize+1) + } + return nil +} + +// sendEOF will make the decoder send EOF on this frame. +func (b *blockDec) sendErr(err error) { + b.Last = true + b.Type = blockTypeReserved + b.err = err +} + +// Close will release resources. +// Closed blockDec cannot be reset. +func (b *blockDec) Close() { +} + +// decodeBuf +func (b *blockDec) decodeBuf(hist *history) error { + switch b.Type { + case blockTypeRLE: + if cap(b.dst) < int(b.RLESize) { + if b.lowMem { + b.dst = make([]byte, b.RLESize) + } else { + b.dst = make([]byte, maxCompressedBlockSize) + } + } + b.dst = b.dst[:b.RLESize] + v := b.data[0] + for i := range b.dst { + b.dst[i] = v + } + hist.appendKeep(b.dst) + return nil + case blockTypeRaw: + hist.appendKeep(b.data) + return nil + case blockTypeCompressed: + saved := b.dst + // Append directly to history + if hist.ignoreBuffer == 0 { + b.dst = hist.b + hist.b = nil + } else { + b.dst = b.dst[:0] + } + err := b.decodeCompressed(hist) + if debugDecoder { + println("Decompressed to total", len(b.dst), "bytes, hash:", xxhash.Sum64(b.dst), "error:", err) + } + if hist.ignoreBuffer == 0 { + hist.b = b.dst + b.dst = saved + } else { + hist.appendKeep(b.dst) + } + return err + case blockTypeReserved: + // Used for returning errors. + return b.err + default: + panic("Invalid block type") + } +} + +func (b *blockDec) decodeLiterals(in []byte, hist *history) (remain []byte, err error) { + // There must be at least one byte for Literals_Block_Type and one for Sequences_Section_Header + if len(in) < 2 { + return in, ErrBlockTooSmall + } + + litType := literalsBlockType(in[0] & 3) + var litRegenSize int + var litCompSize int + sizeFormat := (in[0] >> 2) & 3 + var fourStreams bool + var literals []byte + switch litType { + case literalsBlockRaw, literalsBlockRLE: + switch sizeFormat { + case 0, 2: + // Regenerated_Size uses 5 bits (0-31). Literals_Section_Header uses 1 byte. + litRegenSize = int(in[0] >> 3) + in = in[1:] + case 1: + // Regenerated_Size uses 12 bits (0-4095). Literals_Section_Header uses 2 bytes. + litRegenSize = int(in[0]>>4) + (int(in[1]) << 4) + in = in[2:] + case 3: + // Regenerated_Size uses 20 bits (0-1048575). Literals_Section_Header uses 3 bytes. + if len(in) < 3 { + println("too small: litType:", litType, " sizeFormat", sizeFormat, len(in)) + return in, ErrBlockTooSmall + } + litRegenSize = int(in[0]>>4) + (int(in[1]) << 4) + (int(in[2]) << 12) + in = in[3:] + } + case literalsBlockCompressed, literalsBlockTreeless: + switch sizeFormat { + case 0, 1: + // Both Regenerated_Size and Compressed_Size use 10 bits (0-1023). + if len(in) < 3 { + println("too small: litType:", litType, " sizeFormat", sizeFormat, len(in)) + return in, ErrBlockTooSmall + } + n := uint64(in[0]>>4) + (uint64(in[1]) << 4) + (uint64(in[2]) << 12) + litRegenSize = int(n & 1023) + litCompSize = int(n >> 10) + fourStreams = sizeFormat == 1 + in = in[3:] + case 2: + fourStreams = true + if len(in) < 4 { + println("too small: litType:", litType, " sizeFormat", sizeFormat, len(in)) + return in, ErrBlockTooSmall + } + n := uint64(in[0]>>4) + (uint64(in[1]) << 4) + (uint64(in[2]) << 12) + (uint64(in[3]) << 20) + litRegenSize = int(n & 16383) + litCompSize = int(n >> 14) + in = in[4:] + case 3: + fourStreams = true + if len(in) < 5 { + println("too small: litType:", litType, " sizeFormat", sizeFormat, len(in)) + return in, ErrBlockTooSmall + } + n := uint64(in[0]>>4) + (uint64(in[1]) << 4) + (uint64(in[2]) << 12) + (uint64(in[3]) << 20) + (uint64(in[4]) << 28) + litRegenSize = int(n & 262143) + litCompSize = int(n >> 18) + in = in[5:] + } + } + if debugDecoder { + println("literals type:", litType, "litRegenSize:", litRegenSize, "litCompSize:", litCompSize, "sizeFormat:", sizeFormat, "4X:", fourStreams) + } + if litRegenSize > int(b.WindowSize) || litRegenSize > maxCompressedBlockSize { + return in, ErrWindowSizeExceeded + } + + switch litType { + case literalsBlockRaw: + if len(in) < litRegenSize { + println("too small: litType:", litType, " sizeFormat", sizeFormat, "remain:", len(in), "want:", litRegenSize) + return in, ErrBlockTooSmall + } + literals = in[:litRegenSize] + in = in[litRegenSize:] + //printf("Found %d uncompressed literals\n", litRegenSize) + case literalsBlockRLE: + if len(in) < 1 { + println("too small: litType:", litType, " sizeFormat", sizeFormat, "remain:", len(in), "want:", 1) + return in, ErrBlockTooSmall + } + if cap(b.literalBuf) < litRegenSize { + if b.lowMem { + b.literalBuf = make([]byte, litRegenSize, litRegenSize+compressedBlockOverAlloc) + } else { + b.literalBuf = make([]byte, litRegenSize, maxCompressedBlockSize+compressedBlockOverAlloc) + } + } + literals = b.literalBuf[:litRegenSize] + v := in[0] + for i := range literals { + literals[i] = v + } + in = in[1:] + if debugDecoder { + printf("Found %d RLE compressed literals\n", litRegenSize) + } + case literalsBlockTreeless: + if len(in) < litCompSize { + println("too small: litType:", litType, " sizeFormat", sizeFormat, "remain:", len(in), "want:", litCompSize) + return in, ErrBlockTooSmall + } + // Store compressed literals, so we defer decoding until we get history. + literals = in[:litCompSize] + in = in[litCompSize:] + if debugDecoder { + printf("Found %d compressed literals\n", litCompSize) + } + huff := hist.huffTree + if huff == nil { + return in, errors.New("literal block was treeless, but no history was defined") + } + // Ensure we have space to store it. + if cap(b.literalBuf) < litRegenSize { + if b.lowMem { + b.literalBuf = make([]byte, 0, litRegenSize+compressedBlockOverAlloc) + } else { + b.literalBuf = make([]byte, 0, maxCompressedBlockSize+compressedBlockOverAlloc) + } + } + var err error + // Use our out buffer. + huff.MaxDecodedSize = litRegenSize + if fourStreams { + literals, err = huff.Decoder().Decompress4X(b.literalBuf[:0:litRegenSize], literals) + } else { + literals, err = huff.Decoder().Decompress1X(b.literalBuf[:0:litRegenSize], literals) + } + // Make sure we don't leak our literals buffer + if err != nil { + println("decompressing literals:", err) + return in, err + } + if len(literals) != litRegenSize { + return in, fmt.Errorf("literal output size mismatch want %d, got %d", litRegenSize, len(literals)) + } + + case literalsBlockCompressed: + if len(in) < litCompSize { + println("too small: litType:", litType, " sizeFormat", sizeFormat, "remain:", len(in), "want:", litCompSize) + return in, ErrBlockTooSmall + } + literals = in[:litCompSize] + in = in[litCompSize:] + // Ensure we have space to store it. + if cap(b.literalBuf) < litRegenSize { + if b.lowMem { + b.literalBuf = make([]byte, 0, litRegenSize+compressedBlockOverAlloc) + } else { + b.literalBuf = make([]byte, 0, maxCompressedBlockSize+compressedBlockOverAlloc) + } + } + huff := hist.huffTree + if huff == nil || (hist.dict != nil && huff == hist.dict.litEnc) { + huff = huffDecoderPool.Get().(*huff0.Scratch) + if huff == nil { + huff = &huff0.Scratch{} + } + } + var err error + if debugDecoder { + println("huff table input:", len(literals), "CRC:", crc32.ChecksumIEEE(literals)) + } + huff, literals, err = huff0.ReadTable(literals, huff) + if err != nil { + println("reading huffman table:", err) + return in, err + } + hist.huffTree = huff + huff.MaxDecodedSize = litRegenSize + // Use our out buffer. + if fourStreams { + literals, err = huff.Decoder().Decompress4X(b.literalBuf[:0:litRegenSize], literals) + } else { + literals, err = huff.Decoder().Decompress1X(b.literalBuf[:0:litRegenSize], literals) + } + if err != nil { + println("decoding compressed literals:", err) + return in, err + } + // Make sure we don't leak our literals buffer + if len(literals) != litRegenSize { + return in, fmt.Errorf("literal output size mismatch want %d, got %d", litRegenSize, len(literals)) + } + // Re-cap to get extra size. + literals = b.literalBuf[:len(literals)] + if debugDecoder { + printf("Decompressed %d literals into %d bytes\n", litCompSize, litRegenSize) + } + } + hist.decoders.literals = literals + return in, nil +} + +// decodeCompressed will start decompressing a block. +func (b *blockDec) decodeCompressed(hist *history) error { + in := b.data + in, err := b.decodeLiterals(in, hist) + if err != nil { + return err + } + err = b.prepareSequences(in, hist) + if err != nil { + return err + } + if hist.decoders.nSeqs == 0 { + b.dst = append(b.dst, hist.decoders.literals...) + return nil + } + before := len(hist.decoders.out) + err = hist.decoders.decodeSync(hist.b[hist.ignoreBuffer:]) + if err != nil { + return err + } + if hist.decoders.maxSyncLen > 0 { + hist.decoders.maxSyncLen += uint64(before) + hist.decoders.maxSyncLen -= uint64(len(hist.decoders.out)) + } + b.dst = hist.decoders.out + hist.recentOffsets = hist.decoders.prevOffset + return nil +} + +func (b *blockDec) prepareSequences(in []byte, hist *history) (err error) { + if debugDecoder { + printf("prepareSequences: %d byte(s) input\n", len(in)) + } + // Decode Sequences + // https://github.com/facebook/zstd/blob/dev/doc/zstd_compression_format.md#sequences-section + if len(in) < 1 { + return ErrBlockTooSmall + } + var nSeqs int + seqHeader := in[0] + switch { + case seqHeader < 128: + nSeqs = int(seqHeader) + in = in[1:] + case seqHeader < 255: + if len(in) < 2 { + return ErrBlockTooSmall + } + nSeqs = int(seqHeader-128)<<8 | int(in[1]) + in = in[2:] + case seqHeader == 255: + if len(in) < 3 { + return ErrBlockTooSmall + } + nSeqs = 0x7f00 + int(in[1]) + (int(in[2]) << 8) + in = in[3:] + } + if nSeqs == 0 && len(in) != 0 { + // When no sequences, there should not be any more data... + if debugDecoder { + printf("prepareSequences: 0 sequences, but %d byte(s) left on stream\n", len(in)) + } + return ErrUnexpectedBlockSize + } + + var seqs = &hist.decoders + seqs.nSeqs = nSeqs + if nSeqs > 0 { + if len(in) < 1 { + return ErrBlockTooSmall + } + br := byteReader{b: in, off: 0} + compMode := br.Uint8() + br.advance(1) + if debugDecoder { + printf("Compression modes: 0b%b", compMode) + } + if compMode&3 != 0 { + return errors.New("corrupt block: reserved bits not zero") + } + for i := uint(0); i < 3; i++ { + mode := seqCompMode((compMode >> (6 - i*2)) & 3) + if debugDecoder { + println("Table", tableIndex(i), "is", mode) + } + var seq *sequenceDec + switch tableIndex(i) { + case tableLiteralLengths: + seq = &seqs.litLengths + case tableOffsets: + seq = &seqs.offsets + case tableMatchLengths: + seq = &seqs.matchLengths + default: + panic("unknown table") + } + switch mode { + case compModePredefined: + if seq.fse != nil && !seq.fse.preDefined { + fseDecoderPool.Put(seq.fse) + } + seq.fse = &fsePredef[i] + case compModeRLE: + if br.remain() < 1 { + return ErrBlockTooSmall + } + v := br.Uint8() + br.advance(1) + if seq.fse == nil || seq.fse.preDefined { + seq.fse = fseDecoderPool.Get().(*fseDecoder) + } + symb, err := decSymbolValue(v, symbolTableX[i]) + if err != nil { + printf("RLE Transform table (%v) error: %v", tableIndex(i), err) + return err + } + seq.fse.setRLE(symb) + if debugDecoder { + printf("RLE set to 0x%x, code: %v", symb, v) + } + case compModeFSE: + println("Reading table for", tableIndex(i)) + if seq.fse == nil || seq.fse.preDefined { + seq.fse = fseDecoderPool.Get().(*fseDecoder) + } + err := seq.fse.readNCount(&br, uint16(maxTableSymbol[i])) + if err != nil { + println("Read table error:", err) + return err + } + err = seq.fse.transform(symbolTableX[i]) + if err != nil { + println("Transform table error:", err) + return err + } + if debugDecoder { + println("Read table ok", "symbolLen:", seq.fse.symbolLen) + } + case compModeRepeat: + seq.repeat = true + } + if br.overread() { + return io.ErrUnexpectedEOF + } + } + in = br.unread() + } + if debugDecoder { + println("Literals:", len(seqs.literals), "hash:", xxhash.Sum64(seqs.literals), "and", seqs.nSeqs, "sequences.") + } + + if nSeqs == 0 { + if len(b.sequence) > 0 { + b.sequence = b.sequence[:0] + } + return nil + } + br := seqs.br + if br == nil { + br = &bitReader{} + } + if err := br.init(in); err != nil { + return err + } + + if err := seqs.initialize(br, hist, b.dst); err != nil { + println("initializing sequences:", err) + return err + } + // Extract blocks... + if false && hist.dict == nil { + fatalErr := func(err error) { + if err != nil { + panic(err) + } + } + fn := fmt.Sprintf("n-%d-lits-%d-prev-%d-%d-%d-win-%d.blk", hist.decoders.nSeqs, len(hist.decoders.literals), hist.recentOffsets[0], hist.recentOffsets[1], hist.recentOffsets[2], hist.windowSize) + var buf bytes.Buffer + fatalErr(binary.Write(&buf, binary.LittleEndian, hist.decoders.litLengths.fse)) + fatalErr(binary.Write(&buf, binary.LittleEndian, hist.decoders.matchLengths.fse)) + fatalErr(binary.Write(&buf, binary.LittleEndian, hist.decoders.offsets.fse)) + buf.Write(in) + os.WriteFile(filepath.Join("testdata", "seqs", fn), buf.Bytes(), os.ModePerm) + } + + return nil +} + +func (b *blockDec) decodeSequences(hist *history) error { + if cap(b.sequence) < hist.decoders.nSeqs { + if b.lowMem { + b.sequence = make([]seqVals, 0, hist.decoders.nSeqs) + } else { + b.sequence = make([]seqVals, 0, 0x7F00+0xffff) + } + } + b.sequence = b.sequence[:hist.decoders.nSeqs] + if hist.decoders.nSeqs == 0 { + hist.decoders.seqSize = len(hist.decoders.literals) + return nil + } + hist.decoders.windowSize = hist.windowSize + hist.decoders.prevOffset = hist.recentOffsets + + err := hist.decoders.decode(b.sequence) + hist.recentOffsets = hist.decoders.prevOffset + return err +} + +func (b *blockDec) executeSequences(hist *history) error { + hbytes := hist.b + if len(hbytes) > hist.windowSize { + hbytes = hbytes[len(hbytes)-hist.windowSize:] + // We do not need history anymore. + if hist.dict != nil { + hist.dict.content = nil + } + } + hist.decoders.windowSize = hist.windowSize + hist.decoders.out = b.dst[:0] + err := hist.decoders.execute(b.sequence, hbytes) + if err != nil { + return err + } + return b.updateHistory(hist) +} + +func (b *blockDec) updateHistory(hist *history) error { + if len(b.data) > maxCompressedBlockSize { + return fmt.Errorf("compressed block size too large (%d)", len(b.data)) + } + // Set output and release references. + b.dst = hist.decoders.out + hist.recentOffsets = hist.decoders.prevOffset + + if b.Last { + // if last block we don't care about history. + println("Last block, no history returned") + hist.b = hist.b[:0] + return nil + } else { + hist.append(b.dst) + if debugDecoder { + println("Finished block with ", len(b.sequence), "sequences. Added", len(b.dst), "to history, now length", len(hist.b)) + } + } + hist.decoders.out, hist.decoders.literals = nil, nil + + return nil +} diff --git a/vendor/github.com/klauspost/compress/zstd/blockenc.go b/vendor/github.com/klauspost/compress/zstd/blockenc.go new file mode 100644 index 000000000..32a7f401d --- /dev/null +++ b/vendor/github.com/klauspost/compress/zstd/blockenc.go @@ -0,0 +1,909 @@ +// Copyright 2019+ Klaus Post. All rights reserved. +// License information can be found in the LICENSE file. +// Based on work by Yann Collet, released under BSD License. + +package zstd + +import ( + "errors" + "fmt" + "math" + "math/bits" + + "github.com/klauspost/compress/huff0" +) + +type blockEnc struct { + size int + literals []byte + sequences []seq + coders seqCoders + litEnc *huff0.Scratch + dictLitEnc *huff0.Scratch + wr bitWriter + + extraLits int + output []byte + recentOffsets [3]uint32 + prevRecentOffsets [3]uint32 + + last bool + lowMem bool +} + +// init should be used once the block has been created. +// If called more than once, the effect is the same as calling reset. +func (b *blockEnc) init() { + if b.lowMem { + // 1K literals + if cap(b.literals) < 1<<10 { + b.literals = make([]byte, 0, 1<<10) + } + const defSeqs = 20 + if cap(b.sequences) < defSeqs { + b.sequences = make([]seq, 0, defSeqs) + } + // 1K + if cap(b.output) < 1<<10 { + b.output = make([]byte, 0, 1<<10) + } + } else { + if cap(b.literals) < maxCompressedBlockSize { + b.literals = make([]byte, 0, maxCompressedBlockSize) + } + const defSeqs = 2000 + if cap(b.sequences) < defSeqs { + b.sequences = make([]seq, 0, defSeqs) + } + if cap(b.output) < maxCompressedBlockSize { + b.output = make([]byte, 0, maxCompressedBlockSize) + } + } + + if b.coders.mlEnc == nil { + b.coders.mlEnc = &fseEncoder{} + b.coders.mlPrev = &fseEncoder{} + b.coders.ofEnc = &fseEncoder{} + b.coders.ofPrev = &fseEncoder{} + b.coders.llEnc = &fseEncoder{} + b.coders.llPrev = &fseEncoder{} + } + b.litEnc = &huff0.Scratch{WantLogLess: 4} + b.reset(nil) +} + +// initNewEncode can be used to reset offsets and encoders to the initial state. +func (b *blockEnc) initNewEncode() { + b.recentOffsets = [3]uint32{1, 4, 8} + b.litEnc.Reuse = huff0.ReusePolicyNone + b.coders.setPrev(nil, nil, nil) +} + +// reset will reset the block for a new encode, but in the same stream, +// meaning that state will be carried over, but the block content is reset. +// If a previous block is provided, the recent offsets are carried over. +func (b *blockEnc) reset(prev *blockEnc) { + b.extraLits = 0 + b.literals = b.literals[:0] + b.size = 0 + b.sequences = b.sequences[:0] + b.output = b.output[:0] + b.last = false + if prev != nil { + b.recentOffsets = prev.prevRecentOffsets + } + b.dictLitEnc = nil +} + +// reset will reset the block for a new encode, but in the same stream, +// meaning that state will be carried over, but the block content is reset. +// If a previous block is provided, the recent offsets are carried over. +func (b *blockEnc) swapEncoders(prev *blockEnc) { + b.coders.swap(&prev.coders) + b.litEnc, prev.litEnc = prev.litEnc, b.litEnc +} + +// blockHeader contains the information for a block header. +type blockHeader uint32 + +// setLast sets the 'last' indicator on a block. +func (h *blockHeader) setLast(b bool) { + if b { + *h = *h | 1 + } else { + const mask = (1 << 24) - 2 + *h = *h & mask + } +} + +// setSize will store the compressed size of a block. +func (h *blockHeader) setSize(v uint32) { + const mask = 7 + *h = (*h)&mask | blockHeader(v<<3) +} + +// setType sets the block type. +func (h *blockHeader) setType(t blockType) { + const mask = 1 | (((1 << 24) - 1) ^ 7) + *h = (*h & mask) | blockHeader(t<<1) +} + +// appendTo will append the block header to a slice. +func (h blockHeader) appendTo(b []byte) []byte { + return append(b, uint8(h), uint8(h>>8), uint8(h>>16)) +} + +// String returns a string representation of the block. +func (h blockHeader) String() string { + return fmt.Sprintf("Type: %d, Size: %d, Last:%t", (h>>1)&3, h>>3, h&1 == 1) +} + +// literalsHeader contains literals header information. +type literalsHeader uint64 + +// setType can be used to set the type of literal block. +func (h *literalsHeader) setType(t literalsBlockType) { + const mask = math.MaxUint64 - 3 + *h = (*h & mask) | literalsHeader(t) +} + +// setSize can be used to set a single size, for uncompressed and RLE content. +func (h *literalsHeader) setSize(regenLen int) { + inBits := bits.Len32(uint32(regenLen)) + // Only retain 2 bits + const mask = 3 + lh := uint64(*h & mask) + switch { + case inBits < 5: + lh |= (uint64(regenLen) << 3) | (1 << 60) + if debugEncoder { + got := int(lh>>3) & 0xff + if got != regenLen { + panic(fmt.Sprint("litRegenSize = ", regenLen, "(want) != ", got, "(got)")) + } + } + case inBits < 12: + lh |= (1 << 2) | (uint64(regenLen) << 4) | (2 << 60) + case inBits < 20: + lh |= (3 << 2) | (uint64(regenLen) << 4) | (3 << 60) + default: + panic(fmt.Errorf("internal error: block too big (%d)", regenLen)) + } + *h = literalsHeader(lh) +} + +// setSizes will set the size of a compressed literals section and the input length. +func (h *literalsHeader) setSizes(compLen, inLen int, single bool) { + compBits, inBits := bits.Len32(uint32(compLen)), bits.Len32(uint32(inLen)) + // Only retain 2 bits + const mask = 3 + lh := uint64(*h & mask) + switch { + case compBits <= 10 && inBits <= 10: + if !single { + lh |= 1 << 2 + } + lh |= (uint64(inLen) << 4) | (uint64(compLen) << (10 + 4)) | (3 << 60) + if debugEncoder { + const mmask = (1 << 24) - 1 + n := (lh >> 4) & mmask + if int(n&1023) != inLen { + panic(fmt.Sprint("regensize:", int(n&1023), "!=", inLen, inBits)) + } + if int(n>>10) != compLen { + panic(fmt.Sprint("compsize:", int(n>>10), "!=", compLen, compBits)) + } + } + case compBits <= 14 && inBits <= 14: + lh |= (2 << 2) | (uint64(inLen) << 4) | (uint64(compLen) << (14 + 4)) | (4 << 60) + if single { + panic("single stream used with more than 10 bits length.") + } + case compBits <= 18 && inBits <= 18: + lh |= (3 << 2) | (uint64(inLen) << 4) | (uint64(compLen) << (18 + 4)) | (5 << 60) + if single { + panic("single stream used with more than 10 bits length.") + } + default: + panic("internal error: block too big") + } + *h = literalsHeader(lh) +} + +// appendTo will append the literals header to a byte slice. +func (h literalsHeader) appendTo(b []byte) []byte { + size := uint8(h >> 60) + switch size { + case 1: + b = append(b, uint8(h)) + case 2: + b = append(b, uint8(h), uint8(h>>8)) + case 3: + b = append(b, uint8(h), uint8(h>>8), uint8(h>>16)) + case 4: + b = append(b, uint8(h), uint8(h>>8), uint8(h>>16), uint8(h>>24)) + case 5: + b = append(b, uint8(h), uint8(h>>8), uint8(h>>16), uint8(h>>24), uint8(h>>32)) + default: + panic(fmt.Errorf("internal error: literalsHeader has invalid size (%d)", size)) + } + return b +} + +// size returns the output size with currently set values. +func (h literalsHeader) size() int { + return int(h >> 60) +} + +func (h literalsHeader) String() string { + return fmt.Sprintf("Type: %d, SizeFormat: %d, Size: 0x%d, Bytes:%d", literalsBlockType(h&3), (h>>2)&3, h&((1<<60)-1)>>4, h>>60) +} + +// pushOffsets will push the recent offsets to the backup store. +func (b *blockEnc) pushOffsets() { + b.prevRecentOffsets = b.recentOffsets +} + +// pushOffsets will push the recent offsets to the backup store. +func (b *blockEnc) popOffsets() { + b.recentOffsets = b.prevRecentOffsets +} + +// matchOffset will adjust recent offsets and return the adjusted one, +// if it matches a previous offset. +func (b *blockEnc) matchOffset(offset, lits uint32) uint32 { + // Check if offset is one of the recent offsets. + // Adjusts the output offset accordingly. + // Gives a tiny bit of compression, typically around 1%. + if true { + if lits > 0 { + switch offset { + case b.recentOffsets[0]: + offset = 1 + case b.recentOffsets[1]: + b.recentOffsets[1] = b.recentOffsets[0] + b.recentOffsets[0] = offset + offset = 2 + case b.recentOffsets[2]: + b.recentOffsets[2] = b.recentOffsets[1] + b.recentOffsets[1] = b.recentOffsets[0] + b.recentOffsets[0] = offset + offset = 3 + default: + b.recentOffsets[2] = b.recentOffsets[1] + b.recentOffsets[1] = b.recentOffsets[0] + b.recentOffsets[0] = offset + offset += 3 + } + } else { + switch offset { + case b.recentOffsets[1]: + b.recentOffsets[1] = b.recentOffsets[0] + b.recentOffsets[0] = offset + offset = 1 + case b.recentOffsets[2]: + b.recentOffsets[2] = b.recentOffsets[1] + b.recentOffsets[1] = b.recentOffsets[0] + b.recentOffsets[0] = offset + offset = 2 + case b.recentOffsets[0] - 1: + b.recentOffsets[2] = b.recentOffsets[1] + b.recentOffsets[1] = b.recentOffsets[0] + b.recentOffsets[0] = offset + offset = 3 + default: + b.recentOffsets[2] = b.recentOffsets[1] + b.recentOffsets[1] = b.recentOffsets[0] + b.recentOffsets[0] = offset + offset += 3 + } + } + } else { + offset += 3 + } + return offset +} + +// encodeRaw can be used to set the output to a raw representation of supplied bytes. +func (b *blockEnc) encodeRaw(a []byte) { + var bh blockHeader + bh.setLast(b.last) + bh.setSize(uint32(len(a))) + bh.setType(blockTypeRaw) + b.output = bh.appendTo(b.output[:0]) + b.output = append(b.output, a...) + if debugEncoder { + println("Adding RAW block, length", len(a), "last:", b.last) + } +} + +// encodeRaw can be used to set the output to a raw representation of supplied bytes. +func (b *blockEnc) encodeRawTo(dst, src []byte) []byte { + var bh blockHeader + bh.setLast(b.last) + bh.setSize(uint32(len(src))) + bh.setType(blockTypeRaw) + dst = bh.appendTo(dst) + dst = append(dst, src...) + if debugEncoder { + println("Adding RAW block, length", len(src), "last:", b.last) + } + return dst +} + +// encodeLits can be used if the block is only litLen. +func (b *blockEnc) encodeLits(lits []byte, raw bool) error { + var bh blockHeader + bh.setLast(b.last) + bh.setSize(uint32(len(lits))) + + // Don't compress extremely small blocks + if len(lits) < 8 || (len(lits) < 32 && b.dictLitEnc == nil) || raw { + if debugEncoder { + println("Adding RAW block, length", len(lits), "last:", b.last) + } + bh.setType(blockTypeRaw) + b.output = bh.appendTo(b.output) + b.output = append(b.output, lits...) + return nil + } + + var ( + out []byte + reUsed, single bool + err error + ) + if b.dictLitEnc != nil { + b.litEnc.TransferCTable(b.dictLitEnc) + b.litEnc.Reuse = huff0.ReusePolicyAllow + b.dictLitEnc = nil + } + if len(lits) >= 1024 { + // Use 4 Streams. + out, reUsed, err = huff0.Compress4X(lits, b.litEnc) + } else if len(lits) > 16 { + // Use 1 stream + single = true + out, reUsed, err = huff0.Compress1X(lits, b.litEnc) + } else { + err = huff0.ErrIncompressible + } + if err == nil && len(out)+5 > len(lits) { + // If we are close, we may still be worse or equal to raw. + var lh literalsHeader + lh.setSizes(len(out), len(lits), single) + if len(out)+lh.size() >= len(lits) { + err = huff0.ErrIncompressible + } + } + switch err { + case huff0.ErrIncompressible: + if debugEncoder { + println("Adding RAW block, length", len(lits), "last:", b.last) + } + bh.setType(blockTypeRaw) + b.output = bh.appendTo(b.output) + b.output = append(b.output, lits...) + return nil + case huff0.ErrUseRLE: + if debugEncoder { + println("Adding RLE block, length", len(lits)) + } + bh.setType(blockTypeRLE) + b.output = bh.appendTo(b.output) + b.output = append(b.output, lits[0]) + return nil + case nil: + default: + return err + } + // Compressed... + // Now, allow reuse + b.litEnc.Reuse = huff0.ReusePolicyAllow + bh.setType(blockTypeCompressed) + var lh literalsHeader + if reUsed { + if debugEncoder { + println("Reused tree, compressed to", len(out)) + } + lh.setType(literalsBlockTreeless) + } else { + if debugEncoder { + println("New tree, compressed to", len(out), "tree size:", len(b.litEnc.OutTable)) + } + lh.setType(literalsBlockCompressed) + } + // Set sizes + lh.setSizes(len(out), len(lits), single) + bh.setSize(uint32(len(out) + lh.size() + 1)) + + // Write block headers. + b.output = bh.appendTo(b.output) + b.output = lh.appendTo(b.output) + // Add compressed data. + b.output = append(b.output, out...) + // No sequences. + b.output = append(b.output, 0) + return nil +} + +// encodeRLE will encode an RLE block. +func (b *blockEnc) encodeRLE(val byte, length uint32) { + var bh blockHeader + bh.setLast(b.last) + bh.setSize(length) + bh.setType(blockTypeRLE) + b.output = bh.appendTo(b.output) + b.output = append(b.output, val) +} + +// fuzzFseEncoder can be used to fuzz the FSE encoder. +func fuzzFseEncoder(data []byte) int { + if len(data) > maxSequences || len(data) < 2 { + return 0 + } + enc := fseEncoder{} + hist := enc.Histogram() + maxSym := uint8(0) + for i, v := range data { + v = v & 63 + data[i] = v + hist[v]++ + if v > maxSym { + maxSym = v + } + } + if maxSym == 0 { + // All 0 + return 0 + } + maxCount := func(a []uint32) int { + var max uint32 + for _, v := range a { + if v > max { + max = v + } + } + return int(max) + } + cnt := maxCount(hist[:maxSym]) + if cnt == len(data) { + // RLE + return 0 + } + enc.HistogramFinished(maxSym, cnt) + err := enc.normalizeCount(len(data)) + if err != nil { + return 0 + } + _, err = enc.writeCount(nil) + if err != nil { + panic(err) + } + return 1 +} + +// encode will encode the block and append the output in b.output. +// Previous offset codes must be pushed if more blocks are expected. +func (b *blockEnc) encode(org []byte, raw, rawAllLits bool) error { + if len(b.sequences) == 0 { + return b.encodeLits(b.literals, rawAllLits) + } + if len(b.sequences) == 1 && len(org) > 0 && len(b.literals) <= 1 { + // Check common RLE cases. + seq := b.sequences[0] + if seq.litLen == uint32(len(b.literals)) && seq.offset-3 == 1 { + // Offset == 1 and 0 or 1 literals. + b.encodeRLE(org[0], b.sequences[0].matchLen+zstdMinMatch+seq.litLen) + return nil + } + } + + // We want some difference to at least account for the headers. + saved := b.size - len(b.literals) - (b.size >> 6) + if saved < 16 { + if org == nil { + return errIncompressible + } + b.popOffsets() + return b.encodeLits(org, rawAllLits) + } + + var bh blockHeader + var lh literalsHeader + bh.setLast(b.last) + bh.setType(blockTypeCompressed) + // Store offset of the block header. Needed when we know the size. + bhOffset := len(b.output) + b.output = bh.appendTo(b.output) + + var ( + out []byte + reUsed, single bool + err error + ) + if b.dictLitEnc != nil { + b.litEnc.TransferCTable(b.dictLitEnc) + b.litEnc.Reuse = huff0.ReusePolicyAllow + b.dictLitEnc = nil + } + if len(b.literals) >= 1024 && !raw { + // Use 4 Streams. + out, reUsed, err = huff0.Compress4X(b.literals, b.litEnc) + } else if len(b.literals) > 16 && !raw { + // Use 1 stream + single = true + out, reUsed, err = huff0.Compress1X(b.literals, b.litEnc) + } else { + err = huff0.ErrIncompressible + } + + if err == nil && len(out)+5 > len(b.literals) { + // If we are close, we may still be worse or equal to raw. + var lh literalsHeader + lh.setSize(len(b.literals)) + szRaw := lh.size() + lh.setSizes(len(out), len(b.literals), single) + szComp := lh.size() + if len(out)+szComp >= len(b.literals)+szRaw { + err = huff0.ErrIncompressible + } + } + switch err { + case huff0.ErrIncompressible: + lh.setType(literalsBlockRaw) + lh.setSize(len(b.literals)) + b.output = lh.appendTo(b.output) + b.output = append(b.output, b.literals...) + if debugEncoder { + println("Adding literals RAW, length", len(b.literals)) + } + case huff0.ErrUseRLE: + lh.setType(literalsBlockRLE) + lh.setSize(len(b.literals)) + b.output = lh.appendTo(b.output) + b.output = append(b.output, b.literals[0]) + if debugEncoder { + println("Adding literals RLE") + } + case nil: + // Compressed litLen... + if reUsed { + if debugEncoder { + println("reused tree") + } + lh.setType(literalsBlockTreeless) + } else { + if debugEncoder { + println("new tree, size:", len(b.litEnc.OutTable)) + } + lh.setType(literalsBlockCompressed) + if debugEncoder { + _, _, err := huff0.ReadTable(out, nil) + if err != nil { + panic(err) + } + } + } + lh.setSizes(len(out), len(b.literals), single) + if debugEncoder { + printf("Compressed %d literals to %d bytes", len(b.literals), len(out)) + println("Adding literal header:", lh) + } + b.output = lh.appendTo(b.output) + b.output = append(b.output, out...) + b.litEnc.Reuse = huff0.ReusePolicyAllow + if debugEncoder { + println("Adding literals compressed") + } + default: + if debugEncoder { + println("Adding literals ERROR:", err) + } + return err + } + // Sequence compression + + // Write the number of sequences + switch { + case len(b.sequences) < 128: + b.output = append(b.output, uint8(len(b.sequences))) + case len(b.sequences) < 0x7f00: // TODO: this could be wrong + n := len(b.sequences) + b.output = append(b.output, 128+uint8(n>>8), uint8(n)) + default: + n := len(b.sequences) - 0x7f00 + b.output = append(b.output, 255, uint8(n), uint8(n>>8)) + } + if debugEncoder { + println("Encoding", len(b.sequences), "sequences") + } + b.genCodes() + llEnc := b.coders.llEnc + ofEnc := b.coders.ofEnc + mlEnc := b.coders.mlEnc + err = llEnc.normalizeCount(len(b.sequences)) + if err != nil { + return err + } + err = ofEnc.normalizeCount(len(b.sequences)) + if err != nil { + return err + } + err = mlEnc.normalizeCount(len(b.sequences)) + if err != nil { + return err + } + + // Choose the best compression mode for each type. + // Will evaluate the new vs predefined and previous. + chooseComp := func(cur, prev, preDef *fseEncoder) (*fseEncoder, seqCompMode) { + // See if predefined/previous is better + hist := cur.count[:cur.symbolLen] + nSize := cur.approxSize(hist) + cur.maxHeaderSize() + predefSize := preDef.approxSize(hist) + prevSize := prev.approxSize(hist) + + // Add a small penalty for new encoders. + // Don't bother with extremely small (<2 byte gains). + nSize = nSize + (nSize+2*8*16)>>4 + switch { + case predefSize <= prevSize && predefSize <= nSize || forcePreDef: + if debugEncoder { + println("Using predefined", predefSize>>3, "<=", nSize>>3) + } + return preDef, compModePredefined + case prevSize <= nSize: + if debugEncoder { + println("Using previous", prevSize>>3, "<=", nSize>>3) + } + return prev, compModeRepeat + default: + if debugEncoder { + println("Using new, predef", predefSize>>3, ". previous:", prevSize>>3, ">", nSize>>3, "header max:", cur.maxHeaderSize()>>3, "bytes") + println("tl:", cur.actualTableLog, "symbolLen:", cur.symbolLen, "norm:", cur.norm[:cur.symbolLen], "hist", cur.count[:cur.symbolLen]) + } + return cur, compModeFSE + } + } + + // Write compression mode + var mode uint8 + if llEnc.useRLE { + mode |= uint8(compModeRLE) << 6 + llEnc.setRLE(b.sequences[0].llCode) + if debugEncoder { + println("llEnc.useRLE") + } + } else { + var m seqCompMode + llEnc, m = chooseComp(llEnc, b.coders.llPrev, &fsePredefEnc[tableLiteralLengths]) + mode |= uint8(m) << 6 + } + if ofEnc.useRLE { + mode |= uint8(compModeRLE) << 4 + ofEnc.setRLE(b.sequences[0].ofCode) + if debugEncoder { + println("ofEnc.useRLE") + } + } else { + var m seqCompMode + ofEnc, m = chooseComp(ofEnc, b.coders.ofPrev, &fsePredefEnc[tableOffsets]) + mode |= uint8(m) << 4 + } + + if mlEnc.useRLE { + mode |= uint8(compModeRLE) << 2 + mlEnc.setRLE(b.sequences[0].mlCode) + if debugEncoder { + println("mlEnc.useRLE, code: ", b.sequences[0].mlCode, "value", b.sequences[0].matchLen) + } + } else { + var m seqCompMode + mlEnc, m = chooseComp(mlEnc, b.coders.mlPrev, &fsePredefEnc[tableMatchLengths]) + mode |= uint8(m) << 2 + } + b.output = append(b.output, mode) + if debugEncoder { + printf("Compression modes: 0b%b", mode) + } + b.output, err = llEnc.writeCount(b.output) + if err != nil { + return err + } + start := len(b.output) + b.output, err = ofEnc.writeCount(b.output) + if err != nil { + return err + } + if false { + println("block:", b.output[start:], "tablelog", ofEnc.actualTableLog, "maxcount:", ofEnc.maxCount) + fmt.Printf("selected TableLog: %d, Symbol length: %d\n", ofEnc.actualTableLog, ofEnc.symbolLen) + for i, v := range ofEnc.norm[:ofEnc.symbolLen] { + fmt.Printf("%3d: %5d -> %4d \n", i, ofEnc.count[i], v) + } + } + b.output, err = mlEnc.writeCount(b.output) + if err != nil { + return err + } + + // Maybe in block? + wr := &b.wr + wr.reset(b.output) + + var ll, of, ml cState + + // Current sequence + seq := len(b.sequences) - 1 + s := b.sequences[seq] + llEnc.setBits(llBitsTable[:]) + mlEnc.setBits(mlBitsTable[:]) + ofEnc.setBits(nil) + + llTT, ofTT, mlTT := llEnc.ct.symbolTT[:256], ofEnc.ct.symbolTT[:256], mlEnc.ct.symbolTT[:256] + + // We have 3 bounds checks here (and in the loop). + // Since we are iterating backwards it is kinda hard to avoid. + llB, ofB, mlB := llTT[s.llCode], ofTT[s.ofCode], mlTT[s.mlCode] + ll.init(wr, &llEnc.ct, llB) + of.init(wr, &ofEnc.ct, ofB) + wr.flush32() + ml.init(wr, &mlEnc.ct, mlB) + + // Each of these lookups also generates a bounds check. + wr.addBits32NC(s.litLen, llB.outBits) + wr.addBits32NC(s.matchLen, mlB.outBits) + wr.flush32() + wr.addBits32NC(s.offset, ofB.outBits) + if debugSequences { + println("Encoded seq", seq, s, "codes:", s.llCode, s.mlCode, s.ofCode, "states:", ll.state, ml.state, of.state, "bits:", llB, mlB, ofB) + } + seq-- + // Store sequences in reverse... + for seq >= 0 { + s = b.sequences[seq] + + ofB := ofTT[s.ofCode] + wr.flush32() // tablelog max is below 8 for each, so it will fill max 24 bits. + //of.encode(ofB) + nbBitsOut := (uint32(of.state) + ofB.deltaNbBits) >> 16 + dstState := int32(of.state>>(nbBitsOut&15)) + int32(ofB.deltaFindState) + wr.addBits16NC(of.state, uint8(nbBitsOut)) + of.state = of.stateTable[dstState] + + // Accumulate extra bits. + outBits := ofB.outBits & 31 + extraBits := uint64(s.offset & bitMask32[outBits]) + extraBitsN := outBits + + mlB := mlTT[s.mlCode] + //ml.encode(mlB) + nbBitsOut = (uint32(ml.state) + mlB.deltaNbBits) >> 16 + dstState = int32(ml.state>>(nbBitsOut&15)) + int32(mlB.deltaFindState) + wr.addBits16NC(ml.state, uint8(nbBitsOut)) + ml.state = ml.stateTable[dstState] + + outBits = mlB.outBits & 31 + extraBits = extraBits<> 16 + dstState = int32(ll.state>>(nbBitsOut&15)) + int32(llB.deltaFindState) + wr.addBits16NC(ll.state, uint8(nbBitsOut)) + ll.state = ll.stateTable[dstState] + + outBits = llB.outBits & 31 + extraBits = extraBits<= b.size { + // Discard and encode as raw block. + b.output = b.encodeRawTo(b.output[:bhOffset], org) + b.popOffsets() + b.litEnc.Reuse = huff0.ReusePolicyNone + return nil + } + + // Size is output minus block header. + bh.setSize(uint32(len(b.output)-bhOffset) - 3) + if debugEncoder { + println("Rewriting block header", bh) + } + _ = bh.appendTo(b.output[bhOffset:bhOffset]) + b.coders.setPrev(llEnc, mlEnc, ofEnc) + return nil +} + +var errIncompressible = errors.New("incompressible") + +func (b *blockEnc) genCodes() { + if len(b.sequences) == 0 { + // nothing to do + return + } + if len(b.sequences) > math.MaxUint16 { + panic("can only encode up to 64K sequences") + } + // No bounds checks after here: + llH := b.coders.llEnc.Histogram() + ofH := b.coders.ofEnc.Histogram() + mlH := b.coders.mlEnc.Histogram() + for i := range llH { + llH[i] = 0 + } + for i := range ofH { + ofH[i] = 0 + } + for i := range mlH { + mlH[i] = 0 + } + + var llMax, ofMax, mlMax uint8 + for i := range b.sequences { + seq := &b.sequences[i] + v := llCode(seq.litLen) + seq.llCode = v + llH[v]++ + if v > llMax { + llMax = v + } + + v = ofCode(seq.offset) + seq.ofCode = v + ofH[v]++ + if v > ofMax { + ofMax = v + } + + v = mlCode(seq.matchLen) + seq.mlCode = v + mlH[v]++ + if v > mlMax { + mlMax = v + if debugAsserts && mlMax > maxMatchLengthSymbol { + panic(fmt.Errorf("mlMax > maxMatchLengthSymbol (%d), matchlen: %d", mlMax, seq.matchLen)) + } + } + } + maxCount := func(a []uint32) int { + var max uint32 + for _, v := range a { + if v > max { + max = v + } + } + return int(max) + } + if debugAsserts && mlMax > maxMatchLengthSymbol { + panic(fmt.Errorf("mlMax > maxMatchLengthSymbol (%d)", mlMax)) + } + if debugAsserts && ofMax > maxOffsetBits { + panic(fmt.Errorf("ofMax > maxOffsetBits (%d)", ofMax)) + } + if debugAsserts && llMax > maxLiteralLengthSymbol { + panic(fmt.Errorf("llMax > maxLiteralLengthSymbol (%d)", llMax)) + } + + b.coders.mlEnc.HistogramFinished(mlMax, maxCount(mlH[:mlMax+1])) + b.coders.ofEnc.HistogramFinished(ofMax, maxCount(ofH[:ofMax+1])) + b.coders.llEnc.HistogramFinished(llMax, maxCount(llH[:llMax+1])) +} diff --git a/vendor/github.com/klauspost/compress/zstd/blocktype_string.go b/vendor/github.com/klauspost/compress/zstd/blocktype_string.go new file mode 100644 index 000000000..01a01e486 --- /dev/null +++ b/vendor/github.com/klauspost/compress/zstd/blocktype_string.go @@ -0,0 +1,85 @@ +// Code generated by "stringer -type=blockType,literalsBlockType,seqCompMode,tableIndex"; DO NOT EDIT. + +package zstd + +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[blockTypeRaw-0] + _ = x[blockTypeRLE-1] + _ = x[blockTypeCompressed-2] + _ = x[blockTypeReserved-3] +} + +const _blockType_name = "blockTypeRawblockTypeRLEblockTypeCompressedblockTypeReserved" + +var _blockType_index = [...]uint8{0, 12, 24, 43, 60} + +func (i blockType) String() string { + if i >= blockType(len(_blockType_index)-1) { + return "blockType(" + strconv.FormatInt(int64(i), 10) + ")" + } + return _blockType_name[_blockType_index[i]:_blockType_index[i+1]] +} +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[literalsBlockRaw-0] + _ = x[literalsBlockRLE-1] + _ = x[literalsBlockCompressed-2] + _ = x[literalsBlockTreeless-3] +} + +const _literalsBlockType_name = "literalsBlockRawliteralsBlockRLEliteralsBlockCompressedliteralsBlockTreeless" + +var _literalsBlockType_index = [...]uint8{0, 16, 32, 55, 76} + +func (i literalsBlockType) String() string { + if i >= literalsBlockType(len(_literalsBlockType_index)-1) { + return "literalsBlockType(" + strconv.FormatInt(int64(i), 10) + ")" + } + return _literalsBlockType_name[_literalsBlockType_index[i]:_literalsBlockType_index[i+1]] +} +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[compModePredefined-0] + _ = x[compModeRLE-1] + _ = x[compModeFSE-2] + _ = x[compModeRepeat-3] +} + +const _seqCompMode_name = "compModePredefinedcompModeRLEcompModeFSEcompModeRepeat" + +var _seqCompMode_index = [...]uint8{0, 18, 29, 40, 54} + +func (i seqCompMode) String() string { + if i >= seqCompMode(len(_seqCompMode_index)-1) { + return "seqCompMode(" + strconv.FormatInt(int64(i), 10) + ")" + } + return _seqCompMode_name[_seqCompMode_index[i]:_seqCompMode_index[i+1]] +} +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[tableLiteralLengths-0] + _ = x[tableOffsets-1] + _ = x[tableMatchLengths-2] +} + +const _tableIndex_name = "tableLiteralLengthstableOffsetstableMatchLengths" + +var _tableIndex_index = [...]uint8{0, 19, 31, 48} + +func (i tableIndex) String() string { + if i >= tableIndex(len(_tableIndex_index)-1) { + return "tableIndex(" + strconv.FormatInt(int64(i), 10) + ")" + } + return _tableIndex_name[_tableIndex_index[i]:_tableIndex_index[i+1]] +} diff --git a/vendor/github.com/klauspost/compress/zstd/bytebuf.go b/vendor/github.com/klauspost/compress/zstd/bytebuf.go new file mode 100644 index 000000000..55a388553 --- /dev/null +++ b/vendor/github.com/klauspost/compress/zstd/bytebuf.go @@ -0,0 +1,131 @@ +// Copyright 2019+ Klaus Post. All rights reserved. +// License information can be found in the LICENSE file. +// Based on work by Yann Collet, released under BSD License. + +package zstd + +import ( + "fmt" + "io" +) + +type byteBuffer interface { + // Read up to 8 bytes. + // Returns io.ErrUnexpectedEOF if this cannot be satisfied. + readSmall(n int) ([]byte, error) + + // Read >8 bytes. + // MAY use the destination slice. + readBig(n int, dst []byte) ([]byte, error) + + // Read a single byte. + readByte() (byte, error) + + // Skip n bytes. + skipN(n int64) error +} + +// in-memory buffer +type byteBuf []byte + +func (b *byteBuf) readSmall(n int) ([]byte, error) { + if debugAsserts && n > 8 { + panic(fmt.Errorf("small read > 8 (%d). use readBig", n)) + } + bb := *b + if len(bb) < n { + return nil, io.ErrUnexpectedEOF + } + r := bb[:n] + *b = bb[n:] + return r, nil +} + +func (b *byteBuf) readBig(n int, dst []byte) ([]byte, error) { + bb := *b + if len(bb) < n { + return nil, io.ErrUnexpectedEOF + } + r := bb[:n] + *b = bb[n:] + return r, nil +} + +func (b *byteBuf) readByte() (byte, error) { + bb := *b + if len(bb) < 1 { + return 0, io.ErrUnexpectedEOF + } + r := bb[0] + *b = bb[1:] + return r, nil +} + +func (b *byteBuf) skipN(n int64) error { + bb := *b + if n < 0 { + return fmt.Errorf("negative skip (%d) requested", n) + } + if int64(len(bb)) < n { + return io.ErrUnexpectedEOF + } + *b = bb[n:] + return nil +} + +// wrapper around a reader. +type readerWrapper struct { + r io.Reader + tmp [8]byte +} + +func (r *readerWrapper) readSmall(n int) ([]byte, error) { + if debugAsserts && n > 8 { + panic(fmt.Errorf("small read > 8 (%d). use readBig", n)) + } + n2, err := io.ReadFull(r.r, r.tmp[:n]) + // We only really care about the actual bytes read. + if err != nil { + if err == io.EOF { + return nil, io.ErrUnexpectedEOF + } + if debugDecoder { + println("readSmall: got", n2, "want", n, "err", err) + } + return nil, err + } + return r.tmp[:n], nil +} + +func (r *readerWrapper) readBig(n int, dst []byte) ([]byte, error) { + if cap(dst) < n { + dst = make([]byte, n) + } + n2, err := io.ReadFull(r.r, dst[:n]) + if err == io.EOF && n > 0 { + err = io.ErrUnexpectedEOF + } + return dst[:n2], err +} + +func (r *readerWrapper) readByte() (byte, error) { + n2, err := io.ReadFull(r.r, r.tmp[:1]) + if err != nil { + if err == io.EOF { + err = io.ErrUnexpectedEOF + } + return 0, err + } + if n2 != 1 { + return 0, io.ErrUnexpectedEOF + } + return r.tmp[0], nil +} + +func (r *readerWrapper) skipN(n int64) error { + n2, err := io.CopyN(io.Discard, r.r, n) + if n2 != n { + err = io.ErrUnexpectedEOF + } + return err +} diff --git a/vendor/github.com/klauspost/compress/zstd/bytereader.go b/vendor/github.com/klauspost/compress/zstd/bytereader.go new file mode 100644 index 000000000..0e59a242d --- /dev/null +++ b/vendor/github.com/klauspost/compress/zstd/bytereader.go @@ -0,0 +1,82 @@ +// Copyright 2019+ Klaus Post. All rights reserved. +// License information can be found in the LICENSE file. +// Based on work by Yann Collet, released under BSD License. + +package zstd + +// byteReader provides a byte reader that reads +// little endian values from a byte stream. +// The input stream is manually advanced. +// The reader performs no bounds checks. +type byteReader struct { + b []byte + off int +} + +// advance the stream b n bytes. +func (b *byteReader) advance(n uint) { + b.off += int(n) +} + +// overread returns whether we have advanced too far. +func (b *byteReader) overread() bool { + return b.off > len(b.b) +} + +// Int32 returns a little endian int32 starting at current offset. +func (b byteReader) Int32() int32 { + b2 := b.b[b.off:] + b2 = b2[:4] + v3 := int32(b2[3]) + v2 := int32(b2[2]) + v1 := int32(b2[1]) + v0 := int32(b2[0]) + return v0 | (v1 << 8) | (v2 << 16) | (v3 << 24) +} + +// Uint8 returns the next byte +func (b *byteReader) Uint8() uint8 { + v := b.b[b.off] + return v +} + +// Uint32 returns a little endian uint32 starting at current offset. +func (b byteReader) Uint32() uint32 { + if r := b.remain(); r < 4 { + // Very rare + v := uint32(0) + for i := 1; i <= r; i++ { + v = (v << 8) | uint32(b.b[len(b.b)-i]) + } + return v + } + b2 := b.b[b.off:] + b2 = b2[:4] + v3 := uint32(b2[3]) + v2 := uint32(b2[2]) + v1 := uint32(b2[1]) + v0 := uint32(b2[0]) + return v0 | (v1 << 8) | (v2 << 16) | (v3 << 24) +} + +// Uint32NC returns a little endian uint32 starting at current offset. +// The caller must be sure if there are at least 4 bytes left. +func (b byteReader) Uint32NC() uint32 { + b2 := b.b[b.off:] + b2 = b2[:4] + v3 := uint32(b2[3]) + v2 := uint32(b2[2]) + v1 := uint32(b2[1]) + v0 := uint32(b2[0]) + return v0 | (v1 << 8) | (v2 << 16) | (v3 << 24) +} + +// unread returns the unread portion of the input. +func (b byteReader) unread() []byte { + return b.b[b.off:] +} + +// remain will return the number of bytes remaining. +func (b byteReader) remain() int { + return len(b.b) - b.off +} diff --git a/vendor/github.com/klauspost/compress/zstd/decodeheader.go b/vendor/github.com/klauspost/compress/zstd/decodeheader.go new file mode 100644 index 000000000..6a5a2988b --- /dev/null +++ b/vendor/github.com/klauspost/compress/zstd/decodeheader.go @@ -0,0 +1,261 @@ +// Copyright 2020+ Klaus Post. All rights reserved. +// License information can be found in the LICENSE file. + +package zstd + +import ( + "encoding/binary" + "errors" + "io" +) + +// HeaderMaxSize is the maximum size of a Frame and Block Header. +// If less is sent to Header.Decode it *may* still contain enough information. +const HeaderMaxSize = 14 + 3 + +// Header contains information about the first frame and block within that. +type Header struct { + // SingleSegment specifies whether the data is to be decompressed into a + // single contiguous memory segment. + // It implies that WindowSize is invalid and that FrameContentSize is valid. + SingleSegment bool + + // WindowSize is the window of data to keep while decoding. + // Will only be set if SingleSegment is false. + WindowSize uint64 + + // Dictionary ID. + // If 0, no dictionary. + DictionaryID uint32 + + // HasFCS specifies whether FrameContentSize has a valid value. + HasFCS bool + + // FrameContentSize is the expected uncompressed size of the entire frame. + FrameContentSize uint64 + + // Skippable will be true if the frame is meant to be skipped. + // This implies that FirstBlock.OK is false. + Skippable bool + + // SkippableID is the user-specific ID for the skippable frame. + // Valid values are between 0 to 15, inclusive. + SkippableID int + + // SkippableSize is the length of the user data to skip following + // the header. + SkippableSize uint32 + + // HeaderSize is the raw size of the frame header. + // + // For normal frames, it includes the size of the magic number and + // the size of the header (per section 3.1.1.1). + // It does not include the size for any data blocks (section 3.1.1.2) nor + // the size for the trailing content checksum. + // + // For skippable frames, this counts the size of the magic number + // along with the size of the size field of the payload. + // It does not include the size of the skippable payload itself. + // The total frame size is the HeaderSize plus the SkippableSize. + HeaderSize int + + // First block information. + FirstBlock struct { + // OK will be set if first block could be decoded. + OK bool + + // Is this the last block of a frame? + Last bool + + // Is the data compressed? + // If true CompressedSize will be populated. + // Unfortunately DecompressedSize cannot be determined + // without decoding the blocks. + Compressed bool + + // DecompressedSize is the expected decompressed size of the block. + // Will be 0 if it cannot be determined. + DecompressedSize int + + // CompressedSize of the data in the block. + // Does not include the block header. + // Will be equal to DecompressedSize if not Compressed. + CompressedSize int + } + + // If set there is a checksum present for the block content. + // The checksum field at the end is always 4 bytes long. + HasCheckSum bool +} + +// Decode the header from the beginning of the stream. +// This will decode the frame header and the first block header if enough bytes are provided. +// It is recommended to provide at least HeaderMaxSize bytes. +// If the frame header cannot be read an error will be returned. +// If there isn't enough input, io.ErrUnexpectedEOF is returned. +// The FirstBlock.OK will indicate if enough information was available to decode the first block header. +func (h *Header) Decode(in []byte) error { + _, err := h.DecodeAndStrip(in) + return err +} + +// DecodeAndStrip will decode the header from the beginning of the stream +// and on success return the remaining bytes. +// This will decode the frame header and the first block header if enough bytes are provided. +// It is recommended to provide at least HeaderMaxSize bytes. +// If the frame header cannot be read an error will be returned. +// If there isn't enough input, io.ErrUnexpectedEOF is returned. +// The FirstBlock.OK will indicate if enough information was available to decode the first block header. +func (h *Header) DecodeAndStrip(in []byte) (remain []byte, err error) { + *h = Header{} + if len(in) < 4 { + return nil, io.ErrUnexpectedEOF + } + h.HeaderSize += 4 + b, in := in[:4], in[4:] + if string(b) != frameMagic { + if string(b[1:4]) != skippableFrameMagic || b[0]&0xf0 != 0x50 { + return nil, ErrMagicMismatch + } + if len(in) < 4 { + return nil, io.ErrUnexpectedEOF + } + h.HeaderSize += 4 + h.Skippable = true + h.SkippableID = int(b[0] & 0xf) + h.SkippableSize = binary.LittleEndian.Uint32(in) + return in[4:], nil + } + + // Read Window_Descriptor + // https://github.com/facebook/zstd/blob/dev/doc/zstd_compression_format.md#window_descriptor + if len(in) < 1 { + return nil, io.ErrUnexpectedEOF + } + fhd, in := in[0], in[1:] + h.HeaderSize++ + h.SingleSegment = fhd&(1<<5) != 0 + h.HasCheckSum = fhd&(1<<2) != 0 + if fhd&(1<<3) != 0 { + return nil, errors.New("reserved bit set on frame header") + } + + if !h.SingleSegment { + if len(in) < 1 { + return nil, io.ErrUnexpectedEOF + } + var wd byte + wd, in = in[0], in[1:] + h.HeaderSize++ + windowLog := 10 + (wd >> 3) + windowBase := uint64(1) << windowLog + windowAdd := (windowBase / 8) * uint64(wd&0x7) + h.WindowSize = windowBase + windowAdd + } + + // Read Dictionary_ID + // https://github.com/facebook/zstd/blob/dev/doc/zstd_compression_format.md#dictionary_id + if size := fhd & 3; size != 0 { + if size == 3 { + size = 4 + } + if len(in) < int(size) { + return nil, io.ErrUnexpectedEOF + } + b, in = in[:size], in[size:] + h.HeaderSize += int(size) + switch len(b) { + case 1: + h.DictionaryID = uint32(b[0]) + case 2: + h.DictionaryID = uint32(b[0]) | (uint32(b[1]) << 8) + case 4: + h.DictionaryID = uint32(b[0]) | (uint32(b[1]) << 8) | (uint32(b[2]) << 16) | (uint32(b[3]) << 24) + } + } + + // Read Frame_Content_Size + // https://github.com/facebook/zstd/blob/dev/doc/zstd_compression_format.md#frame_content_size + var fcsSize int + v := fhd >> 6 + switch v { + case 0: + if h.SingleSegment { + fcsSize = 1 + } + default: + fcsSize = 1 << v + } + + if fcsSize > 0 { + h.HasFCS = true + if len(in) < fcsSize { + return nil, io.ErrUnexpectedEOF + } + b, in = in[:fcsSize], in[fcsSize:] + h.HeaderSize += int(fcsSize) + switch len(b) { + case 1: + h.FrameContentSize = uint64(b[0]) + case 2: + // When FCS_Field_Size is 2, the offset of 256 is added. + h.FrameContentSize = uint64(b[0]) | (uint64(b[1]) << 8) + 256 + case 4: + h.FrameContentSize = uint64(b[0]) | (uint64(b[1]) << 8) | (uint64(b[2]) << 16) | (uint64(b[3]) << 24) + case 8: + d1 := uint32(b[0]) | (uint32(b[1]) << 8) | (uint32(b[2]) << 16) | (uint32(b[3]) << 24) + d2 := uint32(b[4]) | (uint32(b[5]) << 8) | (uint32(b[6]) << 16) | (uint32(b[7]) << 24) + h.FrameContentSize = uint64(d1) | (uint64(d2) << 32) + } + } + + // Frame Header done, we will not fail from now on. + if len(in) < 3 { + return in, nil + } + tmp := in[:3] + bh := uint32(tmp[0]) | (uint32(tmp[1]) << 8) | (uint32(tmp[2]) << 16) + h.FirstBlock.Last = bh&1 != 0 + blockType := blockType((bh >> 1) & 3) + // find size. + cSize := int(bh >> 3) + switch blockType { + case blockTypeReserved: + return in, nil + case blockTypeRLE: + h.FirstBlock.Compressed = true + h.FirstBlock.DecompressedSize = cSize + h.FirstBlock.CompressedSize = 1 + case blockTypeCompressed: + h.FirstBlock.Compressed = true + h.FirstBlock.CompressedSize = cSize + case blockTypeRaw: + h.FirstBlock.DecompressedSize = cSize + h.FirstBlock.CompressedSize = cSize + default: + panic("Invalid block type") + } + + h.FirstBlock.OK = true + return in, nil +} + +// AppendTo will append the encoded header to the dst slice. +// There is no error checking performed on the header values. +func (h *Header) AppendTo(dst []byte) ([]byte, error) { + if h.Skippable { + magic := [4]byte{0x50, 0x2a, 0x4d, 0x18} + magic[0] |= byte(h.SkippableID & 0xf) + dst = append(dst, magic[:]...) + f := h.SkippableSize + return append(dst, uint8(f), uint8(f>>8), uint8(f>>16), uint8(f>>24)), nil + } + f := frameHeader{ + ContentSize: h.FrameContentSize, + WindowSize: uint32(h.WindowSize), + SingleSegment: h.SingleSegment, + Checksum: h.HasCheckSum, + DictID: h.DictionaryID, + } + return f.appendTo(dst), nil +} diff --git a/vendor/github.com/klauspost/compress/zstd/decoder.go b/vendor/github.com/klauspost/compress/zstd/decoder.go new file mode 100644 index 000000000..bbca17234 --- /dev/null +++ b/vendor/github.com/klauspost/compress/zstd/decoder.go @@ -0,0 +1,948 @@ +// Copyright 2019+ Klaus Post. All rights reserved. +// License information can be found in the LICENSE file. +// Based on work by Yann Collet, released under BSD License. + +package zstd + +import ( + "context" + "encoding/binary" + "io" + "sync" + + "github.com/klauspost/compress/zstd/internal/xxhash" +) + +// Decoder provides decoding of zstandard streams. +// The decoder has been designed to operate without allocations after a warmup. +// This means that you should store the decoder for best performance. +// To re-use a stream decoder, use the Reset(r io.Reader) error to switch to another stream. +// A decoder can safely be re-used even if the previous stream failed. +// To release the resources, you must call the Close() function on a decoder. +type Decoder struct { + o decoderOptions + + // Unreferenced decoders, ready for use. + decoders chan *blockDec + + // Current read position used for Reader functionality. + current decoderState + + // sync stream decoding + syncStream struct { + decodedFrame uint64 + br readerWrapper + enabled bool + inFrame bool + dstBuf []byte + } + + frame *frameDec + + // Custom dictionaries. + dicts map[uint32]*dict + + // streamWg is the waitgroup for all streams + streamWg sync.WaitGroup +} + +// decoderState is used for maintaining state when the decoder +// is used for streaming. +type decoderState struct { + // current block being written to stream. + decodeOutput + + // output in order to be written to stream. + output chan decodeOutput + + // cancel remaining output. + cancel context.CancelFunc + + // crc of current frame + crc *xxhash.Digest + + flushed bool +} + +var ( + // Check the interfaces we want to support. + _ = io.WriterTo(&Decoder{}) + _ = io.Reader(&Decoder{}) +) + +// NewReader creates a new decoder. +// A nil Reader can be provided in which case Reset can be used to start a decode. +// +// A Decoder can be used in two modes: +// +// 1) As a stream, or +// 2) For stateless decoding using DecodeAll. +// +// Only a single stream can be decoded concurrently, but the same decoder +// can run multiple concurrent stateless decodes. It is even possible to +// use stateless decodes while a stream is being decoded. +// +// The Reset function can be used to initiate a new stream, which will considerably +// reduce the allocations normally caused by NewReader. +func NewReader(r io.Reader, opts ...DOption) (*Decoder, error) { + initPredefined() + var d Decoder + d.o.setDefault() + for _, o := range opts { + err := o(&d.o) + if err != nil { + return nil, err + } + } + d.current.crc = xxhash.New() + d.current.flushed = true + + if r == nil { + d.current.err = ErrDecoderNilInput + } + + // Transfer option dicts. + d.dicts = make(map[uint32]*dict, len(d.o.dicts)) + for _, dc := range d.o.dicts { + d.dicts[dc.id] = dc + } + d.o.dicts = nil + + // Create decoders + d.decoders = make(chan *blockDec, d.o.concurrent) + for i := 0; i < d.o.concurrent; i++ { + dec := newBlockDec(d.o.lowMem) + dec.localFrame = newFrameDec(d.o) + d.decoders <- dec + } + + if r == nil { + return &d, nil + } + return &d, d.Reset(r) +} + +// Read bytes from the decompressed stream into p. +// Returns the number of bytes written and any error that occurred. +// When the stream is done, io.EOF will be returned. +func (d *Decoder) Read(p []byte) (int, error) { + var n int + for { + if len(d.current.b) > 0 { + filled := copy(p, d.current.b) + p = p[filled:] + d.current.b = d.current.b[filled:] + n += filled + } + if len(p) == 0 { + break + } + if len(d.current.b) == 0 { + // We have an error and no more data + if d.current.err != nil { + break + } + if !d.nextBlock(n == 0) { + return n, d.current.err + } + } + } + if len(d.current.b) > 0 { + if debugDecoder { + println("returning", n, "still bytes left:", len(d.current.b)) + } + // Only return error at end of block + return n, nil + } + if d.current.err != nil { + d.drainOutput() + } + if debugDecoder { + println("returning", n, d.current.err, len(d.decoders)) + } + return n, d.current.err +} + +// Reset will reset the decoder the supplied stream after the current has finished processing. +// Note that this functionality cannot be used after Close has been called. +// Reset can be called with a nil reader to release references to the previous reader. +// After being called with a nil reader, no other operations than Reset or DecodeAll or Close +// should be used. +func (d *Decoder) Reset(r io.Reader) error { + if d.current.err == ErrDecoderClosed { + return d.current.err + } + + d.drainOutput() + + d.syncStream.br.r = nil + if r == nil { + d.current.err = ErrDecoderNilInput + if len(d.current.b) > 0 { + d.current.b = d.current.b[:0] + } + d.current.flushed = true + return nil + } + + // If bytes buffer and < 5MB, do sync decoding anyway. + if bb, ok := r.(byter); ok && bb.Len() < d.o.decodeBufsBelow && !d.o.limitToCap { + bb2 := bb + if debugDecoder { + println("*bytes.Buffer detected, doing sync decode, len:", bb.Len()) + } + b := bb2.Bytes() + var dst []byte + if cap(d.syncStream.dstBuf) > 0 { + dst = d.syncStream.dstBuf[:0] + } + + dst, err := d.DecodeAll(b, dst) + if err == nil { + err = io.EOF + } + // Save output buffer + d.syncStream.dstBuf = dst + d.current.b = dst + d.current.err = err + d.current.flushed = true + if debugDecoder { + println("sync decode to", len(dst), "bytes, err:", err) + } + return nil + } + // Remove current block. + d.stashDecoder() + d.current.decodeOutput = decodeOutput{} + d.current.err = nil + d.current.flushed = false + d.current.d = nil + d.syncStream.dstBuf = nil + + // Ensure no-one else is still running... + d.streamWg.Wait() + if d.frame == nil { + d.frame = newFrameDec(d.o) + } + + if d.o.concurrent == 1 { + return d.startSyncDecoder(r) + } + + d.current.output = make(chan decodeOutput, d.o.concurrent) + ctx, cancel := context.WithCancel(context.Background()) + d.current.cancel = cancel + d.streamWg.Add(1) + go d.startStreamDecoder(ctx, r, d.current.output) + + return nil +} + +// drainOutput will drain the output until errEndOfStream is sent. +func (d *Decoder) drainOutput() { + if d.current.cancel != nil { + if debugDecoder { + println("cancelling current") + } + d.current.cancel() + d.current.cancel = nil + } + if d.current.d != nil { + if debugDecoder { + printf("re-adding current decoder %p, decoders: %d", d.current.d, len(d.decoders)) + } + d.decoders <- d.current.d + d.current.d = nil + d.current.b = nil + } + if d.current.output == nil || d.current.flushed { + println("current already flushed") + return + } + for v := range d.current.output { + if v.d != nil { + if debugDecoder { + printf("re-adding decoder %p", v.d) + } + d.decoders <- v.d + } + } + d.current.output = nil + d.current.flushed = true +} + +// WriteTo writes data to w until there's no more data to write or when an error occurs. +// The return value n is the number of bytes written. +// Any error encountered during the write is also returned. +func (d *Decoder) WriteTo(w io.Writer) (int64, error) { + var n int64 + for { + if len(d.current.b) > 0 { + n2, err2 := w.Write(d.current.b) + n += int64(n2) + if err2 != nil && (d.current.err == nil || d.current.err == io.EOF) { + d.current.err = err2 + } else if n2 != len(d.current.b) { + d.current.err = io.ErrShortWrite + } + } + if d.current.err != nil { + break + } + d.nextBlock(true) + } + err := d.current.err + if err != nil { + d.drainOutput() + } + if err == io.EOF { + err = nil + } + return n, err +} + +// DecodeAll allows stateless decoding of a blob of bytes. +// Output will be appended to dst, so if the destination size is known +// you can pre-allocate the destination slice to avoid allocations. +// DecodeAll can be used concurrently. +// The Decoder concurrency limits will be respected. +func (d *Decoder) DecodeAll(input, dst []byte) ([]byte, error) { + if d.decoders == nil { + return dst, ErrDecoderClosed + } + + // Grab a block decoder and frame decoder. + block := <-d.decoders + frame := block.localFrame + initialSize := len(dst) + defer func() { + if debugDecoder { + printf("re-adding decoder: %p", block) + } + frame.rawInput = nil + frame.bBuf = nil + if frame.history.decoders.br != nil { + frame.history.decoders.br.in = nil + } + d.decoders <- block + }() + frame.bBuf = input + + for { + frame.history.reset() + err := frame.reset(&frame.bBuf) + if err != nil { + if err == io.EOF { + if debugDecoder { + println("frame reset return EOF") + } + return dst, nil + } + return dst, err + } + if err = d.setDict(frame); err != nil { + return nil, err + } + if frame.WindowSize > d.o.maxWindowSize { + if debugDecoder { + println("window size exceeded:", frame.WindowSize, ">", d.o.maxWindowSize) + } + return dst, ErrWindowSizeExceeded + } + if frame.FrameContentSize != fcsUnknown { + if frame.FrameContentSize > d.o.maxDecodedSize-uint64(len(dst)-initialSize) { + if debugDecoder { + println("decoder size exceeded; fcs:", frame.FrameContentSize, "> mcs:", d.o.maxDecodedSize-uint64(len(dst)-initialSize), "len:", len(dst)) + } + return dst, ErrDecoderSizeExceeded + } + if d.o.limitToCap && frame.FrameContentSize > uint64(cap(dst)-len(dst)) { + if debugDecoder { + println("decoder size exceeded; fcs:", frame.FrameContentSize, "> (cap-len)", cap(dst)-len(dst)) + } + return dst, ErrDecoderSizeExceeded + } + if cap(dst)-len(dst) < int(frame.FrameContentSize) { + dst2 := make([]byte, len(dst), len(dst)+int(frame.FrameContentSize)+compressedBlockOverAlloc) + copy(dst2, dst) + dst = dst2 + } + } + + if cap(dst) == 0 && !d.o.limitToCap { + // Allocate len(input) * 2 by default if nothing is provided + // and we didn't get frame content size. + size := len(input) * 2 + // Cap to 1 MB. + if size > 1<<20 { + size = 1 << 20 + } + if uint64(size) > d.o.maxDecodedSize { + size = int(d.o.maxDecodedSize) + } + dst = make([]byte, 0, size) + } + + dst, err = frame.runDecoder(dst, block) + if err != nil { + return dst, err + } + if uint64(len(dst)-initialSize) > d.o.maxDecodedSize { + return dst, ErrDecoderSizeExceeded + } + if len(frame.bBuf) == 0 { + if debugDecoder { + println("frame dbuf empty") + } + break + } + } + return dst, nil +} + +// nextBlock returns the next block. +// If an error occurs d.err will be set. +// Optionally the function can block for new output. +// If non-blocking mode is used the returned boolean will be false +// if no data was available without blocking. +func (d *Decoder) nextBlock(blocking bool) (ok bool) { + if d.current.err != nil { + // Keep error state. + return false + } + d.current.b = d.current.b[:0] + + // SYNC: + if d.syncStream.enabled { + if !blocking { + return false + } + ok = d.nextBlockSync() + if !ok { + d.stashDecoder() + } + return ok + } + + //ASYNC: + d.stashDecoder() + if blocking { + d.current.decodeOutput, ok = <-d.current.output + } else { + select { + case d.current.decodeOutput, ok = <-d.current.output: + default: + return false + } + } + if !ok { + // This should not happen, so signal error state... + d.current.err = io.ErrUnexpectedEOF + return false + } + next := d.current.decodeOutput + if next.d != nil && next.d.async.newHist != nil { + d.current.crc.Reset() + } + if debugDecoder { + var tmp [4]byte + binary.LittleEndian.PutUint32(tmp[:], uint32(xxhash.Sum64(next.b))) + println("got", len(d.current.b), "bytes, error:", d.current.err, "data crc:", tmp) + } + + if d.o.ignoreChecksum { + return true + } + + if len(next.b) > 0 { + d.current.crc.Write(next.b) + } + if next.err == nil && next.d != nil && next.d.hasCRC { + got := uint32(d.current.crc.Sum64()) + if got != next.d.checkCRC { + if debugDecoder { + printf("CRC Check Failed: %08x (got) != %08x (on stream)\n", got, next.d.checkCRC) + } + d.current.err = ErrCRCMismatch + } else { + if debugDecoder { + printf("CRC ok %08x\n", got) + } + } + } + + return true +} + +func (d *Decoder) nextBlockSync() (ok bool) { + if d.current.d == nil { + d.current.d = <-d.decoders + } + for len(d.current.b) == 0 { + if !d.syncStream.inFrame { + d.frame.history.reset() + d.current.err = d.frame.reset(&d.syncStream.br) + if d.current.err == nil { + d.current.err = d.setDict(d.frame) + } + if d.current.err != nil { + return false + } + if d.frame.WindowSize > d.o.maxDecodedSize || d.frame.WindowSize > d.o.maxWindowSize { + d.current.err = ErrDecoderSizeExceeded + return false + } + + d.syncStream.decodedFrame = 0 + d.syncStream.inFrame = true + } + d.current.err = d.frame.next(d.current.d) + if d.current.err != nil { + return false + } + d.frame.history.ensureBlock() + if debugDecoder { + println("History trimmed:", len(d.frame.history.b), "decoded already:", d.syncStream.decodedFrame) + } + histBefore := len(d.frame.history.b) + d.current.err = d.current.d.decodeBuf(&d.frame.history) + + if d.current.err != nil { + println("error after:", d.current.err) + return false + } + d.current.b = d.frame.history.b[histBefore:] + if debugDecoder { + println("history after:", len(d.frame.history.b)) + } + + // Check frame size (before CRC) + d.syncStream.decodedFrame += uint64(len(d.current.b)) + if d.syncStream.decodedFrame > d.frame.FrameContentSize { + if debugDecoder { + printf("DecodedFrame (%d) > FrameContentSize (%d)\n", d.syncStream.decodedFrame, d.frame.FrameContentSize) + } + d.current.err = ErrFrameSizeExceeded + return false + } + + // Check FCS + if d.current.d.Last && d.frame.FrameContentSize != fcsUnknown && d.syncStream.decodedFrame != d.frame.FrameContentSize { + if debugDecoder { + printf("DecodedFrame (%d) != FrameContentSize (%d)\n", d.syncStream.decodedFrame, d.frame.FrameContentSize) + } + d.current.err = ErrFrameSizeMismatch + return false + } + + // Update/Check CRC + if d.frame.HasCheckSum { + if !d.o.ignoreChecksum { + d.frame.crc.Write(d.current.b) + } + if d.current.d.Last { + if !d.o.ignoreChecksum { + d.current.err = d.frame.checkCRC() + } else { + d.current.err = d.frame.consumeCRC() + } + if d.current.err != nil { + println("CRC error:", d.current.err) + return false + } + } + } + d.syncStream.inFrame = !d.current.d.Last + } + return true +} + +func (d *Decoder) stashDecoder() { + if d.current.d != nil { + if debugDecoder { + printf("re-adding current decoder %p", d.current.d) + } + d.decoders <- d.current.d + d.current.d = nil + } +} + +// Close will release all resources. +// It is NOT possible to reuse the decoder after this. +func (d *Decoder) Close() { + if d.current.err == ErrDecoderClosed { + return + } + d.drainOutput() + if d.current.cancel != nil { + d.current.cancel() + d.streamWg.Wait() + d.current.cancel = nil + } + if d.decoders != nil { + close(d.decoders) + for dec := range d.decoders { + dec.Close() + } + d.decoders = nil + } + if d.current.d != nil { + d.current.d.Close() + d.current.d = nil + } + d.current.err = ErrDecoderClosed +} + +// IOReadCloser returns the decoder as an io.ReadCloser for convenience. +// Any changes to the decoder will be reflected, so the returned ReadCloser +// can be reused along with the decoder. +// io.WriterTo is also supported by the returned ReadCloser. +func (d *Decoder) IOReadCloser() io.ReadCloser { + return closeWrapper{d: d} +} + +// closeWrapper wraps a function call as a closer. +type closeWrapper struct { + d *Decoder +} + +// WriteTo forwards WriteTo calls to the decoder. +func (c closeWrapper) WriteTo(w io.Writer) (n int64, err error) { + return c.d.WriteTo(w) +} + +// Read forwards read calls to the decoder. +func (c closeWrapper) Read(p []byte) (n int, err error) { + return c.d.Read(p) +} + +// Close closes the decoder. +func (c closeWrapper) Close() error { + c.d.Close() + return nil +} + +type decodeOutput struct { + d *blockDec + b []byte + err error +} + +func (d *Decoder) startSyncDecoder(r io.Reader) error { + d.frame.history.reset() + d.syncStream.br = readerWrapper{r: r} + d.syncStream.inFrame = false + d.syncStream.enabled = true + d.syncStream.decodedFrame = 0 + return nil +} + +// Create Decoder: +// ASYNC: +// Spawn 3 go routines. +// 0: Read frames and decode block literals. +// 1: Decode sequences. +// 2: Execute sequences, send to output. +func (d *Decoder) startStreamDecoder(ctx context.Context, r io.Reader, output chan decodeOutput) { + defer d.streamWg.Done() + br := readerWrapper{r: r} + + var seqDecode = make(chan *blockDec, d.o.concurrent) + var seqExecute = make(chan *blockDec, d.o.concurrent) + + // Async 1: Decode sequences... + go func() { + var hist history + var hasErr bool + + for block := range seqDecode { + if hasErr { + if block != nil { + seqExecute <- block + } + continue + } + if block.async.newHist != nil { + if debugDecoder { + println("Async 1: new history, recent:", block.async.newHist.recentOffsets) + } + hist.reset() + hist.decoders = block.async.newHist.decoders + hist.recentOffsets = block.async.newHist.recentOffsets + hist.windowSize = block.async.newHist.windowSize + if block.async.newHist.dict != nil { + hist.setDict(block.async.newHist.dict) + } + } + if block.err != nil || block.Type != blockTypeCompressed { + hasErr = block.err != nil + seqExecute <- block + continue + } + + hist.decoders.literals = block.async.literals + block.err = block.prepareSequences(block.async.seqData, &hist) + if debugDecoder && block.err != nil { + println("prepareSequences returned:", block.err) + } + hasErr = block.err != nil + if block.err == nil { + block.err = block.decodeSequences(&hist) + if debugDecoder && block.err != nil { + println("decodeSequences returned:", block.err) + } + hasErr = block.err != nil + // block.async.sequence = hist.decoders.seq[:hist.decoders.nSeqs] + block.async.seqSize = hist.decoders.seqSize + } + seqExecute <- block + } + close(seqExecute) + hist.reset() + }() + + var wg sync.WaitGroup + wg.Add(1) + + // Async 3: Execute sequences... + frameHistCache := d.frame.history.b + go func() { + var hist history + var decodedFrame uint64 + var fcs uint64 + var hasErr bool + for block := range seqExecute { + out := decodeOutput{err: block.err, d: block} + if block.err != nil || hasErr { + hasErr = true + output <- out + continue + } + if block.async.newHist != nil { + if debugDecoder { + println("Async 2: new history") + } + hist.reset() + hist.windowSize = block.async.newHist.windowSize + hist.allocFrameBuffer = block.async.newHist.allocFrameBuffer + if block.async.newHist.dict != nil { + hist.setDict(block.async.newHist.dict) + } + + if cap(hist.b) < hist.allocFrameBuffer { + if cap(frameHistCache) >= hist.allocFrameBuffer { + hist.b = frameHistCache + } else { + hist.b = make([]byte, 0, hist.allocFrameBuffer) + println("Alloc history sized", hist.allocFrameBuffer) + } + } + hist.b = hist.b[:0] + fcs = block.async.fcs + decodedFrame = 0 + } + do := decodeOutput{err: block.err, d: block} + switch block.Type { + case blockTypeRLE: + if debugDecoder { + println("add rle block length:", block.RLESize) + } + + if cap(block.dst) < int(block.RLESize) { + if block.lowMem { + block.dst = make([]byte, block.RLESize) + } else { + block.dst = make([]byte, maxCompressedBlockSize) + } + } + block.dst = block.dst[:block.RLESize] + v := block.data[0] + for i := range block.dst { + block.dst[i] = v + } + hist.append(block.dst) + do.b = block.dst + case blockTypeRaw: + if debugDecoder { + println("add raw block length:", len(block.data)) + } + hist.append(block.data) + do.b = block.data + case blockTypeCompressed: + if debugDecoder { + println("execute with history length:", len(hist.b), "window:", hist.windowSize) + } + hist.decoders.seqSize = block.async.seqSize + hist.decoders.literals = block.async.literals + do.err = block.executeSequences(&hist) + hasErr = do.err != nil + if debugDecoder && hasErr { + println("executeSequences returned:", do.err) + } + do.b = block.dst + } + if !hasErr { + decodedFrame += uint64(len(do.b)) + if decodedFrame > fcs { + println("fcs exceeded", block.Last, fcs, decodedFrame) + do.err = ErrFrameSizeExceeded + hasErr = true + } else if block.Last && fcs != fcsUnknown && decodedFrame != fcs { + do.err = ErrFrameSizeMismatch + hasErr = true + } else { + if debugDecoder { + println("fcs ok", block.Last, fcs, decodedFrame) + } + } + } + output <- do + } + close(output) + frameHistCache = hist.b + wg.Done() + if debugDecoder { + println("decoder goroutines finished") + } + hist.reset() + }() + + var hist history +decodeStream: + for { + var hasErr bool + hist.reset() + decodeBlock := func(block *blockDec) { + if hasErr { + if block != nil { + seqDecode <- block + } + return + } + if block.err != nil || block.Type != blockTypeCompressed { + hasErr = block.err != nil + seqDecode <- block + return + } + + remain, err := block.decodeLiterals(block.data, &hist) + block.err = err + hasErr = block.err != nil + if err == nil { + block.async.literals = hist.decoders.literals + block.async.seqData = remain + } else if debugDecoder { + println("decodeLiterals error:", err) + } + seqDecode <- block + } + frame := d.frame + if debugDecoder { + println("New frame...") + } + var historySent bool + frame.history.reset() + err := frame.reset(&br) + if debugDecoder && err != nil { + println("Frame decoder returned", err) + } + if err == nil { + err = d.setDict(frame) + } + if err == nil && d.frame.WindowSize > d.o.maxWindowSize { + if debugDecoder { + println("decoder size exceeded, fws:", d.frame.WindowSize, "> mws:", d.o.maxWindowSize) + } + + err = ErrDecoderSizeExceeded + } + if err != nil { + select { + case <-ctx.Done(): + case dec := <-d.decoders: + dec.sendErr(err) + decodeBlock(dec) + } + break decodeStream + } + + // Go through all blocks of the frame. + for { + var dec *blockDec + select { + case <-ctx.Done(): + break decodeStream + case dec = <-d.decoders: + // Once we have a decoder, we MUST return it. + } + err := frame.next(dec) + if !historySent { + h := frame.history + if debugDecoder { + println("Alloc History:", h.allocFrameBuffer) + } + hist.reset() + if h.dict != nil { + hist.setDict(h.dict) + } + dec.async.newHist = &h + dec.async.fcs = frame.FrameContentSize + historySent = true + } else { + dec.async.newHist = nil + } + if debugDecoder && err != nil { + println("next block returned error:", err) + } + dec.err = err + dec.hasCRC = false + if dec.Last && frame.HasCheckSum && err == nil { + crc, err := frame.rawInput.readSmall(4) + if len(crc) < 4 { + if err == nil { + err = io.ErrUnexpectedEOF + + } + println("CRC missing?", err) + dec.err = err + } else { + dec.checkCRC = binary.LittleEndian.Uint32(crc) + dec.hasCRC = true + if debugDecoder { + printf("found crc to check: %08x\n", dec.checkCRC) + } + } + } + err = dec.err + last := dec.Last + decodeBlock(dec) + if err != nil { + break decodeStream + } + if last { + break + } + } + } + close(seqDecode) + wg.Wait() + hist.reset() + d.frame.history.b = frameHistCache +} + +func (d *Decoder) setDict(frame *frameDec) (err error) { + dict, ok := d.dicts[frame.DictionaryID] + if ok { + if debugDecoder { + println("setting dict", frame.DictionaryID) + } + frame.history.setDict(dict) + } else if frame.DictionaryID != 0 { + // A zero or missing dictionary id is ambiguous: + // either dictionary zero, or no dictionary. In particular, + // zstd --patch-from uses this id for the source file, + // so only return an error if the dictionary id is not zero. + err = ErrUnknownDictionary + } + return err +} diff --git a/vendor/github.com/klauspost/compress/zstd/decoder_options.go b/vendor/github.com/klauspost/compress/zstd/decoder_options.go new file mode 100644 index 000000000..774c5f00f --- /dev/null +++ b/vendor/github.com/klauspost/compress/zstd/decoder_options.go @@ -0,0 +1,169 @@ +// Copyright 2019+ Klaus Post. All rights reserved. +// License information can be found in the LICENSE file. +// Based on work by Yann Collet, released under BSD License. + +package zstd + +import ( + "errors" + "fmt" + "math/bits" + "runtime" +) + +// DOption is an option for creating a decoder. +type DOption func(*decoderOptions) error + +// options retains accumulated state of multiple options. +type decoderOptions struct { + lowMem bool + concurrent int + maxDecodedSize uint64 + maxWindowSize uint64 + dicts []*dict + ignoreChecksum bool + limitToCap bool + decodeBufsBelow int +} + +func (o *decoderOptions) setDefault() { + *o = decoderOptions{ + // use less ram: true for now, but may change. + lowMem: true, + concurrent: runtime.GOMAXPROCS(0), + maxWindowSize: MaxWindowSize, + decodeBufsBelow: 128 << 10, + } + if o.concurrent > 4 { + o.concurrent = 4 + } + o.maxDecodedSize = 64 << 30 +} + +// WithDecoderLowmem will set whether to use a lower amount of memory, +// but possibly have to allocate more while running. +func WithDecoderLowmem(b bool) DOption { + return func(o *decoderOptions) error { o.lowMem = b; return nil } +} + +// WithDecoderConcurrency sets the number of created decoders. +// When decoding block with DecodeAll, this will limit the number +// of possible concurrently running decodes. +// When decoding streams, this will limit the number of +// inflight blocks. +// When decoding streams and setting maximum to 1, +// no async decoding will be done. +// When a value of 0 is provided GOMAXPROCS will be used. +// By default this will be set to 4 or GOMAXPROCS, whatever is lower. +func WithDecoderConcurrency(n int) DOption { + return func(o *decoderOptions) error { + if n < 0 { + return errors.New("concurrency must be at least 1") + } + if n == 0 { + o.concurrent = runtime.GOMAXPROCS(0) + } else { + o.concurrent = n + } + return nil + } +} + +// WithDecoderMaxMemory allows to set a maximum decoded size for in-memory +// non-streaming operations or maximum window size for streaming operations. +// This can be used to control memory usage of potentially hostile content. +// Maximum is 1 << 63 bytes. Default is 64GiB. +func WithDecoderMaxMemory(n uint64) DOption { + return func(o *decoderOptions) error { + if n == 0 { + return errors.New("WithDecoderMaxMemory must be at least 1") + } + if n > 1<<63 { + return errors.New("WithDecoderMaxmemory must be less than 1 << 63") + } + o.maxDecodedSize = n + return nil + } +} + +// WithDecoderDicts allows to register one or more dictionaries for the decoder. +// +// Each slice in dict must be in the [dictionary format] produced by +// "zstd --train" from the Zstandard reference implementation. +// +// If several dictionaries with the same ID are provided, the last one will be used. +// +// [dictionary format]: https://github.com/facebook/zstd/blob/dev/doc/zstd_compression_format.md#dictionary-format +func WithDecoderDicts(dicts ...[]byte) DOption { + return func(o *decoderOptions) error { + for _, b := range dicts { + d, err := loadDict(b) + if err != nil { + return err + } + o.dicts = append(o.dicts, d) + } + return nil + } +} + +// WithDecoderDictRaw registers a dictionary that may be used by the decoder. +// The slice content can be arbitrary data. +func WithDecoderDictRaw(id uint32, content []byte) DOption { + return func(o *decoderOptions) error { + if bits.UintSize > 32 && uint(len(content)) > dictMaxLength { + return fmt.Errorf("dictionary of size %d > 2GiB too large", len(content)) + } + o.dicts = append(o.dicts, &dict{id: id, content: content, offsets: [3]int{1, 4, 8}}) + return nil + } +} + +// WithDecoderMaxWindow allows to set a maximum window size for decodes. +// This allows rejecting packets that will cause big memory usage. +// The Decoder will likely allocate more memory based on the WithDecoderLowmem setting. +// If WithDecoderMaxMemory is set to a lower value, that will be used. +// Default is 512MB, Maximum is ~3.75 TB as per zstandard spec. +func WithDecoderMaxWindow(size uint64) DOption { + return func(o *decoderOptions) error { + if size < MinWindowSize { + return errors.New("WithMaxWindowSize must be at least 1KB, 1024 bytes") + } + if size > (1<<41)+7*(1<<38) { + return errors.New("WithMaxWindowSize must be less than (1<<41) + 7*(1<<38) ~ 3.75TB") + } + o.maxWindowSize = size + return nil + } +} + +// WithDecodeAllCapLimit will limit DecodeAll to decoding cap(dst)-len(dst) bytes, +// or any size set in WithDecoderMaxMemory. +// This can be used to limit decoding to a specific maximum output size. +// Disabled by default. +func WithDecodeAllCapLimit(b bool) DOption { + return func(o *decoderOptions) error { + o.limitToCap = b + return nil + } +} + +// WithDecodeBuffersBelow will fully decode readers that have a +// `Bytes() []byte` and `Len() int` interface similar to bytes.Buffer. +// This typically uses less allocations but will have the full decompressed object in memory. +// Note that DecodeAllCapLimit will disable this, as well as giving a size of 0 or less. +// Default is 128KiB. +func WithDecodeBuffersBelow(size int) DOption { + return func(o *decoderOptions) error { + o.decodeBufsBelow = size + return nil + } +} + +// IgnoreChecksum allows to forcibly ignore checksum checking. +func IgnoreChecksum(b bool) DOption { + return func(o *decoderOptions) error { + o.ignoreChecksum = b + return nil + } +} diff --git a/vendor/github.com/klauspost/compress/zstd/dict.go b/vendor/github.com/klauspost/compress/zstd/dict.go new file mode 100644 index 000000000..b7b83164b --- /dev/null +++ b/vendor/github.com/klauspost/compress/zstd/dict.go @@ -0,0 +1,565 @@ +package zstd + +import ( + "bytes" + "encoding/binary" + "errors" + "fmt" + "io" + "math" + "sort" + + "github.com/klauspost/compress/huff0" +) + +type dict struct { + id uint32 + + litEnc *huff0.Scratch + llDec, ofDec, mlDec sequenceDec + offsets [3]int + content []byte +} + +const dictMagic = "\x37\xa4\x30\xec" + +// Maximum dictionary size for the reference implementation (1.5.3) is 2 GiB. +const dictMaxLength = 1 << 31 + +// ID returns the dictionary id or 0 if d is nil. +func (d *dict) ID() uint32 { + if d == nil { + return 0 + } + return d.id +} + +// ContentSize returns the dictionary content size or 0 if d is nil. +func (d *dict) ContentSize() int { + if d == nil { + return 0 + } + return len(d.content) +} + +// Content returns the dictionary content. +func (d *dict) Content() []byte { + if d == nil { + return nil + } + return d.content +} + +// Offsets returns the initial offsets. +func (d *dict) Offsets() [3]int { + if d == nil { + return [3]int{} + } + return d.offsets +} + +// LitEncoder returns the literal encoder. +func (d *dict) LitEncoder() *huff0.Scratch { + if d == nil { + return nil + } + return d.litEnc +} + +// Load a dictionary as described in +// https://github.com/facebook/zstd/blob/master/doc/zstd_compression_format.md#dictionary-format +func loadDict(b []byte) (*dict, error) { + // Check static field size. + if len(b) <= 8+(3*4) { + return nil, io.ErrUnexpectedEOF + } + d := dict{ + llDec: sequenceDec{fse: &fseDecoder{}}, + ofDec: sequenceDec{fse: &fseDecoder{}}, + mlDec: sequenceDec{fse: &fseDecoder{}}, + } + if string(b[:4]) != dictMagic { + return nil, ErrMagicMismatch + } + d.id = binary.LittleEndian.Uint32(b[4:8]) + if d.id == 0 { + return nil, errors.New("dictionaries cannot have ID 0") + } + + // Read literal table + var err error + d.litEnc, b, err = huff0.ReadTable(b[8:], nil) + if err != nil { + return nil, fmt.Errorf("loading literal table: %w", err) + } + d.litEnc.Reuse = huff0.ReusePolicyMust + + br := byteReader{ + b: b, + off: 0, + } + readDec := func(i tableIndex, dec *fseDecoder) error { + if err := dec.readNCount(&br, uint16(maxTableSymbol[i])); err != nil { + return err + } + if br.overread() { + return io.ErrUnexpectedEOF + } + err = dec.transform(symbolTableX[i]) + if err != nil { + println("Transform table error:", err) + return err + } + if debugDecoder || debugEncoder { + println("Read table ok", "symbolLen:", dec.symbolLen) + } + // Set decoders as predefined so they aren't reused. + dec.preDefined = true + return nil + } + + if err := readDec(tableOffsets, d.ofDec.fse); err != nil { + return nil, err + } + if err := readDec(tableMatchLengths, d.mlDec.fse); err != nil { + return nil, err + } + if err := readDec(tableLiteralLengths, d.llDec.fse); err != nil { + return nil, err + } + if br.remain() < 12 { + return nil, io.ErrUnexpectedEOF + } + + d.offsets[0] = int(br.Uint32()) + br.advance(4) + d.offsets[1] = int(br.Uint32()) + br.advance(4) + d.offsets[2] = int(br.Uint32()) + br.advance(4) + if d.offsets[0] <= 0 || d.offsets[1] <= 0 || d.offsets[2] <= 0 { + return nil, errors.New("invalid offset in dictionary") + } + d.content = make([]byte, br.remain()) + copy(d.content, br.unread()) + if d.offsets[0] > len(d.content) || d.offsets[1] > len(d.content) || d.offsets[2] > len(d.content) { + return nil, fmt.Errorf("initial offset bigger than dictionary content size %d, offsets: %v", len(d.content), d.offsets) + } + + return &d, nil +} + +// InspectDictionary loads a zstd dictionary and provides functions to inspect the content. +func InspectDictionary(b []byte) (interface { + ID() uint32 + ContentSize() int + Content() []byte + Offsets() [3]int + LitEncoder() *huff0.Scratch +}, error) { + initPredefined() + d, err := loadDict(b) + return d, err +} + +type BuildDictOptions struct { + // Dictionary ID. + ID uint32 + + // Content to use to create dictionary tables. + Contents [][]byte + + // History to use for all blocks. + History []byte + + // Offsets to use. + Offsets [3]int + + // CompatV155 will make the dictionary compatible with Zstd v1.5.5 and earlier. + // See https://github.com/facebook/zstd/issues/3724 + CompatV155 bool + + // Use the specified encoder level. + // The dictionary will be built using the specified encoder level, + // which will reflect speed and make the dictionary tailored for that level. + // If not set SpeedBestCompression will be used. + Level EncoderLevel + + // DebugOut will write stats and other details here if set. + DebugOut io.Writer +} + +func BuildDict(o BuildDictOptions) ([]byte, error) { + initPredefined() + hist := o.History + contents := o.Contents + debug := o.DebugOut != nil + println := func(args ...interface{}) { + if o.DebugOut != nil { + fmt.Fprintln(o.DebugOut, args...) + } + } + printf := func(s string, args ...interface{}) { + if o.DebugOut != nil { + fmt.Fprintf(o.DebugOut, s, args...) + } + } + print := func(args ...interface{}) { + if o.DebugOut != nil { + fmt.Fprint(o.DebugOut, args...) + } + } + + if int64(len(hist)) > dictMaxLength { + return nil, fmt.Errorf("dictionary of size %d > %d", len(hist), int64(dictMaxLength)) + } + if len(hist) < 8 { + return nil, fmt.Errorf("dictionary of size %d < %d", len(hist), 8) + } + if len(contents) == 0 { + return nil, errors.New("no content provided") + } + d := dict{ + id: o.ID, + litEnc: nil, + llDec: sequenceDec{}, + ofDec: sequenceDec{}, + mlDec: sequenceDec{}, + offsets: o.Offsets, + content: hist, + } + block := blockEnc{lowMem: false} + block.init() + enc := encoder(&bestFastEncoder{fastBase: fastBase{maxMatchOff: int32(maxMatchLen), bufferReset: math.MaxInt32 - int32(maxMatchLen*2), lowMem: false}}) + if o.Level != 0 { + eOpts := encoderOptions{ + level: o.Level, + blockSize: maxMatchLen, + windowSize: maxMatchLen, + dict: &d, + lowMem: false, + } + enc = eOpts.encoder() + } else { + o.Level = SpeedBestCompression + } + var ( + remain [256]int + ll [256]int + ml [256]int + of [256]int + ) + addValues := func(dst *[256]int, src []byte) { + for _, v := range src { + dst[v]++ + } + } + addHist := func(dst *[256]int, src *[256]uint32) { + for i, v := range src { + dst[i] += int(v) + } + } + seqs := 0 + nUsed := 0 + litTotal := 0 + newOffsets := make(map[uint32]int, 1000) + for _, b := range contents { + block.reset(nil) + if len(b) < 8 { + continue + } + nUsed++ + enc.Reset(&d, true) + enc.Encode(&block, b) + addValues(&remain, block.literals) + litTotal += len(block.literals) + if len(block.sequences) == 0 { + continue + } + seqs += len(block.sequences) + block.genCodes() + addHist(&ll, block.coders.llEnc.Histogram()) + addHist(&ml, block.coders.mlEnc.Histogram()) + addHist(&of, block.coders.ofEnc.Histogram()) + for i, seq := range block.sequences { + if i > 3 { + break + } + offset := seq.offset + if offset == 0 { + continue + } + if int(offset) >= len(o.History) { + continue + } + if offset > 3 { + newOffsets[offset-3]++ + } else { + newOffsets[uint32(o.Offsets[offset-1])]++ + } + } + } + // Find most used offsets. + var sortedOffsets []uint32 + for k := range newOffsets { + sortedOffsets = append(sortedOffsets, k) + } + sort.Slice(sortedOffsets, func(i, j int) bool { + a, b := sortedOffsets[i], sortedOffsets[j] + if a == b { + // Prefer the longer offset + return sortedOffsets[i] > sortedOffsets[j] + } + return newOffsets[sortedOffsets[i]] > newOffsets[sortedOffsets[j]] + }) + if len(sortedOffsets) > 3 { + if debug { + print("Offsets:") + for i, v := range sortedOffsets { + if i > 20 { + break + } + printf("[%d: %d],", v, newOffsets[v]) + } + println("") + } + + sortedOffsets = sortedOffsets[:3] + } + for i, v := range sortedOffsets { + o.Offsets[i] = int(v) + } + if debug { + println("New repeat offsets", o.Offsets) + } + + if nUsed == 0 || seqs == 0 { + return nil, fmt.Errorf("%d blocks, %d sequences found", nUsed, seqs) + } + if debug { + println("Sequences:", seqs, "Blocks:", nUsed, "Literals:", litTotal) + } + if seqs/nUsed < 512 { + // Use 512 as minimum. + nUsed = seqs / 512 + if nUsed == 0 { + nUsed = 1 + } + } + copyHist := func(dst *fseEncoder, src *[256]int) ([]byte, error) { + hist := dst.Histogram() + var maxSym uint8 + var maxCount int + var fakeLength int + for i, v := range src { + if v > 0 { + v = v / nUsed + if v == 0 { + v = 1 + } + } + if v > maxCount { + maxCount = v + } + if v != 0 { + maxSym = uint8(i) + } + fakeLength += v + hist[i] = uint32(v) + } + + // Ensure we aren't trying to represent RLE. + if maxCount == fakeLength { + for i := range hist { + if uint8(i) == maxSym { + fakeLength++ + maxSym++ + hist[i+1] = 1 + if maxSym > 1 { + break + } + } + if hist[0] == 0 { + fakeLength++ + hist[i] = 1 + if maxSym > 1 { + break + } + } + } + } + + dst.HistogramFinished(maxSym, maxCount) + dst.reUsed = false + dst.useRLE = false + err := dst.normalizeCount(fakeLength) + if err != nil { + return nil, err + } + if debug { + println("RAW:", dst.count[:maxSym+1], "NORM:", dst.norm[:maxSym+1], "LEN:", fakeLength) + } + return dst.writeCount(nil) + } + if debug { + print("Literal lengths: ") + } + llTable, err := copyHist(block.coders.llEnc, &ll) + if err != nil { + return nil, err + } + if debug { + print("Match lengths: ") + } + mlTable, err := copyHist(block.coders.mlEnc, &ml) + if err != nil { + return nil, err + } + if debug { + print("Offsets: ") + } + ofTable, err := copyHist(block.coders.ofEnc, &of) + if err != nil { + return nil, err + } + + // Literal table + avgSize := litTotal + if avgSize > huff0.BlockSizeMax/2 { + avgSize = huff0.BlockSizeMax / 2 + } + huffBuff := make([]byte, 0, avgSize) + // Target size + div := litTotal / avgSize + if div < 1 { + div = 1 + } + if debug { + println("Huffman weights:") + } + for i, n := range remain[:] { + if n > 0 { + n = n / div + // Allow all entries to be represented. + if n == 0 { + n = 1 + } + huffBuff = append(huffBuff, bytes.Repeat([]byte{byte(i)}, n)...) + if debug { + printf("[%d: %d], ", i, n) + } + } + } + if o.CompatV155 && remain[255]/div == 0 { + huffBuff = append(huffBuff, 255) + } + scratch := &huff0.Scratch{TableLog: 11} + for tries := 0; tries < 255; tries++ { + scratch = &huff0.Scratch{TableLog: 11} + _, _, err = huff0.Compress1X(huffBuff, scratch) + if err == nil { + break + } + if debug { + printf("Try %d: Huffman error: %v\n", tries+1, err) + } + huffBuff = huffBuff[:0] + if tries == 250 { + if debug { + println("Huffman: Bailing out with predefined table") + } + + // Bail out.... Just generate something + huffBuff = append(huffBuff, bytes.Repeat([]byte{255}, 10000)...) + for i := 0; i < 128; i++ { + huffBuff = append(huffBuff, byte(i)) + } + continue + } + if errors.Is(err, huff0.ErrIncompressible) { + // Try truncating least common. + for i, n := range remain[:] { + if n > 0 { + n = n / (div * (i + 1)) + if n > 0 { + huffBuff = append(huffBuff, bytes.Repeat([]byte{byte(i)}, n)...) + } + } + } + if o.CompatV155 && len(huffBuff) > 0 && huffBuff[len(huffBuff)-1] != 255 { + huffBuff = append(huffBuff, 255) + } + if len(huffBuff) == 0 { + huffBuff = append(huffBuff, 0, 255) + } + } + if errors.Is(err, huff0.ErrUseRLE) { + for i, n := range remain[:] { + n = n / (div * (i + 1)) + // Allow all entries to be represented. + if n == 0 { + n = 1 + } + huffBuff = append(huffBuff, bytes.Repeat([]byte{byte(i)}, n)...) + } + } + } + + var out bytes.Buffer + out.Write([]byte(dictMagic)) + out.Write(binary.LittleEndian.AppendUint32(nil, o.ID)) + out.Write(scratch.OutTable) + if debug { + println("huff table:", len(scratch.OutTable), "bytes") + println("of table:", len(ofTable), "bytes") + println("ml table:", len(mlTable), "bytes") + println("ll table:", len(llTable), "bytes") + } + out.Write(ofTable) + out.Write(mlTable) + out.Write(llTable) + out.Write(binary.LittleEndian.AppendUint32(nil, uint32(o.Offsets[0]))) + out.Write(binary.LittleEndian.AppendUint32(nil, uint32(o.Offsets[1]))) + out.Write(binary.LittleEndian.AppendUint32(nil, uint32(o.Offsets[2]))) + out.Write(hist) + if debug { + _, err := loadDict(out.Bytes()) + if err != nil { + panic(err) + } + i, err := InspectDictionary(out.Bytes()) + if err != nil { + panic(err) + } + println("ID:", i.ID()) + println("Content size:", i.ContentSize()) + println("Encoder:", i.LitEncoder() != nil) + println("Offsets:", i.Offsets()) + var totalSize int + for _, b := range contents { + totalSize += len(b) + } + + encWith := func(opts ...EOption) int { + enc, err := NewWriter(nil, opts...) + if err != nil { + panic(err) + } + defer enc.Close() + var dst []byte + var totalSize int + for _, b := range contents { + dst = enc.EncodeAll(b, dst[:0]) + totalSize += len(dst) + } + return totalSize + } + plain := encWith(WithEncoderLevel(o.Level)) + withDict := encWith(WithEncoderLevel(o.Level), WithEncoderDict(out.Bytes())) + println("Input size:", totalSize) + println("Plain Compressed:", plain) + println("Dict Compressed:", withDict) + println("Saved:", plain-withDict, (plain-withDict)/len(contents), "bytes per input (rounded down)") + } + return out.Bytes(), nil +} diff --git a/vendor/github.com/klauspost/compress/zstd/enc_base.go b/vendor/github.com/klauspost/compress/zstd/enc_base.go new file mode 100644 index 000000000..5ca46038a --- /dev/null +++ b/vendor/github.com/klauspost/compress/zstd/enc_base.go @@ -0,0 +1,173 @@ +package zstd + +import ( + "fmt" + "math/bits" + + "github.com/klauspost/compress/zstd/internal/xxhash" +) + +const ( + dictShardBits = 6 +) + +type fastBase struct { + // cur is the offset at the start of hist + cur int32 + // maximum offset. Should be at least 2x block size. + maxMatchOff int32 + bufferReset int32 + hist []byte + crc *xxhash.Digest + tmp [8]byte + blk *blockEnc + lastDictID uint32 + lowMem bool +} + +// CRC returns the underlying CRC writer. +func (e *fastBase) CRC() *xxhash.Digest { + return e.crc +} + +// AppendCRC will append the CRC to the destination slice and return it. +func (e *fastBase) AppendCRC(dst []byte) []byte { + crc := e.crc.Sum(e.tmp[:0]) + dst = append(dst, crc[7], crc[6], crc[5], crc[4]) + return dst +} + +// WindowSize returns the window size of the encoder, +// or a window size small enough to contain the input size, if > 0. +func (e *fastBase) WindowSize(size int64) int32 { + if size > 0 && size < int64(e.maxMatchOff) { + b := int32(1) << uint(bits.Len(uint(size))) + // Keep minimum window. + if b < 1024 { + b = 1024 + } + return b + } + return e.maxMatchOff +} + +// Block returns the current block. +func (e *fastBase) Block() *blockEnc { + return e.blk +} + +func (e *fastBase) addBlock(src []byte) int32 { + if debugAsserts && e.cur > e.bufferReset { + panic(fmt.Sprintf("ecur (%d) > buffer reset (%d)", e.cur, e.bufferReset)) + } + // check if we have space already + if len(e.hist)+len(src) > cap(e.hist) { + if cap(e.hist) == 0 { + e.ensureHist(len(src)) + } else { + if cap(e.hist) < int(e.maxMatchOff+maxCompressedBlockSize) { + panic(fmt.Errorf("unexpected buffer cap %d, want at least %d with window %d", cap(e.hist), e.maxMatchOff+maxCompressedBlockSize, e.maxMatchOff)) + } + // Move down + offset := int32(len(e.hist)) - e.maxMatchOff + copy(e.hist[0:e.maxMatchOff], e.hist[offset:]) + e.cur += offset + e.hist = e.hist[:e.maxMatchOff] + } + } + s := int32(len(e.hist)) + e.hist = append(e.hist, src...) + return s +} + +// ensureHist will ensure that history can keep at least this many bytes. +func (e *fastBase) ensureHist(n int) { + if cap(e.hist) >= n { + return + } + l := e.maxMatchOff + if (e.lowMem && e.maxMatchOff > maxCompressedBlockSize) || e.maxMatchOff <= maxCompressedBlockSize { + l += maxCompressedBlockSize + } else { + l += e.maxMatchOff + } + // Make it at least 1MB. + if l < 1<<20 && !e.lowMem { + l = 1 << 20 + } + // Make it at least the requested size. + if l < int32(n) { + l = int32(n) + } + e.hist = make([]byte, 0, l) +} + +// useBlock will replace the block with the provided one, +// but transfer recent offsets from the previous. +func (e *fastBase) UseBlock(enc *blockEnc) { + enc.reset(e.blk) + e.blk = enc +} + +func (e *fastBase) matchlen(s, t int32, src []byte) int32 { + if debugAsserts { + if s < 0 { + err := fmt.Sprintf("s (%d) < 0", s) + panic(err) + } + if t < 0 { + err := fmt.Sprintf("s (%d) < 0", s) + panic(err) + } + if s-t > e.maxMatchOff { + err := fmt.Sprintf("s (%d) - t (%d) > maxMatchOff (%d)", s, t, e.maxMatchOff) + panic(err) + } + if len(src)-int(s) > maxCompressedBlockSize { + panic(fmt.Sprintf("len(src)-s (%d) > maxCompressedBlockSize (%d)", len(src)-int(s), maxCompressedBlockSize)) + } + } + return int32(matchLen(src[s:], src[t:])) +} + +// Reset the encoding table. +func (e *fastBase) resetBase(d *dict, singleBlock bool) { + if e.blk == nil { + e.blk = &blockEnc{lowMem: e.lowMem} + e.blk.init() + } else { + e.blk.reset(nil) + } + e.blk.initNewEncode() + if e.crc == nil { + e.crc = xxhash.New() + } else { + e.crc.Reset() + } + e.blk.dictLitEnc = nil + if d != nil { + low := e.lowMem + if singleBlock { + e.lowMem = true + } + e.ensureHist(d.ContentSize() + maxCompressedBlockSize) + e.lowMem = low + } + + // We offset current position so everything will be out of reach. + // If above reset line, history will be purged. + if e.cur < e.bufferReset { + e.cur += e.maxMatchOff + int32(len(e.hist)) + } + e.hist = e.hist[:0] + if d != nil { + // Set offsets (currently not used) + for i, off := range d.offsets { + e.blk.recentOffsets[i] = uint32(off) + e.blk.prevRecentOffsets[i] = e.blk.recentOffsets[i] + } + // Transfer litenc. + e.blk.dictLitEnc = d.litEnc + e.hist = append(e.hist, d.content...) + } +} diff --git a/vendor/github.com/klauspost/compress/zstd/enc_best.go b/vendor/github.com/klauspost/compress/zstd/enc_best.go new file mode 100644 index 000000000..4613724e9 --- /dev/null +++ b/vendor/github.com/klauspost/compress/zstd/enc_best.go @@ -0,0 +1,560 @@ +// Copyright 2019+ Klaus Post. All rights reserved. +// License information can be found in the LICENSE file. +// Based on work by Yann Collet, released under BSD License. + +package zstd + +import ( + "bytes" + "fmt" + + "github.com/klauspost/compress" +) + +const ( + bestLongTableBits = 22 // Bits used in the long match table + bestLongTableSize = 1 << bestLongTableBits // Size of the table + bestLongLen = 8 // Bytes used for table hash + + // Note: Increasing the short table bits or making the hash shorter + // can actually lead to compression degradation since it will 'steal' more from the + // long match table and match offsets are quite big. + // This greatly depends on the type of input. + bestShortTableBits = 18 // Bits used in the short match table + bestShortTableSize = 1 << bestShortTableBits // Size of the table + bestShortLen = 4 // Bytes used for table hash + +) + +type match struct { + offset int32 + s int32 + length int32 + rep int32 + est int32 +} + +const highScore = maxMatchLen * 8 + +// estBits will estimate output bits from predefined tables. +func (m *match) estBits(bitsPerByte int32) { + mlc := mlCode(uint32(m.length - zstdMinMatch)) + var ofc uint8 + if m.rep < 0 { + ofc = ofCode(uint32(m.s-m.offset) + 3) + } else { + ofc = ofCode(uint32(m.rep) & 3) + } + // Cost, excluding + ofTT, mlTT := fsePredefEnc[tableOffsets].ct.symbolTT[ofc], fsePredefEnc[tableMatchLengths].ct.symbolTT[mlc] + + // Add cost of match encoding... + m.est = int32(ofTT.outBits + mlTT.outBits) + m.est += int32(ofTT.deltaNbBits>>16 + mlTT.deltaNbBits>>16) + // Subtract savings compared to literal encoding... + m.est -= (m.length * bitsPerByte) >> 10 + if m.est > 0 { + // Unlikely gain.. + m.length = 0 + m.est = highScore + } +} + +// bestFastEncoder uses 2 tables, one for short matches (5 bytes) and one for long matches. +// The long match table contains the previous entry with the same hash, +// effectively making it a "chain" of length 2. +// When we find a long match we choose between the two values and select the longest. +// When we find a short match, after checking the long, we check if we can find a long at n+1 +// and that it is longer (lazy matching). +type bestFastEncoder struct { + fastBase + table [bestShortTableSize]prevEntry + longTable [bestLongTableSize]prevEntry + dictTable []prevEntry + dictLongTable []prevEntry +} + +// Encode improves compression... +func (e *bestFastEncoder) Encode(blk *blockEnc, src []byte) { + const ( + // Input margin is the number of bytes we read (8) + // and the maximum we will read ahead (2) + inputMargin = 8 + 4 + minNonLiteralBlockSize = 16 + ) + + // Protect against e.cur wraparound. + for e.cur >= e.bufferReset-int32(len(e.hist)) { + if len(e.hist) == 0 { + e.table = [bestShortTableSize]prevEntry{} + e.longTable = [bestLongTableSize]prevEntry{} + e.cur = e.maxMatchOff + break + } + // Shift down everything in the table that isn't already too far away. + minOff := e.cur + int32(len(e.hist)) - e.maxMatchOff + for i := range e.table[:] { + v := e.table[i].offset + v2 := e.table[i].prev + if v < minOff { + v = 0 + v2 = 0 + } else { + v = v - e.cur + e.maxMatchOff + if v2 < minOff { + v2 = 0 + } else { + v2 = v2 - e.cur + e.maxMatchOff + } + } + e.table[i] = prevEntry{ + offset: v, + prev: v2, + } + } + for i := range e.longTable[:] { + v := e.longTable[i].offset + v2 := e.longTable[i].prev + if v < minOff { + v = 0 + v2 = 0 + } else { + v = v - e.cur + e.maxMatchOff + if v2 < minOff { + v2 = 0 + } else { + v2 = v2 - e.cur + e.maxMatchOff + } + } + e.longTable[i] = prevEntry{ + offset: v, + prev: v2, + } + } + e.cur = e.maxMatchOff + break + } + + // Add block to history + s := e.addBlock(src) + blk.size = len(src) + + // Check RLE first + if len(src) > zstdMinMatch { + ml := matchLen(src[1:], src) + if ml == len(src)-1 { + blk.literals = append(blk.literals, src[0]) + blk.sequences = append(blk.sequences, seq{litLen: 1, matchLen: uint32(len(src)-1) - zstdMinMatch, offset: 1 + 3}) + return + } + } + + if len(src) < minNonLiteralBlockSize { + blk.extraLits = len(src) + blk.literals = blk.literals[:len(src)] + copy(blk.literals, src) + return + } + + // Use this to estimate literal cost. + // Scaled by 10 bits. + bitsPerByte := int32((compress.ShannonEntropyBits(src) * 1024) / len(src)) + // Huffman can never go < 1 bit/byte + if bitsPerByte < 1024 { + bitsPerByte = 1024 + } + + // Override src + src = e.hist + sLimit := int32(len(src)) - inputMargin + const kSearchStrength = 10 + + // nextEmit is where in src the next emitLiteral should start from. + nextEmit := s + + // Relative offsets + offset1 := int32(blk.recentOffsets[0]) + offset2 := int32(blk.recentOffsets[1]) + offset3 := int32(blk.recentOffsets[2]) + + addLiterals := func(s *seq, until int32) { + if until == nextEmit { + return + } + blk.literals = append(blk.literals, src[nextEmit:until]...) + s.litLen = uint32(until - nextEmit) + } + + if debugEncoder { + println("recent offsets:", blk.recentOffsets) + } + +encodeLoop: + for { + // We allow the encoder to optionally turn off repeat offsets across blocks + canRepeat := len(blk.sequences) > 2 + + if debugAsserts && canRepeat && offset1 == 0 { + panic("offset0 was 0") + } + + const goodEnough = 250 + + cv := load6432(src, s) + + nextHashL := hashLen(cv, bestLongTableBits, bestLongLen) + nextHashS := hashLen(cv, bestShortTableBits, bestShortLen) + candidateL := e.longTable[nextHashL] + candidateS := e.table[nextHashS] + + // Set m to a match at offset if it looks like that will improve compression. + improve := func(m *match, offset int32, s int32, first uint32, rep int32) { + delta := s - offset + if delta >= e.maxMatchOff || delta <= 0 || load3232(src, offset) != first { + return + } + // Try to quick reject if we already have a long match. + if m.length > 16 { + left := len(src) - int(m.s+m.length) + // If we are too close to the end, keep as is. + if left <= 0 { + return + } + checkLen := m.length - (s - m.s) - 8 + if left > 2 && checkLen > 4 { + // Check 4 bytes, 4 bytes from the end of the current match. + a := load3232(src, offset+checkLen) + b := load3232(src, s+checkLen) + if a != b { + return + } + } + } + l := 4 + e.matchlen(s+4, offset+4, src) + if m.rep <= 0 { + // Extend candidate match backwards as far as possible. + // Do not extend repeats as we can assume they are optimal + // and offsets change if s == nextEmit. + tMin := s - e.maxMatchOff + if tMin < 0 { + tMin = 0 + } + for offset > tMin && s > nextEmit && src[offset-1] == src[s-1] && l < maxMatchLength { + s-- + offset-- + l++ + } + } + if debugAsserts { + if offset >= s { + panic(fmt.Sprintf("offset: %d - s:%d - rep: %d - cur :%d - max: %d", offset, s, rep, e.cur, e.maxMatchOff)) + } + if !bytes.Equal(src[s:s+l], src[offset:offset+l]) { + panic(fmt.Sprintf("second match mismatch: %v != %v, first: %08x", src[s:s+4], src[offset:offset+4], first)) + } + } + cand := match{offset: offset, s: s, length: l, rep: rep} + cand.estBits(bitsPerByte) + if m.est >= highScore || cand.est-m.est+(cand.s-m.s)*bitsPerByte>>10 < 0 { + *m = cand + } + } + + best := match{s: s, est: highScore} + improve(&best, candidateL.offset-e.cur, s, uint32(cv), -1) + improve(&best, candidateL.prev-e.cur, s, uint32(cv), -1) + improve(&best, candidateS.offset-e.cur, s, uint32(cv), -1) + improve(&best, candidateS.prev-e.cur, s, uint32(cv), -1) + + if canRepeat && best.length < goodEnough { + if s == nextEmit { + // Check repeats straight after a match. + improve(&best, s-offset2, s, uint32(cv), 1|4) + improve(&best, s-offset3, s, uint32(cv), 2|4) + if offset1 > 1 { + improve(&best, s-(offset1-1), s, uint32(cv), 3|4) + } + } + + // If either no match or a non-repeat match, check at + 1 + if best.rep <= 0 { + cv32 := uint32(cv >> 8) + spp := s + 1 + improve(&best, spp-offset1, spp, cv32, 1) + improve(&best, spp-offset2, spp, cv32, 2) + improve(&best, spp-offset3, spp, cv32, 3) + if best.rep < 0 { + cv32 = uint32(cv >> 24) + spp += 2 + improve(&best, spp-offset1, spp, cv32, 1) + improve(&best, spp-offset2, spp, cv32, 2) + improve(&best, spp-offset3, spp, cv32, 3) + } + } + } + // Load next and check... + e.longTable[nextHashL] = prevEntry{offset: s + e.cur, prev: candidateL.offset} + e.table[nextHashS] = prevEntry{offset: s + e.cur, prev: candidateS.offset} + index0 := s + 1 + + // Look far ahead, unless we have a really long match already... + if best.length < goodEnough { + // No match found, move forward on input, no need to check forward... + if best.length < 4 { + s += 1 + (s-nextEmit)>>(kSearchStrength-1) + if s >= sLimit { + break encodeLoop + } + continue + } + + candidateS = e.table[hashLen(cv>>8, bestShortTableBits, bestShortLen)] + cv = load6432(src, s+1) + cv2 := load6432(src, s+2) + candidateL = e.longTable[hashLen(cv, bestLongTableBits, bestLongLen)] + candidateL2 := e.longTable[hashLen(cv2, bestLongTableBits, bestLongLen)] + + // Short at s+1 + improve(&best, candidateS.offset-e.cur, s+1, uint32(cv), -1) + // Long at s+1, s+2 + improve(&best, candidateL.offset-e.cur, s+1, uint32(cv), -1) + improve(&best, candidateL.prev-e.cur, s+1, uint32(cv), -1) + improve(&best, candidateL2.offset-e.cur, s+2, uint32(cv2), -1) + improve(&best, candidateL2.prev-e.cur, s+2, uint32(cv2), -1) + if false { + // Short at s+3. + // Too often worse... + improve(&best, e.table[hashLen(cv2>>8, bestShortTableBits, bestShortLen)].offset-e.cur, s+3, uint32(cv2>>8), -1) + } + + // Start check at a fixed offset to allow for a few mismatches. + // For this compression level 2 yields the best results. + // We cannot do this if we have already indexed this position. + const skipBeginning = 2 + if best.s > s-skipBeginning { + // See if we can find a better match by checking where the current best ends. + // Use that offset to see if we can find a better full match. + if sAt := best.s + best.length; sAt < sLimit { + nextHashL := hashLen(load6432(src, sAt), bestLongTableBits, bestLongLen) + candidateEnd := e.longTable[nextHashL] + + if off := candidateEnd.offset - e.cur - best.length + skipBeginning; off >= 0 { + improve(&best, off, best.s+skipBeginning, load3232(src, best.s+skipBeginning), -1) + if off := candidateEnd.prev - e.cur - best.length + skipBeginning; off >= 0 { + improve(&best, off, best.s+skipBeginning, load3232(src, best.s+skipBeginning), -1) + } + } + } + } + } + + if debugAsserts { + if best.offset >= best.s { + panic(fmt.Sprintf("best.offset > s: %d >= %d", best.offset, best.s)) + } + if best.s < nextEmit { + panic(fmt.Sprintf("s %d < nextEmit %d", best.s, nextEmit)) + } + if best.offset < s-e.maxMatchOff { + panic(fmt.Sprintf("best.offset < s-e.maxMatchOff: %d < %d", best.offset, s-e.maxMatchOff)) + } + if !bytes.Equal(src[best.s:best.s+best.length], src[best.offset:best.offset+best.length]) { + panic(fmt.Sprintf("match mismatch: %v != %v", src[best.s:best.s+best.length], src[best.offset:best.offset+best.length])) + } + } + + // We have a match, we can store the forward value + s = best.s + if best.rep > 0 { + var seq seq + seq.matchLen = uint32(best.length - zstdMinMatch) + addLiterals(&seq, best.s) + + // Repeat. If bit 4 is set, this is a non-lit repeat. + seq.offset = uint32(best.rep & 3) + if debugSequences { + println("repeat sequence", seq, "next s:", best.s, "off:", best.s-best.offset) + } + blk.sequences = append(blk.sequences, seq) + + // Index old s + 1 -> s - 1 + s = best.s + best.length + nextEmit = s + + // Index skipped... + end := s + if s > sLimit+4 { + end = sLimit + 4 + } + off := index0 + e.cur + for index0 < end { + cv0 := load6432(src, index0) + h0 := hashLen(cv0, bestLongTableBits, bestLongLen) + h1 := hashLen(cv0, bestShortTableBits, bestShortLen) + e.longTable[h0] = prevEntry{offset: off, prev: e.longTable[h0].offset} + e.table[h1] = prevEntry{offset: off, prev: e.table[h1].offset} + off++ + index0++ + } + + switch best.rep { + case 2, 4 | 1: + offset1, offset2 = offset2, offset1 + case 3, 4 | 2: + offset1, offset2, offset3 = offset3, offset1, offset2 + case 4 | 3: + offset1, offset2, offset3 = offset1-1, offset1, offset2 + } + if s >= sLimit { + if debugEncoder { + println("repeat ended", s, best.length) + } + break encodeLoop + } + continue + } + + // A 4-byte match has been found. Update recent offsets. + // We'll later see if more than 4 bytes. + t := best.offset + offset1, offset2, offset3 = s-t, offset1, offset2 + + if debugAsserts && s <= t { + panic(fmt.Sprintf("s (%d) <= t (%d)", s, t)) + } + + if debugAsserts && int(offset1) > len(src) { + panic("invalid offset") + } + + // Write our sequence + var seq seq + l := best.length + seq.litLen = uint32(s - nextEmit) + seq.matchLen = uint32(l - zstdMinMatch) + if seq.litLen > 0 { + blk.literals = append(blk.literals, src[nextEmit:s]...) + } + seq.offset = uint32(s-t) + 3 + s += l + if debugSequences { + println("sequence", seq, "next s:", s) + } + blk.sequences = append(blk.sequences, seq) + nextEmit = s + + // Index old s + 1 -> s - 1 or sLimit + end := s + if s > sLimit-4 { + end = sLimit - 4 + } + + off := index0 + e.cur + for index0 < end { + cv0 := load6432(src, index0) + h0 := hashLen(cv0, bestLongTableBits, bestLongLen) + h1 := hashLen(cv0, bestShortTableBits, bestShortLen) + e.longTable[h0] = prevEntry{offset: off, prev: e.longTable[h0].offset} + e.table[h1] = prevEntry{offset: off, prev: e.table[h1].offset} + index0++ + off++ + } + if s >= sLimit { + break encodeLoop + } + } + + if int(nextEmit) < len(src) { + blk.literals = append(blk.literals, src[nextEmit:]...) + blk.extraLits = len(src) - int(nextEmit) + } + blk.recentOffsets[0] = uint32(offset1) + blk.recentOffsets[1] = uint32(offset2) + blk.recentOffsets[2] = uint32(offset3) + if debugEncoder { + println("returning, recent offsets:", blk.recentOffsets, "extra literals:", blk.extraLits) + } +} + +// EncodeNoHist will encode a block with no history and no following blocks. +// Most notable difference is that src will not be copied for history and +// we do not need to check for max match length. +func (e *bestFastEncoder) EncodeNoHist(blk *blockEnc, src []byte) { + e.ensureHist(len(src)) + e.Encode(blk, src) +} + +// Reset will reset and set a dictionary if not nil +func (e *bestFastEncoder) Reset(d *dict, singleBlock bool) { + e.resetBase(d, singleBlock) + if d == nil { + return + } + // Init or copy dict table + if len(e.dictTable) != len(e.table) || d.id != e.lastDictID { + if len(e.dictTable) != len(e.table) { + e.dictTable = make([]prevEntry, len(e.table)) + } + end := int32(len(d.content)) - 8 + e.maxMatchOff + for i := e.maxMatchOff; i < end; i += 4 { + const hashLog = bestShortTableBits + + cv := load6432(d.content, i-e.maxMatchOff) + nextHash := hashLen(cv, hashLog, bestShortLen) // 0 -> 4 + nextHash1 := hashLen(cv>>8, hashLog, bestShortLen) // 1 -> 5 + nextHash2 := hashLen(cv>>16, hashLog, bestShortLen) // 2 -> 6 + nextHash3 := hashLen(cv>>24, hashLog, bestShortLen) // 3 -> 7 + e.dictTable[nextHash] = prevEntry{ + prev: e.dictTable[nextHash].offset, + offset: i, + } + e.dictTable[nextHash1] = prevEntry{ + prev: e.dictTable[nextHash1].offset, + offset: i + 1, + } + e.dictTable[nextHash2] = prevEntry{ + prev: e.dictTable[nextHash2].offset, + offset: i + 2, + } + e.dictTable[nextHash3] = prevEntry{ + prev: e.dictTable[nextHash3].offset, + offset: i + 3, + } + } + e.lastDictID = d.id + } + + // Init or copy dict table + if len(e.dictLongTable) != len(e.longTable) || d.id != e.lastDictID { + if len(e.dictLongTable) != len(e.longTable) { + e.dictLongTable = make([]prevEntry, len(e.longTable)) + } + if len(d.content) >= 8 { + cv := load6432(d.content, 0) + h := hashLen(cv, bestLongTableBits, bestLongLen) + e.dictLongTable[h] = prevEntry{ + offset: e.maxMatchOff, + prev: e.dictLongTable[h].offset, + } + + end := int32(len(d.content)) - 8 + e.maxMatchOff + off := 8 // First to read + for i := e.maxMatchOff + 1; i < end; i++ { + cv = cv>>8 | (uint64(d.content[off]) << 56) + h := hashLen(cv, bestLongTableBits, bestLongLen) + e.dictLongTable[h] = prevEntry{ + offset: i, + prev: e.dictLongTable[h].offset, + } + off++ + } + } + e.lastDictID = d.id + } + // Reset table to initial state + copy(e.longTable[:], e.dictLongTable) + + e.cur = e.maxMatchOff + // Reset table to initial state + copy(e.table[:], e.dictTable) +} diff --git a/vendor/github.com/klauspost/compress/zstd/enc_better.go b/vendor/github.com/klauspost/compress/zstd/enc_better.go new file mode 100644 index 000000000..a4f5bf91f --- /dev/null +++ b/vendor/github.com/klauspost/compress/zstd/enc_better.go @@ -0,0 +1,1252 @@ +// Copyright 2019+ Klaus Post. All rights reserved. +// License information can be found in the LICENSE file. +// Based on work by Yann Collet, released under BSD License. + +package zstd + +import "fmt" + +const ( + betterLongTableBits = 19 // Bits used in the long match table + betterLongTableSize = 1 << betterLongTableBits // Size of the table + betterLongLen = 8 // Bytes used for table hash + + // Note: Increasing the short table bits or making the hash shorter + // can actually lead to compression degradation since it will 'steal' more from the + // long match table and match offsets are quite big. + // This greatly depends on the type of input. + betterShortTableBits = 13 // Bits used in the short match table + betterShortTableSize = 1 << betterShortTableBits // Size of the table + betterShortLen = 5 // Bytes used for table hash + + betterLongTableShardCnt = 1 << (betterLongTableBits - dictShardBits) // Number of shards in the table + betterLongTableShardSize = betterLongTableSize / betterLongTableShardCnt // Size of an individual shard + + betterShortTableShardCnt = 1 << (betterShortTableBits - dictShardBits) // Number of shards in the table + betterShortTableShardSize = betterShortTableSize / betterShortTableShardCnt // Size of an individual shard +) + +type prevEntry struct { + offset int32 + prev int32 +} + +// betterFastEncoder uses 2 tables, one for short matches (5 bytes) and one for long matches. +// The long match table contains the previous entry with the same hash, +// effectively making it a "chain" of length 2. +// When we find a long match we choose between the two values and select the longest. +// When we find a short match, after checking the long, we check if we can find a long at n+1 +// and that it is longer (lazy matching). +type betterFastEncoder struct { + fastBase + table [betterShortTableSize]tableEntry + longTable [betterLongTableSize]prevEntry +} + +type betterFastEncoderDict struct { + betterFastEncoder + dictTable []tableEntry + dictLongTable []prevEntry + shortTableShardDirty [betterShortTableShardCnt]bool + longTableShardDirty [betterLongTableShardCnt]bool + allDirty bool +} + +// Encode improves compression... +func (e *betterFastEncoder) Encode(blk *blockEnc, src []byte) { + const ( + // Input margin is the number of bytes we read (8) + // and the maximum we will read ahead (2) + inputMargin = 8 + 2 + minNonLiteralBlockSize = 16 + ) + + // Protect against e.cur wraparound. + for e.cur >= e.bufferReset-int32(len(e.hist)) { + if len(e.hist) == 0 { + e.table = [betterShortTableSize]tableEntry{} + e.longTable = [betterLongTableSize]prevEntry{} + e.cur = e.maxMatchOff + break + } + // Shift down everything in the table that isn't already too far away. + minOff := e.cur + int32(len(e.hist)) - e.maxMatchOff + for i := range e.table[:] { + v := e.table[i].offset + if v < minOff { + v = 0 + } else { + v = v - e.cur + e.maxMatchOff + } + e.table[i].offset = v + } + for i := range e.longTable[:] { + v := e.longTable[i].offset + v2 := e.longTable[i].prev + if v < minOff { + v = 0 + v2 = 0 + } else { + v = v - e.cur + e.maxMatchOff + if v2 < minOff { + v2 = 0 + } else { + v2 = v2 - e.cur + e.maxMatchOff + } + } + e.longTable[i] = prevEntry{ + offset: v, + prev: v2, + } + } + e.cur = e.maxMatchOff + break + } + // Add block to history + s := e.addBlock(src) + blk.size = len(src) + + // Check RLE first + if len(src) > zstdMinMatch { + ml := matchLen(src[1:], src) + if ml == len(src)-1 { + blk.literals = append(blk.literals, src[0]) + blk.sequences = append(blk.sequences, seq{litLen: 1, matchLen: uint32(len(src)-1) - zstdMinMatch, offset: 1 + 3}) + return + } + } + + if len(src) < minNonLiteralBlockSize { + blk.extraLits = len(src) + blk.literals = blk.literals[:len(src)] + copy(blk.literals, src) + return + } + + // Override src + src = e.hist + sLimit := int32(len(src)) - inputMargin + // stepSize is the number of bytes to skip on every main loop iteration. + // It should be >= 1. + const stepSize = 1 + + const kSearchStrength = 9 + + // nextEmit is where in src the next emitLiteral should start from. + nextEmit := s + cv := load6432(src, s) + + // Relative offsets + offset1 := int32(blk.recentOffsets[0]) + offset2 := int32(blk.recentOffsets[1]) + + addLiterals := func(s *seq, until int32) { + if until == nextEmit { + return + } + blk.literals = append(blk.literals, src[nextEmit:until]...) + s.litLen = uint32(until - nextEmit) + } + if debugEncoder { + println("recent offsets:", blk.recentOffsets) + } + +encodeLoop: + for { + var t int32 + // We allow the encoder to optionally turn off repeat offsets across blocks + canRepeat := len(blk.sequences) > 2 + var matched, index0 int32 + + for { + if debugAsserts && canRepeat && offset1 == 0 { + panic("offset0 was 0") + } + + nextHashL := hashLen(cv, betterLongTableBits, betterLongLen) + nextHashS := hashLen(cv, betterShortTableBits, betterShortLen) + candidateL := e.longTable[nextHashL] + candidateS := e.table[nextHashS] + + const repOff = 1 + repIndex := s - offset1 + repOff + off := s + e.cur + e.longTable[nextHashL] = prevEntry{offset: off, prev: candidateL.offset} + e.table[nextHashS] = tableEntry{offset: off, val: uint32(cv)} + index0 = s + 1 + + if canRepeat { + if repIndex >= 0 && load3232(src, repIndex) == uint32(cv>>(repOff*8)) { + // Consider history as well. + var seq seq + lenght := 4 + e.matchlen(s+4+repOff, repIndex+4, src) + + seq.matchLen = uint32(lenght - zstdMinMatch) + + // We might be able to match backwards. + // Extend as long as we can. + start := s + repOff + // We end the search early, so we don't risk 0 literals + // and have to do special offset treatment. + startLimit := nextEmit + 1 + + tMin := s - e.maxMatchOff + if tMin < 0 { + tMin = 0 + } + for repIndex > tMin && start > startLimit && src[repIndex-1] == src[start-1] && seq.matchLen < maxMatchLength-zstdMinMatch-1 { + repIndex-- + start-- + seq.matchLen++ + } + addLiterals(&seq, start) + + // rep 0 + seq.offset = 1 + if debugSequences { + println("repeat sequence", seq, "next s:", s) + } + blk.sequences = append(blk.sequences, seq) + + // Index match start+1 (long) -> s - 1 + index0 := s + repOff + s += lenght + repOff + + nextEmit = s + if s >= sLimit { + if debugEncoder { + println("repeat ended", s, lenght) + + } + break encodeLoop + } + // Index skipped... + for index0 < s-1 { + cv0 := load6432(src, index0) + cv1 := cv0 >> 8 + h0 := hashLen(cv0, betterLongTableBits, betterLongLen) + off := index0 + e.cur + e.longTable[h0] = prevEntry{offset: off, prev: e.longTable[h0].offset} + e.table[hashLen(cv1, betterShortTableBits, betterShortLen)] = tableEntry{offset: off + 1, val: uint32(cv1)} + index0 += 2 + } + cv = load6432(src, s) + continue + } + const repOff2 = 1 + + // We deviate from the reference encoder and also check offset 2. + // Still slower and not much better, so disabled. + // repIndex = s - offset2 + repOff2 + if false && repIndex >= 0 && load6432(src, repIndex) == load6432(src, s+repOff) { + // Consider history as well. + var seq seq + lenght := 8 + e.matchlen(s+8+repOff2, repIndex+8, src) + + seq.matchLen = uint32(lenght - zstdMinMatch) + + // We might be able to match backwards. + // Extend as long as we can. + start := s + repOff2 + // We end the search early, so we don't risk 0 literals + // and have to do special offset treatment. + startLimit := nextEmit + 1 + + tMin := s - e.maxMatchOff + if tMin < 0 { + tMin = 0 + } + for repIndex > tMin && start > startLimit && src[repIndex-1] == src[start-1] && seq.matchLen < maxMatchLength-zstdMinMatch-1 { + repIndex-- + start-- + seq.matchLen++ + } + addLiterals(&seq, start) + + // rep 2 + seq.offset = 2 + if debugSequences { + println("repeat sequence 2", seq, "next s:", s) + } + blk.sequences = append(blk.sequences, seq) + + s += lenght + repOff2 + nextEmit = s + if s >= sLimit { + if debugEncoder { + println("repeat ended", s, lenght) + + } + break encodeLoop + } + + // Index skipped... + for index0 < s-1 { + cv0 := load6432(src, index0) + cv1 := cv0 >> 8 + h0 := hashLen(cv0, betterLongTableBits, betterLongLen) + off := index0 + e.cur + e.longTable[h0] = prevEntry{offset: off, prev: e.longTable[h0].offset} + e.table[hashLen(cv1, betterShortTableBits, betterShortLen)] = tableEntry{offset: off + 1, val: uint32(cv1)} + index0 += 2 + } + cv = load6432(src, s) + // Swap offsets + offset1, offset2 = offset2, offset1 + continue + } + } + // Find the offsets of our two matches. + coffsetL := candidateL.offset - e.cur + coffsetLP := candidateL.prev - e.cur + + // Check if we have a long match. + if s-coffsetL < e.maxMatchOff && cv == load6432(src, coffsetL) { + // Found a long match, at least 8 bytes. + matched = e.matchlen(s+8, coffsetL+8, src) + 8 + t = coffsetL + if debugAsserts && s <= t { + panic(fmt.Sprintf("s (%d) <= t (%d)", s, t)) + } + if debugAsserts && s-t > e.maxMatchOff { + panic("s - t >e.maxMatchOff") + } + if debugMatches { + println("long match") + } + + if s-coffsetLP < e.maxMatchOff && cv == load6432(src, coffsetLP) { + // Found a long match, at least 8 bytes. + prevMatch := e.matchlen(s+8, coffsetLP+8, src) + 8 + if prevMatch > matched { + matched = prevMatch + t = coffsetLP + } + if debugAsserts && s <= t { + panic(fmt.Sprintf("s (%d) <= t (%d)", s, t)) + } + if debugAsserts && s-t > e.maxMatchOff { + panic("s - t >e.maxMatchOff") + } + if debugMatches { + println("long match") + } + } + break + } + + // Check if we have a long match on prev. + if s-coffsetLP < e.maxMatchOff && cv == load6432(src, coffsetLP) { + // Found a long match, at least 8 bytes. + matched = e.matchlen(s+8, coffsetLP+8, src) + 8 + t = coffsetLP + if debugAsserts && s <= t { + panic(fmt.Sprintf("s (%d) <= t (%d)", s, t)) + } + if debugAsserts && s-t > e.maxMatchOff { + panic("s - t >e.maxMatchOff") + } + if debugMatches { + println("long match") + } + break + } + + coffsetS := candidateS.offset - e.cur + + // Check if we have a short match. + if s-coffsetS < e.maxMatchOff && uint32(cv) == candidateS.val { + // found a regular match + matched = e.matchlen(s+4, coffsetS+4, src) + 4 + + // See if we can find a long match at s+1 + const checkAt = 1 + cv := load6432(src, s+checkAt) + nextHashL = hashLen(cv, betterLongTableBits, betterLongLen) + candidateL = e.longTable[nextHashL] + coffsetL = candidateL.offset - e.cur + + // We can store it, since we have at least a 4 byte match. + e.longTable[nextHashL] = prevEntry{offset: s + checkAt + e.cur, prev: candidateL.offset} + if s-coffsetL < e.maxMatchOff && cv == load6432(src, coffsetL) { + // Found a long match, at least 8 bytes. + matchedNext := e.matchlen(s+8+checkAt, coffsetL+8, src) + 8 + if matchedNext > matched { + t = coffsetL + s += checkAt + matched = matchedNext + if debugMatches { + println("long match (after short)") + } + break + } + } + + // Check prev long... + coffsetL = candidateL.prev - e.cur + if s-coffsetL < e.maxMatchOff && cv == load6432(src, coffsetL) { + // Found a long match, at least 8 bytes. + matchedNext := e.matchlen(s+8+checkAt, coffsetL+8, src) + 8 + if matchedNext > matched { + t = coffsetL + s += checkAt + matched = matchedNext + if debugMatches { + println("prev long match (after short)") + } + break + } + } + t = coffsetS + if debugAsserts && s <= t { + panic(fmt.Sprintf("s (%d) <= t (%d)", s, t)) + } + if debugAsserts && s-t > e.maxMatchOff { + panic("s - t >e.maxMatchOff") + } + if debugAsserts && t < 0 { + panic("t<0") + } + if debugMatches { + println("short match") + } + break + } + + // No match found, move forward in input. + s += stepSize + ((s - nextEmit) >> (kSearchStrength - 1)) + if s >= sLimit { + break encodeLoop + } + cv = load6432(src, s) + } + + // Try to find a better match by searching for a long match at the end of the current best match + if s+matched < sLimit { + // Allow some bytes at the beginning to mismatch. + // Sweet spot is around 3 bytes, but depends on input. + // The skipped bytes are tested in Extend backwards, + // and still picked up as part of the match if they do. + const skipBeginning = 3 + + nextHashL := hashLen(load6432(src, s+matched), betterLongTableBits, betterLongLen) + s2 := s + skipBeginning + cv := load3232(src, s2) + candidateL := e.longTable[nextHashL] + coffsetL := candidateL.offset - e.cur - matched + skipBeginning + if coffsetL >= 0 && coffsetL < s2 && s2-coffsetL < e.maxMatchOff && cv == load3232(src, coffsetL) { + // Found a long match, at least 4 bytes. + matchedNext := e.matchlen(s2+4, coffsetL+4, src) + 4 + if matchedNext > matched { + t = coffsetL + s = s2 + matched = matchedNext + if debugMatches { + println("long match at end-of-match") + } + } + } + + // Check prev long... + if true { + coffsetL = candidateL.prev - e.cur - matched + skipBeginning + if coffsetL >= 0 && coffsetL < s2 && s2-coffsetL < e.maxMatchOff && cv == load3232(src, coffsetL) { + // Found a long match, at least 4 bytes. + matchedNext := e.matchlen(s2+4, coffsetL+4, src) + 4 + if matchedNext > matched { + t = coffsetL + s = s2 + matched = matchedNext + if debugMatches { + println("prev long match at end-of-match") + } + } + } + } + } + // A match has been found. Update recent offsets. + offset2 = offset1 + offset1 = s - t + + if debugAsserts && s <= t { + panic(fmt.Sprintf("s (%d) <= t (%d)", s, t)) + } + + if debugAsserts && canRepeat && int(offset1) > len(src) { + panic("invalid offset") + } + + // Extend the n-byte match as long as possible. + l := matched + + // Extend backwards + tMin := s - e.maxMatchOff + if tMin < 0 { + tMin = 0 + } + for t > tMin && s > nextEmit && src[t-1] == src[s-1] && l < maxMatchLength { + s-- + t-- + l++ + } + + // Write our sequence + var seq seq + seq.litLen = uint32(s - nextEmit) + seq.matchLen = uint32(l - zstdMinMatch) + if seq.litLen > 0 { + blk.literals = append(blk.literals, src[nextEmit:s]...) + } + seq.offset = uint32(s-t) + 3 + s += l + if debugSequences { + println("sequence", seq, "next s:", s) + } + blk.sequences = append(blk.sequences, seq) + nextEmit = s + if s >= sLimit { + break encodeLoop + } + + // Index match start+1 (long) -> s - 1 + off := index0 + e.cur + for index0 < s-1 { + cv0 := load6432(src, index0) + cv1 := cv0 >> 8 + h0 := hashLen(cv0, betterLongTableBits, betterLongLen) + e.longTable[h0] = prevEntry{offset: off, prev: e.longTable[h0].offset} + e.table[hashLen(cv1, betterShortTableBits, betterShortLen)] = tableEntry{offset: off + 1, val: uint32(cv1)} + index0 += 2 + off += 2 + } + + cv = load6432(src, s) + if !canRepeat { + continue + } + + // Check offset 2 + for { + o2 := s - offset2 + if load3232(src, o2) != uint32(cv) { + // Do regular search + break + } + + // Store this, since we have it. + nextHashL := hashLen(cv, betterLongTableBits, betterLongLen) + nextHashS := hashLen(cv, betterShortTableBits, betterShortLen) + + // We have at least 4 byte match. + // No need to check backwards. We come straight from a match + l := 4 + e.matchlen(s+4, o2+4, src) + + e.longTable[nextHashL] = prevEntry{offset: s + e.cur, prev: e.longTable[nextHashL].offset} + e.table[nextHashS] = tableEntry{offset: s + e.cur, val: uint32(cv)} + seq.matchLen = uint32(l) - zstdMinMatch + seq.litLen = 0 + + // Since litlen is always 0, this is offset 1. + seq.offset = 1 + s += l + nextEmit = s + if debugSequences { + println("sequence", seq, "next s:", s) + } + blk.sequences = append(blk.sequences, seq) + + // Swap offset 1 and 2. + offset1, offset2 = offset2, offset1 + if s >= sLimit { + // Finished + break encodeLoop + } + cv = load6432(src, s) + } + } + + if int(nextEmit) < len(src) { + blk.literals = append(blk.literals, src[nextEmit:]...) + blk.extraLits = len(src) - int(nextEmit) + } + blk.recentOffsets[0] = uint32(offset1) + blk.recentOffsets[1] = uint32(offset2) + if debugEncoder { + println("returning, recent offsets:", blk.recentOffsets, "extra literals:", blk.extraLits) + } +} + +// EncodeNoHist will encode a block with no history and no following blocks. +// Most notable difference is that src will not be copied for history and +// we do not need to check for max match length. +func (e *betterFastEncoder) EncodeNoHist(blk *blockEnc, src []byte) { + e.ensureHist(len(src)) + e.Encode(blk, src) +} + +// Encode improves compression... +func (e *betterFastEncoderDict) Encode(blk *blockEnc, src []byte) { + const ( + // Input margin is the number of bytes we read (8) + // and the maximum we will read ahead (2) + inputMargin = 8 + 2 + minNonLiteralBlockSize = 16 + ) + + // Protect against e.cur wraparound. + for e.cur >= e.bufferReset-int32(len(e.hist)) { + if len(e.hist) == 0 { + for i := range e.table[:] { + e.table[i] = tableEntry{} + } + for i := range e.longTable[:] { + e.longTable[i] = prevEntry{} + } + e.cur = e.maxMatchOff + e.allDirty = true + break + } + // Shift down everything in the table that isn't already too far away. + minOff := e.cur + int32(len(e.hist)) - e.maxMatchOff + for i := range e.table[:] { + v := e.table[i].offset + if v < minOff { + v = 0 + } else { + v = v - e.cur + e.maxMatchOff + } + e.table[i].offset = v + } + for i := range e.longTable[:] { + v := e.longTable[i].offset + v2 := e.longTable[i].prev + if v < minOff { + v = 0 + v2 = 0 + } else { + v = v - e.cur + e.maxMatchOff + if v2 < minOff { + v2 = 0 + } else { + v2 = v2 - e.cur + e.maxMatchOff + } + } + e.longTable[i] = prevEntry{ + offset: v, + prev: v2, + } + } + e.allDirty = true + e.cur = e.maxMatchOff + break + } + + s := e.addBlock(src) + blk.size = len(src) + if len(src) < minNonLiteralBlockSize { + blk.extraLits = len(src) + blk.literals = blk.literals[:len(src)] + copy(blk.literals, src) + return + } + + // Override src + src = e.hist + sLimit := int32(len(src)) - inputMargin + // stepSize is the number of bytes to skip on every main loop iteration. + // It should be >= 1. + const stepSize = 1 + + const kSearchStrength = 9 + + // nextEmit is where in src the next emitLiteral should start from. + nextEmit := s + cv := load6432(src, s) + + // Relative offsets + offset1 := int32(blk.recentOffsets[0]) + offset2 := int32(blk.recentOffsets[1]) + + addLiterals := func(s *seq, until int32) { + if until == nextEmit { + return + } + blk.literals = append(blk.literals, src[nextEmit:until]...) + s.litLen = uint32(until - nextEmit) + } + if debugEncoder { + println("recent offsets:", blk.recentOffsets) + } + +encodeLoop: + for { + var t int32 + // We allow the encoder to optionally turn off repeat offsets across blocks + canRepeat := len(blk.sequences) > 2 + var matched, index0 int32 + + for { + if debugAsserts && canRepeat && offset1 == 0 { + panic("offset0 was 0") + } + + nextHashL := hashLen(cv, betterLongTableBits, betterLongLen) + nextHashS := hashLen(cv, betterShortTableBits, betterShortLen) + candidateL := e.longTable[nextHashL] + candidateS := e.table[nextHashS] + + const repOff = 1 + repIndex := s - offset1 + repOff + off := s + e.cur + e.longTable[nextHashL] = prevEntry{offset: off, prev: candidateL.offset} + e.markLongShardDirty(nextHashL) + e.table[nextHashS] = tableEntry{offset: off, val: uint32(cv)} + e.markShortShardDirty(nextHashS) + index0 = s + 1 + + if canRepeat { + if repIndex >= 0 && load3232(src, repIndex) == uint32(cv>>(repOff*8)) { + // Consider history as well. + var seq seq + lenght := 4 + e.matchlen(s+4+repOff, repIndex+4, src) + + seq.matchLen = uint32(lenght - zstdMinMatch) + + // We might be able to match backwards. + // Extend as long as we can. + start := s + repOff + // We end the search early, so we don't risk 0 literals + // and have to do special offset treatment. + startLimit := nextEmit + 1 + + tMin := s - e.maxMatchOff + if tMin < 0 { + tMin = 0 + } + for repIndex > tMin && start > startLimit && src[repIndex-1] == src[start-1] && seq.matchLen < maxMatchLength-zstdMinMatch-1 { + repIndex-- + start-- + seq.matchLen++ + } + addLiterals(&seq, start) + + // rep 0 + seq.offset = 1 + if debugSequences { + println("repeat sequence", seq, "next s:", s) + } + blk.sequences = append(blk.sequences, seq) + + // Index match start+1 (long) -> s - 1 + s += lenght + repOff + + nextEmit = s + if s >= sLimit { + if debugEncoder { + println("repeat ended", s, lenght) + + } + break encodeLoop + } + // Index skipped... + for index0 < s-1 { + cv0 := load6432(src, index0) + cv1 := cv0 >> 8 + h0 := hashLen(cv0, betterLongTableBits, betterLongLen) + off := index0 + e.cur + e.longTable[h0] = prevEntry{offset: off, prev: e.longTable[h0].offset} + e.markLongShardDirty(h0) + h1 := hashLen(cv1, betterShortTableBits, betterShortLen) + e.table[h1] = tableEntry{offset: off + 1, val: uint32(cv1)} + e.markShortShardDirty(h1) + index0 += 2 + } + cv = load6432(src, s) + continue + } + const repOff2 = 1 + + // We deviate from the reference encoder and also check offset 2. + // Still slower and not much better, so disabled. + // repIndex = s - offset2 + repOff2 + if false && repIndex >= 0 && load6432(src, repIndex) == load6432(src, s+repOff) { + // Consider history as well. + var seq seq + lenght := 8 + e.matchlen(s+8+repOff2, repIndex+8, src) + + seq.matchLen = uint32(lenght - zstdMinMatch) + + // We might be able to match backwards. + // Extend as long as we can. + start := s + repOff2 + // We end the search early, so we don't risk 0 literals + // and have to do special offset treatment. + startLimit := nextEmit + 1 + + tMin := s - e.maxMatchOff + if tMin < 0 { + tMin = 0 + } + for repIndex > tMin && start > startLimit && src[repIndex-1] == src[start-1] && seq.matchLen < maxMatchLength-zstdMinMatch-1 { + repIndex-- + start-- + seq.matchLen++ + } + addLiterals(&seq, start) + + // rep 2 + seq.offset = 2 + if debugSequences { + println("repeat sequence 2", seq, "next s:", s) + } + blk.sequences = append(blk.sequences, seq) + + s += lenght + repOff2 + nextEmit = s + if s >= sLimit { + if debugEncoder { + println("repeat ended", s, lenght) + + } + break encodeLoop + } + + // Index skipped... + for index0 < s-1 { + cv0 := load6432(src, index0) + cv1 := cv0 >> 8 + h0 := hashLen(cv0, betterLongTableBits, betterLongLen) + off := index0 + e.cur + e.longTable[h0] = prevEntry{offset: off, prev: e.longTable[h0].offset} + e.markLongShardDirty(h0) + h1 := hashLen(cv1, betterShortTableBits, betterShortLen) + e.table[h1] = tableEntry{offset: off + 1, val: uint32(cv1)} + e.markShortShardDirty(h1) + index0 += 2 + } + cv = load6432(src, s) + // Swap offsets + offset1, offset2 = offset2, offset1 + continue + } + } + // Find the offsets of our two matches. + coffsetL := candidateL.offset - e.cur + coffsetLP := candidateL.prev - e.cur + + // Check if we have a long match. + if s-coffsetL < e.maxMatchOff && cv == load6432(src, coffsetL) { + // Found a long match, at least 8 bytes. + matched = e.matchlen(s+8, coffsetL+8, src) + 8 + t = coffsetL + if debugAsserts && s <= t { + panic(fmt.Sprintf("s (%d) <= t (%d)", s, t)) + } + if debugAsserts && s-t > e.maxMatchOff { + panic("s - t >e.maxMatchOff") + } + if debugMatches { + println("long match") + } + + if s-coffsetLP < e.maxMatchOff && cv == load6432(src, coffsetLP) { + // Found a long match, at least 8 bytes. + prevMatch := e.matchlen(s+8, coffsetLP+8, src) + 8 + if prevMatch > matched { + matched = prevMatch + t = coffsetLP + } + if debugAsserts && s <= t { + panic(fmt.Sprintf("s (%d) <= t (%d)", s, t)) + } + if debugAsserts && s-t > e.maxMatchOff { + panic("s - t >e.maxMatchOff") + } + if debugMatches { + println("long match") + } + } + break + } + + // Check if we have a long match on prev. + if s-coffsetLP < e.maxMatchOff && cv == load6432(src, coffsetLP) { + // Found a long match, at least 8 bytes. + matched = e.matchlen(s+8, coffsetLP+8, src) + 8 + t = coffsetLP + if debugAsserts && s <= t { + panic(fmt.Sprintf("s (%d) <= t (%d)", s, t)) + } + if debugAsserts && s-t > e.maxMatchOff { + panic("s - t >e.maxMatchOff") + } + if debugMatches { + println("long match") + } + break + } + + coffsetS := candidateS.offset - e.cur + + // Check if we have a short match. + if s-coffsetS < e.maxMatchOff && uint32(cv) == candidateS.val { + // found a regular match + matched = e.matchlen(s+4, coffsetS+4, src) + 4 + + // See if we can find a long match at s+1 + const checkAt = 1 + cv := load6432(src, s+checkAt) + nextHashL = hashLen(cv, betterLongTableBits, betterLongLen) + candidateL = e.longTable[nextHashL] + coffsetL = candidateL.offset - e.cur + + // We can store it, since we have at least a 4 byte match. + e.longTable[nextHashL] = prevEntry{offset: s + checkAt + e.cur, prev: candidateL.offset} + e.markLongShardDirty(nextHashL) + if s-coffsetL < e.maxMatchOff && cv == load6432(src, coffsetL) { + // Found a long match, at least 8 bytes. + matchedNext := e.matchlen(s+8+checkAt, coffsetL+8, src) + 8 + if matchedNext > matched { + t = coffsetL + s += checkAt + matched = matchedNext + if debugMatches { + println("long match (after short)") + } + break + } + } + + // Check prev long... + coffsetL = candidateL.prev - e.cur + if s-coffsetL < e.maxMatchOff && cv == load6432(src, coffsetL) { + // Found a long match, at least 8 bytes. + matchedNext := e.matchlen(s+8+checkAt, coffsetL+8, src) + 8 + if matchedNext > matched { + t = coffsetL + s += checkAt + matched = matchedNext + if debugMatches { + println("prev long match (after short)") + } + break + } + } + t = coffsetS + if debugAsserts && s <= t { + panic(fmt.Sprintf("s (%d) <= t (%d)", s, t)) + } + if debugAsserts && s-t > e.maxMatchOff { + panic("s - t >e.maxMatchOff") + } + if debugAsserts && t < 0 { + panic("t<0") + } + if debugMatches { + println("short match") + } + break + } + + // No match found, move forward in input. + s += stepSize + ((s - nextEmit) >> (kSearchStrength - 1)) + if s >= sLimit { + break encodeLoop + } + cv = load6432(src, s) + } + // Try to find a better match by searching for a long match at the end of the current best match + if s+matched < sLimit { + nextHashL := hashLen(load6432(src, s+matched), betterLongTableBits, betterLongLen) + cv := load3232(src, s) + candidateL := e.longTable[nextHashL] + coffsetL := candidateL.offset - e.cur - matched + if coffsetL >= 0 && coffsetL < s && s-coffsetL < e.maxMatchOff && cv == load3232(src, coffsetL) { + // Found a long match, at least 4 bytes. + matchedNext := e.matchlen(s+4, coffsetL+4, src) + 4 + if matchedNext > matched { + t = coffsetL + matched = matchedNext + if debugMatches { + println("long match at end-of-match") + } + } + } + + // Check prev long... + if true { + coffsetL = candidateL.prev - e.cur - matched + if coffsetL >= 0 && coffsetL < s && s-coffsetL < e.maxMatchOff && cv == load3232(src, coffsetL) { + // Found a long match, at least 4 bytes. + matchedNext := e.matchlen(s+4, coffsetL+4, src) + 4 + if matchedNext > matched { + t = coffsetL + matched = matchedNext + if debugMatches { + println("prev long match at end-of-match") + } + } + } + } + } + // A match has been found. Update recent offsets. + offset2 = offset1 + offset1 = s - t + + if debugAsserts && s <= t { + panic(fmt.Sprintf("s (%d) <= t (%d)", s, t)) + } + + if debugAsserts && canRepeat && int(offset1) > len(src) { + panic("invalid offset") + } + + // Extend the n-byte match as long as possible. + l := matched + + // Extend backwards + tMin := s - e.maxMatchOff + if tMin < 0 { + tMin = 0 + } + for t > tMin && s > nextEmit && src[t-1] == src[s-1] && l < maxMatchLength { + s-- + t-- + l++ + } + + // Write our sequence + var seq seq + seq.litLen = uint32(s - nextEmit) + seq.matchLen = uint32(l - zstdMinMatch) + if seq.litLen > 0 { + blk.literals = append(blk.literals, src[nextEmit:s]...) + } + seq.offset = uint32(s-t) + 3 + s += l + if debugSequences { + println("sequence", seq, "next s:", s) + } + blk.sequences = append(blk.sequences, seq) + nextEmit = s + if s >= sLimit { + break encodeLoop + } + + // Index match start+1 (long) -> s - 1 + off := index0 + e.cur + for index0 < s-1 { + cv0 := load6432(src, index0) + cv1 := cv0 >> 8 + h0 := hashLen(cv0, betterLongTableBits, betterLongLen) + e.longTable[h0] = prevEntry{offset: off, prev: e.longTable[h0].offset} + e.markLongShardDirty(h0) + h1 := hashLen(cv1, betterShortTableBits, betterShortLen) + e.table[h1] = tableEntry{offset: off + 1, val: uint32(cv1)} + e.markShortShardDirty(h1) + index0 += 2 + off += 2 + } + + cv = load6432(src, s) + if !canRepeat { + continue + } + + // Check offset 2 + for { + o2 := s - offset2 + if load3232(src, o2) != uint32(cv) { + // Do regular search + break + } + + // Store this, since we have it. + nextHashL := hashLen(cv, betterLongTableBits, betterLongLen) + nextHashS := hashLen(cv, betterShortTableBits, betterShortLen) + + // We have at least 4 byte match. + // No need to check backwards. We come straight from a match + l := 4 + e.matchlen(s+4, o2+4, src) + + e.longTable[nextHashL] = prevEntry{offset: s + e.cur, prev: e.longTable[nextHashL].offset} + e.markLongShardDirty(nextHashL) + e.table[nextHashS] = tableEntry{offset: s + e.cur, val: uint32(cv)} + e.markShortShardDirty(nextHashS) + seq.matchLen = uint32(l) - zstdMinMatch + seq.litLen = 0 + + // Since litlen is always 0, this is offset 1. + seq.offset = 1 + s += l + nextEmit = s + if debugSequences { + println("sequence", seq, "next s:", s) + } + blk.sequences = append(blk.sequences, seq) + + // Swap offset 1 and 2. + offset1, offset2 = offset2, offset1 + if s >= sLimit { + // Finished + break encodeLoop + } + cv = load6432(src, s) + } + } + + if int(nextEmit) < len(src) { + blk.literals = append(blk.literals, src[nextEmit:]...) + blk.extraLits = len(src) - int(nextEmit) + } + blk.recentOffsets[0] = uint32(offset1) + blk.recentOffsets[1] = uint32(offset2) + if debugEncoder { + println("returning, recent offsets:", blk.recentOffsets, "extra literals:", blk.extraLits) + } +} + +// ResetDict will reset and set a dictionary if not nil +func (e *betterFastEncoder) Reset(d *dict, singleBlock bool) { + e.resetBase(d, singleBlock) + if d != nil { + panic("betterFastEncoder: Reset with dict") + } +} + +// ResetDict will reset and set a dictionary if not nil +func (e *betterFastEncoderDict) Reset(d *dict, singleBlock bool) { + e.resetBase(d, singleBlock) + if d == nil { + return + } + // Init or copy dict table + if len(e.dictTable) != len(e.table) || d.id != e.lastDictID { + if len(e.dictTable) != len(e.table) { + e.dictTable = make([]tableEntry, len(e.table)) + } + end := int32(len(d.content)) - 8 + e.maxMatchOff + for i := e.maxMatchOff; i < end; i += 4 { + const hashLog = betterShortTableBits + + cv := load6432(d.content, i-e.maxMatchOff) + nextHash := hashLen(cv, hashLog, betterShortLen) // 0 -> 4 + nextHash1 := hashLen(cv>>8, hashLog, betterShortLen) // 1 -> 5 + nextHash2 := hashLen(cv>>16, hashLog, betterShortLen) // 2 -> 6 + nextHash3 := hashLen(cv>>24, hashLog, betterShortLen) // 3 -> 7 + e.dictTable[nextHash] = tableEntry{ + val: uint32(cv), + offset: i, + } + e.dictTable[nextHash1] = tableEntry{ + val: uint32(cv >> 8), + offset: i + 1, + } + e.dictTable[nextHash2] = tableEntry{ + val: uint32(cv >> 16), + offset: i + 2, + } + e.dictTable[nextHash3] = tableEntry{ + val: uint32(cv >> 24), + offset: i + 3, + } + } + e.lastDictID = d.id + e.allDirty = true + } + + // Init or copy dict table + if len(e.dictLongTable) != len(e.longTable) || d.id != e.lastDictID { + if len(e.dictLongTable) != len(e.longTable) { + e.dictLongTable = make([]prevEntry, len(e.longTable)) + } + if len(d.content) >= 8 { + cv := load6432(d.content, 0) + h := hashLen(cv, betterLongTableBits, betterLongLen) + e.dictLongTable[h] = prevEntry{ + offset: e.maxMatchOff, + prev: e.dictLongTable[h].offset, + } + + end := int32(len(d.content)) - 8 + e.maxMatchOff + off := 8 // First to read + for i := e.maxMatchOff + 1; i < end; i++ { + cv = cv>>8 | (uint64(d.content[off]) << 56) + h := hashLen(cv, betterLongTableBits, betterLongLen) + e.dictLongTable[h] = prevEntry{ + offset: i, + prev: e.dictLongTable[h].offset, + } + off++ + } + } + e.lastDictID = d.id + e.allDirty = true + } + + // Reset table to initial state + { + dirtyShardCnt := 0 + if !e.allDirty { + for i := range e.shortTableShardDirty { + if e.shortTableShardDirty[i] { + dirtyShardCnt++ + } + } + } + const shardCnt = betterShortTableShardCnt + const shardSize = betterShortTableShardSize + if e.allDirty || dirtyShardCnt > shardCnt*4/6 { + copy(e.table[:], e.dictTable) + for i := range e.shortTableShardDirty { + e.shortTableShardDirty[i] = false + } + } else { + for i := range e.shortTableShardDirty { + if !e.shortTableShardDirty[i] { + continue + } + + copy(e.table[i*shardSize:(i+1)*shardSize], e.dictTable[i*shardSize:(i+1)*shardSize]) + e.shortTableShardDirty[i] = false + } + } + } + { + dirtyShardCnt := 0 + if !e.allDirty { + for i := range e.shortTableShardDirty { + if e.shortTableShardDirty[i] { + dirtyShardCnt++ + } + } + } + const shardCnt = betterLongTableShardCnt + const shardSize = betterLongTableShardSize + if e.allDirty || dirtyShardCnt > shardCnt*4/6 { + copy(e.longTable[:], e.dictLongTable) + for i := range e.longTableShardDirty { + e.longTableShardDirty[i] = false + } + } else { + for i := range e.longTableShardDirty { + if !e.longTableShardDirty[i] { + continue + } + + copy(e.longTable[i*shardSize:(i+1)*shardSize], e.dictLongTable[i*shardSize:(i+1)*shardSize]) + e.longTableShardDirty[i] = false + } + } + } + e.cur = e.maxMatchOff + e.allDirty = false +} + +func (e *betterFastEncoderDict) markLongShardDirty(entryNum uint32) { + e.longTableShardDirty[entryNum/betterLongTableShardSize] = true +} + +func (e *betterFastEncoderDict) markShortShardDirty(entryNum uint32) { + e.shortTableShardDirty[entryNum/betterShortTableShardSize] = true +} diff --git a/vendor/github.com/klauspost/compress/zstd/enc_dfast.go b/vendor/github.com/klauspost/compress/zstd/enc_dfast.go new file mode 100644 index 000000000..a154c18f7 --- /dev/null +++ b/vendor/github.com/klauspost/compress/zstd/enc_dfast.go @@ -0,0 +1,1123 @@ +// Copyright 2019+ Klaus Post. All rights reserved. +// License information can be found in the LICENSE file. +// Based on work by Yann Collet, released under BSD License. + +package zstd + +import "fmt" + +const ( + dFastLongTableBits = 17 // Bits used in the long match table + dFastLongTableSize = 1 << dFastLongTableBits // Size of the table + dFastLongTableMask = dFastLongTableSize - 1 // Mask for table indices. Redundant, but can eliminate bounds checks. + dFastLongLen = 8 // Bytes used for table hash + + dLongTableShardCnt = 1 << (dFastLongTableBits - dictShardBits) // Number of shards in the table + dLongTableShardSize = dFastLongTableSize / tableShardCnt // Size of an individual shard + + dFastShortTableBits = tableBits // Bits used in the short match table + dFastShortTableSize = 1 << dFastShortTableBits // Size of the table + dFastShortTableMask = dFastShortTableSize - 1 // Mask for table indices. Redundant, but can eliminate bounds checks. + dFastShortLen = 5 // Bytes used for table hash + +) + +type doubleFastEncoder struct { + fastEncoder + longTable [dFastLongTableSize]tableEntry +} + +type doubleFastEncoderDict struct { + fastEncoderDict + longTable [dFastLongTableSize]tableEntry + dictLongTable []tableEntry + longTableShardDirty [dLongTableShardCnt]bool +} + +// Encode mimmics functionality in zstd_dfast.c +func (e *doubleFastEncoder) Encode(blk *blockEnc, src []byte) { + const ( + // Input margin is the number of bytes we read (8) + // and the maximum we will read ahead (2) + inputMargin = 8 + 2 + minNonLiteralBlockSize = 16 + ) + + // Protect against e.cur wraparound. + for e.cur >= e.bufferReset-int32(len(e.hist)) { + if len(e.hist) == 0 { + e.table = [dFastShortTableSize]tableEntry{} + e.longTable = [dFastLongTableSize]tableEntry{} + e.cur = e.maxMatchOff + break + } + // Shift down everything in the table that isn't already too far away. + minOff := e.cur + int32(len(e.hist)) - e.maxMatchOff + for i := range e.table[:] { + v := e.table[i].offset + if v < minOff { + v = 0 + } else { + v = v - e.cur + e.maxMatchOff + } + e.table[i].offset = v + } + for i := range e.longTable[:] { + v := e.longTable[i].offset + if v < minOff { + v = 0 + } else { + v = v - e.cur + e.maxMatchOff + } + e.longTable[i].offset = v + } + e.cur = e.maxMatchOff + break + } + + s := e.addBlock(src) + blk.size = len(src) + if len(src) < minNonLiteralBlockSize { + blk.extraLits = len(src) + blk.literals = blk.literals[:len(src)] + copy(blk.literals, src) + return + } + + // Override src + src = e.hist + sLimit := int32(len(src)) - inputMargin + // stepSize is the number of bytes to skip on every main loop iteration. + // It should be >= 1. + const stepSize = 1 + + const kSearchStrength = 8 + + // nextEmit is where in src the next emitLiteral should start from. + nextEmit := s + cv := load6432(src, s) + + // Relative offsets + offset1 := int32(blk.recentOffsets[0]) + offset2 := int32(blk.recentOffsets[1]) + + addLiterals := func(s *seq, until int32) { + if until == nextEmit { + return + } + blk.literals = append(blk.literals, src[nextEmit:until]...) + s.litLen = uint32(until - nextEmit) + } + if debugEncoder { + println("recent offsets:", blk.recentOffsets) + } + +encodeLoop: + for { + var t int32 + // We allow the encoder to optionally turn off repeat offsets across blocks + canRepeat := len(blk.sequences) > 2 + + for { + if debugAsserts && canRepeat && offset1 == 0 { + panic("offset0 was 0") + } + + nextHashL := hashLen(cv, dFastLongTableBits, dFastLongLen) + nextHashS := hashLen(cv, dFastShortTableBits, dFastShortLen) + candidateL := e.longTable[nextHashL] + candidateS := e.table[nextHashS] + + const repOff = 1 + repIndex := s - offset1 + repOff + entry := tableEntry{offset: s + e.cur, val: uint32(cv)} + e.longTable[nextHashL] = entry + e.table[nextHashS] = entry + + if canRepeat { + if repIndex >= 0 && load3232(src, repIndex) == uint32(cv>>(repOff*8)) { + // Consider history as well. + var seq seq + lenght := 4 + e.matchlen(s+4+repOff, repIndex+4, src) + + seq.matchLen = uint32(lenght - zstdMinMatch) + + // We might be able to match backwards. + // Extend as long as we can. + start := s + repOff + // We end the search early, so we don't risk 0 literals + // and have to do special offset treatment. + startLimit := nextEmit + 1 + + tMin := s - e.maxMatchOff + if tMin < 0 { + tMin = 0 + } + for repIndex > tMin && start > startLimit && src[repIndex-1] == src[start-1] && seq.matchLen < maxMatchLength-zstdMinMatch-1 { + repIndex-- + start-- + seq.matchLen++ + } + addLiterals(&seq, start) + + // rep 0 + seq.offset = 1 + if debugSequences { + println("repeat sequence", seq, "next s:", s) + } + blk.sequences = append(blk.sequences, seq) + s += lenght + repOff + nextEmit = s + if s >= sLimit { + if debugEncoder { + println("repeat ended", s, lenght) + + } + break encodeLoop + } + cv = load6432(src, s) + continue + } + } + // Find the offsets of our two matches. + coffsetL := s - (candidateL.offset - e.cur) + coffsetS := s - (candidateS.offset - e.cur) + + // Check if we have a long match. + if coffsetL < e.maxMatchOff && uint32(cv) == candidateL.val { + // Found a long match, likely at least 8 bytes. + // Reference encoder checks all 8 bytes, we only check 4, + // but the likelihood of both the first 4 bytes and the hash matching should be enough. + t = candidateL.offset - e.cur + if debugAsserts && s <= t { + panic(fmt.Sprintf("s (%d) <= t (%d)", s, t)) + } + if debugAsserts && s-t > e.maxMatchOff { + panic("s - t >e.maxMatchOff") + } + if debugMatches { + println("long match") + } + break + } + + // Check if we have a short match. + if coffsetS < e.maxMatchOff && uint32(cv) == candidateS.val { + // found a regular match + // See if we can find a long match at s+1 + const checkAt = 1 + cv := load6432(src, s+checkAt) + nextHashL = hashLen(cv, dFastLongTableBits, dFastLongLen) + candidateL = e.longTable[nextHashL] + coffsetL = s - (candidateL.offset - e.cur) + checkAt + + // We can store it, since we have at least a 4 byte match. + e.longTable[nextHashL] = tableEntry{offset: s + checkAt + e.cur, val: uint32(cv)} + if coffsetL < e.maxMatchOff && uint32(cv) == candidateL.val { + // Found a long match, likely at least 8 bytes. + // Reference encoder checks all 8 bytes, we only check 4, + // but the likelihood of both the first 4 bytes and the hash matching should be enough. + t = candidateL.offset - e.cur + s += checkAt + if debugMatches { + println("long match (after short)") + } + break + } + + t = candidateS.offset - e.cur + if debugAsserts && s <= t { + panic(fmt.Sprintf("s (%d) <= t (%d)", s, t)) + } + if debugAsserts && s-t > e.maxMatchOff { + panic("s - t >e.maxMatchOff") + } + if debugAsserts && t < 0 { + panic("t<0") + } + if debugMatches { + println("short match") + } + break + } + + // No match found, move forward in input. + s += stepSize + ((s - nextEmit) >> (kSearchStrength - 1)) + if s >= sLimit { + break encodeLoop + } + cv = load6432(src, s) + } + + // A 4-byte match has been found. Update recent offsets. + // We'll later see if more than 4 bytes. + offset2 = offset1 + offset1 = s - t + + if debugAsserts && s <= t { + panic(fmt.Sprintf("s (%d) <= t (%d)", s, t)) + } + + if debugAsserts && canRepeat && int(offset1) > len(src) { + panic("invalid offset") + } + + // Extend the 4-byte match as long as possible. + l := e.matchlen(s+4, t+4, src) + 4 + + // Extend backwards + tMin := s - e.maxMatchOff + if tMin < 0 { + tMin = 0 + } + for t > tMin && s > nextEmit && src[t-1] == src[s-1] && l < maxMatchLength { + s-- + t-- + l++ + } + + // Write our sequence + var seq seq + seq.litLen = uint32(s - nextEmit) + seq.matchLen = uint32(l - zstdMinMatch) + if seq.litLen > 0 { + blk.literals = append(blk.literals, src[nextEmit:s]...) + } + seq.offset = uint32(s-t) + 3 + s += l + if debugSequences { + println("sequence", seq, "next s:", s) + } + blk.sequences = append(blk.sequences, seq) + nextEmit = s + if s >= sLimit { + break encodeLoop + } + + // Index match start+1 (long) and start+2 (short) + index0 := s - l + 1 + // Index match end-2 (long) and end-1 (short) + index1 := s - 2 + + cv0 := load6432(src, index0) + cv1 := load6432(src, index1) + te0 := tableEntry{offset: index0 + e.cur, val: uint32(cv0)} + te1 := tableEntry{offset: index1 + e.cur, val: uint32(cv1)} + e.longTable[hashLen(cv0, dFastLongTableBits, dFastLongLen)] = te0 + e.longTable[hashLen(cv1, dFastLongTableBits, dFastLongLen)] = te1 + cv0 >>= 8 + cv1 >>= 8 + te0.offset++ + te1.offset++ + te0.val = uint32(cv0) + te1.val = uint32(cv1) + e.table[hashLen(cv0, dFastShortTableBits, dFastShortLen)] = te0 + e.table[hashLen(cv1, dFastShortTableBits, dFastShortLen)] = te1 + + cv = load6432(src, s) + + if !canRepeat { + continue + } + + // Check offset 2 + for { + o2 := s - offset2 + if load3232(src, o2) != uint32(cv) { + // Do regular search + break + } + + // Store this, since we have it. + nextHashS := hashLen(cv, dFastShortTableBits, dFastShortLen) + nextHashL := hashLen(cv, dFastLongTableBits, dFastLongLen) + + // We have at least 4 byte match. + // No need to check backwards. We come straight from a match + l := 4 + e.matchlen(s+4, o2+4, src) + + entry := tableEntry{offset: s + e.cur, val: uint32(cv)} + e.longTable[nextHashL] = entry + e.table[nextHashS] = entry + seq.matchLen = uint32(l) - zstdMinMatch + seq.litLen = 0 + + // Since litlen is always 0, this is offset 1. + seq.offset = 1 + s += l + nextEmit = s + if debugSequences { + println("sequence", seq, "next s:", s) + } + blk.sequences = append(blk.sequences, seq) + + // Swap offset 1 and 2. + offset1, offset2 = offset2, offset1 + if s >= sLimit { + // Finished + break encodeLoop + } + cv = load6432(src, s) + } + } + + if int(nextEmit) < len(src) { + blk.literals = append(blk.literals, src[nextEmit:]...) + blk.extraLits = len(src) - int(nextEmit) + } + blk.recentOffsets[0] = uint32(offset1) + blk.recentOffsets[1] = uint32(offset2) + if debugEncoder { + println("returning, recent offsets:", blk.recentOffsets, "extra literals:", blk.extraLits) + } +} + +// EncodeNoHist will encode a block with no history and no following blocks. +// Most notable difference is that src will not be copied for history and +// we do not need to check for max match length. +func (e *doubleFastEncoder) EncodeNoHist(blk *blockEnc, src []byte) { + const ( + // Input margin is the number of bytes we read (8) + // and the maximum we will read ahead (2) + inputMargin = 8 + 2 + minNonLiteralBlockSize = 16 + ) + + // Protect against e.cur wraparound. + if e.cur >= e.bufferReset { + for i := range e.table[:] { + e.table[i] = tableEntry{} + } + for i := range e.longTable[:] { + e.longTable[i] = tableEntry{} + } + e.cur = e.maxMatchOff + } + + s := int32(0) + blk.size = len(src) + if len(src) < minNonLiteralBlockSize { + blk.extraLits = len(src) + blk.literals = blk.literals[:len(src)] + copy(blk.literals, src) + return + } + + // Override src + sLimit := int32(len(src)) - inputMargin + // stepSize is the number of bytes to skip on every main loop iteration. + // It should be >= 1. + const stepSize = 1 + + const kSearchStrength = 8 + + // nextEmit is where in src the next emitLiteral should start from. + nextEmit := s + cv := load6432(src, s) + + // Relative offsets + offset1 := int32(blk.recentOffsets[0]) + offset2 := int32(blk.recentOffsets[1]) + + addLiterals := func(s *seq, until int32) { + if until == nextEmit { + return + } + blk.literals = append(blk.literals, src[nextEmit:until]...) + s.litLen = uint32(until - nextEmit) + } + if debugEncoder { + println("recent offsets:", blk.recentOffsets) + } + +encodeLoop: + for { + var t int32 + for { + + nextHashL := hashLen(cv, dFastLongTableBits, dFastLongLen) + nextHashS := hashLen(cv, dFastShortTableBits, dFastShortLen) + candidateL := e.longTable[nextHashL] + candidateS := e.table[nextHashS] + + const repOff = 1 + repIndex := s - offset1 + repOff + entry := tableEntry{offset: s + e.cur, val: uint32(cv)} + e.longTable[nextHashL] = entry + e.table[nextHashS] = entry + + if len(blk.sequences) > 2 { + if load3232(src, repIndex) == uint32(cv>>(repOff*8)) { + // Consider history as well. + var seq seq + //length := 4 + e.matchlen(s+4+repOff, repIndex+4, src) + length := 4 + int32(matchLen(src[s+4+repOff:], src[repIndex+4:])) + + seq.matchLen = uint32(length - zstdMinMatch) + + // We might be able to match backwards. + // Extend as long as we can. + start := s + repOff + // We end the search early, so we don't risk 0 literals + // and have to do special offset treatment. + startLimit := nextEmit + 1 + + tMin := s - e.maxMatchOff + if tMin < 0 { + tMin = 0 + } + for repIndex > tMin && start > startLimit && src[repIndex-1] == src[start-1] { + repIndex-- + start-- + seq.matchLen++ + } + addLiterals(&seq, start) + + // rep 0 + seq.offset = 1 + if debugSequences { + println("repeat sequence", seq, "next s:", s) + } + blk.sequences = append(blk.sequences, seq) + s += length + repOff + nextEmit = s + if s >= sLimit { + if debugEncoder { + println("repeat ended", s, length) + + } + break encodeLoop + } + cv = load6432(src, s) + continue + } + } + // Find the offsets of our two matches. + coffsetL := s - (candidateL.offset - e.cur) + coffsetS := s - (candidateS.offset - e.cur) + + // Check if we have a long match. + if coffsetL < e.maxMatchOff && uint32(cv) == candidateL.val { + // Found a long match, likely at least 8 bytes. + // Reference encoder checks all 8 bytes, we only check 4, + // but the likelihood of both the first 4 bytes and the hash matching should be enough. + t = candidateL.offset - e.cur + if debugAsserts && s <= t { + panic(fmt.Sprintf("s (%d) <= t (%d). cur: %d", s, t, e.cur)) + } + if debugAsserts && s-t > e.maxMatchOff { + panic("s - t >e.maxMatchOff") + } + if debugMatches { + println("long match") + } + break + } + + // Check if we have a short match. + if coffsetS < e.maxMatchOff && uint32(cv) == candidateS.val { + // found a regular match + // See if we can find a long match at s+1 + const checkAt = 1 + cv := load6432(src, s+checkAt) + nextHashL = hashLen(cv, dFastLongTableBits, dFastLongLen) + candidateL = e.longTable[nextHashL] + coffsetL = s - (candidateL.offset - e.cur) + checkAt + + // We can store it, since we have at least a 4 byte match. + e.longTable[nextHashL] = tableEntry{offset: s + checkAt + e.cur, val: uint32(cv)} + if coffsetL < e.maxMatchOff && uint32(cv) == candidateL.val { + // Found a long match, likely at least 8 bytes. + // Reference encoder checks all 8 bytes, we only check 4, + // but the likelihood of both the first 4 bytes and the hash matching should be enough. + t = candidateL.offset - e.cur + s += checkAt + if debugMatches { + println("long match (after short)") + } + break + } + + t = candidateS.offset - e.cur + if debugAsserts && s <= t { + panic(fmt.Sprintf("s (%d) <= t (%d)", s, t)) + } + if debugAsserts && s-t > e.maxMatchOff { + panic("s - t >e.maxMatchOff") + } + if debugAsserts && t < 0 { + panic("t<0") + } + if debugMatches { + println("short match") + } + break + } + + // No match found, move forward in input. + s += stepSize + ((s - nextEmit) >> (kSearchStrength - 1)) + if s >= sLimit { + break encodeLoop + } + cv = load6432(src, s) + } + + // A 4-byte match has been found. Update recent offsets. + // We'll later see if more than 4 bytes. + offset2 = offset1 + offset1 = s - t + + if debugAsserts && s <= t { + panic(fmt.Sprintf("s (%d) <= t (%d)", s, t)) + } + + // Extend the 4-byte match as long as possible. + //l := e.matchlen(s+4, t+4, src) + 4 + l := int32(matchLen(src[s+4:], src[t+4:])) + 4 + + // Extend backwards + tMin := s - e.maxMatchOff + if tMin < 0 { + tMin = 0 + } + for t > tMin && s > nextEmit && src[t-1] == src[s-1] { + s-- + t-- + l++ + } + + // Write our sequence + var seq seq + seq.litLen = uint32(s - nextEmit) + seq.matchLen = uint32(l - zstdMinMatch) + if seq.litLen > 0 { + blk.literals = append(blk.literals, src[nextEmit:s]...) + } + seq.offset = uint32(s-t) + 3 + s += l + if debugSequences { + println("sequence", seq, "next s:", s) + } + blk.sequences = append(blk.sequences, seq) + nextEmit = s + if s >= sLimit { + break encodeLoop + } + + // Index match start+1 (long) and start+2 (short) + index0 := s - l + 1 + // Index match end-2 (long) and end-1 (short) + index1 := s - 2 + + cv0 := load6432(src, index0) + cv1 := load6432(src, index1) + te0 := tableEntry{offset: index0 + e.cur, val: uint32(cv0)} + te1 := tableEntry{offset: index1 + e.cur, val: uint32(cv1)} + e.longTable[hashLen(cv0, dFastLongTableBits, dFastLongLen)] = te0 + e.longTable[hashLen(cv1, dFastLongTableBits, dFastLongLen)] = te1 + cv0 >>= 8 + cv1 >>= 8 + te0.offset++ + te1.offset++ + te0.val = uint32(cv0) + te1.val = uint32(cv1) + e.table[hashLen(cv0, dFastShortTableBits, dFastShortLen)] = te0 + e.table[hashLen(cv1, dFastShortTableBits, dFastShortLen)] = te1 + + cv = load6432(src, s) + + if len(blk.sequences) <= 2 { + continue + } + + // Check offset 2 + for { + o2 := s - offset2 + if load3232(src, o2) != uint32(cv) { + // Do regular search + break + } + + // Store this, since we have it. + nextHashS := hashLen(cv1>>8, dFastShortTableBits, dFastShortLen) + nextHashL := hashLen(cv, dFastLongTableBits, dFastLongLen) + + // We have at least 4 byte match. + // No need to check backwards. We come straight from a match + //l := 4 + e.matchlen(s+4, o2+4, src) + l := 4 + int32(matchLen(src[s+4:], src[o2+4:])) + + entry := tableEntry{offset: s + e.cur, val: uint32(cv)} + e.longTable[nextHashL] = entry + e.table[nextHashS] = entry + seq.matchLen = uint32(l) - zstdMinMatch + seq.litLen = 0 + + // Since litlen is always 0, this is offset 1. + seq.offset = 1 + s += l + nextEmit = s + if debugSequences { + println("sequence", seq, "next s:", s) + } + blk.sequences = append(blk.sequences, seq) + + // Swap offset 1 and 2. + offset1, offset2 = offset2, offset1 + if s >= sLimit { + // Finished + break encodeLoop + } + cv = load6432(src, s) + } + } + + if int(nextEmit) < len(src) { + blk.literals = append(blk.literals, src[nextEmit:]...) + blk.extraLits = len(src) - int(nextEmit) + } + if debugEncoder { + println("returning, recent offsets:", blk.recentOffsets, "extra literals:", blk.extraLits) + } + + // We do not store history, so we must offset e.cur to avoid false matches for next user. + if e.cur < e.bufferReset { + e.cur += int32(len(src)) + } +} + +// Encode will encode the content, with a dictionary if initialized for it. +func (e *doubleFastEncoderDict) Encode(blk *blockEnc, src []byte) { + const ( + // Input margin is the number of bytes we read (8) + // and the maximum we will read ahead (2) + inputMargin = 8 + 2 + minNonLiteralBlockSize = 16 + ) + + // Protect against e.cur wraparound. + for e.cur >= e.bufferReset-int32(len(e.hist)) { + if len(e.hist) == 0 { + for i := range e.table[:] { + e.table[i] = tableEntry{} + } + for i := range e.longTable[:] { + e.longTable[i] = tableEntry{} + } + e.markAllShardsDirty() + e.cur = e.maxMatchOff + break + } + // Shift down everything in the table that isn't already too far away. + minOff := e.cur + int32(len(e.hist)) - e.maxMatchOff + for i := range e.table[:] { + v := e.table[i].offset + if v < minOff { + v = 0 + } else { + v = v - e.cur + e.maxMatchOff + } + e.table[i].offset = v + } + for i := range e.longTable[:] { + v := e.longTable[i].offset + if v < minOff { + v = 0 + } else { + v = v - e.cur + e.maxMatchOff + } + e.longTable[i].offset = v + } + e.markAllShardsDirty() + e.cur = e.maxMatchOff + break + } + + s := e.addBlock(src) + blk.size = len(src) + if len(src) < minNonLiteralBlockSize { + blk.extraLits = len(src) + blk.literals = blk.literals[:len(src)] + copy(blk.literals, src) + return + } + + // Override src + src = e.hist + sLimit := int32(len(src)) - inputMargin + // stepSize is the number of bytes to skip on every main loop iteration. + // It should be >= 1. + const stepSize = 1 + + const kSearchStrength = 8 + + // nextEmit is where in src the next emitLiteral should start from. + nextEmit := s + cv := load6432(src, s) + + // Relative offsets + offset1 := int32(blk.recentOffsets[0]) + offset2 := int32(blk.recentOffsets[1]) + + addLiterals := func(s *seq, until int32) { + if until == nextEmit { + return + } + blk.literals = append(blk.literals, src[nextEmit:until]...) + s.litLen = uint32(until - nextEmit) + } + if debugEncoder { + println("recent offsets:", blk.recentOffsets) + } + +encodeLoop: + for { + var t int32 + // We allow the encoder to optionally turn off repeat offsets across blocks + canRepeat := len(blk.sequences) > 2 + + for { + if debugAsserts && canRepeat && offset1 == 0 { + panic("offset0 was 0") + } + + nextHashL := hashLen(cv, dFastLongTableBits, dFastLongLen) + nextHashS := hashLen(cv, dFastShortTableBits, dFastShortLen) + candidateL := e.longTable[nextHashL] + candidateS := e.table[nextHashS] + + const repOff = 1 + repIndex := s - offset1 + repOff + entry := tableEntry{offset: s + e.cur, val: uint32(cv)} + e.longTable[nextHashL] = entry + e.markLongShardDirty(nextHashL) + e.table[nextHashS] = entry + e.markShardDirty(nextHashS) + + if canRepeat { + if repIndex >= 0 && load3232(src, repIndex) == uint32(cv>>(repOff*8)) { + // Consider history as well. + var seq seq + lenght := 4 + e.matchlen(s+4+repOff, repIndex+4, src) + + seq.matchLen = uint32(lenght - zstdMinMatch) + + // We might be able to match backwards. + // Extend as long as we can. + start := s + repOff + // We end the search early, so we don't risk 0 literals + // and have to do special offset treatment. + startLimit := nextEmit + 1 + + tMin := s - e.maxMatchOff + if tMin < 0 { + tMin = 0 + } + for repIndex > tMin && start > startLimit && src[repIndex-1] == src[start-1] && seq.matchLen < maxMatchLength-zstdMinMatch-1 { + repIndex-- + start-- + seq.matchLen++ + } + addLiterals(&seq, start) + + // rep 0 + seq.offset = 1 + if debugSequences { + println("repeat sequence", seq, "next s:", s) + } + blk.sequences = append(blk.sequences, seq) + s += lenght + repOff + nextEmit = s + if s >= sLimit { + if debugEncoder { + println("repeat ended", s, lenght) + + } + break encodeLoop + } + cv = load6432(src, s) + continue + } + } + // Find the offsets of our two matches. + coffsetL := s - (candidateL.offset - e.cur) + coffsetS := s - (candidateS.offset - e.cur) + + // Check if we have a long match. + if coffsetL < e.maxMatchOff && uint32(cv) == candidateL.val { + // Found a long match, likely at least 8 bytes. + // Reference encoder checks all 8 bytes, we only check 4, + // but the likelihood of both the first 4 bytes and the hash matching should be enough. + t = candidateL.offset - e.cur + if debugAsserts && s <= t { + panic(fmt.Sprintf("s (%d) <= t (%d)", s, t)) + } + if debugAsserts && s-t > e.maxMatchOff { + panic("s - t >e.maxMatchOff") + } + if debugMatches { + println("long match") + } + break + } + + // Check if we have a short match. + if coffsetS < e.maxMatchOff && uint32(cv) == candidateS.val { + // found a regular match + // See if we can find a long match at s+1 + const checkAt = 1 + cv := load6432(src, s+checkAt) + nextHashL = hashLen(cv, dFastLongTableBits, dFastLongLen) + candidateL = e.longTable[nextHashL] + coffsetL = s - (candidateL.offset - e.cur) + checkAt + + // We can store it, since we have at least a 4 byte match. + e.longTable[nextHashL] = tableEntry{offset: s + checkAt + e.cur, val: uint32(cv)} + e.markLongShardDirty(nextHashL) + if coffsetL < e.maxMatchOff && uint32(cv) == candidateL.val { + // Found a long match, likely at least 8 bytes. + // Reference encoder checks all 8 bytes, we only check 4, + // but the likelihood of both the first 4 bytes and the hash matching should be enough. + t = candidateL.offset - e.cur + s += checkAt + if debugMatches { + println("long match (after short)") + } + break + } + + t = candidateS.offset - e.cur + if debugAsserts && s <= t { + panic(fmt.Sprintf("s (%d) <= t (%d)", s, t)) + } + if debugAsserts && s-t > e.maxMatchOff { + panic("s - t >e.maxMatchOff") + } + if debugAsserts && t < 0 { + panic("t<0") + } + if debugMatches { + println("short match") + } + break + } + + // No match found, move forward in input. + s += stepSize + ((s - nextEmit) >> (kSearchStrength - 1)) + if s >= sLimit { + break encodeLoop + } + cv = load6432(src, s) + } + + // A 4-byte match has been found. Update recent offsets. + // We'll later see if more than 4 bytes. + offset2 = offset1 + offset1 = s - t + + if debugAsserts && s <= t { + panic(fmt.Sprintf("s (%d) <= t (%d)", s, t)) + } + + if debugAsserts && canRepeat && int(offset1) > len(src) { + panic("invalid offset") + } + + // Extend the 4-byte match as long as possible. + l := e.matchlen(s+4, t+4, src) + 4 + + // Extend backwards + tMin := s - e.maxMatchOff + if tMin < 0 { + tMin = 0 + } + for t > tMin && s > nextEmit && src[t-1] == src[s-1] && l < maxMatchLength { + s-- + t-- + l++ + } + + // Write our sequence + var seq seq + seq.litLen = uint32(s - nextEmit) + seq.matchLen = uint32(l - zstdMinMatch) + if seq.litLen > 0 { + blk.literals = append(blk.literals, src[nextEmit:s]...) + } + seq.offset = uint32(s-t) + 3 + s += l + if debugSequences { + println("sequence", seq, "next s:", s) + } + blk.sequences = append(blk.sequences, seq) + nextEmit = s + if s >= sLimit { + break encodeLoop + } + + // Index match start+1 (long) and start+2 (short) + index0 := s - l + 1 + // Index match end-2 (long) and end-1 (short) + index1 := s - 2 + + cv0 := load6432(src, index0) + cv1 := load6432(src, index1) + te0 := tableEntry{offset: index0 + e.cur, val: uint32(cv0)} + te1 := tableEntry{offset: index1 + e.cur, val: uint32(cv1)} + longHash1 := hashLen(cv0, dFastLongTableBits, dFastLongLen) + longHash2 := hashLen(cv1, dFastLongTableBits, dFastLongLen) + e.longTable[longHash1] = te0 + e.longTable[longHash2] = te1 + e.markLongShardDirty(longHash1) + e.markLongShardDirty(longHash2) + cv0 >>= 8 + cv1 >>= 8 + te0.offset++ + te1.offset++ + te0.val = uint32(cv0) + te1.val = uint32(cv1) + hashVal1 := hashLen(cv0, dFastShortTableBits, dFastShortLen) + hashVal2 := hashLen(cv1, dFastShortTableBits, dFastShortLen) + e.table[hashVal1] = te0 + e.markShardDirty(hashVal1) + e.table[hashVal2] = te1 + e.markShardDirty(hashVal2) + + cv = load6432(src, s) + + if !canRepeat { + continue + } + + // Check offset 2 + for { + o2 := s - offset2 + if load3232(src, o2) != uint32(cv) { + // Do regular search + break + } + + // Store this, since we have it. + nextHashL := hashLen(cv, dFastLongTableBits, dFastLongLen) + nextHashS := hashLen(cv, dFastShortTableBits, dFastShortLen) + + // We have at least 4 byte match. + // No need to check backwards. We come straight from a match + l := 4 + e.matchlen(s+4, o2+4, src) + + entry := tableEntry{offset: s + e.cur, val: uint32(cv)} + e.longTable[nextHashL] = entry + e.markLongShardDirty(nextHashL) + e.table[nextHashS] = entry + e.markShardDirty(nextHashS) + seq.matchLen = uint32(l) - zstdMinMatch + seq.litLen = 0 + + // Since litlen is always 0, this is offset 1. + seq.offset = 1 + s += l + nextEmit = s + if debugSequences { + println("sequence", seq, "next s:", s) + } + blk.sequences = append(blk.sequences, seq) + + // Swap offset 1 and 2. + offset1, offset2 = offset2, offset1 + if s >= sLimit { + // Finished + break encodeLoop + } + cv = load6432(src, s) + } + } + + if int(nextEmit) < len(src) { + blk.literals = append(blk.literals, src[nextEmit:]...) + blk.extraLits = len(src) - int(nextEmit) + } + blk.recentOffsets[0] = uint32(offset1) + blk.recentOffsets[1] = uint32(offset2) + if debugEncoder { + println("returning, recent offsets:", blk.recentOffsets, "extra literals:", blk.extraLits) + } + // If we encoded more than 64K mark all dirty. + if len(src) > 64<<10 { + e.markAllShardsDirty() + } +} + +// ResetDict will reset and set a dictionary if not nil +func (e *doubleFastEncoder) Reset(d *dict, singleBlock bool) { + e.fastEncoder.Reset(d, singleBlock) + if d != nil { + panic("doubleFastEncoder: Reset with dict not supported") + } +} + +// ResetDict will reset and set a dictionary if not nil +func (e *doubleFastEncoderDict) Reset(d *dict, singleBlock bool) { + allDirty := e.allDirty + e.fastEncoderDict.Reset(d, singleBlock) + if d == nil { + return + } + + // Init or copy dict table + if len(e.dictLongTable) != len(e.longTable) || d.id != e.lastDictID { + if len(e.dictLongTable) != len(e.longTable) { + e.dictLongTable = make([]tableEntry, len(e.longTable)) + } + if len(d.content) >= 8 { + cv := load6432(d.content, 0) + e.dictLongTable[hashLen(cv, dFastLongTableBits, dFastLongLen)] = tableEntry{ + val: uint32(cv), + offset: e.maxMatchOff, + } + end := int32(len(d.content)) - 8 + e.maxMatchOff + for i := e.maxMatchOff + 1; i < end; i++ { + cv = cv>>8 | (uint64(d.content[i-e.maxMatchOff+7]) << 56) + e.dictLongTable[hashLen(cv, dFastLongTableBits, dFastLongLen)] = tableEntry{ + val: uint32(cv), + offset: i, + } + } + } + e.lastDictID = d.id + allDirty = true + } + // Reset table to initial state + e.cur = e.maxMatchOff + + dirtyShardCnt := 0 + if !allDirty { + for i := range e.longTableShardDirty { + if e.longTableShardDirty[i] { + dirtyShardCnt++ + } + } + } + + if allDirty || dirtyShardCnt > dLongTableShardCnt/2 { + //copy(e.longTable[:], e.dictLongTable) + e.longTable = *(*[dFastLongTableSize]tableEntry)(e.dictLongTable) + for i := range e.longTableShardDirty { + e.longTableShardDirty[i] = false + } + return + } + for i := range e.longTableShardDirty { + if !e.longTableShardDirty[i] { + continue + } + + // copy(e.longTable[i*dLongTableShardSize:(i+1)*dLongTableShardSize], e.dictLongTable[i*dLongTableShardSize:(i+1)*dLongTableShardSize]) + *(*[dLongTableShardSize]tableEntry)(e.longTable[i*dLongTableShardSize:]) = *(*[dLongTableShardSize]tableEntry)(e.dictLongTable[i*dLongTableShardSize:]) + + e.longTableShardDirty[i] = false + } +} + +func (e *doubleFastEncoderDict) markLongShardDirty(entryNum uint32) { + e.longTableShardDirty[entryNum/dLongTableShardSize] = true +} diff --git a/vendor/github.com/klauspost/compress/zstd/enc_fast.go b/vendor/github.com/klauspost/compress/zstd/enc_fast.go new file mode 100644 index 000000000..f45a3da7d --- /dev/null +++ b/vendor/github.com/klauspost/compress/zstd/enc_fast.go @@ -0,0 +1,891 @@ +// Copyright 2019+ Klaus Post. All rights reserved. +// License information can be found in the LICENSE file. +// Based on work by Yann Collet, released under BSD License. + +package zstd + +import ( + "fmt" +) + +const ( + tableBits = 15 // Bits used in the table + tableSize = 1 << tableBits // Size of the table + tableShardCnt = 1 << (tableBits - dictShardBits) // Number of shards in the table + tableShardSize = tableSize / tableShardCnt // Size of an individual shard + tableFastHashLen = 6 + tableMask = tableSize - 1 // Mask for table indices. Redundant, but can eliminate bounds checks. + maxMatchLength = 131074 +) + +type tableEntry struct { + val uint32 + offset int32 +} + +type fastEncoder struct { + fastBase + table [tableSize]tableEntry +} + +type fastEncoderDict struct { + fastEncoder + dictTable []tableEntry + tableShardDirty [tableShardCnt]bool + allDirty bool +} + +// Encode mimmics functionality in zstd_fast.c +func (e *fastEncoder) Encode(blk *blockEnc, src []byte) { + const ( + inputMargin = 8 + minNonLiteralBlockSize = 1 + 1 + inputMargin + ) + + // Protect against e.cur wraparound. + for e.cur >= e.bufferReset-int32(len(e.hist)) { + if len(e.hist) == 0 { + for i := range e.table[:] { + e.table[i] = tableEntry{} + } + e.cur = e.maxMatchOff + break + } + // Shift down everything in the table that isn't already too far away. + minOff := e.cur + int32(len(e.hist)) - e.maxMatchOff + for i := range e.table[:] { + v := e.table[i].offset + if v < minOff { + v = 0 + } else { + v = v - e.cur + e.maxMatchOff + } + e.table[i].offset = v + } + e.cur = e.maxMatchOff + break + } + + s := e.addBlock(src) + blk.size = len(src) + if len(src) < minNonLiteralBlockSize { + blk.extraLits = len(src) + blk.literals = blk.literals[:len(src)] + copy(blk.literals, src) + return + } + + // Override src + src = e.hist + sLimit := int32(len(src)) - inputMargin + // stepSize is the number of bytes to skip on every main loop iteration. + // It should be >= 2. + const stepSize = 2 + + // TEMPLATE + const hashLog = tableBits + // seems global, but would be nice to tweak. + const kSearchStrength = 6 + + // nextEmit is where in src the next emitLiteral should start from. + nextEmit := s + cv := load6432(src, s) + + // Relative offsets + offset1 := int32(blk.recentOffsets[0]) + offset2 := int32(blk.recentOffsets[1]) + + addLiterals := func(s *seq, until int32) { + if until == nextEmit { + return + } + blk.literals = append(blk.literals, src[nextEmit:until]...) + s.litLen = uint32(until - nextEmit) + } + if debugEncoder { + println("recent offsets:", blk.recentOffsets) + } + +encodeLoop: + for { + // t will contain the match offset when we find one. + // When existing the search loop, we have already checked 4 bytes. + var t int32 + + // We will not use repeat offsets across blocks. + // By not using them for the first 3 matches + canRepeat := len(blk.sequences) > 2 + + for { + if debugAsserts && canRepeat && offset1 == 0 { + panic("offset0 was 0") + } + + nextHash := hashLen(cv, hashLog, tableFastHashLen) + nextHash2 := hashLen(cv>>8, hashLog, tableFastHashLen) + candidate := e.table[nextHash] + candidate2 := e.table[nextHash2] + repIndex := s - offset1 + 2 + + e.table[nextHash] = tableEntry{offset: s + e.cur, val: uint32(cv)} + e.table[nextHash2] = tableEntry{offset: s + e.cur + 1, val: uint32(cv >> 8)} + + if canRepeat && repIndex >= 0 && load3232(src, repIndex) == uint32(cv>>16) { + // Consider history as well. + var seq seq + length := 4 + e.matchlen(s+6, repIndex+4, src) + seq.matchLen = uint32(length - zstdMinMatch) + + // We might be able to match backwards. + // Extend as long as we can. + start := s + 2 + // We end the search early, so we don't risk 0 literals + // and have to do special offset treatment. + startLimit := nextEmit + 1 + + sMin := s - e.maxMatchOff + if sMin < 0 { + sMin = 0 + } + for repIndex > sMin && start > startLimit && src[repIndex-1] == src[start-1] && seq.matchLen < maxMatchLength-zstdMinMatch { + repIndex-- + start-- + seq.matchLen++ + } + addLiterals(&seq, start) + + // rep 0 + seq.offset = 1 + if debugSequences { + println("repeat sequence", seq, "next s:", s) + } + blk.sequences = append(blk.sequences, seq) + s += length + 2 + nextEmit = s + if s >= sLimit { + if debugEncoder { + println("repeat ended", s, length) + + } + break encodeLoop + } + cv = load6432(src, s) + continue + } + coffset0 := s - (candidate.offset - e.cur) + coffset1 := s - (candidate2.offset - e.cur) + 1 + if coffset0 < e.maxMatchOff && uint32(cv) == candidate.val { + // found a regular match + t = candidate.offset - e.cur + if debugAsserts && s <= t { + panic(fmt.Sprintf("s (%d) <= t (%d)", s, t)) + } + if debugAsserts && s-t > e.maxMatchOff { + panic("s - t >e.maxMatchOff") + } + break + } + + if coffset1 < e.maxMatchOff && uint32(cv>>8) == candidate2.val { + // found a regular match + t = candidate2.offset - e.cur + s++ + if debugAsserts && s <= t { + panic(fmt.Sprintf("s (%d) <= t (%d)", s, t)) + } + if debugAsserts && s-t > e.maxMatchOff { + panic("s - t >e.maxMatchOff") + } + if debugAsserts && t < 0 { + panic("t<0") + } + break + } + s += stepSize + ((s - nextEmit) >> (kSearchStrength - 1)) + if s >= sLimit { + break encodeLoop + } + cv = load6432(src, s) + } + // A 4-byte match has been found. We'll later see if more than 4 bytes. + offset2 = offset1 + offset1 = s - t + + if debugAsserts && s <= t { + panic(fmt.Sprintf("s (%d) <= t (%d)", s, t)) + } + + if debugAsserts && canRepeat && int(offset1) > len(src) { + panic("invalid offset") + } + + // Extend the 4-byte match as long as possible. + l := e.matchlen(s+4, t+4, src) + 4 + + // Extend backwards + tMin := s - e.maxMatchOff + if tMin < 0 { + tMin = 0 + } + for t > tMin && s > nextEmit && src[t-1] == src[s-1] && l < maxMatchLength { + s-- + t-- + l++ + } + + // Write our sequence. + var seq seq + seq.litLen = uint32(s - nextEmit) + seq.matchLen = uint32(l - zstdMinMatch) + if seq.litLen > 0 { + blk.literals = append(blk.literals, src[nextEmit:s]...) + } + // Don't use repeat offsets + seq.offset = uint32(s-t) + 3 + s += l + if debugSequences { + println("sequence", seq, "next s:", s) + } + blk.sequences = append(blk.sequences, seq) + nextEmit = s + if s >= sLimit { + break encodeLoop + } + cv = load6432(src, s) + + // Check offset 2 + if o2 := s - offset2; canRepeat && load3232(src, o2) == uint32(cv) { + // We have at least 4 byte match. + // No need to check backwards. We come straight from a match + l := 4 + e.matchlen(s+4, o2+4, src) + + // Store this, since we have it. + nextHash := hashLen(cv, hashLog, tableFastHashLen) + e.table[nextHash] = tableEntry{offset: s + e.cur, val: uint32(cv)} + seq.matchLen = uint32(l) - zstdMinMatch + seq.litLen = 0 + // Since litlen is always 0, this is offset 1. + seq.offset = 1 + s += l + nextEmit = s + if debugSequences { + println("sequence", seq, "next s:", s) + } + blk.sequences = append(blk.sequences, seq) + + // Swap offset 1 and 2. + offset1, offset2 = offset2, offset1 + if s >= sLimit { + break encodeLoop + } + // Prepare next loop. + cv = load6432(src, s) + } + } + + if int(nextEmit) < len(src) { + blk.literals = append(blk.literals, src[nextEmit:]...) + blk.extraLits = len(src) - int(nextEmit) + } + blk.recentOffsets[0] = uint32(offset1) + blk.recentOffsets[1] = uint32(offset2) + if debugEncoder { + println("returning, recent offsets:", blk.recentOffsets, "extra literals:", blk.extraLits) + } +} + +// EncodeNoHist will encode a block with no history and no following blocks. +// Most notable difference is that src will not be copied for history and +// we do not need to check for max match length. +func (e *fastEncoder) EncodeNoHist(blk *blockEnc, src []byte) { + const ( + inputMargin = 8 + minNonLiteralBlockSize = 1 + 1 + inputMargin + ) + if debugEncoder { + if len(src) > maxCompressedBlockSize { + panic("src too big") + } + } + + // Protect against e.cur wraparound. + if e.cur >= e.bufferReset { + for i := range e.table[:] { + e.table[i] = tableEntry{} + } + e.cur = e.maxMatchOff + } + + s := int32(0) + blk.size = len(src) + if len(src) < minNonLiteralBlockSize { + blk.extraLits = len(src) + blk.literals = blk.literals[:len(src)] + copy(blk.literals, src) + return + } + + sLimit := int32(len(src)) - inputMargin + // stepSize is the number of bytes to skip on every main loop iteration. + // It should be >= 2. + const stepSize = 2 + + // TEMPLATE + const hashLog = tableBits + // seems global, but would be nice to tweak. + const kSearchStrength = 6 + + // nextEmit is where in src the next emitLiteral should start from. + nextEmit := s + cv := load6432(src, s) + + // Relative offsets + offset1 := int32(blk.recentOffsets[0]) + offset2 := int32(blk.recentOffsets[1]) + + addLiterals := func(s *seq, until int32) { + if until == nextEmit { + return + } + blk.literals = append(blk.literals, src[nextEmit:until]...) + s.litLen = uint32(until - nextEmit) + } + if debugEncoder { + println("recent offsets:", blk.recentOffsets) + } + +encodeLoop: + for { + // t will contain the match offset when we find one. + // When existing the search loop, we have already checked 4 bytes. + var t int32 + + // We will not use repeat offsets across blocks. + // By not using them for the first 3 matches + + for { + nextHash := hashLen(cv, hashLog, tableFastHashLen) + nextHash2 := hashLen(cv>>8, hashLog, tableFastHashLen) + candidate := e.table[nextHash] + candidate2 := e.table[nextHash2] + repIndex := s - offset1 + 2 + + e.table[nextHash] = tableEntry{offset: s + e.cur, val: uint32(cv)} + e.table[nextHash2] = tableEntry{offset: s + e.cur + 1, val: uint32(cv >> 8)} + + if len(blk.sequences) > 2 && load3232(src, repIndex) == uint32(cv>>16) { + // Consider history as well. + var seq seq + length := 4 + e.matchlen(s+6, repIndex+4, src) + + seq.matchLen = uint32(length - zstdMinMatch) + + // We might be able to match backwards. + // Extend as long as we can. + start := s + 2 + // We end the search early, so we don't risk 0 literals + // and have to do special offset treatment. + startLimit := nextEmit + 1 + + sMin := s - e.maxMatchOff + if sMin < 0 { + sMin = 0 + } + for repIndex > sMin && start > startLimit && src[repIndex-1] == src[start-1] { + repIndex-- + start-- + seq.matchLen++ + } + addLiterals(&seq, start) + + // rep 0 + seq.offset = 1 + if debugSequences { + println("repeat sequence", seq, "next s:", s) + } + blk.sequences = append(blk.sequences, seq) + s += length + 2 + nextEmit = s + if s >= sLimit { + if debugEncoder { + println("repeat ended", s, length) + + } + break encodeLoop + } + cv = load6432(src, s) + continue + } + coffset0 := s - (candidate.offset - e.cur) + coffset1 := s - (candidate2.offset - e.cur) + 1 + if coffset0 < e.maxMatchOff && uint32(cv) == candidate.val { + // found a regular match + t = candidate.offset - e.cur + if debugAsserts && s <= t { + panic(fmt.Sprintf("s (%d) <= t (%d)", s, t)) + } + if debugAsserts && s-t > e.maxMatchOff { + panic("s - t >e.maxMatchOff") + } + if debugAsserts && t < 0 { + panic(fmt.Sprintf("t (%d) < 0, candidate.offset: %d, e.cur: %d, coffset0: %d, e.maxMatchOff: %d", t, candidate.offset, e.cur, coffset0, e.maxMatchOff)) + } + break + } + + if coffset1 < e.maxMatchOff && uint32(cv>>8) == candidate2.val { + // found a regular match + t = candidate2.offset - e.cur + s++ + if debugAsserts && s <= t { + panic(fmt.Sprintf("s (%d) <= t (%d)", s, t)) + } + if debugAsserts && s-t > e.maxMatchOff { + panic("s - t >e.maxMatchOff") + } + if debugAsserts && t < 0 { + panic("t<0") + } + break + } + s += stepSize + ((s - nextEmit) >> (kSearchStrength - 1)) + if s >= sLimit { + break encodeLoop + } + cv = load6432(src, s) + } + // A 4-byte match has been found. We'll later see if more than 4 bytes. + offset2 = offset1 + offset1 = s - t + + if debugAsserts && s <= t { + panic(fmt.Sprintf("s (%d) <= t (%d)", s, t)) + } + + if debugAsserts && t < 0 { + panic(fmt.Sprintf("t (%d) < 0 ", t)) + } + // Extend the 4-byte match as long as possible. + l := e.matchlen(s+4, t+4, src) + 4 + + // Extend backwards + tMin := s - e.maxMatchOff + if tMin < 0 { + tMin = 0 + } + for t > tMin && s > nextEmit && src[t-1] == src[s-1] { + s-- + t-- + l++ + } + + // Write our sequence. + var seq seq + seq.litLen = uint32(s - nextEmit) + seq.matchLen = uint32(l - zstdMinMatch) + if seq.litLen > 0 { + blk.literals = append(blk.literals, src[nextEmit:s]...) + } + // Don't use repeat offsets + seq.offset = uint32(s-t) + 3 + s += l + if debugSequences { + println("sequence", seq, "next s:", s) + } + blk.sequences = append(blk.sequences, seq) + nextEmit = s + if s >= sLimit { + break encodeLoop + } + cv = load6432(src, s) + + // Check offset 2 + if o2 := s - offset2; len(blk.sequences) > 2 && load3232(src, o2) == uint32(cv) { + // We have at least 4 byte match. + // No need to check backwards. We come straight from a match + l := 4 + e.matchlen(s+4, o2+4, src) + + // Store this, since we have it. + nextHash := hashLen(cv, hashLog, tableFastHashLen) + e.table[nextHash] = tableEntry{offset: s + e.cur, val: uint32(cv)} + seq.matchLen = uint32(l) - zstdMinMatch + seq.litLen = 0 + // Since litlen is always 0, this is offset 1. + seq.offset = 1 + s += l + nextEmit = s + if debugSequences { + println("sequence", seq, "next s:", s) + } + blk.sequences = append(blk.sequences, seq) + + // Swap offset 1 and 2. + offset1, offset2 = offset2, offset1 + if s >= sLimit { + break encodeLoop + } + // Prepare next loop. + cv = load6432(src, s) + } + } + + if int(nextEmit) < len(src) { + blk.literals = append(blk.literals, src[nextEmit:]...) + blk.extraLits = len(src) - int(nextEmit) + } + if debugEncoder { + println("returning, recent offsets:", blk.recentOffsets, "extra literals:", blk.extraLits) + } + // We do not store history, so we must offset e.cur to avoid false matches for next user. + if e.cur < e.bufferReset { + e.cur += int32(len(src)) + } +} + +// Encode will encode the content, with a dictionary if initialized for it. +func (e *fastEncoderDict) Encode(blk *blockEnc, src []byte) { + const ( + inputMargin = 8 + minNonLiteralBlockSize = 1 + 1 + inputMargin + ) + if e.allDirty || len(src) > 32<<10 { + e.fastEncoder.Encode(blk, src) + e.allDirty = true + return + } + // Protect against e.cur wraparound. + for e.cur >= e.bufferReset-int32(len(e.hist)) { + if len(e.hist) == 0 { + e.table = [tableSize]tableEntry{} + e.cur = e.maxMatchOff + break + } + // Shift down everything in the table that isn't already too far away. + minOff := e.cur + int32(len(e.hist)) - e.maxMatchOff + for i := range e.table[:] { + v := e.table[i].offset + if v < minOff { + v = 0 + } else { + v = v - e.cur + e.maxMatchOff + } + e.table[i].offset = v + } + e.cur = e.maxMatchOff + break + } + + s := e.addBlock(src) + blk.size = len(src) + if len(src) < minNonLiteralBlockSize { + blk.extraLits = len(src) + blk.literals = blk.literals[:len(src)] + copy(blk.literals, src) + return + } + + // Override src + src = e.hist + sLimit := int32(len(src)) - inputMargin + // stepSize is the number of bytes to skip on every main loop iteration. + // It should be >= 2. + const stepSize = 2 + + // TEMPLATE + const hashLog = tableBits + // seems global, but would be nice to tweak. + const kSearchStrength = 7 + + // nextEmit is where in src the next emitLiteral should start from. + nextEmit := s + cv := load6432(src, s) + + // Relative offsets + offset1 := int32(blk.recentOffsets[0]) + offset2 := int32(blk.recentOffsets[1]) + + addLiterals := func(s *seq, until int32) { + if until == nextEmit { + return + } + blk.literals = append(blk.literals, src[nextEmit:until]...) + s.litLen = uint32(until - nextEmit) + } + if debugEncoder { + println("recent offsets:", blk.recentOffsets) + } + +encodeLoop: + for { + // t will contain the match offset when we find one. + // When existing the search loop, we have already checked 4 bytes. + var t int32 + + // We will not use repeat offsets across blocks. + // By not using them for the first 3 matches + canRepeat := len(blk.sequences) > 2 + + for { + if debugAsserts && canRepeat && offset1 == 0 { + panic("offset0 was 0") + } + + nextHash := hashLen(cv, hashLog, tableFastHashLen) + nextHash2 := hashLen(cv>>8, hashLog, tableFastHashLen) + candidate := e.table[nextHash] + candidate2 := e.table[nextHash2] + repIndex := s - offset1 + 2 + + e.table[nextHash] = tableEntry{offset: s + e.cur, val: uint32(cv)} + e.markShardDirty(nextHash) + e.table[nextHash2] = tableEntry{offset: s + e.cur + 1, val: uint32(cv >> 8)} + e.markShardDirty(nextHash2) + + if canRepeat && repIndex >= 0 && load3232(src, repIndex) == uint32(cv>>16) { + // Consider history as well. + var seq seq + length := 4 + e.matchlen(s+6, repIndex+4, src) + + seq.matchLen = uint32(length - zstdMinMatch) + + // We might be able to match backwards. + // Extend as long as we can. + start := s + 2 + // We end the search early, so we don't risk 0 literals + // and have to do special offset treatment. + startLimit := nextEmit + 1 + + sMin := s - e.maxMatchOff + if sMin < 0 { + sMin = 0 + } + for repIndex > sMin && start > startLimit && src[repIndex-1] == src[start-1] && seq.matchLen < maxMatchLength-zstdMinMatch { + repIndex-- + start-- + seq.matchLen++ + } + addLiterals(&seq, start) + + // rep 0 + seq.offset = 1 + if debugSequences { + println("repeat sequence", seq, "next s:", s) + } + blk.sequences = append(blk.sequences, seq) + s += length + 2 + nextEmit = s + if s >= sLimit { + if debugEncoder { + println("repeat ended", s, length) + + } + break encodeLoop + } + cv = load6432(src, s) + continue + } + coffset0 := s - (candidate.offset - e.cur) + coffset1 := s - (candidate2.offset - e.cur) + 1 + if coffset0 < e.maxMatchOff && uint32(cv) == candidate.val { + // found a regular match + t = candidate.offset - e.cur + if debugAsserts && s <= t { + panic(fmt.Sprintf("s (%d) <= t (%d)", s, t)) + } + if debugAsserts && s-t > e.maxMatchOff { + panic("s - t >e.maxMatchOff") + } + break + } + + if coffset1 < e.maxMatchOff && uint32(cv>>8) == candidate2.val { + // found a regular match + t = candidate2.offset - e.cur + s++ + if debugAsserts && s <= t { + panic(fmt.Sprintf("s (%d) <= t (%d)", s, t)) + } + if debugAsserts && s-t > e.maxMatchOff { + panic("s - t >e.maxMatchOff") + } + if debugAsserts && t < 0 { + panic("t<0") + } + break + } + s += stepSize + ((s - nextEmit) >> (kSearchStrength - 1)) + if s >= sLimit { + break encodeLoop + } + cv = load6432(src, s) + } + // A 4-byte match has been found. We'll later see if more than 4 bytes. + offset2 = offset1 + offset1 = s - t + + if debugAsserts && s <= t { + panic(fmt.Sprintf("s (%d) <= t (%d)", s, t)) + } + + if debugAsserts && canRepeat && int(offset1) > len(src) { + panic("invalid offset") + } + + // Extend the 4-byte match as long as possible. + l := e.matchlen(s+4, t+4, src) + 4 + + // Extend backwards + tMin := s - e.maxMatchOff + if tMin < 0 { + tMin = 0 + } + for t > tMin && s > nextEmit && src[t-1] == src[s-1] && l < maxMatchLength { + s-- + t-- + l++ + } + + // Write our sequence. + var seq seq + seq.litLen = uint32(s - nextEmit) + seq.matchLen = uint32(l - zstdMinMatch) + if seq.litLen > 0 { + blk.literals = append(blk.literals, src[nextEmit:s]...) + } + // Don't use repeat offsets + seq.offset = uint32(s-t) + 3 + s += l + if debugSequences { + println("sequence", seq, "next s:", s) + } + blk.sequences = append(blk.sequences, seq) + nextEmit = s + if s >= sLimit { + break encodeLoop + } + cv = load6432(src, s) + + // Check offset 2 + if o2 := s - offset2; canRepeat && load3232(src, o2) == uint32(cv) { + // We have at least 4 byte match. + // No need to check backwards. We come straight from a match + l := 4 + e.matchlen(s+4, o2+4, src) + + // Store this, since we have it. + nextHash := hashLen(cv, hashLog, tableFastHashLen) + e.table[nextHash] = tableEntry{offset: s + e.cur, val: uint32(cv)} + e.markShardDirty(nextHash) + seq.matchLen = uint32(l) - zstdMinMatch + seq.litLen = 0 + // Since litlen is always 0, this is offset 1. + seq.offset = 1 + s += l + nextEmit = s + if debugSequences { + println("sequence", seq, "next s:", s) + } + blk.sequences = append(blk.sequences, seq) + + // Swap offset 1 and 2. + offset1, offset2 = offset2, offset1 + if s >= sLimit { + break encodeLoop + } + // Prepare next loop. + cv = load6432(src, s) + } + } + + if int(nextEmit) < len(src) { + blk.literals = append(blk.literals, src[nextEmit:]...) + blk.extraLits = len(src) - int(nextEmit) + } + blk.recentOffsets[0] = uint32(offset1) + blk.recentOffsets[1] = uint32(offset2) + if debugEncoder { + println("returning, recent offsets:", blk.recentOffsets, "extra literals:", blk.extraLits) + } +} + +// ResetDict will reset and set a dictionary if not nil +func (e *fastEncoder) Reset(d *dict, singleBlock bool) { + e.resetBase(d, singleBlock) + if d != nil { + panic("fastEncoder: Reset with dict") + } +} + +// ResetDict will reset and set a dictionary if not nil +func (e *fastEncoderDict) Reset(d *dict, singleBlock bool) { + e.resetBase(d, singleBlock) + if d == nil { + return + } + + // Init or copy dict table + if len(e.dictTable) != len(e.table) || d.id != e.lastDictID { + if len(e.dictTable) != len(e.table) { + e.dictTable = make([]tableEntry, len(e.table)) + } + if true { + end := e.maxMatchOff + int32(len(d.content)) - 8 + for i := e.maxMatchOff; i < end; i += 2 { + const hashLog = tableBits + + cv := load6432(d.content, i-e.maxMatchOff) + nextHash := hashLen(cv, hashLog, tableFastHashLen) // 0 -> 6 + nextHash1 := hashLen(cv>>8, hashLog, tableFastHashLen) // 1 -> 7 + e.dictTable[nextHash] = tableEntry{ + val: uint32(cv), + offset: i, + } + e.dictTable[nextHash1] = tableEntry{ + val: uint32(cv >> 8), + offset: i + 1, + } + } + } + e.lastDictID = d.id + e.allDirty = true + } + + e.cur = e.maxMatchOff + dirtyShardCnt := 0 + if !e.allDirty { + for i := range e.tableShardDirty { + if e.tableShardDirty[i] { + dirtyShardCnt++ + } + } + } + + const shardCnt = tableShardCnt + const shardSize = tableShardSize + if e.allDirty || dirtyShardCnt > shardCnt*4/6 { + //copy(e.table[:], e.dictTable) + e.table = *(*[tableSize]tableEntry)(e.dictTable) + for i := range e.tableShardDirty { + e.tableShardDirty[i] = false + } + e.allDirty = false + return + } + for i := range e.tableShardDirty { + if !e.tableShardDirty[i] { + continue + } + + //copy(e.table[i*shardSize:(i+1)*shardSize], e.dictTable[i*shardSize:(i+1)*shardSize]) + *(*[shardSize]tableEntry)(e.table[i*shardSize:]) = *(*[shardSize]tableEntry)(e.dictTable[i*shardSize:]) + e.tableShardDirty[i] = false + } + e.allDirty = false +} + +func (e *fastEncoderDict) markAllShardsDirty() { + e.allDirty = true +} + +func (e *fastEncoderDict) markShardDirty(entryNum uint32) { + e.tableShardDirty[entryNum/tableShardSize] = true +} diff --git a/vendor/github.com/klauspost/compress/zstd/encoder.go b/vendor/github.com/klauspost/compress/zstd/encoder.go new file mode 100644 index 000000000..72af7ef0f --- /dev/null +++ b/vendor/github.com/klauspost/compress/zstd/encoder.go @@ -0,0 +1,619 @@ +// Copyright 2019+ Klaus Post. All rights reserved. +// License information can be found in the LICENSE file. +// Based on work by Yann Collet, released under BSD License. + +package zstd + +import ( + "crypto/rand" + "fmt" + "io" + "math" + rdebug "runtime/debug" + "sync" + + "github.com/klauspost/compress/zstd/internal/xxhash" +) + +// Encoder provides encoding to Zstandard. +// An Encoder can be used for either compressing a stream via the +// io.WriteCloser interface supported by the Encoder or as multiple independent +// tasks via the EncodeAll function. +// Smaller encodes are encouraged to use the EncodeAll function. +// Use NewWriter to create a new instance. +type Encoder struct { + o encoderOptions + encoders chan encoder + state encoderState + init sync.Once +} + +type encoder interface { + Encode(blk *blockEnc, src []byte) + EncodeNoHist(blk *blockEnc, src []byte) + Block() *blockEnc + CRC() *xxhash.Digest + AppendCRC([]byte) []byte + WindowSize(size int64) int32 + UseBlock(*blockEnc) + Reset(d *dict, singleBlock bool) +} + +type encoderState struct { + w io.Writer + filling []byte + current []byte + previous []byte + encoder encoder + writing *blockEnc + err error + writeErr error + nWritten int64 + nInput int64 + frameContentSize int64 + headerWritten bool + eofWritten bool + fullFrameWritten bool + + // This waitgroup indicates an encode is running. + wg sync.WaitGroup + // This waitgroup indicates we have a block encoding/writing. + wWg sync.WaitGroup +} + +// NewWriter will create a new Zstandard encoder. +// If the encoder will be used for encoding blocks a nil writer can be used. +func NewWriter(w io.Writer, opts ...EOption) (*Encoder, error) { + initPredefined() + var e Encoder + e.o.setDefault() + for _, o := range opts { + err := o(&e.o) + if err != nil { + return nil, err + } + } + if w != nil { + e.Reset(w) + } + return &e, nil +} + +func (e *Encoder) initialize() { + if e.o.concurrent == 0 { + e.o.setDefault() + } + e.encoders = make(chan encoder, e.o.concurrent) + for i := 0; i < e.o.concurrent; i++ { + enc := e.o.encoder() + e.encoders <- enc + } +} + +// Reset will re-initialize the writer and new writes will encode to the supplied writer +// as a new, independent stream. +func (e *Encoder) Reset(w io.Writer) { + s := &e.state + s.wg.Wait() + s.wWg.Wait() + if cap(s.filling) == 0 { + s.filling = make([]byte, 0, e.o.blockSize) + } + if e.o.concurrent > 1 { + if cap(s.current) == 0 { + s.current = make([]byte, 0, e.o.blockSize) + } + if cap(s.previous) == 0 { + s.previous = make([]byte, 0, e.o.blockSize) + } + s.current = s.current[:0] + s.previous = s.previous[:0] + if s.writing == nil { + s.writing = &blockEnc{lowMem: e.o.lowMem} + s.writing.init() + } + s.writing.initNewEncode() + } + if s.encoder == nil { + s.encoder = e.o.encoder() + } + s.filling = s.filling[:0] + s.encoder.Reset(e.o.dict, false) + s.headerWritten = false + s.eofWritten = false + s.fullFrameWritten = false + s.w = w + s.err = nil + s.nWritten = 0 + s.nInput = 0 + s.writeErr = nil + s.frameContentSize = 0 +} + +// ResetContentSize will reset and set a content size for the next stream. +// If the bytes written does not match the size given an error will be returned +// when calling Close(). +// This is removed when Reset is called. +// Sizes <= 0 results in no content size set. +func (e *Encoder) ResetContentSize(w io.Writer, size int64) { + e.Reset(w) + if size >= 0 { + e.state.frameContentSize = size + } +} + +// Write data to the encoder. +// Input data will be buffered and as the buffer fills up +// content will be compressed and written to the output. +// When done writing, use Close to flush the remaining output +// and write CRC if requested. +func (e *Encoder) Write(p []byte) (n int, err error) { + s := &e.state + for len(p) > 0 { + if len(p)+len(s.filling) < e.o.blockSize { + if e.o.crc { + _, _ = s.encoder.CRC().Write(p) + } + s.filling = append(s.filling, p...) + return n + len(p), nil + } + add := p + if len(p)+len(s.filling) > e.o.blockSize { + add = add[:e.o.blockSize-len(s.filling)] + } + if e.o.crc { + _, _ = s.encoder.CRC().Write(add) + } + s.filling = append(s.filling, add...) + p = p[len(add):] + n += len(add) + if len(s.filling) < e.o.blockSize { + return n, nil + } + err := e.nextBlock(false) + if err != nil { + return n, err + } + if debugAsserts && len(s.filling) > 0 { + panic(len(s.filling)) + } + } + return n, nil +} + +// nextBlock will synchronize and start compressing input in e.state.filling. +// If an error has occurred during encoding it will be returned. +func (e *Encoder) nextBlock(final bool) error { + s := &e.state + // Wait for current block. + s.wg.Wait() + if s.err != nil { + return s.err + } + if len(s.filling) > e.o.blockSize { + return fmt.Errorf("block > maxStoreBlockSize") + } + if !s.headerWritten { + // If we have a single block encode, do a sync compression. + if final && len(s.filling) == 0 && !e.o.fullZero { + s.headerWritten = true + s.fullFrameWritten = true + s.eofWritten = true + return nil + } + if final && len(s.filling) > 0 { + s.current = e.EncodeAll(s.filling, s.current[:0]) + var n2 int + n2, s.err = s.w.Write(s.current) + if s.err != nil { + return s.err + } + s.nWritten += int64(n2) + s.nInput += int64(len(s.filling)) + s.current = s.current[:0] + s.filling = s.filling[:0] + s.headerWritten = true + s.fullFrameWritten = true + s.eofWritten = true + return nil + } + + var tmp [maxHeaderSize]byte + fh := frameHeader{ + ContentSize: uint64(s.frameContentSize), + WindowSize: uint32(s.encoder.WindowSize(s.frameContentSize)), + SingleSegment: false, + Checksum: e.o.crc, + DictID: e.o.dict.ID(), + } + + dst := fh.appendTo(tmp[:0]) + s.headerWritten = true + s.wWg.Wait() + var n2 int + n2, s.err = s.w.Write(dst) + if s.err != nil { + return s.err + } + s.nWritten += int64(n2) + } + if s.eofWritten { + // Ensure we only write it once. + final = false + } + + if len(s.filling) == 0 { + // Final block, but no data. + if final { + enc := s.encoder + blk := enc.Block() + blk.reset(nil) + blk.last = true + blk.encodeRaw(nil) + s.wWg.Wait() + _, s.err = s.w.Write(blk.output) + s.nWritten += int64(len(blk.output)) + s.eofWritten = true + } + return s.err + } + + // SYNC: + if e.o.concurrent == 1 { + src := s.filling + s.nInput += int64(len(s.filling)) + if debugEncoder { + println("Adding sync block,", len(src), "bytes, final:", final) + } + enc := s.encoder + blk := enc.Block() + blk.reset(nil) + enc.Encode(blk, src) + blk.last = final + if final { + s.eofWritten = true + } + + s.err = blk.encode(src, e.o.noEntropy, !e.o.allLitEntropy) + if s.err != nil { + return s.err + } + _, s.err = s.w.Write(blk.output) + s.nWritten += int64(len(blk.output)) + s.filling = s.filling[:0] + return s.err + } + + // Move blocks forward. + s.filling, s.current, s.previous = s.previous[:0], s.filling, s.current + s.nInput += int64(len(s.current)) + s.wg.Add(1) + go func(src []byte) { + if debugEncoder { + println("Adding block,", len(src), "bytes, final:", final) + } + defer func() { + if r := recover(); r != nil { + s.err = fmt.Errorf("panic while encoding: %v", r) + rdebug.PrintStack() + } + s.wg.Done() + }() + enc := s.encoder + blk := enc.Block() + enc.Encode(blk, src) + blk.last = final + if final { + s.eofWritten = true + } + // Wait for pending writes. + s.wWg.Wait() + if s.writeErr != nil { + s.err = s.writeErr + return + } + // Transfer encoders from previous write block. + blk.swapEncoders(s.writing) + // Transfer recent offsets to next. + enc.UseBlock(s.writing) + s.writing = blk + s.wWg.Add(1) + go func() { + defer func() { + if r := recover(); r != nil { + s.writeErr = fmt.Errorf("panic while encoding/writing: %v", r) + rdebug.PrintStack() + } + s.wWg.Done() + }() + s.writeErr = blk.encode(src, e.o.noEntropy, !e.o.allLitEntropy) + if s.writeErr != nil { + return + } + _, s.writeErr = s.w.Write(blk.output) + s.nWritten += int64(len(blk.output)) + }() + }(s.current) + return nil +} + +// ReadFrom reads data from r until EOF or error. +// The return value n is the number of bytes read. +// Any error except io.EOF encountered during the read is also returned. +// +// The Copy function uses ReaderFrom if available. +func (e *Encoder) ReadFrom(r io.Reader) (n int64, err error) { + if debugEncoder { + println("Using ReadFrom") + } + + // Flush any current writes. + if len(e.state.filling) > 0 { + if err := e.nextBlock(false); err != nil { + return 0, err + } + } + e.state.filling = e.state.filling[:e.o.blockSize] + src := e.state.filling + for { + n2, err := r.Read(src) + if e.o.crc { + _, _ = e.state.encoder.CRC().Write(src[:n2]) + } + // src is now the unfilled part... + src = src[n2:] + n += int64(n2) + switch err { + case io.EOF: + e.state.filling = e.state.filling[:len(e.state.filling)-len(src)] + if debugEncoder { + println("ReadFrom: got EOF final block:", len(e.state.filling)) + } + return n, nil + case nil: + default: + if debugEncoder { + println("ReadFrom: got error:", err) + } + e.state.err = err + return n, err + } + if len(src) > 0 { + if debugEncoder { + println("ReadFrom: got space left in source:", len(src)) + } + continue + } + err = e.nextBlock(false) + if err != nil { + return n, err + } + e.state.filling = e.state.filling[:e.o.blockSize] + src = e.state.filling + } +} + +// Flush will send the currently written data to output +// and block until everything has been written. +// This should only be used on rare occasions where pushing the currently queued data is critical. +func (e *Encoder) Flush() error { + s := &e.state + if len(s.filling) > 0 { + err := e.nextBlock(false) + if err != nil { + return err + } + } + s.wg.Wait() + s.wWg.Wait() + if s.err != nil { + return s.err + } + return s.writeErr +} + +// Close will flush the final output and close the stream. +// The function will block until everything has been written. +// The Encoder can still be re-used after calling this. +func (e *Encoder) Close() error { + s := &e.state + if s.encoder == nil { + return nil + } + err := e.nextBlock(true) + if err != nil { + return err + } + if s.frameContentSize > 0 { + if s.nInput != s.frameContentSize { + return fmt.Errorf("frame content size %d given, but %d bytes was written", s.frameContentSize, s.nInput) + } + } + if e.state.fullFrameWritten { + return s.err + } + s.wg.Wait() + s.wWg.Wait() + + if s.err != nil { + return s.err + } + if s.writeErr != nil { + return s.writeErr + } + + // Write CRC + if e.o.crc && s.err == nil { + // heap alloc. + var tmp [4]byte + _, s.err = s.w.Write(s.encoder.AppendCRC(tmp[:0])) + s.nWritten += 4 + } + + // Add padding with content from crypto/rand.Reader + if s.err == nil && e.o.pad > 0 { + add := calcSkippableFrame(s.nWritten, int64(e.o.pad)) + frame, err := skippableFrame(s.filling[:0], add, rand.Reader) + if err != nil { + return err + } + _, s.err = s.w.Write(frame) + } + return s.err +} + +// EncodeAll will encode all input in src and append it to dst. +// This function can be called concurrently, but each call will only run on a single goroutine. +// If empty input is given, nothing is returned, unless WithZeroFrames is specified. +// Encoded blocks can be concatenated and the result will be the combined input stream. +// Data compressed with EncodeAll can be decoded with the Decoder, +// using either a stream or DecodeAll. +func (e *Encoder) EncodeAll(src, dst []byte) []byte { + if len(src) == 0 { + if e.o.fullZero { + // Add frame header. + fh := frameHeader{ + ContentSize: 0, + WindowSize: MinWindowSize, + SingleSegment: true, + // Adding a checksum would be a waste of space. + Checksum: false, + DictID: 0, + } + dst = fh.appendTo(dst) + + // Write raw block as last one only. + var blk blockHeader + blk.setSize(0) + blk.setType(blockTypeRaw) + blk.setLast(true) + dst = blk.appendTo(dst) + } + return dst + } + e.init.Do(e.initialize) + enc := <-e.encoders + defer func() { + // Release encoder reference to last block. + // If a non-single block is needed the encoder will reset again. + e.encoders <- enc + }() + // Use single segments when above minimum window and below window size. + single := len(src) <= e.o.windowSize && len(src) > MinWindowSize + if e.o.single != nil { + single = *e.o.single + } + fh := frameHeader{ + ContentSize: uint64(len(src)), + WindowSize: uint32(enc.WindowSize(int64(len(src)))), + SingleSegment: single, + Checksum: e.o.crc, + DictID: e.o.dict.ID(), + } + + // If less than 1MB, allocate a buffer up front. + if len(dst) == 0 && cap(dst) == 0 && len(src) < 1<<20 && !e.o.lowMem { + dst = make([]byte, 0, len(src)) + } + dst = fh.appendTo(dst) + + // If we can do everything in one block, prefer that. + if len(src) <= e.o.blockSize { + enc.Reset(e.o.dict, true) + // Slightly faster with no history and everything in one block. + if e.o.crc { + _, _ = enc.CRC().Write(src) + } + blk := enc.Block() + blk.last = true + if e.o.dict == nil { + enc.EncodeNoHist(blk, src) + } else { + enc.Encode(blk, src) + } + + // If we got the exact same number of literals as input, + // assume the literals cannot be compressed. + oldout := blk.output + // Output directly to dst + blk.output = dst + + err := blk.encode(src, e.o.noEntropy, !e.o.allLitEntropy) + if err != nil { + panic(err) + } + dst = blk.output + blk.output = oldout + } else { + enc.Reset(e.o.dict, false) + blk := enc.Block() + for len(src) > 0 { + todo := src + if len(todo) > e.o.blockSize { + todo = todo[:e.o.blockSize] + } + src = src[len(todo):] + if e.o.crc { + _, _ = enc.CRC().Write(todo) + } + blk.pushOffsets() + enc.Encode(blk, todo) + if len(src) == 0 { + blk.last = true + } + err := blk.encode(todo, e.o.noEntropy, !e.o.allLitEntropy) + if err != nil { + panic(err) + } + dst = append(dst, blk.output...) + blk.reset(nil) + } + } + if e.o.crc { + dst = enc.AppendCRC(dst) + } + // Add padding with content from crypto/rand.Reader + if e.o.pad > 0 { + add := calcSkippableFrame(int64(len(dst)), int64(e.o.pad)) + var err error + dst, err = skippableFrame(dst, add, rand.Reader) + if err != nil { + panic(err) + } + } + return dst +} + +// MaxEncodedSize returns the expected maximum +// size of an encoded block or stream. +func (e *Encoder) MaxEncodedSize(size int) int { + frameHeader := 4 + 2 // magic + frame header & window descriptor + if e.o.dict != nil { + frameHeader += 4 + } + // Frame content size: + if size < 256 { + frameHeader++ + } else if size < 65536+256 { + frameHeader += 2 + } else if size < math.MaxInt32 { + frameHeader += 4 + } else { + frameHeader += 8 + } + // Final crc + if e.o.crc { + frameHeader += 4 + } + + // Max overhead is 3 bytes/block. + // There cannot be 0 blocks. + blocks := (size + e.o.blockSize) / e.o.blockSize + + // Combine, add padding. + maxSz := frameHeader + 3*blocks + size + if e.o.pad > 1 { + maxSz += calcSkippableFrame(int64(maxSz), int64(e.o.pad)) + } + return maxSz +} diff --git a/vendor/github.com/klauspost/compress/zstd/encoder_options.go b/vendor/github.com/klauspost/compress/zstd/encoder_options.go new file mode 100644 index 000000000..20671dcb9 --- /dev/null +++ b/vendor/github.com/klauspost/compress/zstd/encoder_options.go @@ -0,0 +1,339 @@ +package zstd + +import ( + "errors" + "fmt" + "math" + "math/bits" + "runtime" + "strings" +) + +// EOption is an option for creating a encoder. +type EOption func(*encoderOptions) error + +// options retains accumulated state of multiple options. +type encoderOptions struct { + concurrent int + level EncoderLevel + single *bool + pad int + blockSize int + windowSize int + crc bool + fullZero bool + noEntropy bool + allLitEntropy bool + customWindow bool + customALEntropy bool + customBlockSize bool + lowMem bool + dict *dict +} + +func (o *encoderOptions) setDefault() { + *o = encoderOptions{ + concurrent: runtime.GOMAXPROCS(0), + crc: true, + single: nil, + blockSize: maxCompressedBlockSize, + windowSize: 8 << 20, + level: SpeedDefault, + allLitEntropy: false, + lowMem: false, + } +} + +// encoder returns an encoder with the selected options. +func (o encoderOptions) encoder() encoder { + switch o.level { + case SpeedFastest: + if o.dict != nil { + return &fastEncoderDict{fastEncoder: fastEncoder{fastBase: fastBase{maxMatchOff: int32(o.windowSize), bufferReset: math.MaxInt32 - int32(o.windowSize*2), lowMem: o.lowMem}}} + } + return &fastEncoder{fastBase: fastBase{maxMatchOff: int32(o.windowSize), bufferReset: math.MaxInt32 - int32(o.windowSize*2), lowMem: o.lowMem}} + + case SpeedDefault: + if o.dict != nil { + return &doubleFastEncoderDict{fastEncoderDict: fastEncoderDict{fastEncoder: fastEncoder{fastBase: fastBase{maxMatchOff: int32(o.windowSize), bufferReset: math.MaxInt32 - int32(o.windowSize*2), lowMem: o.lowMem}}}} + } + return &doubleFastEncoder{fastEncoder: fastEncoder{fastBase: fastBase{maxMatchOff: int32(o.windowSize), bufferReset: math.MaxInt32 - int32(o.windowSize*2), lowMem: o.lowMem}}} + case SpeedBetterCompression: + if o.dict != nil { + return &betterFastEncoderDict{betterFastEncoder: betterFastEncoder{fastBase: fastBase{maxMatchOff: int32(o.windowSize), bufferReset: math.MaxInt32 - int32(o.windowSize*2), lowMem: o.lowMem}}} + } + return &betterFastEncoder{fastBase: fastBase{maxMatchOff: int32(o.windowSize), bufferReset: math.MaxInt32 - int32(o.windowSize*2), lowMem: o.lowMem}} + case SpeedBestCompression: + return &bestFastEncoder{fastBase: fastBase{maxMatchOff: int32(o.windowSize), bufferReset: math.MaxInt32 - int32(o.windowSize*2), lowMem: o.lowMem}} + } + panic("unknown compression level") +} + +// WithEncoderCRC will add CRC value to output. +// Output will be 4 bytes larger. +func WithEncoderCRC(b bool) EOption { + return func(o *encoderOptions) error { o.crc = b; return nil } +} + +// WithEncoderConcurrency will set the concurrency, +// meaning the maximum number of encoders to run concurrently. +// The value supplied must be at least 1. +// For streams, setting a value of 1 will disable async compression. +// By default this will be set to GOMAXPROCS. +func WithEncoderConcurrency(n int) EOption { + return func(o *encoderOptions) error { + if n <= 0 { + return fmt.Errorf("concurrency must be at least 1") + } + o.concurrent = n + return nil + } +} + +// WithWindowSize will set the maximum allowed back-reference distance. +// The value must be a power of two between MinWindowSize and MaxWindowSize. +// A larger value will enable better compression but allocate more memory and, +// for above-default values, take considerably longer. +// The default value is determined by the compression level and max 8MB. +func WithWindowSize(n int) EOption { + return func(o *encoderOptions) error { + switch { + case n < MinWindowSize: + return fmt.Errorf("window size must be at least %d", MinWindowSize) + case n > MaxWindowSize: + return fmt.Errorf("window size must be at most %d", MaxWindowSize) + case (n & (n - 1)) != 0: + return errors.New("window size must be a power of 2") + } + + o.windowSize = n + o.customWindow = true + if o.blockSize > o.windowSize { + o.blockSize = o.windowSize + o.customBlockSize = true + } + return nil + } +} + +// WithEncoderPadding will add padding to all output so the size will be a multiple of n. +// This can be used to obfuscate the exact output size or make blocks of a certain size. +// The contents will be a skippable frame, so it will be invisible by the decoder. +// n must be > 0 and <= 1GB, 1<<30 bytes. +// The padded area will be filled with data from crypto/rand.Reader. +// If `EncodeAll` is used with data already in the destination, the total size will be multiple of this. +func WithEncoderPadding(n int) EOption { + return func(o *encoderOptions) error { + if n <= 0 { + return fmt.Errorf("padding must be at least 1") + } + // No need to waste our time. + if n == 1 { + n = 0 + } + if n > 1<<30 { + return fmt.Errorf("padding must less than 1GB (1<<30 bytes) ") + } + o.pad = n + return nil + } +} + +// EncoderLevel predefines encoder compression levels. +// Only use the constants made available, since the actual mapping +// of these values are very likely to change and your compression could change +// unpredictably when upgrading the library. +type EncoderLevel int + +const ( + speedNotSet EncoderLevel = iota + + // SpeedFastest will choose the fastest reasonable compression. + // This is roughly equivalent to the fastest Zstandard mode. + SpeedFastest + + // SpeedDefault is the default "pretty fast" compression option. + // This is roughly equivalent to the default Zstandard mode (level 3). + SpeedDefault + + // SpeedBetterCompression will yield better compression than the default. + // Currently it is about zstd level 7-8 with ~ 2x-3x the default CPU usage. + // By using this, notice that CPU usage may go up in the future. + SpeedBetterCompression + + // SpeedBestCompression will choose the best available compression option. + // This will offer the best compression no matter the CPU cost. + SpeedBestCompression + + // speedLast should be kept as the last actual compression option. + // The is not for external usage, but is used to keep track of the valid options. + speedLast +) + +// EncoderLevelFromString will convert a string representation of an encoding level back +// to a compression level. The compare is not case sensitive. +// If the string wasn't recognized, (false, SpeedDefault) will be returned. +func EncoderLevelFromString(s string) (bool, EncoderLevel) { + for l := speedNotSet + 1; l < speedLast; l++ { + if strings.EqualFold(s, l.String()) { + return true, l + } + } + return false, SpeedDefault +} + +// EncoderLevelFromZstd will return an encoder level that closest matches the compression +// ratio of a specific zstd compression level. +// Many input values will provide the same compression level. +func EncoderLevelFromZstd(level int) EncoderLevel { + switch { + case level < 3: + return SpeedFastest + case level >= 3 && level < 6: + return SpeedDefault + case level >= 6 && level < 10: + return SpeedBetterCompression + default: + return SpeedBestCompression + } +} + +// String provides a string representation of the compression level. +func (e EncoderLevel) String() string { + switch e { + case SpeedFastest: + return "fastest" + case SpeedDefault: + return "default" + case SpeedBetterCompression: + return "better" + case SpeedBestCompression: + return "best" + default: + return "invalid" + } +} + +// WithEncoderLevel specifies a predefined compression level. +func WithEncoderLevel(l EncoderLevel) EOption { + return func(o *encoderOptions) error { + switch { + case l <= speedNotSet || l >= speedLast: + return fmt.Errorf("unknown encoder level") + } + o.level = l + if !o.customWindow { + switch o.level { + case SpeedFastest: + o.windowSize = 4 << 20 + if !o.customBlockSize { + o.blockSize = 1 << 16 + } + case SpeedDefault: + o.windowSize = 8 << 20 + case SpeedBetterCompression: + o.windowSize = 8 << 20 + case SpeedBestCompression: + o.windowSize = 8 << 20 + } + } + if !o.customALEntropy { + o.allLitEntropy = l > SpeedDefault + } + + return nil + } +} + +// WithZeroFrames will encode 0 length input as full frames. +// This can be needed for compatibility with zstandard usage, +// but is not needed for this package. +func WithZeroFrames(b bool) EOption { + return func(o *encoderOptions) error { + o.fullZero = b + return nil + } +} + +// WithAllLitEntropyCompression will apply entropy compression if no matches are found. +// Disabling this will skip incompressible data faster, but in cases with no matches but +// skewed character distribution compression is lost. +// Default value depends on the compression level selected. +func WithAllLitEntropyCompression(b bool) EOption { + return func(o *encoderOptions) error { + o.customALEntropy = true + o.allLitEntropy = b + return nil + } +} + +// WithNoEntropyCompression will always skip entropy compression of literals. +// This can be useful if content has matches, but unlikely to benefit from entropy +// compression. Usually the slight speed improvement is not worth enabling this. +func WithNoEntropyCompression(b bool) EOption { + return func(o *encoderOptions) error { + o.noEntropy = b + return nil + } +} + +// WithSingleSegment will set the "single segment" flag when EncodeAll is used. +// If this flag is set, data must be regenerated within a single continuous memory segment. +// In this case, Window_Descriptor byte is skipped, but Frame_Content_Size is necessarily present. +// As a consequence, the decoder must allocate a memory segment of size equal or larger than size of your content. +// In order to preserve the decoder from unreasonable memory requirements, +// a decoder is allowed to reject a compressed frame which requests a memory size beyond decoder's authorized range. +// For broader compatibility, decoders are recommended to support memory sizes of at least 8 MB. +// This is only a recommendation, each decoder is free to support higher or lower limits, depending on local limitations. +// If this is not specified, block encodes will automatically choose this based on the input size and the window size. +// This setting has no effect on streamed encodes. +func WithSingleSegment(b bool) EOption { + return func(o *encoderOptions) error { + o.single = &b + return nil + } +} + +// WithLowerEncoderMem will trade in some memory cases trade less memory usage for +// slower encoding speed. +// This will not change the window size which is the primary function for reducing +// memory usage. See WithWindowSize. +func WithLowerEncoderMem(b bool) EOption { + return func(o *encoderOptions) error { + o.lowMem = b + return nil + } +} + +// WithEncoderDict allows to register a dictionary that will be used for the encode. +// +// The slice dict must be in the [dictionary format] produced by +// "zstd --train" from the Zstandard reference implementation. +// +// The encoder *may* choose to use no dictionary instead for certain payloads. +// +// [dictionary format]: https://github.com/facebook/zstd/blob/dev/doc/zstd_compression_format.md#dictionary-format +func WithEncoderDict(dict []byte) EOption { + return func(o *encoderOptions) error { + d, err := loadDict(dict) + if err != nil { + return err + } + o.dict = d + return nil + } +} + +// WithEncoderDictRaw registers a dictionary that may be used by the encoder. +// +// The slice content may contain arbitrary data. It will be used as an initial +// history. +func WithEncoderDictRaw(id uint32, content []byte) EOption { + return func(o *encoderOptions) error { + if bits.UintSize > 32 && uint(len(content)) > dictMaxLength { + return fmt.Errorf("dictionary of size %d > 2GiB too large", len(content)) + } + o.dict = &dict{id: id, content: content, offsets: [3]int{1, 4, 8}} + return nil + } +} diff --git a/vendor/github.com/klauspost/compress/zstd/framedec.go b/vendor/github.com/klauspost/compress/zstd/framedec.go new file mode 100644 index 000000000..53e160f7e --- /dev/null +++ b/vendor/github.com/klauspost/compress/zstd/framedec.go @@ -0,0 +1,413 @@ +// Copyright 2019+ Klaus Post. All rights reserved. +// License information can be found in the LICENSE file. +// Based on work by Yann Collet, released under BSD License. + +package zstd + +import ( + "encoding/binary" + "encoding/hex" + "errors" + "io" + + "github.com/klauspost/compress/zstd/internal/xxhash" +) + +type frameDec struct { + o decoderOptions + crc *xxhash.Digest + + WindowSize uint64 + + // Frame history passed between blocks + history history + + rawInput byteBuffer + + // Byte buffer that can be reused for small input blocks. + bBuf byteBuf + + FrameContentSize uint64 + + DictionaryID uint32 + HasCheckSum bool + SingleSegment bool +} + +const ( + // MinWindowSize is the minimum Window Size, which is 1 KB. + MinWindowSize = 1 << 10 + + // MaxWindowSize is the maximum encoder window size + // and the default decoder maximum window size. + MaxWindowSize = 1 << 29 +) + +const ( + frameMagic = "\x28\xb5\x2f\xfd" + skippableFrameMagic = "\x2a\x4d\x18" +) + +func newFrameDec(o decoderOptions) *frameDec { + if o.maxWindowSize > o.maxDecodedSize { + o.maxWindowSize = o.maxDecodedSize + } + d := frameDec{ + o: o, + } + return &d +} + +// reset will read the frame header and prepare for block decoding. +// If nothing can be read from the input, io.EOF will be returned. +// Any other error indicated that the stream contained data, but +// there was a problem. +func (d *frameDec) reset(br byteBuffer) error { + d.HasCheckSum = false + d.WindowSize = 0 + var signature [4]byte + for { + var err error + // Check if we can read more... + b, err := br.readSmall(1) + switch err { + case io.EOF, io.ErrUnexpectedEOF: + return io.EOF + case nil: + signature[0] = b[0] + default: + return err + } + // Read the rest, don't allow io.ErrUnexpectedEOF + b, err = br.readSmall(3) + switch err { + case io.EOF: + return io.EOF + case nil: + copy(signature[1:], b) + default: + return err + } + + if string(signature[1:4]) != skippableFrameMagic || signature[0]&0xf0 != 0x50 { + if debugDecoder { + println("Not skippable", hex.EncodeToString(signature[:]), hex.EncodeToString([]byte(skippableFrameMagic))) + } + // Break if not skippable frame. + break + } + // Read size to skip + b, err = br.readSmall(4) + if err != nil { + if debugDecoder { + println("Reading Frame Size", err) + } + return err + } + n := uint32(b[0]) | (uint32(b[1]) << 8) | (uint32(b[2]) << 16) | (uint32(b[3]) << 24) + println("Skipping frame with", n, "bytes.") + err = br.skipN(int64(n)) + if err != nil { + if debugDecoder { + println("Reading discarded frame", err) + } + return err + } + } + if string(signature[:]) != frameMagic { + if debugDecoder { + println("Got magic numbers: ", signature, "want:", []byte(frameMagic)) + } + return ErrMagicMismatch + } + + // Read Frame_Header_Descriptor + fhd, err := br.readByte() + if err != nil { + if debugDecoder { + println("Reading Frame_Header_Descriptor", err) + } + return err + } + d.SingleSegment = fhd&(1<<5) != 0 + + if fhd&(1<<3) != 0 { + return errors.New("reserved bit set on frame header") + } + + // Read Window_Descriptor + // https://github.com/facebook/zstd/blob/dev/doc/zstd_compression_format.md#window_descriptor + d.WindowSize = 0 + if !d.SingleSegment { + wd, err := br.readByte() + if err != nil { + if debugDecoder { + println("Reading Window_Descriptor", err) + } + return err + } + printf("raw: %x, mantissa: %d, exponent: %d\n", wd, wd&7, wd>>3) + windowLog := 10 + (wd >> 3) + windowBase := uint64(1) << windowLog + windowAdd := (windowBase / 8) * uint64(wd&0x7) + d.WindowSize = windowBase + windowAdd + } + + // Read Dictionary_ID + // https://github.com/facebook/zstd/blob/dev/doc/zstd_compression_format.md#dictionary_id + d.DictionaryID = 0 + if size := fhd & 3; size != 0 { + if size == 3 { + size = 4 + } + + b, err := br.readSmall(int(size)) + if err != nil { + println("Reading Dictionary_ID", err) + return err + } + var id uint32 + switch len(b) { + case 1: + id = uint32(b[0]) + case 2: + id = uint32(b[0]) | (uint32(b[1]) << 8) + case 4: + id = uint32(b[0]) | (uint32(b[1]) << 8) | (uint32(b[2]) << 16) | (uint32(b[3]) << 24) + } + if debugDecoder { + println("Dict size", size, "ID:", id) + } + d.DictionaryID = id + } + + // Read Frame_Content_Size + // https://github.com/facebook/zstd/blob/dev/doc/zstd_compression_format.md#frame_content_size + var fcsSize int + v := fhd >> 6 + switch v { + case 0: + if d.SingleSegment { + fcsSize = 1 + } + default: + fcsSize = 1 << v + } + d.FrameContentSize = fcsUnknown + if fcsSize > 0 { + b, err := br.readSmall(fcsSize) + if err != nil { + println("Reading Frame content", err) + return err + } + switch len(b) { + case 1: + d.FrameContentSize = uint64(b[0]) + case 2: + // When FCS_Field_Size is 2, the offset of 256 is added. + d.FrameContentSize = uint64(b[0]) | (uint64(b[1]) << 8) + 256 + case 4: + d.FrameContentSize = uint64(b[0]) | (uint64(b[1]) << 8) | (uint64(b[2]) << 16) | (uint64(b[3]) << 24) + case 8: + d1 := uint32(b[0]) | (uint32(b[1]) << 8) | (uint32(b[2]) << 16) | (uint32(b[3]) << 24) + d2 := uint32(b[4]) | (uint32(b[5]) << 8) | (uint32(b[6]) << 16) | (uint32(b[7]) << 24) + d.FrameContentSize = uint64(d1) | (uint64(d2) << 32) + } + if debugDecoder { + println("Read FCS:", d.FrameContentSize) + } + } + + // Move this to shared. + d.HasCheckSum = fhd&(1<<2) != 0 + if d.HasCheckSum { + if d.crc == nil { + d.crc = xxhash.New() + } + d.crc.Reset() + } + + if d.WindowSize > d.o.maxWindowSize { + if debugDecoder { + printf("window size %d > max %d\n", d.WindowSize, d.o.maxWindowSize) + } + return ErrWindowSizeExceeded + } + + if d.WindowSize == 0 && d.SingleSegment { + // We may not need window in this case. + d.WindowSize = d.FrameContentSize + if d.WindowSize < MinWindowSize { + d.WindowSize = MinWindowSize + } + if d.WindowSize > d.o.maxDecodedSize { + if debugDecoder { + printf("window size %d > max %d\n", d.WindowSize, d.o.maxWindowSize) + } + return ErrDecoderSizeExceeded + } + } + + // The minimum Window_Size is 1 KB. + if d.WindowSize < MinWindowSize { + if debugDecoder { + println("got window size: ", d.WindowSize) + } + return ErrWindowSizeTooSmall + } + d.history.windowSize = int(d.WindowSize) + if !d.o.lowMem || d.history.windowSize < maxBlockSize { + // Alloc 2x window size if not low-mem, or window size below 2MB. + d.history.allocFrameBuffer = d.history.windowSize * 2 + } else { + if d.o.lowMem { + // Alloc with 1MB extra. + d.history.allocFrameBuffer = d.history.windowSize + maxBlockSize/2 + } else { + // Alloc with 2MB extra. + d.history.allocFrameBuffer = d.history.windowSize + maxBlockSize + } + } + + if debugDecoder { + println("Frame: Dict:", d.DictionaryID, "FrameContentSize:", d.FrameContentSize, "singleseg:", d.SingleSegment, "window:", d.WindowSize, "crc:", d.HasCheckSum) + } + + // history contains input - maybe we do something + d.rawInput = br + return nil +} + +// next will start decoding the next block from stream. +func (d *frameDec) next(block *blockDec) error { + if debugDecoder { + println("decoding new block") + } + err := block.reset(d.rawInput, d.WindowSize) + if err != nil { + println("block error:", err) + // Signal the frame decoder we have a problem. + block.sendErr(err) + return err + } + return nil +} + +// checkCRC will check the checksum, assuming the frame has one. +// Will return ErrCRCMismatch if crc check failed, otherwise nil. +func (d *frameDec) checkCRC() error { + // We can overwrite upper tmp now + buf, err := d.rawInput.readSmall(4) + if err != nil { + println("CRC missing?", err) + return err + } + + want := binary.LittleEndian.Uint32(buf[:4]) + got := uint32(d.crc.Sum64()) + + if got != want { + if debugDecoder { + printf("CRC check failed: got %08x, want %08x\n", got, want) + } + return ErrCRCMismatch + } + if debugDecoder { + printf("CRC ok %08x\n", got) + } + return nil +} + +// consumeCRC skips over the checksum, assuming the frame has one. +func (d *frameDec) consumeCRC() error { + _, err := d.rawInput.readSmall(4) + if err != nil { + println("CRC missing?", err) + } + return err +} + +// runDecoder will run the decoder for the remainder of the frame. +func (d *frameDec) runDecoder(dst []byte, dec *blockDec) ([]byte, error) { + saved := d.history.b + + // We use the history for output to avoid copying it. + d.history.b = dst + d.history.ignoreBuffer = len(dst) + // Store input length, so we only check new data. + crcStart := len(dst) + d.history.decoders.maxSyncLen = 0 + if d.o.limitToCap { + d.history.decoders.maxSyncLen = uint64(cap(dst) - len(dst)) + } + if d.FrameContentSize != fcsUnknown { + if !d.o.limitToCap || d.FrameContentSize+uint64(len(dst)) < d.history.decoders.maxSyncLen { + d.history.decoders.maxSyncLen = d.FrameContentSize + uint64(len(dst)) + } + if d.history.decoders.maxSyncLen > d.o.maxDecodedSize { + if debugDecoder { + println("maxSyncLen:", d.history.decoders.maxSyncLen, "> maxDecodedSize:", d.o.maxDecodedSize) + } + return dst, ErrDecoderSizeExceeded + } + if debugDecoder { + println("maxSyncLen:", d.history.decoders.maxSyncLen) + } + if !d.o.limitToCap && uint64(cap(dst)) < d.history.decoders.maxSyncLen { + // Alloc for output + dst2 := make([]byte, len(dst), d.history.decoders.maxSyncLen+compressedBlockOverAlloc) + copy(dst2, dst) + dst = dst2 + } + } + var err error + for { + err = dec.reset(d.rawInput, d.WindowSize) + if err != nil { + break + } + if debugDecoder { + println("next block:", dec) + } + err = dec.decodeBuf(&d.history) + if err != nil { + break + } + if uint64(len(d.history.b)-crcStart) > d.o.maxDecodedSize { + println("runDecoder: maxDecodedSize exceeded", uint64(len(d.history.b)-crcStart), ">", d.o.maxDecodedSize) + err = ErrDecoderSizeExceeded + break + } + if d.o.limitToCap && len(d.history.b) > cap(dst) { + println("runDecoder: cap exceeded", uint64(len(d.history.b)), ">", cap(dst)) + err = ErrDecoderSizeExceeded + break + } + if uint64(len(d.history.b)-crcStart) > d.FrameContentSize { + println("runDecoder: FrameContentSize exceeded", uint64(len(d.history.b)-crcStart), ">", d.FrameContentSize) + err = ErrFrameSizeExceeded + break + } + if dec.Last { + break + } + if debugDecoder { + println("runDecoder: FrameContentSize", uint64(len(d.history.b)-crcStart), "<=", d.FrameContentSize) + } + } + dst = d.history.b + if err == nil { + if d.FrameContentSize != fcsUnknown && uint64(len(d.history.b)-crcStart) != d.FrameContentSize { + err = ErrFrameSizeMismatch + } else if d.HasCheckSum { + if d.o.ignoreChecksum { + err = d.consumeCRC() + } else { + d.crc.Write(dst[crcStart:]) + err = d.checkCRC() + } + } + } + d.history.b = saved + return dst, err +} diff --git a/vendor/github.com/klauspost/compress/zstd/frameenc.go b/vendor/github.com/klauspost/compress/zstd/frameenc.go new file mode 100644 index 000000000..667ca0679 --- /dev/null +++ b/vendor/github.com/klauspost/compress/zstd/frameenc.go @@ -0,0 +1,137 @@ +// Copyright 2019+ Klaus Post. All rights reserved. +// License information can be found in the LICENSE file. +// Based on work by Yann Collet, released under BSD License. + +package zstd + +import ( + "encoding/binary" + "fmt" + "io" + "math" + "math/bits" +) + +type frameHeader struct { + ContentSize uint64 + WindowSize uint32 + SingleSegment bool + Checksum bool + DictID uint32 +} + +const maxHeaderSize = 14 + +func (f frameHeader) appendTo(dst []byte) []byte { + dst = append(dst, frameMagic...) + var fhd uint8 + if f.Checksum { + fhd |= 1 << 2 + } + if f.SingleSegment { + fhd |= 1 << 5 + } + + var dictIDContent []byte + if f.DictID > 0 { + var tmp [4]byte + if f.DictID < 256 { + fhd |= 1 + tmp[0] = uint8(f.DictID) + dictIDContent = tmp[:1] + } else if f.DictID < 1<<16 { + fhd |= 2 + binary.LittleEndian.PutUint16(tmp[:2], uint16(f.DictID)) + dictIDContent = tmp[:2] + } else { + fhd |= 3 + binary.LittleEndian.PutUint32(tmp[:4], f.DictID) + dictIDContent = tmp[:4] + } + } + var fcs uint8 + if f.ContentSize >= 256 { + fcs++ + } + if f.ContentSize >= 65536+256 { + fcs++ + } + if f.ContentSize >= 0xffffffff { + fcs++ + } + + fhd |= fcs << 6 + + dst = append(dst, fhd) + if !f.SingleSegment { + const winLogMin = 10 + windowLog := (bits.Len32(f.WindowSize-1) - winLogMin) << 3 + dst = append(dst, uint8(windowLog)) + } + if f.DictID > 0 { + dst = append(dst, dictIDContent...) + } + switch fcs { + case 0: + if f.SingleSegment { + dst = append(dst, uint8(f.ContentSize)) + } + // Unless SingleSegment is set, framessizes < 256 are not stored. + case 1: + f.ContentSize -= 256 + dst = append(dst, uint8(f.ContentSize), uint8(f.ContentSize>>8)) + case 2: + dst = append(dst, uint8(f.ContentSize), uint8(f.ContentSize>>8), uint8(f.ContentSize>>16), uint8(f.ContentSize>>24)) + case 3: + dst = append(dst, uint8(f.ContentSize), uint8(f.ContentSize>>8), uint8(f.ContentSize>>16), uint8(f.ContentSize>>24), + uint8(f.ContentSize>>32), uint8(f.ContentSize>>40), uint8(f.ContentSize>>48), uint8(f.ContentSize>>56)) + default: + panic("invalid fcs") + } + return dst +} + +const skippableFrameHeader = 4 + 4 + +// calcSkippableFrame will return a total size to be added for written +// to be divisible by multiple. +// The value will always be > skippableFrameHeader. +// The function will panic if written < 0 or wantMultiple <= 0. +func calcSkippableFrame(written, wantMultiple int64) int { + if wantMultiple <= 0 { + panic("wantMultiple <= 0") + } + if written < 0 { + panic("written < 0") + } + leftOver := written % wantMultiple + if leftOver == 0 { + return 0 + } + toAdd := wantMultiple - leftOver + for toAdd < skippableFrameHeader { + toAdd += wantMultiple + } + return int(toAdd) +} + +// skippableFrame will add a skippable frame with a total size of bytes. +// total should be >= skippableFrameHeader and < math.MaxUint32. +func skippableFrame(dst []byte, total int, r io.Reader) ([]byte, error) { + if total == 0 { + return dst, nil + } + if total < skippableFrameHeader { + return dst, fmt.Errorf("requested skippable frame (%d) < 8", total) + } + if int64(total) > math.MaxUint32 { + return dst, fmt.Errorf("requested skippable frame (%d) > max uint32", total) + } + dst = append(dst, 0x50, 0x2a, 0x4d, 0x18) + f := uint32(total - skippableFrameHeader) + dst = append(dst, uint8(f), uint8(f>>8), uint8(f>>16), uint8(f>>24)) + start := len(dst) + dst = append(dst, make([]byte, f)...) + _, err := io.ReadFull(r, dst[start:]) + return dst, err +} diff --git a/vendor/github.com/klauspost/compress/zstd/fse_decoder.go b/vendor/github.com/klauspost/compress/zstd/fse_decoder.go new file mode 100644 index 000000000..2f8860a72 --- /dev/null +++ b/vendor/github.com/klauspost/compress/zstd/fse_decoder.go @@ -0,0 +1,307 @@ +// Copyright 2019+ Klaus Post. All rights reserved. +// License information can be found in the LICENSE file. +// Based on work by Yann Collet, released under BSD License. + +package zstd + +import ( + "encoding/binary" + "errors" + "fmt" + "io" +) + +const ( + tablelogAbsoluteMax = 9 +) + +const ( + /*!MEMORY_USAGE : + * Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.) + * Increasing memory usage improves compression ratio + * Reduced memory usage can improve speed, due to cache effect + * Recommended max value is 14, for 16KB, which nicely fits into Intel x86 L1 cache */ + maxMemoryUsage = tablelogAbsoluteMax + 2 + + maxTableLog = maxMemoryUsage - 2 + maxTablesize = 1 << maxTableLog + maxTableMask = (1 << maxTableLog) - 1 + minTablelog = 5 + maxSymbolValue = 255 +) + +// fseDecoder provides temporary storage for compression and decompression. +type fseDecoder struct { + dt [maxTablesize]decSymbol // Decompression table. + symbolLen uint16 // Length of active part of the symbol table. + actualTableLog uint8 // Selected tablelog. + maxBits uint8 // Maximum number of additional bits + + // used for table creation to avoid allocations. + stateTable [256]uint16 + norm [maxSymbolValue + 1]int16 + preDefined bool +} + +// tableStep returns the next table index. +func tableStep(tableSize uint32) uint32 { + return (tableSize >> 1) + (tableSize >> 3) + 3 +} + +// readNCount will read the symbol distribution so decoding tables can be constructed. +func (s *fseDecoder) readNCount(b *byteReader, maxSymbol uint16) error { + var ( + charnum uint16 + previous0 bool + ) + if b.remain() < 4 { + return errors.New("input too small") + } + bitStream := b.Uint32NC() + nbBits := uint((bitStream & 0xF) + minTablelog) // extract tableLog + if nbBits > tablelogAbsoluteMax { + println("Invalid tablelog:", nbBits) + return errors.New("tableLog too large") + } + bitStream >>= 4 + bitCount := uint(4) + + s.actualTableLog = uint8(nbBits) + remaining := int32((1 << nbBits) + 1) + threshold := int32(1 << nbBits) + gotTotal := int32(0) + nbBits++ + + for remaining > 1 && charnum <= maxSymbol { + if previous0 { + //println("prev0") + n0 := charnum + for (bitStream & 0xFFFF) == 0xFFFF { + //println("24 x 0") + n0 += 24 + if r := b.remain(); r > 5 { + b.advance(2) + // The check above should make sure we can read 32 bits + bitStream = b.Uint32NC() >> bitCount + } else { + // end of bit stream + bitStream >>= 16 + bitCount += 16 + } + } + //printf("bitstream: %d, 0b%b", bitStream&3, bitStream) + for (bitStream & 3) == 3 { + n0 += 3 + bitStream >>= 2 + bitCount += 2 + } + n0 += uint16(bitStream & 3) + bitCount += 2 + + if n0 > maxSymbolValue { + return errors.New("maxSymbolValue too small") + } + //println("inserting ", n0-charnum, "zeroes from idx", charnum, "ending before", n0) + for charnum < n0 { + s.norm[uint8(charnum)] = 0 + charnum++ + } + + if r := b.remain(); r >= 7 || r-int(bitCount>>3) >= 4 { + b.advance(bitCount >> 3) + bitCount &= 7 + // The check above should make sure we can read 32 bits + bitStream = b.Uint32NC() >> bitCount + } else { + bitStream >>= 2 + } + } + + max := (2*threshold - 1) - remaining + var count int32 + + if int32(bitStream)&(threshold-1) < max { + count = int32(bitStream) & (threshold - 1) + if debugAsserts && nbBits < 1 { + panic("nbBits underflow") + } + bitCount += nbBits - 1 + } else { + count = int32(bitStream) & (2*threshold - 1) + if count >= threshold { + count -= max + } + bitCount += nbBits + } + + // extra accuracy + count-- + if count < 0 { + // -1 means +1 + remaining += count + gotTotal -= count + } else { + remaining -= count + gotTotal += count + } + s.norm[charnum&0xff] = int16(count) + charnum++ + previous0 = count == 0 + for remaining < threshold { + nbBits-- + threshold >>= 1 + } + + if r := b.remain(); r >= 7 || r-int(bitCount>>3) >= 4 { + b.advance(bitCount >> 3) + bitCount &= 7 + // The check above should make sure we can read 32 bits + bitStream = b.Uint32NC() >> (bitCount & 31) + } else { + bitCount -= (uint)(8 * (len(b.b) - 4 - b.off)) + b.off = len(b.b) - 4 + bitStream = b.Uint32() >> (bitCount & 31) + } + } + s.symbolLen = charnum + if s.symbolLen <= 1 { + return fmt.Errorf("symbolLen (%d) too small", s.symbolLen) + } + if s.symbolLen > maxSymbolValue+1 { + return fmt.Errorf("symbolLen (%d) too big", s.symbolLen) + } + if remaining != 1 { + return fmt.Errorf("corruption detected (remaining %d != 1)", remaining) + } + if bitCount > 32 { + return fmt.Errorf("corruption detected (bitCount %d > 32)", bitCount) + } + if gotTotal != 1<> 3) + return s.buildDtable() +} + +func (s *fseDecoder) mustReadFrom(r io.Reader) { + fatalErr := func(err error) { + if err != nil { + panic(err) + } + } + // dt [maxTablesize]decSymbol // Decompression table. + // symbolLen uint16 // Length of active part of the symbol table. + // actualTableLog uint8 // Selected tablelog. + // maxBits uint8 // Maximum number of additional bits + // // used for table creation to avoid allocations. + // stateTable [256]uint16 + // norm [maxSymbolValue + 1]int16 + // preDefined bool + fatalErr(binary.Read(r, binary.LittleEndian, &s.dt)) + fatalErr(binary.Read(r, binary.LittleEndian, &s.symbolLen)) + fatalErr(binary.Read(r, binary.LittleEndian, &s.actualTableLog)) + fatalErr(binary.Read(r, binary.LittleEndian, &s.maxBits)) + fatalErr(binary.Read(r, binary.LittleEndian, &s.stateTable)) + fatalErr(binary.Read(r, binary.LittleEndian, &s.norm)) + fatalErr(binary.Read(r, binary.LittleEndian, &s.preDefined)) +} + +// decSymbol contains information about a state entry, +// Including the state offset base, the output symbol and +// the number of bits to read for the low part of the destination state. +// Using a composite uint64 is faster than a struct with separate members. +type decSymbol uint64 + +func newDecSymbol(nbits, addBits uint8, newState uint16, baseline uint32) decSymbol { + return decSymbol(nbits) | (decSymbol(addBits) << 8) | (decSymbol(newState) << 16) | (decSymbol(baseline) << 32) +} + +func (d decSymbol) nbBits() uint8 { + return uint8(d) +} + +func (d decSymbol) addBits() uint8 { + return uint8(d >> 8) +} + +func (d decSymbol) newState() uint16 { + return uint16(d >> 16) +} + +func (d decSymbol) baselineInt() int { + return int(d >> 32) +} + +func (d *decSymbol) setNBits(nBits uint8) { + const mask = 0xffffffffffffff00 + *d = (*d & mask) | decSymbol(nBits) +} + +func (d *decSymbol) setAddBits(addBits uint8) { + const mask = 0xffffffffffff00ff + *d = (*d & mask) | (decSymbol(addBits) << 8) +} + +func (d *decSymbol) setNewState(state uint16) { + const mask = 0xffffffff0000ffff + *d = (*d & mask) | decSymbol(state)<<16 +} + +func (d *decSymbol) setExt(addBits uint8, baseline uint32) { + const mask = 0xffff00ff + *d = (*d & mask) | (decSymbol(addBits) << 8) | (decSymbol(baseline) << 32) +} + +// decSymbolValue returns the transformed decSymbol for the given symbol. +func decSymbolValue(symb uint8, t []baseOffset) (decSymbol, error) { + if int(symb) >= len(t) { + return 0, fmt.Errorf("rle symbol %d >= max %d", symb, len(t)) + } + lu := t[symb] + return newDecSymbol(0, lu.addBits, 0, lu.baseLine), nil +} + +// setRLE will set the decoder til RLE mode. +func (s *fseDecoder) setRLE(symbol decSymbol) { + s.actualTableLog = 0 + s.maxBits = symbol.addBits() + s.dt[0] = symbol +} + +// transform will transform the decoder table into a table usable for +// decoding without having to apply the transformation while decoding. +// The state will contain the base value and the number of bits to read. +func (s *fseDecoder) transform(t []baseOffset) error { + tableSize := uint16(1 << s.actualTableLog) + s.maxBits = 0 + for i, v := range s.dt[:tableSize] { + add := v.addBits() + if int(add) >= len(t) { + return fmt.Errorf("invalid decoding table entry %d, symbol %d >= max (%d)", i, v.addBits(), len(t)) + } + lu := t[add] + if lu.addBits > s.maxBits { + s.maxBits = lu.addBits + } + v.setExt(lu.addBits, lu.baseLine) + s.dt[i] = v + } + return nil +} + +type fseState struct { + dt []decSymbol + state decSymbol +} + +// Initialize and decodeAsync first state and symbol. +func (s *fseState) init(br *bitReader, tableLog uint8, dt []decSymbol) { + s.dt = dt + br.fill() + s.state = dt[br.getBits(tableLog)] +} + +// final returns the current state symbol without decoding the next. +func (s decSymbol) final() (int, uint8) { + return s.baselineInt(), s.addBits() +} diff --git a/vendor/github.com/klauspost/compress/zstd/fse_decoder_amd64.go b/vendor/github.com/klauspost/compress/zstd/fse_decoder_amd64.go new file mode 100644 index 000000000..d04a829b0 --- /dev/null +++ b/vendor/github.com/klauspost/compress/zstd/fse_decoder_amd64.go @@ -0,0 +1,65 @@ +//go:build amd64 && !appengine && !noasm && gc +// +build amd64,!appengine,!noasm,gc + +package zstd + +import ( + "fmt" +) + +type buildDtableAsmContext struct { + // inputs + stateTable *uint16 + norm *int16 + dt *uint64 + + // outputs --- set by the procedure in the case of error; + // for interpretation please see the error handling part below + errParam1 uint64 + errParam2 uint64 +} + +// buildDtable_asm is an x86 assembly implementation of fseDecoder.buildDtable. +// Function returns non-zero exit code on error. +// +//go:noescape +func buildDtable_asm(s *fseDecoder, ctx *buildDtableAsmContext) int + +// please keep in sync with _generate/gen_fse.go +const ( + errorCorruptedNormalizedCounter = 1 + errorNewStateTooBig = 2 + errorNewStateNoBits = 3 +) + +// buildDtable will build the decoding table. +func (s *fseDecoder) buildDtable() error { + ctx := buildDtableAsmContext{ + stateTable: &s.stateTable[0], + norm: &s.norm[0], + dt: (*uint64)(&s.dt[0]), + } + code := buildDtable_asm(s, &ctx) + + if code != 0 { + switch code { + case errorCorruptedNormalizedCounter: + position := ctx.errParam1 + return fmt.Errorf("corrupted input (position=%d, expected 0)", position) + + case errorNewStateTooBig: + newState := decSymbol(ctx.errParam1) + size := ctx.errParam2 + return fmt.Errorf("newState (%d) outside table size (%d)", newState, size) + + case errorNewStateNoBits: + newState := decSymbol(ctx.errParam1) + oldState := decSymbol(ctx.errParam2) + return fmt.Errorf("newState (%d) == oldState (%d) and no bits", newState, oldState) + + default: + return fmt.Errorf("buildDtable_asm returned unhandled nonzero code = %d", code) + } + } + return nil +} diff --git a/vendor/github.com/klauspost/compress/zstd/fse_decoder_amd64.s b/vendor/github.com/klauspost/compress/zstd/fse_decoder_amd64.s new file mode 100644 index 000000000..bcde39869 --- /dev/null +++ b/vendor/github.com/klauspost/compress/zstd/fse_decoder_amd64.s @@ -0,0 +1,126 @@ +// Code generated by command: go run gen_fse.go -out ../fse_decoder_amd64.s -pkg=zstd. DO NOT EDIT. + +//go:build !appengine && !noasm && gc && !noasm + +// func buildDtable_asm(s *fseDecoder, ctx *buildDtableAsmContext) int +TEXT ·buildDtable_asm(SB), $0-24 + MOVQ ctx+8(FP), CX + MOVQ s+0(FP), DI + + // Load values + MOVBQZX 4098(DI), DX + XORQ AX, AX + BTSQ DX, AX + MOVQ (CX), BX + MOVQ 16(CX), SI + LEAQ -1(AX), R8 + MOVQ 8(CX), CX + MOVWQZX 4096(DI), DI + + // End load values + // Init, lay down lowprob symbols + XORQ R9, R9 + JMP init_main_loop_condition + +init_main_loop: + MOVWQSX (CX)(R9*2), R10 + CMPW R10, $-1 + JNE do_not_update_high_threshold + MOVB R9, 1(SI)(R8*8) + DECQ R8 + MOVQ $0x0000000000000001, R10 + +do_not_update_high_threshold: + MOVW R10, (BX)(R9*2) + INCQ R9 + +init_main_loop_condition: + CMPQ R9, DI + JL init_main_loop + + // Spread symbols + // Calculate table step + MOVQ AX, R9 + SHRQ $0x01, R9 + MOVQ AX, R10 + SHRQ $0x03, R10 + LEAQ 3(R9)(R10*1), R9 + + // Fill add bits values + LEAQ -1(AX), R10 + XORQ R11, R11 + XORQ R12, R12 + JMP spread_main_loop_condition + +spread_main_loop: + XORQ R13, R13 + MOVWQSX (CX)(R12*2), R14 + JMP spread_inner_loop_condition + +spread_inner_loop: + MOVB R12, 1(SI)(R11*8) + +adjust_position: + ADDQ R9, R11 + ANDQ R10, R11 + CMPQ R11, R8 + JG adjust_position + INCQ R13 + +spread_inner_loop_condition: + CMPQ R13, R14 + JL spread_inner_loop + INCQ R12 + +spread_main_loop_condition: + CMPQ R12, DI + JL spread_main_loop + TESTQ R11, R11 + JZ spread_check_ok + MOVQ ctx+8(FP), AX + MOVQ R11, 24(AX) + MOVQ $+1, ret+16(FP) + RET + +spread_check_ok: + // Build Decoding table + XORQ DI, DI + +build_table_main_table: + MOVBQZX 1(SI)(DI*8), CX + MOVWQZX (BX)(CX*2), R8 + LEAQ 1(R8), R9 + MOVW R9, (BX)(CX*2) + MOVQ R8, R9 + BSRQ R9, R9 + MOVQ DX, CX + SUBQ R9, CX + SHLQ CL, R8 + SUBQ AX, R8 + MOVB CL, (SI)(DI*8) + MOVW R8, 2(SI)(DI*8) + CMPQ R8, AX + JLE build_table_check1_ok + MOVQ ctx+8(FP), CX + MOVQ R8, 24(CX) + MOVQ AX, 32(CX) + MOVQ $+2, ret+16(FP) + RET + +build_table_check1_ok: + TESTB CL, CL + JNZ build_table_check2_ok + CMPW R8, DI + JNE build_table_check2_ok + MOVQ ctx+8(FP), AX + MOVQ R8, 24(AX) + MOVQ DI, 32(AX) + MOVQ $+3, ret+16(FP) + RET + +build_table_check2_ok: + INCQ DI + CMPQ DI, AX + JL build_table_main_table + MOVQ $+0, ret+16(FP) + RET diff --git a/vendor/github.com/klauspost/compress/zstd/fse_decoder_generic.go b/vendor/github.com/klauspost/compress/zstd/fse_decoder_generic.go new file mode 100644 index 000000000..8adfebb02 --- /dev/null +++ b/vendor/github.com/klauspost/compress/zstd/fse_decoder_generic.go @@ -0,0 +1,73 @@ +//go:build !amd64 || appengine || !gc || noasm +// +build !amd64 appengine !gc noasm + +package zstd + +import ( + "errors" + "fmt" +) + +// buildDtable will build the decoding table. +func (s *fseDecoder) buildDtable() error { + tableSize := uint32(1 << s.actualTableLog) + highThreshold := tableSize - 1 + symbolNext := s.stateTable[:256] + + // Init, lay down lowprob symbols + { + for i, v := range s.norm[:s.symbolLen] { + if v == -1 { + s.dt[highThreshold].setAddBits(uint8(i)) + highThreshold-- + v = 1 + } + symbolNext[i] = uint16(v) + } + } + + // Spread symbols + { + tableMask := tableSize - 1 + step := tableStep(tableSize) + position := uint32(0) + for ss, v := range s.norm[:s.symbolLen] { + for i := 0; i < int(v); i++ { + s.dt[position].setAddBits(uint8(ss)) + for { + // lowprob area + position = (position + step) & tableMask + if position <= highThreshold { + break + } + } + } + } + if position != 0 { + // position must reach all cells once, otherwise normalizedCounter is incorrect + return errors.New("corrupted input (position != 0)") + } + } + + // Build Decoding table + { + tableSize := uint16(1 << s.actualTableLog) + for u, v := range s.dt[:tableSize] { + symbol := v.addBits() + nextState := symbolNext[symbol] + symbolNext[symbol] = nextState + 1 + nBits := s.actualTableLog - byte(highBits(uint32(nextState))) + s.dt[u&maxTableMask].setNBits(nBits) + newState := (nextState << nBits) - tableSize + if newState > tableSize { + return fmt.Errorf("newState (%d) outside table size (%d)", newState, tableSize) + } + if newState == uint16(u) && nBits == 0 { + // Seems weird that this is possible with nbits > 0. + return fmt.Errorf("newState (%d) == oldState (%d) and no bits", newState, u) + } + s.dt[u&maxTableMask].setNewState(newState) + } + } + return nil +} diff --git a/vendor/github.com/klauspost/compress/zstd/fse_encoder.go b/vendor/github.com/klauspost/compress/zstd/fse_encoder.go new file mode 100644 index 000000000..ab26326a8 --- /dev/null +++ b/vendor/github.com/klauspost/compress/zstd/fse_encoder.go @@ -0,0 +1,701 @@ +// Copyright 2019+ Klaus Post. All rights reserved. +// License information can be found in the LICENSE file. +// Based on work by Yann Collet, released under BSD License. + +package zstd + +import ( + "errors" + "fmt" + "math" +) + +const ( + // For encoding we only support up to + maxEncTableLog = 8 + maxEncTablesize = 1 << maxTableLog + maxEncTableMask = (1 << maxTableLog) - 1 + minEncTablelog = 5 + maxEncSymbolValue = maxMatchLengthSymbol +) + +// Scratch provides temporary storage for compression and decompression. +type fseEncoder struct { + symbolLen uint16 // Length of active part of the symbol table. + actualTableLog uint8 // Selected tablelog. + ct cTable // Compression tables. + maxCount int // count of the most probable symbol + zeroBits bool // no bits has prob > 50%. + clearCount bool // clear count + useRLE bool // This encoder is for RLE + preDefined bool // This encoder is predefined. + reUsed bool // Set to know when the encoder has been reused. + rleVal uint8 // RLE Symbol + maxBits uint8 // Maximum output bits after transform. + + // TODO: Technically zstd should be fine with 64 bytes. + count [256]uint32 + norm [256]int16 +} + +// cTable contains tables used for compression. +type cTable struct { + tableSymbol []byte + stateTable []uint16 + symbolTT []symbolTransform +} + +// symbolTransform contains the state transform for a symbol. +type symbolTransform struct { + deltaNbBits uint32 + deltaFindState int16 + outBits uint8 +} + +// String prints values as a human readable string. +func (s symbolTransform) String() string { + return fmt.Sprintf("{deltabits: %08x, findstate:%d outbits:%d}", s.deltaNbBits, s.deltaFindState, s.outBits) +} + +// Histogram allows to populate the histogram and skip that step in the compression, +// It otherwise allows to inspect the histogram when compression is done. +// To indicate that you have populated the histogram call HistogramFinished +// with the value of the highest populated symbol, as well as the number of entries +// in the most populated entry. These are accepted at face value. +func (s *fseEncoder) Histogram() *[256]uint32 { + return &s.count +} + +// HistogramFinished can be called to indicate that the histogram has been populated. +// maxSymbol is the index of the highest set symbol of the next data segment. +// maxCount is the number of entries in the most populated entry. +// These are accepted at face value. +func (s *fseEncoder) HistogramFinished(maxSymbol uint8, maxCount int) { + s.maxCount = maxCount + s.symbolLen = uint16(maxSymbol) + 1 + s.clearCount = maxCount != 0 +} + +// allocCtable will allocate tables needed for compression. +// If existing tables a re big enough, they are simply re-used. +func (s *fseEncoder) allocCtable() { + tableSize := 1 << s.actualTableLog + // get tableSymbol that is big enough. + if cap(s.ct.tableSymbol) < tableSize { + s.ct.tableSymbol = make([]byte, tableSize) + } + s.ct.tableSymbol = s.ct.tableSymbol[:tableSize] + + ctSize := tableSize + if cap(s.ct.stateTable) < ctSize { + s.ct.stateTable = make([]uint16, ctSize) + } + s.ct.stateTable = s.ct.stateTable[:ctSize] + + if cap(s.ct.symbolTT) < 256 { + s.ct.symbolTT = make([]symbolTransform, 256) + } + s.ct.symbolTT = s.ct.symbolTT[:256] +} + +// buildCTable will populate the compression table so it is ready to be used. +func (s *fseEncoder) buildCTable() error { + tableSize := uint32(1 << s.actualTableLog) + highThreshold := tableSize - 1 + var cumul [256]int16 + + s.allocCtable() + tableSymbol := s.ct.tableSymbol[:tableSize] + // symbol start positions + { + cumul[0] = 0 + for ui, v := range s.norm[:s.symbolLen-1] { + u := byte(ui) // one less than reference + if v == -1 { + // Low proba symbol + cumul[u+1] = cumul[u] + 1 + tableSymbol[highThreshold] = u + highThreshold-- + } else { + cumul[u+1] = cumul[u] + v + } + } + // Encode last symbol separately to avoid overflowing u + u := int(s.symbolLen - 1) + v := s.norm[s.symbolLen-1] + if v == -1 { + // Low proba symbol + cumul[u+1] = cumul[u] + 1 + tableSymbol[highThreshold] = byte(u) + highThreshold-- + } else { + cumul[u+1] = cumul[u] + v + } + if uint32(cumul[s.symbolLen]) != tableSize { + return fmt.Errorf("internal error: expected cumul[s.symbolLen] (%d) == tableSize (%d)", cumul[s.symbolLen], tableSize) + } + cumul[s.symbolLen] = int16(tableSize) + 1 + } + // Spread symbols + s.zeroBits = false + { + step := tableStep(tableSize) + tableMask := tableSize - 1 + var position uint32 + // if any symbol > largeLimit, we may have 0 bits output. + largeLimit := int16(1 << (s.actualTableLog - 1)) + for ui, v := range s.norm[:s.symbolLen] { + symbol := byte(ui) + if v > largeLimit { + s.zeroBits = true + } + for nbOccurrences := int16(0); nbOccurrences < v; nbOccurrences++ { + tableSymbol[position] = symbol + position = (position + step) & tableMask + for position > highThreshold { + position = (position + step) & tableMask + } /* Low proba area */ + } + } + + // Check if we have gone through all positions + if position != 0 { + return errors.New("position!=0") + } + } + + // Build table + table := s.ct.stateTable + { + tsi := int(tableSize) + for u, v := range tableSymbol { + // TableU16 : sorted by symbol order; gives next state value + table[cumul[v]] = uint16(tsi + u) + cumul[v]++ + } + } + + // Build Symbol Transformation Table + { + total := int16(0) + symbolTT := s.ct.symbolTT[:s.symbolLen] + tableLog := s.actualTableLog + tl := (uint32(tableLog) << 16) - (1 << tableLog) + for i, v := range s.norm[:s.symbolLen] { + switch v { + case 0: + case -1, 1: + symbolTT[i].deltaNbBits = tl + symbolTT[i].deltaFindState = total - 1 + total++ + default: + maxBitsOut := uint32(tableLog) - highBit(uint32(v-1)) + minStatePlus := uint32(v) << maxBitsOut + symbolTT[i].deltaNbBits = (maxBitsOut << 16) - minStatePlus + symbolTT[i].deltaFindState = total - v + total += v + } + } + if total != int16(tableSize) { + return fmt.Errorf("total mismatch %d (got) != %d (want)", total, tableSize) + } + } + return nil +} + +var rtbTable = [...]uint32{0, 473195, 504333, 520860, 550000, 700000, 750000, 830000} + +func (s *fseEncoder) setRLE(val byte) { + s.allocCtable() + s.actualTableLog = 0 + s.ct.stateTable = s.ct.stateTable[:1] + s.ct.symbolTT[val] = symbolTransform{ + deltaFindState: 0, + deltaNbBits: 0, + } + if debugEncoder { + println("setRLE: val", val, "symbolTT", s.ct.symbolTT[val]) + } + s.rleVal = val + s.useRLE = true +} + +// setBits will set output bits for the transform. +// if nil is provided, the number of bits is equal to the index. +func (s *fseEncoder) setBits(transform []byte) { + if s.reUsed || s.preDefined { + return + } + if s.useRLE { + if transform == nil { + s.ct.symbolTT[s.rleVal].outBits = s.rleVal + s.maxBits = s.rleVal + return + } + s.maxBits = transform[s.rleVal] + s.ct.symbolTT[s.rleVal].outBits = s.maxBits + return + } + if transform == nil { + for i := range s.ct.symbolTT[:s.symbolLen] { + s.ct.symbolTT[i].outBits = uint8(i) + } + s.maxBits = uint8(s.symbolLen - 1) + return + } + s.maxBits = 0 + for i, v := range transform[:s.symbolLen] { + s.ct.symbolTT[i].outBits = v + if v > s.maxBits { + // We could assume bits always going up, but we play safe. + s.maxBits = v + } + } +} + +// normalizeCount will normalize the count of the symbols so +// the total is equal to the table size. +// If successful, compression tables will also be made ready. +func (s *fseEncoder) normalizeCount(length int) error { + if s.reUsed { + return nil + } + s.optimalTableLog(length) + var ( + tableLog = s.actualTableLog + scale = 62 - uint64(tableLog) + step = (1 << 62) / uint64(length) + vStep = uint64(1) << (scale - 20) + stillToDistribute = int16(1 << tableLog) + largest int + largestP int16 + lowThreshold = (uint32)(length >> tableLog) + ) + if s.maxCount == length { + s.useRLE = true + return nil + } + s.useRLE = false + for i, cnt := range s.count[:s.symbolLen] { + // already handled + // if (count[s] == s.length) return 0; /* rle special case */ + + if cnt == 0 { + s.norm[i] = 0 + continue + } + if cnt <= lowThreshold { + s.norm[i] = -1 + stillToDistribute-- + } else { + proba := (int16)((uint64(cnt) * step) >> scale) + if proba < 8 { + restToBeat := vStep * uint64(rtbTable[proba]) + v := uint64(cnt)*step - (uint64(proba) << scale) + if v > restToBeat { + proba++ + } + } + if proba > largestP { + largestP = proba + largest = i + } + s.norm[i] = proba + stillToDistribute -= proba + } + } + + if -stillToDistribute >= (s.norm[largest] >> 1) { + // corner case, need another normalization method + err := s.normalizeCount2(length) + if err != nil { + return err + } + if debugAsserts { + err = s.validateNorm() + if err != nil { + return err + } + } + return s.buildCTable() + } + s.norm[largest] += stillToDistribute + if debugAsserts { + err := s.validateNorm() + if err != nil { + return err + } + } + return s.buildCTable() +} + +// Secondary normalization method. +// To be used when primary method fails. +func (s *fseEncoder) normalizeCount2(length int) error { + const notYetAssigned = -2 + var ( + distributed uint32 + total = uint32(length) + tableLog = s.actualTableLog + lowThreshold = total >> tableLog + lowOne = (total * 3) >> (tableLog + 1) + ) + for i, cnt := range s.count[:s.symbolLen] { + if cnt == 0 { + s.norm[i] = 0 + continue + } + if cnt <= lowThreshold { + s.norm[i] = -1 + distributed++ + total -= cnt + continue + } + if cnt <= lowOne { + s.norm[i] = 1 + distributed++ + total -= cnt + continue + } + s.norm[i] = notYetAssigned + } + toDistribute := (1 << tableLog) - distributed + + if (total / toDistribute) > lowOne { + // risk of rounding to zero + lowOne = (total * 3) / (toDistribute * 2) + for i, cnt := range s.count[:s.symbolLen] { + if (s.norm[i] == notYetAssigned) && (cnt <= lowOne) { + s.norm[i] = 1 + distributed++ + total -= cnt + continue + } + } + toDistribute = (1 << tableLog) - distributed + } + if distributed == uint32(s.symbolLen)+1 { + // all values are pretty poor; + // probably incompressible data (should have already been detected); + // find max, then give all remaining points to max + var maxV int + var maxC uint32 + for i, cnt := range s.count[:s.symbolLen] { + if cnt > maxC { + maxV = i + maxC = cnt + } + } + s.norm[maxV] += int16(toDistribute) + return nil + } + + if total == 0 { + // all of the symbols were low enough for the lowOne or lowThreshold + for i := uint32(0); toDistribute > 0; i = (i + 1) % (uint32(s.symbolLen)) { + if s.norm[i] > 0 { + toDistribute-- + s.norm[i]++ + } + } + return nil + } + + var ( + vStepLog = 62 - uint64(tableLog) + mid = uint64((1 << (vStepLog - 1)) - 1) + rStep = (((1 << vStepLog) * uint64(toDistribute)) + mid) / uint64(total) // scale on remaining + tmpTotal = mid + ) + for i, cnt := range s.count[:s.symbolLen] { + if s.norm[i] == notYetAssigned { + var ( + end = tmpTotal + uint64(cnt)*rStep + sStart = uint32(tmpTotal >> vStepLog) + sEnd = uint32(end >> vStepLog) + weight = sEnd - sStart + ) + if weight < 1 { + return errors.New("weight < 1") + } + s.norm[i] = int16(weight) + tmpTotal = end + } + } + return nil +} + +// optimalTableLog calculates and sets the optimal tableLog in s.actualTableLog +func (s *fseEncoder) optimalTableLog(length int) { + tableLog := uint8(maxEncTableLog) + minBitsSrc := highBit(uint32(length)) + 1 + minBitsSymbols := highBit(uint32(s.symbolLen-1)) + 2 + minBits := uint8(minBitsSymbols) + if minBitsSrc < minBitsSymbols { + minBits = uint8(minBitsSrc) + } + + maxBitsSrc := uint8(highBit(uint32(length-1))) - 2 + if maxBitsSrc < tableLog { + // Accuracy can be reduced + tableLog = maxBitsSrc + } + if minBits > tableLog { + tableLog = minBits + } + // Need a minimum to safely represent all symbol values + if tableLog < minEncTablelog { + tableLog = minEncTablelog + } + if tableLog > maxEncTableLog { + tableLog = maxEncTableLog + } + s.actualTableLog = tableLog +} + +// validateNorm validates the normalized histogram table. +func (s *fseEncoder) validateNorm() (err error) { + var total int + for _, v := range s.norm[:s.symbolLen] { + if v >= 0 { + total += int(v) + } else { + total -= int(v) + } + } + defer func() { + if err == nil { + return + } + fmt.Printf("selected TableLog: %d, Symbol length: %d\n", s.actualTableLog, s.symbolLen) + for i, v := range s.norm[:s.symbolLen] { + fmt.Printf("%3d: %5d -> %4d \n", i, s.count[i], v) + } + }() + if total != (1 << s.actualTableLog) { + return fmt.Errorf("warning: Total == %d != %d", total, 1<> 3) + 3 + 2 + + // Write Table Size + bitStream = uint32(tableLog - minEncTablelog) + bitCount = uint(4) + remaining = int16(tableSize + 1) /* +1 for extra accuracy */ + threshold = int16(tableSize) + nbBits = uint(tableLog + 1) + outP = len(out) + ) + if cap(out) < outP+maxHeaderSize { + out = append(out, make([]byte, maxHeaderSize*3)...) + out = out[:len(out)-maxHeaderSize*3] + } + out = out[:outP+maxHeaderSize] + + // stops at 1 + for remaining > 1 { + if previous0 { + start := charnum + for s.norm[charnum] == 0 { + charnum++ + } + for charnum >= start+24 { + start += 24 + bitStream += uint32(0xFFFF) << bitCount + out[outP] = byte(bitStream) + out[outP+1] = byte(bitStream >> 8) + outP += 2 + bitStream >>= 16 + } + for charnum >= start+3 { + start += 3 + bitStream += 3 << bitCount + bitCount += 2 + } + bitStream += uint32(charnum-start) << bitCount + bitCount += 2 + if bitCount > 16 { + out[outP] = byte(bitStream) + out[outP+1] = byte(bitStream >> 8) + outP += 2 + bitStream >>= 16 + bitCount -= 16 + } + } + + count := s.norm[charnum] + charnum++ + max := (2*threshold - 1) - remaining + if count < 0 { + remaining += count + } else { + remaining -= count + } + count++ // +1 for extra accuracy + if count >= threshold { + count += max // [0..max[ [max..threshold[ (...) [threshold+max 2*threshold[ + } + bitStream += uint32(count) << bitCount + bitCount += nbBits + if count < max { + bitCount-- + } + + previous0 = count == 1 + if remaining < 1 { + return nil, errors.New("internal error: remaining < 1") + } + for remaining < threshold { + nbBits-- + threshold >>= 1 + } + + if bitCount > 16 { + out[outP] = byte(bitStream) + out[outP+1] = byte(bitStream >> 8) + outP += 2 + bitStream >>= 16 + bitCount -= 16 + } + } + + if outP+2 > len(out) { + return nil, fmt.Errorf("internal error: %d > %d, maxheader: %d, sl: %d, tl: %d, normcount: %v", outP+2, len(out), maxHeaderSize, s.symbolLen, int(tableLog), s.norm[:s.symbolLen]) + } + out[outP] = byte(bitStream) + out[outP+1] = byte(bitStream >> 8) + outP += int((bitCount + 7) / 8) + + if charnum > s.symbolLen { + return nil, errors.New("internal error: charnum > s.symbolLen") + } + return out[:outP], nil +} + +// Approximate symbol cost, as fractional value, using fixed-point format (accuracyLog fractional bits) +// note 1 : assume symbolValue is valid (<= maxSymbolValue) +// note 2 : if freq[symbolValue]==0, @return a fake cost of tableLog+1 bits * +func (s *fseEncoder) bitCost(symbolValue uint8, accuracyLog uint32) uint32 { + minNbBits := s.ct.symbolTT[symbolValue].deltaNbBits >> 16 + threshold := (minNbBits + 1) << 16 + if debugAsserts { + if !(s.actualTableLog < 16) { + panic("!s.actualTableLog < 16") + } + // ensure enough room for renormalization double shift + if !(uint8(accuracyLog) < 31-s.actualTableLog) { + panic("!uint8(accuracyLog) < 31-s.actualTableLog") + } + } + tableSize := uint32(1) << s.actualTableLog + deltaFromThreshold := threshold - (s.ct.symbolTT[symbolValue].deltaNbBits + tableSize) + // linear interpolation (very approximate) + normalizedDeltaFromThreshold := (deltaFromThreshold << accuracyLog) >> s.actualTableLog + bitMultiplier := uint32(1) << accuracyLog + if debugAsserts { + if s.ct.symbolTT[symbolValue].deltaNbBits+tableSize > threshold { + panic("s.ct.symbolTT[symbolValue].deltaNbBits+tableSize > threshold") + } + if normalizedDeltaFromThreshold > bitMultiplier { + panic("normalizedDeltaFromThreshold > bitMultiplier") + } + } + return (minNbBits+1)*bitMultiplier - normalizedDeltaFromThreshold +} + +// Returns the cost in bits of encoding the distribution in count using ctable. +// Histogram should only be up to the last non-zero symbol. +// Returns an -1 if ctable cannot represent all the symbols in count. +func (s *fseEncoder) approxSize(hist []uint32) uint32 { + if int(s.symbolLen) < len(hist) { + // More symbols than we have. + return math.MaxUint32 + } + if s.useRLE { + // We will never reuse RLE encoders. + return math.MaxUint32 + } + const kAccuracyLog = 8 + badCost := (uint32(s.actualTableLog) + 1) << kAccuracyLog + var cost uint32 + for i, v := range hist { + if v == 0 { + continue + } + if s.norm[i] == 0 { + return math.MaxUint32 + } + bitCost := s.bitCost(uint8(i), kAccuracyLog) + if bitCost > badCost { + return math.MaxUint32 + } + cost += v * bitCost + } + return cost >> kAccuracyLog +} + +// maxHeaderSize returns the maximum header size in bits. +// This is not exact size, but we want a penalty for new tables anyway. +func (s *fseEncoder) maxHeaderSize() uint32 { + if s.preDefined { + return 0 + } + if s.useRLE { + return 8 + } + return (((uint32(s.symbolLen) * uint32(s.actualTableLog)) >> 3) + 3) * 8 +} + +// cState contains the compression state of a stream. +type cState struct { + bw *bitWriter + stateTable []uint16 + state uint16 +} + +// init will initialize the compression state to the first symbol of the stream. +func (c *cState) init(bw *bitWriter, ct *cTable, first symbolTransform) { + c.bw = bw + c.stateTable = ct.stateTable + if len(c.stateTable) == 1 { + // RLE + c.stateTable[0] = uint16(0) + c.state = 0 + return + } + nbBitsOut := (first.deltaNbBits + (1 << 15)) >> 16 + im := int32((nbBitsOut << 16) - first.deltaNbBits) + lu := (im >> nbBitsOut) + int32(first.deltaFindState) + c.state = c.stateTable[lu] +} + +// flush will write the tablelog to the output and flush the remaining full bytes. +func (c *cState) flush(tableLog uint8) { + c.bw.flush32() + c.bw.addBits16NC(c.state, tableLog) +} diff --git a/vendor/github.com/klauspost/compress/zstd/fse_predefined.go b/vendor/github.com/klauspost/compress/zstd/fse_predefined.go new file mode 100644 index 000000000..474cb77d2 --- /dev/null +++ b/vendor/github.com/klauspost/compress/zstd/fse_predefined.go @@ -0,0 +1,158 @@ +// Copyright 2019+ Klaus Post. All rights reserved. +// License information can be found in the LICENSE file. +// Based on work by Yann Collet, released under BSD License. + +package zstd + +import ( + "fmt" + "math" + "sync" +) + +var ( + // fsePredef are the predefined fse tables as defined here: + // https://github.com/facebook/zstd/blob/dev/doc/zstd_compression_format.md#default-distributions + // These values are already transformed. + fsePredef [3]fseDecoder + + // fsePredefEnc are the predefined encoder based on fse tables as defined here: + // https://github.com/facebook/zstd/blob/dev/doc/zstd_compression_format.md#default-distributions + // These values are already transformed. + fsePredefEnc [3]fseEncoder + + // symbolTableX contain the transformations needed for each type as defined in + // https://github.com/facebook/zstd/blob/dev/doc/zstd_compression_format.md#the-codes-for-literals-lengths-match-lengths-and-offsets + symbolTableX [3][]baseOffset + + // maxTableSymbol is the biggest supported symbol for each table type + // https://github.com/facebook/zstd/blob/dev/doc/zstd_compression_format.md#the-codes-for-literals-lengths-match-lengths-and-offsets + maxTableSymbol = [3]uint8{tableLiteralLengths: maxLiteralLengthSymbol, tableOffsets: maxOffsetLengthSymbol, tableMatchLengths: maxMatchLengthSymbol} + + // bitTables is the bits table for each table. + bitTables = [3][]byte{tableLiteralLengths: llBitsTable[:], tableOffsets: nil, tableMatchLengths: mlBitsTable[:]} +) + +type tableIndex uint8 + +const ( + // indexes for fsePredef and symbolTableX + tableLiteralLengths tableIndex = 0 + tableOffsets tableIndex = 1 + tableMatchLengths tableIndex = 2 + + maxLiteralLengthSymbol = 35 + maxOffsetLengthSymbol = 30 + maxMatchLengthSymbol = 52 +) + +// baseOffset is used for calculating transformations. +type baseOffset struct { + baseLine uint32 + addBits uint8 +} + +// fillBase will precalculate base offsets with the given bit distributions. +func fillBase(dst []baseOffset, base uint32, bits ...uint8) { + if len(bits) != len(dst) { + panic(fmt.Sprintf("len(dst) (%d) != len(bits) (%d)", len(dst), len(bits))) + } + for i, bit := range bits { + if base > math.MaxInt32 { + panic("invalid decoding table, base overflows int32") + } + + dst[i] = baseOffset{ + baseLine: base, + addBits: bit, + } + base += 1 << bit + } +} + +var predef sync.Once + +func initPredefined() { + predef.Do(func() { + // Literals length codes + tmp := make([]baseOffset, 36) + for i := range tmp[:16] { + tmp[i] = baseOffset{ + baseLine: uint32(i), + addBits: 0, + } + } + fillBase(tmp[16:], 16, 1, 1, 1, 1, 2, 2, 3, 3, 4, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16) + symbolTableX[tableLiteralLengths] = tmp + + // Match length codes + tmp = make([]baseOffset, 53) + for i := range tmp[:32] { + tmp[i] = baseOffset{ + // The transformation adds the 3 length. + baseLine: uint32(i) + 3, + addBits: 0, + } + } + fillBase(tmp[32:], 35, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16) + symbolTableX[tableMatchLengths] = tmp + + // Offset codes + tmp = make([]baseOffset, maxOffsetBits+1) + tmp[1] = baseOffset{ + baseLine: 1, + addBits: 1, + } + fillBase(tmp[2:], 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30) + symbolTableX[tableOffsets] = tmp + + // Fill predefined tables and transform them. + // https://github.com/facebook/zstd/blob/dev/doc/zstd_compression_format.md#default-distributions + for i := range fsePredef[:] { + f := &fsePredef[i] + switch tableIndex(i) { + case tableLiteralLengths: + // https://github.com/facebook/zstd/blob/ededcfca57366461021c922720878c81a5854a0a/lib/decompress/zstd_decompress_block.c#L243 + f.actualTableLog = 6 + copy(f.norm[:], []int16{4, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 1, 1, 1, 1, 1, + -1, -1, -1, -1}) + f.symbolLen = 36 + case tableOffsets: + // https://github.com/facebook/zstd/blob/ededcfca57366461021c922720878c81a5854a0a/lib/decompress/zstd_decompress_block.c#L281 + f.actualTableLog = 5 + copy(f.norm[:], []int16{ + 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1}) + f.symbolLen = 29 + case tableMatchLengths: + //https://github.com/facebook/zstd/blob/ededcfca57366461021c922720878c81a5854a0a/lib/decompress/zstd_decompress_block.c#L304 + f.actualTableLog = 6 + copy(f.norm[:], []int16{ + 1, 4, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, + -1, -1, -1, -1, -1}) + f.symbolLen = 53 + } + if err := f.buildDtable(); err != nil { + panic(fmt.Errorf("building table %v: %v", tableIndex(i), err)) + } + if err := f.transform(symbolTableX[i]); err != nil { + panic(fmt.Errorf("building table %v: %v", tableIndex(i), err)) + } + f.preDefined = true + + // Create encoder as well + enc := &fsePredefEnc[i] + copy(enc.norm[:], f.norm[:]) + enc.symbolLen = f.symbolLen + enc.actualTableLog = f.actualTableLog + if err := enc.buildCTable(); err != nil { + panic(fmt.Errorf("building encoding table %v: %v", tableIndex(i), err)) + } + enc.setBits(bitTables[i]) + enc.preDefined = true + } + }) +} diff --git a/vendor/github.com/klauspost/compress/zstd/hash.go b/vendor/github.com/klauspost/compress/zstd/hash.go new file mode 100644 index 000000000..5d73c21eb --- /dev/null +++ b/vendor/github.com/klauspost/compress/zstd/hash.go @@ -0,0 +1,35 @@ +// Copyright 2019+ Klaus Post. All rights reserved. +// License information can be found in the LICENSE file. +// Based on work by Yann Collet, released under BSD License. + +package zstd + +const ( + prime3bytes = 506832829 + prime4bytes = 2654435761 + prime5bytes = 889523592379 + prime6bytes = 227718039650203 + prime7bytes = 58295818150454627 + prime8bytes = 0xcf1bbcdcb7a56463 +) + +// hashLen returns a hash of the lowest mls bytes of with length output bits. +// mls must be >=3 and <=8. Any other value will return hash for 4 bytes. +// length should always be < 32. +// Preferably length and mls should be a constant for inlining. +func hashLen(u uint64, length, mls uint8) uint32 { + switch mls { + case 3: + return (uint32(u<<8) * prime3bytes) >> (32 - length) + case 5: + return uint32(((u << (64 - 40)) * prime5bytes) >> (64 - length)) + case 6: + return uint32(((u << (64 - 48)) * prime6bytes) >> (64 - length)) + case 7: + return uint32(((u << (64 - 56)) * prime7bytes) >> (64 - length)) + case 8: + return uint32((u * prime8bytes) >> (64 - length)) + default: + return (uint32(u) * prime4bytes) >> (32 - length) + } +} diff --git a/vendor/github.com/klauspost/compress/zstd/history.go b/vendor/github.com/klauspost/compress/zstd/history.go new file mode 100644 index 000000000..09164856d --- /dev/null +++ b/vendor/github.com/klauspost/compress/zstd/history.go @@ -0,0 +1,116 @@ +// Copyright 2019+ Klaus Post. All rights reserved. +// License information can be found in the LICENSE file. +// Based on work by Yann Collet, released under BSD License. + +package zstd + +import ( + "github.com/klauspost/compress/huff0" +) + +// history contains the information transferred between blocks. +type history struct { + // Literal decompression + huffTree *huff0.Scratch + + // Sequence decompression + decoders sequenceDecs + recentOffsets [3]int + + // History buffer... + b []byte + + // ignoreBuffer is meant to ignore a number of bytes + // when checking for matches in history + ignoreBuffer int + + windowSize int + allocFrameBuffer int // needed? + error bool + dict *dict +} + +// reset will reset the history to initial state of a frame. +// The history must already have been initialized to the desired size. +func (h *history) reset() { + h.b = h.b[:0] + h.ignoreBuffer = 0 + h.error = false + h.recentOffsets = [3]int{1, 4, 8} + h.decoders.freeDecoders() + h.decoders = sequenceDecs{br: h.decoders.br} + h.freeHuffDecoder() + h.huffTree = nil + h.dict = nil + //printf("history created: %+v (l: %d, c: %d)", *h, len(h.b), cap(h.b)) +} + +func (h *history) freeHuffDecoder() { + if h.huffTree != nil { + if h.dict == nil || h.dict.litEnc != h.huffTree { + huffDecoderPool.Put(h.huffTree) + h.huffTree = nil + } + } +} + +func (h *history) setDict(dict *dict) { + if dict == nil { + return + } + h.dict = dict + h.decoders.litLengths = dict.llDec + h.decoders.offsets = dict.ofDec + h.decoders.matchLengths = dict.mlDec + h.decoders.dict = dict.content + h.recentOffsets = dict.offsets + h.huffTree = dict.litEnc +} + +// append bytes to history. +// This function will make sure there is space for it, +// if the buffer has been allocated with enough extra space. +func (h *history) append(b []byte) { + if len(b) >= h.windowSize { + // Discard all history by simply overwriting + h.b = h.b[:h.windowSize] + copy(h.b, b[len(b)-h.windowSize:]) + return + } + + // If there is space, append it. + if len(b) < cap(h.b)-len(h.b) { + h.b = append(h.b, b...) + return + } + + // Move data down so we only have window size left. + // We know we have less than window size in b at this point. + discard := len(b) + len(h.b) - h.windowSize + copy(h.b, h.b[discard:]) + h.b = h.b[:h.windowSize] + copy(h.b[h.windowSize-len(b):], b) +} + +// ensureBlock will ensure there is space for at least one block... +func (h *history) ensureBlock() { + if cap(h.b) < h.allocFrameBuffer { + h.b = make([]byte, 0, h.allocFrameBuffer) + return + } + + avail := cap(h.b) - len(h.b) + if avail >= h.windowSize || avail > maxCompressedBlockSize { + return + } + // Move data down so we only have window size left. + // We know we have less than window size in b at this point. + discard := len(h.b) - h.windowSize + copy(h.b, h.b[discard:]) + h.b = h.b[:h.windowSize] +} + +// append bytes to history without ever discarding anything. +func (h *history) appendKeep(b []byte) { + h.b = append(h.b, b...) +} diff --git a/vendor/github.com/klauspost/compress/zstd/internal/xxhash/LICENSE.txt b/vendor/github.com/klauspost/compress/zstd/internal/xxhash/LICENSE.txt new file mode 100644 index 000000000..24b53065f --- /dev/null +++ b/vendor/github.com/klauspost/compress/zstd/internal/xxhash/LICENSE.txt @@ -0,0 +1,22 @@ +Copyright (c) 2016 Caleb Spare + +MIT License + +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/klauspost/compress/zstd/internal/xxhash/README.md b/vendor/github.com/klauspost/compress/zstd/internal/xxhash/README.md new file mode 100644 index 000000000..777290d44 --- /dev/null +++ b/vendor/github.com/klauspost/compress/zstd/internal/xxhash/README.md @@ -0,0 +1,71 @@ +# xxhash + +VENDORED: Go to [github.com/cespare/xxhash](https://github.com/cespare/xxhash) for original package. + +xxhash is a Go implementation of the 64-bit [xxHash] algorithm, XXH64. This is a +high-quality hashing algorithm that is much faster than anything in the Go +standard library. + +This package provides a straightforward API: + +``` +func Sum64(b []byte) uint64 +func Sum64String(s string) uint64 +type Digest struct{ ... } + func New() *Digest +``` + +The `Digest` type implements hash.Hash64. Its key methods are: + +``` +func (*Digest) Write([]byte) (int, error) +func (*Digest) WriteString(string) (int, error) +func (*Digest) Sum64() uint64 +``` + +The package is written with optimized pure Go and also contains even faster +assembly implementations for amd64 and arm64. If desired, the `purego` build tag +opts into using the Go code even on those architectures. + +[xxHash]: http://cyan4973.github.io/xxHash/ + +## Compatibility + +This package is in a module and the latest code is in version 2 of the module. +You need a version of Go with at least "minimal module compatibility" to use +github.com/cespare/xxhash/v2: + +* 1.9.7+ for Go 1.9 +* 1.10.3+ for Go 1.10 +* Go 1.11 or later + +I recommend using the latest release of Go. + +## Benchmarks + +Here are some quick benchmarks comparing the pure-Go and assembly +implementations of Sum64. + +| input size | purego | asm | +| ---------- | --------- | --------- | +| 4 B | 1.3 GB/s | 1.2 GB/s | +| 16 B | 2.9 GB/s | 3.5 GB/s | +| 100 B | 6.9 GB/s | 8.1 GB/s | +| 4 KB | 11.7 GB/s | 16.7 GB/s | +| 10 MB | 12.0 GB/s | 17.3 GB/s | + +These numbers were generated on Ubuntu 20.04 with an Intel Xeon Platinum 8252C +CPU using the following commands under Go 1.19.2: + +``` +benchstat <(go test -tags purego -benchtime 500ms -count 15 -bench 'Sum64$') +benchstat <(go test -benchtime 500ms -count 15 -bench 'Sum64$') +``` + +## Projects using this package + +- [InfluxDB](https://github.com/influxdata/influxdb) +- [Prometheus](https://github.com/prometheus/prometheus) +- [VictoriaMetrics](https://github.com/VictoriaMetrics/VictoriaMetrics) +- [FreeCache](https://github.com/coocood/freecache) +- [FastCache](https://github.com/VictoriaMetrics/fastcache) diff --git a/vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash.go b/vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash.go new file mode 100644 index 000000000..fc40c8200 --- /dev/null +++ b/vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash.go @@ -0,0 +1,230 @@ +// Package xxhash implements the 64-bit variant of xxHash (XXH64) as described +// at http://cyan4973.github.io/xxHash/. +// THIS IS VENDORED: Go to github.com/cespare/xxhash for original package. + +package xxhash + +import ( + "encoding/binary" + "errors" + "math/bits" +) + +const ( + prime1 uint64 = 11400714785074694791 + prime2 uint64 = 14029467366897019727 + prime3 uint64 = 1609587929392839161 + prime4 uint64 = 9650029242287828579 + prime5 uint64 = 2870177450012600261 +) + +// Store the primes in an array as well. +// +// The consts are used when possible in Go code to avoid MOVs but we need a +// contiguous array of the assembly code. +var primes = [...]uint64{prime1, prime2, prime3, prime4, prime5} + +// Digest implements hash.Hash64. +type Digest struct { + v1 uint64 + v2 uint64 + v3 uint64 + v4 uint64 + total uint64 + mem [32]byte + n int // how much of mem is used +} + +// New creates a new Digest that computes the 64-bit xxHash algorithm. +func New() *Digest { + var d Digest + d.Reset() + return &d +} + +// Reset clears the Digest's state so that it can be reused. +func (d *Digest) Reset() { + d.v1 = primes[0] + prime2 + d.v2 = prime2 + d.v3 = 0 + d.v4 = -primes[0] + d.total = 0 + d.n = 0 +} + +// Size always returns 8 bytes. +func (d *Digest) Size() int { return 8 } + +// BlockSize always returns 32 bytes. +func (d *Digest) BlockSize() int { return 32 } + +// Write adds more data to d. It always returns len(b), nil. +func (d *Digest) Write(b []byte) (n int, err error) { + n = len(b) + d.total += uint64(n) + + memleft := d.mem[d.n&(len(d.mem)-1):] + + if d.n+n < 32 { + // This new data doesn't even fill the current block. + copy(memleft, b) + d.n += n + return + } + + if d.n > 0 { + // Finish off the partial block. + c := copy(memleft, b) + d.v1 = round(d.v1, u64(d.mem[0:8])) + d.v2 = round(d.v2, u64(d.mem[8:16])) + d.v3 = round(d.v3, u64(d.mem[16:24])) + d.v4 = round(d.v4, u64(d.mem[24:32])) + b = b[c:] + d.n = 0 + } + + if len(b) >= 32 { + // One or more full blocks left. + nw := writeBlocks(d, b) + b = b[nw:] + } + + // Store any remaining partial block. + copy(d.mem[:], b) + d.n = len(b) + + return +} + +// Sum appends the current hash to b and returns the resulting slice. +func (d *Digest) Sum(b []byte) []byte { + s := d.Sum64() + return append( + b, + byte(s>>56), + byte(s>>48), + byte(s>>40), + byte(s>>32), + byte(s>>24), + byte(s>>16), + byte(s>>8), + byte(s), + ) +} + +// Sum64 returns the current hash. +func (d *Digest) Sum64() uint64 { + var h uint64 + + if d.total >= 32 { + v1, v2, v3, v4 := d.v1, d.v2, d.v3, d.v4 + h = rol1(v1) + rol7(v2) + rol12(v3) + rol18(v4) + h = mergeRound(h, v1) + h = mergeRound(h, v2) + h = mergeRound(h, v3) + h = mergeRound(h, v4) + } else { + h = d.v3 + prime5 + } + + h += d.total + + b := d.mem[:d.n&(len(d.mem)-1)] + for ; len(b) >= 8; b = b[8:] { + k1 := round(0, u64(b[:8])) + h ^= k1 + h = rol27(h)*prime1 + prime4 + } + if len(b) >= 4 { + h ^= uint64(u32(b[:4])) * prime1 + h = rol23(h)*prime2 + prime3 + b = b[4:] + } + for ; len(b) > 0; b = b[1:] { + h ^= uint64(b[0]) * prime5 + h = rol11(h) * prime1 + } + + h ^= h >> 33 + h *= prime2 + h ^= h >> 29 + h *= prime3 + h ^= h >> 32 + + return h +} + +const ( + magic = "xxh\x06" + marshaledSize = len(magic) + 8*5 + 32 +) + +// MarshalBinary implements the encoding.BinaryMarshaler interface. +func (d *Digest) MarshalBinary() ([]byte, error) { + b := make([]byte, 0, marshaledSize) + b = append(b, magic...) + b = appendUint64(b, d.v1) + b = appendUint64(b, d.v2) + b = appendUint64(b, d.v3) + b = appendUint64(b, d.v4) + b = appendUint64(b, d.total) + b = append(b, d.mem[:d.n]...) + b = b[:len(b)+len(d.mem)-d.n] + return b, nil +} + +// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface. +func (d *Digest) UnmarshalBinary(b []byte) error { + if len(b) < len(magic) || string(b[:len(magic)]) != magic { + return errors.New("xxhash: invalid hash state identifier") + } + if len(b) != marshaledSize { + return errors.New("xxhash: invalid hash state size") + } + b = b[len(magic):] + b, d.v1 = consumeUint64(b) + b, d.v2 = consumeUint64(b) + b, d.v3 = consumeUint64(b) + b, d.v4 = consumeUint64(b) + b, d.total = consumeUint64(b) + copy(d.mem[:], b) + d.n = int(d.total % uint64(len(d.mem))) + return nil +} + +func appendUint64(b []byte, x uint64) []byte { + var a [8]byte + binary.LittleEndian.PutUint64(a[:], x) + return append(b, a[:]...) +} + +func consumeUint64(b []byte) ([]byte, uint64) { + x := u64(b) + return b[8:], x +} + +func u64(b []byte) uint64 { return binary.LittleEndian.Uint64(b) } +func u32(b []byte) uint32 { return binary.LittleEndian.Uint32(b) } + +func round(acc, input uint64) uint64 { + acc += input * prime2 + acc = rol31(acc) + acc *= prime1 + return acc +} + +func mergeRound(acc, val uint64) uint64 { + val = round(0, val) + acc ^= val + acc = acc*prime1 + prime4 + return acc +} + +func rol1(x uint64) uint64 { return bits.RotateLeft64(x, 1) } +func rol7(x uint64) uint64 { return bits.RotateLeft64(x, 7) } +func rol11(x uint64) uint64 { return bits.RotateLeft64(x, 11) } +func rol12(x uint64) uint64 { return bits.RotateLeft64(x, 12) } +func rol18(x uint64) uint64 { return bits.RotateLeft64(x, 18) } +func rol23(x uint64) uint64 { return bits.RotateLeft64(x, 23) } +func rol27(x uint64) uint64 { return bits.RotateLeft64(x, 27) } +func rol31(x uint64) uint64 { return bits.RotateLeft64(x, 31) } diff --git a/vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash_amd64.s b/vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash_amd64.s new file mode 100644 index 000000000..ddb63aa91 --- /dev/null +++ b/vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash_amd64.s @@ -0,0 +1,210 @@ +//go:build !appengine && gc && !purego && !noasm +// +build !appengine +// +build gc +// +build !purego +// +build !noasm + +#include "textflag.h" + +// Registers: +#define h AX +#define d AX +#define p SI // pointer to advance through b +#define n DX +#define end BX // loop end +#define v1 R8 +#define v2 R9 +#define v3 R10 +#define v4 R11 +#define x R12 +#define prime1 R13 +#define prime2 R14 +#define prime4 DI + +#define round(acc, x) \ + IMULQ prime2, x \ + ADDQ x, acc \ + ROLQ $31, acc \ + IMULQ prime1, acc + +// round0 performs the operation x = round(0, x). +#define round0(x) \ + IMULQ prime2, x \ + ROLQ $31, x \ + IMULQ prime1, x + +// mergeRound applies a merge round on the two registers acc and x. +// It assumes that prime1, prime2, and prime4 have been loaded. +#define mergeRound(acc, x) \ + round0(x) \ + XORQ x, acc \ + IMULQ prime1, acc \ + ADDQ prime4, acc + +// blockLoop processes as many 32-byte blocks as possible, +// updating v1, v2, v3, and v4. It assumes that there is at least one block +// to process. +#define blockLoop() \ +loop: \ + MOVQ +0(p), x \ + round(v1, x) \ + MOVQ +8(p), x \ + round(v2, x) \ + MOVQ +16(p), x \ + round(v3, x) \ + MOVQ +24(p), x \ + round(v4, x) \ + ADDQ $32, p \ + CMPQ p, end \ + JLE loop + +// func Sum64(b []byte) uint64 +TEXT ·Sum64(SB), NOSPLIT|NOFRAME, $0-32 + // Load fixed primes. + MOVQ ·primes+0(SB), prime1 + MOVQ ·primes+8(SB), prime2 + MOVQ ·primes+24(SB), prime4 + + // Load slice. + MOVQ b_base+0(FP), p + MOVQ b_len+8(FP), n + LEAQ (p)(n*1), end + + // The first loop limit will be len(b)-32. + SUBQ $32, end + + // Check whether we have at least one block. + CMPQ n, $32 + JLT noBlocks + + // Set up initial state (v1, v2, v3, v4). + MOVQ prime1, v1 + ADDQ prime2, v1 + MOVQ prime2, v2 + XORQ v3, v3 + XORQ v4, v4 + SUBQ prime1, v4 + + blockLoop() + + MOVQ v1, h + ROLQ $1, h + MOVQ v2, x + ROLQ $7, x + ADDQ x, h + MOVQ v3, x + ROLQ $12, x + ADDQ x, h + MOVQ v4, x + ROLQ $18, x + ADDQ x, h + + mergeRound(h, v1) + mergeRound(h, v2) + mergeRound(h, v3) + mergeRound(h, v4) + + JMP afterBlocks + +noBlocks: + MOVQ ·primes+32(SB), h + +afterBlocks: + ADDQ n, h + + ADDQ $24, end + CMPQ p, end + JG try4 + +loop8: + MOVQ (p), x + ADDQ $8, p + round0(x) + XORQ x, h + ROLQ $27, h + IMULQ prime1, h + ADDQ prime4, h + + CMPQ p, end + JLE loop8 + +try4: + ADDQ $4, end + CMPQ p, end + JG try1 + + MOVL (p), x + ADDQ $4, p + IMULQ prime1, x + XORQ x, h + + ROLQ $23, h + IMULQ prime2, h + ADDQ ·primes+16(SB), h + +try1: + ADDQ $4, end + CMPQ p, end + JGE finalize + +loop1: + MOVBQZX (p), x + ADDQ $1, p + IMULQ ·primes+32(SB), x + XORQ x, h + ROLQ $11, h + IMULQ prime1, h + + CMPQ p, end + JL loop1 + +finalize: + MOVQ h, x + SHRQ $33, x + XORQ x, h + IMULQ prime2, h + MOVQ h, x + SHRQ $29, x + XORQ x, h + IMULQ ·primes+16(SB), h + MOVQ h, x + SHRQ $32, x + XORQ x, h + + MOVQ h, ret+24(FP) + RET + +// func writeBlocks(d *Digest, b []byte) int +TEXT ·writeBlocks(SB), NOSPLIT|NOFRAME, $0-40 + // Load fixed primes needed for round. + MOVQ ·primes+0(SB), prime1 + MOVQ ·primes+8(SB), prime2 + + // Load slice. + MOVQ b_base+8(FP), p + MOVQ b_len+16(FP), n + LEAQ (p)(n*1), end + SUBQ $32, end + + // Load vN from d. + MOVQ s+0(FP), d + MOVQ 0(d), v1 + MOVQ 8(d), v2 + MOVQ 16(d), v3 + MOVQ 24(d), v4 + + // We don't need to check the loop condition here; this function is + // always called with at least one block of data to process. + blockLoop() + + // Copy vN back to d. + MOVQ v1, 0(d) + MOVQ v2, 8(d) + MOVQ v3, 16(d) + MOVQ v4, 24(d) + + // The number of bytes written is p minus the old base pointer. + SUBQ b_base+8(FP), p + MOVQ p, ret+32(FP) + + RET diff --git a/vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash_arm64.s b/vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash_arm64.s new file mode 100644 index 000000000..ae7d4d329 --- /dev/null +++ b/vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash_arm64.s @@ -0,0 +1,184 @@ +//go:build !appengine && gc && !purego && !noasm +// +build !appengine +// +build gc +// +build !purego +// +build !noasm + +#include "textflag.h" + +// Registers: +#define digest R1 +#define h R2 // return value +#define p R3 // input pointer +#define n R4 // input length +#define nblocks R5 // n / 32 +#define prime1 R7 +#define prime2 R8 +#define prime3 R9 +#define prime4 R10 +#define prime5 R11 +#define v1 R12 +#define v2 R13 +#define v3 R14 +#define v4 R15 +#define x1 R20 +#define x2 R21 +#define x3 R22 +#define x4 R23 + +#define round(acc, x) \ + MADD prime2, acc, x, acc \ + ROR $64-31, acc \ + MUL prime1, acc + +// round0 performs the operation x = round(0, x). +#define round0(x) \ + MUL prime2, x \ + ROR $64-31, x \ + MUL prime1, x + +#define mergeRound(acc, x) \ + round0(x) \ + EOR x, acc \ + MADD acc, prime4, prime1, acc + +// blockLoop processes as many 32-byte blocks as possible, +// updating v1, v2, v3, and v4. It assumes that n >= 32. +#define blockLoop() \ + LSR $5, n, nblocks \ + PCALIGN $16 \ + loop: \ + LDP.P 16(p), (x1, x2) \ + LDP.P 16(p), (x3, x4) \ + round(v1, x1) \ + round(v2, x2) \ + round(v3, x3) \ + round(v4, x4) \ + SUB $1, nblocks \ + CBNZ nblocks, loop + +// func Sum64(b []byte) uint64 +TEXT ·Sum64(SB), NOSPLIT|NOFRAME, $0-32 + LDP b_base+0(FP), (p, n) + + LDP ·primes+0(SB), (prime1, prime2) + LDP ·primes+16(SB), (prime3, prime4) + MOVD ·primes+32(SB), prime5 + + CMP $32, n + CSEL LT, prime5, ZR, h // if n < 32 { h = prime5 } else { h = 0 } + BLT afterLoop + + ADD prime1, prime2, v1 + MOVD prime2, v2 + MOVD $0, v3 + NEG prime1, v4 + + blockLoop() + + ROR $64-1, v1, x1 + ROR $64-7, v2, x2 + ADD x1, x2 + ROR $64-12, v3, x3 + ROR $64-18, v4, x4 + ADD x3, x4 + ADD x2, x4, h + + mergeRound(h, v1) + mergeRound(h, v2) + mergeRound(h, v3) + mergeRound(h, v4) + +afterLoop: + ADD n, h + + TBZ $4, n, try8 + LDP.P 16(p), (x1, x2) + + round0(x1) + + // NOTE: here and below, sequencing the EOR after the ROR (using a + // rotated register) is worth a small but measurable speedup for small + // inputs. + ROR $64-27, h + EOR x1 @> 64-27, h, h + MADD h, prime4, prime1, h + + round0(x2) + ROR $64-27, h + EOR x2 @> 64-27, h, h + MADD h, prime4, prime1, h + +try8: + TBZ $3, n, try4 + MOVD.P 8(p), x1 + + round0(x1) + ROR $64-27, h + EOR x1 @> 64-27, h, h + MADD h, prime4, prime1, h + +try4: + TBZ $2, n, try2 + MOVWU.P 4(p), x2 + + MUL prime1, x2 + ROR $64-23, h + EOR x2 @> 64-23, h, h + MADD h, prime3, prime2, h + +try2: + TBZ $1, n, try1 + MOVHU.P 2(p), x3 + AND $255, x3, x1 + LSR $8, x3, x2 + + MUL prime5, x1 + ROR $64-11, h + EOR x1 @> 64-11, h, h + MUL prime1, h + + MUL prime5, x2 + ROR $64-11, h + EOR x2 @> 64-11, h, h + MUL prime1, h + +try1: + TBZ $0, n, finalize + MOVBU (p), x4 + + MUL prime5, x4 + ROR $64-11, h + EOR x4 @> 64-11, h, h + MUL prime1, h + +finalize: + EOR h >> 33, h + MUL prime2, h + EOR h >> 29, h + MUL prime3, h + EOR h >> 32, h + + MOVD h, ret+24(FP) + RET + +// func writeBlocks(s *Digest, b []byte) int +TEXT ·writeBlocks(SB), NOSPLIT|NOFRAME, $0-40 + LDP ·primes+0(SB), (prime1, prime2) + + // Load state. Assume v[1-4] are stored contiguously. + MOVD s+0(FP), digest + LDP 0(digest), (v1, v2) + LDP 16(digest), (v3, v4) + + LDP b_base+8(FP), (p, n) + + blockLoop() + + // Store updated state. + STP (v1, v2), 0(digest) + STP (v3, v4), 16(digest) + + BIC $31, n + MOVD n, ret+32(FP) + RET diff --git a/vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash_asm.go b/vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash_asm.go new file mode 100644 index 000000000..d4221edf4 --- /dev/null +++ b/vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash_asm.go @@ -0,0 +1,16 @@ +//go:build (amd64 || arm64) && !appengine && gc && !purego && !noasm +// +build amd64 arm64 +// +build !appengine +// +build gc +// +build !purego +// +build !noasm + +package xxhash + +// Sum64 computes the 64-bit xxHash digest of b. +// +//go:noescape +func Sum64(b []byte) uint64 + +//go:noescape +func writeBlocks(s *Digest, b []byte) int diff --git a/vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash_other.go b/vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash_other.go new file mode 100644 index 000000000..0be16cefc --- /dev/null +++ b/vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash_other.go @@ -0,0 +1,76 @@ +//go:build (!amd64 && !arm64) || appengine || !gc || purego || noasm +// +build !amd64,!arm64 appengine !gc purego noasm + +package xxhash + +// Sum64 computes the 64-bit xxHash digest of b. +func Sum64(b []byte) uint64 { + // A simpler version would be + // d := New() + // d.Write(b) + // return d.Sum64() + // but this is faster, particularly for small inputs. + + n := len(b) + var h uint64 + + if n >= 32 { + v1 := primes[0] + prime2 + v2 := prime2 + v3 := uint64(0) + v4 := -primes[0] + for len(b) >= 32 { + v1 = round(v1, u64(b[0:8:len(b)])) + v2 = round(v2, u64(b[8:16:len(b)])) + v3 = round(v3, u64(b[16:24:len(b)])) + v4 = round(v4, u64(b[24:32:len(b)])) + b = b[32:len(b):len(b)] + } + h = rol1(v1) + rol7(v2) + rol12(v3) + rol18(v4) + h = mergeRound(h, v1) + h = mergeRound(h, v2) + h = mergeRound(h, v3) + h = mergeRound(h, v4) + } else { + h = prime5 + } + + h += uint64(n) + + for ; len(b) >= 8; b = b[8:] { + k1 := round(0, u64(b[:8])) + h ^= k1 + h = rol27(h)*prime1 + prime4 + } + if len(b) >= 4 { + h ^= uint64(u32(b[:4])) * prime1 + h = rol23(h)*prime2 + prime3 + b = b[4:] + } + for ; len(b) > 0; b = b[1:] { + h ^= uint64(b[0]) * prime5 + h = rol11(h) * prime1 + } + + h ^= h >> 33 + h *= prime2 + h ^= h >> 29 + h *= prime3 + h ^= h >> 32 + + return h +} + +func writeBlocks(d *Digest, b []byte) int { + v1, v2, v3, v4 := d.v1, d.v2, d.v3, d.v4 + n := len(b) + for len(b) >= 32 { + v1 = round(v1, u64(b[0:8:len(b)])) + v2 = round(v2, u64(b[8:16:len(b)])) + v3 = round(v3, u64(b[16:24:len(b)])) + v4 = round(v4, u64(b[24:32:len(b)])) + b = b[32:len(b):len(b)] + } + d.v1, d.v2, d.v3, d.v4 = v1, v2, v3, v4 + return n - len(b) +} diff --git a/vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash_safe.go b/vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash_safe.go new file mode 100644 index 000000000..6f3b0cb10 --- /dev/null +++ b/vendor/github.com/klauspost/compress/zstd/internal/xxhash/xxhash_safe.go @@ -0,0 +1,11 @@ +package xxhash + +// Sum64String computes the 64-bit xxHash digest of s. +func Sum64String(s string) uint64 { + return Sum64([]byte(s)) +} + +// WriteString adds more data to d. It always returns len(s), nil. +func (d *Digest) WriteString(s string) (n int, err error) { + return d.Write([]byte(s)) +} diff --git a/vendor/github.com/klauspost/compress/zstd/matchlen_amd64.go b/vendor/github.com/klauspost/compress/zstd/matchlen_amd64.go new file mode 100644 index 000000000..f41932b7a --- /dev/null +++ b/vendor/github.com/klauspost/compress/zstd/matchlen_amd64.go @@ -0,0 +1,16 @@ +//go:build amd64 && !appengine && !noasm && gc +// +build amd64,!appengine,!noasm,gc + +// Copyright 2019+ Klaus Post. All rights reserved. +// License information can be found in the LICENSE file. + +package zstd + +// matchLen returns how many bytes match in a and b +// +// It assumes that: +// +// len(a) <= len(b) and len(a) > 0 +// +//go:noescape +func matchLen(a []byte, b []byte) int diff --git a/vendor/github.com/klauspost/compress/zstd/matchlen_amd64.s b/vendor/github.com/klauspost/compress/zstd/matchlen_amd64.s new file mode 100644 index 000000000..0782b86e3 --- /dev/null +++ b/vendor/github.com/klauspost/compress/zstd/matchlen_amd64.s @@ -0,0 +1,66 @@ +// Copied from S2 implementation. + +//go:build !appengine && !noasm && gc && !noasm + +#include "textflag.h" + +// func matchLen(a []byte, b []byte) int +TEXT ·matchLen(SB), NOSPLIT, $0-56 + MOVQ a_base+0(FP), AX + MOVQ b_base+24(FP), CX + MOVQ a_len+8(FP), DX + + // matchLen + XORL SI, SI + CMPL DX, $0x08 + JB matchlen_match4_standalone + +matchlen_loopback_standalone: + MOVQ (AX)(SI*1), BX + XORQ (CX)(SI*1), BX + JZ matchlen_loop_standalone + +#ifdef GOAMD64_v3 + TZCNTQ BX, BX +#else + BSFQ BX, BX +#endif + SHRL $0x03, BX + LEAL (SI)(BX*1), SI + JMP gen_match_len_end + +matchlen_loop_standalone: + LEAL -8(DX), DX + LEAL 8(SI), SI + CMPL DX, $0x08 + JAE matchlen_loopback_standalone + +matchlen_match4_standalone: + CMPL DX, $0x04 + JB matchlen_match2_standalone + MOVL (AX)(SI*1), BX + CMPL (CX)(SI*1), BX + JNE matchlen_match2_standalone + LEAL -4(DX), DX + LEAL 4(SI), SI + +matchlen_match2_standalone: + CMPL DX, $0x02 + JB matchlen_match1_standalone + MOVW (AX)(SI*1), BX + CMPW (CX)(SI*1), BX + JNE matchlen_match1_standalone + LEAL -2(DX), DX + LEAL 2(SI), SI + +matchlen_match1_standalone: + CMPL DX, $0x01 + JB gen_match_len_end + MOVB (AX)(SI*1), BL + CMPB (CX)(SI*1), BL + JNE gen_match_len_end + INCL SI + +gen_match_len_end: + MOVQ SI, ret+48(FP) + RET diff --git a/vendor/github.com/klauspost/compress/zstd/matchlen_generic.go b/vendor/github.com/klauspost/compress/zstd/matchlen_generic.go new file mode 100644 index 000000000..57b9c31c0 --- /dev/null +++ b/vendor/github.com/klauspost/compress/zstd/matchlen_generic.go @@ -0,0 +1,33 @@ +//go:build !amd64 || appengine || !gc || noasm +// +build !amd64 appengine !gc noasm + +// Copyright 2019+ Klaus Post. All rights reserved. +// License information can be found in the LICENSE file. + +package zstd + +import ( + "encoding/binary" + "math/bits" +) + +// matchLen returns the maximum common prefix length of a and b. +// a must be the shortest of the two. +func matchLen(a, b []byte) (n int) { + for ; len(a) >= 8 && len(b) >= 8; a, b = a[8:], b[8:] { + diff := binary.LittleEndian.Uint64(a) ^ binary.LittleEndian.Uint64(b) + if diff != 0 { + return n + bits.TrailingZeros64(diff)>>3 + } + n += 8 + } + + for i := range a { + if a[i] != b[i] { + break + } + n++ + } + return n + +} diff --git a/vendor/github.com/klauspost/compress/zstd/seqdec.go b/vendor/github.com/klauspost/compress/zstd/seqdec.go new file mode 100644 index 000000000..d7fe6d82d --- /dev/null +++ b/vendor/github.com/klauspost/compress/zstd/seqdec.go @@ -0,0 +1,503 @@ +// Copyright 2019+ Klaus Post. All rights reserved. +// License information can be found in the LICENSE file. +// Based on work by Yann Collet, released under BSD License. + +package zstd + +import ( + "errors" + "fmt" + "io" +) + +type seq struct { + litLen uint32 + matchLen uint32 + offset uint32 + + // Codes are stored here for the encoder + // so they only have to be looked up once. + llCode, mlCode, ofCode uint8 +} + +type seqVals struct { + ll, ml, mo int +} + +func (s seq) String() string { + if s.offset <= 3 { + if s.offset == 0 { + return fmt.Sprint("litLen:", s.litLen, ", matchLen:", s.matchLen+zstdMinMatch, ", offset: INVALID (0)") + } + return fmt.Sprint("litLen:", s.litLen, ", matchLen:", s.matchLen+zstdMinMatch, ", offset:", s.offset, " (repeat)") + } + return fmt.Sprint("litLen:", s.litLen, ", matchLen:", s.matchLen+zstdMinMatch, ", offset:", s.offset-3, " (new)") +} + +type seqCompMode uint8 + +const ( + compModePredefined seqCompMode = iota + compModeRLE + compModeFSE + compModeRepeat +) + +type sequenceDec struct { + // decoder keeps track of the current state and updates it from the bitstream. + fse *fseDecoder + state fseState + repeat bool +} + +// init the state of the decoder with input from stream. +func (s *sequenceDec) init(br *bitReader) error { + if s.fse == nil { + return errors.New("sequence decoder not defined") + } + s.state.init(br, s.fse.actualTableLog, s.fse.dt[:1< cap(s.out) { + addBytes := s.seqSize + len(s.out) + s.out = append(s.out, make([]byte, addBytes)...) + s.out = s.out[:len(s.out)-addBytes] + } + + if debugDecoder { + printf("Execute %d seqs with hist %d, dict %d, literals: %d into %d bytes\n", len(seqs), len(hist), len(s.dict), len(s.literals), s.seqSize) + } + + var t = len(s.out) + out := s.out[:t+s.seqSize] + + for _, seq := range seqs { + // Add literals + copy(out[t:], s.literals[:seq.ll]) + t += seq.ll + s.literals = s.literals[seq.ll:] + + // Copy from dictionary... + if seq.mo > t+len(hist) || seq.mo > s.windowSize { + if len(s.dict) == 0 { + return fmt.Errorf("match offset (%d) bigger than current history (%d)", seq.mo, t+len(hist)) + } + + // we may be in dictionary. + dictO := len(s.dict) - (seq.mo - (t + len(hist))) + if dictO < 0 || dictO >= len(s.dict) { + return fmt.Errorf("match offset (%d) bigger than current history+dict (%d)", seq.mo, t+len(hist)+len(s.dict)) + } + end := dictO + seq.ml + if end > len(s.dict) { + n := len(s.dict) - dictO + copy(out[t:], s.dict[dictO:]) + t += n + seq.ml -= n + } else { + copy(out[t:], s.dict[dictO:end]) + t += end - dictO + continue + } + } + + // Copy from history. + if v := seq.mo - t; v > 0 { + // v is the start position in history from end. + start := len(hist) - v + if seq.ml > v { + // Some goes into current block. + // Copy remainder of history + copy(out[t:], hist[start:]) + t += v + seq.ml -= v + } else { + copy(out[t:], hist[start:start+seq.ml]) + t += seq.ml + continue + } + } + // We must be in current buffer now + if seq.ml > 0 { + start := t - seq.mo + if seq.ml <= t-start { + // No overlap + copy(out[t:], out[start:start+seq.ml]) + t += seq.ml + continue + } else { + // Overlapping copy + // Extend destination slice and copy one byte at the time. + src := out[start : start+seq.ml] + dst := out[t:] + dst = dst[:len(src)] + t += len(src) + // Destination is the space we just added. + for i := range src { + dst[i] = src[i] + } + } + } + } + + // Add final literals + copy(out[t:], s.literals) + if debugDecoder { + t += len(s.literals) + if t != len(out) { + panic(fmt.Errorf("length mismatch, want %d, got %d, ss: %d", len(out), t, s.seqSize)) + } + } + s.out = out + + return nil +} + +// decode sequences from the stream with the provided history. +func (s *sequenceDecs) decodeSync(hist []byte) error { + supported, err := s.decodeSyncSimple(hist) + if supported { + return err + } + + br := s.br + seqs := s.nSeqs + startSize := len(s.out) + // Grab full sizes tables, to avoid bounds checks. + llTable, mlTable, ofTable := s.litLengths.fse.dt[:maxTablesize], s.matchLengths.fse.dt[:maxTablesize], s.offsets.fse.dt[:maxTablesize] + llState, mlState, ofState := s.litLengths.state.state, s.matchLengths.state.state, s.offsets.state.state + out := s.out + maxBlockSize := maxCompressedBlockSize + if s.windowSize < maxBlockSize { + maxBlockSize = s.windowSize + } + + if debugDecoder { + println("decodeSync: decoding", seqs, "sequences", br.remain(), "bits remain on stream") + } + for i := seqs - 1; i >= 0; i-- { + if br.overread() { + printf("reading sequence %d, exceeded available data. Overread by %d\n", seqs-i, -br.remain()) + return io.ErrUnexpectedEOF + } + var ll, mo, ml int + if len(br.in) > 4+((maxOffsetBits+16+16)>>3) { + // inlined function: + // ll, mo, ml = s.nextFast(br, llState, mlState, ofState) + + // Final will not read from stream. + var llB, mlB, moB uint8 + ll, llB = llState.final() + ml, mlB = mlState.final() + mo, moB = ofState.final() + + // extra bits are stored in reverse order. + br.fillFast() + mo += br.getBits(moB) + if s.maxBits > 32 { + br.fillFast() + } + ml += br.getBits(mlB) + ll += br.getBits(llB) + + if moB > 1 { + s.prevOffset[2] = s.prevOffset[1] + s.prevOffset[1] = s.prevOffset[0] + s.prevOffset[0] = mo + } else { + // mo = s.adjustOffset(mo, ll, moB) + // Inlined for rather big speedup + if ll == 0 { + // There is an exception though, when current sequence's literals_length = 0. + // In this case, repeated offsets are shifted by one, so an offset_value of 1 means Repeated_Offset2, + // an offset_value of 2 means Repeated_Offset3, and an offset_value of 3 means Repeated_Offset1 - 1_byte. + mo++ + } + + if mo == 0 { + mo = s.prevOffset[0] + } else { + var temp int + if mo == 3 { + temp = s.prevOffset[0] - 1 + } else { + temp = s.prevOffset[mo] + } + + if temp == 0 { + // 0 is not valid; input is corrupted; force offset to 1 + println("WARNING: temp was 0") + temp = 1 + } + + if mo != 1 { + s.prevOffset[2] = s.prevOffset[1] + } + s.prevOffset[1] = s.prevOffset[0] + s.prevOffset[0] = temp + mo = temp + } + } + br.fillFast() + } else { + ll, mo, ml = s.next(br, llState, mlState, ofState) + br.fill() + } + + if debugSequences { + println("Seq", seqs-i-1, "Litlen:", ll, "mo:", mo, "(abs) ml:", ml) + } + + if ll > len(s.literals) { + return fmt.Errorf("unexpected literal count, want %d bytes, but only %d is available", ll, len(s.literals)) + } + size := ll + ml + len(out) + if size-startSize > maxBlockSize { + return fmt.Errorf("output bigger than max block size (%d)", maxBlockSize) + } + if size > cap(out) { + // Not enough size, which can happen under high volume block streaming conditions + // but could be if destination slice is too small for sync operations. + // over-allocating here can create a large amount of GC pressure so we try to keep + // it as contained as possible + used := len(out) - startSize + addBytes := 256 + ll + ml + used>>2 + // Clamp to max block size. + if used+addBytes > maxBlockSize { + addBytes = maxBlockSize - used + } + out = append(out, make([]byte, addBytes)...) + out = out[:len(out)-addBytes] + } + if ml > maxMatchLen { + return fmt.Errorf("match len (%d) bigger than max allowed length", ml) + } + + // Add literals + out = append(out, s.literals[:ll]...) + s.literals = s.literals[ll:] + + if mo == 0 && ml > 0 { + return fmt.Errorf("zero matchoff and matchlen (%d) > 0", ml) + } + + if mo > len(out)+len(hist) || mo > s.windowSize { + if len(s.dict) == 0 { + return fmt.Errorf("match offset (%d) bigger than current history (%d)", mo, len(out)+len(hist)-startSize) + } + + // we may be in dictionary. + dictO := len(s.dict) - (mo - (len(out) + len(hist))) + if dictO < 0 || dictO >= len(s.dict) { + return fmt.Errorf("match offset (%d) bigger than current history (%d)", mo, len(out)+len(hist)-startSize) + } + end := dictO + ml + if end > len(s.dict) { + out = append(out, s.dict[dictO:]...) + ml -= len(s.dict) - dictO + } else { + out = append(out, s.dict[dictO:end]...) + mo = 0 + ml = 0 + } + } + + // Copy from history. + // TODO: Blocks without history could be made to ignore this completely. + if v := mo - len(out); v > 0 { + // v is the start position in history from end. + start := len(hist) - v + if ml > v { + // Some goes into current block. + // Copy remainder of history + out = append(out, hist[start:]...) + ml -= v + } else { + out = append(out, hist[start:start+ml]...) + ml = 0 + } + } + // We must be in current buffer now + if ml > 0 { + start := len(out) - mo + if ml <= len(out)-start { + // No overlap + out = append(out, out[start:start+ml]...) + } else { + // Overlapping copy + // Extend destination slice and copy one byte at the time. + out = out[:len(out)+ml] + src := out[start : start+ml] + // Destination is the space we just added. + dst := out[len(out)-ml:] + dst = dst[:len(src)] + for i := range src { + dst[i] = src[i] + } + } + } + if i == 0 { + // This is the last sequence, so we shouldn't update state. + break + } + + // Manually inlined, ~ 5-20% faster + // Update all 3 states at once. Approx 20% faster. + nBits := llState.nbBits() + mlState.nbBits() + ofState.nbBits() + if nBits == 0 { + llState = llTable[llState.newState()&maxTableMask] + mlState = mlTable[mlState.newState()&maxTableMask] + ofState = ofTable[ofState.newState()&maxTableMask] + } else { + bits := br.get32BitsFast(nBits) + + lowBits := uint16(bits >> ((ofState.nbBits() + mlState.nbBits()) & 31)) + llState = llTable[(llState.newState()+lowBits)&maxTableMask] + + lowBits = uint16(bits >> (ofState.nbBits() & 31)) + lowBits &= bitMask[mlState.nbBits()&15] + mlState = mlTable[(mlState.newState()+lowBits)&maxTableMask] + + lowBits = uint16(bits) & bitMask[ofState.nbBits()&15] + ofState = ofTable[(ofState.newState()+lowBits)&maxTableMask] + } + } + + if size := len(s.literals) + len(out) - startSize; size > maxBlockSize { + return fmt.Errorf("output bigger than max block size (%d)", maxBlockSize) + } + + // Add final literals + s.out = append(out, s.literals...) + return br.close() +} + +var bitMask [16]uint16 + +func init() { + for i := range bitMask[:] { + bitMask[i] = uint16((1 << uint(i)) - 1) + } +} + +func (s *sequenceDecs) next(br *bitReader, llState, mlState, ofState decSymbol) (ll, mo, ml int) { + // Final will not read from stream. + ll, llB := llState.final() + ml, mlB := mlState.final() + mo, moB := ofState.final() + + // extra bits are stored in reverse order. + br.fill() + mo += br.getBits(moB) + if s.maxBits > 32 { + br.fill() + } + // matchlength+literal length, max 32 bits + ml += br.getBits(mlB) + ll += br.getBits(llB) + mo = s.adjustOffset(mo, ll, moB) + return +} + +func (s *sequenceDecs) adjustOffset(offset, litLen int, offsetB uint8) int { + if offsetB > 1 { + s.prevOffset[2] = s.prevOffset[1] + s.prevOffset[1] = s.prevOffset[0] + s.prevOffset[0] = offset + return offset + } + + if litLen == 0 { + // There is an exception though, when current sequence's literals_length = 0. + // In this case, repeated offsets are shifted by one, so an offset_value of 1 means Repeated_Offset2, + // an offset_value of 2 means Repeated_Offset3, and an offset_value of 3 means Repeated_Offset1 - 1_byte. + offset++ + } + + if offset == 0 { + return s.prevOffset[0] + } + var temp int + if offset == 3 { + temp = s.prevOffset[0] - 1 + } else { + temp = s.prevOffset[offset] + } + + if temp == 0 { + // 0 is not valid; input is corrupted; force offset to 1 + println("temp was 0") + temp = 1 + } + + if offset != 1 { + s.prevOffset[2] = s.prevOffset[1] + } + s.prevOffset[1] = s.prevOffset[0] + s.prevOffset[0] = temp + return temp +} diff --git a/vendor/github.com/klauspost/compress/zstd/seqdec_amd64.go b/vendor/github.com/klauspost/compress/zstd/seqdec_amd64.go new file mode 100644 index 000000000..8adabd828 --- /dev/null +++ b/vendor/github.com/klauspost/compress/zstd/seqdec_amd64.go @@ -0,0 +1,394 @@ +//go:build amd64 && !appengine && !noasm && gc +// +build amd64,!appengine,!noasm,gc + +package zstd + +import ( + "fmt" + "io" + + "github.com/klauspost/compress/internal/cpuinfo" +) + +type decodeSyncAsmContext struct { + llTable []decSymbol + mlTable []decSymbol + ofTable []decSymbol + llState uint64 + mlState uint64 + ofState uint64 + iteration int + litRemain int + out []byte + outPosition int + literals []byte + litPosition int + history []byte + windowSize int + ll int // set on error (not for all errors, please refer to _generate/gen.go) + ml int // set on error (not for all errors, please refer to _generate/gen.go) + mo int // set on error (not for all errors, please refer to _generate/gen.go) +} + +// sequenceDecs_decodeSync_amd64 implements the main loop of sequenceDecs.decodeSync in x86 asm. +// +// Please refer to seqdec_generic.go for the reference implementation. +// +//go:noescape +func sequenceDecs_decodeSync_amd64(s *sequenceDecs, br *bitReader, ctx *decodeSyncAsmContext) int + +// sequenceDecs_decodeSync_bmi2 implements the main loop of sequenceDecs.decodeSync in x86 asm with BMI2 extensions. +// +//go:noescape +func sequenceDecs_decodeSync_bmi2(s *sequenceDecs, br *bitReader, ctx *decodeSyncAsmContext) int + +// sequenceDecs_decodeSync_safe_amd64 does the same as above, but does not write more than output buffer. +// +//go:noescape +func sequenceDecs_decodeSync_safe_amd64(s *sequenceDecs, br *bitReader, ctx *decodeSyncAsmContext) int + +// sequenceDecs_decodeSync_safe_bmi2 does the same as above, but does not write more than output buffer. +// +//go:noescape +func sequenceDecs_decodeSync_safe_bmi2(s *sequenceDecs, br *bitReader, ctx *decodeSyncAsmContext) int + +// decode sequences from the stream with the provided history but without a dictionary. +func (s *sequenceDecs) decodeSyncSimple(hist []byte) (bool, error) { + if len(s.dict) > 0 { + return false, nil + } + if s.maxSyncLen == 0 && cap(s.out)-len(s.out) < maxCompressedBlockSize { + return false, nil + } + + // FIXME: Using unsafe memory copies leads to rare, random crashes + // with fuzz testing. It is therefore disabled for now. + const useSafe = true + /* + useSafe := false + if s.maxSyncLen == 0 && cap(s.out)-len(s.out) < maxCompressedBlockSizeAlloc { + useSafe = true + } + if s.maxSyncLen > 0 && cap(s.out)-len(s.out)-compressedBlockOverAlloc < int(s.maxSyncLen) { + useSafe = true + } + if cap(s.literals) < len(s.literals)+compressedBlockOverAlloc { + useSafe = true + } + */ + + br := s.br + + maxBlockSize := maxCompressedBlockSize + if s.windowSize < maxBlockSize { + maxBlockSize = s.windowSize + } + + ctx := decodeSyncAsmContext{ + llTable: s.litLengths.fse.dt[:maxTablesize], + mlTable: s.matchLengths.fse.dt[:maxTablesize], + ofTable: s.offsets.fse.dt[:maxTablesize], + llState: uint64(s.litLengths.state.state), + mlState: uint64(s.matchLengths.state.state), + ofState: uint64(s.offsets.state.state), + iteration: s.nSeqs - 1, + litRemain: len(s.literals), + out: s.out, + outPosition: len(s.out), + literals: s.literals, + windowSize: s.windowSize, + history: hist, + } + + s.seqSize = 0 + startSize := len(s.out) + + var errCode int + if cpuinfo.HasBMI2() { + if useSafe { + errCode = sequenceDecs_decodeSync_safe_bmi2(s, br, &ctx) + } else { + errCode = sequenceDecs_decodeSync_bmi2(s, br, &ctx) + } + } else { + if useSafe { + errCode = sequenceDecs_decodeSync_safe_amd64(s, br, &ctx) + } else { + errCode = sequenceDecs_decodeSync_amd64(s, br, &ctx) + } + } + switch errCode { + case noError: + break + + case errorMatchLenOfsMismatch: + return true, fmt.Errorf("zero matchoff and matchlen (%d) > 0", ctx.ml) + + case errorMatchLenTooBig: + return true, fmt.Errorf("match len (%d) bigger than max allowed length", ctx.ml) + + case errorMatchOffTooBig: + return true, fmt.Errorf("match offset (%d) bigger than current history (%d)", + ctx.mo, ctx.outPosition+len(hist)-startSize) + + case errorNotEnoughLiterals: + return true, fmt.Errorf("unexpected literal count, want %d bytes, but only %d is available", + ctx.ll, ctx.litRemain+ctx.ll) + + case errorOverread: + return true, io.ErrUnexpectedEOF + + case errorNotEnoughSpace: + size := ctx.outPosition + ctx.ll + ctx.ml + if debugDecoder { + println("msl:", s.maxSyncLen, "cap", cap(s.out), "bef:", startSize, "sz:", size-startSize, "mbs:", maxBlockSize, "outsz:", cap(s.out)-startSize) + } + return true, fmt.Errorf("output bigger than max block size (%d)", maxBlockSize) + + default: + return true, fmt.Errorf("sequenceDecs_decode returned erronous code %d", errCode) + } + + s.seqSize += ctx.litRemain + if s.seqSize > maxBlockSize { + return true, fmt.Errorf("output bigger than max block size (%d)", maxBlockSize) + } + err := br.close() + if err != nil { + printf("Closing sequences: %v, %+v\n", err, *br) + return true, err + } + + s.literals = s.literals[ctx.litPosition:] + t := ctx.outPosition + s.out = s.out[:t] + + // Add final literals + s.out = append(s.out, s.literals...) + if debugDecoder { + t += len(s.literals) + if t != len(s.out) { + panic(fmt.Errorf("length mismatch, want %d, got %d", len(s.out), t)) + } + } + + return true, nil +} + +// -------------------------------------------------------------------------------- + +type decodeAsmContext struct { + llTable []decSymbol + mlTable []decSymbol + ofTable []decSymbol + llState uint64 + mlState uint64 + ofState uint64 + iteration int + seqs []seqVals + litRemain int +} + +const noError = 0 + +// error reported when mo == 0 && ml > 0 +const errorMatchLenOfsMismatch = 1 + +// error reported when ml > maxMatchLen +const errorMatchLenTooBig = 2 + +// error reported when mo > available history or mo > s.windowSize +const errorMatchOffTooBig = 3 + +// error reported when the sum of literal lengths exeeceds the literal buffer size +const errorNotEnoughLiterals = 4 + +// error reported when capacity of `out` is too small +const errorNotEnoughSpace = 5 + +// error reported when bits are overread. +const errorOverread = 6 + +// sequenceDecs_decode implements the main loop of sequenceDecs in x86 asm. +// +// Please refer to seqdec_generic.go for the reference implementation. +// +//go:noescape +func sequenceDecs_decode_amd64(s *sequenceDecs, br *bitReader, ctx *decodeAsmContext) int + +// sequenceDecs_decode implements the main loop of sequenceDecs in x86 asm. +// +// Please refer to seqdec_generic.go for the reference implementation. +// +//go:noescape +func sequenceDecs_decode_56_amd64(s *sequenceDecs, br *bitReader, ctx *decodeAsmContext) int + +// sequenceDecs_decode implements the main loop of sequenceDecs in x86 asm with BMI2 extensions. +// +//go:noescape +func sequenceDecs_decode_bmi2(s *sequenceDecs, br *bitReader, ctx *decodeAsmContext) int + +// sequenceDecs_decode implements the main loop of sequenceDecs in x86 asm with BMI2 extensions. +// +//go:noescape +func sequenceDecs_decode_56_bmi2(s *sequenceDecs, br *bitReader, ctx *decodeAsmContext) int + +// decode sequences from the stream without the provided history. +func (s *sequenceDecs) decode(seqs []seqVals) error { + br := s.br + + maxBlockSize := maxCompressedBlockSize + if s.windowSize < maxBlockSize { + maxBlockSize = s.windowSize + } + + ctx := decodeAsmContext{ + llTable: s.litLengths.fse.dt[:maxTablesize], + mlTable: s.matchLengths.fse.dt[:maxTablesize], + ofTable: s.offsets.fse.dt[:maxTablesize], + llState: uint64(s.litLengths.state.state), + mlState: uint64(s.matchLengths.state.state), + ofState: uint64(s.offsets.state.state), + seqs: seqs, + iteration: len(seqs) - 1, + litRemain: len(s.literals), + } + + if debugDecoder { + println("decode: decoding", len(seqs), "sequences", br.remain(), "bits remain on stream") + } + + s.seqSize = 0 + lte56bits := s.maxBits+s.offsets.fse.actualTableLog+s.matchLengths.fse.actualTableLog+s.litLengths.fse.actualTableLog <= 56 + var errCode int + if cpuinfo.HasBMI2() { + if lte56bits { + errCode = sequenceDecs_decode_56_bmi2(s, br, &ctx) + } else { + errCode = sequenceDecs_decode_bmi2(s, br, &ctx) + } + } else { + if lte56bits { + errCode = sequenceDecs_decode_56_amd64(s, br, &ctx) + } else { + errCode = sequenceDecs_decode_amd64(s, br, &ctx) + } + } + if errCode != 0 { + i := len(seqs) - ctx.iteration - 1 + switch errCode { + case errorMatchLenOfsMismatch: + ml := ctx.seqs[i].ml + return fmt.Errorf("zero matchoff and matchlen (%d) > 0", ml) + + case errorMatchLenTooBig: + ml := ctx.seqs[i].ml + return fmt.Errorf("match len (%d) bigger than max allowed length", ml) + + case errorNotEnoughLiterals: + ll := ctx.seqs[i].ll + return fmt.Errorf("unexpected literal count, want %d bytes, but only %d is available", ll, ctx.litRemain+ll) + case errorOverread: + return io.ErrUnexpectedEOF + } + + return fmt.Errorf("sequenceDecs_decode_amd64 returned erronous code %d", errCode) + } + + if ctx.litRemain < 0 { + return fmt.Errorf("literal count is too big: total available %d, total requested %d", + len(s.literals), len(s.literals)-ctx.litRemain) + } + + s.seqSize += ctx.litRemain + if s.seqSize > maxBlockSize { + return fmt.Errorf("output bigger than max block size (%d)", maxBlockSize) + } + if debugDecoder { + println("decode: ", br.remain(), "bits remain on stream. code:", errCode) + } + err := br.close() + if err != nil { + printf("Closing sequences: %v, %+v\n", err, *br) + } + return err +} + +// -------------------------------------------------------------------------------- + +type executeAsmContext struct { + seqs []seqVals + seqIndex int + out []byte + history []byte + literals []byte + outPosition int + litPosition int + windowSize int +} + +// sequenceDecs_executeSimple_amd64 implements the main loop of sequenceDecs.executeSimple in x86 asm. +// +// Returns false if a match offset is too big. +// +// Please refer to seqdec_generic.go for the reference implementation. +// +//go:noescape +func sequenceDecs_executeSimple_amd64(ctx *executeAsmContext) bool + +// Same as above, but with safe memcopies +// +//go:noescape +func sequenceDecs_executeSimple_safe_amd64(ctx *executeAsmContext) bool + +// executeSimple handles cases when dictionary is not used. +func (s *sequenceDecs) executeSimple(seqs []seqVals, hist []byte) error { + // Ensure we have enough output size... + if len(s.out)+s.seqSize+compressedBlockOverAlloc > cap(s.out) { + addBytes := s.seqSize + len(s.out) + compressedBlockOverAlloc + s.out = append(s.out, make([]byte, addBytes)...) + s.out = s.out[:len(s.out)-addBytes] + } + + if debugDecoder { + printf("Execute %d seqs with literals: %d into %d bytes\n", len(seqs), len(s.literals), s.seqSize) + } + + var t = len(s.out) + out := s.out[:t+s.seqSize] + + ctx := executeAsmContext{ + seqs: seqs, + seqIndex: 0, + out: out, + history: hist, + outPosition: t, + litPosition: 0, + literals: s.literals, + windowSize: s.windowSize, + } + var ok bool + if cap(s.literals) < len(s.literals)+compressedBlockOverAlloc { + ok = sequenceDecs_executeSimple_safe_amd64(&ctx) + } else { + ok = sequenceDecs_executeSimple_amd64(&ctx) + } + if !ok { + return fmt.Errorf("match offset (%d) bigger than current history (%d)", + seqs[ctx.seqIndex].mo, ctx.outPosition+len(hist)) + } + s.literals = s.literals[ctx.litPosition:] + t = ctx.outPosition + + // Add final literals + copy(out[t:], s.literals) + if debugDecoder { + t += len(s.literals) + if t != len(out) { + panic(fmt.Errorf("length mismatch, want %d, got %d, ss: %d", len(out), t, s.seqSize)) + } + } + s.out = out + + return nil +} diff --git a/vendor/github.com/klauspost/compress/zstd/seqdec_amd64.s b/vendor/github.com/klauspost/compress/zstd/seqdec_amd64.s new file mode 100644 index 000000000..5b06174b8 --- /dev/null +++ b/vendor/github.com/klauspost/compress/zstd/seqdec_amd64.s @@ -0,0 +1,4151 @@ +// Code generated by command: go run gen.go -out ../seqdec_amd64.s -pkg=zstd. DO NOT EDIT. + +//go:build !appengine && !noasm && gc && !noasm + +// func sequenceDecs_decode_amd64(s *sequenceDecs, br *bitReader, ctx *decodeAsmContext) int +// Requires: CMOV +TEXT ·sequenceDecs_decode_amd64(SB), $8-32 + MOVQ br+8(FP), CX + MOVQ 24(CX), DX + MOVBQZX 32(CX), BX + MOVQ (CX), AX + MOVQ 8(CX), SI + ADDQ SI, AX + MOVQ AX, (SP) + MOVQ ctx+16(FP), AX + MOVQ 72(AX), DI + MOVQ 80(AX), R8 + MOVQ 88(AX), R9 + MOVQ 104(AX), R10 + MOVQ s+0(FP), AX + MOVQ 144(AX), R11 + MOVQ 152(AX), R12 + MOVQ 160(AX), R13 + +sequenceDecs_decode_amd64_main_loop: + MOVQ (SP), R14 + + // Fill bitreader to have enough for the offset and match length. + CMPQ SI, $0x08 + JL sequenceDecs_decode_amd64_fill_byte_by_byte + MOVQ BX, AX + SHRQ $0x03, AX + SUBQ AX, R14 + MOVQ (R14), DX + SUBQ AX, SI + ANDQ $0x07, BX + JMP sequenceDecs_decode_amd64_fill_end + +sequenceDecs_decode_amd64_fill_byte_by_byte: + CMPQ SI, $0x00 + JLE sequenceDecs_decode_amd64_fill_check_overread + CMPQ BX, $0x07 + JLE sequenceDecs_decode_amd64_fill_end + SHLQ $0x08, DX + SUBQ $0x01, R14 + SUBQ $0x01, SI + SUBQ $0x08, BX + MOVBQZX (R14), AX + ORQ AX, DX + JMP sequenceDecs_decode_amd64_fill_byte_by_byte + +sequenceDecs_decode_amd64_fill_check_overread: + CMPQ BX, $0x40 + JA error_overread + +sequenceDecs_decode_amd64_fill_end: + // Update offset + MOVQ R9, AX + MOVQ BX, CX + MOVQ DX, R15 + SHLQ CL, R15 + MOVB AH, CL + SHRQ $0x20, AX + TESTQ CX, CX + JZ sequenceDecs_decode_amd64_of_update_zero + ADDQ CX, BX + CMPQ BX, $0x40 + JA sequenceDecs_decode_amd64_of_update_zero + CMPQ CX, $0x40 + JAE sequenceDecs_decode_amd64_of_update_zero + NEGQ CX + SHRQ CL, R15 + ADDQ R15, AX + +sequenceDecs_decode_amd64_of_update_zero: + MOVQ AX, 16(R10) + + // Update match length + MOVQ R8, AX + MOVQ BX, CX + MOVQ DX, R15 + SHLQ CL, R15 + MOVB AH, CL + SHRQ $0x20, AX + TESTQ CX, CX + JZ sequenceDecs_decode_amd64_ml_update_zero + ADDQ CX, BX + CMPQ BX, $0x40 + JA sequenceDecs_decode_amd64_ml_update_zero + CMPQ CX, $0x40 + JAE sequenceDecs_decode_amd64_ml_update_zero + NEGQ CX + SHRQ CL, R15 + ADDQ R15, AX + +sequenceDecs_decode_amd64_ml_update_zero: + MOVQ AX, 8(R10) + + // Fill bitreader to have enough for the remaining + CMPQ SI, $0x08 + JL sequenceDecs_decode_amd64_fill_2_byte_by_byte + MOVQ BX, AX + SHRQ $0x03, AX + SUBQ AX, R14 + MOVQ (R14), DX + SUBQ AX, SI + ANDQ $0x07, BX + JMP sequenceDecs_decode_amd64_fill_2_end + +sequenceDecs_decode_amd64_fill_2_byte_by_byte: + CMPQ SI, $0x00 + JLE sequenceDecs_decode_amd64_fill_2_check_overread + CMPQ BX, $0x07 + JLE sequenceDecs_decode_amd64_fill_2_end + SHLQ $0x08, DX + SUBQ $0x01, R14 + SUBQ $0x01, SI + SUBQ $0x08, BX + MOVBQZX (R14), AX + ORQ AX, DX + JMP sequenceDecs_decode_amd64_fill_2_byte_by_byte + +sequenceDecs_decode_amd64_fill_2_check_overread: + CMPQ BX, $0x40 + JA error_overread + +sequenceDecs_decode_amd64_fill_2_end: + // Update literal length + MOVQ DI, AX + MOVQ BX, CX + MOVQ DX, R15 + SHLQ CL, R15 + MOVB AH, CL + SHRQ $0x20, AX + TESTQ CX, CX + JZ sequenceDecs_decode_amd64_ll_update_zero + ADDQ CX, BX + CMPQ BX, $0x40 + JA sequenceDecs_decode_amd64_ll_update_zero + CMPQ CX, $0x40 + JAE sequenceDecs_decode_amd64_ll_update_zero + NEGQ CX + SHRQ CL, R15 + ADDQ R15, AX + +sequenceDecs_decode_amd64_ll_update_zero: + MOVQ AX, (R10) + + // Fill bitreader for state updates + MOVQ R14, (SP) + MOVQ R9, AX + SHRQ $0x08, AX + MOVBQZX AL, AX + MOVQ ctx+16(FP), CX + CMPQ 96(CX), $0x00 + JZ sequenceDecs_decode_amd64_skip_update + + // Update Literal Length State + MOVBQZX DI, R14 + SHRL $0x10, DI + LEAQ (BX)(R14*1), CX + MOVQ DX, R15 + MOVQ CX, BX + ROLQ CL, R15 + MOVL $0x00000001, BP + MOVB R14, CL + SHLL CL, BP + DECL BP + ANDQ BP, R15 + ADDQ R15, DI + + // Load ctx.llTable + MOVQ ctx+16(FP), CX + MOVQ (CX), CX + MOVQ (CX)(DI*8), DI + + // Update Match Length State + MOVBQZX R8, R14 + SHRL $0x10, R8 + LEAQ (BX)(R14*1), CX + MOVQ DX, R15 + MOVQ CX, BX + ROLQ CL, R15 + MOVL $0x00000001, BP + MOVB R14, CL + SHLL CL, BP + DECL BP + ANDQ BP, R15 + ADDQ R15, R8 + + // Load ctx.mlTable + MOVQ ctx+16(FP), CX + MOVQ 24(CX), CX + MOVQ (CX)(R8*8), R8 + + // Update Offset State + MOVBQZX R9, R14 + SHRL $0x10, R9 + LEAQ (BX)(R14*1), CX + MOVQ DX, R15 + MOVQ CX, BX + ROLQ CL, R15 + MOVL $0x00000001, BP + MOVB R14, CL + SHLL CL, BP + DECL BP + ANDQ BP, R15 + ADDQ R15, R9 + + // Load ctx.ofTable + MOVQ ctx+16(FP), CX + MOVQ 48(CX), CX + MOVQ (CX)(R9*8), R9 + +sequenceDecs_decode_amd64_skip_update: + // Adjust offset + MOVQ 16(R10), CX + CMPQ AX, $0x01 + JBE sequenceDecs_decode_amd64_adjust_offsetB_1_or_0 + MOVQ R12, R13 + MOVQ R11, R12 + MOVQ CX, R11 + JMP sequenceDecs_decode_amd64_after_adjust + +sequenceDecs_decode_amd64_adjust_offsetB_1_or_0: + CMPQ (R10), $0x00000000 + JNE sequenceDecs_decode_amd64_adjust_offset_maybezero + INCQ CX + JMP sequenceDecs_decode_amd64_adjust_offset_nonzero + +sequenceDecs_decode_amd64_adjust_offset_maybezero: + TESTQ CX, CX + JNZ sequenceDecs_decode_amd64_adjust_offset_nonzero + MOVQ R11, CX + JMP sequenceDecs_decode_amd64_after_adjust + +sequenceDecs_decode_amd64_adjust_offset_nonzero: + CMPQ CX, $0x01 + JB sequenceDecs_decode_amd64_adjust_zero + JEQ sequenceDecs_decode_amd64_adjust_one + CMPQ CX, $0x02 + JA sequenceDecs_decode_amd64_adjust_three + JMP sequenceDecs_decode_amd64_adjust_two + +sequenceDecs_decode_amd64_adjust_zero: + MOVQ R11, AX + JMP sequenceDecs_decode_amd64_adjust_test_temp_valid + +sequenceDecs_decode_amd64_adjust_one: + MOVQ R12, AX + JMP sequenceDecs_decode_amd64_adjust_test_temp_valid + +sequenceDecs_decode_amd64_adjust_two: + MOVQ R13, AX + JMP sequenceDecs_decode_amd64_adjust_test_temp_valid + +sequenceDecs_decode_amd64_adjust_three: + LEAQ -1(R11), AX + +sequenceDecs_decode_amd64_adjust_test_temp_valid: + TESTQ AX, AX + JNZ sequenceDecs_decode_amd64_adjust_temp_valid + MOVQ $0x00000001, AX + +sequenceDecs_decode_amd64_adjust_temp_valid: + CMPQ CX, $0x01 + CMOVQNE R12, R13 + MOVQ R11, R12 + MOVQ AX, R11 + MOVQ AX, CX + +sequenceDecs_decode_amd64_after_adjust: + MOVQ CX, 16(R10) + + // Check values + MOVQ 8(R10), AX + MOVQ (R10), R14 + LEAQ (AX)(R14*1), R15 + MOVQ s+0(FP), BP + ADDQ R15, 256(BP) + MOVQ ctx+16(FP), R15 + SUBQ R14, 128(R15) + JS error_not_enough_literals + CMPQ AX, $0x00020002 + JA sequenceDecs_decode_amd64_error_match_len_too_big + TESTQ CX, CX + JNZ sequenceDecs_decode_amd64_match_len_ofs_ok + TESTQ AX, AX + JNZ sequenceDecs_decode_amd64_error_match_len_ofs_mismatch + +sequenceDecs_decode_amd64_match_len_ofs_ok: + ADDQ $0x18, R10 + MOVQ ctx+16(FP), AX + DECQ 96(AX) + JNS sequenceDecs_decode_amd64_main_loop + MOVQ s+0(FP), AX + MOVQ R11, 144(AX) + MOVQ R12, 152(AX) + MOVQ R13, 160(AX) + MOVQ br+8(FP), AX + MOVQ DX, 24(AX) + MOVB BL, 32(AX) + MOVQ SI, 8(AX) + + // Return success + MOVQ $0x00000000, ret+24(FP) + RET + + // Return with match length error +sequenceDecs_decode_amd64_error_match_len_ofs_mismatch: + MOVQ $0x00000001, ret+24(FP) + RET + + // Return with match too long error +sequenceDecs_decode_amd64_error_match_len_too_big: + MOVQ $0x00000002, ret+24(FP) + RET + + // Return with match offset too long error + MOVQ $0x00000003, ret+24(FP) + RET + + // Return with not enough literals error +error_not_enough_literals: + MOVQ $0x00000004, ret+24(FP) + RET + + // Return with overread error +error_overread: + MOVQ $0x00000006, ret+24(FP) + RET + +// func sequenceDecs_decode_56_amd64(s *sequenceDecs, br *bitReader, ctx *decodeAsmContext) int +// Requires: CMOV +TEXT ·sequenceDecs_decode_56_amd64(SB), $8-32 + MOVQ br+8(FP), CX + MOVQ 24(CX), DX + MOVBQZX 32(CX), BX + MOVQ (CX), AX + MOVQ 8(CX), SI + ADDQ SI, AX + MOVQ AX, (SP) + MOVQ ctx+16(FP), AX + MOVQ 72(AX), DI + MOVQ 80(AX), R8 + MOVQ 88(AX), R9 + MOVQ 104(AX), R10 + MOVQ s+0(FP), AX + MOVQ 144(AX), R11 + MOVQ 152(AX), R12 + MOVQ 160(AX), R13 + +sequenceDecs_decode_56_amd64_main_loop: + MOVQ (SP), R14 + + // Fill bitreader to have enough for the offset and match length. + CMPQ SI, $0x08 + JL sequenceDecs_decode_56_amd64_fill_byte_by_byte + MOVQ BX, AX + SHRQ $0x03, AX + SUBQ AX, R14 + MOVQ (R14), DX + SUBQ AX, SI + ANDQ $0x07, BX + JMP sequenceDecs_decode_56_amd64_fill_end + +sequenceDecs_decode_56_amd64_fill_byte_by_byte: + CMPQ SI, $0x00 + JLE sequenceDecs_decode_56_amd64_fill_check_overread + CMPQ BX, $0x07 + JLE sequenceDecs_decode_56_amd64_fill_end + SHLQ $0x08, DX + SUBQ $0x01, R14 + SUBQ $0x01, SI + SUBQ $0x08, BX + MOVBQZX (R14), AX + ORQ AX, DX + JMP sequenceDecs_decode_56_amd64_fill_byte_by_byte + +sequenceDecs_decode_56_amd64_fill_check_overread: + CMPQ BX, $0x40 + JA error_overread + +sequenceDecs_decode_56_amd64_fill_end: + // Update offset + MOVQ R9, AX + MOVQ BX, CX + MOVQ DX, R15 + SHLQ CL, R15 + MOVB AH, CL + SHRQ $0x20, AX + TESTQ CX, CX + JZ sequenceDecs_decode_56_amd64_of_update_zero + ADDQ CX, BX + CMPQ BX, $0x40 + JA sequenceDecs_decode_56_amd64_of_update_zero + CMPQ CX, $0x40 + JAE sequenceDecs_decode_56_amd64_of_update_zero + NEGQ CX + SHRQ CL, R15 + ADDQ R15, AX + +sequenceDecs_decode_56_amd64_of_update_zero: + MOVQ AX, 16(R10) + + // Update match length + MOVQ R8, AX + MOVQ BX, CX + MOVQ DX, R15 + SHLQ CL, R15 + MOVB AH, CL + SHRQ $0x20, AX + TESTQ CX, CX + JZ sequenceDecs_decode_56_amd64_ml_update_zero + ADDQ CX, BX + CMPQ BX, $0x40 + JA sequenceDecs_decode_56_amd64_ml_update_zero + CMPQ CX, $0x40 + JAE sequenceDecs_decode_56_amd64_ml_update_zero + NEGQ CX + SHRQ CL, R15 + ADDQ R15, AX + +sequenceDecs_decode_56_amd64_ml_update_zero: + MOVQ AX, 8(R10) + + // Update literal length + MOVQ DI, AX + MOVQ BX, CX + MOVQ DX, R15 + SHLQ CL, R15 + MOVB AH, CL + SHRQ $0x20, AX + TESTQ CX, CX + JZ sequenceDecs_decode_56_amd64_ll_update_zero + ADDQ CX, BX + CMPQ BX, $0x40 + JA sequenceDecs_decode_56_amd64_ll_update_zero + CMPQ CX, $0x40 + JAE sequenceDecs_decode_56_amd64_ll_update_zero + NEGQ CX + SHRQ CL, R15 + ADDQ R15, AX + +sequenceDecs_decode_56_amd64_ll_update_zero: + MOVQ AX, (R10) + + // Fill bitreader for state updates + MOVQ R14, (SP) + MOVQ R9, AX + SHRQ $0x08, AX + MOVBQZX AL, AX + MOVQ ctx+16(FP), CX + CMPQ 96(CX), $0x00 + JZ sequenceDecs_decode_56_amd64_skip_update + + // Update Literal Length State + MOVBQZX DI, R14 + SHRL $0x10, DI + LEAQ (BX)(R14*1), CX + MOVQ DX, R15 + MOVQ CX, BX + ROLQ CL, R15 + MOVL $0x00000001, BP + MOVB R14, CL + SHLL CL, BP + DECL BP + ANDQ BP, R15 + ADDQ R15, DI + + // Load ctx.llTable + MOVQ ctx+16(FP), CX + MOVQ (CX), CX + MOVQ (CX)(DI*8), DI + + // Update Match Length State + MOVBQZX R8, R14 + SHRL $0x10, R8 + LEAQ (BX)(R14*1), CX + MOVQ DX, R15 + MOVQ CX, BX + ROLQ CL, R15 + MOVL $0x00000001, BP + MOVB R14, CL + SHLL CL, BP + DECL BP + ANDQ BP, R15 + ADDQ R15, R8 + + // Load ctx.mlTable + MOVQ ctx+16(FP), CX + MOVQ 24(CX), CX + MOVQ (CX)(R8*8), R8 + + // Update Offset State + MOVBQZX R9, R14 + SHRL $0x10, R9 + LEAQ (BX)(R14*1), CX + MOVQ DX, R15 + MOVQ CX, BX + ROLQ CL, R15 + MOVL $0x00000001, BP + MOVB R14, CL + SHLL CL, BP + DECL BP + ANDQ BP, R15 + ADDQ R15, R9 + + // Load ctx.ofTable + MOVQ ctx+16(FP), CX + MOVQ 48(CX), CX + MOVQ (CX)(R9*8), R9 + +sequenceDecs_decode_56_amd64_skip_update: + // Adjust offset + MOVQ 16(R10), CX + CMPQ AX, $0x01 + JBE sequenceDecs_decode_56_amd64_adjust_offsetB_1_or_0 + MOVQ R12, R13 + MOVQ R11, R12 + MOVQ CX, R11 + JMP sequenceDecs_decode_56_amd64_after_adjust + +sequenceDecs_decode_56_amd64_adjust_offsetB_1_or_0: + CMPQ (R10), $0x00000000 + JNE sequenceDecs_decode_56_amd64_adjust_offset_maybezero + INCQ CX + JMP sequenceDecs_decode_56_amd64_adjust_offset_nonzero + +sequenceDecs_decode_56_amd64_adjust_offset_maybezero: + TESTQ CX, CX + JNZ sequenceDecs_decode_56_amd64_adjust_offset_nonzero + MOVQ R11, CX + JMP sequenceDecs_decode_56_amd64_after_adjust + +sequenceDecs_decode_56_amd64_adjust_offset_nonzero: + CMPQ CX, $0x01 + JB sequenceDecs_decode_56_amd64_adjust_zero + JEQ sequenceDecs_decode_56_amd64_adjust_one + CMPQ CX, $0x02 + JA sequenceDecs_decode_56_amd64_adjust_three + JMP sequenceDecs_decode_56_amd64_adjust_two + +sequenceDecs_decode_56_amd64_adjust_zero: + MOVQ R11, AX + JMP sequenceDecs_decode_56_amd64_adjust_test_temp_valid + +sequenceDecs_decode_56_amd64_adjust_one: + MOVQ R12, AX + JMP sequenceDecs_decode_56_amd64_adjust_test_temp_valid + +sequenceDecs_decode_56_amd64_adjust_two: + MOVQ R13, AX + JMP sequenceDecs_decode_56_amd64_adjust_test_temp_valid + +sequenceDecs_decode_56_amd64_adjust_three: + LEAQ -1(R11), AX + +sequenceDecs_decode_56_amd64_adjust_test_temp_valid: + TESTQ AX, AX + JNZ sequenceDecs_decode_56_amd64_adjust_temp_valid + MOVQ $0x00000001, AX + +sequenceDecs_decode_56_amd64_adjust_temp_valid: + CMPQ CX, $0x01 + CMOVQNE R12, R13 + MOVQ R11, R12 + MOVQ AX, R11 + MOVQ AX, CX + +sequenceDecs_decode_56_amd64_after_adjust: + MOVQ CX, 16(R10) + + // Check values + MOVQ 8(R10), AX + MOVQ (R10), R14 + LEAQ (AX)(R14*1), R15 + MOVQ s+0(FP), BP + ADDQ R15, 256(BP) + MOVQ ctx+16(FP), R15 + SUBQ R14, 128(R15) + JS error_not_enough_literals + CMPQ AX, $0x00020002 + JA sequenceDecs_decode_56_amd64_error_match_len_too_big + TESTQ CX, CX + JNZ sequenceDecs_decode_56_amd64_match_len_ofs_ok + TESTQ AX, AX + JNZ sequenceDecs_decode_56_amd64_error_match_len_ofs_mismatch + +sequenceDecs_decode_56_amd64_match_len_ofs_ok: + ADDQ $0x18, R10 + MOVQ ctx+16(FP), AX + DECQ 96(AX) + JNS sequenceDecs_decode_56_amd64_main_loop + MOVQ s+0(FP), AX + MOVQ R11, 144(AX) + MOVQ R12, 152(AX) + MOVQ R13, 160(AX) + MOVQ br+8(FP), AX + MOVQ DX, 24(AX) + MOVB BL, 32(AX) + MOVQ SI, 8(AX) + + // Return success + MOVQ $0x00000000, ret+24(FP) + RET + + // Return with match length error +sequenceDecs_decode_56_amd64_error_match_len_ofs_mismatch: + MOVQ $0x00000001, ret+24(FP) + RET + + // Return with match too long error +sequenceDecs_decode_56_amd64_error_match_len_too_big: + MOVQ $0x00000002, ret+24(FP) + RET + + // Return with match offset too long error + MOVQ $0x00000003, ret+24(FP) + RET + + // Return with not enough literals error +error_not_enough_literals: + MOVQ $0x00000004, ret+24(FP) + RET + + // Return with overread error +error_overread: + MOVQ $0x00000006, ret+24(FP) + RET + +// func sequenceDecs_decode_bmi2(s *sequenceDecs, br *bitReader, ctx *decodeAsmContext) int +// Requires: BMI, BMI2, CMOV +TEXT ·sequenceDecs_decode_bmi2(SB), $8-32 + MOVQ br+8(FP), BX + MOVQ 24(BX), AX + MOVBQZX 32(BX), DX + MOVQ (BX), CX + MOVQ 8(BX), BX + ADDQ BX, CX + MOVQ CX, (SP) + MOVQ ctx+16(FP), CX + MOVQ 72(CX), SI + MOVQ 80(CX), DI + MOVQ 88(CX), R8 + MOVQ 104(CX), R9 + MOVQ s+0(FP), CX + MOVQ 144(CX), R10 + MOVQ 152(CX), R11 + MOVQ 160(CX), R12 + +sequenceDecs_decode_bmi2_main_loop: + MOVQ (SP), R13 + + // Fill bitreader to have enough for the offset and match length. + CMPQ BX, $0x08 + JL sequenceDecs_decode_bmi2_fill_byte_by_byte + MOVQ DX, CX + SHRQ $0x03, CX + SUBQ CX, R13 + MOVQ (R13), AX + SUBQ CX, BX + ANDQ $0x07, DX + JMP sequenceDecs_decode_bmi2_fill_end + +sequenceDecs_decode_bmi2_fill_byte_by_byte: + CMPQ BX, $0x00 + JLE sequenceDecs_decode_bmi2_fill_check_overread + CMPQ DX, $0x07 + JLE sequenceDecs_decode_bmi2_fill_end + SHLQ $0x08, AX + SUBQ $0x01, R13 + SUBQ $0x01, BX + SUBQ $0x08, DX + MOVBQZX (R13), CX + ORQ CX, AX + JMP sequenceDecs_decode_bmi2_fill_byte_by_byte + +sequenceDecs_decode_bmi2_fill_check_overread: + CMPQ DX, $0x40 + JA error_overread + +sequenceDecs_decode_bmi2_fill_end: + // Update offset + MOVQ $0x00000808, CX + BEXTRQ CX, R8, R14 + MOVQ AX, R15 + LEAQ (DX)(R14*1), CX + ROLQ CL, R15 + BZHIQ R14, R15, R15 + MOVQ CX, DX + MOVQ R8, CX + SHRQ $0x20, CX + ADDQ R15, CX + MOVQ CX, 16(R9) + + // Update match length + MOVQ $0x00000808, CX + BEXTRQ CX, DI, R14 + MOVQ AX, R15 + LEAQ (DX)(R14*1), CX + ROLQ CL, R15 + BZHIQ R14, R15, R15 + MOVQ CX, DX + MOVQ DI, CX + SHRQ $0x20, CX + ADDQ R15, CX + MOVQ CX, 8(R9) + + // Fill bitreader to have enough for the remaining + CMPQ BX, $0x08 + JL sequenceDecs_decode_bmi2_fill_2_byte_by_byte + MOVQ DX, CX + SHRQ $0x03, CX + SUBQ CX, R13 + MOVQ (R13), AX + SUBQ CX, BX + ANDQ $0x07, DX + JMP sequenceDecs_decode_bmi2_fill_2_end + +sequenceDecs_decode_bmi2_fill_2_byte_by_byte: + CMPQ BX, $0x00 + JLE sequenceDecs_decode_bmi2_fill_2_check_overread + CMPQ DX, $0x07 + JLE sequenceDecs_decode_bmi2_fill_2_end + SHLQ $0x08, AX + SUBQ $0x01, R13 + SUBQ $0x01, BX + SUBQ $0x08, DX + MOVBQZX (R13), CX + ORQ CX, AX + JMP sequenceDecs_decode_bmi2_fill_2_byte_by_byte + +sequenceDecs_decode_bmi2_fill_2_check_overread: + CMPQ DX, $0x40 + JA error_overread + +sequenceDecs_decode_bmi2_fill_2_end: + // Update literal length + MOVQ $0x00000808, CX + BEXTRQ CX, SI, R14 + MOVQ AX, R15 + LEAQ (DX)(R14*1), CX + ROLQ CL, R15 + BZHIQ R14, R15, R15 + MOVQ CX, DX + MOVQ SI, CX + SHRQ $0x20, CX + ADDQ R15, CX + MOVQ CX, (R9) + + // Fill bitreader for state updates + MOVQ R13, (SP) + MOVQ $0x00000808, CX + BEXTRQ CX, R8, R13 + MOVQ ctx+16(FP), CX + CMPQ 96(CX), $0x00 + JZ sequenceDecs_decode_bmi2_skip_update + LEAQ (SI)(DI*1), R14 + ADDQ R8, R14 + MOVBQZX R14, R14 + LEAQ (DX)(R14*1), CX + MOVQ AX, R15 + MOVQ CX, DX + ROLQ CL, R15 + BZHIQ R14, R15, R15 + + // Update Offset State + BZHIQ R8, R15, CX + SHRXQ R8, R15, R15 + SHRL $0x10, R8 + ADDQ CX, R8 + + // Load ctx.ofTable + MOVQ ctx+16(FP), CX + MOVQ 48(CX), CX + MOVQ (CX)(R8*8), R8 + + // Update Match Length State + BZHIQ DI, R15, CX + SHRXQ DI, R15, R15 + SHRL $0x10, DI + ADDQ CX, DI + + // Load ctx.mlTable + MOVQ ctx+16(FP), CX + MOVQ 24(CX), CX + MOVQ (CX)(DI*8), DI + + // Update Literal Length State + BZHIQ SI, R15, CX + SHRL $0x10, SI + ADDQ CX, SI + + // Load ctx.llTable + MOVQ ctx+16(FP), CX + MOVQ (CX), CX + MOVQ (CX)(SI*8), SI + +sequenceDecs_decode_bmi2_skip_update: + // Adjust offset + MOVQ 16(R9), CX + CMPQ R13, $0x01 + JBE sequenceDecs_decode_bmi2_adjust_offsetB_1_or_0 + MOVQ R11, R12 + MOVQ R10, R11 + MOVQ CX, R10 + JMP sequenceDecs_decode_bmi2_after_adjust + +sequenceDecs_decode_bmi2_adjust_offsetB_1_or_0: + CMPQ (R9), $0x00000000 + JNE sequenceDecs_decode_bmi2_adjust_offset_maybezero + INCQ CX + JMP sequenceDecs_decode_bmi2_adjust_offset_nonzero + +sequenceDecs_decode_bmi2_adjust_offset_maybezero: + TESTQ CX, CX + JNZ sequenceDecs_decode_bmi2_adjust_offset_nonzero + MOVQ R10, CX + JMP sequenceDecs_decode_bmi2_after_adjust + +sequenceDecs_decode_bmi2_adjust_offset_nonzero: + CMPQ CX, $0x01 + JB sequenceDecs_decode_bmi2_adjust_zero + JEQ sequenceDecs_decode_bmi2_adjust_one + CMPQ CX, $0x02 + JA sequenceDecs_decode_bmi2_adjust_three + JMP sequenceDecs_decode_bmi2_adjust_two + +sequenceDecs_decode_bmi2_adjust_zero: + MOVQ R10, R13 + JMP sequenceDecs_decode_bmi2_adjust_test_temp_valid + +sequenceDecs_decode_bmi2_adjust_one: + MOVQ R11, R13 + JMP sequenceDecs_decode_bmi2_adjust_test_temp_valid + +sequenceDecs_decode_bmi2_adjust_two: + MOVQ R12, R13 + JMP sequenceDecs_decode_bmi2_adjust_test_temp_valid + +sequenceDecs_decode_bmi2_adjust_three: + LEAQ -1(R10), R13 + +sequenceDecs_decode_bmi2_adjust_test_temp_valid: + TESTQ R13, R13 + JNZ sequenceDecs_decode_bmi2_adjust_temp_valid + MOVQ $0x00000001, R13 + +sequenceDecs_decode_bmi2_adjust_temp_valid: + CMPQ CX, $0x01 + CMOVQNE R11, R12 + MOVQ R10, R11 + MOVQ R13, R10 + MOVQ R13, CX + +sequenceDecs_decode_bmi2_after_adjust: + MOVQ CX, 16(R9) + + // Check values + MOVQ 8(R9), R13 + MOVQ (R9), R14 + LEAQ (R13)(R14*1), R15 + MOVQ s+0(FP), BP + ADDQ R15, 256(BP) + MOVQ ctx+16(FP), R15 + SUBQ R14, 128(R15) + JS error_not_enough_literals + CMPQ R13, $0x00020002 + JA sequenceDecs_decode_bmi2_error_match_len_too_big + TESTQ CX, CX + JNZ sequenceDecs_decode_bmi2_match_len_ofs_ok + TESTQ R13, R13 + JNZ sequenceDecs_decode_bmi2_error_match_len_ofs_mismatch + +sequenceDecs_decode_bmi2_match_len_ofs_ok: + ADDQ $0x18, R9 + MOVQ ctx+16(FP), CX + DECQ 96(CX) + JNS sequenceDecs_decode_bmi2_main_loop + MOVQ s+0(FP), CX + MOVQ R10, 144(CX) + MOVQ R11, 152(CX) + MOVQ R12, 160(CX) + MOVQ br+8(FP), CX + MOVQ AX, 24(CX) + MOVB DL, 32(CX) + MOVQ BX, 8(CX) + + // Return success + MOVQ $0x00000000, ret+24(FP) + RET + + // Return with match length error +sequenceDecs_decode_bmi2_error_match_len_ofs_mismatch: + MOVQ $0x00000001, ret+24(FP) + RET + + // Return with match too long error +sequenceDecs_decode_bmi2_error_match_len_too_big: + MOVQ $0x00000002, ret+24(FP) + RET + + // Return with match offset too long error + MOVQ $0x00000003, ret+24(FP) + RET + + // Return with not enough literals error +error_not_enough_literals: + MOVQ $0x00000004, ret+24(FP) + RET + + // Return with overread error +error_overread: + MOVQ $0x00000006, ret+24(FP) + RET + +// func sequenceDecs_decode_56_bmi2(s *sequenceDecs, br *bitReader, ctx *decodeAsmContext) int +// Requires: BMI, BMI2, CMOV +TEXT ·sequenceDecs_decode_56_bmi2(SB), $8-32 + MOVQ br+8(FP), BX + MOVQ 24(BX), AX + MOVBQZX 32(BX), DX + MOVQ (BX), CX + MOVQ 8(BX), BX + ADDQ BX, CX + MOVQ CX, (SP) + MOVQ ctx+16(FP), CX + MOVQ 72(CX), SI + MOVQ 80(CX), DI + MOVQ 88(CX), R8 + MOVQ 104(CX), R9 + MOVQ s+0(FP), CX + MOVQ 144(CX), R10 + MOVQ 152(CX), R11 + MOVQ 160(CX), R12 + +sequenceDecs_decode_56_bmi2_main_loop: + MOVQ (SP), R13 + + // Fill bitreader to have enough for the offset and match length. + CMPQ BX, $0x08 + JL sequenceDecs_decode_56_bmi2_fill_byte_by_byte + MOVQ DX, CX + SHRQ $0x03, CX + SUBQ CX, R13 + MOVQ (R13), AX + SUBQ CX, BX + ANDQ $0x07, DX + JMP sequenceDecs_decode_56_bmi2_fill_end + +sequenceDecs_decode_56_bmi2_fill_byte_by_byte: + CMPQ BX, $0x00 + JLE sequenceDecs_decode_56_bmi2_fill_check_overread + CMPQ DX, $0x07 + JLE sequenceDecs_decode_56_bmi2_fill_end + SHLQ $0x08, AX + SUBQ $0x01, R13 + SUBQ $0x01, BX + SUBQ $0x08, DX + MOVBQZX (R13), CX + ORQ CX, AX + JMP sequenceDecs_decode_56_bmi2_fill_byte_by_byte + +sequenceDecs_decode_56_bmi2_fill_check_overread: + CMPQ DX, $0x40 + JA error_overread + +sequenceDecs_decode_56_bmi2_fill_end: + // Update offset + MOVQ $0x00000808, CX + BEXTRQ CX, R8, R14 + MOVQ AX, R15 + LEAQ (DX)(R14*1), CX + ROLQ CL, R15 + BZHIQ R14, R15, R15 + MOVQ CX, DX + MOVQ R8, CX + SHRQ $0x20, CX + ADDQ R15, CX + MOVQ CX, 16(R9) + + // Update match length + MOVQ $0x00000808, CX + BEXTRQ CX, DI, R14 + MOVQ AX, R15 + LEAQ (DX)(R14*1), CX + ROLQ CL, R15 + BZHIQ R14, R15, R15 + MOVQ CX, DX + MOVQ DI, CX + SHRQ $0x20, CX + ADDQ R15, CX + MOVQ CX, 8(R9) + + // Update literal length + MOVQ $0x00000808, CX + BEXTRQ CX, SI, R14 + MOVQ AX, R15 + LEAQ (DX)(R14*1), CX + ROLQ CL, R15 + BZHIQ R14, R15, R15 + MOVQ CX, DX + MOVQ SI, CX + SHRQ $0x20, CX + ADDQ R15, CX + MOVQ CX, (R9) + + // Fill bitreader for state updates + MOVQ R13, (SP) + MOVQ $0x00000808, CX + BEXTRQ CX, R8, R13 + MOVQ ctx+16(FP), CX + CMPQ 96(CX), $0x00 + JZ sequenceDecs_decode_56_bmi2_skip_update + LEAQ (SI)(DI*1), R14 + ADDQ R8, R14 + MOVBQZX R14, R14 + LEAQ (DX)(R14*1), CX + MOVQ AX, R15 + MOVQ CX, DX + ROLQ CL, R15 + BZHIQ R14, R15, R15 + + // Update Offset State + BZHIQ R8, R15, CX + SHRXQ R8, R15, R15 + SHRL $0x10, R8 + ADDQ CX, R8 + + // Load ctx.ofTable + MOVQ ctx+16(FP), CX + MOVQ 48(CX), CX + MOVQ (CX)(R8*8), R8 + + // Update Match Length State + BZHIQ DI, R15, CX + SHRXQ DI, R15, R15 + SHRL $0x10, DI + ADDQ CX, DI + + // Load ctx.mlTable + MOVQ ctx+16(FP), CX + MOVQ 24(CX), CX + MOVQ (CX)(DI*8), DI + + // Update Literal Length State + BZHIQ SI, R15, CX + SHRL $0x10, SI + ADDQ CX, SI + + // Load ctx.llTable + MOVQ ctx+16(FP), CX + MOVQ (CX), CX + MOVQ (CX)(SI*8), SI + +sequenceDecs_decode_56_bmi2_skip_update: + // Adjust offset + MOVQ 16(R9), CX + CMPQ R13, $0x01 + JBE sequenceDecs_decode_56_bmi2_adjust_offsetB_1_or_0 + MOVQ R11, R12 + MOVQ R10, R11 + MOVQ CX, R10 + JMP sequenceDecs_decode_56_bmi2_after_adjust + +sequenceDecs_decode_56_bmi2_adjust_offsetB_1_or_0: + CMPQ (R9), $0x00000000 + JNE sequenceDecs_decode_56_bmi2_adjust_offset_maybezero + INCQ CX + JMP sequenceDecs_decode_56_bmi2_adjust_offset_nonzero + +sequenceDecs_decode_56_bmi2_adjust_offset_maybezero: + TESTQ CX, CX + JNZ sequenceDecs_decode_56_bmi2_adjust_offset_nonzero + MOVQ R10, CX + JMP sequenceDecs_decode_56_bmi2_after_adjust + +sequenceDecs_decode_56_bmi2_adjust_offset_nonzero: + CMPQ CX, $0x01 + JB sequenceDecs_decode_56_bmi2_adjust_zero + JEQ sequenceDecs_decode_56_bmi2_adjust_one + CMPQ CX, $0x02 + JA sequenceDecs_decode_56_bmi2_adjust_three + JMP sequenceDecs_decode_56_bmi2_adjust_two + +sequenceDecs_decode_56_bmi2_adjust_zero: + MOVQ R10, R13 + JMP sequenceDecs_decode_56_bmi2_adjust_test_temp_valid + +sequenceDecs_decode_56_bmi2_adjust_one: + MOVQ R11, R13 + JMP sequenceDecs_decode_56_bmi2_adjust_test_temp_valid + +sequenceDecs_decode_56_bmi2_adjust_two: + MOVQ R12, R13 + JMP sequenceDecs_decode_56_bmi2_adjust_test_temp_valid + +sequenceDecs_decode_56_bmi2_adjust_three: + LEAQ -1(R10), R13 + +sequenceDecs_decode_56_bmi2_adjust_test_temp_valid: + TESTQ R13, R13 + JNZ sequenceDecs_decode_56_bmi2_adjust_temp_valid + MOVQ $0x00000001, R13 + +sequenceDecs_decode_56_bmi2_adjust_temp_valid: + CMPQ CX, $0x01 + CMOVQNE R11, R12 + MOVQ R10, R11 + MOVQ R13, R10 + MOVQ R13, CX + +sequenceDecs_decode_56_bmi2_after_adjust: + MOVQ CX, 16(R9) + + // Check values + MOVQ 8(R9), R13 + MOVQ (R9), R14 + LEAQ (R13)(R14*1), R15 + MOVQ s+0(FP), BP + ADDQ R15, 256(BP) + MOVQ ctx+16(FP), R15 + SUBQ R14, 128(R15) + JS error_not_enough_literals + CMPQ R13, $0x00020002 + JA sequenceDecs_decode_56_bmi2_error_match_len_too_big + TESTQ CX, CX + JNZ sequenceDecs_decode_56_bmi2_match_len_ofs_ok + TESTQ R13, R13 + JNZ sequenceDecs_decode_56_bmi2_error_match_len_ofs_mismatch + +sequenceDecs_decode_56_bmi2_match_len_ofs_ok: + ADDQ $0x18, R9 + MOVQ ctx+16(FP), CX + DECQ 96(CX) + JNS sequenceDecs_decode_56_bmi2_main_loop + MOVQ s+0(FP), CX + MOVQ R10, 144(CX) + MOVQ R11, 152(CX) + MOVQ R12, 160(CX) + MOVQ br+8(FP), CX + MOVQ AX, 24(CX) + MOVB DL, 32(CX) + MOVQ BX, 8(CX) + + // Return success + MOVQ $0x00000000, ret+24(FP) + RET + + // Return with match length error +sequenceDecs_decode_56_bmi2_error_match_len_ofs_mismatch: + MOVQ $0x00000001, ret+24(FP) + RET + + // Return with match too long error +sequenceDecs_decode_56_bmi2_error_match_len_too_big: + MOVQ $0x00000002, ret+24(FP) + RET + + // Return with match offset too long error + MOVQ $0x00000003, ret+24(FP) + RET + + // Return with not enough literals error +error_not_enough_literals: + MOVQ $0x00000004, ret+24(FP) + RET + + // Return with overread error +error_overread: + MOVQ $0x00000006, ret+24(FP) + RET + +// func sequenceDecs_executeSimple_amd64(ctx *executeAsmContext) bool +// Requires: SSE +TEXT ·sequenceDecs_executeSimple_amd64(SB), $8-9 + MOVQ ctx+0(FP), R10 + MOVQ 8(R10), CX + TESTQ CX, CX + JZ empty_seqs + MOVQ (R10), AX + MOVQ 24(R10), DX + MOVQ 32(R10), BX + MOVQ 80(R10), SI + MOVQ 104(R10), DI + MOVQ 120(R10), R8 + MOVQ 56(R10), R9 + MOVQ 64(R10), R10 + ADDQ R10, R9 + + // seqsBase += 24 * seqIndex + LEAQ (DX)(DX*2), R11 + SHLQ $0x03, R11 + ADDQ R11, AX + + // outBase += outPosition + ADDQ DI, BX + +main_loop: + MOVQ (AX), R11 + MOVQ 16(AX), R12 + MOVQ 8(AX), R13 + + // Copy literals + TESTQ R11, R11 + JZ check_offset + XORQ R14, R14 + +copy_1: + MOVUPS (SI)(R14*1), X0 + MOVUPS X0, (BX)(R14*1) + ADDQ $0x10, R14 + CMPQ R14, R11 + JB copy_1 + ADDQ R11, SI + ADDQ R11, BX + ADDQ R11, DI + + // Malformed input if seq.mo > t+len(hist) || seq.mo > s.windowSize) +check_offset: + LEAQ (DI)(R10*1), R11 + CMPQ R12, R11 + JG error_match_off_too_big + CMPQ R12, R8 + JG error_match_off_too_big + + // Copy match from history + MOVQ R12, R11 + SUBQ DI, R11 + JLS copy_match + MOVQ R9, R14 + SUBQ R11, R14 + CMPQ R13, R11 + JG copy_all_from_history + MOVQ R13, R11 + SUBQ $0x10, R11 + JB copy_4_small + +copy_4_loop: + MOVUPS (R14), X0 + MOVUPS X0, (BX) + ADDQ $0x10, R14 + ADDQ $0x10, BX + SUBQ $0x10, R11 + JAE copy_4_loop + LEAQ 16(R14)(R11*1), R14 + LEAQ 16(BX)(R11*1), BX + MOVUPS -16(R14), X0 + MOVUPS X0, -16(BX) + JMP copy_4_end + +copy_4_small: + CMPQ R13, $0x03 + JE copy_4_move_3 + CMPQ R13, $0x08 + JB copy_4_move_4through7 + JMP copy_4_move_8through16 + +copy_4_move_3: + MOVW (R14), R11 + MOVB 2(R14), R12 + MOVW R11, (BX) + MOVB R12, 2(BX) + ADDQ R13, R14 + ADDQ R13, BX + JMP copy_4_end + +copy_4_move_4through7: + MOVL (R14), R11 + MOVL -4(R14)(R13*1), R12 + MOVL R11, (BX) + MOVL R12, -4(BX)(R13*1) + ADDQ R13, R14 + ADDQ R13, BX + JMP copy_4_end + +copy_4_move_8through16: + MOVQ (R14), R11 + MOVQ -8(R14)(R13*1), R12 + MOVQ R11, (BX) + MOVQ R12, -8(BX)(R13*1) + ADDQ R13, R14 + ADDQ R13, BX + +copy_4_end: + ADDQ R13, DI + ADDQ $0x18, AX + INCQ DX + CMPQ DX, CX + JB main_loop + JMP loop_finished + +copy_all_from_history: + MOVQ R11, R15 + SUBQ $0x10, R15 + JB copy_5_small + +copy_5_loop: + MOVUPS (R14), X0 + MOVUPS X0, (BX) + ADDQ $0x10, R14 + ADDQ $0x10, BX + SUBQ $0x10, R15 + JAE copy_5_loop + LEAQ 16(R14)(R15*1), R14 + LEAQ 16(BX)(R15*1), BX + MOVUPS -16(R14), X0 + MOVUPS X0, -16(BX) + JMP copy_5_end + +copy_5_small: + CMPQ R11, $0x03 + JE copy_5_move_3 + JB copy_5_move_1or2 + CMPQ R11, $0x08 + JB copy_5_move_4through7 + JMP copy_5_move_8through16 + +copy_5_move_1or2: + MOVB (R14), R15 + MOVB -1(R14)(R11*1), BP + MOVB R15, (BX) + MOVB BP, -1(BX)(R11*1) + ADDQ R11, R14 + ADDQ R11, BX + JMP copy_5_end + +copy_5_move_3: + MOVW (R14), R15 + MOVB 2(R14), BP + MOVW R15, (BX) + MOVB BP, 2(BX) + ADDQ R11, R14 + ADDQ R11, BX + JMP copy_5_end + +copy_5_move_4through7: + MOVL (R14), R15 + MOVL -4(R14)(R11*1), BP + MOVL R15, (BX) + MOVL BP, -4(BX)(R11*1) + ADDQ R11, R14 + ADDQ R11, BX + JMP copy_5_end + +copy_5_move_8through16: + MOVQ (R14), R15 + MOVQ -8(R14)(R11*1), BP + MOVQ R15, (BX) + MOVQ BP, -8(BX)(R11*1) + ADDQ R11, R14 + ADDQ R11, BX + +copy_5_end: + ADDQ R11, DI + SUBQ R11, R13 + + // Copy match from the current buffer +copy_match: + MOVQ BX, R11 + SUBQ R12, R11 + + // ml <= mo + CMPQ R13, R12 + JA copy_overlapping_match + + // Copy non-overlapping match + ADDQ R13, DI + MOVQ BX, R12 + ADDQ R13, BX + +copy_2: + MOVUPS (R11), X0 + MOVUPS X0, (R12) + ADDQ $0x10, R11 + ADDQ $0x10, R12 + SUBQ $0x10, R13 + JHI copy_2 + JMP handle_loop + + // Copy overlapping match +copy_overlapping_match: + ADDQ R13, DI + +copy_slow_3: + MOVB (R11), R12 + MOVB R12, (BX) + INCQ R11 + INCQ BX + DECQ R13 + JNZ copy_slow_3 + +handle_loop: + ADDQ $0x18, AX + INCQ DX + CMPQ DX, CX + JB main_loop + +loop_finished: + // Return value + MOVB $0x01, ret+8(FP) + + // Update the context + MOVQ ctx+0(FP), AX + MOVQ DX, 24(AX) + MOVQ DI, 104(AX) + SUBQ 80(AX), SI + MOVQ SI, 112(AX) + RET + +error_match_off_too_big: + // Return value + MOVB $0x00, ret+8(FP) + + // Update the context + MOVQ ctx+0(FP), AX + MOVQ DX, 24(AX) + MOVQ DI, 104(AX) + SUBQ 80(AX), SI + MOVQ SI, 112(AX) + RET + +empty_seqs: + // Return value + MOVB $0x01, ret+8(FP) + RET + +// func sequenceDecs_executeSimple_safe_amd64(ctx *executeAsmContext) bool +// Requires: SSE +TEXT ·sequenceDecs_executeSimple_safe_amd64(SB), $8-9 + MOVQ ctx+0(FP), R10 + MOVQ 8(R10), CX + TESTQ CX, CX + JZ empty_seqs + MOVQ (R10), AX + MOVQ 24(R10), DX + MOVQ 32(R10), BX + MOVQ 80(R10), SI + MOVQ 104(R10), DI + MOVQ 120(R10), R8 + MOVQ 56(R10), R9 + MOVQ 64(R10), R10 + ADDQ R10, R9 + + // seqsBase += 24 * seqIndex + LEAQ (DX)(DX*2), R11 + SHLQ $0x03, R11 + ADDQ R11, AX + + // outBase += outPosition + ADDQ DI, BX + +main_loop: + MOVQ (AX), R11 + MOVQ 16(AX), R12 + MOVQ 8(AX), R13 + + // Copy literals + TESTQ R11, R11 + JZ check_offset + MOVQ R11, R14 + SUBQ $0x10, R14 + JB copy_1_small + +copy_1_loop: + MOVUPS (SI), X0 + MOVUPS X0, (BX) + ADDQ $0x10, SI + ADDQ $0x10, BX + SUBQ $0x10, R14 + JAE copy_1_loop + LEAQ 16(SI)(R14*1), SI + LEAQ 16(BX)(R14*1), BX + MOVUPS -16(SI), X0 + MOVUPS X0, -16(BX) + JMP copy_1_end + +copy_1_small: + CMPQ R11, $0x03 + JE copy_1_move_3 + JB copy_1_move_1or2 + CMPQ R11, $0x08 + JB copy_1_move_4through7 + JMP copy_1_move_8through16 + +copy_1_move_1or2: + MOVB (SI), R14 + MOVB -1(SI)(R11*1), R15 + MOVB R14, (BX) + MOVB R15, -1(BX)(R11*1) + ADDQ R11, SI + ADDQ R11, BX + JMP copy_1_end + +copy_1_move_3: + MOVW (SI), R14 + MOVB 2(SI), R15 + MOVW R14, (BX) + MOVB R15, 2(BX) + ADDQ R11, SI + ADDQ R11, BX + JMP copy_1_end + +copy_1_move_4through7: + MOVL (SI), R14 + MOVL -4(SI)(R11*1), R15 + MOVL R14, (BX) + MOVL R15, -4(BX)(R11*1) + ADDQ R11, SI + ADDQ R11, BX + JMP copy_1_end + +copy_1_move_8through16: + MOVQ (SI), R14 + MOVQ -8(SI)(R11*1), R15 + MOVQ R14, (BX) + MOVQ R15, -8(BX)(R11*1) + ADDQ R11, SI + ADDQ R11, BX + +copy_1_end: + ADDQ R11, DI + + // Malformed input if seq.mo > t+len(hist) || seq.mo > s.windowSize) +check_offset: + LEAQ (DI)(R10*1), R11 + CMPQ R12, R11 + JG error_match_off_too_big + CMPQ R12, R8 + JG error_match_off_too_big + + // Copy match from history + MOVQ R12, R11 + SUBQ DI, R11 + JLS copy_match + MOVQ R9, R14 + SUBQ R11, R14 + CMPQ R13, R11 + JG copy_all_from_history + MOVQ R13, R11 + SUBQ $0x10, R11 + JB copy_4_small + +copy_4_loop: + MOVUPS (R14), X0 + MOVUPS X0, (BX) + ADDQ $0x10, R14 + ADDQ $0x10, BX + SUBQ $0x10, R11 + JAE copy_4_loop + LEAQ 16(R14)(R11*1), R14 + LEAQ 16(BX)(R11*1), BX + MOVUPS -16(R14), X0 + MOVUPS X0, -16(BX) + JMP copy_4_end + +copy_4_small: + CMPQ R13, $0x03 + JE copy_4_move_3 + CMPQ R13, $0x08 + JB copy_4_move_4through7 + JMP copy_4_move_8through16 + +copy_4_move_3: + MOVW (R14), R11 + MOVB 2(R14), R12 + MOVW R11, (BX) + MOVB R12, 2(BX) + ADDQ R13, R14 + ADDQ R13, BX + JMP copy_4_end + +copy_4_move_4through7: + MOVL (R14), R11 + MOVL -4(R14)(R13*1), R12 + MOVL R11, (BX) + MOVL R12, -4(BX)(R13*1) + ADDQ R13, R14 + ADDQ R13, BX + JMP copy_4_end + +copy_4_move_8through16: + MOVQ (R14), R11 + MOVQ -8(R14)(R13*1), R12 + MOVQ R11, (BX) + MOVQ R12, -8(BX)(R13*1) + ADDQ R13, R14 + ADDQ R13, BX + +copy_4_end: + ADDQ R13, DI + ADDQ $0x18, AX + INCQ DX + CMPQ DX, CX + JB main_loop + JMP loop_finished + +copy_all_from_history: + MOVQ R11, R15 + SUBQ $0x10, R15 + JB copy_5_small + +copy_5_loop: + MOVUPS (R14), X0 + MOVUPS X0, (BX) + ADDQ $0x10, R14 + ADDQ $0x10, BX + SUBQ $0x10, R15 + JAE copy_5_loop + LEAQ 16(R14)(R15*1), R14 + LEAQ 16(BX)(R15*1), BX + MOVUPS -16(R14), X0 + MOVUPS X0, -16(BX) + JMP copy_5_end + +copy_5_small: + CMPQ R11, $0x03 + JE copy_5_move_3 + JB copy_5_move_1or2 + CMPQ R11, $0x08 + JB copy_5_move_4through7 + JMP copy_5_move_8through16 + +copy_5_move_1or2: + MOVB (R14), R15 + MOVB -1(R14)(R11*1), BP + MOVB R15, (BX) + MOVB BP, -1(BX)(R11*1) + ADDQ R11, R14 + ADDQ R11, BX + JMP copy_5_end + +copy_5_move_3: + MOVW (R14), R15 + MOVB 2(R14), BP + MOVW R15, (BX) + MOVB BP, 2(BX) + ADDQ R11, R14 + ADDQ R11, BX + JMP copy_5_end + +copy_5_move_4through7: + MOVL (R14), R15 + MOVL -4(R14)(R11*1), BP + MOVL R15, (BX) + MOVL BP, -4(BX)(R11*1) + ADDQ R11, R14 + ADDQ R11, BX + JMP copy_5_end + +copy_5_move_8through16: + MOVQ (R14), R15 + MOVQ -8(R14)(R11*1), BP + MOVQ R15, (BX) + MOVQ BP, -8(BX)(R11*1) + ADDQ R11, R14 + ADDQ R11, BX + +copy_5_end: + ADDQ R11, DI + SUBQ R11, R13 + + // Copy match from the current buffer +copy_match: + MOVQ BX, R11 + SUBQ R12, R11 + + // ml <= mo + CMPQ R13, R12 + JA copy_overlapping_match + + // Copy non-overlapping match + ADDQ R13, DI + MOVQ R13, R12 + SUBQ $0x10, R12 + JB copy_2_small + +copy_2_loop: + MOVUPS (R11), X0 + MOVUPS X0, (BX) + ADDQ $0x10, R11 + ADDQ $0x10, BX + SUBQ $0x10, R12 + JAE copy_2_loop + LEAQ 16(R11)(R12*1), R11 + LEAQ 16(BX)(R12*1), BX + MOVUPS -16(R11), X0 + MOVUPS X0, -16(BX) + JMP copy_2_end + +copy_2_small: + CMPQ R13, $0x03 + JE copy_2_move_3 + JB copy_2_move_1or2 + CMPQ R13, $0x08 + JB copy_2_move_4through7 + JMP copy_2_move_8through16 + +copy_2_move_1or2: + MOVB (R11), R12 + MOVB -1(R11)(R13*1), R14 + MOVB R12, (BX) + MOVB R14, -1(BX)(R13*1) + ADDQ R13, R11 + ADDQ R13, BX + JMP copy_2_end + +copy_2_move_3: + MOVW (R11), R12 + MOVB 2(R11), R14 + MOVW R12, (BX) + MOVB R14, 2(BX) + ADDQ R13, R11 + ADDQ R13, BX + JMP copy_2_end + +copy_2_move_4through7: + MOVL (R11), R12 + MOVL -4(R11)(R13*1), R14 + MOVL R12, (BX) + MOVL R14, -4(BX)(R13*1) + ADDQ R13, R11 + ADDQ R13, BX + JMP copy_2_end + +copy_2_move_8through16: + MOVQ (R11), R12 + MOVQ -8(R11)(R13*1), R14 + MOVQ R12, (BX) + MOVQ R14, -8(BX)(R13*1) + ADDQ R13, R11 + ADDQ R13, BX + +copy_2_end: + JMP handle_loop + + // Copy overlapping match +copy_overlapping_match: + ADDQ R13, DI + +copy_slow_3: + MOVB (R11), R12 + MOVB R12, (BX) + INCQ R11 + INCQ BX + DECQ R13 + JNZ copy_slow_3 + +handle_loop: + ADDQ $0x18, AX + INCQ DX + CMPQ DX, CX + JB main_loop + +loop_finished: + // Return value + MOVB $0x01, ret+8(FP) + + // Update the context + MOVQ ctx+0(FP), AX + MOVQ DX, 24(AX) + MOVQ DI, 104(AX) + SUBQ 80(AX), SI + MOVQ SI, 112(AX) + RET + +error_match_off_too_big: + // Return value + MOVB $0x00, ret+8(FP) + + // Update the context + MOVQ ctx+0(FP), AX + MOVQ DX, 24(AX) + MOVQ DI, 104(AX) + SUBQ 80(AX), SI + MOVQ SI, 112(AX) + RET + +empty_seqs: + // Return value + MOVB $0x01, ret+8(FP) + RET + +// func sequenceDecs_decodeSync_amd64(s *sequenceDecs, br *bitReader, ctx *decodeSyncAsmContext) int +// Requires: CMOV, SSE +TEXT ·sequenceDecs_decodeSync_amd64(SB), $64-32 + MOVQ br+8(FP), CX + MOVQ 24(CX), DX + MOVBQZX 32(CX), BX + MOVQ (CX), AX + MOVQ 8(CX), SI + ADDQ SI, AX + MOVQ AX, (SP) + MOVQ ctx+16(FP), AX + MOVQ 72(AX), DI + MOVQ 80(AX), R8 + MOVQ 88(AX), R9 + XORQ CX, CX + MOVQ CX, 8(SP) + MOVQ CX, 16(SP) + MOVQ CX, 24(SP) + MOVQ 112(AX), R10 + MOVQ 128(AX), CX + MOVQ CX, 32(SP) + MOVQ 144(AX), R11 + MOVQ 136(AX), R12 + MOVQ 200(AX), CX + MOVQ CX, 56(SP) + MOVQ 176(AX), CX + MOVQ CX, 48(SP) + MOVQ 184(AX), AX + MOVQ AX, 40(SP) + MOVQ 40(SP), AX + ADDQ AX, 48(SP) + + // Calculate poiter to s.out[cap(s.out)] (a past-end pointer) + ADDQ R10, 32(SP) + + // outBase += outPosition + ADDQ R12, R10 + +sequenceDecs_decodeSync_amd64_main_loop: + MOVQ (SP), R13 + + // Fill bitreader to have enough for the offset and match length. + CMPQ SI, $0x08 + JL sequenceDecs_decodeSync_amd64_fill_byte_by_byte + MOVQ BX, AX + SHRQ $0x03, AX + SUBQ AX, R13 + MOVQ (R13), DX + SUBQ AX, SI + ANDQ $0x07, BX + JMP sequenceDecs_decodeSync_amd64_fill_end + +sequenceDecs_decodeSync_amd64_fill_byte_by_byte: + CMPQ SI, $0x00 + JLE sequenceDecs_decodeSync_amd64_fill_check_overread + CMPQ BX, $0x07 + JLE sequenceDecs_decodeSync_amd64_fill_end + SHLQ $0x08, DX + SUBQ $0x01, R13 + SUBQ $0x01, SI + SUBQ $0x08, BX + MOVBQZX (R13), AX + ORQ AX, DX + JMP sequenceDecs_decodeSync_amd64_fill_byte_by_byte + +sequenceDecs_decodeSync_amd64_fill_check_overread: + CMPQ BX, $0x40 + JA error_overread + +sequenceDecs_decodeSync_amd64_fill_end: + // Update offset + MOVQ R9, AX + MOVQ BX, CX + MOVQ DX, R14 + SHLQ CL, R14 + MOVB AH, CL + SHRQ $0x20, AX + TESTQ CX, CX + JZ sequenceDecs_decodeSync_amd64_of_update_zero + ADDQ CX, BX + CMPQ BX, $0x40 + JA sequenceDecs_decodeSync_amd64_of_update_zero + CMPQ CX, $0x40 + JAE sequenceDecs_decodeSync_amd64_of_update_zero + NEGQ CX + SHRQ CL, R14 + ADDQ R14, AX + +sequenceDecs_decodeSync_amd64_of_update_zero: + MOVQ AX, 8(SP) + + // Update match length + MOVQ R8, AX + MOVQ BX, CX + MOVQ DX, R14 + SHLQ CL, R14 + MOVB AH, CL + SHRQ $0x20, AX + TESTQ CX, CX + JZ sequenceDecs_decodeSync_amd64_ml_update_zero + ADDQ CX, BX + CMPQ BX, $0x40 + JA sequenceDecs_decodeSync_amd64_ml_update_zero + CMPQ CX, $0x40 + JAE sequenceDecs_decodeSync_amd64_ml_update_zero + NEGQ CX + SHRQ CL, R14 + ADDQ R14, AX + +sequenceDecs_decodeSync_amd64_ml_update_zero: + MOVQ AX, 16(SP) + + // Fill bitreader to have enough for the remaining + CMPQ SI, $0x08 + JL sequenceDecs_decodeSync_amd64_fill_2_byte_by_byte + MOVQ BX, AX + SHRQ $0x03, AX + SUBQ AX, R13 + MOVQ (R13), DX + SUBQ AX, SI + ANDQ $0x07, BX + JMP sequenceDecs_decodeSync_amd64_fill_2_end + +sequenceDecs_decodeSync_amd64_fill_2_byte_by_byte: + CMPQ SI, $0x00 + JLE sequenceDecs_decodeSync_amd64_fill_2_check_overread + CMPQ BX, $0x07 + JLE sequenceDecs_decodeSync_amd64_fill_2_end + SHLQ $0x08, DX + SUBQ $0x01, R13 + SUBQ $0x01, SI + SUBQ $0x08, BX + MOVBQZX (R13), AX + ORQ AX, DX + JMP sequenceDecs_decodeSync_amd64_fill_2_byte_by_byte + +sequenceDecs_decodeSync_amd64_fill_2_check_overread: + CMPQ BX, $0x40 + JA error_overread + +sequenceDecs_decodeSync_amd64_fill_2_end: + // Update literal length + MOVQ DI, AX + MOVQ BX, CX + MOVQ DX, R14 + SHLQ CL, R14 + MOVB AH, CL + SHRQ $0x20, AX + TESTQ CX, CX + JZ sequenceDecs_decodeSync_amd64_ll_update_zero + ADDQ CX, BX + CMPQ BX, $0x40 + JA sequenceDecs_decodeSync_amd64_ll_update_zero + CMPQ CX, $0x40 + JAE sequenceDecs_decodeSync_amd64_ll_update_zero + NEGQ CX + SHRQ CL, R14 + ADDQ R14, AX + +sequenceDecs_decodeSync_amd64_ll_update_zero: + MOVQ AX, 24(SP) + + // Fill bitreader for state updates + MOVQ R13, (SP) + MOVQ R9, AX + SHRQ $0x08, AX + MOVBQZX AL, AX + MOVQ ctx+16(FP), CX + CMPQ 96(CX), $0x00 + JZ sequenceDecs_decodeSync_amd64_skip_update + + // Update Literal Length State + MOVBQZX DI, R13 + SHRL $0x10, DI + LEAQ (BX)(R13*1), CX + MOVQ DX, R14 + MOVQ CX, BX + ROLQ CL, R14 + MOVL $0x00000001, R15 + MOVB R13, CL + SHLL CL, R15 + DECL R15 + ANDQ R15, R14 + ADDQ R14, DI + + // Load ctx.llTable + MOVQ ctx+16(FP), CX + MOVQ (CX), CX + MOVQ (CX)(DI*8), DI + + // Update Match Length State + MOVBQZX R8, R13 + SHRL $0x10, R8 + LEAQ (BX)(R13*1), CX + MOVQ DX, R14 + MOVQ CX, BX + ROLQ CL, R14 + MOVL $0x00000001, R15 + MOVB R13, CL + SHLL CL, R15 + DECL R15 + ANDQ R15, R14 + ADDQ R14, R8 + + // Load ctx.mlTable + MOVQ ctx+16(FP), CX + MOVQ 24(CX), CX + MOVQ (CX)(R8*8), R8 + + // Update Offset State + MOVBQZX R9, R13 + SHRL $0x10, R9 + LEAQ (BX)(R13*1), CX + MOVQ DX, R14 + MOVQ CX, BX + ROLQ CL, R14 + MOVL $0x00000001, R15 + MOVB R13, CL + SHLL CL, R15 + DECL R15 + ANDQ R15, R14 + ADDQ R14, R9 + + // Load ctx.ofTable + MOVQ ctx+16(FP), CX + MOVQ 48(CX), CX + MOVQ (CX)(R9*8), R9 + +sequenceDecs_decodeSync_amd64_skip_update: + // Adjust offset + MOVQ s+0(FP), CX + MOVQ 8(SP), R13 + CMPQ AX, $0x01 + JBE sequenceDecs_decodeSync_amd64_adjust_offsetB_1_or_0 + MOVUPS 144(CX), X0 + MOVQ R13, 144(CX) + MOVUPS X0, 152(CX) + JMP sequenceDecs_decodeSync_amd64_after_adjust + +sequenceDecs_decodeSync_amd64_adjust_offsetB_1_or_0: + CMPQ 24(SP), $0x00000000 + JNE sequenceDecs_decodeSync_amd64_adjust_offset_maybezero + INCQ R13 + JMP sequenceDecs_decodeSync_amd64_adjust_offset_nonzero + +sequenceDecs_decodeSync_amd64_adjust_offset_maybezero: + TESTQ R13, R13 + JNZ sequenceDecs_decodeSync_amd64_adjust_offset_nonzero + MOVQ 144(CX), R13 + JMP sequenceDecs_decodeSync_amd64_after_adjust + +sequenceDecs_decodeSync_amd64_adjust_offset_nonzero: + MOVQ R13, AX + XORQ R14, R14 + MOVQ $-1, R15 + CMPQ R13, $0x03 + CMOVQEQ R14, AX + CMOVQEQ R15, R14 + ADDQ 144(CX)(AX*8), R14 + JNZ sequenceDecs_decodeSync_amd64_adjust_temp_valid + MOVQ $0x00000001, R14 + +sequenceDecs_decodeSync_amd64_adjust_temp_valid: + CMPQ R13, $0x01 + JZ sequenceDecs_decodeSync_amd64_adjust_skip + MOVQ 152(CX), AX + MOVQ AX, 160(CX) + +sequenceDecs_decodeSync_amd64_adjust_skip: + MOVQ 144(CX), AX + MOVQ AX, 152(CX) + MOVQ R14, 144(CX) + MOVQ R14, R13 + +sequenceDecs_decodeSync_amd64_after_adjust: + MOVQ R13, 8(SP) + + // Check values + MOVQ 16(SP), AX + MOVQ 24(SP), CX + LEAQ (AX)(CX*1), R14 + MOVQ s+0(FP), R15 + ADDQ R14, 256(R15) + MOVQ ctx+16(FP), R14 + SUBQ CX, 104(R14) + JS error_not_enough_literals + CMPQ AX, $0x00020002 + JA sequenceDecs_decodeSync_amd64_error_match_len_too_big + TESTQ R13, R13 + JNZ sequenceDecs_decodeSync_amd64_match_len_ofs_ok + TESTQ AX, AX + JNZ sequenceDecs_decodeSync_amd64_error_match_len_ofs_mismatch + +sequenceDecs_decodeSync_amd64_match_len_ofs_ok: + MOVQ 24(SP), AX + MOVQ 8(SP), CX + MOVQ 16(SP), R13 + + // Check if we have enough space in s.out + LEAQ (AX)(R13*1), R14 + ADDQ R10, R14 + CMPQ R14, 32(SP) + JA error_not_enough_space + + // Copy literals + TESTQ AX, AX + JZ check_offset + XORQ R14, R14 + +copy_1: + MOVUPS (R11)(R14*1), X0 + MOVUPS X0, (R10)(R14*1) + ADDQ $0x10, R14 + CMPQ R14, AX + JB copy_1 + ADDQ AX, R11 + ADDQ AX, R10 + ADDQ AX, R12 + + // Malformed input if seq.mo > t+len(hist) || seq.mo > s.windowSize) +check_offset: + MOVQ R12, AX + ADDQ 40(SP), AX + CMPQ CX, AX + JG error_match_off_too_big + CMPQ CX, 56(SP) + JG error_match_off_too_big + + // Copy match from history + MOVQ CX, AX + SUBQ R12, AX + JLS copy_match + MOVQ 48(SP), R14 + SUBQ AX, R14 + CMPQ R13, AX + JG copy_all_from_history + MOVQ R13, AX + SUBQ $0x10, AX + JB copy_4_small + +copy_4_loop: + MOVUPS (R14), X0 + MOVUPS X0, (R10) + ADDQ $0x10, R14 + ADDQ $0x10, R10 + SUBQ $0x10, AX + JAE copy_4_loop + LEAQ 16(R14)(AX*1), R14 + LEAQ 16(R10)(AX*1), R10 + MOVUPS -16(R14), X0 + MOVUPS X0, -16(R10) + JMP copy_4_end + +copy_4_small: + CMPQ R13, $0x03 + JE copy_4_move_3 + CMPQ R13, $0x08 + JB copy_4_move_4through7 + JMP copy_4_move_8through16 + +copy_4_move_3: + MOVW (R14), AX + MOVB 2(R14), CL + MOVW AX, (R10) + MOVB CL, 2(R10) + ADDQ R13, R14 + ADDQ R13, R10 + JMP copy_4_end + +copy_4_move_4through7: + MOVL (R14), AX + MOVL -4(R14)(R13*1), CX + MOVL AX, (R10) + MOVL CX, -4(R10)(R13*1) + ADDQ R13, R14 + ADDQ R13, R10 + JMP copy_4_end + +copy_4_move_8through16: + MOVQ (R14), AX + MOVQ -8(R14)(R13*1), CX + MOVQ AX, (R10) + MOVQ CX, -8(R10)(R13*1) + ADDQ R13, R14 + ADDQ R13, R10 + +copy_4_end: + ADDQ R13, R12 + JMP handle_loop + JMP loop_finished + +copy_all_from_history: + MOVQ AX, R15 + SUBQ $0x10, R15 + JB copy_5_small + +copy_5_loop: + MOVUPS (R14), X0 + MOVUPS X0, (R10) + ADDQ $0x10, R14 + ADDQ $0x10, R10 + SUBQ $0x10, R15 + JAE copy_5_loop + LEAQ 16(R14)(R15*1), R14 + LEAQ 16(R10)(R15*1), R10 + MOVUPS -16(R14), X0 + MOVUPS X0, -16(R10) + JMP copy_5_end + +copy_5_small: + CMPQ AX, $0x03 + JE copy_5_move_3 + JB copy_5_move_1or2 + CMPQ AX, $0x08 + JB copy_5_move_4through7 + JMP copy_5_move_8through16 + +copy_5_move_1or2: + MOVB (R14), R15 + MOVB -1(R14)(AX*1), BP + MOVB R15, (R10) + MOVB BP, -1(R10)(AX*1) + ADDQ AX, R14 + ADDQ AX, R10 + JMP copy_5_end + +copy_5_move_3: + MOVW (R14), R15 + MOVB 2(R14), BP + MOVW R15, (R10) + MOVB BP, 2(R10) + ADDQ AX, R14 + ADDQ AX, R10 + JMP copy_5_end + +copy_5_move_4through7: + MOVL (R14), R15 + MOVL -4(R14)(AX*1), BP + MOVL R15, (R10) + MOVL BP, -4(R10)(AX*1) + ADDQ AX, R14 + ADDQ AX, R10 + JMP copy_5_end + +copy_5_move_8through16: + MOVQ (R14), R15 + MOVQ -8(R14)(AX*1), BP + MOVQ R15, (R10) + MOVQ BP, -8(R10)(AX*1) + ADDQ AX, R14 + ADDQ AX, R10 + +copy_5_end: + ADDQ AX, R12 + SUBQ AX, R13 + + // Copy match from the current buffer +copy_match: + MOVQ R10, AX + SUBQ CX, AX + + // ml <= mo + CMPQ R13, CX + JA copy_overlapping_match + + // Copy non-overlapping match + ADDQ R13, R12 + MOVQ R10, CX + ADDQ R13, R10 + +copy_2: + MOVUPS (AX), X0 + MOVUPS X0, (CX) + ADDQ $0x10, AX + ADDQ $0x10, CX + SUBQ $0x10, R13 + JHI copy_2 + JMP handle_loop + + // Copy overlapping match +copy_overlapping_match: + ADDQ R13, R12 + +copy_slow_3: + MOVB (AX), CL + MOVB CL, (R10) + INCQ AX + INCQ R10 + DECQ R13 + JNZ copy_slow_3 + +handle_loop: + MOVQ ctx+16(FP), AX + DECQ 96(AX) + JNS sequenceDecs_decodeSync_amd64_main_loop + +loop_finished: + MOVQ br+8(FP), AX + MOVQ DX, 24(AX) + MOVB BL, 32(AX) + MOVQ SI, 8(AX) + + // Update the context + MOVQ ctx+16(FP), AX + MOVQ R12, 136(AX) + MOVQ 144(AX), CX + SUBQ CX, R11 + MOVQ R11, 168(AX) + + // Return success + MOVQ $0x00000000, ret+24(FP) + RET + + // Return with match length error +sequenceDecs_decodeSync_amd64_error_match_len_ofs_mismatch: + MOVQ 16(SP), AX + MOVQ ctx+16(FP), CX + MOVQ AX, 216(CX) + MOVQ $0x00000001, ret+24(FP) + RET + + // Return with match too long error +sequenceDecs_decodeSync_amd64_error_match_len_too_big: + MOVQ ctx+16(FP), AX + MOVQ 16(SP), CX + MOVQ CX, 216(AX) + MOVQ $0x00000002, ret+24(FP) + RET + + // Return with match offset too long error +error_match_off_too_big: + MOVQ ctx+16(FP), AX + MOVQ 8(SP), CX + MOVQ CX, 224(AX) + MOVQ R12, 136(AX) + MOVQ $0x00000003, ret+24(FP) + RET + + // Return with not enough literals error +error_not_enough_literals: + MOVQ ctx+16(FP), AX + MOVQ 24(SP), CX + MOVQ CX, 208(AX) + MOVQ $0x00000004, ret+24(FP) + RET + + // Return with overread error +error_overread: + MOVQ $0x00000006, ret+24(FP) + RET + + // Return with not enough output space error +error_not_enough_space: + MOVQ ctx+16(FP), AX + MOVQ 24(SP), CX + MOVQ CX, 208(AX) + MOVQ 16(SP), CX + MOVQ CX, 216(AX) + MOVQ R12, 136(AX) + MOVQ $0x00000005, ret+24(FP) + RET + +// func sequenceDecs_decodeSync_bmi2(s *sequenceDecs, br *bitReader, ctx *decodeSyncAsmContext) int +// Requires: BMI, BMI2, CMOV, SSE +TEXT ·sequenceDecs_decodeSync_bmi2(SB), $64-32 + MOVQ br+8(FP), BX + MOVQ 24(BX), AX + MOVBQZX 32(BX), DX + MOVQ (BX), CX + MOVQ 8(BX), BX + ADDQ BX, CX + MOVQ CX, (SP) + MOVQ ctx+16(FP), CX + MOVQ 72(CX), SI + MOVQ 80(CX), DI + MOVQ 88(CX), R8 + XORQ R9, R9 + MOVQ R9, 8(SP) + MOVQ R9, 16(SP) + MOVQ R9, 24(SP) + MOVQ 112(CX), R9 + MOVQ 128(CX), R10 + MOVQ R10, 32(SP) + MOVQ 144(CX), R10 + MOVQ 136(CX), R11 + MOVQ 200(CX), R12 + MOVQ R12, 56(SP) + MOVQ 176(CX), R12 + MOVQ R12, 48(SP) + MOVQ 184(CX), CX + MOVQ CX, 40(SP) + MOVQ 40(SP), CX + ADDQ CX, 48(SP) + + // Calculate poiter to s.out[cap(s.out)] (a past-end pointer) + ADDQ R9, 32(SP) + + // outBase += outPosition + ADDQ R11, R9 + +sequenceDecs_decodeSync_bmi2_main_loop: + MOVQ (SP), R12 + + // Fill bitreader to have enough for the offset and match length. + CMPQ BX, $0x08 + JL sequenceDecs_decodeSync_bmi2_fill_byte_by_byte + MOVQ DX, CX + SHRQ $0x03, CX + SUBQ CX, R12 + MOVQ (R12), AX + SUBQ CX, BX + ANDQ $0x07, DX + JMP sequenceDecs_decodeSync_bmi2_fill_end + +sequenceDecs_decodeSync_bmi2_fill_byte_by_byte: + CMPQ BX, $0x00 + JLE sequenceDecs_decodeSync_bmi2_fill_check_overread + CMPQ DX, $0x07 + JLE sequenceDecs_decodeSync_bmi2_fill_end + SHLQ $0x08, AX + SUBQ $0x01, R12 + SUBQ $0x01, BX + SUBQ $0x08, DX + MOVBQZX (R12), CX + ORQ CX, AX + JMP sequenceDecs_decodeSync_bmi2_fill_byte_by_byte + +sequenceDecs_decodeSync_bmi2_fill_check_overread: + CMPQ DX, $0x40 + JA error_overread + +sequenceDecs_decodeSync_bmi2_fill_end: + // Update offset + MOVQ $0x00000808, CX + BEXTRQ CX, R8, R13 + MOVQ AX, R14 + LEAQ (DX)(R13*1), CX + ROLQ CL, R14 + BZHIQ R13, R14, R14 + MOVQ CX, DX + MOVQ R8, CX + SHRQ $0x20, CX + ADDQ R14, CX + MOVQ CX, 8(SP) + + // Update match length + MOVQ $0x00000808, CX + BEXTRQ CX, DI, R13 + MOVQ AX, R14 + LEAQ (DX)(R13*1), CX + ROLQ CL, R14 + BZHIQ R13, R14, R14 + MOVQ CX, DX + MOVQ DI, CX + SHRQ $0x20, CX + ADDQ R14, CX + MOVQ CX, 16(SP) + + // Fill bitreader to have enough for the remaining + CMPQ BX, $0x08 + JL sequenceDecs_decodeSync_bmi2_fill_2_byte_by_byte + MOVQ DX, CX + SHRQ $0x03, CX + SUBQ CX, R12 + MOVQ (R12), AX + SUBQ CX, BX + ANDQ $0x07, DX + JMP sequenceDecs_decodeSync_bmi2_fill_2_end + +sequenceDecs_decodeSync_bmi2_fill_2_byte_by_byte: + CMPQ BX, $0x00 + JLE sequenceDecs_decodeSync_bmi2_fill_2_check_overread + CMPQ DX, $0x07 + JLE sequenceDecs_decodeSync_bmi2_fill_2_end + SHLQ $0x08, AX + SUBQ $0x01, R12 + SUBQ $0x01, BX + SUBQ $0x08, DX + MOVBQZX (R12), CX + ORQ CX, AX + JMP sequenceDecs_decodeSync_bmi2_fill_2_byte_by_byte + +sequenceDecs_decodeSync_bmi2_fill_2_check_overread: + CMPQ DX, $0x40 + JA error_overread + +sequenceDecs_decodeSync_bmi2_fill_2_end: + // Update literal length + MOVQ $0x00000808, CX + BEXTRQ CX, SI, R13 + MOVQ AX, R14 + LEAQ (DX)(R13*1), CX + ROLQ CL, R14 + BZHIQ R13, R14, R14 + MOVQ CX, DX + MOVQ SI, CX + SHRQ $0x20, CX + ADDQ R14, CX + MOVQ CX, 24(SP) + + // Fill bitreader for state updates + MOVQ R12, (SP) + MOVQ $0x00000808, CX + BEXTRQ CX, R8, R12 + MOVQ ctx+16(FP), CX + CMPQ 96(CX), $0x00 + JZ sequenceDecs_decodeSync_bmi2_skip_update + LEAQ (SI)(DI*1), R13 + ADDQ R8, R13 + MOVBQZX R13, R13 + LEAQ (DX)(R13*1), CX + MOVQ AX, R14 + MOVQ CX, DX + ROLQ CL, R14 + BZHIQ R13, R14, R14 + + // Update Offset State + BZHIQ R8, R14, CX + SHRXQ R8, R14, R14 + SHRL $0x10, R8 + ADDQ CX, R8 + + // Load ctx.ofTable + MOVQ ctx+16(FP), CX + MOVQ 48(CX), CX + MOVQ (CX)(R8*8), R8 + + // Update Match Length State + BZHIQ DI, R14, CX + SHRXQ DI, R14, R14 + SHRL $0x10, DI + ADDQ CX, DI + + // Load ctx.mlTable + MOVQ ctx+16(FP), CX + MOVQ 24(CX), CX + MOVQ (CX)(DI*8), DI + + // Update Literal Length State + BZHIQ SI, R14, CX + SHRL $0x10, SI + ADDQ CX, SI + + // Load ctx.llTable + MOVQ ctx+16(FP), CX + MOVQ (CX), CX + MOVQ (CX)(SI*8), SI + +sequenceDecs_decodeSync_bmi2_skip_update: + // Adjust offset + MOVQ s+0(FP), CX + MOVQ 8(SP), R13 + CMPQ R12, $0x01 + JBE sequenceDecs_decodeSync_bmi2_adjust_offsetB_1_or_0 + MOVUPS 144(CX), X0 + MOVQ R13, 144(CX) + MOVUPS X0, 152(CX) + JMP sequenceDecs_decodeSync_bmi2_after_adjust + +sequenceDecs_decodeSync_bmi2_adjust_offsetB_1_or_0: + CMPQ 24(SP), $0x00000000 + JNE sequenceDecs_decodeSync_bmi2_adjust_offset_maybezero + INCQ R13 + JMP sequenceDecs_decodeSync_bmi2_adjust_offset_nonzero + +sequenceDecs_decodeSync_bmi2_adjust_offset_maybezero: + TESTQ R13, R13 + JNZ sequenceDecs_decodeSync_bmi2_adjust_offset_nonzero + MOVQ 144(CX), R13 + JMP sequenceDecs_decodeSync_bmi2_after_adjust + +sequenceDecs_decodeSync_bmi2_adjust_offset_nonzero: + MOVQ R13, R12 + XORQ R14, R14 + MOVQ $-1, R15 + CMPQ R13, $0x03 + CMOVQEQ R14, R12 + CMOVQEQ R15, R14 + ADDQ 144(CX)(R12*8), R14 + JNZ sequenceDecs_decodeSync_bmi2_adjust_temp_valid + MOVQ $0x00000001, R14 + +sequenceDecs_decodeSync_bmi2_adjust_temp_valid: + CMPQ R13, $0x01 + JZ sequenceDecs_decodeSync_bmi2_adjust_skip + MOVQ 152(CX), R12 + MOVQ R12, 160(CX) + +sequenceDecs_decodeSync_bmi2_adjust_skip: + MOVQ 144(CX), R12 + MOVQ R12, 152(CX) + MOVQ R14, 144(CX) + MOVQ R14, R13 + +sequenceDecs_decodeSync_bmi2_after_adjust: + MOVQ R13, 8(SP) + + // Check values + MOVQ 16(SP), CX + MOVQ 24(SP), R12 + LEAQ (CX)(R12*1), R14 + MOVQ s+0(FP), R15 + ADDQ R14, 256(R15) + MOVQ ctx+16(FP), R14 + SUBQ R12, 104(R14) + JS error_not_enough_literals + CMPQ CX, $0x00020002 + JA sequenceDecs_decodeSync_bmi2_error_match_len_too_big + TESTQ R13, R13 + JNZ sequenceDecs_decodeSync_bmi2_match_len_ofs_ok + TESTQ CX, CX + JNZ sequenceDecs_decodeSync_bmi2_error_match_len_ofs_mismatch + +sequenceDecs_decodeSync_bmi2_match_len_ofs_ok: + MOVQ 24(SP), CX + MOVQ 8(SP), R12 + MOVQ 16(SP), R13 + + // Check if we have enough space in s.out + LEAQ (CX)(R13*1), R14 + ADDQ R9, R14 + CMPQ R14, 32(SP) + JA error_not_enough_space + + // Copy literals + TESTQ CX, CX + JZ check_offset + XORQ R14, R14 + +copy_1: + MOVUPS (R10)(R14*1), X0 + MOVUPS X0, (R9)(R14*1) + ADDQ $0x10, R14 + CMPQ R14, CX + JB copy_1 + ADDQ CX, R10 + ADDQ CX, R9 + ADDQ CX, R11 + + // Malformed input if seq.mo > t+len(hist) || seq.mo > s.windowSize) +check_offset: + MOVQ R11, CX + ADDQ 40(SP), CX + CMPQ R12, CX + JG error_match_off_too_big + CMPQ R12, 56(SP) + JG error_match_off_too_big + + // Copy match from history + MOVQ R12, CX + SUBQ R11, CX + JLS copy_match + MOVQ 48(SP), R14 + SUBQ CX, R14 + CMPQ R13, CX + JG copy_all_from_history + MOVQ R13, CX + SUBQ $0x10, CX + JB copy_4_small + +copy_4_loop: + MOVUPS (R14), X0 + MOVUPS X0, (R9) + ADDQ $0x10, R14 + ADDQ $0x10, R9 + SUBQ $0x10, CX + JAE copy_4_loop + LEAQ 16(R14)(CX*1), R14 + LEAQ 16(R9)(CX*1), R9 + MOVUPS -16(R14), X0 + MOVUPS X0, -16(R9) + JMP copy_4_end + +copy_4_small: + CMPQ R13, $0x03 + JE copy_4_move_3 + CMPQ R13, $0x08 + JB copy_4_move_4through7 + JMP copy_4_move_8through16 + +copy_4_move_3: + MOVW (R14), CX + MOVB 2(R14), R12 + MOVW CX, (R9) + MOVB R12, 2(R9) + ADDQ R13, R14 + ADDQ R13, R9 + JMP copy_4_end + +copy_4_move_4through7: + MOVL (R14), CX + MOVL -4(R14)(R13*1), R12 + MOVL CX, (R9) + MOVL R12, -4(R9)(R13*1) + ADDQ R13, R14 + ADDQ R13, R9 + JMP copy_4_end + +copy_4_move_8through16: + MOVQ (R14), CX + MOVQ -8(R14)(R13*1), R12 + MOVQ CX, (R9) + MOVQ R12, -8(R9)(R13*1) + ADDQ R13, R14 + ADDQ R13, R9 + +copy_4_end: + ADDQ R13, R11 + JMP handle_loop + JMP loop_finished + +copy_all_from_history: + MOVQ CX, R15 + SUBQ $0x10, R15 + JB copy_5_small + +copy_5_loop: + MOVUPS (R14), X0 + MOVUPS X0, (R9) + ADDQ $0x10, R14 + ADDQ $0x10, R9 + SUBQ $0x10, R15 + JAE copy_5_loop + LEAQ 16(R14)(R15*1), R14 + LEAQ 16(R9)(R15*1), R9 + MOVUPS -16(R14), X0 + MOVUPS X0, -16(R9) + JMP copy_5_end + +copy_5_small: + CMPQ CX, $0x03 + JE copy_5_move_3 + JB copy_5_move_1or2 + CMPQ CX, $0x08 + JB copy_5_move_4through7 + JMP copy_5_move_8through16 + +copy_5_move_1or2: + MOVB (R14), R15 + MOVB -1(R14)(CX*1), BP + MOVB R15, (R9) + MOVB BP, -1(R9)(CX*1) + ADDQ CX, R14 + ADDQ CX, R9 + JMP copy_5_end + +copy_5_move_3: + MOVW (R14), R15 + MOVB 2(R14), BP + MOVW R15, (R9) + MOVB BP, 2(R9) + ADDQ CX, R14 + ADDQ CX, R9 + JMP copy_5_end + +copy_5_move_4through7: + MOVL (R14), R15 + MOVL -4(R14)(CX*1), BP + MOVL R15, (R9) + MOVL BP, -4(R9)(CX*1) + ADDQ CX, R14 + ADDQ CX, R9 + JMP copy_5_end + +copy_5_move_8through16: + MOVQ (R14), R15 + MOVQ -8(R14)(CX*1), BP + MOVQ R15, (R9) + MOVQ BP, -8(R9)(CX*1) + ADDQ CX, R14 + ADDQ CX, R9 + +copy_5_end: + ADDQ CX, R11 + SUBQ CX, R13 + + // Copy match from the current buffer +copy_match: + MOVQ R9, CX + SUBQ R12, CX + + // ml <= mo + CMPQ R13, R12 + JA copy_overlapping_match + + // Copy non-overlapping match + ADDQ R13, R11 + MOVQ R9, R12 + ADDQ R13, R9 + +copy_2: + MOVUPS (CX), X0 + MOVUPS X0, (R12) + ADDQ $0x10, CX + ADDQ $0x10, R12 + SUBQ $0x10, R13 + JHI copy_2 + JMP handle_loop + + // Copy overlapping match +copy_overlapping_match: + ADDQ R13, R11 + +copy_slow_3: + MOVB (CX), R12 + MOVB R12, (R9) + INCQ CX + INCQ R9 + DECQ R13 + JNZ copy_slow_3 + +handle_loop: + MOVQ ctx+16(FP), CX + DECQ 96(CX) + JNS sequenceDecs_decodeSync_bmi2_main_loop + +loop_finished: + MOVQ br+8(FP), CX + MOVQ AX, 24(CX) + MOVB DL, 32(CX) + MOVQ BX, 8(CX) + + // Update the context + MOVQ ctx+16(FP), AX + MOVQ R11, 136(AX) + MOVQ 144(AX), CX + SUBQ CX, R10 + MOVQ R10, 168(AX) + + // Return success + MOVQ $0x00000000, ret+24(FP) + RET + + // Return with match length error +sequenceDecs_decodeSync_bmi2_error_match_len_ofs_mismatch: + MOVQ 16(SP), AX + MOVQ ctx+16(FP), CX + MOVQ AX, 216(CX) + MOVQ $0x00000001, ret+24(FP) + RET + + // Return with match too long error +sequenceDecs_decodeSync_bmi2_error_match_len_too_big: + MOVQ ctx+16(FP), AX + MOVQ 16(SP), CX + MOVQ CX, 216(AX) + MOVQ $0x00000002, ret+24(FP) + RET + + // Return with match offset too long error +error_match_off_too_big: + MOVQ ctx+16(FP), AX + MOVQ 8(SP), CX + MOVQ CX, 224(AX) + MOVQ R11, 136(AX) + MOVQ $0x00000003, ret+24(FP) + RET + + // Return with not enough literals error +error_not_enough_literals: + MOVQ ctx+16(FP), AX + MOVQ 24(SP), CX + MOVQ CX, 208(AX) + MOVQ $0x00000004, ret+24(FP) + RET + + // Return with overread error +error_overread: + MOVQ $0x00000006, ret+24(FP) + RET + + // Return with not enough output space error +error_not_enough_space: + MOVQ ctx+16(FP), AX + MOVQ 24(SP), CX + MOVQ CX, 208(AX) + MOVQ 16(SP), CX + MOVQ CX, 216(AX) + MOVQ R11, 136(AX) + MOVQ $0x00000005, ret+24(FP) + RET + +// func sequenceDecs_decodeSync_safe_amd64(s *sequenceDecs, br *bitReader, ctx *decodeSyncAsmContext) int +// Requires: CMOV, SSE +TEXT ·sequenceDecs_decodeSync_safe_amd64(SB), $64-32 + MOVQ br+8(FP), CX + MOVQ 24(CX), DX + MOVBQZX 32(CX), BX + MOVQ (CX), AX + MOVQ 8(CX), SI + ADDQ SI, AX + MOVQ AX, (SP) + MOVQ ctx+16(FP), AX + MOVQ 72(AX), DI + MOVQ 80(AX), R8 + MOVQ 88(AX), R9 + XORQ CX, CX + MOVQ CX, 8(SP) + MOVQ CX, 16(SP) + MOVQ CX, 24(SP) + MOVQ 112(AX), R10 + MOVQ 128(AX), CX + MOVQ CX, 32(SP) + MOVQ 144(AX), R11 + MOVQ 136(AX), R12 + MOVQ 200(AX), CX + MOVQ CX, 56(SP) + MOVQ 176(AX), CX + MOVQ CX, 48(SP) + MOVQ 184(AX), AX + MOVQ AX, 40(SP) + MOVQ 40(SP), AX + ADDQ AX, 48(SP) + + // Calculate poiter to s.out[cap(s.out)] (a past-end pointer) + ADDQ R10, 32(SP) + + // outBase += outPosition + ADDQ R12, R10 + +sequenceDecs_decodeSync_safe_amd64_main_loop: + MOVQ (SP), R13 + + // Fill bitreader to have enough for the offset and match length. + CMPQ SI, $0x08 + JL sequenceDecs_decodeSync_safe_amd64_fill_byte_by_byte + MOVQ BX, AX + SHRQ $0x03, AX + SUBQ AX, R13 + MOVQ (R13), DX + SUBQ AX, SI + ANDQ $0x07, BX + JMP sequenceDecs_decodeSync_safe_amd64_fill_end + +sequenceDecs_decodeSync_safe_amd64_fill_byte_by_byte: + CMPQ SI, $0x00 + JLE sequenceDecs_decodeSync_safe_amd64_fill_check_overread + CMPQ BX, $0x07 + JLE sequenceDecs_decodeSync_safe_amd64_fill_end + SHLQ $0x08, DX + SUBQ $0x01, R13 + SUBQ $0x01, SI + SUBQ $0x08, BX + MOVBQZX (R13), AX + ORQ AX, DX + JMP sequenceDecs_decodeSync_safe_amd64_fill_byte_by_byte + +sequenceDecs_decodeSync_safe_amd64_fill_check_overread: + CMPQ BX, $0x40 + JA error_overread + +sequenceDecs_decodeSync_safe_amd64_fill_end: + // Update offset + MOVQ R9, AX + MOVQ BX, CX + MOVQ DX, R14 + SHLQ CL, R14 + MOVB AH, CL + SHRQ $0x20, AX + TESTQ CX, CX + JZ sequenceDecs_decodeSync_safe_amd64_of_update_zero + ADDQ CX, BX + CMPQ BX, $0x40 + JA sequenceDecs_decodeSync_safe_amd64_of_update_zero + CMPQ CX, $0x40 + JAE sequenceDecs_decodeSync_safe_amd64_of_update_zero + NEGQ CX + SHRQ CL, R14 + ADDQ R14, AX + +sequenceDecs_decodeSync_safe_amd64_of_update_zero: + MOVQ AX, 8(SP) + + // Update match length + MOVQ R8, AX + MOVQ BX, CX + MOVQ DX, R14 + SHLQ CL, R14 + MOVB AH, CL + SHRQ $0x20, AX + TESTQ CX, CX + JZ sequenceDecs_decodeSync_safe_amd64_ml_update_zero + ADDQ CX, BX + CMPQ BX, $0x40 + JA sequenceDecs_decodeSync_safe_amd64_ml_update_zero + CMPQ CX, $0x40 + JAE sequenceDecs_decodeSync_safe_amd64_ml_update_zero + NEGQ CX + SHRQ CL, R14 + ADDQ R14, AX + +sequenceDecs_decodeSync_safe_amd64_ml_update_zero: + MOVQ AX, 16(SP) + + // Fill bitreader to have enough for the remaining + CMPQ SI, $0x08 + JL sequenceDecs_decodeSync_safe_amd64_fill_2_byte_by_byte + MOVQ BX, AX + SHRQ $0x03, AX + SUBQ AX, R13 + MOVQ (R13), DX + SUBQ AX, SI + ANDQ $0x07, BX + JMP sequenceDecs_decodeSync_safe_amd64_fill_2_end + +sequenceDecs_decodeSync_safe_amd64_fill_2_byte_by_byte: + CMPQ SI, $0x00 + JLE sequenceDecs_decodeSync_safe_amd64_fill_2_check_overread + CMPQ BX, $0x07 + JLE sequenceDecs_decodeSync_safe_amd64_fill_2_end + SHLQ $0x08, DX + SUBQ $0x01, R13 + SUBQ $0x01, SI + SUBQ $0x08, BX + MOVBQZX (R13), AX + ORQ AX, DX + JMP sequenceDecs_decodeSync_safe_amd64_fill_2_byte_by_byte + +sequenceDecs_decodeSync_safe_amd64_fill_2_check_overread: + CMPQ BX, $0x40 + JA error_overread + +sequenceDecs_decodeSync_safe_amd64_fill_2_end: + // Update literal length + MOVQ DI, AX + MOVQ BX, CX + MOVQ DX, R14 + SHLQ CL, R14 + MOVB AH, CL + SHRQ $0x20, AX + TESTQ CX, CX + JZ sequenceDecs_decodeSync_safe_amd64_ll_update_zero + ADDQ CX, BX + CMPQ BX, $0x40 + JA sequenceDecs_decodeSync_safe_amd64_ll_update_zero + CMPQ CX, $0x40 + JAE sequenceDecs_decodeSync_safe_amd64_ll_update_zero + NEGQ CX + SHRQ CL, R14 + ADDQ R14, AX + +sequenceDecs_decodeSync_safe_amd64_ll_update_zero: + MOVQ AX, 24(SP) + + // Fill bitreader for state updates + MOVQ R13, (SP) + MOVQ R9, AX + SHRQ $0x08, AX + MOVBQZX AL, AX + MOVQ ctx+16(FP), CX + CMPQ 96(CX), $0x00 + JZ sequenceDecs_decodeSync_safe_amd64_skip_update + + // Update Literal Length State + MOVBQZX DI, R13 + SHRL $0x10, DI + LEAQ (BX)(R13*1), CX + MOVQ DX, R14 + MOVQ CX, BX + ROLQ CL, R14 + MOVL $0x00000001, R15 + MOVB R13, CL + SHLL CL, R15 + DECL R15 + ANDQ R15, R14 + ADDQ R14, DI + + // Load ctx.llTable + MOVQ ctx+16(FP), CX + MOVQ (CX), CX + MOVQ (CX)(DI*8), DI + + // Update Match Length State + MOVBQZX R8, R13 + SHRL $0x10, R8 + LEAQ (BX)(R13*1), CX + MOVQ DX, R14 + MOVQ CX, BX + ROLQ CL, R14 + MOVL $0x00000001, R15 + MOVB R13, CL + SHLL CL, R15 + DECL R15 + ANDQ R15, R14 + ADDQ R14, R8 + + // Load ctx.mlTable + MOVQ ctx+16(FP), CX + MOVQ 24(CX), CX + MOVQ (CX)(R8*8), R8 + + // Update Offset State + MOVBQZX R9, R13 + SHRL $0x10, R9 + LEAQ (BX)(R13*1), CX + MOVQ DX, R14 + MOVQ CX, BX + ROLQ CL, R14 + MOVL $0x00000001, R15 + MOVB R13, CL + SHLL CL, R15 + DECL R15 + ANDQ R15, R14 + ADDQ R14, R9 + + // Load ctx.ofTable + MOVQ ctx+16(FP), CX + MOVQ 48(CX), CX + MOVQ (CX)(R9*8), R9 + +sequenceDecs_decodeSync_safe_amd64_skip_update: + // Adjust offset + MOVQ s+0(FP), CX + MOVQ 8(SP), R13 + CMPQ AX, $0x01 + JBE sequenceDecs_decodeSync_safe_amd64_adjust_offsetB_1_or_0 + MOVUPS 144(CX), X0 + MOVQ R13, 144(CX) + MOVUPS X0, 152(CX) + JMP sequenceDecs_decodeSync_safe_amd64_after_adjust + +sequenceDecs_decodeSync_safe_amd64_adjust_offsetB_1_or_0: + CMPQ 24(SP), $0x00000000 + JNE sequenceDecs_decodeSync_safe_amd64_adjust_offset_maybezero + INCQ R13 + JMP sequenceDecs_decodeSync_safe_amd64_adjust_offset_nonzero + +sequenceDecs_decodeSync_safe_amd64_adjust_offset_maybezero: + TESTQ R13, R13 + JNZ sequenceDecs_decodeSync_safe_amd64_adjust_offset_nonzero + MOVQ 144(CX), R13 + JMP sequenceDecs_decodeSync_safe_amd64_after_adjust + +sequenceDecs_decodeSync_safe_amd64_adjust_offset_nonzero: + MOVQ R13, AX + XORQ R14, R14 + MOVQ $-1, R15 + CMPQ R13, $0x03 + CMOVQEQ R14, AX + CMOVQEQ R15, R14 + ADDQ 144(CX)(AX*8), R14 + JNZ sequenceDecs_decodeSync_safe_amd64_adjust_temp_valid + MOVQ $0x00000001, R14 + +sequenceDecs_decodeSync_safe_amd64_adjust_temp_valid: + CMPQ R13, $0x01 + JZ sequenceDecs_decodeSync_safe_amd64_adjust_skip + MOVQ 152(CX), AX + MOVQ AX, 160(CX) + +sequenceDecs_decodeSync_safe_amd64_adjust_skip: + MOVQ 144(CX), AX + MOVQ AX, 152(CX) + MOVQ R14, 144(CX) + MOVQ R14, R13 + +sequenceDecs_decodeSync_safe_amd64_after_adjust: + MOVQ R13, 8(SP) + + // Check values + MOVQ 16(SP), AX + MOVQ 24(SP), CX + LEAQ (AX)(CX*1), R14 + MOVQ s+0(FP), R15 + ADDQ R14, 256(R15) + MOVQ ctx+16(FP), R14 + SUBQ CX, 104(R14) + JS error_not_enough_literals + CMPQ AX, $0x00020002 + JA sequenceDecs_decodeSync_safe_amd64_error_match_len_too_big + TESTQ R13, R13 + JNZ sequenceDecs_decodeSync_safe_amd64_match_len_ofs_ok + TESTQ AX, AX + JNZ sequenceDecs_decodeSync_safe_amd64_error_match_len_ofs_mismatch + +sequenceDecs_decodeSync_safe_amd64_match_len_ofs_ok: + MOVQ 24(SP), AX + MOVQ 8(SP), CX + MOVQ 16(SP), R13 + + // Check if we have enough space in s.out + LEAQ (AX)(R13*1), R14 + ADDQ R10, R14 + CMPQ R14, 32(SP) + JA error_not_enough_space + + // Copy literals + TESTQ AX, AX + JZ check_offset + MOVQ AX, R14 + SUBQ $0x10, R14 + JB copy_1_small + +copy_1_loop: + MOVUPS (R11), X0 + MOVUPS X0, (R10) + ADDQ $0x10, R11 + ADDQ $0x10, R10 + SUBQ $0x10, R14 + JAE copy_1_loop + LEAQ 16(R11)(R14*1), R11 + LEAQ 16(R10)(R14*1), R10 + MOVUPS -16(R11), X0 + MOVUPS X0, -16(R10) + JMP copy_1_end + +copy_1_small: + CMPQ AX, $0x03 + JE copy_1_move_3 + JB copy_1_move_1or2 + CMPQ AX, $0x08 + JB copy_1_move_4through7 + JMP copy_1_move_8through16 + +copy_1_move_1or2: + MOVB (R11), R14 + MOVB -1(R11)(AX*1), R15 + MOVB R14, (R10) + MOVB R15, -1(R10)(AX*1) + ADDQ AX, R11 + ADDQ AX, R10 + JMP copy_1_end + +copy_1_move_3: + MOVW (R11), R14 + MOVB 2(R11), R15 + MOVW R14, (R10) + MOVB R15, 2(R10) + ADDQ AX, R11 + ADDQ AX, R10 + JMP copy_1_end + +copy_1_move_4through7: + MOVL (R11), R14 + MOVL -4(R11)(AX*1), R15 + MOVL R14, (R10) + MOVL R15, -4(R10)(AX*1) + ADDQ AX, R11 + ADDQ AX, R10 + JMP copy_1_end + +copy_1_move_8through16: + MOVQ (R11), R14 + MOVQ -8(R11)(AX*1), R15 + MOVQ R14, (R10) + MOVQ R15, -8(R10)(AX*1) + ADDQ AX, R11 + ADDQ AX, R10 + +copy_1_end: + ADDQ AX, R12 + + // Malformed input if seq.mo > t+len(hist) || seq.mo > s.windowSize) +check_offset: + MOVQ R12, AX + ADDQ 40(SP), AX + CMPQ CX, AX + JG error_match_off_too_big + CMPQ CX, 56(SP) + JG error_match_off_too_big + + // Copy match from history + MOVQ CX, AX + SUBQ R12, AX + JLS copy_match + MOVQ 48(SP), R14 + SUBQ AX, R14 + CMPQ R13, AX + JG copy_all_from_history + MOVQ R13, AX + SUBQ $0x10, AX + JB copy_4_small + +copy_4_loop: + MOVUPS (R14), X0 + MOVUPS X0, (R10) + ADDQ $0x10, R14 + ADDQ $0x10, R10 + SUBQ $0x10, AX + JAE copy_4_loop + LEAQ 16(R14)(AX*1), R14 + LEAQ 16(R10)(AX*1), R10 + MOVUPS -16(R14), X0 + MOVUPS X0, -16(R10) + JMP copy_4_end + +copy_4_small: + CMPQ R13, $0x03 + JE copy_4_move_3 + CMPQ R13, $0x08 + JB copy_4_move_4through7 + JMP copy_4_move_8through16 + +copy_4_move_3: + MOVW (R14), AX + MOVB 2(R14), CL + MOVW AX, (R10) + MOVB CL, 2(R10) + ADDQ R13, R14 + ADDQ R13, R10 + JMP copy_4_end + +copy_4_move_4through7: + MOVL (R14), AX + MOVL -4(R14)(R13*1), CX + MOVL AX, (R10) + MOVL CX, -4(R10)(R13*1) + ADDQ R13, R14 + ADDQ R13, R10 + JMP copy_4_end + +copy_4_move_8through16: + MOVQ (R14), AX + MOVQ -8(R14)(R13*1), CX + MOVQ AX, (R10) + MOVQ CX, -8(R10)(R13*1) + ADDQ R13, R14 + ADDQ R13, R10 + +copy_4_end: + ADDQ R13, R12 + JMP handle_loop + JMP loop_finished + +copy_all_from_history: + MOVQ AX, R15 + SUBQ $0x10, R15 + JB copy_5_small + +copy_5_loop: + MOVUPS (R14), X0 + MOVUPS X0, (R10) + ADDQ $0x10, R14 + ADDQ $0x10, R10 + SUBQ $0x10, R15 + JAE copy_5_loop + LEAQ 16(R14)(R15*1), R14 + LEAQ 16(R10)(R15*1), R10 + MOVUPS -16(R14), X0 + MOVUPS X0, -16(R10) + JMP copy_5_end + +copy_5_small: + CMPQ AX, $0x03 + JE copy_5_move_3 + JB copy_5_move_1or2 + CMPQ AX, $0x08 + JB copy_5_move_4through7 + JMP copy_5_move_8through16 + +copy_5_move_1or2: + MOVB (R14), R15 + MOVB -1(R14)(AX*1), BP + MOVB R15, (R10) + MOVB BP, -1(R10)(AX*1) + ADDQ AX, R14 + ADDQ AX, R10 + JMP copy_5_end + +copy_5_move_3: + MOVW (R14), R15 + MOVB 2(R14), BP + MOVW R15, (R10) + MOVB BP, 2(R10) + ADDQ AX, R14 + ADDQ AX, R10 + JMP copy_5_end + +copy_5_move_4through7: + MOVL (R14), R15 + MOVL -4(R14)(AX*1), BP + MOVL R15, (R10) + MOVL BP, -4(R10)(AX*1) + ADDQ AX, R14 + ADDQ AX, R10 + JMP copy_5_end + +copy_5_move_8through16: + MOVQ (R14), R15 + MOVQ -8(R14)(AX*1), BP + MOVQ R15, (R10) + MOVQ BP, -8(R10)(AX*1) + ADDQ AX, R14 + ADDQ AX, R10 + +copy_5_end: + ADDQ AX, R12 + SUBQ AX, R13 + + // Copy match from the current buffer +copy_match: + MOVQ R10, AX + SUBQ CX, AX + + // ml <= mo + CMPQ R13, CX + JA copy_overlapping_match + + // Copy non-overlapping match + ADDQ R13, R12 + MOVQ R13, CX + SUBQ $0x10, CX + JB copy_2_small + +copy_2_loop: + MOVUPS (AX), X0 + MOVUPS X0, (R10) + ADDQ $0x10, AX + ADDQ $0x10, R10 + SUBQ $0x10, CX + JAE copy_2_loop + LEAQ 16(AX)(CX*1), AX + LEAQ 16(R10)(CX*1), R10 + MOVUPS -16(AX), X0 + MOVUPS X0, -16(R10) + JMP copy_2_end + +copy_2_small: + CMPQ R13, $0x03 + JE copy_2_move_3 + JB copy_2_move_1or2 + CMPQ R13, $0x08 + JB copy_2_move_4through7 + JMP copy_2_move_8through16 + +copy_2_move_1or2: + MOVB (AX), CL + MOVB -1(AX)(R13*1), R14 + MOVB CL, (R10) + MOVB R14, -1(R10)(R13*1) + ADDQ R13, AX + ADDQ R13, R10 + JMP copy_2_end + +copy_2_move_3: + MOVW (AX), CX + MOVB 2(AX), R14 + MOVW CX, (R10) + MOVB R14, 2(R10) + ADDQ R13, AX + ADDQ R13, R10 + JMP copy_2_end + +copy_2_move_4through7: + MOVL (AX), CX + MOVL -4(AX)(R13*1), R14 + MOVL CX, (R10) + MOVL R14, -4(R10)(R13*1) + ADDQ R13, AX + ADDQ R13, R10 + JMP copy_2_end + +copy_2_move_8through16: + MOVQ (AX), CX + MOVQ -8(AX)(R13*1), R14 + MOVQ CX, (R10) + MOVQ R14, -8(R10)(R13*1) + ADDQ R13, AX + ADDQ R13, R10 + +copy_2_end: + JMP handle_loop + + // Copy overlapping match +copy_overlapping_match: + ADDQ R13, R12 + +copy_slow_3: + MOVB (AX), CL + MOVB CL, (R10) + INCQ AX + INCQ R10 + DECQ R13 + JNZ copy_slow_3 + +handle_loop: + MOVQ ctx+16(FP), AX + DECQ 96(AX) + JNS sequenceDecs_decodeSync_safe_amd64_main_loop + +loop_finished: + MOVQ br+8(FP), AX + MOVQ DX, 24(AX) + MOVB BL, 32(AX) + MOVQ SI, 8(AX) + + // Update the context + MOVQ ctx+16(FP), AX + MOVQ R12, 136(AX) + MOVQ 144(AX), CX + SUBQ CX, R11 + MOVQ R11, 168(AX) + + // Return success + MOVQ $0x00000000, ret+24(FP) + RET + + // Return with match length error +sequenceDecs_decodeSync_safe_amd64_error_match_len_ofs_mismatch: + MOVQ 16(SP), AX + MOVQ ctx+16(FP), CX + MOVQ AX, 216(CX) + MOVQ $0x00000001, ret+24(FP) + RET + + // Return with match too long error +sequenceDecs_decodeSync_safe_amd64_error_match_len_too_big: + MOVQ ctx+16(FP), AX + MOVQ 16(SP), CX + MOVQ CX, 216(AX) + MOVQ $0x00000002, ret+24(FP) + RET + + // Return with match offset too long error +error_match_off_too_big: + MOVQ ctx+16(FP), AX + MOVQ 8(SP), CX + MOVQ CX, 224(AX) + MOVQ R12, 136(AX) + MOVQ $0x00000003, ret+24(FP) + RET + + // Return with not enough literals error +error_not_enough_literals: + MOVQ ctx+16(FP), AX + MOVQ 24(SP), CX + MOVQ CX, 208(AX) + MOVQ $0x00000004, ret+24(FP) + RET + + // Return with overread error +error_overread: + MOVQ $0x00000006, ret+24(FP) + RET + + // Return with not enough output space error +error_not_enough_space: + MOVQ ctx+16(FP), AX + MOVQ 24(SP), CX + MOVQ CX, 208(AX) + MOVQ 16(SP), CX + MOVQ CX, 216(AX) + MOVQ R12, 136(AX) + MOVQ $0x00000005, ret+24(FP) + RET + +// func sequenceDecs_decodeSync_safe_bmi2(s *sequenceDecs, br *bitReader, ctx *decodeSyncAsmContext) int +// Requires: BMI, BMI2, CMOV, SSE +TEXT ·sequenceDecs_decodeSync_safe_bmi2(SB), $64-32 + MOVQ br+8(FP), BX + MOVQ 24(BX), AX + MOVBQZX 32(BX), DX + MOVQ (BX), CX + MOVQ 8(BX), BX + ADDQ BX, CX + MOVQ CX, (SP) + MOVQ ctx+16(FP), CX + MOVQ 72(CX), SI + MOVQ 80(CX), DI + MOVQ 88(CX), R8 + XORQ R9, R9 + MOVQ R9, 8(SP) + MOVQ R9, 16(SP) + MOVQ R9, 24(SP) + MOVQ 112(CX), R9 + MOVQ 128(CX), R10 + MOVQ R10, 32(SP) + MOVQ 144(CX), R10 + MOVQ 136(CX), R11 + MOVQ 200(CX), R12 + MOVQ R12, 56(SP) + MOVQ 176(CX), R12 + MOVQ R12, 48(SP) + MOVQ 184(CX), CX + MOVQ CX, 40(SP) + MOVQ 40(SP), CX + ADDQ CX, 48(SP) + + // Calculate poiter to s.out[cap(s.out)] (a past-end pointer) + ADDQ R9, 32(SP) + + // outBase += outPosition + ADDQ R11, R9 + +sequenceDecs_decodeSync_safe_bmi2_main_loop: + MOVQ (SP), R12 + + // Fill bitreader to have enough for the offset and match length. + CMPQ BX, $0x08 + JL sequenceDecs_decodeSync_safe_bmi2_fill_byte_by_byte + MOVQ DX, CX + SHRQ $0x03, CX + SUBQ CX, R12 + MOVQ (R12), AX + SUBQ CX, BX + ANDQ $0x07, DX + JMP sequenceDecs_decodeSync_safe_bmi2_fill_end + +sequenceDecs_decodeSync_safe_bmi2_fill_byte_by_byte: + CMPQ BX, $0x00 + JLE sequenceDecs_decodeSync_safe_bmi2_fill_check_overread + CMPQ DX, $0x07 + JLE sequenceDecs_decodeSync_safe_bmi2_fill_end + SHLQ $0x08, AX + SUBQ $0x01, R12 + SUBQ $0x01, BX + SUBQ $0x08, DX + MOVBQZX (R12), CX + ORQ CX, AX + JMP sequenceDecs_decodeSync_safe_bmi2_fill_byte_by_byte + +sequenceDecs_decodeSync_safe_bmi2_fill_check_overread: + CMPQ DX, $0x40 + JA error_overread + +sequenceDecs_decodeSync_safe_bmi2_fill_end: + // Update offset + MOVQ $0x00000808, CX + BEXTRQ CX, R8, R13 + MOVQ AX, R14 + LEAQ (DX)(R13*1), CX + ROLQ CL, R14 + BZHIQ R13, R14, R14 + MOVQ CX, DX + MOVQ R8, CX + SHRQ $0x20, CX + ADDQ R14, CX + MOVQ CX, 8(SP) + + // Update match length + MOVQ $0x00000808, CX + BEXTRQ CX, DI, R13 + MOVQ AX, R14 + LEAQ (DX)(R13*1), CX + ROLQ CL, R14 + BZHIQ R13, R14, R14 + MOVQ CX, DX + MOVQ DI, CX + SHRQ $0x20, CX + ADDQ R14, CX + MOVQ CX, 16(SP) + + // Fill bitreader to have enough for the remaining + CMPQ BX, $0x08 + JL sequenceDecs_decodeSync_safe_bmi2_fill_2_byte_by_byte + MOVQ DX, CX + SHRQ $0x03, CX + SUBQ CX, R12 + MOVQ (R12), AX + SUBQ CX, BX + ANDQ $0x07, DX + JMP sequenceDecs_decodeSync_safe_bmi2_fill_2_end + +sequenceDecs_decodeSync_safe_bmi2_fill_2_byte_by_byte: + CMPQ BX, $0x00 + JLE sequenceDecs_decodeSync_safe_bmi2_fill_2_check_overread + CMPQ DX, $0x07 + JLE sequenceDecs_decodeSync_safe_bmi2_fill_2_end + SHLQ $0x08, AX + SUBQ $0x01, R12 + SUBQ $0x01, BX + SUBQ $0x08, DX + MOVBQZX (R12), CX + ORQ CX, AX + JMP sequenceDecs_decodeSync_safe_bmi2_fill_2_byte_by_byte + +sequenceDecs_decodeSync_safe_bmi2_fill_2_check_overread: + CMPQ DX, $0x40 + JA error_overread + +sequenceDecs_decodeSync_safe_bmi2_fill_2_end: + // Update literal length + MOVQ $0x00000808, CX + BEXTRQ CX, SI, R13 + MOVQ AX, R14 + LEAQ (DX)(R13*1), CX + ROLQ CL, R14 + BZHIQ R13, R14, R14 + MOVQ CX, DX + MOVQ SI, CX + SHRQ $0x20, CX + ADDQ R14, CX + MOVQ CX, 24(SP) + + // Fill bitreader for state updates + MOVQ R12, (SP) + MOVQ $0x00000808, CX + BEXTRQ CX, R8, R12 + MOVQ ctx+16(FP), CX + CMPQ 96(CX), $0x00 + JZ sequenceDecs_decodeSync_safe_bmi2_skip_update + LEAQ (SI)(DI*1), R13 + ADDQ R8, R13 + MOVBQZX R13, R13 + LEAQ (DX)(R13*1), CX + MOVQ AX, R14 + MOVQ CX, DX + ROLQ CL, R14 + BZHIQ R13, R14, R14 + + // Update Offset State + BZHIQ R8, R14, CX + SHRXQ R8, R14, R14 + SHRL $0x10, R8 + ADDQ CX, R8 + + // Load ctx.ofTable + MOVQ ctx+16(FP), CX + MOVQ 48(CX), CX + MOVQ (CX)(R8*8), R8 + + // Update Match Length State + BZHIQ DI, R14, CX + SHRXQ DI, R14, R14 + SHRL $0x10, DI + ADDQ CX, DI + + // Load ctx.mlTable + MOVQ ctx+16(FP), CX + MOVQ 24(CX), CX + MOVQ (CX)(DI*8), DI + + // Update Literal Length State + BZHIQ SI, R14, CX + SHRL $0x10, SI + ADDQ CX, SI + + // Load ctx.llTable + MOVQ ctx+16(FP), CX + MOVQ (CX), CX + MOVQ (CX)(SI*8), SI + +sequenceDecs_decodeSync_safe_bmi2_skip_update: + // Adjust offset + MOVQ s+0(FP), CX + MOVQ 8(SP), R13 + CMPQ R12, $0x01 + JBE sequenceDecs_decodeSync_safe_bmi2_adjust_offsetB_1_or_0 + MOVUPS 144(CX), X0 + MOVQ R13, 144(CX) + MOVUPS X0, 152(CX) + JMP sequenceDecs_decodeSync_safe_bmi2_after_adjust + +sequenceDecs_decodeSync_safe_bmi2_adjust_offsetB_1_or_0: + CMPQ 24(SP), $0x00000000 + JNE sequenceDecs_decodeSync_safe_bmi2_adjust_offset_maybezero + INCQ R13 + JMP sequenceDecs_decodeSync_safe_bmi2_adjust_offset_nonzero + +sequenceDecs_decodeSync_safe_bmi2_adjust_offset_maybezero: + TESTQ R13, R13 + JNZ sequenceDecs_decodeSync_safe_bmi2_adjust_offset_nonzero + MOVQ 144(CX), R13 + JMP sequenceDecs_decodeSync_safe_bmi2_after_adjust + +sequenceDecs_decodeSync_safe_bmi2_adjust_offset_nonzero: + MOVQ R13, R12 + XORQ R14, R14 + MOVQ $-1, R15 + CMPQ R13, $0x03 + CMOVQEQ R14, R12 + CMOVQEQ R15, R14 + ADDQ 144(CX)(R12*8), R14 + JNZ sequenceDecs_decodeSync_safe_bmi2_adjust_temp_valid + MOVQ $0x00000001, R14 + +sequenceDecs_decodeSync_safe_bmi2_adjust_temp_valid: + CMPQ R13, $0x01 + JZ sequenceDecs_decodeSync_safe_bmi2_adjust_skip + MOVQ 152(CX), R12 + MOVQ R12, 160(CX) + +sequenceDecs_decodeSync_safe_bmi2_adjust_skip: + MOVQ 144(CX), R12 + MOVQ R12, 152(CX) + MOVQ R14, 144(CX) + MOVQ R14, R13 + +sequenceDecs_decodeSync_safe_bmi2_after_adjust: + MOVQ R13, 8(SP) + + // Check values + MOVQ 16(SP), CX + MOVQ 24(SP), R12 + LEAQ (CX)(R12*1), R14 + MOVQ s+0(FP), R15 + ADDQ R14, 256(R15) + MOVQ ctx+16(FP), R14 + SUBQ R12, 104(R14) + JS error_not_enough_literals + CMPQ CX, $0x00020002 + JA sequenceDecs_decodeSync_safe_bmi2_error_match_len_too_big + TESTQ R13, R13 + JNZ sequenceDecs_decodeSync_safe_bmi2_match_len_ofs_ok + TESTQ CX, CX + JNZ sequenceDecs_decodeSync_safe_bmi2_error_match_len_ofs_mismatch + +sequenceDecs_decodeSync_safe_bmi2_match_len_ofs_ok: + MOVQ 24(SP), CX + MOVQ 8(SP), R12 + MOVQ 16(SP), R13 + + // Check if we have enough space in s.out + LEAQ (CX)(R13*1), R14 + ADDQ R9, R14 + CMPQ R14, 32(SP) + JA error_not_enough_space + + // Copy literals + TESTQ CX, CX + JZ check_offset + MOVQ CX, R14 + SUBQ $0x10, R14 + JB copy_1_small + +copy_1_loop: + MOVUPS (R10), X0 + MOVUPS X0, (R9) + ADDQ $0x10, R10 + ADDQ $0x10, R9 + SUBQ $0x10, R14 + JAE copy_1_loop + LEAQ 16(R10)(R14*1), R10 + LEAQ 16(R9)(R14*1), R9 + MOVUPS -16(R10), X0 + MOVUPS X0, -16(R9) + JMP copy_1_end + +copy_1_small: + CMPQ CX, $0x03 + JE copy_1_move_3 + JB copy_1_move_1or2 + CMPQ CX, $0x08 + JB copy_1_move_4through7 + JMP copy_1_move_8through16 + +copy_1_move_1or2: + MOVB (R10), R14 + MOVB -1(R10)(CX*1), R15 + MOVB R14, (R9) + MOVB R15, -1(R9)(CX*1) + ADDQ CX, R10 + ADDQ CX, R9 + JMP copy_1_end + +copy_1_move_3: + MOVW (R10), R14 + MOVB 2(R10), R15 + MOVW R14, (R9) + MOVB R15, 2(R9) + ADDQ CX, R10 + ADDQ CX, R9 + JMP copy_1_end + +copy_1_move_4through7: + MOVL (R10), R14 + MOVL -4(R10)(CX*1), R15 + MOVL R14, (R9) + MOVL R15, -4(R9)(CX*1) + ADDQ CX, R10 + ADDQ CX, R9 + JMP copy_1_end + +copy_1_move_8through16: + MOVQ (R10), R14 + MOVQ -8(R10)(CX*1), R15 + MOVQ R14, (R9) + MOVQ R15, -8(R9)(CX*1) + ADDQ CX, R10 + ADDQ CX, R9 + +copy_1_end: + ADDQ CX, R11 + + // Malformed input if seq.mo > t+len(hist) || seq.mo > s.windowSize) +check_offset: + MOVQ R11, CX + ADDQ 40(SP), CX + CMPQ R12, CX + JG error_match_off_too_big + CMPQ R12, 56(SP) + JG error_match_off_too_big + + // Copy match from history + MOVQ R12, CX + SUBQ R11, CX + JLS copy_match + MOVQ 48(SP), R14 + SUBQ CX, R14 + CMPQ R13, CX + JG copy_all_from_history + MOVQ R13, CX + SUBQ $0x10, CX + JB copy_4_small + +copy_4_loop: + MOVUPS (R14), X0 + MOVUPS X0, (R9) + ADDQ $0x10, R14 + ADDQ $0x10, R9 + SUBQ $0x10, CX + JAE copy_4_loop + LEAQ 16(R14)(CX*1), R14 + LEAQ 16(R9)(CX*1), R9 + MOVUPS -16(R14), X0 + MOVUPS X0, -16(R9) + JMP copy_4_end + +copy_4_small: + CMPQ R13, $0x03 + JE copy_4_move_3 + CMPQ R13, $0x08 + JB copy_4_move_4through7 + JMP copy_4_move_8through16 + +copy_4_move_3: + MOVW (R14), CX + MOVB 2(R14), R12 + MOVW CX, (R9) + MOVB R12, 2(R9) + ADDQ R13, R14 + ADDQ R13, R9 + JMP copy_4_end + +copy_4_move_4through7: + MOVL (R14), CX + MOVL -4(R14)(R13*1), R12 + MOVL CX, (R9) + MOVL R12, -4(R9)(R13*1) + ADDQ R13, R14 + ADDQ R13, R9 + JMP copy_4_end + +copy_4_move_8through16: + MOVQ (R14), CX + MOVQ -8(R14)(R13*1), R12 + MOVQ CX, (R9) + MOVQ R12, -8(R9)(R13*1) + ADDQ R13, R14 + ADDQ R13, R9 + +copy_4_end: + ADDQ R13, R11 + JMP handle_loop + JMP loop_finished + +copy_all_from_history: + MOVQ CX, R15 + SUBQ $0x10, R15 + JB copy_5_small + +copy_5_loop: + MOVUPS (R14), X0 + MOVUPS X0, (R9) + ADDQ $0x10, R14 + ADDQ $0x10, R9 + SUBQ $0x10, R15 + JAE copy_5_loop + LEAQ 16(R14)(R15*1), R14 + LEAQ 16(R9)(R15*1), R9 + MOVUPS -16(R14), X0 + MOVUPS X0, -16(R9) + JMP copy_5_end + +copy_5_small: + CMPQ CX, $0x03 + JE copy_5_move_3 + JB copy_5_move_1or2 + CMPQ CX, $0x08 + JB copy_5_move_4through7 + JMP copy_5_move_8through16 + +copy_5_move_1or2: + MOVB (R14), R15 + MOVB -1(R14)(CX*1), BP + MOVB R15, (R9) + MOVB BP, -1(R9)(CX*1) + ADDQ CX, R14 + ADDQ CX, R9 + JMP copy_5_end + +copy_5_move_3: + MOVW (R14), R15 + MOVB 2(R14), BP + MOVW R15, (R9) + MOVB BP, 2(R9) + ADDQ CX, R14 + ADDQ CX, R9 + JMP copy_5_end + +copy_5_move_4through7: + MOVL (R14), R15 + MOVL -4(R14)(CX*1), BP + MOVL R15, (R9) + MOVL BP, -4(R9)(CX*1) + ADDQ CX, R14 + ADDQ CX, R9 + JMP copy_5_end + +copy_5_move_8through16: + MOVQ (R14), R15 + MOVQ -8(R14)(CX*1), BP + MOVQ R15, (R9) + MOVQ BP, -8(R9)(CX*1) + ADDQ CX, R14 + ADDQ CX, R9 + +copy_5_end: + ADDQ CX, R11 + SUBQ CX, R13 + + // Copy match from the current buffer +copy_match: + MOVQ R9, CX + SUBQ R12, CX + + // ml <= mo + CMPQ R13, R12 + JA copy_overlapping_match + + // Copy non-overlapping match + ADDQ R13, R11 + MOVQ R13, R12 + SUBQ $0x10, R12 + JB copy_2_small + +copy_2_loop: + MOVUPS (CX), X0 + MOVUPS X0, (R9) + ADDQ $0x10, CX + ADDQ $0x10, R9 + SUBQ $0x10, R12 + JAE copy_2_loop + LEAQ 16(CX)(R12*1), CX + LEAQ 16(R9)(R12*1), R9 + MOVUPS -16(CX), X0 + MOVUPS X0, -16(R9) + JMP copy_2_end + +copy_2_small: + CMPQ R13, $0x03 + JE copy_2_move_3 + JB copy_2_move_1or2 + CMPQ R13, $0x08 + JB copy_2_move_4through7 + JMP copy_2_move_8through16 + +copy_2_move_1or2: + MOVB (CX), R12 + MOVB -1(CX)(R13*1), R14 + MOVB R12, (R9) + MOVB R14, -1(R9)(R13*1) + ADDQ R13, CX + ADDQ R13, R9 + JMP copy_2_end + +copy_2_move_3: + MOVW (CX), R12 + MOVB 2(CX), R14 + MOVW R12, (R9) + MOVB R14, 2(R9) + ADDQ R13, CX + ADDQ R13, R9 + JMP copy_2_end + +copy_2_move_4through7: + MOVL (CX), R12 + MOVL -4(CX)(R13*1), R14 + MOVL R12, (R9) + MOVL R14, -4(R9)(R13*1) + ADDQ R13, CX + ADDQ R13, R9 + JMP copy_2_end + +copy_2_move_8through16: + MOVQ (CX), R12 + MOVQ -8(CX)(R13*1), R14 + MOVQ R12, (R9) + MOVQ R14, -8(R9)(R13*1) + ADDQ R13, CX + ADDQ R13, R9 + +copy_2_end: + JMP handle_loop + + // Copy overlapping match +copy_overlapping_match: + ADDQ R13, R11 + +copy_slow_3: + MOVB (CX), R12 + MOVB R12, (R9) + INCQ CX + INCQ R9 + DECQ R13 + JNZ copy_slow_3 + +handle_loop: + MOVQ ctx+16(FP), CX + DECQ 96(CX) + JNS sequenceDecs_decodeSync_safe_bmi2_main_loop + +loop_finished: + MOVQ br+8(FP), CX + MOVQ AX, 24(CX) + MOVB DL, 32(CX) + MOVQ BX, 8(CX) + + // Update the context + MOVQ ctx+16(FP), AX + MOVQ R11, 136(AX) + MOVQ 144(AX), CX + SUBQ CX, R10 + MOVQ R10, 168(AX) + + // Return success + MOVQ $0x00000000, ret+24(FP) + RET + + // Return with match length error +sequenceDecs_decodeSync_safe_bmi2_error_match_len_ofs_mismatch: + MOVQ 16(SP), AX + MOVQ ctx+16(FP), CX + MOVQ AX, 216(CX) + MOVQ $0x00000001, ret+24(FP) + RET + + // Return with match too long error +sequenceDecs_decodeSync_safe_bmi2_error_match_len_too_big: + MOVQ ctx+16(FP), AX + MOVQ 16(SP), CX + MOVQ CX, 216(AX) + MOVQ $0x00000002, ret+24(FP) + RET + + // Return with match offset too long error +error_match_off_too_big: + MOVQ ctx+16(FP), AX + MOVQ 8(SP), CX + MOVQ CX, 224(AX) + MOVQ R11, 136(AX) + MOVQ $0x00000003, ret+24(FP) + RET + + // Return with not enough literals error +error_not_enough_literals: + MOVQ ctx+16(FP), AX + MOVQ 24(SP), CX + MOVQ CX, 208(AX) + MOVQ $0x00000004, ret+24(FP) + RET + + // Return with overread error +error_overread: + MOVQ $0x00000006, ret+24(FP) + RET + + // Return with not enough output space error +error_not_enough_space: + MOVQ ctx+16(FP), AX + MOVQ 24(SP), CX + MOVQ CX, 208(AX) + MOVQ 16(SP), CX + MOVQ CX, 216(AX) + MOVQ R11, 136(AX) + MOVQ $0x00000005, ret+24(FP) + RET diff --git a/vendor/github.com/klauspost/compress/zstd/seqdec_generic.go b/vendor/github.com/klauspost/compress/zstd/seqdec_generic.go new file mode 100644 index 000000000..2fb35b788 --- /dev/null +++ b/vendor/github.com/klauspost/compress/zstd/seqdec_generic.go @@ -0,0 +1,237 @@ +//go:build !amd64 || appengine || !gc || noasm +// +build !amd64 appengine !gc noasm + +package zstd + +import ( + "fmt" + "io" +) + +// decode sequences from the stream with the provided history but without dictionary. +func (s *sequenceDecs) decodeSyncSimple(hist []byte) (bool, error) { + return false, nil +} + +// decode sequences from the stream without the provided history. +func (s *sequenceDecs) decode(seqs []seqVals) error { + br := s.br + + // Grab full sizes tables, to avoid bounds checks. + llTable, mlTable, ofTable := s.litLengths.fse.dt[:maxTablesize], s.matchLengths.fse.dt[:maxTablesize], s.offsets.fse.dt[:maxTablesize] + llState, mlState, ofState := s.litLengths.state.state, s.matchLengths.state.state, s.offsets.state.state + s.seqSize = 0 + litRemain := len(s.literals) + + maxBlockSize := maxCompressedBlockSize + if s.windowSize < maxBlockSize { + maxBlockSize = s.windowSize + } + for i := range seqs { + var ll, mo, ml int + if len(br.in) > 4+((maxOffsetBits+16+16)>>3) { + // inlined function: + // ll, mo, ml = s.nextFast(br, llState, mlState, ofState) + + // Final will not read from stream. + var llB, mlB, moB uint8 + ll, llB = llState.final() + ml, mlB = mlState.final() + mo, moB = ofState.final() + + // extra bits are stored in reverse order. + br.fillFast() + mo += br.getBits(moB) + if s.maxBits > 32 { + br.fillFast() + } + ml += br.getBits(mlB) + ll += br.getBits(llB) + + if moB > 1 { + s.prevOffset[2] = s.prevOffset[1] + s.prevOffset[1] = s.prevOffset[0] + s.prevOffset[0] = mo + } else { + // mo = s.adjustOffset(mo, ll, moB) + // Inlined for rather big speedup + if ll == 0 { + // There is an exception though, when current sequence's literals_length = 0. + // In this case, repeated offsets are shifted by one, so an offset_value of 1 means Repeated_Offset2, + // an offset_value of 2 means Repeated_Offset3, and an offset_value of 3 means Repeated_Offset1 - 1_byte. + mo++ + } + + if mo == 0 { + mo = s.prevOffset[0] + } else { + var temp int + if mo == 3 { + temp = s.prevOffset[0] - 1 + } else { + temp = s.prevOffset[mo] + } + + if temp == 0 { + // 0 is not valid; input is corrupted; force offset to 1 + println("WARNING: temp was 0") + temp = 1 + } + + if mo != 1 { + s.prevOffset[2] = s.prevOffset[1] + } + s.prevOffset[1] = s.prevOffset[0] + s.prevOffset[0] = temp + mo = temp + } + } + br.fillFast() + } else { + if br.overread() { + if debugDecoder { + printf("reading sequence %d, exceeded available data\n", i) + } + return io.ErrUnexpectedEOF + } + ll, mo, ml = s.next(br, llState, mlState, ofState) + br.fill() + } + + if debugSequences { + println("Seq", i, "Litlen:", ll, "mo:", mo, "(abs) ml:", ml) + } + // Evaluate. + // We might be doing this async, so do it early. + if mo == 0 && ml > 0 { + return fmt.Errorf("zero matchoff and matchlen (%d) > 0", ml) + } + if ml > maxMatchLen { + return fmt.Errorf("match len (%d) bigger than max allowed length", ml) + } + s.seqSize += ll + ml + if s.seqSize > maxBlockSize { + return fmt.Errorf("output bigger than max block size (%d)", maxBlockSize) + } + litRemain -= ll + if litRemain < 0 { + return fmt.Errorf("unexpected literal count, want %d bytes, but only %d is available", ll, litRemain+ll) + } + seqs[i] = seqVals{ + ll: ll, + ml: ml, + mo: mo, + } + if i == len(seqs)-1 { + // This is the last sequence, so we shouldn't update state. + break + } + + // Manually inlined, ~ 5-20% faster + // Update all 3 states at once. Approx 20% faster. + nBits := llState.nbBits() + mlState.nbBits() + ofState.nbBits() + if nBits == 0 { + llState = llTable[llState.newState()&maxTableMask] + mlState = mlTable[mlState.newState()&maxTableMask] + ofState = ofTable[ofState.newState()&maxTableMask] + } else { + bits := br.get32BitsFast(nBits) + lowBits := uint16(bits >> ((ofState.nbBits() + mlState.nbBits()) & 31)) + llState = llTable[(llState.newState()+lowBits)&maxTableMask] + + lowBits = uint16(bits >> (ofState.nbBits() & 31)) + lowBits &= bitMask[mlState.nbBits()&15] + mlState = mlTable[(mlState.newState()+lowBits)&maxTableMask] + + lowBits = uint16(bits) & bitMask[ofState.nbBits()&15] + ofState = ofTable[(ofState.newState()+lowBits)&maxTableMask] + } + } + s.seqSize += litRemain + if s.seqSize > maxBlockSize { + return fmt.Errorf("output bigger than max block size (%d)", maxBlockSize) + } + err := br.close() + if err != nil { + printf("Closing sequences: %v, %+v\n", err, *br) + } + return err +} + +// executeSimple handles cases when a dictionary is not used. +func (s *sequenceDecs) executeSimple(seqs []seqVals, hist []byte) error { + // Ensure we have enough output size... + if len(s.out)+s.seqSize > cap(s.out) { + addBytes := s.seqSize + len(s.out) + s.out = append(s.out, make([]byte, addBytes)...) + s.out = s.out[:len(s.out)-addBytes] + } + + if debugDecoder { + printf("Execute %d seqs with literals: %d into %d bytes\n", len(seqs), len(s.literals), s.seqSize) + } + + var t = len(s.out) + out := s.out[:t+s.seqSize] + + for _, seq := range seqs { + // Add literals + copy(out[t:], s.literals[:seq.ll]) + t += seq.ll + s.literals = s.literals[seq.ll:] + + // Malformed input + if seq.mo > t+len(hist) || seq.mo > s.windowSize { + return fmt.Errorf("match offset (%d) bigger than current history (%d)", seq.mo, t+len(hist)) + } + + // Copy from history. + if v := seq.mo - t; v > 0 { + // v is the start position in history from end. + start := len(hist) - v + if seq.ml > v { + // Some goes into the current block. + // Copy remainder of history + copy(out[t:], hist[start:]) + t += v + seq.ml -= v + } else { + copy(out[t:], hist[start:start+seq.ml]) + t += seq.ml + continue + } + } + + // We must be in the current buffer now + if seq.ml > 0 { + start := t - seq.mo + if seq.ml <= t-start { + // No overlap + copy(out[t:], out[start:start+seq.ml]) + t += seq.ml + } else { + // Overlapping copy + // Extend destination slice and copy one byte at the time. + src := out[start : start+seq.ml] + dst := out[t:] + dst = dst[:len(src)] + t += len(src) + // Destination is the space we just added. + for i := range src { + dst[i] = src[i] + } + } + } + } + // Add final literals + copy(out[t:], s.literals) + if debugDecoder { + t += len(s.literals) + if t != len(out) { + panic(fmt.Errorf("length mismatch, want %d, got %d, ss: %d", len(out), t, s.seqSize)) + } + } + s.out = out + + return nil +} diff --git a/vendor/github.com/klauspost/compress/zstd/seqenc.go b/vendor/github.com/klauspost/compress/zstd/seqenc.go new file mode 100644 index 000000000..8014174a7 --- /dev/null +++ b/vendor/github.com/klauspost/compress/zstd/seqenc.go @@ -0,0 +1,114 @@ +// Copyright 2019+ Klaus Post. All rights reserved. +// License information can be found in the LICENSE file. +// Based on work by Yann Collet, released under BSD License. + +package zstd + +import "math/bits" + +type seqCoders struct { + llEnc, ofEnc, mlEnc *fseEncoder + llPrev, ofPrev, mlPrev *fseEncoder +} + +// swap coders with another (block). +func (s *seqCoders) swap(other *seqCoders) { + *s, *other = *other, *s +} + +// setPrev will update the previous encoders to the actually used ones +// and make sure a fresh one is in the main slot. +func (s *seqCoders) setPrev(ll, ml, of *fseEncoder) { + compareSwap := func(used *fseEncoder, current, prev **fseEncoder) { + // We used the new one, more current to history and reuse the previous history + if *current == used { + *prev, *current = *current, *prev + c := *current + p := *prev + c.reUsed = false + p.reUsed = true + return + } + if used == *prev { + return + } + // Ensure we cannot reuse by accident + prevEnc := *prev + prevEnc.symbolLen = 0 + } + compareSwap(ll, &s.llEnc, &s.llPrev) + compareSwap(ml, &s.mlEnc, &s.mlPrev) + compareSwap(of, &s.ofEnc, &s.ofPrev) +} + +func highBit(val uint32) (n uint32) { + return uint32(bits.Len32(val) - 1) +} + +var llCodeTable = [64]byte{0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15, + 16, 16, 17, 17, 18, 18, 19, 19, + 20, 20, 20, 20, 21, 21, 21, 21, + 22, 22, 22, 22, 22, 22, 22, 22, + 23, 23, 23, 23, 23, 23, 23, 23, + 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24} + +// Up to 6 bits +const maxLLCode = 35 + +// llBitsTable translates from ll code to number of bits. +var llBitsTable = [maxLLCode + 1]byte{ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 2, 2, 3, 3, + 4, 6, 7, 8, 9, 10, 11, 12, + 13, 14, 15, 16} + +// llCode returns the code that represents the literal length requested. +func llCode(litLength uint32) uint8 { + const llDeltaCode = 19 + if litLength <= 63 { + // Compiler insists on bounds check (Go 1.12) + return llCodeTable[litLength&63] + } + return uint8(highBit(litLength)) + llDeltaCode +} + +var mlCodeTable = [128]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 32, 33, 33, 34, 34, 35, 35, 36, 36, 36, 36, 37, 37, 37, 37, + 38, 38, 38, 38, 38, 38, 38, 38, 39, 39, 39, 39, 39, 39, 39, 39, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42} + +// Up to 6 bits +const maxMLCode = 52 + +// mlBitsTable translates from ml code to number of bits. +var mlBitsTable = [maxMLCode + 1]byte{ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 2, 2, 3, 3, + 4, 4, 5, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16} + +// note : mlBase = matchLength - MINMATCH; +// because it's the format it's stored in seqStore->sequences +func mlCode(mlBase uint32) uint8 { + const mlDeltaCode = 36 + if mlBase <= 127 { + // Compiler insists on bounds check (Go 1.12) + return mlCodeTable[mlBase&127] + } + return uint8(highBit(mlBase)) + mlDeltaCode +} + +func ofCode(offset uint32) uint8 { + // A valid offset will always be > 0. + return uint8(bits.Len32(offset) - 1) +} diff --git a/vendor/github.com/klauspost/compress/zstd/snappy.go b/vendor/github.com/klauspost/compress/zstd/snappy.go new file mode 100644 index 000000000..ec13594e8 --- /dev/null +++ b/vendor/github.com/klauspost/compress/zstd/snappy.go @@ -0,0 +1,434 @@ +// Copyright 2019+ Klaus Post. All rights reserved. +// License information can be found in the LICENSE file. +// Based on work by Yann Collet, released under BSD License. + +package zstd + +import ( + "encoding/binary" + "errors" + "hash/crc32" + "io" + + "github.com/klauspost/compress/huff0" + snappy "github.com/klauspost/compress/internal/snapref" +) + +const ( + snappyTagLiteral = 0x00 + snappyTagCopy1 = 0x01 + snappyTagCopy2 = 0x02 + snappyTagCopy4 = 0x03 +) + +const ( + snappyChecksumSize = 4 + snappyMagicBody = "sNaPpY" + + // snappyMaxBlockSize is the maximum size of the input to encodeBlock. It is not + // part of the wire format per se, but some parts of the encoder assume + // that an offset fits into a uint16. + // + // Also, for the framing format (Writer type instead of Encode function), + // https://github.com/google/snappy/blob/master/framing_format.txt says + // that "the uncompressed data in a chunk must be no longer than 65536 + // bytes". + snappyMaxBlockSize = 65536 + + // snappyMaxEncodedLenOfMaxBlockSize equals MaxEncodedLen(snappyMaxBlockSize), but is + // hard coded to be a const instead of a variable, so that obufLen can also + // be a const. Their equivalence is confirmed by + // TestMaxEncodedLenOfMaxBlockSize. + snappyMaxEncodedLenOfMaxBlockSize = 76490 +) + +const ( + chunkTypeCompressedData = 0x00 + chunkTypeUncompressedData = 0x01 + chunkTypePadding = 0xfe + chunkTypeStreamIdentifier = 0xff +) + +var ( + // ErrSnappyCorrupt reports that the input is invalid. + ErrSnappyCorrupt = errors.New("snappy: corrupt input") + // ErrSnappyTooLarge reports that the uncompressed length is too large. + ErrSnappyTooLarge = errors.New("snappy: decoded block is too large") + // ErrSnappyUnsupported reports that the input isn't supported. + ErrSnappyUnsupported = errors.New("snappy: unsupported input") + + errUnsupportedLiteralLength = errors.New("snappy: unsupported literal length") +) + +// SnappyConverter can read SnappyConverter-compressed streams and convert them to zstd. +// Conversion is done by converting the stream directly from Snappy without intermediate +// full decoding. +// Therefore the compression ratio is much less than what can be done by a full decompression +// and compression, and a faulty Snappy stream may lead to a faulty Zstandard stream without +// any errors being generated. +// No CRC value is being generated and not all CRC values of the Snappy stream are checked. +// However, it provides really fast recompression of Snappy streams. +// The converter can be reused to avoid allocations, even after errors. +type SnappyConverter struct { + r io.Reader + err error + buf []byte + block *blockEnc +} + +// Convert the Snappy stream supplied in 'in' and write the zStandard stream to 'w'. +// If any error is detected on the Snappy stream it is returned. +// The number of bytes written is returned. +func (r *SnappyConverter) Convert(in io.Reader, w io.Writer) (int64, error) { + initPredefined() + r.err = nil + r.r = in + if r.block == nil { + r.block = &blockEnc{} + r.block.init() + } + r.block.initNewEncode() + if len(r.buf) != snappyMaxEncodedLenOfMaxBlockSize+snappyChecksumSize { + r.buf = make([]byte, snappyMaxEncodedLenOfMaxBlockSize+snappyChecksumSize) + } + r.block.litEnc.Reuse = huff0.ReusePolicyNone + var written int64 + var readHeader bool + { + header := frameHeader{WindowSize: snappyMaxBlockSize}.appendTo(r.buf[:0]) + + var n int + n, r.err = w.Write(header) + if r.err != nil { + return written, r.err + } + written += int64(n) + } + + for { + if !r.readFull(r.buf[:4], true) { + // Add empty last block + r.block.reset(nil) + r.block.last = true + err := r.block.encodeLits(r.block.literals, false) + if err != nil { + return written, err + } + n, err := w.Write(r.block.output) + if err != nil { + return written, err + } + written += int64(n) + + return written, r.err + } + chunkType := r.buf[0] + if !readHeader { + if chunkType != chunkTypeStreamIdentifier { + println("chunkType != chunkTypeStreamIdentifier", chunkType) + r.err = ErrSnappyCorrupt + return written, r.err + } + readHeader = true + } + chunkLen := int(r.buf[1]) | int(r.buf[2])<<8 | int(r.buf[3])<<16 + if chunkLen > len(r.buf) { + println("chunkLen > len(r.buf)", chunkType) + r.err = ErrSnappyUnsupported + return written, r.err + } + + // The chunk types are specified at + // https://github.com/google/snappy/blob/master/framing_format.txt + switch chunkType { + case chunkTypeCompressedData: + // Section 4.2. Compressed data (chunk type 0x00). + if chunkLen < snappyChecksumSize { + println("chunkLen < snappyChecksumSize", chunkLen, snappyChecksumSize) + r.err = ErrSnappyCorrupt + return written, r.err + } + buf := r.buf[:chunkLen] + if !r.readFull(buf, false) { + return written, r.err + } + //checksum := uint32(buf[0]) | uint32(buf[1])<<8 | uint32(buf[2])<<16 | uint32(buf[3])<<24 + buf = buf[snappyChecksumSize:] + + n, hdr, err := snappyDecodedLen(buf) + if err != nil { + r.err = err + return written, r.err + } + buf = buf[hdr:] + if n > snappyMaxBlockSize { + println("n > snappyMaxBlockSize", n, snappyMaxBlockSize) + r.err = ErrSnappyCorrupt + return written, r.err + } + r.block.reset(nil) + r.block.pushOffsets() + if err := decodeSnappy(r.block, buf); err != nil { + r.err = err + return written, r.err + } + if r.block.size+r.block.extraLits != n { + printf("invalid size, want %d, got %d\n", n, r.block.size+r.block.extraLits) + r.err = ErrSnappyCorrupt + return written, r.err + } + err = r.block.encode(nil, false, false) + switch err { + case errIncompressible: + r.block.popOffsets() + r.block.reset(nil) + r.block.literals, err = snappy.Decode(r.block.literals[:n], r.buf[snappyChecksumSize:chunkLen]) + if err != nil { + return written, err + } + err = r.block.encodeLits(r.block.literals, false) + if err != nil { + return written, err + } + case nil: + default: + return written, err + } + + n, r.err = w.Write(r.block.output) + if r.err != nil { + return written, err + } + written += int64(n) + continue + case chunkTypeUncompressedData: + if debugEncoder { + println("Uncompressed, chunklen", chunkLen) + } + // Section 4.3. Uncompressed data (chunk type 0x01). + if chunkLen < snappyChecksumSize { + println("chunkLen < snappyChecksumSize", chunkLen, snappyChecksumSize) + r.err = ErrSnappyCorrupt + return written, r.err + } + r.block.reset(nil) + buf := r.buf[:snappyChecksumSize] + if !r.readFull(buf, false) { + return written, r.err + } + checksum := uint32(buf[0]) | uint32(buf[1])<<8 | uint32(buf[2])<<16 | uint32(buf[3])<<24 + // Read directly into r.decoded instead of via r.buf. + n := chunkLen - snappyChecksumSize + if n > snappyMaxBlockSize { + println("n > snappyMaxBlockSize", n, snappyMaxBlockSize) + r.err = ErrSnappyCorrupt + return written, r.err + } + r.block.literals = r.block.literals[:n] + if !r.readFull(r.block.literals, false) { + return written, r.err + } + if snappyCRC(r.block.literals) != checksum { + println("literals crc mismatch") + r.err = ErrSnappyCorrupt + return written, r.err + } + err := r.block.encodeLits(r.block.literals, false) + if err != nil { + return written, err + } + n, r.err = w.Write(r.block.output) + if r.err != nil { + return written, err + } + written += int64(n) + continue + + case chunkTypeStreamIdentifier: + if debugEncoder { + println("stream id", chunkLen, len(snappyMagicBody)) + } + // Section 4.1. Stream identifier (chunk type 0xff). + if chunkLen != len(snappyMagicBody) { + println("chunkLen != len(snappyMagicBody)", chunkLen, len(snappyMagicBody)) + r.err = ErrSnappyCorrupt + return written, r.err + } + if !r.readFull(r.buf[:len(snappyMagicBody)], false) { + return written, r.err + } + for i := 0; i < len(snappyMagicBody); i++ { + if r.buf[i] != snappyMagicBody[i] { + println("r.buf[i] != snappyMagicBody[i]", r.buf[i], snappyMagicBody[i], i) + r.err = ErrSnappyCorrupt + return written, r.err + } + } + continue + } + + if chunkType <= 0x7f { + // Section 4.5. Reserved unskippable chunks (chunk types 0x02-0x7f). + println("chunkType <= 0x7f") + r.err = ErrSnappyUnsupported + return written, r.err + } + // Section 4.4 Padding (chunk type 0xfe). + // Section 4.6. Reserved skippable chunks (chunk types 0x80-0xfd). + if !r.readFull(r.buf[:chunkLen], false) { + return written, r.err + } + } +} + +// decodeSnappy writes the decoding of src to dst. It assumes that the varint-encoded +// length of the decompressed bytes has already been read. +func decodeSnappy(blk *blockEnc, src []byte) error { + //decodeRef(make([]byte, snappyMaxBlockSize), src) + var s, length int + lits := blk.extraLits + var offset uint32 + for s < len(src) { + switch src[s] & 0x03 { + case snappyTagLiteral: + x := uint32(src[s] >> 2) + switch { + case x < 60: + s++ + case x == 60: + s += 2 + if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line. + println("uint(s) > uint(len(src)", s, src) + return ErrSnappyCorrupt + } + x = uint32(src[s-1]) + case x == 61: + s += 3 + if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line. + println("uint(s) > uint(len(src)", s, src) + return ErrSnappyCorrupt + } + x = uint32(src[s-2]) | uint32(src[s-1])<<8 + case x == 62: + s += 4 + if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line. + println("uint(s) > uint(len(src)", s, src) + return ErrSnappyCorrupt + } + x = uint32(src[s-3]) | uint32(src[s-2])<<8 | uint32(src[s-1])<<16 + case x == 63: + s += 5 + if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line. + println("uint(s) > uint(len(src)", s, src) + return ErrSnappyCorrupt + } + x = uint32(src[s-4]) | uint32(src[s-3])<<8 | uint32(src[s-2])<<16 | uint32(src[s-1])<<24 + } + if x > snappyMaxBlockSize { + println("x > snappyMaxBlockSize", x, snappyMaxBlockSize) + return ErrSnappyCorrupt + } + length = int(x) + 1 + if length <= 0 { + println("length <= 0 ", length) + + return errUnsupportedLiteralLength + } + //if length > snappyMaxBlockSize-d || uint32(length) > len(src)-s { + // return ErrSnappyCorrupt + //} + + blk.literals = append(blk.literals, src[s:s+length]...) + //println(length, "litLen") + lits += length + s += length + continue + + case snappyTagCopy1: + s += 2 + if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line. + println("uint(s) > uint(len(src)", s, len(src)) + return ErrSnappyCorrupt + } + length = 4 + int(src[s-2])>>2&0x7 + offset = uint32(src[s-2])&0xe0<<3 | uint32(src[s-1]) + + case snappyTagCopy2: + s += 3 + if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line. + println("uint(s) > uint(len(src)", s, len(src)) + return ErrSnappyCorrupt + } + length = 1 + int(src[s-3])>>2 + offset = uint32(src[s-2]) | uint32(src[s-1])<<8 + + case snappyTagCopy4: + s += 5 + if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line. + println("uint(s) > uint(len(src)", s, len(src)) + return ErrSnappyCorrupt + } + length = 1 + int(src[s-5])>>2 + offset = uint32(src[s-4]) | uint32(src[s-3])<<8 | uint32(src[s-2])<<16 | uint32(src[s-1])<<24 + } + + if offset <= 0 || blk.size+lits < int(offset) /*|| length > len(blk)-d */ { + println("offset <= 0 || blk.size+lits < int(offset)", offset, blk.size+lits, int(offset), blk.size, lits) + + return ErrSnappyCorrupt + } + + // Check if offset is one of the recent offsets. + // Adjusts the output offset accordingly. + // Gives a tiny bit of compression, typically around 1%. + if false { + offset = blk.matchOffset(offset, uint32(lits)) + } else { + offset += 3 + } + + blk.sequences = append(blk.sequences, seq{ + litLen: uint32(lits), + offset: offset, + matchLen: uint32(length) - zstdMinMatch, + }) + blk.size += length + lits + lits = 0 + } + blk.extraLits = lits + return nil +} + +func (r *SnappyConverter) readFull(p []byte, allowEOF bool) (ok bool) { + if _, r.err = io.ReadFull(r.r, p); r.err != nil { + if r.err == io.ErrUnexpectedEOF || (r.err == io.EOF && !allowEOF) { + r.err = ErrSnappyCorrupt + } + return false + } + return true +} + +var crcTable = crc32.MakeTable(crc32.Castagnoli) + +// crc implements the checksum specified in section 3 of +// https://github.com/google/snappy/blob/master/framing_format.txt +func snappyCRC(b []byte) uint32 { + c := crc32.Update(0, crcTable, b) + return c>>15 | c<<17 + 0xa282ead8 +} + +// snappyDecodedLen returns the length of the decoded block and the number of bytes +// that the length header occupied. +func snappyDecodedLen(src []byte) (blockLen, headerLen int, err error) { + v, n := binary.Uvarint(src) + if n <= 0 || v > 0xffffffff { + return 0, 0, ErrSnappyCorrupt + } + + const wordSize = 32 << (^uint(0) >> 32 & 1) + if wordSize == 32 && v > 0x7fffffff { + return 0, 0, ErrSnappyTooLarge + } + return int(v), n, nil +} diff --git a/vendor/github.com/klauspost/compress/zstd/zip.go b/vendor/github.com/klauspost/compress/zstd/zip.go new file mode 100644 index 000000000..29c15c8c4 --- /dev/null +++ b/vendor/github.com/klauspost/compress/zstd/zip.go @@ -0,0 +1,141 @@ +// Copyright 2019+ Klaus Post. All rights reserved. +// License information can be found in the LICENSE file. + +package zstd + +import ( + "errors" + "io" + "sync" +) + +// ZipMethodWinZip is the method for Zstandard compressed data inside Zip files for WinZip. +// See https://www.winzip.com/win/en/comp_info.html +const ZipMethodWinZip = 93 + +// ZipMethodPKWare is the original method number used by PKWARE to indicate Zstandard compression. +// Deprecated: This has been deprecated by PKWARE, use ZipMethodWinZip instead for compression. +// See https://pkware.cachefly.net/webdocs/APPNOTE/APPNOTE-6.3.9.TXT +const ZipMethodPKWare = 20 + +// zipReaderPool is the default reader pool. +var zipReaderPool = sync.Pool{New: func() interface{} { + z, err := NewReader(nil, WithDecoderLowmem(true), WithDecoderMaxWindow(128<<20), WithDecoderConcurrency(1)) + if err != nil { + panic(err) + } + return z +}} + +// newZipReader creates a pooled zip decompressor. +func newZipReader(opts ...DOption) func(r io.Reader) io.ReadCloser { + pool := &zipReaderPool + if len(opts) > 0 { + opts = append([]DOption{WithDecoderLowmem(true), WithDecoderMaxWindow(128 << 20)}, opts...) + // Force concurrency 1 + opts = append(opts, WithDecoderConcurrency(1)) + // Create our own pool + pool = &sync.Pool{} + } + return func(r io.Reader) io.ReadCloser { + dec, ok := pool.Get().(*Decoder) + if ok { + dec.Reset(r) + } else { + d, err := NewReader(r, opts...) + if err != nil { + panic(err) + } + dec = d + } + return &pooledZipReader{dec: dec, pool: pool} + } +} + +type pooledZipReader struct { + mu sync.Mutex // guards Close and Read + pool *sync.Pool + dec *Decoder +} + +func (r *pooledZipReader) Read(p []byte) (n int, err error) { + r.mu.Lock() + defer r.mu.Unlock() + if r.dec == nil { + return 0, errors.New("read after close or EOF") + } + dec, err := r.dec.Read(p) + if err == io.EOF { + r.dec.Reset(nil) + r.pool.Put(r.dec) + r.dec = nil + } + return dec, err +} + +func (r *pooledZipReader) Close() error { + r.mu.Lock() + defer r.mu.Unlock() + var err error + if r.dec != nil { + err = r.dec.Reset(nil) + r.pool.Put(r.dec) + r.dec = nil + } + return err +} + +type pooledZipWriter struct { + mu sync.Mutex // guards Close and Read + enc *Encoder + pool *sync.Pool +} + +func (w *pooledZipWriter) Write(p []byte) (n int, err error) { + w.mu.Lock() + defer w.mu.Unlock() + if w.enc == nil { + return 0, errors.New("Write after Close") + } + return w.enc.Write(p) +} + +func (w *pooledZipWriter) Close() error { + w.mu.Lock() + defer w.mu.Unlock() + var err error + if w.enc != nil { + err = w.enc.Close() + w.pool.Put(w.enc) + w.enc = nil + } + return err +} + +// ZipCompressor returns a compressor that can be registered with zip libraries. +// The provided encoder options will be used on all encodes. +func ZipCompressor(opts ...EOption) func(w io.Writer) (io.WriteCloser, error) { + var pool sync.Pool + return func(w io.Writer) (io.WriteCloser, error) { + enc, ok := pool.Get().(*Encoder) + if ok { + enc.Reset(w) + } else { + var err error + enc, err = NewWriter(w, opts...) + if err != nil { + return nil, err + } + } + return &pooledZipWriter{enc: enc, pool: &pool}, nil + } +} + +// ZipDecompressor returns a decompressor that can be registered with zip libraries. +// See ZipCompressor for example. +// Options can be specified. WithDecoderConcurrency(1) is forced, +// and by default a 128MB maximum decompression window is specified. +// The window size can be overridden if required. +func ZipDecompressor(opts ...DOption) func(r io.Reader) io.ReadCloser { + return newZipReader(opts...) +} diff --git a/vendor/github.com/klauspost/compress/zstd/zstd.go b/vendor/github.com/klauspost/compress/zstd/zstd.go new file mode 100644 index 000000000..4be7cc736 --- /dev/null +++ b/vendor/github.com/klauspost/compress/zstd/zstd.go @@ -0,0 +1,121 @@ +// Package zstd provides decompression of zstandard files. +// +// For advanced usage and examples, go to the README: https://github.com/klauspost/compress/tree/master/zstd#zstd +package zstd + +import ( + "bytes" + "encoding/binary" + "errors" + "log" + "math" +) + +// enable debug printing +const debug = false + +// enable encoding debug printing +const debugEncoder = debug + +// enable decoding debug printing +const debugDecoder = debug + +// Enable extra assertions. +const debugAsserts = debug || false + +// print sequence details +const debugSequences = false + +// print detailed matching information +const debugMatches = false + +// force encoder to use predefined tables. +const forcePreDef = false + +// zstdMinMatch is the minimum zstd match length. +const zstdMinMatch = 3 + +// fcsUnknown is used for unknown frame content size. +const fcsUnknown = math.MaxUint64 + +var ( + // ErrReservedBlockType is returned when a reserved block type is found. + // Typically this indicates wrong or corrupted input. + ErrReservedBlockType = errors.New("invalid input: reserved block type encountered") + + // ErrCompressedSizeTooBig is returned when a block is bigger than allowed. + // Typically this indicates wrong or corrupted input. + ErrCompressedSizeTooBig = errors.New("invalid input: compressed size too big") + + // ErrBlockTooSmall is returned when a block is too small to be decoded. + // Typically returned on invalid input. + ErrBlockTooSmall = errors.New("block too small") + + // ErrUnexpectedBlockSize is returned when a block has unexpected size. + // Typically returned on invalid input. + ErrUnexpectedBlockSize = errors.New("unexpected block size") + + // ErrMagicMismatch is returned when a "magic" number isn't what is expected. + // Typically this indicates wrong or corrupted input. + ErrMagicMismatch = errors.New("invalid input: magic number mismatch") + + // ErrWindowSizeExceeded is returned when a reference exceeds the valid window size. + // Typically this indicates wrong or corrupted input. + ErrWindowSizeExceeded = errors.New("window size exceeded") + + // ErrWindowSizeTooSmall is returned when no window size is specified. + // Typically this indicates wrong or corrupted input. + ErrWindowSizeTooSmall = errors.New("invalid input: window size was too small") + + // ErrDecoderSizeExceeded is returned if decompressed size exceeds the configured limit. + ErrDecoderSizeExceeded = errors.New("decompressed size exceeds configured limit") + + // ErrUnknownDictionary is returned if the dictionary ID is unknown. + ErrUnknownDictionary = errors.New("unknown dictionary") + + // ErrFrameSizeExceeded is returned if the stated frame size is exceeded. + // This is only returned if SingleSegment is specified on the frame. + ErrFrameSizeExceeded = errors.New("frame size exceeded") + + // ErrFrameSizeMismatch is returned if the stated frame size does not match the expected size. + // This is only returned if SingleSegment is specified on the frame. + ErrFrameSizeMismatch = errors.New("frame size does not match size on stream") + + // ErrCRCMismatch is returned if CRC mismatches. + ErrCRCMismatch = errors.New("CRC check failed") + + // ErrDecoderClosed will be returned if the Decoder was used after + // Close has been called. + ErrDecoderClosed = errors.New("decoder used after Close") + + // ErrDecoderNilInput is returned when a nil Reader was provided + // and an operation other than Reset/DecodeAll/Close was attempted. + ErrDecoderNilInput = errors.New("nil input provided as reader") +) + +func println(a ...interface{}) { + if debug || debugDecoder || debugEncoder { + log.Println(a...) + } +} + +func printf(format string, a ...interface{}) { + if debug || debugDecoder || debugEncoder { + log.Printf(format, a...) + } +} + +func load3232(b []byte, i int32) uint32 { + return binary.LittleEndian.Uint32(b[:len(b):len(b)][i:]) +} + +func load6432(b []byte, i int32) uint64 { + return binary.LittleEndian.Uint64(b[:len(b):len(b)][i:]) +} + +type byter interface { + Bytes() []byte + Len() int +} + +var _ byter = &bytes.Buffer{} diff --git a/vendor/github.com/miekg/dns/README.md b/vendor/github.com/miekg/dns/README.md index e57d86afe..8d5a2a478 100644 --- a/vendor/github.com/miekg/dns/README.md +++ b/vendor/github.com/miekg/dns/README.md @@ -83,6 +83,8 @@ A not-so-up-to-date-list-that-may-be-actually-current: * https://github.com/egbakou/domainverifier * https://github.com/semihalev/sdns * https://github.com/wintbiit/NineDNS +* https://linuxcontainers.org/incus/ +* https://ifconfig.es Send pull request if you want to be listed here. @@ -146,6 +148,7 @@ Example programs can be found in the `github.com/miekg/exdns` repository. * 3225 - DO bit (DNSSEC OK) * 340{1,2,3} - NAPTR record * 3445 - Limiting the scope of (DNS)KEY +* 3596 - AAAA record * 3597 - Unknown RRs * 4025 - A Method for Storing IPsec Keying Material in DNS * 403{3,4,5} - DNSSEC + validation functions @@ -186,6 +189,9 @@ Example programs can be found in the `github.com/miekg/exdns` repository. * 8777 - DNS Reverse IP Automatic Multicast Tunneling (AMT) Discovery * 8914 - Extended DNS Errors * 8976 - Message Digest for DNS Zones (ZONEMD RR) +* 9460 - Service Binding and Parameter Specification via the DNS +* 9461 - Service Binding Mapping for DNS Servers +* 9462 - Discovery of Designated Resolvers ## Loosely Based Upon diff --git a/vendor/github.com/miekg/dns/defaults.go b/vendor/github.com/miekg/dns/defaults.go index 02d9199a4..68e766c68 100644 --- a/vendor/github.com/miekg/dns/defaults.go +++ b/vendor/github.com/miekg/dns/defaults.go @@ -198,10 +198,12 @@ func IsDomainName(s string) (labels int, ok bool) { off int begin int wasDot bool + escape bool ) for i := 0; i < len(s); i++ { switch s[i] { case '\\': + escape = !escape if off+1 > lenmsg { return labels, false } @@ -217,6 +219,7 @@ func IsDomainName(s string) (labels int, ok bool) { wasDot = false case '.': + escape = false if i == 0 && len(s) > 1 { // leading dots are not legal except for the root zone return labels, false @@ -243,10 +246,13 @@ func IsDomainName(s string) (labels int, ok bool) { labels++ begin = i + 1 default: + escape = false wasDot = false } } - + if escape { + return labels, false + } return labels, true } diff --git a/vendor/github.com/miekg/dns/edns.go b/vendor/github.com/miekg/dns/edns.go index 1b58e8f0a..c1bbdaae2 100644 --- a/vendor/github.com/miekg/dns/edns.go +++ b/vendor/github.com/miekg/dns/edns.go @@ -756,36 +756,48 @@ const ( ExtendedErrorCodeNoReachableAuthority ExtendedErrorCodeNetworkError ExtendedErrorCodeInvalidData + ExtendedErrorCodeSignatureExpiredBeforeValid + ExtendedErrorCodeTooEarly + ExtendedErrorCodeUnsupportedNSEC3IterValue + ExtendedErrorCodeUnableToConformToPolicy + ExtendedErrorCodeSynthesized + ExtendedErrorCodeInvalidQueryType ) // ExtendedErrorCodeToString maps extended error info codes to a human readable // description. var ExtendedErrorCodeToString = map[uint16]string{ - ExtendedErrorCodeOther: "Other", - ExtendedErrorCodeUnsupportedDNSKEYAlgorithm: "Unsupported DNSKEY Algorithm", - ExtendedErrorCodeUnsupportedDSDigestType: "Unsupported DS Digest Type", - ExtendedErrorCodeStaleAnswer: "Stale Answer", - ExtendedErrorCodeForgedAnswer: "Forged Answer", - ExtendedErrorCodeDNSSECIndeterminate: "DNSSEC Indeterminate", - ExtendedErrorCodeDNSBogus: "DNSSEC Bogus", - ExtendedErrorCodeSignatureExpired: "Signature Expired", - ExtendedErrorCodeSignatureNotYetValid: "Signature Not Yet Valid", - ExtendedErrorCodeDNSKEYMissing: "DNSKEY Missing", - ExtendedErrorCodeRRSIGsMissing: "RRSIGs Missing", - ExtendedErrorCodeNoZoneKeyBitSet: "No Zone Key Bit Set", - ExtendedErrorCodeNSECMissing: "NSEC Missing", - ExtendedErrorCodeCachedError: "Cached Error", - ExtendedErrorCodeNotReady: "Not Ready", - ExtendedErrorCodeBlocked: "Blocked", - ExtendedErrorCodeCensored: "Censored", - ExtendedErrorCodeFiltered: "Filtered", - ExtendedErrorCodeProhibited: "Prohibited", - ExtendedErrorCodeStaleNXDOMAINAnswer: "Stale NXDOMAIN Answer", - ExtendedErrorCodeNotAuthoritative: "Not Authoritative", - ExtendedErrorCodeNotSupported: "Not Supported", - ExtendedErrorCodeNoReachableAuthority: "No Reachable Authority", - ExtendedErrorCodeNetworkError: "Network Error", - ExtendedErrorCodeInvalidData: "Invalid Data", + ExtendedErrorCodeOther: "Other", + ExtendedErrorCodeUnsupportedDNSKEYAlgorithm: "Unsupported DNSKEY Algorithm", + ExtendedErrorCodeUnsupportedDSDigestType: "Unsupported DS Digest Type", + ExtendedErrorCodeStaleAnswer: "Stale Answer", + ExtendedErrorCodeForgedAnswer: "Forged Answer", + ExtendedErrorCodeDNSSECIndeterminate: "DNSSEC Indeterminate", + ExtendedErrorCodeDNSBogus: "DNSSEC Bogus", + ExtendedErrorCodeSignatureExpired: "Signature Expired", + ExtendedErrorCodeSignatureNotYetValid: "Signature Not Yet Valid", + ExtendedErrorCodeDNSKEYMissing: "DNSKEY Missing", + ExtendedErrorCodeRRSIGsMissing: "RRSIGs Missing", + ExtendedErrorCodeNoZoneKeyBitSet: "No Zone Key Bit Set", + ExtendedErrorCodeNSECMissing: "NSEC Missing", + ExtendedErrorCodeCachedError: "Cached Error", + ExtendedErrorCodeNotReady: "Not Ready", + ExtendedErrorCodeBlocked: "Blocked", + ExtendedErrorCodeCensored: "Censored", + ExtendedErrorCodeFiltered: "Filtered", + ExtendedErrorCodeProhibited: "Prohibited", + ExtendedErrorCodeStaleNXDOMAINAnswer: "Stale NXDOMAIN Answer", + ExtendedErrorCodeNotAuthoritative: "Not Authoritative", + ExtendedErrorCodeNotSupported: "Not Supported", + ExtendedErrorCodeNoReachableAuthority: "No Reachable Authority", + ExtendedErrorCodeNetworkError: "Network Error", + ExtendedErrorCodeInvalidData: "Invalid Data", + ExtendedErrorCodeSignatureExpiredBeforeValid: "Signature Expired Before Valid", + ExtendedErrorCodeTooEarly: "Too Early", + ExtendedErrorCodeUnsupportedNSEC3IterValue: "Unsupported NSEC3 Iterations Value", + ExtendedErrorCodeUnableToConformToPolicy: "Unable To Conform To Policy", + ExtendedErrorCodeSynthesized: "Synthesized", + ExtendedErrorCodeInvalidQueryType: "Invalid Query Type", } // StringToExtendedErrorCode is a map from human readable descriptions to diff --git a/vendor/github.com/miekg/dns/msg.go b/vendor/github.com/miekg/dns/msg.go index 8294d0395..5fa7f9e83 100644 --- a/vendor/github.com/miekg/dns/msg.go +++ b/vendor/github.com/miekg/dns/msg.go @@ -714,7 +714,7 @@ func (h *MsgHdr) String() string { return s } -// Pack packs a Msg: it is converted to to wire format. +// Pack packs a Msg: it is converted to wire format. // If the dns.Compress is true the message will be in compressed wire format. func (dns *Msg) Pack() (msg []byte, err error) { return dns.PackBuffer(nil) diff --git a/vendor/github.com/miekg/dns/scan.go b/vendor/github.com/miekg/dns/scan.go index 1f92ae421..e26e8027a 100644 --- a/vendor/github.com/miekg/dns/scan.go +++ b/vendor/github.com/miekg/dns/scan.go @@ -101,12 +101,13 @@ type ttlState struct { isByDirective bool // isByDirective indicates whether ttl was set by a $TTL directive } -// NewRR reads the RR contained in the string s. Only the first RR is returned. +// NewRR reads a string s and returns the first RR. // If s contains no records, NewRR will return nil with no error. // -// The class defaults to IN and TTL defaults to 3600. The full zone file syntax -// like $TTL, $ORIGIN, etc. is supported. All fields of the returned RR are -// set, except RR.Header().Rdlength which is set to 0. +// The class defaults to IN, TTL defaults to 3600, and +// origin for resolving relative domain names defaults to the DNS root (.). +// Full zone file syntax is supported, including directives like $TTL and $ORIGIN. +// All fields of the returned RR are set from the read data, except RR.Header().Rdlength which is set to 0. func NewRR(s string) (RR, error) { if len(s) > 0 && s[len(s)-1] != '\n' { // We need a closing newline return ReadRR(strings.NewReader(s+"\n"), "") @@ -1282,7 +1283,7 @@ func stringToCm(token string) (e, m uint8, ok bool) { cmeters *= 10 } } - // This slighly ugly condition will allow omitting the 'meter' part, like .01 (meaning 0.01m = 1cm). + // This slightly ugly condition will allow omitting the 'meter' part, like .01 (meaning 0.01m = 1cm). if !hasCM || mStr != "" { meters, err = strconv.Atoi(mStr) // RFC1876 states the max value is 90000000.00. The latter two conditions enforce it. diff --git a/vendor/github.com/miekg/dns/scan_rr.go b/vendor/github.com/miekg/dns/scan_rr.go index 1a90c61f8..c1a76995e 100644 --- a/vendor/github.com/miekg/dns/scan_rr.go +++ b/vendor/github.com/miekg/dns/scan_rr.go @@ -51,25 +51,24 @@ func endingToTxtSlice(c *zlexer, errstr string) ([]string, *ParseError) { switch l.value { case zString: empty = false - if len(l.token) > 255 { - // split up tokens that are larger than 255 into 255-chunks - sx := []string{} - p, i := 0, 255 - for { - if i <= len(l.token) { - sx = append(sx, l.token[p:i]) - } else { - sx = append(sx, l.token[p:]) - break - - } - p, i = p+255, i+255 + // split up tokens that are larger than 255 into 255-chunks + sx := []string{} + p := 0 + for { + i, ok := escapedStringOffset(l.token[p:], 255) + if !ok { + return nil, &ParseError{err: errstr, lex: l} } - s = append(s, sx...) - break - } + if i != -1 && p+i != len(l.token) { + sx = append(sx, l.token[p:p+i]) + } else { + sx = append(sx, l.token[p:]) + break - s = append(s, l.token) + } + p += i + } + s = append(s, sx...) case zBlank: if quote { // zBlank can only be seen in between txt parts. @@ -1920,3 +1919,39 @@ func (rr *APL) parse(c *zlexer, o string) *ParseError { rr.Prefixes = prefixes return nil } + +// escapedStringOffset finds the offset within a string (which may contain escape +// sequences) that corresponds to a certain byte offset. If the input offset is +// out of bounds, -1 is returned (which is *not* considered an error). +func escapedStringOffset(s string, desiredByteOffset int) (int, bool) { + if desiredByteOffset == 0 { + return 0, true + } + + currentByteOffset, i := 0, 0 + + for i < len(s) { + currentByteOffset += 1 + + // Skip escape sequences + if s[i] != '\\' { + // Single plain byte, not an escape sequence. + i++ + } else if isDDD(s[i+1:]) { + // Skip backslash and DDD. + i += 4 + } else if len(s[i+1:]) < 1 { + // No character following the backslash; that's an error. + return 0, false + } else { + // Skip backslash and following byte. + i += 2 + } + + if currentByteOffset >= desiredByteOffset { + return i, true + } + } + + return -1, true +} diff --git a/vendor/github.com/miekg/dns/server.go b/vendor/github.com/miekg/dns/server.go index 0207d6da2..81580d1e5 100644 --- a/vendor/github.com/miekg/dns/server.go +++ b/vendor/github.com/miekg/dns/server.go @@ -188,6 +188,14 @@ type DecorateReader func(Reader) Reader // Implementations should never return a nil Writer. type DecorateWriter func(Writer) Writer +// MsgInvalidFunc is a listener hook for observing incoming messages that were discarded +// because they could not be parsed. +// Every message that is read by a Reader will eventually be provided to the Handler, +// rejected (or ignored) by the MsgAcceptFunc, or passed to this function. +type MsgInvalidFunc func(m []byte, err error) + +func DefaultMsgInvalidFunc(m []byte, err error) {} + // A Server defines parameters for running an DNS server. type Server struct { // Address to listen on, ":dns" if empty. @@ -233,6 +241,8 @@ type Server struct { // AcceptMsgFunc will check the incoming message and will reject it early in the process. // By default DefaultMsgAcceptFunc will be used. MsgAcceptFunc MsgAcceptFunc + // MsgInvalidFunc is optional, will be called if a message is received but cannot be parsed. + MsgInvalidFunc MsgInvalidFunc // Shutdown handling lock sync.RWMutex @@ -277,6 +287,9 @@ func (srv *Server) init() { if srv.MsgAcceptFunc == nil { srv.MsgAcceptFunc = DefaultMsgAcceptFunc } + if srv.MsgInvalidFunc == nil { + srv.MsgInvalidFunc = DefaultMsgInvalidFunc + } if srv.Handler == nil { srv.Handler = DefaultServeMux } @@ -531,6 +544,7 @@ func (srv *Server) serveUDP(l net.PacketConn) error { if cap(m) == srv.UDPSize { srv.udpPool.Put(m[:srv.UDPSize]) } + srv.MsgInvalidFunc(m, ErrShortRead) continue } wg.Add(1) @@ -611,6 +625,7 @@ func (srv *Server) serveUDPPacket(wg *sync.WaitGroup, m []byte, u net.PacketConn func (srv *Server) serveDNS(m []byte, w *response) { dh, off, err := unpackMsgHdr(m, 0) if err != nil { + srv.MsgInvalidFunc(m, err) // Let client hang, they are sending crap; any reply can be used to amplify. return } @@ -620,10 +635,12 @@ func (srv *Server) serveDNS(m []byte, w *response) { switch action := srv.MsgAcceptFunc(dh); action { case MsgAccept: - if req.unpack(dh, m, off) == nil { + err := req.unpack(dh, m, off) + if err == nil { break } + srv.MsgInvalidFunc(m, err) fallthrough case MsgReject, MsgRejectNotImplemented: opcode := req.Opcode diff --git a/vendor/github.com/miekg/dns/svcb.go b/vendor/github.com/miekg/dns/svcb.go index c1a740b68..310c7d11f 100644 --- a/vendor/github.com/miekg/dns/svcb.go +++ b/vendor/github.com/miekg/dns/svcb.go @@ -14,7 +14,7 @@ import ( // SVCBKey is the type of the keys used in the SVCB RR. type SVCBKey uint16 -// Keys defined in draft-ietf-dnsop-svcb-https-08 Section 14.3.2. +// Keys defined in rfc9460 const ( SVCB_MANDATORY SVCBKey = iota SVCB_ALPN @@ -23,7 +23,8 @@ const ( SVCB_IPV4HINT SVCB_ECHCONFIG SVCB_IPV6HINT - SVCB_DOHPATH // draft-ietf-add-svcb-dns-02 Section 9 + SVCB_DOHPATH // rfc9461 Section 5 + SVCB_OHTTP // rfc9540 Section 8 svcb_RESERVED SVCBKey = 65535 ) @@ -37,6 +38,7 @@ var svcbKeyToStringMap = map[SVCBKey]string{ SVCB_ECHCONFIG: "ech", SVCB_IPV6HINT: "ipv6hint", SVCB_DOHPATH: "dohpath", + SVCB_OHTTP: "ohttp", } var svcbStringToKeyMap = reverseSVCBKeyMap(svcbKeyToStringMap) @@ -201,6 +203,8 @@ func makeSVCBKeyValue(key SVCBKey) SVCBKeyValue { return new(SVCBIPv6Hint) case SVCB_DOHPATH: return new(SVCBDoHPath) + case SVCB_OHTTP: + return new(SVCBOhttp) case svcb_RESERVED: return nil default: @@ -771,8 +775,8 @@ func (s *SVCBIPv6Hint) copy() SVCBKeyValue { // SVCBDoHPath pair is used to indicate the URI template that the // clients may use to construct a DNS over HTTPS URI. // -// See RFC xxxx (https://datatracker.ietf.org/doc/html/draft-ietf-add-svcb-dns-02) -// and RFC yyyy (https://datatracker.ietf.org/doc/html/draft-ietf-add-ddr-06). +// See RFC 9461 (https://datatracker.ietf.org/doc/html/rfc9461) +// and RFC 9462 (https://datatracker.ietf.org/doc/html/rfc9462). // // A basic example of using the dohpath option together with the alpn // option to indicate support for DNS over HTTPS on a certain path: @@ -816,6 +820,44 @@ func (s *SVCBDoHPath) copy() SVCBKeyValue { } } +// The "ohttp" SvcParamKey is used to indicate that a service described in a SVCB RR +// can be accessed as a target using an associated gateway. +// Both the presentation and wire-format values for the "ohttp" parameter MUST be empty. +// +// See RFC 9460 (https://datatracker.ietf.org/doc/html/rfc9460/) +// and RFC 9230 (https://datatracker.ietf.org/doc/html/rfc9230/) +// +// A basic example of using the dohpath option together with the alpn +// option to indicate support for DNS over HTTPS on a certain path: +// +// s := new(dns.SVCB) +// s.Hdr = dns.RR_Header{Name: ".", Rrtype: dns.TypeSVCB, Class: dns.ClassINET} +// e := new(dns.SVCBAlpn) +// e.Alpn = []string{"h2", "h3"} +// p := new(dns.SVCBOhttp) +// s.Value = append(s.Value, e, p) +type SVCBOhttp struct{} + +func (*SVCBOhttp) Key() SVCBKey { return SVCB_OHTTP } +func (*SVCBOhttp) copy() SVCBKeyValue { return &SVCBOhttp{} } +func (*SVCBOhttp) pack() ([]byte, error) { return []byte{}, nil } +func (*SVCBOhttp) String() string { return "" } +func (*SVCBOhttp) len() int { return 0 } + +func (*SVCBOhttp) unpack(b []byte) error { + if len(b) != 0 { + return errors.New("dns: svcbotthp: svcbotthp must have no value") + } + return nil +} + +func (*SVCBOhttp) parse(b string) error { + if b != "" { + return errors.New("dns: svcbotthp: svcbotthp must have no value") + } + return nil +} + // SVCBLocal pair is intended for experimental/private use. The key is recommended // to be in the range [SVCB_PRIVATE_LOWER, SVCB_PRIVATE_UPPER]. // Basic use pattern for creating a keyNNNNN option: diff --git a/vendor/github.com/miekg/dns/types.go b/vendor/github.com/miekg/dns/types.go index 8e3129cbd..7a34c14ca 100644 --- a/vendor/github.com/miekg/dns/types.go +++ b/vendor/github.com/miekg/dns/types.go @@ -96,6 +96,7 @@ const ( TypeLP uint16 = 107 TypeEUI48 uint16 = 108 TypeEUI64 uint16 = 109 + TypeNXNAME uint16 = 128 TypeURI uint16 = 256 TypeCAA uint16 = 257 TypeAVC uint16 = 258 @@ -294,6 +295,19 @@ func (*NULL) parse(c *zlexer, origin string) *ParseError { return &ParseError{err: "NULL records do not have a presentation format"} } +// NXNAME is a meta record. See https://www.iana.org/go/draft-ietf-dnsop-compact-denial-of-existence-04 +// Reference: https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml +type NXNAME struct { + Hdr RR_Header + // Does not have any rdata +} + +func (rr *NXNAME) String() string { return rr.Hdr.String() } + +func (*NXNAME) parse(c *zlexer, origin string) *ParseError { + return &ParseError{err: "NXNAME records do not have a presentation format"} +} + // CNAME RR. See RFC 1034. type CNAME struct { Hdr RR_Header diff --git a/vendor/github.com/miekg/dns/version.go b/vendor/github.com/miekg/dns/version.go index dc34e5902..00c8629f2 100644 --- a/vendor/github.com/miekg/dns/version.go +++ b/vendor/github.com/miekg/dns/version.go @@ -3,7 +3,7 @@ package dns import "fmt" // Version is current version of this library. -var Version = v{1, 1, 58} +var Version = v{1, 1, 62} // v holds the version of this library. type v struct { diff --git a/vendor/github.com/miekg/dns/xfr.go b/vendor/github.com/miekg/dns/xfr.go index 05b3c5add..5cfbb516a 100644 --- a/vendor/github.com/miekg/dns/xfr.go +++ b/vendor/github.com/miekg/dns/xfr.go @@ -1,6 +1,7 @@ package dns import ( + "crypto/tls" "fmt" "time" ) @@ -20,6 +21,7 @@ type Transfer struct { TsigProvider TsigProvider // An implementation of the TsigProvider interface. If defined it replaces TsigSecret and is used for all TSIG operations. TsigSecret map[string]string // Secret(s) for Tsig map[], zonename must be in canonical form (lowercase, fqdn, see RFC 4034 Section 6.2) tsigTimersOnly bool + TLS *tls.Config // TLS config. If Xfr over TLS will be attempted } func (t *Transfer) tsigProvider() TsigProvider { @@ -57,7 +59,11 @@ func (t *Transfer) In(q *Msg, a string) (env chan *Envelope, err error) { } if t.Conn == nil { - t.Conn, err = DialTimeout("tcp", a, timeout) + if t.TLS != nil { + t.Conn, err = DialTimeoutWithTLS("tcp-tls", a, t.TLS, timeout) + } else { + t.Conn, err = DialTimeout("tcp", a, timeout) + } if err != nil { return nil, err } @@ -182,7 +188,7 @@ func (t *Transfer) inIxfr(q *Msg, c chan *Envelope) { if v, ok := rr.(*SOA); ok { if v.Serial == serial { n++ - // quit if it's a full axfr or the the servers' SOA is repeated the third time + // quit if it's a full axfr or the servers' SOA is repeated the third time if axfr && n == 2 || n == 3 { c <- &Envelope{in.Answer, nil} return @@ -203,6 +209,7 @@ func (t *Transfer) inIxfr(q *Msg, c chan *Envelope) { // ch := make(chan *dns.Envelope) // tr := new(dns.Transfer) // var wg sync.WaitGroup +// wg.Add(1) // go func() { // tr.Out(w, r, ch) // wg.Done() diff --git a/vendor/github.com/miekg/dns/zduplicate.go b/vendor/github.com/miekg/dns/zduplicate.go index 03029fb3e..330c05395 100644 --- a/vendor/github.com/miekg/dns/zduplicate.go +++ b/vendor/github.com/miekg/dns/zduplicate.go @@ -886,6 +886,15 @@ func (r1 *NULL) isDuplicate(_r2 RR) bool { return true } +func (r1 *NXNAME) isDuplicate(_r2 RR) bool { + r2, ok := _r2.(*NXNAME) + if !ok { + return false + } + _ = r2 + return true +} + func (r1 *NXT) isDuplicate(_r2 RR) bool { r2, ok := _r2.(*NXT) if !ok { diff --git a/vendor/github.com/miekg/dns/zmsg.go b/vendor/github.com/miekg/dns/zmsg.go index 39b3bc810..5a6cf4c6a 100644 --- a/vendor/github.com/miekg/dns/zmsg.go +++ b/vendor/github.com/miekg/dns/zmsg.go @@ -706,6 +706,10 @@ func (rr *NULL) pack(msg []byte, off int, compression compressionMap, compress b return off, nil } +func (rr *NXNAME) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) { + return off, nil +} + func (rr *NXT) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) { off, err = packDomainName(rr.NextDomain, msg, off, compression, false) if err != nil { @@ -2266,6 +2270,13 @@ func (rr *NULL) unpack(msg []byte, off int) (off1 int, err error) { return off, nil } +func (rr *NXNAME) unpack(msg []byte, off int) (off1 int, err error) { + rdStart := off + _ = rdStart + + return off, nil +} + func (rr *NXT) unpack(msg []byte, off int) (off1 int, err error) { rdStart := off _ = rdStart diff --git a/vendor/github.com/miekg/dns/ztypes.go b/vendor/github.com/miekg/dns/ztypes.go index 2c70fc44d..11f13ecf9 100644 --- a/vendor/github.com/miekg/dns/ztypes.go +++ b/vendor/github.com/miekg/dns/ztypes.go @@ -60,6 +60,7 @@ var TypeToRR = map[uint16]func() RR{ TypeNSEC3: func() RR { return new(NSEC3) }, TypeNSEC3PARAM: func() RR { return new(NSEC3PARAM) }, TypeNULL: func() RR { return new(NULL) }, + TypeNXNAME: func() RR { return new(NXNAME) }, TypeNXT: func() RR { return new(NXT) }, TypeOPENPGPKEY: func() RR { return new(OPENPGPKEY) }, TypeOPT: func() RR { return new(OPT) }, @@ -146,6 +147,7 @@ var TypeToString = map[uint16]string{ TypeNSEC3: "NSEC3", TypeNSEC3PARAM: "NSEC3PARAM", TypeNULL: "NULL", + TypeNXNAME: "NXNAME", TypeNXT: "NXT", TypeNone: "None", TypeOPENPGPKEY: "OPENPGPKEY", @@ -230,6 +232,7 @@ func (rr *NSEC) Header() *RR_Header { return &rr.Hdr } func (rr *NSEC3) Header() *RR_Header { return &rr.Hdr } func (rr *NSEC3PARAM) Header() *RR_Header { return &rr.Hdr } func (rr *NULL) Header() *RR_Header { return &rr.Hdr } +func (rr *NXNAME) Header() *RR_Header { return &rr.Hdr } func (rr *NXT) Header() *RR_Header { return &rr.Hdr } func (rr *OPENPGPKEY) Header() *RR_Header { return &rr.Hdr } func (rr *OPT) Header() *RR_Header { return &rr.Hdr } @@ -594,6 +597,11 @@ func (rr *NULL) len(off int, compression map[string]struct{}) int { return l } +func (rr *NXNAME) len(off int, compression map[string]struct{}) int { + l := rr.Hdr.len(off, compression) + return l +} + func (rr *OPENPGPKEY) len(off int, compression map[string]struct{}) int { l := rr.Hdr.len(off, compression) l += base64.StdEncoding.DecodedLen(len(rr.PublicKey)) @@ -1107,6 +1115,10 @@ func (rr *NULL) copy() RR { return &NULL{rr.Hdr, rr.Data} } +func (rr *NXNAME) copy() RR { + return &NXNAME{rr.Hdr} +} + func (rr *NXT) copy() RR { return &NXT{*rr.NSEC.copy().(*NSEC)} } diff --git a/vendor/github.com/mitchellh/mapstructure/CHANGELOG.md b/vendor/github.com/mitchellh/mapstructure/CHANGELOG.md new file mode 100644 index 000000000..c75823490 --- /dev/null +++ b/vendor/github.com/mitchellh/mapstructure/CHANGELOG.md @@ -0,0 +1,96 @@ +## 1.5.0 + +* New option `IgnoreUntaggedFields` to ignore decoding to any fields + without `mapstructure` (or the configured tag name) set [GH-277] +* New option `ErrorUnset` which makes it an error if any fields + in a target struct are not set by the decoding process. [GH-225] +* New function `OrComposeDecodeHookFunc` to help compose decode hooks. [GH-240] +* Decoding to slice from array no longer crashes [GH-265] +* Decode nested struct pointers to map [GH-271] +* Fix issue where `,squash` was ignored if `Squash` option was set. [GH-280] +* Fix issue where fields with `,omitempty` would sometimes decode + into a map with an empty string key [GH-281] + +## 1.4.3 + +* Fix cases where `json.Number` didn't decode properly [GH-261] + +## 1.4.2 + +* Custom name matchers to support any sort of casing, formatting, etc. for + field names. [GH-250] +* Fix possible panic in ComposeDecodeHookFunc [GH-251] + +## 1.4.1 + +* Fix regression where `*time.Time` value would be set to empty and not be sent + to decode hooks properly [GH-232] + +## 1.4.0 + +* A new decode hook type `DecodeHookFuncValue` has been added that has + access to the full values. [GH-183] +* Squash is now supported with embedded fields that are struct pointers [GH-205] +* Empty strings will convert to 0 for all numeric types when weakly decoding [GH-206] + +## 1.3.3 + +* Decoding maps from maps creates a settable value for decode hooks [GH-203] + +## 1.3.2 + +* Decode into interface type with a struct value is supported [GH-187] + +## 1.3.1 + +* Squash should only squash embedded structs. [GH-194] + +## 1.3.0 + +* Added `",omitempty"` support. This will ignore zero values in the source + structure when encoding. [GH-145] + +## 1.2.3 + +* Fix duplicate entries in Keys list with pointer values. [GH-185] + +## 1.2.2 + +* Do not add unsettable (unexported) values to the unused metadata key + or "remain" value. [GH-150] + +## 1.2.1 + +* Go modules checksum mismatch fix + +## 1.2.0 + +* Added support to capture unused values in a field using the `",remain"` value + in the mapstructure tag. There is an example to showcase usage. +* Added `DecoderConfig` option to always squash embedded structs +* `json.Number` can decode into `uint` types +* Empty slices are preserved and not replaced with nil slices +* Fix panic that can occur in when decoding a map into a nil slice of structs +* Improved package documentation for godoc + +## 1.1.2 + +* Fix error when decode hook decodes interface implementation into interface + type. [GH-140] + +## 1.1.1 + +* Fix panic that can happen in `decodePtr` + +## 1.1.0 + +* Added `StringToIPHookFunc` to convert `string` to `net.IP` and `net.IPNet` [GH-133] +* Support struct to struct decoding [GH-137] +* If source map value is nil, then destination map value is nil (instead of empty) +* If source slice value is nil, then destination slice value is nil (instead of empty) +* If source pointer is nil, then destination pointer is set to nil (instead of + allocated zero value of type) + +## 1.0.0 + +* Initial tagged stable release. diff --git a/vendor/github.com/mitchellh/mapstructure/LICENSE b/vendor/github.com/mitchellh/mapstructure/LICENSE new file mode 100644 index 000000000..f9c841a51 --- /dev/null +++ b/vendor/github.com/mitchellh/mapstructure/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2013 Mitchell Hashimoto + +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/mitchellh/mapstructure/README.md b/vendor/github.com/mitchellh/mapstructure/README.md new file mode 100644 index 000000000..0018dc7d9 --- /dev/null +++ b/vendor/github.com/mitchellh/mapstructure/README.md @@ -0,0 +1,46 @@ +# mapstructure [![Godoc](https://godoc.org/github.com/mitchellh/mapstructure?status.svg)](https://godoc.org/github.com/mitchellh/mapstructure) + +mapstructure is a Go library for decoding generic map values to structures +and vice versa, while providing helpful error handling. + +This library is most useful when decoding values from some data stream (JSON, +Gob, etc.) where you don't _quite_ know the structure of the underlying data +until you read a part of it. You can therefore read a `map[string]interface{}` +and use this library to decode it into the proper underlying native Go +structure. + +## Installation + +Standard `go get`: + +``` +$ go get github.com/mitchellh/mapstructure +``` + +## Usage & Example + +For usage and examples see the [Godoc](http://godoc.org/github.com/mitchellh/mapstructure). + +The `Decode` function has examples associated with it there. + +## But Why?! + +Go offers fantastic standard libraries for decoding formats such as JSON. +The standard method is to have a struct pre-created, and populate that struct +from the bytes of the encoded format. This is great, but the problem is if +you have configuration or an encoding that changes slightly depending on +specific fields. For example, consider this JSON: + +```json +{ + "type": "person", + "name": "Mitchell" +} +``` + +Perhaps we can't populate a specific structure without first reading +the "type" field from the JSON. We could always do two passes over the +decoding of the JSON (reading the "type" first, and the rest later). +However, it is much simpler to just decode this into a `map[string]interface{}` +structure, read the "type" key, then use something like this library +to decode it into the proper structure. diff --git a/vendor/github.com/mitchellh/mapstructure/decode_hooks.go b/vendor/github.com/mitchellh/mapstructure/decode_hooks.go new file mode 100644 index 000000000..3a754ca72 --- /dev/null +++ b/vendor/github.com/mitchellh/mapstructure/decode_hooks.go @@ -0,0 +1,279 @@ +package mapstructure + +import ( + "encoding" + "errors" + "fmt" + "net" + "reflect" + "strconv" + "strings" + "time" +) + +// typedDecodeHook takes a raw DecodeHookFunc (an interface{}) and turns +// it into the proper DecodeHookFunc type, such as DecodeHookFuncType. +func typedDecodeHook(h DecodeHookFunc) DecodeHookFunc { + // Create variables here so we can reference them with the reflect pkg + var f1 DecodeHookFuncType + var f2 DecodeHookFuncKind + var f3 DecodeHookFuncValue + + // Fill in the variables into this interface and the rest is done + // automatically using the reflect package. + potential := []interface{}{f1, f2, f3} + + v := reflect.ValueOf(h) + vt := v.Type() + for _, raw := range potential { + pt := reflect.ValueOf(raw).Type() + if vt.ConvertibleTo(pt) { + return v.Convert(pt).Interface() + } + } + + return nil +} + +// DecodeHookExec executes the given decode hook. This should be used +// since it'll naturally degrade to the older backwards compatible DecodeHookFunc +// that took reflect.Kind instead of reflect.Type. +func DecodeHookExec( + raw DecodeHookFunc, + from reflect.Value, to reflect.Value) (interface{}, error) { + + switch f := typedDecodeHook(raw).(type) { + case DecodeHookFuncType: + return f(from.Type(), to.Type(), from.Interface()) + case DecodeHookFuncKind: + return f(from.Kind(), to.Kind(), from.Interface()) + case DecodeHookFuncValue: + return f(from, to) + default: + return nil, errors.New("invalid decode hook signature") + } +} + +// ComposeDecodeHookFunc creates a single DecodeHookFunc that +// automatically composes multiple DecodeHookFuncs. +// +// The composed funcs are called in order, with the result of the +// previous transformation. +func ComposeDecodeHookFunc(fs ...DecodeHookFunc) DecodeHookFunc { + return func(f reflect.Value, t reflect.Value) (interface{}, error) { + var err error + data := f.Interface() + + newFrom := f + for _, f1 := range fs { + data, err = DecodeHookExec(f1, newFrom, t) + if err != nil { + return nil, err + } + newFrom = reflect.ValueOf(data) + } + + return data, nil + } +} + +// OrComposeDecodeHookFunc executes all input hook functions until one of them returns no error. In that case its value is returned. +// If all hooks return an error, OrComposeDecodeHookFunc returns an error concatenating all error messages. +func OrComposeDecodeHookFunc(ff ...DecodeHookFunc) DecodeHookFunc { + return func(a, b reflect.Value) (interface{}, error) { + var allErrs string + var out interface{} + var err error + + for _, f := range ff { + out, err = DecodeHookExec(f, a, b) + if err != nil { + allErrs += err.Error() + "\n" + continue + } + + return out, nil + } + + return nil, errors.New(allErrs) + } +} + +// StringToSliceHookFunc returns a DecodeHookFunc that converts +// string to []string by splitting on the given sep. +func StringToSliceHookFunc(sep string) DecodeHookFunc { + return func( + f reflect.Kind, + t reflect.Kind, + data interface{}) (interface{}, error) { + if f != reflect.String || t != reflect.Slice { + return data, nil + } + + raw := data.(string) + if raw == "" { + return []string{}, nil + } + + return strings.Split(raw, sep), nil + } +} + +// StringToTimeDurationHookFunc returns a DecodeHookFunc that converts +// strings to time.Duration. +func StringToTimeDurationHookFunc() DecodeHookFunc { + return func( + f reflect.Type, + t reflect.Type, + data interface{}) (interface{}, error) { + if f.Kind() != reflect.String { + return data, nil + } + if t != reflect.TypeOf(time.Duration(5)) { + return data, nil + } + + // Convert it by parsing + return time.ParseDuration(data.(string)) + } +} + +// StringToIPHookFunc returns a DecodeHookFunc that converts +// strings to net.IP +func StringToIPHookFunc() DecodeHookFunc { + return func( + f reflect.Type, + t reflect.Type, + data interface{}) (interface{}, error) { + if f.Kind() != reflect.String { + return data, nil + } + if t != reflect.TypeOf(net.IP{}) { + return data, nil + } + + // Convert it by parsing + ip := net.ParseIP(data.(string)) + if ip == nil { + return net.IP{}, fmt.Errorf("failed parsing ip %v", data) + } + + return ip, nil + } +} + +// StringToIPNetHookFunc returns a DecodeHookFunc that converts +// strings to net.IPNet +func StringToIPNetHookFunc() DecodeHookFunc { + return func( + f reflect.Type, + t reflect.Type, + data interface{}) (interface{}, error) { + if f.Kind() != reflect.String { + return data, nil + } + if t != reflect.TypeOf(net.IPNet{}) { + return data, nil + } + + // Convert it by parsing + _, net, err := net.ParseCIDR(data.(string)) + return net, err + } +} + +// StringToTimeHookFunc returns a DecodeHookFunc that converts +// strings to time.Time. +func StringToTimeHookFunc(layout string) DecodeHookFunc { + return func( + f reflect.Type, + t reflect.Type, + data interface{}) (interface{}, error) { + if f.Kind() != reflect.String { + return data, nil + } + if t != reflect.TypeOf(time.Time{}) { + return data, nil + } + + // Convert it by parsing + return time.Parse(layout, data.(string)) + } +} + +// WeaklyTypedHook is a DecodeHookFunc which adds support for weak typing to +// the decoder. +// +// Note that this is significantly different from the WeaklyTypedInput option +// of the DecoderConfig. +func WeaklyTypedHook( + f reflect.Kind, + t reflect.Kind, + data interface{}) (interface{}, error) { + dataVal := reflect.ValueOf(data) + switch t { + case reflect.String: + switch f { + case reflect.Bool: + if dataVal.Bool() { + return "1", nil + } + return "0", nil + case reflect.Float32: + return strconv.FormatFloat(dataVal.Float(), 'f', -1, 64), nil + case reflect.Int: + return strconv.FormatInt(dataVal.Int(), 10), nil + case reflect.Slice: + dataType := dataVal.Type() + elemKind := dataType.Elem().Kind() + if elemKind == reflect.Uint8 { + return string(dataVal.Interface().([]uint8)), nil + } + case reflect.Uint: + return strconv.FormatUint(dataVal.Uint(), 10), nil + } + } + + return data, nil +} + +func RecursiveStructToMapHookFunc() DecodeHookFunc { + return func(f reflect.Value, t reflect.Value) (interface{}, error) { + if f.Kind() != reflect.Struct { + return f.Interface(), nil + } + + var i interface{} = struct{}{} + if t.Type() != reflect.TypeOf(&i).Elem() { + return f.Interface(), nil + } + + m := make(map[string]interface{}) + t.Set(reflect.ValueOf(m)) + + return f.Interface(), nil + } +} + +// TextUnmarshallerHookFunc returns a DecodeHookFunc that applies +// strings to the UnmarshalText function, when the target type +// implements the encoding.TextUnmarshaler interface +func TextUnmarshallerHookFunc() DecodeHookFuncType { + return func( + f reflect.Type, + t reflect.Type, + data interface{}) (interface{}, error) { + if f.Kind() != reflect.String { + return data, nil + } + result := reflect.New(t).Interface() + unmarshaller, ok := result.(encoding.TextUnmarshaler) + if !ok { + return data, nil + } + if err := unmarshaller.UnmarshalText([]byte(data.(string))); err != nil { + return nil, err + } + return result, nil + } +} diff --git a/vendor/github.com/mitchellh/mapstructure/error.go b/vendor/github.com/mitchellh/mapstructure/error.go new file mode 100644 index 000000000..47a99e5af --- /dev/null +++ b/vendor/github.com/mitchellh/mapstructure/error.go @@ -0,0 +1,50 @@ +package mapstructure + +import ( + "errors" + "fmt" + "sort" + "strings" +) + +// Error implements the error interface and can represents multiple +// errors that occur in the course of a single decode. +type Error struct { + Errors []string +} + +func (e *Error) Error() string { + points := make([]string, len(e.Errors)) + for i, err := range e.Errors { + points[i] = fmt.Sprintf("* %s", err) + } + + sort.Strings(points) + return fmt.Sprintf( + "%d error(s) decoding:\n\n%s", + len(e.Errors), strings.Join(points, "\n")) +} + +// WrappedErrors implements the errwrap.Wrapper interface to make this +// return value more useful with the errwrap and go-multierror libraries. +func (e *Error) WrappedErrors() []error { + if e == nil { + return nil + } + + result := make([]error, len(e.Errors)) + for i, e := range e.Errors { + result[i] = errors.New(e) + } + + return result +} + +func appendErrors(errors []string, err error) []string { + switch e := err.(type) { + case *Error: + return append(errors, e.Errors...) + default: + return append(errors, e.Error()) + } +} diff --git a/vendor/github.com/mitchellh/mapstructure/mapstructure.go b/vendor/github.com/mitchellh/mapstructure/mapstructure.go new file mode 100644 index 000000000..1efb22ac3 --- /dev/null +++ b/vendor/github.com/mitchellh/mapstructure/mapstructure.go @@ -0,0 +1,1540 @@ +// Package mapstructure exposes functionality to convert one arbitrary +// Go type into another, typically to convert a map[string]interface{} +// into a native Go structure. +// +// The Go structure can be arbitrarily complex, containing slices, +// other structs, etc. and the decoder will properly decode nested +// maps and so on into the proper structures in the native Go struct. +// See the examples to see what the decoder is capable of. +// +// The simplest function to start with is Decode. +// +// Field Tags +// +// When decoding to a struct, mapstructure will use the field name by +// default to perform the mapping. For example, if a struct has a field +// "Username" then mapstructure will look for a key in the source value +// of "username" (case insensitive). +// +// type User struct { +// Username string +// } +// +// You can change the behavior of mapstructure by using struct tags. +// The default struct tag that mapstructure looks for is "mapstructure" +// but you can customize it using DecoderConfig. +// +// Renaming Fields +// +// To rename the key that mapstructure looks for, use the "mapstructure" +// tag and set a value directly. For example, to change the "username" example +// above to "user": +// +// type User struct { +// Username string `mapstructure:"user"` +// } +// +// Embedded Structs and Squashing +// +// Embedded structs are treated as if they're another field with that name. +// By default, the two structs below are equivalent when decoding with +// mapstructure: +// +// type Person struct { +// Name string +// } +// +// type Friend struct { +// Person +// } +// +// type Friend struct { +// Person Person +// } +// +// This would require an input that looks like below: +// +// map[string]interface{}{ +// "person": map[string]interface{}{"name": "alice"}, +// } +// +// If your "person" value is NOT nested, then you can append ",squash" to +// your tag value and mapstructure will treat it as if the embedded struct +// were part of the struct directly. Example: +// +// type Friend struct { +// Person `mapstructure:",squash"` +// } +// +// Now the following input would be accepted: +// +// map[string]interface{}{ +// "name": "alice", +// } +// +// When decoding from a struct to a map, the squash tag squashes the struct +// fields into a single map. Using the example structs from above: +// +// Friend{Person: Person{Name: "alice"}} +// +// Will be decoded into a map: +// +// map[string]interface{}{ +// "name": "alice", +// } +// +// DecoderConfig has a field that changes the behavior of mapstructure +// to always squash embedded structs. +// +// Remainder Values +// +// If there are any unmapped keys in the source value, mapstructure by +// default will silently ignore them. You can error by setting ErrorUnused +// in DecoderConfig. If you're using Metadata you can also maintain a slice +// of the unused keys. +// +// You can also use the ",remain" suffix on your tag to collect all unused +// values in a map. The field with this tag MUST be a map type and should +// probably be a "map[string]interface{}" or "map[interface{}]interface{}". +// See example below: +// +// type Friend struct { +// Name string +// Other map[string]interface{} `mapstructure:",remain"` +// } +// +// Given the input below, Other would be populated with the other +// values that weren't used (everything but "name"): +// +// map[string]interface{}{ +// "name": "bob", +// "address": "123 Maple St.", +// } +// +// Omit Empty Values +// +// When decoding from a struct to any other value, you may use the +// ",omitempty" suffix on your tag to omit that value if it equates to +// the zero value. The zero value of all types is specified in the Go +// specification. +// +// For example, the zero type of a numeric type is zero ("0"). If the struct +// field value is zero and a numeric type, the field is empty, and it won't +// be encoded into the destination type. +// +// type Source struct { +// Age int `mapstructure:",omitempty"` +// } +// +// Unexported fields +// +// Since unexported (private) struct fields cannot be set outside the package +// where they are defined, the decoder will simply skip them. +// +// For this output type definition: +// +// type Exported struct { +// private string // this unexported field will be skipped +// Public string +// } +// +// Using this map as input: +// +// map[string]interface{}{ +// "private": "I will be ignored", +// "Public": "I made it through!", +// } +// +// The following struct will be decoded: +// +// type Exported struct { +// private: "" // field is left with an empty string (zero value) +// Public: "I made it through!" +// } +// +// Other Configuration +// +// mapstructure is highly configurable. See the DecoderConfig struct +// for other features and options that are supported. +package mapstructure + +import ( + "encoding/json" + "errors" + "fmt" + "reflect" + "sort" + "strconv" + "strings" +) + +// DecodeHookFunc is the callback function that can be used for +// data transformations. See "DecodeHook" in the DecoderConfig +// struct. +// +// The type must be one of DecodeHookFuncType, DecodeHookFuncKind, or +// DecodeHookFuncValue. +// Values are a superset of Types (Values can return types), and Types are a +// superset of Kinds (Types can return Kinds) and are generally a richer thing +// to use, but Kinds are simpler if you only need those. +// +// The reason DecodeHookFunc is multi-typed is for backwards compatibility: +// we started with Kinds and then realized Types were the better solution, +// but have a promise to not break backwards compat so we now support +// both. +type DecodeHookFunc interface{} + +// DecodeHookFuncType is a DecodeHookFunc which has complete information about +// the source and target types. +type DecodeHookFuncType func(reflect.Type, reflect.Type, interface{}) (interface{}, error) + +// DecodeHookFuncKind is a DecodeHookFunc which knows only the Kinds of the +// source and target types. +type DecodeHookFuncKind func(reflect.Kind, reflect.Kind, interface{}) (interface{}, error) + +// DecodeHookFuncValue is a DecodeHookFunc which has complete access to both the source and target +// values. +type DecodeHookFuncValue func(from reflect.Value, to reflect.Value) (interface{}, error) + +// DecoderConfig is the configuration that is used to create a new decoder +// and allows customization of various aspects of decoding. +type DecoderConfig struct { + // DecodeHook, if set, will be called before any decoding and any + // type conversion (if WeaklyTypedInput is on). This lets you modify + // the values before they're set down onto the resulting struct. The + // DecodeHook is called for every map and value in the input. This means + // that if a struct has embedded fields with squash tags the decode hook + // is called only once with all of the input data, not once for each + // embedded struct. + // + // If an error is returned, the entire decode will fail with that error. + DecodeHook DecodeHookFunc + + // If ErrorUnused is true, then it is an error for there to exist + // keys in the original map that were unused in the decoding process + // (extra keys). + ErrorUnused bool + + // If ErrorUnset is true, then it is an error for there to exist + // fields in the result that were not set in the decoding process + // (extra fields). This only applies to decoding to a struct. This + // will affect all nested structs as well. + ErrorUnset bool + + // ZeroFields, if set to true, will zero fields before writing them. + // For example, a map will be emptied before decoded values are put in + // it. If this is false, a map will be merged. + ZeroFields bool + + // If WeaklyTypedInput is true, the decoder will make the following + // "weak" conversions: + // + // - bools to string (true = "1", false = "0") + // - numbers to string (base 10) + // - bools to int/uint (true = 1, false = 0) + // - strings to int/uint (base implied by prefix) + // - int to bool (true if value != 0) + // - string to bool (accepts: 1, t, T, TRUE, true, True, 0, f, F, + // FALSE, false, False. Anything else is an error) + // - empty array = empty map and vice versa + // - negative numbers to overflowed uint values (base 10) + // - slice of maps to a merged map + // - single values are converted to slices if required. Each + // element is weakly decoded. For example: "4" can become []int{4} + // if the target type is an int slice. + // + WeaklyTypedInput bool + + // Squash will squash embedded structs. A squash tag may also be + // added to an individual struct field using a tag. For example: + // + // type Parent struct { + // Child `mapstructure:",squash"` + // } + Squash bool + + // Metadata is the struct that will contain extra metadata about + // the decoding. If this is nil, then no metadata will be tracked. + Metadata *Metadata + + // Result is a pointer to the struct that will contain the decoded + // value. + Result interface{} + + // The tag name that mapstructure reads for field names. This + // defaults to "mapstructure" + TagName string + + // IgnoreUntaggedFields ignores all struct fields without explicit + // TagName, comparable to `mapstructure:"-"` as default behaviour. + IgnoreUntaggedFields bool + + // MatchName is the function used to match the map key to the struct + // field name or tag. Defaults to `strings.EqualFold`. This can be used + // to implement case-sensitive tag values, support snake casing, etc. + MatchName func(mapKey, fieldName string) bool +} + +// A Decoder takes a raw interface value and turns it into structured +// data, keeping track of rich error information along the way in case +// anything goes wrong. Unlike the basic top-level Decode method, you can +// more finely control how the Decoder behaves using the DecoderConfig +// structure. The top-level Decode method is just a convenience that sets +// up the most basic Decoder. +type Decoder struct { + config *DecoderConfig +} + +// Metadata contains information about decoding a structure that +// is tedious or difficult to get otherwise. +type Metadata struct { + // Keys are the keys of the structure which were successfully decoded + Keys []string + + // Unused is a slice of keys that were found in the raw value but + // weren't decoded since there was no matching field in the result interface + Unused []string + + // Unset is a slice of field names that were found in the result interface + // but weren't set in the decoding process since there was no matching value + // in the input + Unset []string +} + +// Decode takes an input structure and uses reflection to translate it to +// the output structure. output must be a pointer to a map or struct. +func Decode(input interface{}, output interface{}) error { + config := &DecoderConfig{ + Metadata: nil, + Result: output, + } + + decoder, err := NewDecoder(config) + if err != nil { + return err + } + + return decoder.Decode(input) +} + +// WeakDecode is the same as Decode but is shorthand to enable +// WeaklyTypedInput. See DecoderConfig for more info. +func WeakDecode(input, output interface{}) error { + config := &DecoderConfig{ + Metadata: nil, + Result: output, + WeaklyTypedInput: true, + } + + decoder, err := NewDecoder(config) + if err != nil { + return err + } + + return decoder.Decode(input) +} + +// DecodeMetadata is the same as Decode, but is shorthand to +// enable metadata collection. See DecoderConfig for more info. +func DecodeMetadata(input interface{}, output interface{}, metadata *Metadata) error { + config := &DecoderConfig{ + Metadata: metadata, + Result: output, + } + + decoder, err := NewDecoder(config) + if err != nil { + return err + } + + return decoder.Decode(input) +} + +// WeakDecodeMetadata is the same as Decode, but is shorthand to +// enable both WeaklyTypedInput and metadata collection. See +// DecoderConfig for more info. +func WeakDecodeMetadata(input interface{}, output interface{}, metadata *Metadata) error { + config := &DecoderConfig{ + Metadata: metadata, + Result: output, + WeaklyTypedInput: true, + } + + decoder, err := NewDecoder(config) + if err != nil { + return err + } + + return decoder.Decode(input) +} + +// NewDecoder returns a new decoder for the given configuration. Once +// a decoder has been returned, the same configuration must not be used +// again. +func NewDecoder(config *DecoderConfig) (*Decoder, error) { + val := reflect.ValueOf(config.Result) + if val.Kind() != reflect.Ptr { + return nil, errors.New("result must be a pointer") + } + + val = val.Elem() + if !val.CanAddr() { + return nil, errors.New("result must be addressable (a pointer)") + } + + if config.Metadata != nil { + if config.Metadata.Keys == nil { + config.Metadata.Keys = make([]string, 0) + } + + if config.Metadata.Unused == nil { + config.Metadata.Unused = make([]string, 0) + } + + if config.Metadata.Unset == nil { + config.Metadata.Unset = make([]string, 0) + } + } + + if config.TagName == "" { + config.TagName = "mapstructure" + } + + if config.MatchName == nil { + config.MatchName = strings.EqualFold + } + + result := &Decoder{ + config: config, + } + + return result, nil +} + +// Decode decodes the given raw interface to the target pointer specified +// by the configuration. +func (d *Decoder) Decode(input interface{}) error { + return d.decode("", input, reflect.ValueOf(d.config.Result).Elem()) +} + +// Decodes an unknown data type into a specific reflection value. +func (d *Decoder) decode(name string, input interface{}, outVal reflect.Value) error { + var inputVal reflect.Value + if input != nil { + inputVal = reflect.ValueOf(input) + + // We need to check here if input is a typed nil. Typed nils won't + // match the "input == nil" below so we check that here. + if inputVal.Kind() == reflect.Ptr && inputVal.IsNil() { + input = nil + } + } + + if input == nil { + // If the data is nil, then we don't set anything, unless ZeroFields is set + // to true. + if d.config.ZeroFields { + outVal.Set(reflect.Zero(outVal.Type())) + + if d.config.Metadata != nil && name != "" { + d.config.Metadata.Keys = append(d.config.Metadata.Keys, name) + } + } + return nil + } + + if !inputVal.IsValid() { + // If the input value is invalid, then we just set the value + // to be the zero value. + outVal.Set(reflect.Zero(outVal.Type())) + if d.config.Metadata != nil && name != "" { + d.config.Metadata.Keys = append(d.config.Metadata.Keys, name) + } + return nil + } + + if d.config.DecodeHook != nil { + // We have a DecodeHook, so let's pre-process the input. + var err error + input, err = DecodeHookExec(d.config.DecodeHook, inputVal, outVal) + if err != nil { + return fmt.Errorf("error decoding '%s': %s", name, err) + } + } + + var err error + outputKind := getKind(outVal) + addMetaKey := true + switch outputKind { + case reflect.Bool: + err = d.decodeBool(name, input, outVal) + case reflect.Interface: + err = d.decodeBasic(name, input, outVal) + case reflect.String: + err = d.decodeString(name, input, outVal) + case reflect.Int: + err = d.decodeInt(name, input, outVal) + case reflect.Uint: + err = d.decodeUint(name, input, outVal) + case reflect.Float32: + err = d.decodeFloat(name, input, outVal) + case reflect.Struct: + err = d.decodeStruct(name, input, outVal) + case reflect.Map: + err = d.decodeMap(name, input, outVal) + case reflect.Ptr: + addMetaKey, err = d.decodePtr(name, input, outVal) + case reflect.Slice: + err = d.decodeSlice(name, input, outVal) + case reflect.Array: + err = d.decodeArray(name, input, outVal) + case reflect.Func: + err = d.decodeFunc(name, input, outVal) + default: + // If we reached this point then we weren't able to decode it + return fmt.Errorf("%s: unsupported type: %s", name, outputKind) + } + + // If we reached here, then we successfully decoded SOMETHING, so + // mark the key as used if we're tracking metainput. + if addMetaKey && d.config.Metadata != nil && name != "" { + d.config.Metadata.Keys = append(d.config.Metadata.Keys, name) + } + + return err +} + +// This decodes a basic type (bool, int, string, etc.) and sets the +// value to "data" of that type. +func (d *Decoder) decodeBasic(name string, data interface{}, val reflect.Value) error { + if val.IsValid() && val.Elem().IsValid() { + elem := val.Elem() + + // If we can't address this element, then its not writable. Instead, + // we make a copy of the value (which is a pointer and therefore + // writable), decode into that, and replace the whole value. + copied := false + if !elem.CanAddr() { + copied = true + + // Make *T + copy := reflect.New(elem.Type()) + + // *T = elem + copy.Elem().Set(elem) + + // Set elem so we decode into it + elem = copy + } + + // Decode. If we have an error then return. We also return right + // away if we're not a copy because that means we decoded directly. + if err := d.decode(name, data, elem); err != nil || !copied { + return err + } + + // If we're a copy, we need to set te final result + val.Set(elem.Elem()) + return nil + } + + dataVal := reflect.ValueOf(data) + + // If the input data is a pointer, and the assigned type is the dereference + // of that exact pointer, then indirect it so that we can assign it. + // Example: *string to string + if dataVal.Kind() == reflect.Ptr && dataVal.Type().Elem() == val.Type() { + dataVal = reflect.Indirect(dataVal) + } + + if !dataVal.IsValid() { + dataVal = reflect.Zero(val.Type()) + } + + dataValType := dataVal.Type() + if !dataValType.AssignableTo(val.Type()) { + return fmt.Errorf( + "'%s' expected type '%s', got '%s'", + name, val.Type(), dataValType) + } + + val.Set(dataVal) + return nil +} + +func (d *Decoder) decodeString(name string, data interface{}, val reflect.Value) error { + dataVal := reflect.Indirect(reflect.ValueOf(data)) + dataKind := getKind(dataVal) + + converted := true + switch { + case dataKind == reflect.String: + val.SetString(dataVal.String()) + case dataKind == reflect.Bool && d.config.WeaklyTypedInput: + if dataVal.Bool() { + val.SetString("1") + } else { + val.SetString("0") + } + case dataKind == reflect.Int && d.config.WeaklyTypedInput: + val.SetString(strconv.FormatInt(dataVal.Int(), 10)) + case dataKind == reflect.Uint && d.config.WeaklyTypedInput: + val.SetString(strconv.FormatUint(dataVal.Uint(), 10)) + case dataKind == reflect.Float32 && d.config.WeaklyTypedInput: + val.SetString(strconv.FormatFloat(dataVal.Float(), 'f', -1, 64)) + case dataKind == reflect.Slice && d.config.WeaklyTypedInput, + dataKind == reflect.Array && d.config.WeaklyTypedInput: + dataType := dataVal.Type() + elemKind := dataType.Elem().Kind() + switch elemKind { + case reflect.Uint8: + var uints []uint8 + if dataKind == reflect.Array { + uints = make([]uint8, dataVal.Len(), dataVal.Len()) + for i := range uints { + uints[i] = dataVal.Index(i).Interface().(uint8) + } + } else { + uints = dataVal.Interface().([]uint8) + } + val.SetString(string(uints)) + default: + converted = false + } + default: + converted = false + } + + if !converted { + return fmt.Errorf( + "'%s' expected type '%s', got unconvertible type '%s', value: '%v'", + name, val.Type(), dataVal.Type(), data) + } + + return nil +} + +func (d *Decoder) decodeInt(name string, data interface{}, val reflect.Value) error { + dataVal := reflect.Indirect(reflect.ValueOf(data)) + dataKind := getKind(dataVal) + dataType := dataVal.Type() + + switch { + case dataKind == reflect.Int: + val.SetInt(dataVal.Int()) + case dataKind == reflect.Uint: + val.SetInt(int64(dataVal.Uint())) + case dataKind == reflect.Float32: + val.SetInt(int64(dataVal.Float())) + case dataKind == reflect.Bool && d.config.WeaklyTypedInput: + if dataVal.Bool() { + val.SetInt(1) + } else { + val.SetInt(0) + } + case dataKind == reflect.String && d.config.WeaklyTypedInput: + str := dataVal.String() + if str == "" { + str = "0" + } + + i, err := strconv.ParseInt(str, 0, val.Type().Bits()) + if err == nil { + val.SetInt(i) + } else { + return fmt.Errorf("cannot parse '%s' as int: %s", name, err) + } + case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number": + jn := data.(json.Number) + i, err := jn.Int64() + if err != nil { + return fmt.Errorf( + "error decoding json.Number into %s: %s", name, err) + } + val.SetInt(i) + default: + return fmt.Errorf( + "'%s' expected type '%s', got unconvertible type '%s', value: '%v'", + name, val.Type(), dataVal.Type(), data) + } + + return nil +} + +func (d *Decoder) decodeUint(name string, data interface{}, val reflect.Value) error { + dataVal := reflect.Indirect(reflect.ValueOf(data)) + dataKind := getKind(dataVal) + dataType := dataVal.Type() + + switch { + case dataKind == reflect.Int: + i := dataVal.Int() + if i < 0 && !d.config.WeaklyTypedInput { + return fmt.Errorf("cannot parse '%s', %d overflows uint", + name, i) + } + val.SetUint(uint64(i)) + case dataKind == reflect.Uint: + val.SetUint(dataVal.Uint()) + case dataKind == reflect.Float32: + f := dataVal.Float() + if f < 0 && !d.config.WeaklyTypedInput { + return fmt.Errorf("cannot parse '%s', %f overflows uint", + name, f) + } + val.SetUint(uint64(f)) + case dataKind == reflect.Bool && d.config.WeaklyTypedInput: + if dataVal.Bool() { + val.SetUint(1) + } else { + val.SetUint(0) + } + case dataKind == reflect.String && d.config.WeaklyTypedInput: + str := dataVal.String() + if str == "" { + str = "0" + } + + i, err := strconv.ParseUint(str, 0, val.Type().Bits()) + if err == nil { + val.SetUint(i) + } else { + return fmt.Errorf("cannot parse '%s' as uint: %s", name, err) + } + case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number": + jn := data.(json.Number) + i, err := strconv.ParseUint(string(jn), 0, 64) + if err != nil { + return fmt.Errorf( + "error decoding json.Number into %s: %s", name, err) + } + val.SetUint(i) + default: + return fmt.Errorf( + "'%s' expected type '%s', got unconvertible type '%s', value: '%v'", + name, val.Type(), dataVal.Type(), data) + } + + return nil +} + +func (d *Decoder) decodeBool(name string, data interface{}, val reflect.Value) error { + dataVal := reflect.Indirect(reflect.ValueOf(data)) + dataKind := getKind(dataVal) + + switch { + case dataKind == reflect.Bool: + val.SetBool(dataVal.Bool()) + case dataKind == reflect.Int && d.config.WeaklyTypedInput: + val.SetBool(dataVal.Int() != 0) + case dataKind == reflect.Uint && d.config.WeaklyTypedInput: + val.SetBool(dataVal.Uint() != 0) + case dataKind == reflect.Float32 && d.config.WeaklyTypedInput: + val.SetBool(dataVal.Float() != 0) + case dataKind == reflect.String && d.config.WeaklyTypedInput: + b, err := strconv.ParseBool(dataVal.String()) + if err == nil { + val.SetBool(b) + } else if dataVal.String() == "" { + val.SetBool(false) + } else { + return fmt.Errorf("cannot parse '%s' as bool: %s", name, err) + } + default: + return fmt.Errorf( + "'%s' expected type '%s', got unconvertible type '%s', value: '%v'", + name, val.Type(), dataVal.Type(), data) + } + + return nil +} + +func (d *Decoder) decodeFloat(name string, data interface{}, val reflect.Value) error { + dataVal := reflect.Indirect(reflect.ValueOf(data)) + dataKind := getKind(dataVal) + dataType := dataVal.Type() + + switch { + case dataKind == reflect.Int: + val.SetFloat(float64(dataVal.Int())) + case dataKind == reflect.Uint: + val.SetFloat(float64(dataVal.Uint())) + case dataKind == reflect.Float32: + val.SetFloat(dataVal.Float()) + case dataKind == reflect.Bool && d.config.WeaklyTypedInput: + if dataVal.Bool() { + val.SetFloat(1) + } else { + val.SetFloat(0) + } + case dataKind == reflect.String && d.config.WeaklyTypedInput: + str := dataVal.String() + if str == "" { + str = "0" + } + + f, err := strconv.ParseFloat(str, val.Type().Bits()) + if err == nil { + val.SetFloat(f) + } else { + return fmt.Errorf("cannot parse '%s' as float: %s", name, err) + } + case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number": + jn := data.(json.Number) + i, err := jn.Float64() + if err != nil { + return fmt.Errorf( + "error decoding json.Number into %s: %s", name, err) + } + val.SetFloat(i) + default: + return fmt.Errorf( + "'%s' expected type '%s', got unconvertible type '%s', value: '%v'", + name, val.Type(), dataVal.Type(), data) + } + + return nil +} + +func (d *Decoder) decodeMap(name string, data interface{}, val reflect.Value) error { + valType := val.Type() + valKeyType := valType.Key() + valElemType := valType.Elem() + + // By default we overwrite keys in the current map + valMap := val + + // If the map is nil or we're purposely zeroing fields, make a new map + if valMap.IsNil() || d.config.ZeroFields { + // Make a new map to hold our result + mapType := reflect.MapOf(valKeyType, valElemType) + valMap = reflect.MakeMap(mapType) + } + + // Check input type and based on the input type jump to the proper func + dataVal := reflect.Indirect(reflect.ValueOf(data)) + switch dataVal.Kind() { + case reflect.Map: + return d.decodeMapFromMap(name, dataVal, val, valMap) + + case reflect.Struct: + return d.decodeMapFromStruct(name, dataVal, val, valMap) + + case reflect.Array, reflect.Slice: + if d.config.WeaklyTypedInput { + return d.decodeMapFromSlice(name, dataVal, val, valMap) + } + + fallthrough + + default: + return fmt.Errorf("'%s' expected a map, got '%s'", name, dataVal.Kind()) + } +} + +func (d *Decoder) decodeMapFromSlice(name string, dataVal reflect.Value, val reflect.Value, valMap reflect.Value) error { + // Special case for BC reasons (covered by tests) + if dataVal.Len() == 0 { + val.Set(valMap) + return nil + } + + for i := 0; i < dataVal.Len(); i++ { + err := d.decode( + name+"["+strconv.Itoa(i)+"]", + dataVal.Index(i).Interface(), val) + if err != nil { + return err + } + } + + return nil +} + +func (d *Decoder) decodeMapFromMap(name string, dataVal reflect.Value, val reflect.Value, valMap reflect.Value) error { + valType := val.Type() + valKeyType := valType.Key() + valElemType := valType.Elem() + + // Accumulate errors + errors := make([]string, 0) + + // If the input data is empty, then we just match what the input data is. + if dataVal.Len() == 0 { + if dataVal.IsNil() { + if !val.IsNil() { + val.Set(dataVal) + } + } else { + // Set to empty allocated value + val.Set(valMap) + } + + return nil + } + + for _, k := range dataVal.MapKeys() { + fieldName := name + "[" + k.String() + "]" + + // First decode the key into the proper type + currentKey := reflect.Indirect(reflect.New(valKeyType)) + if err := d.decode(fieldName, k.Interface(), currentKey); err != nil { + errors = appendErrors(errors, err) + continue + } + + // Next decode the data into the proper type + v := dataVal.MapIndex(k).Interface() + currentVal := reflect.Indirect(reflect.New(valElemType)) + if err := d.decode(fieldName, v, currentVal); err != nil { + errors = appendErrors(errors, err) + continue + } + + valMap.SetMapIndex(currentKey, currentVal) + } + + // Set the built up map to the value + val.Set(valMap) + + // If we had errors, return those + if len(errors) > 0 { + return &Error{errors} + } + + return nil +} + +func (d *Decoder) decodeMapFromStruct(name string, dataVal reflect.Value, val reflect.Value, valMap reflect.Value) error { + typ := dataVal.Type() + for i := 0; i < typ.NumField(); i++ { + // Get the StructField first since this is a cheap operation. If the + // field is unexported, then ignore it. + f := typ.Field(i) + if f.PkgPath != "" { + continue + } + + // Next get the actual value of this field and verify it is assignable + // to the map value. + v := dataVal.Field(i) + if !v.Type().AssignableTo(valMap.Type().Elem()) { + return fmt.Errorf("cannot assign type '%s' to map value field of type '%s'", v.Type(), valMap.Type().Elem()) + } + + tagValue := f.Tag.Get(d.config.TagName) + keyName := f.Name + + if tagValue == "" && d.config.IgnoreUntaggedFields { + continue + } + + // If Squash is set in the config, we squash the field down. + squash := d.config.Squash && v.Kind() == reflect.Struct && f.Anonymous + + v = dereferencePtrToStructIfNeeded(v, d.config.TagName) + + // Determine the name of the key in the map + if index := strings.Index(tagValue, ","); index != -1 { + if tagValue[:index] == "-" { + continue + } + // If "omitempty" is specified in the tag, it ignores empty values. + if strings.Index(tagValue[index+1:], "omitempty") != -1 && isEmptyValue(v) { + continue + } + + // If "squash" is specified in the tag, we squash the field down. + squash = squash || strings.Index(tagValue[index+1:], "squash") != -1 + if squash { + // When squashing, the embedded type can be a pointer to a struct. + if v.Kind() == reflect.Ptr && v.Elem().Kind() == reflect.Struct { + v = v.Elem() + } + + // The final type must be a struct + if v.Kind() != reflect.Struct { + return fmt.Errorf("cannot squash non-struct type '%s'", v.Type()) + } + } + if keyNameTagValue := tagValue[:index]; keyNameTagValue != "" { + keyName = keyNameTagValue + } + } else if len(tagValue) > 0 { + if tagValue == "-" { + continue + } + keyName = tagValue + } + + switch v.Kind() { + // this is an embedded struct, so handle it differently + case reflect.Struct: + x := reflect.New(v.Type()) + x.Elem().Set(v) + + vType := valMap.Type() + vKeyType := vType.Key() + vElemType := vType.Elem() + mType := reflect.MapOf(vKeyType, vElemType) + vMap := reflect.MakeMap(mType) + + // Creating a pointer to a map so that other methods can completely + // overwrite the map if need be (looking at you decodeMapFromMap). The + // indirection allows the underlying map to be settable (CanSet() == true) + // where as reflect.MakeMap returns an unsettable map. + addrVal := reflect.New(vMap.Type()) + reflect.Indirect(addrVal).Set(vMap) + + err := d.decode(keyName, x.Interface(), reflect.Indirect(addrVal)) + if err != nil { + return err + } + + // the underlying map may have been completely overwritten so pull + // it indirectly out of the enclosing value. + vMap = reflect.Indirect(addrVal) + + if squash { + for _, k := range vMap.MapKeys() { + valMap.SetMapIndex(k, vMap.MapIndex(k)) + } + } else { + valMap.SetMapIndex(reflect.ValueOf(keyName), vMap) + } + + default: + valMap.SetMapIndex(reflect.ValueOf(keyName), v) + } + } + + if val.CanAddr() { + val.Set(valMap) + } + + return nil +} + +func (d *Decoder) decodePtr(name string, data interface{}, val reflect.Value) (bool, error) { + // If the input data is nil, then we want to just set the output + // pointer to be nil as well. + isNil := data == nil + if !isNil { + switch v := reflect.Indirect(reflect.ValueOf(data)); v.Kind() { + case reflect.Chan, + reflect.Func, + reflect.Interface, + reflect.Map, + reflect.Ptr, + reflect.Slice: + isNil = v.IsNil() + } + } + if isNil { + if !val.IsNil() && val.CanSet() { + nilValue := reflect.New(val.Type()).Elem() + val.Set(nilValue) + } + + return true, nil + } + + // Create an element of the concrete (non pointer) type and decode + // into that. Then set the value of the pointer to this type. + valType := val.Type() + valElemType := valType.Elem() + if val.CanSet() { + realVal := val + if realVal.IsNil() || d.config.ZeroFields { + realVal = reflect.New(valElemType) + } + + if err := d.decode(name, data, reflect.Indirect(realVal)); err != nil { + return false, err + } + + val.Set(realVal) + } else { + if err := d.decode(name, data, reflect.Indirect(val)); err != nil { + return false, err + } + } + return false, nil +} + +func (d *Decoder) decodeFunc(name string, data interface{}, val reflect.Value) error { + // Create an element of the concrete (non pointer) type and decode + // into that. Then set the value of the pointer to this type. + dataVal := reflect.Indirect(reflect.ValueOf(data)) + if val.Type() != dataVal.Type() { + return fmt.Errorf( + "'%s' expected type '%s', got unconvertible type '%s', value: '%v'", + name, val.Type(), dataVal.Type(), data) + } + val.Set(dataVal) + return nil +} + +func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value) error { + dataVal := reflect.Indirect(reflect.ValueOf(data)) + dataValKind := dataVal.Kind() + valType := val.Type() + valElemType := valType.Elem() + sliceType := reflect.SliceOf(valElemType) + + // If we have a non array/slice type then we first attempt to convert. + if dataValKind != reflect.Array && dataValKind != reflect.Slice { + if d.config.WeaklyTypedInput { + switch { + // Slice and array we use the normal logic + case dataValKind == reflect.Slice, dataValKind == reflect.Array: + break + + // Empty maps turn into empty slices + case dataValKind == reflect.Map: + if dataVal.Len() == 0 { + val.Set(reflect.MakeSlice(sliceType, 0, 0)) + return nil + } + // Create slice of maps of other sizes + return d.decodeSlice(name, []interface{}{data}, val) + + case dataValKind == reflect.String && valElemType.Kind() == reflect.Uint8: + return d.decodeSlice(name, []byte(dataVal.String()), val) + + // All other types we try to convert to the slice type + // and "lift" it into it. i.e. a string becomes a string slice. + default: + // Just re-try this function with data as a slice. + return d.decodeSlice(name, []interface{}{data}, val) + } + } + + return fmt.Errorf( + "'%s': source data must be an array or slice, got %s", name, dataValKind) + } + + // If the input value is nil, then don't allocate since empty != nil + if dataValKind != reflect.Array && dataVal.IsNil() { + return nil + } + + valSlice := val + if valSlice.IsNil() || d.config.ZeroFields { + // Make a new slice to hold our result, same size as the original data. + valSlice = reflect.MakeSlice(sliceType, dataVal.Len(), dataVal.Len()) + } + + // Accumulate any errors + errors := make([]string, 0) + + for i := 0; i < dataVal.Len(); i++ { + currentData := dataVal.Index(i).Interface() + for valSlice.Len() <= i { + valSlice = reflect.Append(valSlice, reflect.Zero(valElemType)) + } + currentField := valSlice.Index(i) + + fieldName := name + "[" + strconv.Itoa(i) + "]" + if err := d.decode(fieldName, currentData, currentField); err != nil { + errors = appendErrors(errors, err) + } + } + + // Finally, set the value to the slice we built up + val.Set(valSlice) + + // If there were errors, we return those + if len(errors) > 0 { + return &Error{errors} + } + + return nil +} + +func (d *Decoder) decodeArray(name string, data interface{}, val reflect.Value) error { + dataVal := reflect.Indirect(reflect.ValueOf(data)) + dataValKind := dataVal.Kind() + valType := val.Type() + valElemType := valType.Elem() + arrayType := reflect.ArrayOf(valType.Len(), valElemType) + + valArray := val + + if valArray.Interface() == reflect.Zero(valArray.Type()).Interface() || d.config.ZeroFields { + // Check input type + if dataValKind != reflect.Array && dataValKind != reflect.Slice { + if d.config.WeaklyTypedInput { + switch { + // Empty maps turn into empty arrays + case dataValKind == reflect.Map: + if dataVal.Len() == 0 { + val.Set(reflect.Zero(arrayType)) + return nil + } + + // All other types we try to convert to the array type + // and "lift" it into it. i.e. a string becomes a string array. + default: + // Just re-try this function with data as a slice. + return d.decodeArray(name, []interface{}{data}, val) + } + } + + return fmt.Errorf( + "'%s': source data must be an array or slice, got %s", name, dataValKind) + + } + if dataVal.Len() > arrayType.Len() { + return fmt.Errorf( + "'%s': expected source data to have length less or equal to %d, got %d", name, arrayType.Len(), dataVal.Len()) + + } + + // Make a new array to hold our result, same size as the original data. + valArray = reflect.New(arrayType).Elem() + } + + // Accumulate any errors + errors := make([]string, 0) + + for i := 0; i < dataVal.Len(); i++ { + currentData := dataVal.Index(i).Interface() + currentField := valArray.Index(i) + + fieldName := name + "[" + strconv.Itoa(i) + "]" + if err := d.decode(fieldName, currentData, currentField); err != nil { + errors = appendErrors(errors, err) + } + } + + // Finally, set the value to the array we built up + val.Set(valArray) + + // If there were errors, we return those + if len(errors) > 0 { + return &Error{errors} + } + + return nil +} + +func (d *Decoder) decodeStruct(name string, data interface{}, val reflect.Value) error { + dataVal := reflect.Indirect(reflect.ValueOf(data)) + + // If the type of the value to write to and the data match directly, + // then we just set it directly instead of recursing into the structure. + if dataVal.Type() == val.Type() { + val.Set(dataVal) + return nil + } + + dataValKind := dataVal.Kind() + switch dataValKind { + case reflect.Map: + return d.decodeStructFromMap(name, dataVal, val) + + case reflect.Struct: + // Not the most efficient way to do this but we can optimize later if + // we want to. To convert from struct to struct we go to map first + // as an intermediary. + + // Make a new map to hold our result + mapType := reflect.TypeOf((map[string]interface{})(nil)) + mval := reflect.MakeMap(mapType) + + // Creating a pointer to a map so that other methods can completely + // overwrite the map if need be (looking at you decodeMapFromMap). The + // indirection allows the underlying map to be settable (CanSet() == true) + // where as reflect.MakeMap returns an unsettable map. + addrVal := reflect.New(mval.Type()) + + reflect.Indirect(addrVal).Set(mval) + if err := d.decodeMapFromStruct(name, dataVal, reflect.Indirect(addrVal), mval); err != nil { + return err + } + + result := d.decodeStructFromMap(name, reflect.Indirect(addrVal), val) + return result + + default: + return fmt.Errorf("'%s' expected a map, got '%s'", name, dataVal.Kind()) + } +} + +func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) error { + dataValType := dataVal.Type() + if kind := dataValType.Key().Kind(); kind != reflect.String && kind != reflect.Interface { + return fmt.Errorf( + "'%s' needs a map with string keys, has '%s' keys", + name, dataValType.Key().Kind()) + } + + dataValKeys := make(map[reflect.Value]struct{}) + dataValKeysUnused := make(map[interface{}]struct{}) + for _, dataValKey := range dataVal.MapKeys() { + dataValKeys[dataValKey] = struct{}{} + dataValKeysUnused[dataValKey.Interface()] = struct{}{} + } + + targetValKeysUnused := make(map[interface{}]struct{}) + errors := make([]string, 0) + + // This slice will keep track of all the structs we'll be decoding. + // There can be more than one struct if there are embedded structs + // that are squashed. + structs := make([]reflect.Value, 1, 5) + structs[0] = val + + // Compile the list of all the fields that we're going to be decoding + // from all the structs. + type field struct { + field reflect.StructField + val reflect.Value + } + + // remainField is set to a valid field set with the "remain" tag if + // we are keeping track of remaining values. + var remainField *field + + fields := []field{} + for len(structs) > 0 { + structVal := structs[0] + structs = structs[1:] + + structType := structVal.Type() + + for i := 0; i < structType.NumField(); i++ { + fieldType := structType.Field(i) + fieldVal := structVal.Field(i) + if fieldVal.Kind() == reflect.Ptr && fieldVal.Elem().Kind() == reflect.Struct { + // Handle embedded struct pointers as embedded structs. + fieldVal = fieldVal.Elem() + } + + // If "squash" is specified in the tag, we squash the field down. + squash := d.config.Squash && fieldVal.Kind() == reflect.Struct && fieldType.Anonymous + remain := false + + // We always parse the tags cause we're looking for other tags too + tagParts := strings.Split(fieldType.Tag.Get(d.config.TagName), ",") + for _, tag := range tagParts[1:] { + if tag == "squash" { + squash = true + break + } + + if tag == "remain" { + remain = true + break + } + } + + if squash { + if fieldVal.Kind() != reflect.Struct { + errors = appendErrors(errors, + fmt.Errorf("%s: unsupported type for squash: %s", fieldType.Name, fieldVal.Kind())) + } else { + structs = append(structs, fieldVal) + } + continue + } + + // Build our field + if remain { + remainField = &field{fieldType, fieldVal} + } else { + // Normal struct field, store it away + fields = append(fields, field{fieldType, fieldVal}) + } + } + } + + // for fieldType, field := range fields { + for _, f := range fields { + field, fieldValue := f.field, f.val + fieldName := field.Name + + tagValue := field.Tag.Get(d.config.TagName) + tagValue = strings.SplitN(tagValue, ",", 2)[0] + if tagValue != "" { + fieldName = tagValue + } + + rawMapKey := reflect.ValueOf(fieldName) + rawMapVal := dataVal.MapIndex(rawMapKey) + if !rawMapVal.IsValid() { + // Do a slower search by iterating over each key and + // doing case-insensitive search. + for dataValKey := range dataValKeys { + mK, ok := dataValKey.Interface().(string) + if !ok { + // Not a string key + continue + } + + if d.config.MatchName(mK, fieldName) { + rawMapKey = dataValKey + rawMapVal = dataVal.MapIndex(dataValKey) + break + } + } + + if !rawMapVal.IsValid() { + // There was no matching key in the map for the value in + // the struct. Remember it for potential errors and metadata. + targetValKeysUnused[fieldName] = struct{}{} + continue + } + } + + if !fieldValue.IsValid() { + // This should never happen + panic("field is not valid") + } + + // If we can't set the field, then it is unexported or something, + // and we just continue onwards. + if !fieldValue.CanSet() { + continue + } + + // Delete the key we're using from the unused map so we stop tracking + delete(dataValKeysUnused, rawMapKey.Interface()) + + // If the name is empty string, then we're at the root, and we + // don't dot-join the fields. + if name != "" { + fieldName = name + "." + fieldName + } + + if err := d.decode(fieldName, rawMapVal.Interface(), fieldValue); err != nil { + errors = appendErrors(errors, err) + } + } + + // If we have a "remain"-tagged field and we have unused keys then + // we put the unused keys directly into the remain field. + if remainField != nil && len(dataValKeysUnused) > 0 { + // Build a map of only the unused values + remain := map[interface{}]interface{}{} + for key := range dataValKeysUnused { + remain[key] = dataVal.MapIndex(reflect.ValueOf(key)).Interface() + } + + // Decode it as-if we were just decoding this map onto our map. + if err := d.decodeMap(name, remain, remainField.val); err != nil { + errors = appendErrors(errors, err) + } + + // Set the map to nil so we have none so that the next check will + // not error (ErrorUnused) + dataValKeysUnused = nil + } + + if d.config.ErrorUnused && len(dataValKeysUnused) > 0 { + keys := make([]string, 0, len(dataValKeysUnused)) + for rawKey := range dataValKeysUnused { + keys = append(keys, rawKey.(string)) + } + sort.Strings(keys) + + err := fmt.Errorf("'%s' has invalid keys: %s", name, strings.Join(keys, ", ")) + errors = appendErrors(errors, err) + } + + if d.config.ErrorUnset && len(targetValKeysUnused) > 0 { + keys := make([]string, 0, len(targetValKeysUnused)) + for rawKey := range targetValKeysUnused { + keys = append(keys, rawKey.(string)) + } + sort.Strings(keys) + + err := fmt.Errorf("'%s' has unset fields: %s", name, strings.Join(keys, ", ")) + errors = appendErrors(errors, err) + } + + if len(errors) > 0 { + return &Error{errors} + } + + // Add the unused keys to the list of unused keys if we're tracking metadata + if d.config.Metadata != nil { + for rawKey := range dataValKeysUnused { + key := rawKey.(string) + if name != "" { + key = name + "." + key + } + + d.config.Metadata.Unused = append(d.config.Metadata.Unused, key) + } + for rawKey := range targetValKeysUnused { + key := rawKey.(string) + if name != "" { + key = name + "." + key + } + + d.config.Metadata.Unset = append(d.config.Metadata.Unset, key) + } + } + + return nil +} + +func isEmptyValue(v reflect.Value) bool { + switch getKind(v) { + case reflect.Array, reflect.Map, reflect.Slice, reflect.String: + return v.Len() == 0 + case reflect.Bool: + return !v.Bool() + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return v.Int() == 0 + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return v.Uint() == 0 + case reflect.Float32, reflect.Float64: + return v.Float() == 0 + case reflect.Interface, reflect.Ptr: + return v.IsNil() + } + return false +} + +func getKind(val reflect.Value) reflect.Kind { + kind := val.Kind() + + switch { + case kind >= reflect.Int && kind <= reflect.Int64: + return reflect.Int + case kind >= reflect.Uint && kind <= reflect.Uint64: + return reflect.Uint + case kind >= reflect.Float32 && kind <= reflect.Float64: + return reflect.Float32 + default: + return kind + } +} + +func isStructTypeConvertibleToMap(typ reflect.Type, checkMapstructureTags bool, tagName string) bool { + for i := 0; i < typ.NumField(); i++ { + f := typ.Field(i) + if f.PkgPath == "" && !checkMapstructureTags { // check for unexported fields + return true + } + if checkMapstructureTags && f.Tag.Get(tagName) != "" { // check for mapstructure tags inside + return true + } + } + return false +} + +func dereferencePtrToStructIfNeeded(v reflect.Value, tagName string) reflect.Value { + if v.Kind() != reflect.Ptr || v.Elem().Kind() != reflect.Struct { + return v + } + deref := v.Elem() + derefT := deref.Type() + if isStructTypeConvertibleToMap(derefT, true, tagName) { + return deref + } + return v +} diff --git a/vendor/github.com/onsi/ginkgo/v2/ginkgo/generators/bootstrap_command.go b/vendor/github.com/onsi/ginkgo/v2/ginkgo/generators/bootstrap_command.go index 73aff0b7a..b2dc59be6 100644 --- a/vendor/github.com/onsi/ginkgo/v2/ginkgo/generators/bootstrap_command.go +++ b/vendor/github.com/onsi/ginkgo/v2/ginkgo/generators/bootstrap_command.go @@ -7,7 +7,7 @@ import ( "os" "text/template" - sprig "github.com/go-task/slim-sprig" + sprig "github.com/go-task/slim-sprig/v3" "github.com/onsi/ginkgo/v2/ginkgo/command" "github.com/onsi/ginkgo/v2/ginkgo/internal" "github.com/onsi/ginkgo/v2/types" diff --git a/vendor/github.com/onsi/ginkgo/v2/ginkgo/generators/generate_command.go b/vendor/github.com/onsi/ginkgo/v2/ginkgo/generators/generate_command.go index be01dec97..cf3b7cb6d 100644 --- a/vendor/github.com/onsi/ginkgo/v2/ginkgo/generators/generate_command.go +++ b/vendor/github.com/onsi/ginkgo/v2/ginkgo/generators/generate_command.go @@ -10,7 +10,7 @@ import ( "strings" "text/template" - sprig "github.com/go-task/slim-sprig" + sprig "github.com/go-task/slim-sprig/v3" "github.com/onsi/ginkgo/v2/ginkgo/command" "github.com/onsi/ginkgo/v2/ginkgo/internal" "github.com/onsi/ginkgo/v2/types" @@ -174,6 +174,7 @@ func moduleName(modRoot string) string { if err != nil { return "" } + defer modFile.Close() mod := make([]byte, 128) _, err = modFile.Read(mod) diff --git a/vendor/github.com/onsi/ginkgo/v2/ginkgo/internal/gocovmerge.go b/vendor/github.com/onsi/ginkgo/v2/ginkgo/internal/gocovmerge.go new file mode 100644 index 000000000..3c5079ff4 --- /dev/null +++ b/vendor/github.com/onsi/ginkgo/v2/ginkgo/internal/gocovmerge.go @@ -0,0 +1,129 @@ +// Copyright (c) 2015, Wade Simmons +// 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. + +// 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. + +// Package gocovmerge takes the results from multiple `go test -coverprofile` +// runs and merges them into one profile + +// this file was originally taken from the gocovmerge project +// see also: https://go.shabbyrobe.org/gocovmerge +package internal + +import ( + "fmt" + "io" + "sort" + + "golang.org/x/tools/cover" +) + +func AddCoverProfile(profiles []*cover.Profile, p *cover.Profile) []*cover.Profile { + i := sort.Search(len(profiles), func(i int) bool { return profiles[i].FileName >= p.FileName }) + if i < len(profiles) && profiles[i].FileName == p.FileName { + MergeCoverProfiles(profiles[i], p) + } else { + profiles = append(profiles, nil) + copy(profiles[i+1:], profiles[i:]) + profiles[i] = p + } + return profiles +} + +func DumpCoverProfiles(profiles []*cover.Profile, out io.Writer) error { + if len(profiles) == 0 { + return nil + } + if _, err := fmt.Fprintf(out, "mode: %s\n", profiles[0].Mode); err != nil { + return err + } + for _, p := range profiles { + for _, b := range p.Blocks { + if _, err := fmt.Fprintf(out, "%s:%d.%d,%d.%d %d %d\n", p.FileName, b.StartLine, b.StartCol, b.EndLine, b.EndCol, b.NumStmt, b.Count); err != nil { + return err + } + } + } + return nil +} + +func MergeCoverProfiles(into *cover.Profile, merge *cover.Profile) error { + if into.Mode != merge.Mode { + return fmt.Errorf("cannot merge profiles with different modes") + } + // Since the blocks are sorted, we can keep track of where the last block + // was inserted and only look at the blocks after that as targets for merge + startIndex := 0 + for _, b := range merge.Blocks { + var err error + startIndex, err = mergeProfileBlock(into, b, startIndex) + if err != nil { + return err + } + } + return nil +} + +func mergeProfileBlock(p *cover.Profile, pb cover.ProfileBlock, startIndex int) (int, error) { + sortFunc := func(i int) bool { + pi := p.Blocks[i+startIndex] + return pi.StartLine >= pb.StartLine && (pi.StartLine != pb.StartLine || pi.StartCol >= pb.StartCol) + } + + i := 0 + if sortFunc(i) != true { + i = sort.Search(len(p.Blocks)-startIndex, sortFunc) + } + + i += startIndex + if i < len(p.Blocks) && p.Blocks[i].StartLine == pb.StartLine && p.Blocks[i].StartCol == pb.StartCol { + if p.Blocks[i].EndLine != pb.EndLine || p.Blocks[i].EndCol != pb.EndCol { + return i, fmt.Errorf("gocovmerge: overlapping merge %v %v %v", p.FileName, p.Blocks[i], pb) + } + switch p.Mode { + case "set": + p.Blocks[i].Count |= pb.Count + case "count", "atomic": + p.Blocks[i].Count += pb.Count + default: + return i, fmt.Errorf("gocovmerge: unsupported covermode '%s'", p.Mode) + } + + } else { + if i > 0 { + pa := p.Blocks[i-1] + if pa.EndLine >= pb.EndLine && (pa.EndLine != pb.EndLine || pa.EndCol > pb.EndCol) { + return i, fmt.Errorf("gocovmerge: overlap before %v %v %v", p.FileName, pa, pb) + } + } + if i < len(p.Blocks)-1 { + pa := p.Blocks[i+1] + if pa.StartLine <= pb.StartLine && (pa.StartLine != pb.StartLine || pa.StartCol < pb.StartCol) { + return i, fmt.Errorf("gocovmerge: overlap after %v %v %v", p.FileName, pa, pb) + } + } + p.Blocks = append(p.Blocks, cover.ProfileBlock{}) + copy(p.Blocks[i+1:], p.Blocks[i:]) + p.Blocks[i] = pb + } + + return i + 1, nil +} diff --git a/vendor/github.com/onsi/ginkgo/v2/ginkgo/internal/profiles_and_reports.go b/vendor/github.com/onsi/ginkgo/v2/ginkgo/internal/profiles_and_reports.go index bd3c6d028..8e16d2bb0 100644 --- a/vendor/github.com/onsi/ginkgo/v2/ginkgo/internal/profiles_and_reports.go +++ b/vendor/github.com/onsi/ginkgo/v2/ginkgo/internal/profiles_and_reports.go @@ -1,7 +1,6 @@ package internal import ( - "bytes" "fmt" "os" "os/exec" @@ -12,6 +11,7 @@ import ( "github.com/google/pprof/profile" "github.com/onsi/ginkgo/v2/reporters" "github.com/onsi/ginkgo/v2/types" + "golang.org/x/tools/cover" ) func AbsPathForGeneratedAsset(assetName string, suite TestSuite, cliConfig types.CLIConfig, process int) string { @@ -144,38 +144,27 @@ func FinalizeProfilesAndReportsForSuites(suites TestSuites, cliConfig types.CLIC return messages, nil } -//loads each profile, combines them, deletes them, stores them in destination +// loads each profile, merges them, deletes them, stores them in destination func MergeAndCleanupCoverProfiles(profiles []string, destination string) error { - combined := &bytes.Buffer{} - modeRegex := regexp.MustCompile(`^mode: .*\n`) - for i, profile := range profiles { - contents, err := os.ReadFile(profile) + var merged []*cover.Profile + for _, file := range profiles { + parsedProfiles, err := cover.ParseProfiles(file) if err != nil { - return fmt.Errorf("Unable to read coverage file %s:\n%s", profile, err.Error()) + return err } - os.Remove(profile) - - // remove the cover mode line from every file - // except the first one - if i > 0 { - contents = modeRegex.ReplaceAll(contents, []byte{}) - } - - _, err = combined.Write(contents) - - // Add a newline to the end of every file if missing. - if err == nil && len(contents) > 0 && contents[len(contents)-1] != '\n' { - _, err = combined.Write([]byte("\n")) - } - - if err != nil { - return fmt.Errorf("Unable to append to coverprofile:\n%s", err.Error()) + os.Remove(file) + for _, p := range parsedProfiles { + merged = AddCoverProfile(merged, p) } } - - err := os.WriteFile(destination, combined.Bytes(), 0666) + dst, err := os.OpenFile(destination, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0666) + if err != nil { + return err + } + defer dst.Close() + err = DumpCoverProfiles(merged, dst) if err != nil { - return fmt.Errorf("Unable to create combined cover profile:\n%s", err.Error()) + return err } return nil } @@ -184,7 +173,7 @@ func GetCoverageFromCoverProfile(profile string) (float64, error) { cmd := exec.Command("go", "tool", "cover", "-func", profile) output, err := cmd.CombinedOutput() if err != nil { - return 0, fmt.Errorf("Could not process Coverprofile %s: %s", profile, err.Error()) + return 0, fmt.Errorf("Could not process Coverprofile %s: %s - %s", profile, err.Error(), string(output)) } re := regexp.MustCompile(`total:\s*\(statements\)\s*(\d*\.\d*)\%`) matches := re.FindStringSubmatch(string(output)) @@ -208,6 +197,7 @@ func MergeProfiles(profilePaths []string, destination string) error { return fmt.Errorf("Could not open profile: %s\n%s", profilePath, err.Error()) } prof, err := profile.Parse(proFile) + _ = proFile.Close() if err != nil { return fmt.Errorf("Could not parse profile: %s\n%s", profilePath, err.Error()) } diff --git a/vendor/github.com/onsi/ginkgo/v2/ginkgo/internal/test_suite.go b/vendor/github.com/onsi/ginkgo/v2/ginkgo/internal/test_suite.go index 64dcb1b78..df99875be 100644 --- a/vendor/github.com/onsi/ginkgo/v2/ginkgo/internal/test_suite.go +++ b/vendor/github.com/onsi/ginkgo/v2/ginkgo/internal/test_suite.go @@ -7,6 +7,7 @@ import ( "path" "path/filepath" "regexp" + "runtime" "strings" "github.com/onsi/ginkgo/v2/types" @@ -192,7 +193,7 @@ func precompiledTestSuite(path string) (TestSuite, error) { return TestSuite{}, errors.New("this is not a .test binary") } - if filepath.Ext(path) == ".test" && info.Mode()&0111 == 0 { + if filepath.Ext(path) == ".test" && runtime.GOOS != "windows" && info.Mode()&0111 == 0 { return TestSuite{}, errors.New("this is not executable") } @@ -225,7 +226,7 @@ func suitesInDir(dir string, recurse bool) TestSuites { files, _ := os.ReadDir(dir) re := regexp.MustCompile(`^[^._].*_test\.go$`) for _, file := range files { - if !file.IsDir() && re.Match([]byte(file.Name())) { + if !file.IsDir() && re.MatchString(file.Name()) { suite := TestSuite{ Path: relPath(dir), PackageName: packageNameForSuite(dir), @@ -240,7 +241,7 @@ func suitesInDir(dir string, recurse bool) TestSuites { if recurse { re = regexp.MustCompile(`^[._]`) for _, file := range files { - if file.IsDir() && !re.Match([]byte(file.Name())) { + if file.IsDir() && !re.MatchString(file.Name()) { suites = append(suites, suitesInDir(dir+"/"+file.Name(), recurse)...) } } @@ -271,7 +272,7 @@ func filesHaveGinkgoSuite(dir string, files []os.DirEntry) bool { reGinkgo := regexp.MustCompile(`package ginkgo|\/ginkgo"|\/ginkgo\/v2"|\/ginkgo\/v2/dsl/`) for _, file := range files { - if !file.IsDir() && reTestFile.Match([]byte(file.Name())) { + if !file.IsDir() && reTestFile.MatchString(file.Name()) { contents, _ := os.ReadFile(dir + "/" + file.Name()) if reGinkgo.Match(contents) { return true diff --git a/vendor/github.com/onsi/ginkgo/v2/ginkgo/outline/ginkgo.go b/vendor/github.com/onsi/ginkgo/v2/ginkgo/outline/ginkgo.go index 958daccbf..5d8d00bb1 100644 --- a/vendor/github.com/onsi/ginkgo/v2/ginkgo/outline/ginkgo.go +++ b/vendor/github.com/onsi/ginkgo/v2/ginkgo/outline/ginkgo.go @@ -1,10 +1,11 @@ package outline import ( - "github.com/onsi/ginkgo/v2/types" "go/ast" "go/token" "strconv" + + "github.com/onsi/ginkgo/v2/types" ) const ( diff --git a/vendor/github.com/onsi/ginkgo/v2/ginkgo/outline/import.go b/vendor/github.com/onsi/ginkgo/v2/ginkgo/outline/import.go index 67ec5ab75..f0a6b5d26 100644 --- a/vendor/github.com/onsi/ginkgo/v2/ginkgo/outline/import.go +++ b/vendor/github.com/onsi/ginkgo/v2/ginkgo/outline/import.go @@ -28,14 +28,7 @@ func packageNameForImport(f *ast.File, path string) *string { } name := spec.Name.String() if name == "" { - // If the package name is not explicitly specified, - // make an educated guess. This is not guaranteed to be correct. - lastSlash := strings.LastIndex(path, "/") - if lastSlash == -1 { - name = path - } else { - name = path[lastSlash+1:] - } + name = "ginkgo" } if name == "." { name = "" diff --git a/vendor/github.com/onsi/ginkgo/v2/ginkgo/watch/dependencies.go b/vendor/github.com/onsi/ginkgo/v2/ginkgo/watch/dependencies.go index f5ddff30f..a34d94354 100644 --- a/vendor/github.com/onsi/ginkgo/v2/ginkgo/watch/dependencies.go +++ b/vendor/github.com/onsi/ginkgo/v2/ginkgo/watch/dependencies.go @@ -78,7 +78,7 @@ func (d Dependencies) resolveAndAdd(deps []string, depth int) { if err != nil { continue } - if !pkg.Goroot && (!ginkgoAndGomegaFilter.Match([]byte(pkg.Dir)) || ginkgoIntegrationTestFilter.Match([]byte(pkg.Dir))) { + if !pkg.Goroot && (!ginkgoAndGomegaFilter.MatchString(pkg.Dir) || ginkgoIntegrationTestFilter.MatchString(pkg.Dir)) { d.addDepIfNotPresent(pkg.Dir, depth) } } diff --git a/vendor/github.com/onsi/ginkgo/v2/ginkgo/watch/package_hash.go b/vendor/github.com/onsi/ginkgo/v2/ginkgo/watch/package_hash.go index e9f7ec0cb..0e6ae1f29 100644 --- a/vendor/github.com/onsi/ginkgo/v2/ginkgo/watch/package_hash.go +++ b/vendor/github.com/onsi/ginkgo/v2/ginkgo/watch/package_hash.go @@ -4,6 +4,7 @@ import ( "fmt" "os" "regexp" + "strings" "time" ) @@ -79,7 +80,11 @@ func (p *PackageHash) computeHashes() (codeHash string, codeModifiedTime time.Ti continue } - if goTestRegExp.Match([]byte(info.Name())) { + if isHiddenFile(info) { + continue + } + + if goTestRegExp.MatchString(info.Name()) { testHash += p.hashForFileInfo(info) if info.ModTime().After(testModifiedTime) { testModifiedTime = info.ModTime() @@ -87,7 +92,7 @@ func (p *PackageHash) computeHashes() (codeHash string, codeModifiedTime time.Ti continue } - if p.watchRegExp.Match([]byte(info.Name())) { + if p.watchRegExp.MatchString(info.Name()) { codeHash += p.hashForFileInfo(info) if info.ModTime().After(codeModifiedTime) { codeModifiedTime = info.ModTime() @@ -103,6 +108,10 @@ func (p *PackageHash) computeHashes() (codeHash string, codeModifiedTime time.Ti return } +func isHiddenFile(info os.FileInfo) bool { + return strings.HasPrefix(info.Name(), ".") || strings.HasPrefix(info.Name(), "_") +} + func (p *PackageHash) hashForFileInfo(info os.FileInfo) string { return fmt.Sprintf("%s_%d_%d", info.Name(), info.Size(), info.ModTime().UnixNano()) } diff --git a/vendor/github.com/onsi/ginkgo/v2/reporters/default_reporter.go b/vendor/github.com/onsi/ginkgo/v2/reporters/default_reporter.go index 56b7be758..480730486 100644 --- a/vendor/github.com/onsi/ginkgo/v2/reporters/default_reporter.go +++ b/vendor/github.com/onsi/ginkgo/v2/reporters/default_reporter.go @@ -182,10 +182,31 @@ func (r *DefaultReporter) WillRun(report types.SpecReport) { r.emitBlock(r.f(r.codeLocationBlock(report, "{{/}}", v.Is(types.VerbosityLevelVeryVerbose), false))) } +func (r *DefaultReporter) wrapTextBlock(sectionName string, fn func()) { + r.emitBlock("\n") + if r.conf.GithubOutput { + r.emitBlock(r.fi(1, "::group::%s", sectionName)) + } else { + r.emitBlock(r.fi(1, "{{gray}}%s >>{{/}}", sectionName)) + } + fn() + if r.conf.GithubOutput { + r.emitBlock(r.fi(1, "::endgroup::")) + } else { + r.emitBlock(r.fi(1, "{{gray}}<< %s{{/}}", sectionName)) + } + +} + func (r *DefaultReporter) DidRun(report types.SpecReport) { v := r.conf.Verbosity() inParallel := report.RunningInParallel + //should we completely omit this spec? + if report.State.Is(types.SpecStateSkipped) && r.conf.SilenceSkips { + return + } + header := r.specDenoter if report.LeafNodeType.Is(types.NodeTypesForSuiteLevelNodes) { header = fmt.Sprintf("[%s]", report.LeafNodeType) @@ -262,9 +283,12 @@ func (r *DefaultReporter) DidRun(report types.SpecReport) { } } - // If we have no content to show, jsut emit the header and return + // If we have no content to show, just emit the header and return if !reportHasContent { r.emit(r.f(highlightColor + header + "{{/}}")) + if r.conf.ForceNewlines { + r.emit("\n") + } return } @@ -283,26 +307,23 @@ func (r *DefaultReporter) DidRun(report types.SpecReport) { //Emit Stdout/Stderr Output if showSeparateStdSection { - r.emitBlock("\n") - r.emitBlock(r.fi(1, "{{gray}}Captured StdOut/StdErr Output >>{{/}}")) - r.emitBlock(r.fi(1, "%s", report.CapturedStdOutErr)) - r.emitBlock(r.fi(1, "{{gray}}<< Captured StdOut/StdErr Output{{/}}")) + r.wrapTextBlock("Captured StdOut/StdErr Output", func() { + r.emitBlock(r.fi(1, "%s", report.CapturedStdOutErr)) + }) } if showSeparateVisibilityAlwaysReportsSection { - r.emitBlock("\n") - r.emitBlock(r.fi(1, "{{gray}}Report Entries >>{{/}}")) - for _, entry := range report.ReportEntries.WithVisibility(types.ReportEntryVisibilityAlways) { - r.emitReportEntry(1, entry) - } - r.emitBlock(r.fi(1, "{{gray}}<< Report Entries{{/}}")) + r.wrapTextBlock("Report Entries", func() { + for _, entry := range report.ReportEntries.WithVisibility(types.ReportEntryVisibilityAlways) { + r.emitReportEntry(1, entry) + } + }) } if showTimeline { - r.emitBlock("\n") - r.emitBlock(r.fi(1, "{{gray}}Timeline >>{{/}}")) - r.emitTimeline(1, report, timeline) - r.emitBlock(r.fi(1, "{{gray}}<< Timeline{{/}}")) + r.wrapTextBlock("Timeline", func() { + r.emitTimeline(1, report, timeline) + }) } // Emit Failure Message @@ -405,7 +426,15 @@ func (r *DefaultReporter) emitShortFailure(indent uint, state types.SpecState, f func (r *DefaultReporter) emitFailure(indent uint, state types.SpecState, failure types.Failure, includeAdditionalFailure bool) { highlightColor := r.highlightColorForState(state) r.emitBlock(r.fi(indent, highlightColor+"[%s] %s{{/}}", r.humanReadableState(state), failure.Message)) - r.emitBlock(r.fi(indent, highlightColor+"In {{bold}}[%s]{{/}}"+highlightColor+" at: {{bold}}%s{{/}} {{gray}}@ %s{{/}}\n", failure.FailureNodeType, failure.Location, failure.TimelineLocation.Time.Format(types.GINKGO_TIME_FORMAT))) + if r.conf.GithubOutput { + level := "error" + if state.Is(types.SpecStateSkipped) { + level = "notice" + } + r.emitBlock(r.fi(indent, "::%s file=%s,line=%d::%s %s", level, failure.Location.FileName, failure.Location.LineNumber, failure.FailureNodeType, failure.TimelineLocation.Time.Format(types.GINKGO_TIME_FORMAT))) + } else { + r.emitBlock(r.fi(indent, highlightColor+"In {{bold}}[%s]{{/}}"+highlightColor+" at: {{bold}}%s{{/}} {{gray}}@ %s{{/}}\n", failure.FailureNodeType, failure.Location, failure.TimelineLocation.Time.Format(types.GINKGO_TIME_FORMAT))) + } if failure.ForwardedPanic != "" { r.emitBlock("\n") r.emitBlock(r.fi(indent, highlightColor+"%s{{/}}", failure.ForwardedPanic)) diff --git a/vendor/github.com/onsi/ginkgo/v2/reporters/json_report.go b/vendor/github.com/onsi/ginkgo/v2/reporters/json_report.go index be506f9b4..5d3e8db99 100644 --- a/vendor/github.com/onsi/ginkgo/v2/reporters/json_report.go +++ b/vendor/github.com/onsi/ginkgo/v2/reporters/json_report.go @@ -18,6 +18,7 @@ func GenerateJSONReport(report types.Report, destination string) error { if err != nil { return err } + defer f.Close() enc := json.NewEncoder(f) enc.SetIndent("", " ") err = enc.Encode([]types.Report{ @@ -26,7 +27,7 @@ func GenerateJSONReport(report types.Report, destination string) error { if err != nil { return err } - return f.Close() + return nil } // MergeJSONReports produces a single JSON-formatted report at the passed in destination by merging the JSON-formatted reports provided in sources @@ -57,11 +58,12 @@ func MergeAndCleanupJSONReports(sources []string, destination string) ([]string, if err != nil { return messages, err } + defer f.Close() enc := json.NewEncoder(f) enc.SetIndent("", " ") err = enc.Encode(allReports) if err != nil { return messages, err } - return messages, f.Close() + return messages, nil } diff --git a/vendor/github.com/onsi/ginkgo/v2/reporters/junit_report.go b/vendor/github.com/onsi/ginkgo/v2/reporters/junit_report.go index 816042208..562e0f62b 100644 --- a/vendor/github.com/onsi/ginkgo/v2/reporters/junit_report.go +++ b/vendor/github.com/onsi/ginkgo/v2/reporters/junit_report.go @@ -15,6 +15,7 @@ import ( "fmt" "os" "path" + "regexp" "strings" "github.com/onsi/ginkgo/v2/config" @@ -104,6 +105,8 @@ type JUnitProperty struct { Value string `xml:"value,attr"` } +var ownerRE = regexp.MustCompile(`(?i)^owner:(.*)$`) + type JUnitTestCase struct { // Name maps onto the full text of the spec - equivalent to "[SpecReport.LeafNodeType] SpecReport.FullText()" Name string `xml:"name,attr"` @@ -113,6 +116,8 @@ type JUnitTestCase struct { Status string `xml:"status,attr"` // Time is the time in seconds to execute the spec - maps onto SpecReport.RunTime Time float64 `xml:"time,attr"` + // Owner is the owner the spec - is set if a label matching Label("owner:X") is provided. The last matching label is used as the owner, thereby allowing specs to override owners specified in container nodes. + Owner string `xml:"owner,attr,omitempty"` //Skipped is populated with a message if the test was skipped or pending Skipped *JUnitSkipped `xml:"skipped,omitempty"` //Error is populated if the test panicked or was interrupted @@ -172,6 +177,7 @@ func GenerateJUnitReportWithConfig(report types.Report, dst string, config Junit {"FocusFiles", strings.Join(report.SuiteConfig.FocusFiles, ";")}, {"SkipFiles", strings.Join(report.SuiteConfig.SkipFiles, ";")}, {"FailOnPending", fmt.Sprintf("%t", report.SuiteConfig.FailOnPending)}, + {"FailOnEmpty", fmt.Sprintf("%t", report.SuiteConfig.FailOnEmpty)}, {"FailFast", fmt.Sprintf("%t", report.SuiteConfig.FailFast)}, {"FlakeAttempts", fmt.Sprintf("%d", report.SuiteConfig.FlakeAttempts)}, {"DryRun", fmt.Sprintf("%t", report.SuiteConfig.DryRun)}, @@ -195,6 +201,12 @@ func GenerateJUnitReportWithConfig(report types.Report, dst string, config Junit if len(labels) > 0 && !config.OmitSpecLabels { name = name + " [" + strings.Join(labels, ", ") + "]" } + owner := "" + for _, label := range labels { + if matches := ownerRE.FindStringSubmatch(label); len(matches) == 2 { + owner = matches[1] + } + } name = strings.TrimSpace(name) test := JUnitTestCase{ @@ -202,6 +214,7 @@ func GenerateJUnitReportWithConfig(report types.Report, dst string, config Junit Classname: report.SuiteDescription, Status: spec.State.String(), Time: spec.RunTime.Seconds(), + Owner: owner, } if !spec.State.Is(config.OmitTimelinesForSpecState) { test.SystemErr = systemErrForUnstructuredReporters(spec) @@ -312,6 +325,7 @@ func MergeAndCleanupJUnitReports(sources []string, dst string) ([]string, error) continue } err = xml.NewDecoder(f).Decode(&report) + _ = f.Close() if err != nil { messages = append(messages, fmt.Sprintf("Could not decode %s:\n%s", source, err.Error())) continue diff --git a/vendor/github.com/onsi/ginkgo/v2/types/code_location.go b/vendor/github.com/onsi/ginkgo/v2/types/code_location.go index 9cd576817..57e87517e 100644 --- a/vendor/github.com/onsi/ginkgo/v2/types/code_location.go +++ b/vendor/github.com/onsi/ginkgo/v2/types/code_location.go @@ -149,7 +149,7 @@ func PruneStack(fullStackTrace string, skip int) string { re := regexp.MustCompile(`\/ginkgo\/|\/pkg\/testing\/|\/pkg\/runtime\/`) for i := 0; i < len(stack)/2; i++ { // We filter out based on the source code file name. - if !re.Match([]byte(stack[i*2+1])) { + if !re.MatchString(stack[i*2+1]) { prunedStack = append(prunedStack, stack[i*2]) prunedStack = append(prunedStack, stack[i*2+1]) } diff --git a/vendor/github.com/onsi/ginkgo/v2/types/config.go b/vendor/github.com/onsi/ginkgo/v2/types/config.go index c88fc85a7..66463cf5e 100644 --- a/vendor/github.com/onsi/ginkgo/v2/types/config.go +++ b/vendor/github.com/onsi/ginkgo/v2/types/config.go @@ -25,6 +25,7 @@ type SuiteConfig struct { SkipFiles []string LabelFilter string FailOnPending bool + FailOnEmpty bool FailFast bool FlakeAttempts int MustPassRepeatedly int @@ -89,6 +90,9 @@ type ReporterConfig struct { VeryVerbose bool FullTrace bool ShowNodeEvents bool + GithubOutput bool + SilenceSkips bool + ForceNewlines bool JSONReport string JUnitReport string @@ -264,7 +268,7 @@ var FlagSections = GinkgoFlagSections{ // SuiteConfigFlags provides flags for the Ginkgo test process, and CLI var SuiteConfigFlags = GinkgoFlags{ {KeyPath: "S.RandomSeed", Name: "seed", SectionKey: "order", UsageDefaultValue: "randomly generated by Ginkgo", - Usage: "The seed used to randomize the spec suite."}, + Usage: "The seed used to randomize the spec suite.", AlwaysExport: true}, {KeyPath: "S.RandomizeAllSpecs", Name: "randomize-all", SectionKey: "order", DeprecatedName: "randomizeAllSpecs", DeprecatedDocLink: "changed-command-line-flags", Usage: "If set, ginkgo will randomize all specs together. By default, ginkgo only randomizes the top level Describe, Context and When containers."}, @@ -274,6 +278,8 @@ var SuiteConfigFlags = GinkgoFlags{ Usage: "If set, ginkgo will stop running a test suite after a failure occurs."}, {KeyPath: "S.FlakeAttempts", Name: "flake-attempts", SectionKey: "failure", UsageDefaultValue: "0 - failed tests are not retried", DeprecatedName: "flakeAttempts", DeprecatedDocLink: "changed-command-line-flags", Usage: "Make up to this many attempts to run each spec. If any of the attempts succeed, the suite will not be failed."}, + {KeyPath: "S.FailOnEmpty", Name: "fail-on-empty", SectionKey: "failure", + Usage: "If set, ginkgo will mark the test suite as failed if no specs are run."}, {KeyPath: "S.DryRun", Name: "dry-run", SectionKey: "debug", DeprecatedName: "dryRun", DeprecatedDocLink: "changed-command-line-flags", Usage: "If set, ginkgo will walk the test hierarchy without actually running anything. Best paired with -v."}, @@ -331,6 +337,12 @@ var ReporterConfigFlags = GinkgoFlags{ Usage: "If set, default reporter prints out the full stack trace when a failure occurs"}, {KeyPath: "R.ShowNodeEvents", Name: "show-node-events", SectionKey: "output", Usage: "If set, default reporter prints node > Enter and < Exit events when specs fail"}, + {KeyPath: "R.GithubOutput", Name: "github-output", SectionKey: "output", + Usage: "If set, default reporter prints easier to manage output in Github Actions."}, + {KeyPath: "R.SilenceSkips", Name: "silence-skips", SectionKey: "output", + Usage: "If set, default reporter will not print out skipped tests."}, + {KeyPath: "R.ForceNewlines", Name: "force-newlines", SectionKey: "output", + Usage: "If set, default reporter will ensure a newline appears after each test."}, {KeyPath: "R.JSONReport", Name: "json-report", UsageArgument: "filename.json", SectionKey: "output", Usage: "If set, Ginkgo will generate a JSON-formatted test report at the specified location."}, diff --git a/vendor/github.com/onsi/ginkgo/v2/types/errors.go b/vendor/github.com/onsi/ginkgo/v2/types/errors.go index 4fbdc3e9b..6bb72d00c 100644 --- a/vendor/github.com/onsi/ginkgo/v2/types/errors.go +++ b/vendor/github.com/onsi/ginkgo/v2/types/errors.go @@ -505,6 +505,15 @@ func (g ginkgoErrors) IncorrectVariadicParameterTypeToTableFunction(expected, ac } } +func (g ginkgoErrors) ContextsCannotBeUsedInSubtreeTables(cl CodeLocation) error { + return GinkgoError{ + Heading: "Contexts cannot be used in subtree tables", + Message: "You''ve defined a subtree body function that accepts a context but did not provide one in the table entry. Ginkgo SpecContexts can only be passed in to subject and setup nodes - so if you are trying to implement a spec timeout you should request a context in the It function within your subtree body function, not in the subtree body function itself.", + CodeLocation: cl, + DocLink: "table-specs", + } +} + /* Parallel Synchronization errors */ func (g ginkgoErrors) AggregatedReportUnavailableDueToNodeDisappearing() error { diff --git a/vendor/github.com/onsi/ginkgo/v2/types/flags.go b/vendor/github.com/onsi/ginkgo/v2/types/flags.go index 9186ae873..de69f3022 100644 --- a/vendor/github.com/onsi/ginkgo/v2/types/flags.go +++ b/vendor/github.com/onsi/ginkgo/v2/types/flags.go @@ -24,7 +24,8 @@ type GinkgoFlag struct { DeprecatedDocLink string DeprecatedVersion string - ExportAs string + ExportAs string + AlwaysExport bool } type GinkgoFlags []GinkgoFlag @@ -431,7 +432,7 @@ func (ssv stringSliceVar) Set(s string) error { return nil } -//given a set of GinkgoFlags and bindings, generate flag arguments suitable to be passed to an application with that set of flags configured. +// given a set of GinkgoFlags and bindings, generate flag arguments suitable to be passed to an application with that set of flags configured. func GenerateFlagArgs(flags GinkgoFlags, bindings interface{}) ([]string, error) { result := []string{} for _, flag := range flags { @@ -451,19 +452,19 @@ func GenerateFlagArgs(flags GinkgoFlags, bindings interface{}) ([]string, error) iface := value.Interface() switch value.Type() { case reflect.TypeOf(string("")): - if iface.(string) != "" { + if iface.(string) != "" || flag.AlwaysExport { result = append(result, fmt.Sprintf("--%s=%s", name, iface)) } case reflect.TypeOf(int64(0)): - if iface.(int64) != 0 { + if iface.(int64) != 0 || flag.AlwaysExport { result = append(result, fmt.Sprintf("--%s=%d", name, iface)) } case reflect.TypeOf(float64(0)): - if iface.(float64) != 0 { + if iface.(float64) != 0 || flag.AlwaysExport { result = append(result, fmt.Sprintf("--%s=%f", name, iface)) } case reflect.TypeOf(int(0)): - if iface.(int) != 0 { + if iface.(int) != 0 || flag.AlwaysExport { result = append(result, fmt.Sprintf("--%s=%d", name, iface)) } case reflect.TypeOf(bool(true)): @@ -471,7 +472,7 @@ func GenerateFlagArgs(flags GinkgoFlags, bindings interface{}) ([]string, error) result = append(result, fmt.Sprintf("--%s", name)) } case reflect.TypeOf(time.Duration(0)): - if iface.(time.Duration) != time.Duration(0) { + if iface.(time.Duration) != time.Duration(0) || flag.AlwaysExport { result = append(result, fmt.Sprintf("--%s=%s", name, iface)) } diff --git a/vendor/github.com/onsi/ginkgo/v2/types/label_filter.go b/vendor/github.com/onsi/ginkgo/v2/types/label_filter.go index b0d3b651e..7fdc8aa23 100644 --- a/vendor/github.com/onsi/ginkgo/v2/types/label_filter.go +++ b/vendor/github.com/onsi/ginkgo/v2/types/label_filter.go @@ -45,6 +45,83 @@ func orAction(a, b LabelFilter) LabelFilter { return func(labels []string) bool { return a(labels) || b(labels) } } +func labelSetFor(key string, labels []string) map[string]bool { + key = strings.ToLower(strings.TrimSpace(key)) + out := map[string]bool{} + for _, label := range labels { + components := strings.SplitN(label, ":", 2) + if len(components) < 2 { + continue + } + if key == strings.ToLower(strings.TrimSpace(components[0])) { + out[strings.ToLower(strings.TrimSpace(components[1]))] = true + } + } + + return out +} + +func isEmptyLabelSetAction(key string) LabelFilter { + return func(labels []string) bool { + return len(labelSetFor(key, labels)) == 0 + } +} + +func containsAnyLabelSetAction(key string, expectedValues []string) LabelFilter { + return func(labels []string) bool { + set := labelSetFor(key, labels) + for _, value := range expectedValues { + if set[value] { + return true + } + } + return false + } +} + +func containsAllLabelSetAction(key string, expectedValues []string) LabelFilter { + return func(labels []string) bool { + set := labelSetFor(key, labels) + for _, value := range expectedValues { + if !set[value] { + return false + } + } + return true + } +} + +func consistsOfLabelSetAction(key string, expectedValues []string) LabelFilter { + return func(labels []string) bool { + set := labelSetFor(key, labels) + if len(set) != len(expectedValues) { + return false + } + for _, value := range expectedValues { + if !set[value] { + return false + } + } + return true + } +} + +func isSubsetOfLabelSetAction(key string, expectedValues []string) LabelFilter { + expectedSet := map[string]bool{} + for _, value := range expectedValues { + expectedSet[value] = true + } + return func(labels []string) bool { + set := labelSetFor(key, labels) + for value := range set { + if !expectedSet[value] { + return false + } + } + return true + } +} + type lfToken uint const ( @@ -58,6 +135,9 @@ const ( lfTokenOr lfTokenRegexp lfTokenLabel + lfTokenSetKey + lfTokenSetOperation + lfTokenSetArgument lfTokenEOF ) @@ -71,6 +151,8 @@ func (l lfToken) Precedence() int { return 2 case lfTokenNot: return 3 + case lfTokenSetOperation: + return 4 } return -1 } @@ -93,6 +175,12 @@ func (l lfToken) String() string { return "/regexp/" case lfTokenLabel: return "label" + case lfTokenSetKey: + return "set_key" + case lfTokenSetOperation: + return "set_operation" + case lfTokenSetArgument: + return "set_argument" case lfTokenEOF: return "EOF" } @@ -148,6 +236,35 @@ func (tn *treeNode) constructLabelFilter(input string) (LabelFilter, error) { return nil, GinkgoErrors.SyntaxErrorParsingLabelFilter(input, tn.location, fmt.Sprintf("RegExp compilation error: %s", err)) } return matchLabelRegexAction(re), nil + case lfTokenSetOperation: + tokenSetOperation := strings.ToLower(tn.value) + if tokenSetOperation == "isempty" { + return isEmptyLabelSetAction(tn.leftNode.value), nil + } + if tn.rightNode == nil { + return nil, GinkgoErrors.SyntaxErrorParsingLabelFilter(input, tn.location, fmt.Sprintf("Set operation '%s' is missing an argument.", tn.value)) + } + + rawValues := strings.Split(tn.rightNode.value, ",") + values := make([]string, len(rawValues)) + for i := range rawValues { + values[i] = strings.ToLower(strings.TrimSpace(rawValues[i])) + if strings.ContainsAny(values[i], "&|!,()/") { + return nil, GinkgoErrors.SyntaxErrorParsingLabelFilter(input, tn.rightNode.location, fmt.Sprintf("Invalid label value '%s' in set operation argument.", values[i])) + } else if values[i] == "" { + return nil, GinkgoErrors.SyntaxErrorParsingLabelFilter(input, tn.rightNode.location, "Empty label value in set operation argument.") + } + } + switch tokenSetOperation { + case "containsany": + return containsAnyLabelSetAction(tn.leftNode.value, values), nil + case "containsall": + return containsAllLabelSetAction(tn.leftNode.value, values), nil + case "consistsof": + return consistsOfLabelSetAction(tn.leftNode.value, values), nil + case "issubsetof": + return isSubsetOfLabelSetAction(tn.leftNode.value, values), nil + } } if tn.rightNode == nil { @@ -203,7 +320,17 @@ func (tn *treeNode) toString(indent int) string { return out } +var validSetOperations = map[string]string{ + "containsany": "containsAny", + "containsall": "containsAll", + "consistsof": "consistsOf", + "issubsetof": "isSubsetOf", + "isempty": "isEmpty", +} + func tokenize(input string) func() (*treeNode, error) { + lastToken := lfTokenInvalid + lastValue := "" runes, i := []rune(input), 0 peekIs := func(r rune) bool { @@ -233,6 +360,53 @@ func tokenize(input string) func() (*treeNode, error) { } node := &treeNode{location: i} + defer func() { + lastToken = node.token + lastValue = node.value + }() + + if lastToken == lfTokenSetKey { + //we should get a valid set operation next + value, n := consumeUntil(" )") + if validSetOperations[strings.ToLower(value)] == "" { + return &treeNode{}, GinkgoErrors.SyntaxErrorParsingLabelFilter(input, i, fmt.Sprintf("Invalid set operation '%s'.", value)) + } + i += n + node.token, node.value = lfTokenSetOperation, value + return node, nil + } + if lastToken == lfTokenSetOperation { + //we should get an argument next, if we aren't isempty + var arg = "" + origI := i + if runes[i] == '{' { + i += 1 + value, n := consumeUntil("}") + if i+n >= len(runes) { + return &treeNode{}, GinkgoErrors.SyntaxErrorParsingLabelFilter(input, i-1, "Missing closing '}' in set operation argument?") + } + i += n + 1 + arg = value + } else { + value, n := consumeUntil("&|!,()/") + i += n + arg = strings.TrimSpace(value) + } + if strings.ToLower(lastValue) == "isempty" && arg != "" { + return &treeNode{}, GinkgoErrors.SyntaxErrorParsingLabelFilter(input, origI, fmt.Sprintf("isEmpty does not take arguments, was passed '%s'.", arg)) + } + if arg == "" && strings.ToLower(lastValue) != "isempty" { + if i < len(runes) && runes[i] == '/' { + return &treeNode{}, GinkgoErrors.SyntaxErrorParsingLabelFilter(input, origI, "Set operations do not support regular expressions.") + } else { + return &treeNode{}, GinkgoErrors.SyntaxErrorParsingLabelFilter(input, origI, fmt.Sprintf("Set operation '%s' requires an argument.", lastValue)) + } + } + // note that we sent an empty SetArgument token if we are isempty + node.token, node.value = lfTokenSetArgument, arg + return node, nil + } + switch runes[i] { case '&': if !peekIs('&') { @@ -264,8 +438,38 @@ func tokenize(input string) func() (*treeNode, error) { i += n + 1 node.token, node.value = lfTokenRegexp, value default: - value, n := consumeUntil("&|!,()/") + value, n := consumeUntil("&|!,()/:") i += n + value = strings.TrimSpace(value) + + //are we the beginning of a set operation? + if i < len(runes) && runes[i] == ':' { + if peekIs(' ') { + if value == "" { + return &treeNode{}, GinkgoErrors.SyntaxErrorParsingLabelFilter(input, i, "Missing set key.") + } + i += 1 + //we are the beginning of a set operation + node.token, node.value = lfTokenSetKey, value + return node, nil + } + additionalValue, n := consumeUntil("&|!,()/") + additionalValue = strings.TrimSpace(additionalValue) + if additionalValue == ":" { + return &treeNode{}, GinkgoErrors.SyntaxErrorParsingLabelFilter(input, i, "Missing set operation.") + } + i += n + value += additionalValue + } + + valueToCheckForSetOperation := strings.ToLower(value) + for setOperation := range validSetOperations { + idx := strings.Index(valueToCheckForSetOperation, " "+setOperation) + if idx > 0 { + return &treeNode{}, GinkgoErrors.SyntaxErrorParsingLabelFilter(input, i-n+idx+1, fmt.Sprintf("Looks like you are using the set operator '%s' but did not provide a set key. Did you forget the ':'?", validSetOperations[setOperation])) + } + } + node.token, node.value = lfTokenLabel, strings.TrimSpace(value) } return node, nil @@ -307,7 +511,7 @@ LOOP: switch node.token { case lfTokenEOF: break LOOP - case lfTokenLabel, lfTokenRegexp: + case lfTokenLabel, lfTokenRegexp, lfTokenSetKey: if current.rightNode != nil { return nil, GinkgoErrors.SyntaxErrorParsingLabelFilter(input, node.location, "Found two adjacent labels. You need an operator between them.") } @@ -326,6 +530,18 @@ LOOP: node.setLeftNode(nodeToStealFrom.rightNode) nodeToStealFrom.setRightNode(node) current = node + case lfTokenSetOperation: + if current.rightNode == nil { + return nil, GinkgoErrors.SyntaxErrorParsingLabelFilter(input, node.location, fmt.Sprintf("Set operation '%s' missing left hand operand.", node.value)) + } + node.setLeftNode(current.rightNode) + current.setRightNode(node) + current = node + case lfTokenSetArgument: + if current.rightNode != nil { + return nil, GinkgoErrors.SyntaxErrorParsingLabelFilter(input, node.location, fmt.Sprintf("Unexpected set argument '%s'.", node.token)) + } + current.setRightNode(node) case lfTokenCloseGroup: firstUnmatchedOpenNode := current.firstUnmatchedOpenNode() if firstUnmatchedOpenNode == nil { @@ -354,5 +570,14 @@ func ValidateAndCleanupLabel(label string, cl CodeLocation) (string, error) { if strings.ContainsAny(out, "&|!,()/") { return "", GinkgoErrors.InvalidLabel(label, cl) } + if out[0] == ':' { + return "", GinkgoErrors.InvalidLabel(label, cl) + } + if strings.Contains(out, ":") { + components := strings.SplitN(out, ":", 2) + if len(components) < 2 || components[1] == "" { + return "", GinkgoErrors.InvalidLabel(label, cl) + } + } return out, nil } diff --git a/vendor/github.com/onsi/ginkgo/v2/types/version.go b/vendor/github.com/onsi/ginkgo/v2/types/version.go index a37f30828..acab03492 100644 --- a/vendor/github.com/onsi/ginkgo/v2/types/version.go +++ b/vendor/github.com/onsi/ginkgo/v2/types/version.go @@ -1,3 +1,3 @@ package types -const VERSION = "2.13.0" +const VERSION = "2.19.0" diff --git a/vendor/github.com/onsi/gomega/CHANGELOG.md b/vendor/github.com/onsi/gomega/CHANGELOG.md index 1526497b9..62af14ad2 100644 --- a/vendor/github.com/onsi/gomega/CHANGELOG.md +++ b/vendor/github.com/onsi/gomega/CHANGELOG.md @@ -1,3 +1,98 @@ +## 1.33.1 + +### Fixes +- fix confusing eventually docs [3a66379] + +### Maintenance +- Bump github.com/onsi/ginkgo/v2 from 2.17.1 to 2.17.2 [e9bc35a] + +## 1.33.0 + +### Features + +`Receive` not accepts `Receive(, MATCHER>)`, allowing you to pick out a specific value on the channel that satisfies the provided matcher and is stored in the provided pointer. + +### Maintenance +- Bump github.com/onsi/ginkgo/v2 from 2.15.0 to 2.17.1 (#745) [9999deb] +- Bump github-pages from 229 to 230 in /docs (#735) [cb5ff21] +- Bump golang.org/x/net from 0.20.0 to 0.23.0 (#746) [bac6596] + +## 1.32.0 + +### Maintenance +- Migrate github.com/golang/protobuf to google.golang.org/protobuf [436a197] + + This release drops the deprecated github.com/golang/protobuf and adopts google.golang.org/protobuf. Care was taken to ensure the release is backwards compatible (thanks @jbduncan !). Please open an issue if you run into one. + +- chore: test with Go 1.22 (#733) [32ef35e] +- Bump golang.org/x/net from 0.19.0 to 0.20.0 (#717) [a0d0387] +- Bump github-pages and jekyll-feed in /docs (#732) [b71e477] +- docs: fix typo and broken anchor link to gstruct [f460154] +- docs: fix HaveEach matcher signature [a2862e4] + +## 1.31.1 + +### Fixes +- Inverted arguments order of FailureMessage of BeComparableToMatcher [e0dd999] +- Update test in case keeping msg is desired [ad1a367] + +### Maintenance +- Show how to import the format sub package [24e958d] +- tidy up go.sum [26661b8] +- bump dependencies [bde8f7a] + +## 1.31.0 + +### Features +- Async assertions include context cancellation cause if present [121c37f] + +### Maintenance +- Bump minimum go version [dee1e3c] +- docs: fix typo in example usage "occured" -> "occurred" [49005fe] +- Bump actions/setup-go from 4 to 5 (#714) [f1c8757] +- Bump github/codeql-action from 2 to 3 (#715) [9836e76] +- Bump github.com/onsi/ginkgo/v2 from 2.13.0 to 2.13.2 (#713) [54726f0] +- Bump golang.org/x/net from 0.17.0 to 0.19.0 (#711) [df97ecc] +- docs: fix `HaveExactElement` typo (#712) [a672c86] + +## 1.30.0 + +### Features +- BeTrueBecause and BeFalseBecause allow for better failure messages [4da4c7f] + +### Maintenance +- Bump actions/checkout from 3 to 4 (#694) [6ca6e97] +- doc: fix type on gleak go doc [f1b8343] + +## 1.29.0 + +### Features +- MatchError can now take an optional func(error) bool + description [2b39142] + +## 1.28.1 + +### Maintenance +- Bump github.com/onsi/ginkgo/v2 from 2.12.0 to 2.13.0 [635d196] +- Bump github.com/google/go-cmp from 0.5.9 to 0.6.0 [14f8859] +- Bump golang.org/x/net from 0.14.0 to 0.17.0 [d8a6508] +- #703 doc(matchers): HaveEach() doc comment updated [2705bdb] +- Minor typos (#699) [375648c] + +## 1.28.0 + +### Features +- Add VerifyHost handler to ghttp (#698) [0b03b36] + +### Fixes +- Read Body for Newer Responses in HaveHTTPBodyMatcher (#686) [18d6673] + +### Maintenance +- Bump github.com/onsi/ginkgo/v2 from 2.11.0 to 2.12.0 (#693) [55a33f3] +- Typo in matchers.go (#691) [de68e8f] +- Bump commonmarker from 0.23.9 to 0.23.10 in /docs (#690) [ab17f5e] +- chore: update test matrix for Go 1.21 (#689) [5069017] +- Bump golang.org/x/net from 0.12.0 to 0.14.0 (#688) [babe25f] + ## 1.27.10 ### Fixes diff --git a/vendor/github.com/onsi/gomega/gomega_dsl.go b/vendor/github.com/onsi/gomega/gomega_dsl.go index 1fd1803ac..9697d5134 100644 --- a/vendor/github.com/onsi/gomega/gomega_dsl.go +++ b/vendor/github.com/onsi/gomega/gomega_dsl.go @@ -22,7 +22,7 @@ import ( "github.com/onsi/gomega/types" ) -const GOMEGA_VERSION = "1.27.10" +const GOMEGA_VERSION = "1.33.1" const nilGomegaPanic = `You are trying to make an assertion, but haven't registered Gomega's fail handler. If you're using Ginkgo then you probably forgot to put your assertion in an It(). @@ -242,7 +242,7 @@ func ExpectWithOffset(offset int, actual interface{}, extra ...interface{}) Asse Eventually enables making assertions on asynchronous behavior. Eventually checks that an assertion *eventually* passes. Eventually blocks when called and attempts an assertion periodically until it passes or a timeout occurs. Both the timeout and polling interval are configurable as optional arguments. -The first optional argument is the timeout (which defaults to 1s), the second is the polling interval (which defaults to 10ms). Both intervals can be specified as time.Duration, parsable duration strings or floats/integers (in which case they are interpreted as seconds). In addition an optional context.Context can be passed in - Eventually will keep trying until either the timeout epxires or the context is cancelled, whichever comes first. +The first optional argument is the timeout (which defaults to 1s), the second is the polling interval (which defaults to 10ms). Both intervals can be specified as time.Duration, parsable duration strings or floats/integers (in which case they are interpreted as seconds). In addition an optional context.Context can be passed in - Eventually will keep trying until either the timeout expires or the context is cancelled, whichever comes first. Eventually works with any Gomega compatible matcher and supports making assertions against three categories of actual value: @@ -313,13 +313,13 @@ It is important to note that the function passed into Eventually is invoked *syn }).Should(BeNumerically(">=", 17)) }, SpecTimeout(time.Second)) -you an also use Eventually().WithContext(ctx) to pass in the context. Passed-in contexts play nicely with paseed-in arguments as long as the context appears first. You can rewrite the above example as: +you an also use Eventually().WithContext(ctx) to pass in the context. Passed-in contexts play nicely with passed-in arguments as long as the context appears first. You can rewrite the above example as: It("fetches the correct count", func(ctx SpecContext) { Eventually(client.FetchCount).WithContext(ctx).WithArguments("/users").Should(BeNumerically(">=", 17)) }, SpecTimeout(time.Second)) -Either way the context passd to Eventually is also passed to the underlying funciton. Now, when Ginkgo cancels the context both the FetchCount client and Gomega will be informed and can exit. +Either way the context passd to Eventually is also passed to the underlying function. Now, when Ginkgo cancels the context both the FetchCount client and Gomega will be informed and can exit. **Category 3: Making assertions _in_ the function passed into Eventually** @@ -349,7 +349,7 @@ For example: will rerun the function until all assertions pass. -You can also pass additional arugments to functions that take a Gomega. The only rule is that the Gomega argument must be first. If you also want to pass the context attached to Eventually you must ensure that is the second argument. For example: +You can also pass additional arguments to functions that take a Gomega. The only rule is that the Gomega argument must be first. If you also want to pass the context attached to Eventually you must ensure that is the second argument. For example: Eventually(func(g Gomega, ctx context.Context, path string, expected ...string){ tok, err := client.GetToken(ctx) @@ -372,11 +372,11 @@ You can ensure that you get a number of consecutive successful tries before succ Finally, in addition to passing timeouts and a context to Eventually you can be more explicit with Eventually's chaining configuration methods: - Eventually(..., "1s", "2s", ctx).Should(...) + Eventually(..., "10s", "2s", ctx).Should(...) is equivalent to - Eventually(...).WithTimeout(time.Second).WithPolling(2*time.Second).WithContext(ctx).Should(...) + Eventually(...).WithTimeout(10*time.Second).WithPolling(2*time.Second).WithContext(ctx).Should(...) */ func Eventually(actualOrCtx interface{}, args ...interface{}) AsyncAssertion { ensureDefaultGomegaIsConfigured() diff --git a/vendor/github.com/onsi/gomega/internal/async_assertion.go b/vendor/github.com/onsi/gomega/internal/async_assertion.go index 1188b0bce..cde9e2ec8 100644 --- a/vendor/github.com/onsi/gomega/internal/async_assertion.go +++ b/vendor/github.com/onsi/gomega/internal/async_assertion.go @@ -553,7 +553,12 @@ func (assertion *AsyncAssertion) match(matcher types.GomegaMatcher, desiredMatch lock.Unlock() } case <-contextDone: - fail("Context was cancelled") + err := context.Cause(assertion.ctx) + if err != nil && err != context.Canceled { + fail(fmt.Sprintf("Context was cancelled (cause: %s)", err)) + } else { + fail("Context was cancelled") + } return false case <-timeout: if assertion.asyncType == AsyncAssertionTypeEventually { diff --git a/vendor/github.com/onsi/gomega/matchers.go b/vendor/github.com/onsi/gomega/matchers.go index bdaf62b56..7ef27dc9c 100644 --- a/vendor/github.com/onsi/gomega/matchers.go +++ b/vendor/github.com/onsi/gomega/matchers.go @@ -1,6 +1,7 @@ package gomega import ( + "fmt" "time" "github.com/google/go-cmp/cmp" @@ -52,15 +53,31 @@ func BeNil() types.GomegaMatcher { } // BeTrue succeeds if actual is true +// +// In general, it's better to use `BeTrueBecause(reason)` to provide a more useful error message if a true check fails. func BeTrue() types.GomegaMatcher { return &matchers.BeTrueMatcher{} } // BeFalse succeeds if actual is false +// +// In general, it's better to use `BeFalseBecause(reason)` to provide a more useful error message if a false check fails. func BeFalse() types.GomegaMatcher { return &matchers.BeFalseMatcher{} } +// BeTrueBecause succeeds if actual is true and displays the provided reason if it is false +// fmt.Sprintf is used to render the reason +func BeTrueBecause(format string, args ...any) types.GomegaMatcher { + return &matchers.BeTrueMatcher{Reason: fmt.Sprintf(format, args...)} +} + +// BeFalseBecause succeeds if actual is false and displays the provided reason if it is true. +// fmt.Sprintf is used to render the reason +func BeFalseBecause(format string, args ...any) types.GomegaMatcher { + return &matchers.BeFalseMatcher{Reason: fmt.Sprintf(format, args...)} +} + // HaveOccurred succeeds if actual is a non-nil error // The typical Go error checking pattern looks like: // @@ -88,19 +105,44 @@ func Succeed() types.GomegaMatcher { } // MatchError succeeds if actual is a non-nil error that matches the passed in -// string, error, or matcher. +// string, error, function, or matcher. // // These are valid use-cases: // -// Expect(err).Should(MatchError("an error")) //asserts that err.Error() == "an error" -// Expect(err).Should(MatchError(SomeError)) //asserts that err == SomeError (via reflect.DeepEqual) -// Expect(err).Should(MatchError(ContainSubstring("sprocket not found"))) // asserts that edrr.Error() contains substring "sprocket not found" +// When passed a string: +// +// Expect(err).To(MatchError("an error")) +// +// asserts that err.Error() == "an error" +// +// When passed an error: +// +// Expect(err).To(MatchError(SomeError)) +// +// First checks if errors.Is(err, SomeError). +// If that fails then it checks if reflect.DeepEqual(err, SomeError) repeatedly for err and any errors wrapped by err +// +// When passed a matcher: +// +// Expect(err).To(MatchError(ContainSubstring("sprocket not found"))) +// +// the matcher is passed err.Error(). In this case it asserts that err.Error() contains substring "sprocket not found" +// +// When passed a func(err) bool and a description: +// +// Expect(err).To(MatchError(os.IsNotExist, "IsNotExist")) +// +// the function is passed err and matches if the return value is true. The description is required to allow Gomega +// to print a useful error message. // // It is an error for err to be nil or an object that does not implement the // Error interface -func MatchError(expected interface{}) types.GomegaMatcher { +// +// The optional second argument is a description of the error function, if used. This is required when passing a function but is ignored in all other cases. +func MatchError(expected interface{}, functionErrorDescription ...any) types.GomegaMatcher { return &matchers.MatchErrorMatcher{ - Expected: expected, + Expected: expected, + FuncErrDescription: functionErrorDescription, } } @@ -152,20 +194,21 @@ func BeClosed() types.GomegaMatcher { // // will repeatedly attempt to pull values out of `c` until a value matching "bar" is received. // -// Finally, if you want to have a reference to the value *sent* to the channel you can pass the `Receive` matcher a pointer to a variable of the appropriate type: +// Furthermore, if you want to have a reference to the value *sent* to the channel you can pass the `Receive` matcher a pointer to a variable of the appropriate type: // // var myThing thing // Eventually(thingChan).Should(Receive(&myThing)) // Expect(myThing.Sprocket).Should(Equal("foo")) // Expect(myThing.IsValid()).Should(BeTrue()) +// +// Finally, if you want to match the received object as well as get the actual received value into a variable, so you can reason further about the value received, +// you can pass a pointer to a variable of the approriate type first, and second a matcher: +// +// var myThing thing +// Eventually(thingChan).Should(Receive(&myThing, ContainSubstring("bar"))) func Receive(args ...interface{}) types.GomegaMatcher { - var arg interface{} - if len(args) > 0 { - arg = args[0] - } - return &matchers.ReceiveMatcher{ - Arg: arg, + Args: args, } } @@ -352,7 +395,7 @@ func ConsistOf(elements ...interface{}) types.GomegaMatcher { } } -// HaveExactElemets succeeds if actual contains elements that precisely match the elemets passed into the matcher. The ordering of the elements does matter. +// HaveExactElements succeeds if actual contains elements that precisely match the elemets passed into the matcher. The ordering of the elements does matter. // By default HaveExactElements() uses Equal() to match the elements, however custom matchers can be passed in instead. Here are some examples: // // Expect([]string{"Foo", "FooBar"}).Should(HaveExactElements("Foo", "FooBar")) @@ -381,7 +424,7 @@ func ContainElements(elements ...interface{}) types.GomegaMatcher { } // HaveEach succeeds if actual solely contains elements that match the passed in element. -// Please note that if actual is empty, HaveEach always will succeed. +// Please note that if actual is empty, HaveEach always will fail. // By default HaveEach() uses Equal() to perform the match, however a // matcher can be passed in instead: // diff --git a/vendor/github.com/onsi/gomega/matchers/be_comparable_to_matcher.go b/vendor/github.com/onsi/gomega/matchers/be_comparable_to_matcher.go index 8ab4bb919..4e3897858 100644 --- a/vendor/github.com/onsi/gomega/matchers/be_comparable_to_matcher.go +++ b/vendor/github.com/onsi/gomega/matchers/be_comparable_to_matcher.go @@ -41,9 +41,9 @@ func (matcher *BeComparableToMatcher) Match(actual interface{}) (success bool, m } func (matcher *BeComparableToMatcher) FailureMessage(actual interface{}) (message string) { - return cmp.Diff(matcher.Expected, actual, matcher.Options) + return fmt.Sprint("Expected object to be comparable, diff: ", cmp.Diff(actual, matcher.Expected, matcher.Options...)) } func (matcher *BeComparableToMatcher) NegatedFailureMessage(actual interface{}) (message string) { - return format.Message(actual, "not to equal", matcher.Expected) + return format.Message(actual, "not to be comparable to", matcher.Expected) } diff --git a/vendor/github.com/onsi/gomega/matchers/be_false_matcher.go b/vendor/github.com/onsi/gomega/matchers/be_false_matcher.go index e326c0157..8ee2b1c51 100644 --- a/vendor/github.com/onsi/gomega/matchers/be_false_matcher.go +++ b/vendor/github.com/onsi/gomega/matchers/be_false_matcher.go @@ -9,6 +9,7 @@ import ( ) type BeFalseMatcher struct { + Reason string } func (matcher *BeFalseMatcher) Match(actual interface{}) (success bool, err error) { @@ -20,9 +21,17 @@ func (matcher *BeFalseMatcher) Match(actual interface{}) (success bool, err erro } func (matcher *BeFalseMatcher) FailureMessage(actual interface{}) (message string) { - return format.Message(actual, "to be false") + if matcher.Reason == "" { + return format.Message(actual, "to be false") + } else { + return matcher.Reason + } } func (matcher *BeFalseMatcher) NegatedFailureMessage(actual interface{}) (message string) { - return format.Message(actual, "not to be false") + if matcher.Reason == "" { + return format.Message(actual, "not to be false") + } else { + return fmt.Sprintf(`Expected not false but got false\nNegation of "%s" failed`, matcher.Reason) + } } diff --git a/vendor/github.com/onsi/gomega/matchers/be_true_matcher.go b/vendor/github.com/onsi/gomega/matchers/be_true_matcher.go index 60bc1e3fa..3576aac88 100644 --- a/vendor/github.com/onsi/gomega/matchers/be_true_matcher.go +++ b/vendor/github.com/onsi/gomega/matchers/be_true_matcher.go @@ -9,6 +9,7 @@ import ( ) type BeTrueMatcher struct { + Reason string } func (matcher *BeTrueMatcher) Match(actual interface{}) (success bool, err error) { @@ -20,9 +21,17 @@ func (matcher *BeTrueMatcher) Match(actual interface{}) (success bool, err error } func (matcher *BeTrueMatcher) FailureMessage(actual interface{}) (message string) { - return format.Message(actual, "to be true") + if matcher.Reason == "" { + return format.Message(actual, "to be true") + } else { + return matcher.Reason + } } func (matcher *BeTrueMatcher) NegatedFailureMessage(actual interface{}) (message string) { - return format.Message(actual, "not to be true") + if matcher.Reason == "" { + return format.Message(actual, "not to be true") + } else { + return fmt.Sprintf(`Expected not true but got true\nNegation of "%s" failed`, matcher.Reason) + } } diff --git a/vendor/github.com/onsi/gomega/matchers/have_http_body_matcher.go b/vendor/github.com/onsi/gomega/matchers/have_http_body_matcher.go index 6a3dcdc35..d14d9e5fc 100644 --- a/vendor/github.com/onsi/gomega/matchers/have_http_body_matcher.go +++ b/vendor/github.com/onsi/gomega/matchers/have_http_body_matcher.go @@ -11,8 +11,9 @@ import ( ) type HaveHTTPBodyMatcher struct { - Expected interface{} - cachedBody []byte + Expected interface{} + cachedResponse interface{} + cachedBody []byte } func (matcher *HaveHTTPBodyMatcher) Match(actual interface{}) (bool, error) { @@ -73,7 +74,7 @@ func (matcher *HaveHTTPBodyMatcher) NegatedFailureMessage(actual interface{}) (m // the Reader is closed and it is not readable again in FailureMessage() // or NegatedFailureMessage() func (matcher *HaveHTTPBodyMatcher) body(actual interface{}) ([]byte, error) { - if matcher.cachedBody != nil { + if matcher.cachedResponse == actual && matcher.cachedBody != nil { return matcher.cachedBody, nil } @@ -91,8 +92,10 @@ func (matcher *HaveHTTPBodyMatcher) body(actual interface{}) ([]byte, error) { switch a := actual.(type) { case *http.Response: + matcher.cachedResponse = a return body(a) case *httptest.ResponseRecorder: + matcher.cachedResponse = a return body(a.Result()) default: return nil, fmt.Errorf("HaveHTTPBody matcher expects *http.Response or *httptest.ResponseRecorder. Got:\n%s", format.Object(actual, 1)) diff --git a/vendor/github.com/onsi/gomega/matchers/match_error_matcher.go b/vendor/github.com/onsi/gomega/matchers/match_error_matcher.go index 827475ea5..c539dd389 100644 --- a/vendor/github.com/onsi/gomega/matchers/match_error_matcher.go +++ b/vendor/github.com/onsi/gomega/matchers/match_error_matcher.go @@ -9,10 +9,14 @@ import ( ) type MatchErrorMatcher struct { - Expected interface{} + Expected any + FuncErrDescription []any + isFunc bool } -func (matcher *MatchErrorMatcher) Match(actual interface{}) (success bool, err error) { +func (matcher *MatchErrorMatcher) Match(actual any) (success bool, err error) { + matcher.isFunc = false + if isNil(actual) { return false, fmt.Errorf("Expected an error, got nil") } @@ -42,6 +46,17 @@ func (matcher *MatchErrorMatcher) Match(actual interface{}) (success bool, err e return actualErr.Error() == expected, nil } + v := reflect.ValueOf(expected) + t := v.Type() + errorInterface := reflect.TypeOf((*error)(nil)).Elem() + if t.Kind() == reflect.Func && t.NumIn() == 1 && t.In(0).Implements(errorInterface) && t.NumOut() == 1 && t.Out(0).Kind() == reflect.Bool { + if len(matcher.FuncErrDescription) == 0 { + return false, fmt.Errorf("MatchError requires an additional description when passed a function") + } + matcher.isFunc = true + return v.Call([]reflect.Value{reflect.ValueOf(actualErr)})[0].Bool(), nil + } + var subMatcher omegaMatcher var hasSubMatcher bool if expected != nil { @@ -57,9 +72,15 @@ func (matcher *MatchErrorMatcher) Match(actual interface{}) (success bool, err e } func (matcher *MatchErrorMatcher) FailureMessage(actual interface{}) (message string) { + if matcher.isFunc { + return format.Message(actual, fmt.Sprintf("to match error function %s", matcher.FuncErrDescription[0])) + } return format.Message(actual, "to match error", matcher.Expected) } func (matcher *MatchErrorMatcher) NegatedFailureMessage(actual interface{}) (message string) { + if matcher.isFunc { + return format.Message(actual, fmt.Sprintf("not to match error function %s", matcher.FuncErrDescription[0])) + } return format.Message(actual, "not to match error", matcher.Expected) } diff --git a/vendor/github.com/onsi/gomega/matchers/receive_matcher.go b/vendor/github.com/onsi/gomega/matchers/receive_matcher.go index 1936a2ba5..948164eaf 100644 --- a/vendor/github.com/onsi/gomega/matchers/receive_matcher.go +++ b/vendor/github.com/onsi/gomega/matchers/receive_matcher.go @@ -3,6 +3,7 @@ package matchers import ( + "errors" "fmt" "reflect" @@ -10,7 +11,7 @@ import ( ) type ReceiveMatcher struct { - Arg interface{} + Args []interface{} receivedValue reflect.Value channelClosed bool } @@ -29,15 +30,38 @@ func (matcher *ReceiveMatcher) Match(actual interface{}) (success bool, err erro var subMatcher omegaMatcher var hasSubMatcher bool - - if matcher.Arg != nil { - subMatcher, hasSubMatcher = (matcher.Arg).(omegaMatcher) + var resultReference interface{} + + // Valid arg formats are as follows, always with optional POINTER before + // optional MATCHER: + // - Receive() + // - Receive(POINTER) + // - Receive(MATCHER) + // - Receive(POINTER, MATCHER) + args := matcher.Args + if len(args) > 0 { + arg := args[0] + _, isSubMatcher := arg.(omegaMatcher) + if !isSubMatcher && reflect.ValueOf(arg).Kind() == reflect.Ptr { + // Consume optional POINTER arg first, if it ain't no matcher ;) + resultReference = arg + args = args[1:] + } + } + if len(args) > 0 { + arg := args[0] + subMatcher, hasSubMatcher = arg.(omegaMatcher) if !hasSubMatcher { - argType := reflect.TypeOf(matcher.Arg) - if argType.Kind() != reflect.Ptr { - return false, fmt.Errorf("Cannot assign a value from the channel:\n%s\nTo:\n%s\nYou need to pass a pointer!", format.Object(actual, 1), format.Object(matcher.Arg, 1)) - } + // At this point we assume the dev user wanted to assign a received + // value, so [POINTER,]MATCHER. + return false, fmt.Errorf("Cannot assign a value from the channel:\n%s\nTo:\n%s\nYou need to pass a pointer!", format.Object(actual, 1), format.Object(arg, 1)) } + // Consume optional MATCHER arg. + args = args[1:] + } + if len(args) > 0 { + // If there are still args present, reject all. + return false, errors.New("Receive matcher expects at most an optional pointer and/or an optional matcher") } winnerIndex, value, open := reflect.Select([]reflect.SelectCase{ @@ -58,16 +82,20 @@ func (matcher *ReceiveMatcher) Match(actual interface{}) (success bool, err erro } if hasSubMatcher { - if didReceive { - matcher.receivedValue = value - return subMatcher.Match(matcher.receivedValue.Interface()) + if !didReceive { + return false, nil } - return false, nil + matcher.receivedValue = value + if match, err := subMatcher.Match(matcher.receivedValue.Interface()); err != nil || !match { + return match, err + } + // if we received a match, then fall through in order to handle an + // optional assignment of the received value to the specified reference. } if didReceive { - if matcher.Arg != nil { - outValue := reflect.ValueOf(matcher.Arg) + if resultReference != nil { + outValue := reflect.ValueOf(resultReference) if value.Type().AssignableTo(outValue.Elem().Type()) { outValue.Elem().Set(value) @@ -77,7 +105,7 @@ func (matcher *ReceiveMatcher) Match(actual interface{}) (success bool, err erro outValue.Elem().Set(value.Elem()) return true, nil } else { - return false, fmt.Errorf("Cannot assign a value from the channel:\n%s\nType:\n%s\nTo:\n%s", format.Object(actual, 1), format.Object(value.Interface(), 1), format.Object(matcher.Arg, 1)) + return false, fmt.Errorf("Cannot assign a value from the channel:\n%s\nType:\n%s\nTo:\n%s", format.Object(actual, 1), format.Object(value.Interface(), 1), format.Object(resultReference, 1)) } } @@ -88,7 +116,11 @@ func (matcher *ReceiveMatcher) Match(actual interface{}) (success bool, err erro } func (matcher *ReceiveMatcher) FailureMessage(actual interface{}) (message string) { - subMatcher, hasSubMatcher := (matcher.Arg).(omegaMatcher) + var matcherArg interface{} + if len(matcher.Args) > 0 { + matcherArg = matcher.Args[len(matcher.Args)-1] + } + subMatcher, hasSubMatcher := (matcherArg).(omegaMatcher) closedAddendum := "" if matcher.channelClosed { @@ -105,7 +137,11 @@ func (matcher *ReceiveMatcher) FailureMessage(actual interface{}) (message strin } func (matcher *ReceiveMatcher) NegatedFailureMessage(actual interface{}) (message string) { - subMatcher, hasSubMatcher := (matcher.Arg).(omegaMatcher) + var matcherArg interface{} + if len(matcher.Args) > 0 { + matcherArg = matcher.Args[len(matcher.Args)-1] + } + subMatcher, hasSubMatcher := (matcherArg).(omegaMatcher) closedAddendum := "" if matcher.channelClosed { diff --git a/vendor/github.com/openzipkin/zipkin-go/.golangci.yml b/vendor/github.com/openzipkin/zipkin-go/.golangci.yml index e990f027f..0c797fbf2 100644 --- a/vendor/github.com/openzipkin/zipkin-go/.golangci.yml +++ b/vendor/github.com/openzipkin/zipkin-go/.golangci.yml @@ -1,6 +1,8 @@ run: - deadline: 5m - skip-dirs: + timeout: 5m + +issues: + exclude-dirs: - zipkin_proto3 linters: @@ -16,6 +18,7 @@ linters: - lll - misspell - nakedret + - revive - unparam - unused @@ -26,5 +29,5 @@ linters-settings: line-length: 170 gocyclo: min-complexity: 20 - golint: - min-confidence: 0.85 + revive: + confidence: 0.85 diff --git a/vendor/github.com/openzipkin/zipkin-go/README.md b/vendor/github.com/openzipkin/zipkin-go/README.md index 05000f80a..646bf2242 100644 --- a/vendor/github.com/openzipkin/zipkin-go/README.md +++ b/vendor/github.com/openzipkin/zipkin-go/README.md @@ -112,5 +112,17 @@ Producer digesting JSON V2 Spans. The reporter uses the [Sarama async producer](https://pkg.go.dev/github.com/IBM/sarama#AsyncProducer) underneath. -## usage and examples +## Usage and Examples [HTTP Server Example](examples/httpserver_test.go) + +## Go Support Policy + +zipkin-go follows the same version policy as Go's [Release Policy](https://go.dev/doc/devel/release): +two versions. zipkin-go will ensure these versions work and bugs are valid if +there's an issue with a current Go version. + +Additionally, zipkin-go intentionally delays usage of language or standard +library features one additional version. For example, when Go 1.29 is released, +zipkin-go can use language features or standard libraries added in 1.27. This +is a convenience for embedders who have a slower version policy than Go. +However, only supported Go versions may be used to raise support issues. diff --git a/vendor/github.com/openzipkin/zipkin-go/SECURITY.md b/vendor/github.com/openzipkin/zipkin-go/SECURITY.md new file mode 100644 index 000000000..bba9ddbdf --- /dev/null +++ b/vendor/github.com/openzipkin/zipkin-go/SECURITY.md @@ -0,0 +1,13 @@ +# OpenZipkin Security Process + +This document outlines the process for handling security concerns in OpenZipkin projects. + +Any vulnerability or misconfiguration detected in our [security workflow](.github/workflows/security.yml) +should be addressed as a normal pull request. + +OpenZipkin is a volunteer community and does not have a dedicated security team. There may be +periods where no volunteer is able to address a security concern. There is no SLA or warranty +offered by volunteers. If you are a security researcher, please consider this before escalating. + +For security concerns that are sensitive or otherwise outside the scope of public issues, please +contact zipkin-admin@googlegroups.com. diff --git a/vendor/github.com/openzipkin/zipkin-go/span_implementation.go b/vendor/github.com/openzipkin/zipkin-go/span_implementation.go index ab2f39bea..5b9c69231 100644 --- a/vendor/github.com/openzipkin/zipkin-go/span_implementation.go +++ b/vendor/github.com/openzipkin/zipkin-go/span_implementation.go @@ -80,7 +80,9 @@ func (s *spanImpl) Finish() { if atomic.CompareAndSwapInt32(&s.mustCollect, 1, 0) { s.Duration = time.Since(s.Timestamp) if s.flushOnFinish { + s.mtx.RLock() s.tracer.reporter.Send(s.SpanModel) + s.mtx.RUnlock() } } } @@ -89,13 +91,17 @@ func (s *spanImpl) FinishedWithDuration(d time.Duration) { if atomic.CompareAndSwapInt32(&s.mustCollect, 1, 0) { s.Duration = d if s.flushOnFinish { + s.mtx.RLock() s.tracer.reporter.Send(s.SpanModel) + s.mtx.RUnlock() } } } func (s *spanImpl) Flush() { if s.SpanModel.Debug || (s.SpanModel.Sampled != nil && *s.SpanModel.Sampled) { + s.mtx.RLock() s.tracer.reporter.Send(s.SpanModel) + s.mtx.RUnlock() } } diff --git a/vendor/github.com/openzipkin/zipkin-go/span_options.go b/vendor/github.com/openzipkin/zipkin-go/span_options.go index 0eabeaa02..ad9f5c29f 100644 --- a/vendor/github.com/openzipkin/zipkin-go/span_options.go +++ b/vendor/github.com/openzipkin/zipkin-go/span_options.go @@ -26,7 +26,7 @@ type SpanOption func(t *Tracer, s *spanImpl) // Kind sets the kind of the span being created. func Kind(kind model.Kind) SpanOption { - return func(t *Tracer, s *spanImpl) { + return func(_ *Tracer, s *spanImpl) { s.Kind = kind } } @@ -54,14 +54,14 @@ func Parent(sc model.SpanContext) SpanOption { // StartTime uses a given start time for the span being created. func StartTime(start time.Time) SpanOption { - return func(t *Tracer, s *spanImpl) { + return func(_ *Tracer, s *spanImpl) { s.Timestamp = start } } // RemoteEndpoint sets the remote endpoint of the span being created. func RemoteEndpoint(e *model.Endpoint) SpanOption { - return func(t *Tracer, s *spanImpl) { + return func(_ *Tracer, s *spanImpl) { s.RemoteEndpoint = e } } @@ -69,7 +69,7 @@ func RemoteEndpoint(e *model.Endpoint) SpanOption { // Tags sets initial tags for the span being created. If default tracer tags // are present they will be overwritten on key collisions. func Tags(tags map[string]string) SpanOption { - return func(t *Tracer, s *spanImpl) { + return func(_ *Tracer, s *spanImpl) { for k, v := range tags { s.Tags[k] = v } @@ -82,7 +82,7 @@ func Tags(tags map[string]string) SpanOption { // This is available if late tag data is expected to be only available after the // required finish time of the Span. func FlushOnFinish(b bool) SpanOption { - return func(t *Tracer, s *spanImpl) { + return func(_ *Tracer, s *spanImpl) { s.flushOnFinish = b } } diff --git a/vendor/github.com/philhofer/fwd/README.md b/vendor/github.com/philhofer/fwd/README.md index 62bd5c6d0..4e9952342 100644 --- a/vendor/github.com/philhofer/fwd/README.md +++ b/vendor/github.com/philhofer/fwd/README.md @@ -45,6 +45,15 @@ the write position by the length of the returned slice. This allows users to write directly to the end of the buffer. +## Portability + +Because it uses the unsafe package, there are theoretically +no promises about forward or backward portability. + +To stay compatible with tinygo 0.32, unsafestr() has been updated +to use unsafe.Slice() as suggested by +https://tinygo.org/docs/guides/compatibility, which also required +bumping go.mod to require at least go 1.20. ##
Index diff --git a/vendor/github.com/philhofer/fwd/writer_tinygo.go b/vendor/github.com/philhofer/fwd/writer_tinygo.go index b060faf7a..c98cd57f3 100644 --- a/vendor/github.com/philhofer/fwd/writer_tinygo.go +++ b/vendor/github.com/philhofer/fwd/writer_tinygo.go @@ -4,16 +4,10 @@ package fwd import ( - "reflect" "unsafe" ) // unsafe cast string as []byte func unsafestr(b string) []byte { - l := uintptr(len(b)) - return *(*[]byte)(unsafe.Pointer(&reflect.SliceHeader{ - Len: l, - Cap: l, - Data: (*reflect.StringHeader)(unsafe.Pointer(&b)).Data, - })) + return unsafe.Slice(unsafe.StringData(b), len(b)) } diff --git a/vendor/github.com/prometheus/client_golang/NOTICE b/vendor/github.com/prometheus/client_golang/NOTICE index dd878a30e..b9cc55abb 100644 --- a/vendor/github.com/prometheus/client_golang/NOTICE +++ b/vendor/github.com/prometheus/client_golang/NOTICE @@ -16,8 +16,3 @@ Go support for Protocol Buffers - Google's data interchange format http://github.com/golang/protobuf/ Copyright 2010 The Go Authors See source code for license details. - -Support for streaming Protocol Buffer messages for the Go language (golang). -https://github.com/matttproud/golang_protobuf_extensions -Copyright 2013 Matt T. Proud -Licensed under the Apache License, Version 2.0 diff --git a/vendor/github.com/prometheus/client_golang/internal/github.com/golang/gddo/LICENSE b/vendor/github.com/prometheus/client_golang/internal/github.com/golang/gddo/LICENSE new file mode 100644 index 000000000..65d761bc9 --- /dev/null +++ b/vendor/github.com/prometheus/client_golang/internal/github.com/golang/gddo/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2013 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. diff --git a/vendor/github.com/prometheus/client_golang/internal/github.com/golang/gddo/httputil/header/header.go b/vendor/github.com/prometheus/client_golang/internal/github.com/golang/gddo/httputil/header/header.go new file mode 100644 index 000000000..8547c8dfd --- /dev/null +++ b/vendor/github.com/prometheus/client_golang/internal/github.com/golang/gddo/httputil/header/header.go @@ -0,0 +1,145 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file or at +// https://developers.google.com/open-source/licenses/bsd. + +// Package header provides functions for parsing HTTP headers. +package header + +import ( + "net/http" + "strings" +) + +// Octet types from RFC 2616. +var octetTypes [256]octetType + +type octetType byte + +const ( + isToken octetType = 1 << iota + isSpace +) + +func init() { + // OCTET = + // CHAR = + // CTL = + // CR = + // LF = + // SP = + // HT = + // <"> = + // CRLF = CR LF + // LWS = [CRLF] 1*( SP | HT ) + // TEXT = + // separators = "(" | ")" | "<" | ">" | "@" | "," | ";" | ":" | "\" | <"> + // | "/" | "[" | "]" | "?" | "=" | "{" | "}" | SP | HT + // token = 1* + // qdtext = > + + for c := 0; c < 256; c++ { + var t octetType + isCtl := c <= 31 || c == 127 + isChar := 0 <= c && c <= 127 + isSeparator := strings.ContainsRune(" \t\"(),/:;<=>?@[]\\{}", rune(c)) + if strings.ContainsRune(" \t\r\n", rune(c)) { + t |= isSpace + } + if isChar && !isCtl && !isSeparator { + t |= isToken + } + octetTypes[c] = t + } +} + +// AcceptSpec describes an Accept* header. +type AcceptSpec struct { + Value string + Q float64 +} + +// ParseAccept parses Accept* headers. +func ParseAccept(header http.Header, key string) (specs []AcceptSpec) { +loop: + for _, s := range header[key] { + for { + var spec AcceptSpec + spec.Value, s = expectTokenSlash(s) + if spec.Value == "" { + continue loop + } + spec.Q = 1.0 + s = skipSpace(s) + if strings.HasPrefix(s, ";") { + s = skipSpace(s[1:]) + if !strings.HasPrefix(s, "q=") { + continue loop + } + spec.Q, s = expectQuality(s[2:]) + if spec.Q < 0.0 { + continue loop + } + } + specs = append(specs, spec) + s = skipSpace(s) + if !strings.HasPrefix(s, ",") { + continue loop + } + s = skipSpace(s[1:]) + } + } + return +} + +func skipSpace(s string) (rest string) { + i := 0 + for ; i < len(s); i++ { + if octetTypes[s[i]]&isSpace == 0 { + break + } + } + return s[i:] +} + +func expectTokenSlash(s string) (token, rest string) { + i := 0 + for ; i < len(s); i++ { + b := s[i] + if (octetTypes[b]&isToken == 0) && b != '/' { + break + } + } + return s[:i], s[i:] +} + +func expectQuality(s string) (q float64, rest string) { + switch { + case len(s) == 0: + return -1, "" + case s[0] == '0': + q = 0 + case s[0] == '1': + q = 1 + default: + return -1, "" + } + s = s[1:] + if !strings.HasPrefix(s, ".") { + return q, s + } + s = s[1:] + i := 0 + n := 0 + d := 1 + for ; i < len(s); i++ { + b := s[i] + if b < '0' || b > '9' { + break + } + n = n*10 + int(b) - '0' + d *= 10 + } + return q + float64(n)/float64(d), s[i:] +} diff --git a/vendor/github.com/prometheus/client_golang/internal/github.com/golang/gddo/httputil/negotiate.go b/vendor/github.com/prometheus/client_golang/internal/github.com/golang/gddo/httputil/negotiate.go new file mode 100644 index 000000000..2e45780b7 --- /dev/null +++ b/vendor/github.com/prometheus/client_golang/internal/github.com/golang/gddo/httputil/negotiate.go @@ -0,0 +1,36 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file or at +// https://developers.google.com/open-source/licenses/bsd. + +package httputil + +import ( + "net/http" + + "github.com/prometheus/client_golang/internal/github.com/golang/gddo/httputil/header" +) + +// NegotiateContentEncoding returns the best offered content encoding for the +// request's Accept-Encoding header. If two offers match with equal weight and +// then the offer earlier in the list is preferred. If no offers are +// acceptable, then "" is returned. +func NegotiateContentEncoding(r *http.Request, offers []string) string { + bestOffer := "identity" + bestQ := -1.0 + specs := header.ParseAccept(r.Header, "Accept-Encoding") + for _, offer := range offers { + for _, spec := range specs { + if spec.Q > bestQ && + (spec.Value == "*" || spec.Value == offer) { + bestQ = spec.Q + bestOffer = offer + } + } + } + if bestQ == 0 { + bestOffer = "" + } + return bestOffer +} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/collectors/go_collector_latest.go b/vendor/github.com/prometheus/client_golang/prometheus/collectors/go_collector_latest.go index bcfa4fa10..cc4ef1077 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/collectors/go_collector_latest.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/collectors/go_collector_latest.go @@ -37,6 +37,9 @@ var ( // MetricsScheduler allows only scheduler metrics to be collected from Go runtime. // e.g. go_sched_goroutines_goroutines MetricsScheduler = GoRuntimeMetricsRule{regexp.MustCompile(`^/sched/.*`)} + // MetricsDebug allows only debug metrics to be collected from Go runtime. + // e.g. go_godebug_non_default_behavior_gocachetest_events_total + MetricsDebug = GoRuntimeMetricsRule{regexp.MustCompile(`^/godebug/.*`)} ) // WithGoCollectorMemStatsMetricsDisabled disables metrics that is gathered in runtime.MemStats structure such as: @@ -44,7 +47,6 @@ var ( // go_memstats_alloc_bytes // go_memstats_alloc_bytes_total // go_memstats_sys_bytes -// go_memstats_lookups_total // go_memstats_mallocs_total // go_memstats_frees_total // go_memstats_heap_alloc_bytes diff --git a/vendor/github.com/prometheus/client_golang/prometheus/go_collector.go b/vendor/github.com/prometheus/client_golang/prometheus/go_collector.go index ad9a71a5e..520cbd7d4 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/go_collector.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/go_collector.go @@ -22,13 +22,13 @@ import ( // goRuntimeMemStats provides the metrics initially provided by runtime.ReadMemStats. // From Go 1.17 those similar (and better) statistics are provided by runtime/metrics, so // while eval closure works on runtime.MemStats, the struct from Go 1.17+ is -// populated using runtime/metrics. +// populated using runtime/metrics. Those are the defaults we can't alter. func goRuntimeMemStats() memStatsMetrics { return memStatsMetrics{ { desc: NewDesc( memstatNamespace("alloc_bytes"), - "Number of bytes allocated and still in use.", + "Number of bytes allocated in heap and currently in use. Equals to /memory/classes/heap/objects:bytes.", nil, nil, ), eval: func(ms *runtime.MemStats) float64 { return float64(ms.Alloc) }, @@ -36,7 +36,7 @@ func goRuntimeMemStats() memStatsMetrics { }, { desc: NewDesc( memstatNamespace("alloc_bytes_total"), - "Total number of bytes allocated, even if freed.", + "Total number of bytes allocated in heap until now, even if released already. Equals to /gc/heap/allocs:bytes.", nil, nil, ), eval: func(ms *runtime.MemStats) float64 { return float64(ms.TotalAlloc) }, @@ -44,23 +44,16 @@ func goRuntimeMemStats() memStatsMetrics { }, { desc: NewDesc( memstatNamespace("sys_bytes"), - "Number of bytes obtained from system.", + "Number of bytes obtained from system. Equals to /memory/classes/total:byte.", nil, nil, ), eval: func(ms *runtime.MemStats) float64 { return float64(ms.Sys) }, valType: GaugeValue, - }, { - desc: NewDesc( - memstatNamespace("lookups_total"), - "Total number of pointer lookups.", - nil, nil, - ), - eval: func(ms *runtime.MemStats) float64 { return float64(ms.Lookups) }, - valType: CounterValue, }, { desc: NewDesc( memstatNamespace("mallocs_total"), - "Total number of mallocs.", + // TODO(bwplotka): We could add go_memstats_heap_objects, probably useful for discovery. Let's gather more feedback, kind of a waste of bytes for everybody for compatibility reasons to keep both, and we can't really rename/remove useful metric. + "Total number of heap objects allocated, both live and gc-ed. Semantically a counter version for go_memstats_heap_objects gauge. Equals to /gc/heap/allocs:objects + /gc/heap/tiny/allocs:objects.", nil, nil, ), eval: func(ms *runtime.MemStats) float64 { return float64(ms.Mallocs) }, @@ -68,7 +61,7 @@ func goRuntimeMemStats() memStatsMetrics { }, { desc: NewDesc( memstatNamespace("frees_total"), - "Total number of frees.", + "Total number of heap objects frees. Equals to /gc/heap/frees:objects + /gc/heap/tiny/allocs:objects.", nil, nil, ), eval: func(ms *runtime.MemStats) float64 { return float64(ms.Frees) }, @@ -76,7 +69,7 @@ func goRuntimeMemStats() memStatsMetrics { }, { desc: NewDesc( memstatNamespace("heap_alloc_bytes"), - "Number of heap bytes allocated and still in use.", + "Number of heap bytes allocated and currently in use, same as go_memstats_alloc_bytes. Equals to /memory/classes/heap/objects:bytes.", nil, nil, ), eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapAlloc) }, @@ -84,7 +77,7 @@ func goRuntimeMemStats() memStatsMetrics { }, { desc: NewDesc( memstatNamespace("heap_sys_bytes"), - "Number of heap bytes obtained from system.", + "Number of heap bytes obtained from system. Equals to /memory/classes/heap/objects:bytes + /memory/classes/heap/unused:bytes + /memory/classes/heap/released:bytes + /memory/classes/heap/free:bytes.", nil, nil, ), eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapSys) }, @@ -92,7 +85,7 @@ func goRuntimeMemStats() memStatsMetrics { }, { desc: NewDesc( memstatNamespace("heap_idle_bytes"), - "Number of heap bytes waiting to be used.", + "Number of heap bytes waiting to be used. Equals to /memory/classes/heap/released:bytes + /memory/classes/heap/free:bytes.", nil, nil, ), eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapIdle) }, @@ -100,7 +93,7 @@ func goRuntimeMemStats() memStatsMetrics { }, { desc: NewDesc( memstatNamespace("heap_inuse_bytes"), - "Number of heap bytes that are in use.", + "Number of heap bytes that are in use. Equals to /memory/classes/heap/objects:bytes + /memory/classes/heap/unused:bytes", nil, nil, ), eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapInuse) }, @@ -108,7 +101,7 @@ func goRuntimeMemStats() memStatsMetrics { }, { desc: NewDesc( memstatNamespace("heap_released_bytes"), - "Number of heap bytes released to OS.", + "Number of heap bytes released to OS. Equals to /memory/classes/heap/released:bytes.", nil, nil, ), eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapReleased) }, @@ -116,7 +109,7 @@ func goRuntimeMemStats() memStatsMetrics { }, { desc: NewDesc( memstatNamespace("heap_objects"), - "Number of allocated objects.", + "Number of currently allocated objects. Equals to /gc/heap/objects:objects.", nil, nil, ), eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapObjects) }, @@ -124,7 +117,7 @@ func goRuntimeMemStats() memStatsMetrics { }, { desc: NewDesc( memstatNamespace("stack_inuse_bytes"), - "Number of bytes in use by the stack allocator.", + "Number of bytes obtained from system for stack allocator in non-CGO environments. Equals to /memory/classes/heap/stacks:bytes.", nil, nil, ), eval: func(ms *runtime.MemStats) float64 { return float64(ms.StackInuse) }, @@ -132,7 +125,7 @@ func goRuntimeMemStats() memStatsMetrics { }, { desc: NewDesc( memstatNamespace("stack_sys_bytes"), - "Number of bytes obtained from system for stack allocator.", + "Number of bytes obtained from system for stack allocator. Equals to /memory/classes/heap/stacks:bytes + /memory/classes/os-stacks:bytes.", nil, nil, ), eval: func(ms *runtime.MemStats) float64 { return float64(ms.StackSys) }, @@ -140,7 +133,7 @@ func goRuntimeMemStats() memStatsMetrics { }, { desc: NewDesc( memstatNamespace("mspan_inuse_bytes"), - "Number of bytes in use by mspan structures.", + "Number of bytes in use by mspan structures. Equals to /memory/classes/metadata/mspan/inuse:bytes.", nil, nil, ), eval: func(ms *runtime.MemStats) float64 { return float64(ms.MSpanInuse) }, @@ -148,7 +141,7 @@ func goRuntimeMemStats() memStatsMetrics { }, { desc: NewDesc( memstatNamespace("mspan_sys_bytes"), - "Number of bytes used for mspan structures obtained from system.", + "Number of bytes used for mspan structures obtained from system. Equals to /memory/classes/metadata/mspan/inuse:bytes + /memory/classes/metadata/mspan/free:bytes.", nil, nil, ), eval: func(ms *runtime.MemStats) float64 { return float64(ms.MSpanSys) }, @@ -156,7 +149,7 @@ func goRuntimeMemStats() memStatsMetrics { }, { desc: NewDesc( memstatNamespace("mcache_inuse_bytes"), - "Number of bytes in use by mcache structures.", + "Number of bytes in use by mcache structures. Equals to /memory/classes/metadata/mcache/inuse:bytes.", nil, nil, ), eval: func(ms *runtime.MemStats) float64 { return float64(ms.MCacheInuse) }, @@ -164,7 +157,7 @@ func goRuntimeMemStats() memStatsMetrics { }, { desc: NewDesc( memstatNamespace("mcache_sys_bytes"), - "Number of bytes used for mcache structures obtained from system.", + "Number of bytes used for mcache structures obtained from system. Equals to /memory/classes/metadata/mcache/inuse:bytes + /memory/classes/metadata/mcache/free:bytes.", nil, nil, ), eval: func(ms *runtime.MemStats) float64 { return float64(ms.MCacheSys) }, @@ -172,7 +165,7 @@ func goRuntimeMemStats() memStatsMetrics { }, { desc: NewDesc( memstatNamespace("buck_hash_sys_bytes"), - "Number of bytes used by the profiling bucket hash table.", + "Number of bytes used by the profiling bucket hash table. Equals to /memory/classes/profiling/buckets:bytes.", nil, nil, ), eval: func(ms *runtime.MemStats) float64 { return float64(ms.BuckHashSys) }, @@ -180,7 +173,7 @@ func goRuntimeMemStats() memStatsMetrics { }, { desc: NewDesc( memstatNamespace("gc_sys_bytes"), - "Number of bytes used for garbage collection system metadata.", + "Number of bytes used for garbage collection system metadata. Equals to /memory/classes/metadata/other:bytes.", nil, nil, ), eval: func(ms *runtime.MemStats) float64 { return float64(ms.GCSys) }, @@ -188,7 +181,7 @@ func goRuntimeMemStats() memStatsMetrics { }, { desc: NewDesc( memstatNamespace("other_sys_bytes"), - "Number of bytes used for other system allocations.", + "Number of bytes used for other system allocations. Equals to /memory/classes/other:bytes.", nil, nil, ), eval: func(ms *runtime.MemStats) float64 { return float64(ms.OtherSys) }, @@ -196,7 +189,7 @@ func goRuntimeMemStats() memStatsMetrics { }, { desc: NewDesc( memstatNamespace("next_gc_bytes"), - "Number of heap bytes when next garbage collection will take place.", + "Number of heap bytes when next garbage collection will take place. Equals to /gc/heap/goal:bytes.", nil, nil, ), eval: func(ms *runtime.MemStats) float64 { return float64(ms.NextGC) }, @@ -225,7 +218,7 @@ func newBaseGoCollector() baseGoCollector { nil, nil), gcDesc: NewDesc( "go_gc_duration_seconds", - "A summary of the pause duration of garbage collection cycles.", + "A summary of the wall-time pause (stop-the-world) duration in garbage collection cycles.", nil, nil), gcLastTimeDesc: NewDesc( "go_memstats_last_gc_time_seconds", diff --git a/vendor/github.com/prometheus/client_golang/prometheus/go_collector_latest.go b/vendor/github.com/prometheus/client_golang/prometheus/go_collector_latest.go index 2d8d9f64f..511746417 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/go_collector_latest.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/go_collector_latest.go @@ -17,6 +17,7 @@ package prometheus import ( + "fmt" "math" "runtime" "runtime/metrics" @@ -153,7 +154,8 @@ func defaultGoCollectorOptions() internal.GoCollectorOptions { "/gc/heap/frees-by-size:bytes": goGCHeapFreesBytes, }, RuntimeMetricRules: []internal.GoCollectorRule{ - //{Matcher: regexp.MustCompile("")}, + // Recommended metrics we want by default from runtime/metrics. + {Matcher: internal.GoCollectorDefaultRuntimeMetrics}, }, } } @@ -203,6 +205,7 @@ func NewGoCollector(opts ...func(o *internal.GoCollectorOptions)) Collector { // to fail here. This condition is tested in TestExpectedRuntimeMetrics. continue } + help := attachOriginalName(d.Description.Description, d.Name) sampleBuf = append(sampleBuf, metrics.Sample{Name: d.Name}) sampleMap[d.Name] = &sampleBuf[len(sampleBuf)-1] @@ -214,7 +217,7 @@ func NewGoCollector(opts ...func(o *internal.GoCollectorOptions)) Collector { m = newBatchHistogram( NewDesc( BuildFQName(namespace, subsystem, name), - d.Description.Description, + help, nil, nil, ), @@ -226,7 +229,7 @@ func NewGoCollector(opts ...func(o *internal.GoCollectorOptions)) Collector { Namespace: namespace, Subsystem: subsystem, Name: name, - Help: d.Description.Description, + Help: help, }, ) } else { @@ -234,7 +237,7 @@ func NewGoCollector(opts ...func(o *internal.GoCollectorOptions)) Collector { Namespace: namespace, Subsystem: subsystem, Name: name, - Help: d.Description.Description, + Help: help, }) } metricSet = append(metricSet, m) @@ -284,6 +287,10 @@ func NewGoCollector(opts ...func(o *internal.GoCollectorOptions)) Collector { } } +func attachOriginalName(desc, origName string) string { + return fmt.Sprintf("%s Sourced from %s", desc, origName) +} + // Describe returns all descriptions of the collector. func (c *goCollector) Describe(ch chan<- *Desc) { c.base.Describe(ch) @@ -376,13 +383,13 @@ func unwrapScalarRMValue(v metrics.Value) float64 { // // This should never happen because we always populate our metric // set from the runtime/metrics package. - panic("unexpected unsupported metric") + panic("unexpected bad kind metric") default: // Unsupported metric kind. // // This should never happen because we check for this during initialization // and flag and filter metrics whose kinds we don't understand. - panic("unexpected unsupported metric kind") + panic(fmt.Sprintf("unexpected unsupported metric: %v", v.Kind())) } } diff --git a/vendor/github.com/prometheus/client_golang/prometheus/histogram.go b/vendor/github.com/prometheus/client_golang/prometheus/histogram.go index b5c8bcb39..519db348a 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/histogram.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/histogram.go @@ -440,7 +440,7 @@ type HistogramOpts struct { // constant (or any negative float value). NativeHistogramZeroThreshold float64 - // The remaining fields define a strategy to limit the number of + // The next three fields define a strategy to limit the number of // populated sparse buckets. If NativeHistogramMaxBucketNumber is left // at zero, the number of buckets is not limited. (Note that this might // lead to unbounded memory consumption if the values observed by the @@ -473,6 +473,22 @@ type HistogramOpts struct { NativeHistogramMinResetDuration time.Duration NativeHistogramMaxZeroThreshold float64 + // NativeHistogramMaxExemplars limits the number of exemplars + // that are kept in memory for each native histogram. If you leave it at + // zero, a default value of 10 is used. If no exemplars should be kept specifically + // for native histograms, set it to a negative value. (Scrapers can + // still use the exemplars exposed for classic buckets, which are managed + // independently.) + NativeHistogramMaxExemplars int + // NativeHistogramExemplarTTL is only checked once + // NativeHistogramMaxExemplars is exceeded. In that case, the + // oldest exemplar is removed if it is older than NativeHistogramExemplarTTL. + // Otherwise, the older exemplar in the pair of exemplars that are closest + // together (on an exponential scale) is removed. + // If NativeHistogramExemplarTTL is left at its zero value, a default value of + // 5m is used. To always delete the oldest exemplar, set it to a negative value. + NativeHistogramExemplarTTL time.Duration + // now is for testing purposes, by default it's time.Now. now func() time.Time @@ -532,6 +548,7 @@ func newHistogram(desc *Desc, opts HistogramOpts, labelValues ...string) Histogr if opts.afterFunc == nil { opts.afterFunc = time.AfterFunc } + h := &histogram{ desc: desc, upperBounds: opts.Buckets, @@ -556,6 +573,7 @@ func newHistogram(desc *Desc, opts HistogramOpts, labelValues ...string) Histogr h.nativeHistogramZeroThreshold = DefNativeHistogramZeroThreshold } // Leave h.nativeHistogramZeroThreshold at 0 otherwise. h.nativeHistogramSchema = pickSchema(opts.NativeHistogramBucketFactor) + h.nativeExemplars = makeNativeExemplars(opts.NativeHistogramExemplarTTL, opts.NativeHistogramMaxExemplars) } for i, upperBound := range h.upperBounds { if i < len(h.upperBounds)-1 { @@ -725,7 +743,8 @@ type histogram struct { // resetScheduled is protected by mtx. It is true if a reset is // scheduled for a later time (when nativeHistogramMinResetDuration has // passed). - resetScheduled bool + resetScheduled bool + nativeExemplars nativeExemplars // now is for testing purposes, by default it's time.Now. now func() time.Time @@ -742,6 +761,9 @@ func (h *histogram) Observe(v float64) { h.observe(v, h.findBucket(v)) } +// ObserveWithExemplar should not be called in a high-frequency setting +// for a native histogram with configured exemplars. For this case, +// the implementation isn't lock-free and might suffer from lock contention. func (h *histogram) ObserveWithExemplar(v float64, e Labels) { i := h.findBucket(v) h.observe(v, i) @@ -821,6 +843,13 @@ func (h *histogram) Write(out *dto.Metric) error { Length: proto.Uint32(0), }} } + + if h.nativeExemplars.isEnabled() { + h.nativeExemplars.Lock() + his.Exemplars = append(his.Exemplars, h.nativeExemplars.exemplars...) + h.nativeExemplars.Unlock() + } + } addAndResetCounts(hotCounts, coldCounts) return nil @@ -1091,8 +1120,10 @@ func (h *histogram) resetCounts(counts *histogramCounts) { deleteSyncMap(&counts.nativeHistogramBucketsPositive) } -// updateExemplar replaces the exemplar for the provided bucket. With empty -// labels, it's a no-op. It panics if any of the labels is invalid. +// updateExemplar replaces the exemplar for the provided classic bucket. +// With empty labels, it's a no-op. It panics if any of the labels is invalid. +// If histogram is native, the exemplar will be cached into nativeExemplars, +// which has a limit, and will remove one exemplar when limit is reached. func (h *histogram) updateExemplar(v float64, bucket int, l Labels) { if l == nil { return @@ -1102,6 +1133,10 @@ func (h *histogram) updateExemplar(v float64, bucket int, l Labels) { panic(err) } h.exemplars[bucket].Store(e) + doSparse := h.nativeHistogramSchema > math.MinInt32 && !math.IsNaN(v) + if doSparse { + h.nativeExemplars.addExemplar(e) + } } // HistogramVec is a Collector that bundles a set of Histograms that all share the @@ -1336,6 +1371,48 @@ func MustNewConstHistogram( return m } +// NewConstHistogramWithCreatedTimestamp does the same thing as NewConstHistogram but sets the created timestamp. +func NewConstHistogramWithCreatedTimestamp( + desc *Desc, + count uint64, + sum float64, + buckets map[float64]uint64, + ct time.Time, + labelValues ...string, +) (Metric, error) { + if desc.err != nil { + return nil, desc.err + } + if err := validateLabelValues(labelValues, len(desc.variableLabels.names)); err != nil { + return nil, err + } + return &constHistogram{ + desc: desc, + count: count, + sum: sum, + buckets: buckets, + labelPairs: MakeLabelPairs(desc, labelValues), + createdTs: timestamppb.New(ct), + }, nil +} + +// MustNewConstHistogramWithCreatedTimestamp is a version of NewConstHistogramWithCreatedTimestamp that panics where +// NewConstHistogramWithCreatedTimestamp would have returned an error. +func MustNewConstHistogramWithCreatedTimestamp( + desc *Desc, + count uint64, + sum float64, + buckets map[float64]uint64, + ct time.Time, + labelValues ...string, +) Metric { + m, err := NewConstHistogramWithCreatedTimestamp(desc, count, sum, buckets, ct, labelValues...) + if err != nil { + panic(err) + } + return m +} + type buckSort []*dto.Bucket func (s buckSort) Len() int { @@ -1575,3 +1652,186 @@ func addAndResetCounts(hot, cold *histogramCounts) { atomic.AddUint64(&hot.nativeHistogramZeroBucket, atomic.LoadUint64(&cold.nativeHistogramZeroBucket)) atomic.StoreUint64(&cold.nativeHistogramZeroBucket, 0) } + +type nativeExemplars struct { + sync.Mutex + + // Time-to-live for exemplars, it is set to -1 if exemplars are disabled, that is NativeHistogramMaxExemplars is below 0. + // The ttl is used on insertion to remove an exemplar that is older than ttl, if present. + ttl time.Duration + + exemplars []*dto.Exemplar +} + +func (n *nativeExemplars) isEnabled() bool { + return n.ttl != -1 +} + +func makeNativeExemplars(ttl time.Duration, maxCount int) nativeExemplars { + if ttl == 0 { + ttl = 5 * time.Minute + } + + if maxCount == 0 { + maxCount = 10 + } + + if maxCount < 0 { + maxCount = 0 + ttl = -1 + } + + return nativeExemplars{ + ttl: ttl, + exemplars: make([]*dto.Exemplar, 0, maxCount), + } +} + +func (n *nativeExemplars) addExemplar(e *dto.Exemplar) { + if !n.isEnabled() { + return + } + + n.Lock() + defer n.Unlock() + + // When the number of exemplars has not yet exceeded or + // is equal to cap(n.exemplars), then + // insert the new exemplar directly. + if len(n.exemplars) < cap(n.exemplars) { + var nIdx int + for nIdx = 0; nIdx < len(n.exemplars); nIdx++ { + if *e.Value < *n.exemplars[nIdx].Value { + break + } + } + n.exemplars = append(n.exemplars[:nIdx], append([]*dto.Exemplar{e}, n.exemplars[nIdx:]...)...) + return + } + + if len(n.exemplars) == 1 { + // When the number of exemplars is 1, then + // replace the existing exemplar with the new exemplar. + n.exemplars[0] = e + return + } + // From this point on, the number of exemplars is greater than 1. + + // When the number of exemplars exceeds the limit, remove one exemplar. + var ( + ot = time.Time{} // Oldest timestamp seen. Initial value doesn't matter as we replace it due to otIdx == -1 in the loop. + otIdx = -1 // Index of the exemplar with the oldest timestamp. + + md = -1.0 // Logarithm of the delta of the closest pair of exemplars. + + // The insertion point of the new exemplar in the exemplars slice after insertion. + // This is calculated purely based on the order of the exemplars by value. + // nIdx == len(n.exemplars) means the new exemplar is to be inserted after the end. + nIdx = -1 + + // rIdx is ultimately the index for the exemplar that we are replacing with the new exemplar. + // The aim is to keep a good spread of exemplars by value and not let them bunch up too much. + // It is calculated in 3 steps: + // 1. First we set rIdx to the index of the older exemplar within the closest pair by value. + // That is the following will be true (on log scale): + // either the exemplar pair on index (rIdx-1, rIdx) or (rIdx, rIdx+1) will have + // the closest values to each other from all pairs. + // For example, suppose the values are distributed like this: + // |-----------x-------------x----------------x----x-----| + // ^--rIdx as this is older. + // Or like this: + // |-----------x-------------x----------------x----x-----| + // ^--rIdx as this is older. + // 2. If there is an exemplar that expired, then we simple reset rIdx to that index. + // 3. We check if by inserting the new exemplar we would create a closer pair at + // (nIdx-1, nIdx) or (nIdx, nIdx+1) and set rIdx to nIdx-1 or nIdx accordingly to + // keep the spread of exemplars by value; otherwise we keep rIdx as it is. + rIdx = -1 + cLog float64 // Logarithm of the current exemplar. + pLog float64 // Logarithm of the previous exemplar. + ) + + for i, exemplar := range n.exemplars { + // Find the exemplar with the oldest timestamp. + if otIdx == -1 || exemplar.Timestamp.AsTime().Before(ot) { + ot = exemplar.Timestamp.AsTime() + otIdx = i + } + + // Find the index at which to insert new the exemplar. + if nIdx == -1 && *e.Value <= *exemplar.Value { + nIdx = i + } + + // Find the two closest exemplars and pick the one the with older timestamp. + pLog = cLog + cLog = math.Log(exemplar.GetValue()) + if i == 0 { + continue + } + diff := math.Abs(cLog - pLog) + if md == -1 || diff < md { + // The closest exemplar pair is at index: i-1, i. + // Choose the exemplar with the older timestamp for replacement. + md = diff + if n.exemplars[i].Timestamp.AsTime().Before(n.exemplars[i-1].Timestamp.AsTime()) { + rIdx = i + } else { + rIdx = i - 1 + } + } + + } + + // If all existing exemplar are smaller than new exemplar, + // then the exemplar should be inserted at the end. + if nIdx == -1 { + nIdx = len(n.exemplars) + } + // Here, we have the following relationships: + // n.exemplars[nIdx-1].Value < e.Value (if nIdx > 0) + // e.Value <= n.exemplars[nIdx].Value (if nIdx < len(n.exemplars)) + + if otIdx != -1 && e.Timestamp.AsTime().Sub(ot) > n.ttl { + // If the oldest exemplar has expired, then replace it with the new exemplar. + rIdx = otIdx + } else { + // In the previous for loop, when calculating the closest pair of exemplars, + // we did not take into account the newly inserted exemplar. + // So we need to calculate with the newly inserted exemplar again. + elog := math.Log(e.GetValue()) + if nIdx > 0 { + diff := math.Abs(elog - math.Log(n.exemplars[nIdx-1].GetValue())) + if diff < md { + // The value we are about to insert is closer to the previous exemplar at the insertion point than what we calculated before in rIdx. + // v--rIdx + // |-----------x-n-----------x----------------x----x-----| + // nIdx-1--^ ^--new exemplar value + // Do not make the spread worse, replace nIdx-1 and not rIdx. + md = diff + rIdx = nIdx - 1 + } + } + if nIdx < len(n.exemplars) { + diff := math.Abs(math.Log(n.exemplars[nIdx].GetValue()) - elog) + if diff < md { + // The value we are about to insert is closer to the next exemplar at the insertion point than what we calculated before in rIdx. + // v--rIdx + // |-----------x-----------n-x----------------x----x-----| + // new exemplar value--^ ^--nIdx + // Do not make the spread worse, replace nIdx-1 and not rIdx. + rIdx = nIdx + } + } + } + + // Adjust the slice according to rIdx and nIdx. + switch { + case rIdx == nIdx: + n.exemplars[nIdx] = e + case rIdx < nIdx: + n.exemplars = append(n.exemplars[:rIdx], append(n.exemplars[rIdx+1:nIdx], append([]*dto.Exemplar{e}, n.exemplars[nIdx:]...)...)...) + case rIdx > nIdx: + n.exemplars = append(n.exemplars[:nIdx], append([]*dto.Exemplar{e}, append(n.exemplars[nIdx:rIdx], n.exemplars[rIdx+1:]...)...)...) + } +} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/internal/go_collector_options.go b/vendor/github.com/prometheus/client_golang/prometheus/internal/go_collector_options.go index 723b45d64..a4fa6eabd 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/internal/go_collector_options.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/internal/go_collector_options.go @@ -30,3 +30,5 @@ type GoCollectorOptions struct { RuntimeMetricSumForHist map[string]string RuntimeMetricRules []GoCollectorRule } + +var GoCollectorDefaultRuntimeMetrics = regexp.MustCompile(`/gc/gogc:percent|/gc/gomemlimit:bytes|/sched/gomaxprocs:threads`) diff --git a/vendor/github.com/prometheus/client_golang/prometheus/metric.go b/vendor/github.com/prometheus/client_golang/prometheus/metric.go index f018e5723..9d9b81ab4 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/metric.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/metric.go @@ -234,7 +234,7 @@ func NewMetricWithExemplars(m Metric, exemplars ...Exemplar) (Metric, error) { ) for i, e := range exemplars { ts := e.Timestamp - if ts == (time.Time{}) { + if ts.IsZero() { ts = now } exs[i], err = newExemplar(e.Value, ts, e.Labels) diff --git a/vendor/github.com/prometheus/client_golang/prometheus/process_collector.go b/vendor/github.com/prometheus/client_golang/prometheus/process_collector.go index 8548dd18e..62a4e7ad9 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/process_collector.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/process_collector.go @@ -22,14 +22,15 @@ import ( ) type processCollector struct { - collectFn func(chan<- Metric) - pidFn func() (int, error) - reportErrors bool - cpuTotal *Desc - openFDs, maxFDs *Desc - vsize, maxVsize *Desc - rss *Desc - startTime *Desc + collectFn func(chan<- Metric) + pidFn func() (int, error) + reportErrors bool + cpuTotal *Desc + openFDs, maxFDs *Desc + vsize, maxVsize *Desc + rss *Desc + startTime *Desc + inBytes, outBytes *Desc } // ProcessCollectorOpts defines the behavior of a process metrics collector @@ -100,6 +101,16 @@ func NewProcessCollector(opts ProcessCollectorOpts) Collector { "Start time of the process since unix epoch in seconds.", nil, nil, ), + inBytes: NewDesc( + ns+"process_network_receive_bytes_total", + "Number of bytes received by the process over the network.", + nil, nil, + ), + outBytes: NewDesc( + ns+"process_network_transmit_bytes_total", + "Number of bytes sent by the process over the network.", + nil, nil, + ), } if opts.PidFn == nil { @@ -129,6 +140,8 @@ func (c *processCollector) Describe(ch chan<- *Desc) { ch <- c.maxVsize ch <- c.rss ch <- c.startTime + ch <- c.inBytes + ch <- c.outBytes } // Collect returns the current state of all metrics of the collector. diff --git a/vendor/github.com/prometheus/client_golang/prometheus/process_collector_other.go b/vendor/github.com/prometheus/client_golang/prometheus/process_collector_other.go index 8c1136cee..14d56d2d0 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/process_collector_other.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/process_collector_other.go @@ -63,4 +63,18 @@ func (c *processCollector) processCollect(ch chan<- Metric) { } else { c.reportError(ch, nil, err) } + + if netstat, err := p.Netstat(); err == nil { + var inOctets, outOctets float64 + if netstat.IpExt.InOctets != nil { + inOctets = *netstat.IpExt.InOctets + } + if netstat.IpExt.OutOctets != nil { + outOctets = *netstat.IpExt.OutOctets + } + ch <- MustNewConstMetric(c.inBytes, CounterValue, inOctets) + ch <- MustNewConstMetric(c.outBytes, CounterValue, outOctets) + } else { + c.reportError(ch, nil, err) + } } diff --git a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/delegator.go b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/delegator.go index 9819917b8..315eab5f1 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/delegator.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/delegator.go @@ -76,6 +76,12 @@ func (r *responseWriterDelegator) Write(b []byte) (int, error) { return n, err } +// Unwrap lets http.ResponseController get the underlying http.ResponseWriter, +// by implementing the [rwUnwrapper](https://cs.opensource.google/go/go/+/refs/tags/go1.21.4:src/net/http/responsecontroller.go;l=42-44) interface. +func (r *responseWriterDelegator) Unwrap() http.ResponseWriter { + return r.ResponseWriter +} + type ( closeNotifierDelegator struct{ *responseWriterDelegator } flusherDelegator struct{ *responseWriterDelegator } diff --git a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/http.go b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/http.go index 09b8d2fbe..e598e66e6 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/http.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/http.go @@ -38,12 +38,13 @@ import ( "io" "net/http" "strconv" - "strings" "sync" "time" + "github.com/klauspost/compress/zstd" "github.com/prometheus/common/expfmt" + "github.com/prometheus/client_golang/internal/github.com/golang/gddo/httputil" "github.com/prometheus/client_golang/prometheus" ) @@ -54,6 +55,18 @@ const ( processStartTimeHeader = "Process-Start-Time-Unix" ) +// Compression represents the content encodings handlers support for the HTTP +// responses. +type Compression string + +const ( + Identity Compression = "identity" + Gzip Compression = "gzip" + Zstd Compression = "zstd" +) + +var defaultCompressionFormats = []Compression{Identity, Gzip, Zstd} + var gzipPool = sync.Pool{ New: func() interface{} { return gzip.NewWriter(nil) @@ -122,6 +135,18 @@ func HandlerForTransactional(reg prometheus.TransactionalGatherer, opts HandlerO } } + // Select compression formats to offer based on default or user choice. + var compressions []string + if !opts.DisableCompression { + offers := defaultCompressionFormats + if len(opts.OfferedCompressions) > 0 { + offers = opts.OfferedCompressions + } + for _, comp := range offers { + compressions = append(compressions, string(comp)) + } + } + h := http.HandlerFunc(func(rsp http.ResponseWriter, req *http.Request) { if !opts.ProcessStartTime.IsZero() { rsp.Header().Set(processStartTimeHeader, strconv.FormatInt(opts.ProcessStartTime.Unix(), 10)) @@ -165,21 +190,23 @@ func HandlerForTransactional(reg prometheus.TransactionalGatherer, opts HandlerO } else { contentType = expfmt.Negotiate(req.Header) } - header := rsp.Header() - header.Set(contentTypeHeader, string(contentType)) + rsp.Header().Set(contentTypeHeader, string(contentType)) - w := io.Writer(rsp) - if !opts.DisableCompression && gzipAccepted(req.Header) { - header.Set(contentEncodingHeader, "gzip") - gz := gzipPool.Get().(*gzip.Writer) - defer gzipPool.Put(gz) + w, encodingHeader, closeWriter, err := negotiateEncodingWriter(req, rsp, compressions) + if err != nil { + if opts.ErrorLog != nil { + opts.ErrorLog.Println("error getting writer", err) + } + w = io.Writer(rsp) + encodingHeader = string(Identity) + } - gz.Reset(w) - defer gz.Close() + defer closeWriter() - w = gz + // Set Content-Encoding only when data is compressed + if encodingHeader != string(Identity) { + rsp.Header().Set(contentEncodingHeader, encodingHeader) } - enc := expfmt.NewEncoder(w, contentType) // handleError handles the error according to opts.ErrorHandling @@ -343,9 +370,19 @@ type HandlerOpts struct { // no effect on the HTTP status code because ErrorHandling is set to // ContinueOnError. Registry prometheus.Registerer - // If DisableCompression is true, the handler will never compress the - // response, even if requested by the client. + // DisableCompression disables the response encoding (compression) and + // encoding negotiation. If true, the handler will + // never compress the response, even if requested + // by the client and the OfferedCompressions field is set. DisableCompression bool + // OfferedCompressions is a set of encodings (compressions) handler will + // try to offer when negotiating with the client. This defaults to identity, gzip + // and zstd. + // NOTE: If handler can't agree with the client on the encodings or + // unsupported or empty encodings are set in OfferedCompressions, + // handler always fallbacks to no compression (identity), for + // compatibility reasons. In such cases ErrorLog will be used if set. + OfferedCompressions []Compression // The number of concurrent HTTP requests is limited to // MaxRequestsInFlight. Additional requests are responded to with 503 // Service Unavailable and a suitable message in the body. If @@ -381,19 +418,6 @@ type HandlerOpts struct { ProcessStartTime time.Time } -// gzipAccepted returns whether the client will accept gzip-encoded content. -func gzipAccepted(header http.Header) bool { - a := header.Get(acceptEncodingHeader) - parts := strings.Split(a, ",") - for _, part := range parts { - part = strings.TrimSpace(part) - if part == "gzip" || strings.HasPrefix(part, "gzip;") { - return true - } - } - return false -} - // httpError removes any content-encoding header and then calls http.Error with // the provided error and http.StatusInternalServerError. Error contents is // supposed to be uncompressed plain text. Same as with a plain http.Error, this @@ -406,3 +430,38 @@ func httpError(rsp http.ResponseWriter, err error) { http.StatusInternalServerError, ) } + +// negotiateEncodingWriter reads the Accept-Encoding header from a request and +// selects the right compression based on an allow-list of supported +// compressions. It returns a writer implementing the compression and an the +// correct value that the caller can set in the response header. +func negotiateEncodingWriter(r *http.Request, rw io.Writer, compressions []string) (_ io.Writer, encodingHeaderValue string, closeWriter func(), _ error) { + if len(compressions) == 0 { + return rw, string(Identity), func() {}, nil + } + + // TODO(mrueg): Replace internal/github.com/gddo once https://github.com/golang/go/issues/19307 is implemented. + selected := httputil.NegotiateContentEncoding(r, compressions) + + switch selected { + case "zstd": + // TODO(mrueg): Replace klauspost/compress with stdlib implementation once https://github.com/golang/go/issues/62513 is implemented. + z, err := zstd.NewWriter(rw, zstd.WithEncoderLevel(zstd.SpeedFastest)) + if err != nil { + return nil, "", func() {}, err + } + + z.Reset(rw) + return z, selected, func() { _ = z.Close() }, nil + case "gzip": + gz := gzipPool.Get().(*gzip.Writer) + gz.Reset(rw) + return gz, selected, func() { _ = gz.Close(); gzipPool.Put(gz) }, nil + case "identity": + // This means the content is not compressed. + return rw, selected, func() {}, nil + default: + // The content encoding was not implemented yet. + return nil, "", func() {}, fmt.Errorf("content compression format not recognized: %s. Valid formats are: %s", selected, defaultCompressionFormats) + } +} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/registry.go b/vendor/github.com/prometheus/client_golang/prometheus/registry.go index 5e2ced25a..c6fd2f58b 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/registry.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/registry.go @@ -314,16 +314,17 @@ func (r *Registry) Register(c Collector) error { if dimHash != desc.dimHash { return fmt.Errorf("a previously registered descriptor with the same fully-qualified name as %s has different label names or a different help string", desc) } - } else { - // ...then check the new descriptors already seen. - if dimHash, exists := newDimHashesByName[desc.fqName]; exists { - if dimHash != desc.dimHash { - return fmt.Errorf("descriptors reported by collector have inconsistent label names or help strings for the same fully-qualified name, offender is %s", desc) - } - } else { - newDimHashesByName[desc.fqName] = desc.dimHash + continue + } + + // ...then check the new descriptors already seen. + if dimHash, exists := newDimHashesByName[desc.fqName]; exists { + if dimHash != desc.dimHash { + return fmt.Errorf("descriptors reported by collector have inconsistent label names or help strings for the same fully-qualified name, offender is %s", desc) } + continue } + newDimHashesByName[desc.fqName] = desc.dimHash } // A Collector yielding no Desc at all is considered unchecked. if len(newDescIDs) == 0 { diff --git a/vendor/github.com/prometheus/client_golang/prometheus/summary.go b/vendor/github.com/prometheus/client_golang/prometheus/summary.go index 146270444..1ab0e4796 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/summary.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/summary.go @@ -783,3 +783,45 @@ func MustNewConstSummary( } return m } + +// NewConstSummaryWithCreatedTimestamp does the same thing as NewConstSummary but sets the created timestamp. +func NewConstSummaryWithCreatedTimestamp( + desc *Desc, + count uint64, + sum float64, + quantiles map[float64]float64, + ct time.Time, + labelValues ...string, +) (Metric, error) { + if desc.err != nil { + return nil, desc.err + } + if err := validateLabelValues(labelValues, len(desc.variableLabels.names)); err != nil { + return nil, err + } + return &constSummary{ + desc: desc, + count: count, + sum: sum, + quantiles: quantiles, + labelPairs: MakeLabelPairs(desc, labelValues), + createdTs: timestamppb.New(ct), + }, nil +} + +// MustNewConstSummaryWithCreatedTimestamp is a version of NewConstSummaryWithCreatedTimestamp that panics where +// NewConstSummaryWithCreatedTimestamp would have returned an error. +func MustNewConstSummaryWithCreatedTimestamp( + desc *Desc, + count uint64, + sum float64, + quantiles map[float64]float64, + ct time.Time, + labelValues ...string, +) Metric { + m, err := NewConstSummaryWithCreatedTimestamp(desc, count, sum, quantiles, ct, labelValues...) + if err != nil { + panic(err) + } + return m +} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/vec.go b/vendor/github.com/prometheus/client_golang/prometheus/vec.go index 955cfd59f..2c808eece 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/vec.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/vec.go @@ -507,7 +507,7 @@ func (m *metricMap) getOrCreateMetricWithLabelValues( return metric } -// getOrCreateMetricWithLabelValues retrieves the metric by hash and label value +// getOrCreateMetricWithLabels retrieves the metric by hash and label value // or creates it and returns the new one. // // This function holds the mutex. diff --git a/vendor/github.com/prometheus/common/expfmt/decode.go b/vendor/github.com/prometheus/common/expfmt/decode.go index 25cfaa216..1448439b7 100644 --- a/vendor/github.com/prometheus/common/expfmt/decode.go +++ b/vendor/github.com/prometheus/common/expfmt/decode.go @@ -45,7 +45,7 @@ func ResponseFormat(h http.Header) Format { mediatype, params, err := mime.ParseMediaType(ct) if err != nil { - return fmtUnknown + return FmtUnknown } const textType = "text/plain" @@ -53,21 +53,21 @@ func ResponseFormat(h http.Header) Format { switch mediatype { case ProtoType: if p, ok := params["proto"]; ok && p != ProtoProtocol { - return fmtUnknown + return FmtUnknown } if e, ok := params["encoding"]; ok && e != "delimited" { - return fmtUnknown + return FmtUnknown } - return fmtProtoDelim + return FmtProtoDelim case textType: if v, ok := params["version"]; ok && v != TextVersion { - return fmtUnknown + return FmtUnknown } - return fmtText + return FmtText } - return fmtUnknown + return FmtUnknown } // NewDecoder returns a new decoder based on the given input format. diff --git a/vendor/github.com/prometheus/common/expfmt/encode.go b/vendor/github.com/prometheus/common/expfmt/encode.go index 7f6cbe7d2..cf0c150c2 100644 --- a/vendor/github.com/prometheus/common/expfmt/encode.go +++ b/vendor/github.com/prometheus/common/expfmt/encode.go @@ -21,9 +21,10 @@ import ( "google.golang.org/protobuf/encoding/protodelim" "google.golang.org/protobuf/encoding/prototext" - "github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg" "github.com/prometheus/common/model" + "github.com/munnerz/goautoneg" + dto "github.com/prometheus/client_model/go" ) @@ -76,18 +77,18 @@ func Negotiate(h http.Header) Format { if ac.Type+"/"+ac.SubType == ProtoType && ac.Params["proto"] == ProtoProtocol { switch ac.Params["encoding"] { case "delimited": - return fmtProtoDelim + escapingScheme + return FmtProtoDelim + escapingScheme case "text": - return fmtProtoText + escapingScheme + return FmtProtoText + escapingScheme case "compact-text": - return fmtProtoCompact + escapingScheme + return FmtProtoCompact + escapingScheme } } if ac.Type == "text" && ac.SubType == "plain" && (ver == TextVersion || ver == "") { - return fmtText + escapingScheme + return FmtText + escapingScheme } } - return fmtText + escapingScheme + return FmtText + escapingScheme } // NegotiateIncludingOpenMetrics works like Negotiate but includes @@ -109,26 +110,26 @@ func NegotiateIncludingOpenMetrics(h http.Header) Format { if ac.Type+"/"+ac.SubType == ProtoType && ac.Params["proto"] == ProtoProtocol { switch ac.Params["encoding"] { case "delimited": - return fmtProtoDelim + escapingScheme + return FmtProtoDelim + escapingScheme case "text": - return fmtProtoText + escapingScheme + return FmtProtoText + escapingScheme case "compact-text": - return fmtProtoCompact + escapingScheme + return FmtProtoCompact + escapingScheme } } if ac.Type == "text" && ac.SubType == "plain" && (ver == TextVersion || ver == "") { - return fmtText + escapingScheme + return FmtText + escapingScheme } if ac.Type+"/"+ac.SubType == OpenMetricsType && (ver == OpenMetricsVersion_0_0_1 || ver == OpenMetricsVersion_1_0_0 || ver == "") { switch ver { case OpenMetricsVersion_1_0_0: - return fmtOpenMetrics_1_0_0 + escapingScheme + return FmtOpenMetrics_1_0_0 + escapingScheme default: - return fmtOpenMetrics_0_0_1 + escapingScheme + return FmtOpenMetrics_0_0_1 + escapingScheme } } } - return fmtText + escapingScheme + return FmtText + escapingScheme } // NewEncoder returns a new encoder based on content type negotiation. All diff --git a/vendor/github.com/prometheus/common/expfmt/expfmt.go b/vendor/github.com/prometheus/common/expfmt/expfmt.go index 051b38cd1..d942af8ed 100644 --- a/vendor/github.com/prometheus/common/expfmt/expfmt.go +++ b/vendor/github.com/prometheus/common/expfmt/expfmt.go @@ -32,24 +32,31 @@ type Format string // it on the wire, new content-type strings will have to be agreed upon and // added here. const ( - TextVersion = "0.0.4" - ProtoType = `application/vnd.google.protobuf` - ProtoProtocol = `io.prometheus.client.MetricFamily` - protoFmt = ProtoType + "; proto=" + ProtoProtocol + ";" + TextVersion = "0.0.4" + ProtoType = `application/vnd.google.protobuf` + ProtoProtocol = `io.prometheus.client.MetricFamily` + // Deprecated: Use expfmt.NewFormat(expfmt.TypeProtoCompact) instead. + ProtoFmt = ProtoType + "; proto=" + ProtoProtocol + ";" OpenMetricsType = `application/openmetrics-text` OpenMetricsVersion_0_0_1 = "0.0.1" OpenMetricsVersion_1_0_0 = "1.0.0" - // The Content-Type values for the different wire protocols. Note that these - // values are now unexported. If code was relying on comparisons to these - // constants, instead use FormatType(). - fmtUnknown Format = `` - fmtText Format = `text/plain; version=` + TextVersion + `; charset=utf-8` - fmtProtoDelim Format = protoFmt + ` encoding=delimited` - fmtProtoText Format = protoFmt + ` encoding=text` - fmtProtoCompact Format = protoFmt + ` encoding=compact-text` - fmtOpenMetrics_1_0_0 Format = OpenMetricsType + `; version=` + OpenMetricsVersion_1_0_0 + `; charset=utf-8` - fmtOpenMetrics_0_0_1 Format = OpenMetricsType + `; version=` + OpenMetricsVersion_0_0_1 + `; charset=utf-8` + // The Content-Type values for the different wire protocols. Do not do direct + // comparisons to these constants, instead use the comparison functions. + // Deprecated: Use expfmt.NewFormat(expfmt.TypeUnknown) instead. + FmtUnknown Format = `` + // Deprecated: Use expfmt.NewFormat(expfmt.TypeTextPlain) instead. + FmtText Format = `text/plain; version=` + TextVersion + `; charset=utf-8` + // Deprecated: Use expfmt.NewFormat(expfmt.TypeProtoDelim) instead. + FmtProtoDelim Format = ProtoFmt + ` encoding=delimited` + // Deprecated: Use expfmt.NewFormat(expfmt.TypeProtoText) instead. + FmtProtoText Format = ProtoFmt + ` encoding=text` + // Deprecated: Use expfmt.NewFormat(expfmt.TypeProtoCompact) instead. + FmtProtoCompact Format = ProtoFmt + ` encoding=compact-text` + // Deprecated: Use expfmt.NewFormat(expfmt.TypeOpenMetrics) instead. + FmtOpenMetrics_1_0_0 Format = OpenMetricsType + `; version=` + OpenMetricsVersion_1_0_0 + `; charset=utf-8` + // Deprecated: Use expfmt.NewFormat(expfmt.TypeOpenMetrics) instead. + FmtOpenMetrics_0_0_1 Format = OpenMetricsType + `; version=` + OpenMetricsVersion_0_0_1 + `; charset=utf-8` ) const ( @@ -79,17 +86,17 @@ const ( func NewFormat(t FormatType) Format { switch t { case TypeProtoCompact: - return fmtProtoCompact + return FmtProtoCompact case TypeProtoDelim: - return fmtProtoDelim + return FmtProtoDelim case TypeProtoText: - return fmtProtoText + return FmtProtoText case TypeTextPlain: - return fmtText + return FmtText case TypeOpenMetrics: - return fmtOpenMetrics_1_0_0 + return FmtOpenMetrics_1_0_0 default: - return fmtUnknown + return FmtUnknown } } @@ -97,12 +104,35 @@ func NewFormat(t FormatType) Format { // specified version number. func NewOpenMetricsFormat(version string) (Format, error) { if version == OpenMetricsVersion_0_0_1 { - return fmtOpenMetrics_0_0_1, nil + return FmtOpenMetrics_0_0_1, nil } if version == OpenMetricsVersion_1_0_0 { - return fmtOpenMetrics_1_0_0, nil + return FmtOpenMetrics_1_0_0, nil } - return fmtUnknown, fmt.Errorf("unknown open metrics version string") + return FmtUnknown, fmt.Errorf("unknown open metrics version string") +} + +// WithEscapingScheme returns a copy of Format with the specified escaping +// scheme appended to the end. If an escaping scheme already exists it is +// removed. +func (f Format) WithEscapingScheme(s model.EscapingScheme) Format { + var terms []string + for _, p := range strings.Split(string(f), ";") { + toks := strings.Split(p, "=") + if len(toks) != 2 { + trimmed := strings.TrimSpace(p) + if len(trimmed) > 0 { + terms = append(terms, trimmed) + } + continue + } + key := strings.TrimSpace(toks[0]) + if key != model.EscapingKey { + terms = append(terms, strings.TrimSpace(p)) + } + } + terms = append(terms, model.EscapingKey+"="+s.String()) + return Format(strings.Join(terms, "; ")) } // FormatType deduces an overall FormatType for the given format. diff --git a/vendor/github.com/prometheus/common/expfmt/openmetrics_create.go b/vendor/github.com/prometheus/common/expfmt/openmetrics_create.go index 353c5e93f..11c8ff4b9 100644 --- a/vendor/github.com/prometheus/common/expfmt/openmetrics_create.go +++ b/vendor/github.com/prometheus/common/expfmt/openmetrics_create.go @@ -477,7 +477,7 @@ func writeOpenMetricsNameAndLabelPairs( if name != "" { // If the name does not pass the legacy validity check, we must put the // metric name inside the braces, quoted. - if !model.IsValidLegacyMetricName(model.LabelValue(name)) { + if !model.IsValidLegacyMetricName(name) { metricInsideBraces = true err := w.WriteByte(separator) written++ diff --git a/vendor/github.com/prometheus/common/expfmt/text_create.go b/vendor/github.com/prometheus/common/expfmt/text_create.go index f9b8265a9..4b86434b3 100644 --- a/vendor/github.com/prometheus/common/expfmt/text_create.go +++ b/vendor/github.com/prometheus/common/expfmt/text_create.go @@ -354,7 +354,7 @@ func writeNameAndLabelPairs( if name != "" { // If the name does not pass the legacy validity check, we must put the // metric name inside the braces. - if !model.IsValidLegacyMetricName(model.LabelValue(name)) { + if !model.IsValidLegacyMetricName(name) { metricInsideBraces = true err := w.WriteByte(separator) written++ @@ -498,7 +498,7 @@ func writeInt(w enhancedWriter, i int64) (int, error) { // writeName writes a string as-is if it complies with the legacy naming // scheme, or escapes it in double quotes if not. func writeName(w enhancedWriter, name string) (int, error) { - if model.IsValidLegacyMetricName(model.LabelValue(name)) { + if model.IsValidLegacyMetricName(name) { return w.WriteString(name) } var written int diff --git a/vendor/github.com/prometheus/common/expfmt/text_parse.go b/vendor/github.com/prometheus/common/expfmt/text_parse.go index 26490211a..f085a923f 100644 --- a/vendor/github.com/prometheus/common/expfmt/text_parse.go +++ b/vendor/github.com/prometheus/common/expfmt/text_parse.go @@ -22,9 +22,9 @@ import ( "math" "strconv" "strings" + "unicode/utf8" dto "github.com/prometheus/client_model/go" - "google.golang.org/protobuf/proto" "github.com/prometheus/common/model" @@ -60,6 +60,7 @@ type TextParser struct { currentMF *dto.MetricFamily currentMetric *dto.Metric currentLabelPair *dto.LabelPair + currentLabelPairs []*dto.LabelPair // Temporarily stores label pairs while parsing a metric line. // The remaining member variables are only used for summaries/histograms. currentLabels map[string]string // All labels including '__name__' but excluding 'quantile'/'le' @@ -74,6 +75,9 @@ type TextParser struct { // count and sum of that summary/histogram. currentIsSummaryCount, currentIsSummarySum bool currentIsHistogramCount, currentIsHistogramSum bool + // These indicate if the metric name from the current line being parsed is inside + // braces and if that metric name was found respectively. + currentMetricIsInsideBraces, currentMetricInsideBracesIsPresent bool } // TextToMetricFamilies reads 'in' as the simple and flat text-based exchange @@ -137,12 +141,15 @@ func (p *TextParser) reset(in io.Reader) { } p.currentQuantile = math.NaN() p.currentBucket = math.NaN() + p.currentMF = nil } // startOfLine represents the state where the next byte read from p.buf is the // start of a line (or whitespace leading up to it). func (p *TextParser) startOfLine() stateFn { p.lineCount++ + p.currentMetricIsInsideBraces = false + p.currentMetricInsideBracesIsPresent = false if p.skipBlankTab(); p.err != nil { // This is the only place that we expect to see io.EOF, // which is not an error but the signal that we are done. @@ -158,6 +165,9 @@ func (p *TextParser) startOfLine() stateFn { return p.startComment case '\n': return p.startOfLine // Empty line, start the next one. + case '{': + p.currentMetricIsInsideBraces = true + return p.readingLabels } return p.readingMetricName } @@ -275,6 +285,8 @@ func (p *TextParser) startLabelName() stateFn { return nil // Unexpected end of input. } if p.currentByte == '}' { + p.currentMetric.Label = append(p.currentMetric.Label, p.currentLabelPairs...) + p.currentLabelPairs = nil if p.skipBlankTab(); p.err != nil { return nil // Unexpected end of input. } @@ -287,6 +299,45 @@ func (p *TextParser) startLabelName() stateFn { p.parseError(fmt.Sprintf("invalid label name for metric %q", p.currentMF.GetName())) return nil } + if p.skipBlankTabIfCurrentBlankTab(); p.err != nil { + return nil // Unexpected end of input. + } + if p.currentByte != '=' { + if p.currentMetricIsInsideBraces { + if p.currentMetricInsideBracesIsPresent { + p.parseError(fmt.Sprintf("multiple metric names for metric %q", p.currentMF.GetName())) + return nil + } + switch p.currentByte { + case ',': + p.setOrCreateCurrentMF() + if p.currentMF.Type == nil { + p.currentMF.Type = dto.MetricType_UNTYPED.Enum() + } + p.currentMetric = &dto.Metric{} + p.currentMetricInsideBracesIsPresent = true + return p.startLabelName + case '}': + p.setOrCreateCurrentMF() + if p.currentMF.Type == nil { + p.currentMF.Type = dto.MetricType_UNTYPED.Enum() + } + p.currentMetric = &dto.Metric{} + p.currentMetric.Label = append(p.currentMetric.Label, p.currentLabelPairs...) + p.currentLabelPairs = nil + if p.skipBlankTab(); p.err != nil { + return nil // Unexpected end of input. + } + return p.readingValue + default: + p.parseError(fmt.Sprintf("unexpected end of metric name %q", p.currentByte)) + return nil + } + } + p.parseError(fmt.Sprintf("expected '=' after label name, found %q", p.currentByte)) + p.currentLabelPairs = nil + return nil + } p.currentLabelPair = &dto.LabelPair{Name: proto.String(p.currentToken.String())} if p.currentLabelPair.GetName() == string(model.MetricNameLabel) { p.parseError(fmt.Sprintf("label name %q is reserved", model.MetricNameLabel)) @@ -296,23 +347,17 @@ func (p *TextParser) startLabelName() stateFn { // labels to 'real' labels. if !(p.currentMF.GetType() == dto.MetricType_SUMMARY && p.currentLabelPair.GetName() == model.QuantileLabel) && !(p.currentMF.GetType() == dto.MetricType_HISTOGRAM && p.currentLabelPair.GetName() == model.BucketLabel) { - p.currentMetric.Label = append(p.currentMetric.Label, p.currentLabelPair) - } - if p.skipBlankTabIfCurrentBlankTab(); p.err != nil { - return nil // Unexpected end of input. - } - if p.currentByte != '=' { - p.parseError(fmt.Sprintf("expected '=' after label name, found %q", p.currentByte)) - return nil + p.currentLabelPairs = append(p.currentLabelPairs, p.currentLabelPair) } // Check for duplicate label names. labels := make(map[string]struct{}) - for _, l := range p.currentMetric.Label { + for _, l := range p.currentLabelPairs { lName := l.GetName() if _, exists := labels[lName]; !exists { labels[lName] = struct{}{} } else { p.parseError(fmt.Sprintf("duplicate label names for metric %q", p.currentMF.GetName())) + p.currentLabelPairs = nil return nil } } @@ -345,6 +390,7 @@ func (p *TextParser) startLabelValue() stateFn { if p.currentQuantile, p.err = parseFloat(p.currentLabelPair.GetValue()); p.err != nil { // Create a more helpful error message. p.parseError(fmt.Sprintf("expected float as value for 'quantile' label, got %q", p.currentLabelPair.GetValue())) + p.currentLabelPairs = nil return nil } } else { @@ -371,12 +417,19 @@ func (p *TextParser) startLabelValue() stateFn { return p.startLabelName case '}': + if p.currentMF == nil { + p.parseError("invalid metric name") + return nil + } + p.currentMetric.Label = append(p.currentMetric.Label, p.currentLabelPairs...) + p.currentLabelPairs = nil if p.skipBlankTab(); p.err != nil { return nil // Unexpected end of input. } return p.readingValue default: p.parseError(fmt.Sprintf("unexpected end of label value %q", p.currentLabelPair.GetValue())) + p.currentLabelPairs = nil return nil } } @@ -585,6 +638,8 @@ func (p *TextParser) readTokenUntilNewline(recognizeEscapeSequence bool) { p.currentToken.WriteByte(p.currentByte) case 'n': p.currentToken.WriteByte('\n') + case '"': + p.currentToken.WriteByte('"') default: p.parseError(fmt.Sprintf("invalid escape sequence '\\%c'", p.currentByte)) return @@ -610,13 +665,45 @@ func (p *TextParser) readTokenUntilNewline(recognizeEscapeSequence bool) { // but not into p.currentToken. func (p *TextParser) readTokenAsMetricName() { p.currentToken.Reset() + // A UTF-8 metric name must be quoted and may have escaped characters. + quoted := false + escaped := false if !isValidMetricNameStart(p.currentByte) { return } - for { - p.currentToken.WriteByte(p.currentByte) + for p.err == nil { + if escaped { + switch p.currentByte { + case '\\': + p.currentToken.WriteByte(p.currentByte) + case 'n': + p.currentToken.WriteByte('\n') + case '"': + p.currentToken.WriteByte('"') + default: + p.parseError(fmt.Sprintf("invalid escape sequence '\\%c'", p.currentByte)) + return + } + escaped = false + } else { + switch p.currentByte { + case '"': + quoted = !quoted + if !quoted { + p.currentByte, p.err = p.buf.ReadByte() + return + } + case '\n': + p.parseError(fmt.Sprintf("metric name %q contains unescaped new-line", p.currentToken.String())) + return + case '\\': + escaped = true + default: + p.currentToken.WriteByte(p.currentByte) + } + } p.currentByte, p.err = p.buf.ReadByte() - if p.err != nil || !isValidMetricNameContinuation(p.currentByte) { + if !isValidMetricNameContinuation(p.currentByte, quoted) || (!quoted && p.currentByte == ' ') { return } } @@ -628,13 +715,45 @@ func (p *TextParser) readTokenAsMetricName() { // but not into p.currentToken. func (p *TextParser) readTokenAsLabelName() { p.currentToken.Reset() + // A UTF-8 label name must be quoted and may have escaped characters. + quoted := false + escaped := false if !isValidLabelNameStart(p.currentByte) { return } - for { - p.currentToken.WriteByte(p.currentByte) + for p.err == nil { + if escaped { + switch p.currentByte { + case '\\': + p.currentToken.WriteByte(p.currentByte) + case 'n': + p.currentToken.WriteByte('\n') + case '"': + p.currentToken.WriteByte('"') + default: + p.parseError(fmt.Sprintf("invalid escape sequence '\\%c'", p.currentByte)) + return + } + escaped = false + } else { + switch p.currentByte { + case '"': + quoted = !quoted + if !quoted { + p.currentByte, p.err = p.buf.ReadByte() + return + } + case '\n': + p.parseError(fmt.Sprintf("label name %q contains unescaped new-line", p.currentToken.String())) + return + case '\\': + escaped = true + default: + p.currentToken.WriteByte(p.currentByte) + } + } p.currentByte, p.err = p.buf.ReadByte() - if p.err != nil || !isValidLabelNameContinuation(p.currentByte) { + if !isValidLabelNameContinuation(p.currentByte, quoted) || (!quoted && p.currentByte == '=') { return } } @@ -660,6 +779,7 @@ func (p *TextParser) readTokenAsLabelValue() { p.currentToken.WriteByte('\n') default: p.parseError(fmt.Sprintf("invalid escape sequence '\\%c'", p.currentByte)) + p.currentLabelPairs = nil return } escaped = false @@ -718,19 +838,19 @@ func (p *TextParser) setOrCreateCurrentMF() { } func isValidLabelNameStart(b byte) bool { - return (b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') || b == '_' + return (b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') || b == '_' || b == '"' } -func isValidLabelNameContinuation(b byte) bool { - return isValidLabelNameStart(b) || (b >= '0' && b <= '9') +func isValidLabelNameContinuation(b byte, quoted bool) bool { + return isValidLabelNameStart(b) || (b >= '0' && b <= '9') || (quoted && utf8.ValidString(string(b))) } func isValidMetricNameStart(b byte) bool { return isValidLabelNameStart(b) || b == ':' } -func isValidMetricNameContinuation(b byte) bool { - return isValidLabelNameContinuation(b) || b == ':' +func isValidMetricNameContinuation(b byte, quoted bool) bool { + return isValidLabelNameContinuation(b, quoted) || b == ':' } func isBlankOrTab(b byte) bool { diff --git a/vendor/github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg/README.txt b/vendor/github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg/README.txt deleted file mode 100644 index 7723656d5..000000000 --- a/vendor/github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg/README.txt +++ /dev/null @@ -1,67 +0,0 @@ -PACKAGE - -package goautoneg -import "bitbucket.org/ww/goautoneg" - -HTTP Content-Type Autonegotiation. - -The functions in this package implement the behaviour specified in -http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html - -Copyright (c) 2011, Open Knowledge Foundation Ltd. -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 Open Knowledge Foundation Ltd. 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. - - -FUNCTIONS - -func Negotiate(header string, alternatives []string) (content_type string) -Negotiate the most appropriate content_type given the accept header -and a list of alternatives. - -func ParseAccept(header string) (accept []Accept) -Parse an Accept Header string returning a sorted list -of clauses - - -TYPES - -type Accept struct { - Type, SubType string - Q float32 - Params map[string]string -} -Structure to represent a clause in an HTTP Accept Header - - -SUBDIRECTORIES - - .hg diff --git a/vendor/github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg/autoneg.go b/vendor/github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg/autoneg.go deleted file mode 100644 index a21b9d15d..000000000 --- a/vendor/github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg/autoneg.go +++ /dev/null @@ -1,160 +0,0 @@ -/* -Copyright (c) 2011, Open Knowledge Foundation Ltd. -All rights reserved. - -HTTP Content-Type Autonegotiation. - -The functions in this package implement the behaviour specified in -http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html - -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 Open Knowledge Foundation Ltd. 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. -*/ -package goautoneg - -import ( - "sort" - "strconv" - "strings" -) - -// Structure to represent a clause in an HTTP Accept Header -type Accept struct { - Type, SubType string - Q float64 - Params map[string]string -} - -// For internal use, so that we can use the sort interface -type accept_slice []Accept - -func (accept accept_slice) Len() int { - slice := []Accept(accept) - return len(slice) -} - -func (accept accept_slice) Less(i, j int) bool { - slice := []Accept(accept) - ai, aj := slice[i], slice[j] - if ai.Q > aj.Q { - return true - } - if ai.Type != "*" && aj.Type == "*" { - return true - } - if ai.SubType != "*" && aj.SubType == "*" { - return true - } - return false -} - -func (accept accept_slice) Swap(i, j int) { - slice := []Accept(accept) - slice[i], slice[j] = slice[j], slice[i] -} - -// Parse an Accept Header string returning a sorted list -// of clauses -func ParseAccept(header string) (accept []Accept) { - parts := strings.Split(header, ",") - accept = make([]Accept, 0, len(parts)) - for _, part := range parts { - part := strings.Trim(part, " ") - - a := Accept{} - a.Params = make(map[string]string) - a.Q = 1.0 - - mrp := strings.Split(part, ";") - - media_range := mrp[0] - sp := strings.Split(media_range, "/") - a.Type = strings.Trim(sp[0], " ") - - switch { - case len(sp) == 1 && a.Type == "*": - a.SubType = "*" - case len(sp) == 2: - a.SubType = strings.Trim(sp[1], " ") - default: - continue - } - - if len(mrp) == 1 { - accept = append(accept, a) - continue - } - - for _, param := range mrp[1:] { - sp := strings.SplitN(param, "=", 2) - if len(sp) != 2 { - continue - } - token := strings.Trim(sp[0], " ") - if token == "q" { - a.Q, _ = strconv.ParseFloat(sp[1], 32) - } else { - a.Params[token] = strings.Trim(sp[1], " ") - } - } - - accept = append(accept, a) - } - - slice := accept_slice(accept) - sort.Sort(slice) - - return -} - -// Negotiate the most appropriate content_type given the accept header -// and a list of alternatives. -func Negotiate(header string, alternatives []string) (content_type string) { - asp := make([][]string, 0, len(alternatives)) - for _, ctype := range alternatives { - asp = append(asp, strings.SplitN(ctype, "/", 2)) - } - for _, clause := range ParseAccept(header) { - for i, ctsp := range asp { - if clause.Type == ctsp[0] && clause.SubType == ctsp[1] { - content_type = alternatives[i] - return - } - if clause.Type == ctsp[0] && clause.SubType == "*" { - content_type = alternatives[i] - return - } - if clause.Type == "*" && clause.SubType == "*" { - content_type = alternatives[i] - return - } - } - } - return -} diff --git a/vendor/github.com/prometheus/common/model/labels.go b/vendor/github.com/prometheus/common/model/labels.go index 3317ce22f..73b7aa3e6 100644 --- a/vendor/github.com/prometheus/common/model/labels.go +++ b/vendor/github.com/prometheus/common/model/labels.go @@ -97,26 +97,35 @@ var LabelNameRE = regexp.MustCompile("^[a-zA-Z_][a-zA-Z0-9_]*$") // therewith. type LabelName string -// IsValid returns true iff name matches the pattern of LabelNameRE for legacy -// names, and iff it's valid UTF-8 if NameValidationScheme is set to -// UTF8Validation. For the legacy matching, it does not use LabelNameRE for the -// check but a much faster hardcoded implementation. +// IsValid returns true iff the name matches the pattern of LabelNameRE when +// NameValidationScheme is set to LegacyValidation, or valid UTF-8 if +// NameValidationScheme is set to UTF8Validation. func (ln LabelName) IsValid() bool { if len(ln) == 0 { return false } switch NameValidationScheme { case LegacyValidation: - for i, b := range ln { - if !((b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') || b == '_' || (b >= '0' && b <= '9' && i > 0)) { - return false - } - } + return ln.IsValidLegacy() case UTF8Validation: return utf8.ValidString(string(ln)) default: panic(fmt.Sprintf("Invalid name validation scheme requested: %d", NameValidationScheme)) } +} + +// IsValidLegacy returns true iff name matches the pattern of LabelNameRE for +// legacy names. It does not use LabelNameRE for the check but a much faster +// hardcoded implementation. +func (ln LabelName) IsValidLegacy() bool { + if len(ln) == 0 { + return false + } + for i, b := range ln { + if !((b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') || b == '_' || (b >= '0' && b <= '9' && i > 0)) { + return false + } + } return true } diff --git a/vendor/github.com/prometheus/common/model/labelset_string.go b/vendor/github.com/prometheus/common/model/labelset_string.go index 481c47b46..abb2c9001 100644 --- a/vendor/github.com/prometheus/common/model/labelset_string.go +++ b/vendor/github.com/prometheus/common/model/labelset_string.go @@ -11,8 +11,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -//go:build go1.21 - package model import ( diff --git a/vendor/github.com/prometheus/common/model/labelset_string_go120.go b/vendor/github.com/prometheus/common/model/labelset_string_go120.go deleted file mode 100644 index c4212685e..000000000 --- a/vendor/github.com/prometheus/common/model/labelset_string_go120.go +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2024 The Prometheus 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. - -//go:build !go1.21 - -package model - -import ( - "fmt" - "sort" - "strings" -) - -// String was optimized using functions not available for go 1.20 -// or lower. We keep the old implementation for compatibility with client_golang. -// Once client golang drops support for go 1.20 (scheduled for August 2024), this -// file can be removed. -func (l LabelSet) String() string { - labelNames := make([]string, 0, len(l)) - for name := range l { - labelNames = append(labelNames, string(name)) - } - sort.Strings(labelNames) - lstrs := make([]string, 0, len(l)) - for _, name := range labelNames { - lstrs = append(lstrs, fmt.Sprintf("%s=%q", name, l[LabelName(name)])) - } - return fmt.Sprintf("{%s}", strings.Join(lstrs, ", ")) -} diff --git a/vendor/github.com/prometheus/common/model/metric.go b/vendor/github.com/prometheus/common/model/metric.go index eb865e5a5..f50966bc4 100644 --- a/vendor/github.com/prometheus/common/model/metric.go +++ b/vendor/github.com/prometheus/common/model/metric.go @@ -34,10 +34,13 @@ var ( // goroutines are started. NameValidationScheme = LegacyValidation - // NameEscapingScheme defines the default way that names will be - // escaped when presented to systems that do not support UTF-8 names. If the - // Content-Type "escaping" term is specified, that will override this value. - NameEscapingScheme = ValueEncodingEscaping + // NameEscapingScheme defines the default way that names will be escaped when + // presented to systems that do not support UTF-8 names. If the Content-Type + // "escaping" term is specified, that will override this value. + // NameEscapingScheme should not be set to the NoEscaping value. That string + // is used in content negotiation to indicate that a system supports UTF-8 and + // has that feature enabled. + NameEscapingScheme = UnderscoreEscaping ) // ValidationScheme is a Go enum for determining how metric and label names will @@ -161,7 +164,7 @@ func (m Metric) FastFingerprint() Fingerprint { func IsValidMetricName(n LabelValue) bool { switch NameValidationScheme { case LegacyValidation: - return IsValidLegacyMetricName(n) + return IsValidLegacyMetricName(string(n)) case UTF8Validation: if len(n) == 0 { return false @@ -176,7 +179,7 @@ func IsValidMetricName(n LabelValue) bool { // legacy validation scheme regardless of the value of NameValidationScheme. // This function, however, does not use MetricNameRE for the check but a much // faster hardcoded implementation. -func IsValidLegacyMetricName(n LabelValue) bool { +func IsValidLegacyMetricName(n string) bool { if len(n) == 0 { return false } @@ -208,7 +211,7 @@ func EscapeMetricFamily(v *dto.MetricFamily, scheme EscapingScheme) *dto.MetricF } // If the name is nil, copy as-is, don't try to escape. - if v.Name == nil || IsValidLegacyMetricName(LabelValue(v.GetName())) { + if v.Name == nil || IsValidLegacyMetricName(v.GetName()) { out.Name = v.Name } else { out.Name = proto.String(EscapeName(v.GetName(), scheme)) @@ -230,7 +233,7 @@ func EscapeMetricFamily(v *dto.MetricFamily, scheme EscapingScheme) *dto.MetricF for _, l := range m.Label { if l.GetName() == MetricNameLabel { - if l.Value == nil || IsValidLegacyMetricName(LabelValue(l.GetValue())) { + if l.Value == nil || IsValidLegacyMetricName(l.GetValue()) { escaped.Label = append(escaped.Label, l) continue } @@ -240,7 +243,7 @@ func EscapeMetricFamily(v *dto.MetricFamily, scheme EscapingScheme) *dto.MetricF }) continue } - if l.Name == nil || IsValidLegacyMetricName(LabelValue(l.GetName())) { + if l.Name == nil || IsValidLegacyMetricName(l.GetName()) { escaped.Label = append(escaped.Label, l) continue } @@ -256,10 +259,10 @@ func EscapeMetricFamily(v *dto.MetricFamily, scheme EscapingScheme) *dto.MetricF func metricNeedsEscaping(m *dto.Metric) bool { for _, l := range m.Label { - if l.GetName() == MetricNameLabel && !IsValidLegacyMetricName(LabelValue(l.GetValue())) { + if l.GetName() == MetricNameLabel && !IsValidLegacyMetricName(l.GetValue()) { return true } - if !IsValidLegacyMetricName(LabelValue(l.GetName())) { + if !IsValidLegacyMetricName(l.GetName()) { return true } } @@ -283,7 +286,7 @@ func EscapeName(name string, scheme EscapingScheme) string { case NoEscaping: return name case UnderscoreEscaping: - if IsValidLegacyMetricName(LabelValue(name)) { + if IsValidLegacyMetricName(name) { return name } for i, b := range name { @@ -309,7 +312,7 @@ func EscapeName(name string, scheme EscapingScheme) string { } return escaped.String() case ValueEncodingEscaping: - if IsValidLegacyMetricName(LabelValue(name)) { + if IsValidLegacyMetricName(name) { return name } escaped.WriteString("U__") @@ -452,6 +455,6 @@ func ToEscapingScheme(s string) (EscapingScheme, error) { case EscapeValues: return ValueEncodingEscaping, nil default: - return NoEscaping, fmt.Errorf("unknown format scheme " + s) + return NoEscaping, fmt.Errorf("unknown format scheme %s", s) } } diff --git a/vendor/github.com/prometheus/procfs/.golangci.yml b/vendor/github.com/prometheus/procfs/.golangci.yml index c24864a92..126df9e67 100644 --- a/vendor/github.com/prometheus/procfs/.golangci.yml +++ b/vendor/github.com/prometheus/procfs/.golangci.yml @@ -1,9 +1,16 @@ --- linters: enable: + - errcheck - godot + - gosimple + - govet + - ineffassign - misspell - revive + - staticcheck + - testifylint + - unused linter-settings: godot: diff --git a/vendor/github.com/prometheus/procfs/MAINTAINERS.md b/vendor/github.com/prometheus/procfs/MAINTAINERS.md index 56ba67d3e..e00f3b365 100644 --- a/vendor/github.com/prometheus/procfs/MAINTAINERS.md +++ b/vendor/github.com/prometheus/procfs/MAINTAINERS.md @@ -1,2 +1,3 @@ * Johannes 'fish' Ziemke @discordianfish -* Paul Gier @pgier +* Paul Gier @pgier +* Ben Kochie @SuperQ diff --git a/vendor/github.com/prometheus/procfs/Makefile.common b/vendor/github.com/prometheus/procfs/Makefile.common index 062a28185..161729235 100644 --- a/vendor/github.com/prometheus/procfs/Makefile.common +++ b/vendor/github.com/prometheus/procfs/Makefile.common @@ -49,23 +49,23 @@ endif GOTEST := $(GO) test GOTEST_DIR := ifneq ($(CIRCLE_JOB),) -ifneq ($(shell command -v gotestsum > /dev/null),) +ifneq ($(shell command -v gotestsum 2> /dev/null),) GOTEST_DIR := test-results GOTEST := gotestsum --junitfile $(GOTEST_DIR)/unit-tests.xml -- endif endif -PROMU_VERSION ?= 0.15.0 +PROMU_VERSION ?= 0.17.0 PROMU_URL := https://github.com/prometheus/promu/releases/download/v$(PROMU_VERSION)/promu-$(PROMU_VERSION).$(GO_BUILD_PLATFORM).tar.gz SKIP_GOLANGCI_LINT := GOLANGCI_LINT := GOLANGCI_LINT_OPTS ?= -GOLANGCI_LINT_VERSION ?= v1.54.2 -# golangci-lint only supports linux, darwin and windows platforms on i386/amd64. +GOLANGCI_LINT_VERSION ?= v1.59.0 +# golangci-lint only supports linux, darwin and windows platforms on i386/amd64/arm64. # windows isn't included here because of the path separator being different. ifeq ($(GOHOSTOS),$(filter $(GOHOSTOS),linux darwin)) - ifeq ($(GOHOSTARCH),$(filter $(GOHOSTARCH),amd64 i386)) + ifeq ($(GOHOSTARCH),$(filter $(GOHOSTARCH),amd64 i386 arm64)) # If we're in CI and there is an Actions file, that means the linter # is being run in Actions, so we don't need to run it here. ifneq (,$(SKIP_GOLANGCI_LINT)) @@ -169,16 +169,20 @@ common-vet: common-lint: $(GOLANGCI_LINT) ifdef GOLANGCI_LINT @echo ">> running golangci-lint" -# 'go list' needs to be executed before staticcheck to prepopulate the modules cache. -# Otherwise staticcheck might fail randomly for some reason not yet explained. - $(GO) list -e -compiled -test=true -export=false -deps=true -find=false -tags= -- ./... > /dev/null $(GOLANGCI_LINT) run $(GOLANGCI_LINT_OPTS) $(pkgs) endif +.PHONY: common-lint-fix +common-lint-fix: $(GOLANGCI_LINT) +ifdef GOLANGCI_LINT + @echo ">> running golangci-lint fix" + $(GOLANGCI_LINT) run --fix $(GOLANGCI_LINT_OPTS) $(pkgs) +endif + .PHONY: common-yamllint common-yamllint: @echo ">> running yamllint on all YAML files in the repository" -ifeq (, $(shell command -v yamllint > /dev/null)) +ifeq (, $(shell command -v yamllint 2> /dev/null)) @echo "yamllint not installed so skipping" else yamllint . @@ -204,6 +208,10 @@ common-tarball: promu @echo ">> building release tarball" $(PROMU) tarball --prefix $(PREFIX) $(BIN_DIR) +.PHONY: common-docker-repo-name +common-docker-repo-name: + @echo "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)" + .PHONY: common-docker $(BUILD_DOCKER_ARCHS) common-docker: $(BUILD_DOCKER_ARCHS) $(BUILD_DOCKER_ARCHS): common-docker-%: diff --git a/vendor/github.com/prometheus/procfs/arp.go b/vendor/github.com/prometheus/procfs/arp.go index 28783e2dd..cdcc8a7cc 100644 --- a/vendor/github.com/prometheus/procfs/arp.go +++ b/vendor/github.com/prometheus/procfs/arp.go @@ -55,7 +55,7 @@ type ARPEntry struct { func (fs FS) GatherARPEntries() ([]ARPEntry, error) { data, err := os.ReadFile(fs.proc.Path("net/arp")) if err != nil { - return nil, fmt.Errorf("%s: error reading arp %s: %w", ErrFileRead, fs.proc.Path("net/arp"), err) + return nil, fmt.Errorf("%w: error reading arp %s: %w", ErrFileRead, fs.proc.Path("net/arp"), err) } return parseARPEntries(data) @@ -78,11 +78,11 @@ func parseARPEntries(data []byte) ([]ARPEntry, error) { } else if width == expectedDataWidth { entry, err := parseARPEntry(columns) if err != nil { - return []ARPEntry{}, fmt.Errorf("%s: Failed to parse ARP entry: %v: %w", ErrFileParse, entry, err) + return []ARPEntry{}, fmt.Errorf("%w: Failed to parse ARP entry: %v: %w", ErrFileParse, entry, err) } entries = append(entries, entry) } else { - return []ARPEntry{}, fmt.Errorf("%s: %d columns found, but expected %d: %w", ErrFileParse, width, expectedDataWidth, err) + return []ARPEntry{}, fmt.Errorf("%w: %d columns found, but expected %d: %w", ErrFileParse, width, expectedDataWidth, err) } } diff --git a/vendor/github.com/prometheus/procfs/buddyinfo.go b/vendor/github.com/prometheus/procfs/buddyinfo.go index 4a173636c..838075009 100644 --- a/vendor/github.com/prometheus/procfs/buddyinfo.go +++ b/vendor/github.com/prometheus/procfs/buddyinfo.go @@ -58,8 +58,8 @@ func parseBuddyInfo(r io.Reader) ([]BuddyInfo, error) { return nil, fmt.Errorf("%w: Invalid number of fields, found: %v", ErrFileParse, parts) } - node := strings.TrimRight(parts[1], ",") - zone := strings.TrimRight(parts[3], ",") + node := strings.TrimSuffix(parts[1], ",") + zone := strings.TrimSuffix(parts[3], ",") arraySize := len(parts[4:]) if bucketCount == -1 { @@ -74,7 +74,7 @@ func parseBuddyInfo(r io.Reader) ([]BuddyInfo, error) { for i := 0; i < arraySize; i++ { sizes[i], err = strconv.ParseFloat(parts[i+4], 64) if err != nil { - return nil, fmt.Errorf("%s: Invalid valid in buddyinfo: %f: %w", ErrFileParse, sizes[i], err) + return nil, fmt.Errorf("%w: Invalid valid in buddyinfo: %f: %w", ErrFileParse, sizes[i], err) } } diff --git a/vendor/github.com/prometheus/procfs/cpuinfo.go b/vendor/github.com/prometheus/procfs/cpuinfo.go index f4f5501c6..f0950bb49 100644 --- a/vendor/github.com/prometheus/procfs/cpuinfo.go +++ b/vendor/github.com/prometheus/procfs/cpuinfo.go @@ -194,7 +194,7 @@ func parseCPUInfoARM(info []byte) ([]CPUInfo, error) { firstLine := firstNonEmptyLine(scanner) match, err := regexp.MatchString("^[Pp]rocessor", firstLine) if !match || !strings.Contains(firstLine, ":") { - return nil, fmt.Errorf("%s: Cannot parse line: %q: %w", ErrFileParse, firstLine, err) + return nil, fmt.Errorf("%w: Cannot parse line: %q: %w", ErrFileParse, firstLine, err) } field := strings.SplitN(firstLine, ": ", 2) @@ -386,7 +386,7 @@ func parseCPUInfoLoong(info []byte) ([]CPUInfo, error) { // find the first "processor" line firstLine := firstNonEmptyLine(scanner) if !strings.HasPrefix(firstLine, "system type") || !strings.Contains(firstLine, ":") { - return nil, errors.New("invalid cpuinfo file: " + firstLine) + return nil, fmt.Errorf("%w: %q", ErrFileParse, firstLine) } field := strings.SplitN(firstLine, ": ", 2) cpuinfo := []CPUInfo{} diff --git a/vendor/github.com/prometheus/procfs/crypto.go b/vendor/github.com/prometheus/procfs/crypto.go index 9a73e2639..5f2a37a78 100644 --- a/vendor/github.com/prometheus/procfs/crypto.go +++ b/vendor/github.com/prometheus/procfs/crypto.go @@ -55,13 +55,13 @@ func (fs FS) Crypto() ([]Crypto, error) { path := fs.proc.Path("crypto") b, err := util.ReadFileNoStat(path) if err != nil { - return nil, fmt.Errorf("%s: Cannot read file %v: %w", ErrFileRead, b, err) + return nil, fmt.Errorf("%w: Cannot read file %v: %w", ErrFileRead, b, err) } crypto, err := parseCrypto(bytes.NewReader(b)) if err != nil { - return nil, fmt.Errorf("%s: Cannot parse %v: %w", ErrFileParse, crypto, err) + return nil, fmt.Errorf("%w: Cannot parse %v: %w", ErrFileParse, crypto, err) } return crypto, nil @@ -84,7 +84,7 @@ func parseCrypto(r io.Reader) ([]Crypto, error) { kv := strings.Split(text, ":") if len(kv) != 2 { - return nil, fmt.Errorf("%w: Cannot parae line: %q", ErrFileParse, text) + return nil, fmt.Errorf("%w: Cannot parse line: %q", ErrFileParse, text) } k := strings.TrimSpace(kv[0]) diff --git a/vendor/github.com/prometheus/procfs/fscache.go b/vendor/github.com/prometheus/procfs/fscache.go index f560a8db3..cf2e3eaa0 100644 --- a/vendor/github.com/prometheus/procfs/fscache.go +++ b/vendor/github.com/prometheus/procfs/fscache.go @@ -236,7 +236,7 @@ func (fs FS) Fscacheinfo() (Fscacheinfo, error) { m, err := parseFscacheinfo(bytes.NewReader(b)) if err != nil { - return Fscacheinfo{}, fmt.Errorf("%s: Cannot parse %v: %w", ErrFileParse, m, err) + return Fscacheinfo{}, fmt.Errorf("%w: Cannot parse %v: %w", ErrFileParse, m, err) } return *m, nil @@ -245,7 +245,7 @@ func (fs FS) Fscacheinfo() (Fscacheinfo, error) { func setFSCacheFields(fields []string, setFields ...*uint64) error { var err error if len(fields) < len(setFields) { - return fmt.Errorf("%s: Expected %d, but got %d: %w", ErrFileParse, len(setFields), len(fields), err) + return fmt.Errorf("%w: Expected %d, but got %d: %w", ErrFileParse, len(setFields), len(fields), err) } for i := range setFields { diff --git a/vendor/github.com/prometheus/procfs/ipvs.go b/vendor/github.com/prometheus/procfs/ipvs.go index 5a145bbfe..bc3a20c93 100644 --- a/vendor/github.com/prometheus/procfs/ipvs.go +++ b/vendor/github.com/prometheus/procfs/ipvs.go @@ -221,16 +221,16 @@ func parseIPPort(s string) (net.IP, uint16, error) { case 46: ip = net.ParseIP(s[1:40]) if ip == nil { - return nil, 0, fmt.Errorf("%s: Invalid IPv6 addr %s: %w", ErrFileParse, s[1:40], err) + return nil, 0, fmt.Errorf("%w: Invalid IPv6 addr %s: %w", ErrFileParse, s[1:40], err) } default: - return nil, 0, fmt.Errorf("%s: Unexpected IP:Port %s: %w", ErrFileParse, s, err) + return nil, 0, fmt.Errorf("%w: Unexpected IP:Port %s: %w", ErrFileParse, s, err) } portString := s[len(s)-4:] if len(portString) != 4 { return nil, 0, - fmt.Errorf("%s: Unexpected port string format %s: %w", ErrFileParse, portString, err) + fmt.Errorf("%w: Unexpected port string format %s: %w", ErrFileParse, portString, err) } port, err := strconv.ParseUint(portString, 16, 16) if err != nil { diff --git a/vendor/github.com/prometheus/procfs/loadavg.go b/vendor/github.com/prometheus/procfs/loadavg.go index 59465c5bb..332e76c17 100644 --- a/vendor/github.com/prometheus/procfs/loadavg.go +++ b/vendor/github.com/prometheus/procfs/loadavg.go @@ -51,7 +51,7 @@ func parseLoad(loadavgBytes []byte) (*LoadAvg, error) { for i, load := range parts[0:3] { loads[i], err = strconv.ParseFloat(load, 64) if err != nil { - return nil, fmt.Errorf("%s: Cannot parse load: %f: %w", ErrFileParse, loads[i], err) + return nil, fmt.Errorf("%w: Cannot parse load: %f: %w", ErrFileParse, loads[i], err) } } return &LoadAvg{ diff --git a/vendor/github.com/prometheus/procfs/mdstat.go b/vendor/github.com/prometheus/procfs/mdstat.go index fdd4b9544..67a9d2b44 100644 --- a/vendor/github.com/prometheus/procfs/mdstat.go +++ b/vendor/github.com/prometheus/procfs/mdstat.go @@ -23,7 +23,7 @@ import ( var ( statusLineRE = regexp.MustCompile(`(\d+) blocks .*\[(\d+)/(\d+)\] \[([U_]+)\]`) - recoveryLineBlocksRE = regexp.MustCompile(`\((\d+)/\d+\)`) + recoveryLineBlocksRE = regexp.MustCompile(`\((\d+/\d+)\)`) recoveryLinePctRE = regexp.MustCompile(`= (.+)%`) recoveryLineFinishRE = regexp.MustCompile(`finish=(.+)min`) recoveryLineSpeedRE = regexp.MustCompile(`speed=(.+)[A-Z]`) @@ -50,6 +50,8 @@ type MDStat struct { BlocksTotal int64 // Number of blocks on the device that are in sync. BlocksSynced int64 + // Number of blocks on the device that need to be synced. + BlocksToBeSynced int64 // progress percentage of current sync BlocksSyncedPct float64 // estimated finishing time for current sync (in minutes) @@ -70,7 +72,7 @@ func (fs FS) MDStat() ([]MDStat, error) { } mdstat, err := parseMDStat(data) if err != nil { - return nil, fmt.Errorf("%s: Cannot parse %v: %w", ErrFileParse, fs.proc.Path("mdstat"), err) + return nil, fmt.Errorf("%w: Cannot parse %v: %w", ErrFileParse, fs.proc.Path("mdstat"), err) } return mdstat, nil } @@ -90,7 +92,7 @@ func parseMDStat(mdStatData []byte) ([]MDStat, error) { deviceFields := strings.Fields(line) if len(deviceFields) < 3 { - return nil, fmt.Errorf("%s: Expected 3+ lines, got %q", ErrFileParse, line) + return nil, fmt.Errorf("%w: Expected 3+ lines, got %q", ErrFileParse, line) } mdName := deviceFields[0] // mdx state := deviceFields[2] // active or inactive @@ -105,7 +107,7 @@ func parseMDStat(mdStatData []byte) ([]MDStat, error) { active, total, down, size, err := evalStatusLine(lines[i], lines[i+1]) if err != nil { - return nil, fmt.Errorf("%s: Cannot parse md device lines: %v: %w", ErrFileParse, active, err) + return nil, fmt.Errorf("%w: Cannot parse md device lines: %v: %w", ErrFileParse, active, err) } syncLineIdx := i + 2 @@ -115,7 +117,8 @@ func parseMDStat(mdStatData []byte) ([]MDStat, error) { // If device is syncing at the moment, get the number of currently // synced bytes, otherwise that number equals the size of the device. - syncedBlocks := size + blocksSynced := size + blocksToBeSynced := size speed := float64(0) finish := float64(0) pct := float64(0) @@ -136,11 +139,11 @@ func parseMDStat(mdStatData []byte) ([]MDStat, error) { // Handle case when resync=PENDING or resync=DELAYED. if strings.Contains(lines[syncLineIdx], "PENDING") || strings.Contains(lines[syncLineIdx], "DELAYED") { - syncedBlocks = 0 + blocksSynced = 0 } else { - syncedBlocks, pct, finish, speed, err = evalRecoveryLine(lines[syncLineIdx]) + blocksSynced, blocksToBeSynced, pct, finish, speed, err = evalRecoveryLine(lines[syncLineIdx]) if err != nil { - return nil, fmt.Errorf("%s: Cannot parse sync line in md device: %q: %w", ErrFileParse, mdName, err) + return nil, fmt.Errorf("%w: Cannot parse sync line in md device: %q: %w", ErrFileParse, mdName, err) } } } @@ -154,7 +157,8 @@ func parseMDStat(mdStatData []byte) ([]MDStat, error) { DisksSpare: spare, DisksTotal: total, BlocksTotal: size, - BlocksSynced: syncedBlocks, + BlocksSynced: blocksSynced, + BlocksToBeSynced: blocksToBeSynced, BlocksSyncedPct: pct, BlocksSyncedFinishTime: finish, BlocksSyncedSpeed: speed, @@ -168,13 +172,13 @@ func parseMDStat(mdStatData []byte) ([]MDStat, error) { func evalStatusLine(deviceLine, statusLine string) (active, total, down, size int64, err error) { statusFields := strings.Fields(statusLine) if len(statusFields) < 1 { - return 0, 0, 0, 0, fmt.Errorf("%s: Unexpected statusline %q: %w", ErrFileParse, statusLine, err) + return 0, 0, 0, 0, fmt.Errorf("%w: Unexpected statusline %q: %w", ErrFileParse, statusLine, err) } sizeStr := statusFields[0] size, err = strconv.ParseInt(sizeStr, 10, 64) if err != nil { - return 0, 0, 0, 0, fmt.Errorf("%s: Unexpected statusline %q: %w", ErrFileParse, statusLine, err) + return 0, 0, 0, 0, fmt.Errorf("%w: Unexpected statusline %q: %w", ErrFileParse, statusLine, err) } if strings.Contains(deviceLine, "raid0") || strings.Contains(deviceLine, "linear") { @@ -189,65 +193,71 @@ func evalStatusLine(deviceLine, statusLine string) (active, total, down, size in matches := statusLineRE.FindStringSubmatch(statusLine) if len(matches) != 5 { - return 0, 0, 0, 0, fmt.Errorf("%s: Could not fild all substring matches %s: %w", ErrFileParse, statusLine, err) + return 0, 0, 0, 0, fmt.Errorf("%w: Could not fild all substring matches %s: %w", ErrFileParse, statusLine, err) } total, err = strconv.ParseInt(matches[2], 10, 64) if err != nil { - return 0, 0, 0, 0, fmt.Errorf("%s: Unexpected statusline %q: %w", ErrFileParse, statusLine, err) + return 0, 0, 0, 0, fmt.Errorf("%w: Unexpected statusline %q: %w", ErrFileParse, statusLine, err) } active, err = strconv.ParseInt(matches[3], 10, 64) if err != nil { - return 0, 0, 0, 0, fmt.Errorf("%s: Unexpected active %d: %w", ErrFileParse, active, err) + return 0, 0, 0, 0, fmt.Errorf("%w: Unexpected active %d: %w", ErrFileParse, active, err) } down = int64(strings.Count(matches[4], "_")) return active, total, down, size, nil } -func evalRecoveryLine(recoveryLine string) (syncedBlocks int64, pct float64, finish float64, speed float64, err error) { +func evalRecoveryLine(recoveryLine string) (blocksSynced int64, blocksToBeSynced int64, pct float64, finish float64, speed float64, err error) { matches := recoveryLineBlocksRE.FindStringSubmatch(recoveryLine) if len(matches) != 2 { - return 0, 0, 0, 0, fmt.Errorf("%s: Unexpected recoveryLine %s: %w", ErrFileParse, recoveryLine, err) + return 0, 0, 0, 0, 0, fmt.Errorf("%w: Unexpected recoveryLine blocks %s: %w", ErrFileParse, recoveryLine, err) } - syncedBlocks, err = strconv.ParseInt(matches[1], 10, 64) + blocks := strings.Split(matches[1], "/") + blocksSynced, err = strconv.ParseInt(blocks[0], 10, 64) if err != nil { - return 0, 0, 0, 0, fmt.Errorf("%s: Unexpected parsing of recoveryLine %q: %w", ErrFileParse, recoveryLine, err) + return 0, 0, 0, 0, 0, fmt.Errorf("%w: Unable to parse recovery blocks synced %q: %w", ErrFileParse, matches[1], err) + } + + blocksToBeSynced, err = strconv.ParseInt(blocks[1], 10, 64) + if err != nil { + return blocksSynced, 0, 0, 0, 0, fmt.Errorf("%w: Unable to parse recovery to be synced blocks %q: %w", ErrFileParse, matches[2], err) } // Get percentage complete matches = recoveryLinePctRE.FindStringSubmatch(recoveryLine) if len(matches) != 2 { - return syncedBlocks, 0, 0, 0, fmt.Errorf("%w: Unexpected recoveryLine matching percentage %s", ErrFileParse, recoveryLine) + return blocksSynced, blocksToBeSynced, 0, 0, 0, fmt.Errorf("%w: Unexpected recoveryLine matching percentage %s", ErrFileParse, recoveryLine) } pct, err = strconv.ParseFloat(strings.TrimSpace(matches[1]), 64) if err != nil { - return syncedBlocks, 0, 0, 0, fmt.Errorf("%w: Error parsing float from recoveryLine %q", ErrFileParse, recoveryLine) + return blocksSynced, blocksToBeSynced, 0, 0, 0, fmt.Errorf("%w: Error parsing float from recoveryLine %q", ErrFileParse, recoveryLine) } // Get time expected left to complete matches = recoveryLineFinishRE.FindStringSubmatch(recoveryLine) if len(matches) != 2 { - return syncedBlocks, pct, 0, 0, fmt.Errorf("%w: Unexpected recoveryLine matching est. finish time: %s", ErrFileParse, recoveryLine) + return blocksSynced, blocksToBeSynced, pct, 0, 0, fmt.Errorf("%w: Unexpected recoveryLine matching est. finish time: %s", ErrFileParse, recoveryLine) } finish, err = strconv.ParseFloat(matches[1], 64) if err != nil { - return syncedBlocks, pct, 0, 0, fmt.Errorf("%w: Unable to parse float from recoveryLine: %q", ErrFileParse, recoveryLine) + return blocksSynced, blocksToBeSynced, pct, 0, 0, fmt.Errorf("%w: Unable to parse float from recoveryLine: %q", ErrFileParse, recoveryLine) } // Get recovery speed matches = recoveryLineSpeedRE.FindStringSubmatch(recoveryLine) if len(matches) != 2 { - return syncedBlocks, pct, finish, 0, fmt.Errorf("%w: Unexpected recoveryLine value: %s", ErrFileParse, recoveryLine) + return blocksSynced, blocksToBeSynced, pct, finish, 0, fmt.Errorf("%w: Unexpected recoveryLine value: %s", ErrFileParse, recoveryLine) } speed, err = strconv.ParseFloat(matches[1], 64) if err != nil { - return syncedBlocks, pct, finish, 0, fmt.Errorf("%s: Error parsing float from recoveryLine: %q: %w", ErrFileParse, recoveryLine, err) + return blocksSynced, blocksToBeSynced, pct, finish, 0, fmt.Errorf("%w: Error parsing float from recoveryLine: %q: %w", ErrFileParse, recoveryLine, err) } - return syncedBlocks, pct, finish, speed, nil + return blocksSynced, blocksToBeSynced, pct, finish, speed, nil } func evalComponentDevices(deviceFields []string) []string { diff --git a/vendor/github.com/prometheus/procfs/meminfo.go b/vendor/github.com/prometheus/procfs/meminfo.go index eaf00e224..4b2c4050a 100644 --- a/vendor/github.com/prometheus/procfs/meminfo.go +++ b/vendor/github.com/prometheus/procfs/meminfo.go @@ -126,6 +126,7 @@ type Meminfo struct { VmallocUsed *uint64 // largest contiguous block of vmalloc area which is free VmallocChunk *uint64 + Percpu *uint64 HardwareCorrupted *uint64 AnonHugePages *uint64 ShmemHugePages *uint64 @@ -140,6 +141,55 @@ type Meminfo struct { DirectMap4k *uint64 DirectMap2M *uint64 DirectMap1G *uint64 + + // The struct fields below are the byte-normalized counterparts to the + // existing struct fields. Values are normalized using the optional + // unit field in the meminfo line. + MemTotalBytes *uint64 + MemFreeBytes *uint64 + MemAvailableBytes *uint64 + BuffersBytes *uint64 + CachedBytes *uint64 + SwapCachedBytes *uint64 + ActiveBytes *uint64 + InactiveBytes *uint64 + ActiveAnonBytes *uint64 + InactiveAnonBytes *uint64 + ActiveFileBytes *uint64 + InactiveFileBytes *uint64 + UnevictableBytes *uint64 + MlockedBytes *uint64 + SwapTotalBytes *uint64 + SwapFreeBytes *uint64 + DirtyBytes *uint64 + WritebackBytes *uint64 + AnonPagesBytes *uint64 + MappedBytes *uint64 + ShmemBytes *uint64 + SlabBytes *uint64 + SReclaimableBytes *uint64 + SUnreclaimBytes *uint64 + KernelStackBytes *uint64 + PageTablesBytes *uint64 + NFSUnstableBytes *uint64 + BounceBytes *uint64 + WritebackTmpBytes *uint64 + CommitLimitBytes *uint64 + CommittedASBytes *uint64 + VmallocTotalBytes *uint64 + VmallocUsedBytes *uint64 + VmallocChunkBytes *uint64 + PercpuBytes *uint64 + HardwareCorruptedBytes *uint64 + AnonHugePagesBytes *uint64 + ShmemHugePagesBytes *uint64 + ShmemPmdMappedBytes *uint64 + CmaTotalBytes *uint64 + CmaFreeBytes *uint64 + HugepagesizeBytes *uint64 + DirectMap4kBytes *uint64 + DirectMap2MBytes *uint64 + DirectMap1GBytes *uint64 } // Meminfo returns an information about current kernel/system memory statistics. @@ -152,7 +202,7 @@ func (fs FS) Meminfo() (Meminfo, error) { m, err := parseMemInfo(bytes.NewReader(b)) if err != nil { - return Meminfo{}, fmt.Errorf("%s: %w", ErrFileParse, err) + return Meminfo{}, fmt.Errorf("%w: %w", ErrFileParse, err) } return *m, nil @@ -162,114 +212,176 @@ func parseMemInfo(r io.Reader) (*Meminfo, error) { var m Meminfo s := bufio.NewScanner(r) for s.Scan() { - // Each line has at least a name and value; we ignore the unit. fields := strings.Fields(s.Text()) - if len(fields) < 2 { - return nil, fmt.Errorf("%w: Malformed line %q", ErrFileParse, s.Text()) - } + var val, valBytes uint64 - v, err := strconv.ParseUint(fields[1], 0, 64) + val, err := strconv.ParseUint(fields[1], 0, 64) if err != nil { return nil, err } + switch len(fields) { + case 2: + // No unit present, use the parsed the value as bytes directly. + valBytes = val + case 3: + // Unit present in optional 3rd field, convert it to + // bytes. The only unit supported within the Linux + // kernel is `kB`. + if fields[2] != "kB" { + return nil, fmt.Errorf("%w: Unsupported unit in optional 3rd field %q", ErrFileParse, fields[2]) + } + + valBytes = 1024 * val + + default: + return nil, fmt.Errorf("%w: Malformed line %q", ErrFileParse, s.Text()) + } + switch fields[0] { case "MemTotal:": - m.MemTotal = &v + m.MemTotal = &val + m.MemTotalBytes = &valBytes case "MemFree:": - m.MemFree = &v + m.MemFree = &val + m.MemFreeBytes = &valBytes case "MemAvailable:": - m.MemAvailable = &v + m.MemAvailable = &val + m.MemAvailableBytes = &valBytes case "Buffers:": - m.Buffers = &v + m.Buffers = &val + m.BuffersBytes = &valBytes case "Cached:": - m.Cached = &v + m.Cached = &val + m.CachedBytes = &valBytes case "SwapCached:": - m.SwapCached = &v + m.SwapCached = &val + m.SwapCachedBytes = &valBytes case "Active:": - m.Active = &v + m.Active = &val + m.ActiveBytes = &valBytes case "Inactive:": - m.Inactive = &v + m.Inactive = &val + m.InactiveBytes = &valBytes case "Active(anon):": - m.ActiveAnon = &v + m.ActiveAnon = &val + m.ActiveAnonBytes = &valBytes case "Inactive(anon):": - m.InactiveAnon = &v + m.InactiveAnon = &val + m.InactiveAnonBytes = &valBytes case "Active(file):": - m.ActiveFile = &v + m.ActiveFile = &val + m.ActiveFileBytes = &valBytes case "Inactive(file):": - m.InactiveFile = &v + m.InactiveFile = &val + m.InactiveFileBytes = &valBytes case "Unevictable:": - m.Unevictable = &v + m.Unevictable = &val + m.UnevictableBytes = &valBytes case "Mlocked:": - m.Mlocked = &v + m.Mlocked = &val + m.MlockedBytes = &valBytes case "SwapTotal:": - m.SwapTotal = &v + m.SwapTotal = &val + m.SwapTotalBytes = &valBytes case "SwapFree:": - m.SwapFree = &v + m.SwapFree = &val + m.SwapFreeBytes = &valBytes case "Dirty:": - m.Dirty = &v + m.Dirty = &val + m.DirtyBytes = &valBytes case "Writeback:": - m.Writeback = &v + m.Writeback = &val + m.WritebackBytes = &valBytes case "AnonPages:": - m.AnonPages = &v + m.AnonPages = &val + m.AnonPagesBytes = &valBytes case "Mapped:": - m.Mapped = &v + m.Mapped = &val + m.MappedBytes = &valBytes case "Shmem:": - m.Shmem = &v + m.Shmem = &val + m.ShmemBytes = &valBytes case "Slab:": - m.Slab = &v + m.Slab = &val + m.SlabBytes = &valBytes case "SReclaimable:": - m.SReclaimable = &v + m.SReclaimable = &val + m.SReclaimableBytes = &valBytes case "SUnreclaim:": - m.SUnreclaim = &v + m.SUnreclaim = &val + m.SUnreclaimBytes = &valBytes case "KernelStack:": - m.KernelStack = &v + m.KernelStack = &val + m.KernelStackBytes = &valBytes case "PageTables:": - m.PageTables = &v + m.PageTables = &val + m.PageTablesBytes = &valBytes case "NFS_Unstable:": - m.NFSUnstable = &v + m.NFSUnstable = &val + m.NFSUnstableBytes = &valBytes case "Bounce:": - m.Bounce = &v + m.Bounce = &val + m.BounceBytes = &valBytes case "WritebackTmp:": - m.WritebackTmp = &v + m.WritebackTmp = &val + m.WritebackTmpBytes = &valBytes case "CommitLimit:": - m.CommitLimit = &v + m.CommitLimit = &val + m.CommitLimitBytes = &valBytes case "Committed_AS:": - m.CommittedAS = &v + m.CommittedAS = &val + m.CommittedASBytes = &valBytes case "VmallocTotal:": - m.VmallocTotal = &v + m.VmallocTotal = &val + m.VmallocTotalBytes = &valBytes case "VmallocUsed:": - m.VmallocUsed = &v + m.VmallocUsed = &val + m.VmallocUsedBytes = &valBytes case "VmallocChunk:": - m.VmallocChunk = &v + m.VmallocChunk = &val + m.VmallocChunkBytes = &valBytes + case "Percpu:": + m.Percpu = &val + m.PercpuBytes = &valBytes case "HardwareCorrupted:": - m.HardwareCorrupted = &v + m.HardwareCorrupted = &val + m.HardwareCorruptedBytes = &valBytes case "AnonHugePages:": - m.AnonHugePages = &v + m.AnonHugePages = &val + m.AnonHugePagesBytes = &valBytes case "ShmemHugePages:": - m.ShmemHugePages = &v + m.ShmemHugePages = &val + m.ShmemHugePagesBytes = &valBytes case "ShmemPmdMapped:": - m.ShmemPmdMapped = &v + m.ShmemPmdMapped = &val + m.ShmemPmdMappedBytes = &valBytes case "CmaTotal:": - m.CmaTotal = &v + m.CmaTotal = &val + m.CmaTotalBytes = &valBytes case "CmaFree:": - m.CmaFree = &v + m.CmaFree = &val + m.CmaFreeBytes = &valBytes case "HugePages_Total:": - m.HugePagesTotal = &v + m.HugePagesTotal = &val case "HugePages_Free:": - m.HugePagesFree = &v + m.HugePagesFree = &val case "HugePages_Rsvd:": - m.HugePagesRsvd = &v + m.HugePagesRsvd = &val case "HugePages_Surp:": - m.HugePagesSurp = &v + m.HugePagesSurp = &val case "Hugepagesize:": - m.Hugepagesize = &v + m.Hugepagesize = &val + m.HugepagesizeBytes = &valBytes case "DirectMap4k:": - m.DirectMap4k = &v + m.DirectMap4k = &val + m.DirectMap4kBytes = &valBytes case "DirectMap2M:": - m.DirectMap2M = &v + m.DirectMap2M = &val + m.DirectMap2MBytes = &valBytes case "DirectMap1G:": - m.DirectMap1G = &v + m.DirectMap1G = &val + m.DirectMap1GBytes = &valBytes } } diff --git a/vendor/github.com/prometheus/procfs/mountinfo.go b/vendor/github.com/prometheus/procfs/mountinfo.go index 388ebf396..a704c5e73 100644 --- a/vendor/github.com/prometheus/procfs/mountinfo.go +++ b/vendor/github.com/prometheus/procfs/mountinfo.go @@ -109,7 +109,7 @@ func parseMountInfoString(mountString string) (*MountInfo, error) { if mountInfo[6] != "" { mount.OptionalFields, err = mountOptionsParseOptionalFields(mountInfo[6 : mountInfoLength-4]) if err != nil { - return nil, fmt.Errorf("%s: %w", ErrFileParse, err) + return nil, fmt.Errorf("%w: %w", ErrFileParse, err) } } return mount, nil diff --git a/vendor/github.com/prometheus/procfs/mountstats.go b/vendor/github.com/prometheus/procfs/mountstats.go index 9d8af6db7..75a3b6c81 100644 --- a/vendor/github.com/prometheus/procfs/mountstats.go +++ b/vendor/github.com/prometheus/procfs/mountstats.go @@ -88,7 +88,7 @@ type MountStatsNFS struct { // Statistics broken down by filesystem operation. Operations []NFSOperationStats // Statistics about the NFS RPC transport. - Transport NFSTransportStats + Transport []NFSTransportStats } // mountStats implements MountStats. @@ -194,8 +194,6 @@ type NFSOperationStats struct { CumulativeTotalResponseMilliseconds uint64 // Duration from when a request was enqueued to when it was completely handled. CumulativeTotalRequestMilliseconds uint64 - // The average time from the point the client sends RPC requests until it receives the response. - AverageRTTMilliseconds float64 // The count of operations that complete with tk_status < 0. These statuses usually indicate error conditions. Errors uint64 } @@ -434,7 +432,7 @@ func parseMountStatsNFS(s *bufio.Scanner, statVersion string) (*MountStatsNFS, e return nil, err } - stats.Transport = *tstats + stats.Transport = append(stats.Transport, *tstats) } // When encountering "per-operation statistics", we must break this @@ -582,9 +580,6 @@ func parseNFSOperationStats(s *bufio.Scanner) ([]NFSOperationStats, error) { CumulativeTotalResponseMilliseconds: ns[6], CumulativeTotalRequestMilliseconds: ns[7], } - if ns[0] != 0 { - opStats.AverageRTTMilliseconds = float64(ns[6]) / float64(ns[0]) - } if len(ns) > 8 { opStats.Errors = ns[8] @@ -632,7 +627,7 @@ func parseNFSTransportStats(ss []string, statVersion string) (*NFSTransportStats return nil, fmt.Errorf("%w: invalid NFS transport stats 1.1 statement: %v, protocol: %v", ErrFileParse, ss, protocol) } default: - return nil, fmt.Errorf("%s: Unrecognized NFS transport stats version: %q, protocol: %v", ErrFileParse, statVersion, protocol) + return nil, fmt.Errorf("%w: Unrecognized NFS transport stats version: %q, protocol: %v", ErrFileParse, statVersion, protocol) } // Allocate enough for v1.1 stats since zero value for v1.1 stats will be okay diff --git a/vendor/github.com/prometheus/procfs/net_conntrackstat.go b/vendor/github.com/prometheus/procfs/net_conntrackstat.go index fdfa45611..316df5fbb 100644 --- a/vendor/github.com/prometheus/procfs/net_conntrackstat.go +++ b/vendor/github.com/prometheus/procfs/net_conntrackstat.go @@ -58,7 +58,7 @@ func readConntrackStat(path string) ([]ConntrackStatEntry, error) { stat, err := parseConntrackStat(bytes.NewReader(b)) if err != nil { - return nil, fmt.Errorf("%s: Cannot read file: %v: %w", ErrFileRead, path, err) + return nil, fmt.Errorf("%w: Cannot read file: %v: %w", ErrFileRead, path, err) } return stat, nil @@ -86,7 +86,7 @@ func parseConntrackStat(r io.Reader) ([]ConntrackStatEntry, error) { func parseConntrackStatEntry(fields []string) (*ConntrackStatEntry, error) { entries, err := util.ParseHexUint64s(fields) if err != nil { - return nil, fmt.Errorf("%s: Cannot parse entry: %d: %w", ErrFileParse, entries, err) + return nil, fmt.Errorf("%w: Cannot parse entry: %d: %w", ErrFileParse, entries, err) } numEntries := len(entries) if numEntries < 16 || numEntries > 17 { diff --git a/vendor/github.com/prometheus/procfs/net_ip_socket.go b/vendor/github.com/prometheus/procfs/net_ip_socket.go index 4da81ea57..b70f1fc7a 100644 --- a/vendor/github.com/prometheus/procfs/net_ip_socket.go +++ b/vendor/github.com/prometheus/procfs/net_ip_socket.go @@ -50,10 +50,13 @@ type ( // UsedSockets shows the total number of parsed lines representing the // number of used sockets. UsedSockets uint64 + // Drops shows the total number of dropped packets of all UPD sockets. + Drops *uint64 } // netIPSocketLine represents the fields parsed from a single line // in /proc/net/{t,u}dp{,6}. Fields which are not used by IPSocket are skipped. + // Drops is non-nil for udp{,6}, but nil for tcp{,6}. // For the proc file format details, see https://linux.die.net/man/5/proc. netIPSocketLine struct { Sl uint64 @@ -66,6 +69,7 @@ type ( RxQueue uint64 UID uint64 Inode uint64 + Drops *uint64 } ) @@ -77,13 +81,14 @@ func newNetIPSocket(file string) (NetIPSocket, error) { defer f.Close() var netIPSocket NetIPSocket + isUDP := strings.Contains(file, "udp") lr := io.LimitReader(f, readLimit) s := bufio.NewScanner(lr) s.Scan() // skip first line with headers for s.Scan() { fields := strings.Fields(s.Text()) - line, err := parseNetIPSocketLine(fields) + line, err := parseNetIPSocketLine(fields, isUDP) if err != nil { return nil, err } @@ -104,19 +109,25 @@ func newNetIPSocketSummary(file string) (*NetIPSocketSummary, error) { defer f.Close() var netIPSocketSummary NetIPSocketSummary + var udpPacketDrops uint64 + isUDP := strings.Contains(file, "udp") lr := io.LimitReader(f, readLimit) s := bufio.NewScanner(lr) s.Scan() // skip first line with headers for s.Scan() { fields := strings.Fields(s.Text()) - line, err := parseNetIPSocketLine(fields) + line, err := parseNetIPSocketLine(fields, isUDP) if err != nil { return nil, err } netIPSocketSummary.TxQueueLength += line.TxQueue netIPSocketSummary.RxQueueLength += line.RxQueue netIPSocketSummary.UsedSockets++ + if isUDP { + udpPacketDrops += *line.Drops + netIPSocketSummary.Drops = &udpPacketDrops + } } if err := s.Err(); err != nil { return nil, err @@ -130,7 +141,7 @@ func parseIP(hexIP string) (net.IP, error) { var byteIP []byte byteIP, err := hex.DecodeString(hexIP) if err != nil { - return nil, fmt.Errorf("%s: Cannot parse socket field in %q: %w", ErrFileParse, hexIP, err) + return nil, fmt.Errorf("%w: Cannot parse socket field in %q: %w", ErrFileParse, hexIP, err) } switch len(byteIP) { case 4: @@ -144,12 +155,12 @@ func parseIP(hexIP string) (net.IP, error) { } return i, nil default: - return nil, fmt.Errorf("%s: Unable to parse IP %s: %w", ErrFileParse, hexIP, nil) + return nil, fmt.Errorf("%w: Unable to parse IP %s: %v", ErrFileParse, hexIP, nil) } } // parseNetIPSocketLine parses a single line, represented by a list of fields. -func parseNetIPSocketLine(fields []string) (*netIPSocketLine, error) { +func parseNetIPSocketLine(fields []string, isUDP bool) (*netIPSocketLine, error) { line := &netIPSocketLine{} if len(fields) < 10 { return nil, fmt.Errorf( @@ -167,7 +178,7 @@ func parseNetIPSocketLine(fields []string) (*netIPSocketLine, error) { } if line.Sl, err = strconv.ParseUint(s[0], 0, 64); err != nil { - return nil, fmt.Errorf("%s: Unable to parse sl field in %q: %w", ErrFileParse, line.Sl, err) + return nil, fmt.Errorf("%w: Unable to parse sl field in %q: %w", ErrFileParse, line.Sl, err) } // local_address l := strings.Split(fields[1], ":") @@ -178,7 +189,7 @@ func parseNetIPSocketLine(fields []string) (*netIPSocketLine, error) { return nil, err } if line.LocalPort, err = strconv.ParseUint(l[1], 16, 64); err != nil { - return nil, fmt.Errorf("%s: Unable to parse local_address port value line %q: %w", ErrFileParse, line.LocalPort, err) + return nil, fmt.Errorf("%w: Unable to parse local_address port value line %q: %w", ErrFileParse, line.LocalPort, err) } // remote_address @@ -190,12 +201,12 @@ func parseNetIPSocketLine(fields []string) (*netIPSocketLine, error) { return nil, err } if line.RemPort, err = strconv.ParseUint(r[1], 16, 64); err != nil { - return nil, fmt.Errorf("%s: Cannot parse rem_address port value in %q: %w", ErrFileParse, line.RemPort, err) + return nil, fmt.Errorf("%w: Cannot parse rem_address port value in %q: %w", ErrFileParse, line.RemPort, err) } // st if line.St, err = strconv.ParseUint(fields[3], 16, 64); err != nil { - return nil, fmt.Errorf("%s: Cannot parse st value in %q: %w", ErrFileParse, line.St, err) + return nil, fmt.Errorf("%w: Cannot parse st value in %q: %w", ErrFileParse, line.St, err) } // tx_queue and rx_queue @@ -208,20 +219,29 @@ func parseNetIPSocketLine(fields []string) (*netIPSocketLine, error) { ) } if line.TxQueue, err = strconv.ParseUint(q[0], 16, 64); err != nil { - return nil, fmt.Errorf("%s: Cannot parse tx_queue value in %q: %w", ErrFileParse, line.TxQueue, err) + return nil, fmt.Errorf("%w: Cannot parse tx_queue value in %q: %w", ErrFileParse, line.TxQueue, err) } if line.RxQueue, err = strconv.ParseUint(q[1], 16, 64); err != nil { - return nil, fmt.Errorf("%s: Cannot parse trx_queue value in %q: %w", ErrFileParse, line.RxQueue, err) + return nil, fmt.Errorf("%w: Cannot parse trx_queue value in %q: %w", ErrFileParse, line.RxQueue, err) } // uid if line.UID, err = strconv.ParseUint(fields[7], 0, 64); err != nil { - return nil, fmt.Errorf("%s: Cannot parse UID value in %q: %w", ErrFileParse, line.UID, err) + return nil, fmt.Errorf("%w: Cannot parse UID value in %q: %w", ErrFileParse, line.UID, err) } // inode if line.Inode, err = strconv.ParseUint(fields[9], 0, 64); err != nil { - return nil, fmt.Errorf("%s: Cannot parse inode value in %q: %w", ErrFileParse, line.Inode, err) + return nil, fmt.Errorf("%w: Cannot parse inode value in %q: %w", ErrFileParse, line.Inode, err) + } + + // drops + if isUDP { + drops, err := strconv.ParseUint(fields[12], 0, 64) + if err != nil { + return nil, fmt.Errorf("%w: Cannot parse drops value in %q: %w", ErrFileParse, drops, err) + } + line.Drops = &drops } return line, nil diff --git a/vendor/github.com/prometheus/procfs/net_sockstat.go b/vendor/github.com/prometheus/procfs/net_sockstat.go index 360e36af7..fae62b13d 100644 --- a/vendor/github.com/prometheus/procfs/net_sockstat.go +++ b/vendor/github.com/prometheus/procfs/net_sockstat.go @@ -69,7 +69,7 @@ func readSockstat(name string) (*NetSockstat, error) { stat, err := parseSockstat(bytes.NewReader(b)) if err != nil { - return nil, fmt.Errorf("%s: sockstats from %q: %w", ErrFileRead, name, err) + return nil, fmt.Errorf("%w: sockstats from %q: %w", ErrFileRead, name, err) } return stat, nil @@ -89,7 +89,7 @@ func parseSockstat(r io.Reader) (*NetSockstat, error) { // The remaining fields are key/value pairs. kvs, err := parseSockstatKVs(fields[1:]) if err != nil { - return nil, fmt.Errorf("%s: sockstat key/value pairs from %q: %w", ErrFileParse, s.Text(), err) + return nil, fmt.Errorf("%w: sockstat key/value pairs from %q: %w", ErrFileParse, s.Text(), err) } // The first field is the protocol. We must trim its colon suffix. diff --git a/vendor/github.com/prometheus/procfs/net_softnet.go b/vendor/github.com/prometheus/procfs/net_softnet.go index c77085291..71c8059f4 100644 --- a/vendor/github.com/prometheus/procfs/net_softnet.go +++ b/vendor/github.com/prometheus/procfs/net_softnet.go @@ -64,7 +64,7 @@ func (fs FS) NetSoftnetStat() ([]SoftnetStat, error) { entries, err := parseSoftnet(bytes.NewReader(b)) if err != nil { - return nil, fmt.Errorf("%s: /proc/net/softnet_stat: %w", ErrFileParse, err) + return nil, fmt.Errorf("%w: /proc/net/softnet_stat: %w", ErrFileParse, err) } return entries, nil diff --git a/vendor/github.com/prometheus/procfs/net_tls_stat.go b/vendor/github.com/prometheus/procfs/net_tls_stat.go new file mode 100644 index 000000000..13994c178 --- /dev/null +++ b/vendor/github.com/prometheus/procfs/net_tls_stat.go @@ -0,0 +1,119 @@ +// Copyright 2023 Prometheus Team +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package procfs + +import ( + "bufio" + "fmt" + "os" + "strconv" + "strings" +) + +// TLSStat struct represents data in /proc/net/tls_stat. +// See https://docs.kernel.org/networking/tls.html#statistics +type TLSStat struct { + // number of TX sessions currently installed where host handles cryptography + TLSCurrTxSw int + // number of RX sessions currently installed where host handles cryptography + TLSCurrRxSw int + // number of TX sessions currently installed where NIC handles cryptography + TLSCurrTxDevice int + // number of RX sessions currently installed where NIC handles cryptography + TLSCurrRxDevice int + //number of TX sessions opened with host cryptography + TLSTxSw int + //number of RX sessions opened with host cryptography + TLSRxSw int + // number of TX sessions opened with NIC cryptography + TLSTxDevice int + // number of RX sessions opened with NIC cryptography + TLSRxDevice int + // record decryption failed (e.g. due to incorrect authentication tag) + TLSDecryptError int + // number of RX resyncs sent to NICs handling cryptography + TLSRxDeviceResync int + // number of RX records which had to be re-decrypted due to TLS_RX_EXPECT_NO_PAD mis-prediction. Note that this counter will also increment for non-data records. + TLSDecryptRetry int + // number of data RX records which had to be re-decrypted due to TLS_RX_EXPECT_NO_PAD mis-prediction. + TLSRxNoPadViolation int +} + +// NewTLSStat reads the tls_stat statistics. +func NewTLSStat() (TLSStat, error) { + fs, err := NewFS(DefaultMountPoint) + if err != nil { + return TLSStat{}, err + } + + return fs.NewTLSStat() +} + +// NewTLSStat reads the tls_stat statistics. +func (fs FS) NewTLSStat() (TLSStat, error) { + file, err := os.Open(fs.proc.Path("net/tls_stat")) + if err != nil { + return TLSStat{}, err + } + defer file.Close() + + var ( + tlsstat = TLSStat{} + s = bufio.NewScanner(file) + ) + + for s.Scan() { + fields := strings.Fields(s.Text()) + + if len(fields) != 2 { + return TLSStat{}, fmt.Errorf("%w: %q line %q", ErrFileParse, file.Name(), s.Text()) + } + + name := fields[0] + value, err := strconv.Atoi(fields[1]) + if err != nil { + return TLSStat{}, err + } + + switch name { + case "TlsCurrTxSw": + tlsstat.TLSCurrTxSw = value + case "TlsCurrRxSw": + tlsstat.TLSCurrRxSw = value + case "TlsCurrTxDevice": + tlsstat.TLSCurrTxDevice = value + case "TlsCurrRxDevice": + tlsstat.TLSCurrRxDevice = value + case "TlsTxSw": + tlsstat.TLSTxSw = value + case "TlsRxSw": + tlsstat.TLSRxSw = value + case "TlsTxDevice": + tlsstat.TLSTxDevice = value + case "TlsRxDevice": + tlsstat.TLSRxDevice = value + case "TlsDecryptError": + tlsstat.TLSDecryptError = value + case "TlsRxDeviceResync": + tlsstat.TLSRxDeviceResync = value + case "TlsDecryptRetry": + tlsstat.TLSDecryptRetry = value + case "TlsRxNoPadViolation": + tlsstat.TLSRxNoPadViolation = value + } + + } + + return tlsstat, s.Err() +} diff --git a/vendor/github.com/prometheus/procfs/net_unix.go b/vendor/github.com/prometheus/procfs/net_unix.go index acbbc57ea..d868cebda 100644 --- a/vendor/github.com/prometheus/procfs/net_unix.go +++ b/vendor/github.com/prometheus/procfs/net_unix.go @@ -108,14 +108,14 @@ func parseNetUNIX(r io.Reader) (*NetUNIX, error) { line := s.Text() item, err := nu.parseLine(line, hasInode, minFields) if err != nil { - return nil, fmt.Errorf("%s: /proc/net/unix encountered data %q: %w", ErrFileParse, line, err) + return nil, fmt.Errorf("%w: /proc/net/unix encountered data %q: %w", ErrFileParse, line, err) } nu.Rows = append(nu.Rows, item) } if err := s.Err(); err != nil { - return nil, fmt.Errorf("%s: /proc/net/unix encountered data: %w", ErrFileParse, err) + return nil, fmt.Errorf("%w: /proc/net/unix encountered data: %w", ErrFileParse, err) } return &nu, nil @@ -136,29 +136,29 @@ func (u *NetUNIX) parseLine(line string, hasInode bool, min int) (*NetUNIXLine, users, err := u.parseUsers(fields[1]) if err != nil { - return nil, fmt.Errorf("%s: ref count %q: %w", ErrFileParse, fields[1], err) + return nil, fmt.Errorf("%w: ref count %q: %w", ErrFileParse, fields[1], err) } flags, err := u.parseFlags(fields[3]) if err != nil { - return nil, fmt.Errorf("%s: Unable to parse flags %q: %w", ErrFileParse, fields[3], err) + return nil, fmt.Errorf("%w: Unable to parse flags %q: %w", ErrFileParse, fields[3], err) } typ, err := u.parseType(fields[4]) if err != nil { - return nil, fmt.Errorf("%s: Failed to parse type %q: %w", ErrFileParse, fields[4], err) + return nil, fmt.Errorf("%w: Failed to parse type %q: %w", ErrFileParse, fields[4], err) } state, err := u.parseState(fields[5]) if err != nil { - return nil, fmt.Errorf("%s: Failed to parse state %q: %w", ErrFileParse, fields[5], err) + return nil, fmt.Errorf("%w: Failed to parse state %q: %w", ErrFileParse, fields[5], err) } var inode uint64 if hasInode { inode, err = u.parseInode(fields[6]) if err != nil { - return nil, fmt.Errorf("%s failed to parse inode %q: %w", ErrFileParse, fields[6], err) + return nil, fmt.Errorf("%w failed to parse inode %q: %w", ErrFileParse, fields[6], err) } } diff --git a/vendor/github.com/prometheus/procfs/net_wireless.go b/vendor/github.com/prometheus/procfs/net_wireless.go index 7443edca9..7c597bc87 100644 --- a/vendor/github.com/prometheus/procfs/net_wireless.go +++ b/vendor/github.com/prometheus/procfs/net_wireless.go @@ -68,7 +68,7 @@ func (fs FS) Wireless() ([]*Wireless, error) { m, err := parseWireless(bytes.NewReader(b)) if err != nil { - return nil, fmt.Errorf("%s: wireless: %w", ErrFileParse, err) + return nil, fmt.Errorf("%w: wireless: %w", ErrFileParse, err) } return m, nil @@ -114,47 +114,47 @@ func parseWireless(r io.Reader) ([]*Wireless, error) { qlink, err := strconv.Atoi(strings.TrimSuffix(stats[1], ".")) if err != nil { - return nil, fmt.Errorf("%s: parse Quality:link as integer %q: %w", ErrFileParse, qlink, err) + return nil, fmt.Errorf("%w: parse Quality:link as integer %q: %w", ErrFileParse, qlink, err) } qlevel, err := strconv.Atoi(strings.TrimSuffix(stats[2], ".")) if err != nil { - return nil, fmt.Errorf("%s: Quality:level as integer %q: %w", ErrFileParse, qlevel, err) + return nil, fmt.Errorf("%w: Quality:level as integer %q: %w", ErrFileParse, qlevel, err) } qnoise, err := strconv.Atoi(strings.TrimSuffix(stats[3], ".")) if err != nil { - return nil, fmt.Errorf("%s: Quality:noise as integer %q: %w", ErrFileParse, qnoise, err) + return nil, fmt.Errorf("%w: Quality:noise as integer %q: %w", ErrFileParse, qnoise, err) } dnwid, err := strconv.Atoi(stats[4]) if err != nil { - return nil, fmt.Errorf("%s: Discarded:nwid as integer %q: %w", ErrFileParse, dnwid, err) + return nil, fmt.Errorf("%w: Discarded:nwid as integer %q: %w", ErrFileParse, dnwid, err) } dcrypt, err := strconv.Atoi(stats[5]) if err != nil { - return nil, fmt.Errorf("%s: Discarded:crypt as integer %q: %w", ErrFileParse, dcrypt, err) + return nil, fmt.Errorf("%w: Discarded:crypt as integer %q: %w", ErrFileParse, dcrypt, err) } dfrag, err := strconv.Atoi(stats[6]) if err != nil { - return nil, fmt.Errorf("%s: Discarded:frag as integer %q: %w", ErrFileParse, dfrag, err) + return nil, fmt.Errorf("%w: Discarded:frag as integer %q: %w", ErrFileParse, dfrag, err) } dretry, err := strconv.Atoi(stats[7]) if err != nil { - return nil, fmt.Errorf("%s: Discarded:retry as integer %q: %w", ErrFileParse, dretry, err) + return nil, fmt.Errorf("%w: Discarded:retry as integer %q: %w", ErrFileParse, dretry, err) } dmisc, err := strconv.Atoi(stats[8]) if err != nil { - return nil, fmt.Errorf("%s: Discarded:misc as integer %q: %w", ErrFileParse, dmisc, err) + return nil, fmt.Errorf("%w: Discarded:misc as integer %q: %w", ErrFileParse, dmisc, err) } mbeacon, err := strconv.Atoi(stats[9]) if err != nil { - return nil, fmt.Errorf("%s: Missed:beacon as integer %q: %w", ErrFileParse, mbeacon, err) + return nil, fmt.Errorf("%w: Missed:beacon as integer %q: %w", ErrFileParse, mbeacon, err) } w := &Wireless{ @@ -175,7 +175,7 @@ func parseWireless(r io.Reader) ([]*Wireless, error) { } if err := scanner.Err(); err != nil { - return nil, fmt.Errorf("%s: Failed to scan /proc/net/wireless: %w", ErrFileRead, err) + return nil, fmt.Errorf("%w: Failed to scan /proc/net/wireless: %w", ErrFileRead, err) } return interfaces, nil diff --git a/vendor/github.com/prometheus/procfs/proc.go b/vendor/github.com/prometheus/procfs/proc.go index d1f71caa5..142796368 100644 --- a/vendor/github.com/prometheus/procfs/proc.go +++ b/vendor/github.com/prometheus/procfs/proc.go @@ -111,7 +111,7 @@ func (fs FS) AllProcs() (Procs, error) { names, err := d.Readdirnames(-1) if err != nil { - return Procs{}, fmt.Errorf("%s: Cannot read file: %v: %w", ErrFileRead, names, err) + return Procs{}, fmt.Errorf("%w: Cannot read file: %v: %w", ErrFileRead, names, err) } p := Procs{} @@ -137,7 +137,7 @@ func (p Proc) CmdLine() ([]string, error) { return []string{}, nil } - return strings.Split(string(bytes.TrimRight(data, string("\x00"))), string(byte(0))), nil + return strings.Split(string(bytes.TrimRight(data, "\x00")), "\x00"), nil } // Wchan returns the wchan (wait channel) of a process. @@ -212,7 +212,7 @@ func (p Proc) FileDescriptors() ([]uintptr, error) { for i, n := range names { fd, err := strconv.ParseInt(n, 10, 32) if err != nil { - return nil, fmt.Errorf("%s: Cannot parse line: %v: %w", ErrFileParse, i, err) + return nil, fmt.Errorf("%w: Cannot parse line: %v: %w", ErrFileParse, i, err) } fds[i] = uintptr(fd) } @@ -297,7 +297,7 @@ func (p Proc) fileDescriptors() ([]string, error) { names, err := d.Readdirnames(-1) if err != nil { - return nil, fmt.Errorf("%s: Cannot read file: %v: %w", ErrFileRead, names, err) + return nil, fmt.Errorf("%w: Cannot read file: %v: %w", ErrFileRead, names, err) } return names, nil diff --git a/vendor/github.com/prometheus/procfs/proc_limits.go b/vendor/github.com/prometheus/procfs/proc_limits.go index c86d815d7..9530b14bc 100644 --- a/vendor/github.com/prometheus/procfs/proc_limits.go +++ b/vendor/github.com/prometheus/procfs/proc_limits.go @@ -154,7 +154,7 @@ func parseUint(s string) (uint64, error) { } i, err := strconv.ParseUint(s, 10, 64) if err != nil { - return 0, fmt.Errorf("%s: couldn't parse value %q: %w", ErrFileParse, s, err) + return 0, fmt.Errorf("%w: couldn't parse value %q: %w", ErrFileParse, s, err) } return i, nil } diff --git a/vendor/github.com/prometheus/procfs/proc_ns.go b/vendor/github.com/prometheus/procfs/proc_ns.go index c22666750..0f8f847f9 100644 --- a/vendor/github.com/prometheus/procfs/proc_ns.go +++ b/vendor/github.com/prometheus/procfs/proc_ns.go @@ -40,7 +40,7 @@ func (p Proc) Namespaces() (Namespaces, error) { names, err := d.Readdirnames(-1) if err != nil { - return nil, fmt.Errorf("%s: failed to read contents of ns dir: %w", ErrFileRead, err) + return nil, fmt.Errorf("%w: failed to read contents of ns dir: %w", ErrFileRead, err) } ns := make(Namespaces, len(names)) @@ -58,7 +58,7 @@ func (p Proc) Namespaces() (Namespaces, error) { typ := fields[0] inode, err := strconv.ParseUint(strings.Trim(fields[1], "[]"), 10, 32) if err != nil { - return nil, fmt.Errorf("%s: inode from %q: %w", ErrFileParse, fields[1], err) + return nil, fmt.Errorf("%w: inode from %q: %w", ErrFileParse, fields[1], err) } ns[name] = Namespace{typ, uint32(inode)} diff --git a/vendor/github.com/prometheus/procfs/proc_psi.go b/vendor/github.com/prometheus/procfs/proc_psi.go index fe9dbb425..ccd35f153 100644 --- a/vendor/github.com/prometheus/procfs/proc_psi.go +++ b/vendor/github.com/prometheus/procfs/proc_psi.go @@ -61,7 +61,7 @@ type PSIStats struct { func (fs FS) PSIStatsForResource(resource string) (PSIStats, error) { data, err := util.ReadFileNoStat(fs.proc.Path(fmt.Sprintf("%s/%s", "pressure", resource))) if err != nil { - return PSIStats{}, fmt.Errorf("%s: psi_stats: unavailable for %q: %w", ErrFileRead, resource, err) + return PSIStats{}, fmt.Errorf("%w: psi_stats: unavailable for %q: %w", ErrFileRead, resource, err) } return parsePSIStats(bytes.NewReader(data)) diff --git a/vendor/github.com/prometheus/procfs/proc_smaps.go b/vendor/github.com/prometheus/procfs/proc_smaps.go index ad8785a40..09060e820 100644 --- a/vendor/github.com/prometheus/procfs/proc_smaps.go +++ b/vendor/github.com/prometheus/procfs/proc_smaps.go @@ -127,7 +127,7 @@ func (s *ProcSMapsRollup) parseLine(line string) error { } v := strings.TrimSpace(kv[1]) - v = strings.TrimRight(v, " kB") + v = strings.TrimSuffix(v, " kB") vKBytes, err := strconv.ParseUint(v, 10, 64) if err != nil { diff --git a/vendor/github.com/prometheus/procfs/proc_stat.go b/vendor/github.com/prometheus/procfs/proc_stat.go index 923e55005..06a8d931c 100644 --- a/vendor/github.com/prometheus/procfs/proc_stat.go +++ b/vendor/github.com/prometheus/procfs/proc_stat.go @@ -110,6 +110,11 @@ type ProcStat struct { Policy uint // Aggregated block I/O delays, measured in clock ticks (centiseconds). DelayAcctBlkIOTicks uint64 + // Guest time of the process (time spent running a virtual CPU for a guest + // operating system), measured in clock ticks. + GuestTime int + // Guest time of the process's children, measured in clock ticks. + CGuestTime int proc FS } @@ -189,6 +194,8 @@ func (p Proc) Stat() (ProcStat, error) { &s.RTPriority, &s.Policy, &s.DelayAcctBlkIOTicks, + &s.GuestTime, + &s.CGuestTime, ) if err != nil { return ProcStat{}, err diff --git a/vendor/github.com/prometheus/procfs/proc_status.go b/vendor/github.com/prometheus/procfs/proc_status.go index 46307f572..a055197c6 100644 --- a/vendor/github.com/prometheus/procfs/proc_status.go +++ b/vendor/github.com/prometheus/procfs/proc_status.go @@ -15,6 +15,7 @@ package procfs import ( "bytes" + "math/bits" "sort" "strconv" "strings" @@ -76,9 +77,9 @@ type ProcStatus struct { NonVoluntaryCtxtSwitches uint64 // UIDs of the process (Real, effective, saved set, and filesystem UIDs) - UIDs [4]string + UIDs [4]uint64 // GIDs of the process (Real, effective, saved set, and filesystem GIDs) - GIDs [4]string + GIDs [4]uint64 // CpusAllowedList: List of cpu cores processes are allowed to run on. CpusAllowedList []uint64 @@ -113,22 +114,37 @@ func (p Proc) NewStatus() (ProcStatus, error) { // convert kB to B vBytes := vKBytes * 1024 - s.fillStatus(k, v, vKBytes, vBytes) + err = s.fillStatus(k, v, vKBytes, vBytes) + if err != nil { + return ProcStatus{}, err + } } return s, nil } -func (s *ProcStatus) fillStatus(k string, vString string, vUint uint64, vUintBytes uint64) { +func (s *ProcStatus) fillStatus(k string, vString string, vUint uint64, vUintBytes uint64) error { switch k { case "Tgid": s.TGID = int(vUint) case "Name": s.Name = vString case "Uid": - copy(s.UIDs[:], strings.Split(vString, "\t")) + var err error + for i, v := range strings.Split(vString, "\t") { + s.UIDs[i], err = strconv.ParseUint(v, 10, bits.UintSize) + if err != nil { + return err + } + } case "Gid": - copy(s.GIDs[:], strings.Split(vString, "\t")) + var err error + for i, v := range strings.Split(vString, "\t") { + s.GIDs[i], err = strconv.ParseUint(v, 10, bits.UintSize) + if err != nil { + return err + } + } case "NSpid": s.NSpids = calcNSPidsList(vString) case "VmPeak": @@ -173,6 +189,7 @@ func (s *ProcStatus) fillStatus(k string, vString string, vUint uint64, vUintByt s.CpusAllowedList = calcCpusAllowedList(vString) } + return nil } // TotalCtxtSwitches returns the total context switch. diff --git a/vendor/github.com/prometheus/procfs/proc_sys.go b/vendor/github.com/prometheus/procfs/proc_sys.go index 12c5bf05b..5eefbe2ef 100644 --- a/vendor/github.com/prometheus/procfs/proc_sys.go +++ b/vendor/github.com/prometheus/procfs/proc_sys.go @@ -44,7 +44,7 @@ func (fs FS) SysctlInts(sysctl string) ([]int, error) { vp := util.NewValueParser(f) values[i] = vp.Int() if err := vp.Err(); err != nil { - return nil, fmt.Errorf("%s: field %d in sysctl %s is not a valid int: %w", ErrFileParse, i, sysctl, err) + return nil, fmt.Errorf("%w: field %d in sysctl %s is not a valid int: %w", ErrFileParse, i, sysctl, err) } } return values, nil diff --git a/vendor/github.com/prometheus/procfs/softirqs.go b/vendor/github.com/prometheus/procfs/softirqs.go index b8fad677d..28708e074 100644 --- a/vendor/github.com/prometheus/procfs/softirqs.go +++ b/vendor/github.com/prometheus/procfs/softirqs.go @@ -74,7 +74,7 @@ func parseSoftirqs(r io.Reader) (Softirqs, error) { softirqs.Hi = make([]uint64, len(perCPU)) for i, count := range perCPU { if softirqs.Hi[i], err = strconv.ParseUint(count, 10, 64); err != nil { - return Softirqs{}, fmt.Errorf("%s: couldn't parse %q (HI%d): %w", ErrFileParse, count, i, err) + return Softirqs{}, fmt.Errorf("%w: couldn't parse %q (HI%d): %w", ErrFileParse, count, i, err) } } case parts[0] == "TIMER:": @@ -82,7 +82,7 @@ func parseSoftirqs(r io.Reader) (Softirqs, error) { softirqs.Timer = make([]uint64, len(perCPU)) for i, count := range perCPU { if softirqs.Timer[i], err = strconv.ParseUint(count, 10, 64); err != nil { - return Softirqs{}, fmt.Errorf("%s: couldn't parse %q (TIMER%d): %w", ErrFileParse, count, i, err) + return Softirqs{}, fmt.Errorf("%w: couldn't parse %q (TIMER%d): %w", ErrFileParse, count, i, err) } } case parts[0] == "NET_TX:": @@ -90,7 +90,7 @@ func parseSoftirqs(r io.Reader) (Softirqs, error) { softirqs.NetTx = make([]uint64, len(perCPU)) for i, count := range perCPU { if softirqs.NetTx[i], err = strconv.ParseUint(count, 10, 64); err != nil { - return Softirqs{}, fmt.Errorf("%s: couldn't parse %q (NET_TX%d): %w", ErrFileParse, count, i, err) + return Softirqs{}, fmt.Errorf("%w: couldn't parse %q (NET_TX%d): %w", ErrFileParse, count, i, err) } } case parts[0] == "NET_RX:": @@ -98,7 +98,7 @@ func parseSoftirqs(r io.Reader) (Softirqs, error) { softirqs.NetRx = make([]uint64, len(perCPU)) for i, count := range perCPU { if softirqs.NetRx[i], err = strconv.ParseUint(count, 10, 64); err != nil { - return Softirqs{}, fmt.Errorf("%s: couldn't parse %q (NET_RX%d): %w", ErrFileParse, count, i, err) + return Softirqs{}, fmt.Errorf("%w: couldn't parse %q (NET_RX%d): %w", ErrFileParse, count, i, err) } } case parts[0] == "BLOCK:": @@ -106,7 +106,7 @@ func parseSoftirqs(r io.Reader) (Softirqs, error) { softirqs.Block = make([]uint64, len(perCPU)) for i, count := range perCPU { if softirqs.Block[i], err = strconv.ParseUint(count, 10, 64); err != nil { - return Softirqs{}, fmt.Errorf("%s: couldn't parse %q (BLOCK%d): %w", ErrFileParse, count, i, err) + return Softirqs{}, fmt.Errorf("%w: couldn't parse %q (BLOCK%d): %w", ErrFileParse, count, i, err) } } case parts[0] == "IRQ_POLL:": @@ -114,7 +114,7 @@ func parseSoftirqs(r io.Reader) (Softirqs, error) { softirqs.IRQPoll = make([]uint64, len(perCPU)) for i, count := range perCPU { if softirqs.IRQPoll[i], err = strconv.ParseUint(count, 10, 64); err != nil { - return Softirqs{}, fmt.Errorf("%s: couldn't parse %q (IRQ_POLL%d): %w", ErrFileParse, count, i, err) + return Softirqs{}, fmt.Errorf("%w: couldn't parse %q (IRQ_POLL%d): %w", ErrFileParse, count, i, err) } } case parts[0] == "TASKLET:": @@ -122,7 +122,7 @@ func parseSoftirqs(r io.Reader) (Softirqs, error) { softirqs.Tasklet = make([]uint64, len(perCPU)) for i, count := range perCPU { if softirqs.Tasklet[i], err = strconv.ParseUint(count, 10, 64); err != nil { - return Softirqs{}, fmt.Errorf("%s: couldn't parse %q (TASKLET%d): %w", ErrFileParse, count, i, err) + return Softirqs{}, fmt.Errorf("%w: couldn't parse %q (TASKLET%d): %w", ErrFileParse, count, i, err) } } case parts[0] == "SCHED:": @@ -130,7 +130,7 @@ func parseSoftirqs(r io.Reader) (Softirqs, error) { softirqs.Sched = make([]uint64, len(perCPU)) for i, count := range perCPU { if softirqs.Sched[i], err = strconv.ParseUint(count, 10, 64); err != nil { - return Softirqs{}, fmt.Errorf("%s: couldn't parse %q (SCHED%d): %w", ErrFileParse, count, i, err) + return Softirqs{}, fmt.Errorf("%w: couldn't parse %q (SCHED%d): %w", ErrFileParse, count, i, err) } } case parts[0] == "HRTIMER:": @@ -138,7 +138,7 @@ func parseSoftirqs(r io.Reader) (Softirqs, error) { softirqs.HRTimer = make([]uint64, len(perCPU)) for i, count := range perCPU { if softirqs.HRTimer[i], err = strconv.ParseUint(count, 10, 64); err != nil { - return Softirqs{}, fmt.Errorf("%s: couldn't parse %q (HRTIMER%d): %w", ErrFileParse, count, i, err) + return Softirqs{}, fmt.Errorf("%w: couldn't parse %q (HRTIMER%d): %w", ErrFileParse, count, i, err) } } case parts[0] == "RCU:": @@ -146,14 +146,14 @@ func parseSoftirqs(r io.Reader) (Softirqs, error) { softirqs.RCU = make([]uint64, len(perCPU)) for i, count := range perCPU { if softirqs.RCU[i], err = strconv.ParseUint(count, 10, 64); err != nil { - return Softirqs{}, fmt.Errorf("%s: couldn't parse %q (RCU%d): %w", ErrFileParse, count, i, err) + return Softirqs{}, fmt.Errorf("%w: couldn't parse %q (RCU%d): %w", ErrFileParse, count, i, err) } } } } if err := scanner.Err(); err != nil { - return Softirqs{}, fmt.Errorf("%s: couldn't parse softirqs: %w", ErrFileParse, err) + return Softirqs{}, fmt.Errorf("%w: couldn't parse softirqs: %w", ErrFileParse, err) } return softirqs, scanner.Err() diff --git a/vendor/github.com/prometheus/procfs/stat.go b/vendor/github.com/prometheus/procfs/stat.go index 34fc3ee21..e36b41c18 100644 --- a/vendor/github.com/prometheus/procfs/stat.go +++ b/vendor/github.com/prometheus/procfs/stat.go @@ -93,7 +93,7 @@ func parseCPUStat(line string) (CPUStat, int64, error) { &cpuStat.Guest, &cpuStat.GuestNice) if err != nil && err != io.EOF { - return CPUStat{}, -1, fmt.Errorf("%s: couldn't parse %q (cpu): %w", ErrFileParse, line, err) + return CPUStat{}, -1, fmt.Errorf("%w: couldn't parse %q (cpu): %w", ErrFileParse, line, err) } if count == 0 { return CPUStat{}, -1, fmt.Errorf("%w: couldn't parse %q (cpu): 0 elements parsed", ErrFileParse, line) @@ -116,7 +116,7 @@ func parseCPUStat(line string) (CPUStat, int64, error) { cpuID, err := strconv.ParseInt(cpu[3:], 10, 64) if err != nil { - return CPUStat{}, -1, fmt.Errorf("%s: couldn't parse %q (cpu/cpuid): %w", ErrFileParse, line, err) + return CPUStat{}, -1, fmt.Errorf("%w: couldn't parse %q (cpu/cpuid): %w", ErrFileParse, line, err) } return cpuStat, cpuID, nil @@ -136,7 +136,7 @@ func parseSoftIRQStat(line string) (SoftIRQStat, uint64, error) { &softIRQStat.Hrtimer, &softIRQStat.Rcu) if err != nil { - return SoftIRQStat{}, 0, fmt.Errorf("%s: couldn't parse %q (softirq): %w", ErrFileParse, line, err) + return SoftIRQStat{}, 0, fmt.Errorf("%w: couldn't parse %q (softirq): %w", ErrFileParse, line, err) } return softIRQStat, total, nil @@ -201,34 +201,34 @@ func parseStat(r io.Reader, fileName string) (Stat, error) { switch { case parts[0] == "btime": if stat.BootTime, err = strconv.ParseUint(parts[1], 10, 64); err != nil { - return Stat{}, fmt.Errorf("%s: couldn't parse %q (btime): %w", ErrFileParse, parts[1], err) + return Stat{}, fmt.Errorf("%w: couldn't parse %q (btime): %w", ErrFileParse, parts[1], err) } case parts[0] == "intr": if stat.IRQTotal, err = strconv.ParseUint(parts[1], 10, 64); err != nil { - return Stat{}, fmt.Errorf("%s: couldn't parse %q (intr): %w", ErrFileParse, parts[1], err) + return Stat{}, fmt.Errorf("%w: couldn't parse %q (intr): %w", ErrFileParse, parts[1], err) } numberedIRQs := parts[2:] stat.IRQ = make([]uint64, len(numberedIRQs)) for i, count := range numberedIRQs { if stat.IRQ[i], err = strconv.ParseUint(count, 10, 64); err != nil { - return Stat{}, fmt.Errorf("%s: couldn't parse %q (intr%d): %w", ErrFileParse, count, i, err) + return Stat{}, fmt.Errorf("%w: couldn't parse %q (intr%d): %w", ErrFileParse, count, i, err) } } case parts[0] == "ctxt": if stat.ContextSwitches, err = strconv.ParseUint(parts[1], 10, 64); err != nil { - return Stat{}, fmt.Errorf("%s: couldn't parse %q (ctxt): %w", ErrFileParse, parts[1], err) + return Stat{}, fmt.Errorf("%w: couldn't parse %q (ctxt): %w", ErrFileParse, parts[1], err) } case parts[0] == "processes": if stat.ProcessCreated, err = strconv.ParseUint(parts[1], 10, 64); err != nil { - return Stat{}, fmt.Errorf("%s: couldn't parse %q (processes): %w", ErrFileParse, parts[1], err) + return Stat{}, fmt.Errorf("%w: couldn't parse %q (processes): %w", ErrFileParse, parts[1], err) } case parts[0] == "procs_running": if stat.ProcessesRunning, err = strconv.ParseUint(parts[1], 10, 64); err != nil { - return Stat{}, fmt.Errorf("%s: couldn't parse %q (procs_running): %w", ErrFileParse, parts[1], err) + return Stat{}, fmt.Errorf("%w: couldn't parse %q (procs_running): %w", ErrFileParse, parts[1], err) } case parts[0] == "procs_blocked": if stat.ProcessesBlocked, err = strconv.ParseUint(parts[1], 10, 64); err != nil { - return Stat{}, fmt.Errorf("%s: couldn't parse %q (procs_blocked): %w", ErrFileParse, parts[1], err) + return Stat{}, fmt.Errorf("%w: couldn't parse %q (procs_blocked): %w", ErrFileParse, parts[1], err) } case parts[0] == "softirq": softIRQStats, total, err := parseSoftIRQStat(line) @@ -251,7 +251,7 @@ func parseStat(r io.Reader, fileName string) (Stat, error) { } if err := scanner.Err(); err != nil { - return Stat{}, fmt.Errorf("%s: couldn't parse %q: %w", ErrFileParse, fileName, err) + return Stat{}, fmt.Errorf("%w: couldn't parse %q: %w", ErrFileParse, fileName, err) } return stat, nil diff --git a/vendor/github.com/prometheus/procfs/swaps.go b/vendor/github.com/prometheus/procfs/swaps.go index fa00f555d..65fec834b 100644 --- a/vendor/github.com/prometheus/procfs/swaps.go +++ b/vendor/github.com/prometheus/procfs/swaps.go @@ -74,15 +74,15 @@ func parseSwapString(swapString string) (*Swap, error) { swap.Size, err = strconv.Atoi(swapFields[2]) if err != nil { - return nil, fmt.Errorf("%s: invalid swap size: %s: %w", ErrFileParse, swapFields[2], err) + return nil, fmt.Errorf("%w: invalid swap size: %s: %w", ErrFileParse, swapFields[2], err) } swap.Used, err = strconv.Atoi(swapFields[3]) if err != nil { - return nil, fmt.Errorf("%s: invalid swap used: %s: %w", ErrFileParse, swapFields[3], err) + return nil, fmt.Errorf("%w: invalid swap used: %s: %w", ErrFileParse, swapFields[3], err) } swap.Priority, err = strconv.Atoi(swapFields[4]) if err != nil { - return nil, fmt.Errorf("%s: invalid swap priority: %s: %w", ErrFileParse, swapFields[4], err) + return nil, fmt.Errorf("%w: invalid swap priority: %s: %w", ErrFileParse, swapFields[4], err) } return swap, nil diff --git a/vendor/github.com/prometheus/procfs/thread.go b/vendor/github.com/prometheus/procfs/thread.go index df2215ece..80e0e947b 100644 --- a/vendor/github.com/prometheus/procfs/thread.go +++ b/vendor/github.com/prometheus/procfs/thread.go @@ -45,7 +45,7 @@ func (fs FS) AllThreads(pid int) (Procs, error) { names, err := d.Readdirnames(-1) if err != nil { - return Procs{}, fmt.Errorf("%s: could not read %q: %w", ErrFileRead, d.Name(), err) + return Procs{}, fmt.Errorf("%w: could not read %q: %w", ErrFileRead, d.Name(), err) } t := Procs{} diff --git a/vendor/github.com/prometheus/procfs/zoneinfo.go b/vendor/github.com/prometheus/procfs/zoneinfo.go index ce5fefa5b..e54d94b09 100644 --- a/vendor/github.com/prometheus/procfs/zoneinfo.go +++ b/vendor/github.com/prometheus/procfs/zoneinfo.go @@ -75,11 +75,11 @@ var nodeZoneRE = regexp.MustCompile(`(\d+), zone\s+(\w+)`) func (fs FS) Zoneinfo() ([]Zoneinfo, error) { data, err := os.ReadFile(fs.proc.Path("zoneinfo")) if err != nil { - return nil, fmt.Errorf("%s: error reading zoneinfo %q: %w", ErrFileRead, fs.proc.Path("zoneinfo"), err) + return nil, fmt.Errorf("%w: error reading zoneinfo %q: %w", ErrFileRead, fs.proc.Path("zoneinfo"), err) } zoneinfo, err := parseZoneinfo(data) if err != nil { - return nil, fmt.Errorf("%s: error parsing zoneinfo %q: %w", ErrFileParse, fs.proc.Path("zoneinfo"), err) + return nil, fmt.Errorf("%w: error parsing zoneinfo %q: %w", ErrFileParse, fs.proc.Path("zoneinfo"), err) } return zoneinfo, nil } diff --git a/vendor/github.com/quic-go/quic-go/.gitignore b/vendor/github.com/quic-go/quic-go/.gitignore index 3cc06f240..b454729d5 100644 --- a/vendor/github.com/quic-go/quic-go/.gitignore +++ b/vendor/github.com/quic-go/quic-go/.gitignore @@ -4,6 +4,7 @@ main mockgen_tmp.go *.qtr *.qlog +*.sqlog *.txt race.[0-9]* diff --git a/vendor/github.com/quic-go/quic-go/.golangci.yml b/vendor/github.com/quic-go/quic-go/.golangci.yml index 469d54cfb..63b40cc34 100644 --- a/vendor/github.com/quic-go/quic-go/.golangci.yml +++ b/vendor/github.com/quic-go/quic-go/.golangci.yml @@ -1,21 +1,29 @@ -run: - skip-files: - - internal/handshake/cipher_suite.go linters-settings: misspell: ignore-words: - ect + depguard: + rules: + quicvarint: + list-mode: strict + files: + - "**/github.com/quic-go/quic-go/quicvarint/*" + - "!$test" + allow: + - $gostd linters: disable-all: true enable: - asciicheck + - depguard - exhaustive - exportloopref - goimports - gofmt # redundant, since gofmt *should* be a no-op after gofumpt - gofumpt - gosimple + - govet - ineffassign - misspell - prealloc @@ -24,10 +32,15 @@ linters: - unconvert - unparam - unused - - vet issues: + exclude-files: + - internal/handshake/cipher_suite.go exclude-rules: - path: internal/qtls linters: - depguard + - path: _test\.go + linters: + - exhaustive + - prealloc diff --git a/vendor/github.com/quic-go/quic-go/README.md b/vendor/github.com/quic-go/quic-go/README.md index faba82f3d..94823d994 100644 --- a/vendor/github.com/quic-go/quic-go/README.md +++ b/vendor/github.com/quic-go/quic-go/README.md @@ -2,11 +2,12 @@ +[![Documentation](https://img.shields.io/badge/docs-quic--go.net-red?style=flat)](https://quic-go.net/docs/) [![PkgGoDev](https://pkg.go.dev/badge/github.com/quic-go/quic-go)](https://pkg.go.dev/github.com/quic-go/quic-go) [![Code Coverage](https://img.shields.io/codecov/c/github/quic-go/quic-go/master.svg?style=flat-square)](https://codecov.io/gh/quic-go/quic-go/) [![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/quic-go.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:quic-go) -quic-go is an implementation of the QUIC protocol ([RFC 9000](https://datatracker.ietf.org/doc/html/rfc9000), [RFC 9001](https://datatracker.ietf.org/doc/html/rfc9001), [RFC 9002](https://datatracker.ietf.org/doc/html/rfc9002)) in Go. It has support for HTTP/3 ([RFC 9114](https://datatracker.ietf.org/doc/html/rfc9114)), including QPACK ([RFC 9204](https://datatracker.ietf.org/doc/html/rfc9204)). +quic-go is an implementation of the QUIC protocol ([RFC 9000](https://datatracker.ietf.org/doc/html/rfc9000), [RFC 9001](https://datatracker.ietf.org/doc/html/rfc9001), [RFC 9002](https://datatracker.ietf.org/doc/html/rfc9002)) in Go. It has support for HTTP/3 ([RFC 9114](https://datatracker.ietf.org/doc/html/rfc9114)), including QPACK ([RFC 9204](https://datatracker.ietf.org/doc/html/rfc9204)) and HTTP Datagrams ([RFC 9297](https://datatracker.ietf.org/doc/html/rfc9297)). In addition to these base RFCs, it also implements the following RFCs: * Unreliable Datagram Extension ([RFC 9221](https://datatracker.ietf.org/doc/html/rfc9221)) @@ -16,207 +17,7 @@ In addition to these base RFCs, it also implements the following RFCs: Support for WebTransport over HTTP/3 ([draft-ietf-webtrans-http3](https://datatracker.ietf.org/doc/draft-ietf-webtrans-http3/)) is implemented in [webtransport-go](https://github.com/quic-go/webtransport-go). -## Using QUIC - -### Running a Server - -The central entry point is the `quic.Transport`. A transport manages QUIC connections running on a single UDP socket. Since QUIC uses Connection IDs, it can demultiplex a listener (accepting incoming connections) and an arbitrary number of outgoing QUIC connections on the same UDP socket. - -```go -udpConn, err := net.ListenUDP("udp4", &net.UDPAddr{Port: 1234}) -// ... error handling -tr := quic.Transport{ - Conn: udpConn, -} -ln, err := tr.Listen(tlsConf, quicConf) -// ... error handling -go func() { - for { - conn, err := ln.Accept() - // ... error handling - // handle the connection, usually in a new Go routine - } -}() -``` - -The listener `ln` can now be used to accept incoming QUIC connections by (repeatedly) calling the `Accept` method (see below for more information on the `quic.Connection`). - -As a shortcut, `quic.Listen` and `quic.ListenAddr` can be used without explicitly initializing a `quic.Transport`: - -``` -ln, err := quic.Listen(udpConn, tlsConf, quicConf) -``` - -When using the shortcut, it's not possible to reuse the same UDP socket for outgoing connections. - -### Running a Client - -As mentioned above, multiple outgoing connections can share a single UDP socket, since QUIC uses Connection IDs to demultiplex connections. - -```go -ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) // 3s handshake timeout -defer cancel() -conn, err := tr.Dial(ctx, , , ) -// ... error handling -``` - -As a shortcut, `quic.Dial` and `quic.DialAddr` can be used without explictly initializing a `quic.Transport`: - -```go -ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) // 3s handshake timeout -defer cancel() -conn, err := quic.Dial(ctx, conn, , , ) -``` - -Just as we saw before when used a similar shortcut to run a server, it's also not possible to reuse the same UDP socket for other outgoing connections, or to listen for incoming connections. - -### Using a QUIC Connection - -#### Accepting Streams - -QUIC is a stream-multiplexed transport. A `quic.Connection` fundamentally differs from the `net.Conn` and the `net.PacketConn` interface defined in the standard library. Data is sent and received on (unidirectional and bidirectional) streams (and, if supported, in [datagrams](#quic-datagrams)), not on the connection itself. The stream state machine is described in detail in [Section 3 of RFC 9000](https://datatracker.ietf.org/doc/html/rfc9000#section-3). - -Note: A unidirectional stream is a stream that the initiator can only write to (`quic.SendStream`), and the receiver can only read from (`quic.ReceiveStream`). A bidirectional stream (`quic.Stream`) allows reading from and writing to for both sides. - -On the receiver side, streams are accepted using the `AcceptStream` (for bidirectional) and `AcceptUniStream` functions. For most user cases, it makes sense to call these functions in a loop: - -```go -for { - str, err := conn.AcceptStream(context.Background()) // for bidirectional streams - // ... error handling - // handle the stream, usually in a new Go routine -} -``` - -These functions return an error when the underlying QUIC connection is closed. - -#### Opening Streams - -There are two slightly different ways to open streams, one synchronous and one (potentially) asynchronous. This API is necessary since the receiver grants us a certain number of streams that we're allowed to open. It may grant us additional streams later on (typically when existing streams are closed), but it means that at the time we want to open a new stream, we might not be able to do so. - -Using the synchronous method `OpenStreamSync` for bidirectional streams, and `OpenUniStreamSync` for unidirectional streams, an application can block until the peer allows opening additional streams. In case that we're allowed to open a new stream, these methods return right away: - -```go -ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) -defer cancel() -str, err := conn.OpenStreamSync(ctx) // wait up to 5s to open a new bidirectional stream -``` - -The asynchronous version never blocks. If it's currently not possible to open a new stream, it returns a `net.Error` timeout error: - -```go -str, err := conn.OpenStream() -if nerr, ok := err.(net.Error); ok && nerr.Timeout() { - // It's currently not possible to open another stream, - // but it might be possible later, once the peer allowed us to do so. -} -``` - -These functions return an error when the underlying QUIC connection is closed. - -#### Using Streams - -Using QUIC streams is pretty straightforward. The `quic.ReceiveStream` implements the `io.Reader` interface, and the `quic.SendStream` implements the `io.Writer` interface. A bidirectional stream (`quic.Stream`) implements both these interfaces. Conceptually, a bidirectional stream can be thought of as the composition of two unidirectional streams in opposite directions. - -Calling `Close` on a `quic.SendStream` or a `quic.Stream` closes the send side of the stream. On the receiver side, this will be surfaced as an `io.EOF` returned from the `io.Reader` once all data has been consumed. Note that for bidirectional streams, `Close` _only_ closes the send side of the stream. It is still possible to read from the stream until the peer closes or resets the stream. - -In case the application wishes to abort sending on a `quic.SendStream` or a `quic.Stream` , it can reset the send side by calling `CancelWrite` with an application-defined error code (an unsigned 62-bit number). On the receiver side, this surfaced as a `quic.StreamError` containing that error code on the `io.Reader`. Note that for bidirectional streams, `CancelWrite` _only_ resets the send side of the stream. It is still possible to read from the stream until the peer closes or resets the stream. - -Conversely, in case the application wishes to abort receiving from a `quic.ReceiveStream` or a `quic.Stream`, it can ask the sender to abort data transmission by calling `CancelRead` with an application-defined error code (an unsigned 62-bit number). On the receiver side, this surfaced as a `quic.StreamError` containing that error code on the `io.Writer`. Note that for bidirectional streams, `CancelWrite` _only_ resets the receive side of the stream. It is still possible to write to the stream. - -A bidirectional stream is only closed once both the read and the write side of the stream have been either closed or reset. Only then the peer is granted a new stream according to the maximum number of concurrent streams configured via `quic.Config.MaxIncomingStreams`. - -### Configuring QUIC - -The `quic.Config` struct passed to both the listen and dial calls (see above) contains a wide range of configuration options for QUIC connections, incl. the ability to fine-tune flow control limits, the number of streams that the peer is allowed to open concurrently, keep-alives, idle timeouts, and many more. Please refer to the documentation for the `quic.Config` for details. - -The `quic.Transport` contains a few configuration options that don't apply to any single QUIC connection, but to all connections handled by that transport. It is highly recommend to set the `StatelessResetToken`, which allows endpoints to quickly recover from crashes / reboots of our node (see [Section 10.3 of RFC 9000](https://datatracker.ietf.org/doc/html/rfc9000#section-10.3)). - -### Closing a Connection - -#### When the remote Peer closes the Connection - -In case the peer closes the QUIC connection, all calls to open streams, accept streams, as well as all methods on streams immediately return an error. Additionally, it is set as cancellation cause of the connection context. Users can use errors assertions to find out what exactly went wrong: - -* `quic.VersionNegotiationError`: Happens during the handshake, if there is no overlap between our and the remote's supported QUIC versions. -* `quic.HandshakeTimeoutError`: Happens if the QUIC handshake doesn't complete within the time specified in `quic.Config.HandshakeTimeout`. -* `quic.IdleTimeoutError`: Happens after completion of the handshake if the connection is idle for longer than the minimum of both peers idle timeouts (as configured by `quic.Config.IdleTimeout`). The connection is considered idle when no stream data (and datagrams, if applicable) are exchanged for that period. The QUIC connection can be instructed to regularly send a packet to prevent a connection from going idle by setting `quic.Config.KeepAlive`. However, this is no guarantee that the peer doesn't suddenly go away (e.g. by abruptly shutting down the node or by crashing), or by a NAT binding expiring, in which case this error might still occur. -* `quic.StatelessResetError`: Happens when the remote peer lost the state required to decrypt the packet. This requires the `quic.Transport.StatelessResetToken` to be configured by the peer. -* `quic.TransportError`: Happens if when the QUIC protocol is violated. Unless the error code is `APPLICATION_ERROR`, this will not happen unless one of the QUIC stacks involved is misbehaving. Please open an issue if you encounter this error. -* `quic.ApplicationError`: Happens when the remote decides to close the connection, see below. - -#### Initiated by the Application - -A `quic.Connection` can be closed using `CloseWithError`: - -```go -conn.CloseWithError(0x42, "error 0x42 occurred") -``` - -Applications can transmit both an error code (an unsigned 62-bit number) as well as a UTF-8 encoded human-readable reason. The error code allows the receiver to learn why the connection was closed, and the reason can be useful for debugging purposes. - -On the receiver side, this is surfaced as a `quic.ApplicationError`. - -### QUIC Datagrams - -Unreliable datagrams are a QUIC extension ([RFC 9221](https://datatracker.ietf.org/doc/html/rfc9221)) that is negotiated during the handshake. Support can be enabled by setting the `quic.Config.EnableDatagram` flag. Note that this doesn't guarantee that the peer also supports datagrams. Whether or not the feature negotiation succeeded can be learned from the `quic.ConnectionState.SupportsDatagrams` obtained from `quic.Connection.ConnectionState()`. - -QUIC DATAGRAMs are a new QUIC frame type sent in QUIC 1-RTT packets (i.e. after completion of the handshake). Therefore, they're end-to-end encrypted and congestion-controlled. However, if a DATAGRAM frame is deemed lost by QUIC's loss detection mechanism, they are not retransmitted. - -Datagrams are sent using the `SendDatagram` method on the `quic.Connection`: - -```go -conn.SendDatagram([]byte("foobar")) -``` - -And received using `ReceiveDatagram`: - -```go -msg, err := conn.ReceiveDatagram() -``` - -Note that this code path is currently not optimized. It works for datagrams that are sent occasionally, but it doesn't achieve the same throughput as writing data on a stream. Please get in touch on issue #3766 if your use case relies on high datagram throughput, or if you'd like to help fix this issue. There are also some restrictions regarding the maximum message size (see #3599). - -### QUIC Event Logging using qlog - -quic-go logs a wide range of events defined in [draft-ietf-quic-qlog-quic-events](https://datatracker.ietf.org/doc/draft-ietf-quic-qlog-quic-events/), providing comprehensive insights in the internals of a QUIC connection. - -qlog files can be processed by a number of 3rd-party tools. [qviz](https://qvis.quictools.info/) has proven very useful for debugging all kinds of QUIC connection failures. - -qlog can be activated by setting the `Tracer` callback on the `Config`. It is called as soon as quic-go decides to start the QUIC handshake on a new connection. -`qlog.DefaultTracer` provides a tracer implementation which writes qlog files to a directory specified by the `QLOGDIR` environment variable, if set. -The default qlog tracer can be used like this: -```go -quic.Config{ - Tracer: qlog.DefaultTracer, -} -``` - -This example creates a new qlog file under `/_.qlog`, e.g. `qlogs/2e0407da_client.qlog`. - - -For custom qlog behavior, `qlog.NewConnectionTracer` can be used. - -## Using HTTP/3 - -### As a server - -See the [example server](example/main.go). Starting a QUIC server is very similar to the standard library http package in Go: - -```go -http.Handle("/", http.FileServer(http.Dir(wwwDir))) -http3.ListenAndServeQUIC("localhost:4242", "/path/to/cert/chain.pem", "/path/to/privkey.pem", nil) -``` - -### As a client - -See the [example client](example/client/main.go). Use a `http3.RoundTripper` as a `Transport` in a `http.Client`. - -```go -http.Client{ - Transport: &http3.RoundTripper{}, -} -``` +Detailed documentation can be found on [quic-go.net](https://quic-go.net/docs/). ## Projects using quic-go diff --git a/vendor/github.com/quic-go/quic-go/client.go b/vendor/github.com/quic-go/quic-go/client.go index 70dd5e19c..1c5654f6d 100644 --- a/vendor/github.com/quic-go/quic-go/client.go +++ b/vendor/github.com/quic-go/quic-go/client.go @@ -35,7 +35,7 @@ type client struct { conn quicConn tracer *logging.ConnectionTracer - tracingID uint64 + tracingID ConnectionTracingID logger utils.Logger } @@ -191,6 +191,7 @@ func (c *client) dial(ctx context.Context) error { c.logger.Infof("Starting new connection to %s (%s -> %s), source connection ID %s, destination connection ID %s, version %s", c.tlsConf.ServerName, c.sendConn.LocalAddr(), c.sendConn.RemoteAddr(), c.srcConnID, c.destConnID, c.version) c.conn = newClientConnection( + context.WithValue(context.WithoutCancel(ctx), ConnectionTracingKey, c.tracingID), c.sendConn, c.packetHandlers, c.destConnID, @@ -202,7 +203,6 @@ func (c *client) dial(ctx context.Context) error { c.use0RTT, c.hasNegotiatedVersion, c.tracer, - c.tracingID, c.logger, c.version, ) diff --git a/vendor/github.com/quic-go/quic-go/config.go b/vendor/github.com/quic-go/quic-go/config.go index ee032e6ea..d42bdc1c5 100644 --- a/vendor/github.com/quic-go/quic-go/config.go +++ b/vendor/github.com/quic-go/quic-go/config.go @@ -39,6 +39,12 @@ func validateConfig(config *Config) error { if config.MaxConnectionReceiveWindow > quicvarint.Max { config.MaxConnectionReceiveWindow = quicvarint.Max } + if config.InitialPacketSize > 0 && config.InitialPacketSize < protocol.MinInitialPacketSize { + config.InitialPacketSize = protocol.MinInitialPacketSize + } + if config.InitialPacketSize > protocol.MaxPacketBufferSize { + config.InitialPacketSize = protocol.MaxPacketBufferSize + } // check that all QUIC versions are actually supported for _, v := range config.Versions { if !protocol.IsValidVersion(v) { @@ -94,6 +100,10 @@ func populateConfig(config *Config) *Config { } else if maxIncomingUniStreams < 0 { maxIncomingUniStreams = 0 } + initialPacketSize := config.InitialPacketSize + if initialPacketSize == 0 { + initialPacketSize = protocol.InitialPacketSize + } return &Config{ GetConfigForClient: config.GetConfigForClient, @@ -110,6 +120,7 @@ func populateConfig(config *Config) *Config { MaxIncomingUniStreams: maxIncomingUniStreams, TokenStore: config.TokenStore, EnableDatagrams: config.EnableDatagrams, + InitialPacketSize: initialPacketSize, DisablePathMTUDiscovery: config.DisablePathMTUDiscovery, Allow0RTT: config.Allow0RTT, Tracer: config.Tracer, diff --git a/vendor/github.com/quic-go/quic-go/connection.go b/vendor/github.com/quic-go/quic-go/connection.go index f8bcd613c..1411a77b7 100644 --- a/vendor/github.com/quic-go/quic-go/connection.go +++ b/vendor/github.com/quic-go/quic-go/connection.go @@ -16,7 +16,6 @@ import ( "github.com/quic-go/quic-go/internal/ackhandler" "github.com/quic-go/quic-go/internal/flowcontrol" "github.com/quic-go/quic-go/internal/handshake" - "github.com/quic-go/quic-go/internal/logutils" "github.com/quic-go/quic-go/internal/protocol" "github.com/quic-go/quic-go/internal/qerr" "github.com/quic-go/quic-go/internal/utils" @@ -25,15 +24,10 @@ import ( ) type unpacker interface { - UnpackLongHeader(hdr *wire.Header, rcvTime time.Time, data []byte, v protocol.Version) (*unpackedPacket, error) + UnpackLongHeader(hdr *wire.Header, data []byte) (*unpackedPacket, error) UnpackShortHeader(rcvTime time.Time, data []byte) (protocol.PacketNumber, protocol.PacketNumberLen, protocol.KeyPhaseBit, []byte, error) } -type streamGetter interface { - GetOrOpenReceiveStream(protocol.StreamID) (receiveStreamI, error) - GetOrOpenSendStream(protocol.StreamID) (sendStreamI, error) -} - type streamManager interface { GetOrOpenSendStream(protocol.StreamID) (sendStreamI, error) GetOrOpenReceiveStream(protocol.StreamID) (receiveStreamI, error) @@ -52,13 +46,14 @@ type streamManager interface { } type cryptoStreamHandler interface { - StartHandshake() error + StartHandshake(context.Context) error ChangeConnectionID(protocol.ConnectionID) SetLargest1RTTAcked(protocol.PacketNumber) error SetHandshakeConfirmed() GetSessionTicket() ([]byte, error) NextEvent() handshake.Event DiscardInitialKeys() + HandleMessage([]byte, protocol.EncryptionLevel) error io.Closer ConnectionState() handshake.ConnectionState } @@ -113,8 +108,8 @@ func (e *errCloseForRecreating) Error() string { return "closing connection in order to recreate it" } -var connTracingID uint64 // to be accessed atomically -func nextConnTracingID() uint64 { return atomic.AddUint64(&connTracingID, 1) } +var connTracingID atomic.Uint64 // to be accessed atomically +func nextConnTracingID() ConnectionTracingID { return ConnectionTracingID(connTracingID.Add(1)) } // A Connection is a QUIC connection type connection struct { @@ -144,8 +139,7 @@ type connection struct { sentPacketHandler ackhandler.SentPacketHandler receivedPacketHandler ackhandler.ReceivedPacketHandler retransmissionQueue *retransmissionQueue - framer framer - windowUpdateQueue *windowUpdateQueue + framer *framer connFlowController flowcontrol.ConnectionFlowController tokenStoreKey string // only set for the client tokenGenerator *handshake.TokenGenerator // only set for the server @@ -153,11 +147,13 @@ type connection struct { unpacker unpacker frameParser wire.FrameParser packer packer - mtuDiscoverer mtuDiscoverer // initialized when the handshake completes + mtuDiscoverer mtuDiscoverer // initialized when the transport parameters are received + + maxPayloadSizeEstimate atomic.Uint32 - initialStream cryptoStream - handshakeStream cryptoStream - oneRTTStream cryptoStream // only set for the server + initialStream *cryptoStream + handshakeStream *cryptoStream + oneRTTStream *cryptoStream // only set for the server cryptoStreamHandler cryptoStreamHandler receivedPackets chan receivedPacket @@ -167,10 +163,9 @@ type connection struct { // closeChan is used to notify the run loop that it should terminate closeChan chan closeError - ctx context.Context - ctxCancel context.CancelCauseFunc - handshakeCtx context.Context - handshakeCtxCancel context.CancelFunc + ctx context.Context + ctxCancel context.CancelCauseFunc + handshakeCompleteChan chan struct{} undecryptablePackets []receivedPacket // undecryptable packets, waiting for a change in encryption level undecryptablePacketsToProcess []receivedPacket @@ -220,6 +215,8 @@ var ( ) var newConnection = func( + ctx context.Context, + ctxCancel context.CancelCauseFunc, conn sendConn, runner connRunner, origDestConnID protocol.ConnectionID, @@ -234,11 +231,12 @@ var newConnection = func( tokenGenerator *handshake.TokenGenerator, clientAddressValidated bool, tracer *logging.ConnectionTracer, - tracingID uint64, logger utils.Logger, v protocol.Version, ) quicConn { s := &connection{ + ctx: ctx, + ctxCancel: ctxCancel, conn: conn, config: conf, handshakeDestConnID: destConnID, @@ -273,10 +271,9 @@ var newConnection = func( connIDGenerator, ) s.preSetup() - s.ctx, s.ctxCancel = context.WithCancelCause(context.WithValue(context.Background(), ConnectionTracingKey, tracingID)) s.sentPacketHandler, s.receivedPacketHandler = ackhandler.NewAckHandler( 0, - getMaxPacketSize(s.conn.RemoteAddr()), + protocol.ByteCount(s.config.InitialPacketSize), s.rttStats, clientAddressValidated, s.conn.capabilities().ECN, @@ -284,7 +281,7 @@ var newConnection = func( s.tracer, s.logger, ) - s.mtuDiscoverer = newMTUDiscoverer(s.rttStats, getMaxPacketSize(s.conn.RemoteAddr()), s.sentPacketHandler.SetMaxDatagramSize) + s.maxPayloadSizeEstimate.Store(uint32(estimateMaxPayloadSize(protocol.ByteCount(s.config.InitialPacketSize)))) params := &wire.TransportParameters{ InitialMaxStreamDataBidiLocal: protocol.ByteCount(s.config.InitialStreamReceiveWindow), InitialMaxStreamDataBidiRemote: protocol.ByteCount(s.config.InitialStreamReceiveWindow), @@ -295,6 +292,7 @@ var newConnection = func( MaxUniStreamNum: protocol.StreamNum(s.config.MaxIncomingUniStreams), MaxAckDelay: protocol.MaxAckDelayInclGranularity, AckDelayExponent: protocol.AckDelayExponent, + MaxUDPPayloadSize: protocol.MaxPacketBufferSize, DisableActiveMigration: true, StatelessResetToken: &statelessResetToken, OriginalDestinationConnectionID: origDestConnID, @@ -330,12 +328,13 @@ var newConnection = func( s.cryptoStreamHandler = cs s.packer = newPacketPacker(srcConnID, s.connIDManager.Get, s.initialStream, s.handshakeStream, s.sentPacketHandler, s.retransmissionQueue, cs, s.framer, s.receivedPacketHandler, s.datagramQueue, s.perspective) s.unpacker = newPacketUnpacker(cs, s.srcConnIDLen) - s.cryptoStreamManager = newCryptoStreamManager(cs, s.initialStream, s.handshakeStream, s.oneRTTStream) + s.cryptoStreamManager = newCryptoStreamManager(s.initialStream, s.handshakeStream, s.oneRTTStream) return s } // declare this as a variable, such that we can it mock it in the tests var newClientConnection = func( + ctx context.Context, conn sendConn, runner connRunner, destConnID protocol.ConnectionID, @@ -347,7 +346,6 @@ var newClientConnection = func( enable0RTT bool, hasNegotiatedVersion bool, tracer *logging.ConnectionTracer, - tracingID uint64, logger utils.Logger, v protocol.Version, ) quicConn { @@ -381,11 +379,11 @@ var newClientConnection = func( s.queueControlFrame, connIDGenerator, ) + s.ctx, s.ctxCancel = context.WithCancelCause(ctx) s.preSetup() - s.ctx, s.ctxCancel = context.WithCancelCause(context.WithValue(context.Background(), ConnectionTracingKey, tracingID)) s.sentPacketHandler, s.receivedPacketHandler = ackhandler.NewAckHandler( initialPacketNumber, - getMaxPacketSize(s.conn.RemoteAddr()), + protocol.ByteCount(s.config.InitialPacketSize), s.rttStats, false, // has no effect s.conn.capabilities().ECN, @@ -393,7 +391,7 @@ var newClientConnection = func( s.tracer, s.logger, ) - s.mtuDiscoverer = newMTUDiscoverer(s.rttStats, getMaxPacketSize(s.conn.RemoteAddr()), s.sentPacketHandler.SetMaxDatagramSize) + s.maxPayloadSizeEstimate.Store(uint32(estimateMaxPayloadSize(protocol.ByteCount(s.config.InitialPacketSize)))) oneRTTStream := newCryptoStream() params := &wire.TransportParameters{ InitialMaxStreamDataBidiRemote: protocol.ByteCount(s.config.InitialStreamReceiveWindow), @@ -404,6 +402,7 @@ var newClientConnection = func( MaxBidiStreamNum: protocol.StreamNum(s.config.MaxIncomingStreams), MaxUniStreamNum: protocol.StreamNum(s.config.MaxIncomingUniStreams), MaxAckDelay: protocol.MaxAckDelayInclGranularity, + MaxUDPPayloadSize: protocol.MaxPacketBufferSize, AckDelayExponent: protocol.AckDelayExponent, DisableActiveMigration: true, // For interoperability with quic-go versions before May 2023, this value must be set to a value @@ -433,7 +432,7 @@ var newClientConnection = func( s.version, ) s.cryptoStreamHandler = cs - s.cryptoStreamManager = newCryptoStreamManager(cs, s.initialStream, s.handshakeStream, oneRTTStream) + s.cryptoStreamManager = newCryptoStreamManager(s.initialStream, s.handshakeStream, oneRTTStream) s.unpacker = newPacketUnpacker(cs, s.srcConnIDLen) s.packer = newPacketPacker(srcConnID, s.connIDManager.Get, s.initialStream, s.handshakeStream, s.sentPacketHandler, s.retransmissionQueue, cs, s.framer, s.receivedPacketHandler, s.datagramQueue, s.perspective) if len(tlsConf.ServerName) > 0 { @@ -459,7 +458,6 @@ func (s *connection) preSetup() { s.connFlowController = flowcontrol.NewConnectionFlowController( protocol.ByteCount(s.config.InitialConnectionReceiveWindow), protocol.ByteCount(s.config.MaxConnectionReceiveWindow), - s.onHasConnectionWindowUpdate, func(size protocol.ByteCount) bool { if s.config.AllowConnectionWindowIncrease == nil { return true @@ -471,23 +469,24 @@ func (s *connection) preSetup() { ) s.earlyConnReadyChan = make(chan struct{}) s.streamsMap = newStreamsMap( + s.ctx, s, + s.queueControlFrame, s.newFlowController, uint64(s.config.MaxIncomingStreams), uint64(s.config.MaxIncomingUniStreams), s.perspective, ) - s.framer = newFramer(s.streamsMap) + s.framer = newFramer() s.receivedPackets = make(chan receivedPacket, protocol.MaxConnUnprocessedPackets) s.closeChan = make(chan closeError, 1) s.sendingScheduled = make(chan struct{}, 1) - s.handshakeCtx, s.handshakeCtxCancel = context.WithCancel(context.Background()) + s.handshakeCompleteChan = make(chan struct{}) now := time.Now() s.lastPacketReceivedTime = now s.creationTime = now - s.windowUpdateQueue = newWindowUpdateQueue(s.streamsMap, s.connFlowController, s.framer.QueueControlFrame) s.datagramQueue = newDatagramQueue(s.scheduleSending, s.logger) s.connState.Version = s.version } @@ -495,13 +494,11 @@ func (s *connection) preSetup() { // run the connection main loop func (s *connection) run() error { var closeErr closeError - defer func() { - s.ctxCancel(closeErr.err) - }() + defer func() { s.ctxCancel(closeErr.err) }() s.timer = *newTimer() - if err := s.cryptoStreamHandler.StartHandshake(); err != nil { + if err := s.cryptoStreamHandler.StartHandshake(s.ctx); err != nil { return err } if err := s.handleHandshakeEvents(); err != nil { @@ -662,7 +659,7 @@ func (s *connection) earlyConnReady() <-chan struct{} { } func (s *connection) HandshakeComplete() <-chan struct{} { - return s.handshakeCtx.Done() + return s.handshakeCompleteChan } func (s *connection) Context() context.Context { @@ -702,10 +699,10 @@ func (s *connection) nextKeepAliveTime() time.Time { func (s *connection) maybeResetTimer() { var deadline time.Time if !s.handshakeComplete { - deadline = utils.MinTime( - s.creationTime.Add(s.config.handshakeTimeout()), - s.idleTimeoutStartTime().Add(s.config.HandshakeIdleTimeout), - ) + deadline = s.creationTime.Add(s.config.handshakeTimeout()) + if t := s.idleTimeoutStartTime().Add(s.config.HandshakeIdleTimeout); t.Before(deadline) { + deadline = t + } } else { if keepAliveTime := s.nextKeepAliveTime(); !keepAliveTime.IsZero() { deadline = keepAliveTime @@ -723,11 +720,15 @@ func (s *connection) maybeResetTimer() { } func (s *connection) idleTimeoutStartTime() time.Time { - return utils.MaxTime(s.lastPacketReceivedTime, s.firstAckElicitingPacketAfterIdleSentTime) + startTime := s.lastPacketReceivedTime + if t := s.firstAckElicitingPacketAfterIdleSentTime; t.After(startTime) { + startTime = t + } + return startTime } func (s *connection) handleHandshakeComplete() error { - defer s.handshakeCtxCancel() + defer close(s.handshakeCompleteChan) // Once the handshake completes, we have derived 1-RTT keys. // There's no point in queueing undecryptable packets for later decryption anymore. s.undecryptablePackets = nil @@ -780,11 +781,7 @@ func (s *connection) handleHandshakeConfirmed() error { s.cryptoStreamHandler.SetHandshakeConfirmed() if !s.config.DisablePathMTUDiscovery && s.conn.capabilities().DF { - maxPacketSize := s.peerParams.MaxUDPPayloadSize - if maxPacketSize == 0 { - maxPacketSize = protocol.MaxByteCount - } - s.mtuDiscoverer.Start(min(maxPacketSize, protocol.MaxPacketBufferSize)) + s.mtuDiscoverer.Start() } return nil } @@ -803,13 +800,11 @@ func (s *connection) handlePacketImpl(rp receivedPacket) bool { data := rp.data p := rp for len(data) > 0 { - var destConnID protocol.ConnectionID if counter > 0 { p = *(p.Clone()) p.data = data - var err error - destConnID, err = wire.ParseConnectionID(p.data, s.srcConnIDLen) + destConnID, err := wire.ParseConnectionID(p.data, s.srcConnIDLen) if err != nil { if s.tracer != nil && s.tracer.DroppedPacket != nil { s.tracer.DroppedPacket(logging.PacketTypeNotDetermined, protocol.InvalidPacketNumber, protocol.ByteCount(len(data)), logging.PacketDropHeaderParseError) @@ -869,7 +864,9 @@ func (s *connection) handlePacketImpl(rp receivedPacket) bool { if counter > 0 { p.buffer.Split() } - processed = s.handleShortHeaderPacket(p, destConnID) + if wasProcessed := s.handleShortHeaderPacket(p); wasProcessed { + processed = true + } break } } @@ -878,7 +875,7 @@ func (s *connection) handlePacketImpl(rp receivedPacket) bool { return processed } -func (s *connection) handleShortHeaderPacket(p receivedPacket, destConnID protocol.ConnectionID) bool { +func (s *connection) handleShortHeaderPacket(p receivedPacket) bool { var wasQueued bool defer func() { @@ -888,6 +885,11 @@ func (s *connection) handleShortHeaderPacket(p receivedPacket, destConnID protoc } }() + destConnID, err := wire.ParseConnectionID(p.data, s.srcConnIDLen) + if err != nil { + s.tracer.DroppedPacket(logging.PacketType1RTT, protocol.InvalidPacketNumber, protocol.ByteCount(len(p.data)), logging.PacketDropHeaderParseError) + return false + } pn, pnLen, keyPhase, data, err := s.unpacker.UnpackShortHeader(p.rcvTime, p.data) if err != nil { wasQueued = s.handleUnpackError(err, p, logging.PacketType1RTT) @@ -961,7 +963,7 @@ func (s *connection) handleLongHeaderPacket(p receivedPacket, hdr *wire.Header) return false } - packet, err := s.unpacker.UnpackLongHeader(hdr, p.rcvTime, p.data, s.version) + packet, err := s.unpacker.UnpackLongHeader(hdr, p.data) if err != nil { wasQueued = s.handleUnpackError(err, p, logging.PacketTypeFromHeader(hdr)) return false @@ -1261,7 +1263,7 @@ func (s *connection) handleFrames( isAckEliciting = true } if log != nil { - frames = append(frames, logutils.ConvertFrame(frame)) + frames = append(frames, toLoggingFrame(frame)) } // An error occurred handling a previous frame. // Don't handle the current frame. @@ -1378,6 +1380,15 @@ func (s *connection) handleCryptoFrame(frame *wire.CryptoFrame, encLevel protoco if err := s.cryptoStreamManager.HandleCryptoFrame(frame, encLevel); err != nil { return err } + for { + data := s.cryptoStreamManager.GetCryptoData(encLevel) + if data == nil { + break + } + if err := s.cryptoStreamHandler.HandleMessage(data, encLevel); err != nil { + return err + } + } return s.handleHandshakeEvents() } @@ -1668,10 +1679,8 @@ func (s *connection) dropEncryptionLevel(encLevel protocol.EncryptionLevel) erro s.cryptoStreamHandler.DiscardInitialKeys() case protocol.Encryption0RTT: s.streamsMap.ResetFor0RTT() - if err := s.connFlowController.Reset(); err != nil { - return err - } - return s.framer.Handle0RTTRejection() + s.framer.Handle0RTTRejection() + return s.connFlowController.Reset() } return s.cryptoStreamManager.Drop(encLevel) } @@ -1758,7 +1767,11 @@ func (s *connection) checkTransportParameters(params *wire.TransportParameters) func (s *connection) applyTransportParameters() { params := s.peerParams // Our local idle timeout will always be > 0. - s.idleTimeout = utils.MinNonZeroDuration(s.config.MaxIdleTimeout, params.MaxIdleTimeout) + s.idleTimeout = s.config.MaxIdleTimeout + // If the peer advertised an idle timeout, take the minimum of the values. + if params.MaxIdleTimeout > 0 { + s.idleTimeout = min(s.idleTimeout, params.MaxIdleTimeout) + } s.keepAliveInterval = min(s.config.KeepAlivePeriod, min(s.idleTimeout/2, protocol.MaxKeepAliveInterval)) s.streamsMap.UpdateLimits(params) s.frameParser.SetAckDelayExponent(params.AckDelayExponent) @@ -1773,6 +1786,17 @@ func (s *connection) applyTransportParameters() { // Retire the connection ID. s.connIDManager.AddFromPreferredAddress(params.PreferredAddress.ConnectionID, params.PreferredAddress.StatelessResetToken) } + maxPacketSize := protocol.ByteCount(protocol.MaxPacketBufferSize) + if params.MaxUDPPayloadSize > 0 && params.MaxUDPPayloadSize < maxPacketSize { + maxPacketSize = params.MaxUDPPayloadSize + } + s.mtuDiscoverer = newMTUDiscoverer( + s.rttStats, + protocol.ByteCount(s.config.InitialPacketSize), + maxPacketSize, + s.onMTUIncreased, + s.tracer, + ) } func (s *connection) triggerSending(now time.Time) error { @@ -1855,13 +1879,15 @@ func (s *connection) sendPackets(now time.Time) error { if isBlocked, offset := s.connFlowController.IsNewlyBlocked(); isBlocked { s.framer.QueueControlFrame(&wire.DataBlockedFrame{MaximumData: offset}) } - s.windowUpdateQueue.QueueAll() + if offset := s.connFlowController.GetWindowUpdate(); offset > 0 { + s.framer.QueueControlFrame(&wire.MaxDataFrame{MaximumData: offset}) + } if cf := s.cryptoStreamManager.GetPostHandshakeData(protocol.MaxPostHandshakeCryptoFrameSize); cf != nil { s.queueControlFrame(cf) } if !s.handshakeConfirmed { - packet, err := s.packer.PackCoalescedPacket(false, s.mtuDiscoverer.CurrentSize(), s.version) + packet, err := s.packer.PackCoalescedPacket(false, s.maxPacketSize(), s.version) if err != nil || packet == nil { return err } @@ -1888,7 +1914,7 @@ func (s *connection) sendPacketsWithoutGSO(now time.Time) error { for { buf := getPacketBuffer() ecn := s.sentPacketHandler.ECNMode(true) - if _, err := s.appendOneShortHeaderPacket(buf, s.mtuDiscoverer.CurrentSize(), ecn, now); err != nil { + if _, err := s.appendOneShortHeaderPacket(buf, s.maxPacketSize(), ecn, now); err != nil { if err == errNothingToPack { buf.Release() return nil @@ -1919,7 +1945,7 @@ func (s *connection) sendPacketsWithoutGSO(now time.Time) error { func (s *connection) sendPacketsWithGSO(now time.Time) error { buf := getLargePacketBuffer() - maxSize := s.mtuDiscoverer.CurrentSize() + maxSize := s.maxPacketSize() ecn := s.sentPacketHandler.ECNMode(true) for { @@ -1988,7 +2014,7 @@ func (s *connection) resetPacingDeadline() { func (s *connection) maybeSendAckOnlyPacket(now time.Time) error { if !s.handshakeConfirmed { ecn := s.sentPacketHandler.ECNMode(false) - packet, err := s.packer.PackCoalescedPacket(true, s.mtuDiscoverer.CurrentSize(), s.version) + packet, err := s.packer.PackCoalescedPacket(true, s.maxPacketSize(), s.version) if err != nil { return err } @@ -1999,7 +2025,7 @@ func (s *connection) maybeSendAckOnlyPacket(now time.Time) error { } ecn := s.sentPacketHandler.ECNMode(true) - p, buf, err := s.packer.PackAckOnlyPacket(s.mtuDiscoverer.CurrentSize(), s.version) + p, buf, err := s.packer.PackAckOnlyPacket(s.maxPacketSize(), s.version) if err != nil { if err == errNothingToPack { return nil @@ -2021,7 +2047,7 @@ func (s *connection) sendProbePacket(encLevel protocol.EncryptionLevel, now time break } var err error - packet, err = s.packer.MaybePackProbePacket(encLevel, s.mtuDiscoverer.CurrentSize(), s.version) + packet, err = s.packer.MaybePackProbePacket(encLevel, s.maxPacketSize(), s.version) if err != nil { return err } @@ -2032,7 +2058,7 @@ func (s *connection) sendProbePacket(encLevel protocol.EncryptionLevel, now time if packet == nil { s.retransmissionQueue.AddPing(encLevel) var err error - packet, err = s.packer.MaybePackProbePacket(encLevel, s.mtuDiscoverer.CurrentSize(), s.version) + packet, err = s.packer.MaybePackProbePacket(encLevel, s.maxPacketSize(), s.version) if err != nil { return err } @@ -2111,14 +2137,14 @@ func (s *connection) sendConnectionClose(e error) ([]byte, error) { var transportErr *qerr.TransportError var applicationErr *qerr.ApplicationError if errors.As(e, &transportErr) { - packet, err = s.packer.PackConnectionClose(transportErr, s.mtuDiscoverer.CurrentSize(), s.version) + packet, err = s.packer.PackConnectionClose(transportErr, s.maxPacketSize(), s.version) } else if errors.As(e, &applicationErr) { - packet, err = s.packer.PackApplicationClose(applicationErr, s.mtuDiscoverer.CurrentSize(), s.version) + packet, err = s.packer.PackApplicationClose(applicationErr, s.maxPacketSize(), s.version) } else { packet, err = s.packer.PackConnectionClose(&qerr.TransportError{ ErrorCode: qerr.InternalError, ErrorMessage: fmt.Sprintf("connection BUG: unspecified error type (msg: %s)", e.Error()), - }, s.mtuDiscoverer.CurrentSize(), s.version) + }, s.maxPacketSize(), s.version) } if err != nil { return nil, err @@ -2128,126 +2154,22 @@ func (s *connection) sendConnectionClose(e error) ([]byte, error) { return packet.buffer.Data, s.conn.Write(packet.buffer.Data, 0, ecn) } -func (s *connection) logLongHeaderPacket(p *longHeaderPacket, ecn protocol.ECN) { - // quic-go logging - if s.logger.Debug() { - p.header.Log(s.logger) - if p.ack != nil { - wire.LogFrame(s.logger, p.ack, true) - } - for _, frame := range p.frames { - wire.LogFrame(s.logger, frame.Frame, true) - } - for _, frame := range p.streamFrames { - wire.LogFrame(s.logger, frame.Frame, true) - } - } - - // tracing - if s.tracer != nil && s.tracer.SentLongHeaderPacket != nil { - frames := make([]logging.Frame, 0, len(p.frames)) - for _, f := range p.frames { - frames = append(frames, logutils.ConvertFrame(f.Frame)) - } - for _, f := range p.streamFrames { - frames = append(frames, logutils.ConvertFrame(f.Frame)) +func (s *connection) maxPacketSize() protocol.ByteCount { + if s.mtuDiscoverer == nil { + // Use the configured packet size on the client side. + // If the server sends a max_udp_payload_size that's smaller than this size, we can ignore this: + // Apparently the server still processed the (fully padded) Initial packet anyway. + if s.perspective == protocol.PerspectiveClient { + return protocol.ByteCount(s.config.InitialPacketSize) } - var ack *logging.AckFrame - if p.ack != nil { - ack = logutils.ConvertAckFrame(p.ack) - } - s.tracer.SentLongHeaderPacket(p.header, p.length, ecn, ack, frames) - } -} - -func (s *connection) logShortHeaderPacket( - destConnID protocol.ConnectionID, - ackFrame *wire.AckFrame, - frames []ackhandler.Frame, - streamFrames []ackhandler.StreamFrame, - pn protocol.PacketNumber, - pnLen protocol.PacketNumberLen, - kp protocol.KeyPhaseBit, - ecn protocol.ECN, - size protocol.ByteCount, - isCoalesced bool, -) { - if s.logger.Debug() && !isCoalesced { - s.logger.Debugf("-> Sending packet %d (%d bytes) for connection %s, 1-RTT (ECN: %s)", pn, size, s.logID, ecn) - } - // quic-go logging - if s.logger.Debug() { - wire.LogShortHeader(s.logger, destConnID, pn, pnLen, kp) - if ackFrame != nil { - wire.LogFrame(s.logger, ackFrame, true) - } - for _, f := range frames { - wire.LogFrame(s.logger, f.Frame, true) - } - for _, f := range streamFrames { - wire.LogFrame(s.logger, f.Frame, true) - } - } - - // tracing - if s.tracer != nil && s.tracer.SentShortHeaderPacket != nil { - fs := make([]logging.Frame, 0, len(frames)+len(streamFrames)) - for _, f := range frames { - fs = append(fs, logutils.ConvertFrame(f.Frame)) - } - for _, f := range streamFrames { - fs = append(fs, logutils.ConvertFrame(f.Frame)) - } - var ack *logging.AckFrame - if ackFrame != nil { - ack = logutils.ConvertAckFrame(ackFrame) - } - s.tracer.SentShortHeaderPacket( - &logging.ShortHeader{ - DestConnectionID: destConnID, - PacketNumber: pn, - PacketNumberLen: pnLen, - KeyPhase: kp, - }, - size, - ecn, - ack, - fs, - ) - } -} - -func (s *connection) logCoalescedPacket(packet *coalescedPacket, ecn protocol.ECN) { - if s.logger.Debug() { - // There's a short period between dropping both Initial and Handshake keys and completion of the handshake, - // during which we might call PackCoalescedPacket but just pack a short header packet. - if len(packet.longHdrPackets) == 0 && packet.shortHdrPacket != nil { - s.logShortHeaderPacket( - packet.shortHdrPacket.DestConnID, - packet.shortHdrPacket.Ack, - packet.shortHdrPacket.Frames, - packet.shortHdrPacket.StreamFrames, - packet.shortHdrPacket.PacketNumber, - packet.shortHdrPacket.PacketNumberLen, - packet.shortHdrPacket.KeyPhase, - ecn, - packet.shortHdrPacket.Length, - false, - ) - return - } - if len(packet.longHdrPackets) > 1 { - s.logger.Debugf("-> Sending coalesced packet (%d parts, %d bytes) for connection %s", len(packet.longHdrPackets), packet.buffer.Len(), s.logID) - } else { - s.logger.Debugf("-> Sending packet %d (%d bytes) for connection %s, %s", packet.longHdrPackets[0].header.PacketNumber, packet.buffer.Len(), s.logID, packet.longHdrPackets[0].EncryptionLevel()) - } - } - for _, p := range packet.longHdrPackets { - s.logLongHeaderPacket(p, ecn) - } - if p := packet.shortHdrPacket; p != nil { - s.logShortHeaderPacket(p.DestConnID, p.Ack, p.Frames, p.StreamFrames, p.PacketNumber, p.PacketNumberLen, p.KeyPhase, ecn, p.Length, true) + // On the server side, there's no downside to using 1200 bytes until we received the client's transport + // parameters: + // * If the first packet didn't contain the entire ClientHello, all we can do is ACK that packet. We don't + // need a lot of bytes for that. + // * If it did, we will have processed the transport parameters and initialized the MTU discoverer. + return protocol.MinInitialPacketSize } + return s.mtuDiscoverer.CurrentSize() } // AcceptStream returns the next stream openend by the peer @@ -2291,7 +2213,6 @@ func (s *connection) newFlowController(id protocol.StreamID) flowcontrol.StreamF protocol.ByteCount(s.config.InitialStreamReceiveWindow), protocol.ByteCount(s.config.MaxStreamReceiveWindow), initialSendWindow, - s.onHasStreamWindowUpdate, s.rttStats, s.logger, ) @@ -2330,18 +2251,13 @@ func (s *connection) queueControlFrame(f wire.Frame) { s.scheduleSending() } -func (s *connection) onHasStreamWindowUpdate(id protocol.StreamID) { - s.windowUpdateQueue.AddStream(id) - s.scheduleSending() -} - -func (s *connection) onHasConnectionWindowUpdate() { - s.windowUpdateQueue.AddConnection() +func (s *connection) onHasStreamData(id protocol.StreamID, str sendStreamI) { + s.framer.AddActiveStream(id, str) s.scheduleSending() } -func (s *connection) onHasStreamData(id protocol.StreamID) { - s.framer.AddActiveStream(id) +func (s *connection) onHasStreamControlFrame(id protocol.StreamID, str streamControlFrameGetter) { + s.framer.AddStreamWithControlFrames(id, str) s.scheduleSending() } @@ -2349,6 +2265,12 @@ func (s *connection) onStreamCompleted(id protocol.StreamID) { if err := s.streamsMap.DeleteStream(id); err != nil { s.closeLocal(err) } + s.framer.RemoveActiveStream(id) +} + +func (s *connection) onMTUIncreased(mtu protocol.ByteCount) { + s.maxPayloadSizeEstimate.Store(uint32(estimateMaxPayloadSize(mtu))) + s.sentPacketHandler.SetMaxDatagramSize(mtu) } func (s *connection) SendDatagram(p []byte) error { @@ -2357,10 +2279,14 @@ func (s *connection) SendDatagram(p []byte) error { } f := &wire.DatagramFrame{DataLenPresent: true} - if protocol.ByteCount(len(p)) > f.MaxDataLen(s.peerParams.MaxDatagramFrameSize, s.version) { - return &DatagramTooLargeError{ - PeerMaxDatagramFrameSize: int64(s.peerParams.MaxDatagramFrameSize), - } + // The payload size estimate is conservative. + // Under many circumstances we could send a few more bytes. + maxDataLen := min( + f.MaxDataLen(s.peerParams.MaxDatagramFrameSize, s.version), + protocol.ByteCount(s.maxPayloadSizeEstimate.Load()), + ) + if protocol.ByteCount(len(p)) > maxDataLen { + return &DatagramTooLargeError{MaxDatagramPayloadSize: int64(maxDataLen)} } f.Data = make([]byte, len(p)) copy(f.Data, p) @@ -2386,8 +2312,22 @@ func (s *connection) GetVersion() protocol.Version { return s.version } -func (s *connection) NextConnection() Connection { - <-s.HandshakeComplete() - s.streamsMap.UseResetMaps() - return s +func (s *connection) NextConnection(ctx context.Context) (Connection, error) { + // The handshake might fail after the server rejected 0-RTT. + // This could happen if the Finished message is malformed or never received. + select { + case <-ctx.Done(): + return nil, context.Cause(ctx) + case <-s.Context().Done(): + case <-s.HandshakeComplete(): + s.streamsMap.UseResetMaps() + } + return s, nil +} + +// estimateMaxPayloadSize estimates the maximum payload size for short header packets. +// It is not very sophisticated: it just subtracts the size of header (assuming the maximum +// connection ID length), and the size of the encryption tag. +func estimateMaxPayloadSize(mtu protocol.ByteCount) protocol.ByteCount { + return mtu - 1 /* type byte */ - 20 /* maximum connection ID length */ - 16 /* tag size */ } diff --git a/vendor/github.com/quic-go/quic-go/connection_logging.go b/vendor/github.com/quic-go/quic-go/connection_logging.go new file mode 100644 index 000000000..f75b39f6f --- /dev/null +++ b/vendor/github.com/quic-go/quic-go/connection_logging.go @@ -0,0 +1,173 @@ +package quic + +import ( + "slices" + + "github.com/quic-go/quic-go/internal/ackhandler" + "github.com/quic-go/quic-go/internal/protocol" + "github.com/quic-go/quic-go/internal/wire" + "github.com/quic-go/quic-go/logging" +) + +// ConvertFrame converts a wire.Frame into a logging.Frame. +// This makes it possible for external packages to access the frames. +// Furthermore, it removes the data slices from CRYPTO and STREAM frames. +func toLoggingFrame(frame wire.Frame) logging.Frame { + switch f := frame.(type) { + case *wire.AckFrame: + // We use a pool for ACK frames. + // Implementations of the tracer interface may hold on to frames, so we need to make a copy here. + return toLoggingAckFrame(f) + case *wire.CryptoFrame: + return &logging.CryptoFrame{ + Offset: f.Offset, + Length: protocol.ByteCount(len(f.Data)), + } + case *wire.StreamFrame: + return &logging.StreamFrame{ + StreamID: f.StreamID, + Offset: f.Offset, + Length: f.DataLen(), + Fin: f.Fin, + } + case *wire.DatagramFrame: + return &logging.DatagramFrame{ + Length: logging.ByteCount(len(f.Data)), + } + default: + return logging.Frame(frame) + } +} + +func toLoggingAckFrame(f *wire.AckFrame) *logging.AckFrame { + ack := &logging.AckFrame{ + AckRanges: slices.Clone(f.AckRanges), + DelayTime: f.DelayTime, + ECNCE: f.ECNCE, + ECT0: f.ECT0, + ECT1: f.ECT1, + } + return ack +} + +func (s *connection) logLongHeaderPacket(p *longHeaderPacket, ecn protocol.ECN) { + // quic-go logging + if s.logger.Debug() { + p.header.Log(s.logger) + if p.ack != nil { + wire.LogFrame(s.logger, p.ack, true) + } + for _, frame := range p.frames { + wire.LogFrame(s.logger, frame.Frame, true) + } + for _, frame := range p.streamFrames { + wire.LogFrame(s.logger, frame.Frame, true) + } + } + + // tracing + if s.tracer != nil && s.tracer.SentLongHeaderPacket != nil { + frames := make([]logging.Frame, 0, len(p.frames)) + for _, f := range p.frames { + frames = append(frames, toLoggingFrame(f.Frame)) + } + for _, f := range p.streamFrames { + frames = append(frames, toLoggingFrame(f.Frame)) + } + var ack *logging.AckFrame + if p.ack != nil { + ack = toLoggingAckFrame(p.ack) + } + s.tracer.SentLongHeaderPacket(p.header, p.length, ecn, ack, frames) + } +} + +func (s *connection) logShortHeaderPacket( + destConnID protocol.ConnectionID, + ackFrame *wire.AckFrame, + frames []ackhandler.Frame, + streamFrames []ackhandler.StreamFrame, + pn protocol.PacketNumber, + pnLen protocol.PacketNumberLen, + kp protocol.KeyPhaseBit, + ecn protocol.ECN, + size protocol.ByteCount, + isCoalesced bool, +) { + if s.logger.Debug() && !isCoalesced { + s.logger.Debugf("-> Sending packet %d (%d bytes) for connection %s, 1-RTT (ECN: %s)", pn, size, s.logID, ecn) + } + // quic-go logging + if s.logger.Debug() { + wire.LogShortHeader(s.logger, destConnID, pn, pnLen, kp) + if ackFrame != nil { + wire.LogFrame(s.logger, ackFrame, true) + } + for _, f := range frames { + wire.LogFrame(s.logger, f.Frame, true) + } + for _, f := range streamFrames { + wire.LogFrame(s.logger, f.Frame, true) + } + } + + // tracing + if s.tracer != nil && s.tracer.SentShortHeaderPacket != nil { + fs := make([]logging.Frame, 0, len(frames)+len(streamFrames)) + for _, f := range frames { + fs = append(fs, toLoggingFrame(f.Frame)) + } + for _, f := range streamFrames { + fs = append(fs, toLoggingFrame(f.Frame)) + } + var ack *logging.AckFrame + if ackFrame != nil { + ack = toLoggingAckFrame(ackFrame) + } + s.tracer.SentShortHeaderPacket( + &logging.ShortHeader{ + DestConnectionID: destConnID, + PacketNumber: pn, + PacketNumberLen: pnLen, + KeyPhase: kp, + }, + size, + ecn, + ack, + fs, + ) + } +} + +func (s *connection) logCoalescedPacket(packet *coalescedPacket, ecn protocol.ECN) { + if s.logger.Debug() { + // There's a short period between dropping both Initial and Handshake keys and completion of the handshake, + // during which we might call PackCoalescedPacket but just pack a short header packet. + if len(packet.longHdrPackets) == 0 && packet.shortHdrPacket != nil { + s.logShortHeaderPacket( + packet.shortHdrPacket.DestConnID, + packet.shortHdrPacket.Ack, + packet.shortHdrPacket.Frames, + packet.shortHdrPacket.StreamFrames, + packet.shortHdrPacket.PacketNumber, + packet.shortHdrPacket.PacketNumberLen, + packet.shortHdrPacket.KeyPhase, + ecn, + packet.shortHdrPacket.Length, + false, + ) + return + } + if len(packet.longHdrPackets) > 1 { + s.logger.Debugf("-> Sending coalesced packet (%d parts, %d bytes) for connection %s", len(packet.longHdrPackets), packet.buffer.Len(), s.logID) + } else { + s.logger.Debugf("-> Sending packet %d (%d bytes) for connection %s, %s", packet.longHdrPackets[0].header.PacketNumber, packet.buffer.Len(), s.logID, packet.longHdrPackets[0].EncryptionLevel()) + } + } + for _, p := range packet.longHdrPackets { + s.logLongHeaderPacket(p, ecn) + } + if p := packet.shortHdrPacket; p != nil { + s.logShortHeaderPacket(p.DestConnID, p.Ack, p.Frames, p.StreamFrames, p.PacketNumber, p.PacketNumberLen, p.KeyPhase, ecn, p.Length, true) + } +} diff --git a/vendor/github.com/quic-go/quic-go/crypto_stream.go b/vendor/github.com/quic-go/quic-go/crypto_stream.go index abc7ddcf8..9a387baa4 100644 --- a/vendor/github.com/quic-go/quic-go/crypto_stream.go +++ b/vendor/github.com/quic-go/quic-go/crypto_stream.go @@ -2,27 +2,14 @@ package quic import ( "fmt" - "io" "github.com/quic-go/quic-go/internal/protocol" "github.com/quic-go/quic-go/internal/qerr" "github.com/quic-go/quic-go/internal/wire" ) -type cryptoStream interface { - // for receiving data - HandleCryptoFrame(*wire.CryptoFrame) error - GetCryptoData() []byte - Finish() error - // for sending data - io.Writer - HasData() bool - PopCryptoFrame(protocol.ByteCount) *wire.CryptoFrame -} - -type cryptoStreamImpl struct { - queue *frameSorter - msgBuf []byte +type cryptoStream struct { + queue frameSorter highestOffset protocol.ByteCount finished bool @@ -31,11 +18,11 @@ type cryptoStreamImpl struct { writeBuf []byte } -func newCryptoStream() cryptoStream { - return &cryptoStreamImpl{queue: newFrameSorter()} +func newCryptoStream() *cryptoStream { + return &cryptoStream{queue: *newFrameSorter()} } -func (s *cryptoStreamImpl) HandleCryptoFrame(f *wire.CryptoFrame) error { +func (s *cryptoStream) HandleCryptoFrame(f *wire.CryptoFrame) error { highestOffset := f.Offset + protocol.ByteCount(len(f.Data)) if maxOffset := highestOffset; maxOffset > protocol.MaxCryptoStreamOffset { return &qerr.TransportError{ @@ -56,26 +43,16 @@ func (s *cryptoStreamImpl) HandleCryptoFrame(f *wire.CryptoFrame) error { return nil } s.highestOffset = max(s.highestOffset, highestOffset) - if err := s.queue.Push(f.Data, f.Offset, nil); err != nil { - return err - } - for { - _, data, _ := s.queue.Pop() - if data == nil { - return nil - } - s.msgBuf = append(s.msgBuf, data...) - } + return s.queue.Push(f.Data, f.Offset, nil) } // GetCryptoData retrieves data that was received in CRYPTO frames -func (s *cryptoStreamImpl) GetCryptoData() []byte { - b := s.msgBuf - s.msgBuf = nil - return b +func (s *cryptoStream) GetCryptoData() []byte { + _, data, _ := s.queue.Pop() + return data } -func (s *cryptoStreamImpl) Finish() error { +func (s *cryptoStream) Finish() error { if s.queue.HasMoreData() { return &qerr.TransportError{ ErrorCode: qerr.ProtocolViolation, @@ -87,16 +64,16 @@ func (s *cryptoStreamImpl) Finish() error { } // Writes writes data that should be sent out in CRYPTO frames -func (s *cryptoStreamImpl) Write(p []byte) (int, error) { +func (s *cryptoStream) Write(p []byte) (int, error) { s.writeBuf = append(s.writeBuf, p...) return len(p), nil } -func (s *cryptoStreamImpl) HasData() bool { +func (s *cryptoStream) HasData() bool { return len(s.writeBuf) > 0 } -func (s *cryptoStreamImpl) PopCryptoFrame(maxLen protocol.ByteCount) *wire.CryptoFrame { +func (s *cryptoStream) PopCryptoFrame(maxLen protocol.ByteCount) *wire.CryptoFrame { f := &wire.CryptoFrame{Offset: s.writeOffset} n := min(f.MaxDataLen(maxLen), protocol.ByteCount(len(s.writeBuf))) f.Data = s.writeBuf[:n] diff --git a/vendor/github.com/quic-go/quic-go/crypto_stream_manager.go b/vendor/github.com/quic-go/quic-go/crypto_stream_manager.go index c48e238a7..d70b9b007 100644 --- a/vendor/github.com/quic-go/quic-go/crypto_stream_manager.go +++ b/vendor/github.com/quic-go/quic-go/crypto_stream_manager.go @@ -3,32 +3,22 @@ package quic import ( "fmt" - "github.com/quic-go/quic-go/internal/handshake" "github.com/quic-go/quic-go/internal/protocol" "github.com/quic-go/quic-go/internal/wire" ) -type cryptoDataHandler interface { - HandleMessage([]byte, protocol.EncryptionLevel) error - NextEvent() handshake.Event -} - type cryptoStreamManager struct { - cryptoHandler cryptoDataHandler - - initialStream cryptoStream - handshakeStream cryptoStream - oneRTTStream cryptoStream + initialStream *cryptoStream + handshakeStream *cryptoStream + oneRTTStream *cryptoStream } func newCryptoStreamManager( - cryptoHandler cryptoDataHandler, - initialStream cryptoStream, - handshakeStream cryptoStream, - oneRTTStream cryptoStream, + initialStream *cryptoStream, + handshakeStream *cryptoStream, + oneRTTStream *cryptoStream, ) *cryptoStreamManager { return &cryptoStreamManager{ - cryptoHandler: cryptoHandler, initialStream: initialStream, handshakeStream: handshakeStream, oneRTTStream: oneRTTStream, @@ -36,7 +26,7 @@ func newCryptoStreamManager( } func (m *cryptoStreamManager) HandleCryptoFrame(frame *wire.CryptoFrame, encLevel protocol.EncryptionLevel) error { - var str cryptoStream + var str *cryptoStream //nolint:exhaustive // CRYPTO frames cannot be sent in 0-RTT packets. switch encLevel { case protocol.EncryptionInitial: @@ -48,18 +38,23 @@ func (m *cryptoStreamManager) HandleCryptoFrame(frame *wire.CryptoFrame, encLeve default: return fmt.Errorf("received CRYPTO frame with unexpected encryption level: %s", encLevel) } - if err := str.HandleCryptoFrame(frame); err != nil { - return err - } - for { - data := str.GetCryptoData() - if data == nil { - return nil - } - if err := m.cryptoHandler.HandleMessage(data, encLevel); err != nil { - return err - } + return str.HandleCryptoFrame(frame) +} + +func (m *cryptoStreamManager) GetCryptoData(encLevel protocol.EncryptionLevel) []byte { + var str *cryptoStream + //nolint:exhaustive // CRYPTO frames cannot be sent in 0-RTT packets. + switch encLevel { + case protocol.EncryptionInitial: + str = m.initialStream + case protocol.EncryptionHandshake: + str = m.handshakeStream + case protocol.Encryption1RTT: + str = m.oneRTTStream + default: + panic(fmt.Sprintf("received CRYPTO frame with unexpected encryption level: %s", encLevel)) } + return str.GetCryptoData() } func (m *cryptoStreamManager) GetPostHandshakeData(maxSize protocol.ByteCount) *wire.CryptoFrame { diff --git a/vendor/github.com/quic-go/quic-go/errors.go b/vendor/github.com/quic-go/quic-go/errors.go index fda3c9247..3fe1e0a90 100644 --- a/vendor/github.com/quic-go/quic-go/errors.go +++ b/vendor/github.com/quic-go/quic-go/errors.go @@ -64,7 +64,7 @@ func (e *StreamError) Error() string { // DatagramTooLargeError is returned from Connection.SendDatagram if the payload is too large to be sent. type DatagramTooLargeError struct { - PeerMaxDatagramFrameSize int64 + MaxDatagramPayloadSize int64 } func (e *DatagramTooLargeError) Is(target error) bool { diff --git a/vendor/github.com/quic-go/quic-go/framer.go b/vendor/github.com/quic-go/quic-go/framer.go index 1e6219a46..e162f6b8f 100644 --- a/vendor/github.com/quic-go/quic-go/framer.go +++ b/vendor/github.com/quic-go/quic-go/framer.go @@ -1,7 +1,7 @@ package quic import ( - "errors" + "slices" "sync" "github.com/quic-go/quic-go/internal/ackhandler" @@ -11,37 +11,25 @@ import ( "github.com/quic-go/quic-go/quicvarint" ) -type framer interface { - HasData() bool - - QueueControlFrame(wire.Frame) - AppendControlFrames([]ackhandler.Frame, protocol.ByteCount, protocol.Version) ([]ackhandler.Frame, protocol.ByteCount) - - AddActiveStream(protocol.StreamID) - AppendStreamFrames([]ackhandler.StreamFrame, protocol.ByteCount, protocol.Version) ([]ackhandler.StreamFrame, protocol.ByteCount) - - Handle0RTTRejection() error - - // QueuedTooManyControlFrames says if the control frame queue exceeded its maximum queue length. - // This is a hack. - // It is easier to implement than propagating an error return value in QueueControlFrame. - // The correct solution would be to queue frames with their respective structs. - // See https://github.com/quic-go/quic-go/issues/4271 for the queueing of stream-related control frames. - QueuedTooManyControlFrames() bool -} - const ( maxPathResponses = 256 maxControlFrames = 16 << 10 ) -type framerI struct { - mutex sync.Mutex +// This is the largest possible size of a stream-related control frame +// (which is the RESET_STREAM frame). +const maxStreamControlFrameSize = 25 - streamGetter streamGetter +type streamControlFrameGetter interface { + getControlFrame() (_ ackhandler.Frame, ok, hasMore bool) +} - activeStreams map[protocol.StreamID]struct{} - streamQueue ringbuffer.RingBuffer[protocol.StreamID] +type framer struct { + mutex sync.Mutex + + activeStreams map[protocol.StreamID]sendStreamI + streamQueue ringbuffer.RingBuffer[protocol.StreamID] + streamsWithControlFrames map[protocol.StreamID]streamControlFrameGetter controlFrameMutex sync.Mutex controlFrames []wire.Frame @@ -49,16 +37,14 @@ type framerI struct { queuedTooManyControlFrames bool } -var _ framer = &framerI{} - -func newFramer(streamGetter streamGetter) framer { - return &framerI{ - streamGetter: streamGetter, - activeStreams: make(map[protocol.StreamID]struct{}), +func newFramer() *framer { + return &framer{ + activeStreams: make(map[protocol.StreamID]sendStreamI), + streamsWithControlFrames: make(map[protocol.StreamID]streamControlFrameGetter), } } -func (f *framerI) HasData() bool { +func (f *framer) HasData() bool { f.mutex.Lock() hasData := !f.streamQueue.Empty() f.mutex.Unlock() @@ -67,10 +53,10 @@ func (f *framerI) HasData() bool { } f.controlFrameMutex.Lock() defer f.controlFrameMutex.Unlock() - return len(f.controlFrames) > 0 || len(f.pathResponses) > 0 + return len(f.streamsWithControlFrames) > 0 || len(f.controlFrames) > 0 || len(f.pathResponses) > 0 } -func (f *framerI) QueueControlFrame(frame wire.Frame) { +func (f *framer) QueueControlFrame(frame wire.Frame) { f.controlFrameMutex.Lock() defer f.controlFrameMutex.Unlock() @@ -92,7 +78,7 @@ func (f *framerI) QueueControlFrame(frame wire.Frame) { f.controlFrames = append(f.controlFrames, frame) } -func (f *framerI) AppendControlFrames(frames []ackhandler.Frame, maxLen protocol.ByteCount, v protocol.Version) ([]ackhandler.Frame, protocol.ByteCount) { +func (f *framer) AppendControlFrames(frames []ackhandler.Frame, maxLen protocol.ByteCount, v protocol.Version) ([]ackhandler.Frame, protocol.ByteCount) { f.controlFrameMutex.Lock() defer f.controlFrameMutex.Unlock() @@ -108,6 +94,29 @@ func (f *framerI) AppendControlFrames(frames []ackhandler.Frame, maxLen protocol } } + // add stream-related control frames + for id, str := range f.streamsWithControlFrames { + start: + remainingLen := maxLen - length + if remainingLen <= maxStreamControlFrameSize { + break + } + fr, ok, hasMore := str.getControlFrame() + if !hasMore { + delete(f.streamsWithControlFrames, id) + } + if !ok { + continue + } + frames = append(frames, fr) + length += fr.Frame.Length(v) + if hasMore { + // It is rare that a stream has more than one control frame to queue. + // We don't want to spawn another loop for just to cover that case. + goto start + } + } + for len(f.controlFrames) > 0 { frame := f.controlFrames[len(f.controlFrames)-1] frameLen := frame.Length(v) @@ -118,27 +127,51 @@ func (f *framerI) AppendControlFrames(frames []ackhandler.Frame, maxLen protocol length += frameLen f.controlFrames = f.controlFrames[:len(f.controlFrames)-1] } + return frames, length } -func (f *framerI) QueuedTooManyControlFrames() bool { +// QueuedTooManyControlFrames says if the control frame queue exceeded its maximum queue length. +// This is a hack. +// It is easier to implement than propagating an error return value in QueueControlFrame. +// The correct solution would be to queue frames with their respective structs. +// See https://github.com/quic-go/quic-go/issues/4271 for the queueing of stream-related control frames. +func (f *framer) QueuedTooManyControlFrames() bool { return f.queuedTooManyControlFrames } -func (f *framerI) AddActiveStream(id protocol.StreamID) { +func (f *framer) AddActiveStream(id protocol.StreamID, str sendStreamI) { f.mutex.Lock() if _, ok := f.activeStreams[id]; !ok { f.streamQueue.PushBack(id) - f.activeStreams[id] = struct{}{} + f.activeStreams[id] = str } f.mutex.Unlock() } -func (f *framerI) AppendStreamFrames(frames []ackhandler.StreamFrame, maxLen protocol.ByteCount, v protocol.Version) ([]ackhandler.StreamFrame, protocol.ByteCount) { +func (f *framer) AddStreamWithControlFrames(id protocol.StreamID, str streamControlFrameGetter) { + f.controlFrameMutex.Lock() + if _, ok := f.streamsWithControlFrames[id]; !ok { + f.streamsWithControlFrames[id] = str + } + f.controlFrameMutex.Unlock() +} + +// RemoveActiveStream is called when a stream completes. +func (f *framer) RemoveActiveStream(id protocol.StreamID) { + f.mutex.Lock() + delete(f.activeStreams, id) + // We don't delete the stream from the streamQueue, + // since we'd have to iterate over the ringbuffer. + // Instead, we check if the stream is still in activeStreams in AppendStreamFrames. + f.mutex.Unlock() +} + +func (f *framer) AppendStreamFrames(frames []ackhandler.StreamFrame, maxLen protocol.ByteCount, v protocol.Version) ([]ackhandler.StreamFrame, protocol.ByteCount) { startLen := len(frames) var length protocol.ByteCount f.mutex.Lock() - // pop STREAM frames, until less than MinStreamFrameSize bytes are left in the packet + // pop STREAM frames, until less than 128 bytes are left in the packet numActiveStreams := f.streamQueue.Len() for i := 0; i < numActiveStreams; i++ { if protocol.MinStreamFrameSize+length > maxLen { @@ -147,17 +180,16 @@ func (f *framerI) AppendStreamFrames(frames []ackhandler.StreamFrame, maxLen pro id := f.streamQueue.PopFront() // This should never return an error. Better check it anyway. // The stream will only be in the streamQueue, if it enqueued itself there. - str, err := f.streamGetter.GetOrOpenSendStream(id) - // The stream can be nil if it completed after it said it had data. - if str == nil || err != nil { - delete(f.activeStreams, id) + str, ok := f.activeStreams[id] + // The stream might have been removed after being enqueued. + if !ok { continue } remainingLen := maxLen - length // For the last STREAM frame, we'll remove the DataLen field later. // Therefore, we can pretend to have more bytes available when popping // the STREAM frame (which will always have the DataLen set). - remainingLen += quicvarint.Len(uint64(remainingLen)) + remainingLen += protocol.ByteCount(quicvarint.Len(uint64(remainingLen))) frame, ok, hasMoreData := str.popStreamFrame(remainingLen, v) if hasMoreData { // put the stream back in the queue (at the end) f.streamQueue.PushBack(id) @@ -165,7 +197,7 @@ func (f *framerI) AppendStreamFrames(frames []ackhandler.StreamFrame, maxLen pro delete(f.activeStreams, id) } // The frame can be "nil" - // * if the receiveStream was canceled after it said it had data + // * if the stream was canceled after it said it had data // * the remaining size doesn't allow us to add another STREAM frame if !ok { continue @@ -183,11 +215,12 @@ func (f *framerI) AppendStreamFrames(frames []ackhandler.StreamFrame, maxLen pro return frames, length } -func (f *framerI) Handle0RTTRejection() error { +func (f *framer) Handle0RTTRejection() { f.mutex.Lock() defer f.mutex.Unlock() - f.controlFrameMutex.Lock() + defer f.controlFrameMutex.Unlock() + f.streamQueue.Clear() for id := range f.activeStreams { delete(f.activeStreams, id) @@ -195,16 +228,13 @@ func (f *framerI) Handle0RTTRejection() error { var j int for i, frame := range f.controlFrames { switch frame.(type) { - case *wire.MaxDataFrame, *wire.MaxStreamDataFrame, *wire.MaxStreamsFrame: - return errors.New("didn't expect MAX_DATA / MAX_STREAM_DATA / MAX_STREAMS frame to be sent in 0-RTT") - case *wire.DataBlockedFrame, *wire.StreamDataBlockedFrame, *wire.StreamsBlockedFrame: + case *wire.MaxDataFrame, *wire.MaxStreamDataFrame, *wire.MaxStreamsFrame, + *wire.DataBlockedFrame, *wire.StreamDataBlockedFrame, *wire.StreamsBlockedFrame: continue default: f.controlFrames[j] = f.controlFrames[i] j++ } } - f.controlFrames = f.controlFrames[:j] - f.controlFrameMutex.Unlock() - return nil + f.controlFrames = slices.Delete(f.controlFrames, j, len(f.controlFrames)) } diff --git a/vendor/github.com/quic-go/quic-go/interface.go b/vendor/github.com/quic-go/quic-go/interface.go index ca8544d8f..2071b596f 100644 --- a/vendor/github.com/quic-go/quic-go/interface.go +++ b/vendor/github.com/quic-go/quic-go/interface.go @@ -19,10 +19,6 @@ type StreamID = protocol.StreamID // A Version is a QUIC version number. type Version = protocol.Version -// A VersionNumber is a QUIC version number. -// Deprecated: VersionNumber was renamed to Version. -type VersionNumber = Version - const ( // Version1 is RFC 9000 Version1 = protocol.Version1 @@ -57,8 +53,13 @@ var Err0RTTRejected = errors.New("0-RTT rejected") // ConnectionTracingKey can be used to associate a ConnectionTracer with a Connection. // It is set on the Connection.Context() context, // as well as on the context passed to logging.Tracer.NewConnectionTracer. +// Deprecated: Applications can set their own tracing key using Transport.ConnContext. var ConnectionTracingKey = connTracingCtxKey{} +// ConnectionTracingID is the type of the context value saved under the ConnectionTracingKey. +// Deprecated: Applications can set their own tracing key using Transport.ConnContext. +type ConnectionTracingID uint64 + type connTracingCtxKey struct{} // QUICVersionContextKey can be used to find out the QUIC version of a TLS handshake from the @@ -84,8 +85,8 @@ type ReceiveStream interface { // Read reads data from the stream. // Read can be made to time out and return a net.Error with Timeout() == true // after a fixed time limit; see SetDeadline and SetReadDeadline. - // If the stream was canceled by the peer, the error implements the StreamError - // interface, and Canceled() == true. + // If the stream was canceled by the peer, the error is a StreamError and + // Remote == true. // If the connection was closed due to a timeout, the error satisfies // the net.Error interface, and Timeout() will be true. io.Reader @@ -108,8 +109,8 @@ type SendStream interface { // Write writes data to the stream. // Write can be made to time out and return a net.Error with Timeout() == true // after a fixed time limit; see SetDeadline and SetWriteDeadline. - // If the stream was canceled by the peer, the error implements the StreamError - // interface, and Canceled() == true. + // If the stream was canceled by the peer, the error is a StreamError and + // Remote == true. // If the connection was closed due to a timeout, the error satisfies // the net.Error interface, and Timeout() will be true. io.Writer @@ -121,7 +122,9 @@ type SendStream interface { // CancelWrite aborts sending on this stream. // Data already written, but not yet delivered to the peer is not guaranteed to be delivered reliably. // Write will unblock immediately, and future calls to Write will fail. - // When called multiple times or after closing the stream it is a no-op. + // When called multiple times it is a no-op. + // When called after Close, it aborts delivery. Note that there is no guarantee if + // the peer will receive the FIN or the reset first. CancelWrite(StreamErrorCode) // The Context is canceled as soon as the write-side of the stream is closed. // This happens when Close() or CancelWrite() is called, or when the peer @@ -143,7 +146,7 @@ type SendStream interface { // * TransportError: for errors triggered by the QUIC transport (in many cases a misbehaving peer) // * IdleTimeoutError: when the peer goes away unexpectedly (this is a net.Error timeout error) // * HandshakeTimeoutError: when the cryptographic handshake takes too long (this is a net.Error timeout error) -// * StatelessResetError: when we receive a stateless reset (this is a net.Error temporary error) +// * StatelessResetError: when we receive a stateless reset // * VersionNegotiationError: returned by the client, when there's no version overlap between the peers type Connection interface { // AcceptStream returns the next stream opened by the peer, blocking until one is available. @@ -156,28 +159,29 @@ type Connection interface { AcceptUniStream(context.Context) (ReceiveStream, error) // OpenStream opens a new bidirectional QUIC stream. // There is no signaling to the peer about new streams: - // The peer can only accept the stream after data has been sent on the stream. - // If the error is non-nil, it satisfies the net.Error interface. - // When reaching the peer's stream limit, err.Temporary() will be true. - // If the connection was closed due to a timeout, Timeout() will be true. + // The peer can only accept the stream after data has been sent on the stream, + // or the stream has been reset or closed. + // When reaching the peer's stream limit, it is not possible to open a new stream until the + // peer raises the stream limit. In that case, a StreamLimitReachedError is returned. OpenStream() (Stream, error) // OpenStreamSync opens a new bidirectional QUIC stream. // It blocks until a new stream can be opened. // There is no signaling to the peer about new streams: // The peer can only accept the stream after data has been sent on the stream, // or the stream has been reset or closed. - // If the error is non-nil, it satisfies the net.Error interface. - // If the connection was closed due to a timeout, Timeout() will be true. OpenStreamSync(context.Context) (Stream, error) // OpenUniStream opens a new outgoing unidirectional QUIC stream. - // If the error is non-nil, it satisfies the net.Error interface. - // When reaching the peer's stream limit, Temporary() will be true. - // If the connection was closed due to a timeout, Timeout() will be true. + // There is no signaling to the peer about new streams: + // The peer can only accept the stream after data has been sent on the stream, + // or the stream has been reset or closed. + // When reaching the peer's stream limit, it is not possible to open a new stream until the + // peer raises the stream limit. In that case, a StreamLimitReachedError is returned. OpenUniStream() (SendStream, error) // OpenUniStreamSync opens a new outgoing unidirectional QUIC stream. // It blocks until a new stream can be opened. - // If the error is non-nil, it satisfies the net.Error interface. - // If the connection was closed due to a timeout, Timeout() will be true. + // There is no signaling to the peer about new streams: + // The peer can only accept the stream after data has been sent on the stream, + // or the stream has been reset or closed. OpenUniStreamSync(context.Context) (SendStream, error) // LocalAddr returns the local address. LocalAddr() net.Addr @@ -217,7 +221,7 @@ type EarlyConnection interface { // however the client's identity is only verified once the handshake completes. HandshakeComplete() <-chan struct{} - NextConnection() Connection + NextConnection(context.Context) (Connection, error) } // StatelessResetKey is a key used to derive stateless reset tokens. @@ -320,10 +324,15 @@ type Config struct { // If set to 0, then no keep alive is sent. Otherwise, the keep alive is sent on that period (or at most // every half of MaxIdleTimeout, whichever is smaller). KeepAlivePeriod time.Duration + // InitialPacketSize is the initial size of packets sent. + // It is usually not necessary to manually set this value, + // since Path MTU discovery very quickly finds the path's MTU. + // If set too high, the path might not support packets that large, leading to a timeout of the QUIC handshake. + // Values below 1200 are invalid. + InitialPacketSize uint16 // DisablePathMTUDiscovery disables Path MTU Discovery (RFC 8899). // This allows the sending of QUIC packets that fully utilize the available MTU of the path. // Path MTU discovery is only available on systems that allow setting of the Don't Fragment (DF) bit. - // If unavailable or disabled, packets will be at most 1252 (IPv4) / 1232 (IPv6) bytes in size. DisablePathMTUDiscovery bool // Allow0RTT allows the application to decide if a 0-RTT connection attempt should be accepted. // Only valid for the server. diff --git a/vendor/github.com/quic-go/quic-go/internal/ackhandler/received_packet_history.go b/vendor/github.com/quic-go/quic-go/internal/ackhandler/received_packet_history.go index 3143bfe12..f9feae1db 100644 --- a/vendor/github.com/quic-go/quic-go/internal/ackhandler/received_packet_history.go +++ b/vendor/github.com/quic-go/quic-go/internal/ackhandler/received_packet_history.go @@ -1,10 +1,9 @@ package ackhandler import ( - "sync" + "slices" "github.com/quic-go/quic-go/internal/protocol" - list "github.com/quic-go/quic-go/internal/utils/linkedlist" "github.com/quic-go/quic-go/internal/wire" ) @@ -14,25 +13,17 @@ type interval struct { End protocol.PacketNumber } -var intervalElementPool sync.Pool - -func init() { - intervalElementPool = *list.NewPool[interval]() -} - // The receivedPacketHistory stores if a packet number has already been received. // It generates ACK ranges which can be used to assemble an ACK frame. // It does not store packet contents. type receivedPacketHistory struct { - ranges *list.List[interval] + ranges []interval // maximum length: protocol.MaxNumAckRanges deletedBelow protocol.PacketNumber } func newReceivedPacketHistory() *receivedPacketHistory { - return &receivedPacketHistory{ - ranges: list.NewWithPool[interval](&intervalElementPool), - } + return &receivedPacketHistory{} } // ReceivedPacket registers a packet with PacketNumber p and updates the ranges @@ -41,58 +32,54 @@ func (h *receivedPacketHistory) ReceivedPacket(p protocol.PacketNumber) bool /* if p < h.deletedBelow { return false } + isNew := h.addToRanges(p) - h.maybeDeleteOldRanges() + // Delete old ranges, if we're tracking too many of them. + // This is a DoS defense against a peer that sends us too many gaps. + if len(h.ranges) > protocol.MaxNumAckRanges { + h.ranges = slices.Delete(h.ranges, 0, len(h.ranges)-protocol.MaxNumAckRanges) + } return isNew } func (h *receivedPacketHistory) addToRanges(p protocol.PacketNumber) bool /* is a new packet (and not a duplicate / delayed packet) */ { - if h.ranges.Len() == 0 { - h.ranges.PushBack(interval{Start: p, End: p}) + if len(h.ranges) == 0 { + h.ranges = append(h.ranges, interval{Start: p, End: p}) return true } - for el := h.ranges.Back(); el != nil; el = el.Prev() { + for i := len(h.ranges) - 1; i >= 0; i-- { // p already included in an existing range. Nothing to do here - if p >= el.Value.Start && p <= el.Value.End { + if p >= h.ranges[i].Start && p <= h.ranges[i].End { return false } - if el.Value.End == p-1 { // extend a range at the end - el.Value.End = p + if h.ranges[i].End == p-1 { // extend a range at the end + h.ranges[i].End = p return true } - if el.Value.Start == p+1 { // extend a range at the beginning - el.Value.Start = p + if h.ranges[i].Start == p+1 { // extend a range at the beginning + h.ranges[i].Start = p - prev := el.Prev() - if prev != nil && prev.Value.End+1 == el.Value.Start { // merge two ranges - prev.Value.End = el.Value.End - h.ranges.Remove(el) + if i > 0 && h.ranges[i-1].End+1 == h.ranges[i].Start { // merge two ranges + h.ranges[i-1].End = h.ranges[i].End + h.ranges = slices.Delete(h.ranges, i, i+1) } return true } - // create a new range at the end - if p > el.Value.End { - h.ranges.InsertAfter(interval{Start: p, End: p}, el) + // create a new range after the current one + if p > h.ranges[i].End { + h.ranges = slices.Insert(h.ranges, i+1, interval{Start: p, End: p}) return true } } // create a new range at the beginning - h.ranges.InsertBefore(interval{Start: p, End: p}, h.ranges.Front()) + h.ranges = slices.Insert(h.ranges, 0, interval{Start: p, End: p}) return true } -// Delete old ranges, if we're tracking more than 500 of them. -// This is a DoS defense against a peer that sends us too many gaps. -func (h *receivedPacketHistory) maybeDeleteOldRanges() { - for h.ranges.Len() > protocol.MaxNumAckRanges { - h.ranges.Remove(h.ranges.Front()) - } -} - // DeleteBelow deletes all entries below (but not including) p func (h *receivedPacketHistory) DeleteBelow(p protocol.PacketNumber) { if p < h.deletedBelow { @@ -100,37 +87,39 @@ func (h *receivedPacketHistory) DeleteBelow(p protocol.PacketNumber) { } h.deletedBelow = p - nextEl := h.ranges.Front() - for el := h.ranges.Front(); nextEl != nil; el = nextEl { - nextEl = el.Next() + if len(h.ranges) == 0 { + return + } - if el.Value.End < p { // delete a whole range - h.ranges.Remove(el) - } else if p > el.Value.Start && p <= el.Value.End { - el.Value.Start = p - return + idx := -1 + for i := 0; i < len(h.ranges); i++ { + if h.ranges[i].End < p { // delete a whole range + idx = i + } else if p > h.ranges[i].Start && p <= h.ranges[i].End { + h.ranges[i].Start = p + break } else { // no ranges affected. Nothing to do - return + break } } + if idx >= 0 { + h.ranges = slices.Delete(h.ranges, 0, idx+1) + } } // AppendAckRanges appends to a slice of all AckRanges that can be used in an AckFrame func (h *receivedPacketHistory) AppendAckRanges(ackRanges []wire.AckRange) []wire.AckRange { - if h.ranges.Len() > 0 { - for el := h.ranges.Back(); el != nil; el = el.Prev() { - ackRanges = append(ackRanges, wire.AckRange{Smallest: el.Value.Start, Largest: el.Value.End}) - } + for i := len(h.ranges) - 1; i >= 0; i-- { + ackRanges = append(ackRanges, wire.AckRange{Smallest: h.ranges[i].Start, Largest: h.ranges[i].End}) } return ackRanges } func (h *receivedPacketHistory) GetHighestAckRange() wire.AckRange { ackRange := wire.AckRange{} - if h.ranges.Len() > 0 { - r := h.ranges.Back().Value - ackRange.Smallest = r.Start - ackRange.Largest = r.End + if len(h.ranges) > 0 { + ackRange.Smallest = h.ranges[len(h.ranges)-1].Start + ackRange.Largest = h.ranges[len(h.ranges)-1].End } return ackRange } @@ -139,11 +128,12 @@ func (h *receivedPacketHistory) IsPotentiallyDuplicate(p protocol.PacketNumber) if p < h.deletedBelow { return true } - for el := h.ranges.Back(); el != nil; el = el.Prev() { - if p > el.Value.End { + // Iterating over the slices is faster than using a binary search (using slices.BinarySearchFunc). + for i := len(h.ranges) - 1; i >= 0; i-- { + if p > h.ranges[i].End { return false } - if p <= el.Value.End && p >= el.Value.Start { + if p <= h.ranges[i].End && p >= h.ranges[i].Start { return true } } diff --git a/vendor/github.com/quic-go/quic-go/internal/ackhandler/sent_packet_handler.go b/vendor/github.com/quic-go/quic-go/internal/ackhandler/sent_packet_handler.go index 3cef89239..b84f0dcbb 100644 --- a/vendor/github.com/quic-go/quic-go/internal/ackhandler/sent_packet_handler.go +++ b/vendor/github.com/quic-go/quic-go/internal/ackhandler/sent_packet_handler.go @@ -28,7 +28,7 @@ const ( ) type packetNumberSpace struct { - history *sentPacketHistory + history sentPacketHistory pns packetNumberGenerator lossTime time.Time @@ -38,15 +38,15 @@ type packetNumberSpace struct { largestSent protocol.PacketNumber } -func newPacketNumberSpace(initialPN protocol.PacketNumber, skipPNs bool) *packetNumberSpace { +func newPacketNumberSpace(initialPN protocol.PacketNumber, isAppData bool) *packetNumberSpace { var pns packetNumberGenerator - if skipPNs { + if isAppData { pns = newSkippingPacketNumberGenerator(initialPN, protocol.SkipPacketInitialPeriod, protocol.SkipPacketMaxPeriod) } else { pns = newSequentialPacketNumberGenerator(initialPN) } return &packetNumberSpace{ - history: newSentPacketHistory(), + history: *newSentPacketHistory(isAppData), pns: pns, largestSent: protocol.InvalidPacketNumber, largestAcked: protocol.InvalidPacketNumber, @@ -756,7 +756,7 @@ func (h *sentPacketHandler) PeekPacketNumber(encLevel protocol.EncryptionLevel) pnSpace := h.getPacketNumberSpace(encLevel) pn := pnSpace.pns.Peek() // See section 17.1 of RFC 9000. - return pn, protocol.GetPacketNumberLengthForHeader(pn, pnSpace.largestAcked) + return pn, protocol.PacketNumberLengthForHeader(pn, pnSpace.largestAcked) } func (h *sentPacketHandler) PopPacketNumber(encLevel protocol.EncryptionLevel) protocol.PacketNumber { diff --git a/vendor/github.com/quic-go/quic-go/internal/ackhandler/sent_packet_history.go b/vendor/github.com/quic-go/quic-go/internal/ackhandler/sent_packet_history.go index c14c0f49b..9968df6ac 100644 --- a/vendor/github.com/quic-go/quic-go/internal/ackhandler/sent_packet_history.go +++ b/vendor/github.com/quic-go/quic-go/internal/ackhandler/sent_packet_history.go @@ -14,11 +14,16 @@ type sentPacketHistory struct { highestPacketNumber protocol.PacketNumber } -func newSentPacketHistory() *sentPacketHistory { - return &sentPacketHistory{ - packets: make([]*packet, 0, 32), +func newSentPacketHistory(isAppData bool) *sentPacketHistory { + h := &sentPacketHistory{ highestPacketNumber: protocol.InvalidPacketNumber, } + if isAppData { + h.packets = make([]*packet, 0, 32) + } else { + h.packets = make([]*packet, 0, 6) + } + return h } func (h *sentPacketHistory) checkSequentialPacketNumberUse(pn protocol.PacketNumber) { diff --git a/vendor/github.com/quic-go/quic-go/internal/congestion/cubic.go b/vendor/github.com/quic-go/quic-go/internal/congestion/cubic.go index 4e30de650..b35d40d41 100644 --- a/vendor/github.com/quic-go/quic-go/internal/congestion/cubic.go +++ b/vendor/github.com/quic-go/quic-go/internal/congestion/cubic.go @@ -17,11 +17,11 @@ import ( // 1024*1024^3 (first 1024 is from 0.100^3) // where 0.100 is 100 ms which is the scaling round trip time. const ( - cubeScale = 40 - cubeCongestionWindowScale = 410 - cubeFactor protocol.ByteCount = 1 << cubeScale / cubeCongestionWindowScale / maxDatagramSize + cubeScale = 40 + cubeCongestionWindowScale = 410 + cubeFactor = 1 << cubeScale / cubeCongestionWindowScale / maxDatagramSize // TODO: when re-enabling cubic, make sure to use the actual packet size here - maxDatagramSize = protocol.ByteCount(protocol.InitialPacketSizeIPv4) + maxDatagramSize = protocol.ByteCount(protocol.InitialPacketSize) ) const defaultNumConnections = 1 diff --git a/vendor/github.com/quic-go/quic-go/internal/congestion/cubic_sender.go b/vendor/github.com/quic-go/quic-go/internal/congestion/cubic_sender.go index a1b06ab34..075b08e00 100644 --- a/vendor/github.com/quic-go/quic-go/internal/congestion/cubic_sender.go +++ b/vendor/github.com/quic-go/quic-go/internal/congestion/cubic_sender.go @@ -12,7 +12,7 @@ import ( const ( // maxDatagramSize is the default maximum packet size used in the Linux TCP implementation. // Used in QUIC for congestion window computations in bytes. - initialMaxDatagramSize = protocol.ByteCount(protocol.InitialPacketSizeIPv4) + initialMaxDatagramSize = protocol.ByteCount(protocol.InitialPacketSize) maxBurstPackets = 3 renoBeta = 0.7 // Reno backoff factor. minCongestionWindowPackets = 2 diff --git a/vendor/github.com/quic-go/quic-go/internal/flowcontrol/connection_flow_controller.go b/vendor/github.com/quic-go/quic-go/internal/flowcontrol/connection_flow_controller.go index 8504cdcf5..2efcad747 100644 --- a/vendor/github.com/quic-go/quic-go/internal/flowcontrol/connection_flow_controller.go +++ b/vendor/github.com/quic-go/quic-go/internal/flowcontrol/connection_flow_controller.go @@ -12,8 +12,6 @@ import ( type connectionFlowController struct { baseFlowController - - queueWindowUpdate func() } var _ ConnectionFlowController = &connectionFlowController{} @@ -23,7 +21,6 @@ var _ ConnectionFlowController = &connectionFlowController{} func NewConnectionFlowController( receiveWindow protocol.ByteCount, maxReceiveWindow protocol.ByteCount, - queueWindowUpdate func(), allowWindowIncrease func(size protocol.ByteCount) bool, rttStats *utils.RTTStats, logger utils.Logger, @@ -37,7 +34,6 @@ func NewConnectionFlowController( allowWindowIncrease: allowWindowIncrease, logger: logger, }, - queueWindowUpdate: queueWindowUpdate, } } @@ -63,18 +59,14 @@ func (c *connectionFlowController) IncrementHighestReceived(increment protocol.B func (c *connectionFlowController) AddBytesRead(n protocol.ByteCount) { c.mutex.Lock() c.baseFlowController.addBytesRead(n) - shouldQueueWindowUpdate := c.hasWindowUpdate() c.mutex.Unlock() - if shouldQueueWindowUpdate { - c.queueWindowUpdate() - } } func (c *connectionFlowController) GetWindowUpdate() protocol.ByteCount { c.mutex.Lock() oldWindowSize := c.receiveWindowSize offset := c.baseFlowController.getWindowUpdate() - if oldWindowSize < c.receiveWindowSize { + if c.logger.Debug() && oldWindowSize < c.receiveWindowSize { c.logger.Debugf("Increasing receive flow control window for the connection to %d kB", c.receiveWindowSize/(1<<10)) } c.mutex.Unlock() diff --git a/vendor/github.com/quic-go/quic-go/internal/flowcontrol/interface.go b/vendor/github.com/quic-go/quic-go/internal/flowcontrol/interface.go index fc5f9de0a..57d12a95e 100644 --- a/vendor/github.com/quic-go/quic-go/internal/flowcontrol/interface.go +++ b/vendor/github.com/quic-go/quic-go/internal/flowcontrol/interface.go @@ -8,14 +8,13 @@ type flowController interface { UpdateSendWindow(protocol.ByteCount) (updated bool) AddBytesSent(protocol.ByteCount) // for receiving - AddBytesRead(protocol.ByteCount) GetWindowUpdate() protocol.ByteCount // returns 0 if no update is necessary - IsNewlyBlocked() (bool, protocol.ByteCount) } // A StreamFlowController is a flow controller for a QUIC stream. type StreamFlowController interface { flowController + AddBytesRead(protocol.ByteCount) (shouldQueueWindowUpdate bool) // UpdateHighestReceived is called when a new highest offset is received // final has to be to true if this is the final offset of the stream, // as contained in a STREAM frame with FIN bit, and the RESET_STREAM frame @@ -23,12 +22,15 @@ type StreamFlowController interface { // Abandon is called when reading from the stream is aborted early, // and there won't be any further calls to AddBytesRead. Abandon() + IsNewlyBlocked() bool } // The ConnectionFlowController is the flow controller for the connection. type ConnectionFlowController interface { flowController + AddBytesRead(protocol.ByteCount) Reset() error + IsNewlyBlocked() (bool, protocol.ByteCount) } type connectionFlowControllerI interface { diff --git a/vendor/github.com/quic-go/quic-go/internal/flowcontrol/stream_flow_controller.go b/vendor/github.com/quic-go/quic-go/internal/flowcontrol/stream_flow_controller.go index 1a69fb2b3..2d58351cb 100644 --- a/vendor/github.com/quic-go/quic-go/internal/flowcontrol/stream_flow_controller.go +++ b/vendor/github.com/quic-go/quic-go/internal/flowcontrol/stream_flow_controller.go @@ -13,8 +13,6 @@ type streamFlowController struct { streamID protocol.StreamID - queueWindowUpdate func() - connection connectionFlowControllerI receivedFinalOffset bool @@ -29,14 +27,12 @@ func NewStreamFlowController( receiveWindow protocol.ByteCount, maxReceiveWindow protocol.ByteCount, initialSendWindow protocol.ByteCount, - queueWindowUpdate func(protocol.StreamID), rttStats *utils.RTTStats, logger utils.Logger, ) StreamFlowController { return &streamFlowController{ - streamID: streamID, - connection: cfc.(connectionFlowControllerI), - queueWindowUpdate: func() { queueWindowUpdate(streamID) }, + streamID: streamID, + connection: cfc.(connectionFlowControllerI), baseFlowController: baseFlowController{ rttStats: rttStats, receiveWindow: receiveWindow, @@ -97,20 +93,19 @@ func (c *streamFlowController) UpdateHighestReceived(offset protocol.ByteCount, return c.connection.IncrementHighestReceived(increment) } -func (c *streamFlowController) AddBytesRead(n protocol.ByteCount) { +func (c *streamFlowController) AddBytesRead(n protocol.ByteCount) (shouldQueueWindowUpdate bool) { c.mutex.Lock() c.baseFlowController.addBytesRead(n) - shouldQueueWindowUpdate := c.shouldQueueWindowUpdate() + shouldQueueWindowUpdate = c.shouldQueueWindowUpdate() c.mutex.Unlock() - if shouldQueueWindowUpdate { - c.queueWindowUpdate() - } c.connection.AddBytesRead(n) + return } func (c *streamFlowController) Abandon() { c.mutex.Lock() unread := c.highestReceived - c.bytesRead + c.bytesRead = c.highestReceived c.mutex.Unlock() if unread > 0 { c.connection.AddBytesRead(unread) @@ -126,6 +121,11 @@ func (c *streamFlowController) SendWindowSize() protocol.ByteCount { return min(c.baseFlowController.sendWindowSize(), c.connection.SendWindowSize()) } +func (c *streamFlowController) IsNewlyBlocked() bool { + blocked, _ := c.baseFlowController.IsNewlyBlocked() + return blocked +} + func (c *streamFlowController) shouldQueueWindowUpdate() bool { return !c.receivedFinalOffset && c.hasWindowUpdate() } diff --git a/vendor/github.com/quic-go/quic-go/internal/handshake/crypto_setup.go b/vendor/github.com/quic-go/quic-go/internal/handshake/crypto_setup.go index adf74fe74..c8e6cb33e 100644 --- a/vendor/github.com/quic-go/quic-go/internal/handshake/crypto_setup.go +++ b/vendor/github.com/quic-go/quic-go/internal/handshake/crypto_setup.go @@ -1,7 +1,6 @@ package handshake import ( - "bytes" "context" "crypto/tls" "errors" @@ -124,44 +123,12 @@ func NewCryptoSetupServer( ) cs.allow0RTT = allow0RTT - quicConf := &tls.QUICConfig{TLSConfig: tlsConf} - qtls.SetupConfigForServer(quicConf, cs.allow0RTT, cs.getDataForSessionTicket, cs.handleSessionTicket) - addConnToClientHelloInfo(quicConf.TLSConfig, localAddr, remoteAddr) - - cs.tlsConf = quicConf.TLSConfig - cs.conn = tls.QUICServer(quicConf) - + tlsConf = qtls.SetupConfigForServer(tlsConf, localAddr, remoteAddr, cs.getDataForSessionTicket, cs.handleSessionTicket) + cs.tlsConf = tlsConf + cs.conn = tls.QUICServer(&tls.QUICConfig{TLSConfig: tlsConf}) return cs } -// The tls.Config contains two callbacks that pass in a tls.ClientHelloInfo. -// Since crypto/tls doesn't do it, we need to make sure to set the Conn field with a fake net.Conn -// that allows the caller to get the local and the remote address. -func addConnToClientHelloInfo(conf *tls.Config, localAddr, remoteAddr net.Addr) { - if conf.GetConfigForClient != nil { - gcfc := conf.GetConfigForClient - conf.GetConfigForClient = func(info *tls.ClientHelloInfo) (*tls.Config, error) { - info.Conn = &conn{localAddr: localAddr, remoteAddr: remoteAddr} - c, err := gcfc(info) - if c != nil { - c = c.Clone() - // This won't be necessary anymore once https://github.com/golang/go/issues/63722 is accepted. - c.MinVersion = tls.VersionTLS13 - // We're returning a tls.Config here, so we need to apply this recursively. - addConnToClientHelloInfo(c, localAddr, remoteAddr) - } - return c, err - } - } - if conf.GetCertificate != nil { - gc := conf.GetCertificate - conf.GetCertificate = func(info *tls.ClientHelloInfo) (*tls.Certificate, error) { - info.Conn = &conn{localAddr: localAddr, remoteAddr: remoteAddr} - return gc(info) - } - } -} - func newCryptoSetup( connID protocol.ConnectionID, tp *wire.TransportParameters, @@ -204,8 +171,8 @@ func (h *cryptoSetup) SetLargest1RTTAcked(pn protocol.PacketNumber) error { return h.aead.SetLargestAcked(pn) } -func (h *cryptoSetup) StartHandshake() error { - err := h.conn.Start(context.WithValue(context.Background(), QUICVersionContextKey, h.version)) +func (h *cryptoSetup) StartHandshake(ctx context.Context) error { + err := h.conn.Start(context.WithValue(ctx, QUICVersionContextKey, h.version)) if err != nil { return wrapError(err) } @@ -262,6 +229,9 @@ func (h *cryptoSetup) handleMessage(data []byte, encLevel protocol.EncryptionLev } func (h *cryptoSetup) handleEvent(ev tls.QUICEvent) (done bool, err error) { + //nolint:exhaustive + // Go 1.23 added new 0-RTT events, see https://github.com/quic-go/quic-go/issues/4272. + // We will start using these events when dropping support for Go 1.22. switch ev.Kind { case tls.QUICNoEvent: return true, nil @@ -286,7 +256,10 @@ func (h *cryptoSetup) handleEvent(ev tls.QUICEvent) (done bool, err error) { h.handshakeComplete() return false, nil default: - return false, fmt.Errorf("unexpected event: %d", ev.Kind) + // Unknown events should be ignored. + // crypto/tls will ensure that this is safe to do. + // See the discussion following https://github.com/golang/go/issues/68124#issuecomment-2187042510 for details. + return false, nil } } @@ -338,25 +311,26 @@ func (h *cryptoSetup) handleDataFromSessionState(data []byte, earlyData bool) (a return false } -func decodeDataFromSessionState(data []byte, earlyData bool) (time.Duration, *wire.TransportParameters, error) { - r := bytes.NewReader(data) - ver, err := quicvarint.Read(r) +func decodeDataFromSessionState(b []byte, earlyData bool) (time.Duration, *wire.TransportParameters, error) { + ver, l, err := quicvarint.Parse(b) if err != nil { return 0, nil, err } + b = b[l:] if ver != clientSessionStateRevision { return 0, nil, fmt.Errorf("mismatching version. Got %d, expected %d", ver, clientSessionStateRevision) } - rttEncoded, err := quicvarint.Read(r) + rttEncoded, l, err := quicvarint.Parse(b) if err != nil { return 0, nil, err } + b = b[l:] rtt := time.Duration(rttEncoded) * time.Microsecond if !earlyData { return rtt, nil, nil } var tp wire.TransportParameters - if err := tp.UnmarshalFromSessionTicket(r); err != nil { + if err := tp.UnmarshalFromSessionTicket(b); err != nil { return 0, nil, err } return rtt, &tp, nil @@ -376,9 +350,7 @@ func (h *cryptoSetup) getDataForSessionTicket() []byte { // Due to limitations in crypto/tls, it's only possible to generate a single session ticket per connection. // It is only valid for the server. func (h *cryptoSetup) GetSessionTicket() ([]byte, error) { - if err := h.conn.SendSessionTicket(tls.QUICSessionTicketOptions{ - EarlyData: h.allow0RTT, - }); err != nil { + if err := h.conn.SendSessionTicket(tls.QUICSessionTicketOptions{EarlyData: h.allow0RTT}); err != nil { // Session tickets might be disabled by tls.Config.SessionTicketsDisabled. // We can't check h.tlsConfig here, since the actual config might have been obtained from // the GetConfigForClient callback. @@ -655,8 +627,7 @@ func (h *cryptoSetup) ConnectionState() ConnectionState { } func wrapError(err error) error { - // alert 80 is an internal error - if alertErr := tls.AlertError(0); errors.As(err, &alertErr) && alertErr != 80 { + if alertErr := tls.AlertError(0); errors.As(err, &alertErr) { return qerr.NewLocalCryptoError(uint8(alertErr), err) } return &qerr.TransportError{ErrorCode: qerr.InternalError, ErrorMessage: err.Error()} diff --git a/vendor/github.com/quic-go/quic-go/internal/handshake/interface.go b/vendor/github.com/quic-go/quic-go/internal/handshake/interface.go index fab224f9b..c3a59fcd0 100644 --- a/vendor/github.com/quic-go/quic-go/internal/handshake/interface.go +++ b/vendor/github.com/quic-go/quic-go/internal/handshake/interface.go @@ -1,6 +1,7 @@ package handshake import ( + "context" "crypto/tls" "errors" "io" @@ -82,6 +83,29 @@ const ( EventHandshakeComplete ) +func (k EventKind) String() string { + switch k { + case EventNoEvent: + return "EventNoEvent" + case EventWriteInitialData: + return "EventWriteInitialData" + case EventWriteHandshakeData: + return "EventWriteHandshakeData" + case EventReceivedReadKeys: + return "EventReceivedReadKeys" + case EventDiscard0RTTKeys: + return "EventDiscard0RTTKeys" + case EventReceivedTransportParameters: + return "EventReceivedTransportParameters" + case EventRestoredTransportParameters: + return "EventRestoredTransportParameters" + case EventHandshakeComplete: + return "EventHandshakeComplete" + default: + return "Unknown EventKind" + } +} + // Event is a handshake event. type Event struct { Kind EventKind @@ -91,7 +115,7 @@ type Event struct { // CryptoSetup handles the handshake and protecting / unprotecting packets type CryptoSetup interface { - StartHandshake() error + StartHandshake(context.Context) error io.Closer ChangeConnectionID(protocol.ConnectionID) GetSessionTicket() ([]byte, error) diff --git a/vendor/github.com/quic-go/quic-go/internal/handshake/session_ticket.go b/vendor/github.com/quic-go/quic-go/internal/handshake/session_ticket.go index 9481af563..b67f0101e 100644 --- a/vendor/github.com/quic-go/quic-go/internal/handshake/session_ticket.go +++ b/vendor/github.com/quic-go/quic-go/internal/handshake/session_ticket.go @@ -1,7 +1,6 @@ package handshake import ( - "bytes" "errors" "fmt" "time" @@ -28,25 +27,26 @@ func (t *sessionTicket) Marshal() []byte { } func (t *sessionTicket) Unmarshal(b []byte, using0RTT bool) error { - r := bytes.NewReader(b) - rev, err := quicvarint.Read(r) + rev, l, err := quicvarint.Parse(b) if err != nil { return errors.New("failed to read session ticket revision") } + b = b[l:] if rev != sessionTicketRevision { return fmt.Errorf("unknown session ticket revision: %d", rev) } - rtt, err := quicvarint.Read(r) + rtt, l, err := quicvarint.Parse(b) if err != nil { return errors.New("failed to read RTT") } + b = b[l:] if using0RTT { var tp wire.TransportParameters - if err := tp.UnmarshalFromSessionTicket(r); err != nil { + if err := tp.UnmarshalFromSessionTicket(b); err != nil { return fmt.Errorf("unmarshaling transport parameters from session ticket failed: %s", err.Error()) } t.Parameters = &tp - } else if r.Len() > 0 { + } else if len(b) > 0 { return fmt.Errorf("the session ticket has more bytes than expected") } t.RTT = time.Duration(rtt) * time.Microsecond diff --git a/vendor/github.com/quic-go/quic-go/internal/handshake/token_generator.go b/vendor/github.com/quic-go/quic-go/internal/handshake/token_generator.go index 2d91e6b25..84e58cfc7 100644 --- a/vendor/github.com/quic-go/quic-go/internal/handshake/token_generator.go +++ b/vendor/github.com/quic-go/quic-go/internal/handshake/token_generator.go @@ -46,7 +46,7 @@ type TokenGenerator struct { // NewTokenGenerator initializes a new TokenGenerator func NewTokenGenerator(key TokenProtectorKey) *TokenGenerator { - return &TokenGenerator{tokenProtector: newTokenProtector(key)} + return &TokenGenerator{tokenProtector: *newTokenProtector(key)} } // NewRetryToken generates a new token for a Retry for a given source address diff --git a/vendor/github.com/quic-go/quic-go/internal/handshake/token_protector.go b/vendor/github.com/quic-go/quic-go/internal/handshake/token_protector.go index f3a99e411..157791895 100644 --- a/vendor/github.com/quic-go/quic-go/internal/handshake/token_protector.go +++ b/vendor/github.com/quic-go/quic-go/internal/handshake/token_protector.go @@ -14,28 +14,20 @@ import ( // TokenProtectorKey is the key used to encrypt both Retry and session resumption tokens. type TokenProtectorKey [32]byte -// TokenProtector is used to create and verify a token -type tokenProtector interface { - // NewToken creates a new token - NewToken([]byte) ([]byte, error) - // DecodeToken decodes a token - DecodeToken([]byte) ([]byte, error) -} - const tokenNonceSize = 32 // tokenProtector is used to create and verify a token -type tokenProtectorImpl struct { +type tokenProtector struct { key TokenProtectorKey } // newTokenProtector creates a source for source address tokens -func newTokenProtector(key TokenProtectorKey) tokenProtector { - return &tokenProtectorImpl{key: key} +func newTokenProtector(key TokenProtectorKey) *tokenProtector { + return &tokenProtector{key: key} } // NewToken encodes data into a new token. -func (s *tokenProtectorImpl) NewToken(data []byte) ([]byte, error) { +func (s *tokenProtector) NewToken(data []byte) ([]byte, error) { var nonce [tokenNonceSize]byte if _, err := rand.Read(nonce[:]); err != nil { return nil, err @@ -48,7 +40,7 @@ func (s *tokenProtectorImpl) NewToken(data []byte) ([]byte, error) { } // DecodeToken decodes a token. -func (s *tokenProtectorImpl) DecodeToken(p []byte) ([]byte, error) { +func (s *tokenProtector) DecodeToken(p []byte) ([]byte, error) { if len(p) < tokenNonceSize { return nil, fmt.Errorf("token too short: %d", len(p)) } @@ -60,7 +52,7 @@ func (s *tokenProtectorImpl) DecodeToken(p []byte) ([]byte, error) { return aead.Open(nil, aeadNonce, p[tokenNonceSize:], nil) } -func (s *tokenProtectorImpl) createAEAD(nonce []byte) (cipher.AEAD, []byte, error) { +func (s *tokenProtector) createAEAD(nonce []byte) (cipher.AEAD, []byte, error) { h := hkdf.New(sha256.New, s.key[:], nonce, []byte("quic-go token source")) key := make([]byte, 32) // use a 32 byte key, in order to select AES-256 if _, err := io.ReadFull(h, key); err != nil { diff --git a/vendor/github.com/quic-go/quic-go/internal/logutils/frame.go b/vendor/github.com/quic-go/quic-go/internal/logutils/frame.go deleted file mode 100644 index a6032fc20..000000000 --- a/vendor/github.com/quic-go/quic-go/internal/logutils/frame.go +++ /dev/null @@ -1,50 +0,0 @@ -package logutils - -import ( - "github.com/quic-go/quic-go/internal/protocol" - "github.com/quic-go/quic-go/internal/wire" - "github.com/quic-go/quic-go/logging" -) - -// ConvertFrame converts a wire.Frame into a logging.Frame. -// This makes it possible for external packages to access the frames. -// Furthermore, it removes the data slices from CRYPTO and STREAM frames. -func ConvertFrame(frame wire.Frame) logging.Frame { - switch f := frame.(type) { - case *wire.AckFrame: - // We use a pool for ACK frames. - // Implementations of the tracer interface may hold on to frames, so we need to make a copy here. - return ConvertAckFrame(f) - case *wire.CryptoFrame: - return &logging.CryptoFrame{ - Offset: f.Offset, - Length: protocol.ByteCount(len(f.Data)), - } - case *wire.StreamFrame: - return &logging.StreamFrame{ - StreamID: f.StreamID, - Offset: f.Offset, - Length: f.DataLen(), - Fin: f.Fin, - } - case *wire.DatagramFrame: - return &logging.DatagramFrame{ - Length: logging.ByteCount(len(f.Data)), - } - default: - return logging.Frame(frame) - } -} - -func ConvertAckFrame(f *wire.AckFrame) *logging.AckFrame { - ranges := make([]wire.AckRange, 0, len(f.AckRanges)) - ranges = append(ranges, f.AckRanges...) - ack := &logging.AckFrame{ - AckRanges: ranges, - DelayTime: f.DelayTime, - ECNCE: f.ECNCE, - ECT0: f.ECT0, - ECT1: f.ECT1, - } - return ack -} diff --git a/vendor/github.com/quic-go/quic-go/internal/protocol/packet_number.go b/vendor/github.com/quic-go/quic-go/internal/protocol/packet_number.go index bd3401619..9422db924 100644 --- a/vendor/github.com/quic-go/quic-go/internal/protocol/packet_number.go +++ b/vendor/github.com/quic-go/quic-go/internal/protocol/packet_number.go @@ -21,58 +21,36 @@ const ( PacketNumberLen4 PacketNumberLen = 4 ) -// DecodePacketNumber calculates the packet number based on the received packet number, its length and the last seen packet number -func DecodePacketNumber( - packetNumberLength PacketNumberLen, - lastPacketNumber PacketNumber, - wirePacketNumber PacketNumber, -) PacketNumber { - var epochDelta PacketNumber - switch packetNumberLength { - case PacketNumberLen1: - epochDelta = PacketNumber(1) << 8 - case PacketNumberLen2: - epochDelta = PacketNumber(1) << 16 - case PacketNumberLen3: - epochDelta = PacketNumber(1) << 24 - case PacketNumberLen4: - epochDelta = PacketNumber(1) << 32 +// DecodePacketNumber calculates the packet number based its length and the last seen packet number +// This function is taken from https://www.rfc-editor.org/rfc/rfc9000.html#section-a.3. +func DecodePacketNumber(length PacketNumberLen, largest PacketNumber, truncated PacketNumber) PacketNumber { + expected := largest + 1 + win := PacketNumber(1 << (length * 8)) + hwin := win / 2 + mask := win - 1 + candidate := (expected & ^mask) | truncated + if candidate <= expected-hwin && candidate < 1<<62-win { + return candidate + win } - epoch := lastPacketNumber & ^(epochDelta - 1) - var prevEpochBegin PacketNumber - if epoch > epochDelta { - prevEpochBegin = epoch - epochDelta + if candidate > expected+hwin && candidate >= win { + return candidate - win } - nextEpochBegin := epoch + epochDelta - return closestTo( - lastPacketNumber+1, - epoch+wirePacketNumber, - closestTo(lastPacketNumber+1, prevEpochBegin+wirePacketNumber, nextEpochBegin+wirePacketNumber), - ) + return candidate } -func closestTo(target, a, b PacketNumber) PacketNumber { - if delta(target, a) < delta(target, b) { - return a - } - return b -} - -func delta(a, b PacketNumber) PacketNumber { - if a < b { - return b - a - } - return a - b -} - -// GetPacketNumberLengthForHeader gets the length of the packet number for the public header +// PacketNumberLengthForHeader gets the length of the packet number for the public header // it never chooses a PacketNumberLen of 1 byte, since this is too short under certain circumstances -func GetPacketNumberLengthForHeader(packetNumber, leastUnacked PacketNumber) PacketNumberLen { - diff := uint64(packetNumber - leastUnacked) - if diff < (1 << (16 - 1)) { +func PacketNumberLengthForHeader(pn, largestAcked PacketNumber) PacketNumberLen { + var numUnacked PacketNumber + if largestAcked == InvalidPacketNumber { + numUnacked = pn + 1 + } else { + numUnacked = pn - largestAcked + } + if numUnacked < 1<<(16-1) { return PacketNumberLen2 } - if diff < (1 << (24 - 1)) { + if numUnacked < 1<<(24-1) { return PacketNumberLen3 } return PacketNumberLen4 diff --git a/vendor/github.com/quic-go/quic-go/internal/protocol/params.go b/vendor/github.com/quic-go/quic-go/internal/protocol/params.go index 487cbc06b..7c4d8d4de 100644 --- a/vendor/github.com/quic-go/quic-go/internal/protocol/params.go +++ b/vendor/github.com/quic-go/quic-go/internal/protocol/params.go @@ -3,16 +3,13 @@ package protocol import "time" // DesiredReceiveBufferSize is the kernel UDP receive buffer size that we'd like to use. -const DesiredReceiveBufferSize = (1 << 20) * 2 // 2 MB +const DesiredReceiveBufferSize = (1 << 20) * 7 // 7 MB // DesiredSendBufferSize is the kernel UDP send buffer size that we'd like to use. -const DesiredSendBufferSize = (1 << 20) * 2 // 2 MB +const DesiredSendBufferSize = (1 << 20) * 7 // 7 MB -// InitialPacketSizeIPv4 is the maximum packet size that we use for sending IPv4 packets. -const InitialPacketSizeIPv4 = 1252 - -// InitialPacketSizeIPv6 is the maximum packet size that we use for sending IPv6 packets. -const InitialPacketSizeIPv6 = 1232 +// InitialPacketSize is the initial (before Path MTU discovery) maximum packet size used. +const InitialPacketSize = 1280 // MaxCongestionWindowPackets is the maximum congestion window in packet. const MaxCongestionWindowPackets = 10000 diff --git a/vendor/github.com/quic-go/quic-go/internal/handshake/conn.go b/vendor/github.com/quic-go/quic-go/internal/qtls/conn.go similarity index 97% rename from vendor/github.com/quic-go/quic-go/internal/handshake/conn.go rename to vendor/github.com/quic-go/quic-go/internal/qtls/conn.go index 54af823ba..6660ac667 100644 --- a/vendor/github.com/quic-go/quic-go/internal/handshake/conn.go +++ b/vendor/github.com/quic-go/quic-go/internal/qtls/conn.go @@ -1,4 +1,4 @@ -package handshake +package qtls import ( "net" diff --git a/vendor/github.com/quic-go/quic-go/internal/qtls/qtls.go b/vendor/github.com/quic-go/quic-go/internal/qtls/qtls.go index ebcd9d4de..cdfe82a2b 100644 --- a/vendor/github.com/quic-go/quic-go/internal/qtls/qtls.go +++ b/vendor/github.com/quic-go/quic-go/internal/qtls/qtls.go @@ -4,20 +4,23 @@ import ( "bytes" "crypto/tls" "fmt" + "net" "github.com/quic-go/quic-go/internal/protocol" ) -func SetupConfigForServer(qconf *tls.QUICConfig, _ bool, getData func() []byte, handleSessionTicket func([]byte, bool) bool) { - conf := qconf.TLSConfig - +func SetupConfigForServer( + conf *tls.Config, + localAddr, remoteAddr net.Addr, + getData func() []byte, + handleSessionTicket func([]byte, bool) bool, +) *tls.Config { // Workaround for https://github.com/golang/go/issues/60506. // This initializes the session tickets _before_ cloning the config. _, _ = conf.DecryptTicket(nil, tls.ConnectionState{}) conf = conf.Clone() conf.MinVersion = tls.VersionTLS13 - qconf.TLSConfig = conf // add callbacks to save transport parameters into the session ticket origWrapSession := conf.WrapSession @@ -58,6 +61,29 @@ func SetupConfigForServer(qconf *tls.QUICConfig, _ bool, getData func() []byte, return state, nil } + // The tls.Config contains two callbacks that pass in a tls.ClientHelloInfo. + // Since crypto/tls doesn't do it, we need to make sure to set the Conn field with a fake net.Conn + // that allows the caller to get the local and the remote address. + if conf.GetConfigForClient != nil { + gcfc := conf.GetConfigForClient + conf.GetConfigForClient = func(info *tls.ClientHelloInfo) (*tls.Config, error) { + info.Conn = &conn{localAddr: localAddr, remoteAddr: remoteAddr} + c, err := gcfc(info) + if c != nil { + // We're returning a tls.Config here, so we need to apply this recursively. + c = SetupConfigForServer(c, localAddr, remoteAddr, getData, handleSessionTicket) + } + return c, err + } + } + if conf.GetCertificate != nil { + gc := conf.GetCertificate + conf.GetCertificate = func(info *tls.ClientHelloInfo) (*tls.Certificate, error) { + info.Conn = &conn{localAddr: localAddr, remoteAddr: remoteAddr} + return gc(info) + } + } + return conf } func SetupConfigForClient( diff --git a/vendor/github.com/quic-go/quic-go/internal/utils/byteorder.go b/vendor/github.com/quic-go/quic-go/internal/utils/byteorder.go deleted file mode 100644 index a9b715e2f..000000000 --- a/vendor/github.com/quic-go/quic-go/internal/utils/byteorder.go +++ /dev/null @@ -1,21 +0,0 @@ -package utils - -import ( - "bytes" - "io" -) - -// A ByteOrder specifies how to convert byte sequences into 16-, 32-, or 64-bit unsigned integers. -type ByteOrder interface { - Uint32([]byte) uint32 - Uint24([]byte) uint32 - Uint16([]byte) uint16 - - ReadUint32(io.ByteReader) (uint32, error) - ReadUint24(io.ByteReader) (uint32, error) - ReadUint16(io.ByteReader) (uint16, error) - - WriteUint32(*bytes.Buffer, uint32) - WriteUint24(*bytes.Buffer, uint32) - WriteUint16(*bytes.Buffer, uint16) -} diff --git a/vendor/github.com/quic-go/quic-go/internal/utils/byteorder_big_endian.go b/vendor/github.com/quic-go/quic-go/internal/utils/byteorder_big_endian.go deleted file mode 100644 index 834a711b9..000000000 --- a/vendor/github.com/quic-go/quic-go/internal/utils/byteorder_big_endian.go +++ /dev/null @@ -1,103 +0,0 @@ -package utils - -import ( - "bytes" - "encoding/binary" - "io" -) - -// BigEndian is the big-endian implementation of ByteOrder. -var BigEndian ByteOrder = bigEndian{} - -type bigEndian struct{} - -var _ ByteOrder = &bigEndian{} - -// ReadUintN reads N bytes -func (bigEndian) ReadUintN(b io.ByteReader, length uint8) (uint64, error) { - var res uint64 - for i := uint8(0); i < length; i++ { - bt, err := b.ReadByte() - if err != nil { - return 0, err - } - res ^= uint64(bt) << ((length - 1 - i) * 8) - } - return res, nil -} - -// ReadUint32 reads a uint32 -func (bigEndian) ReadUint32(b io.ByteReader) (uint32, error) { - var b1, b2, b3, b4 uint8 - var err error - if b4, err = b.ReadByte(); err != nil { - return 0, err - } - if b3, err = b.ReadByte(); err != nil { - return 0, err - } - if b2, err = b.ReadByte(); err != nil { - return 0, err - } - if b1, err = b.ReadByte(); err != nil { - return 0, err - } - return uint32(b1) + uint32(b2)<<8 + uint32(b3)<<16 + uint32(b4)<<24, nil -} - -// ReadUint24 reads a uint24 -func (bigEndian) ReadUint24(b io.ByteReader) (uint32, error) { - var b1, b2, b3 uint8 - var err error - if b3, err = b.ReadByte(); err != nil { - return 0, err - } - if b2, err = b.ReadByte(); err != nil { - return 0, err - } - if b1, err = b.ReadByte(); err != nil { - return 0, err - } - return uint32(b1) + uint32(b2)<<8 + uint32(b3)<<16, nil -} - -// ReadUint16 reads a uint16 -func (bigEndian) ReadUint16(b io.ByteReader) (uint16, error) { - var b1, b2 uint8 - var err error - if b2, err = b.ReadByte(); err != nil { - return 0, err - } - if b1, err = b.ReadByte(); err != nil { - return 0, err - } - return uint16(b1) + uint16(b2)<<8, nil -} - -func (bigEndian) Uint32(b []byte) uint32 { - return binary.BigEndian.Uint32(b) -} - -func (bigEndian) Uint24(b []byte) uint32 { - _ = b[2] // bounds check hint to compiler; see golang.org/issue/14808 - return uint32(b[2]) | uint32(b[1])<<8 | uint32(b[0])<<16 -} - -func (bigEndian) Uint16(b []byte) uint16 { - return binary.BigEndian.Uint16(b) -} - -// WriteUint32 writes a uint32 -func (bigEndian) WriteUint32(b *bytes.Buffer, i uint32) { - b.Write([]byte{uint8(i >> 24), uint8(i >> 16), uint8(i >> 8), uint8(i)}) -} - -// WriteUint24 writes a uint24 -func (bigEndian) WriteUint24(b *bytes.Buffer, i uint32) { - b.Write([]byte{uint8(i >> 16), uint8(i >> 8), uint8(i)}) -} - -// WriteUint16 writes a uint16 -func (bigEndian) WriteUint16(b *bytes.Buffer, i uint16) { - b.Write([]byte{uint8(i >> 8), uint8(i)}) -} diff --git a/vendor/github.com/quic-go/quic-go/internal/utils/ip.go b/vendor/github.com/quic-go/quic-go/internal/utils/ip.go deleted file mode 100644 index 7ac7ffec1..000000000 --- a/vendor/github.com/quic-go/quic-go/internal/utils/ip.go +++ /dev/null @@ -1,10 +0,0 @@ -package utils - -import "net" - -func IsIPv4(ip net.IP) bool { - // If ip is not an IPv4 address, To4 returns nil. - // Note that there might be some corner cases, where this is not correct. - // See https://stackoverflow.com/questions/22751035/golang-distinguish-ipv4-ipv6. - return ip.To4() != nil -} diff --git a/vendor/github.com/quic-go/quic-go/internal/utils/minmax.go b/vendor/github.com/quic-go/quic-go/internal/utils/minmax.go deleted file mode 100644 index 03a9c9a87..000000000 --- a/vendor/github.com/quic-go/quic-go/internal/utils/minmax.go +++ /dev/null @@ -1,36 +0,0 @@ -package utils - -import ( - "math" - "time" -) - -// InfDuration is a duration of infinite length -const InfDuration = time.Duration(math.MaxInt64) - -// MinNonZeroDuration return the minimum duration that's not zero. -func MinNonZeroDuration(a, b time.Duration) time.Duration { - if a == 0 { - return b - } - if b == 0 { - return a - } - return min(a, b) -} - -// MinTime returns the earlier time -func MinTime(a, b time.Time) time.Time { - if a.After(b) { - return b - } - return a -} - -// MaxTime returns the later time -func MaxTime(a, b time.Time) time.Time { - if a.After(b) { - return a - } - return b -} diff --git a/vendor/github.com/quic-go/quic-go/internal/utils/rtt_stats.go b/vendor/github.com/quic-go/quic-go/internal/utils/rtt_stats.go index 463b95424..dcfac67d5 100644 --- a/vendor/github.com/quic-go/quic-go/internal/utils/rtt_stats.go +++ b/vendor/github.com/quic-go/quic-go/internal/utils/rtt_stats.go @@ -27,11 +27,6 @@ type RTTStats struct { maxAckDelay time.Duration } -// NewRTTStats makes a properly initialized RTTStats object -func NewRTTStats() *RTTStats { - return &RTTStats{} -} - // MinRTT Returns the minRTT for the entire connection. // May return Zero if no valid updates have occurred. func (r *RTTStats) MinRTT() time.Duration { return r.minRTT } @@ -64,7 +59,7 @@ func (r *RTTStats) PTO(includeMaxAckDelay bool) time.Duration { // UpdateRTT updates the RTT based on a new sample. func (r *RTTStats) UpdateRTT(sendDelta, ackDelay time.Duration, now time.Time) { - if sendDelta == InfDuration || sendDelta <= 0 { + if sendDelta <= 0 { return } @@ -113,19 +108,3 @@ func (r *RTTStats) SetInitialRTT(t time.Duration) { r.smoothedRTT = t r.latestRTT = t } - -// OnConnectionMigration is called when connection migrates and rtt measurement needs to be reset. -func (r *RTTStats) OnConnectionMigration() { - r.latestRTT = 0 - r.minRTT = 0 - r.smoothedRTT = 0 - r.meanDeviation = 0 -} - -// ExpireSmoothedMetrics causes the smoothed_rtt to be increased to the latest_rtt if the latest_rtt -// is larger. The mean deviation is increased to the most recent deviation if -// it's larger. -func (r *RTTStats) ExpireSmoothedMetrics() { - r.meanDeviation = max(r.meanDeviation, (r.smoothedRTT - r.latestRTT).Abs()) - r.smoothedRTT = max(r.smoothedRTT, r.latestRTT) -} diff --git a/vendor/github.com/quic-go/quic-go/internal/wire/ack_frame.go b/vendor/github.com/quic-go/quic-go/internal/wire/ack_frame.go index a0f3feb06..8befef4f2 100644 --- a/vendor/github.com/quic-go/quic-go/internal/wire/ack_frame.go +++ b/vendor/github.com/quic-go/quic-go/internal/wire/ack_frame.go @@ -1,13 +1,12 @@ package wire import ( - "bytes" "errors" + "math" "sort" "time" "github.com/quic-go/quic-go/internal/protocol" - "github.com/quic-go/quic-go/internal/utils" "github.com/quic-go/quic-go/quicvarint" ) @@ -22,91 +21,101 @@ type AckFrame struct { } // parseAckFrame reads an ACK frame -func parseAckFrame(frame *AckFrame, r *bytes.Reader, typ uint64, ackDelayExponent uint8, _ protocol.Version) error { +func parseAckFrame(frame *AckFrame, b []byte, typ uint64, ackDelayExponent uint8, _ protocol.Version) (int, error) { + startLen := len(b) ecn := typ == ackECNFrameType - la, err := quicvarint.Read(r) + la, l, err := quicvarint.Parse(b) if err != nil { - return err + return 0, replaceUnexpectedEOF(err) } + b = b[l:] largestAcked := protocol.PacketNumber(la) - delay, err := quicvarint.Read(r) + delay, l, err := quicvarint.Parse(b) if err != nil { - return err + return 0, replaceUnexpectedEOF(err) } + b = b[l:] delayTime := time.Duration(delay*1< largestAcked { - return errors.New("invalid first ACK range") + return 0, errors.New("invalid first ACK range") } smallest := largestAcked - ackBlock frame.AckRanges = append(frame.AckRanges, AckRange{Smallest: smallest, Largest: largestAcked}) // read all the other ACK ranges for i := uint64(0); i < numBlocks; i++ { - g, err := quicvarint.Read(r) + g, l, err := quicvarint.Parse(b) if err != nil { - return err + return 0, replaceUnexpectedEOF(err) } + b = b[l:] gap := protocol.PacketNumber(g) if smallest < gap+2 { - return errInvalidAckRanges + return 0, errInvalidAckRanges } largest := smallest - gap - 2 - ab, err := quicvarint.Read(r) + ab, l, err := quicvarint.Parse(b) if err != nil { - return err + return 0, replaceUnexpectedEOF(err) } + b = b[l:] ackBlock := protocol.PacketNumber(ab) if ackBlock > largest { - return errInvalidAckRanges + return 0, errInvalidAckRanges } smallest = largest - ackBlock frame.AckRanges = append(frame.AckRanges, AckRange{Smallest: smallest, Largest: largest}) } if !frame.validateAckRanges() { - return errInvalidAckRanges + return 0, errInvalidAckRanges } if ecn { - ect0, err := quicvarint.Read(r) + ect0, l, err := quicvarint.Parse(b) if err != nil { - return err + return 0, replaceUnexpectedEOF(err) } + b = b[l:] frame.ECT0 = ect0 - ect1, err := quicvarint.Read(r) + ect1, l, err := quicvarint.Parse(b) if err != nil { - return err + return 0, replaceUnexpectedEOF(err) } + b = b[l:] frame.ECT1 = ect1 - ecnce, err := quicvarint.Read(r) + ecnce, l, err := quicvarint.Parse(b) if err != nil { - return err + return 0, replaceUnexpectedEOF(err) } + b = b[l:] frame.ECNCE = ecnce } - return nil + return startLen - len(b), nil } // Append appends an ACK frame. @@ -163,7 +172,7 @@ func (f *AckFrame) Length(_ protocol.Version) protocol.ByteCount { length += quicvarint.Len(f.ECT1) length += quicvarint.Len(f.ECNCE) } - return length + return protocol.ByteCount(length) } // gets the number of ACK ranges that can be encoded @@ -174,7 +183,7 @@ func (f *AckFrame) numEncodableAckRanges() int { for i := 1; i < len(f.AckRanges); i++ { gap, len := f.encodeAckRange(i) rangeLen := quicvarint.Len(gap) + quicvarint.Len(len) - if length+rangeLen > protocol.MaxAckFrameSize { + if protocol.ByteCount(length+rangeLen) > protocol.MaxAckFrameSize { // Writing range i would exceed the MaxAckFrameSize. // So encode one range less than that. return i - 1 diff --git a/vendor/github.com/quic-go/quic-go/internal/wire/connection_close_frame.go b/vendor/github.com/quic-go/quic-go/internal/wire/connection_close_frame.go index df3624474..be11a1b2e 100644 --- a/vendor/github.com/quic-go/quic-go/internal/wire/connection_close_frame.go +++ b/vendor/github.com/quic-go/quic-go/internal/wire/connection_close_frame.go @@ -1,7 +1,6 @@ package wire import ( - "bytes" "io" "github.com/quic-go/quic-go/internal/protocol" @@ -16,47 +15,45 @@ type ConnectionCloseFrame struct { ReasonPhrase string } -func parseConnectionCloseFrame(r *bytes.Reader, typ uint64, _ protocol.Version) (*ConnectionCloseFrame, error) { +func parseConnectionCloseFrame(b []byte, typ uint64, _ protocol.Version) (*ConnectionCloseFrame, int, error) { + startLen := len(b) f := &ConnectionCloseFrame{IsApplicationError: typ == applicationCloseFrameType} - ec, err := quicvarint.Read(r) + ec, l, err := quicvarint.Parse(b) if err != nil { - return nil, err + return nil, 0, replaceUnexpectedEOF(err) } + b = b[l:] f.ErrorCode = ec // read the Frame Type, if this is not an application error if !f.IsApplicationError { - ft, err := quicvarint.Read(r) + ft, l, err := quicvarint.Parse(b) if err != nil { - return nil, err + return nil, 0, replaceUnexpectedEOF(err) } + b = b[l:] f.FrameType = ft } var reasonPhraseLen uint64 - reasonPhraseLen, err = quicvarint.Read(r) + reasonPhraseLen, l, err = quicvarint.Parse(b) if err != nil { - return nil, err + return nil, 0, replaceUnexpectedEOF(err) } - // shortcut to prevent the unnecessary allocation of dataLen bytes - // if the dataLen is larger than the remaining length of the packet - // reading the whole reason phrase would result in EOF when attempting to READ - if int(reasonPhraseLen) > r.Len() { - return nil, io.EOF + b = b[l:] + if int(reasonPhraseLen) > len(b) { + return nil, 0, io.EOF } reasonPhrase := make([]byte, reasonPhraseLen) - if _, err := io.ReadFull(r, reasonPhrase); err != nil { - // this should never happen, since we already checked the reasonPhraseLen earlier - return nil, err - } + copy(reasonPhrase, b) f.ReasonPhrase = string(reasonPhrase) - return f, nil + return f, startLen - len(b) + int(reasonPhraseLen), nil } // Length of a written frame func (f *ConnectionCloseFrame) Length(protocol.Version) protocol.ByteCount { - length := 1 + quicvarint.Len(f.ErrorCode) + quicvarint.Len(uint64(len(f.ReasonPhrase))) + protocol.ByteCount(len(f.ReasonPhrase)) + length := 1 + protocol.ByteCount(quicvarint.Len(f.ErrorCode)+quicvarint.Len(uint64(len(f.ReasonPhrase)))) + protocol.ByteCount(len(f.ReasonPhrase)) if !f.IsApplicationError { - length += quicvarint.Len(f.FrameType) // for the frame type + length += protocol.ByteCount(quicvarint.Len(f.FrameType)) // for the frame type } return length } diff --git a/vendor/github.com/quic-go/quic-go/internal/wire/crypto_frame.go b/vendor/github.com/quic-go/quic-go/internal/wire/crypto_frame.go index d42146391..0aa7fe7bc 100644 --- a/vendor/github.com/quic-go/quic-go/internal/wire/crypto_frame.go +++ b/vendor/github.com/quic-go/quic-go/internal/wire/crypto_frame.go @@ -1,7 +1,6 @@ package wire import ( - "bytes" "io" "github.com/quic-go/quic-go/internal/protocol" @@ -14,28 +13,28 @@ type CryptoFrame struct { Data []byte } -func parseCryptoFrame(r *bytes.Reader, _ protocol.Version) (*CryptoFrame, error) { +func parseCryptoFrame(b []byte, _ protocol.Version) (*CryptoFrame, int, error) { + startLen := len(b) frame := &CryptoFrame{} - offset, err := quicvarint.Read(r) + offset, l, err := quicvarint.Parse(b) if err != nil { - return nil, err + return nil, 0, replaceUnexpectedEOF(err) } + b = b[l:] frame.Offset = protocol.ByteCount(offset) - dataLen, err := quicvarint.Read(r) + dataLen, l, err := quicvarint.Parse(b) if err != nil { - return nil, err + return nil, 0, replaceUnexpectedEOF(err) } - if dataLen > uint64(r.Len()) { - return nil, io.EOF + b = b[l:] + if dataLen > uint64(len(b)) { + return nil, 0, io.EOF } if dataLen != 0 { frame.Data = make([]byte, dataLen) - if _, err := io.ReadFull(r, frame.Data); err != nil { - // this should never happen, since we already checked the dataLen earlier - return nil, err - } + copy(frame.Data, b) } - return frame, nil + return frame, startLen - len(b) + int(dataLen), nil } func (f *CryptoFrame) Append(b []byte, _ protocol.Version) ([]byte, error) { @@ -48,14 +47,14 @@ func (f *CryptoFrame) Append(b []byte, _ protocol.Version) ([]byte, error) { // Length of a written frame func (f *CryptoFrame) Length(_ protocol.Version) protocol.ByteCount { - return 1 + quicvarint.Len(uint64(f.Offset)) + quicvarint.Len(uint64(len(f.Data))) + protocol.ByteCount(len(f.Data)) + return protocol.ByteCount(1 + quicvarint.Len(uint64(f.Offset)) + quicvarint.Len(uint64(len(f.Data))) + len(f.Data)) } // MaxDataLen returns the maximum data length func (f *CryptoFrame) MaxDataLen(maxSize protocol.ByteCount) protocol.ByteCount { // pretend that the data size will be 1 bytes // if it turns out that varint encoding the length will consume 2 bytes, we need to adjust the data length afterwards - headerLen := 1 + quicvarint.Len(uint64(f.Offset)) + 1 + headerLen := protocol.ByteCount(1 + quicvarint.Len(uint64(f.Offset)) + 1) if headerLen > maxSize { return 0 } diff --git a/vendor/github.com/quic-go/quic-go/internal/wire/data_blocked_frame.go b/vendor/github.com/quic-go/quic-go/internal/wire/data_blocked_frame.go index 8fe2acb54..c97d4c629 100644 --- a/vendor/github.com/quic-go/quic-go/internal/wire/data_blocked_frame.go +++ b/vendor/github.com/quic-go/quic-go/internal/wire/data_blocked_frame.go @@ -1,8 +1,6 @@ package wire import ( - "bytes" - "github.com/quic-go/quic-go/internal/protocol" "github.com/quic-go/quic-go/quicvarint" ) @@ -12,12 +10,12 @@ type DataBlockedFrame struct { MaximumData protocol.ByteCount } -func parseDataBlockedFrame(r *bytes.Reader, _ protocol.Version) (*DataBlockedFrame, error) { - offset, err := quicvarint.Read(r) +func parseDataBlockedFrame(b []byte, _ protocol.Version) (*DataBlockedFrame, int, error) { + offset, l, err := quicvarint.Parse(b) if err != nil { - return nil, err + return nil, 0, replaceUnexpectedEOF(err) } - return &DataBlockedFrame{MaximumData: protocol.ByteCount(offset)}, nil + return &DataBlockedFrame{MaximumData: protocol.ByteCount(offset)}, l, nil } func (f *DataBlockedFrame) Append(b []byte, version protocol.Version) ([]byte, error) { @@ -27,5 +25,5 @@ func (f *DataBlockedFrame) Append(b []byte, version protocol.Version) ([]byte, e // Length of a written frame func (f *DataBlockedFrame) Length(version protocol.Version) protocol.ByteCount { - return 1 + quicvarint.Len(uint64(f.MaximumData)) + return 1 + protocol.ByteCount(quicvarint.Len(uint64(f.MaximumData))) } diff --git a/vendor/github.com/quic-go/quic-go/internal/wire/datagram_frame.go b/vendor/github.com/quic-go/quic-go/internal/wire/datagram_frame.go index 8e406f1ad..071fda9a0 100644 --- a/vendor/github.com/quic-go/quic-go/internal/wire/datagram_frame.go +++ b/vendor/github.com/quic-go/quic-go/internal/wire/datagram_frame.go @@ -1,7 +1,6 @@ package wire import ( - "bytes" "io" "github.com/quic-go/quic-go/internal/protocol" @@ -20,29 +19,29 @@ type DatagramFrame struct { Data []byte } -func parseDatagramFrame(r *bytes.Reader, typ uint64, _ protocol.Version) (*DatagramFrame, error) { +func parseDatagramFrame(b []byte, typ uint64, _ protocol.Version) (*DatagramFrame, int, error) { + startLen := len(b) f := &DatagramFrame{} f.DataLenPresent = typ&0x1 > 0 var length uint64 if f.DataLenPresent { var err error - len, err := quicvarint.Read(r) + var l int + length, l, err = quicvarint.Parse(b) if err != nil { - return nil, err + return nil, 0, replaceUnexpectedEOF(err) } - if len > uint64(r.Len()) { - return nil, io.EOF + b = b[l:] + if length > uint64(len(b)) { + return nil, 0, io.EOF } - length = len } else { - length = uint64(r.Len()) + length = uint64(len(b)) } f.Data = make([]byte, length) - if _, err := io.ReadFull(r, f.Data); err != nil { - return nil, err - } - return f, nil + copy(f.Data, b) + return f, startLen - len(b) + int(length), nil } func (f *DatagramFrame) Append(b []byte, _ protocol.Version) ([]byte, error) { @@ -80,7 +79,7 @@ func (f *DatagramFrame) MaxDataLen(maxSize protocol.ByteCount, version protocol. func (f *DatagramFrame) Length(_ protocol.Version) protocol.ByteCount { length := 1 + protocol.ByteCount(len(f.Data)) if f.DataLenPresent { - length += quicvarint.Len(uint64(len(f.Data))) + length += protocol.ByteCount(quicvarint.Len(uint64(len(f.Data)))) } return length } diff --git a/vendor/github.com/quic-go/quic-go/internal/wire/extended_header.go b/vendor/github.com/quic-go/quic-go/internal/wire/extended_header.go index e04d91b78..1c6ad991d 100644 --- a/vendor/github.com/quic-go/quic-go/internal/wire/extended_header.go +++ b/vendor/github.com/quic-go/quic-go/internal/wire/extended_header.go @@ -1,7 +1,6 @@ package wire import ( - "bytes" "encoding/binary" "errors" "fmt" @@ -32,66 +31,23 @@ type ExtendedHeader struct { parsedLen protocol.ByteCount } -func (h *ExtendedHeader) parse(b *bytes.Reader, v protocol.Version) (bool /* reserved bits valid */, error) { - startLen := b.Len() +func (h *ExtendedHeader) parse(data []byte) (bool /* reserved bits valid */, error) { // read the (now unencrypted) first byte - var err error - h.typeByte, err = b.ReadByte() - if err != nil { - return false, err - } - if _, err := b.Seek(int64(h.Header.ParsedLen())-1, io.SeekCurrent); err != nil { - return false, err - } - reservedBitsValid, err := h.parseLongHeader(b, v) - if err != nil { - return false, err + h.typeByte = data[0] + h.PacketNumberLen = protocol.PacketNumberLen(h.typeByte&0x3) + 1 + if protocol.ByteCount(len(data)) < h.Header.ParsedLen()+protocol.ByteCount(h.PacketNumberLen) { + return false, io.EOF } - h.parsedLen = protocol.ByteCount(startLen - b.Len()) - return reservedBitsValid, err -} -func (h *ExtendedHeader) parseLongHeader(b *bytes.Reader, _ protocol.Version) (bool /* reserved bits valid */, error) { - if err := h.readPacketNumber(b); err != nil { - return false, err - } - if h.typeByte&0xc != 0 { - return false, nil + pn, err := readPacketNumber(data[h.Header.ParsedLen():], h.PacketNumberLen) + if err != nil { + return true, nil } - return true, nil -} + h.PacketNumber = pn + reservedBitsValid := h.typeByte&0xc == 0 -func (h *ExtendedHeader) readPacketNumber(b *bytes.Reader) error { - h.PacketNumberLen = protocol.PacketNumberLen(h.typeByte&0x3) + 1 - switch h.PacketNumberLen { - case protocol.PacketNumberLen1: - n, err := b.ReadByte() - if err != nil { - return err - } - h.PacketNumber = protocol.PacketNumber(n) - case protocol.PacketNumberLen2: - n, err := utils.BigEndian.ReadUint16(b) - if err != nil { - return err - } - h.PacketNumber = protocol.PacketNumber(n) - case protocol.PacketNumberLen3: - n, err := utils.BigEndian.ReadUint24(b) - if err != nil { - return err - } - h.PacketNumber = protocol.PacketNumber(n) - case protocol.PacketNumberLen4: - n, err := utils.BigEndian.ReadUint32(b) - if err != nil { - return err - } - h.PacketNumber = protocol.PacketNumber(n) - default: - return fmt.Errorf("invalid packet number length: %d", h.PacketNumberLen) - } - return nil + h.parsedLen = h.Header.ParsedLen() + protocol.ByteCount(h.PacketNumberLen) + return reservedBitsValid, err } // Append appends the Header. @@ -165,7 +121,7 @@ func (h *ExtendedHeader) ParsedLen() protocol.ByteCount { func (h *ExtendedHeader) GetLength(_ protocol.Version) protocol.ByteCount { length := 1 /* type byte */ + 4 /* version */ + 1 /* dest conn ID len */ + protocol.ByteCount(h.DestConnectionID.Len()) + 1 /* src conn ID len */ + protocol.ByteCount(h.SrcConnectionID.Len()) + protocol.ByteCount(h.PacketNumberLen) + 2 /* length */ if h.Type == protocol.PacketTypeInitial { - length += quicvarint.Len(uint64(len(h.Token))) + protocol.ByteCount(len(h.Token)) + length += protocol.ByteCount(quicvarint.Len(uint64(len(h.Token))) + len(h.Token)) } return length } diff --git a/vendor/github.com/quic-go/quic-go/internal/wire/frame_parser.go b/vendor/github.com/quic-go/quic-go/internal/wire/frame_parser.go index cf7d4cecd..59d41444a 100644 --- a/vendor/github.com/quic-go/quic-go/internal/wire/frame_parser.go +++ b/vendor/github.com/quic-go/quic-go/internal/wire/frame_parser.go @@ -1,9 +1,9 @@ package wire import ( - "bytes" "errors" "fmt" + "io" "reflect" "github.com/quic-go/quic-go/internal/protocol" @@ -38,8 +38,6 @@ const ( // The FrameParser parses QUIC frames, one by one. type FrameParser struct { - r bytes.Reader // cached bytes.Reader, so we don't have to repeatedly allocate them - ackDelayExponent uint8 supportsDatagrams bool @@ -51,7 +49,6 @@ type FrameParser struct { // NewFrameParser creates a new frame parser. func NewFrameParser(supportsDatagrams bool) *FrameParser { return &FrameParser{ - r: *bytes.NewReader(nil), supportsDatagrams: supportsDatagrams, ackFrame: &AckFrame{}, } @@ -60,45 +57,46 @@ func NewFrameParser(supportsDatagrams bool) *FrameParser { // ParseNext parses the next frame. // It skips PADDING frames. func (p *FrameParser) ParseNext(data []byte, encLevel protocol.EncryptionLevel, v protocol.Version) (int, Frame, error) { - startLen := len(data) - p.r.Reset(data) - frame, err := p.parseNext(&p.r, encLevel, v) - n := startLen - p.r.Len() - p.r.Reset(nil) - return n, frame, err + frame, l, err := p.parseNext(data, encLevel, v) + return l, frame, err } -func (p *FrameParser) parseNext(r *bytes.Reader, encLevel protocol.EncryptionLevel, v protocol.Version) (Frame, error) { - for r.Len() != 0 { - typ, err := quicvarint.Read(r) +func (p *FrameParser) parseNext(b []byte, encLevel protocol.EncryptionLevel, v protocol.Version) (Frame, int, error) { + var parsed int + for len(b) != 0 { + typ, l, err := quicvarint.Parse(b) + parsed += l if err != nil { - return nil, &qerr.TransportError{ + return nil, parsed, &qerr.TransportError{ ErrorCode: qerr.FrameEncodingError, ErrorMessage: err.Error(), } } + b = b[l:] if typ == 0x0 { // skip PADDING frames continue } - f, err := p.parseFrame(r, typ, encLevel, v) + f, l, err := p.parseFrame(b, typ, encLevel, v) + parsed += l if err != nil { - return nil, &qerr.TransportError{ + return nil, parsed, &qerr.TransportError{ FrameType: typ, ErrorCode: qerr.FrameEncodingError, ErrorMessage: err.Error(), } } - return f, nil + return f, parsed, nil } - return nil, nil + return nil, parsed, nil } -func (p *FrameParser) parseFrame(r *bytes.Reader, typ uint64, encLevel protocol.EncryptionLevel, v protocol.Version) (Frame, error) { +func (p *FrameParser) parseFrame(b []byte, typ uint64, encLevel protocol.EncryptionLevel, v protocol.Version) (Frame, int, error) { var frame Frame var err error + var l int if typ&0xf8 == 0x8 { - frame, err = parseStreamFrame(r, typ, v) + frame, l, err = parseStreamFrame(b, typ, v) } else { switch typ { case pingFrameType: @@ -109,43 +107,43 @@ func (p *FrameParser) parseFrame(r *bytes.Reader, typ uint64, encLevel protocol. ackDelayExponent = protocol.DefaultAckDelayExponent } p.ackFrame.Reset() - err = parseAckFrame(p.ackFrame, r, typ, ackDelayExponent, v) + l, err = parseAckFrame(p.ackFrame, b, typ, ackDelayExponent, v) frame = p.ackFrame case resetStreamFrameType: - frame, err = parseResetStreamFrame(r, v) + frame, l, err = parseResetStreamFrame(b, v) case stopSendingFrameType: - frame, err = parseStopSendingFrame(r, v) + frame, l, err = parseStopSendingFrame(b, v) case cryptoFrameType: - frame, err = parseCryptoFrame(r, v) + frame, l, err = parseCryptoFrame(b, v) case newTokenFrameType: - frame, err = parseNewTokenFrame(r, v) + frame, l, err = parseNewTokenFrame(b, v) case maxDataFrameType: - frame, err = parseMaxDataFrame(r, v) + frame, l, err = parseMaxDataFrame(b, v) case maxStreamDataFrameType: - frame, err = parseMaxStreamDataFrame(r, v) + frame, l, err = parseMaxStreamDataFrame(b, v) case bidiMaxStreamsFrameType, uniMaxStreamsFrameType: - frame, err = parseMaxStreamsFrame(r, typ, v) + frame, l, err = parseMaxStreamsFrame(b, typ, v) case dataBlockedFrameType: - frame, err = parseDataBlockedFrame(r, v) + frame, l, err = parseDataBlockedFrame(b, v) case streamDataBlockedFrameType: - frame, err = parseStreamDataBlockedFrame(r, v) + frame, l, err = parseStreamDataBlockedFrame(b, v) case bidiStreamBlockedFrameType, uniStreamBlockedFrameType: - frame, err = parseStreamsBlockedFrame(r, typ, v) + frame, l, err = parseStreamsBlockedFrame(b, typ, v) case newConnectionIDFrameType: - frame, err = parseNewConnectionIDFrame(r, v) + frame, l, err = parseNewConnectionIDFrame(b, v) case retireConnectionIDFrameType: - frame, err = parseRetireConnectionIDFrame(r, v) + frame, l, err = parseRetireConnectionIDFrame(b, v) case pathChallengeFrameType: - frame, err = parsePathChallengeFrame(r, v) + frame, l, err = parsePathChallengeFrame(b, v) case pathResponseFrameType: - frame, err = parsePathResponseFrame(r, v) + frame, l, err = parsePathResponseFrame(b, v) case connectionCloseFrameType, applicationCloseFrameType: - frame, err = parseConnectionCloseFrame(r, typ, v) + frame, l, err = parseConnectionCloseFrame(b, typ, v) case handshakeDoneFrameType: frame = &HandshakeDoneFrame{} case 0x30, 0x31: if p.supportsDatagrams { - frame, err = parseDatagramFrame(r, typ, v) + frame, l, err = parseDatagramFrame(b, typ, v) break } fallthrough @@ -154,12 +152,12 @@ func (p *FrameParser) parseFrame(r *bytes.Reader, typ uint64, encLevel protocol. } } if err != nil { - return nil, err + return nil, 0, err } if !p.isAllowedAtEncLevel(frame, encLevel) { - return nil, fmt.Errorf("%s not allowed at encryption level %s", reflect.TypeOf(frame).Elem().Name(), encLevel) + return nil, l, fmt.Errorf("%s not allowed at encryption level %s", reflect.TypeOf(frame).Elem().Name(), encLevel) } - return frame, nil + return frame, l, nil } func (p *FrameParser) isAllowedAtEncLevel(f Frame, encLevel protocol.EncryptionLevel) bool { @@ -190,3 +188,10 @@ func (p *FrameParser) isAllowedAtEncLevel(f Frame, encLevel protocol.EncryptionL func (p *FrameParser) SetAckDelayExponent(exp uint8) { p.ackDelayExponent = exp } + +func replaceUnexpectedEOF(e error) error { + if e == io.ErrUnexpectedEOF { + return io.EOF + } + return e +} diff --git a/vendor/github.com/quic-go/quic-go/internal/wire/header.go b/vendor/github.com/quic-go/quic-go/internal/wire/header.go index 299116849..678a04a24 100644 --- a/vendor/github.com/quic-go/quic-go/internal/wire/header.go +++ b/vendor/github.com/quic-go/quic-go/internal/wire/header.go @@ -1,14 +1,12 @@ package wire import ( - "bytes" "encoding/binary" "errors" "fmt" "io" "github.com/quic-go/quic-go/internal/protocol" - "github.com/quic-go/quic-go/internal/utils" "github.com/quic-go/quic-go/quicvarint" ) @@ -41,37 +39,27 @@ func ParseConnectionID(data []byte, shortHeaderConnIDLen int) (protocol.Connecti // https://datatracker.ietf.org/doc/html/rfc8999#section-5.1. // This function should only be called on Long Header packets for which we don't support the version. func ParseArbitraryLenConnectionIDs(data []byte) (bytesParsed int, dest, src protocol.ArbitraryLenConnectionID, _ error) { - r := bytes.NewReader(data) - remaining := r.Len() - src, dest, err := parseArbitraryLenConnectionIDs(r) - return remaining - r.Len(), src, dest, err -} - -func parseArbitraryLenConnectionIDs(r *bytes.Reader) (dest, src protocol.ArbitraryLenConnectionID, _ error) { - r.Seek(5, io.SeekStart) // skip first byte and version field - destConnIDLen, err := r.ReadByte() - if err != nil { - return nil, nil, err + startLen := len(data) + if len(data) < 6 { + return 0, nil, nil, io.EOF } + data = data[5:] // skip first byte and version field + destConnIDLen := data[0] + data = data[1:] destConnID := make(protocol.ArbitraryLenConnectionID, destConnIDLen) - if _, err := io.ReadFull(r, destConnID); err != nil { - if err == io.ErrUnexpectedEOF { - err = io.EOF - } - return nil, nil, err + if len(data) < int(destConnIDLen)+1 { + return 0, nil, nil, io.EOF } - srcConnIDLen, err := r.ReadByte() - if err != nil { - return nil, nil, err + copy(destConnID, data) + data = data[destConnIDLen:] + srcConnIDLen := data[0] + data = data[1:] + if len(data) < int(srcConnIDLen) { + return 0, nil, nil, io.EOF } srcConnID := make(protocol.ArbitraryLenConnectionID, srcConnIDLen) - if _, err := io.ReadFull(r, srcConnID); err != nil { - if err == io.ErrUnexpectedEOF { - err = io.EOF - } - return nil, nil, err - } - return destConnID, srcConnID, nil + copy(srcConnID, data) + return startLen - len(data) + int(srcConnIDLen), destConnID, srcConnID, nil } func IsPotentialQUICPacket(firstByte byte) bool { @@ -139,18 +127,18 @@ type Header struct { parsedLen protocol.ByteCount // how many bytes were read while parsing this header } -// ParsePacket parses a packet. -// If the packet has a long header, the packet is cut according to the length field. -// If we understand the version, the packet is header up unto the packet number. +// ParsePacket parses a long header packet. +// The packet is cut according to the length field. +// If we understand the version, the packet is parsed up unto the packet number. // Otherwise, only the invariant part of the header is parsed. func ParsePacket(data []byte) (*Header, []byte, []byte, error) { if len(data) == 0 || !IsLongHeaderPacket(data[0]) { return nil, nil, nil, errors.New("not a long header packet") } - hdr, err := parseHeader(bytes.NewReader(data)) + hdr, err := parseHeader(data) if err != nil { - if err == ErrUnsupportedVersion { - return hdr, nil, nil, ErrUnsupportedVersion + if errors.Is(err, ErrUnsupportedVersion) { + return hdr, nil, nil, err } return nil, nil, nil, err } @@ -161,55 +149,55 @@ func ParsePacket(data []byte) (*Header, []byte, []byte, error) { return hdr, data[:packetLen], data[packetLen:], nil } -// ParseHeader parses the header. -// For short header packets: up to the packet number. -// For long header packets: +// ParseHeader parses the header: // * if we understand the version: up to the packet number // * if not, only the invariant part of the header -func parseHeader(b *bytes.Reader) (*Header, error) { - startLen := b.Len() - typeByte, err := b.ReadByte() - if err != nil { - return nil, err +func parseHeader(b []byte) (*Header, error) { + if len(b) == 0 { + return nil, io.EOF } + typeByte := b[0] h := &Header{typeByte: typeByte} - err = h.parseLongHeader(b) - h.parsedLen = protocol.ByteCount(startLen - b.Len()) + l, err := h.parseLongHeader(b[1:]) + h.parsedLen = protocol.ByteCount(l) + 1 return h, err } -func (h *Header) parseLongHeader(b *bytes.Reader) error { - v, err := utils.BigEndian.ReadUint32(b) - if err != nil { - return err +func (h *Header) parseLongHeader(b []byte) (int, error) { + startLen := len(b) + if len(b) < 5 { + return 0, io.EOF } - h.Version = protocol.Version(v) + h.Version = protocol.Version(binary.BigEndian.Uint32(b[:4])) if h.Version != 0 && h.typeByte&0x40 == 0 { - return errors.New("not a QUIC packet") + return startLen - len(b), errors.New("not a QUIC packet") } - destConnIDLen, err := b.ReadByte() - if err != nil { - return err + destConnIDLen := int(b[4]) + if destConnIDLen > protocol.MaxConnIDLen { + return startLen - len(b), protocol.ErrInvalidConnectionIDLen } - h.DestConnectionID, err = protocol.ReadConnectionID(b, int(destConnIDLen)) - if err != nil { - return err + b = b[5:] + if len(b) < destConnIDLen+1 { + return startLen - len(b), io.EOF } - srcConnIDLen, err := b.ReadByte() - if err != nil { - return err + h.DestConnectionID = protocol.ParseConnectionID(b[:destConnIDLen]) + srcConnIDLen := int(b[destConnIDLen]) + if srcConnIDLen > protocol.MaxConnIDLen { + return startLen - len(b), protocol.ErrInvalidConnectionIDLen } - h.SrcConnectionID, err = protocol.ReadConnectionID(b, int(srcConnIDLen)) - if err != nil { - return err + b = b[destConnIDLen+1:] + if len(b) < srcConnIDLen { + return startLen - len(b), io.EOF } + h.SrcConnectionID = protocol.ParseConnectionID(b[:srcConnIDLen]) + b = b[srcConnIDLen:] if h.Version == 0 { // version negotiation packet - return nil + return startLen - len(b), nil } // If we don't understand the version, we have no idea how to interpret the rest of the bytes if !protocol.IsSupportedVersion(protocol.SupportedVersions, h.Version) { - return ErrUnsupportedVersion + return startLen - len(b), ErrUnsupportedVersion } if h.Version == protocol.Version2 { @@ -237,38 +225,35 @@ func (h *Header) parseLongHeader(b *bytes.Reader) error { } if h.Type == protocol.PacketTypeRetry { - tokenLen := b.Len() - 16 + tokenLen := len(b) - 16 if tokenLen <= 0 { - return io.EOF + return startLen - len(b), io.EOF } h.Token = make([]byte, tokenLen) - if _, err := io.ReadFull(b, h.Token); err != nil { - return err - } - _, err := b.Seek(16, io.SeekCurrent) - return err + copy(h.Token, b[:tokenLen]) + return startLen - len(b) + tokenLen + 16, nil } if h.Type == protocol.PacketTypeInitial { - tokenLen, err := quicvarint.Read(b) + tokenLen, n, err := quicvarint.Parse(b) if err != nil { - return err + return startLen - len(b), err } - if tokenLen > uint64(b.Len()) { - return io.EOF + b = b[n:] + if tokenLen > uint64(len(b)) { + return startLen - len(b), io.EOF } h.Token = make([]byte, tokenLen) - if _, err := io.ReadFull(b, h.Token); err != nil { - return err - } + copy(h.Token, b[:tokenLen]) + b = b[tokenLen:] } - pl, err := quicvarint.Read(b) + pl, n, err := quicvarint.Parse(b) if err != nil { - return err + return 0, err } h.Length = protocol.ByteCount(pl) - return nil + return startLen - len(b) + n, nil } // ParsedLen returns the number of bytes that were consumed when parsing the header @@ -278,9 +263,9 @@ func (h *Header) ParsedLen() protocol.ByteCount { // ParseExtended parses the version dependent part of the header. // The Reader has to be set such that it points to the first byte of the header. -func (h *Header) ParseExtended(b *bytes.Reader, ver protocol.Version) (*ExtendedHeader, error) { +func (h *Header) ParseExtended(data []byte) (*ExtendedHeader, error) { extHdr := h.toExtendedHeader() - reservedBitsValid, err := extHdr.parse(b, ver) + reservedBitsValid, err := extHdr.parse(data) if err != nil { return nil, err } @@ -298,3 +283,20 @@ func (h *Header) toExtendedHeader() *ExtendedHeader { func (h *Header) PacketType() string { return h.Type.String() } + +func readPacketNumber(data []byte, pnLen protocol.PacketNumberLen) (protocol.PacketNumber, error) { + var pn protocol.PacketNumber + switch pnLen { + case protocol.PacketNumberLen1: + pn = protocol.PacketNumber(data[0]) + case protocol.PacketNumberLen2: + pn = protocol.PacketNumber(binary.BigEndian.Uint16(data[:2])) + case protocol.PacketNumberLen3: + pn = protocol.PacketNumber(uint32(data[2]) + uint32(data[1])<<8 + uint32(data[0])<<16) + case protocol.PacketNumberLen4: + pn = protocol.PacketNumber(binary.BigEndian.Uint32(data[:4])) + default: + return 0, fmt.Errorf("invalid packet number length: %d", pnLen) + } + return pn, nil +} diff --git a/vendor/github.com/quic-go/quic-go/internal/wire/max_data_frame.go b/vendor/github.com/quic-go/quic-go/internal/wire/max_data_frame.go index 3dfd76116..5819c0273 100644 --- a/vendor/github.com/quic-go/quic-go/internal/wire/max_data_frame.go +++ b/vendor/github.com/quic-go/quic-go/internal/wire/max_data_frame.go @@ -1,8 +1,6 @@ package wire import ( - "bytes" - "github.com/quic-go/quic-go/internal/protocol" "github.com/quic-go/quic-go/quicvarint" ) @@ -13,14 +11,14 @@ type MaxDataFrame struct { } // parseMaxDataFrame parses a MAX_DATA frame -func parseMaxDataFrame(r *bytes.Reader, _ protocol.Version) (*MaxDataFrame, error) { +func parseMaxDataFrame(b []byte, _ protocol.Version) (*MaxDataFrame, int, error) { frame := &MaxDataFrame{} - byteOffset, err := quicvarint.Read(r) + byteOffset, l, err := quicvarint.Parse(b) if err != nil { - return nil, err + return nil, 0, replaceUnexpectedEOF(err) } frame.MaximumData = protocol.ByteCount(byteOffset) - return frame, nil + return frame, l, nil } func (f *MaxDataFrame) Append(b []byte, _ protocol.Version) ([]byte, error) { @@ -31,5 +29,5 @@ func (f *MaxDataFrame) Append(b []byte, _ protocol.Version) ([]byte, error) { // Length of a written frame func (f *MaxDataFrame) Length(_ protocol.Version) protocol.ByteCount { - return 1 + quicvarint.Len(uint64(f.MaximumData)) + return 1 + protocol.ByteCount(quicvarint.Len(uint64(f.MaximumData))) } diff --git a/vendor/github.com/quic-go/quic-go/internal/wire/max_stream_data_frame.go b/vendor/github.com/quic-go/quic-go/internal/wire/max_stream_data_frame.go index cb5eab1b0..db9091af8 100644 --- a/vendor/github.com/quic-go/quic-go/internal/wire/max_stream_data_frame.go +++ b/vendor/github.com/quic-go/quic-go/internal/wire/max_stream_data_frame.go @@ -1,8 +1,6 @@ package wire import ( - "bytes" - "github.com/quic-go/quic-go/internal/protocol" "github.com/quic-go/quic-go/quicvarint" ) @@ -13,23 +11,26 @@ type MaxStreamDataFrame struct { MaximumStreamData protocol.ByteCount } -func parseMaxStreamDataFrame(r *bytes.Reader, _ protocol.Version) (*MaxStreamDataFrame, error) { - sid, err := quicvarint.Read(r) +func parseMaxStreamDataFrame(b []byte, _ protocol.Version) (*MaxStreamDataFrame, int, error) { + startLen := len(b) + sid, l, err := quicvarint.Parse(b) if err != nil { - return nil, err + return nil, 0, replaceUnexpectedEOF(err) } - offset, err := quicvarint.Read(r) + b = b[l:] + offset, l, err := quicvarint.Parse(b) if err != nil { - return nil, err + return nil, 0, replaceUnexpectedEOF(err) } + b = b[l:] return &MaxStreamDataFrame{ StreamID: protocol.StreamID(sid), MaximumStreamData: protocol.ByteCount(offset), - }, nil + }, startLen - len(b), nil } -func (f *MaxStreamDataFrame) Append(b []byte, version protocol.Version) ([]byte, error) { +func (f *MaxStreamDataFrame) Append(b []byte, _ protocol.Version) ([]byte, error) { b = append(b, maxStreamDataFrameType) b = quicvarint.Append(b, uint64(f.StreamID)) b = quicvarint.Append(b, uint64(f.MaximumStreamData)) @@ -37,6 +38,6 @@ func (f *MaxStreamDataFrame) Append(b []byte, version protocol.Version) ([]byte, } // Length of a written frame -func (f *MaxStreamDataFrame) Length(version protocol.Version) protocol.ByteCount { - return 1 + quicvarint.Len(uint64(f.StreamID)) + quicvarint.Len(uint64(f.MaximumStreamData)) +func (f *MaxStreamDataFrame) Length(protocol.Version) protocol.ByteCount { + return 1 + protocol.ByteCount(quicvarint.Len(uint64(f.StreamID))+quicvarint.Len(uint64(f.MaximumStreamData))) } diff --git a/vendor/github.com/quic-go/quic-go/internal/wire/max_streams_frame.go b/vendor/github.com/quic-go/quic-go/internal/wire/max_streams_frame.go index d90293383..a8745bd12 100644 --- a/vendor/github.com/quic-go/quic-go/internal/wire/max_streams_frame.go +++ b/vendor/github.com/quic-go/quic-go/internal/wire/max_streams_frame.go @@ -1,7 +1,6 @@ package wire import ( - "bytes" "fmt" "github.com/quic-go/quic-go/internal/protocol" @@ -14,7 +13,7 @@ type MaxStreamsFrame struct { MaxStreamNum protocol.StreamNum } -func parseMaxStreamsFrame(r *bytes.Reader, typ uint64, _ protocol.Version) (*MaxStreamsFrame, error) { +func parseMaxStreamsFrame(b []byte, typ uint64, _ protocol.Version) (*MaxStreamsFrame, int, error) { f := &MaxStreamsFrame{} switch typ { case bidiMaxStreamsFrameType: @@ -22,15 +21,15 @@ func parseMaxStreamsFrame(r *bytes.Reader, typ uint64, _ protocol.Version) (*Max case uniMaxStreamsFrameType: f.Type = protocol.StreamTypeUni } - streamID, err := quicvarint.Read(r) + streamID, l, err := quicvarint.Parse(b) if err != nil { - return nil, err + return nil, 0, replaceUnexpectedEOF(err) } f.MaxStreamNum = protocol.StreamNum(streamID) if f.MaxStreamNum > protocol.MaxStreamCount { - return nil, fmt.Errorf("%d exceeds the maximum stream count", f.MaxStreamNum) + return nil, 0, fmt.Errorf("%d exceeds the maximum stream count", f.MaxStreamNum) } - return f, nil + return f, l, nil } func (f *MaxStreamsFrame) Append(b []byte, _ protocol.Version) ([]byte, error) { @@ -46,5 +45,5 @@ func (f *MaxStreamsFrame) Append(b []byte, _ protocol.Version) ([]byte, error) { // Length of a written frame func (f *MaxStreamsFrame) Length(protocol.Version) protocol.ByteCount { - return 1 + quicvarint.Len(uint64(f.MaxStreamNum)) + return 1 + protocol.ByteCount(quicvarint.Len(uint64(f.MaxStreamNum))) } diff --git a/vendor/github.com/quic-go/quic-go/internal/wire/new_connection_id_frame.go b/vendor/github.com/quic-go/quic-go/internal/wire/new_connection_id_frame.go index afae010ad..852d46ef1 100644 --- a/vendor/github.com/quic-go/quic-go/internal/wire/new_connection_id_frame.go +++ b/vendor/github.com/quic-go/quic-go/internal/wire/new_connection_id_frame.go @@ -1,7 +1,6 @@ package wire import ( - "bytes" "errors" "fmt" "io" @@ -18,43 +17,47 @@ type NewConnectionIDFrame struct { StatelessResetToken protocol.StatelessResetToken } -func parseNewConnectionIDFrame(r *bytes.Reader, _ protocol.Version) (*NewConnectionIDFrame, error) { - seq, err := quicvarint.Read(r) +func parseNewConnectionIDFrame(b []byte, _ protocol.Version) (*NewConnectionIDFrame, int, error) { + startLen := len(b) + seq, l, err := quicvarint.Parse(b) if err != nil { - return nil, err + return nil, 0, replaceUnexpectedEOF(err) } - ret, err := quicvarint.Read(r) + b = b[l:] + ret, l, err := quicvarint.Parse(b) if err != nil { - return nil, err + return nil, 0, replaceUnexpectedEOF(err) } + b = b[l:] if ret > seq { //nolint:stylecheck - return nil, fmt.Errorf("Retire Prior To value (%d) larger than Sequence Number (%d)", ret, seq) + return nil, 0, fmt.Errorf("Retire Prior To value (%d) larger than Sequence Number (%d)", ret, seq) } - connIDLen, err := r.ReadByte() - if err != nil { - return nil, err + if len(b) == 0 { + return nil, 0, io.EOF } + connIDLen := int(b[0]) + b = b[1:] if connIDLen == 0 { - return nil, errors.New("invalid zero-length connection ID") + return nil, 0, errors.New("invalid zero-length connection ID") } - connID, err := protocol.ReadConnectionID(r, int(connIDLen)) - if err != nil { - return nil, err + if connIDLen > protocol.MaxConnIDLen { + return nil, 0, protocol.ErrInvalidConnectionIDLen + } + if len(b) < connIDLen { + return nil, 0, io.EOF } frame := &NewConnectionIDFrame{ SequenceNumber: seq, RetirePriorTo: ret, - ConnectionID: connID, + ConnectionID: protocol.ParseConnectionID(b[:connIDLen]), } - if _, err := io.ReadFull(r, frame.StatelessResetToken[:]); err != nil { - if err == io.ErrUnexpectedEOF { - return nil, io.EOF - } - return nil, err + b = b[connIDLen:] + if len(b) < len(frame.StatelessResetToken) { + return nil, 0, io.EOF } - - return frame, nil + copy(frame.StatelessResetToken[:], b) + return frame, startLen - len(b) + len(frame.StatelessResetToken), nil } func (f *NewConnectionIDFrame) Append(b []byte, _ protocol.Version) ([]byte, error) { @@ -73,5 +76,5 @@ func (f *NewConnectionIDFrame) Append(b []byte, _ protocol.Version) ([]byte, err // Length of a written frame func (f *NewConnectionIDFrame) Length(protocol.Version) protocol.ByteCount { - return 1 + quicvarint.Len(f.SequenceNumber) + quicvarint.Len(f.RetirePriorTo) + 1 /* connection ID length */ + protocol.ByteCount(f.ConnectionID.Len()) + 16 + return 1 + protocol.ByteCount(quicvarint.Len(f.SequenceNumber)+quicvarint.Len(f.RetirePriorTo)+1 /* connection ID length */ +f.ConnectionID.Len()) + 16 } diff --git a/vendor/github.com/quic-go/quic-go/internal/wire/new_token_frame.go b/vendor/github.com/quic-go/quic-go/internal/wire/new_token_frame.go index 6a2eac945..f1d4d00fe 100644 --- a/vendor/github.com/quic-go/quic-go/internal/wire/new_token_frame.go +++ b/vendor/github.com/quic-go/quic-go/internal/wire/new_token_frame.go @@ -1,7 +1,6 @@ package wire import ( - "bytes" "errors" "io" @@ -14,22 +13,21 @@ type NewTokenFrame struct { Token []byte } -func parseNewTokenFrame(r *bytes.Reader, _ protocol.Version) (*NewTokenFrame, error) { - tokenLen, err := quicvarint.Read(r) +func parseNewTokenFrame(b []byte, _ protocol.Version) (*NewTokenFrame, int, error) { + tokenLen, l, err := quicvarint.Parse(b) if err != nil { - return nil, err - } - if uint64(r.Len()) < tokenLen { - return nil, io.EOF + return nil, 0, replaceUnexpectedEOF(err) } + b = b[l:] if tokenLen == 0 { - return nil, errors.New("token must not be empty") + return nil, 0, errors.New("token must not be empty") } - token := make([]byte, int(tokenLen)) - if _, err := io.ReadFull(r, token); err != nil { - return nil, err + if uint64(len(b)) < tokenLen { + return nil, 0, io.EOF } - return &NewTokenFrame{Token: token}, nil + token := make([]byte, int(tokenLen)) + copy(token, b) + return &NewTokenFrame{Token: token}, l + int(tokenLen), nil } func (f *NewTokenFrame) Append(b []byte, _ protocol.Version) ([]byte, error) { @@ -41,5 +39,5 @@ func (f *NewTokenFrame) Append(b []byte, _ protocol.Version) ([]byte, error) { // Length of a written frame func (f *NewTokenFrame) Length(protocol.Version) protocol.ByteCount { - return 1 + quicvarint.Len(uint64(len(f.Token))) + protocol.ByteCount(len(f.Token)) + return 1 + protocol.ByteCount(quicvarint.Len(uint64(len(f.Token)))+len(f.Token)) } diff --git a/vendor/github.com/quic-go/quic-go/internal/wire/path_challenge_frame.go b/vendor/github.com/quic-go/quic-go/internal/wire/path_challenge_frame.go index 772041ac6..2aca989fa 100644 --- a/vendor/github.com/quic-go/quic-go/internal/wire/path_challenge_frame.go +++ b/vendor/github.com/quic-go/quic-go/internal/wire/path_challenge_frame.go @@ -1,7 +1,6 @@ package wire import ( - "bytes" "io" "github.com/quic-go/quic-go/internal/protocol" @@ -12,15 +11,13 @@ type PathChallengeFrame struct { Data [8]byte } -func parsePathChallengeFrame(r *bytes.Reader, _ protocol.Version) (*PathChallengeFrame, error) { - frame := &PathChallengeFrame{} - if _, err := io.ReadFull(r, frame.Data[:]); err != nil { - if err == io.ErrUnexpectedEOF { - return nil, io.EOF - } - return nil, err +func parsePathChallengeFrame(b []byte, _ protocol.Version) (*PathChallengeFrame, int, error) { + f := &PathChallengeFrame{} + if len(b) < 8 { + return nil, 0, io.EOF } - return frame, nil + copy(f.Data[:], b) + return f, 8, nil } func (f *PathChallengeFrame) Append(b []byte, _ protocol.Version) ([]byte, error) { diff --git a/vendor/github.com/quic-go/quic-go/internal/wire/path_response_frame.go b/vendor/github.com/quic-go/quic-go/internal/wire/path_response_frame.go index 86bbe619f..76532c852 100644 --- a/vendor/github.com/quic-go/quic-go/internal/wire/path_response_frame.go +++ b/vendor/github.com/quic-go/quic-go/internal/wire/path_response_frame.go @@ -1,7 +1,6 @@ package wire import ( - "bytes" "io" "github.com/quic-go/quic-go/internal/protocol" @@ -12,15 +11,13 @@ type PathResponseFrame struct { Data [8]byte } -func parsePathResponseFrame(r *bytes.Reader, _ protocol.Version) (*PathResponseFrame, error) { - frame := &PathResponseFrame{} - if _, err := io.ReadFull(r, frame.Data[:]); err != nil { - if err == io.ErrUnexpectedEOF { - return nil, io.EOF - } - return nil, err +func parsePathResponseFrame(b []byte, _ protocol.Version) (*PathResponseFrame, int, error) { + f := &PathResponseFrame{} + if len(b) < 8 { + return nil, 0, io.EOF } - return frame, nil + copy(f.Data[:], b) + return f, 8, nil } func (f *PathResponseFrame) Append(b []byte, _ protocol.Version) ([]byte, error) { diff --git a/vendor/github.com/quic-go/quic-go/internal/wire/reset_stream_frame.go b/vendor/github.com/quic-go/quic-go/internal/wire/reset_stream_frame.go index e60f1db12..a20029af2 100644 --- a/vendor/github.com/quic-go/quic-go/internal/wire/reset_stream_frame.go +++ b/vendor/github.com/quic-go/quic-go/internal/wire/reset_stream_frame.go @@ -1,8 +1,6 @@ package wire import ( - "bytes" - "github.com/quic-go/quic-go/internal/protocol" "github.com/quic-go/quic-go/internal/qerr" "github.com/quic-go/quic-go/quicvarint" @@ -15,21 +13,24 @@ type ResetStreamFrame struct { FinalSize protocol.ByteCount } -func parseResetStreamFrame(r *bytes.Reader, _ protocol.Version) (*ResetStreamFrame, error) { +func parseResetStreamFrame(b []byte, _ protocol.Version) (*ResetStreamFrame, int, error) { + startLen := len(b) var streamID protocol.StreamID var byteOffset protocol.ByteCount - sid, err := quicvarint.Read(r) + sid, l, err := quicvarint.Parse(b) if err != nil { - return nil, err + return nil, 0, replaceUnexpectedEOF(err) } + b = b[l:] streamID = protocol.StreamID(sid) - errorCode, err := quicvarint.Read(r) + errorCode, l, err := quicvarint.Parse(b) if err != nil { - return nil, err + return nil, 0, replaceUnexpectedEOF(err) } - bo, err := quicvarint.Read(r) + b = b[l:] + bo, l, err := quicvarint.Parse(b) if err != nil { - return nil, err + return nil, 0, replaceUnexpectedEOF(err) } byteOffset = protocol.ByteCount(bo) @@ -37,7 +38,7 @@ func parseResetStreamFrame(r *bytes.Reader, _ protocol.Version) (*ResetStreamFra StreamID: streamID, ErrorCode: qerr.StreamErrorCode(errorCode), FinalSize: byteOffset, - }, nil + }, startLen - len(b) + l, nil } func (f *ResetStreamFrame) Append(b []byte, _ protocol.Version) ([]byte, error) { @@ -49,6 +50,6 @@ func (f *ResetStreamFrame) Append(b []byte, _ protocol.Version) ([]byte, error) } // Length of a written frame -func (f *ResetStreamFrame) Length(version protocol.Version) protocol.ByteCount { - return 1 + quicvarint.Len(uint64(f.StreamID)) + quicvarint.Len(uint64(f.ErrorCode)) + quicvarint.Len(uint64(f.FinalSize)) +func (f *ResetStreamFrame) Length(protocol.Version) protocol.ByteCount { + return 1 + protocol.ByteCount(quicvarint.Len(uint64(f.StreamID))+quicvarint.Len(uint64(f.ErrorCode))+quicvarint.Len(uint64(f.FinalSize))) } diff --git a/vendor/github.com/quic-go/quic-go/internal/wire/retire_connection_id_frame.go b/vendor/github.com/quic-go/quic-go/internal/wire/retire_connection_id_frame.go index 981536224..27aeff842 100644 --- a/vendor/github.com/quic-go/quic-go/internal/wire/retire_connection_id_frame.go +++ b/vendor/github.com/quic-go/quic-go/internal/wire/retire_connection_id_frame.go @@ -1,8 +1,6 @@ package wire import ( - "bytes" - "github.com/quic-go/quic-go/internal/protocol" "github.com/quic-go/quic-go/quicvarint" ) @@ -12,12 +10,12 @@ type RetireConnectionIDFrame struct { SequenceNumber uint64 } -func parseRetireConnectionIDFrame(r *bytes.Reader, _ protocol.Version) (*RetireConnectionIDFrame, error) { - seq, err := quicvarint.Read(r) +func parseRetireConnectionIDFrame(b []byte, _ protocol.Version) (*RetireConnectionIDFrame, int, error) { + seq, l, err := quicvarint.Parse(b) if err != nil { - return nil, err + return nil, 0, replaceUnexpectedEOF(err) } - return &RetireConnectionIDFrame{SequenceNumber: seq}, nil + return &RetireConnectionIDFrame{SequenceNumber: seq}, l, nil } func (f *RetireConnectionIDFrame) Append(b []byte, _ protocol.Version) ([]byte, error) { @@ -28,5 +26,5 @@ func (f *RetireConnectionIDFrame) Append(b []byte, _ protocol.Version) ([]byte, // Length of a written frame func (f *RetireConnectionIDFrame) Length(protocol.Version) protocol.ByteCount { - return 1 + quicvarint.Len(f.SequenceNumber) + return 1 + protocol.ByteCount(quicvarint.Len(f.SequenceNumber)) } diff --git a/vendor/github.com/quic-go/quic-go/internal/wire/short_header.go b/vendor/github.com/quic-go/quic-go/internal/wire/short_header.go index 69aa83411..cf2889c58 100644 --- a/vendor/github.com/quic-go/quic-go/internal/wire/short_header.go +++ b/vendor/github.com/quic-go/quic-go/internal/wire/short_header.go @@ -2,7 +2,6 @@ package wire import ( "errors" - "fmt" "io" "github.com/quic-go/quic-go/internal/protocol" @@ -28,25 +27,15 @@ func ParseShortHeader(data []byte, connIDLen int) (length int, _ protocol.Packet } pos := 1 + connIDLen - var pn protocol.PacketNumber - switch pnLen { - case protocol.PacketNumberLen1: - pn = protocol.PacketNumber(data[pos]) - case protocol.PacketNumberLen2: - pn = protocol.PacketNumber(utils.BigEndian.Uint16(data[pos : pos+2])) - case protocol.PacketNumberLen3: - pn = protocol.PacketNumber(utils.BigEndian.Uint24(data[pos : pos+3])) - case protocol.PacketNumberLen4: - pn = protocol.PacketNumber(utils.BigEndian.Uint32(data[pos : pos+4])) - default: - return 0, 0, 0, 0, fmt.Errorf("invalid packet number length: %d", pnLen) + pn, err := readPacketNumber(data[pos:], pnLen) + if err != nil { + return 0, 0, 0, 0, err } kp := protocol.KeyPhaseZero if data[0]&0b100 > 0 { kp = protocol.KeyPhaseOne } - var err error if data[0]&0x18 != 0 { err = ErrInvalidReservedBits } diff --git a/vendor/github.com/quic-go/quic-go/internal/wire/stop_sending_frame.go b/vendor/github.com/quic-go/quic-go/internal/wire/stop_sending_frame.go index d314a5698..a2326f8ec 100644 --- a/vendor/github.com/quic-go/quic-go/internal/wire/stop_sending_frame.go +++ b/vendor/github.com/quic-go/quic-go/internal/wire/stop_sending_frame.go @@ -1,8 +1,6 @@ package wire import ( - "bytes" - "github.com/quic-go/quic-go/internal/protocol" "github.com/quic-go/quic-go/internal/qerr" "github.com/quic-go/quic-go/quicvarint" @@ -15,25 +13,28 @@ type StopSendingFrame struct { } // parseStopSendingFrame parses a STOP_SENDING frame -func parseStopSendingFrame(r *bytes.Reader, _ protocol.Version) (*StopSendingFrame, error) { - streamID, err := quicvarint.Read(r) +func parseStopSendingFrame(b []byte, _ protocol.Version) (*StopSendingFrame, int, error) { + startLen := len(b) + streamID, l, err := quicvarint.Parse(b) if err != nil { - return nil, err + return nil, 0, replaceUnexpectedEOF(err) } - errorCode, err := quicvarint.Read(r) + b = b[l:] + errorCode, l, err := quicvarint.Parse(b) if err != nil { - return nil, err + return nil, 0, replaceUnexpectedEOF(err) } + b = b[l:] return &StopSendingFrame{ StreamID: protocol.StreamID(streamID), ErrorCode: qerr.StreamErrorCode(errorCode), - }, nil + }, startLen - len(b), nil } // Length of a written frame func (f *StopSendingFrame) Length(_ protocol.Version) protocol.ByteCount { - return 1 + quicvarint.Len(uint64(f.StreamID)) + quicvarint.Len(uint64(f.ErrorCode)) + return 1 + protocol.ByteCount(quicvarint.Len(uint64(f.StreamID))+quicvarint.Len(uint64(f.ErrorCode))) } func (f *StopSendingFrame) Append(b []byte, _ protocol.Version) ([]byte, error) { diff --git a/vendor/github.com/quic-go/quic-go/internal/wire/stream_data_blocked_frame.go b/vendor/github.com/quic-go/quic-go/internal/wire/stream_data_blocked_frame.go index f79740f98..3762ec76a 100644 --- a/vendor/github.com/quic-go/quic-go/internal/wire/stream_data_blocked_frame.go +++ b/vendor/github.com/quic-go/quic-go/internal/wire/stream_data_blocked_frame.go @@ -1,8 +1,6 @@ package wire import ( - "bytes" - "github.com/quic-go/quic-go/internal/protocol" "github.com/quic-go/quic-go/quicvarint" ) @@ -13,20 +11,22 @@ type StreamDataBlockedFrame struct { MaximumStreamData protocol.ByteCount } -func parseStreamDataBlockedFrame(r *bytes.Reader, _ protocol.Version) (*StreamDataBlockedFrame, error) { - sid, err := quicvarint.Read(r) +func parseStreamDataBlockedFrame(b []byte, _ protocol.Version) (*StreamDataBlockedFrame, int, error) { + startLen := len(b) + sid, l, err := quicvarint.Parse(b) if err != nil { - return nil, err + return nil, 0, replaceUnexpectedEOF(err) } - offset, err := quicvarint.Read(r) + b = b[l:] + offset, l, err := quicvarint.Parse(b) if err != nil { - return nil, err + return nil, 0, replaceUnexpectedEOF(err) } return &StreamDataBlockedFrame{ StreamID: protocol.StreamID(sid), MaximumStreamData: protocol.ByteCount(offset), - }, nil + }, startLen - len(b) + l, nil } func (f *StreamDataBlockedFrame) Append(b []byte, _ protocol.Version) ([]byte, error) { @@ -37,6 +37,6 @@ func (f *StreamDataBlockedFrame) Append(b []byte, _ protocol.Version) ([]byte, e } // Length of a written frame -func (f *StreamDataBlockedFrame) Length(version protocol.Version) protocol.ByteCount { - return 1 + quicvarint.Len(uint64(f.StreamID)) + quicvarint.Len(uint64(f.MaximumStreamData)) +func (f *StreamDataBlockedFrame) Length(protocol.Version) protocol.ByteCount { + return 1 + protocol.ByteCount(quicvarint.Len(uint64(f.StreamID))+quicvarint.Len(uint64(f.MaximumStreamData))) } diff --git a/vendor/github.com/quic-go/quic-go/internal/wire/stream_frame.go b/vendor/github.com/quic-go/quic-go/internal/wire/stream_frame.go index 0f6c00da2..f9470ecd6 100644 --- a/vendor/github.com/quic-go/quic-go/internal/wire/stream_frame.go +++ b/vendor/github.com/quic-go/quic-go/internal/wire/stream_frame.go @@ -1,7 +1,6 @@ package wire import ( - "bytes" "errors" "io" @@ -20,33 +19,41 @@ type StreamFrame struct { fromPool bool } -func parseStreamFrame(r *bytes.Reader, typ uint64, _ protocol.Version) (*StreamFrame, error) { +func parseStreamFrame(b []byte, typ uint64, _ protocol.Version) (*StreamFrame, int, error) { + startLen := len(b) hasOffset := typ&0b100 > 0 fin := typ&0b1 > 0 hasDataLen := typ&0b10 > 0 - streamID, err := quicvarint.Read(r) + streamID, l, err := quicvarint.Parse(b) if err != nil { - return nil, err + return nil, 0, replaceUnexpectedEOF(err) } + b = b[l:] var offset uint64 if hasOffset { - offset, err = quicvarint.Read(r) + offset, l, err = quicvarint.Parse(b) if err != nil { - return nil, err + return nil, 0, replaceUnexpectedEOF(err) } + b = b[l:] } var dataLen uint64 if hasDataLen { var err error - dataLen, err = quicvarint.Read(r) + var l int + dataLen, l, err = quicvarint.Parse(b) if err != nil { - return nil, err + return nil, 0, replaceUnexpectedEOF(err) + } + b = b[l:] + if dataLen > uint64(len(b)) { + return nil, 0, io.EOF } } else { // The rest of the packet is data - dataLen = uint64(r.Len()) + dataLen = uint64(len(b)) } var frame *StreamFrame @@ -57,7 +64,7 @@ func parseStreamFrame(r *bytes.Reader, typ uint64, _ protocol.Version) (*StreamF // The STREAM frame can't be larger than the StreamFrame we obtained from the buffer, // since those StreamFrames have a buffer length of the maximum packet size. if dataLen > uint64(cap(frame.Data)) { - return nil, io.EOF + return nil, 0, io.EOF } frame.Data = frame.Data[:dataLen] } @@ -68,17 +75,14 @@ func parseStreamFrame(r *bytes.Reader, typ uint64, _ protocol.Version) (*StreamF frame.DataLenPresent = hasDataLen if dataLen != 0 { - if _, err := io.ReadFull(r, frame.Data); err != nil { - return nil, err - } + copy(frame.Data, b) } if frame.Offset+frame.DataLen() > protocol.MaxByteCount { - return nil, errors.New("stream data overflows maximum offset") + return nil, 0, errors.New("stream data overflows maximum offset") } - return frame, nil + return frame, startLen - len(b) + int(dataLen), nil } -// Write writes a STREAM frame func (f *StreamFrame) Append(b []byte, _ protocol.Version) ([]byte, error) { if len(f.Data) == 0 && !f.Fin { return nil, errors.New("StreamFrame: attempting to write empty frame without FIN") @@ -108,7 +112,7 @@ func (f *StreamFrame) Append(b []byte, _ protocol.Version) ([]byte, error) { } // Length returns the total length of the STREAM frame -func (f *StreamFrame) Length(version protocol.Version) protocol.ByteCount { +func (f *StreamFrame) Length(protocol.Version) protocol.ByteCount { length := 1 + quicvarint.Len(uint64(f.StreamID)) if f.Offset != 0 { length += quicvarint.Len(uint64(f.Offset)) @@ -116,7 +120,7 @@ func (f *StreamFrame) Length(version protocol.Version) protocol.ByteCount { if f.DataLenPresent { length += quicvarint.Len(uint64(f.DataLen())) } - return length + f.DataLen() + return protocol.ByteCount(length) + f.DataLen() } // DataLen gives the length of data in bytes @@ -126,14 +130,14 @@ func (f *StreamFrame) DataLen() protocol.ByteCount { // MaxDataLen returns the maximum data length // If 0 is returned, writing will fail (a STREAM frame must contain at least 1 byte of data). -func (f *StreamFrame) MaxDataLen(maxSize protocol.ByteCount, version protocol.Version) protocol.ByteCount { - headerLen := 1 + quicvarint.Len(uint64(f.StreamID)) +func (f *StreamFrame) MaxDataLen(maxSize protocol.ByteCount, _ protocol.Version) protocol.ByteCount { + headerLen := 1 + protocol.ByteCount(quicvarint.Len(uint64(f.StreamID))) if f.Offset != 0 { - headerLen += quicvarint.Len(uint64(f.Offset)) + headerLen += protocol.ByteCount(quicvarint.Len(uint64(f.Offset))) } if f.DataLenPresent { - // pretend that the data size will be 1 bytes - // if it turns out that varint encoding the length will consume 2 bytes, we need to adjust the data length afterwards + // Pretend that the data size will be 1 byte. + // If it turns out that varint encoding the length will consume 2 bytes, we need to adjust the data length afterward headerLen++ } if headerLen > maxSize { diff --git a/vendor/github.com/quic-go/quic-go/internal/wire/streams_blocked_frame.go b/vendor/github.com/quic-go/quic-go/internal/wire/streams_blocked_frame.go index b24619ab0..c946fec31 100644 --- a/vendor/github.com/quic-go/quic-go/internal/wire/streams_blocked_frame.go +++ b/vendor/github.com/quic-go/quic-go/internal/wire/streams_blocked_frame.go @@ -1,7 +1,6 @@ package wire import ( - "bytes" "fmt" "github.com/quic-go/quic-go/internal/protocol" @@ -14,7 +13,7 @@ type StreamsBlockedFrame struct { StreamLimit protocol.StreamNum } -func parseStreamsBlockedFrame(r *bytes.Reader, typ uint64, _ protocol.Version) (*StreamsBlockedFrame, error) { +func parseStreamsBlockedFrame(b []byte, typ uint64, _ protocol.Version) (*StreamsBlockedFrame, int, error) { f := &StreamsBlockedFrame{} switch typ { case bidiStreamBlockedFrameType: @@ -22,15 +21,15 @@ func parseStreamsBlockedFrame(r *bytes.Reader, typ uint64, _ protocol.Version) ( case uniStreamBlockedFrameType: f.Type = protocol.StreamTypeUni } - streamLimit, err := quicvarint.Read(r) + streamLimit, l, err := quicvarint.Parse(b) if err != nil { - return nil, err + return nil, 0, replaceUnexpectedEOF(err) } f.StreamLimit = protocol.StreamNum(streamLimit) if f.StreamLimit > protocol.MaxStreamCount { - return nil, fmt.Errorf("%d exceeds the maximum stream count", f.StreamLimit) + return nil, 0, fmt.Errorf("%d exceeds the maximum stream count", f.StreamLimit) } - return f, nil + return f, l, nil } func (f *StreamsBlockedFrame) Append(b []byte, _ protocol.Version) ([]byte, error) { @@ -46,5 +45,5 @@ func (f *StreamsBlockedFrame) Append(b []byte, _ protocol.Version) ([]byte, erro // Length of a written frame func (f *StreamsBlockedFrame) Length(_ protocol.Version) protocol.ByteCount { - return 1 + quicvarint.Len(uint64(f.StreamLimit)) + return 1 + protocol.ByteCount(quicvarint.Len(uint64(f.StreamLimit))) } diff --git a/vendor/github.com/quic-go/quic-go/internal/wire/transport_parameters.go b/vendor/github.com/quic-go/quic-go/internal/wire/transport_parameters.go index c03be3cd7..cee74b8fa 100644 --- a/vendor/github.com/quic-go/quic-go/internal/wire/transport_parameters.go +++ b/vendor/github.com/quic-go/quic-go/internal/wire/transport_parameters.go @@ -1,19 +1,17 @@ package wire import ( - "bytes" "crypto/rand" "encoding/binary" "errors" "fmt" "io" "net/netip" - "sort" + "slices" "time" "github.com/quic-go/quic-go/internal/protocol" "github.com/quic-go/quic-go/internal/qerr" - "github.com/quic-go/quic-go/internal/utils" "github.com/quic-go/quic-go/quicvarint" ) @@ -89,7 +87,7 @@ type TransportParameters struct { // Unmarshal the transport parameters func (p *TransportParameters) Unmarshal(data []byte, sentBy protocol.Perspective) error { - if err := p.unmarshal(bytes.NewReader(data), sentBy, false); err != nil { + if err := p.unmarshal(data, sentBy, false); err != nil { return &qerr.TransportError{ ErrorCode: qerr.TransportParameterError, ErrorMessage: err.Error(), @@ -98,9 +96,9 @@ func (p *TransportParameters) Unmarshal(data []byte, sentBy protocol.Perspective return nil } -func (p *TransportParameters) unmarshal(r *bytes.Reader, sentBy protocol.Perspective, fromSessionTicket bool) error { +func (p *TransportParameters) unmarshal(b []byte, sentBy protocol.Perspective, fromSessionTicket bool) error { // needed to check that every parameter is only sent at most once - var parameterIDs []transportParameterID + parameterIDs := make([]transportParameterID, 0, 32) var ( readOriginalDestinationConnectionID bool @@ -112,18 +110,20 @@ func (p *TransportParameters) unmarshal(r *bytes.Reader, sentBy protocol.Perspec p.MaxAckDelay = protocol.DefaultMaxAckDelay p.MaxDatagramFrameSize = protocol.InvalidByteCount - for r.Len() > 0 { - paramIDInt, err := quicvarint.Read(r) + for len(b) > 0 { + paramIDInt, l, err := quicvarint.Parse(b) if err != nil { return err } paramID := transportParameterID(paramIDInt) - paramLen, err := quicvarint.Read(r) + b = b[l:] + paramLen, l, err := quicvarint.Parse(b) if err != nil { return err } - if uint64(r.Len()) < paramLen { - return fmt.Errorf("remaining length (%d) smaller than parameter length (%d)", r.Len(), paramLen) + b = b[l:] + if uint64(len(b)) < paramLen { + return fmt.Errorf("remaining length (%d) smaller than parameter length (%d)", len(b), paramLen) } parameterIDs = append(parameterIDs, paramID) switch paramID { @@ -141,16 +141,18 @@ func (p *TransportParameters) unmarshal(r *bytes.Reader, sentBy protocol.Perspec maxAckDelayParameterID, maxDatagramFrameSizeParameterID, ackDelayExponentParameterID: - if err := p.readNumericTransportParameter(r, paramID, int(paramLen)); err != nil { + if err := p.readNumericTransportParameter(b, paramID, int(paramLen)); err != nil { return err } + b = b[paramLen:] case preferredAddressParameterID: if sentBy == protocol.PerspectiveClient { return errors.New("client sent a preferred_address") } - if err := p.readPreferredAddress(r, int(paramLen)); err != nil { + if err := p.readPreferredAddress(b, int(paramLen)); err != nil { return err } + b = b[paramLen:] case disableActiveMigrationParameterID: if paramLen != 0 { return fmt.Errorf("wrong length for disable_active_migration: %d (expected empty)", paramLen) @@ -164,25 +166,41 @@ func (p *TransportParameters) unmarshal(r *bytes.Reader, sentBy protocol.Perspec return fmt.Errorf("wrong length for stateless_reset_token: %d (expected 16)", paramLen) } var token protocol.StatelessResetToken - r.Read(token[:]) + if len(b) < len(token) { + return io.EOF + } + copy(token[:], b) + b = b[len(token):] p.StatelessResetToken = &token case originalDestinationConnectionIDParameterID: if sentBy == protocol.PerspectiveClient { return errors.New("client sent an original_destination_connection_id") } - p.OriginalDestinationConnectionID, _ = protocol.ReadConnectionID(r, int(paramLen)) + if paramLen > protocol.MaxConnIDLen { + return protocol.ErrInvalidConnectionIDLen + } + p.OriginalDestinationConnectionID = protocol.ParseConnectionID(b[:paramLen]) + b = b[paramLen:] readOriginalDestinationConnectionID = true case initialSourceConnectionIDParameterID: - p.InitialSourceConnectionID, _ = protocol.ReadConnectionID(r, int(paramLen)) + if paramLen > protocol.MaxConnIDLen { + return protocol.ErrInvalidConnectionIDLen + } + p.InitialSourceConnectionID = protocol.ParseConnectionID(b[:paramLen]) + b = b[paramLen:] readInitialSourceConnectionID = true case retrySourceConnectionIDParameterID: if sentBy == protocol.PerspectiveClient { return errors.New("client sent a retry_source_connection_id") } - connID, _ := protocol.ReadConnectionID(r, int(paramLen)) + if paramLen > protocol.MaxConnIDLen { + return protocol.ErrInvalidConnectionIDLen + } + connID := protocol.ParseConnectionID(b[:paramLen]) + b = b[paramLen:] p.RetrySourceConnectionID = &connID default: - r.Seek(int64(paramLen), io.SeekCurrent) + b = b[paramLen:] } } @@ -202,7 +220,12 @@ func (p *TransportParameters) unmarshal(r *bytes.Reader, sentBy protocol.Perspec } // check that every transport parameter was sent at most once - sort.Slice(parameterIDs, func(i, j int) bool { return parameterIDs[i] < parameterIDs[j] }) + slices.SortFunc(parameterIDs, func(a, b transportParameterID) int { + if a < b { + return -1 + } + return 1 + }) for i := 0; i < len(parameterIDs)-1; i++ { if parameterIDs[i] == parameterIDs[i+1] { return fmt.Errorf("received duplicate transport parameter %#x", parameterIDs[i]) @@ -212,60 +235,47 @@ func (p *TransportParameters) unmarshal(r *bytes.Reader, sentBy protocol.Perspec return nil } -func (p *TransportParameters) readPreferredAddress(r *bytes.Reader, expectedLen int) error { - remainingLen := r.Len() +func (p *TransportParameters) readPreferredAddress(b []byte, expectedLen int) error { + remainingLen := len(b) pa := &PreferredAddress{} - var ipv4 [4]byte - if _, err := io.ReadFull(r, ipv4[:]); err != nil { - return err - } - port, err := utils.BigEndian.ReadUint16(r) - if err != nil { - return err + if len(b) < 4+2+16+2+1 { + return io.EOF } - pa.IPv4 = netip.AddrPortFrom(netip.AddrFrom4(ipv4), port) + var ipv4 [4]byte + copy(ipv4[:], b[:4]) + port4 := binary.BigEndian.Uint16(b[4:]) + b = b[4+2:] + pa.IPv4 = netip.AddrPortFrom(netip.AddrFrom4(ipv4), port4) var ipv6 [16]byte - if _, err := io.ReadFull(r, ipv6[:]); err != nil { - return err - } - port, err = utils.BigEndian.ReadUint16(r) - if err != nil { - return err - } - pa.IPv6 = netip.AddrPortFrom(netip.AddrFrom16(ipv6), port) - connIDLen, err := r.ReadByte() - if err != nil { - return err - } + copy(ipv6[:], b[:16]) + port6 := binary.BigEndian.Uint16(b[16:]) + pa.IPv6 = netip.AddrPortFrom(netip.AddrFrom16(ipv6), port6) + b = b[16+2:] + connIDLen := int(b[0]) + b = b[1:] if connIDLen == 0 || connIDLen > protocol.MaxConnIDLen { return fmt.Errorf("invalid connection ID length: %d", connIDLen) } - connID, err := protocol.ReadConnectionID(r, int(connIDLen)) - if err != nil { - return err - } - pa.ConnectionID = connID - if _, err := io.ReadFull(r, pa.StatelessResetToken[:]); err != nil { - return err + if len(b) < connIDLen+len(pa.StatelessResetToken) { + return io.EOF } - if bytesRead := remainingLen - r.Len(); bytesRead != expectedLen { + pa.ConnectionID = protocol.ParseConnectionID(b[:connIDLen]) + b = b[connIDLen:] + copy(pa.StatelessResetToken[:], b) + b = b[len(pa.StatelessResetToken):] + if bytesRead := remainingLen - len(b); bytesRead != expectedLen { return fmt.Errorf("expected preferred_address to be %d long, read %d bytes", expectedLen, bytesRead) } p.PreferredAddress = pa return nil } -func (p *TransportParameters) readNumericTransportParameter( - r *bytes.Reader, - paramID transportParameterID, - expectedLen int, -) error { - remainingLen := r.Len() - val, err := quicvarint.Read(r) +func (p *TransportParameters) readNumericTransportParameter(b []byte, paramID transportParameterID, expectedLen int) error { + val, l, err := quicvarint.Parse(b) if err != nil { return fmt.Errorf("error while reading transport parameter %d: %s", paramID, err) } - if remainingLen-r.Len() != expectedLen { + if l != expectedLen { return fmt.Errorf("inconsistent transport parameter length for transport parameter %#x", paramID) } //nolint:exhaustive // This only covers the numeric transport parameters. @@ -292,7 +302,7 @@ func (p *TransportParameters) readNumericTransportParameter( p.MaxIdleTimeout = max(protocol.MinRemoteIdleTimeout, time.Duration(val)*time.Millisecond) case maxUDPPayloadSizeParameterID: if val < 1200 { - return fmt.Errorf("invalid value for max_packet_size: %d (minimum 1200)", val) + return fmt.Errorf("invalid value for max_udp_payload_size: %d (minimum 1200)", val) } p.MaxUDPPayloadSize = protocol.ByteCount(val) case ackDelayExponentParameterID: @@ -347,8 +357,10 @@ func (p *TransportParameters) Marshal(pers protocol.Perspective) []byte { b = p.marshalVarintParam(b, initialMaxStreamsUniParameterID, uint64(p.MaxUniStreamNum)) // idle_timeout b = p.marshalVarintParam(b, maxIdleTimeoutParameterID, uint64(p.MaxIdleTimeout/time.Millisecond)) - // max_packet_size - b = p.marshalVarintParam(b, maxUDPPayloadSizeParameterID, uint64(protocol.MaxPacketBufferSize)) + // max_udp_payload_size + if p.MaxUDPPayloadSize > 0 { + b = p.marshalVarintParam(b, maxUDPPayloadSizeParameterID, uint64(p.MaxUDPPayloadSize)) + } // max_ack_delay // Only send it if is different from the default value. if p.MaxAckDelay != protocol.DefaultMaxAckDelay { @@ -457,15 +469,15 @@ func (p *TransportParameters) MarshalForSessionTicket(b []byte) []byte { } // UnmarshalFromSessionTicket unmarshals transport parameters from a session ticket. -func (p *TransportParameters) UnmarshalFromSessionTicket(r *bytes.Reader) error { - version, err := quicvarint.Read(r) +func (p *TransportParameters) UnmarshalFromSessionTicket(b []byte) error { + version, l, err := quicvarint.Parse(b) if err != nil { return err } if version != transportParameterMarshalingVersion { return fmt.Errorf("unknown transport parameter marshaling version: %d", version) } - return p.unmarshal(r, protocol.PerspectiveServer, true) + return p.unmarshal(b[l:], protocol.PerspectiveServer, true) } // ValidFor0RTT checks if the transport parameters match those saved in the session ticket. diff --git a/vendor/github.com/quic-go/quic-go/logging/connection_tracer.go b/vendor/github.com/quic-go/quic-go/logging/connection_tracer.go index 7f54d6cda..96bf4617d 100644 --- a/vendor/github.com/quic-go/quic-go/logging/connection_tracer.go +++ b/vendor/github.com/quic-go/quic-go/logging/connection_tracer.go @@ -8,14 +8,14 @@ import ( // A ConnectionTracer records events. type ConnectionTracer struct { StartedConnection func(local, remote net.Addr, srcConnID, destConnID ConnectionID) - NegotiatedVersion func(chosen VersionNumber, clientVersions, serverVersions []VersionNumber) + NegotiatedVersion func(chosen Version, clientVersions, serverVersions []Version) ClosedConnection func(error) SentTransportParameters func(*TransportParameters) ReceivedTransportParameters func(*TransportParameters) RestoredTransportParameters func(parameters *TransportParameters) // for 0-RTT SentLongHeaderPacket func(*ExtendedHeader, ByteCount, ECN, *AckFrame, []Frame) SentShortHeaderPacket func(*ShortHeader, ByteCount, ECN, *AckFrame, []Frame) - ReceivedVersionNegotiationPacket func(dest, src ArbitraryLenConnectionID, _ []VersionNumber) + ReceivedVersionNegotiationPacket func(dest, src ArbitraryLenConnectionID, _ []Version) ReceivedRetry func(*Header) ReceivedLongHeaderPacket func(*ExtendedHeader, ByteCount, ECN, []Frame) ReceivedShortHeaderPacket func(*ShortHeader, ByteCount, ECN, []Frame) @@ -24,6 +24,7 @@ type ConnectionTracer struct { UpdatedMetrics func(rttStats *RTTStats, cwnd, bytesInFlight ByteCount, packetsInFlight int) AcknowledgedPacket func(EncryptionLevel, PacketNumber) LostPacket func(EncryptionLevel, PacketNumber, PacketLossReason) + UpdatedMTU func(mtu ByteCount, done bool) UpdatedCongestionState func(CongestionState) UpdatedPTOCount func(value uint32) UpdatedKeyFromTLS func(EncryptionLevel, Perspective) @@ -56,7 +57,7 @@ func NewMultiplexedConnectionTracer(tracers ...*ConnectionTracer) *ConnectionTra } } }, - NegotiatedVersion: func(chosen VersionNumber, clientVersions, serverVersions []VersionNumber) { + NegotiatedVersion: func(chosen Version, clientVersions, serverVersions []Version) { for _, t := range tracers { if t.NegotiatedVersion != nil { t.NegotiatedVersion(chosen, clientVersions, serverVersions) @@ -105,7 +106,7 @@ func NewMultiplexedConnectionTracer(tracers ...*ConnectionTracer) *ConnectionTra } } }, - ReceivedVersionNegotiationPacket: func(dest, src ArbitraryLenConnectionID, versions []VersionNumber) { + ReceivedVersionNegotiationPacket: func(dest, src ArbitraryLenConnectionID, versions []Version) { for _, t := range tracers { if t.ReceivedVersionNegotiationPacket != nil { t.ReceivedVersionNegotiationPacket(dest, src, versions) @@ -168,6 +169,13 @@ func NewMultiplexedConnectionTracer(tracers ...*ConnectionTracer) *ConnectionTra } } }, + UpdatedMTU: func(mtu ByteCount, done bool) { + for _, t := range tracers { + if t.UpdatedMTU != nil { + t.UpdatedMTU(mtu, done) + } + } + }, UpdatedCongestionState: func(state CongestionState) { for _, t := range tracers { if t.UpdatedCongestionState != nil { diff --git a/vendor/github.com/quic-go/quic-go/logging/interface.go b/vendor/github.com/quic-go/quic-go/logging/interface.go index a618a1893..1f8edb92c 100644 --- a/vendor/github.com/quic-go/quic-go/logging/interface.go +++ b/vendor/github.com/quic-go/quic-go/logging/interface.go @@ -36,8 +36,8 @@ type ( StreamNum = protocol.StreamNum // The StreamType is the type of the stream (unidirectional or bidirectional). StreamType = protocol.StreamType - // The VersionNumber is the QUIC version. - VersionNumber = protocol.Version + // The Version is the QUIC version. + Version = protocol.Version // The Header is the QUIC packet header, before removing header protection. Header = wire.Header @@ -72,27 +72,27 @@ const ( const ( // KeyPhaseZero is key phase bit 0 - KeyPhaseZero KeyPhaseBit = protocol.KeyPhaseZero + KeyPhaseZero = protocol.KeyPhaseZero // KeyPhaseOne is key phase bit 1 - KeyPhaseOne KeyPhaseBit = protocol.KeyPhaseOne + KeyPhaseOne = protocol.KeyPhaseOne ) const ( // PerspectiveServer is used for a QUIC server - PerspectiveServer Perspective = protocol.PerspectiveServer + PerspectiveServer = protocol.PerspectiveServer // PerspectiveClient is used for a QUIC client - PerspectiveClient Perspective = protocol.PerspectiveClient + PerspectiveClient = protocol.PerspectiveClient ) const ( // EncryptionInitial is the Initial encryption level - EncryptionInitial EncryptionLevel = protocol.EncryptionInitial + EncryptionInitial = protocol.EncryptionInitial // EncryptionHandshake is the Handshake encryption level - EncryptionHandshake EncryptionLevel = protocol.EncryptionHandshake + EncryptionHandshake = protocol.EncryptionHandshake // Encryption1RTT is the 1-RTT encryption level - Encryption1RTT EncryptionLevel = protocol.Encryption1RTT + Encryption1RTT = protocol.Encryption1RTT // Encryption0RTT is the 0-RTT encryption level - Encryption0RTT EncryptionLevel = protocol.Encryption0RTT + Encryption0RTT = protocol.Encryption0RTT ) const ( diff --git a/vendor/github.com/quic-go/quic-go/logging/tracer.go b/vendor/github.com/quic-go/quic-go/logging/tracer.go index edd85dbaa..625a809ee 100644 --- a/vendor/github.com/quic-go/quic-go/logging/tracer.go +++ b/vendor/github.com/quic-go/quic-go/logging/tracer.go @@ -5,7 +5,7 @@ import "net" // A Tracer traces events. type Tracer struct { SentPacket func(net.Addr, *Header, ByteCount, []Frame) - SentVersionNegotiationPacket func(_ net.Addr, dest, src ArbitraryLenConnectionID, _ []VersionNumber) + SentVersionNegotiationPacket func(_ net.Addr, dest, src ArbitraryLenConnectionID, _ []Version) DroppedPacket func(net.Addr, PacketType, ByteCount, PacketDropReason) Debug func(name, msg string) Close func() @@ -27,7 +27,7 @@ func NewMultiplexedTracer(tracers ...*Tracer) *Tracer { } } }, - SentVersionNegotiationPacket: func(remote net.Addr, dest, src ArbitraryLenConnectionID, versions []VersionNumber) { + SentVersionNegotiationPacket: func(remote net.Addr, dest, src ArbitraryLenConnectionID, versions []Version) { for _, t := range tracers { if t.SentVersionNegotiationPacket != nil { t.SentVersionNegotiationPacket(remote, dest, src, versions) diff --git a/vendor/github.com/quic-go/quic-go/mockgen.go b/vendor/github.com/quic-go/quic-go/mockgen.go index 81cc4a5ef..65ec465aa 100644 --- a/vendor/github.com/quic-go/quic-go/mockgen.go +++ b/vendor/github.com/quic-go/quic-go/mockgen.go @@ -14,23 +14,17 @@ type Sender = sender //go:generate sh -c "go run go.uber.org/mock/mockgen -typed -build_flags=\"-tags=gomock\" -package quic -self_package github.com/quic-go/quic-go -destination mock_stream_internal_test.go github.com/quic-go/quic-go StreamI" type StreamI = streamI -//go:generate sh -c "go run go.uber.org/mock/mockgen -typed -build_flags=\"-tags=gomock\" -package quic -self_package github.com/quic-go/quic-go -destination mock_crypto_stream_test.go github.com/quic-go/quic-go CryptoStream" -type CryptoStream = cryptoStream - //go:generate sh -c "go run go.uber.org/mock/mockgen -typed -build_flags=\"-tags=gomock\" -package quic -self_package github.com/quic-go/quic-go -destination mock_receive_stream_internal_test.go github.com/quic-go/quic-go ReceiveStreamI" type ReceiveStreamI = receiveStreamI //go:generate sh -c "go run go.uber.org/mock/mockgen -typed -build_flags=\"-tags=gomock\" -package quic -self_package github.com/quic-go/quic-go -destination mock_send_stream_internal_test.go github.com/quic-go/quic-go SendStreamI" type SendStreamI = sendStreamI -//go:generate sh -c "go run go.uber.org/mock/mockgen -typed -build_flags=\"-tags=gomock\" -package quic -self_package github.com/quic-go/quic-go -destination mock_stream_getter_test.go github.com/quic-go/quic-go StreamGetter" -type StreamGetter = streamGetter - //go:generate sh -c "go run go.uber.org/mock/mockgen -typed -build_flags=\"-tags=gomock\" -package quic -self_package github.com/quic-go/quic-go -destination mock_stream_sender_test.go github.com/quic-go/quic-go StreamSender" type StreamSender = streamSender -//go:generate sh -c "go run go.uber.org/mock/mockgen -typed -build_flags=\"-tags=gomock\" -package quic -self_package github.com/quic-go/quic-go -destination mock_crypto_data_handler_test.go github.com/quic-go/quic-go CryptoDataHandler" -type CryptoDataHandler = cryptoDataHandler +//go:generate sh -c "go run go.uber.org/mock/mockgen -typed -build_flags=\"-tags=gomock\" -package quic -self_package github.com/quic-go/quic-go -destination mock_stream_control_frame_getter_test.go github.com/quic-go/quic-go StreamControlFrameGetter" +type StreamControlFrameGetter = streamControlFrameGetter //go:generate sh -c "go run go.uber.org/mock/mockgen -typed -build_flags=\"-tags=gomock\" -package quic -self_package github.com/quic-go/quic-go -destination mock_frame_source_test.go github.com/quic-go/quic-go FrameSource" type FrameSource = frameSource @@ -72,5 +66,4 @@ type PacketHandlerManager = packetHandlerManager // //go:generate sh -c "go run go.uber.org/mock/mockgen -typed -package quic -self_package github.com/quic-go/quic-go -source sys_conn_oob.go -destination mock_batch_conn_test.go -mock_names batchConn=MockBatchConn" -//go:generate sh -c "go run go.uber.org/mock/mockgen -typed -package quic -self_package github.com/quic-go/quic-go -self_package github.com/quic-go/quic-go -destination mock_token_store_test.go github.com/quic-go/quic-go TokenStore" //go:generate sh -c "go run go.uber.org/mock/mockgen -typed -package quic -self_package github.com/quic-go/quic-go -self_package github.com/quic-go/quic-go -destination mock_packetconn_test.go net PacketConn" diff --git a/vendor/github.com/quic-go/quic-go/mtu_discoverer.go b/vendor/github.com/quic-go/quic-go/mtu_discoverer.go index 317b09292..3f3a640ae 100644 --- a/vendor/github.com/quic-go/quic-go/mtu_discoverer.go +++ b/vendor/github.com/quic-go/quic-go/mtu_discoverer.go @@ -1,19 +1,19 @@ package quic import ( - "net" "time" "github.com/quic-go/quic-go/internal/ackhandler" "github.com/quic-go/quic-go/internal/protocol" "github.com/quic-go/quic-go/internal/utils" "github.com/quic-go/quic-go/internal/wire" + "github.com/quic-go/quic-go/logging" ) type mtuDiscoverer interface { // Start starts the MTU discovery process. // It's unnecessary to call ShouldSendProbe before that. - Start(maxPacketSize protocol.ByteCount) + Start() ShouldSendProbe(now time.Time) bool CurrentSize() protocol.ByteCount GetPing() (ping ackhandler.Frame, datagramSize protocol.ByteCount) @@ -25,54 +25,129 @@ const ( maxMTUDiff = 20 // send a probe packet every mtuProbeDelay RTTs mtuProbeDelay = 5 + // Once maxLostMTUProbes MTU probe packets larger than a certain size are lost, + // MTU discovery won't probe for larger MTUs than this size. + // The algorithm used here is resilient to packet loss of (maxLostMTUProbes - 1) packets. + maxLostMTUProbes = 3 ) -func getMaxPacketSize(addr net.Addr) protocol.ByteCount { - maxSize := protocol.ByteCount(protocol.MinInitialPacketSize) - // If this is not a UDP address, we don't know anything about the MTU. - // Use the minimum size of an Initial packet as the max packet size. - if udpAddr, ok := addr.(*net.UDPAddr); ok { - if utils.IsIPv4(udpAddr.IP) { - maxSize = protocol.InitialPacketSizeIPv4 - } else { - maxSize = protocol.InitialPacketSizeIPv6 - } - } - return maxSize -} +// The Path MTU is found by sending a larger packet every now and then. +// If the packet is acknowledged, we conclude that the path supports this larger packet size. +// If the packet is lost, this can mean one of two things: +// 1. The path doesn't support this larger packet size, or +// 2. The packet was lost due to packet loss, independent of its size. +// The algorithm used here is resilient to packet loss of (maxLostMTUProbes - 1) packets. +// For simplicty, the following example use maxLostMTUProbes = 2. +// +// Initialization: +// |------------------------------------------------------------------------------| +// min max +// +// The first MTU probe packet will have size (min+max)/2. +// Assume that this packet is acknowledged. We can now move the min marker, +// and continue the search in the resulting interval. +// +// If 1st probe packet acknowledged: +// |---------------------------------------|--------------------------------------| +// min max +// +// If 1st probe packet lost: +// |---------------------------------------|--------------------------------------| +// min lost[0] max +// +// We can't conclude that the path doesn't support this packet size, since the loss of the probe +// packet could have been unrelated to the packet size. A larger probe packet will be sent later on. +// After a loss, the next probe packet has size (min+lost[0])/2. +// Now assume this probe packet is acknowledged: +// +// 2nd probe packet acknowledged: +// |------------------|--------------------|--------------------------------------| +// min lost[0] max +// +// First of all, we conclude that the path supports at least this MTU. That's progress! +// Second, we probe a bit more aggressively with the next probe packet: +// After an acknowledgement, the next probe packet has size (min+max)/2. +// This means we'll send a packet larger than the first probe packet (which was lost). +// +// If 3rd probe packet acknowledged: +// |-------------------------------------------------|----------------------------| +// min max +// +// We can conclude that the loss of the 1st probe packet was not due to its size, and +// continue searching in a much smaller interval now. +// +// If 3rd probe packet lost: +// |------------------|--------------------|---------|----------------------------| +// min lost[0] max +// +// Since in our example numPTOProbes = 2, and we lost 2 packets smaller than max, we +// conclude that this packet size is not supported on the path, and reduce the maximum +// value of the search interval. +// +// MTU discovery concludes once the interval min and max has been narrowed down to maxMTUDiff. type mtuFinder struct { lastProbeTime time.Time mtuIncreased func(protocol.ByteCount) rttStats *utils.RTTStats + inFlight protocol.ByteCount // the size of the probe packet currently in flight. InvalidByteCount if none is in flight - current protocol.ByteCount - max protocol.ByteCount // the maximum value, as advertised by the peer (or our maximum size buffer) + min protocol.ByteCount + limit protocol.ByteCount + + // on initialization, we treat the maximum size as the first "lost" packet + lost [maxLostMTUProbes]protocol.ByteCount + lastProbeWasLost bool + + tracer *logging.ConnectionTracer } var _ mtuDiscoverer = &mtuFinder{} -func newMTUDiscoverer(rttStats *utils.RTTStats, start protocol.ByteCount, mtuIncreased func(protocol.ByteCount)) *mtuFinder { - return &mtuFinder{ +func newMTUDiscoverer( + rttStats *utils.RTTStats, + start, max protocol.ByteCount, + mtuIncreased func(protocol.ByteCount), + tracer *logging.ConnectionTracer, +) *mtuFinder { + f := &mtuFinder{ inFlight: protocol.InvalidByteCount, - current: start, + min: start, + limit: max, rttStats: rttStats, mtuIncreased: mtuIncreased, + tracer: tracer, } + for i := range f.lost { + if i == 0 { + f.lost[i] = max + continue + } + f.lost[i] = protocol.InvalidByteCount + } + return f } func (f *mtuFinder) done() bool { - return f.max-f.current <= maxMTUDiff+1 + return f.max()-f.min <= maxMTUDiff+1 } -func (f *mtuFinder) Start(maxPacketSize protocol.ByteCount) { +func (f *mtuFinder) max() protocol.ByteCount { + for i, v := range f.lost { + if v == protocol.InvalidByteCount { + return f.lost[i-1] + } + } + return f.lost[len(f.lost)-1] +} + +func (f *mtuFinder) Start() { f.lastProbeTime = time.Now() // makes sure the first probe packet is not sent immediately - f.max = maxPacketSize } func (f *mtuFinder) ShouldSendProbe(now time.Time) bool { - if f.max == 0 || f.lastProbeTime.IsZero() { + if f.lastProbeTime.IsZero() { return false } if f.inFlight != protocol.InvalidByteCount || f.done() { @@ -82,20 +157,27 @@ func (f *mtuFinder) ShouldSendProbe(now time.Time) bool { } func (f *mtuFinder) GetPing() (ackhandler.Frame, protocol.ByteCount) { - size := (f.max + f.current) / 2 + var size protocol.ByteCount + if f.lastProbeWasLost { + size = (f.min + f.lost[0]) / 2 + } else { + size = (f.min + f.max()) / 2 + } f.lastProbeTime = time.Now() f.inFlight = size return ackhandler.Frame{ Frame: &wire.PingFrame{}, - Handler: (*mtuFinderAckHandler)(f), + Handler: &mtuFinderAckHandler{f}, }, size } func (f *mtuFinder) CurrentSize() protocol.ByteCount { - return f.current + return f.min } -type mtuFinderAckHandler mtuFinder +type mtuFinderAckHandler struct { + *mtuFinder +} var _ ackhandler.FrameHandler = &mtuFinderAckHandler{} @@ -105,7 +187,28 @@ func (h *mtuFinderAckHandler) OnAcked(wire.Frame) { panic("OnAcked callback called although there's no MTU probe packet in flight") } h.inFlight = protocol.InvalidByteCount - h.current = size + h.min = size + h.lastProbeWasLost = false + // remove all values smaller than size from the lost array + var j int + for i, v := range h.lost { + if size < v { + j = i + break + } + } + if j > 0 { + for i := 0; i < len(h.lost); i++ { + if i+j < len(h.lost) { + h.lost[i] = h.lost[i+j] + } else { + h.lost[i] = protocol.InvalidByteCount + } + } + } + if h.tracer != nil && h.tracer.UpdatedMTU != nil { + h.tracer.UpdatedMTU(size, h.done()) + } h.mtuIncreased(size) } @@ -114,6 +217,13 @@ func (h *mtuFinderAckHandler) OnLost(wire.Frame) { if size == protocol.InvalidByteCount { panic("OnLost callback called although there's no MTU probe packet in flight") } - h.max = size + h.lastProbeWasLost = true h.inFlight = protocol.InvalidByteCount + for i, v := range h.lost { + if size < v { + copy(h.lost[i+1:], h.lost[i:]) + h.lost[i] = size + break + } + } } diff --git a/vendor/github.com/quic-go/quic-go/oss-fuzz.sh b/vendor/github.com/quic-go/quic-go/oss-fuzz.sh index 22a577fe1..92a57a2cc 100644 --- a/vendor/github.com/quic-go/quic-go/oss-fuzz.sh +++ b/vendor/github.com/quic-go/quic-go/oss-fuzz.sh @@ -3,12 +3,12 @@ # Install Go manually, since oss-fuzz ships with an outdated Go version. # See https://github.com/google/oss-fuzz/pull/10643. export CXX="${CXX} -lresolv" # required by Go 1.20 -wget https://go.dev/dl/go1.22.0.linux-amd64.tar.gz \ +wget https://go.dev/dl/go1.23.0.linux-amd64.tar.gz \ && mkdir temp-go \ && rm -rf /root/.go/* \ - && tar -C temp-go/ -xzf go1.22.0.linux-amd64.tar.gz \ + && tar -C temp-go/ -xzf go1.23.0.linux-amd64.tar.gz \ && mv temp-go/go/* /root/.go/ \ - && rm -rf temp-go go1.22.0.linux-amd64.tar.gz + && rm -rf temp-go go1.23.0.linux-amd64.tar.gz ( # fuzz qpack diff --git a/vendor/github.com/quic-go/quic-go/packet_packer.go b/vendor/github.com/quic-go/quic-go/packet_packer.go index e707734fb..8b8a03d44 100644 --- a/vendor/github.com/quic-go/quic-go/packet_packer.go +++ b/vendor/github.com/quic-go/quic-go/packet_packer.go @@ -121,8 +121,8 @@ type packetPacker struct { perspective protocol.Perspective cryptoSetup sealingManager - initialStream cryptoStream - handshakeStream cryptoStream + initialStream *cryptoStream + handshakeStream *cryptoStream token []byte @@ -141,7 +141,7 @@ var _ packer = &packetPacker{} func newPacketPacker( srcConnID protocol.ConnectionID, getDestConnID func() protocol.ConnectionID, - initialStream, handshakeStream cryptoStream, + initialStream, handshakeStream *cryptoStream, packetNumberManager packetNumberManager, retransmissionQueue *retransmissionQueue, cryptoSetup sealingManager, @@ -482,7 +482,7 @@ func (p *packetPacker) maybeGetCryptoPacket(maxPacketSize protocol.ByteCount, en return nil, payload{} } - var s cryptoStream + var s *cryptoStream var handler ackhandler.FrameHandler var hasRetransmission bool //nolint:exhaustive // Initial and Handshake are the only two encryption levels here. @@ -645,6 +645,9 @@ func (p *packetPacker) composeNextPacket(maxFrameSize protocol.ByteCount, onlyAc pl.length += lengthAdded // add handlers for the control frames that were added for i := startLen; i < len(pl.frames); i++ { + if pl.frames[i].Handler != nil { + continue + } switch pl.frames[i].Frame.(type) { case *wire.PathChallengeFrame, *wire.PathResponseFrame: // Path probing is currently not supported, therefore we don't need to set the OnAcked callback yet. diff --git a/vendor/github.com/quic-go/quic-go/packet_unpacker.go b/vendor/github.com/quic-go/quic-go/packet_unpacker.go index 1034aab1d..9e0fa9d90 100644 --- a/vendor/github.com/quic-go/quic-go/packet_unpacker.go +++ b/vendor/github.com/quic-go/quic-go/packet_unpacker.go @@ -1,7 +1,6 @@ package quic import ( - "bytes" "fmt" "time" @@ -53,7 +52,7 @@ func newPacketUnpacker(cs handshake.CryptoSetup, shortHdrConnIDLen int) *packetU // If the reserved bits are invalid, the error is wire.ErrInvalidReservedBits. // If any other error occurred when parsing the header, the error is of type headerParseError. // If decrypting the payload fails for any reason, the error is the error returned by the AEAD. -func (u *packetUnpacker) UnpackLongHeader(hdr *wire.Header, rcvTime time.Time, data []byte, v protocol.Version) (*unpackedPacket, error) { +func (u *packetUnpacker) UnpackLongHeader(hdr *wire.Header, data []byte) (*unpackedPacket, error) { var encLevel protocol.EncryptionLevel var extHdr *wire.ExtendedHeader var decrypted []byte @@ -65,7 +64,7 @@ func (u *packetUnpacker) UnpackLongHeader(hdr *wire.Header, rcvTime time.Time, d if err != nil { return nil, err } - extHdr, decrypted, err = u.unpackLongHeaderPacket(opener, hdr, data, v) + extHdr, decrypted, err = u.unpackLongHeaderPacket(opener, hdr, data) if err != nil { return nil, err } @@ -75,7 +74,7 @@ func (u *packetUnpacker) UnpackLongHeader(hdr *wire.Header, rcvTime time.Time, d if err != nil { return nil, err } - extHdr, decrypted, err = u.unpackLongHeaderPacket(opener, hdr, data, v) + extHdr, decrypted, err = u.unpackLongHeaderPacket(opener, hdr, data) if err != nil { return nil, err } @@ -85,7 +84,7 @@ func (u *packetUnpacker) UnpackLongHeader(hdr *wire.Header, rcvTime time.Time, d if err != nil { return nil, err } - extHdr, decrypted, err = u.unpackLongHeaderPacket(opener, hdr, data, v) + extHdr, decrypted, err = u.unpackLongHeaderPacket(opener, hdr, data) if err != nil { return nil, err } @@ -125,8 +124,8 @@ func (u *packetUnpacker) UnpackShortHeader(rcvTime time.Time, data []byte) (prot return pn, pnLen, kp, decrypted, nil } -func (u *packetUnpacker) unpackLongHeaderPacket(opener handshake.LongHeaderOpener, hdr *wire.Header, data []byte, v protocol.Version) (*wire.ExtendedHeader, []byte, error) { - extHdr, parseErr := u.unpackLongHeader(opener, hdr, data, v) +func (u *packetUnpacker) unpackLongHeaderPacket(opener handshake.LongHeaderOpener, hdr *wire.Header, data []byte) (*wire.ExtendedHeader, []byte, error) { + extHdr, parseErr := u.unpackLongHeader(opener, hdr, data) // If the reserved bits are set incorrectly, we still need to continue unpacking. // This avoids a timing side-channel, which otherwise might allow an attacker // to gain information about the header encryption. @@ -187,17 +186,15 @@ func (u *packetUnpacker) unpackShortHeader(hd headerDecryptor, data []byte) (int } // The error is either nil, a wire.ErrInvalidReservedBits or of type headerParseError. -func (u *packetUnpacker) unpackLongHeader(hd headerDecryptor, hdr *wire.Header, data []byte, v protocol.Version) (*wire.ExtendedHeader, error) { - extHdr, err := unpackLongHeader(hd, hdr, data, v) +func (u *packetUnpacker) unpackLongHeader(hd headerDecryptor, hdr *wire.Header, data []byte) (*wire.ExtendedHeader, error) { + extHdr, err := unpackLongHeader(hd, hdr, data) if err != nil && err != wire.ErrInvalidReservedBits { return nil, &headerParseError{err: err} } return extHdr, err } -func unpackLongHeader(hd headerDecryptor, hdr *wire.Header, data []byte, v protocol.Version) (*wire.ExtendedHeader, error) { - r := bytes.NewReader(data) - +func unpackLongHeader(hd headerDecryptor, hdr *wire.Header, data []byte) (*wire.ExtendedHeader, error) { hdrLen := hdr.ParsedLen() if protocol.ByteCount(len(data)) < hdrLen+4+16 { //nolint:stylecheck @@ -214,7 +211,7 @@ func unpackLongHeader(hd headerDecryptor, hdr *wire.Header, data []byte, v proto data[hdrLen:hdrLen+4], ) // 3. parse the header (and learn the actual length of the packet number) - extHdr, parseErr := hdr.ParseExtended(r, v) + extHdr, parseErr := hdr.ParseExtended(data) if parseErr != nil && parseErr != wire.ErrInvalidReservedBits { return nil, parseErr } diff --git a/vendor/github.com/quic-go/quic-go/quicvarint/varint.go b/vendor/github.com/quic-go/quic-go/quicvarint/varint.go index 3f12c0760..9a22e334f 100644 --- a/vendor/github.com/quic-go/quic-go/quicvarint/varint.go +++ b/vendor/github.com/quic-go/quic-go/quicvarint/varint.go @@ -3,8 +3,6 @@ package quicvarint import ( "fmt" "io" - - "github.com/quic-go/quic-go/internal/protocol" ) // taken from the QUIC draft @@ -28,16 +26,16 @@ func Read(r io.ByteReader) (uint64, error) { return 0, err } // the first two bits of the first byte encode the length - len := 1 << ((firstByte & 0xc0) >> 6) + l := 1 << ((firstByte & 0xc0) >> 6) b1 := firstByte & (0xff - 0xc0) - if len == 1 { + if l == 1 { return uint64(b1), nil } b2, err := r.ReadByte() if err != nil { return 0, err } - if len == 2 { + if l == 2 { return uint64(b2) + uint64(b1)<<8, nil } b3, err := r.ReadByte() @@ -48,7 +46,7 @@ func Read(r io.ByteReader) (uint64, error) { if err != nil { return 0, err } - if len == 4 { + if l == 4 { return uint64(b4) + uint64(b3)<<8 + uint64(b2)<<16 + uint64(b1)<<24, nil } b5, err := r.ReadByte() @@ -70,6 +68,31 @@ func Read(r io.ByteReader) (uint64, error) { return uint64(b8) + uint64(b7)<<8 + uint64(b6)<<16 + uint64(b5)<<24 + uint64(b4)<<32 + uint64(b3)<<40 + uint64(b2)<<48 + uint64(b1)<<56, nil } +// Parse reads a number in the QUIC varint format. +// It returns the number of bytes consumed. +func Parse(b []byte) (uint64 /* value */, int /* bytes consumed */, error) { + if len(b) == 0 { + return 0, 0, io.EOF + } + firstByte := b[0] + // the first two bits of the first byte encode the length + l := 1 << ((firstByte & 0xc0) >> 6) + if len(b) < l { + return 0, 0, io.ErrUnexpectedEOF + } + b0 := firstByte & (0xff - 0xc0) + if l == 1 { + return uint64(b0), 1, nil + } + if l == 2 { + return uint64(b[1]) + uint64(b0)<<8, 2, nil + } + if l == 4 { + return uint64(b[3]) + uint64(b[2])<<8 + uint64(b[1])<<16 + uint64(b0)<<24, 4, nil + } + return uint64(b[7]) + uint64(b[6])<<8 + uint64(b[5])<<16 + uint64(b[4])<<24 + uint64(b[3])<<32 + uint64(b[2])<<40 + uint64(b[1])<<48 + uint64(b0)<<56, 8, nil +} + // Append appends i in the QUIC varint format. func Append(b []byte, i uint64) []byte { if i <= maxVarInt1 { @@ -91,7 +114,7 @@ func Append(b []byte, i uint64) []byte { } // AppendWithLen append i in the QUIC varint format with the desired length. -func AppendWithLen(b []byte, i uint64, length protocol.ByteCount) []byte { +func AppendWithLen(b []byte, i uint64, length int) []byte { if length != 1 && length != 2 && length != 4 && length != 8 { panic("invalid varint length") } @@ -109,17 +132,17 @@ func AppendWithLen(b []byte, i uint64, length protocol.ByteCount) []byte { } else if length == 8 { b = append(b, 0b11000000) } - for j := protocol.ByteCount(1); j < length-l; j++ { + for j := 1; j < length-l; j++ { b = append(b, 0) } - for j := protocol.ByteCount(0); j < l; j++ { + for j := 0; j < l; j++ { b = append(b, uint8(i>>(8*(l-1-j)))) } return b } // Len determines the number of bytes that will be needed to write the number i. -func Len(i uint64) protocol.ByteCount { +func Len(i uint64) int { if i <= maxVarInt1 { return 1 } diff --git a/vendor/github.com/quic-go/quic-go/receive_stream.go b/vendor/github.com/quic-go/quic-go/receive_stream.go index 1235ff0e7..b8535ef52 100644 --- a/vendor/github.com/quic-go/quic-go/receive_stream.go +++ b/vendor/github.com/quic-go/quic-go/receive_stream.go @@ -6,6 +6,7 @@ import ( "sync" "time" + "github.com/quic-go/quic-go/internal/ackhandler" "github.com/quic-go/quic-go/internal/flowcontrol" "github.com/quic-go/quic-go/internal/protocol" "github.com/quic-go/quic-go/internal/qerr" @@ -19,7 +20,6 @@ type receiveStreamI interface { handleStreamFrame(*wire.StreamFrame) error handleResetStreamFrame(*wire.ResetStreamFrame) error closeForShutdown(error) - getWindowUpdate() protocol.ByteCount } type receiveStream struct { @@ -37,10 +37,17 @@ type receiveStream struct { readPosInFrame int currentFrameIsLast bool // is the currentFrame the last frame on this stream - finRead bool // set once we read a frame with a Fin + queuedStopSending bool + queuedMaxStreamData bool + + // Set once we read the io.EOF or the cancellation error. + // Note that for local cancellations, this doesn't necessarily mean that we know the final offset yet. + errorRead bool + completed bool // set once we've called streamSender.onStreamCompleted + cancelledRemotely bool + cancelledLocally bool + cancelErr *StreamError closeForShutdownErr error - cancelReadErr error - resetRemotelyErr *StreamError readChan chan struct{} readOnce chan struct{} // cap: 1, to protect against concurrent use of Read @@ -50,8 +57,9 @@ type receiveStream struct { } var ( - _ ReceiveStream = &receiveStream{} - _ receiveStreamI = &receiveStream{} + _ ReceiveStream = &receiveStream{} + _ receiveStreamI = &receiveStream{} + _ streamControlFrameGetter = &receiveStream{} ) func newReceiveStream( @@ -83,29 +91,54 @@ func (s *receiveStream) Read(p []byte) (int, error) { defer func() { <-s.readOnce }() s.mutex.Lock() - completed, n, err := s.readImpl(p) + queuedNewControlFrame, n, err := s.readImpl(p) + completed := s.isNewlyCompleted() s.mutex.Unlock() if completed { s.sender.onStreamCompleted(s.streamID) } + if queuedNewControlFrame { + s.sender.onHasStreamControlFrame(s.streamID, s) + } return n, err } -func (s *receiveStream) readImpl(p []byte) (bool /*stream completed */, int, error) { - if s.finRead { - return false, 0, io.EOF +func (s *receiveStream) isNewlyCompleted() bool { + if s.completed { + return false + } + // We need to know the final offset (either via FIN or RESET_STREAM) for flow control accounting. + if s.finalOffset == protocol.MaxByteCount { + return false + } + // We're done with the stream if it was cancelled locally... + if s.cancelledLocally { + s.completed = true + return true + } + // ... or if the error (either io.EOF or the reset error) was read + if s.errorRead { + s.completed = true + return true } - if s.cancelReadErr != nil { - return false, 0, s.cancelReadErr + return false +} + +func (s *receiveStream) readImpl(p []byte) (bool, int, error) { + if s.currentFrameIsLast && s.currentFrame == nil { + s.errorRead = true + return false, 0, io.EOF } - if s.resetRemotelyErr != nil { - return false, 0, s.resetRemotelyErr + if s.cancelledRemotely || s.cancelledLocally { + s.errorRead = true + return false, 0, s.cancelErr } if s.closeForShutdownErr != nil { return false, 0, s.closeForShutdownErr } + var queuedNewControlFrame bool var bytesRead int var deadlineTimer *utils.Timer for bytesRead < len(p) { @@ -113,25 +146,23 @@ func (s *receiveStream) readImpl(p []byte) (bool /*stream completed */, int, err s.dequeueNextFrame() } if s.currentFrame == nil && bytesRead > 0 { - return false, bytesRead, s.closeForShutdownErr + return queuedNewControlFrame, bytesRead, s.closeForShutdownErr } for { // Stop waiting on errors if s.closeForShutdownErr != nil { - return false, bytesRead, s.closeForShutdownErr - } - if s.cancelReadErr != nil { - return false, bytesRead, s.cancelReadErr + return queuedNewControlFrame, bytesRead, s.closeForShutdownErr } - if s.resetRemotelyErr != nil { - return false, bytesRead, s.resetRemotelyErr + if s.cancelledRemotely || s.cancelledLocally { + s.errorRead = true + return queuedNewControlFrame, 0, s.cancelErr } deadline := s.deadline if !deadline.IsZero() { if !time.Now().Before(deadline) { - return false, bytesRead, errDeadline + return queuedNewControlFrame, bytesRead, errDeadline } if deadlineTimer == nil { deadlineTimer = utils.NewTimer() @@ -161,10 +192,10 @@ func (s *receiveStream) readImpl(p []byte) (bool /*stream completed */, int, err } if bytesRead > len(p) { - return false, bytesRead, fmt.Errorf("BUG: bytesRead (%d) > len(p) (%d) in stream.Read", bytesRead, len(p)) + return queuedNewControlFrame, bytesRead, fmt.Errorf("BUG: bytesRead (%d) > len(p) (%d) in stream.Read", bytesRead, len(p)) } if s.readPosInFrame > len(s.currentFrame) { - return false, bytesRead, fmt.Errorf("BUG: readPosInFrame (%d) > frame.DataLen (%d) in stream.Read", s.readPosInFrame, len(s.currentFrame)) + return queuedNewControlFrame, bytesRead, fmt.Errorf("BUG: readPosInFrame (%d) > frame.DataLen (%d) in stream.Read", s.readPosInFrame, len(s.currentFrame)) } m := copy(p[bytesRead:], s.currentFrame[s.readPosInFrame:]) @@ -173,20 +204,23 @@ func (s *receiveStream) readImpl(p []byte) (bool /*stream completed */, int, err // when a RESET_STREAM was received, the flow controller was already // informed about the final byteOffset for this stream - if s.resetRemotelyErr == nil { - s.flowController.AddBytesRead(protocol.ByteCount(m)) + if !s.cancelledRemotely { + if queueMaxStreamData := s.flowController.AddBytesRead(protocol.ByteCount(m)); queueMaxStreamData { + s.queuedMaxStreamData = true + queuedNewControlFrame = true + } } if s.readPosInFrame >= len(s.currentFrame) && s.currentFrameIsLast { - s.finRead = true s.currentFrame = nil if s.currentFrameDone != nil { s.currentFrameDone() } - return true, bytesRead, io.EOF + s.errorRead = true + return queuedNewControlFrame, bytesRead, io.EOF } } - return false, bytesRead, nil + return queuedNewControlFrame, bytesRead, nil } func (s *receiveStream) dequeueNextFrame() { @@ -202,32 +236,40 @@ func (s *receiveStream) dequeueNextFrame() { func (s *receiveStream) CancelRead(errorCode StreamErrorCode) { s.mutex.Lock() - completed := s.cancelReadImpl(errorCode) + queuedNewControlFrame := s.cancelReadImpl(errorCode) + completed := s.isNewlyCompleted() s.mutex.Unlock() + if queuedNewControlFrame { + s.sender.onHasStreamControlFrame(s.streamID, s) + } if completed { s.flowController.Abandon() s.sender.onStreamCompleted(s.streamID) } } -func (s *receiveStream) cancelReadImpl(errorCode qerr.StreamErrorCode) bool /* completed */ { - if s.finRead || s.cancelReadErr != nil || s.resetRemotelyErr != nil { +func (s *receiveStream) cancelReadImpl(errorCode qerr.StreamErrorCode) (queuedNewControlFrame bool) { + if s.cancelledLocally { // duplicate call to CancelRead return false } - s.cancelReadErr = &StreamError{StreamID: s.streamID, ErrorCode: errorCode, Remote: false} + if s.closeForShutdownErr != nil { + return false + } + s.cancelledLocally = true + if s.errorRead || s.cancelledRemotely { + return false + } + s.queuedStopSending = true + s.cancelErr = &StreamError{StreamID: s.streamID, ErrorCode: errorCode, Remote: false} s.signalRead() - s.sender.queueControlFrame(&wire.StopSendingFrame{ - StreamID: s.streamID, - ErrorCode: errorCode, - }) - // We're done with this stream if the final offset was already received. - return s.finalOffset != protocol.MaxByteCount + return true } func (s *receiveStream) handleStreamFrame(frame *wire.StreamFrame) error { s.mutex.Lock() - completed, err := s.handleStreamFrameImpl(frame) + err := s.handleStreamFrameImpl(frame) + completed := s.isNewlyCompleted() s.mutex.Unlock() if completed { @@ -237,59 +279,78 @@ func (s *receiveStream) handleStreamFrame(frame *wire.StreamFrame) error { return err } -func (s *receiveStream) handleStreamFrameImpl(frame *wire.StreamFrame) (bool /* completed */, error) { +func (s *receiveStream) handleStreamFrameImpl(frame *wire.StreamFrame) error { maxOffset := frame.Offset + frame.DataLen() if err := s.flowController.UpdateHighestReceived(maxOffset, frame.Fin); err != nil { - return false, err + return err } - var newlyRcvdFinalOffset bool if frame.Fin { - newlyRcvdFinalOffset = s.finalOffset == protocol.MaxByteCount s.finalOffset = maxOffset } - if s.cancelReadErr != nil { - return newlyRcvdFinalOffset, nil + if s.cancelledLocally { + return nil } if err := s.frameQueue.Push(frame.Data, frame.Offset, frame.PutBack); err != nil { - return false, err + return err } s.signalRead() - return false, nil + return nil } func (s *receiveStream) handleResetStreamFrame(frame *wire.ResetStreamFrame) error { s.mutex.Lock() - completed, err := s.handleResetStreamFrameImpl(frame) + err := s.handleResetStreamFrameImpl(frame) + completed := s.isNewlyCompleted() s.mutex.Unlock() if completed { - s.flowController.Abandon() s.sender.onStreamCompleted(s.streamID) } return err } -func (s *receiveStream) handleResetStreamFrameImpl(frame *wire.ResetStreamFrame) (bool /*completed */, error) { +func (s *receiveStream) handleResetStreamFrameImpl(frame *wire.ResetStreamFrame) error { if s.closeForShutdownErr != nil { - return false, nil + return nil } if err := s.flowController.UpdateHighestReceived(frame.FinalSize, true); err != nil { - return false, err + return err } - newlyRcvdFinalOffset := s.finalOffset == protocol.MaxByteCount s.finalOffset = frame.FinalSize // ignore duplicate RESET_STREAM frames for this stream (after checking their final offset) - if s.resetRemotelyErr != nil { - return false, nil + if s.cancelledRemotely { + return nil } - s.resetRemotelyErr = &StreamError{ - StreamID: s.streamID, - ErrorCode: frame.ErrorCode, - Remote: true, + s.flowController.Abandon() + // don't save the error if the RESET_STREAM frames was received after CancelRead was called + if s.cancelledLocally { + return nil } + s.cancelledRemotely = true + s.cancelErr = &StreamError{StreamID: s.streamID, ErrorCode: frame.ErrorCode, Remote: true} s.signalRead() - return newlyRcvdFinalOffset, nil + return nil +} + +func (s *receiveStream) getControlFrame() (_ ackhandler.Frame, ok, hasMore bool) { + s.mutex.Lock() + defer s.mutex.Unlock() + + if !s.queuedStopSending && !s.queuedMaxStreamData { + return ackhandler.Frame{}, false, false + } + if s.queuedStopSending { + s.queuedStopSending = false + return ackhandler.Frame{ + Frame: &wire.StopSendingFrame{StreamID: s.streamID, ErrorCode: s.cancelErr.ErrorCode}, + }, true, s.queuedMaxStreamData + } + + s.queuedMaxStreamData = false + return ackhandler.Frame{ + Frame: &wire.MaxStreamDataFrame{StreamID: s.streamID, MaximumStreamData: s.flowController.GetWindowUpdate()}, + }, true, false } func (s *receiveStream) SetReadDeadline(t time.Time) error { @@ -310,10 +371,6 @@ func (s *receiveStream) closeForShutdown(err error) { s.signalRead() } -func (s *receiveStream) getWindowUpdate() protocol.ByteCount { - return s.flowController.GetWindowUpdate() -} - // signalRead performs a non-blocking send on the readChan func (s *receiveStream) signalRead() { select { diff --git a/vendor/github.com/quic-go/quic-go/send_stream.go b/vendor/github.com/quic-go/quic-go/send_stream.go index e1ce3e677..699c40ef6 100644 --- a/vendor/github.com/quic-go/quic-go/send_stream.go +++ b/vendor/github.com/quic-go/quic-go/send_stream.go @@ -26,7 +26,7 @@ type sendStreamI interface { type sendStream struct { mutex sync.Mutex - numOutstandingFrames int64 + numOutstandingFrames int64 // outstanding STREAM and RESET_STREAM frames retransmissionQueue []*wire.StreamFrame ctx context.Context @@ -37,12 +37,19 @@ type sendStream struct { writeOffset protocol.ByteCount - cancelWriteErr error + cancelWriteErr *StreamError closeForShutdownErr error + queuedResetStreamFrame bool + queuedBlockedFrame bool + finishedWriting bool // set once Close() is called finSent bool // set when a STREAM_FRAME with FIN bit has been sent - completed bool // set when this stream has been reported to the streamSender as completed + // Set when the application knows about the cancellation. + // This can happen because the application called CancelWrite, + // or because Write returned the error (for remote cancellations). + cancellationFlagged bool + completed bool // set when this stream has been reported to the streamSender as completed dataForWriting []byte // during a Write() call, this slice is the part of p that still needs to be sent out nextFrame *wire.StreamFrame @@ -55,11 +62,13 @@ type sendStream struct { } var ( - _ SendStream = &sendStream{} - _ sendStreamI = &sendStream{} + _ SendStream = &sendStream{} + _ sendStreamI = &sendStream{} + _ streamControlFrameGetter = &sendStream{} ) func newSendStream( + ctx context.Context, streamID protocol.StreamID, sender streamSender, flowController flowcontrol.StreamFlowController, @@ -71,7 +80,7 @@ func newSendStream( writeChan: make(chan struct{}, 1), writeOnce: make(chan struct{}, 1), // cap: 1, to protect against concurrent use of Write } - s.ctx, s.ctxCancel = context.WithCancelCause(context.Background()) + s.ctx, s.ctxCancel = context.WithCancelCause(ctx) return s } @@ -86,23 +95,32 @@ func (s *sendStream) Write(p []byte) (int, error) { s.writeOnce <- struct{}{} defer func() { <-s.writeOnce }() + isNewlyCompleted, n, err := s.write(p) + if isNewlyCompleted { + s.sender.onStreamCompleted(s.streamID) + } + return n, err +} + +func (s *sendStream) write(p []byte) (bool /* is newly completed */, int, error) { s.mutex.Lock() defer s.mutex.Unlock() if s.finishedWriting { - return 0, fmt.Errorf("write on closed stream %d", s.streamID) + return false, 0, fmt.Errorf("write on closed stream %d", s.streamID) } if s.cancelWriteErr != nil { - return 0, s.cancelWriteErr + s.cancellationFlagged = true + return s.isNewlyCompleted(), 0, s.cancelWriteErr } if s.closeForShutdownErr != nil { - return 0, s.closeForShutdownErr + return false, 0, s.closeForShutdownErr } if !s.deadline.IsZero() && !time.Now().Before(s.deadline) { - return 0, errDeadline + return false, 0, errDeadline } if len(p) == 0 { - return 0, nil + return false, 0, nil } s.dataForWriting = p @@ -143,7 +161,7 @@ func (s *sendStream) Write(p []byte) (int, error) { if !deadline.IsZero() { if !time.Now().Before(deadline) { s.dataForWriting = nil - return bytesWritten, errDeadline + return false, bytesWritten, errDeadline } if deadlineTimer == nil { deadlineTimer = utils.NewTimer() @@ -158,7 +176,7 @@ func (s *sendStream) Write(p []byte) (int, error) { s.mutex.Unlock() if !notifiedSender { - s.sender.onHasStreamData(s.streamID) // must be called without holding the mutex + s.sender.onHasStreamData(s.streamID, s) // must be called without holding the mutex notifiedSender = true } if copied { @@ -178,14 +196,15 @@ func (s *sendStream) Write(p []byte) (int, error) { } if bytesWritten == len(p) { - return bytesWritten, nil + return false, bytesWritten, nil } if s.closeForShutdownErr != nil { - return bytesWritten, s.closeForShutdownErr + return false, bytesWritten, s.closeForShutdownErr } else if s.cancelWriteErr != nil { - return bytesWritten, s.cancelWriteErr + s.cancellationFlagged = true + return s.isNewlyCompleted(), bytesWritten, s.cancelWriteErr } - return bytesWritten, nil + return false, bytesWritten, nil } func (s *sendStream) canBufferStreamFrame() bool { @@ -200,12 +219,15 @@ func (s *sendStream) canBufferStreamFrame() bool { // maxBytes is the maximum length this frame (including frame header) will have. func (s *sendStream) popStreamFrame(maxBytes protocol.ByteCount, v protocol.Version) (af ackhandler.StreamFrame, ok, hasMore bool) { s.mutex.Lock() - f, hasMoreData := s.popNewOrRetransmittedStreamFrame(maxBytes, v) + f, hasMoreData, queuedControlFrame := s.popNewOrRetransmittedStreamFrame(maxBytes, v) if f != nil { s.numOutstandingFrames++ } s.mutex.Unlock() + if queuedControlFrame { + s.sender.onHasStreamControlFrame(s.streamID, s) + } if f == nil { return ackhandler.StreamFrame{}, false, hasMoreData } @@ -215,20 +237,20 @@ func (s *sendStream) popStreamFrame(maxBytes protocol.ByteCount, v protocol.Vers }, true, hasMoreData } -func (s *sendStream) popNewOrRetransmittedStreamFrame(maxBytes protocol.ByteCount, v protocol.Version) (*wire.StreamFrame, bool /* has more data to send */) { +func (s *sendStream) popNewOrRetransmittedStreamFrame(maxBytes protocol.ByteCount, v protocol.Version) (_ *wire.StreamFrame, hasMoreData, queuedControlFrame bool) { if s.cancelWriteErr != nil || s.closeForShutdownErr != nil { - return nil, false + return nil, false, false } if len(s.retransmissionQueue) > 0 { f, hasMoreRetransmissions := s.maybeGetRetransmission(maxBytes, v) if f != nil || hasMoreRetransmissions { if f == nil { - return nil, true + return nil, true, false } // We always claim that we have more data to send. // This might be incorrect, in which case there'll be a spurious call to popStreamFrame in the future. - return f, true + return f, true, false } } @@ -240,21 +262,18 @@ func (s *sendStream) popNewOrRetransmittedStreamFrame(maxBytes protocol.ByteCoun Offset: s.writeOffset, DataLenPresent: true, Fin: true, - }, false + }, false, false } - return nil, false + return nil, false, false } sendWindow := s.flowController.SendWindowSize() if sendWindow == 0 { - if isBlocked, offset := s.flowController.IsNewlyBlocked(); isBlocked { - s.sender.queueControlFrame(&wire.StreamDataBlockedFrame{ - StreamID: s.streamID, - MaximumStreamData: offset, - }) - return nil, false + if s.flowController.IsNewlyBlocked() { + s.queuedBlockedFrame = true + return nil, false, true } - return nil, true + return nil, true, false } f, hasMoreData := s.popNewStreamFrame(maxBytes, sendWindow, v) @@ -266,7 +285,7 @@ func (s *sendStream) popNewOrRetransmittedStreamFrame(maxBytes protocol.ByteCoun if f.Fin { s.finSent = true } - return f, hasMoreData + return f, hasMoreData, false } func (s *sendStream) popNewStreamFrame(maxBytes, sendWindow protocol.ByteCount, v protocol.Version) (*wire.StreamFrame, bool) { @@ -348,8 +367,24 @@ func (s *sendStream) getDataForWriting(f *wire.StreamFrame, maxBytes protocol.By } func (s *sendStream) isNewlyCompleted() bool { - completed := (s.finSent || s.cancelWriteErr != nil) && s.numOutstandingFrames == 0 && len(s.retransmissionQueue) == 0 - if completed && !s.completed { + if s.completed { + return false + } + // We need to keep the stream around until all frames have been sent and acknowledged. + if s.numOutstandingFrames > 0 || len(s.retransmissionQueue) > 0 || s.queuedResetStreamFrame { + return false + } + // The stream is completed if we sent the FIN. + if s.finSent { + s.completed = true + return true + } + // The stream is also completed if: + // 1. the application called CancelWrite, or + // 2. we received a STOP_SENDING, and + // * the application consumed the error via Write, or + // * the application called Close + if s.cancelWriteErr != nil && (s.cancellationFlagged || s.finishedWriting) { s.completed = true return true } @@ -362,15 +397,23 @@ func (s *sendStream) Close() error { s.mutex.Unlock() return nil } - if s.cancelWriteErr != nil { - s.mutex.Unlock() - return fmt.Errorf("close called for canceled stream %d", s.streamID) - } - s.ctxCancel(nil) s.finishedWriting = true + cancelWriteErr := s.cancelWriteErr + if cancelWriteErr != nil { + s.cancellationFlagged = true + } + completed := s.isNewlyCompleted() s.mutex.Unlock() - s.sender.onHasStreamData(s.streamID) // need to send the FIN, must be called without holding the mutex + if completed { + s.sender.onStreamCompleted(s.streamID) + } + if cancelWriteErr != nil { + return fmt.Errorf("close called for canceled stream %d", s.streamID) + } + s.sender.onHasStreamData(s.streamID, s) // need to send the FIN, must be called without holding the mutex + + s.ctxCancel(nil) return nil } @@ -378,9 +421,26 @@ func (s *sendStream) CancelWrite(errorCode StreamErrorCode) { s.cancelWriteImpl(errorCode, false) } -// must be called after locking the mutex func (s *sendStream) cancelWriteImpl(errorCode qerr.StreamErrorCode, remote bool) { s.mutex.Lock() + if s.closeForShutdownErr != nil { + s.mutex.Unlock() + return + } + if !remote { + s.cancellationFlagged = true + if s.cancelWriteErr != nil { + completed := s.isNewlyCompleted() + s.mutex.Unlock() + // The user has called CancelWrite. If the previous cancellation was + // because of a STOP_SENDING, we don't need to flag the error to the + // user anymore. + if completed { + s.sender.onStreamCompleted(s.streamID) + } + return + } + } if s.cancelWriteErr != nil { s.mutex.Unlock() return @@ -389,18 +449,11 @@ func (s *sendStream) cancelWriteImpl(errorCode qerr.StreamErrorCode, remote bool s.ctxCancel(s.cancelWriteErr) s.numOutstandingFrames = 0 s.retransmissionQueue = nil - newlyCompleted := s.isNewlyCompleted() + s.queuedResetStreamFrame = true s.mutex.Unlock() s.signalWrite() - s.sender.queueControlFrame(&wire.ResetStreamFrame{ - StreamID: s.streamID, - FinalSize: s.writeOffset, - ErrorCode: errorCode, - }) - if newlyCompleted { - s.sender.onStreamCompleted(s.streamID) - } + s.sender.onHasStreamControlFrame(s.streamID, s) } func (s *sendStream) updateSendWindow(limit protocol.ByteCount) { @@ -412,7 +465,7 @@ func (s *sendStream) updateSendWindow(limit protocol.ByteCount) { hasStreamData := s.dataForWriting != nil || s.nextFrame != nil s.mutex.Unlock() if hasStreamData { - s.sender.onHasStreamData(s.streamID) + s.sender.onHasStreamData(s.streamID, s) } } @@ -420,6 +473,32 @@ func (s *sendStream) handleStopSendingFrame(frame *wire.StopSendingFrame) { s.cancelWriteImpl(frame.ErrorCode, true) } +func (s *sendStream) getControlFrame() (_ ackhandler.Frame, ok, hasMore bool) { + s.mutex.Lock() + defer s.mutex.Unlock() + + if !s.queuedBlockedFrame && !s.queuedResetStreamFrame { + return ackhandler.Frame{}, false, false + } + if s.queuedBlockedFrame { + s.queuedBlockedFrame = false + return ackhandler.Frame{ + Frame: &wire.StreamDataBlockedFrame{StreamID: s.streamID, MaximumStreamData: s.writeOffset}, + }, true, s.queuedResetStreamFrame + } + // RESET_STREAM frame + s.queuedResetStreamFrame = false + s.numOutstandingFrames++ + return ackhandler.Frame{ + Frame: &wire.ResetStreamFrame{ + StreamID: s.streamID, + FinalSize: s.writeOffset, + ErrorCode: s.cancelWriteErr.ErrorCode, + }, + Handler: (*sendStreamResetStreamHandler)(s), + }, true, false +} + func (s *sendStream) Context() context.Context { return s.ctx } @@ -437,7 +516,6 @@ func (s *sendStream) SetWriteDeadline(t time.Time) error { // The peer will NOT be informed about this: the stream is closed without sending a FIN or RST. func (s *sendStream) closeForShutdown(err error) { s.mutex.Lock() - s.ctxCancel(err) s.closeForShutdownErr = err s.mutex.Unlock() s.signalWrite() @@ -467,10 +545,10 @@ func (s *sendStreamAckHandler) OnAcked(f wire.Frame) { if s.numOutstandingFrames < 0 { panic("numOutStandingFrames negative") } - newlyCompleted := (*sendStream)(s).isNewlyCompleted() + completed := (*sendStream)(s).isNewlyCompleted() s.mutex.Unlock() - if newlyCompleted { + if completed { s.sender.onStreamCompleted(s.streamID) } } @@ -490,5 +568,30 @@ func (s *sendStreamAckHandler) OnLost(f wire.Frame) { } s.mutex.Unlock() - s.sender.onHasStreamData(s.streamID) + s.sender.onHasStreamData(s.streamID, (*sendStream)(s)) +} + +type sendStreamResetStreamHandler sendStream + +var _ ackhandler.FrameHandler = &sendStreamResetStreamHandler{} + +func (s *sendStreamResetStreamHandler) OnAcked(wire.Frame) { + s.mutex.Lock() + s.numOutstandingFrames-- + if s.numOutstandingFrames < 0 { + panic("numOutStandingFrames negative") + } + completed := (*sendStream)(s).isNewlyCompleted() + s.mutex.Unlock() + + if completed { + s.sender.onStreamCompleted(s.streamID) + } +} + +func (s *sendStreamResetStreamHandler) OnLost(wire.Frame) { + s.mutex.Lock() + s.queuedResetStreamFrame = true + s.mutex.Unlock() + s.sender.onHasStreamControlFrame(s.streamID, (*sendStream)(s)) } diff --git a/vendor/github.com/quic-go/quic-go/server.go b/vendor/github.com/quic-go/quic-go/server.go index afbd18fd2..0cf45acaf 100644 --- a/vendor/github.com/quic-go/quic-go/server.go +++ b/vendor/github.com/quic-go/quic-go/server.go @@ -18,7 +18,12 @@ import ( ) // ErrServerClosed is returned by the Listener or EarlyListener's Accept method after a call to Close. -var ErrServerClosed = errors.New("quic: server closed") +var ErrServerClosed = errServerClosed{} + +type errServerClosed struct{} + +func (errServerClosed) Error() string { return "quic: server closed" } +func (errServerClosed) Unwrap() error { return net.ErrClosed } // packetHandler handles packets type packetHandler interface { @@ -76,8 +81,12 @@ type baseServer struct { nextZeroRTTCleanup time.Time zeroRTTQueues map[protocol.ConnectionID]*zeroRTTQueue // only initialized if acceptEarlyConns == true + connContext func(context.Context) context.Context + // set as a member, so they can be set in the tests newConn func( + context.Context, + context.CancelCauseFunc, sendConn, connRunner, protocol.ConnectionID, /* original dest connection ID */ @@ -92,7 +101,6 @@ type baseServer struct { *handshake.TokenGenerator, bool, /* client address validated by an address validation token */ *logging.ConnectionTracer, - uint64, utils.Logger, protocol.Version, ) quicConn @@ -231,6 +239,7 @@ func newServer( conn rawConn, connHandler packetHandlerManager, connIDGenerator ConnectionIDGenerator, + connContext func(context.Context) context.Context, tlsConf *tls.Config, config *Config, tracer *logging.Tracer, @@ -243,6 +252,7 @@ func newServer( ) *baseServer { s := &baseServer{ conn: conn, + connContext: connContext, tlsConf: tlsConf, config: config, tokenGenerator: handshake.NewTokenGenerator(tokenGeneratorKey), @@ -631,7 +641,26 @@ func (s *baseServer) handleInitialImpl(p receivedPacket, hdr *wire.Header) error } var conn quicConn - tracingID := nextConnTracingID() + var cancel context.CancelCauseFunc + ctx, cancel1 := context.WithCancelCause(context.Background()) + if s.connContext != nil { + ctx = s.connContext(ctx) + if ctx == nil { + panic("quic: ConnContext returned nil") + } + // There's no guarantee that the application returns a context + // that's derived from the context we passed into ConnContext. + // We need to make sure that both contexts are cancelled. + var cancel2 context.CancelCauseFunc + ctx, cancel2 = context.WithCancelCause(ctx) + cancel = func(cause error) { + cancel1(cause) + cancel2(cause) + } + } else { + cancel = cancel1 + } + ctx = context.WithValue(ctx, ConnectionTracingKey, nextConnTracingID()) var tracer *logging.ConnectionTracer if config.Tracer != nil { // Use the same connection ID that is passed to the client's GetLogWriter callback. @@ -639,7 +668,7 @@ func (s *baseServer) handleInitialImpl(p receivedPacket, hdr *wire.Header) error if origDestConnID.Len() > 0 { connID = origDestConnID } - tracer = config.Tracer(context.WithValue(context.Background(), ConnectionTracingKey, tracingID), protocol.PerspectiveServer, connID) + tracer = config.Tracer(ctx, protocol.PerspectiveServer, connID) } connID, err := s.connIDGenerator.GenerateConnectionID() if err != nil { @@ -647,6 +676,8 @@ func (s *baseServer) handleInitialImpl(p receivedPacket, hdr *wire.Header) error } s.logger.Debugf("Changing connection ID to %s.", connID) conn = s.newConn( + ctx, + cancel, newSendConn(s.conn, p.remoteAddr, p.info, s.logger), s.connHandler, origDestConnID, @@ -661,7 +692,6 @@ func (s *baseServer) handleInitialImpl(p receivedPacket, hdr *wire.Header) error s.tokenGenerator, clientAddrVerified, tracer, - tracingID, s.logger, hdr.Version, ) @@ -778,7 +808,7 @@ func (s *baseServer) maybeSendInvalidToken(p rejectedPacket) { hdr := p.hdr sealer, opener := handshake.NewInitialAEAD(hdr.DestConnectionID, protocol.PerspectiveServer, hdr.Version) data := p.data[:hdr.ParsedLen()+hdr.Length] - extHdr, err := unpackLongHeader(opener, hdr, data, hdr.Version) + extHdr, err := unpackLongHeader(opener, hdr, data) // Only send INVALID_TOKEN if we can unprotect the packet. // This makes sure that we won't send it for packets that were corrupted. if err != nil { diff --git a/vendor/github.com/quic-go/quic-go/stream.go b/vendor/github.com/quic-go/quic-go/stream.go index ce4374d60..1ed263233 100644 --- a/vendor/github.com/quic-go/quic-go/stream.go +++ b/vendor/github.com/quic-go/quic-go/stream.go @@ -1,6 +1,7 @@ package quic import ( + "context" "net" "os" "sync" @@ -23,8 +24,8 @@ var errDeadline net.Error = &deadlineError{} // The streamSender is notified by the stream about various events. type streamSender interface { - queueControlFrame(wire.Frame) - onHasStreamData(protocol.StreamID) + onHasStreamData(protocol.StreamID, sendStreamI) + onHasStreamControlFrame(protocol.StreamID, streamControlFrameGetter) // must be called without holding the mutex that is acquired by closeForShutdown onStreamCompleted(protocol.StreamID) } @@ -33,19 +34,16 @@ type streamSender interface { // This is necessary in order to keep track when both halves have been completed. type uniStreamSender struct { streamSender - onStreamCompletedImpl func() + onStreamCompletedImpl func() + onHasStreamControlFrameImpl func(protocol.StreamID, streamControlFrameGetter) } -func (s *uniStreamSender) queueControlFrame(f wire.Frame) { - s.streamSender.queueControlFrame(f) +func (s *uniStreamSender) onHasStreamData(id protocol.StreamID, str sendStreamI) { + s.streamSender.onHasStreamData(id, str) } - -func (s *uniStreamSender) onHasStreamData(id protocol.StreamID) { - s.streamSender.onHasStreamData(id) -} - -func (s *uniStreamSender) onStreamCompleted(protocol.StreamID) { - s.onStreamCompletedImpl() +func (s *uniStreamSender) onStreamCompleted(protocol.StreamID) { s.onStreamCompletedImpl() } +func (s *uniStreamSender) onHasStreamControlFrame(id protocol.StreamID, str streamControlFrameGetter) { + s.onHasStreamControlFrameImpl(id, str) } var _ streamSender = &uniStreamSender{} @@ -56,7 +54,6 @@ type streamI interface { // for receiving handleStreamFrame(*wire.StreamFrame) error handleResetStreamFrame(*wire.ResetStreamFrame) error - getWindowUpdate() protocol.ByteCount // for sending hasData() bool handleStopSendingFrame(*wire.StopSendingFrame) @@ -82,10 +79,15 @@ type stream struct { sendStreamCompleted bool } -var _ Stream = &stream{} +var ( + _ Stream = &stream{} + _ streamControlFrameGetter = &receiveStream{} +) // newStream creates a new Stream -func newStream(streamID protocol.StreamID, +func newStream( + ctx context.Context, + streamID protocol.StreamID, sender streamSender, flowController flowcontrol.StreamFlowController, ) *stream { @@ -98,8 +100,11 @@ func newStream(streamID protocol.StreamID, s.checkIfCompleted() s.completedMutex.Unlock() }, + onHasStreamControlFrameImpl: func(id protocol.StreamID, str streamControlFrameGetter) { + sender.onHasStreamControlFrame(streamID, s) + }, } - s.sendStream = *newSendStream(streamID, senderForSendStream, flowController) + s.sendStream = *newSendStream(ctx, streamID, senderForSendStream, flowController) senderForReceiveStream := &uniStreamSender{ streamSender: sender, onStreamCompletedImpl: func() { @@ -108,6 +113,9 @@ func newStream(streamID protocol.StreamID, s.checkIfCompleted() s.completedMutex.Unlock() }, + onHasStreamControlFrameImpl: func(id protocol.StreamID, str streamControlFrameGetter) { + sender.onHasStreamControlFrame(streamID, s) + }, } s.receiveStream = *newReceiveStream(streamID, senderForReceiveStream, flowController) return s @@ -123,6 +131,14 @@ func (s *stream) Close() error { return s.sendStream.Close() } +func (s *stream) getControlFrame() (_ ackhandler.Frame, ok, hasMore bool) { + f, ok, _ := s.sendStream.getControlFrame() + if ok { + return f, true, true + } + return s.receiveStream.getControlFrame() +} + func (s *stream) SetDeadline(t time.Time) error { _ = s.SetReadDeadline(t) // SetReadDeadline never errors _ = s.SetWriteDeadline(t) // SetWriteDeadline never errors diff --git a/vendor/github.com/quic-go/quic-go/streams_map.go b/vendor/github.com/quic-go/quic-go/streams_map.go index b1a80eb36..0ce91287b 100644 --- a/vendor/github.com/quic-go/quic-go/streams_map.go +++ b/vendor/github.com/quic-go/quic-go/streams_map.go @@ -38,19 +38,31 @@ type streamOpenErr struct{ error } var _ net.Error = &streamOpenErr{} -func (e streamOpenErr) Temporary() bool { return e.error == errTooManyOpenStreams } -func (streamOpenErr) Timeout() bool { return false } +func (streamOpenErr) Timeout() bool { return false } +func (e streamOpenErr) Unwrap() error { return e.error } -// errTooManyOpenStreams is used internally by the outgoing streams maps. -var errTooManyOpenStreams = errors.New("too many open streams") +func (e streamOpenErr) Temporary() bool { + // In older versions of quic-go, the stream limit error was documented to be a net.Error.Temporary. + // This function was since deprecated, but we keep the existing behavior. + return errors.Is(e, &StreamLimitReachedError{}) +} + +// StreamLimitReachedError is returned from Connection.OpenStream and Connection.OpenUniStream +// when it is not possible to open a new stream because the number of opens streams reached +// the peer's stream limit. +type StreamLimitReachedError struct{} + +func (e StreamLimitReachedError) Error() string { return "too many open streams" } type streamsMap struct { + ctx context.Context // not used for cancellations, but carries the values associated with the connection perspective protocol.Perspective maxIncomingBidiStreams uint64 maxIncomingUniStreams uint64 sender streamSender + queueControlFrame func(wire.Frame) newFlowController func(protocol.StreamID) flowcontrol.StreamFlowController mutex sync.Mutex @@ -64,14 +76,18 @@ type streamsMap struct { var _ streamManager = &streamsMap{} func newStreamsMap( + ctx context.Context, sender streamSender, + queueControlFrame func(wire.Frame), newFlowController func(protocol.StreamID) flowcontrol.StreamFlowController, maxIncomingBidiStreams uint64, maxIncomingUniStreams uint64, perspective protocol.Perspective, -) streamManager { +) *streamsMap { m := &streamsMap{ + ctx: ctx, perspective: perspective, + queueControlFrame: queueControlFrame, newFlowController: newFlowController, maxIncomingBidiStreams: maxIncomingBidiStreams, maxIncomingUniStreams: maxIncomingUniStreams, @@ -86,26 +102,26 @@ func (m *streamsMap) initMaps() { protocol.StreamTypeBidi, func(num protocol.StreamNum) streamI { id := num.StreamID(protocol.StreamTypeBidi, m.perspective) - return newStream(id, m.sender, m.newFlowController(id)) + return newStream(m.ctx, id, m.sender, m.newFlowController(id)) }, - m.sender.queueControlFrame, + m.queueControlFrame, ) m.incomingBidiStreams = newIncomingStreamsMap( protocol.StreamTypeBidi, func(num protocol.StreamNum) streamI { id := num.StreamID(protocol.StreamTypeBidi, m.perspective.Opposite()) - return newStream(id, m.sender, m.newFlowController(id)) + return newStream(m.ctx, id, m.sender, m.newFlowController(id)) }, m.maxIncomingBidiStreams, - m.sender.queueControlFrame, + m.queueControlFrame, ) m.outgoingUniStreams = newOutgoingStreamsMap( protocol.StreamTypeUni, func(num protocol.StreamNum) sendStreamI { id := num.StreamID(protocol.StreamTypeUni, m.perspective) - return newSendStream(id, m.sender, m.newFlowController(id)) + return newSendStream(m.ctx, id, m.sender, m.newFlowController(id)) }, - m.sender.queueControlFrame, + m.queueControlFrame, ) m.incomingUniStreams = newIncomingStreamsMap( protocol.StreamTypeUni, @@ -114,7 +130,7 @@ func (m *streamsMap) initMaps() { return newReceiveStream(id, m.sender, m.newFlowController(id)) }, m.maxIncomingUniStreams, - m.sender.queueControlFrame, + m.queueControlFrame, ) } diff --git a/vendor/github.com/quic-go/quic-go/streams_map_outgoing.go b/vendor/github.com/quic-go/quic-go/streams_map_outgoing.go index fd45f4e7c..a8d04b04f 100644 --- a/vendor/github.com/quic-go/quic-go/streams_map_outgoing.go +++ b/vendor/github.com/quic-go/quic-go/streams_map_outgoing.go @@ -60,7 +60,7 @@ func (m *outgoingStreamsMap[T]) OpenStream() (T, error) { // if there are OpenStreamSync calls waiting, return an error here if len(m.openQueue) > 0 || m.nextStream > m.maxStream { m.maybeSendBlockedFrame() - return *new(T), streamOpenErr{errTooManyOpenStreams} + return *new(T), streamOpenErr{&StreamLimitReachedError{}} } return m.openStream(), nil } diff --git a/vendor/github.com/quic-go/quic-go/sys_conn_helper_darwin.go b/vendor/github.com/quic-go/quic-go/sys_conn_helper_darwin.go index d761072f2..545502dda 100644 --- a/vendor/github.com/quic-go/quic-go/sys_conn_helper_darwin.go +++ b/vendor/github.com/quic-go/quic-go/sys_conn_helper_darwin.go @@ -33,4 +33,6 @@ func parseIPv4PktInfo(body []byte) (ip netip.Addr, ifIndex uint32, ok bool) { return netip.AddrFrom4(*(*[4]byte)(body[8:12])), binary.LittleEndian.Uint32(body), true } -func isGSOSupported(syscall.RawConn) bool { return false } +func isGSOEnabled(syscall.RawConn) bool { return false } + +func isECNEnabled() bool { return !isECNDisabledUsingEnv() } diff --git a/vendor/github.com/quic-go/quic-go/sys_conn_helper_freebsd.go b/vendor/github.com/quic-go/quic-go/sys_conn_helper_freebsd.go index a53ca2eae..521f80d46 100644 --- a/vendor/github.com/quic-go/quic-go/sys_conn_helper_freebsd.go +++ b/vendor/github.com/quic-go/quic-go/sys_conn_helper_freebsd.go @@ -28,4 +28,6 @@ func parseIPv4PktInfo(body []byte) (ip netip.Addr, _ uint32, ok bool) { return netip.AddrFrom4(*(*[4]byte)(body)), 0, true } -func isGSOSupported(syscall.RawConn) bool { return false } +func isGSOEnabled(syscall.RawConn) bool { return false } + +func isECNEnabled() bool { return !isECNDisabledUsingEnv() } diff --git a/vendor/github.com/quic-go/quic-go/sys_conn_helper_linux.go b/vendor/github.com/quic-go/quic-go/sys_conn_helper_linux.go index 5fbf34ade..eec127197 100644 --- a/vendor/github.com/quic-go/quic-go/sys_conn_helper_linux.go +++ b/vendor/github.com/quic-go/quic-go/sys_conn_helper_linux.go @@ -23,6 +23,12 @@ const ecnIPv4DataLen = 1 const batchSize = 8 // needs to smaller than MaxUint8 (otherwise the type of oobConn.readPos has to be changed) +var kernelVersionMajor int + +func init() { + kernelVersionMajor, _ = kernelVersion() +} + func forceSetReceiveBuffer(c syscall.RawConn, bytes int) error { var serr error if err := c.Control(func(fd uintptr) { @@ -55,9 +61,12 @@ func parseIPv4PktInfo(body []byte) (ip netip.Addr, ifIndex uint32, ok bool) { return netip.AddrFrom4(*(*[4]byte)(body[8:12])), binary.LittleEndian.Uint32(body), true } -// isGSOSupported tests if the kernel supports GSO. +// isGSOEnabled tests if the kernel supports GSO. // Sending with GSO might still fail later on, if the interface doesn't support it (see isGSOError). -func isGSOSupported(conn syscall.RawConn) bool { +func isGSOEnabled(conn syscall.RawConn) bool { + if kernelVersionMajor < 5 { + return false + } disabled, err := strconv.ParseBool(os.Getenv("QUIC_GO_DISABLE_GSO")) if err == nil && disabled { return false @@ -108,3 +117,40 @@ func isPermissionError(err error) bool { } return false } + +func isECNEnabled() bool { + return kernelVersionMajor >= 5 && !isECNDisabledUsingEnv() +} + +// kernelVersion returns major and minor kernel version numbers, parsed from +// the syscall.Uname's Release field, or 0, 0 if the version can't be obtained +// or parsed. +// +// copied from the standard library's internal/syscall/unix/kernel_version_linux.go +func kernelVersion() (major, minor int) { + var uname syscall.Utsname + if err := syscall.Uname(&uname); err != nil { + return + } + + var ( + values [2]int + value, vi int + ) + for _, c := range uname.Release { + if '0' <= c && c <= '9' { + value = (value * 10) + int(c-'0') + } else { + // Note that we're assuming N.N.N here. + // If we see anything else, we are likely to mis-parse it. + values[vi] = value + vi++ + if vi >= len(values) { + break + } + value = 0 + } + } + + return values[0], values[1] +} diff --git a/vendor/github.com/quic-go/quic-go/sys_conn_oob.go b/vendor/github.com/quic-go/quic-go/sys_conn_oob.go index 64d581c06..a6795ca26 100644 --- a/vendor/github.com/quic-go/quic-go/sys_conn_oob.go +++ b/vendor/github.com/quic-go/quic-go/sys_conn_oob.go @@ -59,7 +59,7 @@ func inspectWriteBuffer(c syscall.RawConn) (int, error) { return size, serr } -func isECNDisabled() bool { +func isECNDisabledUsingEnv() bool { disabled, err := strconv.ParseBool(os.Getenv("QUIC_GO_DISABLE_ECN")) return err == nil && disabled } @@ -147,8 +147,8 @@ func newConn(c OOBCapablePacketConn, supportsDF bool) (*oobConn, error) { readPos: batchSize, cap: connCapabilities{ DF: supportsDF, - GSO: isGSOSupported(rawConn), - ECN: !isECNDisabled(), + GSO: isGSOEnabled(rawConn), + ECN: isECNEnabled(), }, } for i := 0; i < batchSize; i++ { @@ -247,7 +247,7 @@ func (c *oobConn) WritePacket(b []byte, addr net.Addr, packetInfoOOB []byte, gso } if ecn != protocol.ECNUnsupported { if !c.capabilities().ECN { - panic("tried to send a ECN-marked packet although ECN is disabled") + panic("tried to send an ECN-marked packet although ECN is disabled") } if remoteUDPAddr, ok := addr.(*net.UDPAddr); ok { if remoteUDPAddr.IP.To4() != nil { diff --git a/vendor/github.com/quic-go/quic-go/transport.go b/vendor/github.com/quic-go/quic-go/transport.go index ea219c112..059f30f5b 100644 --- a/vendor/github.com/quic-go/quic-go/transport.go +++ b/vendor/github.com/quic-go/quic-go/transport.go @@ -89,6 +89,17 @@ type Transport struct { // implementation of this callback (negating its return value). VerifySourceAddress func(net.Addr) bool + // ConnContext is called when the server accepts a new connection. + // The context is closed when the connection is closed, or when the handshake fails for any reason. + // The context returned from the callback is used to derive every other context used during the + // lifetime of the connection: + // * the context passed to crypto/tls (and used on the tls.ClientHelloInfo) + // * the context used in Config.Tracer + // * the context returned from Connection.Context + // * the context returned from SendStream.Context + // It is not used for dialed connections. + ConnContext func(context.Context) context.Context + // A Tracer traces events that don't belong to a single QUIC connection. // Tracer.Close is called when the transport is closed. Tracer *logging.Tracer @@ -168,6 +179,7 @@ func (t *Transport) createServer(tlsConf *tls.Config, conf *Config, allow0RTT bo t.conn, t.handlerMap, t.connIDGenerator, + t.ConnContext, tlsConf, conf, t.Tracer, diff --git a/vendor/github.com/quic-go/quic-go/window_update_queue.go b/vendor/github.com/quic-go/quic-go/window_update_queue.go deleted file mode 100644 index 9ed121430..000000000 --- a/vendor/github.com/quic-go/quic-go/window_update_queue.go +++ /dev/null @@ -1,71 +0,0 @@ -package quic - -import ( - "sync" - - "github.com/quic-go/quic-go/internal/flowcontrol" - "github.com/quic-go/quic-go/internal/protocol" - "github.com/quic-go/quic-go/internal/wire" -) - -type windowUpdateQueue struct { - mutex sync.Mutex - - queue map[protocol.StreamID]struct{} // used as a set - queuedConn bool // connection-level window update - - streamGetter streamGetter - connFlowController flowcontrol.ConnectionFlowController - callback func(wire.Frame) -} - -func newWindowUpdateQueue( - streamGetter streamGetter, - connFC flowcontrol.ConnectionFlowController, - cb func(wire.Frame), -) *windowUpdateQueue { - return &windowUpdateQueue{ - queue: make(map[protocol.StreamID]struct{}), - streamGetter: streamGetter, - connFlowController: connFC, - callback: cb, - } -} - -func (q *windowUpdateQueue) AddStream(id protocol.StreamID) { - q.mutex.Lock() - q.queue[id] = struct{}{} - q.mutex.Unlock() -} - -func (q *windowUpdateQueue) AddConnection() { - q.mutex.Lock() - q.queuedConn = true - q.mutex.Unlock() -} - -func (q *windowUpdateQueue) QueueAll() { - q.mutex.Lock() - // queue a connection-level window update - if q.queuedConn { - q.callback(&wire.MaxDataFrame{MaximumData: q.connFlowController.GetWindowUpdate()}) - q.queuedConn = false - } - // queue all stream-level window updates - for id := range q.queue { - delete(q.queue, id) - str, err := q.streamGetter.GetOrOpenReceiveStream(id) - if err != nil || str == nil { // the stream can be nil if it was completed before dequeing the window update - continue - } - offset := str.getWindowUpdate() - if offset == 0 { // can happen if we received a final offset, right after queueing the window update - continue - } - q.callback(&wire.MaxStreamDataFrame{ - StreamID: id, - MaximumStreamData: offset, - }) - } - q.mutex.Unlock() -} diff --git a/vendor/github.com/ryanuber/go-glob/.travis.yml b/vendor/github.com/ryanuber/go-glob/.travis.yml new file mode 100644 index 000000000..9d1ca3c37 --- /dev/null +++ b/vendor/github.com/ryanuber/go-glob/.travis.yml @@ -0,0 +1,5 @@ +language: go +go: + - tip +script: + - go test -v ./... diff --git a/vendor/github.com/ryanuber/go-glob/LICENSE b/vendor/github.com/ryanuber/go-glob/LICENSE new file mode 100644 index 000000000..bdfbd9514 --- /dev/null +++ b/vendor/github.com/ryanuber/go-glob/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Ryan Uber + +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/ryanuber/go-glob/README.md b/vendor/github.com/ryanuber/go-glob/README.md new file mode 100644 index 000000000..48f7fcb05 --- /dev/null +++ b/vendor/github.com/ryanuber/go-glob/README.md @@ -0,0 +1,29 @@ +# String globbing in golang [![Build Status](https://travis-ci.org/ryanuber/go-glob.svg)](https://travis-ci.org/ryanuber/go-glob) + +`go-glob` is a single-function library implementing basic string glob support. + +Globs are an extremely user-friendly way of supporting string matching without +requiring knowledge of regular expressions or Go's particular regex engine. Most +people understand that if you put a `*` character somewhere in a string, it is +treated as a wildcard. Surprisingly, this functionality isn't found in Go's +standard library, except for `path.Match`, which is intended to be used while +comparing paths (not arbitrary strings), and contains specialized logic for this +use case. A better solution might be a POSIX basic (non-ERE) regular expression +engine for Go, which doesn't exist currently. + +Example +======= + +``` +package main + +import "github.com/ryanuber/go-glob" + +func main() { + glob.Glob("*World!", "Hello, World!") // true + glob.Glob("Hello,*", "Hello, World!") // true + glob.Glob("*ello,*", "Hello, World!") // true + glob.Glob("World!", "Hello, World!") // false + glob.Glob("/home/*", "/home/ryanuber/.bashrc") // true +} +``` diff --git a/vendor/github.com/ryanuber/go-glob/glob.go b/vendor/github.com/ryanuber/go-glob/glob.go new file mode 100644 index 000000000..e67db3be1 --- /dev/null +++ b/vendor/github.com/ryanuber/go-glob/glob.go @@ -0,0 +1,56 @@ +package glob + +import "strings" + +// The character which is treated like a glob +const GLOB = "*" + +// Glob will test a string pattern, potentially containing globs, against a +// subject string. The result is a simple true/false, determining whether or +// not the glob pattern matched the subject text. +func Glob(pattern, subj string) bool { + // Empty pattern can only match empty subject + if pattern == "" { + return subj == pattern + } + + // If the pattern _is_ a glob, it matches everything + if pattern == GLOB { + return true + } + + parts := strings.Split(pattern, GLOB) + + if len(parts) == 1 { + // No globs in pattern, so test for equality + return subj == pattern + } + + leadingGlob := strings.HasPrefix(pattern, GLOB) + trailingGlob := strings.HasSuffix(pattern, GLOB) + end := len(parts) - 1 + + // Go over the leading parts and ensure they match. + for i := 0; i < end; i++ { + idx := strings.Index(subj, parts[i]) + + switch i { + case 0: + // Check the first section. Requires special handling. + if !leadingGlob && idx != 0 { + return false + } + default: + // Check that the middle parts match. + if idx < 0 { + return false + } + } + + // Trim evaluated text from subj as we loop over the pattern. + subj = subj[idx+len(parts[i]):] + } + + // Reached the last section. Requires special handling. + return trailingGlob || strings.HasSuffix(subj, parts[end]) +} diff --git a/vendor/github.com/spf13/cobra/.golangci.yml b/vendor/github.com/spf13/cobra/.golangci.yml index 2578d94b5..2c8f4808c 100644 --- a/vendor/github.com/spf13/cobra/.golangci.yml +++ b/vendor/github.com/spf13/cobra/.golangci.yml @@ -19,44 +19,39 @@ linters: disable-all: true enable: #- bodyclose - - deadcode + # - deadcode ! deprecated since v1.49.0; replaced by 'unused' #- depguard #- dogsled #- dupl - errcheck #- exhaustive #- funlen - - gas #- gochecknoinits - goconst - #- gocritic + - gocritic #- gocyclo - #- gofmt + - gofmt - goimports - - golint #- gomnd #- goprintffuncname - #- gosec - #- gosimple + - gosec + - gosimple - govet - ineffassign - - interfacer #- lll - - maligned - - megacheck - #- misspell + - misspell #- nakedret #- noctx - #- nolintlint + - nolintlint #- rowserrcheck #- scopelint - #- staticcheck - - structcheck - #- stylecheck + - staticcheck + #- structcheck ! deprecated since v1.49.0; replaced by 'unused' + - stylecheck #- typecheck - unconvert #- unparam - #- unused - - varcheck + - unused + # - varcheck ! deprecated since v1.49.0; replaced by 'unused' #- whitespace fast: false diff --git a/vendor/github.com/spf13/cobra/README.md b/vendor/github.com/spf13/cobra/README.md index 592c0b8ab..6444f4b7f 100644 --- a/vendor/github.com/spf13/cobra/README.md +++ b/vendor/github.com/spf13/cobra/README.md @@ -4,7 +4,7 @@ Cobra is a library for creating powerful modern CLI applications. Cobra is used in many Go projects such as [Kubernetes](https://kubernetes.io/), [Hugo](https://gohugo.io), and [GitHub CLI](https://github.com/cli/cli) to -name a few. [This list](./projects_using_cobra.md) contains a more extensive list of projects using Cobra. +name a few. [This list](site/content/projects_using_cobra.md) contains a more extensive list of projects using Cobra. [![](https://img.shields.io/github/actions/workflow/status/spf13/cobra/test.yml?branch=main&longCache=true&label=Test&logo=github%20actions&logoColor=fff)](https://github.com/spf13/cobra/actions?query=workflow%3ATest) [![Go Reference](https://pkg.go.dev/badge/github.com/spf13/cobra.svg)](https://pkg.go.dev/github.com/spf13/cobra) @@ -80,7 +80,7 @@ which maintains the same interface while adding POSIX compliance. # Installing Using Cobra is easy. First, use `go get` to install the latest version -of the library. +of the library. ``` go get -u github.com/spf13/cobra@latest @@ -105,8 +105,8 @@ go install github.com/spf13/cobra-cli@latest For complete details on using the Cobra-CLI generator, please read [The Cobra Generator README](https://github.com/spf13/cobra-cli/blob/main/README.md) -For complete details on using the Cobra library, please read the [The Cobra User Guide](user_guide.md). +For complete details on using the Cobra library, please read the [The Cobra User Guide](site/content/user_guide.md). # License -Cobra is released under the Apache 2.0 license. See [LICENSE.txt](https://github.com/spf13/cobra/blob/master/LICENSE.txt) +Cobra is released under the Apache 2.0 license. See [LICENSE.txt](LICENSE.txt) diff --git a/vendor/github.com/spf13/cobra/active_help.go b/vendor/github.com/spf13/cobra/active_help.go index 2d0239437..25c30e3cc 100644 --- a/vendor/github.com/spf13/cobra/active_help.go +++ b/vendor/github.com/spf13/cobra/active_help.go @@ -17,15 +17,14 @@ package cobra import ( "fmt" "os" - "strings" ) const ( activeHelpMarker = "_activeHelp_ " // The below values should not be changed: programs will be using them explicitly // in their user documentation, and users will be using them explicitly. - activeHelpEnvVarSuffix = "_ACTIVE_HELP" - activeHelpGlobalEnvVar = "COBRA_ACTIVE_HELP" + activeHelpEnvVarSuffix = "ACTIVE_HELP" + activeHelpGlobalEnvVar = configEnvVarGlobalPrefix + "_" + activeHelpEnvVarSuffix activeHelpGlobalDisable = "0" ) @@ -42,7 +41,7 @@ func AppendActiveHelp(compArray []string, activeHelpStr string) []string { // GetActiveHelpConfig returns the value of the ActiveHelp environment variable // _ACTIVE_HELP where is the name of the root command in upper -// case, with all - replaced by _. +// case, with all non-ASCII-alphanumeric characters replaced by `_`. // It will always return "0" if the global environment variable COBRA_ACTIVE_HELP // is set to "0". func GetActiveHelpConfig(cmd *Command) string { @@ -55,9 +54,7 @@ func GetActiveHelpConfig(cmd *Command) string { // activeHelpEnvVar returns the name of the program-specific ActiveHelp environment // variable. It has the format _ACTIVE_HELP where is the name of the -// root command in upper case, with all - replaced by _. +// root command in upper case, with all non-ASCII-alphanumeric characters replaced by `_`. func activeHelpEnvVar(name string) string { - // This format should not be changed: users will be using it explicitly. - activeHelpEnvVar := strings.ToUpper(fmt.Sprintf("%s%s", name, activeHelpEnvVarSuffix)) - return strings.ReplaceAll(activeHelpEnvVar, "-", "_") + return configEnvVar(name, activeHelpEnvVarSuffix) } diff --git a/vendor/github.com/spf13/cobra/active_help.md b/vendor/github.com/spf13/cobra/active_help.md deleted file mode 100644 index 5e7f59af3..000000000 --- a/vendor/github.com/spf13/cobra/active_help.md +++ /dev/null @@ -1,157 +0,0 @@ -# Active Help - -Active Help is a framework provided by Cobra which allows a program to define messages (hints, warnings, etc) that will be printed during program usage. It aims to make it easier for your users to learn how to use your program. If configured by the program, Active Help is printed when the user triggers shell completion. - -For example, -``` -bash-5.1$ helm repo add [tab] -You must choose a name for the repo you are adding. - -bash-5.1$ bin/helm package [tab] -Please specify the path to the chart to package - -bash-5.1$ bin/helm package [tab][tab] -bin/ internal/ scripts/ pkg/ testdata/ -``` - -**Hint**: A good place to use Active Help messages is when the normal completion system does not provide any suggestions. In such cases, Active Help nicely supplements the normal shell completions to guide the user in knowing what is expected by the program. -## Supported shells - -Active Help is currently only supported for the following shells: -- Bash (using [bash completion V2](shell_completions.md#bash-completion-v2) only). Note that bash 4.4 or higher is required for the prompt to appear when an Active Help message is printed. -- Zsh - -## Adding Active Help messages - -As Active Help uses the shell completion system, the implementation of Active Help messages is done by enhancing custom dynamic completions. If you are not familiar with dynamic completions, please refer to [Shell Completions](shell_completions.md). - -Adding Active Help is done through the use of the `cobra.AppendActiveHelp(...)` function, where the program repeatedly adds Active Help messages to the list of completions. Keep reading for details. - -### Active Help for nouns - -Adding Active Help when completing a noun is done within the `ValidArgsFunction(...)` of a command. Please notice the use of `cobra.AppendActiveHelp(...)` in the following example: - -```go -cmd := &cobra.Command{ - Use: "add [NAME] [URL]", - Short: "add a chart repository", - Args: require.ExactArgs(2), - RunE: func(cmd *cobra.Command, args []string) error { - return addRepo(args) - }, - ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - var comps []string - if len(args) == 0 { - comps = cobra.AppendActiveHelp(comps, "You must choose a name for the repo you are adding") - } else if len(args) == 1 { - comps = cobra.AppendActiveHelp(comps, "You must specify the URL for the repo you are adding") - } else { - comps = cobra.AppendActiveHelp(comps, "This command does not take any more arguments") - } - return comps, cobra.ShellCompDirectiveNoFileComp - }, -} -``` -The example above defines the completions (none, in this specific example) as well as the Active Help messages for the `helm repo add` command. It yields the following behavior: -``` -bash-5.1$ helm repo add [tab] -You must choose a name for the repo you are adding - -bash-5.1$ helm repo add grafana [tab] -You must specify the URL for the repo you are adding - -bash-5.1$ helm repo add grafana https://grafana.github.io/helm-charts [tab] -This command does not take any more arguments -``` -**Hint**: As can be seen in the above example, a good place to use Active Help messages is when the normal completion system does not provide any suggestions. In such cases, Active Help nicely supplements the normal shell completions. - -### Active Help for flags - -Providing Active Help for flags is done in the same fashion as for nouns, but using the completion function registered for the flag. For example: -```go -_ = cmd.RegisterFlagCompletionFunc("version", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - if len(args) != 2 { - return cobra.AppendActiveHelp(nil, "You must first specify the chart to install before the --version flag can be completed"), cobra.ShellCompDirectiveNoFileComp - } - return compVersionFlag(args[1], toComplete) - }) -``` -The example above prints an Active Help message when not enough information was given by the user to complete the `--version` flag. -``` -bash-5.1$ bin/helm install myrelease --version 2.0.[tab] -You must first specify the chart to install before the --version flag can be completed - -bash-5.1$ bin/helm install myrelease bitnami/solr --version 2.0.[tab][tab] -2.0.1 2.0.2 2.0.3 -``` - -## User control of Active Help - -You may want to allow your users to disable Active Help or choose between different levels of Active Help. It is entirely up to the program to define the type of configurability of Active Help that it wants to offer, if any. -Allowing to configure Active Help is entirely optional; you can use Active Help in your program without doing anything about Active Help configuration. - -The way to configure Active Help is to use the program's Active Help environment -variable. That variable is named `_ACTIVE_HELP` where `` is the name of your -program in uppercase with any `-` replaced by an `_`. The variable should be set by the user to whatever -Active Help configuration values are supported by the program. - -For example, say `helm` has chosen to support three levels for Active Help: `on`, `off`, `local`. Then a user -would set the desired behavior to `local` by doing `export HELM_ACTIVE_HELP=local` in their shell. - -For simplicity, when in `cmd.ValidArgsFunction(...)` or a flag's completion function, the program should read the -Active Help configuration using the `cobra.GetActiveHelpConfig(cmd)` function and select what Active Help messages -should or should not be added (instead of reading the environment variable directly). - -For example: -```go -ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - activeHelpLevel := cobra.GetActiveHelpConfig(cmd) - - var comps []string - if len(args) == 0 { - if activeHelpLevel != "off" { - comps = cobra.AppendActiveHelp(comps, "You must choose a name for the repo you are adding") - } - } else if len(args) == 1 { - if activeHelpLevel != "off" { - comps = cobra.AppendActiveHelp(comps, "You must specify the URL for the repo you are adding") - } - } else { - if activeHelpLevel == "local" { - comps = cobra.AppendActiveHelp(comps, "This command does not take any more arguments") - } - } - return comps, cobra.ShellCompDirectiveNoFileComp -}, -``` -**Note 1**: If the `_ACTIVE_HELP` environment variable is set to the string "0", Cobra will automatically disable all Active Help output (even if some output was specified by the program using the `cobra.AppendActiveHelp(...)` function). Using "0" can simplify your code in situations where you want to blindly disable Active Help without having to call `cobra.GetActiveHelpConfig(cmd)` explicitly. - -**Note 2**: If a user wants to disable Active Help for every single program based on Cobra, she can set the environment variable `COBRA_ACTIVE_HELP` to "0". In this case `cobra.GetActiveHelpConfig(cmd)` will return "0" no matter what the variable `_ACTIVE_HELP` is set to. - -**Note 3**: If the user does not set `_ACTIVE_HELP` or `COBRA_ACTIVE_HELP` (which will be a common case), the default value for the Active Help configuration returned by `cobra.GetActiveHelpConfig(cmd)` will be the empty string. -## Active Help with Cobra's default completion command - -Cobra provides a default `completion` command for programs that wish to use it. -When using the default `completion` command, Active Help is configurable in the same -fashion as described above using environment variables. You may wish to document this in more -details for your users. - -## Debugging Active Help - -Debugging your Active Help code is done in the same way as debugging your dynamic completion code, which is with Cobra's hidden `__complete` command. Please refer to [debugging shell completion](shell_completions.md#debugging) for details. - -When debugging with the `__complete` command, if you want to specify different Active Help configurations, you should use the active help environment variable. That variable is named `_ACTIVE_HELP` where any `-` is replaced by an `_`. For example, we can test deactivating some Active Help as shown below: -``` -$ HELM_ACTIVE_HELP=1 bin/helm __complete install wordpress bitnami/h -bitnami/haproxy -bitnami/harbor -_activeHelp_ WARNING: cannot re-use a name that is still in use -:0 -Completion ended with directive: ShellCompDirectiveDefault - -$ HELM_ACTIVE_HELP=0 bin/helm __complete install wordpress bitnami/h -bitnami/haproxy -bitnami/harbor -:0 -Completion ended with directive: ShellCompDirectiveDefault -``` diff --git a/vendor/github.com/spf13/cobra/args.go b/vendor/github.com/spf13/cobra/args.go index e79ec33a8..ed1e70cea 100644 --- a/vendor/github.com/spf13/cobra/args.go +++ b/vendor/github.com/spf13/cobra/args.go @@ -52,9 +52,9 @@ func OnlyValidArgs(cmd *Command, args []string) error { if len(cmd.ValidArgs) > 0 { // Remove any description that may be included in ValidArgs. // A description is following a tab character. - var validArgs []string + validArgs := make([]string, 0, len(cmd.ValidArgs)) for _, v := range cmd.ValidArgs { - validArgs = append(validArgs, strings.Split(v, "\t")[0]) + validArgs = append(validArgs, strings.SplitN(v, "\t", 2)[0]) } for _, v := range args { if !stringInSlice(v, validArgs) { diff --git a/vendor/github.com/spf13/cobra/bash_completions.go b/vendor/github.com/spf13/cobra/bash_completions.go index 10c78847d..f4d198cbc 100644 --- a/vendor/github.com/spf13/cobra/bash_completions.go +++ b/vendor/github.com/spf13/cobra/bash_completions.go @@ -85,7 +85,7 @@ __%[1]s_handle_go_custom_completion() local out requestComp lastParam lastChar comp directive args # Prepare the command to request completions for the program. - # Calling ${words[0]} instead of directly %[1]s allows to handle aliases + # Calling ${words[0]} instead of directly %[1]s allows handling aliases args=("${words[@]:1}") # Disable ActiveHelp which is not supported for bash completion v1 requestComp="%[8]s=0 ${words[0]} %[2]s ${args[*]}" @@ -597,19 +597,16 @@ func writeRequiredFlag(buf io.StringWriter, cmd *Command) { if nonCompletableFlag(flag) { return } - for key := range flag.Annotations { - switch key { - case BashCompOneRequiredFlag: - format := " must_have_one_flag+=(\"--%s" - if flag.Value.Type() != "bool" { - format += "=" - } - format += cbn - WriteStringAndCheck(buf, fmt.Sprintf(format, flag.Name)) - - if len(flag.Shorthand) > 0 { - WriteStringAndCheck(buf, fmt.Sprintf(" must_have_one_flag+=(\"-%s"+cbn, flag.Shorthand)) - } + if _, ok := flag.Annotations[BashCompOneRequiredFlag]; ok { + format := " must_have_one_flag+=(\"--%s" + if flag.Value.Type() != "bool" { + format += "=" + } + format += cbn + WriteStringAndCheck(buf, fmt.Sprintf(format, flag.Name)) + + if len(flag.Shorthand) > 0 { + WriteStringAndCheck(buf, fmt.Sprintf(" must_have_one_flag+=(\"-%s"+cbn, flag.Shorthand)) } } }) @@ -621,7 +618,7 @@ func writeRequiredNouns(buf io.StringWriter, cmd *Command) { for _, value := range cmd.ValidArgs { // Remove any description that may be included following a tab character. // Descriptions are not supported by bash completion. - value = strings.Split(value, "\t")[0] + value = strings.SplitN(value, "\t", 2)[0] WriteStringAndCheck(buf, fmt.Sprintf(" must_have_one_noun+=(%q)\n", value)) } if cmd.ValidArgsFunction != nil { diff --git a/vendor/github.com/spf13/cobra/bash_completions.md b/vendor/github.com/spf13/cobra/bash_completions.md deleted file mode 100644 index 52919b2fa..000000000 --- a/vendor/github.com/spf13/cobra/bash_completions.md +++ /dev/null @@ -1,93 +0,0 @@ -# Generating Bash Completions For Your cobra.Command - -Please refer to [Shell Completions](shell_completions.md) for details. - -## Bash legacy dynamic completions - -For backward compatibility, Cobra still supports its legacy dynamic completion solution (described below). Unlike the `ValidArgsFunction` solution, the legacy solution will only work for Bash shell-completion and not for other shells. This legacy solution can be used along-side `ValidArgsFunction` and `RegisterFlagCompletionFunc()`, as long as both solutions are not used for the same command. This provides a path to gradually migrate from the legacy solution to the new solution. - -**Note**: Cobra's default `completion` command uses bash completion V2. If you are currently using Cobra's legacy dynamic completion solution, you should not use the default `completion` command but continue using your own. - -The legacy solution allows you to inject bash functions into the bash completion script. Those bash functions are responsible for providing the completion choices for your own completions. - -Some code that works in kubernetes: - -```bash -const ( - bash_completion_func = `__kubectl_parse_get() -{ - local kubectl_output out - if kubectl_output=$(kubectl get --no-headers "$1" 2>/dev/null); then - out=($(echo "${kubectl_output}" | awk '{print $1}')) - COMPREPLY=( $( compgen -W "${out[*]}" -- "$cur" ) ) - fi -} - -__kubectl_get_resource() -{ - if [[ ${#nouns[@]} -eq 0 ]]; then - return 1 - fi - __kubectl_parse_get ${nouns[${#nouns[@]} -1]} - if [[ $? -eq 0 ]]; then - return 0 - fi -} - -__kubectl_custom_func() { - case ${last_command} in - kubectl_get | kubectl_describe | kubectl_delete | kubectl_stop) - __kubectl_get_resource - return - ;; - *) - ;; - esac -} -`) -``` - -And then I set that in my command definition: - -```go -cmds := &cobra.Command{ - Use: "kubectl", - Short: "kubectl controls the Kubernetes cluster manager", - Long: `kubectl controls the Kubernetes cluster manager. - -Find more information at https://github.com/GoogleCloudPlatform/kubernetes.`, - Run: runHelp, - BashCompletionFunction: bash_completion_func, -} -``` - -The `BashCompletionFunction` option is really only valid/useful on the root command. Doing the above will cause `__kubectl_custom_func()` (`___custom_func()`) to be called when the built in processor was unable to find a solution. In the case of kubernetes a valid command might look something like `kubectl get pod [mypod]`. If you type `kubectl get pod [tab][tab]` the `__kubectl_customc_func()` will run because the cobra.Command only understood "kubectl" and "get." `__kubectl_custom_func()` will see that the cobra.Command is "kubectl_get" and will thus call another helper `__kubectl_get_resource()`. `__kubectl_get_resource` will look at the 'nouns' collected. In our example the only noun will be `pod`. So it will call `__kubectl_parse_get pod`. `__kubectl_parse_get` will actually call out to kubernetes and get any pods. It will then set `COMPREPLY` to valid pods! - -Similarly, for flags: - -```go - annotation := make(map[string][]string) - annotation[cobra.BashCompCustom] = []string{"__kubectl_get_namespaces"} - - flag := &pflag.Flag{ - Name: "namespace", - Usage: usage, - Annotations: annotation, - } - cmd.Flags().AddFlag(flag) -``` - -In addition add the `__kubectl_get_namespaces` implementation in the `BashCompletionFunction` -value, e.g.: - -```bash -__kubectl_get_namespaces() -{ - local template - template="{{ range .items }}{{ .metadata.name }} {{ end }}" - local kubectl_out - if kubectl_out=$(kubectl get -o template --template="${template}" namespace 2>/dev/null); then - COMPREPLY=( $( compgen -W "${kubectl_out}[*]" -- "$cur" ) ) - fi -} -``` diff --git a/vendor/github.com/spf13/cobra/bash_completionsV2.go b/vendor/github.com/spf13/cobra/bash_completionsV2.go index 19b09560c..1cce5c329 100644 --- a/vendor/github.com/spf13/cobra/bash_completionsV2.go +++ b/vendor/github.com/spf13/cobra/bash_completionsV2.go @@ -57,7 +57,7 @@ __%[1]s_get_completion_results() { local requestComp lastParam lastChar args # Prepare the command to request completions for the program. - # Calling ${words[0]} instead of directly %[1]s allows to handle aliases + # Calling ${words[0]} instead of directly %[1]s allows handling aliases args=("${words[@]:1}") requestComp="${words[0]} %[2]s ${args[*]}" diff --git a/vendor/github.com/spf13/cobra/cobra.go b/vendor/github.com/spf13/cobra/cobra.go index b07b44a0c..e0b0947b0 100644 --- a/vendor/github.com/spf13/cobra/cobra.go +++ b/vendor/github.com/spf13/cobra/cobra.go @@ -43,12 +43,13 @@ var initializers []func() var finalizers []func() const ( - defaultPrefixMatching = false - defaultCommandSorting = true - defaultCaseInsensitive = false + defaultPrefixMatching = false + defaultCommandSorting = true + defaultCaseInsensitive = false + defaultTraverseRunHooks = false ) -// EnablePrefixMatching allows to set automatic prefix matching. Automatic prefix matching can be a dangerous thing +// EnablePrefixMatching allows setting automatic prefix matching. Automatic prefix matching can be a dangerous thing // to automatically enable in CLI tools. // Set this to true to enable it. var EnablePrefixMatching = defaultPrefixMatching @@ -60,6 +61,10 @@ var EnableCommandSorting = defaultCommandSorting // EnableCaseInsensitive allows case-insensitive commands names. (case sensitive by default) var EnableCaseInsensitive = defaultCaseInsensitive +// EnableTraverseRunHooks executes persistent pre-run and post-run hooks from all parents. +// By default this is disabled, which means only the first run hook to be found is executed. +var EnableTraverseRunHooks = defaultTraverseRunHooks + // MousetrapHelpText enables an information splash screen on Windows // if the CLI is started from explorer.exe. // To disable the mousetrap, just set this variable to blank string (""). @@ -188,8 +193,6 @@ func ld(s, t string, ignoreCase bool) int { d := make([][]int, len(s)+1) for i := range d { d[i] = make([]int, len(t)+1) - } - for i := range d { d[i][0] = i } for j := range d[0] { diff --git a/vendor/github.com/spf13/cobra/command.go b/vendor/github.com/spf13/cobra/command.go index 01f7c6f1c..54748fc67 100644 --- a/vendor/github.com/spf13/cobra/command.go +++ b/vendor/github.com/spf13/cobra/command.go @@ -30,7 +30,10 @@ import ( flag "github.com/spf13/pflag" ) -const FlagSetByCobraAnnotation = "cobra_annotation_flag_set_by_cobra" +const ( + FlagSetByCobraAnnotation = "cobra_annotation_flag_set_by_cobra" + CommandDisplayNameAnnotation = "cobra_annotation_command_display_name" +) // FParseErrWhitelist configures Flag parse errors to be ignored type FParseErrWhitelist flag.ParseErrorsWhitelist @@ -99,7 +102,7 @@ type Command struct { Deprecated string // Annotations are key/value pairs that can be used by applications to identify or - // group commands. + // group commands or set special options. Annotations map[string]string // Version defines the version for this command. If this value is non-empty and the command does not @@ -115,6 +118,8 @@ type Command struct { // * PostRun() // * PersistentPostRun() // All functions get the same args, the arguments after the command name. + // The *PreRun and *PostRun functions will only be executed if the Run function of the current + // command has been declared. // // PersistentPreRun: children of this command will inherit and execute. PersistentPreRun func(cmd *Command, args []string) @@ -149,8 +154,10 @@ type Command struct { // pflags contains persistent flags. pflags *flag.FlagSet // lflags contains local flags. + // This field does not represent internal state, it's used as a cache to optimise LocalFlags function call lflags *flag.FlagSet // iflags contains inherited flags. + // This field does not represent internal state, it's used as a cache to optimise InheritedFlags function call iflags *flag.FlagSet // parentsPflags is all persistent flags of cmd's parents. parentsPflags *flag.FlagSet @@ -181,6 +188,9 @@ type Command struct { // versionTemplate is the version template defined by user. versionTemplate string + // errPrefix is the error message prefix defined by user. + errPrefix string + // inReader is a reader defined by the user that replaces stdin inReader io.Reader // outWriter is a writer defined by the user that replaces stdout @@ -346,6 +356,11 @@ func (c *Command) SetVersionTemplate(s string) { c.versionTemplate = s } +// SetErrPrefix sets error message prefix to be used. Application can use it to set custom prefix. +func (c *Command) SetErrPrefix(s string) { + c.errPrefix = s +} + // SetGlobalNormalizationFunc sets a normalization function to all flag sets and also to child commands. // The user should not have a cyclic dependency on commands. func (c *Command) SetGlobalNormalizationFunc(n func(f *flag.FlagSet, name string) flag.NormalizedName) { @@ -595,6 +610,18 @@ func (c *Command) VersionTemplate() string { ` } +// ErrPrefix return error message prefix for the command +func (c *Command) ErrPrefix() string { + if c.errPrefix != "" { + return c.errPrefix + } + + if c.HasParent() { + return c.parent.ErrPrefix() + } + return "Error:" +} + func hasNoOptDefVal(name string, fs *flag.FlagSet) bool { flag := fs.Lookup(name) if flag == nil { @@ -681,7 +708,7 @@ Loop: // This is not a flag or a flag value. Check to see if it matches what we're looking for, and if so, // return the args, excluding the one at this position. if s == x { - ret := []string{} + ret := make([]string, 0, len(args)-1) ret = append(ret, args[:pos]...) ret = append(ret, args[pos+1:]...) return ret @@ -729,14 +756,14 @@ func (c *Command) findSuggestions(arg string) string { if c.SuggestionsMinimumDistance <= 0 { c.SuggestionsMinimumDistance = 2 } - suggestionsString := "" + var sb strings.Builder if suggestions := c.SuggestionsFor(arg); len(suggestions) > 0 { - suggestionsString += "\n\nDid you mean this?\n" + sb.WriteString("\n\nDid you mean this?\n") for _, s := range suggestions { - suggestionsString += fmt.Sprintf("\t%v\n", s) + _, _ = fmt.Fprintf(&sb, "\t%v\n", s) } } - return suggestionsString + return sb.String() } func (c *Command) findNext(next string) *Command { @@ -752,7 +779,9 @@ func (c *Command) findNext(next string) *Command { } if len(matches) == 1 { - return matches[0] + // Temporarily disable gosec G602, which produces a false positive. + // See https://github.com/securego/gosec/issues/1005. + return matches[0] // #nosec G602 } return nil @@ -846,7 +875,7 @@ func (c *Command) ArgsLenAtDash() int { func (c *Command) execute(a []string) (err error) { if c == nil { - return fmt.Errorf("Called Execute() on a nil Command") + return fmt.Errorf("called Execute() on a nil Command") } if len(c.Deprecated) > 0 { @@ -910,15 +939,31 @@ func (c *Command) execute(a []string) (err error) { return err } + parents := make([]*Command, 0, 5) for p := c; p != nil; p = p.Parent() { + if EnableTraverseRunHooks { + // When EnableTraverseRunHooks is set: + // - Execute all persistent pre-runs from the root parent till this command. + // - Execute all persistent post-runs from this command till the root parent. + parents = append([]*Command{p}, parents...) + } else { + // Otherwise, execute only the first found persistent hook. + parents = append(parents, p) + } + } + for _, p := range parents { if p.PersistentPreRunE != nil { if err := p.PersistentPreRunE(c, argWoFlags); err != nil { return err } - break + if !EnableTraverseRunHooks { + break + } } else if p.PersistentPreRun != nil { p.PersistentPreRun(c, argWoFlags) - break + if !EnableTraverseRunHooks { + break + } } } if c.PreRunE != nil { @@ -955,10 +1000,14 @@ func (c *Command) execute(a []string) (err error) { if err := p.PersistentPostRunE(c, argWoFlags); err != nil { return err } - break + if !EnableTraverseRunHooks { + break + } } else if p.PersistentPostRun != nil { p.PersistentPostRun(c, argWoFlags) - break + if !EnableTraverseRunHooks { + break + } } } @@ -1048,7 +1097,7 @@ func (c *Command) ExecuteC() (cmd *Command, err error) { c = cmd } if !c.SilenceErrors { - c.PrintErrln("Error:", err.Error()) + c.PrintErrln(c.ErrPrefix(), err.Error()) c.PrintErrf("Run '%v --help' for usage.\n", c.CommandPath()) } return c, err @@ -1077,7 +1126,7 @@ func (c *Command) ExecuteC() (cmd *Command, err error) { // If root command has SilenceErrors flagged, // all subcommands should respect it if !cmd.SilenceErrors && !c.SilenceErrors { - c.PrintErrln("Error:", err.Error()) + c.PrintErrln(cmd.ErrPrefix(), err.Error()) } // If root command has SilenceUsage flagged, @@ -1140,10 +1189,11 @@ func (c *Command) InitDefaultHelpFlag() { c.mergePersistentFlags() if c.Flags().Lookup("help") == nil { usage := "help for " - if c.Name() == "" { + name := c.displayName() + if name == "" { usage += "this command" } else { - usage += c.Name() + usage += name } c.Flags().BoolP("help", "h", false, usage) _ = c.Flags().SetAnnotation("help", FlagSetByCobraAnnotation, []string{"true"}) @@ -1189,7 +1239,7 @@ func (c *Command) InitDefaultHelpCmd() { Use: "help [command]", Short: "Help about any command", Long: `Help provides help for any command in the application. -Simply type ` + c.Name() + ` help [path to command] for full details.`, +Simply type ` + c.displayName() + ` help [path to command] for full details.`, ValidArgsFunction: func(c *Command, args []string, toComplete string) ([]string, ShellCompDirective) { var completions []string cmd, _, e := c.Root().Find(args) @@ -1380,16 +1430,24 @@ func (c *Command) CommandPath() string { if c.HasParent() { return c.Parent().CommandPath() + " " + c.Name() } + return c.displayName() +} + +func (c *Command) displayName() string { + if displayName, ok := c.Annotations[CommandDisplayNameAnnotation]; ok { + return displayName + } return c.Name() } // UseLine puts out the full usage for a given command (including parents). func (c *Command) UseLine() string { var useline string + use := strings.Replace(c.Use, c.Name(), c.displayName(), 1) if c.HasParent() { - useline = c.parent.CommandPath() + " " + c.Use + useline = c.parent.CommandPath() + " " + use } else { - useline = c.Use + useline = use } if c.DisableFlagsInUseLine { return useline @@ -1591,7 +1649,7 @@ func (c *Command) GlobalNormalizationFunc() func(f *flag.FlagSet, name string) f // to this command (local and persistent declared here and by all parents). func (c *Command) Flags() *flag.FlagSet { if c.flags == nil { - c.flags = flag.NewFlagSet(c.Name(), flag.ContinueOnError) + c.flags = flag.NewFlagSet(c.displayName(), flag.ContinueOnError) if c.flagErrorBuf == nil { c.flagErrorBuf = new(bytes.Buffer) } @@ -1602,10 +1660,11 @@ func (c *Command) Flags() *flag.FlagSet { } // LocalNonPersistentFlags are flags specific to this command which will NOT persist to subcommands. +// This function does not modify the flags of the current command, it's purpose is to return the current state. func (c *Command) LocalNonPersistentFlags() *flag.FlagSet { persistentFlags := c.PersistentFlags() - out := flag.NewFlagSet(c.Name(), flag.ContinueOnError) + out := flag.NewFlagSet(c.displayName(), flag.ContinueOnError) c.LocalFlags().VisitAll(func(f *flag.Flag) { if persistentFlags.Lookup(f.Name) == nil { out.AddFlag(f) @@ -1615,11 +1674,12 @@ func (c *Command) LocalNonPersistentFlags() *flag.FlagSet { } // LocalFlags returns the local FlagSet specifically set in the current command. +// This function does not modify the flags of the current command, it's purpose is to return the current state. func (c *Command) LocalFlags() *flag.FlagSet { c.mergePersistentFlags() if c.lflags == nil { - c.lflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError) + c.lflags = flag.NewFlagSet(c.displayName(), flag.ContinueOnError) if c.flagErrorBuf == nil { c.flagErrorBuf = new(bytes.Buffer) } @@ -1642,11 +1702,12 @@ func (c *Command) LocalFlags() *flag.FlagSet { } // InheritedFlags returns all flags which were inherited from parent commands. +// This function does not modify the flags of the current command, it's purpose is to return the current state. func (c *Command) InheritedFlags() *flag.FlagSet { c.mergePersistentFlags() if c.iflags == nil { - c.iflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError) + c.iflags = flag.NewFlagSet(c.displayName(), flag.ContinueOnError) if c.flagErrorBuf == nil { c.flagErrorBuf = new(bytes.Buffer) } @@ -1667,6 +1728,7 @@ func (c *Command) InheritedFlags() *flag.FlagSet { } // NonInheritedFlags returns all flags which were not inherited from parent commands. +// This function does not modify the flags of the current command, it's purpose is to return the current state. func (c *Command) NonInheritedFlags() *flag.FlagSet { return c.LocalFlags() } @@ -1674,7 +1736,7 @@ func (c *Command) NonInheritedFlags() *flag.FlagSet { // PersistentFlags returns the persistent FlagSet specifically set in the current command. func (c *Command) PersistentFlags() *flag.FlagSet { if c.pflags == nil { - c.pflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError) + c.pflags = flag.NewFlagSet(c.displayName(), flag.ContinueOnError) if c.flagErrorBuf == nil { c.flagErrorBuf = new(bytes.Buffer) } @@ -1687,9 +1749,9 @@ func (c *Command) PersistentFlags() *flag.FlagSet { func (c *Command) ResetFlags() { c.flagErrorBuf = new(bytes.Buffer) c.flagErrorBuf.Reset() - c.flags = flag.NewFlagSet(c.Name(), flag.ContinueOnError) + c.flags = flag.NewFlagSet(c.displayName(), flag.ContinueOnError) c.flags.SetOutput(c.flagErrorBuf) - c.pflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError) + c.pflags = flag.NewFlagSet(c.displayName(), flag.ContinueOnError) c.pflags.SetOutput(c.flagErrorBuf) c.lflags = nil @@ -1806,7 +1868,7 @@ func (c *Command) mergePersistentFlags() { // If c.parentsPflags == nil, it makes new. func (c *Command) updateParentsPflags() { if c.parentsPflags == nil { - c.parentsPflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError) + c.parentsPflags = flag.NewFlagSet(c.displayName(), flag.ContinueOnError) c.parentsPflags.SetOutput(c.flagErrorBuf) c.parentsPflags.SortFlags = false } diff --git a/vendor/github.com/spf13/cobra/completions.go b/vendor/github.com/spf13/cobra/completions.go index ee38c4d0b..c0c08b057 100644 --- a/vendor/github.com/spf13/cobra/completions.go +++ b/vendor/github.com/spf13/cobra/completions.go @@ -17,6 +17,8 @@ package cobra import ( "fmt" "os" + "regexp" + "strconv" "strings" "sync" @@ -145,6 +147,20 @@ func (c *Command) RegisterFlagCompletionFunc(flagName string, f func(cmd *Comman return nil } +// GetFlagCompletionFunc returns the completion function for the given flag of the command, if available. +func (c *Command) GetFlagCompletionFunc(flagName string) (func(*Command, []string, string) ([]string, ShellCompDirective), bool) { + flag := c.Flag(flagName) + if flag == nil { + return nil, false + } + + flagCompletionMutex.RLock() + defer flagCompletionMutex.RUnlock() + + completionFunc, exists := flagCompletionFunctions[flag] + return completionFunc, exists +} + // Returns a string listing the different directive enabled in the specified parameter func (d ShellCompDirective) string() string { var directives []string @@ -197,24 +213,29 @@ func (c *Command) initCompleteCmd(args []string) { // 2- Even without completions, we need to print the directive } - noDescriptions := (cmd.CalledAs() == ShellCompNoDescRequestCmd) + noDescriptions := cmd.CalledAs() == ShellCompNoDescRequestCmd + if !noDescriptions { + if doDescriptions, err := strconv.ParseBool(getEnvConfig(cmd, configEnvVarSuffixDescriptions)); err == nil { + noDescriptions = !doDescriptions + } + } + noActiveHelp := GetActiveHelpConfig(finalCmd) == activeHelpGlobalDisable + out := finalCmd.OutOrStdout() for _, comp := range completions { - if GetActiveHelpConfig(finalCmd) == activeHelpGlobalDisable { - // Remove all activeHelp entries in this case - if strings.HasPrefix(comp, activeHelpMarker) { - continue - } + if noActiveHelp && strings.HasPrefix(comp, activeHelpMarker) { + // Remove all activeHelp entries if it's disabled. + continue } if noDescriptions { // Remove any description that may be included following a tab character. - comp = strings.Split(comp, "\t")[0] + comp = strings.SplitN(comp, "\t", 2)[0] } // Make sure we only write the first line to the output. // This is needed if a description contains a linebreak. // Otherwise the shell scripts will interpret the other lines as new flags // and could therefore provide a wrong completion. - comp = strings.Split(comp, "\n")[0] + comp = strings.SplitN(comp, "\n", 2)[0] // Finally trim the completion. This is especially important to get rid // of a trailing tab when there are no description following it. @@ -223,14 +244,14 @@ func (c *Command) initCompleteCmd(args []string) { // although there is no description). comp = strings.TrimSpace(comp) - // Print each possible completion to stdout for the completion script to consume. - fmt.Fprintln(finalCmd.OutOrStdout(), comp) + // Print each possible completion to the output for the completion script to consume. + fmt.Fprintln(out, comp) } // As the last printout, print the completion directive for the completion script to parse. // The directive integer must be that last character following a single colon (:). // The completion script expects : - fmt.Fprintf(finalCmd.OutOrStdout(), ":%d\n", directive) + fmt.Fprintf(out, ":%d\n", directive) // Print some helpful info to stderr for the user to understand. // Output from stderr must be ignored by the completion script. @@ -277,15 +298,19 @@ func (c *Command) getCompletions(args []string) (*Command, []string, ShellCompDi } if err != nil { // Unable to find the real command. E.g., someInvalidCmd - return c, []string{}, ShellCompDirectiveDefault, fmt.Errorf("Unable to find a command for arguments: %v", trimmedArgs) + return c, []string{}, ShellCompDirectiveDefault, fmt.Errorf("unable to find a command for arguments: %v", trimmedArgs) } finalCmd.ctx = c.ctx // These flags are normally added when `execute()` is called on `finalCmd`, // however, when doing completion, we don't call `finalCmd.execute()`. - // Let's add the --help and --version flag ourselves. - finalCmd.InitDefaultHelpFlag() - finalCmd.InitDefaultVersionFlag() + // Let's add the --help and --version flag ourselves but only if the finalCmd + // has not disabled flag parsing; if flag parsing is disabled, it is up to the + // finalCmd itself to handle the completion of *all* flags. + if !finalCmd.DisableFlagParsing { + finalCmd.InitDefaultHelpFlag() + finalCmd.InitDefaultVersionFlag() + } // Check if we are doing flag value completion before parsing the flags. // This is important because if we are completing a flag value, we need to also @@ -389,6 +414,11 @@ func (c *Command) getCompletions(args []string) (*Command, []string, ShellCompDi finalCmd.InheritedFlags().VisitAll(func(flag *pflag.Flag) { doCompleteFlags(flag) }) + // Try to complete non-inherited flags even if DisableFlagParsing==true. + // This allows programs to tell Cobra about flags for completion even + // if the actual parsing of flags is not done by Cobra. + // For instance, Helm uses this to provide flag name completion for + // some of its plugins. finalCmd.NonInheritedFlags().VisitAll(func(flag *pflag.Flag) { doCompleteFlags(flag) }) @@ -876,3 +906,34 @@ func CompError(msg string) { func CompErrorln(msg string) { CompError(fmt.Sprintf("%s\n", msg)) } + +// These values should not be changed: users will be using them explicitly. +const ( + configEnvVarGlobalPrefix = "COBRA" + configEnvVarSuffixDescriptions = "COMPLETION_DESCRIPTIONS" +) + +var configEnvVarPrefixSubstRegexp = regexp.MustCompile(`[^A-Z0-9_]`) + +// configEnvVar returns the name of the program-specific configuration environment +// variable. It has the format _ where is the name of the +// root command in upper case, with all non-ASCII-alphanumeric characters replaced by `_`. +func configEnvVar(name, suffix string) string { + // This format should not be changed: users will be using it explicitly. + v := strings.ToUpper(fmt.Sprintf("%s_%s", name, suffix)) + v = configEnvVarPrefixSubstRegexp.ReplaceAllString(v, "_") + return v +} + +// getEnvConfig returns the value of the configuration environment variable +// _ where is the name of the root command in upper +// case, with all non-ASCII-alphanumeric characters replaced by `_`. +// If the value is empty or not set, the value of the environment variable +// COBRA_ is returned instead. +func getEnvConfig(cmd *Command, suffix string) string { + v := os.Getenv(configEnvVar(cmd.Root().Name(), suffix)) + if v == "" { + v = os.Getenv(configEnvVar(configEnvVarGlobalPrefix, suffix)) + } + return v +} diff --git a/vendor/github.com/spf13/cobra/fish_completions.go b/vendor/github.com/spf13/cobra/fish_completions.go index 12ca0d2b1..12d61b691 100644 --- a/vendor/github.com/spf13/cobra/fish_completions.go +++ b/vendor/github.com/spf13/cobra/fish_completions.go @@ -113,7 +113,7 @@ function __%[1]s_clear_perform_completion_once_result __%[1]s_debug "" __%[1]s_debug "========= clearing previously set __%[1]s_perform_completion_once_result variable ==========" set --erase __%[1]s_perform_completion_once_result - __%[1]s_debug "Succesfully erased the variable __%[1]s_perform_completion_once_result" + __%[1]s_debug "Successfully erased the variable __%[1]s_perform_completion_once_result" end function __%[1]s_requires_order_preservation diff --git a/vendor/github.com/spf13/cobra/fish_completions.md b/vendor/github.com/spf13/cobra/fish_completions.md deleted file mode 100644 index 19b2ed129..000000000 --- a/vendor/github.com/spf13/cobra/fish_completions.md +++ /dev/null @@ -1,4 +0,0 @@ -## Generating Fish Completions For Your cobra.Command - -Please refer to [Shell Completions](shell_completions.md) for details. - diff --git a/vendor/github.com/spf13/cobra/flag_groups.go b/vendor/github.com/spf13/cobra/flag_groups.go index b35fde155..560612fd3 100644 --- a/vendor/github.com/spf13/cobra/flag_groups.go +++ b/vendor/github.com/spf13/cobra/flag_groups.go @@ -23,8 +23,9 @@ import ( ) const ( - requiredAsGroup = "cobra_annotation_required_if_others_set" - mutuallyExclusive = "cobra_annotation_mutually_exclusive" + requiredAsGroupAnnotation = "cobra_annotation_required_if_others_set" + oneRequiredAnnotation = "cobra_annotation_one_required" + mutuallyExclusiveAnnotation = "cobra_annotation_mutually_exclusive" ) // MarkFlagsRequiredTogether marks the given flags with annotations so that Cobra errors @@ -36,7 +37,23 @@ func (c *Command) MarkFlagsRequiredTogether(flagNames ...string) { if f == nil { panic(fmt.Sprintf("Failed to find flag %q and mark it as being required in a flag group", v)) } - if err := c.Flags().SetAnnotation(v, requiredAsGroup, append(f.Annotations[requiredAsGroup], strings.Join(flagNames, " "))); err != nil { + if err := c.Flags().SetAnnotation(v, requiredAsGroupAnnotation, append(f.Annotations[requiredAsGroupAnnotation], strings.Join(flagNames, " "))); err != nil { + // Only errs if the flag isn't found. + panic(err) + } + } +} + +// MarkFlagsOneRequired marks the given flags with annotations so that Cobra errors +// if the command is invoked without at least one flag from the given set of flags. +func (c *Command) MarkFlagsOneRequired(flagNames ...string) { + c.mergePersistentFlags() + for _, v := range flagNames { + f := c.Flags().Lookup(v) + if f == nil { + panic(fmt.Sprintf("Failed to find flag %q and mark it as being in a one-required flag group", v)) + } + if err := c.Flags().SetAnnotation(v, oneRequiredAnnotation, append(f.Annotations[oneRequiredAnnotation], strings.Join(flagNames, " "))); err != nil { // Only errs if the flag isn't found. panic(err) } @@ -53,13 +70,13 @@ func (c *Command) MarkFlagsMutuallyExclusive(flagNames ...string) { panic(fmt.Sprintf("Failed to find flag %q and mark it as being in a mutually exclusive flag group", v)) } // Each time this is called is a single new entry; this allows it to be a member of multiple groups if needed. - if err := c.Flags().SetAnnotation(v, mutuallyExclusive, append(f.Annotations[mutuallyExclusive], strings.Join(flagNames, " "))); err != nil { + if err := c.Flags().SetAnnotation(v, mutuallyExclusiveAnnotation, append(f.Annotations[mutuallyExclusiveAnnotation], strings.Join(flagNames, " "))); err != nil { panic(err) } } } -// ValidateFlagGroups validates the mutuallyExclusive/requiredAsGroup logic and returns the +// ValidateFlagGroups validates the mutuallyExclusive/oneRequired/requiredAsGroup logic and returns the // first error encountered. func (c *Command) ValidateFlagGroups() error { if c.DisableFlagParsing { @@ -71,15 +88,20 @@ func (c *Command) ValidateFlagGroups() error { // groupStatus format is the list of flags as a unique ID, // then a map of each flag name and whether it is set or not. groupStatus := map[string]map[string]bool{} + oneRequiredGroupStatus := map[string]map[string]bool{} mutuallyExclusiveGroupStatus := map[string]map[string]bool{} flags.VisitAll(func(pflag *flag.Flag) { - processFlagForGroupAnnotation(flags, pflag, requiredAsGroup, groupStatus) - processFlagForGroupAnnotation(flags, pflag, mutuallyExclusive, mutuallyExclusiveGroupStatus) + processFlagForGroupAnnotation(flags, pflag, requiredAsGroupAnnotation, groupStatus) + processFlagForGroupAnnotation(flags, pflag, oneRequiredAnnotation, oneRequiredGroupStatus) + processFlagForGroupAnnotation(flags, pflag, mutuallyExclusiveAnnotation, mutuallyExclusiveGroupStatus) }) if err := validateRequiredFlagGroups(groupStatus); err != nil { return err } + if err := validateOneRequiredFlagGroups(oneRequiredGroupStatus); err != nil { + return err + } if err := validateExclusiveFlagGroups(mutuallyExclusiveGroupStatus); err != nil { return err } @@ -108,7 +130,7 @@ func processFlagForGroupAnnotation(flags *flag.FlagSet, pflag *flag.Flag, annota continue } - groupStatus[group] = map[string]bool{} + groupStatus[group] = make(map[string]bool, len(flagnames)) for _, name := range flagnames { groupStatus[group][name] = false } @@ -142,6 +164,27 @@ func validateRequiredFlagGroups(data map[string]map[string]bool) error { return nil } +func validateOneRequiredFlagGroups(data map[string]map[string]bool) error { + keys := sortedKeys(data) + for _, flagList := range keys { + flagnameAndStatus := data[flagList] + var set []string + for flagname, isSet := range flagnameAndStatus { + if isSet { + set = append(set, flagname) + } + } + if len(set) >= 1 { + continue + } + + // Sort values, so they can be tested/scripted against consistently. + sort.Strings(set) + return fmt.Errorf("at least one of the flags in the group [%v] is required", flagList) + } + return nil +} + func validateExclusiveFlagGroups(data map[string]map[string]bool) error { keys := sortedKeys(data) for _, flagList := range keys { @@ -176,6 +219,7 @@ func sortedKeys(m map[string]map[string]bool) []string { // enforceFlagGroupsForCompletion will do the following: // - when a flag in a group is present, other flags in the group will be marked required +// - when none of the flags in a one-required group are present, all flags in the group will be marked required // - when a flag in a mutually exclusive group is present, other flags in the group will be marked as hidden // This allows the standard completion logic to behave appropriately for flag groups func (c *Command) enforceFlagGroupsForCompletion() { @@ -185,10 +229,12 @@ func (c *Command) enforceFlagGroupsForCompletion() { flags := c.Flags() groupStatus := map[string]map[string]bool{} + oneRequiredGroupStatus := map[string]map[string]bool{} mutuallyExclusiveGroupStatus := map[string]map[string]bool{} c.Flags().VisitAll(func(pflag *flag.Flag) { - processFlagForGroupAnnotation(flags, pflag, requiredAsGroup, groupStatus) - processFlagForGroupAnnotation(flags, pflag, mutuallyExclusive, mutuallyExclusiveGroupStatus) + processFlagForGroupAnnotation(flags, pflag, requiredAsGroupAnnotation, groupStatus) + processFlagForGroupAnnotation(flags, pflag, oneRequiredAnnotation, oneRequiredGroupStatus) + processFlagForGroupAnnotation(flags, pflag, mutuallyExclusiveAnnotation, mutuallyExclusiveGroupStatus) }) // If a flag that is part of a group is present, we make all the other flags @@ -204,6 +250,26 @@ func (c *Command) enforceFlagGroupsForCompletion() { } } + // If none of the flags of a one-required group are present, we make all the flags + // of that group required so that the shell completion suggests them automatically + for flagList, flagnameAndStatus := range oneRequiredGroupStatus { + isSet := false + + for _, isSet = range flagnameAndStatus { + if isSet { + break + } + } + + // None of the flags of the group are set, mark all flags in the group + // as required + if !isSet { + for _, fName := range strings.Split(flagList, " ") { + _ = c.MarkFlagRequired(fName) + } + } + } + // If a flag that is mutually exclusive to others is present, we hide the other // flags of that group so the shell completion does not suggest them for flagList, flagnameAndStatus := range mutuallyExclusiveGroupStatus { diff --git a/vendor/github.com/spf13/cobra/powershell_completions.go b/vendor/github.com/spf13/cobra/powershell_completions.go index 177d2755f..a830b7bca 100644 --- a/vendor/github.com/spf13/cobra/powershell_completions.go +++ b/vendor/github.com/spf13/cobra/powershell_completions.go @@ -28,8 +28,8 @@ import ( func genPowerShellComp(buf io.StringWriter, name string, includeDesc bool) { // Variables should not contain a '-' or ':' character nameForVar := name - nameForVar = strings.Replace(nameForVar, "-", "_", -1) - nameForVar = strings.Replace(nameForVar, ":", "_", -1) + nameForVar = strings.ReplaceAll(nameForVar, "-", "_") + nameForVar = strings.ReplaceAll(nameForVar, ":", "_") compCmd := ShellCompRequestCmd if !includeDesc { @@ -47,7 +47,7 @@ filter __%[1]s_escapeStringWithSpecialChars { `+" $_ -replace '\\s|#|@|\\$|;|,|''|\\{|\\}|\\(|\\)|\"|`|\\||<|>|&','`$&'"+` } -[scriptblock]$__%[2]sCompleterBlock = { +[scriptblock]${__%[2]sCompleterBlock} = { param( $WordToComplete, $CommandAst, @@ -122,7 +122,7 @@ filter __%[1]s_escapeStringWithSpecialChars { __%[1]s_debug "Calling $RequestComp" # First disable ActiveHelp which is not supported for Powershell - $env:%[10]s=0 + ${env:%[10]s}=0 #call the command store the output in $out and redirect stderr and stdout to null # $Out is an array contains each line per element @@ -279,7 +279,7 @@ filter __%[1]s_escapeStringWithSpecialChars { } } -Register-ArgumentCompleter -CommandName '%[1]s' -ScriptBlock $__%[2]sCompleterBlock +Register-ArgumentCompleter -CommandName '%[1]s' -ScriptBlock ${__%[2]sCompleterBlock} `, name, nameForVar, compCmd, ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp, ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, ShellCompDirectiveKeepOrder, activeHelpEnvVar(name))) diff --git a/vendor/github.com/spf13/cobra/powershell_completions.md b/vendor/github.com/spf13/cobra/powershell_completions.md deleted file mode 100644 index c449f1e5c..000000000 --- a/vendor/github.com/spf13/cobra/powershell_completions.md +++ /dev/null @@ -1,3 +0,0 @@ -# Generating PowerShell Completions For Your Own cobra.Command - -Please refer to [Shell Completions](shell_completions.md#powershell-completions) for details. diff --git a/vendor/github.com/spf13/cobra/projects_using_cobra.md b/vendor/github.com/spf13/cobra/projects_using_cobra.md deleted file mode 100644 index 8a291eb20..000000000 --- a/vendor/github.com/spf13/cobra/projects_using_cobra.md +++ /dev/null @@ -1,64 +0,0 @@ -## Projects using Cobra - -- [Allero](https://github.com/allero-io/allero) -- [Arewefastyet](https://benchmark.vitess.io) -- [Arduino CLI](https://github.com/arduino/arduino-cli) -- [Bleve](https://blevesearch.com/) -- [Cilium](https://cilium.io/) -- [CloudQuery](https://github.com/cloudquery/cloudquery) -- [CockroachDB](https://www.cockroachlabs.com/) -- [Constellation](https://github.com/edgelesssys/constellation) -- [Cosmos SDK](https://github.com/cosmos/cosmos-sdk) -- [Datree](https://github.com/datreeio/datree) -- [Delve](https://github.com/derekparker/delve) -- [Docker (distribution)](https://github.com/docker/distribution) -- [Etcd](https://etcd.io/) -- [Gardener](https://github.com/gardener/gardenctl) -- [Giant Swarm's gsctl](https://github.com/giantswarm/gsctl) -- [Git Bump](https://github.com/erdaltsksn/git-bump) -- [GitHub CLI](https://github.com/cli/cli) -- [GitHub Labeler](https://github.com/erdaltsksn/gh-label) -- [Golangci-lint](https://golangci-lint.run) -- [GopherJS](https://github.com/gopherjs/gopherjs) -- [GoReleaser](https://goreleaser.com) -- [Helm](https://helm.sh) -- [Hugo](https://gohugo.io) -- [Infracost](https://github.com/infracost/infracost) -- [Istio](https://istio.io) -- [Kool](https://github.com/kool-dev/kool) -- [Kubernetes](https://kubernetes.io/) -- [Kubescape](https://github.com/kubescape/kubescape) -- [KubeVirt](https://github.com/kubevirt/kubevirt) -- [Linkerd](https://linkerd.io/) -- [Mattermost-server](https://github.com/mattermost/mattermost-server) -- [Mercure](https://mercure.rocks/) -- [Meroxa CLI](https://github.com/meroxa/cli) -- [Metal Stack CLI](https://github.com/metal-stack/metalctl) -- [Moby (former Docker)](https://github.com/moby/moby) -- [Moldy](https://github.com/Moldy-Community/moldy) -- [Multi-gitter](https://github.com/lindell/multi-gitter) -- [Nanobox](https://github.com/nanobox-io/nanobox)/[Nanopack](https://github.com/nanopack) -- [nFPM](https://nfpm.goreleaser.com) -- [Okteto](https://github.com/okteto/okteto) -- [OpenShift](https://www.openshift.com/) -- [Ory Hydra](https://github.com/ory/hydra) -- [Ory Kratos](https://github.com/ory/kratos) -- [Pixie](https://github.com/pixie-io/pixie) -- [Polygon Edge](https://github.com/0xPolygon/polygon-edge) -- [Pouch](https://github.com/alibaba/pouch) -- [ProjectAtomic (enterprise)](https://www.projectatomic.io/) -- [Prototool](https://github.com/uber/prototool) -- [Pulumi](https://www.pulumi.com) -- [QRcp](https://github.com/claudiodangelis/qrcp) -- [Random](https://github.com/erdaltsksn/random) -- [Rclone](https://rclone.org/) -- [Scaleway CLI](https://github.com/scaleway/scaleway-cli) -- [Sia](https://github.com/SiaFoundation/siad) -- [Skaffold](https://skaffold.dev/) -- [Tendermint](https://github.com/tendermint/tendermint) -- [Twitch CLI](https://github.com/twitchdev/twitch-cli) -- [UpCloud CLI (`upctl`)](https://github.com/UpCloudLtd/upcloud-cli) -- [Vitess](https://vitess.io) -- VMware's [Tanzu Community Edition](https://github.com/vmware-tanzu/community-edition) & [Tanzu Framework](https://github.com/vmware-tanzu/tanzu-framework) -- [Werf](https://werf.io/) -- [ZITADEL](https://github.com/zitadel/zitadel) diff --git a/vendor/github.com/spf13/cobra/shell_completions.md b/vendor/github.com/spf13/cobra/shell_completions.md deleted file mode 100644 index 065c0621d..000000000 --- a/vendor/github.com/spf13/cobra/shell_completions.md +++ /dev/null @@ -1,576 +0,0 @@ -# Generating shell completions - -Cobra can generate shell completions for multiple shells. -The currently supported shells are: -- Bash -- Zsh -- fish -- PowerShell - -Cobra will automatically provide your program with a fully functional `completion` command, -similarly to how it provides the `help` command. - -## Creating your own completion command - -If you do not wish to use the default `completion` command, you can choose to -provide your own, which will take precedence over the default one. (This also provides -backwards-compatibility with programs that already have their own `completion` command.) - -If you are using the `cobra-cli` generator, -which can be found at [spf13/cobra-cli](https://github.com/spf13/cobra-cli), -you can create a completion command by running - -```bash -cobra-cli add completion -``` -and then modifying the generated `cmd/completion.go` file to look something like this -(writing the shell script to stdout allows the most flexible use): - -```go -var completionCmd = &cobra.Command{ - Use: "completion [bash|zsh|fish|powershell]", - Short: "Generate completion script", - Long: fmt.Sprintf(`To load completions: - -Bash: - - $ source <(%[1]s completion bash) - - # To load completions for each session, execute once: - # Linux: - $ %[1]s completion bash > /etc/bash_completion.d/%[1]s - # macOS: - $ %[1]s completion bash > $(brew --prefix)/etc/bash_completion.d/%[1]s - -Zsh: - - # If shell completion is not already enabled in your environment, - # you will need to enable it. You can execute the following once: - - $ echo "autoload -U compinit; compinit" >> ~/.zshrc - - # To load completions for each session, execute once: - $ %[1]s completion zsh > "${fpath[1]}/_%[1]s" - - # You will need to start a new shell for this setup to take effect. - -fish: - - $ %[1]s completion fish | source - - # To load completions for each session, execute once: - $ %[1]s completion fish > ~/.config/fish/completions/%[1]s.fish - -PowerShell: - - PS> %[1]s completion powershell | Out-String | Invoke-Expression - - # To load completions for every new session, run: - PS> %[1]s completion powershell > %[1]s.ps1 - # and source this file from your PowerShell profile. -`,cmd.Root().Name()), - DisableFlagsInUseLine: true, - ValidArgs: []string{"bash", "zsh", "fish", "powershell"}, - Args: cobra.MatchAll(cobra.ExactArgs(1), cobra.OnlyValidArgs), - Run: func(cmd *cobra.Command, args []string) { - switch args[0] { - case "bash": - cmd.Root().GenBashCompletion(os.Stdout) - case "zsh": - cmd.Root().GenZshCompletion(os.Stdout) - case "fish": - cmd.Root().GenFishCompletion(os.Stdout, true) - case "powershell": - cmd.Root().GenPowerShellCompletionWithDesc(os.Stdout) - } - }, -} -``` - -**Note:** The cobra generator may include messages printed to stdout, for example, if the config file is loaded; this will break the auto-completion script so must be removed. - -## Adapting the default completion command - -Cobra provides a few options for the default `completion` command. To configure such options you must set -the `CompletionOptions` field on the *root* command. - -To tell Cobra *not* to provide the default `completion` command: -``` -rootCmd.CompletionOptions.DisableDefaultCmd = true -``` - -To tell Cobra to mark the default `completion` command as *hidden*: -``` -rootCmd.CompletionOptions.HiddenDefaultCmd = true -``` - -To tell Cobra *not* to provide the user with the `--no-descriptions` flag to the completion sub-commands: -``` -rootCmd.CompletionOptions.DisableNoDescFlag = true -``` - -To tell Cobra to completely disable descriptions for completions: -``` -rootCmd.CompletionOptions.DisableDescriptions = true -``` - -# Customizing completions - -The generated completion scripts will automatically handle completing commands and flags. However, you can make your completions much more powerful by providing information to complete your program's nouns and flag values. - -## Completion of nouns - -### Static completion of nouns - -Cobra allows you to provide a pre-defined list of completion choices for your nouns using the `ValidArgs` field. -For example, if you want `kubectl get [tab][tab]` to show a list of valid "nouns" you have to set them. -Some simplified code from `kubectl get` looks like: - -```go -validArgs = []string{ "pod", "node", "service", "replicationcontroller" } - -cmd := &cobra.Command{ - Use: "get [(-o|--output=)json|yaml|template|...] (RESOURCE [NAME] | RESOURCE/NAME ...)", - Short: "Display one or many resources", - Long: get_long, - Example: get_example, - Run: func(cmd *cobra.Command, args []string) { - cobra.CheckErr(RunGet(f, out, cmd, args)) - }, - ValidArgs: validArgs, -} -``` - -Notice we put the `ValidArgs` field on the `get` sub-command. Doing so will give results like: - -```bash -$ kubectl get [tab][tab] -node pod replicationcontroller service -``` - -#### Aliases for nouns - -If your nouns have aliases, you can define them alongside `ValidArgs` using `ArgAliases`: - -```go -argAliases = []string { "pods", "nodes", "services", "svc", "replicationcontrollers", "rc" } - -cmd := &cobra.Command{ - ... - ValidArgs: validArgs, - ArgAliases: argAliases -} -``` - -The aliases are shown to the user on tab completion only if no completions were found within sub-commands or `ValidArgs`. - -### Dynamic completion of nouns - -In some cases it is not possible to provide a list of completions in advance. Instead, the list of completions must be determined at execution-time. In a similar fashion as for static completions, you can use the `ValidArgsFunction` field to provide a Go function that Cobra will execute when it needs the list of completion choices for the nouns of a command. Note that either `ValidArgs` or `ValidArgsFunction` can be used for a single cobra command, but not both. -Simplified code from `helm status` looks like: - -```go -cmd := &cobra.Command{ - Use: "status RELEASE_NAME", - Short: "Display the status of the named release", - Long: status_long, - RunE: func(cmd *cobra.Command, args []string) { - RunGet(args[0]) - }, - ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - if len(args) != 0 { - return nil, cobra.ShellCompDirectiveNoFileComp - } - return getReleasesFromCluster(toComplete), cobra.ShellCompDirectiveNoFileComp - }, -} -``` -Where `getReleasesFromCluster()` is a Go function that obtains the list of current Helm releases running on the Kubernetes cluster. -Notice we put the `ValidArgsFunction` on the `status` sub-command. Let's assume the Helm releases on the cluster are: `harbor`, `notary`, `rook` and `thanos` then this dynamic completion will give results like: - -```bash -$ helm status [tab][tab] -harbor notary rook thanos -``` -You may have noticed the use of `cobra.ShellCompDirective`. These directives are bit fields allowing to control some shell completion behaviors for your particular completion. You can combine them with the bit-or operator such as `cobra.ShellCompDirectiveNoSpace | cobra.ShellCompDirectiveNoFileComp` -```go -// Indicates that the shell will perform its default behavior after completions -// have been provided (this implies none of the other directives). -ShellCompDirectiveDefault - -// Indicates an error occurred and completions should be ignored. -ShellCompDirectiveError - -// Indicates that the shell should not add a space after the completion, -// even if there is a single completion provided. -ShellCompDirectiveNoSpace - -// Indicates that the shell should not provide file completion even when -// no completion is provided. -ShellCompDirectiveNoFileComp - -// Indicates that the returned completions should be used as file extension filters. -// For example, to complete only files of the form *.json or *.yaml: -// return []string{"yaml", "json"}, ShellCompDirectiveFilterFileExt -// For flags, using MarkFlagFilename() and MarkPersistentFlagFilename() -// is a shortcut to using this directive explicitly. -// -ShellCompDirectiveFilterFileExt - -// Indicates that only directory names should be provided in file completion. -// For example: -// return nil, ShellCompDirectiveFilterDirs -// For flags, using MarkFlagDirname() is a shortcut to using this directive explicitly. -// -// To request directory names within another directory, the returned completions -// should specify a single directory name within which to search. For example, -// to complete directories within "themes/": -// return []string{"themes"}, ShellCompDirectiveFilterDirs -// -ShellCompDirectiveFilterDirs - -// ShellCompDirectiveKeepOrder indicates that the shell should preserve the order -// in which the completions are provided -ShellCompDirectiveKeepOrder -``` - -***Note***: When using the `ValidArgsFunction`, Cobra will call your registered function after having parsed all flags and arguments provided in the command-line. You therefore don't need to do this parsing yourself. For example, when a user calls `helm status --namespace my-rook-ns [tab][tab]`, Cobra will call your registered `ValidArgsFunction` after having parsed the `--namespace` flag, as it would have done when calling the `RunE` function. - -#### Debugging - -Cobra achieves dynamic completion through the use of a hidden command called by the completion script. To debug your Go completion code, you can call this hidden command directly: -```bash -$ helm __complete status har -harbor -:4 -Completion ended with directive: ShellCompDirectiveNoFileComp # This is on stderr -``` -***Important:*** If the noun to complete is empty (when the user has not yet typed any letters of that noun), you must pass an empty parameter to the `__complete` command: -```bash -$ helm __complete status "" -harbor -notary -rook -thanos -:4 -Completion ended with directive: ShellCompDirectiveNoFileComp # This is on stderr -``` -Calling the `__complete` command directly allows you to run the Go debugger to troubleshoot your code. You can also add printouts to your code; Cobra provides the following functions to use for printouts in Go completion code: -```go -// Prints to the completion script debug file (if BASH_COMP_DEBUG_FILE -// is set to a file path) and optionally prints to stderr. -cobra.CompDebug(msg string, printToStdErr bool) { -cobra.CompDebugln(msg string, printToStdErr bool) - -// Prints to the completion script debug file (if BASH_COMP_DEBUG_FILE -// is set to a file path) and to stderr. -cobra.CompError(msg string) -cobra.CompErrorln(msg string) -``` -***Important:*** You should **not** leave traces that print directly to stdout in your completion code as they will be interpreted as completion choices by the completion script. Instead, use the cobra-provided debugging traces functions mentioned above. - -## Completions for flags - -### Mark flags as required - -Most of the time completions will only show sub-commands. But if a flag is required to make a sub-command work, you probably want it to show up when the user types [tab][tab]. You can mark a flag as 'Required' like so: - -```go -cmd.MarkFlagRequired("pod") -cmd.MarkFlagRequired("container") -``` - -and you'll get something like - -```bash -$ kubectl exec [tab][tab] --c --container= -p --pod= -``` - -### Specify dynamic flag completion - -As for nouns, Cobra provides a way of defining dynamic completion of flags. To provide a Go function that Cobra will execute when it needs the list of completion choices for a flag, you must register the function using the `command.RegisterFlagCompletionFunc()` function. - -```go -flagName := "output" -cmd.RegisterFlagCompletionFunc(flagName, func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - return []string{"json", "table", "yaml"}, cobra.ShellCompDirectiveDefault -}) -``` -Notice that calling `RegisterFlagCompletionFunc()` is done through the `command` with which the flag is associated. In our example this dynamic completion will give results like so: - -```bash -$ helm status --output [tab][tab] -json table yaml -``` - -#### Debugging - -You can also easily debug your Go completion code for flags: -```bash -$ helm __complete status --output "" -json -table -yaml -:4 -Completion ended with directive: ShellCompDirectiveNoFileComp # This is on stderr -``` -***Important:*** You should **not** leave traces that print to stdout in your completion code as they will be interpreted as completion choices by the completion script. Instead, use the cobra-provided debugging traces functions mentioned further above. - -### Specify valid filename extensions for flags that take a filename - -To limit completions of flag values to file names with certain extensions you can either use the different `MarkFlagFilename()` functions or a combination of `RegisterFlagCompletionFunc()` and `ShellCompDirectiveFilterFileExt`, like so: -```go -flagName := "output" -cmd.MarkFlagFilename(flagName, "yaml", "json") -``` -or -```go -flagName := "output" -cmd.RegisterFlagCompletionFunc(flagName, func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - return []string{"yaml", "json"}, ShellCompDirectiveFilterFileExt}) -``` - -### Limit flag completions to directory names - -To limit completions of flag values to directory names you can either use the `MarkFlagDirname()` functions or a combination of `RegisterFlagCompletionFunc()` and `ShellCompDirectiveFilterDirs`, like so: -```go -flagName := "output" -cmd.MarkFlagDirname(flagName) -``` -or -```go -flagName := "output" -cmd.RegisterFlagCompletionFunc(flagName, func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - return nil, cobra.ShellCompDirectiveFilterDirs -}) -``` -To limit completions of flag values to directory names *within another directory* you can use a combination of `RegisterFlagCompletionFunc()` and `ShellCompDirectiveFilterDirs` like so: -```go -flagName := "output" -cmd.RegisterFlagCompletionFunc(flagName, func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - return []string{"themes"}, cobra.ShellCompDirectiveFilterDirs -}) -``` -### Descriptions for completions - -Cobra provides support for completion descriptions. Such descriptions are supported for each shell -(however, for bash, it is only available in the [completion V2 version](#bash-completion-v2)). -For commands and flags, Cobra will provide the descriptions automatically, based on usage information. -For example, using zsh: -``` -$ helm s[tab] -search -- search for a keyword in charts -show -- show information of a chart -status -- displays the status of the named release -``` -while using fish: -``` -$ helm s[tab] -search (search for a keyword in charts) show (show information of a chart) status (displays the status of the named release) -``` - -Cobra allows you to add descriptions to your own completions. Simply add the description text after each completion, following a `\t` separator. This technique applies to completions returned by `ValidArgs`, `ValidArgsFunction` and `RegisterFlagCompletionFunc()`. For example: -```go -ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - return []string{"harbor\tAn image registry", "thanos\tLong-term metrics"}, cobra.ShellCompDirectiveNoFileComp -}} -``` -or -```go -ValidArgs: []string{"bash\tCompletions for bash", "zsh\tCompletions for zsh"} -``` - -If you don't want to show descriptions in the completions, you can add `--no-descriptions` to the default `completion` command to disable them, like: - -```bash -$ source <(helm completion bash) -$ helm completion [tab][tab] -bash (generate autocompletion script for bash) powershell (generate autocompletion script for powershell) -fish (generate autocompletion script for fish) zsh (generate autocompletion script for zsh) - -$ source <(helm completion bash --no-descriptions) -$ helm completion [tab][tab] -bash fish powershell zsh -``` -## Bash completions - -### Dependencies - -The bash completion script generated by Cobra requires the `bash_completion` package. You should update the help text of your completion command to show how to install the `bash_completion` package ([Kubectl docs](https://kubernetes.io/docs/tasks/tools/install-kubectl/#enabling-shell-autocompletion)) - -### Aliases - -You can also configure `bash` aliases for your program and they will also support completions. - -```bash -alias aliasname=origcommand -complete -o default -F __start_origcommand aliasname - -# and now when you run `aliasname` completion will make -# suggestions as it did for `origcommand`. - -$ aliasname -completion firstcommand secondcommand -``` -### Bash legacy dynamic completions - -For backward compatibility, Cobra still supports its bash legacy dynamic completion solution. -Please refer to [Bash Completions](bash_completions.md) for details. - -### Bash completion V2 - -Cobra provides two versions for bash completion. The original bash completion (which started it all!) can be used by calling -`GenBashCompletion()` or `GenBashCompletionFile()`. - -A new V2 bash completion version is also available. This version can be used by calling `GenBashCompletionV2()` or -`GenBashCompletionFileV2()`. The V2 version does **not** support the legacy dynamic completion -(see [Bash Completions](bash_completions.md)) but instead works only with the Go dynamic completion -solution described in this document. -Unless your program already uses the legacy dynamic completion solution, it is recommended that you use the bash -completion V2 solution which provides the following extra features: -- Supports completion descriptions (like the other shells) -- Small completion script of less than 300 lines (v1 generates scripts of thousands of lines; `kubectl` for example has a bash v1 completion script of over 13K lines) -- Streamlined user experience thanks to a completion behavior aligned with the other shells - -`Bash` completion V2 supports descriptions for completions. When calling `GenBashCompletionV2()` or `GenBashCompletionFileV2()` -you must provide these functions with a parameter indicating if the completions should be annotated with a description; Cobra -will provide the description automatically based on usage information. You can choose to make this option configurable by -your users. - -``` -# With descriptions -$ helm s[tab][tab] -search (search for a keyword in charts) status (display the status of the named release) -show (show information of a chart) - -# Without descriptions -$ helm s[tab][tab] -search show status -``` -**Note**: Cobra's default `completion` command uses bash completion V2. If for some reason you need to use bash completion V1, you will need to implement your own `completion` command. -## Zsh completions - -Cobra supports native zsh completion generated from the root `cobra.Command`. -The generated completion script should be put somewhere in your `$fpath` and be named -`_`. You will need to start a new shell for the completions to become available. - -Zsh supports descriptions for completions. Cobra will provide the description automatically, -based on usage information. Cobra provides a way to completely disable such descriptions by -using `GenZshCompletionNoDesc()` or `GenZshCompletionFileNoDesc()`. You can choose to make -this a configurable option to your users. -``` -# With descriptions -$ helm s[tab] -search -- search for a keyword in charts -show -- show information of a chart -status -- displays the status of the named release - -# Without descriptions -$ helm s[tab] -search show status -``` -*Note*: Because of backward-compatibility requirements, we were forced to have a different API to disable completion descriptions between `zsh` and `fish`. - -### Limitations - -* Custom completions implemented in Bash scripting (legacy) are not supported and will be ignored for `zsh` (including the use of the `BashCompCustom` flag annotation). - * You should instead use `ValidArgsFunction` and `RegisterFlagCompletionFunc()` which are portable to the different shells (`bash`, `zsh`, `fish`, `powershell`). -* The function `MarkFlagCustom()` is not supported and will be ignored for `zsh`. - * You should instead use `RegisterFlagCompletionFunc()`. - -### Zsh completions standardization - -Cobra 1.1 standardized its zsh completion support to align it with its other shell completions. Although the API was kept backward-compatible, some small changes in behavior were introduced. -Please refer to [Zsh Completions](zsh_completions.md) for details. - -## fish completions - -Cobra supports native fish completions generated from the root `cobra.Command`. You can use the `command.GenFishCompletion()` or `command.GenFishCompletionFile()` functions. You must provide these functions with a parameter indicating if the completions should be annotated with a description; Cobra will provide the description automatically based on usage information. You can choose to make this option configurable by your users. -``` -# With descriptions -$ helm s[tab] -search (search for a keyword in charts) show (show information of a chart) status (displays the status of the named release) - -# Without descriptions -$ helm s[tab] -search show status -``` -*Note*: Because of backward-compatibility requirements, we were forced to have a different API to disable completion descriptions between `zsh` and `fish`. - -### Limitations - -* Custom completions implemented in bash scripting (legacy) are not supported and will be ignored for `fish` (including the use of the `BashCompCustom` flag annotation). - * You should instead use `ValidArgsFunction` and `RegisterFlagCompletionFunc()` which are portable to the different shells (`bash`, `zsh`, `fish`, `powershell`). -* The function `MarkFlagCustom()` is not supported and will be ignored for `fish`. - * You should instead use `RegisterFlagCompletionFunc()`. -* The following flag completion annotations are not supported and will be ignored for `fish`: - * `BashCompFilenameExt` (filtering by file extension) - * `BashCompSubdirsInDir` (filtering by directory) -* The functions corresponding to the above annotations are consequently not supported and will be ignored for `fish`: - * `MarkFlagFilename()` and `MarkPersistentFlagFilename()` (filtering by file extension) - * `MarkFlagDirname()` and `MarkPersistentFlagDirname()` (filtering by directory) -* Similarly, the following completion directives are not supported and will be ignored for `fish`: - * `ShellCompDirectiveFilterFileExt` (filtering by file extension) - * `ShellCompDirectiveFilterDirs` (filtering by directory) - -## PowerShell completions - -Cobra supports native PowerShell completions generated from the root `cobra.Command`. You can use the `command.GenPowerShellCompletion()` or `command.GenPowerShellCompletionFile()` functions. To include descriptions use `command.GenPowerShellCompletionWithDesc()` and `command.GenPowerShellCompletionFileWithDesc()`. Cobra will provide the description automatically based on usage information. You can choose to make this option configurable by your users. - -The script is designed to support all three PowerShell completion modes: - -* TabCompleteNext (default windows style - on each key press the next option is displayed) -* Complete (works like bash) -* MenuComplete (works like zsh) - -You set the mode with `Set-PSReadLineKeyHandler -Key Tab -Function `. Descriptions are only displayed when using the `Complete` or `MenuComplete` mode. - -Users need PowerShell version 5.0 or above, which comes with Windows 10 and can be downloaded separately for Windows 7 or 8.1. They can then write the completions to a file and source this file from their PowerShell profile, which is referenced by the `$Profile` environment variable. See `Get-Help about_Profiles` for more info about PowerShell profiles. - -``` -# With descriptions and Mode 'Complete' -$ helm s[tab] -search (search for a keyword in charts) show (show information of a chart) status (displays the status of the named release) - -# With descriptions and Mode 'MenuComplete' The description of the current selected value will be displayed below the suggestions. -$ helm s[tab] -search show status - -search for a keyword in charts - -# Without descriptions -$ helm s[tab] -search show status -``` -### Aliases - -You can also configure `powershell` aliases for your program and they will also support completions. - -``` -$ sal aliasname origcommand -$ Register-ArgumentCompleter -CommandName 'aliasname' -ScriptBlock $__origcommandCompleterBlock - -# and now when you run `aliasname` completion will make -# suggestions as it did for `origcommand`. - -$ aliasname -completion firstcommand secondcommand -``` -The name of the completer block variable is of the form `$__CompleterBlock` where every `-` and `:` in the program name have been replaced with `_`, to respect powershell naming syntax. - -### Limitations - -* Custom completions implemented in bash scripting (legacy) are not supported and will be ignored for `powershell` (including the use of the `BashCompCustom` flag annotation). - * You should instead use `ValidArgsFunction` and `RegisterFlagCompletionFunc()` which are portable to the different shells (`bash`, `zsh`, `fish`, `powershell`). -* The function `MarkFlagCustom()` is not supported and will be ignored for `powershell`. - * You should instead use `RegisterFlagCompletionFunc()`. -* The following flag completion annotations are not supported and will be ignored for `powershell`: - * `BashCompFilenameExt` (filtering by file extension) - * `BashCompSubdirsInDir` (filtering by directory) -* The functions corresponding to the above annotations are consequently not supported and will be ignored for `powershell`: - * `MarkFlagFilename()` and `MarkPersistentFlagFilename()` (filtering by file extension) - * `MarkFlagDirname()` and `MarkPersistentFlagDirname()` (filtering by directory) -* Similarly, the following completion directives are not supported and will be ignored for `powershell`: - * `ShellCompDirectiveFilterFileExt` (filtering by file extension) - * `ShellCompDirectiveFilterDirs` (filtering by directory) diff --git a/vendor/github.com/spf13/cobra/user_guide.md b/vendor/github.com/spf13/cobra/user_guide.md deleted file mode 100644 index 85201d840..000000000 --- a/vendor/github.com/spf13/cobra/user_guide.md +++ /dev/null @@ -1,726 +0,0 @@ -# User Guide - -While you are welcome to provide your own organization, typically a Cobra-based -application will follow the following organizational structure: - -``` - ▾ appName/ - ▾ cmd/ - add.go - your.go - commands.go - here.go - main.go -``` - -In a Cobra app, typically the main.go file is very bare. It serves one purpose: initializing Cobra. - -```go -package main - -import ( - "{pathToYourApp}/cmd" -) - -func main() { - cmd.Execute() -} -``` - -## Using the Cobra Generator - -Cobra-CLI is its own program that will create your application and add any -commands you want. It's the easiest way to incorporate Cobra into your application. - -For complete details on using the Cobra generator, please refer to [The Cobra-CLI Generator README](https://github.com/spf13/cobra-cli/blob/main/README.md) - -## Using the Cobra Library - -To manually implement Cobra you need to create a bare main.go file and a rootCmd file. -You will optionally provide additional commands as you see fit. - -### Create rootCmd - -Cobra doesn't require any special constructors. Simply create your commands. - -Ideally you place this in app/cmd/root.go: - -```go -var rootCmd = &cobra.Command{ - Use: "hugo", - Short: "Hugo is a very fast static site generator", - Long: `A Fast and Flexible Static Site Generator built with - love by spf13 and friends in Go. - Complete documentation is available at https://gohugo.io/documentation/`, - Run: func(cmd *cobra.Command, args []string) { - // Do Stuff Here - }, -} - -func Execute() { - if err := rootCmd.Execute(); err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(1) - } -} -``` - -You will additionally define flags and handle configuration in your init() function. - -For example cmd/root.go: - -```go -package cmd - -import ( - "fmt" - "os" - - "github.com/spf13/cobra" - "github.com/spf13/viper" -) - -var ( - // Used for flags. - cfgFile string - userLicense string - - rootCmd = &cobra.Command{ - Use: "cobra-cli", - Short: "A generator for Cobra based Applications", - Long: `Cobra is a CLI library for Go that empowers applications. -This application is a tool to generate the needed files -to quickly create a Cobra application.`, - } -) - -// Execute executes the root command. -func Execute() error { - return rootCmd.Execute() -} - -func init() { - cobra.OnInitialize(initConfig) - - rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.cobra.yaml)") - rootCmd.PersistentFlags().StringP("author", "a", "YOUR NAME", "author name for copyright attribution") - rootCmd.PersistentFlags().StringVarP(&userLicense, "license", "l", "", "name of license for the project") - rootCmd.PersistentFlags().Bool("viper", true, "use Viper for configuration") - viper.BindPFlag("author", rootCmd.PersistentFlags().Lookup("author")) - viper.BindPFlag("useViper", rootCmd.PersistentFlags().Lookup("viper")) - viper.SetDefault("author", "NAME HERE ") - viper.SetDefault("license", "apache") - - rootCmd.AddCommand(addCmd) - rootCmd.AddCommand(initCmd) -} - -func initConfig() { - if cfgFile != "" { - // Use config file from the flag. - viper.SetConfigFile(cfgFile) - } else { - // Find home directory. - home, err := os.UserHomeDir() - cobra.CheckErr(err) - - // Search config in home directory with name ".cobra" (without extension). - viper.AddConfigPath(home) - viper.SetConfigType("yaml") - viper.SetConfigName(".cobra") - } - - viper.AutomaticEnv() - - if err := viper.ReadInConfig(); err == nil { - fmt.Println("Using config file:", viper.ConfigFileUsed()) - } -} -``` - -### Create your main.go - -With the root command you need to have your main function execute it. -Execute should be run on the root for clarity, though it can be called on any command. - -In a Cobra app, typically the main.go file is very bare. It serves one purpose: to initialize Cobra. - -```go -package main - -import ( - "{pathToYourApp}/cmd" -) - -func main() { - cmd.Execute() -} -``` - -### Create additional commands - -Additional commands can be defined and typically are each given their own file -inside of the cmd/ directory. - -If you wanted to create a version command you would create cmd/version.go and -populate it with the following: - -```go -package cmd - -import ( - "fmt" - - "github.com/spf13/cobra" -) - -func init() { - rootCmd.AddCommand(versionCmd) -} - -var versionCmd = &cobra.Command{ - Use: "version", - Short: "Print the version number of Hugo", - Long: `All software has versions. This is Hugo's`, - Run: func(cmd *cobra.Command, args []string) { - fmt.Println("Hugo Static Site Generator v0.9 -- HEAD") - }, -} -``` - -### Organizing subcommands - -A command may have subcommands which in turn may have other subcommands. This is achieved by using -`AddCommand`. In some cases, especially in larger applications, each subcommand may be defined in -its own go package. - -The suggested approach is for the parent command to use `AddCommand` to add its most immediate -subcommands. For example, consider the following directory structure: - -```text -├── cmd -│   ├── root.go -│   └── sub1 -│   ├── sub1.go -│   └── sub2 -│   ├── leafA.go -│   ├── leafB.go -│   └── sub2.go -└── main.go -``` - -In this case: - -* The `init` function of `root.go` adds the command defined in `sub1.go` to the root command. -* The `init` function of `sub1.go` adds the command defined in `sub2.go` to the sub1 command. -* The `init` function of `sub2.go` adds the commands defined in `leafA.go` and `leafB.go` to the - sub2 command. - -This approach ensures the subcommands are always included at compile time while avoiding cyclic -references. - -### Returning and handling errors - -If you wish to return an error to the caller of a command, `RunE` can be used. - -```go -package cmd - -import ( - "fmt" - - "github.com/spf13/cobra" -) - -func init() { - rootCmd.AddCommand(tryCmd) -} - -var tryCmd = &cobra.Command{ - Use: "try", - Short: "Try and possibly fail at something", - RunE: func(cmd *cobra.Command, args []string) error { - if err := someFunc(); err != nil { - return err - } - return nil - }, -} -``` - -The error can then be caught at the execute function call. - -## Working with Flags - -Flags provide modifiers to control how the action command operates. - -### Assign flags to a command - -Since the flags are defined and used in different locations, we need to -define a variable outside with the correct scope to assign the flag to -work with. - -```go -var Verbose bool -var Source string -``` - -There are two different approaches to assign a flag. - -### Persistent Flags - -A flag can be 'persistent', meaning that this flag will be available to the -command it's assigned to as well as every command under that command. For -global flags, assign a flag as a persistent flag on the root. - -```go -rootCmd.PersistentFlags().BoolVarP(&Verbose, "verbose", "v", false, "verbose output") -``` - -### Local Flags - -A flag can also be assigned locally, which will only apply to that specific command. - -```go -localCmd.Flags().StringVarP(&Source, "source", "s", "", "Source directory to read from") -``` - -### Local Flag on Parent Commands - -By default, Cobra only parses local flags on the target command, and any local flags on -parent commands are ignored. By enabling `Command.TraverseChildren`, Cobra will -parse local flags on each command before executing the target command. - -```go -command := cobra.Command{ - Use: "print [OPTIONS] [COMMANDS]", - TraverseChildren: true, -} -``` - -### Bind Flags with Config - -You can also bind your flags with [viper](https://github.com/spf13/viper): -```go -var author string - -func init() { - rootCmd.PersistentFlags().StringVar(&author, "author", "YOUR NAME", "Author name for copyright attribution") - viper.BindPFlag("author", rootCmd.PersistentFlags().Lookup("author")) -} -``` - -In this example, the persistent flag `author` is bound with `viper`. -**Note**: the variable `author` will not be set to the value from config, -when the `--author` flag is provided by user. - -More in [viper documentation](https://github.com/spf13/viper#working-with-flags). - -### Required flags - -Flags are optional by default. If instead you wish your command to report an error -when a flag has not been set, mark it as required: -```go -rootCmd.Flags().StringVarP(&Region, "region", "r", "", "AWS region (required)") -rootCmd.MarkFlagRequired("region") -``` - -Or, for persistent flags: -```go -rootCmd.PersistentFlags().StringVarP(&Region, "region", "r", "", "AWS region (required)") -rootCmd.MarkPersistentFlagRequired("region") -``` - -### Flag Groups - -If you have different flags that must be provided together (e.g. if they provide the `--username` flag they MUST provide the `--password` flag as well) then -Cobra can enforce that requirement: -```go -rootCmd.Flags().StringVarP(&u, "username", "u", "", "Username (required if password is set)") -rootCmd.Flags().StringVarP(&pw, "password", "p", "", "Password (required if username is set)") -rootCmd.MarkFlagsRequiredTogether("username", "password") -``` - -You can also prevent different flags from being provided together if they represent mutually -exclusive options such as specifying an output format as either `--json` or `--yaml` but never both: -```go -rootCmd.Flags().BoolVar(&ofJson, "json", false, "Output in JSON") -rootCmd.Flags().BoolVar(&ofYaml, "yaml", false, "Output in YAML") -rootCmd.MarkFlagsMutuallyExclusive("json", "yaml") -``` - -In both of these cases: - - both local and persistent flags can be used - - **NOTE:** the group is only enforced on commands where every flag is defined - - a flag may appear in multiple groups - - a group may contain any number of flags - -## Positional and Custom Arguments - -Validation of positional arguments can be specified using the `Args` field of `Command`. -The following validators are built in: - -- Number of arguments: - - `NoArgs` - report an error if there are any positional args. - - `ArbitraryArgs` - accept any number of args. - - `MinimumNArgs(int)` - report an error if less than N positional args are provided. - - `MaximumNArgs(int)` - report an error if more than N positional args are provided. - - `ExactArgs(int)` - report an error if there are not exactly N positional args. - - `RangeArgs(min, max)` - report an error if the number of args is not between `min` and `max`. -- Content of the arguments: - - `OnlyValidArgs` - report an error if there are any positional args not specified in the `ValidArgs` field of `Command`, which can optionally be set to a list of valid values for positional args. - -If `Args` is undefined or `nil`, it defaults to `ArbitraryArgs`. - -Moreover, `MatchAll(pargs ...PositionalArgs)` enables combining existing checks with arbitrary other checks. -For instance, if you want to report an error if there are not exactly N positional args OR if there are any positional -args that are not in the `ValidArgs` field of `Command`, you can call `MatchAll` on `ExactArgs` and `OnlyValidArgs`, as -shown below: - -```go -var cmd = &cobra.Command{ - Short: "hello", - Args: cobra.MatchAll(cobra.ExactArgs(2), cobra.OnlyValidArgs), - Run: func(cmd *cobra.Command, args []string) { - fmt.Println("Hello, World!") - }, -} -``` - -It is possible to set any custom validator that satisfies `func(cmd *cobra.Command, args []string) error`. -For example: - -```go -var cmd = &cobra.Command{ - Short: "hello", - Args: func(cmd *cobra.Command, args []string) error { - // Optionally run one of the validators provided by cobra - if err := cobra.MinimumNArgs(1)(cmd, args); err != nil { - return err - } - // Run the custom validation logic - if myapp.IsValidColor(args[0]) { - return nil - } - return fmt.Errorf("invalid color specified: %s", args[0]) - }, - Run: func(cmd *cobra.Command, args []string) { - fmt.Println("Hello, World!") - }, -} -``` - -## Example - -In the example below, we have defined three commands. Two are at the top level -and one (cmdTimes) is a child of one of the top commands. In this case the root -is not executable, meaning that a subcommand is required. This is accomplished -by not providing a 'Run' for the 'rootCmd'. - -We have only defined one flag for a single command. - -More documentation about flags is available at https://github.com/spf13/pflag - -```go -package main - -import ( - "fmt" - "strings" - - "github.com/spf13/cobra" -) - -func main() { - var echoTimes int - - var cmdPrint = &cobra.Command{ - Use: "print [string to print]", - Short: "Print anything to the screen", - Long: `print is for printing anything back to the screen. -For many years people have printed back to the screen.`, - Args: cobra.MinimumNArgs(1), - Run: func(cmd *cobra.Command, args []string) { - fmt.Println("Print: " + strings.Join(args, " ")) - }, - } - - var cmdEcho = &cobra.Command{ - Use: "echo [string to echo]", - Short: "Echo anything to the screen", - Long: `echo is for echoing anything back. -Echo works a lot like print, except it has a child command.`, - Args: cobra.MinimumNArgs(1), - Run: func(cmd *cobra.Command, args []string) { - fmt.Println("Echo: " + strings.Join(args, " ")) - }, - } - - var cmdTimes = &cobra.Command{ - Use: "times [string to echo]", - Short: "Echo anything to the screen more times", - Long: `echo things multiple times back to the user by providing -a count and a string.`, - Args: cobra.MinimumNArgs(1), - Run: func(cmd *cobra.Command, args []string) { - for i := 0; i < echoTimes; i++ { - fmt.Println("Echo: " + strings.Join(args, " ")) - } - }, - } - - cmdTimes.Flags().IntVarP(&echoTimes, "times", "t", 1, "times to echo the input") - - var rootCmd = &cobra.Command{Use: "app"} - rootCmd.AddCommand(cmdPrint, cmdEcho) - cmdEcho.AddCommand(cmdTimes) - rootCmd.Execute() -} -``` - -For a more complete example of a larger application, please checkout [Hugo](https://gohugo.io/). - -## Help Command - -Cobra automatically adds a help command to your application when you have subcommands. -This will be called when a user runs 'app help'. Additionally, help will also -support all other commands as input. Say, for instance, you have a command called -'create' without any additional configuration; Cobra will work when 'app help -create' is called. Every command will automatically have the '--help' flag added. - -### Example - -The following output is automatically generated by Cobra. Nothing beyond the -command and flag definitions are needed. - - $ cobra-cli help - - Cobra is a CLI library for Go that empowers applications. - This application is a tool to generate the needed files - to quickly create a Cobra application. - - Usage: - cobra-cli [command] - - Available Commands: - add Add a command to a Cobra Application - completion Generate the autocompletion script for the specified shell - help Help about any command - init Initialize a Cobra Application - - Flags: - -a, --author string author name for copyright attribution (default "YOUR NAME") - --config string config file (default is $HOME/.cobra.yaml) - -h, --help help for cobra-cli - -l, --license string name of license for the project - --viper use Viper for configuration - - Use "cobra-cli [command] --help" for more information about a command. - - -Help is just a command like any other. There is no special logic or behavior -around it. In fact, you can provide your own if you want. - -### Grouping commands in help - -Cobra supports grouping of available commands in the help output. To group commands, each group must be explicitly -defined using `AddGroup()` on the parent command. Then a subcommand can be added to a group using the `GroupID` element -of that subcommand. The groups will appear in the help output in the same order as they are defined using different -calls to `AddGroup()`. If you use the generated `help` or `completion` commands, you can set their group ids using -`SetHelpCommandGroupId()` and `SetCompletionCommandGroupId()` on the root command, respectively. - -### Defining your own help - -You can provide your own Help command or your own template for the default command to use -with the following functions: - -```go -cmd.SetHelpCommand(cmd *Command) -cmd.SetHelpFunc(f func(*Command, []string)) -cmd.SetHelpTemplate(s string) -``` - -The latter two will also apply to any children commands. - -## Usage Message - -When the user provides an invalid flag or invalid command, Cobra responds by -showing the user the 'usage'. - -### Example -You may recognize this from the help above. That's because the default help -embeds the usage as part of its output. - - $ cobra-cli --invalid - Error: unknown flag: --invalid - Usage: - cobra-cli [command] - - Available Commands: - add Add a command to a Cobra Application - completion Generate the autocompletion script for the specified shell - help Help about any command - init Initialize a Cobra Application - - Flags: - -a, --author string author name for copyright attribution (default "YOUR NAME") - --config string config file (default is $HOME/.cobra.yaml) - -h, --help help for cobra-cli - -l, --license string name of license for the project - --viper use Viper for configuration - - Use "cobra [command] --help" for more information about a command. - -### Defining your own usage -You can provide your own usage function or template for Cobra to use. -Like help, the function and template are overridable through public methods: - -```go -cmd.SetUsageFunc(f func(*Command) error) -cmd.SetUsageTemplate(s string) -``` - -## Version Flag - -Cobra adds a top-level '--version' flag if the Version field is set on the root command. -Running an application with the '--version' flag will print the version to stdout using -the version template. The template can be customized using the -`cmd.SetVersionTemplate(s string)` function. - -## PreRun and PostRun Hooks - -It is possible to run functions before or after the main `Run` function of your command. The `PersistentPreRun` and `PreRun` functions will be executed before `Run`. `PersistentPostRun` and `PostRun` will be executed after `Run`. The `Persistent*Run` functions will be inherited by children if they do not declare their own. These functions are run in the following order: - -- `PersistentPreRun` -- `PreRun` -- `Run` -- `PostRun` -- `PersistentPostRun` - -An example of two commands which use all of these features is below. When the subcommand is executed, it will run the root command's `PersistentPreRun` but not the root command's `PersistentPostRun`: - -```go -package main - -import ( - "fmt" - - "github.com/spf13/cobra" -) - -func main() { - - var rootCmd = &cobra.Command{ - Use: "root [sub]", - Short: "My root command", - PersistentPreRun: func(cmd *cobra.Command, args []string) { - fmt.Printf("Inside rootCmd PersistentPreRun with args: %v\n", args) - }, - PreRun: func(cmd *cobra.Command, args []string) { - fmt.Printf("Inside rootCmd PreRun with args: %v\n", args) - }, - Run: func(cmd *cobra.Command, args []string) { - fmt.Printf("Inside rootCmd Run with args: %v\n", args) - }, - PostRun: func(cmd *cobra.Command, args []string) { - fmt.Printf("Inside rootCmd PostRun with args: %v\n", args) - }, - PersistentPostRun: func(cmd *cobra.Command, args []string) { - fmt.Printf("Inside rootCmd PersistentPostRun with args: %v\n", args) - }, - } - - var subCmd = &cobra.Command{ - Use: "sub [no options!]", - Short: "My subcommand", - PreRun: func(cmd *cobra.Command, args []string) { - fmt.Printf("Inside subCmd PreRun with args: %v\n", args) - }, - Run: func(cmd *cobra.Command, args []string) { - fmt.Printf("Inside subCmd Run with args: %v\n", args) - }, - PostRun: func(cmd *cobra.Command, args []string) { - fmt.Printf("Inside subCmd PostRun with args: %v\n", args) - }, - PersistentPostRun: func(cmd *cobra.Command, args []string) { - fmt.Printf("Inside subCmd PersistentPostRun with args: %v\n", args) - }, - } - - rootCmd.AddCommand(subCmd) - - rootCmd.SetArgs([]string{""}) - rootCmd.Execute() - fmt.Println() - rootCmd.SetArgs([]string{"sub", "arg1", "arg2"}) - rootCmd.Execute() -} -``` - -Output: -``` -Inside rootCmd PersistentPreRun with args: [] -Inside rootCmd PreRun with args: [] -Inside rootCmd Run with args: [] -Inside rootCmd PostRun with args: [] -Inside rootCmd PersistentPostRun with args: [] - -Inside rootCmd PersistentPreRun with args: [arg1 arg2] -Inside subCmd PreRun with args: [arg1 arg2] -Inside subCmd Run with args: [arg1 arg2] -Inside subCmd PostRun with args: [arg1 arg2] -Inside subCmd PersistentPostRun with args: [arg1 arg2] -``` - -## Suggestions when "unknown command" happens - -Cobra will print automatic suggestions when "unknown command" errors happen. This allows Cobra to behave similarly to the `git` command when a typo happens. For example: - -``` -$ hugo srever -Error: unknown command "srever" for "hugo" - -Did you mean this? - server - -Run 'hugo --help' for usage. -``` - -Suggestions are automatically generated based on existing subcommands and use an implementation of [Levenshtein distance](https://en.wikipedia.org/wiki/Levenshtein_distance). Every registered command that matches a minimum distance of 2 (ignoring case) will be displayed as a suggestion. - -If you need to disable suggestions or tweak the string distance in your command, use: - -```go -command.DisableSuggestions = true -``` - -or - -```go -command.SuggestionsMinimumDistance = 1 -``` - -You can also explicitly set names for which a given command will be suggested using the `SuggestFor` attribute. This allows suggestions for strings that are not close in terms of string distance, but make sense in your set of commands but for which -you don't want aliases. Example: - -``` -$ kubectl remove -Error: unknown command "remove" for "kubectl" - -Did you mean this? - delete - -Run 'kubectl help' for usage. -``` - -## Generating documentation for your command - -Cobra can generate documentation based on subcommands, flags, etc. Read more about it in the [docs generation documentation](doc/README.md). - -## Generating shell completions - -Cobra can generate a shell-completion file for the following shells: bash, zsh, fish, PowerShell. If you add more information to your commands, these completions can be amazingly powerful and flexible. Read more about it in [Shell Completions](shell_completions.md). - -## Providing Active Help - -Cobra makes use of the shell-completion system to define a framework allowing you to provide Active Help to your users. Active Help are messages (hints, warnings, etc) printed as the program is being used. Read more about it in [Active Help](active_help.md). diff --git a/vendor/github.com/spf13/cobra/zsh_completions.md b/vendor/github.com/spf13/cobra/zsh_completions.md deleted file mode 100644 index 7cff61787..000000000 --- a/vendor/github.com/spf13/cobra/zsh_completions.md +++ /dev/null @@ -1,48 +0,0 @@ -## Generating Zsh Completion For Your cobra.Command - -Please refer to [Shell Completions](shell_completions.md) for details. - -## Zsh completions standardization - -Cobra 1.1 standardized its zsh completion support to align it with its other shell completions. Although the API was kept backwards-compatible, some small changes in behavior were introduced. - -### Deprecation summary - -See further below for more details on these deprecations. - -* `cmd.MarkZshCompPositionalArgumentFile(pos, []string{})` is no longer needed. It is therefore **deprecated** and silently ignored. -* `cmd.MarkZshCompPositionalArgumentFile(pos, glob[])` is **deprecated** and silently ignored. - * Instead use `ValidArgsFunction` with `ShellCompDirectiveFilterFileExt`. -* `cmd.MarkZshCompPositionalArgumentWords()` is **deprecated** and silently ignored. - * Instead use `ValidArgsFunction`. - -### Behavioral changes - -**Noun completion** -|Old behavior|New behavior| -|---|---| -|No file completion by default (opposite of bash)|File completion by default; use `ValidArgsFunction` with `ShellCompDirectiveNoFileComp` to turn off file completion on a per-argument basis| -|Completion of flag names without the `-` prefix having been typed|Flag names are only completed if the user has typed the first `-`| -`cmd.MarkZshCompPositionalArgumentFile(pos, []string{})` used to turn on file completion on a per-argument position basis|File completion for all arguments by default; `cmd.MarkZshCompPositionalArgumentFile()` is **deprecated** and silently ignored| -|`cmd.MarkZshCompPositionalArgumentFile(pos, glob[])` used to turn on file completion **with glob filtering** on a per-argument position basis (zsh-specific)|`cmd.MarkZshCompPositionalArgumentFile()` is **deprecated** and silently ignored; use `ValidArgsFunction` with `ShellCompDirectiveFilterFileExt` for file **extension** filtering (not full glob filtering)| -|`cmd.MarkZshCompPositionalArgumentWords(pos, words[])` used to provide completion choices on a per-argument position basis (zsh-specific)|`cmd.MarkZshCompPositionalArgumentWords()` is **deprecated** and silently ignored; use `ValidArgsFunction` to achieve the same behavior| - -**Flag-value completion** - -|Old behavior|New behavior| -|---|---| -|No file completion by default (opposite of bash)|File completion by default; use `RegisterFlagCompletionFunc()` with `ShellCompDirectiveNoFileComp` to turn off file completion| -|`cmd.MarkFlagFilename(flag, []string{})` and similar used to turn on file completion|File completion by default; `cmd.MarkFlagFilename(flag, []string{})` no longer needed in this context and silently ignored| -|`cmd.MarkFlagFilename(flag, glob[])` used to turn on file completion **with glob filtering** (syntax of `[]string{"*.yaml", "*.yml"}` incompatible with bash)|Will continue to work, however, support for bash syntax is added and should be used instead so as to work for all shells (`[]string{"yaml", "yml"}`)| -|`cmd.MarkFlagDirname(flag)` only completes directories (zsh-specific)|Has been added for all shells| -|Completion of a flag name does not repeat, unless flag is of type `*Array` or `*Slice` (not supported by bash)|Retained for `zsh` and added to `fish`| -|Completion of a flag name does not provide the `=` form (unlike bash)|Retained for `zsh` and added to `fish`| - -**Improvements** - -* Custom completion support (`ValidArgsFunction` and `RegisterFlagCompletionFunc()`) -* File completion by default if no other completions found -* Handling of required flags -* File extension filtering no longer mutually exclusive with bash usage -* Completion of directory names *within* another directory -* Support for `=` form of flags diff --git a/vendor/github.com/stretchr/testify/assert/assertion_compare.go b/vendor/github.com/stretchr/testify/assert/assertion_compare.go index b774da88d..4d4b4aad6 100644 --- a/vendor/github.com/stretchr/testify/assert/assertion_compare.go +++ b/vendor/github.com/stretchr/testify/assert/assertion_compare.go @@ -28,6 +28,8 @@ var ( uint32Type = reflect.TypeOf(uint32(1)) uint64Type = reflect.TypeOf(uint64(1)) + uintptrType = reflect.TypeOf(uintptr(1)) + float32Type = reflect.TypeOf(float32(1)) float64Type = reflect.TypeOf(float64(1)) @@ -308,11 +310,11 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) { case reflect.Struct: { // All structs enter here. We're not interested in most types. - if !canConvert(obj1Value, timeType) { + if !obj1Value.CanConvert(timeType) { break } - // time.Time can compared! + // time.Time can be compared! timeObj1, ok := obj1.(time.Time) if !ok { timeObj1 = obj1Value.Convert(timeType).Interface().(time.Time) @@ -328,7 +330,7 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) { case reflect.Slice: { // We only care about the []byte type. - if !canConvert(obj1Value, bytesType) { + if !obj1Value.CanConvert(bytesType) { break } @@ -345,6 +347,26 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) { return CompareType(bytes.Compare(bytesObj1, bytesObj2)), true } + case reflect.Uintptr: + { + uintptrObj1, ok := obj1.(uintptr) + if !ok { + uintptrObj1 = obj1Value.Convert(uintptrType).Interface().(uintptr) + } + uintptrObj2, ok := obj2.(uintptr) + if !ok { + uintptrObj2 = obj2Value.Convert(uintptrType).Interface().(uintptr) + } + if uintptrObj1 > uintptrObj2 { + return compareGreater, true + } + if uintptrObj1 == uintptrObj2 { + return compareEqual, true + } + if uintptrObj1 < uintptrObj2 { + return compareLess, true + } + } } return compareEqual, false diff --git a/vendor/github.com/stretchr/testify/assert/assertion_compare_can_convert.go b/vendor/github.com/stretchr/testify/assert/assertion_compare_can_convert.go deleted file mode 100644 index da867903e..000000000 --- a/vendor/github.com/stretchr/testify/assert/assertion_compare_can_convert.go +++ /dev/null @@ -1,16 +0,0 @@ -//go:build go1.17 -// +build go1.17 - -// TODO: once support for Go 1.16 is dropped, this file can be -// merged/removed with assertion_compare_go1.17_test.go and -// assertion_compare_legacy.go - -package assert - -import "reflect" - -// Wrapper around reflect.Value.CanConvert, for compatibility -// reasons. -func canConvert(value reflect.Value, to reflect.Type) bool { - return value.CanConvert(to) -} diff --git a/vendor/github.com/stretchr/testify/assert/assertion_compare_legacy.go b/vendor/github.com/stretchr/testify/assert/assertion_compare_legacy.go deleted file mode 100644 index 1701af2a3..000000000 --- a/vendor/github.com/stretchr/testify/assert/assertion_compare_legacy.go +++ /dev/null @@ -1,16 +0,0 @@ -//go:build !go1.17 -// +build !go1.17 - -// TODO: once support for Go 1.16 is dropped, this file can be -// merged/removed with assertion_compare_go1.17_test.go and -// assertion_compare_can_convert.go - -package assert - -import "reflect" - -// Older versions of Go does not have the reflect.Value.CanConvert -// method. -func canConvert(value reflect.Value, to reflect.Type) bool { - return false -} diff --git a/vendor/github.com/stretchr/testify/assert/assertion_format.go b/vendor/github.com/stretchr/testify/assert/assertion_format.go index 84dbd6c79..3ddab109a 100644 --- a/vendor/github.com/stretchr/testify/assert/assertion_format.go +++ b/vendor/github.com/stretchr/testify/assert/assertion_format.go @@ -1,7 +1,4 @@ -/* -* CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen -* THIS FILE MUST NOT BE EDITED BY HAND - */ +// Code generated with github.com/stretchr/testify/_codegen; DO NOT EDIT. package assert @@ -107,7 +104,7 @@ func EqualExportedValuesf(t TestingT, expected interface{}, actual interface{}, return EqualExportedValues(t, expected, actual, append([]interface{}{msg}, args...)...) } -// EqualValuesf asserts that two objects are equal or convertable to the same types +// EqualValuesf asserts that two objects are equal or convertible to the same types // and equal. // // assert.EqualValuesf(t, uint32(123), int32(123), "error message %s", "formatted") @@ -616,6 +613,16 @@ func NotErrorIsf(t TestingT, err error, target error, msg string, args ...interf return NotErrorIs(t, err, target, append([]interface{}{msg}, args...)...) } +// NotImplementsf asserts that an object does not implement the specified interface. +// +// assert.NotImplementsf(t, (*MyInterface)(nil), new(MyObject), "error message %s", "formatted") +func NotImplementsf(t TestingT, interfaceObject interface{}, object interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return NotImplements(t, interfaceObject, object, append([]interface{}{msg}, args...)...) +} + // NotNilf asserts that the specified object is not nil. // // assert.NotNilf(t, err, "error message %s", "formatted") @@ -660,10 +667,12 @@ func NotSamef(t TestingT, expected interface{}, actual interface{}, msg string, return NotSame(t, expected, actual, append([]interface{}{msg}, args...)...) } -// NotSubsetf asserts that the specified list(array, slice...) contains not all -// elements given in the specified subset(array, slice...). +// NotSubsetf asserts that the specified list(array, slice...) or map does NOT +// contain all elements given in the specified subset list(array, slice...) or +// map. // -// assert.NotSubsetf(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted") +// assert.NotSubsetf(t, [1, 3, 4], [1, 2], "error message %s", "formatted") +// assert.NotSubsetf(t, {"x": 1, "y": 2}, {"z": 3}, "error message %s", "formatted") func NotSubsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() @@ -747,10 +756,11 @@ func Samef(t TestingT, expected interface{}, actual interface{}, msg string, arg return Same(t, expected, actual, append([]interface{}{msg}, args...)...) } -// Subsetf asserts that the specified list(array, slice...) contains all -// elements given in the specified subset(array, slice...). +// Subsetf asserts that the specified list(array, slice...) or map contains all +// elements given in the specified subset list(array, slice...) or map. // -// assert.Subsetf(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted") +// assert.Subsetf(t, [1, 2, 3], [1, 2], "error message %s", "formatted") +// assert.Subsetf(t, {"x": 1, "y": 2}, {"x": 1}, "error message %s", "formatted") func Subsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() diff --git a/vendor/github.com/stretchr/testify/assert/assertion_forward.go b/vendor/github.com/stretchr/testify/assert/assertion_forward.go index b1d94aec5..a84e09bd4 100644 --- a/vendor/github.com/stretchr/testify/assert/assertion_forward.go +++ b/vendor/github.com/stretchr/testify/assert/assertion_forward.go @@ -1,7 +1,4 @@ -/* -* CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen -* THIS FILE MUST NOT BE EDITED BY HAND - */ +// Code generated with github.com/stretchr/testify/_codegen; DO NOT EDIT. package assert @@ -189,7 +186,7 @@ func (a *Assertions) EqualExportedValuesf(expected interface{}, actual interface return EqualExportedValuesf(a.t, expected, actual, msg, args...) } -// EqualValues asserts that two objects are equal or convertable to the same types +// EqualValues asserts that two objects are equal or convertible to the same types // and equal. // // a.EqualValues(uint32(123), int32(123)) @@ -200,7 +197,7 @@ func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAn return EqualValues(a.t, expected, actual, msgAndArgs...) } -// EqualValuesf asserts that two objects are equal or convertable to the same types +// EqualValuesf asserts that two objects are equal or convertible to the same types // and equal. // // a.EqualValuesf(uint32(123), int32(123), "error message %s", "formatted") @@ -1221,6 +1218,26 @@ func (a *Assertions) NotErrorIsf(err error, target error, msg string, args ...in return NotErrorIsf(a.t, err, target, msg, args...) } +// NotImplements asserts that an object does not implement the specified interface. +// +// a.NotImplements((*MyInterface)(nil), new(MyObject)) +func (a *Assertions) NotImplements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NotImplements(a.t, interfaceObject, object, msgAndArgs...) +} + +// NotImplementsf asserts that an object does not implement the specified interface. +// +// a.NotImplementsf((*MyInterface)(nil), new(MyObject), "error message %s", "formatted") +func (a *Assertions) NotImplementsf(interfaceObject interface{}, object interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NotImplementsf(a.t, interfaceObject, object, msg, args...) +} + // NotNil asserts that the specified object is not nil. // // a.NotNil(err) @@ -1309,10 +1326,12 @@ func (a *Assertions) NotSamef(expected interface{}, actual interface{}, msg stri return NotSamef(a.t, expected, actual, msg, args...) } -// NotSubset asserts that the specified list(array, slice...) contains not all -// elements given in the specified subset(array, slice...). +// NotSubset asserts that the specified list(array, slice...) or map does NOT +// contain all elements given in the specified subset list(array, slice...) or +// map. // -// a.NotSubset([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]") +// a.NotSubset([1, 3, 4], [1, 2]) +// a.NotSubset({"x": 1, "y": 2}, {"z": 3}) func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1320,10 +1339,12 @@ func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs return NotSubset(a.t, list, subset, msgAndArgs...) } -// NotSubsetf asserts that the specified list(array, slice...) contains not all -// elements given in the specified subset(array, slice...). +// NotSubsetf asserts that the specified list(array, slice...) or map does NOT +// contain all elements given in the specified subset list(array, slice...) or +// map. // -// a.NotSubsetf([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted") +// a.NotSubsetf([1, 3, 4], [1, 2], "error message %s", "formatted") +// a.NotSubsetf({"x": 1, "y": 2}, {"z": 3}, "error message %s", "formatted") func (a *Assertions) NotSubsetf(list interface{}, subset interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1483,10 +1504,11 @@ func (a *Assertions) Samef(expected interface{}, actual interface{}, msg string, return Samef(a.t, expected, actual, msg, args...) } -// Subset asserts that the specified list(array, slice...) contains all -// elements given in the specified subset(array, slice...). +// Subset asserts that the specified list(array, slice...) or map contains all +// elements given in the specified subset list(array, slice...) or map. // -// a.Subset([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]") +// a.Subset([1, 2, 3], [1, 2]) +// a.Subset({"x": 1, "y": 2}, {"x": 1}) func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1494,10 +1516,11 @@ func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ... return Subset(a.t, list, subset, msgAndArgs...) } -// Subsetf asserts that the specified list(array, slice...) contains all -// elements given in the specified subset(array, slice...). +// Subsetf asserts that the specified list(array, slice...) or map contains all +// elements given in the specified subset list(array, slice...) or map. // -// a.Subsetf([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted") +// a.Subsetf([1, 2, 3], [1, 2], "error message %s", "formatted") +// a.Subsetf({"x": 1, "y": 2}, {"x": 1}, "error message %s", "formatted") func (a *Assertions) Subsetf(list interface{}, subset interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() diff --git a/vendor/github.com/stretchr/testify/assert/assertions.go b/vendor/github.com/stretchr/testify/assert/assertions.go index a55d1bba9..0b7570f21 100644 --- a/vendor/github.com/stretchr/testify/assert/assertions.go +++ b/vendor/github.com/stretchr/testify/assert/assertions.go @@ -19,7 +19,7 @@ import ( "github.com/davecgh/go-spew/spew" "github.com/pmezard/go-difflib/difflib" - yaml "gopkg.in/yaml.v3" + "gopkg.in/yaml.v3" ) //go:generate sh -c "cd ../_codegen && go build && cd - && ../_codegen/_codegen -output-package=assert -template=assertion_format.go.tmpl" @@ -110,7 +110,12 @@ func copyExportedFields(expected interface{}) interface{} { return result.Interface() case reflect.Array, reflect.Slice: - result := reflect.MakeSlice(expectedType, expectedValue.Len(), expectedValue.Len()) + var result reflect.Value + if expectedKind == reflect.Array { + result = reflect.New(reflect.ArrayOf(expectedValue.Len(), expectedType.Elem())).Elem() + } else { + result = reflect.MakeSlice(expectedType, expectedValue.Len(), expectedValue.Len()) + } for i := 0; i < expectedValue.Len(); i++ { index := expectedValue.Index(i) if isNil(index) { @@ -140,6 +145,8 @@ func copyExportedFields(expected interface{}) interface{} { // structures. // // This function does no assertion of any kind. +// +// Deprecated: Use [EqualExportedValues] instead. func ObjectsExportedFieldsAreEqual(expected, actual interface{}) bool { expectedCleaned := copyExportedFields(expected) actualCleaned := copyExportedFields(actual) @@ -153,17 +160,40 @@ func ObjectsAreEqualValues(expected, actual interface{}) bool { return true } - actualType := reflect.TypeOf(actual) - if actualType == nil { + expectedValue := reflect.ValueOf(expected) + actualValue := reflect.ValueOf(actual) + if !expectedValue.IsValid() || !actualValue.IsValid() { return false } - expectedValue := reflect.ValueOf(expected) - if expectedValue.IsValid() && expectedValue.Type().ConvertibleTo(actualType) { + + expectedType := expectedValue.Type() + actualType := actualValue.Type() + if !expectedType.ConvertibleTo(actualType) { + return false + } + + if !isNumericType(expectedType) || !isNumericType(actualType) { // Attempt comparison after type conversion - return reflect.DeepEqual(expectedValue.Convert(actualType).Interface(), actual) + return reflect.DeepEqual( + expectedValue.Convert(actualType).Interface(), actual, + ) } - return false + // If BOTH values are numeric, there are chances of false positives due + // to overflow or underflow. So, we need to make sure to always convert + // the smaller type to a larger type before comparing. + if expectedType.Size() >= actualType.Size() { + return actualValue.Convert(expectedType).Interface() == expected + } + + return expectedValue.Convert(actualType).Interface() == actual +} + +// isNumericType returns true if the type is one of: +// int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, +// float32, float64, complex64, complex128 +func isNumericType(t reflect.Type) bool { + return t.Kind() >= reflect.Int && t.Kind() <= reflect.Complex128 } /* CallerInfo is necessary because the assert functions use the testing object @@ -266,7 +296,7 @@ func messageFromMsgAndArgs(msgAndArgs ...interface{}) string { // Aligns the provided message so that all lines after the first line start at the same location as the first line. // Assumes that the first line starts at the correct location (after carriage return, tab, label, spacer and tab). -// The longestLabelLen parameter specifies the length of the longest label in the output (required becaues this is the +// The longestLabelLen parameter specifies the length of the longest label in the output (required because this is the // basis on which the alignment occurs). func indentMessageLines(message string, longestLabelLen int) string { outBuf := new(bytes.Buffer) @@ -382,6 +412,25 @@ func Implements(t TestingT, interfaceObject interface{}, object interface{}, msg return true } +// NotImplements asserts that an object does not implement the specified interface. +// +// assert.NotImplements(t, (*MyInterface)(nil), new(MyObject)) +func NotImplements(t TestingT, interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + interfaceType := reflect.TypeOf(interfaceObject).Elem() + + if object == nil { + return Fail(t, fmt.Sprintf("Cannot check if nil does not implement %v", interfaceType), msgAndArgs...) + } + if reflect.TypeOf(object).Implements(interfaceType) { + return Fail(t, fmt.Sprintf("%T implements %v", object, interfaceType), msgAndArgs...) + } + + return true +} + // IsType asserts that the specified objects are of the same type. func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { @@ -496,7 +545,7 @@ func samePointers(first, second interface{}) bool { // representations appropriate to be presented to the user. // // If the values are not of like type, the returned strings will be prefixed -// with the type name, and the value will be enclosed in parenthesis similar +// with the type name, and the value will be enclosed in parentheses similar // to a type conversion in the Go grammar. func formatUnequalValues(expected, actual interface{}) (e string, a string) { if reflect.TypeOf(expected) != reflect.TypeOf(actual) { @@ -523,7 +572,7 @@ func truncatingFormat(data interface{}) string { return value } -// EqualValues asserts that two objects are equal or convertable to the same types +// EqualValues asserts that two objects are equal or convertible to the same types // and equal. // // assert.EqualValues(t, uint32(123), int32(123)) @@ -566,12 +615,19 @@ func EqualExportedValues(t TestingT, expected, actual interface{}, msgAndArgs .. return Fail(t, fmt.Sprintf("Types expected to match exactly\n\t%v != %v", aType, bType), msgAndArgs...) } + if aType.Kind() == reflect.Ptr { + aType = aType.Elem() + } + if bType.Kind() == reflect.Ptr { + bType = bType.Elem() + } + if aType.Kind() != reflect.Struct { - return Fail(t, fmt.Sprintf("Types expected to both be struct \n\t%v != %v", aType.Kind(), reflect.Struct), msgAndArgs...) + return Fail(t, fmt.Sprintf("Types expected to both be struct or pointer to struct \n\t%v != %v", aType.Kind(), reflect.Struct), msgAndArgs...) } if bType.Kind() != reflect.Struct { - return Fail(t, fmt.Sprintf("Types expected to both be struct \n\t%v != %v", bType.Kind(), reflect.Struct), msgAndArgs...) + return Fail(t, fmt.Sprintf("Types expected to both be struct or pointer to struct \n\t%v != %v", bType.Kind(), reflect.Struct), msgAndArgs...) } expected = copyExportedFields(expected) @@ -620,17 +676,6 @@ func NotNil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { return Fail(t, "Expected value not to be nil.", msgAndArgs...) } -// containsKind checks if a specified kind in the slice of kinds. -func containsKind(kinds []reflect.Kind, kind reflect.Kind) bool { - for i := 0; i < len(kinds); i++ { - if kind == kinds[i] { - return true - } - } - - return false -} - // isNil checks if a specified object is nil or not, without Failing. func isNil(object interface{}) bool { if object == nil { @@ -638,16 +683,13 @@ func isNil(object interface{}) bool { } value := reflect.ValueOf(object) - kind := value.Kind() - isNilableKind := containsKind( - []reflect.Kind{ - reflect.Chan, reflect.Func, - reflect.Interface, reflect.Map, - reflect.Ptr, reflect.Slice, reflect.UnsafePointer}, - kind) - - if isNilableKind && value.IsNil() { - return true + switch value.Kind() { + case + reflect.Chan, reflect.Func, + reflect.Interface, reflect.Map, + reflect.Ptr, reflect.Slice, reflect.UnsafePointer: + + return value.IsNil() } return false @@ -731,16 +773,14 @@ func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { } -// getLen try to get length of object. -// return (false, 0) if impossible. -func getLen(x interface{}) (ok bool, length int) { +// getLen tries to get the length of an object. +// It returns (0, false) if impossible. +func getLen(x interface{}) (length int, ok bool) { v := reflect.ValueOf(x) defer func() { - if e := recover(); e != nil { - ok = false - } + ok = recover() == nil }() - return true, v.Len() + return v.Len(), true } // Len asserts that the specified object has specific length. @@ -751,13 +791,13 @@ func Len(t TestingT, object interface{}, length int, msgAndArgs ...interface{}) if h, ok := t.(tHelper); ok { h.Helper() } - ok, l := getLen(object) + l, ok := getLen(object) if !ok { - return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", object), msgAndArgs...) + return Fail(t, fmt.Sprintf("\"%v\" could not be applied builtin len()", object), msgAndArgs...) } if l != length { - return Fail(t, fmt.Sprintf("\"%s\" should have %d item(s), but has %d", object, length, l), msgAndArgs...) + return Fail(t, fmt.Sprintf("\"%v\" should have %d item(s), but has %d", object, length, l), msgAndArgs...) } return true } @@ -919,10 +959,11 @@ func NotContains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) } -// Subset asserts that the specified list(array, slice...) contains all -// elements given in the specified subset(array, slice...). +// Subset asserts that the specified list(array, slice...) or map contains all +// elements given in the specified subset list(array, slice...) or map. // -// assert.Subset(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]") +// assert.Subset(t, [1, 2, 3], [1, 2]) +// assert.Subset(t, {"x": 1, "y": 2}, {"x": 1}) func Subset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok bool) { if h, ok := t.(tHelper); ok { h.Helper() @@ -975,10 +1016,12 @@ func Subset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok return true } -// NotSubset asserts that the specified list(array, slice...) contains not all -// elements given in the specified subset(array, slice...). +// NotSubset asserts that the specified list(array, slice...) or map does NOT +// contain all elements given in the specified subset list(array, slice...) or +// map. // -// assert.NotSubset(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]") +// assert.NotSubset(t, [1, 3, 4], [1, 2]) +// assert.NotSubset(t, {"x": 1, "y": 2}, {"z": 3}) func NotSubset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok bool) { if h, ok := t.(tHelper); ok { h.Helper() @@ -1439,7 +1482,7 @@ func InEpsilon(t TestingT, expected, actual interface{}, epsilon float64, msgAnd h.Helper() } if math.IsNaN(epsilon) { - return Fail(t, "epsilon must not be NaN") + return Fail(t, "epsilon must not be NaN", msgAndArgs...) } actualEpsilon, err := calcRelativeError(expected, actual) if err != nil { @@ -1458,19 +1501,26 @@ func InEpsilonSlice(t TestingT, expected, actual interface{}, epsilon float64, m if h, ok := t.(tHelper); ok { h.Helper() } - if expected == nil || actual == nil || - reflect.TypeOf(actual).Kind() != reflect.Slice || - reflect.TypeOf(expected).Kind() != reflect.Slice { + + if expected == nil || actual == nil { return Fail(t, "Parameters must be slice", msgAndArgs...) } - actualSlice := reflect.ValueOf(actual) expectedSlice := reflect.ValueOf(expected) + actualSlice := reflect.ValueOf(actual) - for i := 0; i < actualSlice.Len(); i++ { - result := InEpsilon(t, actualSlice.Index(i).Interface(), expectedSlice.Index(i).Interface(), epsilon) - if !result { - return result + if expectedSlice.Type().Kind() != reflect.Slice { + return Fail(t, "Expected value must be slice", msgAndArgs...) + } + + expectedLen := expectedSlice.Len() + if !IsType(t, expected, actual) || !Len(t, actual, expectedLen) { + return false + } + + for i := 0; i < expectedLen; i++ { + if !InEpsilon(t, expectedSlice.Index(i).Interface(), actualSlice.Index(i).Interface(), epsilon, "at index %d", i) { + return false } } @@ -1870,23 +1920,18 @@ func (c *CollectT) Errorf(format string, args ...interface{}) { } // FailNow panics. -func (c *CollectT) FailNow() { +func (*CollectT) FailNow() { panic("Assertion failed") } -// Reset clears the collected errors. -func (c *CollectT) Reset() { - c.errors = nil +// Deprecated: That was a method for internal usage that should not have been published. Now just panics. +func (*CollectT) Reset() { + panic("Reset() is deprecated") } -// Copy copies the collected errors to the supplied t. -func (c *CollectT) Copy(t TestingT) { - if tt, ok := t.(tHelper); ok { - tt.Helper() - } - for _, err := range c.errors { - t.Errorf("%v", err) - } +// Deprecated: That was a method for internal usage that should not have been published. Now just panics. +func (*CollectT) Copy(TestingT) { + panic("Copy() is deprecated") } // EventuallyWithT asserts that given condition will be met in waitFor time, @@ -1912,8 +1957,8 @@ func EventuallyWithT(t TestingT, condition func(collect *CollectT), waitFor time h.Helper() } - collect := new(CollectT) - ch := make(chan bool, 1) + var lastFinishedTickErrs []error + ch := make(chan []error, 1) timer := time.NewTimer(waitFor) defer timer.Stop() @@ -1924,19 +1969,25 @@ func EventuallyWithT(t TestingT, condition func(collect *CollectT), waitFor time for tick := ticker.C; ; { select { case <-timer.C: - collect.Copy(t) + for _, err := range lastFinishedTickErrs { + t.Errorf("%v", err) + } return Fail(t, "Condition never satisfied", msgAndArgs...) case <-tick: tick = nil - collect.Reset() go func() { + collect := new(CollectT) + defer func() { + ch <- collect.errors + }() condition(collect) - ch <- len(collect.errors) == 0 }() - case v := <-ch: - if v { + case errs := <-ch: + if len(errs) == 0 { return true } + // Keep the errors from the last ended condition, so that they can be copied to t if timeout is reached. + lastFinishedTickErrs = errs tick = ticker.C } } diff --git a/vendor/github.com/stretchr/testify/assert/http_assertions.go b/vendor/github.com/stretchr/testify/assert/http_assertions.go index d8038c28a..861ed4b7c 100644 --- a/vendor/github.com/stretchr/testify/assert/http_assertions.go +++ b/vendor/github.com/stretchr/testify/assert/http_assertions.go @@ -12,7 +12,7 @@ import ( // an error if building a new request fails. func httpCode(handler http.HandlerFunc, method, url string, values url.Values) (int, error) { w := httptest.NewRecorder() - req, err := http.NewRequest(method, url, nil) + req, err := http.NewRequest(method, url, http.NoBody) if err != nil { return -1, err } @@ -32,12 +32,12 @@ func HTTPSuccess(t TestingT, handler http.HandlerFunc, method, url string, value } code, err := httpCode(handler, method, url, values) if err != nil { - Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err)) + Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err), msgAndArgs...) } isSuccessCode := code >= http.StatusOK && code <= http.StatusPartialContent if !isSuccessCode { - Fail(t, fmt.Sprintf("Expected HTTP success status code for %q but received %d", url+"?"+values.Encode(), code)) + Fail(t, fmt.Sprintf("Expected HTTP success status code for %q but received %d", url+"?"+values.Encode(), code), msgAndArgs...) } return isSuccessCode @@ -54,12 +54,12 @@ func HTTPRedirect(t TestingT, handler http.HandlerFunc, method, url string, valu } code, err := httpCode(handler, method, url, values) if err != nil { - Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err)) + Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err), msgAndArgs...) } isRedirectCode := code >= http.StatusMultipleChoices && code <= http.StatusTemporaryRedirect if !isRedirectCode { - Fail(t, fmt.Sprintf("Expected HTTP redirect status code for %q but received %d", url+"?"+values.Encode(), code)) + Fail(t, fmt.Sprintf("Expected HTTP redirect status code for %q but received %d", url+"?"+values.Encode(), code), msgAndArgs...) } return isRedirectCode @@ -76,12 +76,12 @@ func HTTPError(t TestingT, handler http.HandlerFunc, method, url string, values } code, err := httpCode(handler, method, url, values) if err != nil { - Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err)) + Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err), msgAndArgs...) } isErrorCode := code >= http.StatusBadRequest if !isErrorCode { - Fail(t, fmt.Sprintf("Expected HTTP error status code for %q but received %d", url+"?"+values.Encode(), code)) + Fail(t, fmt.Sprintf("Expected HTTP error status code for %q but received %d", url+"?"+values.Encode(), code), msgAndArgs...) } return isErrorCode @@ -98,12 +98,12 @@ func HTTPStatusCode(t TestingT, handler http.HandlerFunc, method, url string, va } code, err := httpCode(handler, method, url, values) if err != nil { - Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err)) + Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err), msgAndArgs...) } successful := code == statuscode if !successful { - Fail(t, fmt.Sprintf("Expected HTTP status code %d for %q but received %d", statuscode, url+"?"+values.Encode(), code)) + Fail(t, fmt.Sprintf("Expected HTTP status code %d for %q but received %d", statuscode, url+"?"+values.Encode(), code), msgAndArgs...) } return successful @@ -113,7 +113,10 @@ func HTTPStatusCode(t TestingT, handler http.HandlerFunc, method, url string, va // empty string if building a new request fails. func HTTPBody(handler http.HandlerFunc, method, url string, values url.Values) string { w := httptest.NewRecorder() - req, err := http.NewRequest(method, url+"?"+values.Encode(), nil) + if len(values) > 0 { + url += "?" + values.Encode() + } + req, err := http.NewRequest(method, url, http.NoBody) if err != nil { return "" } @@ -135,7 +138,7 @@ func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method, url string, contains := strings.Contains(body, fmt.Sprint(str)) if !contains { - Fail(t, fmt.Sprintf("Expected response body for \"%s\" to contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body)) + Fail(t, fmt.Sprintf("Expected response body for \"%s\" to contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body), msgAndArgs...) } return contains @@ -155,7 +158,7 @@ func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, method, url strin contains := strings.Contains(body, fmt.Sprint(str)) if contains { - Fail(t, fmt.Sprintf("Expected response body for \"%s\" to NOT contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body)) + Fail(t, fmt.Sprintf("Expected response body for \"%s\" to NOT contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body), msgAndArgs...) } return !contains diff --git a/vendor/github.com/stretchr/testify/require/require.go b/vendor/github.com/stretchr/testify/require/require.go index 63f852147..506a82f80 100644 --- a/vendor/github.com/stretchr/testify/require/require.go +++ b/vendor/github.com/stretchr/testify/require/require.go @@ -1,7 +1,4 @@ -/* -* CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen -* THIS FILE MUST NOT BE EDITED BY HAND - */ +// Code generated with github.com/stretchr/testify/_codegen; DO NOT EDIT. package require @@ -235,7 +232,7 @@ func EqualExportedValuesf(t TestingT, expected interface{}, actual interface{}, t.FailNow() } -// EqualValues asserts that two objects are equal or convertable to the same types +// EqualValues asserts that two objects are equal or convertible to the same types // and equal. // // assert.EqualValues(t, uint32(123), int32(123)) @@ -249,7 +246,7 @@ func EqualValues(t TestingT, expected interface{}, actual interface{}, msgAndArg t.FailNow() } -// EqualValuesf asserts that two objects are equal or convertable to the same types +// EqualValuesf asserts that two objects are equal or convertible to the same types // and equal. // // assert.EqualValuesf(t, uint32(123), int32(123), "error message %s", "formatted") @@ -1546,6 +1543,32 @@ func NotErrorIsf(t TestingT, err error, target error, msg string, args ...interf t.FailNow() } +// NotImplements asserts that an object does not implement the specified interface. +// +// assert.NotImplements(t, (*MyInterface)(nil), new(MyObject)) +func NotImplements(t TestingT, interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.NotImplements(t, interfaceObject, object, msgAndArgs...) { + return + } + t.FailNow() +} + +// NotImplementsf asserts that an object does not implement the specified interface. +// +// assert.NotImplementsf(t, (*MyInterface)(nil), new(MyObject), "error message %s", "formatted") +func NotImplementsf(t TestingT, interfaceObject interface{}, object interface{}, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.NotImplementsf(t, interfaceObject, object, msg, args...) { + return + } + t.FailNow() +} + // NotNil asserts that the specified object is not nil. // // assert.NotNil(t, err) @@ -1658,10 +1681,12 @@ func NotSamef(t TestingT, expected interface{}, actual interface{}, msg string, t.FailNow() } -// NotSubset asserts that the specified list(array, slice...) contains not all -// elements given in the specified subset(array, slice...). +// NotSubset asserts that the specified list(array, slice...) or map does NOT +// contain all elements given in the specified subset list(array, slice...) or +// map. // -// assert.NotSubset(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]") +// assert.NotSubset(t, [1, 3, 4], [1, 2]) +// assert.NotSubset(t, {"x": 1, "y": 2}, {"z": 3}) func NotSubset(t TestingT, list interface{}, subset interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -1672,10 +1697,12 @@ func NotSubset(t TestingT, list interface{}, subset interface{}, msgAndArgs ...i t.FailNow() } -// NotSubsetf asserts that the specified list(array, slice...) contains not all -// elements given in the specified subset(array, slice...). +// NotSubsetf asserts that the specified list(array, slice...) or map does NOT +// contain all elements given in the specified subset list(array, slice...) or +// map. // -// assert.NotSubsetf(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted") +// assert.NotSubsetf(t, [1, 3, 4], [1, 2], "error message %s", "formatted") +// assert.NotSubsetf(t, {"x": 1, "y": 2}, {"z": 3}, "error message %s", "formatted") func NotSubsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -1880,10 +1907,11 @@ func Samef(t TestingT, expected interface{}, actual interface{}, msg string, arg t.FailNow() } -// Subset asserts that the specified list(array, slice...) contains all -// elements given in the specified subset(array, slice...). +// Subset asserts that the specified list(array, slice...) or map contains all +// elements given in the specified subset list(array, slice...) or map. // -// assert.Subset(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]") +// assert.Subset(t, [1, 2, 3], [1, 2]) +// assert.Subset(t, {"x": 1, "y": 2}, {"x": 1}) func Subset(t TestingT, list interface{}, subset interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -1894,10 +1922,11 @@ func Subset(t TestingT, list interface{}, subset interface{}, msgAndArgs ...inte t.FailNow() } -// Subsetf asserts that the specified list(array, slice...) contains all -// elements given in the specified subset(array, slice...). +// Subsetf asserts that the specified list(array, slice...) or map contains all +// elements given in the specified subset list(array, slice...) or map. // -// assert.Subsetf(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted") +// assert.Subsetf(t, [1, 2, 3], [1, 2], "error message %s", "formatted") +// assert.Subsetf(t, {"x": 1, "y": 2}, {"x": 1}, "error message %s", "formatted") func Subsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() diff --git a/vendor/github.com/stretchr/testify/require/require_forward.go b/vendor/github.com/stretchr/testify/require/require_forward.go index 3b5b09330..eee8310a5 100644 --- a/vendor/github.com/stretchr/testify/require/require_forward.go +++ b/vendor/github.com/stretchr/testify/require/require_forward.go @@ -1,7 +1,4 @@ -/* -* CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen -* THIS FILE MUST NOT BE EDITED BY HAND - */ +// Code generated with github.com/stretchr/testify/_codegen; DO NOT EDIT. package require @@ -190,7 +187,7 @@ func (a *Assertions) EqualExportedValuesf(expected interface{}, actual interface EqualExportedValuesf(a.t, expected, actual, msg, args...) } -// EqualValues asserts that two objects are equal or convertable to the same types +// EqualValues asserts that two objects are equal or convertible to the same types // and equal. // // a.EqualValues(uint32(123), int32(123)) @@ -201,7 +198,7 @@ func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAn EqualValues(a.t, expected, actual, msgAndArgs...) } -// EqualValuesf asserts that two objects are equal or convertable to the same types +// EqualValuesf asserts that two objects are equal or convertible to the same types // and equal. // // a.EqualValuesf(uint32(123), int32(123), "error message %s", "formatted") @@ -1222,6 +1219,26 @@ func (a *Assertions) NotErrorIsf(err error, target error, msg string, args ...in NotErrorIsf(a.t, err, target, msg, args...) } +// NotImplements asserts that an object does not implement the specified interface. +// +// a.NotImplements((*MyInterface)(nil), new(MyObject)) +func (a *Assertions) NotImplements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + NotImplements(a.t, interfaceObject, object, msgAndArgs...) +} + +// NotImplementsf asserts that an object does not implement the specified interface. +// +// a.NotImplementsf((*MyInterface)(nil), new(MyObject), "error message %s", "formatted") +func (a *Assertions) NotImplementsf(interfaceObject interface{}, object interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + NotImplementsf(a.t, interfaceObject, object, msg, args...) +} + // NotNil asserts that the specified object is not nil. // // a.NotNil(err) @@ -1310,10 +1327,12 @@ func (a *Assertions) NotSamef(expected interface{}, actual interface{}, msg stri NotSamef(a.t, expected, actual, msg, args...) } -// NotSubset asserts that the specified list(array, slice...) contains not all -// elements given in the specified subset(array, slice...). +// NotSubset asserts that the specified list(array, slice...) or map does NOT +// contain all elements given in the specified subset list(array, slice...) or +// map. // -// a.NotSubset([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]") +// a.NotSubset([1, 3, 4], [1, 2]) +// a.NotSubset({"x": 1, "y": 2}, {"z": 3}) func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1321,10 +1340,12 @@ func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs NotSubset(a.t, list, subset, msgAndArgs...) } -// NotSubsetf asserts that the specified list(array, slice...) contains not all -// elements given in the specified subset(array, slice...). +// NotSubsetf asserts that the specified list(array, slice...) or map does NOT +// contain all elements given in the specified subset list(array, slice...) or +// map. // -// a.NotSubsetf([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted") +// a.NotSubsetf([1, 3, 4], [1, 2], "error message %s", "formatted") +// a.NotSubsetf({"x": 1, "y": 2}, {"z": 3}, "error message %s", "formatted") func (a *Assertions) NotSubsetf(list interface{}, subset interface{}, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1484,10 +1505,11 @@ func (a *Assertions) Samef(expected interface{}, actual interface{}, msg string, Samef(a.t, expected, actual, msg, args...) } -// Subset asserts that the specified list(array, slice...) contains all -// elements given in the specified subset(array, slice...). +// Subset asserts that the specified list(array, slice...) or map contains all +// elements given in the specified subset list(array, slice...) or map. // -// a.Subset([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]") +// a.Subset([1, 2, 3], [1, 2]) +// a.Subset({"x": 1, "y": 2}, {"x": 1}) func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1495,10 +1517,11 @@ func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ... Subset(a.t, list, subset, msgAndArgs...) } -// Subsetf asserts that the specified list(array, slice...) contains all -// elements given in the specified subset(array, slice...). +// Subsetf asserts that the specified list(array, slice...) or map contains all +// elements given in the specified subset list(array, slice...) or map. // -// a.Subsetf([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted") +// a.Subsetf([1, 2, 3], [1, 2], "error message %s", "formatted") +// a.Subsetf({"x": 1, "y": 2}, {"x": 1}, "error message %s", "formatted") func (a *Assertions) Subsetf(list interface{}, subset interface{}, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() diff --git a/vendor/github.com/tinylib/msgp/msgp/advise_other.go b/vendor/github.com/tinylib/msgp/msgp/advise_other.go index 1b6ed5727..07f524af7 100644 --- a/vendor/github.com/tinylib/msgp/msgp/advise_other.go +++ b/vendor/github.com/tinylib/msgp/msgp/advise_other.go @@ -1,5 +1,5 @@ -//go:build (!linux && !tinygo) || appengine -// +build !linux,!tinygo appengine +//go:build (!linux && !tinygo && !windows) || appengine +// +build !linux,!tinygo,!windows appengine package msgp diff --git a/vendor/github.com/tinylib/msgp/msgp/defs.go b/vendor/github.com/tinylib/msgp/msgp/defs.go index e265aa4f8..47a8c1834 100644 --- a/vendor/github.com/tinylib/msgp/msgp/defs.go +++ b/vendor/github.com/tinylib/msgp/msgp/defs.go @@ -32,6 +32,10 @@ const ( last5 = 0x1f first3 = 0xe0 last7 = 0x7f + + // recursionLimit is the limit of recursive calls. + // This limits the call depth of dynamic code, like Skip and interface conversions. + recursionLimit = 100000 ) func isfixint(b byte) bool { diff --git a/vendor/github.com/tinylib/msgp/msgp/errors.go b/vendor/github.com/tinylib/msgp/msgp/errors.go index 4f19359a2..984cca32a 100644 --- a/vendor/github.com/tinylib/msgp/msgp/errors.go +++ b/vendor/github.com/tinylib/msgp/msgp/errors.go @@ -13,6 +13,10 @@ var ( // contain the contents of the message ErrShortBytes error = errShort{} + // ErrRecursion is returned when the maximum recursion limit is reached for an operation. + // This should only realistically be seen on adversarial data trying to exhaust the stack. + ErrRecursion error = errRecursion{} + // this error is only returned // if we reach code that should // be unreachable @@ -134,6 +138,11 @@ func (f errFatal) Resumable() bool { return false } func (f errFatal) withContext(ctx string) error { f.ctx = addCtx(f.ctx, ctx); return f } +type errRecursion struct{} + +func (e errRecursion) Error() string { return "msgp: recursion limit reached" } +func (e errRecursion) Resumable() bool { return false } + // ArrayError is an error returned // when decoding a fix-sized array // of the wrong size diff --git a/vendor/github.com/tinylib/msgp/msgp/extension.go b/vendor/github.com/tinylib/msgp/msgp/extension.go index b5ef3a4e3..5f7624730 100644 --- a/vendor/github.com/tinylib/msgp/msgp/extension.go +++ b/vendor/github.com/tinylib/msgp/msgp/extension.go @@ -121,11 +121,8 @@ func (r *RawExtension) UnmarshalBinary(b []byte) error { return nil } -// WriteExtension writes an extension type to the writer -func (mw *Writer) WriteExtension(e Extension) error { - l := e.Len() - var err error - switch l { +func (mw *Writer) writeExtensionHeader(length int, extType int8) error { + switch length { case 0: o, err := mw.require(3) if err != nil { @@ -133,75 +130,88 @@ func (mw *Writer) WriteExtension(e Extension) error { } mw.buf[o] = mext8 mw.buf[o+1] = 0 - mw.buf[o+2] = byte(e.ExtensionType()) + mw.buf[o+2] = byte(extType) case 1: o, err := mw.require(2) if err != nil { return err } mw.buf[o] = mfixext1 - mw.buf[o+1] = byte(e.ExtensionType()) + mw.buf[o+1] = byte(extType) case 2: o, err := mw.require(2) if err != nil { return err } mw.buf[o] = mfixext2 - mw.buf[o+1] = byte(e.ExtensionType()) + mw.buf[o+1] = byte(extType) case 4: o, err := mw.require(2) if err != nil { return err } mw.buf[o] = mfixext4 - mw.buf[o+1] = byte(e.ExtensionType()) + mw.buf[o+1] = byte(extType) case 8: o, err := mw.require(2) if err != nil { return err } mw.buf[o] = mfixext8 - mw.buf[o+1] = byte(e.ExtensionType()) + mw.buf[o+1] = byte(extType) case 16: o, err := mw.require(2) if err != nil { return err } mw.buf[o] = mfixext16 - mw.buf[o+1] = byte(e.ExtensionType()) + mw.buf[o+1] = byte(extType) default: switch { - case l < math.MaxUint8: + case length < math.MaxUint8: o, err := mw.require(3) if err != nil { return err } mw.buf[o] = mext8 - mw.buf[o+1] = byte(uint8(l)) - mw.buf[o+2] = byte(e.ExtensionType()) - case l < math.MaxUint16: + mw.buf[o+1] = byte(uint8(length)) + mw.buf[o+2] = byte(extType) + case length < math.MaxUint16: o, err := mw.require(4) if err != nil { return err } mw.buf[o] = mext16 - big.PutUint16(mw.buf[o+1:], uint16(l)) - mw.buf[o+3] = byte(e.ExtensionType()) + big.PutUint16(mw.buf[o+1:], uint16(length)) + mw.buf[o+3] = byte(extType) default: o, err := mw.require(6) if err != nil { return err } mw.buf[o] = mext32 - big.PutUint32(mw.buf[o+1:], uint32(l)) - mw.buf[o+5] = byte(e.ExtensionType()) + big.PutUint32(mw.buf[o+1:], uint32(length)) + mw.buf[o+5] = byte(extType) } } + + return nil +} + +// WriteExtension writes an extension type to the writer +func (mw *Writer) WriteExtension(e Extension) error { + length := e.Len() + + err := mw.writeExtensionHeader(length, e.ExtensionType()) + if err != nil { + return err + } + // we can only write directly to the // buffer if we're sure that it // fits the object - if l <= mw.bufsize() { - o, err := mw.require(l) + if length <= mw.bufsize() { + o, err := mw.require(length) if err != nil { return err } @@ -214,36 +224,50 @@ func (mw *Writer) WriteExtension(e Extension) error { if err != nil { return err } - buf := make([]byte, l) + buf := make([]byte, length) err = e.MarshalBinaryTo(buf) if err != nil { return err } mw.buf = buf - mw.wloc = l + mw.wloc = length + return nil +} + +// WriteExtensionRaw writes an extension type to the writer +func (mw *Writer) WriteExtensionRaw(extType int8, payload []byte) error { + if err := mw.writeExtensionHeader(len(payload), extType); err != nil { + return err + } + + // instead of using mw.Write(), we'll copy the data through the internal + // buffer, otherwise the payload would be moved to the heap + // (meaning we can use stack-allocated buffers with zero allocations) + for len(payload) > 0 { + chunkSize := mw.avail() + if chunkSize == 0 { + if err := mw.flush(); err != nil { + return err + } + chunkSize = mw.avail() + } + if chunkSize > len(payload) { + chunkSize = len(payload) + } + + mw.wloc += copy(mw.buf[mw.wloc:], payload[:chunkSize]) + payload = payload[chunkSize:] + } + return nil } // peek at the extension type, assuming the next // kind to be read is Extension func (m *Reader) peekExtensionType() (int8, error) { - p, err := m.R.Peek(2) - if err != nil { - return 0, err - } - spec := getBytespec(p[0]) - if spec.typ != ExtensionType { - return 0, badPrefix(ExtensionType, p[0]) - } - if spec.extra == constsize { - return int8(p[1]), nil - } - size := spec.size - p, err = m.R.Peek(int(size)) - if err != nil { - return 0, err - } - return int8(p[size-1]), nil + _, _, extType, err := m.peekExtensionHeader() + + return extType, err } // peekExtension peeks at the extension encoding type @@ -268,93 +292,40 @@ func peekExtension(b []byte) (int8, error) { return int8(b[size-1]), nil } -// ReadExtension reads the next object from the reader -// as an extension. ReadExtension will fail if the next -// object in the stream is not an extension, or if -// e.Type() is not the same as the wire type. -func (m *Reader) ReadExtension(e Extension) (err error) { +func (m *Reader) peekExtensionHeader() (offset int, length int, extType int8, err error) { var p []byte p, err = m.R.Peek(2) if err != nil { return } + + offset = 2 + lead := p[0] - var read int - var off int switch lead { case mfixext1: - if int8(p[1]) != e.ExtensionType() { - err = errExt(int8(p[1]), e.ExtensionType()) - return - } - p, err = m.R.Peek(3) - if err != nil { - return - } - err = e.UnmarshalBinary(p[2:]) - if err == nil { - _, err = m.R.Skip(3) - } + extType = int8(p[1]) + length = 1 return case mfixext2: - if int8(p[1]) != e.ExtensionType() { - err = errExt(int8(p[1]), e.ExtensionType()) - return - } - p, err = m.R.Peek(4) - if err != nil { - return - } - err = e.UnmarshalBinary(p[2:]) - if err == nil { - _, err = m.R.Skip(4) - } + extType = int8(p[1]) + length = 2 return case mfixext4: - if int8(p[1]) != e.ExtensionType() { - err = errExt(int8(p[1]), e.ExtensionType()) - return - } - p, err = m.R.Peek(6) - if err != nil { - return - } - err = e.UnmarshalBinary(p[2:]) - if err == nil { - _, err = m.R.Skip(6) - } + extType = int8(p[1]) + length = 4 return case mfixext8: - if int8(p[1]) != e.ExtensionType() { - err = errExt(int8(p[1]), e.ExtensionType()) - return - } - p, err = m.R.Peek(10) - if err != nil { - return - } - err = e.UnmarshalBinary(p[2:]) - if err == nil { - _, err = m.R.Skip(10) - } + extType = int8(p[1]) + length = 8 return case mfixext16: - if int8(p[1]) != e.ExtensionType() { - err = errExt(int8(p[1]), e.ExtensionType()) - return - } - p, err = m.R.Peek(18) - if err != nil { - return - } - err = e.UnmarshalBinary(p[2:]) - if err == nil { - _, err = m.R.Skip(18) - } + extType = int8(p[1]) + length = 16 return case mext8: @@ -362,51 +333,77 @@ func (m *Reader) ReadExtension(e Extension) (err error) { if err != nil { return } - if int8(p[2]) != e.ExtensionType() { - err = errExt(int8(p[2]), e.ExtensionType()) - return - } - read = int(uint8(p[1])) - off = 3 + offset = 3 + extType = int8(p[2]) + length = int(uint8(p[1])) case mext16: p, err = m.R.Peek(4) if err != nil { return } - if int8(p[3]) != e.ExtensionType() { - err = errExt(int8(p[3]), e.ExtensionType()) - return - } - read = int(big.Uint16(p[1:])) - off = 4 + offset = 4 + extType = int8(p[3]) + length = int(big.Uint16(p[1:])) case mext32: p, err = m.R.Peek(6) if err != nil { return } - if int8(p[5]) != e.ExtensionType() { - err = errExt(int8(p[5]), e.ExtensionType()) - return - } - read = int(big.Uint32(p[1:])) - off = 6 + offset = 6 + extType = int8(p[5]) + length = int(big.Uint32(p[1:])) default: err = badPrefix(ExtensionType, lead) return } - p, err = m.R.Peek(read + off) + return +} + +// ReadExtension reads the next object from the reader +// as an extension. ReadExtension will fail if the next +// object in the stream is not an extension, or if +// e.Type() is not the same as the wire type. +func (m *Reader) ReadExtension(e Extension) error { + offset, length, extType, err := m.peekExtensionHeader() if err != nil { - return + return err + } + + if expectedType := e.ExtensionType(); extType != expectedType { + return errExt(extType, expectedType) } - err = e.UnmarshalBinary(p[off:]) + + p, err := m.R.Peek(offset + length) + if err != nil { + return err + } + err = e.UnmarshalBinary(p[offset:]) if err == nil { - _, err = m.R.Skip(read + off) + // consume the peeked bytes + _, err = m.R.Skip(offset + length) } - return + return err +} + +// ReadExtensionRaw reads the next object from the reader +// as an extension. The returned slice is only +// valid until the next *Reader method call. +func (m *Reader) ReadExtensionRaw() (int8, []byte, error) { + offset, length, extType, err := m.peekExtensionHeader() + if err != nil { + return 0, nil, err + } + + payload, err := m.R.Next(offset + length) + if err != nil { + return 0, nil, err + } + + return extType, payload[offset:], nil } // AppendExtension appends a MessagePack extension to the provided slice diff --git a/vendor/github.com/tinylib/msgp/msgp/file.go b/vendor/github.com/tinylib/msgp/msgp/file.go index 0f2c37520..a6d91ede1 100644 --- a/vendor/github.com/tinylib/msgp/msgp/file.go +++ b/vendor/github.com/tinylib/msgp/msgp/file.go @@ -1,5 +1,5 @@ -//go:build (linux || darwin || dragonfly || freebsd || netbsd || openbsd) && !appengine && !tinygo -// +build linux darwin dragonfly freebsd netbsd openbsd +//go:build (linux || darwin || dragonfly || freebsd || illumos || netbsd || openbsd) && !appengine && !tinygo +// +build linux darwin dragonfly freebsd illumos netbsd openbsd // +build !appengine // +build !tinygo diff --git a/vendor/github.com/tinylib/msgp/msgp/file_port.go b/vendor/github.com/tinylib/msgp/msgp/file_port.go index 2bbb3ad13..dac0dba3f 100644 --- a/vendor/github.com/tinylib/msgp/msgp/file_port.go +++ b/vendor/github.com/tinylib/msgp/msgp/file_port.go @@ -4,7 +4,7 @@ package msgp import ( - "io/ioutil" + "io" "os" ) @@ -21,7 +21,7 @@ func ReadFile(dst Unmarshaler, file *os.File) error { return u.DecodeMsg(NewReader(file)) } - data, err := ioutil.ReadAll(file) + data, err := io.ReadAll(file) if err != nil { return err } diff --git a/vendor/github.com/tinylib/msgp/msgp/integers.go b/vendor/github.com/tinylib/msgp/msgp/integers.go index f817d7759..d07a5fba7 100644 --- a/vendor/github.com/tinylib/msgp/msgp/integers.go +++ b/vendor/github.com/tinylib/msgp/msgp/integers.go @@ -1,5 +1,7 @@ package msgp +import "encoding/binary" + /* ---------------------------------- integer encoding utilities (inline-able) @@ -11,6 +13,8 @@ package msgp ---------------------------------- */ func putMint64(b []byte, i int64) { + _ = b[8] // bounds check elimination + b[0] = mint64 b[1] = byte(i >> 56) b[2] = byte(i >> 48) @@ -23,6 +27,8 @@ func putMint64(b []byte, i int64) { } func getMint64(b []byte) int64 { + _ = b[8] // bounds check elimination + return (int64(b[1]) << 56) | (int64(b[2]) << 48) | (int64(b[3]) << 40) | (int64(b[4]) << 32) | (int64(b[5]) << 24) | (int64(b[6]) << 16) | @@ -30,6 +36,8 @@ func getMint64(b []byte) int64 { } func putMint32(b []byte, i int32) { + _ = b[4] // bounds check elimination + b[0] = mint32 b[1] = byte(i >> 24) b[2] = byte(i >> 16) @@ -38,20 +46,28 @@ func putMint32(b []byte, i int32) { } func getMint32(b []byte) int32 { + _ = b[4] // bounds check elimination + return (int32(b[1]) << 24) | (int32(b[2]) << 16) | (int32(b[3]) << 8) | (int32(b[4])) } func putMint16(b []byte, i int16) { + _ = b[2] // bounds check elimination + b[0] = mint16 b[1] = byte(i >> 8) b[2] = byte(i) } func getMint16(b []byte) (i int16) { + _ = b[2] // bounds check elimination + return (int16(b[1]) << 8) | int16(b[2]) } func putMint8(b []byte, i int8) { + _ = b[1] // bounds check elimination + b[0] = mint8 b[1] = byte(i) } @@ -61,6 +77,8 @@ func getMint8(b []byte) (i int8) { } func putMuint64(b []byte, u uint64) { + _ = b[8] // bounds check elimination + b[0] = muint64 b[1] = byte(u >> 56) b[2] = byte(u >> 48) @@ -73,6 +91,8 @@ func putMuint64(b []byte, u uint64) { } func getMuint64(b []byte) uint64 { + _ = b[8] // bounds check elimination + return (uint64(b[1]) << 56) | (uint64(b[2]) << 48) | (uint64(b[3]) << 40) | (uint64(b[4]) << 32) | (uint64(b[5]) << 24) | (uint64(b[6]) << 16) | @@ -80,6 +100,8 @@ func getMuint64(b []byte) uint64 { } func putMuint32(b []byte, u uint32) { + _ = b[4] // bounds check elimination + b[0] = muint32 b[1] = byte(u >> 24) b[2] = byte(u >> 16) @@ -88,20 +110,28 @@ func putMuint32(b []byte, u uint32) { } func getMuint32(b []byte) uint32 { + _ = b[4] // bounds check elimination + return (uint32(b[1]) << 24) | (uint32(b[2]) << 16) | (uint32(b[3]) << 8) | (uint32(b[4])) } func putMuint16(b []byte, u uint16) { + _ = b[2] // bounds check elimination + b[0] = muint16 b[1] = byte(u >> 8) b[2] = byte(u) } func getMuint16(b []byte) uint16 { + _ = b[2] // bounds check elimination + return (uint16(b[1]) << 8) | uint16(b[2]) } func putMuint8(b []byte, u uint8) { + _ = b[1] // bounds check elimination + b[0] = muint8 b[1] = byte(u) } @@ -111,28 +141,15 @@ func getMuint8(b []byte) uint8 { } func getUnix(b []byte) (sec int64, nsec int32) { - sec = (int64(b[0]) << 56) | (int64(b[1]) << 48) | - (int64(b[2]) << 40) | (int64(b[3]) << 32) | - (int64(b[4]) << 24) | (int64(b[5]) << 16) | - (int64(b[6]) << 8) | (int64(b[7])) + sec = int64(binary.BigEndian.Uint64(b)) + nsec = int32(binary.BigEndian.Uint32(b[8:])) - nsec = (int32(b[8]) << 24) | (int32(b[9]) << 16) | (int32(b[10]) << 8) | (int32(b[11])) return } func putUnix(b []byte, sec int64, nsec int32) { - b[0] = byte(sec >> 56) - b[1] = byte(sec >> 48) - b[2] = byte(sec >> 40) - b[3] = byte(sec >> 32) - b[4] = byte(sec >> 24) - b[5] = byte(sec >> 16) - b[6] = byte(sec >> 8) - b[7] = byte(sec) - b[8] = byte(nsec >> 24) - b[9] = byte(nsec >> 16) - b[10] = byte(nsec >> 8) - b[11] = byte(nsec) + binary.BigEndian.PutUint64(b, uint64(sec)) + binary.BigEndian.PutUint32(b[8:], uint32(nsec)) } /* ----------------------------- @@ -141,12 +158,16 @@ func putUnix(b []byte, sec int64, nsec int32) { // write prefix and uint8 func prefixu8(b []byte, pre byte, sz uint8) { + _ = b[1] // bounds check elimination + b[0] = pre b[1] = byte(sz) } // write prefix and big-endian uint16 func prefixu16(b []byte, pre byte, sz uint16) { + _ = b[2] // bounds check elimination + b[0] = pre b[1] = byte(sz >> 8) b[2] = byte(sz) @@ -154,6 +175,8 @@ func prefixu16(b []byte, pre byte, sz uint16) { // write prefix and big-endian uint32 func prefixu32(b []byte, pre byte, sz uint32) { + _ = b[4] // bounds check elimination + b[0] = pre b[1] = byte(sz >> 24) b[2] = byte(sz >> 16) @@ -162,6 +185,8 @@ func prefixu32(b []byte, pre byte, sz uint32) { } func prefixu64(b []byte, pre byte, sz uint64) { + _ = b[8] // bounds check elimination + b[0] = pre b[1] = byte(sz >> 56) b[2] = byte(sz >> 48) diff --git a/vendor/github.com/tinylib/msgp/msgp/json.go b/vendor/github.com/tinylib/msgp/msgp/json.go index 0e11e603c..fe5703732 100644 --- a/vendor/github.com/tinylib/msgp/msgp/json.go +++ b/vendor/github.com/tinylib/msgp/msgp/json.go @@ -109,6 +109,13 @@ func rwMap(dst jsWriter, src *Reader) (n int, err error) { return dst.WriteString("{}") } + // This is potentially a recursive call. + if done, err := src.recursiveCall(); err != nil { + return 0, err + } else { + defer done() + } + err = dst.WriteByte('{') if err != nil { return @@ -162,6 +169,13 @@ func rwArray(dst jsWriter, src *Reader) (n int, err error) { if err != nil { return } + // This is potentially a recursive call. + if done, err := src.recursiveCall(); err != nil { + return 0, err + } else { + defer done() + } + var sz uint32 var nn int sz, err = src.ReadArrayHeader() diff --git a/vendor/github.com/tinylib/msgp/msgp/json_bytes.go b/vendor/github.com/tinylib/msgp/msgp/json_bytes.go index e6162d0a6..88ec60451 100644 --- a/vendor/github.com/tinylib/msgp/msgp/json_bytes.go +++ b/vendor/github.com/tinylib/msgp/msgp/json_bytes.go @@ -9,12 +9,12 @@ import ( "time" ) -var unfuns [_maxtype]func(jsWriter, []byte, []byte) ([]byte, []byte, error) +var unfuns [_maxtype]func(jsWriter, []byte, []byte, int) ([]byte, []byte, error) func init() { // NOTE(pmh): this is best expressed as a jump table, // but gc doesn't do that yet. revisit post-go1.5. - unfuns = [_maxtype]func(jsWriter, []byte, []byte) ([]byte, []byte, error){ + unfuns = [_maxtype]func(jsWriter, []byte, []byte, int) ([]byte, []byte, error){ StrType: rwStringBytes, BinType: rwBytesBytes, MapType: rwMapBytes, @@ -51,7 +51,7 @@ func UnmarshalAsJSON(w io.Writer, msg []byte) ([]byte, error) { dst = bufio.NewWriterSize(w, 512) } for len(msg) > 0 && err == nil { - msg, scratch, err = writeNext(dst, msg, scratch) + msg, scratch, err = writeNext(dst, msg, scratch, 0) } if !cast && err == nil { err = dst.(*bufio.Writer).Flush() @@ -59,7 +59,7 @@ func UnmarshalAsJSON(w io.Writer, msg []byte) ([]byte, error) { return msg, err } -func writeNext(w jsWriter, msg []byte, scratch []byte) ([]byte, []byte, error) { +func writeNext(w jsWriter, msg []byte, scratch []byte, depth int) ([]byte, []byte, error) { if len(msg) < 1 { return msg, scratch, ErrShortBytes } @@ -76,10 +76,13 @@ func writeNext(w jsWriter, msg []byte, scratch []byte) ([]byte, []byte, error) { t = TimeType } } - return unfuns[t](w, msg, scratch) + return unfuns[t](w, msg, scratch, depth) } -func rwArrayBytes(w jsWriter, msg []byte, scratch []byte) ([]byte, []byte, error) { +func rwArrayBytes(w jsWriter, msg []byte, scratch []byte, depth int) ([]byte, []byte, error) { + if depth >= recursionLimit { + return msg, scratch, ErrRecursion + } sz, msg, err := ReadArrayHeaderBytes(msg) if err != nil { return msg, scratch, err @@ -95,7 +98,7 @@ func rwArrayBytes(w jsWriter, msg []byte, scratch []byte) ([]byte, []byte, error return msg, scratch, err } } - msg, scratch, err = writeNext(w, msg, scratch) + msg, scratch, err = writeNext(w, msg, scratch, depth+1) if err != nil { return msg, scratch, err } @@ -104,7 +107,10 @@ func rwArrayBytes(w jsWriter, msg []byte, scratch []byte) ([]byte, []byte, error return msg, scratch, err } -func rwMapBytes(w jsWriter, msg []byte, scratch []byte) ([]byte, []byte, error) { +func rwMapBytes(w jsWriter, msg []byte, scratch []byte, depth int) ([]byte, []byte, error) { + if depth >= recursionLimit { + return msg, scratch, ErrRecursion + } sz, msg, err := ReadMapHeaderBytes(msg) if err != nil { return msg, scratch, err @@ -120,7 +126,7 @@ func rwMapBytes(w jsWriter, msg []byte, scratch []byte) ([]byte, []byte, error) return msg, scratch, err } } - msg, scratch, err = rwMapKeyBytes(w, msg, scratch) + msg, scratch, err = rwMapKeyBytes(w, msg, scratch, depth) if err != nil { return msg, scratch, err } @@ -128,7 +134,7 @@ func rwMapBytes(w jsWriter, msg []byte, scratch []byte) ([]byte, []byte, error) if err != nil { return msg, scratch, err } - msg, scratch, err = writeNext(w, msg, scratch) + msg, scratch, err = writeNext(w, msg, scratch, depth+1) if err != nil { return msg, scratch, err } @@ -137,17 +143,17 @@ func rwMapBytes(w jsWriter, msg []byte, scratch []byte) ([]byte, []byte, error) return msg, scratch, err } -func rwMapKeyBytes(w jsWriter, msg []byte, scratch []byte) ([]byte, []byte, error) { - msg, scratch, err := rwStringBytes(w, msg, scratch) +func rwMapKeyBytes(w jsWriter, msg []byte, scratch []byte, depth int) ([]byte, []byte, error) { + msg, scratch, err := rwStringBytes(w, msg, scratch, depth) if err != nil { if tperr, ok := err.(TypeError); ok && tperr.Encoded == BinType { - return rwBytesBytes(w, msg, scratch) + return rwBytesBytes(w, msg, scratch, depth) } } return msg, scratch, err } -func rwStringBytes(w jsWriter, msg []byte, scratch []byte) ([]byte, []byte, error) { +func rwStringBytes(w jsWriter, msg []byte, scratch []byte, depth int) ([]byte, []byte, error) { str, msg, err := ReadStringZC(msg) if err != nil { return msg, scratch, err @@ -156,7 +162,7 @@ func rwStringBytes(w jsWriter, msg []byte, scratch []byte) ([]byte, []byte, erro return msg, scratch, err } -func rwBytesBytes(w jsWriter, msg []byte, scratch []byte) ([]byte, []byte, error) { +func rwBytesBytes(w jsWriter, msg []byte, scratch []byte, depth int) ([]byte, []byte, error) { bts, msg, err := ReadBytesZC(msg) if err != nil { return msg, scratch, err @@ -180,7 +186,7 @@ func rwBytesBytes(w jsWriter, msg []byte, scratch []byte) ([]byte, []byte, error return msg, scratch, err } -func rwNullBytes(w jsWriter, msg []byte, scratch []byte) ([]byte, []byte, error) { +func rwNullBytes(w jsWriter, msg []byte, scratch []byte, depth int) ([]byte, []byte, error) { msg, err := ReadNilBytes(msg) if err != nil { return msg, scratch, err @@ -189,7 +195,7 @@ func rwNullBytes(w jsWriter, msg []byte, scratch []byte) ([]byte, []byte, error) return msg, scratch, err } -func rwBoolBytes(w jsWriter, msg []byte, scratch []byte) ([]byte, []byte, error) { +func rwBoolBytes(w jsWriter, msg []byte, scratch []byte, depth int) ([]byte, []byte, error) { b, msg, err := ReadBoolBytes(msg) if err != nil { return msg, scratch, err @@ -202,7 +208,7 @@ func rwBoolBytes(w jsWriter, msg []byte, scratch []byte) ([]byte, []byte, error) return msg, scratch, err } -func rwIntBytes(w jsWriter, msg []byte, scratch []byte) ([]byte, []byte, error) { +func rwIntBytes(w jsWriter, msg []byte, scratch []byte, depth int) ([]byte, []byte, error) { i, msg, err := ReadInt64Bytes(msg) if err != nil { return msg, scratch, err @@ -212,7 +218,7 @@ func rwIntBytes(w jsWriter, msg []byte, scratch []byte) ([]byte, []byte, error) return msg, scratch, err } -func rwUintBytes(w jsWriter, msg []byte, scratch []byte) ([]byte, []byte, error) { +func rwUintBytes(w jsWriter, msg []byte, scratch []byte, depth int) ([]byte, []byte, error) { u, msg, err := ReadUint64Bytes(msg) if err != nil { return msg, scratch, err @@ -222,7 +228,7 @@ func rwUintBytes(w jsWriter, msg []byte, scratch []byte) ([]byte, []byte, error) return msg, scratch, err } -func rwFloat32Bytes(w jsWriter, msg []byte, scratch []byte) ([]byte, []byte, error) { +func rwFloat32Bytes(w jsWriter, msg []byte, scratch []byte, depth int) ([]byte, []byte, error) { var f float32 var err error f, msg, err = ReadFloat32Bytes(msg) @@ -234,7 +240,7 @@ func rwFloat32Bytes(w jsWriter, msg []byte, scratch []byte) ([]byte, []byte, err return msg, scratch, err } -func rwFloat64Bytes(w jsWriter, msg []byte, scratch []byte) ([]byte, []byte, error) { +func rwFloat64Bytes(w jsWriter, msg []byte, scratch []byte, depth int) ([]byte, []byte, error) { var f float64 var err error f, msg, err = ReadFloat64Bytes(msg) @@ -246,7 +252,7 @@ func rwFloat64Bytes(w jsWriter, msg []byte, scratch []byte) ([]byte, []byte, err return msg, scratch, err } -func rwTimeBytes(w jsWriter, msg []byte, scratch []byte) ([]byte, []byte, error) { +func rwTimeBytes(w jsWriter, msg []byte, scratch []byte, depth int) ([]byte, []byte, error) { var t time.Time var err error t, msg, err = ReadTimeBytes(msg) @@ -261,7 +267,7 @@ func rwTimeBytes(w jsWriter, msg []byte, scratch []byte) ([]byte, []byte, error) return msg, scratch, err } -func rwExtensionBytes(w jsWriter, msg []byte, scratch []byte) ([]byte, []byte, error) { +func rwExtensionBytes(w jsWriter, msg []byte, scratch []byte, depth int) ([]byte, []byte, error) { var err error var et int8 et, err = peekExtension(msg) diff --git a/vendor/github.com/tinylib/msgp/msgp/purego.go b/vendor/github.com/tinylib/msgp/msgp/purego.go index 2cd35c3e1..fe8723412 100644 --- a/vendor/github.com/tinylib/msgp/msgp/purego.go +++ b/vendor/github.com/tinylib/msgp/msgp/purego.go @@ -1,5 +1,5 @@ -//go:build purego || appengine -// +build purego appengine +//go:build (purego && !unsafe) || appengine +// +build purego,!unsafe appengine package msgp diff --git a/vendor/github.com/tinylib/msgp/msgp/read.go b/vendor/github.com/tinylib/msgp/msgp/read.go index e6d72f17d..0215a5b95 100644 --- a/vendor/github.com/tinylib/msgp/msgp/read.go +++ b/vendor/github.com/tinylib/msgp/msgp/read.go @@ -143,8 +143,9 @@ type Reader struct { // is stateless; all the // buffering is done // within R. - R *fwd.Reader - scratch []byte + R *fwd.Reader + scratch []byte + recursionDepth int } // Read implements `io.Reader` @@ -190,6 +191,11 @@ func (m *Reader) CopyNext(w io.Writer) (int64, error) { return n, io.ErrShortWrite } + if done, err := m.recursiveCall(); err != nil { + return n, err + } else { + defer done() + } // for maps and slices, read elements for x := uintptr(0); x < o; x++ { var n2 int64 @@ -202,6 +208,18 @@ func (m *Reader) CopyNext(w io.Writer) (int64, error) { return n, nil } +// recursiveCall will increment the recursion depth and return an error if it is exceeded. +// If a nil error is returned, done must be called to decrement the counter. +func (m *Reader) recursiveCall() (done func(), err error) { + if m.recursionDepth >= recursionLimit { + return func() {}, ErrRecursion + } + m.recursionDepth++ + return func() { + m.recursionDepth-- + }, nil +} + // ReadFull implements `io.ReadFull` func (m *Reader) ReadFull(p []byte) (int, error) { return m.R.ReadFull(p) @@ -332,7 +350,12 @@ func (m *Reader) Skip() error { return err } - // for maps and slices, skip elements + // for maps and slices, skip elements with recursive call + if done, err := m.recursiveCall(); err != nil { + return err + } else { + defer done() + } for x := uintptr(0); x < o; x++ { err = m.Skip() if err != nil { @@ -1266,7 +1289,7 @@ func (m *Reader) ReadTime() (t time.Time, err error) { return } -// ReadIntf reads out the next object as a raw interface{}. +// ReadIntf reads out the next object as a raw interface{}/any. // Arrays are decoded as []interface{}, and maps are decoded // as map[string]interface{}. Integers are decoded as int64 // and unsigned integers are decoded as uint64. @@ -1333,6 +1356,13 @@ func (m *Reader) ReadIntf() (i interface{}, err error) { return case MapType: + // This can call back here, so treat as recursive call. + if done, err := m.recursiveCall(); err != nil { + return nil, err + } else { + defer done() + } + mp := make(map[string]interface{}) err = m.ReadMapStrIntf(mp) i = mp @@ -1358,6 +1388,13 @@ func (m *Reader) ReadIntf() (i interface{}, err error) { if err != nil { return } + + if done, err := m.recursiveCall(); err != nil { + return nil, err + } else { + defer done() + } + out := make([]interface{}, int(sz)) for j := range out { out[j], err = m.ReadIntf() diff --git a/vendor/github.com/tinylib/msgp/msgp/read_bytes.go b/vendor/github.com/tinylib/msgp/msgp/read_bytes.go index a204ac4b9..948faf1de 100644 --- a/vendor/github.com/tinylib/msgp/msgp/read_bytes.go +++ b/vendor/github.com/tinylib/msgp/msgp/read_bytes.go @@ -1095,6 +1095,15 @@ func ReadTimeBytes(b []byte) (t time.Time, o []byte, err error) { // out of 'b' and returns the map and remaining bytes. // If 'old' is non-nil, the values will be read into that map. func ReadMapStrIntfBytes(b []byte, old map[string]interface{}) (v map[string]interface{}, o []byte, err error) { + return readMapStrIntfBytesDepth(b, old, 0) +} + +func readMapStrIntfBytesDepth(b []byte, old map[string]interface{}, depth int) (v map[string]interface{}, o []byte, err error) { + if depth >= recursionLimit { + err = ErrRecursion + return + } + var sz uint32 o = b sz, o, err = ReadMapHeaderBytes(o) @@ -1123,7 +1132,7 @@ func ReadMapStrIntfBytes(b []byte, old map[string]interface{}) (v map[string]int return } var val interface{} - val, o, err = ReadIntfBytes(o) + val, o, err = readIntfBytesDepth(o, depth) if err != nil { return } @@ -1136,6 +1145,14 @@ func ReadMapStrIntfBytes(b []byte, old map[string]interface{}) (v map[string]int // the next object out of 'b' as a raw interface{} and // return the remaining bytes. func ReadIntfBytes(b []byte) (i interface{}, o []byte, err error) { + return readIntfBytesDepth(b, 0) +} + +func readIntfBytesDepth(b []byte, depth int) (i interface{}, o []byte, err error) { + if depth >= recursionLimit { + err = ErrRecursion + return + } if len(b) < 1 { err = ErrShortBytes return @@ -1145,7 +1162,7 @@ func ReadIntfBytes(b []byte) (i interface{}, o []byte, err error) { switch k { case MapType: - i, o, err = ReadMapStrIntfBytes(b, nil) + i, o, err = readMapStrIntfBytesDepth(b, nil, depth+1) return case ArrayType: @@ -1157,7 +1174,7 @@ func ReadIntfBytes(b []byte) (i interface{}, o []byte, err error) { j := make([]interface{}, int(sz)) i = j for d := range j { - j[d], o, err = ReadIntfBytes(o) + j[d], o, err = readIntfBytesDepth(o, depth+1) if err != nil { return } @@ -1245,7 +1262,15 @@ func ReadIntfBytes(b []byte) (i interface{}, o []byte, err error) { // // - [ErrShortBytes] (not enough bytes in b) // - [InvalidPrefixError] (bad encoding) +// - [ErrRecursion] (too deeply nested data) func Skip(b []byte) ([]byte, error) { + return skipDepth(b, 0) +} + +func skipDepth(b []byte, depth int) ([]byte, error) { + if depth >= recursionLimit { + return b, ErrRecursion + } sz, asz, err := getSize(b) if err != nil { return b, err @@ -1255,7 +1280,7 @@ func Skip(b []byte) ([]byte, error) { } b = b[sz:] for asz > 0 { - b, err = Skip(b) + b, err = skipDepth(b, depth+1) if err != nil { return b, err } diff --git a/vendor/github.com/tinylib/msgp/msgp/unsafe.go b/vendor/github.com/tinylib/msgp/msgp/unsafe.go index 06e8d8437..7d36bfb1e 100644 --- a/vendor/github.com/tinylib/msgp/msgp/unsafe.go +++ b/vendor/github.com/tinylib/msgp/msgp/unsafe.go @@ -1,5 +1,5 @@ -//go:build !purego && !appengine -// +build !purego,!appengine +//go:build (!purego && !appengine) || (!appengine && purego && unsafe) +// +build !purego,!appengine !appengine,purego,unsafe package msgp diff --git a/vendor/github.com/tinylib/msgp/msgp/write_bytes.go b/vendor/github.com/tinylib/msgp/msgp/write_bytes.go index 676a6efe1..12606cc2a 100644 --- a/vendor/github.com/tinylib/msgp/msgp/write_bytes.go +++ b/vendor/github.com/tinylib/msgp/msgp/write_bytes.go @@ -1,6 +1,7 @@ package msgp import ( + "errors" "math" "reflect" "time" @@ -342,10 +343,10 @@ func AppendMapStrIntf(b []byte, m map[string]interface{}) ([]byte, error) { // provided []byte. 'i' must be one of the following: // - 'nil' // - A bool, float, string, []byte, int, uint, or complex -// - A map[string]interface{} or map[string]string +// - A map[string]T where T is another supported type // - A []T, where T is another supported type // - A *T, where T is another supported type -// - A type that satisfieds the msgp.Marshaler interface +// - A type that satisfies the msgp.Marshaler interface // - A type that satisfies the msgp.Extension interface func AppendIntf(b []byte, i interface{}) ([]byte, error) { if i == nil { @@ -395,6 +396,8 @@ func AppendIntf(b []byte, i interface{}) ([]byte, error) { return AppendUint64(b, i), nil case time.Time: return AppendTime(b, i), nil + case time.Duration: + return AppendDuration(b, i), nil case map[string]interface{}: return AppendMapStrIntf(b, i) case map[string]string: @@ -414,6 +417,21 @@ func AppendIntf(b []byte, i interface{}) ([]byte, error) { var err error v := reflect.ValueOf(i) switch v.Kind() { + case reflect.Map: + if v.Type().Key().Kind() != reflect.String { + return b, errors.New("msgp: map keys must be strings") + } + ks := v.MapKeys() + b = AppendMapHeader(b, uint32(len(ks))) + for _, key := range ks { + val := v.MapIndex(key) + b = AppendString(b, key.String()) + b, err = AppendIntf(b, val.Interface()) + if err != nil { + return nil, err + } + } + return b, nil case reflect.Array, reflect.Slice: l := v.Len() b = AppendArrayHeader(b, uint32(l)) diff --git a/vendor/github.com/vishvananda/netlink/.gitignore b/vendor/github.com/vishvananda/netlink/.gitignore index 9f11b755a..66f8fb502 100644 --- a/vendor/github.com/vishvananda/netlink/.gitignore +++ b/vendor/github.com/vishvananda/netlink/.gitignore @@ -1 +1,2 @@ .idea/ +.vscode/ diff --git a/vendor/github.com/vishvananda/netlink/.travis.yml b/vendor/github.com/vishvananda/netlink/.travis.yml deleted file mode 100644 index 7d14af4d6..000000000 --- a/vendor/github.com/vishvananda/netlink/.travis.yml +++ /dev/null @@ -1,19 +0,0 @@ -language: go -go: - - "1.10.x" - - "1.11.x" - - "1.12.x" -before_script: - # make sure we keep path in tact when we sudo - - sudo sed -i -e 's/^Defaults\tsecure_path.*$//' /etc/sudoers - # modprobe ip_gre or else the first gre device can't be deleted - - sudo modprobe ip_gre - # modprobe nf_conntrack for the conntrack testing - - sudo modprobe nf_conntrack - - sudo modprobe nf_conntrack_netlink - - sudo modprobe nf_conntrack_ipv4 - - sudo modprobe nf_conntrack_ipv6 - - sudo modprobe sch_hfsc -install: - - go get github.com/vishvananda/netns -go_import_path: github.com/vishvananda/netlink diff --git a/vendor/github.com/vishvananda/netlink/README.md b/vendor/github.com/vishvananda/netlink/README.md index a88e2f418..0128bc67d 100644 --- a/vendor/github.com/vishvananda/netlink/README.md +++ b/vendor/github.com/vishvananda/netlink/README.md @@ -1,6 +1,6 @@ # netlink - netlink library for go # -[![Build Status](https://travis-ci.org/vishvananda/netlink.png?branch=master)](https://travis-ci.org/vishvananda/netlink) [![GoDoc](https://godoc.org/github.com/vishvananda/netlink?status.svg)](https://godoc.org/github.com/vishvananda/netlink) +![Build Status](https://github.com/vishvananda/netlink/actions/workflows/main.yml/badge.svg) [![GoDoc](https://godoc.org/github.com/vishvananda/netlink?status.svg)](https://godoc.org/github.com/vishvananda/netlink) The netlink package provides a simple netlink library for go. Netlink is the interface a user-space program in linux uses to communicate with diff --git a/vendor/github.com/vishvananda/netlink/addr.go b/vendor/github.com/vishvananda/netlink/addr.go index f08c95696..653f540db 100644 --- a/vendor/github.com/vishvananda/netlink/addr.go +++ b/vendor/github.com/vishvananda/netlink/addr.go @@ -17,6 +17,7 @@ type Addr struct { Broadcast net.IP PreferedLft int ValidLft int + LinkIndex int } // String returns $ip/$netmask $label diff --git a/vendor/github.com/vishvananda/netlink/addr_linux.go b/vendor/github.com/vishvananda/netlink/addr_linux.go index 28746d5af..218ab2379 100644 --- a/vendor/github.com/vishvananda/netlink/addr_linux.go +++ b/vendor/github.com/vishvananda/netlink/addr_linux.go @@ -11,9 +11,6 @@ import ( "golang.org/x/sys/unix" ) -// IFA_FLAGS is a u32 attribute. -const IFA_FLAGS = 0x8 - // AddrAdd will add an IP address to a link device. // // Equivalent to: `ip addr add $addr dev $link` @@ -77,17 +74,19 @@ func (h *Handle) AddrDel(link Link, addr *Addr) error { } func (h *Handle) addrHandle(link Link, addr *Addr, req *nl.NetlinkRequest) error { - base := link.Attrs() - if addr.Label != "" && !strings.HasPrefix(addr.Label, base.Name) { - return fmt.Errorf("label must begin with interface name") - } - h.ensureIndex(base) - family := nl.GetIPFamily(addr.IP) - msg := nl.NewIfAddrmsg(family) - msg.Index = uint32(base.Index) msg.Scope = uint8(addr.Scope) + if link == nil { + msg.Index = uint32(addr.LinkIndex) + } else { + base := link.Attrs() + if addr.Label != "" && !strings.HasPrefix(addr.Label, base.Name) { + return fmt.Errorf("label must begin with interface name") + } + h.ensureIndex(base) + msg.Index = uint32(base.Index) + } mask := addr.Mask if addr.Peer != nil { mask = addr.Peer.Mask @@ -125,7 +124,7 @@ func (h *Handle) addrHandle(link Link, addr *Addr, req *nl.NetlinkRequest) error } else { b := make([]byte, 4) native.PutUint32(b, uint32(addr.Flags)) - flagsData := nl.NewRtAttr(IFA_FLAGS, b) + flagsData := nl.NewRtAttr(unix.IFA_FLAGS, b) req.AddData(flagsData) } } @@ -156,10 +155,10 @@ func (h *Handle) addrHandle(link Link, addr *Addr, req *nl.NetlinkRequest) error // value should be "forever". To compensate for that, only add the attributes if at least one of the values is // non-zero, which means the caller has explicitly set them if addr.ValidLft > 0 || addr.PreferedLft > 0 { - cachedata := nl.IfaCacheInfo{ - IfaValid: uint32(addr.ValidLft), - IfaPrefered: uint32(addr.PreferedLft), - } + cachedata := nl.IfaCacheInfo{unix.IfaCacheinfo{ + Valid: uint32(addr.ValidLft), + Prefered: uint32(addr.PreferedLft), + }} req.AddData(nl.NewRtAttr(unix.IFA_CACHEINFO, cachedata.Serialize())) } @@ -179,7 +178,7 @@ func AddrList(link Link, family int) ([]Addr, error) { // The list can be filtered by link and ip family. func (h *Handle) AddrList(link Link, family int) ([]Addr, error) { req := h.newNetlinkRequest(unix.RTM_GETADDR, unix.NLM_F_DUMP) - msg := nl.NewIfInfomsg(family) + msg := nl.NewIfAddrmsg(family) req.AddData(msg) msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWADDR) @@ -196,12 +195,12 @@ func (h *Handle) AddrList(link Link, family int) ([]Addr, error) { var res []Addr for _, m := range msgs { - addr, msgFamily, ifindex, err := parseAddr(m) + addr, msgFamily, err := parseAddr(m) if err != nil { return res, err } - if link != nil && ifindex != indexFilter { + if link != nil && addr.LinkIndex != indexFilter { // Ignore messages from other interfaces continue } @@ -216,11 +215,11 @@ func (h *Handle) AddrList(link Link, family int) ([]Addr, error) { return res, nil } -func parseAddr(m []byte) (addr Addr, family, index int, err error) { +func parseAddr(m []byte) (addr Addr, family int, err error) { msg := nl.DeserializeIfAddrmsg(m) family = -1 - index = -1 + addr.LinkIndex = -1 attrs, err1 := nl.ParseRouteAttr(m[msg.Len():]) if err1 != nil { @@ -229,7 +228,7 @@ func parseAddr(m []byte) (addr Addr, family, index int, err error) { } family = int(msg.Family) - index = int(msg.Index) + addr.LinkIndex = int(msg.Index) var local, dst *net.IPNet for _, attr := range attrs { @@ -254,12 +253,12 @@ func parseAddr(m []byte) (addr Addr, family, index int, err error) { addr.Broadcast = attr.Value case unix.IFA_LABEL: addr.Label = string(attr.Value[:len(attr.Value)-1]) - case IFA_FLAGS: + case unix.IFA_FLAGS: addr.Flags = int(native.Uint32(attr.Value[0:4])) - case nl.IFA_CACHEINFO: + case unix.IFA_CACHEINFO: ci := nl.DeserializeIfaCacheInfo(attr.Value) - addr.PreferedLft = int(ci.IfaPrefered) - addr.ValidLft = int(ci.IfaValid) + addr.PreferedLft = int(ci.Prefered) + addr.ValidLft = int(ci.Valid) } } @@ -271,7 +270,7 @@ func parseAddr(m []byte) (addr Addr, family, index int, err error) { // But obviously, as there are IPv6 PtP addresses, too, // IFA_LOCAL should also be handled for IPv6. if local != nil { - if family == FAMILY_V4 && local.IP.Equal(dst.IP) { + if family == FAMILY_V4 && dst != nil && local.IP.Equal(dst.IP) { addr.IPNet = dst } else { addr.IPNet = local @@ -299,22 +298,24 @@ type AddrUpdate struct { // AddrSubscribe takes a chan down which notifications will be sent // when addresses change. Close the 'done' chan to stop subscription. func AddrSubscribe(ch chan<- AddrUpdate, done <-chan struct{}) error { - return addrSubscribeAt(netns.None(), netns.None(), ch, done, nil, false, 0) + return addrSubscribeAt(netns.None(), netns.None(), ch, done, nil, false, 0, nil, false) } // AddrSubscribeAt works like AddrSubscribe plus it allows the caller // to choose the network namespace in which to subscribe (ns). func AddrSubscribeAt(ns netns.NsHandle, ch chan<- AddrUpdate, done <-chan struct{}) error { - return addrSubscribeAt(ns, netns.None(), ch, done, nil, false, 0) + return addrSubscribeAt(ns, netns.None(), ch, done, nil, false, 0, nil, false) } // AddrSubscribeOptions contains a set of options to use with // AddrSubscribeWithOptions. type AddrSubscribeOptions struct { - Namespace *netns.NsHandle - ErrorCallback func(error) - ListExisting bool - ReceiveBufferSize int + Namespace *netns.NsHandle + ErrorCallback func(error) + ListExisting bool + ReceiveBufferSize int + ReceiveBufferForceSize bool + ReceiveTimeout *unix.Timeval } // AddrSubscribeWithOptions work like AddrSubscribe but enable to @@ -325,26 +326,33 @@ func AddrSubscribeWithOptions(ch chan<- AddrUpdate, done <-chan struct{}, option none := netns.None() options.Namespace = &none } - return addrSubscribeAt(*options.Namespace, netns.None(), ch, done, options.ErrorCallback, options.ListExisting, options.ReceiveBufferSize) + return addrSubscribeAt(*options.Namespace, netns.None(), ch, done, options.ErrorCallback, options.ListExisting, + options.ReceiveBufferSize, options.ReceiveTimeout, options.ReceiveBufferForceSize) } -func addrSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- AddrUpdate, done <-chan struct{}, cberr func(error), listExisting bool, rcvbuf int) error { +func addrSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- AddrUpdate, done <-chan struct{}, cberr func(error), listExisting bool, + rcvbuf int, rcvTimeout *unix.Timeval, rcvBufForce bool) error { s, err := nl.SubscribeAt(newNs, curNs, unix.NETLINK_ROUTE, unix.RTNLGRP_IPV4_IFADDR, unix.RTNLGRP_IPV6_IFADDR) if err != nil { return err } - if done != nil { - go func() { - <-done - s.Close() - }() + if rcvTimeout != nil { + if err := s.SetReceiveTimeout(rcvTimeout); err != nil { + return err + } } if rcvbuf != 0 { - err = pkgHandle.SetSocketReceiveBufferSize(rcvbuf, false) + err = s.SetReceiveBufferSize(rcvbuf, rcvBufForce) if err != nil { return err } } + if done != nil { + go func() { + <-done + s.Close() + }() + } if listExisting { req := pkgHandle.newNetlinkRequest(unix.RTM_GETADDR, unix.NLM_F_DUMP) @@ -360,7 +368,8 @@ func addrSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- AddrUpdate, done <-c msgs, from, err := s.Receive() if err != nil { if cberr != nil { - cberr(err) + cberr(fmt.Errorf("Receive failed: %v", + err)) } return } @@ -375,7 +384,6 @@ func addrSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- AddrUpdate, done <-c continue } if m.Header.Type == unix.NLMSG_ERROR { - native := nl.NativeEndian() error := int32(native.Uint32(m.Data[0:4])) if error == 0 { continue @@ -394,7 +402,7 @@ func addrSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- AddrUpdate, done <-c continue } - addr, _, ifindex, err := parseAddr(m.Data) + addr, _, err := parseAddr(m.Data) if err != nil { if cberr != nil { cberr(fmt.Errorf("could not parse address: %v", err)) @@ -403,7 +411,7 @@ func addrSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- AddrUpdate, done <-c } ch <- AddrUpdate{LinkAddress: *addr.IPNet, - LinkIndex: ifindex, + LinkIndex: addr.LinkIndex, NewAddr: msgType == unix.RTM_NEWADDR, Flags: addr.Flags, Scope: addr.Scope, diff --git a/vendor/github.com/vishvananda/netlink/bpf_linux.go b/vendor/github.com/vishvananda/netlink/bpf_linux.go index 6631626bf..96befbfe0 100644 --- a/vendor/github.com/vishvananda/netlink/bpf_linux.go +++ b/vendor/github.com/vishvananda/netlink/bpf_linux.go @@ -16,6 +16,30 @@ const ( BPF_PROG_TYPE_SCHED_ACT BPF_PROG_TYPE_TRACEPOINT BPF_PROG_TYPE_XDP + BPF_PROG_TYPE_PERF_EVENT + BPF_PROG_TYPE_CGROUP_SKB + BPF_PROG_TYPE_CGROUP_SOCK + BPF_PROG_TYPE_LWT_IN + BPF_PROG_TYPE_LWT_OUT + BPF_PROG_TYPE_LWT_XMIT + BPF_PROG_TYPE_SOCK_OPS + BPF_PROG_TYPE_SK_SKB + BPF_PROG_TYPE_CGROUP_DEVICE + BPF_PROG_TYPE_SK_MSG + BPF_PROG_TYPE_RAW_TRACEPOINT + BPF_PROG_TYPE_CGROUP_SOCK_ADDR + BPF_PROG_TYPE_LWT_SEG6LOCAL + BPF_PROG_TYPE_LIRC_MODE2 + BPF_PROG_TYPE_SK_REUSEPORT + BPF_PROG_TYPE_FLOW_DISSECTOR + BPF_PROG_TYPE_CGROUP_SYSCTL + BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE + BPF_PROG_TYPE_CGROUP_SOCKOPT + BPF_PROG_TYPE_TRACING + BPF_PROG_TYPE_STRUCT_OPS + BPF_PROG_TYPE_EXT + BPF_PROG_TYPE_LSM + BPF_PROG_TYPE_SK_LOOKUP ) type BPFAttr struct { diff --git a/vendor/github.com/vishvananda/netlink/bridge_linux.go b/vendor/github.com/vishvananda/netlink/bridge_linux.go index 6e1224c47..6c340b0ce 100644 --- a/vendor/github.com/vishvananda/netlink/bridge_linux.go +++ b/vendor/github.com/vishvananda/netlink/bridge_linux.go @@ -63,7 +63,19 @@ func BridgeVlanAdd(link Link, vid uint16, pvid, untagged, self, master bool) err // BridgeVlanAdd adds a new vlan filter entry // Equivalent to: `bridge vlan add dev DEV vid VID [ pvid ] [ untagged ] [ self ] [ master ]` func (h *Handle) BridgeVlanAdd(link Link, vid uint16, pvid, untagged, self, master bool) error { - return h.bridgeVlanModify(unix.RTM_SETLINK, link, vid, pvid, untagged, self, master) + return h.bridgeVlanModify(unix.RTM_SETLINK, link, vid, 0, pvid, untagged, self, master) +} + +// BridgeVlanAddRange adds a new vlan filter entry +// Equivalent to: `bridge vlan add dev DEV vid VID-VIDEND [ pvid ] [ untagged ] [ self ] [ master ]` +func BridgeVlanAddRange(link Link, vid, vidEnd uint16, pvid, untagged, self, master bool) error { + return pkgHandle.BridgeVlanAddRange(link, vid, vidEnd, pvid, untagged, self, master) +} + +// BridgeVlanAddRange adds a new vlan filter entry +// Equivalent to: `bridge vlan add dev DEV vid VID-VIDEND [ pvid ] [ untagged ] [ self ] [ master ]` +func (h *Handle) BridgeVlanAddRange(link Link, vid, vidEnd uint16, pvid, untagged, self, master bool) error { + return h.bridgeVlanModify(unix.RTM_SETLINK, link, vid, vidEnd, pvid, untagged, self, master) } // BridgeVlanDel adds a new vlan filter entry @@ -75,10 +87,22 @@ func BridgeVlanDel(link Link, vid uint16, pvid, untagged, self, master bool) err // BridgeVlanDel adds a new vlan filter entry // Equivalent to: `bridge vlan del dev DEV vid VID [ pvid ] [ untagged ] [ self ] [ master ]` func (h *Handle) BridgeVlanDel(link Link, vid uint16, pvid, untagged, self, master bool) error { - return h.bridgeVlanModify(unix.RTM_DELLINK, link, vid, pvid, untagged, self, master) + return h.bridgeVlanModify(unix.RTM_DELLINK, link, vid, 0, pvid, untagged, self, master) } -func (h *Handle) bridgeVlanModify(cmd int, link Link, vid uint16, pvid, untagged, self, master bool) error { +// BridgeVlanDelRange adds a new vlan filter entry +// Equivalent to: `bridge vlan del dev DEV vid VID-VIDEND [ pvid ] [ untagged ] [ self ] [ master ]` +func BridgeVlanDelRange(link Link, vid, vidEnd uint16, pvid, untagged, self, master bool) error { + return pkgHandle.BridgeVlanDelRange(link, vid, vidEnd, pvid, untagged, self, master) +} + +// BridgeVlanDelRange adds a new vlan filter entry +// Equivalent to: `bridge vlan del dev DEV vid VID-VIDEND [ pvid ] [ untagged ] [ self ] [ master ]` +func (h *Handle) BridgeVlanDelRange(link Link, vid, vidEnd uint16, pvid, untagged, self, master bool) error { + return h.bridgeVlanModify(unix.RTM_DELLINK, link, vid, vidEnd, pvid, untagged, self, master) +} + +func (h *Handle) bridgeVlanModify(cmd int, link Link, vid, vidEnd uint16, pvid, untagged, self, master bool) error { base := link.Attrs() h.ensureIndex(base) req := h.newNetlinkRequest(cmd, unix.NLM_F_ACK) @@ -105,7 +129,20 @@ func (h *Handle) bridgeVlanModify(cmd int, link Link, vid uint16, pvid, untagged if untagged { vlanInfo.Flags |= nl.BRIDGE_VLAN_INFO_UNTAGGED } - br.AddRtAttr(nl.IFLA_BRIDGE_VLAN_INFO, vlanInfo.Serialize()) + + if vidEnd != 0 { + vlanEndInfo := &nl.BridgeVlanInfo{Vid: vidEnd} + vlanEndInfo.Flags = vlanInfo.Flags + + vlanInfo.Flags |= nl.BRIDGE_VLAN_INFO_RANGE_BEGIN + br.AddRtAttr(nl.IFLA_BRIDGE_VLAN_INFO, vlanInfo.Serialize()) + + vlanEndInfo.Flags |= nl.BRIDGE_VLAN_INFO_RANGE_END + br.AddRtAttr(nl.IFLA_BRIDGE_VLAN_INFO, vlanEndInfo.Serialize()) + } else { + br.AddRtAttr(nl.IFLA_BRIDGE_VLAN_INFO, vlanInfo.Serialize()) + } + req.AddData(br) _, err := req.Execute(unix.NETLINK_ROUTE, 0) return err diff --git a/vendor/github.com/vishvananda/netlink/chain.go b/vendor/github.com/vishvananda/netlink/chain.go new file mode 100644 index 000000000..1d1c144e9 --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/chain.go @@ -0,0 +1,22 @@ +package netlink + +import ( + "fmt" +) + +// Chain contains the attributes of a Chain +type Chain struct { + Parent uint32 + Chain uint32 +} + +func (c Chain) String() string { + return fmt.Sprintf("{Parent: %d, Chain: %d}", c.Parent, c.Chain) +} + +func NewChain(parent uint32, chain uint32) Chain { + return Chain{ + Parent: parent, + Chain: chain, + } +} diff --git a/vendor/github.com/vishvananda/netlink/chain_linux.go b/vendor/github.com/vishvananda/netlink/chain_linux.go new file mode 100644 index 000000000..d9f441613 --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/chain_linux.go @@ -0,0 +1,112 @@ +package netlink + +import ( + "github.com/vishvananda/netlink/nl" + "golang.org/x/sys/unix" +) + +// ChainDel will delete a chain from the system. +func ChainDel(link Link, chain Chain) error { + // Equivalent to: `tc chain del $chain` + return pkgHandle.ChainDel(link, chain) +} + +// ChainDel will delete a chain from the system. +// Equivalent to: `tc chain del $chain` +func (h *Handle) ChainDel(link Link, chain Chain) error { + return h.chainModify(unix.RTM_DELCHAIN, 0, link, chain) +} + +// ChainAdd will add a chain to the system. +// Equivalent to: `tc chain add` +func ChainAdd(link Link, chain Chain) error { + return pkgHandle.ChainAdd(link, chain) +} + +// ChainAdd will add a chain to the system. +// Equivalent to: `tc chain add` +func (h *Handle) ChainAdd(link Link, chain Chain) error { + return h.chainModify( + unix.RTM_NEWCHAIN, + unix.NLM_F_CREATE|unix.NLM_F_EXCL, + link, + chain) +} + +func (h *Handle) chainModify(cmd, flags int, link Link, chain Chain) error { + req := h.newNetlinkRequest(cmd, flags|unix.NLM_F_ACK) + index := int32(0) + if link != nil { + base := link.Attrs() + h.ensureIndex(base) + index = int32(base.Index) + } + msg := &nl.TcMsg{ + Family: nl.FAMILY_ALL, + Ifindex: index, + Parent: chain.Parent, + } + req.AddData(msg) + req.AddData(nl.NewRtAttr(nl.TCA_CHAIN, nl.Uint32Attr(chain.Chain))) + + _, err := req.Execute(unix.NETLINK_ROUTE, 0) + return err +} + +// ChainList gets a list of chains in the system. +// Equivalent to: `tc chain list`. +// The list can be filtered by link. +func ChainList(link Link, parent uint32) ([]Chain, error) { + return pkgHandle.ChainList(link, parent) +} + +// ChainList gets a list of chains in the system. +// Equivalent to: `tc chain list`. +// The list can be filtered by link. +func (h *Handle) ChainList(link Link, parent uint32) ([]Chain, error) { + req := h.newNetlinkRequest(unix.RTM_GETCHAIN, unix.NLM_F_DUMP) + index := int32(0) + if link != nil { + base := link.Attrs() + h.ensureIndex(base) + index = int32(base.Index) + } + msg := &nl.TcMsg{ + Family: nl.FAMILY_ALL, + Ifindex: index, + Parent: parent, + } + req.AddData(msg) + + msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWCHAIN) + if err != nil { + return nil, err + } + + var res []Chain + for _, m := range msgs { + msg := nl.DeserializeTcMsg(m) + + attrs, err := nl.ParseRouteAttr(m[msg.Len():]) + if err != nil { + return nil, err + } + + // skip chains from other interfaces + if link != nil && msg.Ifindex != index { + continue + } + + var chain Chain + for _, attr := range attrs { + switch attr.Attr.Type { + case nl.TCA_CHAIN: + chain.Chain = native.Uint32(attr.Value) + chain.Parent = parent + } + } + res = append(res, chain) + } + + return res, nil +} diff --git a/vendor/github.com/vishvananda/netlink/class.go b/vendor/github.com/vishvananda/netlink/class.go index dcc22d9e9..e686f6745 100644 --- a/vendor/github.com/vishvananda/netlink/class.go +++ b/vendor/github.com/vishvananda/netlink/class.go @@ -47,6 +47,7 @@ type ClassStatistics struct { Basic *GnetStatsBasic Queue *GnetStatsQueue RateEst *GnetStatsRateEst + BasicHw *GnetStatsBasic // Hardward statistics added in kernel 4.20 } // NewClassStatistics Construct a ClassStatistics struct which fields are all initialized by 0. @@ -55,6 +56,7 @@ func NewClassStatistics() *ClassStatistics { Basic: &GnetStatsBasic{}, Queue: &GnetStatsQueue{}, RateEst: &GnetStatsRateEst{}, + BasicHw: &GnetStatsBasic{}, } } @@ -132,7 +134,10 @@ func (class *GenericClass) Type() string { return class.ClassType } -// ServiceCurve is the way the HFSC curve are represented +// ServiceCurve is a nondecreasing function of some time unit, returning the amount of service +// (an allowed or allocated amount of bandwidth) at some specific point in time. The purpose of it +// should be subconsciously obvious: if a class was allowed to transfer not less than the amount +// specified by its service curve, then the service curve is not violated. type ServiceCurve struct { m1 uint32 d uint32 @@ -144,6 +149,21 @@ func (c *ServiceCurve) Attrs() (uint32, uint32, uint32) { return c.m1, c.d, c.m2 } +// Burst returns the burst rate (m1) of the curve +func (c *ServiceCurve) Burst() uint32 { + return c.m1 +} + +// Delay return the delay (d) of the curve +func (c *ServiceCurve) Delay() uint32 { + return c.d +} + +// Rate returns the rate (m2) of the curve +func (c *ServiceCurve) Rate() uint32 { + return c.m2 +} + // HfscClass is a representation of the HFSC class type HfscClass struct { ClassAttrs @@ -152,35 +172,44 @@ type HfscClass struct { Usc ServiceCurve } -// SetUsc sets the Usc curve +// SetUsc sets the USC curve. The bandwidth (m1 and m2) is specified in bits and the delay in +// seconds. func (hfsc *HfscClass) SetUsc(m1 uint32, d uint32, m2 uint32) { - hfsc.Usc = ServiceCurve{m1: m1 / 8, d: d, m2: m2 / 8} + hfsc.Usc = ServiceCurve{m1: m1, d: d, m2: m2} } -// SetFsc sets the Fsc curve +// SetFsc sets the Fsc curve. The bandwidth (m1 and m2) is specified in bits and the delay in +// seconds. func (hfsc *HfscClass) SetFsc(m1 uint32, d uint32, m2 uint32) { - hfsc.Fsc = ServiceCurve{m1: m1 / 8, d: d, m2: m2 / 8} + hfsc.Fsc = ServiceCurve{m1: m1, d: d, m2: m2} } -// SetRsc sets the Rsc curve +// SetRsc sets the Rsc curve. The bandwidth (m1 and m2) is specified in bits and the delay in +// seconds. func (hfsc *HfscClass) SetRsc(m1 uint32, d uint32, m2 uint32) { - hfsc.Rsc = ServiceCurve{m1: m1 / 8, d: d, m2: m2 / 8} + hfsc.Rsc = ServiceCurve{m1: m1, d: d, m2: m2} } -// SetSC implements the SC from the tc CLI +// SetSC implements the SC from the `tc` CLI. This function behaves the same as if one would set the +// USC through the `tc` command-line tool. This means bandwidth (m1 and m2) is specified in bits and +// the delay in ms. func (hfsc *HfscClass) SetSC(m1 uint32, d uint32, m2 uint32) { - hfsc.Rsc = ServiceCurve{m1: m1 / 8, d: d, m2: m2 / 8} - hfsc.Fsc = ServiceCurve{m1: m1 / 8, d: d, m2: m2 / 8} + hfsc.SetRsc(m1, d, m2) + hfsc.SetFsc(m1, d, m2) } -// SetUL implements the UL from the tc CLI +// SetUL implements the UL from the `tc` CLI. This function behaves the same as if one would set the +// USC through the `tc` command-line tool. This means bandwidth (m1 and m2) is specified in bits and +// the delay in ms. func (hfsc *HfscClass) SetUL(m1 uint32, d uint32, m2 uint32) { - hfsc.Usc = ServiceCurve{m1: m1 / 8, d: d, m2: m2 / 8} + hfsc.SetUsc(m1, d, m2) } -// SetLS implements the LS from the tc CLI +// SetLS implements the LS from the `tc` CLI. This function behaves the same as if one would set the +// USC through the `tc` command-line tool. This means bandwidth (m1 and m2) is specified in bits and +// the delay in ms. func (hfsc *HfscClass) SetLS(m1 uint32, d uint32, m2 uint32) { - hfsc.Fsc = ServiceCurve{m1: m1 / 8, d: d, m2: m2 / 8} + hfsc.SetFsc(m1, d, m2) } // NewHfscClass returns a new HFSC struct with the set parameters @@ -193,6 +222,7 @@ func NewHfscClass(attrs ClassAttrs) *HfscClass { } } +// String() returns a string that contains the information and attributes of the HFSC class func (hfsc *HfscClass) String() string { return fmt.Sprintf( "{%s -- {RSC: {m1=%d d=%d m2=%d}} {FSC: {m1=%d d=%d m2=%d}} {USC: {m1=%d d=%d m2=%d}}}", diff --git a/vendor/github.com/vishvananda/netlink/class_linux.go b/vendor/github.com/vishvananda/netlink/class_linux.go index 31091e501..a82eb09de 100644 --- a/vendor/github.com/vishvananda/netlink/class_linux.go +++ b/vendor/github.com/vishvananda/netlink/class_linux.go @@ -43,12 +43,12 @@ func NewHtbClass(attrs ClassAttrs, cattrs HtbClassAttrs) *HtbClass { if buffer == 0 { buffer = uint32(float64(rate)/Hz() + float64(mtu)) } - buffer = uint32(Xmittime(rate, buffer)) + buffer = Xmittime(rate, buffer) if cbuffer == 0 { cbuffer = uint32(float64(ceil)/Hz() + float64(mtu)) } - cbuffer = uint32(Xmittime(ceil, cbuffer)) + cbuffer = Xmittime(ceil, cbuffer) return &HtbClass{ ClassAttrs: attrs, @@ -56,9 +56,9 @@ func NewHtbClass(attrs ClassAttrs, cattrs HtbClassAttrs) *HtbClass { Ceil: ceil, Buffer: buffer, Cbuffer: cbuffer, - Quantum: 10, Level: 0, - Prio: 0, + Prio: cattrs.Prio, + Quantum: cattrs.Quantum, } } @@ -176,12 +176,21 @@ func classPayload(req *nl.NetlinkRequest, class Class) error { options.AddRtAttr(nl.TCA_HTB_PARMS, opt.Serialize()) options.AddRtAttr(nl.TCA_HTB_RTAB, SerializeRtab(rtab)) options.AddRtAttr(nl.TCA_HTB_CTAB, SerializeRtab(ctab)) + if htb.Rate >= uint64(1<<32) { + options.AddRtAttr(nl.TCA_HTB_RATE64, nl.Uint64Attr(htb.Rate)) + } + if htb.Ceil >= uint64(1<<32) { + options.AddRtAttr(nl.TCA_HTB_CEIL64, nl.Uint64Attr(htb.Ceil)) + } case "hfsc": hfsc := class.(*HfscClass) opt := nl.HfscCopt{} - opt.Rsc.Set(hfsc.Rsc.Attrs()) - opt.Fsc.Set(hfsc.Fsc.Attrs()) - opt.Usc.Set(hfsc.Usc.Attrs()) + rm1, rd, rm2 := hfsc.Rsc.Attrs() + opt.Rsc.Set(rm1/8, rd, rm2/8) + fm1, fd, fm2 := hfsc.Fsc.Attrs() + opt.Fsc.Set(fm1/8, fd, fm2/8) + um1, ud, um2 := hfsc.Usc.Attrs() + opt.Usc.Set(um1/8, ud, um2/8) options.AddRtAttr(nl.TCA_HFSC_RSC, nl.SerializeHfscCurve(&opt.Rsc)) options.AddRtAttr(nl.TCA_HFSC_FSC, nl.SerializeHfscCurve(&opt.Fsc)) options.AddRtAttr(nl.TCA_HFSC_USC, nl.SerializeHfscCurve(&opt.Usc)) @@ -303,6 +312,10 @@ func parseHtbClassData(class Class, data []syscall.NetlinkRouteAttr) (bool, erro htb.Quantum = opt.Quantum htb.Level = opt.Level htb.Prio = opt.Prio + case nl.TCA_HTB_RATE64: + htb.Rate = native.Uint64(datum.Value[0:8]) + case nl.TCA_HTB_CEIL64: + htb.Ceil = native.Uint64(datum.Value[0:8]) } } return detailed, nil @@ -315,11 +328,11 @@ func parseHfscClassData(class Class, data []syscall.NetlinkRouteAttr) (bool, err m1, d, m2 := nl.DeserializeHfscCurve(datum.Value).Attrs() switch datum.Attr.Type { case nl.TCA_HFSC_RSC: - hfsc.Rsc = ServiceCurve{m1: m1, d: d, m2: m2} + hfsc.Rsc = ServiceCurve{m1: m1 * 8, d: d, m2: m2 * 8} case nl.TCA_HFSC_FSC: - hfsc.Fsc = ServiceCurve{m1: m1, d: d, m2: m2} + hfsc.Fsc = ServiceCurve{m1: m1 * 8, d: d, m2: m2 * 8} case nl.TCA_HFSC_USC: - hfsc.Usc = ServiceCurve{m1: m1, d: d, m2: m2} + hfsc.Usc = ServiceCurve{m1: m1 * 8, d: d, m2: m2 * 8} } } return detailed, nil @@ -328,7 +341,6 @@ func parseHfscClassData(class Class, data []syscall.NetlinkRouteAttr) (bool, err func parseTcStats(data []byte) (*ClassStatistics, error) { buf := &bytes.Buffer{} buf.Write(data) - native := nl.NativeEndian() tcStats := &tcStats{} if err := binary.Read(buf, native, tcStats); err != nil { return nil, err @@ -350,7 +362,6 @@ func parseTcStats(data []byte) (*ClassStatistics, error) { func parseGnetStats(data []byte, gnetStats interface{}) error { buf := &bytes.Buffer{} buf.Write(data) - native := nl.NativeEndian() return binary.Read(buf, native, gnetStats) } @@ -377,6 +388,11 @@ func parseTcStats2(data []byte) (*ClassStatistics, error) { return nil, fmt.Errorf("Failed to parse ClassStatistics.RateEst with: %v\n%s", err, hex.Dump(datum.Value)) } + case nl.TCA_STATS_BASIC_HW: + if err := parseGnetStats(datum.Value, stats.BasicHw); err != nil { + return nil, fmt.Errorf("Failed to parse ClassStatistics.BasicHw with: %v\n%s", + err, hex.Dump(datum.Value)) + } } } diff --git a/vendor/github.com/vishvananda/netlink/conntrack_linux.go b/vendor/github.com/vishvananda/netlink/conntrack_linux.go index 4bff0dcba..ba022453b 100644 --- a/vendor/github.com/vishvananda/netlink/conntrack_linux.go +++ b/vendor/github.com/vishvananda/netlink/conntrack_linux.go @@ -6,6 +6,7 @@ import ( "errors" "fmt" "net" + "time" "github.com/vishvananda/netlink/nl" "golang.org/x/sys/unix" @@ -54,10 +55,30 @@ func ConntrackTableFlush(table ConntrackTableType) error { return pkgHandle.ConntrackTableFlush(table) } +// ConntrackCreate creates a new conntrack flow in the desired table +// conntrack -I [table] Create a conntrack or expectation +func ConntrackCreate(table ConntrackTableType, family InetFamily, flow *ConntrackFlow) error { + return pkgHandle.ConntrackCreate(table, family, flow) +} + +// ConntrackUpdate updates an existing conntrack flow in the desired table using the handle +// conntrack -U [table] Update a conntrack +func ConntrackUpdate(table ConntrackTableType, family InetFamily, flow *ConntrackFlow) error { + return pkgHandle.ConntrackUpdate(table, family, flow) +} + // ConntrackDeleteFilter deletes entries on the specified table on the base of the filter // conntrack -D [table] parameters Delete conntrack or expectation +// +// Deprecated: use [ConntrackDeleteFilter] instead. func ConntrackDeleteFilter(table ConntrackTableType, family InetFamily, filter CustomConntrackFilter) (uint, error) { - return pkgHandle.ConntrackDeleteFilter(table, family, filter) + return pkgHandle.ConntrackDeleteFilters(table, family, filter) +} + +// ConntrackDeleteFilters deletes entries on the specified table matching any of the specified filters +// conntrack -D [table] parameters Delete conntrack or expectation +func ConntrackDeleteFilters(table ConntrackTableType, family InetFamily, filters ...CustomConntrackFilter) (uint, error) { + return pkgHandle.ConntrackDeleteFilters(table, family, filters...) } // ConntrackTableList returns the flow list of a table of a specific family using the netlink handle passed @@ -86,9 +107,51 @@ func (h *Handle) ConntrackTableFlush(table ConntrackTableType) error { return err } +// ConntrackCreate creates a new conntrack flow in the desired table using the handle +// conntrack -I [table] Create a conntrack or expectation +func (h *Handle) ConntrackCreate(table ConntrackTableType, family InetFamily, flow *ConntrackFlow) error { + req := h.newConntrackRequest(table, family, nl.IPCTNL_MSG_CT_NEW, unix.NLM_F_ACK|unix.NLM_F_CREATE) + attr, err := flow.toNlData() + if err != nil { + return err + } + + for _, a := range attr { + req.AddData(a) + } + + _, err = req.Execute(unix.NETLINK_NETFILTER, 0) + return err +} + +// ConntrackUpdate updates an existing conntrack flow in the desired table using the handle +// conntrack -U [table] Update a conntrack +func (h *Handle) ConntrackUpdate(table ConntrackTableType, family InetFamily, flow *ConntrackFlow) error { + req := h.newConntrackRequest(table, family, nl.IPCTNL_MSG_CT_NEW, unix.NLM_F_ACK|unix.NLM_F_REPLACE) + attr, err := flow.toNlData() + if err != nil { + return err + } + + for _, a := range attr { + req.AddData(a) + } + + _, err = req.Execute(unix.NETLINK_NETFILTER, 0) + return err +} + // ConntrackDeleteFilter deletes entries on the specified table on the base of the filter using the netlink handle passed // conntrack -D [table] parameters Delete conntrack or expectation +// +// Deprecated: use [Handle.ConntrackDeleteFilters] instead. func (h *Handle) ConntrackDeleteFilter(table ConntrackTableType, family InetFamily, filter CustomConntrackFilter) (uint, error) { + return h.ConntrackDeleteFilters(table, family, filter) +} + +// ConntrackDeleteFilters deletes entries on the specified table matching any of the specified filters using the netlink handle passed +// conntrack -D [table] parameters Delete conntrack or expectation +func (h *Handle) ConntrackDeleteFilters(table ConntrackTableType, family InetFamily, filters ...CustomConntrackFilter) (uint, error) { res, err := h.dumpConntrackTable(table, family) if err != nil { return 0, err @@ -97,12 +160,16 @@ func (h *Handle) ConntrackDeleteFilter(table ConntrackTableType, family InetFami var matched uint for _, dataRaw := range res { flow := parseRawData(dataRaw) - if match := filter.MatchConntrackFlow(flow); match { - req2 := h.newConntrackRequest(table, family, nl.IPCTNL_MSG_CT_DELETE, unix.NLM_F_ACK) - // skip the first 4 byte that are the netfilter header, the newConntrackRequest is adding it already - req2.AddRawData(dataRaw[4:]) - req2.Execute(unix.NETLINK_NETFILTER, 0) - matched++ + for _, filter := range filters { + if match := filter.MatchConntrackFlow(flow); match { + req2 := h.newConntrackRequest(table, family, nl.IPCTNL_MSG_CT_DELETE, unix.NLM_F_ACK) + // skip the first 4 byte that are the netfilter header, the newConntrackRequest is adding it already + req2.AddRawData(dataRaw[4:]) + req2.Execute(unix.NETLINK_NETFILTER, 0) + matched++ + // flow is already deleted, no need to match on other filters and continue to the next flow. + break + } } } @@ -127,10 +194,44 @@ func (h *Handle) dumpConntrackTable(table ConntrackTableType, family InetFamily) return req.Execute(unix.NETLINK_NETFILTER, 0) } +// ProtoInfo wraps an L4-protocol structure - roughly corresponds to the +// __nfct_protoinfo union found in libnetfilter_conntrack/include/internal/object.h. +// Currently, only protocol names, and TCP state is supported. +type ProtoInfo interface { + Protocol() string +} + +// ProtoInfoTCP corresponds to the `tcp` struct of the __nfct_protoinfo union. +// Only TCP state is currently supported. +type ProtoInfoTCP struct { + State uint8 +} +// Protocol returns "tcp". +func (*ProtoInfoTCP) Protocol() string {return "tcp"} +func (p *ProtoInfoTCP) toNlData() ([]*nl.RtAttr, error) { + ctProtoInfo := nl.NewRtAttr(unix.NLA_F_NESTED | nl.CTA_PROTOINFO, []byte{}) + ctProtoInfoTCP := nl.NewRtAttr(unix.NLA_F_NESTED|nl.CTA_PROTOINFO_TCP, []byte{}) + ctProtoInfoTCPState := nl.NewRtAttr(nl.CTA_PROTOINFO_TCP_STATE, nl.Uint8Attr(p.State)) + ctProtoInfoTCP.AddChild(ctProtoInfoTCPState) + ctProtoInfo.AddChild(ctProtoInfoTCP) + + return []*nl.RtAttr{ctProtoInfo}, nil +} + +// ProtoInfoSCTP only supports the protocol name. +type ProtoInfoSCTP struct {} +// Protocol returns "sctp". +func (*ProtoInfoSCTP) Protocol() string {return "sctp"} + +// ProtoInfoDCCP only supports the protocol name. +type ProtoInfoDCCP struct {} +// Protocol returns "dccp". +func (*ProtoInfoDCCP) Protocol() string {return "dccp"} + // The full conntrack flow structure is very complicated and can be found in the file: // http://git.netfilter.org/libnetfilter_conntrack/tree/include/internal/object.h // For the time being, the structure below allows to parse and extract the base information of a flow -type ipTuple struct { +type IPTuple struct { Bytes uint64 DstIP net.IP DstPort uint16 @@ -140,21 +241,150 @@ type ipTuple struct { SrcPort uint16 } +// toNlData generates the inner fields of a nested tuple netlink datastructure +// does not generate the "nested"-flagged outer message. +func (t *IPTuple) toNlData(family uint8) ([]*nl.RtAttr, error) { + + var srcIPsFlag, dstIPsFlag int + if family == nl.FAMILY_V4 { + srcIPsFlag = nl.CTA_IP_V4_SRC + dstIPsFlag = nl.CTA_IP_V4_DST + } else if family == nl.FAMILY_V6 { + srcIPsFlag = nl.CTA_IP_V6_SRC + dstIPsFlag = nl.CTA_IP_V6_DST + } else { + return []*nl.RtAttr{}, fmt.Errorf("couldn't generate netlink message for tuple due to unrecognized FamilyType '%d'", family) + } + + ctTupleIP := nl.NewRtAttr(unix.NLA_F_NESTED|nl.CTA_TUPLE_IP, nil) + ctTupleIPSrc := nl.NewRtAttr(srcIPsFlag, t.SrcIP) + ctTupleIP.AddChild(ctTupleIPSrc) + ctTupleIPDst := nl.NewRtAttr(dstIPsFlag, t.DstIP) + ctTupleIP.AddChild(ctTupleIPDst) + + ctTupleProto := nl.NewRtAttr(unix.NLA_F_NESTED|nl.CTA_TUPLE_PROTO, nil) + ctTupleProtoNum := nl.NewRtAttr(nl.CTA_PROTO_NUM, []byte{t.Protocol}) + ctTupleProto.AddChild(ctTupleProtoNum) + ctTupleProtoSrcPort := nl.NewRtAttr(nl.CTA_PROTO_SRC_PORT, nl.BEUint16Attr(t.SrcPort)) + ctTupleProto.AddChild(ctTupleProtoSrcPort) + ctTupleProtoDstPort := nl.NewRtAttr(nl.CTA_PROTO_DST_PORT, nl.BEUint16Attr(t.DstPort)) + ctTupleProto.AddChild(ctTupleProtoDstPort, ) + + return []*nl.RtAttr{ctTupleIP, ctTupleProto}, nil +} + type ConntrackFlow struct { FamilyType uint8 - Forward ipTuple - Reverse ipTuple + Forward IPTuple + Reverse IPTuple Mark uint32 + Zone uint16 + TimeStart uint64 + TimeStop uint64 + TimeOut uint32 + Labels []byte + ProtoInfo ProtoInfo } func (s *ConntrackFlow) String() string { // conntrack cmd output: - // udp 17 src=127.0.0.1 dst=127.0.0.1 sport=4001 dport=1234 packets=5 bytes=532 [UNREPLIED] src=127.0.0.1 dst=127.0.0.1 sport=1234 dport=4001 packets=10 bytes=1078 mark=0 - return fmt.Sprintf("%s\t%d src=%s dst=%s sport=%d dport=%d packets=%d bytes=%d\tsrc=%s dst=%s sport=%d dport=%d packets=%d bytes=%d mark=%d", + // udp 17 src=127.0.0.1 dst=127.0.0.1 sport=4001 dport=1234 packets=5 bytes=532 [UNREPLIED] src=127.0.0.1 dst=127.0.0.1 sport=1234 dport=4001 packets=10 bytes=1078 mark=0 labels=0x00000000050012ac4202010000000000 zone=100 + // start=2019-07-26 01:26:21.557800506 +0000 UTC stop=1970-01-01 00:00:00 +0000 UTC timeout=30(sec) + start := time.Unix(0, int64(s.TimeStart)) + stop := time.Unix(0, int64(s.TimeStop)) + timeout := int32(s.TimeOut) + res := fmt.Sprintf("%s\t%d src=%s dst=%s sport=%d dport=%d packets=%d bytes=%d\tsrc=%s dst=%s sport=%d dport=%d packets=%d bytes=%d mark=0x%x ", nl.L4ProtoMap[s.Forward.Protocol], s.Forward.Protocol, s.Forward.SrcIP.String(), s.Forward.DstIP.String(), s.Forward.SrcPort, s.Forward.DstPort, s.Forward.Packets, s.Forward.Bytes, s.Reverse.SrcIP.String(), s.Reverse.DstIP.String(), s.Reverse.SrcPort, s.Reverse.DstPort, s.Reverse.Packets, s.Reverse.Bytes, s.Mark) + if len(s.Labels) > 0 { + res += fmt.Sprintf("labels=0x%x ", s.Labels) + } + if s.Zone != 0 { + res += fmt.Sprintf("zone=%d ", s.Zone) + } + res += fmt.Sprintf("start=%v stop=%v timeout=%d(sec)", start, stop, timeout) + return res +} + +// toNlData generates netlink messages representing the flow. +func (s *ConntrackFlow) toNlData() ([]*nl.RtAttr, error) { + var payload []*nl.RtAttr + // The message structure is built as follows: + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + + // CTA_TUPLE_ORIG + ctTupleOrig := nl.NewRtAttr(unix.NLA_F_NESTED|nl.CTA_TUPLE_ORIG, nil) + forwardFlowAttrs, err := s.Forward.toNlData(s.FamilyType) + if err != nil { + return nil, fmt.Errorf("couldn't generate netlink data for conntrack forward flow: %w", err) + } + for _, a := range forwardFlowAttrs { + ctTupleOrig.AddChild(a) + } + + // CTA_TUPLE_REPLY + ctTupleReply := nl.NewRtAttr(unix.NLA_F_NESTED|nl.CTA_TUPLE_REPLY, nil) + reverseFlowAttrs, err := s.Reverse.toNlData(s.FamilyType) + if err != nil { + return nil, fmt.Errorf("couldn't generate netlink data for conntrack reverse flow: %w", err) + } + for _, a := range reverseFlowAttrs { + ctTupleReply.AddChild(a) + } + + ctMark := nl.NewRtAttr(nl.CTA_MARK, nl.BEUint32Attr(s.Mark)) + ctTimeout := nl.NewRtAttr(nl.CTA_TIMEOUT, nl.BEUint32Attr(s.TimeOut)) + + payload = append(payload, ctTupleOrig, ctTupleReply, ctMark, ctTimeout) + + if s.ProtoInfo != nil { + switch p := s.ProtoInfo.(type) { + case *ProtoInfoTCP: + attrs, err := p.toNlData() + if err != nil { + return nil, fmt.Errorf("couldn't generate netlink data for conntrack flow's TCP protoinfo: %w", err) + } + payload = append(payload, attrs...) + default: + return nil, errors.New("couldn't generate netlink data for conntrack: field 'ProtoInfo' only supports TCP or nil") + } + } + + return payload, nil } // This method parse the ip tuple structure @@ -164,7 +394,7 @@ func (s *ConntrackFlow) String() string { // // // -func parseIpTuple(reader *bytes.Reader, tpl *ipTuple) uint8 { +func parseIpTuple(reader *bytes.Reader, tpl *IPTuple) uint8 { for i := 0; i < 2; i++ { _, t, _, v := parseNfAttrTLV(reader) switch t { @@ -174,25 +404,43 @@ func parseIpTuple(reader *bytes.Reader, tpl *ipTuple) uint8 { tpl.DstIP = v } } - // Skip the next 4 bytes nl.NLA_F_NESTED|nl.CTA_TUPLE_PROTO - reader.Seek(4, seekCurrent) - _, t, _, v := parseNfAttrTLV(reader) + // Get total length of nested protocol-specific info. + _, _, protoInfoTotalLen := parseNfAttrTL(reader) + _, t, l, v := parseNfAttrTLV(reader) + // Track the number of bytes read. + protoInfoBytesRead := uint16(nl.SizeofNfattr) + l if t == nl.CTA_PROTO_NUM { tpl.Protocol = uint8(v[0]) } - // Skip some padding 3 bytes + // We only parse TCP & UDP headers. Skip the others. + if tpl.Protocol != unix.IPPROTO_TCP && tpl.Protocol != unix.IPPROTO_UDP { + // skip the rest + bytesRemaining := protoInfoTotalLen - protoInfoBytesRead + reader.Seek(int64(bytesRemaining), seekCurrent) + return tpl.Protocol + } + // Skip 3 bytes of padding reader.Seek(3, seekCurrent) + protoInfoBytesRead += 3 for i := 0; i < 2; i++ { _, t, _ := parseNfAttrTL(reader) + protoInfoBytesRead += uint16(nl.SizeofNfattr) switch t { case nl.CTA_PROTO_SRC_PORT: parseBERaw16(reader, &tpl.SrcPort) + protoInfoBytesRead += 2 case nl.CTA_PROTO_DST_PORT: parseBERaw16(reader, &tpl.DstPort) + protoInfoBytesRead += 2 } - // Skip some padding 2 byte + // Skip 2 bytes of padding reader.Seek(2, seekCurrent) + protoInfoBytesRead += 2 } + // Skip any remaining/unknown parts of the message + bytesRemaining := protoInfoTotalLen - protoInfoBytesRead + reader.Seek(int64(bytesRemaining), seekCurrent) + return tpl.Protocol } @@ -211,10 +459,18 @@ func parseNfAttrTL(r *bytes.Reader) (isNested bool, attrType, len uint16) { binary.Read(r, nl.NativeEndian(), &attrType) isNested = (attrType & nl.NLA_F_NESTED) == nl.NLA_F_NESTED attrType = attrType & (nl.NLA_F_NESTED - 1) - return isNested, attrType, len } +// skipNfAttrValue seeks `r` past attr of length `len`. +// Maintains buffer alignment. +// Returns length of the seek performed. +func skipNfAttrValue(r *bytes.Reader, len uint16) uint16 { + len = (len + nl.NLA_ALIGNTO - 1) & ^(nl.NLA_ALIGNTO - 1) + r.Seek(int64(len), seekCurrent) + return len +} + func parseBERaw16(r *bytes.Reader, v *uint16) { binary.Read(r, binary.BigEndian, v) } @@ -227,6 +483,10 @@ func parseBERaw64(r *bytes.Reader, v *uint64) { binary.Read(r, binary.BigEndian, v) } +func parseRaw32(r *bytes.Reader, v *uint32) { + binary.Read(r, nl.NativeEndian(), v) +} + func parseByteAndPacketCounters(r *bytes.Reader) (bytes, packets uint64) { for i := 0; i < 2; i++ { switch _, t, _ := parseNfAttrTL(r); t { @@ -241,11 +501,107 @@ func parseByteAndPacketCounters(r *bytes.Reader) (bytes, packets uint64) { return } +// when the flow is alive, only the timestamp_start is returned in structure +func parseTimeStamp(r *bytes.Reader, readSize uint16) (tstart, tstop uint64) { + var numTimeStamps int + oneItem := nl.SizeofNfattr + 8 // 4 bytes attr header + 8 bytes timestamp + if readSize == uint16(oneItem) { + numTimeStamps = 1 + } else if readSize == 2*uint16(oneItem) { + numTimeStamps = 2 + } else { + return + } + for i := 0; i < numTimeStamps; i++ { + switch _, t, _ := parseNfAttrTL(r); t { + case nl.CTA_TIMESTAMP_START: + parseBERaw64(r, &tstart) + case nl.CTA_TIMESTAMP_STOP: + parseBERaw64(r, &tstop) + default: + return + } + } + return + +} + +func parseProtoInfoTCPState(r *bytes.Reader) (s uint8) { + binary.Read(r, binary.BigEndian, &s) + r.Seek(nl.SizeofNfattr - 1, seekCurrent) + return s +} + +// parseProtoInfoTCP reads the entire nested protoinfo structure, but only parses the state attr. +func parseProtoInfoTCP(r *bytes.Reader, attrLen uint16) (*ProtoInfoTCP) { + p := new(ProtoInfoTCP) + bytesRead := 0 + for bytesRead < int(attrLen) { + _, t, l := parseNfAttrTL(r) + bytesRead += nl.SizeofNfattr + + switch t { + case nl.CTA_PROTOINFO_TCP_STATE: + p.State = parseProtoInfoTCPState(r) + bytesRead += nl.SizeofNfattr + default: + bytesRead += int(skipNfAttrValue(r, l)) + } + } + + return p +} + +func parseProtoInfo(r *bytes.Reader, attrLen uint16) (p ProtoInfo) { + bytesRead := 0 + for bytesRead < int(attrLen) { + _, t, l := parseNfAttrTL(r) + bytesRead += nl.SizeofNfattr + + switch t { + case nl.CTA_PROTOINFO_TCP: + p = parseProtoInfoTCP(r, l) + bytesRead += int(l) + // No inner fields of DCCP / SCTP currently supported. + case nl.CTA_PROTOINFO_DCCP: + p = new(ProtoInfoDCCP) + skipped := skipNfAttrValue(r, l) + bytesRead += int(skipped) + case nl.CTA_PROTOINFO_SCTP: + p = new(ProtoInfoSCTP) + skipped := skipNfAttrValue(r, l) + bytesRead += int(skipped) + default: + skipped := skipNfAttrValue(r, l) + bytesRead += int(skipped) + } + } + + return p +} + +func parseTimeOut(r *bytes.Reader) (ttimeout uint32) { + parseBERaw32(r, &ttimeout) + return +} + func parseConnectionMark(r *bytes.Reader) (mark uint32) { parseBERaw32(r, &mark) return } +func parseConnectionLabels(r *bytes.Reader) (label []byte) { + label = make([]byte, 16) // netfilter defines 128 bit labels value + binary.Read(r, nl.NativeEndian(), &label) + return +} + +func parseConnectionZone(r *bytes.Reader) (zone uint16) { + parseBERaw16(r, &zone) + r.Seek(2, seekCurrent) + return +} + func parseRawData(data []byte) *ConntrackFlow { s := &ConntrackFlow{} // First there is the Nfgenmsg header @@ -266,25 +622,41 @@ func parseRawData(data []byte) *ConntrackFlow { if nested, t, l := parseNfAttrTL(reader); nested { switch t { case nl.CTA_TUPLE_ORIG: - if nested, t, _ = parseNfAttrTL(reader); nested && t == nl.CTA_TUPLE_IP { + if nested, t, l = parseNfAttrTL(reader); nested && t == nl.CTA_TUPLE_IP { parseIpTuple(reader, &s.Forward) } case nl.CTA_TUPLE_REPLY: - if nested, t, _ = parseNfAttrTL(reader); nested && t == nl.CTA_TUPLE_IP { + if nested, t, l = parseNfAttrTL(reader); nested && t == nl.CTA_TUPLE_IP { parseIpTuple(reader, &s.Reverse) } else { // Header not recognized skip it - reader.Seek(int64(l), seekCurrent) + skipNfAttrValue(reader, l) } case nl.CTA_COUNTERS_ORIG: s.Forward.Bytes, s.Forward.Packets = parseByteAndPacketCounters(reader) case nl.CTA_COUNTERS_REPLY: s.Reverse.Bytes, s.Reverse.Packets = parseByteAndPacketCounters(reader) + case nl.CTA_TIMESTAMP: + s.TimeStart, s.TimeStop = parseTimeStamp(reader, l) + case nl.CTA_PROTOINFO: + s.ProtoInfo = parseProtoInfo(reader, l) + default: + skipNfAttrValue(reader, l) } } else { switch t { case nl.CTA_MARK: s.Mark = parseConnectionMark(reader) + case nl.CTA_LABELS: + s.Labels = parseConnectionLabels(reader) + case nl.CTA_TIMEOUT: + s.TimeOut = parseTimeOut(reader) + case nl.CTA_ID, nl.CTA_STATUS, nl.CTA_USE: + skipNfAttrValue(reader, l) + case nl.CTA_ZONE: + s.Zone = parseConnectionZone(reader) + default: + skipNfAttrValue(reader, l) } } } @@ -318,18 +690,27 @@ func parseRawData(data []byte) *ConntrackFlow { // --mask-src ip Source mask address // --mask-dst ip Destination mask address +// Layer 4 Protocol common parameters and options: +// TCP, UDP, SCTP, UDPLite and DCCP +// --sport, --orig-port-src port Source port in original direction +// --dport, --orig-port-dst port Destination port in original direction + // Filter types type ConntrackFilterType uint8 const ( - ConntrackOrigSrcIP = iota // -orig-src ip Source address from original direction - ConntrackOrigDstIP // -orig-dst ip Destination address from original direction - ConntrackReplySrcIP // --reply-src ip Reply Source IP - ConntrackReplyDstIP // --reply-dst ip Reply Destination IP - ConntrackReplyAnyIP // Match source or destination reply IP - ConntrackNatSrcIP = ConntrackReplySrcIP // deprecated use instead ConntrackReplySrcIP - ConntrackNatDstIP = ConntrackReplyDstIP // deprecated use instead ConntrackReplyDstIP - ConntrackNatAnyIP = ConntrackReplyAnyIP // deprecated use instaed ConntrackReplyAnyIP + ConntrackOrigSrcIP = iota // -orig-src ip Source address from original direction + ConntrackOrigDstIP // -orig-dst ip Destination address from original direction + ConntrackReplySrcIP // --reply-src ip Reply Source IP + ConntrackReplyDstIP // --reply-dst ip Reply Destination IP + ConntrackReplyAnyIP // Match source or destination reply IP + ConntrackOrigSrcPort // --orig-port-src port Source port in original direction + ConntrackOrigDstPort // --orig-port-dst port Destination port in original direction + ConntrackMatchLabels // --label label1,label2 Labels used in entry + ConntrackUnmatchLabels // --label label1,label2 Labels not used in entry + ConntrackNatSrcIP = ConntrackReplySrcIP // deprecated use instead ConntrackReplySrcIP + ConntrackNatDstIP = ConntrackReplyDstIP // deprecated use instead ConntrackReplyDstIP + ConntrackNatAnyIP = ConntrackReplyAnyIP // deprecated use instead ConntrackReplyAnyIP ) type CustomConntrackFilter interface { @@ -339,53 +720,180 @@ type CustomConntrackFilter interface { } type ConntrackFilter struct { - ipFilter map[ConntrackFilterType]net.IP + ipNetFilter map[ConntrackFilterType]*net.IPNet + portFilter map[ConntrackFilterType]uint16 + protoFilter uint8 + labelFilter map[ConntrackFilterType][][]byte + zoneFilter *uint16 +} + +// AddIPNet adds a IP subnet to the conntrack filter +func (f *ConntrackFilter) AddIPNet(tp ConntrackFilterType, ipNet *net.IPNet) error { + if ipNet == nil { + return fmt.Errorf("Filter attribute empty") + } + if f.ipNetFilter == nil { + f.ipNetFilter = make(map[ConntrackFilterType]*net.IPNet) + } + if _, ok := f.ipNetFilter[tp]; ok { + return errors.New("Filter attribute already present") + } + f.ipNetFilter[tp] = ipNet + return nil } // AddIP adds an IP to the conntrack filter func (f *ConntrackFilter) AddIP(tp ConntrackFilterType, ip net.IP) error { - if f.ipFilter == nil { - f.ipFilter = make(map[ConntrackFilterType]net.IP) + if ip == nil { + return fmt.Errorf("Filter attribute empty") + } + return f.AddIPNet(tp, NewIPNet(ip)) +} + +// AddPort adds a Port to the conntrack filter if the Layer 4 protocol allows it +func (f *ConntrackFilter) AddPort(tp ConntrackFilterType, port uint16) error { + switch f.protoFilter { + // TCP, UDP, DCCP, SCTP, UDPLite + case 6, 17, 33, 132, 136: + default: + return fmt.Errorf("Filter attribute not available without a valid Layer 4 protocol: %d", f.protoFilter) } - if _, ok := f.ipFilter[tp]; ok { + + if f.portFilter == nil { + f.portFilter = make(map[ConntrackFilterType]uint16) + } + if _, ok := f.portFilter[tp]; ok { return errors.New("Filter attribute already present") } - f.ipFilter[tp] = ip + f.portFilter[tp] = port + return nil +} + +// AddProtocol adds the Layer 4 protocol to the conntrack filter +func (f *ConntrackFilter) AddProtocol(proto uint8) error { + if f.protoFilter != 0 { + return errors.New("Filter attribute already present") + } + f.protoFilter = proto + return nil +} + +// AddLabels adds the provided list (zero or more) of labels to the conntrack filter +// ConntrackFilterType here can be either: +// 1. ConntrackMatchLabels: This matches every flow that has a label value (len(flow.Labels) > 0) +// against the list of provided labels. If `flow.Labels` contains ALL the provided labels +// it is considered a match. This can be used when you want to match flows that contain +// one or more labels. +// 2. ConntrackUnmatchLabels: This matches every flow that has a label value (len(flow.Labels) > 0) +// against the list of provided labels. If `flow.Labels` does NOT contain ALL the provided labels +// it is considered a match. This can be used when you want to match flows that don't contain +// one or more labels. +func (f *ConntrackFilter) AddLabels(tp ConntrackFilterType, labels [][]byte) error { + if len(labels) == 0 { + return errors.New("Invalid length for provided labels") + } + if f.labelFilter == nil { + f.labelFilter = make(map[ConntrackFilterType][][]byte) + } + if _, ok := f.labelFilter[tp]; ok { + return errors.New("Filter attribute already present") + } + f.labelFilter[tp] = labels + return nil +} + +// AddZone adds a zone to the conntrack filter +func (f *ConntrackFilter) AddZone(zone uint16) error { + if f.zoneFilter != nil { + return errors.New("Filter attribute already present") + } + f.zoneFilter = &zone return nil } // MatchConntrackFlow applies the filter to the flow and returns true if the flow matches the filter // false otherwise func (f *ConntrackFilter) MatchConntrackFlow(flow *ConntrackFlow) bool { - if len(f.ipFilter) == 0 { + if len(f.ipNetFilter) == 0 && len(f.portFilter) == 0 && f.protoFilter == 0 && len(f.labelFilter) == 0 && f.zoneFilter == nil { // empty filter always not match return false } - match := true - // -orig-src ip Source address from original direction - if elem, found := f.ipFilter[ConntrackOrigSrcIP]; found { - match = match && elem.Equal(flow.Forward.SrcIP) + // -p, --protonum proto Layer 4 Protocol, eg. 'tcp' + if f.protoFilter != 0 && flow.Forward.Protocol != f.protoFilter { + // different Layer 4 protocol always not match + return false } - // -orig-dst ip Destination address from original direction - if elem, found := f.ipFilter[ConntrackOrigDstIP]; match && found { - match = match && elem.Equal(flow.Forward.DstIP) + // Conntrack zone filter + if f.zoneFilter != nil && *f.zoneFilter != flow.Zone { + return false } - // -src-nat ip Source NAT ip - if elem, found := f.ipFilter[ConntrackReplySrcIP]; match && found { - match = match && elem.Equal(flow.Reverse.SrcIP) + match := true + + // IP conntrack filter + if len(f.ipNetFilter) > 0 { + // -orig-src ip Source address from original direction + if elem, found := f.ipNetFilter[ConntrackOrigSrcIP]; found { + match = match && elem.Contains(flow.Forward.SrcIP) + } + + // -orig-dst ip Destination address from original direction + if elem, found := f.ipNetFilter[ConntrackOrigDstIP]; match && found { + match = match && elem.Contains(flow.Forward.DstIP) + } + + // -src-nat ip Source NAT ip + if elem, found := f.ipNetFilter[ConntrackReplySrcIP]; match && found { + match = match && elem.Contains(flow.Reverse.SrcIP) + } + + // -dst-nat ip Destination NAT ip + if elem, found := f.ipNetFilter[ConntrackReplyDstIP]; match && found { + match = match && elem.Contains(flow.Reverse.DstIP) + } + + // Match source or destination reply IP + if elem, found := f.ipNetFilter[ConntrackReplyAnyIP]; match && found { + match = match && (elem.Contains(flow.Reverse.SrcIP) || elem.Contains(flow.Reverse.DstIP)) + } } - // -dst-nat ip Destination NAT ip - if elem, found := f.ipFilter[ConntrackReplyDstIP]; match && found { - match = match && elem.Equal(flow.Reverse.DstIP) + // Layer 4 Port filter + if len(f.portFilter) > 0 { + // -orig-port-src port Source port from original direction + if elem, found := f.portFilter[ConntrackOrigSrcPort]; match && found { + match = match && elem == flow.Forward.SrcPort + } + + // -orig-port-dst port Destination port from original direction + if elem, found := f.portFilter[ConntrackOrigDstPort]; match && found { + match = match && elem == flow.Forward.DstPort + } } - // Match source or destination reply IP - if elem, found := f.ipFilter[ConntrackReplyAnyIP]; match && found { - match = match && (elem.Equal(flow.Reverse.SrcIP) || elem.Equal(flow.Reverse.DstIP)) + // Label filter + if len(f.labelFilter) > 0 { + if len(flow.Labels) > 0 { + // --label label1,label2 in conn entry; + // every label passed should be contained in flow.Labels for a match to be true + if elem, found := f.labelFilter[ConntrackMatchLabels]; match && found { + for _, label := range elem { + match = match && (bytes.Contains(flow.Labels, label)) + } + } + // --label label1,label2 in conn entry; + // every label passed should be not contained in flow.Labels for a match to be true + if elem, found := f.labelFilter[ConntrackUnmatchLabels]; match && found { + for _, label := range elem { + match = match && !(bytes.Contains(flow.Labels, label)) + } + } + } else { + // flow doesn't contain labels, so it doesn't contain or notContain any provided matches + match = false + } } return match diff --git a/vendor/github.com/vishvananda/netlink/conntrack_unspecified.go b/vendor/github.com/vishvananda/netlink/conntrack_unspecified.go index af7af799e..0bfdf422d 100644 --- a/vendor/github.com/vishvananda/netlink/conntrack_unspecified.go +++ b/vendor/github.com/vishvananda/netlink/conntrack_unspecified.go @@ -11,6 +11,9 @@ type InetFamily uint8 // ConntrackFlow placeholder type ConntrackFlow struct{} +// CustomConntrackFilter placeholder +type CustomConntrackFilter struct{} + // ConntrackFilter placeholder type ConntrackFilter struct{} @@ -29,10 +32,18 @@ func ConntrackTableFlush(table ConntrackTableType) error { // ConntrackDeleteFilter deletes entries on the specified table on the base of the filter // conntrack -D [table] parameters Delete conntrack or expectation +// +// Deprecated: use [ConntrackDeleteFilter] instead. func ConntrackDeleteFilter(table ConntrackTableType, family InetFamily, filter *ConntrackFilter) (uint, error) { return 0, ErrNotImplemented } +// ConntrackDeleteFilters deletes entries on the specified table matching any of the specified filters +// conntrack -D [table] parameters Delete conntrack or expectation +func ConntrackDeleteFilters(table ConntrackTableType, family InetFamily, filters ...CustomConntrackFilter) (uint, error) { + return 0, ErrNotImplemented +} + // ConntrackTableList returns the flow list of a table of a specific family using the netlink handle passed // conntrack -L [table] [options] List conntrack or expectation table func (h *Handle) ConntrackTableList(table ConntrackTableType, family InetFamily) ([]*ConntrackFlow, error) { @@ -48,6 +59,14 @@ func (h *Handle) ConntrackTableFlush(table ConntrackTableType) error { // ConntrackDeleteFilter deletes entries on the specified table on the base of the filter using the netlink handle passed // conntrack -D [table] parameters Delete conntrack or expectation +// +// Deprecated: use [Handle.ConntrackDeleteFilters] instead. func (h *Handle) ConntrackDeleteFilter(table ConntrackTableType, family InetFamily, filter *ConntrackFilter) (uint, error) { return 0, ErrNotImplemented } + +// ConntrackDeleteFilters deletes entries on the specified table matching any of the specified filters using the netlink handle passed +// conntrack -D [table] parameters Delete conntrack or expectation +func (h *Handle) ConntrackDeleteFilters(table ConntrackTableType, family InetFamily, filters ...CustomConntrackFilter) (uint, error) { + return 0, ErrNotImplemented +} diff --git a/vendor/github.com/vishvananda/netlink/devlink_linux.go b/vendor/github.com/vishvananda/netlink/devlink_linux.go index 29b3f8ec1..d98801dbb 100644 --- a/vendor/github.com/vishvananda/netlink/devlink_linux.go +++ b/vendor/github.com/vishvananda/netlink/devlink_linux.go @@ -1,9 +1,11 @@ package netlink import ( + "fmt" + "net" + "strings" "syscall" - "fmt" "github.com/vishvananda/netlink/nl" "golang.org/x/sys/unix" ) @@ -27,6 +29,325 @@ type DevlinkDevice struct { Attrs DevlinkDevAttrs } +// DevlinkPortFn represents port function and its attributes +type DevlinkPortFn struct { + HwAddr net.HardwareAddr + State uint8 + OpState uint8 +} + +// DevlinkPortFnSetAttrs represents attributes to set +type DevlinkPortFnSetAttrs struct { + FnAttrs DevlinkPortFn + HwAddrValid bool + StateValid bool +} + +// DevlinkPort represents port and its attributes +type DevlinkPort struct { + BusName string + DeviceName string + PortIndex uint32 + PortType uint16 + NetdeviceName string + NetdevIfIndex uint32 + RdmaDeviceName string + PortFlavour uint16 + Fn *DevlinkPortFn +} + +type DevLinkPortAddAttrs struct { + Controller uint32 + SfNumber uint32 + PortIndex uint32 + PfNumber uint16 + SfNumberValid bool + PortIndexValid bool + ControllerValid bool +} + +// DevlinkDeviceInfo represents devlink info +type DevlinkDeviceInfo struct { + Driver string + SerialNumber string + BoardID string + FwApp string + FwAppBoundleID string + FwAppName string + FwBoundleID string + FwMgmt string + FwMgmtAPI string + FwMgmtBuild string + FwNetlist string + FwNetlistBuild string + FwPsidAPI string + FwUndi string +} + +// DevlinkResource represents a device resource +type DevlinkResource struct { + Name string + ID uint64 + Size uint64 + SizeNew uint64 + SizeMin uint64 + SizeMax uint64 + SizeGranularity uint64 + PendingChange bool + Unit uint8 + SizeValid bool + OCCValid bool + OCCSize uint64 + Parent *DevlinkResource + Children []DevlinkResource +} + +// parseAttributes parses provided Netlink Attributes and populates DevlinkResource, returns error if occured +func (dlr *DevlinkResource) parseAttributes(attrs map[uint16]syscall.NetlinkRouteAttr) error { + var attr syscall.NetlinkRouteAttr + var ok bool + + // mandatory attributes + attr, ok = attrs[nl.DEVLINK_ATTR_RESOURCE_ID] + if !ok { + return fmt.Errorf("missing resource id") + } + dlr.ID = native.Uint64(attr.Value) + + attr, ok = attrs[nl.DEVLINK_ATTR_RESOURCE_NAME] + if !ok { + return fmt.Errorf("missing resource name") + } + dlr.Name = nl.BytesToString(attr.Value) + + attr, ok = attrs[nl.DEVLINK_ATTR_RESOURCE_SIZE] + if !ok { + return fmt.Errorf("missing resource size") + } + dlr.Size = native.Uint64(attr.Value) + + attr, ok = attrs[nl.DEVLINK_ATTR_RESOURCE_SIZE_GRAN] + if !ok { + return fmt.Errorf("missing resource size granularity") + } + dlr.SizeGranularity = native.Uint64(attr.Value) + + attr, ok = attrs[nl.DEVLINK_ATTR_RESOURCE_UNIT] + if !ok { + return fmt.Errorf("missing resource unit") + } + dlr.Unit = uint8(attr.Value[0]) + + attr, ok = attrs[nl.DEVLINK_ATTR_RESOURCE_SIZE_MIN] + if !ok { + return fmt.Errorf("missing resource size min") + } + dlr.SizeMin = native.Uint64(attr.Value) + + attr, ok = attrs[nl.DEVLINK_ATTR_RESOURCE_SIZE_MAX] + if !ok { + return fmt.Errorf("missing resource size max") + } + dlr.SizeMax = native.Uint64(attr.Value) + + // optional attributes + attr, ok = attrs[nl.DEVLINK_ATTR_RESOURCE_OCC] + if ok { + dlr.OCCSize = native.Uint64(attr.Value) + dlr.OCCValid = true + } + + attr, ok = attrs[nl.DEVLINK_ATTR_RESOURCE_SIZE_VALID] + if ok { + dlr.SizeValid = uint8(attr.Value[0]) != 0 + } + + dlr.SizeNew = dlr.Size + attr, ok = attrs[nl.DEVLINK_ATTR_RESOURCE_SIZE_NEW] + if ok { + dlr.SizeNew = native.Uint64(attr.Value) + } + + dlr.PendingChange = dlr.Size != dlr.SizeNew + + attr, ok = attrs[nl.DEVLINK_ATTR_RESOURCE_LIST] + if ok { + // handle nested resoruces recursively + subResources, err := nl.ParseRouteAttr(attr.Value) + if err != nil { + return err + } + + for _, subresource := range subResources { + resource := DevlinkResource{Parent: dlr} + attrs, err := nl.ParseRouteAttrAsMap(subresource.Value) + if err != nil { + return err + } + err = resource.parseAttributes(attrs) + if err != nil { + return fmt.Errorf("failed to parse child resource, parent:%s. %w", dlr.Name, err) + } + dlr.Children = append(dlr.Children, resource) + } + } + return nil +} + +// DevlinkResources represents all devlink resources of a devlink device +type DevlinkResources struct { + Bus string + Device string + Resources []DevlinkResource +} + +// parseAttributes parses provided Netlink Attributes and populates DevlinkResources, returns error if occured +func (dlrs *DevlinkResources) parseAttributes(attrs map[uint16]syscall.NetlinkRouteAttr) error { + var attr syscall.NetlinkRouteAttr + var ok bool + + // Bus + attr, ok = attrs[nl.DEVLINK_ATTR_BUS_NAME] + if !ok { + return fmt.Errorf("missing bus name") + } + dlrs.Bus = nl.BytesToString(attr.Value) + + // Device + attr, ok = attrs[nl.DEVLINK_ATTR_DEV_NAME] + if !ok { + return fmt.Errorf("missing device name") + } + dlrs.Device = nl.BytesToString(attr.Value) + + // Resource List + attr, ok = attrs[nl.DEVLINK_ATTR_RESOURCE_LIST] + if !ok { + return fmt.Errorf("missing resource list") + } + + resourceAttrs, err := nl.ParseRouteAttr(attr.Value) + if err != nil { + return err + } + + for _, resourceAttr := range resourceAttrs { + resource := DevlinkResource{} + attrs, err := nl.ParseRouteAttrAsMap(resourceAttr.Value) + if err != nil { + return err + } + err = resource.parseAttributes(attrs) + if err != nil { + return fmt.Errorf("failed to parse root resoruces, %w", err) + } + dlrs.Resources = append(dlrs.Resources, resource) + } + + return nil +} + +// DevlinkParam represents parameter of the device +type DevlinkParam struct { + Name string + IsGeneric bool + Type uint8 // possible values are in nl.DEVLINK_PARAM_TYPE_* constants + Values []DevlinkParamValue +} + +// DevlinkParamValue contains values of the parameter +// Data field contains specific type which can be casted by unsing info from the DevlinkParam.Type field +type DevlinkParamValue struct { + rawData []byte + Data interface{} + CMODE uint8 // possible values are in nl.DEVLINK_PARAM_CMODE_* constants +} + +// parseAttributes parses provided Netlink Attributes and populates DevlinkParam, returns error if occured +func (dlp *DevlinkParam) parseAttributes(attrs []syscall.NetlinkRouteAttr) error { + var valuesList [][]syscall.NetlinkRouteAttr + for _, attr := range attrs { + switch attr.Attr.Type { + case nl.DEVLINK_ATTR_PARAM: + nattrs, err := nl.ParseRouteAttr(attr.Value) + if err != nil { + return err + } + for _, nattr := range nattrs { + switch nattr.Attr.Type { + case nl.DEVLINK_ATTR_PARAM_NAME: + dlp.Name = nl.BytesToString(nattr.Value) + case nl.DEVLINK_ATTR_PARAM_GENERIC: + dlp.IsGeneric = true + case nl.DEVLINK_ATTR_PARAM_TYPE: + if len(nattr.Value) == 1 { + dlp.Type = nattr.Value[0] + } + case nl.DEVLINK_ATTR_PARAM_VALUES_LIST: + nnattrs, err := nl.ParseRouteAttr(nattr.Value) + if err != nil { + return err + } + valuesList = append(valuesList, nnattrs) + } + } + } + } + for _, valAttr := range valuesList { + v := DevlinkParamValue{} + if err := v.parseAttributes(valAttr, dlp.Type); err != nil { + return err + } + dlp.Values = append(dlp.Values, v) + } + return nil +} + +func (dlpv *DevlinkParamValue) parseAttributes(attrs []syscall.NetlinkRouteAttr, paramType uint8) error { + for _, attr := range attrs { + nattrs, err := nl.ParseRouteAttr(attr.Value) + if err != nil { + return err + } + var rawData []byte + for _, nattr := range nattrs { + switch nattr.Attr.Type { + case nl.DEVLINK_ATTR_PARAM_VALUE_DATA: + rawData = nattr.Value + case nl.DEVLINK_ATTR_PARAM_VALUE_CMODE: + if len(nattr.Value) == 1 { + dlpv.CMODE = nattr.Value[0] + } + } + } + switch paramType { + case nl.DEVLINK_PARAM_TYPE_U8: + dlpv.Data = uint8(0) + if rawData != nil && len(rawData) == 1 { + dlpv.Data = uint8(rawData[0]) + } + case nl.DEVLINK_PARAM_TYPE_U16: + dlpv.Data = uint16(0) + if rawData != nil { + dlpv.Data = native.Uint16(rawData) + } + case nl.DEVLINK_PARAM_TYPE_U32: + dlpv.Data = uint32(0) + if rawData != nil { + dlpv.Data = native.Uint32(rawData) + } + case nl.DEVLINK_PARAM_TYPE_STRING: + dlpv.Data = "" + if rawData != nil { + dlpv.Data = nl.BytesToString(rawData) + } + case nl.DEVLINK_PARAM_TYPE_BOOL: + dlpv.Data = rawData != nil + } + } + return nil +} + func parseDevLinkDeviceList(msgs [][]byte) ([]*DevlinkDevice, error) { devices := make([]*DevlinkDevice, 0, len(msgs)) for _, m := range msgs { @@ -95,9 +416,9 @@ func (d *DevlinkDevice) parseAttributes(attrs []syscall.NetlinkRouteAttr) error for _, a := range attrs { switch a.Attr.Type { case nl.DEVLINK_ATTR_BUS_NAME: - d.BusName = string(a.Value) + d.BusName = string(a.Value[:len(a.Value)-1]) case nl.DEVLINK_ATTR_DEV_NAME: - d.DeviceName = string(a.Value) + d.DeviceName = string(a.Value[:len(a.Value)-1]) case nl.DEVLINK_ATTR_ESWITCH_MODE: d.Attrs.Eswitch.Mode = parseEswitchMode(native.Uint16(a.Value)) case nl.DEVLINK_ATTR_ESWITCH_INLINE_MODE: @@ -126,12 +447,12 @@ func (h *Handle) getEswitchAttrs(family *GenlFamily, dev *DevlinkDevice) { req := h.newNetlinkRequest(int(family.ID), unix.NLM_F_REQUEST|unix.NLM_F_ACK) req.AddData(msg) - b := make([]byte, len(dev.BusName)) + b := make([]byte, len(dev.BusName)+1) copy(b, dev.BusName) data := nl.NewRtAttr(nl.DEVLINK_ATTR_BUS_NAME, b) req.AddData(data) - b = make([]byte, len(dev.DeviceName)) + b = make([]byte, len(dev.DeviceName)+1) copy(b, dev.DeviceName) data = nl.NewRtAttr(nl.DEVLINK_ATTR_DEV_NAME, b) req.AddData(data) @@ -270,3 +591,569 @@ func (h *Handle) DevLinkSetEswitchMode(Dev *DevlinkDevice, NewMode string) error func DevLinkSetEswitchMode(Dev *DevlinkDevice, NewMode string) error { return pkgHandle.DevLinkSetEswitchMode(Dev, NewMode) } + +func (port *DevlinkPort) parseAttributes(attrs []syscall.NetlinkRouteAttr) error { + for _, a := range attrs { + switch a.Attr.Type { + case nl.DEVLINK_ATTR_BUS_NAME: + port.BusName = string(a.Value[:len(a.Value)-1]) + case nl.DEVLINK_ATTR_DEV_NAME: + port.DeviceName = string(a.Value[:len(a.Value)-1]) + case nl.DEVLINK_ATTR_PORT_INDEX: + port.PortIndex = native.Uint32(a.Value) + case nl.DEVLINK_ATTR_PORT_TYPE: + port.PortType = native.Uint16(a.Value) + case nl.DEVLINK_ATTR_PORT_NETDEV_NAME: + port.NetdeviceName = string(a.Value[:len(a.Value)-1]) + case nl.DEVLINK_ATTR_PORT_NETDEV_IFINDEX: + port.NetdevIfIndex = native.Uint32(a.Value) + case nl.DEVLINK_ATTR_PORT_IBDEV_NAME: + port.RdmaDeviceName = string(a.Value[:len(a.Value)-1]) + case nl.DEVLINK_ATTR_PORT_FLAVOUR: + port.PortFlavour = native.Uint16(a.Value) + case nl.DEVLINK_ATTR_PORT_FUNCTION: + port.Fn = &DevlinkPortFn{} + for nested := range nl.ParseAttributes(a.Value) { + switch nested.Type { + case nl.DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR: + port.Fn.HwAddr = nested.Value[:] + case nl.DEVLINK_PORT_FN_ATTR_STATE: + port.Fn.State = uint8(nested.Value[0]) + case nl.DEVLINK_PORT_FN_ATTR_OPSTATE: + port.Fn.OpState = uint8(nested.Value[0]) + } + } + } + } + return nil +} + +func parseDevLinkAllPortList(msgs [][]byte) ([]*DevlinkPort, error) { + ports := make([]*DevlinkPort, 0, len(msgs)) + for _, m := range msgs { + attrs, err := nl.ParseRouteAttr(m[nl.SizeofGenlmsg:]) + if err != nil { + return nil, err + } + port := &DevlinkPort{} + if err = port.parseAttributes(attrs); err != nil { + return nil, err + } + ports = append(ports, port) + } + return ports, nil +} + +// DevLinkGetPortList provides a pointer to devlink ports and nil error, +// otherwise returns an error code. +func (h *Handle) DevLinkGetAllPortList() ([]*DevlinkPort, error) { + f, err := h.GenlFamilyGet(nl.GENL_DEVLINK_NAME) + if err != nil { + return nil, err + } + msg := &nl.Genlmsg{ + Command: nl.DEVLINK_CMD_PORT_GET, + Version: nl.GENL_DEVLINK_VERSION, + } + req := h.newNetlinkRequest(int(f.ID), + unix.NLM_F_REQUEST|unix.NLM_F_ACK|unix.NLM_F_DUMP) + req.AddData(msg) + msgs, err := req.Execute(unix.NETLINK_GENERIC, 0) + if err != nil { + return nil, err + } + ports, err := parseDevLinkAllPortList(msgs) + if err != nil { + return nil, err + } + return ports, nil +} + +// DevLinkGetPortList provides a pointer to devlink ports and nil error, +// otherwise returns an error code. +func DevLinkGetAllPortList() ([]*DevlinkPort, error) { + return pkgHandle.DevLinkGetAllPortList() +} + +func parseDevlinkPortMsg(msgs [][]byte) (*DevlinkPort, error) { + m := msgs[0] + attrs, err := nl.ParseRouteAttr(m[nl.SizeofGenlmsg:]) + if err != nil { + return nil, err + } + port := &DevlinkPort{} + if err = port.parseAttributes(attrs); err != nil { + return nil, err + } + return port, nil +} + +// DevLinkGetPortByIndexprovides a pointer to devlink device and nil error, +// otherwise returns an error code. +func (h *Handle) DevLinkGetPortByIndex(Bus string, Device string, PortIndex uint32) (*DevlinkPort, error) { + + _, req, err := h.createCmdReq(nl.DEVLINK_CMD_PORT_GET, Bus, Device) + if err != nil { + return nil, err + } + + req.AddData(nl.NewRtAttr(nl.DEVLINK_ATTR_PORT_INDEX, nl.Uint32Attr(PortIndex))) + + respmsg, err := req.Execute(unix.NETLINK_GENERIC, 0) + if err != nil { + return nil, err + } + port, err := parseDevlinkPortMsg(respmsg) + return port, err +} + +// DevlinkGetDeviceResources returns devlink device resources +func DevlinkGetDeviceResources(bus string, device string) (*DevlinkResources, error) { + return pkgHandle.DevlinkGetDeviceResources(bus, device) +} + +// DevlinkGetDeviceResources returns devlink device resources +func (h *Handle) DevlinkGetDeviceResources(bus string, device string) (*DevlinkResources, error) { + _, req, err := h.createCmdReq(nl.DEVLINK_CMD_RESOURCE_DUMP, bus, device) + if err != nil { + return nil, err + } + + respmsg, err := req.Execute(unix.NETLINK_GENERIC, 0) + if err != nil { + return nil, err + } + + var resources DevlinkResources + for _, m := range respmsg { + attrs, err := nl.ParseRouteAttrAsMap(m[nl.SizeofGenlmsg:]) + if err != nil { + return nil, err + } + resources.parseAttributes(attrs) + } + + return &resources, nil +} + +// DevlinkGetDeviceParams returns parameters for devlink device +// Equivalent to: `devlink dev param show /` +func (h *Handle) DevlinkGetDeviceParams(bus string, device string) ([]*DevlinkParam, error) { + _, req, err := h.createCmdReq(nl.DEVLINK_CMD_PARAM_GET, bus, device) + if err != nil { + return nil, err + } + req.Flags |= unix.NLM_F_DUMP + respmsg, err := req.Execute(unix.NETLINK_GENERIC, 0) + if err != nil { + return nil, err + } + var params []*DevlinkParam + for _, m := range respmsg { + attrs, err := nl.ParseRouteAttr(m[nl.SizeofGenlmsg:]) + if err != nil { + return nil, err + } + p := &DevlinkParam{} + if err := p.parseAttributes(attrs); err != nil { + return nil, err + } + params = append(params, p) + } + + return params, nil +} + +// DevlinkGetDeviceParams returns parameters for devlink device +// Equivalent to: `devlink dev param show /` +func DevlinkGetDeviceParams(bus string, device string) ([]*DevlinkParam, error) { + return pkgHandle.DevlinkGetDeviceParams(bus, device) +} + +// DevlinkGetDeviceParamByName returns specific parameter for devlink device +// Equivalent to: `devlink dev param show / name ` +func (h *Handle) DevlinkGetDeviceParamByName(bus string, device string, param string) (*DevlinkParam, error) { + _, req, err := h.createCmdReq(nl.DEVLINK_CMD_PARAM_GET, bus, device) + if err != nil { + return nil, err + } + req.AddData(nl.NewRtAttr(nl.DEVLINK_ATTR_PARAM_NAME, nl.ZeroTerminated(param))) + respmsg, err := req.Execute(unix.NETLINK_GENERIC, 0) + if err != nil { + return nil, err + } + if len(respmsg) == 0 { + return nil, fmt.Errorf("unexpected response") + } + attrs, err := nl.ParseRouteAttr(respmsg[0][nl.SizeofGenlmsg:]) + if err != nil { + return nil, err + } + p := &DevlinkParam{} + if err := p.parseAttributes(attrs); err != nil { + return nil, err + } + return p, nil +} + +// DevlinkGetDeviceParamByName returns specific parameter for devlink device +// Equivalent to: `devlink dev param show / name ` +func DevlinkGetDeviceParamByName(bus string, device string, param string) (*DevlinkParam, error) { + return pkgHandle.DevlinkGetDeviceParamByName(bus, device, param) +} + +// DevlinkSetDeviceParam set specific parameter for devlink device +// Equivalent to: `devlink dev param set / name cmode value ` +// cmode argument should contain valid cmode value as uint8, modes are define in nl.DEVLINK_PARAM_CMODE_* constants +// value argument should have one of the following types: uint8, uint16, uint32, string, bool +func (h *Handle) DevlinkSetDeviceParam(bus string, device string, param string, cmode uint8, value interface{}) error { + // retrive the param type + p, err := h.DevlinkGetDeviceParamByName(bus, device, param) + if err != nil { + return fmt.Errorf("failed to get device param: %v", err) + } + paramType := p.Type + + _, req, err := h.createCmdReq(nl.DEVLINK_CMD_PARAM_SET, bus, device) + if err != nil { + return err + } + req.AddData(nl.NewRtAttr(nl.DEVLINK_ATTR_PARAM_TYPE, nl.Uint8Attr(paramType))) + req.AddData(nl.NewRtAttr(nl.DEVLINK_ATTR_PARAM_NAME, nl.ZeroTerminated(param))) + req.AddData(nl.NewRtAttr(nl.DEVLINK_ATTR_PARAM_VALUE_CMODE, nl.Uint8Attr(cmode))) + + var valueAsBytes []byte + switch paramType { + case nl.DEVLINK_PARAM_TYPE_U8: + v, ok := value.(uint8) + if !ok { + return fmt.Errorf("unepected value type required: uint8, actual: %T", value) + } + valueAsBytes = nl.Uint8Attr(v) + case nl.DEVLINK_PARAM_TYPE_U16: + v, ok := value.(uint16) + if !ok { + return fmt.Errorf("unepected value type required: uint16, actual: %T", value) + } + valueAsBytes = nl.Uint16Attr(v) + case nl.DEVLINK_PARAM_TYPE_U32: + v, ok := value.(uint32) + if !ok { + return fmt.Errorf("unepected value type required: uint32, actual: %T", value) + } + valueAsBytes = nl.Uint32Attr(v) + case nl.DEVLINK_PARAM_TYPE_STRING: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unepected value type required: string, actual: %T", value) + } + valueAsBytes = nl.ZeroTerminated(v) + case nl.DEVLINK_PARAM_TYPE_BOOL: + v, ok := value.(bool) + if !ok { + return fmt.Errorf("unepected value type required: bool, actual: %T", value) + } + if v { + valueAsBytes = []byte{} + } + default: + return fmt.Errorf("unsupported parameter type: %d", paramType) + } + if valueAsBytes != nil { + req.AddData(nl.NewRtAttr(nl.DEVLINK_ATTR_PARAM_VALUE_DATA, valueAsBytes)) + } + _, err = req.Execute(unix.NETLINK_GENERIC, 0) + return err +} + +// DevlinkSetDeviceParam set specific parameter for devlink device +// Equivalent to: `devlink dev param set / name cmode value ` +// cmode argument should contain valid cmode value as uint8, modes are define in nl.DEVLINK_PARAM_CMODE_* constants +// value argument should have one of the following types: uint8, uint16, uint32, string, bool +func DevlinkSetDeviceParam(bus string, device string, param string, cmode uint8, value interface{}) error { + return pkgHandle.DevlinkSetDeviceParam(bus, device, param, cmode, value) +} + +// DevLinkGetPortByIndex provides a pointer to devlink portand nil error, +// otherwise returns an error code. +func DevLinkGetPortByIndex(Bus string, Device string, PortIndex uint32) (*DevlinkPort, error) { + return pkgHandle.DevLinkGetPortByIndex(Bus, Device, PortIndex) +} + +// DevLinkPortAdd adds a devlink port and returns a port on success +// otherwise returns nil port and an error code. +func (h *Handle) DevLinkPortAdd(Bus string, Device string, Flavour uint16, Attrs DevLinkPortAddAttrs) (*DevlinkPort, error) { + _, req, err := h.createCmdReq(nl.DEVLINK_CMD_PORT_NEW, Bus, Device) + if err != nil { + return nil, err + } + + req.AddData(nl.NewRtAttr(nl.DEVLINK_ATTR_PORT_FLAVOUR, nl.Uint16Attr(Flavour))) + + req.AddData(nl.NewRtAttr(nl.DEVLINK_ATTR_PORT_PCI_PF_NUMBER, nl.Uint16Attr(Attrs.PfNumber))) + if Flavour == nl.DEVLINK_PORT_FLAVOUR_PCI_SF && Attrs.SfNumberValid { + req.AddData(nl.NewRtAttr(nl.DEVLINK_ATTR_PORT_PCI_SF_NUMBER, nl.Uint32Attr(Attrs.SfNumber))) + } + if Attrs.PortIndexValid { + req.AddData(nl.NewRtAttr(nl.DEVLINK_ATTR_PORT_INDEX, nl.Uint32Attr(Attrs.PortIndex))) + } + if Attrs.ControllerValid { + req.AddData(nl.NewRtAttr(nl.DEVLINK_ATTR_PORT_CONTROLLER_NUMBER, nl.Uint32Attr(Attrs.Controller))) + } + respmsg, err := req.Execute(unix.NETLINK_GENERIC, 0) + if err != nil { + return nil, err + } + port, err := parseDevlinkPortMsg(respmsg) + return port, err +} + +// DevLinkPortAdd adds a devlink port and returns a port on success +// otherwise returns nil port and an error code. +func DevLinkPortAdd(Bus string, Device string, Flavour uint16, Attrs DevLinkPortAddAttrs) (*DevlinkPort, error) { + return pkgHandle.DevLinkPortAdd(Bus, Device, Flavour, Attrs) +} + +// DevLinkPortDel deletes a devlink port and returns success or error code. +func (h *Handle) DevLinkPortDel(Bus string, Device string, PortIndex uint32) error { + _, req, err := h.createCmdReq(nl.DEVLINK_CMD_PORT_DEL, Bus, Device) + if err != nil { + return err + } + + req.AddData(nl.NewRtAttr(nl.DEVLINK_ATTR_PORT_INDEX, nl.Uint32Attr(PortIndex))) + _, err = req.Execute(unix.NETLINK_GENERIC, 0) + return err +} + +// DevLinkPortDel deletes a devlink port and returns success or error code. +func DevLinkPortDel(Bus string, Device string, PortIndex uint32) error { + return pkgHandle.DevLinkPortDel(Bus, Device, PortIndex) +} + +// DevlinkPortFnSet sets one or more port function attributes specified by the attribute mask. +// It returns 0 on success or error code. +func (h *Handle) DevlinkPortFnSet(Bus string, Device string, PortIndex uint32, FnAttrs DevlinkPortFnSetAttrs) error { + _, req, err := h.createCmdReq(nl.DEVLINK_CMD_PORT_SET, Bus, Device) + if err != nil { + return err + } + + req.AddData(nl.NewRtAttr(nl.DEVLINK_ATTR_PORT_INDEX, nl.Uint32Attr(PortIndex))) + + fnAttr := nl.NewRtAttr(nl.DEVLINK_ATTR_PORT_FUNCTION|unix.NLA_F_NESTED, nil) + + if FnAttrs.HwAddrValid { + fnAttr.AddRtAttr(nl.DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR, []byte(FnAttrs.FnAttrs.HwAddr)) + } + + if FnAttrs.StateValid { + fnAttr.AddRtAttr(nl.DEVLINK_PORT_FN_ATTR_STATE, nl.Uint8Attr(FnAttrs.FnAttrs.State)) + } + req.AddData(fnAttr) + + _, err = req.Execute(unix.NETLINK_GENERIC, 0) + return err +} + +// DevlinkPortFnSet sets one or more port function attributes specified by the attribute mask. +// It returns 0 on success or error code. +func DevlinkPortFnSet(Bus string, Device string, PortIndex uint32, FnAttrs DevlinkPortFnSetAttrs) error { + return pkgHandle.DevlinkPortFnSet(Bus, Device, PortIndex, FnAttrs) +} + +// devlinkInfoGetter is function that is responsible for getting devlink info message +// this is introduced for test purpose +type devlinkInfoGetter func(bus, device string) ([]byte, error) + +// DevlinkGetDeviceInfoByName returns devlink info for selected device, +// otherwise returns an error code. +// Equivalent to: `devlink dev info $dev` +func (h *Handle) DevlinkGetDeviceInfoByName(Bus string, Device string, getInfoMsg devlinkInfoGetter) (*DevlinkDeviceInfo, error) { + info, err := h.DevlinkGetDeviceInfoByNameAsMap(Bus, Device, getInfoMsg) + if err != nil { + return nil, err + } + + return parseInfoData(info), nil +} + +// DevlinkGetDeviceInfoByName returns devlink info for selected device, +// otherwise returns an error code. +// Equivalent to: `devlink dev info $dev` +func DevlinkGetDeviceInfoByName(Bus string, Device string) (*DevlinkDeviceInfo, error) { + return pkgHandle.DevlinkGetDeviceInfoByName(Bus, Device, pkgHandle.getDevlinkInfoMsg) +} + +// DevlinkGetDeviceInfoByNameAsMap returns devlink info for selected device as a map, +// otherwise returns an error code. +// Equivalent to: `devlink dev info $dev` +func (h *Handle) DevlinkGetDeviceInfoByNameAsMap(Bus string, Device string, getInfoMsg devlinkInfoGetter) (map[string]string, error) { + response, err := getInfoMsg(Bus, Device) + if err != nil { + return nil, err + } + + info, err := parseInfoMsg(response) + if err != nil { + return nil, err + } + + return info, nil +} + +// DevlinkGetDeviceInfoByNameAsMap returns devlink info for selected device as a map, +// otherwise returns an error code. +// Equivalent to: `devlink dev info $dev` +func DevlinkGetDeviceInfoByNameAsMap(Bus string, Device string) (map[string]string, error) { + return pkgHandle.DevlinkGetDeviceInfoByNameAsMap(Bus, Device, pkgHandle.getDevlinkInfoMsg) +} + +// GetDevlinkInfo returns devlink info for target device, +// otherwise returns an error code. +func (d *DevlinkDevice) GetDevlinkInfo() (*DevlinkDeviceInfo, error) { + return pkgHandle.DevlinkGetDeviceInfoByName(d.BusName, d.DeviceName, pkgHandle.getDevlinkInfoMsg) +} + +// GetDevlinkInfoAsMap returns devlink info for target device as a map, +// otherwise returns an error code. +func (d *DevlinkDevice) GetDevlinkInfoAsMap() (map[string]string, error) { + return pkgHandle.DevlinkGetDeviceInfoByNameAsMap(d.BusName, d.DeviceName, pkgHandle.getDevlinkInfoMsg) +} + +func (h *Handle) getDevlinkInfoMsg(bus, device string) ([]byte, error) { + _, req, err := h.createCmdReq(nl.DEVLINK_CMD_INFO_GET, bus, device) + if err != nil { + return nil, err + } + + response, err := req.Execute(unix.NETLINK_GENERIC, 0) + if err != nil { + return nil, err + } + + if len(response) < 1 { + return nil, fmt.Errorf("getDevlinkInfoMsg: message too short") + } + + return response[0], nil +} + +func parseInfoMsg(msg []byte) (map[string]string, error) { + if len(msg) < nl.SizeofGenlmsg { + return nil, fmt.Errorf("parseInfoMsg: message too short") + } + + info := make(map[string]string) + err := collectInfoData(msg[nl.SizeofGenlmsg:], info) + + if err != nil { + return nil, err + } + + return info, nil +} + +func collectInfoData(msg []byte, data map[string]string) error { + attrs, err := nl.ParseRouteAttr(msg) + if err != nil { + return err + } + + for _, attr := range attrs { + switch attr.Attr.Type { + case nl.DEVLINK_ATTR_INFO_DRIVER_NAME: + data["driver"] = parseInfoValue(attr.Value) + case nl.DEVLINK_ATTR_INFO_SERIAL_NUMBER: + data["serialNumber"] = parseInfoValue(attr.Value) + case nl.DEVLINK_ATTR_INFO_VERSION_RUNNING, nl.DEVLINK_ATTR_INFO_VERSION_FIXED, + nl.DEVLINK_ATTR_INFO_VERSION_STORED: + key, value, err := getNestedInfoData(attr.Value) + if err != nil { + return err + } + data[key] = value + } + } + + if len(data) == 0 { + return fmt.Errorf("collectInfoData: could not read attributes") + } + + return nil +} + +func getNestedInfoData(msg []byte) (string, string, error) { + nestedAttrs, err := nl.ParseRouteAttr(msg) + + var key, value string + + if err != nil { + return "", "", err + } + + if len(nestedAttrs) != 2 { + return "", "", fmt.Errorf("getNestedInfoData: too few attributes in nested structure") + } + + for _, nestedAttr := range nestedAttrs { + switch nestedAttr.Attr.Type { + case nl.DEVLINK_ATTR_INFO_VERSION_NAME: + key = parseInfoValue(nestedAttr.Value) + case nl.DEVLINK_ATTR_INFO_VERSION_VALUE: + value = parseInfoValue(nestedAttr.Value) + } + } + + if key == "" { + return "", "", fmt.Errorf("getNestedInfoData: key not found") + } + + if value == "" { + return "", "", fmt.Errorf("getNestedInfoData: value not found") + } + + return key, value, nil +} + +func parseInfoData(data map[string]string) *DevlinkDeviceInfo { + info := new(DevlinkDeviceInfo) + for key, value := range data { + switch key { + case "driver": + info.Driver = value + case "serialNumber": + info.SerialNumber = value + case "board.id": + info.BoardID = value + case "fw.app": + info.FwApp = value + case "fw.app.bundle_id": + info.FwAppBoundleID = value + case "fw.app.name": + info.FwAppName = value + case "fw.bundle_id": + info.FwBoundleID = value + case "fw.mgmt": + info.FwMgmt = value + case "fw.mgmt.api": + info.FwMgmtAPI = value + case "fw.mgmt.build": + info.FwMgmtBuild = value + case "fw.netlist": + info.FwNetlist = value + case "fw.netlist.build": + info.FwNetlistBuild = value + case "fw.psid.api": + info.FwPsidAPI = value + case "fw.undi": + info.FwUndi = value + } + } + return info +} + +func parseInfoValue(value []byte) string { + v := strings.ReplaceAll(string(value), "\x00", "") + return strings.TrimSpace(v) +} diff --git a/vendor/github.com/vishvananda/netlink/filter.go b/vendor/github.com/vishvananda/netlink/filter.go index 88792eab0..84e1ca7a4 100644 --- a/vendor/github.com/vishvananda/netlink/filter.go +++ b/vendor/github.com/vishvananda/netlink/filter.go @@ -19,6 +19,7 @@ type FilterAttrs struct { Parent uint32 Priority uint16 // lower is higher priority Protocol uint16 // unix.ETH_P_* + Chain *uint32 } func (q FilterAttrs) String() string { @@ -27,6 +28,11 @@ func (q FilterAttrs) String() string { type TcAct int32 +const ( + TC_ACT_EXT_SHIFT = 28 + TC_ACT_EXT_VAL_MASK = (1 << TC_ACT_EXT_SHIFT) - 1 +) + const ( TC_ACT_UNSPEC TcAct = -1 TC_ACT_OK TcAct = 0 @@ -40,6 +46,22 @@ const ( TC_ACT_JUMP TcAct = 0x10000000 ) +func getTcActExt(local int32) int32 { + return local << TC_ACT_EXT_SHIFT +} + +func getTcActGotoChain() TcAct { + return TcAct(getTcActExt(2)) +} + +func getTcActExtOpcode(combined int32) int32 { + return combined & (^TC_ACT_EXT_VAL_MASK) +} + +func TcActExtCmp(combined int32, opcode int32) bool { + return getTcActExtOpcode(combined) == opcode +} + func (a TcAct) String() string { switch a { case TC_ACT_UNSPEC: @@ -63,6 +85,9 @@ func (a TcAct) String() string { case TC_ACT_JUMP: return "jump" } + if TcActExtCmp(int32(a), int32(getTcActGotoChain())) { + return "goto" + } return fmt.Sprintf("0x%x", int32(a)) } @@ -93,17 +118,32 @@ func (a TcPolAct) String() string { } type ActionAttrs struct { - Index int - Capab int - Action TcAct - Refcnt int - Bindcnt int + Index int + Capab int + Action TcAct + Refcnt int + Bindcnt int + Statistics *ActionStatistic + Timestamp *ActionTimestamp } func (q ActionAttrs) String() string { return fmt.Sprintf("{Index: %d, Capab: %x, Action: %s, Refcnt: %d, Bindcnt: %d}", q.Index, q.Capab, q.Action.String(), q.Refcnt, q.Bindcnt) } +type ActionTimestamp struct { + Installed uint64 + LastUsed uint64 + Expires uint64 + FirstUsed uint64 +} + +func (t ActionTimestamp) String() string { + return fmt.Sprintf("Installed %d LastUsed %d Expires %d FirstUsed %d", t.Installed, t.LastUsed, t.Expires, t.FirstUsed) +} + +type ActionStatistic ClassStatistics + // Action represents an action in any supported filter. type Action interface { Attrs() *ActionAttrs @@ -112,6 +152,7 @@ type Action interface { type GenericAction struct { ActionAttrs + Chain int32 } func (action *GenericAction) Type() string { @@ -157,6 +198,39 @@ func NewConnmarkAction() *ConnmarkAction { } } +type CsumUpdateFlags uint32 + +const ( + TCA_CSUM_UPDATE_FLAG_IPV4HDR CsumUpdateFlags = 1 + TCA_CSUM_UPDATE_FLAG_ICMP CsumUpdateFlags = 2 + TCA_CSUM_UPDATE_FLAG_IGMP CsumUpdateFlags = 4 + TCA_CSUM_UPDATE_FLAG_TCP CsumUpdateFlags = 8 + TCA_CSUM_UPDATE_FLAG_UDP CsumUpdateFlags = 16 + TCA_CSUM_UPDATE_FLAG_UDPLITE CsumUpdateFlags = 32 + TCA_CSUM_UPDATE_FLAG_SCTP CsumUpdateFlags = 64 +) + +type CsumAction struct { + ActionAttrs + UpdateFlags CsumUpdateFlags +} + +func (action *CsumAction) Type() string { + return "csum" +} + +func (action *CsumAction) Attrs() *ActionAttrs { + return &action.ActionAttrs +} + +func NewCsumAction() *CsumAction { + return &CsumAction{ + ActionAttrs: ActionAttrs{ + Action: TC_ACT_PIPE, + }, + } +} + type MirredAct uint8 func (a MirredAct) String() string { @@ -213,10 +287,11 @@ const ( type TunnelKeyAction struct { ActionAttrs - Action TunnelKeyAct - SrcAddr net.IP - DstAddr net.IP - KeyID uint32 + Action TunnelKeyAct + SrcAddr net.IP + DstAddr net.IP + KeyID uint32 + DestPort uint16 } func (action *TunnelKeyAction) Type() string { @@ -241,6 +316,7 @@ type SkbEditAction struct { PType *uint16 Priority *uint32 Mark *uint32 + Mask *uint32 } func (action *SkbEditAction) Type() string { @@ -259,6 +335,40 @@ func NewSkbEditAction() *SkbEditAction { } } +type PoliceAction struct { + ActionAttrs + Rate uint32 // in byte per second + Burst uint32 // in byte + RCellLog int + Mtu uint32 + Mpu uint16 // in byte + PeakRate uint32 // in byte per second + PCellLog int + AvRate uint32 // in byte per second + Overhead uint16 + LinkLayer int + ExceedAction TcPolAct + NotExceedAction TcPolAct +} + +func (action *PoliceAction) Type() string { + return "police" +} + +func (action *PoliceAction) Attrs() *ActionAttrs { + return &action.ActionAttrs +} + +func NewPoliceAction() *PoliceAction { + return &PoliceAction{ + RCellLog: -1, + PCellLog: -1, + LinkLayer: 1, // ETHERNET + ExceedAction: TC_POLICE_RECLASSIFY, + NotExceedAction: TC_POLICE_OK, + } +} + // MatchAll filters match all packets type MatchAll struct { FilterAttrs @@ -274,20 +384,21 @@ func (filter *MatchAll) Type() string { return "matchall" } -type FilterFwAttrs struct { - ClassId uint32 - InDev string - Mask uint32 - Index uint32 - Buffer uint32 - Mtu uint32 - Mpu uint16 - Rate uint32 - AvRate uint32 - PeakRate uint32 - Action TcPolAct - Overhead uint16 - LinkLayer int +type FwFilter struct { + FilterAttrs + ClassId uint32 + InDev string + Mask uint32 + Police *PoliceAction + Actions []Action +} + +func (filter *FwFilter) Attrs() *FilterAttrs { + return &filter.FilterAttrs +} + +func (filter *FwFilter) Type() string { + return "fw" } type BpfFilter struct { @@ -322,3 +433,30 @@ func (filter *GenericFilter) Attrs() *FilterAttrs { func (filter *GenericFilter) Type() string { return filter.FilterType } + +type PeditAction struct { + ActionAttrs + Proto uint8 + SrcMacAddr net.HardwareAddr + DstMacAddr net.HardwareAddr + SrcIP net.IP + DstIP net.IP + SrcPort uint16 + DstPort uint16 +} + +func (p *PeditAction) Attrs() *ActionAttrs { + return &p.ActionAttrs +} + +func (p *PeditAction) Type() string { + return "pedit" +} + +func NewPeditAction() *PeditAction { + return &PeditAction{ + ActionAttrs: ActionAttrs{ + Action: TC_ACT_PIPE, + }, + } +} diff --git a/vendor/github.com/vishvananda/netlink/filter_linux.go b/vendor/github.com/vishvananda/netlink/filter_linux.go index c56f314cd..87cd18f8e 100644 --- a/vendor/github.com/vishvananda/netlink/filter_linux.go +++ b/vendor/github.com/vishvananda/netlink/filter_linux.go @@ -37,9 +37,11 @@ type U32 struct { ClassId uint32 Divisor uint32 // Divisor MUST be power of 2. Hash uint32 + Link uint32 RedirIndex int Sel *TcU32Sel Actions []Action + Police *PoliceAction } func (filter *U32) Attrs() *FilterAttrs { @@ -50,74 +52,185 @@ func (filter *U32) Type() string { return "u32" } -// Fw filter filters on firewall marks -// NOTE: this is in filter_linux because it refers to nl.TcPolice which -// is defined in nl/tc_linux.go -type Fw struct { +type Flower struct { FilterAttrs - ClassId uint32 - // TODO remove nl type from interface - Police nl.TcPolice - InDev string - // TODO Action - Mask uint32 - AvRate uint32 - Rtab [256]uint32 - Ptab [256]uint32 -} - -func NewFw(attrs FilterAttrs, fattrs FilterFwAttrs) (*Fw, error) { - var rtab [256]uint32 - var ptab [256]uint32 - rcellLog := -1 - pcellLog := -1 - avrate := fattrs.AvRate / 8 - police := nl.TcPolice{} - police.Rate.Rate = fattrs.Rate / 8 - police.PeakRate.Rate = fattrs.PeakRate / 8 - buffer := fattrs.Buffer - linklayer := nl.LINKLAYER_ETHERNET + DestIP net.IP + DestIPMask net.IPMask + SrcIP net.IP + SrcIPMask net.IPMask + EthType uint16 + EncDestIP net.IP + EncDestIPMask net.IPMask + EncSrcIP net.IP + EncSrcIPMask net.IPMask + EncDestPort uint16 + EncKeyId uint32 + SkipHw bool + SkipSw bool + IPProto *nl.IPProto + DestPort uint16 + SrcPort uint16 - if fattrs.LinkLayer != nl.LINKLAYER_UNSPEC { - linklayer = fattrs.LinkLayer - } + Actions []Action +} - police.Action = int32(fattrs.Action) - if police.Rate.Rate != 0 { - police.Rate.Mpu = fattrs.Mpu - police.Rate.Overhead = fattrs.Overhead - if CalcRtable(&police.Rate, rtab[:], rcellLog, fattrs.Mtu, linklayer) < 0 { - return nil, errors.New("TBF: failed to calculate rate table") - } - police.Burst = uint32(Xmittime(uint64(police.Rate.Rate), uint32(buffer))) +func (filter *Flower) Attrs() *FilterAttrs { + return &filter.FilterAttrs +} + +func (filter *Flower) Type() string { + return "flower" +} + +func (filter *Flower) encodeIP(parent *nl.RtAttr, ip net.IP, mask net.IPMask, v4Type, v6Type int, v4MaskType, v6MaskType int) { + ipType := v4Type + maskType := v4MaskType + + encodeMask := mask + if mask == nil { + encodeMask = net.CIDRMask(32, 32) } - police.Mtu = fattrs.Mtu - if police.PeakRate.Rate != 0 { - police.PeakRate.Mpu = fattrs.Mpu - police.PeakRate.Overhead = fattrs.Overhead - if CalcRtable(&police.PeakRate, ptab[:], pcellLog, fattrs.Mtu, linklayer) < 0 { - return nil, errors.New("POLICE: failed to calculate peak rate table") + v4IP := ip.To4() + if v4IP == nil { + ipType = v6Type + maskType = v6MaskType + if mask == nil { + encodeMask = net.CIDRMask(128, 128) } + } else { + ip = v4IP } - return &Fw{ - FilterAttrs: attrs, - ClassId: fattrs.ClassId, - InDev: fattrs.InDev, - Mask: fattrs.Mask, - Police: police, - AvRate: avrate, - Rtab: rtab, - Ptab: ptab, - }, nil + parent.AddRtAttr(ipType, ip) + parent.AddRtAttr(maskType, encodeMask) } -func (filter *Fw) Attrs() *FilterAttrs { - return &filter.FilterAttrs +func (filter *Flower) encode(parent *nl.RtAttr) error { + if filter.EthType != 0 { + parent.AddRtAttr(nl.TCA_FLOWER_KEY_ETH_TYPE, htons(filter.EthType)) + } + if filter.SrcIP != nil { + filter.encodeIP(parent, filter.SrcIP, filter.SrcIPMask, + nl.TCA_FLOWER_KEY_IPV4_SRC, nl.TCA_FLOWER_KEY_IPV6_SRC, + nl.TCA_FLOWER_KEY_IPV4_SRC_MASK, nl.TCA_FLOWER_KEY_IPV6_SRC_MASK) + } + if filter.DestIP != nil { + filter.encodeIP(parent, filter.DestIP, filter.DestIPMask, + nl.TCA_FLOWER_KEY_IPV4_DST, nl.TCA_FLOWER_KEY_IPV6_DST, + nl.TCA_FLOWER_KEY_IPV4_DST_MASK, nl.TCA_FLOWER_KEY_IPV6_DST_MASK) + } + if filter.EncSrcIP != nil { + filter.encodeIP(parent, filter.EncSrcIP, filter.EncSrcIPMask, + nl.TCA_FLOWER_KEY_ENC_IPV4_SRC, nl.TCA_FLOWER_KEY_ENC_IPV6_SRC, + nl.TCA_FLOWER_KEY_ENC_IPV4_SRC_MASK, nl.TCA_FLOWER_KEY_ENC_IPV6_SRC_MASK) + } + if filter.EncDestIP != nil { + filter.encodeIP(parent, filter.EncDestIP, filter.EncSrcIPMask, + nl.TCA_FLOWER_KEY_ENC_IPV4_DST, nl.TCA_FLOWER_KEY_ENC_IPV6_DST, + nl.TCA_FLOWER_KEY_ENC_IPV4_DST_MASK, nl.TCA_FLOWER_KEY_ENC_IPV6_DST_MASK) + } + if filter.EncDestPort != 0 { + parent.AddRtAttr(nl.TCA_FLOWER_KEY_ENC_UDP_DST_PORT, htons(filter.EncDestPort)) + } + if filter.EncKeyId != 0 { + parent.AddRtAttr(nl.TCA_FLOWER_KEY_ENC_KEY_ID, htonl(filter.EncKeyId)) + } + if filter.IPProto != nil { + ipproto := *filter.IPProto + parent.AddRtAttr(nl.TCA_FLOWER_KEY_IP_PROTO, ipproto.Serialize()) + if filter.SrcPort != 0 { + switch ipproto { + case nl.IPPROTO_TCP: + parent.AddRtAttr(nl.TCA_FLOWER_KEY_TCP_SRC, htons(filter.SrcPort)) + case nl.IPPROTO_UDP: + parent.AddRtAttr(nl.TCA_FLOWER_KEY_UDP_SRC, htons(filter.SrcPort)) + case nl.IPPROTO_SCTP: + parent.AddRtAttr(nl.TCA_FLOWER_KEY_SCTP_SRC, htons(filter.SrcPort)) + } + } + if filter.DestPort != 0 { + switch ipproto { + case nl.IPPROTO_TCP: + parent.AddRtAttr(nl.TCA_FLOWER_KEY_TCP_DST, htons(filter.DestPort)) + case nl.IPPROTO_UDP: + parent.AddRtAttr(nl.TCA_FLOWER_KEY_UDP_DST, htons(filter.DestPort)) + case nl.IPPROTO_SCTP: + parent.AddRtAttr(nl.TCA_FLOWER_KEY_SCTP_DST, htons(filter.DestPort)) + } + } + } + + var flags uint32 = 0 + if filter.SkipHw { + flags |= nl.TCA_CLS_FLAGS_SKIP_HW + } + if filter.SkipSw { + flags |= nl.TCA_CLS_FLAGS_SKIP_SW + } + parent.AddRtAttr(nl.TCA_FLOWER_FLAGS, htonl(flags)) + + actionsAttr := parent.AddRtAttr(nl.TCA_FLOWER_ACT, nil) + if err := EncodeActions(actionsAttr, filter.Actions); err != nil { + return err + } + return nil } -func (filter *Fw) Type() string { - return "fw" +func (filter *Flower) decode(data []syscall.NetlinkRouteAttr) error { + for _, datum := range data { + switch datum.Attr.Type { + case nl.TCA_FLOWER_KEY_ETH_TYPE: + filter.EthType = ntohs(datum.Value) + case nl.TCA_FLOWER_KEY_IPV4_SRC, nl.TCA_FLOWER_KEY_IPV6_SRC: + filter.SrcIP = datum.Value + case nl.TCA_FLOWER_KEY_IPV4_SRC_MASK, nl.TCA_FLOWER_KEY_IPV6_SRC_MASK: + filter.SrcIPMask = datum.Value + case nl.TCA_FLOWER_KEY_IPV4_DST, nl.TCA_FLOWER_KEY_IPV6_DST: + filter.DestIP = datum.Value + case nl.TCA_FLOWER_KEY_IPV4_DST_MASK, nl.TCA_FLOWER_KEY_IPV6_DST_MASK: + filter.DestIPMask = datum.Value + case nl.TCA_FLOWER_KEY_ENC_IPV4_SRC, nl.TCA_FLOWER_KEY_ENC_IPV6_SRC: + filter.EncSrcIP = datum.Value + case nl.TCA_FLOWER_KEY_ENC_IPV4_SRC_MASK, nl.TCA_FLOWER_KEY_ENC_IPV6_SRC_MASK: + filter.EncSrcIPMask = datum.Value + case nl.TCA_FLOWER_KEY_ENC_IPV4_DST, nl.TCA_FLOWER_KEY_ENC_IPV6_DST: + filter.EncDestIP = datum.Value + case nl.TCA_FLOWER_KEY_ENC_IPV4_DST_MASK, nl.TCA_FLOWER_KEY_ENC_IPV6_DST_MASK: + filter.EncDestIPMask = datum.Value + case nl.TCA_FLOWER_KEY_ENC_UDP_DST_PORT: + filter.EncDestPort = ntohs(datum.Value) + case nl.TCA_FLOWER_KEY_ENC_KEY_ID: + filter.EncKeyId = ntohl(datum.Value) + case nl.TCA_FLOWER_KEY_IP_PROTO: + val := new(nl.IPProto) + *val = nl.IPProto(datum.Value[0]) + filter.IPProto = val + case nl.TCA_FLOWER_KEY_TCP_SRC, nl.TCA_FLOWER_KEY_UDP_SRC, nl.TCA_FLOWER_KEY_SCTP_SRC: + filter.SrcPort = ntohs(datum.Value) + case nl.TCA_FLOWER_KEY_TCP_DST, nl.TCA_FLOWER_KEY_UDP_DST, nl.TCA_FLOWER_KEY_SCTP_DST: + filter.DestPort = ntohs(datum.Value) + case nl.TCA_FLOWER_ACT: + tables, err := nl.ParseRouteAttr(datum.Value) + if err != nil { + return err + } + filter.Actions, err = parseActions(tables) + if err != nil { + return err + } + case nl.TCA_FLOWER_FLAGS: + attr := nl.DeserializeUint32Bitfield(datum.Value) + skipSw := attr.Value & nl.TCA_CLS_FLAGS_SKIP_HW + skipHw := attr.Value & nl.TCA_CLS_FLAGS_SKIP_SW + if skipSw != 0 { + filter.SkipSw = true + } + if skipHw != 0 { + filter.SkipHw = true + } + } + } + return nil } // FilterDel will delete a filter from the system. @@ -129,19 +242,7 @@ func FilterDel(filter Filter) error { // FilterDel will delete a filter from the system. // Equivalent to: `tc filter del $filter` func (h *Handle) FilterDel(filter Filter) error { - req := h.newNetlinkRequest(unix.RTM_DELTFILTER, unix.NLM_F_ACK) - base := filter.Attrs() - msg := &nl.TcMsg{ - Family: nl.FAMILY_ALL, - Ifindex: int32(base.LinkIndex), - Handle: base.Handle, - Parent: base.Parent, - Info: MakeHandle(base.Priority, nl.Swap16(base.Protocol)), - } - req.AddData(msg) - - _, err := req.Execute(unix.NETLINK_ROUTE, 0) - return err + return h.filterModify(filter, unix.RTM_DELTFILTER, 0) } // FilterAdd will add a filter to the system. @@ -153,7 +254,7 @@ func FilterAdd(filter Filter) error { // FilterAdd will add a filter to the system. // Equivalent to: `tc filter add $filter` func (h *Handle) FilterAdd(filter Filter) error { - return h.filterModify(filter, unix.NLM_F_CREATE|unix.NLM_F_EXCL) + return h.filterModify(filter, unix.RTM_NEWTFILTER, unix.NLM_F_CREATE|unix.NLM_F_EXCL) } // FilterReplace will replace a filter. @@ -165,12 +266,11 @@ func FilterReplace(filter Filter) error { // FilterReplace will replace a filter. // Equivalent to: `tc filter replace $filter` func (h *Handle) FilterReplace(filter Filter) error { - return h.filterModify(filter, unix.NLM_F_CREATE) + return h.filterModify(filter, unix.RTM_NEWTFILTER, unix.NLM_F_CREATE) } -func (h *Handle) filterModify(filter Filter, flags int) error { - native = nl.NativeEndian() - req := h.newNetlinkRequest(unix.RTM_NEWTFILTER, flags|unix.NLM_F_ACK) +func (h *Handle) filterModify(filter Filter, proto, flags int) error { + req := h.newNetlinkRequest(proto, flags|unix.NLM_F_ACK) base := filter.Attrs() msg := &nl.TcMsg{ Family: nl.FAMILY_ALL, @@ -180,6 +280,9 @@ func (h *Handle) filterModify(filter Filter, flags int) error { Info: MakeHandle(base.Priority, nl.Swap16(base.Protocol)), } req.AddData(msg) + if filter.Attrs().Chain != nil { + req.AddData(nl.NewRtAttr(nl.TCA_CHAIN, nl.Uint32Attr(*filter.Attrs().Chain))) + } req.AddData(nl.NewRtAttr(nl.TCA_KIND, nl.ZeroTerminated(filter.Type()))) options := nl.NewRtAttr(nl.TCA_OPTIONS, nil) @@ -226,6 +329,15 @@ func (h *Handle) filterModify(filter Filter, flags int) error { if filter.Hash != 0 { options.AddRtAttr(nl.TCA_U32_HASH, nl.Uint32Attr(filter.Hash)) } + if filter.Link != 0 { + options.AddRtAttr(nl.TCA_U32_LINK, nl.Uint32Attr(filter.Link)) + } + if filter.Police != nil { + police := options.AddRtAttr(nl.TCA_U32_POLICE, nil) + if err := encodePolice(police, filter.Police); err != nil { + return err + } + } actionsAttr := options.AddRtAttr(nl.TCA_U32_ACT, nil) // backwards compatibility if filter.RedirIndex != 0 { @@ -234,7 +346,7 @@ func (h *Handle) filterModify(filter Filter, flags int) error { if err := EncodeActions(actionsAttr, filter.Actions); err != nil { return err } - case *Fw: + case *FwFilter: if filter.Mask != 0 { b := make([]byte, 4) native.PutUint32(b, filter.Mask) @@ -243,17 +355,10 @@ func (h *Handle) filterModify(filter Filter, flags int) error { if filter.InDev != "" { options.AddRtAttr(nl.TCA_FW_INDEV, nl.ZeroTerminated(filter.InDev)) } - if (filter.Police != nl.TcPolice{}) { - + if filter.Police != nil { police := options.AddRtAttr(nl.TCA_FW_POLICE, nil) - police.AddRtAttr(nl.TCA_POLICE_TBF, filter.Police.Serialize()) - if (filter.Police.Rate != nl.TcRateSpec{}) { - payload := SerializeRtab(filter.Rtab) - police.AddRtAttr(nl.TCA_POLICE_RATE, payload) - } - if (filter.Police.PeakRate != nl.TcRateSpec{}) { - payload := SerializeRtab(filter.Ptab) - police.AddRtAttr(nl.TCA_POLICE_PEAKRATE, payload) + if err := encodePolice(police, filter.Police); err != nil { + return err } } if filter.ClassId != 0 { @@ -261,6 +366,10 @@ func (h *Handle) filterModify(filter Filter, flags int) error { native.PutUint32(b, filter.ClassId) options.AddRtAttr(nl.TCA_FW_CLASSID, b) } + actionsAttr := options.AddRtAttr(nl.TCA_FW_ACT, nil) + if err := EncodeActions(actionsAttr, filter.Actions); err != nil { + return err + } case *BpfFilter: var bpfFlags uint32 if filter.ClassId != 0 { @@ -284,8 +393,11 @@ func (h *Handle) filterModify(filter Filter, flags int) error { if filter.ClassId != 0 { options.AddRtAttr(nl.TCA_MATCHALL_CLASSID, nl.Uint32Attr(filter.ClassId)) } + case *Flower: + if err := filter.encode(options); err != nil { + return err + } } - req.AddData(options) _, err := req.Execute(unix.NETLINK_ROUTE, 0) return err @@ -347,11 +459,13 @@ func (h *Handle) FilterList(link Link, parent uint32) ([]Filter, error) { case "u32": filter = &U32{} case "fw": - filter = &Fw{} + filter = &FwFilter{} case "bpf": filter = &BpfFilter{} case "matchall": filter = &MatchAll{} + case "flower": + filter = &Flower{} default: filter = &GenericFilter{FilterType: filterType} } @@ -381,9 +495,18 @@ func (h *Handle) FilterList(link Link, parent uint32) ([]Filter, error) { if err != nil { return nil, err } + case "flower": + detailed, err = parseFlowerData(filter, data) + if err != nil { + return nil, err + } default: detailed = true } + case nl.TCA_CHAIN: + val := new(uint32) + *val = native.Uint32(attr.Value) + base.Chain = val } } // only return the detailed version of the filter @@ -412,6 +535,61 @@ func toAttrs(tcgen *nl.TcGen, attrs *ActionAttrs) { attrs.Bindcnt = int(tcgen.Bindcnt) } +func toTimeStamp(tcf *nl.Tcf) *ActionTimestamp { + return &ActionTimestamp{ + Installed: tcf.Install, + LastUsed: tcf.LastUse, + Expires: tcf.Expires, + FirstUsed: tcf.FirstUse} +} + +func encodePolice(attr *nl.RtAttr, action *PoliceAction) error { + var rtab [256]uint32 + var ptab [256]uint32 + police := nl.TcPolice{} + police.Index = uint32(action.Attrs().Index) + police.Bindcnt = int32(action.Attrs().Bindcnt) + police.Capab = uint32(action.Attrs().Capab) + police.Refcnt = int32(action.Attrs().Refcnt) + police.Rate.Rate = action.Rate + police.PeakRate.Rate = action.PeakRate + police.Action = int32(action.ExceedAction) + + if police.Rate.Rate != 0 { + police.Rate.Mpu = action.Mpu + police.Rate.Overhead = action.Overhead + if CalcRtable(&police.Rate, rtab[:], action.RCellLog, action.Mtu, action.LinkLayer) < 0 { + return errors.New("TBF: failed to calculate rate table") + } + police.Burst = Xmittime(uint64(police.Rate.Rate), action.Burst) + } + + police.Mtu = action.Mtu + if police.PeakRate.Rate != 0 { + police.PeakRate.Mpu = action.Mpu + police.PeakRate.Overhead = action.Overhead + if CalcRtable(&police.PeakRate, ptab[:], action.PCellLog, action.Mtu, action.LinkLayer) < 0 { + return errors.New("POLICE: failed to calculate peak rate table") + } + } + + attr.AddRtAttr(nl.TCA_POLICE_TBF, police.Serialize()) + if police.Rate.Rate != 0 { + attr.AddRtAttr(nl.TCA_POLICE_RATE, SerializeRtab(rtab)) + } + if police.PeakRate.Rate != 0 { + attr.AddRtAttr(nl.TCA_POLICE_PEAKRATE, SerializeRtab(ptab)) + } + if action.AvRate != 0 { + attr.AddRtAttr(nl.TCA_POLICE_AVRATE, nl.Uint32Attr(action.AvRate)) + } + if action.NotExceedAction != 0 { + attr.AddRtAttr(nl.TCA_POLICE_RESULT, nl.Uint32Attr(uint32(action.NotExceedAction))) + } + + return nil +} + func EncodeActions(attr *nl.RtAttr, actions []Action) error { tabIndex := int(nl.TCA_ACT_TAB) @@ -419,6 +597,14 @@ func EncodeActions(attr *nl.RtAttr, actions []Action) error { switch action := action.(type) { default: return fmt.Errorf("unknown action type %s", action.Type()) + case *PoliceAction: + table := attr.AddRtAttr(tabIndex, nil) + tabIndex++ + table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("police")) + aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil) + if err := encodePolice(aopts, action); err != nil { + return err + } case *MirredAction: table := attr.AddRtAttr(tabIndex, nil) tabIndex++ @@ -456,6 +642,9 @@ func EncodeActions(attr *nl.RtAttr, actions []Action) error { } else { return fmt.Errorf("invalid dst addr %s for tunnel_key action", action.DstAddr) } + if action.DestPort != 0 { + aopts.AddRtAttr(nl.TCA_TUNNEL_KEY_ENC_DST_PORT, htons(action.DestPort)) + } } case *SkbEditAction: table := attr.AddRtAttr(tabIndex, nil) @@ -477,6 +666,9 @@ func EncodeActions(attr *nl.RtAttr, actions []Action) error { if action.Mark != nil { aopts.AddRtAttr(nl.TCA_SKBEDIT_MARK, nl.Uint32Attr(*action.Mark)) } + if action.Mask != nil { + aopts.AddRtAttr(nl.TCA_SKBEDIT_MASK, nl.Uint32Attr(*action.Mask)) + } case *ConnmarkAction: table := attr.AddRtAttr(tabIndex, nil) tabIndex++ @@ -487,6 +679,16 @@ func EncodeActions(attr *nl.RtAttr, actions []Action) error { } toTcGen(action.Attrs(), &connmark.TcGen) aopts.AddRtAttr(nl.TCA_CONNMARK_PARMS, connmark.Serialize()) + case *CsumAction: + table := attr.AddRtAttr(tabIndex, nil) + tabIndex++ + table.AddRtAttr(nl.TCA_ACT_KIND, nl.ZeroTerminated("csum")) + aopts := table.AddRtAttr(nl.TCA_ACT_OPTIONS, nil) + csum := nl.TcCsum{ + UpdateFlags: uint32(action.UpdateFlags), + } + toTcGen(action.Attrs(), &csum.TcGen) + aopts.AddRtAttr(nl.TCA_CSUM_PARMS, csum.Serialize()) case *BpfAction: table := attr.AddRtAttr(tabIndex, nil) tabIndex++ @@ -505,16 +707,64 @@ func EncodeActions(attr *nl.RtAttr, actions []Action) error { gen := nl.TcGen{} toTcGen(action.Attrs(), &gen) aopts.AddRtAttr(nl.TCA_GACT_PARMS, gen.Serialize()) + case *PeditAction: + table := attr.AddRtAttr(tabIndex, nil) + tabIndex++ + pedit := nl.TcPedit{} + if action.SrcMacAddr != nil { + pedit.SetEthSrc(action.SrcMacAddr) + } + if action.DstMacAddr != nil { + pedit.SetEthDst(action.DstMacAddr) + } + if action.SrcIP != nil { + pedit.SetSrcIP(action.SrcIP) + } + if action.DstIP != nil { + pedit.SetDstIP(action.DstIP) + } + if action.SrcPort != 0 { + pedit.SetSrcPort(action.SrcPort, action.Proto) + } + if action.DstPort != 0 { + pedit.SetDstPort(action.DstPort, action.Proto) + } + pedit.Encode(table) } } return nil } +func parsePolice(data syscall.NetlinkRouteAttr, police *PoliceAction) { + switch data.Attr.Type { + case nl.TCA_POLICE_RESULT: + police.NotExceedAction = TcPolAct(native.Uint32(data.Value[0:4])) + case nl.TCA_POLICE_AVRATE: + police.AvRate = native.Uint32(data.Value[0:4]) + case nl.TCA_POLICE_TBF: + p := *nl.DeserializeTcPolice(data.Value) + police.ActionAttrs = ActionAttrs{} + police.Attrs().Index = int(p.Index) + police.Attrs().Bindcnt = int(p.Bindcnt) + police.Attrs().Capab = int(p.Capab) + police.Attrs().Refcnt = int(p.Refcnt) + police.ExceedAction = TcPolAct(p.Action) + police.Rate = p.Rate.Rate + police.PeakRate = p.PeakRate.Rate + police.Burst = Xmitsize(uint64(p.Rate.Rate), p.Burst) + police.Mtu = p.Mtu + police.LinkLayer = int(p.Rate.Linklayer) & nl.TC_LINKLAYER_MASK + police.Overhead = p.Rate.Overhead + } +} + func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) { var actions []Action for _, table := range tables { var action Action var actionType string + var actionnStatistic *ActionStatistic + var actionTimestamp *ActionTimestamp aattrs, err := nl.ParseRouteAttr(table.Value) if err != nil { return nil, err @@ -532,12 +782,18 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) { action = &BpfAction{} case "connmark": action = &ConnmarkAction{} + case "csum": + action = &CsumAction{} case "gact": action = &GenericAction{} case "tunnel_key": action = &TunnelKeyAction{} case "skbedit": action = &SkbEditAction{} + case "police": + action = &PoliceAction{} + case "pedit": + action = &PeditAction{} default: break nextattr } @@ -556,7 +812,11 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) { toAttrs(&mirred.TcGen, action.Attrs()) action.(*MirredAction).Ifindex = int(mirred.Ifindex) action.(*MirredAction).MirredAction = MirredAct(mirred.Eaction) + case nl.TCA_MIRRED_TM: + tcTs := nl.DeserializeTcf(adatum.Value) + actionTimestamp = toTimeStamp(tcTs) } + case "tunnel_key": switch adatum.Attr.Type { case nl.TCA_TUNNEL_KEY_PARMS: @@ -566,12 +826,15 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) { action.(*TunnelKeyAction).Action = TunnelKeyAct(tun.Action) case nl.TCA_TUNNEL_KEY_ENC_KEY_ID: action.(*TunnelKeyAction).KeyID = networkOrder.Uint32(adatum.Value[0:4]) - case nl.TCA_TUNNEL_KEY_ENC_IPV6_SRC: - case nl.TCA_TUNNEL_KEY_ENC_IPV4_SRC: - action.(*TunnelKeyAction).SrcAddr = net.IP(adatum.Value[:]) - case nl.TCA_TUNNEL_KEY_ENC_IPV6_DST: - case nl.TCA_TUNNEL_KEY_ENC_IPV4_DST: - action.(*TunnelKeyAction).DstAddr = net.IP(adatum.Value[:]) + case nl.TCA_TUNNEL_KEY_ENC_IPV6_SRC, nl.TCA_TUNNEL_KEY_ENC_IPV4_SRC: + action.(*TunnelKeyAction).SrcAddr = adatum.Value[:] + case nl.TCA_TUNNEL_KEY_ENC_IPV6_DST, nl.TCA_TUNNEL_KEY_ENC_IPV4_DST: + action.(*TunnelKeyAction).DstAddr = adatum.Value[:] + case nl.TCA_TUNNEL_KEY_ENC_DST_PORT: + action.(*TunnelKeyAction).DestPort = ntohs(adatum.Value) + case nl.TCA_TUNNEL_KEY_TM: + tcTs := nl.DeserializeTcf(adatum.Value) + actionTimestamp = toTimeStamp(tcTs) } case "skbedit": switch adatum.Attr.Type { @@ -582,6 +845,9 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) { case nl.TCA_SKBEDIT_MARK: mark := native.Uint32(adatum.Value[0:4]) action.(*SkbEditAction).Mark = &mark + case nl.TCA_SKBEDIT_MASK: + mask := native.Uint32(adatum.Value[0:4]) + action.(*SkbEditAction).Mask = &mask case nl.TCA_SKBEDIT_PRIORITY: priority := native.Uint32(adatum.Value[0:4]) action.(*SkbEditAction).Priority = &priority @@ -591,6 +857,9 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) { case nl.TCA_SKBEDIT_QUEUE_MAPPING: mapping := native.Uint16(adatum.Value[0:2]) action.(*SkbEditAction).QueueMapping = &mapping + case nl.TCA_SKBEDIT_TM: + tcTs := nl.DeserializeTcf(adatum.Value) + actionTimestamp = toTimeStamp(tcTs) } case "bpf": switch adatum.Attr.Type { @@ -601,6 +870,9 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) { action.(*BpfAction).Fd = int(native.Uint32(adatum.Value[0:4])) case nl.TCA_ACT_BPF_NAME: action.(*BpfAction).Name = string(adatum.Value[:len(adatum.Value)-1]) + case nl.TCA_ACT_BPF_TM: + tcTs := nl.DeserializeTcf(adatum.Value) + actionTimestamp = toTimeStamp(tcTs) } case "connmark": switch adatum.Attr.Type { @@ -609,24 +881,53 @@ func parseActions(tables []syscall.NetlinkRouteAttr) ([]Action, error) { action.(*ConnmarkAction).ActionAttrs = ActionAttrs{} toAttrs(&connmark.TcGen, action.Attrs()) action.(*ConnmarkAction).Zone = connmark.Zone + case nl.TCA_CONNMARK_TM: + tcTs := nl.DeserializeTcf(adatum.Value) + actionTimestamp = toTimeStamp(tcTs) + } + case "csum": + switch adatum.Attr.Type { + case nl.TCA_CSUM_PARMS: + csum := *nl.DeserializeTcCsum(adatum.Value) + action.(*CsumAction).ActionAttrs = ActionAttrs{} + toAttrs(&csum.TcGen, action.Attrs()) + action.(*CsumAction).UpdateFlags = CsumUpdateFlags(csum.UpdateFlags) + case nl.TCA_CSUM_TM: + tcTs := nl.DeserializeTcf(adatum.Value) + actionTimestamp = toTimeStamp(tcTs) } case "gact": switch adatum.Attr.Type { case nl.TCA_GACT_PARMS: gen := *nl.DeserializeTcGen(adatum.Value) toAttrs(&gen, action.Attrs()) + if action.Attrs().Action.String() == "goto" { + action.(*GenericAction).Chain = TC_ACT_EXT_VAL_MASK & gen.Action + } + case nl.TCA_GACT_TM: + tcTs := nl.DeserializeTcf(adatum.Value) + actionTimestamp = toTimeStamp(tcTs) } + case "police": + parsePolice(adatum, action.(*PoliceAction)) } } + case nl.TCA_ACT_STATS: + s, err := parseTcStats2(aattr.Value) + if err != nil { + return nil, err + } + actionnStatistic = (*ActionStatistic)(s) } } + action.Attrs().Statistics = actionnStatistic + action.Attrs().Timestamp = actionTimestamp actions = append(actions, action) } return actions, nil } func parseU32Data(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) { - native = nl.NativeEndian() u32 := filter.(*U32) detailed := false for _, datum := range data { @@ -658,20 +959,28 @@ func parseU32Data(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) u32.RedirIndex = int(action.Ifindex) } } + case nl.TCA_U32_POLICE: + var police PoliceAction + adata, _ := nl.ParseRouteAttr(datum.Value) + for _, aattr := range adata { + parsePolice(aattr, &police) + } + u32.Police = &police case nl.TCA_U32_CLASSID: u32.ClassId = native.Uint32(datum.Value) case nl.TCA_U32_DIVISOR: u32.Divisor = native.Uint32(datum.Value) case nl.TCA_U32_HASH: u32.Hash = native.Uint32(datum.Value) + case nl.TCA_U32_LINK: + u32.Link = native.Uint32(datum.Value) } } return detailed, nil } func parseFwData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) { - native = nl.NativeEndian() - fw := filter.(*Fw) + fw := filter.(*FwFilter) detailed := true for _, datum := range data { switch datum.Attr.Type { @@ -682,16 +991,20 @@ func parseFwData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) { case nl.TCA_FW_INDEV: fw.InDev = string(datum.Value[:len(datum.Value)-1]) case nl.TCA_FW_POLICE: + var police PoliceAction adata, _ := nl.ParseRouteAttr(datum.Value) for _, aattr := range adata { - switch aattr.Attr.Type { - case nl.TCA_POLICE_TBF: - fw.Police = *nl.DeserializeTcPolice(aattr.Value) - case nl.TCA_POLICE_RATE: - fw.Rtab = DeserializeRtab(aattr.Value) - case nl.TCA_POLICE_PEAKRATE: - fw.Ptab = DeserializeRtab(aattr.Value) - } + parsePolice(aattr, &police) + } + fw.Police = &police + case nl.TCA_FW_ACT: + tables, err := nl.ParseRouteAttr(datum.Value) + if err != nil { + return detailed, err + } + fw.Actions, err = parseActions(tables) + if err != nil { + return detailed, err } } } @@ -699,7 +1012,6 @@ func parseFwData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) { } func parseBpfData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) { - native = nl.NativeEndian() bpf := filter.(*BpfFilter) detailed := true for _, datum := range data { @@ -718,14 +1030,13 @@ func parseBpfData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) case nl.TCA_BPF_ID: bpf.Id = int(native.Uint32(datum.Value[0:4])) case nl.TCA_BPF_TAG: - bpf.Tag = hex.EncodeToString(datum.Value[:len(datum.Value)-1]) + bpf.Tag = hex.EncodeToString(datum.Value) } } return detailed, nil } func parseMatchAllData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) { - native = nl.NativeEndian() matchall := filter.(*MatchAll) detailed := true for _, datum := range data { @@ -746,6 +1057,10 @@ func parseMatchAllData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, er return detailed, nil } +func parseFlowerData(filter Filter, data []syscall.NetlinkRouteAttr) (bool, error) { + return true, filter.(*Flower).decode(data) +} + func AlignToAtm(size uint) uint { var linksize, cells int cells = int(size / nl.ATM_CELL_PAYLOAD) @@ -783,7 +1098,7 @@ func CalcRtable(rate *nl.TcRateSpec, rtab []uint32, cellLog int, mtu uint32, lin } for i := 0; i < 256; i++ { sz = AdjustSize(uint((i+1)<= nl.IPSET_ERR_PRIVATE { + err = nl.IPSetError(uintptr(errno)) + } + } + return +} + +func ipsetUnserialize(msgs [][]byte) (result IPSetResult) { + for _, msg := range msgs { + result.unserialize(msg) + } + return result +} + +func (result *IPSetResult) unserialize(msg []byte) { + result.Nfgenmsg = nl.DeserializeNfgenmsg(msg) + + for attr := range nl.ParseAttributes(msg[4:]) { + switch attr.Type { + case nl.IPSET_ATTR_PROTOCOL: + result.Protocol = attr.Value[0] + case nl.IPSET_ATTR_SETNAME: + result.SetName = nl.BytesToString(attr.Value) + case nl.IPSET_ATTR_COMMENT: + result.Comment = nl.BytesToString(attr.Value) + case nl.IPSET_ATTR_TYPENAME: + result.TypeName = nl.BytesToString(attr.Value) + case nl.IPSET_ATTR_REVISION: + result.Revision = attr.Value[0] + case nl.IPSET_ATTR_FAMILY: + result.Family = attr.Value[0] + case nl.IPSET_ATTR_FLAGS: + result.Flags = attr.Value[0] + case nl.IPSET_ATTR_DATA | nl.NLA_F_NESTED: + result.parseAttrData(attr.Value) + case nl.IPSET_ATTR_ADT | nl.NLA_F_NESTED: + result.parseAttrADT(attr.Value) + case nl.IPSET_ATTR_PROTOCOL_MIN: + result.ProtocolMinVersion = attr.Value[0] + case nl.IPSET_ATTR_MARKMASK: + result.MarkMask = attr.Uint32() + default: + log.Printf("unknown ipset attribute from kernel: %+v %v", attr, attr.Type&nl.NLA_TYPE_MASK) + } + } +} + +func (result *IPSetResult) parseAttrData(data []byte) { + for attr := range nl.ParseAttributes(data) { + switch attr.Type { + case nl.IPSET_ATTR_HASHSIZE | nl.NLA_F_NET_BYTEORDER: + result.HashSize = attr.Uint32() + case nl.IPSET_ATTR_MAXELEM | nl.NLA_F_NET_BYTEORDER: + result.MaxElements = attr.Uint32() + case nl.IPSET_ATTR_TIMEOUT | nl.NLA_F_NET_BYTEORDER: + val := attr.Uint32() + result.Timeout = &val + case nl.IPSET_ATTR_ELEMENTS | nl.NLA_F_NET_BYTEORDER: + result.NumEntries = attr.Uint32() + case nl.IPSET_ATTR_REFERENCES | nl.NLA_F_NET_BYTEORDER: + result.References = attr.Uint32() + case nl.IPSET_ATTR_MEMSIZE | nl.NLA_F_NET_BYTEORDER: + result.SizeInMemory = attr.Uint32() + case nl.IPSET_ATTR_CADT_FLAGS | nl.NLA_F_NET_BYTEORDER: + result.CadtFlags = attr.Uint32() + case nl.IPSET_ATTR_IP | nl.NLA_F_NESTED: + for nested := range nl.ParseAttributes(attr.Value) { + switch nested.Type { + case nl.IPSET_ATTR_IP | nl.NLA_F_NET_BYTEORDER: + result.Entries = append(result.Entries, IPSetEntry{IP: nested.Value}) + case nl.IPSET_ATTR_IP: + result.IPFrom = nested.Value + default: + log.Printf("unknown nested ipset data attribute from kernel: %+v %v", nested, nested.Type&nl.NLA_TYPE_MASK) + } + } + case nl.IPSET_ATTR_IP_TO | nl.NLA_F_NESTED: + for nested := range nl.ParseAttributes(attr.Value) { + switch nested.Type { + case nl.IPSET_ATTR_IP: + result.IPTo = nested.Value + default: + log.Printf("unknown nested ipset data attribute from kernel: %+v %v", nested, nested.Type&nl.NLA_TYPE_MASK) + } + } + case nl.IPSET_ATTR_PORT_FROM | nl.NLA_F_NET_BYTEORDER: + result.PortFrom = networkOrder.Uint16(attr.Value) + case nl.IPSET_ATTR_PORT_TO | nl.NLA_F_NET_BYTEORDER: + result.PortTo = networkOrder.Uint16(attr.Value) + case nl.IPSET_ATTR_CADT_LINENO | nl.NLA_F_NET_BYTEORDER: + result.LineNo = attr.Uint32() + case nl.IPSET_ATTR_COMMENT: + result.Comment = nl.BytesToString(attr.Value) + case nl.IPSET_ATTR_MARKMASK: + result.MarkMask = attr.Uint32() + default: + log.Printf("unknown ipset data attribute from kernel: %+v %v", attr, attr.Type&nl.NLA_TYPE_MASK) + } + } +} + +func (result *IPSetResult) parseAttrADT(data []byte) { + for attr := range nl.ParseAttributes(data) { + switch attr.Type { + case nl.IPSET_ATTR_DATA | nl.NLA_F_NESTED: + result.Entries = append(result.Entries, parseIPSetEntry(attr.Value)) + default: + log.Printf("unknown ADT attribute from kernel: %+v %v", attr, attr.Type&nl.NLA_TYPE_MASK) + } + } +} + +func parseIPSetEntry(data []byte) (entry IPSetEntry) { + for attr := range nl.ParseAttributes(data) { + switch attr.Type { + case nl.IPSET_ATTR_TIMEOUT | nl.NLA_F_NET_BYTEORDER: + val := attr.Uint32() + entry.Timeout = &val + case nl.IPSET_ATTR_BYTES | nl.NLA_F_NET_BYTEORDER: + val := attr.Uint64() + entry.Bytes = &val + case nl.IPSET_ATTR_PACKETS | nl.NLA_F_NET_BYTEORDER: + val := attr.Uint64() + entry.Packets = &val + case nl.IPSET_ATTR_ETHER: + entry.MAC = net.HardwareAddr(attr.Value) + case nl.IPSET_ATTR_IP: + entry.IP = net.IP(attr.Value) + case nl.IPSET_ATTR_COMMENT: + entry.Comment = nl.BytesToString(attr.Value) + case nl.IPSET_ATTR_IP | nl.NLA_F_NESTED: + for attr := range nl.ParseAttributes(attr.Value) { + switch attr.Type { + case nl.IPSET_ATTR_IPADDR_IPV4, nl.IPSET_ATTR_IPADDR_IPV6: + entry.IP = net.IP(attr.Value) + default: + log.Printf("unknown nested ADT attribute from kernel: %+v", attr) + } + } + case nl.IPSET_ATTR_IP2 | nl.NLA_F_NESTED: + for attr := range nl.ParseAttributes(attr.Value) { + switch attr.Type { + case nl.IPSET_ATTR_IPADDR_IPV4, nl.IPSET_ATTR_IPADDR_IPV6: + entry.IP2 = net.IP(attr.Value) + default: + log.Printf("unknown nested ADT attribute from kernel: %+v", attr) + } + } + case nl.IPSET_ATTR_CIDR: + entry.CIDR = attr.Value[0] + case nl.IPSET_ATTR_CIDR2: + entry.CIDR2 = attr.Value[0] + case nl.IPSET_ATTR_PORT | nl.NLA_F_NET_BYTEORDER: + val := networkOrder.Uint16(attr.Value) + entry.Port = &val + case nl.IPSET_ATTR_PROTO: + val := attr.Value[0] + entry.Protocol = &val + case nl.IPSET_ATTR_IFACE: + entry.IFace = nl.BytesToString(attr.Value) + case nl.IPSET_ATTR_MARK | nl.NLA_F_NET_BYTEORDER: + val := attr.Uint32() + entry.Mark = &val + default: + log.Printf("unknown ADT attribute from kernel: %+v", attr) + } + } + return +} diff --git a/vendor/github.com/vishvananda/netlink/link.go b/vendor/github.com/vishvananda/netlink/link.go index 886d88d1b..f820cdb67 100644 --- a/vendor/github.com/vishvananda/netlink/link.go +++ b/vendor/github.com/vishvananda/netlink/link.go @@ -22,31 +22,41 @@ type ( // LinkAttrs represents data shared by most link types type LinkAttrs struct { - Index int - MTU int - TxQLen int // Transmit Queue Length - Name string - HardwareAddr net.HardwareAddr - Flags net.Flags - RawFlags uint32 - ParentIndex int // index of the parent link device - MasterIndex int // must be the index of a bridge - Namespace interface{} // nil | NsPid | NsFd - Alias string - Statistics *LinkStatistics - Promisc int - Xdp *LinkXdp - EncapType string - Protinfo *Protinfo - OperState LinkOperState - NetNsID int - NumTxQueues int - NumRxQueues int - GSOMaxSize uint32 - GSOMaxSegs uint32 - Vfs []VfInfo // virtual functions available on link - Group uint32 - Slave LinkSlave + Index int + MTU int + TxQLen int // Transmit Queue Length + Name string + HardwareAddr net.HardwareAddr + Flags net.Flags + RawFlags uint32 + ParentIndex int // index of the parent link device + MasterIndex int // must be the index of a bridge + Namespace interface{} // nil | NsPid | NsFd + Alias string + AltNames []string + Statistics *LinkStatistics + Promisc int + Allmulti int + Multi int + Xdp *LinkXdp + EncapType string + Protinfo *Protinfo + OperState LinkOperState + PhysSwitchID int + NetNsID int + NumTxQueues int + NumRxQueues int + TSOMaxSegs uint32 + TSOMaxSize uint32 + GSOMaxSegs uint32 + GSOMaxSize uint32 + GROMaxSize uint32 + GSOIPv4MaxSize uint32 + GROIPv4MaxSize uint32 + Vfs []VfInfo // virtual functions available on link + Group uint32 + PermHWAddr net.HardwareAddr + Slave LinkSlave } // LinkSlave represents a slave device. @@ -60,11 +70,23 @@ type VfInfo struct { Mac net.HardwareAddr Vlan int Qos int + VlanProto int TxRate int // IFLA_VF_TX_RATE Max TxRate Spoofchk bool LinkState uint32 MaxTxRate uint32 // IFLA_VF_RATE Max TxRate MinTxRate uint32 // IFLA_VF_RATE Min TxRate + RxPackets uint64 + TxPackets uint64 + RxBytes uint64 + TxBytes uint64 + Multicast uint64 + Broadcast uint64 + RxDropped uint64 + TxDropped uint64 + + RssQuery uint32 + Trust uint32 } // LinkOperState represents the values of the IFLA_OPERSTATE link @@ -103,7 +125,8 @@ func (s LinkOperState) String() string { // NewLinkAttrs returns LinkAttrs structure filled with default values func NewLinkAttrs() LinkAttrs { return LinkAttrs{ - TxQLen: -1, + NetNsID: -1, + TxQLen: -1, } } @@ -196,10 +219,11 @@ type LinkStatistics64 struct { } type LinkXdp struct { - Fd int - Attached bool - Flags uint32 - ProgId uint32 + Fd int + Attached bool + AttachMode uint32 + Flags uint32 + ProgId uint32 } // Device links cannot be created via netlink. These links @@ -246,8 +270,11 @@ func (ifb *Ifb) Type() string { type Bridge struct { LinkAttrs MulticastSnooping *bool + AgeingTime *uint32 HelloTime *uint32 VlanFiltering *bool + VlanDefaultPVID *uint16 + GroupFwdMask *uint16 } func (bridge *Bridge) Attrs() *LinkAttrs { @@ -291,6 +318,9 @@ type Macvlan struct { // MACAddrs is only populated for Macvlan SOURCE links MACAddrs []net.HardwareAddr + + BCQueueLen uint32 + UsedBCQueueLen uint32 } func (macvlan *Macvlan) Attrs() *LinkAttrs { @@ -333,11 +363,52 @@ func (tuntap *Tuntap) Type() string { return "tuntap" } +type NetkitMode uint32 + +const ( + NETKIT_MODE_L2 NetkitMode = iota + NETKIT_MODE_L3 +) + +type NetkitPolicy int + +const ( + NETKIT_POLICY_FORWARD NetkitPolicy = 0 + NETKIT_POLICY_BLACKHOLE NetkitPolicy = 2 +) + +func (n *Netkit) IsPrimary() bool { + return n.isPrimary +} + +// SetPeerAttrs will not take effect if trying to modify an existing netkit device +func (n *Netkit) SetPeerAttrs(Attrs *LinkAttrs) { + n.peerLinkAttrs = *Attrs +} + +type Netkit struct { + LinkAttrs + Mode NetkitMode + Policy NetkitPolicy + PeerPolicy NetkitPolicy + isPrimary bool + peerLinkAttrs LinkAttrs +} + +func (n *Netkit) Attrs() *LinkAttrs { + return &n.LinkAttrs +} + +func (n *Netkit) Type() string { + return "netkit" +} + // Veth devices must specify PeerName on create type Veth struct { LinkAttrs PeerName string // veth on create only PeerHardwareAddr net.HardwareAddr + PeerNamespace interface{} } func (veth *Veth) Attrs() *LinkAttrs { @@ -348,6 +419,19 @@ func (veth *Veth) Type() string { return "veth" } +// Wireguard represent links of type "wireguard", see https://www.wireguard.com/ +type Wireguard struct { + LinkAttrs +} + +func (wg *Wireguard) Attrs() *LinkAttrs { + return &wg.LinkAttrs +} + +func (wg *Wireguard) Type() string { + return "wireguard" +} + // GenericLink links represent types that are not currently understood // by this netlink library. type GenericLink struct { @@ -428,6 +512,19 @@ func (ipvlan *IPVlan) Type() string { return "ipvlan" } +// IPVtap - IPVtap is a virtual interfaces based on ipvlan +type IPVtap struct { + IPVlan +} + +func (ipvtap *IPVtap) Attrs() *LinkAttrs { + return &ipvtap.LinkAttrs +} + +func (ipvtap IPVtap) Type() string { + return "ipvtap" +} + // VlanProtocol type type VlanProtocol int @@ -527,6 +624,27 @@ const ( BOND_ARP_VALIDATE_ALL ) +var bondArpValidateToString = map[BondArpValidate]string{ + BOND_ARP_VALIDATE_NONE: "none", + BOND_ARP_VALIDATE_ACTIVE: "active", + BOND_ARP_VALIDATE_BACKUP: "backup", + BOND_ARP_VALIDATE_ALL: "none", +} +var StringToBondArpValidateMap = map[string]BondArpValidate{ + "none": BOND_ARP_VALIDATE_NONE, + "active": BOND_ARP_VALIDATE_ACTIVE, + "backup": BOND_ARP_VALIDATE_BACKUP, + "all": BOND_ARP_VALIDATE_ALL, +} + +func (b BondArpValidate) String() string { + s, ok := bondArpValidateToString[b] + if !ok { + return fmt.Sprintf("BondArpValidate(%d)", b) + } + return s +} + // BondPrimaryReselect type type BondPrimaryReselect int @@ -537,6 +655,25 @@ const ( BOND_PRIMARY_RESELECT_FAILURE ) +var bondPrimaryReselectToString = map[BondPrimaryReselect]string{ + BOND_PRIMARY_RESELECT_ALWAYS: "always", + BOND_PRIMARY_RESELECT_BETTER: "better", + BOND_PRIMARY_RESELECT_FAILURE: "failure", +} +var StringToBondPrimaryReselectMap = map[string]BondPrimaryReselect{ + "always": BOND_PRIMARY_RESELECT_ALWAYS, + "better": BOND_PRIMARY_RESELECT_BETTER, + "failure": BOND_PRIMARY_RESELECT_FAILURE, +} + +func (b BondPrimaryReselect) String() string { + s, ok := bondPrimaryReselectToString[b] + if !ok { + return fmt.Sprintf("BondPrimaryReselect(%d)", b) + } + return s +} + // BondArpAllTargets type type BondArpAllTargets int @@ -546,6 +683,23 @@ const ( BOND_ARP_ALL_TARGETS_ALL ) +var bondArpAllTargetsToString = map[BondArpAllTargets]string{ + BOND_ARP_ALL_TARGETS_ANY: "any", + BOND_ARP_ALL_TARGETS_ALL: "all", +} +var StringToBondArpAllTargetsMap = map[string]BondArpAllTargets{ + "any": BOND_ARP_ALL_TARGETS_ANY, + "all": BOND_ARP_ALL_TARGETS_ALL, +} + +func (b BondArpAllTargets) String() string { + s, ok := bondArpAllTargetsToString[b] + if !ok { + return fmt.Sprintf("BondArpAllTargets(%d)", b) + } + return s +} + // BondFailOverMac type type BondFailOverMac int @@ -556,6 +710,25 @@ const ( BOND_FAIL_OVER_MAC_FOLLOW ) +var bondFailOverMacToString = map[BondFailOverMac]string{ + BOND_FAIL_OVER_MAC_NONE: "none", + BOND_FAIL_OVER_MAC_ACTIVE: "active", + BOND_FAIL_OVER_MAC_FOLLOW: "follow", +} +var StringToBondFailOverMacMap = map[string]BondFailOverMac{ + "none": BOND_FAIL_OVER_MAC_NONE, + "active": BOND_FAIL_OVER_MAC_ACTIVE, + "follow": BOND_FAIL_OVER_MAC_FOLLOW, +} + +func (b BondFailOverMac) String() string { + s, ok := bondFailOverMacToString[b] + if !ok { + return fmt.Sprintf("BondFailOverMac(%d)", b) + } + return s +} + // BondXmitHashPolicy type type BondXmitHashPolicy int @@ -583,6 +756,7 @@ const ( BOND_XMIT_HASH_POLICY_LAYER2_3 BOND_XMIT_HASH_POLICY_ENCAP2_3 BOND_XMIT_HASH_POLICY_ENCAP3_4 + BOND_XMIT_HASH_POLICY_VLAN_SRCMAC BOND_XMIT_HASH_POLICY_UNKNOWN ) @@ -592,6 +766,7 @@ var bondXmitHashPolicyToString = map[BondXmitHashPolicy]string{ BOND_XMIT_HASH_POLICY_LAYER2_3: "layer2+3", BOND_XMIT_HASH_POLICY_ENCAP2_3: "encap2+3", BOND_XMIT_HASH_POLICY_ENCAP3_4: "encap3+4", + BOND_XMIT_HASH_POLICY_VLAN_SRCMAC: "vlan+srcmac", } var StringToBondXmitHashPolicyMap = map[string]BondXmitHashPolicy{ "layer2": BOND_XMIT_HASH_POLICY_LAYER2, @@ -599,6 +774,7 @@ var StringToBondXmitHashPolicyMap = map[string]BondXmitHashPolicy{ "layer2+3": BOND_XMIT_HASH_POLICY_LAYER2_3, "encap2+3": BOND_XMIT_HASH_POLICY_ENCAP2_3, "encap3+4": BOND_XMIT_HASH_POLICY_ENCAP3_4, + "vlan+srcmac": BOND_XMIT_HASH_POLICY_VLAN_SRCMAC, } // BondLacpRate type @@ -647,6 +823,25 @@ const ( BOND_AD_SELECT_COUNT ) +var bondAdSelectToString = map[BondAdSelect]string{ + BOND_AD_SELECT_STABLE: "stable", + BOND_AD_SELECT_BANDWIDTH: "bandwidth", + BOND_AD_SELECT_COUNT: "count", +} +var StringToBondAdSelectMap = map[string]BondAdSelect{ + "stable": BOND_AD_SELECT_STABLE, + "bandwidth": BOND_AD_SELECT_BANDWIDTH, + "count": BOND_AD_SELECT_COUNT, +} + +func (b BondAdSelect) String() string { + s, ok := bondAdSelectToString[b] + if !ok { + return fmt.Sprintf("BondAdSelect(%d)", b) + } + return s +} + // BondAdInfo represents ad info for bond type BondAdInfo struct { AggregatorId int @@ -678,7 +873,7 @@ type Bond struct { AllSlavesActive int MinLinks int LpInterval int - PackersPerSlave int + PacketsPerSlave int LacpRate BondLacpRate AdSelect BondAdSelect // looking at iproute tool AdInfo can only be retrived. It can't be set. @@ -711,7 +906,7 @@ func NewLinkBond(atr LinkAttrs) *Bond { AllSlavesActive: -1, MinLinks: -1, LpInterval: -1, - PackersPerSlave: -1, + PacketsPerSlave: -1, LacpRate: -1, AdSelect: -1, AdActorSysPrio: -1, @@ -761,8 +956,10 @@ func (bond *Bond) Type() string { type BondSlaveState uint8 const ( - BondStateActive = iota // Link is active. - BondStateBackup // Link is backup. + //BondStateActive Link is active. + BondStateActive BondSlaveState = iota + //BondStateBackup Link is backup. + BondStateBackup ) func (s BondSlaveState) String() string { @@ -776,15 +973,19 @@ func (s BondSlaveState) String() string { } } -// BondSlaveState represents the values of the IFLA_BOND_SLAVE_MII_STATUS bond slave +// BondSlaveMiiStatus represents the values of the IFLA_BOND_SLAVE_MII_STATUS bond slave // attribute, which contains the status of MII link monitoring type BondSlaveMiiStatus uint8 const ( - BondLinkUp = iota // link is up and running. - BondLinkFail // link has just gone down. - BondLinkDown // link has been down for too long time. - BondLinkBack // link is going back. + //BondLinkUp link is up and running. + BondLinkUp BondSlaveMiiStatus = iota + //BondLinkFail link has just gone down. + BondLinkFail + //BondLinkDown link has been down for too long time. + BondLinkDown + //BondLinkBack link is going back. + BondLinkBack ) func (s BondSlaveMiiStatus) String() string { @@ -817,6 +1018,49 @@ func (b *BondSlave) SlaveType() string { return "bond" } +type VrfSlave struct { + Table uint32 +} + +func (v *VrfSlave) SlaveType() string { + return "vrf" +} + +// Geneve devices must specify RemoteIP and ID (VNI) on create +// https://github.com/torvalds/linux/blob/47ec5303d73ea344e84f46660fff693c57641386/drivers/net/geneve.c#L1209-L1223 +type Geneve struct { + LinkAttrs + ID uint32 // vni + Remote net.IP + Ttl uint8 + Tos uint8 + Dport uint16 + UdpCsum uint8 + UdpZeroCsum6Tx uint8 + UdpZeroCsum6Rx uint8 + Link uint32 + FlowBased bool + InnerProtoInherit bool + Df GeneveDf +} + +func (geneve *Geneve) Attrs() *LinkAttrs { + return &geneve.LinkAttrs +} + +func (geneve *Geneve) Type() string { + return "geneve" +} + +type GeneveDf uint8 + +const ( + GENEVE_DF_UNSET GeneveDf = iota + GENEVE_DF_SET + GENEVE_DF_INHERIT + GENEVE_DF_MAX +) + // Gretap devices must specify LocalIP and RemoteIP on create type Gretap struct { LinkAttrs @@ -861,6 +1105,7 @@ type Iptun struct { EncapType uint16 EncapFlags uint16 FlowBased bool + Proto uint8 } func (iptun *Iptun) Attrs() *LinkAttrs { @@ -878,10 +1123,15 @@ type Ip6tnl struct { Remote net.IP Ttl uint8 Tos uint8 - EncapLimit uint8 Flags uint32 Proto uint8 FlowInfo uint32 + EncapLimit uint8 + EncapType uint16 + EncapFlags uint16 + EncapSport uint16 + EncapDport uint16 + FlowBased bool } func (ip6tnl *Ip6tnl) Attrs() *LinkAttrs { @@ -892,14 +1142,47 @@ func (ip6tnl *Ip6tnl) Type() string { return "ip6tnl" } +// from https://elixir.bootlin.com/linux/v5.15.4/source/include/uapi/linux/if_tunnel.h#L84 +type TunnelEncapType uint16 + +const ( + None TunnelEncapType = iota + FOU + GUE +) + +// from https://elixir.bootlin.com/linux/v5.15.4/source/include/uapi/linux/if_tunnel.h#L91 +type TunnelEncapFlag uint16 + +const ( + CSum TunnelEncapFlag = 1 << 0 + CSum6 = 1 << 1 + RemCSum = 1 << 2 +) + +// from https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/ip6_tunnel.h#L12 +type IP6TunnelFlag uint16 + +const ( + IP6_TNL_F_IGN_ENCAP_LIMIT IP6TunnelFlag = 1 // don't add encapsulation limit if one isn't present in inner packet + IP6_TNL_F_USE_ORIG_TCLASS = 2 // copy the traffic class field from the inner packet + IP6_TNL_F_USE_ORIG_FLOWLABEL = 4 // copy the flowlabel from the inner packet + IP6_TNL_F_MIP6_DEV = 8 // being used for Mobile IPv6 + IP6_TNL_F_RCV_DSCP_COPY = 10 // copy DSCP from the outer packet + IP6_TNL_F_USE_ORIG_FWMARK = 20 // copy fwmark from inner packet + IP6_TNL_F_ALLOW_LOCAL_REMOTE = 40 // allow remote endpoint on the local node +) + type Sittun struct { LinkAttrs Link uint32 - Local net.IP - Remote net.IP Ttl uint8 Tos uint8 PMtuDisc uint8 + Proto uint8 + Local net.IP + Remote net.IP + EncapLimit uint8 EncapType uint16 EncapFlags uint16 EncapSport uint16 @@ -950,6 +1233,7 @@ type Gretun struct { EncapFlags uint16 EncapSport uint16 EncapDport uint16 + FlowBased bool } func (gretun *Gretun) Attrs() *LinkAttrs { @@ -993,6 +1277,7 @@ func (gtp *GTP) Type() string { } // Virtual XFRM Interfaces +// // Named "xfrmi" to prevent confusion with XFRM objects type Xfrmi struct { LinkAttrs @@ -1034,6 +1319,58 @@ var StringToIPoIBMode = map[string]IPoIBMode{ "connected": IPOIB_MODE_CONNECTED, } +const ( + CAN_STATE_ERROR_ACTIVE = iota + CAN_STATE_ERROR_WARNING + CAN_STATE_ERROR_PASSIVE + CAN_STATE_BUS_OFF + CAN_STATE_STOPPED + CAN_STATE_SLEEPING +) + +type Can struct { + LinkAttrs + + BitRate uint32 + SamplePoint uint32 + TimeQuanta uint32 + PropagationSegment uint32 + PhaseSegment1 uint32 + PhaseSegment2 uint32 + SyncJumpWidth uint32 + BitRatePreScaler uint32 + + Name string + TimeSegment1Min uint32 + TimeSegment1Max uint32 + TimeSegment2Min uint32 + TimeSegment2Max uint32 + SyncJumpWidthMax uint32 + BitRatePreScalerMin uint32 + BitRatePreScalerMax uint32 + BitRatePreScalerInc uint32 + + ClockFrequency uint32 + + State uint32 + + Mask uint32 + Flags uint32 + + TxError uint16 + RxError uint16 + + RestartMs uint32 +} + +func (can *Can) Attrs() *LinkAttrs { + return &can.LinkAttrs +} + +func (can *Can) Type() string { + return "can" +} + type IPoIB struct { LinkAttrs Pkey uint16 @@ -1049,11 +1386,27 @@ func (ipoib *IPoIB) Type() string { return "ipoib" } +type BareUDP struct { + LinkAttrs + Port uint16 + EtherType uint16 + SrcPortMin uint16 + MultiProto bool +} + +func (bareudp *BareUDP) Attrs() *LinkAttrs { + return &bareudp.LinkAttrs +} + +func (bareudp *BareUDP) Type() string { + return "bareudp" +} + // iproute2 supported devices; // vlan | veth | vcan | dummy | ifb | macvlan | macvtap | // bridge | bond | ipoib | ip6tnl | ipip | sit | vxlan | // gre | gretap | ip6gre | ip6gretap | vti | vti6 | nlmon | -// bond_slave | ipvlan | xfrm +// bond_slave | ipvlan | xfrm | bareudp // LinkNotFoundError wraps the various not found errors when // getting/reading links. This is intended for better error diff --git a/vendor/github.com/vishvananda/netlink/link_linux.go b/vendor/github.com/vishvananda/netlink/link_linux.go index ec915a0b9..d713612a9 100644 --- a/vendor/github.com/vishvananda/netlink/link_linux.go +++ b/vendor/github.com/vishvananda/netlink/link_linux.go @@ -34,14 +34,27 @@ const ( TUNTAP_MULTI_QUEUE_DEFAULTS TuntapFlag = TUNTAP_MULTI_QUEUE | TUNTAP_NO_PI ) +var StringToTuntapModeMap = map[string]TuntapMode{ + "tun": TUNTAP_MODE_TUN, + "tap": TUNTAP_MODE_TAP, +} + +func (ttm TuntapMode) String() string { + switch ttm { + case TUNTAP_MODE_TUN: + return "tun" + case TUNTAP_MODE_TAP: + return "tap" + } + return "unknown" +} + const ( VF_LINK_STATE_AUTO uint32 = 0 VF_LINK_STATE_ENABLE uint32 = 1 VF_LINK_STATE_DISABLE uint32 = 2 ) -var lookupByDump = false - var macvlanModes = [...]uint32{ 0, nl.MACVLAN_MODE_PRIVATE, @@ -138,7 +151,6 @@ func (h *Handle) LinkSetAllmulticastOn(link Link) error { msg := nl.NewIfInfomsg(unix.AF_UNSPEC) msg.Change = unix.IFF_ALLMULTI msg.Flags = unix.IFF_ALLMULTI - msg.Index = int32(base.Index) req.AddData(msg) @@ -168,6 +180,51 @@ func (h *Handle) LinkSetAllmulticastOff(link Link) error { return err } +// LinkSetMulticastOn enables the reception of multicast packets for the link device. +// Equivalent to: `ip link set $link multicast on` +func LinkSetMulticastOn(link Link) error { + return pkgHandle.LinkSetMulticastOn(link) +} + +// LinkSetMulticastOn enables the reception of multicast packets for the link device. +// Equivalent to: `ip link set $link multicast on` +func (h *Handle) LinkSetMulticastOn(link Link) error { + base := link.Attrs() + h.ensureIndex(base) + req := h.newNetlinkRequest(unix.RTM_NEWLINK, unix.NLM_F_ACK) + + msg := nl.NewIfInfomsg(unix.AF_UNSPEC) + msg.Change = unix.IFF_MULTICAST + msg.Flags = unix.IFF_MULTICAST + msg.Index = int32(base.Index) + req.AddData(msg) + + _, err := req.Execute(unix.NETLINK_ROUTE, 0) + return err +} + +// LinkSetAllmulticastOff disables the reception of multicast packets for the link device. +// Equivalent to: `ip link set $link multicast off` +func LinkSetMulticastOff(link Link) error { + return pkgHandle.LinkSetMulticastOff(link) +} + +// LinkSetAllmulticastOff disables the reception of multicast packets for the link device. +// Equivalent to: `ip link set $link multicast off` +func (h *Handle) LinkSetMulticastOff(link Link) error { + base := link.Attrs() + h.ensureIndex(base) + req := h.newNetlinkRequest(unix.RTM_NEWLINK, unix.NLM_F_ACK) + + msg := nl.NewIfInfomsg(unix.AF_UNSPEC) + msg.Change = unix.IFF_MULTICAST + msg.Index = int32(base.Index) + req.AddData(msg) + + _, err := req.Execute(unix.NETLINK_ROUTE, 0) + return err +} + func MacvlanMACAddrAdd(link Link, addr net.HardwareAddr) error { return pkgHandle.MacvlanMACAddrAdd(link, addr) } @@ -237,6 +294,37 @@ func (h *Handle) macvlanMACAddrChange(link Link, addrs []net.HardwareAddr, mode return err } +// LinkSetMacvlanMode sets the mode of a macvlan or macvtap link device. +// Note that passthrough mode cannot be set to and from and will fail. +// Equivalent to: `ip link set $link type (macvlan|macvtap) mode $mode +func LinkSetMacvlanMode(link Link, mode MacvlanMode) error { + return pkgHandle.LinkSetMacvlanMode(link, mode) +} + +// LinkSetMacvlanMode sets the mode of the macvlan or macvtap link device. +// Note that passthrough mode cannot be set to and from and will fail. +// Equivalent to: `ip link set $link type (macvlan|macvtap) mode $mode +func (h *Handle) LinkSetMacvlanMode(link Link, mode MacvlanMode) error { + base := link.Attrs() + h.ensureIndex(base) + req := h.newNetlinkRequest(unix.RTM_NEWLINK, unix.NLM_F_ACK) + + msg := nl.NewIfInfomsg(unix.AF_UNSPEC) + msg.Index = int32(base.Index) + req.AddData(msg) + + linkInfo := nl.NewRtAttr(unix.IFLA_LINKINFO, nil) + linkInfo.AddRtAttr(nl.IFLA_INFO_KIND, nl.NonZeroTerminated(link.Type())) + + data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) + data.AddRtAttr(nl.IFLA_MACVLAN_MODE, nl.Uint32Attr(macvlanModes[mode])) + + req.AddData(linkInfo) + + _, err := req.Execute(unix.NETLINK_ROUTE, 0) + return err +} + func BridgeSetMcastSnoop(link Link, on bool) error { return pkgHandle.BridgeSetMcastSnoop(link, on) } @@ -247,6 +335,26 @@ func (h *Handle) BridgeSetMcastSnoop(link Link, on bool) error { return h.linkModify(bridge, unix.NLM_F_ACK) } +func BridgeSetVlanFiltering(link Link, on bool) error { + return pkgHandle.BridgeSetVlanFiltering(link, on) +} + +func (h *Handle) BridgeSetVlanFiltering(link Link, on bool) error { + bridge := link.(*Bridge) + bridge.VlanFiltering = &on + return h.linkModify(bridge, unix.NLM_F_ACK) +} + +func BridgeSetVlanDefaultPVID(link Link, pvid uint16) error { + return pkgHandle.BridgeSetVlanDefaultPVID(link, pvid) +} + +func (h *Handle) BridgeSetVlanDefaultPVID(link Link, pvid uint16) error { + bridge := link.(*Bridge) + bridge.VlanDefaultPVID = &pvid + return h.linkModify(bridge, unix.NLM_F_ACK) +} + func SetPromiscOn(link Link) error { return pkgHandle.SetPromiscOn(link) } @@ -389,6 +497,58 @@ func (h *Handle) LinkSetAlias(link Link, name string) error { return err } +// LinkAddAltName adds a new alternative name for the link device. +// Equivalent to: `ip link property add $link altname $name` +func LinkAddAltName(link Link, name string) error { + return pkgHandle.LinkAddAltName(link, name) +} + +// LinkAddAltName adds a new alternative name for the link device. +// Equivalent to: `ip link property add $link altname $name` +func (h *Handle) LinkAddAltName(link Link, name string) error { + base := link.Attrs() + h.ensureIndex(base) + req := h.newNetlinkRequest(unix.RTM_NEWLINKPROP, unix.NLM_F_ACK) + + msg := nl.NewIfInfomsg(unix.AF_UNSPEC) + msg.Index = int32(base.Index) + req.AddData(msg) + + data := nl.NewRtAttr(unix.IFLA_PROP_LIST|unix.NLA_F_NESTED, nil) + data.AddRtAttr(unix.IFLA_ALT_IFNAME, []byte(name)) + + req.AddData(data) + + _, err := req.Execute(unix.NETLINK_ROUTE, 0) + return err +} + +// LinkDelAltName delete an alternative name for the link device. +// Equivalent to: `ip link property del $link altname $name` +func LinkDelAltName(link Link, name string) error { + return pkgHandle.LinkDelAltName(link, name) +} + +// LinkDelAltName delete an alternative name for the link device. +// Equivalent to: `ip link property del $link altname $name` +func (h *Handle) LinkDelAltName(link Link, name string) error { + base := link.Attrs() + h.ensureIndex(base) + req := h.newNetlinkRequest(unix.RTM_DELLINKPROP, unix.NLM_F_ACK) + + msg := nl.NewIfInfomsg(unix.AF_UNSPEC) + msg.Index = int32(base.Index) + req.AddData(msg) + + data := nl.NewRtAttr(unix.IFLA_PROP_LIST|unix.NLA_F_NESTED, nil) + data.AddRtAttr(unix.IFLA_ALT_IFNAME, []byte(name)) + + req.AddData(data) + + _, err := req.Execute(unix.NETLINK_ROUTE, 0) + return err +} + // LinkSetHardwareAddr sets the hardware address of the link device. // Equivalent to: `ip link set $link address $hwaddr` func LinkSetHardwareAddr(link Link, hwaddr net.HardwareAddr) error { @@ -491,13 +651,50 @@ func (h *Handle) LinkSetVfVlanQos(link Link, vf, vlan, qos int) error { req.AddData(msg) data := nl.NewRtAttr(unix.IFLA_VFINFO_LIST, nil) - info := nl.NewRtAttrChild(data, nl.IFLA_VF_INFO, nil) + info := data.AddRtAttr(nl.IFLA_VF_INFO, nil) vfmsg := nl.VfVlan{ Vf: uint32(vf), Vlan: uint32(vlan), Qos: uint32(qos), } - nl.NewRtAttrChild(info, nl.IFLA_VF_VLAN, vfmsg.Serialize()) + info.AddRtAttr(nl.IFLA_VF_VLAN, vfmsg.Serialize()) + req.AddData(data) + + _, err := req.Execute(unix.NETLINK_ROUTE, 0) + return err +} + +// LinkSetVfVlanQosProto sets the vlan, qos and protocol of a vf for the link. +// Equivalent to: `ip link set $link vf $vf vlan $vlan qos $qos proto $proto` +func LinkSetVfVlanQosProto(link Link, vf, vlan, qos, proto int) error { + return pkgHandle.LinkSetVfVlanQosProto(link, vf, vlan, qos, proto) +} + +// LinkSetVfVlanQosProto sets the vlan, qos and protocol of a vf for the link. +// Equivalent to: `ip link set $link vf $vf vlan $vlan qos $qos proto $proto` +func (h *Handle) LinkSetVfVlanQosProto(link Link, vf, vlan, qos, proto int) error { + base := link.Attrs() + h.ensureIndex(base) + req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK) + + msg := nl.NewIfInfomsg(unix.AF_UNSPEC) + msg.Index = int32(base.Index) + req.AddData(msg) + + data := nl.NewRtAttr(unix.IFLA_VFINFO_LIST, nil) + vfInfo := data.AddRtAttr(nl.IFLA_VF_INFO, nil) + vfVlanList := vfInfo.AddRtAttr(nl.IFLA_VF_VLAN_LIST, nil) + + vfmsg := nl.VfVlanInfo{ + VfVlan: nl.VfVlan{ + Vf: uint32(vf), + Vlan: uint32(vlan), + Qos: uint32(qos), + }, + VlanProto: (uint16(proto)>>8)&0xFF | (uint16(proto)&0xFF)<<8, + } + + vfVlanList.AddRtAttr(nl.IFLA_VF_VLAN_INFO, vfmsg.Serialize()) req.AddData(data) _, err := req.Execute(unix.NETLINK_ROUTE, 0) @@ -848,6 +1045,141 @@ func LinkSetXdpFdWithFlags(link Link, fd, flags int) error { return err } +// LinkSetGSOMaxSegs sets the GSO maximum segment count of the link device. +// Equivalent to: `ip link set $link gso_max_segs $maxSegs` +func LinkSetGSOMaxSegs(link Link, maxSegs int) error { + return pkgHandle.LinkSetGSOMaxSegs(link, maxSegs) +} + +// LinkSetGSOMaxSegs sets the GSO maximum segment count of the link device. +// Equivalent to: `ip link set $link gso_max_segs $maxSegs` +func (h *Handle) LinkSetGSOMaxSegs(link Link, maxSize int) error { + base := link.Attrs() + h.ensureIndex(base) + req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK) + + msg := nl.NewIfInfomsg(unix.AF_UNSPEC) + msg.Index = int32(base.Index) + req.AddData(msg) + + b := make([]byte, 4) + native.PutUint32(b, uint32(maxSize)) + + data := nl.NewRtAttr(unix.IFLA_GSO_MAX_SEGS, b) + req.AddData(data) + + _, err := req.Execute(unix.NETLINK_ROUTE, 0) + return err +} + +// LinkSetGSOMaxSize sets the IPv6 GSO maximum size of the link device. +// Equivalent to: `ip link set $link gso_max_size $maxSize` +func LinkSetGSOMaxSize(link Link, maxSize int) error { + return pkgHandle.LinkSetGSOMaxSize(link, maxSize) +} + +// LinkSetGSOMaxSize sets the IPv6 GSO maximum size of the link device. +// Equivalent to: `ip link set $link gso_max_size $maxSize` +func (h *Handle) LinkSetGSOMaxSize(link Link, maxSize int) error { + base := link.Attrs() + h.ensureIndex(base) + req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK) + + msg := nl.NewIfInfomsg(unix.AF_UNSPEC) + msg.Index = int32(base.Index) + req.AddData(msg) + + b := make([]byte, 4) + native.PutUint32(b, uint32(maxSize)) + + data := nl.NewRtAttr(unix.IFLA_GSO_MAX_SIZE, b) + req.AddData(data) + + _, err := req.Execute(unix.NETLINK_ROUTE, 0) + return err +} + +// LinkSetGROMaxSize sets the IPv6 GRO maximum size of the link device. +// Equivalent to: `ip link set $link gro_max_size $maxSize` +func LinkSetGROMaxSize(link Link, maxSize int) error { + return pkgHandle.LinkSetGROMaxSize(link, maxSize) +} + +// LinkSetGROMaxSize sets the IPv6 GRO maximum size of the link device. +// Equivalent to: `ip link set $link gro_max_size $maxSize` +func (h *Handle) LinkSetGROMaxSize(link Link, maxSize int) error { + base := link.Attrs() + h.ensureIndex(base) + req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK) + + msg := nl.NewIfInfomsg(unix.AF_UNSPEC) + msg.Index = int32(base.Index) + req.AddData(msg) + + b := make([]byte, 4) + native.PutUint32(b, uint32(maxSize)) + + data := nl.NewRtAttr(unix.IFLA_GRO_MAX_SIZE, b) + req.AddData(data) + + _, err := req.Execute(unix.NETLINK_ROUTE, 0) + return err +} + +// LinkSetGSOIPv4MaxSize sets the IPv4 GSO maximum size of the link device. +// Equivalent to: `ip link set $link gso_ipv4_max_size $maxSize` +func LinkSetGSOIPv4MaxSize(link Link, maxSize int) error { + return pkgHandle.LinkSetGSOIPv4MaxSize(link, maxSize) +} + +// LinkSetGSOIPv4MaxSize sets the IPv4 GSO maximum size of the link device. +// Equivalent to: `ip link set $link gso_ipv4_max_size $maxSize` +func (h *Handle) LinkSetGSOIPv4MaxSize(link Link, maxSize int) error { + base := link.Attrs() + h.ensureIndex(base) + req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK) + + msg := nl.NewIfInfomsg(unix.AF_UNSPEC) + msg.Index = int32(base.Index) + req.AddData(msg) + + b := make([]byte, 4) + native.PutUint32(b, uint32(maxSize)) + + data := nl.NewRtAttr(unix.IFLA_GSO_IPV4_MAX_SIZE, b) + req.AddData(data) + + _, err := req.Execute(unix.NETLINK_ROUTE, 0) + return err +} + +// LinkSetGROIPv4MaxSize sets the IPv4 GRO maximum size of the link device. +// Equivalent to: `ip link set $link gro_ipv4_max_size $maxSize` +func LinkSetGROIPv4MaxSize(link Link, maxSize int) error { + return pkgHandle.LinkSetGROIPv4MaxSize(link, maxSize) +} + +// LinkSetGROIPv4MaxSize sets the IPv4 GRO maximum size of the link device. +// Equivalent to: `ip link set $link gro_ipv4_max_size $maxSize` +func (h *Handle) LinkSetGROIPv4MaxSize(link Link, maxSize int) error { + base := link.Attrs() + h.ensureIndex(base) + req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK) + + msg := nl.NewIfInfomsg(unix.AF_UNSPEC) + msg.Index = int32(base.Index) + req.AddData(msg) + + b := make([]byte, 4) + native.PutUint32(b, uint32(maxSize)) + + data := nl.NewRtAttr(unix.IFLA_GRO_IPV4_MAX_SIZE, b) + req.AddData(data) + + _, err := req.Execute(unix.NETLINK_ROUTE, 0) + return err +} + func boolAttr(val bool) []byte { var v uint8 if val { @@ -1005,8 +1337,8 @@ func addBondAttrs(bond *Bond, linkInfo *nl.RtAttr) { if bond.LpInterval >= 0 { data.AddRtAttr(nl.IFLA_BOND_LP_INTERVAL, nl.Uint32Attr(uint32(bond.LpInterval))) } - if bond.PackersPerSlave >= 0 { - data.AddRtAttr(nl.IFLA_BOND_PACKETS_PER_SLAVE, nl.Uint32Attr(uint32(bond.PackersPerSlave))) + if bond.PacketsPerSlave >= 0 { + data.AddRtAttr(nl.IFLA_BOND_PACKETS_PER_SLAVE, nl.Uint32Attr(uint32(bond.PacketsPerSlave))) } if bond.LacpRate >= 0 { data.AddRtAttr(nl.IFLA_BOND_AD_LACP_RATE, nl.Uint8Attr(uint8(bond.LacpRate))) @@ -1048,6 +1380,14 @@ func (h *Handle) LinkAdd(link Link) error { return h.linkModify(link, unix.NLM_F_CREATE|unix.NLM_F_EXCL|unix.NLM_F_ACK) } +func LinkModify(link Link) error { + return pkgHandle.LinkModify(link) +} + +func (h *Handle) LinkModify(link Link) error { + return h.linkModify(link, unix.NLM_F_REQUEST|unix.NLM_F_ACK) +} + func (h *Handle) linkModify(link Link, flags int) error { // TODO: support extra data for macvlan base := link.Attrs() @@ -1060,8 +1400,6 @@ func (h *Handle) linkModify(link Link, flags int) error { } if isTuntap { - // TODO: support user - // TODO: support group if tuntap.Mode < unix.IFF_TUN || tuntap.Mode > unix.IFF_TAP { return fmt.Errorf("Tuntap.Mode %v unknown", tuntap.Mode) } @@ -1089,21 +1427,64 @@ func (h *Handle) linkModify(link Link, flags int) error { } req.Flags |= uint16(tuntap.Mode) - + const TUN = "/dev/net/tun" for i := 0; i < queues; i++ { localReq := req - file, err := os.OpenFile("/dev/net/tun", os.O_RDWR, 0) + fd, err := unix.Open(TUN, os.O_RDWR|syscall.O_CLOEXEC, 0) if err != nil { cleanupFds(fds) return err } - fds = append(fds, file) - _, _, errno := unix.Syscall(unix.SYS_IOCTL, file.Fd(), uintptr(unix.TUNSETIFF), uintptr(unsafe.Pointer(&localReq))) + _, _, errno := unix.Syscall(unix.SYS_IOCTL, uintptr(fd), uintptr(unix.TUNSETIFF), uintptr(unsafe.Pointer(&localReq))) if errno != 0 { + // close the new fd + unix.Close(fd) + // and the already opened ones cleanupFds(fds) return fmt.Errorf("Tuntap IOCTL TUNSETIFF failed [%d], errno %v", i, errno) } + + _, _, errno = syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), syscall.TUNSETOWNER, uintptr(tuntap.Owner)) + if errno != 0 { + cleanupFds(fds) + return fmt.Errorf("Tuntap IOCTL TUNSETOWNER failed [%d], errno %v", i, errno) + } + + _, _, errno = syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), syscall.TUNSETGROUP, uintptr(tuntap.Group)) + if errno != 0 { + cleanupFds(fds) + return fmt.Errorf("Tuntap IOCTL TUNSETGROUP failed [%d], errno %v", i, errno) + } + + // Set the tun device to non-blocking before use. The below comment + // taken from: + // + // https://github.com/mistsys/tuntap/commit/161418c25003bbee77d085a34af64d189df62bea + // + // Note there is a complication because in go, if a device node is + // opened, go sets it to use nonblocking I/O. However a /dev/net/tun + // doesn't work with epoll until after the TUNSETIFF ioctl has been + // done. So we open the unix fd directly, do the ioctl, then put the + // fd in nonblocking mode, an then finally wrap it in a os.File, + // which will see the nonblocking mode and add the fd to the + // pollable set, so later on when we Read() from it blocked the + // calling thread in the kernel. + // + // See + // https://github.com/golang/go/issues/30426 + // which got exposed in go 1.13 by the fix to + // https://github.com/golang/go/issues/30624 + err = unix.SetNonblock(fd, true) + if err != nil { + cleanupFds(fds) + return fmt.Errorf("Tuntap set to non-blocking failed [%d], err %v", i, err) + } + + // create the file from the file descriptor and store it + file := os.NewFile(uintptr(fd), TUN) + fds = append(fds, file) + // 1) we only care for the name of the first tap in the multi queue set // 2) if the original name was empty, the localReq has now the actual name // @@ -1114,11 +1495,29 @@ func (h *Handle) linkModify(link Link, flags int) error { if i == 0 { link.Attrs().Name = strings.Trim(string(localReq.Name[:]), "\x00") } + + } + + control := func(file *os.File, f func(fd uintptr)) error { + name := file.Name() + conn, err := file.SyscallConn() + if err != nil { + return fmt.Errorf("SyscallConn() failed on %s: %v", name, err) + } + if err := conn.Control(f); err != nil { + return fmt.Errorf("Failed to get file descriptor for %s: %v", name, err) + } + return nil } // only persist interface if NonPersist is NOT set if !tuntap.NonPersist { - _, _, errno := unix.Syscall(unix.SYS_IOCTL, fds[0].Fd(), uintptr(unix.TUNSETPERSIST), 1) + var errno syscall.Errno + if err := control(fds[0], func(fd uintptr) { + _, _, errno = unix.Syscall(unix.SYS_IOCTL, fd, uintptr(unix.TUNSETPERSIST), 1) + }); err != nil { + return err + } if errno != 0 { cleanupFds(fds) return fmt.Errorf("Tuntap IOCTL TUNSETPERSIST failed, errno %v", errno) @@ -1135,7 +1534,10 @@ func (h *Handle) linkModify(link Link, flags int) error { // un-persist (e.g. allow the interface to be removed) the tuntap // should not hurt if not set prior, condition might be not needed if !tuntap.NonPersist { - _, _, _ = unix.Syscall(unix.SYS_IOCTL, fds[0].Fd(), uintptr(unix.TUNSETPERSIST), 0) + // ignore error + _ = control(fds[0], func(fd uintptr) { + _, _, _ = unix.Syscall(unix.SYS_IOCTL, fd, uintptr(unix.TUNSETPERSIST), 0) + }) } cleanupFds(fds) return err @@ -1193,6 +1595,11 @@ func (h *Handle) linkModify(link Link, flags int) error { nameData := nl.NewRtAttr(unix.IFLA_IFNAME, nl.ZeroTerminated(base.Name)) req.AddData(nameData) + if base.Alias != "" { + alias := nl.NewRtAttr(unix.IFLA_IFALIAS, []byte(base.Alias)) + req.AddData(alias) + } + if base.MTU > 0 { mtu := nl.NewRtAttr(unix.IFLA_MTU, nl.Uint32Attr(uint32(base.MTU))) req.AddData(mtu) @@ -1228,6 +1635,21 @@ func (h *Handle) linkModify(link Link, flags int) error { req.AddData(gsoAttr) } + if base.GROMaxSize > 0 { + groAttr := nl.NewRtAttr(unix.IFLA_GRO_MAX_SIZE, nl.Uint32Attr(base.GROMaxSize)) + req.AddData(groAttr) + } + + if base.GSOIPv4MaxSize > 0 { + gsoAttr := nl.NewRtAttr(unix.IFLA_GSO_IPV4_MAX_SIZE, nl.Uint32Attr(base.GSOIPv4MaxSize)) + req.AddData(gsoAttr) + } + + if base.GROIPv4MaxSize > 0 { + groAttr := nl.NewRtAttr(unix.IFLA_GRO_IPV4_MAX_SIZE, nl.Uint32Attr(base.GROIPv4MaxSize)) + req.AddData(groAttr) + } + if base.Group > 0 { groupAttr := nl.NewRtAttr(unix.IFLA_GROUP, nl.Uint32Attr(base.Group)) req.AddData(groupAttr) @@ -1264,6 +1686,10 @@ func (h *Handle) linkModify(link Link, flags int) error { if link.VlanProtocol != VLAN_PROTOCOL_UNKNOWN { data.AddRtAttr(nl.IFLA_VLAN_PROTOCOL, htons(uint16(link.VlanProtocol))) } + case *Netkit: + if err := addNetkitAttrs(link, linkInfo, flags); err != nil { + return err + } case *Veth: data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) peer := data.AddRtAttr(nl.VETH_INFO_PEER, nil) @@ -1272,12 +1698,28 @@ func (h *Handle) linkModify(link Link, flags int) error { if base.TxQLen >= 0 { peer.AddRtAttr(unix.IFLA_TXQLEN, nl.Uint32Attr(uint32(base.TxQLen))) } + if base.NumTxQueues > 0 { + peer.AddRtAttr(unix.IFLA_NUM_TX_QUEUES, nl.Uint32Attr(uint32(base.NumTxQueues))) + } + if base.NumRxQueues > 0 { + peer.AddRtAttr(unix.IFLA_NUM_RX_QUEUES, nl.Uint32Attr(uint32(base.NumRxQueues))) + } if base.MTU > 0 { peer.AddRtAttr(unix.IFLA_MTU, nl.Uint32Attr(uint32(base.MTU))) } if link.PeerHardwareAddr != nil { peer.AddRtAttr(unix.IFLA_ADDRESS, []byte(link.PeerHardwareAddr)) } + if link.PeerNamespace != nil { + switch ns := link.PeerNamespace.(type) { + case NsPid: + val := nl.Uint32Attr(uint32(ns)) + peer.AddRtAttr(unix.IFLA_NET_NS_PID, val) + case NsFd: + val := nl.Uint32Attr(uint32(ns)) + peer.AddRtAttr(unix.IFLA_NET_NS_FD, val) + } + } case *Vxlan: addVxlanAttrs(link, linkInfo) case *Bond: @@ -1286,16 +1728,16 @@ func (h *Handle) linkModify(link Link, flags int) error { data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) data.AddRtAttr(nl.IFLA_IPVLAN_MODE, nl.Uint16Attr(uint16(link.Mode))) data.AddRtAttr(nl.IFLA_IPVLAN_FLAG, nl.Uint16Attr(uint16(link.Flag))) + case *IPVtap: + data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) + data.AddRtAttr(nl.IFLA_IPVLAN_MODE, nl.Uint16Attr(uint16(link.Mode))) + data.AddRtAttr(nl.IFLA_IPVLAN_FLAG, nl.Uint16Attr(uint16(link.Flag))) case *Macvlan: - if link.Mode != MACVLAN_MODE_DEFAULT { - data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) - data.AddRtAttr(nl.IFLA_MACVLAN_MODE, nl.Uint32Attr(macvlanModes[link.Mode])) - } + addMacvlanAttrs(link, linkInfo) case *Macvtap: - if link.Mode != MACVLAN_MODE_DEFAULT { - data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) - data.AddRtAttr(nl.IFLA_MACVLAN_MODE, nl.Uint32Attr(macvlanModes[link.Mode])) - } + addMacvtapAttrs(link, linkInfo) + case *Geneve: + addGeneveAttrs(link, linkInfo) case *Gretap: addGretapAttrs(link, linkInfo) case *Iptun: @@ -1318,6 +1760,8 @@ func (h *Handle) linkModify(link Link, flags int) error { addXfrmiAttrs(link, linkInfo) case *IPoIB: addIPoIBAttrs(link, linkInfo) + case *BareUDP: + addBareUDPAttrs(link, linkInfo) } req.AddData(linkInfo) @@ -1372,6 +1816,13 @@ func (h *Handle) linkByNameDump(name string) (Link, error) { if link.Attrs().Name == name { return link, nil } + + // support finding interfaces also via altnames + for _, altName := range link.Attrs().AltNames { + if altName == name { + return link, nil + } + } } return nil, LinkNotFoundError{fmt.Errorf("Link %s not found", name)} } @@ -1410,6 +1861,9 @@ func (h *Handle) LinkByName(name string) (Link, error) { req.AddData(attr) nameData := nl.NewRtAttr(unix.IFLA_IFNAME, nl.ZeroTerminated(name)) + if len(name) > 15 { + nameData = nl.NewRtAttr(unix.IFLA_ALT_IFNAME, nl.ZeroTerminated(name)) + } req.AddData(nameData) link, err := execGetLink(req) @@ -1499,7 +1953,7 @@ func execGetLink(req *nl.NetlinkRequest) (Link, error) { } } -// linkDeserialize deserializes a raw message received from netlink into +// LinkDeserialize deserializes a raw message received from netlink into // a link object. func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) { msg := nl.DeserializeIfInfomsg(m) @@ -1509,10 +1963,19 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) { return nil, err } - base := LinkAttrs{Index: int(msg.Index), RawFlags: msg.Flags, Flags: linkFlags(msg.Flags), EncapType: msg.EncapType()} - if msg.Flags&unix.IFF_PROMISC != 0 { - base.Promisc = 1 + base := NewLinkAttrs() + base.Index = int(msg.Index) + base.RawFlags = msg.Flags + base.Flags = linkFlags(msg.Flags) + base.EncapType = msg.EncapType() + base.NetNsID = -1 + if msg.Flags&unix.IFF_ALLMULTI != 0 { + base.Allmulti = 1 } + if msg.Flags&unix.IFF_MULTICAST != 0 { + base.Multi = 1 + } + var ( link Link stats32 *LinkStatistics32 @@ -1541,18 +2004,26 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) { link = &Bridge{} case "vlan": link = &Vlan{} + case "netkit": + link = &Netkit{} case "veth": link = &Veth{} + case "wireguard": + link = &Wireguard{} case "vxlan": link = &Vxlan{} case "bond": link = &Bond{} case "ipvlan": link = &IPVlan{} + case "ipvtap": + link = &IPVtap{} case "macvlan": link = &Macvlan{} case "macvtap": link = &Macvtap{} + case "geneve": + link = &Geneve{} case "gretap": link = &Gretap{} case "ip6gretap": @@ -1579,6 +2050,10 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) { link = &Tuntap{} case "ipoib": link = &IPoIB{} + case "can": + link = &Can{} + case "bareudp": + link = &BareUDP{} default: link = &GenericLink{LinkType: linkType} } @@ -1588,6 +2063,8 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) { return nil, err } switch linkType { + case "netkit": + parseNetkitData(link, data) case "vlan": parseVlanData(link, data) case "vxlan": @@ -1596,10 +2073,14 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) { parseBondData(link, data) case "ipvlan": parseIPVlanData(link, data) + case "ipvtap": + parseIPVtapData(link, data) case "macvlan": parseMacvlanData(link, data) case "macvtap": parseMacvtapData(link, data) + case "geneve": + parseGeneveData(link, data) case "gretap": parseGretapData(link, data) case "ip6gretap": @@ -1628,13 +2109,21 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) { parseTuntapData(link, data) case "ipoib": parseIPoIBData(link, data) + case "can": + parseCanData(link, data) + case "bareudp": + parseBareUDPData(link, data) } + case nl.IFLA_INFO_SLAVE_KIND: slaveType = string(info.Value[:len(info.Value)-1]) switch slaveType { case "bond": linkSlave = &BondSlave{} + case "vrf": + linkSlave = &VrfSlave{} } + case nl.IFLA_INFO_SLAVE_DATA: switch slaveType { case "bond": @@ -1643,6 +2132,12 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) { return nil, err } parseBondSlaveData(linkSlave, data) + case "vrf": + data, err := nl.ParseRouteAttr(info.Value) + if err != nil { + return nil, err + } + parseVrfSlaveData(linkSlave, data) } } } @@ -1660,6 +2155,8 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) { base.Name = string(attr.Value[:len(attr.Value)-1]) case unix.IFLA_MTU: base.MTU = int(native.Uint32(attr.Value[0:4])) + case unix.IFLA_PROMISCUITY: + base.Promisc = int(native.Uint32(attr.Value[0:4])) case unix.IFLA_LINK: base.ParentIndex = int(native.Uint32(attr.Value[0:4])) case unix.IFLA_MASTER: @@ -1694,14 +2191,38 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) { protinfo := parseProtinfo(attrs) base.Protinfo = &protinfo } + case unix.IFLA_PROP_LIST | unix.NLA_F_NESTED: + attrs, err := nl.ParseRouteAttr(attr.Value[:]) + if err != nil { + return nil, err + } + + base.AltNames = []string{} + for _, attr := range attrs { + if attr.Attr.Type == unix.IFLA_ALT_IFNAME { + base.AltNames = append(base.AltNames, nl.BytesToString(attr.Value)) + } + } case unix.IFLA_OPERSTATE: base.OperState = LinkOperState(uint8(attr.Value[0])) + case unix.IFLA_PHYS_SWITCH_ID: + base.PhysSwitchID = int(native.Uint32(attr.Value[0:4])) case unix.IFLA_LINK_NETNSID: base.NetNsID = int(native.Uint32(attr.Value[0:4])) - case unix.IFLA_GSO_MAX_SIZE: - base.GSOMaxSize = native.Uint32(attr.Value[0:4]) + case unix.IFLA_TSO_MAX_SEGS: + base.TSOMaxSegs = native.Uint32(attr.Value[0:4]) + case unix.IFLA_TSO_MAX_SIZE: + base.TSOMaxSize = native.Uint32(attr.Value[0:4]) case unix.IFLA_GSO_MAX_SEGS: base.GSOMaxSegs = native.Uint32(attr.Value[0:4]) + case unix.IFLA_GSO_MAX_SIZE: + base.GSOMaxSize = native.Uint32(attr.Value[0:4]) + case unix.IFLA_GRO_MAX_SIZE: + base.GROMaxSize = native.Uint32(attr.Value[0:4]) + case unix.IFLA_GSO_IPV4_MAX_SIZE: + base.GSOIPv4MaxSize = native.Uint32(attr.Value[0:4]) + case unix.IFLA_GRO_IPV4_MAX_SIZE: + base.GROIPv4MaxSize = native.Uint32(attr.Value[0:4]) case unix.IFLA_VFINFO_LIST: data, err := nl.ParseRouteAttr(attr.Value) if err != nil { @@ -1718,6 +2239,13 @@ func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) { base.NumRxQueues = int(native.Uint32(attr.Value[0:4])) case unix.IFLA_GROUP: base.Group = native.Uint32(attr.Value[0:4]) + case unix.IFLA_PERM_ADDRESS: + for _, b := range attr.Value { + if b != 0 { + base.PermHWAddr = attr.Value[:] + break + } + } } } @@ -1830,21 +2358,24 @@ type LinkUpdate struct { // LinkSubscribe takes a chan down which notifications will be sent // when links change. Close the 'done' chan to stop subscription. func LinkSubscribe(ch chan<- LinkUpdate, done <-chan struct{}) error { - return linkSubscribeAt(netns.None(), netns.None(), ch, done, nil, false) + return linkSubscribeAt(netns.None(), netns.None(), ch, done, nil, false, 0, nil, false) } // LinkSubscribeAt works like LinkSubscribe plus it allows the caller // to choose the network namespace in which to subscribe (ns). func LinkSubscribeAt(ns netns.NsHandle, ch chan<- LinkUpdate, done <-chan struct{}) error { - return linkSubscribeAt(ns, netns.None(), ch, done, nil, false) + return linkSubscribeAt(ns, netns.None(), ch, done, nil, false, 0, nil, false) } // LinkSubscribeOptions contains a set of options to use with // LinkSubscribeWithOptions. type LinkSubscribeOptions struct { - Namespace *netns.NsHandle - ErrorCallback func(error) - ListExisting bool + Namespace *netns.NsHandle + ErrorCallback func(error) + ListExisting bool + ReceiveBufferSize int + ReceiveBufferForceSize bool + ReceiveTimeout *unix.Timeval } // LinkSubscribeWithOptions work like LinkSubscribe but enable to @@ -1855,14 +2386,27 @@ func LinkSubscribeWithOptions(ch chan<- LinkUpdate, done <-chan struct{}, option none := netns.None() options.Namespace = &none } - return linkSubscribeAt(*options.Namespace, netns.None(), ch, done, options.ErrorCallback, options.ListExisting) + return linkSubscribeAt(*options.Namespace, netns.None(), ch, done, options.ErrorCallback, options.ListExisting, + options.ReceiveBufferSize, options.ReceiveTimeout, options.ReceiveBufferForceSize) } -func linkSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- LinkUpdate, done <-chan struct{}, cberr func(error), listExisting bool) error { +func linkSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- LinkUpdate, done <-chan struct{}, cberr func(error), listExisting bool, + rcvbuf int, rcvTimeout *unix.Timeval, rcvbufForce bool) error { s, err := nl.SubscribeAt(newNs, curNs, unix.NETLINK_ROUTE, unix.RTNLGRP_LINK) if err != nil { return err } + if rcvTimeout != nil { + if err := s.SetReceiveTimeout(rcvTimeout); err != nil { + return err + } + } + if rcvbuf != 0 { + err = s.SetReceiveBufferSize(rcvbuf, rcvbufForce) + if err != nil { + return err + } + } if done != nil { go func() { <-done @@ -1884,7 +2428,8 @@ func linkSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- LinkUpdate, done <-c msgs, from, err := s.Receive() if err != nil { if cberr != nil { - cberr(err) + cberr(fmt.Errorf("Receive failed: %v", + err)) } return } @@ -1899,15 +2444,15 @@ func linkSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- LinkUpdate, done <-c continue } if m.Header.Type == unix.NLMSG_ERROR { - native := nl.NativeEndian() error := int32(native.Uint32(m.Data[0:4])) if error == 0 { continue } if cberr != nil { - cberr(syscall.Errno(-error)) + cberr(fmt.Errorf("error message: %v", + syscall.Errno(-error))) } - return + continue } ifmsg := nl.DeserializeIfInfomsg(m.Data) header := unix.NlMsghdr(m.Header) @@ -1916,7 +2461,7 @@ func linkSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- LinkUpdate, done <-c if cberr != nil { cberr(err) } - return + continue } ch <- LinkUpdate{IfInfomsg: *ifmsg, Header: header, Link: link} } @@ -1942,6 +2487,16 @@ func (h *Handle) LinkSetGuard(link Link, mode bool) error { return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_GUARD) } +// LinkSetBRSlaveGroupFwdMask set the group_fwd_mask of a bridge slave interface +func LinkSetBRSlaveGroupFwdMask(link Link, mask uint16) error { + return pkgHandle.LinkSetBRSlaveGroupFwdMask(link, mask) +} + +// LinkSetBRSlaveGroupFwdMask set the group_fwd_mask of a bridge slave interface +func (h *Handle) LinkSetBRSlaveGroupFwdMask(link Link, mask uint16) error { + return h.setProtinfoAttrRawVal(link, nl.Uint16Attr(mask), nl.IFLA_BRPORT_GROUP_FWD_MASK) +} + func LinkSetFastLeave(link Link, mode bool) error { return pkgHandle.LinkSetFastLeave(link, mode) } @@ -1974,6 +2529,14 @@ func (h *Handle) LinkSetFlood(link Link, mode bool) error { return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_UNICAST_FLOOD) } +func LinkSetIsolated(link Link, mode bool) error { + return pkgHandle.LinkSetIsolated(link, mode) +} + +func (h *Handle) LinkSetIsolated(link Link, mode bool) error { + return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_ISOLATED) +} + func LinkSetBrProxyArp(link Link, mode bool) error { return pkgHandle.LinkSetBrProxyArp(link, mode) } @@ -1990,7 +2553,15 @@ func (h *Handle) LinkSetBrProxyArpWiFi(link Link, mode bool) error { return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_PROXYARP_WIFI) } -func (h *Handle) setProtinfoAttr(link Link, mode bool, attr int) error { +func LinkSetBrNeighSuppress(link Link, mode bool) error { + return pkgHandle.LinkSetBrNeighSuppress(link, mode) +} + +func (h *Handle) LinkSetBrNeighSuppress(link Link, mode bool) error { + return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_NEIGH_SUPPRESS) +} + +func (h *Handle) setProtinfoAttrRawVal(link Link, val []byte, attr int) error { base := link.Attrs() h.ensureIndex(base) req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK) @@ -2000,7 +2571,7 @@ func (h *Handle) setProtinfoAttr(link Link, mode bool, attr int) error { req.AddData(msg) br := nl.NewRtAttr(unix.IFLA_PROTINFO|unix.NLA_F_NESTED, nil) - br.AddRtAttr(attr, boolToByte(mode)) + br.AddRtAttr(attr, val) req.AddData(br) _, err := req.Execute(unix.NETLINK_ROUTE, 0) if err != nil { @@ -2008,6 +2579,9 @@ func (h *Handle) setProtinfoAttr(link Link, mode bool, attr int) error { } return nil } +func (h *Handle) setProtinfoAttr(link Link, mode bool, attr int) error { + return h.setProtinfoAttrRawVal(link, boolToByte(mode), attr) +} // LinkSetTxQLen sets the transaction queue length for the link. // Equivalent to: `ip link set $link txqlen $qlen` @@ -2065,6 +2639,80 @@ func (h *Handle) LinkSetGroup(link Link, group int) error { return err } +func addNetkitAttrs(nk *Netkit, linkInfo *nl.RtAttr, flag int) error { + if nk.peerLinkAttrs.HardwareAddr != nil || nk.HardwareAddr != nil { + return fmt.Errorf("netkit doesn't support setting Ethernet") + } + + data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) + // Kernel will return error if trying to change the mode of an existing netkit device + data.AddRtAttr(nl.IFLA_NETKIT_MODE, nl.Uint32Attr(uint32(nk.Mode))) + data.AddRtAttr(nl.IFLA_NETKIT_POLICY, nl.Uint32Attr(uint32(nk.Policy))) + data.AddRtAttr(nl.IFLA_NETKIT_PEER_POLICY, nl.Uint32Attr(uint32(nk.PeerPolicy))) + + if (flag & unix.NLM_F_EXCL) == 0 { + // Modifying peer link attributes will not take effect + return nil + } + + peer := data.AddRtAttr(nl.IFLA_NETKIT_PEER_INFO, nil) + msg := nl.NewIfInfomsg(unix.AF_UNSPEC) + if nk.peerLinkAttrs.Flags&net.FlagUp != 0 { + msg.Change = unix.IFF_UP + msg.Flags = unix.IFF_UP + } + if nk.peerLinkAttrs.Index != 0 { + msg.Index = int32(nk.peerLinkAttrs.Index) + } + peer.AddChild(msg) + if nk.peerLinkAttrs.Name != "" { + peer.AddRtAttr(unix.IFLA_IFNAME, nl.ZeroTerminated(nk.peerLinkAttrs.Name)) + } + if nk.peerLinkAttrs.MTU > 0 { + peer.AddRtAttr(unix.IFLA_MTU, nl.Uint32Attr(uint32(nk.peerLinkAttrs.MTU))) + } + if nk.peerLinkAttrs.GSOMaxSegs > 0 { + peer.AddRtAttr(unix.IFLA_GSO_MAX_SEGS, nl.Uint32Attr(nk.peerLinkAttrs.GSOMaxSegs)) + } + if nk.peerLinkAttrs.GSOMaxSize > 0 { + peer.AddRtAttr(unix.IFLA_GSO_MAX_SIZE, nl.Uint32Attr(nk.peerLinkAttrs.GSOMaxSize)) + } + if nk.peerLinkAttrs.GSOIPv4MaxSize > 0 { + peer.AddRtAttr(unix.IFLA_GSO_IPV4_MAX_SIZE, nl.Uint32Attr(nk.peerLinkAttrs.GSOIPv4MaxSize)) + } + if nk.peerLinkAttrs.GROIPv4MaxSize > 0 { + peer.AddRtAttr(unix.IFLA_GRO_IPV4_MAX_SIZE, nl.Uint32Attr(nk.peerLinkAttrs.GROIPv4MaxSize)) + } + if nk.peerLinkAttrs.Namespace != nil { + switch ns := nk.peerLinkAttrs.Namespace.(type) { + case NsPid: + peer.AddRtAttr(unix.IFLA_NET_NS_PID, nl.Uint32Attr(uint32(ns))) + case NsFd: + peer.AddRtAttr(unix.IFLA_NET_NS_FD, nl.Uint32Attr(uint32(ns))) + } + } + return nil +} + +func parseNetkitData(link Link, data []syscall.NetlinkRouteAttr) { + netkit := link.(*Netkit) + for _, datum := range data { + switch datum.Attr.Type { + case nl.IFLA_NETKIT_PRIMARY: + isPrimary := datum.Value[0:1][0] + if isPrimary != 0 { + netkit.isPrimary = true + } + case nl.IFLA_NETKIT_MODE: + netkit.Mode = NetkitMode(native.Uint32(datum.Value[0:4])) + case nl.IFLA_NETKIT_POLICY: + netkit.Policy = NetkitPolicy(native.Uint32(datum.Value[0:4])) + case nl.IFLA_NETKIT_PEER_POLICY: + netkit.PeerPolicy = NetkitPolicy(native.Uint32(datum.Value[0:4])) + } + } +} + func parseVlanData(link Link, data []syscall.NetlinkRouteAttr) { vlan := link.(*Vlan) for _, datum := range data { @@ -2080,6 +2728,13 @@ func parseVlanData(link Link, data []syscall.NetlinkRouteAttr) { func parseVxlanData(link Link, data []syscall.NetlinkRouteAttr) { vxlan := link.(*Vxlan) for _, datum := range data { + // NOTE(vish): Apparently some messages can be sent with no value. + // We special case GBP here to not change existing + // functionality. It appears that GBP sends a datum.Value + // of null. + if len(datum.Value) == 0 && datum.Attr.Type != nl.IFLA_VXLAN_GBP { + continue + } switch datum.Attr.Type { case nl.IFLA_VXLAN_ID: vxlan.VxlanId = int(native.Uint32(datum.Value[0:4])) @@ -2178,7 +2833,7 @@ func parseBondData(link Link, data []syscall.NetlinkRouteAttr) { case nl.IFLA_BOND_LP_INTERVAL: bond.LpInterval = int(native.Uint32(data[i].Value[0:4])) case nl.IFLA_BOND_PACKETS_PER_SLAVE: - bond.PackersPerSlave = int(native.Uint32(data[i].Value[0:4])) + bond.PacketsPerSlave = int(native.Uint32(data[i].Value[0:4])) case nl.IFLA_BOND_AD_LACP_RATE: bond.LacpRate = BondLacpRate(data[i].Value[0]) case nl.IFLA_BOND_AD_SELECT: @@ -2258,6 +2913,16 @@ func parseBondSlaveData(slave LinkSlave, data []syscall.NetlinkRouteAttr) { } } +func parseVrfSlaveData(slave LinkSlave, data []syscall.NetlinkRouteAttr) { + vrfSlave := slave.(*VrfSlave) + for i := range data { + switch data[i].Attr.Type { + case nl.IFLA_BOND_SLAVE_STATE: + vrfSlave.Table = native.Uint32(data[i].Value[0:4]) + } + } +} + func parseIPVlanData(link Link, data []syscall.NetlinkRouteAttr) { ipv := link.(*IPVlan) for _, datum := range data { @@ -2270,11 +2935,42 @@ func parseIPVlanData(link Link, data []syscall.NetlinkRouteAttr) { } } +func parseIPVtapData(link Link, data []syscall.NetlinkRouteAttr) { + ipv := link.(*IPVtap) + for _, datum := range data { + switch datum.Attr.Type { + case nl.IFLA_IPVLAN_MODE: + ipv.Mode = IPVlanMode(native.Uint32(datum.Value[0:4])) + case nl.IFLA_IPVLAN_FLAG: + ipv.Flag = IPVlanFlag(native.Uint32(datum.Value[0:4])) + } + } +} + +func addMacvtapAttrs(macvtap *Macvtap, linkInfo *nl.RtAttr) { + addMacvlanAttrs(&macvtap.Macvlan, linkInfo) +} + func parseMacvtapData(link Link, data []syscall.NetlinkRouteAttr) { macv := link.(*Macvtap) parseMacvlanData(&macv.Macvlan, data) } +func addMacvlanAttrs(macvlan *Macvlan, linkInfo *nl.RtAttr) { + var data *nl.RtAttr + + if macvlan.Mode != MACVLAN_MODE_DEFAULT || macvlan.BCQueueLen > 0 { + data = linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) + } + + if macvlan.Mode != MACVLAN_MODE_DEFAULT { + data.AddRtAttr(nl.IFLA_MACVLAN_MODE, nl.Uint32Attr(macvlanModes[macvlan.Mode])) + } + if macvlan.BCQueueLen > 0 { + data.AddRtAttr(nl.IFLA_MACVLAN_BC_QUEUE_LEN, nl.Uint32Attr(macvlan.BCQueueLen)) + } +} + func parseMacvlanData(link Link, data []syscall.NetlinkRouteAttr) { macv := link.(*Macvlan) for _, datum := range data { @@ -2302,6 +2998,10 @@ func parseMacvlanData(link Link, data []syscall.NetlinkRouteAttr) { for _, macDatum := range macs { macv.MACAddrs = append(macv.MACAddrs, net.HardwareAddr(macDatum.Value[0:6])) } + case nl.IFLA_MACVLAN_BC_QUEUE_LEN: + macv.BCQueueLen = native.Uint32(datum.Value[0:4]) + case nl.IFLA_MACVLAN_BC_QUEUE_LEN_USED: + macv.UsedBCQueueLen = native.Uint32(datum.Value[0:4]) } } } @@ -2327,12 +3027,73 @@ func linkFlags(rawFlags uint32) net.Flags { return f } +func addGeneveAttrs(geneve *Geneve, linkInfo *nl.RtAttr) { + data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) + + if geneve.InnerProtoInherit { + data.AddRtAttr(nl.IFLA_GENEVE_INNER_PROTO_INHERIT, []byte{}) + } + + if geneve.FlowBased { + geneve.ID = 0 + data.AddRtAttr(nl.IFLA_GENEVE_COLLECT_METADATA, []byte{}) + } + + if ip := geneve.Remote; ip != nil { + if ip4 := ip.To4(); ip4 != nil { + data.AddRtAttr(nl.IFLA_GENEVE_REMOTE, ip.To4()) + } else { + data.AddRtAttr(nl.IFLA_GENEVE_REMOTE6, []byte(ip)) + } + } + + if geneve.ID != 0 { + data.AddRtAttr(nl.IFLA_GENEVE_ID, nl.Uint32Attr(geneve.ID)) + } + + if geneve.Dport != 0 { + data.AddRtAttr(nl.IFLA_GENEVE_PORT, htons(geneve.Dport)) + } + + if geneve.Ttl != 0 { + data.AddRtAttr(nl.IFLA_GENEVE_TTL, nl.Uint8Attr(geneve.Ttl)) + } + + if geneve.Tos != 0 { + data.AddRtAttr(nl.IFLA_GENEVE_TOS, nl.Uint8Attr(geneve.Tos)) + } + + data.AddRtAttr(nl.IFLA_GENEVE_DF, nl.Uint8Attr(uint8(geneve.Df))) +} + +func parseGeneveData(link Link, data []syscall.NetlinkRouteAttr) { + geneve := link.(*Geneve) + for _, datum := range data { + switch datum.Attr.Type { + case nl.IFLA_GENEVE_ID: + geneve.ID = native.Uint32(datum.Value[0:4]) + case nl.IFLA_GENEVE_REMOTE, nl.IFLA_GENEVE_REMOTE6: + geneve.Remote = datum.Value + case nl.IFLA_GENEVE_PORT: + geneve.Dport = ntohs(datum.Value[0:2]) + case nl.IFLA_GENEVE_TTL: + geneve.Ttl = uint8(datum.Value[0]) + case nl.IFLA_GENEVE_TOS: + geneve.Tos = uint8(datum.Value[0]) + case nl.IFLA_GENEVE_COLLECT_METADATA: + geneve.FlowBased = true + case nl.IFLA_GENEVE_INNER_PROTO_INHERIT: + geneve.InnerProtoInherit = true + } + } +} + func addGretapAttrs(gretap *Gretap, linkInfo *nl.RtAttr) { data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) if gretap.FlowBased { // In flow based mode, no other attributes need to be configured - data.AddRtAttr(nl.IFLA_GRE_COLLECT_METADATA, boolAttr(gretap.FlowBased)) + data.AddRtAttr(nl.IFLA_GRE_COLLECT_METADATA, []byte{}) return } @@ -2415,6 +3176,12 @@ func parseGretapData(link Link, data []syscall.NetlinkRouteAttr) { func addGretunAttrs(gre *Gretun, linkInfo *nl.RtAttr) { data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) + if gre.FlowBased { + // In flow based mode, no other attributes need to be configured + data.AddRtAttr(nl.IFLA_GRE_COLLECT_METADATA, []byte{}) + return + } + if ip := gre.Local; ip != nil { if ip.To4() != nil { ip = ip.To4() @@ -2485,6 +3252,8 @@ func parseGretunData(link Link, data []syscall.NetlinkRouteAttr) { gre.EncapSport = ntohs(datum.Value[0:2]) case nl.IFLA_GRE_ENCAP_DPORT: gre.EncapDport = ntohs(datum.Value[0:2]) + case nl.IFLA_GRE_COLLECT_METADATA: + gre.FlowBased = true } } } @@ -2513,7 +3282,8 @@ func parseLinkXdp(data []byte) (*LinkXdp, error) { case nl.IFLA_XDP_FD: xdp.Fd = int(native.Uint32(attr.Value[0:4])) case nl.IFLA_XDP_ATTACHED: - xdp.Attached = attr.Value[0] != 0 + xdp.AttachMode = uint32(attr.Value[0]) + xdp.Attached = xdp.AttachMode != 0 case nl.IFLA_XDP_FLAGS: xdp.Flags = native.Uint32(attr.Value[0:4]) case nl.IFLA_XDP_PROG_ID: @@ -2524,14 +3294,14 @@ func parseLinkXdp(data []byte) (*LinkXdp, error) { } func addIptunAttrs(iptun *Iptun, linkInfo *nl.RtAttr) { + data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) + if iptun.FlowBased { // In flow based mode, no other attributes need to be configured - linkInfo.AddRtAttr(nl.IFLA_IPTUN_COLLECT_METADATA, boolAttr(iptun.FlowBased)) + data.AddRtAttr(nl.IFLA_IPTUN_COLLECT_METADATA, []byte{}) return } - data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) - ip := iptun.Local.To4() if ip != nil { data.AddRtAttr(nl.IFLA_IPTUN_LOCAL, []byte(ip)) @@ -2552,6 +3322,7 @@ func addIptunAttrs(iptun *Iptun, linkInfo *nl.RtAttr) { data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_FLAGS, nl.Uint16Attr(iptun.EncapFlags)) data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_SPORT, htons(iptun.EncapSport)) data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_DPORT, htons(iptun.EncapDport)) + data.AddRtAttr(nl.IFLA_IPTUN_PROTO, nl.Uint8Attr(iptun.Proto)) } func parseIptunData(link Link, data []syscall.NetlinkRouteAttr) { @@ -2577,7 +3348,9 @@ func parseIptunData(link Link, data []syscall.NetlinkRouteAttr) { case nl.IFLA_IPTUN_ENCAP_FLAGS: iptun.EncapFlags = native.Uint16(datum.Value[0:2]) case nl.IFLA_IPTUN_COLLECT_METADATA: - iptun.FlowBased = int8(datum.Value[0]) != 0 + iptun.FlowBased = true + case nl.IFLA_IPTUN_PROTO: + iptun.Proto = datum.Value[0] } } } @@ -2585,6 +3358,12 @@ func parseIptunData(link Link, data []syscall.NetlinkRouteAttr) { func addIp6tnlAttrs(ip6tnl *Ip6tnl, linkInfo *nl.RtAttr) { data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) + if ip6tnl.FlowBased { + // In flow based mode, no other attributes need to be configured + data.AddRtAttr(nl.IFLA_IPTUN_COLLECT_METADATA, []byte{}) + return + } + if ip6tnl.Link != 0 { data.AddRtAttr(nl.IFLA_IPTUN_LINK, nl.Uint32Attr(ip6tnl.Link)) } @@ -2601,10 +3380,14 @@ func addIp6tnlAttrs(ip6tnl *Ip6tnl, linkInfo *nl.RtAttr) { data.AddRtAttr(nl.IFLA_IPTUN_TTL, nl.Uint8Attr(ip6tnl.Ttl)) data.AddRtAttr(nl.IFLA_IPTUN_TOS, nl.Uint8Attr(ip6tnl.Tos)) - data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_LIMIT, nl.Uint8Attr(ip6tnl.EncapLimit)) data.AddRtAttr(nl.IFLA_IPTUN_FLAGS, nl.Uint32Attr(ip6tnl.Flags)) data.AddRtAttr(nl.IFLA_IPTUN_PROTO, nl.Uint8Attr(ip6tnl.Proto)) data.AddRtAttr(nl.IFLA_IPTUN_FLOWINFO, nl.Uint32Attr(ip6tnl.FlowInfo)) + data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_LIMIT, nl.Uint8Attr(ip6tnl.EncapLimit)) + data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_TYPE, nl.Uint16Attr(ip6tnl.EncapType)) + data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_FLAGS, nl.Uint16Attr(ip6tnl.EncapFlags)) + data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_SPORT, htons(ip6tnl.EncapSport)) + data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_DPORT, htons(ip6tnl.EncapDport)) } func parseIp6tnlData(link Link, data []syscall.NetlinkRouteAttr) { @@ -2616,17 +3399,27 @@ func parseIp6tnlData(link Link, data []syscall.NetlinkRouteAttr) { case nl.IFLA_IPTUN_REMOTE: ip6tnl.Remote = net.IP(datum.Value[:16]) case nl.IFLA_IPTUN_TTL: - ip6tnl.Ttl = uint8(datum.Value[0]) + ip6tnl.Ttl = datum.Value[0] case nl.IFLA_IPTUN_TOS: - ip6tnl.Tos = uint8(datum.Value[0]) - case nl.IFLA_IPTUN_ENCAP_LIMIT: - ip6tnl.EncapLimit = uint8(datum.Value[0]) + ip6tnl.Tos = datum.Value[0] case nl.IFLA_IPTUN_FLAGS: ip6tnl.Flags = native.Uint32(datum.Value[:4]) case nl.IFLA_IPTUN_PROTO: - ip6tnl.Proto = uint8(datum.Value[0]) + ip6tnl.Proto = datum.Value[0] case nl.IFLA_IPTUN_FLOWINFO: ip6tnl.FlowInfo = native.Uint32(datum.Value[:4]) + case nl.IFLA_IPTUN_ENCAP_LIMIT: + ip6tnl.EncapLimit = datum.Value[0] + case nl.IFLA_IPTUN_ENCAP_TYPE: + ip6tnl.EncapType = native.Uint16(datum.Value[0:2]) + case nl.IFLA_IPTUN_ENCAP_FLAGS: + ip6tnl.EncapFlags = native.Uint16(datum.Value[0:2]) + case nl.IFLA_IPTUN_ENCAP_SPORT: + ip6tnl.EncapSport = ntohs(datum.Value[0:2]) + case nl.IFLA_IPTUN_ENCAP_DPORT: + ip6tnl.EncapDport = ntohs(datum.Value[0:2]) + case nl.IFLA_IPTUN_COLLECT_METADATA: + ip6tnl.FlowBased = true } } } @@ -2653,8 +3446,10 @@ func addSittunAttrs(sittun *Sittun, linkInfo *nl.RtAttr) { data.AddRtAttr(nl.IFLA_IPTUN_TTL, nl.Uint8Attr(sittun.Ttl)) } + data.AddRtAttr(nl.IFLA_IPTUN_PROTO, nl.Uint8Attr(sittun.Proto)) data.AddRtAttr(nl.IFLA_IPTUN_TOS, nl.Uint8Attr(sittun.Tos)) data.AddRtAttr(nl.IFLA_IPTUN_PMTUDISC, nl.Uint8Attr(sittun.PMtuDisc)) + data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_LIMIT, nl.Uint8Attr(sittun.EncapLimit)) data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_TYPE, nl.Uint16Attr(sittun.EncapType)) data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_FLAGS, nl.Uint16Attr(sittun.EncapFlags)) data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_SPORT, htons(sittun.EncapSport)) @@ -2670,11 +3465,13 @@ func parseSittunData(link Link, data []syscall.NetlinkRouteAttr) { case nl.IFLA_IPTUN_REMOTE: sittun.Remote = net.IP(datum.Value[0:4]) case nl.IFLA_IPTUN_TTL: - sittun.Ttl = uint8(datum.Value[0]) + sittun.Ttl = datum.Value[0] case nl.IFLA_IPTUN_TOS: - sittun.Tos = uint8(datum.Value[0]) + sittun.Tos = datum.Value[0] case nl.IFLA_IPTUN_PMTUDISC: - sittun.PMtuDisc = uint8(datum.Value[0]) + sittun.PMtuDisc = datum.Value[0] + case nl.IFLA_IPTUN_PROTO: + sittun.Proto = datum.Value[0] case nl.IFLA_IPTUN_ENCAP_TYPE: sittun.EncapType = native.Uint16(datum.Value[0:2]) case nl.IFLA_IPTUN_ENCAP_FLAGS: @@ -2761,18 +3558,30 @@ func addBridgeAttrs(bridge *Bridge, linkInfo *nl.RtAttr) { if bridge.MulticastSnooping != nil { data.AddRtAttr(nl.IFLA_BR_MCAST_SNOOPING, boolToByte(*bridge.MulticastSnooping)) } + if bridge.AgeingTime != nil { + data.AddRtAttr(nl.IFLA_BR_AGEING_TIME, nl.Uint32Attr(*bridge.AgeingTime)) + } if bridge.HelloTime != nil { data.AddRtAttr(nl.IFLA_BR_HELLO_TIME, nl.Uint32Attr(*bridge.HelloTime)) } if bridge.VlanFiltering != nil { data.AddRtAttr(nl.IFLA_BR_VLAN_FILTERING, boolToByte(*bridge.VlanFiltering)) } + if bridge.VlanDefaultPVID != nil { + data.AddRtAttr(nl.IFLA_BR_VLAN_DEFAULT_PVID, nl.Uint16Attr(*bridge.VlanDefaultPVID)) + } + if bridge.GroupFwdMask != nil { + data.AddRtAttr(nl.IFLA_BR_GROUP_FWD_MASK, nl.Uint16Attr(*bridge.GroupFwdMask)) + } } func parseBridgeData(bridge Link, data []syscall.NetlinkRouteAttr) { br := bridge.(*Bridge) for _, datum := range data { switch datum.Attr.Type { + case nl.IFLA_BR_AGEING_TIME: + ageingTime := native.Uint32(datum.Value[0:4]) + br.AgeingTime = &ageingTime case nl.IFLA_BR_HELLO_TIME: helloTime := native.Uint32(datum.Value[0:4]) br.HelloTime = &helloTime @@ -2782,6 +3591,12 @@ func parseBridgeData(bridge Link, data []syscall.NetlinkRouteAttr) { case nl.IFLA_BR_VLAN_FILTERING: vlanFiltering := datum.Value[0] == 1 br.VlanFiltering = &vlanFiltering + case nl.IFLA_BR_VLAN_DEFAULT_PVID: + vlanDefaultPVID := native.Uint16(datum.Value[0:2]) + br.VlanDefaultPVID = &vlanDefaultPVID + case nl.IFLA_BR_GROUP_FWD_MASK: + mask := native.Uint16(datum.Value[0:2]) + br.GroupFwdMask = &mask } } } @@ -2823,12 +3638,17 @@ func parseVfInfoList(data []syscall.NetlinkRouteAttr) ([]VfInfo, error) { if err != nil { return nil, err } - vfs = append(vfs, parseVfInfo(vfAttrs, i)) + + vf, err := parseVfInfo(vfAttrs, i) + if err != nil { + return nil, err + } + vfs = append(vfs, vf) } return vfs, nil } -func parseVfInfo(data []syscall.NetlinkRouteAttr, id int) VfInfo { +func parseVfInfo(data []syscall.NetlinkRouteAttr, id int) (VfInfo, error) { vf := VfInfo{ID: id} for _, element := range data { switch element.Attr.Type { @@ -2839,6 +3659,12 @@ func parseVfInfo(data []syscall.NetlinkRouteAttr, id int) VfInfo { vl := nl.DeserializeVfVlan(element.Value[:]) vf.Vlan = int(vl.Vlan) vf.Qos = int(vl.Qos) + case nl.IFLA_VF_VLAN_LIST: + vfVlanInfoList, err := nl.DeserializeVfVlanList(element.Value[:]) + if err != nil { + return vf, err + } + vf.VlanProto = int(vfVlanInfoList[0].VlanProto) case nl.IFLA_VF_TX_RATE: txr := nl.DeserializeVfTxRate(element.Value[:]) vf.TxRate = int(txr.Rate) @@ -2852,16 +3678,35 @@ func parseVfInfo(data []syscall.NetlinkRouteAttr, id int) VfInfo { vfr := nl.DeserializeVfRate(element.Value[:]) vf.MaxTxRate = vfr.MaxTxRate vf.MinTxRate = vfr.MinTxRate + case nl.IFLA_VF_STATS: + vfstats := nl.DeserializeVfStats(element.Value[:]) + vf.RxPackets = vfstats.RxPackets + vf.TxPackets = vfstats.TxPackets + vf.RxBytes = vfstats.RxBytes + vf.TxBytes = vfstats.TxBytes + vf.Multicast = vfstats.Multicast + vf.Broadcast = vfstats.Broadcast + vf.RxDropped = vfstats.RxDropped + vf.TxDropped = vfstats.TxDropped + + case nl.IFLA_VF_RSS_QUERY_EN: + result := nl.DeserializeVfRssQueryEn(element.Value) + vf.RssQuery = result.Setting + + case nl.IFLA_VF_TRUST: + result := nl.DeserializeVfTrust(element.Value) + vf.Trust = result.Setting } } - return vf + return vf, nil } func addXfrmiAttrs(xfrmi *Xfrmi, linkInfo *nl.RtAttr) { data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) data.AddRtAttr(nl.IFLA_XFRM_LINK, nl.Uint32Attr(uint32(xfrmi.ParentIndex))) - data.AddRtAttr(nl.IFLA_XFRM_IF_ID, nl.Uint32Attr(xfrmi.Ifid)) - + if xfrmi.Ifid != 0 { + data.AddRtAttr(nl.IFLA_XFRM_IF_ID, nl.Uint32Attr(xfrmi.Ifid)) + } } func parseXfrmiData(link Link, data []syscall.NetlinkRouteAttr) { @@ -2876,8 +3721,7 @@ func parseXfrmiData(link Link, data []syscall.NetlinkRouteAttr) { } } -// LinkSetBondSlave add slave to bond link via ioctl interface. -func LinkSetBondSlave(link Link, master *Bond) error { +func ioctlBondSlave(cmd uintptr, link Link, master *Bond) error { fd, err := getSocketUDP() if err != nil { return err @@ -2885,10 +3729,38 @@ func LinkSetBondSlave(link Link, master *Bond) error { defer syscall.Close(fd) ifreq := newIocltSlaveReq(link.Attrs().Name, master.Attrs().Name) - - _, _, errno := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), unix.SIOCBONDENSLAVE, uintptr(unsafe.Pointer(ifreq))) + _, _, errno := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), cmd, uintptr(unsafe.Pointer(ifreq))) if errno != 0 { - return fmt.Errorf("Failed to enslave %q to %q, errno=%v", link.Attrs().Name, master.Attrs().Name, errno) + return fmt.Errorf("errno=%v", errno) + } + return nil +} + +// LinkSetBondSlaveActive sets specified slave to ACTIVE in an `active-backup` bond link via ioctl interface. +// +// Multiple calls keeps the status unchanged(shown in the unit test). +func LinkSetBondSlaveActive(link Link, master *Bond) error { + err := ioctlBondSlave(unix.SIOCBONDCHANGEACTIVE, link, master) + if err != nil { + return fmt.Errorf("Failed to set slave %q active in %q, %v", link.Attrs().Name, master.Attrs().Name, err) + } + return nil +} + +// LinkSetBondSlave add slave to bond link via ioctl interface. +func LinkSetBondSlave(link Link, master *Bond) error { + err := ioctlBondSlave(unix.SIOCBONDENSLAVE, link, master) + if err != nil { + return fmt.Errorf("Failed to enslave %q to %q, %v", link.Attrs().Name, master.Attrs().Name, err) + } + return nil +} + +// LinkSetBondSlave removes specified slave from bond link via ioctl interface. +func LinkDelBondSlave(link Link, master *Bond) error { + err := ioctlBondSlave(unix.SIOCBONDRELEASE, link, master) + if err != nil { + return fmt.Errorf("Failed to del slave %q from %q, %v", link.Attrs().Name, master.Attrs().Name, err) } return nil } @@ -3010,9 +3882,86 @@ func parseIPoIBData(link Link, data []syscall.NetlinkRouteAttr) { } } +func parseCanData(link Link, data []syscall.NetlinkRouteAttr) { + can := link.(*Can) + for _, datum := range data { + + switch datum.Attr.Type { + case nl.IFLA_CAN_BITTIMING: + can.BitRate = native.Uint32(datum.Value) + can.SamplePoint = native.Uint32(datum.Value[4:]) + can.TimeQuanta = native.Uint32(datum.Value[8:]) + can.PropagationSegment = native.Uint32(datum.Value[12:]) + can.PhaseSegment1 = native.Uint32(datum.Value[16:]) + can.PhaseSegment2 = native.Uint32(datum.Value[20:]) + can.SyncJumpWidth = native.Uint32(datum.Value[24:]) + can.BitRatePreScaler = native.Uint32(datum.Value[28:]) + case nl.IFLA_CAN_BITTIMING_CONST: + can.Name = string(datum.Value[:16]) + can.TimeSegment1Min = native.Uint32(datum.Value[16:]) + can.TimeSegment1Max = native.Uint32(datum.Value[20:]) + can.TimeSegment2Min = native.Uint32(datum.Value[24:]) + can.TimeSegment2Max = native.Uint32(datum.Value[28:]) + can.SyncJumpWidthMax = native.Uint32(datum.Value[32:]) + can.BitRatePreScalerMin = native.Uint32(datum.Value[36:]) + can.BitRatePreScalerMax = native.Uint32(datum.Value[40:]) + can.BitRatePreScalerInc = native.Uint32(datum.Value[44:]) + case nl.IFLA_CAN_CLOCK: + can.ClockFrequency = native.Uint32(datum.Value) + case nl.IFLA_CAN_STATE: + can.State = native.Uint32(datum.Value) + case nl.IFLA_CAN_CTRLMODE: + can.Mask = native.Uint32(datum.Value) + can.Flags = native.Uint32(datum.Value[4:]) + case nl.IFLA_CAN_BERR_COUNTER: + can.TxError = native.Uint16(datum.Value) + can.RxError = native.Uint16(datum.Value[2:]) + case nl.IFLA_CAN_RESTART_MS: + can.RestartMs = native.Uint32(datum.Value) + case nl.IFLA_CAN_DATA_BITTIMING_CONST: + case nl.IFLA_CAN_RESTART: + case nl.IFLA_CAN_DATA_BITTIMING: + case nl.IFLA_CAN_TERMINATION: + case nl.IFLA_CAN_TERMINATION_CONST: + case nl.IFLA_CAN_BITRATE_CONST: + case nl.IFLA_CAN_DATA_BITRATE_CONST: + case nl.IFLA_CAN_BITRATE_MAX: + } + } +} + func addIPoIBAttrs(ipoib *IPoIB, linkInfo *nl.RtAttr) { data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) data.AddRtAttr(nl.IFLA_IPOIB_PKEY, nl.Uint16Attr(uint16(ipoib.Pkey))) data.AddRtAttr(nl.IFLA_IPOIB_MODE, nl.Uint16Attr(uint16(ipoib.Mode))) data.AddRtAttr(nl.IFLA_IPOIB_UMCAST, nl.Uint16Attr(uint16(ipoib.Umcast))) } + +func addBareUDPAttrs(bareudp *BareUDP, linkInfo *nl.RtAttr) { + data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil) + + data.AddRtAttr(nl.IFLA_BAREUDP_PORT, nl.Uint16Attr(nl.Swap16(bareudp.Port))) + data.AddRtAttr(nl.IFLA_BAREUDP_ETHERTYPE, nl.Uint16Attr(nl.Swap16(bareudp.EtherType))) + if bareudp.SrcPortMin != 0 { + data.AddRtAttr(nl.IFLA_BAREUDP_SRCPORT_MIN, nl.Uint16Attr(bareudp.SrcPortMin)) + } + if bareudp.MultiProto { + data.AddRtAttr(nl.IFLA_BAREUDP_MULTIPROTO_MODE, []byte{}) + } +} + +func parseBareUDPData(link Link, data []syscall.NetlinkRouteAttr) { + bareudp := link.(*BareUDP) + for _, attr := range data { + switch attr.Attr.Type { + case nl.IFLA_BAREUDP_PORT: + bareudp.Port = binary.BigEndian.Uint16(attr.Value) + case nl.IFLA_BAREUDP_ETHERTYPE: + bareudp.EtherType = binary.BigEndian.Uint16(attr.Value) + case nl.IFLA_BAREUDP_SRCPORT_MIN: + bareudp.SrcPortMin = native.Uint16(attr.Value) + case nl.IFLA_BAREUDP_MULTIPROTO_MODE: + bareudp.MultiProto = true + } + } +} diff --git a/vendor/github.com/vishvananda/netlink/neigh.go b/vendor/github.com/vishvananda/netlink/neigh.go index 379e5655f..32d722e88 100644 --- a/vendor/github.com/vishvananda/netlink/neigh.go +++ b/vendor/github.com/vishvananda/netlink/neigh.go @@ -12,6 +12,7 @@ type Neigh struct { State int Type int Flags int + FlagsExt int IP net.IP HardwareAddr net.HardwareAddr LLIPAddr net.IP //Used in the case of NHRP diff --git a/vendor/github.com/vishvananda/netlink/neigh_linux.go b/vendor/github.com/vishvananda/netlink/neigh_linux.go index cb3b55d35..2d93044a6 100644 --- a/vendor/github.com/vishvananda/netlink/neigh_linux.go +++ b/vendor/github.com/vishvananda/netlink/neigh_linux.go @@ -24,7 +24,11 @@ const ( NDA_MASTER NDA_LINK_NETNSID NDA_SRC_VNI - NDA_MAX = NDA_SRC_VNI + NDA_PROTOCOL + NDA_NH_ID + NDA_FDB_EXT_ATTRS + NDA_FLAGS_EXT + NDA_MAX = NDA_FLAGS_EXT ) // Neighbor Cache Entry States. @@ -42,11 +46,19 @@ const ( // Neighbor Flags const ( - NTF_USE = 0x01 - NTF_SELF = 0x02 - NTF_MASTER = 0x04 - NTF_PROXY = 0x08 - NTF_ROUTER = 0x80 + NTF_USE = 0x01 + NTF_SELF = 0x02 + NTF_MASTER = 0x04 + NTF_PROXY = 0x08 + NTF_EXT_LEARNED = 0x10 + NTF_OFFLOADED = 0x20 + NTF_STICKY = 0x40 + NTF_ROUTER = 0x80 +) + +// Extended Neighbor Flags +const ( + NTF_EXT_MANAGED = 0x00000001 ) // Ndmsg is for adding, removing or receiving information about a neighbor table entry @@ -162,11 +174,16 @@ func neighHandle(neigh *Neigh, req *nl.NetlinkRequest) error { if neigh.LLIPAddr != nil { llIPData := nl.NewRtAttr(NDA_LLADDR, neigh.LLIPAddr.To4()) req.AddData(llIPData) - } else if neigh.Flags != NTF_PROXY || neigh.HardwareAddr != nil { + } else if neigh.HardwareAddr != nil { hwData := nl.NewRtAttr(NDA_LLADDR, []byte(neigh.HardwareAddr)) req.AddData(hwData) } + if neigh.FlagsExt != 0 { + flagsExtData := nl.NewRtAttr(NDA_FLAGS_EXT, nl.Uint32Attr(uint32(neigh.FlagsExt))) + req.AddData(flagsExtData) + } + if neigh.Vlan != 0 { vlanData := nl.NewRtAttr(NDA_VLAN, nl.Uint16Attr(uint16(neigh.Vlan))) req.AddData(vlanData) @@ -243,6 +260,18 @@ func (h *Handle) NeighListExecute(msg Ndmsg) ([]Neigh, error) { // Ignore messages from other interfaces continue } + if msg.Family != 0 && ndm.Family != msg.Family { + continue + } + if msg.State != 0 && ndm.State != msg.State { + continue + } + if msg.Type != 0 && ndm.Type != msg.Type { + continue + } + if msg.Flags != 0 && ndm.Flags != msg.Flags { + continue + } neigh, err := NeighDeserialize(m) if err != nil { @@ -293,6 +322,8 @@ func NeighDeserialize(m []byte) (*Neigh, error) { } else { neigh.HardwareAddr = net.HardwareAddr(attr.Value) } + case NDA_FLAGS_EXT: + neigh.FlagsExt = int(native.Uint32(attr.Value[0:4])) case NDA_VLAN: neigh.Vlan = int(native.Uint16(attr.Value[0:2])) case NDA_VNI: @@ -308,13 +339,13 @@ func NeighDeserialize(m []byte) (*Neigh, error) { // NeighSubscribe takes a chan down which notifications will be sent // when neighbors are added or deleted. Close the 'done' chan to stop subscription. func NeighSubscribe(ch chan<- NeighUpdate, done <-chan struct{}) error { - return neighSubscribeAt(netns.None(), netns.None(), ch, done, nil, false) + return neighSubscribeAt(netns.None(), netns.None(), ch, done, nil, false, 0, nil, false) } // NeighSubscribeAt works like NeighSubscribe plus it allows the caller // to choose the network namespace in which to subscribe (ns). func NeighSubscribeAt(ns netns.NsHandle, ch chan<- NeighUpdate, done <-chan struct{}) error { - return neighSubscribeAt(ns, netns.None(), ch, done, nil, false) + return neighSubscribeAt(ns, netns.None(), ch, done, nil, false, 0, nil, false) } // NeighSubscribeOptions contains a set of options to use with @@ -323,6 +354,11 @@ type NeighSubscribeOptions struct { Namespace *netns.NsHandle ErrorCallback func(error) ListExisting bool + + // max size is based on value of /proc/sys/net/core/rmem_max + ReceiveBufferSize int + ReceiveBufferForceSize bool + ReceiveTimeout *unix.Timeval } // NeighSubscribeWithOptions work like NeighSubscribe but enable to @@ -333,16 +369,17 @@ func NeighSubscribeWithOptions(ch chan<- NeighUpdate, done <-chan struct{}, opti none := netns.None() options.Namespace = &none } - return neighSubscribeAt(*options.Namespace, netns.None(), ch, done, options.ErrorCallback, options.ListExisting) + return neighSubscribeAt(*options.Namespace, netns.None(), ch, done, options.ErrorCallback, options.ListExisting, + options.ReceiveBufferSize, options.ReceiveTimeout, options.ReceiveBufferForceSize) } -func neighSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- NeighUpdate, done <-chan struct{}, cberr func(error), listExisting bool) error { +func neighSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- NeighUpdate, done <-chan struct{}, cberr func(error), listExisting bool, + rcvbuf int, rcvTimeout *unix.Timeval, rcvbufForce bool) error { s, err := nl.SubscribeAt(newNs, curNs, unix.NETLINK_ROUTE, unix.RTNLGRP_NEIGH) makeRequest := func(family int) error { - req := pkgHandle.newNetlinkRequest(unix.RTM_GETNEIGH, - unix.NLM_F_DUMP) - infmsg := nl.NewIfInfomsg(family) - req.AddData(infmsg) + req := pkgHandle.newNetlinkRequest(unix.RTM_GETNEIGH, unix.NLM_F_DUMP) + ndmsg := &Ndmsg{Family: uint8(family)} + req.AddData(ndmsg) if err := s.Send(req); err != nil { return err } @@ -351,6 +388,17 @@ func neighSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- NeighUpdate, done < if err != nil { return err } + if rcvTimeout != nil { + if err := s.SetReceiveTimeout(rcvTimeout); err != nil { + return err + } + } + if rcvbuf != 0 { + err = s.SetReceiveBufferSize(rcvbuf, rcvbufForce) + if err != nil { + return err + } + } if done != nil { go func() { <-done @@ -396,13 +444,12 @@ func neighSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- NeighUpdate, done < continue } if m.Header.Type == unix.NLMSG_ERROR { - native := nl.NativeEndian() - error := int32(native.Uint32(m.Data[0:4])) - if error == 0 { + nError := int32(native.Uint32(m.Data[0:4])) + if nError == 0 { continue } if cberr != nil { - cberr(syscall.Errno(-error)) + cberr(syscall.Errno(-nError)) } return } diff --git a/vendor/github.com/vishvananda/netlink/netlink_unspecified.go b/vendor/github.com/vishvananda/netlink/netlink_unspecified.go index 42d3acf91..da12c42a5 100644 --- a/vendor/github.com/vishvananda/netlink/netlink_unspecified.go +++ b/vendor/github.com/vishvananda/netlink/netlink_unspecified.go @@ -16,7 +16,7 @@ func LinkSetMTU(link Link, mtu int) error { return ErrNotImplemented } -func LinkSetMaster(link Link, master *Bridge) error { +func LinkSetMaster(link Link, master Link) error { return ErrNotImplemented } @@ -52,6 +52,10 @@ func LinkSetVfVlanQos(link Link, vf, vlan, qos int) error { return ErrNotImplemented } +func LinkSetVfVlanQosProto(link Link, vf, vlan, qos, proto int) error { + return ErrNotImplemented +} + func LinkSetVfTxRate(link Link, vf, rate int) error { return ErrNotImplemented } @@ -72,6 +76,10 @@ func LinkSetXdpFd(link Link, fd int) error { return ErrNotImplemented } +func LinkSetXdpFdWithFlags(link Link, fd, flags int) error { + return ErrNotImplemented +} + func LinkSetARPOff(link Link) error { return ErrNotImplemented } @@ -120,6 +128,22 @@ func LinkSetTxQLen(link Link, qlen int) error { return ErrNotImplemented } +func LinkSetGSOMaxSize(link Link, maxSize int) error { + return ErrNotImplemented +} + +func LinkSetGROMaxSize(link Link, maxSize int) error { + return ErrNotImplemented +} + +func LinkSetGSOIPv4MaxSize(link Link, maxSize int) error { + return ErrNotImplemented +} + +func LinkSetGROIPv4MaxSize(link Link, maxSize int) error { + return ErrNotImplemented +} + func LinkAdd(link Link) error { return ErrNotImplemented } @@ -176,14 +200,34 @@ func RouteAdd(route *Route) error { return ErrNotImplemented } +func RouteAppend(route *Route) error { + return ErrNotImplemented +} + +func RouteChange(route *Route) error { + return ErrNotImplemented +} + func RouteDel(route *Route) error { return ErrNotImplemented } +func RouteGet(destination net.IP) ([]Route, error) { + return nil, ErrNotImplemented +} + func RouteList(link Link, family int) ([]Route, error) { return nil, ErrNotImplemented } +func RouteListFiltered(family int, filter *Route, filterMask uint64) ([]Route, error) { + return nil, ErrNotImplemented +} + +func RouteReplace(route *Route) error { + return ErrNotImplemented +} + func XfrmPolicyAdd(policy *XfrmPolicy) error { return ErrNotImplemented } @@ -196,6 +240,10 @@ func XfrmPolicyList(family int) ([]XfrmPolicy, error) { return nil, ErrNotImplemented } +func XfrmPolicyGet(policy *XfrmPolicy) (*XfrmPolicy, error) { + return nil, ErrNotImplemented +} + func XfrmStateAdd(policy *XfrmState) error { return ErrNotImplemented } @@ -235,3 +283,7 @@ func NeighDeserialize(m []byte) (*Neigh, error) { func SocketGet(local, remote net.Addr) (*Socket, error) { return nil, ErrNotImplemented } + +func SocketDestroy(local, remote net.Addr) (*Socket, error) { + return nil, ErrNotImplemented +} diff --git a/vendor/github.com/vishvananda/netlink/netns_linux.go b/vendor/github.com/vishvananda/netlink/netns_linux.go index 77cf6f469..2eb29c7ce 100644 --- a/vendor/github.com/vishvananda/netlink/netns_linux.go +++ b/vendor/github.com/vishvananda/netlink/netns_linux.go @@ -87,7 +87,7 @@ func (h *Handle) getNetNsId(attrType int, val uint32) (int, error) { rtgen := nl.NewRtGenMsg() req.AddData(rtgen) - b := make([]byte, 4, 4) + b := make([]byte, 4) native.PutUint32(b, val) attr := nl.NewRtAttr(attrType, b) req.AddData(attr) @@ -126,12 +126,12 @@ func (h *Handle) setNetNsId(attrType int, val uint32, newnsid uint32) error { rtgen := nl.NewRtGenMsg() req.AddData(rtgen) - b := make([]byte, 4, 4) + b := make([]byte, 4) native.PutUint32(b, val) attr := nl.NewRtAttr(attrType, b) req.AddData(attr) - b1 := make([]byte, 4, 4) + b1 := make([]byte, 4) native.PutUint32(b1, newnsid) attr1 := nl.NewRtAttr(NETNSA_NSID, b1) req.AddData(attr1) diff --git a/vendor/github.com/vishvananda/netlink/nl/addr_linux.go b/vendor/github.com/vishvananda/netlink/nl/addr_linux.go index 50db3b4cd..6bea4ed02 100644 --- a/vendor/github.com/vishvananda/netlink/nl/addr_linux.go +++ b/vendor/github.com/vishvananda/netlink/nl/addr_linux.go @@ -54,24 +54,18 @@ func (msg *IfAddrmsg) Len() int { // __u32 tstamp; /* updated timestamp, hundredths of seconds */ // }; -const IFA_CACHEINFO = 6 -const SizeofIfaCacheInfo = 0x10 - type IfaCacheInfo struct { - IfaPrefered uint32 - IfaValid uint32 - Cstamp uint32 - Tstamp uint32 + unix.IfaCacheinfo } func (msg *IfaCacheInfo) Len() int { - return SizeofIfaCacheInfo + return unix.SizeofIfaCacheinfo } func DeserializeIfaCacheInfo(b []byte) *IfaCacheInfo { - return (*IfaCacheInfo)(unsafe.Pointer(&b[0:SizeofIfaCacheInfo][0])) + return (*IfaCacheInfo)(unsafe.Pointer(&b[0:unix.SizeofIfaCacheinfo][0])) } func (msg *IfaCacheInfo) Serialize() []byte { - return (*(*[SizeofIfaCacheInfo]byte)(unsafe.Pointer(msg)))[:] + return (*(*[unix.SizeofIfaCacheinfo]byte)(unsafe.Pointer(msg)))[:] } diff --git a/vendor/github.com/vishvananda/netlink/nl/conntrack_linux.go b/vendor/github.com/vishvananda/netlink/nl/conntrack_linux.go index 79d2b6b89..6989d1edc 100644 --- a/vendor/github.com/vishvananda/netlink/nl/conntrack_linux.go +++ b/vendor/github.com/vishvananda/netlink/nl/conntrack_linux.go @@ -15,6 +15,38 @@ var L4ProtoMap = map[uint8]string{ 17: "udp", } +// From https://git.netfilter.org/libnetfilter_conntrack/tree/include/libnetfilter_conntrack/libnetfilter_conntrack_tcp.h +// enum tcp_state { +// TCP_CONNTRACK_NONE, +// TCP_CONNTRACK_SYN_SENT, +// TCP_CONNTRACK_SYN_RECV, +// TCP_CONNTRACK_ESTABLISHED, +// TCP_CONNTRACK_FIN_WAIT, +// TCP_CONNTRACK_CLOSE_WAIT, +// TCP_CONNTRACK_LAST_ACK, +// TCP_CONNTRACK_TIME_WAIT, +// TCP_CONNTRACK_CLOSE, +// TCP_CONNTRACK_LISTEN, /* obsolete */ +// #define TCP_CONNTRACK_SYN_SENT2 TCP_CONNTRACK_LISTEN +// TCP_CONNTRACK_MAX, +// TCP_CONNTRACK_IGNORE +// }; +const ( + TCP_CONNTRACK_NONE = 0 + TCP_CONNTRACK_SYN_SENT = 1 + TCP_CONNTRACK_SYN_RECV = 2 + TCP_CONNTRACK_ESTABLISHED = 3 + TCP_CONNTRACK_FIN_WAIT = 4 + TCP_CONNTRACK_CLOSE_WAIT = 5 + TCP_CONNTRACK_LAST_ACK = 6 + TCP_CONNTRACK_TIME_WAIT = 7 + TCP_CONNTRACK_CLOSE = 8 + TCP_CONNTRACK_LISTEN = 9 + TCP_CONNTRACK_SYN_SENT2 = 9 + TCP_CONNTRACK_MAX = 10 + TCP_CONNTRACK_IGNORE = 11 +) + // All the following constants are coming from: // https://github.com/torvalds/linux/blob/master/include/uapi/linux/netfilter/nfnetlink_conntrack.h @@ -31,6 +63,7 @@ var L4ProtoMap = map[uint8]string{ // IPCTNL_MSG_MAX // }; const ( + IPCTNL_MSG_CT_NEW = 0 IPCTNL_MSG_CT_GET = 1 IPCTNL_MSG_CT_DELETE = 2 ) @@ -40,9 +73,11 @@ const ( NFNETLINK_V0 = 0 ) -// #define NLA_F_NESTED (1 << 15) const ( - NLA_F_NESTED = (1 << 15) + NLA_F_NESTED uint16 = (1 << 15) // #define NLA_F_NESTED (1 << 15) + NLA_F_NET_BYTEORDER uint16 = (1 << 14) // #define NLA_F_NESTED (1 << 14) + NLA_TYPE_MASK = ^(NLA_F_NESTED | NLA_F_NET_BYTEORDER) + NLA_ALIGNTO uint16 = 4 // #define NLA_ALIGNTO 4 ) // enum ctattr_type { @@ -86,7 +121,10 @@ const ( CTA_COUNTERS_REPLY = 10 CTA_USE = 11 CTA_ID = 12 + CTA_ZONE = 18 CTA_TIMESTAMP = 20 + CTA_LABELS = 22 + CTA_LABELS_MASK = 23 ) // enum ctattr_tuple { @@ -147,7 +185,10 @@ const ( // }; // #define CTA_PROTOINFO_MAX (__CTA_PROTOINFO_MAX - 1) const ( + CTA_PROTOINFO_UNSPEC = 0 CTA_PROTOINFO_TCP = 1 + CTA_PROTOINFO_DCCP = 2 + CTA_PROTOINFO_SCTP = 3 ) // enum ctattr_protoinfo_tcp { diff --git a/vendor/github.com/vishvananda/netlink/nl/devlink_linux.go b/vendor/github.com/vishvananda/netlink/nl/devlink_linux.go index db66faaad..956367b29 100644 --- a/vendor/github.com/vishvananda/netlink/nl/devlink_linux.go +++ b/vendor/github.com/vishvananda/netlink/nl/devlink_linux.go @@ -9,17 +9,56 @@ const ( ) const ( - DEVLINK_CMD_GET = 1 - DEVLINK_CMD_ESWITCH_GET = 29 - DEVLINK_CMD_ESWITCH_SET = 30 + DEVLINK_CMD_GET = 1 + DEVLINK_CMD_PORT_GET = 5 + DEVLINK_CMD_PORT_SET = 6 + DEVLINK_CMD_PORT_NEW = 7 + DEVLINK_CMD_PORT_DEL = 8 + DEVLINK_CMD_ESWITCH_GET = 29 + DEVLINK_CMD_ESWITCH_SET = 30 + DEVLINK_CMD_RESOURCE_DUMP = 36 + DEVLINK_CMD_PARAM_GET = 38 + DEVLINK_CMD_PARAM_SET = 39 + DEVLINK_CMD_INFO_GET = 51 ) const ( - DEVLINK_ATTR_BUS_NAME = 1 - DEVLINK_ATTR_DEV_NAME = 2 - DEVLINK_ATTR_ESWITCH_MODE = 25 - DEVLINK_ATTR_ESWITCH_INLINE_MODE = 26 - DEVLINK_ATTR_ESWITCH_ENCAP_MODE = 62 + DEVLINK_ATTR_BUS_NAME = 1 + DEVLINK_ATTR_DEV_NAME = 2 + DEVLINK_ATTR_PORT_INDEX = 3 + DEVLINK_ATTR_PORT_TYPE = 4 + DEVLINK_ATTR_PORT_NETDEV_IFINDEX = 6 + DEVLINK_ATTR_PORT_NETDEV_NAME = 7 + DEVLINK_ATTR_PORT_IBDEV_NAME = 8 + DEVLINK_ATTR_ESWITCH_MODE = 25 + DEVLINK_ATTR_ESWITCH_INLINE_MODE = 26 + DEVLINK_ATTR_ESWITCH_ENCAP_MODE = 62 + DEVLINK_ATTR_RESOURCE_LIST = 63 /* nested */ + DEVLINK_ATTR_RESOURCE = 64 /* nested */ + DEVLINK_ATTR_RESOURCE_NAME = 65 /* string */ + DEVLINK_ATTR_RESOURCE_ID = 66 /* u64 */ + DEVLINK_ATTR_RESOURCE_SIZE = 67 /* u64 */ + DEVLINK_ATTR_RESOURCE_SIZE_NEW = 68 /* u64 */ + DEVLINK_ATTR_RESOURCE_SIZE_VALID = 69 /* u8 */ + DEVLINK_ATTR_RESOURCE_SIZE_MIN = 70 /* u64 */ + DEVLINK_ATTR_RESOURCE_SIZE_MAX = 71 /* u64 */ + DEVLINK_ATTR_RESOURCE_SIZE_GRAN = 72 /* u64 */ + DEVLINK_ATTR_RESOURCE_UNIT = 73 /* u8 */ + DEVLINK_ATTR_RESOURCE_OCC = 74 /* u64 */ + DEVLINK_ATTR_DPIPE_TABLE_RESOURCE_ID = 75 /* u64 */ + DEVLINK_ATTR_DPIPE_TABLE_RESOURCE_UNITS = 76 /* u64 */ + DEVLINK_ATTR_PORT_FLAVOUR = 77 + DEVLINK_ATTR_INFO_DRIVER_NAME = 98 + DEVLINK_ATTR_INFO_SERIAL_NUMBER = 99 + DEVLINK_ATTR_INFO_VERSION_FIXED = 100 + DEVLINK_ATTR_INFO_VERSION_RUNNING = 101 + DEVLINK_ATTR_INFO_VERSION_STORED = 102 + DEVLINK_ATTR_INFO_VERSION_NAME = 103 + DEVLINK_ATTR_INFO_VERSION_VALUE = 104 + DEVLINK_ATTR_PORT_PCI_PF_NUMBER = 127 + DEVLINK_ATTR_PORT_FUNCTION = 145 + DEVLINK_ATTR_PORT_CONTROLLER_NUMBER = 150 + DEVLINK_ATTR_PORT_PCI_SF_NUMBER = 164 ) const ( @@ -38,3 +77,66 @@ const ( DEVLINK_ESWITCH_ENCAP_MODE_NONE = 0 DEVLINK_ESWITCH_ENCAP_MODE_BASIC = 1 ) + +const ( + DEVLINK_PORT_FLAVOUR_PHYSICAL = 0 + DEVLINK_PORT_FLAVOUR_CPU = 1 + DEVLINK_PORT_FLAVOUR_DSA = 2 + DEVLINK_PORT_FLAVOUR_PCI_PF = 3 + DEVLINK_PORT_FLAVOUR_PCI_VF = 4 + DEVLINK_PORT_FLAVOUR_VIRTUAL = 5 + DEVLINK_PORT_FLAVOUR_UNUSED = 6 + DEVLINK_PORT_FLAVOUR_PCI_SF = 7 +) + +const ( + DEVLINK_PORT_TYPE_NOTSET = 0 + DEVLINK_PORT_TYPE_AUTO = 1 + DEVLINK_PORT_TYPE_ETH = 2 + DEVLINK_PORT_TYPE_IB = 3 +) + +const ( + DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR = 1 + DEVLINK_PORT_FN_ATTR_STATE = 2 + DEVLINK_PORT_FN_ATTR_OPSTATE = 3 +) + +const ( + DEVLINK_PORT_FN_STATE_INACTIVE = 0 + DEVLINK_PORT_FN_STATE_ACTIVE = 1 +) + +const ( + DEVLINK_PORT_FN_OPSTATE_DETACHED = 0 + DEVLINK_PORT_FN_OPSTATE_ATTACHED = 1 +) + +const ( + DEVLINK_RESOURCE_UNIT_ENTRY uint8 = 0 +) + +const ( + DEVLINK_ATTR_PARAM = iota + 80 /* nested */ + DEVLINK_ATTR_PARAM_NAME /* string */ + DEVLINK_ATTR_PARAM_GENERIC /* flag */ + DEVLINK_ATTR_PARAM_TYPE /* u8 */ + DEVLINK_ATTR_PARAM_VALUES_LIST /* nested */ + DEVLINK_ATTR_PARAM_VALUE /* nested */ + DEVLINK_ATTR_PARAM_VALUE_DATA /* dynamic */ + DEVLINK_ATTR_PARAM_VALUE_CMODE /* u8 */ +) + +const ( + DEVLINK_PARAM_TYPE_U8 = 1 + DEVLINK_PARAM_TYPE_U16 = 2 + DEVLINK_PARAM_TYPE_U32 = 3 + DEVLINK_PARAM_TYPE_STRING = 5 + DEVLINK_PARAM_TYPE_BOOL = 6 +) + +const ( + DEVLINK_PARAM_CMODE_RUNTIME = iota + DEVLINK_PARAM_CMODE_DRIVERINIT + DEVLINK_PARAM_CMODE_PERMANENT +) diff --git a/vendor/github.com/vishvananda/netlink/nl/ip6tnl_linux.go b/vendor/github.com/vishvananda/netlink/nl/ip6tnl_linux.go new file mode 100644 index 000000000..d5dd69e0c --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/nl/ip6tnl_linux.go @@ -0,0 +1,21 @@ +package nl + +// id's of route attribute from https://elixir.bootlin.com/linux/v5.17.3/source/include/uapi/linux/lwtunnel.h#L38 +// the value's size are specified in https://elixir.bootlin.com/linux/v5.17.3/source/net/ipv4/ip_tunnel_core.c#L928 + +const ( + LWTUNNEL_IP6_UNSPEC = iota + LWTUNNEL_IP6_ID + LWTUNNEL_IP6_DST + LWTUNNEL_IP6_SRC + LWTUNNEL_IP6_HOPLIMIT + LWTUNNEL_IP6_TC + LWTUNNEL_IP6_FLAGS + LWTUNNEL_IP6_PAD // not implemented + LWTUNNEL_IP6_OPTS // not implemented + __LWTUNNEL_IP6_MAX +) + + + + diff --git a/vendor/github.com/vishvananda/netlink/nl/ipset_linux.go b/vendor/github.com/vishvananda/netlink/nl/ipset_linux.go new file mode 100644 index 000000000..89dd009df --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/nl/ipset_linux.go @@ -0,0 +1,227 @@ +package nl + +import ( + "strconv" + + "golang.org/x/sys/unix" +) + +const ( + /* The protocol version */ + IPSET_PROTOCOL = 6 + + /* The max length of strings including NUL: set and type identifiers */ + IPSET_MAXNAMELEN = 32 + + /* The maximum permissible comment length we will accept over netlink */ + IPSET_MAX_COMMENT_SIZE = 255 +) + +const ( + _ = iota + IPSET_CMD_PROTOCOL /* 1: Return protocol version */ + IPSET_CMD_CREATE /* 2: Create a new (empty) set */ + IPSET_CMD_DESTROY /* 3: Destroy a (empty) set */ + IPSET_CMD_FLUSH /* 4: Remove all elements from a set */ + IPSET_CMD_RENAME /* 5: Rename a set */ + IPSET_CMD_SWAP /* 6: Swap two sets */ + IPSET_CMD_LIST /* 7: List sets */ + IPSET_CMD_SAVE /* 8: Save sets */ + IPSET_CMD_ADD /* 9: Add an element to a set */ + IPSET_CMD_DEL /* 10: Delete an element from a set */ + IPSET_CMD_TEST /* 11: Test an element in a set */ + IPSET_CMD_HEADER /* 12: Get set header data only */ + IPSET_CMD_TYPE /* 13: Get set type */ +) + +/* Attributes at command level */ +const ( + _ = iota + IPSET_ATTR_PROTOCOL /* 1: Protocol version */ + IPSET_ATTR_SETNAME /* 2: Name of the set */ + IPSET_ATTR_TYPENAME /* 3: Typename */ + IPSET_ATTR_REVISION /* 4: Settype revision */ + IPSET_ATTR_FAMILY /* 5: Settype family */ + IPSET_ATTR_FLAGS /* 6: Flags at command level */ + IPSET_ATTR_DATA /* 7: Nested attributes */ + IPSET_ATTR_ADT /* 8: Multiple data containers */ + IPSET_ATTR_LINENO /* 9: Restore lineno */ + IPSET_ATTR_PROTOCOL_MIN /* 10: Minimal supported version number */ + + IPSET_ATTR_SETNAME2 = IPSET_ATTR_TYPENAME /* Setname at rename/swap */ + IPSET_ATTR_REVISION_MIN = IPSET_ATTR_PROTOCOL_MIN /* type rev min */ +) + +/* CADT specific attributes */ +const ( + IPSET_ATTR_IP = 1 + IPSET_ATTR_IP_FROM = 1 + IPSET_ATTR_IP_TO = 2 + IPSET_ATTR_CIDR = 3 + IPSET_ATTR_PORT = 4 + IPSET_ATTR_PORT_FROM = 4 + IPSET_ATTR_PORT_TO = 5 + IPSET_ATTR_TIMEOUT = 6 + IPSET_ATTR_PROTO = 7 + IPSET_ATTR_CADT_FLAGS = 8 + IPSET_ATTR_CADT_LINENO = IPSET_ATTR_LINENO /* 9 */ + IPSET_ATTR_MARK = 10 + IPSET_ATTR_MARKMASK = 11 + + /* Reserve empty slots */ + IPSET_ATTR_CADT_MAX = 16 + + /* Create-only specific attributes */ + IPSET_ATTR_GC = 3 + iota + IPSET_ATTR_HASHSIZE + IPSET_ATTR_MAXELEM + IPSET_ATTR_NETMASK + IPSET_ATTR_PROBES + IPSET_ATTR_RESIZE + IPSET_ATTR_SIZE + + /* Kernel-only */ + IPSET_ATTR_ELEMENTS + IPSET_ATTR_REFERENCES + IPSET_ATTR_MEMSIZE + + SET_ATTR_CREATE_MAX +) + +const ( + IPSET_ATTR_IPADDR_IPV4 = 1 + IPSET_ATTR_IPADDR_IPV6 = 2 +) + +/* ADT specific attributes */ +const ( + IPSET_ATTR_ETHER = IPSET_ATTR_CADT_MAX + iota + 1 + IPSET_ATTR_NAME + IPSET_ATTR_NAMEREF + IPSET_ATTR_IP2 + IPSET_ATTR_CIDR2 + IPSET_ATTR_IP2_TO + IPSET_ATTR_IFACE + IPSET_ATTR_BYTES + IPSET_ATTR_PACKETS + IPSET_ATTR_COMMENT + IPSET_ATTR_SKBMARK + IPSET_ATTR_SKBPRIO + IPSET_ATTR_SKBQUEUE +) + +/* Flags at CADT attribute level, upper half of cmdattrs */ +const ( + IPSET_FLAG_BIT_BEFORE = 0 + IPSET_FLAG_BEFORE = (1 << IPSET_FLAG_BIT_BEFORE) + IPSET_FLAG_BIT_PHYSDEV = 1 + IPSET_FLAG_PHYSDEV = (1 << IPSET_FLAG_BIT_PHYSDEV) + IPSET_FLAG_BIT_NOMATCH = 2 + IPSET_FLAG_NOMATCH = (1 << IPSET_FLAG_BIT_NOMATCH) + IPSET_FLAG_BIT_WITH_COUNTERS = 3 + IPSET_FLAG_WITH_COUNTERS = (1 << IPSET_FLAG_BIT_WITH_COUNTERS) + IPSET_FLAG_BIT_WITH_COMMENT = 4 + IPSET_FLAG_WITH_COMMENT = (1 << IPSET_FLAG_BIT_WITH_COMMENT) + IPSET_FLAG_BIT_WITH_FORCEADD = 5 + IPSET_FLAG_WITH_FORCEADD = (1 << IPSET_FLAG_BIT_WITH_FORCEADD) + IPSET_FLAG_BIT_WITH_SKBINFO = 6 + IPSET_FLAG_WITH_SKBINFO = (1 << IPSET_FLAG_BIT_WITH_SKBINFO) + IPSET_FLAG_CADT_MAX = 15 +) + +const ( + IPSET_ERR_PRIVATE = 4096 + iota + IPSET_ERR_PROTOCOL + IPSET_ERR_FIND_TYPE + IPSET_ERR_MAX_SETS + IPSET_ERR_BUSY + IPSET_ERR_EXIST_SETNAME2 + IPSET_ERR_TYPE_MISMATCH + IPSET_ERR_EXIST + IPSET_ERR_INVALID_CIDR + IPSET_ERR_INVALID_NETMASK + IPSET_ERR_INVALID_FAMILY + IPSET_ERR_TIMEOUT + IPSET_ERR_REFERENCED + IPSET_ERR_IPADDR_IPV4 + IPSET_ERR_IPADDR_IPV6 + IPSET_ERR_COUNTER + IPSET_ERR_COMMENT + IPSET_ERR_INVALID_MARKMASK + IPSET_ERR_SKBINFO + + /* Type specific error codes */ + IPSET_ERR_TYPE_SPECIFIC = 4352 +) + +type IPSetError uintptr + +func (e IPSetError) Error() string { + switch int(e) { + case IPSET_ERR_PRIVATE: + return "private" + case IPSET_ERR_PROTOCOL: + return "invalid protocol" + case IPSET_ERR_FIND_TYPE: + return "invalid type" + case IPSET_ERR_MAX_SETS: + return "max sets reached" + case IPSET_ERR_BUSY: + return "busy" + case IPSET_ERR_EXIST_SETNAME2: + return "exist_setname2" + case IPSET_ERR_TYPE_MISMATCH: + return "type mismatch" + case IPSET_ERR_EXIST: + return "exist" + case IPSET_ERR_INVALID_CIDR: + return "invalid cidr" + case IPSET_ERR_INVALID_NETMASK: + return "invalid netmask" + case IPSET_ERR_INVALID_FAMILY: + return "invalid family" + case IPSET_ERR_TIMEOUT: + return "timeout" + case IPSET_ERR_REFERENCED: + return "referenced" + case IPSET_ERR_IPADDR_IPV4: + return "invalid ipv4 address" + case IPSET_ERR_IPADDR_IPV6: + return "invalid ipv6 address" + case IPSET_ERR_COUNTER: + return "invalid counter" + case IPSET_ERR_COMMENT: + return "invalid comment" + case IPSET_ERR_INVALID_MARKMASK: + return "invalid markmask" + case IPSET_ERR_SKBINFO: + return "skbinfo" + default: + return "errno " + strconv.Itoa(int(e)) + } +} + +func GetIpsetFlags(cmd int) int { + switch cmd { + case IPSET_CMD_CREATE: + return unix.NLM_F_REQUEST | unix.NLM_F_ACK | unix.NLM_F_CREATE + case IPSET_CMD_DESTROY, + IPSET_CMD_FLUSH, + IPSET_CMD_RENAME, + IPSET_CMD_SWAP, + IPSET_CMD_TEST: + return unix.NLM_F_REQUEST | unix.NLM_F_ACK + case IPSET_CMD_LIST, + IPSET_CMD_SAVE: + return unix.NLM_F_REQUEST | unix.NLM_F_ACK | unix.NLM_F_ROOT | unix.NLM_F_MATCH | unix.NLM_F_DUMP + case IPSET_CMD_ADD, + IPSET_CMD_DEL: + return unix.NLM_F_REQUEST | unix.NLM_F_ACK + case IPSET_CMD_HEADER, + IPSET_CMD_TYPE, + IPSET_CMD_PROTOCOL: + return unix.NLM_F_REQUEST + default: + return 0 + } +} diff --git a/vendor/github.com/vishvananda/netlink/nl/link_linux.go b/vendor/github.com/vishvananda/netlink/nl/link_linux.go index afb16a9c1..0b5be470c 100644 --- a/vendor/github.com/vishvananda/netlink/nl/link_linux.go +++ b/vendor/github.com/vishvananda/netlink/nl/link_linux.go @@ -1,6 +1,9 @@ package nl import ( + "bytes" + "encoding/binary" + "fmt" "unsafe" ) @@ -28,6 +31,16 @@ const ( IFLA_VLAN_MAX = IFLA_VLAN_PROTOCOL ) +const ( + IFLA_NETKIT_UNSPEC = iota + IFLA_NETKIT_PEER_INFO + IFLA_NETKIT_PRIMARY + IFLA_NETKIT_POLICY + IFLA_NETKIT_PEER_POLICY + IFLA_NETKIT_MODE + IFLA_NETKIT_MAX = IFLA_NETKIT_MODE +) + const ( VETH_INFO_UNSPEC = iota VETH_INFO_PEER @@ -83,7 +96,37 @@ const ( IFLA_BRPORT_PROXYARP IFLA_BRPORT_LEARNING_SYNC IFLA_BRPORT_PROXYARP_WIFI - IFLA_BRPORT_MAX = IFLA_BRPORT_PROXYARP_WIFI + IFLA_BRPORT_ROOT_ID + IFLA_BRPORT_BRIDGE_ID + IFLA_BRPORT_DESIGNATED_PORT + IFLA_BRPORT_DESIGNATED_COST + IFLA_BRPORT_ID + IFLA_BRPORT_NO + IFLA_BRPORT_TOPOLOGY_CHANGE_ACK + IFLA_BRPORT_CONFIG_PENDING + IFLA_BRPORT_MESSAGE_AGE_TIMER + IFLA_BRPORT_FORWARD_DELAY_TIMER + IFLA_BRPORT_HOLD_TIMER + IFLA_BRPORT_FLUSH + IFLA_BRPORT_MULTICAST_ROUTER + IFLA_BRPORT_PAD + IFLA_BRPORT_MCAST_FLOOD + IFLA_BRPORT_MCAST_TO_UCAST + IFLA_BRPORT_VLAN_TUNNEL + IFLA_BRPORT_BCAST_FLOOD + IFLA_BRPORT_GROUP_FWD_MASK + IFLA_BRPORT_NEIGH_SUPPRESS + IFLA_BRPORT_ISOLATED + IFLA_BRPORT_BACKUP_PORT + IFLA_BRPORT_MRP_RING_OPEN + IFLA_BRPORT_MRP_IN_OPEN + IFLA_BRPORT_MCAST_EHT_HOSTS_LIMIT + IFLA_BRPORT_MCAST_EHT_HOSTS_CNT + IFLA_BRPORT_LOCKED + IFLA_BRPORT_MAB + IFLA_BRPORT_MCAST_N_GROUPS + IFLA_BRPORT_MCAST_MAX_GROUPS + IFLA_BRPORT_MAX = IFLA_BRPORT_MCAST_MAX_GROUPS ) const ( @@ -101,7 +144,9 @@ const ( IFLA_MACVLAN_MACADDR IFLA_MACVLAN_MACADDR_DATA IFLA_MACVLAN_MACADDR_COUNT - IFLA_MACVLAN_MAX = IFLA_MACVLAN_FLAGS + IFLA_MACVLAN_BC_QUEUE_LEN + IFLA_MACVLAN_BC_QUEUE_LEN_USED + IFLA_MACVLAN_MAX = IFLA_MACVLAN_BC_QUEUE_LEN_USED ) const ( @@ -171,6 +216,25 @@ const ( IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE ) +const ( + IFLA_GENEVE_UNSPEC = iota + IFLA_GENEVE_ID // vni + IFLA_GENEVE_REMOTE + IFLA_GENEVE_TTL + IFLA_GENEVE_TOS + IFLA_GENEVE_PORT // destination port + IFLA_GENEVE_COLLECT_METADATA + IFLA_GENEVE_REMOTE6 + IFLA_GENEVE_UDP_CSUM + IFLA_GENEVE_UDP_ZERO_CSUM6_TX + IFLA_GENEVE_UDP_ZERO_CSUM6_RX + IFLA_GENEVE_LABEL + IFLA_GENEVE_TTL_INHERIT + IFLA_GENEVE_DF + IFLA_GENEVE_INNER_PROTO_INHERIT + IFLA_GENEVE_MAX = IFLA_GENEVE_INNER_PROTO_INHERIT +) + const ( IFLA_GRE_UNSPEC = iota IFLA_GRE_LINK @@ -226,7 +290,15 @@ const ( IFLA_VF_TRUST /* Trust state of VF */ IFLA_VF_IB_NODE_GUID /* VF Infiniband node GUID */ IFLA_VF_IB_PORT_GUID /* VF Infiniband port GUID */ - IFLA_VF_MAX = IFLA_VF_IB_PORT_GUID + IFLA_VF_VLAN_LIST /* nested list of vlans, option for QinQ */ + + IFLA_VF_MAX = IFLA_VF_IB_PORT_GUID +) + +const ( + IFLA_VF_VLAN_INFO_UNSPEC = iota + IFLA_VF_VLAN_INFO /* VLAN ID, QoS and VLAN protocol */ + __IFLA_VF_VLAN_INFO_MAX ) const ( @@ -243,12 +315,15 @@ const ( IFLA_VF_STATS_TX_BYTES IFLA_VF_STATS_BROADCAST IFLA_VF_STATS_MULTICAST - IFLA_VF_STATS_MAX = IFLA_VF_STATS_MULTICAST + IFLA_VF_STATS_RX_DROPPED + IFLA_VF_STATS_TX_DROPPED + IFLA_VF_STATS_MAX = IFLA_VF_STATS_TX_DROPPED ) const ( SizeofVfMac = 0x24 SizeofVfVlan = 0x0c + SizeofVfVlanInfo = 0x10 SizeofVfTxRate = 0x08 SizeofVfRate = 0x0c SizeofVfSpoofchk = 0x08 @@ -304,6 +379,49 @@ func (msg *VfVlan) Serialize() []byte { return (*(*[SizeofVfVlan]byte)(unsafe.Pointer(msg)))[:] } +func DeserializeVfVlanList(b []byte) ([]*VfVlanInfo, error) { + var vfVlanInfoList []*VfVlanInfo + attrs, err := ParseRouteAttr(b) + if err != nil { + return nil, err + } + + for _, element := range attrs { + if element.Attr.Type == IFLA_VF_VLAN_INFO { + vfVlanInfoList = append(vfVlanInfoList, DeserializeVfVlanInfo(element.Value)) + } + } + + if len(vfVlanInfoList) == 0 { + return nil, fmt.Errorf("VF vlan list is defined but no vf vlan info elements were found") + } + + return vfVlanInfoList, nil +} + +// struct ifla_vf_vlan_info { +// __u32 vf; +// __u32 vlan; /* 0 - 4095, 0 disables VLAN filter */ +// __u32 qos; +// __be16 vlan_proto; /* VLAN protocol either 802.1Q or 802.1ad */ +// }; + +type VfVlanInfo struct { + VfVlan + VlanProto uint16 +} + +func DeserializeVfVlanInfo(b []byte) *VfVlanInfo { + return &VfVlanInfo{ + *(*VfVlan)(unsafe.Pointer(&b[0:SizeofVfVlan][0])), + binary.BigEndian.Uint16(b[SizeofVfVlan:SizeofVfVlanInfo]), + } +} + +func (msg *VfVlanInfo) Serialize() []byte { + return (*(*[SizeofVfVlanInfo]byte)(unsafe.Pointer(msg)))[:] +} + // struct ifla_vf_tx_rate { // __u32 vf; // __u32 rate; /* Max TX bandwidth in Mbps, 0 disables throttling */ @@ -326,6 +444,59 @@ func (msg *VfTxRate) Serialize() []byte { return (*(*[SizeofVfTxRate]byte)(unsafe.Pointer(msg)))[:] } +//struct ifla_vf_stats { +// __u64 rx_packets; +// __u64 tx_packets; +// __u64 rx_bytes; +// __u64 tx_bytes; +// __u64 broadcast; +// __u64 multicast; +//}; + +type VfStats struct { + RxPackets uint64 + TxPackets uint64 + RxBytes uint64 + TxBytes uint64 + Multicast uint64 + Broadcast uint64 + RxDropped uint64 + TxDropped uint64 +} + +func DeserializeVfStats(b []byte) VfStats { + var vfstat VfStats + stats, err := ParseRouteAttr(b) + if err != nil { + return vfstat + } + var valueVar uint64 + for _, stat := range stats { + if err := binary.Read(bytes.NewBuffer(stat.Value), NativeEndian(), &valueVar); err != nil { + break + } + switch stat.Attr.Type { + case IFLA_VF_STATS_RX_PACKETS: + vfstat.RxPackets = valueVar + case IFLA_VF_STATS_TX_PACKETS: + vfstat.TxPackets = valueVar + case IFLA_VF_STATS_RX_BYTES: + vfstat.RxBytes = valueVar + case IFLA_VF_STATS_TX_BYTES: + vfstat.TxBytes = valueVar + case IFLA_VF_STATS_MULTICAST: + vfstat.Multicast = valueVar + case IFLA_VF_STATS_BROADCAST: + vfstat.Broadcast = valueVar + case IFLA_VF_STATS_RX_DROPPED: + vfstat.RxDropped = valueVar + case IFLA_VF_STATS_TX_DROPPED: + vfstat.TxDropped = valueVar + } + } + return vfstat +} + // struct ifla_vf_rate { // __u32 vf; // __u32 min_tx_rate; /* Min Bandwidth in Mbps */ @@ -478,6 +649,14 @@ const ( IFLA_XDP_MAX = IFLA_XDP_PROG_ID ) +// XDP program attach mode (used as dump value for IFLA_XDP_ATTACHED) +const ( + XDP_ATTACHED_NONE = iota + XDP_ATTACHED_DRV + XDP_ATTACHED_SKB + XDP_ATTACHED_HW +) + const ( IFLA_IPTUN_UNSPEC = iota IFLA_IPTUN_LINK @@ -608,3 +787,32 @@ const ( IFLA_IPOIB_UMCAST IFLA_IPOIB_MAX = IFLA_IPOIB_UMCAST ) + +const ( + IFLA_CAN_UNSPEC = iota + IFLA_CAN_BITTIMING + IFLA_CAN_BITTIMING_CONST + IFLA_CAN_CLOCK + IFLA_CAN_STATE + IFLA_CAN_CTRLMODE + IFLA_CAN_RESTART_MS + IFLA_CAN_RESTART + IFLA_CAN_BERR_COUNTER + IFLA_CAN_DATA_BITTIMING + IFLA_CAN_DATA_BITTIMING_CONST + IFLA_CAN_TERMINATION + IFLA_CAN_TERMINATION_CONST + IFLA_CAN_BITRATE_CONST + IFLA_CAN_DATA_BITRATE_CONST + IFLA_CAN_BITRATE_MAX + IFLA_CAN_MAX = IFLA_CAN_BITRATE_MAX +) + +const ( + IFLA_BAREUDP_UNSPEC = iota + IFLA_BAREUDP_PORT + IFLA_BAREUDP_ETHERTYPE + IFLA_BAREUDP_SRCPORT_MIN + IFLA_BAREUDP_MULTIPROTO_MODE + IFLA_BAREUDP_MAX = IFLA_BAREUDP_MULTIPROTO_MODE +) diff --git a/vendor/github.com/vishvananda/netlink/nl/lwt_linux.go b/vendor/github.com/vishvananda/netlink/nl/lwt_linux.go new file mode 100644 index 000000000..bafd593c4 --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/nl/lwt_linux.go @@ -0,0 +1,29 @@ +package nl + +const ( + LWT_BPF_PROG_UNSPEC = iota + LWT_BPF_PROG_FD + LWT_BPF_PROG_NAME + __LWT_BPF_PROG_MAX +) + +const ( + LWT_BPF_PROG_MAX = __LWT_BPF_PROG_MAX - 1 +) + +const ( + LWT_BPF_UNSPEC = iota + LWT_BPF_IN + LWT_BPF_OUT + LWT_BPF_XMIT + LWT_BPF_XMIT_HEADROOM + __LWT_BPF_MAX +) + +const ( + LWT_BPF_MAX = __LWT_BPF_MAX - 1 +) + +const ( + LWT_BPF_MAX_HEADROOM = 256 +) diff --git a/vendor/github.com/vishvananda/netlink/nl/nl_linux.go b/vendor/github.com/vishvananda/netlink/nl/nl_linux.go index aaf56c671..6cecc4517 100644 --- a/vendor/github.com/vishvananda/netlink/nl/nl_linux.go +++ b/vendor/github.com/vishvananda/netlink/nl/nl_linux.go @@ -6,6 +6,7 @@ import ( "encoding/binary" "fmt" "net" + "os" "runtime" "sync" "sync/atomic" @@ -27,7 +28,8 @@ const ( // tc rules or filters, or other more memory requiring data. RECEIVE_BUFFER_SIZE = 65536 // Kernel netlink pid - PidKernel uint32 = 0 + PidKernel uint32 = 0 + SizeofCnMsgOp = 0x18 ) // SupportedNlFamilies contains the list of netlink families this netlink package supports @@ -35,6 +37,12 @@ var SupportedNlFamilies = []int{unix.NETLINK_ROUTE, unix.NETLINK_XFRM, unix.NETL var nextSeqNr uint32 +// Default netlink socket timeout, 60s +var SocketTimeoutTv = unix.Timeval{Sec: 60, Usec: 0} + +// ErrorMessageReporting is the default error message reporting configuration for the new netlink sockets +var EnableErrorMessageReporting bool = false + // GetIPFamily returns the family type of a net.IP. func GetIPFamily(ip net.IP) int { if len(ip) <= net.IPv4len { @@ -77,11 +85,69 @@ func Swap32(i uint32) uint32 { return (i&0xff000000)>>24 | (i&0xff0000)>>8 | (i&0xff00)<<8 | (i&0xff)<<24 } +const ( + NLMSGERR_ATTR_UNUSED = 0 + NLMSGERR_ATTR_MSG = 1 + NLMSGERR_ATTR_OFFS = 2 + NLMSGERR_ATTR_COOKIE = 3 + NLMSGERR_ATTR_POLICY = 4 +) + type NetlinkRequestData interface { Len() int Serialize() []byte } +const ( + PROC_CN_MCAST_LISTEN = 1 + PROC_CN_MCAST_IGNORE +) + +type CbID struct { + Idx uint32 + Val uint32 +} + +type CnMsg struct { + ID CbID + Seq uint32 + Ack uint32 + Length uint16 + Flags uint16 +} + +type CnMsgOp struct { + CnMsg + // here we differ from the C header + Op uint32 +} + +func NewCnMsg(idx, val, op uint32) *CnMsgOp { + var cm CnMsgOp + + cm.ID.Idx = idx + cm.ID.Val = val + + cm.Ack = 0 + cm.Seq = 1 + cm.Length = uint16(binary.Size(op)) + cm.Op = op + + return &cm +} + +func (msg *CnMsgOp) Serialize() []byte { + return (*(*[SizeofCnMsgOp]byte)(unsafe.Pointer(msg)))[:] +} + +func DeserializeCnMsgOp(b []byte) *CnMsgOp { + return (*CnMsgOp)(unsafe.Pointer(&b[0:SizeofCnMsgOp][0])) +} + +func (msg *CnMsgOp) Len() int { + return SizeofCnMsgOp +} + // IfInfomsg is related to links, but it is used for list requests as well type IfInfomsg struct { unix.IfInfomsg @@ -249,6 +315,12 @@ func (msg *IfInfomsg) EncapType() string { return fmt.Sprintf("unknown%d", msg.Type) } +// Round the length of a netlink message up to align it properly. +// Taken from syscall/netlink_linux.go by The Go Authors under BSD-style license. +func nlmAlignOf(msglen int) int { + return (msglen + syscall.NLMSG_ALIGNTO - 1) & ^(syscall.NLMSG_ALIGNTO - 1) +} + func rtaAlignOf(attrlen int) int { return (attrlen + unix.RTA_ALIGNTO - 1) & ^(unix.RTA_ALIGNTO - 1) } @@ -259,6 +331,42 @@ func NewIfInfomsgChild(parent *RtAttr, family int) *IfInfomsg { return msg } +type Uint32Bitfield struct { + Value uint32 + Selector uint32 +} + +func (a *Uint32Bitfield) Serialize() []byte { + return (*(*[SizeofUint32Bitfield]byte)(unsafe.Pointer(a)))[:] +} + +func DeserializeUint32Bitfield(data []byte) *Uint32Bitfield { + return (*Uint32Bitfield)(unsafe.Pointer(&data[0:SizeofUint32Bitfield][0])) +} + +type Uint32Attribute struct { + Type uint16 + Value uint32 +} + +func (a *Uint32Attribute) Serialize() []byte { + native := NativeEndian() + buf := make([]byte, rtaAlignOf(8)) + native.PutUint16(buf[0:2], 8) + native.PutUint16(buf[2:4], a.Type) + + if a.Type&NLA_F_NET_BYTEORDER != 0 { + binary.BigEndian.PutUint32(buf[4:], a.Value) + } else { + native.PutUint32(buf[4:], a.Value) + } + return buf +} + +func (a *Uint32Attribute) Len() int { + return 8 +} + // Extend RtAttr to handle data and children type RtAttr struct { unix.RtAttr @@ -381,10 +489,30 @@ func (req *NetlinkRequest) AddRawData(data []byte) { req.RawData = append(req.RawData, data...) } -// Execute the request against a the given sockType. +// Execute the request against the given sockType. // Returns a list of netlink messages in serialized format, optionally filtered // by resType. func (req *NetlinkRequest) Execute(sockType int, resType uint16) ([][]byte, error) { + var res [][]byte + err := req.ExecuteIter(sockType, resType, func(msg []byte) bool { + res = append(res, msg) + return true + }) + if err != nil { + return nil, err + } + return res, nil +} + +// ExecuteIter executes the request against the given sockType. +// Calls the provided callback func once for each netlink message. +// If the callback returns false, it is not called again, but +// the remaining messages are consumed/discarded. +// +// Thread safety: ExecuteIter holds a lock on the socket until +// it finishes iteration so the callback must not call back into +// the netlink API. +func (req *NetlinkRequest) ExecuteIter(sockType int, resType uint16, f func(msg []byte) bool) error { var ( s *NetlinkSocket err error @@ -401,8 +529,21 @@ func (req *NetlinkRequest) Execute(sockType int, resType uint16) ([][]byte, erro if s == nil { s, err = getNetlinkSocket(sockType) if err != nil { - return nil, err + return err } + + if err := s.SetSendTimeout(&SocketTimeoutTv); err != nil { + return err + } + if err := s.SetReceiveTimeout(&SocketTimeoutTv); err != nil { + return err + } + if EnableErrorMessageReporting { + if err := s.SetExtAck(true); err != nil { + return err + } + } + defer s.Close() } else { s.Lock() @@ -410,56 +551,94 @@ func (req *NetlinkRequest) Execute(sockType int, resType uint16) ([][]byte, erro } if err := s.Send(req); err != nil { - return nil, err + return err } pid, err := s.GetPid() if err != nil { - return nil, err + return err } - var res [][]byte - done: for { msgs, from, err := s.Receive() if err != nil { - return nil, err + return err } if from.Pid != PidKernel { - return nil, fmt.Errorf("Wrong sender portid %d, expected %d", from.Pid, PidKernel) + return fmt.Errorf("Wrong sender portid %d, expected %d", from.Pid, PidKernel) } for _, m := range msgs { if m.Header.Seq != req.Seq { if sharedSocket { continue } - return nil, fmt.Errorf("Wrong Seq nr %d, expected %d", m.Header.Seq, req.Seq) + return fmt.Errorf("Wrong Seq nr %d, expected %d", m.Header.Seq, req.Seq) } if m.Header.Pid != pid { continue } - if m.Header.Type == unix.NLMSG_DONE { - break done + + if m.Header.Flags&unix.NLM_F_DUMP_INTR != 0 { + return syscall.Errno(unix.EINTR) } - if m.Header.Type == unix.NLMSG_ERROR { + + if m.Header.Type == unix.NLMSG_DONE || m.Header.Type == unix.NLMSG_ERROR { + // NLMSG_DONE might have no payload, if so assume no error. + if m.Header.Type == unix.NLMSG_DONE && len(m.Data) == 0 { + break done + } + native := NativeEndian() - error := int32(native.Uint32(m.Data[0:4])) - if error == 0 { + errno := int32(native.Uint32(m.Data[0:4])) + if errno == 0 { break done } - return nil, syscall.Errno(-error) + var err error + err = syscall.Errno(-errno) + + unreadData := m.Data[4:] + if m.Header.Flags&unix.NLM_F_ACK_TLVS != 0 && len(unreadData) > syscall.SizeofNlMsghdr { + // Skip the echoed request message. + echoReqH := (*syscall.NlMsghdr)(unsafe.Pointer(&unreadData[0])) + unreadData = unreadData[nlmAlignOf(int(echoReqH.Len)):] + + // Annotate `err` using nlmsgerr attributes. + for len(unreadData) >= syscall.SizeofRtAttr { + attr := (*syscall.RtAttr)(unsafe.Pointer(&unreadData[0])) + attrData := unreadData[syscall.SizeofRtAttr:attr.Len] + + switch attr.Type { + case NLMSGERR_ATTR_MSG: + err = fmt.Errorf("%w: %s", err, unix.ByteSliceToString(attrData)) + default: + // TODO: handle other NLMSGERR_ATTR types + } + + unreadData = unreadData[rtaAlignOf(int(attr.Len)):] + } + } + + return err } if resType != 0 && m.Header.Type != resType { continue } - res = append(res, m.Data) + if cont := f(m.Data); !cont { + // Drain the rest of the messages from the kernel but don't + // pass them to the iterator func. + f = dummyMsgIterFunc + } if m.Header.Flags&unix.NLM_F_MULTI == 0 { break done } } } - return res, nil + return nil +} + +func dummyMsgIterFunc(msg []byte) bool { + return true } // Create a new netlink request from proto and flags @@ -477,8 +656,9 @@ func NewNetlinkRequest(proto, flags int) *NetlinkRequest { } type NetlinkSocket struct { - fd int32 - lsa unix.SockaddrNetlink + fd int32 + file *os.File + lsa unix.SockaddrNetlink sync.Mutex } @@ -487,8 +667,13 @@ func getNetlinkSocket(protocol int) (*NetlinkSocket, error) { if err != nil { return nil, err } + err = unix.SetNonblock(fd, true) + if err != nil { + return nil, err + } s := &NetlinkSocket{ - fd: int32(fd), + fd: int32(fd), + file: os.NewFile(uintptr(fd), "netlink"), } s.lsa.Family = unix.AF_NETLINK if err := unix.Bind(fd, &s.lsa); err != nil { @@ -519,12 +704,14 @@ func GetNetlinkSocketAt(newNs, curNs netns.NsHandle, protocol int) (*NetlinkSock // In case of success, the caller is expected to execute the returned function // at the end of the code that needs to be executed in the network namespace. // Example: -// func jobAt(...) error { -// d, err := executeInNetns(...) -// if err != nil { return err} -// defer d() -// < code which needs to be executed in specific netns> -// } +// +// func jobAt(...) error { +// d, err := executeInNetns(...) +// if err != nil { return err} +// defer d() +// < code which needs to be executed in specific netns> +// } +// // TODO: his function probably belongs to netns pkg. func executeInNetns(newNs, curNs netns.NsHandle) (func(), error) { var ( @@ -573,8 +760,13 @@ func Subscribe(protocol int, groups ...uint) (*NetlinkSocket, error) { if err != nil { return nil, err } + err = unix.SetNonblock(fd, true) + if err != nil { + return nil, err + } s := &NetlinkSocket{ - fd: int32(fd), + fd: int32(fd), + file: os.NewFile(uintptr(fd), "netlink"), } s.lsa.Family = unix.AF_NETLINK @@ -603,33 +795,36 @@ func SubscribeAt(newNs, curNs netns.NsHandle, protocol int, groups ...uint) (*Ne } func (s *NetlinkSocket) Close() { - fd := int(atomic.SwapInt32(&s.fd, -1)) - unix.Close(fd) + s.file.Close() } func (s *NetlinkSocket) GetFd() int { - return int(atomic.LoadInt32(&s.fd)) + return int(s.fd) } func (s *NetlinkSocket) Send(request *NetlinkRequest) error { - fd := int(atomic.LoadInt32(&s.fd)) - if fd < 0 { - return fmt.Errorf("Send called on a closed socket") - } - if err := unix.Sendto(fd, request.Serialize(), 0, &s.lsa); err != nil { - return err - } - return nil + return unix.Sendto(int(s.fd), request.Serialize(), 0, &s.lsa) } func (s *NetlinkSocket) Receive() ([]syscall.NetlinkMessage, *unix.SockaddrNetlink, error) { - fd := int(atomic.LoadInt32(&s.fd)) - if fd < 0 { - return nil, nil, fmt.Errorf("Receive called on a closed socket") + rawConn, err := s.file.SyscallConn() + if err != nil { + return nil, nil, err + } + var ( + fromAddr *unix.SockaddrNetlink + rb [RECEIVE_BUFFER_SIZE]byte + nr int + from unix.Sockaddr + innerErr error + ) + err = rawConn.Read(func(fd uintptr) (done bool) { + nr, from, innerErr = unix.Recvfrom(int(fd), rb[:], 0) + return innerErr != unix.EWOULDBLOCK + }) + if innerErr != nil { + err = innerErr } - var fromAddr *unix.SockaddrNetlink - var rb [RECEIVE_BUFFER_SIZE]byte - nr, from, err := unix.Recvfrom(fd, rb[:], 0) if err != nil { return nil, nil, err } @@ -640,8 +835,9 @@ func (s *NetlinkSocket) Receive() ([]syscall.NetlinkMessage, *unix.SockaddrNetli if nr < unix.NLMSG_HDRLEN { return nil, nil, fmt.Errorf("Got short response from netlink") } - rb2 := make([]byte, nr) - copy(rb2, rb[:nr]) + msgLen := nlmAlignOf(nr) + rb2 := make([]byte, msgLen) + copy(rb2, rb[:msgLen]) nl, err := syscall.ParseNetlinkMessage(rb2) if err != nil { return nil, nil, err @@ -663,9 +859,27 @@ func (s *NetlinkSocket) SetReceiveTimeout(timeout *unix.Timeval) error { return unix.SetsockoptTimeval(int(s.fd), unix.SOL_SOCKET, unix.SO_RCVTIMEO, timeout) } +// SetReceiveBufferSize allows to set a receive buffer size on the socket +func (s *NetlinkSocket) SetReceiveBufferSize(size int, force bool) error { + opt := unix.SO_RCVBUF + if force { + opt = unix.SO_RCVBUFFORCE + } + return unix.SetsockoptInt(int(s.fd), unix.SOL_SOCKET, opt, size) +} + +// SetExtAck requests error messages to be reported on the socket +func (s *NetlinkSocket) SetExtAck(enable bool) error { + var enableN int + if enable { + enableN = 1 + } + + return unix.SetsockoptInt(int(s.fd), unix.SOL_NETLINK, unix.NETLINK_EXT_ACK, enableN) +} + func (s *NetlinkSocket) GetPid() (uint32, error) { - fd := int(atomic.LoadInt32(&s.fd)) - lsa, err := unix.Getsockname(fd) + lsa, err := unix.Getsockname(int(s.fd)) if err != nil { return 0, err } @@ -709,6 +923,12 @@ func Uint16Attr(v uint16) []byte { return bytes } +func BEUint16Attr(v uint16) []byte { + bytes := make([]byte, 2) + binary.BigEndian.PutUint16(bytes, v) + return bytes +} + func Uint32Attr(v uint32) []byte { native := NativeEndian() bytes := make([]byte, 4) @@ -716,6 +936,12 @@ func Uint32Attr(v uint32) []byte { return bytes } +func BEUint32Attr(v uint32) []byte { + bytes := make([]byte, 4) + binary.BigEndian.PutUint32(bytes, v) + return bytes +} + func Uint64Attr(v uint64) []byte { native := NativeEndian() bytes := make([]byte, 8) @@ -723,6 +949,12 @@ func Uint64Attr(v uint64) []byte { return bytes } +func BEUint64Attr(v uint64) []byte { + bytes := make([]byte, 8) + binary.BigEndian.PutUint64(bytes, v) + return bytes +} + func ParseRouteAttr(b []byte) ([]syscall.NetlinkRouteAttr, error) { var attrs []syscall.NetlinkRouteAttr for len(b) >= unix.SizeofRtAttr { @@ -737,6 +969,22 @@ func ParseRouteAttr(b []byte) ([]syscall.NetlinkRouteAttr, error) { return attrs, nil } +// ParseRouteAttrAsMap parses provided buffer that contains raw RtAttrs and returns a map of parsed +// atttributes indexed by attribute type or error if occured. +func ParseRouteAttrAsMap(b []byte) (map[uint16]syscall.NetlinkRouteAttr, error) { + attrMap := make(map[uint16]syscall.NetlinkRouteAttr) + + attrs, err := ParseRouteAttr(b) + if err != nil { + return nil, err + } + + for _, attr := range attrs { + attrMap[attr.Attr.Type] = attr + } + return attrMap, nil +} + func netlinkRouteAttrAndValue(b []byte) (*unix.RtAttr, []byte, int, error) { a := (*unix.RtAttr)(unsafe.Pointer(&b[0])) if int(a.Len) < unix.SizeofRtAttr || int(a.Len) > len(b) { diff --git a/vendor/github.com/vishvananda/netlink/nl/parse_attr_linux.go b/vendor/github.com/vishvananda/netlink/nl/parse_attr_linux.go new file mode 100644 index 000000000..7f49125cf --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/nl/parse_attr_linux.go @@ -0,0 +1,79 @@ +package nl + +import ( + "encoding/binary" + "fmt" + "log" +) + +type Attribute struct { + Type uint16 + Value []byte +} + +func ParseAttributes(data []byte) <-chan Attribute { + native := NativeEndian() + result := make(chan Attribute) + + go func() { + i := 0 + for i+4 < len(data) { + length := int(native.Uint16(data[i : i+2])) + attrType := native.Uint16(data[i+2 : i+4]) + + if length < 4 { + log.Printf("attribute 0x%02x has invalid length of %d bytes", attrType, length) + break + } + + if len(data) < i+length { + log.Printf("attribute 0x%02x of length %d is truncated, only %d bytes remaining", attrType, length, len(data)-i) + break + } + + result <- Attribute{ + Type: attrType, + Value: data[i+4 : i+length], + } + i += rtaAlignOf(length) + } + close(result) + }() + + return result +} + +func PrintAttributes(data []byte) { + printAttributes(data, 0) +} + +func printAttributes(data []byte, level int) { + for attr := range ParseAttributes(data) { + for i := 0; i < level; i++ { + print("> ") + } + nested := attr.Type&NLA_F_NESTED != 0 + fmt.Printf("type=%d nested=%v len=%v %v\n", attr.Type&NLA_TYPE_MASK, nested, len(attr.Value), attr.Value) + if nested { + printAttributes(attr.Value, level+1) + } + } +} + +// Uint32 returns the uint32 value respecting the NET_BYTEORDER flag +func (attr *Attribute) Uint32() uint32 { + if attr.Type&NLA_F_NET_BYTEORDER != 0 { + return binary.BigEndian.Uint32(attr.Value) + } else { + return NativeEndian().Uint32(attr.Value) + } +} + +// Uint64 returns the uint64 value respecting the NET_BYTEORDER flag +func (attr *Attribute) Uint64() uint64 { + if attr.Type&NLA_F_NET_BYTEORDER != 0 { + return binary.BigEndian.Uint64(attr.Value) + } else { + return NativeEndian().Uint64(attr.Value) + } +} diff --git a/vendor/github.com/vishvananda/netlink/nl/rdma_link_linux.go b/vendor/github.com/vishvananda/netlink/nl/rdma_link_linux.go index 1224b747d..ce43ee155 100644 --- a/vendor/github.com/vishvananda/netlink/nl/rdma_link_linux.go +++ b/vendor/github.com/vishvananda/netlink/nl/rdma_link_linux.go @@ -11,6 +11,8 @@ const ( const ( RDMA_NLDEV_CMD_GET = 1 RDMA_NLDEV_CMD_SET = 2 + RDMA_NLDEV_CMD_NEWLINK = 3 + RDMA_NLDEV_CMD_DELLINK = 4 RDMA_NLDEV_CMD_SYS_GET = 6 RDMA_NLDEV_CMD_SYS_SET = 7 ) @@ -30,6 +32,8 @@ const ( RDMA_NLDEV_ATTR_PORT_STATE = 12 RDMA_NLDEV_ATTR_PORT_PHYS_STATE = 13 RDMA_NLDEV_ATTR_DEV_NODE_TYPE = 14 + RDMA_NLDEV_ATTR_NDEV_NAME = 51 + RDMA_NLDEV_ATTR_LINK_TYPE = 65 RDMA_NLDEV_SYS_ATTR_NETNS_MODE = 66 RDMA_NLDEV_NET_NS_FD = 68 ) diff --git a/vendor/github.com/vishvananda/netlink/nl/route_linux.go b/vendor/github.com/vishvananda/netlink/nl/route_linux.go index 03c1900ff..c26f3bf91 100644 --- a/vendor/github.com/vishvananda/netlink/nl/route_linux.go +++ b/vendor/github.com/vishvananda/netlink/nl/route_linux.go @@ -48,7 +48,9 @@ type RtNexthop struct { } func DeserializeRtNexthop(b []byte) *RtNexthop { - return (*RtNexthop)(unsafe.Pointer(&b[0:unix.SizeofRtNexthop][0])) + return &RtNexthop{ + RtNexthop: *((*unix.RtNexthop)(unsafe.Pointer(&b[0:unix.SizeofRtNexthop][0]))), + } } func (msg *RtNexthop) Len() int { diff --git a/vendor/github.com/vishvananda/netlink/nl/seg6_linux.go b/vendor/github.com/vishvananda/netlink/nl/seg6_linux.go index 5774cbb15..fe88285f2 100644 --- a/vendor/github.com/vishvananda/netlink/nl/seg6_linux.go +++ b/vendor/github.com/vishvananda/netlink/nl/seg6_linux.go @@ -23,7 +23,7 @@ func (s1 *IPv6SrHdr) Equal(s2 IPv6SrHdr) bool { return false } for i := range s1.Segments { - if s1.Segments[i].Equal(s2.Segments[i]) != true { + if !s1.Segments[i].Equal(s2.Segments[i]) { return false } } @@ -89,7 +89,7 @@ func DecodeSEG6Encap(buf []byte) (int, []net.IP, error) { } buf = buf[12:] if len(buf)%16 != 0 { - err := fmt.Errorf("DecodeSEG6Encap: error parsing Segment List (buf len: %d)\n", len(buf)) + err := fmt.Errorf("DecodeSEG6Encap: error parsing Segment List (buf len: %d)", len(buf)) return mode, nil, err } for len(buf) > 0 { diff --git a/vendor/github.com/vishvananda/netlink/nl/seg6local_linux.go b/vendor/github.com/vishvananda/netlink/nl/seg6local_linux.go index 150017726..8172b8471 100644 --- a/vendor/github.com/vishvananda/netlink/nl/seg6local_linux.go +++ b/vendor/github.com/vishvananda/netlink/nl/seg6local_linux.go @@ -12,6 +12,7 @@ const ( SEG6_LOCAL_NH6 SEG6_LOCAL_IIF SEG6_LOCAL_OIF + SEG6_LOCAL_BPF __SEG6_LOCAL_MAX ) const ( @@ -34,6 +35,7 @@ const ( SEG6_LOCAL_ACTION_END_S // 12 SEG6_LOCAL_ACTION_END_AS // 13 SEG6_LOCAL_ACTION_END_AM // 14 + SEG6_LOCAL_ACTION_END_BPF // 15 __SEG6_LOCAL_ACTION_MAX ) const ( @@ -71,6 +73,8 @@ func SEG6LocalActionString(action int) string { return "End.AS" case SEG6_LOCAL_ACTION_END_AM: return "End.AM" + case SEG6_LOCAL_ACTION_END_BPF: + return "End.BPF" } return "unknown" } diff --git a/vendor/github.com/vishvananda/netlink/nl/syscall.go b/vendor/github.com/vishvananda/netlink/nl/syscall.go index f7f7f92e6..b5ba039ac 100644 --- a/vendor/github.com/vishvananda/netlink/nl/syscall.go +++ b/vendor/github.com/vishvananda/netlink/nl/syscall.go @@ -1,6 +1,6 @@ package nl -// syscall package lack of rule atributes type. +// syscall package lack of rule attributes type. // Thus there are defined below const ( FRA_UNSPEC = iota @@ -21,6 +21,13 @@ const ( FRA_TABLE /* Extended table id */ FRA_FWMASK /* mask for netfilter mark */ FRA_OIFNAME + FRA_PAD + FRA_L3MDEV /* iif or oif is l3mdev goto its table */ + FRA_UID_RANGE /* UID range */ + FRA_PROTOCOL /* Originator of the rule */ + FRA_IP_PROTO /* ip proto */ + FRA_SPORT_RANGE /* sport */ + FRA_DPORT_RANGE /* dport */ ) // ip rule netlink request types @@ -39,6 +46,7 @@ const ( // socket diags related const ( SOCK_DIAG_BY_FAMILY = 20 /* linux.sock_diag.h */ + SOCK_DESTROY = 21 TCPDIAG_NOCOOKIE = 0xFFFFFFFF /* TCPDIAG_NOCOOKIE in net/ipv4/tcp_diag.h*/ ) diff --git a/vendor/github.com/vishvananda/netlink/nl/tc_linux.go b/vendor/github.com/vishvananda/netlink/nl/tc_linux.go index 501f554b2..0720729a9 100644 --- a/vendor/github.com/vishvananda/netlink/nl/tc_linux.go +++ b/vendor/github.com/vishvananda/netlink/nl/tc_linux.go @@ -1,8 +1,13 @@ package nl import ( + "bytes" "encoding/binary" + "fmt" + "net" "unsafe" + + "golang.org/x/sys/unix" ) // LinkLayer @@ -42,7 +47,14 @@ const ( TCA_FCNT TCA_STATS2 TCA_STAB - TCA_MAX = TCA_STAB + TCA_PAD + TCA_DUMP_INVISIBLE + TCA_CHAIN + TCA_HW_OFFLOAD + TCA_INGRESS_BLOCK + TCA_EGRESS_BLOCK + TCA_DUMP_FLAGS + TCA_MAX = TCA_DUMP_FLAGS ) const ( @@ -56,6 +68,12 @@ const ( TCA_ACT_OPTIONS TCA_ACT_INDEX TCA_ACT_STATS + TCA_ACT_PAD + TCA_ACT_COOKIE + TCA_ACT_FLAGS + TCA_ACT_HW_STATS + TCA_ACT_USED_HW_STATS + TCA_ACT_IN_HW_COUNT TCA_ACT_MAX ) @@ -71,7 +89,11 @@ const ( TCA_STATS_RATE_EST TCA_STATS_QUEUE TCA_STATS_APP - TCA_STATS_MAX = TCA_STATS_APP + TCA_STATS_RATE_EST64 + TCA_STATS_PAD + TCA_STATS_BASIC_HW + TCA_STATS_PKT64 + TCA_STATS_MAX = TCA_STATS_PKT64 ) const ( @@ -83,17 +105,23 @@ const ( SizeofTcNetemCorr = 0x0c SizeofTcNetemReorder = 0x08 SizeofTcNetemCorrupt = 0x08 + SizeOfTcNetemRate = 0x10 SizeofTcTbfQopt = 2*SizeofTcRateSpec + 0x0c SizeofTcHtbCopt = 2*SizeofTcRateSpec + 0x14 SizeofTcHtbGlob = 0x14 SizeofTcU32Key = 0x10 SizeofTcU32Sel = 0x10 // without keys - SizeofTcGen = 0x14 + SizeofTcGen = 0x16 SizeofTcConnmark = SizeofTcGen + 0x04 + SizeofTcCsum = SizeofTcGen + 0x04 SizeofTcMirred = SizeofTcGen + 0x08 SizeofTcTunnelKey = SizeofTcGen + 0x04 SizeofTcSkbEdit = SizeofTcGen SizeofTcPolice = 2*SizeofTcRateSpec + 0x20 + SizeofTcSfqQopt = 0x0b + SizeofTcSfqRedStats = 0x18 + SizeofTcSfqQoptV1 = SizeofTcSfqQopt + SizeofTcSfqRedStats + 0x1c + SizeofUint32Bitfield = 0x8 ) // struct tcmsg { @@ -127,6 +155,18 @@ func (x *TcMsg) Serialize() []byte { return (*(*[SizeofTcMsg]byte)(unsafe.Pointer(x)))[:] } +type Tcf struct { + Install uint64 + LastUse uint64 + Expires uint64 + FirstUse uint64 +} + +func DeserializeTcf(b []byte) *Tcf { + const size = int(unsafe.Sizeof(Tcf{})) + return (*Tcf)(unsafe.Pointer(&b[0:size][0])) +} + // struct tcamsg { // unsigned char tca_family; // unsigned char tca__pad1; @@ -333,6 +373,26 @@ func (x *TcNetemCorrupt) Serialize() []byte { return (*(*[SizeofTcNetemCorrupt]byte)(unsafe.Pointer(x)))[:] } +// TcNetemRate is a struct that represents the rate of a netem qdisc +type TcNetemRate struct { + Rate uint32 + PacketOverhead int32 + CellSize uint32 + CellOverhead int32 +} + +func (msg *TcNetemRate) Len() int { + return SizeofTcRateSpec +} + +func DeserializeTcNetemRate(b []byte) *TcNetemRate { + return (*TcNetemRate)(unsafe.Pointer(&b[0:SizeofTcRateSpec][0])) +} + +func (msg *TcNetemRate) Serialize() []byte { + return (*(*[SizeOfTcNetemRate]byte)(unsafe.Pointer(msg)))[:] +} + // struct tc_tbf_qopt { // struct tc_ratespec rate; // struct tc_ratespec peakrate; @@ -691,6 +751,36 @@ func (x *TcConnmark) Serialize() []byte { return (*(*[SizeofTcConnmark]byte)(unsafe.Pointer(x)))[:] } +const ( + TCA_CSUM_UNSPEC = iota + TCA_CSUM_PARMS + TCA_CSUM_TM + TCA_CSUM_PAD + TCA_CSUM_MAX = TCA_CSUM_PAD +) + +// struct tc_csum { +// tc_gen; +// __u32 update_flags; +// } + +type TcCsum struct { + TcGen + UpdateFlags uint32 +} + +func (msg *TcCsum) Len() int { + return SizeofTcCsum +} + +func DeserializeTcCsum(b []byte) *TcCsum { + return (*TcCsum)(unsafe.Pointer(&b[0:SizeofTcCsum][0])) +} + +func (x *TcCsum) Serialize() []byte { + return (*(*[SizeofTcCsum]byte)(unsafe.Pointer(x)))[:] +} + const ( TCA_ACT_MIRRED = 8 ) @@ -735,7 +825,13 @@ const ( TCA_TUNNEL_KEY_ENC_IPV6_SRC TCA_TUNNEL_KEY_ENC_IPV6_DST TCA_TUNNEL_KEY_ENC_KEY_ID - TCA_TUNNEL_KEY_MAX = TCA_TUNNEL_KEY_ENC_KEY_ID + TCA_TUNNEL_KEY_PAD + TCA_TUNNEL_KEY_ENC_DST_PORT + TCA_TUNNEL_KEY_NO_CSUM + TCA_TUNNEL_KEY_ENC_OPTS + TCA_TUNNEL_KEY_ENC_TOS + TCA_TUNNEL_KEY_ENC_TTL + TCA_TUNNEL_KEY_MAX ) type TcTunnelKey struct { @@ -764,7 +860,8 @@ const ( TCA_SKBEDIT_MARK TCA_SKBEDIT_PAD TCA_SKBEDIT_PTYPE - TCA_SKBEDIT_MAX = TCA_SKBEDIT_MARK + TCA_SKBEDIT_MASK + TCA_SKBEDIT_MAX ) type TcSkbEdit struct { @@ -851,6 +948,10 @@ const ( TCA_FQ_FLOW_REFILL_DELAY // flow credit refill delay in usec TCA_FQ_ORPHAN_MASK // mask applied to orphaned skb hashes TCA_FQ_LOW_RATE_THRESHOLD // per packet delay under this rate + TCA_FQ_CE_THRESHOLD // DCTCP-like CE-marking threshold + TCA_FQ_TIMER_SLACK // timer slack + TCA_FQ_HORIZON // time horizon in us + TCA_FQ_HORIZON_DROP // drop packets beyond horizon, or cap their EDT ) const ( @@ -872,3 +973,639 @@ const ( TCA_HFSC_FSC TCA_HFSC_USC ) + +const ( + TCA_FLOWER_UNSPEC = iota + TCA_FLOWER_CLASSID + TCA_FLOWER_INDEV + TCA_FLOWER_ACT + TCA_FLOWER_KEY_ETH_DST /* ETH_ALEN */ + TCA_FLOWER_KEY_ETH_DST_MASK /* ETH_ALEN */ + TCA_FLOWER_KEY_ETH_SRC /* ETH_ALEN */ + TCA_FLOWER_KEY_ETH_SRC_MASK /* ETH_ALEN */ + TCA_FLOWER_KEY_ETH_TYPE /* be16 */ + TCA_FLOWER_KEY_IP_PROTO /* u8 */ + TCA_FLOWER_KEY_IPV4_SRC /* be32 */ + TCA_FLOWER_KEY_IPV4_SRC_MASK /* be32 */ + TCA_FLOWER_KEY_IPV4_DST /* be32 */ + TCA_FLOWER_KEY_IPV4_DST_MASK /* be32 */ + TCA_FLOWER_KEY_IPV6_SRC /* struct in6_addr */ + TCA_FLOWER_KEY_IPV6_SRC_MASK /* struct in6_addr */ + TCA_FLOWER_KEY_IPV6_DST /* struct in6_addr */ + TCA_FLOWER_KEY_IPV6_DST_MASK /* struct in6_addr */ + TCA_FLOWER_KEY_TCP_SRC /* be16 */ + TCA_FLOWER_KEY_TCP_DST /* be16 */ + TCA_FLOWER_KEY_UDP_SRC /* be16 */ + TCA_FLOWER_KEY_UDP_DST /* be16 */ + + TCA_FLOWER_FLAGS + TCA_FLOWER_KEY_VLAN_ID /* be16 */ + TCA_FLOWER_KEY_VLAN_PRIO /* u8 */ + TCA_FLOWER_KEY_VLAN_ETH_TYPE /* be16 */ + + TCA_FLOWER_KEY_ENC_KEY_ID /* be32 */ + TCA_FLOWER_KEY_ENC_IPV4_SRC /* be32 */ + TCA_FLOWER_KEY_ENC_IPV4_SRC_MASK /* be32 */ + TCA_FLOWER_KEY_ENC_IPV4_DST /* be32 */ + TCA_FLOWER_KEY_ENC_IPV4_DST_MASK /* be32 */ + TCA_FLOWER_KEY_ENC_IPV6_SRC /* struct in6_addr */ + TCA_FLOWER_KEY_ENC_IPV6_SRC_MASK /* struct in6_addr */ + TCA_FLOWER_KEY_ENC_IPV6_DST /* struct in6_addr */ + TCA_FLOWER_KEY_ENC_IPV6_DST_MASK /* struct in6_addr */ + + TCA_FLOWER_KEY_TCP_SRC_MASK /* be16 */ + TCA_FLOWER_KEY_TCP_DST_MASK /* be16 */ + TCA_FLOWER_KEY_UDP_SRC_MASK /* be16 */ + TCA_FLOWER_KEY_UDP_DST_MASK /* be16 */ + TCA_FLOWER_KEY_SCTP_SRC_MASK /* be16 */ + TCA_FLOWER_KEY_SCTP_DST_MASK /* be16 */ + + TCA_FLOWER_KEY_SCTP_SRC /* be16 */ + TCA_FLOWER_KEY_SCTP_DST /* be16 */ + + TCA_FLOWER_KEY_ENC_UDP_SRC_PORT /* be16 */ + TCA_FLOWER_KEY_ENC_UDP_SRC_PORT_MASK /* be16 */ + TCA_FLOWER_KEY_ENC_UDP_DST_PORT /* be16 */ + TCA_FLOWER_KEY_ENC_UDP_DST_PORT_MASK /* be16 */ + + TCA_FLOWER_KEY_FLAGS /* be32 */ + TCA_FLOWER_KEY_FLAGS_MASK /* be32 */ + + TCA_FLOWER_KEY_ICMPV4_CODE /* u8 */ + TCA_FLOWER_KEY_ICMPV4_CODE_MASK /* u8 */ + TCA_FLOWER_KEY_ICMPV4_TYPE /* u8 */ + TCA_FLOWER_KEY_ICMPV4_TYPE_MASK /* u8 */ + TCA_FLOWER_KEY_ICMPV6_CODE /* u8 */ + TCA_FLOWER_KEY_ICMPV6_CODE_MASK /* u8 */ + TCA_FLOWER_KEY_ICMPV6_TYPE /* u8 */ + TCA_FLOWER_KEY_ICMPV6_TYPE_MASK /* u8 */ + + TCA_FLOWER_KEY_ARP_SIP /* be32 */ + TCA_FLOWER_KEY_ARP_SIP_MASK /* be32 */ + TCA_FLOWER_KEY_ARP_TIP /* be32 */ + TCA_FLOWER_KEY_ARP_TIP_MASK /* be32 */ + TCA_FLOWER_KEY_ARP_OP /* u8 */ + TCA_FLOWER_KEY_ARP_OP_MASK /* u8 */ + TCA_FLOWER_KEY_ARP_SHA /* ETH_ALEN */ + TCA_FLOWER_KEY_ARP_SHA_MASK /* ETH_ALEN */ + TCA_FLOWER_KEY_ARP_THA /* ETH_ALEN */ + TCA_FLOWER_KEY_ARP_THA_MASK /* ETH_ALEN */ + + TCA_FLOWER_KEY_MPLS_TTL /* u8 - 8 bits */ + TCA_FLOWER_KEY_MPLS_BOS /* u8 - 1 bit */ + TCA_FLOWER_KEY_MPLS_TC /* u8 - 3 bits */ + TCA_FLOWER_KEY_MPLS_LABEL /* be32 - 20 bits */ + + TCA_FLOWER_KEY_TCP_FLAGS /* be16 */ + TCA_FLOWER_KEY_TCP_FLAGS_MASK /* be16 */ + + TCA_FLOWER_KEY_IP_TOS /* u8 */ + TCA_FLOWER_KEY_IP_TOS_MASK /* u8 */ + TCA_FLOWER_KEY_IP_TTL /* u8 */ + TCA_FLOWER_KEY_IP_TTL_MASK /* u8 */ + + TCA_FLOWER_KEY_CVLAN_ID /* be16 */ + TCA_FLOWER_KEY_CVLAN_PRIO /* u8 */ + TCA_FLOWER_KEY_CVLAN_ETH_TYPE /* be16 */ + + TCA_FLOWER_KEY_ENC_IP_TOS /* u8 */ + TCA_FLOWER_KEY_ENC_IP_TOS_MASK /* u8 */ + TCA_FLOWER_KEY_ENC_IP_TTL /* u8 */ + TCA_FLOWER_KEY_ENC_IP_TTL_MASK /* u8 */ + + TCA_FLOWER_KEY_ENC_OPTS + TCA_FLOWER_KEY_ENC_OPTS_MASK + + __TCA_FLOWER_MAX +) + +const TCA_CLS_FLAGS_SKIP_HW = 1 << 0 /* don't offload filter to HW */ +const TCA_CLS_FLAGS_SKIP_SW = 1 << 1 /* don't use filter in SW */ + +// struct tc_sfq_qopt { +// unsigned quantum; /* Bytes per round allocated to flow */ +// int perturb_period; /* Period of hash perturbation */ +// __u32 limit; /* Maximal packets in queue */ +// unsigned divisor; /* Hash divisor */ +// unsigned flows; /* Maximal number of flows */ +// }; + +type TcSfqQopt struct { + Quantum uint8 + Perturb int32 + Limit uint32 + Divisor uint8 + Flows uint8 +} + +func (x *TcSfqQopt) Len() int { + return SizeofTcSfqQopt +} + +func DeserializeTcSfqQopt(b []byte) *TcSfqQopt { + return (*TcSfqQopt)(unsafe.Pointer(&b[0:SizeofTcSfqQopt][0])) +} + +func (x *TcSfqQopt) Serialize() []byte { + return (*(*[SizeofTcSfqQopt]byte)(unsafe.Pointer(x)))[:] +} + +// struct tc_sfqred_stats { +// __u32 prob_drop; /* Early drops, below max threshold */ +// __u32 forced_drop; /* Early drops, after max threshold */ +// __u32 prob_mark; /* Marked packets, below max threshold */ +// __u32 forced_mark; /* Marked packets, after max threshold */ +// __u32 prob_mark_head; /* Marked packets, below max threshold */ +// __u32 forced_mark_head;/* Marked packets, after max threshold */ +// }; +type TcSfqRedStats struct { + ProbDrop uint32 + ForcedDrop uint32 + ProbMark uint32 + ForcedMark uint32 + ProbMarkHead uint32 + ForcedMarkHead uint32 +} + +func (x *TcSfqRedStats) Len() int { + return SizeofTcSfqRedStats +} + +func DeserializeTcSfqRedStats(b []byte) *TcSfqRedStats { + return (*TcSfqRedStats)(unsafe.Pointer(&b[0:SizeofTcSfqRedStats][0])) +} + +func (x *TcSfqRedStats) Serialize() []byte { + return (*(*[SizeofTcSfqRedStats]byte)(unsafe.Pointer(x)))[:] +} + +// struct tc_sfq_qopt_v1 { +// struct tc_sfq_qopt v0; +// unsigned int depth; /* max number of packets per flow */ +// unsigned int headdrop; +// +// /* SFQRED parameters */ +// +// __u32 limit; /* HARD maximal flow queue length (bytes) */ +// __u32 qth_min; /* Min average length threshold (bytes) */ +// __u32 qth_max; /* Max average length threshold (bytes) */ +// unsigned char Wlog; /* log(W) */ +// unsigned char Plog; /* log(P_max/(qth_max-qth_min)) */ +// unsigned char Scell_log; /* cell size for idle damping */ +// unsigned char flags; +// __u32 max_P; /* probability, high resolution */ +// +// /* SFQRED stats */ +// +// struct tc_sfqred_stats stats; +// }; +type TcSfqQoptV1 struct { + TcSfqQopt + Depth uint32 + HeadDrop uint32 + Limit uint32 + QthMin uint32 + QthMax uint32 + Wlog byte + Plog byte + ScellLog byte + Flags byte + MaxP uint32 + TcSfqRedStats +} + +func (x *TcSfqQoptV1) Len() int { + return SizeofTcSfqQoptV1 +} + +func DeserializeTcSfqQoptV1(b []byte) *TcSfqQoptV1 { + return (*TcSfqQoptV1)(unsafe.Pointer(&b[0:SizeofTcSfqQoptV1][0])) +} + +func (x *TcSfqQoptV1) Serialize() []byte { + return (*(*[SizeofTcSfqQoptV1]byte)(unsafe.Pointer(x)))[:] +} + +// IPProto represents Flower ip_proto attribute +type IPProto uint8 + +const ( + IPPROTO_TCP IPProto = unix.IPPROTO_TCP + IPPROTO_UDP IPProto = unix.IPPROTO_UDP + IPPROTO_SCTP IPProto = unix.IPPROTO_SCTP + IPPROTO_ICMP IPProto = unix.IPPROTO_ICMP + IPPROTO_ICMPV6 IPProto = unix.IPPROTO_ICMPV6 +) + +func (i IPProto) Serialize() []byte { + arr := make([]byte, 1) + arr[0] = byte(i) + return arr +} + +func (i IPProto) String() string { + switch i { + case IPPROTO_TCP: + return "tcp" + case IPPROTO_UDP: + return "udp" + case IPPROTO_SCTP: + return "sctp" + case IPPROTO_ICMP: + return "icmp" + case IPPROTO_ICMPV6: + return "icmpv6" + } + return fmt.Sprintf("%d", i) +} + +const ( + MaxOffs = 128 + SizeOfPeditSel = 24 + SizeOfPeditKey = 24 + + TCA_PEDIT_KEY_EX_HTYPE = 1 + TCA_PEDIT_KEY_EX_CMD = 2 +) + +const ( + TCA_PEDIT_UNSPEC = iota + TCA_PEDIT_TM + TCA_PEDIT_PARMS + TCA_PEDIT_PAD + TCA_PEDIT_PARMS_EX + TCA_PEDIT_KEYS_EX + TCA_PEDIT_KEY_EX +) + +// /* TCA_PEDIT_KEY_EX_HDR_TYPE_NETWROK is a special case for legacy users. It +// * means no specific header type - offset is relative to the network layer +// */ +type PeditHeaderType uint16 + +const ( + TCA_PEDIT_KEY_EX_HDR_TYPE_NETWORK = iota + TCA_PEDIT_KEY_EX_HDR_TYPE_ETH + TCA_PEDIT_KEY_EX_HDR_TYPE_IP4 + TCA_PEDIT_KEY_EX_HDR_TYPE_IP6 + TCA_PEDIT_KEY_EX_HDR_TYPE_TCP + TCA_PEDIT_KEY_EX_HDR_TYPE_UDP + __PEDIT_HDR_TYPE_MAX +) + +type PeditCmd uint16 + +const ( + TCA_PEDIT_KEY_EX_CMD_SET = 0 + TCA_PEDIT_KEY_EX_CMD_ADD = 1 +) + +type TcPeditSel struct { + TcGen + NKeys uint8 + Flags uint8 +} + +func DeserializeTcPeditKey(b []byte) *TcPeditKey { + return (*TcPeditKey)(unsafe.Pointer(&b[0:SizeOfPeditKey][0])) +} + +func DeserializeTcPedit(b []byte) (*TcPeditSel, []TcPeditKey) { + x := &TcPeditSel{} + copy((*(*[SizeOfPeditSel]byte)(unsafe.Pointer(x)))[:SizeOfPeditSel], b) + + var keys []TcPeditKey + + next := SizeOfPeditKey + var i uint8 + for i = 0; i < x.NKeys; i++ { + keys = append(keys, *DeserializeTcPeditKey(b[next:])) + next += SizeOfPeditKey + } + + return x, keys +} + +type TcPeditKey struct { + Mask uint32 + Val uint32 + Off uint32 + At uint32 + OffMask uint32 + Shift uint32 +} + +type TcPeditKeyEx struct { + HeaderType PeditHeaderType + Cmd PeditCmd +} + +type TcPedit struct { + Sel TcPeditSel + Keys []TcPeditKey + KeysEx []TcPeditKeyEx + Extend uint8 +} + +func (p *TcPedit) Encode(parent *RtAttr) { + parent.AddRtAttr(TCA_ACT_KIND, ZeroTerminated("pedit")) + actOpts := parent.AddRtAttr(TCA_ACT_OPTIONS, nil) + + bbuf := bytes.NewBuffer(make([]byte, 0, int(unsafe.Sizeof(p.Sel)+unsafe.Sizeof(p.Keys)))) + + bbuf.Write((*(*[SizeOfPeditSel]byte)(unsafe.Pointer(&p.Sel)))[:]) + + for i := uint8(0); i < p.Sel.NKeys; i++ { + bbuf.Write((*(*[SizeOfPeditKey]byte)(unsafe.Pointer(&p.Keys[i])))[:]) + } + actOpts.AddRtAttr(TCA_PEDIT_PARMS_EX, bbuf.Bytes()) + + exAttrs := actOpts.AddRtAttr(int(TCA_PEDIT_KEYS_EX|NLA_F_NESTED), nil) + for i := uint8(0); i < p.Sel.NKeys; i++ { + keyAttr := exAttrs.AddRtAttr(int(TCA_PEDIT_KEY_EX|NLA_F_NESTED), nil) + + htypeBuf := make([]byte, 2) + cmdBuf := make([]byte, 2) + + NativeEndian().PutUint16(htypeBuf, uint16(p.KeysEx[i].HeaderType)) + NativeEndian().PutUint16(cmdBuf, uint16(p.KeysEx[i].Cmd)) + + keyAttr.AddRtAttr(TCA_PEDIT_KEY_EX_HTYPE, htypeBuf) + keyAttr.AddRtAttr(TCA_PEDIT_KEY_EX_CMD, cmdBuf) + } +} + +func (p *TcPedit) SetEthDst(mac net.HardwareAddr) { + u32 := NativeEndian().Uint32(mac) + u16 := NativeEndian().Uint16(mac[4:]) + + tKey := TcPeditKey{} + tKeyEx := TcPeditKeyEx{} + + tKey.Val = u32 + + tKeyEx.HeaderType = TCA_PEDIT_KEY_EX_HDR_TYPE_ETH + tKeyEx.Cmd = TCA_PEDIT_KEY_EX_CMD_SET + + p.Keys = append(p.Keys, tKey) + p.KeysEx = append(p.KeysEx, tKeyEx) + p.Sel.NKeys++ + + tKey = TcPeditKey{} + tKeyEx = TcPeditKeyEx{} + + tKey.Val = uint32(u16) + tKey.Mask = 0xffff0000 + tKey.Off = 4 + tKeyEx.HeaderType = TCA_PEDIT_KEY_EX_HDR_TYPE_ETH + tKeyEx.Cmd = TCA_PEDIT_KEY_EX_CMD_SET + + p.Keys = append(p.Keys, tKey) + p.KeysEx = append(p.KeysEx, tKeyEx) + + p.Sel.NKeys++ +} + +func (p *TcPedit) SetEthSrc(mac net.HardwareAddr) { + u16 := NativeEndian().Uint16(mac) + u32 := NativeEndian().Uint32(mac[2:]) + + tKey := TcPeditKey{} + tKeyEx := TcPeditKeyEx{} + + tKey.Val = uint32(u16) << 16 + tKey.Mask = 0x0000ffff + tKey.Off = 4 + + tKeyEx.HeaderType = TCA_PEDIT_KEY_EX_HDR_TYPE_ETH + tKeyEx.Cmd = TCA_PEDIT_KEY_EX_CMD_SET + + p.Keys = append(p.Keys, tKey) + p.KeysEx = append(p.KeysEx, tKeyEx) + p.Sel.NKeys++ + + tKey = TcPeditKey{} + tKeyEx = TcPeditKeyEx{} + + tKey.Val = u32 + tKey.Mask = 0 + tKey.Off = 8 + + tKeyEx.HeaderType = TCA_PEDIT_KEY_EX_HDR_TYPE_ETH + tKeyEx.Cmd = TCA_PEDIT_KEY_EX_CMD_SET + + p.Keys = append(p.Keys, tKey) + p.KeysEx = append(p.KeysEx, tKeyEx) + + p.Sel.NKeys++ +} + +func (p *TcPedit) SetIPv6Src(ip6 net.IP) { + u32 := NativeEndian().Uint32(ip6[:4]) + + tKey := TcPeditKey{} + tKeyEx := TcPeditKeyEx{} + + tKey.Val = u32 + tKey.Off = 8 + tKeyEx.HeaderType = TCA_PEDIT_KEY_EX_HDR_TYPE_IP6 + tKeyEx.Cmd = TCA_PEDIT_KEY_EX_CMD_SET + + p.Keys = append(p.Keys, tKey) + p.KeysEx = append(p.KeysEx, tKeyEx) + p.Sel.NKeys++ + + u32 = NativeEndian().Uint32(ip6[4:8]) + tKey = TcPeditKey{} + tKeyEx = TcPeditKeyEx{} + + tKey.Val = u32 + tKey.Off = 12 + tKeyEx.HeaderType = TCA_PEDIT_KEY_EX_HDR_TYPE_IP6 + tKeyEx.Cmd = TCA_PEDIT_KEY_EX_CMD_SET + + p.Keys = append(p.Keys, tKey) + p.KeysEx = append(p.KeysEx, tKeyEx) + + p.Sel.NKeys++ + + u32 = NativeEndian().Uint32(ip6[8:12]) + tKey = TcPeditKey{} + tKeyEx = TcPeditKeyEx{} + + tKey.Val = u32 + tKey.Off = 16 + tKeyEx.HeaderType = TCA_PEDIT_KEY_EX_HDR_TYPE_IP6 + tKeyEx.Cmd = TCA_PEDIT_KEY_EX_CMD_SET + + p.Keys = append(p.Keys, tKey) + p.KeysEx = append(p.KeysEx, tKeyEx) + + p.Sel.NKeys++ + + u32 = NativeEndian().Uint32(ip6[12:16]) + tKey = TcPeditKey{} + tKeyEx = TcPeditKeyEx{} + + tKey.Val = u32 + tKey.Off = 20 + tKeyEx.HeaderType = TCA_PEDIT_KEY_EX_HDR_TYPE_IP6 + tKeyEx.Cmd = TCA_PEDIT_KEY_EX_CMD_SET + + p.Keys = append(p.Keys, tKey) + p.KeysEx = append(p.KeysEx, tKeyEx) + + p.Sel.NKeys++ +} + +func (p *TcPedit) SetDstIP(ip net.IP) { + if ip.To4() != nil { + p.SetIPv4Dst(ip) + } else { + p.SetIPv6Dst(ip) + } +} + +func (p *TcPedit) SetSrcIP(ip net.IP) { + if ip.To4() != nil { + p.SetIPv4Src(ip) + } else { + p.SetIPv6Src(ip) + } +} + +func (p *TcPedit) SetIPv6Dst(ip6 net.IP) { + u32 := NativeEndian().Uint32(ip6[:4]) + + tKey := TcPeditKey{} + tKeyEx := TcPeditKeyEx{} + + tKey.Val = u32 + tKey.Off = 24 + tKeyEx.HeaderType = TCA_PEDIT_KEY_EX_HDR_TYPE_IP6 + tKeyEx.Cmd = TCA_PEDIT_KEY_EX_CMD_SET + + p.Keys = append(p.Keys, tKey) + p.KeysEx = append(p.KeysEx, tKeyEx) + p.Sel.NKeys++ + + u32 = NativeEndian().Uint32(ip6[4:8]) + tKey = TcPeditKey{} + tKeyEx = TcPeditKeyEx{} + + tKey.Val = u32 + tKey.Off = 28 + tKeyEx.HeaderType = TCA_PEDIT_KEY_EX_HDR_TYPE_IP6 + tKeyEx.Cmd = TCA_PEDIT_KEY_EX_CMD_SET + + p.Keys = append(p.Keys, tKey) + p.KeysEx = append(p.KeysEx, tKeyEx) + + p.Sel.NKeys++ + + u32 = NativeEndian().Uint32(ip6[8:12]) + tKey = TcPeditKey{} + tKeyEx = TcPeditKeyEx{} + + tKey.Val = u32 + tKey.Off = 32 + tKeyEx.HeaderType = TCA_PEDIT_KEY_EX_HDR_TYPE_IP6 + tKeyEx.Cmd = TCA_PEDIT_KEY_EX_CMD_SET + + p.Keys = append(p.Keys, tKey) + p.KeysEx = append(p.KeysEx, tKeyEx) + + p.Sel.NKeys++ + + u32 = NativeEndian().Uint32(ip6[12:16]) + tKey = TcPeditKey{} + tKeyEx = TcPeditKeyEx{} + + tKey.Val = u32 + tKey.Off = 36 + tKeyEx.HeaderType = TCA_PEDIT_KEY_EX_HDR_TYPE_IP6 + tKeyEx.Cmd = TCA_PEDIT_KEY_EX_CMD_SET + + p.Keys = append(p.Keys, tKey) + p.KeysEx = append(p.KeysEx, tKeyEx) + + p.Sel.NKeys++ +} + +func (p *TcPedit) SetIPv4Src(ip net.IP) { + u32 := NativeEndian().Uint32(ip[:4]) + + tKey := TcPeditKey{} + tKeyEx := TcPeditKeyEx{} + + tKey.Val = u32 + tKey.Off = 12 + tKeyEx.HeaderType = TCA_PEDIT_KEY_EX_HDR_TYPE_IP4 + tKeyEx.Cmd = TCA_PEDIT_KEY_EX_CMD_SET + + p.Keys = append(p.Keys, tKey) + p.KeysEx = append(p.KeysEx, tKeyEx) + p.Sel.NKeys++ +} + +func (p *TcPedit) SetIPv4Dst(ip net.IP) { + u32 := NativeEndian().Uint32(ip[:4]) + + tKey := TcPeditKey{} + tKeyEx := TcPeditKeyEx{} + + tKey.Val = u32 + tKey.Off = 16 + tKeyEx.HeaderType = TCA_PEDIT_KEY_EX_HDR_TYPE_IP4 + tKeyEx.Cmd = TCA_PEDIT_KEY_EX_CMD_SET + + p.Keys = append(p.Keys, tKey) + p.KeysEx = append(p.KeysEx, tKeyEx) + p.Sel.NKeys++ +} + +// SetDstPort only tcp and udp are supported to set port +func (p *TcPedit) SetDstPort(dstPort uint16, protocol uint8) { + tKey := TcPeditKey{} + tKeyEx := TcPeditKeyEx{} + + switch protocol { + case unix.IPPROTO_TCP: + tKeyEx.HeaderType = TCA_PEDIT_KEY_EX_HDR_TYPE_TCP + case unix.IPPROTO_UDP: + tKeyEx.HeaderType = TCA_PEDIT_KEY_EX_HDR_TYPE_UDP + default: + return + } + + tKeyEx.Cmd = TCA_PEDIT_KEY_EX_CMD_SET + + tKey.Val = uint32(Swap16(dstPort)) << 16 + tKey.Mask = 0x0000ffff + p.Keys = append(p.Keys, tKey) + p.KeysEx = append(p.KeysEx, tKeyEx) + p.Sel.NKeys++ +} + +// SetSrcPort only tcp and udp are supported to set port +func (p *TcPedit) SetSrcPort(srcPort uint16, protocol uint8) { + tKey := TcPeditKey{} + tKeyEx := TcPeditKeyEx{} + + switch protocol { + case unix.IPPROTO_TCP: + tKeyEx.HeaderType = TCA_PEDIT_KEY_EX_HDR_TYPE_TCP + case unix.IPPROTO_UDP: + tKeyEx.HeaderType = TCA_PEDIT_KEY_EX_HDR_TYPE_UDP + default: + return + } + + tKeyEx.Cmd = TCA_PEDIT_KEY_EX_CMD_SET + + tKey.Val = uint32(Swap16(srcPort)) + tKey.Mask = 0xffff0000 + p.Keys = append(p.Keys, tKey) + p.KeysEx = append(p.KeysEx, tKeyEx) + p.Sel.NKeys++ +} diff --git a/vendor/github.com/vishvananda/netlink/nl/vdpa_linux.go b/vendor/github.com/vishvananda/netlink/nl/vdpa_linux.go new file mode 100644 index 000000000..f209125df --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/nl/vdpa_linux.go @@ -0,0 +1,41 @@ +package nl + +const ( + VDPA_GENL_NAME = "vdpa" + VDPA_GENL_VERSION = 0x1 +) + +const ( + VDPA_CMD_UNSPEC = iota + VDPA_CMD_MGMTDEV_NEW + VDPA_CMD_MGMTDEV_GET /* can dump */ + VDPA_CMD_DEV_NEW + VDPA_CMD_DEV_DEL + VDPA_CMD_DEV_GET /* can dump */ + VDPA_CMD_DEV_CONFIG_GET /* can dump */ + VDPA_CMD_DEV_VSTATS_GET +) + +const ( + VDPA_ATTR_UNSPEC = iota + VDPA_ATTR_MGMTDEV_BUS_NAME + VDPA_ATTR_MGMTDEV_DEV_NAME + VDPA_ATTR_MGMTDEV_SUPPORTED_CLASSES + VDPA_ATTR_DEV_NAME + VDPA_ATTR_DEV_ID + VDPA_ATTR_DEV_VENDOR_ID + VDPA_ATTR_DEV_MAX_VQS + VDPA_ATTR_DEV_MAX_VQ_SIZE + VDPA_ATTR_DEV_MIN_VQ_SIZE + VDPA_ATTR_DEV_NET_CFG_MACADDR + VDPA_ATTR_DEV_NET_STATUS + VDPA_ATTR_DEV_NET_CFG_MAX_VQP + VDPA_ATTR_DEV_NET_CFG_MTU + VDPA_ATTR_DEV_NEGOTIATED_FEATURES + VDPA_ATTR_DEV_MGMTDEV_MAX_VQS + VDPA_ATTR_DEV_SUPPORTED_FEATURES + VDPA_ATTR_DEV_QUEUE_INDEX + VDPA_ATTR_DEV_VENDOR_ATTR_NAME + VDPA_ATTR_DEV_VENDOR_ATTR_VALUE + VDPA_ATTR_DEV_FEATURES +) diff --git a/vendor/github.com/vishvananda/netlink/nl/xfrm_linux.go b/vendor/github.com/vishvananda/netlink/nl/xfrm_linux.go index dce9073f7..cdb318ba5 100644 --- a/vendor/github.com/vishvananda/netlink/nl/xfrm_linux.go +++ b/vendor/github.com/vishvananda/netlink/nl/xfrm_linux.go @@ -131,7 +131,15 @@ func (x *XfrmAddress) ToIP() net.IP { return ip } -func (x *XfrmAddress) ToIPNet(prefixlen uint8) *net.IPNet { +// family is only used when x and prefixlen are both 0 +func (x *XfrmAddress) ToIPNet(prefixlen uint8, family uint16) *net.IPNet { + empty := [SizeofXfrmAddress]byte{} + if bytes.Equal(x[:], empty[:]) && prefixlen == 0 { + if family == FAMILY_V6 { + return &net.IPNet{IP: net.ParseIP("::"), Mask: net.CIDRMask(int(prefixlen), 128)} + } + return &net.IPNet{IP: net.ParseIP("0.0.0.0"), Mask: net.CIDRMask(int(prefixlen), 32)} + } ip := x.ToIP() if GetIPFamily(ip) == FAMILY_V4 { return &net.IPNet{IP: ip, Mask: net.CIDRMask(int(prefixlen), 32)} diff --git a/vendor/github.com/vishvananda/netlink/nl/xfrm_state_linux.go b/vendor/github.com/vishvananda/netlink/nl/xfrm_state_linux.go index b6290fd54..e8920b9a6 100644 --- a/vendor/github.com/vishvananda/netlink/nl/xfrm_state_linux.go +++ b/vendor/github.com/vishvananda/netlink/nl/xfrm_state_linux.go @@ -13,8 +13,9 @@ const ( SizeofXfrmAlgoAuth = 0x48 SizeofXfrmAlgoAEAD = 0x48 SizeofXfrmEncapTmpl = 0x18 - SizeofXfrmUsersaFlush = 0x8 + SizeofXfrmUsersaFlush = 0x1 SizeofXfrmReplayStateEsn = 0x18 + SizeofXfrmReplayState = 0x0c ) const ( @@ -28,6 +29,11 @@ const ( XFRM_STATE_ESN = 128 ) +const ( + XFRM_SA_XFLAG_DONT_ENCAP_DSCP = 1 + XFRM_SA_XFLAG_OSEQ_MAY_WRAP = 2 +) + // struct xfrm_usersa_id { // xfrm_address_t daddr; // __be32 spi; @@ -103,6 +109,7 @@ func (msg *XfrmStats) Serialize() []byte { // }; // // #define XFRM_SA_XFLAG_DONT_ENCAP_DSCP 1 +// #define XFRM_SA_XFLAG_OSEQ_MAY_WRAP 2 // type XfrmUsersaInfo struct { @@ -332,3 +339,23 @@ func (msg *XfrmReplayStateEsn) Serialize() []byte { // We deliberately do not pass Bmp, as it gets set by the kernel. return (*(*[SizeofXfrmReplayStateEsn]byte)(unsafe.Pointer(msg)))[:] } + +// struct xfrm_replay_state { +// __u32 oseq; +// __u32 seq; +// __u32 bitmap; +// }; + +type XfrmReplayState struct { + OSeq uint32 + Seq uint32 + BitMap uint32 +} + +func DeserializeXfrmReplayState(b []byte) *XfrmReplayState { + return (*XfrmReplayState)(unsafe.Pointer(&b[0:SizeofXfrmReplayState][0])) +} + +func (msg *XfrmReplayState) Serialize() []byte { + return (*(*[SizeofXfrmReplayState]byte)(unsafe.Pointer(msg)))[:] +} diff --git a/vendor/github.com/vishvananda/netlink/proc_event_linux.go b/vendor/github.com/vishvananda/netlink/proc_event_linux.go new file mode 100644 index 000000000..ac8762bd8 --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/proc_event_linux.go @@ -0,0 +1,208 @@ +package netlink + +import ( + "bytes" + "encoding/binary" + "fmt" + "os" + "syscall" + + "github.com/vishvananda/netlink/nl" + "github.com/vishvananda/netns" + "golang.org/x/sys/unix" +) + +const CN_IDX_PROC = 0x1 + +const ( + PROC_EVENT_NONE = 0x00000000 + PROC_EVENT_FORK = 0x00000001 + PROC_EVENT_EXEC = 0x00000002 + PROC_EVENT_UID = 0x00000004 + PROC_EVENT_GID = 0x00000040 + PROC_EVENT_SID = 0x00000080 + PROC_EVENT_PTRACE = 0x00000100 + PROC_EVENT_COMM = 0x00000200 + PROC_EVENT_COREDUMP = 0x40000000 + PROC_EVENT_EXIT = 0x80000000 +) + +const ( + CN_VAL_PROC = 0x1 + PROC_CN_MCAST_LISTEN = 0x1 +) + +type ProcEventMsg interface { + Pid() uint32 + Tgid() uint32 +} + +type ProcEventHeader struct { + What uint32 + CPU uint32 + Timestamp uint64 +} + +type ProcEvent struct { + ProcEventHeader + Msg ProcEventMsg +} + +func (pe *ProcEvent) setHeader(h ProcEventHeader) { + pe.What = h.What + pe.CPU = h.CPU + pe.Timestamp = h.Timestamp +} + +type ExitProcEvent struct { + ProcessPid uint32 + ProcessTgid uint32 + ExitCode uint32 + ExitSignal uint32 + ParentPid uint32 + ParentTgid uint32 +} + +func (e *ExitProcEvent) Pid() uint32 { + return e.ProcessPid +} + +func (e *ExitProcEvent) Tgid() uint32 { + return e.ProcessTgid +} + +type ExecProcEvent struct { + ProcessPid uint32 + ProcessTgid uint32 +} + +func (e *ExecProcEvent) Pid() uint32 { + return e.ProcessPid +} + +func (e *ExecProcEvent) Tgid() uint32 { + return e.ProcessTgid +} + +type ForkProcEvent struct { + ParentPid uint32 + ParentTgid uint32 + ChildPid uint32 + ChildTgid uint32 +} + +func (e *ForkProcEvent) Pid() uint32 { + return e.ParentPid +} + +func (e *ForkProcEvent) Tgid() uint32 { + return e.ParentTgid +} + +type CommProcEvent struct { + ProcessPid uint32 + ProcessTgid uint32 + Comm [16]byte +} + +func (e *CommProcEvent) Pid() uint32 { + return e.ProcessPid +} + +func (e *CommProcEvent) Tgid() uint32 { + return e.ProcessTgid +} + +func ProcEventMonitor(ch chan<- ProcEvent, done <-chan struct{}, errorChan chan<- error) error { + h, err := NewHandle() + if err != nil { + return err + } + defer h.Delete() + + s, err := nl.SubscribeAt(netns.None(), netns.None(), unix.NETLINK_CONNECTOR, CN_IDX_PROC) + if err != nil { + return err + } + + var nlmsg nl.NetlinkRequest + + nlmsg.Pid = uint32(os.Getpid()) + nlmsg.Type = unix.NLMSG_DONE + nlmsg.Len = uint32(unix.SizeofNlMsghdr) + + cm := nl.NewCnMsg(CN_IDX_PROC, CN_VAL_PROC, PROC_CN_MCAST_LISTEN) + nlmsg.AddData(cm) + + s.Send(&nlmsg) + + if done != nil { + go func() { + <-done + s.Close() + }() + } + + go func() { + defer close(ch) + for { + msgs, from, err := s.Receive() + if err != nil { + errorChan <- err + return + } + if from.Pid != nl.PidKernel { + errorChan <- fmt.Errorf("Wrong sender portid %d, expected %d", from.Pid, nl.PidKernel) + return + } + + for _, m := range msgs { + e := parseNetlinkMessage(m) + if e != nil { + ch <- *e + } + } + + } + }() + + return nil +} + +func parseNetlinkMessage(m syscall.NetlinkMessage) *ProcEvent { + if m.Header.Type == unix.NLMSG_DONE { + buf := bytes.NewBuffer(m.Data) + msg := &nl.CnMsg{} + hdr := &ProcEventHeader{} + binary.Read(buf, nl.NativeEndian(), msg) + binary.Read(buf, nl.NativeEndian(), hdr) + + pe := &ProcEvent{} + pe.setHeader(*hdr) + switch hdr.What { + case PROC_EVENT_EXIT: + event := &ExitProcEvent{} + binary.Read(buf, nl.NativeEndian(), event) + pe.Msg = event + return pe + case PROC_EVENT_FORK: + event := &ForkProcEvent{} + binary.Read(buf, nl.NativeEndian(), event) + pe.Msg = event + return pe + case PROC_EVENT_EXEC: + event := &ExecProcEvent{} + binary.Read(buf, nl.NativeEndian(), event) + pe.Msg = event + return pe + case PROC_EVENT_COMM: + event := &CommProcEvent{} + binary.Read(buf, nl.NativeEndian(), event) + pe.Msg = event + return pe + } + return nil + } + + return nil +} diff --git a/vendor/github.com/vishvananda/netlink/protinfo.go b/vendor/github.com/vishvananda/netlink/protinfo.go index 60b23b374..0163cba3a 100644 --- a/vendor/github.com/vishvananda/netlink/protinfo.go +++ b/vendor/github.com/vishvananda/netlink/protinfo.go @@ -6,14 +6,16 @@ import ( // Protinfo represents bridge flags from netlink. type Protinfo struct { - Hairpin bool - Guard bool - FastLeave bool - RootBlock bool - Learning bool - Flood bool - ProxyArp bool - ProxyArpWiFi bool + Hairpin bool + Guard bool + FastLeave bool + RootBlock bool + Learning bool + Flood bool + ProxyArp bool + ProxyArpWiFi bool + Isolated bool + NeighSuppress bool } // String returns a list of enabled flags @@ -47,6 +49,12 @@ func (prot *Protinfo) String() string { if prot.ProxyArpWiFi { boolStrings = append(boolStrings, "ProxyArpWiFi") } + if prot.Isolated { + boolStrings = append(boolStrings, "Isolated") + } + if prot.NeighSuppress { + boolStrings = append(boolStrings, "NeighSuppress") + } return strings.Join(boolStrings, " ") } diff --git a/vendor/github.com/vishvananda/netlink/protinfo_linux.go b/vendor/github.com/vishvananda/netlink/protinfo_linux.go index 15b65123c..1ba25d3cd 100644 --- a/vendor/github.com/vishvananda/netlink/protinfo_linux.go +++ b/vendor/github.com/vishvananda/netlink/protinfo_linux.go @@ -68,6 +68,10 @@ func parseProtinfo(infos []syscall.NetlinkRouteAttr) (pi Protinfo) { pi.ProxyArp = byteToBool(info.Value[0]) case nl.IFLA_BRPORT_PROXYARP_WIFI: pi.ProxyArpWiFi = byteToBool(info.Value[0]) + case nl.IFLA_BRPORT_ISOLATED: + pi.Isolated = byteToBool(info.Value[0]) + case nl.IFLA_BRPORT_NEIGH_SUPPRESS: + pi.NeighSuppress = byteToBool(info.Value[0]) } } return diff --git a/vendor/github.com/vishvananda/netlink/qdisc.go b/vendor/github.com/vishvananda/netlink/qdisc.go index af78305ac..067743d39 100644 --- a/vendor/github.com/vishvananda/netlink/qdisc.go +++ b/vendor/github.com/vishvananda/netlink/qdisc.go @@ -17,19 +17,29 @@ const ( HANDLE_MIN_EGRESS = 0xFFFFFFF3 ) +const ( + HORIZON_DROP_POLICY_CAP = 0 + HORIZON_DROP_POLICY_DROP = 1 + HORIZON_DROP_POLICY_DEFAULT = 255 +) + type Qdisc interface { Attrs() *QdiscAttrs Type() string } +type QdiscStatistics ClassStatistics + // QdiscAttrs represents a netlink qdisc. A qdisc is associated with a link, // has a handle, a parent and a refcnt. The root qdisc of a device should // have parent == HANDLE_ROOT. type QdiscAttrs struct { - LinkIndex int - Handle uint32 - Parent uint32 - Refcnt uint32 // read only + LinkIndex int + Handle uint32 + Parent uint32 + Refcnt uint32 // read only + IngressBlock *uint32 + Statistics *QdiscStatistics } func (q QdiscAttrs) String() string { @@ -113,6 +123,7 @@ type Htb struct { Defcls uint32 Debug uint32 DirectPkts uint32 + DirectQlen *uint32 } func NewHtb(attrs QdiscAttrs) *Htb { @@ -123,6 +134,7 @@ func NewHtb(attrs QdiscAttrs) *Htb { Rate2Quantum: 10, Debug: 0, DirectPkts: 0, + DirectQlen: nil, } } @@ -150,6 +162,7 @@ type NetemQdiscAttrs struct { ReorderCorr float32 // in % CorruptProb float32 // in % CorruptCorr float32 // in % + Rate64 uint64 } func (q NetemQdiscAttrs) String() string { @@ -174,6 +187,7 @@ type Netem struct { ReorderCorr uint32 CorruptProb uint32 CorruptCorr uint32 + Rate64 uint64 } func (netem *Netem) String() string { @@ -210,6 +224,19 @@ func (qdisc *Tbf) Type() string { return "tbf" } +// Clsact is a qdisc for adding filters +type Clsact struct { + QdiscAttrs +} + +func (qdisc *Clsact) Attrs() *QdiscAttrs { + return &qdisc.QdiscAttrs +} + +func (qdisc *Clsact) Type() string { + return "clsact" +} + // Ingress is a qdisc for adding ingress filters type Ingress struct { QdiscAttrs @@ -278,22 +305,25 @@ type Fq struct { FlowDefaultRate uint32 FlowMaxRate uint32 // called BucketsLog under the hood - Buckets uint32 - FlowRefillDelay uint32 - LowRateThreshold uint32 + Buckets uint32 + FlowRefillDelay uint32 + LowRateThreshold uint32 + Horizon uint32 + HorizonDropPolicy uint8 } func (fq *Fq) String() string { return fmt.Sprintf( - "{PacketLimit: %v, FlowPacketLimit: %v, Quantum: %v, InitialQuantum: %v, Pacing: %v, FlowDefaultRate: %v, FlowMaxRate: %v, Buckets: %v, FlowRefillDelay: %v, LowRateThreshold: %v}", - fq.PacketLimit, fq.FlowPacketLimit, fq.Quantum, fq.InitialQuantum, fq.Pacing, fq.FlowDefaultRate, fq.FlowMaxRate, fq.Buckets, fq.FlowRefillDelay, fq.LowRateThreshold, + "{PacketLimit: %v, FlowPacketLimit: %v, Quantum: %v, InitialQuantum: %v, Pacing: %v, FlowDefaultRate: %v, FlowMaxRate: %v, Buckets: %v, FlowRefillDelay: %v, LowRateThreshold: %v, Horizon: %v, HorizonDropPolicy: %v}", + fq.PacketLimit, fq.FlowPacketLimit, fq.Quantum, fq.InitialQuantum, fq.Pacing, fq.FlowDefaultRate, fq.FlowMaxRate, fq.Buckets, fq.FlowRefillDelay, fq.LowRateThreshold, fq.Horizon, fq.HorizonDropPolicy, ) } func NewFq(attrs QdiscAttrs) *Fq { return &Fq{ - QdiscAttrs: attrs, - Pacing: 1, + QdiscAttrs: attrs, + Pacing: 1, + HorizonDropPolicy: HORIZON_DROP_POLICY_DEFAULT, } } @@ -308,13 +338,15 @@ func (qdisc *Fq) Type() string { // FQ_Codel (Fair Queuing Controlled Delay) is queuing discipline that combines Fair Queuing with the CoDel AQM scheme. type FqCodel struct { QdiscAttrs - Target uint32 - Limit uint32 - Interval uint32 - ECN uint32 - Flows uint32 - Quantum uint32 - // There are some more attributes here, but support for them seems not ubiquitous + Target uint32 + Limit uint32 + Interval uint32 + ECN uint32 + Flows uint32 + Quantum uint32 + CEThreshold uint32 + DropBatchSize uint32 + MemoryLimit uint32 } func (fqcodel *FqCodel) String() string { @@ -338,3 +370,27 @@ func (qdisc *FqCodel) Attrs() *QdiscAttrs { func (qdisc *FqCodel) Type() string { return "fq_codel" } + +type Sfq struct { + QdiscAttrs + // TODO: Only the simplified options for SFQ are handled here. Support for the extended one can be added later. + Quantum uint8 + Perturb uint8 + Limit uint32 + Divisor uint8 +} + +func (sfq *Sfq) String() string { + return fmt.Sprintf( + "{%v -- Quantum: %v, Perturb: %v, Limit: %v, Divisor: %v}", + sfq.Attrs(), sfq.Quantum, sfq.Perturb, sfq.Limit, sfq.Divisor, + ) +} + +func (qdisc *Sfq) Attrs() *QdiscAttrs { + return &qdisc.QdiscAttrs +} + +func (qdisc *Sfq) Type() string { + return "sfq" +} diff --git a/vendor/github.com/vishvananda/netlink/qdisc_linux.go b/vendor/github.com/vishvananda/netlink/qdisc_linux.go index e9eee5908..e732ae3bd 100644 --- a/vendor/github.com/vishvananda/netlink/qdisc_linux.go +++ b/vendor/github.com/vishvananda/netlink/qdisc_linux.go @@ -5,6 +5,7 @@ import ( "io/ioutil" "strconv" "strings" + "sync" "syscall" "github.com/vishvananda/netlink/nl" @@ -17,6 +18,7 @@ func NewNetem(attrs QdiscAttrs, nattrs NetemQdiscAttrs) *Netem { var lossCorr, delayCorr, duplicateCorr uint32 var reorderProb, reorderCorr uint32 var corruptProb, corruptCorr uint32 + var rate64 uint64 latency := nattrs.Latency loss := Percentage2u32(nattrs.Loss) @@ -57,6 +59,7 @@ func NewNetem(attrs QdiscAttrs, nattrs NetemQdiscAttrs) *Netem { corruptProb = Percentage2u32(nattrs.CorruptProb) corruptCorr = Percentage2u32(nattrs.CorruptCorr) + rate64 = nattrs.Rate64 return &Netem{ QdiscAttrs: attrs, @@ -73,6 +76,7 @@ func NewNetem(attrs QdiscAttrs, nattrs NetemQdiscAttrs) *Netem { ReorderCorr: reorderCorr, CorruptProb: corruptProb, CorruptCorr: corruptCorr, + Rate64: rate64, } } @@ -159,6 +163,9 @@ func (h *Handle) qdiscModify(cmd, flags int, qdisc Qdisc) error { func qdiscPayload(req *nl.NetlinkRequest, qdisc Qdisc) error { req.AddData(nl.NewRtAttr(nl.TCA_KIND, nl.ZeroTerminated(qdisc.Type()))) + if qdisc.Attrs().IngressBlock != nil { + req.AddData(nl.NewRtAttr(nl.TCA_INGRESS_BLOCK, nl.Uint32Attr(*qdisc.Attrs().IngressBlock))) + } options := nl.NewRtAttr(nl.TCA_OPTIONS, nil) @@ -194,7 +201,9 @@ func qdiscPayload(req *nl.NetlinkRequest, qdisc Qdisc) error { opt.Debug = qdisc.Debug opt.DirectPkts = qdisc.DirectPkts options.AddRtAttr(nl.TCA_HTB_INIT, opt.Serialize()) - // options.AddRtAttr(nl.TCA_HTB_DIRECT_QLEN, opt.Serialize()) + if qdisc.DirectQlen != nil { + options.AddRtAttr(nl.TCA_HTB_DIRECT_QLEN, nl.Uint32Attr(*qdisc.DirectQlen)) + } case *Hfsc: opt := nl.TcHfscOpt{} opt.Defcls = qdisc.Defcls @@ -231,6 +240,19 @@ func qdiscPayload(req *nl.NetlinkRequest, qdisc Qdisc) error { if reorder.Probability > 0 { options.AddRtAttr(nl.TCA_NETEM_REORDER, reorder.Serialize()) } + // Rate + if qdisc.Rate64 > 0 { + rate := nl.TcNetemRate{} + if qdisc.Rate64 >= uint64(1<<32) { + options.AddRtAttr(nl.TCA_NETEM_RATE64, nl.Uint64Attr(qdisc.Rate64)) + rate.Rate = ^uint32(0) + } else { + rate.Rate = uint32(qdisc.Rate64) + } + options.AddRtAttr(nl.TCA_NETEM_RATE, rate.Serialize()) + } + case *Clsact: + options = nil case *Ingress: // ingress filters must use the proper handle if qdisc.Attrs().Parent != HANDLE_INGRESS { @@ -250,13 +272,24 @@ func qdiscPayload(req *nl.NetlinkRequest, qdisc Qdisc) error { if qdisc.Quantum > 0 { options.AddRtAttr(nl.TCA_FQ_CODEL_QUANTUM, nl.Uint32Attr((uint32(qdisc.Quantum)))) } - + if qdisc.CEThreshold > 0 { + options.AddRtAttr(nl.TCA_FQ_CODEL_CE_THRESHOLD, nl.Uint32Attr(qdisc.CEThreshold)) + } + if qdisc.DropBatchSize > 0 { + options.AddRtAttr(nl.TCA_FQ_CODEL_DROP_BATCH_SIZE, nl.Uint32Attr(qdisc.DropBatchSize)) + } + if qdisc.MemoryLimit > 0 { + options.AddRtAttr(nl.TCA_FQ_CODEL_MEMORY_LIMIT, nl.Uint32Attr(qdisc.MemoryLimit)) + } case *Fq: options.AddRtAttr(nl.TCA_FQ_RATE_ENABLE, nl.Uint32Attr((uint32(qdisc.Pacing)))) if qdisc.Buckets > 0 { options.AddRtAttr(nl.TCA_FQ_BUCKETS_LOG, nl.Uint32Attr((uint32(qdisc.Buckets)))) } + if qdisc.PacketLimit > 0 { + options.AddRtAttr(nl.TCA_FQ_PLIMIT, nl.Uint32Attr((uint32(qdisc.PacketLimit)))) + } if qdisc.LowRateThreshold > 0 { options.AddRtAttr(nl.TCA_FQ_LOW_RATE_THRESHOLD, nl.Uint32Attr((uint32(qdisc.LowRateThreshold)))) } @@ -278,6 +311,20 @@ func qdiscPayload(req *nl.NetlinkRequest, qdisc Qdisc) error { if qdisc.FlowDefaultRate > 0 { options.AddRtAttr(nl.TCA_FQ_FLOW_DEFAULT_RATE, nl.Uint32Attr((uint32(qdisc.FlowDefaultRate)))) } + if qdisc.Horizon > 0 { + options.AddRtAttr(nl.TCA_FQ_HORIZON, nl.Uint32Attr(qdisc.Horizon)) + } + if qdisc.HorizonDropPolicy != HORIZON_DROP_POLICY_DEFAULT { + options.AddRtAttr(nl.TCA_FQ_HORIZON_DROP, nl.Uint8Attr(qdisc.HorizonDropPolicy)) + } + case *Sfq: + opt := nl.TcSfqQoptV1{} + opt.TcSfqQopt.Quantum = qdisc.Quantum + opt.TcSfqQopt.Perturb = int32(qdisc.Perturb) + opt.TcSfqQopt.Limit = qdisc.Limit + opt.TcSfqQopt.Divisor = qdisc.Divisor + + options = nl.NewRtAttr(nl.TCA_OPTIONS, opt.Serialize()) default: options = nil } @@ -362,6 +409,10 @@ func (h *Handle) QdiscList(link Link) ([]Qdisc, error) { qdisc = &FqCodel{} case "netem": qdisc = &Netem{} + case "sfq": + qdisc = &Sfq{} + case "clsact": + qdisc = &Clsact{} default: qdisc = &GenericQdisc{QdiscType: qdiscType} } @@ -417,9 +468,29 @@ func (h *Handle) QdiscList(link Link) ([]Qdisc, error) { if err := parseNetemData(qdisc, attr.Value); err != nil { return nil, err } + case "sfq": + if err := parseSfqData(qdisc, attr.Value); err != nil { + return nil, err + } // no options for ingress } + case nl.TCA_INGRESS_BLOCK: + ingressBlock := new(uint32) + *ingressBlock = native.Uint32(attr.Value) + base.IngressBlock = ingressBlock + case nl.TCA_STATS: + s, err := parseTcStats(attr.Value) + if err != nil { + return nil, err + } + base.Statistics = (*QdiscStatistics)(s) + case nl.TCA_STATS2: + s, err := parseTcStats2(attr.Value) + if err != nil { + return nil, err + } + base.Statistics = (*QdiscStatistics)(s) } } *qdisc.Attrs() = base @@ -446,7 +517,6 @@ func parsePrioData(qdisc Qdisc, value []byte) error { } func parseHtbData(qdisc Qdisc, data []syscall.NetlinkRouteAttr) error { - native = nl.NativeEndian() htb := qdisc.(*Htb) for _, datum := range data { switch datum.Attr.Type { @@ -458,15 +528,14 @@ func parseHtbData(qdisc Qdisc, data []syscall.NetlinkRouteAttr) error { htb.Debug = opt.Debug htb.DirectPkts = opt.DirectPkts case nl.TCA_HTB_DIRECT_QLEN: - // TODO - //htb.DirectQlen = native.uint32(datum.Value) + directQlen := native.Uint32(datum.Value) + htb.DirectQlen = &directQlen } } return nil } func parseFqCodelData(qdisc Qdisc, data []syscall.NetlinkRouteAttr) error { - native = nl.NativeEndian() fqCodel := qdisc.(*FqCodel) for _, datum := range data { @@ -483,6 +552,12 @@ func parseFqCodelData(qdisc Qdisc, data []syscall.NetlinkRouteAttr) error { fqCodel.Flows = native.Uint32(datum.Value) case nl.TCA_FQ_CODEL_QUANTUM: fqCodel.Quantum = native.Uint32(datum.Value) + case nl.TCA_FQ_CODEL_CE_THRESHOLD: + fqCodel.CEThreshold = native.Uint32(datum.Value) + case nl.TCA_FQ_CODEL_DROP_BATCH_SIZE: + fqCodel.DropBatchSize = native.Uint32(datum.Value) + case nl.TCA_FQ_CODEL_MEMORY_LIMIT: + fqCodel.MemoryLimit = native.Uint32(datum.Value) } } return nil @@ -490,13 +565,11 @@ func parseFqCodelData(qdisc Qdisc, data []syscall.NetlinkRouteAttr) error { func parseHfscData(qdisc Qdisc, data []byte) error { Hfsc := qdisc.(*Hfsc) - native = nl.NativeEndian() Hfsc.Defcls = native.Uint16(data) return nil } func parseFqData(qdisc Qdisc, data []syscall.NetlinkRouteAttr) error { - native = nl.NativeEndian() fq := qdisc.(*Fq) for _, datum := range data { switch datum.Attr.Type { @@ -522,6 +595,11 @@ func parseFqData(qdisc Qdisc, data []syscall.NetlinkRouteAttr) error { fq.FlowMaxRate = native.Uint32(datum.Value) case nl.TCA_FQ_FLOW_DEFAULT_RATE: fq.FlowDefaultRate = native.Uint32(datum.Value) + case nl.TCA_FQ_HORIZON: + fq.Horizon = native.Uint32(datum.Value) + case nl.TCA_FQ_HORIZON_DROP: + fq.HorizonDropPolicy = datum.Value[0] + } } return nil @@ -540,6 +618,8 @@ func parseNetemData(qdisc Qdisc, value []byte) error { if err != nil { return err } + var rate *nl.TcNetemRate + var rate64 uint64 for _, datum := range data { switch datum.Attr.Type { case nl.TCA_NETEM_CORR: @@ -555,13 +635,23 @@ func parseNetemData(qdisc Qdisc, value []byte) error { opt := nl.DeserializeTcNetemReorder(datum.Value) netem.ReorderProb = opt.Probability netem.ReorderCorr = opt.Correlation + case nl.TCA_NETEM_RATE: + rate = nl.DeserializeTcNetemRate(datum.Value) + case nl.TCA_NETEM_RATE64: + rate64 = native.Uint64(datum.Value) } } + if rate != nil { + netem.Rate64 = uint64(rate.Rate) + if rate64 > 0 { + netem.Rate64 = rate64 + } + } + return nil } func parseTbfData(qdisc Qdisc, data []syscall.NetlinkRouteAttr) error { - native = nl.NativeEndian() tbf := qdisc.(*Tbf) for _, datum := range data { switch datum.Attr.Type { @@ -582,6 +672,17 @@ func parseTbfData(qdisc Qdisc, data []syscall.NetlinkRouteAttr) error { return nil } +func parseSfqData(qdisc Qdisc, value []byte) error { + sfq := qdisc.(*Sfq) + opt := nl.DeserializeTcSfqQoptV1(value) + sfq.Quantum = opt.TcSfqQopt.Quantum + sfq.Perturb = uint8(opt.TcSfqQopt.Perturb) + sfq.Limit = opt.TcSfqQopt.Limit + sfq.Divisor = opt.TcSfqQopt.Divisor + + return nil +} + const ( TIME_UNITS_PER_SEC = 1000000 ) @@ -590,6 +691,9 @@ var ( tickInUsec float64 clockFactor float64 hz float64 + + // Without this, the go race detector may report races. + initClockMutex sync.Mutex ) func initClock() { @@ -598,10 +702,10 @@ func initClock() { return } parts := strings.Split(strings.TrimSpace(string(data)), " ") - if len(parts) < 3 { + if len(parts) < 4 { return } - var vals [3]uint64 + var vals [4]uint64 for i := range vals { val, err := strconv.ParseUint(parts[i], 16, 32) if err != nil { @@ -615,10 +719,17 @@ func initClock() { } clockFactor = float64(vals[2]) / TIME_UNITS_PER_SEC tickInUsec = float64(vals[0]) / float64(vals[1]) * clockFactor - hz = float64(vals[0]) + if vals[2] == 1000000 { + // ref https://git.kernel.org/pub/scm/network/iproute2/iproute2.git/tree/lib/utils.c#n963 + hz = float64(vals[3]) + } else { + hz = 100 + } } func TickInUsec() float64 { + initClockMutex.Lock() + defer initClockMutex.Unlock() if tickInUsec == 0.0 { initClock() } @@ -626,6 +737,8 @@ func TickInUsec() float64 { } func ClockFactor() float64 { + initClockMutex.Lock() + defer initClockMutex.Unlock() if clockFactor == 0.0 { initClock() } @@ -633,6 +746,8 @@ func ClockFactor() float64 { } func Hz() float64 { + initClockMutex.Lock() + defer initClockMutex.Unlock() if hz == 0.0 { initClock() } @@ -663,6 +778,11 @@ func latency(rate uint64, limit, buffer uint32) float64 { return TIME_UNITS_PER_SEC*(float64(limit)/float64(rate)) - float64(tick2Time(buffer)) } -func Xmittime(rate uint64, size uint32) float64 { - return TickInUsec() * TIME_UNITS_PER_SEC * (float64(size) / float64(rate)) +func Xmittime(rate uint64, size uint32) uint32 { + // https://git.kernel.org/pub/scm/network/iproute2/iproute2.git/tree/tc/tc_core.c#n62 + return time2Tick(uint32(TIME_UNITS_PER_SEC * (float64(size) / float64(rate)))) +} + +func Xmitsize(rate uint64, ticks uint32) uint32 { + return uint32((float64(rate) * float64(tick2Time(ticks))) / TIME_UNITS_PER_SEC) } diff --git a/vendor/github.com/vishvananda/netlink/rdma_link_linux.go b/vendor/github.com/vishvananda/netlink/rdma_link_linux.go index 2d0bdc8c3..036399db6 100644 --- a/vendor/github.com/vishvananda/netlink/rdma_link_linux.go +++ b/vendor/github.com/vishvananda/netlink/rdma_link_linux.go @@ -77,28 +77,39 @@ func executeOneGetRdmaLink(data []byte) (*RdmaLink, error) { return &link, nil } -func execRdmaGetLink(req *nl.NetlinkRequest, name string) (*RdmaLink, error) { +func execRdmaSetLink(req *nl.NetlinkRequest) error { + + _, err := req.Execute(unix.NETLINK_RDMA, 0) + return err +} + +// RdmaLinkList gets a list of RDMA link devices. +// Equivalent to: `rdma dev show` +func RdmaLinkList() ([]*RdmaLink, error) { + return pkgHandle.RdmaLinkList() +} + +// RdmaLinkList gets a list of RDMA link devices. +// Equivalent to: `rdma dev show` +func (h *Handle) RdmaLinkList() ([]*RdmaLink, error) { + proto := getProtoField(nl.RDMA_NL_NLDEV, nl.RDMA_NLDEV_CMD_GET) + req := h.newNetlinkRequest(proto, unix.NLM_F_ACK|unix.NLM_F_DUMP) msgs, err := req.Execute(unix.NETLINK_RDMA, 0) if err != nil { return nil, err } + + var res []*RdmaLink for _, m := range msgs { link, err := executeOneGetRdmaLink(m) if err != nil { return nil, err } - if link.Attrs.Name == name { - return link, nil - } + res = append(res, link) } - return nil, fmt.Errorf("Rdma device %v not found", name) -} - -func execRdmaSetLink(req *nl.NetlinkRequest) error { - _, err := req.Execute(unix.NETLINK_RDMA, 0) - return err + return res, nil } // RdmaLinkByName finds a link by name and returns a pointer to the object if @@ -110,11 +121,16 @@ func RdmaLinkByName(name string) (*RdmaLink, error) { // RdmaLinkByName finds a link by name and returns a pointer to the object if // found and nil error, otherwise returns error code. func (h *Handle) RdmaLinkByName(name string) (*RdmaLink, error) { - - proto := getProtoField(nl.RDMA_NL_NLDEV, nl.RDMA_NLDEV_CMD_GET) - req := h.newNetlinkRequest(proto, unix.NLM_F_ACK|unix.NLM_F_DUMP) - - return execRdmaGetLink(req, name) + links, err := h.RdmaLinkList() + if err != nil { + return nil, err + } + for _, link := range links { + if link.Attrs.Name == name { + return link, nil + } + } + return nil, fmt.Errorf("Rdma device %v not found", name) } // RdmaLinkSetName sets the name of the rdma link device. Return nil on success @@ -262,3 +278,54 @@ func (h *Handle) RdmaLinkSetNsFd(link *RdmaLink, fd uint32) error { return execRdmaSetLink(req) } + +// RdmaLinkDel deletes an rdma link +// +// Similar to: rdma link delete NAME +// REF: https://man7.org/linux/man-pages/man8/rdma-link.8.html +func RdmaLinkDel(name string) error { + return pkgHandle.RdmaLinkDel(name) +} + +// RdmaLinkDel deletes an rdma link. +func (h *Handle) RdmaLinkDel(name string) error { + link, err := h.RdmaLinkByName(name) + if err != nil { + return err + } + + proto := getProtoField(nl.RDMA_NL_NLDEV, nl.RDMA_NLDEV_CMD_DELLINK) + req := h.newNetlinkRequest(proto, unix.NLM_F_ACK) + + b := make([]byte, 4) + native.PutUint32(b, link.Attrs.Index) + req.AddData(nl.NewRtAttr(nl.RDMA_NLDEV_ATTR_DEV_INDEX, b)) + + _, err = req.Execute(unix.NETLINK_RDMA, 0) + return err +} + +// RdmaLinkAdd adds an rdma link for the specified type to the network device. +// Similar to: rdma link add NAME type TYPE netdev NETDEV +// NAME - specifies the new name of the rdma link to add +// TYPE - specifies which rdma type to use. Link types: +// rxe - Soft RoCE driver +// siw - Soft iWARP driver +// NETDEV - specifies the network device to which the link is bound +// +// REF: https://man7.org/linux/man-pages/man8/rdma-link.8.html +func RdmaLinkAdd(linkName, linkType, netdev string) error { + return pkgHandle.RdmaLinkAdd(linkName, linkType, netdev) +} + +// RdmaLinkAdd adds an rdma link for the specified type to the network device. +func (h *Handle) RdmaLinkAdd(linkName string, linkType string, netdev string) error { + proto := getProtoField(nl.RDMA_NL_NLDEV, nl.RDMA_NLDEV_CMD_NEWLINK) + req := h.newNetlinkRequest(proto, unix.NLM_F_ACK) + + req.AddData(nl.NewRtAttr(nl.RDMA_NLDEV_ATTR_DEV_NAME, nl.ZeroTerminated(linkName))) + req.AddData(nl.NewRtAttr(nl.RDMA_NLDEV_ATTR_LINK_TYPE, nl.ZeroTerminated(linkType))) + req.AddData(nl.NewRtAttr(nl.RDMA_NLDEV_ATTR_NDEV_NAME, nl.ZeroTerminated(netdev))) + _, err := req.Execute(unix.NETLINK_RDMA, 0) + return err +} diff --git a/vendor/github.com/vishvananda/netlink/route.go b/vendor/github.com/vishvananda/netlink/route.go index 58ff1af60..1b4555d5c 100644 --- a/vendor/github.com/vishvananda/netlink/route.go +++ b/vendor/github.com/vishvananda/netlink/route.go @@ -11,6 +11,24 @@ type Scope uint8 type NextHopFlag int +const ( + RT_FILTER_PROTOCOL uint64 = 1 << (1 + iota) + RT_FILTER_SCOPE + RT_FILTER_TYPE + RT_FILTER_TOS + RT_FILTER_IIF + RT_FILTER_OIF + RT_FILTER_DST + RT_FILTER_SRC + RT_FILTER_GW + RT_FILTER_TABLE + RT_FILTER_HOPLIMIT + RT_FILTER_PRIORITY + RT_FILTER_MARK + RT_FILTER_MASK + RT_FILTER_REALM +) + type Destination interface { Family() int Decode([]byte) error @@ -27,27 +45,46 @@ type Encap interface { Equal(Encap) bool } +//Protocol describe what was the originator of the route +type RouteProtocol int + // Route represents a netlink route. type Route struct { - LinkIndex int - ILinkIndex int - Scope Scope - Dst *net.IPNet - Src net.IP - Gw net.IP - MultiPath []*NexthopInfo - Protocol int - Priority int - Table int - Type int - Tos int - Flags int - MPLSDst *int - NewDst Destination - Encap Encap - MTU int - AdvMSS int - Hoplimit int + LinkIndex int + ILinkIndex int + Scope Scope + Dst *net.IPNet + Src net.IP + Gw net.IP + MultiPath []*NexthopInfo + Protocol RouteProtocol + Priority int + Family int + Table int + Type int + Tos int + Flags int + MPLSDst *int + NewDst Destination + Encap Encap + Via Destination + Realm int + MTU int + Window int + Rtt int + RttVar int + Ssthresh int + Cwnd int + AdvMSS int + Reordering int + Hoplimit int + InitCwnd int + Features int + RtoMin int + InitRwnd int + QuickACK int + Congctl string + FastOpenNoCookie int } func (r Route) String() string { @@ -66,6 +103,9 @@ func (r Route) String() string { if r.Encap != nil { elems = append(elems, fmt.Sprintf("Encap: %s", r.Encap)) } + if r.Via != nil { + elems = append(elems, fmt.Sprintf("Via: %s", r.Via)) + } elems = append(elems, fmt.Sprintf("Src: %s", r.Src)) if len(r.MultiPath) > 0 { elems = append(elems, fmt.Sprintf("Gw: %s", r.MultiPath)) @@ -74,6 +114,7 @@ func (r Route) String() string { } elems = append(elems, fmt.Sprintf("Flags: %s", r.ListFlags())) elems = append(elems, fmt.Sprintf("Table: %d", r.Table)) + elems = append(elems, fmt.Sprintf("Realm: %d", r.Realm)) return fmt.Sprintf("{%s}", strings.Join(elems, " ")) } @@ -87,6 +128,7 @@ func (r Route) Equal(x Route) bool { nexthopInfoSlice(r.MultiPath).Equal(x.MultiPath) && r.Protocol == x.Protocol && r.Priority == x.Priority && + r.Realm == x.Realm && r.Table == x.Table && r.Type == x.Type && r.Tos == x.Tos && @@ -94,6 +136,7 @@ func (r Route) Equal(x Route) bool { r.Flags == x.Flags && (r.MPLSDst == x.MPLSDst || (r.MPLSDst != nil && x.MPLSDst != nil && *r.MPLSDst == *x.MPLSDst)) && (r.NewDst == x.NewDst || (r.NewDst != nil && r.NewDst.Equal(x.NewDst))) && + (r.Via == x.Via || (r.Via != nil && r.Via.Equal(x.Via))) && (r.Encap == x.Encap || (r.Encap != nil && r.Encap.Equal(x.Encap))) } @@ -111,8 +154,15 @@ type flagString struct { } // RouteUpdate is sent when a route changes - type is RTM_NEWROUTE or RTM_DELROUTE + +// NlFlags is only non-zero for RTM_NEWROUTE, the following flags can be set: +// - unix.NLM_F_REPLACE - Replace existing matching config object with this request +// - unix.NLM_F_EXCL - Don't replace the config object if it already exists +// - unix.NLM_F_CREATE - Create config object if it doesn't already exist +// - unix.NLM_F_APPEND - Add to the end of the object list type RouteUpdate struct { - Type uint16 + Type uint16 + NlFlags uint16 Route } @@ -123,6 +173,7 @@ type NexthopInfo struct { Flags int NewDst Destination Encap Encap + Via Destination } func (n *NexthopInfo) String() string { @@ -134,6 +185,9 @@ func (n *NexthopInfo) String() string { if n.Encap != nil { elems = append(elems, fmt.Sprintf("Encap: %s", n.Encap)) } + if n.Via != nil { + elems = append(elems, fmt.Sprintf("Via: %s", n.Via)) + } elems = append(elems, fmt.Sprintf("Weight: %d", n.Hops+1)) elems = append(elems, fmt.Sprintf("Gw: %s", n.Gw)) elems = append(elems, fmt.Sprintf("Flags: %s", n.ListFlags())) diff --git a/vendor/github.com/vishvananda/netlink/route_linux.go b/vendor/github.com/vishvananda/netlink/route_linux.go index c69c595ed..0cd4f8363 100644 --- a/vendor/github.com/vishvananda/netlink/route_linux.go +++ b/vendor/github.com/vishvananda/netlink/route_linux.go @@ -1,8 +1,11 @@ package netlink import ( + "bytes" + "encoding/binary" "fmt" "net" + "strconv" "strings" "syscall" @@ -21,19 +24,22 @@ const ( SCOPE_NOWHERE Scope = unix.RT_SCOPE_NOWHERE ) -const ( - RT_FILTER_PROTOCOL uint64 = 1 << (1 + iota) - RT_FILTER_SCOPE - RT_FILTER_TYPE - RT_FILTER_TOS - RT_FILTER_IIF - RT_FILTER_OIF - RT_FILTER_DST - RT_FILTER_SRC - RT_FILTER_GW - RT_FILTER_TABLE - RT_FILTER_HOPLIMIT -) +func (s Scope) String() string { + switch s { + case SCOPE_UNIVERSE: + return "universe" + case SCOPE_SITE: + return "site" + case SCOPE_LINK: + return "link" + case SCOPE_HOST: + return "host" + case SCOPE_NOWHERE: + return "nowhere" + default: + return "unknown" + } +} const ( FLAG_ONLINK NextHopFlag = unix.RTNH_F_ONLINK @@ -128,7 +134,6 @@ func (e *MPLSEncap) Decode(buf []byte) error { if len(buf) < 4 { return fmt.Errorf("lack of bytes") } - native := nl.NativeEndian() l := native.Uint16(buf) if len(buf) < int(l) { return fmt.Errorf("lack of bytes") @@ -144,7 +149,6 @@ func (e *MPLSEncap) Decode(buf []byte) error { func (e *MPLSEncap) Encode() ([]byte, error) { s := nl.EncodeMPLSStack(e.Labels...) - native := nl.NativeEndian() hdr := make([]byte, 4) native.PutUint16(hdr, uint16(len(s)+4)) native.PutUint16(hdr[2:], nl.MPLS_IPTUNNEL_DST) @@ -200,7 +204,6 @@ func (e *SEG6Encap) Decode(buf []byte) error { if len(buf) < 4 { return fmt.Errorf("lack of bytes") } - native := nl.NativeEndian() // Get Length(l) & Type(typ) : 2 + 2 bytes l := native.Uint16(buf) if len(buf) < int(l) { @@ -220,7 +223,6 @@ func (e *SEG6Encap) Decode(buf []byte) error { } func (e *SEG6Encap) Encode() ([]byte, error) { s, err := nl.EncodeSEG6Encap(e.Mode, e.Segments) - native := nl.NativeEndian() hdr := make([]byte, 4) native.PutUint16(hdr, uint16(len(s)+4)) native.PutUint16(hdr[2:], nl.SEG6_IPTUNNEL_SRH) @@ -230,7 +232,7 @@ func (e *SEG6Encap) String() string { segs := make([]string, 0, len(e.Segments)) // append segment backwards (from n to 0) since seg#0 is the last segment. for i := len(e.Segments); i > 0; i-- { - segs = append(segs, fmt.Sprintf("%s", e.Segments[i-1])) + segs = append(segs, e.Segments[i-1].String()) } str := fmt.Sprintf("mode %s segs %d [ %s ]", nl.SEG6EncapModeString(e.Mode), len(e.Segments), strings.Join(segs, " ")) @@ -271,6 +273,16 @@ type SEG6LocalEncap struct { In6Addr net.IP Iif int Oif int + bpf bpfObj +} + +func (e *SEG6LocalEncap) SetProg(progFd int, progName string) error { + if progFd <= 0 { + return fmt.Errorf("seg6local bpf SetProg: invalid fd") + } + e.bpf.progFd = progFd + e.bpf.progName = progName + return nil } func (e *SEG6LocalEncap) Type() int { @@ -281,7 +293,6 @@ func (e *SEG6LocalEncap) Decode(buf []byte) error { if err != nil { return err } - native := nl.NativeEndian() for _, attr := range attrs { switch attr.Attr.Type { case nl.SEG6_LOCAL_ACTION: @@ -305,13 +316,28 @@ func (e *SEG6LocalEncap) Decode(buf []byte) error { case nl.SEG6_LOCAL_OIF: e.Oif = int(native.Uint32(attr.Value[0:4])) e.Flags[nl.SEG6_LOCAL_OIF] = true + case nl.SEG6_LOCAL_BPF: + var bpfAttrs []syscall.NetlinkRouteAttr + bpfAttrs, err = nl.ParseRouteAttr(attr.Value) + bpfobj := bpfObj{} + for _, bpfAttr := range bpfAttrs { + switch bpfAttr.Attr.Type { + case nl.LWT_BPF_PROG_FD: + bpfobj.progFd = int(native.Uint32(bpfAttr.Value)) + case nl.LWT_BPF_PROG_NAME: + bpfobj.progName = string(bpfAttr.Value) + default: + err = fmt.Errorf("seg6local bpf decode: unknown attribute: Type %d", bpfAttr.Attr) + } + } + e.bpf = bpfobj + e.Flags[nl.SEG6_LOCAL_BPF] = true } } return err } func (e *SEG6LocalEncap) Encode() ([]byte, error) { var err error - native := nl.NativeEndian() res := make([]byte, 8) native.PutUint16(res, 8) // length native.PutUint16(res[2:], nl.SEG6_LOCAL_ACTION) @@ -367,6 +393,16 @@ func (e *SEG6LocalEncap) Encode() ([]byte, error) { native.PutUint32(attr[4:], uint32(e.Oif)) res = append(res, attr...) } + if e.Flags[nl.SEG6_LOCAL_BPF] { + attr := nl.NewRtAttr(nl.SEG6_LOCAL_BPF, []byte{}) + if e.bpf.progFd != 0 { + attr.AddRtAttr(nl.LWT_BPF_PROG_FD, nl.Uint32Attr(uint32(e.bpf.progFd))) + } + if e.bpf.progName != "" { + attr.AddRtAttr(nl.LWT_BPF_PROG_NAME, nl.ZeroTerminated(e.bpf.progName)) + } + res = append(res, attr.Serialize()...) + } return res, err } func (e *SEG6LocalEncap) String() string { @@ -400,12 +436,15 @@ func (e *SEG6LocalEncap) String() string { } if e.Flags[nl.SEG6_LOCAL_SRH] { segs := make([]string, 0, len(e.Segments)) - //append segment backwards (from n to 0) since seg#0 is the last segment. + // append segment backwards (from n to 0) since seg#0 is the last segment. for i := len(e.Segments); i > 0; i-- { - segs = append(segs, fmt.Sprintf("%s", e.Segments[i-1])) + segs = append(segs, e.Segments[i-1].String()) } strs = append(strs, fmt.Sprintf("segs %d [ %s ]", len(e.Segments), strings.Join(segs, " "))) } + if e.Flags[nl.SEG6_LOCAL_BPF] { + strs = append(strs, fmt.Sprintf("bpf %s[%d]", e.bpf.progName, e.bpf.progFd)) + } return strings.Join(strs, " ") } func (e *SEG6LocalEncap) Equal(x Encap) bool { @@ -437,12 +476,316 @@ func (e *SEG6LocalEncap) Equal(x Encap) bool { if !e.InAddr.Equal(o.InAddr) || !e.In6Addr.Equal(o.In6Addr) { return false } - if e.Action != o.Action || e.Table != o.Table || e.Iif != o.Iif || e.Oif != o.Oif { + if e.Action != o.Action || e.Table != o.Table || e.Iif != o.Iif || e.Oif != o.Oif || e.bpf != o.bpf { + return false + } + return true +} + +// Encap BPF definitions +type bpfObj struct { + progFd int + progName string +} +type BpfEncap struct { + progs [nl.LWT_BPF_MAX]bpfObj + headroom int +} + +// SetProg adds a bpf function to the route via netlink RTA_ENCAP. The fd must be a bpf +// program loaded with bpf(type=BPF_PROG_TYPE_LWT_*) matching the direction the program should +// be applied to (LWT_BPF_IN, LWT_BPF_OUT, LWT_BPF_XMIT). +func (e *BpfEncap) SetProg(mode, progFd int, progName string) error { + if progFd <= 0 { + return fmt.Errorf("lwt bpf SetProg: invalid fd") + } + if mode <= nl.LWT_BPF_UNSPEC || mode >= nl.LWT_BPF_XMIT_HEADROOM { + return fmt.Errorf("lwt bpf SetProg:invalid mode") + } + e.progs[mode].progFd = progFd + e.progs[mode].progName = fmt.Sprintf("%s[fd:%d]", progName, progFd) + return nil +} + +// SetXmitHeadroom sets the xmit headroom (LWT_BPF_MAX_HEADROOM) via netlink RTA_ENCAP. +// maximum headroom is LWT_BPF_MAX_HEADROOM +func (e *BpfEncap) SetXmitHeadroom(headroom int) error { + if headroom > nl.LWT_BPF_MAX_HEADROOM || headroom < 0 { + return fmt.Errorf("invalid headroom size. range is 0 - %d", nl.LWT_BPF_MAX_HEADROOM) + } + e.headroom = headroom + return nil +} + +func (e *BpfEncap) Type() int { + return nl.LWTUNNEL_ENCAP_BPF +} +func (e *BpfEncap) Decode(buf []byte) error { + if len(buf) < 4 { + return fmt.Errorf("lwt bpf decode: lack of bytes") + } + native := nl.NativeEndian() + attrs, err := nl.ParseRouteAttr(buf) + if err != nil { + return fmt.Errorf("lwt bpf decode: failed parsing attribute. err: %v", err) + } + for _, attr := range attrs { + if int(attr.Attr.Type) < 1 { + // nl.LWT_BPF_UNSPEC + continue + } + if int(attr.Attr.Type) > nl.LWT_BPF_MAX { + return fmt.Errorf("lwt bpf decode: received unknown attribute type: %d", attr.Attr.Type) + } + switch int(attr.Attr.Type) { + case nl.LWT_BPF_MAX_HEADROOM: + e.headroom = int(native.Uint32(attr.Value)) + default: + bpfO := bpfObj{} + parsedAttrs, err := nl.ParseRouteAttr(attr.Value) + if err != nil { + return fmt.Errorf("lwt bpf decode: failed parsing route attribute") + } + for _, parsedAttr := range parsedAttrs { + switch int(parsedAttr.Attr.Type) { + case nl.LWT_BPF_PROG_FD: + bpfO.progFd = int(native.Uint32(parsedAttr.Value)) + case nl.LWT_BPF_PROG_NAME: + bpfO.progName = string(parsedAttr.Value) + default: + return fmt.Errorf("lwt bpf decode: received unknown attribute: type: %d, len: %d", parsedAttr.Attr.Type, parsedAttr.Attr.Len) + } + } + e.progs[attr.Attr.Type] = bpfO + } + } + return nil +} + +func (e *BpfEncap) Encode() ([]byte, error) { + buf := make([]byte, 0) + native = nl.NativeEndian() + for index, attr := range e.progs { + nlMsg := nl.NewRtAttr(index, []byte{}) + if attr.progFd != 0 { + nlMsg.AddRtAttr(nl.LWT_BPF_PROG_FD, nl.Uint32Attr(uint32(attr.progFd))) + } + if attr.progName != "" { + nlMsg.AddRtAttr(nl.LWT_BPF_PROG_NAME, nl.ZeroTerminated(attr.progName)) + } + if nlMsg.Len() > 4 { + buf = append(buf, nlMsg.Serialize()...) + } + } + if len(buf) <= 4 { + return nil, fmt.Errorf("lwt bpf encode: bpf obj definitions returned empty buffer") + } + if e.headroom > 0 { + hRoom := nl.NewRtAttr(nl.LWT_BPF_XMIT_HEADROOM, nl.Uint32Attr(uint32(e.headroom))) + buf = append(buf, hRoom.Serialize()...) + } + return buf, nil +} + +func (e *BpfEncap) String() string { + progs := make([]string, 0) + for index, obj := range e.progs { + empty := bpfObj{} + switch index { + case nl.LWT_BPF_IN: + if obj != empty { + progs = append(progs, fmt.Sprintf("in: %s", obj.progName)) + } + case nl.LWT_BPF_OUT: + if obj != empty { + progs = append(progs, fmt.Sprintf("out: %s", obj.progName)) + } + case nl.LWT_BPF_XMIT: + if obj != empty { + progs = append(progs, fmt.Sprintf("xmit: %s", obj.progName)) + } + } + } + if e.headroom > 0 { + progs = append(progs, fmt.Sprintf("xmit headroom: %d", e.headroom)) + } + return strings.Join(progs, " ") +} + +func (e *BpfEncap) Equal(x Encap) bool { + o, ok := x.(*BpfEncap) + if !ok { + return false + } + if e.headroom != o.headroom { + return false + } + for i := range o.progs { + if o.progs[i] != e.progs[i] { + return false + } + } + return true +} + +// IP6tnlEncap definition +type IP6tnlEncap struct { + ID uint64 + Dst net.IP + Src net.IP + Hoplimit uint8 + TC uint8 + Flags uint16 +} + +func (e *IP6tnlEncap) Type() int { + return nl.LWTUNNEL_ENCAP_IP6 +} + +func (e *IP6tnlEncap) Decode(buf []byte) error { + attrs, err := nl.ParseRouteAttr(buf) + if err != nil { + return err + } + for _, attr := range attrs { + switch attr.Attr.Type { + case nl.LWTUNNEL_IP6_ID: + e.ID = uint64(native.Uint64(attr.Value[0:4])) + case nl.LWTUNNEL_IP6_DST: + e.Dst = net.IP(attr.Value[:]) + case nl.LWTUNNEL_IP6_SRC: + e.Src = net.IP(attr.Value[:]) + case nl.LWTUNNEL_IP6_HOPLIMIT: + e.Hoplimit = attr.Value[0] + case nl.LWTUNNEL_IP6_TC: + // e.TC = attr.Value[0] + err = fmt.Errorf("decoding TC in IP6tnlEncap is not supported") + case nl.LWTUNNEL_IP6_FLAGS: + // e.Flags = uint16(native.Uint16(attr.Value[0:2])) + err = fmt.Errorf("decoding FLAG in IP6tnlEncap is not supported") + case nl.LWTUNNEL_IP6_PAD: + err = fmt.Errorf("decoding PAD in IP6tnlEncap is not supported") + case nl.LWTUNNEL_IP6_OPTS: + err = fmt.Errorf("decoding OPTS in IP6tnlEncap is not supported") + } + } + return err +} + +func (e *IP6tnlEncap) Encode() ([]byte, error) { + + final := []byte{} + + resID := make([]byte, 12) + native.PutUint16(resID, 12) // 2+2+8 + native.PutUint16(resID[2:], nl.LWTUNNEL_IP6_ID) + native.PutUint64(resID[4:], 0) + final = append(final, resID...) + + resDst := make([]byte, 4) + native.PutUint16(resDst, 20) // 2+2+16 + native.PutUint16(resDst[2:], nl.LWTUNNEL_IP6_DST) + resDst = append(resDst, e.Dst...) + final = append(final, resDst...) + + resSrc := make([]byte, 4) + native.PutUint16(resSrc, 20) + native.PutUint16(resSrc[2:], nl.LWTUNNEL_IP6_SRC) + resSrc = append(resSrc, e.Src...) + final = append(final, resSrc...) + + // resTc := make([]byte, 5) + // native.PutUint16(resTc, 5) + // native.PutUint16(resTc[2:], nl.LWTUNNEL_IP6_TC) + // resTc[4] = e.TC + // final = append(final,resTc...) + + resHops := make([]byte, 5) + native.PutUint16(resHops, 5) + native.PutUint16(resHops[2:], nl.LWTUNNEL_IP6_HOPLIMIT) + resHops[4] = e.Hoplimit + final = append(final, resHops...) + + // resFlags := make([]byte, 6) + // native.PutUint16(resFlags, 6) + // native.PutUint16(resFlags[2:], nl.LWTUNNEL_IP6_FLAGS) + // native.PutUint16(resFlags[4:], e.Flags) + // final = append(final,resFlags...) + + return final, nil +} + +func (e *IP6tnlEncap) String() string { + return fmt.Sprintf("id %d src %s dst %s hoplimit %d tc %d flags 0x%.4x", e.ID, e.Src, e.Dst, e.Hoplimit, e.TC, e.Flags) +} + +func (e *IP6tnlEncap) Equal(x Encap) bool { + o, ok := x.(*IP6tnlEncap) + if !ok { + return false + } + + if e.ID != o.ID || e.Flags != o.Flags || e.Hoplimit != o.Hoplimit || e.Src.Equal(o.Src) || e.Dst.Equal(o.Dst) || e.TC != o.TC { return false } return true } +type Via struct { + AddrFamily int + Addr net.IP +} + +func (v *Via) Equal(x Destination) bool { + o, ok := x.(*Via) + if !ok { + return false + } + if v.AddrFamily == x.Family() && v.Addr.Equal(o.Addr) { + return true + } + return false +} + +func (v *Via) String() string { + return fmt.Sprintf("Family: %d, Address: %s", v.AddrFamily, v.Addr.String()) +} + +func (v *Via) Family() int { + return v.AddrFamily +} + +func (v *Via) Encode() ([]byte, error) { + buf := &bytes.Buffer{} + err := binary.Write(buf, native, uint16(v.AddrFamily)) + if err != nil { + return nil, err + } + err = binary.Write(buf, native, v.Addr) + if err != nil { + return nil, err + } + return buf.Bytes(), nil +} + +func (v *Via) Decode(b []byte) error { + if len(b) < 6 { + return fmt.Errorf("decoding failed: buffer too small (%d bytes)", len(b)) + } + v.AddrFamily = int(native.Uint16(b[0:2])) + if v.AddrFamily == nl.FAMILY_V4 { + v.Addr = net.IP(b[2:6]) + return nil + } else if v.AddrFamily == nl.FAMILY_V6 { + if len(b) < 18 { + return fmt.Errorf("decoding failed: buffer too small (%d bytes)", len(b)) + } + v.Addr = net.IP(b[2:]) + return nil + } + return fmt.Errorf("decoding failed: address family %d unknown", v.AddrFamily) +} + // RouteAdd will add a route to the system. // Equivalent to: `ip route add $route` func RouteAdd(route *Route) error { @@ -454,7 +797,51 @@ func RouteAdd(route *Route) error { func (h *Handle) RouteAdd(route *Route) error { flags := unix.NLM_F_CREATE | unix.NLM_F_EXCL | unix.NLM_F_ACK req := h.newNetlinkRequest(unix.RTM_NEWROUTE, flags) - return h.routeHandle(route, req, nl.NewRtMsg()) + _, err := h.routeHandle(route, req, nl.NewRtMsg()) + return err +} + +// RouteAppend will append a route to the system. +// Equivalent to: `ip route append $route` +func RouteAppend(route *Route) error { + return pkgHandle.RouteAppend(route) +} + +// RouteAppend will append a route to the system. +// Equivalent to: `ip route append $route` +func (h *Handle) RouteAppend(route *Route) error { + flags := unix.NLM_F_CREATE | unix.NLM_F_APPEND | unix.NLM_F_ACK + req := h.newNetlinkRequest(unix.RTM_NEWROUTE, flags) + _, err := h.routeHandle(route, req, nl.NewRtMsg()) + return err +} + +// RouteAddEcmp will add a route to the system. +func RouteAddEcmp(route *Route) error { + return pkgHandle.RouteAddEcmp(route) +} + +// RouteAddEcmp will add a route to the system. +func (h *Handle) RouteAddEcmp(route *Route) error { + flags := unix.NLM_F_CREATE | unix.NLM_F_ACK + req := h.newNetlinkRequest(unix.RTM_NEWROUTE, flags) + _, err := h.routeHandle(route, req, nl.NewRtMsg()) + return err +} + +// RouteChange will change an existing route in the system. +// Equivalent to: `ip route change $route` +func RouteChange(route *Route) error { + return pkgHandle.RouteChange(route) +} + +// RouteChange will change an existing route in the system. +// Equivalent to: `ip route change $route` +func (h *Handle) RouteChange(route *Route) error { + flags := unix.NLM_F_REPLACE | unix.NLM_F_ACK + req := h.newNetlinkRequest(unix.RTM_NEWROUTE, flags) + _, err := h.routeHandle(route, req, nl.NewRtMsg()) + return err } // RouteReplace will add a route to the system. @@ -468,7 +855,8 @@ func RouteReplace(route *Route) error { func (h *Handle) RouteReplace(route *Route) error { flags := unix.NLM_F_CREATE | unix.NLM_F_REPLACE | unix.NLM_F_ACK req := h.newNetlinkRequest(unix.RTM_NEWROUTE, flags) - return h.routeHandle(route, req, nl.NewRtMsg()) + _, err := h.routeHandle(route, req, nl.NewRtMsg()) + return err } // RouteDel will delete a route from the system. @@ -481,12 +869,27 @@ func RouteDel(route *Route) error { // Equivalent to: `ip route del $route` func (h *Handle) RouteDel(route *Route) error { req := h.newNetlinkRequest(unix.RTM_DELROUTE, unix.NLM_F_ACK) - return h.routeHandle(route, req, nl.NewRtDelMsg()) + _, err := h.routeHandle(route, req, nl.NewRtDelMsg()) + return err } -func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg) error { - if (route.Dst == nil || route.Dst.IP == nil) && route.Src == nil && route.Gw == nil && route.MPLSDst == nil { - return fmt.Errorf("one of Dst.IP, Src, or Gw must not be nil") +func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg) ([][]byte, error) { + if err := h.prepareRouteReq(route, req, msg); err != nil { + return nil, err + } + return req.Execute(unix.NETLINK_ROUTE, 0) +} + +func (h *Handle) routeHandleIter(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg, f func(msg []byte) bool) error { + if err := h.prepareRouteReq(route, req, msg); err != nil { + return err + } + return req.ExecuteIter(unix.NETLINK_ROUTE, 0, f) +} + +func (h *Handle) prepareRouteReq(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg) error { + if req.NlMsghdr.Type != unix.RTM_GETROUTE && (route.Dst == nil || route.Dst.IP == nil) && route.Src == nil && route.Gw == nil && route.MPLSDst == nil { + return fmt.Errorf("either Dst.IP, Src.IP or Gw must be set") } family := -1 @@ -530,7 +933,13 @@ func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg if err != nil { return err } - rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_ENCAP, buf)) + switch route.Encap.Type() { + case nl.LWTUNNEL_ENCAP_BPF: + rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_ENCAP|unix.NLA_F_NESTED, buf)) + default: + rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_ENCAP, buf)) + } + } if route.Src != nil { @@ -564,6 +973,14 @@ func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_GATEWAY, gwData)) } + if route.Via != nil { + buf, err := route.Via.Encode() + if err != nil { + return fmt.Errorf("failed to encode RTA_VIA: %v", err) + } + rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_VIA, buf)) + } + if len(route.MultiPath) > 0 { buf := []byte{} for _, nh := range route.MultiPath { @@ -606,6 +1023,13 @@ func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg } children = append(children, nl.NewRtAttr(unix.RTA_ENCAP, buf)) } + if nh.Via != nil { + buf, err := nh.Via.Encode() + if err != nil { + return err + } + children = append(children, nl.NewRtAttr(unix.RTA_VIA, buf)) + } rtnh.Children = children buf = append(buf, rtnh.Serialize()...) } @@ -628,6 +1052,11 @@ func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg native.PutUint32(b, uint32(route.Priority)) rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_PRIORITY, b)) } + if route.Realm > 0 { + b := make([]byte, 4) + native.PutUint32(b, uint32(route.Realm)) + rtAttrs = append(rtAttrs, nl.NewRtAttr(unix.RTA_FLOW, b)) + } if route.Tos > 0 { msg.Tos = uint8(route.Tos) } @@ -639,19 +1068,70 @@ func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg } var metrics []*nl.RtAttr - // TODO: support other rta_metric values if route.MTU > 0 { b := nl.Uint32Attr(uint32(route.MTU)) metrics = append(metrics, nl.NewRtAttr(unix.RTAX_MTU, b)) } + if route.Window > 0 { + b := nl.Uint32Attr(uint32(route.Window)) + metrics = append(metrics, nl.NewRtAttr(unix.RTAX_WINDOW, b)) + } + if route.Rtt > 0 { + b := nl.Uint32Attr(uint32(route.Rtt)) + metrics = append(metrics, nl.NewRtAttr(unix.RTAX_RTT, b)) + } + if route.RttVar > 0 { + b := nl.Uint32Attr(uint32(route.RttVar)) + metrics = append(metrics, nl.NewRtAttr(unix.RTAX_RTTVAR, b)) + } + if route.Ssthresh > 0 { + b := nl.Uint32Attr(uint32(route.Ssthresh)) + metrics = append(metrics, nl.NewRtAttr(unix.RTAX_SSTHRESH, b)) + } + if route.Cwnd > 0 { + b := nl.Uint32Attr(uint32(route.Cwnd)) + metrics = append(metrics, nl.NewRtAttr(unix.RTAX_CWND, b)) + } if route.AdvMSS > 0 { b := nl.Uint32Attr(uint32(route.AdvMSS)) metrics = append(metrics, nl.NewRtAttr(unix.RTAX_ADVMSS, b)) } + if route.Reordering > 0 { + b := nl.Uint32Attr(uint32(route.Reordering)) + metrics = append(metrics, nl.NewRtAttr(unix.RTAX_REORDERING, b)) + } if route.Hoplimit > 0 { b := nl.Uint32Attr(uint32(route.Hoplimit)) metrics = append(metrics, nl.NewRtAttr(unix.RTAX_HOPLIMIT, b)) } + if route.InitCwnd > 0 { + b := nl.Uint32Attr(uint32(route.InitCwnd)) + metrics = append(metrics, nl.NewRtAttr(unix.RTAX_INITCWND, b)) + } + if route.Features > 0 { + b := nl.Uint32Attr(uint32(route.Features)) + metrics = append(metrics, nl.NewRtAttr(unix.RTAX_FEATURES, b)) + } + if route.RtoMin > 0 { + b := nl.Uint32Attr(uint32(route.RtoMin)) + metrics = append(metrics, nl.NewRtAttr(unix.RTAX_RTO_MIN, b)) + } + if route.InitRwnd > 0 { + b := nl.Uint32Attr(uint32(route.InitRwnd)) + metrics = append(metrics, nl.NewRtAttr(unix.RTAX_INITRWND, b)) + } + if route.QuickACK > 0 { + b := nl.Uint32Attr(uint32(route.QuickACK)) + metrics = append(metrics, nl.NewRtAttr(unix.RTAX_QUICKACK, b)) + } + if route.Congctl != "" { + b := nl.ZeroTerminated(route.Congctl) + metrics = append(metrics, nl.NewRtAttr(unix.RTAX_CC_ALGO, b)) + } + if route.FastOpenNoCookie > 0 { + b := nl.Uint32Attr(uint32(route.FastOpenNoCookie)) + metrics = append(metrics, nl.NewRtAttr(unix.RTAX_FASTOPEN_NO_COOKIE, b)) + } if metrics != nil { attr := nl.NewRtAttr(unix.RTA_METRICS, nil) @@ -663,22 +1143,21 @@ func (h *Handle) routeHandle(route *Route, req *nl.NetlinkRequest, msg *nl.RtMsg msg.Flags = uint32(route.Flags) msg.Scope = uint8(route.Scope) - msg.Family = uint8(family) + // only overwrite family if it was not set in msg + if msg.Family == 0 { + msg.Family = uint8(family) + } req.AddData(msg) for _, attr := range rtAttrs { req.AddData(attr) } - var ( - b = make([]byte, 4) - native = nl.NativeEndian() - ) - native.PutUint32(b, uint32(route.LinkIndex)) - - req.AddData(nl.NewRtAttr(unix.RTA_OIF, b)) - - _, err := req.Execute(unix.NETLINK_ROUTE, 0) - return err + if (req.NlMsghdr.Type != unix.RTM_GETROUTE) || (req.NlMsghdr.Type == unix.RTM_GETROUTE && route.LinkIndex > 0) { + b := make([]byte, 4) + native.PutUint32(b, uint32(route.LinkIndex)) + req.AddData(nl.NewRtAttr(unix.RTA_OIF, b)) + } + return nil } // RouteList gets a list of routes in the system. @@ -692,13 +1171,13 @@ func RouteList(link Link, family int) ([]Route, error) { // Equivalent to: `ip route show`. // The list can be filtered by link and ip family. func (h *Handle) RouteList(link Link, family int) ([]Route, error) { - var routeFilter *Route + routeFilter := &Route{} if link != nil { - routeFilter = &Route{ - LinkIndex: link.Attrs().Index, - } + routeFilter.LinkIndex = link.Attrs().Index + + return h.RouteListFiltered(family, routeFilter, RT_FILTER_OIF) } - return h.RouteListFiltered(family, routeFilter, RT_FILTER_OIF) + return h.RouteListFiltered(family, routeFilter, 0) } // RouteListFiltered gets a list of routes in the system filtered with specified rules. @@ -710,65 +1189,94 @@ func RouteListFiltered(family int, filter *Route, filterMask uint64) ([]Route, e // RouteListFiltered gets a list of routes in the system filtered with specified rules. // All rules must be defined in RouteFilter struct func (h *Handle) RouteListFiltered(family int, filter *Route, filterMask uint64) ([]Route, error) { - req := h.newNetlinkRequest(unix.RTM_GETROUTE, unix.NLM_F_DUMP) - infmsg := nl.NewIfInfomsg(family) - req.AddData(infmsg) - - msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWROUTE) + var res []Route + err := h.RouteListFilteredIter(family, filter, filterMask, func(route Route) (cont bool) { + res = append(res, route) + return true + }) if err != nil { return nil, err } + return res, nil +} - var res []Route - for _, m := range msgs { +// RouteListFilteredIter passes each route that matches the filter to the given iterator func. Iteration continues +// until all routes are loaded or the func returns false. +func RouteListFilteredIter(family int, filter *Route, filterMask uint64, f func(Route) (cont bool)) error { + return pkgHandle.RouteListFilteredIter(family, filter, filterMask, f) +} + +func (h *Handle) RouteListFilteredIter(family int, filter *Route, filterMask uint64, f func(Route) (cont bool)) error { + req := h.newNetlinkRequest(unix.RTM_GETROUTE, unix.NLM_F_DUMP) + rtmsg := &nl.RtMsg{} + rtmsg.Family = uint8(family) + + var parseErr error + err := h.routeHandleIter(filter, req, rtmsg, func(m []byte) bool { msg := nl.DeserializeRtMsg(m) + if family != FAMILY_ALL && msg.Family != uint8(family) { + // Ignore routes not matching requested family + return true + } if msg.Flags&unix.RTM_F_CLONED != 0 { // Ignore cloned routes - continue + return true } if msg.Table != unix.RT_TABLE_MAIN { - if filter == nil || filter != nil && filterMask&RT_FILTER_TABLE == 0 { + if filter == nil || filterMask&RT_FILTER_TABLE == 0 { // Ignore non-main tables - continue + return true } } route, err := deserializeRoute(m) if err != nil { - return nil, err + parseErr = err + return false } if filter != nil { switch { case filterMask&RT_FILTER_TABLE != 0 && filter.Table != unix.RT_TABLE_UNSPEC && route.Table != filter.Table: - continue + return true case filterMask&RT_FILTER_PROTOCOL != 0 && route.Protocol != filter.Protocol: - continue + return true case filterMask&RT_FILTER_SCOPE != 0 && route.Scope != filter.Scope: - continue + return true case filterMask&RT_FILTER_TYPE != 0 && route.Type != filter.Type: - continue + return true case filterMask&RT_FILTER_TOS != 0 && route.Tos != filter.Tos: - continue + return true + case filterMask&RT_FILTER_REALM != 0 && route.Realm != filter.Realm: + return true case filterMask&RT_FILTER_OIF != 0 && route.LinkIndex != filter.LinkIndex: - continue + return true case filterMask&RT_FILTER_IIF != 0 && route.ILinkIndex != filter.ILinkIndex: - continue + return true case filterMask&RT_FILTER_GW != 0 && !route.Gw.Equal(filter.Gw): - continue + return true case filterMask&RT_FILTER_SRC != 0 && !route.Src.Equal(filter.Src): - continue + return true case filterMask&RT_FILTER_DST != 0: if filter.MPLSDst == nil || route.MPLSDst == nil || (*filter.MPLSDst) != (*route.MPLSDst) { + if filter.Dst == nil { + filter.Dst = genZeroIPNet(family) + } if !ipNetEqual(route.Dst, filter.Dst) { - continue + return true } } case filterMask&RT_FILTER_HOPLIMIT != 0 && route.Hoplimit != filter.Hoplimit: - continue + return true } } - res = append(res, route) + return f(route) + }) + if err != nil { + return err } - return res, nil + if parseErr != nil { + return parseErr + } + return nil } // deserializeRoute decodes a binary netlink message into a Route struct @@ -780,14 +1288,14 @@ func deserializeRoute(m []byte) (Route, error) { } route := Route{ Scope: Scope(msg.Scope), - Protocol: int(msg.Protocol), + Protocol: RouteProtocol(int(msg.Protocol)), Table: int(msg.Table), Type: int(msg.Type), Tos: int(msg.Tos), Flags: int(msg.Flags), + Family: int(msg.Family), } - native := nl.NativeEndian() var encap, encapType syscall.NetlinkRouteAttr for _, attr := range attrs { switch attr.Attr.Type { @@ -814,6 +1322,8 @@ func deserializeRoute(m []byte) (Route, error) { route.ILinkIndex = int(native.Uint32(attr.Value[0:4])) case unix.RTA_PRIORITY: route.Priority = int(native.Uint32(attr.Value[0:4])) + case unix.RTA_FLOW: + route.Realm = int(native.Uint32(attr.Value[0:4])) case unix.RTA_TABLE: route.Table = int(native.Uint32(attr.Value[0:4])) case unix.RTA_MULTIPATH: @@ -853,6 +1363,12 @@ func deserializeRoute(m []byte) (Route, error) { encapType = attr case unix.RTA_ENCAP: encap = attr + case unix.RTA_VIA: + d := &Via{} + if err := d.Decode(attr.Value); err != nil { + return nil, nil, err + } + info.Via = d } } @@ -890,6 +1406,12 @@ func deserializeRoute(m []byte) (Route, error) { return route, err } route.NewDst = d + case unix.RTA_VIA: + v := &Via{} + if err := v.Decode(attr.Value); err != nil { + return route, err + } + route.Via = v case unix.RTA_ENCAP_TYPE: encapType = attr case unix.RTA_ENCAP: @@ -903,15 +1425,62 @@ func deserializeRoute(m []byte) (Route, error) { switch metric.Attr.Type { case unix.RTAX_MTU: route.MTU = int(native.Uint32(metric.Value[0:4])) + case unix.RTAX_WINDOW: + route.Window = int(native.Uint32(metric.Value[0:4])) + case unix.RTAX_RTT: + route.Rtt = int(native.Uint32(metric.Value[0:4])) + case unix.RTAX_RTTVAR: + route.RttVar = int(native.Uint32(metric.Value[0:4])) + case unix.RTAX_SSTHRESH: + route.Ssthresh = int(native.Uint32(metric.Value[0:4])) + case unix.RTAX_CWND: + route.Cwnd = int(native.Uint32(metric.Value[0:4])) case unix.RTAX_ADVMSS: route.AdvMSS = int(native.Uint32(metric.Value[0:4])) + case unix.RTAX_REORDERING: + route.Reordering = int(native.Uint32(metric.Value[0:4])) case unix.RTAX_HOPLIMIT: route.Hoplimit = int(native.Uint32(metric.Value[0:4])) + case unix.RTAX_INITCWND: + route.InitCwnd = int(native.Uint32(metric.Value[0:4])) + case unix.RTAX_FEATURES: + route.Features = int(native.Uint32(metric.Value[0:4])) + case unix.RTAX_RTO_MIN: + route.RtoMin = int(native.Uint32(metric.Value[0:4])) + case unix.RTAX_INITRWND: + route.InitRwnd = int(native.Uint32(metric.Value[0:4])) + case unix.RTAX_QUICKACK: + route.QuickACK = int(native.Uint32(metric.Value[0:4])) + case unix.RTAX_CC_ALGO: + route.Congctl = nl.BytesToString(metric.Value) + case unix.RTAX_FASTOPEN_NO_COOKIE: + route.FastOpenNoCookie = int(native.Uint32(metric.Value[0:4])) } } } } + // Same logic to generate "default" dst with iproute2 implementation + if route.Dst == nil { + var addLen int + var ip net.IP + switch msg.Family { + case FAMILY_V4: + addLen = net.IPv4len + ip = net.IPv4zero + case FAMILY_V6: + addLen = net.IPv6len + ip = net.IPv6zero + } + + if addLen != 0 { + route.Dst = &net.IPNet{ + IP: ip, + Mask: net.CIDRMask(int(msg.Dst_len), 8*addLen), + } + } + } + if len(encap.Value) != 0 && len(encapType.Value) != 0 { typ := int(native.Uint16(encapType.Value[0:2])) var e Encap @@ -931,6 +1500,11 @@ func deserializeRoute(m []byte) (Route, error) { if err := e.Decode(encap.Value); err != nil { return route, err } + case nl.LWTUNNEL_ENCAP_BPF: + e = &BpfEncap{} + if err := e.Decode(encap.Value); err != nil { + return route, err + } } route.Encap = e } @@ -938,15 +1512,34 @@ func deserializeRoute(m []byte) (Route, error) { return route, nil } +// RouteGetOptions contains a set of options to use with +// RouteGetWithOptions +type RouteGetOptions struct { + Iif string + IifIndex int + Oif string + VrfName string + SrcAddr net.IP + UID *uint32 + Mark uint32 + FIBMatch bool +} + +// RouteGetWithOptions gets a route to a specific destination from the host system. +// Equivalent to: 'ip route get <> vrf '. +func RouteGetWithOptions(destination net.IP, options *RouteGetOptions) ([]Route, error) { + return pkgHandle.RouteGetWithOptions(destination, options) +} + // RouteGet gets a route to a specific destination from the host system. // Equivalent to: 'ip route get'. func RouteGet(destination net.IP) ([]Route, error) { return pkgHandle.RouteGet(destination) } -// RouteGet gets a route to a specific destination from the host system. -// Equivalent to: 'ip route get'. -func (h *Handle) RouteGet(destination net.IP) ([]Route, error) { +// RouteGetWithOptions gets a route to a specific destination from the host system. +// Equivalent to: 'ip route get <> vrf '. +func (h *Handle) RouteGetWithOptions(destination net.IP, options *RouteGetOptions) ([]Route, error) { req := h.newNetlinkRequest(unix.RTM_GETROUTE, unix.NLM_F_REQUEST) family := nl.GetIPFamily(destination) var destinationData []byte @@ -961,11 +1554,88 @@ func (h *Handle) RouteGet(destination net.IP) ([]Route, error) { msg := &nl.RtMsg{} msg.Family = uint8(family) msg.Dst_len = bitlen + if options != nil && options.SrcAddr != nil { + msg.Src_len = bitlen + } + msg.Flags = unix.RTM_F_LOOKUP_TABLE + if options != nil && options.FIBMatch { + msg.Flags |= unix.RTM_F_FIB_MATCH + } req.AddData(msg) rtaDst := nl.NewRtAttr(unix.RTA_DST, destinationData) req.AddData(rtaDst) + if options != nil { + if options.VrfName != "" { + link, err := h.LinkByName(options.VrfName) + if err != nil { + return nil, err + } + b := make([]byte, 4) + native.PutUint32(b, uint32(link.Attrs().Index)) + + req.AddData(nl.NewRtAttr(unix.RTA_OIF, b)) + } + + iifIndex := 0 + if len(options.Iif) > 0 { + link, err := h.LinkByName(options.Iif) + if err != nil { + return nil, err + } + + iifIndex = link.Attrs().Index + } else if options.IifIndex > 0 { + iifIndex = options.IifIndex + } + + if iifIndex > 0 { + b := make([]byte, 4) + native.PutUint32(b, uint32(iifIndex)) + + req.AddData(nl.NewRtAttr(unix.RTA_IIF, b)) + } + + if len(options.Oif) > 0 { + link, err := h.LinkByName(options.Oif) + if err != nil { + return nil, err + } + + b := make([]byte, 4) + native.PutUint32(b, uint32(link.Attrs().Index)) + + req.AddData(nl.NewRtAttr(unix.RTA_OIF, b)) + } + + if options.SrcAddr != nil { + var srcAddr []byte + if family == FAMILY_V4 { + srcAddr = options.SrcAddr.To4() + } else { + srcAddr = options.SrcAddr.To16() + } + + req.AddData(nl.NewRtAttr(unix.RTA_SRC, srcAddr)) + } + + if options.UID != nil { + uid := *options.UID + b := make([]byte, 4) + native.PutUint32(b, uid) + + req.AddData(nl.NewRtAttr(unix.RTA_UID, b)) + } + + if options.Mark > 0 { + b := make([]byte, 4) + native.PutUint32(b, options.Mark) + + req.AddData(nl.NewRtAttr(unix.RTA_MARK, b)) + } + } + msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWROUTE) if err != nil { return nil, err @@ -980,27 +1650,35 @@ func (h *Handle) RouteGet(destination net.IP) ([]Route, error) { res = append(res, route) } return res, nil +} +// RouteGet gets a route to a specific destination from the host system. +// Equivalent to: 'ip route get'. +func (h *Handle) RouteGet(destination net.IP) ([]Route, error) { + return h.RouteGetWithOptions(destination, nil) } // RouteSubscribe takes a chan down which notifications will be sent // when routes are added or deleted. Close the 'done' chan to stop subscription. func RouteSubscribe(ch chan<- RouteUpdate, done <-chan struct{}) error { - return routeSubscribeAt(netns.None(), netns.None(), ch, done, nil, false) + return routeSubscribeAt(netns.None(), netns.None(), ch, done, nil, false, 0, nil, false) } // RouteSubscribeAt works like RouteSubscribe plus it allows the caller // to choose the network namespace in which to subscribe (ns). func RouteSubscribeAt(ns netns.NsHandle, ch chan<- RouteUpdate, done <-chan struct{}) error { - return routeSubscribeAt(ns, netns.None(), ch, done, nil, false) + return routeSubscribeAt(ns, netns.None(), ch, done, nil, false, 0, nil, false) } // RouteSubscribeOptions contains a set of options to use with // RouteSubscribeWithOptions. type RouteSubscribeOptions struct { - Namespace *netns.NsHandle - ErrorCallback func(error) - ListExisting bool + Namespace *netns.NsHandle + ErrorCallback func(error) + ListExisting bool + ReceiveBufferSize int + ReceiveBufferForceSize bool + ReceiveTimeout *unix.Timeval } // RouteSubscribeWithOptions work like RouteSubscribe but enable to @@ -1011,14 +1689,27 @@ func RouteSubscribeWithOptions(ch chan<- RouteUpdate, done <-chan struct{}, opti none := netns.None() options.Namespace = &none } - return routeSubscribeAt(*options.Namespace, netns.None(), ch, done, options.ErrorCallback, options.ListExisting) + return routeSubscribeAt(*options.Namespace, netns.None(), ch, done, options.ErrorCallback, options.ListExisting, + options.ReceiveBufferSize, options.ReceiveTimeout, options.ReceiveBufferForceSize) } -func routeSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- RouteUpdate, done <-chan struct{}, cberr func(error), listExisting bool) error { +func routeSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- RouteUpdate, done <-chan struct{}, cberr func(error), listExisting bool, + rcvbuf int, rcvTimeout *unix.Timeval, rcvbufForce bool) error { s, err := nl.SubscribeAt(newNs, curNs, unix.NETLINK_ROUTE, unix.RTNLGRP_IPV4_ROUTE, unix.RTNLGRP_IPV6_ROUTE) if err != nil { return err } + if rcvTimeout != nil { + if err := s.SetReceiveTimeout(rcvTimeout); err != nil { + return err + } + } + if rcvbuf != 0 { + err = s.SetReceiveBufferSize(rcvbuf, rcvbufForce) + if err != nil { + return err + } + } if done != nil { go func() { <-done @@ -1040,7 +1731,8 @@ func routeSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- RouteUpdate, done < msgs, from, err := s.Receive() if err != nil { if cberr != nil { - cberr(err) + cberr(fmt.Errorf("Receive failed: %v", + err)) } return } @@ -1055,27 +1747,103 @@ func routeSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- RouteUpdate, done < continue } if m.Header.Type == unix.NLMSG_ERROR { - native := nl.NativeEndian() error := int32(native.Uint32(m.Data[0:4])) if error == 0 { continue } if cberr != nil { - cberr(syscall.Errno(-error)) + cberr(fmt.Errorf("error message: %v", + syscall.Errno(-error))) } - return + continue } route, err := deserializeRoute(m.Data) if err != nil { if cberr != nil { cberr(err) } - return + continue + } + ch <- RouteUpdate{ + Type: m.Header.Type, + NlFlags: m.Header.Flags & (unix.NLM_F_REPLACE | unix.NLM_F_EXCL | unix.NLM_F_CREATE | unix.NLM_F_APPEND), + Route: route, } - ch <- RouteUpdate{Type: m.Header.Type, Route: route} } } }() return nil } + +func (p RouteProtocol) String() string { + switch int(p) { + case unix.RTPROT_BABEL: + return "babel" + case unix.RTPROT_BGP: + return "bgp" + case unix.RTPROT_BIRD: + return "bird" + case unix.RTPROT_BOOT: + return "boot" + case unix.RTPROT_DHCP: + return "dhcp" + case unix.RTPROT_DNROUTED: + return "dnrouted" + case unix.RTPROT_EIGRP: + return "eigrp" + case unix.RTPROT_GATED: + return "gated" + case unix.RTPROT_ISIS: + return "isis" + // case unix.RTPROT_KEEPALIVED: + // return "keepalived" + case unix.RTPROT_KERNEL: + return "kernel" + case unix.RTPROT_MROUTED: + return "mrouted" + case unix.RTPROT_MRT: + return "mrt" + case unix.RTPROT_NTK: + return "ntk" + case unix.RTPROT_OSPF: + return "ospf" + case unix.RTPROT_RA: + return "ra" + case unix.RTPROT_REDIRECT: + return "redirect" + case unix.RTPROT_RIP: + return "rip" + case unix.RTPROT_STATIC: + return "static" + case unix.RTPROT_UNSPEC: + return "unspec" + case unix.RTPROT_XORP: + return "xorp" + case unix.RTPROT_ZEBRA: + return "zebra" + default: + return strconv.Itoa(int(p)) + } +} + +// genZeroIPNet returns 0.0.0.0/0 or ::/0 for IPv4 or IPv6, otherwise nil +func genZeroIPNet(family int) *net.IPNet { + var addLen int + var ip net.IP + switch family { + case FAMILY_V4: + addLen = net.IPv4len + ip = net.IPv4zero + case FAMILY_V6: + addLen = net.IPv6len + ip = net.IPv6zero + } + if addLen != 0 { + return &net.IPNet{ + IP: ip, + Mask: net.CIDRMask(0, 8*addLen), + } + } + return nil +} diff --git a/vendor/github.com/vishvananda/netlink/route_unspecified.go b/vendor/github.com/vishvananda/netlink/route_unspecified.go index 2701862b4..db7372689 100644 --- a/vendor/github.com/vishvananda/netlink/route_unspecified.go +++ b/vendor/github.com/vishvananda/netlink/route_unspecified.go @@ -2,6 +2,8 @@ package netlink +import "strconv" + func (r *Route) ListFlags() []string { return []string{} } @@ -9,3 +11,11 @@ func (r *Route) ListFlags() []string { func (n *NexthopInfo) ListFlags() []string { return []string{} } + +func (s Scope) String() string { + return "unknown" +} + +func (p RouteProtocol) String() string { + return strconv.Itoa(int(p)) +} diff --git a/vendor/github.com/vishvananda/netlink/rule.go b/vendor/github.com/vishvananda/netlink/rule.go index 7fc8ae5df..9d74c7cd8 100644 --- a/vendor/github.com/vishvananda/netlink/rule.go +++ b/vendor/github.com/vishvananda/netlink/rule.go @@ -10,8 +10,9 @@ type Rule struct { Priority int Family int Table int - Mark int - Mask int + Mark uint32 + Mask *uint32 + Tos uint TunID uint Goto int Src *net.IPNet @@ -22,10 +23,27 @@ type Rule struct { SuppressIfgroup int SuppressPrefixlen int Invert bool + Dport *RulePortRange + Sport *RulePortRange + IPProto int + UIDRange *RuleUIDRange + Protocol uint8 + Type uint8 } func (r Rule) String() string { - return fmt.Sprintf("ip rule %d: from %s table %d", r.Priority, r.Src, r.Table) + from := "all" + if r.Src != nil && r.Src.String() != "" { + from = r.Src.String() + } + + to := "all" + if r.Dst != nil && r.Dst.String() != "" { + to = r.Dst.String() + } + + return fmt.Sprintf("ip rule %d: from %s to %s table %d %s", + r.Priority, from, to, r.Table, r.typeString()) } // NewRule return empty rules. @@ -34,9 +52,31 @@ func NewRule() *Rule { SuppressIfgroup: -1, SuppressPrefixlen: -1, Priority: -1, - Mark: -1, - Mask: -1, + Mark: 0, + Mask: nil, Goto: -1, Flow: -1, } } + +// NewRulePortRange creates rule sport/dport range. +func NewRulePortRange(start, end uint16) *RulePortRange { + return &RulePortRange{Start: start, End: end} +} + +// RulePortRange represents rule sport/dport range. +type RulePortRange struct { + Start uint16 + End uint16 +} + +// NewRuleUIDRange creates rule uid range. +func NewRuleUIDRange(start, end uint32) *RuleUIDRange { + return &RuleUIDRange{Start: start, End: end} +} + +// RuleUIDRange represents rule uid range. +type RuleUIDRange struct { + Start uint32 + End uint32 +} diff --git a/vendor/github.com/vishvananda/netlink/rule_linux.go b/vendor/github.com/vishvananda/netlink/rule_linux.go index e12569fe4..ddff99cfa 100644 --- a/vendor/github.com/vishvananda/netlink/rule_linux.go +++ b/vendor/github.com/vishvananda/netlink/rule_linux.go @@ -1,6 +1,7 @@ package netlink import ( + "bytes" "fmt" "net" @@ -42,8 +43,8 @@ func ruleHandle(rule *Rule, req *nl.NetlinkRequest) error { msg.Protocol = unix.RTPROT_BOOT msg.Scope = unix.RT_SCOPE_UNIVERSE msg.Table = unix.RT_TABLE_UNSPEC - msg.Type = unix.RTN_UNSPEC - if req.NlMsghdr.Flags&unix.NLM_F_CREATE > 0 { + msg.Type = rule.Type // usually 0, same as unix.RTN_UNSPEC + if msg.Type == 0 && req.NlMsghdr.Flags&unix.NLM_F_CREATE > 0 { msg.Type = unix.RTN_UNICAST } if rule.Invert { @@ -55,6 +56,9 @@ func ruleHandle(rule *Rule, req *nl.NetlinkRequest) error { if rule.Table >= 0 && rule.Table < 256 { msg.Table = uint8(rule.Table) } + if rule.Tos != 0 { + msg.Tos = uint8(rule.Tos) + } var dstFamily uint8 var rtAttrs []*nl.RtAttr @@ -93,21 +97,19 @@ func ruleHandle(rule *Rule, req *nl.NetlinkRequest) error { req.AddData(rtAttrs[i]) } - native := nl.NativeEndian() - if rule.Priority >= 0 { b := make([]byte, 4) native.PutUint32(b, uint32(rule.Priority)) req.AddData(nl.NewRtAttr(nl.FRA_PRIORITY, b)) } - if rule.Mark >= 0 { + if rule.Mark != 0 || rule.Mask != nil { b := make([]byte, 4) - native.PutUint32(b, uint32(rule.Mark)) + native.PutUint32(b, rule.Mark) req.AddData(nl.NewRtAttr(nl.FRA_FWMARK, b)) } - if rule.Mask >= 0 { + if rule.Mask != nil { b := make([]byte, 4) - native.PutUint32(b, uint32(rule.Mask)) + native.PutUint32(b, *rule.Mask) req.AddData(nl.NewRtAttr(nl.FRA_FWMASK, b)) } if rule.Flow >= 0 { @@ -138,10 +140,10 @@ func ruleHandle(rule *Rule, req *nl.NetlinkRequest) error { } } if rule.IifName != "" { - req.AddData(nl.NewRtAttr(nl.FRA_IIFNAME, []byte(rule.IifName))) + req.AddData(nl.NewRtAttr(nl.FRA_IIFNAME, []byte(rule.IifName+"\x00"))) } if rule.OifName != "" { - req.AddData(nl.NewRtAttr(nl.FRA_OIFNAME, []byte(rule.OifName))) + req.AddData(nl.NewRtAttr(nl.FRA_OIFNAME, []byte(rule.OifName+"\x00"))) } if rule.Goto >= 0 { msg.Type = nl.FR_ACT_GOTO @@ -150,6 +152,31 @@ func ruleHandle(rule *Rule, req *nl.NetlinkRequest) error { req.AddData(nl.NewRtAttr(nl.FRA_GOTO, b)) } + if rule.IPProto > 0 { + b := make([]byte, 4) + native.PutUint32(b, uint32(rule.IPProto)) + req.AddData(nl.NewRtAttr(nl.FRA_IP_PROTO, b)) + } + + if rule.Dport != nil { + b := rule.Dport.toRtAttrData() + req.AddData(nl.NewRtAttr(nl.FRA_DPORT_RANGE, b)) + } + + if rule.Sport != nil { + b := rule.Sport.toRtAttrData() + req.AddData(nl.NewRtAttr(nl.FRA_SPORT_RANGE, b)) + } + + if rule.UIDRange != nil { + b := rule.UIDRange.toRtAttrData() + req.AddData(nl.NewRtAttr(nl.FRA_UID_RANGE, b)) + } + + if rule.Protocol > 0 { + req.AddData(nl.NewRtAttr(nl.FRA_PROTOCOL, nl.Uint8Attr(rule.Protocol))) + } + _, err := req.Execute(unix.NETLINK_ROUTE, 0) return err } @@ -163,6 +190,19 @@ func RuleList(family int) ([]Rule, error) { // RuleList lists rules in the system. // Equivalent to: ip rule list func (h *Handle) RuleList(family int) ([]Rule, error) { + return h.RuleListFiltered(family, nil, 0) +} + +// RuleListFiltered gets a list of rules in the system filtered by the +// specified rule template `filter`. +// Equivalent to: ip rule list +func RuleListFiltered(family int, filter *Rule, filterMask uint64) ([]Rule, error) { + return pkgHandle.RuleListFiltered(family, filter, filterMask) +} + +// RuleListFiltered lists rules in the system. +// Equivalent to: ip rule list +func (h *Handle) RuleListFiltered(family int, filter *Rule, filterMask uint64) ([]Rule, error) { req := h.newNetlinkRequest(unix.RTM_GETRULE, unix.NLM_F_DUMP|unix.NLM_F_REQUEST) msg := nl.NewIfInfomsg(family) req.AddData(msg) @@ -172,7 +212,6 @@ func (h *Handle) RuleList(family int) ([]Rule, error) { return nil, err } - native := nl.NativeEndian() var res = make([]Rule, 0) for i := range msgs { msg := nl.DeserializeRtMsg(msgs[i]) @@ -182,8 +221,11 @@ func (h *Handle) RuleList(family int) ([]Rule, error) { } rule := NewRule() + rule.Priority = 0 // The default priority from kernel rule.Invert = msg.Flags&FibRuleInvert > 0 + rule.Family = int(msg.Family) + rule.Tos = uint(msg.Tos) for j := range attrs { switch attrs[j].Attr.Type { @@ -200,11 +242,12 @@ func (h *Handle) RuleList(family int) ([]Rule, error) { Mask: net.CIDRMask(int(msg.Dst_len), 8*len(attrs[j].Value)), } case nl.FRA_FWMARK: - rule.Mark = int(native.Uint32(attrs[j].Value[0:4])) + rule.Mark = native.Uint32(attrs[j].Value[0:4]) case nl.FRA_FWMASK: - rule.Mask = int(native.Uint32(attrs[j].Value[0:4])) + mask := native.Uint32(attrs[j].Value[0:4]) + rule.Mask = &mask case nl.FRA_TUN_ID: - rule.TunID = uint(native.Uint64(attrs[j].Value[0:4])) + rule.TunID = uint(native.Uint64(attrs[j].Value[0:8])) case nl.FRA_IIFNAME: rule.IifName = string(attrs[j].Value[:len(attrs[j].Value)-1]) case nl.FRA_OIFNAME: @@ -225,10 +268,98 @@ func (h *Handle) RuleList(family int) ([]Rule, error) { rule.Goto = int(native.Uint32(attrs[j].Value[0:4])) case nl.FRA_PRIORITY: rule.Priority = int(native.Uint32(attrs[j].Value[0:4])) + case nl.FRA_IP_PROTO: + rule.IPProto = int(native.Uint32(attrs[j].Value[0:4])) + case nl.FRA_DPORT_RANGE: + rule.Dport = NewRulePortRange(native.Uint16(attrs[j].Value[0:2]), native.Uint16(attrs[j].Value[2:4])) + case nl.FRA_SPORT_RANGE: + rule.Sport = NewRulePortRange(native.Uint16(attrs[j].Value[0:2]), native.Uint16(attrs[j].Value[2:4])) + case nl.FRA_UID_RANGE: + rule.UIDRange = NewRuleUIDRange(native.Uint32(attrs[j].Value[0:4]), native.Uint32(attrs[j].Value[4:8])) + case nl.FRA_PROTOCOL: + rule.Protocol = uint8(attrs[j].Value[0]) + } + } + + if filter != nil { + switch { + case filterMask&RT_FILTER_SRC != 0 && + (rule.Src == nil || rule.Src.String() != filter.Src.String()): + continue + case filterMask&RT_FILTER_DST != 0 && + (rule.Dst == nil || rule.Dst.String() != filter.Dst.String()): + continue + case filterMask&RT_FILTER_TABLE != 0 && + filter.Table != unix.RT_TABLE_UNSPEC && rule.Table != filter.Table: + continue + case filterMask&RT_FILTER_TOS != 0 && rule.Tos != filter.Tos: + continue + case filterMask&RT_FILTER_PRIORITY != 0 && rule.Priority != filter.Priority: + continue + case filterMask&RT_FILTER_MARK != 0 && rule.Mark != filter.Mark: + continue + case filterMask&RT_FILTER_MASK != 0 && !ptrEqual(rule.Mask, filter.Mask): + continue } } + res = append(res, *rule) } return res, nil } + +func (pr *RulePortRange) toRtAttrData() []byte { + b := [][]byte{make([]byte, 2), make([]byte, 2)} + native.PutUint16(b[0], pr.Start) + native.PutUint16(b[1], pr.End) + return bytes.Join(b, []byte{}) +} + +func (pr *RuleUIDRange) toRtAttrData() []byte { + b := [][]byte{make([]byte, 4), make([]byte, 4)} + native.PutUint32(b[0], pr.Start) + native.PutUint32(b[1], pr.End) + return bytes.Join(b, []byte{}) +} + +func ptrEqual(a, b *uint32) bool { + if a == b { + return true + } + if (a == nil) || (b == nil) { + return false + } + return *a == *b +} + +func (r Rule) typeString() string { + switch r.Type { + case unix.RTN_UNSPEC: // zero + return "" + case unix.RTN_UNICAST: + return "" + case unix.RTN_LOCAL: + return "local" + case unix.RTN_BROADCAST: + return "broadcast" + case unix.RTN_ANYCAST: + return "anycast" + case unix.RTN_MULTICAST: + return "multicast" + case unix.RTN_BLACKHOLE: + return "blackhole" + case unix.RTN_UNREACHABLE: + return "unreachable" + case unix.RTN_PROHIBIT: + return "prohibit" + case unix.RTN_THROW: + return "throw" + case unix.RTN_NAT: + return "nat" + case unix.RTN_XRESOLVE: + return "xresolve" + default: + return fmt.Sprintf("type(0x%x)", r.Type) + } +} diff --git a/vendor/github.com/vishvananda/netlink/rule_nonlinux.go b/vendor/github.com/vishvananda/netlink/rule_nonlinux.go new file mode 100644 index 000000000..2b19aa64c --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/rule_nonlinux.go @@ -0,0 +1,8 @@ +//go:build !linux +// +build !linux + +package netlink + +func (r Rule) typeString() string { + return "" +} diff --git a/vendor/github.com/vishvananda/netlink/socket.go b/vendor/github.com/vishvananda/netlink/socket.go index 41aa72624..e65efb130 100644 --- a/vendor/github.com/vishvananda/netlink/socket.go +++ b/vendor/github.com/vishvananda/netlink/socket.go @@ -25,3 +25,80 @@ type Socket struct { UID uint32 INode uint32 } + +// UnixSocket represents a netlink unix socket. +type UnixSocket struct { + Type uint8 + Family uint8 + State uint8 + pad uint8 + INode uint32 + Cookie [2]uint32 +} + +// XDPSocket represents an XDP socket (and the common diagnosis part in +// particular). Please note that in contrast to [UnixSocket] the XDPSocket type +// does not feature “State” information. +type XDPSocket struct { + // xdp_diag_msg + // https://elixir.bootlin.com/linux/v6.2/source/include/uapi/linux/xdp_diag.h#L21 + Family uint8 + Type uint8 + pad uint16 + Ino uint32 + Cookie [2]uint32 +} + +type XDPInfo struct { + // XDP_DIAG_INFO/xdp_diag_info + // https://elixir.bootlin.com/linux/v6.2/source/include/uapi/linux/xdp_diag.h#L51 + Ifindex uint32 + QueueID uint32 + + // XDP_DIAG_UID + UID uint32 + + // XDP_RX_RING + // https://elixir.bootlin.com/linux/v6.2/source/include/uapi/linux/xdp_diag.h#L56 + RxRingEntries uint32 + TxRingEntries uint32 + UmemFillRingEntries uint32 + UmemCompletionRingEntries uint32 + + // XDR_DIAG_UMEM + Umem *XDPDiagUmem + + // XDR_DIAG_STATS + Stats *XDPDiagStats +} + +const ( + XDP_DU_F_ZEROCOPY = 1 << iota +) + +// XDPDiagUmem describes the umem attached to an XDP socket. +// +// https://elixir.bootlin.com/linux/v6.2/source/include/uapi/linux/xdp_diag.h#L62 +type XDPDiagUmem struct { + Size uint64 + ID uint32 + NumPages uint32 + ChunkSize uint32 + Headroom uint32 + Ifindex uint32 + QueueID uint32 + Flags uint32 + Refs uint32 +} + +// XDPDiagStats contains ring statistics for an XDP socket. +// +// https://elixir.bootlin.com/linux/v6.2/source/include/uapi/linux/xdp_diag.h#L74 +type XDPDiagStats struct { + RxDropped uint64 + RxInvalid uint64 + RxFull uint64 + FillRingEmpty uint64 + TxInvalid uint64 + TxRingEmpty uint64 +} diff --git a/vendor/github.com/vishvananda/netlink/socket_linux.go b/vendor/github.com/vishvananda/netlink/socket_linux.go index c4d89c17e..4eb4aeafb 100644 --- a/vendor/github.com/vishvananda/netlink/socket_linux.go +++ b/vendor/github.com/vishvananda/netlink/socket_linux.go @@ -4,15 +4,18 @@ import ( "errors" "fmt" "net" + "syscall" "github.com/vishvananda/netlink/nl" "golang.org/x/sys/unix" ) const ( - sizeofSocketID = 0x30 - sizeofSocketRequest = sizeofSocketID + 0x8 - sizeofSocket = sizeofSocketID + 0x18 + sizeofSocketID = 0x30 + sizeofSocketRequest = sizeofSocketID + 0x8 + sizeofSocket = sizeofSocketID + 0x18 + sizeofUnixSocketRequest = 0x18 // 24 byte + sizeofUnixSocket = 0x10 // 16 byte ) type socketRequest struct { @@ -49,10 +52,13 @@ func (r *socketRequest) Serialize() []byte { native.PutUint32(b.Next(4), r.States) networkOrder.PutUint16(b.Next(2), r.ID.SourcePort) networkOrder.PutUint16(b.Next(2), r.ID.DestinationPort) - copy(b.Next(4), r.ID.Source.To4()) - b.Next(12) - copy(b.Next(4), r.ID.Destination.To4()) - b.Next(12) + if r.Family == unix.AF_INET6 { + copy(b.Next(16), r.ID.Source) + copy(b.Next(16), r.ID.Destination) + } else { + copy(b.Next(16), r.ID.Source.To4()) + copy(b.Next(16), r.ID.Destination.To4()) + } native.PutUint32(b.Next(4), r.ID.Interface) native.PutUint32(b.Next(4), r.ID.Cookie[0]) native.PutUint32(b.Next(4), r.ID.Cookie[1]) @@ -61,6 +67,32 @@ func (r *socketRequest) Serialize() []byte { func (r *socketRequest) Len() int { return sizeofSocketRequest } +// According to linux/include/uapi/linux/unix_diag.h +type unixSocketRequest struct { + Family uint8 + Protocol uint8 + pad uint16 + States uint32 + INode uint32 + Show uint32 + Cookie [2]uint32 +} + +func (r *unixSocketRequest) Serialize() []byte { + b := writeBuffer{Bytes: make([]byte, sizeofUnixSocketRequest)} + b.Write(r.Family) + b.Write(r.Protocol) + native.PutUint16(b.Next(2), r.pad) + native.PutUint32(b.Next(4), r.States) + native.PutUint32(b.Next(4), r.INode) + native.PutUint32(b.Next(4), r.Show) + native.PutUint32(b.Next(4), r.Cookie[0]) + native.PutUint32(b.Next(4), r.Cookie[1]) + return b.Bytes +} + +func (r *unixSocketRequest) Len() int { return sizeofUnixSocketRequest } + type readBuffer struct { Bytes []byte pos int @@ -89,10 +121,15 @@ func (s *Socket) deserialize(b []byte) error { s.Retrans = rb.Read() s.ID.SourcePort = networkOrder.Uint16(rb.Next(2)) s.ID.DestinationPort = networkOrder.Uint16(rb.Next(2)) - s.ID.Source = net.IPv4(rb.Read(), rb.Read(), rb.Read(), rb.Read()) - rb.Next(12) - s.ID.Destination = net.IPv4(rb.Read(), rb.Read(), rb.Read(), rb.Read()) - rb.Next(12) + if s.Family == unix.AF_INET6 { + s.ID.Source = net.IP(rb.Next(16)) + s.ID.Destination = net.IP(rb.Next(16)) + } else { + s.ID.Source = net.IPv4(rb.Read(), rb.Read(), rb.Read(), rb.Read()) + rb.Next(12) + s.ID.Destination = net.IPv4(rb.Read(), rb.Read(), rb.Read(), rb.Read()) + rb.Next(12) + } s.ID.Interface = native.Uint32(rb.Next(4)) s.ID.Cookie[0] = native.Uint32(rb.Next(4)) s.ID.Cookie[1] = native.Uint32(rb.Next(4)) @@ -104,31 +141,126 @@ func (s *Socket) deserialize(b []byte) error { return nil } +func (u *UnixSocket) deserialize(b []byte) error { + if len(b) < sizeofUnixSocket { + return fmt.Errorf("unix diag data short read (%d); want %d", len(b), sizeofUnixSocket) + } + rb := readBuffer{Bytes: b} + u.Type = rb.Read() + u.Family = rb.Read() + u.State = rb.Read() + u.pad = rb.Read() + u.INode = native.Uint32(rb.Next(4)) + u.Cookie[0] = native.Uint32(rb.Next(4)) + u.Cookie[1] = native.Uint32(rb.Next(4)) + return nil +} + +// SocketGet returns the Socket identified by its local and remote addresses. +func (h *Handle) SocketGet(local, remote net.Addr) (*Socket, error) { + var protocol uint8 + var localIP, remoteIP net.IP + var localPort, remotePort uint16 + switch l := local.(type) { + case *net.TCPAddr: + r, ok := remote.(*net.TCPAddr) + if !ok { + return nil, ErrNotImplemented + } + localIP = l.IP + localPort = uint16(l.Port) + remoteIP = r.IP + remotePort = uint16(r.Port) + protocol = unix.IPPROTO_TCP + case *net.UDPAddr: + r, ok := remote.(*net.UDPAddr) + if !ok { + return nil, ErrNotImplemented + } + localIP = l.IP + localPort = uint16(l.Port) + remoteIP = r.IP + remotePort = uint16(r.Port) + protocol = unix.IPPROTO_UDP + default: + return nil, ErrNotImplemented + } + + var family uint8 + if localIP.To4() != nil && remoteIP.To4() != nil { + family = unix.AF_INET + } + + if family == 0 && localIP.To16() != nil && remoteIP.To16() != nil { + family = unix.AF_INET6 + } + + if family == 0 { + return nil, ErrNotImplemented + } + + req := h.newNetlinkRequest(nl.SOCK_DIAG_BY_FAMILY, unix.NLM_F_DUMP) + req.AddData(&socketRequest{ + Family: family, + Protocol: protocol, + States: 0xffffffff, + ID: SocketID{ + SourcePort: localPort, + DestinationPort: remotePort, + Source: localIP, + Destination: remoteIP, + Cookie: [2]uint32{nl.TCPDIAG_NOCOOKIE, nl.TCPDIAG_NOCOOKIE}, + }, + }) + + msgs, err := req.Execute(unix.NETLINK_INET_DIAG, nl.SOCK_DIAG_BY_FAMILY) + if err != nil { + return nil, err + } + if len(msgs) == 0 { + return nil, errors.New("no message nor error from netlink") + } + if len(msgs) > 2 { + return nil, fmt.Errorf("multiple (%d) matching sockets", len(msgs)) + } + + sock := &Socket{} + if err := sock.deserialize(msgs[0]); err != nil { + return nil, err + } + return sock, nil +} + // SocketGet returns the Socket identified by its local and remote addresses. func SocketGet(local, remote net.Addr) (*Socket, error) { + return pkgHandle.SocketGet(local, remote) +} + +// SocketDestroy kills the Socket identified by its local and remote addresses. +func (h *Handle) SocketDestroy(local, remote net.Addr) error { localTCP, ok := local.(*net.TCPAddr) if !ok { - return nil, ErrNotImplemented + return ErrNotImplemented } remoteTCP, ok := remote.(*net.TCPAddr) if !ok { - return nil, ErrNotImplemented + return ErrNotImplemented } localIP := localTCP.IP.To4() if localIP == nil { - return nil, ErrNotImplemented + return ErrNotImplemented } remoteIP := remoteTCP.IP.To4() if remoteIP == nil { - return nil, ErrNotImplemented + return ErrNotImplemented } s, err := nl.Subscribe(unix.NETLINK_INET_DIAG) if err != nil { - return nil, err + return err } defer s.Close() - req := nl.NewNetlinkRequest(nl.SOCK_DIAG_BY_FAMILY, 0) + req := h.newNetlinkRequest(nl.SOCK_DESTROY, unix.NLM_F_ACK) req.AddData(&socketRequest{ Family: unix.AF_INET, Protocol: unix.IPPROTO_TCP, @@ -140,23 +272,319 @@ func SocketGet(local, remote net.Addr) (*Socket, error) { Cookie: [2]uint32{nl.TCPDIAG_NOCOOKIE, nl.TCPDIAG_NOCOOKIE}, }, }) - s.Send(req) - msgs, from, err := s.Receive() + + _, err = req.Execute(unix.NETLINK_INET_DIAG, 0) + return err +} + +// SocketDestroy kills the Socket identified by its local and remote addresses. +func SocketDestroy(local, remote net.Addr) error { + return pkgHandle.SocketDestroy(local, remote) +} + +// SocketDiagTCPInfo requests INET_DIAG_INFO for TCP protocol for specified family type and return with extension TCP info. +func (h *Handle) SocketDiagTCPInfo(family uint8) ([]*InetDiagTCPInfoResp, error) { + // Construct the request + req := h.newNetlinkRequest(nl.SOCK_DIAG_BY_FAMILY, unix.NLM_F_DUMP) + req.AddData(&socketRequest{ + Family: family, + Protocol: unix.IPPROTO_TCP, + Ext: (1 << (INET_DIAG_VEGASINFO - 1)) | (1 << (INET_DIAG_INFO - 1)), + States: uint32(0xfff), // all states + }) + + // Do the query and parse the result + var result []*InetDiagTCPInfoResp + var err error + err = req.ExecuteIter(unix.NETLINK_INET_DIAG, nl.SOCK_DIAG_BY_FAMILY, func(msg []byte) bool { + sockInfo := &Socket{} + if err = sockInfo.deserialize(msg); err != nil { + return false + } + var attrs []syscall.NetlinkRouteAttr + if attrs, err = nl.ParseRouteAttr(msg[sizeofSocket:]); err != nil { + return false + } + + var res *InetDiagTCPInfoResp + if res, err = attrsToInetDiagTCPInfoResp(attrs, sockInfo); err != nil { + return false + } + + result = append(result, res) + return true + }) + + if err != nil { + return nil, err + } + return result, nil +} + +// SocketDiagTCPInfo requests INET_DIAG_INFO for TCP protocol for specified family type and return with extension TCP info. +func SocketDiagTCPInfo(family uint8) ([]*InetDiagTCPInfoResp, error) { + return pkgHandle.SocketDiagTCPInfo(family) +} + +// SocketDiagTCP requests INET_DIAG_INFO for TCP protocol for specified family type and return related socket. +func (h *Handle) SocketDiagTCP(family uint8) ([]*Socket, error) { + // Construct the request + req := h.newNetlinkRequest(nl.SOCK_DIAG_BY_FAMILY, unix.NLM_F_DUMP) + req.AddData(&socketRequest{ + Family: family, + Protocol: unix.IPPROTO_TCP, + Ext: (1 << (INET_DIAG_VEGASINFO - 1)) | (1 << (INET_DIAG_INFO - 1)), + States: uint32(0xfff), // all states + }) + + // Do the query and parse the result + var result []*Socket + var err error + err = req.ExecuteIter(unix.NETLINK_INET_DIAG, nl.SOCK_DIAG_BY_FAMILY, func(msg []byte) bool { + sockInfo := &Socket{} + if err = sockInfo.deserialize(msg); err != nil { + return false + } + result = append(result, sockInfo) + return true + }) if err != nil { return nil, err } - if from.Pid != nl.PidKernel { - return nil, fmt.Errorf("Wrong sender portid %d, expected %d", from.Pid, nl.PidKernel) + return result, nil +} + +// SocketDiagTCP requests INET_DIAG_INFO for TCP protocol for specified family type and return related socket. +func SocketDiagTCP(family uint8) ([]*Socket, error) { + return pkgHandle.SocketDiagTCP(family) +} + +// SocketDiagUDPInfo requests INET_DIAG_INFO for UDP protocol for specified family type and return with extension info. +func (h *Handle) SocketDiagUDPInfo(family uint8) ([]*InetDiagUDPInfoResp, error) { + // Construct the request + var extensions uint8 + extensions = 1 << (INET_DIAG_VEGASINFO - 1) + extensions |= 1 << (INET_DIAG_INFO - 1) + extensions |= 1 << (INET_DIAG_MEMINFO - 1) + + req := h.newNetlinkRequest(nl.SOCK_DIAG_BY_FAMILY, unix.NLM_F_DUMP) + req.AddData(&socketRequest{ + Family: family, + Protocol: unix.IPPROTO_UDP, + Ext: extensions, + States: uint32(0xfff), // all states + }) + + // Do the query and parse the result + var result []*InetDiagUDPInfoResp + var err error + err = req.ExecuteIter(unix.NETLINK_INET_DIAG, nl.SOCK_DIAG_BY_FAMILY, func(msg []byte) bool { + sockInfo := &Socket{} + if err = sockInfo.deserialize(msg); err != nil { + return false + } + + var attrs []syscall.NetlinkRouteAttr + if attrs, err = nl.ParseRouteAttr(msg[sizeofSocket:]); err != nil { + return false + } + + var res *InetDiagUDPInfoResp + if res, err = attrsToInetDiagUDPInfoResp(attrs, sockInfo); err != nil { + return false + } + + result = append(result, res) + return true + }) + if err != nil { + return nil, err } - if len(msgs) == 0 { - return nil, errors.New("no message nor error from netlink") + return result, nil +} + +// SocketDiagUDPInfo requests INET_DIAG_INFO for UDP protocol for specified family type and return with extension info. +func SocketDiagUDPInfo(family uint8) ([]*InetDiagUDPInfoResp, error) { + return pkgHandle.SocketDiagUDPInfo(family) +} + +// SocketDiagUDP requests INET_DIAG_INFO for UDP protocol for specified family type and return related socket. +func (h *Handle) SocketDiagUDP(family uint8) ([]*Socket, error) { + // Construct the request + req := h.newNetlinkRequest(nl.SOCK_DIAG_BY_FAMILY, unix.NLM_F_DUMP) + req.AddData(&socketRequest{ + Family: family, + Protocol: unix.IPPROTO_UDP, + Ext: (1 << (INET_DIAG_VEGASINFO - 1)) | (1 << (INET_DIAG_INFO - 1)), + States: uint32(0xfff), // all states + }) + + // Do the query and parse the result + var result []*Socket + var err error + err = req.ExecuteIter(unix.NETLINK_INET_DIAG, nl.SOCK_DIAG_BY_FAMILY, func(msg []byte) bool { + sockInfo := &Socket{} + if err = sockInfo.deserialize(msg); err != nil { + return false + } + result = append(result, sockInfo) + return true + }) + if err != nil { + return nil, err } - if len(msgs) > 2 { - return nil, fmt.Errorf("multiple (%d) matching sockets", len(msgs)) + return result, nil +} + +// SocketDiagUDP requests INET_DIAG_INFO for UDP protocol for specified family type and return related socket. +func SocketDiagUDP(family uint8) ([]*Socket, error) { + return pkgHandle.SocketDiagUDP(family) +} + +// UnixSocketDiagInfo requests UNIX_DIAG_INFO for unix sockets and return with extension info. +func (h *Handle) UnixSocketDiagInfo() ([]*UnixDiagInfoResp, error) { + // Construct the request + var extensions uint8 + extensions = 1 << UNIX_DIAG_NAME + extensions |= 1 << UNIX_DIAG_PEER + extensions |= 1 << UNIX_DIAG_RQLEN + req := h.newNetlinkRequest(nl.SOCK_DIAG_BY_FAMILY, unix.NLM_F_DUMP) + req.AddData(&unixSocketRequest{ + Family: unix.AF_UNIX, + States: ^uint32(0), // all states + Show: uint32(extensions), + }) + + var result []*UnixDiagInfoResp + var err error + err = req.ExecuteIter(unix.NETLINK_INET_DIAG, nl.SOCK_DIAG_BY_FAMILY, func(msg []byte) bool { + sockInfo := &UnixSocket{} + if err = sockInfo.deserialize(msg); err != nil { + return false + } + + // Diagnosis also delivers sockets with AF_INET family, filter those + if sockInfo.Family != unix.AF_UNIX { + return false + } + + var attrs []syscall.NetlinkRouteAttr + if attrs, err = nl.ParseRouteAttr(msg[sizeofSocket:]); err != nil { + return false + } + + var res *UnixDiagInfoResp + if res, err = attrsToUnixDiagInfoResp(attrs, sockInfo); err != nil { + return false + } + result = append(result, res) + return true + }) + if err != nil { + return nil, err } - sock := &Socket{} - if err := sock.deserialize(msgs[0].Data); err != nil { + return result, nil +} + +// UnixSocketDiagInfo requests UNIX_DIAG_INFO for unix sockets and return with extension info. +func UnixSocketDiagInfo() ([]*UnixDiagInfoResp, error) { + return pkgHandle.UnixSocketDiagInfo() +} + +// UnixSocketDiag requests UNIX_DIAG_INFO for unix sockets. +func (h *Handle) UnixSocketDiag() ([]*UnixSocket, error) { + // Construct the request + req := h.newNetlinkRequest(nl.SOCK_DIAG_BY_FAMILY, unix.NLM_F_DUMP) + req.AddData(&unixSocketRequest{ + Family: unix.AF_UNIX, + States: ^uint32(0), // all states + }) + + var result []*UnixSocket + var err error + err = req.ExecuteIter(unix.NETLINK_INET_DIAG, nl.SOCK_DIAG_BY_FAMILY, func(msg []byte) bool { + sockInfo := &UnixSocket{} + if err = sockInfo.deserialize(msg); err != nil { + return false + } + + // Diagnosis also delivers sockets with AF_INET family, filter those + if sockInfo.Family == unix.AF_UNIX { + result = append(result, sockInfo) + } + return true + }) + if err != nil { return nil, err } - return sock, nil + return result, nil +} + +// UnixSocketDiag requests UNIX_DIAG_INFO for unix sockets. +func UnixSocketDiag() ([]*UnixSocket, error) { + return pkgHandle.UnixSocketDiag() +} + +func attrsToInetDiagTCPInfoResp(attrs []syscall.NetlinkRouteAttr, sockInfo *Socket) (*InetDiagTCPInfoResp, error) { + info := &InetDiagTCPInfoResp{ + InetDiagMsg: sockInfo, + } + for _, a := range attrs { + switch a.Attr.Type { + case INET_DIAG_INFO: + info.TCPInfo = &TCPInfo{} + if err := info.TCPInfo.deserialize(a.Value); err != nil { + return nil, err + } + case INET_DIAG_BBRINFO: + info.TCPBBRInfo = &TCPBBRInfo{} + if err := info.TCPBBRInfo.deserialize(a.Value); err != nil { + return nil, err + } + } + } + + return info, nil +} + +func attrsToInetDiagUDPInfoResp(attrs []syscall.NetlinkRouteAttr, sockInfo *Socket) (*InetDiagUDPInfoResp, error) { + info := &InetDiagUDPInfoResp{ + InetDiagMsg: sockInfo, + } + for _, a := range attrs { + switch a.Attr.Type { + case INET_DIAG_MEMINFO: + info.Memory = &MemInfo{} + if err := info.Memory.deserialize(a.Value); err != nil { + return nil, err + } + } + } + + return info, nil +} + +func attrsToUnixDiagInfoResp(attrs []syscall.NetlinkRouteAttr, sockInfo *UnixSocket) (*UnixDiagInfoResp, error) { + info := &UnixDiagInfoResp{ + DiagMsg: sockInfo, + } + for _, a := range attrs { + switch a.Attr.Type { + case UNIX_DIAG_NAME: + name := string(a.Value[:a.Attr.Len]) + info.Name = &name + case UNIX_DIAG_PEER: + peer := native.Uint32(a.Value) + info.Peer = &peer + case UNIX_DIAG_RQLEN: + info.Queue = &QueueInfo{ + RQueue: native.Uint32(a.Value[:4]), + WQueue: native.Uint32(a.Value[4:]), + } + // default: + // fmt.Println("unknown unix attribute type", a.Attr.Type, "with data", a.Value) + } + } + + return info, nil } diff --git a/vendor/github.com/vishvananda/netlink/socket_xdp_linux.go b/vendor/github.com/vishvananda/netlink/socket_xdp_linux.go new file mode 100644 index 000000000..20c82f9c7 --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/socket_xdp_linux.go @@ -0,0 +1,195 @@ +package netlink + +import ( + "errors" + "fmt" + "syscall" + + "github.com/vishvananda/netlink/nl" + "golang.org/x/sys/unix" +) + +const ( + sizeofXDPSocketRequest = 1 + 1 + 2 + 4 + 4 + 2*4 + sizeofXDPSocket = 0x10 +) + +// https://elixir.bootlin.com/linux/v6.2/source/include/uapi/linux/xdp_diag.h#L12 +type xdpSocketRequest struct { + Family uint8 + Protocol uint8 + pad uint16 + Ino uint32 + Show uint32 + Cookie [2]uint32 +} + +func (r *xdpSocketRequest) Serialize() []byte { + b := writeBuffer{Bytes: make([]byte, sizeofSocketRequest)} + b.Write(r.Family) + b.Write(r.Protocol) + native.PutUint16(b.Next(2), r.pad) + native.PutUint32(b.Next(4), r.Ino) + native.PutUint32(b.Next(4), r.Show) + native.PutUint32(b.Next(4), r.Cookie[0]) + native.PutUint32(b.Next(4), r.Cookie[1]) + return b.Bytes +} + +func (r *xdpSocketRequest) Len() int { return sizeofXDPSocketRequest } + +func (s *XDPSocket) deserialize(b []byte) error { + if len(b) < sizeofXDPSocket { + return fmt.Errorf("XDP socket data short read (%d); want %d", len(b), sizeofXDPSocket) + } + rb := readBuffer{Bytes: b} + s.Family = rb.Read() + s.Type = rb.Read() + s.pad = native.Uint16(rb.Next(2)) + s.Ino = native.Uint32(rb.Next(4)) + s.Cookie[0] = native.Uint32(rb.Next(4)) + s.Cookie[1] = native.Uint32(rb.Next(4)) + return nil +} + +// XDPSocketGet returns the XDP socket identified by its inode number and/or +// socket cookie. Specify the cookie as SOCK_ANY_COOKIE if +func SocketXDPGetInfo(ino uint32, cookie uint64) (*XDPDiagInfoResp, error) { + // We have a problem here: dumping AF_XDP sockets currently does not support + // filtering. We thus need to dump all XSKs and then only filter afterwards + // :( + xsks, err := SocketDiagXDP() + if err != nil { + return nil, err + } + checkCookie := cookie != SOCK_ANY_COOKIE && cookie != 0 + crumblingCookie := [2]uint32{uint32(cookie), uint32(cookie >> 32)} + checkIno := ino != 0 + var xskinfo *XDPDiagInfoResp + for _, xsk := range xsks { + if checkIno && xsk.XDPDiagMsg.Ino != ino { + continue + } + if checkCookie && xsk.XDPDiagMsg.Cookie != crumblingCookie { + continue + } + if xskinfo != nil { + return nil, errors.New("multiple matching XDP sockets") + } + xskinfo = xsk + } + if xskinfo == nil { + return nil, errors.New("no matching XDP socket") + } + return xskinfo, nil +} + +// SocketDiagXDP requests XDP_DIAG_INFO for XDP family sockets. +func SocketDiagXDP() ([]*XDPDiagInfoResp, error) { + var result []*XDPDiagInfoResp + err := socketDiagXDPExecutor(func(m syscall.NetlinkMessage) error { + sockInfo := &XDPSocket{} + if err := sockInfo.deserialize(m.Data); err != nil { + return err + } + attrs, err := nl.ParseRouteAttr(m.Data[sizeofXDPSocket:]) + if err != nil { + return err + } + + res, err := attrsToXDPDiagInfoResp(attrs, sockInfo) + if err != nil { + return err + } + + result = append(result, res) + return nil + }) + if err != nil { + return nil, err + } + return result, nil +} + +// socketDiagXDPExecutor requests XDP_DIAG_INFO for XDP family sockets. +func socketDiagXDPExecutor(receiver func(syscall.NetlinkMessage) error) error { + s, err := nl.Subscribe(unix.NETLINK_INET_DIAG) + if err != nil { + return err + } + defer s.Close() + + req := nl.NewNetlinkRequest(nl.SOCK_DIAG_BY_FAMILY, unix.NLM_F_DUMP) + req.AddData(&xdpSocketRequest{ + Family: unix.AF_XDP, + Show: XDP_SHOW_INFO | XDP_SHOW_RING_CFG | XDP_SHOW_UMEM | XDP_SHOW_STATS, + }) + if err := s.Send(req); err != nil { + return err + } + +loop: + for { + msgs, from, err := s.Receive() + if err != nil { + return err + } + if from.Pid != nl.PidKernel { + return fmt.Errorf("Wrong sender portid %d, expected %d", from.Pid, nl.PidKernel) + } + if len(msgs) == 0 { + return errors.New("no message nor error from netlink") + } + + for _, m := range msgs { + switch m.Header.Type { + case unix.NLMSG_DONE: + break loop + case unix.NLMSG_ERROR: + error := int32(native.Uint32(m.Data[0:4])) + return syscall.Errno(-error) + } + if err := receiver(m); err != nil { + return err + } + } + } + return nil +} + +func attrsToXDPDiagInfoResp(attrs []syscall.NetlinkRouteAttr, sockInfo *XDPSocket) (*XDPDiagInfoResp, error) { + resp := &XDPDiagInfoResp{ + XDPDiagMsg: sockInfo, + XDPInfo: &XDPInfo{}, + } + for _, a := range attrs { + switch a.Attr.Type { + case XDP_DIAG_INFO: + resp.XDPInfo.Ifindex = native.Uint32(a.Value[0:4]) + resp.XDPInfo.QueueID = native.Uint32(a.Value[4:8]) + case XDP_DIAG_UID: + resp.XDPInfo.UID = native.Uint32(a.Value[0:4]) + case XDP_DIAG_RX_RING: + resp.XDPInfo.RxRingEntries = native.Uint32(a.Value[0:4]) + case XDP_DIAG_TX_RING: + resp.XDPInfo.TxRingEntries = native.Uint32(a.Value[0:4]) + case XDP_DIAG_UMEM_FILL_RING: + resp.XDPInfo.UmemFillRingEntries = native.Uint32(a.Value[0:4]) + case XDP_DIAG_UMEM_COMPLETION_RING: + resp.XDPInfo.UmemCompletionRingEntries = native.Uint32(a.Value[0:4]) + case XDP_DIAG_UMEM: + umem := &XDPDiagUmem{} + if err := umem.deserialize(a.Value); err != nil { + return nil, err + } + resp.XDPInfo.Umem = umem + case XDP_DIAG_STATS: + stats := &XDPDiagStats{} + if err := stats.deserialize(a.Value); err != nil { + return nil, err + } + resp.XDPInfo.Stats = stats + } + } + return resp, nil +} diff --git a/vendor/github.com/vishvananda/netlink/tcp.go b/vendor/github.com/vishvananda/netlink/tcp.go new file mode 100644 index 000000000..43f80a0fc --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/tcp.go @@ -0,0 +1,92 @@ +package netlink + +// TCP States +const ( + TCP_ESTABLISHED = iota + 0x01 + TCP_SYN_SENT + TCP_SYN_RECV + TCP_FIN_WAIT1 + TCP_FIN_WAIT2 + TCP_TIME_WAIT + TCP_CLOSE + TCP_CLOSE_WAIT + TCP_LAST_ACK + TCP_LISTEN + TCP_CLOSING + TCP_NEW_SYN_REC + TCP_MAX_STATES +) + +type TCPInfo struct { + State uint8 + Ca_state uint8 + Retransmits uint8 + Probes uint8 + Backoff uint8 + Options uint8 + Snd_wscale uint8 // no uint4 + Rcv_wscale uint8 + Delivery_rate_app_limited uint8 + Fastopen_client_fail uint8 + Rto uint32 + Ato uint32 + Snd_mss uint32 + Rcv_mss uint32 + Unacked uint32 + Sacked uint32 + Lost uint32 + Retrans uint32 + Fackets uint32 + Last_data_sent uint32 + Last_ack_sent uint32 + Last_data_recv uint32 + Last_ack_recv uint32 + Pmtu uint32 + Rcv_ssthresh uint32 + Rtt uint32 + Rttvar uint32 + Snd_ssthresh uint32 + Snd_cwnd uint32 + Advmss uint32 + Reordering uint32 + Rcv_rtt uint32 + Rcv_space uint32 + Total_retrans uint32 + Pacing_rate uint64 + Max_pacing_rate uint64 + Bytes_acked uint64 /* RFC4898 tcpEStatsAppHCThruOctetsAcked */ + Bytes_received uint64 /* RFC4898 tcpEStatsAppHCThruOctetsReceived */ + Segs_out uint32 /* RFC4898 tcpEStatsPerfSegsOut */ + Segs_in uint32 /* RFC4898 tcpEStatsPerfSegsIn */ + Notsent_bytes uint32 + Min_rtt uint32 + Data_segs_in uint32 /* RFC4898 tcpEStatsDataSegsIn */ + Data_segs_out uint32 /* RFC4898 tcpEStatsDataSegsOut */ + Delivery_rate uint64 + Busy_time uint64 /* Time (usec) busy sending data */ + Rwnd_limited uint64 /* Time (usec) limited by receive window */ + Sndbuf_limited uint64 /* Time (usec) limited by send buffer */ + Delivered uint32 + Delivered_ce uint32 + Bytes_sent uint64 /* RFC4898 tcpEStatsPerfHCDataOctetsOut */ + Bytes_retrans uint64 /* RFC4898 tcpEStatsPerfOctetsRetrans */ + Dsack_dups uint32 /* RFC4898 tcpEStatsStackDSACKDups */ + Reord_seen uint32 /* reordering events seen */ + Rcv_ooopack uint32 /* Out-of-order packets received */ + Snd_wnd uint32 /* peer's advertised receive window after * scaling (bytes) */ +} + +type TCPBBRInfo struct { + BBRBW uint64 + BBRMinRTT uint32 + BBRPacingGain uint32 + BBRCwndGain uint32 +} + +// According to https://man7.org/linux/man-pages/man7/sock_diag.7.html +type MemInfo struct { + RMem uint32 + WMem uint32 + FMem uint32 + TMem uint32 +} diff --git a/vendor/github.com/vishvananda/netlink/tcp_linux.go b/vendor/github.com/vishvananda/netlink/tcp_linux.go new file mode 100644 index 000000000..e98036da5 --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/tcp_linux.go @@ -0,0 +1,368 @@ +package netlink + +import ( + "bytes" + "errors" + "io" +) + +const ( + tcpBBRInfoLen = 20 + memInfoLen = 16 +) + +func checkDeserErr(err error) error { + if err == io.EOF { + return nil + } + return err +} + +func (t *TCPInfo) deserialize(b []byte) error { + var err error + rb := bytes.NewBuffer(b) + + t.State, err = rb.ReadByte() + if err != nil { + return checkDeserErr(err) + } + + t.Ca_state, err = rb.ReadByte() + if err != nil { + return checkDeserErr(err) + } + + t.Retransmits, err = rb.ReadByte() + if err != nil { + return checkDeserErr(err) + } + + t.Probes, err = rb.ReadByte() + if err != nil { + return checkDeserErr(err) + } + + t.Backoff, err = rb.ReadByte() + if err != nil { + return checkDeserErr(err) + } + t.Options, err = rb.ReadByte() + if err != nil { + return checkDeserErr(err) + } + + scales, err := rb.ReadByte() + if err != nil { + return checkDeserErr(err) + } + t.Snd_wscale = scales >> 4 // first 4 bits + t.Rcv_wscale = scales & 0xf // last 4 bits + + rateLimAndFastOpen, err := rb.ReadByte() + if err != nil { + return checkDeserErr(err) + } + t.Delivery_rate_app_limited = rateLimAndFastOpen >> 7 // get first bit + t.Fastopen_client_fail = rateLimAndFastOpen >> 5 & 3 // get next two bits + + next := rb.Next(4) + if len(next) == 0 { + return nil + } + t.Rto = native.Uint32(next) + + next = rb.Next(4) + if len(next) == 0 { + return nil + } + t.Ato = native.Uint32(next) + + next = rb.Next(4) + if len(next) == 0 { + return nil + } + t.Snd_mss = native.Uint32(next) + + next = rb.Next(4) + if len(next) == 0 { + return nil + } + t.Rcv_mss = native.Uint32(next) + + next = rb.Next(4) + if len(next) == 0 { + return nil + } + t.Unacked = native.Uint32(next) + + next = rb.Next(4) + if len(next) == 0 { + return nil + } + t.Sacked = native.Uint32(next) + + next = rb.Next(4) + if len(next) == 0 { + return nil + } + t.Lost = native.Uint32(next) + + next = rb.Next(4) + if len(next) == 0 { + return nil + } + t.Retrans = native.Uint32(next) + + next = rb.Next(4) + if len(next) == 0 { + return nil + } + t.Fackets = native.Uint32(next) + + next = rb.Next(4) + if len(next) == 0 { + return nil + } + t.Last_data_sent = native.Uint32(next) + + next = rb.Next(4) + if len(next) == 0 { + return nil + } + t.Last_ack_sent = native.Uint32(next) + + next = rb.Next(4) + if len(next) == 0 { + return nil + } + t.Last_data_recv = native.Uint32(next) + + next = rb.Next(4) + if len(next) == 0 { + return nil + } + t.Last_ack_recv = native.Uint32(next) + + next = rb.Next(4) + if len(next) == 0 { + return nil + } + t.Pmtu = native.Uint32(next) + + next = rb.Next(4) + if len(next) == 0 { + return nil + } + t.Rcv_ssthresh = native.Uint32(next) + + next = rb.Next(4) + if len(next) == 0 { + return nil + } + t.Rtt = native.Uint32(next) + + next = rb.Next(4) + if len(next) == 0 { + return nil + } + t.Rttvar = native.Uint32(next) + + next = rb.Next(4) + if len(next) == 0 { + return nil + } + t.Snd_ssthresh = native.Uint32(next) + + next = rb.Next(4) + if len(next) == 0 { + return nil + } + t.Snd_cwnd = native.Uint32(next) + + next = rb.Next(4) + if len(next) == 0 { + return nil + } + t.Advmss = native.Uint32(next) + + next = rb.Next(4) + if len(next) == 0 { + return nil + } + t.Reordering = native.Uint32(next) + + next = rb.Next(4) + if len(next) == 0 { + return nil + } + t.Rcv_rtt = native.Uint32(next) + + next = rb.Next(4) + if len(next) == 0 { + return nil + } + t.Rcv_space = native.Uint32(next) + + next = rb.Next(4) + if len(next) == 0 { + return nil + } + t.Total_retrans = native.Uint32(next) + + next = rb.Next(8) + if len(next) == 0 { + return nil + } + t.Pacing_rate = native.Uint64(next) + + next = rb.Next(8) + if len(next) == 0 { + return nil + } + t.Max_pacing_rate = native.Uint64(next) + + next = rb.Next(8) + if len(next) == 0 { + return nil + } + t.Bytes_acked = native.Uint64(next) + + next = rb.Next(8) + if len(next) == 0 { + return nil + } + t.Bytes_received = native.Uint64(next) + + next = rb.Next(4) + if len(next) == 0 { + return nil + } + t.Segs_out = native.Uint32(next) + + next = rb.Next(4) + if len(next) == 0 { + return nil + } + t.Segs_in = native.Uint32(next) + next = rb.Next(4) + if len(next) == 0 { + return nil + } + t.Notsent_bytes = native.Uint32(next) + next = rb.Next(4) + if len(next) == 0 { + return nil + } + t.Min_rtt = native.Uint32(next) + next = rb.Next(4) + if len(next) == 0 { + return nil + } + t.Data_segs_in = native.Uint32(next) + next = rb.Next(4) + if len(next) == 0 { + return nil + } + t.Data_segs_out = native.Uint32(next) + + next = rb.Next(8) + if len(next) == 0 { + return nil + } + t.Delivery_rate = native.Uint64(next) + + next = rb.Next(8) + if len(next) == 0 { + return nil + } + t.Busy_time = native.Uint64(next) + + next = rb.Next(8) + if len(next) == 0 { + return nil + } + t.Rwnd_limited = native.Uint64(next) + + next = rb.Next(8) + if len(next) == 0 { + return nil + } + t.Sndbuf_limited = native.Uint64(next) + + next = rb.Next(4) + if len(next) == 0 { + return nil + } + t.Delivered = native.Uint32(next) + + next = rb.Next(4) + if len(next) == 0 { + return nil + } + t.Delivered_ce = native.Uint32(next) + + next = rb.Next(8) + if len(next) == 0 { + return nil + } + t.Bytes_sent = native.Uint64(next) + + next = rb.Next(8) + if len(next) == 0 { + return nil + } + t.Bytes_retrans = native.Uint64(next) + + next = rb.Next(4) + if len(next) == 0 { + return nil + } + t.Dsack_dups = native.Uint32(next) + + next = rb.Next(4) + if len(next) == 0 { + return nil + } + t.Reord_seen = native.Uint32(next) + + next = rb.Next(4) + if len(next) == 0 { + return nil + } + t.Rcv_ooopack = native.Uint32(next) + + next = rb.Next(4) + if len(next) == 0 { + return nil + } + t.Snd_wnd = native.Uint32(next) + return nil +} + +func (t *TCPBBRInfo) deserialize(b []byte) error { + if len(b) != tcpBBRInfoLen { + return errors.New("Invalid length") + } + + rb := bytes.NewBuffer(b) + t.BBRBW = native.Uint64(rb.Next(8)) + t.BBRMinRTT = native.Uint32(rb.Next(4)) + t.BBRPacingGain = native.Uint32(rb.Next(4)) + t.BBRCwndGain = native.Uint32(rb.Next(4)) + + return nil +} + +func (m *MemInfo) deserialize(b []byte) error { + if len(b) != memInfoLen { + return errors.New("Invalid length") + } + + rb := bytes.NewBuffer(b) + m.RMem = native.Uint32(rb.Next(4)) + m.WMem = native.Uint32(rb.Next(4)) + m.FMem = native.Uint32(rb.Next(4)) + m.TMem = native.Uint32(rb.Next(4)) + + return nil +} diff --git a/vendor/github.com/vishvananda/netlink/unix_diag.go b/vendor/github.com/vishvananda/netlink/unix_diag.go new file mode 100644 index 000000000..d81776f36 --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/unix_diag.go @@ -0,0 +1,27 @@ +package netlink + +// According to linux/include/uapi/linux/unix_diag.h +const ( + UNIX_DIAG_NAME = iota + UNIX_DIAG_VFS + UNIX_DIAG_PEER + UNIX_DIAG_ICONS + UNIX_DIAG_RQLEN + UNIX_DIAG_MEMINFO + UNIX_DIAG_SHUTDOWN + UNIX_DIAG_UID + UNIX_DIAG_MAX +) + +type UnixDiagInfoResp struct { + DiagMsg *UnixSocket + Name *string + Peer *uint32 + Queue *QueueInfo + Shutdown *uint8 +} + +type QueueInfo struct { + RQueue uint32 + WQueue uint32 +} diff --git a/vendor/github.com/vishvananda/netlink/vdpa_linux.go b/vendor/github.com/vishvananda/netlink/vdpa_linux.go new file mode 100644 index 000000000..7c15986d0 --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/vdpa_linux.go @@ -0,0 +1,463 @@ +package netlink + +import ( + "fmt" + "net" + "syscall" + + "golang.org/x/sys/unix" + + "github.com/vishvananda/netlink/nl" +) + +type vdpaDevID struct { + Name string + ID uint32 +} + +// VDPADev contains info about VDPA device +type VDPADev struct { + vdpaDevID + VendorID uint32 + MaxVQS uint32 + MaxVQSize uint16 + MinVQSize uint16 +} + +// VDPADevConfig contains configuration of the VDPA device +type VDPADevConfig struct { + vdpaDevID + Features uint64 + NegotiatedFeatures uint64 + Net VDPADevConfigNet +} + +// VDPADevVStats conatins vStats for the VDPA device +type VDPADevVStats struct { + vdpaDevID + QueueIndex uint32 + Vendor []VDPADevVStatsVendor + NegotiatedFeatures uint64 +} + +// VDPADevVStatsVendor conatins name and value for vendor specific vstat option +type VDPADevVStatsVendor struct { + Name string + Value uint64 +} + +// VDPADevConfigNet conatins status and net config for the VDPA device +type VDPADevConfigNet struct { + Status VDPADevConfigNetStatus + Cfg VDPADevConfigNetCfg +} + +// VDPADevConfigNetStatus contains info about net status +type VDPADevConfigNetStatus struct { + LinkUp bool + Announce bool +} + +// VDPADevConfigNetCfg contains net config for the VDPA device +type VDPADevConfigNetCfg struct { + MACAddr net.HardwareAddr + MaxVQP uint16 + MTU uint16 +} + +// VDPAMGMTDev conatins info about VDPA management device +type VDPAMGMTDev struct { + BusName string + DevName string + SupportedClasses uint64 + SupportedFeatures uint64 + MaxVQS uint32 +} + +// VDPANewDevParams contains parameters for new VDPA device +// use SetBits to configure requried features for the device +// example: +// +// VDPANewDevParams{Features: SetBits(0, VIRTIO_NET_F_MTU, VIRTIO_NET_F_CTRL_MAC_ADDR)} +type VDPANewDevParams struct { + MACAddr net.HardwareAddr + MaxVQP uint16 + MTU uint16 + Features uint64 +} + +// SetBits set provided bits in the uint64 input value +// usage example: +// features := SetBits(0, VIRTIO_NET_F_MTU, VIRTIO_NET_F_CTRL_MAC_ADDR) +func SetBits(input uint64, pos ...int) uint64 { + for _, p := range pos { + input |= 1 << uint64(p) + } + return input +} + +// IsBitSet check if specific bit is set in the uint64 input value +// usage example: +// hasNetClass := IsBitSet(mgmtDev, VIRTIO_ID_NET) +func IsBitSet(input uint64, pos int) bool { + val := input & (1 << uint64(pos)) + return val > 0 +} + +// VDPANewDev adds new VDPA device +// Equivalent to: `vdpa dev add name mgmtdev /mgmtName [params]` +func VDPANewDev(name, mgmtBus, mgmtName string, params VDPANewDevParams) error { + return pkgHandle.VDPANewDev(name, mgmtBus, mgmtName, params) +} + +// VDPADelDev removes VDPA device +// Equivalent to: `vdpa dev del ` +func VDPADelDev(name string) error { + return pkgHandle.VDPADelDev(name) +} + +// VDPAGetDevList returns list of VDPA devices +// Equivalent to: `vdpa dev show` +func VDPAGetDevList() ([]*VDPADev, error) { + return pkgHandle.VDPAGetDevList() +} + +// VDPAGetDevByName returns VDPA device selected by name +// Equivalent to: `vdpa dev show ` +func VDPAGetDevByName(name string) (*VDPADev, error) { + return pkgHandle.VDPAGetDevByName(name) +} + +// VDPAGetDevConfigList returns list of VDPA devices configurations +// Equivalent to: `vdpa dev config show` +func VDPAGetDevConfigList() ([]*VDPADevConfig, error) { + return pkgHandle.VDPAGetDevConfigList() +} + +// VDPAGetDevConfigByName returns VDPA device configuration selected by name +// Equivalent to: `vdpa dev config show ` +func VDPAGetDevConfigByName(name string) (*VDPADevConfig, error) { + return pkgHandle.VDPAGetDevConfigByName(name) +} + +// VDPAGetDevVStats returns vstats for VDPA device +// Equivalent to: `vdpa dev vstats show qidx ` +func VDPAGetDevVStats(name string, queueIndex uint32) (*VDPADevVStats, error) { + return pkgHandle.VDPAGetDevVStats(name, queueIndex) +} + +// VDPAGetMGMTDevList returns list of mgmt devices +// Equivalent to: `vdpa mgmtdev show` +func VDPAGetMGMTDevList() ([]*VDPAMGMTDev, error) { + return pkgHandle.VDPAGetMGMTDevList() +} + +// VDPAGetMGMTDevByBusAndName returns mgmt devices selected by bus and name +// Equivalent to: `vdpa mgmtdev show /` +func VDPAGetMGMTDevByBusAndName(bus, name string) (*VDPAMGMTDev, error) { + return pkgHandle.VDPAGetMGMTDevByBusAndName(bus, name) +} + +type vdpaNetlinkMessage []syscall.NetlinkRouteAttr + +func (id *vdpaDevID) parseIDAttribute(attr syscall.NetlinkRouteAttr) { + switch attr.Attr.Type { + case nl.VDPA_ATTR_DEV_NAME: + id.Name = nl.BytesToString(attr.Value) + case nl.VDPA_ATTR_DEV_ID: + id.ID = native.Uint32(attr.Value) + } +} + +func (netStatus *VDPADevConfigNetStatus) parseStatusAttribute(value []byte) { + a := native.Uint16(value) + netStatus.Announce = (a & VIRTIO_NET_S_ANNOUNCE) > 0 + netStatus.LinkUp = (a & VIRTIO_NET_S_LINK_UP) > 0 +} + +func (d *VDPADev) parseAttributes(attrs vdpaNetlinkMessage) { + for _, a := range attrs { + d.parseIDAttribute(a) + switch a.Attr.Type { + case nl.VDPA_ATTR_DEV_VENDOR_ID: + d.VendorID = native.Uint32(a.Value) + case nl.VDPA_ATTR_DEV_MAX_VQS: + d.MaxVQS = native.Uint32(a.Value) + case nl.VDPA_ATTR_DEV_MAX_VQ_SIZE: + d.MaxVQSize = native.Uint16(a.Value) + case nl.VDPA_ATTR_DEV_MIN_VQ_SIZE: + d.MinVQSize = native.Uint16(a.Value) + } + } +} + +func (c *VDPADevConfig) parseAttributes(attrs vdpaNetlinkMessage) { + for _, a := range attrs { + c.parseIDAttribute(a) + switch a.Attr.Type { + case nl.VDPA_ATTR_DEV_NET_CFG_MACADDR: + c.Net.Cfg.MACAddr = a.Value + case nl.VDPA_ATTR_DEV_NET_STATUS: + c.Net.Status.parseStatusAttribute(a.Value) + case nl.VDPA_ATTR_DEV_NET_CFG_MAX_VQP: + c.Net.Cfg.MaxVQP = native.Uint16(a.Value) + case nl.VDPA_ATTR_DEV_NET_CFG_MTU: + c.Net.Cfg.MTU = native.Uint16(a.Value) + case nl.VDPA_ATTR_DEV_FEATURES: + c.Features = native.Uint64(a.Value) + case nl.VDPA_ATTR_DEV_NEGOTIATED_FEATURES: + c.NegotiatedFeatures = native.Uint64(a.Value) + } + } +} + +func (s *VDPADevVStats) parseAttributes(attrs vdpaNetlinkMessage) { + for _, a := range attrs { + s.parseIDAttribute(a) + switch a.Attr.Type { + case nl.VDPA_ATTR_DEV_QUEUE_INDEX: + s.QueueIndex = native.Uint32(a.Value) + case nl.VDPA_ATTR_DEV_VENDOR_ATTR_NAME: + s.Vendor = append(s.Vendor, VDPADevVStatsVendor{Name: nl.BytesToString(a.Value)}) + case nl.VDPA_ATTR_DEV_VENDOR_ATTR_VALUE: + if len(s.Vendor) == 0 { + break + } + s.Vendor[len(s.Vendor)-1].Value = native.Uint64(a.Value) + case nl.VDPA_ATTR_DEV_NEGOTIATED_FEATURES: + s.NegotiatedFeatures = native.Uint64(a.Value) + } + } +} + +func (d *VDPAMGMTDev) parseAttributes(attrs vdpaNetlinkMessage) { + for _, a := range attrs { + switch a.Attr.Type { + case nl.VDPA_ATTR_MGMTDEV_BUS_NAME: + d.BusName = nl.BytesToString(a.Value) + case nl.VDPA_ATTR_MGMTDEV_DEV_NAME: + d.DevName = nl.BytesToString(a.Value) + case nl.VDPA_ATTR_MGMTDEV_SUPPORTED_CLASSES: + d.SupportedClasses = native.Uint64(a.Value) + case nl.VDPA_ATTR_DEV_SUPPORTED_FEATURES: + d.SupportedFeatures = native.Uint64(a.Value) + case nl.VDPA_ATTR_DEV_MGMTDEV_MAX_VQS: + d.MaxVQS = native.Uint32(a.Value) + } + } +} + +func (h *Handle) vdpaRequest(command uint8, extraFlags int, attrs []*nl.RtAttr) ([]vdpaNetlinkMessage, error) { + f, err := h.GenlFamilyGet(nl.VDPA_GENL_NAME) + if err != nil { + return nil, err + } + req := h.newNetlinkRequest(int(f.ID), unix.NLM_F_ACK|extraFlags) + req.AddData(&nl.Genlmsg{ + Command: command, + Version: nl.VDPA_GENL_VERSION, + }) + for _, a := range attrs { + req.AddData(a) + } + + resp, err := req.Execute(unix.NETLINK_GENERIC, 0) + if err != nil { + return nil, err + } + messages := make([]vdpaNetlinkMessage, 0, len(resp)) + for _, m := range resp { + attrs, err := nl.ParseRouteAttr(m[nl.SizeofGenlmsg:]) + if err != nil { + return nil, err + } + messages = append(messages, attrs) + } + return messages, nil +} + +// dump all devices if dev is nil +func (h *Handle) vdpaDevGet(dev *string) ([]*VDPADev, error) { + var extraFlags int + var attrs []*nl.RtAttr + if dev != nil { + attrs = append(attrs, nl.NewRtAttr(nl.VDPA_ATTR_DEV_NAME, nl.ZeroTerminated(*dev))) + } else { + extraFlags = extraFlags | unix.NLM_F_DUMP + } + messages, err := h.vdpaRequest(nl.VDPA_CMD_DEV_GET, extraFlags, attrs) + if err != nil { + return nil, err + } + devs := make([]*VDPADev, 0, len(messages)) + for _, m := range messages { + d := &VDPADev{} + d.parseAttributes(m) + devs = append(devs, d) + } + return devs, nil +} + +// dump all devices if dev is nil +func (h *Handle) vdpaDevConfigGet(dev *string) ([]*VDPADevConfig, error) { + var extraFlags int + var attrs []*nl.RtAttr + if dev != nil { + attrs = append(attrs, nl.NewRtAttr(nl.VDPA_ATTR_DEV_NAME, nl.ZeroTerminated(*dev))) + } else { + extraFlags = extraFlags | unix.NLM_F_DUMP + } + messages, err := h.vdpaRequest(nl.VDPA_CMD_DEV_CONFIG_GET, extraFlags, attrs) + if err != nil { + return nil, err + } + cfgs := make([]*VDPADevConfig, 0, len(messages)) + for _, m := range messages { + cfg := &VDPADevConfig{} + cfg.parseAttributes(m) + cfgs = append(cfgs, cfg) + } + return cfgs, nil +} + +// dump all devices if dev is nil +func (h *Handle) vdpaMGMTDevGet(bus, dev *string) ([]*VDPAMGMTDev, error) { + var extraFlags int + var attrs []*nl.RtAttr + if dev != nil { + attrs = append(attrs, + nl.NewRtAttr(nl.VDPA_ATTR_MGMTDEV_DEV_NAME, nl.ZeroTerminated(*dev)), + ) + if bus != nil { + attrs = append(attrs, + nl.NewRtAttr(nl.VDPA_ATTR_MGMTDEV_BUS_NAME, nl.ZeroTerminated(*bus)), + ) + } + } else { + extraFlags = extraFlags | unix.NLM_F_DUMP + } + messages, err := h.vdpaRequest(nl.VDPA_CMD_MGMTDEV_GET, extraFlags, attrs) + if err != nil { + return nil, err + } + cfgs := make([]*VDPAMGMTDev, 0, len(messages)) + for _, m := range messages { + cfg := &VDPAMGMTDev{} + cfg.parseAttributes(m) + cfgs = append(cfgs, cfg) + } + return cfgs, nil +} + +// VDPANewDev adds new VDPA device +// Equivalent to: `vdpa dev add name mgmtdev /mgmtName [params]` +func (h *Handle) VDPANewDev(name, mgmtBus, mgmtName string, params VDPANewDevParams) error { + attrs := []*nl.RtAttr{ + nl.NewRtAttr(nl.VDPA_ATTR_DEV_NAME, nl.ZeroTerminated(name)), + nl.NewRtAttr(nl.VDPA_ATTR_MGMTDEV_DEV_NAME, nl.ZeroTerminated(mgmtName)), + } + if mgmtBus != "" { + attrs = append(attrs, nl.NewRtAttr(nl.VDPA_ATTR_MGMTDEV_BUS_NAME, nl.ZeroTerminated(mgmtBus))) + } + if len(params.MACAddr) != 0 { + attrs = append(attrs, nl.NewRtAttr(nl.VDPA_ATTR_DEV_NET_CFG_MACADDR, params.MACAddr)) + } + if params.MaxVQP > 0 { + attrs = append(attrs, nl.NewRtAttr(nl.VDPA_ATTR_DEV_NET_CFG_MAX_VQP, nl.Uint16Attr(params.MaxVQP))) + } + if params.MTU > 0 { + attrs = append(attrs, nl.NewRtAttr(nl.VDPA_ATTR_DEV_NET_CFG_MTU, nl.Uint16Attr(params.MTU))) + } + if params.Features > 0 { + attrs = append(attrs, nl.NewRtAttr(nl.VDPA_ATTR_DEV_FEATURES, nl.Uint64Attr(params.Features))) + } + _, err := h.vdpaRequest(nl.VDPA_CMD_DEV_NEW, 0, attrs) + return err +} + +// VDPADelDev removes VDPA device +// Equivalent to: `vdpa dev del ` +func (h *Handle) VDPADelDev(name string) error { + _, err := h.vdpaRequest(nl.VDPA_CMD_DEV_DEL, 0, []*nl.RtAttr{ + nl.NewRtAttr(nl.VDPA_ATTR_DEV_NAME, nl.ZeroTerminated(name))}) + return err +} + +// VDPAGetDevList returns list of VDPA devices +// Equivalent to: `vdpa dev show` +func (h *Handle) VDPAGetDevList() ([]*VDPADev, error) { + return h.vdpaDevGet(nil) +} + +// VDPAGetDevByName returns VDPA device selected by name +// Equivalent to: `vdpa dev show ` +func (h *Handle) VDPAGetDevByName(name string) (*VDPADev, error) { + devs, err := h.vdpaDevGet(&name) + if err != nil { + return nil, err + } + if len(devs) == 0 { + return nil, fmt.Errorf("device not found") + } + return devs[0], nil +} + +// VDPAGetDevConfigList returns list of VDPA devices configurations +// Equivalent to: `vdpa dev config show` +func (h *Handle) VDPAGetDevConfigList() ([]*VDPADevConfig, error) { + return h.vdpaDevConfigGet(nil) +} + +// VDPAGetDevConfigByName returns VDPA device configuration selected by name +// Equivalent to: `vdpa dev config show ` +func (h *Handle) VDPAGetDevConfigByName(name string) (*VDPADevConfig, error) { + cfgs, err := h.vdpaDevConfigGet(&name) + if err != nil { + return nil, err + } + if len(cfgs) == 0 { + return nil, fmt.Errorf("configuration not found") + } + return cfgs[0], nil +} + +// VDPAGetDevVStats returns vstats for VDPA device +// Equivalent to: `vdpa dev vstats show qidx ` +func (h *Handle) VDPAGetDevVStats(name string, queueIndex uint32) (*VDPADevVStats, error) { + messages, err := h.vdpaRequest(nl.VDPA_CMD_DEV_VSTATS_GET, 0, []*nl.RtAttr{ + nl.NewRtAttr(nl.VDPA_ATTR_DEV_NAME, nl.ZeroTerminated(name)), + nl.NewRtAttr(nl.VDPA_ATTR_DEV_QUEUE_INDEX, nl.Uint32Attr(queueIndex)), + }) + if err != nil { + return nil, err + } + if len(messages) == 0 { + return nil, fmt.Errorf("stats not found") + } + stats := &VDPADevVStats{} + stats.parseAttributes(messages[0]) + return stats, nil +} + +// VDPAGetMGMTDevList returns list of mgmt devices +// Equivalent to: `vdpa mgmtdev show` +func (h *Handle) VDPAGetMGMTDevList() ([]*VDPAMGMTDev, error) { + return h.vdpaMGMTDevGet(nil, nil) +} + +// VDPAGetMGMTDevByBusAndName returns mgmt devices selected by bus and name +// Equivalent to: `vdpa mgmtdev show /` +func (h *Handle) VDPAGetMGMTDevByBusAndName(bus, name string) (*VDPAMGMTDev, error) { + var busPtr *string + if bus != "" { + busPtr = &bus + } + devs, err := h.vdpaMGMTDevGet(busPtr, &name) + if err != nil { + return nil, err + } + if len(devs) == 0 { + return nil, fmt.Errorf("mgmtdev not found") + } + return devs[0], nil +} diff --git a/vendor/github.com/vishvananda/netlink/virtio.go b/vendor/github.com/vishvananda/netlink/virtio.go new file mode 100644 index 000000000..78a497bbc --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/virtio.go @@ -0,0 +1,132 @@ +package netlink + +// features for virtio net +const ( + VIRTIO_NET_F_CSUM = 0 // Host handles pkts w/ partial csum + VIRTIO_NET_F_GUEST_CSUM = 1 // Guest handles pkts w/ partial csum + VIRTIO_NET_F_CTRL_GUEST_OFFLOADS = 2 // Dynamic offload configuration. + VIRTIO_NET_F_MTU = 3 // Initial MTU advice + VIRTIO_NET_F_MAC = 5 // Host has given MAC address. + VIRTIO_NET_F_GUEST_TSO4 = 7 // Guest can handle TSOv4 in. + VIRTIO_NET_F_GUEST_TSO6 = 8 // Guest can handle TSOv6 in. + VIRTIO_NET_F_GUEST_ECN = 9 // Guest can handle TSO[6] w/ ECN in. + VIRTIO_NET_F_GUEST_UFO = 10 // Guest can handle UFO in. + VIRTIO_NET_F_HOST_TSO4 = 11 // Host can handle TSOv4 in. + VIRTIO_NET_F_HOST_TSO6 = 12 // Host can handle TSOv6 in. + VIRTIO_NET_F_HOST_ECN = 13 // Host can handle TSO[6] w/ ECN in. + VIRTIO_NET_F_HOST_UFO = 14 // Host can handle UFO in. + VIRTIO_NET_F_MRG_RXBUF = 15 // Host can merge receive buffers. + VIRTIO_NET_F_STATUS = 16 // virtio_net_config.status available + VIRTIO_NET_F_CTRL_VQ = 17 // Control channel available + VIRTIO_NET_F_CTRL_RX = 18 // Control channel RX mode support + VIRTIO_NET_F_CTRL_VLAN = 19 // Control channel VLAN filtering + VIRTIO_NET_F_CTRL_RX_EXTRA = 20 // Extra RX mode control support + VIRTIO_NET_F_GUEST_ANNOUNCE = 21 // Guest can announce device on the* network + VIRTIO_NET_F_MQ = 22 // Device supports Receive Flow Steering + VIRTIO_NET_F_CTRL_MAC_ADDR = 23 // Set MAC address + VIRTIO_NET_F_VQ_NOTF_COAL = 52 // Device supports virtqueue notification coalescing + VIRTIO_NET_F_NOTF_COAL = 53 // Device supports notifications coalescing + VIRTIO_NET_F_GUEST_USO4 = 54 // Guest can handle USOv4 in. + VIRTIO_NET_F_GUEST_USO6 = 55 // Guest can handle USOv6 in. + VIRTIO_NET_F_HOST_USO = 56 // Host can handle USO in. + VIRTIO_NET_F_HASH_REPORT = 57 // Supports hash report + VIRTIO_NET_F_GUEST_HDRLEN = 59 // Guest provides the exact hdr_len value. + VIRTIO_NET_F_RSS = 60 // Supports RSS RX steering + VIRTIO_NET_F_RSC_EXT = 61 // extended coalescing info + VIRTIO_NET_F_STANDBY = 62 // Act as standby for another device with the same MAC. + VIRTIO_NET_F_SPEED_DUPLEX = 63 // Device set linkspeed and duplex + VIRTIO_NET_F_GSO = 6 // Host handles pkts any GSO type +) + +// virtio net status +const ( + VIRTIO_NET_S_LINK_UP = 1 // Link is up + VIRTIO_NET_S_ANNOUNCE = 2 // Announcement is needed +) + +// virtio config +const ( + // Do we get callbacks when the ring is completely used, even if we've + // suppressed them? + VIRTIO_F_NOTIFY_ON_EMPTY = 24 + // Can the device handle any descriptor layout? + VIRTIO_F_ANY_LAYOUT = 27 + // v1.0 compliant + VIRTIO_F_VERSION_1 = 32 + // If clear - device has the platform DMA (e.g. IOMMU) bypass quirk feature. + // If set - use platform DMA tools to access the memory. + // Note the reverse polarity (compared to most other features), + // this is for compatibility with legacy systems. + VIRTIO_F_ACCESS_PLATFORM = 33 + // Legacy name for VIRTIO_F_ACCESS_PLATFORM (for compatibility with old userspace) + VIRTIO_F_IOMMU_PLATFORM = VIRTIO_F_ACCESS_PLATFORM + // This feature indicates support for the packed virtqueue layout. + VIRTIO_F_RING_PACKED = 34 + // Inorder feature indicates that all buffers are used by the device + // in the same order in which they have been made available. + VIRTIO_F_IN_ORDER = 35 + // This feature indicates that memory accesses by the driver and the + // device are ordered in a way described by the platform. + VIRTIO_F_ORDER_PLATFORM = 36 + // Does the device support Single Root I/O Virtualization? + VIRTIO_F_SR_IOV = 37 + // This feature indicates that the driver passes extra data (besides + // identifying the virtqueue) in its device notifications. + VIRTIO_F_NOTIFICATION_DATA = 38 + // This feature indicates that the driver uses the data provided by the device + // as a virtqueue identifier in available buffer notifications. + VIRTIO_F_NOTIF_CONFIG_DATA = 39 + // This feature indicates that the driver can reset a queue individually. + VIRTIO_F_RING_RESET = 40 +) + +// virtio device ids +const ( + VIRTIO_ID_NET = 1 // virtio net + VIRTIO_ID_BLOCK = 2 // virtio block + VIRTIO_ID_CONSOLE = 3 // virtio console + VIRTIO_ID_RNG = 4 // virtio rng + VIRTIO_ID_BALLOON = 5 // virtio balloon + VIRTIO_ID_IOMEM = 6 // virtio ioMemory + VIRTIO_ID_RPMSG = 7 // virtio remote processor messaging + VIRTIO_ID_SCSI = 8 // virtio scsi + VIRTIO_ID_9P = 9 // 9p virtio console + VIRTIO_ID_MAC80211_WLAN = 10 // virtio WLAN MAC + VIRTIO_ID_RPROC_SERIAL = 11 // virtio remoteproc serial link + VIRTIO_ID_CAIF = 12 // Virtio caif + VIRTIO_ID_MEMORY_BALLOON = 13 // virtio memory balloon + VIRTIO_ID_GPU = 16 // virtio GPU + VIRTIO_ID_CLOCK = 17 // virtio clock/timer + VIRTIO_ID_INPUT = 18 // virtio input + VIRTIO_ID_VSOCK = 19 // virtio vsock transport + VIRTIO_ID_CRYPTO = 20 // virtio crypto + VIRTIO_ID_SIGNAL_DIST = 21 // virtio signal distribution device + VIRTIO_ID_PSTORE = 22 // virtio pstore device + VIRTIO_ID_IOMMU = 23 // virtio IOMMU + VIRTIO_ID_MEM = 24 // virtio mem + VIRTIO_ID_SOUND = 25 // virtio sound + VIRTIO_ID_FS = 26 // virtio filesystem + VIRTIO_ID_PMEM = 27 // virtio pmem + VIRTIO_ID_RPMB = 28 // virtio rpmb + VIRTIO_ID_MAC80211_HWSIM = 29 // virtio mac80211-hwsim + VIRTIO_ID_VIDEO_ENCODER = 30 // virtio video encoder + VIRTIO_ID_VIDEO_DECODER = 31 // virtio video decoder + VIRTIO_ID_SCMI = 32 // virtio SCMI + VIRTIO_ID_NITRO_SEC_MOD = 33 // virtio nitro secure module + VIRTIO_ID_I2C_ADAPTER = 34 // virtio i2c adapter + VIRTIO_ID_WATCHDOG = 35 // virtio watchdog + VIRTIO_ID_CAN = 36 // virtio can + VIRTIO_ID_DMABUF = 37 // virtio dmabuf + VIRTIO_ID_PARAM_SERV = 38 // virtio parameter server + VIRTIO_ID_AUDIO_POLICY = 39 // virtio audio policy + VIRTIO_ID_BT = 40 // virtio bluetooth + VIRTIO_ID_GPIO = 41 // virtio gpio + // Virtio Transitional IDs + VIRTIO_TRANS_ID_NET = 0x1000 // transitional virtio net + VIRTIO_TRANS_ID_BLOCK = 0x1001 // transitional virtio block + VIRTIO_TRANS_ID_BALLOON = 0x1002 // transitional virtio balloon + VIRTIO_TRANS_ID_CONSOLE = 0x1003 // transitional virtio console + VIRTIO_TRANS_ID_SCSI = 0x1004 // transitional virtio SCSI + VIRTIO_TRANS_ID_RNG = 0x1005 // transitional virtio rng + VIRTIO_TRANS_ID_9P = 0x1009 // transitional virtio 9p console +) diff --git a/vendor/github.com/vishvananda/netlink/xdp_diag.go b/vendor/github.com/vishvananda/netlink/xdp_diag.go new file mode 100644 index 000000000..e88825bf5 --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/xdp_diag.go @@ -0,0 +1,34 @@ +package netlink + +import "github.com/vishvananda/netlink/nl" + +const SOCK_ANY_COOKIE = uint64(nl.TCPDIAG_NOCOOKIE)<<32 + uint64(nl.TCPDIAG_NOCOOKIE) + +// XDP diagnosis show flag constants to request particular information elements. +const ( + XDP_SHOW_INFO = 1 << iota + XDP_SHOW_RING_CFG + XDP_SHOW_UMEM + XDP_SHOW_MEMINFO + XDP_SHOW_STATS +) + +// XDP diag element constants +const ( + XDP_DIAG_NONE = iota + XDP_DIAG_INFO // when using XDP_SHOW_INFO + XDP_DIAG_UID // when using XDP_SHOW_INFO + XDP_DIAG_RX_RING // when using XDP_SHOW_RING_CFG + XDP_DIAG_TX_RING // when using XDP_SHOW_RING_CFG + XDP_DIAG_UMEM // when using XDP_SHOW_UMEM + XDP_DIAG_UMEM_FILL_RING // when using XDP_SHOW_UMEM + XDP_DIAG_UMEM_COMPLETION_RING // when using XDP_SHOW_UMEM + XDP_DIAG_MEMINFO // when using XDP_SHOW_MEMINFO + XDP_DIAG_STATS // when using XDP_SHOW_STATS +) + +// https://elixir.bootlin.com/linux/v6.2/source/include/uapi/linux/xdp_diag.h#L21 +type XDPDiagInfoResp struct { + XDPDiagMsg *XDPSocket + XDPInfo *XDPInfo +} diff --git a/vendor/github.com/vishvananda/netlink/xdp_linux.go b/vendor/github.com/vishvananda/netlink/xdp_linux.go new file mode 100644 index 000000000..896a406de --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/xdp_linux.go @@ -0,0 +1,46 @@ +package netlink + +import ( + "bytes" + "fmt" +) + +const ( + xdrDiagUmemLen = 8 + 8*4 + xdrDiagStatsLen = 6 * 8 +) + +func (x *XDPDiagUmem) deserialize(b []byte) error { + if len(b) < xdrDiagUmemLen { + return fmt.Errorf("XDP umem diagnosis data short read (%d); want %d", len(b), xdrDiagUmemLen) + } + + rb := bytes.NewBuffer(b) + x.Size = native.Uint64(rb.Next(8)) + x.ID = native.Uint32(rb.Next(4)) + x.NumPages = native.Uint32(rb.Next(4)) + x.ChunkSize = native.Uint32(rb.Next(4)) + x.Headroom = native.Uint32(rb.Next(4)) + x.Ifindex = native.Uint32(rb.Next(4)) + x.QueueID = native.Uint32(rb.Next(4)) + x.Flags = native.Uint32(rb.Next(4)) + x.Refs = native.Uint32(rb.Next(4)) + + return nil +} + +func (x *XDPDiagStats) deserialize(b []byte) error { + if len(b) < xdrDiagStatsLen { + return fmt.Errorf("XDP diagnosis statistics short read (%d); want %d", len(b), xdrDiagStatsLen) + } + + rb := bytes.NewBuffer(b) + x.RxDropped = native.Uint64(rb.Next(8)) + x.RxInvalid = native.Uint64(rb.Next(8)) + x.RxFull = native.Uint64(rb.Next(8)) + x.FillRingEmpty = native.Uint64(rb.Next(8)) + x.TxInvalid = native.Uint64(rb.Next(8)) + x.TxRingEmpty = native.Uint64(rb.Next(8)) + + return nil +} diff --git a/vendor/github.com/vishvananda/netlink/xfrm.go b/vendor/github.com/vishvananda/netlink/xfrm_linux.go similarity index 95% rename from vendor/github.com/vishvananda/netlink/xfrm.go rename to vendor/github.com/vishvananda/netlink/xfrm_linux.go index 02b41842e..dd38ed8e0 100644 --- a/vendor/github.com/vishvananda/netlink/xfrm.go +++ b/vendor/github.com/vishvananda/netlink/xfrm_linux.go @@ -14,7 +14,7 @@ const ( XFRM_PROTO_ESP Proto = unix.IPPROTO_ESP XFRM_PROTO_AH Proto = unix.IPPROTO_AH XFRM_PROTO_HAO Proto = unix.IPPROTO_DSTOPTS - XFRM_PROTO_COMP Proto = 0x6c // NOTE not defined on darwin + XFRM_PROTO_COMP Proto = unix.IPPROTO_COMP XFRM_PROTO_IPSEC_ANY Proto = unix.IPPROTO_RAW ) diff --git a/vendor/github.com/vishvananda/netlink/xfrm_policy.go b/vendor/github.com/vishvananda/netlink/xfrm_policy.go deleted file mode 100644 index 6219d2772..000000000 --- a/vendor/github.com/vishvananda/netlink/xfrm_policy.go +++ /dev/null @@ -1,96 +0,0 @@ -package netlink - -import ( - "fmt" - "net" -) - -// Dir is an enum representing an ipsec template direction. -type Dir uint8 - -const ( - XFRM_DIR_IN Dir = iota - XFRM_DIR_OUT - XFRM_DIR_FWD - XFRM_SOCKET_IN - XFRM_SOCKET_OUT - XFRM_SOCKET_FWD -) - -func (d Dir) String() string { - switch d { - case XFRM_DIR_IN: - return "dir in" - case XFRM_DIR_OUT: - return "dir out" - case XFRM_DIR_FWD: - return "dir fwd" - case XFRM_SOCKET_IN: - return "socket in" - case XFRM_SOCKET_OUT: - return "socket out" - case XFRM_SOCKET_FWD: - return "socket fwd" - } - return fmt.Sprintf("socket %d", d-XFRM_SOCKET_IN) -} - -// PolicyAction is an enum representing an ipsec policy action. -type PolicyAction uint8 - -const ( - XFRM_POLICY_ALLOW PolicyAction = 0 - XFRM_POLICY_BLOCK PolicyAction = 1 -) - -func (a PolicyAction) String() string { - switch a { - case XFRM_POLICY_ALLOW: - return "allow" - case XFRM_POLICY_BLOCK: - return "block" - default: - return fmt.Sprintf("action %d", a) - } -} - -// XfrmPolicyTmpl encapsulates a rule for the base addresses of an ipsec -// policy. These rules are matched with XfrmState to determine encryption -// and authentication algorithms. -type XfrmPolicyTmpl struct { - Dst net.IP - Src net.IP - Proto Proto - Mode Mode - Spi int - Reqid int -} - -func (t XfrmPolicyTmpl) String() string { - return fmt.Sprintf("{Dst: %v, Src: %v, Proto: %s, Mode: %s, Spi: 0x%x, Reqid: 0x%x}", - t.Dst, t.Src, t.Proto, t.Mode, t.Spi, t.Reqid) -} - -// XfrmPolicy represents an ipsec policy. It represents the overlay network -// and has a list of XfrmPolicyTmpls representing the base addresses of -// the policy. -type XfrmPolicy struct { - Dst *net.IPNet - Src *net.IPNet - Proto Proto - DstPort int - SrcPort int - Dir Dir - Priority int - Index int - Action PolicyAction - Ifindex int - Ifid int - Mark *XfrmMark - Tmpls []XfrmPolicyTmpl -} - -func (p XfrmPolicy) String() string { - return fmt.Sprintf("{Dst: %v, Src: %v, Proto: %s, DstPort: %d, SrcPort: %d, Dir: %s, Priority: %d, Index: %d, Action: %s, Ifindex: %d, Ifid: %d, Mark: %s, Tmpls: %s}", - p.Dst, p.Src, p.Proto, p.DstPort, p.SrcPort, p.Dir, p.Priority, p.Index, p.Action, p.Ifindex, p.Ifid, p.Mark, p.Tmpls) -} diff --git a/vendor/github.com/vishvananda/netlink/xfrm_policy_linux.go b/vendor/github.com/vishvananda/netlink/xfrm_policy_linux.go index a4e132ef5..d526739ce 100644 --- a/vendor/github.com/vishvananda/netlink/xfrm_policy_linux.go +++ b/vendor/github.com/vishvananda/netlink/xfrm_policy_linux.go @@ -1,10 +1,104 @@ package netlink import ( + "fmt" + "net" + "github.com/vishvananda/netlink/nl" "golang.org/x/sys/unix" ) +// Dir is an enum representing an ipsec template direction. +type Dir uint8 + +const ( + XFRM_DIR_IN Dir = iota + XFRM_DIR_OUT + XFRM_DIR_FWD + XFRM_SOCKET_IN + XFRM_SOCKET_OUT + XFRM_SOCKET_FWD +) + +func (d Dir) String() string { + switch d { + case XFRM_DIR_IN: + return "dir in" + case XFRM_DIR_OUT: + return "dir out" + case XFRM_DIR_FWD: + return "dir fwd" + case XFRM_SOCKET_IN: + return "socket in" + case XFRM_SOCKET_OUT: + return "socket out" + case XFRM_SOCKET_FWD: + return "socket fwd" + } + return fmt.Sprintf("socket %d", d-XFRM_SOCKET_IN) +} + +// PolicyAction is an enum representing an ipsec policy action. +type PolicyAction uint8 + +const ( + XFRM_POLICY_ALLOW PolicyAction = 0 + XFRM_POLICY_BLOCK PolicyAction = 1 +) + +func (a PolicyAction) String() string { + switch a { + case XFRM_POLICY_ALLOW: + return "allow" + case XFRM_POLICY_BLOCK: + return "block" + default: + return fmt.Sprintf("action %d", a) + } +} + +// XfrmPolicyTmpl encapsulates a rule for the base addresses of an ipsec +// policy. These rules are matched with XfrmState to determine encryption +// and authentication algorithms. +type XfrmPolicyTmpl struct { + Dst net.IP + Src net.IP + Proto Proto + Mode Mode + Spi int + Reqid int + Optional int +} + +func (t XfrmPolicyTmpl) String() string { + return fmt.Sprintf("{Dst: %v, Src: %v, Proto: %s, Mode: %s, Spi: 0x%x, Reqid: 0x%x}", + t.Dst, t.Src, t.Proto, t.Mode, t.Spi, t.Reqid) +} + +// XfrmPolicy represents an ipsec policy. It represents the overlay network +// and has a list of XfrmPolicyTmpls representing the base addresses of +// the policy. +type XfrmPolicy struct { + Dst *net.IPNet + Src *net.IPNet + Proto Proto + DstPort int + SrcPort int + Dir Dir + Priority int + Index int + Action PolicyAction + Ifindex int + Ifid int + Mark *XfrmMark + Tmpls []XfrmPolicyTmpl +} + +func (p XfrmPolicy) String() string { + return fmt.Sprintf("{Dst: %v, Src: %v, Proto: %s, DstPort: %d, SrcPort: %d, Dir: %s, Priority: %d, Index: %d, Action: %s, Ifindex: %d, Ifid: %d, Mark: %s, Tmpls: %s}", + p.Dst, p.Src, p.Proto, p.DstPort, p.SrcPort, p.Dir, p.Priority, p.Index, p.Action, p.Ifindex, p.Ifid, p.Mark, p.Tmpls) +} + func selFromPolicy(sel *nl.XfrmSelector, policy *XfrmPolicy) { sel.Family = uint16(nl.FAMILY_V4) if policy.Dst != nil { @@ -75,10 +169,12 @@ func (h *Handle) xfrmPolicyAddOrUpdate(policy *XfrmPolicy, nlProto int) error { userTmpl := nl.DeserializeXfrmUserTmpl(tmplData[start : start+nl.SizeofXfrmUserTmpl]) userTmpl.XfrmId.Daddr.FromIP(tmpl.Dst) userTmpl.Saddr.FromIP(tmpl.Src) + userTmpl.Family = uint16(nl.GetIPFamily(tmpl.Dst)) userTmpl.XfrmId.Proto = uint8(tmpl.Proto) userTmpl.XfrmId.Spi = nl.Swap32(uint32(tmpl.Spi)) userTmpl.Mode = uint8(tmpl.Mode) userTmpl.Reqid = uint32(tmpl.Reqid) + userTmpl.Optional = uint8(tmpl.Optional) userTmpl.Aalgos = ^uint32(0) userTmpl.Ealgos = ^uint32(0) userTmpl.Calgos = ^uint32(0) @@ -92,8 +188,10 @@ func (h *Handle) xfrmPolicyAddOrUpdate(policy *XfrmPolicy, nlProto int) error { req.AddData(out) } - ifId := nl.NewRtAttr(nl.XFRMA_IF_ID, nl.Uint32Attr(uint32(policy.Ifid))) - req.AddData(ifId) + if policy.Ifid != 0 { + ifId := nl.NewRtAttr(nl.XFRMA_IF_ID, nl.Uint32Attr(uint32(policy.Ifid))) + req.AddData(ifId) + } _, err := req.Execute(unix.NETLINK_XFRM, 0) return err @@ -188,8 +286,10 @@ func (h *Handle) xfrmPolicyGetOrDelete(policy *XfrmPolicy, nlProto int) (*XfrmPo req.AddData(out) } - ifId := nl.NewRtAttr(nl.XFRMA_IF_ID, nl.Uint32Attr(uint32(policy.Ifid))) - req.AddData(ifId) + if policy.Ifid != 0 { + ifId := nl.NewRtAttr(nl.XFRMA_IF_ID, nl.Uint32Attr(uint32(policy.Ifid))) + req.AddData(ifId) + } resType := nl.XFRM_MSG_NEWPOLICY if nlProto == nl.XFRM_MSG_DELPOLICY { @@ -218,8 +318,8 @@ func parseXfrmPolicy(m []byte, family int) (*XfrmPolicy, error) { var policy XfrmPolicy - policy.Dst = msg.Sel.Daddr.ToIPNet(msg.Sel.PrefixlenD) - policy.Src = msg.Sel.Saddr.ToIPNet(msg.Sel.PrefixlenS) + policy.Dst = msg.Sel.Daddr.ToIPNet(msg.Sel.PrefixlenD, uint16(family)) + policy.Src = msg.Sel.Saddr.ToIPNet(msg.Sel.PrefixlenS, uint16(family)) policy.Proto = Proto(msg.Sel.Proto) policy.DstPort = int(nl.Swap16(msg.Sel.Dport)) policy.SrcPort = int(nl.Swap16(msg.Sel.Sport)) @@ -247,6 +347,7 @@ func parseXfrmPolicy(m []byte, family int) (*XfrmPolicy, error) { resTmpl.Mode = Mode(tmpl.Mode) resTmpl.Spi = int(nl.Swap32(tmpl.XfrmId.Spi)) resTmpl.Reqid = int(tmpl.Reqid) + resTmpl.Optional = int(tmpl.Optional) policy.Tmpls = append(policy.Tmpls, resTmpl) } case nl.XFRMA_MARK: diff --git a/vendor/github.com/vishvananda/netlink/xfrm_state.go b/vendor/github.com/vishvananda/netlink/xfrm_state.go deleted file mode 100644 index 483d8934a..000000000 --- a/vendor/github.com/vishvananda/netlink/xfrm_state.go +++ /dev/null @@ -1,131 +0,0 @@ -package netlink - -import ( - "fmt" - "net" - "time" -) - -// XfrmStateAlgo represents the algorithm to use for the ipsec encryption. -type XfrmStateAlgo struct { - Name string - Key []byte - TruncateLen int // Auth only - ICVLen int // AEAD only -} - -func (a XfrmStateAlgo) String() string { - base := fmt.Sprintf("{Name: %s, Key: 0x%x", a.Name, a.Key) - if a.TruncateLen != 0 { - base = fmt.Sprintf("%s, Truncate length: %d", base, a.TruncateLen) - } - if a.ICVLen != 0 { - base = fmt.Sprintf("%s, ICV length: %d", base, a.ICVLen) - } - return fmt.Sprintf("%s}", base) -} - -// EncapType is an enum representing the optional packet encapsulation. -type EncapType uint8 - -const ( - XFRM_ENCAP_ESPINUDP_NONIKE EncapType = iota + 1 - XFRM_ENCAP_ESPINUDP -) - -func (e EncapType) String() string { - switch e { - case XFRM_ENCAP_ESPINUDP_NONIKE: - return "espinudp-non-ike" - case XFRM_ENCAP_ESPINUDP: - return "espinudp" - } - return "unknown" -} - -// XfrmStateEncap represents the encapsulation to use for the ipsec encryption. -type XfrmStateEncap struct { - Type EncapType - SrcPort int - DstPort int - OriginalAddress net.IP -} - -func (e XfrmStateEncap) String() string { - return fmt.Sprintf("{Type: %s, Srcport: %d, DstPort: %d, OriginalAddress: %v}", - e.Type, e.SrcPort, e.DstPort, e.OriginalAddress) -} - -// XfrmStateLimits represents the configured limits for the state. -type XfrmStateLimits struct { - ByteSoft uint64 - ByteHard uint64 - PacketSoft uint64 - PacketHard uint64 - TimeSoft uint64 - TimeHard uint64 - TimeUseSoft uint64 - TimeUseHard uint64 -} - -// XfrmStateStats represents the current number of bytes/packets -// processed by this State, the State's installation and first use -// time and the replay window counters. -type XfrmStateStats struct { - ReplayWindow uint32 - Replay uint32 - Failed uint32 - Bytes uint64 - Packets uint64 - AddTime uint64 - UseTime uint64 -} - -// XfrmState represents the state of an ipsec policy. It optionally -// contains an XfrmStateAlgo for encryption and one for authentication. -type XfrmState struct { - Dst net.IP - Src net.IP - Proto Proto - Mode Mode - Spi int - Reqid int - ReplayWindow int - Limits XfrmStateLimits - Statistics XfrmStateStats - Mark *XfrmMark - OutputMark int - Ifid int - Auth *XfrmStateAlgo - Crypt *XfrmStateAlgo - Aead *XfrmStateAlgo - Encap *XfrmStateEncap - ESN bool -} - -func (sa XfrmState) String() string { - return fmt.Sprintf("Dst: %v, Src: %v, Proto: %s, Mode: %s, SPI: 0x%x, ReqID: 0x%x, ReplayWindow: %d, Mark: %v, OutputMark: %d, Ifid: %d, Auth: %v, Crypt: %v, Aead: %v, Encap: %v, ESN: %t", - sa.Dst, sa.Src, sa.Proto, sa.Mode, sa.Spi, sa.Reqid, sa.ReplayWindow, sa.Mark, sa.OutputMark, sa.Ifid, sa.Auth, sa.Crypt, sa.Aead, sa.Encap, sa.ESN) -} -func (sa XfrmState) Print(stats bool) string { - if !stats { - return sa.String() - } - at := time.Unix(int64(sa.Statistics.AddTime), 0).Format(time.UnixDate) - ut := "-" - if sa.Statistics.UseTime > 0 { - ut = time.Unix(int64(sa.Statistics.UseTime), 0).Format(time.UnixDate) - } - return fmt.Sprintf("%s, ByteSoft: %s, ByteHard: %s, PacketSoft: %s, PacketHard: %s, TimeSoft: %d, TimeHard: %d, TimeUseSoft: %d, TimeUseHard: %d, Bytes: %d, Packets: %d, "+ - "AddTime: %s, UseTime: %s, ReplayWindow: %d, Replay: %d, Failed: %d", - sa.String(), printLimit(sa.Limits.ByteSoft), printLimit(sa.Limits.ByteHard), printLimit(sa.Limits.PacketSoft), printLimit(sa.Limits.PacketHard), - sa.Limits.TimeSoft, sa.Limits.TimeHard, sa.Limits.TimeUseSoft, sa.Limits.TimeUseHard, sa.Statistics.Bytes, sa.Statistics.Packets, at, ut, - sa.Statistics.ReplayWindow, sa.Statistics.Replay, sa.Statistics.Failed) -} - -func printLimit(lmt uint64) string { - if lmt == ^uint64(0) { - return "(INF)" - } - return fmt.Sprintf("%d", lmt) -} diff --git a/vendor/github.com/vishvananda/netlink/xfrm_state_linux.go b/vendor/github.com/vishvananda/netlink/xfrm_state_linux.go index 66c99423c..554f2498c 100644 --- a/vendor/github.com/vishvananda/netlink/xfrm_state_linux.go +++ b/vendor/github.com/vishvananda/netlink/xfrm_state_linux.go @@ -2,12 +2,154 @@ package netlink import ( "fmt" + "net" + "time" "unsafe" "github.com/vishvananda/netlink/nl" "golang.org/x/sys/unix" ) +// XfrmStateAlgo represents the algorithm to use for the ipsec encryption. +type XfrmStateAlgo struct { + Name string + Key []byte + TruncateLen int // Auth only + ICVLen int // AEAD only +} + +func (a XfrmStateAlgo) String() string { + base := fmt.Sprintf("{Name: %s, Key: 0x%x", a.Name, a.Key) + if a.TruncateLen != 0 { + base = fmt.Sprintf("%s, Truncate length: %d", base, a.TruncateLen) + } + if a.ICVLen != 0 { + base = fmt.Sprintf("%s, ICV length: %d", base, a.ICVLen) + } + return fmt.Sprintf("%s}", base) +} + +// EncapType is an enum representing the optional packet encapsulation. +type EncapType uint8 + +const ( + XFRM_ENCAP_ESPINUDP_NONIKE EncapType = iota + 1 + XFRM_ENCAP_ESPINUDP +) + +func (e EncapType) String() string { + switch e { + case XFRM_ENCAP_ESPINUDP_NONIKE: + return "espinudp-non-ike" + case XFRM_ENCAP_ESPINUDP: + return "espinudp" + } + return "unknown" +} + +// XfrmStateEncap represents the encapsulation to use for the ipsec encryption. +type XfrmStateEncap struct { + Type EncapType + SrcPort int + DstPort int + OriginalAddress net.IP +} + +func (e XfrmStateEncap) String() string { + return fmt.Sprintf("{Type: %s, Srcport: %d, DstPort: %d, OriginalAddress: %v}", + e.Type, e.SrcPort, e.DstPort, e.OriginalAddress) +} + +// XfrmStateLimits represents the configured limits for the state. +type XfrmStateLimits struct { + ByteSoft uint64 + ByteHard uint64 + PacketSoft uint64 + PacketHard uint64 + TimeSoft uint64 + TimeHard uint64 + TimeUseSoft uint64 + TimeUseHard uint64 +} + +// XfrmStateStats represents the current number of bytes/packets +// processed by this State, the State's installation and first use +// time and the replay window counters. +type XfrmStateStats struct { + ReplayWindow uint32 + Replay uint32 + Failed uint32 + Bytes uint64 + Packets uint64 + AddTime uint64 + UseTime uint64 +} + +// XfrmReplayState represents the sequence number states for +// "legacy" anti-replay mode. +type XfrmReplayState struct { + OSeq uint32 + Seq uint32 + BitMap uint32 +} + +func (r XfrmReplayState) String() string { + return fmt.Sprintf("{OSeq: 0x%x, Seq: 0x%x, BitMap: 0x%x}", + r.OSeq, r.Seq, r.BitMap) +} + +// XfrmState represents the state of an ipsec policy. It optionally +// contains an XfrmStateAlgo for encryption and one for authentication. +type XfrmState struct { + Dst net.IP + Src net.IP + Proto Proto + Mode Mode + Spi int + Reqid int + ReplayWindow int + Limits XfrmStateLimits + Statistics XfrmStateStats + Mark *XfrmMark + OutputMark *XfrmMark + Ifid int + Auth *XfrmStateAlgo + Crypt *XfrmStateAlgo + Aead *XfrmStateAlgo + Encap *XfrmStateEncap + ESN bool + DontEncapDSCP bool + OSeqMayWrap bool + Replay *XfrmReplayState + Selector *XfrmPolicy +} + +func (sa XfrmState) String() string { + return fmt.Sprintf("Dst: %v, Src: %v, Proto: %s, Mode: %s, SPI: 0x%x, ReqID: 0x%x, ReplayWindow: %d, Mark: %v, OutputMark: %v, Ifid: %d, Auth: %v, Crypt: %v, Aead: %v, Encap: %v, ESN: %t, DontEncapDSCP: %t, OSeqMayWrap: %t, Replay: %v", + sa.Dst, sa.Src, sa.Proto, sa.Mode, sa.Spi, sa.Reqid, sa.ReplayWindow, sa.Mark, sa.OutputMark, sa.Ifid, sa.Auth, sa.Crypt, sa.Aead, sa.Encap, sa.ESN, sa.DontEncapDSCP, sa.OSeqMayWrap, sa.Replay) +} +func (sa XfrmState) Print(stats bool) string { + if !stats { + return sa.String() + } + at := time.Unix(int64(sa.Statistics.AddTime), 0).Format(time.UnixDate) + ut := "-" + if sa.Statistics.UseTime > 0 { + ut = time.Unix(int64(sa.Statistics.UseTime), 0).Format(time.UnixDate) + } + return fmt.Sprintf("%s, ByteSoft: %s, ByteHard: %s, PacketSoft: %s, PacketHard: %s, TimeSoft: %d, TimeHard: %d, TimeUseSoft: %d, TimeUseHard: %d, Bytes: %d, Packets: %d, "+ + "AddTime: %s, UseTime: %s, ReplayWindow: %d, Replay: %d, Failed: %d", + sa.String(), printLimit(sa.Limits.ByteSoft), printLimit(sa.Limits.ByteHard), printLimit(sa.Limits.PacketSoft), printLimit(sa.Limits.PacketHard), + sa.Limits.TimeSoft, sa.Limits.TimeHard, sa.Limits.TimeUseSoft, sa.Limits.TimeUseHard, sa.Statistics.Bytes, sa.Statistics.Packets, at, ut, + sa.Statistics.ReplayWindow, sa.Statistics.Replay, sa.Statistics.Failed) +} + +func printLimit(lmt uint64) string { + if lmt == ^uint64(0) { + return "(INF)" + } + return fmt.Sprintf("%d", lmt) +} func writeStateAlgo(a *XfrmStateAlgo) []byte { algo := nl.XfrmAlgo{ AlgKeyLen: uint32(len(a.Key) * 8), @@ -77,6 +219,14 @@ func writeReplayEsn(replayWindow int) []byte { return replayEsn.Serialize() } +func writeReplay(r *XfrmReplayState) []byte { + return (&nl.XfrmReplayState{ + OSeq: r.OSeq, + Seq: r.Seq, + BitMap: r.BitMap, + }).Serialize() +} + // XfrmStateAdd will add an xfrm state to the system. // Equivalent to: `ip xfrm state add $state` func XfrmStateAdd(state *XfrmState) error { @@ -111,7 +261,7 @@ func (h *Handle) xfrmStateAddOrUpdate(state *XfrmState, nlProto int) error { // A state with spi 0 can't be deleted so don't allow it to be set if state.Spi == 0 { - return fmt.Errorf("Spi must be set when adding xfrm state.") + return fmt.Errorf("Spi must be set when adding xfrm state") } req := h.newNetlinkRequest(nlProto, unix.NLM_F_CREATE|unix.NLM_F_EXCL|unix.NLM_F_ACK) @@ -158,13 +308,34 @@ func (h *Handle) xfrmStateAddOrUpdate(state *XfrmState, nlProto int) error { out := nl.NewRtAttr(nl.XFRMA_REPLAY_ESN_VAL, writeReplayEsn(state.ReplayWindow)) req.AddData(out) } - if state.OutputMark != 0 { - out := nl.NewRtAttr(nl.XFRMA_OUTPUT_MARK, nl.Uint32Attr(uint32(state.OutputMark))) + if state.OutputMark != nil { + out := nl.NewRtAttr(nl.XFRMA_SET_MARK, nl.Uint32Attr(state.OutputMark.Value)) + req.AddData(out) + if state.OutputMark.Mask != 0 { + out = nl.NewRtAttr(nl.XFRMA_SET_MARK_MASK, nl.Uint32Attr(state.OutputMark.Mask)) + req.AddData(out) + } + } + if state.OSeqMayWrap || state.DontEncapDSCP { + var flags uint32 + if state.DontEncapDSCP { + flags |= nl.XFRM_SA_XFLAG_DONT_ENCAP_DSCP + } + if state.OSeqMayWrap { + flags |= nl.XFRM_SA_XFLAG_OSEQ_MAY_WRAP + } + out := nl.NewRtAttr(nl.XFRMA_SA_EXTRA_FLAGS, nl.Uint32Attr(flags)) + req.AddData(out) + } + if state.Replay != nil { + out := nl.NewRtAttr(nl.XFRMA_REPLAY_VAL, writeReplay(state.Replay)) req.AddData(out) } - ifId := nl.NewRtAttr(nl.XFRMA_IF_ID, nl.Uint32Attr(uint32(state.Ifid))) - req.AddData(ifId) + if state.Ifid != 0 { + ifId := nl.NewRtAttr(nl.XFRMA_IF_ID, nl.Uint32Attr(uint32(state.Ifid))) + req.AddData(ifId) + } _, err := req.Execute(unix.NETLINK_XFRM, 0) return err @@ -180,7 +351,6 @@ func (h *Handle) xfrmStateAllocSpi(state *XfrmState) (*XfrmState, error) { msg.Min = 0x100 msg.Max = 0xffffffff req.AddData(msg) - if state.Mark != nil { out := nl.NewRtAttr(nl.XFRMA_MARK, writeMark(state.Mark)) req.AddData(out) @@ -277,8 +447,10 @@ func (h *Handle) xfrmStateGetOrDelete(state *XfrmState, nlProto int) (*XfrmState req.AddData(out) } - ifId := nl.NewRtAttr(nl.XFRMA_IF_ID, nl.Uint32Attr(uint32(state.Ifid))) - req.AddData(ifId) + if state.Ifid != 0 { + ifId := nl.NewRtAttr(nl.XFRMA_IF_ID, nl.Uint32Attr(uint32(state.Ifid))) + req.AddData(ifId) + } resType := nl.XFRM_MSG_NEWSA if nlProto == nl.XFRM_MSG_DELSA { @@ -306,7 +478,6 @@ var familyError = fmt.Errorf("family error") func xfrmStateFromXfrmUsersaInfo(msg *nl.XfrmUsersaInfo) *XfrmState { var state XfrmState - state.Dst = msg.Id.Daddr.ToIP() state.Src = msg.Saddr.ToIP() state.Proto = Proto(msg.Id.Proto) @@ -316,20 +487,25 @@ func xfrmStateFromXfrmUsersaInfo(msg *nl.XfrmUsersaInfo) *XfrmState { state.ReplayWindow = int(msg.ReplayWindow) lftToLimits(&msg.Lft, &state.Limits) curToStats(&msg.Curlft, &msg.Stats, &state.Statistics) + state.Selector = &XfrmPolicy{ + Dst: msg.Sel.Daddr.ToIPNet(msg.Sel.PrefixlenD, msg.Sel.Family), + Src: msg.Sel.Saddr.ToIPNet(msg.Sel.PrefixlenS, msg.Sel.Family), + Proto: Proto(msg.Sel.Proto), + DstPort: int(nl.Swap16(msg.Sel.Dport)), + SrcPort: int(nl.Swap16(msg.Sel.Sport)), + Ifindex: int(msg.Sel.Ifindex), + } return &state } func parseXfrmState(m []byte, family int) (*XfrmState, error) { msg := nl.DeserializeXfrmUsersaInfo(m) - // This is mainly for the state dump if family != FAMILY_ALL && family != int(msg.Family) { return nil, familyError } - state := xfrmStateFromXfrmUsersaInfo(msg) - attrs, err := nl.ParseRouteAttr(m[nl.SizeofXfrmUsersaInfo:]) if err != nil { return nil, err @@ -377,10 +553,37 @@ func parseXfrmState(m []byte, family int) (*XfrmState, error) { state.Mark = new(XfrmMark) state.Mark.Value = mark.Value state.Mark.Mask = mark.Mask - case nl.XFRMA_OUTPUT_MARK: - state.OutputMark = int(native.Uint32(attr.Value)) + case nl.XFRMA_SA_EXTRA_FLAGS: + flags := native.Uint32(attr.Value) + if (flags & nl.XFRM_SA_XFLAG_DONT_ENCAP_DSCP) != 0 { + state.DontEncapDSCP = true + } + if (flags & nl.XFRM_SA_XFLAG_OSEQ_MAY_WRAP) != 0 { + state.OSeqMayWrap = true + } + case nl.XFRMA_SET_MARK: + if state.OutputMark == nil { + state.OutputMark = new(XfrmMark) + } + state.OutputMark.Value = native.Uint32(attr.Value) + case nl.XFRMA_SET_MARK_MASK: + if state.OutputMark == nil { + state.OutputMark = new(XfrmMark) + } + state.OutputMark.Mask = native.Uint32(attr.Value) + if state.OutputMark.Mask == 0xffffffff { + state.OutputMark.Mask = 0 + } case nl.XFRMA_IF_ID: state.Ifid = int(native.Uint32(attr.Value)) + case nl.XFRMA_REPLAY_VAL: + if state.Replay == nil { + state.Replay = new(XfrmReplayState) + } + replay := nl.DeserializeXfrmReplayState(attr.Value[:]) + state.Replay.OSeq = replay.OSeq + state.Replay.Seq = replay.Seq + state.Replay.BitMap = replay.BitMap } } @@ -457,6 +660,9 @@ func xfrmUsersaInfoFromXfrmState(state *XfrmState) *nl.XfrmUsersaInfo { msg.Id.Spi = nl.Swap32(uint32(state.Spi)) msg.Reqid = uint32(state.Reqid) msg.ReplayWindow = uint8(state.ReplayWindow) - + msg.Sel = nl.XfrmSelector{} + if state.Selector != nil { + selFromPolicy(&msg.Sel, state.Selector) + } return msg } diff --git a/vendor/github.com/vishvananda/netlink/xfrm_unspecified.go b/vendor/github.com/vishvananda/netlink/xfrm_unspecified.go new file mode 100644 index 000000000..12fdd26d7 --- /dev/null +++ b/vendor/github.com/vishvananda/netlink/xfrm_unspecified.go @@ -0,0 +1,7 @@ +//go:build !linux +// +build !linux + +package netlink + +type XfrmPolicy struct{} +type XfrmState struct{} diff --git a/vendor/go.etcd.io/etcd/api/v3/version/version.go b/vendor/go.etcd.io/etcd/api/v3/version/version.go index 4858a08bf..ca6efc513 100644 --- a/vendor/go.etcd.io/etcd/api/v3/version/version.go +++ b/vendor/go.etcd.io/etcd/api/v3/version/version.go @@ -26,7 +26,7 @@ import ( var ( // MinClusterVersion is the min cluster version this etcd binary is compatible with. MinClusterVersion = "3.0.0" - Version = "3.5.12" + Version = "3.5.17" APIVersion = "unknown" // Git SHA Value will be set during build diff --git a/vendor/go.etcd.io/etcd/client/pkg/v3/logutil/zap.go b/vendor/go.etcd.io/etcd/client/pkg/v3/logutil/zap.go index 34f35b9f2..f0f3739aa 100644 --- a/vendor/go.etcd.io/etcd/client/pkg/v3/logutil/zap.go +++ b/vendor/go.etcd.io/etcd/client/pkg/v3/logutil/zap.go @@ -58,7 +58,7 @@ var DefaultZapLoggerConfig = zap.Config{ // Custom EncodeTime function to ensure we match format and precision of historic capnslog timestamps EncodeTime: func(t time.Time, enc zapcore.PrimitiveArrayEncoder) { - enc.AppendString(t.Format("2006-01-02T15:04:05.999999Z0700")) + enc.AppendString(t.Format("2006-01-02T15:04:05.000000Z0700")) }, EncodeDuration: zapcore.StringDurationEncoder, diff --git a/vendor/go.etcd.io/etcd/client/pkg/v3/types/urls.go b/vendor/go.etcd.io/etcd/client/pkg/v3/types/urls.go index 9e5d03ff6..49a38967e 100644 --- a/vendor/go.etcd.io/etcd/client/pkg/v3/types/urls.go +++ b/vendor/go.etcd.io/etcd/client/pkg/v3/types/urls.go @@ -36,20 +36,25 @@ func NewURLs(strs []string) (URLs, error) { if err != nil { return nil, err } - if u.Scheme != "http" && u.Scheme != "https" && u.Scheme != "unix" && u.Scheme != "unixs" { + + switch u.Scheme { + case "http", "https": + if _, _, err := net.SplitHostPort(u.Host); err != nil { + return nil, fmt.Errorf(`URL address does not have the form "host:port": %s`, in) + } + + if u.Path != "" { + return nil, fmt.Errorf("URL must not contain a path: %s", in) + } + case "unix", "unixs": + break + default: return nil, fmt.Errorf("URL scheme must be http, https, unix, or unixs: %s", in) } - if _, _, err := net.SplitHostPort(u.Host); err != nil { - return nil, fmt.Errorf(`URL address does not have the form "host:port": %s`, in) - } - if u.Path != "" { - return nil, fmt.Errorf("URL must not contain a path: %s", in) - } all[i] = *u } us := URLs(all) us.Sort() - return us, nil } diff --git a/vendor/go.etcd.io/etcd/client/v3/README.md b/vendor/go.etcd.io/etcd/client/v3/README.md index 1e037d7eb..16c0fe888 100644 --- a/vendor/go.etcd.io/etcd/client/v3/README.md +++ b/vendor/go.etcd.io/etcd/client/v3/README.md @@ -11,13 +11,6 @@ go get go.etcd.io/etcd/client/v3 ``` -Warning: As etcd 3.5.0 was not yet released, the command above does not work. -After first pre-release of 3.5.0 [#12498](https://github.com/etcd-io/etcd/issues/12498), -etcd can be referenced using: -``` -go get go.etcd.io/etcd/client/v3@v3.5.0-pre -``` - ## Get started Create client using `clientv3.New`: diff --git a/vendor/go.etcd.io/etcd/client/v3/auth.go b/vendor/go.etcd.io/etcd/client/v3/auth.go index a6f75d321..110918a4c 100644 --- a/vendor/go.etcd.io/etcd/client/v3/auth.go +++ b/vendor/go.etcd.io/etcd/client/v3/auth.go @@ -134,67 +134,67 @@ func NewAuthFromAuthClient(remote pb.AuthClient, c *Client) Auth { func (auth *authClient) Authenticate(ctx context.Context, name string, password string) (*AuthenticateResponse, error) { resp, err := auth.remote.Authenticate(ctx, &pb.AuthenticateRequest{Name: name, Password: password}, auth.callOpts...) - return (*AuthenticateResponse)(resp), toErr(ctx, err) + return (*AuthenticateResponse)(resp), ContextError(ctx, err) } func (auth *authClient) AuthEnable(ctx context.Context) (*AuthEnableResponse, error) { resp, err := auth.remote.AuthEnable(ctx, &pb.AuthEnableRequest{}, auth.callOpts...) - return (*AuthEnableResponse)(resp), toErr(ctx, err) + return (*AuthEnableResponse)(resp), ContextError(ctx, err) } func (auth *authClient) AuthDisable(ctx context.Context) (*AuthDisableResponse, error) { resp, err := auth.remote.AuthDisable(ctx, &pb.AuthDisableRequest{}, auth.callOpts...) - return (*AuthDisableResponse)(resp), toErr(ctx, err) + return (*AuthDisableResponse)(resp), ContextError(ctx, err) } func (auth *authClient) AuthStatus(ctx context.Context) (*AuthStatusResponse, error) { resp, err := auth.remote.AuthStatus(ctx, &pb.AuthStatusRequest{}, auth.callOpts...) - return (*AuthStatusResponse)(resp), toErr(ctx, err) + return (*AuthStatusResponse)(resp), ContextError(ctx, err) } func (auth *authClient) UserAdd(ctx context.Context, name string, password string) (*AuthUserAddResponse, error) { resp, err := auth.remote.UserAdd(ctx, &pb.AuthUserAddRequest{Name: name, Password: password, Options: &authpb.UserAddOptions{NoPassword: false}}, auth.callOpts...) - return (*AuthUserAddResponse)(resp), toErr(ctx, err) + return (*AuthUserAddResponse)(resp), ContextError(ctx, err) } func (auth *authClient) UserAddWithOptions(ctx context.Context, name string, password string, options *UserAddOptions) (*AuthUserAddResponse, error) { resp, err := auth.remote.UserAdd(ctx, &pb.AuthUserAddRequest{Name: name, Password: password, Options: (*authpb.UserAddOptions)(options)}, auth.callOpts...) - return (*AuthUserAddResponse)(resp), toErr(ctx, err) + return (*AuthUserAddResponse)(resp), ContextError(ctx, err) } func (auth *authClient) UserDelete(ctx context.Context, name string) (*AuthUserDeleteResponse, error) { resp, err := auth.remote.UserDelete(ctx, &pb.AuthUserDeleteRequest{Name: name}, auth.callOpts...) - return (*AuthUserDeleteResponse)(resp), toErr(ctx, err) + return (*AuthUserDeleteResponse)(resp), ContextError(ctx, err) } func (auth *authClient) UserChangePassword(ctx context.Context, name string, password string) (*AuthUserChangePasswordResponse, error) { resp, err := auth.remote.UserChangePassword(ctx, &pb.AuthUserChangePasswordRequest{Name: name, Password: password}, auth.callOpts...) - return (*AuthUserChangePasswordResponse)(resp), toErr(ctx, err) + return (*AuthUserChangePasswordResponse)(resp), ContextError(ctx, err) } func (auth *authClient) UserGrantRole(ctx context.Context, user string, role string) (*AuthUserGrantRoleResponse, error) { resp, err := auth.remote.UserGrantRole(ctx, &pb.AuthUserGrantRoleRequest{User: user, Role: role}, auth.callOpts...) - return (*AuthUserGrantRoleResponse)(resp), toErr(ctx, err) + return (*AuthUserGrantRoleResponse)(resp), ContextError(ctx, err) } func (auth *authClient) UserGet(ctx context.Context, name string) (*AuthUserGetResponse, error) { resp, err := auth.remote.UserGet(ctx, &pb.AuthUserGetRequest{Name: name}, auth.callOpts...) - return (*AuthUserGetResponse)(resp), toErr(ctx, err) + return (*AuthUserGetResponse)(resp), ContextError(ctx, err) } func (auth *authClient) UserList(ctx context.Context) (*AuthUserListResponse, error) { resp, err := auth.remote.UserList(ctx, &pb.AuthUserListRequest{}, auth.callOpts...) - return (*AuthUserListResponse)(resp), toErr(ctx, err) + return (*AuthUserListResponse)(resp), ContextError(ctx, err) } func (auth *authClient) UserRevokeRole(ctx context.Context, name string, role string) (*AuthUserRevokeRoleResponse, error) { resp, err := auth.remote.UserRevokeRole(ctx, &pb.AuthUserRevokeRoleRequest{Name: name, Role: role}, auth.callOpts...) - return (*AuthUserRevokeRoleResponse)(resp), toErr(ctx, err) + return (*AuthUserRevokeRoleResponse)(resp), ContextError(ctx, err) } func (auth *authClient) RoleAdd(ctx context.Context, name string) (*AuthRoleAddResponse, error) { resp, err := auth.remote.RoleAdd(ctx, &pb.AuthRoleAddRequest{Name: name}, auth.callOpts...) - return (*AuthRoleAddResponse)(resp), toErr(ctx, err) + return (*AuthRoleAddResponse)(resp), ContextError(ctx, err) } func (auth *authClient) RoleGrantPermission(ctx context.Context, name string, key, rangeEnd string, permType PermissionType) (*AuthRoleGrantPermissionResponse, error) { @@ -204,27 +204,27 @@ func (auth *authClient) RoleGrantPermission(ctx context.Context, name string, ke PermType: authpb.Permission_Type(permType), } resp, err := auth.remote.RoleGrantPermission(ctx, &pb.AuthRoleGrantPermissionRequest{Name: name, Perm: perm}, auth.callOpts...) - return (*AuthRoleGrantPermissionResponse)(resp), toErr(ctx, err) + return (*AuthRoleGrantPermissionResponse)(resp), ContextError(ctx, err) } func (auth *authClient) RoleGet(ctx context.Context, role string) (*AuthRoleGetResponse, error) { resp, err := auth.remote.RoleGet(ctx, &pb.AuthRoleGetRequest{Role: role}, auth.callOpts...) - return (*AuthRoleGetResponse)(resp), toErr(ctx, err) + return (*AuthRoleGetResponse)(resp), ContextError(ctx, err) } func (auth *authClient) RoleList(ctx context.Context) (*AuthRoleListResponse, error) { resp, err := auth.remote.RoleList(ctx, &pb.AuthRoleListRequest{}, auth.callOpts...) - return (*AuthRoleListResponse)(resp), toErr(ctx, err) + return (*AuthRoleListResponse)(resp), ContextError(ctx, err) } func (auth *authClient) RoleRevokePermission(ctx context.Context, role string, key, rangeEnd string) (*AuthRoleRevokePermissionResponse, error) { resp, err := auth.remote.RoleRevokePermission(ctx, &pb.AuthRoleRevokePermissionRequest{Role: role, Key: []byte(key), RangeEnd: []byte(rangeEnd)}, auth.callOpts...) - return (*AuthRoleRevokePermissionResponse)(resp), toErr(ctx, err) + return (*AuthRoleRevokePermissionResponse)(resp), ContextError(ctx, err) } func (auth *authClient) RoleDelete(ctx context.Context, role string) (*AuthRoleDeleteResponse, error) { resp, err := auth.remote.RoleDelete(ctx, &pb.AuthRoleDeleteRequest{Role: role}, auth.callOpts...) - return (*AuthRoleDeleteResponse)(resp), toErr(ctx, err) + return (*AuthRoleDeleteResponse)(resp), ContextError(ctx, err) } func StrToPermissionType(s string) (PermissionType, error) { diff --git a/vendor/go.etcd.io/etcd/client/v3/client.go b/vendor/go.etcd.io/etcd/client/v3/client.go index efa44e890..f7aa65a0a 100644 --- a/vendor/go.etcd.io/etcd/client/v3/client.go +++ b/vendor/go.etcd.io/etcd/client/v3/client.go @@ -86,7 +86,7 @@ func New(cfg Config) (*Client, error) { // service interface implementations and do not need connection management. func NewCtxClient(ctx context.Context, opts ...Option) *Client { cctx, cancel := context.WithCancel(ctx) - c := &Client{ctx: cctx, cancel: cancel, lgMu: new(sync.RWMutex)} + c := &Client{ctx: cctx, cancel: cancel, lgMu: new(sync.RWMutex), mu: new(sync.RWMutex)} for _, opt := range opts { opt(c) } @@ -148,7 +148,7 @@ func (c *Client) Close() error { c.Lease.Close() } if c.conn != nil { - return toErr(c.ctx, c.conn.Close()) + return ContextError(c.ctx, c.conn.Close()) } return c.ctx.Err() } @@ -231,15 +231,30 @@ func (c *Client) dialSetupOpts(creds grpccredentials.TransportCredentials, dopts opts = append(opts, grpc.WithInsecure()) } + unaryMaxRetries := defaultUnaryMaxRetries + if c.cfg.MaxUnaryRetries > 0 { + unaryMaxRetries = c.cfg.MaxUnaryRetries + } + + backoffWaitBetween := defaultBackoffWaitBetween + if c.cfg.BackoffWaitBetween > 0 { + backoffWaitBetween = c.cfg.BackoffWaitBetween + } + + backoffJitterFraction := defaultBackoffJitterFraction + if c.cfg.BackoffJitterFraction > 0 { + backoffJitterFraction = c.cfg.BackoffJitterFraction + } + // Interceptor retry and backoff. // TODO: Replace all of clientv3/retry.go with RetryPolicy: // https://github.com/grpc/grpc-proto/blob/cdd9ed5c3d3f87aef62f373b93361cf7bddc620d/grpc/service_config/service_config.proto#L130 - rrBackoff := withBackoff(c.roundRobinQuorumBackoff(defaultBackoffWaitBetween, defaultBackoffJitterFraction)) + rrBackoff := withBackoff(c.roundRobinQuorumBackoff(backoffWaitBetween, backoffJitterFraction)) opts = append(opts, // Disable stream retry by default since go-grpc-middleware/retry does not support client streams. // Streams that are safe to retry are enabled individually. grpc.WithStreamInterceptor(c.streamClientInterceptor(withMax(0), rrBackoff)), - grpc.WithUnaryInterceptor(c.unaryClientInterceptor(withMax(defaultUnaryMaxRetries), rrBackoff)), + grpc.WithUnaryInterceptor(c.unaryClientInterceptor(withMax(unaryMaxRetries), rrBackoff)), ) return opts, nil @@ -558,7 +573,9 @@ func isUnavailableErr(ctx context.Context, err error) bool { return false } -func toErr(ctx context.Context, err error) error { +// ContextError converts the error into an EtcdError if the error message matches one of +// the defined messages; otherwise, it tries to retrieve the context error. +func ContextError(ctx context.Context, err error) error { if err == nil { return nil } diff --git a/vendor/go.etcd.io/etcd/client/v3/cluster.go b/vendor/go.etcd.io/etcd/client/v3/cluster.go index 92d7cdb56..1815c1c96 100644 --- a/vendor/go.etcd.io/etcd/client/v3/cluster.go +++ b/vendor/go.etcd.io/etcd/client/v3/cluster.go @@ -93,7 +93,7 @@ func (c *cluster) memberAdd(ctx context.Context, peerAddrs []string, isLearner b } resp, err := c.remote.MemberAdd(ctx, r, c.callOpts...) if err != nil { - return nil, toErr(ctx, err) + return nil, ContextError(ctx, err) } return (*MemberAddResponse)(resp), nil } @@ -102,7 +102,7 @@ func (c *cluster) MemberRemove(ctx context.Context, id uint64) (*MemberRemoveRes r := &pb.MemberRemoveRequest{ID: id} resp, err := c.remote.MemberRemove(ctx, r, c.callOpts...) if err != nil { - return nil, toErr(ctx, err) + return nil, ContextError(ctx, err) } return (*MemberRemoveResponse)(resp), nil } @@ -119,7 +119,7 @@ func (c *cluster) MemberUpdate(ctx context.Context, id uint64, peerAddrs []strin if err == nil { return (*MemberUpdateResponse)(resp), nil } - return nil, toErr(ctx, err) + return nil, ContextError(ctx, err) } func (c *cluster) MemberList(ctx context.Context) (*MemberListResponse, error) { @@ -128,14 +128,14 @@ func (c *cluster) MemberList(ctx context.Context) (*MemberListResponse, error) { if err == nil { return (*MemberListResponse)(resp), nil } - return nil, toErr(ctx, err) + return nil, ContextError(ctx, err) } func (c *cluster) MemberPromote(ctx context.Context, id uint64) (*MemberPromoteResponse, error) { r := &pb.MemberPromoteRequest{ID: id} resp, err := c.remote.MemberPromote(ctx, r, c.callOpts...) if err != nil { - return nil, toErr(ctx, err) + return nil, ContextError(ctx, err) } return (*MemberPromoteResponse)(resp), nil } diff --git a/vendor/go.etcd.io/etcd/client/v3/config.go b/vendor/go.etcd.io/etcd/client/v3/config.go index 335a28873..6f5b41978 100644 --- a/vendor/go.etcd.io/etcd/client/v3/config.go +++ b/vendor/go.etcd.io/etcd/client/v3/config.go @@ -88,5 +88,14 @@ type Config struct { // PermitWithoutStream when set will allow client to send keepalive pings to server without any active streams(RPCs). PermitWithoutStream bool `json:"permit-without-stream"` + // MaxUnaryRetries is the maximum number of retries for unary RPCs. + MaxUnaryRetries uint `json:"max-unary-retries"` + + // BackoffWaitBetween is the wait time before retrying an RPC. + BackoffWaitBetween time.Duration `json:"backoff-wait-between"` + + // BackoffJitterFraction is the jitter fraction to randomize backoff wait time. + BackoffJitterFraction float64 `json:"backoff-jitter-fraction"` + // TODO: support custom balancer picker } diff --git a/vendor/go.etcd.io/etcd/client/v3/kv.go b/vendor/go.etcd.io/etcd/client/v3/kv.go index 5e9fb7d45..be5b508dd 100644 --- a/vendor/go.etcd.io/etcd/client/v3/kv.go +++ b/vendor/go.etcd.io/etcd/client/v3/kv.go @@ -112,23 +112,23 @@ func NewKVFromKVClient(remote pb.KVClient, c *Client) KV { func (kv *kv) Put(ctx context.Context, key, val string, opts ...OpOption) (*PutResponse, error) { r, err := kv.Do(ctx, OpPut(key, val, opts...)) - return r.put, toErr(ctx, err) + return r.put, ContextError(ctx, err) } func (kv *kv) Get(ctx context.Context, key string, opts ...OpOption) (*GetResponse, error) { r, err := kv.Do(ctx, OpGet(key, opts...)) - return r.get, toErr(ctx, err) + return r.get, ContextError(ctx, err) } func (kv *kv) Delete(ctx context.Context, key string, opts ...OpOption) (*DeleteResponse, error) { r, err := kv.Do(ctx, OpDelete(key, opts...)) - return r.del, toErr(ctx, err) + return r.del, ContextError(ctx, err) } func (kv *kv) Compact(ctx context.Context, rev int64, opts ...CompactOption) (*CompactResponse, error) { resp, err := kv.remote.Compact(ctx, OpCompact(rev, opts...).toRequest(), kv.callOpts...) if err != nil { - return nil, toErr(ctx, err) + return nil, ContextError(ctx, err) } return (*CompactResponse)(resp), err } @@ -173,5 +173,5 @@ func (kv *kv) Do(ctx context.Context, op Op) (OpResponse, error) { default: panic("Unknown op") } - return OpResponse{}, toErr(ctx, err) + return OpResponse{}, ContextError(ctx, err) } diff --git a/vendor/go.etcd.io/etcd/client/v3/lease.go b/vendor/go.etcd.io/etcd/client/v3/lease.go index 19af9c093..4e7d1caf8 100644 --- a/vendor/go.etcd.io/etcd/client/v3/lease.go +++ b/vendor/go.etcd.io/etcd/client/v3/lease.go @@ -223,7 +223,7 @@ func (l *lessor) Grant(ctx context.Context, ttl int64) (*LeaseGrantResponse, err } return gresp, nil } - return nil, toErr(ctx, err) + return nil, ContextError(ctx, err) } func (l *lessor) Revoke(ctx context.Context, id LeaseID) (*LeaseRevokeResponse, error) { @@ -232,14 +232,14 @@ func (l *lessor) Revoke(ctx context.Context, id LeaseID) (*LeaseRevokeResponse, if err == nil { return (*LeaseRevokeResponse)(resp), nil } - return nil, toErr(ctx, err) + return nil, ContextError(ctx, err) } func (l *lessor) TimeToLive(ctx context.Context, id LeaseID, opts ...LeaseOption) (*LeaseTimeToLiveResponse, error) { r := toLeaseTimeToLiveRequest(id, opts...) resp, err := l.remote.LeaseTimeToLive(ctx, r, l.callOpts...) if err != nil { - return nil, toErr(ctx, err) + return nil, ContextError(ctx, err) } gresp := &LeaseTimeToLiveResponse{ ResponseHeader: resp.GetHeader(), @@ -260,7 +260,7 @@ func (l *lessor) Leases(ctx context.Context) (*LeaseLeasesResponse, error) { } return &LeaseLeasesResponse{ResponseHeader: resp.GetHeader(), Leases: leases}, nil } - return nil, toErr(ctx, err) + return nil, ContextError(ctx, err) } func (l *lessor) KeepAlive(ctx context.Context, id LeaseID) (<-chan *LeaseKeepAliveResponse, error) { @@ -315,7 +315,7 @@ func (l *lessor) KeepAliveOnce(ctx context.Context, id LeaseID) (*LeaseKeepAlive return resp, err } if isHaltErr(ctx, err) { - return nil, toErr(ctx, err) + return nil, ContextError(ctx, err) } } } @@ -405,13 +405,13 @@ func (l *lessor) keepAliveOnce(ctx context.Context, id LeaseID) (karesp *LeaseKe stream, err := l.remote.LeaseKeepAlive(cctx, l.callOpts...) if err != nil { - return nil, toErr(ctx, err) + return nil, ContextError(ctx, err) } defer func() { if err := stream.CloseSend(); err != nil { if ferr == nil { - ferr = toErr(ctx, err) + ferr = ContextError(ctx, err) } return } @@ -419,12 +419,12 @@ func (l *lessor) keepAliveOnce(ctx context.Context, id LeaseID) (karesp *LeaseKe err = stream.Send(&pb.LeaseKeepAliveRequest{ID: int64(id)}) if err != nil { - return nil, toErr(ctx, err) + return nil, ContextError(ctx, err) } resp, rerr := stream.Recv() if rerr != nil { - return nil, toErr(ctx, rerr) + return nil, ContextError(ctx, rerr) } karesp = &LeaseKeepAliveResponse{ @@ -461,7 +461,7 @@ func (l *lessor) recvKeepAliveLoop() (gerr error) { return err } - if toErr(l.stopCtx, err) == rpctypes.ErrNoLeader { + if ContextError(l.stopCtx, err) == rpctypes.ErrNoLeader { l.closeRequireLeader() } break diff --git a/vendor/go.etcd.io/etcd/client/v3/maintenance.go b/vendor/go.etcd.io/etcd/client/v3/maintenance.go index a98b8ca51..71b28e6dc 100644 --- a/vendor/go.etcd.io/etcd/client/v3/maintenance.go +++ b/vendor/go.etcd.io/etcd/client/v3/maintenance.go @@ -130,7 +130,7 @@ func (m *maintenance) AlarmList(ctx context.Context) (*AlarmResponse, error) { if err == nil { return (*AlarmResponse)(resp), nil } - return nil, toErr(ctx, err) + return nil, ContextError(ctx, err) } func (m *maintenance) AlarmDisarm(ctx context.Context, am *AlarmMember) (*AlarmResponse, error) { @@ -143,13 +143,13 @@ func (m *maintenance) AlarmDisarm(ctx context.Context, am *AlarmMember) (*AlarmR if req.MemberID == 0 && req.Alarm == pb.AlarmType_NONE { ar, err := m.AlarmList(ctx) if err != nil { - return nil, toErr(ctx, err) + return nil, ContextError(ctx, err) } ret := AlarmResponse{} for _, am := range ar.Alarms { dresp, derr := m.AlarmDisarm(ctx, (*AlarmMember)(am)) if derr != nil { - return nil, toErr(ctx, derr) + return nil, ContextError(ctx, derr) } ret.Alarms = append(ret.Alarms, dresp.Alarms...) } @@ -160,18 +160,18 @@ func (m *maintenance) AlarmDisarm(ctx context.Context, am *AlarmMember) (*AlarmR if err == nil { return (*AlarmResponse)(resp), nil } - return nil, toErr(ctx, err) + return nil, ContextError(ctx, err) } func (m *maintenance) Defragment(ctx context.Context, endpoint string) (*DefragmentResponse, error) { remote, cancel, err := m.dial(endpoint) if err != nil { - return nil, toErr(ctx, err) + return nil, ContextError(ctx, err) } defer cancel() resp, err := remote.Defragment(ctx, &pb.DefragmentRequest{}, m.callOpts...) if err != nil { - return nil, toErr(ctx, err) + return nil, ContextError(ctx, err) } return (*DefragmentResponse)(resp), nil } @@ -179,12 +179,12 @@ func (m *maintenance) Defragment(ctx context.Context, endpoint string) (*Defragm func (m *maintenance) Status(ctx context.Context, endpoint string) (*StatusResponse, error) { remote, cancel, err := m.dial(endpoint) if err != nil { - return nil, toErr(ctx, err) + return nil, ContextError(ctx, err) } defer cancel() resp, err := remote.Status(ctx, &pb.StatusRequest{}, m.callOpts...) if err != nil { - return nil, toErr(ctx, err) + return nil, ContextError(ctx, err) } return (*StatusResponse)(resp), nil } @@ -193,12 +193,12 @@ func (m *maintenance) HashKV(ctx context.Context, endpoint string, rev int64) (* remote, cancel, err := m.dial(endpoint) if err != nil { - return nil, toErr(ctx, err) + return nil, ContextError(ctx, err) } defer cancel() resp, err := remote.HashKV(ctx, &pb.HashKVRequest{Revision: rev}, m.callOpts...) if err != nil { - return nil, toErr(ctx, err) + return nil, ContextError(ctx, err) } return (*HashKVResponse)(resp), nil } @@ -206,7 +206,7 @@ func (m *maintenance) HashKV(ctx context.Context, endpoint string, rev int64) (* func (m *maintenance) Snapshot(ctx context.Context) (io.ReadCloser, error) { ss, err := m.remote.Snapshot(ctx, &pb.SnapshotRequest{}, append(m.callOpts, withMax(defaultStreamMaxRetries))...) if err != nil { - return nil, toErr(ctx, err) + return nil, ContextError(ctx, err) } m.lg.Info("opened snapshot stream; downloading") @@ -246,10 +246,10 @@ type snapshotReadCloser struct { func (rc *snapshotReadCloser) Read(p []byte) (n int, err error) { n, err = rc.ReadCloser.Read(p) - return n, toErr(rc.ctx, err) + return n, ContextError(rc.ctx, err) } func (m *maintenance) MoveLeader(ctx context.Context, transfereeID uint64) (*MoveLeaderResponse, error) { resp, err := m.remote.MoveLeader(ctx, &pb.MoveLeaderRequest{TargetID: transfereeID}, m.callOpts...) - return (*MoveLeaderResponse)(resp), toErr(ctx, err) + return (*MoveLeaderResponse)(resp), ContextError(ctx, err) } diff --git a/vendor/go.etcd.io/etcd/client/v3/retry_interceptor.go b/vendor/go.etcd.io/etcd/client/v3/retry_interceptor.go index 7dc5ddae0..8c50dcfa9 100644 --- a/vendor/go.etcd.io/etcd/client/v3/retry_interceptor.go +++ b/vendor/go.etcd.io/etcd/client/v3/retry_interceptor.go @@ -19,6 +19,7 @@ package clientv3 import ( "context" + "errors" "io" "sync" "time" @@ -85,7 +86,7 @@ func (c *Client) unaryClientInterceptor(optFuncs ...retryOption) grpc.UnaryClien } continue } - if !isSafeRetry(c.lg, lastErr, callOpts) { + if !isSafeRetry(c, lastErr, callOpts) { return lastErr } } @@ -279,7 +280,7 @@ func (s *serverStreamingRetryingStream) receiveMsgAndIndicateRetry(m interface{} return true, err } - return isSafeRetry(s.client.lg, err, s.callOpts), err + return isSafeRetry(s.client, err, s.callOpts), err } func (s *serverStreamingRetryingStream) reestablishStreamAndResendBuffer(callCtx context.Context) (grpc.ClientStream, error) { @@ -319,17 +320,28 @@ func waitRetryBackoff(ctx context.Context, attempt uint, callOpts *options) erro } // isSafeRetry returns "true", if request is safe for retry with the given error. -func isSafeRetry(lg *zap.Logger, err error, callOpts *options) bool { +func isSafeRetry(c *Client, err error, callOpts *options) bool { if isContextError(err) { return false } + + // Situation when learner refuses RPC it is supposed to not serve is from the server + // perspective not retryable. + // But for backward-compatibility reasons we need to support situation that + // customer provides mix of learners (not yet voters) and voters with an + // expectation to pick voter in the next attempt. + // TODO: Ideally client should be 'aware' which endpoint represents: leader/voter/learner with high probability. + if errors.Is(err, rpctypes.ErrGPRCNotSupportedForLearner) && len(c.Endpoints()) > 1 { + return true + } + switch callOpts.retryPolicy { case repeatable: return isSafeRetryImmutableRPC(err) case nonRepeatable: return isSafeRetryMutableRPC(err) default: - lg.Warn("unrecognized retry policy", zap.String("retryPolicy", callOpts.retryPolicy.String())) + c.lg.Warn("unrecognized retry policy", zap.String("retryPolicy", callOpts.retryPolicy.String())) return false } } diff --git a/vendor/go.etcd.io/etcd/client/v3/txn.go b/vendor/go.etcd.io/etcd/client/v3/txn.go index 3f6a953cf..e31bfe0b9 100644 --- a/vendor/go.etcd.io/etcd/client/v3/txn.go +++ b/vendor/go.etcd.io/etcd/client/v3/txn.go @@ -144,7 +144,7 @@ func (txn *txn) Commit() (*TxnResponse, error) { var err error resp, err = txn.kv.remote.Txn(txn.ctx, r, txn.callOpts...) if err != nil { - return nil, toErr(txn.ctx, err) + return nil, ContextError(txn.ctx, err) } return (*TxnResponse)(resp), nil } diff --git a/vendor/go.etcd.io/etcd/client/v3/watch.go b/vendor/go.etcd.io/etcd/client/v3/watch.go index 41a6ec976..725e8a869 100644 --- a/vendor/go.etcd.io/etcd/client/v3/watch.go +++ b/vendor/go.etcd.io/etcd/client/v3/watch.go @@ -442,7 +442,7 @@ func (w *watchGrpcStream) close() (err error) { case err = <-w.errc: default: } - return toErr(w.ctx, err) + return ContextError(w.ctx, err) } func (w *watcher) closeStream(wgs *watchGrpcStream) { @@ -653,7 +653,7 @@ func (w *watchGrpcStream) run() { // watch client failed on Recv; spawn another if possible case err := <-w.errc: - if isHaltErr(w.ctx, err) || toErr(w.ctx, err) == v3rpc.ErrNoLeader { + if isHaltErr(w.ctx, err) || ContextError(w.ctx, err) == v3rpc.ErrNoLeader { closeErr = err return } @@ -1036,7 +1036,7 @@ func (pr *progressRequest) toPB() *pb.WatchRequest { func streamKeyFromCtx(ctx context.Context) string { if md, ok := metadata.FromOutgoingContext(ctx); ok { - return fmt.Sprintf("%+v", md) + return fmt.Sprintf("%+v", map[string][]string(md)) } return "" } diff --git a/vendor/go.uber.org/automaxprocs/LICENSE b/vendor/go.uber.org/automaxprocs/LICENSE new file mode 100644 index 000000000..20dcf51d9 --- /dev/null +++ b/vendor/go.uber.org/automaxprocs/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2017 Uber Technologies, Inc. + +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. \ No newline at end of file diff --git a/vendor/go.uber.org/automaxprocs/internal/cgroups/cgroup.go b/vendor/go.uber.org/automaxprocs/internal/cgroups/cgroup.go new file mode 100644 index 000000000..fe4ecf561 --- /dev/null +++ b/vendor/go.uber.org/automaxprocs/internal/cgroups/cgroup.go @@ -0,0 +1,79 @@ +// Copyright (c) 2017 Uber Technologies, Inc. +// +// 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. + +//go:build linux +// +build linux + +package cgroups + +import ( + "bufio" + "io" + "os" + "path/filepath" + "strconv" +) + +// CGroup represents the data structure for a Linux control group. +type CGroup struct { + path string +} + +// NewCGroup returns a new *CGroup from a given path. +func NewCGroup(path string) *CGroup { + return &CGroup{path: path} +} + +// Path returns the path of the CGroup*. +func (cg *CGroup) Path() string { + return cg.path +} + +// ParamPath returns the path of the given cgroup param under itself. +func (cg *CGroup) ParamPath(param string) string { + return filepath.Join(cg.path, param) +} + +// readFirstLine reads the first line from a cgroup param file. +func (cg *CGroup) readFirstLine(param string) (string, error) { + paramFile, err := os.Open(cg.ParamPath(param)) + if err != nil { + return "", err + } + defer paramFile.Close() + + scanner := bufio.NewScanner(paramFile) + if scanner.Scan() { + return scanner.Text(), nil + } + if err := scanner.Err(); err != nil { + return "", err + } + return "", io.ErrUnexpectedEOF +} + +// readInt parses the first line from a cgroup param file as int. +func (cg *CGroup) readInt(param string) (int, error) { + text, err := cg.readFirstLine(param) + if err != nil { + return 0, err + } + return strconv.Atoi(text) +} diff --git a/vendor/go.uber.org/automaxprocs/internal/cgroups/cgroups.go b/vendor/go.uber.org/automaxprocs/internal/cgroups/cgroups.go new file mode 100644 index 000000000..e89f54360 --- /dev/null +++ b/vendor/go.uber.org/automaxprocs/internal/cgroups/cgroups.go @@ -0,0 +1,118 @@ +// Copyright (c) 2017 Uber Technologies, Inc. +// +// 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. + +//go:build linux +// +build linux + +package cgroups + +const ( + // _cgroupFSType is the Linux CGroup file system type used in + // `/proc/$PID/mountinfo`. + _cgroupFSType = "cgroup" + // _cgroupSubsysCPU is the CPU CGroup subsystem. + _cgroupSubsysCPU = "cpu" + // _cgroupSubsysCPUAcct is the CPU accounting CGroup subsystem. + _cgroupSubsysCPUAcct = "cpuacct" + // _cgroupSubsysCPUSet is the CPUSet CGroup subsystem. + _cgroupSubsysCPUSet = "cpuset" + // _cgroupSubsysMemory is the Memory CGroup subsystem. + _cgroupSubsysMemory = "memory" + + // _cgroupCPUCFSQuotaUsParam is the file name for the CGroup CFS quota + // parameter. + _cgroupCPUCFSQuotaUsParam = "cpu.cfs_quota_us" + // _cgroupCPUCFSPeriodUsParam is the file name for the CGroup CFS period + // parameter. + _cgroupCPUCFSPeriodUsParam = "cpu.cfs_period_us" +) + +const ( + _procPathCGroup = "/proc/self/cgroup" + _procPathMountInfo = "/proc/self/mountinfo" +) + +// CGroups is a map that associates each CGroup with its subsystem name. +type CGroups map[string]*CGroup + +// NewCGroups returns a new *CGroups from given `mountinfo` and `cgroup` files +// under for some process under `/proc` file system (see also proc(5) for more +// information). +func NewCGroups(procPathMountInfo, procPathCGroup string) (CGroups, error) { + cgroupSubsystems, err := parseCGroupSubsystems(procPathCGroup) + if err != nil { + return nil, err + } + + cgroups := make(CGroups) + newMountPoint := func(mp *MountPoint) error { + if mp.FSType != _cgroupFSType { + return nil + } + + for _, opt := range mp.SuperOptions { + subsys, exists := cgroupSubsystems[opt] + if !exists { + continue + } + + cgroupPath, err := mp.Translate(subsys.Name) + if err != nil { + return err + } + cgroups[opt] = NewCGroup(cgroupPath) + } + + return nil + } + + if err := parseMountInfo(procPathMountInfo, newMountPoint); err != nil { + return nil, err + } + return cgroups, nil +} + +// NewCGroupsForCurrentProcess returns a new *CGroups instance for the current +// process. +func NewCGroupsForCurrentProcess() (CGroups, error) { + return NewCGroups(_procPathMountInfo, _procPathCGroup) +} + +// CPUQuota returns the CPU quota applied with the CPU cgroup controller. +// It is a result of `cpu.cfs_quota_us / cpu.cfs_period_us`. If the value of +// `cpu.cfs_quota_us` was not set (-1), the method returns `(-1, nil)`. +func (cg CGroups) CPUQuota() (float64, bool, error) { + cpuCGroup, exists := cg[_cgroupSubsysCPU] + if !exists { + return -1, false, nil + } + + cfsQuotaUs, err := cpuCGroup.readInt(_cgroupCPUCFSQuotaUsParam) + if defined := cfsQuotaUs > 0; err != nil || !defined { + return -1, defined, err + } + + cfsPeriodUs, err := cpuCGroup.readInt(_cgroupCPUCFSPeriodUsParam) + if defined := cfsPeriodUs > 0; err != nil || !defined { + return -1, defined, err + } + + return float64(cfsQuotaUs) / float64(cfsPeriodUs), true, nil +} diff --git a/vendor/go.uber.org/automaxprocs/internal/cgroups/cgroups2.go b/vendor/go.uber.org/automaxprocs/internal/cgroups/cgroups2.go new file mode 100644 index 000000000..78556062f --- /dev/null +++ b/vendor/go.uber.org/automaxprocs/internal/cgroups/cgroups2.go @@ -0,0 +1,176 @@ +// Copyright (c) 2022 Uber Technologies, Inc. +// +// 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. + +//go:build linux +// +build linux + +package cgroups + +import ( + "bufio" + "errors" + "fmt" + "io" + "os" + "path" + "strconv" + "strings" +) + +const ( + // _cgroupv2CPUMax is the file name for the CGroup-V2 CPU max and period + // parameter. + _cgroupv2CPUMax = "cpu.max" + // _cgroupFSType is the Linux CGroup-V2 file system type used in + // `/proc/$PID/mountinfo`. + _cgroupv2FSType = "cgroup2" + + _cgroupv2MountPoint = "/sys/fs/cgroup" + + _cgroupV2CPUMaxDefaultPeriod = 100000 + _cgroupV2CPUMaxQuotaMax = "max" +) + +const ( + _cgroupv2CPUMaxQuotaIndex = iota + _cgroupv2CPUMaxPeriodIndex +) + +// ErrNotV2 indicates that the system is not using cgroups2. +var ErrNotV2 = errors.New("not using cgroups2") + +// CGroups2 provides access to cgroups data for systems using cgroups2. +type CGroups2 struct { + mountPoint string + groupPath string + cpuMaxFile string +} + +// NewCGroups2ForCurrentProcess builds a CGroups2 for the current process. +// +// This returns ErrNotV2 if the system is not using cgroups2. +func NewCGroups2ForCurrentProcess() (*CGroups2, error) { + return newCGroups2From(_procPathMountInfo, _procPathCGroup) +} + +func newCGroups2From(mountInfoPath, procPathCGroup string) (*CGroups2, error) { + isV2, err := isCGroupV2(mountInfoPath) + if err != nil { + return nil, err + } + + if !isV2 { + return nil, ErrNotV2 + } + + subsystems, err := parseCGroupSubsystems(procPathCGroup) + if err != nil { + return nil, err + } + + // Find v2 subsystem by looking for the `0` id + var v2subsys *CGroupSubsys + for _, subsys := range subsystems { + if subsys.ID == 0 { + v2subsys = subsys + break + } + } + + if v2subsys == nil { + return nil, ErrNotV2 + } + + return &CGroups2{ + mountPoint: _cgroupv2MountPoint, + groupPath: v2subsys.Name, + cpuMaxFile: _cgroupv2CPUMax, + }, nil +} + +func isCGroupV2(procPathMountInfo string) (bool, error) { + var ( + isV2 bool + newMountPoint = func(mp *MountPoint) error { + isV2 = isV2 || (mp.FSType == _cgroupv2FSType && mp.MountPoint == _cgroupv2MountPoint) + return nil + } + ) + + if err := parseMountInfo(procPathMountInfo, newMountPoint); err != nil { + return false, err + } + + return isV2, nil +} + +// CPUQuota returns the CPU quota applied with the CPU cgroup2 controller. +// It is a result of reading cpu quota and period from cpu.max file. +// It will return `cpu.max / cpu.period`. If cpu.max is set to max, it returns +// (-1, false, nil) +func (cg *CGroups2) CPUQuota() (float64, bool, error) { + cpuMaxParams, err := os.Open(path.Join(cg.mountPoint, cg.groupPath, cg.cpuMaxFile)) + if err != nil { + if os.IsNotExist(err) { + return -1, false, nil + } + return -1, false, err + } + defer cpuMaxParams.Close() + + scanner := bufio.NewScanner(cpuMaxParams) + if scanner.Scan() { + fields := strings.Fields(scanner.Text()) + if len(fields) == 0 || len(fields) > 2 { + return -1, false, fmt.Errorf("invalid format") + } + + if fields[_cgroupv2CPUMaxQuotaIndex] == _cgroupV2CPUMaxQuotaMax { + return -1, false, nil + } + + max, err := strconv.Atoi(fields[_cgroupv2CPUMaxQuotaIndex]) + if err != nil { + return -1, false, err + } + + var period int + if len(fields) == 1 { + period = _cgroupV2CPUMaxDefaultPeriod + } else { + period, err = strconv.Atoi(fields[_cgroupv2CPUMaxPeriodIndex]) + if err != nil { + return -1, false, err + } + + if period == 0 { + return -1, false, errors.New("zero value for period is not allowed") + } + } + + return float64(max) / float64(period), true, nil + } + + if err := scanner.Err(); err != nil { + return -1, false, err + } + + return 0, false, io.ErrUnexpectedEOF +} diff --git a/vendor/go.uber.org/zap/global_prego112.go b/vendor/go.uber.org/automaxprocs/internal/cgroups/doc.go similarity index 84% rename from vendor/go.uber.org/zap/global_prego112.go rename to vendor/go.uber.org/automaxprocs/internal/cgroups/doc.go index d3ab9af93..113555f63 100644 --- a/vendor/go.uber.org/zap/global_prego112.go +++ b/vendor/go.uber.org/automaxprocs/internal/cgroups/doc.go @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Uber Technologies, Inc. +// Copyright (c) 2017 Uber Technologies, Inc. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -18,9 +18,6 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -// See #682 for more information. -// +build !go1.12 - -package zap - -const _stdLogDefaultDepth = 2 +// Package cgroups provides utilities to access Linux control group (CGroups) +// parameters (CPU quota, for example) for a given process. +package cgroups diff --git a/vendor/go.uber.org/automaxprocs/internal/cgroups/errors.go b/vendor/go.uber.org/automaxprocs/internal/cgroups/errors.go new file mode 100644 index 000000000..94ac75a46 --- /dev/null +++ b/vendor/go.uber.org/automaxprocs/internal/cgroups/errors.go @@ -0,0 +1,52 @@ +// Copyright (c) 2017 Uber Technologies, Inc. +// +// 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. + +//go:build linux +// +build linux + +package cgroups + +import "fmt" + +type cgroupSubsysFormatInvalidError struct { + line string +} + +type mountPointFormatInvalidError struct { + line string +} + +type pathNotExposedFromMountPointError struct { + mountPoint string + root string + path string +} + +func (err cgroupSubsysFormatInvalidError) Error() string { + return fmt.Sprintf("invalid format for CGroupSubsys: %q", err.line) +} + +func (err mountPointFormatInvalidError) Error() string { + return fmt.Sprintf("invalid format for MountPoint: %q", err.line) +} + +func (err pathNotExposedFromMountPointError) Error() string { + return fmt.Sprintf("path %q is not a descendant of mount point root %q and cannot be exposed from %q", err.path, err.root, err.mountPoint) +} diff --git a/vendor/go.uber.org/automaxprocs/internal/cgroups/mountpoint.go b/vendor/go.uber.org/automaxprocs/internal/cgroups/mountpoint.go new file mode 100644 index 000000000..f3877f78a --- /dev/null +++ b/vendor/go.uber.org/automaxprocs/internal/cgroups/mountpoint.go @@ -0,0 +1,171 @@ +// Copyright (c) 2017 Uber Technologies, Inc. +// +// 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. + +//go:build linux +// +build linux + +package cgroups + +import ( + "bufio" + "os" + "path/filepath" + "strconv" + "strings" +) + +const ( + _mountInfoSep = " " + _mountInfoOptsSep = "," + _mountInfoOptionalFieldsSep = "-" +) + +const ( + _miFieldIDMountID = iota + _miFieldIDParentID + _miFieldIDDeviceID + _miFieldIDRoot + _miFieldIDMountPoint + _miFieldIDOptions + _miFieldIDOptionalFields + + _miFieldCountFirstHalf +) + +const ( + _miFieldOffsetFSType = iota + _miFieldOffsetMountSource + _miFieldOffsetSuperOptions + + _miFieldCountSecondHalf +) + +const _miFieldCountMin = _miFieldCountFirstHalf + _miFieldCountSecondHalf + +// MountPoint is the data structure for the mount points in +// `/proc/$PID/mountinfo`. See also proc(5) for more information. +type MountPoint struct { + MountID int + ParentID int + DeviceID string + Root string + MountPoint string + Options []string + OptionalFields []string + FSType string + MountSource string + SuperOptions []string +} + +// NewMountPointFromLine parses a line read from `/proc/$PID/mountinfo` and +// returns a new *MountPoint. +func NewMountPointFromLine(line string) (*MountPoint, error) { + fields := strings.Split(line, _mountInfoSep) + + if len(fields) < _miFieldCountMin { + return nil, mountPointFormatInvalidError{line} + } + + mountID, err := strconv.Atoi(fields[_miFieldIDMountID]) + if err != nil { + return nil, err + } + + parentID, err := strconv.Atoi(fields[_miFieldIDParentID]) + if err != nil { + return nil, err + } + + for i, field := range fields[_miFieldIDOptionalFields:] { + if field == _mountInfoOptionalFieldsSep { + // End of optional fields. + fsTypeStart := _miFieldIDOptionalFields + i + 1 + + // Now we know where the optional fields end, split the line again with a + // limit to avoid issues with spaces in super options as present on WSL. + fields = strings.SplitN(line, _mountInfoSep, fsTypeStart+_miFieldCountSecondHalf) + if len(fields) != fsTypeStart+_miFieldCountSecondHalf { + return nil, mountPointFormatInvalidError{line} + } + + miFieldIDFSType := _miFieldOffsetFSType + fsTypeStart + miFieldIDMountSource := _miFieldOffsetMountSource + fsTypeStart + miFieldIDSuperOptions := _miFieldOffsetSuperOptions + fsTypeStart + + return &MountPoint{ + MountID: mountID, + ParentID: parentID, + DeviceID: fields[_miFieldIDDeviceID], + Root: fields[_miFieldIDRoot], + MountPoint: fields[_miFieldIDMountPoint], + Options: strings.Split(fields[_miFieldIDOptions], _mountInfoOptsSep), + OptionalFields: fields[_miFieldIDOptionalFields:(fsTypeStart - 1)], + FSType: fields[miFieldIDFSType], + MountSource: fields[miFieldIDMountSource], + SuperOptions: strings.Split(fields[miFieldIDSuperOptions], _mountInfoOptsSep), + }, nil + } + } + + return nil, mountPointFormatInvalidError{line} +} + +// Translate converts an absolute path inside the *MountPoint's file system to +// the host file system path in the mount namespace the *MountPoint belongs to. +func (mp *MountPoint) Translate(absPath string) (string, error) { + relPath, err := filepath.Rel(mp.Root, absPath) + + if err != nil { + return "", err + } + if relPath == ".." || strings.HasPrefix(relPath, "../") { + return "", pathNotExposedFromMountPointError{ + mountPoint: mp.MountPoint, + root: mp.Root, + path: absPath, + } + } + + return filepath.Join(mp.MountPoint, relPath), nil +} + +// parseMountInfo parses procPathMountInfo (usually at `/proc/$PID/mountinfo`) +// and yields parsed *MountPoint into newMountPoint. +func parseMountInfo(procPathMountInfo string, newMountPoint func(*MountPoint) error) error { + mountInfoFile, err := os.Open(procPathMountInfo) + if err != nil { + return err + } + defer mountInfoFile.Close() + + scanner := bufio.NewScanner(mountInfoFile) + + for scanner.Scan() { + mountPoint, err := NewMountPointFromLine(scanner.Text()) + if err != nil { + return err + } + if err := newMountPoint(mountPoint); err != nil { + return err + } + } + + return scanner.Err() +} diff --git a/vendor/go.uber.org/automaxprocs/internal/cgroups/subsys.go b/vendor/go.uber.org/automaxprocs/internal/cgroups/subsys.go new file mode 100644 index 000000000..cddc3eaec --- /dev/null +++ b/vendor/go.uber.org/automaxprocs/internal/cgroups/subsys.go @@ -0,0 +1,103 @@ +// Copyright (c) 2017 Uber Technologies, Inc. +// +// 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. + +//go:build linux +// +build linux + +package cgroups + +import ( + "bufio" + "os" + "strconv" + "strings" +) + +const ( + _cgroupSep = ":" + _cgroupSubsysSep = "," +) + +const ( + _csFieldIDID = iota + _csFieldIDSubsystems + _csFieldIDName + _csFieldCount +) + +// CGroupSubsys represents the data structure for entities in +// `/proc/$PID/cgroup`. See also proc(5) for more information. +type CGroupSubsys struct { + ID int + Subsystems []string + Name string +} + +// NewCGroupSubsysFromLine returns a new *CGroupSubsys by parsing a string in +// the format of `/proc/$PID/cgroup` +func NewCGroupSubsysFromLine(line string) (*CGroupSubsys, error) { + fields := strings.SplitN(line, _cgroupSep, _csFieldCount) + + if len(fields) != _csFieldCount { + return nil, cgroupSubsysFormatInvalidError{line} + } + + id, err := strconv.Atoi(fields[_csFieldIDID]) + if err != nil { + return nil, err + } + + cgroup := &CGroupSubsys{ + ID: id, + Subsystems: strings.Split(fields[_csFieldIDSubsystems], _cgroupSubsysSep), + Name: fields[_csFieldIDName], + } + + return cgroup, nil +} + +// parseCGroupSubsystems parses procPathCGroup (usually at `/proc/$PID/cgroup`) +// and returns a new map[string]*CGroupSubsys. +func parseCGroupSubsystems(procPathCGroup string) (map[string]*CGroupSubsys, error) { + cgroupFile, err := os.Open(procPathCGroup) + if err != nil { + return nil, err + } + defer cgroupFile.Close() + + scanner := bufio.NewScanner(cgroupFile) + subsystems := make(map[string]*CGroupSubsys) + + for scanner.Scan() { + cgroup, err := NewCGroupSubsysFromLine(scanner.Text()) + if err != nil { + return nil, err + } + for _, subsys := range cgroup.Subsystems { + subsystems[subsys] = cgroup + } + } + + if err := scanner.Err(); err != nil { + return nil, err + } + + return subsystems, nil +} diff --git a/vendor/go.uber.org/automaxprocs/internal/runtime/cpu_quota_linux.go b/vendor/go.uber.org/automaxprocs/internal/runtime/cpu_quota_linux.go new file mode 100644 index 000000000..f9057fd27 --- /dev/null +++ b/vendor/go.uber.org/automaxprocs/internal/runtime/cpu_quota_linux.go @@ -0,0 +1,75 @@ +// Copyright (c) 2017 Uber Technologies, Inc. +// +// 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. + +//go:build linux +// +build linux + +package runtime + +import ( + "errors" + + cg "go.uber.org/automaxprocs/internal/cgroups" +) + +// CPUQuotaToGOMAXPROCS converts the CPU quota applied to the calling process +// to a valid GOMAXPROCS value. The quota is converted from float to int using round. +// If round == nil, DefaultRoundFunc is used. +func CPUQuotaToGOMAXPROCS(minValue int, round func(v float64) int) (int, CPUQuotaStatus, error) { + if round == nil { + round = DefaultRoundFunc + } + cgroups, err := _newQueryer() + if err != nil { + return -1, CPUQuotaUndefined, err + } + + quota, defined, err := cgroups.CPUQuota() + if !defined || err != nil { + return -1, CPUQuotaUndefined, err + } + + maxProcs := round(quota) + if minValue > 0 && maxProcs < minValue { + return minValue, CPUQuotaMinUsed, nil + } + return maxProcs, CPUQuotaUsed, nil +} + +type queryer interface { + CPUQuota() (float64, bool, error) +} + +var ( + _newCgroups2 = cg.NewCGroups2ForCurrentProcess + _newCgroups = cg.NewCGroupsForCurrentProcess + _newQueryer = newQueryer +) + +func newQueryer() (queryer, error) { + cgroups, err := _newCgroups2() + if err == nil { + return cgroups, nil + } + if errors.Is(err, cg.ErrNotV2) { + return _newCgroups() + } + return nil, err +} diff --git a/vendor/go.uber.org/automaxprocs/internal/runtime/cpu_quota_unsupported.go b/vendor/go.uber.org/automaxprocs/internal/runtime/cpu_quota_unsupported.go new file mode 100644 index 000000000..e74701508 --- /dev/null +++ b/vendor/go.uber.org/automaxprocs/internal/runtime/cpu_quota_unsupported.go @@ -0,0 +1,31 @@ +// Copyright (c) 2017 Uber Technologies, Inc. +// +// 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. + +//go:build !linux +// +build !linux + +package runtime + +// CPUQuotaToGOMAXPROCS converts the CPU quota applied to the calling process +// to a valid GOMAXPROCS value. This is Linux-specific and not supported in the +// current OS. +func CPUQuotaToGOMAXPROCS(_ int, _ func(v float64) int) (int, CPUQuotaStatus, error) { + return -1, CPUQuotaUndefined, nil +} diff --git a/vendor/go.uber.org/automaxprocs/internal/runtime/runtime.go b/vendor/go.uber.org/automaxprocs/internal/runtime/runtime.go new file mode 100644 index 000000000..f8a2834ac --- /dev/null +++ b/vendor/go.uber.org/automaxprocs/internal/runtime/runtime.go @@ -0,0 +1,40 @@ +// Copyright (c) 2017 Uber Technologies, Inc. +// +// 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. + +package runtime + +import "math" + +// CPUQuotaStatus presents the status of how CPU quota is used +type CPUQuotaStatus int + +const ( + // CPUQuotaUndefined is returned when CPU quota is undefined + CPUQuotaUndefined CPUQuotaStatus = iota + // CPUQuotaUsed is returned when a valid CPU quota can be used + CPUQuotaUsed + // CPUQuotaMinUsed is returned when CPU quota is smaller than the min value + CPUQuotaMinUsed +) + +// DefaultRoundFunc is the default function to convert CPU quota from float to int. It rounds the value down (floor). +func DefaultRoundFunc(v float64) int { + return int(math.Floor(v)) +} diff --git a/vendor/go.uber.org/automaxprocs/maxprocs/maxprocs.go b/vendor/go.uber.org/automaxprocs/maxprocs/maxprocs.go new file mode 100644 index 000000000..e561fe60b --- /dev/null +++ b/vendor/go.uber.org/automaxprocs/maxprocs/maxprocs.go @@ -0,0 +1,139 @@ +// Copyright (c) 2017 Uber Technologies, Inc. +// +// 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. + +// Package maxprocs lets Go programs easily configure runtime.GOMAXPROCS to +// match the configured Linux CPU quota. Unlike the top-level automaxprocs +// package, it lets the caller configure logging and handle errors. +package maxprocs // import "go.uber.org/automaxprocs/maxprocs" + +import ( + "os" + "runtime" + + iruntime "go.uber.org/automaxprocs/internal/runtime" +) + +const _maxProcsKey = "GOMAXPROCS" + +func currentMaxProcs() int { + return runtime.GOMAXPROCS(0) +} + +type config struct { + printf func(string, ...interface{}) + procs func(int, func(v float64) int) (int, iruntime.CPUQuotaStatus, error) + minGOMAXPROCS int + roundQuotaFunc func(v float64) int +} + +func (c *config) log(fmt string, args ...interface{}) { + if c.printf != nil { + c.printf(fmt, args...) + } +} + +// An Option alters the behavior of Set. +type Option interface { + apply(*config) +} + +// Logger uses the supplied printf implementation for log output. By default, +// Set doesn't log anything. +func Logger(printf func(string, ...interface{})) Option { + return optionFunc(func(cfg *config) { + cfg.printf = printf + }) +} + +// Min sets the minimum GOMAXPROCS value that will be used. +// Any value below 1 is ignored. +func Min(n int) Option { + return optionFunc(func(cfg *config) { + if n >= 1 { + cfg.minGOMAXPROCS = n + } + }) +} + +// RoundQuotaFunc sets the function that will be used to covert the CPU quota from float to int. +func RoundQuotaFunc(rf func(v float64) int) Option { + return optionFunc(func(cfg *config) { + cfg.roundQuotaFunc = rf + }) +} + +type optionFunc func(*config) + +func (of optionFunc) apply(cfg *config) { of(cfg) } + +// Set GOMAXPROCS to match the Linux container CPU quota (if any), returning +// any error encountered and an undo function. +// +// Set is a no-op on non-Linux systems and in Linux environments without a +// configured CPU quota. +func Set(opts ...Option) (func(), error) { + cfg := &config{ + procs: iruntime.CPUQuotaToGOMAXPROCS, + roundQuotaFunc: iruntime.DefaultRoundFunc, + minGOMAXPROCS: 1, + } + for _, o := range opts { + o.apply(cfg) + } + + undoNoop := func() { + cfg.log("maxprocs: No GOMAXPROCS change to reset") + } + + // Honor the GOMAXPROCS environment variable if present. Otherwise, amend + // `runtime.GOMAXPROCS()` with the current process' CPU quota if the OS is + // Linux, and guarantee a minimum value of 1. The minimum guaranteed value + // can be overridden using `maxprocs.Min()`. + if max, exists := os.LookupEnv(_maxProcsKey); exists { + cfg.log("maxprocs: Honoring GOMAXPROCS=%q as set in environment", max) + return undoNoop, nil + } + + maxProcs, status, err := cfg.procs(cfg.minGOMAXPROCS, cfg.roundQuotaFunc) + if err != nil { + return undoNoop, err + } + + if status == iruntime.CPUQuotaUndefined { + cfg.log("maxprocs: Leaving GOMAXPROCS=%v: CPU quota undefined", currentMaxProcs()) + return undoNoop, nil + } + + prev := currentMaxProcs() + undo := func() { + cfg.log("maxprocs: Resetting GOMAXPROCS to %v", prev) + runtime.GOMAXPROCS(prev) + } + + switch status { + case iruntime.CPUQuotaMinUsed: + cfg.log("maxprocs: Updating GOMAXPROCS=%v: using minimum allowed GOMAXPROCS", maxProcs) + case iruntime.CPUQuotaUsed: + cfg.log("maxprocs: Updating GOMAXPROCS=%v: determined from CPU quota", maxProcs) + } + + runtime.GOMAXPROCS(maxProcs) + return undo, nil +} diff --git a/vendor/go.uber.org/zap/global_go112.go b/vendor/go.uber.org/automaxprocs/maxprocs/version.go similarity index 88% rename from vendor/go.uber.org/zap/global_go112.go rename to vendor/go.uber.org/automaxprocs/maxprocs/version.go index 6b5dbda80..cc7fc5aee 100644 --- a/vendor/go.uber.org/zap/global_go112.go +++ b/vendor/go.uber.org/automaxprocs/maxprocs/version.go @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Uber Technologies, Inc. +// Copyright (c) 2017 Uber Technologies, Inc. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -18,9 +18,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -// See #682 for more information. -// +build go1.12 +package maxprocs -package zap - -const _stdLogDefaultDepth = 1 +// Version is the current package version. +const Version = "1.6.0" diff --git a/vendor/go.uber.org/zap/.golangci.yml b/vendor/go.uber.org/zap/.golangci.yml new file mode 100644 index 000000000..fbc6df790 --- /dev/null +++ b/vendor/go.uber.org/zap/.golangci.yml @@ -0,0 +1,77 @@ +output: + # Make output more digestible with quickfix in vim/emacs/etc. + sort-results: true + print-issued-lines: false + +linters: + # We'll track the golangci-lint default linters manually + # instead of letting them change without our control. + disable-all: true + enable: + # golangci-lint defaults: + - errcheck + - gosimple + - govet + - ineffassign + - staticcheck + - unused + + # Our own extras: + - gofmt + - nolintlint # lints nolint directives + - revive + +linters-settings: + govet: + # These govet checks are disabled by default, but they're useful. + enable: + - niliness + - reflectvaluecompare + - sortslice + - unusedwrite + + errcheck: + exclude-functions: + # These methods can not fail. + # They operate on an in-memory buffer. + - (*go.uber.org/zap/buffer.Buffer).Write + - (*go.uber.org/zap/buffer.Buffer).WriteByte + - (*go.uber.org/zap/buffer.Buffer).WriteString + + - (*go.uber.org/zap/zapio.Writer).Close + - (*go.uber.org/zap/zapio.Writer).Sync + - (*go.uber.org/zap/zapio.Writer).Write + # Write to zapio.Writer cannot fail, + # so io.WriteString on it cannot fail. + - io.WriteString(*go.uber.org/zap/zapio.Writer) + + # Writing a plain string to a fmt.State cannot fail. + - io.WriteString(fmt.State) + +issues: + # Print all issues reported by all linters. + max-issues-per-linter: 0 + max-same-issues: 0 + + # Don't ignore some of the issues that golangci-lint considers okay. + # This includes documenting all exported entities. + exclude-use-default: false + + exclude-rules: + # Don't warn on unused parameters. + # Parameter names are useful; replacing them with '_' is undesirable. + - linters: [revive] + text: 'unused-parameter: parameter \S+ seems to be unused, consider removing or renaming it as _' + + # staticcheck already has smarter checks for empty blocks. + # revive's empty-block linter has false positives. + # For example, as of writing this, the following is not allowed. + # for foo() { } + - linters: [revive] + text: 'empty-block: this block is empty, you can remove it' + + # Ignore logger.Sync() errcheck failures in example_test.go + # since those are intended to be uncomplicated examples. + - linters: [errcheck] + path: example_test.go + text: 'Error return value of `logger.Sync` is not checked' diff --git a/vendor/go.uber.org/zap/.readme.tmpl b/vendor/go.uber.org/zap/.readme.tmpl index 3154a1e64..92aa65d66 100644 --- a/vendor/go.uber.org/zap/.readme.tmpl +++ b/vendor/go.uber.org/zap/.readme.tmpl @@ -96,14 +96,14 @@ Released under the [MIT License](LICENSE.txt). 1 In particular, keep in mind that we may be benchmarking against slightly older versions of other packages. Versions are -pinned in zap's [glide.lock][] file. [↩](#anchor-versions) +pinned in the [benchmarks/go.mod][] file. [↩](#anchor-versions) -[doc-img]: https://godoc.org/go.uber.org/zap?status.svg -[doc]: https://godoc.org/go.uber.org/zap -[ci-img]: https://travis-ci.com/uber-go/zap.svg?branch=master -[ci]: https://travis-ci.com/uber-go/zap +[doc-img]: https://pkg.go.dev/badge/go.uber.org/zap +[doc]: https://pkg.go.dev/go.uber.org/zap +[ci-img]: https://github.com/uber-go/zap/actions/workflows/go.yml/badge.svg +[ci]: https://github.com/uber-go/zap/actions/workflows/go.yml [cov-img]: https://codecov.io/gh/uber-go/zap/branch/master/graph/badge.svg [cov]: https://codecov.io/gh/uber-go/zap [benchmarking suite]: https://github.com/uber-go/zap/tree/master/benchmarks -[glide.lock]: https://github.com/uber-go/zap/blob/master/glide.lock +[benchmarks/go.mod]: https://github.com/uber-go/zap/blob/master/benchmarks/go.mod diff --git a/vendor/go.uber.org/zap/CHANGELOG.md b/vendor/go.uber.org/zap/CHANGELOG.md index fdfef8808..11b465976 100644 --- a/vendor/go.uber.org/zap/CHANGELOG.md +++ b/vendor/go.uber.org/zap/CHANGELOG.md @@ -1,4 +1,148 @@ # Changelog +All notable changes to this project will be documented in this file. + +This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## 1.26.0 (14 Sep 2023) +Enhancements: +* [#1319][]: Add `WithLazy` method to `Logger` which lazily evaluates the structured +context. +* [#1350][]: String encoding is much (~50%) faster now. + +Thanks to @jquirke, @cdvr1993 for their contributions to this release. + +[#1319]: https://github.com/uber-go/zap/pull/1319 +[#1350]: https://github.com/uber-go/zap/pull/1350 + +## 1.25.0 (1 Aug 2023) + +This release contains several improvements including performance, API additions, +and two new experimental packages whose APIs are unstable and may change in the +future. + +Enhancements: +* [#1246][]: Add `zap/exp/zapslog` package for integration with slog. +* [#1273][]: Add `Name` to `Logger` which returns the Logger's name if one is set. +* [#1281][]: Add `zap/exp/expfield` package which contains helper methods +`Str` and `Strs` for constructing String-like zap.Fields. +* [#1310][]: Reduce stack size on `Any`. + +Thanks to @knight42, @dzakaammar, @bcspragu, and @rexywork for their contributions +to this release. + +[#1246]: https://github.com/uber-go/zap/pull/1246 +[#1273]: https://github.com/uber-go/zap/pull/1273 +[#1281]: https://github.com/uber-go/zap/pull/1281 +[#1310]: https://github.com/uber-go/zap/pull/1310 + +## 1.24.0 (30 Nov 2022) + +Enhancements: +* [#1148][]: Add `Level` to both `Logger` and `SugaredLogger` that reports the + current minimum enabled log level. +* [#1185][]: `SugaredLogger` turns errors to zap.Error automatically. + +Thanks to @Abirdcfly, @craigpastro, @nnnkkk7, and @sashamelentyev for their +contributions to this release. + +[#1148]: https://github.coml/uber-go/zap/pull/1148 +[#1185]: https://github.coml/uber-go/zap/pull/1185 + +## 1.23.0 (24 Aug 2022) + +Enhancements: +* [#1147][]: Add a `zapcore.LevelOf` function to determine the level of a + `LevelEnabler` or `Core`. +* [#1155][]: Add `zap.Stringers` field constructor to log arrays of objects + that implement `String() string`. + +[#1147]: https://github.com/uber-go/zap/pull/1147 +[#1155]: https://github.com/uber-go/zap/pull/1155 + +## 1.22.0 (8 Aug 2022) + +Enhancements: +* [#1071][]: Add `zap.Objects` and `zap.ObjectValues` field constructors to log + arrays of objects. With these two constructors, you don't need to implement + `zapcore.ArrayMarshaler` for use with `zap.Array` if those objects implement + `zapcore.ObjectMarshaler`. +* [#1079][]: Add `SugaredLogger.WithOptions` to build a copy of an existing + `SugaredLogger` with the provided options applied. +* [#1080][]: Add `*ln` variants to `SugaredLogger` for each log level. + These functions provide a string joining behavior similar to `fmt.Println`. +* [#1088][]: Add `zap.WithFatalHook` option to control the behavior of the + logger for `Fatal`-level log entries. This defaults to exiting the program. +* [#1108][]: Add a `zap.Must` function that you can use with `NewProduction` or + `NewDevelopment` to panic if the system was unable to build the logger. +* [#1118][]: Add a `Logger.Log` method that allows specifying the log level for + a statement dynamically. + +Thanks to @cardil, @craigpastro, @sashamelentyev, @shota3506, and @zhupeijun +for their contributions to this release. + +[#1071]: https://github.com/uber-go/zap/pull/1071 +[#1079]: https://github.com/uber-go/zap/pull/1079 +[#1080]: https://github.com/uber-go/zap/pull/1080 +[#1088]: https://github.com/uber-go/zap/pull/1088 +[#1108]: https://github.com/uber-go/zap/pull/1108 +[#1118]: https://github.com/uber-go/zap/pull/1118 + +## 1.21.0 (7 Feb 2022) + +Enhancements: +* [#1047][]: Add `zapcore.ParseLevel` to parse a `Level` from a string. +* [#1048][]: Add `zap.ParseAtomicLevel` to parse an `AtomicLevel` from a + string. + +Bugfixes: +* [#1058][]: Fix panic in JSON encoder when `EncodeLevel` is unset. + +Other changes: +* [#1052][]: Improve encoding performance when the `AddCaller` and + `AddStacktrace` options are used together. + +[#1047]: https://github.com/uber-go/zap/pull/1047 +[#1048]: https://github.com/uber-go/zap/pull/1048 +[#1052]: https://github.com/uber-go/zap/pull/1052 +[#1058]: https://github.com/uber-go/zap/pull/1058 + +Thanks to @aerosol and @Techassi for their contributions to this release. + +## 1.20.0 (4 Jan 2022) + +Enhancements: +* [#989][]: Add `EncoderConfig.SkipLineEnding` flag to disable adding newline + characters between log statements. +* [#1039][]: Add `EncoderConfig.NewReflectedEncoder` field to customize JSON + encoding of reflected log fields. + +Bugfixes: +* [#1011][]: Fix inaccurate precision when encoding complex64 as JSON. +* [#554][], [#1017][]: Close JSON namespaces opened in `MarshalLogObject` + methods when the methods return. +* [#1033][]: Avoid panicking in Sampler core if `thereafter` is zero. + +Other changes: +* [#1028][]: Drop support for Go < 1.15. + +[#554]: https://github.com/uber-go/zap/pull/554 +[#989]: https://github.com/uber-go/zap/pull/989 +[#1011]: https://github.com/uber-go/zap/pull/1011 +[#1017]: https://github.com/uber-go/zap/pull/1017 +[#1028]: https://github.com/uber-go/zap/pull/1028 +[#1033]: https://github.com/uber-go/zap/pull/1033 +[#1039]: https://github.com/uber-go/zap/pull/1039 + +Thanks to @psrajat, @lruggieri, @sammyrnycreal for their contributions to this release. + +## 1.19.1 (8 Sep 2021) + +Bugfixes: +* [#1001][]: JSON: Fix complex number encoding with negative imaginary part. Thanks to @hemantjadon. +* [#1003][]: JSON: Fix inaccurate precision when encoding float32. + +[#1001]: https://github.com/uber-go/zap/pull/1001 +[#1003]: https://github.com/uber-go/zap/pull/1003 ## 1.19.0 (9 Aug 2021) @@ -63,6 +207,16 @@ Enhancements: Thanks to @ash2k, @FMLS, @jimmystewpot, @Oncilla, @tsoslow, @tylitianrui, @withshubh, and @wziww for their contributions to this release. +[#865]: https://github.com/uber-go/zap/pull/865 +[#867]: https://github.com/uber-go/zap/pull/867 +[#881]: https://github.com/uber-go/zap/pull/881 +[#903]: https://github.com/uber-go/zap/pull/903 +[#912]: https://github.com/uber-go/zap/pull/912 +[#913]: https://github.com/uber-go/zap/pull/913 +[#928]: https://github.com/uber-go/zap/pull/928 +[#931]: https://github.com/uber-go/zap/pull/931 +[#936]: https://github.com/uber-go/zap/pull/936 + ## 1.16.0 (1 Sep 2020) Bugfixes: @@ -84,6 +238,17 @@ Enhancements: Thanks to @SteelPhase, @tmshn, @lixingwang, @wyxloading, @moul, @segevfiner, @andy-retailnext and @jcorbin for their contributions to this release. +[#629]: https://github.com/uber-go/zap/pull/629 +[#697]: https://github.com/uber-go/zap/pull/697 +[#828]: https://github.com/uber-go/zap/pull/828 +[#835]: https://github.com/uber-go/zap/pull/835 +[#843]: https://github.com/uber-go/zap/pull/843 +[#844]: https://github.com/uber-go/zap/pull/844 +[#852]: https://github.com/uber-go/zap/pull/852 +[#854]: https://github.com/uber-go/zap/pull/854 +[#861]: https://github.com/uber-go/zap/pull/861 +[#862]: https://github.com/uber-go/zap/pull/862 + ## 1.15.0 (23 Apr 2020) Bugfixes: @@ -100,6 +265,11 @@ Enhancements: Thanks to @danielbprice for their contributions to this release. +[#804]: https://github.com/uber-go/zap/pull/804 +[#812]: https://github.com/uber-go/zap/pull/812 +[#806]: https://github.com/uber-go/zap/pull/806 +[#813]: https://github.com/uber-go/zap/pull/813 + ## 1.14.1 (14 Mar 2020) Bugfixes: @@ -112,6 +282,10 @@ Bugfixes: Thanks to @YashishDua for their contributions to this release. +[#791]: https://github.com/uber-go/zap/pull/791 +[#795]: https://github.com/uber-go/zap/pull/795 +[#799]: https://github.com/uber-go/zap/pull/799 + ## 1.14.0 (20 Feb 2020) Enhancements: @@ -122,6 +296,11 @@ Enhancements: Thanks to @caibirdme for their contributions to this release. +[#771]: https://github.com/uber-go/zap/pull/771 +[#773]: https://github.com/uber-go/zap/pull/773 +[#775]: https://github.com/uber-go/zap/pull/775 +[#786]: https://github.com/uber-go/zap/pull/786 + ## 1.13.0 (13 Nov 2019) Enhancements: @@ -130,11 +309,15 @@ Enhancements: Thanks to @jbizzle for their contributions to this release. +[#758]: https://github.com/uber-go/zap/pull/758 + ## 1.12.0 (29 Oct 2019) Enhancements: * [#751][]: Migrate to Go modules. +[#751]: https://github.com/uber-go/zap/pull/751 + ## 1.11.0 (21 Oct 2019) Enhancements: @@ -143,6 +326,9 @@ Enhancements: Thanks to @juicemia, @uhthomas for their contributions to this release. +[#725]: https://github.com/uber-go/zap/pull/725 +[#736]: https://github.com/uber-go/zap/pull/736 + ## 1.10.0 (29 Apr 2019) Bugfixes: @@ -160,12 +346,20 @@ Enhancements: Thanks to @iaroslav-ciupin, @lelenanam, @joa, @NWilson for their contributions to this release. +[#657]: https://github.com/uber-go/zap/pull/657 +[#706]: https://github.com/uber-go/zap/pull/706 +[#610]: https://github.com/uber-go/zap/pull/610 +[#675]: https://github.com/uber-go/zap/pull/675 +[#704]: https://github.com/uber-go/zap/pull/704 + ## v1.9.1 (06 Aug 2018) Bugfixes: * [#614][]: MapObjectEncoder should not ignore empty slices. +[#614]: https://github.com/uber-go/zap/pull/614 + ## v1.9.0 (19 Jul 2018) Enhancements: @@ -175,6 +369,10 @@ Enhancements: Thanks to @nfarah86, @AlekSi, @JeanMertz, @philippgille, @etsangsplk, and @dimroc for their contributions to this release. +[#602]: https://github.com/uber-go/zap/pull/602 +[#572]: https://github.com/uber-go/zap/pull/572 +[#606]: https://github.com/uber-go/zap/pull/606 + ## v1.8.0 (13 Apr 2018) Enhancements: @@ -188,11 +386,18 @@ Bugfixes: Thanks to @DiSiqueira and @djui for their contributions to this release. +[#508]: https://github.com/uber-go/zap/pull/508 +[#518]: https://github.com/uber-go/zap/pull/518 +[#577]: https://github.com/uber-go/zap/pull/577 +[#574]: https://github.com/uber-go/zap/pull/574 + ## v1.7.1 (25 Sep 2017) Bugfixes: * [#504][]: Store strings when using AddByteString with the map encoder. +[#504]: https://github.com/uber-go/zap/pull/504 + ## v1.7.0 (21 Sep 2017) Enhancements: @@ -200,6 +405,8 @@ Enhancements: * [#487][]: Add `NewStdLogAt`, which extends `NewStdLog` by allowing the user to specify the level of the logged messages. +[#487]: https://github.com/uber-go/zap/pull/487 + ## v1.6.0 (30 Aug 2017) Enhancements: @@ -208,6 +415,9 @@ Enhancements: * [#490][]: Add a `ContextMap` method to observer logs for simpler field validation in tests. +[#490]: https://github.com/uber-go/zap/pull/490 +[#491]: https://github.com/uber-go/zap/pull/491 + ## v1.5.0 (22 Jul 2017) Enhancements: @@ -221,6 +431,11 @@ Bugfixes: Thanks to @richard-tunein and @pavius for their contributions to this release. +[#477]: https://github.com/uber-go/zap/pull/477 +[#465]: https://github.com/uber-go/zap/pull/465 +[#460]: https://github.com/uber-go/zap/pull/460 +[#470]: https://github.com/uber-go/zap/pull/470 + ## v1.4.1 (08 Jun 2017) This release fixes two bugs. @@ -230,6 +445,9 @@ Bugfixes: * [#435][]: Support a variety of case conventions when unmarshaling levels. * [#444][]: Fix a panic in the observer. +[#435]: https://github.com/uber-go/zap/pull/435 +[#444]: https://github.com/uber-go/zap/pull/444 + ## v1.4.0 (12 May 2017) This release adds a few small features and is fully backward-compatible. @@ -242,6 +460,10 @@ Enhancements: * [#431][]: Make `zap.AtomicLevel` implement `fmt.Stringer`, which makes a variety of operations a bit simpler. +[#424]: https://github.com/uber-go/zap/pull/424 +[#425]: https://github.com/uber-go/zap/pull/425 +[#431]: https://github.com/uber-go/zap/pull/431 + ## v1.3.0 (25 Apr 2017) This release adds an enhancement to zap's testing helpers as well as the @@ -253,6 +475,9 @@ Enhancements: particularly useful when testing the `SugaredLogger`. * [#416][]: Make `AtomicLevel` implement `encoding.TextMarshaler`. +[#415]: https://github.com/uber-go/zap/pull/415 +[#416]: https://github.com/uber-go/zap/pull/416 + ## v1.2.0 (13 Apr 2017) This release adds a gRPC compatibility wrapper. It is fully backward-compatible. @@ -262,6 +487,8 @@ Enhancements: * [#402][]: Add a `zapgrpc` package that wraps zap's Logger and implements `grpclog.Logger`. +[#402]: https://github.com/uber-go/zap/pull/402 + ## v1.1.0 (31 Mar 2017) This release fixes two bugs and adds some enhancements to zap's testing helpers. @@ -279,6 +506,10 @@ Enhancements: Thanks to @moitias for contributing to this release. +[#385]: https://github.com/uber-go/zap/pull/385 +[#396]: https://github.com/uber-go/zap/pull/396 +[#386]: https://github.com/uber-go/zap/pull/386 + ## v1.0.0 (14 Mar 2017) This is zap's first stable release. All exported APIs are now final, and no @@ -324,6 +555,20 @@ Enhancements: Thanks to @suyash, @htrendev, @flisky, @Ulexus, and @skipor for their contributions to this release. +[#366]: https://github.com/uber-go/zap/pull/366 +[#364]: https://github.com/uber-go/zap/pull/364 +[#371]: https://github.com/uber-go/zap/pull/371 +[#362]: https://github.com/uber-go/zap/pull/362 +[#369]: https://github.com/uber-go/zap/pull/369 +[#347]: https://github.com/uber-go/zap/pull/347 +[#373]: https://github.com/uber-go/zap/pull/373 +[#348]: https://github.com/uber-go/zap/pull/348 +[#327]: https://github.com/uber-go/zap/pull/327 +[#376]: https://github.com/uber-go/zap/pull/376 +[#346]: https://github.com/uber-go/zap/pull/346 +[#365]: https://github.com/uber-go/zap/pull/365 +[#372]: https://github.com/uber-go/zap/pull/372 + ## v1.0.0-rc.3 (7 Mar 2017) This is the third release candidate for zap's stable release. There are no @@ -345,6 +590,11 @@ Enhancements: Thanks to @ansel1 and @suyash for their contributions to this release. +[#339]: https://github.com/uber-go/zap/pull/339 +[#307]: https://github.com/uber-go/zap/pull/307 +[#353]: https://github.com/uber-go/zap/pull/353 +[#311]: https://github.com/uber-go/zap/pull/311 + ## v1.0.0-rc.2 (21 Feb 2017) This is the second release candidate for zap's stable release. It includes two @@ -382,6 +632,15 @@ Enhancements: Thanks to @skipor and @chapsuk for their contributions to this release. +[#316]: https://github.com/uber-go/zap/pull/316 +[#309]: https://github.com/uber-go/zap/pull/309 +[#317]: https://github.com/uber-go/zap/pull/317 +[#321]: https://github.com/uber-go/zap/pull/321 +[#325]: https://github.com/uber-go/zap/pull/325 +[#333]: https://github.com/uber-go/zap/pull/333 +[#326]: https://github.com/uber-go/zap/pull/326 +[#300]: https://github.com/uber-go/zap/pull/300 + ## v1.0.0-rc.1 (14 Feb 2017) This is the first release candidate for zap's stable release. There are multiple @@ -410,95 +669,3 @@ backward compatibility concerns and all functionality is new. Early zap adopters should pin to the 0.1.x minor version until they're ready to upgrade to the upcoming stable release. - -[#316]: https://github.com/uber-go/zap/pull/316 -[#309]: https://github.com/uber-go/zap/pull/309 -[#317]: https://github.com/uber-go/zap/pull/317 -[#321]: https://github.com/uber-go/zap/pull/321 -[#325]: https://github.com/uber-go/zap/pull/325 -[#333]: https://github.com/uber-go/zap/pull/333 -[#326]: https://github.com/uber-go/zap/pull/326 -[#300]: https://github.com/uber-go/zap/pull/300 -[#339]: https://github.com/uber-go/zap/pull/339 -[#307]: https://github.com/uber-go/zap/pull/307 -[#353]: https://github.com/uber-go/zap/pull/353 -[#311]: https://github.com/uber-go/zap/pull/311 -[#366]: https://github.com/uber-go/zap/pull/366 -[#364]: https://github.com/uber-go/zap/pull/364 -[#371]: https://github.com/uber-go/zap/pull/371 -[#362]: https://github.com/uber-go/zap/pull/362 -[#369]: https://github.com/uber-go/zap/pull/369 -[#347]: https://github.com/uber-go/zap/pull/347 -[#373]: https://github.com/uber-go/zap/pull/373 -[#348]: https://github.com/uber-go/zap/pull/348 -[#327]: https://github.com/uber-go/zap/pull/327 -[#376]: https://github.com/uber-go/zap/pull/376 -[#346]: https://github.com/uber-go/zap/pull/346 -[#365]: https://github.com/uber-go/zap/pull/365 -[#372]: https://github.com/uber-go/zap/pull/372 -[#385]: https://github.com/uber-go/zap/pull/385 -[#396]: https://github.com/uber-go/zap/pull/396 -[#386]: https://github.com/uber-go/zap/pull/386 -[#402]: https://github.com/uber-go/zap/pull/402 -[#415]: https://github.com/uber-go/zap/pull/415 -[#416]: https://github.com/uber-go/zap/pull/416 -[#424]: https://github.com/uber-go/zap/pull/424 -[#425]: https://github.com/uber-go/zap/pull/425 -[#431]: https://github.com/uber-go/zap/pull/431 -[#435]: https://github.com/uber-go/zap/pull/435 -[#444]: https://github.com/uber-go/zap/pull/444 -[#477]: https://github.com/uber-go/zap/pull/477 -[#465]: https://github.com/uber-go/zap/pull/465 -[#460]: https://github.com/uber-go/zap/pull/460 -[#470]: https://github.com/uber-go/zap/pull/470 -[#487]: https://github.com/uber-go/zap/pull/487 -[#490]: https://github.com/uber-go/zap/pull/490 -[#491]: https://github.com/uber-go/zap/pull/491 -[#504]: https://github.com/uber-go/zap/pull/504 -[#508]: https://github.com/uber-go/zap/pull/508 -[#518]: https://github.com/uber-go/zap/pull/518 -[#577]: https://github.com/uber-go/zap/pull/577 -[#574]: https://github.com/uber-go/zap/pull/574 -[#602]: https://github.com/uber-go/zap/pull/602 -[#572]: https://github.com/uber-go/zap/pull/572 -[#606]: https://github.com/uber-go/zap/pull/606 -[#614]: https://github.com/uber-go/zap/pull/614 -[#657]: https://github.com/uber-go/zap/pull/657 -[#706]: https://github.com/uber-go/zap/pull/706 -[#610]: https://github.com/uber-go/zap/pull/610 -[#675]: https://github.com/uber-go/zap/pull/675 -[#704]: https://github.com/uber-go/zap/pull/704 -[#725]: https://github.com/uber-go/zap/pull/725 -[#736]: https://github.com/uber-go/zap/pull/736 -[#751]: https://github.com/uber-go/zap/pull/751 -[#758]: https://github.com/uber-go/zap/pull/758 -[#771]: https://github.com/uber-go/zap/pull/771 -[#773]: https://github.com/uber-go/zap/pull/773 -[#775]: https://github.com/uber-go/zap/pull/775 -[#786]: https://github.com/uber-go/zap/pull/786 -[#791]: https://github.com/uber-go/zap/pull/791 -[#795]: https://github.com/uber-go/zap/pull/795 -[#799]: https://github.com/uber-go/zap/pull/799 -[#804]: https://github.com/uber-go/zap/pull/804 -[#812]: https://github.com/uber-go/zap/pull/812 -[#806]: https://github.com/uber-go/zap/pull/806 -[#813]: https://github.com/uber-go/zap/pull/813 -[#629]: https://github.com/uber-go/zap/pull/629 -[#697]: https://github.com/uber-go/zap/pull/697 -[#828]: https://github.com/uber-go/zap/pull/828 -[#835]: https://github.com/uber-go/zap/pull/835 -[#843]: https://github.com/uber-go/zap/pull/843 -[#844]: https://github.com/uber-go/zap/pull/844 -[#852]: https://github.com/uber-go/zap/pull/852 -[#854]: https://github.com/uber-go/zap/pull/854 -[#861]: https://github.com/uber-go/zap/pull/861 -[#862]: https://github.com/uber-go/zap/pull/862 -[#865]: https://github.com/uber-go/zap/pull/865 -[#867]: https://github.com/uber-go/zap/pull/867 -[#881]: https://github.com/uber-go/zap/pull/881 -[#903]: https://github.com/uber-go/zap/pull/903 -[#912]: https://github.com/uber-go/zap/pull/912 -[#913]: https://github.com/uber-go/zap/pull/913 -[#928]: https://github.com/uber-go/zap/pull/928 -[#931]: https://github.com/uber-go/zap/pull/931 -[#936]: https://github.com/uber-go/zap/pull/936 diff --git a/vendor/go.uber.org/zap/CONTRIBUTING.md b/vendor/go.uber.org/zap/CONTRIBUTING.md index 5cd965687..ea02f3cae 100644 --- a/vendor/go.uber.org/zap/CONTRIBUTING.md +++ b/vendor/go.uber.org/zap/CONTRIBUTING.md @@ -16,7 +16,7 @@ you to accept the CLA when you open your pull request. [Fork][fork], then clone the repository: -``` +```bash mkdir -p $GOPATH/src/go.uber.org cd $GOPATH/src/go.uber.org git clone git@github.com:your_github_username/zap.git @@ -27,21 +27,16 @@ git fetch upstream Make sure that the tests and the linters pass: -``` +```bash make test make lint ``` -If you're not using the minor version of Go specified in the Makefile's -`LINTABLE_MINOR_VERSIONS` variable, `make lint` doesn't do anything. This is -fine, but it means that you'll only discover lint failures after you open your -pull request. - ## Making Changes Start by creating a new branch for your changes: -``` +```bash cd $GOPATH/src/go.uber.org/zap git checkout master git fetch upstream @@ -52,22 +47,22 @@ git checkout -b cool_new_feature Make your changes, then ensure that `make lint` and `make test` still pass. If you're satisfied with your changes, push them to your fork. -``` +```bash git push origin cool_new_feature ``` Then use the GitHub UI to open a pull request. -At this point, you're waiting on us to review your changes. We *try* to respond +At this point, you're waiting on us to review your changes. We _try_ to respond to issues and pull requests within a few business days, and we may suggest some improvements or alternatives. Once your changes are approved, one of the project maintainers will merge them. We're much more likely to approve your changes if you: -* Add tests for new functionality. -* Write a [good commit message][commit-message]. -* Maintain backward compatibility. +- Add tests for new functionality. +- Write a [good commit message][commit-message]. +- Maintain backward compatibility. [fork]: https://github.com/uber-go/zap/fork [open-issue]: https://github.com/uber-go/zap/issues/new diff --git a/vendor/go.uber.org/zap/Makefile b/vendor/go.uber.org/zap/Makefile index 9b1bc3b0e..eb1cee53b 100644 --- a/vendor/go.uber.org/zap/Makefile +++ b/vendor/go.uber.org/zap/Makefile @@ -1,50 +1,51 @@ -export GOBIN ?= $(shell pwd)/bin +# Directory containing the Makefile. +PROJECT_ROOT = $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) -GOLINT = $(GOBIN)/golint -STATICCHECK = $(GOBIN)/staticcheck +export GOBIN ?= $(PROJECT_ROOT)/bin +export PATH := $(GOBIN):$(PATH) + +GOVULNCHECK = $(GOBIN)/govulncheck BENCH_FLAGS ?= -cpuprofile=cpu.pprof -memprofile=mem.pprof -benchmem # Directories containing independent Go modules. -# -# We track coverage only for the main module. -MODULE_DIRS = . ./benchmarks ./zapgrpc/internal/test +MODULE_DIRS = . ./exp ./benchmarks ./zapgrpc/internal/test -# Many Go tools take file globs or directories as arguments instead of packages. -GO_FILES := $(shell \ - find . '(' -path '*/.*' -o -path './vendor' ')' -prune \ - -o -name '*.go' -print | cut -b3-) +# Directories that we want to track coverage for. +COVER_DIRS = . ./exp .PHONY: all all: lint test .PHONY: lint -lint: $(GOLINT) $(STATICCHECK) - @rm -rf lint.log - @echo "Checking formatting..." - @gofmt -d -s $(GO_FILES) 2>&1 | tee lint.log - @echo "Checking vet..." - @$(foreach dir,$(MODULE_DIRS),(cd $(dir) && go vet ./... 2>&1) &&) true | tee -a lint.log - @echo "Checking lint..." - @$(foreach dir,$(MODULE_DIRS),(cd $(dir) && $(GOLINT) ./... 2>&1) &&) true | tee -a lint.log - @echo "Checking staticcheck..." - @$(foreach dir,$(MODULE_DIRS),(cd $(dir) && $(STATICCHECK) ./... 2>&1) &&) true | tee -a lint.log - @echo "Checking for unresolved FIXMEs..." - @git grep -i fixme | grep -v -e Makefile | tee -a lint.log - @echo "Checking for license headers..." - @./checklicense.sh | tee -a lint.log - @[ ! -s lint.log ] - @echo "Checking 'go mod tidy'..." - @make tidy - @if ! git diff --quiet; then \ - echo "'go mod tidy' resulted in changes or working tree is dirty:"; \ - git --no-pager diff; \ - fi - -$(GOLINT): - cd tools && go install golang.org/x/lint/golint - -$(STATICCHECK): - cd tools && go install honnef.co/go/tools/cmd/staticcheck +lint: golangci-lint tidy-lint license-lint + +.PHONY: golangci-lint +golangci-lint: + @$(foreach mod,$(MODULE_DIRS), \ + (cd $(mod) && \ + echo "[lint] golangci-lint: $(mod)" && \ + golangci-lint run --path-prefix $(mod)) &&) true + +.PHONY: tidy +tidy: + @$(foreach dir,$(MODULE_DIRS), \ + (cd $(dir) && go mod tidy) &&) true + +.PHONY: tidy-lint +tidy-lint: + @$(foreach mod,$(MODULE_DIRS), \ + (cd $(mod) && \ + echo "[lint] tidy: $(mod)" && \ + go mod tidy && \ + git diff --exit-code -- go.mod go.sum) &&) true + + +.PHONY: license-lint +license-lint: + ./checklicense.sh + +$(GOVULNCHECK): + cd tools && go install golang.org/x/vuln/cmd/govulncheck .PHONY: test test: @@ -52,8 +53,10 @@ test: .PHONY: cover cover: - go test -race -coverprofile=cover.out -coverpkg=./... ./... - go tool cover -html=cover.out -o cover.html + @$(foreach dir,$(COVER_DIRS), ( \ + cd $(dir) && \ + go test -race -coverprofile=cover.out -coverpkg=./... ./... \ + && go tool cover -html=cover.out -o cover.html) &&) true .PHONY: bench BENCH ?= . @@ -68,6 +71,6 @@ updatereadme: rm -f README.md cat .readme.tmpl | go run internal/readme/readme.go > README.md -.PHONY: tidy -tidy: - @$(foreach dir,$(MODULE_DIRS),(cd $(dir) && go mod tidy) &&) true +.PHONY: vulncheck +vulncheck: $(GOVULNCHECK) + $(GOVULNCHECK) ./... diff --git a/vendor/go.uber.org/zap/README.md b/vendor/go.uber.org/zap/README.md index 1e64d6cff..9de08927b 100644 --- a/vendor/go.uber.org/zap/README.md +++ b/vendor/go.uber.org/zap/README.md @@ -66,38 +66,41 @@ Log a message and 10 fields: | Package | Time | Time % to zap | Objects Allocated | | :------ | :--: | :-----------: | :---------------: | -| :zap: zap | 862 ns/op | +0% | 5 allocs/op -| :zap: zap (sugared) | 1250 ns/op | +45% | 11 allocs/op -| zerolog | 4021 ns/op | +366% | 76 allocs/op -| go-kit | 4542 ns/op | +427% | 105 allocs/op -| apex/log | 26785 ns/op | +3007% | 115 allocs/op -| logrus | 29501 ns/op | +3322% | 125 allocs/op -| log15 | 29906 ns/op | +3369% | 122 allocs/op +| :zap: zap | 1744 ns/op | +0% | 5 allocs/op +| :zap: zap (sugared) | 2483 ns/op | +42% | 10 allocs/op +| zerolog | 918 ns/op | -47% | 1 allocs/op +| go-kit | 5590 ns/op | +221% | 57 allocs/op +| slog | 5640 ns/op | +223% | 40 allocs/op +| apex/log | 21184 ns/op | +1115% | 63 allocs/op +| logrus | 24338 ns/op | +1296% | 79 allocs/op +| log15 | 26054 ns/op | +1394% | 74 allocs/op Log a message with a logger that already has 10 fields of context: | Package | Time | Time % to zap | Objects Allocated | | :------ | :--: | :-----------: | :---------------: | -| :zap: zap | 126 ns/op | +0% | 0 allocs/op -| :zap: zap (sugared) | 187 ns/op | +48% | 2 allocs/op -| zerolog | 88 ns/op | -30% | 0 allocs/op -| go-kit | 5087 ns/op | +3937% | 103 allocs/op -| log15 | 18548 ns/op | +14621% | 73 allocs/op -| apex/log | 26012 ns/op | +20544% | 104 allocs/op -| logrus | 27236 ns/op | +21516% | 113 allocs/op +| :zap: zap | 193 ns/op | +0% | 0 allocs/op +| :zap: zap (sugared) | 227 ns/op | +18% | 1 allocs/op +| zerolog | 81 ns/op | -58% | 0 allocs/op +| slog | 322 ns/op | +67% | 0 allocs/op +| go-kit | 5377 ns/op | +2686% | 56 allocs/op +| apex/log | 19518 ns/op | +10013% | 53 allocs/op +| log15 | 19812 ns/op | +10165% | 70 allocs/op +| logrus | 21997 ns/op | +11297% | 68 allocs/op Log a static string, without any context or `printf`-style templating: | Package | Time | Time % to zap | Objects Allocated | | :------ | :--: | :-----------: | :---------------: | -| :zap: zap | 118 ns/op | +0% | 0 allocs/op -| :zap: zap (sugared) | 191 ns/op | +62% | 2 allocs/op -| zerolog | 93 ns/op | -21% | 0 allocs/op -| go-kit | 280 ns/op | +137% | 11 allocs/op -| standard library | 499 ns/op | +323% | 2 allocs/op -| apex/log | 1990 ns/op | +1586% | 10 allocs/op -| logrus | 3129 ns/op | +2552% | 24 allocs/op -| log15 | 3887 ns/op | +3194% | 23 allocs/op +| :zap: zap | 165 ns/op | +0% | 0 allocs/op +| :zap: zap (sugared) | 212 ns/op | +28% | 1 allocs/op +| zerolog | 95 ns/op | -42% | 0 allocs/op +| slog | 296 ns/op | +79% | 0 allocs/op +| go-kit | 415 ns/op | +152% | 9 allocs/op +| standard library | 422 ns/op | +156% | 2 allocs/op +| apex/log | 1601 ns/op | +870% | 5 allocs/op +| logrus | 3017 ns/op | +1728% | 23 allocs/op +| log15 | 3469 ns/op | +2002% | 20 allocs/op ## Development Status: Stable diff --git a/vendor/go.uber.org/zap/array.go b/vendor/go.uber.org/zap/array.go index 5be3704a3..abfccb566 100644 --- a/vendor/go.uber.org/zap/array.go +++ b/vendor/go.uber.org/zap/array.go @@ -21,6 +21,7 @@ package zap import ( + "fmt" "time" "go.uber.org/zap/zapcore" @@ -94,11 +95,137 @@ func Int8s(key string, nums []int8) Field { return Array(key, int8s(nums)) } +// Objects constructs a field with the given key, holding a list of the +// provided objects that can be marshaled by Zap. +// +// Note that these objects must implement zapcore.ObjectMarshaler directly. +// That is, if you're trying to marshal a []Request, the MarshalLogObject +// method must be declared on the Request type, not its pointer (*Request). +// If it's on the pointer, use ObjectValues. +// +// Given an object that implements MarshalLogObject on the value receiver, you +// can log a slice of those objects with Objects like so: +// +// type Author struct{ ... } +// func (a Author) MarshalLogObject(enc zapcore.ObjectEncoder) error +// +// var authors []Author = ... +// logger.Info("loading article", zap.Objects("authors", authors)) +// +// Similarly, given a type that implements MarshalLogObject on its pointer +// receiver, you can log a slice of pointers to that object with Objects like +// so: +// +// type Request struct{ ... } +// func (r *Request) MarshalLogObject(enc zapcore.ObjectEncoder) error +// +// var requests []*Request = ... +// logger.Info("sending requests", zap.Objects("requests", requests)) +// +// If instead, you have a slice of values of such an object, use the +// ObjectValues constructor. +// +// var requests []Request = ... +// logger.Info("sending requests", zap.ObjectValues("requests", requests)) +func Objects[T zapcore.ObjectMarshaler](key string, values []T) Field { + return Array(key, objects[T](values)) +} + +type objects[T zapcore.ObjectMarshaler] []T + +func (os objects[T]) MarshalLogArray(arr zapcore.ArrayEncoder) error { + for _, o := range os { + if err := arr.AppendObject(o); err != nil { + return err + } + } + return nil +} + +// ObjectMarshalerPtr is a constraint that specifies that the given type +// implements zapcore.ObjectMarshaler on a pointer receiver. +type ObjectMarshalerPtr[T any] interface { + *T + zapcore.ObjectMarshaler +} + +// ObjectValues constructs a field with the given key, holding a list of the +// provided objects, where pointers to these objects can be marshaled by Zap. +// +// Note that pointers to these objects must implement zapcore.ObjectMarshaler. +// That is, if you're trying to marshal a []Request, the MarshalLogObject +// method must be declared on the *Request type, not the value (Request). +// If it's on the value, use Objects. +// +// Given an object that implements MarshalLogObject on the pointer receiver, +// you can log a slice of those objects with ObjectValues like so: +// +// type Request struct{ ... } +// func (r *Request) MarshalLogObject(enc zapcore.ObjectEncoder) error +// +// var requests []Request = ... +// logger.Info("sending requests", zap.ObjectValues("requests", requests)) +// +// If instead, you have a slice of pointers of such an object, use the Objects +// field constructor. +// +// var requests []*Request = ... +// logger.Info("sending requests", zap.Objects("requests", requests)) +func ObjectValues[T any, P ObjectMarshalerPtr[T]](key string, values []T) Field { + return Array(key, objectValues[T, P](values)) +} + +type objectValues[T any, P ObjectMarshalerPtr[T]] []T + +func (os objectValues[T, P]) MarshalLogArray(arr zapcore.ArrayEncoder) error { + for i := range os { + // It is necessary for us to explicitly reference the "P" type. + // We cannot simply pass "&os[i]" to AppendObject because its type + // is "*T", which the type system does not consider as + // implementing ObjectMarshaler. + // Only the type "P" satisfies ObjectMarshaler, which we have + // to convert "*T" to explicitly. + var p P = &os[i] + if err := arr.AppendObject(p); err != nil { + return err + } + } + return nil +} + // Strings constructs a field that carries a slice of strings. func Strings(key string, ss []string) Field { return Array(key, stringArray(ss)) } +// Stringers constructs a field with the given key, holding a list of the +// output provided by the value's String method +// +// Given an object that implements String on the value receiver, you +// can log a slice of those objects with Objects like so: +// +// type Request struct{ ... } +// func (a Request) String() string +// +// var requests []Request = ... +// logger.Info("sending requests", zap.Stringers("requests", requests)) +// +// Note that these objects must implement fmt.Stringer directly. +// That is, if you're trying to marshal a []Request, the String method +// must be declared on the Request type, not its pointer (*Request). +func Stringers[T fmt.Stringer](key string, values []T) Field { + return Array(key, stringers[T](values)) +} + +type stringers[T fmt.Stringer] []T + +func (os stringers[T]) MarshalLogArray(arr zapcore.ArrayEncoder) error { + for _, o := range os { + arr.AppendString(o.String()) + } + return nil +} + // Times constructs a field that carries a slice of time.Times. func Times(key string, ts []time.Time) Field { return Array(key, times(ts)) diff --git a/vendor/go.uber.org/zap/buffer/buffer.go b/vendor/go.uber.org/zap/buffer/buffer.go index 9e929cd98..27fb5cd5d 100644 --- a/vendor/go.uber.org/zap/buffer/buffer.go +++ b/vendor/go.uber.org/zap/buffer/buffer.go @@ -42,6 +42,11 @@ func (b *Buffer) AppendByte(v byte) { b.bs = append(b.bs, v) } +// AppendBytes writes a single byte to the Buffer. +func (b *Buffer) AppendBytes(v []byte) { + b.bs = append(b.bs, v...) +} + // AppendString writes a string to the Buffer. func (b *Buffer) AppendString(s string) { b.bs = append(b.bs, s...) diff --git a/vendor/go.uber.org/zap/buffer/pool.go b/vendor/go.uber.org/zap/buffer/pool.go index 8fb3e202c..846323360 100644 --- a/vendor/go.uber.org/zap/buffer/pool.go +++ b/vendor/go.uber.org/zap/buffer/pool.go @@ -20,25 +20,29 @@ package buffer -import "sync" +import ( + "go.uber.org/zap/internal/pool" +) // A Pool is a type-safe wrapper around a sync.Pool. type Pool struct { - p *sync.Pool + p *pool.Pool[*Buffer] } // NewPool constructs a new Pool. func NewPool() Pool { - return Pool{p: &sync.Pool{ - New: func() interface{} { - return &Buffer{bs: make([]byte, 0, _size)} - }, - }} + return Pool{ + p: pool.New(func() *Buffer { + return &Buffer{ + bs: make([]byte, 0, _size), + } + }), + } } // Get retrieves a Buffer from the pool, creating one if necessary. func (p Pool) Get() *Buffer { - buf := p.p.Get().(*Buffer) + buf := p.p.Get() buf.Reset() buf.pool = p return buf diff --git a/vendor/go.uber.org/zap/config.go b/vendor/go.uber.org/zap/config.go index 55637fb0b..e76e4e64f 100644 --- a/vendor/go.uber.org/zap/config.go +++ b/vendor/go.uber.org/zap/config.go @@ -21,7 +21,7 @@ package zap import ( - "fmt" + "errors" "sort" "time" @@ -95,6 +95,32 @@ type Config struct { // NewProductionEncoderConfig returns an opinionated EncoderConfig for // production environments. +// +// Messages encoded with this configuration will be JSON-formatted +// and will have the following keys by default: +// +// - "level": The logging level (e.g. "info", "error"). +// - "ts": The current time in number of seconds since the Unix epoch. +// - "msg": The message passed to the log statement. +// - "caller": If available, a short path to the file and line number +// where the log statement was issued. +// The logger configuration determines whether this field is captured. +// - "stacktrace": If available, a stack trace from the line +// where the log statement was issued. +// The logger configuration determines whether this field is captured. +// +// By default, the following formats are used for different types: +// +// - Time is formatted as floating-point number of seconds since the Unix +// epoch. +// - Duration is formatted as floating-point number of seconds. +// +// You may change these by setting the appropriate fields in the returned +// object. +// For example, use the following to change the time encoding format: +// +// cfg := zap.NewProductionEncoderConfig() +// cfg.EncodeTime = zapcore.ISO8601TimeEncoder func NewProductionEncoderConfig() zapcore.EncoderConfig { return zapcore.EncoderConfig{ TimeKey: "ts", @@ -112,11 +138,22 @@ func NewProductionEncoderConfig() zapcore.EncoderConfig { } } -// NewProductionConfig is a reasonable production logging configuration. -// Logging is enabled at InfoLevel and above. +// NewProductionConfig builds a reasonable default production logging +// configuration. +// Logging is enabled at InfoLevel and above, and uses a JSON encoder. +// Logs are written to standard error. +// Stacktraces are included on logs of ErrorLevel and above. +// DPanicLevel logs will not panic, but will write a stacktrace. +// +// Sampling is enabled at 100:100 by default, +// meaning that after the first 100 log entries +// with the same level and message in the same second, +// it will log every 100th entry +// with the same level and message in the same second. +// You may disable this behavior by setting Sampling to nil. // -// It uses a JSON encoder, writes to standard error, and enables sampling. -// Stacktraces are automatically included on logs of ErrorLevel and above. +// See [NewProductionEncoderConfig] for information +// on the default encoder configuration. func NewProductionConfig() Config { return Config{ Level: NewAtomicLevelAt(InfoLevel), @@ -134,6 +171,32 @@ func NewProductionConfig() Config { // NewDevelopmentEncoderConfig returns an opinionated EncoderConfig for // development environments. +// +// Messages encoded with this configuration will use Zap's console encoder +// intended to print human-readable output. +// It will print log messages with the following information: +// +// - The log level (e.g. "INFO", "ERROR"). +// - The time in ISO8601 format (e.g. "2017-01-01T12:00:00Z"). +// - The message passed to the log statement. +// - If available, a short path to the file and line number +// where the log statement was issued. +// The logger configuration determines whether this field is captured. +// - If available, a stacktrace from the line +// where the log statement was issued. +// The logger configuration determines whether this field is captured. +// +// By default, the following formats are used for different types: +// +// - Time is formatted in ISO8601 format (e.g. "2017-01-01T12:00:00Z"). +// - Duration is formatted as a string (e.g. "1.234s"). +// +// You may change these by setting the appropriate fields in the returned +// object. +// For example, use the following to change the time encoding format: +// +// cfg := zap.NewDevelopmentEncoderConfig() +// cfg.EncodeTime = zapcore.ISO8601TimeEncoder func NewDevelopmentEncoderConfig() zapcore.EncoderConfig { return zapcore.EncoderConfig{ // Keys can be anything except the empty string. @@ -152,12 +215,15 @@ func NewDevelopmentEncoderConfig() zapcore.EncoderConfig { } } -// NewDevelopmentConfig is a reasonable development logging configuration. -// Logging is enabled at DebugLevel and above. +// NewDevelopmentConfig builds a reasonable default development logging +// configuration. +// Logging is enabled at DebugLevel and above, and uses a console encoder. +// Logs are written to standard error. +// Stacktraces are included on logs of WarnLevel and above. +// DPanicLevel logs will panic. // -// It enables development mode (which makes DPanicLevel logs panic), uses a -// console encoder, writes to standard error, and disables sampling. -// Stacktraces are automatically included on logs of WarnLevel and above. +// See [NewDevelopmentEncoderConfig] for information +// on the default encoder configuration. func NewDevelopmentConfig() Config { return Config{ Level: NewAtomicLevelAt(DebugLevel), @@ -182,7 +248,7 @@ func (cfg Config) Build(opts ...Option) (*Logger, error) { } if cfg.Level == (AtomicLevel{}) { - return nil, fmt.Errorf("missing Level") + return nil, errors.New("missing Level") } log := New( diff --git a/vendor/go.uber.org/zap/doc.go b/vendor/go.uber.org/zap/doc.go index 8638dd1b9..3c50d7b4d 100644 --- a/vendor/go.uber.org/zap/doc.go +++ b/vendor/go.uber.org/zap/doc.go @@ -32,7 +32,7 @@ // they need to count every allocation and when they'd prefer a more familiar, // loosely typed API. // -// Choosing a Logger +// # Choosing a Logger // // In contexts where performance is nice, but not critical, use the // SugaredLogger. It's 4-10x faster than other structured logging packages and @@ -41,14 +41,15 @@ // variadic number of key-value pairs. (For more advanced use cases, they also // accept strongly typed fields - see the SugaredLogger.With documentation for // details.) -// sugar := zap.NewExample().Sugar() -// defer sugar.Sync() -// sugar.Infow("failed to fetch URL", -// "url", "http://example.com", -// "attempt", 3, -// "backoff", time.Second, -// ) -// sugar.Infof("failed to fetch URL: %s", "http://example.com") +// +// sugar := zap.NewExample().Sugar() +// defer sugar.Sync() +// sugar.Infow("failed to fetch URL", +// "url", "http://example.com", +// "attempt", 3, +// "backoff", time.Second, +// ) +// sugar.Infof("failed to fetch URL: %s", "http://example.com") // // By default, loggers are unbuffered. However, since zap's low-level APIs // allow buffering, calling Sync before letting your process exit is a good @@ -57,32 +58,35 @@ // In the rare contexts where every microsecond and every allocation matter, // use the Logger. It's even faster than the SugaredLogger and allocates far // less, but it only supports strongly-typed, structured logging. -// logger := zap.NewExample() -// defer logger.Sync() -// logger.Info("failed to fetch URL", -// zap.String("url", "http://example.com"), -// zap.Int("attempt", 3), -// zap.Duration("backoff", time.Second), -// ) +// +// logger := zap.NewExample() +// defer logger.Sync() +// logger.Info("failed to fetch URL", +// zap.String("url", "http://example.com"), +// zap.Int("attempt", 3), +// zap.Duration("backoff", time.Second), +// ) // // Choosing between the Logger and SugaredLogger doesn't need to be an // application-wide decision: converting between the two is simple and // inexpensive. -// logger := zap.NewExample() -// defer logger.Sync() -// sugar := logger.Sugar() -// plain := sugar.Desugar() // -// Configuring Zap +// logger := zap.NewExample() +// defer logger.Sync() +// sugar := logger.Sugar() +// plain := sugar.Desugar() +// +// # Configuring Zap // // The simplest way to build a Logger is to use zap's opinionated presets: // NewExample, NewProduction, and NewDevelopment. These presets build a logger // with a single function call: -// logger, err := zap.NewProduction() -// if err != nil { -// log.Fatalf("can't initialize zap logger: %v", err) -// } -// defer logger.Sync() +// +// logger, err := zap.NewProduction() +// if err != nil { +// log.Fatalf("can't initialize zap logger: %v", err) +// } +// defer logger.Sync() // // Presets are fine for small projects, but larger projects and organizations // naturally require a bit more customization. For most users, zap's Config @@ -94,7 +98,7 @@ // go.uber.org/zap/zapcore. See the package-level AdvancedConfiguration // example for sample code. // -// Extending Zap +// # Extending Zap // // The zap package itself is a relatively thin wrapper around the interfaces // in go.uber.org/zap/zapcore. Extending zap to support a new encoding (e.g., @@ -106,7 +110,7 @@ // Similarly, package authors can use the high-performance Encoder and Core // implementations in the zapcore package to build their own loggers. // -// Frequently Asked Questions +// # Frequently Asked Questions // // An FAQ covering everything from installation errors to design decisions is // available at https://github.com/uber-go/zap/blob/master/FAQ.md. diff --git a/vendor/go.uber.org/zap/encoder.go b/vendor/go.uber.org/zap/encoder.go index 08ed83354..caa04ceef 100644 --- a/vendor/go.uber.org/zap/encoder.go +++ b/vendor/go.uber.org/zap/encoder.go @@ -63,7 +63,7 @@ func RegisterEncoder(name string, constructor func(zapcore.EncoderConfig) (zapco func newEncoder(name string, encoderConfig zapcore.EncoderConfig) (zapcore.Encoder, error) { if encoderConfig.TimeKey != "" && encoderConfig.EncodeTime == nil { - return nil, fmt.Errorf("missing EncodeTime in EncoderConfig") + return nil, errors.New("missing EncodeTime in EncoderConfig") } _encoderMutex.RLock() diff --git a/vendor/go.uber.org/zap/error.go b/vendor/go.uber.org/zap/error.go index 65982a51e..45f7b838d 100644 --- a/vendor/go.uber.org/zap/error.go +++ b/vendor/go.uber.org/zap/error.go @@ -21,14 +21,13 @@ package zap import ( - "sync" - + "go.uber.org/zap/internal/pool" "go.uber.org/zap/zapcore" ) -var _errArrayElemPool = sync.Pool{New: func() interface{} { +var _errArrayElemPool = pool.New(func() *errArrayElem { return &errArrayElem{} -}} +}) // Error is shorthand for the common idiom NamedError("error", err). func Error(err error) Field { @@ -60,11 +59,14 @@ func (errs errArray) MarshalLogArray(arr zapcore.ArrayEncoder) error { // potentially an "errorVerbose" attribute, we need to wrap it in a // type that implements LogObjectMarshaler. To prevent this from // allocating, pool the wrapper type. - elem := _errArrayElemPool.Get().(*errArrayElem) + elem := _errArrayElemPool.Get() elem.error = errs[i] - arr.AppendObject(elem) + err := arr.AppendObject(elem) elem.error = nil _errArrayElemPool.Put(elem) + if err != nil { + return err + } } return nil } diff --git a/vendor/go.uber.org/zap/field.go b/vendor/go.uber.org/zap/field.go index bbb745db5..c8dd3358a 100644 --- a/vendor/go.uber.org/zap/field.go +++ b/vendor/go.uber.org/zap/field.go @@ -25,6 +25,7 @@ import ( "math" "time" + "go.uber.org/zap/internal/stacktrace" "go.uber.org/zap/zapcore" ) @@ -374,7 +375,7 @@ func StackSkip(key string, skip int) Field { // from expanding the zapcore.Field union struct to include a byte slice. Since // taking a stacktrace is already so expensive (~10us), the extra allocation // is okay. - return String(key, takeStacktrace(skip+1)) // skip StackSkip + return String(key, stacktrace.Take(skip+1)) // skip StackSkip } // Duration constructs a field with the given key and value. The encoder @@ -410,6 +411,63 @@ func Inline(val zapcore.ObjectMarshaler) Field { } } +// Dict constructs a field containing the provided key-value pairs. +// It acts similar to [Object], but with the fields specified as arguments. +func Dict(key string, val ...Field) Field { + return dictField(key, val) +} + +// We need a function with the signature (string, T) for zap.Any. +func dictField(key string, val []Field) Field { + return Object(key, dictObject(val)) +} + +type dictObject []Field + +func (d dictObject) MarshalLogObject(enc zapcore.ObjectEncoder) error { + for _, f := range d { + f.AddTo(enc) + } + return nil +} + +// We discovered an issue where zap.Any can cause a performance degradation +// when used in new goroutines. +// +// This happens because the compiler assigns 4.8kb (one zap.Field per arm of +// switch statement) of stack space for zap.Any when it takes the form: +// +// switch v := v.(type) { +// case string: +// return String(key, v) +// case int: +// return Int(key, v) +// // ... +// default: +// return Reflect(key, v) +// } +// +// To avoid this, we use the type switch to assign a value to a single local variable +// and then call a function on it. +// The local variable is just a function reference so it doesn't allocate +// when converted to an interface{}. +// +// A fair bit of experimentation went into this. +// See also: +// +// - https://github.com/uber-go/zap/pull/1301 +// - https://github.com/uber-go/zap/pull/1303 +// - https://github.com/uber-go/zap/pull/1304 +// - https://github.com/uber-go/zap/pull/1305 +// - https://github.com/uber-go/zap/pull/1308 +type anyFieldC[T any] func(string, T) Field + +func (f anyFieldC[T]) Any(key string, val any) Field { + v, _ := val.(T) + // val is guaranteed to be a T, except when it's nil. + return f(key, v) +} + // Any takes a key and an arbitrary value and chooses the best way to represent // them as a field, falling back to a reflection-based approach only if // necessary. @@ -418,132 +476,138 @@ func Inline(val zapcore.ObjectMarshaler) Field { // them. To minimize surprises, []byte values are treated as binary blobs, byte // values are treated as uint8, and runes are always treated as integers. func Any(key string, value interface{}) Field { - switch val := value.(type) { + var c interface{ Any(string, any) Field } + + switch value.(type) { case zapcore.ObjectMarshaler: - return Object(key, val) + c = anyFieldC[zapcore.ObjectMarshaler](Object) case zapcore.ArrayMarshaler: - return Array(key, val) + c = anyFieldC[zapcore.ArrayMarshaler](Array) + case []Field: + c = anyFieldC[[]Field](dictField) case bool: - return Bool(key, val) + c = anyFieldC[bool](Bool) case *bool: - return Boolp(key, val) + c = anyFieldC[*bool](Boolp) case []bool: - return Bools(key, val) + c = anyFieldC[[]bool](Bools) case complex128: - return Complex128(key, val) + c = anyFieldC[complex128](Complex128) case *complex128: - return Complex128p(key, val) + c = anyFieldC[*complex128](Complex128p) case []complex128: - return Complex128s(key, val) + c = anyFieldC[[]complex128](Complex128s) case complex64: - return Complex64(key, val) + c = anyFieldC[complex64](Complex64) case *complex64: - return Complex64p(key, val) + c = anyFieldC[*complex64](Complex64p) case []complex64: - return Complex64s(key, val) + c = anyFieldC[[]complex64](Complex64s) case float64: - return Float64(key, val) + c = anyFieldC[float64](Float64) case *float64: - return Float64p(key, val) + c = anyFieldC[*float64](Float64p) case []float64: - return Float64s(key, val) + c = anyFieldC[[]float64](Float64s) case float32: - return Float32(key, val) + c = anyFieldC[float32](Float32) case *float32: - return Float32p(key, val) + c = anyFieldC[*float32](Float32p) case []float32: - return Float32s(key, val) + c = anyFieldC[[]float32](Float32s) case int: - return Int(key, val) + c = anyFieldC[int](Int) case *int: - return Intp(key, val) + c = anyFieldC[*int](Intp) case []int: - return Ints(key, val) + c = anyFieldC[[]int](Ints) case int64: - return Int64(key, val) + c = anyFieldC[int64](Int64) case *int64: - return Int64p(key, val) + c = anyFieldC[*int64](Int64p) case []int64: - return Int64s(key, val) + c = anyFieldC[[]int64](Int64s) case int32: - return Int32(key, val) + c = anyFieldC[int32](Int32) case *int32: - return Int32p(key, val) + c = anyFieldC[*int32](Int32p) case []int32: - return Int32s(key, val) + c = anyFieldC[[]int32](Int32s) case int16: - return Int16(key, val) + c = anyFieldC[int16](Int16) case *int16: - return Int16p(key, val) + c = anyFieldC[*int16](Int16p) case []int16: - return Int16s(key, val) + c = anyFieldC[[]int16](Int16s) case int8: - return Int8(key, val) + c = anyFieldC[int8](Int8) case *int8: - return Int8p(key, val) + c = anyFieldC[*int8](Int8p) case []int8: - return Int8s(key, val) + c = anyFieldC[[]int8](Int8s) case string: - return String(key, val) + c = anyFieldC[string](String) case *string: - return Stringp(key, val) + c = anyFieldC[*string](Stringp) case []string: - return Strings(key, val) + c = anyFieldC[[]string](Strings) case uint: - return Uint(key, val) + c = anyFieldC[uint](Uint) case *uint: - return Uintp(key, val) + c = anyFieldC[*uint](Uintp) case []uint: - return Uints(key, val) + c = anyFieldC[[]uint](Uints) case uint64: - return Uint64(key, val) + c = anyFieldC[uint64](Uint64) case *uint64: - return Uint64p(key, val) + c = anyFieldC[*uint64](Uint64p) case []uint64: - return Uint64s(key, val) + c = anyFieldC[[]uint64](Uint64s) case uint32: - return Uint32(key, val) + c = anyFieldC[uint32](Uint32) case *uint32: - return Uint32p(key, val) + c = anyFieldC[*uint32](Uint32p) case []uint32: - return Uint32s(key, val) + c = anyFieldC[[]uint32](Uint32s) case uint16: - return Uint16(key, val) + c = anyFieldC[uint16](Uint16) case *uint16: - return Uint16p(key, val) + c = anyFieldC[*uint16](Uint16p) case []uint16: - return Uint16s(key, val) + c = anyFieldC[[]uint16](Uint16s) case uint8: - return Uint8(key, val) + c = anyFieldC[uint8](Uint8) case *uint8: - return Uint8p(key, val) + c = anyFieldC[*uint8](Uint8p) case []byte: - return Binary(key, val) + c = anyFieldC[[]byte](Binary) case uintptr: - return Uintptr(key, val) + c = anyFieldC[uintptr](Uintptr) case *uintptr: - return Uintptrp(key, val) + c = anyFieldC[*uintptr](Uintptrp) case []uintptr: - return Uintptrs(key, val) + c = anyFieldC[[]uintptr](Uintptrs) case time.Time: - return Time(key, val) + c = anyFieldC[time.Time](Time) case *time.Time: - return Timep(key, val) + c = anyFieldC[*time.Time](Timep) case []time.Time: - return Times(key, val) + c = anyFieldC[[]time.Time](Times) case time.Duration: - return Duration(key, val) + c = anyFieldC[time.Duration](Duration) case *time.Duration: - return Durationp(key, val) + c = anyFieldC[*time.Duration](Durationp) case []time.Duration: - return Durations(key, val) + c = anyFieldC[[]time.Duration](Durations) case error: - return NamedError(key, val) + c = anyFieldC[error](NamedError) case []error: - return Errors(key, val) + c = anyFieldC[[]error](Errors) case fmt.Stringer: - return Stringer(key, val) + c = anyFieldC[fmt.Stringer](Stringer) default: - return Reflect(key, val) + c = anyFieldC[any](Reflect) } + + return c.Any(key, value) } diff --git a/vendor/go.uber.org/zap/global.go b/vendor/go.uber.org/zap/global.go index c1ac0507c..3cb46c9e0 100644 --- a/vendor/go.uber.org/zap/global.go +++ b/vendor/go.uber.org/zap/global.go @@ -31,6 +31,7 @@ import ( ) const ( + _stdLogDefaultDepth = 1 _loggerWriterDepth = 2 _programmerErrorTemplate = "You've found a bug in zap! Please file a bug at " + "https://github.com/uber-go/zap/issues/new and reference this error: %v" diff --git a/vendor/go.uber.org/zap/http_handler.go b/vendor/go.uber.org/zap/http_handler.go index 1297c33b3..2be8f6515 100644 --- a/vendor/go.uber.org/zap/http_handler.go +++ b/vendor/go.uber.org/zap/http_handler.go @@ -22,6 +22,7 @@ package zap import ( "encoding/json" + "errors" "fmt" "io" "net/http" @@ -32,22 +33,23 @@ import ( // ServeHTTP is a simple JSON endpoint that can report on or change the current // logging level. // -// GET +// # GET // // The GET request returns a JSON description of the current logging level like: -// {"level":"info"} // -// PUT +// {"level":"info"} +// +// # PUT // // The PUT request changes the logging level. It is perfectly safe to change the // logging level while a program is running. Two content types are supported: // -// Content-Type: application/x-www-form-urlencoded +// Content-Type: application/x-www-form-urlencoded // // With this content type, the level can be provided through the request body or // a query parameter. The log level is URL encoded like: // -// level=debug +// level=debug // // The request body takes precedence over the query parameter, if both are // specified. @@ -55,19 +57,25 @@ import ( // This content type is the default for a curl PUT request. Following are two // example curl requests that both set the logging level to debug. // -// curl -X PUT localhost:8080/log/level?level=debug -// curl -X PUT localhost:8080/log/level -d level=debug +// curl -X PUT localhost:8080/log/level?level=debug +// curl -X PUT localhost:8080/log/level -d level=debug // // For any other content type, the payload is expected to be JSON encoded and // look like: // -// {"level":"info"} +// {"level":"info"} // // An example curl request could look like this: // -// curl -X PUT localhost:8080/log/level -H "Content-Type: application/json" -d '{"level":"debug"}' -// +// curl -X PUT localhost:8080/log/level -H "Content-Type: application/json" -d '{"level":"debug"}' func (lvl AtomicLevel) ServeHTTP(w http.ResponseWriter, r *http.Request) { + if err := lvl.serveHTTP(w, r); err != nil { + w.WriteHeader(http.StatusInternalServerError) + fmt.Fprintf(w, "internal error: %v", err) + } +} + +func (lvl AtomicLevel) serveHTTP(w http.ResponseWriter, r *http.Request) error { type errorResponse struct { Error string `json:"error"` } @@ -79,19 +87,20 @@ func (lvl AtomicLevel) ServeHTTP(w http.ResponseWriter, r *http.Request) { switch r.Method { case http.MethodGet: - enc.Encode(payload{Level: lvl.Level()}) + return enc.Encode(payload{Level: lvl.Level()}) + case http.MethodPut: requestedLvl, err := decodePutRequest(r.Header.Get("Content-Type"), r) if err != nil { w.WriteHeader(http.StatusBadRequest) - enc.Encode(errorResponse{Error: err.Error()}) - return + return enc.Encode(errorResponse{Error: err.Error()}) } lvl.SetLevel(requestedLvl) - enc.Encode(payload{Level: lvl.Level()}) + return enc.Encode(payload{Level: lvl.Level()}) + default: w.WriteHeader(http.StatusMethodNotAllowed) - enc.Encode(errorResponse{ + return enc.Encode(errorResponse{ Error: "Only GET and PUT are supported.", }) } @@ -108,7 +117,7 @@ func decodePutRequest(contentType string, r *http.Request) (zapcore.Level, error func decodePutURL(r *http.Request) (zapcore.Level, error) { lvl := r.FormValue("level") if lvl == "" { - return 0, fmt.Errorf("must specify logging level") + return 0, errors.New("must specify logging level") } var l zapcore.Level if err := l.UnmarshalText([]byte(lvl)); err != nil { @@ -125,8 +134,7 @@ func decodePutJSON(body io.Reader) (zapcore.Level, error) { return 0, fmt.Errorf("malformed request body: %v", err) } if pld.Level == nil { - return 0, fmt.Errorf("must specify logging level") + return 0, errors.New("must specify logging level") } return *pld.Level, nil - } diff --git a/vendor/go.uber.org/zap/internal/exit/exit.go b/vendor/go.uber.org/zap/internal/exit/exit.go index dfc5b05fe..f673f9947 100644 --- a/vendor/go.uber.org/zap/internal/exit/exit.go +++ b/vendor/go.uber.org/zap/internal/exit/exit.go @@ -24,24 +24,25 @@ package exit import "os" -var real = func() { os.Exit(1) } +var _exit = os.Exit -// Exit normally terminates the process by calling os.Exit(1). If the package -// is stubbed, it instead records a call in the testing spy. -func Exit() { - real() +// With terminates the process by calling os.Exit(code). If the package is +// stubbed, it instead records a call in the testing spy. +func With(code int) { + _exit(code) } // A StubbedExit is a testing fake for os.Exit. type StubbedExit struct { Exited bool - prev func() + Code int + prev func(code int) } // Stub substitutes a fake for the call to os.Exit(1). func Stub() *StubbedExit { - s := &StubbedExit{prev: real} - real = s.exit + s := &StubbedExit{prev: _exit} + _exit = s.exit return s } @@ -56,9 +57,10 @@ func WithStub(f func()) *StubbedExit { // Unstub restores the previous exit function. func (se *StubbedExit) Unstub() { - real = se.prev + _exit = se.prev } -func (se *StubbedExit) exit() { +func (se *StubbedExit) exit(code int) { se.Exited = true + se.Code = code } diff --git a/vendor/go.uber.org/zap/internal/level_enabler.go b/vendor/go.uber.org/zap/internal/level_enabler.go new file mode 100644 index 000000000..40bfed81e --- /dev/null +++ b/vendor/go.uber.org/zap/internal/level_enabler.go @@ -0,0 +1,37 @@ +// Copyright (c) 2022 Uber Technologies, Inc. +// +// 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. + +// Package internal and its subpackages hold types and functionality +// that are not part of Zap's public API. +package internal + +import "go.uber.org/zap/zapcore" + +// LeveledEnabler is an interface satisfied by LevelEnablers that are able to +// report their own level. +// +// This interface is defined to use more conveniently in tests and non-zapcore +// packages. +// This cannot be imported from zapcore because of the cyclic dependency. +type LeveledEnabler interface { + zapcore.LevelEnabler + + Level() zapcore.Level +} diff --git a/vendor/go.uber.org/zap/internal/pool/pool.go b/vendor/go.uber.org/zap/internal/pool/pool.go new file mode 100644 index 000000000..60e9d2c43 --- /dev/null +++ b/vendor/go.uber.org/zap/internal/pool/pool.go @@ -0,0 +1,58 @@ +// Copyright (c) 2023 Uber Technologies, Inc. +// +// 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. + +// Package pool provides internal pool utilities. +package pool + +import ( + "sync" +) + +// A Pool is a generic wrapper around [sync.Pool] to provide strongly-typed +// object pooling. +// +// Note that SA6002 (ref: https://staticcheck.io/docs/checks/#SA6002) will +// not be detected, so all internal pool use must take care to only store +// pointer types. +type Pool[T any] struct { + pool sync.Pool +} + +// New returns a new [Pool] for T, and will use fn to construct new Ts when +// the pool is empty. +func New[T any](fn func() T) *Pool[T] { + return &Pool[T]{ + pool: sync.Pool{ + New: func() any { + return fn() + }, + }, + } +} + +// Get gets a T from the pool, or creates a new one if the pool is empty. +func (p *Pool[T]) Get() T { + return p.pool.Get().(T) +} + +// Put returns x into the pool. +func (p *Pool[T]) Put(x T) { + p.pool.Put(x) +} diff --git a/vendor/go.uber.org/zap/internal/stacktrace/stack.go b/vendor/go.uber.org/zap/internal/stacktrace/stack.go new file mode 100644 index 000000000..82af7551f --- /dev/null +++ b/vendor/go.uber.org/zap/internal/stacktrace/stack.go @@ -0,0 +1,181 @@ +// Copyright (c) 2023 Uber Technologies, Inc. +// +// 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. + +// Package stacktrace provides support for gathering stack traces +// efficiently. +package stacktrace + +import ( + "runtime" + + "go.uber.org/zap/buffer" + "go.uber.org/zap/internal/bufferpool" + "go.uber.org/zap/internal/pool" +) + +var _stackPool = pool.New(func() *Stack { + return &Stack{ + storage: make([]uintptr, 64), + } +}) + +// Stack is a captured stack trace. +type Stack struct { + pcs []uintptr // program counters; always a subslice of storage + frames *runtime.Frames + + // The size of pcs varies depending on requirements: + // it will be one if the only the first frame was requested, + // and otherwise it will reflect the depth of the call stack. + // + // storage decouples the slice we need (pcs) from the slice we pool. + // We will always allocate a reasonably large storage, but we'll use + // only as much of it as we need. + storage []uintptr +} + +// Depth specifies how deep of a stack trace should be captured. +type Depth int + +const ( + // First captures only the first frame. + First Depth = iota + + // Full captures the entire call stack, allocating more + // storage for it if needed. + Full +) + +// Capture captures a stack trace of the specified depth, skipping +// the provided number of frames. skip=0 identifies the caller of +// Capture. +// +// The caller must call Free on the returned stacktrace after using it. +func Capture(skip int, depth Depth) *Stack { + stack := _stackPool.Get() + + switch depth { + case First: + stack.pcs = stack.storage[:1] + case Full: + stack.pcs = stack.storage + } + + // Unlike other "skip"-based APIs, skip=0 identifies runtime.Callers + // itself. +2 to skip captureStacktrace and runtime.Callers. + numFrames := runtime.Callers( + skip+2, + stack.pcs, + ) + + // runtime.Callers truncates the recorded stacktrace if there is no + // room in the provided slice. For the full stack trace, keep expanding + // storage until there are fewer frames than there is room. + if depth == Full { + pcs := stack.pcs + for numFrames == len(pcs) { + pcs = make([]uintptr, len(pcs)*2) + numFrames = runtime.Callers(skip+2, pcs) + } + + // Discard old storage instead of returning it to the pool. + // This will adjust the pool size over time if stack traces are + // consistently very deep. + stack.storage = pcs + stack.pcs = pcs[:numFrames] + } else { + stack.pcs = stack.pcs[:numFrames] + } + + stack.frames = runtime.CallersFrames(stack.pcs) + return stack +} + +// Free releases resources associated with this stacktrace +// and returns it back to the pool. +func (st *Stack) Free() { + st.frames = nil + st.pcs = nil + _stackPool.Put(st) +} + +// Count reports the total number of frames in this stacktrace. +// Count DOES NOT change as Next is called. +func (st *Stack) Count() int { + return len(st.pcs) +} + +// Next returns the next frame in the stack trace, +// and a boolean indicating whether there are more after it. +func (st *Stack) Next() (_ runtime.Frame, more bool) { + return st.frames.Next() +} + +// Take returns a string representation of the current stacktrace. +// +// skip is the number of frames to skip before recording the stack trace. +// skip=0 identifies the caller of Take. +func Take(skip int) string { + stack := Capture(skip+1, Full) + defer stack.Free() + + buffer := bufferpool.Get() + defer buffer.Free() + + stackfmt := NewFormatter(buffer) + stackfmt.FormatStack(stack) + return buffer.String() +} + +// Formatter formats a stack trace into a readable string representation. +type Formatter struct { + b *buffer.Buffer + nonEmpty bool // whehther we've written at least one frame already +} + +// NewFormatter builds a new Formatter. +func NewFormatter(b *buffer.Buffer) Formatter { + return Formatter{b: b} +} + +// FormatStack formats all remaining frames in the provided stacktrace -- minus +// the final runtime.main/runtime.goexit frame. +func (sf *Formatter) FormatStack(stack *Stack) { + // Note: On the last iteration, frames.Next() returns false, with a valid + // frame, but we ignore this frame. The last frame is a runtime frame which + // adds noise, since it's only either runtime.main or runtime.goexit. + for frame, more := stack.Next(); more; frame, more = stack.Next() { + sf.FormatFrame(frame) + } +} + +// FormatFrame formats the given frame. +func (sf *Formatter) FormatFrame(frame runtime.Frame) { + if sf.nonEmpty { + sf.b.AppendByte('\n') + } + sf.nonEmpty = true + sf.b.AppendString(frame.Function) + sf.b.AppendByte('\n') + sf.b.AppendByte('\t') + sf.b.AppendString(frame.File) + sf.b.AppendByte(':') + sf.b.AppendInt(int64(frame.Line)) +} diff --git a/vendor/go.uber.org/zap/level.go b/vendor/go.uber.org/zap/level.go index 3567a9a1e..155b208bd 100644 --- a/vendor/go.uber.org/zap/level.go +++ b/vendor/go.uber.org/zap/level.go @@ -21,7 +21,9 @@ package zap import ( - "go.uber.org/atomic" + "sync/atomic" + + "go.uber.org/zap/internal" "go.uber.org/zap/zapcore" ) @@ -70,12 +72,14 @@ type AtomicLevel struct { l *atomic.Int32 } +var _ internal.LeveledEnabler = AtomicLevel{} + // NewAtomicLevel creates an AtomicLevel with InfoLevel and above logging // enabled. func NewAtomicLevel() AtomicLevel { - return AtomicLevel{ - l: atomic.NewInt32(int32(InfoLevel)), - } + lvl := AtomicLevel{l: new(atomic.Int32)} + lvl.l.Store(int32(InfoLevel)) + return lvl } // NewAtomicLevelAt is a convenience function that creates an AtomicLevel @@ -86,6 +90,23 @@ func NewAtomicLevelAt(l zapcore.Level) AtomicLevel { return a } +// ParseAtomicLevel parses an AtomicLevel based on a lowercase or all-caps ASCII +// representation of the log level. If the provided ASCII representation is +// invalid an error is returned. +// +// This is particularly useful when dealing with text input to configure log +// levels. +func ParseAtomicLevel(text string) (AtomicLevel, error) { + a := NewAtomicLevel() + l, err := zapcore.ParseLevel(text) + if err != nil { + return a, err + } + + a.SetLevel(l) + return a, nil +} + // Enabled implements the zapcore.LevelEnabler interface, which allows the // AtomicLevel to be used in place of traditional static levels. func (lvl AtomicLevel) Enabled(l zapcore.Level) bool { diff --git a/vendor/go.uber.org/zap/logger.go b/vendor/go.uber.org/zap/logger.go index f116bd936..6205fe48a 100644 --- a/vendor/go.uber.org/zap/logger.go +++ b/vendor/go.uber.org/zap/logger.go @@ -22,11 +22,12 @@ package zap import ( "fmt" - "io/ioutil" + "io" "os" - "runtime" "strings" + "go.uber.org/zap/internal/bufferpool" + "go.uber.org/zap/internal/stacktrace" "go.uber.org/zap/zapcore" ) @@ -42,7 +43,7 @@ type Logger struct { development bool addCaller bool - onFatal zapcore.CheckWriteAction // default is WriteThenFatal + onFatal zapcore.CheckWriteHook // default is WriteThenFatal name string errorOutput zapcore.WriteSyncer @@ -85,7 +86,7 @@ func New(core zapcore.Core, options ...Option) *Logger { func NewNop() *Logger { return &Logger{ core: zapcore.NewNopCore(), - errorOutput: zapcore.AddSync(ioutil.Discard), + errorOutput: zapcore.AddSync(io.Discard), addStack: zapcore.FatalLevel + 1, clock: zapcore.DefaultClock, } @@ -107,6 +108,19 @@ func NewDevelopment(options ...Option) (*Logger, error) { return NewDevelopmentConfig().Build(options...) } +// Must is a helper that wraps a call to a function returning (*Logger, error) +// and panics if the error is non-nil. It is intended for use in variable +// initialization such as: +// +// var logger = zap.Must(zap.NewProduction()) +func Must(logger *Logger, err error) *Logger { + if err != nil { + panic(err) + } + + return logger +} + // NewExample builds a Logger that's designed for use in zap's testable // examples. It writes DebugLevel and above logs to standard out as JSON, but // omits the timestamp and calling function to keep example output @@ -160,7 +174,8 @@ func (log *Logger) WithOptions(opts ...Option) *Logger { } // With creates a child logger and adds structured context to it. Fields added -// to the child don't affect the parent, and vice versa. +// to the child don't affect the parent, and vice versa. Any fields that +// require evaluation (such as Objects) are evaluated upon invocation of With. func (log *Logger) With(fields ...Field) *Logger { if len(fields) == 0 { return log @@ -170,6 +185,35 @@ func (log *Logger) With(fields ...Field) *Logger { return l } +// WithLazy creates a child logger and adds structured context to it lazily. +// +// The fields are evaluated only if the logger is further chained with [With] +// or is written to with any of the log level methods. +// Until that occurs, the logger may retain references to objects inside the fields, +// and logging will reflect the state of an object at the time of logging, +// not the time of WithLazy(). +// +// WithLazy provides a worthwhile performance optimization for contextual loggers +// when the likelihood of using the child logger is low, +// such as error paths and rarely taken branches. +// +// Similar to [With], fields added to the child don't affect the parent, and vice versa. +func (log *Logger) WithLazy(fields ...Field) *Logger { + if len(fields) == 0 { + return log + } + return log.WithOptions(WrapCore(func(core zapcore.Core) zapcore.Core { + return zapcore.NewLazyWith(core, fields) + })) +} + +// Level reports the minimum enabled level for this logger. +// +// For NopLoggers, this is [zapcore.InvalidLevel]. +func (log *Logger) Level() zapcore.Level { + return zapcore.LevelOf(log.core) +} + // Check returns a CheckedEntry if logging a message at the specified level // is enabled. It's a completely optional optimization; in high-performance // applications, Check can help avoid allocating a slice to hold fields. @@ -177,6 +221,16 @@ func (log *Logger) Check(lvl zapcore.Level, msg string) *zapcore.CheckedEntry { return log.check(lvl, msg) } +// Log logs a message at the specified level. The message includes any fields +// passed at the log site, as well as any fields accumulated on the logger. +// Any Fields that require evaluation (such as Objects) are evaluated upon +// invocation of Log. +func (log *Logger) Log(lvl zapcore.Level, msg string, fields ...Field) { + if ce := log.check(lvl, msg); ce != nil { + ce.Write(fields...) + } +} + // Debug logs a message at DebugLevel. The message includes any fields passed // at the log site, as well as any fields accumulated on the logger. func (log *Logger) Debug(msg string, fields ...Field) { @@ -253,14 +307,22 @@ func (log *Logger) Core() zapcore.Core { return log.core } +// Name returns the Logger's underlying name, +// or an empty string if the logger is unnamed. +func (log *Logger) Name() string { + return log.name +} + func (log *Logger) clone() *Logger { - copy := *log - return © + clone := *log + return &clone } func (log *Logger) check(lvl zapcore.Level, msg string) *zapcore.CheckedEntry { - // check must always be called directly by a method in the Logger interface - // (e.g., Check, Info, Fatal). + // Logger.check must always be called directly by a method in the + // Logger interface (e.g., Check, Info, Fatal). + // This skips Logger.check and the Info/Fatal/Check/etc. method that + // called it. const callerSkipOffset = 2 // Check the level first to reduce the cost of disabled log calls. @@ -283,18 +345,27 @@ func (log *Logger) check(lvl zapcore.Level, msg string) *zapcore.CheckedEntry { // Set up any required terminal behavior. switch ent.Level { case zapcore.PanicLevel: - ce = ce.Should(ent, zapcore.WriteThenPanic) + ce = ce.After(ent, zapcore.WriteThenPanic) case zapcore.FatalLevel: onFatal := log.onFatal - // Noop is the default value for CheckWriteAction, and it leads to - // continued execution after a Fatal which is unexpected. - if onFatal == zapcore.WriteThenNoop { + // nil or WriteThenNoop will lead to continued execution after + // a Fatal log entry, which is unexpected. For example, + // + // f, err := os.Open(..) + // if err != nil { + // log.Fatal("cannot open", zap.Error(err)) + // } + // fmt.Println(f.Name()) + // + // The f.Name() will panic if we continue execution after the + // log.Fatal. + if onFatal == nil || onFatal == zapcore.WriteThenNoop { onFatal = zapcore.WriteThenFatal } - ce = ce.Should(ent, onFatal) + ce = ce.After(ent, onFatal) case zapcore.DPanicLevel: if log.development { - ce = ce.Should(ent, zapcore.WriteThenPanic) + ce = ce.After(ent, zapcore.WriteThenPanic) } } @@ -307,42 +378,55 @@ func (log *Logger) check(lvl zapcore.Level, msg string) *zapcore.CheckedEntry { // Thread the error output through to the CheckedEntry. ce.ErrorOutput = log.errorOutput - if log.addCaller { - frame, defined := getCallerFrame(log.callerSkip + callerSkipOffset) - if !defined { + + addStack := log.addStack.Enabled(ce.Level) + if !log.addCaller && !addStack { + return ce + } + + // Adding the caller or stack trace requires capturing the callers of + // this function. We'll share information between these two. + stackDepth := stacktrace.First + if addStack { + stackDepth = stacktrace.Full + } + stack := stacktrace.Capture(log.callerSkip+callerSkipOffset, stackDepth) + defer stack.Free() + + if stack.Count() == 0 { + if log.addCaller { fmt.Fprintf(log.errorOutput, "%v Logger.check error: failed to get caller\n", ent.Time.UTC()) - log.errorOutput.Sync() + _ = log.errorOutput.Sync() } + return ce + } + + frame, more := stack.Next() - ce.Entry.Caller = zapcore.EntryCaller{ - Defined: defined, + if log.addCaller { + ce.Caller = zapcore.EntryCaller{ + Defined: frame.PC != 0, PC: frame.PC, File: frame.File, Line: frame.Line, Function: frame.Function, } } - if log.addStack.Enabled(ce.Entry.Level) { - ce.Entry.Stack = StackSkip("", log.callerSkip+callerSkipOffset).String - } - return ce -} + if addStack { + buffer := bufferpool.Get() + defer buffer.Free() -// getCallerFrame gets caller frame. The argument skip is the number of stack -// frames to ascend, with 0 identifying the caller of getCallerFrame. The -// boolean ok is false if it was not possible to recover the information. -// -// Note: This implementation is similar to runtime.Caller, but it returns the whole frame. -func getCallerFrame(skip int) (frame runtime.Frame, ok bool) { - const skipOffset = 2 // skip getCallerFrame and Callers - - pc := make([]uintptr, 1) - numFrames := runtime.Callers(skip+skipOffset, pc) - if numFrames < 1 { - return + stackfmt := stacktrace.NewFormatter(buffer) + + // We've already extracted the first frame, so format that + // separately and defer to stackfmt for the rest. + stackfmt.FormatFrame(frame) + if more { + stackfmt.FormatStack(stack) + } + ce.Stack = buffer.String() } - frame, _ = runtime.CallersFrames(pc).Next() - return frame, frame.PC != 0 + return ce } diff --git a/vendor/go.uber.org/zap/options.go b/vendor/go.uber.org/zap/options.go index e9e66161f..c4f3bca3d 100644 --- a/vendor/go.uber.org/zap/options.go +++ b/vendor/go.uber.org/zap/options.go @@ -133,9 +133,28 @@ func IncreaseLevel(lvl zapcore.LevelEnabler) Option { } // OnFatal sets the action to take on fatal logs. +// +// Deprecated: Use [WithFatalHook] instead. func OnFatal(action zapcore.CheckWriteAction) Option { + return WithFatalHook(action) +} + +// WithFatalHook sets a CheckWriteHook to run on fatal logs. +// Zap will call this hook after writing a log statement with a Fatal level. +// +// For example, the following builds a logger that will exit the current +// goroutine after writing a fatal log message, but it will not exit the +// program. +// +// zap.New(core, zap.WithFatalHook(zapcore.WriteThenGoexit)) +// +// It is important that the provided CheckWriteHook stops the control flow at +// the current statement to meet expectations of callers of the logger. +// We recommend calling os.Exit or runtime.Goexit inside custom hooks at +// minimum. +func WithFatalHook(hook zapcore.CheckWriteHook) Option { return optionFunc(func(log *Logger) { - log.onFatal = action + log.onFatal = hook }) } diff --git a/vendor/go.uber.org/zap/sink.go b/vendor/go.uber.org/zap/sink.go index df46fa87a..499772a00 100644 --- a/vendor/go.uber.org/zap/sink.go +++ b/vendor/go.uber.org/zap/sink.go @@ -1,4 +1,4 @@ -// Copyright (c) 2016 Uber Technologies, Inc. +// Copyright (c) 2016-2022 Uber Technologies, Inc. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -26,6 +26,7 @@ import ( "io" "net/url" "os" + "path/filepath" "strings" "sync" @@ -34,23 +35,7 @@ import ( const schemeFile = "file" -var ( - _sinkMutex sync.RWMutex - _sinkFactories map[string]func(*url.URL) (Sink, error) // keyed by scheme -) - -func init() { - resetSinkRegistry() -} - -func resetSinkRegistry() { - _sinkMutex.Lock() - defer _sinkMutex.Unlock() - - _sinkFactories = map[string]func(*url.URL) (Sink, error){ - schemeFile: newFileSink, - } -} +var _sinkRegistry = newSinkRegistry() // Sink defines the interface to write to and close logger destinations. type Sink interface { @@ -58,10 +43,6 @@ type Sink interface { io.Closer } -type nopCloserSink struct{ zapcore.WriteSyncer } - -func (nopCloserSink) Close() error { return nil } - type errSinkNotFound struct { scheme string } @@ -70,16 +51,30 @@ func (e *errSinkNotFound) Error() string { return fmt.Sprintf("no sink found for scheme %q", e.scheme) } -// RegisterSink registers a user-supplied factory for all sinks with a -// particular scheme. -// -// All schemes must be ASCII, valid under section 3.1 of RFC 3986 -// (https://tools.ietf.org/html/rfc3986#section-3.1), and must not already -// have a factory registered. Zap automatically registers a factory for the -// "file" scheme. -func RegisterSink(scheme string, factory func(*url.URL) (Sink, error)) error { - _sinkMutex.Lock() - defer _sinkMutex.Unlock() +type nopCloserSink struct{ zapcore.WriteSyncer } + +func (nopCloserSink) Close() error { return nil } + +type sinkRegistry struct { + mu sync.Mutex + factories map[string]func(*url.URL) (Sink, error) // keyed by scheme + openFile func(string, int, os.FileMode) (*os.File, error) // type matches os.OpenFile +} + +func newSinkRegistry() *sinkRegistry { + sr := &sinkRegistry{ + factories: make(map[string]func(*url.URL) (Sink, error)), + openFile: os.OpenFile, + } + // Infallible operation: the registry is empty, so we can't have a conflict. + _ = sr.RegisterSink(schemeFile, sr.newFileSinkFromURL) + return sr +} + +// RegisterScheme registers the given factory for the specific scheme. +func (sr *sinkRegistry) RegisterSink(scheme string, factory func(*url.URL) (Sink, error)) error { + sr.mu.Lock() + defer sr.mu.Unlock() if scheme == "" { return errors.New("can't register a sink factory for empty string") @@ -88,14 +83,22 @@ func RegisterSink(scheme string, factory func(*url.URL) (Sink, error)) error { if err != nil { return fmt.Errorf("%q is not a valid scheme: %v", scheme, err) } - if _, ok := _sinkFactories[normalized]; ok { + if _, ok := sr.factories[normalized]; ok { return fmt.Errorf("sink factory already registered for scheme %q", normalized) } - _sinkFactories[normalized] = factory + sr.factories[normalized] = factory return nil } -func newSink(rawURL string) (Sink, error) { +func (sr *sinkRegistry) newSink(rawURL string) (Sink, error) { + // URL parsing doesn't work well for Windows paths such as `c:\log.txt`, as scheme is set to + // the drive, and path is unset unless `c:/log.txt` is used. + // To avoid Windows-specific URL handling, we instead check IsAbs to open as a file. + // filepath.IsAbs is OS-specific, so IsAbs('c:/log.txt') is false outside of Windows. + if filepath.IsAbs(rawURL) { + return sr.newFileSinkFromPath(rawURL) + } + u, err := url.Parse(rawURL) if err != nil { return nil, fmt.Errorf("can't parse %q as a URL: %v", rawURL, err) @@ -104,16 +107,27 @@ func newSink(rawURL string) (Sink, error) { u.Scheme = schemeFile } - _sinkMutex.RLock() - factory, ok := _sinkFactories[u.Scheme] - _sinkMutex.RUnlock() + sr.mu.Lock() + factory, ok := sr.factories[u.Scheme] + sr.mu.Unlock() if !ok { return nil, &errSinkNotFound{u.Scheme} } return factory(u) } -func newFileSink(u *url.URL) (Sink, error) { +// RegisterSink registers a user-supplied factory for all sinks with a +// particular scheme. +// +// All schemes must be ASCII, valid under section 0.1 of RFC 3986 +// (https://tools.ietf.org/html/rfc3983#section-3.1), and must not already +// have a factory registered. Zap automatically registers a factory for the +// "file" scheme. +func RegisterSink(scheme string, factory func(*url.URL) (Sink, error)) error { + return _sinkRegistry.RegisterSink(scheme, factory) +} + +func (sr *sinkRegistry) newFileSinkFromURL(u *url.URL) (Sink, error) { if u.User != nil { return nil, fmt.Errorf("user and password not allowed with file URLs: got %v", u) } @@ -130,13 +144,18 @@ func newFileSink(u *url.URL) (Sink, error) { if hn := u.Hostname(); hn != "" && hn != "localhost" { return nil, fmt.Errorf("file URLs must leave host empty or use localhost: got %v", u) } - switch u.Path { + + return sr.newFileSinkFromPath(u.Path) +} + +func (sr *sinkRegistry) newFileSinkFromPath(path string) (Sink, error) { + switch path { case "stdout": return nopCloserSink{os.Stdout}, nil case "stderr": return nopCloserSink{os.Stderr}, nil } - return os.OpenFile(u.Path, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0666) + return sr.openFile(path, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0o666) } func normalizeScheme(s string) (string, error) { diff --git a/vendor/go.uber.org/zap/stacktrace.go b/vendor/go.uber.org/zap/stacktrace.go deleted file mode 100644 index 0cf8c1ddf..000000000 --- a/vendor/go.uber.org/zap/stacktrace.go +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright (c) 2016 Uber Technologies, Inc. -// -// 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. - -package zap - -import ( - "runtime" - "sync" - - "go.uber.org/zap/internal/bufferpool" -) - -var ( - _stacktracePool = sync.Pool{ - New: func() interface{} { - return newProgramCounters(64) - }, - } -) - -func takeStacktrace(skip int) string { - buffer := bufferpool.Get() - defer buffer.Free() - programCounters := _stacktracePool.Get().(*programCounters) - defer _stacktracePool.Put(programCounters) - - var numFrames int - for { - // Skip the call to runtime.Callers and takeStacktrace so that the - // program counters start at the caller of takeStacktrace. - numFrames = runtime.Callers(skip+2, programCounters.pcs) - if numFrames < len(programCounters.pcs) { - break - } - // Don't put the too-short counter slice back into the pool; this lets - // the pool adjust if we consistently take deep stacktraces. - programCounters = newProgramCounters(len(programCounters.pcs) * 2) - } - - i := 0 - frames := runtime.CallersFrames(programCounters.pcs[:numFrames]) - - // Note: On the last iteration, frames.Next() returns false, with a valid - // frame, but we ignore this frame. The last frame is a a runtime frame which - // adds noise, since it's only either runtime.main or runtime.goexit. - for frame, more := frames.Next(); more; frame, more = frames.Next() { - if i != 0 { - buffer.AppendByte('\n') - } - i++ - buffer.AppendString(frame.Function) - buffer.AppendByte('\n') - buffer.AppendByte('\t') - buffer.AppendString(frame.File) - buffer.AppendByte(':') - buffer.AppendInt(int64(frame.Line)) - } - - return buffer.String() -} - -type programCounters struct { - pcs []uintptr -} - -func newProgramCounters(size int) *programCounters { - return &programCounters{make([]uintptr, size)} -} diff --git a/vendor/go.uber.org/zap/sugar.go b/vendor/go.uber.org/zap/sugar.go index 0b9651981..00ac5fe3a 100644 --- a/vendor/go.uber.org/zap/sugar.go +++ b/vendor/go.uber.org/zap/sugar.go @@ -31,6 +31,7 @@ import ( const ( _oddNumberErrMsg = "Ignored key without a value." _nonStringKeyErrMsg = "Ignored key-value pairs with non-string keys." + _multipleErrMsg = "Multiple errors without a key." ) // A SugaredLogger wraps the base Logger functionality in a slower, but less @@ -38,10 +39,19 @@ const ( // method. // // Unlike the Logger, the SugaredLogger doesn't insist on structured logging. -// For each log level, it exposes three methods: one for loosely-typed -// structured logging, one for println-style formatting, and one for -// printf-style formatting. For example, SugaredLoggers can produce InfoLevel -// output with Infow ("info with" structured context), Info, or Infof. +// For each log level, it exposes four methods: +// +// - methods named after the log level for log.Print-style logging +// - methods ending in "w" for loosely-typed structured logging +// - methods ending in "f" for log.Printf-style logging +// - methods ending in "ln" for log.Println-style logging +// +// For example, the methods for InfoLevel are: +// +// Info(...any) Print-style logging +// Infow(...any) Structured logging (read as "info with") +// Infof(string, ...any) Printf-style logging +// Infoln(...any) Println-style logging type SugaredLogger struct { base *Logger } @@ -61,27 +71,40 @@ func (s *SugaredLogger) Named(name string) *SugaredLogger { return &SugaredLogger{base: s.base.Named(name)} } +// WithOptions clones the current SugaredLogger, applies the supplied Options, +// and returns the result. It's safe to use concurrently. +func (s *SugaredLogger) WithOptions(opts ...Option) *SugaredLogger { + base := s.base.clone() + for _, opt := range opts { + opt.apply(base) + } + return &SugaredLogger{base: base} +} + // With adds a variadic number of fields to the logging context. It accepts a // mix of strongly-typed Field objects and loosely-typed key-value pairs. When // processing pairs, the first element of the pair is used as the field key // and the second as the field value. // // For example, -// sugaredLogger.With( -// "hello", "world", -// "failure", errors.New("oh no"), -// Stack(), -// "count", 42, -// "user", User{Name: "alice"}, -// ) +// +// sugaredLogger.With( +// "hello", "world", +// "failure", errors.New("oh no"), +// Stack(), +// "count", 42, +// "user", User{Name: "alice"}, +// ) +// // is the equivalent of -// unsugared.With( -// String("hello", "world"), -// String("failure", "oh no"), -// Stack(), -// Int("count", 42), -// Object("user", User{Name: "alice"}), -// ) +// +// unsugared.With( +// String("hello", "world"), +// String("failure", "oh no"), +// Stack(), +// Int("count", 42), +// Object("user", User{Name: "alice"}), +// ) // // Note that the keys in key-value pairs should be strings. In development, // passing a non-string key panics. In production, the logger is more @@ -92,74 +115,95 @@ func (s *SugaredLogger) With(args ...interface{}) *SugaredLogger { return &SugaredLogger{base: s.base.With(s.sweetenFields(args)...)} } -// Debug uses fmt.Sprint to construct and log a message. +// Level reports the minimum enabled level for this logger. +// +// For NopLoggers, this is [zapcore.InvalidLevel]. +func (s *SugaredLogger) Level() zapcore.Level { + return zapcore.LevelOf(s.base.core) +} + +// Debug logs the provided arguments at [DebugLevel]. +// Spaces are added between arguments when neither is a string. func (s *SugaredLogger) Debug(args ...interface{}) { s.log(DebugLevel, "", args, nil) } -// Info uses fmt.Sprint to construct and log a message. +// Info logs the provided arguments at [InfoLevel]. +// Spaces are added between arguments when neither is a string. func (s *SugaredLogger) Info(args ...interface{}) { s.log(InfoLevel, "", args, nil) } -// Warn uses fmt.Sprint to construct and log a message. +// Warn logs the provided arguments at [WarnLevel]. +// Spaces are added between arguments when neither is a string. func (s *SugaredLogger) Warn(args ...interface{}) { s.log(WarnLevel, "", args, nil) } -// Error uses fmt.Sprint to construct and log a message. +// Error logs the provided arguments at [ErrorLevel]. +// Spaces are added between arguments when neither is a string. func (s *SugaredLogger) Error(args ...interface{}) { s.log(ErrorLevel, "", args, nil) } -// DPanic uses fmt.Sprint to construct and log a message. In development, the -// logger then panics. (See DPanicLevel for details.) +// DPanic logs the provided arguments at [DPanicLevel]. +// In development, the logger then panics. (See [DPanicLevel] for details.) +// Spaces are added between arguments when neither is a string. func (s *SugaredLogger) DPanic(args ...interface{}) { s.log(DPanicLevel, "", args, nil) } -// Panic uses fmt.Sprint to construct and log a message, then panics. +// Panic constructs a message with the provided arguments and panics. +// Spaces are added between arguments when neither is a string. func (s *SugaredLogger) Panic(args ...interface{}) { s.log(PanicLevel, "", args, nil) } -// Fatal uses fmt.Sprint to construct and log a message, then calls os.Exit. +// Fatal constructs a message with the provided arguments and calls os.Exit. +// Spaces are added between arguments when neither is a string. func (s *SugaredLogger) Fatal(args ...interface{}) { s.log(FatalLevel, "", args, nil) } -// Debugf uses fmt.Sprintf to log a templated message. +// Debugf formats the message according to the format specifier +// and logs it at [DebugLevel]. func (s *SugaredLogger) Debugf(template string, args ...interface{}) { s.log(DebugLevel, template, args, nil) } -// Infof uses fmt.Sprintf to log a templated message. +// Infof formats the message according to the format specifier +// and logs it at [InfoLevel]. func (s *SugaredLogger) Infof(template string, args ...interface{}) { s.log(InfoLevel, template, args, nil) } -// Warnf uses fmt.Sprintf to log a templated message. +// Warnf formats the message according to the format specifier +// and logs it at [WarnLevel]. func (s *SugaredLogger) Warnf(template string, args ...interface{}) { s.log(WarnLevel, template, args, nil) } -// Errorf uses fmt.Sprintf to log a templated message. +// Errorf formats the message according to the format specifier +// and logs it at [ErrorLevel]. func (s *SugaredLogger) Errorf(template string, args ...interface{}) { s.log(ErrorLevel, template, args, nil) } -// DPanicf uses fmt.Sprintf to log a templated message. In development, the -// logger then panics. (See DPanicLevel for details.) +// DPanicf formats the message according to the format specifier +// and logs it at [DPanicLevel]. +// In development, the logger then panics. (See [DPanicLevel] for details.) func (s *SugaredLogger) DPanicf(template string, args ...interface{}) { s.log(DPanicLevel, template, args, nil) } -// Panicf uses fmt.Sprintf to log a templated message, then panics. +// Panicf formats the message according to the format specifier +// and panics. func (s *SugaredLogger) Panicf(template string, args ...interface{}) { s.log(PanicLevel, template, args, nil) } -// Fatalf uses fmt.Sprintf to log a templated message, then calls os.Exit. +// Fatalf formats the message according to the format specifier +// and calls os.Exit. func (s *SugaredLogger) Fatalf(template string, args ...interface{}) { s.log(FatalLevel, template, args, nil) } @@ -168,7 +212,8 @@ func (s *SugaredLogger) Fatalf(template string, args ...interface{}) { // pairs are treated as they are in With. // // When debug-level logging is disabled, this is much faster than -// s.With(keysAndValues).Debug(msg) +// +// s.With(keysAndValues).Debug(msg) func (s *SugaredLogger) Debugw(msg string, keysAndValues ...interface{}) { s.log(DebugLevel, msg, nil, keysAndValues) } @@ -210,11 +255,55 @@ func (s *SugaredLogger) Fatalw(msg string, keysAndValues ...interface{}) { s.log(FatalLevel, msg, nil, keysAndValues) } +// Debugln logs a message at [DebugLevel]. +// Spaces are always added between arguments. +func (s *SugaredLogger) Debugln(args ...interface{}) { + s.logln(DebugLevel, args, nil) +} + +// Infoln logs a message at [InfoLevel]. +// Spaces are always added between arguments. +func (s *SugaredLogger) Infoln(args ...interface{}) { + s.logln(InfoLevel, args, nil) +} + +// Warnln logs a message at [WarnLevel]. +// Spaces are always added between arguments. +func (s *SugaredLogger) Warnln(args ...interface{}) { + s.logln(WarnLevel, args, nil) +} + +// Errorln logs a message at [ErrorLevel]. +// Spaces are always added between arguments. +func (s *SugaredLogger) Errorln(args ...interface{}) { + s.logln(ErrorLevel, args, nil) +} + +// DPanicln logs a message at [DPanicLevel]. +// In development, the logger then panics. (See [DPanicLevel] for details.) +// Spaces are always added between arguments. +func (s *SugaredLogger) DPanicln(args ...interface{}) { + s.logln(DPanicLevel, args, nil) +} + +// Panicln logs a message at [PanicLevel] and panics. +// Spaces are always added between arguments. +func (s *SugaredLogger) Panicln(args ...interface{}) { + s.logln(PanicLevel, args, nil) +} + +// Fatalln logs a message at [FatalLevel] and calls os.Exit. +// Spaces are always added between arguments. +func (s *SugaredLogger) Fatalln(args ...interface{}) { + s.logln(FatalLevel, args, nil) +} + // Sync flushes any buffered log entries. func (s *SugaredLogger) Sync() error { return s.base.Sync() } +// log message with Sprint, Sprintf, or neither. func (s *SugaredLogger) log(lvl zapcore.Level, template string, fmtArgs []interface{}, context []interface{}) { // If logging at this level is completely disabled, skip the overhead of // string formatting. @@ -228,6 +317,18 @@ func (s *SugaredLogger) log(lvl zapcore.Level, template string, fmtArgs []interf } } +// logln message with Sprintln +func (s *SugaredLogger) logln(lvl zapcore.Level, fmtArgs []interface{}, context []interface{}) { + if lvl < DPanicLevel && !s.base.Core().Enabled(lvl) { + return + } + + msg := getMessageln(fmtArgs) + if ce := s.base.Check(lvl, msg); ce != nil { + ce.Write(s.sweetenFields(context)...) + } +} + // getMessage format with Sprint, Sprintf, or neither. func getMessage(template string, fmtArgs []interface{}) string { if len(fmtArgs) == 0 { @@ -246,15 +347,24 @@ func getMessage(template string, fmtArgs []interface{}) string { return fmt.Sprint(fmtArgs...) } +// getMessageln format with Sprintln. +func getMessageln(fmtArgs []interface{}) string { + msg := fmt.Sprintln(fmtArgs...) + return msg[:len(msg)-1] +} + func (s *SugaredLogger) sweetenFields(args []interface{}) []Field { if len(args) == 0 { return nil } - // Allocate enough space for the worst case; if users pass only structured - // fields, we shouldn't penalize them with extra allocations. - fields := make([]Field, 0, len(args)) - var invalid invalidPairs + var ( + // Allocate enough space for the worst case; if users pass only structured + // fields, we shouldn't penalize them with extra allocations. + fields = make([]Field, 0, len(args)) + invalid invalidPairs + seenError bool + ) for i := 0; i < len(args); { // This is a strongly-typed field. Consume it and move on. @@ -264,6 +374,18 @@ func (s *SugaredLogger) sweetenFields(args []interface{}) []Field { continue } + // If it is an error, consume it and move on. + if err, ok := args[i].(error); ok { + if !seenError { + seenError = true + fields = append(fields, Error(err)) + } else { + s.base.Error(_multipleErrMsg, Error(err)) + } + i++ + continue + } + // Make sure this element isn't a dangling key. if i == len(args)-1 { s.base.Error(_oddNumberErrMsg, Any("ignored", args[i])) diff --git a/vendor/go.uber.org/zap/writer.go b/vendor/go.uber.org/zap/writer.go index 86a709ab0..06768c679 100644 --- a/vendor/go.uber.org/zap/writer.go +++ b/vendor/go.uber.org/zap/writer.go @@ -1,4 +1,4 @@ -// Copyright (c) 2016 Uber Technologies, Inc. +// Copyright (c) 2016-2022 Uber Technologies, Inc. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -23,7 +23,6 @@ package zap import ( "fmt" "io" - "io/ioutil" "go.uber.org/zap/zapcore" @@ -49,40 +48,40 @@ import ( // os.Stdout and os.Stderr. When specified without a scheme, relative file // paths also work. func Open(paths ...string) (zapcore.WriteSyncer, func(), error) { - writers, close, err := open(paths) + writers, closeAll, err := open(paths) if err != nil { return nil, nil, err } writer := CombineWriteSyncers(writers...) - return writer, close, nil + return writer, closeAll, nil } func open(paths []string) ([]zapcore.WriteSyncer, func(), error) { writers := make([]zapcore.WriteSyncer, 0, len(paths)) closers := make([]io.Closer, 0, len(paths)) - close := func() { + closeAll := func() { for _, c := range closers { - c.Close() + _ = c.Close() } } var openErr error for _, path := range paths { - sink, err := newSink(path) + sink, err := _sinkRegistry.newSink(path) if err != nil { - openErr = multierr.Append(openErr, fmt.Errorf("couldn't open sink %q: %v", path, err)) + openErr = multierr.Append(openErr, fmt.Errorf("open sink %q: %w", path, err)) continue } writers = append(writers, sink) closers = append(closers, sink) } if openErr != nil { - close() - return writers, nil, openErr + closeAll() + return nil, nil, openErr } - return writers, close, nil + return writers, closeAll, nil } // CombineWriteSyncers is a utility that combines multiple WriteSyncers into a @@ -93,7 +92,7 @@ func open(paths []string) ([]zapcore.WriteSyncer, func(), error) { // using zapcore.NewMultiWriteSyncer and zapcore.Lock individually. func CombineWriteSyncers(writers ...zapcore.WriteSyncer) zapcore.WriteSyncer { if len(writers) == 0 { - return zapcore.AddSync(ioutil.Discard) + return zapcore.AddSync(io.Discard) } return zapcore.Lock(zapcore.NewMultiWriteSyncer(writers...)) } diff --git a/vendor/go.uber.org/zap/zapcore/buffered_write_syncer.go b/vendor/go.uber.org/zap/zapcore/buffered_write_syncer.go index ef2f7d963..a40e93b3e 100644 --- a/vendor/go.uber.org/zap/zapcore/buffered_write_syncer.go +++ b/vendor/go.uber.org/zap/zapcore/buffered_write_syncer.go @@ -43,6 +43,37 @@ const ( // // BufferedWriteSyncer is safe for concurrent use. You don't need to use // zapcore.Lock for WriteSyncers with BufferedWriteSyncer. +// +// To set up a BufferedWriteSyncer, construct a WriteSyncer for your log +// destination (*os.File is a valid WriteSyncer), wrap it with +// BufferedWriteSyncer, and defer a Stop() call for when you no longer need the +// object. +// +// func main() { +// ws := ... // your log destination +// bws := &zapcore.BufferedWriteSyncer{WS: ws} +// defer bws.Stop() +// +// // ... +// core := zapcore.NewCore(enc, bws, lvl) +// logger := zap.New(core) +// +// // ... +// } +// +// By default, a BufferedWriteSyncer will buffer up to 256 kilobytes of logs, +// waiting at most 30 seconds between flushes. +// You can customize these parameters by setting the Size or FlushInterval +// fields. +// For example, the following buffers up to 512 kB of logs before flushing them +// to Stderr, with a maximum of one minute between each flush. +// +// ws := &BufferedWriteSyncer{ +// WS: os.Stderr, +// Size: 512 * 1024, // 512 kB +// FlushInterval: time.Minute, +// } +// defer ws.Stop() type BufferedWriteSyncer struct { // WS is the WriteSyncer around which BufferedWriteSyncer will buffer // writes. diff --git a/vendor/go.uber.org/zap/zapcore/clock.go b/vendor/go.uber.org/zap/zapcore/clock.go index d2ea95b39..422fd82a6 100644 --- a/vendor/go.uber.org/zap/zapcore/clock.go +++ b/vendor/go.uber.org/zap/zapcore/clock.go @@ -20,9 +20,7 @@ package zapcore -import ( - "time" -) +import "time" // DefaultClock is the default clock used by Zap in operations that require // time. This clock uses the system clock for all operations. diff --git a/vendor/go.uber.org/zap/zapcore/console_encoder.go b/vendor/go.uber.org/zap/zapcore/console_encoder.go index 2307af404..8ca0bfaf5 100644 --- a/vendor/go.uber.org/zap/zapcore/console_encoder.go +++ b/vendor/go.uber.org/zap/zapcore/console_encoder.go @@ -22,20 +22,20 @@ package zapcore import ( "fmt" - "sync" "go.uber.org/zap/buffer" "go.uber.org/zap/internal/bufferpool" + "go.uber.org/zap/internal/pool" ) -var _sliceEncoderPool = sync.Pool{ - New: func() interface{} { - return &sliceArrayEncoder{elems: make([]interface{}, 0, 2)} - }, -} +var _sliceEncoderPool = pool.New(func() *sliceArrayEncoder { + return &sliceArrayEncoder{ + elems: make([]interface{}, 0, 2), + } +}) func getSliceEncoder() *sliceArrayEncoder { - return _sliceEncoderPool.Get().(*sliceArrayEncoder) + return _sliceEncoderPool.Get() } func putSliceEncoder(e *sliceArrayEncoder) { @@ -125,11 +125,7 @@ func (c consoleEncoder) EncodeEntry(ent Entry, fields []Field) (*buffer.Buffer, line.AppendString(ent.Stack) } - if c.LineEnding != "" { - line.AppendString(c.LineEnding) - } else { - line.AppendString(DefaultLineEnding) - } + line.AppendString(c.LineEnding) return line, nil } diff --git a/vendor/go.uber.org/zap/zapcore/core.go b/vendor/go.uber.org/zap/zapcore/core.go index a1ef8b034..776e93f6f 100644 --- a/vendor/go.uber.org/zap/zapcore/core.go +++ b/vendor/go.uber.org/zap/zapcore/core.go @@ -69,6 +69,15 @@ type ioCore struct { out WriteSyncer } +var ( + _ Core = (*ioCore)(nil) + _ leveledEnabler = (*ioCore)(nil) +) + +func (c *ioCore) Level() Level { + return LevelOf(c.LevelEnabler) +} + func (c *ioCore) With(fields []Field) Core { clone := c.clone() addFields(clone.enc, fields) @@ -93,9 +102,9 @@ func (c *ioCore) Write(ent Entry, fields []Field) error { return err } if ent.Level > ErrorLevel { - // Since we may be crashing the program, sync the output. Ignore Sync - // errors, pending a clean solution to issue #370. - c.Sync() + // Since we may be crashing the program, sync the output. + // Ignore Sync errors, pending a clean solution to issue #370. + _ = c.Sync() } return nil } diff --git a/vendor/go.uber.org/zap/zapcore/encoder.go b/vendor/go.uber.org/zap/zapcore/encoder.go index 6601ca166..5769ff3e4 100644 --- a/vendor/go.uber.org/zap/zapcore/encoder.go +++ b/vendor/go.uber.org/zap/zapcore/encoder.go @@ -22,6 +22,7 @@ package zapcore import ( "encoding/json" + "io" "time" "go.uber.org/zap/buffer" @@ -187,10 +188,13 @@ func (e *TimeEncoder) UnmarshalText(text []byte) error { // UnmarshalYAML unmarshals YAML to a TimeEncoder. // If value is an object with a "layout" field, it will be unmarshaled to TimeEncoder with given layout. -// timeEncoder: -// layout: 06/01/02 03:04pm +// +// timeEncoder: +// layout: 06/01/02 03:04pm +// // If value is string, it uses UnmarshalText. -// timeEncoder: iso8601 +// +// timeEncoder: iso8601 func (e *TimeEncoder) UnmarshalYAML(unmarshal func(interface{}) error) error { var o struct { Layout string `json:"layout" yaml:"layout"` @@ -312,14 +316,15 @@ func (e *NameEncoder) UnmarshalText(text []byte) error { type EncoderConfig struct { // Set the keys used for each log entry. If any key is empty, that portion // of the entry is omitted. - MessageKey string `json:"messageKey" yaml:"messageKey"` - LevelKey string `json:"levelKey" yaml:"levelKey"` - TimeKey string `json:"timeKey" yaml:"timeKey"` - NameKey string `json:"nameKey" yaml:"nameKey"` - CallerKey string `json:"callerKey" yaml:"callerKey"` - FunctionKey string `json:"functionKey" yaml:"functionKey"` - StacktraceKey string `json:"stacktraceKey" yaml:"stacktraceKey"` - LineEnding string `json:"lineEnding" yaml:"lineEnding"` + MessageKey string `json:"messageKey" yaml:"messageKey"` + LevelKey string `json:"levelKey" yaml:"levelKey"` + TimeKey string `json:"timeKey" yaml:"timeKey"` + NameKey string `json:"nameKey" yaml:"nameKey"` + CallerKey string `json:"callerKey" yaml:"callerKey"` + FunctionKey string `json:"functionKey" yaml:"functionKey"` + StacktraceKey string `json:"stacktraceKey" yaml:"stacktraceKey"` + SkipLineEnding bool `json:"skipLineEnding" yaml:"skipLineEnding"` + LineEnding string `json:"lineEnding" yaml:"lineEnding"` // Configure the primitive representations of common complex types. For // example, some users may want all time.Times serialized as floating-point // seconds since epoch, while others may prefer ISO8601 strings. @@ -330,6 +335,9 @@ type EncoderConfig struct { // Unlike the other primitive type encoders, EncodeName is optional. The // zero value falls back to FullNameEncoder. EncodeName NameEncoder `json:"nameEncoder" yaml:"nameEncoder"` + // Configure the encoder for interface{} type objects. + // If not provided, objects are encoded using json.Encoder + NewReflectedEncoder func(io.Writer) ReflectedEncoder `json:"-" yaml:"-"` // Configures the field separator used by the console encoder. Defaults // to tab. ConsoleSeparator string `json:"consoleSeparator" yaml:"consoleSeparator"` diff --git a/vendor/go.uber.org/zap/zapcore/entry.go b/vendor/go.uber.org/zap/zapcore/entry.go index 0885505b7..459a5d7ce 100644 --- a/vendor/go.uber.org/zap/zapcore/entry.go +++ b/vendor/go.uber.org/zap/zapcore/entry.go @@ -24,26 +24,23 @@ import ( "fmt" "runtime" "strings" - "sync" "time" + "go.uber.org/multierr" "go.uber.org/zap/internal/bufferpool" "go.uber.org/zap/internal/exit" - - "go.uber.org/multierr" + "go.uber.org/zap/internal/pool" ) -var ( - _cePool = sync.Pool{New: func() interface{} { - // Pre-allocate some space for cores. - return &CheckedEntry{ - cores: make([]Core, 4), - } - }} -) +var _cePool = pool.New(func() *CheckedEntry { + // Pre-allocate some space for cores. + return &CheckedEntry{ + cores: make([]Core, 4), + } +}) func getCheckedEntry() *CheckedEntry { - ce := _cePool.Get().(*CheckedEntry) + ce := _cePool.Get() ce.reset() return ce } @@ -152,6 +149,27 @@ type Entry struct { Stack string } +// CheckWriteHook is a custom action that may be executed after an entry is +// written. +// +// Register one on a CheckedEntry with the After method. +// +// if ce := logger.Check(...); ce != nil { +// ce = ce.After(hook) +// ce.Write(...) +// } +// +// You can configure the hook for Fatal log statements at the logger level with +// the zap.WithFatalHook option. +type CheckWriteHook interface { + // OnWrite is invoked with the CheckedEntry that was written and a list + // of fields added with that entry. + // + // The list of fields DOES NOT include fields that were already added + // to the logger with the With method. + OnWrite(*CheckedEntry, []Field) +} + // CheckWriteAction indicates what action to take after a log entry is // processed. Actions are ordered in increasing severity. type CheckWriteAction uint8 @@ -164,21 +182,36 @@ const ( WriteThenGoexit // WriteThenPanic causes a panic after Write. WriteThenPanic - // WriteThenFatal causes a fatal os.Exit after Write. + // WriteThenFatal causes an os.Exit(1) after Write. WriteThenFatal ) +// OnWrite implements the OnWrite method to keep CheckWriteAction compatible +// with the new CheckWriteHook interface which deprecates CheckWriteAction. +func (a CheckWriteAction) OnWrite(ce *CheckedEntry, _ []Field) { + switch a { + case WriteThenGoexit: + runtime.Goexit() + case WriteThenPanic: + panic(ce.Message) + case WriteThenFatal: + exit.With(1) + } +} + +var _ CheckWriteHook = CheckWriteAction(0) + // CheckedEntry is an Entry together with a collection of Cores that have // already agreed to log it. // -// CheckedEntry references should be created by calling AddCore or Should on a +// CheckedEntry references should be created by calling AddCore or After on a // nil *CheckedEntry. References are returned to a pool after Write, and MUST // NOT be retained after calling their Write method. type CheckedEntry struct { Entry ErrorOutput WriteSyncer dirty bool // best-effort detection of pool misuse - should CheckWriteAction + after CheckWriteHook cores []Core } @@ -186,7 +219,7 @@ func (ce *CheckedEntry) reset() { ce.Entry = Entry{} ce.ErrorOutput = nil ce.dirty = false - ce.should = WriteThenNoop + ce.after = nil for i := range ce.cores { // don't keep references to cores ce.cores[i] = nil @@ -209,7 +242,7 @@ func (ce *CheckedEntry) Write(fields ...Field) { // CheckedEntry is being used after it was returned to the pool, // the message may be an amalgamation from multiple call sites. fmt.Fprintf(ce.ErrorOutput, "%v Unsafe CheckedEntry re-use near Entry %+v.\n", ce.Time, ce.Entry) - ce.ErrorOutput.Sync() + _ = ce.ErrorOutput.Sync() // ignore error } return } @@ -221,20 +254,14 @@ func (ce *CheckedEntry) Write(fields ...Field) { } if err != nil && ce.ErrorOutput != nil { fmt.Fprintf(ce.ErrorOutput, "%v write error: %v\n", ce.Time, err) - ce.ErrorOutput.Sync() + _ = ce.ErrorOutput.Sync() // ignore error } - should, msg := ce.should, ce.Message - putCheckedEntry(ce) - - switch should { - case WriteThenPanic: - panic(msg) - case WriteThenFatal: - exit.Exit() - case WriteThenGoexit: - runtime.Goexit() + hook := ce.after + if hook != nil { + hook.OnWrite(ce, fields) } + putCheckedEntry(ce) } // AddCore adds a Core that has agreed to log this CheckedEntry. It's intended to be @@ -252,11 +279,20 @@ func (ce *CheckedEntry) AddCore(ent Entry, core Core) *CheckedEntry { // Should sets this CheckedEntry's CheckWriteAction, which controls whether a // Core will panic or fatal after writing this log entry. Like AddCore, it's // safe to call on nil CheckedEntry references. +// +// Deprecated: Use [CheckedEntry.After] instead. func (ce *CheckedEntry) Should(ent Entry, should CheckWriteAction) *CheckedEntry { + return ce.After(ent, should) +} + +// After sets this CheckEntry's CheckWriteHook, which will be called after this +// log entry has been written. It's safe to call this on nil CheckedEntry +// references. +func (ce *CheckedEntry) After(ent Entry, hook CheckWriteHook) *CheckedEntry { if ce == nil { ce = getCheckedEntry() ce.Entry = ent } - ce.should = should + ce.after = hook return ce } diff --git a/vendor/go.uber.org/zap/zapcore/error.go b/vendor/go.uber.org/zap/zapcore/error.go index 74919b0cc..c40df1326 100644 --- a/vendor/go.uber.org/zap/zapcore/error.go +++ b/vendor/go.uber.org/zap/zapcore/error.go @@ -23,7 +23,8 @@ package zapcore import ( "fmt" "reflect" - "sync" + + "go.uber.org/zap/internal/pool" ) // Encodes the given error into fields of an object. A field with the given @@ -36,13 +37,13 @@ import ( // causer (from github.com/pkg/errors), a ${key}Causes field is added with an // array of objects containing the errors this error was comprised of. // -// { -// "error": err.Error(), -// "errorVerbose": fmt.Sprintf("%+v", err), -// "errorCauses": [ -// ... -// ], -// } +// { +// "error": err.Error(), +// "errorVerbose": fmt.Sprintf("%+v", err), +// "errorCauses": [ +// ... +// ], +// } func encodeError(key string, err error, enc ObjectEncoder) (retErr error) { // Try to capture panics (from nil references or otherwise) when calling // the Error() method @@ -97,15 +98,18 @@ func (errs errArray) MarshalLogArray(arr ArrayEncoder) error { } el := newErrArrayElem(errs[i]) - arr.AppendObject(el) + err := arr.AppendObject(el) el.Free() + if err != nil { + return err + } } return nil } -var _errArrayElemPool = sync.Pool{New: func() interface{} { +var _errArrayElemPool = pool.New(func() *errArrayElem { return &errArrayElem{} -}} +}) // Encodes any error into a {"error": ...} re-using the same errors logic. // @@ -113,7 +117,7 @@ var _errArrayElemPool = sync.Pool{New: func() interface{} { type errArrayElem struct{ err error } func newErrArrayElem(err error) *errArrayElem { - e := _errArrayElemPool.Get().(*errArrayElem) + e := _errArrayElemPool.Get() e.err = err return e } diff --git a/vendor/go.uber.org/zap/zapcore/hook.go b/vendor/go.uber.org/zap/zapcore/hook.go index 5db4afb30..198def991 100644 --- a/vendor/go.uber.org/zap/zapcore/hook.go +++ b/vendor/go.uber.org/zap/zapcore/hook.go @@ -27,6 +27,11 @@ type hooked struct { funcs []func(Entry) error } +var ( + _ Core = (*hooked)(nil) + _ leveledEnabler = (*hooked)(nil) +) + // RegisterHooks wraps a Core and runs a collection of user-defined callback // hooks each time a message is logged. Execution of the callbacks is blocking. // @@ -40,6 +45,10 @@ func RegisterHooks(core Core, hooks ...func(Entry) error) Core { } } +func (h *hooked) Level() Level { + return LevelOf(h.Core) +} + func (h *hooked) Check(ent Entry, ce *CheckedEntry) *CheckedEntry { // Let the wrapped Core decide whether to log this message or not. This // also gives the downstream a chance to register itself directly with the diff --git a/vendor/go.uber.org/zap/zapcore/increase_level.go b/vendor/go.uber.org/zap/zapcore/increase_level.go index 5a1749261..7a11237ae 100644 --- a/vendor/go.uber.org/zap/zapcore/increase_level.go +++ b/vendor/go.uber.org/zap/zapcore/increase_level.go @@ -27,6 +27,11 @@ type levelFilterCore struct { level LevelEnabler } +var ( + _ Core = (*levelFilterCore)(nil) + _ leveledEnabler = (*levelFilterCore)(nil) +) + // NewIncreaseLevelCore creates a core that can be used to increase the level of // an existing Core. It cannot be used to decrease the logging level, as it acts // as a filter before calling the underlying core. If level decreases the log level, @@ -45,6 +50,10 @@ func (c *levelFilterCore) Enabled(lvl Level) bool { return c.level.Enabled(lvl) } +func (c *levelFilterCore) Level() Level { + return LevelOf(c.level) +} + func (c *levelFilterCore) With(fields []Field) Core { return &levelFilterCore{c.core.With(fields), c.level} } diff --git a/vendor/go.uber.org/zap/zapcore/json_encoder.go b/vendor/go.uber.org/zap/zapcore/json_encoder.go index 5cf7d917e..c8ab86979 100644 --- a/vendor/go.uber.org/zap/zapcore/json_encoder.go +++ b/vendor/go.uber.org/zap/zapcore/json_encoder.go @@ -22,26 +22,21 @@ package zapcore import ( "encoding/base64" - "encoding/json" "math" - "sync" "time" "unicode/utf8" "go.uber.org/zap/buffer" "go.uber.org/zap/internal/bufferpool" + "go.uber.org/zap/internal/pool" ) // For JSON-escaping; see jsonEncoder.safeAddString below. const _hex = "0123456789abcdef" -var _jsonPool = sync.Pool{New: func() interface{} { +var _jsonPool = pool.New(func() *jsonEncoder { return &jsonEncoder{} -}} - -func getJSONEncoder() *jsonEncoder { - return _jsonPool.Get().(*jsonEncoder) -} +}) func putJSONEncoder(enc *jsonEncoder) { if enc.reflectBuf != nil { @@ -64,7 +59,7 @@ type jsonEncoder struct { // for encoding generic values by reflection reflectBuf *buffer.Buffer - reflectEnc *json.Encoder + reflectEnc ReflectedEncoder } // NewJSONEncoder creates a fast, low-allocation JSON encoder. The encoder @@ -72,7 +67,9 @@ type jsonEncoder struct { // // Note that the encoder doesn't deduplicate keys, so it's possible to produce // a message like -// {"foo":"bar","foo":"baz"} +// +// {"foo":"bar","foo":"baz"} +// // This is permitted by the JSON specification, but not encouraged. Many // libraries will ignore duplicate key-value pairs (typically keeping the last // pair) when unmarshaling, but users should attempt to avoid adding duplicate @@ -82,6 +79,17 @@ func NewJSONEncoder(cfg EncoderConfig) Encoder { } func newJSONEncoder(cfg EncoderConfig, spaced bool) *jsonEncoder { + if cfg.SkipLineEnding { + cfg.LineEnding = "" + } else if cfg.LineEnding == "" { + cfg.LineEnding = DefaultLineEnding + } + + // If no EncoderConfig.NewReflectedEncoder is provided by the user, then use default + if cfg.NewReflectedEncoder == nil { + cfg.NewReflectedEncoder = defaultReflectedEncoder + } + return &jsonEncoder{ EncoderConfig: &cfg, buf: bufferpool.Get(), @@ -118,6 +126,11 @@ func (enc *jsonEncoder) AddComplex128(key string, val complex128) { enc.AppendComplex128(val) } +func (enc *jsonEncoder) AddComplex64(key string, val complex64) { + enc.addKey(key) + enc.AppendComplex64(val) +} + func (enc *jsonEncoder) AddDuration(key string, val time.Duration) { enc.addKey(key) enc.AppendDuration(val) @@ -128,6 +141,11 @@ func (enc *jsonEncoder) AddFloat64(key string, val float64) { enc.AppendFloat64(val) } +func (enc *jsonEncoder) AddFloat32(key string, val float32) { + enc.addKey(key) + enc.AppendFloat32(val) +} + func (enc *jsonEncoder) AddInt64(key string, val int64) { enc.addKey(key) enc.AppendInt64(val) @@ -136,10 +154,7 @@ func (enc *jsonEncoder) AddInt64(key string, val int64) { func (enc *jsonEncoder) resetReflectBuf() { if enc.reflectBuf == nil { enc.reflectBuf = bufferpool.Get() - enc.reflectEnc = json.NewEncoder(enc.reflectBuf) - - // For consistency with our custom JSON encoder. - enc.reflectEnc.SetEscapeHTML(false) + enc.reflectEnc = enc.NewReflectedEncoder(enc.reflectBuf) } else { enc.reflectBuf.Reset() } @@ -201,10 +216,16 @@ func (enc *jsonEncoder) AppendArray(arr ArrayMarshaler) error { } func (enc *jsonEncoder) AppendObject(obj ObjectMarshaler) error { + // Close ONLY new openNamespaces that are created during + // AppendObject(). + old := enc.openNamespaces + enc.openNamespaces = 0 enc.addElementSeparator() enc.buf.AppendByte('{') err := obj.MarshalLogObject(enc) enc.buf.AppendByte('}') + enc.closeOpenNamespaces() + enc.openNamespaces = old return err } @@ -220,16 +241,23 @@ func (enc *jsonEncoder) AppendByteString(val []byte) { enc.buf.AppendByte('"') } -func (enc *jsonEncoder) AppendComplex128(val complex128) { +// appendComplex appends the encoded form of the provided complex128 value. +// precision specifies the encoding precision for the real and imaginary +// components of the complex number. +func (enc *jsonEncoder) appendComplex(val complex128, precision int) { enc.addElementSeparator() // Cast to a platform-independent, fixed-size type. r, i := float64(real(val)), float64(imag(val)) enc.buf.AppendByte('"') // Because we're always in a quoted string, we can use strconv without // special-casing NaN and +/-Inf. - enc.buf.AppendFloat(r, 64) - enc.buf.AppendByte('+') - enc.buf.AppendFloat(i, 64) + enc.buf.AppendFloat(r, precision) + // If imaginary part is less than 0, minus (-) sign is added by default + // by AppendFloat. + if i >= 0 { + enc.buf.AppendByte('+') + } + enc.buf.AppendFloat(i, precision) enc.buf.AppendByte('i') enc.buf.AppendByte('"') } @@ -292,29 +320,28 @@ func (enc *jsonEncoder) AppendUint64(val uint64) { enc.buf.AppendUint(val) } -func (enc *jsonEncoder) AddComplex64(k string, v complex64) { enc.AddComplex128(k, complex128(v)) } -func (enc *jsonEncoder) AddFloat32(k string, v float32) { enc.AddFloat64(k, float64(v)) } -func (enc *jsonEncoder) AddInt(k string, v int) { enc.AddInt64(k, int64(v)) } -func (enc *jsonEncoder) AddInt32(k string, v int32) { enc.AddInt64(k, int64(v)) } -func (enc *jsonEncoder) AddInt16(k string, v int16) { enc.AddInt64(k, int64(v)) } -func (enc *jsonEncoder) AddInt8(k string, v int8) { enc.AddInt64(k, int64(v)) } -func (enc *jsonEncoder) AddUint(k string, v uint) { enc.AddUint64(k, uint64(v)) } -func (enc *jsonEncoder) AddUint32(k string, v uint32) { enc.AddUint64(k, uint64(v)) } -func (enc *jsonEncoder) AddUint16(k string, v uint16) { enc.AddUint64(k, uint64(v)) } -func (enc *jsonEncoder) AddUint8(k string, v uint8) { enc.AddUint64(k, uint64(v)) } -func (enc *jsonEncoder) AddUintptr(k string, v uintptr) { enc.AddUint64(k, uint64(v)) } -func (enc *jsonEncoder) AppendComplex64(v complex64) { enc.AppendComplex128(complex128(v)) } -func (enc *jsonEncoder) AppendFloat64(v float64) { enc.appendFloat(v, 64) } -func (enc *jsonEncoder) AppendFloat32(v float32) { enc.appendFloat(float64(v), 32) } -func (enc *jsonEncoder) AppendInt(v int) { enc.AppendInt64(int64(v)) } -func (enc *jsonEncoder) AppendInt32(v int32) { enc.AppendInt64(int64(v)) } -func (enc *jsonEncoder) AppendInt16(v int16) { enc.AppendInt64(int64(v)) } -func (enc *jsonEncoder) AppendInt8(v int8) { enc.AppendInt64(int64(v)) } -func (enc *jsonEncoder) AppendUint(v uint) { enc.AppendUint64(uint64(v)) } -func (enc *jsonEncoder) AppendUint32(v uint32) { enc.AppendUint64(uint64(v)) } -func (enc *jsonEncoder) AppendUint16(v uint16) { enc.AppendUint64(uint64(v)) } -func (enc *jsonEncoder) AppendUint8(v uint8) { enc.AppendUint64(uint64(v)) } -func (enc *jsonEncoder) AppendUintptr(v uintptr) { enc.AppendUint64(uint64(v)) } +func (enc *jsonEncoder) AddInt(k string, v int) { enc.AddInt64(k, int64(v)) } +func (enc *jsonEncoder) AddInt32(k string, v int32) { enc.AddInt64(k, int64(v)) } +func (enc *jsonEncoder) AddInt16(k string, v int16) { enc.AddInt64(k, int64(v)) } +func (enc *jsonEncoder) AddInt8(k string, v int8) { enc.AddInt64(k, int64(v)) } +func (enc *jsonEncoder) AddUint(k string, v uint) { enc.AddUint64(k, uint64(v)) } +func (enc *jsonEncoder) AddUint32(k string, v uint32) { enc.AddUint64(k, uint64(v)) } +func (enc *jsonEncoder) AddUint16(k string, v uint16) { enc.AddUint64(k, uint64(v)) } +func (enc *jsonEncoder) AddUint8(k string, v uint8) { enc.AddUint64(k, uint64(v)) } +func (enc *jsonEncoder) AddUintptr(k string, v uintptr) { enc.AddUint64(k, uint64(v)) } +func (enc *jsonEncoder) AppendComplex64(v complex64) { enc.appendComplex(complex128(v), 32) } +func (enc *jsonEncoder) AppendComplex128(v complex128) { enc.appendComplex(complex128(v), 64) } +func (enc *jsonEncoder) AppendFloat64(v float64) { enc.appendFloat(v, 64) } +func (enc *jsonEncoder) AppendFloat32(v float32) { enc.appendFloat(float64(v), 32) } +func (enc *jsonEncoder) AppendInt(v int) { enc.AppendInt64(int64(v)) } +func (enc *jsonEncoder) AppendInt32(v int32) { enc.AppendInt64(int64(v)) } +func (enc *jsonEncoder) AppendInt16(v int16) { enc.AppendInt64(int64(v)) } +func (enc *jsonEncoder) AppendInt8(v int8) { enc.AppendInt64(int64(v)) } +func (enc *jsonEncoder) AppendUint(v uint) { enc.AppendUint64(uint64(v)) } +func (enc *jsonEncoder) AppendUint32(v uint32) { enc.AppendUint64(uint64(v)) } +func (enc *jsonEncoder) AppendUint16(v uint16) { enc.AppendUint64(uint64(v)) } +func (enc *jsonEncoder) AppendUint8(v uint8) { enc.AppendUint64(uint64(v)) } +func (enc *jsonEncoder) AppendUintptr(v uintptr) { enc.AppendUint64(uint64(v)) } func (enc *jsonEncoder) Clone() Encoder { clone := enc.clone() @@ -323,7 +350,7 @@ func (enc *jsonEncoder) Clone() Encoder { } func (enc *jsonEncoder) clone() *jsonEncoder { - clone := getJSONEncoder() + clone := _jsonPool.Get() clone.EncoderConfig = enc.EncoderConfig clone.spaced = enc.spaced clone.openNamespaces = enc.openNamespaces @@ -335,7 +362,7 @@ func (enc *jsonEncoder) EncodeEntry(ent Entry, fields []Field) (*buffer.Buffer, final := enc.clone() final.buf.AppendByte('{') - if final.LevelKey != "" { + if final.LevelKey != "" && final.EncodeLevel != nil { final.addKey(final.LevelKey) cur := final.buf.Len() final.EncodeLevel(ent.Level, final) @@ -396,11 +423,7 @@ func (enc *jsonEncoder) EncodeEntry(ent Entry, fields []Field) (*buffer.Buffer, final.AddString(final.StacktraceKey, ent.Stack) } final.buf.AppendByte('}') - if final.LineEnding != "" { - final.buf.AppendString(final.LineEnding) - } else { - final.buf.AppendString(DefaultLineEnding) - } + final.buf.AppendString(final.LineEnding) ret := final.buf putJSONEncoder(final) @@ -415,6 +438,7 @@ func (enc *jsonEncoder) closeOpenNamespaces() { for i := 0; i < enc.openNamespaces; i++ { enc.buf.AppendByte('}') } + enc.openNamespaces = 0 } func (enc *jsonEncoder) addKey(key string) { @@ -462,73 +486,98 @@ func (enc *jsonEncoder) appendFloat(val float64, bitSize int) { // Unlike the standard library's encoder, it doesn't attempt to protect the // user from browser vulnerabilities or JSONP-related problems. func (enc *jsonEncoder) safeAddString(s string) { - for i := 0; i < len(s); { - if enc.tryAddRuneSelf(s[i]) { - i++ - continue - } - r, size := utf8.DecodeRuneInString(s[i:]) - if enc.tryAddRuneError(r, size) { - i++ - continue - } - enc.buf.AppendString(s[i : i+size]) - i += size - } + safeAppendStringLike( + (*buffer.Buffer).AppendString, + utf8.DecodeRuneInString, + enc.buf, + s, + ) } // safeAddByteString is no-alloc equivalent of safeAddString(string(s)) for s []byte. func (enc *jsonEncoder) safeAddByteString(s []byte) { + safeAppendStringLike( + (*buffer.Buffer).AppendBytes, + utf8.DecodeRune, + enc.buf, + s, + ) +} + +// safeAppendStringLike is a generic implementation of safeAddString and safeAddByteString. +// It appends a string or byte slice to the buffer, escaping all special characters. +func safeAppendStringLike[S []byte | string]( + // appendTo appends this string-like object to the buffer. + appendTo func(*buffer.Buffer, S), + // decodeRune decodes the next rune from the string-like object + // and returns its value and width in bytes. + decodeRune func(S) (rune, int), + buf *buffer.Buffer, + s S, +) { + // The encoding logic below works by skipping over characters + // that can be safely copied as-is, + // until a character is found that needs special handling. + // At that point, we copy everything we've seen so far, + // and then handle that special character. + // + // last is the index of the last byte that was copied to the buffer. + last := 0 for i := 0; i < len(s); { - if enc.tryAddRuneSelf(s[i]) { + if s[i] >= utf8.RuneSelf { + // Character >= RuneSelf may be part of a multi-byte rune. + // They need to be decoded before we can decide how to handle them. + r, size := decodeRune(s[i:]) + if r != utf8.RuneError || size != 1 { + // No special handling required. + // Skip over this rune and continue. + i += size + continue + } + + // Invalid UTF-8 sequence. + // Replace it with the Unicode replacement character. + appendTo(buf, s[last:i]) + buf.AppendString(`\ufffd`) + i++ - continue - } - r, size := utf8.DecodeRune(s[i:]) - if enc.tryAddRuneError(r, size) { + last = i + } else { + // Character < RuneSelf is a single-byte UTF-8 rune. + if s[i] >= 0x20 && s[i] != '\\' && s[i] != '"' { + // No escaping necessary. + // Skip over this character and continue. + i++ + continue + } + + // This character needs to be escaped. + appendTo(buf, s[last:i]) + switch s[i] { + case '\\', '"': + buf.AppendByte('\\') + buf.AppendByte(s[i]) + case '\n': + buf.AppendByte('\\') + buf.AppendByte('n') + case '\r': + buf.AppendByte('\\') + buf.AppendByte('r') + case '\t': + buf.AppendByte('\\') + buf.AppendByte('t') + default: + // Encode bytes < 0x20, except for the escape sequences above. + buf.AppendString(`\u00`) + buf.AppendByte(_hex[s[i]>>4]) + buf.AppendByte(_hex[s[i]&0xF]) + } + i++ - continue + last = i } - enc.buf.Write(s[i : i+size]) - i += size - } -} - -// tryAddRuneSelf appends b if it is valid UTF-8 character represented in a single byte. -func (enc *jsonEncoder) tryAddRuneSelf(b byte) bool { - if b >= utf8.RuneSelf { - return false } - if 0x20 <= b && b != '\\' && b != '"' { - enc.buf.AppendByte(b) - return true - } - switch b { - case '\\', '"': - enc.buf.AppendByte('\\') - enc.buf.AppendByte(b) - case '\n': - enc.buf.AppendByte('\\') - enc.buf.AppendByte('n') - case '\r': - enc.buf.AppendByte('\\') - enc.buf.AppendByte('r') - case '\t': - enc.buf.AppendByte('\\') - enc.buf.AppendByte('t') - default: - // Encode bytes < 0x20, except for the escape sequences above. - enc.buf.AppendString(`\u00`) - enc.buf.AppendByte(_hex[b>>4]) - enc.buf.AppendByte(_hex[b&0xF]) - } - return true -} -func (enc *jsonEncoder) tryAddRuneError(r rune, size int) bool { - if r == utf8.RuneError && size == 1 { - enc.buf.AppendString(`\ufffd`) - return true - } - return false + // add remaining + appendTo(buf, s[last:]) } diff --git a/vendor/go.uber.org/zap/zapcore/lazy_with.go b/vendor/go.uber.org/zap/zapcore/lazy_with.go new file mode 100644 index 000000000..05288d6a8 --- /dev/null +++ b/vendor/go.uber.org/zap/zapcore/lazy_with.go @@ -0,0 +1,54 @@ +// Copyright (c) 2023 Uber Technologies, Inc. +// +// 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. + +package zapcore + +import "sync" + +type lazyWithCore struct { + Core + sync.Once + fields []Field +} + +// NewLazyWith wraps a Core with a "lazy" Core that will only encode fields if +// the logger is written to (or is further chained in a lon-lazy manner). +func NewLazyWith(core Core, fields []Field) Core { + return &lazyWithCore{ + Core: core, + fields: fields, + } +} + +func (d *lazyWithCore) initOnce() { + d.Once.Do(func() { + d.Core = d.Core.With(d.fields) + }) +} + +func (d *lazyWithCore) With(fields []Field) Core { + d.initOnce() + return d.Core.With(fields) +} + +func (d *lazyWithCore) Check(e Entry, ce *CheckedEntry) *CheckedEntry { + d.initOnce() + return d.Core.Check(e, ce) +} diff --git a/vendor/go.uber.org/zap/zapcore/level.go b/vendor/go.uber.org/zap/zapcore/level.go index e575c9f43..e01a24131 100644 --- a/vendor/go.uber.org/zap/zapcore/level.go +++ b/vendor/go.uber.org/zap/zapcore/level.go @@ -53,8 +53,62 @@ const ( _minLevel = DebugLevel _maxLevel = FatalLevel + + // InvalidLevel is an invalid value for Level. + // + // Core implementations may panic if they see messages of this level. + InvalidLevel = _maxLevel + 1 ) +// ParseLevel parses a level based on the lower-case or all-caps ASCII +// representation of the log level. If the provided ASCII representation is +// invalid an error is returned. +// +// This is particularly useful when dealing with text input to configure log +// levels. +func ParseLevel(text string) (Level, error) { + var level Level + err := level.UnmarshalText([]byte(text)) + return level, err +} + +type leveledEnabler interface { + LevelEnabler + + Level() Level +} + +// LevelOf reports the minimum enabled log level for the given LevelEnabler +// from Zap's supported log levels, or [InvalidLevel] if none of them are +// enabled. +// +// A LevelEnabler may implement a 'Level() Level' method to override the +// behavior of this function. +// +// func (c *core) Level() Level { +// return c.currentLevel +// } +// +// It is recommended that [Core] implementations that wrap other cores use +// LevelOf to retrieve the level of the wrapped core. For example, +// +// func (c *coreWrapper) Level() Level { +// return zapcore.LevelOf(c.wrappedCore) +// } +func LevelOf(enab LevelEnabler) Level { + if lvler, ok := enab.(leveledEnabler); ok { + return lvler.Level() + } + + for lvl := _minLevel; lvl <= _maxLevel; lvl++ { + if enab.Enabled(lvl) { + return lvl + } + } + + return InvalidLevel +} + // String returns a lower-case ASCII representation of the log level. func (l Level) String() string { switch l { diff --git a/vendor/go.uber.org/zap/zapcore/reflected_encoder.go b/vendor/go.uber.org/zap/zapcore/reflected_encoder.go new file mode 100644 index 000000000..8746360ec --- /dev/null +++ b/vendor/go.uber.org/zap/zapcore/reflected_encoder.go @@ -0,0 +1,41 @@ +// Copyright (c) 2016 Uber Technologies, Inc. +// +// 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. + +package zapcore + +import ( + "encoding/json" + "io" +) + +// ReflectedEncoder serializes log fields that can't be serialized with Zap's +// JSON encoder. These have the ReflectType field type. +// Use EncoderConfig.NewReflectedEncoder to set this. +type ReflectedEncoder interface { + // Encode encodes and writes to the underlying data stream. + Encode(interface{}) error +} + +func defaultReflectedEncoder(w io.Writer) ReflectedEncoder { + enc := json.NewEncoder(w) + // For consistency with our custom JSON encoder. + enc.SetEscapeHTML(false) + return enc +} diff --git a/vendor/go.uber.org/zap/zapcore/sampler.go b/vendor/go.uber.org/zap/zapcore/sampler.go index 31ed96e12..b7c093a4f 100644 --- a/vendor/go.uber.org/zap/zapcore/sampler.go +++ b/vendor/go.uber.org/zap/zapcore/sampler.go @@ -1,4 +1,4 @@ -// Copyright (c) 2016 Uber Technologies, Inc. +// Copyright (c) 2016-2022 Uber Technologies, Inc. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -21,9 +21,8 @@ package zapcore import ( + "sync/atomic" "time" - - "go.uber.org/atomic" ) const ( @@ -66,16 +65,16 @@ func (c *counter) IncCheckReset(t time.Time, tick time.Duration) uint64 { tn := t.UnixNano() resetAfter := c.resetAt.Load() if resetAfter > tn { - return c.counter.Inc() + return c.counter.Add(1) } c.counter.Store(1) newResetAfter := tn + tick.Nanoseconds() - if !c.resetAt.CAS(resetAfter, newResetAfter) { + if !c.resetAt.CompareAndSwap(resetAfter, newResetAfter) { // We raced with another goroutine trying to reset, and it also reset // the counter to 1, so we need to reincrement the counter. - return c.counter.Inc() + return c.counter.Add(1) } return 1 @@ -113,12 +112,12 @@ func nopSamplingHook(Entry, SamplingDecision) {} // This hook may be used to get visibility into the performance of the sampler. // For example, use it to track metrics of dropped versus sampled logs. // -// var dropped atomic.Int64 -// zapcore.SamplerHook(func(ent zapcore.Entry, dec zapcore.SamplingDecision) { -// if dec&zapcore.LogDropped > 0 { -// dropped.Inc() -// } -// }) +// var dropped atomic.Int64 +// zapcore.SamplerHook(func(ent zapcore.Entry, dec zapcore.SamplingDecision) { +// if dec&zapcore.LogDropped > 0 { +// dropped.Inc() +// } +// }) func SamplerHook(hook func(entry Entry, dec SamplingDecision)) SamplerOption { return optionFunc(func(s *sampler) { s.hook = hook @@ -133,10 +132,21 @@ func SamplerHook(hook func(entry Entry, dec SamplingDecision)) SamplerOption { // each tick. If more Entries with the same level and message are seen during // the same interval, every Mth message is logged and the rest are dropped. // +// For example, +// +// core = NewSamplerWithOptions(core, time.Second, 10, 5) +// +// This will log the first 10 log entries with the same level and message +// in a one second interval as-is. Following that, it will allow through +// every 5th log entry with the same level and message in that interval. +// +// If thereafter is zero, the Core will drop all log entries after the first N +// in that interval. +// // Sampler can be configured to report sampling decisions with the SamplerHook // option. // -// Keep in mind that zap's sampling implementation is optimized for speed over +// Keep in mind that Zap's sampling implementation is optimized for speed over // absolute precision; under load, each tick may be slightly over- or // under-sampled. func NewSamplerWithOptions(core Core, tick time.Duration, first, thereafter int, opts ...SamplerOption) Core { @@ -164,6 +174,11 @@ type sampler struct { hook func(Entry, SamplingDecision) } +var ( + _ Core = (*sampler)(nil) + _ leveledEnabler = (*sampler)(nil) +) + // NewSampler creates a Core that samples incoming entries, which // caps the CPU and I/O load of logging while attempting to preserve a // representative subset of your logs. @@ -181,6 +196,10 @@ func NewSampler(core Core, tick time.Duration, first, thereafter int) Core { return NewSamplerWithOptions(core, tick, first, thereafter) } +func (s *sampler) Level() Level { + return LevelOf(s.Core) +} + func (s *sampler) With(fields []Field) Core { return &sampler{ Core: s.Core.With(fields), @@ -200,7 +219,7 @@ func (s *sampler) Check(ent Entry, ce *CheckedEntry) *CheckedEntry { if ent.Level >= _minLevel && ent.Level <= _maxLevel { counter := s.counts.get(ent.Level, ent.Message) n := counter.IncCheckReset(ent.Time, s.tick) - if n > s.first && (n-s.first)%s.thereafter != 0 { + if n > s.first && (s.thereafter == 0 || (n-s.first)%s.thereafter != 0) { s.hook(ent, LogDropped) return ce } diff --git a/vendor/go.uber.org/zap/zapcore/tee.go b/vendor/go.uber.org/zap/zapcore/tee.go index 07a32eef9..9bb32f055 100644 --- a/vendor/go.uber.org/zap/zapcore/tee.go +++ b/vendor/go.uber.org/zap/zapcore/tee.go @@ -1,4 +1,4 @@ -// Copyright (c) 2016 Uber Technologies, Inc. +// Copyright (c) 2016-2022 Uber Technologies, Inc. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -24,6 +24,11 @@ import "go.uber.org/multierr" type multiCore []Core +var ( + _ leveledEnabler = multiCore(nil) + _ Core = multiCore(nil) +) + // NewTee creates a Core that duplicates log entries into two or more // underlying Cores. // @@ -48,6 +53,16 @@ func (mc multiCore) With(fields []Field) Core { return clone } +func (mc multiCore) Level() Level { + minLvl := _maxLevel // mc is never empty + for i := range mc { + if lvl := LevelOf(mc[i]); lvl < minLvl { + minLvl = lvl + } + } + return minLvl +} + func (mc multiCore) Enabled(lvl Level) bool { for i := range mc { if mc[i].Enabled(lvl) { diff --git a/vendor/go.uber.org/zap/zapgrpc/zapgrpc.go b/vendor/go.uber.org/zap/zapgrpc/zapgrpc.go index 356e12741..6823773b7 100644 --- a/vendor/go.uber.org/zap/zapgrpc/zapgrpc.go +++ b/vendor/go.uber.org/zap/zapgrpc/zapgrpc.go @@ -30,10 +30,10 @@ import ( // See https://github.com/grpc/grpc-go/blob/v1.35.0/grpclog/loggerv2.go#L77-L86 const ( - grpcLvlInfo = 0 - grpcLvlWarn = 1 - grpcLvlError = 2 - grpcLvlFatal = 3 + grpcLvlInfo int = iota + grpcLvlWarn + grpcLvlError + grpcLvlFatal ) var ( @@ -61,6 +61,7 @@ func (f optionFunc) apply(log *Logger) { // WithDebug configures a Logger to print at zap's DebugLevel instead of // InfoLevel. // It only affects the Printf, Println and Print methods, which are only used in the gRPC v1 grpclog.Logger API. +// // Deprecated: use grpclog.SetLoggerV2() for v2 API. func WithDebug() Option { return optionFunc(func(logger *Logger) { @@ -146,19 +147,22 @@ type Logger struct { } // Print implements grpclog.Logger. -// Deprecated: use Info(). +// +// Deprecated: use [Logger.Info]. func (l *Logger) Print(args ...interface{}) { l.print.Print(args...) } // Printf implements grpclog.Logger. -// Deprecated: use Infof(). +// +// Deprecated: use [Logger.Infof]. func (l *Logger) Printf(format string, args ...interface{}) { l.print.Printf(format, args...) } // Println implements grpclog.Logger. -// Deprecated: use Info(). +// +// Deprecated: use [Logger.Info]. func (l *Logger) Println(args ...interface{}) { l.print.Println(args...) } diff --git a/vendor/golang.org/x/crypto/LICENSE b/vendor/golang.org/x/crypto/LICENSE index 6a66aea5e..2a7cf70da 100644 --- a/vendor/golang.org/x/crypto/LICENSE +++ b/vendor/golang.org/x/crypto/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2009 The Go Authors. All rights reserved. +Copyright 2009 The Go Authors. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are @@ -10,7 +10,7 @@ notice, this list of conditions and the following disclaimer. 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 + * Neither the name of Google LLC nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. diff --git a/vendor/golang.org/x/crypto/chacha20/chacha_noasm.go b/vendor/golang.org/x/crypto/chacha20/chacha_noasm.go index db42e6676..c709b7284 100644 --- a/vendor/golang.org/x/crypto/chacha20/chacha_noasm.go +++ b/vendor/golang.org/x/crypto/chacha20/chacha_noasm.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build (!arm64 && !s390x && !ppc64le) || !gc || purego +//go:build (!arm64 && !s390x && !ppc64 && !ppc64le) || !gc || purego package chacha20 diff --git a/vendor/golang.org/x/crypto/chacha20/chacha_ppc64le.go b/vendor/golang.org/x/crypto/chacha20/chacha_ppc64x.go similarity index 89% rename from vendor/golang.org/x/crypto/chacha20/chacha_ppc64le.go rename to vendor/golang.org/x/crypto/chacha20/chacha_ppc64x.go index 3a4287f99..bd183d9ba 100644 --- a/vendor/golang.org/x/crypto/chacha20/chacha_ppc64le.go +++ b/vendor/golang.org/x/crypto/chacha20/chacha_ppc64x.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build gc && !purego +//go:build gc && !purego && (ppc64 || ppc64le) package chacha20 diff --git a/vendor/golang.org/x/crypto/chacha20/chacha_ppc64le.s b/vendor/golang.org/x/crypto/chacha20/chacha_ppc64x.s similarity index 76% rename from vendor/golang.org/x/crypto/chacha20/chacha_ppc64le.s rename to vendor/golang.org/x/crypto/chacha20/chacha_ppc64x.s index c672ccf69..a660b4112 100644 --- a/vendor/golang.org/x/crypto/chacha20/chacha_ppc64le.s +++ b/vendor/golang.org/x/crypto/chacha20/chacha_ppc64x.s @@ -19,7 +19,7 @@ // The differences in this and the original implementation are // due to the calling conventions and initialization of constants. -//go:build gc && !purego +//go:build gc && !purego && (ppc64 || ppc64le) #include "textflag.h" @@ -36,32 +36,68 @@ // for VPERMXOR #define MASK R18 -DATA consts<>+0x00(SB)/8, $0x3320646e61707865 -DATA consts<>+0x08(SB)/8, $0x6b20657479622d32 -DATA consts<>+0x10(SB)/8, $0x0000000000000001 -DATA consts<>+0x18(SB)/8, $0x0000000000000000 -DATA consts<>+0x20(SB)/8, $0x0000000000000004 -DATA consts<>+0x28(SB)/8, $0x0000000000000000 -DATA consts<>+0x30(SB)/8, $0x0a0b08090e0f0c0d -DATA consts<>+0x38(SB)/8, $0x0203000106070405 -DATA consts<>+0x40(SB)/8, $0x090a0b080d0e0f0c -DATA consts<>+0x48(SB)/8, $0x0102030005060704 -DATA consts<>+0x50(SB)/8, $0x6170786561707865 -DATA consts<>+0x58(SB)/8, $0x6170786561707865 -DATA consts<>+0x60(SB)/8, $0x3320646e3320646e -DATA consts<>+0x68(SB)/8, $0x3320646e3320646e -DATA consts<>+0x70(SB)/8, $0x79622d3279622d32 -DATA consts<>+0x78(SB)/8, $0x79622d3279622d32 -DATA consts<>+0x80(SB)/8, $0x6b2065746b206574 -DATA consts<>+0x88(SB)/8, $0x6b2065746b206574 -DATA consts<>+0x90(SB)/8, $0x0000000100000000 -DATA consts<>+0x98(SB)/8, $0x0000000300000002 -DATA consts<>+0xa0(SB)/8, $0x5566774411223300 -DATA consts<>+0xa8(SB)/8, $0xddeeffcc99aabb88 -DATA consts<>+0xb0(SB)/8, $0x6677445522330011 -DATA consts<>+0xb8(SB)/8, $0xeeffccddaabb8899 +DATA consts<>+0x00(SB)/4, $0x61707865 +DATA consts<>+0x04(SB)/4, $0x3320646e +DATA consts<>+0x08(SB)/4, $0x79622d32 +DATA consts<>+0x0c(SB)/4, $0x6b206574 +DATA consts<>+0x10(SB)/4, $0x00000001 +DATA consts<>+0x14(SB)/4, $0x00000000 +DATA consts<>+0x18(SB)/4, $0x00000000 +DATA consts<>+0x1c(SB)/4, $0x00000000 +DATA consts<>+0x20(SB)/4, $0x00000004 +DATA consts<>+0x24(SB)/4, $0x00000000 +DATA consts<>+0x28(SB)/4, $0x00000000 +DATA consts<>+0x2c(SB)/4, $0x00000000 +DATA consts<>+0x30(SB)/4, $0x0e0f0c0d +DATA consts<>+0x34(SB)/4, $0x0a0b0809 +DATA consts<>+0x38(SB)/4, $0x06070405 +DATA consts<>+0x3c(SB)/4, $0x02030001 +DATA consts<>+0x40(SB)/4, $0x0d0e0f0c +DATA consts<>+0x44(SB)/4, $0x090a0b08 +DATA consts<>+0x48(SB)/4, $0x05060704 +DATA consts<>+0x4c(SB)/4, $0x01020300 +DATA consts<>+0x50(SB)/4, $0x61707865 +DATA consts<>+0x54(SB)/4, $0x61707865 +DATA consts<>+0x58(SB)/4, $0x61707865 +DATA consts<>+0x5c(SB)/4, $0x61707865 +DATA consts<>+0x60(SB)/4, $0x3320646e +DATA consts<>+0x64(SB)/4, $0x3320646e +DATA consts<>+0x68(SB)/4, $0x3320646e +DATA consts<>+0x6c(SB)/4, $0x3320646e +DATA consts<>+0x70(SB)/4, $0x79622d32 +DATA consts<>+0x74(SB)/4, $0x79622d32 +DATA consts<>+0x78(SB)/4, $0x79622d32 +DATA consts<>+0x7c(SB)/4, $0x79622d32 +DATA consts<>+0x80(SB)/4, $0x6b206574 +DATA consts<>+0x84(SB)/4, $0x6b206574 +DATA consts<>+0x88(SB)/4, $0x6b206574 +DATA consts<>+0x8c(SB)/4, $0x6b206574 +DATA consts<>+0x90(SB)/4, $0x00000000 +DATA consts<>+0x94(SB)/4, $0x00000001 +DATA consts<>+0x98(SB)/4, $0x00000002 +DATA consts<>+0x9c(SB)/4, $0x00000003 +DATA consts<>+0xa0(SB)/4, $0x11223300 +DATA consts<>+0xa4(SB)/4, $0x55667744 +DATA consts<>+0xa8(SB)/4, $0x99aabb88 +DATA consts<>+0xac(SB)/4, $0xddeeffcc +DATA consts<>+0xb0(SB)/4, $0x22330011 +DATA consts<>+0xb4(SB)/4, $0x66774455 +DATA consts<>+0xb8(SB)/4, $0xaabb8899 +DATA consts<>+0xbc(SB)/4, $0xeeffccdd GLOBL consts<>(SB), RODATA, $0xc0 +#ifdef GOARCH_ppc64 +#define BE_XXBRW_INIT() \ + LVSL (R0)(R0), V24 \ + VSPLTISB $3, V25 \ + VXOR V24, V25, V24 \ + +#define BE_XXBRW(vr) VPERM vr, vr, V24, vr +#else +#define BE_XXBRW_INIT() +#define BE_XXBRW(vr) +#endif + //func chaCha20_ctr32_vsx(out, inp *byte, len int, key *[8]uint32, counter *uint32) TEXT ·chaCha20_ctr32_vsx(SB),NOSPLIT,$64-40 MOVD out+0(FP), OUT @@ -94,6 +130,8 @@ TEXT ·chaCha20_ctr32_vsx(SB),NOSPLIT,$64-40 // Clear V27 VXOR V27, V27, V27 + BE_XXBRW_INIT() + // V28 LXVW4X (CONSTBASE)(R11), VS60 @@ -299,6 +337,11 @@ loop_vsx: VADDUWM V8, V18, V8 VADDUWM V12, V19, V12 + BE_XXBRW(V0) + BE_XXBRW(V4) + BE_XXBRW(V8) + BE_XXBRW(V12) + CMPU LEN, $64 BLT tail_vsx @@ -327,6 +370,11 @@ loop_vsx: VADDUWM V9, V18, V8 VADDUWM V13, V19, V12 + BE_XXBRW(V0) + BE_XXBRW(V4) + BE_XXBRW(V8) + BE_XXBRW(V12) + CMPU LEN, $64 BLT tail_vsx @@ -334,8 +382,8 @@ loop_vsx: LXVW4X (INP)(R8), VS60 LXVW4X (INP)(R9), VS61 LXVW4X (INP)(R10), VS62 - VXOR V27, V0, V27 + VXOR V27, V0, V27 VXOR V28, V4, V28 VXOR V29, V8, V29 VXOR V30, V12, V30 @@ -354,6 +402,11 @@ loop_vsx: VADDUWM V10, V18, V8 VADDUWM V14, V19, V12 + BE_XXBRW(V0) + BE_XXBRW(V4) + BE_XXBRW(V8) + BE_XXBRW(V12) + CMPU LEN, $64 BLT tail_vsx @@ -381,6 +434,11 @@ loop_vsx: VADDUWM V11, V18, V8 VADDUWM V15, V19, V12 + BE_XXBRW(V0) + BE_XXBRW(V4) + BE_XXBRW(V8) + BE_XXBRW(V12) + CMPU LEN, $64 BLT tail_vsx @@ -408,9 +466,9 @@ loop_vsx: done_vsx: // Increment counter by number of 64 byte blocks - MOVD (CNT), R14 + MOVWZ (CNT), R14 ADD BLOCKS, R14 - MOVD R14, (CNT) + MOVWZ R14, (CNT) RET tail_vsx: diff --git a/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305.go b/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305.go index 93da7322b..8cf5d8112 100644 --- a/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305.go +++ b/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305.go @@ -5,7 +5,7 @@ // Package chacha20poly1305 implements the ChaCha20-Poly1305 AEAD and its // extended nonce variant XChaCha20-Poly1305, as specified in RFC 8439 and // draft-irtf-cfrg-xchacha-01. -package chacha20poly1305 // import "golang.org/x/crypto/chacha20poly1305" +package chacha20poly1305 import ( "crypto/cipher" diff --git a/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.s b/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.s index 731d2ac6d..fd5ee845f 100644 --- a/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.s +++ b/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.s @@ -1,2715 +1,9762 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// This file was originally from https://golang.org/cl/24717 by Vlad Krasnov of CloudFlare. +// Code generated by command: go run chacha20poly1305_amd64_asm.go -out ../chacha20poly1305_amd64.s -pkg chacha20poly1305. DO NOT EDIT. //go:build gc && !purego #include "textflag.h" -// General register allocation -#define oup DI -#define inp SI -#define inl BX -#define adp CX // free to reuse, after we hash the additional data -#define keyp R8 // free to reuse, when we copy the key to stack -#define itr2 R9 // general iterator -#define itr1 CX // general iterator -#define acc0 R10 -#define acc1 R11 -#define acc2 R12 -#define t0 R13 -#define t1 R14 -#define t2 R15 -#define t3 R8 -// Register and stack allocation for the SSE code -#define rStore (0*16)(BP) -#define sStore (1*16)(BP) -#define state1Store (2*16)(BP) -#define state2Store (3*16)(BP) -#define tmpStore (4*16)(BP) -#define ctr0Store (5*16)(BP) -#define ctr1Store (6*16)(BP) -#define ctr2Store (7*16)(BP) -#define ctr3Store (8*16)(BP) -#define A0 X0 -#define A1 X1 -#define A2 X2 -#define B0 X3 -#define B1 X4 -#define B2 X5 -#define C0 X6 -#define C1 X7 -#define C2 X8 -#define D0 X9 -#define D1 X10 -#define D2 X11 -#define T0 X12 -#define T1 X13 -#define T2 X14 -#define T3 X15 -#define A3 T0 -#define B3 T1 -#define C3 T2 -#define D3 T3 -// Register and stack allocation for the AVX2 code -#define rsStoreAVX2 (0*32)(BP) -#define state1StoreAVX2 (1*32)(BP) -#define state2StoreAVX2 (2*32)(BP) -#define ctr0StoreAVX2 (3*32)(BP) -#define ctr1StoreAVX2 (4*32)(BP) -#define ctr2StoreAVX2 (5*32)(BP) -#define ctr3StoreAVX2 (6*32)(BP) -#define tmpStoreAVX2 (7*32)(BP) // 256 bytes on stack -#define AA0 Y0 -#define AA1 Y5 -#define AA2 Y6 -#define AA3 Y7 -#define BB0 Y14 -#define BB1 Y9 -#define BB2 Y10 -#define BB3 Y11 -#define CC0 Y12 -#define CC1 Y13 -#define CC2 Y8 -#define CC3 Y15 -#define DD0 Y4 -#define DD1 Y1 -#define DD2 Y2 -#define DD3 Y3 -#define TT0 DD3 -#define TT1 AA3 -#define TT2 BB3 -#define TT3 CC3 -// ChaCha20 constants -DATA ·chacha20Constants<>+0x00(SB)/4, $0x61707865 -DATA ·chacha20Constants<>+0x04(SB)/4, $0x3320646e -DATA ·chacha20Constants<>+0x08(SB)/4, $0x79622d32 -DATA ·chacha20Constants<>+0x0c(SB)/4, $0x6b206574 -DATA ·chacha20Constants<>+0x10(SB)/4, $0x61707865 -DATA ·chacha20Constants<>+0x14(SB)/4, $0x3320646e -DATA ·chacha20Constants<>+0x18(SB)/4, $0x79622d32 -DATA ·chacha20Constants<>+0x1c(SB)/4, $0x6b206574 -// <<< 16 with PSHUFB -DATA ·rol16<>+0x00(SB)/8, $0x0504070601000302 -DATA ·rol16<>+0x08(SB)/8, $0x0D0C0F0E09080B0A -DATA ·rol16<>+0x10(SB)/8, $0x0504070601000302 -DATA ·rol16<>+0x18(SB)/8, $0x0D0C0F0E09080B0A -// <<< 8 with PSHUFB -DATA ·rol8<>+0x00(SB)/8, $0x0605040702010003 -DATA ·rol8<>+0x08(SB)/8, $0x0E0D0C0F0A09080B -DATA ·rol8<>+0x10(SB)/8, $0x0605040702010003 -DATA ·rol8<>+0x18(SB)/8, $0x0E0D0C0F0A09080B - -DATA ·avx2InitMask<>+0x00(SB)/8, $0x0 -DATA ·avx2InitMask<>+0x08(SB)/8, $0x0 -DATA ·avx2InitMask<>+0x10(SB)/8, $0x1 -DATA ·avx2InitMask<>+0x18(SB)/8, $0x0 - -DATA ·avx2IncMask<>+0x00(SB)/8, $0x2 -DATA ·avx2IncMask<>+0x08(SB)/8, $0x0 -DATA ·avx2IncMask<>+0x10(SB)/8, $0x2 -DATA ·avx2IncMask<>+0x18(SB)/8, $0x0 -// Poly1305 key clamp -DATA ·polyClampMask<>+0x00(SB)/8, $0x0FFFFFFC0FFFFFFF -DATA ·polyClampMask<>+0x08(SB)/8, $0x0FFFFFFC0FFFFFFC -DATA ·polyClampMask<>+0x10(SB)/8, $0xFFFFFFFFFFFFFFFF -DATA ·polyClampMask<>+0x18(SB)/8, $0xFFFFFFFFFFFFFFFF - -DATA ·sseIncMask<>+0x00(SB)/8, $0x1 -DATA ·sseIncMask<>+0x08(SB)/8, $0x0 -// To load/store the last < 16 bytes in a buffer -DATA ·andMask<>+0x00(SB)/8, $0x00000000000000ff -DATA ·andMask<>+0x08(SB)/8, $0x0000000000000000 -DATA ·andMask<>+0x10(SB)/8, $0x000000000000ffff -DATA ·andMask<>+0x18(SB)/8, $0x0000000000000000 -DATA ·andMask<>+0x20(SB)/8, $0x0000000000ffffff -DATA ·andMask<>+0x28(SB)/8, $0x0000000000000000 -DATA ·andMask<>+0x30(SB)/8, $0x00000000ffffffff -DATA ·andMask<>+0x38(SB)/8, $0x0000000000000000 -DATA ·andMask<>+0x40(SB)/8, $0x000000ffffffffff -DATA ·andMask<>+0x48(SB)/8, $0x0000000000000000 -DATA ·andMask<>+0x50(SB)/8, $0x0000ffffffffffff -DATA ·andMask<>+0x58(SB)/8, $0x0000000000000000 -DATA ·andMask<>+0x60(SB)/8, $0x00ffffffffffffff -DATA ·andMask<>+0x68(SB)/8, $0x0000000000000000 -DATA ·andMask<>+0x70(SB)/8, $0xffffffffffffffff -DATA ·andMask<>+0x78(SB)/8, $0x0000000000000000 -DATA ·andMask<>+0x80(SB)/8, $0xffffffffffffffff -DATA ·andMask<>+0x88(SB)/8, $0x00000000000000ff -DATA ·andMask<>+0x90(SB)/8, $0xffffffffffffffff -DATA ·andMask<>+0x98(SB)/8, $0x000000000000ffff -DATA ·andMask<>+0xa0(SB)/8, $0xffffffffffffffff -DATA ·andMask<>+0xa8(SB)/8, $0x0000000000ffffff -DATA ·andMask<>+0xb0(SB)/8, $0xffffffffffffffff -DATA ·andMask<>+0xb8(SB)/8, $0x00000000ffffffff -DATA ·andMask<>+0xc0(SB)/8, $0xffffffffffffffff -DATA ·andMask<>+0xc8(SB)/8, $0x000000ffffffffff -DATA ·andMask<>+0xd0(SB)/8, $0xffffffffffffffff -DATA ·andMask<>+0xd8(SB)/8, $0x0000ffffffffffff -DATA ·andMask<>+0xe0(SB)/8, $0xffffffffffffffff -DATA ·andMask<>+0xe8(SB)/8, $0x00ffffffffffffff - -GLOBL ·chacha20Constants<>(SB), (NOPTR+RODATA), $32 -GLOBL ·rol16<>(SB), (NOPTR+RODATA), $32 -GLOBL ·rol8<>(SB), (NOPTR+RODATA), $32 -GLOBL ·sseIncMask<>(SB), (NOPTR+RODATA), $16 -GLOBL ·avx2IncMask<>(SB), (NOPTR+RODATA), $32 -GLOBL ·avx2InitMask<>(SB), (NOPTR+RODATA), $32 -GLOBL ·polyClampMask<>(SB), (NOPTR+RODATA), $32 -GLOBL ·andMask<>(SB), (NOPTR+RODATA), $240 -// No PALIGNR in Go ASM yet (but VPALIGNR is present). -#define shiftB0Left BYTE $0x66; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xdb; BYTE $0x04 // PALIGNR $4, X3, X3 -#define shiftB1Left BYTE $0x66; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xe4; BYTE $0x04 // PALIGNR $4, X4, X4 -#define shiftB2Left BYTE $0x66; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xed; BYTE $0x04 // PALIGNR $4, X5, X5 -#define shiftB3Left BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xed; BYTE $0x04 // PALIGNR $4, X13, X13 -#define shiftC0Left BYTE $0x66; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xf6; BYTE $0x08 // PALIGNR $8, X6, X6 -#define shiftC1Left BYTE $0x66; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xff; BYTE $0x08 // PALIGNR $8, X7, X7 -#define shiftC2Left BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xc0; BYTE $0x08 // PALIGNR $8, X8, X8 -#define shiftC3Left BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xf6; BYTE $0x08 // PALIGNR $8, X14, X14 -#define shiftD0Left BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xc9; BYTE $0x0c // PALIGNR $12, X9, X9 -#define shiftD1Left BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xd2; BYTE $0x0c // PALIGNR $12, X10, X10 -#define shiftD2Left BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xdb; BYTE $0x0c // PALIGNR $12, X11, X11 -#define shiftD3Left BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xff; BYTE $0x0c // PALIGNR $12, X15, X15 -#define shiftB0Right BYTE $0x66; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xdb; BYTE $0x0c // PALIGNR $12, X3, X3 -#define shiftB1Right BYTE $0x66; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xe4; BYTE $0x0c // PALIGNR $12, X4, X4 -#define shiftB2Right BYTE $0x66; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xed; BYTE $0x0c // PALIGNR $12, X5, X5 -#define shiftB3Right BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xed; BYTE $0x0c // PALIGNR $12, X13, X13 -#define shiftC0Right shiftC0Left -#define shiftC1Right shiftC1Left -#define shiftC2Right shiftC2Left -#define shiftC3Right shiftC3Left -#define shiftD0Right BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xc9; BYTE $0x04 // PALIGNR $4, X9, X9 -#define shiftD1Right BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xd2; BYTE $0x04 // PALIGNR $4, X10, X10 -#define shiftD2Right BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xdb; BYTE $0x04 // PALIGNR $4, X11, X11 -#define shiftD3Right BYTE $0x66; BYTE $0x45; BYTE $0x0f; BYTE $0x3a; BYTE $0x0f; BYTE $0xff; BYTE $0x04 // PALIGNR $4, X15, X15 - -// Some macros - -// ROL rotates the uint32s in register R left by N bits, using temporary T. -#define ROL(N, R, T) \ - MOVO R, T; PSLLL $(N), T; PSRLL $(32-(N)), R; PXOR T, R - -// ROL16 rotates the uint32s in register R left by 16, using temporary T if needed. -#ifdef GOAMD64_v2 -#define ROL16(R, T) PSHUFB ·rol16<>(SB), R -#else -#define ROL16(R, T) ROL(16, R, T) -#endif - -// ROL8 rotates the uint32s in register R left by 8, using temporary T if needed. -#ifdef GOAMD64_v2 -#define ROL8(R, T) PSHUFB ·rol8<>(SB), R -#else -#define ROL8(R, T) ROL(8, R, T) -#endif - -#define chachaQR(A, B, C, D, T) \ - PADDD B, A; PXOR A, D; ROL16(D, T) \ - PADDD D, C; PXOR C, B; MOVO B, T; PSLLL $12, T; PSRLL $20, B; PXOR T, B \ - PADDD B, A; PXOR A, D; ROL8(D, T) \ - PADDD D, C; PXOR C, B; MOVO B, T; PSLLL $7, T; PSRLL $25, B; PXOR T, B - -#define chachaQR_AVX2(A, B, C, D, T) \ - VPADDD B, A, A; VPXOR A, D, D; VPSHUFB ·rol16<>(SB), D, D \ - VPADDD D, C, C; VPXOR C, B, B; VPSLLD $12, B, T; VPSRLD $20, B, B; VPXOR T, B, B \ - VPADDD B, A, A; VPXOR A, D, D; VPSHUFB ·rol8<>(SB), D, D \ - VPADDD D, C, C; VPXOR C, B, B; VPSLLD $7, B, T; VPSRLD $25, B, B; VPXOR T, B, B - -#define polyAdd(S) ADDQ S, acc0; ADCQ 8+S, acc1; ADCQ $1, acc2 -#define polyMulStage1 MOVQ (0*8)(BP), AX; MOVQ AX, t2; MULQ acc0; MOVQ AX, t0; MOVQ DX, t1; MOVQ (0*8)(BP), AX; MULQ acc1; IMULQ acc2, t2; ADDQ AX, t1; ADCQ DX, t2 -#define polyMulStage2 MOVQ (1*8)(BP), AX; MOVQ AX, t3; MULQ acc0; ADDQ AX, t1; ADCQ $0, DX; MOVQ DX, acc0; MOVQ (1*8)(BP), AX; MULQ acc1; ADDQ AX, t2; ADCQ $0, DX -#define polyMulStage3 IMULQ acc2, t3; ADDQ acc0, t2; ADCQ DX, t3 -#define polyMulReduceStage MOVQ t0, acc0; MOVQ t1, acc1; MOVQ t2, acc2; ANDQ $3, acc2; MOVQ t2, t0; ANDQ $-4, t0; MOVQ t3, t1; SHRQ $2, t3, t2; SHRQ $2, t3; ADDQ t0, acc0; ADCQ t1, acc1; ADCQ $0, acc2; ADDQ t2, acc0; ADCQ t3, acc1; ADCQ $0, acc2 - -#define polyMulStage1_AVX2 MOVQ (0*8)(BP), DX; MOVQ DX, t2; MULXQ acc0, t0, t1; IMULQ acc2, t2; MULXQ acc1, AX, DX; ADDQ AX, t1; ADCQ DX, t2 -#define polyMulStage2_AVX2 MOVQ (1*8)(BP), DX; MULXQ acc0, acc0, AX; ADDQ acc0, t1; MULXQ acc1, acc1, t3; ADCQ acc1, t2; ADCQ $0, t3 -#define polyMulStage3_AVX2 IMULQ acc2, DX; ADDQ AX, t2; ADCQ DX, t3 - -#define polyMul polyMulStage1; polyMulStage2; polyMulStage3; polyMulReduceStage -#define polyMulAVX2 polyMulStage1_AVX2; polyMulStage2_AVX2; polyMulStage3_AVX2; polyMulReduceStage -// ---------------------------------------------------------------------------- + +// func polyHashADInternal<>() TEXT polyHashADInternal<>(SB), NOSPLIT, $0 - // adp points to beginning of additional data - // itr2 holds ad length - XORQ acc0, acc0 - XORQ acc1, acc1 - XORQ acc2, acc2 - CMPQ itr2, $13 - JNE hashADLoop - -openFastTLSAD: - // Special treatment for the TLS case of 13 bytes - MOVQ (adp), acc0 - MOVQ 5(adp), acc1 - SHRQ $24, acc1 - MOVQ $1, acc2 - polyMul + // Hack: Must declare #define macros inside of a function due to Avo constraints + // ROL rotates the uint32s in register R left by N bits, using temporary T. + #define ROL(N, R, T) \ + MOVO R, T; \ + PSLLL $(N), T; \ + PSRLL $(32-(N)), R; \ + PXOR T, R + + // ROL8 rotates the uint32s in register R left by 8, using temporary T if needed. + #ifdef GOAMD64_v2 + #define ROL8(R, T) PSHUFB ·rol8<>(SB), R + #else + #define ROL8(R, T) ROL(8, R, T) + #endif + + // ROL16 rotates the uint32s in register R left by 16, using temporary T if needed. + #ifdef GOAMD64_v2 + #define ROL16(R, T) PSHUFB ·rol16<>(SB), R + #else + #define ROL16(R, T) ROL(16, R, T) + #endif + XORQ R10, R10 + XORQ R11, R11 + XORQ R12, R12 + CMPQ R9, $0x0d + JNE hashADLoop + MOVQ (CX), R10 + MOVQ 5(CX), R11 + SHRQ $0x18, R11 + MOVQ $0x00000001, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 RET hashADLoop: // Hash in 16 byte chunks - CMPQ itr2, $16 - JB hashADTail - polyAdd(0(adp)) - LEAQ (1*16)(adp), adp - SUBQ $16, itr2 - polyMul - JMP hashADLoop + CMPQ R9, $0x10 + JB hashADTail + ADDQ (CX), R10 + ADCQ 8(CX), R11 + ADCQ $0x01, R12 + LEAQ 16(CX), CX + SUBQ $0x10, R9 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + JMP hashADLoop hashADTail: - CMPQ itr2, $0 + CMPQ R9, $0x00 JE hashADDone // Hash last < 16 byte tail - XORQ t0, t0 - XORQ t1, t1 - XORQ t2, t2 - ADDQ itr2, adp + XORQ R13, R13 + XORQ R14, R14 + XORQ R15, R15 + ADDQ R9, CX hashADTailLoop: - SHLQ $8, t0, t1 - SHLQ $8, t0 - MOVB -1(adp), t2 - XORQ t2, t0 - DECQ adp - DECQ itr2 - JNE hashADTailLoop - -hashADTailFinish: - ADDQ t0, acc0; ADCQ t1, acc1; ADCQ $1, acc2 - polyMul - - // Finished AD + SHLQ $0x08, R13, R14 + SHLQ $0x08, R13 + MOVB -1(CX), R15 + XORQ R15, R13 + DECQ CX + DECQ R9 + JNE hashADTailLoop + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + hashADDone: RET -// ---------------------------------------------------------------------------- -// func chacha20Poly1305Open(dst, key, src, ad []byte) bool -TEXT ·chacha20Poly1305Open(SB), 0, $288-97 +// func chacha20Poly1305Open(dst []byte, key []uint32, src []byte, ad []byte) bool +// Requires: AVX, AVX2, BMI2, CMOV, SSE2 +TEXT ·chacha20Poly1305Open(SB), $288-97 // For aligned stack access MOVQ SP, BP - ADDQ $32, BP + ADDQ $0x20, BP ANDQ $-32, BP - MOVQ dst+0(FP), oup - MOVQ key+24(FP), keyp - MOVQ src+48(FP), inp - MOVQ src_len+56(FP), inl - MOVQ ad+72(FP), adp + MOVQ dst_base+0(FP), DI + MOVQ key_base+24(FP), R8 + MOVQ src_base+48(FP), SI + MOVQ src_len+56(FP), BX + MOVQ ad_base+72(FP), CX // Check for AVX2 support - CMPB ·useAVX2(SB), $1 + CMPB ·useAVX2+0(SB), $0x01 JE chacha20Poly1305Open_AVX2 // Special optimization, for very short buffers - CMPQ inl, $128 - JBE openSSE128 // About 16% faster + CMPQ BX, $0x80 + JBE openSSE128 // For long buffers, prepare the poly key first - MOVOU ·chacha20Constants<>(SB), A0 - MOVOU (1*16)(keyp), B0 - MOVOU (2*16)(keyp), C0 - MOVOU (3*16)(keyp), D0 - MOVO D0, T1 + MOVOU ·chacha20Constants<>+0(SB), X0 + MOVOU 16(R8), X3 + MOVOU 32(R8), X6 + MOVOU 48(R8), X9 + MOVO X9, X13 // Store state on stack for future use - MOVO B0, state1Store - MOVO C0, state2Store - MOVO D0, ctr3Store - MOVQ $10, itr2 + MOVO X3, 32(BP) + MOVO X6, 48(BP) + MOVO X9, 128(BP) + MOVQ $0x0000000a, R9 openSSEPreparePolyKey: - chachaQR(A0, B0, C0, D0, T0) - shiftB0Left; shiftC0Left; shiftD0Left - chachaQR(A0, B0, C0, D0, T0) - shiftB0Right; shiftC0Right; shiftD0Right - DECQ itr2 - JNE openSSEPreparePolyKey + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X3 + PXOR X12, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X3 + PXOR X12, X3 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x0c + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X3 + PXOR X12, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X3 + PXOR X12, X3 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x04 + DECQ R9 + JNE openSSEPreparePolyKey // A0|B0 hold the Poly1305 32-byte key, C0,D0 can be discarded - PADDL ·chacha20Constants<>(SB), A0; PADDL state1Store, B0 + PADDL ·chacha20Constants<>+0(SB), X0 + PADDL 32(BP), X3 // Clamp and store the key - PAND ·polyClampMask<>(SB), A0 - MOVO A0, rStore; MOVO B0, sStore + PAND ·polyClampMask<>+0(SB), X0 + MOVO X0, (BP) + MOVO X3, 16(BP) // Hash AAD - MOVQ ad_len+80(FP), itr2 + MOVQ ad_len+80(FP), R9 CALL polyHashADInternal<>(SB) openSSEMainLoop: - CMPQ inl, $256 + CMPQ BX, $0x00000100 JB openSSEMainLoopDone // Load state, increment counter blocks - MOVO ·chacha20Constants<>(SB), A0; MOVO state1Store, B0; MOVO state2Store, C0; MOVO ctr3Store, D0; PADDL ·sseIncMask<>(SB), D0 - MOVO A0, A1; MOVO B0, B1; MOVO C0, C1; MOVO D0, D1; PADDL ·sseIncMask<>(SB), D1 - MOVO A1, A2; MOVO B1, B2; MOVO C1, C2; MOVO D1, D2; PADDL ·sseIncMask<>(SB), D2 - MOVO A2, A3; MOVO B2, B3; MOVO C2, C3; MOVO D2, D3; PADDL ·sseIncMask<>(SB), D3 + MOVO ·chacha20Constants<>+0(SB), X0 + MOVO 32(BP), X3 + MOVO 48(BP), X6 + MOVO 128(BP), X9 + PADDL ·sseIncMask<>+0(SB), X9 + MOVO X0, X1 + MOVO X3, X4 + MOVO X6, X7 + MOVO X9, X10 + PADDL ·sseIncMask<>+0(SB), X10 + MOVO X1, X2 + MOVO X4, X5 + MOVO X7, X8 + MOVO X10, X11 + PADDL ·sseIncMask<>+0(SB), X11 + MOVO X2, X12 + MOVO X5, X13 + MOVO X8, X14 + MOVO X11, X15 + PADDL ·sseIncMask<>+0(SB), X15 // Store counters - MOVO D0, ctr0Store; MOVO D1, ctr1Store; MOVO D2, ctr2Store; MOVO D3, ctr3Store + MOVO X9, 80(BP) + MOVO X10, 96(BP) + MOVO X11, 112(BP) + MOVO X15, 128(BP) - // There are 10 ChaCha20 iterations of 2QR each, so for 6 iterations we hash 2 blocks, and for the remaining 4 only 1 block - for a total of 16 - MOVQ $4, itr1 - MOVQ inp, itr2 + // There are 10 ChaCha20 iterations of 2QR each, so for 6 iterations we hash + // 2 blocks, and for the remaining 4 only 1 block - for a total of 16 + MOVQ $0x00000004, CX + MOVQ SI, R9 openSSEInternalLoop: - MOVO C3, tmpStore - chachaQR(A0, B0, C0, D0, C3); chachaQR(A1, B1, C1, D1, C3); chachaQR(A2, B2, C2, D2, C3) - MOVO tmpStore, C3 - MOVO C1, tmpStore - chachaQR(A3, B3, C3, D3, C1) - MOVO tmpStore, C1 - polyAdd(0(itr2)) - shiftB0Left; shiftB1Left; shiftB2Left; shiftB3Left - shiftC0Left; shiftC1Left; shiftC2Left; shiftC3Left - shiftD0Left; shiftD1Left; shiftD2Left; shiftD3Left - polyMulStage1 - polyMulStage2 - LEAQ (2*8)(itr2), itr2 - MOVO C3, tmpStore - chachaQR(A0, B0, C0, D0, C3); chachaQR(A1, B1, C1, D1, C3); chachaQR(A2, B2, C2, D2, C3) - MOVO tmpStore, C3 - MOVO C1, tmpStore - polyMulStage3 - chachaQR(A3, B3, C3, D3, C1) - MOVO tmpStore, C1 - polyMulReduceStage - shiftB0Right; shiftB1Right; shiftB2Right; shiftB3Right - shiftC0Right; shiftC1Right; shiftC2Right; shiftC3Right - shiftD0Right; shiftD1Right; shiftD2Right; shiftD3Right - DECQ itr1 - JGE openSSEInternalLoop - - polyAdd(0(itr2)) - polyMul - LEAQ (2*8)(itr2), itr2 - - CMPQ itr1, $-6 - JG openSSEInternalLoop + MOVO X14, 64(BP) + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X14) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X3 + PXOR X14, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X14) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X3 + PXOR X14, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X14) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X4 + PXOR X14, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X14) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X4 + PXOR X14, X4 + PADDD X5, X2 + PXOR X2, X11 + ROL16(X11, X14) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X5 + PXOR X14, X5 + PADDD X5, X2 + PXOR X2, X11 + ROL8(X11, X14) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X5 + PXOR X14, X5 + MOVO 64(BP), X14 + MOVO X7, 64(BP) + PADDD X13, X12 + PXOR X12, X15 + ROL16(X15, X7) + PADDD X15, X14 + PXOR X14, X13 + MOVO X13, X7 + PSLLL $0x0c, X7 + PSRLL $0x14, X13 + PXOR X7, X13 + PADDD X13, X12 + PXOR X12, X15 + ROL8(X15, X7) + PADDD X15, X14 + PXOR X14, X13 + MOVO X13, X7 + PSLLL $0x07, X7 + PSRLL $0x19, X13 + PXOR X7, X13 + MOVO 64(BP), X7 + ADDQ (R9), R10 + ADCQ 8(R9), R11 + ADCQ $0x01, R12 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc0 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x0c + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + LEAQ 16(R9), R9 + MOVO X14, 64(BP) + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X14) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X3 + PXOR X14, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X14) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X3 + PXOR X14, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X14) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X4 + PXOR X14, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X14) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X4 + PXOR X14, X4 + PADDD X5, X2 + PXOR X2, X11 + ROL16(X11, X14) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X5 + PXOR X14, X5 + PADDD X5, X2 + PXOR X2, X11 + ROL8(X11, X14) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X5 + PXOR X14, X5 + MOVO 64(BP), X14 + MOVO X7, 64(BP) + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + PADDD X13, X12 + PXOR X12, X15 + ROL16(X15, X7) + PADDD X15, X14 + PXOR X14, X13 + MOVO X13, X7 + PSLLL $0x0c, X7 + PSRLL $0x14, X13 + PXOR X7, X13 + PADDD X13, X12 + PXOR X12, X15 + ROL8(X15, X7) + PADDD X15, X14 + PXOR X14, X13 + MOVO X13, X7 + PSLLL $0x07, X7 + PSRLL $0x19, X13 + PXOR X7, X13 + MOVO 64(BP), X7 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc0 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x04 + DECQ CX + JGE openSSEInternalLoop + ADDQ (R9), R10 + ADCQ 8(R9), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 16(R9), R9 + CMPQ CX, $-6 + JG openSSEInternalLoop // Add in the state - PADDD ·chacha20Constants<>(SB), A0; PADDD ·chacha20Constants<>(SB), A1; PADDD ·chacha20Constants<>(SB), A2; PADDD ·chacha20Constants<>(SB), A3 - PADDD state1Store, B0; PADDD state1Store, B1; PADDD state1Store, B2; PADDD state1Store, B3 - PADDD state2Store, C0; PADDD state2Store, C1; PADDD state2Store, C2; PADDD state2Store, C3 - PADDD ctr0Store, D0; PADDD ctr1Store, D1; PADDD ctr2Store, D2; PADDD ctr3Store, D3 + PADDD ·chacha20Constants<>+0(SB), X0 + PADDD ·chacha20Constants<>+0(SB), X1 + PADDD ·chacha20Constants<>+0(SB), X2 + PADDD ·chacha20Constants<>+0(SB), X12 + PADDD 32(BP), X3 + PADDD 32(BP), X4 + PADDD 32(BP), X5 + PADDD 32(BP), X13 + PADDD 48(BP), X6 + PADDD 48(BP), X7 + PADDD 48(BP), X8 + PADDD 48(BP), X14 + PADDD 80(BP), X9 + PADDD 96(BP), X10 + PADDD 112(BP), X11 + PADDD 128(BP), X15 // Load - xor - store - MOVO D3, tmpStore - MOVOU (0*16)(inp), D3; PXOR D3, A0; MOVOU A0, (0*16)(oup) - MOVOU (1*16)(inp), D3; PXOR D3, B0; MOVOU B0, (1*16)(oup) - MOVOU (2*16)(inp), D3; PXOR D3, C0; MOVOU C0, (2*16)(oup) - MOVOU (3*16)(inp), D3; PXOR D3, D0; MOVOU D0, (3*16)(oup) - MOVOU (4*16)(inp), D0; PXOR D0, A1; MOVOU A1, (4*16)(oup) - MOVOU (5*16)(inp), D0; PXOR D0, B1; MOVOU B1, (5*16)(oup) - MOVOU (6*16)(inp), D0; PXOR D0, C1; MOVOU C1, (6*16)(oup) - MOVOU (7*16)(inp), D0; PXOR D0, D1; MOVOU D1, (7*16)(oup) - MOVOU (8*16)(inp), D0; PXOR D0, A2; MOVOU A2, (8*16)(oup) - MOVOU (9*16)(inp), D0; PXOR D0, B2; MOVOU B2, (9*16)(oup) - MOVOU (10*16)(inp), D0; PXOR D0, C2; MOVOU C2, (10*16)(oup) - MOVOU (11*16)(inp), D0; PXOR D0, D2; MOVOU D2, (11*16)(oup) - MOVOU (12*16)(inp), D0; PXOR D0, A3; MOVOU A3, (12*16)(oup) - MOVOU (13*16)(inp), D0; PXOR D0, B3; MOVOU B3, (13*16)(oup) - MOVOU (14*16)(inp), D0; PXOR D0, C3; MOVOU C3, (14*16)(oup) - MOVOU (15*16)(inp), D0; PXOR tmpStore, D0; MOVOU D0, (15*16)(oup) - LEAQ 256(inp), inp - LEAQ 256(oup), oup - SUBQ $256, inl + MOVO X15, 64(BP) + MOVOU (SI), X15 + PXOR X15, X0 + MOVOU X0, (DI) + MOVOU 16(SI), X15 + PXOR X15, X3 + MOVOU X3, 16(DI) + MOVOU 32(SI), X15 + PXOR X15, X6 + MOVOU X6, 32(DI) + MOVOU 48(SI), X15 + PXOR X15, X9 + MOVOU X9, 48(DI) + MOVOU 64(SI), X9 + PXOR X9, X1 + MOVOU X1, 64(DI) + MOVOU 80(SI), X9 + PXOR X9, X4 + MOVOU X4, 80(DI) + MOVOU 96(SI), X9 + PXOR X9, X7 + MOVOU X7, 96(DI) + MOVOU 112(SI), X9 + PXOR X9, X10 + MOVOU X10, 112(DI) + MOVOU 128(SI), X9 + PXOR X9, X2 + MOVOU X2, 128(DI) + MOVOU 144(SI), X9 + PXOR X9, X5 + MOVOU X5, 144(DI) + MOVOU 160(SI), X9 + PXOR X9, X8 + MOVOU X8, 160(DI) + MOVOU 176(SI), X9 + PXOR X9, X11 + MOVOU X11, 176(DI) + MOVOU 192(SI), X9 + PXOR X9, X12 + MOVOU X12, 192(DI) + MOVOU 208(SI), X9 + PXOR X9, X13 + MOVOU X13, 208(DI) + MOVOU 224(SI), X9 + PXOR X9, X14 + MOVOU X14, 224(DI) + MOVOU 240(SI), X9 + PXOR 64(BP), X9 + MOVOU X9, 240(DI) + LEAQ 256(SI), SI + LEAQ 256(DI), DI + SUBQ $0x00000100, BX JMP openSSEMainLoop openSSEMainLoopDone: // Handle the various tail sizes efficiently - TESTQ inl, inl + TESTQ BX, BX JE openSSEFinalize - CMPQ inl, $64 + CMPQ BX, $0x40 JBE openSSETail64 - CMPQ inl, $128 + CMPQ BX, $0x80 JBE openSSETail128 - CMPQ inl, $192 + CMPQ BX, $0xc0 JBE openSSETail192 JMP openSSETail256 openSSEFinalize: // Hash in the PT, AAD lengths - ADDQ ad_len+80(FP), acc0; ADCQ src_len+56(FP), acc1; ADCQ $1, acc2 - polyMul + ADDQ ad_len+80(FP), R10 + ADCQ src_len+56(FP), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 // Final reduce - MOVQ acc0, t0 - MOVQ acc1, t1 - MOVQ acc2, t2 - SUBQ $-5, acc0 - SBBQ $-1, acc1 - SBBQ $3, acc2 - CMOVQCS t0, acc0 - CMOVQCS t1, acc1 - CMOVQCS t2, acc2 + MOVQ R10, R13 + MOVQ R11, R14 + MOVQ R12, R15 + SUBQ $-5, R10 + SBBQ $-1, R11 + SBBQ $0x03, R12 + CMOVQCS R13, R10 + CMOVQCS R14, R11 + CMOVQCS R15, R12 // Add in the "s" part of the key - ADDQ 0+sStore, acc0 - ADCQ 8+sStore, acc1 + ADDQ 16(BP), R10 + ADCQ 24(BP), R11 // Finally, constant time compare to the tag at the end of the message XORQ AX, AX - MOVQ $1, DX - XORQ (0*8)(inp), acc0 - XORQ (1*8)(inp), acc1 - ORQ acc1, acc0 + MOVQ $0x00000001, DX + XORQ (SI), R10 + XORQ 8(SI), R11 + ORQ R11, R10 CMOVQEQ DX, AX // Return true iff tags are equal MOVB AX, ret+96(FP) RET -// ---------------------------------------------------------------------------- -// Special optimization for buffers smaller than 129 bytes openSSE128: - // For up to 128 bytes of ciphertext and 64 bytes for the poly key, we require to process three blocks - MOVOU ·chacha20Constants<>(SB), A0; MOVOU (1*16)(keyp), B0; MOVOU (2*16)(keyp), C0; MOVOU (3*16)(keyp), D0 - MOVO A0, A1; MOVO B0, B1; MOVO C0, C1; MOVO D0, D1; PADDL ·sseIncMask<>(SB), D1 - MOVO A1, A2; MOVO B1, B2; MOVO C1, C2; MOVO D1, D2; PADDL ·sseIncMask<>(SB), D2 - MOVO B0, T1; MOVO C0, T2; MOVO D1, T3 - MOVQ $10, itr2 + MOVOU ·chacha20Constants<>+0(SB), X0 + MOVOU 16(R8), X3 + MOVOU 32(R8), X6 + MOVOU 48(R8), X9 + MOVO X0, X1 + MOVO X3, X4 + MOVO X6, X7 + MOVO X9, X10 + PADDL ·sseIncMask<>+0(SB), X10 + MOVO X1, X2 + MOVO X4, X5 + MOVO X7, X8 + MOVO X10, X11 + PADDL ·sseIncMask<>+0(SB), X11 + MOVO X3, X13 + MOVO X6, X14 + MOVO X10, X15 + MOVQ $0x0000000a, R9 openSSE128InnerCipherLoop: - chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0); chachaQR(A2, B2, C2, D2, T0) - shiftB0Left; shiftB1Left; shiftB2Left - shiftC0Left; shiftC1Left; shiftC2Left - shiftD0Left; shiftD1Left; shiftD2Left - chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0); chachaQR(A2, B2, C2, D2, T0) - shiftB0Right; shiftB1Right; shiftB2Right - shiftC0Right; shiftC1Right; shiftC2Right - shiftD0Right; shiftD1Right; shiftD2Right - DECQ itr2 - JNE openSSE128InnerCipherLoop + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X3 + PXOR X12, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X3 + PXOR X12, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X4 + PXOR X12, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X4 + PXOR X12, X4 + PADDD X5, X2 + PXOR X2, X11 + ROL16(X11, X12) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X5 + PXOR X12, X5 + PADDD X5, X2 + PXOR X2, X11 + ROL8(X11, X12) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X5 + PXOR X12, X5 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc0 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X3 + PXOR X12, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X3 + PXOR X12, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X4 + PXOR X12, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X4 + PXOR X12, X4 + PADDD X5, X2 + PXOR X2, X11 + ROL16(X11, X12) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X5 + PXOR X12, X5 + PADDD X5, X2 + PXOR X2, X11 + ROL8(X11, X12) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X5 + PXOR X12, X5 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc0 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + DECQ R9 + JNE openSSE128InnerCipherLoop // A0|B0 hold the Poly1305 32-byte key, C0,D0 can be discarded - PADDL ·chacha20Constants<>(SB), A0; PADDL ·chacha20Constants<>(SB), A1; PADDL ·chacha20Constants<>(SB), A2 - PADDL T1, B0; PADDL T1, B1; PADDL T1, B2 - PADDL T2, C1; PADDL T2, C2 - PADDL T3, D1; PADDL ·sseIncMask<>(SB), T3; PADDL T3, D2 + PADDL ·chacha20Constants<>+0(SB), X0 + PADDL ·chacha20Constants<>+0(SB), X1 + PADDL ·chacha20Constants<>+0(SB), X2 + PADDL X13, X3 + PADDL X13, X4 + PADDL X13, X5 + PADDL X14, X7 + PADDL X14, X8 + PADDL X15, X10 + PADDL ·sseIncMask<>+0(SB), X15 + PADDL X15, X11 // Clamp and store the key - PAND ·polyClampMask<>(SB), A0 - MOVOU A0, rStore; MOVOU B0, sStore + PAND ·polyClampMask<>+0(SB), X0 + MOVOU X0, (BP) + MOVOU X3, 16(BP) // Hash - MOVQ ad_len+80(FP), itr2 + MOVQ ad_len+80(FP), R9 CALL polyHashADInternal<>(SB) openSSE128Open: - CMPQ inl, $16 + CMPQ BX, $0x10 JB openSSETail16 - SUBQ $16, inl + SUBQ $0x10, BX // Load for hashing - polyAdd(0(inp)) + ADDQ (SI), R10 + ADCQ 8(SI), R11 + ADCQ $0x01, R12 // Load for decryption - MOVOU (inp), T0; PXOR T0, A1; MOVOU A1, (oup) - LEAQ (1*16)(inp), inp - LEAQ (1*16)(oup), oup - polyMul + MOVOU (SI), X12 + PXOR X12, X1 + MOVOU X1, (DI) + LEAQ 16(SI), SI + LEAQ 16(DI), DI + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 // Shift the stream "left" - MOVO B1, A1 - MOVO C1, B1 - MOVO D1, C1 - MOVO A2, D1 - MOVO B2, A2 - MOVO C2, B2 - MOVO D2, C2 + MOVO X4, X1 + MOVO X7, X4 + MOVO X10, X7 + MOVO X2, X10 + MOVO X5, X2 + MOVO X8, X5 + MOVO X11, X8 JMP openSSE128Open openSSETail16: - TESTQ inl, inl + TESTQ BX, BX JE openSSEFinalize // We can safely load the CT from the end, because it is padded with the MAC - MOVQ inl, itr2 - SHLQ $4, itr2 - LEAQ ·andMask<>(SB), t0 - MOVOU (inp), T0 - ADDQ inl, inp - PAND -16(t0)(itr2*1), T0 - MOVO T0, 0+tmpStore - MOVQ T0, t0 - MOVQ 8+tmpStore, t1 - PXOR A1, T0 + MOVQ BX, R9 + SHLQ $0x04, R9 + LEAQ ·andMask<>+0(SB), R13 + MOVOU (SI), X12 + ADDQ BX, SI + PAND -16(R13)(R9*1), X12 + MOVO X12, 64(BP) + MOVQ X12, R13 + MOVQ 72(BP), R14 + PXOR X1, X12 // We can only store one byte at a time, since plaintext can be shorter than 16 bytes openSSETail16Store: - MOVQ T0, t3 - MOVB t3, (oup) - PSRLDQ $1, T0 - INCQ oup - DECQ inl + MOVQ X12, R8 + MOVB R8, (DI) + PSRLDQ $0x01, X12 + INCQ DI + DECQ BX JNE openSSETail16Store - ADDQ t0, acc0; ADCQ t1, acc1; ADCQ $1, acc2 - polyMul + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 JMP openSSEFinalize -// ---------------------------------------------------------------------------- -// Special optimization for the last 64 bytes of ciphertext openSSETail64: - // Need to decrypt up to 64 bytes - prepare single block - MOVO ·chacha20Constants<>(SB), A0; MOVO state1Store, B0; MOVO state2Store, C0; MOVO ctr3Store, D0; PADDL ·sseIncMask<>(SB), D0; MOVO D0, ctr0Store - XORQ itr2, itr2 - MOVQ inl, itr1 - CMPQ itr1, $16 - JB openSSETail64LoopB + MOVO ·chacha20Constants<>+0(SB), X0 + MOVO 32(BP), X3 + MOVO 48(BP), X6 + MOVO 128(BP), X9 + PADDL ·sseIncMask<>+0(SB), X9 + MOVO X9, 80(BP) + XORQ R9, R9 + MOVQ BX, CX + CMPQ CX, $0x10 + JB openSSETail64LoopB openSSETail64LoopA: - // Perform ChaCha rounds, while hashing the remaining input - polyAdd(0(inp)(itr2*1)) - polyMul - SUBQ $16, itr1 + ADDQ (SI)(R9*1), R10 + ADCQ 8(SI)(R9*1), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + SUBQ $0x10, CX openSSETail64LoopB: - ADDQ $16, itr2 - chachaQR(A0, B0, C0, D0, T0) - shiftB0Left; shiftC0Left; shiftD0Left - chachaQR(A0, B0, C0, D0, T0) - shiftB0Right; shiftC0Right; shiftD0Right - - CMPQ itr1, $16 - JAE openSSETail64LoopA - - CMPQ itr2, $160 - JNE openSSETail64LoopB - - PADDL ·chacha20Constants<>(SB), A0; PADDL state1Store, B0; PADDL state2Store, C0; PADDL ctr0Store, D0 + ADDQ $0x10, R9 + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X3 + PXOR X12, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X3 + PXOR X12, X3 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x0c + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X3 + PXOR X12, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X3 + PXOR X12, X3 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x04 + CMPQ CX, $0x10 + JAE openSSETail64LoopA + CMPQ R9, $0xa0 + JNE openSSETail64LoopB + PADDL ·chacha20Constants<>+0(SB), X0 + PADDL 32(BP), X3 + PADDL 48(BP), X6 + PADDL 80(BP), X9 openSSETail64DecLoop: - CMPQ inl, $16 + CMPQ BX, $0x10 JB openSSETail64DecLoopDone - SUBQ $16, inl - MOVOU (inp), T0 - PXOR T0, A0 - MOVOU A0, (oup) - LEAQ 16(inp), inp - LEAQ 16(oup), oup - MOVO B0, A0 - MOVO C0, B0 - MOVO D0, C0 + SUBQ $0x10, BX + MOVOU (SI), X12 + PXOR X12, X0 + MOVOU X0, (DI) + LEAQ 16(SI), SI + LEAQ 16(DI), DI + MOVO X3, X0 + MOVO X6, X3 + MOVO X9, X6 JMP openSSETail64DecLoop openSSETail64DecLoopDone: - MOVO A0, A1 + MOVO X0, X1 JMP openSSETail16 -// ---------------------------------------------------------------------------- -// Special optimization for the last 128 bytes of ciphertext openSSETail128: - // Need to decrypt up to 128 bytes - prepare two blocks - MOVO ·chacha20Constants<>(SB), A1; MOVO state1Store, B1; MOVO state2Store, C1; MOVO ctr3Store, D1; PADDL ·sseIncMask<>(SB), D1; MOVO D1, ctr0Store - MOVO A1, A0; MOVO B1, B0; MOVO C1, C0; MOVO D1, D0; PADDL ·sseIncMask<>(SB), D0; MOVO D0, ctr1Store - XORQ itr2, itr2 - MOVQ inl, itr1 - ANDQ $-16, itr1 + MOVO ·chacha20Constants<>+0(SB), X1 + MOVO 32(BP), X4 + MOVO 48(BP), X7 + MOVO 128(BP), X10 + PADDL ·sseIncMask<>+0(SB), X10 + MOVO X10, 80(BP) + MOVO X1, X0 + MOVO X4, X3 + MOVO X7, X6 + MOVO X10, X9 + PADDL ·sseIncMask<>+0(SB), X9 + MOVO X9, 96(BP) + XORQ R9, R9 + MOVQ BX, CX + ANDQ $-16, CX openSSETail128LoopA: - // Perform ChaCha rounds, while hashing the remaining input - polyAdd(0(inp)(itr2*1)) - polyMul + ADDQ (SI)(R9*1), R10 + ADCQ 8(SI)(R9*1), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 openSSETail128LoopB: - ADDQ $16, itr2 - chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0) - shiftB0Left; shiftC0Left; shiftD0Left - shiftB1Left; shiftC1Left; shiftD1Left - chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0) - shiftB0Right; shiftC0Right; shiftD0Right - shiftB1Right; shiftC1Right; shiftD1Right - - CMPQ itr2, itr1 - JB openSSETail128LoopA - - CMPQ itr2, $160 - JNE openSSETail128LoopB - - PADDL ·chacha20Constants<>(SB), A0; PADDL ·chacha20Constants<>(SB), A1 - PADDL state1Store, B0; PADDL state1Store, B1 - PADDL state2Store, C0; PADDL state2Store, C1 - PADDL ctr1Store, D0; PADDL ctr0Store, D1 - - MOVOU (0*16)(inp), T0; MOVOU (1*16)(inp), T1; MOVOU (2*16)(inp), T2; MOVOU (3*16)(inp), T3 - PXOR T0, A1; PXOR T1, B1; PXOR T2, C1; PXOR T3, D1 - MOVOU A1, (0*16)(oup); MOVOU B1, (1*16)(oup); MOVOU C1, (2*16)(oup); MOVOU D1, (3*16)(oup) - - SUBQ $64, inl - LEAQ 64(inp), inp - LEAQ 64(oup), oup - JMP openSSETail64DecLoop - -// ---------------------------------------------------------------------------- -// Special optimization for the last 192 bytes of ciphertext + ADDQ $0x10, R9 + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X3 + PXOR X12, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X3 + PXOR X12, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X4 + PXOR X12, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X4 + PXOR X12, X4 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x0c + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X3 + PXOR X12, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X3 + PXOR X12, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X4 + PXOR X12, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X4 + PXOR X12, X4 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x04 + CMPQ R9, CX + JB openSSETail128LoopA + CMPQ R9, $0xa0 + JNE openSSETail128LoopB + PADDL ·chacha20Constants<>+0(SB), X0 + PADDL ·chacha20Constants<>+0(SB), X1 + PADDL 32(BP), X3 + PADDL 32(BP), X4 + PADDL 48(BP), X6 + PADDL 48(BP), X7 + PADDL 96(BP), X9 + PADDL 80(BP), X10 + MOVOU (SI), X12 + MOVOU 16(SI), X13 + MOVOU 32(SI), X14 + MOVOU 48(SI), X15 + PXOR X12, X1 + PXOR X13, X4 + PXOR X14, X7 + PXOR X15, X10 + MOVOU X1, (DI) + MOVOU X4, 16(DI) + MOVOU X7, 32(DI) + MOVOU X10, 48(DI) + SUBQ $0x40, BX + LEAQ 64(SI), SI + LEAQ 64(DI), DI + JMP openSSETail64DecLoop + openSSETail192: - // Need to decrypt up to 192 bytes - prepare three blocks - MOVO ·chacha20Constants<>(SB), A2; MOVO state1Store, B2; MOVO state2Store, C2; MOVO ctr3Store, D2; PADDL ·sseIncMask<>(SB), D2; MOVO D2, ctr0Store - MOVO A2, A1; MOVO B2, B1; MOVO C2, C1; MOVO D2, D1; PADDL ·sseIncMask<>(SB), D1; MOVO D1, ctr1Store - MOVO A1, A0; MOVO B1, B0; MOVO C1, C0; MOVO D1, D0; PADDL ·sseIncMask<>(SB), D0; MOVO D0, ctr2Store - - MOVQ inl, itr1 - MOVQ $160, itr2 - CMPQ itr1, $160 - CMOVQGT itr2, itr1 - ANDQ $-16, itr1 - XORQ itr2, itr2 + MOVO ·chacha20Constants<>+0(SB), X2 + MOVO 32(BP), X5 + MOVO 48(BP), X8 + MOVO 128(BP), X11 + PADDL ·sseIncMask<>+0(SB), X11 + MOVO X11, 80(BP) + MOVO X2, X1 + MOVO X5, X4 + MOVO X8, X7 + MOVO X11, X10 + PADDL ·sseIncMask<>+0(SB), X10 + MOVO X10, 96(BP) + MOVO X1, X0 + MOVO X4, X3 + MOVO X7, X6 + MOVO X10, X9 + PADDL ·sseIncMask<>+0(SB), X9 + MOVO X9, 112(BP) + MOVQ BX, CX + MOVQ $0x000000a0, R9 + CMPQ CX, $0xa0 + CMOVQGT R9, CX + ANDQ $-16, CX + XORQ R9, R9 openSSLTail192LoopA: - // Perform ChaCha rounds, while hashing the remaining input - polyAdd(0(inp)(itr2*1)) - polyMul + ADDQ (SI)(R9*1), R10 + ADCQ 8(SI)(R9*1), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 openSSLTail192LoopB: - ADDQ $16, itr2 - chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0); chachaQR(A2, B2, C2, D2, T0) - shiftB0Left; shiftC0Left; shiftD0Left - shiftB1Left; shiftC1Left; shiftD1Left - shiftB2Left; shiftC2Left; shiftD2Left - - chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0); chachaQR(A2, B2, C2, D2, T0) - shiftB0Right; shiftC0Right; shiftD0Right - shiftB1Right; shiftC1Right; shiftD1Right - shiftB2Right; shiftC2Right; shiftD2Right - - CMPQ itr2, itr1 - JB openSSLTail192LoopA - - CMPQ itr2, $160 - JNE openSSLTail192LoopB - - CMPQ inl, $176 - JB openSSLTail192Store - - polyAdd(160(inp)) - polyMul - - CMPQ inl, $192 - JB openSSLTail192Store - - polyAdd(176(inp)) - polyMul + ADDQ $0x10, R9 + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X3 + PXOR X12, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X3 + PXOR X12, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X4 + PXOR X12, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X4 + PXOR X12, X4 + PADDD X5, X2 + PXOR X2, X11 + ROL16(X11, X12) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X5 + PXOR X12, X5 + PADDD X5, X2 + PXOR X2, X11 + ROL8(X11, X12) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X5 + PXOR X12, X5 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc0 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X3 + PXOR X12, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X3 + PXOR X12, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X4 + PXOR X12, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X4 + PXOR X12, X4 + PADDD X5, X2 + PXOR X2, X11 + ROL16(X11, X12) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X5 + PXOR X12, X5 + PADDD X5, X2 + PXOR X2, X11 + ROL8(X11, X12) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X5 + PXOR X12, X5 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc0 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + CMPQ R9, CX + JB openSSLTail192LoopA + CMPQ R9, $0xa0 + JNE openSSLTail192LoopB + CMPQ BX, $0xb0 + JB openSSLTail192Store + ADDQ 160(SI), R10 + ADCQ 168(SI), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + CMPQ BX, $0xc0 + JB openSSLTail192Store + ADDQ 176(SI), R10 + ADCQ 184(SI), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 openSSLTail192Store: - PADDL ·chacha20Constants<>(SB), A0; PADDL ·chacha20Constants<>(SB), A1; PADDL ·chacha20Constants<>(SB), A2 - PADDL state1Store, B0; PADDL state1Store, B1; PADDL state1Store, B2 - PADDL state2Store, C0; PADDL state2Store, C1; PADDL state2Store, C2 - PADDL ctr2Store, D0; PADDL ctr1Store, D1; PADDL ctr0Store, D2 - - MOVOU (0*16)(inp), T0; MOVOU (1*16)(inp), T1; MOVOU (2*16)(inp), T2; MOVOU (3*16)(inp), T3 - PXOR T0, A2; PXOR T1, B2; PXOR T2, C2; PXOR T3, D2 - MOVOU A2, (0*16)(oup); MOVOU B2, (1*16)(oup); MOVOU C2, (2*16)(oup); MOVOU D2, (3*16)(oup) - - MOVOU (4*16)(inp), T0; MOVOU (5*16)(inp), T1; MOVOU (6*16)(inp), T2; MOVOU (7*16)(inp), T3 - PXOR T0, A1; PXOR T1, B1; PXOR T2, C1; PXOR T3, D1 - MOVOU A1, (4*16)(oup); MOVOU B1, (5*16)(oup); MOVOU C1, (6*16)(oup); MOVOU D1, (7*16)(oup) - - SUBQ $128, inl - LEAQ 128(inp), inp - LEAQ 128(oup), oup - JMP openSSETail64DecLoop - -// ---------------------------------------------------------------------------- -// Special optimization for the last 256 bytes of ciphertext + PADDL ·chacha20Constants<>+0(SB), X0 + PADDL ·chacha20Constants<>+0(SB), X1 + PADDL ·chacha20Constants<>+0(SB), X2 + PADDL 32(BP), X3 + PADDL 32(BP), X4 + PADDL 32(BP), X5 + PADDL 48(BP), X6 + PADDL 48(BP), X7 + PADDL 48(BP), X8 + PADDL 112(BP), X9 + PADDL 96(BP), X10 + PADDL 80(BP), X11 + MOVOU (SI), X12 + MOVOU 16(SI), X13 + MOVOU 32(SI), X14 + MOVOU 48(SI), X15 + PXOR X12, X2 + PXOR X13, X5 + PXOR X14, X8 + PXOR X15, X11 + MOVOU X2, (DI) + MOVOU X5, 16(DI) + MOVOU X8, 32(DI) + MOVOU X11, 48(DI) + MOVOU 64(SI), X12 + MOVOU 80(SI), X13 + MOVOU 96(SI), X14 + MOVOU 112(SI), X15 + PXOR X12, X1 + PXOR X13, X4 + PXOR X14, X7 + PXOR X15, X10 + MOVOU X1, 64(DI) + MOVOU X4, 80(DI) + MOVOU X7, 96(DI) + MOVOU X10, 112(DI) + SUBQ $0x80, BX + LEAQ 128(SI), SI + LEAQ 128(DI), DI + JMP openSSETail64DecLoop + openSSETail256: - // Need to decrypt up to 256 bytes - prepare four blocks - MOVO ·chacha20Constants<>(SB), A0; MOVO state1Store, B0; MOVO state2Store, C0; MOVO ctr3Store, D0; PADDL ·sseIncMask<>(SB), D0 - MOVO A0, A1; MOVO B0, B1; MOVO C0, C1; MOVO D0, D1; PADDL ·sseIncMask<>(SB), D1 - MOVO A1, A2; MOVO B1, B2; MOVO C1, C2; MOVO D1, D2; PADDL ·sseIncMask<>(SB), D2 - MOVO A2, A3; MOVO B2, B3; MOVO C2, C3; MOVO D2, D3; PADDL ·sseIncMask<>(SB), D3 + MOVO ·chacha20Constants<>+0(SB), X0 + MOVO 32(BP), X3 + MOVO 48(BP), X6 + MOVO 128(BP), X9 + PADDL ·sseIncMask<>+0(SB), X9 + MOVO X0, X1 + MOVO X3, X4 + MOVO X6, X7 + MOVO X9, X10 + PADDL ·sseIncMask<>+0(SB), X10 + MOVO X1, X2 + MOVO X4, X5 + MOVO X7, X8 + MOVO X10, X11 + PADDL ·sseIncMask<>+0(SB), X11 + MOVO X2, X12 + MOVO X5, X13 + MOVO X8, X14 + MOVO X11, X15 + PADDL ·sseIncMask<>+0(SB), X15 // Store counters - MOVO D0, ctr0Store; MOVO D1, ctr1Store; MOVO D2, ctr2Store; MOVO D3, ctr3Store - XORQ itr2, itr2 + MOVO X9, 80(BP) + MOVO X10, 96(BP) + MOVO X11, 112(BP) + MOVO X15, 128(BP) + XORQ R9, R9 openSSETail256Loop: - // This loop inteleaves 8 ChaCha quarter rounds with 1 poly multiplication - polyAdd(0(inp)(itr2*1)) - MOVO C3, tmpStore - chachaQR(A0, B0, C0, D0, C3); chachaQR(A1, B1, C1, D1, C3); chachaQR(A2, B2, C2, D2, C3) - MOVO tmpStore, C3 - MOVO C1, tmpStore - chachaQR(A3, B3, C3, D3, C1) - MOVO tmpStore, C1 - shiftB0Left; shiftB1Left; shiftB2Left; shiftB3Left - shiftC0Left; shiftC1Left; shiftC2Left; shiftC3Left - shiftD0Left; shiftD1Left; shiftD2Left; shiftD3Left - polyMulStage1 - polyMulStage2 - MOVO C3, tmpStore - chachaQR(A0, B0, C0, D0, C3); chachaQR(A1, B1, C1, D1, C3); chachaQR(A2, B2, C2, D2, C3) - MOVO tmpStore, C3 - MOVO C1, tmpStore - chachaQR(A3, B3, C3, D3, C1) - MOVO tmpStore, C1 - polyMulStage3 - polyMulReduceStage - shiftB0Right; shiftB1Right; shiftB2Right; shiftB3Right - shiftC0Right; shiftC1Right; shiftC2Right; shiftC3Right - shiftD0Right; shiftD1Right; shiftD2Right; shiftD3Right - ADDQ $2*8, itr2 - CMPQ itr2, $160 - JB openSSETail256Loop - MOVQ inl, itr1 - ANDQ $-16, itr1 + ADDQ (SI)(R9*1), R10 + ADCQ 8(SI)(R9*1), R11 + ADCQ $0x01, R12 + MOVO X14, 64(BP) + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X14) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X3 + PXOR X14, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X14) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X3 + PXOR X14, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X14) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X4 + PXOR X14, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X14) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X4 + PXOR X14, X4 + PADDD X5, X2 + PXOR X2, X11 + ROL16(X11, X14) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X5 + PXOR X14, X5 + PADDD X5, X2 + PXOR X2, X11 + ROL8(X11, X14) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X5 + PXOR X14, X5 + MOVO 64(BP), X14 + MOVO X7, 64(BP) + PADDD X13, X12 + PXOR X12, X15 + ROL16(X15, X7) + PADDD X15, X14 + PXOR X14, X13 + MOVO X13, X7 + PSLLL $0x0c, X7 + PSRLL $0x14, X13 + PXOR X7, X13 + PADDD X13, X12 + PXOR X12, X15 + ROL8(X15, X7) + PADDD X15, X14 + PXOR X14, X13 + MOVO X13, X7 + PSLLL $0x07, X7 + PSRLL $0x19, X13 + PXOR X7, X13 + MOVO 64(BP), X7 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc0 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x0c + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + MOVO X14, 64(BP) + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X14) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X3 + PXOR X14, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X14) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X3 + PXOR X14, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X14) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X4 + PXOR X14, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X14) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X4 + PXOR X14, X4 + PADDD X5, X2 + PXOR X2, X11 + ROL16(X11, X14) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X5 + PXOR X14, X5 + PADDD X5, X2 + PXOR X2, X11 + ROL8(X11, X14) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X5 + PXOR X14, X5 + MOVO 64(BP), X14 + MOVO X7, 64(BP) + PADDD X13, X12 + PXOR X12, X15 + ROL16(X15, X7) + PADDD X15, X14 + PXOR X14, X13 + MOVO X13, X7 + PSLLL $0x0c, X7 + PSRLL $0x14, X13 + PXOR X7, X13 + PADDD X13, X12 + PXOR X12, X15 + ROL8(X15, X7) + PADDD X15, X14 + PXOR X14, X13 + MOVO X13, X7 + PSLLL $0x07, X7 + PSRLL $0x19, X13 + PXOR X7, X13 + MOVO 64(BP), X7 + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc0 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x04 + ADDQ $0x10, R9 + CMPQ R9, $0xa0 + JB openSSETail256Loop + MOVQ BX, CX + ANDQ $-16, CX openSSETail256HashLoop: - polyAdd(0(inp)(itr2*1)) - polyMul - ADDQ $2*8, itr2 - CMPQ itr2, itr1 - JB openSSETail256HashLoop + ADDQ (SI)(R9*1), R10 + ADCQ 8(SI)(R9*1), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + ADDQ $0x10, R9 + CMPQ R9, CX + JB openSSETail256HashLoop // Add in the state - PADDD ·chacha20Constants<>(SB), A0; PADDD ·chacha20Constants<>(SB), A1; PADDD ·chacha20Constants<>(SB), A2; PADDD ·chacha20Constants<>(SB), A3 - PADDD state1Store, B0; PADDD state1Store, B1; PADDD state1Store, B2; PADDD state1Store, B3 - PADDD state2Store, C0; PADDD state2Store, C1; PADDD state2Store, C2; PADDD state2Store, C3 - PADDD ctr0Store, D0; PADDD ctr1Store, D1; PADDD ctr2Store, D2; PADDD ctr3Store, D3 - MOVO D3, tmpStore + PADDD ·chacha20Constants<>+0(SB), X0 + PADDD ·chacha20Constants<>+0(SB), X1 + PADDD ·chacha20Constants<>+0(SB), X2 + PADDD ·chacha20Constants<>+0(SB), X12 + PADDD 32(BP), X3 + PADDD 32(BP), X4 + PADDD 32(BP), X5 + PADDD 32(BP), X13 + PADDD 48(BP), X6 + PADDD 48(BP), X7 + PADDD 48(BP), X8 + PADDD 48(BP), X14 + PADDD 80(BP), X9 + PADDD 96(BP), X10 + PADDD 112(BP), X11 + PADDD 128(BP), X15 + MOVO X15, 64(BP) // Load - xor - store - MOVOU (0*16)(inp), D3; PXOR D3, A0 - MOVOU (1*16)(inp), D3; PXOR D3, B0 - MOVOU (2*16)(inp), D3; PXOR D3, C0 - MOVOU (3*16)(inp), D3; PXOR D3, D0 - MOVOU A0, (0*16)(oup) - MOVOU B0, (1*16)(oup) - MOVOU C0, (2*16)(oup) - MOVOU D0, (3*16)(oup) - MOVOU (4*16)(inp), A0; MOVOU (5*16)(inp), B0; MOVOU (6*16)(inp), C0; MOVOU (7*16)(inp), D0 - PXOR A0, A1; PXOR B0, B1; PXOR C0, C1; PXOR D0, D1 - MOVOU A1, (4*16)(oup); MOVOU B1, (5*16)(oup); MOVOU C1, (6*16)(oup); MOVOU D1, (7*16)(oup) - MOVOU (8*16)(inp), A0; MOVOU (9*16)(inp), B0; MOVOU (10*16)(inp), C0; MOVOU (11*16)(inp), D0 - PXOR A0, A2; PXOR B0, B2; PXOR C0, C2; PXOR D0, D2 - MOVOU A2, (8*16)(oup); MOVOU B2, (9*16)(oup); MOVOU C2, (10*16)(oup); MOVOU D2, (11*16)(oup) - LEAQ 192(inp), inp - LEAQ 192(oup), oup - SUBQ $192, inl - MOVO A3, A0 - MOVO B3, B0 - MOVO C3, C0 - MOVO tmpStore, D0 - - JMP openSSETail64DecLoop - -// ---------------------------------------------------------------------------- -// ------------------------- AVX2 Code ---------------------------------------- + MOVOU (SI), X15 + PXOR X15, X0 + MOVOU 16(SI), X15 + PXOR X15, X3 + MOVOU 32(SI), X15 + PXOR X15, X6 + MOVOU 48(SI), X15 + PXOR X15, X9 + MOVOU X0, (DI) + MOVOU X3, 16(DI) + MOVOU X6, 32(DI) + MOVOU X9, 48(DI) + MOVOU 64(SI), X0 + MOVOU 80(SI), X3 + MOVOU 96(SI), X6 + MOVOU 112(SI), X9 + PXOR X0, X1 + PXOR X3, X4 + PXOR X6, X7 + PXOR X9, X10 + MOVOU X1, 64(DI) + MOVOU X4, 80(DI) + MOVOU X7, 96(DI) + MOVOU X10, 112(DI) + MOVOU 128(SI), X0 + MOVOU 144(SI), X3 + MOVOU 160(SI), X6 + MOVOU 176(SI), X9 + PXOR X0, X2 + PXOR X3, X5 + PXOR X6, X8 + PXOR X9, X11 + MOVOU X2, 128(DI) + MOVOU X5, 144(DI) + MOVOU X8, 160(DI) + MOVOU X11, 176(DI) + LEAQ 192(SI), SI + LEAQ 192(DI), DI + SUBQ $0xc0, BX + MOVO X12, X0 + MOVO X13, X3 + MOVO X14, X6 + MOVO 64(BP), X9 + JMP openSSETail64DecLoop + chacha20Poly1305Open_AVX2: VZEROUPPER - VMOVDQU ·chacha20Constants<>(SB), AA0 - BYTE $0xc4; BYTE $0x42; BYTE $0x7d; BYTE $0x5a; BYTE $0x70; BYTE $0x10 // broadcasti128 16(r8), ymm14 - BYTE $0xc4; BYTE $0x42; BYTE $0x7d; BYTE $0x5a; BYTE $0x60; BYTE $0x20 // broadcasti128 32(r8), ymm12 - BYTE $0xc4; BYTE $0xc2; BYTE $0x7d; BYTE $0x5a; BYTE $0x60; BYTE $0x30 // broadcasti128 48(r8), ymm4 - VPADDD ·avx2InitMask<>(SB), DD0, DD0 + VMOVDQU ·chacha20Constants<>+0(SB), Y0 + BYTE $0xc4 + BYTE $0x42 + BYTE $0x7d + BYTE $0x5a + BYTE $0x70 + BYTE $0x10 + BYTE $0xc4 + BYTE $0x42 + BYTE $0x7d + BYTE $0x5a + BYTE $0x60 + BYTE $0x20 + BYTE $0xc4 + BYTE $0xc2 + BYTE $0x7d + BYTE $0x5a + BYTE $0x60 + BYTE $0x30 + VPADDD ·avx2InitMask<>+0(SB), Y4, Y4 // Special optimization, for very short buffers - CMPQ inl, $192 + CMPQ BX, $0xc0 JBE openAVX2192 - CMPQ inl, $320 + CMPQ BX, $0x00000140 JBE openAVX2320 // For the general key prepare the key first - as a byproduct we have 64 bytes of cipher stream - VMOVDQA BB0, state1StoreAVX2 - VMOVDQA CC0, state2StoreAVX2 - VMOVDQA DD0, ctr3StoreAVX2 - MOVQ $10, itr2 + VMOVDQA Y14, 32(BP) + VMOVDQA Y12, 64(BP) + VMOVDQA Y4, 192(BP) + MOVQ $0x0000000a, R9 openAVX2PreparePolyKey: - chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0) - VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $12, DD0, DD0, DD0 - chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0) - VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $4, DD0, DD0, DD0 - DECQ itr2 - JNE openAVX2PreparePolyKey - - VPADDD ·chacha20Constants<>(SB), AA0, AA0 - VPADDD state1StoreAVX2, BB0, BB0 - VPADDD state2StoreAVX2, CC0, CC0 - VPADDD ctr3StoreAVX2, DD0, DD0 - - VPERM2I128 $0x02, AA0, BB0, TT0 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y3 + VPSRLD $0x14, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y3 + VPSRLD $0x19, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPALIGNR $0x04, Y14, Y14, Y14 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x0c, Y4, Y4, Y4 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y3 + VPSRLD $0x14, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y3 + VPSRLD $0x19, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPALIGNR $0x0c, Y14, Y14, Y14 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x04, Y4, Y4, Y4 + DECQ R9 + JNE openAVX2PreparePolyKey + VPADDD ·chacha20Constants<>+0(SB), Y0, Y0 + VPADDD 32(BP), Y14, Y14 + VPADDD 64(BP), Y12, Y12 + VPADDD 192(BP), Y4, Y4 + VPERM2I128 $0x02, Y0, Y14, Y3 // Clamp and store poly key - VPAND ·polyClampMask<>(SB), TT0, TT0 - VMOVDQA TT0, rsStoreAVX2 + VPAND ·polyClampMask<>+0(SB), Y3, Y3 + VMOVDQA Y3, (BP) // Stream for the first 64 bytes - VPERM2I128 $0x13, AA0, BB0, AA0 - VPERM2I128 $0x13, CC0, DD0, BB0 + VPERM2I128 $0x13, Y0, Y14, Y0 + VPERM2I128 $0x13, Y12, Y4, Y14 // Hash AD + first 64 bytes - MOVQ ad_len+80(FP), itr2 + MOVQ ad_len+80(FP), R9 CALL polyHashADInternal<>(SB) - XORQ itr1, itr1 + XORQ CX, CX openAVX2InitialHash64: - polyAdd(0(inp)(itr1*1)) - polyMulAVX2 - ADDQ $16, itr1 - CMPQ itr1, $64 - JNE openAVX2InitialHash64 + ADDQ (SI)(CX*1), R10 + ADCQ 8(SI)(CX*1), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + ADDQ $0x10, CX + CMPQ CX, $0x40 + JNE openAVX2InitialHash64 // Decrypt the first 64 bytes - VPXOR (0*32)(inp), AA0, AA0 - VPXOR (1*32)(inp), BB0, BB0 - VMOVDQU AA0, (0*32)(oup) - VMOVDQU BB0, (1*32)(oup) - LEAQ (2*32)(inp), inp - LEAQ (2*32)(oup), oup - SUBQ $64, inl + VPXOR (SI), Y0, Y0 + VPXOR 32(SI), Y14, Y14 + VMOVDQU Y0, (DI) + VMOVDQU Y14, 32(DI) + LEAQ 64(SI), SI + LEAQ 64(DI), DI + SUBQ $0x40, BX openAVX2MainLoop: - CMPQ inl, $512 + CMPQ BX, $0x00000200 JB openAVX2MainLoopDone // Load state, increment counter blocks, store the incremented counters - VMOVDQU ·chacha20Constants<>(SB), AA0; VMOVDQA AA0, AA1; VMOVDQA AA0, AA2; VMOVDQA AA0, AA3 - VMOVDQA state1StoreAVX2, BB0; VMOVDQA BB0, BB1; VMOVDQA BB0, BB2; VMOVDQA BB0, BB3 - VMOVDQA state2StoreAVX2, CC0; VMOVDQA CC0, CC1; VMOVDQA CC0, CC2; VMOVDQA CC0, CC3 - VMOVDQA ctr3StoreAVX2, DD0; VPADDD ·avx2IncMask<>(SB), DD0, DD0; VPADDD ·avx2IncMask<>(SB), DD0, DD1; VPADDD ·avx2IncMask<>(SB), DD1, DD2; VPADDD ·avx2IncMask<>(SB), DD2, DD3 - VMOVDQA DD0, ctr0StoreAVX2; VMOVDQA DD1, ctr1StoreAVX2; VMOVDQA DD2, ctr2StoreAVX2; VMOVDQA DD3, ctr3StoreAVX2 - XORQ itr1, itr1 + VMOVDQU ·chacha20Constants<>+0(SB), Y0 + VMOVDQA Y0, Y5 + VMOVDQA Y0, Y6 + VMOVDQA Y0, Y7 + VMOVDQA 32(BP), Y14 + VMOVDQA Y14, Y9 + VMOVDQA Y14, Y10 + VMOVDQA Y14, Y11 + VMOVDQA 64(BP), Y12 + VMOVDQA Y12, Y13 + VMOVDQA Y12, Y8 + VMOVDQA Y12, Y15 + VMOVDQA 192(BP), Y4 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y4 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y1 + VPADDD ·avx2IncMask<>+0(SB), Y1, Y2 + VPADDD ·avx2IncMask<>+0(SB), Y2, Y3 + VMOVDQA Y4, 96(BP) + VMOVDQA Y1, 128(BP) + VMOVDQA Y2, 160(BP) + VMOVDQA Y3, 192(BP) + XORQ CX, CX openAVX2InternalLoop: - // Lets just say this spaghetti loop interleaves 2 quarter rounds with 3 poly multiplications - // Effectively per 512 bytes of stream we hash 480 bytes of ciphertext - polyAdd(0*8(inp)(itr1*1)) - VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 - polyMulStage1_AVX2 - VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 - VPSHUFB ·rol16<>(SB), DD0, DD0; VPSHUFB ·rol16<>(SB), DD1, DD1; VPSHUFB ·rol16<>(SB), DD2, DD2; VPSHUFB ·rol16<>(SB), DD3, DD3 - polyMulStage2_AVX2 - VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 - VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 - polyMulStage3_AVX2 - VMOVDQA CC3, tmpStoreAVX2 - VPSLLD $12, BB0, CC3; VPSRLD $20, BB0, BB0; VPXOR CC3, BB0, BB0 - VPSLLD $12, BB1, CC3; VPSRLD $20, BB1, BB1; VPXOR CC3, BB1, BB1 - VPSLLD $12, BB2, CC3; VPSRLD $20, BB2, BB2; VPXOR CC3, BB2, BB2 - VPSLLD $12, BB3, CC3; VPSRLD $20, BB3, BB3; VPXOR CC3, BB3, BB3 - VMOVDQA tmpStoreAVX2, CC3 - polyMulReduceStage - VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 - VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 - VPSHUFB ·rol8<>(SB), DD0, DD0; VPSHUFB ·rol8<>(SB), DD1, DD1; VPSHUFB ·rol8<>(SB), DD2, DD2; VPSHUFB ·rol8<>(SB), DD3, DD3 - polyAdd(2*8(inp)(itr1*1)) - VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 - polyMulStage1_AVX2 - VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 - VMOVDQA CC3, tmpStoreAVX2 - VPSLLD $7, BB0, CC3; VPSRLD $25, BB0, BB0; VPXOR CC3, BB0, BB0 - VPSLLD $7, BB1, CC3; VPSRLD $25, BB1, BB1; VPXOR CC3, BB1, BB1 - VPSLLD $7, BB2, CC3; VPSRLD $25, BB2, BB2; VPXOR CC3, BB2, BB2 - VPSLLD $7, BB3, CC3; VPSRLD $25, BB3, BB3; VPXOR CC3, BB3, BB3 - VMOVDQA tmpStoreAVX2, CC3 - polyMulStage2_AVX2 - VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $4, BB2, BB2, BB2; VPALIGNR $4, BB3, BB3, BB3 - VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $8, CC3, CC3, CC3 - VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1; VPALIGNR $12, DD2, DD2, DD2; VPALIGNR $12, DD3, DD3, DD3 - VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 - polyMulStage3_AVX2 - VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 - VPSHUFB ·rol16<>(SB), DD0, DD0; VPSHUFB ·rol16<>(SB), DD1, DD1; VPSHUFB ·rol16<>(SB), DD2, DD2; VPSHUFB ·rol16<>(SB), DD3, DD3 - polyMulReduceStage - VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 - VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 - polyAdd(4*8(inp)(itr1*1)) - LEAQ (6*8)(itr1), itr1 - VMOVDQA CC3, tmpStoreAVX2 - VPSLLD $12, BB0, CC3; VPSRLD $20, BB0, BB0; VPXOR CC3, BB0, BB0 - VPSLLD $12, BB1, CC3; VPSRLD $20, BB1, BB1; VPXOR CC3, BB1, BB1 - VPSLLD $12, BB2, CC3; VPSRLD $20, BB2, BB2; VPXOR CC3, BB2, BB2 - VPSLLD $12, BB3, CC3; VPSRLD $20, BB3, BB3; VPXOR CC3, BB3, BB3 - VMOVDQA tmpStoreAVX2, CC3 - polyMulStage1_AVX2 - VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 - VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 - polyMulStage2_AVX2 - VPSHUFB ·rol8<>(SB), DD0, DD0; VPSHUFB ·rol8<>(SB), DD1, DD1; VPSHUFB ·rol8<>(SB), DD2, DD2; VPSHUFB ·rol8<>(SB), DD3, DD3 - VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 - polyMulStage3_AVX2 - VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 - VMOVDQA CC3, tmpStoreAVX2 - VPSLLD $7, BB0, CC3; VPSRLD $25, BB0, BB0; VPXOR CC3, BB0, BB0 - VPSLLD $7, BB1, CC3; VPSRLD $25, BB1, BB1; VPXOR CC3, BB1, BB1 - VPSLLD $7, BB2, CC3; VPSRLD $25, BB2, BB2; VPXOR CC3, BB2, BB2 - VPSLLD $7, BB3, CC3; VPSRLD $25, BB3, BB3; VPXOR CC3, BB3, BB3 - VMOVDQA tmpStoreAVX2, CC3 - polyMulReduceStage - VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $12, BB2, BB2, BB2; VPALIGNR $12, BB3, BB3, BB3 - VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $8, CC3, CC3, CC3 - VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1; VPALIGNR $4, DD2, DD2, DD2; VPALIGNR $4, DD3, DD3, DD3 - CMPQ itr1, $480 + ADDQ (SI)(CX*1), R10 + ADCQ 8(SI)(CX*1), R11 + ADCQ $0x01, R12 + VPADDD Y14, Y0, Y0 + VPADDD Y9, Y5, Y5 + VPADDD Y10, Y6, Y6 + VPADDD Y11, Y7, Y7 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + VPXOR Y0, Y4, Y4 + VPXOR Y5, Y1, Y1 + VPXOR Y6, Y2, Y2 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y2, Y2 + VPSHUFB ·rol16<>+0(SB), Y3, Y3 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + VPADDD Y4, Y12, Y12 + VPADDD Y1, Y13, Y13 + VPADDD Y2, Y8, Y8 + VPADDD Y3, Y15, Y15 + VPXOR Y12, Y14, Y14 + VPXOR Y13, Y9, Y9 + VPXOR Y8, Y10, Y10 + VPXOR Y15, Y11, Y11 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + VMOVDQA Y15, 224(BP) + VPSLLD $0x0c, Y14, Y15 + VPSRLD $0x14, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPSLLD $0x0c, Y9, Y15 + VPSRLD $0x14, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPSLLD $0x0c, Y10, Y15 + VPSRLD $0x14, Y10, Y10 + VPXOR Y15, Y10, Y10 + VPSLLD $0x0c, Y11, Y15 + VPSRLD $0x14, Y11, Y11 + VPXOR Y15, Y11, Y11 + VMOVDQA 224(BP), Y15 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + VPADDD Y14, Y0, Y0 + VPADDD Y9, Y5, Y5 + VPADDD Y10, Y6, Y6 + VPADDD Y11, Y7, Y7 + VPXOR Y0, Y4, Y4 + VPXOR Y5, Y1, Y1 + VPXOR Y6, Y2, Y2 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y2, Y2 + VPSHUFB ·rol8<>+0(SB), Y3, Y3 + ADDQ 16(SI)(CX*1), R10 + ADCQ 24(SI)(CX*1), R11 + ADCQ $0x01, R12 + VPADDD Y4, Y12, Y12 + VPADDD Y1, Y13, Y13 + VPADDD Y2, Y8, Y8 + VPADDD Y3, Y15, Y15 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + VPXOR Y12, Y14, Y14 + VPXOR Y13, Y9, Y9 + VPXOR Y8, Y10, Y10 + VPXOR Y15, Y11, Y11 + VMOVDQA Y15, 224(BP) + VPSLLD $0x07, Y14, Y15 + VPSRLD $0x19, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPSLLD $0x07, Y9, Y15 + VPSRLD $0x19, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPSLLD $0x07, Y10, Y15 + VPSRLD $0x19, Y10, Y10 + VPXOR Y15, Y10, Y10 + VPSLLD $0x07, Y11, Y15 + VPSRLD $0x19, Y11, Y11 + VPXOR Y15, Y11, Y11 + VMOVDQA 224(BP), Y15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + VPALIGNR $0x04, Y14, Y14, Y14 + VPALIGNR $0x04, Y9, Y9, Y9 + VPALIGNR $0x04, Y10, Y10, Y10 + VPALIGNR $0x04, Y11, Y11, Y11 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x08, Y8, Y8, Y8 + VPALIGNR $0x08, Y15, Y15, Y15 + VPALIGNR $0x0c, Y4, Y4, Y4 + VPALIGNR $0x0c, Y1, Y1, Y1 + VPALIGNR $0x0c, Y2, Y2, Y2 + VPALIGNR $0x0c, Y3, Y3, Y3 + VPADDD Y14, Y0, Y0 + VPADDD Y9, Y5, Y5 + VPADDD Y10, Y6, Y6 + VPADDD Y11, Y7, Y7 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + VPXOR Y0, Y4, Y4 + VPXOR Y5, Y1, Y1 + VPXOR Y6, Y2, Y2 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y2, Y2 + VPSHUFB ·rol16<>+0(SB), Y3, Y3 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + VPADDD Y4, Y12, Y12 + VPADDD Y1, Y13, Y13 + VPADDD Y2, Y8, Y8 + VPADDD Y3, Y15, Y15 + VPXOR Y12, Y14, Y14 + VPXOR Y13, Y9, Y9 + VPXOR Y8, Y10, Y10 + VPXOR Y15, Y11, Y11 + ADDQ 32(SI)(CX*1), R10 + ADCQ 40(SI)(CX*1), R11 + ADCQ $0x01, R12 + LEAQ 48(CX), CX + VMOVDQA Y15, 224(BP) + VPSLLD $0x0c, Y14, Y15 + VPSRLD $0x14, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPSLLD $0x0c, Y9, Y15 + VPSRLD $0x14, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPSLLD $0x0c, Y10, Y15 + VPSRLD $0x14, Y10, Y10 + VPXOR Y15, Y10, Y10 + VPSLLD $0x0c, Y11, Y15 + VPSRLD $0x14, Y11, Y11 + VPXOR Y15, Y11, Y11 + VMOVDQA 224(BP), Y15 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + VPADDD Y14, Y0, Y0 + VPADDD Y9, Y5, Y5 + VPADDD Y10, Y6, Y6 + VPADDD Y11, Y7, Y7 + VPXOR Y0, Y4, Y4 + VPXOR Y5, Y1, Y1 + VPXOR Y6, Y2, Y2 + VPXOR Y7, Y3, Y3 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y2, Y2 + VPSHUFB ·rol8<>+0(SB), Y3, Y3 + VPADDD Y4, Y12, Y12 + VPADDD Y1, Y13, Y13 + VPADDD Y2, Y8, Y8 + VPADDD Y3, Y15, Y15 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + VPXOR Y12, Y14, Y14 + VPXOR Y13, Y9, Y9 + VPXOR Y8, Y10, Y10 + VPXOR Y15, Y11, Y11 + VMOVDQA Y15, 224(BP) + VPSLLD $0x07, Y14, Y15 + VPSRLD $0x19, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPSLLD $0x07, Y9, Y15 + VPSRLD $0x19, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPSLLD $0x07, Y10, Y15 + VPSRLD $0x19, Y10, Y10 + VPXOR Y15, Y10, Y10 + VPSLLD $0x07, Y11, Y15 + VPSRLD $0x19, Y11, Y11 + VPXOR Y15, Y11, Y11 + VMOVDQA 224(BP), Y15 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + VPALIGNR $0x0c, Y14, Y14, Y14 + VPALIGNR $0x0c, Y9, Y9, Y9 + VPALIGNR $0x0c, Y10, Y10, Y10 + VPALIGNR $0x0c, Y11, Y11, Y11 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x08, Y8, Y8, Y8 + VPALIGNR $0x08, Y15, Y15, Y15 + VPALIGNR $0x04, Y4, Y4, Y4 + VPALIGNR $0x04, Y1, Y1, Y1 + VPALIGNR $0x04, Y2, Y2, Y2 + VPALIGNR $0x04, Y3, Y3, Y3 + CMPQ CX, $0x000001e0 JNE openAVX2InternalLoop - - VPADDD ·chacha20Constants<>(SB), AA0, AA0; VPADDD ·chacha20Constants<>(SB), AA1, AA1; VPADDD ·chacha20Constants<>(SB), AA2, AA2; VPADDD ·chacha20Constants<>(SB), AA3, AA3 - VPADDD state1StoreAVX2, BB0, BB0; VPADDD state1StoreAVX2, BB1, BB1; VPADDD state1StoreAVX2, BB2, BB2; VPADDD state1StoreAVX2, BB3, BB3 - VPADDD state2StoreAVX2, CC0, CC0; VPADDD state2StoreAVX2, CC1, CC1; VPADDD state2StoreAVX2, CC2, CC2; VPADDD state2StoreAVX2, CC3, CC3 - VPADDD ctr0StoreAVX2, DD0, DD0; VPADDD ctr1StoreAVX2, DD1, DD1; VPADDD ctr2StoreAVX2, DD2, DD2; VPADDD ctr3StoreAVX2, DD3, DD3 - VMOVDQA CC3, tmpStoreAVX2 + VPADDD ·chacha20Constants<>+0(SB), Y0, Y0 + VPADDD ·chacha20Constants<>+0(SB), Y5, Y5 + VPADDD ·chacha20Constants<>+0(SB), Y6, Y6 + VPADDD ·chacha20Constants<>+0(SB), Y7, Y7 + VPADDD 32(BP), Y14, Y14 + VPADDD 32(BP), Y9, Y9 + VPADDD 32(BP), Y10, Y10 + VPADDD 32(BP), Y11, Y11 + VPADDD 64(BP), Y12, Y12 + VPADDD 64(BP), Y13, Y13 + VPADDD 64(BP), Y8, Y8 + VPADDD 64(BP), Y15, Y15 + VPADDD 96(BP), Y4, Y4 + VPADDD 128(BP), Y1, Y1 + VPADDD 160(BP), Y2, Y2 + VPADDD 192(BP), Y3, Y3 + VMOVDQA Y15, 224(BP) // We only hashed 480 of the 512 bytes available - hash the remaining 32 here - polyAdd(480(inp)) - polyMulAVX2 - VPERM2I128 $0x02, AA0, BB0, CC3; VPERM2I128 $0x13, AA0, BB0, BB0; VPERM2I128 $0x02, CC0, DD0, AA0; VPERM2I128 $0x13, CC0, DD0, CC0 - VPXOR (0*32)(inp), CC3, CC3; VPXOR (1*32)(inp), AA0, AA0; VPXOR (2*32)(inp), BB0, BB0; VPXOR (3*32)(inp), CC0, CC0 - VMOVDQU CC3, (0*32)(oup); VMOVDQU AA0, (1*32)(oup); VMOVDQU BB0, (2*32)(oup); VMOVDQU CC0, (3*32)(oup) - VPERM2I128 $0x02, AA1, BB1, AA0; VPERM2I128 $0x02, CC1, DD1, BB0; VPERM2I128 $0x13, AA1, BB1, CC0; VPERM2I128 $0x13, CC1, DD1, DD0 - VPXOR (4*32)(inp), AA0, AA0; VPXOR (5*32)(inp), BB0, BB0; VPXOR (6*32)(inp), CC0, CC0; VPXOR (7*32)(inp), DD0, DD0 - VMOVDQU AA0, (4*32)(oup); VMOVDQU BB0, (5*32)(oup); VMOVDQU CC0, (6*32)(oup); VMOVDQU DD0, (7*32)(oup) + ADDQ 480(SI), R10 + ADCQ 488(SI), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + VPERM2I128 $0x02, Y0, Y14, Y15 + VPERM2I128 $0x13, Y0, Y14, Y14 + VPERM2I128 $0x02, Y12, Y4, Y0 + VPERM2I128 $0x13, Y12, Y4, Y12 + VPXOR (SI), Y15, Y15 + VPXOR 32(SI), Y0, Y0 + VPXOR 64(SI), Y14, Y14 + VPXOR 96(SI), Y12, Y12 + VMOVDQU Y15, (DI) + VMOVDQU Y0, 32(DI) + VMOVDQU Y14, 64(DI) + VMOVDQU Y12, 96(DI) + VPERM2I128 $0x02, Y5, Y9, Y0 + VPERM2I128 $0x02, Y13, Y1, Y14 + VPERM2I128 $0x13, Y5, Y9, Y12 + VPERM2I128 $0x13, Y13, Y1, Y4 + VPXOR 128(SI), Y0, Y0 + VPXOR 160(SI), Y14, Y14 + VPXOR 192(SI), Y12, Y12 + VPXOR 224(SI), Y4, Y4 + VMOVDQU Y0, 128(DI) + VMOVDQU Y14, 160(DI) + VMOVDQU Y12, 192(DI) + VMOVDQU Y4, 224(DI) // and here - polyAdd(496(inp)) - polyMulAVX2 - VPERM2I128 $0x02, AA2, BB2, AA0; VPERM2I128 $0x02, CC2, DD2, BB0; VPERM2I128 $0x13, AA2, BB2, CC0; VPERM2I128 $0x13, CC2, DD2, DD0 - VPXOR (8*32)(inp), AA0, AA0; VPXOR (9*32)(inp), BB0, BB0; VPXOR (10*32)(inp), CC0, CC0; VPXOR (11*32)(inp), DD0, DD0 - VMOVDQU AA0, (8*32)(oup); VMOVDQU BB0, (9*32)(oup); VMOVDQU CC0, (10*32)(oup); VMOVDQU DD0, (11*32)(oup) - VPERM2I128 $0x02, AA3, BB3, AA0; VPERM2I128 $0x02, tmpStoreAVX2, DD3, BB0; VPERM2I128 $0x13, AA3, BB3, CC0; VPERM2I128 $0x13, tmpStoreAVX2, DD3, DD0 - VPXOR (12*32)(inp), AA0, AA0; VPXOR (13*32)(inp), BB0, BB0; VPXOR (14*32)(inp), CC0, CC0; VPXOR (15*32)(inp), DD0, DD0 - VMOVDQU AA0, (12*32)(oup); VMOVDQU BB0, (13*32)(oup); VMOVDQU CC0, (14*32)(oup); VMOVDQU DD0, (15*32)(oup) - LEAQ (32*16)(inp), inp - LEAQ (32*16)(oup), oup - SUBQ $(32*16), inl + ADDQ 496(SI), R10 + ADCQ 504(SI), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + VPERM2I128 $0x02, Y6, Y10, Y0 + VPERM2I128 $0x02, Y8, Y2, Y14 + VPERM2I128 $0x13, Y6, Y10, Y12 + VPERM2I128 $0x13, Y8, Y2, Y4 + VPXOR 256(SI), Y0, Y0 + VPXOR 288(SI), Y14, Y14 + VPXOR 320(SI), Y12, Y12 + VPXOR 352(SI), Y4, Y4 + VMOVDQU Y0, 256(DI) + VMOVDQU Y14, 288(DI) + VMOVDQU Y12, 320(DI) + VMOVDQU Y4, 352(DI) + VPERM2I128 $0x02, Y7, Y11, Y0 + VPERM2I128 $0x02, 224(BP), Y3, Y14 + VPERM2I128 $0x13, Y7, Y11, Y12 + VPERM2I128 $0x13, 224(BP), Y3, Y4 + VPXOR 384(SI), Y0, Y0 + VPXOR 416(SI), Y14, Y14 + VPXOR 448(SI), Y12, Y12 + VPXOR 480(SI), Y4, Y4 + VMOVDQU Y0, 384(DI) + VMOVDQU Y14, 416(DI) + VMOVDQU Y12, 448(DI) + VMOVDQU Y4, 480(DI) + LEAQ 512(SI), SI + LEAQ 512(DI), DI + SUBQ $0x00000200, BX JMP openAVX2MainLoop openAVX2MainLoopDone: // Handle the various tail sizes efficiently - TESTQ inl, inl + TESTQ BX, BX JE openSSEFinalize - CMPQ inl, $128 + CMPQ BX, $0x80 JBE openAVX2Tail128 - CMPQ inl, $256 + CMPQ BX, $0x00000100 JBE openAVX2Tail256 - CMPQ inl, $384 + CMPQ BX, $0x00000180 JBE openAVX2Tail384 JMP openAVX2Tail512 -// ---------------------------------------------------------------------------- -// Special optimization for buffers smaller than 193 bytes openAVX2192: - // For up to 192 bytes of ciphertext and 64 bytes for the poly key, we process four blocks - VMOVDQA AA0, AA1 - VMOVDQA BB0, BB1 - VMOVDQA CC0, CC1 - VPADDD ·avx2IncMask<>(SB), DD0, DD1 - VMOVDQA AA0, AA2 - VMOVDQA BB0, BB2 - VMOVDQA CC0, CC2 - VMOVDQA DD0, DD2 - VMOVDQA DD1, TT3 - MOVQ $10, itr2 + VMOVDQA Y0, Y5 + VMOVDQA Y14, Y9 + VMOVDQA Y12, Y13 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y1 + VMOVDQA Y0, Y6 + VMOVDQA Y14, Y10 + VMOVDQA Y12, Y8 + VMOVDQA Y4, Y2 + VMOVDQA Y1, Y15 + MOVQ $0x0000000a, R9 openAVX2192InnerCipherLoop: - chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) - VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1 - VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1 - VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1 - chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) - VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1 - VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1 - VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1 - DECQ itr2 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y3 + VPSRLD $0x14, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y3 + VPSRLD $0x19, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x0c, Y9, Y3 + VPSRLD $0x14, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x07, Y9, Y3 + VPSRLD $0x19, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPALIGNR $0x04, Y14, Y14, Y14 + VPALIGNR $0x04, Y9, Y9, Y9 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x0c, Y4, Y4, Y4 + VPALIGNR $0x0c, Y1, Y1, Y1 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y3 + VPSRLD $0x14, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y3 + VPSRLD $0x19, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x0c, Y9, Y3 + VPSRLD $0x14, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x07, Y9, Y3 + VPSRLD $0x19, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPALIGNR $0x0c, Y14, Y14, Y14 + VPALIGNR $0x0c, Y9, Y9, Y9 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x04, Y4, Y4, Y4 + VPALIGNR $0x04, Y1, Y1, Y1 + DECQ R9 JNE openAVX2192InnerCipherLoop - VPADDD AA2, AA0, AA0; VPADDD AA2, AA1, AA1 - VPADDD BB2, BB0, BB0; VPADDD BB2, BB1, BB1 - VPADDD CC2, CC0, CC0; VPADDD CC2, CC1, CC1 - VPADDD DD2, DD0, DD0; VPADDD TT3, DD1, DD1 - VPERM2I128 $0x02, AA0, BB0, TT0 + VPADDD Y6, Y0, Y0 + VPADDD Y6, Y5, Y5 + VPADDD Y10, Y14, Y14 + VPADDD Y10, Y9, Y9 + VPADDD Y8, Y12, Y12 + VPADDD Y8, Y13, Y13 + VPADDD Y2, Y4, Y4 + VPADDD Y15, Y1, Y1 + VPERM2I128 $0x02, Y0, Y14, Y3 // Clamp and store poly key - VPAND ·polyClampMask<>(SB), TT0, TT0 - VMOVDQA TT0, rsStoreAVX2 + VPAND ·polyClampMask<>+0(SB), Y3, Y3 + VMOVDQA Y3, (BP) // Stream for up to 192 bytes - VPERM2I128 $0x13, AA0, BB0, AA0 - VPERM2I128 $0x13, CC0, DD0, BB0 - VPERM2I128 $0x02, AA1, BB1, CC0 - VPERM2I128 $0x02, CC1, DD1, DD0 - VPERM2I128 $0x13, AA1, BB1, AA1 - VPERM2I128 $0x13, CC1, DD1, BB1 + VPERM2I128 $0x13, Y0, Y14, Y0 + VPERM2I128 $0x13, Y12, Y4, Y14 + VPERM2I128 $0x02, Y5, Y9, Y12 + VPERM2I128 $0x02, Y13, Y1, Y4 + VPERM2I128 $0x13, Y5, Y9, Y5 + VPERM2I128 $0x13, Y13, Y1, Y9 openAVX2ShortOpen: // Hash - MOVQ ad_len+80(FP), itr2 + MOVQ ad_len+80(FP), R9 CALL polyHashADInternal<>(SB) openAVX2ShortOpenLoop: - CMPQ inl, $32 + CMPQ BX, $0x20 JB openAVX2ShortTail32 - SUBQ $32, inl + SUBQ $0x20, BX // Load for hashing - polyAdd(0*8(inp)) - polyMulAVX2 - polyAdd(2*8(inp)) - polyMulAVX2 + ADDQ (SI), R10 + ADCQ 8(SI), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + ADDQ 16(SI), R10 + ADCQ 24(SI), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 // Load for decryption - VPXOR (inp), AA0, AA0 - VMOVDQU AA0, (oup) - LEAQ (1*32)(inp), inp - LEAQ (1*32)(oup), oup + VPXOR (SI), Y0, Y0 + VMOVDQU Y0, (DI) + LEAQ 32(SI), SI + LEAQ 32(DI), DI // Shift stream left - VMOVDQA BB0, AA0 - VMOVDQA CC0, BB0 - VMOVDQA DD0, CC0 - VMOVDQA AA1, DD0 - VMOVDQA BB1, AA1 - VMOVDQA CC1, BB1 - VMOVDQA DD1, CC1 - VMOVDQA AA2, DD1 - VMOVDQA BB2, AA2 + VMOVDQA Y14, Y0 + VMOVDQA Y12, Y14 + VMOVDQA Y4, Y12 + VMOVDQA Y5, Y4 + VMOVDQA Y9, Y5 + VMOVDQA Y13, Y9 + VMOVDQA Y1, Y13 + VMOVDQA Y6, Y1 + VMOVDQA Y10, Y6 JMP openAVX2ShortOpenLoop openAVX2ShortTail32: - CMPQ inl, $16 - VMOVDQA A0, A1 + CMPQ BX, $0x10 + VMOVDQA X0, X1 JB openAVX2ShortDone - - SUBQ $16, inl + SUBQ $0x10, BX // Load for hashing - polyAdd(0*8(inp)) - polyMulAVX2 + ADDQ (SI), R10 + ADCQ 8(SI), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 // Load for decryption - VPXOR (inp), A0, T0 - VMOVDQU T0, (oup) - LEAQ (1*16)(inp), inp - LEAQ (1*16)(oup), oup - VPERM2I128 $0x11, AA0, AA0, AA0 - VMOVDQA A0, A1 + VPXOR (SI), X0, X12 + VMOVDQU X12, (DI) + LEAQ 16(SI), SI + LEAQ 16(DI), DI + VPERM2I128 $0x11, Y0, Y0, Y0 + VMOVDQA X0, X1 openAVX2ShortDone: VZEROUPPER JMP openSSETail16 -// ---------------------------------------------------------------------------- -// Special optimization for buffers smaller than 321 bytes openAVX2320: - // For up to 320 bytes of ciphertext and 64 bytes for the poly key, we process six blocks - VMOVDQA AA0, AA1; VMOVDQA BB0, BB1; VMOVDQA CC0, CC1; VPADDD ·avx2IncMask<>(SB), DD0, DD1 - VMOVDQA AA0, AA2; VMOVDQA BB0, BB2; VMOVDQA CC0, CC2; VPADDD ·avx2IncMask<>(SB), DD1, DD2 - VMOVDQA BB0, TT1; VMOVDQA CC0, TT2; VMOVDQA DD0, TT3 - MOVQ $10, itr2 + VMOVDQA Y0, Y5 + VMOVDQA Y14, Y9 + VMOVDQA Y12, Y13 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y1 + VMOVDQA Y0, Y6 + VMOVDQA Y14, Y10 + VMOVDQA Y12, Y8 + VPADDD ·avx2IncMask<>+0(SB), Y1, Y2 + VMOVDQA Y14, Y7 + VMOVDQA Y12, Y11 + VMOVDQA Y4, Y15 + MOVQ $0x0000000a, R9 openAVX2320InnerCipherLoop: - chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0); chachaQR_AVX2(AA2, BB2, CC2, DD2, TT0) - VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $4, BB2, BB2, BB2 - VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2 - VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1; VPALIGNR $12, DD2, DD2, DD2 - chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0); chachaQR_AVX2(AA2, BB2, CC2, DD2, TT0) - VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $12, BB2, BB2, BB2 - VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2 - VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1; VPALIGNR $4, DD2, DD2, DD2 - DECQ itr2 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y3 + VPSRLD $0x14, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y3 + VPSRLD $0x19, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x0c, Y9, Y3 + VPSRLD $0x14, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x07, Y9, Y3 + VPSRLD $0x19, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol16<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x0c, Y10, Y3 + VPSRLD $0x14, Y10, Y10 + VPXOR Y3, Y10, Y10 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol8<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x07, Y10, Y3 + VPSRLD $0x19, Y10, Y10 + VPXOR Y3, Y10, Y10 + VPALIGNR $0x04, Y14, Y14, Y14 + VPALIGNR $0x04, Y9, Y9, Y9 + VPALIGNR $0x04, Y10, Y10, Y10 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x08, Y8, Y8, Y8 + VPALIGNR $0x0c, Y4, Y4, Y4 + VPALIGNR $0x0c, Y1, Y1, Y1 + VPALIGNR $0x0c, Y2, Y2, Y2 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y3 + VPSRLD $0x14, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y3 + VPSRLD $0x19, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x0c, Y9, Y3 + VPSRLD $0x14, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x07, Y9, Y3 + VPSRLD $0x19, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol16<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x0c, Y10, Y3 + VPSRLD $0x14, Y10, Y10 + VPXOR Y3, Y10, Y10 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol8<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x07, Y10, Y3 + VPSRLD $0x19, Y10, Y10 + VPXOR Y3, Y10, Y10 + VPALIGNR $0x0c, Y14, Y14, Y14 + VPALIGNR $0x0c, Y9, Y9, Y9 + VPALIGNR $0x0c, Y10, Y10, Y10 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x08, Y8, Y8, Y8 + VPALIGNR $0x04, Y4, Y4, Y4 + VPALIGNR $0x04, Y1, Y1, Y1 + VPALIGNR $0x04, Y2, Y2, Y2 + DECQ R9 JNE openAVX2320InnerCipherLoop - - VMOVDQA ·chacha20Constants<>(SB), TT0 - VPADDD TT0, AA0, AA0; VPADDD TT0, AA1, AA1; VPADDD TT0, AA2, AA2 - VPADDD TT1, BB0, BB0; VPADDD TT1, BB1, BB1; VPADDD TT1, BB2, BB2 - VPADDD TT2, CC0, CC0; VPADDD TT2, CC1, CC1; VPADDD TT2, CC2, CC2 - VMOVDQA ·avx2IncMask<>(SB), TT0 - VPADDD TT3, DD0, DD0; VPADDD TT0, TT3, TT3 - VPADDD TT3, DD1, DD1; VPADDD TT0, TT3, TT3 - VPADDD TT3, DD2, DD2 + VMOVDQA ·chacha20Constants<>+0(SB), Y3 + VPADDD Y3, Y0, Y0 + VPADDD Y3, Y5, Y5 + VPADDD Y3, Y6, Y6 + VPADDD Y7, Y14, Y14 + VPADDD Y7, Y9, Y9 + VPADDD Y7, Y10, Y10 + VPADDD Y11, Y12, Y12 + VPADDD Y11, Y13, Y13 + VPADDD Y11, Y8, Y8 + VMOVDQA ·avx2IncMask<>+0(SB), Y3 + VPADDD Y15, Y4, Y4 + VPADDD Y3, Y15, Y15 + VPADDD Y15, Y1, Y1 + VPADDD Y3, Y15, Y15 + VPADDD Y15, Y2, Y2 // Clamp and store poly key - VPERM2I128 $0x02, AA0, BB0, TT0 - VPAND ·polyClampMask<>(SB), TT0, TT0 - VMOVDQA TT0, rsStoreAVX2 + VPERM2I128 $0x02, Y0, Y14, Y3 + VPAND ·polyClampMask<>+0(SB), Y3, Y3 + VMOVDQA Y3, (BP) // Stream for up to 320 bytes - VPERM2I128 $0x13, AA0, BB0, AA0 - VPERM2I128 $0x13, CC0, DD0, BB0 - VPERM2I128 $0x02, AA1, BB1, CC0 - VPERM2I128 $0x02, CC1, DD1, DD0 - VPERM2I128 $0x13, AA1, BB1, AA1 - VPERM2I128 $0x13, CC1, DD1, BB1 - VPERM2I128 $0x02, AA2, BB2, CC1 - VPERM2I128 $0x02, CC2, DD2, DD1 - VPERM2I128 $0x13, AA2, BB2, AA2 - VPERM2I128 $0x13, CC2, DD2, BB2 + VPERM2I128 $0x13, Y0, Y14, Y0 + VPERM2I128 $0x13, Y12, Y4, Y14 + VPERM2I128 $0x02, Y5, Y9, Y12 + VPERM2I128 $0x02, Y13, Y1, Y4 + VPERM2I128 $0x13, Y5, Y9, Y5 + VPERM2I128 $0x13, Y13, Y1, Y9 + VPERM2I128 $0x02, Y6, Y10, Y13 + VPERM2I128 $0x02, Y8, Y2, Y1 + VPERM2I128 $0x13, Y6, Y10, Y6 + VPERM2I128 $0x13, Y8, Y2, Y10 JMP openAVX2ShortOpen -// ---------------------------------------------------------------------------- -// Special optimization for the last 128 bytes of ciphertext openAVX2Tail128: // Need to decrypt up to 128 bytes - prepare two blocks - VMOVDQA ·chacha20Constants<>(SB), AA1 - VMOVDQA state1StoreAVX2, BB1 - VMOVDQA state2StoreAVX2, CC1 - VMOVDQA ctr3StoreAVX2, DD1 - VPADDD ·avx2IncMask<>(SB), DD1, DD1 - VMOVDQA DD1, DD0 - - XORQ itr2, itr2 - MOVQ inl, itr1 - ANDQ $-16, itr1 - TESTQ itr1, itr1 - JE openAVX2Tail128LoopB + VMOVDQA ·chacha20Constants<>+0(SB), Y5 + VMOVDQA 32(BP), Y9 + VMOVDQA 64(BP), Y13 + VMOVDQA 192(BP), Y1 + VPADDD ·avx2IncMask<>+0(SB), Y1, Y1 + VMOVDQA Y1, Y4 + XORQ R9, R9 + MOVQ BX, CX + ANDQ $-16, CX + TESTQ CX, CX + JE openAVX2Tail128LoopB openAVX2Tail128LoopA: - // Perform ChaCha rounds, while hashing the remaining input - polyAdd(0(inp)(itr2*1)) - polyMulAVX2 + ADDQ (SI)(R9*1), R10 + ADCQ 8(SI)(R9*1), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 openAVX2Tail128LoopB: - ADDQ $16, itr2 - chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) - VPALIGNR $4, BB1, BB1, BB1 - VPALIGNR $8, CC1, CC1, CC1 - VPALIGNR $12, DD1, DD1, DD1 - chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) - VPALIGNR $12, BB1, BB1, BB1 - VPALIGNR $8, CC1, CC1, CC1 - VPALIGNR $4, DD1, DD1, DD1 - CMPQ itr2, itr1 - JB openAVX2Tail128LoopA - CMPQ itr2, $160 - JNE openAVX2Tail128LoopB - - VPADDD ·chacha20Constants<>(SB), AA1, AA1 - VPADDD state1StoreAVX2, BB1, BB1 - VPADDD state2StoreAVX2, CC1, CC1 - VPADDD DD0, DD1, DD1 - VPERM2I128 $0x02, AA1, BB1, AA0; VPERM2I128 $0x02, CC1, DD1, BB0; VPERM2I128 $0x13, AA1, BB1, CC0; VPERM2I128 $0x13, CC1, DD1, DD0 + ADDQ $0x10, R9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x0c, Y9, Y3 + VPSRLD $0x14, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x07, Y9, Y3 + VPSRLD $0x19, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPALIGNR $0x04, Y9, Y9, Y9 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x0c, Y1, Y1, Y1 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x0c, Y9, Y3 + VPSRLD $0x14, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x07, Y9, Y3 + VPSRLD $0x19, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPALIGNR $0x0c, Y9, Y9, Y9 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x04, Y1, Y1, Y1 + CMPQ R9, CX + JB openAVX2Tail128LoopA + CMPQ R9, $0xa0 + JNE openAVX2Tail128LoopB + VPADDD ·chacha20Constants<>+0(SB), Y5, Y5 + VPADDD 32(BP), Y9, Y9 + VPADDD 64(BP), Y13, Y13 + VPADDD Y4, Y1, Y1 + VPERM2I128 $0x02, Y5, Y9, Y0 + VPERM2I128 $0x02, Y13, Y1, Y14 + VPERM2I128 $0x13, Y5, Y9, Y12 + VPERM2I128 $0x13, Y13, Y1, Y4 openAVX2TailLoop: - CMPQ inl, $32 + CMPQ BX, $0x20 JB openAVX2Tail - SUBQ $32, inl + SUBQ $0x20, BX // Load for decryption - VPXOR (inp), AA0, AA0 - VMOVDQU AA0, (oup) - LEAQ (1*32)(inp), inp - LEAQ (1*32)(oup), oup - VMOVDQA BB0, AA0 - VMOVDQA CC0, BB0 - VMOVDQA DD0, CC0 + VPXOR (SI), Y0, Y0 + VMOVDQU Y0, (DI) + LEAQ 32(SI), SI + LEAQ 32(DI), DI + VMOVDQA Y14, Y0 + VMOVDQA Y12, Y14 + VMOVDQA Y4, Y12 JMP openAVX2TailLoop openAVX2Tail: - CMPQ inl, $16 - VMOVDQA A0, A1 + CMPQ BX, $0x10 + VMOVDQA X0, X1 JB openAVX2TailDone - SUBQ $16, inl + SUBQ $0x10, BX // Load for decryption - VPXOR (inp), A0, T0 - VMOVDQU T0, (oup) - LEAQ (1*16)(inp), inp - LEAQ (1*16)(oup), oup - VPERM2I128 $0x11, AA0, AA0, AA0 - VMOVDQA A0, A1 + VPXOR (SI), X0, X12 + VMOVDQU X12, (DI) + LEAQ 16(SI), SI + LEAQ 16(DI), DI + VPERM2I128 $0x11, Y0, Y0, Y0 + VMOVDQA X0, X1 openAVX2TailDone: VZEROUPPER JMP openSSETail16 -// ---------------------------------------------------------------------------- -// Special optimization for the last 256 bytes of ciphertext openAVX2Tail256: - // Need to decrypt up to 256 bytes - prepare four blocks - VMOVDQA ·chacha20Constants<>(SB), AA0; VMOVDQA AA0, AA1 - VMOVDQA state1StoreAVX2, BB0; VMOVDQA BB0, BB1 - VMOVDQA state2StoreAVX2, CC0; VMOVDQA CC0, CC1 - VMOVDQA ctr3StoreAVX2, DD0 - VPADDD ·avx2IncMask<>(SB), DD0, DD0 - VPADDD ·avx2IncMask<>(SB), DD0, DD1 - VMOVDQA DD0, TT1 - VMOVDQA DD1, TT2 + VMOVDQA ·chacha20Constants<>+0(SB), Y0 + VMOVDQA Y0, Y5 + VMOVDQA 32(BP), Y14 + VMOVDQA Y14, Y9 + VMOVDQA 64(BP), Y12 + VMOVDQA Y12, Y13 + VMOVDQA 192(BP), Y4 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y4 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y1 + VMOVDQA Y4, Y7 + VMOVDQA Y1, Y11 // Compute the number of iterations that will hash data - MOVQ inl, tmpStoreAVX2 - MOVQ inl, itr1 - SUBQ $128, itr1 - SHRQ $4, itr1 - MOVQ $10, itr2 - CMPQ itr1, $10 - CMOVQGT itr2, itr1 - MOVQ inp, inl - XORQ itr2, itr2 + MOVQ BX, 224(BP) + MOVQ BX, CX + SUBQ $0x80, CX + SHRQ $0x04, CX + MOVQ $0x0000000a, R9 + CMPQ CX, $0x0a + CMOVQGT R9, CX + MOVQ SI, BX + XORQ R9, R9 openAVX2Tail256LoopA: - polyAdd(0(inl)) - polyMulAVX2 - LEAQ 16(inl), inl + ADDQ (BX), R10 + ADCQ 8(BX), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 16(BX), BX - // Perform ChaCha rounds, while hashing the remaining input openAVX2Tail256LoopB: - chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) - VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1 - VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1 - VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1 - INCQ itr2 - chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) - VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1 - VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1 - VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1 - CMPQ itr2, itr1 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y3 + VPSRLD $0x14, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y3 + VPSRLD $0x19, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x0c, Y9, Y3 + VPSRLD $0x14, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x07, Y9, Y3 + VPSRLD $0x19, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPALIGNR $0x04, Y14, Y14, Y14 + VPALIGNR $0x04, Y9, Y9, Y9 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x0c, Y4, Y4, Y4 + VPALIGNR $0x0c, Y1, Y1, Y1 + INCQ R9 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y3 + VPSRLD $0x14, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y3 + VPSRLD $0x19, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x0c, Y9, Y3 + VPSRLD $0x14, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x07, Y9, Y3 + VPSRLD $0x19, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPALIGNR $0x0c, Y14, Y14, Y14 + VPALIGNR $0x0c, Y9, Y9, Y9 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x04, Y4, Y4, Y4 + VPALIGNR $0x04, Y1, Y1, Y1 + CMPQ R9, CX JB openAVX2Tail256LoopA + CMPQ R9, $0x0a + JNE openAVX2Tail256LoopB + MOVQ BX, R9 + SUBQ SI, BX + MOVQ BX, CX + MOVQ 224(BP), BX - CMPQ itr2, $10 - JNE openAVX2Tail256LoopB - - MOVQ inl, itr2 - SUBQ inp, inl - MOVQ inl, itr1 - MOVQ tmpStoreAVX2, inl - - // Hash the remainder of data (if any) openAVX2Tail256Hash: - ADDQ $16, itr1 - CMPQ itr1, inl - JGT openAVX2Tail256HashEnd - polyAdd (0(itr2)) - polyMulAVX2 - LEAQ 16(itr2), itr2 - JMP openAVX2Tail256Hash - -// Store 128 bytes safely, then go to store loop + ADDQ $0x10, CX + CMPQ CX, BX + JGT openAVX2Tail256HashEnd + ADDQ (R9), R10 + ADCQ 8(R9), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 16(R9), R9 + JMP openAVX2Tail256Hash + openAVX2Tail256HashEnd: - VPADDD ·chacha20Constants<>(SB), AA0, AA0; VPADDD ·chacha20Constants<>(SB), AA1, AA1 - VPADDD state1StoreAVX2, BB0, BB0; VPADDD state1StoreAVX2, BB1, BB1 - VPADDD state2StoreAVX2, CC0, CC0; VPADDD state2StoreAVX2, CC1, CC1 - VPADDD TT1, DD0, DD0; VPADDD TT2, DD1, DD1 - VPERM2I128 $0x02, AA0, BB0, AA2; VPERM2I128 $0x02, CC0, DD0, BB2; VPERM2I128 $0x13, AA0, BB0, CC2; VPERM2I128 $0x13, CC0, DD0, DD2 - VPERM2I128 $0x02, AA1, BB1, AA0; VPERM2I128 $0x02, CC1, DD1, BB0; VPERM2I128 $0x13, AA1, BB1, CC0; VPERM2I128 $0x13, CC1, DD1, DD0 - - VPXOR (0*32)(inp), AA2, AA2; VPXOR (1*32)(inp), BB2, BB2; VPXOR (2*32)(inp), CC2, CC2; VPXOR (3*32)(inp), DD2, DD2 - VMOVDQU AA2, (0*32)(oup); VMOVDQU BB2, (1*32)(oup); VMOVDQU CC2, (2*32)(oup); VMOVDQU DD2, (3*32)(oup) - LEAQ (4*32)(inp), inp - LEAQ (4*32)(oup), oup - SUBQ $4*32, inl - - JMP openAVX2TailLoop - -// ---------------------------------------------------------------------------- -// Special optimization for the last 384 bytes of ciphertext + VPADDD ·chacha20Constants<>+0(SB), Y0, Y0 + VPADDD ·chacha20Constants<>+0(SB), Y5, Y5 + VPADDD 32(BP), Y14, Y14 + VPADDD 32(BP), Y9, Y9 + VPADDD 64(BP), Y12, Y12 + VPADDD 64(BP), Y13, Y13 + VPADDD Y7, Y4, Y4 + VPADDD Y11, Y1, Y1 + VPERM2I128 $0x02, Y0, Y14, Y6 + VPERM2I128 $0x02, Y12, Y4, Y10 + VPERM2I128 $0x13, Y0, Y14, Y8 + VPERM2I128 $0x13, Y12, Y4, Y2 + VPERM2I128 $0x02, Y5, Y9, Y0 + VPERM2I128 $0x02, Y13, Y1, Y14 + VPERM2I128 $0x13, Y5, Y9, Y12 + VPERM2I128 $0x13, Y13, Y1, Y4 + VPXOR (SI), Y6, Y6 + VPXOR 32(SI), Y10, Y10 + VPXOR 64(SI), Y8, Y8 + VPXOR 96(SI), Y2, Y2 + VMOVDQU Y6, (DI) + VMOVDQU Y10, 32(DI) + VMOVDQU Y8, 64(DI) + VMOVDQU Y2, 96(DI) + LEAQ 128(SI), SI + LEAQ 128(DI), DI + SUBQ $0x80, BX + JMP openAVX2TailLoop + openAVX2Tail384: // Need to decrypt up to 384 bytes - prepare six blocks - VMOVDQA ·chacha20Constants<>(SB), AA0; VMOVDQA AA0, AA1; VMOVDQA AA0, AA2 - VMOVDQA state1StoreAVX2, BB0; VMOVDQA BB0, BB1; VMOVDQA BB0, BB2 - VMOVDQA state2StoreAVX2, CC0; VMOVDQA CC0, CC1; VMOVDQA CC0, CC2 - VMOVDQA ctr3StoreAVX2, DD0 - VPADDD ·avx2IncMask<>(SB), DD0, DD0 - VPADDD ·avx2IncMask<>(SB), DD0, DD1 - VPADDD ·avx2IncMask<>(SB), DD1, DD2 - VMOVDQA DD0, ctr0StoreAVX2 - VMOVDQA DD1, ctr1StoreAVX2 - VMOVDQA DD2, ctr2StoreAVX2 + VMOVDQA ·chacha20Constants<>+0(SB), Y0 + VMOVDQA Y0, Y5 + VMOVDQA Y0, Y6 + VMOVDQA 32(BP), Y14 + VMOVDQA Y14, Y9 + VMOVDQA Y14, Y10 + VMOVDQA 64(BP), Y12 + VMOVDQA Y12, Y13 + VMOVDQA Y12, Y8 + VMOVDQA 192(BP), Y4 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y4 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y1 + VPADDD ·avx2IncMask<>+0(SB), Y1, Y2 + VMOVDQA Y4, 96(BP) + VMOVDQA Y1, 128(BP) + VMOVDQA Y2, 160(BP) // Compute the number of iterations that will hash two blocks of data - MOVQ inl, tmpStoreAVX2 - MOVQ inl, itr1 - SUBQ $256, itr1 - SHRQ $4, itr1 - ADDQ $6, itr1 - MOVQ $10, itr2 - CMPQ itr1, $10 - CMOVQGT itr2, itr1 - MOVQ inp, inl - XORQ itr2, itr2 - - // Perform ChaCha rounds, while hashing the remaining input + MOVQ BX, 224(BP) + MOVQ BX, CX + SUBQ $0x00000100, CX + SHRQ $0x04, CX + ADDQ $0x06, CX + MOVQ $0x0000000a, R9 + CMPQ CX, $0x0a + CMOVQGT R9, CX + MOVQ SI, BX + XORQ R9, R9 + openAVX2Tail384LoopB: - polyAdd(0(inl)) - polyMulAVX2 - LEAQ 16(inl), inl + ADDQ (BX), R10 + ADCQ 8(BX), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 16(BX), BX openAVX2Tail384LoopA: - chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0); chachaQR_AVX2(AA2, BB2, CC2, DD2, TT0) - VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $4, BB2, BB2, BB2 - VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2 - VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1; VPALIGNR $12, DD2, DD2, DD2 - polyAdd(0(inl)) - polyMulAVX2 - LEAQ 16(inl), inl - INCQ itr2 - chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0); chachaQR_AVX2(AA2, BB2, CC2, DD2, TT0) - VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $12, BB2, BB2, BB2 - VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2 - VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1; VPALIGNR $4, DD2, DD2, DD2 - - CMPQ itr2, itr1 - JB openAVX2Tail384LoopB - - CMPQ itr2, $10 - JNE openAVX2Tail384LoopA - - MOVQ inl, itr2 - SUBQ inp, inl - MOVQ inl, itr1 - MOVQ tmpStoreAVX2, inl + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y3 + VPSRLD $0x14, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y3 + VPSRLD $0x19, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x0c, Y9, Y3 + VPSRLD $0x14, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x07, Y9, Y3 + VPSRLD $0x19, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol16<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x0c, Y10, Y3 + VPSRLD $0x14, Y10, Y10 + VPXOR Y3, Y10, Y10 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol8<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x07, Y10, Y3 + VPSRLD $0x19, Y10, Y10 + VPXOR Y3, Y10, Y10 + VPALIGNR $0x04, Y14, Y14, Y14 + VPALIGNR $0x04, Y9, Y9, Y9 + VPALIGNR $0x04, Y10, Y10, Y10 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x08, Y8, Y8, Y8 + VPALIGNR $0x0c, Y4, Y4, Y4 + VPALIGNR $0x0c, Y1, Y1, Y1 + VPALIGNR $0x0c, Y2, Y2, Y2 + ADDQ (BX), R10 + ADCQ 8(BX), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 16(BX), BX + INCQ R9 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y3 + VPSRLD $0x14, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y3 + VPSRLD $0x19, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x0c, Y9, Y3 + VPSRLD $0x14, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x07, Y9, Y3 + VPSRLD $0x19, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol16<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x0c, Y10, Y3 + VPSRLD $0x14, Y10, Y10 + VPXOR Y3, Y10, Y10 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol8<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x07, Y10, Y3 + VPSRLD $0x19, Y10, Y10 + VPXOR Y3, Y10, Y10 + VPALIGNR $0x0c, Y14, Y14, Y14 + VPALIGNR $0x0c, Y9, Y9, Y9 + VPALIGNR $0x0c, Y10, Y10, Y10 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x08, Y8, Y8, Y8 + VPALIGNR $0x04, Y4, Y4, Y4 + VPALIGNR $0x04, Y1, Y1, Y1 + VPALIGNR $0x04, Y2, Y2, Y2 + CMPQ R9, CX + JB openAVX2Tail384LoopB + CMPQ R9, $0x0a + JNE openAVX2Tail384LoopA + MOVQ BX, R9 + SUBQ SI, BX + MOVQ BX, CX + MOVQ 224(BP), BX openAVX2Tail384Hash: - ADDQ $16, itr1 - CMPQ itr1, inl - JGT openAVX2Tail384HashEnd - polyAdd(0(itr2)) - polyMulAVX2 - LEAQ 16(itr2), itr2 - JMP openAVX2Tail384Hash - -// Store 256 bytes safely, then go to store loop + ADDQ $0x10, CX + CMPQ CX, BX + JGT openAVX2Tail384HashEnd + ADDQ (R9), R10 + ADCQ 8(R9), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 16(R9), R9 + JMP openAVX2Tail384Hash + openAVX2Tail384HashEnd: - VPADDD ·chacha20Constants<>(SB), AA0, AA0; VPADDD ·chacha20Constants<>(SB), AA1, AA1; VPADDD ·chacha20Constants<>(SB), AA2, AA2 - VPADDD state1StoreAVX2, BB0, BB0; VPADDD state1StoreAVX2, BB1, BB1; VPADDD state1StoreAVX2, BB2, BB2 - VPADDD state2StoreAVX2, CC0, CC0; VPADDD state2StoreAVX2, CC1, CC1; VPADDD state2StoreAVX2, CC2, CC2 - VPADDD ctr0StoreAVX2, DD0, DD0; VPADDD ctr1StoreAVX2, DD1, DD1; VPADDD ctr2StoreAVX2, DD2, DD2 - VPERM2I128 $0x02, AA0, BB0, TT0; VPERM2I128 $0x02, CC0, DD0, TT1; VPERM2I128 $0x13, AA0, BB0, TT2; VPERM2I128 $0x13, CC0, DD0, TT3 - VPXOR (0*32)(inp), TT0, TT0; VPXOR (1*32)(inp), TT1, TT1; VPXOR (2*32)(inp), TT2, TT2; VPXOR (3*32)(inp), TT3, TT3 - VMOVDQU TT0, (0*32)(oup); VMOVDQU TT1, (1*32)(oup); VMOVDQU TT2, (2*32)(oup); VMOVDQU TT3, (3*32)(oup) - VPERM2I128 $0x02, AA1, BB1, TT0; VPERM2I128 $0x02, CC1, DD1, TT1; VPERM2I128 $0x13, AA1, BB1, TT2; VPERM2I128 $0x13, CC1, DD1, TT3 - VPXOR (4*32)(inp), TT0, TT0; VPXOR (5*32)(inp), TT1, TT1; VPXOR (6*32)(inp), TT2, TT2; VPXOR (7*32)(inp), TT3, TT3 - VMOVDQU TT0, (4*32)(oup); VMOVDQU TT1, (5*32)(oup); VMOVDQU TT2, (6*32)(oup); VMOVDQU TT3, (7*32)(oup) - VPERM2I128 $0x02, AA2, BB2, AA0; VPERM2I128 $0x02, CC2, DD2, BB0; VPERM2I128 $0x13, AA2, BB2, CC0; VPERM2I128 $0x13, CC2, DD2, DD0 - LEAQ (8*32)(inp), inp - LEAQ (8*32)(oup), oup - SUBQ $8*32, inl + VPADDD ·chacha20Constants<>+0(SB), Y0, Y0 + VPADDD ·chacha20Constants<>+0(SB), Y5, Y5 + VPADDD ·chacha20Constants<>+0(SB), Y6, Y6 + VPADDD 32(BP), Y14, Y14 + VPADDD 32(BP), Y9, Y9 + VPADDD 32(BP), Y10, Y10 + VPADDD 64(BP), Y12, Y12 + VPADDD 64(BP), Y13, Y13 + VPADDD 64(BP), Y8, Y8 + VPADDD 96(BP), Y4, Y4 + VPADDD 128(BP), Y1, Y1 + VPADDD 160(BP), Y2, Y2 + VPERM2I128 $0x02, Y0, Y14, Y3 + VPERM2I128 $0x02, Y12, Y4, Y7 + VPERM2I128 $0x13, Y0, Y14, Y11 + VPERM2I128 $0x13, Y12, Y4, Y15 + VPXOR (SI), Y3, Y3 + VPXOR 32(SI), Y7, Y7 + VPXOR 64(SI), Y11, Y11 + VPXOR 96(SI), Y15, Y15 + VMOVDQU Y3, (DI) + VMOVDQU Y7, 32(DI) + VMOVDQU Y11, 64(DI) + VMOVDQU Y15, 96(DI) + VPERM2I128 $0x02, Y5, Y9, Y3 + VPERM2I128 $0x02, Y13, Y1, Y7 + VPERM2I128 $0x13, Y5, Y9, Y11 + VPERM2I128 $0x13, Y13, Y1, Y15 + VPXOR 128(SI), Y3, Y3 + VPXOR 160(SI), Y7, Y7 + VPXOR 192(SI), Y11, Y11 + VPXOR 224(SI), Y15, Y15 + VMOVDQU Y3, 128(DI) + VMOVDQU Y7, 160(DI) + VMOVDQU Y11, 192(DI) + VMOVDQU Y15, 224(DI) + VPERM2I128 $0x02, Y6, Y10, Y0 + VPERM2I128 $0x02, Y8, Y2, Y14 + VPERM2I128 $0x13, Y6, Y10, Y12 + VPERM2I128 $0x13, Y8, Y2, Y4 + LEAQ 256(SI), SI + LEAQ 256(DI), DI + SUBQ $0x00000100, BX JMP openAVX2TailLoop -// ---------------------------------------------------------------------------- -// Special optimization for the last 512 bytes of ciphertext openAVX2Tail512: - VMOVDQU ·chacha20Constants<>(SB), AA0; VMOVDQA AA0, AA1; VMOVDQA AA0, AA2; VMOVDQA AA0, AA3 - VMOVDQA state1StoreAVX2, BB0; VMOVDQA BB0, BB1; VMOVDQA BB0, BB2; VMOVDQA BB0, BB3 - VMOVDQA state2StoreAVX2, CC0; VMOVDQA CC0, CC1; VMOVDQA CC0, CC2; VMOVDQA CC0, CC3 - VMOVDQA ctr3StoreAVX2, DD0; VPADDD ·avx2IncMask<>(SB), DD0, DD0; VPADDD ·avx2IncMask<>(SB), DD0, DD1; VPADDD ·avx2IncMask<>(SB), DD1, DD2; VPADDD ·avx2IncMask<>(SB), DD2, DD3 - VMOVDQA DD0, ctr0StoreAVX2; VMOVDQA DD1, ctr1StoreAVX2; VMOVDQA DD2, ctr2StoreAVX2; VMOVDQA DD3, ctr3StoreAVX2 - XORQ itr1, itr1 - MOVQ inp, itr2 + VMOVDQU ·chacha20Constants<>+0(SB), Y0 + VMOVDQA Y0, Y5 + VMOVDQA Y0, Y6 + VMOVDQA Y0, Y7 + VMOVDQA 32(BP), Y14 + VMOVDQA Y14, Y9 + VMOVDQA Y14, Y10 + VMOVDQA Y14, Y11 + VMOVDQA 64(BP), Y12 + VMOVDQA Y12, Y13 + VMOVDQA Y12, Y8 + VMOVDQA Y12, Y15 + VMOVDQA 192(BP), Y4 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y4 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y1 + VPADDD ·avx2IncMask<>+0(SB), Y1, Y2 + VPADDD ·avx2IncMask<>+0(SB), Y2, Y3 + VMOVDQA Y4, 96(BP) + VMOVDQA Y1, 128(BP) + VMOVDQA Y2, 160(BP) + VMOVDQA Y3, 192(BP) + XORQ CX, CX + MOVQ SI, R9 openAVX2Tail512LoopB: - polyAdd(0(itr2)) - polyMulAVX2 - LEAQ (2*8)(itr2), itr2 + ADDQ (R9), R10 + ADCQ 8(R9), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 16(R9), R9 openAVX2Tail512LoopA: - VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 - VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 - VPSHUFB ·rol16<>(SB), DD0, DD0; VPSHUFB ·rol16<>(SB), DD1, DD1; VPSHUFB ·rol16<>(SB), DD2, DD2; VPSHUFB ·rol16<>(SB), DD3, DD3 - VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 - VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 - VMOVDQA CC3, tmpStoreAVX2 - VPSLLD $12, BB0, CC3; VPSRLD $20, BB0, BB0; VPXOR CC3, BB0, BB0 - VPSLLD $12, BB1, CC3; VPSRLD $20, BB1, BB1; VPXOR CC3, BB1, BB1 - VPSLLD $12, BB2, CC3; VPSRLD $20, BB2, BB2; VPXOR CC3, BB2, BB2 - VPSLLD $12, BB3, CC3; VPSRLD $20, BB3, BB3; VPXOR CC3, BB3, BB3 - VMOVDQA tmpStoreAVX2, CC3 - polyAdd(0*8(itr2)) - polyMulAVX2 - VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 - VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 - VPSHUFB ·rol8<>(SB), DD0, DD0; VPSHUFB ·rol8<>(SB), DD1, DD1; VPSHUFB ·rol8<>(SB), DD2, DD2; VPSHUFB ·rol8<>(SB), DD3, DD3 - VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 - VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 - VMOVDQA CC3, tmpStoreAVX2 - VPSLLD $7, BB0, CC3; VPSRLD $25, BB0, BB0; VPXOR CC3, BB0, BB0 - VPSLLD $7, BB1, CC3; VPSRLD $25, BB1, BB1; VPXOR CC3, BB1, BB1 - VPSLLD $7, BB2, CC3; VPSRLD $25, BB2, BB2; VPXOR CC3, BB2, BB2 - VPSLLD $7, BB3, CC3; VPSRLD $25, BB3, BB3; VPXOR CC3, BB3, BB3 - VMOVDQA tmpStoreAVX2, CC3 - VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $4, BB2, BB2, BB2; VPALIGNR $4, BB3, BB3, BB3 - VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $8, CC3, CC3, CC3 - VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1; VPALIGNR $12, DD2, DD2, DD2; VPALIGNR $12, DD3, DD3, DD3 - VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 - VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 - VPSHUFB ·rol16<>(SB), DD0, DD0; VPSHUFB ·rol16<>(SB), DD1, DD1; VPSHUFB ·rol16<>(SB), DD2, DD2; VPSHUFB ·rol16<>(SB), DD3, DD3 - VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 - VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 - polyAdd(2*8(itr2)) - polyMulAVX2 - LEAQ (4*8)(itr2), itr2 - VMOVDQA CC3, tmpStoreAVX2 - VPSLLD $12, BB0, CC3; VPSRLD $20, BB0, BB0; VPXOR CC3, BB0, BB0 - VPSLLD $12, BB1, CC3; VPSRLD $20, BB1, BB1; VPXOR CC3, BB1, BB1 - VPSLLD $12, BB2, CC3; VPSRLD $20, BB2, BB2; VPXOR CC3, BB2, BB2 - VPSLLD $12, BB3, CC3; VPSRLD $20, BB3, BB3; VPXOR CC3, BB3, BB3 - VMOVDQA tmpStoreAVX2, CC3 - VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 - VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 - VPSHUFB ·rol8<>(SB), DD0, DD0; VPSHUFB ·rol8<>(SB), DD1, DD1; VPSHUFB ·rol8<>(SB), DD2, DD2; VPSHUFB ·rol8<>(SB), DD3, DD3 - VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 - VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 - VMOVDQA CC3, tmpStoreAVX2 - VPSLLD $7, BB0, CC3; VPSRLD $25, BB0, BB0; VPXOR CC3, BB0, BB0 - VPSLLD $7, BB1, CC3; VPSRLD $25, BB1, BB1; VPXOR CC3, BB1, BB1 - VPSLLD $7, BB2, CC3; VPSRLD $25, BB2, BB2; VPXOR CC3, BB2, BB2 - VPSLLD $7, BB3, CC3; VPSRLD $25, BB3, BB3; VPXOR CC3, BB3, BB3 - VMOVDQA tmpStoreAVX2, CC3 - VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $12, BB2, BB2, BB2; VPALIGNR $12, BB3, BB3, BB3 - VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $8, CC3, CC3, CC3 - VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1; VPALIGNR $4, DD2, DD2, DD2; VPALIGNR $4, DD3, DD3, DD3 - INCQ itr1 - CMPQ itr1, $4 + VPADDD Y14, Y0, Y0 + VPADDD Y9, Y5, Y5 + VPADDD Y10, Y6, Y6 + VPADDD Y11, Y7, Y7 + VPXOR Y0, Y4, Y4 + VPXOR Y5, Y1, Y1 + VPXOR Y6, Y2, Y2 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y2, Y2 + VPSHUFB ·rol16<>+0(SB), Y3, Y3 + VPADDD Y4, Y12, Y12 + VPADDD Y1, Y13, Y13 + VPADDD Y2, Y8, Y8 + VPADDD Y3, Y15, Y15 + VPXOR Y12, Y14, Y14 + VPXOR Y13, Y9, Y9 + VPXOR Y8, Y10, Y10 + VPXOR Y15, Y11, Y11 + VMOVDQA Y15, 224(BP) + VPSLLD $0x0c, Y14, Y15 + VPSRLD $0x14, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPSLLD $0x0c, Y9, Y15 + VPSRLD $0x14, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPSLLD $0x0c, Y10, Y15 + VPSRLD $0x14, Y10, Y10 + VPXOR Y15, Y10, Y10 + VPSLLD $0x0c, Y11, Y15 + VPSRLD $0x14, Y11, Y11 + VPXOR Y15, Y11, Y11 + VMOVDQA 224(BP), Y15 + ADDQ (R9), R10 + ADCQ 8(R9), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + VPADDD Y14, Y0, Y0 + VPADDD Y9, Y5, Y5 + VPADDD Y10, Y6, Y6 + VPADDD Y11, Y7, Y7 + VPXOR Y0, Y4, Y4 + VPXOR Y5, Y1, Y1 + VPXOR Y6, Y2, Y2 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y2, Y2 + VPSHUFB ·rol8<>+0(SB), Y3, Y3 + VPADDD Y4, Y12, Y12 + VPADDD Y1, Y13, Y13 + VPADDD Y2, Y8, Y8 + VPADDD Y3, Y15, Y15 + VPXOR Y12, Y14, Y14 + VPXOR Y13, Y9, Y9 + VPXOR Y8, Y10, Y10 + VPXOR Y15, Y11, Y11 + VMOVDQA Y15, 224(BP) + VPSLLD $0x07, Y14, Y15 + VPSRLD $0x19, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPSLLD $0x07, Y9, Y15 + VPSRLD $0x19, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPSLLD $0x07, Y10, Y15 + VPSRLD $0x19, Y10, Y10 + VPXOR Y15, Y10, Y10 + VPSLLD $0x07, Y11, Y15 + VPSRLD $0x19, Y11, Y11 + VPXOR Y15, Y11, Y11 + VMOVDQA 224(BP), Y15 + VPALIGNR $0x04, Y14, Y14, Y14 + VPALIGNR $0x04, Y9, Y9, Y9 + VPALIGNR $0x04, Y10, Y10, Y10 + VPALIGNR $0x04, Y11, Y11, Y11 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x08, Y8, Y8, Y8 + VPALIGNR $0x08, Y15, Y15, Y15 + VPALIGNR $0x0c, Y4, Y4, Y4 + VPALIGNR $0x0c, Y1, Y1, Y1 + VPALIGNR $0x0c, Y2, Y2, Y2 + VPALIGNR $0x0c, Y3, Y3, Y3 + VPADDD Y14, Y0, Y0 + VPADDD Y9, Y5, Y5 + VPADDD Y10, Y6, Y6 + VPADDD Y11, Y7, Y7 + VPXOR Y0, Y4, Y4 + VPXOR Y5, Y1, Y1 + VPXOR Y6, Y2, Y2 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y2, Y2 + VPSHUFB ·rol16<>+0(SB), Y3, Y3 + VPADDD Y4, Y12, Y12 + VPADDD Y1, Y13, Y13 + VPADDD Y2, Y8, Y8 + VPADDD Y3, Y15, Y15 + VPXOR Y12, Y14, Y14 + VPXOR Y13, Y9, Y9 + VPXOR Y8, Y10, Y10 + VPXOR Y15, Y11, Y11 + ADDQ 16(R9), R10 + ADCQ 24(R9), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 32(R9), R9 + VMOVDQA Y15, 224(BP) + VPSLLD $0x0c, Y14, Y15 + VPSRLD $0x14, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPSLLD $0x0c, Y9, Y15 + VPSRLD $0x14, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPSLLD $0x0c, Y10, Y15 + VPSRLD $0x14, Y10, Y10 + VPXOR Y15, Y10, Y10 + VPSLLD $0x0c, Y11, Y15 + VPSRLD $0x14, Y11, Y11 + VPXOR Y15, Y11, Y11 + VMOVDQA 224(BP), Y15 + VPADDD Y14, Y0, Y0 + VPADDD Y9, Y5, Y5 + VPADDD Y10, Y6, Y6 + VPADDD Y11, Y7, Y7 + VPXOR Y0, Y4, Y4 + VPXOR Y5, Y1, Y1 + VPXOR Y6, Y2, Y2 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y2, Y2 + VPSHUFB ·rol8<>+0(SB), Y3, Y3 + VPADDD Y4, Y12, Y12 + VPADDD Y1, Y13, Y13 + VPADDD Y2, Y8, Y8 + VPADDD Y3, Y15, Y15 + VPXOR Y12, Y14, Y14 + VPXOR Y13, Y9, Y9 + VPXOR Y8, Y10, Y10 + VPXOR Y15, Y11, Y11 + VMOVDQA Y15, 224(BP) + VPSLLD $0x07, Y14, Y15 + VPSRLD $0x19, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPSLLD $0x07, Y9, Y15 + VPSRLD $0x19, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPSLLD $0x07, Y10, Y15 + VPSRLD $0x19, Y10, Y10 + VPXOR Y15, Y10, Y10 + VPSLLD $0x07, Y11, Y15 + VPSRLD $0x19, Y11, Y11 + VPXOR Y15, Y11, Y11 + VMOVDQA 224(BP), Y15 + VPALIGNR $0x0c, Y14, Y14, Y14 + VPALIGNR $0x0c, Y9, Y9, Y9 + VPALIGNR $0x0c, Y10, Y10, Y10 + VPALIGNR $0x0c, Y11, Y11, Y11 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x08, Y8, Y8, Y8 + VPALIGNR $0x08, Y15, Y15, Y15 + VPALIGNR $0x04, Y4, Y4, Y4 + VPALIGNR $0x04, Y1, Y1, Y1 + VPALIGNR $0x04, Y2, Y2, Y2 + VPALIGNR $0x04, Y3, Y3, Y3 + INCQ CX + CMPQ CX, $0x04 JLT openAVX2Tail512LoopB - - CMPQ itr1, $10 - JNE openAVX2Tail512LoopA - - MOVQ inl, itr1 - SUBQ $384, itr1 - ANDQ $-16, itr1 + CMPQ CX, $0x0a + JNE openAVX2Tail512LoopA + MOVQ BX, CX + SUBQ $0x00000180, CX + ANDQ $-16, CX openAVX2Tail512HashLoop: - TESTQ itr1, itr1 + TESTQ CX, CX JE openAVX2Tail512HashEnd - polyAdd(0(itr2)) - polyMulAVX2 - LEAQ 16(itr2), itr2 - SUBQ $16, itr1 + ADDQ (R9), R10 + ADCQ 8(R9), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 16(R9), R9 + SUBQ $0x10, CX JMP openAVX2Tail512HashLoop openAVX2Tail512HashEnd: - VPADDD ·chacha20Constants<>(SB), AA0, AA0; VPADDD ·chacha20Constants<>(SB), AA1, AA1; VPADDD ·chacha20Constants<>(SB), AA2, AA2; VPADDD ·chacha20Constants<>(SB), AA3, AA3 - VPADDD state1StoreAVX2, BB0, BB0; VPADDD state1StoreAVX2, BB1, BB1; VPADDD state1StoreAVX2, BB2, BB2; VPADDD state1StoreAVX2, BB3, BB3 - VPADDD state2StoreAVX2, CC0, CC0; VPADDD state2StoreAVX2, CC1, CC1; VPADDD state2StoreAVX2, CC2, CC2; VPADDD state2StoreAVX2, CC3, CC3 - VPADDD ctr0StoreAVX2, DD0, DD0; VPADDD ctr1StoreAVX2, DD1, DD1; VPADDD ctr2StoreAVX2, DD2, DD2; VPADDD ctr3StoreAVX2, DD3, DD3 - VMOVDQA CC3, tmpStoreAVX2 - VPERM2I128 $0x02, AA0, BB0, CC3; VPERM2I128 $0x13, AA0, BB0, BB0; VPERM2I128 $0x02, CC0, DD0, AA0; VPERM2I128 $0x13, CC0, DD0, CC0 - VPXOR (0*32)(inp), CC3, CC3; VPXOR (1*32)(inp), AA0, AA0; VPXOR (2*32)(inp), BB0, BB0; VPXOR (3*32)(inp), CC0, CC0 - VMOVDQU CC3, (0*32)(oup); VMOVDQU AA0, (1*32)(oup); VMOVDQU BB0, (2*32)(oup); VMOVDQU CC0, (3*32)(oup) - VPERM2I128 $0x02, AA1, BB1, AA0; VPERM2I128 $0x02, CC1, DD1, BB0; VPERM2I128 $0x13, AA1, BB1, CC0; VPERM2I128 $0x13, CC1, DD1, DD0 - VPXOR (4*32)(inp), AA0, AA0; VPXOR (5*32)(inp), BB0, BB0; VPXOR (6*32)(inp), CC0, CC0; VPXOR (7*32)(inp), DD0, DD0 - VMOVDQU AA0, (4*32)(oup); VMOVDQU BB0, (5*32)(oup); VMOVDQU CC0, (6*32)(oup); VMOVDQU DD0, (7*32)(oup) - VPERM2I128 $0x02, AA2, BB2, AA0; VPERM2I128 $0x02, CC2, DD2, BB0; VPERM2I128 $0x13, AA2, BB2, CC0; VPERM2I128 $0x13, CC2, DD2, DD0 - VPXOR (8*32)(inp), AA0, AA0; VPXOR (9*32)(inp), BB0, BB0; VPXOR (10*32)(inp), CC0, CC0; VPXOR (11*32)(inp), DD0, DD0 - VMOVDQU AA0, (8*32)(oup); VMOVDQU BB0, (9*32)(oup); VMOVDQU CC0, (10*32)(oup); VMOVDQU DD0, (11*32)(oup) - VPERM2I128 $0x02, AA3, BB3, AA0; VPERM2I128 $0x02, tmpStoreAVX2, DD3, BB0; VPERM2I128 $0x13, AA3, BB3, CC0; VPERM2I128 $0x13, tmpStoreAVX2, DD3, DD0 - - LEAQ (12*32)(inp), inp - LEAQ (12*32)(oup), oup - SUBQ $12*32, inl - - JMP openAVX2TailLoop - -// ---------------------------------------------------------------------------- -// ---------------------------------------------------------------------------- -// func chacha20Poly1305Seal(dst, key, src, ad []byte) -TEXT ·chacha20Poly1305Seal(SB), 0, $288-96 - // For aligned stack access + VPADDD ·chacha20Constants<>+0(SB), Y0, Y0 + VPADDD ·chacha20Constants<>+0(SB), Y5, Y5 + VPADDD ·chacha20Constants<>+0(SB), Y6, Y6 + VPADDD ·chacha20Constants<>+0(SB), Y7, Y7 + VPADDD 32(BP), Y14, Y14 + VPADDD 32(BP), Y9, Y9 + VPADDD 32(BP), Y10, Y10 + VPADDD 32(BP), Y11, Y11 + VPADDD 64(BP), Y12, Y12 + VPADDD 64(BP), Y13, Y13 + VPADDD 64(BP), Y8, Y8 + VPADDD 64(BP), Y15, Y15 + VPADDD 96(BP), Y4, Y4 + VPADDD 128(BP), Y1, Y1 + VPADDD 160(BP), Y2, Y2 + VPADDD 192(BP), Y3, Y3 + VMOVDQA Y15, 224(BP) + VPERM2I128 $0x02, Y0, Y14, Y15 + VPERM2I128 $0x13, Y0, Y14, Y14 + VPERM2I128 $0x02, Y12, Y4, Y0 + VPERM2I128 $0x13, Y12, Y4, Y12 + VPXOR (SI), Y15, Y15 + VPXOR 32(SI), Y0, Y0 + VPXOR 64(SI), Y14, Y14 + VPXOR 96(SI), Y12, Y12 + VMOVDQU Y15, (DI) + VMOVDQU Y0, 32(DI) + VMOVDQU Y14, 64(DI) + VMOVDQU Y12, 96(DI) + VPERM2I128 $0x02, Y5, Y9, Y0 + VPERM2I128 $0x02, Y13, Y1, Y14 + VPERM2I128 $0x13, Y5, Y9, Y12 + VPERM2I128 $0x13, Y13, Y1, Y4 + VPXOR 128(SI), Y0, Y0 + VPXOR 160(SI), Y14, Y14 + VPXOR 192(SI), Y12, Y12 + VPXOR 224(SI), Y4, Y4 + VMOVDQU Y0, 128(DI) + VMOVDQU Y14, 160(DI) + VMOVDQU Y12, 192(DI) + VMOVDQU Y4, 224(DI) + VPERM2I128 $0x02, Y6, Y10, Y0 + VPERM2I128 $0x02, Y8, Y2, Y14 + VPERM2I128 $0x13, Y6, Y10, Y12 + VPERM2I128 $0x13, Y8, Y2, Y4 + VPXOR 256(SI), Y0, Y0 + VPXOR 288(SI), Y14, Y14 + VPXOR 320(SI), Y12, Y12 + VPXOR 352(SI), Y4, Y4 + VMOVDQU Y0, 256(DI) + VMOVDQU Y14, 288(DI) + VMOVDQU Y12, 320(DI) + VMOVDQU Y4, 352(DI) + VPERM2I128 $0x02, Y7, Y11, Y0 + VPERM2I128 $0x02, 224(BP), Y3, Y14 + VPERM2I128 $0x13, Y7, Y11, Y12 + VPERM2I128 $0x13, 224(BP), Y3, Y4 + LEAQ 384(SI), SI + LEAQ 384(DI), DI + SUBQ $0x00000180, BX + JMP openAVX2TailLoop + +DATA ·chacha20Constants<>+0(SB)/4, $0x61707865 +DATA ·chacha20Constants<>+4(SB)/4, $0x3320646e +DATA ·chacha20Constants<>+8(SB)/4, $0x79622d32 +DATA ·chacha20Constants<>+12(SB)/4, $0x6b206574 +DATA ·chacha20Constants<>+16(SB)/4, $0x61707865 +DATA ·chacha20Constants<>+20(SB)/4, $0x3320646e +DATA ·chacha20Constants<>+24(SB)/4, $0x79622d32 +DATA ·chacha20Constants<>+28(SB)/4, $0x6b206574 +GLOBL ·chacha20Constants<>(SB), RODATA|NOPTR, $32 + +DATA ·polyClampMask<>+0(SB)/8, $0x0ffffffc0fffffff +DATA ·polyClampMask<>+8(SB)/8, $0x0ffffffc0ffffffc +DATA ·polyClampMask<>+16(SB)/8, $0xffffffffffffffff +DATA ·polyClampMask<>+24(SB)/8, $0xffffffffffffffff +GLOBL ·polyClampMask<>(SB), RODATA|NOPTR, $32 + +DATA ·sseIncMask<>+0(SB)/8, $0x0000000000000001 +DATA ·sseIncMask<>+8(SB)/8, $0x0000000000000000 +GLOBL ·sseIncMask<>(SB), RODATA|NOPTR, $16 + +DATA ·andMask<>+0(SB)/8, $0x00000000000000ff +DATA ·andMask<>+8(SB)/8, $0x0000000000000000 +DATA ·andMask<>+16(SB)/8, $0x000000000000ffff +DATA ·andMask<>+24(SB)/8, $0x0000000000000000 +DATA ·andMask<>+32(SB)/8, $0x0000000000ffffff +DATA ·andMask<>+40(SB)/8, $0x0000000000000000 +DATA ·andMask<>+48(SB)/8, $0x00000000ffffffff +DATA ·andMask<>+56(SB)/8, $0x0000000000000000 +DATA ·andMask<>+64(SB)/8, $0x000000ffffffffff +DATA ·andMask<>+72(SB)/8, $0x0000000000000000 +DATA ·andMask<>+80(SB)/8, $0x0000ffffffffffff +DATA ·andMask<>+88(SB)/8, $0x0000000000000000 +DATA ·andMask<>+96(SB)/8, $0x00ffffffffffffff +DATA ·andMask<>+104(SB)/8, $0x0000000000000000 +DATA ·andMask<>+112(SB)/8, $0xffffffffffffffff +DATA ·andMask<>+120(SB)/8, $0x0000000000000000 +DATA ·andMask<>+128(SB)/8, $0xffffffffffffffff +DATA ·andMask<>+136(SB)/8, $0x00000000000000ff +DATA ·andMask<>+144(SB)/8, $0xffffffffffffffff +DATA ·andMask<>+152(SB)/8, $0x000000000000ffff +DATA ·andMask<>+160(SB)/8, $0xffffffffffffffff +DATA ·andMask<>+168(SB)/8, $0x0000000000ffffff +DATA ·andMask<>+176(SB)/8, $0xffffffffffffffff +DATA ·andMask<>+184(SB)/8, $0x00000000ffffffff +DATA ·andMask<>+192(SB)/8, $0xffffffffffffffff +DATA ·andMask<>+200(SB)/8, $0x000000ffffffffff +DATA ·andMask<>+208(SB)/8, $0xffffffffffffffff +DATA ·andMask<>+216(SB)/8, $0x0000ffffffffffff +DATA ·andMask<>+224(SB)/8, $0xffffffffffffffff +DATA ·andMask<>+232(SB)/8, $0x00ffffffffffffff +GLOBL ·andMask<>(SB), RODATA|NOPTR, $240 + +DATA ·avx2InitMask<>+0(SB)/8, $0x0000000000000000 +DATA ·avx2InitMask<>+8(SB)/8, $0x0000000000000000 +DATA ·avx2InitMask<>+16(SB)/8, $0x0000000000000001 +DATA ·avx2InitMask<>+24(SB)/8, $0x0000000000000000 +GLOBL ·avx2InitMask<>(SB), RODATA|NOPTR, $32 + +DATA ·rol16<>+0(SB)/8, $0x0504070601000302 +DATA ·rol16<>+8(SB)/8, $0x0d0c0f0e09080b0a +DATA ·rol16<>+16(SB)/8, $0x0504070601000302 +DATA ·rol16<>+24(SB)/8, $0x0d0c0f0e09080b0a +GLOBL ·rol16<>(SB), RODATA|NOPTR, $32 + +DATA ·rol8<>+0(SB)/8, $0x0605040702010003 +DATA ·rol8<>+8(SB)/8, $0x0e0d0c0f0a09080b +DATA ·rol8<>+16(SB)/8, $0x0605040702010003 +DATA ·rol8<>+24(SB)/8, $0x0e0d0c0f0a09080b +GLOBL ·rol8<>(SB), RODATA|NOPTR, $32 + +DATA ·avx2IncMask<>+0(SB)/8, $0x0000000000000002 +DATA ·avx2IncMask<>+8(SB)/8, $0x0000000000000000 +DATA ·avx2IncMask<>+16(SB)/8, $0x0000000000000002 +DATA ·avx2IncMask<>+24(SB)/8, $0x0000000000000000 +GLOBL ·avx2IncMask<>(SB), RODATA|NOPTR, $32 + +// func chacha20Poly1305Seal(dst []byte, key []uint32, src []byte, ad []byte) +// Requires: AVX, AVX2, BMI2, CMOV, SSE2 +TEXT ·chacha20Poly1305Seal(SB), $288-96 MOVQ SP, BP - ADDQ $32, BP + ADDQ $0x20, BP ANDQ $-32, BP - MOVQ dst+0(FP), oup - MOVQ key+24(FP), keyp - MOVQ src+48(FP), inp - MOVQ src_len+56(FP), inl - MOVQ ad+72(FP), adp - - CMPB ·useAVX2(SB), $1 + MOVQ dst_base+0(FP), DI + MOVQ key_base+24(FP), R8 + MOVQ src_base+48(FP), SI + MOVQ src_len+56(FP), BX + MOVQ ad_base+72(FP), CX + CMPB ·useAVX2+0(SB), $0x01 JE chacha20Poly1305Seal_AVX2 // Special optimization, for very short buffers - CMPQ inl, $128 - JBE sealSSE128 // About 15% faster + CMPQ BX, $0x80 + JBE sealSSE128 // In the seal case - prepare the poly key + 3 blocks of stream in the first iteration - MOVOU ·chacha20Constants<>(SB), A0 - MOVOU (1*16)(keyp), B0 - MOVOU (2*16)(keyp), C0 - MOVOU (3*16)(keyp), D0 + MOVOU ·chacha20Constants<>+0(SB), X0 + MOVOU 16(R8), X3 + MOVOU 32(R8), X6 + MOVOU 48(R8), X9 // Store state on stack for future use - MOVO B0, state1Store - MOVO C0, state2Store + MOVO X3, 32(BP) + MOVO X6, 48(BP) // Load state, increment counter blocks - MOVO A0, A1; MOVO B0, B1; MOVO C0, C1; MOVO D0, D1; PADDL ·sseIncMask<>(SB), D1 - MOVO A1, A2; MOVO B1, B2; MOVO C1, C2; MOVO D1, D2; PADDL ·sseIncMask<>(SB), D2 - MOVO A2, A3; MOVO B2, B3; MOVO C2, C3; MOVO D2, D3; PADDL ·sseIncMask<>(SB), D3 + MOVO X0, X1 + MOVO X3, X4 + MOVO X6, X7 + MOVO X9, X10 + PADDL ·sseIncMask<>+0(SB), X10 + MOVO X1, X2 + MOVO X4, X5 + MOVO X7, X8 + MOVO X10, X11 + PADDL ·sseIncMask<>+0(SB), X11 + MOVO X2, X12 + MOVO X5, X13 + MOVO X8, X14 + MOVO X11, X15 + PADDL ·sseIncMask<>+0(SB), X15 // Store counters - MOVO D0, ctr0Store; MOVO D1, ctr1Store; MOVO D2, ctr2Store; MOVO D3, ctr3Store - MOVQ $10, itr2 + MOVO X9, 80(BP) + MOVO X10, 96(BP) + MOVO X11, 112(BP) + MOVO X15, 128(BP) + MOVQ $0x0000000a, R9 sealSSEIntroLoop: - MOVO C3, tmpStore - chachaQR(A0, B0, C0, D0, C3); chachaQR(A1, B1, C1, D1, C3); chachaQR(A2, B2, C2, D2, C3) - MOVO tmpStore, C3 - MOVO C1, tmpStore - chachaQR(A3, B3, C3, D3, C1) - MOVO tmpStore, C1 - shiftB0Left; shiftB1Left; shiftB2Left; shiftB3Left - shiftC0Left; shiftC1Left; shiftC2Left; shiftC3Left - shiftD0Left; shiftD1Left; shiftD2Left; shiftD3Left - - MOVO C3, tmpStore - chachaQR(A0, B0, C0, D0, C3); chachaQR(A1, B1, C1, D1, C3); chachaQR(A2, B2, C2, D2, C3) - MOVO tmpStore, C3 - MOVO C1, tmpStore - chachaQR(A3, B3, C3, D3, C1) - MOVO tmpStore, C1 - shiftB0Right; shiftB1Right; shiftB2Right; shiftB3Right - shiftC0Right; shiftC1Right; shiftC2Right; shiftC3Right - shiftD0Right; shiftD1Right; shiftD2Right; shiftD3Right - DECQ itr2 - JNE sealSSEIntroLoop + MOVO X14, 64(BP) + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X14) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X3 + PXOR X14, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X14) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X3 + PXOR X14, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X14) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X4 + PXOR X14, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X14) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X4 + PXOR X14, X4 + PADDD X5, X2 + PXOR X2, X11 + ROL16(X11, X14) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X5 + PXOR X14, X5 + PADDD X5, X2 + PXOR X2, X11 + ROL8(X11, X14) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X5 + PXOR X14, X5 + MOVO 64(BP), X14 + MOVO X7, 64(BP) + PADDD X13, X12 + PXOR X12, X15 + ROL16(X15, X7) + PADDD X15, X14 + PXOR X14, X13 + MOVO X13, X7 + PSLLL $0x0c, X7 + PSRLL $0x14, X13 + PXOR X7, X13 + PADDD X13, X12 + PXOR X12, X15 + ROL8(X15, X7) + PADDD X15, X14 + PXOR X14, X13 + MOVO X13, X7 + PSLLL $0x07, X7 + PSRLL $0x19, X13 + PXOR X7, X13 + MOVO 64(BP), X7 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc0 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x0c + MOVO X14, 64(BP) + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X14) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X3 + PXOR X14, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X14) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X3 + PXOR X14, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X14) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X4 + PXOR X14, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X14) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X4 + PXOR X14, X4 + PADDD X5, X2 + PXOR X2, X11 + ROL16(X11, X14) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X5 + PXOR X14, X5 + PADDD X5, X2 + PXOR X2, X11 + ROL8(X11, X14) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X5 + PXOR X14, X5 + MOVO 64(BP), X14 + MOVO X7, 64(BP) + PADDD X13, X12 + PXOR X12, X15 + ROL16(X15, X7) + PADDD X15, X14 + PXOR X14, X13 + MOVO X13, X7 + PSLLL $0x0c, X7 + PSRLL $0x14, X13 + PXOR X7, X13 + PADDD X13, X12 + PXOR X12, X15 + ROL8(X15, X7) + PADDD X15, X14 + PXOR X14, X13 + MOVO X13, X7 + PSLLL $0x07, X7 + PSRLL $0x19, X13 + PXOR X7, X13 + MOVO 64(BP), X7 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc0 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x04 + DECQ R9 + JNE sealSSEIntroLoop // Add in the state - PADDD ·chacha20Constants<>(SB), A0; PADDD ·chacha20Constants<>(SB), A1; PADDD ·chacha20Constants<>(SB), A2; PADDD ·chacha20Constants<>(SB), A3 - PADDD state1Store, B0; PADDD state1Store, B1; PADDD state1Store, B2; PADDD state1Store, B3 - PADDD state2Store, C1; PADDD state2Store, C2; PADDD state2Store, C3 - PADDD ctr1Store, D1; PADDD ctr2Store, D2; PADDD ctr3Store, D3 + PADDD ·chacha20Constants<>+0(SB), X0 + PADDD ·chacha20Constants<>+0(SB), X1 + PADDD ·chacha20Constants<>+0(SB), X2 + PADDD ·chacha20Constants<>+0(SB), X12 + PADDD 32(BP), X3 + PADDD 32(BP), X4 + PADDD 32(BP), X5 + PADDD 32(BP), X13 + PADDD 48(BP), X7 + PADDD 48(BP), X8 + PADDD 48(BP), X14 + PADDD 96(BP), X10 + PADDD 112(BP), X11 + PADDD 128(BP), X15 // Clamp and store the key - PAND ·polyClampMask<>(SB), A0 - MOVO A0, rStore - MOVO B0, sStore + PAND ·polyClampMask<>+0(SB), X0 + MOVO X0, (BP) + MOVO X3, 16(BP) // Hash AAD - MOVQ ad_len+80(FP), itr2 - CALL polyHashADInternal<>(SB) - - MOVOU (0*16)(inp), A0; MOVOU (1*16)(inp), B0; MOVOU (2*16)(inp), C0; MOVOU (3*16)(inp), D0 - PXOR A0, A1; PXOR B0, B1; PXOR C0, C1; PXOR D0, D1 - MOVOU A1, (0*16)(oup); MOVOU B1, (1*16)(oup); MOVOU C1, (2*16)(oup); MOVOU D1, (3*16)(oup) - MOVOU (4*16)(inp), A0; MOVOU (5*16)(inp), B0; MOVOU (6*16)(inp), C0; MOVOU (7*16)(inp), D0 - PXOR A0, A2; PXOR B0, B2; PXOR C0, C2; PXOR D0, D2 - MOVOU A2, (4*16)(oup); MOVOU B2, (5*16)(oup); MOVOU C2, (6*16)(oup); MOVOU D2, (7*16)(oup) - - MOVQ $128, itr1 - SUBQ $128, inl - LEAQ 128(inp), inp - - MOVO A3, A1; MOVO B3, B1; MOVO C3, C1; MOVO D3, D1 - - CMPQ inl, $64 - JBE sealSSE128SealHash - - MOVOU (0*16)(inp), A0; MOVOU (1*16)(inp), B0; MOVOU (2*16)(inp), C0; MOVOU (3*16)(inp), D0 - PXOR A0, A3; PXOR B0, B3; PXOR C0, C3; PXOR D0, D3 - MOVOU A3, (8*16)(oup); MOVOU B3, (9*16)(oup); MOVOU C3, (10*16)(oup); MOVOU D3, (11*16)(oup) - - ADDQ $64, itr1 - SUBQ $64, inl - LEAQ 64(inp), inp - - MOVQ $2, itr1 - MOVQ $8, itr2 - - CMPQ inl, $64 - JBE sealSSETail64 - CMPQ inl, $128 - JBE sealSSETail128 - CMPQ inl, $192 - JBE sealSSETail192 + MOVQ ad_len+80(FP), R9 + CALL polyHashADInternal<>(SB) + MOVOU (SI), X0 + MOVOU 16(SI), X3 + MOVOU 32(SI), X6 + MOVOU 48(SI), X9 + PXOR X0, X1 + PXOR X3, X4 + PXOR X6, X7 + PXOR X9, X10 + MOVOU X1, (DI) + MOVOU X4, 16(DI) + MOVOU X7, 32(DI) + MOVOU X10, 48(DI) + MOVOU 64(SI), X0 + MOVOU 80(SI), X3 + MOVOU 96(SI), X6 + MOVOU 112(SI), X9 + PXOR X0, X2 + PXOR X3, X5 + PXOR X6, X8 + PXOR X9, X11 + MOVOU X2, 64(DI) + MOVOU X5, 80(DI) + MOVOU X8, 96(DI) + MOVOU X11, 112(DI) + MOVQ $0x00000080, CX + SUBQ $0x80, BX + LEAQ 128(SI), SI + MOVO X12, X1 + MOVO X13, X4 + MOVO X14, X7 + MOVO X15, X10 + CMPQ BX, $0x40 + JBE sealSSE128SealHash + MOVOU (SI), X0 + MOVOU 16(SI), X3 + MOVOU 32(SI), X6 + MOVOU 48(SI), X9 + PXOR X0, X12 + PXOR X3, X13 + PXOR X6, X14 + PXOR X9, X15 + MOVOU X12, 128(DI) + MOVOU X13, 144(DI) + MOVOU X14, 160(DI) + MOVOU X15, 176(DI) + ADDQ $0x40, CX + SUBQ $0x40, BX + LEAQ 64(SI), SI + MOVQ $0x00000002, CX + MOVQ $0x00000008, R9 + CMPQ BX, $0x40 + JBE sealSSETail64 + CMPQ BX, $0x80 + JBE sealSSETail128 + CMPQ BX, $0xc0 + JBE sealSSETail192 sealSSEMainLoop: // Load state, increment counter blocks - MOVO ·chacha20Constants<>(SB), A0; MOVO state1Store, B0; MOVO state2Store, C0; MOVO ctr3Store, D0; PADDL ·sseIncMask<>(SB), D0 - MOVO A0, A1; MOVO B0, B1; MOVO C0, C1; MOVO D0, D1; PADDL ·sseIncMask<>(SB), D1 - MOVO A1, A2; MOVO B1, B2; MOVO C1, C2; MOVO D1, D2; PADDL ·sseIncMask<>(SB), D2 - MOVO A2, A3; MOVO B2, B3; MOVO C2, C3; MOVO D2, D3; PADDL ·sseIncMask<>(SB), D3 + MOVO ·chacha20Constants<>+0(SB), X0 + MOVO 32(BP), X3 + MOVO 48(BP), X6 + MOVO 128(BP), X9 + PADDL ·sseIncMask<>+0(SB), X9 + MOVO X0, X1 + MOVO X3, X4 + MOVO X6, X7 + MOVO X9, X10 + PADDL ·sseIncMask<>+0(SB), X10 + MOVO X1, X2 + MOVO X4, X5 + MOVO X7, X8 + MOVO X10, X11 + PADDL ·sseIncMask<>+0(SB), X11 + MOVO X2, X12 + MOVO X5, X13 + MOVO X8, X14 + MOVO X11, X15 + PADDL ·sseIncMask<>+0(SB), X15 // Store counters - MOVO D0, ctr0Store; MOVO D1, ctr1Store; MOVO D2, ctr2Store; MOVO D3, ctr3Store + MOVO X9, 80(BP) + MOVO X10, 96(BP) + MOVO X11, 112(BP) + MOVO X15, 128(BP) sealSSEInnerLoop: - MOVO C3, tmpStore - chachaQR(A0, B0, C0, D0, C3); chachaQR(A1, B1, C1, D1, C3); chachaQR(A2, B2, C2, D2, C3) - MOVO tmpStore, C3 - MOVO C1, tmpStore - chachaQR(A3, B3, C3, D3, C1) - MOVO tmpStore, C1 - polyAdd(0(oup)) - shiftB0Left; shiftB1Left; shiftB2Left; shiftB3Left - shiftC0Left; shiftC1Left; shiftC2Left; shiftC3Left - shiftD0Left; shiftD1Left; shiftD2Left; shiftD3Left - polyMulStage1 - polyMulStage2 - LEAQ (2*8)(oup), oup - MOVO C3, tmpStore - chachaQR(A0, B0, C0, D0, C3); chachaQR(A1, B1, C1, D1, C3); chachaQR(A2, B2, C2, D2, C3) - MOVO tmpStore, C3 - MOVO C1, tmpStore - polyMulStage3 - chachaQR(A3, B3, C3, D3, C1) - MOVO tmpStore, C1 - polyMulReduceStage - shiftB0Right; shiftB1Right; shiftB2Right; shiftB3Right - shiftC0Right; shiftC1Right; shiftC2Right; shiftC3Right - shiftD0Right; shiftD1Right; shiftD2Right; shiftD3Right - DECQ itr2 - JGE sealSSEInnerLoop - polyAdd(0(oup)) - polyMul - LEAQ (2*8)(oup), oup - DECQ itr1 - JG sealSSEInnerLoop + MOVO X14, 64(BP) + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X14) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X3 + PXOR X14, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X14) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X3 + PXOR X14, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X14) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X4 + PXOR X14, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X14) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X4 + PXOR X14, X4 + PADDD X5, X2 + PXOR X2, X11 + ROL16(X11, X14) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X5 + PXOR X14, X5 + PADDD X5, X2 + PXOR X2, X11 + ROL8(X11, X14) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X5 + PXOR X14, X5 + MOVO 64(BP), X14 + MOVO X7, 64(BP) + PADDD X13, X12 + PXOR X12, X15 + ROL16(X15, X7) + PADDD X15, X14 + PXOR X14, X13 + MOVO X13, X7 + PSLLL $0x0c, X7 + PSRLL $0x14, X13 + PXOR X7, X13 + PADDD X13, X12 + PXOR X12, X15 + ROL8(X15, X7) + PADDD X15, X14 + PXOR X14, X13 + MOVO X13, X7 + PSLLL $0x07, X7 + PSRLL $0x19, X13 + PXOR X7, X13 + MOVO 64(BP), X7 + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc0 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x0c + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + LEAQ 16(DI), DI + MOVO X14, 64(BP) + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X14) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X3 + PXOR X14, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X14) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X3 + PXOR X14, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X14) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X4 + PXOR X14, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X14) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X4 + PXOR X14, X4 + PADDD X5, X2 + PXOR X2, X11 + ROL16(X11, X14) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X5 + PXOR X14, X5 + PADDD X5, X2 + PXOR X2, X11 + ROL8(X11, X14) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X5 + PXOR X14, X5 + MOVO 64(BP), X14 + MOVO X7, 64(BP) + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + PADDD X13, X12 + PXOR X12, X15 + ROL16(X15, X7) + PADDD X15, X14 + PXOR X14, X13 + MOVO X13, X7 + PSLLL $0x0c, X7 + PSRLL $0x14, X13 + PXOR X7, X13 + PADDD X13, X12 + PXOR X12, X15 + ROL8(X15, X7) + PADDD X15, X14 + PXOR X14, X13 + MOVO X13, X7 + PSLLL $0x07, X7 + PSRLL $0x19, X13 + PXOR X7, X13 + MOVO 64(BP), X7 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc0 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x04 + DECQ R9 + JGE sealSSEInnerLoop + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 16(DI), DI + DECQ CX + JG sealSSEInnerLoop // Add in the state - PADDD ·chacha20Constants<>(SB), A0; PADDD ·chacha20Constants<>(SB), A1; PADDD ·chacha20Constants<>(SB), A2; PADDD ·chacha20Constants<>(SB), A3 - PADDD state1Store, B0; PADDD state1Store, B1; PADDD state1Store, B2; PADDD state1Store, B3 - PADDD state2Store, C0; PADDD state2Store, C1; PADDD state2Store, C2; PADDD state2Store, C3 - PADDD ctr0Store, D0; PADDD ctr1Store, D1; PADDD ctr2Store, D2; PADDD ctr3Store, D3 - MOVO D3, tmpStore + PADDD ·chacha20Constants<>+0(SB), X0 + PADDD ·chacha20Constants<>+0(SB), X1 + PADDD ·chacha20Constants<>+0(SB), X2 + PADDD ·chacha20Constants<>+0(SB), X12 + PADDD 32(BP), X3 + PADDD 32(BP), X4 + PADDD 32(BP), X5 + PADDD 32(BP), X13 + PADDD 48(BP), X6 + PADDD 48(BP), X7 + PADDD 48(BP), X8 + PADDD 48(BP), X14 + PADDD 80(BP), X9 + PADDD 96(BP), X10 + PADDD 112(BP), X11 + PADDD 128(BP), X15 + MOVO X15, 64(BP) // Load - xor - store - MOVOU (0*16)(inp), D3; PXOR D3, A0 - MOVOU (1*16)(inp), D3; PXOR D3, B0 - MOVOU (2*16)(inp), D3; PXOR D3, C0 - MOVOU (3*16)(inp), D3; PXOR D3, D0 - MOVOU A0, (0*16)(oup) - MOVOU B0, (1*16)(oup) - MOVOU C0, (2*16)(oup) - MOVOU D0, (3*16)(oup) - MOVO tmpStore, D3 - - MOVOU (4*16)(inp), A0; MOVOU (5*16)(inp), B0; MOVOU (6*16)(inp), C0; MOVOU (7*16)(inp), D0 - PXOR A0, A1; PXOR B0, B1; PXOR C0, C1; PXOR D0, D1 - MOVOU A1, (4*16)(oup); MOVOU B1, (5*16)(oup); MOVOU C1, (6*16)(oup); MOVOU D1, (7*16)(oup) - MOVOU (8*16)(inp), A0; MOVOU (9*16)(inp), B0; MOVOU (10*16)(inp), C0; MOVOU (11*16)(inp), D0 - PXOR A0, A2; PXOR B0, B2; PXOR C0, C2; PXOR D0, D2 - MOVOU A2, (8*16)(oup); MOVOU B2, (9*16)(oup); MOVOU C2, (10*16)(oup); MOVOU D2, (11*16)(oup) - ADDQ $192, inp - MOVQ $192, itr1 - SUBQ $192, inl - MOVO A3, A1 - MOVO B3, B1 - MOVO C3, C1 - MOVO D3, D1 - CMPQ inl, $64 + MOVOU (SI), X15 + PXOR X15, X0 + MOVOU 16(SI), X15 + PXOR X15, X3 + MOVOU 32(SI), X15 + PXOR X15, X6 + MOVOU 48(SI), X15 + PXOR X15, X9 + MOVOU X0, (DI) + MOVOU X3, 16(DI) + MOVOU X6, 32(DI) + MOVOU X9, 48(DI) + MOVO 64(BP), X15 + MOVOU 64(SI), X0 + MOVOU 80(SI), X3 + MOVOU 96(SI), X6 + MOVOU 112(SI), X9 + PXOR X0, X1 + PXOR X3, X4 + PXOR X6, X7 + PXOR X9, X10 + MOVOU X1, 64(DI) + MOVOU X4, 80(DI) + MOVOU X7, 96(DI) + MOVOU X10, 112(DI) + MOVOU 128(SI), X0 + MOVOU 144(SI), X3 + MOVOU 160(SI), X6 + MOVOU 176(SI), X9 + PXOR X0, X2 + PXOR X3, X5 + PXOR X6, X8 + PXOR X9, X11 + MOVOU X2, 128(DI) + MOVOU X5, 144(DI) + MOVOU X8, 160(DI) + MOVOU X11, 176(DI) + ADDQ $0xc0, SI + MOVQ $0x000000c0, CX + SUBQ $0xc0, BX + MOVO X12, X1 + MOVO X13, X4 + MOVO X14, X7 + MOVO X15, X10 + CMPQ BX, $0x40 JBE sealSSE128SealHash - MOVOU (0*16)(inp), A0; MOVOU (1*16)(inp), B0; MOVOU (2*16)(inp), C0; MOVOU (3*16)(inp), D0 - PXOR A0, A3; PXOR B0, B3; PXOR C0, C3; PXOR D0, D3 - MOVOU A3, (12*16)(oup); MOVOU B3, (13*16)(oup); MOVOU C3, (14*16)(oup); MOVOU D3, (15*16)(oup) - LEAQ 64(inp), inp - SUBQ $64, inl - MOVQ $6, itr1 - MOVQ $4, itr2 - CMPQ inl, $192 + MOVOU (SI), X0 + MOVOU 16(SI), X3 + MOVOU 32(SI), X6 + MOVOU 48(SI), X9 + PXOR X0, X12 + PXOR X3, X13 + PXOR X6, X14 + PXOR X9, X15 + MOVOU X12, 192(DI) + MOVOU X13, 208(DI) + MOVOU X14, 224(DI) + MOVOU X15, 240(DI) + LEAQ 64(SI), SI + SUBQ $0x40, BX + MOVQ $0x00000006, CX + MOVQ $0x00000004, R9 + CMPQ BX, $0xc0 JG sealSSEMainLoop - - MOVQ inl, itr1 - TESTQ inl, inl + MOVQ BX, CX + TESTQ BX, BX JE sealSSE128SealHash - MOVQ $6, itr1 - CMPQ inl, $64 + MOVQ $0x00000006, CX + CMPQ BX, $0x40 JBE sealSSETail64 - CMPQ inl, $128 + CMPQ BX, $0x80 JBE sealSSETail128 JMP sealSSETail192 -// ---------------------------------------------------------------------------- -// Special optimization for the last 64 bytes of plaintext sealSSETail64: - // Need to encrypt up to 64 bytes - prepare single block, hash 192 or 256 bytes - MOVO ·chacha20Constants<>(SB), A1 - MOVO state1Store, B1 - MOVO state2Store, C1 - MOVO ctr3Store, D1 - PADDL ·sseIncMask<>(SB), D1 - MOVO D1, ctr0Store + MOVO ·chacha20Constants<>+0(SB), X1 + MOVO 32(BP), X4 + MOVO 48(BP), X7 + MOVO 128(BP), X10 + PADDL ·sseIncMask<>+0(SB), X10 + MOVO X10, 80(BP) sealSSETail64LoopA: - // Perform ChaCha rounds, while hashing the previously encrypted ciphertext - polyAdd(0(oup)) - polyMul - LEAQ 16(oup), oup + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 16(DI), DI sealSSETail64LoopB: - chachaQR(A1, B1, C1, D1, T1) - shiftB1Left; shiftC1Left; shiftD1Left - chachaQR(A1, B1, C1, D1, T1) - shiftB1Right; shiftC1Right; shiftD1Right - polyAdd(0(oup)) - polyMul - LEAQ 16(oup), oup - - DECQ itr1 - JG sealSSETail64LoopA - - DECQ itr2 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X13) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X13 + PSLLL $0x0c, X13 + PSRLL $0x14, X4 + PXOR X13, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X13) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X13 + PSLLL $0x07, X13 + PSRLL $0x19, X4 + PXOR X13, X4 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x0c + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X13) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X13 + PSLLL $0x0c, X13 + PSRLL $0x14, X4 + PXOR X13, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X13) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X13 + PSLLL $0x07, X13 + PSRLL $0x19, X4 + PXOR X13, X4 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x04 + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 16(DI), DI + DECQ CX + JG sealSSETail64LoopA + DECQ R9 JGE sealSSETail64LoopB - PADDL ·chacha20Constants<>(SB), A1 - PADDL state1Store, B1 - PADDL state2Store, C1 - PADDL ctr0Store, D1 + PADDL ·chacha20Constants<>+0(SB), X1 + PADDL 32(BP), X4 + PADDL 48(BP), X7 + PADDL 80(BP), X10 + JMP sealSSE128Seal - JMP sealSSE128Seal - -// ---------------------------------------------------------------------------- -// Special optimization for the last 128 bytes of plaintext sealSSETail128: - // Need to encrypt up to 128 bytes - prepare two blocks, hash 192 or 256 bytes - MOVO ·chacha20Constants<>(SB), A0; MOVO state1Store, B0; MOVO state2Store, C0; MOVO ctr3Store, D0; PADDL ·sseIncMask<>(SB), D0; MOVO D0, ctr0Store - MOVO A0, A1; MOVO B0, B1; MOVO C0, C1; MOVO D0, D1; PADDL ·sseIncMask<>(SB), D1; MOVO D1, ctr1Store + MOVO ·chacha20Constants<>+0(SB), X0 + MOVO 32(BP), X3 + MOVO 48(BP), X6 + MOVO 128(BP), X9 + PADDL ·sseIncMask<>+0(SB), X9 + MOVO X9, 80(BP) + MOVO X0, X1 + MOVO X3, X4 + MOVO X6, X7 + MOVO X9, X10 + PADDL ·sseIncMask<>+0(SB), X10 + MOVO X10, 96(BP) sealSSETail128LoopA: - // Perform ChaCha rounds, while hashing the previously encrypted ciphertext - polyAdd(0(oup)) - polyMul - LEAQ 16(oup), oup + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 16(DI), DI sealSSETail128LoopB: - chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0) - shiftB0Left; shiftC0Left; shiftD0Left - shiftB1Left; shiftC1Left; shiftD1Left - polyAdd(0(oup)) - polyMul - LEAQ 16(oup), oup - chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0) - shiftB0Right; shiftC0Right; shiftD0Right - shiftB1Right; shiftC1Right; shiftD1Right - - DECQ itr1 - JG sealSSETail128LoopA - - DECQ itr2 - JGE sealSSETail128LoopB - - PADDL ·chacha20Constants<>(SB), A0; PADDL ·chacha20Constants<>(SB), A1 - PADDL state1Store, B0; PADDL state1Store, B1 - PADDL state2Store, C0; PADDL state2Store, C1 - PADDL ctr0Store, D0; PADDL ctr1Store, D1 - - MOVOU (0*16)(inp), T0; MOVOU (1*16)(inp), T1; MOVOU (2*16)(inp), T2; MOVOU (3*16)(inp), T3 - PXOR T0, A0; PXOR T1, B0; PXOR T2, C0; PXOR T3, D0 - MOVOU A0, (0*16)(oup); MOVOU B0, (1*16)(oup); MOVOU C0, (2*16)(oup); MOVOU D0, (3*16)(oup) - - MOVQ $64, itr1 - LEAQ 64(inp), inp - SUBQ $64, inl - - JMP sealSSE128SealHash - -// ---------------------------------------------------------------------------- -// Special optimization for the last 192 bytes of plaintext + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X3 + PXOR X12, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X3 + PXOR X12, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X4 + PXOR X12, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X4 + PXOR X12, X4 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x0c + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 16(DI), DI + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X3 + PXOR X12, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X3 + PXOR X12, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X4 + PXOR X12, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X4 + PXOR X12, X4 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x04 + DECQ CX + JG sealSSETail128LoopA + DECQ R9 + JGE sealSSETail128LoopB + PADDL ·chacha20Constants<>+0(SB), X0 + PADDL ·chacha20Constants<>+0(SB), X1 + PADDL 32(BP), X3 + PADDL 32(BP), X4 + PADDL 48(BP), X6 + PADDL 48(BP), X7 + PADDL 80(BP), X9 + PADDL 96(BP), X10 + MOVOU (SI), X12 + MOVOU 16(SI), X13 + MOVOU 32(SI), X14 + MOVOU 48(SI), X15 + PXOR X12, X0 + PXOR X13, X3 + PXOR X14, X6 + PXOR X15, X9 + MOVOU X0, (DI) + MOVOU X3, 16(DI) + MOVOU X6, 32(DI) + MOVOU X9, 48(DI) + MOVQ $0x00000040, CX + LEAQ 64(SI), SI + SUBQ $0x40, BX + JMP sealSSE128SealHash + sealSSETail192: - // Need to encrypt up to 192 bytes - prepare three blocks, hash 192 or 256 bytes - MOVO ·chacha20Constants<>(SB), A0; MOVO state1Store, B0; MOVO state2Store, C0; MOVO ctr3Store, D0; PADDL ·sseIncMask<>(SB), D0; MOVO D0, ctr0Store - MOVO A0, A1; MOVO B0, B1; MOVO C0, C1; MOVO D0, D1; PADDL ·sseIncMask<>(SB), D1; MOVO D1, ctr1Store - MOVO A1, A2; MOVO B1, B2; MOVO C1, C2; MOVO D1, D2; PADDL ·sseIncMask<>(SB), D2; MOVO D2, ctr2Store + MOVO ·chacha20Constants<>+0(SB), X0 + MOVO 32(BP), X3 + MOVO 48(BP), X6 + MOVO 128(BP), X9 + PADDL ·sseIncMask<>+0(SB), X9 + MOVO X9, 80(BP) + MOVO X0, X1 + MOVO X3, X4 + MOVO X6, X7 + MOVO X9, X10 + PADDL ·sseIncMask<>+0(SB), X10 + MOVO X10, 96(BP) + MOVO X1, X2 + MOVO X4, X5 + MOVO X7, X8 + MOVO X10, X11 + PADDL ·sseIncMask<>+0(SB), X11 + MOVO X11, 112(BP) sealSSETail192LoopA: - // Perform ChaCha rounds, while hashing the previously encrypted ciphertext - polyAdd(0(oup)) - polyMul - LEAQ 16(oup), oup + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 16(DI), DI sealSSETail192LoopB: - chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0); chachaQR(A2, B2, C2, D2, T0) - shiftB0Left; shiftC0Left; shiftD0Left - shiftB1Left; shiftC1Left; shiftD1Left - shiftB2Left; shiftC2Left; shiftD2Left - - polyAdd(0(oup)) - polyMul - LEAQ 16(oup), oup - - chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0); chachaQR(A2, B2, C2, D2, T0) - shiftB0Right; shiftC0Right; shiftD0Right - shiftB1Right; shiftC1Right; shiftD1Right - shiftB2Right; shiftC2Right; shiftD2Right - - DECQ itr1 - JG sealSSETail192LoopA - - DECQ itr2 - JGE sealSSETail192LoopB - - PADDL ·chacha20Constants<>(SB), A0; PADDL ·chacha20Constants<>(SB), A1; PADDL ·chacha20Constants<>(SB), A2 - PADDL state1Store, B0; PADDL state1Store, B1; PADDL state1Store, B2 - PADDL state2Store, C0; PADDL state2Store, C1; PADDL state2Store, C2 - PADDL ctr0Store, D0; PADDL ctr1Store, D1; PADDL ctr2Store, D2 - - MOVOU (0*16)(inp), T0; MOVOU (1*16)(inp), T1; MOVOU (2*16)(inp), T2; MOVOU (3*16)(inp), T3 - PXOR T0, A0; PXOR T1, B0; PXOR T2, C0; PXOR T3, D0 - MOVOU A0, (0*16)(oup); MOVOU B0, (1*16)(oup); MOVOU C0, (2*16)(oup); MOVOU D0, (3*16)(oup) - MOVOU (4*16)(inp), T0; MOVOU (5*16)(inp), T1; MOVOU (6*16)(inp), T2; MOVOU (7*16)(inp), T3 - PXOR T0, A1; PXOR T1, B1; PXOR T2, C1; PXOR T3, D1 - MOVOU A1, (4*16)(oup); MOVOU B1, (5*16)(oup); MOVOU C1, (6*16)(oup); MOVOU D1, (7*16)(oup) - - MOVO A2, A1 - MOVO B2, B1 - MOVO C2, C1 - MOVO D2, D1 - MOVQ $128, itr1 - LEAQ 128(inp), inp - SUBQ $128, inl - - JMP sealSSE128SealHash - -// ---------------------------------------------------------------------------- -// Special seal optimization for buffers smaller than 129 bytes + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X3 + PXOR X12, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X3 + PXOR X12, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X4 + PXOR X12, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X4 + PXOR X12, X4 + PADDD X5, X2 + PXOR X2, X11 + ROL16(X11, X12) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X5 + PXOR X12, X5 + PADDD X5, X2 + PXOR X2, X11 + ROL8(X11, X12) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X5 + PXOR X12, X5 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc0 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 16(DI), DI + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X3 + PXOR X12, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X3 + PXOR X12, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X4 + PXOR X12, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X4 + PXOR X12, X4 + PADDD X5, X2 + PXOR X2, X11 + ROL16(X11, X12) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X5 + PXOR X12, X5 + PADDD X5, X2 + PXOR X2, X11 + ROL8(X11, X12) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X5 + PXOR X12, X5 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc0 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + DECQ CX + JG sealSSETail192LoopA + DECQ R9 + JGE sealSSETail192LoopB + PADDL ·chacha20Constants<>+0(SB), X0 + PADDL ·chacha20Constants<>+0(SB), X1 + PADDL ·chacha20Constants<>+0(SB), X2 + PADDL 32(BP), X3 + PADDL 32(BP), X4 + PADDL 32(BP), X5 + PADDL 48(BP), X6 + PADDL 48(BP), X7 + PADDL 48(BP), X8 + PADDL 80(BP), X9 + PADDL 96(BP), X10 + PADDL 112(BP), X11 + MOVOU (SI), X12 + MOVOU 16(SI), X13 + MOVOU 32(SI), X14 + MOVOU 48(SI), X15 + PXOR X12, X0 + PXOR X13, X3 + PXOR X14, X6 + PXOR X15, X9 + MOVOU X0, (DI) + MOVOU X3, 16(DI) + MOVOU X6, 32(DI) + MOVOU X9, 48(DI) + MOVOU 64(SI), X12 + MOVOU 80(SI), X13 + MOVOU 96(SI), X14 + MOVOU 112(SI), X15 + PXOR X12, X1 + PXOR X13, X4 + PXOR X14, X7 + PXOR X15, X10 + MOVOU X1, 64(DI) + MOVOU X4, 80(DI) + MOVOU X7, 96(DI) + MOVOU X10, 112(DI) + MOVO X2, X1 + MOVO X5, X4 + MOVO X8, X7 + MOVO X11, X10 + MOVQ $0x00000080, CX + LEAQ 128(SI), SI + SUBQ $0x80, BX + JMP sealSSE128SealHash + sealSSE128: - // For up to 128 bytes of ciphertext and 64 bytes for the poly key, we require to process three blocks - MOVOU ·chacha20Constants<>(SB), A0; MOVOU (1*16)(keyp), B0; MOVOU (2*16)(keyp), C0; MOVOU (3*16)(keyp), D0 - MOVO A0, A1; MOVO B0, B1; MOVO C0, C1; MOVO D0, D1; PADDL ·sseIncMask<>(SB), D1 - MOVO A1, A2; MOVO B1, B2; MOVO C1, C2; MOVO D1, D2; PADDL ·sseIncMask<>(SB), D2 - MOVO B0, T1; MOVO C0, T2; MOVO D1, T3 - MOVQ $10, itr2 + MOVOU ·chacha20Constants<>+0(SB), X0 + MOVOU 16(R8), X3 + MOVOU 32(R8), X6 + MOVOU 48(R8), X9 + MOVO X0, X1 + MOVO X3, X4 + MOVO X6, X7 + MOVO X9, X10 + PADDL ·sseIncMask<>+0(SB), X10 + MOVO X1, X2 + MOVO X4, X5 + MOVO X7, X8 + MOVO X10, X11 + PADDL ·sseIncMask<>+0(SB), X11 + MOVO X3, X13 + MOVO X6, X14 + MOVO X10, X15 + MOVQ $0x0000000a, R9 sealSSE128InnerCipherLoop: - chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0); chachaQR(A2, B2, C2, D2, T0) - shiftB0Left; shiftB1Left; shiftB2Left - shiftC0Left; shiftC1Left; shiftC2Left - shiftD0Left; shiftD1Left; shiftD2Left - chachaQR(A0, B0, C0, D0, T0); chachaQR(A1, B1, C1, D1, T0); chachaQR(A2, B2, C2, D2, T0) - shiftB0Right; shiftB1Right; shiftB2Right - shiftC0Right; shiftC1Right; shiftC2Right - shiftD0Right; shiftD1Right; shiftD2Right - DECQ itr2 - JNE sealSSE128InnerCipherLoop + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X3 + PXOR X12, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X3 + PXOR X12, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X4 + PXOR X12, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X4 + PXOR X12, X4 + PADDD X5, X2 + PXOR X2, X11 + ROL16(X11, X12) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X5 + PXOR X12, X5 + PADDD X5, X2 + PXOR X2, X11 + ROL8(X11, X12) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X5 + PXOR X12, X5 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc0 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X3 + PXOR X12, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X3 + PXOR X12, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X4 + PXOR X12, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X4 + PXOR X12, X4 + PADDD X5, X2 + PXOR X2, X11 + ROL16(X11, X12) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X5 + PXOR X12, X5 + PADDD X5, X2 + PXOR X2, X11 + ROL8(X11, X12) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X5 + PXOR X12, X5 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc0 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + DECQ R9 + JNE sealSSE128InnerCipherLoop // A0|B0 hold the Poly1305 32-byte key, C0,D0 can be discarded - PADDL ·chacha20Constants<>(SB), A0; PADDL ·chacha20Constants<>(SB), A1; PADDL ·chacha20Constants<>(SB), A2 - PADDL T1, B0; PADDL T1, B1; PADDL T1, B2 - PADDL T2, C1; PADDL T2, C2 - PADDL T3, D1; PADDL ·sseIncMask<>(SB), T3; PADDL T3, D2 - PAND ·polyClampMask<>(SB), A0 - MOVOU A0, rStore - MOVOU B0, sStore + PADDL ·chacha20Constants<>+0(SB), X0 + PADDL ·chacha20Constants<>+0(SB), X1 + PADDL ·chacha20Constants<>+0(SB), X2 + PADDL X13, X3 + PADDL X13, X4 + PADDL X13, X5 + PADDL X14, X7 + PADDL X14, X8 + PADDL X15, X10 + PADDL ·sseIncMask<>+0(SB), X15 + PADDL X15, X11 + PAND ·polyClampMask<>+0(SB), X0 + MOVOU X0, (BP) + MOVOU X3, 16(BP) // Hash - MOVQ ad_len+80(FP), itr2 + MOVQ ad_len+80(FP), R9 CALL polyHashADInternal<>(SB) - XORQ itr1, itr1 + XORQ CX, CX sealSSE128SealHash: - // itr1 holds the number of bytes encrypted but not yet hashed - CMPQ itr1, $16 - JB sealSSE128Seal - polyAdd(0(oup)) - polyMul - - SUBQ $16, itr1 - ADDQ $16, oup - - JMP sealSSE128SealHash + CMPQ CX, $0x10 + JB sealSSE128Seal + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + SUBQ $0x10, CX + ADDQ $0x10, DI + JMP sealSSE128SealHash sealSSE128Seal: - CMPQ inl, $16 + CMPQ BX, $0x10 JB sealSSETail - SUBQ $16, inl + SUBQ $0x10, BX // Load for decryption - MOVOU (inp), T0 - PXOR T0, A1 - MOVOU A1, (oup) - LEAQ (1*16)(inp), inp - LEAQ (1*16)(oup), oup + MOVOU (SI), X12 + PXOR X12, X1 + MOVOU X1, (DI) + LEAQ 16(SI), SI + LEAQ 16(DI), DI // Extract for hashing - MOVQ A1, t0 - PSRLDQ $8, A1 - MOVQ A1, t1 - ADDQ t0, acc0; ADCQ t1, acc1; ADCQ $1, acc2 - polyMul + MOVQ X1, R13 + PSRLDQ $0x08, X1 + MOVQ X1, R14 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 // Shift the stream "left" - MOVO B1, A1 - MOVO C1, B1 - MOVO D1, C1 - MOVO A2, D1 - MOVO B2, A2 - MOVO C2, B2 - MOVO D2, C2 + MOVO X4, X1 + MOVO X7, X4 + MOVO X10, X7 + MOVO X2, X10 + MOVO X5, X2 + MOVO X8, X5 + MOVO X11, X8 JMP sealSSE128Seal sealSSETail: - TESTQ inl, inl + TESTQ BX, BX JE sealSSEFinalize // We can only load the PT one byte at a time to avoid read after end of buffer - MOVQ inl, itr2 - SHLQ $4, itr2 - LEAQ ·andMask<>(SB), t0 - MOVQ inl, itr1 - LEAQ -1(inp)(inl*1), inp - XORQ t2, t2 - XORQ t3, t3 + MOVQ BX, R9 + SHLQ $0x04, R9 + LEAQ ·andMask<>+0(SB), R13 + MOVQ BX, CX + LEAQ -1(SI)(BX*1), SI + XORQ R15, R15 + XORQ R8, R8 XORQ AX, AX sealSSETailLoadLoop: - SHLQ $8, t2, t3 - SHLQ $8, t2 - MOVB (inp), AX - XORQ AX, t2 - LEAQ -1(inp), inp - DECQ itr1 + SHLQ $0x08, R15, R8 + SHLQ $0x08, R15 + MOVB (SI), AX + XORQ AX, R15 + LEAQ -1(SI), SI + DECQ CX JNE sealSSETailLoadLoop - MOVQ t2, 0+tmpStore - MOVQ t3, 8+tmpStore - PXOR 0+tmpStore, A1 - MOVOU A1, (oup) - MOVOU -16(t0)(itr2*1), T0 - PAND T0, A1 - MOVQ A1, t0 - PSRLDQ $8, A1 - MOVQ A1, t1 - ADDQ t0, acc0; ADCQ t1, acc1; ADCQ $1, acc2 - polyMul - - ADDQ inl, oup + MOVQ R15, 64(BP) + MOVQ R8, 72(BP) + PXOR 64(BP), X1 + MOVOU X1, (DI) + MOVOU -16(R13)(R9*1), X12 + PAND X12, X1 + MOVQ X1, R13 + PSRLDQ $0x08, X1 + MOVQ X1, R14 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + ADDQ BX, DI sealSSEFinalize: // Hash in the buffer lengths - ADDQ ad_len+80(FP), acc0 - ADCQ src_len+56(FP), acc1 - ADCQ $1, acc2 - polyMul + ADDQ ad_len+80(FP), R10 + ADCQ src_len+56(FP), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 // Final reduce - MOVQ acc0, t0 - MOVQ acc1, t1 - MOVQ acc2, t2 - SUBQ $-5, acc0 - SBBQ $-1, acc1 - SBBQ $3, acc2 - CMOVQCS t0, acc0 - CMOVQCS t1, acc1 - CMOVQCS t2, acc2 + MOVQ R10, R13 + MOVQ R11, R14 + MOVQ R12, R15 + SUBQ $-5, R10 + SBBQ $-1, R11 + SBBQ $0x03, R12 + CMOVQCS R13, R10 + CMOVQCS R14, R11 + CMOVQCS R15, R12 // Add in the "s" part of the key - ADDQ 0+sStore, acc0 - ADCQ 8+sStore, acc1 + ADDQ 16(BP), R10 + ADCQ 24(BP), R11 // Finally store the tag at the end of the message - MOVQ acc0, (0*8)(oup) - MOVQ acc1, (1*8)(oup) + MOVQ R10, (DI) + MOVQ R11, 8(DI) RET -// ---------------------------------------------------------------------------- -// ------------------------- AVX2 Code ---------------------------------------- chacha20Poly1305Seal_AVX2: VZEROUPPER - VMOVDQU ·chacha20Constants<>(SB), AA0 - BYTE $0xc4; BYTE $0x42; BYTE $0x7d; BYTE $0x5a; BYTE $0x70; BYTE $0x10 // broadcasti128 16(r8), ymm14 - BYTE $0xc4; BYTE $0x42; BYTE $0x7d; BYTE $0x5a; BYTE $0x60; BYTE $0x20 // broadcasti128 32(r8), ymm12 - BYTE $0xc4; BYTE $0xc2; BYTE $0x7d; BYTE $0x5a; BYTE $0x60; BYTE $0x30 // broadcasti128 48(r8), ymm4 - VPADDD ·avx2InitMask<>(SB), DD0, DD0 + VMOVDQU ·chacha20Constants<>+0(SB), Y0 + BYTE $0xc4 + BYTE $0x42 + BYTE $0x7d + BYTE $0x5a + BYTE $0x70 + BYTE $0x10 + BYTE $0xc4 + BYTE $0x42 + BYTE $0x7d + BYTE $0x5a + BYTE $0x60 + BYTE $0x20 + BYTE $0xc4 + BYTE $0xc2 + BYTE $0x7d + BYTE $0x5a + BYTE $0x60 + BYTE $0x30 + VPADDD ·avx2InitMask<>+0(SB), Y4, Y4 // Special optimizations, for very short buffers - CMPQ inl, $192 - JBE seal192AVX2 // 33% faster - CMPQ inl, $320 - JBE seal320AVX2 // 17% faster + CMPQ BX, $0x000000c0 + JBE seal192AVX2 + CMPQ BX, $0x00000140 + JBE seal320AVX2 // For the general key prepare the key first - as a byproduct we have 64 bytes of cipher stream - VMOVDQA AA0, AA1; VMOVDQA AA0, AA2; VMOVDQA AA0, AA3 - VMOVDQA BB0, BB1; VMOVDQA BB0, BB2; VMOVDQA BB0, BB3; VMOVDQA BB0, state1StoreAVX2 - VMOVDQA CC0, CC1; VMOVDQA CC0, CC2; VMOVDQA CC0, CC3; VMOVDQA CC0, state2StoreAVX2 - VPADDD ·avx2IncMask<>(SB), DD0, DD1; VMOVDQA DD0, ctr0StoreAVX2 - VPADDD ·avx2IncMask<>(SB), DD1, DD2; VMOVDQA DD1, ctr1StoreAVX2 - VPADDD ·avx2IncMask<>(SB), DD2, DD3; VMOVDQA DD2, ctr2StoreAVX2 - VMOVDQA DD3, ctr3StoreAVX2 - MOVQ $10, itr2 + VMOVDQA Y0, Y5 + VMOVDQA Y0, Y6 + VMOVDQA Y0, Y7 + VMOVDQA Y14, Y9 + VMOVDQA Y14, Y10 + VMOVDQA Y14, Y11 + VMOVDQA Y14, 32(BP) + VMOVDQA Y12, Y13 + VMOVDQA Y12, Y8 + VMOVDQA Y12, Y15 + VMOVDQA Y12, 64(BP) + VPADDD ·avx2IncMask<>+0(SB), Y4, Y1 + VMOVDQA Y4, 96(BP) + VPADDD ·avx2IncMask<>+0(SB), Y1, Y2 + VMOVDQA Y1, 128(BP) + VPADDD ·avx2IncMask<>+0(SB), Y2, Y3 + VMOVDQA Y2, 160(BP) + VMOVDQA Y3, 192(BP) + MOVQ $0x0000000a, R9 sealAVX2IntroLoop: - VMOVDQA CC3, tmpStoreAVX2 - chachaQR_AVX2(AA0, BB0, CC0, DD0, CC3); chachaQR_AVX2(AA1, BB1, CC1, DD1, CC3); chachaQR_AVX2(AA2, BB2, CC2, DD2, CC3) - VMOVDQA tmpStoreAVX2, CC3 - VMOVDQA CC1, tmpStoreAVX2 - chachaQR_AVX2(AA3, BB3, CC3, DD3, CC1) - VMOVDQA tmpStoreAVX2, CC1 - - VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $12, DD0, DD0, DD0 - VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $12, DD1, DD1, DD1 - VPALIGNR $4, BB2, BB2, BB2; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $12, DD2, DD2, DD2 - VPALIGNR $4, BB3, BB3, BB3; VPALIGNR $8, CC3, CC3, CC3; VPALIGNR $12, DD3, DD3, DD3 - - VMOVDQA CC3, tmpStoreAVX2 - chachaQR_AVX2(AA0, BB0, CC0, DD0, CC3); chachaQR_AVX2(AA1, BB1, CC1, DD1, CC3); chachaQR_AVX2(AA2, BB2, CC2, DD2, CC3) - VMOVDQA tmpStoreAVX2, CC3 - VMOVDQA CC1, tmpStoreAVX2 - chachaQR_AVX2(AA3, BB3, CC3, DD3, CC1) - VMOVDQA tmpStoreAVX2, CC1 - - VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $4, DD0, DD0, DD0 - VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $4, DD1, DD1, DD1 - VPALIGNR $12, BB2, BB2, BB2; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $4, DD2, DD2, DD2 - VPALIGNR $12, BB3, BB3, BB3; VPALIGNR $8, CC3, CC3, CC3; VPALIGNR $4, DD3, DD3, DD3 - DECQ itr2 - JNE sealAVX2IntroLoop - - VPADDD ·chacha20Constants<>(SB), AA0, AA0; VPADDD ·chacha20Constants<>(SB), AA1, AA1; VPADDD ·chacha20Constants<>(SB), AA2, AA2; VPADDD ·chacha20Constants<>(SB), AA3, AA3 - VPADDD state1StoreAVX2, BB0, BB0; VPADDD state1StoreAVX2, BB1, BB1; VPADDD state1StoreAVX2, BB2, BB2; VPADDD state1StoreAVX2, BB3, BB3 - VPADDD state2StoreAVX2, CC0, CC0; VPADDD state2StoreAVX2, CC1, CC1; VPADDD state2StoreAVX2, CC2, CC2; VPADDD state2StoreAVX2, CC3, CC3 - VPADDD ctr0StoreAVX2, DD0, DD0; VPADDD ctr1StoreAVX2, DD1, DD1; VPADDD ctr2StoreAVX2, DD2, DD2; VPADDD ctr3StoreAVX2, DD3, DD3 - - VPERM2I128 $0x13, CC0, DD0, CC0 // Stream bytes 96 - 127 - VPERM2I128 $0x02, AA0, BB0, DD0 // The Poly1305 key - VPERM2I128 $0x13, AA0, BB0, AA0 // Stream bytes 64 - 95 + VMOVDQA Y15, 224(BP) + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y15 + VPSRLD $0x14, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y15 + VPSRLD $0x19, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x0c, Y9, Y15 + VPSRLD $0x14, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x07, Y9, Y15 + VPSRLD $0x19, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol16<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x0c, Y10, Y15 + VPSRLD $0x14, Y10, Y10 + VPXOR Y15, Y10, Y10 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol8<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x07, Y10, Y15 + VPSRLD $0x19, Y10, Y10 + VPXOR Y15, Y10, Y10 + VMOVDQA 224(BP), Y15 + VMOVDQA Y13, 224(BP) + VPADDD Y11, Y7, Y7 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol16<>+0(SB), Y3, Y3 + VPADDD Y3, Y15, Y15 + VPXOR Y15, Y11, Y11 + VPSLLD $0x0c, Y11, Y13 + VPSRLD $0x14, Y11, Y11 + VPXOR Y13, Y11, Y11 + VPADDD Y11, Y7, Y7 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol8<>+0(SB), Y3, Y3 + VPADDD Y3, Y15, Y15 + VPXOR Y15, Y11, Y11 + VPSLLD $0x07, Y11, Y13 + VPSRLD $0x19, Y11, Y11 + VPXOR Y13, Y11, Y11 + VMOVDQA 224(BP), Y13 + VPALIGNR $0x04, Y14, Y14, Y14 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x0c, Y4, Y4, Y4 + VPALIGNR $0x04, Y9, Y9, Y9 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x0c, Y1, Y1, Y1 + VPALIGNR $0x04, Y10, Y10, Y10 + VPALIGNR $0x08, Y8, Y8, Y8 + VPALIGNR $0x0c, Y2, Y2, Y2 + VPALIGNR $0x04, Y11, Y11, Y11 + VPALIGNR $0x08, Y15, Y15, Y15 + VPALIGNR $0x0c, Y3, Y3, Y3 + VMOVDQA Y15, 224(BP) + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y15 + VPSRLD $0x14, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y15 + VPSRLD $0x19, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x0c, Y9, Y15 + VPSRLD $0x14, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x07, Y9, Y15 + VPSRLD $0x19, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol16<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x0c, Y10, Y15 + VPSRLD $0x14, Y10, Y10 + VPXOR Y15, Y10, Y10 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol8<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x07, Y10, Y15 + VPSRLD $0x19, Y10, Y10 + VPXOR Y15, Y10, Y10 + VMOVDQA 224(BP), Y15 + VMOVDQA Y13, 224(BP) + VPADDD Y11, Y7, Y7 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol16<>+0(SB), Y3, Y3 + VPADDD Y3, Y15, Y15 + VPXOR Y15, Y11, Y11 + VPSLLD $0x0c, Y11, Y13 + VPSRLD $0x14, Y11, Y11 + VPXOR Y13, Y11, Y11 + VPADDD Y11, Y7, Y7 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol8<>+0(SB), Y3, Y3 + VPADDD Y3, Y15, Y15 + VPXOR Y15, Y11, Y11 + VPSLLD $0x07, Y11, Y13 + VPSRLD $0x19, Y11, Y11 + VPXOR Y13, Y11, Y11 + VMOVDQA 224(BP), Y13 + VPALIGNR $0x0c, Y14, Y14, Y14 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x04, Y4, Y4, Y4 + VPALIGNR $0x0c, Y9, Y9, Y9 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x04, Y1, Y1, Y1 + VPALIGNR $0x0c, Y10, Y10, Y10 + VPALIGNR $0x08, Y8, Y8, Y8 + VPALIGNR $0x04, Y2, Y2, Y2 + VPALIGNR $0x0c, Y11, Y11, Y11 + VPALIGNR $0x08, Y15, Y15, Y15 + VPALIGNR $0x04, Y3, Y3, Y3 + DECQ R9 + JNE sealAVX2IntroLoop + VPADDD ·chacha20Constants<>+0(SB), Y0, Y0 + VPADDD ·chacha20Constants<>+0(SB), Y5, Y5 + VPADDD ·chacha20Constants<>+0(SB), Y6, Y6 + VPADDD ·chacha20Constants<>+0(SB), Y7, Y7 + VPADDD 32(BP), Y14, Y14 + VPADDD 32(BP), Y9, Y9 + VPADDD 32(BP), Y10, Y10 + VPADDD 32(BP), Y11, Y11 + VPADDD 64(BP), Y12, Y12 + VPADDD 64(BP), Y13, Y13 + VPADDD 64(BP), Y8, Y8 + VPADDD 64(BP), Y15, Y15 + VPADDD 96(BP), Y4, Y4 + VPADDD 128(BP), Y1, Y1 + VPADDD 160(BP), Y2, Y2 + VPADDD 192(BP), Y3, Y3 + VPERM2I128 $0x13, Y12, Y4, Y12 + VPERM2I128 $0x02, Y0, Y14, Y4 + VPERM2I128 $0x13, Y0, Y14, Y0 // Clamp and store poly key - VPAND ·polyClampMask<>(SB), DD0, DD0 - VMOVDQA DD0, rsStoreAVX2 + VPAND ·polyClampMask<>+0(SB), Y4, Y4 + VMOVDQA Y4, (BP) // Hash AD - MOVQ ad_len+80(FP), itr2 + MOVQ ad_len+80(FP), R9 CALL polyHashADInternal<>(SB) // Can store at least 320 bytes - VPXOR (0*32)(inp), AA0, AA0 - VPXOR (1*32)(inp), CC0, CC0 - VMOVDQU AA0, (0*32)(oup) - VMOVDQU CC0, (1*32)(oup) - - VPERM2I128 $0x02, AA1, BB1, AA0; VPERM2I128 $0x02, CC1, DD1, BB0; VPERM2I128 $0x13, AA1, BB1, CC0; VPERM2I128 $0x13, CC1, DD1, DD0 - VPXOR (2*32)(inp), AA0, AA0; VPXOR (3*32)(inp), BB0, BB0; VPXOR (4*32)(inp), CC0, CC0; VPXOR (5*32)(inp), DD0, DD0 - VMOVDQU AA0, (2*32)(oup); VMOVDQU BB0, (3*32)(oup); VMOVDQU CC0, (4*32)(oup); VMOVDQU DD0, (5*32)(oup) - VPERM2I128 $0x02, AA2, BB2, AA0; VPERM2I128 $0x02, CC2, DD2, BB0; VPERM2I128 $0x13, AA2, BB2, CC0; VPERM2I128 $0x13, CC2, DD2, DD0 - VPXOR (6*32)(inp), AA0, AA0; VPXOR (7*32)(inp), BB0, BB0; VPXOR (8*32)(inp), CC0, CC0; VPXOR (9*32)(inp), DD0, DD0 - VMOVDQU AA0, (6*32)(oup); VMOVDQU BB0, (7*32)(oup); VMOVDQU CC0, (8*32)(oup); VMOVDQU DD0, (9*32)(oup) - - MOVQ $320, itr1 - SUBQ $320, inl - LEAQ 320(inp), inp - - VPERM2I128 $0x02, AA3, BB3, AA0; VPERM2I128 $0x02, CC3, DD3, BB0; VPERM2I128 $0x13, AA3, BB3, CC0; VPERM2I128 $0x13, CC3, DD3, DD0 - CMPQ inl, $128 + VPXOR (SI), Y0, Y0 + VPXOR 32(SI), Y12, Y12 + VMOVDQU Y0, (DI) + VMOVDQU Y12, 32(DI) + VPERM2I128 $0x02, Y5, Y9, Y0 + VPERM2I128 $0x02, Y13, Y1, Y14 + VPERM2I128 $0x13, Y5, Y9, Y12 + VPERM2I128 $0x13, Y13, Y1, Y4 + VPXOR 64(SI), Y0, Y0 + VPXOR 96(SI), Y14, Y14 + VPXOR 128(SI), Y12, Y12 + VPXOR 160(SI), Y4, Y4 + VMOVDQU Y0, 64(DI) + VMOVDQU Y14, 96(DI) + VMOVDQU Y12, 128(DI) + VMOVDQU Y4, 160(DI) + VPERM2I128 $0x02, Y6, Y10, Y0 + VPERM2I128 $0x02, Y8, Y2, Y14 + VPERM2I128 $0x13, Y6, Y10, Y12 + VPERM2I128 $0x13, Y8, Y2, Y4 + VPXOR 192(SI), Y0, Y0 + VPXOR 224(SI), Y14, Y14 + VPXOR 256(SI), Y12, Y12 + VPXOR 288(SI), Y4, Y4 + VMOVDQU Y0, 192(DI) + VMOVDQU Y14, 224(DI) + VMOVDQU Y12, 256(DI) + VMOVDQU Y4, 288(DI) + MOVQ $0x00000140, CX + SUBQ $0x00000140, BX + LEAQ 320(SI), SI + VPERM2I128 $0x02, Y7, Y11, Y0 + VPERM2I128 $0x02, Y15, Y3, Y14 + VPERM2I128 $0x13, Y7, Y11, Y12 + VPERM2I128 $0x13, Y15, Y3, Y4 + CMPQ BX, $0x80 JBE sealAVX2SealHash - - VPXOR (0*32)(inp), AA0, AA0; VPXOR (1*32)(inp), BB0, BB0; VPXOR (2*32)(inp), CC0, CC0; VPXOR (3*32)(inp), DD0, DD0 - VMOVDQU AA0, (10*32)(oup); VMOVDQU BB0, (11*32)(oup); VMOVDQU CC0, (12*32)(oup); VMOVDQU DD0, (13*32)(oup) - SUBQ $128, inl - LEAQ 128(inp), inp - - MOVQ $8, itr1 - MOVQ $2, itr2 - - CMPQ inl, $128 - JBE sealAVX2Tail128 - CMPQ inl, $256 - JBE sealAVX2Tail256 - CMPQ inl, $384 - JBE sealAVX2Tail384 - CMPQ inl, $512 - JBE sealAVX2Tail512 + VPXOR (SI), Y0, Y0 + VPXOR 32(SI), Y14, Y14 + VPXOR 64(SI), Y12, Y12 + VPXOR 96(SI), Y4, Y4 + VMOVDQU Y0, 320(DI) + VMOVDQU Y14, 352(DI) + VMOVDQU Y12, 384(DI) + VMOVDQU Y4, 416(DI) + SUBQ $0x80, BX + LEAQ 128(SI), SI + MOVQ $0x00000008, CX + MOVQ $0x00000002, R9 + CMPQ BX, $0x80 + JBE sealAVX2Tail128 + CMPQ BX, $0x00000100 + JBE sealAVX2Tail256 + CMPQ BX, $0x00000180 + JBE sealAVX2Tail384 + CMPQ BX, $0x00000200 + JBE sealAVX2Tail512 // We have 448 bytes to hash, but main loop hashes 512 bytes at a time - perform some rounds, before the main loop - VMOVDQA ·chacha20Constants<>(SB), AA0; VMOVDQA AA0, AA1; VMOVDQA AA0, AA2; VMOVDQA AA0, AA3 - VMOVDQA state1StoreAVX2, BB0; VMOVDQA BB0, BB1; VMOVDQA BB0, BB2; VMOVDQA BB0, BB3 - VMOVDQA state2StoreAVX2, CC0; VMOVDQA CC0, CC1; VMOVDQA CC0, CC2; VMOVDQA CC0, CC3 - VMOVDQA ctr3StoreAVX2, DD0 - VPADDD ·avx2IncMask<>(SB), DD0, DD0; VPADDD ·avx2IncMask<>(SB), DD0, DD1; VPADDD ·avx2IncMask<>(SB), DD1, DD2; VPADDD ·avx2IncMask<>(SB), DD2, DD3 - VMOVDQA DD0, ctr0StoreAVX2; VMOVDQA DD1, ctr1StoreAVX2; VMOVDQA DD2, ctr2StoreAVX2; VMOVDQA DD3, ctr3StoreAVX2 - - VMOVDQA CC3, tmpStoreAVX2 - chachaQR_AVX2(AA0, BB0, CC0, DD0, CC3); chachaQR_AVX2(AA1, BB1, CC1, DD1, CC3); chachaQR_AVX2(AA2, BB2, CC2, DD2, CC3) - VMOVDQA tmpStoreAVX2, CC3 - VMOVDQA CC1, tmpStoreAVX2 - chachaQR_AVX2(AA3, BB3, CC3, DD3, CC1) - VMOVDQA tmpStoreAVX2, CC1 - - VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $12, DD0, DD0, DD0 - VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $12, DD1, DD1, DD1 - VPALIGNR $4, BB2, BB2, BB2; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $12, DD2, DD2, DD2 - VPALIGNR $4, BB3, BB3, BB3; VPALIGNR $8, CC3, CC3, CC3; VPALIGNR $12, DD3, DD3, DD3 - - VMOVDQA CC3, tmpStoreAVX2 - chachaQR_AVX2(AA0, BB0, CC0, DD0, CC3); chachaQR_AVX2(AA1, BB1, CC1, DD1, CC3); chachaQR_AVX2(AA2, BB2, CC2, DD2, CC3) - VMOVDQA tmpStoreAVX2, CC3 - VMOVDQA CC1, tmpStoreAVX2 - chachaQR_AVX2(AA3, BB3, CC3, DD3, CC1) - VMOVDQA tmpStoreAVX2, CC1 - - VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $4, DD0, DD0, DD0 - VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $4, DD1, DD1, DD1 - VPALIGNR $12, BB2, BB2, BB2; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $4, DD2, DD2, DD2 - VPALIGNR $12, BB3, BB3, BB3; VPALIGNR $8, CC3, CC3, CC3; VPALIGNR $4, DD3, DD3, DD3 - VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 - VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 - VPSHUFB ·rol16<>(SB), DD0, DD0; VPSHUFB ·rol16<>(SB), DD1, DD1; VPSHUFB ·rol16<>(SB), DD2, DD2; VPSHUFB ·rol16<>(SB), DD3, DD3 - VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 - VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 - VMOVDQA CC3, tmpStoreAVX2 - VPSLLD $12, BB0, CC3; VPSRLD $20, BB0, BB0; VPXOR CC3, BB0, BB0 - VPSLLD $12, BB1, CC3; VPSRLD $20, BB1, BB1; VPXOR CC3, BB1, BB1 - VPSLLD $12, BB2, CC3; VPSRLD $20, BB2, BB2; VPXOR CC3, BB2, BB2 - VPSLLD $12, BB3, CC3; VPSRLD $20, BB3, BB3; VPXOR CC3, BB3, BB3 - VMOVDQA tmpStoreAVX2, CC3 - - SUBQ $16, oup // Adjust the pointer - MOVQ $9, itr1 - JMP sealAVX2InternalLoopStart + VMOVDQA ·chacha20Constants<>+0(SB), Y0 + VMOVDQA Y0, Y5 + VMOVDQA Y0, Y6 + VMOVDQA Y0, Y7 + VMOVDQA 32(BP), Y14 + VMOVDQA Y14, Y9 + VMOVDQA Y14, Y10 + VMOVDQA Y14, Y11 + VMOVDQA 64(BP), Y12 + VMOVDQA Y12, Y13 + VMOVDQA Y12, Y8 + VMOVDQA Y12, Y15 + VMOVDQA 192(BP), Y4 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y4 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y1 + VPADDD ·avx2IncMask<>+0(SB), Y1, Y2 + VPADDD ·avx2IncMask<>+0(SB), Y2, Y3 + VMOVDQA Y4, 96(BP) + VMOVDQA Y1, 128(BP) + VMOVDQA Y2, 160(BP) + VMOVDQA Y3, 192(BP) + VMOVDQA Y15, 224(BP) + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y15 + VPSRLD $0x14, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y15 + VPSRLD $0x19, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x0c, Y9, Y15 + VPSRLD $0x14, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x07, Y9, Y15 + VPSRLD $0x19, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol16<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x0c, Y10, Y15 + VPSRLD $0x14, Y10, Y10 + VPXOR Y15, Y10, Y10 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol8<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x07, Y10, Y15 + VPSRLD $0x19, Y10, Y10 + VPXOR Y15, Y10, Y10 + VMOVDQA 224(BP), Y15 + VMOVDQA Y13, 224(BP) + VPADDD Y11, Y7, Y7 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol16<>+0(SB), Y3, Y3 + VPADDD Y3, Y15, Y15 + VPXOR Y15, Y11, Y11 + VPSLLD $0x0c, Y11, Y13 + VPSRLD $0x14, Y11, Y11 + VPXOR Y13, Y11, Y11 + VPADDD Y11, Y7, Y7 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol8<>+0(SB), Y3, Y3 + VPADDD Y3, Y15, Y15 + VPXOR Y15, Y11, Y11 + VPSLLD $0x07, Y11, Y13 + VPSRLD $0x19, Y11, Y11 + VPXOR Y13, Y11, Y11 + VMOVDQA 224(BP), Y13 + VPALIGNR $0x04, Y14, Y14, Y14 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x0c, Y4, Y4, Y4 + VPALIGNR $0x04, Y9, Y9, Y9 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x0c, Y1, Y1, Y1 + VPALIGNR $0x04, Y10, Y10, Y10 + VPALIGNR $0x08, Y8, Y8, Y8 + VPALIGNR $0x0c, Y2, Y2, Y2 + VPALIGNR $0x04, Y11, Y11, Y11 + VPALIGNR $0x08, Y15, Y15, Y15 + VPALIGNR $0x0c, Y3, Y3, Y3 + VMOVDQA Y15, 224(BP) + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y15 + VPSRLD $0x14, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y15 + VPSRLD $0x19, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x0c, Y9, Y15 + VPSRLD $0x14, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x07, Y9, Y15 + VPSRLD $0x19, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol16<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x0c, Y10, Y15 + VPSRLD $0x14, Y10, Y10 + VPXOR Y15, Y10, Y10 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol8<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x07, Y10, Y15 + VPSRLD $0x19, Y10, Y10 + VPXOR Y15, Y10, Y10 + VMOVDQA 224(BP), Y15 + VMOVDQA Y13, 224(BP) + VPADDD Y11, Y7, Y7 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol16<>+0(SB), Y3, Y3 + VPADDD Y3, Y15, Y15 + VPXOR Y15, Y11, Y11 + VPSLLD $0x0c, Y11, Y13 + VPSRLD $0x14, Y11, Y11 + VPXOR Y13, Y11, Y11 + VPADDD Y11, Y7, Y7 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol8<>+0(SB), Y3, Y3 + VPADDD Y3, Y15, Y15 + VPXOR Y15, Y11, Y11 + VPSLLD $0x07, Y11, Y13 + VPSRLD $0x19, Y11, Y11 + VPXOR Y13, Y11, Y11 + VMOVDQA 224(BP), Y13 + VPALIGNR $0x0c, Y14, Y14, Y14 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x04, Y4, Y4, Y4 + VPALIGNR $0x0c, Y9, Y9, Y9 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x04, Y1, Y1, Y1 + VPALIGNR $0x0c, Y10, Y10, Y10 + VPALIGNR $0x08, Y8, Y8, Y8 + VPALIGNR $0x04, Y2, Y2, Y2 + VPALIGNR $0x0c, Y11, Y11, Y11 + VPALIGNR $0x08, Y15, Y15, Y15 + VPALIGNR $0x04, Y3, Y3, Y3 + VPADDD Y14, Y0, Y0 + VPADDD Y9, Y5, Y5 + VPADDD Y10, Y6, Y6 + VPADDD Y11, Y7, Y7 + VPXOR Y0, Y4, Y4 + VPXOR Y5, Y1, Y1 + VPXOR Y6, Y2, Y2 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y2, Y2 + VPSHUFB ·rol16<>+0(SB), Y3, Y3 + VPADDD Y4, Y12, Y12 + VPADDD Y1, Y13, Y13 + VPADDD Y2, Y8, Y8 + VPADDD Y3, Y15, Y15 + VPXOR Y12, Y14, Y14 + VPXOR Y13, Y9, Y9 + VPXOR Y8, Y10, Y10 + VPXOR Y15, Y11, Y11 + VMOVDQA Y15, 224(BP) + VPSLLD $0x0c, Y14, Y15 + VPSRLD $0x14, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPSLLD $0x0c, Y9, Y15 + VPSRLD $0x14, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPSLLD $0x0c, Y10, Y15 + VPSRLD $0x14, Y10, Y10 + VPXOR Y15, Y10, Y10 + VPSLLD $0x0c, Y11, Y15 + VPSRLD $0x14, Y11, Y11 + VPXOR Y15, Y11, Y11 + VMOVDQA 224(BP), Y15 + SUBQ $0x10, DI + MOVQ $0x00000009, CX + JMP sealAVX2InternalLoopStart sealAVX2MainLoop: - // Load state, increment counter blocks, store the incremented counters - VMOVDQU ·chacha20Constants<>(SB), AA0; VMOVDQA AA0, AA1; VMOVDQA AA0, AA2; VMOVDQA AA0, AA3 - VMOVDQA state1StoreAVX2, BB0; VMOVDQA BB0, BB1; VMOVDQA BB0, BB2; VMOVDQA BB0, BB3 - VMOVDQA state2StoreAVX2, CC0; VMOVDQA CC0, CC1; VMOVDQA CC0, CC2; VMOVDQA CC0, CC3 - VMOVDQA ctr3StoreAVX2, DD0; VPADDD ·avx2IncMask<>(SB), DD0, DD0; VPADDD ·avx2IncMask<>(SB), DD0, DD1; VPADDD ·avx2IncMask<>(SB), DD1, DD2; VPADDD ·avx2IncMask<>(SB), DD2, DD3 - VMOVDQA DD0, ctr0StoreAVX2; VMOVDQA DD1, ctr1StoreAVX2; VMOVDQA DD2, ctr2StoreAVX2; VMOVDQA DD3, ctr3StoreAVX2 - MOVQ $10, itr1 + VMOVDQU ·chacha20Constants<>+0(SB), Y0 + VMOVDQA Y0, Y5 + VMOVDQA Y0, Y6 + VMOVDQA Y0, Y7 + VMOVDQA 32(BP), Y14 + VMOVDQA Y14, Y9 + VMOVDQA Y14, Y10 + VMOVDQA Y14, Y11 + VMOVDQA 64(BP), Y12 + VMOVDQA Y12, Y13 + VMOVDQA Y12, Y8 + VMOVDQA Y12, Y15 + VMOVDQA 192(BP), Y4 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y4 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y1 + VPADDD ·avx2IncMask<>+0(SB), Y1, Y2 + VPADDD ·avx2IncMask<>+0(SB), Y2, Y3 + VMOVDQA Y4, 96(BP) + VMOVDQA Y1, 128(BP) + VMOVDQA Y2, 160(BP) + VMOVDQA Y3, 192(BP) + MOVQ $0x0000000a, CX sealAVX2InternalLoop: - polyAdd(0*8(oup)) - VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 - polyMulStage1_AVX2 - VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 - VPSHUFB ·rol16<>(SB), DD0, DD0; VPSHUFB ·rol16<>(SB), DD1, DD1; VPSHUFB ·rol16<>(SB), DD2, DD2; VPSHUFB ·rol16<>(SB), DD3, DD3 - polyMulStage2_AVX2 - VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 - VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 - polyMulStage3_AVX2 - VMOVDQA CC3, tmpStoreAVX2 - VPSLLD $12, BB0, CC3; VPSRLD $20, BB0, BB0; VPXOR CC3, BB0, BB0 - VPSLLD $12, BB1, CC3; VPSRLD $20, BB1, BB1; VPXOR CC3, BB1, BB1 - VPSLLD $12, BB2, CC3; VPSRLD $20, BB2, BB2; VPXOR CC3, BB2, BB2 - VPSLLD $12, BB3, CC3; VPSRLD $20, BB3, BB3; VPXOR CC3, BB3, BB3 - VMOVDQA tmpStoreAVX2, CC3 - polyMulReduceStage + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + VPADDD Y14, Y0, Y0 + VPADDD Y9, Y5, Y5 + VPADDD Y10, Y6, Y6 + VPADDD Y11, Y7, Y7 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + VPXOR Y0, Y4, Y4 + VPXOR Y5, Y1, Y1 + VPXOR Y6, Y2, Y2 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y2, Y2 + VPSHUFB ·rol16<>+0(SB), Y3, Y3 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + VPADDD Y4, Y12, Y12 + VPADDD Y1, Y13, Y13 + VPADDD Y2, Y8, Y8 + VPADDD Y3, Y15, Y15 + VPXOR Y12, Y14, Y14 + VPXOR Y13, Y9, Y9 + VPXOR Y8, Y10, Y10 + VPXOR Y15, Y11, Y11 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + VMOVDQA Y15, 224(BP) + VPSLLD $0x0c, Y14, Y15 + VPSRLD $0x14, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPSLLD $0x0c, Y9, Y15 + VPSRLD $0x14, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPSLLD $0x0c, Y10, Y15 + VPSRLD $0x14, Y10, Y10 + VPXOR Y15, Y10, Y10 + VPSLLD $0x0c, Y11, Y15 + VPSRLD $0x14, Y11, Y11 + VPXOR Y15, Y11, Y11 + VMOVDQA 224(BP), Y15 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 sealAVX2InternalLoopStart: - VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 - VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 - VPSHUFB ·rol8<>(SB), DD0, DD0; VPSHUFB ·rol8<>(SB), DD1, DD1; VPSHUFB ·rol8<>(SB), DD2, DD2; VPSHUFB ·rol8<>(SB), DD3, DD3 - polyAdd(2*8(oup)) - VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 - polyMulStage1_AVX2 - VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 - VMOVDQA CC3, tmpStoreAVX2 - VPSLLD $7, BB0, CC3; VPSRLD $25, BB0, BB0; VPXOR CC3, BB0, BB0 - VPSLLD $7, BB1, CC3; VPSRLD $25, BB1, BB1; VPXOR CC3, BB1, BB1 - VPSLLD $7, BB2, CC3; VPSRLD $25, BB2, BB2; VPXOR CC3, BB2, BB2 - VPSLLD $7, BB3, CC3; VPSRLD $25, BB3, BB3; VPXOR CC3, BB3, BB3 - VMOVDQA tmpStoreAVX2, CC3 - polyMulStage2_AVX2 - VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $4, BB2, BB2, BB2; VPALIGNR $4, BB3, BB3, BB3 - VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $8, CC3, CC3, CC3 - VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1; VPALIGNR $12, DD2, DD2, DD2; VPALIGNR $12, DD3, DD3, DD3 - VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 - polyMulStage3_AVX2 - VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 - VPSHUFB ·rol16<>(SB), DD0, DD0; VPSHUFB ·rol16<>(SB), DD1, DD1; VPSHUFB ·rol16<>(SB), DD2, DD2; VPSHUFB ·rol16<>(SB), DD3, DD3 - polyMulReduceStage - VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 - VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 - polyAdd(4*8(oup)) - LEAQ (6*8)(oup), oup - VMOVDQA CC3, tmpStoreAVX2 - VPSLLD $12, BB0, CC3; VPSRLD $20, BB0, BB0; VPXOR CC3, BB0, BB0 - VPSLLD $12, BB1, CC3; VPSRLD $20, BB1, BB1; VPXOR CC3, BB1, BB1 - VPSLLD $12, BB2, CC3; VPSRLD $20, BB2, BB2; VPXOR CC3, BB2, BB2 - VPSLLD $12, BB3, CC3; VPSRLD $20, BB3, BB3; VPXOR CC3, BB3, BB3 - VMOVDQA tmpStoreAVX2, CC3 - polyMulStage1_AVX2 - VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 - VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 - polyMulStage2_AVX2 - VPSHUFB ·rol8<>(SB), DD0, DD0; VPSHUFB ·rol8<>(SB), DD1, DD1; VPSHUFB ·rol8<>(SB), DD2, DD2; VPSHUFB ·rol8<>(SB), DD3, DD3 - VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 - polyMulStage3_AVX2 - VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 - VMOVDQA CC3, tmpStoreAVX2 - VPSLLD $7, BB0, CC3; VPSRLD $25, BB0, BB0; VPXOR CC3, BB0, BB0 - VPSLLD $7, BB1, CC3; VPSRLD $25, BB1, BB1; VPXOR CC3, BB1, BB1 - VPSLLD $7, BB2, CC3; VPSRLD $25, BB2, BB2; VPXOR CC3, BB2, BB2 - VPSLLD $7, BB3, CC3; VPSRLD $25, BB3, BB3; VPXOR CC3, BB3, BB3 - VMOVDQA tmpStoreAVX2, CC3 - polyMulReduceStage - VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $12, BB2, BB2, BB2; VPALIGNR $12, BB3, BB3, BB3 - VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $8, CC3, CC3, CC3 - VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1; VPALIGNR $4, DD2, DD2, DD2; VPALIGNR $4, DD3, DD3, DD3 - DECQ itr1 + VPADDD Y14, Y0, Y0 + VPADDD Y9, Y5, Y5 + VPADDD Y10, Y6, Y6 + VPADDD Y11, Y7, Y7 + VPXOR Y0, Y4, Y4 + VPXOR Y5, Y1, Y1 + VPXOR Y6, Y2, Y2 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y2, Y2 + VPSHUFB ·rol8<>+0(SB), Y3, Y3 + ADDQ 16(DI), R10 + ADCQ 24(DI), R11 + ADCQ $0x01, R12 + VPADDD Y4, Y12, Y12 + VPADDD Y1, Y13, Y13 + VPADDD Y2, Y8, Y8 + VPADDD Y3, Y15, Y15 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + VPXOR Y12, Y14, Y14 + VPXOR Y13, Y9, Y9 + VPXOR Y8, Y10, Y10 + VPXOR Y15, Y11, Y11 + VMOVDQA Y15, 224(BP) + VPSLLD $0x07, Y14, Y15 + VPSRLD $0x19, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPSLLD $0x07, Y9, Y15 + VPSRLD $0x19, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPSLLD $0x07, Y10, Y15 + VPSRLD $0x19, Y10, Y10 + VPXOR Y15, Y10, Y10 + VPSLLD $0x07, Y11, Y15 + VPSRLD $0x19, Y11, Y11 + VPXOR Y15, Y11, Y11 + VMOVDQA 224(BP), Y15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + VPALIGNR $0x04, Y14, Y14, Y14 + VPALIGNR $0x04, Y9, Y9, Y9 + VPALIGNR $0x04, Y10, Y10, Y10 + VPALIGNR $0x04, Y11, Y11, Y11 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x08, Y8, Y8, Y8 + VPALIGNR $0x08, Y15, Y15, Y15 + VPALIGNR $0x0c, Y4, Y4, Y4 + VPALIGNR $0x0c, Y1, Y1, Y1 + VPALIGNR $0x0c, Y2, Y2, Y2 + VPALIGNR $0x0c, Y3, Y3, Y3 + VPADDD Y14, Y0, Y0 + VPADDD Y9, Y5, Y5 + VPADDD Y10, Y6, Y6 + VPADDD Y11, Y7, Y7 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + VPXOR Y0, Y4, Y4 + VPXOR Y5, Y1, Y1 + VPXOR Y6, Y2, Y2 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y2, Y2 + VPSHUFB ·rol16<>+0(SB), Y3, Y3 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + VPADDD Y4, Y12, Y12 + VPADDD Y1, Y13, Y13 + VPADDD Y2, Y8, Y8 + VPADDD Y3, Y15, Y15 + VPXOR Y12, Y14, Y14 + VPXOR Y13, Y9, Y9 + VPXOR Y8, Y10, Y10 + VPXOR Y15, Y11, Y11 + ADDQ 32(DI), R10 + ADCQ 40(DI), R11 + ADCQ $0x01, R12 + LEAQ 48(DI), DI + VMOVDQA Y15, 224(BP) + VPSLLD $0x0c, Y14, Y15 + VPSRLD $0x14, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPSLLD $0x0c, Y9, Y15 + VPSRLD $0x14, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPSLLD $0x0c, Y10, Y15 + VPSRLD $0x14, Y10, Y10 + VPXOR Y15, Y10, Y10 + VPSLLD $0x0c, Y11, Y15 + VPSRLD $0x14, Y11, Y11 + VPXOR Y15, Y11, Y11 + VMOVDQA 224(BP), Y15 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + VPADDD Y14, Y0, Y0 + VPADDD Y9, Y5, Y5 + VPADDD Y10, Y6, Y6 + VPADDD Y11, Y7, Y7 + VPXOR Y0, Y4, Y4 + VPXOR Y5, Y1, Y1 + VPXOR Y6, Y2, Y2 + VPXOR Y7, Y3, Y3 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y2, Y2 + VPSHUFB ·rol8<>+0(SB), Y3, Y3 + VPADDD Y4, Y12, Y12 + VPADDD Y1, Y13, Y13 + VPADDD Y2, Y8, Y8 + VPADDD Y3, Y15, Y15 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + VPXOR Y12, Y14, Y14 + VPXOR Y13, Y9, Y9 + VPXOR Y8, Y10, Y10 + VPXOR Y15, Y11, Y11 + VMOVDQA Y15, 224(BP) + VPSLLD $0x07, Y14, Y15 + VPSRLD $0x19, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPSLLD $0x07, Y9, Y15 + VPSRLD $0x19, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPSLLD $0x07, Y10, Y15 + VPSRLD $0x19, Y10, Y10 + VPXOR Y15, Y10, Y10 + VPSLLD $0x07, Y11, Y15 + VPSRLD $0x19, Y11, Y11 + VPXOR Y15, Y11, Y11 + VMOVDQA 224(BP), Y15 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + VPALIGNR $0x0c, Y14, Y14, Y14 + VPALIGNR $0x0c, Y9, Y9, Y9 + VPALIGNR $0x0c, Y10, Y10, Y10 + VPALIGNR $0x0c, Y11, Y11, Y11 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x08, Y8, Y8, Y8 + VPALIGNR $0x08, Y15, Y15, Y15 + VPALIGNR $0x04, Y4, Y4, Y4 + VPALIGNR $0x04, Y1, Y1, Y1 + VPALIGNR $0x04, Y2, Y2, Y2 + VPALIGNR $0x04, Y3, Y3, Y3 + DECQ CX JNE sealAVX2InternalLoop - - VPADDD ·chacha20Constants<>(SB), AA0, AA0; VPADDD ·chacha20Constants<>(SB), AA1, AA1; VPADDD ·chacha20Constants<>(SB), AA2, AA2; VPADDD ·chacha20Constants<>(SB), AA3, AA3 - VPADDD state1StoreAVX2, BB0, BB0; VPADDD state1StoreAVX2, BB1, BB1; VPADDD state1StoreAVX2, BB2, BB2; VPADDD state1StoreAVX2, BB3, BB3 - VPADDD state2StoreAVX2, CC0, CC0; VPADDD state2StoreAVX2, CC1, CC1; VPADDD state2StoreAVX2, CC2, CC2; VPADDD state2StoreAVX2, CC3, CC3 - VPADDD ctr0StoreAVX2, DD0, DD0; VPADDD ctr1StoreAVX2, DD1, DD1; VPADDD ctr2StoreAVX2, DD2, DD2; VPADDD ctr3StoreAVX2, DD3, DD3 - VMOVDQA CC3, tmpStoreAVX2 + VPADDD ·chacha20Constants<>+0(SB), Y0, Y0 + VPADDD ·chacha20Constants<>+0(SB), Y5, Y5 + VPADDD ·chacha20Constants<>+0(SB), Y6, Y6 + VPADDD ·chacha20Constants<>+0(SB), Y7, Y7 + VPADDD 32(BP), Y14, Y14 + VPADDD 32(BP), Y9, Y9 + VPADDD 32(BP), Y10, Y10 + VPADDD 32(BP), Y11, Y11 + VPADDD 64(BP), Y12, Y12 + VPADDD 64(BP), Y13, Y13 + VPADDD 64(BP), Y8, Y8 + VPADDD 64(BP), Y15, Y15 + VPADDD 96(BP), Y4, Y4 + VPADDD 128(BP), Y1, Y1 + VPADDD 160(BP), Y2, Y2 + VPADDD 192(BP), Y3, Y3 + VMOVDQA Y15, 224(BP) // We only hashed 480 of the 512 bytes available - hash the remaining 32 here - polyAdd(0*8(oup)) - polyMulAVX2 - LEAQ (4*8)(oup), oup - VPERM2I128 $0x02, AA0, BB0, CC3; VPERM2I128 $0x13, AA0, BB0, BB0; VPERM2I128 $0x02, CC0, DD0, AA0; VPERM2I128 $0x13, CC0, DD0, CC0 - VPXOR (0*32)(inp), CC3, CC3; VPXOR (1*32)(inp), AA0, AA0; VPXOR (2*32)(inp), BB0, BB0; VPXOR (3*32)(inp), CC0, CC0 - VMOVDQU CC3, (0*32)(oup); VMOVDQU AA0, (1*32)(oup); VMOVDQU BB0, (2*32)(oup); VMOVDQU CC0, (3*32)(oup) - VPERM2I128 $0x02, AA1, BB1, AA0; VPERM2I128 $0x02, CC1, DD1, BB0; VPERM2I128 $0x13, AA1, BB1, CC0; VPERM2I128 $0x13, CC1, DD1, DD0 - VPXOR (4*32)(inp), AA0, AA0; VPXOR (5*32)(inp), BB0, BB0; VPXOR (6*32)(inp), CC0, CC0; VPXOR (7*32)(inp), DD0, DD0 - VMOVDQU AA0, (4*32)(oup); VMOVDQU BB0, (5*32)(oup); VMOVDQU CC0, (6*32)(oup); VMOVDQU DD0, (7*32)(oup) + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 32(DI), DI + VPERM2I128 $0x02, Y0, Y14, Y15 + VPERM2I128 $0x13, Y0, Y14, Y14 + VPERM2I128 $0x02, Y12, Y4, Y0 + VPERM2I128 $0x13, Y12, Y4, Y12 + VPXOR (SI), Y15, Y15 + VPXOR 32(SI), Y0, Y0 + VPXOR 64(SI), Y14, Y14 + VPXOR 96(SI), Y12, Y12 + VMOVDQU Y15, (DI) + VMOVDQU Y0, 32(DI) + VMOVDQU Y14, 64(DI) + VMOVDQU Y12, 96(DI) + VPERM2I128 $0x02, Y5, Y9, Y0 + VPERM2I128 $0x02, Y13, Y1, Y14 + VPERM2I128 $0x13, Y5, Y9, Y12 + VPERM2I128 $0x13, Y13, Y1, Y4 + VPXOR 128(SI), Y0, Y0 + VPXOR 160(SI), Y14, Y14 + VPXOR 192(SI), Y12, Y12 + VPXOR 224(SI), Y4, Y4 + VMOVDQU Y0, 128(DI) + VMOVDQU Y14, 160(DI) + VMOVDQU Y12, 192(DI) + VMOVDQU Y4, 224(DI) // and here - polyAdd(-2*8(oup)) - polyMulAVX2 - VPERM2I128 $0x02, AA2, BB2, AA0; VPERM2I128 $0x02, CC2, DD2, BB0; VPERM2I128 $0x13, AA2, BB2, CC0; VPERM2I128 $0x13, CC2, DD2, DD0 - VPXOR (8*32)(inp), AA0, AA0; VPXOR (9*32)(inp), BB0, BB0; VPXOR (10*32)(inp), CC0, CC0; VPXOR (11*32)(inp), DD0, DD0 - VMOVDQU AA0, (8*32)(oup); VMOVDQU BB0, (9*32)(oup); VMOVDQU CC0, (10*32)(oup); VMOVDQU DD0, (11*32)(oup) - VPERM2I128 $0x02, AA3, BB3, AA0; VPERM2I128 $0x02, tmpStoreAVX2, DD3, BB0; VPERM2I128 $0x13, AA3, BB3, CC0; VPERM2I128 $0x13, tmpStoreAVX2, DD3, DD0 - VPXOR (12*32)(inp), AA0, AA0; VPXOR (13*32)(inp), BB0, BB0; VPXOR (14*32)(inp), CC0, CC0; VPXOR (15*32)(inp), DD0, DD0 - VMOVDQU AA0, (12*32)(oup); VMOVDQU BB0, (13*32)(oup); VMOVDQU CC0, (14*32)(oup); VMOVDQU DD0, (15*32)(oup) - LEAQ (32*16)(inp), inp - SUBQ $(32*16), inl - CMPQ inl, $512 + ADDQ -16(DI), R10 + ADCQ -8(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + VPERM2I128 $0x02, Y6, Y10, Y0 + VPERM2I128 $0x02, Y8, Y2, Y14 + VPERM2I128 $0x13, Y6, Y10, Y12 + VPERM2I128 $0x13, Y8, Y2, Y4 + VPXOR 256(SI), Y0, Y0 + VPXOR 288(SI), Y14, Y14 + VPXOR 320(SI), Y12, Y12 + VPXOR 352(SI), Y4, Y4 + VMOVDQU Y0, 256(DI) + VMOVDQU Y14, 288(DI) + VMOVDQU Y12, 320(DI) + VMOVDQU Y4, 352(DI) + VPERM2I128 $0x02, Y7, Y11, Y0 + VPERM2I128 $0x02, 224(BP), Y3, Y14 + VPERM2I128 $0x13, Y7, Y11, Y12 + VPERM2I128 $0x13, 224(BP), Y3, Y4 + VPXOR 384(SI), Y0, Y0 + VPXOR 416(SI), Y14, Y14 + VPXOR 448(SI), Y12, Y12 + VPXOR 480(SI), Y4, Y4 + VMOVDQU Y0, 384(DI) + VMOVDQU Y14, 416(DI) + VMOVDQU Y12, 448(DI) + VMOVDQU Y4, 480(DI) + LEAQ 512(SI), SI + SUBQ $0x00000200, BX + CMPQ BX, $0x00000200 JG sealAVX2MainLoop // Tail can only hash 480 bytes - polyAdd(0*8(oup)) - polyMulAVX2 - polyAdd(2*8(oup)) - polyMulAVX2 - LEAQ 32(oup), oup - - MOVQ $10, itr1 - MOVQ $0, itr2 - CMPQ inl, $128 - JBE sealAVX2Tail128 - CMPQ inl, $256 - JBE sealAVX2Tail256 - CMPQ inl, $384 - JBE sealAVX2Tail384 - JMP sealAVX2Tail512 - -// ---------------------------------------------------------------------------- -// Special optimization for buffers smaller than 193 bytes + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + ADDQ 16(DI), R10 + ADCQ 24(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 32(DI), DI + MOVQ $0x0000000a, CX + MOVQ $0x00000000, R9 + CMPQ BX, $0x80 + JBE sealAVX2Tail128 + CMPQ BX, $0x00000100 + JBE sealAVX2Tail256 + CMPQ BX, $0x00000180 + JBE sealAVX2Tail384 + JMP sealAVX2Tail512 + seal192AVX2: - // For up to 192 bytes of ciphertext and 64 bytes for the poly key, we process four blocks - VMOVDQA AA0, AA1 - VMOVDQA BB0, BB1 - VMOVDQA CC0, CC1 - VPADDD ·avx2IncMask<>(SB), DD0, DD1 - VMOVDQA AA0, AA2 - VMOVDQA BB0, BB2 - VMOVDQA CC0, CC2 - VMOVDQA DD0, DD2 - VMOVDQA DD1, TT3 - MOVQ $10, itr2 + VMOVDQA Y0, Y5 + VMOVDQA Y14, Y9 + VMOVDQA Y12, Y13 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y1 + VMOVDQA Y0, Y6 + VMOVDQA Y14, Y10 + VMOVDQA Y12, Y8 + VMOVDQA Y4, Y2 + VMOVDQA Y1, Y15 + MOVQ $0x0000000a, R9 sealAVX2192InnerCipherLoop: - chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) - VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1 - VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1 - VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1 - chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) - VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1 - VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1 - VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1 - DECQ itr2 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y3 + VPSRLD $0x14, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y3 + VPSRLD $0x19, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x0c, Y9, Y3 + VPSRLD $0x14, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x07, Y9, Y3 + VPSRLD $0x19, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPALIGNR $0x04, Y14, Y14, Y14 + VPALIGNR $0x04, Y9, Y9, Y9 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x0c, Y4, Y4, Y4 + VPALIGNR $0x0c, Y1, Y1, Y1 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y3 + VPSRLD $0x14, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y3 + VPSRLD $0x19, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x0c, Y9, Y3 + VPSRLD $0x14, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x07, Y9, Y3 + VPSRLD $0x19, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPALIGNR $0x0c, Y14, Y14, Y14 + VPALIGNR $0x0c, Y9, Y9, Y9 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x04, Y4, Y4, Y4 + VPALIGNR $0x04, Y1, Y1, Y1 + DECQ R9 JNE sealAVX2192InnerCipherLoop - VPADDD AA2, AA0, AA0; VPADDD AA2, AA1, AA1 - VPADDD BB2, BB0, BB0; VPADDD BB2, BB1, BB1 - VPADDD CC2, CC0, CC0; VPADDD CC2, CC1, CC1 - VPADDD DD2, DD0, DD0; VPADDD TT3, DD1, DD1 - VPERM2I128 $0x02, AA0, BB0, TT0 + VPADDD Y6, Y0, Y0 + VPADDD Y6, Y5, Y5 + VPADDD Y10, Y14, Y14 + VPADDD Y10, Y9, Y9 + VPADDD Y8, Y12, Y12 + VPADDD Y8, Y13, Y13 + VPADDD Y2, Y4, Y4 + VPADDD Y15, Y1, Y1 + VPERM2I128 $0x02, Y0, Y14, Y3 // Clamp and store poly key - VPAND ·polyClampMask<>(SB), TT0, TT0 - VMOVDQA TT0, rsStoreAVX2 + VPAND ·polyClampMask<>+0(SB), Y3, Y3 + VMOVDQA Y3, (BP) // Stream for up to 192 bytes - VPERM2I128 $0x13, AA0, BB0, AA0 - VPERM2I128 $0x13, CC0, DD0, BB0 - VPERM2I128 $0x02, AA1, BB1, CC0 - VPERM2I128 $0x02, CC1, DD1, DD0 - VPERM2I128 $0x13, AA1, BB1, AA1 - VPERM2I128 $0x13, CC1, DD1, BB1 + VPERM2I128 $0x13, Y0, Y14, Y0 + VPERM2I128 $0x13, Y12, Y4, Y14 + VPERM2I128 $0x02, Y5, Y9, Y12 + VPERM2I128 $0x02, Y13, Y1, Y4 + VPERM2I128 $0x13, Y5, Y9, Y5 + VPERM2I128 $0x13, Y13, Y1, Y9 sealAVX2ShortSeal: // Hash aad - MOVQ ad_len+80(FP), itr2 + MOVQ ad_len+80(FP), R9 CALL polyHashADInternal<>(SB) - XORQ itr1, itr1 + XORQ CX, CX sealAVX2SealHash: // itr1 holds the number of bytes encrypted but not yet hashed - CMPQ itr1, $16 - JB sealAVX2ShortSealLoop - polyAdd(0(oup)) - polyMul - SUBQ $16, itr1 - ADDQ $16, oup - JMP sealAVX2SealHash + CMPQ CX, $0x10 + JB sealAVX2ShortSealLoop + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + SUBQ $0x10, CX + ADDQ $0x10, DI + JMP sealAVX2SealHash sealAVX2ShortSealLoop: - CMPQ inl, $32 + CMPQ BX, $0x20 JB sealAVX2ShortTail32 - SUBQ $32, inl + SUBQ $0x20, BX // Load for encryption - VPXOR (inp), AA0, AA0 - VMOVDQU AA0, (oup) - LEAQ (1*32)(inp), inp + VPXOR (SI), Y0, Y0 + VMOVDQU Y0, (DI) + LEAQ 32(SI), SI // Now can hash - polyAdd(0*8(oup)) - polyMulAVX2 - polyAdd(2*8(oup)) - polyMulAVX2 - LEAQ (1*32)(oup), oup + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + ADDQ 16(DI), R10 + ADCQ 24(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 32(DI), DI // Shift stream left - VMOVDQA BB0, AA0 - VMOVDQA CC0, BB0 - VMOVDQA DD0, CC0 - VMOVDQA AA1, DD0 - VMOVDQA BB1, AA1 - VMOVDQA CC1, BB1 - VMOVDQA DD1, CC1 - VMOVDQA AA2, DD1 - VMOVDQA BB2, AA2 + VMOVDQA Y14, Y0 + VMOVDQA Y12, Y14 + VMOVDQA Y4, Y12 + VMOVDQA Y5, Y4 + VMOVDQA Y9, Y5 + VMOVDQA Y13, Y9 + VMOVDQA Y1, Y13 + VMOVDQA Y6, Y1 + VMOVDQA Y10, Y6 JMP sealAVX2ShortSealLoop sealAVX2ShortTail32: - CMPQ inl, $16 - VMOVDQA A0, A1 + CMPQ BX, $0x10 + VMOVDQA X0, X1 JB sealAVX2ShortDone - - SUBQ $16, inl + SUBQ $0x10, BX // Load for encryption - VPXOR (inp), A0, T0 - VMOVDQU T0, (oup) - LEAQ (1*16)(inp), inp + VPXOR (SI), X0, X12 + VMOVDQU X12, (DI) + LEAQ 16(SI), SI // Hash - polyAdd(0*8(oup)) - polyMulAVX2 - LEAQ (1*16)(oup), oup - VPERM2I128 $0x11, AA0, AA0, AA0 - VMOVDQA A0, A1 + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 16(DI), DI + VPERM2I128 $0x11, Y0, Y0, Y0 + VMOVDQA X0, X1 sealAVX2ShortDone: VZEROUPPER JMP sealSSETail -// ---------------------------------------------------------------------------- -// Special optimization for buffers smaller than 321 bytes seal320AVX2: - // For up to 320 bytes of ciphertext and 64 bytes for the poly key, we process six blocks - VMOVDQA AA0, AA1; VMOVDQA BB0, BB1; VMOVDQA CC0, CC1; VPADDD ·avx2IncMask<>(SB), DD0, DD1 - VMOVDQA AA0, AA2; VMOVDQA BB0, BB2; VMOVDQA CC0, CC2; VPADDD ·avx2IncMask<>(SB), DD1, DD2 - VMOVDQA BB0, TT1; VMOVDQA CC0, TT2; VMOVDQA DD0, TT3 - MOVQ $10, itr2 + VMOVDQA Y0, Y5 + VMOVDQA Y14, Y9 + VMOVDQA Y12, Y13 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y1 + VMOVDQA Y0, Y6 + VMOVDQA Y14, Y10 + VMOVDQA Y12, Y8 + VPADDD ·avx2IncMask<>+0(SB), Y1, Y2 + VMOVDQA Y14, Y7 + VMOVDQA Y12, Y11 + VMOVDQA Y4, Y15 + MOVQ $0x0000000a, R9 sealAVX2320InnerCipherLoop: - chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0); chachaQR_AVX2(AA2, BB2, CC2, DD2, TT0) - VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $4, BB2, BB2, BB2 - VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2 - VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1; VPALIGNR $12, DD2, DD2, DD2 - chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0); chachaQR_AVX2(AA2, BB2, CC2, DD2, TT0) - VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $12, BB2, BB2, BB2 - VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2 - VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1; VPALIGNR $4, DD2, DD2, DD2 - DECQ itr2 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y3 + VPSRLD $0x14, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y3 + VPSRLD $0x19, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x0c, Y9, Y3 + VPSRLD $0x14, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x07, Y9, Y3 + VPSRLD $0x19, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol16<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x0c, Y10, Y3 + VPSRLD $0x14, Y10, Y10 + VPXOR Y3, Y10, Y10 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol8<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x07, Y10, Y3 + VPSRLD $0x19, Y10, Y10 + VPXOR Y3, Y10, Y10 + VPALIGNR $0x04, Y14, Y14, Y14 + VPALIGNR $0x04, Y9, Y9, Y9 + VPALIGNR $0x04, Y10, Y10, Y10 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x08, Y8, Y8, Y8 + VPALIGNR $0x0c, Y4, Y4, Y4 + VPALIGNR $0x0c, Y1, Y1, Y1 + VPALIGNR $0x0c, Y2, Y2, Y2 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y3 + VPSRLD $0x14, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y3 + VPSRLD $0x19, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x0c, Y9, Y3 + VPSRLD $0x14, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x07, Y9, Y3 + VPSRLD $0x19, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol16<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x0c, Y10, Y3 + VPSRLD $0x14, Y10, Y10 + VPXOR Y3, Y10, Y10 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol8<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x07, Y10, Y3 + VPSRLD $0x19, Y10, Y10 + VPXOR Y3, Y10, Y10 + VPALIGNR $0x0c, Y14, Y14, Y14 + VPALIGNR $0x0c, Y9, Y9, Y9 + VPALIGNR $0x0c, Y10, Y10, Y10 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x08, Y8, Y8, Y8 + VPALIGNR $0x04, Y4, Y4, Y4 + VPALIGNR $0x04, Y1, Y1, Y1 + VPALIGNR $0x04, Y2, Y2, Y2 + DECQ R9 JNE sealAVX2320InnerCipherLoop - - VMOVDQA ·chacha20Constants<>(SB), TT0 - VPADDD TT0, AA0, AA0; VPADDD TT0, AA1, AA1; VPADDD TT0, AA2, AA2 - VPADDD TT1, BB0, BB0; VPADDD TT1, BB1, BB1; VPADDD TT1, BB2, BB2 - VPADDD TT2, CC0, CC0; VPADDD TT2, CC1, CC1; VPADDD TT2, CC2, CC2 - VMOVDQA ·avx2IncMask<>(SB), TT0 - VPADDD TT3, DD0, DD0; VPADDD TT0, TT3, TT3 - VPADDD TT3, DD1, DD1; VPADDD TT0, TT3, TT3 - VPADDD TT3, DD2, DD2 + VMOVDQA ·chacha20Constants<>+0(SB), Y3 + VPADDD Y3, Y0, Y0 + VPADDD Y3, Y5, Y5 + VPADDD Y3, Y6, Y6 + VPADDD Y7, Y14, Y14 + VPADDD Y7, Y9, Y9 + VPADDD Y7, Y10, Y10 + VPADDD Y11, Y12, Y12 + VPADDD Y11, Y13, Y13 + VPADDD Y11, Y8, Y8 + VMOVDQA ·avx2IncMask<>+0(SB), Y3 + VPADDD Y15, Y4, Y4 + VPADDD Y3, Y15, Y15 + VPADDD Y15, Y1, Y1 + VPADDD Y3, Y15, Y15 + VPADDD Y15, Y2, Y2 // Clamp and store poly key - VPERM2I128 $0x02, AA0, BB0, TT0 - VPAND ·polyClampMask<>(SB), TT0, TT0 - VMOVDQA TT0, rsStoreAVX2 + VPERM2I128 $0x02, Y0, Y14, Y3 + VPAND ·polyClampMask<>+0(SB), Y3, Y3 + VMOVDQA Y3, (BP) // Stream for up to 320 bytes - VPERM2I128 $0x13, AA0, BB0, AA0 - VPERM2I128 $0x13, CC0, DD0, BB0 - VPERM2I128 $0x02, AA1, BB1, CC0 - VPERM2I128 $0x02, CC1, DD1, DD0 - VPERM2I128 $0x13, AA1, BB1, AA1 - VPERM2I128 $0x13, CC1, DD1, BB1 - VPERM2I128 $0x02, AA2, BB2, CC1 - VPERM2I128 $0x02, CC2, DD2, DD1 - VPERM2I128 $0x13, AA2, BB2, AA2 - VPERM2I128 $0x13, CC2, DD2, BB2 + VPERM2I128 $0x13, Y0, Y14, Y0 + VPERM2I128 $0x13, Y12, Y4, Y14 + VPERM2I128 $0x02, Y5, Y9, Y12 + VPERM2I128 $0x02, Y13, Y1, Y4 + VPERM2I128 $0x13, Y5, Y9, Y5 + VPERM2I128 $0x13, Y13, Y1, Y9 + VPERM2I128 $0x02, Y6, Y10, Y13 + VPERM2I128 $0x02, Y8, Y2, Y1 + VPERM2I128 $0x13, Y6, Y10, Y6 + VPERM2I128 $0x13, Y8, Y2, Y10 JMP sealAVX2ShortSeal -// ---------------------------------------------------------------------------- -// Special optimization for the last 128 bytes of ciphertext sealAVX2Tail128: - // Need to decrypt up to 128 bytes - prepare two blocks - // If we got here after the main loop - there are 512 encrypted bytes waiting to be hashed - // If we got here before the main loop - there are 448 encrpyred bytes waiting to be hashed - VMOVDQA ·chacha20Constants<>(SB), AA0 - VMOVDQA state1StoreAVX2, BB0 - VMOVDQA state2StoreAVX2, CC0 - VMOVDQA ctr3StoreAVX2, DD0 - VPADDD ·avx2IncMask<>(SB), DD0, DD0 - VMOVDQA DD0, DD1 + VMOVDQA ·chacha20Constants<>+0(SB), Y0 + VMOVDQA 32(BP), Y14 + VMOVDQA 64(BP), Y12 + VMOVDQA 192(BP), Y4 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y4 + VMOVDQA Y4, Y1 sealAVX2Tail128LoopA: - polyAdd(0(oup)) - polyMul - LEAQ 16(oup), oup + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 16(DI), DI sealAVX2Tail128LoopB: - chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0) - polyAdd(0(oup)) - polyMul - VPALIGNR $4, BB0, BB0, BB0 - VPALIGNR $8, CC0, CC0, CC0 - VPALIGNR $12, DD0, DD0, DD0 - chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0) - polyAdd(16(oup)) - polyMul - LEAQ 32(oup), oup - VPALIGNR $12, BB0, BB0, BB0 - VPALIGNR $8, CC0, CC0, CC0 - VPALIGNR $4, DD0, DD0, DD0 - DECQ itr1 - JG sealAVX2Tail128LoopA - DECQ itr2 - JGE sealAVX2Tail128LoopB - - VPADDD ·chacha20Constants<>(SB), AA0, AA1 - VPADDD state1StoreAVX2, BB0, BB1 - VPADDD state2StoreAVX2, CC0, CC1 - VPADDD DD1, DD0, DD1 - - VPERM2I128 $0x02, AA1, BB1, AA0 - VPERM2I128 $0x02, CC1, DD1, BB0 - VPERM2I128 $0x13, AA1, BB1, CC0 - VPERM2I128 $0x13, CC1, DD1, DD0 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y3 + VPSRLD $0x14, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y3 + VPSRLD $0x19, Y14, Y14 + VPXOR Y3, Y14, Y14 + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + VPALIGNR $0x04, Y14, Y14, Y14 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x0c, Y4, Y4, Y4 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y3 + VPSRLD $0x14, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y3 + VPSRLD $0x19, Y14, Y14 + VPXOR Y3, Y14, Y14 + ADDQ 16(DI), R10 + ADCQ 24(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 32(DI), DI + VPALIGNR $0x0c, Y14, Y14, Y14 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x04, Y4, Y4, Y4 + DECQ CX + JG sealAVX2Tail128LoopA + DECQ R9 + JGE sealAVX2Tail128LoopB + VPADDD ·chacha20Constants<>+0(SB), Y0, Y5 + VPADDD 32(BP), Y14, Y9 + VPADDD 64(BP), Y12, Y13 + VPADDD Y1, Y4, Y1 + VPERM2I128 $0x02, Y5, Y9, Y0 + VPERM2I128 $0x02, Y13, Y1, Y14 + VPERM2I128 $0x13, Y5, Y9, Y12 + VPERM2I128 $0x13, Y13, Y1, Y4 JMP sealAVX2ShortSealLoop -// ---------------------------------------------------------------------------- -// Special optimization for the last 256 bytes of ciphertext sealAVX2Tail256: - // Need to decrypt up to 256 bytes - prepare two blocks - // If we got here after the main loop - there are 512 encrypted bytes waiting to be hashed - // If we got here before the main loop - there are 448 encrpyred bytes waiting to be hashed - VMOVDQA ·chacha20Constants<>(SB), AA0; VMOVDQA ·chacha20Constants<>(SB), AA1 - VMOVDQA state1StoreAVX2, BB0; VMOVDQA state1StoreAVX2, BB1 - VMOVDQA state2StoreAVX2, CC0; VMOVDQA state2StoreAVX2, CC1 - VMOVDQA ctr3StoreAVX2, DD0 - VPADDD ·avx2IncMask<>(SB), DD0, DD0 - VPADDD ·avx2IncMask<>(SB), DD0, DD1 - VMOVDQA DD0, TT1 - VMOVDQA DD1, TT2 + VMOVDQA ·chacha20Constants<>+0(SB), Y0 + VMOVDQA ·chacha20Constants<>+0(SB), Y5 + VMOVDQA 32(BP), Y14 + VMOVDQA 32(BP), Y9 + VMOVDQA 64(BP), Y12 + VMOVDQA 64(BP), Y13 + VMOVDQA 192(BP), Y4 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y4 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y1 + VMOVDQA Y4, Y7 + VMOVDQA Y1, Y11 sealAVX2Tail256LoopA: - polyAdd(0(oup)) - polyMul - LEAQ 16(oup), oup + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 16(DI), DI sealAVX2Tail256LoopB: - chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) - polyAdd(0(oup)) - polyMul - VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1 - VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1 - VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1 - chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0) - polyAdd(16(oup)) - polyMul - LEAQ 32(oup), oup - VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1 - VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1 - VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1 - DECQ itr1 - JG sealAVX2Tail256LoopA - DECQ itr2 - JGE sealAVX2Tail256LoopB - - VPADDD ·chacha20Constants<>(SB), AA0, AA0; VPADDD ·chacha20Constants<>(SB), AA1, AA1 - VPADDD state1StoreAVX2, BB0, BB0; VPADDD state1StoreAVX2, BB1, BB1 - VPADDD state2StoreAVX2, CC0, CC0; VPADDD state2StoreAVX2, CC1, CC1 - VPADDD TT1, DD0, DD0; VPADDD TT2, DD1, DD1 - VPERM2I128 $0x02, AA0, BB0, TT0 - VPERM2I128 $0x02, CC0, DD0, TT1 - VPERM2I128 $0x13, AA0, BB0, TT2 - VPERM2I128 $0x13, CC0, DD0, TT3 - VPXOR (0*32)(inp), TT0, TT0; VPXOR (1*32)(inp), TT1, TT1; VPXOR (2*32)(inp), TT2, TT2; VPXOR (3*32)(inp), TT3, TT3 - VMOVDQU TT0, (0*32)(oup); VMOVDQU TT1, (1*32)(oup); VMOVDQU TT2, (2*32)(oup); VMOVDQU TT3, (3*32)(oup) - MOVQ $128, itr1 - LEAQ 128(inp), inp - SUBQ $128, inl - VPERM2I128 $0x02, AA1, BB1, AA0 - VPERM2I128 $0x02, CC1, DD1, BB0 - VPERM2I128 $0x13, AA1, BB1, CC0 - VPERM2I128 $0x13, CC1, DD1, DD0 - - JMP sealAVX2SealHash - -// ---------------------------------------------------------------------------- -// Special optimization for the last 384 bytes of ciphertext + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y3 + VPSRLD $0x14, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y3 + VPSRLD $0x19, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x0c, Y9, Y3 + VPSRLD $0x14, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x07, Y9, Y3 + VPSRLD $0x19, Y9, Y9 + VPXOR Y3, Y9, Y9 + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + VPALIGNR $0x04, Y14, Y14, Y14 + VPALIGNR $0x04, Y9, Y9, Y9 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x0c, Y4, Y4, Y4 + VPALIGNR $0x0c, Y1, Y1, Y1 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y3 + VPSRLD $0x14, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y3 + VPSRLD $0x19, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x0c, Y9, Y3 + VPSRLD $0x14, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x07, Y9, Y3 + VPSRLD $0x19, Y9, Y9 + VPXOR Y3, Y9, Y9 + ADDQ 16(DI), R10 + ADCQ 24(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 32(DI), DI + VPALIGNR $0x0c, Y14, Y14, Y14 + VPALIGNR $0x0c, Y9, Y9, Y9 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x04, Y4, Y4, Y4 + VPALIGNR $0x04, Y1, Y1, Y1 + DECQ CX + JG sealAVX2Tail256LoopA + DECQ R9 + JGE sealAVX2Tail256LoopB + VPADDD ·chacha20Constants<>+0(SB), Y0, Y0 + VPADDD ·chacha20Constants<>+0(SB), Y5, Y5 + VPADDD 32(BP), Y14, Y14 + VPADDD 32(BP), Y9, Y9 + VPADDD 64(BP), Y12, Y12 + VPADDD 64(BP), Y13, Y13 + VPADDD Y7, Y4, Y4 + VPADDD Y11, Y1, Y1 + VPERM2I128 $0x02, Y0, Y14, Y3 + VPERM2I128 $0x02, Y12, Y4, Y7 + VPERM2I128 $0x13, Y0, Y14, Y11 + VPERM2I128 $0x13, Y12, Y4, Y15 + VPXOR (SI), Y3, Y3 + VPXOR 32(SI), Y7, Y7 + VPXOR 64(SI), Y11, Y11 + VPXOR 96(SI), Y15, Y15 + VMOVDQU Y3, (DI) + VMOVDQU Y7, 32(DI) + VMOVDQU Y11, 64(DI) + VMOVDQU Y15, 96(DI) + MOVQ $0x00000080, CX + LEAQ 128(SI), SI + SUBQ $0x80, BX + VPERM2I128 $0x02, Y5, Y9, Y0 + VPERM2I128 $0x02, Y13, Y1, Y14 + VPERM2I128 $0x13, Y5, Y9, Y12 + VPERM2I128 $0x13, Y13, Y1, Y4 + JMP sealAVX2SealHash + sealAVX2Tail384: - // Need to decrypt up to 384 bytes - prepare two blocks - // If we got here after the main loop - there are 512 encrypted bytes waiting to be hashed - // If we got here before the main loop - there are 448 encrpyred bytes waiting to be hashed - VMOVDQA ·chacha20Constants<>(SB), AA0; VMOVDQA AA0, AA1; VMOVDQA AA0, AA2 - VMOVDQA state1StoreAVX2, BB0; VMOVDQA BB0, BB1; VMOVDQA BB0, BB2 - VMOVDQA state2StoreAVX2, CC0; VMOVDQA CC0, CC1; VMOVDQA CC0, CC2 - VMOVDQA ctr3StoreAVX2, DD0 - VPADDD ·avx2IncMask<>(SB), DD0, DD0; VPADDD ·avx2IncMask<>(SB), DD0, DD1; VPADDD ·avx2IncMask<>(SB), DD1, DD2 - VMOVDQA DD0, TT1; VMOVDQA DD1, TT2; VMOVDQA DD2, TT3 + VMOVDQA ·chacha20Constants<>+0(SB), Y0 + VMOVDQA Y0, Y5 + VMOVDQA Y0, Y6 + VMOVDQA 32(BP), Y14 + VMOVDQA Y14, Y9 + VMOVDQA Y14, Y10 + VMOVDQA 64(BP), Y12 + VMOVDQA Y12, Y13 + VMOVDQA Y12, Y8 + VMOVDQA 192(BP), Y4 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y4 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y1 + VPADDD ·avx2IncMask<>+0(SB), Y1, Y2 + VMOVDQA Y4, Y7 + VMOVDQA Y1, Y11 + VMOVDQA Y2, Y15 sealAVX2Tail384LoopA: - polyAdd(0(oup)) - polyMul - LEAQ 16(oup), oup + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 16(DI), DI sealAVX2Tail384LoopB: - chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0); chachaQR_AVX2(AA2, BB2, CC2, DD2, TT0) - polyAdd(0(oup)) - polyMul - VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $4, BB2, BB2, BB2 - VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2 - VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1; VPALIGNR $12, DD2, DD2, DD2 - chachaQR_AVX2(AA0, BB0, CC0, DD0, TT0); chachaQR_AVX2(AA1, BB1, CC1, DD1, TT0); chachaQR_AVX2(AA2, BB2, CC2, DD2, TT0) - polyAdd(16(oup)) - polyMul - LEAQ 32(oup), oup - VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $12, BB2, BB2, BB2 - VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2 - VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1; VPALIGNR $4, DD2, DD2, DD2 - DECQ itr1 - JG sealAVX2Tail384LoopA - DECQ itr2 - JGE sealAVX2Tail384LoopB - - VPADDD ·chacha20Constants<>(SB), AA0, AA0; VPADDD ·chacha20Constants<>(SB), AA1, AA1; VPADDD ·chacha20Constants<>(SB), AA2, AA2 - VPADDD state1StoreAVX2, BB0, BB0; VPADDD state1StoreAVX2, BB1, BB1; VPADDD state1StoreAVX2, BB2, BB2 - VPADDD state2StoreAVX2, CC0, CC0; VPADDD state2StoreAVX2, CC1, CC1; VPADDD state2StoreAVX2, CC2, CC2 - VPADDD TT1, DD0, DD0; VPADDD TT2, DD1, DD1; VPADDD TT3, DD2, DD2 - VPERM2I128 $0x02, AA0, BB0, TT0 - VPERM2I128 $0x02, CC0, DD0, TT1 - VPERM2I128 $0x13, AA0, BB0, TT2 - VPERM2I128 $0x13, CC0, DD0, TT3 - VPXOR (0*32)(inp), TT0, TT0; VPXOR (1*32)(inp), TT1, TT1; VPXOR (2*32)(inp), TT2, TT2; VPXOR (3*32)(inp), TT3, TT3 - VMOVDQU TT0, (0*32)(oup); VMOVDQU TT1, (1*32)(oup); VMOVDQU TT2, (2*32)(oup); VMOVDQU TT3, (3*32)(oup) - VPERM2I128 $0x02, AA1, BB1, TT0 - VPERM2I128 $0x02, CC1, DD1, TT1 - VPERM2I128 $0x13, AA1, BB1, TT2 - VPERM2I128 $0x13, CC1, DD1, TT3 - VPXOR (4*32)(inp), TT0, TT0; VPXOR (5*32)(inp), TT1, TT1; VPXOR (6*32)(inp), TT2, TT2; VPXOR (7*32)(inp), TT3, TT3 - VMOVDQU TT0, (4*32)(oup); VMOVDQU TT1, (5*32)(oup); VMOVDQU TT2, (6*32)(oup); VMOVDQU TT3, (7*32)(oup) - MOVQ $256, itr1 - LEAQ 256(inp), inp - SUBQ $256, inl - VPERM2I128 $0x02, AA2, BB2, AA0 - VPERM2I128 $0x02, CC2, DD2, BB0 - VPERM2I128 $0x13, AA2, BB2, CC0 - VPERM2I128 $0x13, CC2, DD2, DD0 - - JMP sealAVX2SealHash - -// ---------------------------------------------------------------------------- -// Special optimization for the last 512 bytes of ciphertext + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y3 + VPSRLD $0x14, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y3 + VPSRLD $0x19, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x0c, Y9, Y3 + VPSRLD $0x14, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x07, Y9, Y3 + VPSRLD $0x19, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol16<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x0c, Y10, Y3 + VPSRLD $0x14, Y10, Y10 + VPXOR Y3, Y10, Y10 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol8<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x07, Y10, Y3 + VPSRLD $0x19, Y10, Y10 + VPXOR Y3, Y10, Y10 + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + VPALIGNR $0x04, Y14, Y14, Y14 + VPALIGNR $0x04, Y9, Y9, Y9 + VPALIGNR $0x04, Y10, Y10, Y10 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x08, Y8, Y8, Y8 + VPALIGNR $0x0c, Y4, Y4, Y4 + VPALIGNR $0x0c, Y1, Y1, Y1 + VPALIGNR $0x0c, Y2, Y2, Y2 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y3 + VPSRLD $0x14, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y3 + VPSRLD $0x19, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x0c, Y9, Y3 + VPSRLD $0x14, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x07, Y9, Y3 + VPSRLD $0x19, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol16<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x0c, Y10, Y3 + VPSRLD $0x14, Y10, Y10 + VPXOR Y3, Y10, Y10 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol8<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x07, Y10, Y3 + VPSRLD $0x19, Y10, Y10 + VPXOR Y3, Y10, Y10 + ADDQ 16(DI), R10 + ADCQ 24(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 32(DI), DI + VPALIGNR $0x0c, Y14, Y14, Y14 + VPALIGNR $0x0c, Y9, Y9, Y9 + VPALIGNR $0x0c, Y10, Y10, Y10 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x08, Y8, Y8, Y8 + VPALIGNR $0x04, Y4, Y4, Y4 + VPALIGNR $0x04, Y1, Y1, Y1 + VPALIGNR $0x04, Y2, Y2, Y2 + DECQ CX + JG sealAVX2Tail384LoopA + DECQ R9 + JGE sealAVX2Tail384LoopB + VPADDD ·chacha20Constants<>+0(SB), Y0, Y0 + VPADDD ·chacha20Constants<>+0(SB), Y5, Y5 + VPADDD ·chacha20Constants<>+0(SB), Y6, Y6 + VPADDD 32(BP), Y14, Y14 + VPADDD 32(BP), Y9, Y9 + VPADDD 32(BP), Y10, Y10 + VPADDD 64(BP), Y12, Y12 + VPADDD 64(BP), Y13, Y13 + VPADDD 64(BP), Y8, Y8 + VPADDD Y7, Y4, Y4 + VPADDD Y11, Y1, Y1 + VPADDD Y15, Y2, Y2 + VPERM2I128 $0x02, Y0, Y14, Y3 + VPERM2I128 $0x02, Y12, Y4, Y7 + VPERM2I128 $0x13, Y0, Y14, Y11 + VPERM2I128 $0x13, Y12, Y4, Y15 + VPXOR (SI), Y3, Y3 + VPXOR 32(SI), Y7, Y7 + VPXOR 64(SI), Y11, Y11 + VPXOR 96(SI), Y15, Y15 + VMOVDQU Y3, (DI) + VMOVDQU Y7, 32(DI) + VMOVDQU Y11, 64(DI) + VMOVDQU Y15, 96(DI) + VPERM2I128 $0x02, Y5, Y9, Y3 + VPERM2I128 $0x02, Y13, Y1, Y7 + VPERM2I128 $0x13, Y5, Y9, Y11 + VPERM2I128 $0x13, Y13, Y1, Y15 + VPXOR 128(SI), Y3, Y3 + VPXOR 160(SI), Y7, Y7 + VPXOR 192(SI), Y11, Y11 + VPXOR 224(SI), Y15, Y15 + VMOVDQU Y3, 128(DI) + VMOVDQU Y7, 160(DI) + VMOVDQU Y11, 192(DI) + VMOVDQU Y15, 224(DI) + MOVQ $0x00000100, CX + LEAQ 256(SI), SI + SUBQ $0x00000100, BX + VPERM2I128 $0x02, Y6, Y10, Y0 + VPERM2I128 $0x02, Y8, Y2, Y14 + VPERM2I128 $0x13, Y6, Y10, Y12 + VPERM2I128 $0x13, Y8, Y2, Y4 + JMP sealAVX2SealHash + sealAVX2Tail512: - // Need to decrypt up to 512 bytes - prepare two blocks - // If we got here after the main loop - there are 512 encrypted bytes waiting to be hashed - // If we got here before the main loop - there are 448 encrpyred bytes waiting to be hashed - VMOVDQA ·chacha20Constants<>(SB), AA0; VMOVDQA AA0, AA1; VMOVDQA AA0, AA2; VMOVDQA AA0, AA3 - VMOVDQA state1StoreAVX2, BB0; VMOVDQA BB0, BB1; VMOVDQA BB0, BB2; VMOVDQA BB0, BB3 - VMOVDQA state2StoreAVX2, CC0; VMOVDQA CC0, CC1; VMOVDQA CC0, CC2; VMOVDQA CC0, CC3 - VMOVDQA ctr3StoreAVX2, DD0 - VPADDD ·avx2IncMask<>(SB), DD0, DD0; VPADDD ·avx2IncMask<>(SB), DD0, DD1; VPADDD ·avx2IncMask<>(SB), DD1, DD2; VPADDD ·avx2IncMask<>(SB), DD2, DD3 - VMOVDQA DD0, ctr0StoreAVX2; VMOVDQA DD1, ctr1StoreAVX2; VMOVDQA DD2, ctr2StoreAVX2; VMOVDQA DD3, ctr3StoreAVX2 + VMOVDQA ·chacha20Constants<>+0(SB), Y0 + VMOVDQA Y0, Y5 + VMOVDQA Y0, Y6 + VMOVDQA Y0, Y7 + VMOVDQA 32(BP), Y14 + VMOVDQA Y14, Y9 + VMOVDQA Y14, Y10 + VMOVDQA Y14, Y11 + VMOVDQA 64(BP), Y12 + VMOVDQA Y12, Y13 + VMOVDQA Y12, Y8 + VMOVDQA Y12, Y15 + VMOVDQA 192(BP), Y4 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y4 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y1 + VPADDD ·avx2IncMask<>+0(SB), Y1, Y2 + VPADDD ·avx2IncMask<>+0(SB), Y2, Y3 + VMOVDQA Y4, 96(BP) + VMOVDQA Y1, 128(BP) + VMOVDQA Y2, 160(BP) + VMOVDQA Y3, 192(BP) sealAVX2Tail512LoopA: - polyAdd(0(oup)) - polyMul - LEAQ 16(oup), oup + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 16(DI), DI sealAVX2Tail512LoopB: - VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 - VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 - VPSHUFB ·rol16<>(SB), DD0, DD0; VPSHUFB ·rol16<>(SB), DD1, DD1; VPSHUFB ·rol16<>(SB), DD2, DD2; VPSHUFB ·rol16<>(SB), DD3, DD3 - VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 - VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 - VMOVDQA CC3, tmpStoreAVX2 - VPSLLD $12, BB0, CC3; VPSRLD $20, BB0, BB0; VPXOR CC3, BB0, BB0 - VPSLLD $12, BB1, CC3; VPSRLD $20, BB1, BB1; VPXOR CC3, BB1, BB1 - VPSLLD $12, BB2, CC3; VPSRLD $20, BB2, BB2; VPXOR CC3, BB2, BB2 - VPSLLD $12, BB3, CC3; VPSRLD $20, BB3, BB3; VPXOR CC3, BB3, BB3 - VMOVDQA tmpStoreAVX2, CC3 - polyAdd(0*8(oup)) - polyMulAVX2 - VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 - VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 - VPSHUFB ·rol8<>(SB), DD0, DD0; VPSHUFB ·rol8<>(SB), DD1, DD1; VPSHUFB ·rol8<>(SB), DD2, DD2; VPSHUFB ·rol8<>(SB), DD3, DD3 - VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 - VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 - VMOVDQA CC3, tmpStoreAVX2 - VPSLLD $7, BB0, CC3; VPSRLD $25, BB0, BB0; VPXOR CC3, BB0, BB0 - VPSLLD $7, BB1, CC3; VPSRLD $25, BB1, BB1; VPXOR CC3, BB1, BB1 - VPSLLD $7, BB2, CC3; VPSRLD $25, BB2, BB2; VPXOR CC3, BB2, BB2 - VPSLLD $7, BB3, CC3; VPSRLD $25, BB3, BB3; VPXOR CC3, BB3, BB3 - VMOVDQA tmpStoreAVX2, CC3 - VPALIGNR $4, BB0, BB0, BB0; VPALIGNR $4, BB1, BB1, BB1; VPALIGNR $4, BB2, BB2, BB2; VPALIGNR $4, BB3, BB3, BB3 - VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $8, CC3, CC3, CC3 - VPALIGNR $12, DD0, DD0, DD0; VPALIGNR $12, DD1, DD1, DD1; VPALIGNR $12, DD2, DD2, DD2; VPALIGNR $12, DD3, DD3, DD3 - VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 - VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 - VPSHUFB ·rol16<>(SB), DD0, DD0; VPSHUFB ·rol16<>(SB), DD1, DD1; VPSHUFB ·rol16<>(SB), DD2, DD2; VPSHUFB ·rol16<>(SB), DD3, DD3 - VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 - VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 - polyAdd(2*8(oup)) - polyMulAVX2 - LEAQ (4*8)(oup), oup - VMOVDQA CC3, tmpStoreAVX2 - VPSLLD $12, BB0, CC3; VPSRLD $20, BB0, BB0; VPXOR CC3, BB0, BB0 - VPSLLD $12, BB1, CC3; VPSRLD $20, BB1, BB1; VPXOR CC3, BB1, BB1 - VPSLLD $12, BB2, CC3; VPSRLD $20, BB2, BB2; VPXOR CC3, BB2, BB2 - VPSLLD $12, BB3, CC3; VPSRLD $20, BB3, BB3; VPXOR CC3, BB3, BB3 - VMOVDQA tmpStoreAVX2, CC3 - VPADDD BB0, AA0, AA0; VPADDD BB1, AA1, AA1; VPADDD BB2, AA2, AA2; VPADDD BB3, AA3, AA3 - VPXOR AA0, DD0, DD0; VPXOR AA1, DD1, DD1; VPXOR AA2, DD2, DD2; VPXOR AA3, DD3, DD3 - VPSHUFB ·rol8<>(SB), DD0, DD0; VPSHUFB ·rol8<>(SB), DD1, DD1; VPSHUFB ·rol8<>(SB), DD2, DD2; VPSHUFB ·rol8<>(SB), DD3, DD3 - VPADDD DD0, CC0, CC0; VPADDD DD1, CC1, CC1; VPADDD DD2, CC2, CC2; VPADDD DD3, CC3, CC3 - VPXOR CC0, BB0, BB0; VPXOR CC1, BB1, BB1; VPXOR CC2, BB2, BB2; VPXOR CC3, BB3, BB3 - VMOVDQA CC3, tmpStoreAVX2 - VPSLLD $7, BB0, CC3; VPSRLD $25, BB0, BB0; VPXOR CC3, BB0, BB0 - VPSLLD $7, BB1, CC3; VPSRLD $25, BB1, BB1; VPXOR CC3, BB1, BB1 - VPSLLD $7, BB2, CC3; VPSRLD $25, BB2, BB2; VPXOR CC3, BB2, BB2 - VPSLLD $7, BB3, CC3; VPSRLD $25, BB3, BB3; VPXOR CC3, BB3, BB3 - VMOVDQA tmpStoreAVX2, CC3 - VPALIGNR $12, BB0, BB0, BB0; VPALIGNR $12, BB1, BB1, BB1; VPALIGNR $12, BB2, BB2, BB2; VPALIGNR $12, BB3, BB3, BB3 - VPALIGNR $8, CC0, CC0, CC0; VPALIGNR $8, CC1, CC1, CC1; VPALIGNR $8, CC2, CC2, CC2; VPALIGNR $8, CC3, CC3, CC3 - VPALIGNR $4, DD0, DD0, DD0; VPALIGNR $4, DD1, DD1, DD1; VPALIGNR $4, DD2, DD2, DD2; VPALIGNR $4, DD3, DD3, DD3 - - DECQ itr1 - JG sealAVX2Tail512LoopA - DECQ itr2 - JGE sealAVX2Tail512LoopB - - VPADDD ·chacha20Constants<>(SB), AA0, AA0; VPADDD ·chacha20Constants<>(SB), AA1, AA1; VPADDD ·chacha20Constants<>(SB), AA2, AA2; VPADDD ·chacha20Constants<>(SB), AA3, AA3 - VPADDD state1StoreAVX2, BB0, BB0; VPADDD state1StoreAVX2, BB1, BB1; VPADDD state1StoreAVX2, BB2, BB2; VPADDD state1StoreAVX2, BB3, BB3 - VPADDD state2StoreAVX2, CC0, CC0; VPADDD state2StoreAVX2, CC1, CC1; VPADDD state2StoreAVX2, CC2, CC2; VPADDD state2StoreAVX2, CC3, CC3 - VPADDD ctr0StoreAVX2, DD0, DD0; VPADDD ctr1StoreAVX2, DD1, DD1; VPADDD ctr2StoreAVX2, DD2, DD2; VPADDD ctr3StoreAVX2, DD3, DD3 - VMOVDQA CC3, tmpStoreAVX2 - VPERM2I128 $0x02, AA0, BB0, CC3 - VPXOR (0*32)(inp), CC3, CC3 - VMOVDQU CC3, (0*32)(oup) - VPERM2I128 $0x02, CC0, DD0, CC3 - VPXOR (1*32)(inp), CC3, CC3 - VMOVDQU CC3, (1*32)(oup) - VPERM2I128 $0x13, AA0, BB0, CC3 - VPXOR (2*32)(inp), CC3, CC3 - VMOVDQU CC3, (2*32)(oup) - VPERM2I128 $0x13, CC0, DD0, CC3 - VPXOR (3*32)(inp), CC3, CC3 - VMOVDQU CC3, (3*32)(oup) - - VPERM2I128 $0x02, AA1, BB1, AA0 - VPERM2I128 $0x02, CC1, DD1, BB0 - VPERM2I128 $0x13, AA1, BB1, CC0 - VPERM2I128 $0x13, CC1, DD1, DD0 - VPXOR (4*32)(inp), AA0, AA0; VPXOR (5*32)(inp), BB0, BB0; VPXOR (6*32)(inp), CC0, CC0; VPXOR (7*32)(inp), DD0, DD0 - VMOVDQU AA0, (4*32)(oup); VMOVDQU BB0, (5*32)(oup); VMOVDQU CC0, (6*32)(oup); VMOVDQU DD0, (7*32)(oup) - - VPERM2I128 $0x02, AA2, BB2, AA0 - VPERM2I128 $0x02, CC2, DD2, BB0 - VPERM2I128 $0x13, AA2, BB2, CC0 - VPERM2I128 $0x13, CC2, DD2, DD0 - VPXOR (8*32)(inp), AA0, AA0; VPXOR (9*32)(inp), BB0, BB0; VPXOR (10*32)(inp), CC0, CC0; VPXOR (11*32)(inp), DD0, DD0 - VMOVDQU AA0, (8*32)(oup); VMOVDQU BB0, (9*32)(oup); VMOVDQU CC0, (10*32)(oup); VMOVDQU DD0, (11*32)(oup) - - MOVQ $384, itr1 - LEAQ 384(inp), inp - SUBQ $384, inl - VPERM2I128 $0x02, AA3, BB3, AA0 - VPERM2I128 $0x02, tmpStoreAVX2, DD3, BB0 - VPERM2I128 $0x13, AA3, BB3, CC0 - VPERM2I128 $0x13, tmpStoreAVX2, DD3, DD0 - - JMP sealAVX2SealHash + VPADDD Y14, Y0, Y0 + VPADDD Y9, Y5, Y5 + VPADDD Y10, Y6, Y6 + VPADDD Y11, Y7, Y7 + VPXOR Y0, Y4, Y4 + VPXOR Y5, Y1, Y1 + VPXOR Y6, Y2, Y2 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y2, Y2 + VPSHUFB ·rol16<>+0(SB), Y3, Y3 + VPADDD Y4, Y12, Y12 + VPADDD Y1, Y13, Y13 + VPADDD Y2, Y8, Y8 + VPADDD Y3, Y15, Y15 + VPXOR Y12, Y14, Y14 + VPXOR Y13, Y9, Y9 + VPXOR Y8, Y10, Y10 + VPXOR Y15, Y11, Y11 + VMOVDQA Y15, 224(BP) + VPSLLD $0x0c, Y14, Y15 + VPSRLD $0x14, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPSLLD $0x0c, Y9, Y15 + VPSRLD $0x14, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPSLLD $0x0c, Y10, Y15 + VPSRLD $0x14, Y10, Y10 + VPXOR Y15, Y10, Y10 + VPSLLD $0x0c, Y11, Y15 + VPSRLD $0x14, Y11, Y11 + VPXOR Y15, Y11, Y11 + VMOVDQA 224(BP), Y15 + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + VPADDD Y14, Y0, Y0 + VPADDD Y9, Y5, Y5 + VPADDD Y10, Y6, Y6 + VPADDD Y11, Y7, Y7 + VPXOR Y0, Y4, Y4 + VPXOR Y5, Y1, Y1 + VPXOR Y6, Y2, Y2 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y2, Y2 + VPSHUFB ·rol8<>+0(SB), Y3, Y3 + VPADDD Y4, Y12, Y12 + VPADDD Y1, Y13, Y13 + VPADDD Y2, Y8, Y8 + VPADDD Y3, Y15, Y15 + VPXOR Y12, Y14, Y14 + VPXOR Y13, Y9, Y9 + VPXOR Y8, Y10, Y10 + VPXOR Y15, Y11, Y11 + VMOVDQA Y15, 224(BP) + VPSLLD $0x07, Y14, Y15 + VPSRLD $0x19, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPSLLD $0x07, Y9, Y15 + VPSRLD $0x19, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPSLLD $0x07, Y10, Y15 + VPSRLD $0x19, Y10, Y10 + VPXOR Y15, Y10, Y10 + VPSLLD $0x07, Y11, Y15 + VPSRLD $0x19, Y11, Y11 + VPXOR Y15, Y11, Y11 + VMOVDQA 224(BP), Y15 + VPALIGNR $0x04, Y14, Y14, Y14 + VPALIGNR $0x04, Y9, Y9, Y9 + VPALIGNR $0x04, Y10, Y10, Y10 + VPALIGNR $0x04, Y11, Y11, Y11 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x08, Y8, Y8, Y8 + VPALIGNR $0x08, Y15, Y15, Y15 + VPALIGNR $0x0c, Y4, Y4, Y4 + VPALIGNR $0x0c, Y1, Y1, Y1 + VPALIGNR $0x0c, Y2, Y2, Y2 + VPALIGNR $0x0c, Y3, Y3, Y3 + VPADDD Y14, Y0, Y0 + VPADDD Y9, Y5, Y5 + VPADDD Y10, Y6, Y6 + VPADDD Y11, Y7, Y7 + VPXOR Y0, Y4, Y4 + VPXOR Y5, Y1, Y1 + VPXOR Y6, Y2, Y2 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y2, Y2 + VPSHUFB ·rol16<>+0(SB), Y3, Y3 + VPADDD Y4, Y12, Y12 + VPADDD Y1, Y13, Y13 + VPADDD Y2, Y8, Y8 + VPADDD Y3, Y15, Y15 + VPXOR Y12, Y14, Y14 + VPXOR Y13, Y9, Y9 + VPXOR Y8, Y10, Y10 + VPXOR Y15, Y11, Y11 + ADDQ 16(DI), R10 + ADCQ 24(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 32(DI), DI + VMOVDQA Y15, 224(BP) + VPSLLD $0x0c, Y14, Y15 + VPSRLD $0x14, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPSLLD $0x0c, Y9, Y15 + VPSRLD $0x14, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPSLLD $0x0c, Y10, Y15 + VPSRLD $0x14, Y10, Y10 + VPXOR Y15, Y10, Y10 + VPSLLD $0x0c, Y11, Y15 + VPSRLD $0x14, Y11, Y11 + VPXOR Y15, Y11, Y11 + VMOVDQA 224(BP), Y15 + VPADDD Y14, Y0, Y0 + VPADDD Y9, Y5, Y5 + VPADDD Y10, Y6, Y6 + VPADDD Y11, Y7, Y7 + VPXOR Y0, Y4, Y4 + VPXOR Y5, Y1, Y1 + VPXOR Y6, Y2, Y2 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y2, Y2 + VPSHUFB ·rol8<>+0(SB), Y3, Y3 + VPADDD Y4, Y12, Y12 + VPADDD Y1, Y13, Y13 + VPADDD Y2, Y8, Y8 + VPADDD Y3, Y15, Y15 + VPXOR Y12, Y14, Y14 + VPXOR Y13, Y9, Y9 + VPXOR Y8, Y10, Y10 + VPXOR Y15, Y11, Y11 + VMOVDQA Y15, 224(BP) + VPSLLD $0x07, Y14, Y15 + VPSRLD $0x19, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPSLLD $0x07, Y9, Y15 + VPSRLD $0x19, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPSLLD $0x07, Y10, Y15 + VPSRLD $0x19, Y10, Y10 + VPXOR Y15, Y10, Y10 + VPSLLD $0x07, Y11, Y15 + VPSRLD $0x19, Y11, Y11 + VPXOR Y15, Y11, Y11 + VMOVDQA 224(BP), Y15 + VPALIGNR $0x0c, Y14, Y14, Y14 + VPALIGNR $0x0c, Y9, Y9, Y9 + VPALIGNR $0x0c, Y10, Y10, Y10 + VPALIGNR $0x0c, Y11, Y11, Y11 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x08, Y8, Y8, Y8 + VPALIGNR $0x08, Y15, Y15, Y15 + VPALIGNR $0x04, Y4, Y4, Y4 + VPALIGNR $0x04, Y1, Y1, Y1 + VPALIGNR $0x04, Y2, Y2, Y2 + VPALIGNR $0x04, Y3, Y3, Y3 + DECQ CX + JG sealAVX2Tail512LoopA + DECQ R9 + JGE sealAVX2Tail512LoopB + VPADDD ·chacha20Constants<>+0(SB), Y0, Y0 + VPADDD ·chacha20Constants<>+0(SB), Y5, Y5 + VPADDD ·chacha20Constants<>+0(SB), Y6, Y6 + VPADDD ·chacha20Constants<>+0(SB), Y7, Y7 + VPADDD 32(BP), Y14, Y14 + VPADDD 32(BP), Y9, Y9 + VPADDD 32(BP), Y10, Y10 + VPADDD 32(BP), Y11, Y11 + VPADDD 64(BP), Y12, Y12 + VPADDD 64(BP), Y13, Y13 + VPADDD 64(BP), Y8, Y8 + VPADDD 64(BP), Y15, Y15 + VPADDD 96(BP), Y4, Y4 + VPADDD 128(BP), Y1, Y1 + VPADDD 160(BP), Y2, Y2 + VPADDD 192(BP), Y3, Y3 + VMOVDQA Y15, 224(BP) + VPERM2I128 $0x02, Y0, Y14, Y15 + VPXOR (SI), Y15, Y15 + VMOVDQU Y15, (DI) + VPERM2I128 $0x02, Y12, Y4, Y15 + VPXOR 32(SI), Y15, Y15 + VMOVDQU Y15, 32(DI) + VPERM2I128 $0x13, Y0, Y14, Y15 + VPXOR 64(SI), Y15, Y15 + VMOVDQU Y15, 64(DI) + VPERM2I128 $0x13, Y12, Y4, Y15 + VPXOR 96(SI), Y15, Y15 + VMOVDQU Y15, 96(DI) + VPERM2I128 $0x02, Y5, Y9, Y0 + VPERM2I128 $0x02, Y13, Y1, Y14 + VPERM2I128 $0x13, Y5, Y9, Y12 + VPERM2I128 $0x13, Y13, Y1, Y4 + VPXOR 128(SI), Y0, Y0 + VPXOR 160(SI), Y14, Y14 + VPXOR 192(SI), Y12, Y12 + VPXOR 224(SI), Y4, Y4 + VMOVDQU Y0, 128(DI) + VMOVDQU Y14, 160(DI) + VMOVDQU Y12, 192(DI) + VMOVDQU Y4, 224(DI) + VPERM2I128 $0x02, Y6, Y10, Y0 + VPERM2I128 $0x02, Y8, Y2, Y14 + VPERM2I128 $0x13, Y6, Y10, Y12 + VPERM2I128 $0x13, Y8, Y2, Y4 + VPXOR 256(SI), Y0, Y0 + VPXOR 288(SI), Y14, Y14 + VPXOR 320(SI), Y12, Y12 + VPXOR 352(SI), Y4, Y4 + VMOVDQU Y0, 256(DI) + VMOVDQU Y14, 288(DI) + VMOVDQU Y12, 320(DI) + VMOVDQU Y4, 352(DI) + MOVQ $0x00000180, CX + LEAQ 384(SI), SI + SUBQ $0x00000180, BX + VPERM2I128 $0x02, Y7, Y11, Y0 + VPERM2I128 $0x02, 224(BP), Y3, Y14 + VPERM2I128 $0x13, Y7, Y11, Y12 + VPERM2I128 $0x13, 224(BP), Y3, Y4 + JMP sealAVX2SealHash diff --git a/vendor/golang.org/x/crypto/hkdf/hkdf.go b/vendor/golang.org/x/crypto/hkdf/hkdf.go index f4ded5fee..3bee66294 100644 --- a/vendor/golang.org/x/crypto/hkdf/hkdf.go +++ b/vendor/golang.org/x/crypto/hkdf/hkdf.go @@ -8,7 +8,7 @@ // HKDF is a cryptographic key derivation function (KDF) with the goal of // expanding limited input keying material into one or more cryptographically // strong secret keys. -package hkdf // import "golang.org/x/crypto/hkdf" +package hkdf import ( "crypto/hmac" diff --git a/vendor/golang.org/x/crypto/internal/poly1305/mac_noasm.go b/vendor/golang.org/x/crypto/internal/poly1305/mac_noasm.go index 333da285b..bd896bdc7 100644 --- a/vendor/golang.org/x/crypto/internal/poly1305/mac_noasm.go +++ b/vendor/golang.org/x/crypto/internal/poly1305/mac_noasm.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build (!amd64 && !ppc64le && !s390x) || !gc || purego +//go:build (!amd64 && !ppc64le && !ppc64 && !s390x) || !gc || purego package poly1305 diff --git a/vendor/golang.org/x/crypto/internal/poly1305/sum_amd64.s b/vendor/golang.org/x/crypto/internal/poly1305/sum_amd64.s index e0d3c6475..133757384 100644 --- a/vendor/golang.org/x/crypto/internal/poly1305/sum_amd64.s +++ b/vendor/golang.org/x/crypto/internal/poly1305/sum_amd64.s @@ -1,108 +1,93 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. +// Code generated by command: go run sum_amd64_asm.go -out ../sum_amd64.s -pkg poly1305. DO NOT EDIT. //go:build gc && !purego -#include "textflag.h" - -#define POLY1305_ADD(msg, h0, h1, h2) \ - ADDQ 0(msg), h0; \ - ADCQ 8(msg), h1; \ - ADCQ $1, h2; \ - LEAQ 16(msg), msg - -#define POLY1305_MUL(h0, h1, h2, r0, r1, t0, t1, t2, t3) \ - MOVQ r0, AX; \ - MULQ h0; \ - MOVQ AX, t0; \ - MOVQ DX, t1; \ - MOVQ r0, AX; \ - MULQ h1; \ - ADDQ AX, t1; \ - ADCQ $0, DX; \ - MOVQ r0, t2; \ - IMULQ h2, t2; \ - ADDQ DX, t2; \ - \ - MOVQ r1, AX; \ - MULQ h0; \ - ADDQ AX, t1; \ - ADCQ $0, DX; \ - MOVQ DX, h0; \ - MOVQ r1, t3; \ - IMULQ h2, t3; \ - MOVQ r1, AX; \ - MULQ h1; \ - ADDQ AX, t2; \ - ADCQ DX, t3; \ - ADDQ h0, t2; \ - ADCQ $0, t3; \ - \ - MOVQ t0, h0; \ - MOVQ t1, h1; \ - MOVQ t2, h2; \ - ANDQ $3, h2; \ - MOVQ t2, t0; \ - ANDQ $0xFFFFFFFFFFFFFFFC, t0; \ - ADDQ t0, h0; \ - ADCQ t3, h1; \ - ADCQ $0, h2; \ - SHRQ $2, t3, t2; \ - SHRQ $2, t3; \ - ADDQ t2, h0; \ - ADCQ t3, h1; \ - ADCQ $0, h2 - -// func update(state *[7]uint64, msg []byte) +// func update(state *macState, msg []byte) TEXT ·update(SB), $0-32 MOVQ state+0(FP), DI MOVQ msg_base+8(FP), SI MOVQ msg_len+16(FP), R15 - - MOVQ 0(DI), R8 // h0 - MOVQ 8(DI), R9 // h1 - MOVQ 16(DI), R10 // h2 - MOVQ 24(DI), R11 // r0 - MOVQ 32(DI), R12 // r1 - - CMPQ R15, $16 + MOVQ (DI), R8 + MOVQ 8(DI), R9 + MOVQ 16(DI), R10 + MOVQ 24(DI), R11 + MOVQ 32(DI), R12 + CMPQ R15, $0x10 JB bytes_between_0_and_15 loop: - POLY1305_ADD(SI, R8, R9, R10) + ADDQ (SI), R8 + ADCQ 8(SI), R9 + ADCQ $0x01, R10 + LEAQ 16(SI), SI multiply: - POLY1305_MUL(R8, R9, R10, R11, R12, BX, CX, R13, R14) - SUBQ $16, R15 - CMPQ R15, $16 - JAE loop + MOVQ R11, AX + MULQ R8 + MOVQ AX, BX + MOVQ DX, CX + MOVQ R11, AX + MULQ R9 + ADDQ AX, CX + ADCQ $0x00, DX + MOVQ R11, R13 + IMULQ R10, R13 + ADDQ DX, R13 + MOVQ R12, AX + MULQ R8 + ADDQ AX, CX + ADCQ $0x00, DX + MOVQ DX, R8 + MOVQ R12, R14 + IMULQ R10, R14 + MOVQ R12, AX + MULQ R9 + ADDQ AX, R13 + ADCQ DX, R14 + ADDQ R8, R13 + ADCQ $0x00, R14 + MOVQ BX, R8 + MOVQ CX, R9 + MOVQ R13, R10 + ANDQ $0x03, R10 + MOVQ R13, BX + ANDQ $-4, BX + ADDQ BX, R8 + ADCQ R14, R9 + ADCQ $0x00, R10 + SHRQ $0x02, R14, R13 + SHRQ $0x02, R14 + ADDQ R13, R8 + ADCQ R14, R9 + ADCQ $0x00, R10 + SUBQ $0x10, R15 + CMPQ R15, $0x10 + JAE loop bytes_between_0_and_15: TESTQ R15, R15 JZ done - MOVQ $1, BX + MOVQ $0x00000001, BX XORQ CX, CX XORQ R13, R13 ADDQ R15, SI flush_buffer: - SHLQ $8, BX, CX - SHLQ $8, BX + SHLQ $0x08, BX, CX + SHLQ $0x08, BX MOVB -1(SI), R13 XORQ R13, BX DECQ SI DECQ R15 JNZ flush_buffer - ADDQ BX, R8 ADCQ CX, R9 - ADCQ $0, R10 - MOVQ $16, R15 + ADCQ $0x00, R10 + MOVQ $0x00000010, R15 JMP multiply done: - MOVQ R8, 0(DI) + MOVQ R8, (DI) MOVQ R9, 8(DI) MOVQ R10, 16(DI) RET diff --git a/vendor/golang.org/x/crypto/internal/poly1305/sum_ppc64le.go b/vendor/golang.org/x/crypto/internal/poly1305/sum_ppc64x.go similarity index 95% rename from vendor/golang.org/x/crypto/internal/poly1305/sum_ppc64le.go rename to vendor/golang.org/x/crypto/internal/poly1305/sum_ppc64x.go index 4aec4874b..1a1679aaa 100644 --- a/vendor/golang.org/x/crypto/internal/poly1305/sum_ppc64le.go +++ b/vendor/golang.org/x/crypto/internal/poly1305/sum_ppc64x.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build gc && !purego +//go:build gc && !purego && (ppc64 || ppc64le) package poly1305 diff --git a/vendor/golang.org/x/crypto/internal/poly1305/sum_ppc64le.s b/vendor/golang.org/x/crypto/internal/poly1305/sum_ppc64x.s similarity index 89% rename from vendor/golang.org/x/crypto/internal/poly1305/sum_ppc64le.s rename to vendor/golang.org/x/crypto/internal/poly1305/sum_ppc64x.s index b3c1699bf..6899a1dab 100644 --- a/vendor/golang.org/x/crypto/internal/poly1305/sum_ppc64le.s +++ b/vendor/golang.org/x/crypto/internal/poly1305/sum_ppc64x.s @@ -2,15 +2,25 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build gc && !purego +//go:build gc && !purego && (ppc64 || ppc64le) #include "textflag.h" // This was ported from the amd64 implementation. +#ifdef GOARCH_ppc64le +#define LE_MOVD MOVD +#define LE_MOVWZ MOVWZ +#define LE_MOVHZ MOVHZ +#else +#define LE_MOVD MOVDBR +#define LE_MOVWZ MOVWBR +#define LE_MOVHZ MOVHBR +#endif + #define POLY1305_ADD(msg, h0, h1, h2, t0, t1, t2) \ - MOVD (msg), t0; \ - MOVD 8(msg), t1; \ + LE_MOVD (msg)( R0), t0; \ + LE_MOVD (msg)(R24), t1; \ MOVD $1, t2; \ ADDC t0, h0, h0; \ ADDE t1, h1, h1; \ @@ -50,10 +60,6 @@ ADDE t3, h1, h1; \ ADDZE h2 -DATA ·poly1305Mask<>+0x00(SB)/8, $0x0FFFFFFC0FFFFFFF -DATA ·poly1305Mask<>+0x08(SB)/8, $0x0FFFFFFC0FFFFFFC -GLOBL ·poly1305Mask<>(SB), RODATA, $16 - // func update(state *[7]uint64, msg []byte) TEXT ·update(SB), $0-32 MOVD state+0(FP), R3 @@ -66,6 +72,8 @@ TEXT ·update(SB), $0-32 MOVD 24(R3), R11 // r0 MOVD 32(R3), R12 // r1 + MOVD $8, R24 + CMP R5, $16 BLT bytes_between_0_and_15 @@ -94,7 +102,7 @@ flush_buffer: // Greater than 8 -- load the rightmost remaining bytes in msg // and put into R17 (h1) - MOVD (R4)(R21), R17 + LE_MOVD (R4)(R21), R17 MOVD $16, R22 // Find the offset to those bytes @@ -118,7 +126,7 @@ just1: BLT less8 // Exactly 8 - MOVD (R4), R16 + LE_MOVD (R4), R16 CMP R17, $0 @@ -133,7 +141,7 @@ less8: MOVD $0, R22 // shift count CMP R5, $4 BLT less4 - MOVWZ (R4), R16 + LE_MOVWZ (R4), R16 ADD $4, R4 ADD $-4, R5 MOVD $32, R22 @@ -141,7 +149,7 @@ less8: less4: CMP R5, $2 BLT less2 - MOVHZ (R4), R21 + LE_MOVHZ (R4), R21 SLD R22, R21, R21 OR R16, R21, R16 ADD $16, R22 diff --git a/vendor/golang.org/x/mod/modfile/read.go b/vendor/golang.org/x/mod/modfile/read.go index 5b5bb5e11..220568259 100644 --- a/vendor/golang.org/x/mod/modfile/read.go +++ b/vendor/golang.org/x/mod/modfile/read.go @@ -225,7 +225,7 @@ func (x *FileSyntax) Cleanup() { if ww == 0 { continue } - if ww == 1 { + if ww == 1 && len(stmt.RParen.Comments.Before) == 0 { // Collapse block into single line. line := &Line{ Comments: Comments{ diff --git a/vendor/golang.org/x/mod/modfile/rule.go b/vendor/golang.org/x/mod/modfile/rule.go index 35fd1f534..66dcaf980 100644 --- a/vendor/golang.org/x/mod/modfile/rule.go +++ b/vendor/golang.org/x/mod/modfile/rule.go @@ -38,6 +38,7 @@ type File struct { Module *Module Go *Go Toolchain *Toolchain + Godebug []*Godebug Require []*Require Exclude []*Exclude Replace []*Replace @@ -65,6 +66,13 @@ type Toolchain struct { Syntax *Line } +// A Godebug is a single godebug key=value statement. +type Godebug struct { + Key string + Value string + Syntax *Line +} + // An Exclude is a single exclude statement. type Exclude struct { Mod module.Version @@ -289,7 +297,7 @@ func parseToFile(file string, data []byte, fix VersionFixer, strict bool) (parse }) } continue - case "module", "require", "exclude", "replace", "retract": + case "module", "godebug", "require", "exclude", "replace", "retract": for _, l := range x.Line { f.add(&errs, x, l, x.Token[0], l.Token, fix, strict) } @@ -308,6 +316,9 @@ var laxGoVersionRE = lazyregexp.New(`^v?(([1-9][0-9]*)\.(0|[1-9][0-9]*))([^0-9]. // Toolchains must be named beginning with `go1`, // like "go1.20.3" or "go1.20.3-gccgo". As a special case, "default" is also permitted. +// Note that this regexp is a much looser condition than go/version.IsValid, +// for forward compatibility. +// (This code has to be work to identify new toolchains even if we tweak the syntax in the future.) var ToolchainRE = lazyregexp.New(`^default$|^go1($|\.)`) func (f *File) add(errs *ErrorList, block *LineBlock, line *Line, verb string, args []string, fix VersionFixer, strict bool) { @@ -383,8 +394,8 @@ func (f *File) add(errs *ErrorList, block *LineBlock, line *Line, verb string, a if len(args) != 1 { errorf("toolchain directive expects exactly one argument") return - } else if strict && !ToolchainRE.MatchString(args[0]) { - errorf("invalid toolchain version '%s': must match format go1.23.0 or local", args[0]) + } else if !ToolchainRE.MatchString(args[0]) { + errorf("invalid toolchain version '%s': must match format go1.23.0 or default", args[0]) return } f.Toolchain = &Toolchain{Syntax: line} @@ -411,6 +422,22 @@ func (f *File) add(errs *ErrorList, block *LineBlock, line *Line, verb string, a } f.Module.Mod = module.Version{Path: s} + case "godebug": + if len(args) != 1 || strings.ContainsAny(args[0], "\"`',") { + errorf("usage: godebug key=value") + return + } + key, value, ok := strings.Cut(args[0], "=") + if !ok { + errorf("usage: godebug key=value") + return + } + f.Godebug = append(f.Godebug, &Godebug{ + Key: key, + Value: value, + Syntax: line, + }) + case "require", "exclude": if len(args) != 2 { errorf("usage: %s module/path v1.2.3", verb) @@ -630,7 +657,7 @@ func (f *WorkFile) add(errs *ErrorList, line *Line, verb string, args []string, errorf("go directive expects exactly one argument") return } else if !GoVersionRE.MatchString(args[0]) { - errorf("invalid go version '%s': must match format 1.23", args[0]) + errorf("invalid go version '%s': must match format 1.23.0", args[0]) return } @@ -646,13 +673,29 @@ func (f *WorkFile) add(errs *ErrorList, line *Line, verb string, args []string, errorf("toolchain directive expects exactly one argument") return } else if !ToolchainRE.MatchString(args[0]) { - errorf("invalid toolchain version '%s': must match format go1.23 or local", args[0]) + errorf("invalid toolchain version '%s': must match format go1.23.0 or default", args[0]) return } f.Toolchain = &Toolchain{Syntax: line} f.Toolchain.Name = args[0] + case "godebug": + if len(args) != 1 || strings.ContainsAny(args[0], "\"`',") { + errorf("usage: godebug key=value") + return + } + key, value, ok := strings.Cut(args[0], "=") + if !ok { + errorf("usage: godebug key=value") + return + } + f.Godebug = append(f.Godebug, &Godebug{ + Key: key, + Value: value, + Syntax: line, + }) + case "use": if len(args) != 1 { errorf("usage: %s local/dir", verb) @@ -928,6 +971,15 @@ func (f *File) Format() ([]byte, error) { // Cleanup cleans out all the cleared entries. func (f *File) Cleanup() { w := 0 + for _, g := range f.Godebug { + if g.Key != "" { + f.Godebug[w] = g + w++ + } + } + f.Godebug = f.Godebug[:w] + + w = 0 for _, r := range f.Require { if r.Mod.Path != "" { f.Require[w] = r @@ -974,6 +1026,8 @@ func (f *File) AddGoStmt(version string) error { var hint Expr if f.Module != nil && f.Module.Syntax != nil { hint = f.Module.Syntax + } else if f.Syntax == nil { + f.Syntax = new(FileSyntax) } f.Go = &Go{ Version: version, @@ -1024,6 +1078,45 @@ func (f *File) AddToolchainStmt(name string) error { return nil } +// AddGodebug sets the first godebug line for key to value, +// preserving any existing comments for that line and removing all +// other godebug lines for key. +// +// If no line currently exists for key, AddGodebug adds a new line +// at the end of the last godebug block. +func (f *File) AddGodebug(key, value string) error { + need := true + for _, g := range f.Godebug { + if g.Key == key { + if need { + g.Value = value + f.Syntax.updateLine(g.Syntax, "godebug", key+"="+value) + need = false + } else { + g.Syntax.markRemoved() + *g = Godebug{} + } + } + } + + if need { + f.addNewGodebug(key, value) + } + return nil +} + +// addNewGodebug adds a new godebug key=value line at the end +// of the last godebug block, regardless of any existing godebug lines for key. +func (f *File) addNewGodebug(key, value string) { + line := f.Syntax.addLine(nil, "godebug", key+"="+value) + g := &Godebug{ + Key: key, + Value: value, + Syntax: line, + } + f.Godebug = append(f.Godebug, g) +} + // AddRequire sets the first require line for path to version vers, // preserving any existing comments for that line and removing all // other lines for path. @@ -1331,6 +1424,16 @@ func (f *File) SetRequireSeparateIndirect(req []*Require) { f.SortBlocks() } +func (f *File) DropGodebug(key string) error { + for _, g := range f.Godebug { + if g.Key == key { + g.Syntax.markRemoved() + *g = Godebug{} + } + } + return nil +} + func (f *File) DropRequire(path string) error { for _, r := range f.Require { if r.Mod.Path == path { diff --git a/vendor/golang.org/x/mod/modfile/work.go b/vendor/golang.org/x/mod/modfile/work.go index d7b99376e..8f54897cf 100644 --- a/vendor/golang.org/x/mod/modfile/work.go +++ b/vendor/golang.org/x/mod/modfile/work.go @@ -14,6 +14,7 @@ import ( type WorkFile struct { Go *Go Toolchain *Toolchain + Godebug []*Godebug Use []*Use Replace []*Replace @@ -68,7 +69,7 @@ func ParseWork(file string, data []byte, fix VersionFixer) (*WorkFile, error) { Err: fmt.Errorf("unknown block type: %s", strings.Join(x.Token, " ")), }) continue - case "use", "replace": + case "godebug", "use", "replace": for _, l := range x.Line { f.add(&errs, l, x.Token[0], l.Token, fix) } @@ -184,6 +185,55 @@ func (f *WorkFile) DropToolchainStmt() { } } +// AddGodebug sets the first godebug line for key to value, +// preserving any existing comments for that line and removing all +// other godebug lines for key. +// +// If no line currently exists for key, AddGodebug adds a new line +// at the end of the last godebug block. +func (f *WorkFile) AddGodebug(key, value string) error { + need := true + for _, g := range f.Godebug { + if g.Key == key { + if need { + g.Value = value + f.Syntax.updateLine(g.Syntax, "godebug", key+"="+value) + need = false + } else { + g.Syntax.markRemoved() + *g = Godebug{} + } + } + } + + if need { + f.addNewGodebug(key, value) + } + return nil +} + +// addNewGodebug adds a new godebug key=value line at the end +// of the last godebug block, regardless of any existing godebug lines for key. +func (f *WorkFile) addNewGodebug(key, value string) { + line := f.Syntax.addLine(nil, "godebug", key+"="+value) + g := &Godebug{ + Key: key, + Value: value, + Syntax: line, + } + f.Godebug = append(f.Godebug, g) +} + +func (f *WorkFile) DropGodebug(key string) error { + for _, g := range f.Godebug { + if g.Key == key { + g.Syntax.markRemoved() + *g = Godebug{} + } + } + return nil +} + func (f *WorkFile) AddUse(diskPath, modulePath string) error { need := true for _, d := range f.Use { diff --git a/vendor/golang.org/x/mod/module/module.go b/vendor/golang.org/x/mod/module/module.go index 2a364b229..cac1a899e 100644 --- a/vendor/golang.org/x/mod/module/module.go +++ b/vendor/golang.org/x/mod/module/module.go @@ -506,6 +506,7 @@ var badWindowsNames = []string{ "PRN", "AUX", "NUL", + "COM0", "COM1", "COM2", "COM3", @@ -515,6 +516,7 @@ var badWindowsNames = []string{ "COM7", "COM8", "COM9", + "LPT0", "LPT1", "LPT2", "LPT3", diff --git a/vendor/golang.org/x/net/LICENSE b/vendor/golang.org/x/net/LICENSE index 6a66aea5e..2a7cf70da 100644 --- a/vendor/golang.org/x/net/LICENSE +++ b/vendor/golang.org/x/net/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2009 The Go Authors. All rights reserved. +Copyright 2009 The Go Authors. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are @@ -10,7 +10,7 @@ notice, this list of conditions and the following disclaimer. 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 + * Neither the name of Google LLC nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. diff --git a/vendor/golang.org/x/net/html/doc.go b/vendor/golang.org/x/net/html/doc.go index 2466ae3d9..885c4c593 100644 --- a/vendor/golang.org/x/net/html/doc.go +++ b/vendor/golang.org/x/net/html/doc.go @@ -78,16 +78,11 @@ example, to process each anchor node in depth-first order: if err != nil { // ... } - var f func(*html.Node) - f = func(n *html.Node) { + for n := range doc.Descendants() { if n.Type == html.ElementNode && n.Data == "a" { // Do something with n... } - for c := n.FirstChild; c != nil; c = c.NextSibling { - f(c) - } } - f(doc) The relevant specifications include: https://html.spec.whatwg.org/multipage/syntax.html and @@ -104,7 +99,7 @@ tokenization, and tokenization and tree construction stages of the WHATWG HTML parsing specification respectively. While the tokenizer parses and normalizes individual HTML tokens, only the parser constructs the DOM tree from the tokenized HTML, as described in the tree construction stage of the -specification, dynamically modifying or extending the docuemnt's DOM tree. +specification, dynamically modifying or extending the document's DOM tree. If your use case requires semantically well-formed HTML documents, as defined by the WHATWG specification, the parser should be used rather than the tokenizer. diff --git a/vendor/golang.org/x/net/html/iter.go b/vendor/golang.org/x/net/html/iter.go new file mode 100644 index 000000000..54be8fd30 --- /dev/null +++ b/vendor/golang.org/x/net/html/iter.go @@ -0,0 +1,56 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build go1.23 + +package html + +import "iter" + +// Ancestors returns an iterator over the ancestors of n, starting with n.Parent. +// +// Mutating a Node or its parents while iterating may have unexpected results. +func (n *Node) Ancestors() iter.Seq[*Node] { + _ = n.Parent // eager nil check + + return func(yield func(*Node) bool) { + for p := n.Parent; p != nil && yield(p); p = p.Parent { + } + } +} + +// ChildNodes returns an iterator over the immediate children of n, +// starting with n.FirstChild. +// +// Mutating a Node or its children while iterating may have unexpected results. +func (n *Node) ChildNodes() iter.Seq[*Node] { + _ = n.FirstChild // eager nil check + + return func(yield func(*Node) bool) { + for c := n.FirstChild; c != nil && yield(c); c = c.NextSibling { + } + } + +} + +// Descendants returns an iterator over all nodes recursively beneath +// n, excluding n itself. Nodes are visited in depth-first preorder. +// +// Mutating a Node or its descendants while iterating may have unexpected results. +func (n *Node) Descendants() iter.Seq[*Node] { + _ = n.FirstChild // eager nil check + + return func(yield func(*Node) bool) { + n.descendants(yield) + } +} + +func (n *Node) descendants(yield func(*Node) bool) bool { + for c := range n.ChildNodes() { + if !yield(c) || !c.descendants(yield) { + return false + } + } + return true +} diff --git a/vendor/golang.org/x/net/html/node.go b/vendor/golang.org/x/net/html/node.go index 1350eef22..77741a195 100644 --- a/vendor/golang.org/x/net/html/node.go +++ b/vendor/golang.org/x/net/html/node.go @@ -38,6 +38,10 @@ var scopeMarker = Node{Type: scopeMarkerNode} // that it looks like "a maxFrameSize { + conf.MaxReadFrameSize = maxFrameSize + } + + if h2.t1 != nil { + fillNetHTTPTransportConfig(&conf, h2.t1) + } + setConfigDefaults(&conf, false) + return conf +} + +func setDefault[T ~int | ~int32 | ~uint32 | ~int64](v *T, minval, maxval, defval T) { + if *v < minval || *v > maxval { + *v = defval + } +} + +func setConfigDefaults(conf *http2Config, server bool) { + setDefault(&conf.MaxConcurrentStreams, 1, math.MaxUint32, defaultMaxStreams) + setDefault(&conf.MaxEncoderHeaderTableSize, 1, math.MaxUint32, initialHeaderTableSize) + setDefault(&conf.MaxDecoderHeaderTableSize, 1, math.MaxUint32, initialHeaderTableSize) + if server { + setDefault(&conf.MaxUploadBufferPerConnection, initialWindowSize, math.MaxInt32, 1<<20) + } else { + setDefault(&conf.MaxUploadBufferPerConnection, initialWindowSize, math.MaxInt32, transportDefaultConnFlow) + } + if server { + setDefault(&conf.MaxUploadBufferPerStream, 1, math.MaxInt32, 1<<20) + } else { + setDefault(&conf.MaxUploadBufferPerStream, 1, math.MaxInt32, transportDefaultStreamFlow) + } + setDefault(&conf.MaxReadFrameSize, minMaxFrameSize, maxFrameSize, defaultMaxReadFrameSize) + setDefault(&conf.PingTimeout, 1, math.MaxInt64, 15*time.Second) +} + +// adjustHTTP1MaxHeaderSize converts a limit in bytes on the size of an HTTP/1 header +// to an HTTP/2 MAX_HEADER_LIST_SIZE value. +func adjustHTTP1MaxHeaderSize(n int64) int64 { + // http2's count is in a slightly different unit and includes 32 bytes per pair. + // So, take the net/http.Server value and pad it up a bit, assuming 10 headers. + const perFieldOverhead = 32 // per http2 spec + const typicalHeaders = 10 // conservative + return n + typicalHeaders*perFieldOverhead +} diff --git a/vendor/golang.org/x/net/http2/config_go124.go b/vendor/golang.org/x/net/http2/config_go124.go new file mode 100644 index 000000000..e3784123c --- /dev/null +++ b/vendor/golang.org/x/net/http2/config_go124.go @@ -0,0 +1,61 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build go1.24 + +package http2 + +import "net/http" + +// fillNetHTTPServerConfig sets fields in conf from srv.HTTP2. +func fillNetHTTPServerConfig(conf *http2Config, srv *http.Server) { + fillNetHTTPConfig(conf, srv.HTTP2) +} + +// fillNetHTTPServerConfig sets fields in conf from tr.HTTP2. +func fillNetHTTPTransportConfig(conf *http2Config, tr *http.Transport) { + fillNetHTTPConfig(conf, tr.HTTP2) +} + +func fillNetHTTPConfig(conf *http2Config, h2 *http.HTTP2Config) { + if h2 == nil { + return + } + if h2.MaxConcurrentStreams != 0 { + conf.MaxConcurrentStreams = uint32(h2.MaxConcurrentStreams) + } + if h2.MaxEncoderHeaderTableSize != 0 { + conf.MaxEncoderHeaderTableSize = uint32(h2.MaxEncoderHeaderTableSize) + } + if h2.MaxDecoderHeaderTableSize != 0 { + conf.MaxDecoderHeaderTableSize = uint32(h2.MaxDecoderHeaderTableSize) + } + if h2.MaxConcurrentStreams != 0 { + conf.MaxConcurrentStreams = uint32(h2.MaxConcurrentStreams) + } + if h2.MaxReadFrameSize != 0 { + conf.MaxReadFrameSize = uint32(h2.MaxReadFrameSize) + } + if h2.MaxReceiveBufferPerConnection != 0 { + conf.MaxUploadBufferPerConnection = int32(h2.MaxReceiveBufferPerConnection) + } + if h2.MaxReceiveBufferPerStream != 0 { + conf.MaxUploadBufferPerStream = int32(h2.MaxReceiveBufferPerStream) + } + if h2.SendPingTimeout != 0 { + conf.SendPingTimeout = h2.SendPingTimeout + } + if h2.PingTimeout != 0 { + conf.PingTimeout = h2.PingTimeout + } + if h2.WriteByteTimeout != 0 { + conf.WriteByteTimeout = h2.WriteByteTimeout + } + if h2.PermitProhibitedCipherSuites { + conf.PermitProhibitedCipherSuites = true + } + if h2.CountError != nil { + conf.CountError = h2.CountError + } +} diff --git a/vendor/golang.org/x/net/http2/config_pre_go124.go b/vendor/golang.org/x/net/http2/config_pre_go124.go new file mode 100644 index 000000000..060fd6c64 --- /dev/null +++ b/vendor/golang.org/x/net/http2/config_pre_go124.go @@ -0,0 +1,16 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !go1.24 + +package http2 + +import "net/http" + +// Pre-Go 1.24 fallback. +// The Server.HTTP2 and Transport.HTTP2 config fields were added in Go 1.24. + +func fillNetHTTPServerConfig(conf *http2Config, srv *http.Server) {} + +func fillNetHTTPTransportConfig(conf *http2Config, tr *http.Transport) {} diff --git a/vendor/golang.org/x/net/http2/frame.go b/vendor/golang.org/x/net/http2/frame.go index 43557ab7e..105c3b279 100644 --- a/vendor/golang.org/x/net/http2/frame.go +++ b/vendor/golang.org/x/net/http2/frame.go @@ -490,6 +490,9 @@ func terminalReadFrameError(err error) bool { // returned error is ErrFrameTooLarge. Other errors may be of type // ConnectionError, StreamError, or anything else from the underlying // reader. +// +// If ReadFrame returns an error and a non-nil Frame, the Frame's StreamID +// indicates the stream responsible for the error. func (fr *Framer) ReadFrame() (Frame, error) { fr.errDetail = nil if fr.lastFrame != nil { @@ -1521,7 +1524,7 @@ func (fr *Framer) maxHeaderStringLen() int { // readMetaFrame returns 0 or more CONTINUATION frames from fr and // merge them into the provided hf and returns a MetaHeadersFrame // with the decoded hpack values. -func (fr *Framer) readMetaFrame(hf *HeadersFrame) (*MetaHeadersFrame, error) { +func (fr *Framer) readMetaFrame(hf *HeadersFrame) (Frame, error) { if fr.AllowIllegalReads { return nil, errors.New("illegal use of AllowIllegalReads with ReadMetaHeaders") } @@ -1592,7 +1595,7 @@ func (fr *Framer) readMetaFrame(hf *HeadersFrame) (*MetaHeadersFrame, error) { } // It would be nice to send a RST_STREAM before sending the GOAWAY, // but the structure of the server's frame writer makes this difficult. - return nil, ConnectionError(ErrCodeProtocol) + return mh, ConnectionError(ErrCodeProtocol) } // Also close the connection after any CONTINUATION frame following an @@ -1604,11 +1607,11 @@ func (fr *Framer) readMetaFrame(hf *HeadersFrame) (*MetaHeadersFrame, error) { } // It would be nice to send a RST_STREAM before sending the GOAWAY, // but the structure of the server's frame writer makes this difficult. - return nil, ConnectionError(ErrCodeProtocol) + return mh, ConnectionError(ErrCodeProtocol) } if _, err := hdec.Write(frag); err != nil { - return nil, ConnectionError(ErrCodeCompression) + return mh, ConnectionError(ErrCodeCompression) } if hc.HeadersEnded() { @@ -1625,7 +1628,7 @@ func (fr *Framer) readMetaFrame(hf *HeadersFrame) (*MetaHeadersFrame, error) { mh.HeadersFrame.invalidate() if err := hdec.Close(); err != nil { - return nil, ConnectionError(ErrCodeCompression) + return mh, ConnectionError(ErrCodeCompression) } if invalid != nil { fr.errDetail = invalid diff --git a/vendor/golang.org/x/net/http2/http2.go b/vendor/golang.org/x/net/http2/http2.go index 6f2df2818..7688c356b 100644 --- a/vendor/golang.org/x/net/http2/http2.go +++ b/vendor/golang.org/x/net/http2/http2.go @@ -17,15 +17,18 @@ package http2 // import "golang.org/x/net/http2" import ( "bufio" + "context" "crypto/tls" + "errors" "fmt" - "io" + "net" "net/http" "os" "sort" "strconv" "strings" "sync" + "time" "golang.org/x/net/http/httpguts" ) @@ -210,12 +213,6 @@ type stringWriter interface { WriteString(s string) (n int, err error) } -// A gate lets two goroutines coordinate their activities. -type gate chan struct{} - -func (g gate) Done() { g <- struct{}{} } -func (g gate) Wait() { <-g } - // A closeWaiter is like a sync.WaitGroup but only goes 1 to 0 (open to closed). type closeWaiter chan struct{} @@ -241,13 +238,19 @@ func (cw closeWaiter) Wait() { // Its buffered writer is lazily allocated as needed, to minimize // idle memory usage with many connections. type bufferedWriter struct { - _ incomparable - w io.Writer // immutable - bw *bufio.Writer // non-nil when data is buffered + _ incomparable + group synctestGroupInterface // immutable + conn net.Conn // immutable + bw *bufio.Writer // non-nil when data is buffered + byteTimeout time.Duration // immutable, WriteByteTimeout } -func newBufferedWriter(w io.Writer) *bufferedWriter { - return &bufferedWriter{w: w} +func newBufferedWriter(group synctestGroupInterface, conn net.Conn, timeout time.Duration) *bufferedWriter { + return &bufferedWriter{ + group: group, + conn: conn, + byteTimeout: timeout, + } } // bufWriterPoolBufferSize is the size of bufio.Writer's @@ -274,7 +277,7 @@ func (w *bufferedWriter) Available() int { func (w *bufferedWriter) Write(p []byte) (n int, err error) { if w.bw == nil { bw := bufWriterPool.Get().(*bufio.Writer) - bw.Reset(w.w) + bw.Reset((*bufferedWriterTimeoutWriter)(w)) w.bw = bw } return w.bw.Write(p) @@ -292,6 +295,38 @@ func (w *bufferedWriter) Flush() error { return err } +type bufferedWriterTimeoutWriter bufferedWriter + +func (w *bufferedWriterTimeoutWriter) Write(p []byte) (n int, err error) { + return writeWithByteTimeout(w.group, w.conn, w.byteTimeout, p) +} + +// writeWithByteTimeout writes to conn. +// If more than timeout passes without any bytes being written to the connection, +// the write fails. +func writeWithByteTimeout(group synctestGroupInterface, conn net.Conn, timeout time.Duration, p []byte) (n int, err error) { + if timeout <= 0 { + return conn.Write(p) + } + for { + var now time.Time + if group == nil { + now = time.Now() + } else { + now = group.Now() + } + conn.SetWriteDeadline(now.Add(timeout)) + nn, err := conn.Write(p[n:]) + n += nn + if n == len(p) || nn == 0 || !errors.Is(err, os.ErrDeadlineExceeded) { + // Either we finished the write, made no progress, or hit the deadline. + // Whichever it is, we're done now. + conn.SetWriteDeadline(time.Time{}) + return n, err + } + } +} + func mustUint31(v int32) uint32 { if v < 0 || v > 2147483647 { panic("out of range") @@ -383,3 +418,14 @@ func validPseudoPath(v string) bool { // makes that struct also non-comparable, and generally doesn't add // any size (as long as it's first). type incomparable [0]func() + +// synctestGroupInterface is the methods of synctestGroup used by Server and Transport. +// It's defined as an interface here to let us keep synctestGroup entirely test-only +// and not a part of non-test builds. +type synctestGroupInterface interface { + Join() + Now() time.Time + NewTimer(d time.Duration) timer + AfterFunc(d time.Duration, f func()) timer + ContextWithTimeout(ctx context.Context, d time.Duration) (context.Context, context.CancelFunc) +} diff --git a/vendor/golang.org/x/net/http2/server.go b/vendor/golang.org/x/net/http2/server.go index ce2e8b40e..832414b45 100644 --- a/vendor/golang.org/x/net/http2/server.go +++ b/vendor/golang.org/x/net/http2/server.go @@ -29,6 +29,7 @@ import ( "bufio" "bytes" "context" + "crypto/rand" "crypto/tls" "errors" "fmt" @@ -52,10 +53,14 @@ import ( ) const ( - prefaceTimeout = 10 * time.Second - firstSettingsTimeout = 2 * time.Second // should be in-flight with preface anyway - handlerChunkWriteSize = 4 << 10 - defaultMaxStreams = 250 // TODO: make this 100 as the GFE seems to? + prefaceTimeout = 10 * time.Second + firstSettingsTimeout = 2 * time.Second // should be in-flight with preface anyway + handlerChunkWriteSize = 4 << 10 + defaultMaxStreams = 250 // TODO: make this 100 as the GFE seems to? + + // maxQueuedControlFrames is the maximum number of control frames like + // SETTINGS, PING and RST_STREAM that will be queued for writing before + // the connection is closed to prevent memory exhaustion attacks. maxQueuedControlFrames = 10000 ) @@ -127,6 +132,22 @@ type Server struct { // If zero or negative, there is no timeout. IdleTimeout time.Duration + // ReadIdleTimeout is the timeout after which a health check using a ping + // frame will be carried out if no frame is received on the connection. + // If zero, no health check is performed. + ReadIdleTimeout time.Duration + + // PingTimeout is the timeout after which the connection will be closed + // if a response to a ping is not received. + // If zero, a default of 15 seconds is used. + PingTimeout time.Duration + + // WriteByteTimeout is the timeout after which a connection will be + // closed if no data can be written to it. The timeout begins when data is + // available to write, and is extended whenever any bytes are written. + // If zero or negative, there is no timeout. + WriteByteTimeout time.Duration + // MaxUploadBufferPerConnection is the size of the initial flow // control window for each connections. The HTTP/2 spec does not // allow this to be smaller than 65535 or larger than 2^32-1. @@ -154,57 +175,39 @@ type Server struct { // so that we don't embed a Mutex in this struct, which will make the // struct non-copyable, which might break some callers. state *serverInternalState -} -func (s *Server) initialConnRecvWindowSize() int32 { - if s.MaxUploadBufferPerConnection >= initialWindowSize { - return s.MaxUploadBufferPerConnection - } - return 1 << 20 + // Synchronization group used for testing. + // Outside of tests, this is nil. + group synctestGroupInterface } -func (s *Server) initialStreamRecvWindowSize() int32 { - if s.MaxUploadBufferPerStream > 0 { - return s.MaxUploadBufferPerStream +func (s *Server) markNewGoroutine() { + if s.group != nil { + s.group.Join() } - return 1 << 20 } -func (s *Server) maxReadFrameSize() uint32 { - if v := s.MaxReadFrameSize; v >= minMaxFrameSize && v <= maxFrameSize { - return v +func (s *Server) now() time.Time { + if s.group != nil { + return s.group.Now() } - return defaultMaxReadFrameSize + return time.Now() } -func (s *Server) maxConcurrentStreams() uint32 { - if v := s.MaxConcurrentStreams; v > 0 { - return v +// newTimer creates a new time.Timer, or a synthetic timer in tests. +func (s *Server) newTimer(d time.Duration) timer { + if s.group != nil { + return s.group.NewTimer(d) } - return defaultMaxStreams + return timeTimer{time.NewTimer(d)} } -func (s *Server) maxDecoderHeaderTableSize() uint32 { - if v := s.MaxDecoderHeaderTableSize; v > 0 { - return v +// afterFunc creates a new time.AfterFunc timer, or a synthetic timer in tests. +func (s *Server) afterFunc(d time.Duration, f func()) timer { + if s.group != nil { + return s.group.AfterFunc(d, f) } - return initialHeaderTableSize -} - -func (s *Server) maxEncoderHeaderTableSize() uint32 { - if v := s.MaxEncoderHeaderTableSize; v > 0 { - return v - } - return initialHeaderTableSize -} - -// maxQueuedControlFrames is the maximum number of control frames like -// SETTINGS, PING and RST_STREAM that will be queued for writing before -// the connection is closed to prevent memory exhaustion attacks. -func (s *Server) maxQueuedControlFrames() int { - // TODO: if anybody asks, add a Server field, and remember to define the - // behavior of negative values. - return maxQueuedControlFrames + return timeTimer{time.AfterFunc(d, f)} } type serverInternalState struct { @@ -303,7 +306,7 @@ func ConfigureServer(s *http.Server, conf *Server) error { if s.TLSNextProto == nil { s.TLSNextProto = map[string]func(*http.Server, *tls.Conn, http.Handler){} } - protoHandler := func(hs *http.Server, c *tls.Conn, h http.Handler) { + protoHandler := func(hs *http.Server, c net.Conn, h http.Handler, sawClientPreface bool) { if testHookOnConn != nil { testHookOnConn() } @@ -320,12 +323,31 @@ func ConfigureServer(s *http.Server, conf *Server) error { ctx = bc.BaseContext() } conf.ServeConn(c, &ServeConnOpts{ - Context: ctx, - Handler: h, - BaseConfig: hs, + Context: ctx, + Handler: h, + BaseConfig: hs, + SawClientPreface: sawClientPreface, }) } - s.TLSNextProto[NextProtoTLS] = protoHandler + s.TLSNextProto[NextProtoTLS] = func(hs *http.Server, c *tls.Conn, h http.Handler) { + protoHandler(hs, c, h, false) + } + // The "unencrypted_http2" TLSNextProto key is used to pass off non-TLS HTTP/2 conns. + // + // A connection passed in this method has already had the HTTP/2 preface read from it. + s.TLSNextProto[nextProtoUnencryptedHTTP2] = func(hs *http.Server, c *tls.Conn, h http.Handler) { + nc, err := unencryptedNetConnFromTLSConn(c) + if err != nil { + if lg := hs.ErrorLog; lg != nil { + lg.Print(err) + } else { + log.Print(err) + } + go c.Close() + return + } + protoHandler(hs, nc, h, true) + } return nil } @@ -400,16 +422,22 @@ func (o *ServeConnOpts) handler() http.Handler { // // The opts parameter is optional. If nil, default values are used. func (s *Server) ServeConn(c net.Conn, opts *ServeConnOpts) { + s.serveConn(c, opts, nil) +} + +func (s *Server) serveConn(c net.Conn, opts *ServeConnOpts, newf func(*serverConn)) { baseCtx, cancel := serverConnBaseContext(c, opts) defer cancel() + http1srv := opts.baseConfig() + conf := configFromServer(http1srv, s) sc := &serverConn{ srv: s, - hs: opts.baseConfig(), + hs: http1srv, conn: c, baseCtx: baseCtx, remoteAddrStr: c.RemoteAddr().String(), - bw: newBufferedWriter(c), + bw: newBufferedWriter(s.group, c, conf.WriteByteTimeout), handler: opts.handler(), streams: make(map[uint32]*stream), readFrameCh: make(chan readFrameResult), @@ -419,13 +447,19 @@ func (s *Server) ServeConn(c net.Conn, opts *ServeConnOpts) { bodyReadCh: make(chan bodyReadMsg), // buffering doesn't matter either way doneServing: make(chan struct{}), clientMaxStreams: math.MaxUint32, // Section 6.5.2: "Initially, there is no limit to this value" - advMaxStreams: s.maxConcurrentStreams(), + advMaxStreams: conf.MaxConcurrentStreams, initialStreamSendWindowSize: initialWindowSize, + initialStreamRecvWindowSize: conf.MaxUploadBufferPerStream, maxFrameSize: initialMaxFrameSize, + pingTimeout: conf.PingTimeout, + countErrorFunc: conf.CountError, serveG: newGoroutineLock(), pushEnabled: true, sawClientPreface: opts.SawClientPreface, } + if newf != nil { + newf(sc) + } s.state.registerConn(sc) defer s.state.unregisterConn(sc) @@ -451,15 +485,15 @@ func (s *Server) ServeConn(c net.Conn, opts *ServeConnOpts) { sc.flow.add(initialWindowSize) sc.inflow.init(initialWindowSize) sc.hpackEncoder = hpack.NewEncoder(&sc.headerWriteBuf) - sc.hpackEncoder.SetMaxDynamicTableSizeLimit(s.maxEncoderHeaderTableSize()) + sc.hpackEncoder.SetMaxDynamicTableSizeLimit(conf.MaxEncoderHeaderTableSize) fr := NewFramer(sc.bw, c) - if s.CountError != nil { - fr.countError = s.CountError + if conf.CountError != nil { + fr.countError = conf.CountError } - fr.ReadMetaHeaders = hpack.NewDecoder(s.maxDecoderHeaderTableSize(), nil) + fr.ReadMetaHeaders = hpack.NewDecoder(conf.MaxDecoderHeaderTableSize, nil) fr.MaxHeaderListSize = sc.maxHeaderListSize() - fr.SetMaxReadFrameSize(s.maxReadFrameSize()) + fr.SetMaxReadFrameSize(conf.MaxReadFrameSize) sc.framer = fr if tc, ok := c.(connectionStater); ok { @@ -492,7 +526,7 @@ func (s *Server) ServeConn(c net.Conn, opts *ServeConnOpts) { // So for now, do nothing here again. } - if !s.PermitProhibitedCipherSuites && isBadCipher(sc.tlsState.CipherSuite) { + if !conf.PermitProhibitedCipherSuites && isBadCipher(sc.tlsState.CipherSuite) { // "Endpoints MAY choose to generate a connection error // (Section 5.4.1) of type INADEQUATE_SECURITY if one of // the prohibited cipher suites are negotiated." @@ -529,7 +563,7 @@ func (s *Server) ServeConn(c net.Conn, opts *ServeConnOpts) { opts.UpgradeRequest = nil } - sc.serve() + sc.serve(conf) } func serverConnBaseContext(c net.Conn, opts *ServeConnOpts) (ctx context.Context, cancel func()) { @@ -569,6 +603,7 @@ type serverConn struct { tlsState *tls.ConnectionState // shared by all handlers, like net/http remoteAddrStr string writeSched WriteScheduler + countErrorFunc func(errType string) // Everything following is owned by the serve loop; use serveG.check(): serveG goroutineLock // used to verify funcs are on serve() @@ -588,6 +623,7 @@ type serverConn struct { streams map[uint32]*stream unstartedHandlers []unstartedHandler initialStreamSendWindowSize int32 + initialStreamRecvWindowSize int32 maxFrameSize int32 peerMaxHeaderListSize uint32 // zero means unknown (default) canonHeader map[string]string // http2-lower-case -> Go-Canonical-Case @@ -598,9 +634,14 @@ type serverConn struct { inGoAway bool // we've started to or sent GOAWAY inFrameScheduleLoop bool // whether we're in the scheduleFrameWrite loop needToSendGoAway bool // we need to schedule a GOAWAY frame write + pingSent bool + sentPingData [8]byte goAwayCode ErrCode - shutdownTimer *time.Timer // nil until used - idleTimer *time.Timer // nil if unused + shutdownTimer timer // nil until used + idleTimer timer // nil if unused + readIdleTimeout time.Duration + pingTimeout time.Duration + readIdleTimer timer // nil if unused // Owned by the writeFrameAsync goroutine: headerWriteBuf bytes.Buffer @@ -615,11 +656,7 @@ func (sc *serverConn) maxHeaderListSize() uint32 { if n <= 0 { n = http.DefaultMaxHeaderBytes } - // http2's count is in a slightly different unit and includes 32 bytes per pair. - // So, take the net/http.Server value and pad it up a bit, assuming 10 headers. - const perFieldOverhead = 32 // per http2 spec - const typicalHeaders = 10 // conservative - return uint32(n + typicalHeaders*perFieldOverhead) + return uint32(adjustHTTP1MaxHeaderSize(int64(n))) } func (sc *serverConn) curOpenStreams() uint32 { @@ -649,12 +686,12 @@ type stream struct { flow outflow // limits writing from Handler to client inflow inflow // what the client is allowed to POST/etc to us state streamState - resetQueued bool // RST_STREAM queued for write; set by sc.resetStream - gotTrailerHeader bool // HEADER frame for trailers was seen - wroteHeaders bool // whether we wrote headers (not status 100) - readDeadline *time.Timer // nil if unused - writeDeadline *time.Timer // nil if unused - closeErr error // set before cw is closed + resetQueued bool // RST_STREAM queued for write; set by sc.resetStream + gotTrailerHeader bool // HEADER frame for trailers was seen + wroteHeaders bool // whether we wrote headers (not status 100) + readDeadline timer // nil if unused + writeDeadline timer // nil if unused + closeErr error // set before cw is closed trailer http.Header // accumulated trailers reqTrailer http.Header // handler's Request.Trailer @@ -732,11 +769,7 @@ func isClosedConnError(err error) bool { return false } - // TODO: remove this string search and be more like the Windows - // case below. That might involve modifying the standard library - // to return better error types. - str := err.Error() - if strings.Contains(str, "use of closed network connection") { + if errors.Is(err, net.ErrClosed) { return true } @@ -815,8 +848,9 @@ type readFrameResult struct { // consumer is done with the frame. // It's run on its own goroutine. func (sc *serverConn) readFrames() { - gate := make(gate) - gateDone := gate.Done + sc.srv.markNewGoroutine() + gate := make(chan struct{}) + gateDone := func() { gate <- struct{}{} } for { f, err := sc.framer.ReadFrame() select { @@ -847,6 +881,7 @@ type frameWriteResult struct { // At most one goroutine can be running writeFrameAsync at a time per // serverConn. func (sc *serverConn) writeFrameAsync(wr FrameWriteRequest, wd *writeData) { + sc.srv.markNewGoroutine() var err error if wd == nil { err = wr.write.writeFrame(sc) @@ -885,7 +920,7 @@ func (sc *serverConn) notePanic() { } } -func (sc *serverConn) serve() { +func (sc *serverConn) serve(conf http2Config) { sc.serveG.check() defer sc.notePanic() defer sc.conn.Close() @@ -899,18 +934,18 @@ func (sc *serverConn) serve() { sc.writeFrame(FrameWriteRequest{ write: writeSettings{ - {SettingMaxFrameSize, sc.srv.maxReadFrameSize()}, + {SettingMaxFrameSize, conf.MaxReadFrameSize}, {SettingMaxConcurrentStreams, sc.advMaxStreams}, {SettingMaxHeaderListSize, sc.maxHeaderListSize()}, - {SettingHeaderTableSize, sc.srv.maxDecoderHeaderTableSize()}, - {SettingInitialWindowSize, uint32(sc.srv.initialStreamRecvWindowSize())}, + {SettingHeaderTableSize, conf.MaxDecoderHeaderTableSize}, + {SettingInitialWindowSize, uint32(sc.initialStreamRecvWindowSize)}, }, }) sc.unackedSettings++ // Each connection starts with initialWindowSize inflow tokens. // If a higher value is configured, we add more tokens. - if diff := sc.srv.initialConnRecvWindowSize() - initialWindowSize; diff > 0 { + if diff := conf.MaxUploadBufferPerConnection - initialWindowSize; diff > 0 { sc.sendWindowUpdate(nil, int(diff)) } @@ -926,15 +961,22 @@ func (sc *serverConn) serve() { sc.setConnState(http.StateIdle) if sc.srv.IdleTimeout > 0 { - sc.idleTimer = time.AfterFunc(sc.srv.IdleTimeout, sc.onIdleTimer) + sc.idleTimer = sc.srv.afterFunc(sc.srv.IdleTimeout, sc.onIdleTimer) defer sc.idleTimer.Stop() } + if conf.SendPingTimeout > 0 { + sc.readIdleTimeout = conf.SendPingTimeout + sc.readIdleTimer = sc.srv.afterFunc(conf.SendPingTimeout, sc.onReadIdleTimer) + defer sc.readIdleTimer.Stop() + } + go sc.readFrames() // closed by defer sc.conn.Close above - settingsTimer := time.AfterFunc(firstSettingsTimeout, sc.onSettingsTimer) + settingsTimer := sc.srv.afterFunc(firstSettingsTimeout, sc.onSettingsTimer) defer settingsTimer.Stop() + lastFrameTime := sc.srv.now() loopNum := 0 for { loopNum++ @@ -948,6 +990,7 @@ func (sc *serverConn) serve() { case res := <-sc.wroteFrameCh: sc.wroteFrame(res) case res := <-sc.readFrameCh: + lastFrameTime = sc.srv.now() // Process any written frames before reading new frames from the client since a // written frame could have triggered a new stream to be started. if sc.writingFrameAsync { @@ -979,6 +1022,8 @@ func (sc *serverConn) serve() { case idleTimerMsg: sc.vlogf("connection is idle") sc.goAway(ErrCodeNo) + case readIdleTimerMsg: + sc.handlePingTimer(lastFrameTime) case shutdownTimerMsg: sc.vlogf("GOAWAY close timer fired; closing conn from %v", sc.conn.RemoteAddr()) return @@ -1001,7 +1046,7 @@ func (sc *serverConn) serve() { // If the peer is causing us to generate a lot of control frames, // but not reading them from us, assume they are trying to make us // run out of memory. - if sc.queuedControlFrames > sc.srv.maxQueuedControlFrames() { + if sc.queuedControlFrames > maxQueuedControlFrames { sc.vlogf("http2: too many control frames in send queue, closing connection") return } @@ -1017,12 +1062,39 @@ func (sc *serverConn) serve() { } } +func (sc *serverConn) handlePingTimer(lastFrameReadTime time.Time) { + if sc.pingSent { + sc.vlogf("timeout waiting for PING response") + sc.conn.Close() + return + } + + pingAt := lastFrameReadTime.Add(sc.readIdleTimeout) + now := sc.srv.now() + if pingAt.After(now) { + // We received frames since arming the ping timer. + // Reset it for the next possible timeout. + sc.readIdleTimer.Reset(pingAt.Sub(now)) + return + } + + sc.pingSent = true + // Ignore crypto/rand.Read errors: It generally can't fail, and worse case if it does + // is we send a PING frame containing 0s. + _, _ = rand.Read(sc.sentPingData[:]) + sc.writeFrame(FrameWriteRequest{ + write: &writePing{data: sc.sentPingData}, + }) + sc.readIdleTimer.Reset(sc.pingTimeout) +} + type serverMessage int // Message values sent to serveMsgCh. var ( settingsTimerMsg = new(serverMessage) idleTimerMsg = new(serverMessage) + readIdleTimerMsg = new(serverMessage) shutdownTimerMsg = new(serverMessage) gracefulShutdownMsg = new(serverMessage) handlerDoneMsg = new(serverMessage) @@ -1030,6 +1102,7 @@ var ( func (sc *serverConn) onSettingsTimer() { sc.sendServeMsg(settingsTimerMsg) } func (sc *serverConn) onIdleTimer() { sc.sendServeMsg(idleTimerMsg) } +func (sc *serverConn) onReadIdleTimer() { sc.sendServeMsg(readIdleTimerMsg) } func (sc *serverConn) onShutdownTimer() { sc.sendServeMsg(shutdownTimerMsg) } func (sc *serverConn) sendServeMsg(msg interface{}) { @@ -1061,10 +1134,10 @@ func (sc *serverConn) readPreface() error { errc <- nil } }() - timer := time.NewTimer(prefaceTimeout) // TODO: configurable on *Server? + timer := sc.srv.newTimer(prefaceTimeout) // TODO: configurable on *Server? defer timer.Stop() select { - case <-timer.C: + case <-timer.C(): return errPrefaceTimeout case err := <-errc: if err == nil { @@ -1282,6 +1355,10 @@ func (sc *serverConn) wroteFrame(res frameWriteResult) { sc.writingFrame = false sc.writingFrameAsync = false + if res.err != nil { + sc.conn.Close() + } + wr := res.wr if writeEndsStream(wr.write) { @@ -1429,7 +1506,7 @@ func (sc *serverConn) goAway(code ErrCode) { func (sc *serverConn) shutDownIn(d time.Duration) { sc.serveG.check() - sc.shutdownTimer = time.AfterFunc(d, sc.onShutdownTimer) + sc.shutdownTimer = sc.srv.afterFunc(d, sc.onShutdownTimer) } func (sc *serverConn) resetStream(se StreamError) { @@ -1482,6 +1559,11 @@ func (sc *serverConn) processFrameFromReader(res readFrameResult) bool { sc.goAway(ErrCodeFlowControl) return true case ConnectionError: + if res.f != nil { + if id := res.f.Header().StreamID; id > sc.maxClientStreamID { + sc.maxClientStreamID = id + } + } sc.logf("http2: server connection error from %v: %v", sc.conn.RemoteAddr(), ev) sc.goAway(ErrCode(ev)) return true // goAway will handle shutdown @@ -1551,6 +1633,11 @@ func (sc *serverConn) processFrame(f Frame) error { func (sc *serverConn) processPing(f *PingFrame) error { sc.serveG.check() if f.IsAck() { + if sc.pingSent && sc.sentPingData == f.Data { + // This is a response to a PING we sent. + sc.pingSent = false + sc.readIdleTimer.Reset(sc.readIdleTimeout) + } // 6.7 PING: " An endpoint MUST NOT respond to PING frames // containing this flag." return nil @@ -1638,7 +1725,7 @@ func (sc *serverConn) closeStream(st *stream, err error) { delete(sc.streams, st.id) if len(sc.streams) == 0 { sc.setConnState(http.StateIdle) - if sc.srv.IdleTimeout > 0 { + if sc.srv.IdleTimeout > 0 && sc.idleTimer != nil { sc.idleTimer.Reset(sc.srv.IdleTimeout) } if h1ServerKeepAlivesDisabled(sc.hs) { @@ -1660,6 +1747,7 @@ func (sc *serverConn) closeStream(st *stream, err error) { } } st.closeErr = err + st.cancelCtx() st.cw.Close() // signals Handler's CloseNotifier, unblocks writes, etc sc.writeSched.CloseStream(st.id) } @@ -2020,7 +2108,7 @@ func (sc *serverConn) processHeaders(f *MetaHeadersFrame) error { // (in Go 1.8), though. That's a more sane option anyway. if sc.hs.ReadTimeout > 0 { sc.conn.SetReadDeadline(time.Time{}) - st.readDeadline = time.AfterFunc(sc.hs.ReadTimeout, st.onReadTimeout) + st.readDeadline = sc.srv.afterFunc(sc.hs.ReadTimeout, st.onReadTimeout) } return sc.scheduleHandler(id, rw, req, handler) @@ -2116,9 +2204,9 @@ func (sc *serverConn) newStream(id, pusherID uint32, state streamState) *stream st.cw.Init() st.flow.conn = &sc.flow // link to conn-level counter st.flow.add(sc.initialStreamSendWindowSize) - st.inflow.init(sc.srv.initialStreamRecvWindowSize()) + st.inflow.init(sc.initialStreamRecvWindowSize) if sc.hs.WriteTimeout > 0 { - st.writeDeadline = time.AfterFunc(sc.hs.WriteTimeout, st.onWriteTimeout) + st.writeDeadline = sc.srv.afterFunc(sc.hs.WriteTimeout, st.onWriteTimeout) } sc.streams[id] = st @@ -2342,6 +2430,7 @@ func (sc *serverConn) handlerDone() { // Run on its own goroutine. func (sc *serverConn) runHandler(rw *responseWriter, req *http.Request, handler func(http.ResponseWriter, *http.Request)) { + sc.srv.markNewGoroutine() defer sc.sendServeMsg(handlerDoneMsg) didPanic := true defer func() { @@ -2638,7 +2727,7 @@ func (rws *responseWriterState) writeChunk(p []byte) (n int, err error) { var date string if _, ok := rws.snapHeader["Date"]; !ok { // TODO(bradfitz): be faster here, like net/http? measure. - date = time.Now().UTC().Format(http.TimeFormat) + date = rws.conn.srv.now().UTC().Format(http.TimeFormat) } for _, v := range rws.snapHeader["Trailer"] { @@ -2760,7 +2849,7 @@ func (rws *responseWriterState) promoteUndeclaredTrailers() { func (w *responseWriter) SetReadDeadline(deadline time.Time) error { st := w.rws.stream - if !deadline.IsZero() && deadline.Before(time.Now()) { + if !deadline.IsZero() && deadline.Before(w.rws.conn.srv.now()) { // If we're setting a deadline in the past, reset the stream immediately // so writes after SetWriteDeadline returns will fail. st.onReadTimeout() @@ -2776,9 +2865,9 @@ func (w *responseWriter) SetReadDeadline(deadline time.Time) error { if deadline.IsZero() { st.readDeadline = nil } else if st.readDeadline == nil { - st.readDeadline = time.AfterFunc(deadline.Sub(time.Now()), st.onReadTimeout) + st.readDeadline = sc.srv.afterFunc(deadline.Sub(sc.srv.now()), st.onReadTimeout) } else { - st.readDeadline.Reset(deadline.Sub(time.Now())) + st.readDeadline.Reset(deadline.Sub(sc.srv.now())) } }) return nil @@ -2786,7 +2875,7 @@ func (w *responseWriter) SetReadDeadline(deadline time.Time) error { func (w *responseWriter) SetWriteDeadline(deadline time.Time) error { st := w.rws.stream - if !deadline.IsZero() && deadline.Before(time.Now()) { + if !deadline.IsZero() && deadline.Before(w.rws.conn.srv.now()) { // If we're setting a deadline in the past, reset the stream immediately // so writes after SetWriteDeadline returns will fail. st.onWriteTimeout() @@ -2802,14 +2891,19 @@ func (w *responseWriter) SetWriteDeadline(deadline time.Time) error { if deadline.IsZero() { st.writeDeadline = nil } else if st.writeDeadline == nil { - st.writeDeadline = time.AfterFunc(deadline.Sub(time.Now()), st.onWriteTimeout) + st.writeDeadline = sc.srv.afterFunc(deadline.Sub(sc.srv.now()), st.onWriteTimeout) } else { - st.writeDeadline.Reset(deadline.Sub(time.Now())) + st.writeDeadline.Reset(deadline.Sub(sc.srv.now())) } }) return nil } +func (w *responseWriter) EnableFullDuplex() error { + // We always support full duplex responses, so this is a no-op. + return nil +} + func (w *responseWriter) Flush() { w.FlushError() } @@ -3256,7 +3350,7 @@ func (sc *serverConn) countError(name string, err error) error { if sc == nil || sc.srv == nil { return err } - f := sc.srv.CountError + f := sc.countErrorFunc if f == nil { return err } diff --git a/vendor/golang.org/x/net/http2/testsync.go b/vendor/golang.org/x/net/http2/testsync.go deleted file mode 100644 index 61075bd16..000000000 --- a/vendor/golang.org/x/net/http2/testsync.go +++ /dev/null @@ -1,331 +0,0 @@ -// Copyright 2024 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. -package http2 - -import ( - "context" - "sync" - "time" -) - -// testSyncHooks coordinates goroutines in tests. -// -// For example, a call to ClientConn.RoundTrip involves several goroutines, including: -// - the goroutine running RoundTrip; -// - the clientStream.doRequest goroutine, which writes the request; and -// - the clientStream.readLoop goroutine, which reads the response. -// -// Using testSyncHooks, a test can start a RoundTrip and identify when all these goroutines -// are blocked waiting for some condition such as reading the Request.Body or waiting for -// flow control to become available. -// -// The testSyncHooks also manage timers and synthetic time in tests. -// This permits us to, for example, start a request and cause it to time out waiting for -// response headers without resorting to time.Sleep calls. -type testSyncHooks struct { - // active/inactive act as a mutex and condition variable. - // - // - neither chan contains a value: testSyncHooks is locked. - // - active contains a value: unlocked, and at least one goroutine is not blocked - // - inactive contains a value: unlocked, and all goroutines are blocked - active chan struct{} - inactive chan struct{} - - // goroutine counts - total int // total goroutines - condwait map[*sync.Cond]int // blocked in sync.Cond.Wait - blocked []*testBlockedGoroutine // otherwise blocked - - // fake time - now time.Time - timers []*fakeTimer - - // Transport testing: Report various events. - newclientconn func(*ClientConn) - newstream func(*clientStream) -} - -// testBlockedGoroutine is a blocked goroutine. -type testBlockedGoroutine struct { - f func() bool // blocked until f returns true - ch chan struct{} // closed when unblocked -} - -func newTestSyncHooks() *testSyncHooks { - h := &testSyncHooks{ - active: make(chan struct{}, 1), - inactive: make(chan struct{}, 1), - condwait: map[*sync.Cond]int{}, - } - h.inactive <- struct{}{} - h.now = time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC) - return h -} - -// lock acquires the testSyncHooks mutex. -func (h *testSyncHooks) lock() { - select { - case <-h.active: - case <-h.inactive: - } -} - -// waitInactive waits for all goroutines to become inactive. -func (h *testSyncHooks) waitInactive() { - for { - <-h.inactive - if !h.unlock() { - break - } - } -} - -// unlock releases the testSyncHooks mutex. -// It reports whether any goroutines are active. -func (h *testSyncHooks) unlock() (active bool) { - // Look for a blocked goroutine which can be unblocked. - blocked := h.blocked[:0] - unblocked := false - for _, b := range h.blocked { - if !unblocked && b.f() { - unblocked = true - close(b.ch) - } else { - blocked = append(blocked, b) - } - } - h.blocked = blocked - - // Count goroutines blocked on condition variables. - condwait := 0 - for _, count := range h.condwait { - condwait += count - } - - if h.total > condwait+len(blocked) { - h.active <- struct{}{} - return true - } else { - h.inactive <- struct{}{} - return false - } -} - -// goRun starts a new goroutine. -func (h *testSyncHooks) goRun(f func()) { - h.lock() - h.total++ - h.unlock() - go func() { - defer func() { - h.lock() - h.total-- - h.unlock() - }() - f() - }() -} - -// blockUntil indicates that a goroutine is blocked waiting for some condition to become true. -// It waits until f returns true before proceeding. -// -// Example usage: -// -// h.blockUntil(func() bool { -// // Is the context done yet? -// select { -// case <-ctx.Done(): -// default: -// return false -// } -// return true -// }) -// // Wait for the context to become done. -// <-ctx.Done() -// -// The function f passed to blockUntil must be non-blocking and idempotent. -func (h *testSyncHooks) blockUntil(f func() bool) { - if f() { - return - } - ch := make(chan struct{}) - h.lock() - h.blocked = append(h.blocked, &testBlockedGoroutine{ - f: f, - ch: ch, - }) - h.unlock() - <-ch -} - -// broadcast is sync.Cond.Broadcast. -func (h *testSyncHooks) condBroadcast(cond *sync.Cond) { - h.lock() - delete(h.condwait, cond) - h.unlock() - cond.Broadcast() -} - -// broadcast is sync.Cond.Wait. -func (h *testSyncHooks) condWait(cond *sync.Cond) { - h.lock() - h.condwait[cond]++ - h.unlock() -} - -// newTimer creates a new fake timer. -func (h *testSyncHooks) newTimer(d time.Duration) timer { - h.lock() - defer h.unlock() - t := &fakeTimer{ - hooks: h, - when: h.now.Add(d), - c: make(chan time.Time), - } - h.timers = append(h.timers, t) - return t -} - -// afterFunc creates a new fake AfterFunc timer. -func (h *testSyncHooks) afterFunc(d time.Duration, f func()) timer { - h.lock() - defer h.unlock() - t := &fakeTimer{ - hooks: h, - when: h.now.Add(d), - f: f, - } - h.timers = append(h.timers, t) - return t -} - -func (h *testSyncHooks) contextWithTimeout(ctx context.Context, d time.Duration) (context.Context, context.CancelFunc) { - ctx, cancel := context.WithCancel(ctx) - t := h.afterFunc(d, cancel) - return ctx, func() { - t.Stop() - cancel() - } -} - -func (h *testSyncHooks) timeUntilEvent() time.Duration { - h.lock() - defer h.unlock() - var next time.Time - for _, t := range h.timers { - if next.IsZero() || t.when.Before(next) { - next = t.when - } - } - if d := next.Sub(h.now); d > 0 { - return d - } - return 0 -} - -// advance advances time and causes synthetic timers to fire. -func (h *testSyncHooks) advance(d time.Duration) { - h.lock() - defer h.unlock() - h.now = h.now.Add(d) - timers := h.timers[:0] - for _, t := range h.timers { - t := t // remove after go.mod depends on go1.22 - t.mu.Lock() - switch { - case t.when.After(h.now): - timers = append(timers, t) - case t.when.IsZero(): - // stopped timer - default: - t.when = time.Time{} - if t.c != nil { - close(t.c) - } - if t.f != nil { - h.total++ - go func() { - defer func() { - h.lock() - h.total-- - h.unlock() - }() - t.f() - }() - } - } - t.mu.Unlock() - } - h.timers = timers -} - -// A timer wraps a time.Timer, or a synthetic equivalent in tests. -// Unlike time.Timer, timer is single-use: The timer channel is closed when the timer expires. -type timer interface { - C() <-chan time.Time - Stop() bool - Reset(d time.Duration) bool -} - -// timeTimer implements timer using real time. -type timeTimer struct { - t *time.Timer - c chan time.Time -} - -// newTimeTimer creates a new timer using real time. -func newTimeTimer(d time.Duration) timer { - ch := make(chan time.Time) - t := time.AfterFunc(d, func() { - close(ch) - }) - return &timeTimer{t, ch} -} - -// newTimeAfterFunc creates an AfterFunc timer using real time. -func newTimeAfterFunc(d time.Duration, f func()) timer { - return &timeTimer{ - t: time.AfterFunc(d, f), - } -} - -func (t timeTimer) C() <-chan time.Time { return t.c } -func (t timeTimer) Stop() bool { return t.t.Stop() } -func (t timeTimer) Reset(d time.Duration) bool { return t.t.Reset(d) } - -// fakeTimer implements timer using fake time. -type fakeTimer struct { - hooks *testSyncHooks - - mu sync.Mutex - when time.Time // when the timer will fire - c chan time.Time // closed when the timer fires; mutually exclusive with f - f func() // called when the timer fires; mutually exclusive with c -} - -func (t *fakeTimer) C() <-chan time.Time { return t.c } - -func (t *fakeTimer) Stop() bool { - t.mu.Lock() - defer t.mu.Unlock() - stopped := t.when.IsZero() - t.when = time.Time{} - return stopped -} - -func (t *fakeTimer) Reset(d time.Duration) bool { - if t.c != nil || t.f == nil { - panic("fakeTimer only supports Reset on AfterFunc timers") - } - t.mu.Lock() - defer t.mu.Unlock() - t.hooks.lock() - defer t.hooks.unlock() - active := !t.when.IsZero() - t.when = t.hooks.now.Add(d) - if !active { - t.hooks.timers = append(t.hooks.timers, t) - } - return active -} diff --git a/vendor/golang.org/x/net/http2/timer.go b/vendor/golang.org/x/net/http2/timer.go new file mode 100644 index 000000000..0b1c17b81 --- /dev/null +++ b/vendor/golang.org/x/net/http2/timer.go @@ -0,0 +1,20 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +package http2 + +import "time" + +// A timer is a time.Timer, as an interface which can be replaced in tests. +type timer = interface { + C() <-chan time.Time + Reset(d time.Duration) bool + Stop() bool +} + +// timeTimer adapts a time.Timer to the timer interface. +type timeTimer struct { + *time.Timer +} + +func (t timeTimer) C() <-chan time.Time { return t.Timer.C } diff --git a/vendor/golang.org/x/net/http2/transport.go b/vendor/golang.org/x/net/http2/transport.go index ce375c8c7..f5968f440 100644 --- a/vendor/golang.org/x/net/http2/transport.go +++ b/vendor/golang.org/x/net/http2/transport.go @@ -25,7 +25,6 @@ import ( "net/http" "net/http/httptrace" "net/textproto" - "os" "sort" "strconv" "strings" @@ -185,42 +184,80 @@ type Transport struct { connPoolOnce sync.Once connPoolOrDef ClientConnPool // non-nil version of ConnPool - syncHooks *testSyncHooks + *transportTestHooks } -func (t *Transport) maxHeaderListSize() uint32 { - if t.MaxHeaderListSize == 0 { - return 10 << 20 +// Hook points used for testing. +// Outside of tests, t.transportTestHooks is nil and these all have minimal implementations. +// Inside tests, see the testSyncHooks function docs. + +type transportTestHooks struct { + newclientconn func(*ClientConn) + group synctestGroupInterface +} + +func (t *Transport) markNewGoroutine() { + if t != nil && t.transportTestHooks != nil { + t.transportTestHooks.group.Join() } - if t.MaxHeaderListSize == 0xffffffff { - return 0 +} + +func (t *Transport) now() time.Time { + if t != nil && t.transportTestHooks != nil { + return t.transportTestHooks.group.Now() } - return t.MaxHeaderListSize + return time.Now() } -func (t *Transport) maxFrameReadSize() uint32 { - if t.MaxReadFrameSize == 0 { - return 0 // use the default provided by the peer +func (t *Transport) timeSince(when time.Time) time.Duration { + if t != nil && t.transportTestHooks != nil { + return t.now().Sub(when) } - if t.MaxReadFrameSize < minMaxFrameSize { - return minMaxFrameSize + return time.Since(when) +} + +// newTimer creates a new time.Timer, or a synthetic timer in tests. +func (t *Transport) newTimer(d time.Duration) timer { + if t.transportTestHooks != nil { + return t.transportTestHooks.group.NewTimer(d) } - if t.MaxReadFrameSize > maxFrameSize { - return maxFrameSize + return timeTimer{time.NewTimer(d)} +} + +// afterFunc creates a new time.AfterFunc timer, or a synthetic timer in tests. +func (t *Transport) afterFunc(d time.Duration, f func()) timer { + if t.transportTestHooks != nil { + return t.transportTestHooks.group.AfterFunc(d, f) } - return t.MaxReadFrameSize + return timeTimer{time.AfterFunc(d, f)} } -func (t *Transport) disableCompression() bool { - return t.DisableCompression || (t.t1 != nil && t.t1.DisableCompression) +func (t *Transport) contextWithTimeout(ctx context.Context, d time.Duration) (context.Context, context.CancelFunc) { + if t.transportTestHooks != nil { + return t.transportTestHooks.group.ContextWithTimeout(ctx, d) + } + return context.WithTimeout(ctx, d) } -func (t *Transport) pingTimeout() time.Duration { - if t.PingTimeout == 0 { - return 15 * time.Second +func (t *Transport) maxHeaderListSize() uint32 { + n := int64(t.MaxHeaderListSize) + if t.t1 != nil && t.t1.MaxResponseHeaderBytes != 0 { + n = t.t1.MaxResponseHeaderBytes + if n > 0 { + n = adjustHTTP1MaxHeaderSize(n) + } + } + if n <= 0 { + return 10 << 20 } - return t.PingTimeout + if n >= 0xffffffff { + return 0 + } + return uint32(n) +} +func (t *Transport) disableCompression() bool { + return t.DisableCompression || (t.t1 != nil && t.t1.DisableCompression) } // ConfigureTransport configures a net/http HTTP/1 Transport to use HTTP/2. @@ -258,8 +295,8 @@ func configureTransports(t1 *http.Transport) (*Transport, error) { if !strSliceContains(t1.TLSClientConfig.NextProtos, "http/1.1") { t1.TLSClientConfig.NextProtos = append(t1.TLSClientConfig.NextProtos, "http/1.1") } - upgradeFn := func(authority string, c *tls.Conn) http.RoundTripper { - addr := authorityAddr("https", authority) + upgradeFn := func(scheme, authority string, c net.Conn) http.RoundTripper { + addr := authorityAddr(scheme, authority) if used, err := connPool.addConnIfNeeded(addr, t2, c); err != nil { go c.Close() return erringRoundTripper{err} @@ -270,18 +307,37 @@ func configureTransports(t1 *http.Transport) (*Transport, error) { // was unknown) go c.Close() } + if scheme == "http" { + return (*unencryptedTransport)(t2) + } return t2 } - if m := t1.TLSNextProto; len(m) == 0 { - t1.TLSNextProto = map[string]func(string, *tls.Conn) http.RoundTripper{ - "h2": upgradeFn, + if t1.TLSNextProto == nil { + t1.TLSNextProto = make(map[string]func(string, *tls.Conn) http.RoundTripper) + } + t1.TLSNextProto[NextProtoTLS] = func(authority string, c *tls.Conn) http.RoundTripper { + return upgradeFn("https", authority, c) + } + // The "unencrypted_http2" TLSNextProto key is used to pass off non-TLS HTTP/2 conns. + t1.TLSNextProto[nextProtoUnencryptedHTTP2] = func(authority string, c *tls.Conn) http.RoundTripper { + nc, err := unencryptedNetConnFromTLSConn(c) + if err != nil { + go c.Close() + return erringRoundTripper{err} } - } else { - m["h2"] = upgradeFn + return upgradeFn("http", authority, nc) } return t2, nil } +// unencryptedTransport is a Transport with a RoundTrip method that +// always permits http:// URLs. +type unencryptedTransport Transport + +func (t *unencryptedTransport) RoundTrip(req *http.Request) (*http.Response, error) { + return (*Transport)(t).RoundTripOpt(req, RoundTripOpt{allowHTTP: true}) +} + func (t *Transport) connPool() ClientConnPool { t.connPoolOnce.Do(t.initConnPool) return t.connPoolOrDef @@ -301,7 +357,7 @@ type ClientConn struct { t *Transport tconn net.Conn // usually *tls.Conn, except specialized impls tlsState *tls.ConnectionState // nil only for specialized impls - reused uint32 // whether conn is being reused; atomic + atomicReused uint32 // whether conn is being reused; atomic singleUse bool // whether being used for a single http.Request getConnCalled bool // used by clientConnPool @@ -332,11 +388,22 @@ type ClientConn struct { lastActive time.Time lastIdle time.Time // time last idle // Settings from peer: (also guarded by wmu) - maxFrameSize uint32 - maxConcurrentStreams uint32 - peerMaxHeaderListSize uint64 - peerMaxHeaderTableSize uint32 - initialWindowSize uint32 + maxFrameSize uint32 + maxConcurrentStreams uint32 + peerMaxHeaderListSize uint64 + peerMaxHeaderTableSize uint32 + initialWindowSize uint32 + initialStreamRecvWindowSize int32 + readIdleTimeout time.Duration + pingTimeout time.Duration + + // pendingResets is the number of RST_STREAM frames we have sent to the peer, + // without confirming that the peer has received them. When we send a RST_STREAM, + // we bundle it with a PING frame, unless a PING is already in flight. We count + // the reset stream against the connection's concurrency limit until we get + // a PING response. This limits the number of requests we'll try to send to a + // completely unresponsive connection. + pendingResets int // reqHeaderMu is a 1-element semaphore channel controlling access to sending new requests. // Write to reqHeaderMu to lock it, read from it to unlock. @@ -352,60 +419,6 @@ type ClientConn struct { werr error // first write error that has occurred hbuf bytes.Buffer // HPACK encoder writes into this henc *hpack.Encoder - - syncHooks *testSyncHooks // can be nil -} - -// Hook points used for testing. -// Outside of tests, cc.syncHooks is nil and these all have minimal implementations. -// Inside tests, see the testSyncHooks function docs. - -// goRun starts a new goroutine. -func (cc *ClientConn) goRun(f func()) { - if cc.syncHooks != nil { - cc.syncHooks.goRun(f) - return - } - go f() -} - -// condBroadcast is cc.cond.Broadcast. -func (cc *ClientConn) condBroadcast() { - if cc.syncHooks != nil { - cc.syncHooks.condBroadcast(cc.cond) - } - cc.cond.Broadcast() -} - -// condWait is cc.cond.Wait. -func (cc *ClientConn) condWait() { - if cc.syncHooks != nil { - cc.syncHooks.condWait(cc.cond) - } - cc.cond.Wait() -} - -// newTimer creates a new time.Timer, or a synthetic timer in tests. -func (cc *ClientConn) newTimer(d time.Duration) timer { - if cc.syncHooks != nil { - return cc.syncHooks.newTimer(d) - } - return newTimeTimer(d) -} - -// afterFunc creates a new time.AfterFunc timer, or a synthetic timer in tests. -func (cc *ClientConn) afterFunc(d time.Duration, f func()) timer { - if cc.syncHooks != nil { - return cc.syncHooks.afterFunc(d, f) - } - return newTimeAfterFunc(d, f) -} - -func (cc *ClientConn) contextWithTimeout(ctx context.Context, d time.Duration) (context.Context, context.CancelFunc) { - if cc.syncHooks != nil { - return cc.syncHooks.contextWithTimeout(ctx, d) - } - return context.WithTimeout(ctx, d) } // clientStream is the state for a single HTTP/2 stream. One of these @@ -448,12 +461,12 @@ type clientStream struct { sentHeaders bool // owned by clientConnReadLoop: - firstByte bool // got the first response byte - pastHeaders bool // got first MetaHeadersFrame (actual headers) - pastTrailers bool // got optional second MetaHeadersFrame (trailers) - num1xx uint8 // number of 1xx responses seen - readClosed bool // peer sent an END_STREAM flag - readAborted bool // read loop reset the stream + firstByte bool // got the first response byte + pastHeaders bool // got first MetaHeadersFrame (actual headers) + pastTrailers bool // got optional second MetaHeadersFrame (trailers) + readClosed bool // peer sent an END_STREAM flag + readAborted bool // read loop reset the stream + totalHeaderSize int64 // total size of 1xx headers seen trailer http.Header // accumulated trailers resTrailer *http.Header // client's Response.Trailer @@ -487,7 +500,7 @@ func (cs *clientStream) abortStreamLocked(err error) { // TODO(dneil): Clean up tests where cs.cc.cond is nil. if cs.cc.cond != nil { // Wake up writeRequestBody if it is waiting on flow control. - cs.cc.condBroadcast() + cs.cc.cond.Broadcast() } } @@ -497,7 +510,7 @@ func (cs *clientStream) abortRequestBodyWrite() { defer cc.mu.Unlock() if cs.reqBody != nil && cs.reqBodyClosed == nil { cs.closeReqBodyLocked() - cc.condBroadcast() + cc.cond.Broadcast() } } @@ -507,13 +520,15 @@ func (cs *clientStream) closeReqBodyLocked() { } cs.reqBodyClosed = make(chan struct{}) reqBodyClosed := cs.reqBodyClosed - cs.cc.goRun(func() { + go func() { + cs.cc.t.markNewGoroutine() cs.reqBody.Close() close(reqBodyClosed) - }) + }() } type stickyErrWriter struct { + group synctestGroupInterface conn net.Conn timeout time.Duration err *error @@ -523,22 +538,9 @@ func (sew stickyErrWriter) Write(p []byte) (n int, err error) { if *sew.err != nil { return 0, *sew.err } - for { - if sew.timeout != 0 { - sew.conn.SetWriteDeadline(time.Now().Add(sew.timeout)) - } - nn, err := sew.conn.Write(p[n:]) - n += nn - if n < len(p) && nn > 0 && errors.Is(err, os.ErrDeadlineExceeded) { - // Keep extending the deadline so long as we're making progress. - continue - } - if sew.timeout != 0 { - sew.conn.SetWriteDeadline(time.Time{}) - } - *sew.err = err - return n, err - } + n, err = writeWithByteTimeout(sew.group, sew.conn, sew.timeout, p) + *sew.err = err + return n, err } // noCachedConnError is the concrete type of ErrNoCachedConn, which @@ -569,6 +571,8 @@ type RoundTripOpt struct { // no cached connection is available, RoundTripOpt // will return ErrNoCachedConn. OnlyCachedConn bool + + allowHTTP bool // allow http:// URLs } func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error) { @@ -601,7 +605,14 @@ func authorityAddr(scheme string, authority string) (addr string) { // RoundTripOpt is like RoundTrip, but takes options. func (t *Transport) RoundTripOpt(req *http.Request, opt RoundTripOpt) (*http.Response, error) { - if !(req.URL.Scheme == "https" || (req.URL.Scheme == "http" && t.AllowHTTP)) { + switch req.URL.Scheme { + case "https": + // Always okay. + case "http": + if !t.AllowHTTP && !opt.allowHTTP { + return nil, errors.New("http2: unencrypted HTTP/2 not enabled") + } + default: return nil, errors.New("http2: unsupported scheme") } @@ -612,7 +623,7 @@ func (t *Transport) RoundTripOpt(req *http.Request, opt RoundTripOpt) (*http.Res t.vlogf("http2: Transport failed to get client conn for %s: %v", addr, err) return nil, err } - reused := !atomic.CompareAndSwapUint32(&cc.reused, 0, 1) + reused := !atomic.CompareAndSwapUint32(&cc.atomicReused, 0, 1) traceGotConn(req, cc, reused) res, err := cc.RoundTrip(req) if err != nil && retry <= 6 { @@ -626,21 +637,7 @@ func (t *Transport) RoundTripOpt(req *http.Request, opt RoundTripOpt) (*http.Res backoff := float64(uint(1) << (uint(retry) - 1)) backoff += backoff * (0.1 * mathrand.Float64()) d := time.Second * time.Duration(backoff) - var tm timer - if t.syncHooks != nil { - tm = t.syncHooks.newTimer(d) - t.syncHooks.blockUntil(func() bool { - select { - case <-tm.C(): - case <-req.Context().Done(): - default: - return false - } - return true - }) - } else { - tm = newTimeTimer(d) - } + tm := t.newTimer(d) select { case <-tm.C(): t.vlogf("RoundTrip retrying after failure: %v", roundTripErr) @@ -651,6 +648,22 @@ func (t *Transport) RoundTripOpt(req *http.Request, opt RoundTripOpt) (*http.Res } } } + if err == errClientConnNotEstablished { + // This ClientConn was created recently, + // this is the first request to use it, + // and the connection is closed and not usable. + // + // In this state, cc.idleTimer will remove the conn from the pool + // when it fires. Stop the timer and remove it here so future requests + // won't try to use this connection. + // + // If the timer has already fired and we're racing it, the redundant + // call to MarkDead is harmless. + if cc.idleTimer != nil { + cc.idleTimer.Stop() + } + t.connPool().MarkDead(cc) + } if err != nil { t.vlogf("RoundTrip failure: %v", err) return nil, err @@ -669,9 +682,10 @@ func (t *Transport) CloseIdleConnections() { } var ( - errClientConnClosed = errors.New("http2: client conn is closed") - errClientConnUnusable = errors.New("http2: client conn not usable") - errClientConnGotGoAway = errors.New("http2: Transport received Server's graceful shutdown GOAWAY") + errClientConnClosed = errors.New("http2: client conn is closed") + errClientConnUnusable = errors.New("http2: client conn not usable") + errClientConnNotEstablished = errors.New("http2: client conn could not be established") + errClientConnGotGoAway = errors.New("http2: Transport received Server's graceful shutdown GOAWAY") ) // shouldRetryRequest is called by RoundTrip when a request fails to get @@ -725,8 +739,8 @@ func canRetryError(err error) bool { } func (t *Transport) dialClientConn(ctx context.Context, addr string, singleUse bool) (*ClientConn, error) { - if t.syncHooks != nil { - return t.newClientConn(nil, singleUse, t.syncHooks) + if t.transportTestHooks != nil { + return t.newClientConn(nil, singleUse) } host, _, err := net.SplitHostPort(addr) if err != nil { @@ -736,7 +750,7 @@ func (t *Transport) dialClientConn(ctx context.Context, addr string, singleUse b if err != nil { return nil, err } - return t.newClientConn(tconn, singleUse, nil) + return t.newClientConn(tconn, singleUse) } func (t *Transport) newTLSConfig(host string) *tls.Config { @@ -787,48 +801,37 @@ func (t *Transport) expectContinueTimeout() time.Duration { return t.t1.ExpectContinueTimeout } -func (t *Transport) maxDecoderHeaderTableSize() uint32 { - if v := t.MaxDecoderHeaderTableSize; v > 0 { - return v - } - return initialHeaderTableSize -} - -func (t *Transport) maxEncoderHeaderTableSize() uint32 { - if v := t.MaxEncoderHeaderTableSize; v > 0 { - return v - } - return initialHeaderTableSize -} - func (t *Transport) NewClientConn(c net.Conn) (*ClientConn, error) { - return t.newClientConn(c, t.disableKeepAlives(), nil) + return t.newClientConn(c, t.disableKeepAlives()) } -func (t *Transport) newClientConn(c net.Conn, singleUse bool, hooks *testSyncHooks) (*ClientConn, error) { +func (t *Transport) newClientConn(c net.Conn, singleUse bool) (*ClientConn, error) { + conf := configFromTransport(t) cc := &ClientConn{ - t: t, - tconn: c, - readerDone: make(chan struct{}), - nextStreamID: 1, - maxFrameSize: 16 << 10, // spec default - initialWindowSize: 65535, // spec default - maxConcurrentStreams: initialMaxConcurrentStreams, // "infinite", per spec. Use a smaller value until we have received server settings. - peerMaxHeaderListSize: 0xffffffffffffffff, // "infinite", per spec. Use 2^64-1 instead. - streams: make(map[uint32]*clientStream), - singleUse: singleUse, - wantSettingsAck: true, - pings: make(map[[8]byte]chan struct{}), - reqHeaderMu: make(chan struct{}, 1), - syncHooks: hooks, - } - if hooks != nil { - hooks.newclientconn(cc) + t: t, + tconn: c, + readerDone: make(chan struct{}), + nextStreamID: 1, + maxFrameSize: 16 << 10, // spec default + initialWindowSize: 65535, // spec default + initialStreamRecvWindowSize: conf.MaxUploadBufferPerStream, + maxConcurrentStreams: initialMaxConcurrentStreams, // "infinite", per spec. Use a smaller value until we have received server settings. + peerMaxHeaderListSize: 0xffffffffffffffff, // "infinite", per spec. Use 2^64-1 instead. + streams: make(map[uint32]*clientStream), + singleUse: singleUse, + wantSettingsAck: true, + readIdleTimeout: conf.SendPingTimeout, + pingTimeout: conf.PingTimeout, + pings: make(map[[8]byte]chan struct{}), + reqHeaderMu: make(chan struct{}, 1), + lastActive: t.now(), + } + var group synctestGroupInterface + if t.transportTestHooks != nil { + t.markNewGoroutine() + t.transportTestHooks.newclientconn(cc) c = cc.tconn - } - if d := t.idleConnTimeout(); d != 0 { - cc.idleTimeout = d - cc.idleTimer = cc.afterFunc(d, cc.onIdleTimeout) + group = t.group } if VerboseLogs { t.vlogf("http2: Transport creating client conn %p to %v", cc, c.RemoteAddr()) @@ -840,30 +843,25 @@ func (t *Transport) newClientConn(c net.Conn, singleUse bool, hooks *testSyncHoo // TODO: adjust this writer size to account for frame size + // MTU + crypto/tls record padding. cc.bw = bufio.NewWriter(stickyErrWriter{ + group: group, conn: c, - timeout: t.WriteByteTimeout, + timeout: conf.WriteByteTimeout, err: &cc.werr, }) cc.br = bufio.NewReader(c) cc.fr = NewFramer(cc.bw, cc.br) - if t.maxFrameReadSize() != 0 { - cc.fr.SetMaxReadFrameSize(t.maxFrameReadSize()) - } + cc.fr.SetMaxReadFrameSize(conf.MaxReadFrameSize) if t.CountError != nil { cc.fr.countError = t.CountError } - maxHeaderTableSize := t.maxDecoderHeaderTableSize() + maxHeaderTableSize := conf.MaxDecoderHeaderTableSize cc.fr.ReadMetaHeaders = hpack.NewDecoder(maxHeaderTableSize, nil) cc.fr.MaxHeaderListSize = t.maxHeaderListSize() cc.henc = hpack.NewEncoder(&cc.hbuf) - cc.henc.SetMaxDynamicTableSizeLimit(t.maxEncoderHeaderTableSize()) + cc.henc.SetMaxDynamicTableSizeLimit(conf.MaxEncoderHeaderTableSize) cc.peerMaxHeaderTableSize = initialHeaderTableSize - if t.AllowHTTP { - cc.nextStreamID = 3 - } - if cs, ok := c.(connectionStater); ok { state := cs.ConnectionState() cc.tlsState = &state @@ -871,11 +869,9 @@ func (t *Transport) newClientConn(c net.Conn, singleUse bool, hooks *testSyncHoo initialSettings := []Setting{ {ID: SettingEnablePush, Val: 0}, - {ID: SettingInitialWindowSize, Val: transportDefaultStreamFlow}, - } - if max := t.maxFrameReadSize(); max != 0 { - initialSettings = append(initialSettings, Setting{ID: SettingMaxFrameSize, Val: max}) + {ID: SettingInitialWindowSize, Val: uint32(cc.initialStreamRecvWindowSize)}, } + initialSettings = append(initialSettings, Setting{ID: SettingMaxFrameSize, Val: conf.MaxReadFrameSize}) if max := t.maxHeaderListSize(); max != 0 { initialSettings = append(initialSettings, Setting{ID: SettingMaxHeaderListSize, Val: max}) } @@ -885,23 +881,29 @@ func (t *Transport) newClientConn(c net.Conn, singleUse bool, hooks *testSyncHoo cc.bw.Write(clientPreface) cc.fr.WriteSettings(initialSettings...) - cc.fr.WriteWindowUpdate(0, transportDefaultConnFlow) - cc.inflow.init(transportDefaultConnFlow + initialWindowSize) + cc.fr.WriteWindowUpdate(0, uint32(conf.MaxUploadBufferPerConnection)) + cc.inflow.init(conf.MaxUploadBufferPerConnection + initialWindowSize) cc.bw.Flush() if cc.werr != nil { cc.Close() return nil, cc.werr } - cc.goRun(cc.readLoop) + // Start the idle timer after the connection is fully initialized. + if d := t.idleConnTimeout(); d != 0 { + cc.idleTimeout = d + cc.idleTimer = t.afterFunc(d, cc.onIdleTimeout) + } + + go cc.readLoop() return cc, nil } func (cc *ClientConn) healthCheck() { - pingTimeout := cc.t.pingTimeout() + pingTimeout := cc.pingTimeout // We don't need to periodically ping in the health check, because the readLoop of ClientConn will // trigger the healthCheck again if there is no frame received. - ctx, cancel := cc.contextWithTimeout(context.Background(), pingTimeout) + ctx, cancel := cc.t.contextWithTimeout(context.Background(), pingTimeout) defer cancel() cc.vlogf("http2: Transport sending health check") err := cc.Ping(ctx) @@ -936,7 +938,20 @@ func (cc *ClientConn) setGoAway(f *GoAwayFrame) { } last := f.LastStreamID for streamID, cs := range cc.streams { - if streamID > last { + if streamID <= last { + // The server's GOAWAY indicates that it received this stream. + // It will either finish processing it, or close the connection + // without doing so. Either way, leave the stream alone for now. + continue + } + if streamID == 1 && cc.goAway.ErrCode != ErrCodeNo { + // Don't retry the first stream on a connection if we get a non-NO error. + // If the server is sending an error on a new connection, + // retrying the request on a new one probably isn't going to work. + cs.abortStreamLocked(fmt.Errorf("http2: Transport received GOAWAY from server ErrCode:%v", cc.goAway.ErrCode)) + } else { + // Aborting the stream with errClentConnGotGoAway indicates that + // the request should be retried on a new connection. cs.abortStreamLocked(errClientConnGotGoAway) } } @@ -1013,7 +1028,7 @@ func (cc *ClientConn) State() ClientConnState { return ClientConnState{ Closed: cc.closed, Closing: cc.closing || cc.singleUse || cc.doNotReuse || cc.goAway != nil, - StreamsActive: len(cc.streams), + StreamsActive: len(cc.streams) + cc.pendingResets, StreamsReserved: cc.streamsReserved, StreamsPending: cc.pendingRequests, LastIdle: cc.lastIdle, @@ -1045,16 +1060,38 @@ func (cc *ClientConn) idleStateLocked() (st clientConnIdleState) { // writing it. maxConcurrentOkay = true } else { - maxConcurrentOkay = int64(len(cc.streams)+cc.streamsReserved+1) <= int64(cc.maxConcurrentStreams) + // We can take a new request if the total of + // - active streams; + // - reservation slots for new streams; and + // - streams for which we have sent a RST_STREAM and a PING, + // but received no subsequent frame + // is less than the concurrency limit. + maxConcurrentOkay = cc.currentRequestCountLocked() < int(cc.maxConcurrentStreams) } st.canTakeNewRequest = cc.goAway == nil && !cc.closed && !cc.closing && maxConcurrentOkay && !cc.doNotReuse && int64(cc.nextStreamID)+2*int64(cc.pendingRequests) < math.MaxInt32 && !cc.tooIdleLocked() + + // If this connection has never been used for a request and is closed, + // then let it take a request (which will fail). + // + // This avoids a situation where an error early in a connection's lifetime + // goes unreported. + if cc.nextStreamID == 1 && cc.streamsReserved == 0 && cc.closed { + st.canTakeNewRequest = true + } + return } +// currentRequestCountLocked reports the number of concurrency slots currently in use, +// including active streams, reserved slots, and reset streams waiting for acknowledgement. +func (cc *ClientConn) currentRequestCountLocked() int { + return len(cc.streams) + cc.streamsReserved + cc.pendingResets +} + func (cc *ClientConn) canTakeNewRequestLocked() bool { st := cc.idleStateLocked() return st.canTakeNewRequest @@ -1067,7 +1104,7 @@ func (cc *ClientConn) tooIdleLocked() bool { // times are compared based on their wall time. We don't want // to reuse a connection that's been sitting idle during // VM/laptop suspend if monotonic time was also frozen. - return cc.idleTimeout != 0 && !cc.lastIdle.IsZero() && time.Since(cc.lastIdle.Round(0)) > cc.idleTimeout + return cc.idleTimeout != 0 && !cc.lastIdle.IsZero() && cc.t.timeSince(cc.lastIdle.Round(0)) > cc.idleTimeout } // onIdleTimeout is called from a time.AfterFunc goroutine. It will @@ -1131,7 +1168,8 @@ func (cc *ClientConn) Shutdown(ctx context.Context) error { // Wait for all in-flight streams to complete or connection to close done := make(chan struct{}) cancelled := false // guarded by cc.mu - cc.goRun(func() { + go func() { + cc.t.markNewGoroutine() cc.mu.Lock() defer cc.mu.Unlock() for { @@ -1143,9 +1181,9 @@ func (cc *ClientConn) Shutdown(ctx context.Context) error { if cancelled { break } - cc.condWait() + cc.cond.Wait() } - }) + }() shutdownEnterWaitStateHook() select { case <-done: @@ -1155,7 +1193,7 @@ func (cc *ClientConn) Shutdown(ctx context.Context) error { cc.mu.Lock() // Free the goroutine above cancelled = true - cc.condBroadcast() + cc.cond.Broadcast() cc.mu.Unlock() return ctx.Err() } @@ -1193,7 +1231,7 @@ func (cc *ClientConn) closeForError(err error) { for _, cs := range cc.streams { cs.abortStreamLocked(err) } - cc.condBroadcast() + cc.cond.Broadcast() cc.mu.Unlock() cc.closeConn() } @@ -1308,23 +1346,30 @@ func (cc *ClientConn) roundTrip(req *http.Request, streamf func(*clientStream)) respHeaderRecv: make(chan struct{}), donec: make(chan struct{}), } - cc.goRun(func() { - cs.doRequest(req) - }) + + // TODO(bradfitz): this is a copy of the logic in net/http. Unify somewhere? + if !cc.t.disableCompression() && + req.Header.Get("Accept-Encoding") == "" && + req.Header.Get("Range") == "" && + !cs.isHead { + // Request gzip only, not deflate. Deflate is ambiguous and + // not as universally supported anyway. + // See: https://zlib.net/zlib_faq.html#faq39 + // + // Note that we don't request this for HEAD requests, + // due to a bug in nginx: + // http://trac.nginx.org/nginx/ticket/358 + // https://golang.org/issue/5522 + // + // We don't request gzip if the request is for a range, since + // auto-decoding a portion of a gzipped document will just fail + // anyway. See https://golang.org/issue/8923 + cs.requestedGzip = true + } + + go cs.doRequest(req, streamf) waitDone := func() error { - if cc.syncHooks != nil { - cc.syncHooks.blockUntil(func() bool { - select { - case <-cs.donec: - case <-ctx.Done(): - case <-cs.reqCancel: - default: - return false - } - return true - }) - } select { case <-cs.donec: return nil @@ -1385,24 +1430,7 @@ func (cc *ClientConn) roundTrip(req *http.Request, streamf func(*clientStream)) return err } - if streamf != nil { - streamf(cs) - } - for { - if cc.syncHooks != nil { - cc.syncHooks.blockUntil(func() bool { - select { - case <-cs.respHeaderRecv: - case <-cs.abort: - case <-ctx.Done(): - case <-cs.reqCancel: - default: - return false - } - return true - }) - } select { case <-cs.respHeaderRecv: return handleResponseHeaders() @@ -1432,8 +1460,9 @@ func (cc *ClientConn) roundTrip(req *http.Request, streamf func(*clientStream)) // doRequest runs for the duration of the request lifetime. // // It sends the request and performs post-request cleanup (closing Request.Body, etc.). -func (cs *clientStream) doRequest(req *http.Request) { - err := cs.writeRequest(req) +func (cs *clientStream) doRequest(req *http.Request, streamf func(*clientStream)) { + cs.cc.t.markNewGoroutine() + err := cs.writeRequest(req, streamf) cs.cleanupWriteRequest(err) } @@ -1444,7 +1473,7 @@ func (cs *clientStream) doRequest(req *http.Request) { // // It returns non-nil if the request ends otherwise. // If the returned error is StreamError, the error Code may be used in resetting the stream. -func (cs *clientStream) writeRequest(req *http.Request) (err error) { +func (cs *clientStream) writeRequest(req *http.Request, streamf func(*clientStream)) (err error) { cc := cs.cc ctx := cs.ctx @@ -1458,21 +1487,6 @@ func (cs *clientStream) writeRequest(req *http.Request) (err error) { if cc.reqHeaderMu == nil { panic("RoundTrip on uninitialized ClientConn") // for tests } - var newStreamHook func(*clientStream) - if cc.syncHooks != nil { - newStreamHook = cc.syncHooks.newstream - cc.syncHooks.blockUntil(func() bool { - select { - case cc.reqHeaderMu <- struct{}{}: - <-cc.reqHeaderMu - case <-cs.reqCancel: - case <-ctx.Done(): - default: - return false - } - return true - }) - } select { case cc.reqHeaderMu <- struct{}{}: case <-cs.reqCancel: @@ -1497,28 +1511,8 @@ func (cs *clientStream) writeRequest(req *http.Request) (err error) { } cc.mu.Unlock() - if newStreamHook != nil { - newStreamHook(cs) - } - - // TODO(bradfitz): this is a copy of the logic in net/http. Unify somewhere? - if !cc.t.disableCompression() && - req.Header.Get("Accept-Encoding") == "" && - req.Header.Get("Range") == "" && - !cs.isHead { - // Request gzip only, not deflate. Deflate is ambiguous and - // not as universally supported anyway. - // See: https://zlib.net/zlib_faq.html#faq39 - // - // Note that we don't request this for HEAD requests, - // due to a bug in nginx: - // http://trac.nginx.org/nginx/ticket/358 - // https://golang.org/issue/5522 - // - // We don't request gzip if the request is for a range, since - // auto-decoding a portion of a gzipped document will just fail - // anyway. See https://golang.org/issue/8923 - cs.requestedGzip = true + if streamf != nil { + streamf(cs) } continueTimeout := cc.t.expectContinueTimeout() @@ -1581,7 +1575,7 @@ func (cs *clientStream) writeRequest(req *http.Request) (err error) { var respHeaderTimer <-chan time.Time var respHeaderRecv chan struct{} if d := cc.responseHeaderTimeout(); d != 0 { - timer := cc.newTimer(d) + timer := cc.t.newTimer(d) defer timer.Stop() respHeaderTimer = timer.C() respHeaderRecv = cs.respHeaderRecv @@ -1590,21 +1584,6 @@ func (cs *clientStream) writeRequest(req *http.Request) (err error) { // or until the request is aborted (via context, error, or otherwise), // whichever comes first. for { - if cc.syncHooks != nil { - cc.syncHooks.blockUntil(func() bool { - select { - case <-cs.peerClosed: - case <-respHeaderTimer: - case <-respHeaderRecv: - case <-cs.abort: - case <-ctx.Done(): - case <-cs.reqCancel: - default: - return false - } - return true - }) - } select { case <-cs.peerClosed: return nil @@ -1689,6 +1668,7 @@ func (cs *clientStream) cleanupWriteRequest(err error) { cs.reqBodyClosed = make(chan struct{}) } bodyClosed := cs.reqBodyClosed + closeOnIdle := cc.singleUse || cc.doNotReuse || cc.t.disableKeepAlives() || cc.goAway != nil cc.mu.Unlock() if mustCloseBody { cs.reqBody.Close() @@ -1713,16 +1693,40 @@ func (cs *clientStream) cleanupWriteRequest(err error) { if cs.sentHeaders { if se, ok := err.(StreamError); ok { if se.Cause != errFromPeer { - cc.writeStreamReset(cs.ID, se.Code, err) + cc.writeStreamReset(cs.ID, se.Code, false, err) } } else { - cc.writeStreamReset(cs.ID, ErrCodeCancel, err) + // We're cancelling an in-flight request. + // + // This could be due to the server becoming unresponsive. + // To avoid sending too many requests on a dead connection, + // we let the request continue to consume a concurrency slot + // until we can confirm the server is still responding. + // We do this by sending a PING frame along with the RST_STREAM + // (unless a ping is already in flight). + // + // For simplicity, we don't bother tracking the PING payload: + // We reset cc.pendingResets any time we receive a PING ACK. + // + // We skip this if the conn is going to be closed on idle, + // because it's short lived and will probably be closed before + // we get the ping response. + ping := false + if !closeOnIdle { + cc.mu.Lock() + if cc.pendingResets == 0 { + ping = true + } + cc.pendingResets++ + cc.mu.Unlock() + } + cc.writeStreamReset(cs.ID, ErrCodeCancel, ping, err) } } cs.bufPipe.CloseWithError(err) // no-op if already closed } else { if cs.sentHeaders && !cs.sentEndStream { - cc.writeStreamReset(cs.ID, ErrCodeNo, nil) + cc.writeStreamReset(cs.ID, ErrCodeNo, false, nil) } cs.bufPipe.CloseWithError(errRequestCanceled) } @@ -1744,16 +1748,21 @@ func (cs *clientStream) cleanupWriteRequest(err error) { // Must hold cc.mu. func (cc *ClientConn) awaitOpenSlotForStreamLocked(cs *clientStream) error { for { - cc.lastActive = time.Now() + if cc.closed && cc.nextStreamID == 1 && cc.streamsReserved == 0 { + // This is the very first request sent to this connection. + // Return a fatal error which aborts the retry loop. + return errClientConnNotEstablished + } + cc.lastActive = cc.t.now() if cc.closed || !cc.canTakeNewRequestLocked() { return errClientConnUnusable } cc.lastIdle = time.Time{} - if int64(len(cc.streams)) < int64(cc.maxConcurrentStreams) { + if cc.currentRequestCountLocked() < int(cc.maxConcurrentStreams) { return nil } cc.pendingRequests++ - cc.condWait() + cc.cond.Wait() cc.pendingRequests-- select { case <-cs.abort: @@ -2015,7 +2024,7 @@ func (cs *clientStream) awaitFlowControl(maxBytes int) (taken int32, err error) cs.flow.take(take) return take, nil } - cc.condWait() + cc.cond.Wait() } } @@ -2275,7 +2284,7 @@ type resAndError struct { func (cc *ClientConn) addStreamLocked(cs *clientStream) { cs.flow.add(int32(cc.initialWindowSize)) cs.flow.setConnFlow(&cc.flow) - cs.inflow.init(transportDefaultStreamFlow) + cs.inflow.init(cc.initialStreamRecvWindowSize) cs.ID = cc.nextStreamID cc.nextStreamID += 2 cc.streams[cs.ID] = cs @@ -2291,14 +2300,14 @@ func (cc *ClientConn) forgetStreamID(id uint32) { if len(cc.streams) != slen-1 { panic("forgetting unknown stream id") } - cc.lastActive = time.Now() + cc.lastActive = cc.t.now() if len(cc.streams) == 0 && cc.idleTimer != nil { cc.idleTimer.Reset(cc.idleTimeout) - cc.lastIdle = time.Now() + cc.lastIdle = cc.t.now() } // Wake up writeRequestBody via clientStream.awaitFlowControl and // wake up RoundTrip if there is a pending request. - cc.condBroadcast() + cc.cond.Broadcast() closeOnIdle := cc.singleUse || cc.doNotReuse || cc.t.disableKeepAlives() || cc.goAway != nil if closeOnIdle && cc.streamsReserved == 0 && len(cc.streams) == 0 { @@ -2320,6 +2329,7 @@ type clientConnReadLoop struct { // readLoop runs in its own goroutine and reads and dispatches frames. func (cc *ClientConn) readLoop() { + cc.t.markNewGoroutine() rl := &clientConnReadLoop{cc: cc} defer rl.cleanup() cc.readerErr = rl.run() @@ -2353,7 +2363,6 @@ func isEOFOrNetReadError(err error) bool { func (rl *clientConnReadLoop) cleanup() { cc := rl.cc - cc.t.connPool().MarkDead(cc) defer cc.closeConn() defer close(cc.readerDone) @@ -2377,6 +2386,24 @@ func (rl *clientConnReadLoop) cleanup() { } cc.closed = true + // If the connection has never been used, and has been open for only a short time, + // leave it in the connection pool for a little while. + // + // This avoids a situation where new connections are constantly created, + // added to the pool, fail, and are removed from the pool, without any error + // being surfaced to the user. + const unusedWaitTime = 5 * time.Second + idleTime := cc.t.now().Sub(cc.lastActive) + if atomic.LoadUint32(&cc.atomicReused) == 0 && idleTime < unusedWaitTime { + cc.idleTimer = cc.t.afterFunc(unusedWaitTime-idleTime, func() { + cc.t.connPool().MarkDead(cc) + }) + } else { + cc.mu.Unlock() // avoid any deadlocks in MarkDead + cc.t.connPool().MarkDead(cc) + cc.mu.Lock() + } + for _, cs := range cc.streams { select { case <-cs.peerClosed: @@ -2386,7 +2413,7 @@ func (rl *clientConnReadLoop) cleanup() { cs.abortStreamLocked(err) } } - cc.condBroadcast() + cc.cond.Broadcast() cc.mu.Unlock() } @@ -2420,10 +2447,10 @@ func (cc *ClientConn) countReadFrameError(err error) { func (rl *clientConnReadLoop) run() error { cc := rl.cc gotSettings := false - readIdleTimeout := cc.t.ReadIdleTimeout + readIdleTimeout := cc.readIdleTimeout var t timer if readIdleTimeout != 0 { - t = cc.afterFunc(readIdleTimeout, cc.healthCheck) + t = cc.t.afterFunc(readIdleTimeout, cc.healthCheck) } for { f, err := cc.fr.ReadFrame() @@ -2604,15 +2631,34 @@ func (rl *clientConnReadLoop) handleResponse(cs *clientStream, f *MetaHeadersFra if f.StreamEnded() { return nil, errors.New("1xx informational response with END_STREAM flag") } - cs.num1xx++ - const max1xxResponses = 5 // arbitrary bound on number of informational responses, same as net/http - if cs.num1xx > max1xxResponses { - return nil, errors.New("http2: too many 1xx informational responses") - } if fn := cs.get1xxTraceFunc(); fn != nil { + // If the 1xx response is being delivered to the user, + // then they're responsible for limiting the number + // of responses. if err := fn(statusCode, textproto.MIMEHeader(header)); err != nil { return nil, err } + } else { + // If the user didn't examine the 1xx response, then we + // limit the size of all 1xx headers. + // + // This differs a bit from the HTTP/1 implementation, which + // limits the size of all 1xx headers plus the final response. + // Use the larger limit of MaxHeaderListSize and + // net/http.Transport.MaxResponseHeaderBytes. + limit := int64(cs.cc.t.maxHeaderListSize()) + if t1 := cs.cc.t.t1; t1 != nil && t1.MaxResponseHeaderBytes > limit { + limit = t1.MaxResponseHeaderBytes + } + for _, h := range f.Fields { + cs.totalHeaderSize += int64(h.Size()) + } + if cs.totalHeaderSize > limit { + if VerboseLogs { + log.Printf("http2: 1xx informational responses too large") + } + return nil, errors.New("header list too large") + } } if statusCode == 100 { traceGot100Continue(cs.trace) @@ -3021,7 +3067,7 @@ func (rl *clientConnReadLoop) processSettingsNoWrite(f *SettingsFrame) error { for _, cs := range cc.streams { cs.flow.add(delta) } - cc.condBroadcast() + cc.cond.Broadcast() cc.initialWindowSize = s.Val case SettingHeaderTableSize: @@ -3076,7 +3122,7 @@ func (rl *clientConnReadLoop) processWindowUpdate(f *WindowUpdateFrame) error { return ConnectionError(ErrCodeFlowControl) } - cc.condBroadcast() + cc.cond.Broadcast() return nil } @@ -3120,7 +3166,8 @@ func (cc *ClientConn) Ping(ctx context.Context) error { } var pingError error errc := make(chan struct{}) - cc.goRun(func() { + go func() { + cc.t.markNewGoroutine() cc.wmu.Lock() defer cc.wmu.Unlock() if pingError = cc.fr.WritePing(false, p); pingError != nil { @@ -3131,20 +3178,7 @@ func (cc *ClientConn) Ping(ctx context.Context) error { close(errc) return } - }) - if cc.syncHooks != nil { - cc.syncHooks.blockUntil(func() bool { - select { - case <-c: - case <-errc: - case <-ctx.Done(): - case <-cc.readerDone: - default: - return false - } - return true - }) - } + }() select { case <-c: return nil @@ -3168,6 +3202,11 @@ func (rl *clientConnReadLoop) processPing(f *PingFrame) error { close(c) delete(cc.pings, f.Data) } + if cc.pendingResets > 0 { + // See clientStream.cleanupWriteRequest. + cc.pendingResets = 0 + cc.cond.Broadcast() + } return nil } cc := rl.cc @@ -3190,13 +3229,20 @@ func (rl *clientConnReadLoop) processPushPromise(f *PushPromiseFrame) error { return ConnectionError(ErrCodeProtocol) } -func (cc *ClientConn) writeStreamReset(streamID uint32, code ErrCode, err error) { +// writeStreamReset sends a RST_STREAM frame. +// When ping is true, it also sends a PING frame with a random payload. +func (cc *ClientConn) writeStreamReset(streamID uint32, code ErrCode, ping bool, err error) { // TODO: map err to more interesting error codes, once the // HTTP community comes up with some. But currently for // RST_STREAM there's no equivalent to GOAWAY frame's debug // data, and the error codes are all pretty vague ("cancel"). cc.wmu.Lock() cc.fr.WriteRSTStream(streamID, code) + if ping { + var payload [8]byte + rand.Read(payload[:]) + cc.fr.WritePing(false, payload) + } cc.bw.Flush() cc.wmu.Unlock() } @@ -3350,7 +3396,7 @@ func traceGotConn(req *http.Request, cc *ClientConn, reused bool) { cc.mu.Lock() ci.WasIdle = len(cc.streams) == 0 && reused if ci.WasIdle && !cc.lastActive.IsZero() { - ci.IdleTime = time.Since(cc.lastActive) + ci.IdleTime = cc.t.timeSince(cc.lastActive) } cc.mu.Unlock() diff --git a/vendor/golang.org/x/net/http2/unencrypted.go b/vendor/golang.org/x/net/http2/unencrypted.go new file mode 100644 index 000000000..b2de21161 --- /dev/null +++ b/vendor/golang.org/x/net/http2/unencrypted.go @@ -0,0 +1,32 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package http2 + +import ( + "crypto/tls" + "errors" + "net" +) + +const nextProtoUnencryptedHTTP2 = "unencrypted_http2" + +// unencryptedNetConnFromTLSConn retrieves a net.Conn wrapped in a *tls.Conn. +// +// TLSNextProto functions accept a *tls.Conn. +// +// When passing an unencrypted HTTP/2 connection to a TLSNextProto function, +// we pass a *tls.Conn with an underlying net.Conn containing the unencrypted connection. +// To be extra careful about mistakes (accidentally dropping TLS encryption in a place +// where we want it), the tls.Conn contains a net.Conn with an UnencryptedNetConn method +// that returns the actual connection we want to use. +func unencryptedNetConnFromTLSConn(tc *tls.Conn) (net.Conn, error) { + conner, ok := tc.NetConn().(interface { + UnencryptedNetConn() net.Conn + }) + if !ok { + return nil, errors.New("http2: TLS conn unexpectedly found in unencrypted handoff") + } + return conner.UnencryptedNetConn(), nil +} diff --git a/vendor/golang.org/x/net/http2/write.go b/vendor/golang.org/x/net/http2/write.go index 33f61398a..6ff6bee7e 100644 --- a/vendor/golang.org/x/net/http2/write.go +++ b/vendor/golang.org/x/net/http2/write.go @@ -131,6 +131,16 @@ func (se StreamError) writeFrame(ctx writeContext) error { func (se StreamError) staysWithinBuffer(max int) bool { return frameHeaderLen+4 <= max } +type writePing struct { + data [8]byte +} + +func (w writePing) writeFrame(ctx writeContext) error { + return ctx.Framer().WritePing(false, w.data) +} + +func (w writePing) staysWithinBuffer(max int) bool { return frameHeaderLen+len(w.data) <= max } + type writePingAck struct{ pf *PingFrame } func (w writePingAck) writeFrame(ctx writeContext) error { diff --git a/vendor/golang.org/x/net/http2/writesched_priority.go b/vendor/golang.org/x/net/http2/writesched_priority.go index 0a242c669..f6783339d 100644 --- a/vendor/golang.org/x/net/http2/writesched_priority.go +++ b/vendor/golang.org/x/net/http2/writesched_priority.go @@ -443,8 +443,8 @@ func (ws *priorityWriteScheduler) addClosedOrIdleNode(list *[]*priorityNode, max } func (ws *priorityWriteScheduler) removeNode(n *priorityNode) { - for k := n.kids; k != nil; k = k.next { - k.setParent(n.parent) + for n.kids != nil { + n.kids.setParent(n.parent) } n.setParent(nil) delete(ws.nodes, n.id) diff --git a/vendor/golang.org/x/net/internal/socket/zsys_openbsd_ppc64.go b/vendor/golang.org/x/net/internal/socket/zsys_openbsd_ppc64.go index cebde7634..3c9576e2d 100644 --- a/vendor/golang.org/x/net/internal/socket/zsys_openbsd_ppc64.go +++ b/vendor/golang.org/x/net/internal/socket/zsys_openbsd_ppc64.go @@ -4,27 +4,27 @@ package socket type iovec struct { - Base *byte - Len uint64 + Base *byte + Len uint64 } type msghdr struct { - Name *byte - Namelen uint32 - Iov *iovec - Iovlen uint32 - Control *byte - Controllen uint32 - Flags int32 + Name *byte + Namelen uint32 + Iov *iovec + Iovlen uint32 + Control *byte + Controllen uint32 + Flags int32 } type cmsghdr struct { - Len uint32 - Level int32 - Type int32 + Len uint32 + Level int32 + Type int32 } const ( - sizeofIovec = 0x10 - sizeofMsghdr = 0x30 + sizeofIovec = 0x10 + sizeofMsghdr = 0x30 ) diff --git a/vendor/golang.org/x/net/internal/socket/zsys_openbsd_riscv64.go b/vendor/golang.org/x/net/internal/socket/zsys_openbsd_riscv64.go index cebde7634..3c9576e2d 100644 --- a/vendor/golang.org/x/net/internal/socket/zsys_openbsd_riscv64.go +++ b/vendor/golang.org/x/net/internal/socket/zsys_openbsd_riscv64.go @@ -4,27 +4,27 @@ package socket type iovec struct { - Base *byte - Len uint64 + Base *byte + Len uint64 } type msghdr struct { - Name *byte - Namelen uint32 - Iov *iovec - Iovlen uint32 - Control *byte - Controllen uint32 - Flags int32 + Name *byte + Namelen uint32 + Iov *iovec + Iovlen uint32 + Control *byte + Controllen uint32 + Flags int32 } type cmsghdr struct { - Len uint32 - Level int32 - Type int32 + Len uint32 + Level int32 + Type int32 } const ( - sizeofIovec = 0x10 - sizeofMsghdr = 0x30 + sizeofIovec = 0x10 + sizeofMsghdr = 0x30 ) diff --git a/vendor/golang.org/x/oauth2/LICENSE b/vendor/golang.org/x/oauth2/LICENSE index 6a66aea5e..2a7cf70da 100644 --- a/vendor/golang.org/x/oauth2/LICENSE +++ b/vendor/golang.org/x/oauth2/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2009 The Go Authors. All rights reserved. +Copyright 2009 The Go Authors. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are @@ -10,7 +10,7 @@ notice, this list of conditions and the following disclaimer. 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 + * Neither the name of Google LLC nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. diff --git a/vendor/golang.org/x/oauth2/README.md b/vendor/golang.org/x/oauth2/README.md index 781770c20..48dbb9d84 100644 --- a/vendor/golang.org/x/oauth2/README.md +++ b/vendor/golang.org/x/oauth2/README.md @@ -5,15 +5,6 @@ oauth2 package contains a client implementation for OAuth 2.0 spec. -## Installation - -~~~~ -go get golang.org/x/oauth2 -~~~~ - -Or you can manually git clone the repository to -`$(go env GOPATH)/src/golang.org/x/oauth2`. - See pkg.go.dev for further documentation and examples. * [pkg.go.dev/golang.org/x/oauth2](https://pkg.go.dev/golang.org/x/oauth2) @@ -33,7 +24,11 @@ The main issue tracker for the oauth2 repository is located at https://github.com/golang/oauth2/issues. This repository uses Gerrit for code changes. To learn how to submit changes to -this repository, see https://golang.org/doc/contribute.html. In particular: +this repository, see https://go.dev/doc/contribute. + +The git repository is https://go.googlesource.com/oauth2. + +Note: * Excluding trivial changes, all contributions should be connected to an existing issue. * API changes must go through the [change proposal process](https://go.dev/s/proposal-process) before they can be accepted. diff --git a/vendor/golang.org/x/oauth2/internal/client_appengine.go b/vendor/golang.org/x/oauth2/internal/client_appengine.go deleted file mode 100644 index d28140f78..000000000 --- a/vendor/golang.org/x/oauth2/internal/client_appengine.go +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build appengine - -package internal - -import "google.golang.org/appengine/urlfetch" - -func init() { - appengineClientHook = urlfetch.Client -} diff --git a/vendor/golang.org/x/oauth2/internal/transport.go b/vendor/golang.org/x/oauth2/internal/transport.go index 572074a63..b9db01ddf 100644 --- a/vendor/golang.org/x/oauth2/internal/transport.go +++ b/vendor/golang.org/x/oauth2/internal/transport.go @@ -18,16 +18,11 @@ var HTTPClient ContextKey // because nobody else can create a ContextKey, being unexported. type ContextKey struct{} -var appengineClientHook func(context.Context) *http.Client - func ContextClient(ctx context.Context) *http.Client { if ctx != nil { if hc, ok := ctx.Value(HTTPClient).(*http.Client); ok { return hc } } - if appengineClientHook != nil { - return appengineClientHook(ctx) - } return http.DefaultClient } diff --git a/vendor/golang.org/x/oauth2/oauth2.go b/vendor/golang.org/x/oauth2/oauth2.go index 90a2c3d6d..09f6a49b8 100644 --- a/vendor/golang.org/x/oauth2/oauth2.go +++ b/vendor/golang.org/x/oauth2/oauth2.go @@ -393,7 +393,7 @@ func ReuseTokenSource(t *Token, src TokenSource) TokenSource { } } -// ReuseTokenSource returns a TokenSource that acts in the same manner as the +// ReuseTokenSourceWithExpiry returns a TokenSource that acts in the same manner as the // TokenSource returned by ReuseTokenSource, except the expiry buffer is // configurable. The expiration time of a token is calculated as // t.Expiry.Add(-earlyExpiry). diff --git a/vendor/golang.org/x/oauth2/token.go b/vendor/golang.org/x/oauth2/token.go index 5bbb33217..109997d77 100644 --- a/vendor/golang.org/x/oauth2/token.go +++ b/vendor/golang.org/x/oauth2/token.go @@ -49,6 +49,13 @@ type Token struct { // mechanisms for that TokenSource will not be used. Expiry time.Time `json:"expiry,omitempty"` + // ExpiresIn is the OAuth2 wire format "expires_in" field, + // which specifies how many seconds later the token expires, + // relative to an unknown time base approximately around "now". + // It is the application's responsibility to populate + // `Expiry` from `ExpiresIn` when required. + ExpiresIn int64 `json:"expires_in,omitempty"` + // raw optionally contains extra metadata from the server // when updating a token. raw interface{} diff --git a/vendor/golang.org/x/sync/LICENSE b/vendor/golang.org/x/sync/LICENSE new file mode 100644 index 000000000..2a7cf70da --- /dev/null +++ b/vendor/golang.org/x/sync/LICENSE @@ -0,0 +1,27 @@ +Copyright 2009 The Go Authors. + +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 LLC 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. diff --git a/vendor/golang.org/x/sync/PATENTS b/vendor/golang.org/x/sync/PATENTS new file mode 100644 index 000000000..733099041 --- /dev/null +++ b/vendor/golang.org/x/sync/PATENTS @@ -0,0 +1,22 @@ +Additional IP Rights Grant (Patents) + +"This implementation" means the copyrightable works distributed by +Google as part of the Go project. + +Google 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, +transfer and otherwise run, modify and propagate the contents of this +implementation of Go, where such license applies only to those patent +claims, both currently owned or controlled by Google and acquired in +the future, licensable by Google that are necessarily infringed by this +implementation of Go. This grant does not include claims that would be +infringed only as a consequence of further modification of this +implementation. If you or your agent or exclusive licensee institute or +order or agree to the institution of patent litigation against any +entity (including a cross-claim or counterclaim in a lawsuit) alleging +that this implementation of Go or any code incorporated within this +implementation of Go constitutes direct or contributory patent +infringement, or inducement of patent infringement, then any patent +rights granted to you under this License for this implementation of Go +shall terminate as of the date such litigation is filed. diff --git a/vendor/golang.org/x/sync/errgroup/errgroup.go b/vendor/golang.org/x/sync/errgroup/errgroup.go new file mode 100644 index 000000000..948a3ee63 --- /dev/null +++ b/vendor/golang.org/x/sync/errgroup/errgroup.go @@ -0,0 +1,135 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package errgroup provides synchronization, error propagation, and Context +// cancelation for groups of goroutines working on subtasks of a common task. +// +// [errgroup.Group] is related to [sync.WaitGroup] but adds handling of tasks +// returning errors. +package errgroup + +import ( + "context" + "fmt" + "sync" +) + +type token struct{} + +// A Group is a collection of goroutines working on subtasks that are part of +// the same overall task. +// +// A zero Group is valid, has no limit on the number of active goroutines, +// and does not cancel on error. +type Group struct { + cancel func(error) + + wg sync.WaitGroup + + sem chan token + + errOnce sync.Once + err error +} + +func (g *Group) done() { + if g.sem != nil { + <-g.sem + } + g.wg.Done() +} + +// WithContext returns a new Group and an associated Context derived from ctx. +// +// The derived Context is canceled the first time a function passed to Go +// returns a non-nil error or the first time Wait returns, whichever occurs +// first. +func WithContext(ctx context.Context) (*Group, context.Context) { + ctx, cancel := withCancelCause(ctx) + return &Group{cancel: cancel}, ctx +} + +// Wait blocks until all function calls from the Go method have returned, then +// returns the first non-nil error (if any) from them. +func (g *Group) Wait() error { + g.wg.Wait() + if g.cancel != nil { + g.cancel(g.err) + } + return g.err +} + +// Go calls the given function in a new goroutine. +// It blocks until the new goroutine can be added without the number of +// active goroutines in the group exceeding the configured limit. +// +// The first call to return a non-nil error cancels the group's context, if the +// group was created by calling WithContext. The error will be returned by Wait. +func (g *Group) Go(f func() error) { + if g.sem != nil { + g.sem <- token{} + } + + g.wg.Add(1) + go func() { + defer g.done() + + if err := f(); err != nil { + g.errOnce.Do(func() { + g.err = err + if g.cancel != nil { + g.cancel(g.err) + } + }) + } + }() +} + +// TryGo calls the given function in a new goroutine only if the number of +// active goroutines in the group is currently below the configured limit. +// +// The return value reports whether the goroutine was started. +func (g *Group) TryGo(f func() error) bool { + if g.sem != nil { + select { + case g.sem <- token{}: + // Note: this allows barging iff channels in general allow barging. + default: + return false + } + } + + g.wg.Add(1) + go func() { + defer g.done() + + if err := f(); err != nil { + g.errOnce.Do(func() { + g.err = err + if g.cancel != nil { + g.cancel(g.err) + } + }) + } + }() + return true +} + +// SetLimit limits the number of active goroutines in this group to at most n. +// A negative value indicates no limit. +// +// Any subsequent call to the Go method will block until it can add an active +// goroutine without exceeding the configured limit. +// +// The limit must not be modified while any goroutines in the group are active. +func (g *Group) SetLimit(n int) { + if n < 0 { + g.sem = nil + return + } + if len(g.sem) != 0 { + panic(fmt.Errorf("errgroup: modify limit while %v goroutines in the group are still active", len(g.sem))) + } + g.sem = make(chan token, n) +} diff --git a/vendor/golang.org/x/sync/errgroup/go120.go b/vendor/golang.org/x/sync/errgroup/go120.go new file mode 100644 index 000000000..f93c740b6 --- /dev/null +++ b/vendor/golang.org/x/sync/errgroup/go120.go @@ -0,0 +1,13 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build go1.20 + +package errgroup + +import "context" + +func withCancelCause(parent context.Context) (context.Context, func(error)) { + return context.WithCancelCause(parent) +} diff --git a/vendor/golang.org/x/sync/errgroup/pre_go120.go b/vendor/golang.org/x/sync/errgroup/pre_go120.go new file mode 100644 index 000000000..88ce33434 --- /dev/null +++ b/vendor/golang.org/x/sync/errgroup/pre_go120.go @@ -0,0 +1,14 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !go1.20 + +package errgroup + +import "context" + +func withCancelCause(parent context.Context) (context.Context, func(error)) { + ctx, cancel := context.WithCancel(parent) + return ctx, func(error) { cancel() } +} diff --git a/vendor/golang.org/x/sys/LICENSE b/vendor/golang.org/x/sys/LICENSE index 6a66aea5e..2a7cf70da 100644 --- a/vendor/golang.org/x/sys/LICENSE +++ b/vendor/golang.org/x/sys/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2009 The Go Authors. All rights reserved. +Copyright 2009 The Go Authors. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are @@ -10,7 +10,7 @@ notice, this list of conditions and the following disclaimer. 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 + * Neither the name of Google LLC nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. diff --git a/vendor/golang.org/x/sys/cpu/asm_darwin_x86_gc.s b/vendor/golang.org/x/sys/cpu/asm_darwin_x86_gc.s new file mode 100644 index 000000000..ec2acfe54 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/asm_darwin_x86_gc.s @@ -0,0 +1,17 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build darwin && amd64 && gc + +#include "textflag.h" + +TEXT libc_sysctl_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_sysctl(SB) +GLOBL ·libc_sysctl_trampoline_addr(SB), RODATA, $8 +DATA ·libc_sysctl_trampoline_addr(SB)/8, $libc_sysctl_trampoline<>(SB) + +TEXT libc_sysctlbyname_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_sysctlbyname(SB) +GLOBL ·libc_sysctlbyname_trampoline_addr(SB), RODATA, $8 +DATA ·libc_sysctlbyname_trampoline_addr(SB)/8, $libc_sysctlbyname_trampoline<>(SB) diff --git a/vendor/golang.org/x/sys/cpu/cpu.go b/vendor/golang.org/x/sys/cpu/cpu.go index 4756ad5f7..02609d5b2 100644 --- a/vendor/golang.org/x/sys/cpu/cpu.go +++ b/vendor/golang.org/x/sys/cpu/cpu.go @@ -103,7 +103,10 @@ var ARM64 struct { HasASIMDDP bool // Advanced SIMD double precision instruction set HasSHA512 bool // SHA512 hardware implementation HasSVE bool // Scalable Vector Extensions + HasSVE2 bool // Scalable Vector Extensions 2 HasASIMDFHM bool // Advanced SIMD multiplication FP16 to FP32 + HasDIT bool // Data Independent Timing support + HasI8MM bool // Advanced SIMD Int8 matrix multiplication instructions _ CacheLinePad } @@ -198,6 +201,25 @@ var S390X struct { _ CacheLinePad } +// RISCV64 contains the supported CPU features and performance characteristics for riscv64 +// platforms. The booleans in RISCV64, with the exception of HasFastMisaligned, indicate +// the presence of RISC-V extensions. +// +// It is safe to assume that all the RV64G extensions are supported and so they are omitted from +// this structure. As riscv64 Go programs require at least RV64G, the code that populates +// this structure cannot run successfully if some of the RV64G extensions are missing. +// The struct is padded to avoid false sharing. +var RISCV64 struct { + _ CacheLinePad + HasFastMisaligned bool // Fast misaligned accesses + HasC bool // Compressed instruction-set extension + HasV bool // Vector extension compatible with RVV 1.0 + HasZba bool // Address generation instructions extension + HasZbb bool // Basic bit-manipulation extension + HasZbs bool // Single-bit instructions extension + _ CacheLinePad +} + func init() { archInit() initOptions() diff --git a/vendor/golang.org/x/sys/cpu/cpu_arm64.go b/vendor/golang.org/x/sys/cpu/cpu_arm64.go index f3eb993bf..af2aa99f9 100644 --- a/vendor/golang.org/x/sys/cpu/cpu_arm64.go +++ b/vendor/golang.org/x/sys/cpu/cpu_arm64.go @@ -28,6 +28,7 @@ func initOptions() { {Name: "sm3", Feature: &ARM64.HasSM3}, {Name: "sm4", Feature: &ARM64.HasSM4}, {Name: "sve", Feature: &ARM64.HasSVE}, + {Name: "sve2", Feature: &ARM64.HasSVE2}, {Name: "crc32", Feature: &ARM64.HasCRC32}, {Name: "atomics", Feature: &ARM64.HasATOMICS}, {Name: "asimdhp", Feature: &ARM64.HasASIMDHP}, @@ -37,6 +38,8 @@ func initOptions() { {Name: "dcpop", Feature: &ARM64.HasDCPOP}, {Name: "asimddp", Feature: &ARM64.HasASIMDDP}, {Name: "asimdfhm", Feature: &ARM64.HasASIMDFHM}, + {Name: "dit", Feature: &ARM64.HasDIT}, + {Name: "i8mm", Feature: &ARM64.HasI8MM}, } } @@ -144,6 +147,11 @@ func parseARM64SystemRegisters(isar0, isar1, pfr0 uint64) { ARM64.HasLRCPC = true } + switch extractBits(isar1, 52, 55) { + case 1: + ARM64.HasI8MM = true + } + // ID_AA64PFR0_EL1 switch extractBits(pfr0, 16, 19) { case 0: @@ -164,6 +172,20 @@ func parseARM64SystemRegisters(isar0, isar1, pfr0 uint64) { switch extractBits(pfr0, 32, 35) { case 1: ARM64.HasSVE = true + + parseARM64SVERegister(getzfr0()) + } + + switch extractBits(pfr0, 48, 51) { + case 1: + ARM64.HasDIT = true + } +} + +func parseARM64SVERegister(zfr0 uint64) { + switch extractBits(zfr0, 0, 3) { + case 1: + ARM64.HasSVE2 = true } } diff --git a/vendor/golang.org/x/sys/cpu/cpu_arm64.s b/vendor/golang.org/x/sys/cpu/cpu_arm64.s index fcb9a3888..22cc99844 100644 --- a/vendor/golang.org/x/sys/cpu/cpu_arm64.s +++ b/vendor/golang.org/x/sys/cpu/cpu_arm64.s @@ -29,3 +29,11 @@ TEXT ·getpfr0(SB),NOSPLIT,$0-8 WORD $0xd5380400 MOVD R0, ret+0(FP) RET + +// func getzfr0() uint64 +TEXT ·getzfr0(SB),NOSPLIT,$0-8 + // get SVE Feature Register 0 into x0 + // mrs x0, ID_AA64ZFR0_EL1 = d5380480 + WORD $0xd5380480 + MOVD R0, ret+0(FP) + RET diff --git a/vendor/golang.org/x/sys/cpu/cpu_darwin_x86.go b/vendor/golang.org/x/sys/cpu/cpu_darwin_x86.go new file mode 100644 index 000000000..b838cb9e9 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_darwin_x86.go @@ -0,0 +1,61 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build darwin && amd64 && gc + +package cpu + +// darwinSupportsAVX512 checks Darwin kernel for AVX512 support via sysctl +// call (see issue 43089). It also restricts AVX512 support for Darwin to +// kernel version 21.3.0 (MacOS 12.2.0) or later (see issue 49233). +// +// Background: +// Darwin implements a special mechanism to economize on thread state when +// AVX512 specific registers are not in use. This scheme minimizes state when +// preempting threads that haven't yet used any AVX512 instructions, but adds +// special requirements to check for AVX512 hardware support at runtime (e.g. +// via sysctl call or commpage inspection). See issue 43089 and link below for +// full background: +// https://github.com/apple-oss-distributions/xnu/blob/xnu-11215.1.10/osfmk/i386/fpu.c#L214-L240 +// +// Additionally, all versions of the Darwin kernel from 19.6.0 through 21.2.0 +// (corresponding to MacOS 10.15.6 - 12.1) have a bug that can cause corruption +// of the AVX512 mask registers (K0-K7) upon signal return. For this reason +// AVX512 is considered unsafe to use on Darwin for kernel versions prior to +// 21.3.0, where a fix has been confirmed. See issue 49233 for full background. +func darwinSupportsAVX512() bool { + return darwinSysctlEnabled([]byte("hw.optional.avx512f\x00")) && darwinKernelVersionCheck(21, 3, 0) +} + +// Ensure Darwin kernel version is at least major.minor.patch, avoiding dependencies +func darwinKernelVersionCheck(major, minor, patch int) bool { + var release [256]byte + err := darwinOSRelease(&release) + if err != nil { + return false + } + + var mmp [3]int + c := 0 +Loop: + for _, b := range release[:] { + switch { + case b >= '0' && b <= '9': + mmp[c] = 10*mmp[c] + int(b-'0') + case b == '.': + c++ + if c > 2 { + return false + } + case b == 0: + break Loop + default: + return false + } + } + if c != 2 { + return false + } + return mmp[0] > major || mmp[0] == major && (mmp[1] > minor || mmp[1] == minor && mmp[2] >= patch) +} diff --git a/vendor/golang.org/x/sys/cpu/cpu_gc_arm64.go b/vendor/golang.org/x/sys/cpu/cpu_gc_arm64.go index a8acd3e32..6ac6e1efb 100644 --- a/vendor/golang.org/x/sys/cpu/cpu_gc_arm64.go +++ b/vendor/golang.org/x/sys/cpu/cpu_gc_arm64.go @@ -9,3 +9,4 @@ package cpu func getisar0() uint64 func getisar1() uint64 func getpfr0() uint64 +func getzfr0() uint64 diff --git a/vendor/golang.org/x/sys/cpu/cpu_gc_x86.go b/vendor/golang.org/x/sys/cpu/cpu_gc_x86.go index 910728fb1..32a44514e 100644 --- a/vendor/golang.org/x/sys/cpu/cpu_gc_x86.go +++ b/vendor/golang.org/x/sys/cpu/cpu_gc_x86.go @@ -6,10 +6,10 @@ package cpu -// cpuid is implemented in cpu_x86.s for gc compiler +// cpuid is implemented in cpu_gc_x86.s for gc compiler // and in cpu_gccgo.c for gccgo. func cpuid(eaxArg, ecxArg uint32) (eax, ebx, ecx, edx uint32) -// xgetbv with ecx = 0 is implemented in cpu_x86.s for gc compiler +// xgetbv with ecx = 0 is implemented in cpu_gc_x86.s for gc compiler // and in cpu_gccgo.c for gccgo. func xgetbv() (eax, edx uint32) diff --git a/vendor/golang.org/x/sys/cpu/cpu_x86.s b/vendor/golang.org/x/sys/cpu/cpu_gc_x86.s similarity index 94% rename from vendor/golang.org/x/sys/cpu/cpu_x86.s rename to vendor/golang.org/x/sys/cpu/cpu_gc_x86.s index 7d7ba33ef..ce208ce6d 100644 --- a/vendor/golang.org/x/sys/cpu/cpu_x86.s +++ b/vendor/golang.org/x/sys/cpu/cpu_gc_x86.s @@ -18,7 +18,7 @@ TEXT ·cpuid(SB), NOSPLIT, $0-24 RET // func xgetbv() (eax, edx uint32) -TEXT ·xgetbv(SB),NOSPLIT,$0-8 +TEXT ·xgetbv(SB), NOSPLIT, $0-8 MOVL $0, CX XGETBV MOVL AX, eax+0(FP) diff --git a/vendor/golang.org/x/sys/cpu/cpu_gccgo_x86.go b/vendor/golang.org/x/sys/cpu/cpu_gccgo_x86.go index 99c60fe9f..170d21ddf 100644 --- a/vendor/golang.org/x/sys/cpu/cpu_gccgo_x86.go +++ b/vendor/golang.org/x/sys/cpu/cpu_gccgo_x86.go @@ -23,9 +23,3 @@ func xgetbv() (eax, edx uint32) { gccgoXgetbv(&a, &d) return a, d } - -// gccgo doesn't build on Darwin, per: -// https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/gcc.rb#L76 -func darwinSupportsAVX512() bool { - return false -} diff --git a/vendor/golang.org/x/sys/cpu/cpu_linux_arm64.go b/vendor/golang.org/x/sys/cpu/cpu_linux_arm64.go index a968b80fa..f1caf0f78 100644 --- a/vendor/golang.org/x/sys/cpu/cpu_linux_arm64.go +++ b/vendor/golang.org/x/sys/cpu/cpu_linux_arm64.go @@ -35,6 +35,10 @@ const ( hwcap_SHA512 = 1 << 21 hwcap_SVE = 1 << 22 hwcap_ASIMDFHM = 1 << 23 + hwcap_DIT = 1 << 24 + + hwcap2_SVE2 = 1 << 1 + hwcap2_I8MM = 1 << 13 ) // linuxKernelCanEmulateCPUID reports whether we're running @@ -104,6 +108,11 @@ func doinit() { ARM64.HasSHA512 = isSet(hwCap, hwcap_SHA512) ARM64.HasSVE = isSet(hwCap, hwcap_SVE) ARM64.HasASIMDFHM = isSet(hwCap, hwcap_ASIMDFHM) + ARM64.HasDIT = isSet(hwCap, hwcap_DIT) + + // HWCAP2 feature bits + ARM64.HasSVE2 = isSet(hwCap2, hwcap2_SVE2) + ARM64.HasI8MM = isSet(hwCap2, hwcap2_I8MM) } func isSet(hwc uint, value uint) bool { diff --git a/vendor/golang.org/x/sys/cpu/cpu_linux_noinit.go b/vendor/golang.org/x/sys/cpu/cpu_linux_noinit.go index cd63e7335..7d902b684 100644 --- a/vendor/golang.org/x/sys/cpu/cpu_linux_noinit.go +++ b/vendor/golang.org/x/sys/cpu/cpu_linux_noinit.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build linux && !arm && !arm64 && !mips64 && !mips64le && !ppc64 && !ppc64le && !s390x +//go:build linux && !arm && !arm64 && !mips64 && !mips64le && !ppc64 && !ppc64le && !s390x && !riscv64 package cpu diff --git a/vendor/golang.org/x/sys/cpu/cpu_linux_riscv64.go b/vendor/golang.org/x/sys/cpu/cpu_linux_riscv64.go new file mode 100644 index 000000000..cb4a0c572 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_linux_riscv64.go @@ -0,0 +1,137 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cpu + +import ( + "syscall" + "unsafe" +) + +// RISC-V extension discovery code for Linux. The approach here is to first try the riscv_hwprobe +// syscall falling back to HWCAP to check for the C extension if riscv_hwprobe is not available. +// +// A note on detection of the Vector extension using HWCAP. +// +// Support for the Vector extension version 1.0 was added to the Linux kernel in release 6.5. +// Support for the riscv_hwprobe syscall was added in 6.4. It follows that if the riscv_hwprobe +// syscall is not available then neither is the Vector extension (which needs kernel support). +// The riscv_hwprobe syscall should then be all we need to detect the Vector extension. +// However, some RISC-V board manufacturers ship boards with an older kernel on top of which +// they have back-ported various versions of the Vector extension patches but not the riscv_hwprobe +// patches. These kernels advertise support for the Vector extension using HWCAP. Falling +// back to HWCAP to detect the Vector extension, if riscv_hwprobe is not available, or simply not +// bothering with riscv_hwprobe at all and just using HWCAP may then seem like an attractive option. +// +// Unfortunately, simply checking the 'V' bit in AT_HWCAP will not work as this bit is used by +// RISC-V board and cloud instance providers to mean different things. The Lichee Pi 4A board +// and the Scaleway RV1 cloud instances use the 'V' bit to advertise their support for the unratified +// 0.7.1 version of the Vector Specification. The Banana Pi BPI-F3 and the CanMV-K230 board use +// it to advertise support for 1.0 of the Vector extension. Versions 0.7.1 and 1.0 of the Vector +// extension are binary incompatible. HWCAP can then not be used in isolation to populate the +// HasV field as this field indicates that the underlying CPU is compatible with RVV 1.0. +// +// There is a way at runtime to distinguish between versions 0.7.1 and 1.0 of the Vector +// specification by issuing a RVV 1.0 vsetvli instruction and checking the vill bit of the vtype +// register. This check would allow us to safely detect version 1.0 of the Vector extension +// with HWCAP, if riscv_hwprobe were not available. However, the check cannot +// be added until the assembler supports the Vector instructions. +// +// Note the riscv_hwprobe syscall does not suffer from these ambiguities by design as all of the +// extensions it advertises support for are explicitly versioned. It's also worth noting that +// the riscv_hwprobe syscall is the only way to detect multi-letter RISC-V extensions, e.g., Zba. +// These cannot be detected using HWCAP and so riscv_hwprobe must be used to detect the majority +// of RISC-V extensions. +// +// Please see https://docs.kernel.org/arch/riscv/hwprobe.html for more information. + +// golang.org/x/sys/cpu is not allowed to depend on golang.org/x/sys/unix so we must +// reproduce the constants, types and functions needed to make the riscv_hwprobe syscall +// here. + +const ( + // Copied from golang.org/x/sys/unix/ztypes_linux_riscv64.go. + riscv_HWPROBE_KEY_IMA_EXT_0 = 0x4 + riscv_HWPROBE_IMA_C = 0x2 + riscv_HWPROBE_IMA_V = 0x4 + riscv_HWPROBE_EXT_ZBA = 0x8 + riscv_HWPROBE_EXT_ZBB = 0x10 + riscv_HWPROBE_EXT_ZBS = 0x20 + riscv_HWPROBE_KEY_CPUPERF_0 = 0x5 + riscv_HWPROBE_MISALIGNED_FAST = 0x3 + riscv_HWPROBE_MISALIGNED_MASK = 0x7 +) + +const ( + // sys_RISCV_HWPROBE is copied from golang.org/x/sys/unix/zsysnum_linux_riscv64.go. + sys_RISCV_HWPROBE = 258 +) + +// riscvHWProbePairs is copied from golang.org/x/sys/unix/ztypes_linux_riscv64.go. +type riscvHWProbePairs struct { + key int64 + value uint64 +} + +const ( + // CPU features + hwcap_RISCV_ISA_C = 1 << ('C' - 'A') +) + +func doinit() { + // A slice of key/value pair structures is passed to the RISCVHWProbe syscall. The key + // field should be initialised with one of the key constants defined above, e.g., + // RISCV_HWPROBE_KEY_IMA_EXT_0. The syscall will set the value field to the appropriate value. + // If the kernel does not recognise a key it will set the key field to -1 and the value field to 0. + + pairs := []riscvHWProbePairs{ + {riscv_HWPROBE_KEY_IMA_EXT_0, 0}, + {riscv_HWPROBE_KEY_CPUPERF_0, 0}, + } + + // This call only indicates that extensions are supported if they are implemented on all cores. + if riscvHWProbe(pairs, 0) { + if pairs[0].key != -1 { + v := uint(pairs[0].value) + RISCV64.HasC = isSet(v, riscv_HWPROBE_IMA_C) + RISCV64.HasV = isSet(v, riscv_HWPROBE_IMA_V) + RISCV64.HasZba = isSet(v, riscv_HWPROBE_EXT_ZBA) + RISCV64.HasZbb = isSet(v, riscv_HWPROBE_EXT_ZBB) + RISCV64.HasZbs = isSet(v, riscv_HWPROBE_EXT_ZBS) + } + if pairs[1].key != -1 { + v := pairs[1].value & riscv_HWPROBE_MISALIGNED_MASK + RISCV64.HasFastMisaligned = v == riscv_HWPROBE_MISALIGNED_FAST + } + } + + // Let's double check with HWCAP if the C extension does not appear to be supported. + // This may happen if we're running on a kernel older than 6.4. + + if !RISCV64.HasC { + RISCV64.HasC = isSet(hwCap, hwcap_RISCV_ISA_C) + } +} + +func isSet(hwc uint, value uint) bool { + return hwc&value != 0 +} + +// riscvHWProbe is a simplified version of the generated wrapper function found in +// golang.org/x/sys/unix/zsyscall_linux_riscv64.go. We simplify it by removing the +// cpuCount and cpus parameters which we do not need. We always want to pass 0 for +// these parameters here so the kernel only reports the extensions that are present +// on all cores. +func riscvHWProbe(pairs []riscvHWProbePairs, flags uint) bool { + var _zero uintptr + var p0 unsafe.Pointer + if len(pairs) > 0 { + p0 = unsafe.Pointer(&pairs[0]) + } else { + p0 = unsafe.Pointer(&_zero) + } + + _, _, e1 := syscall.Syscall6(sys_RISCV_HWPROBE, uintptr(p0), uintptr(len(pairs)), uintptr(0), uintptr(0), uintptr(flags), 0) + return e1 == 0 +} diff --git a/vendor/golang.org/x/sys/cpu/cpu_other_x86.go b/vendor/golang.org/x/sys/cpu/cpu_other_x86.go new file mode 100644 index 000000000..a0fd7e2f7 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_other_x86.go @@ -0,0 +1,11 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build 386 || amd64p32 || (amd64 && (!darwin || !gc)) + +package cpu + +func darwinSupportsAVX512() bool { + panic("only implemented for gc && amd64 && darwin") +} diff --git a/vendor/golang.org/x/sys/cpu/cpu_riscv64.go b/vendor/golang.org/x/sys/cpu/cpu_riscv64.go index 7f0c79c00..aca3199c9 100644 --- a/vendor/golang.org/x/sys/cpu/cpu_riscv64.go +++ b/vendor/golang.org/x/sys/cpu/cpu_riscv64.go @@ -8,4 +8,13 @@ package cpu const cacheLineSize = 64 -func initOptions() {} +func initOptions() { + options = []option{ + {Name: "fastmisaligned", Feature: &RISCV64.HasFastMisaligned}, + {Name: "c", Feature: &RISCV64.HasC}, + {Name: "v", Feature: &RISCV64.HasV}, + {Name: "zba", Feature: &RISCV64.HasZba}, + {Name: "zbb", Feature: &RISCV64.HasZbb}, + {Name: "zbs", Feature: &RISCV64.HasZbs}, + } +} diff --git a/vendor/golang.org/x/sys/cpu/cpu_x86.go b/vendor/golang.org/x/sys/cpu/cpu_x86.go index c29f5e4c5..600a68078 100644 --- a/vendor/golang.org/x/sys/cpu/cpu_x86.go +++ b/vendor/golang.org/x/sys/cpu/cpu_x86.go @@ -92,10 +92,8 @@ func archInit() { osSupportsAVX = isSet(1, eax) && isSet(2, eax) if runtime.GOOS == "darwin" { - // Darwin doesn't save/restore AVX-512 mask registers correctly across signal handlers. - // Since users can't rely on mask register contents, let's not advertise AVX-512 support. - // See issue 49233. - osSupportsAVX512 = false + // Darwin requires special AVX512 checks, see cpu_darwin_x86.go + osSupportsAVX512 = osSupportsAVX && darwinSupportsAVX512() } else { // Check if OPMASK and ZMM registers have OS support. osSupportsAVX512 = osSupportsAVX && isSet(5, eax) && isSet(6, eax) && isSet(7, eax) diff --git a/vendor/golang.org/x/sys/cpu/syscall_darwin_x86_gc.go b/vendor/golang.org/x/sys/cpu/syscall_darwin_x86_gc.go new file mode 100644 index 000000000..4d0888b0c --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/syscall_darwin_x86_gc.go @@ -0,0 +1,98 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Minimal copy of x/sys/unix so the cpu package can make a +// system call on Darwin without depending on x/sys/unix. + +//go:build darwin && amd64 && gc + +package cpu + +import ( + "syscall" + "unsafe" +) + +type _C_int int32 + +// adapted from unix.Uname() at x/sys/unix/syscall_darwin.go L419 +func darwinOSRelease(release *[256]byte) error { + // from x/sys/unix/zerrors_openbsd_amd64.go + const ( + CTL_KERN = 0x1 + KERN_OSRELEASE = 0x2 + ) + + mib := []_C_int{CTL_KERN, KERN_OSRELEASE} + n := unsafe.Sizeof(*release) + + return sysctl(mib, &release[0], &n, nil, 0) +} + +type Errno = syscall.Errno + +var _zero uintptr // Single-word zero for use when we need a valid pointer to 0 bytes. + +// from x/sys/unix/zsyscall_darwin_amd64.go L791-807 +func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) error { + var _p0 unsafe.Pointer + if len(mib) > 0 { + _p0 = unsafe.Pointer(&mib[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + if _, _, err := syscall_syscall6( + libc_sysctl_trampoline_addr, + uintptr(_p0), + uintptr(len(mib)), + uintptr(unsafe.Pointer(old)), + uintptr(unsafe.Pointer(oldlen)), + uintptr(unsafe.Pointer(new)), + uintptr(newlen), + ); err != 0 { + return err + } + + return nil +} + +var libc_sysctl_trampoline_addr uintptr + +// adapted from internal/cpu/cpu_arm64_darwin.go +func darwinSysctlEnabled(name []byte) bool { + out := int32(0) + nout := unsafe.Sizeof(out) + if ret := sysctlbyname(&name[0], (*byte)(unsafe.Pointer(&out)), &nout, nil, 0); ret != nil { + return false + } + return out > 0 +} + +//go:cgo_import_dynamic libc_sysctl sysctl "/usr/lib/libSystem.B.dylib" + +var libc_sysctlbyname_trampoline_addr uintptr + +// adapted from runtime/sys_darwin.go in the pattern of sysctl() above, as defined in x/sys/unix +func sysctlbyname(name *byte, old *byte, oldlen *uintptr, new *byte, newlen uintptr) error { + if _, _, err := syscall_syscall6( + libc_sysctlbyname_trampoline_addr, + uintptr(unsafe.Pointer(name)), + uintptr(unsafe.Pointer(old)), + uintptr(unsafe.Pointer(oldlen)), + uintptr(unsafe.Pointer(new)), + uintptr(newlen), + 0, + ); err != 0 { + return err + } + + return nil +} + +//go:cgo_import_dynamic libc_sysctlbyname sysctlbyname "/usr/lib/libSystem.B.dylib" + +// Implemented in the runtime package (runtime/sys_darwin.go) +func syscall_syscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) + +//go:linkname syscall_syscall6 syscall.syscall6 diff --git a/vendor/golang.org/x/sys/unix/README.md b/vendor/golang.org/x/sys/unix/README.md index 7d3c060e1..6e08a76a7 100644 --- a/vendor/golang.org/x/sys/unix/README.md +++ b/vendor/golang.org/x/sys/unix/README.md @@ -156,7 +156,7 @@ from the generated architecture-specific files listed below, and merge these into a common file for each OS. The merge is performed in the following steps: -1. Construct the set of common code that is idential in all architecture-specific files. +1. Construct the set of common code that is identical in all architecture-specific files. 2. Write this common code to the merged file. 3. Remove the common code from all architecture-specific files. diff --git a/vendor/golang.org/x/sys/unix/asm_zos_s390x.s b/vendor/golang.org/x/sys/unix/asm_zos_s390x.s index 2f67ba86d..813dfad7d 100644 --- a/vendor/golang.org/x/sys/unix/asm_zos_s390x.s +++ b/vendor/golang.org/x/sys/unix/asm_zos_s390x.s @@ -9,9 +9,11 @@ #define PSALAA 1208(R0) #define GTAB64(x) 80(x) #define LCA64(x) 88(x) +#define SAVSTACK_ASYNC(x) 336(x) // in the LCA #define CAA(x) 8(x) -#define EDCHPXV(x) 1016(x) // in the CAA -#define SAVSTACK_ASYNC(x) 336(x) // in the LCA +#define CEECAATHDID(x) 976(x) // in the CAA +#define EDCHPXV(x) 1016(x) // in the CAA +#define GOCB(x) 1104(x) // in the CAA // SS_*, where x=SAVSTACK_ASYNC #define SS_LE(x) 0(x) @@ -19,405 +21,362 @@ #define SS_ERRNO(x) 16(x) #define SS_ERRNOJR(x) 20(x) -#define LE_CALL BYTE $0x0D; BYTE $0x76; // BL R7, R6 +// Function Descriptor Offsets +#define __errno 0x156*16 +#define __err2ad 0x16C*16 -TEXT ·clearErrno(SB),NOSPLIT,$0-0 - BL addrerrno<>(SB) - MOVD $0, 0(R3) +// Call Instructions +#define LE_CALL BYTE $0x0D; BYTE $0x76 // BL R7, R6 +#define SVC_LOAD BYTE $0x0A; BYTE $0x08 // SVC 08 LOAD +#define SVC_DELETE BYTE $0x0A; BYTE $0x09 // SVC 09 DELETE + +DATA zosLibVec<>(SB)/8, $0 +GLOBL zosLibVec<>(SB), NOPTR, $8 + +TEXT ·initZosLibVec(SB), NOSPLIT|NOFRAME, $0-0 + MOVW PSALAA, R8 + MOVD LCA64(R8), R8 + MOVD CAA(R8), R8 + MOVD EDCHPXV(R8), R8 + MOVD R8, zosLibVec<>(SB) + RET + +TEXT ·GetZosLibVec(SB), NOSPLIT|NOFRAME, $0-0 + MOVD zosLibVec<>(SB), R8 + MOVD R8, ret+0(FP) + RET + +TEXT ·clearErrno(SB), NOSPLIT, $0-0 + BL addrerrno<>(SB) + MOVD $0, 0(R3) RET // Returns the address of errno in R3. -TEXT addrerrno<>(SB),NOSPLIT|NOFRAME,$0-0 +TEXT addrerrno<>(SB), NOSPLIT|NOFRAME, $0-0 // Get library control area (LCA). - MOVW PSALAA, R8 - MOVD LCA64(R8), R8 + MOVW PSALAA, R8 + MOVD LCA64(R8), R8 // Get __errno FuncDesc. - MOVD CAA(R8), R9 - MOVD EDCHPXV(R9), R9 - ADD $(0x156*16), R9 - LMG 0(R9), R5, R6 + MOVD CAA(R8), R9 + MOVD EDCHPXV(R9), R9 + ADD $(__errno), R9 + LMG 0(R9), R5, R6 // Switch to saved LE stack. - MOVD SAVSTACK_ASYNC(R8), R9 - MOVD 0(R9), R4 - MOVD $0, 0(R9) + MOVD SAVSTACK_ASYNC(R8), R9 + MOVD 0(R9), R4 + MOVD $0, 0(R9) // Call __errno function. LE_CALL NOPH // Switch back to Go stack. - XOR R0, R0 // Restore R0 to $0. - MOVD R4, 0(R9) // Save stack pointer. + XOR R0, R0 // Restore R0 to $0. + MOVD R4, 0(R9) // Save stack pointer. RET -TEXT ·syscall_syscall(SB),NOSPLIT,$0-56 - BL runtime·entersyscall(SB) - MOVD a1+8(FP), R1 - MOVD a2+16(FP), R2 - MOVD a3+24(FP), R3 +// func svcCall(fnptr unsafe.Pointer, argv *unsafe.Pointer, dsa *uint64) +TEXT ·svcCall(SB), NOSPLIT, $0 + BL runtime·save_g(SB) // Save g and stack pointer + MOVW PSALAA, R8 + MOVD LCA64(R8), R8 + MOVD SAVSTACK_ASYNC(R8), R9 + MOVD R15, 0(R9) - // Get library control area (LCA). - MOVW PSALAA, R8 - MOVD LCA64(R8), R8 + MOVD argv+8(FP), R1 // Move function arguments into registers + MOVD dsa+16(FP), g + MOVD fnptr+0(FP), R15 - // Get function. - MOVD CAA(R8), R9 - MOVD EDCHPXV(R9), R9 - MOVD trap+0(FP), R5 - SLD $4, R5 - ADD R5, R9 - LMG 0(R9), R5, R6 + BYTE $0x0D // Branch to function + BYTE $0xEF - // Restore LE stack. - MOVD SAVSTACK_ASYNC(R8), R9 - MOVD 0(R9), R4 - MOVD $0, 0(R9) + BL runtime·load_g(SB) // Restore g and stack pointer + MOVW PSALAA, R8 + MOVD LCA64(R8), R8 + MOVD SAVSTACK_ASYNC(R8), R9 + MOVD 0(R9), R15 - // Call function. - LE_CALL - NOPH - XOR R0, R0 // Restore R0 to $0. - MOVD R4, 0(R9) // Save stack pointer. - - MOVD R3, r1+32(FP) - MOVD R0, r2+40(FP) - MOVD R0, err+48(FP) - MOVW R3, R4 - CMP R4, $-1 - BNE done - BL addrerrno<>(SB) - MOVWZ 0(R3), R3 - MOVD R3, err+48(FP) -done: - BL runtime·exitsyscall(SB) RET -TEXT ·syscall_rawsyscall(SB),NOSPLIT,$0-56 - MOVD a1+8(FP), R1 - MOVD a2+16(FP), R2 - MOVD a3+24(FP), R3 - - // Get library control area (LCA). - MOVW PSALAA, R8 - MOVD LCA64(R8), R8 - - // Get function. - MOVD CAA(R8), R9 - MOVD EDCHPXV(R9), R9 - MOVD trap+0(FP), R5 - SLD $4, R5 - ADD R5, R9 - LMG 0(R9), R5, R6 +// func svcLoad(name *byte) unsafe.Pointer +TEXT ·svcLoad(SB), NOSPLIT, $0 + MOVD R15, R2 // Save go stack pointer + MOVD name+0(FP), R0 // Move SVC args into registers + MOVD $0x80000000, R1 + MOVD $0, R15 + SVC_LOAD + MOVW R15, R3 // Save return code from SVC + MOVD R2, R15 // Restore go stack pointer + CMP R3, $0 // Check SVC return code + BNE error + + MOVD $-2, R3 // Reset last bit of entry point to zero + AND R0, R3 + MOVD R3, ret+8(FP) // Return entry point returned by SVC + CMP R0, R3 // Check if last bit of entry point was set + BNE done + + MOVD R15, R2 // Save go stack pointer + MOVD $0, R15 // Move SVC args into registers (entry point still in r0 from SVC 08) + SVC_DELETE + MOVD R2, R15 // Restore go stack pointer - // Restore LE stack. - MOVD SAVSTACK_ASYNC(R8), R9 - MOVD 0(R9), R4 - MOVD $0, 0(R9) +error: + MOVD $0, ret+8(FP) // Return 0 on failure - // Call function. - LE_CALL - NOPH - XOR R0, R0 // Restore R0 to $0. - MOVD R4, 0(R9) // Save stack pointer. - - MOVD R3, r1+32(FP) - MOVD R0, r2+40(FP) - MOVD R0, err+48(FP) - MOVW R3, R4 - CMP R4, $-1 - BNE done - BL addrerrno<>(SB) - MOVWZ 0(R3), R3 - MOVD R3, err+48(FP) done: + XOR R0, R0 // Reset r0 to 0 RET -TEXT ·syscall_syscall6(SB),NOSPLIT,$0-80 - BL runtime·entersyscall(SB) - MOVD a1+8(FP), R1 - MOVD a2+16(FP), R2 - MOVD a3+24(FP), R3 +// func svcUnload(name *byte, fnptr unsafe.Pointer) int64 +TEXT ·svcUnload(SB), NOSPLIT, $0 + MOVD R15, R2 // Save go stack pointer + MOVD name+0(FP), R0 // Move SVC args into registers + MOVD fnptr+8(FP), R15 + SVC_DELETE + XOR R0, R0 // Reset r0 to 0 + MOVD R15, R1 // Save SVC return code + MOVD R2, R15 // Restore go stack pointer + MOVD R1, ret+16(FP) // Return SVC return code + RET +// func gettid() uint64 +TEXT ·gettid(SB), NOSPLIT, $0 // Get library control area (LCA). - MOVW PSALAA, R8 - MOVD LCA64(R8), R8 + MOVW PSALAA, R8 + MOVD LCA64(R8), R8 - // Get function. - MOVD CAA(R8), R9 - MOVD EDCHPXV(R9), R9 - MOVD trap+0(FP), R5 - SLD $4, R5 - ADD R5, R9 - LMG 0(R9), R5, R6 + // Get CEECAATHDID + MOVD CAA(R8), R9 + MOVD CEECAATHDID(R9), R9 + MOVD R9, ret+0(FP) - // Restore LE stack. - MOVD SAVSTACK_ASYNC(R8), R9 - MOVD 0(R9), R4 - MOVD $0, 0(R9) - - // Fill in parameter list. - MOVD a4+32(FP), R12 - MOVD R12, (2176+24)(R4) - MOVD a5+40(FP), R12 - MOVD R12, (2176+32)(R4) - MOVD a6+48(FP), R12 - MOVD R12, (2176+40)(R4) - - // Call function. - LE_CALL - NOPH - XOR R0, R0 // Restore R0 to $0. - MOVD R4, 0(R9) // Save stack pointer. - - MOVD R3, r1+56(FP) - MOVD R0, r2+64(FP) - MOVD R0, err+72(FP) - MOVW R3, R4 - CMP R4, $-1 - BNE done - BL addrerrno<>(SB) - MOVWZ 0(R3), R3 - MOVD R3, err+72(FP) -done: - BL runtime·exitsyscall(SB) RET -TEXT ·syscall_rawsyscall6(SB),NOSPLIT,$0-80 - MOVD a1+8(FP), R1 - MOVD a2+16(FP), R2 - MOVD a3+24(FP), R3 - - // Get library control area (LCA). - MOVW PSALAA, R8 - MOVD LCA64(R8), R8 - - // Get function. - MOVD CAA(R8), R9 - MOVD EDCHPXV(R9), R9 - MOVD trap+0(FP), R5 - SLD $4, R5 - ADD R5, R9 - LMG 0(R9), R5, R6 +// +// Call LE function, if the return is -1 +// errno and errno2 is retrieved +// +TEXT ·CallLeFuncWithErr(SB), NOSPLIT, $0 + MOVW PSALAA, R8 + MOVD LCA64(R8), R8 + MOVD CAA(R8), R9 + MOVD g, GOCB(R9) // Restore LE stack. - MOVD SAVSTACK_ASYNC(R8), R9 - MOVD 0(R9), R4 - MOVD $0, 0(R9) - - // Fill in parameter list. - MOVD a4+32(FP), R12 - MOVD R12, (2176+24)(R4) - MOVD a5+40(FP), R12 - MOVD R12, (2176+32)(R4) - MOVD a6+48(FP), R12 - MOVD R12, (2176+40)(R4) - - // Call function. - LE_CALL + MOVD SAVSTACK_ASYNC(R8), R9 // R9-> LE stack frame saving address + MOVD 0(R9), R4 // R4-> restore previously saved stack frame pointer + + MOVD parms_base+8(FP), R7 // R7 -> argument array + MOVD parms_len+16(FP), R8 // R8 number of arguments + + // arg 1 ---> R1 + CMP R8, $0 + BEQ docall + SUB $1, R8 + MOVD 0(R7), R1 + + // arg 2 ---> R2 + CMP R8, $0 + BEQ docall + SUB $1, R8 + ADD $8, R7 + MOVD 0(R7), R2 + + // arg 3 --> R3 + CMP R8, $0 + BEQ docall + SUB $1, R8 + ADD $8, R7 + MOVD 0(R7), R3 + + CMP R8, $0 + BEQ docall + MOVD $2176+16, R6 // starting LE stack address-8 to store 4th argument + +repeat: + ADD $8, R7 + MOVD 0(R7), R0 // advance arg pointer by 8 byte + ADD $8, R6 // advance LE argument address by 8 byte + MOVD R0, (R4)(R6*1) // copy argument from go-slice to le-frame + SUB $1, R8 + CMP R8, $0 + BNE repeat + +docall: + MOVD funcdesc+0(FP), R8 // R8-> function descriptor + LMG 0(R8), R5, R6 + MOVD $0, 0(R9) // R9 address of SAVSTACK_ASYNC + LE_CALL // balr R7, R6 (return #1) + NOPH + MOVD R3, ret+32(FP) + CMP R3, $-1 // compare result to -1 + BNE done + + // retrieve errno and errno2 + MOVD zosLibVec<>(SB), R8 + ADD $(__errno), R8 + LMG 0(R8), R5, R6 + LE_CALL // balr R7, R6 __errno (return #3) NOPH - XOR R0, R0 // Restore R0 to $0. - MOVD R4, 0(R9) // Save stack pointer. - - MOVD R3, r1+56(FP) - MOVD R0, r2+64(FP) - MOVD R0, err+72(FP) - MOVW R3, R4 - CMP R4, $-1 - BNE done - BL ·rrno<>(SB) - MOVWZ 0(R3), R3 - MOVD R3, err+72(FP) + MOVWZ 0(R3), R3 + MOVD R3, err+48(FP) + MOVD zosLibVec<>(SB), R8 + ADD $(__err2ad), R8 + LMG 0(R8), R5, R6 + LE_CALL // balr R7, R6 __err2ad (return #2) + NOPH + MOVW (R3), R2 // retrieve errno2 + MOVD R2, errno2+40(FP) // store in return area + done: + MOVD R4, 0(R9) // Save stack pointer. RET -TEXT ·syscall_syscall9(SB),NOSPLIT,$0 - BL runtime·entersyscall(SB) - MOVD a1+8(FP), R1 - MOVD a2+16(FP), R2 - MOVD a3+24(FP), R3 - - // Get library control area (LCA). - MOVW PSALAA, R8 - MOVD LCA64(R8), R8 - - // Get function. - MOVD CAA(R8), R9 - MOVD EDCHPXV(R9), R9 - MOVD trap+0(FP), R5 - SLD $4, R5 - ADD R5, R9 - LMG 0(R9), R5, R6 +// +// Call LE function, if the return is 0 +// errno and errno2 is retrieved +// +TEXT ·CallLeFuncWithPtrReturn(SB), NOSPLIT, $0 + MOVW PSALAA, R8 + MOVD LCA64(R8), R8 + MOVD CAA(R8), R9 + MOVD g, GOCB(R9) // Restore LE stack. - MOVD SAVSTACK_ASYNC(R8), R9 - MOVD 0(R9), R4 - MOVD $0, 0(R9) - - // Fill in parameter list. - MOVD a4+32(FP), R12 - MOVD R12, (2176+24)(R4) - MOVD a5+40(FP), R12 - MOVD R12, (2176+32)(R4) - MOVD a6+48(FP), R12 - MOVD R12, (2176+40)(R4) - MOVD a7+56(FP), R12 - MOVD R12, (2176+48)(R4) - MOVD a8+64(FP), R12 - MOVD R12, (2176+56)(R4) - MOVD a9+72(FP), R12 - MOVD R12, (2176+64)(R4) - - // Call function. - LE_CALL + MOVD SAVSTACK_ASYNC(R8), R9 // R9-> LE stack frame saving address + MOVD 0(R9), R4 // R4-> restore previously saved stack frame pointer + + MOVD parms_base+8(FP), R7 // R7 -> argument array + MOVD parms_len+16(FP), R8 // R8 number of arguments + + // arg 1 ---> R1 + CMP R8, $0 + BEQ docall + SUB $1, R8 + MOVD 0(R7), R1 + + // arg 2 ---> R2 + CMP R8, $0 + BEQ docall + SUB $1, R8 + ADD $8, R7 + MOVD 0(R7), R2 + + // arg 3 --> R3 + CMP R8, $0 + BEQ docall + SUB $1, R8 + ADD $8, R7 + MOVD 0(R7), R3 + + CMP R8, $0 + BEQ docall + MOVD $2176+16, R6 // starting LE stack address-8 to store 4th argument + +repeat: + ADD $8, R7 + MOVD 0(R7), R0 // advance arg pointer by 8 byte + ADD $8, R6 // advance LE argument address by 8 byte + MOVD R0, (R4)(R6*1) // copy argument from go-slice to le-frame + SUB $1, R8 + CMP R8, $0 + BNE repeat + +docall: + MOVD funcdesc+0(FP), R8 // R8-> function descriptor + LMG 0(R8), R5, R6 + MOVD $0, 0(R9) // R9 address of SAVSTACK_ASYNC + LE_CALL // balr R7, R6 (return #1) NOPH - XOR R0, R0 // Restore R0 to $0. - MOVD R4, 0(R9) // Save stack pointer. - - MOVD R3, r1+80(FP) - MOVD R0, r2+88(FP) - MOVD R0, err+96(FP) - MOVW R3, R4 - CMP R4, $-1 - BNE done - BL addrerrno<>(SB) - MOVWZ 0(R3), R3 - MOVD R3, err+96(FP) -done: - BL runtime·exitsyscall(SB) - RET - -TEXT ·syscall_rawsyscall9(SB),NOSPLIT,$0 - MOVD a1+8(FP), R1 - MOVD a2+16(FP), R2 - MOVD a3+24(FP), R3 - - // Get library control area (LCA). - MOVW PSALAA, R8 - MOVD LCA64(R8), R8 - - // Get function. - MOVD CAA(R8), R9 - MOVD EDCHPXV(R9), R9 - MOVD trap+0(FP), R5 - SLD $4, R5 - ADD R5, R9 - LMG 0(R9), R5, R6 - - // Restore LE stack. - MOVD SAVSTACK_ASYNC(R8), R9 - MOVD 0(R9), R4 - MOVD $0, 0(R9) - - // Fill in parameter list. - MOVD a4+32(FP), R12 - MOVD R12, (2176+24)(R4) - MOVD a5+40(FP), R12 - MOVD R12, (2176+32)(R4) - MOVD a6+48(FP), R12 - MOVD R12, (2176+40)(R4) - MOVD a7+56(FP), R12 - MOVD R12, (2176+48)(R4) - MOVD a8+64(FP), R12 - MOVD R12, (2176+56)(R4) - MOVD a9+72(FP), R12 - MOVD R12, (2176+64)(R4) - - // Call function. - LE_CALL + MOVD R3, ret+32(FP) + CMP R3, $0 // compare result to 0 + BNE done + + // retrieve errno and errno2 + MOVD zosLibVec<>(SB), R8 + ADD $(__errno), R8 + LMG 0(R8), R5, R6 + LE_CALL // balr R7, R6 __errno (return #3) NOPH - XOR R0, R0 // Restore R0 to $0. - MOVD R4, 0(R9) // Save stack pointer. - - MOVD R3, r1+80(FP) - MOVD R0, r2+88(FP) - MOVD R0, err+96(FP) - MOVW R3, R4 - CMP R4, $-1 - BNE done - BL addrerrno<>(SB) - MOVWZ 0(R3), R3 - MOVD R3, err+96(FP) -done: - RET - -// func svcCall(fnptr unsafe.Pointer, argv *unsafe.Pointer, dsa *uint64) -TEXT ·svcCall(SB),NOSPLIT,$0 - BL runtime·save_g(SB) // Save g and stack pointer - MOVW PSALAA, R8 - MOVD LCA64(R8), R8 - MOVD SAVSTACK_ASYNC(R8), R9 - MOVD R15, 0(R9) - - MOVD argv+8(FP), R1 // Move function arguments into registers - MOVD dsa+16(FP), g - MOVD fnptr+0(FP), R15 - - BYTE $0x0D // Branch to function - BYTE $0xEF - - BL runtime·load_g(SB) // Restore g and stack pointer - MOVW PSALAA, R8 - MOVD LCA64(R8), R8 - MOVD SAVSTACK_ASYNC(R8), R9 - MOVD 0(R9), R15 - - RET - -// func svcLoad(name *byte) unsafe.Pointer -TEXT ·svcLoad(SB),NOSPLIT,$0 - MOVD R15, R2 // Save go stack pointer - MOVD name+0(FP), R0 // Move SVC args into registers - MOVD $0x80000000, R1 - MOVD $0, R15 - BYTE $0x0A // SVC 08 LOAD - BYTE $0x08 - MOVW R15, R3 // Save return code from SVC - MOVD R2, R15 // Restore go stack pointer - CMP R3, $0 // Check SVC return code - BNE error - - MOVD $-2, R3 // Reset last bit of entry point to zero - AND R0, R3 - MOVD R3, addr+8(FP) // Return entry point returned by SVC - CMP R0, R3 // Check if last bit of entry point was set - BNE done - - MOVD R15, R2 // Save go stack pointer - MOVD $0, R15 // Move SVC args into registers (entry point still in r0 from SVC 08) - BYTE $0x0A // SVC 09 DELETE - BYTE $0x09 - MOVD R2, R15 // Restore go stack pointer + MOVWZ 0(R3), R3 + MOVD R3, err+48(FP) + MOVD zosLibVec<>(SB), R8 + ADD $(__err2ad), R8 + LMG 0(R8), R5, R6 + LE_CALL // balr R7, R6 __err2ad (return #2) + NOPH + MOVW (R3), R2 // retrieve errno2 + MOVD R2, errno2+40(FP) // store in return area + XOR R2, R2 + MOVWZ R2, (R3) // clear errno2 -error: - MOVD $0, addr+8(FP) // Return 0 on failure done: - XOR R0, R0 // Reset r0 to 0 + MOVD R4, 0(R9) // Save stack pointer. RET -// func svcUnload(name *byte, fnptr unsafe.Pointer) int64 -TEXT ·svcUnload(SB),NOSPLIT,$0 - MOVD R15, R2 // Save go stack pointer - MOVD name+0(FP), R0 // Move SVC args into registers - MOVD addr+8(FP), R15 - BYTE $0x0A // SVC 09 - BYTE $0x09 - XOR R0, R0 // Reset r0 to 0 - MOVD R15, R1 // Save SVC return code - MOVD R2, R15 // Restore go stack pointer - MOVD R1, rc+0(FP) // Return SVC return code +// +// function to test if a pointer can be safely dereferenced (content read) +// return 0 for succces +// +TEXT ·ptrtest(SB), NOSPLIT, $0-16 + MOVD arg+0(FP), R10 // test pointer in R10 + + // set up R2 to point to CEECAADMC + BYTE $0xE3; BYTE $0x20; BYTE $0x04; BYTE $0xB8; BYTE $0x00; BYTE $0x17 // llgt 2,1208 + BYTE $0xB9; BYTE $0x17; BYTE $0x00; BYTE $0x22 // llgtr 2,2 + BYTE $0xA5; BYTE $0x26; BYTE $0x7F; BYTE $0xFF // nilh 2,32767 + BYTE $0xE3; BYTE $0x22; BYTE $0x00; BYTE $0x58; BYTE $0x00; BYTE $0x04 // lg 2,88(2) + BYTE $0xE3; BYTE $0x22; BYTE $0x00; BYTE $0x08; BYTE $0x00; BYTE $0x04 // lg 2,8(2) + BYTE $0x41; BYTE $0x22; BYTE $0x03; BYTE $0x68 // la 2,872(2) + + // set up R5 to point to the "shunt" path which set 1 to R3 (failure) + BYTE $0xB9; BYTE $0x82; BYTE $0x00; BYTE $0x33 // xgr 3,3 + BYTE $0xA7; BYTE $0x55; BYTE $0x00; BYTE $0x04 // bras 5,lbl1 + BYTE $0xA7; BYTE $0x39; BYTE $0x00; BYTE $0x01 // lghi 3,1 + + // if r3 is not zero (failed) then branch to finish + BYTE $0xB9; BYTE $0x02; BYTE $0x00; BYTE $0x33 // lbl1 ltgr 3,3 + BYTE $0xA7; BYTE $0x74; BYTE $0x00; BYTE $0x08 // brc b'0111',lbl2 + + // stomic store shunt address in R5 into CEECAADMC + BYTE $0xE3; BYTE $0x52; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x24 // stg 5,0(2) + + // now try reading from the test pointer in R10, if it fails it branches to the "lghi" instruction above + BYTE $0xE3; BYTE $0x9A; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x04 // lg 9,0(10) + + // finish here, restore 0 into CEECAADMC + BYTE $0xB9; BYTE $0x82; BYTE $0x00; BYTE $0x99 // lbl2 xgr 9,9 + BYTE $0xE3; BYTE $0x92; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x24 // stg 9,0(2) + MOVD R3, ret+8(FP) // result in R3 RET -// func gettid() uint64 -TEXT ·gettid(SB), NOSPLIT, $0 - // Get library control area (LCA). - MOVW PSALAA, R8 - MOVD LCA64(R8), R8 - - // Get CEECAATHDID - MOVD CAA(R8), R9 - MOVD 0x3D0(R9), R9 - MOVD R9, ret+0(FP) - +// +// function to test if a untptr can be loaded from a pointer +// return 1: the 8-byte content +// 2: 0 for success, 1 for failure +// +// func safeload(ptr uintptr) ( value uintptr, error uintptr) +TEXT ·safeload(SB), NOSPLIT, $0-24 + MOVD ptr+0(FP), R10 // test pointer in R10 + MOVD $0x0, R6 + BYTE $0xE3; BYTE $0x20; BYTE $0x04; BYTE $0xB8; BYTE $0x00; BYTE $0x17 // llgt 2,1208 + BYTE $0xB9; BYTE $0x17; BYTE $0x00; BYTE $0x22 // llgtr 2,2 + BYTE $0xA5; BYTE $0x26; BYTE $0x7F; BYTE $0xFF // nilh 2,32767 + BYTE $0xE3; BYTE $0x22; BYTE $0x00; BYTE $0x58; BYTE $0x00; BYTE $0x04 // lg 2,88(2) + BYTE $0xE3; BYTE $0x22; BYTE $0x00; BYTE $0x08; BYTE $0x00; BYTE $0x04 // lg 2,8(2) + BYTE $0x41; BYTE $0x22; BYTE $0x03; BYTE $0x68 // la 2,872(2) + BYTE $0xB9; BYTE $0x82; BYTE $0x00; BYTE $0x33 // xgr 3,3 + BYTE $0xA7; BYTE $0x55; BYTE $0x00; BYTE $0x04 // bras 5,lbl1 + BYTE $0xA7; BYTE $0x39; BYTE $0x00; BYTE $0x01 // lghi 3,1 + BYTE $0xB9; BYTE $0x02; BYTE $0x00; BYTE $0x33 // lbl1 ltgr 3,3 + BYTE $0xA7; BYTE $0x74; BYTE $0x00; BYTE $0x08 // brc b'0111',lbl2 + BYTE $0xE3; BYTE $0x52; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x24 // stg 5,0(2) + BYTE $0xE3; BYTE $0x6A; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x04 // lg 6,0(10) + BYTE $0xB9; BYTE $0x82; BYTE $0x00; BYTE $0x99 // lbl2 xgr 9,9 + BYTE $0xE3; BYTE $0x92; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x24 // stg 9,0(2) + MOVD R6, value+8(FP) // result in R6 + MOVD R3, error+16(FP) // error in R3 RET diff --git a/vendor/golang.org/x/sys/unix/bpxsvc_zos.go b/vendor/golang.org/x/sys/unix/bpxsvc_zos.go new file mode 100644 index 000000000..39d647d86 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/bpxsvc_zos.go @@ -0,0 +1,657 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build zos + +package unix + +import ( + "bytes" + "fmt" + "unsafe" +) + +//go:noescape +func bpxcall(plist []unsafe.Pointer, bpx_offset int64) + +//go:noescape +func A2e([]byte) + +//go:noescape +func E2a([]byte) + +const ( + BPX4STA = 192 // stat + BPX4FST = 104 // fstat + BPX4LST = 132 // lstat + BPX4OPN = 156 // open + BPX4CLO = 72 // close + BPX4CHR = 500 // chattr + BPX4FCR = 504 // fchattr + BPX4LCR = 1180 // lchattr + BPX4CTW = 492 // cond_timed_wait + BPX4GTH = 1056 // __getthent + BPX4PTQ = 412 // pthread_quiesc + BPX4PTR = 320 // ptrace +) + +const ( + //options + //byte1 + BPX_OPNFHIGH = 0x80 + //byte2 + BPX_OPNFEXEC = 0x80 + //byte3 + BPX_O_NOLARGEFILE = 0x08 + BPX_O_LARGEFILE = 0x04 + BPX_O_ASYNCSIG = 0x02 + BPX_O_SYNC = 0x01 + //byte4 + BPX_O_CREXCL = 0xc0 + BPX_O_CREAT = 0x80 + BPX_O_EXCL = 0x40 + BPX_O_NOCTTY = 0x20 + BPX_O_TRUNC = 0x10 + BPX_O_APPEND = 0x08 + BPX_O_NONBLOCK = 0x04 + BPX_FNDELAY = 0x04 + BPX_O_RDWR = 0x03 + BPX_O_RDONLY = 0x02 + BPX_O_WRONLY = 0x01 + BPX_O_ACCMODE = 0x03 + BPX_O_GETFL = 0x0f + + //mode + // byte1 (file type) + BPX_FT_DIR = 1 + BPX_FT_CHARSPEC = 2 + BPX_FT_REGFILE = 3 + BPX_FT_FIFO = 4 + BPX_FT_SYMLINK = 5 + BPX_FT_SOCKET = 6 + //byte3 + BPX_S_ISUID = 0x08 + BPX_S_ISGID = 0x04 + BPX_S_ISVTX = 0x02 + BPX_S_IRWXU1 = 0x01 + BPX_S_IRUSR = 0x01 + //byte4 + BPX_S_IRWXU2 = 0xc0 + BPX_S_IWUSR = 0x80 + BPX_S_IXUSR = 0x40 + BPX_S_IRWXG = 0x38 + BPX_S_IRGRP = 0x20 + BPX_S_IWGRP = 0x10 + BPX_S_IXGRP = 0x08 + BPX_S_IRWXOX = 0x07 + BPX_S_IROTH = 0x04 + BPX_S_IWOTH = 0x02 + BPX_S_IXOTH = 0x01 + + CW_INTRPT = 1 + CW_CONDVAR = 32 + CW_TIMEOUT = 64 + + PGTHA_NEXT = 2 + PGTHA_CURRENT = 1 + PGTHA_FIRST = 0 + PGTHA_LAST = 3 + PGTHA_PROCESS = 0x80 + PGTHA_CONTTY = 0x40 + PGTHA_PATH = 0x20 + PGTHA_COMMAND = 0x10 + PGTHA_FILEDATA = 0x08 + PGTHA_THREAD = 0x04 + PGTHA_PTAG = 0x02 + PGTHA_COMMANDLONG = 0x01 + PGTHA_THREADFAST = 0x80 + PGTHA_FILEPATH = 0x40 + PGTHA_THDSIGMASK = 0x20 + // thread quiece mode + QUIESCE_TERM int32 = 1 + QUIESCE_FORCE int32 = 2 + QUIESCE_QUERY int32 = 3 + QUIESCE_FREEZE int32 = 4 + QUIESCE_UNFREEZE int32 = 5 + FREEZE_THIS_THREAD int32 = 6 + FREEZE_EXIT int32 = 8 + QUIESCE_SRB int32 = 9 +) + +type Pgtha struct { + Pid uint32 // 0 + Tid0 uint32 // 4 + Tid1 uint32 + Accesspid byte // C + Accesstid byte // D + Accessasid uint16 // E + Loginname [8]byte // 10 + Flag1 byte // 18 + Flag1b2 byte // 19 +} + +type Bpxystat_t struct { // DSECT BPXYSTAT + St_id [4]uint8 // 0 + St_length uint16 // 0x4 + St_version uint16 // 0x6 + St_mode uint32 // 0x8 + St_ino uint32 // 0xc + St_dev uint32 // 0x10 + St_nlink uint32 // 0x14 + St_uid uint32 // 0x18 + St_gid uint32 // 0x1c + St_size uint64 // 0x20 + St_atime uint32 // 0x28 + St_mtime uint32 // 0x2c + St_ctime uint32 // 0x30 + St_rdev uint32 // 0x34 + St_auditoraudit uint32 // 0x38 + St_useraudit uint32 // 0x3c + St_blksize uint32 // 0x40 + St_createtime uint32 // 0x44 + St_auditid [4]uint32 // 0x48 + St_res01 uint32 // 0x58 + Ft_ccsid uint16 // 0x5c + Ft_flags uint16 // 0x5e + St_res01a [2]uint32 // 0x60 + St_res02 uint32 // 0x68 + St_blocks uint32 // 0x6c + St_opaque [3]uint8 // 0x70 + St_visible uint8 // 0x73 + St_reftime uint32 // 0x74 + St_fid uint64 // 0x78 + St_filefmt uint8 // 0x80 + St_fspflag2 uint8 // 0x81 + St_res03 [2]uint8 // 0x82 + St_ctimemsec uint32 // 0x84 + St_seclabel [8]uint8 // 0x88 + St_res04 [4]uint8 // 0x90 + // end of version 1 + _ uint32 // 0x94 + St_atime64 uint64 // 0x98 + St_mtime64 uint64 // 0xa0 + St_ctime64 uint64 // 0xa8 + St_createtime64 uint64 // 0xb0 + St_reftime64 uint64 // 0xb8 + _ uint64 // 0xc0 + St_res05 [16]uint8 // 0xc8 + // end of version 2 +} + +type BpxFilestatus struct { + Oflag1 byte + Oflag2 byte + Oflag3 byte + Oflag4 byte +} + +type BpxMode struct { + Ftype byte + Mode1 byte + Mode2 byte + Mode3 byte +} + +// Thr attribute structure for extended attributes +type Bpxyatt_t struct { // DSECT BPXYATT + Att_id [4]uint8 + Att_version uint16 + Att_res01 [2]uint8 + Att_setflags1 uint8 + Att_setflags2 uint8 + Att_setflags3 uint8 + Att_setflags4 uint8 + Att_mode uint32 + Att_uid uint32 + Att_gid uint32 + Att_opaquemask [3]uint8 + Att_visblmaskres uint8 + Att_opaque [3]uint8 + Att_visibleres uint8 + Att_size_h uint32 + Att_size_l uint32 + Att_atime uint32 + Att_mtime uint32 + Att_auditoraudit uint32 + Att_useraudit uint32 + Att_ctime uint32 + Att_reftime uint32 + // end of version 1 + Att_filefmt uint8 + Att_res02 [3]uint8 + Att_filetag uint32 + Att_res03 [8]uint8 + // end of version 2 + Att_atime64 uint64 + Att_mtime64 uint64 + Att_ctime64 uint64 + Att_reftime64 uint64 + Att_seclabel [8]uint8 + Att_ver3res02 [8]uint8 + // end of version 3 +} + +func BpxOpen(name string, options *BpxFilestatus, mode *BpxMode) (rv int32, rc int32, rn int32) { + if len(name) < 1024 { + var namebuf [1024]byte + sz := int32(copy(namebuf[:], name)) + A2e(namebuf[:sz]) + var parms [7]unsafe.Pointer + parms[0] = unsafe.Pointer(&sz) + parms[1] = unsafe.Pointer(&namebuf[0]) + parms[2] = unsafe.Pointer(options) + parms[3] = unsafe.Pointer(mode) + parms[4] = unsafe.Pointer(&rv) + parms[5] = unsafe.Pointer(&rc) + parms[6] = unsafe.Pointer(&rn) + bpxcall(parms[:], BPX4OPN) + return rv, rc, rn + } + return -1, -1, -1 +} + +func BpxClose(fd int32) (rv int32, rc int32, rn int32) { + var parms [4]unsafe.Pointer + parms[0] = unsafe.Pointer(&fd) + parms[1] = unsafe.Pointer(&rv) + parms[2] = unsafe.Pointer(&rc) + parms[3] = unsafe.Pointer(&rn) + bpxcall(parms[:], BPX4CLO) + return rv, rc, rn +} + +func BpxFileFStat(fd int32, st *Bpxystat_t) (rv int32, rc int32, rn int32) { + st.St_id = [4]uint8{0xe2, 0xe3, 0xc1, 0xe3} + st.St_version = 2 + stat_sz := uint32(unsafe.Sizeof(*st)) + var parms [6]unsafe.Pointer + parms[0] = unsafe.Pointer(&fd) + parms[1] = unsafe.Pointer(&stat_sz) + parms[2] = unsafe.Pointer(st) + parms[3] = unsafe.Pointer(&rv) + parms[4] = unsafe.Pointer(&rc) + parms[5] = unsafe.Pointer(&rn) + bpxcall(parms[:], BPX4FST) + return rv, rc, rn +} + +func BpxFileStat(name string, st *Bpxystat_t) (rv int32, rc int32, rn int32) { + if len(name) < 1024 { + var namebuf [1024]byte + sz := int32(copy(namebuf[:], name)) + A2e(namebuf[:sz]) + st.St_id = [4]uint8{0xe2, 0xe3, 0xc1, 0xe3} + st.St_version = 2 + stat_sz := uint32(unsafe.Sizeof(*st)) + var parms [7]unsafe.Pointer + parms[0] = unsafe.Pointer(&sz) + parms[1] = unsafe.Pointer(&namebuf[0]) + parms[2] = unsafe.Pointer(&stat_sz) + parms[3] = unsafe.Pointer(st) + parms[4] = unsafe.Pointer(&rv) + parms[5] = unsafe.Pointer(&rc) + parms[6] = unsafe.Pointer(&rn) + bpxcall(parms[:], BPX4STA) + return rv, rc, rn + } + return -1, -1, -1 +} + +func BpxFileLStat(name string, st *Bpxystat_t) (rv int32, rc int32, rn int32) { + if len(name) < 1024 { + var namebuf [1024]byte + sz := int32(copy(namebuf[:], name)) + A2e(namebuf[:sz]) + st.St_id = [4]uint8{0xe2, 0xe3, 0xc1, 0xe3} + st.St_version = 2 + stat_sz := uint32(unsafe.Sizeof(*st)) + var parms [7]unsafe.Pointer + parms[0] = unsafe.Pointer(&sz) + parms[1] = unsafe.Pointer(&namebuf[0]) + parms[2] = unsafe.Pointer(&stat_sz) + parms[3] = unsafe.Pointer(st) + parms[4] = unsafe.Pointer(&rv) + parms[5] = unsafe.Pointer(&rc) + parms[6] = unsafe.Pointer(&rn) + bpxcall(parms[:], BPX4LST) + return rv, rc, rn + } + return -1, -1, -1 +} + +func BpxChattr(path string, attr *Bpxyatt_t) (rv int32, rc int32, rn int32) { + if len(path) >= 1024 { + return -1, -1, -1 + } + var namebuf [1024]byte + sz := int32(copy(namebuf[:], path)) + A2e(namebuf[:sz]) + attr_sz := uint32(unsafe.Sizeof(*attr)) + var parms [7]unsafe.Pointer + parms[0] = unsafe.Pointer(&sz) + parms[1] = unsafe.Pointer(&namebuf[0]) + parms[2] = unsafe.Pointer(&attr_sz) + parms[3] = unsafe.Pointer(attr) + parms[4] = unsafe.Pointer(&rv) + parms[5] = unsafe.Pointer(&rc) + parms[6] = unsafe.Pointer(&rn) + bpxcall(parms[:], BPX4CHR) + return rv, rc, rn +} + +func BpxLchattr(path string, attr *Bpxyatt_t) (rv int32, rc int32, rn int32) { + if len(path) >= 1024 { + return -1, -1, -1 + } + var namebuf [1024]byte + sz := int32(copy(namebuf[:], path)) + A2e(namebuf[:sz]) + attr_sz := uint32(unsafe.Sizeof(*attr)) + var parms [7]unsafe.Pointer + parms[0] = unsafe.Pointer(&sz) + parms[1] = unsafe.Pointer(&namebuf[0]) + parms[2] = unsafe.Pointer(&attr_sz) + parms[3] = unsafe.Pointer(attr) + parms[4] = unsafe.Pointer(&rv) + parms[5] = unsafe.Pointer(&rc) + parms[6] = unsafe.Pointer(&rn) + bpxcall(parms[:], BPX4LCR) + return rv, rc, rn +} + +func BpxFchattr(fd int32, attr *Bpxyatt_t) (rv int32, rc int32, rn int32) { + attr_sz := uint32(unsafe.Sizeof(*attr)) + var parms [6]unsafe.Pointer + parms[0] = unsafe.Pointer(&fd) + parms[1] = unsafe.Pointer(&attr_sz) + parms[2] = unsafe.Pointer(attr) + parms[3] = unsafe.Pointer(&rv) + parms[4] = unsafe.Pointer(&rc) + parms[5] = unsafe.Pointer(&rn) + bpxcall(parms[:], BPX4FCR) + return rv, rc, rn +} + +func BpxCondTimedWait(sec uint32, nsec uint32, events uint32, secrem *uint32, nsecrem *uint32) (rv int32, rc int32, rn int32) { + var parms [8]unsafe.Pointer + parms[0] = unsafe.Pointer(&sec) + parms[1] = unsafe.Pointer(&nsec) + parms[2] = unsafe.Pointer(&events) + parms[3] = unsafe.Pointer(secrem) + parms[4] = unsafe.Pointer(nsecrem) + parms[5] = unsafe.Pointer(&rv) + parms[6] = unsafe.Pointer(&rc) + parms[7] = unsafe.Pointer(&rn) + bpxcall(parms[:], BPX4CTW) + return rv, rc, rn +} +func BpxGetthent(in *Pgtha, outlen *uint32, out unsafe.Pointer) (rv int32, rc int32, rn int32) { + var parms [7]unsafe.Pointer + inlen := uint32(26) // nothing else will work. Go says Pgtha is 28-byte because of alignment, but Pgtha is "packed" and must be 26-byte + parms[0] = unsafe.Pointer(&inlen) + parms[1] = unsafe.Pointer(&in) + parms[2] = unsafe.Pointer(outlen) + parms[3] = unsafe.Pointer(&out) + parms[4] = unsafe.Pointer(&rv) + parms[5] = unsafe.Pointer(&rc) + parms[6] = unsafe.Pointer(&rn) + bpxcall(parms[:], BPX4GTH) + return rv, rc, rn +} +func ZosJobname() (jobname string, err error) { + var pgtha Pgtha + pgtha.Pid = uint32(Getpid()) + pgtha.Accesspid = PGTHA_CURRENT + pgtha.Flag1 = PGTHA_PROCESS + var out [256]byte + var outlen uint32 + outlen = 256 + rv, rc, rn := BpxGetthent(&pgtha, &outlen, unsafe.Pointer(&out[0])) + if rv == 0 { + gthc := []byte{0x87, 0xa3, 0x88, 0x83} // 'gthc' in ebcdic + ix := bytes.Index(out[:], gthc) + if ix == -1 { + err = fmt.Errorf("BPX4GTH: gthc return data not found") + return + } + jn := out[ix+80 : ix+88] // we didn't declare Pgthc, but jobname is 8-byte at offset 80 + E2a(jn) + jobname = string(bytes.TrimRight(jn, " ")) + + } else { + err = fmt.Errorf("BPX4GTH: rc=%d errno=%d reason=code=0x%x", rv, rc, rn) + } + return +} +func Bpx4ptq(code int32, data string) (rv int32, rc int32, rn int32) { + var userdata [8]byte + var parms [5]unsafe.Pointer + copy(userdata[:], data+" ") + A2e(userdata[:]) + parms[0] = unsafe.Pointer(&code) + parms[1] = unsafe.Pointer(&userdata[0]) + parms[2] = unsafe.Pointer(&rv) + parms[3] = unsafe.Pointer(&rc) + parms[4] = unsafe.Pointer(&rn) + bpxcall(parms[:], BPX4PTQ) + return rv, rc, rn +} + +const ( + PT_TRACE_ME = 0 // Debug this process + PT_READ_I = 1 // Read a full word + PT_READ_D = 2 // Read a full word + PT_READ_U = 3 // Read control info + PT_WRITE_I = 4 //Write a full word + PT_WRITE_D = 5 //Write a full word + PT_CONTINUE = 7 //Continue the process + PT_KILL = 8 //Terminate the process + PT_READ_GPR = 11 // Read GPR, CR, PSW + PT_READ_FPR = 12 // Read FPR + PT_READ_VR = 13 // Read VR + PT_WRITE_GPR = 14 // Write GPR, CR, PSW + PT_WRITE_FPR = 15 // Write FPR + PT_WRITE_VR = 16 // Write VR + PT_READ_BLOCK = 17 // Read storage + PT_WRITE_BLOCK = 19 // Write storage + PT_READ_GPRH = 20 // Read GPRH + PT_WRITE_GPRH = 21 // Write GPRH + PT_REGHSET = 22 // Read all GPRHs + PT_ATTACH = 30 // Attach to a process + PT_DETACH = 31 // Detach from a process + PT_REGSET = 32 // Read all GPRs + PT_REATTACH = 33 // Reattach to a process + PT_LDINFO = 34 // Read loader info + PT_MULTI = 35 // Multi process mode + PT_LD64INFO = 36 // RMODE64 Info Area + PT_BLOCKREQ = 40 // Block request + PT_THREAD_INFO = 60 // Read thread info + PT_THREAD_MODIFY = 61 + PT_THREAD_READ_FOCUS = 62 + PT_THREAD_WRITE_FOCUS = 63 + PT_THREAD_HOLD = 64 + PT_THREAD_SIGNAL = 65 + PT_EXPLAIN = 66 + PT_EVENTS = 67 + PT_THREAD_INFO_EXTENDED = 68 + PT_REATTACH2 = 71 + PT_CAPTURE = 72 + PT_UNCAPTURE = 73 + PT_GET_THREAD_TCB = 74 + PT_GET_ALET = 75 + PT_SWAPIN = 76 + PT_EXTENDED_EVENT = 98 + PT_RECOVER = 99 // Debug a program check + PT_GPR0 = 0 // General purpose register 0 + PT_GPR1 = 1 // General purpose register 1 + PT_GPR2 = 2 // General purpose register 2 + PT_GPR3 = 3 // General purpose register 3 + PT_GPR4 = 4 // General purpose register 4 + PT_GPR5 = 5 // General purpose register 5 + PT_GPR6 = 6 // General purpose register 6 + PT_GPR7 = 7 // General purpose register 7 + PT_GPR8 = 8 // General purpose register 8 + PT_GPR9 = 9 // General purpose register 9 + PT_GPR10 = 10 // General purpose register 10 + PT_GPR11 = 11 // General purpose register 11 + PT_GPR12 = 12 // General purpose register 12 + PT_GPR13 = 13 // General purpose register 13 + PT_GPR14 = 14 // General purpose register 14 + PT_GPR15 = 15 // General purpose register 15 + PT_FPR0 = 16 // Floating point register 0 + PT_FPR1 = 17 // Floating point register 1 + PT_FPR2 = 18 // Floating point register 2 + PT_FPR3 = 19 // Floating point register 3 + PT_FPR4 = 20 // Floating point register 4 + PT_FPR5 = 21 // Floating point register 5 + PT_FPR6 = 22 // Floating point register 6 + PT_FPR7 = 23 // Floating point register 7 + PT_FPR8 = 24 // Floating point register 8 + PT_FPR9 = 25 // Floating point register 9 + PT_FPR10 = 26 // Floating point register 10 + PT_FPR11 = 27 // Floating point register 11 + PT_FPR12 = 28 // Floating point register 12 + PT_FPR13 = 29 // Floating point register 13 + PT_FPR14 = 30 // Floating point register 14 + PT_FPR15 = 31 // Floating point register 15 + PT_FPC = 32 // Floating point control register + PT_PSW = 40 // PSW + PT_PSW0 = 40 // Left half of the PSW + PT_PSW1 = 41 // Right half of the PSW + PT_CR0 = 42 // Control register 0 + PT_CR1 = 43 // Control register 1 + PT_CR2 = 44 // Control register 2 + PT_CR3 = 45 // Control register 3 + PT_CR4 = 46 // Control register 4 + PT_CR5 = 47 // Control register 5 + PT_CR6 = 48 // Control register 6 + PT_CR7 = 49 // Control register 7 + PT_CR8 = 50 // Control register 8 + PT_CR9 = 51 // Control register 9 + PT_CR10 = 52 // Control register 10 + PT_CR11 = 53 // Control register 11 + PT_CR12 = 54 // Control register 12 + PT_CR13 = 55 // Control register 13 + PT_CR14 = 56 // Control register 14 + PT_CR15 = 57 // Control register 15 + PT_GPRH0 = 58 // GP High register 0 + PT_GPRH1 = 59 // GP High register 1 + PT_GPRH2 = 60 // GP High register 2 + PT_GPRH3 = 61 // GP High register 3 + PT_GPRH4 = 62 // GP High register 4 + PT_GPRH5 = 63 // GP High register 5 + PT_GPRH6 = 64 // GP High register 6 + PT_GPRH7 = 65 // GP High register 7 + PT_GPRH8 = 66 // GP High register 8 + PT_GPRH9 = 67 // GP High register 9 + PT_GPRH10 = 68 // GP High register 10 + PT_GPRH11 = 69 // GP High register 11 + PT_GPRH12 = 70 // GP High register 12 + PT_GPRH13 = 71 // GP High register 13 + PT_GPRH14 = 72 // GP High register 14 + PT_GPRH15 = 73 // GP High register 15 + PT_VR0 = 74 // Vector register 0 + PT_VR1 = 75 // Vector register 1 + PT_VR2 = 76 // Vector register 2 + PT_VR3 = 77 // Vector register 3 + PT_VR4 = 78 // Vector register 4 + PT_VR5 = 79 // Vector register 5 + PT_VR6 = 80 // Vector register 6 + PT_VR7 = 81 // Vector register 7 + PT_VR8 = 82 // Vector register 8 + PT_VR9 = 83 // Vector register 9 + PT_VR10 = 84 // Vector register 10 + PT_VR11 = 85 // Vector register 11 + PT_VR12 = 86 // Vector register 12 + PT_VR13 = 87 // Vector register 13 + PT_VR14 = 88 // Vector register 14 + PT_VR15 = 89 // Vector register 15 + PT_VR16 = 90 // Vector register 16 + PT_VR17 = 91 // Vector register 17 + PT_VR18 = 92 // Vector register 18 + PT_VR19 = 93 // Vector register 19 + PT_VR20 = 94 // Vector register 20 + PT_VR21 = 95 // Vector register 21 + PT_VR22 = 96 // Vector register 22 + PT_VR23 = 97 // Vector register 23 + PT_VR24 = 98 // Vector register 24 + PT_VR25 = 99 // Vector register 25 + PT_VR26 = 100 // Vector register 26 + PT_VR27 = 101 // Vector register 27 + PT_VR28 = 102 // Vector register 28 + PT_VR29 = 103 // Vector register 29 + PT_VR30 = 104 // Vector register 30 + PT_VR31 = 105 // Vector register 31 + PT_PSWG = 106 // PSWG + PT_PSWG0 = 106 // Bytes 0-3 + PT_PSWG1 = 107 // Bytes 4-7 + PT_PSWG2 = 108 // Bytes 8-11 (IA high word) + PT_PSWG3 = 109 // Bytes 12-15 (IA low word) +) + +func Bpx4ptr(request int32, pid int32, addr unsafe.Pointer, data unsafe.Pointer, buffer unsafe.Pointer) (rv int32, rc int32, rn int32) { + var parms [8]unsafe.Pointer + parms[0] = unsafe.Pointer(&request) + parms[1] = unsafe.Pointer(&pid) + parms[2] = unsafe.Pointer(&addr) + parms[3] = unsafe.Pointer(&data) + parms[4] = unsafe.Pointer(&buffer) + parms[5] = unsafe.Pointer(&rv) + parms[6] = unsafe.Pointer(&rc) + parms[7] = unsafe.Pointer(&rn) + bpxcall(parms[:], BPX4PTR) + return rv, rc, rn +} + +func copyU8(val uint8, dest []uint8) int { + if len(dest) < 1 { + return 0 + } + dest[0] = val + return 1 +} + +func copyU8Arr(src, dest []uint8) int { + if len(dest) < len(src) { + return 0 + } + for i, v := range src { + dest[i] = v + } + return len(src) +} + +func copyU16(val uint16, dest []uint16) int { + if len(dest) < 1 { + return 0 + } + dest[0] = val + return 1 +} + +func copyU32(val uint32, dest []uint32) int { + if len(dest) < 1 { + return 0 + } + dest[0] = val + return 1 +} + +func copyU32Arr(src, dest []uint32) int { + if len(dest) < len(src) { + return 0 + } + for i, v := range src { + dest[i] = v + } + return len(src) +} + +func copyU64(val uint64, dest []uint64) int { + if len(dest) < 1 { + return 0 + } + dest[0] = val + return 1 +} diff --git a/vendor/golang.org/x/sys/unix/bpxsvc_zos.s b/vendor/golang.org/x/sys/unix/bpxsvc_zos.s new file mode 100644 index 000000000..4bd4a1798 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/bpxsvc_zos.s @@ -0,0 +1,192 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include "go_asm.h" +#include "textflag.h" + +// function to call USS assembly language services +// +// doc: https://www.ibm.com/support/knowledgecenter/en/SSLTBW_3.1.0/com.ibm.zos.v3r1.bpxb100/bit64env.htm +// +// arg1 unsafe.Pointer array that ressembles an OS PLIST +// +// arg2 function offset as in +// doc: https://www.ibm.com/support/knowledgecenter/en/SSLTBW_3.1.0/com.ibm.zos.v3r1.bpxb100/bpx2cr_List_of_offsets.htm +// +// func bpxcall(plist []unsafe.Pointer, bpx_offset int64) + +TEXT ·bpxcall(SB), NOSPLIT|NOFRAME, $0 + MOVD plist_base+0(FP), R1 // r1 points to plist + MOVD bpx_offset+24(FP), R2 // r2 offset to BPX vector table + MOVD R14, R7 // save r14 + MOVD R15, R8 // save r15 + MOVWZ 16(R0), R9 + MOVWZ 544(R9), R9 + MOVWZ 24(R9), R9 // call vector in r9 + ADD R2, R9 // add offset to vector table + MOVWZ (R9), R9 // r9 points to entry point + BYTE $0x0D // BL R14,R9 --> basr r14,r9 + BYTE $0xE9 // clobbers 0,1,14,15 + MOVD R8, R15 // restore 15 + JMP R7 // return via saved return address + +// func A2e(arr [] byte) +// code page conversion from 819 to 1047 +TEXT ·A2e(SB), NOSPLIT|NOFRAME, $0 + MOVD arg_base+0(FP), R2 // pointer to arry of characters + MOVD arg_len+8(FP), R3 // count + XOR R0, R0 + XOR R1, R1 + BYTE $0xA7; BYTE $0x15; BYTE $0x00; BYTE $0x82 // BRAS 1,(2+(256/2)) + + // ASCII -> EBCDIC conversion table: + BYTE $0x00; BYTE $0x01; BYTE $0x02; BYTE $0x03 + BYTE $0x37; BYTE $0x2d; BYTE $0x2e; BYTE $0x2f + BYTE $0x16; BYTE $0x05; BYTE $0x15; BYTE $0x0b + BYTE $0x0c; BYTE $0x0d; BYTE $0x0e; BYTE $0x0f + BYTE $0x10; BYTE $0x11; BYTE $0x12; BYTE $0x13 + BYTE $0x3c; BYTE $0x3d; BYTE $0x32; BYTE $0x26 + BYTE $0x18; BYTE $0x19; BYTE $0x3f; BYTE $0x27 + BYTE $0x1c; BYTE $0x1d; BYTE $0x1e; BYTE $0x1f + BYTE $0x40; BYTE $0x5a; BYTE $0x7f; BYTE $0x7b + BYTE $0x5b; BYTE $0x6c; BYTE $0x50; BYTE $0x7d + BYTE $0x4d; BYTE $0x5d; BYTE $0x5c; BYTE $0x4e + BYTE $0x6b; BYTE $0x60; BYTE $0x4b; BYTE $0x61 + BYTE $0xf0; BYTE $0xf1; BYTE $0xf2; BYTE $0xf3 + BYTE $0xf4; BYTE $0xf5; BYTE $0xf6; BYTE $0xf7 + BYTE $0xf8; BYTE $0xf9; BYTE $0x7a; BYTE $0x5e + BYTE $0x4c; BYTE $0x7e; BYTE $0x6e; BYTE $0x6f + BYTE $0x7c; BYTE $0xc1; BYTE $0xc2; BYTE $0xc3 + BYTE $0xc4; BYTE $0xc5; BYTE $0xc6; BYTE $0xc7 + BYTE $0xc8; BYTE $0xc9; BYTE $0xd1; BYTE $0xd2 + BYTE $0xd3; BYTE $0xd4; BYTE $0xd5; BYTE $0xd6 + BYTE $0xd7; BYTE $0xd8; BYTE $0xd9; BYTE $0xe2 + BYTE $0xe3; BYTE $0xe4; BYTE $0xe5; BYTE $0xe6 + BYTE $0xe7; BYTE $0xe8; BYTE $0xe9; BYTE $0xad + BYTE $0xe0; BYTE $0xbd; BYTE $0x5f; BYTE $0x6d + BYTE $0x79; BYTE $0x81; BYTE $0x82; BYTE $0x83 + BYTE $0x84; BYTE $0x85; BYTE $0x86; BYTE $0x87 + BYTE $0x88; BYTE $0x89; BYTE $0x91; BYTE $0x92 + BYTE $0x93; BYTE $0x94; BYTE $0x95; BYTE $0x96 + BYTE $0x97; BYTE $0x98; BYTE $0x99; BYTE $0xa2 + BYTE $0xa3; BYTE $0xa4; BYTE $0xa5; BYTE $0xa6 + BYTE $0xa7; BYTE $0xa8; BYTE $0xa9; BYTE $0xc0 + BYTE $0x4f; BYTE $0xd0; BYTE $0xa1; BYTE $0x07 + BYTE $0x20; BYTE $0x21; BYTE $0x22; BYTE $0x23 + BYTE $0x24; BYTE $0x25; BYTE $0x06; BYTE $0x17 + BYTE $0x28; BYTE $0x29; BYTE $0x2a; BYTE $0x2b + BYTE $0x2c; BYTE $0x09; BYTE $0x0a; BYTE $0x1b + BYTE $0x30; BYTE $0x31; BYTE $0x1a; BYTE $0x33 + BYTE $0x34; BYTE $0x35; BYTE $0x36; BYTE $0x08 + BYTE $0x38; BYTE $0x39; BYTE $0x3a; BYTE $0x3b + BYTE $0x04; BYTE $0x14; BYTE $0x3e; BYTE $0xff + BYTE $0x41; BYTE $0xaa; BYTE $0x4a; BYTE $0xb1 + BYTE $0x9f; BYTE $0xb2; BYTE $0x6a; BYTE $0xb5 + BYTE $0xbb; BYTE $0xb4; BYTE $0x9a; BYTE $0x8a + BYTE $0xb0; BYTE $0xca; BYTE $0xaf; BYTE $0xbc + BYTE $0x90; BYTE $0x8f; BYTE $0xea; BYTE $0xfa + BYTE $0xbe; BYTE $0xa0; BYTE $0xb6; BYTE $0xb3 + BYTE $0x9d; BYTE $0xda; BYTE $0x9b; BYTE $0x8b + BYTE $0xb7; BYTE $0xb8; BYTE $0xb9; BYTE $0xab + BYTE $0x64; BYTE $0x65; BYTE $0x62; BYTE $0x66 + BYTE $0x63; BYTE $0x67; BYTE $0x9e; BYTE $0x68 + BYTE $0x74; BYTE $0x71; BYTE $0x72; BYTE $0x73 + BYTE $0x78; BYTE $0x75; BYTE $0x76; BYTE $0x77 + BYTE $0xac; BYTE $0x69; BYTE $0xed; BYTE $0xee + BYTE $0xeb; BYTE $0xef; BYTE $0xec; BYTE $0xbf + BYTE $0x80; BYTE $0xfd; BYTE $0xfe; BYTE $0xfb + BYTE $0xfc; BYTE $0xba; BYTE $0xae; BYTE $0x59 + BYTE $0x44; BYTE $0x45; BYTE $0x42; BYTE $0x46 + BYTE $0x43; BYTE $0x47; BYTE $0x9c; BYTE $0x48 + BYTE $0x54; BYTE $0x51; BYTE $0x52; BYTE $0x53 + BYTE $0x58; BYTE $0x55; BYTE $0x56; BYTE $0x57 + BYTE $0x8c; BYTE $0x49; BYTE $0xcd; BYTE $0xce + BYTE $0xcb; BYTE $0xcf; BYTE $0xcc; BYTE $0xe1 + BYTE $0x70; BYTE $0xdd; BYTE $0xde; BYTE $0xdb + BYTE $0xdc; BYTE $0x8d; BYTE $0x8e; BYTE $0xdf + +retry: + WORD $0xB9931022 // TROO 2,2,b'0001' + BVS retry + RET + +// func e2a(arr [] byte) +// code page conversion from 1047 to 819 +TEXT ·E2a(SB), NOSPLIT|NOFRAME, $0 + MOVD arg_base+0(FP), R2 // pointer to arry of characters + MOVD arg_len+8(FP), R3 // count + XOR R0, R0 + XOR R1, R1 + BYTE $0xA7; BYTE $0x15; BYTE $0x00; BYTE $0x82 // BRAS 1,(2+(256/2)) + + // EBCDIC -> ASCII conversion table: + BYTE $0x00; BYTE $0x01; BYTE $0x02; BYTE $0x03 + BYTE $0x9c; BYTE $0x09; BYTE $0x86; BYTE $0x7f + BYTE $0x97; BYTE $0x8d; BYTE $0x8e; BYTE $0x0b + BYTE $0x0c; BYTE $0x0d; BYTE $0x0e; BYTE $0x0f + BYTE $0x10; BYTE $0x11; BYTE $0x12; BYTE $0x13 + BYTE $0x9d; BYTE $0x0a; BYTE $0x08; BYTE $0x87 + BYTE $0x18; BYTE $0x19; BYTE $0x92; BYTE $0x8f + BYTE $0x1c; BYTE $0x1d; BYTE $0x1e; BYTE $0x1f + BYTE $0x80; BYTE $0x81; BYTE $0x82; BYTE $0x83 + BYTE $0x84; BYTE $0x85; BYTE $0x17; BYTE $0x1b + BYTE $0x88; BYTE $0x89; BYTE $0x8a; BYTE $0x8b + BYTE $0x8c; BYTE $0x05; BYTE $0x06; BYTE $0x07 + BYTE $0x90; BYTE $0x91; BYTE $0x16; BYTE $0x93 + BYTE $0x94; BYTE $0x95; BYTE $0x96; BYTE $0x04 + BYTE $0x98; BYTE $0x99; BYTE $0x9a; BYTE $0x9b + BYTE $0x14; BYTE $0x15; BYTE $0x9e; BYTE $0x1a + BYTE $0x20; BYTE $0xa0; BYTE $0xe2; BYTE $0xe4 + BYTE $0xe0; BYTE $0xe1; BYTE $0xe3; BYTE $0xe5 + BYTE $0xe7; BYTE $0xf1; BYTE $0xa2; BYTE $0x2e + BYTE $0x3c; BYTE $0x28; BYTE $0x2b; BYTE $0x7c + BYTE $0x26; BYTE $0xe9; BYTE $0xea; BYTE $0xeb + BYTE $0xe8; BYTE $0xed; BYTE $0xee; BYTE $0xef + BYTE $0xec; BYTE $0xdf; BYTE $0x21; BYTE $0x24 + BYTE $0x2a; BYTE $0x29; BYTE $0x3b; BYTE $0x5e + BYTE $0x2d; BYTE $0x2f; BYTE $0xc2; BYTE $0xc4 + BYTE $0xc0; BYTE $0xc1; BYTE $0xc3; BYTE $0xc5 + BYTE $0xc7; BYTE $0xd1; BYTE $0xa6; BYTE $0x2c + BYTE $0x25; BYTE $0x5f; BYTE $0x3e; BYTE $0x3f + BYTE $0xf8; BYTE $0xc9; BYTE $0xca; BYTE $0xcb + BYTE $0xc8; BYTE $0xcd; BYTE $0xce; BYTE $0xcf + BYTE $0xcc; BYTE $0x60; BYTE $0x3a; BYTE $0x23 + BYTE $0x40; BYTE $0x27; BYTE $0x3d; BYTE $0x22 + BYTE $0xd8; BYTE $0x61; BYTE $0x62; BYTE $0x63 + BYTE $0x64; BYTE $0x65; BYTE $0x66; BYTE $0x67 + BYTE $0x68; BYTE $0x69; BYTE $0xab; BYTE $0xbb + BYTE $0xf0; BYTE $0xfd; BYTE $0xfe; BYTE $0xb1 + BYTE $0xb0; BYTE $0x6a; BYTE $0x6b; BYTE $0x6c + BYTE $0x6d; BYTE $0x6e; BYTE $0x6f; BYTE $0x70 + BYTE $0x71; BYTE $0x72; BYTE $0xaa; BYTE $0xba + BYTE $0xe6; BYTE $0xb8; BYTE $0xc6; BYTE $0xa4 + BYTE $0xb5; BYTE $0x7e; BYTE $0x73; BYTE $0x74 + BYTE $0x75; BYTE $0x76; BYTE $0x77; BYTE $0x78 + BYTE $0x79; BYTE $0x7a; BYTE $0xa1; BYTE $0xbf + BYTE $0xd0; BYTE $0x5b; BYTE $0xde; BYTE $0xae + BYTE $0xac; BYTE $0xa3; BYTE $0xa5; BYTE $0xb7 + BYTE $0xa9; BYTE $0xa7; BYTE $0xb6; BYTE $0xbc + BYTE $0xbd; BYTE $0xbe; BYTE $0xdd; BYTE $0xa8 + BYTE $0xaf; BYTE $0x5d; BYTE $0xb4; BYTE $0xd7 + BYTE $0x7b; BYTE $0x41; BYTE $0x42; BYTE $0x43 + BYTE $0x44; BYTE $0x45; BYTE $0x46; BYTE $0x47 + BYTE $0x48; BYTE $0x49; BYTE $0xad; BYTE $0xf4 + BYTE $0xf6; BYTE $0xf2; BYTE $0xf3; BYTE $0xf5 + BYTE $0x7d; BYTE $0x4a; BYTE $0x4b; BYTE $0x4c + BYTE $0x4d; BYTE $0x4e; BYTE $0x4f; BYTE $0x50 + BYTE $0x51; BYTE $0x52; BYTE $0xb9; BYTE $0xfb + BYTE $0xfc; BYTE $0xf9; BYTE $0xfa; BYTE $0xff + BYTE $0x5c; BYTE $0xf7; BYTE $0x53; BYTE $0x54 + BYTE $0x55; BYTE $0x56; BYTE $0x57; BYTE $0x58 + BYTE $0x59; BYTE $0x5a; BYTE $0xb2; BYTE $0xd4 + BYTE $0xd6; BYTE $0xd2; BYTE $0xd3; BYTE $0xd5 + BYTE $0x30; BYTE $0x31; BYTE $0x32; BYTE $0x33 + BYTE $0x34; BYTE $0x35; BYTE $0x36; BYTE $0x37 + BYTE $0x38; BYTE $0x39; BYTE $0xb3; BYTE $0xdb + BYTE $0xdc; BYTE $0xd9; BYTE $0xda; BYTE $0x9f + +retry: + WORD $0xB9931022 // TROO 2,2,b'0001' + BVS retry + RET diff --git a/vendor/golang.org/x/sys/unix/epoll_zos.go b/vendor/golang.org/x/sys/unix/epoll_zos.go deleted file mode 100644 index 7753fddea..000000000 --- a/vendor/golang.org/x/sys/unix/epoll_zos.go +++ /dev/null @@ -1,220 +0,0 @@ -// Copyright 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build zos && s390x - -package unix - -import ( - "sync" -) - -// This file simulates epoll on z/OS using poll. - -// Analogous to epoll_event on Linux. -// TODO(neeilan): Pad is because the Linux kernel expects a 96-bit struct. We never pass this to the kernel; remove? -type EpollEvent struct { - Events uint32 - Fd int32 - Pad int32 -} - -const ( - EPOLLERR = 0x8 - EPOLLHUP = 0x10 - EPOLLIN = 0x1 - EPOLLMSG = 0x400 - EPOLLOUT = 0x4 - EPOLLPRI = 0x2 - EPOLLRDBAND = 0x80 - EPOLLRDNORM = 0x40 - EPOLLWRBAND = 0x200 - EPOLLWRNORM = 0x100 - EPOLL_CTL_ADD = 0x1 - EPOLL_CTL_DEL = 0x2 - EPOLL_CTL_MOD = 0x3 - // The following constants are part of the epoll API, but represent - // currently unsupported functionality on z/OS. - // EPOLL_CLOEXEC = 0x80000 - // EPOLLET = 0x80000000 - // EPOLLONESHOT = 0x40000000 - // EPOLLRDHUP = 0x2000 // Typically used with edge-triggered notis - // EPOLLEXCLUSIVE = 0x10000000 // Exclusive wake-up mode - // EPOLLWAKEUP = 0x20000000 // Relies on Linux's BLOCK_SUSPEND capability -) - -// TODO(neeilan): We can eliminate these epToPoll / pToEpoll calls by using identical mask values for POLL/EPOLL -// constants where possible The lower 16 bits of epoll events (uint32) can fit any system poll event (int16). - -// epToPollEvt converts epoll event field to poll equivalent. -// In epoll, Events is a 32-bit field, while poll uses 16 bits. -func epToPollEvt(events uint32) int16 { - var ep2p = map[uint32]int16{ - EPOLLIN: POLLIN, - EPOLLOUT: POLLOUT, - EPOLLHUP: POLLHUP, - EPOLLPRI: POLLPRI, - EPOLLERR: POLLERR, - } - - var pollEvts int16 = 0 - for epEvt, pEvt := range ep2p { - if (events & epEvt) != 0 { - pollEvts |= pEvt - } - } - - return pollEvts -} - -// pToEpollEvt converts 16 bit poll event bitfields to 32-bit epoll event fields. -func pToEpollEvt(revents int16) uint32 { - var p2ep = map[int16]uint32{ - POLLIN: EPOLLIN, - POLLOUT: EPOLLOUT, - POLLHUP: EPOLLHUP, - POLLPRI: EPOLLPRI, - POLLERR: EPOLLERR, - } - - var epollEvts uint32 = 0 - for pEvt, epEvt := range p2ep { - if (revents & pEvt) != 0 { - epollEvts |= epEvt - } - } - - return epollEvts -} - -// Per-process epoll implementation. -type epollImpl struct { - mu sync.Mutex - epfd2ep map[int]*eventPoll - nextEpfd int -} - -// eventPoll holds a set of file descriptors being watched by the process. A process can have multiple epoll instances. -// On Linux, this is an in-kernel data structure accessed through a fd. -type eventPoll struct { - mu sync.Mutex - fds map[int]*EpollEvent -} - -// epoll impl for this process. -var impl epollImpl = epollImpl{ - epfd2ep: make(map[int]*eventPoll), - nextEpfd: 0, -} - -func (e *epollImpl) epollcreate(size int) (epfd int, err error) { - e.mu.Lock() - defer e.mu.Unlock() - epfd = e.nextEpfd - e.nextEpfd++ - - e.epfd2ep[epfd] = &eventPoll{ - fds: make(map[int]*EpollEvent), - } - return epfd, nil -} - -func (e *epollImpl) epollcreate1(flag int) (fd int, err error) { - return e.epollcreate(4) -} - -func (e *epollImpl) epollctl(epfd int, op int, fd int, event *EpollEvent) (err error) { - e.mu.Lock() - defer e.mu.Unlock() - - ep, ok := e.epfd2ep[epfd] - if !ok { - - return EBADF - } - - switch op { - case EPOLL_CTL_ADD: - // TODO(neeilan): When we make epfds and fds disjoint, detect epoll - // loops here (instances watching each other) and return ELOOP. - if _, ok := ep.fds[fd]; ok { - return EEXIST - } - ep.fds[fd] = event - case EPOLL_CTL_MOD: - if _, ok := ep.fds[fd]; !ok { - return ENOENT - } - ep.fds[fd] = event - case EPOLL_CTL_DEL: - if _, ok := ep.fds[fd]; !ok { - return ENOENT - } - delete(ep.fds, fd) - - } - return nil -} - -// Must be called while holding ep.mu -func (ep *eventPoll) getFds() []int { - fds := make([]int, len(ep.fds)) - for fd := range ep.fds { - fds = append(fds, fd) - } - return fds -} - -func (e *epollImpl) epollwait(epfd int, events []EpollEvent, msec int) (n int, err error) { - e.mu.Lock() // in [rare] case of concurrent epollcreate + epollwait - ep, ok := e.epfd2ep[epfd] - - if !ok { - e.mu.Unlock() - return 0, EBADF - } - - pollfds := make([]PollFd, 4) - for fd, epollevt := range ep.fds { - pollfds = append(pollfds, PollFd{Fd: int32(fd), Events: epToPollEvt(epollevt.Events)}) - } - e.mu.Unlock() - - n, err = Poll(pollfds, msec) - if err != nil { - return n, err - } - - i := 0 - for _, pFd := range pollfds { - if pFd.Revents != 0 { - events[i] = EpollEvent{Fd: pFd.Fd, Events: pToEpollEvt(pFd.Revents)} - i++ - } - - if i == n { - break - } - } - - return n, nil -} - -func EpollCreate(size int) (fd int, err error) { - return impl.epollcreate(size) -} - -func EpollCreate1(flag int) (fd int, err error) { - return impl.epollcreate1(flag) -} - -func EpollCtl(epfd int, op int, fd int, event *EpollEvent) (err error) { - return impl.epollctl(epfd, op, fd, event) -} - -// Because EpollWait mutates events, the caller is expected to coordinate -// concurrent access if calling with the same epfd from multiple goroutines. -func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) { - return impl.epollwait(epfd, events, msec) -} diff --git a/vendor/golang.org/x/sys/unix/fstatfs_zos.go b/vendor/golang.org/x/sys/unix/fstatfs_zos.go deleted file mode 100644 index c8bde601e..000000000 --- a/vendor/golang.org/x/sys/unix/fstatfs_zos.go +++ /dev/null @@ -1,163 +0,0 @@ -// Copyright 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build zos && s390x - -package unix - -import ( - "unsafe" -) - -// This file simulates fstatfs on z/OS using fstatvfs and w_getmntent. - -func Fstatfs(fd int, stat *Statfs_t) (err error) { - var stat_v Statvfs_t - err = Fstatvfs(fd, &stat_v) - if err == nil { - // populate stat - stat.Type = 0 - stat.Bsize = stat_v.Bsize - stat.Blocks = stat_v.Blocks - stat.Bfree = stat_v.Bfree - stat.Bavail = stat_v.Bavail - stat.Files = stat_v.Files - stat.Ffree = stat_v.Ffree - stat.Fsid = stat_v.Fsid - stat.Namelen = stat_v.Namemax - stat.Frsize = stat_v.Frsize - stat.Flags = stat_v.Flag - for passn := 0; passn < 5; passn++ { - switch passn { - case 0: - err = tryGetmntent64(stat) - break - case 1: - err = tryGetmntent128(stat) - break - case 2: - err = tryGetmntent256(stat) - break - case 3: - err = tryGetmntent512(stat) - break - case 4: - err = tryGetmntent1024(stat) - break - default: - break - } - //proceed to return if: err is nil (found), err is nonnil but not ERANGE (another error occurred) - if err == nil || err != nil && err != ERANGE { - break - } - } - } - return err -} - -func tryGetmntent64(stat *Statfs_t) (err error) { - var mnt_ent_buffer struct { - header W_Mnth - filesys_info [64]W_Mntent - } - var buffer_size int = int(unsafe.Sizeof(mnt_ent_buffer)) - fs_count, err := W_Getmntent((*byte)(unsafe.Pointer(&mnt_ent_buffer)), buffer_size) - if err != nil { - return err - } - err = ERANGE //return ERANGE if no match is found in this batch - for i := 0; i < fs_count; i++ { - if stat.Fsid == uint64(mnt_ent_buffer.filesys_info[i].Dev) { - stat.Type = uint32(mnt_ent_buffer.filesys_info[i].Fstname[0]) - err = nil - break - } - } - return err -} - -func tryGetmntent128(stat *Statfs_t) (err error) { - var mnt_ent_buffer struct { - header W_Mnth - filesys_info [128]W_Mntent - } - var buffer_size int = int(unsafe.Sizeof(mnt_ent_buffer)) - fs_count, err := W_Getmntent((*byte)(unsafe.Pointer(&mnt_ent_buffer)), buffer_size) - if err != nil { - return err - } - err = ERANGE //return ERANGE if no match is found in this batch - for i := 0; i < fs_count; i++ { - if stat.Fsid == uint64(mnt_ent_buffer.filesys_info[i].Dev) { - stat.Type = uint32(mnt_ent_buffer.filesys_info[i].Fstname[0]) - err = nil - break - } - } - return err -} - -func tryGetmntent256(stat *Statfs_t) (err error) { - var mnt_ent_buffer struct { - header W_Mnth - filesys_info [256]W_Mntent - } - var buffer_size int = int(unsafe.Sizeof(mnt_ent_buffer)) - fs_count, err := W_Getmntent((*byte)(unsafe.Pointer(&mnt_ent_buffer)), buffer_size) - if err != nil { - return err - } - err = ERANGE //return ERANGE if no match is found in this batch - for i := 0; i < fs_count; i++ { - if stat.Fsid == uint64(mnt_ent_buffer.filesys_info[i].Dev) { - stat.Type = uint32(mnt_ent_buffer.filesys_info[i].Fstname[0]) - err = nil - break - } - } - return err -} - -func tryGetmntent512(stat *Statfs_t) (err error) { - var mnt_ent_buffer struct { - header W_Mnth - filesys_info [512]W_Mntent - } - var buffer_size int = int(unsafe.Sizeof(mnt_ent_buffer)) - fs_count, err := W_Getmntent((*byte)(unsafe.Pointer(&mnt_ent_buffer)), buffer_size) - if err != nil { - return err - } - err = ERANGE //return ERANGE if no match is found in this batch - for i := 0; i < fs_count; i++ { - if stat.Fsid == uint64(mnt_ent_buffer.filesys_info[i].Dev) { - stat.Type = uint32(mnt_ent_buffer.filesys_info[i].Fstname[0]) - err = nil - break - } - } - return err -} - -func tryGetmntent1024(stat *Statfs_t) (err error) { - var mnt_ent_buffer struct { - header W_Mnth - filesys_info [1024]W_Mntent - } - var buffer_size int = int(unsafe.Sizeof(mnt_ent_buffer)) - fs_count, err := W_Getmntent((*byte)(unsafe.Pointer(&mnt_ent_buffer)), buffer_size) - if err != nil { - return err - } - err = ERANGE //return ERANGE if no match is found in this batch - for i := 0; i < fs_count; i++ { - if stat.Fsid == uint64(mnt_ent_buffer.filesys_info[i].Dev) { - stat.Type = uint32(mnt_ent_buffer.filesys_info[i].Fstname[0]) - err = nil - break - } - } - return err -} diff --git a/vendor/golang.org/x/sys/unix/ioctl_linux.go b/vendor/golang.org/x/sys/unix/ioctl_linux.go index dbe680eab..7ca4fa12a 100644 --- a/vendor/golang.org/x/sys/unix/ioctl_linux.go +++ b/vendor/golang.org/x/sys/unix/ioctl_linux.go @@ -58,6 +58,102 @@ func IoctlGetEthtoolDrvinfo(fd int, ifname string) (*EthtoolDrvinfo, error) { return &value, err } +// IoctlGetEthtoolTsInfo fetches ethtool timestamping and PHC +// association for the network device specified by ifname. +func IoctlGetEthtoolTsInfo(fd int, ifname string) (*EthtoolTsInfo, error) { + ifr, err := NewIfreq(ifname) + if err != nil { + return nil, err + } + + value := EthtoolTsInfo{Cmd: ETHTOOL_GET_TS_INFO} + ifrd := ifr.withData(unsafe.Pointer(&value)) + + err = ioctlIfreqData(fd, SIOCETHTOOL, &ifrd) + return &value, err +} + +// IoctlGetHwTstamp retrieves the hardware timestamping configuration +// for the network device specified by ifname. +func IoctlGetHwTstamp(fd int, ifname string) (*HwTstampConfig, error) { + ifr, err := NewIfreq(ifname) + if err != nil { + return nil, err + } + + value := HwTstampConfig{} + ifrd := ifr.withData(unsafe.Pointer(&value)) + + err = ioctlIfreqData(fd, SIOCGHWTSTAMP, &ifrd) + return &value, err +} + +// IoctlSetHwTstamp updates the hardware timestamping configuration for +// the network device specified by ifname. +func IoctlSetHwTstamp(fd int, ifname string, cfg *HwTstampConfig) error { + ifr, err := NewIfreq(ifname) + if err != nil { + return err + } + ifrd := ifr.withData(unsafe.Pointer(cfg)) + return ioctlIfreqData(fd, SIOCSHWTSTAMP, &ifrd) +} + +// FdToClockID derives the clock ID from the file descriptor number +// - see clock_gettime(3), FD_TO_CLOCKID macros. The resulting ID is +// suitable for system calls like ClockGettime. +func FdToClockID(fd int) int32 { return int32((int(^fd) << 3) | 3) } + +// IoctlPtpClockGetcaps returns the description of a given PTP device. +func IoctlPtpClockGetcaps(fd int) (*PtpClockCaps, error) { + var value PtpClockCaps + err := ioctlPtr(fd, PTP_CLOCK_GETCAPS2, unsafe.Pointer(&value)) + return &value, err +} + +// IoctlPtpSysOffsetPrecise returns a description of the clock +// offset compared to the system clock. +func IoctlPtpSysOffsetPrecise(fd int) (*PtpSysOffsetPrecise, error) { + var value PtpSysOffsetPrecise + err := ioctlPtr(fd, PTP_SYS_OFFSET_PRECISE2, unsafe.Pointer(&value)) + return &value, err +} + +// IoctlPtpSysOffsetExtended returns an extended description of the +// clock offset compared to the system clock. The samples parameter +// specifies the desired number of measurements. +func IoctlPtpSysOffsetExtended(fd int, samples uint) (*PtpSysOffsetExtended, error) { + value := PtpSysOffsetExtended{Samples: uint32(samples)} + err := ioctlPtr(fd, PTP_SYS_OFFSET_EXTENDED2, unsafe.Pointer(&value)) + return &value, err +} + +// IoctlPtpPinGetfunc returns the configuration of the specified +// I/O pin on given PTP device. +func IoctlPtpPinGetfunc(fd int, index uint) (*PtpPinDesc, error) { + value := PtpPinDesc{Index: uint32(index)} + err := ioctlPtr(fd, PTP_PIN_GETFUNC2, unsafe.Pointer(&value)) + return &value, err +} + +// IoctlPtpPinSetfunc updates configuration of the specified PTP +// I/O pin. +func IoctlPtpPinSetfunc(fd int, pd *PtpPinDesc) error { + return ioctlPtr(fd, PTP_PIN_SETFUNC2, unsafe.Pointer(pd)) +} + +// IoctlPtpPeroutRequest configures the periodic output mode of the +// PTP I/O pins. +func IoctlPtpPeroutRequest(fd int, r *PtpPeroutRequest) error { + return ioctlPtr(fd, PTP_PEROUT_REQUEST2, unsafe.Pointer(r)) +} + +// IoctlPtpExttsRequest configures the external timestamping mode +// of the PTP I/O pins. +func IoctlPtpExttsRequest(fd int, r *PtpExttsRequest) error { + return ioctlPtr(fd, PTP_EXTTS_REQUEST2, unsafe.Pointer(r)) +} + // IoctlGetWatchdogInfo fetches information about a watchdog device from the // Linux watchdog API. For more information, see: // https://www.kernel.org/doc/html/latest/watchdog/watchdog-api.html. diff --git a/vendor/golang.org/x/sys/unix/mkerrors.sh b/vendor/golang.org/x/sys/unix/mkerrors.sh index fdcaa974d..6ab02b6c3 100644 --- a/vendor/golang.org/x/sys/unix/mkerrors.sh +++ b/vendor/golang.org/x/sys/unix/mkerrors.sh @@ -58,6 +58,7 @@ includes_Darwin=' #define _DARWIN_USE_64_BIT_INODE #define __APPLE_USE_RFC_3542 #include +#include #include #include #include @@ -157,6 +158,16 @@ includes_Linux=' #endif #define _GNU_SOURCE +// See the description in unix/linux/types.go +#if defined(__ARM_EABI__) || \ + (defined(__mips__) && (_MIPS_SIM == _ABIO32)) || \ + (defined(__powerpc__) && (!defined(__powerpc64__))) +# ifdef _TIME_BITS +# undef _TIME_BITS +# endif +# define _TIME_BITS 32 +#endif + // is broken on powerpc64, as it fails to include definitions of // these structures. We just include them copied from . #if defined(__powerpc__) @@ -255,6 +266,7 @@ struct ltchars { #include #include #include +#include #include #include #include @@ -263,6 +275,7 @@ struct ltchars { #include #include #include +#include #include #include #include @@ -525,6 +538,7 @@ ccflags="$@" $2 ~ /^(AF|SOCK|SO|SOL|IPPROTO|IP|IPV6|TCP|MCAST|EVFILT|NOTE|SHUT|PROT|MAP|MREMAP|MFD|T?PACKET|MSG|SCM|MCL|DT|MADV|PR|LOCAL|TCPOPT|UDP)_/ || $2 ~ /^NFC_(GENL|PROTO|COMM|RF|SE|DIRECTION|LLCP|SOCKPROTO)_/ || $2 ~ /^NFC_.*_(MAX)?SIZE$/ || + $2 ~ /^PTP_/ || $2 ~ /^RAW_PAYLOAD_/ || $2 ~ /^[US]F_/ || $2 ~ /^TP_STATUS_/ || @@ -549,6 +563,8 @@ ccflags="$@" $2 !~ "NLA_TYPE_MASK" && $2 !~ /^RTC_VL_(ACCURACY|BACKUP|DATA)/ && $2 ~ /^(NETLINK|NLM|NLMSG|NLA|IFA|IFAN|RT|RTC|RTCF|RTN|RTPROT|RTNH|ARPHRD|ETH_P|NETNSA)_/ || + $2 ~ /^SOCK_|SK_DIAG_|SKNLGRP_$/ || + $2 ~ /^(CONNECT|SAE)_/ || $2 ~ /^FIORDCHK$/ || $2 ~ /^SIOC/ || $2 ~ /^TIOC/ || @@ -652,7 +668,7 @@ errors=$( signals=$( echo '#include ' | $CC -x c - -E -dM $ccflags | awk '$1=="#define" && $2 ~ /^SIG[A-Z0-9]+$/ { print $2 }' | - grep -v 'SIGSTKSIZE\|SIGSTKSZ\|SIGRT\|SIGMAX64' | + grep -E -v '(SIGSTKSIZE|SIGSTKSZ|SIGRT|SIGMAX64)' | sort ) @@ -662,7 +678,7 @@ echo '#include ' | $CC -x c - -E -dM $ccflags | sort >_error.grep echo '#include ' | $CC -x c - -E -dM $ccflags | awk '$1=="#define" && $2 ~ /^SIG[A-Z0-9]+$/ { print "^\t" $2 "[ \t]*=" }' | - grep -v 'SIGSTKSIZE\|SIGSTKSZ\|SIGRT\|SIGMAX64' | + grep -E -v '(SIGSTKSIZE|SIGSTKSZ|SIGRT|SIGMAX64)' | sort >_signal.grep echo '// mkerrors.sh' "$@" diff --git a/vendor/golang.org/x/sys/unix/mremap.go b/vendor/golang.org/x/sys/unix/mremap.go index fd45fe529..3a5e776f8 100644 --- a/vendor/golang.org/x/sys/unix/mremap.go +++ b/vendor/golang.org/x/sys/unix/mremap.go @@ -50,3 +50,8 @@ func (m *mremapMmapper) Mremap(oldData []byte, newLength int, flags int) (data [ func Mremap(oldData []byte, newLength int, flags int) (data []byte, err error) { return mapper.Mremap(oldData, newLength, flags) } + +func MremapPtr(oldAddr unsafe.Pointer, oldSize uintptr, newAddr unsafe.Pointer, newSize uintptr, flags int) (ret unsafe.Pointer, err error) { + xaddr, err := mapper.mremap(uintptr(oldAddr), oldSize, newSize, flags, uintptr(newAddr)) + return unsafe.Pointer(xaddr), err +} diff --git a/vendor/golang.org/x/sys/unix/pagesize_unix.go b/vendor/golang.org/x/sys/unix/pagesize_unix.go index 4d0a3430e..0482408d7 100644 --- a/vendor/golang.org/x/sys/unix/pagesize_unix.go +++ b/vendor/golang.org/x/sys/unix/pagesize_unix.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris +//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos // For Unix, get the pagesize from the runtime. diff --git a/vendor/golang.org/x/sys/unix/readdirent_getdirentries.go b/vendor/golang.org/x/sys/unix/readdirent_getdirentries.go index 130398b6b..b903c0060 100644 --- a/vendor/golang.org/x/sys/unix/readdirent_getdirentries.go +++ b/vendor/golang.org/x/sys/unix/readdirent_getdirentries.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build darwin +//go:build darwin || zos package unix diff --git a/vendor/golang.org/x/sys/unix/sockcmsg_zos.go b/vendor/golang.org/x/sys/unix/sockcmsg_zos.go new file mode 100644 index 000000000..3e53dbc02 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/sockcmsg_zos.go @@ -0,0 +1,58 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Socket control messages + +package unix + +import "unsafe" + +// UnixCredentials encodes credentials into a socket control message +// for sending to another process. This can be used for +// authentication. +func UnixCredentials(ucred *Ucred) []byte { + b := make([]byte, CmsgSpace(SizeofUcred)) + h := (*Cmsghdr)(unsafe.Pointer(&b[0])) + h.Level = SOL_SOCKET + h.Type = SCM_CREDENTIALS + h.SetLen(CmsgLen(SizeofUcred)) + *(*Ucred)(h.data(0)) = *ucred + return b +} + +// ParseUnixCredentials decodes a socket control message that contains +// credentials in a Ucred structure. To receive such a message, the +// SO_PASSCRED option must be enabled on the socket. +func ParseUnixCredentials(m *SocketControlMessage) (*Ucred, error) { + if m.Header.Level != SOL_SOCKET { + return nil, EINVAL + } + if m.Header.Type != SCM_CREDENTIALS { + return nil, EINVAL + } + ucred := *(*Ucred)(unsafe.Pointer(&m.Data[0])) + return &ucred, nil +} + +// PktInfo4 encodes Inet4Pktinfo into a socket control message of type IP_PKTINFO. +func PktInfo4(info *Inet4Pktinfo) []byte { + b := make([]byte, CmsgSpace(SizeofInet4Pktinfo)) + h := (*Cmsghdr)(unsafe.Pointer(&b[0])) + h.Level = SOL_IP + h.Type = IP_PKTINFO + h.SetLen(CmsgLen(SizeofInet4Pktinfo)) + *(*Inet4Pktinfo)(h.data(0)) = *info + return b +} + +// PktInfo6 encodes Inet6Pktinfo into a socket control message of type IPV6_PKTINFO. +func PktInfo6(info *Inet6Pktinfo) []byte { + b := make([]byte, CmsgSpace(SizeofInet6Pktinfo)) + h := (*Cmsghdr)(unsafe.Pointer(&b[0])) + h.Level = SOL_IPV6 + h.Type = IPV6_PKTINFO + h.SetLen(CmsgLen(SizeofInet6Pktinfo)) + *(*Inet6Pktinfo)(h.data(0)) = *info + return b +} diff --git a/vendor/golang.org/x/sys/unix/symaddr_zos_s390x.s b/vendor/golang.org/x/sys/unix/symaddr_zos_s390x.s new file mode 100644 index 000000000..3c4f33cb6 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/symaddr_zos_s390x.s @@ -0,0 +1,75 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build zos && s390x && gc + +#include "textflag.h" + +// provide the address of function variable to be fixed up. + +TEXT ·getPipe2Addr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Pipe2(SB), R8 + MOVD R8, ret+0(FP) + RET + +TEXT ·get_FlockAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Flock(SB), R8 + MOVD R8, ret+0(FP) + RET + +TEXT ·get_GetxattrAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Getxattr(SB), R8 + MOVD R8, ret+0(FP) + RET + +TEXT ·get_NanosleepAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Nanosleep(SB), R8 + MOVD R8, ret+0(FP) + RET + +TEXT ·get_SetxattrAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Setxattr(SB), R8 + MOVD R8, ret+0(FP) + RET + +TEXT ·get_Wait4Addr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Wait4(SB), R8 + MOVD R8, ret+0(FP) + RET + +TEXT ·get_MountAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Mount(SB), R8 + MOVD R8, ret+0(FP) + RET + +TEXT ·get_UnmountAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Unmount(SB), R8 + MOVD R8, ret+0(FP) + RET + +TEXT ·get_UtimesNanoAtAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·UtimesNanoAt(SB), R8 + MOVD R8, ret+0(FP) + RET + +TEXT ·get_UtimesNanoAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·UtimesNano(SB), R8 + MOVD R8, ret+0(FP) + RET + +TEXT ·get_MkfifoatAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Mkfifoat(SB), R8 + MOVD R8, ret+0(FP) + RET + +TEXT ·get_ChtagAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Chtag(SB), R8 + MOVD R8, ret+0(FP) + RET + +TEXT ·get_ReadlinkatAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Readlinkat(SB), R8 + MOVD R8, ret+0(FP) + RET + diff --git a/vendor/golang.org/x/sys/unix/syscall_aix.go b/vendor/golang.org/x/sys/unix/syscall_aix.go index 67ce6cef2..6f15ba1ea 100644 --- a/vendor/golang.org/x/sys/unix/syscall_aix.go +++ b/vendor/golang.org/x/sys/unix/syscall_aix.go @@ -360,7 +360,7 @@ func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, var status _C_int var r Pid_t err = ERESTART - // AIX wait4 may return with ERESTART errno, while the processus is still + // AIX wait4 may return with ERESTART errno, while the process is still // active. for err == ERESTART { r, err = wait4(Pid_t(pid), &status, options, rusage) diff --git a/vendor/golang.org/x/sys/unix/syscall_darwin.go b/vendor/golang.org/x/sys/unix/syscall_darwin.go index 59542a897..099867dee 100644 --- a/vendor/golang.org/x/sys/unix/syscall_darwin.go +++ b/vendor/golang.org/x/sys/unix/syscall_darwin.go @@ -402,6 +402,18 @@ func IoctlSetIfreqMTU(fd int, ifreq *IfreqMTU) error { return ioctlPtr(fd, SIOCSIFMTU, unsafe.Pointer(ifreq)) } +//sys renamexNp(from string, to string, flag uint32) (err error) + +func RenamexNp(from string, to string, flag uint32) (err error) { + return renamexNp(from, to, flag) +} + +//sys renameatxNp(fromfd int, from string, tofd int, to string, flag uint32) (err error) + +func RenameatxNp(fromfd int, from string, tofd int, to string, flag uint32) (err error) { + return renameatxNp(fromfd, from, tofd, to, flag) +} + //sys sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) = SYS_SYSCTL func Uname(uname *Utsname) error { @@ -542,6 +554,55 @@ func SysctlKinfoProcSlice(name string, args ...int) ([]KinfoProc, error) { } } +//sys pthread_chdir_np(path string) (err error) + +func PthreadChdir(path string) (err error) { + return pthread_chdir_np(path) +} + +//sys pthread_fchdir_np(fd int) (err error) + +func PthreadFchdir(fd int) (err error) { + return pthread_fchdir_np(fd) +} + +// Connectx calls connectx(2) to initiate a connection on a socket. +// +// srcIf, srcAddr, and dstAddr are filled into a [SaEndpoints] struct and passed as the endpoints argument. +// +// - srcIf is the optional source interface index. 0 means unspecified. +// - srcAddr is the optional source address. nil means unspecified. +// - dstAddr is the destination address. +// +// On success, Connectx returns the number of bytes enqueued for transmission. +func Connectx(fd int, srcIf uint32, srcAddr, dstAddr Sockaddr, associd SaeAssocID, flags uint32, iov []Iovec, connid *SaeConnID) (n uintptr, err error) { + endpoints := SaEndpoints{ + Srcif: srcIf, + } + + if srcAddr != nil { + addrp, addrlen, err := srcAddr.sockaddr() + if err != nil { + return 0, err + } + endpoints.Srcaddr = (*RawSockaddr)(addrp) + endpoints.Srcaddrlen = uint32(addrlen) + } + + if dstAddr != nil { + addrp, addrlen, err := dstAddr.sockaddr() + if err != nil { + return 0, err + } + endpoints.Dstaddr = (*RawSockaddr)(addrp) + endpoints.Dstaddrlen = uint32(addrlen) + } + + err = connectx(fd, &endpoints, associd, flags, iov, &n, connid) + return +} + +//sys connectx(fd int, endpoints *SaEndpoints, associd SaeAssocID, flags uint32, iov []Iovec, n *uintptr, connid *SaeConnID) (err error) //sys sendfile(infd int, outfd int, offset int64, len *int64, hdtr unsafe.Pointer, flags int) (err error) //sys shmat(id int, addr uintptr, flag int) (ret uintptr, err error) diff --git a/vendor/golang.org/x/sys/unix/syscall_hurd.go b/vendor/golang.org/x/sys/unix/syscall_hurd.go index ba46651f8..a6a2d2fc2 100644 --- a/vendor/golang.org/x/sys/unix/syscall_hurd.go +++ b/vendor/golang.org/x/sys/unix/syscall_hurd.go @@ -11,6 +11,7 @@ package unix int ioctl(int, unsigned long int, uintptr_t); */ import "C" +import "unsafe" func ioctl(fd int, req uint, arg uintptr) (err error) { r0, er := C.ioctl(C.int(fd), C.ulong(req), C.uintptr_t(arg)) diff --git a/vendor/golang.org/x/sys/unix/syscall_linux.go b/vendor/golang.org/x/sys/unix/syscall_linux.go index 5682e2628..230a94549 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux.go @@ -1295,6 +1295,48 @@ func GetsockoptTCPInfo(fd, level, opt int) (*TCPInfo, error) { return &value, err } +// GetsockoptTCPCCVegasInfo returns algorithm specific congestion control information for a socket using the "vegas" +// algorithm. +// +// The socket's congestion control algorighm can be retrieved via [GetsockoptString] with the [TCP_CONGESTION] option: +// +// algo, err := unix.GetsockoptString(fd, unix.IPPROTO_TCP, unix.TCP_CONGESTION) +func GetsockoptTCPCCVegasInfo(fd, level, opt int) (*TCPVegasInfo, error) { + var value [SizeofTCPCCInfo / 4]uint32 // ensure proper alignment + vallen := _Socklen(SizeofTCPCCInfo) + err := getsockopt(fd, level, opt, unsafe.Pointer(&value[0]), &vallen) + out := (*TCPVegasInfo)(unsafe.Pointer(&value[0])) + return out, err +} + +// GetsockoptTCPCCDCTCPInfo returns algorithm specific congestion control information for a socket using the "dctp" +// algorithm. +// +// The socket's congestion control algorighm can be retrieved via [GetsockoptString] with the [TCP_CONGESTION] option: +// +// algo, err := unix.GetsockoptString(fd, unix.IPPROTO_TCP, unix.TCP_CONGESTION) +func GetsockoptTCPCCDCTCPInfo(fd, level, opt int) (*TCPDCTCPInfo, error) { + var value [SizeofTCPCCInfo / 4]uint32 // ensure proper alignment + vallen := _Socklen(SizeofTCPCCInfo) + err := getsockopt(fd, level, opt, unsafe.Pointer(&value[0]), &vallen) + out := (*TCPDCTCPInfo)(unsafe.Pointer(&value[0])) + return out, err +} + +// GetsockoptTCPCCBBRInfo returns algorithm specific congestion control information for a socket using the "bbr" +// algorithm. +// +// The socket's congestion control algorighm can be retrieved via [GetsockoptString] with the [TCP_CONGESTION] option: +// +// algo, err := unix.GetsockoptString(fd, unix.IPPROTO_TCP, unix.TCP_CONGESTION) +func GetsockoptTCPCCBBRInfo(fd, level, opt int) (*TCPBBRInfo, error) { + var value [SizeofTCPCCInfo / 4]uint32 // ensure proper alignment + vallen := _Socklen(SizeofTCPCCInfo) + err := getsockopt(fd, level, opt, unsafe.Pointer(&value[0]), &vallen) + out := (*TCPBBRInfo)(unsafe.Pointer(&value[0])) + return out, err +} + // GetsockoptString returns the string value of the socket option opt for the // socket associated with fd at the given socket level. func GetsockoptString(fd, level, opt int) (string, error) { @@ -1818,6 +1860,7 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e //sys ClockAdjtime(clockid int32, buf *Timex) (state int, err error) //sys ClockGetres(clockid int32, res *Timespec) (err error) //sys ClockGettime(clockid int32, time *Timespec) (err error) +//sys ClockSettime(clockid int32, time *Timespec) (err error) //sys ClockNanosleep(clockid int32, flags int, request *Timespec, remain *Timespec) (err error) //sys Close(fd int) (err error) //sys CloseRange(first uint, last uint, flags uint) (err error) @@ -1959,7 +2002,26 @@ func Getpgrp() (pid int) { //sysnb Getpid() (pid int) //sysnb Getppid() (ppid int) //sys Getpriority(which int, who int) (prio int, err error) -//sys Getrandom(buf []byte, flags int) (n int, err error) + +func Getrandom(buf []byte, flags int) (n int, err error) { + vdsoRet, supported := vgetrandom(buf, uint32(flags)) + if supported { + if vdsoRet < 0 { + return 0, errnoErr(syscall.Errno(-vdsoRet)) + } + return vdsoRet, nil + } + var p *byte + if len(buf) > 0 { + p = &buf[0] + } + r, _, e := Syscall(SYS_GETRANDOM, uintptr(unsafe.Pointer(p)), uintptr(len(buf)), uintptr(flags)) + if e != 0 { + return 0, errnoErr(e) + } + return int(r), nil +} + //sysnb Getrusage(who int, rusage *Rusage) (err error) //sysnb Getsid(pid int) (sid int, err error) //sysnb Gettid() (tid int) @@ -2592,3 +2654,4 @@ func SchedGetAttr(pid int, flags uint) (*SchedAttr, error) { } //sys Cachestat(fd uint, crange *CachestatRange, cstat *Cachestat_t, flags uint) (err error) +//sys Mseal(b []byte, flags uint) (err error) diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_arm64.go b/vendor/golang.org/x/sys/unix/syscall_linux_arm64.go index cf2ee6c75..745e5c7e6 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_arm64.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_arm64.go @@ -182,3 +182,5 @@ func KexecFileLoad(kernelFd int, initrdFd int, cmdline string, flags int) error } return kexecFileLoad(kernelFd, initrdFd, cmdlineLen, cmdline, flags) } + +const SYS_FSTATAT = SYS_NEWFSTATAT diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_loong64.go b/vendor/golang.org/x/sys/unix/syscall_linux_loong64.go index 3d0e98451..dd2262a40 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_loong64.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_loong64.go @@ -214,3 +214,5 @@ func KexecFileLoad(kernelFd int, initrdFd int, cmdline string, flags int) error } return kexecFileLoad(kernelFd, initrdFd, cmdlineLen, cmdline, flags) } + +const SYS_FSTATAT = SYS_NEWFSTATAT diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_riscv64.go b/vendor/golang.org/x/sys/unix/syscall_linux_riscv64.go index 6f5a28894..8cf3670bd 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_riscv64.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_riscv64.go @@ -187,3 +187,5 @@ func RISCVHWProbe(pairs []RISCVHWProbePairs, set *CPUSet, flags uint) (err error } return riscvHWProbe(pairs, setSize, set, flags) } + +const SYS_FSTATAT = SYS_NEWFSTATAT diff --git a/vendor/golang.org/x/sys/unix/syscall_openbsd.go b/vendor/golang.org/x/sys/unix/syscall_openbsd.go index b25343c71..b86ded549 100644 --- a/vendor/golang.org/x/sys/unix/syscall_openbsd.go +++ b/vendor/golang.org/x/sys/unix/syscall_openbsd.go @@ -293,6 +293,7 @@ func Uname(uname *Utsname) error { //sys Mkfifoat(dirfd int, path string, mode uint32) (err error) //sys Mknod(path string, mode uint32, dev int) (err error) //sys Mknodat(dirfd int, path string, mode uint32, dev int) (err error) +//sys Mount(fsType string, dir string, flags int, data unsafe.Pointer) (err error) //sys Nanosleep(time *Timespec, leftover *Timespec) (err error) //sys Open(path string, mode int, perm uint32) (fd int, err error) //sys Openat(dirfd int, path string, mode int, perm uint32) (fd int, err error) diff --git a/vendor/golang.org/x/sys/unix/syscall_unix.go b/vendor/golang.org/x/sys/unix/syscall_unix.go index 77081de8c..4e92e5aa4 100644 --- a/vendor/golang.org/x/sys/unix/syscall_unix.go +++ b/vendor/golang.org/x/sys/unix/syscall_unix.go @@ -154,6 +154,15 @@ func Munmap(b []byte) (err error) { return mapper.Munmap(b) } +func MmapPtr(fd int, offset int64, addr unsafe.Pointer, length uintptr, prot int, flags int) (ret unsafe.Pointer, err error) { + xaddr, err := mapper.mmap(uintptr(addr), length, prot, flags, fd, offset) + return unsafe.Pointer(xaddr), err +} + +func MunmapPtr(addr unsafe.Pointer, length uintptr) (err error) { + return mapper.munmap(uintptr(addr), length) +} + func Read(fd int, p []byte) (n int, err error) { n, err = read(fd, p) if raceenabled { diff --git a/vendor/golang.org/x/sys/unix/syscall_zos_s390x.go b/vendor/golang.org/x/sys/unix/syscall_zos_s390x.go index 27c41b6f0..7bf5c04bb 100644 --- a/vendor/golang.org/x/sys/unix/syscall_zos_s390x.go +++ b/vendor/golang.org/x/sys/unix/syscall_zos_s390x.go @@ -4,11 +4,21 @@ //go:build zos && s390x +// Many of the following syscalls are not available on all versions of z/OS. +// Some missing calls have legacy implementations/simulations but others +// will be missing completely. To achieve consistent failing behaviour on +// legacy systems, we first test the function pointer via a safeloading +// mechanism to see if the function exists on a given system. Then execution +// is branched to either continue the function call, or return an error. + package unix import ( "bytes" "fmt" + "os" + "reflect" + "regexp" "runtime" "sort" "strings" @@ -17,17 +27,205 @@ import ( "unsafe" ) +//go:noescape +func initZosLibVec() + +//go:noescape +func GetZosLibVec() uintptr + +func init() { + initZosLibVec() + r0, _, _ := CallLeFuncWithPtrReturn(GetZosLibVec()+SYS_____GETENV_A<<4, uintptr(unsafe.Pointer(&([]byte("__ZOS_XSYSTRACE\x00"))[0]))) + if r0 != 0 { + n, _, _ := CallLeFuncWithPtrReturn(GetZosLibVec()+SYS___ATOI_A<<4, r0) + ZosTraceLevel = int(n) + r0, _, _ := CallLeFuncWithPtrReturn(GetZosLibVec()+SYS_____GETENV_A<<4, uintptr(unsafe.Pointer(&([]byte("__ZOS_XSYSTRACEFD\x00"))[0]))) + if r0 != 0 { + fd, _, _ := CallLeFuncWithPtrReturn(GetZosLibVec()+SYS___ATOI_A<<4, r0) + f := os.NewFile(fd, "zostracefile") + if f != nil { + ZosTracefile = f + } + } + + } +} + +//go:noescape +func CallLeFuncWithErr(funcdesc uintptr, parms ...uintptr) (ret, errno2 uintptr, err Errno) + +//go:noescape +func CallLeFuncWithPtrReturn(funcdesc uintptr, parms ...uintptr) (ret, errno2 uintptr, err Errno) + +// ------------------------------- +// pointer validity test +// good pointer returns 0 +// bad pointer returns 1 +// +//go:nosplit +func ptrtest(uintptr) uint64 + +// Load memory at ptr location with error handling if the location is invalid +// +//go:noescape +func safeload(ptr uintptr) (value uintptr, error uintptr) + const ( - O_CLOEXEC = 0 // Dummy value (not supported). - AF_LOCAL = AF_UNIX // AF_LOCAL is an alias for AF_UNIX + entrypointLocationOffset = 8 // From function descriptor + + xplinkEyecatcher = 0x00c300c500c500f1 // ".C.E.E.1" + eyecatcherOffset = 16 // From function entrypoint (negative) + ppa1LocationOffset = 8 // From function entrypoint (negative) + + nameLenOffset = 0x14 // From PPA1 start + nameOffset = 0x16 // From PPA1 start ) -func syscall_syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) -func syscall_rawsyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) -func syscall_syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) -func syscall_rawsyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) -func syscall_syscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err Errno) -func syscall_rawsyscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err Errno) +func getPpaOffset(funcptr uintptr) int64 { + entrypoint, err := safeload(funcptr + entrypointLocationOffset) + if err != 0 { + return -1 + } + + // XPLink functions have ".C.E.E.1" as the first 8 bytes (EBCDIC) + val, err := safeload(entrypoint - eyecatcherOffset) + if err != 0 { + return -1 + } + if val != xplinkEyecatcher { + return -1 + } + + ppaoff, err := safeload(entrypoint - ppa1LocationOffset) + if err != 0 { + return -1 + } + + ppaoff >>= 32 + return int64(ppaoff) +} + +//------------------------------- +// function descriptor pointer validity test +// good pointer returns 0 +// bad pointer returns 1 + +// TODO: currently mksyscall_zos_s390x.go generate empty string for funcName +// have correct funcName pass to the funcptrtest function +func funcptrtest(funcptr uintptr, funcName string) uint64 { + entrypoint, err := safeload(funcptr + entrypointLocationOffset) + if err != 0 { + return 1 + } + + ppaoff := getPpaOffset(funcptr) + if ppaoff == -1 { + return 1 + } + + // PPA1 offset value is from the start of the entire function block, not the entrypoint + ppa1 := (entrypoint - eyecatcherOffset) + uintptr(ppaoff) + + nameLen, err := safeload(ppa1 + nameLenOffset) + if err != 0 { + return 1 + } + + nameLen >>= 48 + if nameLen > 128 { + return 1 + } + + // no function name input to argument end here + if funcName == "" { + return 0 + } + + var funcname [128]byte + for i := 0; i < int(nameLen); i += 8 { + v, err := safeload(ppa1 + nameOffset + uintptr(i)) + if err != 0 { + return 1 + } + funcname[i] = byte(v >> 56) + funcname[i+1] = byte(v >> 48) + funcname[i+2] = byte(v >> 40) + funcname[i+3] = byte(v >> 32) + funcname[i+4] = byte(v >> 24) + funcname[i+5] = byte(v >> 16) + funcname[i+6] = byte(v >> 8) + funcname[i+7] = byte(v) + } + + runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___E2A_L<<4, // __e2a_l + []uintptr{uintptr(unsafe.Pointer(&funcname[0])), nameLen}) + + name := string(funcname[:nameLen]) + if name != funcName { + return 1 + } + + return 0 +} + +// For detection of capabilities on a system. +// Is function descriptor f a valid function? +func isValidLeFunc(f uintptr) error { + ret := funcptrtest(f, "") + if ret != 0 { + return fmt.Errorf("Bad pointer, not an LE function ") + } + return nil +} + +// Retrieve function name from descriptor +func getLeFuncName(f uintptr) (string, error) { + // assume it has been checked, only check ppa1 validity here + entry := ((*[2]uintptr)(unsafe.Pointer(f)))[1] + preamp := ((*[4]uint32)(unsafe.Pointer(entry - eyecatcherOffset))) + + offsetPpa1 := preamp[2] + if offsetPpa1 > 0x0ffff { + return "", fmt.Errorf("PPA1 offset seems too big 0x%x\n", offsetPpa1) + } + + ppa1 := uintptr(unsafe.Pointer(preamp)) + uintptr(offsetPpa1) + res := ptrtest(ppa1) + if res != 0 { + return "", fmt.Errorf("PPA1 address not valid") + } + + size := *(*uint16)(unsafe.Pointer(ppa1 + nameLenOffset)) + if size > 128 { + return "", fmt.Errorf("Function name seems too long, length=%d\n", size) + } + + var name [128]byte + funcname := (*[128]byte)(unsafe.Pointer(ppa1 + nameOffset)) + copy(name[0:size], funcname[0:size]) + + runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___E2A_L<<4, // __e2a_l + []uintptr{uintptr(unsafe.Pointer(&name[0])), uintptr(size)}) + + return string(name[:size]), nil +} + +// Check z/OS version +func zosLeVersion() (version, release uint32) { + p1 := (*(*uintptr)(unsafe.Pointer(uintptr(1208)))) >> 32 + p1 = *(*uintptr)(unsafe.Pointer(uintptr(p1 + 88))) + p1 = *(*uintptr)(unsafe.Pointer(uintptr(p1 + 8))) + p1 = *(*uintptr)(unsafe.Pointer(uintptr(p1 + 984))) + vrm := *(*uint32)(unsafe.Pointer(p1 + 80)) + version = (vrm & 0x00ff0000) >> 16 + release = (vrm & 0x0000ff00) >> 8 + return +} + +// returns a zos C FILE * for stdio fd 0, 1, 2 +func ZosStdioFilep(fd int32) uintptr { + return uintptr(*(*uint64)(unsafe.Pointer(uintptr(*(*uint64)(unsafe.Pointer(uintptr(*(*uint64)(unsafe.Pointer(uintptr(uint64(*(*uint32)(unsafe.Pointer(uintptr(1208)))) + 80))) + uint64((fd+2)<<3)))))))) +} func copyStat(stat *Stat_t, statLE *Stat_LE_t) { stat.Dev = uint64(statLE.Dev) @@ -65,6 +263,21 @@ func (d *Dirent) NameString() string { } } +func DecodeData(dest []byte, sz int, val uint64) { + for i := 0; i < sz; i++ { + dest[sz-1-i] = byte((val >> (uint64(i * 8))) & 0xff) + } +} + +func EncodeData(data []byte) uint64 { + var value uint64 + sz := len(data) + for i := 0; i < sz; i++ { + value |= uint64(data[i]) << uint64(((sz - i - 1) * 8)) + } + return value +} + func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) { if sa.Port < 0 || sa.Port > 0xFFFF { return nil, 0, EINVAL @@ -74,7 +287,9 @@ func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) { p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)) p[0] = byte(sa.Port >> 8) p[1] = byte(sa.Port) - sa.raw.Addr = sa.Addr + for i := 0; i < len(sa.Addr); i++ { + sa.raw.Addr[i] = sa.Addr[i] + } return unsafe.Pointer(&sa.raw), _Socklen(sa.raw.Len), nil } @@ -88,7 +303,9 @@ func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, _Socklen, error) { p[0] = byte(sa.Port >> 8) p[1] = byte(sa.Port) sa.raw.Scope_id = sa.ZoneId - sa.raw.Addr = sa.Addr + for i := 0; i < len(sa.Addr); i++ { + sa.raw.Addr[i] = sa.Addr[i] + } return unsafe.Pointer(&sa.raw), _Socklen(sa.raw.Len), nil } @@ -146,7 +363,9 @@ func anyToSockaddr(_ int, rsa *RawSockaddrAny) (Sockaddr, error) { sa := new(SockaddrInet4) p := (*[2]byte)(unsafe.Pointer(&pp.Port)) sa.Port = int(p[0])<<8 + int(p[1]) - sa.Addr = pp.Addr + for i := 0; i < len(sa.Addr); i++ { + sa.Addr[i] = pp.Addr[i] + } return sa, nil case AF_INET6: @@ -155,7 +374,9 @@ func anyToSockaddr(_ int, rsa *RawSockaddrAny) (Sockaddr, error) { p := (*[2]byte)(unsafe.Pointer(&pp.Port)) sa.Port = int(p[0])<<8 + int(p[1]) sa.ZoneId = pp.Scope_id - sa.Addr = pp.Addr + for i := 0; i < len(sa.Addr); i++ { + sa.Addr[i] = pp.Addr[i] + } return sa, nil } return nil, EAFNOSUPPORT @@ -177,6 +398,43 @@ func Accept(fd int) (nfd int, sa Sockaddr, err error) { return } +func Accept4(fd int, flags int) (nfd int, sa Sockaddr, err error) { + var rsa RawSockaddrAny + var len _Socklen = SizeofSockaddrAny + nfd, err = accept4(fd, &rsa, &len, flags) + if err != nil { + return + } + if len > SizeofSockaddrAny { + panic("RawSockaddrAny too small") + } + // TODO(neeilan): Remove 0 in call + sa, err = anyToSockaddr(0, &rsa) + if err != nil { + Close(nfd) + nfd = 0 + } + return +} + +func Ctermid() (tty string, err error) { + var termdev [1025]byte + runtime.EnterSyscall() + r0, err2, err1 := CallLeFuncWithPtrReturn(GetZosLibVec()+SYS___CTERMID_A<<4, uintptr(unsafe.Pointer(&termdev[0]))) + runtime.ExitSyscall() + if r0 == 0 { + return "", fmt.Errorf("%s (errno2=0x%x)\n", err1.Error(), err2) + } + s := string(termdev[:]) + idx := strings.Index(s, string(rune(0))) + if idx == -1 { + tty = s + } else { + tty = s[:idx] + } + return +} + func (iov *Iovec) SetLen(length int) { iov.Len = uint64(length) } @@ -190,10 +448,16 @@ func (cmsg *Cmsghdr) SetLen(length int) { } //sys fcntl(fd int, cmd int, arg int) (val int, err error) +//sys Flistxattr(fd int, dest []byte) (sz int, err error) = SYS___FLISTXATTR_A +//sys Fremovexattr(fd int, attr string) (err error) = SYS___FREMOVEXATTR_A //sys read(fd int, p []byte) (n int, err error) //sys write(fd int, p []byte) (n int, err error) +//sys Fgetxattr(fd int, attr string, dest []byte) (sz int, err error) = SYS___FGETXATTR_A +//sys Fsetxattr(fd int, attr string, data []byte, flag int) (err error) = SYS___FSETXATTR_A + //sys accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) = SYS___ACCEPT_A +//sys accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) = SYS___ACCEPT4_A //sys bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) = SYS___BIND_A //sys connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) = SYS___CONNECT_A //sysnb getgroups(n int, list *_Gid_t) (nn int, err error) @@ -204,6 +468,7 @@ func (cmsg *Cmsghdr) SetLen(length int) { //sysnb socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) //sysnb getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) = SYS___GETPEERNAME_A //sysnb getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) = SYS___GETSOCKNAME_A +//sys Removexattr(path string, attr string) (err error) = SYS___REMOVEXATTR_A //sys recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) = SYS___RECVFROM_A //sys sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error) = SYS___SENDTO_A //sys recvmsg(s int, msg *Msghdr, flags int) (n int, err error) = SYS___RECVMSG_A @@ -212,6 +477,10 @@ func (cmsg *Cmsghdr) SetLen(length int) { //sys munmap(addr uintptr, length uintptr) (err error) = SYS_MUNMAP //sys ioctl(fd int, req int, arg uintptr) (err error) = SYS_IOCTL //sys ioctlPtr(fd int, req int, arg unsafe.Pointer) (err error) = SYS_IOCTL +//sys shmat(id int, addr uintptr, flag int) (ret uintptr, err error) = SYS_SHMAT +//sys shmctl(id int, cmd int, buf *SysvShmDesc) (result int, err error) = SYS_SHMCTL64 +//sys shmdt(addr uintptr) (err error) = SYS_SHMDT +//sys shmget(key int, size int, flag int) (id int, err error) = SYS_SHMGET //sys Access(path string, mode uint32) (err error) = SYS___ACCESS_A //sys Chdir(path string) (err error) = SYS___CHDIR_A @@ -220,14 +489,31 @@ func (cmsg *Cmsghdr) SetLen(length int) { //sys Creat(path string, mode uint32) (fd int, err error) = SYS___CREAT_A //sys Dup(oldfd int) (fd int, err error) //sys Dup2(oldfd int, newfd int) (err error) +//sys Dup3(oldfd int, newfd int, flags int) (err error) = SYS_DUP3 +//sys Dirfd(dirp uintptr) (fd int, err error) = SYS_DIRFD +//sys EpollCreate(size int) (fd int, err error) = SYS_EPOLL_CREATE +//sys EpollCreate1(flags int) (fd int, err error) = SYS_EPOLL_CREATE1 +//sys EpollCtl(epfd int, op int, fd int, event *EpollEvent) (err error) = SYS_EPOLL_CTL +//sys EpollPwait(epfd int, events []EpollEvent, msec int, sigmask *int) (n int, err error) = SYS_EPOLL_PWAIT +//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) = SYS_EPOLL_WAIT //sys Errno2() (er2 int) = SYS___ERRNO2 -//sys Err2ad() (eadd *int) = SYS___ERR2AD +//sys Eventfd(initval uint, flags int) (fd int, err error) = SYS_EVENTFD //sys Exit(code int) +//sys Faccessat(dirfd int, path string, mode uint32, flags int) (err error) = SYS___FACCESSAT_A + +func Faccessat2(dirfd int, path string, mode uint32, flags int) (err error) { + return Faccessat(dirfd, path, mode, flags) +} + //sys Fchdir(fd int) (err error) //sys Fchmod(fd int, mode uint32) (err error) +//sys Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) = SYS___FCHMODAT_A //sys Fchown(fd int, uid int, gid int) (err error) +//sys Fchownat(fd int, path string, uid int, gid int, flags int) (err error) = SYS___FCHOWNAT_A //sys FcntlInt(fd uintptr, cmd int, arg int) (retval int, err error) = SYS_FCNTL +//sys Fdatasync(fd int) (err error) = SYS_FDATASYNC //sys fstat(fd int, stat *Stat_LE_t) (err error) +//sys fstatat(dirfd int, path string, stat *Stat_LE_t, flags int) (err error) = SYS___FSTATAT_A func Fstat(fd int, stat *Stat_t) (err error) { var statLE Stat_LE_t @@ -236,28 +522,208 @@ func Fstat(fd int, stat *Stat_t) (err error) { return } +func Fstatat(dirfd int, path string, stat *Stat_t, flags int) (err error) { + var statLE Stat_LE_t + err = fstatat(dirfd, path, &statLE, flags) + copyStat(stat, &statLE) + return +} + +func impl_Getxattr(path string, attr string, dest []byte) (sz int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(attr) + if err != nil { + return + } + var _p2 unsafe.Pointer + if len(dest) > 0 { + _p2 = unsafe.Pointer(&dest[0]) + } else { + _p2 = unsafe.Pointer(&_zero) + } + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___GETXATTR_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(dest))) + sz = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_GetxattrAddr() *(func(path string, attr string, dest []byte) (sz int, err error)) + +var Getxattr = enter_Getxattr + +func enter_Getxattr(path string, attr string, dest []byte) (sz int, err error) { + funcref := get_GetxattrAddr() + if validGetxattr() { + *funcref = impl_Getxattr + } else { + *funcref = error_Getxattr + } + return (*funcref)(path, attr, dest) +} + +func error_Getxattr(path string, attr string, dest []byte) (sz int, err error) { + return -1, ENOSYS +} + +func validGetxattr() bool { + if funcptrtest(GetZosLibVec()+SYS___GETXATTR_A<<4, "") == 0 { + if name, err := getLeFuncName(GetZosLibVec() + SYS___GETXATTR_A<<4); err == nil { + return name == "__getxattr_a" + } + } + return false +} + +//sys Lgetxattr(link string, attr string, dest []byte) (sz int, err error) = SYS___LGETXATTR_A +//sys Lsetxattr(path string, attr string, data []byte, flags int) (err error) = SYS___LSETXATTR_A + +func impl_Setxattr(path string, attr string, data []byte, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(attr) + if err != nil { + return + } + var _p2 unsafe.Pointer + if len(data) > 0 { + _p2 = unsafe.Pointer(&data[0]) + } else { + _p2 = unsafe.Pointer(&_zero) + } + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___SETXATTR_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(data)), uintptr(flags)) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_SetxattrAddr() *(func(path string, attr string, data []byte, flags int) (err error)) + +var Setxattr = enter_Setxattr + +func enter_Setxattr(path string, attr string, data []byte, flags int) (err error) { + funcref := get_SetxattrAddr() + if validSetxattr() { + *funcref = impl_Setxattr + } else { + *funcref = error_Setxattr + } + return (*funcref)(path, attr, data, flags) +} + +func error_Setxattr(path string, attr string, data []byte, flags int) (err error) { + return ENOSYS +} + +func validSetxattr() bool { + if funcptrtest(GetZosLibVec()+SYS___SETXATTR_A<<4, "") == 0 { + if name, err := getLeFuncName(GetZosLibVec() + SYS___SETXATTR_A<<4); err == nil { + return name == "__setxattr_a" + } + } + return false +} + +//sys Fstatfs(fd int, buf *Statfs_t) (err error) = SYS_FSTATFS //sys Fstatvfs(fd int, stat *Statvfs_t) (err error) = SYS_FSTATVFS //sys Fsync(fd int) (err error) +//sys Futimes(fd int, tv []Timeval) (err error) = SYS_FUTIMES +//sys Futimesat(dirfd int, path string, tv []Timeval) (err error) = SYS___FUTIMESAT_A //sys Ftruncate(fd int, length int64) (err error) -//sys Getpagesize() (pgsize int) = SYS_GETPAGESIZE +//sys Getrandom(buf []byte, flags int) (n int, err error) = SYS_GETRANDOM +//sys InotifyInit() (fd int, err error) = SYS_INOTIFY_INIT +//sys InotifyInit1(flags int) (fd int, err error) = SYS_INOTIFY_INIT1 +//sys InotifyAddWatch(fd int, pathname string, mask uint32) (watchdesc int, err error) = SYS___INOTIFY_ADD_WATCH_A +//sys InotifyRmWatch(fd int, watchdesc uint32) (success int, err error) = SYS_INOTIFY_RM_WATCH +//sys Listxattr(path string, dest []byte) (sz int, err error) = SYS___LISTXATTR_A +//sys Llistxattr(path string, dest []byte) (sz int, err error) = SYS___LLISTXATTR_A +//sys Lremovexattr(path string, attr string) (err error) = SYS___LREMOVEXATTR_A +//sys Lutimes(path string, tv []Timeval) (err error) = SYS___LUTIMES_A //sys Mprotect(b []byte, prot int) (err error) = SYS_MPROTECT //sys Msync(b []byte, flags int) (err error) = SYS_MSYNC +//sys Console2(cmsg *ConsMsg2, modstr *byte, concmd *uint32) (err error) = SYS___CONSOLE2 + +// Pipe2 begin + +//go:nosplit +func getPipe2Addr() *(func([]int, int) error) + +var Pipe2 = pipe2Enter + +func pipe2Enter(p []int, flags int) (err error) { + if funcptrtest(GetZosLibVec()+SYS_PIPE2<<4, "") == 0 { + *getPipe2Addr() = pipe2Impl + } else { + *getPipe2Addr() = pipe2Error + } + return (*getPipe2Addr())(p, flags) +} + +func pipe2Impl(p []int, flags int) (err error) { + var pp [2]_C_int + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_PIPE2<<4, uintptr(unsafe.Pointer(&pp[0])), uintptr(flags)) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } else { + p[0] = int(pp[0]) + p[1] = int(pp[1]) + } + return +} +func pipe2Error(p []int, flags int) (err error) { + return fmt.Errorf("Pipe2 is not available on this system") +} + +// Pipe2 end + //sys Poll(fds []PollFd, timeout int) (n int, err error) = SYS_POLL + +func Readdir(dir uintptr) (dirent *Dirent, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___READDIR_A<<4, uintptr(dir)) + runtime.ExitSyscall() + dirent = (*Dirent)(unsafe.Pointer(r0)) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//sys Readdir_r(dirp uintptr, entry *direntLE, result **direntLE) (err error) = SYS___READDIR_R_A +//sys Statfs(path string, buf *Statfs_t) (err error) = SYS___STATFS_A +//sys Syncfs(fd int) (err error) = SYS_SYNCFS //sys Times(tms *Tms) (ticks uintptr, err error) = SYS_TIMES //sys W_Getmntent(buff *byte, size int) (lastsys int, err error) = SYS_W_GETMNTENT //sys W_Getmntent_A(buff *byte, size int) (lastsys int, err error) = SYS___W_GETMNTENT_A //sys mount_LE(path string, filesystem string, fstype string, mtm uint32, parmlen int32, parm string) (err error) = SYS___MOUNT_A -//sys unmount(filesystem string, mtm int) (err error) = SYS___UMOUNT_A +//sys unmount_LE(filesystem string, mtm int) (err error) = SYS___UMOUNT_A //sys Chroot(path string) (err error) = SYS___CHROOT_A //sys Select(nmsgsfds int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (ret int, err error) = SYS_SELECT -//sysnb Uname(buf *Utsname) (err error) = SYS___UNAME_A +//sysnb Uname(buf *Utsname) (err error) = SYS_____OSNAME_A +//sys Unshare(flags int) (err error) = SYS_UNSHARE func Ptsname(fd int) (name string, err error) { - r0, _, e1 := syscall_syscall(SYS___PTSNAME_A, uintptr(fd), 0, 0) - name = u2s(unsafe.Pointer(r0)) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithPtrReturn(GetZosLibVec()+SYS___PTSNAME_A<<4, uintptr(fd)) + runtime.ExitSyscall() + if r0 == 0 { + err = errnoErr2(e1, e2) + } else { + name = u2s(unsafe.Pointer(r0)) } return } @@ -272,13 +738,19 @@ func u2s(cstr unsafe.Pointer) string { } func Close(fd int) (err error) { - _, _, e1 := syscall_syscall(SYS_CLOSE, uintptr(fd), 0, 0) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_CLOSE<<4, uintptr(fd)) + runtime.ExitSyscall() for i := 0; e1 == EAGAIN && i < 10; i++ { - _, _, _ = syscall_syscall(SYS_USLEEP, uintptr(10), 0, 0) - _, _, e1 = syscall_syscall(SYS_CLOSE, uintptr(fd), 0, 0) + runtime.EnterSyscall() + CallLeFuncWithErr(GetZosLibVec()+SYS_USLEEP<<4, uintptr(10)) + runtime.ExitSyscall() + runtime.EnterSyscall() + r0, e2, e1 = CallLeFuncWithErr(GetZosLibVec()+SYS_CLOSE<<4, uintptr(fd)) + runtime.ExitSyscall() } - if e1 != 0 { - err = errnoErr(e1) + if r0 != 0 { + err = errnoErr2(e1, e2) } return } @@ -288,9 +760,24 @@ func Madvise(b []byte, advice int) (err error) { return } +func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) { + return mapper.Mmap(fd, offset, length, prot, flags) +} + +func Munmap(b []byte) (err error) { + return mapper.Munmap(b) +} + +func MmapPtr(fd int, offset int64, addr unsafe.Pointer, length uintptr, prot int, flags int) (ret unsafe.Pointer, err error) { + xaddr, err := mapper.mmap(uintptr(addr), length, prot, flags, fd, offset) + return unsafe.Pointer(xaddr), err +} + +func MunmapPtr(addr unsafe.Pointer, length uintptr) (err error) { + return mapper.munmap(uintptr(addr), length) +} + //sys Gethostname(buf []byte) (err error) = SYS___GETHOSTNAME_A -//sysnb Getegid() (egid int) -//sysnb Geteuid() (uid int) //sysnb Getgid() (gid int) //sysnb Getpid() (pid int) //sysnb Getpgid(pid int) (pgid int, err error) = SYS_GETPGID @@ -317,11 +804,14 @@ func Getrusage(who int, rusage *Rusage) (err error) { return } +//sys Getegid() (egid int) = SYS_GETEGID +//sys Geteuid() (euid int) = SYS_GETEUID //sysnb Getsid(pid int) (sid int, err error) = SYS_GETSID //sysnb Getuid() (uid int) //sysnb Kill(pid int, sig Signal) (err error) //sys Lchown(path string, uid int, gid int) (err error) = SYS___LCHOWN_A //sys Link(path string, link string) (err error) = SYS___LINK_A +//sys Linkat(oldDirFd int, oldPath string, newDirFd int, newPath string, flags int) (err error) = SYS___LINKAT_A //sys Listen(s int, n int) (err error) //sys lstat(path string, stat *Stat_LE_t) (err error) = SYS___LSTAT_A @@ -332,15 +822,150 @@ func Lstat(path string, stat *Stat_t) (err error) { return } +// for checking symlinks begins with $VERSION/ $SYSNAME/ $SYSSYMR/ $SYSSYMA/ +func isSpecialPath(path []byte) (v bool) { + var special = [4][8]byte{ + {'V', 'E', 'R', 'S', 'I', 'O', 'N', '/'}, + {'S', 'Y', 'S', 'N', 'A', 'M', 'E', '/'}, + {'S', 'Y', 'S', 'S', 'Y', 'M', 'R', '/'}, + {'S', 'Y', 'S', 'S', 'Y', 'M', 'A', '/'}} + + var i, j int + for i = 0; i < len(special); i++ { + for j = 0; j < len(special[i]); j++ { + if path[j] != special[i][j] { + break + } + } + if j == len(special[i]) { + return true + } + } + return false +} + +func realpath(srcpath string, abspath []byte) (pathlen int, errno int) { + var source [1024]byte + copy(source[:], srcpath) + source[len(srcpath)] = 0 + ret := runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___REALPATH_A<<4, //__realpath_a() + []uintptr{uintptr(unsafe.Pointer(&source[0])), + uintptr(unsafe.Pointer(&abspath[0]))}) + if ret != 0 { + index := bytes.IndexByte(abspath[:], byte(0)) + if index != -1 { + return index, 0 + } + } else { + errptr := (*int)(unsafe.Pointer(runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___ERRNO<<4, []uintptr{}))) //__errno() + return 0, *errptr + } + return 0, 245 // EBADDATA 245 +} + +func Readlink(path string, buf []byte) (n int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(buf) > 0 { + _p1 = unsafe.Pointer(&buf[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + n = int(runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___READLINK_A<<4, + []uintptr{uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf))})) + runtime.KeepAlive(unsafe.Pointer(_p0)) + if n == -1 { + value := *(*int32)(unsafe.Pointer(runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___ERRNO<<4, []uintptr{}))) + err = errnoErr(Errno(value)) + } else { + if buf[0] == '$' { + if isSpecialPath(buf[1:9]) { + cnt, err1 := realpath(path, buf) + if err1 == 0 { + n = cnt + } + } + } + } + return +} + +func impl_Readlinkat(dirfd int, path string, buf []byte) (n int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(buf) > 0 { + _p1 = unsafe.Pointer(&buf[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___READLINKAT_A<<4, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf))) + runtime.ExitSyscall() + n = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + return n, err + } else { + if buf[0] == '$' { + if isSpecialPath(buf[1:9]) { + cnt, err1 := realpath(path, buf) + if err1 == 0 { + n = cnt + } + } + } + } + return +} + +//go:nosplit +func get_ReadlinkatAddr() *(func(dirfd int, path string, buf []byte) (n int, err error)) + +var Readlinkat = enter_Readlinkat + +func enter_Readlinkat(dirfd int, path string, buf []byte) (n int, err error) { + funcref := get_ReadlinkatAddr() + if funcptrtest(GetZosLibVec()+SYS___READLINKAT_A<<4, "") == 0 { + *funcref = impl_Readlinkat + } else { + *funcref = error_Readlinkat + } + return (*funcref)(dirfd, path, buf) +} + +func error_Readlinkat(dirfd int, path string, buf []byte) (n int, err error) { + n = -1 + err = ENOSYS + return +} + //sys Mkdir(path string, mode uint32) (err error) = SYS___MKDIR_A +//sys Mkdirat(dirfd int, path string, mode uint32) (err error) = SYS___MKDIRAT_A //sys Mkfifo(path string, mode uint32) (err error) = SYS___MKFIFO_A //sys Mknod(path string, mode uint32, dev int) (err error) = SYS___MKNOD_A +//sys Mknodat(dirfd int, path string, mode uint32, dev int) (err error) = SYS___MKNODAT_A +//sys PivotRoot(newroot string, oldroot string) (err error) = SYS___PIVOT_ROOT_A //sys Pread(fd int, p []byte, offset int64) (n int, err error) //sys Pwrite(fd int, p []byte, offset int64) (n int, err error) -//sys Readlink(path string, buf []byte) (n int, err error) = SYS___READLINK_A +//sys Prctl(option int, arg2 uintptr, arg3 uintptr, arg4 uintptr, arg5 uintptr) (err error) = SYS___PRCTL_A +//sysnb Prlimit(pid int, resource int, newlimit *Rlimit, old *Rlimit) (err error) = SYS_PRLIMIT //sys Rename(from string, to string) (err error) = SYS___RENAME_A +//sys Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) = SYS___RENAMEAT_A +//sys Renameat2(olddirfd int, oldpath string, newdirfd int, newpath string, flags uint) (err error) = SYS___RENAMEAT2_A //sys Rmdir(path string) (err error) = SYS___RMDIR_A //sys Seek(fd int, offset int64, whence int) (off int64, err error) = SYS_LSEEK +//sys Setegid(egid int) (err error) = SYS_SETEGID +//sys Seteuid(euid int) (err error) = SYS_SETEUID +//sys Sethostname(p []byte) (err error) = SYS___SETHOSTNAME_A +//sys Setns(fd int, nstype int) (err error) = SYS_SETNS //sys Setpriority(which int, who int, prio int) (err error) //sysnb Setpgid(pid int, pgid int) (err error) = SYS_SETPGID //sysnb Setrlimit(resource int, lim *Rlimit) (err error) @@ -360,32 +985,57 @@ func Stat(path string, sta *Stat_t) (err error) { } //sys Symlink(path string, link string) (err error) = SYS___SYMLINK_A +//sys Symlinkat(oldPath string, dirfd int, newPath string) (err error) = SYS___SYMLINKAT_A //sys Sync() = SYS_SYNC //sys Truncate(path string, length int64) (err error) = SYS___TRUNCATE_A //sys Tcgetattr(fildes int, termptr *Termios) (err error) = SYS_TCGETATTR //sys Tcsetattr(fildes int, when int, termptr *Termios) (err error) = SYS_TCSETATTR //sys Umask(mask int) (oldmask int) //sys Unlink(path string) (err error) = SYS___UNLINK_A +//sys Unlinkat(dirfd int, path string, flags int) (err error) = SYS___UNLINKAT_A //sys Utime(path string, utim *Utimbuf) (err error) = SYS___UTIME_A //sys open(path string, mode int, perm uint32) (fd int, err error) = SYS___OPEN_A func Open(path string, mode int, perm uint32) (fd int, err error) { + if mode&O_ACCMODE == 0 { + mode |= O_RDONLY + } return open(path, mode, perm) } -func Mkfifoat(dirfd int, path string, mode uint32) (err error) { - wd, err := Getwd() - if err != nil { - return err +//sys openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) = SYS___OPENAT_A + +func Openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) { + if flags&O_ACCMODE == 0 { + flags |= O_RDONLY } + return openat(dirfd, path, flags, mode) +} - if err := Fchdir(dirfd); err != nil { - return err +//sys openat2(dirfd int, path string, open_how *OpenHow, size int) (fd int, err error) = SYS___OPENAT2_A + +func Openat2(dirfd int, path string, how *OpenHow) (fd int, err error) { + if how.Flags&O_ACCMODE == 0 { + how.Flags |= O_RDONLY } - defer Chdir(wd) + return openat2(dirfd, path, how, SizeofOpenHow) +} - return Mkfifo(path, mode) +func ZosFdToPath(dirfd int) (path string, err error) { + var buffer [1024]byte + runtime.EnterSyscall() + ret, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_W_IOCTL<<4, uintptr(dirfd), 17, 1024, uintptr(unsafe.Pointer(&buffer[0]))) + runtime.ExitSyscall() + if ret == 0 { + zb := bytes.IndexByte(buffer[:], 0) + if zb == -1 { + zb = len(buffer) + } + CallLeFuncWithErr(GetZosLibVec()+SYS___E2A_L<<4, uintptr(unsafe.Pointer(&buffer[0])), uintptr(zb)) + return string(buffer[:zb]), nil + } + return "", errnoErr2(e1, e2) } //sys remove(path string) (err error) @@ -403,10 +1053,12 @@ func Getcwd(buf []byte) (n int, err error) { } else { p = unsafe.Pointer(&_zero) } - _, _, e := syscall_syscall(SYS___GETCWD_A, uintptr(p), uintptr(len(buf)), 0) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithPtrReturn(GetZosLibVec()+SYS___GETCWD_A<<4, uintptr(p), uintptr(len(buf))) + runtime.ExitSyscall() n = clen(buf) + 1 - if e != 0 { - err = errnoErr(e) + if r0 == 0 { + err = errnoErr2(e1, e2) } return } @@ -520,9 +1172,41 @@ func (w WaitStatus) StopSignal() Signal { func (w WaitStatus) TrapCause() int { return -1 } +//sys waitid(idType int, id int, info *Siginfo, options int) (err error) + +func Waitid(idType int, id int, info *Siginfo, options int, rusage *Rusage) (err error) { + return waitid(idType, id, info, options) +} + //sys waitpid(pid int, wstatus *_C_int, options int) (wpid int, err error) -func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error) { +func impl_Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_WAIT4<<4, uintptr(pid), uintptr(unsafe.Pointer(wstatus)), uintptr(options), uintptr(unsafe.Pointer(rusage))) + runtime.ExitSyscall() + wpid = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_Wait4Addr() *(func(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error)) + +var Wait4 = enter_Wait4 + +func enter_Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error) { + funcref := get_Wait4Addr() + if funcptrtest(GetZosLibVec()+SYS_WAIT4<<4, "") == 0 { + *funcref = impl_Wait4 + } else { + *funcref = legacyWait4 + } + return (*funcref)(pid, wstatus, options, rusage) +} + +func legacyWait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error) { // TODO(mundaym): z/OS doesn't have wait4. I don't think getrusage does what we want. // At the moment rusage will not be touched. var status _C_int @@ -571,23 +1255,62 @@ func Pipe(p []int) (err error) { } var pp [2]_C_int err = pipe(&pp) - if err == nil { - p[0] = int(pp[0]) - p[1] = int(pp[1]) - } + p[0] = int(pp[0]) + p[1] = int(pp[1]) return } //sys utimes(path string, timeval *[2]Timeval) (err error) = SYS___UTIMES_A func Utimes(path string, tv []Timeval) (err error) { + if tv == nil { + return utimes(path, nil) + } if len(tv) != 2 { return EINVAL } return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0]))) } -func UtimesNano(path string, ts []Timespec) error { +//sys utimensat(dirfd int, path string, ts *[2]Timespec, flags int) (err error) = SYS___UTIMENSAT_A + +func validUtimensat() bool { + if funcptrtest(GetZosLibVec()+SYS___UTIMENSAT_A<<4, "") == 0 { + if name, err := getLeFuncName(GetZosLibVec() + SYS___UTIMENSAT_A<<4); err == nil { + return name == "__utimensat_a" + } + } + return false +} + +// Begin UtimesNano + +//go:nosplit +func get_UtimesNanoAddr() *(func(path string, ts []Timespec) (err error)) + +var UtimesNano = enter_UtimesNano + +func enter_UtimesNano(path string, ts []Timespec) (err error) { + funcref := get_UtimesNanoAddr() + if validUtimensat() { + *funcref = utimesNanoImpl + } else { + *funcref = legacyUtimesNano + } + return (*funcref)(path, ts) +} + +func utimesNanoImpl(path string, ts []Timespec) (err error) { + if ts == nil { + return utimensat(AT_FDCWD, path, nil, 0) + } + if len(ts) != 2 { + return EINVAL + } + return utimensat(AT_FDCWD, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), 0) +} + +func legacyUtimesNano(path string, ts []Timespec) (err error) { if len(ts) != 2 { return EINVAL } @@ -600,6 +1323,70 @@ func UtimesNano(path string, ts []Timespec) error { return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0]))) } +// End UtimesNano + +// Begin UtimesNanoAt + +//go:nosplit +func get_UtimesNanoAtAddr() *(func(dirfd int, path string, ts []Timespec, flags int) (err error)) + +var UtimesNanoAt = enter_UtimesNanoAt + +func enter_UtimesNanoAt(dirfd int, path string, ts []Timespec, flags int) (err error) { + funcref := get_UtimesNanoAtAddr() + if validUtimensat() { + *funcref = utimesNanoAtImpl + } else { + *funcref = legacyUtimesNanoAt + } + return (*funcref)(dirfd, path, ts, flags) +} + +func utimesNanoAtImpl(dirfd int, path string, ts []Timespec, flags int) (err error) { + if ts == nil { + return utimensat(dirfd, path, nil, flags) + } + if len(ts) != 2 { + return EINVAL + } + return utimensat(dirfd, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), flags) +} + +func legacyUtimesNanoAt(dirfd int, path string, ts []Timespec, flags int) (err error) { + if path[0] != '/' { + dirPath, err := ZosFdToPath(dirfd) + if err != nil { + return err + } + path = dirPath + "/" + path + } + if flags == AT_SYMLINK_NOFOLLOW { + if len(ts) != 2 { + return EINVAL + } + + if ts[0].Nsec >= 5e8 { + ts[0].Sec++ + } + ts[0].Nsec = 0 + if ts[1].Nsec >= 5e8 { + ts[1].Sec++ + } + ts[1].Nsec = 0 + + // Not as efficient as it could be because Timespec and + // Timeval have different types in the different OSes + tv := []Timeval{ + NsecToTimeval(TimespecToNsec(ts[0])), + NsecToTimeval(TimespecToNsec(ts[1])), + } + return Lutimes(path, tv) + } + return UtimesNano(path, ts) +} + +// End UtimesNanoAt + func Getsockname(fd int) (sa Sockaddr, err error) { var rsa RawSockaddrAny var len _Socklen = SizeofSockaddrAny @@ -1191,10 +1978,13 @@ func Opendir(name string) (uintptr, error) { if err != nil { return 0, err } - dir, _, e := syscall_syscall(SYS___OPENDIR_A, uintptr(unsafe.Pointer(p)), 0, 0) + err = nil + runtime.EnterSyscall() + dir, e2, e1 := CallLeFuncWithPtrReturn(GetZosLibVec()+SYS___OPENDIR_A<<4, uintptr(unsafe.Pointer(p))) + runtime.ExitSyscall() runtime.KeepAlive(unsafe.Pointer(p)) - if e != 0 { - err = errnoErr(e) + if dir == 0 { + err = errnoErr2(e1, e2) } return dir, err } @@ -1202,51 +1992,27 @@ func Opendir(name string) (uintptr, error) { // clearsyscall.Errno resets the errno value to 0. func clearErrno() -func Readdir(dir uintptr) (*Dirent, error) { - var ent Dirent - var res uintptr - // __readdir_r_a returns errno at the end of the directory stream, rather than 0. - // Therefore to avoid false positives we clear errno before calling it. - - // TODO(neeilan): Commented this out to get sys/unix compiling on z/OS. Uncomment and fix. Error: "undefined: clearsyscall" - //clearsyscall.Errno() // TODO(mundaym): check pre-emption rules. - - e, _, _ := syscall_syscall(SYS___READDIR_R_A, dir, uintptr(unsafe.Pointer(&ent)), uintptr(unsafe.Pointer(&res))) - var err error - if e != 0 { - err = errnoErr(Errno(e)) - } - if res == 0 { - return nil, err - } - return &ent, err -} - -func readdir_r(dirp uintptr, entry *direntLE, result **direntLE) (err error) { - r0, _, e1 := syscall_syscall(SYS___READDIR_R_A, dirp, uintptr(unsafe.Pointer(entry)), uintptr(unsafe.Pointer(result))) - if int64(r0) == -1 { - err = errnoErr(Errno(e1)) - } - return -} - func Closedir(dir uintptr) error { - _, _, e := syscall_syscall(SYS_CLOSEDIR, dir, 0, 0) - if e != 0 { - return errnoErr(e) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_CLOSEDIR<<4, dir) + runtime.ExitSyscall() + if r0 != 0 { + return errnoErr2(e1, e2) } return nil } func Seekdir(dir uintptr, pos int) { - _, _, _ = syscall_syscall(SYS_SEEKDIR, dir, uintptr(pos), 0) + runtime.EnterSyscall() + CallLeFuncWithErr(GetZosLibVec()+SYS_SEEKDIR<<4, dir, uintptr(pos)) + runtime.ExitSyscall() } func Telldir(dir uintptr) (int, error) { - p, _, e := syscall_syscall(SYS_TELLDIR, dir, 0, 0) + p, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_TELLDIR<<4, dir) pos := int(p) - if pos == -1 { - return pos, errnoErr(e) + if int64(p) == -1 { + return pos, errnoErr2(e1, e2) } return pos, nil } @@ -1261,19 +2027,55 @@ func FcntlFlock(fd uintptr, cmd int, lk *Flock_t) error { *(*int64)(unsafe.Pointer(&flock[4])) = lk.Start *(*int64)(unsafe.Pointer(&flock[12])) = lk.Len *(*int32)(unsafe.Pointer(&flock[20])) = lk.Pid - _, _, errno := syscall_syscall(SYS_FCNTL, fd, uintptr(cmd), uintptr(unsafe.Pointer(&flock))) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_FCNTL<<4, fd, uintptr(cmd), uintptr(unsafe.Pointer(&flock))) + runtime.ExitSyscall() lk.Type = *(*int16)(unsafe.Pointer(&flock[0])) lk.Whence = *(*int16)(unsafe.Pointer(&flock[2])) lk.Start = *(*int64)(unsafe.Pointer(&flock[4])) lk.Len = *(*int64)(unsafe.Pointer(&flock[12])) lk.Pid = *(*int32)(unsafe.Pointer(&flock[20])) - if errno == 0 { + if r0 == 0 { return nil } - return errno + return errnoErr2(e1, e2) +} + +func impl_Flock(fd int, how int) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_FLOCK<<4, uintptr(fd), uintptr(how)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_FlockAddr() *(func(fd int, how int) (err error)) + +var Flock = enter_Flock + +func validFlock(fp uintptr) bool { + if funcptrtest(GetZosLibVec()+SYS_FLOCK<<4, "") == 0 { + if name, err := getLeFuncName(GetZosLibVec() + SYS_FLOCK<<4); err == nil { + return name == "flock" + } + } + return false +} + +func enter_Flock(fd int, how int) (err error) { + funcref := get_FlockAddr() + if validFlock(GetZosLibVec() + SYS_FLOCK<<4) { + *funcref = impl_Flock + } else { + *funcref = legacyFlock + } + return (*funcref)(fd, how) } -func Flock(fd int, how int) error { +func legacyFlock(fd int, how int) error { var flock_type int16 var fcntl_cmd int @@ -1307,41 +2109,51 @@ func Flock(fd int, how int) error { } func Mlock(b []byte) (err error) { - _, _, e1 := syscall_syscall(SYS___MLOCKALL, _BPX_NONSWAP, 0, 0) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___MLOCKALL<<4, _BPX_NONSWAP) + runtime.ExitSyscall() + if r0 != 0 { + err = errnoErr2(e1, e2) } return } func Mlock2(b []byte, flags int) (err error) { - _, _, e1 := syscall_syscall(SYS___MLOCKALL, _BPX_NONSWAP, 0, 0) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___MLOCKALL<<4, _BPX_NONSWAP) + runtime.ExitSyscall() + if r0 != 0 { + err = errnoErr2(e1, e2) } return } func Mlockall(flags int) (err error) { - _, _, e1 := syscall_syscall(SYS___MLOCKALL, _BPX_NONSWAP, 0, 0) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___MLOCKALL<<4, _BPX_NONSWAP) + runtime.ExitSyscall() + if r0 != 0 { + err = errnoErr2(e1, e2) } return } func Munlock(b []byte) (err error) { - _, _, e1 := syscall_syscall(SYS___MLOCKALL, _BPX_SWAP, 0, 0) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___MLOCKALL<<4, _BPX_SWAP) + runtime.ExitSyscall() + if r0 != 0 { + err = errnoErr2(e1, e2) } return } func Munlockall() (err error) { - _, _, e1 := syscall_syscall(SYS___MLOCKALL, _BPX_SWAP, 0, 0) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___MLOCKALL<<4, _BPX_SWAP) + runtime.ExitSyscall() + if r0 != 0 { + err = errnoErr2(e1, e2) } return } @@ -1367,20 +2179,109 @@ func ClockGettime(clockid int32, ts *Timespec) error { ts.Sec = int64(tm.Utime / ticks_per_sec) ts.Nsec = int64(tm.Utime) * nsec_per_sec / int64(ticks_per_sec) } else { - return EINVAL + return EINVAL + } + return nil +} + +// Chtag + +//go:nosplit +func get_ChtagAddr() *(func(path string, ccsid uint64, textbit uint64) error) + +var Chtag = enter_Chtag + +func enter_Chtag(path string, ccsid uint64, textbit uint64) error { + funcref := get_ChtagAddr() + if validSetxattr() { + *funcref = impl_Chtag + } else { + *funcref = legacy_Chtag + } + return (*funcref)(path, ccsid, textbit) +} + +func legacy_Chtag(path string, ccsid uint64, textbit uint64) error { + tag := ccsid<<16 | textbit<<15 + var tag_buff [8]byte + DecodeData(tag_buff[:], 8, tag) + return Setxattr(path, "filetag", tag_buff[:], XATTR_REPLACE) +} + +func impl_Chtag(path string, ccsid uint64, textbit uint64) error { + tag := ccsid<<16 | textbit<<15 + var tag_buff [4]byte + DecodeData(tag_buff[:], 4, tag) + return Setxattr(path, "system.filetag", tag_buff[:], XATTR_REPLACE) +} + +// End of Chtag + +// Nanosleep + +//go:nosplit +func get_NanosleepAddr() *(func(time *Timespec, leftover *Timespec) error) + +var Nanosleep = enter_Nanosleep + +func enter_Nanosleep(time *Timespec, leftover *Timespec) error { + funcref := get_NanosleepAddr() + if funcptrtest(GetZosLibVec()+SYS_NANOSLEEP<<4, "") == 0 { + *funcref = impl_Nanosleep + } else { + *funcref = legacyNanosleep + } + return (*funcref)(time, leftover) +} + +func impl_Nanosleep(time *Timespec, leftover *Timespec) error { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_NANOSLEEP<<4, uintptr(unsafe.Pointer(time)), uintptr(unsafe.Pointer(leftover))) + runtime.ExitSyscall() + if int64(r0) == -1 { + return errnoErr2(e1, e2) } return nil } -func Statfs(path string, stat *Statfs_t) (err error) { - fd, err := open(path, O_RDONLY, 0) - defer Close(fd) - if err != nil { - return err +func legacyNanosleep(time *Timespec, leftover *Timespec) error { + t0 := runtime.Nanotime1() + var secrem uint32 + var nsecrem uint32 + total := time.Sec*1000000000 + time.Nsec + elapsed := runtime.Nanotime1() - t0 + var rv int32 + var rc int32 + var err error + // repeatedly sleep for 1 second until less than 1 second left + for total-elapsed > 1000000000 { + rv, rc, _ = BpxCondTimedWait(uint32(1), uint32(0), uint32(CW_CONDVAR), &secrem, &nsecrem) + if rv != 0 && rc != 112 { // 112 is EAGAIN + if leftover != nil && rc == 120 { // 120 is EINTR + leftover.Sec = int64(secrem) + leftover.Nsec = int64(nsecrem) + } + err = Errno(rc) + return err + } + elapsed = runtime.Nanotime1() - t0 + } + // sleep the remainder + if total > elapsed { + rv, rc, _ = BpxCondTimedWait(uint32(0), uint32(total-elapsed), uint32(CW_CONDVAR), &secrem, &nsecrem) + } + if leftover != nil && rc == 120 { + leftover.Sec = int64(secrem) + leftover.Nsec = int64(nsecrem) + } + if rv != 0 && rc != 112 { + err = Errno(rc) } - return Fstatfs(fd, stat) + return err } +// End of Nanosleep + var ( Stdin = 0 Stdout = 1 @@ -1395,6 +2296,9 @@ var ( errENOENT error = syscall.ENOENT ) +var ZosTraceLevel int +var ZosTracefile *os.File + var ( signalNameMapOnce sync.Once signalNameMap map[string]syscall.Signal @@ -1416,6 +2320,56 @@ func errnoErr(e Errno) error { return e } +var reg *regexp.Regexp + +// enhanced with zos specific errno2 +func errnoErr2(e Errno, e2 uintptr) error { + switch e { + case 0: + return nil + case EAGAIN: + return errEAGAIN + /* + Allow the retrieval of errno2 for EINVAL and ENOENT on zos + case EINVAL: + return errEINVAL + case ENOENT: + return errENOENT + */ + } + if ZosTraceLevel > 0 { + var name string + if reg == nil { + reg = regexp.MustCompile("(^unix\\.[^/]+$|.*\\/unix\\.[^/]+$)") + } + i := 1 + pc, file, line, ok := runtime.Caller(i) + if ok { + name = runtime.FuncForPC(pc).Name() + } + for ok && reg.MatchString(runtime.FuncForPC(pc).Name()) { + i += 1 + pc, file, line, ok = runtime.Caller(i) + } + if ok { + if ZosTracefile == nil { + ZosConsolePrintf("From %s:%d\n", file, line) + ZosConsolePrintf("%s: %s (errno2=0x%x)\n", name, e.Error(), e2) + } else { + fmt.Fprintf(ZosTracefile, "From %s:%d\n", file, line) + fmt.Fprintf(ZosTracefile, "%s: %s (errno2=0x%x)\n", name, e.Error(), e2) + } + } else { + if ZosTracefile == nil { + ZosConsolePrintf("%s (errno2=0x%x)\n", e.Error(), e2) + } else { + fmt.Fprintf(ZosTracefile, "%s (errno2=0x%x)\n", e.Error(), e2) + } + } + } + return e +} + // ErrnoName returns the error name for error number e. func ErrnoName(e Errno) string { i := sort.Search(len(errorList), func(i int) bool { @@ -1474,6 +2428,9 @@ func (m *mmapper) Mmap(fd int, offset int64, length int, prot int, flags int) (d return nil, EINVAL } + // Set __MAP_64 by default + flags |= __MAP_64 + // Map the requested memory. addr, errno := m.mmap(0, uintptr(length), prot, flags, fd, offset) if errno != nil { @@ -1520,14 +2477,6 @@ func (m *mmapper) Munmap(data []byte) (err error) { return nil } -func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) { - return mapper.Mmap(fd, offset, length, prot, flags) -} - -func Munmap(b []byte) (err error) { - return mapper.Munmap(b) -} - func Read(fd int, p []byte) (n int, err error) { n, err = read(fd, p) if raceenabled { @@ -1786,83 +2735,170 @@ func Exec(argv0 string, argv []string, envv []string) error { return syscall.Exec(argv0, argv, envv) } -func Mount(source string, target string, fstype string, flags uintptr, data string) (err error) { +func Getag(path string) (ccsid uint16, flag uint16, err error) { + var val [8]byte + sz, err := Getxattr(path, "ccsid", val[:]) + if err != nil { + return + } + ccsid = uint16(EncodeData(val[0:sz])) + sz, err = Getxattr(path, "flags", val[:]) + if err != nil { + return + } + flag = uint16(EncodeData(val[0:sz]) >> 15) + return +} + +// Mount begin +func impl_Mount(source string, target string, fstype string, flags uintptr, data string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(source) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(target) + if err != nil { + return + } + var _p2 *byte + _p2, err = BytePtrFromString(fstype) + if err != nil { + return + } + var _p3 *byte + _p3, err = BytePtrFromString(data) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___MOUNT1_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(unsafe.Pointer(_p2)), uintptr(flags), uintptr(unsafe.Pointer(_p3))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_MountAddr() *(func(source string, target string, fstype string, flags uintptr, data string) (err error)) + +var Mount = enter_Mount + +func enter_Mount(source string, target string, fstype string, flags uintptr, data string) (err error) { + funcref := get_MountAddr() + if validMount() { + *funcref = impl_Mount + } else { + *funcref = legacyMount + } + return (*funcref)(source, target, fstype, flags, data) +} + +func legacyMount(source string, target string, fstype string, flags uintptr, data string) (err error) { if needspace := 8 - len(fstype); needspace <= 0 { - fstype = fstype[:8] + fstype = fstype[0:8] } else { - fstype += " "[:needspace] + fstype += " "[0:needspace] } return mount_LE(target, source, fstype, uint32(flags), int32(len(data)), data) } -func Unmount(name string, mtm int) (err error) { +func validMount() bool { + if funcptrtest(GetZosLibVec()+SYS___MOUNT1_A<<4, "") == 0 { + if name, err := getLeFuncName(GetZosLibVec() + SYS___MOUNT1_A<<4); err == nil { + return name == "__mount1_a" + } + } + return false +} + +// Mount end + +// Unmount begin +func impl_Unmount(target string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(target) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___UMOUNT2_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(flags)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_UnmountAddr() *(func(target string, flags int) (err error)) + +var Unmount = enter_Unmount + +func enter_Unmount(target string, flags int) (err error) { + funcref := get_UnmountAddr() + if funcptrtest(GetZosLibVec()+SYS___UMOUNT2_A<<4, "") == 0 { + *funcref = impl_Unmount + } else { + *funcref = legacyUnmount + } + return (*funcref)(target, flags) +} + +func legacyUnmount(name string, mtm int) (err error) { // mountpoint is always a full path and starts with a '/' // check if input string is not a mountpoint but a filesystem name if name[0] != '/' { - return unmount(name, mtm) + return unmount_LE(name, mtm) } // treat name as mountpoint b2s := func(arr []byte) string { - nulli := bytes.IndexByte(arr, 0) - if nulli == -1 { - return string(arr) - } else { - return string(arr[:nulli]) + var str string + for i := 0; i < len(arr); i++ { + if arr[i] == 0 { + str = string(arr[:i]) + break + } } + return str } var buffer struct { header W_Mnth fsinfo [64]W_Mntent } - fsCount, err := W_Getmntent_A((*byte)(unsafe.Pointer(&buffer)), int(unsafe.Sizeof(buffer))) - if err != nil { - return err - } - if fsCount == 0 { - return EINVAL - } - for i := 0; i < fsCount; i++ { - if b2s(buffer.fsinfo[i].Mountpoint[:]) == name { - err = unmount(b2s(buffer.fsinfo[i].Fsname[:]), mtm) - break + fs_count, err := W_Getmntent_A((*byte)(unsafe.Pointer(&buffer)), int(unsafe.Sizeof(buffer))) + if err == nil { + err = EINVAL + for i := 0; i < fs_count; i++ { + if b2s(buffer.fsinfo[i].Mountpoint[:]) == name { + err = unmount_LE(b2s(buffer.fsinfo[i].Fsname[:]), mtm) + break + } } + } else if fs_count == 0 { + err = EINVAL } return err } -func fdToPath(dirfd int) (path string, err error) { - var buffer [1024]byte - // w_ctrl() - ret := runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS_W_IOCTL<<4, - []uintptr{uintptr(dirfd), 17, 1024, uintptr(unsafe.Pointer(&buffer[0]))}) - if ret == 0 { - zb := bytes.IndexByte(buffer[:], 0) - if zb == -1 { - zb = len(buffer) - } - // __e2a_l() - runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___E2A_L<<4, - []uintptr{uintptr(unsafe.Pointer(&buffer[0])), uintptr(zb)}) - return string(buffer[:zb]), nil - } - // __errno() - errno := int(*(*int32)(unsafe.Pointer(runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___ERRNO<<4, - []uintptr{})))) - // __errno2() - errno2 := int(runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___ERRNO2<<4, - []uintptr{})) - // strerror_r() - ret = runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS_STRERROR_R<<4, - []uintptr{uintptr(errno), uintptr(unsafe.Pointer(&buffer[0])), 1024}) - if ret == 0 { - zb := bytes.IndexByte(buffer[:], 0) - if zb == -1 { - zb = len(buffer) - } - return "", fmt.Errorf("%s (errno2=0x%x)", buffer[:zb], errno2) - } else { - return "", fmt.Errorf("fdToPath errno %d (errno2=0x%x)", errno, errno2) +// Unmount end + +func direntIno(buf []byte) (uint64, bool) { + return readInt(buf, unsafe.Offsetof(Dirent{}.Ino), unsafe.Sizeof(Dirent{}.Ino)) +} + +func direntReclen(buf []byte) (uint64, bool) { + return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen)) +} + +func direntNamlen(buf []byte) (uint64, bool) { + reclen, ok := direntReclen(buf) + if !ok { + return 0, false } + return reclen - uint64(unsafe.Offsetof(Dirent{}.Name)), true } func direntLeToDirentUnix(dirent *direntLE, dir uintptr, path string) (Dirent, error) { @@ -1904,7 +2940,7 @@ func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) { } // Get path from fd to avoid unavailable call (fdopendir) - path, err := fdToPath(fd) + path, err := ZosFdToPath(fd) if err != nil { return 0, err } @@ -1918,7 +2954,7 @@ func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) { for { var entryLE direntLE var entrypLE *direntLE - e := readdir_r(d, &entryLE, &entrypLE) + e := Readdir_r(d, &entryLE, &entrypLE) if e != nil { return n, e } @@ -1964,23 +3000,214 @@ func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) { return n, nil } -func ReadDirent(fd int, buf []byte) (n int, err error) { - var base = (*uintptr)(unsafe.Pointer(new(uint64))) - return Getdirentries(fd, buf, base) +func Err2ad() (eadd *int) { + r0, _, _ := CallLeFuncWithErr(GetZosLibVec() + SYS___ERR2AD<<4) + eadd = (*int)(unsafe.Pointer(r0)) + return } -func direntIno(buf []byte) (uint64, bool) { - return readInt(buf, unsafe.Offsetof(Dirent{}.Ino), unsafe.Sizeof(Dirent{}.Ino)) +func ZosConsolePrintf(format string, v ...interface{}) (int, error) { + type __cmsg struct { + _ uint16 + _ [2]uint8 + __msg_length uint32 + __msg uintptr + _ [4]uint8 + } + msg := fmt.Sprintf(format, v...) + strptr := unsafe.Pointer((*reflect.StringHeader)(unsafe.Pointer(&msg)).Data) + len := (*reflect.StringHeader)(unsafe.Pointer(&msg)).Len + cmsg := __cmsg{__msg_length: uint32(len), __msg: uintptr(strptr)} + cmd := uint32(0) + runtime.EnterSyscall() + rc, err2, err1 := CallLeFuncWithErr(GetZosLibVec()+SYS_____CONSOLE_A<<4, uintptr(unsafe.Pointer(&cmsg)), 0, uintptr(unsafe.Pointer(&cmd))) + runtime.ExitSyscall() + if rc != 0 { + return 0, fmt.Errorf("%s (errno2=0x%x)\n", err1.Error(), err2) + } + return 0, nil +} +func ZosStringToEbcdicBytes(str string, nullterm bool) (ebcdicBytes []byte) { + if nullterm { + ebcdicBytes = []byte(str + "\x00") + } else { + ebcdicBytes = []byte(str) + } + A2e(ebcdicBytes) + return +} +func ZosEbcdicBytesToString(b []byte, trimRight bool) (str string) { + res := make([]byte, len(b)) + copy(res, b) + E2a(res) + if trimRight { + str = string(bytes.TrimRight(res, " \x00")) + } else { + str = string(res) + } + return } -func direntReclen(buf []byte) (uint64, bool) { - return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen)) +func fdToPath(dirfd int) (path string, err error) { + var buffer [1024]byte + // w_ctrl() + ret := runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS_W_IOCTL<<4, + []uintptr{uintptr(dirfd), 17, 1024, uintptr(unsafe.Pointer(&buffer[0]))}) + if ret == 0 { + zb := bytes.IndexByte(buffer[:], 0) + if zb == -1 { + zb = len(buffer) + } + // __e2a_l() + runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___E2A_L<<4, + []uintptr{uintptr(unsafe.Pointer(&buffer[0])), uintptr(zb)}) + return string(buffer[:zb]), nil + } + // __errno() + errno := int(*(*int32)(unsafe.Pointer(runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___ERRNO<<4, + []uintptr{})))) + // __errno2() + errno2 := int(runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___ERRNO2<<4, + []uintptr{})) + // strerror_r() + ret = runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS_STRERROR_R<<4, + []uintptr{uintptr(errno), uintptr(unsafe.Pointer(&buffer[0])), 1024}) + if ret == 0 { + zb := bytes.IndexByte(buffer[:], 0) + if zb == -1 { + zb = len(buffer) + } + return "", fmt.Errorf("%s (errno2=0x%x)", buffer[:zb], errno2) + } else { + return "", fmt.Errorf("fdToPath errno %d (errno2=0x%x)", errno, errno2) + } } -func direntNamlen(buf []byte) (uint64, bool) { - reclen, ok := direntReclen(buf) - if !ok { - return 0, false +func impl_Mkfifoat(dirfd int, path string, mode uint32) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return } - return reclen - uint64(unsafe.Offsetof(Dirent{}.Name)), true + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___MKFIFOAT_A<<4, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_MkfifoatAddr() *(func(dirfd int, path string, mode uint32) (err error)) + +var Mkfifoat = enter_Mkfifoat + +func enter_Mkfifoat(dirfd int, path string, mode uint32) (err error) { + funcref := get_MkfifoatAddr() + if funcptrtest(GetZosLibVec()+SYS___MKFIFOAT_A<<4, "") == 0 { + *funcref = impl_Mkfifoat + } else { + *funcref = legacy_Mkfifoat + } + return (*funcref)(dirfd, path, mode) +} + +func legacy_Mkfifoat(dirfd int, path string, mode uint32) (err error) { + dirname, err := ZosFdToPath(dirfd) + if err != nil { + return err + } + return Mkfifo(dirname+"/"+path, mode) +} + +//sys Posix_openpt(oflag int) (fd int, err error) = SYS_POSIX_OPENPT +//sys Grantpt(fildes int) (rc int, err error) = SYS_GRANTPT +//sys Unlockpt(fildes int) (rc int, err error) = SYS_UNLOCKPT + +func fcntlAsIs(fd uintptr, cmd int, arg uintptr) (val int, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_FCNTL<<4, uintptr(fd), uintptr(cmd), arg) + runtime.ExitSyscall() + val = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +func Fcntl(fd uintptr, cmd int, op interface{}) (ret int, err error) { + switch op.(type) { + case *Flock_t: + err = FcntlFlock(fd, cmd, op.(*Flock_t)) + if err != nil { + ret = -1 + } + return + case int: + return FcntlInt(fd, cmd, op.(int)) + case *F_cnvrt: + return fcntlAsIs(fd, cmd, uintptr(unsafe.Pointer(op.(*F_cnvrt)))) + case unsafe.Pointer: + return fcntlAsIs(fd, cmd, uintptr(op.(unsafe.Pointer))) + default: + return -1, EINVAL + } + return +} + +func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) { + if raceenabled { + raceReleaseMerge(unsafe.Pointer(&ioSync)) + } + return sendfile(outfd, infd, offset, count) +} + +func sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) { + // TODO: use LE call instead if the call is implemented + originalOffset, err := Seek(infd, 0, SEEK_CUR) + if err != nil { + return -1, err + } + //start reading data from in_fd + if offset != nil { + _, err := Seek(infd, *offset, SEEK_SET) + if err != nil { + return -1, err + } + } + + buf := make([]byte, count) + readBuf := make([]byte, 0) + var n int = 0 + for i := 0; i < count; i += n { + n, err := Read(infd, buf) + if n == 0 { + if err != nil { + return -1, err + } else { // EOF + break + } + } + readBuf = append(readBuf, buf...) + buf = buf[0:0] + } + + n2, err := Write(outfd, readBuf) + if err != nil { + return -1, err + } + + //When sendfile() returns, this variable will be set to the + // offset of the byte following the last byte that was read. + if offset != nil { + *offset = *offset + int64(n) + // If offset is not NULL, then sendfile() does not modify the file + // offset of in_fd + _, err := Seek(infd, originalOffset, SEEK_SET) + if err != nil { + return -1, err + } + } + return n2, nil } diff --git a/vendor/golang.org/x/sys/unix/sysvshm_unix.go b/vendor/golang.org/x/sys/unix/sysvshm_unix.go index 79a84f18b..672d6b0a8 100644 --- a/vendor/golang.org/x/sys/unix/sysvshm_unix.go +++ b/vendor/golang.org/x/sys/unix/sysvshm_unix.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build (darwin && !ios) || linux +//go:build (darwin && !ios) || linux || zos package unix diff --git a/vendor/golang.org/x/sys/unix/sysvshm_unix_other.go b/vendor/golang.org/x/sys/unix/sysvshm_unix_other.go index 9eb0db664..8b7977a28 100644 --- a/vendor/golang.org/x/sys/unix/sysvshm_unix_other.go +++ b/vendor/golang.org/x/sys/unix/sysvshm_unix_other.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build darwin && !ios +//go:build (darwin && !ios) || zos package unix diff --git a/vendor/golang.org/x/sys/unix/vgetrandom_linux.go b/vendor/golang.org/x/sys/unix/vgetrandom_linux.go new file mode 100644 index 000000000..07ac8e09d --- /dev/null +++ b/vendor/golang.org/x/sys/unix/vgetrandom_linux.go @@ -0,0 +1,13 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build linux && go1.24 + +package unix + +import _ "unsafe" + +//go:linkname vgetrandom runtime.vgetrandom +//go:noescape +func vgetrandom(p []byte, flags uint32) (ret int, supported bool) diff --git a/vendor/golang.org/x/sys/unix/vgetrandom_unsupported.go b/vendor/golang.org/x/sys/unix/vgetrandom_unsupported.go new file mode 100644 index 000000000..297e97bce --- /dev/null +++ b/vendor/golang.org/x/sys/unix/vgetrandom_unsupported.go @@ -0,0 +1,11 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !linux || !go1.24 + +package unix + +func vgetrandom(p []byte, flags uint32) (ret int, supported bool) { + return -1, false +} diff --git a/vendor/golang.org/x/sys/unix/zerrors_darwin_amd64.go b/vendor/golang.org/x/sys/unix/zerrors_darwin_amd64.go index e40fa8524..d73c4652e 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_darwin_amd64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_darwin_amd64.go @@ -237,6 +237,9 @@ const ( CLOCK_UPTIME_RAW_APPROX = 0x9 CLONE_NOFOLLOW = 0x1 CLONE_NOOWNERCOPY = 0x2 + CONNECT_DATA_AUTHENTICATED = 0x4 + CONNECT_DATA_IDEMPOTENT = 0x2 + CONNECT_RESUME_ON_READ_WRITE = 0x1 CR0 = 0x0 CR1 = 0x1000 CR2 = 0x2000 @@ -1169,6 +1172,11 @@ const ( PT_WRITE_D = 0x5 PT_WRITE_I = 0x4 PT_WRITE_U = 0x6 + RENAME_EXCL = 0x4 + RENAME_NOFOLLOW_ANY = 0x10 + RENAME_RESERVED1 = 0x8 + RENAME_SECLUDE = 0x1 + RENAME_SWAP = 0x2 RLIMIT_AS = 0x5 RLIMIT_CORE = 0x4 RLIMIT_CPU = 0x0 @@ -1260,6 +1268,10 @@ const ( RTV_SSTHRESH = 0x20 RUSAGE_CHILDREN = -0x1 RUSAGE_SELF = 0x0 + SAE_ASSOCID_ALL = 0xffffffff + SAE_ASSOCID_ANY = 0x0 + SAE_CONNID_ALL = 0xffffffff + SAE_CONNID_ANY = 0x0 SCM_CREDS = 0x3 SCM_RIGHTS = 0x1 SCM_TIMESTAMP = 0x2 diff --git a/vendor/golang.org/x/sys/unix/zerrors_darwin_arm64.go b/vendor/golang.org/x/sys/unix/zerrors_darwin_arm64.go index bb02aa6c0..4a55a4005 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_darwin_arm64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_darwin_arm64.go @@ -237,6 +237,9 @@ const ( CLOCK_UPTIME_RAW_APPROX = 0x9 CLONE_NOFOLLOW = 0x1 CLONE_NOOWNERCOPY = 0x2 + CONNECT_DATA_AUTHENTICATED = 0x4 + CONNECT_DATA_IDEMPOTENT = 0x2 + CONNECT_RESUME_ON_READ_WRITE = 0x1 CR0 = 0x0 CR1 = 0x1000 CR2 = 0x2000 @@ -1169,6 +1172,11 @@ const ( PT_WRITE_D = 0x5 PT_WRITE_I = 0x4 PT_WRITE_U = 0x6 + RENAME_EXCL = 0x4 + RENAME_NOFOLLOW_ANY = 0x10 + RENAME_RESERVED1 = 0x8 + RENAME_SECLUDE = 0x1 + RENAME_SWAP = 0x2 RLIMIT_AS = 0x5 RLIMIT_CORE = 0x4 RLIMIT_CPU = 0x0 @@ -1260,6 +1268,10 @@ const ( RTV_SSTHRESH = 0x20 RUSAGE_CHILDREN = -0x1 RUSAGE_SELF = 0x0 + SAE_ASSOCID_ALL = 0xffffffff + SAE_ASSOCID_ANY = 0x0 + SAE_CONNID_ALL = 0xffffffff + SAE_CONNID_ANY = 0x0 SCM_CREDS = 0x3 SCM_RIGHTS = 0x1 SCM_TIMESTAMP = 0x2 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux.go b/vendor/golang.org/x/sys/unix/zerrors_linux.go index 36bf8399f..ccba391c9 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux.go @@ -457,6 +457,7 @@ const ( B600 = 0x8 B75 = 0x2 B9600 = 0xd + BCACHEFS_SUPER_MAGIC = 0xca451a4e BDEVFS_MAGIC = 0x62646576 BINDERFS_SUPER_MAGIC = 0x6c6f6f70 BINFMTFS_MAGIC = 0x42494e4d @@ -491,8 +492,10 @@ const ( BPF_F_REPLACE = 0x4 BPF_F_SLEEPABLE = 0x10 BPF_F_STRICT_ALIGNMENT = 0x1 + BPF_F_TEST_REG_INVARIANTS = 0x80 BPF_F_TEST_RND_HI32 = 0x4 BPF_F_TEST_RUN_ON_CPU = 0x1 + BPF_F_TEST_SKB_CHECKSUM_COMPLETE = 0x4 BPF_F_TEST_STATE_FREQ = 0x8 BPF_F_TEST_XDP_LIVE_FRAMES = 0x2 BPF_F_XDP_DEV_BOUND_ONLY = 0x40 @@ -501,6 +504,7 @@ const ( BPF_IMM = 0x0 BPF_IND = 0x40 BPF_JA = 0x0 + BPF_JCOND = 0xe0 BPF_JEQ = 0x10 BPF_JGE = 0x30 BPF_JGT = 0x20 @@ -656,6 +660,9 @@ const ( CAN_NPROTO = 0x8 CAN_RAW = 0x1 CAN_RAW_FILTER_MAX = 0x200 + CAN_RAW_XL_VCID_RX_FILTER = 0x4 + CAN_RAW_XL_VCID_TX_PASS = 0x2 + CAN_RAW_XL_VCID_TX_SET = 0x1 CAN_RTR_FLAG = 0x40000000 CAN_SFF_ID_BITS = 0xb CAN_SFF_MASK = 0x7ff @@ -923,6 +930,7 @@ const ( EPOLL_CTL_ADD = 0x1 EPOLL_CTL_DEL = 0x2 EPOLL_CTL_MOD = 0x3 + EPOLL_IOC_TYPE = 0x8a EROFS_SUPER_MAGIC_V1 = 0xe0f5e1e2 ESP_V4_FLOW = 0xa ESP_V6_FLOW = 0xc @@ -936,9 +944,6 @@ const ( ETHTOOL_FEC_OFF = 0x4 ETHTOOL_FEC_RS = 0x8 ETHTOOL_FLAG_ALL = 0x7 - ETHTOOL_FLAG_COMPACT_BITSETS = 0x1 - ETHTOOL_FLAG_OMIT_REPLY = 0x2 - ETHTOOL_FLAG_STATS = 0x4 ETHTOOL_FLASHDEV = 0x33 ETHTOOL_FLASH_MAX_FILENAME = 0x80 ETHTOOL_FWVERS_LEN = 0x20 @@ -1338,6 +1343,7 @@ const ( F_OFD_SETLK = 0x25 F_OFD_SETLKW = 0x26 F_OK = 0x0 + F_SEAL_EXEC = 0x20 F_SEAL_FUTURE_WRITE = 0x10 F_SEAL_GROW = 0x4 F_SEAL_SEAL = 0x1 @@ -1626,6 +1632,7 @@ const ( IP_FREEBIND = 0xf IP_HDRINCL = 0x3 IP_IPSEC_POLICY = 0x10 + IP_LOCAL_PORT_RANGE = 0x33 IP_MAXPACKET = 0xffff IP_MAX_MEMBERSHIPS = 0x14 IP_MF = 0x2000 @@ -1652,6 +1659,7 @@ const ( IP_PMTUDISC_OMIT = 0x5 IP_PMTUDISC_PROBE = 0x3 IP_PMTUDISC_WANT = 0x1 + IP_PROTOCOL = 0x34 IP_RECVERR = 0xb IP_RECVERR_RFC4884 = 0x1a IP_RECVFRAGSIZE = 0x19 @@ -1697,6 +1705,8 @@ const ( KEXEC_ARCH_S390 = 0x160000 KEXEC_ARCH_SH = 0x2a0000 KEXEC_ARCH_X86_64 = 0x3e0000 + KEXEC_CRASH_HOTPLUG_SUPPORT = 0x8 + KEXEC_FILE_DEBUG = 0x8 KEXEC_FILE_NO_INITRAMFS = 0x4 KEXEC_FILE_ON_CRASH = 0x2 KEXEC_FILE_UNLOAD = 0x1 @@ -1771,6 +1781,7 @@ const ( KEY_SPEC_USER_KEYRING = -0x4 KEY_SPEC_USER_SESSION_KEYRING = -0x5 LANDLOCK_ACCESS_FS_EXECUTE = 0x1 + LANDLOCK_ACCESS_FS_IOCTL_DEV = 0x8000 LANDLOCK_ACCESS_FS_MAKE_BLOCK = 0x800 LANDLOCK_ACCESS_FS_MAKE_CHAR = 0x40 LANDLOCK_ACCESS_FS_MAKE_DIR = 0x80 @@ -1852,6 +1863,19 @@ const ( MAP_FILE = 0x0 MAP_FIXED = 0x10 MAP_FIXED_NOREPLACE = 0x100000 + MAP_HUGE_16GB = 0x88000000 + MAP_HUGE_16KB = 0x38000000 + MAP_HUGE_16MB = 0x60000000 + MAP_HUGE_1GB = 0x78000000 + MAP_HUGE_1MB = 0x50000000 + MAP_HUGE_256MB = 0x70000000 + MAP_HUGE_2GB = 0x7c000000 + MAP_HUGE_2MB = 0x54000000 + MAP_HUGE_32MB = 0x64000000 + MAP_HUGE_512KB = 0x4c000000 + MAP_HUGE_512MB = 0x74000000 + MAP_HUGE_64KB = 0x40000000 + MAP_HUGE_8MB = 0x5c000000 MAP_HUGE_MASK = 0x3f MAP_HUGE_SHIFT = 0x1a MAP_PRIVATE = 0x2 @@ -1898,6 +1922,8 @@ const ( MNT_DETACH = 0x2 MNT_EXPIRE = 0x4 MNT_FORCE = 0x1 + MNT_ID_REQ_SIZE_VER0 = 0x18 + MNT_ID_REQ_SIZE_VER1 = 0x20 MODULE_INIT_COMPRESSED_FILE = 0x4 MODULE_INIT_IGNORE_MODVERSIONS = 0x1 MODULE_INIT_IGNORE_VERMAGIC = 0x2 @@ -2163,10 +2189,10 @@ const ( NFT_REG_SIZE = 0x10 NFT_REJECT_ICMPX_MAX = 0x3 NFT_RT_MAX = 0x4 - NFT_SECMARK_CTX_MAXLEN = 0x100 + NFT_SECMARK_CTX_MAXLEN = 0x1000 NFT_SET_MAXNAMELEN = 0x100 NFT_SOCKET_MAX = 0x3 - NFT_TABLE_F_MASK = 0x3 + NFT_TABLE_F_MASK = 0x7 NFT_TABLE_MAXNAMELEN = 0x100 NFT_TRACETYPE_MAX = 0x3 NFT_TUNNEL_F_MASK = 0x7 @@ -2302,6 +2328,7 @@ const ( PERF_AUX_FLAG_PARTIAL = 0x4 PERF_AUX_FLAG_PMU_FORMAT_TYPE_MASK = 0xff00 PERF_AUX_FLAG_TRUNCATED = 0x1 + PERF_BRANCH_ENTRY_INFO_BITS_MAX = 0x21 PERF_BR_ARM64_DEBUG_DATA = 0x7 PERF_BR_ARM64_DEBUG_EXIT = 0x5 PERF_BR_ARM64_DEBUG_HALT = 0x4 @@ -2331,9 +2358,11 @@ const ( PERF_MEM_LVLNUM_IO = 0xa PERF_MEM_LVLNUM_L1 = 0x1 PERF_MEM_LVLNUM_L2 = 0x2 + PERF_MEM_LVLNUM_L2_MHB = 0x5 PERF_MEM_LVLNUM_L3 = 0x3 PERF_MEM_LVLNUM_L4 = 0x4 PERF_MEM_LVLNUM_LFB = 0xc + PERF_MEM_LVLNUM_MSC = 0x6 PERF_MEM_LVLNUM_NA = 0xf PERF_MEM_LVLNUM_PMEM = 0xe PERF_MEM_LVLNUM_RAM = 0xd @@ -2399,12 +2428,14 @@ const ( PERF_RECORD_MISC_USER = 0x2 PERF_SAMPLE_BRANCH_PLM_ALL = 0x7 PERF_SAMPLE_WEIGHT_TYPE = 0x1004000 + PID_FS_MAGIC = 0x50494446 PIPEFS_MAGIC = 0x50495045 PPPIOCGNPMODE = 0xc008744c PPPIOCNEWUNIT = 0xc004743e PRIO_PGRP = 0x1 PRIO_PROCESS = 0x0 PRIO_USER = 0x2 + PROCFS_IOCTL_MAGIC = 'f' PROC_SUPER_MAGIC = 0x9fa0 PROT_EXEC = 0x4 PROT_GROWSDOWN = 0x1000000 @@ -2486,6 +2517,23 @@ const ( PR_PAC_GET_ENABLED_KEYS = 0x3d PR_PAC_RESET_KEYS = 0x36 PR_PAC_SET_ENABLED_KEYS = 0x3c + PR_PPC_DEXCR_CTRL_CLEAR = 0x4 + PR_PPC_DEXCR_CTRL_CLEAR_ONEXEC = 0x10 + PR_PPC_DEXCR_CTRL_EDITABLE = 0x1 + PR_PPC_DEXCR_CTRL_MASK = 0x1f + PR_PPC_DEXCR_CTRL_SET = 0x2 + PR_PPC_DEXCR_CTRL_SET_ONEXEC = 0x8 + PR_PPC_DEXCR_IBRTPD = 0x1 + PR_PPC_DEXCR_NPHIE = 0x3 + PR_PPC_DEXCR_SBHE = 0x0 + PR_PPC_DEXCR_SRAPD = 0x2 + PR_PPC_GET_DEXCR = 0x48 + PR_PPC_SET_DEXCR = 0x49 + PR_RISCV_CTX_SW_FENCEI_OFF = 0x1 + PR_RISCV_CTX_SW_FENCEI_ON = 0x0 + PR_RISCV_SCOPE_PER_PROCESS = 0x0 + PR_RISCV_SCOPE_PER_THREAD = 0x1 + PR_RISCV_SET_ICACHE_FLUSH_CTX = 0x47 PR_RISCV_V_GET_CONTROL = 0x46 PR_RISCV_V_SET_CONTROL = 0x45 PR_RISCV_V_VSTATE_CTRL_CUR_MASK = 0x3 @@ -2577,6 +2625,28 @@ const ( PR_UNALIGN_NOPRINT = 0x1 PR_UNALIGN_SIGBUS = 0x2 PSTOREFS_MAGIC = 0x6165676c + PTP_CLK_MAGIC = '=' + PTP_ENABLE_FEATURE = 0x1 + PTP_EXTTS_EDGES = 0x6 + PTP_EXTTS_EVENT_VALID = 0x1 + PTP_EXTTS_V1_VALID_FLAGS = 0x7 + PTP_EXTTS_VALID_FLAGS = 0x1f + PTP_EXT_OFFSET = 0x10 + PTP_FALLING_EDGE = 0x4 + PTP_MAX_SAMPLES = 0x19 + PTP_PEROUT_DUTY_CYCLE = 0x2 + PTP_PEROUT_ONE_SHOT = 0x1 + PTP_PEROUT_PHASE = 0x4 + PTP_PEROUT_V1_VALID_FLAGS = 0x0 + PTP_PEROUT_VALID_FLAGS = 0x7 + PTP_PIN_GETFUNC = 0xc0603d06 + PTP_PIN_GETFUNC2 = 0xc0603d0f + PTP_RISING_EDGE = 0x2 + PTP_STRICT_FLAGS = 0x8 + PTP_SYS_OFFSET_EXTENDED = 0xc4c03d09 + PTP_SYS_OFFSET_EXTENDED2 = 0xc4c03d12 + PTP_SYS_OFFSET_PRECISE = 0xc0403d08 + PTP_SYS_OFFSET_PRECISE2 = 0xc0403d11 PTRACE_ATTACH = 0x10 PTRACE_CONT = 0x7 PTRACE_DETACH = 0x11 @@ -2890,10 +2960,12 @@ const ( RUSAGE_SELF = 0x0 RUSAGE_THREAD = 0x1 RWF_APPEND = 0x10 + RWF_ATOMIC = 0x40 RWF_DSYNC = 0x2 RWF_HIPRI = 0x1 + RWF_NOAPPEND = 0x20 RWF_NOWAIT = 0x8 - RWF_SUPPORTED = 0x1f + RWF_SUPPORTED = 0x7f RWF_SYNC = 0x4 RWF_WRITE_LIFE_NOT_SET = 0x0 SCHED_BATCH = 0x3 @@ -2914,7 +2986,9 @@ const ( SCHED_RESET_ON_FORK = 0x40000000 SCHED_RR = 0x2 SCM_CREDENTIALS = 0x2 + SCM_PIDFD = 0x4 SCM_RIGHTS = 0x1 + SCM_SECURITY = 0x3 SCM_TIMESTAMP = 0x1d SC_LOG_FLUSH = 0x100000 SECCOMP_ADDFD_FLAG_SEND = 0x2 @@ -3047,6 +3121,8 @@ const ( SIOCSMIIREG = 0x8949 SIOCSRARP = 0x8962 SIOCWANDEV = 0x894a + SK_DIAG_BPF_STORAGE_MAX = 0x3 + SK_DIAG_BPF_STORAGE_REQ_MAX = 0x1 SMACK_MAGIC = 0x43415d53 SMART_AUTOSAVE = 0xd2 SMART_AUTO_OFFLINE = 0xdb @@ -3067,6 +3143,8 @@ const ( SOCKFS_MAGIC = 0x534f434b SOCK_BUF_LOCK_MASK = 0x3 SOCK_DCCP = 0x6 + SOCK_DESTROY = 0x15 + SOCK_DIAG_BY_FAMILY = 0x14 SOCK_IOC_TYPE = 0x89 SOCK_PACKET = 0xa SOCK_RAW = 0x3 @@ -3160,6 +3238,7 @@ const ( STATX_ATTR_MOUNT_ROOT = 0x2000 STATX_ATTR_NODUMP = 0x40 STATX_ATTR_VERITY = 0x100000 + STATX_ATTR_WRITE_ATOMIC = 0x400000 STATX_BASIC_STATS = 0x7ff STATX_BLOCKS = 0x400 STATX_BTIME = 0x800 @@ -3168,12 +3247,15 @@ const ( STATX_GID = 0x10 STATX_INO = 0x100 STATX_MNT_ID = 0x1000 + STATX_MNT_ID_UNIQUE = 0x4000 STATX_MODE = 0x2 STATX_MTIME = 0x40 STATX_NLINK = 0x4 STATX_SIZE = 0x200 + STATX_SUBVOL = 0x8000 STATX_TYPE = 0x1 STATX_UID = 0x8 + STATX_WRITE_ATOMIC = 0x10000 STATX__RESERVED = 0x80000000 SYNC_FILE_RANGE_WAIT_AFTER = 0x4 SYNC_FILE_RANGE_WAIT_BEFORE = 0x1 @@ -3255,6 +3337,7 @@ const ( TCP_MAX_WINSHIFT = 0xe TCP_MD5SIG = 0xe TCP_MD5SIG_EXT = 0x20 + TCP_MD5SIG_FLAG_IFINDEX = 0x2 TCP_MD5SIG_FLAG_PREFIX = 0x1 TCP_MD5SIG_MAXKEYLEN = 0x50 TCP_MSS = 0x200 @@ -3562,12 +3645,17 @@ const ( XDP_RX_RING = 0x2 XDP_SHARED_UMEM = 0x1 XDP_STATISTICS = 0x7 + XDP_TXMD_FLAGS_CHECKSUM = 0x2 + XDP_TXMD_FLAGS_TIMESTAMP = 0x1 + XDP_TX_METADATA = 0x2 XDP_TX_RING = 0x3 XDP_UMEM_COMPLETION_RING = 0x6 XDP_UMEM_FILL_RING = 0x5 XDP_UMEM_PGOFF_COMPLETION_RING = 0x180000000 XDP_UMEM_PGOFF_FILL_RING = 0x100000000 XDP_UMEM_REG = 0x4 + XDP_UMEM_TX_METADATA_LEN = 0x4 + XDP_UMEM_TX_SW_CSUM = 0x2 XDP_UMEM_UNALIGNED_CHUNK_FLAG = 0x1 XDP_USE_NEED_WAKEUP = 0x8 XDP_USE_SG = 0x10 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_386.go b/vendor/golang.org/x/sys/unix/zerrors_linux_386.go index 42ff8c3c1..0c00cb3f3 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_386.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_386.go @@ -78,6 +78,8 @@ const ( ECHOPRT = 0x400 EFD_CLOEXEC = 0x80000 EFD_NONBLOCK = 0x800 + EPIOCGPARAMS = 0x80088a02 + EPIOCSPARAMS = 0x40088a01 EPOLL_CLOEXEC = 0x80000 EXTPROC = 0x10000 FF1 = 0x8000 @@ -118,6 +120,7 @@ const ( IXOFF = 0x1000 IXON = 0x400 MAP_32BIT = 0x40 + MAP_ABOVE4G = 0x80 MAP_ANON = 0x20 MAP_ANONYMOUS = 0x20 MAP_DENYWRITE = 0x800 @@ -150,9 +153,14 @@ const ( NFDBITS = 0x20 NLDLY = 0x100 NOFLSH = 0x80 + NS_GET_MNTNS_ID = 0x8008b705 NS_GET_NSTYPE = 0xb703 NS_GET_OWNER_UID = 0xb704 NS_GET_PARENT = 0xb702 + NS_GET_PID_FROM_PIDNS = 0x8004b706 + NS_GET_PID_IN_PIDNS = 0x8004b708 + NS_GET_TGID_FROM_PIDNS = 0x8004b707 + NS_GET_TGID_IN_PIDNS = 0x8004b709 NS_GET_USERNS = 0xb701 OLCUC = 0x2 ONLCR = 0x4 @@ -229,6 +237,20 @@ const ( PPPIOCUNBRIDGECHAN = 0x7434 PPPIOCXFERUNIT = 0x744e PR_SET_PTRACER_ANY = 0xffffffff + PTP_CLOCK_GETCAPS = 0x80503d01 + PTP_CLOCK_GETCAPS2 = 0x80503d0a + PTP_ENABLE_PPS = 0x40043d04 + PTP_ENABLE_PPS2 = 0x40043d0d + PTP_EXTTS_REQUEST = 0x40103d02 + PTP_EXTTS_REQUEST2 = 0x40103d0b + PTP_MASK_CLEAR_ALL = 0x3d13 + PTP_MASK_EN_SINGLE = 0x40043d14 + PTP_PEROUT_REQUEST = 0x40383d03 + PTP_PEROUT_REQUEST2 = 0x40383d0c + PTP_PIN_SETFUNC = 0x40603d07 + PTP_PIN_SETFUNC2 = 0x40603d10 + PTP_SYS_OFFSET = 0x43403d05 + PTP_SYS_OFFSET2 = 0x43403d0e PTRACE_GETFPREGS = 0xe PTRACE_GETFPXREGS = 0x12 PTRACE_GET_THREAD_AREA = 0x19 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go index dca436004..dfb364554 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go @@ -78,6 +78,8 @@ const ( ECHOPRT = 0x400 EFD_CLOEXEC = 0x80000 EFD_NONBLOCK = 0x800 + EPIOCGPARAMS = 0x80088a02 + EPIOCSPARAMS = 0x40088a01 EPOLL_CLOEXEC = 0x80000 EXTPROC = 0x10000 FF1 = 0x8000 @@ -118,6 +120,7 @@ const ( IXOFF = 0x1000 IXON = 0x400 MAP_32BIT = 0x40 + MAP_ABOVE4G = 0x80 MAP_ANON = 0x20 MAP_ANONYMOUS = 0x20 MAP_DENYWRITE = 0x800 @@ -150,9 +153,14 @@ const ( NFDBITS = 0x40 NLDLY = 0x100 NOFLSH = 0x80 + NS_GET_MNTNS_ID = 0x8008b705 NS_GET_NSTYPE = 0xb703 NS_GET_OWNER_UID = 0xb704 NS_GET_PARENT = 0xb702 + NS_GET_PID_FROM_PIDNS = 0x8004b706 + NS_GET_PID_IN_PIDNS = 0x8004b708 + NS_GET_TGID_FROM_PIDNS = 0x8004b707 + NS_GET_TGID_IN_PIDNS = 0x8004b709 NS_GET_USERNS = 0xb701 OLCUC = 0x2 ONLCR = 0x4 @@ -229,6 +237,20 @@ const ( PPPIOCUNBRIDGECHAN = 0x7434 PPPIOCXFERUNIT = 0x744e PR_SET_PTRACER_ANY = 0xffffffffffffffff + PTP_CLOCK_GETCAPS = 0x80503d01 + PTP_CLOCK_GETCAPS2 = 0x80503d0a + PTP_ENABLE_PPS = 0x40043d04 + PTP_ENABLE_PPS2 = 0x40043d0d + PTP_EXTTS_REQUEST = 0x40103d02 + PTP_EXTTS_REQUEST2 = 0x40103d0b + PTP_MASK_CLEAR_ALL = 0x3d13 + PTP_MASK_EN_SINGLE = 0x40043d14 + PTP_PEROUT_REQUEST = 0x40383d03 + PTP_PEROUT_REQUEST2 = 0x40383d0c + PTP_PIN_SETFUNC = 0x40603d07 + PTP_PIN_SETFUNC2 = 0x40603d10 + PTP_SYS_OFFSET = 0x43403d05 + PTP_SYS_OFFSET2 = 0x43403d0e PTRACE_ARCH_PRCTL = 0x1e PTRACE_GETFPREGS = 0xe PTRACE_GETFPXREGS = 0x12 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go b/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go index 5cca668ac..d46dcf78a 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go @@ -78,6 +78,8 @@ const ( ECHOPRT = 0x400 EFD_CLOEXEC = 0x80000 EFD_NONBLOCK = 0x800 + EPIOCGPARAMS = 0x80088a02 + EPIOCSPARAMS = 0x40088a01 EPOLL_CLOEXEC = 0x80000 EXTPROC = 0x10000 FF1 = 0x8000 @@ -148,9 +150,14 @@ const ( NFDBITS = 0x20 NLDLY = 0x100 NOFLSH = 0x80 + NS_GET_MNTNS_ID = 0x8008b705 NS_GET_NSTYPE = 0xb703 NS_GET_OWNER_UID = 0xb704 NS_GET_PARENT = 0xb702 + NS_GET_PID_FROM_PIDNS = 0x8004b706 + NS_GET_PID_IN_PIDNS = 0x8004b708 + NS_GET_TGID_FROM_PIDNS = 0x8004b707 + NS_GET_TGID_IN_PIDNS = 0x8004b709 NS_GET_USERNS = 0xb701 OLCUC = 0x2 ONLCR = 0x4 @@ -227,6 +234,20 @@ const ( PPPIOCUNBRIDGECHAN = 0x7434 PPPIOCXFERUNIT = 0x744e PR_SET_PTRACER_ANY = 0xffffffff + PTP_CLOCK_GETCAPS = 0x80503d01 + PTP_CLOCK_GETCAPS2 = 0x80503d0a + PTP_ENABLE_PPS = 0x40043d04 + PTP_ENABLE_PPS2 = 0x40043d0d + PTP_EXTTS_REQUEST = 0x40103d02 + PTP_EXTTS_REQUEST2 = 0x40103d0b + PTP_MASK_CLEAR_ALL = 0x3d13 + PTP_MASK_EN_SINGLE = 0x40043d14 + PTP_PEROUT_REQUEST = 0x40383d03 + PTP_PEROUT_REQUEST2 = 0x40383d0c + PTP_PIN_SETFUNC = 0x40603d07 + PTP_PIN_SETFUNC2 = 0x40603d10 + PTP_SYS_OFFSET = 0x43403d05 + PTP_SYS_OFFSET2 = 0x43403d0e PTRACE_GETCRUNCHREGS = 0x19 PTRACE_GETFDPIC = 0x1f PTRACE_GETFDPIC_EXEC = 0x0 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go index d8cae6d15..3af3248a7 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go @@ -78,6 +78,8 @@ const ( ECHOPRT = 0x400 EFD_CLOEXEC = 0x80000 EFD_NONBLOCK = 0x800 + EPIOCGPARAMS = 0x80088a02 + EPIOCSPARAMS = 0x40088a01 EPOLL_CLOEXEC = 0x80000 ESR_MAGIC = 0x45535201 EXTPROC = 0x10000 @@ -87,6 +89,7 @@ const ( FICLONE = 0x40049409 FICLONERANGE = 0x4020940d FLUSHO = 0x1000 + FPMR_MAGIC = 0x46504d52 FPSIMD_MAGIC = 0x46508001 FS_IOC_ENABLE_VERITY = 0x40806685 FS_IOC_GETFLAGS = 0x80086601 @@ -151,9 +154,14 @@ const ( NFDBITS = 0x40 NLDLY = 0x100 NOFLSH = 0x80 + NS_GET_MNTNS_ID = 0x8008b705 NS_GET_NSTYPE = 0xb703 NS_GET_OWNER_UID = 0xb704 NS_GET_PARENT = 0xb702 + NS_GET_PID_FROM_PIDNS = 0x8004b706 + NS_GET_PID_IN_PIDNS = 0x8004b708 + NS_GET_TGID_FROM_PIDNS = 0x8004b707 + NS_GET_TGID_IN_PIDNS = 0x8004b709 NS_GET_USERNS = 0xb701 OLCUC = 0x2 ONLCR = 0x4 @@ -232,6 +240,20 @@ const ( PROT_BTI = 0x10 PROT_MTE = 0x20 PR_SET_PTRACER_ANY = 0xffffffffffffffff + PTP_CLOCK_GETCAPS = 0x80503d01 + PTP_CLOCK_GETCAPS2 = 0x80503d0a + PTP_ENABLE_PPS = 0x40043d04 + PTP_ENABLE_PPS2 = 0x40043d0d + PTP_EXTTS_REQUEST = 0x40103d02 + PTP_EXTTS_REQUEST2 = 0x40103d0b + PTP_MASK_CLEAR_ALL = 0x3d13 + PTP_MASK_EN_SINGLE = 0x40043d14 + PTP_PEROUT_REQUEST = 0x40383d03 + PTP_PEROUT_REQUEST2 = 0x40383d0c + PTP_PIN_SETFUNC = 0x40603d07 + PTP_PIN_SETFUNC2 = 0x40603d10 + PTP_SYS_OFFSET = 0x43403d05 + PTP_SYS_OFFSET2 = 0x43403d0e PTRACE_PEEKMTETAGS = 0x21 PTRACE_POKEMTETAGS = 0x22 PTRACE_SYSEMU = 0x1f diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go index 28e39afdc..292bcf028 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go @@ -78,6 +78,8 @@ const ( ECHOPRT = 0x400 EFD_CLOEXEC = 0x80000 EFD_NONBLOCK = 0x800 + EPIOCGPARAMS = 0x80088a02 + EPIOCSPARAMS = 0x40088a01 EPOLL_CLOEXEC = 0x80000 EXTPROC = 0x10000 FF1 = 0x8000 @@ -152,9 +154,14 @@ const ( NFDBITS = 0x40 NLDLY = 0x100 NOFLSH = 0x80 + NS_GET_MNTNS_ID = 0x8008b705 NS_GET_NSTYPE = 0xb703 NS_GET_OWNER_UID = 0xb704 NS_GET_PARENT = 0xb702 + NS_GET_PID_FROM_PIDNS = 0x8004b706 + NS_GET_PID_IN_PIDNS = 0x8004b708 + NS_GET_TGID_FROM_PIDNS = 0x8004b707 + NS_GET_TGID_IN_PIDNS = 0x8004b709 NS_GET_USERNS = 0xb701 OLCUC = 0x2 ONLCR = 0x4 @@ -231,6 +238,20 @@ const ( PPPIOCUNBRIDGECHAN = 0x7434 PPPIOCXFERUNIT = 0x744e PR_SET_PTRACER_ANY = 0xffffffffffffffff + PTP_CLOCK_GETCAPS = 0x80503d01 + PTP_CLOCK_GETCAPS2 = 0x80503d0a + PTP_ENABLE_PPS = 0x40043d04 + PTP_ENABLE_PPS2 = 0x40043d0d + PTP_EXTTS_REQUEST = 0x40103d02 + PTP_EXTTS_REQUEST2 = 0x40103d0b + PTP_MASK_CLEAR_ALL = 0x3d13 + PTP_MASK_EN_SINGLE = 0x40043d14 + PTP_PEROUT_REQUEST = 0x40383d03 + PTP_PEROUT_REQUEST2 = 0x40383d0c + PTP_PIN_SETFUNC = 0x40603d07 + PTP_PIN_SETFUNC2 = 0x40603d10 + PTP_SYS_OFFSET = 0x43403d05 + PTP_SYS_OFFSET2 = 0x43403d0e PTRACE_SYSEMU = 0x1f PTRACE_SYSEMU_SINGLESTEP = 0x20 RLIMIT_AS = 0x9 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go b/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go index cd66e92cb..782b7110f 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go @@ -78,6 +78,8 @@ const ( ECHOPRT = 0x400 EFD_CLOEXEC = 0x80000 EFD_NONBLOCK = 0x80 + EPIOCGPARAMS = 0x40088a02 + EPIOCSPARAMS = 0x80088a01 EPOLL_CLOEXEC = 0x80000 EXTPROC = 0x10000 FF1 = 0x8000 @@ -148,9 +150,14 @@ const ( NFDBITS = 0x20 NLDLY = 0x100 NOFLSH = 0x80 + NS_GET_MNTNS_ID = 0x4008b705 NS_GET_NSTYPE = 0x2000b703 NS_GET_OWNER_UID = 0x2000b704 NS_GET_PARENT = 0x2000b702 + NS_GET_PID_FROM_PIDNS = 0x4004b706 + NS_GET_PID_IN_PIDNS = 0x4004b708 + NS_GET_TGID_FROM_PIDNS = 0x4004b707 + NS_GET_TGID_IN_PIDNS = 0x4004b709 NS_GET_USERNS = 0x2000b701 OLCUC = 0x2 ONLCR = 0x4 @@ -227,6 +234,20 @@ const ( PPPIOCUNBRIDGECHAN = 0x20007434 PPPIOCXFERUNIT = 0x2000744e PR_SET_PTRACER_ANY = 0xffffffff + PTP_CLOCK_GETCAPS = 0x40503d01 + PTP_CLOCK_GETCAPS2 = 0x40503d0a + PTP_ENABLE_PPS = 0x80043d04 + PTP_ENABLE_PPS2 = 0x80043d0d + PTP_EXTTS_REQUEST = 0x80103d02 + PTP_EXTTS_REQUEST2 = 0x80103d0b + PTP_MASK_CLEAR_ALL = 0x20003d13 + PTP_MASK_EN_SINGLE = 0x80043d14 + PTP_PEROUT_REQUEST = 0x80383d03 + PTP_PEROUT_REQUEST2 = 0x80383d0c + PTP_PIN_SETFUNC = 0x80603d07 + PTP_PIN_SETFUNC2 = 0x80603d10 + PTP_SYS_OFFSET = 0x83403d05 + PTP_SYS_OFFSET2 = 0x83403d0e PTRACE_GETFPREGS = 0xe PTRACE_GET_THREAD_AREA = 0x19 PTRACE_GET_THREAD_AREA_3264 = 0xc4 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go index c1595eba7..84973fd92 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go @@ -78,6 +78,8 @@ const ( ECHOPRT = 0x400 EFD_CLOEXEC = 0x80000 EFD_NONBLOCK = 0x80 + EPIOCGPARAMS = 0x40088a02 + EPIOCSPARAMS = 0x80088a01 EPOLL_CLOEXEC = 0x80000 EXTPROC = 0x10000 FF1 = 0x8000 @@ -148,9 +150,14 @@ const ( NFDBITS = 0x40 NLDLY = 0x100 NOFLSH = 0x80 + NS_GET_MNTNS_ID = 0x4008b705 NS_GET_NSTYPE = 0x2000b703 NS_GET_OWNER_UID = 0x2000b704 NS_GET_PARENT = 0x2000b702 + NS_GET_PID_FROM_PIDNS = 0x4004b706 + NS_GET_PID_IN_PIDNS = 0x4004b708 + NS_GET_TGID_FROM_PIDNS = 0x4004b707 + NS_GET_TGID_IN_PIDNS = 0x4004b709 NS_GET_USERNS = 0x2000b701 OLCUC = 0x2 ONLCR = 0x4 @@ -227,6 +234,20 @@ const ( PPPIOCUNBRIDGECHAN = 0x20007434 PPPIOCXFERUNIT = 0x2000744e PR_SET_PTRACER_ANY = 0xffffffffffffffff + PTP_CLOCK_GETCAPS = 0x40503d01 + PTP_CLOCK_GETCAPS2 = 0x40503d0a + PTP_ENABLE_PPS = 0x80043d04 + PTP_ENABLE_PPS2 = 0x80043d0d + PTP_EXTTS_REQUEST = 0x80103d02 + PTP_EXTTS_REQUEST2 = 0x80103d0b + PTP_MASK_CLEAR_ALL = 0x20003d13 + PTP_MASK_EN_SINGLE = 0x80043d14 + PTP_PEROUT_REQUEST = 0x80383d03 + PTP_PEROUT_REQUEST2 = 0x80383d0c + PTP_PIN_SETFUNC = 0x80603d07 + PTP_PIN_SETFUNC2 = 0x80603d10 + PTP_SYS_OFFSET = 0x83403d05 + PTP_SYS_OFFSET2 = 0x83403d0e PTRACE_GETFPREGS = 0xe PTRACE_GET_THREAD_AREA = 0x19 PTRACE_GET_THREAD_AREA_3264 = 0xc4 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go index ee9456b0d..6d9cbc3b2 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go @@ -78,6 +78,8 @@ const ( ECHOPRT = 0x400 EFD_CLOEXEC = 0x80000 EFD_NONBLOCK = 0x80 + EPIOCGPARAMS = 0x40088a02 + EPIOCSPARAMS = 0x80088a01 EPOLL_CLOEXEC = 0x80000 EXTPROC = 0x10000 FF1 = 0x8000 @@ -148,9 +150,14 @@ const ( NFDBITS = 0x40 NLDLY = 0x100 NOFLSH = 0x80 + NS_GET_MNTNS_ID = 0x4008b705 NS_GET_NSTYPE = 0x2000b703 NS_GET_OWNER_UID = 0x2000b704 NS_GET_PARENT = 0x2000b702 + NS_GET_PID_FROM_PIDNS = 0x4004b706 + NS_GET_PID_IN_PIDNS = 0x4004b708 + NS_GET_TGID_FROM_PIDNS = 0x4004b707 + NS_GET_TGID_IN_PIDNS = 0x4004b709 NS_GET_USERNS = 0x2000b701 OLCUC = 0x2 ONLCR = 0x4 @@ -227,6 +234,20 @@ const ( PPPIOCUNBRIDGECHAN = 0x20007434 PPPIOCXFERUNIT = 0x2000744e PR_SET_PTRACER_ANY = 0xffffffffffffffff + PTP_CLOCK_GETCAPS = 0x40503d01 + PTP_CLOCK_GETCAPS2 = 0x40503d0a + PTP_ENABLE_PPS = 0x80043d04 + PTP_ENABLE_PPS2 = 0x80043d0d + PTP_EXTTS_REQUEST = 0x80103d02 + PTP_EXTTS_REQUEST2 = 0x80103d0b + PTP_MASK_CLEAR_ALL = 0x20003d13 + PTP_MASK_EN_SINGLE = 0x80043d14 + PTP_PEROUT_REQUEST = 0x80383d03 + PTP_PEROUT_REQUEST2 = 0x80383d0c + PTP_PIN_SETFUNC = 0x80603d07 + PTP_PIN_SETFUNC2 = 0x80603d10 + PTP_SYS_OFFSET = 0x83403d05 + PTP_SYS_OFFSET2 = 0x83403d0e PTRACE_GETFPREGS = 0xe PTRACE_GET_THREAD_AREA = 0x19 PTRACE_GET_THREAD_AREA_3264 = 0xc4 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go b/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go index 8cfca81e1..5f9fedbce 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go @@ -78,6 +78,8 @@ const ( ECHOPRT = 0x400 EFD_CLOEXEC = 0x80000 EFD_NONBLOCK = 0x80 + EPIOCGPARAMS = 0x40088a02 + EPIOCSPARAMS = 0x80088a01 EPOLL_CLOEXEC = 0x80000 EXTPROC = 0x10000 FF1 = 0x8000 @@ -148,9 +150,14 @@ const ( NFDBITS = 0x20 NLDLY = 0x100 NOFLSH = 0x80 + NS_GET_MNTNS_ID = 0x4008b705 NS_GET_NSTYPE = 0x2000b703 NS_GET_OWNER_UID = 0x2000b704 NS_GET_PARENT = 0x2000b702 + NS_GET_PID_FROM_PIDNS = 0x4004b706 + NS_GET_PID_IN_PIDNS = 0x4004b708 + NS_GET_TGID_FROM_PIDNS = 0x4004b707 + NS_GET_TGID_IN_PIDNS = 0x4004b709 NS_GET_USERNS = 0x2000b701 OLCUC = 0x2 ONLCR = 0x4 @@ -227,6 +234,20 @@ const ( PPPIOCUNBRIDGECHAN = 0x20007434 PPPIOCXFERUNIT = 0x2000744e PR_SET_PTRACER_ANY = 0xffffffff + PTP_CLOCK_GETCAPS = 0x40503d01 + PTP_CLOCK_GETCAPS2 = 0x40503d0a + PTP_ENABLE_PPS = 0x80043d04 + PTP_ENABLE_PPS2 = 0x80043d0d + PTP_EXTTS_REQUEST = 0x80103d02 + PTP_EXTTS_REQUEST2 = 0x80103d0b + PTP_MASK_CLEAR_ALL = 0x20003d13 + PTP_MASK_EN_SINGLE = 0x80043d14 + PTP_PEROUT_REQUEST = 0x80383d03 + PTP_PEROUT_REQUEST2 = 0x80383d0c + PTP_PIN_SETFUNC = 0x80603d07 + PTP_PIN_SETFUNC2 = 0x80603d10 + PTP_SYS_OFFSET = 0x83403d05 + PTP_SYS_OFFSET2 = 0x83403d0e PTRACE_GETFPREGS = 0xe PTRACE_GET_THREAD_AREA = 0x19 PTRACE_GET_THREAD_AREA_3264 = 0xc4 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go index 60b0deb3a..bb0026ee0 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go @@ -78,6 +78,8 @@ const ( ECHOPRT = 0x20 EFD_CLOEXEC = 0x80000 EFD_NONBLOCK = 0x800 + EPIOCGPARAMS = 0x40088a02 + EPIOCSPARAMS = 0x80088a01 EPOLL_CLOEXEC = 0x80000 EXTPROC = 0x10000000 FF1 = 0x4000 @@ -150,9 +152,14 @@ const ( NL3 = 0x300 NLDLY = 0x300 NOFLSH = 0x80000000 + NS_GET_MNTNS_ID = 0x4008b705 NS_GET_NSTYPE = 0x2000b703 NS_GET_OWNER_UID = 0x2000b704 NS_GET_PARENT = 0x2000b702 + NS_GET_PID_FROM_PIDNS = 0x4004b706 + NS_GET_PID_IN_PIDNS = 0x4004b708 + NS_GET_TGID_FROM_PIDNS = 0x4004b707 + NS_GET_TGID_IN_PIDNS = 0x4004b709 NS_GET_USERNS = 0x2000b701 OLCUC = 0x4 ONLCR = 0x2 @@ -230,6 +237,20 @@ const ( PPPIOCXFERUNIT = 0x2000744e PROT_SAO = 0x10 PR_SET_PTRACER_ANY = 0xffffffff + PTP_CLOCK_GETCAPS = 0x40503d01 + PTP_CLOCK_GETCAPS2 = 0x40503d0a + PTP_ENABLE_PPS = 0x80043d04 + PTP_ENABLE_PPS2 = 0x80043d0d + PTP_EXTTS_REQUEST = 0x80103d02 + PTP_EXTTS_REQUEST2 = 0x80103d0b + PTP_MASK_CLEAR_ALL = 0x20003d13 + PTP_MASK_EN_SINGLE = 0x80043d14 + PTP_PEROUT_REQUEST = 0x80383d03 + PTP_PEROUT_REQUEST2 = 0x80383d0c + PTP_PIN_SETFUNC = 0x80603d07 + PTP_PIN_SETFUNC2 = 0x80603d10 + PTP_SYS_OFFSET = 0x83403d05 + PTP_SYS_OFFSET2 = 0x83403d0e PTRACE_GETEVRREGS = 0x14 PTRACE_GETFPREGS = 0xe PTRACE_GETREGS64 = 0x16 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go index f90aa7281..46120db5c 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go @@ -78,6 +78,8 @@ const ( ECHOPRT = 0x20 EFD_CLOEXEC = 0x80000 EFD_NONBLOCK = 0x800 + EPIOCGPARAMS = 0x40088a02 + EPIOCSPARAMS = 0x80088a01 EPOLL_CLOEXEC = 0x80000 EXTPROC = 0x10000000 FF1 = 0x4000 @@ -150,9 +152,14 @@ const ( NL3 = 0x300 NLDLY = 0x300 NOFLSH = 0x80000000 + NS_GET_MNTNS_ID = 0x4008b705 NS_GET_NSTYPE = 0x2000b703 NS_GET_OWNER_UID = 0x2000b704 NS_GET_PARENT = 0x2000b702 + NS_GET_PID_FROM_PIDNS = 0x4004b706 + NS_GET_PID_IN_PIDNS = 0x4004b708 + NS_GET_TGID_FROM_PIDNS = 0x4004b707 + NS_GET_TGID_IN_PIDNS = 0x4004b709 NS_GET_USERNS = 0x2000b701 OLCUC = 0x4 ONLCR = 0x2 @@ -230,6 +237,20 @@ const ( PPPIOCXFERUNIT = 0x2000744e PROT_SAO = 0x10 PR_SET_PTRACER_ANY = 0xffffffffffffffff + PTP_CLOCK_GETCAPS = 0x40503d01 + PTP_CLOCK_GETCAPS2 = 0x40503d0a + PTP_ENABLE_PPS = 0x80043d04 + PTP_ENABLE_PPS2 = 0x80043d0d + PTP_EXTTS_REQUEST = 0x80103d02 + PTP_EXTTS_REQUEST2 = 0x80103d0b + PTP_MASK_CLEAR_ALL = 0x20003d13 + PTP_MASK_EN_SINGLE = 0x80043d14 + PTP_PEROUT_REQUEST = 0x80383d03 + PTP_PEROUT_REQUEST2 = 0x80383d0c + PTP_PIN_SETFUNC = 0x80603d07 + PTP_PIN_SETFUNC2 = 0x80603d10 + PTP_SYS_OFFSET = 0x83403d05 + PTP_SYS_OFFSET2 = 0x83403d0e PTRACE_GETEVRREGS = 0x14 PTRACE_GETFPREGS = 0xe PTRACE_GETREGS64 = 0x16 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go index ba9e01503..5c951634f 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go @@ -78,6 +78,8 @@ const ( ECHOPRT = 0x20 EFD_CLOEXEC = 0x80000 EFD_NONBLOCK = 0x800 + EPIOCGPARAMS = 0x40088a02 + EPIOCSPARAMS = 0x80088a01 EPOLL_CLOEXEC = 0x80000 EXTPROC = 0x10000000 FF1 = 0x4000 @@ -150,9 +152,14 @@ const ( NL3 = 0x300 NLDLY = 0x300 NOFLSH = 0x80000000 + NS_GET_MNTNS_ID = 0x4008b705 NS_GET_NSTYPE = 0x2000b703 NS_GET_OWNER_UID = 0x2000b704 NS_GET_PARENT = 0x2000b702 + NS_GET_PID_FROM_PIDNS = 0x4004b706 + NS_GET_PID_IN_PIDNS = 0x4004b708 + NS_GET_TGID_FROM_PIDNS = 0x4004b707 + NS_GET_TGID_IN_PIDNS = 0x4004b709 NS_GET_USERNS = 0x2000b701 OLCUC = 0x4 ONLCR = 0x2 @@ -230,6 +237,20 @@ const ( PPPIOCXFERUNIT = 0x2000744e PROT_SAO = 0x10 PR_SET_PTRACER_ANY = 0xffffffffffffffff + PTP_CLOCK_GETCAPS = 0x40503d01 + PTP_CLOCK_GETCAPS2 = 0x40503d0a + PTP_ENABLE_PPS = 0x80043d04 + PTP_ENABLE_PPS2 = 0x80043d0d + PTP_EXTTS_REQUEST = 0x80103d02 + PTP_EXTTS_REQUEST2 = 0x80103d0b + PTP_MASK_CLEAR_ALL = 0x20003d13 + PTP_MASK_EN_SINGLE = 0x80043d14 + PTP_PEROUT_REQUEST = 0x80383d03 + PTP_PEROUT_REQUEST2 = 0x80383d0c + PTP_PIN_SETFUNC = 0x80603d07 + PTP_PIN_SETFUNC2 = 0x80603d10 + PTP_SYS_OFFSET = 0x83403d05 + PTP_SYS_OFFSET2 = 0x83403d0e PTRACE_GETEVRREGS = 0x14 PTRACE_GETFPREGS = 0xe PTRACE_GETREGS64 = 0x16 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go index 07cdfd6e9..11a84d5af 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go @@ -78,6 +78,8 @@ const ( ECHOPRT = 0x400 EFD_CLOEXEC = 0x80000 EFD_NONBLOCK = 0x800 + EPIOCGPARAMS = 0x80088a02 + EPIOCSPARAMS = 0x40088a01 EPOLL_CLOEXEC = 0x80000 EXTPROC = 0x10000 FF1 = 0x8000 @@ -148,9 +150,14 @@ const ( NFDBITS = 0x40 NLDLY = 0x100 NOFLSH = 0x80 + NS_GET_MNTNS_ID = 0x8008b705 NS_GET_NSTYPE = 0xb703 NS_GET_OWNER_UID = 0xb704 NS_GET_PARENT = 0xb702 + NS_GET_PID_FROM_PIDNS = 0x8004b706 + NS_GET_PID_IN_PIDNS = 0x8004b708 + NS_GET_TGID_FROM_PIDNS = 0x8004b707 + NS_GET_TGID_IN_PIDNS = 0x8004b709 NS_GET_USERNS = 0xb701 OLCUC = 0x2 ONLCR = 0x4 @@ -227,6 +234,20 @@ const ( PPPIOCUNBRIDGECHAN = 0x7434 PPPIOCXFERUNIT = 0x744e PR_SET_PTRACER_ANY = 0xffffffffffffffff + PTP_CLOCK_GETCAPS = 0x80503d01 + PTP_CLOCK_GETCAPS2 = 0x80503d0a + PTP_ENABLE_PPS = 0x40043d04 + PTP_ENABLE_PPS2 = 0x40043d0d + PTP_EXTTS_REQUEST = 0x40103d02 + PTP_EXTTS_REQUEST2 = 0x40103d0b + PTP_MASK_CLEAR_ALL = 0x3d13 + PTP_MASK_EN_SINGLE = 0x40043d14 + PTP_PEROUT_REQUEST = 0x40383d03 + PTP_PEROUT_REQUEST2 = 0x40383d0c + PTP_PIN_SETFUNC = 0x40603d07 + PTP_PIN_SETFUNC2 = 0x40603d10 + PTP_SYS_OFFSET = 0x43403d05 + PTP_SYS_OFFSET2 = 0x43403d0e PTRACE_GETFDPIC = 0x21 PTRACE_GETFDPIC_EXEC = 0x0 PTRACE_GETFDPIC_INTERP = 0x1 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go b/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go index 2f1dd214a..f78c4617c 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go @@ -78,6 +78,8 @@ const ( ECHOPRT = 0x400 EFD_CLOEXEC = 0x80000 EFD_NONBLOCK = 0x800 + EPIOCGPARAMS = 0x80088a02 + EPIOCSPARAMS = 0x40088a01 EPOLL_CLOEXEC = 0x80000 EXTPROC = 0x10000 FF1 = 0x8000 @@ -148,9 +150,14 @@ const ( NFDBITS = 0x40 NLDLY = 0x100 NOFLSH = 0x80 + NS_GET_MNTNS_ID = 0x8008b705 NS_GET_NSTYPE = 0xb703 NS_GET_OWNER_UID = 0xb704 NS_GET_PARENT = 0xb702 + NS_GET_PID_FROM_PIDNS = 0x8004b706 + NS_GET_PID_IN_PIDNS = 0x8004b708 + NS_GET_TGID_FROM_PIDNS = 0x8004b707 + NS_GET_TGID_IN_PIDNS = 0x8004b709 NS_GET_USERNS = 0xb701 OLCUC = 0x2 ONLCR = 0x4 @@ -227,6 +234,20 @@ const ( PPPIOCUNBRIDGECHAN = 0x7434 PPPIOCXFERUNIT = 0x744e PR_SET_PTRACER_ANY = 0xffffffffffffffff + PTP_CLOCK_GETCAPS = 0x80503d01 + PTP_CLOCK_GETCAPS2 = 0x80503d0a + PTP_ENABLE_PPS = 0x40043d04 + PTP_ENABLE_PPS2 = 0x40043d0d + PTP_EXTTS_REQUEST = 0x40103d02 + PTP_EXTTS_REQUEST2 = 0x40103d0b + PTP_MASK_CLEAR_ALL = 0x3d13 + PTP_MASK_EN_SINGLE = 0x40043d14 + PTP_PEROUT_REQUEST = 0x40383d03 + PTP_PEROUT_REQUEST2 = 0x40383d0c + PTP_PIN_SETFUNC = 0x40603d07 + PTP_PIN_SETFUNC2 = 0x40603d10 + PTP_SYS_OFFSET = 0x43403d05 + PTP_SYS_OFFSET2 = 0x43403d0e PTRACE_DISABLE_TE = 0x5010 PTRACE_ENABLE_TE = 0x5009 PTRACE_GET_LAST_BREAK = 0x5006 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go index f40519d90..aeb777c34 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go @@ -82,6 +82,8 @@ const ( EFD_CLOEXEC = 0x400000 EFD_NONBLOCK = 0x4000 EMT_TAGOVF = 0x1 + EPIOCGPARAMS = 0x40088a02 + EPIOCSPARAMS = 0x80088a01 EPOLL_CLOEXEC = 0x400000 EXTPROC = 0x10000 FF1 = 0x8000 @@ -153,9 +155,14 @@ const ( NFDBITS = 0x40 NLDLY = 0x100 NOFLSH = 0x80 + NS_GET_MNTNS_ID = 0x4008b705 NS_GET_NSTYPE = 0x2000b703 NS_GET_OWNER_UID = 0x2000b704 NS_GET_PARENT = 0x2000b702 + NS_GET_PID_FROM_PIDNS = 0x4004b706 + NS_GET_PID_IN_PIDNS = 0x4004b708 + NS_GET_TGID_FROM_PIDNS = 0x4004b707 + NS_GET_TGID_IN_PIDNS = 0x4004b709 NS_GET_USERNS = 0x2000b701 OLCUC = 0x2 ONLCR = 0x4 @@ -232,6 +239,20 @@ const ( PPPIOCUNBRIDGECHAN = 0x20007434 PPPIOCXFERUNIT = 0x2000744e PR_SET_PTRACER_ANY = 0xffffffffffffffff + PTP_CLOCK_GETCAPS = 0x40503d01 + PTP_CLOCK_GETCAPS2 = 0x40503d0a + PTP_ENABLE_PPS = 0x80043d04 + PTP_ENABLE_PPS2 = 0x80043d0d + PTP_EXTTS_REQUEST = 0x80103d02 + PTP_EXTTS_REQUEST2 = 0x80103d0b + PTP_MASK_CLEAR_ALL = 0x20003d13 + PTP_MASK_EN_SINGLE = 0x80043d14 + PTP_PEROUT_REQUEST = 0x80383d03 + PTP_PEROUT_REQUEST2 = 0x80383d0c + PTP_PIN_SETFUNC = 0x80603d07 + PTP_PIN_SETFUNC2 = 0x80603d10 + PTP_SYS_OFFSET = 0x83403d05 + PTP_SYS_OFFSET2 = 0x83403d0e PTRACE_GETFPAREGS = 0x14 PTRACE_GETFPREGS = 0xe PTRACE_GETFPREGS64 = 0x19 diff --git a/vendor/golang.org/x/sys/unix/zerrors_zos_s390x.go b/vendor/golang.org/x/sys/unix/zerrors_zos_s390x.go index 4dfd2e051..1ec2b1407 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_zos_s390x.go +++ b/vendor/golang.org/x/sys/unix/zerrors_zos_s390x.go @@ -10,41 +10,99 @@ package unix const ( - BRKINT = 0x0001 - CLOCK_MONOTONIC = 0x1 - CLOCK_PROCESS_CPUTIME_ID = 0x2 - CLOCK_REALTIME = 0x0 - CLOCK_THREAD_CPUTIME_ID = 0x3 - CS8 = 0x0030 - CSIZE = 0x0030 - ECHO = 0x00000008 - ECHONL = 0x00000001 - FD_CLOEXEC = 0x01 - FD_CLOFORK = 0x02 - FNDELAY = 0x04 - F_CLOSFD = 9 - F_CONTROL_CVT = 13 - F_DUPFD = 0 - F_DUPFD2 = 8 - F_GETFD = 1 - F_GETFL = 259 - F_GETLK = 5 - F_GETOWN = 10 - F_OK = 0x0 - F_RDLCK = 1 - F_SETFD = 2 - F_SETFL = 4 - F_SETLK = 6 - F_SETLKW = 7 - F_SETOWN = 11 - F_SETTAG = 12 - F_UNLCK = 3 - F_WRLCK = 2 - FSTYPE_ZFS = 0xe9 //"Z" - FSTYPE_HFS = 0xc8 //"H" - FSTYPE_NFS = 0xd5 //"N" - FSTYPE_TFS = 0xe3 //"T" - FSTYPE_AUTOMOUNT = 0xc1 //"A" + BRKINT = 0x0001 + CLOCAL = 0x1 + CLOCK_MONOTONIC = 0x1 + CLOCK_PROCESS_CPUTIME_ID = 0x2 + CLOCK_REALTIME = 0x0 + CLOCK_THREAD_CPUTIME_ID = 0x3 + CLONE_NEWIPC = 0x08000000 + CLONE_NEWNET = 0x40000000 + CLONE_NEWNS = 0x00020000 + CLONE_NEWPID = 0x20000000 + CLONE_NEWUTS = 0x04000000 + CLONE_PARENT = 0x00008000 + CS8 = 0x0030 + CSIZE = 0x0030 + ECHO = 0x00000008 + ECHONL = 0x00000001 + EFD_SEMAPHORE = 0x00002000 + EFD_CLOEXEC = 0x00001000 + EFD_NONBLOCK = 0x00000004 + EPOLL_CLOEXEC = 0x00001000 + EPOLL_CTL_ADD = 0 + EPOLL_CTL_MOD = 1 + EPOLL_CTL_DEL = 2 + EPOLLRDNORM = 0x0001 + EPOLLRDBAND = 0x0002 + EPOLLIN = 0x0003 + EPOLLOUT = 0x0004 + EPOLLWRBAND = 0x0008 + EPOLLPRI = 0x0010 + EPOLLERR = 0x0020 + EPOLLHUP = 0x0040 + EPOLLEXCLUSIVE = 0x20000000 + EPOLLONESHOT = 0x40000000 + FD_CLOEXEC = 0x01 + FD_CLOFORK = 0x02 + FD_SETSIZE = 0x800 + FNDELAY = 0x04 + F_CLOSFD = 9 + F_CONTROL_CVT = 13 + F_DUPFD = 0 + F_DUPFD2 = 8 + F_GETFD = 1 + F_GETFL = 259 + F_GETLK = 5 + F_GETOWN = 10 + F_OK = 0x0 + F_RDLCK = 1 + F_SETFD = 2 + F_SETFL = 4 + F_SETLK = 6 + F_SETLKW = 7 + F_SETOWN = 11 + F_SETTAG = 12 + F_UNLCK = 3 + F_WRLCK = 2 + FSTYPE_ZFS = 0xe9 //"Z" + FSTYPE_HFS = 0xc8 //"H" + FSTYPE_NFS = 0xd5 //"N" + FSTYPE_TFS = 0xe3 //"T" + FSTYPE_AUTOMOUNT = 0xc1 //"A" + GRND_NONBLOCK = 1 + GRND_RANDOM = 2 + HUPCL = 0x0100 // Hang up on last close + IN_CLOEXEC = 0x00001000 + IN_NONBLOCK = 0x00000004 + IN_ACCESS = 0x00000001 + IN_MODIFY = 0x00000002 + IN_ATTRIB = 0x00000004 + IN_CLOSE_WRITE = 0x00000008 + IN_CLOSE_NOWRITE = 0x00000010 + IN_OPEN = 0x00000020 + IN_MOVED_FROM = 0x00000040 + IN_MOVED_TO = 0x00000080 + IN_CREATE = 0x00000100 + IN_DELETE = 0x00000200 + IN_DELETE_SELF = 0x00000400 + IN_MOVE_SELF = 0x00000800 + IN_UNMOUNT = 0x00002000 + IN_Q_OVERFLOW = 0x00004000 + IN_IGNORED = 0x00008000 + IN_CLOSE = (IN_CLOSE_WRITE | IN_CLOSE_NOWRITE) + IN_MOVE = (IN_MOVED_FROM | IN_MOVED_TO) + IN_ALL_EVENTS = (IN_ACCESS | IN_MODIFY | IN_ATTRIB | + IN_CLOSE | IN_OPEN | IN_MOVE | + IN_CREATE | IN_DELETE | IN_DELETE_SELF | + IN_MOVE_SELF) + IN_ONLYDIR = 0x01000000 + IN_DONT_FOLLOW = 0x02000000 + IN_EXCL_UNLINK = 0x04000000 + IN_MASK_CREATE = 0x10000000 + IN_MASK_ADD = 0x20000000 + IN_ISDIR = 0x40000000 + IN_ONESHOT = 0x80000000 IP6F_MORE_FRAG = 0x0001 IP6F_OFF_MASK = 0xfff8 IP6F_RESERVED_MASK = 0x0006 @@ -152,10 +210,18 @@ const ( IP_PKTINFO = 101 IP_RECVPKTINFO = 102 IP_TOS = 2 - IP_TTL = 3 + IP_TTL = 14 IP_UNBLOCK_SOURCE = 11 + ICMP6_FILTER = 1 + MCAST_INCLUDE = 0 + MCAST_EXCLUDE = 1 + MCAST_JOIN_GROUP = 40 + MCAST_LEAVE_GROUP = 41 + MCAST_JOIN_SOURCE_GROUP = 42 + MCAST_LEAVE_SOURCE_GROUP = 43 + MCAST_BLOCK_SOURCE = 44 + MCAST_UNBLOCK_SOURCE = 46 ICANON = 0x0010 - ICMP6_FILTER = 0x26 ICRNL = 0x0002 IEXTEN = 0x0020 IGNBRK = 0x0004 @@ -165,10 +231,10 @@ const ( ISTRIP = 0x0080 IXON = 0x0200 IXOFF = 0x0100 - LOCK_SH = 0x1 // Not exist on zOS - LOCK_EX = 0x2 // Not exist on zOS - LOCK_NB = 0x4 // Not exist on zOS - LOCK_UN = 0x8 // Not exist on zOS + LOCK_SH = 0x1 + LOCK_EX = 0x2 + LOCK_NB = 0x4 + LOCK_UN = 0x8 POLLIN = 0x0003 POLLOUT = 0x0004 POLLPRI = 0x0010 @@ -182,15 +248,29 @@ const ( MAP_PRIVATE = 0x1 // changes are private MAP_SHARED = 0x2 // changes are shared MAP_FIXED = 0x4 // place exactly - MCAST_JOIN_GROUP = 40 - MCAST_LEAVE_GROUP = 41 - MCAST_JOIN_SOURCE_GROUP = 42 - MCAST_LEAVE_SOURCE_GROUP = 43 - MCAST_BLOCK_SOURCE = 44 - MCAST_UNBLOCK_SOURCE = 45 + __MAP_MEGA = 0x8 + __MAP_64 = 0x10 + MAP_ANON = 0x20 + MAP_ANONYMOUS = 0x20 MS_SYNC = 0x1 // msync - synchronous writes MS_ASYNC = 0x2 // asynchronous writes MS_INVALIDATE = 0x4 // invalidate mappings + MS_BIND = 0x00001000 + MS_MOVE = 0x00002000 + MS_NOSUID = 0x00000002 + MS_PRIVATE = 0x00040000 + MS_REC = 0x00004000 + MS_REMOUNT = 0x00008000 + MS_RDONLY = 0x00000001 + MS_UNBINDABLE = 0x00020000 + MNT_DETACH = 0x00000004 + ZOSDSFS_SUPER_MAGIC = 0x44534653 // zOS DSFS + NFS_SUPER_MAGIC = 0x6969 // NFS + NSFS_MAGIC = 0x6e736673 // PROCNS + PROC_SUPER_MAGIC = 0x9fa0 // proc FS + ZOSTFS_SUPER_MAGIC = 0x544653 // zOS TFS + ZOSUFS_SUPER_MAGIC = 0x554653 // zOS UFS + ZOSZFS_SUPER_MAGIC = 0x5A4653 // zOS ZFS MTM_RDONLY = 0x80000000 MTM_RDWR = 0x40000000 MTM_UMOUNT = 0x10000000 @@ -205,13 +285,20 @@ const ( MTM_REMOUNT = 0x00000100 MTM_NOSECURITY = 0x00000080 NFDBITS = 0x20 + ONLRET = 0x0020 // NL performs CR function O_ACCMODE = 0x03 O_APPEND = 0x08 O_ASYNCSIG = 0x0200 O_CREAT = 0x80 + O_DIRECT = 0x00002000 + O_NOFOLLOW = 0x00004000 + O_DIRECTORY = 0x00008000 + O_PATH = 0x00080000 + O_CLOEXEC = 0x00001000 O_EXCL = 0x40 O_GETFL = 0x0F O_LARGEFILE = 0x0400 + O_NDELAY = 0x4 O_NONBLOCK = 0x04 O_RDONLY = 0x02 O_RDWR = 0x03 @@ -248,6 +335,7 @@ const ( AF_IUCV = 17 AF_LAT = 14 AF_LINK = 18 + AF_LOCAL = AF_UNIX // AF_LOCAL is an alias for AF_UNIX AF_MAX = 30 AF_NBS = 7 AF_NDD = 23 @@ -285,15 +373,33 @@ const ( RLIMIT_AS = 5 RLIMIT_NOFILE = 6 RLIMIT_MEMLIMIT = 7 + RLIMIT_MEMLOCK = 0x8 RLIM_INFINITY = 2147483647 + SCHED_FIFO = 0x2 + SCM_CREDENTIALS = 0x2 SCM_RIGHTS = 0x01 SF_CLOSE = 0x00000002 SF_REUSE = 0x00000001 + SHM_RND = 0x2 + SHM_RDONLY = 0x1 + SHMLBA = 0x1000 + IPC_STAT = 0x3 + IPC_SET = 0x2 + IPC_RMID = 0x1 + IPC_PRIVATE = 0x0 + IPC_CREAT = 0x1000000 + __IPC_MEGA = 0x4000000 + __IPC_SHAREAS = 0x20000000 + __IPC_BELOWBAR = 0x10000000 + IPC_EXCL = 0x2000000 + __IPC_GIGA = 0x8000000 SHUT_RD = 0 SHUT_RDWR = 2 SHUT_WR = 1 + SOCK_CLOEXEC = 0x00001000 SOCK_CONN_DGRAM = 6 SOCK_DGRAM = 2 + SOCK_NONBLOCK = 0x800 SOCK_RAW = 3 SOCK_RDM = 4 SOCK_SEQPACKET = 5 @@ -378,8 +484,6 @@ const ( S_IFMST = 0x00FF0000 TCP_KEEPALIVE = 0x8 TCP_NODELAY = 0x1 - TCP_INFO = 0xb - TCP_USER_TIMEOUT = 0x1 TIOCGWINSZ = 0x4008a368 TIOCSWINSZ = 0x8008a367 TIOCSBRK = 0x2000a77b @@ -427,7 +531,10 @@ const ( VSUSP = 9 VTIME = 10 WCONTINUED = 0x4 + WEXITED = 0x8 WNOHANG = 0x1 + WNOWAIT = 0x20 + WSTOPPED = 0x10 WUNTRACED = 0x2 _BPX_SWAP = 1 _BPX_NONSWAP = 2 @@ -452,8 +559,30 @@ const ( MADV_FREE = 15 // for Linux compatibility -- no zos semantics MADV_WIPEONFORK = 16 // for Linux compatibility -- no zos semantics MADV_KEEPONFORK = 17 // for Linux compatibility -- no zos semantics - AT_SYMLINK_NOFOLLOW = 1 // for Unix compatibility -- no zos semantics - AT_FDCWD = 2 // for Unix compatibility -- no zos semantics + AT_SYMLINK_FOLLOW = 0x400 + AT_SYMLINK_NOFOLLOW = 0x100 + XATTR_CREATE = 0x1 + XATTR_REPLACE = 0x2 + P_PID = 0 + P_PGID = 1 + P_ALL = 2 + PR_SET_NAME = 15 + PR_GET_NAME = 16 + PR_SET_NO_NEW_PRIVS = 38 + PR_GET_NO_NEW_PRIVS = 39 + PR_SET_DUMPABLE = 4 + PR_GET_DUMPABLE = 3 + PR_SET_PDEATHSIG = 1 + PR_GET_PDEATHSIG = 2 + PR_SET_CHILD_SUBREAPER = 36 + PR_GET_CHILD_SUBREAPER = 37 + AT_FDCWD = -100 + AT_EACCESS = 0x200 + AT_EMPTY_PATH = 0x1000 + AT_REMOVEDIR = 0x200 + RENAME_NOREPLACE = 1 << 0 + ST_RDONLY = 1 + ST_NOSUID = 2 ) const ( @@ -476,6 +605,7 @@ const ( EMLINK = Errno(125) ENAMETOOLONG = Errno(126) ENFILE = Errno(127) + ENOATTR = Errno(265) ENODEV = Errno(128) ENOENT = Errno(129) ENOEXEC = Errno(130) @@ -700,7 +830,7 @@ var errorList = [...]struct { {145, "EDC5145I", "The parameter list is too long, or the message to receive was too large for the buffer."}, {146, "EDC5146I", "Too many levels of symbolic links."}, {147, "EDC5147I", "Illegal byte sequence."}, - {148, "", ""}, + {148, "EDC5148I", "The named attribute or data not available."}, {149, "EDC5149I", "Value Overflow Error."}, {150, "EDC5150I", "UNIX System Services is not active."}, {151, "EDC5151I", "Dynamic allocation error."}, @@ -743,6 +873,7 @@ var errorList = [...]struct { {259, "EDC5259I", "A CUN_RS_NO_CONVERSION error was issued by Unicode Services."}, {260, "EDC5260I", "A CUN_RS_TABLE_NOT_ALIGNED error was issued by Unicode Services."}, {262, "EDC5262I", "An iconv() function encountered an unexpected error while using Unicode Services."}, + {265, "EDC5265I", "The named attribute not available."}, {1000, "EDC8000I", "A bad socket-call constant was found in the IUCV header."}, {1001, "EDC8001I", "An error was found in the IUCV header."}, {1002, "EDC8002I", "A socket descriptor is out of range."}, diff --git a/vendor/golang.org/x/sys/unix/zsymaddr_zos_s390x.s b/vendor/golang.org/x/sys/unix/zsymaddr_zos_s390x.s new file mode 100644 index 000000000..b77ff5db9 --- /dev/null +++ b/vendor/golang.org/x/sys/unix/zsymaddr_zos_s390x.s @@ -0,0 +1,364 @@ +// go run mksyscall_zos_s390x.go -o_sysnum zsysnum_zos_s390x.go -o_syscall zsyscall_zos_s390x.go -i_syscall syscall_zos_s390x.go -o_asm zsymaddr_zos_s390x.s +// Code generated by the command above; see README.md. DO NOT EDIT. + +//go:build zos && s390x +#include "textflag.h" + +// provide the address of function variable to be fixed up. + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_FlistxattrAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Flistxattr(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_FremovexattrAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Fremovexattr(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_FgetxattrAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Fgetxattr(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_FsetxattrAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Fsetxattr(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_accept4Addr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·accept4(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_RemovexattrAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Removexattr(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_Dup3Addr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Dup3(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_DirfdAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Dirfd(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_EpollCreateAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·EpollCreate(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_EpollCreate1Addr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·EpollCreate1(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_EpollCtlAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·EpollCtl(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_EpollPwaitAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·EpollPwait(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_EpollWaitAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·EpollWait(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_EventfdAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Eventfd(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_FaccessatAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Faccessat(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_FchmodatAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Fchmodat(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_FchownatAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Fchownat(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_FdatasyncAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Fdatasync(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_fstatatAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·fstatat(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_LgetxattrAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Lgetxattr(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_LsetxattrAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Lsetxattr(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_FstatfsAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Fstatfs(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_FutimesAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Futimes(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_FutimesatAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Futimesat(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_GetrandomAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Getrandom(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_InotifyInitAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·InotifyInit(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_InotifyInit1Addr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·InotifyInit1(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_InotifyAddWatchAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·InotifyAddWatch(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_InotifyRmWatchAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·InotifyRmWatch(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_ListxattrAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Listxattr(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_LlistxattrAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Llistxattr(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_LremovexattrAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Lremovexattr(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_LutimesAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Lutimes(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_StatfsAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Statfs(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_SyncfsAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Syncfs(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_UnshareAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Unshare(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_LinkatAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Linkat(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_MkdiratAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Mkdirat(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_MknodatAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Mknodat(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_PivotRootAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·PivotRoot(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_PrctlAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Prctl(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_PrlimitAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Prlimit(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_RenameatAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Renameat(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_Renameat2Addr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Renameat2(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_SethostnameAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Sethostname(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_SetnsAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Setns(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_SymlinkatAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Symlinkat(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_UnlinkatAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Unlinkat(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_openatAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·openat(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_openat2Addr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·openat2(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_utimensatAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·utimensat(SB), R8 + MOVD R8, ret+0(FP) + RET diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go b/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go index ccb02f240..24b346e1a 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go @@ -740,6 +740,54 @@ func ioctlPtr(fd int, req uint, arg unsafe.Pointer) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func renamexNp(from string, to string, flag uint32) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(from) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(to) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_renamex_np_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(flag)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_renamex_np_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_renamex_np renamex_np "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func renameatxNp(fromfd int, from string, tofd int, to string, flag uint32) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(from) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(to) + if err != nil { + return + } + _, _, e1 := syscall_syscall6(libc_renameatx_np_trampoline_addr, uintptr(fromfd), uintptr(unsafe.Pointer(_p0)), uintptr(tofd), uintptr(unsafe.Pointer(_p1)), uintptr(flag), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_renameatx_np_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_renameatx_np renameatx_np "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { var _p0 unsafe.Pointer if len(mib) > 0 { @@ -760,6 +808,59 @@ var libc_sysctl_trampoline_addr uintptr // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func pthread_chdir_np(path string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_pthread_chdir_np_trampoline_addr, uintptr(unsafe.Pointer(_p0)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_pthread_chdir_np_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pthread_chdir_np pthread_chdir_np "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func pthread_fchdir_np(fd int) (err error) { + _, _, e1 := syscall_syscall(libc_pthread_fchdir_np_trampoline_addr, uintptr(fd), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_pthread_fchdir_np_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pthread_fchdir_np pthread_fchdir_np "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func connectx(fd int, endpoints *SaEndpoints, associd SaeAssocID, flags uint32, iov []Iovec, n *uintptr, connid *SaeConnID) (err error) { + var _p0 unsafe.Pointer + if len(iov) > 0 { + _p0 = unsafe.Pointer(&iov[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := syscall_syscall9(libc_connectx_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(endpoints)), uintptr(associd), uintptr(flags), uintptr(_p0), uintptr(len(iov)), uintptr(unsafe.Pointer(n)), uintptr(unsafe.Pointer(connid)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_connectx_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_connectx connectx "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func sendfile(infd int, outfd int, offset int64, len *int64, hdtr unsafe.Pointer, flags int) (err error) { _, _, e1 := syscall_syscall6(libc_sendfile_trampoline_addr, uintptr(infd), uintptr(outfd), uintptr(offset), uintptr(unsafe.Pointer(len)), uintptr(hdtr), uintptr(flags)) if e1 != 0 { diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.s b/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.s index 8b8bb2840..ebd213100 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.s +++ b/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.s @@ -223,11 +223,36 @@ TEXT libc_ioctl_trampoline<>(SB),NOSPLIT,$0-0 GLOBL ·libc_ioctl_trampoline_addr(SB), RODATA, $8 DATA ·libc_ioctl_trampoline_addr(SB)/8, $libc_ioctl_trampoline<>(SB) +TEXT libc_renamex_np_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_renamex_np(SB) +GLOBL ·libc_renamex_np_trampoline_addr(SB), RODATA, $8 +DATA ·libc_renamex_np_trampoline_addr(SB)/8, $libc_renamex_np_trampoline<>(SB) + +TEXT libc_renameatx_np_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_renameatx_np(SB) +GLOBL ·libc_renameatx_np_trampoline_addr(SB), RODATA, $8 +DATA ·libc_renameatx_np_trampoline_addr(SB)/8, $libc_renameatx_np_trampoline<>(SB) + TEXT libc_sysctl_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_sysctl(SB) GLOBL ·libc_sysctl_trampoline_addr(SB), RODATA, $8 DATA ·libc_sysctl_trampoline_addr(SB)/8, $libc_sysctl_trampoline<>(SB) +TEXT libc_pthread_chdir_np_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_pthread_chdir_np(SB) +GLOBL ·libc_pthread_chdir_np_trampoline_addr(SB), RODATA, $8 +DATA ·libc_pthread_chdir_np_trampoline_addr(SB)/8, $libc_pthread_chdir_np_trampoline<>(SB) + +TEXT libc_pthread_fchdir_np_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_pthread_fchdir_np(SB) +GLOBL ·libc_pthread_fchdir_np_trampoline_addr(SB), RODATA, $8 +DATA ·libc_pthread_fchdir_np_trampoline_addr(SB)/8, $libc_pthread_fchdir_np_trampoline<>(SB) + +TEXT libc_connectx_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_connectx(SB) +GLOBL ·libc_connectx_trampoline_addr(SB), RODATA, $8 +DATA ·libc_connectx_trampoline_addr(SB)/8, $libc_connectx_trampoline<>(SB) + TEXT libc_sendfile_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_sendfile(SB) GLOBL ·libc_sendfile_trampoline_addr(SB), RODATA, $8 diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go b/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go index 1b40b997b..824b9c2d5 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go @@ -740,6 +740,54 @@ func ioctlPtr(fd int, req uint, arg unsafe.Pointer) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func renamexNp(from string, to string, flag uint32) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(from) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(to) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_renamex_np_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(flag)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_renamex_np_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_renamex_np renamex_np "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func renameatxNp(fromfd int, from string, tofd int, to string, flag uint32) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(from) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(to) + if err != nil { + return + } + _, _, e1 := syscall_syscall6(libc_renameatx_np_trampoline_addr, uintptr(fromfd), uintptr(unsafe.Pointer(_p0)), uintptr(tofd), uintptr(unsafe.Pointer(_p1)), uintptr(flag), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_renameatx_np_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_renameatx_np renameatx_np "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { var _p0 unsafe.Pointer if len(mib) > 0 { @@ -760,6 +808,59 @@ var libc_sysctl_trampoline_addr uintptr // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func pthread_chdir_np(path string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_pthread_chdir_np_trampoline_addr, uintptr(unsafe.Pointer(_p0)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_pthread_chdir_np_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pthread_chdir_np pthread_chdir_np "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func pthread_fchdir_np(fd int) (err error) { + _, _, e1 := syscall_syscall(libc_pthread_fchdir_np_trampoline_addr, uintptr(fd), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_pthread_fchdir_np_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pthread_fchdir_np pthread_fchdir_np "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func connectx(fd int, endpoints *SaEndpoints, associd SaeAssocID, flags uint32, iov []Iovec, n *uintptr, connid *SaeConnID) (err error) { + var _p0 unsafe.Pointer + if len(iov) > 0 { + _p0 = unsafe.Pointer(&iov[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := syscall_syscall9(libc_connectx_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(endpoints)), uintptr(associd), uintptr(flags), uintptr(_p0), uintptr(len(iov)), uintptr(unsafe.Pointer(n)), uintptr(unsafe.Pointer(connid)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_connectx_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_connectx connectx "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func sendfile(infd int, outfd int, offset int64, len *int64, hdtr unsafe.Pointer, flags int) (err error) { _, _, e1 := syscall_syscall6(libc_sendfile_trampoline_addr, uintptr(infd), uintptr(outfd), uintptr(offset), uintptr(unsafe.Pointer(len)), uintptr(hdtr), uintptr(flags)) if e1 != 0 { diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.s b/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.s index 08362c1ab..4f178a229 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.s +++ b/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.s @@ -223,11 +223,36 @@ TEXT libc_ioctl_trampoline<>(SB),NOSPLIT,$0-0 GLOBL ·libc_ioctl_trampoline_addr(SB), RODATA, $8 DATA ·libc_ioctl_trampoline_addr(SB)/8, $libc_ioctl_trampoline<>(SB) +TEXT libc_renamex_np_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_renamex_np(SB) +GLOBL ·libc_renamex_np_trampoline_addr(SB), RODATA, $8 +DATA ·libc_renamex_np_trampoline_addr(SB)/8, $libc_renamex_np_trampoline<>(SB) + +TEXT libc_renameatx_np_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_renameatx_np(SB) +GLOBL ·libc_renameatx_np_trampoline_addr(SB), RODATA, $8 +DATA ·libc_renameatx_np_trampoline_addr(SB)/8, $libc_renameatx_np_trampoline<>(SB) + TEXT libc_sysctl_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_sysctl(SB) GLOBL ·libc_sysctl_trampoline_addr(SB), RODATA, $8 DATA ·libc_sysctl_trampoline_addr(SB)/8, $libc_sysctl_trampoline<>(SB) +TEXT libc_pthread_chdir_np_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_pthread_chdir_np(SB) +GLOBL ·libc_pthread_chdir_np_trampoline_addr(SB), RODATA, $8 +DATA ·libc_pthread_chdir_np_trampoline_addr(SB)/8, $libc_pthread_chdir_np_trampoline<>(SB) + +TEXT libc_pthread_fchdir_np_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_pthread_fchdir_np(SB) +GLOBL ·libc_pthread_fchdir_np_trampoline_addr(SB), RODATA, $8 +DATA ·libc_pthread_fchdir_np_trampoline_addr(SB)/8, $libc_pthread_fchdir_np_trampoline<>(SB) + +TEXT libc_connectx_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_connectx(SB) +GLOBL ·libc_connectx_trampoline_addr(SB), RODATA, $8 +DATA ·libc_connectx_trampoline_addr(SB)/8, $libc_connectx_trampoline<>(SB) + TEXT libc_sendfile_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_sendfile(SB) GLOBL ·libc_sendfile_trampoline_addr(SB), RODATA, $8 diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux.go b/vendor/golang.org/x/sys/unix/zsyscall_linux.go index 87d8612a1..5cc1e8eb2 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux.go @@ -592,6 +592,16 @@ func ClockGettime(clockid int32, time *Timespec) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func ClockSettime(clockid int32, time *Timespec) (err error) { + _, _, e1 := Syscall(SYS_CLOCK_SETTIME, uintptr(clockid), uintptr(unsafe.Pointer(time)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func ClockNanosleep(clockid int32, flags int, request *Timespec, remain *Timespec) (err error) { _, _, e1 := Syscall6(SYS_CLOCK_NANOSLEEP, uintptr(clockid), uintptr(flags), uintptr(unsafe.Pointer(request)), uintptr(unsafe.Pointer(remain)), 0, 0) if e1 != 0 { @@ -971,23 +981,6 @@ func Getpriority(which int, who int) (prio int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Getrandom(buf []byte, flags int) (n int, err error) { - var _p0 unsafe.Pointer - if len(buf) > 0 { - _p0 = unsafe.Pointer(&buf[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - r0, _, e1 := Syscall(SYS_GETRANDOM, uintptr(_p0), uintptr(len(buf)), uintptr(flags)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Getrusage(who int, rusage *Rusage) (err error) { _, _, e1 := RawSyscall(SYS_GETRUSAGE, uintptr(who), uintptr(unsafe.Pointer(rusage)), 0) if e1 != 0 { @@ -2229,3 +2222,19 @@ func Cachestat(fd uint, crange *CachestatRange, cstat *Cachestat_t, flags uint) } return } + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Mseal(b []byte, flags uint) (err error) { + var _p0 unsafe.Pointer + if len(b) > 0 { + _p0 = unsafe.Pointer(&b[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := Syscall(SYS_MSEAL, uintptr(_p0), uintptr(len(b)), uintptr(flags)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.go b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.go index 9dc42410b..1851df14e 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.go @@ -1493,6 +1493,30 @@ var libc_mknodat_trampoline_addr uintptr // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Mount(fsType string, dir string, flags int, data unsafe.Pointer) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(fsType) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(dir) + if err != nil { + return + } + _, _, e1 := syscall_syscall6(libc_mount_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(flags), uintptr(data), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_mount_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mount mount "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Nanosleep(time *Timespec, leftover *Timespec) (err error) { _, _, e1 := syscall_syscall(libc_nanosleep_trampoline_addr, uintptr(unsafe.Pointer(time)), uintptr(unsafe.Pointer(leftover)), 0) if e1 != 0 { diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.s b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.s index 41b561731..0b43c6936 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.s +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.s @@ -463,6 +463,11 @@ TEXT libc_mknodat_trampoline<>(SB),NOSPLIT,$0-0 GLOBL ·libc_mknodat_trampoline_addr(SB), RODATA, $4 DATA ·libc_mknodat_trampoline_addr(SB)/4, $libc_mknodat_trampoline<>(SB) +TEXT libc_mount_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mount(SB) +GLOBL ·libc_mount_trampoline_addr(SB), RODATA, $4 +DATA ·libc_mount_trampoline_addr(SB)/4, $libc_mount_trampoline<>(SB) + TEXT libc_nanosleep_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_nanosleep(SB) GLOBL ·libc_nanosleep_trampoline_addr(SB), RODATA, $4 diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.go b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.go index 0d3a0751c..e1ec0dbe4 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.go @@ -1493,6 +1493,30 @@ var libc_mknodat_trampoline_addr uintptr // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Mount(fsType string, dir string, flags int, data unsafe.Pointer) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(fsType) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(dir) + if err != nil { + return + } + _, _, e1 := syscall_syscall6(libc_mount_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(flags), uintptr(data), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_mount_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mount mount "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Nanosleep(time *Timespec, leftover *Timespec) (err error) { _, _, e1 := syscall_syscall(libc_nanosleep_trampoline_addr, uintptr(unsafe.Pointer(time)), uintptr(unsafe.Pointer(leftover)), 0) if e1 != 0 { diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.s b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.s index 4019a656f..880c6d6e3 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.s +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.s @@ -463,6 +463,11 @@ TEXT libc_mknodat_trampoline<>(SB),NOSPLIT,$0-0 GLOBL ·libc_mknodat_trampoline_addr(SB), RODATA, $8 DATA ·libc_mknodat_trampoline_addr(SB)/8, $libc_mknodat_trampoline<>(SB) +TEXT libc_mount_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mount(SB) +GLOBL ·libc_mount_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mount_trampoline_addr(SB)/8, $libc_mount_trampoline<>(SB) + TEXT libc_nanosleep_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_nanosleep(SB) GLOBL ·libc_nanosleep_trampoline_addr(SB), RODATA, $8 diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.go b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.go index c39f7776d..7c8452a63 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.go @@ -1493,6 +1493,30 @@ var libc_mknodat_trampoline_addr uintptr // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Mount(fsType string, dir string, flags int, data unsafe.Pointer) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(fsType) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(dir) + if err != nil { + return + } + _, _, e1 := syscall_syscall6(libc_mount_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(flags), uintptr(data), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_mount_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mount mount "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Nanosleep(time *Timespec, leftover *Timespec) (err error) { _, _, e1 := syscall_syscall(libc_nanosleep_trampoline_addr, uintptr(unsafe.Pointer(time)), uintptr(unsafe.Pointer(leftover)), 0) if e1 != 0 { diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.s b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.s index ac4af24f9..b8ef95b0f 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.s +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.s @@ -463,6 +463,11 @@ TEXT libc_mknodat_trampoline<>(SB),NOSPLIT,$0-0 GLOBL ·libc_mknodat_trampoline_addr(SB), RODATA, $4 DATA ·libc_mknodat_trampoline_addr(SB)/4, $libc_mknodat_trampoline<>(SB) +TEXT libc_mount_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mount(SB) +GLOBL ·libc_mount_trampoline_addr(SB), RODATA, $4 +DATA ·libc_mount_trampoline_addr(SB)/4, $libc_mount_trampoline<>(SB) + TEXT libc_nanosleep_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_nanosleep(SB) GLOBL ·libc_nanosleep_trampoline_addr(SB), RODATA, $4 diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm64.go b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm64.go index 57571d072..2ffdf861f 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm64.go @@ -1493,6 +1493,30 @@ var libc_mknodat_trampoline_addr uintptr // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Mount(fsType string, dir string, flags int, data unsafe.Pointer) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(fsType) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(dir) + if err != nil { + return + } + _, _, e1 := syscall_syscall6(libc_mount_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(flags), uintptr(data), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_mount_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mount mount "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Nanosleep(time *Timespec, leftover *Timespec) (err error) { _, _, e1 := syscall_syscall(libc_nanosleep_trampoline_addr, uintptr(unsafe.Pointer(time)), uintptr(unsafe.Pointer(leftover)), 0) if e1 != 0 { diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm64.s b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm64.s index f77d53212..2af3b5c76 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm64.s +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm64.s @@ -463,6 +463,11 @@ TEXT libc_mknodat_trampoline<>(SB),NOSPLIT,$0-0 GLOBL ·libc_mknodat_trampoline_addr(SB), RODATA, $8 DATA ·libc_mknodat_trampoline_addr(SB)/8, $libc_mknodat_trampoline<>(SB) +TEXT libc_mount_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mount(SB) +GLOBL ·libc_mount_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mount_trampoline_addr(SB)/8, $libc_mount_trampoline<>(SB) + TEXT libc_nanosleep_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_nanosleep(SB) GLOBL ·libc_nanosleep_trampoline_addr(SB), RODATA, $8 diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_mips64.go b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_mips64.go index e62963e67..1da08d526 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_mips64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_mips64.go @@ -1493,6 +1493,30 @@ var libc_mknodat_trampoline_addr uintptr // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Mount(fsType string, dir string, flags int, data unsafe.Pointer) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(fsType) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(dir) + if err != nil { + return + } + _, _, e1 := syscall_syscall6(libc_mount_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(flags), uintptr(data), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_mount_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mount mount "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Nanosleep(time *Timespec, leftover *Timespec) (err error) { _, _, e1 := syscall_syscall(libc_nanosleep_trampoline_addr, uintptr(unsafe.Pointer(time)), uintptr(unsafe.Pointer(leftover)), 0) if e1 != 0 { diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_mips64.s b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_mips64.s index fae140b62..b7a251353 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_mips64.s +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_mips64.s @@ -463,6 +463,11 @@ TEXT libc_mknodat_trampoline<>(SB),NOSPLIT,$0-0 GLOBL ·libc_mknodat_trampoline_addr(SB), RODATA, $8 DATA ·libc_mknodat_trampoline_addr(SB)/8, $libc_mknodat_trampoline<>(SB) +TEXT libc_mount_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mount(SB) +GLOBL ·libc_mount_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mount_trampoline_addr(SB)/8, $libc_mount_trampoline<>(SB) + TEXT libc_nanosleep_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_nanosleep(SB) GLOBL ·libc_nanosleep_trampoline_addr(SB), RODATA, $8 diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_ppc64.go b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_ppc64.go index 00831354c..6e85b0aac 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_ppc64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_ppc64.go @@ -1493,6 +1493,30 @@ var libc_mknodat_trampoline_addr uintptr // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Mount(fsType string, dir string, flags int, data unsafe.Pointer) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(fsType) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(dir) + if err != nil { + return + } + _, _, e1 := syscall_syscall6(libc_mount_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(flags), uintptr(data), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_mount_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mount mount "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Nanosleep(time *Timespec, leftover *Timespec) (err error) { _, _, e1 := syscall_syscall(libc_nanosleep_trampoline_addr, uintptr(unsafe.Pointer(time)), uintptr(unsafe.Pointer(leftover)), 0) if e1 != 0 { diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_ppc64.s b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_ppc64.s index 9d1e0ff06..f15dadf05 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_ppc64.s +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_ppc64.s @@ -555,6 +555,12 @@ TEXT libc_mknodat_trampoline<>(SB),NOSPLIT,$0-0 GLOBL ·libc_mknodat_trampoline_addr(SB), RODATA, $8 DATA ·libc_mknodat_trampoline_addr(SB)/8, $libc_mknodat_trampoline<>(SB) +TEXT libc_mount_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_mount(SB) + RET +GLOBL ·libc_mount_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mount_trampoline_addr(SB)/8, $libc_mount_trampoline<>(SB) + TEXT libc_nanosleep_trampoline<>(SB),NOSPLIT,$0-0 CALL libc_nanosleep(SB) RET diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_riscv64.go b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_riscv64.go index 79029ed58..28b487df2 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_riscv64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_riscv64.go @@ -1493,6 +1493,30 @@ var libc_mknodat_trampoline_addr uintptr // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Mount(fsType string, dir string, flags int, data unsafe.Pointer) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(fsType) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(dir) + if err != nil { + return + } + _, _, e1 := syscall_syscall6(libc_mount_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(flags), uintptr(data), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_mount_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mount mount "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Nanosleep(time *Timespec, leftover *Timespec) (err error) { _, _, e1 := syscall_syscall(libc_nanosleep_trampoline_addr, uintptr(unsafe.Pointer(time)), uintptr(unsafe.Pointer(leftover)), 0) if e1 != 0 { diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_riscv64.s b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_riscv64.s index da115f9a4..1e7f321e4 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_riscv64.s +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_riscv64.s @@ -463,6 +463,11 @@ TEXT libc_mknodat_trampoline<>(SB),NOSPLIT,$0-0 GLOBL ·libc_mknodat_trampoline_addr(SB), RODATA, $8 DATA ·libc_mknodat_trampoline_addr(SB)/8, $libc_mknodat_trampoline<>(SB) +TEXT libc_mount_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mount(SB) +GLOBL ·libc_mount_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mount_trampoline_addr(SB)/8, $libc_mount_trampoline<>(SB) + TEXT libc_nanosleep_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_nanosleep(SB) GLOBL ·libc_nanosleep_trampoline_addr(SB), RODATA, $8 diff --git a/vendor/golang.org/x/sys/unix/zsyscall_zos_s390x.go b/vendor/golang.org/x/sys/unix/zsyscall_zos_s390x.go index 94f011238..7ccf66b7e 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_zos_s390x.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_zos_s390x.go @@ -1,4 +1,4 @@ -// go run mksyscall.go -tags zos,s390x syscall_zos_s390x.go +// go run mksyscall_zos_s390x.go -o_sysnum zsysnum_zos_s390x.go -o_syscall zsyscall_zos_s390x.go -i_syscall syscall_zos_s390x.go -o_asm zsymaddr_zos_s390x.s // Code generated by the command above; see README.md. DO NOT EDIT. //go:build zos && s390x @@ -6,17 +6,100 @@ package unix import ( + "runtime" + "syscall" "unsafe" ) +var _ syscall.Errno + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func fcntl(fd int, cmd int, arg int) (val int, err error) { - r0, _, e1 := syscall_syscall(SYS_FCNTL, uintptr(fd), uintptr(cmd), uintptr(arg)) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_FCNTL<<4, uintptr(fd), uintptr(cmd), uintptr(arg)) + runtime.ExitSyscall() val = int(r0) - if e1 != 0 { - err = errnoErr(e1) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Flistxattr(fd int, dest []byte) (sz int, err error) { + var _p0 unsafe.Pointer + if len(dest) > 0 { + _p0 = unsafe.Pointer(&dest[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___FLISTXATTR_A<<4, uintptr(fd), uintptr(_p0), uintptr(len(dest))) + runtime.ExitSyscall() + sz = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_FlistxattrAddr() *(func(fd int, dest []byte) (sz int, err error)) + +var Flistxattr = enter_Flistxattr + +func enter_Flistxattr(fd int, dest []byte) (sz int, err error) { + funcref := get_FlistxattrAddr() + if funcptrtest(GetZosLibVec()+SYS___FLISTXATTR_A<<4, "") == 0 { + *funcref = impl_Flistxattr + } else { + *funcref = error_Flistxattr + } + return (*funcref)(fd, dest) +} + +func error_Flistxattr(fd int, dest []byte) (sz int, err error) { + sz = -1 + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Fremovexattr(fd int, attr string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(attr) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___FREMOVEXATTR_A<<4, uintptr(fd), uintptr(unsafe.Pointer(_p0))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_FremovexattrAddr() *(func(fd int, attr string) (err error)) + +var Fremovexattr = enter_Fremovexattr + +func enter_Fremovexattr(fd int, attr string) (err error) { + funcref := get_FremovexattrAddr() + if funcptrtest(GetZosLibVec()+SYS___FREMOVEXATTR_A<<4, "") == 0 { + *funcref = impl_Fremovexattr + } else { + *funcref = error_Fremovexattr } + return (*funcref)(fd, attr) +} + +func error_Fremovexattr(fd int, attr string) (err error) { + err = ENOSYS return } @@ -29,10 +112,12 @@ func read(fd int, p []byte) (n int, err error) { } else { _p0 = unsafe.Pointer(&_zero) } - r0, _, e1 := syscall_syscall(SYS_READ, uintptr(fd), uintptr(_p0), uintptr(len(p))) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_READ<<4, uintptr(fd), uintptr(_p0), uintptr(len(p))) + runtime.ExitSyscall() n = int(r0) - if e1 != 0 { - err = errnoErr(e1) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -46,31 +131,159 @@ func write(fd int, p []byte) (n int, err error) { } else { _p0 = unsafe.Pointer(&_zero) } - r0, _, e1 := syscall_syscall(SYS_WRITE, uintptr(fd), uintptr(_p0), uintptr(len(p))) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_WRITE<<4, uintptr(fd), uintptr(_p0), uintptr(len(p))) + runtime.ExitSyscall() n = int(r0) - if e1 != 0 { - err = errnoErr(e1) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Fgetxattr(fd int, attr string, dest []byte) (sz int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(attr) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(dest) > 0 { + _p1 = unsafe.Pointer(&dest[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___FGETXATTR_A<<4, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest))) + runtime.ExitSyscall() + sz = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_FgetxattrAddr() *(func(fd int, attr string, dest []byte) (sz int, err error)) + +var Fgetxattr = enter_Fgetxattr + +func enter_Fgetxattr(fd int, attr string, dest []byte) (sz int, err error) { + funcref := get_FgetxattrAddr() + if funcptrtest(GetZosLibVec()+SYS___FGETXATTR_A<<4, "") == 0 { + *funcref = impl_Fgetxattr + } else { + *funcref = error_Fgetxattr + } + return (*funcref)(fd, attr, dest) +} + +func error_Fgetxattr(fd int, attr string, dest []byte) (sz int, err error) { + sz = -1 + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Fsetxattr(fd int, attr string, data []byte, flag int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(attr) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(data) > 0 { + _p1 = unsafe.Pointer(&data[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___FSETXATTR_A<<4, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(data)), uintptr(flag)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_FsetxattrAddr() *(func(fd int, attr string, data []byte, flag int) (err error)) + +var Fsetxattr = enter_Fsetxattr + +func enter_Fsetxattr(fd int, attr string, data []byte, flag int) (err error) { + funcref := get_FsetxattrAddr() + if funcptrtest(GetZosLibVec()+SYS___FSETXATTR_A<<4, "") == 0 { + *funcref = impl_Fsetxattr + } else { + *funcref = error_Fsetxattr } + return (*funcref)(fd, attr, data, flag) +} + +func error_Fsetxattr(fd int, attr string, data []byte, flag int) (err error) { + err = ENOSYS return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) { - r0, _, e1 := syscall_syscall(SYS___ACCEPT_A, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___ACCEPT_A<<4, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) + runtime.ExitSyscall() + fd = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___ACCEPT4_A<<4, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), uintptr(flags)) + runtime.ExitSyscall() fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_accept4Addr() *(func(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error)) + +var accept4 = enter_accept4 + +func enter_accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) { + funcref := get_accept4Addr() + if funcptrtest(GetZosLibVec()+SYS___ACCEPT4_A<<4, "") == 0 { + *funcref = impl_accept4 + } else { + *funcref = error_accept4 } + return (*funcref)(s, rsa, addrlen, flags) +} + +func error_accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) { + fd = -1 + err = ENOSYS return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) { - _, _, e1 := syscall_syscall(SYS___BIND_A, uintptr(s), uintptr(addr), uintptr(addrlen)) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___BIND_A<<4, uintptr(s), uintptr(addr), uintptr(addrlen)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -78,9 +291,11 @@ func bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) { - _, _, e1 := syscall_syscall(SYS___CONNECT_A, uintptr(s), uintptr(addr), uintptr(addrlen)) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___CONNECT_A<<4, uintptr(s), uintptr(addr), uintptr(addrlen)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -88,10 +303,10 @@ func connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func getgroups(n int, list *_Gid_t) (nn int, err error) { - r0, _, e1 := syscall_rawsyscall(SYS_GETGROUPS, uintptr(n), uintptr(unsafe.Pointer(list)), 0) + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_GETGROUPS<<4, uintptr(n), uintptr(unsafe.Pointer(list))) nn = int(r0) - if e1 != 0 { - err = errnoErr(e1) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -99,9 +314,9 @@ func getgroups(n int, list *_Gid_t) (nn int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func setgroups(n int, list *_Gid_t) (err error) { - _, _, e1 := syscall_rawsyscall(SYS_SETGROUPS, uintptr(n), uintptr(unsafe.Pointer(list)), 0) - if e1 != 0 { - err = errnoErr(e1) + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SETGROUPS<<4, uintptr(n), uintptr(unsafe.Pointer(list))) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -109,9 +324,11 @@ func setgroups(n int, list *_Gid_t) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error) { - _, _, e1 := syscall_syscall6(SYS_GETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(unsafe.Pointer(vallen)), 0) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_GETSOCKOPT<<4, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(unsafe.Pointer(vallen))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -119,9 +336,11 @@ func getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error) { - _, _, e1 := syscall_syscall6(SYS_SETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(vallen), 0) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SETSOCKOPT<<4, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(vallen)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -129,10 +348,10 @@ func setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func socket(domain int, typ int, proto int) (fd int, err error) { - r0, _, e1 := syscall_rawsyscall(SYS_SOCKET, uintptr(domain), uintptr(typ), uintptr(proto)) + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SOCKET<<4, uintptr(domain), uintptr(typ), uintptr(proto)) fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -140,9 +359,9 @@ func socket(domain int, typ int, proto int) (fd int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) { - _, _, e1 := syscall_rawsyscall6(SYS_SOCKETPAIR, uintptr(domain), uintptr(typ), uintptr(proto), uintptr(unsafe.Pointer(fd)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SOCKETPAIR<<4, uintptr(domain), uintptr(typ), uintptr(proto), uintptr(unsafe.Pointer(fd))) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -150,9 +369,9 @@ func socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) { - _, _, e1 := syscall_rawsyscall(SYS___GETPEERNAME_A, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) - if e1 != 0 { - err = errnoErr(e1) + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___GETPEERNAME_A<<4, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -160,10 +379,52 @@ func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) { - _, _, e1 := syscall_rawsyscall(SYS___GETSOCKNAME_A, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) - if e1 != 0 { - err = errnoErr(e1) + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___GETSOCKNAME_A<<4, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Removexattr(path string, attr string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(attr) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___REMOVEXATTR_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_RemovexattrAddr() *(func(path string, attr string) (err error)) + +var Removexattr = enter_Removexattr + +func enter_Removexattr(path string, attr string) (err error) { + funcref := get_RemovexattrAddr() + if funcptrtest(GetZosLibVec()+SYS___REMOVEXATTR_A<<4, "") == 0 { + *funcref = impl_Removexattr + } else { + *funcref = error_Removexattr } + return (*funcref)(path, attr) +} + +func error_Removexattr(path string, attr string) (err error) { + err = ENOSYS return } @@ -176,10 +437,12 @@ func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Sockl } else { _p0 = unsafe.Pointer(&_zero) } - r0, _, e1 := syscall_syscall6(SYS___RECVFROM_A, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen))) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___RECVFROM_A<<4, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen))) + runtime.ExitSyscall() n = int(r0) - if e1 != 0 { - err = errnoErr(e1) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -193,9 +456,11 @@ func sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) ( } else { _p0 = unsafe.Pointer(&_zero) } - _, _, e1 := syscall_syscall6(SYS___SENDTO_A, uintptr(s), uintptr(_p0), uintptr(len(buf)), uintptr(flags), uintptr(to), uintptr(addrlen)) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___SENDTO_A<<4, uintptr(s), uintptr(_p0), uintptr(len(buf)), uintptr(flags), uintptr(to), uintptr(addrlen)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -203,10 +468,12 @@ func sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) ( // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func recvmsg(s int, msg *Msghdr, flags int) (n int, err error) { - r0, _, e1 := syscall_syscall(SYS___RECVMSG_A, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags)) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___RECVMSG_A<<4, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags)) + runtime.ExitSyscall() n = int(r0) - if e1 != 0 { - err = errnoErr(e1) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -214,10 +481,12 @@ func recvmsg(s int, msg *Msghdr, flags int) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func sendmsg(s int, msg *Msghdr, flags int) (n int, err error) { - r0, _, e1 := syscall_syscall(SYS___SENDMSG_A, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags)) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___SENDMSG_A<<4, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags)) + runtime.ExitSyscall() n = int(r0) - if e1 != 0 { - err = errnoErr(e1) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -225,10 +494,12 @@ func sendmsg(s int, msg *Msghdr, flags int) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error) { - r0, _, e1 := syscall_syscall6(SYS_MMAP, uintptr(addr), uintptr(length), uintptr(prot), uintptr(flag), uintptr(fd), uintptr(pos)) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_MMAP<<4, uintptr(addr), uintptr(length), uintptr(prot), uintptr(flag), uintptr(fd), uintptr(pos)) + runtime.ExitSyscall() ret = uintptr(r0) - if e1 != 0 { - err = errnoErr(e1) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -236,9 +507,11 @@ func mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) ( // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func munmap(addr uintptr, length uintptr) (err error) { - _, _, e1 := syscall_syscall(SYS_MUNMAP, uintptr(addr), uintptr(length), 0) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_MUNMAP<<4, uintptr(addr), uintptr(length)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -246,9 +519,11 @@ func munmap(addr uintptr, length uintptr) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func ioctl(fd int, req int, arg uintptr) (err error) { - _, _, e1 := syscall_syscall(SYS_IOCTL, uintptr(fd), uintptr(req), uintptr(arg)) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_IOCTL<<4, uintptr(fd), uintptr(req), uintptr(arg)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -256,9 +531,62 @@ func ioctl(fd int, req int, arg uintptr) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func ioctlPtr(fd int, req int, arg unsafe.Pointer) (err error) { - _, _, e1 := syscall_syscall(SYS_IOCTL, uintptr(fd), uintptr(req), uintptr(arg)) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_IOCTL<<4, uintptr(fd), uintptr(req), uintptr(arg)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func shmat(id int, addr uintptr, flag int) (ret uintptr, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SHMAT<<4, uintptr(id), uintptr(addr), uintptr(flag)) + runtime.ExitSyscall() + ret = uintptr(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func shmctl(id int, cmd int, buf *SysvShmDesc) (result int, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SHMCTL64<<4, uintptr(id), uintptr(cmd), uintptr(unsafe.Pointer(buf))) + runtime.ExitSyscall() + result = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func shmdt(addr uintptr) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SHMDT<<4, uintptr(addr)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func shmget(key int, size int, flag int) (id int, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SHMGET<<4, uintptr(key), uintptr(size), uintptr(flag)) + runtime.ExitSyscall() + id = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -271,9 +599,11 @@ func Access(path string, mode uint32) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(SYS___ACCESS_A, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___ACCESS_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(mode)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -286,9 +616,11 @@ func Chdir(path string) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(SYS___CHDIR_A, uintptr(unsafe.Pointer(_p0)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___CHDIR_A<<4, uintptr(unsafe.Pointer(_p0))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -301,9 +633,11 @@ func Chown(path string, uid int, gid int) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(SYS___CHOWN_A, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid)) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___CHOWN_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -316,9 +650,11 @@ func Chmod(path string, mode uint32) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(SYS___CHMOD_A, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___CHMOD_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(mode)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -331,10 +667,12 @@ func Creat(path string, mode uint32) (fd int, err error) { if err != nil { return } - r0, _, e1 := syscall_syscall(SYS___CREAT_A, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___CREAT_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(mode)) + runtime.ExitSyscall() fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -342,10 +680,12 @@ func Creat(path string, mode uint32) (fd int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Dup(oldfd int) (fd int, err error) { - r0, _, e1 := syscall_syscall(SYS_DUP, uintptr(oldfd), 0, 0) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_DUP<<4, uintptr(oldfd)) + runtime.ExitSyscall() fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -353,617 +693,2216 @@ func Dup(oldfd int) (fd int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Dup2(oldfd int, newfd int) (err error) { - _, _, e1 := syscall_syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_DUP2<<4, uintptr(oldfd), uintptr(newfd)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Errno2() (er2 int) { - uer2, _, _ := syscall_syscall(SYS___ERRNO2, 0, 0, 0) - er2 = int(uer2) +func impl_Dup3(oldfd int, newfd int, flags int) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_DUP3<<4, uintptr(oldfd), uintptr(newfd), uintptr(flags)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } return } -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +//go:nosplit +func get_Dup3Addr() *(func(oldfd int, newfd int, flags int) (err error)) -func Err2ad() (eadd *int) { - ueadd, _, _ := syscall_syscall(SYS___ERR2AD, 0, 0, 0) - eadd = (*int)(unsafe.Pointer(ueadd)) - return -} +var Dup3 = enter_Dup3 -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func enter_Dup3(oldfd int, newfd int, flags int) (err error) { + funcref := get_Dup3Addr() + if funcptrtest(GetZosLibVec()+SYS_DUP3<<4, "") == 0 { + *funcref = impl_Dup3 + } else { + *funcref = error_Dup3 + } + return (*funcref)(oldfd, newfd, flags) +} -func Exit(code int) { - syscall_syscall(SYS_EXIT, uintptr(code), 0, 0) +func error_Dup3(oldfd int, newfd int, flags int) (err error) { + err = ENOSYS return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Fchdir(fd int) (err error) { - _, _, e1 := syscall_syscall(SYS_FCHDIR, uintptr(fd), 0, 0) - if e1 != 0 { - err = errnoErr(e1) +func impl_Dirfd(dirp uintptr) (fd int, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_DIRFD<<4, uintptr(dirp)) + runtime.ExitSyscall() + fd = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +//go:nosplit +func get_DirfdAddr() *(func(dirp uintptr) (fd int, err error)) -func Fchmod(fd int, mode uint32) (err error) { - _, _, e1 := syscall_syscall(SYS_FCHMOD, uintptr(fd), uintptr(mode), 0) - if e1 != 0 { - err = errnoErr(e1) +var Dirfd = enter_Dirfd + +func enter_Dirfd(dirp uintptr) (fd int, err error) { + funcref := get_DirfdAddr() + if funcptrtest(GetZosLibVec()+SYS_DIRFD<<4, "") == 0 { + *funcref = impl_Dirfd + } else { + *funcref = error_Dirfd } + return (*funcref)(dirp) +} + +func error_Dirfd(dirp uintptr) (fd int, err error) { + fd = -1 + err = ENOSYS return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Fchown(fd int, uid int, gid int) (err error) { - _, _, e1 := syscall_syscall(SYS_FCHOWN, uintptr(fd), uintptr(uid), uintptr(gid)) - if e1 != 0 { - err = errnoErr(e1) +func impl_EpollCreate(size int) (fd int, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_EPOLL_CREATE<<4, uintptr(size)) + runtime.ExitSyscall() + fd = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +//go:nosplit +func get_EpollCreateAddr() *(func(size int) (fd int, err error)) -func FcntlInt(fd uintptr, cmd int, arg int) (retval int, err error) { - r0, _, e1 := syscall_syscall(SYS_FCNTL, uintptr(fd), uintptr(cmd), uintptr(arg)) - retval = int(r0) - if e1 != 0 { - err = errnoErr(e1) +var EpollCreate = enter_EpollCreate + +func enter_EpollCreate(size int) (fd int, err error) { + funcref := get_EpollCreateAddr() + if funcptrtest(GetZosLibVec()+SYS_EPOLL_CREATE<<4, "") == 0 { + *funcref = impl_EpollCreate + } else { + *funcref = error_EpollCreate } + return (*funcref)(size) +} + +func error_EpollCreate(size int) (fd int, err error) { + fd = -1 + err = ENOSYS return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func fstat(fd int, stat *Stat_LE_t) (err error) { - _, _, e1 := syscall_syscall(SYS_FSTAT, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) - if e1 != 0 { - err = errnoErr(e1) +func impl_EpollCreate1(flags int) (fd int, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_EPOLL_CREATE1<<4, uintptr(flags)) + runtime.ExitSyscall() + fd = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +//go:nosplit +func get_EpollCreate1Addr() *(func(flags int) (fd int, err error)) -func Fstatvfs(fd int, stat *Statvfs_t) (err error) { - _, _, e1 := syscall_syscall(SYS_FSTATVFS, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) - if e1 != 0 { - err = errnoErr(e1) +var EpollCreate1 = enter_EpollCreate1 + +func enter_EpollCreate1(flags int) (fd int, err error) { + funcref := get_EpollCreate1Addr() + if funcptrtest(GetZosLibVec()+SYS_EPOLL_CREATE1<<4, "") == 0 { + *funcref = impl_EpollCreate1 + } else { + *funcref = error_EpollCreate1 } + return (*funcref)(flags) +} + +func error_EpollCreate1(flags int) (fd int, err error) { + fd = -1 + err = ENOSYS return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Fsync(fd int) (err error) { - _, _, e1 := syscall_syscall(SYS_FSYNC, uintptr(fd), 0, 0) - if e1 != 0 { - err = errnoErr(e1) +func impl_EpollCtl(epfd int, op int, fd int, event *EpollEvent) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_EPOLL_CTL<<4, uintptr(epfd), uintptr(op), uintptr(fd), uintptr(unsafe.Pointer(event))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +//go:nosplit +func get_EpollCtlAddr() *(func(epfd int, op int, fd int, event *EpollEvent) (err error)) -func Ftruncate(fd int, length int64) (err error) { - _, _, e1 := syscall_syscall(SYS_FTRUNCATE, uintptr(fd), uintptr(length), 0) - if e1 != 0 { - err = errnoErr(e1) +var EpollCtl = enter_EpollCtl + +func enter_EpollCtl(epfd int, op int, fd int, event *EpollEvent) (err error) { + funcref := get_EpollCtlAddr() + if funcptrtest(GetZosLibVec()+SYS_EPOLL_CTL<<4, "") == 0 { + *funcref = impl_EpollCtl + } else { + *funcref = error_EpollCtl } - return + return (*funcref)(epfd, op, fd, event) } -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Getpagesize() (pgsize int) { - r0, _, _ := syscall_syscall(SYS_GETPAGESIZE, 0, 0, 0) - pgsize = int(r0) +func error_EpollCtl(epfd int, op int, fd int, event *EpollEvent) (err error) { + err = ENOSYS return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Mprotect(b []byte, prot int) (err error) { +func impl_EpollPwait(epfd int, events []EpollEvent, msec int, sigmask *int) (n int, err error) { var _p0 unsafe.Pointer - if len(b) > 0 { - _p0 = unsafe.Pointer(&b[0]) + if len(events) > 0 { + _p0 = unsafe.Pointer(&events[0]) } else { _p0 = unsafe.Pointer(&_zero) } - _, _, e1 := syscall_syscall(SYS_MPROTECT, uintptr(_p0), uintptr(len(b)), uintptr(prot)) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_EPOLL_PWAIT<<4, uintptr(epfd), uintptr(_p0), uintptr(len(events)), uintptr(msec), uintptr(unsafe.Pointer(sigmask))) + runtime.ExitSyscall() + n = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +//go:nosplit +func get_EpollPwaitAddr() *(func(epfd int, events []EpollEvent, msec int, sigmask *int) (n int, err error)) -func Msync(b []byte, flags int) (err error) { - var _p0 unsafe.Pointer - if len(b) > 0 { - _p0 = unsafe.Pointer(&b[0]) +var EpollPwait = enter_EpollPwait + +func enter_EpollPwait(epfd int, events []EpollEvent, msec int, sigmask *int) (n int, err error) { + funcref := get_EpollPwaitAddr() + if funcptrtest(GetZosLibVec()+SYS_EPOLL_PWAIT<<4, "") == 0 { + *funcref = impl_EpollPwait } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := syscall_syscall(SYS_MSYNC, uintptr(_p0), uintptr(len(b)), uintptr(flags)) - if e1 != 0 { - err = errnoErr(e1) + *funcref = error_EpollPwait } + return (*funcref)(epfd, events, msec, sigmask) +} + +func error_EpollPwait(epfd int, events []EpollEvent, msec int, sigmask *int) (n int, err error) { + n = -1 + err = ENOSYS return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Poll(fds []PollFd, timeout int) (n int, err error) { +func impl_EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) { var _p0 unsafe.Pointer - if len(fds) > 0 { - _p0 = unsafe.Pointer(&fds[0]) + if len(events) > 0 { + _p0 = unsafe.Pointer(&events[0]) } else { _p0 = unsafe.Pointer(&_zero) } - r0, _, e1 := syscall_syscall(SYS_POLL, uintptr(_p0), uintptr(len(fds)), uintptr(timeout)) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_EPOLL_WAIT<<4, uintptr(epfd), uintptr(_p0), uintptr(len(events)), uintptr(msec)) + runtime.ExitSyscall() n = int(r0) - if e1 != 0 { - err = errnoErr(e1) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +//go:nosplit +func get_EpollWaitAddr() *(func(epfd int, events []EpollEvent, msec int) (n int, err error)) -func Times(tms *Tms) (ticks uintptr, err error) { - r0, _, e1 := syscall_syscall(SYS_TIMES, uintptr(unsafe.Pointer(tms)), 0, 0) - ticks = uintptr(r0) - if e1 != 0 { - err = errnoErr(e1) +var EpollWait = enter_EpollWait + +func enter_EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) { + funcref := get_EpollWaitAddr() + if funcptrtest(GetZosLibVec()+SYS_EPOLL_WAIT<<4, "") == 0 { + *funcref = impl_EpollWait + } else { + *funcref = error_EpollWait } + return (*funcref)(epfd, events, msec) +} + +func error_EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) { + n = -1 + err = ENOSYS return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func W_Getmntent(buff *byte, size int) (lastsys int, err error) { - r0, _, e1 := syscall_syscall(SYS_W_GETMNTENT, uintptr(unsafe.Pointer(buff)), uintptr(size), 0) - lastsys = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } +func Errno2() (er2 int) { + runtime.EnterSyscall() + r0, _, _ := CallLeFuncWithErr(GetZosLibVec() + SYS___ERRNO2<<4) + runtime.ExitSyscall() + er2 = int(r0) return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func W_Getmntent_A(buff *byte, size int) (lastsys int, err error) { - r0, _, e1 := syscall_syscall(SYS___W_GETMNTENT_A, uintptr(unsafe.Pointer(buff)), uintptr(size), 0) - lastsys = int(r0) - if e1 != 0 { - err = errnoErr(e1) +func impl_Eventfd(initval uint, flags int) (fd int, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_EVENTFD<<4, uintptr(initval), uintptr(flags)) + runtime.ExitSyscall() + fd = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } +//go:nosplit +func get_EventfdAddr() *(func(initval uint, flags int) (fd int, err error)) + +var Eventfd = enter_Eventfd + +func enter_Eventfd(initval uint, flags int) (fd int, err error) { + funcref := get_EventfdAddr() + if funcptrtest(GetZosLibVec()+SYS_EVENTFD<<4, "") == 0 { + *funcref = impl_Eventfd + } else { + *funcref = error_Eventfd + } + return (*funcref)(initval, flags) +} + +func error_Eventfd(initval uint, flags int) (fd int, err error) { + fd = -1 + err = ENOSYS + return +} + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func mount_LE(path string, filesystem string, fstype string, mtm uint32, parmlen int32, parm string) (err error) { +func Exit(code int) { + runtime.EnterSyscall() + CallLeFuncWithErr(GetZosLibVec()+SYS_EXIT<<4, uintptr(code)) + runtime.ExitSyscall() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Faccessat(dirfd int, path string, mode uint32, flags int) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) if err != nil { return } - var _p1 *byte - _p1, err = BytePtrFromString(filesystem) - if err != nil { - return - } - var _p2 *byte - _p2, err = BytePtrFromString(fstype) - if err != nil { - return - } - var _p3 *byte - _p3, err = BytePtrFromString(parm) - if err != nil { - return - } - _, _, e1 := syscall_syscall6(SYS___MOUNT_A, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(unsafe.Pointer(_p2)), uintptr(mtm), uintptr(parmlen), uintptr(unsafe.Pointer(_p3))) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___FACCESSAT_A<<4, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +//go:nosplit +func get_FaccessatAddr() *(func(dirfd int, path string, mode uint32, flags int) (err error)) -func unmount(filesystem string, mtm int) (err error) { +var Faccessat = enter_Faccessat + +func enter_Faccessat(dirfd int, path string, mode uint32, flags int) (err error) { + funcref := get_FaccessatAddr() + if funcptrtest(GetZosLibVec()+SYS___FACCESSAT_A<<4, "") == 0 { + *funcref = impl_Faccessat + } else { + *funcref = error_Faccessat + } + return (*funcref)(dirfd, path, mode, flags) +} + +func error_Faccessat(dirfd int, path string, mode uint32, flags int) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fchdir(fd int) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_FCHDIR<<4, uintptr(fd)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fchmod(fd int, mode uint32) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_FCHMOD<<4, uintptr(fd), uintptr(mode)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) { var _p0 *byte - _p0, err = BytePtrFromString(filesystem) + _p0, err = BytePtrFromString(path) if err != nil { return } - _, _, e1 := syscall_syscall(SYS___UMOUNT_A, uintptr(unsafe.Pointer(_p0)), uintptr(mtm), 0) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___FCHMODAT_A<<4, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_FchmodatAddr() *(func(dirfd int, path string, mode uint32, flags int) (err error)) + +var Fchmodat = enter_Fchmodat + +func enter_Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) { + funcref := get_FchmodatAddr() + if funcptrtest(GetZosLibVec()+SYS___FCHMODAT_A<<4, "") == 0 { + *funcref = impl_Fchmodat + } else { + *funcref = error_Fchmodat + } + return (*funcref)(dirfd, path, mode, flags) +} + +func error_Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fchown(fd int, uid int, gid int) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_FCHOWN<<4, uintptr(fd), uintptr(uid), uintptr(gid)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Chroot(path string) (err error) { +func impl_Fchownat(fd int, path string, uid int, gid int, flags int) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) if err != nil { return } - _, _, e1 := syscall_syscall(SYS___CHROOT_A, uintptr(unsafe.Pointer(_p0)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___FCHOWNAT_A<<4, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid), uintptr(flags)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_FchownatAddr() *(func(fd int, path string, uid int, gid int, flags int) (err error)) + +var Fchownat = enter_Fchownat + +func enter_Fchownat(fd int, path string, uid int, gid int, flags int) (err error) { + funcref := get_FchownatAddr() + if funcptrtest(GetZosLibVec()+SYS___FCHOWNAT_A<<4, "") == 0 { + *funcref = impl_Fchownat + } else { + *funcref = error_Fchownat } + return (*funcref)(fd, path, uid, gid, flags) +} + +func error_Fchownat(fd int, path string, uid int, gid int, flags int) (err error) { + err = ENOSYS return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Uname(buf *Utsname) (err error) { - _, _, e1 := syscall_rawsyscall(SYS___UNAME_A, uintptr(unsafe.Pointer(buf)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) +func FcntlInt(fd uintptr, cmd int, arg int) (retval int, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_FCNTL<<4, uintptr(fd), uintptr(cmd), uintptr(arg)) + runtime.ExitSyscall() + retval = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Gethostname(buf []byte) (err error) { +func impl_Fdatasync(fd int) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_FDATASYNC<<4, uintptr(fd)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_FdatasyncAddr() *(func(fd int) (err error)) + +var Fdatasync = enter_Fdatasync + +func enter_Fdatasync(fd int) (err error) { + funcref := get_FdatasyncAddr() + if funcptrtest(GetZosLibVec()+SYS_FDATASYNC<<4, "") == 0 { + *funcref = impl_Fdatasync + } else { + *funcref = error_Fdatasync + } + return (*funcref)(fd) +} + +func error_Fdatasync(fd int) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func fstat(fd int, stat *Stat_LE_t) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_FSTAT<<4, uintptr(fd), uintptr(unsafe.Pointer(stat))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_fstatat(dirfd int, path string, stat *Stat_LE_t, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___FSTATAT_A<<4, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_fstatatAddr() *(func(dirfd int, path string, stat *Stat_LE_t, flags int) (err error)) + +var fstatat = enter_fstatat + +func enter_fstatat(dirfd int, path string, stat *Stat_LE_t, flags int) (err error) { + funcref := get_fstatatAddr() + if funcptrtest(GetZosLibVec()+SYS___FSTATAT_A<<4, "") == 0 { + *funcref = impl_fstatat + } else { + *funcref = error_fstatat + } + return (*funcref)(dirfd, path, stat, flags) +} + +func error_fstatat(dirfd int, path string, stat *Stat_LE_t, flags int) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Lgetxattr(link string, attr string, dest []byte) (sz int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(link) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(attr) + if err != nil { + return + } + var _p2 unsafe.Pointer + if len(dest) > 0 { + _p2 = unsafe.Pointer(&dest[0]) + } else { + _p2 = unsafe.Pointer(&_zero) + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___LGETXATTR_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(dest))) + runtime.ExitSyscall() + sz = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_LgetxattrAddr() *(func(link string, attr string, dest []byte) (sz int, err error)) + +var Lgetxattr = enter_Lgetxattr + +func enter_Lgetxattr(link string, attr string, dest []byte) (sz int, err error) { + funcref := get_LgetxattrAddr() + if funcptrtest(GetZosLibVec()+SYS___LGETXATTR_A<<4, "") == 0 { + *funcref = impl_Lgetxattr + } else { + *funcref = error_Lgetxattr + } + return (*funcref)(link, attr, dest) +} + +func error_Lgetxattr(link string, attr string, dest []byte) (sz int, err error) { + sz = -1 + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Lsetxattr(path string, attr string, data []byte, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(attr) + if err != nil { + return + } + var _p2 unsafe.Pointer + if len(data) > 0 { + _p2 = unsafe.Pointer(&data[0]) + } else { + _p2 = unsafe.Pointer(&_zero) + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___LSETXATTR_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(data)), uintptr(flags)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_LsetxattrAddr() *(func(path string, attr string, data []byte, flags int) (err error)) + +var Lsetxattr = enter_Lsetxattr + +func enter_Lsetxattr(path string, attr string, data []byte, flags int) (err error) { + funcref := get_LsetxattrAddr() + if funcptrtest(GetZosLibVec()+SYS___LSETXATTR_A<<4, "") == 0 { + *funcref = impl_Lsetxattr + } else { + *funcref = error_Lsetxattr + } + return (*funcref)(path, attr, data, flags) +} + +func error_Lsetxattr(path string, attr string, data []byte, flags int) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Fstatfs(fd int, buf *Statfs_t) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_FSTATFS<<4, uintptr(fd), uintptr(unsafe.Pointer(buf))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_FstatfsAddr() *(func(fd int, buf *Statfs_t) (err error)) + +var Fstatfs = enter_Fstatfs + +func enter_Fstatfs(fd int, buf *Statfs_t) (err error) { + funcref := get_FstatfsAddr() + if funcptrtest(GetZosLibVec()+SYS_FSTATFS<<4, "") == 0 { + *funcref = impl_Fstatfs + } else { + *funcref = error_Fstatfs + } + return (*funcref)(fd, buf) +} + +func error_Fstatfs(fd int, buf *Statfs_t) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fstatvfs(fd int, stat *Statvfs_t) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_FSTATVFS<<4, uintptr(fd), uintptr(unsafe.Pointer(stat))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fsync(fd int) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_FSYNC<<4, uintptr(fd)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Futimes(fd int, tv []Timeval) (err error) { var _p0 unsafe.Pointer - if len(buf) > 0 { - _p0 = unsafe.Pointer(&buf[0]) + if len(tv) > 0 { + _p0 = unsafe.Pointer(&tv[0]) } else { _p0 = unsafe.Pointer(&_zero) } - _, _, e1 := syscall_syscall(SYS___GETHOSTNAME_A, uintptr(_p0), uintptr(len(buf)), 0) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_FUTIMES<<4, uintptr(fd), uintptr(_p0), uintptr(len(tv))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +//go:nosplit +func get_FutimesAddr() *(func(fd int, tv []Timeval) (err error)) -func Getegid() (egid int) { - r0, _, _ := syscall_rawsyscall(SYS_GETEGID, 0, 0, 0) - egid = int(r0) +var Futimes = enter_Futimes + +func enter_Futimes(fd int, tv []Timeval) (err error) { + funcref := get_FutimesAddr() + if funcptrtest(GetZosLibVec()+SYS_FUTIMES<<4, "") == 0 { + *funcref = impl_Futimes + } else { + *funcref = error_Futimes + } + return (*funcref)(fd, tv) +} + +func error_Futimes(fd int, tv []Timeval) (err error) { + err = ENOSYS return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Geteuid() (uid int) { - r0, _, _ := syscall_rawsyscall(SYS_GETEUID, 0, 0, 0) - uid = int(r0) +func impl_Futimesat(dirfd int, path string, tv []Timeval) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(tv) > 0 { + _p1 = unsafe.Pointer(&tv[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___FUTIMESAT_A<<4, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(tv))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_FutimesatAddr() *(func(dirfd int, path string, tv []Timeval) (err error)) + +var Futimesat = enter_Futimesat + +func enter_Futimesat(dirfd int, path string, tv []Timeval) (err error) { + funcref := get_FutimesatAddr() + if funcptrtest(GetZosLibVec()+SYS___FUTIMESAT_A<<4, "") == 0 { + *funcref = impl_Futimesat + } else { + *funcref = error_Futimesat + } + return (*funcref)(dirfd, path, tv) +} + +func error_Futimesat(dirfd int, path string, tv []Timeval) (err error) { + err = ENOSYS return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Getgid() (gid int) { - r0, _, _ := syscall_rawsyscall(SYS_GETGID, 0, 0, 0) - gid = int(r0) +func Ftruncate(fd int, length int64) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_FTRUNCATE<<4, uintptr(fd), uintptr(length)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Getpid() (pid int) { - r0, _, _ := syscall_rawsyscall(SYS_GETPID, 0, 0, 0) - pid = int(r0) +func impl_Getrandom(buf []byte, flags int) (n int, err error) { + var _p0 unsafe.Pointer + if len(buf) > 0 { + _p0 = unsafe.Pointer(&buf[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_GETRANDOM<<4, uintptr(_p0), uintptr(len(buf)), uintptr(flags)) + runtime.ExitSyscall() + n = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_GetrandomAddr() *(func(buf []byte, flags int) (n int, err error)) + +var Getrandom = enter_Getrandom + +func enter_Getrandom(buf []byte, flags int) (n int, err error) { + funcref := get_GetrandomAddr() + if funcptrtest(GetZosLibVec()+SYS_GETRANDOM<<4, "") == 0 { + *funcref = impl_Getrandom + } else { + *funcref = error_Getrandom + } + return (*funcref)(buf, flags) +} + +func error_Getrandom(buf []byte, flags int) (n int, err error) { + n = -1 + err = ENOSYS return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Getpgid(pid int) (pgid int, err error) { - r0, _, e1 := syscall_rawsyscall(SYS_GETPGID, uintptr(pid), 0, 0) - pgid = int(r0) - if e1 != 0 { - err = errnoErr(e1) +func impl_InotifyInit() (fd int, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec() + SYS_INOTIFY_INIT<<4) + runtime.ExitSyscall() + fd = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_InotifyInitAddr() *(func() (fd int, err error)) + +var InotifyInit = enter_InotifyInit + +func enter_InotifyInit() (fd int, err error) { + funcref := get_InotifyInitAddr() + if funcptrtest(GetZosLibVec()+SYS_INOTIFY_INIT<<4, "") == 0 { + *funcref = impl_InotifyInit + } else { + *funcref = error_InotifyInit } + return (*funcref)() +} + +func error_InotifyInit() (fd int, err error) { + fd = -1 + err = ENOSYS return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Getppid() (pid int) { - r0, _, _ := syscall_rawsyscall(SYS_GETPPID, 0, 0, 0) - pid = int(r0) +func impl_InotifyInit1(flags int) (fd int, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_INOTIFY_INIT1<<4, uintptr(flags)) + runtime.ExitSyscall() + fd = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_InotifyInit1Addr() *(func(flags int) (fd int, err error)) + +var InotifyInit1 = enter_InotifyInit1 + +func enter_InotifyInit1(flags int) (fd int, err error) { + funcref := get_InotifyInit1Addr() + if funcptrtest(GetZosLibVec()+SYS_INOTIFY_INIT1<<4, "") == 0 { + *funcref = impl_InotifyInit1 + } else { + *funcref = error_InotifyInit1 + } + return (*funcref)(flags) +} + +func error_InotifyInit1(flags int) (fd int, err error) { + fd = -1 + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_InotifyAddWatch(fd int, pathname string, mask uint32) (watchdesc int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(pathname) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___INOTIFY_ADD_WATCH_A<<4, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(mask)) + runtime.ExitSyscall() + watchdesc = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_InotifyAddWatchAddr() *(func(fd int, pathname string, mask uint32) (watchdesc int, err error)) + +var InotifyAddWatch = enter_InotifyAddWatch + +func enter_InotifyAddWatch(fd int, pathname string, mask uint32) (watchdesc int, err error) { + funcref := get_InotifyAddWatchAddr() + if funcptrtest(GetZosLibVec()+SYS___INOTIFY_ADD_WATCH_A<<4, "") == 0 { + *funcref = impl_InotifyAddWatch + } else { + *funcref = error_InotifyAddWatch + } + return (*funcref)(fd, pathname, mask) +} + +func error_InotifyAddWatch(fd int, pathname string, mask uint32) (watchdesc int, err error) { + watchdesc = -1 + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_InotifyRmWatch(fd int, watchdesc uint32) (success int, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_INOTIFY_RM_WATCH<<4, uintptr(fd), uintptr(watchdesc)) + runtime.ExitSyscall() + success = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_InotifyRmWatchAddr() *(func(fd int, watchdesc uint32) (success int, err error)) + +var InotifyRmWatch = enter_InotifyRmWatch + +func enter_InotifyRmWatch(fd int, watchdesc uint32) (success int, err error) { + funcref := get_InotifyRmWatchAddr() + if funcptrtest(GetZosLibVec()+SYS_INOTIFY_RM_WATCH<<4, "") == 0 { + *funcref = impl_InotifyRmWatch + } else { + *funcref = error_InotifyRmWatch + } + return (*funcref)(fd, watchdesc) +} + +func error_InotifyRmWatch(fd int, watchdesc uint32) (success int, err error) { + success = -1 + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Listxattr(path string, dest []byte) (sz int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(dest) > 0 { + _p1 = unsafe.Pointer(&dest[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___LISTXATTR_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest))) + runtime.ExitSyscall() + sz = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_ListxattrAddr() *(func(path string, dest []byte) (sz int, err error)) + +var Listxattr = enter_Listxattr + +func enter_Listxattr(path string, dest []byte) (sz int, err error) { + funcref := get_ListxattrAddr() + if funcptrtest(GetZosLibVec()+SYS___LISTXATTR_A<<4, "") == 0 { + *funcref = impl_Listxattr + } else { + *funcref = error_Listxattr + } + return (*funcref)(path, dest) +} + +func error_Listxattr(path string, dest []byte) (sz int, err error) { + sz = -1 + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Llistxattr(path string, dest []byte) (sz int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(dest) > 0 { + _p1 = unsafe.Pointer(&dest[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___LLISTXATTR_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest))) + runtime.ExitSyscall() + sz = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_LlistxattrAddr() *(func(path string, dest []byte) (sz int, err error)) + +var Llistxattr = enter_Llistxattr + +func enter_Llistxattr(path string, dest []byte) (sz int, err error) { + funcref := get_LlistxattrAddr() + if funcptrtest(GetZosLibVec()+SYS___LLISTXATTR_A<<4, "") == 0 { + *funcref = impl_Llistxattr + } else { + *funcref = error_Llistxattr + } + return (*funcref)(path, dest) +} + +func error_Llistxattr(path string, dest []byte) (sz int, err error) { + sz = -1 + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Lremovexattr(path string, attr string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(attr) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___LREMOVEXATTR_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_LremovexattrAddr() *(func(path string, attr string) (err error)) + +var Lremovexattr = enter_Lremovexattr + +func enter_Lremovexattr(path string, attr string) (err error) { + funcref := get_LremovexattrAddr() + if funcptrtest(GetZosLibVec()+SYS___LREMOVEXATTR_A<<4, "") == 0 { + *funcref = impl_Lremovexattr + } else { + *funcref = error_Lremovexattr + } + return (*funcref)(path, attr) +} + +func error_Lremovexattr(path string, attr string) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Lutimes(path string, tv []Timeval) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(tv) > 0 { + _p1 = unsafe.Pointer(&tv[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___LUTIMES_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(tv))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_LutimesAddr() *(func(path string, tv []Timeval) (err error)) + +var Lutimes = enter_Lutimes + +func enter_Lutimes(path string, tv []Timeval) (err error) { + funcref := get_LutimesAddr() + if funcptrtest(GetZosLibVec()+SYS___LUTIMES_A<<4, "") == 0 { + *funcref = impl_Lutimes + } else { + *funcref = error_Lutimes + } + return (*funcref)(path, tv) +} + +func error_Lutimes(path string, tv []Timeval) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Mprotect(b []byte, prot int) (err error) { + var _p0 unsafe.Pointer + if len(b) > 0 { + _p0 = unsafe.Pointer(&b[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_MPROTECT<<4, uintptr(_p0), uintptr(len(b)), uintptr(prot)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Msync(b []byte, flags int) (err error) { + var _p0 unsafe.Pointer + if len(b) > 0 { + _p0 = unsafe.Pointer(&b[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_MSYNC<<4, uintptr(_p0), uintptr(len(b)), uintptr(flags)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Console2(cmsg *ConsMsg2, modstr *byte, concmd *uint32) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___CONSOLE2<<4, uintptr(unsafe.Pointer(cmsg)), uintptr(unsafe.Pointer(modstr)), uintptr(unsafe.Pointer(concmd))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Poll(fds []PollFd, timeout int) (n int, err error) { + var _p0 unsafe.Pointer + if len(fds) > 0 { + _p0 = unsafe.Pointer(&fds[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_POLL<<4, uintptr(_p0), uintptr(len(fds)), uintptr(timeout)) + runtime.ExitSyscall() + n = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Readdir_r(dirp uintptr, entry *direntLE, result **direntLE) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___READDIR_R_A<<4, uintptr(dirp), uintptr(unsafe.Pointer(entry)), uintptr(unsafe.Pointer(result))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Statfs(path string, buf *Statfs_t) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___STATFS_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(buf))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_StatfsAddr() *(func(path string, buf *Statfs_t) (err error)) + +var Statfs = enter_Statfs + +func enter_Statfs(path string, buf *Statfs_t) (err error) { + funcref := get_StatfsAddr() + if funcptrtest(GetZosLibVec()+SYS___STATFS_A<<4, "") == 0 { + *funcref = impl_Statfs + } else { + *funcref = error_Statfs + } + return (*funcref)(path, buf) +} + +func error_Statfs(path string, buf *Statfs_t) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Syncfs(fd int) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SYNCFS<<4, uintptr(fd)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_SyncfsAddr() *(func(fd int) (err error)) + +var Syncfs = enter_Syncfs + +func enter_Syncfs(fd int) (err error) { + funcref := get_SyncfsAddr() + if funcptrtest(GetZosLibVec()+SYS_SYNCFS<<4, "") == 0 { + *funcref = impl_Syncfs + } else { + *funcref = error_Syncfs + } + return (*funcref)(fd) +} + +func error_Syncfs(fd int) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Times(tms *Tms) (ticks uintptr, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_TIMES<<4, uintptr(unsafe.Pointer(tms))) + runtime.ExitSyscall() + ticks = uintptr(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func W_Getmntent(buff *byte, size int) (lastsys int, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_W_GETMNTENT<<4, uintptr(unsafe.Pointer(buff)), uintptr(size)) + runtime.ExitSyscall() + lastsys = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func W_Getmntent_A(buff *byte, size int) (lastsys int, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___W_GETMNTENT_A<<4, uintptr(unsafe.Pointer(buff)), uintptr(size)) + runtime.ExitSyscall() + lastsys = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func mount_LE(path string, filesystem string, fstype string, mtm uint32, parmlen int32, parm string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(filesystem) + if err != nil { + return + } + var _p2 *byte + _p2, err = BytePtrFromString(fstype) + if err != nil { + return + } + var _p3 *byte + _p3, err = BytePtrFromString(parm) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___MOUNT_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(unsafe.Pointer(_p2)), uintptr(mtm), uintptr(parmlen), uintptr(unsafe.Pointer(_p3))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func unmount_LE(filesystem string, mtm int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(filesystem) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___UMOUNT_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(mtm)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Chroot(path string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___CHROOT_A<<4, uintptr(unsafe.Pointer(_p0))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Select(nmsgsfds int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (ret int, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SELECT<<4, uintptr(nmsgsfds), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout))) + runtime.ExitSyscall() + ret = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Uname(buf *Utsname) (err error) { + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_____OSNAME_A<<4, uintptr(unsafe.Pointer(buf))) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Unshare(flags int) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_UNSHARE<<4, uintptr(flags)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_UnshareAddr() *(func(flags int) (err error)) + +var Unshare = enter_Unshare + +func enter_Unshare(flags int) (err error) { + funcref := get_UnshareAddr() + if funcptrtest(GetZosLibVec()+SYS_UNSHARE<<4, "") == 0 { + *funcref = impl_Unshare + } else { + *funcref = error_Unshare + } + return (*funcref)(flags) +} + +func error_Unshare(flags int) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Gethostname(buf []byte) (err error) { + var _p0 unsafe.Pointer + if len(buf) > 0 { + _p0 = unsafe.Pointer(&buf[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___GETHOSTNAME_A<<4, uintptr(_p0), uintptr(len(buf))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getgid() (gid int) { + r0, _, _ := CallLeFuncWithErr(GetZosLibVec() + SYS_GETGID<<4) + gid = int(r0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getpid() (pid int) { + r0, _, _ := CallLeFuncWithErr(GetZosLibVec() + SYS_GETPID<<4) + pid = int(r0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getpgid(pid int) (pgid int, err error) { + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_GETPGID<<4, uintptr(pid)) + pgid = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getppid() (pid int) { + r0, _, _ := CallLeFuncWithErr(GetZosLibVec() + SYS_GETPPID<<4) + pid = int(r0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getpriority(which int, who int) (prio int, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_GETPRIORITY<<4, uintptr(which), uintptr(who)) + runtime.ExitSyscall() + prio = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getrlimit(resource int, rlim *Rlimit) (err error) { + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_GETRLIMIT<<4, uintptr(resource), uintptr(unsafe.Pointer(rlim))) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func getrusage(who int, rusage *rusage_zos) (err error) { + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_GETRUSAGE<<4, uintptr(who), uintptr(unsafe.Pointer(rusage))) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getegid() (egid int) { + runtime.EnterSyscall() + r0, _, _ := CallLeFuncWithErr(GetZosLibVec() + SYS_GETEGID<<4) + runtime.ExitSyscall() + egid = int(r0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Geteuid() (euid int) { + runtime.EnterSyscall() + r0, _, _ := CallLeFuncWithErr(GetZosLibVec() + SYS_GETEUID<<4) + runtime.ExitSyscall() + euid = int(r0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getsid(pid int) (sid int, err error) { + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_GETSID<<4, uintptr(pid)) + sid = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Getuid() (uid int) { + r0, _, _ := CallLeFuncWithErr(GetZosLibVec() + SYS_GETUID<<4) + uid = int(r0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Kill(pid int, sig Signal) (err error) { + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_KILL<<4, uintptr(pid), uintptr(sig)) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Lchown(path string, uid int, gid int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___LCHOWN_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Link(path string, link string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(link) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___LINK_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Linkat(oldDirFd int, oldPath string, newDirFd int, newPath string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(oldPath) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(newPath) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___LINKAT_A<<4, uintptr(oldDirFd), uintptr(unsafe.Pointer(_p0)), uintptr(newDirFd), uintptr(unsafe.Pointer(_p1)), uintptr(flags)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_LinkatAddr() *(func(oldDirFd int, oldPath string, newDirFd int, newPath string, flags int) (err error)) + +var Linkat = enter_Linkat + +func enter_Linkat(oldDirFd int, oldPath string, newDirFd int, newPath string, flags int) (err error) { + funcref := get_LinkatAddr() + if funcptrtest(GetZosLibVec()+SYS___LINKAT_A<<4, "") == 0 { + *funcref = impl_Linkat + } else { + *funcref = error_Linkat + } + return (*funcref)(oldDirFd, oldPath, newDirFd, newPath, flags) +} + +func error_Linkat(oldDirFd int, oldPath string, newDirFd int, newPath string, flags int) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Listen(s int, n int) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_LISTEN<<4, uintptr(s), uintptr(n)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func lstat(path string, stat *Stat_LE_t) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___LSTAT_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Mkdir(path string, mode uint32) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___MKDIR_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(mode)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Mkdirat(dirfd int, path string, mode uint32) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___MKDIRAT_A<<4, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_MkdiratAddr() *(func(dirfd int, path string, mode uint32) (err error)) + +var Mkdirat = enter_Mkdirat + +func enter_Mkdirat(dirfd int, path string, mode uint32) (err error) { + funcref := get_MkdiratAddr() + if funcptrtest(GetZosLibVec()+SYS___MKDIRAT_A<<4, "") == 0 { + *funcref = impl_Mkdirat + } else { + *funcref = error_Mkdirat + } + return (*funcref)(dirfd, path, mode) +} + +func error_Mkdirat(dirfd int, path string, mode uint32) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Mkfifo(path string, mode uint32) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___MKFIFO_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(mode)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Mknod(path string, mode uint32, dev int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___MKNOD_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Mknodat(dirfd int, path string, mode uint32, dev int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___MKNODAT_A<<4, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_MknodatAddr() *(func(dirfd int, path string, mode uint32, dev int) (err error)) + +var Mknodat = enter_Mknodat + +func enter_Mknodat(dirfd int, path string, mode uint32, dev int) (err error) { + funcref := get_MknodatAddr() + if funcptrtest(GetZosLibVec()+SYS___MKNODAT_A<<4, "") == 0 { + *funcref = impl_Mknodat + } else { + *funcref = error_Mknodat + } + return (*funcref)(dirfd, path, mode, dev) +} + +func error_Mknodat(dirfd int, path string, mode uint32, dev int) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_PivotRoot(newroot string, oldroot string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(newroot) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(oldroot) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___PIVOT_ROOT_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_PivotRootAddr() *(func(newroot string, oldroot string) (err error)) + +var PivotRoot = enter_PivotRoot + +func enter_PivotRoot(newroot string, oldroot string) (err error) { + funcref := get_PivotRootAddr() + if funcptrtest(GetZosLibVec()+SYS___PIVOT_ROOT_A<<4, "") == 0 { + *funcref = impl_PivotRoot + } else { + *funcref = error_PivotRoot + } + return (*funcref)(newroot, oldroot) +} + +func error_PivotRoot(newroot string, oldroot string) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Pread(fd int, p []byte, offset int64) (n int, err error) { + var _p0 unsafe.Pointer + if len(p) > 0 { + _p0 = unsafe.Pointer(&p[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_PREAD<<4, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset)) + runtime.ExitSyscall() + n = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Getpriority(which int, who int) (prio int, err error) { - r0, _, e1 := syscall_syscall(SYS_GETPRIORITY, uintptr(which), uintptr(who), 0) - prio = int(r0) - if e1 != 0 { - err = errnoErr(e1) +func Pwrite(fd int, p []byte, offset int64) (n int, err error) { + var _p0 unsafe.Pointer + if len(p) > 0 { + _p0 = unsafe.Pointer(&p[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_PWRITE<<4, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset)) + runtime.ExitSyscall() + n = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Getrlimit(resource int, rlim *Rlimit) (err error) { - _, _, e1 := syscall_rawsyscall(SYS_GETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0) - if e1 != 0 { - err = errnoErr(e1) +func impl_Prctl(option int, arg2 uintptr, arg3 uintptr, arg4 uintptr, arg5 uintptr) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___PRCTL_A<<4, uintptr(option), uintptr(arg2), uintptr(arg3), uintptr(arg4), uintptr(arg5)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +//go:nosplit +func get_PrctlAddr() *(func(option int, arg2 uintptr, arg3 uintptr, arg4 uintptr, arg5 uintptr) (err error)) -func getrusage(who int, rusage *rusage_zos) (err error) { - _, _, e1 := syscall_rawsyscall(SYS_GETRUSAGE, uintptr(who), uintptr(unsafe.Pointer(rusage)), 0) - if e1 != 0 { - err = errnoErr(e1) +var Prctl = enter_Prctl + +func enter_Prctl(option int, arg2 uintptr, arg3 uintptr, arg4 uintptr, arg5 uintptr) (err error) { + funcref := get_PrctlAddr() + if funcptrtest(GetZosLibVec()+SYS___PRCTL_A<<4, "") == 0 { + *funcref = impl_Prctl + } else { + *funcref = error_Prctl } - return + return (*funcref)(option, arg2, arg3, arg4, arg5) } -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Getsid(pid int) (sid int, err error) { - r0, _, e1 := syscall_rawsyscall(SYS_GETSID, uintptr(pid), 0, 0) - sid = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } +func error_Prctl(option int, arg2 uintptr, arg3 uintptr, arg4 uintptr, arg5 uintptr) (err error) { + err = ENOSYS return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Getuid() (uid int) { - r0, _, _ := syscall_rawsyscall(SYS_GETUID, 0, 0, 0) - uid = int(r0) +func impl_Prlimit(pid int, resource int, newlimit *Rlimit, old *Rlimit) (err error) { + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_PRLIMIT<<4, uintptr(pid), uintptr(resource), uintptr(unsafe.Pointer(newlimit)), uintptr(unsafe.Pointer(old))) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } return } -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +//go:nosplit +func get_PrlimitAddr() *(func(pid int, resource int, newlimit *Rlimit, old *Rlimit) (err error)) -func Kill(pid int, sig Signal) (err error) { - _, _, e1 := syscall_rawsyscall(SYS_KILL, uintptr(pid), uintptr(sig), 0) - if e1 != 0 { - err = errnoErr(e1) +var Prlimit = enter_Prlimit + +func enter_Prlimit(pid int, resource int, newlimit *Rlimit, old *Rlimit) (err error) { + funcref := get_PrlimitAddr() + if funcptrtest(GetZosLibVec()+SYS_PRLIMIT<<4, "") == 0 { + *funcref = impl_Prlimit + } else { + *funcref = error_Prlimit } + return (*funcref)(pid, resource, newlimit, old) +} + +func error_Prlimit(pid int, resource int, newlimit *Rlimit, old *Rlimit) (err error) { + err = ENOSYS return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Lchown(path string, uid int, gid int) (err error) { +func Rename(from string, to string) (err error) { var _p0 *byte - _p0, err = BytePtrFromString(path) + _p0, err = BytePtrFromString(from) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(to) if err != nil { return } - _, _, e1 := syscall_syscall(SYS___LCHOWN_A, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid)) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___RENAME_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Link(path string, link string) (err error) { +func impl_Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) { var _p0 *byte - _p0, err = BytePtrFromString(path) + _p0, err = BytePtrFromString(oldpath) if err != nil { return } var _p1 *byte - _p1, err = BytePtrFromString(link) + _p1, err = BytePtrFromString(newpath) if err != nil { return } - _, _, e1 := syscall_syscall(SYS___LINK_A, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___RENAMEAT_A<<4, uintptr(olddirfd), uintptr(unsafe.Pointer(_p0)), uintptr(newdirfd), uintptr(unsafe.Pointer(_p1))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +//go:nosplit +func get_RenameatAddr() *(func(olddirfd int, oldpath string, newdirfd int, newpath string) (err error)) -func Listen(s int, n int) (err error) { - _, _, e1 := syscall_syscall(SYS_LISTEN, uintptr(s), uintptr(n), 0) - if e1 != 0 { - err = errnoErr(e1) +var Renameat = enter_Renameat + +func enter_Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) { + funcref := get_RenameatAddr() + if funcptrtest(GetZosLibVec()+SYS___RENAMEAT_A<<4, "") == 0 { + *funcref = impl_Renameat + } else { + *funcref = error_Renameat } + return (*funcref)(olddirfd, oldpath, newdirfd, newpath) +} + +func error_Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) { + err = ENOSYS return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func lstat(path string, stat *Stat_LE_t) (err error) { +func impl_Renameat2(olddirfd int, oldpath string, newdirfd int, newpath string, flags uint) (err error) { var _p0 *byte - _p0, err = BytePtrFromString(path) + _p0, err = BytePtrFromString(oldpath) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(newpath) if err != nil { return } - _, _, e1 := syscall_syscall(SYS___LSTAT_A, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___RENAMEAT2_A<<4, uintptr(olddirfd), uintptr(unsafe.Pointer(_p0)), uintptr(newdirfd), uintptr(unsafe.Pointer(_p1)), uintptr(flags)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +//go:nosplit +func get_Renameat2Addr() *(func(olddirfd int, oldpath string, newdirfd int, newpath string, flags uint) (err error)) -func Mkdir(path string, mode uint32) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := syscall_syscall(SYS___MKDIR_A, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) - if e1 != 0 { - err = errnoErr(e1) +var Renameat2 = enter_Renameat2 + +func enter_Renameat2(olddirfd int, oldpath string, newdirfd int, newpath string, flags uint) (err error) { + funcref := get_Renameat2Addr() + if funcptrtest(GetZosLibVec()+SYS___RENAMEAT2_A<<4, "") == 0 { + *funcref = impl_Renameat2 + } else { + *funcref = error_Renameat2 } + return (*funcref)(olddirfd, oldpath, newdirfd, newpath, flags) +} + +func error_Renameat2(olddirfd int, oldpath string, newdirfd int, newpath string, flags uint) (err error) { + err = ENOSYS return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Mkfifo(path string, mode uint32) (err error) { +func Rmdir(path string) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) if err != nil { return } - _, _, e1 := syscall_syscall(SYS___MKFIFO_A, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___RMDIR_A<<4, uintptr(unsafe.Pointer(_p0))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Mknod(path string, mode uint32, dev int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := syscall_syscall(SYS___MKNOD_A, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev)) - if e1 != 0 { - err = errnoErr(e1) +func Seek(fd int, offset int64, whence int) (off int64, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_LSEEK<<4, uintptr(fd), uintptr(offset), uintptr(whence)) + runtime.ExitSyscall() + off = int64(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Pread(fd int, p []byte, offset int64) (n int, err error) { - var _p0 unsafe.Pointer - if len(p) > 0 { - _p0 = unsafe.Pointer(&p[0]) - } else { - _p0 = unsafe.Pointer(&_zero) +func Setegid(egid int) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SETEGID<<4, uintptr(egid)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } - r0, _, e1 := syscall_syscall6(SYS_PREAD, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), 0, 0) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Seteuid(euid int) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SETEUID<<4, uintptr(euid)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Pwrite(fd int, p []byte, offset int64) (n int, err error) { +func impl_Sethostname(p []byte) (err error) { var _p0 unsafe.Pointer if len(p) > 0 { _p0 = unsafe.Pointer(&p[0]) } else { _p0 = unsafe.Pointer(&_zero) } - r0, _, e1 := syscall_syscall6(SYS_PWRITE, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), 0, 0) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___SETHOSTNAME_A<<4, uintptr(_p0), uintptr(len(p))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +//go:nosplit +func get_SethostnameAddr() *(func(p []byte) (err error)) -func Readlink(path string, buf []byte) (n int, err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - var _p1 unsafe.Pointer - if len(buf) > 0 { - _p1 = unsafe.Pointer(&buf[0]) +var Sethostname = enter_Sethostname + +func enter_Sethostname(p []byte) (err error) { + funcref := get_SethostnameAddr() + if funcptrtest(GetZosLibVec()+SYS___SETHOSTNAME_A<<4, "") == 0 { + *funcref = impl_Sethostname } else { - _p1 = unsafe.Pointer(&_zero) + *funcref = error_Sethostname } - r0, _, e1 := syscall_syscall(SYS___READLINK_A, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf))) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return + return (*funcref)(p) } -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Rename(from string, to string) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(from) - if err != nil { - return - } - var _p1 *byte - _p1, err = BytePtrFromString(to) - if err != nil { - return - } - _, _, e1 := syscall_syscall(SYS___RENAME_A, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) - if e1 != 0 { - err = errnoErr(e1) - } +func error_Sethostname(p []byte) (err error) { + err = ENOSYS return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Rmdir(path string) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := syscall_syscall(SYS___RMDIR_A, uintptr(unsafe.Pointer(_p0)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) +func impl_Setns(fd int, nstype int) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SETNS<<4, uintptr(fd), uintptr(nstype)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +//go:nosplit +func get_SetnsAddr() *(func(fd int, nstype int) (err error)) -func Seek(fd int, offset int64, whence int) (off int64, err error) { - r0, _, e1 := syscall_syscall(SYS_LSEEK, uintptr(fd), uintptr(offset), uintptr(whence)) - off = int64(r0) - if e1 != 0 { - err = errnoErr(e1) +var Setns = enter_Setns + +func enter_Setns(fd int, nstype int) (err error) { + funcref := get_SetnsAddr() + if funcptrtest(GetZosLibVec()+SYS_SETNS<<4, "") == 0 { + *funcref = impl_Setns + } else { + *funcref = error_Setns } + return (*funcref)(fd, nstype) +} + +func error_Setns(fd int, nstype int) (err error) { + err = ENOSYS return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setpriority(which int, who int, prio int) (err error) { - _, _, e1 := syscall_syscall(SYS_SETPRIORITY, uintptr(which), uintptr(who), uintptr(prio)) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SETPRIORITY<<4, uintptr(which), uintptr(who), uintptr(prio)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -971,9 +2910,9 @@ func Setpriority(which int, who int, prio int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setpgid(pid int, pgid int) (err error) { - _, _, e1 := syscall_rawsyscall(SYS_SETPGID, uintptr(pid), uintptr(pgid), 0) - if e1 != 0 { - err = errnoErr(e1) + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SETPGID<<4, uintptr(pid), uintptr(pgid)) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -981,9 +2920,9 @@ func Setpgid(pid int, pgid int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setrlimit(resource int, lim *Rlimit) (err error) { - _, _, e1 := syscall_rawsyscall(SYS_SETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(lim)), 0) - if e1 != 0 { - err = errnoErr(e1) + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SETRLIMIT<<4, uintptr(resource), uintptr(unsafe.Pointer(lim))) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -991,9 +2930,9 @@ func Setrlimit(resource int, lim *Rlimit) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setregid(rgid int, egid int) (err error) { - _, _, e1 := syscall_rawsyscall(SYS_SETREGID, uintptr(rgid), uintptr(egid), 0) - if e1 != 0 { - err = errnoErr(e1) + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SETREGID<<4, uintptr(rgid), uintptr(egid)) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -1001,9 +2940,9 @@ func Setregid(rgid int, egid int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setreuid(ruid int, euid int) (err error) { - _, _, e1 := syscall_rawsyscall(SYS_SETREUID, uintptr(ruid), uintptr(euid), 0) - if e1 != 0 { - err = errnoErr(e1) + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SETREUID<<4, uintptr(ruid), uintptr(euid)) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -1011,10 +2950,10 @@ func Setreuid(ruid int, euid int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setsid() (pid int, err error) { - r0, _, e1 := syscall_rawsyscall(SYS_SETSID, 0, 0, 0) + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec() + SYS_SETSID<<4) pid = int(r0) - if e1 != 0 { - err = errnoErr(e1) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -1022,9 +2961,11 @@ func Setsid() (pid int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setuid(uid int) (err error) { - _, _, e1 := syscall_syscall(SYS_SETUID, uintptr(uid), 0, 0) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SETUID<<4, uintptr(uid)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -1032,9 +2973,11 @@ func Setuid(uid int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setgid(uid int) (err error) { - _, _, e1 := syscall_syscall(SYS_SETGID, uintptr(uid), 0, 0) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SETGID<<4, uintptr(uid)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -1042,9 +2985,11 @@ func Setgid(uid int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Shutdown(fd int, how int) (err error) { - _, _, e1 := syscall_syscall(SYS_SHUTDOWN, uintptr(fd), uintptr(how), 0) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SHUTDOWN<<4, uintptr(fd), uintptr(how)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -1057,9 +3002,11 @@ func stat(path string, statLE *Stat_LE_t) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(SYS___STAT_A, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(statLE)), 0) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___STAT_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(statLE))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -1077,17 +3024,63 @@ func Symlink(path string, link string) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(SYS___SYMLINK_A, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___SYMLINK_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Symlinkat(oldPath string, dirfd int, newPath string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(oldPath) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(newPath) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___SYMLINKAT_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(dirfd), uintptr(unsafe.Pointer(_p1))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } +//go:nosplit +func get_SymlinkatAddr() *(func(oldPath string, dirfd int, newPath string) (err error)) + +var Symlinkat = enter_Symlinkat + +func enter_Symlinkat(oldPath string, dirfd int, newPath string) (err error) { + funcref := get_SymlinkatAddr() + if funcptrtest(GetZosLibVec()+SYS___SYMLINKAT_A<<4, "") == 0 { + *funcref = impl_Symlinkat + } else { + *funcref = error_Symlinkat + } + return (*funcref)(oldPath, dirfd, newPath) +} + +func error_Symlinkat(oldPath string, dirfd int, newPath string) (err error) { + err = ENOSYS + return +} + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Sync() { - syscall_syscall(SYS_SYNC, 0, 0, 0) + runtime.EnterSyscall() + CallLeFuncWithErr(GetZosLibVec() + SYS_SYNC<<4) + runtime.ExitSyscall() return } @@ -1099,9 +3092,11 @@ func Truncate(path string, length int64) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(SYS___TRUNCATE_A, uintptr(unsafe.Pointer(_p0)), uintptr(length), 0) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___TRUNCATE_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(length)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -1109,9 +3104,11 @@ func Truncate(path string, length int64) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Tcgetattr(fildes int, termptr *Termios) (err error) { - _, _, e1 := syscall_syscall(SYS_TCGETATTR, uintptr(fildes), uintptr(unsafe.Pointer(termptr)), 0) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_TCGETATTR<<4, uintptr(fildes), uintptr(unsafe.Pointer(termptr))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -1119,9 +3116,11 @@ func Tcgetattr(fildes int, termptr *Termios) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Tcsetattr(fildes int, when int, termptr *Termios) (err error) { - _, _, e1 := syscall_syscall(SYS_TCSETATTR, uintptr(fildes), uintptr(when), uintptr(unsafe.Pointer(termptr))) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_TCSETATTR<<4, uintptr(fildes), uintptr(when), uintptr(unsafe.Pointer(termptr))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -1129,7 +3128,9 @@ func Tcsetattr(fildes int, when int, termptr *Termios) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Umask(mask int) (oldmask int) { - r0, _, _ := syscall_syscall(SYS_UMASK, uintptr(mask), 0, 0) + runtime.EnterSyscall() + r0, _, _ := CallLeFuncWithErr(GetZosLibVec()+SYS_UMASK<<4, uintptr(mask)) + runtime.ExitSyscall() oldmask = int(r0) return } @@ -1142,10 +3143,49 @@ func Unlink(path string) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(SYS___UNLINK_A, uintptr(unsafe.Pointer(_p0)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___UNLINK_A<<4, uintptr(unsafe.Pointer(_p0))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Unlinkat(dirfd int, path string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___UNLINKAT_A<<4, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_UnlinkatAddr() *(func(dirfd int, path string, flags int) (err error)) + +var Unlinkat = enter_Unlinkat + +func enter_Unlinkat(dirfd int, path string, flags int) (err error) { + funcref := get_UnlinkatAddr() + if funcptrtest(GetZosLibVec()+SYS___UNLINKAT_A<<4, "") == 0 { + *funcref = impl_Unlinkat + } else { + *funcref = error_Unlinkat } + return (*funcref)(dirfd, path, flags) +} + +func error_Unlinkat(dirfd int, path string, flags int) (err error) { + err = ENOSYS return } @@ -1157,9 +3197,11 @@ func Utime(path string, utim *Utimbuf) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(SYS___UTIME_A, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(utim)), 0) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___UTIME_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(utim))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -1172,11 +3214,91 @@ func open(path string, mode int, perm uint32) (fd int, err error) { if err != nil { return } - r0, _, e1 := syscall_syscall(SYS___OPEN_A, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm)) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___OPEN_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm)) + runtime.ExitSyscall() + fd = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___OPENAT_A<<4, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags), uintptr(mode)) + runtime.ExitSyscall() + fd = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_openatAddr() *(func(dirfd int, path string, flags int, mode uint32) (fd int, err error)) + +var openat = enter_openat + +func enter_openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) { + funcref := get_openatAddr() + if funcptrtest(GetZosLibVec()+SYS___OPENAT_A<<4, "") == 0 { + *funcref = impl_openat + } else { + *funcref = error_openat + } + return (*funcref)(dirfd, path, flags, mode) +} + +func error_openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) { + fd = -1 + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_openat2(dirfd int, path string, open_how *OpenHow, size int) (fd int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___OPENAT2_A<<4, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(open_how)), uintptr(size)) + runtime.ExitSyscall() fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_openat2Addr() *(func(dirfd int, path string, open_how *OpenHow, size int) (fd int, err error)) + +var openat2 = enter_openat2 + +func enter_openat2(dirfd int, path string, open_how *OpenHow, size int) (fd int, err error) { + funcref := get_openat2Addr() + if funcptrtest(GetZosLibVec()+SYS___OPENAT2_A<<4, "") == 0 { + *funcref = impl_openat2 + } else { + *funcref = error_openat2 } + return (*funcref)(dirfd, path, open_how, size) +} + +func error_openat2(dirfd int, path string, open_how *OpenHow, size int) (fd int, err error) { + fd = -1 + err = ENOSYS return } @@ -1188,9 +3310,23 @@ func remove(path string) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(SYS_REMOVE, uintptr(unsafe.Pointer(_p0)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_REMOVE<<4, uintptr(unsafe.Pointer(_p0))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func waitid(idType int, id int, info *Siginfo, options int) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_WAITID<<4, uintptr(idType), uintptr(id), uintptr(unsafe.Pointer(info)), uintptr(options)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -1198,10 +3334,12 @@ func remove(path string) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func waitpid(pid int, wstatus *_C_int, options int) (wpid int, err error) { - r0, _, e1 := syscall_syscall(SYS_WAITPID, uintptr(pid), uintptr(unsafe.Pointer(wstatus)), uintptr(options)) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_WAITPID<<4, uintptr(pid), uintptr(unsafe.Pointer(wstatus)), uintptr(options)) + runtime.ExitSyscall() wpid = int(r0) - if e1 != 0 { - err = errnoErr(e1) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -1209,9 +3347,9 @@ func waitpid(pid int, wstatus *_C_int, options int) (wpid int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func gettimeofday(tv *timeval_zos) (err error) { - _, _, e1 := syscall_rawsyscall(SYS_GETTIMEOFDAY, uintptr(unsafe.Pointer(tv)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_GETTIMEOFDAY<<4, uintptr(unsafe.Pointer(tv))) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -1219,9 +3357,9 @@ func gettimeofday(tv *timeval_zos) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func pipe(p *[2]_C_int) (err error) { - _, _, e1 := syscall_rawsyscall(SYS_PIPE, uintptr(unsafe.Pointer(p)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_PIPE<<4, uintptr(unsafe.Pointer(p))) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -1234,20 +3372,87 @@ func utimes(path string, timeval *[2]Timeval) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(SYS___UTIMES_A, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(timeval)), 0) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___UTIMES_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(timeval))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Select(nmsgsfds int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (ret int, err error) { - r0, _, e1 := syscall_syscall6(SYS_SELECT, uintptr(nmsgsfds), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) - ret = int(r0) - if e1 != 0 { - err = errnoErr(e1) +func impl_utimensat(dirfd int, path string, ts *[2]Timespec, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___UTIMENSAT_A<<4, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(ts)), uintptr(flags)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_utimensatAddr() *(func(dirfd int, path string, ts *[2]Timespec, flags int) (err error)) + +var utimensat = enter_utimensat + +func enter_utimensat(dirfd int, path string, ts *[2]Timespec, flags int) (err error) { + funcref := get_utimensatAddr() + if funcptrtest(GetZosLibVec()+SYS___UTIMENSAT_A<<4, "") == 0 { + *funcref = impl_utimensat + } else { + *funcref = error_utimensat + } + return (*funcref)(dirfd, path, ts, flags) +} + +func error_utimensat(dirfd int, path string, ts *[2]Timespec, flags int) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Posix_openpt(oflag int) (fd int, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_POSIX_OPENPT<<4, uintptr(oflag)) + runtime.ExitSyscall() + fd = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Grantpt(fildes int) (rc int, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_GRANTPT<<4, uintptr(fildes)) + runtime.ExitSyscall() + rc = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Unlockpt(fildes int) (rc int, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_UNLOCKPT<<4, uintptr(fildes)) + runtime.ExitSyscall() + rc = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go index 0cc3ce496..524b0820c 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go @@ -452,4 +452,10 @@ const ( SYS_FUTEX_WAKE = 454 SYS_FUTEX_WAIT = 455 SYS_FUTEX_REQUEUE = 456 + SYS_STATMOUNT = 457 + SYS_LISTMOUNT = 458 + SYS_LSM_GET_SELF_ATTR = 459 + SYS_LSM_SET_SELF_ATTR = 460 + SYS_LSM_LIST_MODULES = 461 + SYS_MSEAL = 462 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go index 856d92d69..f485dbf45 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go @@ -341,6 +341,7 @@ const ( SYS_STATX = 332 SYS_IO_PGETEVENTS = 333 SYS_RSEQ = 334 + SYS_URETPROBE = 335 SYS_PIDFD_SEND_SIGNAL = 424 SYS_IO_URING_SETUP = 425 SYS_IO_URING_ENTER = 426 @@ -374,4 +375,10 @@ const ( SYS_FUTEX_WAKE = 454 SYS_FUTEX_WAIT = 455 SYS_FUTEX_REQUEUE = 456 + SYS_STATMOUNT = 457 + SYS_LISTMOUNT = 458 + SYS_LSM_GET_SELF_ATTR = 459 + SYS_LSM_SET_SELF_ATTR = 460 + SYS_LSM_LIST_MODULES = 461 + SYS_MSEAL = 462 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go index 8d467094c..70b35bf3b 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go @@ -416,4 +416,10 @@ const ( SYS_FUTEX_WAKE = 454 SYS_FUTEX_WAIT = 455 SYS_FUTEX_REQUEUE = 456 + SYS_STATMOUNT = 457 + SYS_LISTMOUNT = 458 + SYS_LSM_GET_SELF_ATTR = 459 + SYS_LSM_SET_SELF_ATTR = 460 + SYS_LSM_LIST_MODULES = 461 + SYS_MSEAL = 462 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go index edc173244..1893e2fe8 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go @@ -85,7 +85,7 @@ const ( SYS_SPLICE = 76 SYS_TEE = 77 SYS_READLINKAT = 78 - SYS_FSTATAT = 79 + SYS_NEWFSTATAT = 79 SYS_FSTAT = 80 SYS_SYNC = 81 SYS_FSYNC = 82 @@ -319,4 +319,10 @@ const ( SYS_FUTEX_WAKE = 454 SYS_FUTEX_WAIT = 455 SYS_FUTEX_REQUEUE = 456 + SYS_STATMOUNT = 457 + SYS_LISTMOUNT = 458 + SYS_LSM_GET_SELF_ATTR = 459 + SYS_LSM_SET_SELF_ATTR = 460 + SYS_LSM_LIST_MODULES = 461 + SYS_MSEAL = 462 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_loong64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_loong64.go index 445eba206..16a4017da 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_loong64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_loong64.go @@ -84,6 +84,8 @@ const ( SYS_SPLICE = 76 SYS_TEE = 77 SYS_READLINKAT = 78 + SYS_NEWFSTATAT = 79 + SYS_FSTAT = 80 SYS_SYNC = 81 SYS_FSYNC = 82 SYS_FDATASYNC = 83 @@ -313,4 +315,10 @@ const ( SYS_FUTEX_WAKE = 454 SYS_FUTEX_WAIT = 455 SYS_FUTEX_REQUEUE = 456 + SYS_STATMOUNT = 457 + SYS_LISTMOUNT = 458 + SYS_LSM_GET_SELF_ATTR = 459 + SYS_LSM_SET_SELF_ATTR = 460 + SYS_LSM_LIST_MODULES = 461 + SYS_MSEAL = 462 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go index adba01bca..7e567f1ef 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go @@ -436,4 +436,10 @@ const ( SYS_FUTEX_WAKE = 4454 SYS_FUTEX_WAIT = 4455 SYS_FUTEX_REQUEUE = 4456 + SYS_STATMOUNT = 4457 + SYS_LISTMOUNT = 4458 + SYS_LSM_GET_SELF_ATTR = 4459 + SYS_LSM_SET_SELF_ATTR = 4460 + SYS_LSM_LIST_MODULES = 4461 + SYS_MSEAL = 4462 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go index 014c4e9c7..38ae55e5e 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go @@ -366,4 +366,10 @@ const ( SYS_FUTEX_WAKE = 5454 SYS_FUTEX_WAIT = 5455 SYS_FUTEX_REQUEUE = 5456 + SYS_STATMOUNT = 5457 + SYS_LISTMOUNT = 5458 + SYS_LSM_GET_SELF_ATTR = 5459 + SYS_LSM_SET_SELF_ATTR = 5460 + SYS_LSM_LIST_MODULES = 5461 + SYS_MSEAL = 5462 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go index ccc97d74d..55e92e60a 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go @@ -366,4 +366,10 @@ const ( SYS_FUTEX_WAKE = 5454 SYS_FUTEX_WAIT = 5455 SYS_FUTEX_REQUEUE = 5456 + SYS_STATMOUNT = 5457 + SYS_LISTMOUNT = 5458 + SYS_LSM_GET_SELF_ATTR = 5459 + SYS_LSM_SET_SELF_ATTR = 5460 + SYS_LSM_LIST_MODULES = 5461 + SYS_MSEAL = 5462 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go index ec2b64a95..60658d6a0 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go @@ -436,4 +436,10 @@ const ( SYS_FUTEX_WAKE = 4454 SYS_FUTEX_WAIT = 4455 SYS_FUTEX_REQUEUE = 4456 + SYS_STATMOUNT = 4457 + SYS_LISTMOUNT = 4458 + SYS_LSM_GET_SELF_ATTR = 4459 + SYS_LSM_SET_SELF_ATTR = 4460 + SYS_LSM_LIST_MODULES = 4461 + SYS_MSEAL = 4462 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go index 21a839e33..e203e8a7e 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go @@ -443,4 +443,10 @@ const ( SYS_FUTEX_WAKE = 454 SYS_FUTEX_WAIT = 455 SYS_FUTEX_REQUEUE = 456 + SYS_STATMOUNT = 457 + SYS_LISTMOUNT = 458 + SYS_LSM_GET_SELF_ATTR = 459 + SYS_LSM_SET_SELF_ATTR = 460 + SYS_LSM_LIST_MODULES = 461 + SYS_MSEAL = 462 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go index c11121ec3..5944b97d5 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go @@ -415,4 +415,10 @@ const ( SYS_FUTEX_WAKE = 454 SYS_FUTEX_WAIT = 455 SYS_FUTEX_REQUEUE = 456 + SYS_STATMOUNT = 457 + SYS_LISTMOUNT = 458 + SYS_LSM_GET_SELF_ATTR = 459 + SYS_LSM_SET_SELF_ATTR = 460 + SYS_LSM_LIST_MODULES = 461 + SYS_MSEAL = 462 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go index 909b631fc..c66d416da 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go @@ -415,4 +415,10 @@ const ( SYS_FUTEX_WAKE = 454 SYS_FUTEX_WAIT = 455 SYS_FUTEX_REQUEUE = 456 + SYS_STATMOUNT = 457 + SYS_LISTMOUNT = 458 + SYS_LSM_GET_SELF_ATTR = 459 + SYS_LSM_SET_SELF_ATTR = 460 + SYS_LSM_LIST_MODULES = 461 + SYS_MSEAL = 462 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go index e49bed16e..a5459e766 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go @@ -84,7 +84,7 @@ const ( SYS_SPLICE = 76 SYS_TEE = 77 SYS_READLINKAT = 78 - SYS_FSTATAT = 79 + SYS_NEWFSTATAT = 79 SYS_FSTAT = 80 SYS_SYNC = 81 SYS_FSYNC = 82 @@ -320,4 +320,10 @@ const ( SYS_FUTEX_WAKE = 454 SYS_FUTEX_WAIT = 455 SYS_FUTEX_REQUEUE = 456 + SYS_STATMOUNT = 457 + SYS_LISTMOUNT = 458 + SYS_LSM_GET_SELF_ATTR = 459 + SYS_LSM_SET_SELF_ATTR = 460 + SYS_LSM_LIST_MODULES = 461 + SYS_MSEAL = 462 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go index 66017d2d3..01d86825b 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go @@ -381,4 +381,10 @@ const ( SYS_FUTEX_WAKE = 454 SYS_FUTEX_WAIT = 455 SYS_FUTEX_REQUEUE = 456 + SYS_STATMOUNT = 457 + SYS_LISTMOUNT = 458 + SYS_LSM_GET_SELF_ATTR = 459 + SYS_LSM_SET_SELF_ATTR = 460 + SYS_LSM_LIST_MODULES = 461 + SYS_MSEAL = 462 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go b/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go index 47bab18dc..7b703e77c 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go @@ -394,4 +394,10 @@ const ( SYS_FUTEX_WAKE = 454 SYS_FUTEX_WAIT = 455 SYS_FUTEX_REQUEUE = 456 + SYS_STATMOUNT = 457 + SYS_LISTMOUNT = 458 + SYS_LSM_GET_SELF_ATTR = 459 + SYS_LSM_SET_SELF_ATTR = 460 + SYS_LSM_LIST_MODULES = 461 + SYS_MSEAL = 462 ) diff --git a/vendor/golang.org/x/sys/unix/zsysnum_zos_s390x.go b/vendor/golang.org/x/sys/unix/zsysnum_zos_s390x.go index b2e308581..5e8c263ca 100644 --- a/vendor/golang.org/x/sys/unix/zsysnum_zos_s390x.go +++ b/vendor/golang.org/x/sys/unix/zsysnum_zos_s390x.go @@ -1,2669 +1,2852 @@ -// Copyright 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. +// go run mksyscall_zos_s390x.go -o_sysnum zsysnum_zos_s390x.go -o_syscall zsyscall_zos_s390x.go -i_syscall syscall_zos_s390x.go -o_asm zsymaddr_zos_s390x.s +// Code generated by the command above; see README.md. DO NOT EDIT. //go:build zos && s390x package unix -// TODO: auto-generate. - const ( - SYS_ACOSD128 = 0xB80 - SYS_ACOSD32 = 0xB7E - SYS_ACOSD64 = 0xB7F - SYS_ACOSHD128 = 0xB83 - SYS_ACOSHD32 = 0xB81 - SYS_ACOSHD64 = 0xB82 - SYS_AIO_FSYNC = 0xC69 - SYS_ASCTIME = 0x0AE - SYS_ASCTIME64 = 0xCD7 - SYS_ASCTIME64_R = 0xCD8 - SYS_ASIND128 = 0xB86 - SYS_ASIND32 = 0xB84 - SYS_ASIND64 = 0xB85 - SYS_ASINHD128 = 0xB89 - SYS_ASINHD32 = 0xB87 - SYS_ASINHD64 = 0xB88 - SYS_ATAN2D128 = 0xB8F - SYS_ATAN2D32 = 0xB8D - SYS_ATAN2D64 = 0xB8E - SYS_ATAND128 = 0xB8C - SYS_ATAND32 = 0xB8A - SYS_ATAND64 = 0xB8B - SYS_ATANHD128 = 0xB92 - SYS_ATANHD32 = 0xB90 - SYS_ATANHD64 = 0xB91 - SYS_BIND2ADDRSEL = 0xD59 - SYS_C16RTOMB = 0xD40 - SYS_C32RTOMB = 0xD41 - SYS_CBRTD128 = 0xB95 - SYS_CBRTD32 = 0xB93 - SYS_CBRTD64 = 0xB94 - SYS_CEILD128 = 0xB98 - SYS_CEILD32 = 0xB96 - SYS_CEILD64 = 0xB97 - SYS_CLEARENV = 0x0C9 - SYS_CLEARERR_UNLOCKED = 0xCA1 - SYS_CLOCK = 0x0AA - SYS_CLOGL = 0xA00 - SYS_CLRMEMF = 0x0BD - SYS_CONJ = 0xA03 - SYS_CONJF = 0xA06 - SYS_CONJL = 0xA09 - SYS_COPYSIGND128 = 0xB9E - SYS_COPYSIGND32 = 0xB9C - SYS_COPYSIGND64 = 0xB9D - SYS_COSD128 = 0xBA1 - SYS_COSD32 = 0xB9F - SYS_COSD64 = 0xBA0 - SYS_COSHD128 = 0xBA4 - SYS_COSHD32 = 0xBA2 - SYS_COSHD64 = 0xBA3 - SYS_CPOW = 0xA0C - SYS_CPOWF = 0xA0F - SYS_CPOWL = 0xA12 - SYS_CPROJ = 0xA15 - SYS_CPROJF = 0xA18 - SYS_CPROJL = 0xA1B - SYS_CREAL = 0xA1E - SYS_CREALF = 0xA21 - SYS_CREALL = 0xA24 - SYS_CSIN = 0xA27 - SYS_CSINF = 0xA2A - SYS_CSINH = 0xA30 - SYS_CSINHF = 0xA33 - SYS_CSINHL = 0xA36 - SYS_CSINL = 0xA2D - SYS_CSNAP = 0x0C5 - SYS_CSQRT = 0xA39 - SYS_CSQRTF = 0xA3C - SYS_CSQRTL = 0xA3F - SYS_CTAN = 0xA42 - SYS_CTANF = 0xA45 - SYS_CTANH = 0xA4B - SYS_CTANHF = 0xA4E - SYS_CTANHL = 0xA51 - SYS_CTANL = 0xA48 - SYS_CTIME = 0x0AB - SYS_CTIME64 = 0xCD9 - SYS_CTIME64_R = 0xCDA - SYS_CTRACE = 0x0C6 - SYS_DIFFTIME = 0x0A7 - SYS_DIFFTIME64 = 0xCDB - SYS_DLADDR = 0xC82 - SYS_DYNALLOC = 0x0C3 - SYS_DYNFREE = 0x0C2 - SYS_ERFCD128 = 0xBAA - SYS_ERFCD32 = 0xBA8 - SYS_ERFCD64 = 0xBA9 - SYS_ERFD128 = 0xBA7 - SYS_ERFD32 = 0xBA5 - SYS_ERFD64 = 0xBA6 - SYS_EXP2D128 = 0xBB0 - SYS_EXP2D32 = 0xBAE - SYS_EXP2D64 = 0xBAF - SYS_EXPD128 = 0xBAD - SYS_EXPD32 = 0xBAB - SYS_EXPD64 = 0xBAC - SYS_EXPM1D128 = 0xBB3 - SYS_EXPM1D32 = 0xBB1 - SYS_EXPM1D64 = 0xBB2 - SYS_FABSD128 = 0xBB6 - SYS_FABSD32 = 0xBB4 - SYS_FABSD64 = 0xBB5 - SYS_FDELREC_UNLOCKED = 0xCA2 - SYS_FDIMD128 = 0xBB9 - SYS_FDIMD32 = 0xBB7 - SYS_FDIMD64 = 0xBB8 - SYS_FDOPEN_UNLOCKED = 0xCFC - SYS_FECLEAREXCEPT = 0xAEA - SYS_FEGETENV = 0xAEB - SYS_FEGETEXCEPTFLAG = 0xAEC - SYS_FEGETROUND = 0xAED - SYS_FEHOLDEXCEPT = 0xAEE - SYS_FEOF_UNLOCKED = 0xCA3 - SYS_FERAISEEXCEPT = 0xAEF - SYS_FERROR_UNLOCKED = 0xCA4 - SYS_FESETENV = 0xAF0 - SYS_FESETEXCEPTFLAG = 0xAF1 - SYS_FESETROUND = 0xAF2 - SYS_FETCHEP = 0x0BF - SYS_FETESTEXCEPT = 0xAF3 - SYS_FEUPDATEENV = 0xAF4 - SYS_FE_DEC_GETROUND = 0xBBA - SYS_FE_DEC_SETROUND = 0xBBB - SYS_FFLUSH_UNLOCKED = 0xCA5 - SYS_FGETC_UNLOCKED = 0xC80 - SYS_FGETPOS64 = 0xCEE - SYS_FGETPOS64_UNLOCKED = 0xCF4 - SYS_FGETPOS_UNLOCKED = 0xCA6 - SYS_FGETS_UNLOCKED = 0xC7C - SYS_FGETWC_UNLOCKED = 0xCA7 - SYS_FGETWS_UNLOCKED = 0xCA8 - SYS_FILENO_UNLOCKED = 0xCA9 - SYS_FLDATA = 0x0C1 - SYS_FLDATA_UNLOCKED = 0xCAA - SYS_FLOCATE_UNLOCKED = 0xCAB - SYS_FLOORD128 = 0xBBE - SYS_FLOORD32 = 0xBBC - SYS_FLOORD64 = 0xBBD - SYS_FMA = 0xA63 - SYS_FMAD128 = 0xBC1 - SYS_FMAD32 = 0xBBF - SYS_FMAD64 = 0xBC0 - SYS_FMAF = 0xA66 - SYS_FMAL = 0xA69 - SYS_FMAX = 0xA6C - SYS_FMAXD128 = 0xBC4 - SYS_FMAXD32 = 0xBC2 - SYS_FMAXD64 = 0xBC3 - SYS_FMAXF = 0xA6F - SYS_FMAXL = 0xA72 - SYS_FMIN = 0xA75 - SYS_FMIND128 = 0xBC7 - SYS_FMIND32 = 0xBC5 - SYS_FMIND64 = 0xBC6 - SYS_FMINF = 0xA78 - SYS_FMINL = 0xA7B - SYS_FMODD128 = 0xBCA - SYS_FMODD32 = 0xBC8 - SYS_FMODD64 = 0xBC9 - SYS_FOPEN64 = 0xD49 - SYS_FOPEN64_UNLOCKED = 0xD4A - SYS_FOPEN_UNLOCKED = 0xCFA - SYS_FPRINTF_UNLOCKED = 0xCAC - SYS_FPUTC_UNLOCKED = 0xC81 - SYS_FPUTS_UNLOCKED = 0xC7E - SYS_FPUTWC_UNLOCKED = 0xCAD - SYS_FPUTWS_UNLOCKED = 0xCAE - SYS_FREAD_NOUPDATE = 0xCEC - SYS_FREAD_NOUPDATE_UNLOCKED = 0xCED - SYS_FREAD_UNLOCKED = 0xC7B - SYS_FREEIFADDRS = 0xCE6 - SYS_FREOPEN64 = 0xD4B - SYS_FREOPEN64_UNLOCKED = 0xD4C - SYS_FREOPEN_UNLOCKED = 0xCFB - SYS_FREXPD128 = 0xBCE - SYS_FREXPD32 = 0xBCC - SYS_FREXPD64 = 0xBCD - SYS_FSCANF_UNLOCKED = 0xCAF - SYS_FSEEK64 = 0xCEF - SYS_FSEEK64_UNLOCKED = 0xCF5 - SYS_FSEEKO64 = 0xCF0 - SYS_FSEEKO64_UNLOCKED = 0xCF6 - SYS_FSEEKO_UNLOCKED = 0xCB1 - SYS_FSEEK_UNLOCKED = 0xCB0 - SYS_FSETPOS64 = 0xCF1 - SYS_FSETPOS64_UNLOCKED = 0xCF7 - SYS_FSETPOS_UNLOCKED = 0xCB3 - SYS_FTELL64 = 0xCF2 - SYS_FTELL64_UNLOCKED = 0xCF8 - SYS_FTELLO64 = 0xCF3 - SYS_FTELLO64_UNLOCKED = 0xCF9 - SYS_FTELLO_UNLOCKED = 0xCB5 - SYS_FTELL_UNLOCKED = 0xCB4 - SYS_FUPDATE = 0x0B5 - SYS_FUPDATE_UNLOCKED = 0xCB7 - SYS_FWIDE_UNLOCKED = 0xCB8 - SYS_FWPRINTF_UNLOCKED = 0xCB9 - SYS_FWRITE_UNLOCKED = 0xC7A - SYS_FWSCANF_UNLOCKED = 0xCBA - SYS_GETDATE64 = 0xD4F - SYS_GETIFADDRS = 0xCE7 - SYS_GETIPV4SOURCEFILTER = 0xC77 - SYS_GETSOURCEFILTER = 0xC79 - SYS_GETSYNTX = 0x0FD - SYS_GETS_UNLOCKED = 0xC7D - SYS_GETTIMEOFDAY64 = 0xD50 - SYS_GETWCHAR_UNLOCKED = 0xCBC - SYS_GETWC_UNLOCKED = 0xCBB - SYS_GMTIME = 0x0B0 - SYS_GMTIME64 = 0xCDC - SYS_GMTIME64_R = 0xCDD - SYS_HYPOTD128 = 0xBD1 - SYS_HYPOTD32 = 0xBCF - SYS_HYPOTD64 = 0xBD0 - SYS_ILOGBD128 = 0xBD4 - SYS_ILOGBD32 = 0xBD2 - SYS_ILOGBD64 = 0xBD3 - SYS_ILOGBF = 0xA7E - SYS_ILOGBL = 0xA81 - SYS_INET6_IS_SRCADDR = 0xD5A - SYS_ISBLANK = 0x0FE - SYS_ISWALNUM = 0x0FF - SYS_LDEXPD128 = 0xBD7 - SYS_LDEXPD32 = 0xBD5 - SYS_LDEXPD64 = 0xBD6 - SYS_LGAMMAD128 = 0xBDA - SYS_LGAMMAD32 = 0xBD8 - SYS_LGAMMAD64 = 0xBD9 - SYS_LIO_LISTIO = 0xC6A - SYS_LLRINT = 0xA84 - SYS_LLRINTD128 = 0xBDD - SYS_LLRINTD32 = 0xBDB - SYS_LLRINTD64 = 0xBDC - SYS_LLRINTF = 0xA87 - SYS_LLRINTL = 0xA8A - SYS_LLROUND = 0xA8D - SYS_LLROUNDD128 = 0xBE0 - SYS_LLROUNDD32 = 0xBDE - SYS_LLROUNDD64 = 0xBDF - SYS_LLROUNDF = 0xA90 - SYS_LLROUNDL = 0xA93 - SYS_LOCALTIM = 0x0B1 - SYS_LOCALTIME = 0x0B1 - SYS_LOCALTIME64 = 0xCDE - SYS_LOCALTIME64_R = 0xCDF - SYS_LOG10D128 = 0xBE6 - SYS_LOG10D32 = 0xBE4 - SYS_LOG10D64 = 0xBE5 - SYS_LOG1PD128 = 0xBE9 - SYS_LOG1PD32 = 0xBE7 - SYS_LOG1PD64 = 0xBE8 - SYS_LOG2D128 = 0xBEC - SYS_LOG2D32 = 0xBEA - SYS_LOG2D64 = 0xBEB - SYS_LOGBD128 = 0xBEF - SYS_LOGBD32 = 0xBED - SYS_LOGBD64 = 0xBEE - SYS_LOGBF = 0xA96 - SYS_LOGBL = 0xA99 - SYS_LOGD128 = 0xBE3 - SYS_LOGD32 = 0xBE1 - SYS_LOGD64 = 0xBE2 - SYS_LRINT = 0xA9C - SYS_LRINTD128 = 0xBF2 - SYS_LRINTD32 = 0xBF0 - SYS_LRINTD64 = 0xBF1 - SYS_LRINTF = 0xA9F - SYS_LRINTL = 0xAA2 - SYS_LROUNDD128 = 0xBF5 - SYS_LROUNDD32 = 0xBF3 - SYS_LROUNDD64 = 0xBF4 - SYS_LROUNDL = 0xAA5 - SYS_MBLEN = 0x0AF - SYS_MBRTOC16 = 0xD42 - SYS_MBRTOC32 = 0xD43 - SYS_MEMSET = 0x0A3 - SYS_MKTIME = 0x0AC - SYS_MKTIME64 = 0xCE0 - SYS_MODFD128 = 0xBF8 - SYS_MODFD32 = 0xBF6 - SYS_MODFD64 = 0xBF7 - SYS_NAN = 0xAA8 - SYS_NAND128 = 0xBFB - SYS_NAND32 = 0xBF9 - SYS_NAND64 = 0xBFA - SYS_NANF = 0xAAA - SYS_NANL = 0xAAC - SYS_NEARBYINT = 0xAAE - SYS_NEARBYINTD128 = 0xBFE - SYS_NEARBYINTD32 = 0xBFC - SYS_NEARBYINTD64 = 0xBFD - SYS_NEARBYINTF = 0xAB1 - SYS_NEARBYINTL = 0xAB4 - SYS_NEXTAFTERD128 = 0xC01 - SYS_NEXTAFTERD32 = 0xBFF - SYS_NEXTAFTERD64 = 0xC00 - SYS_NEXTAFTERF = 0xAB7 - SYS_NEXTAFTERL = 0xABA - SYS_NEXTTOWARD = 0xABD - SYS_NEXTTOWARDD128 = 0xC04 - SYS_NEXTTOWARDD32 = 0xC02 - SYS_NEXTTOWARDD64 = 0xC03 - SYS_NEXTTOWARDF = 0xAC0 - SYS_NEXTTOWARDL = 0xAC3 - SYS_NL_LANGINFO = 0x0FC - SYS_PERROR_UNLOCKED = 0xCBD - SYS_POSIX_FALLOCATE = 0xCE8 - SYS_POSIX_MEMALIGN = 0xCE9 - SYS_POSIX_OPENPT = 0xC66 - SYS_POWD128 = 0xC07 - SYS_POWD32 = 0xC05 - SYS_POWD64 = 0xC06 - SYS_PRINTF_UNLOCKED = 0xCBE - SYS_PSELECT = 0xC67 - SYS_PTHREAD_ATTR_GETSTACK = 0xB3E - SYS_PTHREAD_ATTR_SETSTACK = 0xB3F - SYS_PTHREAD_SECURITY_APPLID_NP = 0xCE4 - SYS_PUTS_UNLOCKED = 0xC7F - SYS_PUTWCHAR_UNLOCKED = 0xCC0 - SYS_PUTWC_UNLOCKED = 0xCBF - SYS_QUANTEXPD128 = 0xD46 - SYS_QUANTEXPD32 = 0xD44 - SYS_QUANTEXPD64 = 0xD45 - SYS_QUANTIZED128 = 0xC0A - SYS_QUANTIZED32 = 0xC08 - SYS_QUANTIZED64 = 0xC09 - SYS_REMAINDERD128 = 0xC0D - SYS_REMAINDERD32 = 0xC0B - SYS_REMAINDERD64 = 0xC0C - SYS_RESIZE_ALLOC = 0xCEB - SYS_REWIND_UNLOCKED = 0xCC1 - SYS_RINTD128 = 0xC13 - SYS_RINTD32 = 0xC11 - SYS_RINTD64 = 0xC12 - SYS_RINTF = 0xACB - SYS_RINTL = 0xACD - SYS_ROUND = 0xACF - SYS_ROUNDD128 = 0xC16 - SYS_ROUNDD32 = 0xC14 - SYS_ROUNDD64 = 0xC15 - SYS_ROUNDF = 0xAD2 - SYS_ROUNDL = 0xAD5 - SYS_SAMEQUANTUMD128 = 0xC19 - SYS_SAMEQUANTUMD32 = 0xC17 - SYS_SAMEQUANTUMD64 = 0xC18 - SYS_SCALBLN = 0xAD8 - SYS_SCALBLND128 = 0xC1C - SYS_SCALBLND32 = 0xC1A - SYS_SCALBLND64 = 0xC1B - SYS_SCALBLNF = 0xADB - SYS_SCALBLNL = 0xADE - SYS_SCALBND128 = 0xC1F - SYS_SCALBND32 = 0xC1D - SYS_SCALBND64 = 0xC1E - SYS_SCALBNF = 0xAE3 - SYS_SCALBNL = 0xAE6 - SYS_SCANF_UNLOCKED = 0xCC2 - SYS_SCHED_YIELD = 0xB32 - SYS_SETENV = 0x0C8 - SYS_SETIPV4SOURCEFILTER = 0xC76 - SYS_SETSOURCEFILTER = 0xC78 - SYS_SHM_OPEN = 0xC8C - SYS_SHM_UNLINK = 0xC8D - SYS_SIND128 = 0xC22 - SYS_SIND32 = 0xC20 - SYS_SIND64 = 0xC21 - SYS_SINHD128 = 0xC25 - SYS_SINHD32 = 0xC23 - SYS_SINHD64 = 0xC24 - SYS_SIZEOF_ALLOC = 0xCEA - SYS_SOCKATMARK = 0xC68 - SYS_SQRTD128 = 0xC28 - SYS_SQRTD32 = 0xC26 - SYS_SQRTD64 = 0xC27 - SYS_STRCHR = 0x0A0 - SYS_STRCSPN = 0x0A1 - SYS_STRERROR = 0x0A8 - SYS_STRERROR_R = 0xB33 - SYS_STRFTIME = 0x0B2 - SYS_STRLEN = 0x0A9 - SYS_STRPBRK = 0x0A2 - SYS_STRSPN = 0x0A4 - SYS_STRSTR = 0x0A5 - SYS_STRTOD128 = 0xC2B - SYS_STRTOD32 = 0xC29 - SYS_STRTOD64 = 0xC2A - SYS_STRTOK = 0x0A6 - SYS_TAND128 = 0xC2E - SYS_TAND32 = 0xC2C - SYS_TAND64 = 0xC2D - SYS_TANHD128 = 0xC31 - SYS_TANHD32 = 0xC2F - SYS_TANHD64 = 0xC30 - SYS_TGAMMAD128 = 0xC34 - SYS_TGAMMAD32 = 0xC32 - SYS_TGAMMAD64 = 0xC33 - SYS_TIME = 0x0AD - SYS_TIME64 = 0xCE1 - SYS_TMPFILE64 = 0xD4D - SYS_TMPFILE64_UNLOCKED = 0xD4E - SYS_TMPFILE_UNLOCKED = 0xCFD - SYS_TRUNCD128 = 0xC40 - SYS_TRUNCD32 = 0xC3E - SYS_TRUNCD64 = 0xC3F - SYS_UNGETC_UNLOCKED = 0xCC3 - SYS_UNGETWC_UNLOCKED = 0xCC4 - SYS_UNSETENV = 0xB34 - SYS_VFPRINTF_UNLOCKED = 0xCC5 - SYS_VFSCANF_UNLOCKED = 0xCC7 - SYS_VFWPRINTF_UNLOCKED = 0xCC9 - SYS_VFWSCANF_UNLOCKED = 0xCCB - SYS_VPRINTF_UNLOCKED = 0xCCD - SYS_VSCANF_UNLOCKED = 0xCCF - SYS_VWPRINTF_UNLOCKED = 0xCD1 - SYS_VWSCANF_UNLOCKED = 0xCD3 - SYS_WCSTOD128 = 0xC43 - SYS_WCSTOD32 = 0xC41 - SYS_WCSTOD64 = 0xC42 - SYS_WPRINTF_UNLOCKED = 0xCD5 - SYS_WSCANF_UNLOCKED = 0xCD6 - SYS__FLUSHLBF = 0xD68 - SYS__FLUSHLBF_UNLOCKED = 0xD6F - SYS___ACOSHF_H = 0xA54 - SYS___ACOSHL_H = 0xA55 - SYS___ASINHF_H = 0xA56 - SYS___ASINHL_H = 0xA57 - SYS___ATANPID128 = 0xC6D - SYS___ATANPID32 = 0xC6B - SYS___ATANPID64 = 0xC6C - SYS___CBRTF_H = 0xA58 - SYS___CBRTL_H = 0xA59 - SYS___CDUMP = 0x0C4 - SYS___CLASS = 0xAFA - SYS___CLASS2 = 0xB99 - SYS___CLASS2D128 = 0xC99 - SYS___CLASS2D32 = 0xC97 - SYS___CLASS2D64 = 0xC98 - SYS___CLASS2F = 0xC91 - SYS___CLASS2F_B = 0xC93 - SYS___CLASS2F_H = 0xC94 - SYS___CLASS2L = 0xC92 - SYS___CLASS2L_B = 0xC95 - SYS___CLASS2L_H = 0xC96 - SYS___CLASS2_B = 0xB9A - SYS___CLASS2_H = 0xB9B - SYS___CLASS_B = 0xAFB - SYS___CLASS_H = 0xAFC - SYS___CLOGL_B = 0xA01 - SYS___CLOGL_H = 0xA02 - SYS___CLRENV = 0x0C9 - SYS___CLRMF = 0x0BD - SYS___CODEPAGE_INFO = 0xC64 - SYS___CONJF_B = 0xA07 - SYS___CONJF_H = 0xA08 - SYS___CONJL_B = 0xA0A - SYS___CONJL_H = 0xA0B - SYS___CONJ_B = 0xA04 - SYS___CONJ_H = 0xA05 - SYS___COPYSIGN_B = 0xA5A - SYS___COPYSIGN_H = 0xAF5 - SYS___COSPID128 = 0xC70 - SYS___COSPID32 = 0xC6E - SYS___COSPID64 = 0xC6F - SYS___CPOWF_B = 0xA10 - SYS___CPOWF_H = 0xA11 - SYS___CPOWL_B = 0xA13 - SYS___CPOWL_H = 0xA14 - SYS___CPOW_B = 0xA0D - SYS___CPOW_H = 0xA0E - SYS___CPROJF_B = 0xA19 - SYS___CPROJF_H = 0xA1A - SYS___CPROJL_B = 0xA1C - SYS___CPROJL_H = 0xA1D - SYS___CPROJ_B = 0xA16 - SYS___CPROJ_H = 0xA17 - SYS___CREALF_B = 0xA22 - SYS___CREALF_H = 0xA23 - SYS___CREALL_B = 0xA25 - SYS___CREALL_H = 0xA26 - SYS___CREAL_B = 0xA1F - SYS___CREAL_H = 0xA20 - SYS___CSINF_B = 0xA2B - SYS___CSINF_H = 0xA2C - SYS___CSINHF_B = 0xA34 - SYS___CSINHF_H = 0xA35 - SYS___CSINHL_B = 0xA37 - SYS___CSINHL_H = 0xA38 - SYS___CSINH_B = 0xA31 - SYS___CSINH_H = 0xA32 - SYS___CSINL_B = 0xA2E - SYS___CSINL_H = 0xA2F - SYS___CSIN_B = 0xA28 - SYS___CSIN_H = 0xA29 - SYS___CSNAP = 0x0C5 - SYS___CSQRTF_B = 0xA3D - SYS___CSQRTF_H = 0xA3E - SYS___CSQRTL_B = 0xA40 - SYS___CSQRTL_H = 0xA41 - SYS___CSQRT_B = 0xA3A - SYS___CSQRT_H = 0xA3B - SYS___CTANF_B = 0xA46 - SYS___CTANF_H = 0xA47 - SYS___CTANHF_B = 0xA4F - SYS___CTANHF_H = 0xA50 - SYS___CTANHL_B = 0xA52 - SYS___CTANHL_H = 0xA53 - SYS___CTANH_B = 0xA4C - SYS___CTANH_H = 0xA4D - SYS___CTANL_B = 0xA49 - SYS___CTANL_H = 0xA4A - SYS___CTAN_B = 0xA43 - SYS___CTAN_H = 0xA44 - SYS___CTEST = 0x0C7 - SYS___CTRACE = 0x0C6 - SYS___D1TOP = 0xC9B - SYS___D2TOP = 0xC9C - SYS___D4TOP = 0xC9D - SYS___DYNALL = 0x0C3 - SYS___DYNFRE = 0x0C2 - SYS___EXP2F_H = 0xA5E - SYS___EXP2L_H = 0xA5F - SYS___EXP2_H = 0xA5D - SYS___EXPM1F_H = 0xA5B - SYS___EXPM1L_H = 0xA5C - SYS___FBUFSIZE = 0xD60 - SYS___FLBF = 0xD62 - SYS___FLDATA = 0x0C1 - SYS___FMAF_B = 0xA67 - SYS___FMAF_H = 0xA68 - SYS___FMAL_B = 0xA6A - SYS___FMAL_H = 0xA6B - SYS___FMAXF_B = 0xA70 - SYS___FMAXF_H = 0xA71 - SYS___FMAXL_B = 0xA73 - SYS___FMAXL_H = 0xA74 - SYS___FMAX_B = 0xA6D - SYS___FMAX_H = 0xA6E - SYS___FMA_B = 0xA64 - SYS___FMA_H = 0xA65 - SYS___FMINF_B = 0xA79 - SYS___FMINF_H = 0xA7A - SYS___FMINL_B = 0xA7C - SYS___FMINL_H = 0xA7D - SYS___FMIN_B = 0xA76 - SYS___FMIN_H = 0xA77 - SYS___FPENDING = 0xD61 - SYS___FPENDING_UNLOCKED = 0xD6C - SYS___FPURGE = 0xD69 - SYS___FPURGE_UNLOCKED = 0xD70 - SYS___FP_CAST_D = 0xBCB - SYS___FREADABLE = 0xD63 - SYS___FREADAHEAD = 0xD6A - SYS___FREADAHEAD_UNLOCKED = 0xD71 - SYS___FREADING = 0xD65 - SYS___FREADING_UNLOCKED = 0xD6D - SYS___FSEEK2 = 0xB3C - SYS___FSETERR = 0xD6B - SYS___FSETLOCKING = 0xD67 - SYS___FTCHEP = 0x0BF - SYS___FTELL2 = 0xB3B - SYS___FUPDT = 0x0B5 - SYS___FWRITABLE = 0xD64 - SYS___FWRITING = 0xD66 - SYS___FWRITING_UNLOCKED = 0xD6E - SYS___GETCB = 0x0B4 - SYS___GETGRGID1 = 0xD5B - SYS___GETGRNAM1 = 0xD5C - SYS___GETTHENT = 0xCE5 - SYS___GETTOD = 0xD3E - SYS___HYPOTF_H = 0xAF6 - SYS___HYPOTL_H = 0xAF7 - SYS___ILOGBF_B = 0xA7F - SYS___ILOGBF_H = 0xA80 - SYS___ILOGBL_B = 0xA82 - SYS___ILOGBL_H = 0xA83 - SYS___ISBLANK_A = 0xB2E - SYS___ISBLNK = 0x0FE - SYS___ISWBLANK_A = 0xB2F - SYS___LE_CEEGTJS = 0xD72 - SYS___LE_TRACEBACK = 0xB7A - SYS___LGAMMAL_H = 0xA62 - SYS___LGAMMA_B_C99 = 0xB39 - SYS___LGAMMA_H_C99 = 0xB38 - SYS___LGAMMA_R_C99 = 0xB3A - SYS___LLRINTF_B = 0xA88 - SYS___LLRINTF_H = 0xA89 - SYS___LLRINTL_B = 0xA8B - SYS___LLRINTL_H = 0xA8C - SYS___LLRINT_B = 0xA85 - SYS___LLRINT_H = 0xA86 - SYS___LLROUNDF_B = 0xA91 - SYS___LLROUNDF_H = 0xA92 - SYS___LLROUNDL_B = 0xA94 - SYS___LLROUNDL_H = 0xA95 - SYS___LLROUND_B = 0xA8E - SYS___LLROUND_H = 0xA8F - SYS___LOCALE_CTL = 0xD47 - SYS___LOG1PF_H = 0xA60 - SYS___LOG1PL_H = 0xA61 - SYS___LOGBF_B = 0xA97 - SYS___LOGBF_H = 0xA98 - SYS___LOGBL_B = 0xA9A - SYS___LOGBL_H = 0xA9B - SYS___LOGIN_APPLID = 0xCE2 - SYS___LRINTF_B = 0xAA0 - SYS___LRINTF_H = 0xAA1 - SYS___LRINTL_B = 0xAA3 - SYS___LRINTL_H = 0xAA4 - SYS___LRINT_B = 0xA9D - SYS___LRINT_H = 0xA9E - SYS___LROUNDF_FIXUP = 0xB31 - SYS___LROUNDL_B = 0xAA6 - SYS___LROUNDL_H = 0xAA7 - SYS___LROUND_FIXUP = 0xB30 - SYS___MOSERVICES = 0xD3D - SYS___MUST_STAY_CLEAN = 0xB7C - SYS___NANF_B = 0xAAB - SYS___NANL_B = 0xAAD - SYS___NAN_B = 0xAA9 - SYS___NEARBYINTF_B = 0xAB2 - SYS___NEARBYINTF_H = 0xAB3 - SYS___NEARBYINTL_B = 0xAB5 - SYS___NEARBYINTL_H = 0xAB6 - SYS___NEARBYINT_B = 0xAAF - SYS___NEARBYINT_H = 0xAB0 - SYS___NEXTAFTERF_B = 0xAB8 - SYS___NEXTAFTERF_H = 0xAB9 - SYS___NEXTAFTERL_B = 0xABB - SYS___NEXTAFTERL_H = 0xABC - SYS___NEXTTOWARDF_B = 0xAC1 - SYS___NEXTTOWARDF_H = 0xAC2 - SYS___NEXTTOWARDL_B = 0xAC4 - SYS___NEXTTOWARDL_H = 0xAC5 - SYS___NEXTTOWARD_B = 0xABE - SYS___NEXTTOWARD_H = 0xABF - SYS___O_ENV = 0xB7D - SYS___PASSWD_APPLID = 0xCE3 - SYS___PTOD1 = 0xC9E - SYS___PTOD2 = 0xC9F - SYS___PTOD4 = 0xCA0 - SYS___REGCOMP_STD = 0x0EA - SYS___REMAINDERF_H = 0xAC6 - SYS___REMAINDERL_H = 0xAC7 - SYS___REMQUOD128 = 0xC10 - SYS___REMQUOD32 = 0xC0E - SYS___REMQUOD64 = 0xC0F - SYS___REMQUOF_H = 0xAC9 - SYS___REMQUOL_H = 0xACA - SYS___REMQUO_H = 0xAC8 - SYS___RINTF_B = 0xACC - SYS___RINTL_B = 0xACE - SYS___ROUNDF_B = 0xAD3 - SYS___ROUNDF_H = 0xAD4 - SYS___ROUNDL_B = 0xAD6 - SYS___ROUNDL_H = 0xAD7 - SYS___ROUND_B = 0xAD0 - SYS___ROUND_H = 0xAD1 - SYS___SCALBLNF_B = 0xADC - SYS___SCALBLNF_H = 0xADD - SYS___SCALBLNL_B = 0xADF - SYS___SCALBLNL_H = 0xAE0 - SYS___SCALBLN_B = 0xAD9 - SYS___SCALBLN_H = 0xADA - SYS___SCALBNF_B = 0xAE4 - SYS___SCALBNF_H = 0xAE5 - SYS___SCALBNL_B = 0xAE7 - SYS___SCALBNL_H = 0xAE8 - SYS___SCALBN_B = 0xAE1 - SYS___SCALBN_H = 0xAE2 - SYS___SETENV = 0x0C8 - SYS___SINPID128 = 0xC73 - SYS___SINPID32 = 0xC71 - SYS___SINPID64 = 0xC72 - SYS___SMF_RECORD2 = 0xD48 - SYS___STATIC_REINIT = 0xB3D - SYS___TGAMMAF_H_C99 = 0xB79 - SYS___TGAMMAL_H = 0xAE9 - SYS___TGAMMA_H_C99 = 0xB78 - SYS___TOCSNAME2 = 0xC9A - SYS_CEIL = 0x01F - SYS_CHAUDIT = 0x1E0 - SYS_EXP = 0x01A - SYS_FCHAUDIT = 0x1E1 - SYS_FREXP = 0x01D - SYS_GETGROUPSBYNAME = 0x1E2 - SYS_GETPWUID = 0x1A0 - SYS_GETUID = 0x1A1 - SYS_ISATTY = 0x1A3 - SYS_KILL = 0x1A4 - SYS_LDEXP = 0x01E - SYS_LINK = 0x1A5 - SYS_LOG10 = 0x01C - SYS_LSEEK = 0x1A6 - SYS_LSTAT = 0x1A7 - SYS_MKDIR = 0x1A8 - SYS_MKFIFO = 0x1A9 - SYS_MKNOD = 0x1AA - SYS_MODF = 0x01B - SYS_MOUNT = 0x1AB - SYS_OPEN = 0x1AC - SYS_OPENDIR = 0x1AD - SYS_PATHCONF = 0x1AE - SYS_PAUSE = 0x1AF - SYS_PIPE = 0x1B0 - SYS_PTHREAD_ATTR_DESTROY = 0x1E7 - SYS_PTHREAD_ATTR_GETDETACHSTATE = 0x1EB - SYS_PTHREAD_ATTR_GETSTACKSIZE = 0x1E9 - SYS_PTHREAD_ATTR_GETWEIGHT_NP = 0x1ED - SYS_PTHREAD_ATTR_INIT = 0x1E6 - SYS_PTHREAD_ATTR_SETDETACHSTATE = 0x1EA - SYS_PTHREAD_ATTR_SETSTACKSIZE = 0x1E8 - SYS_PTHREAD_ATTR_SETWEIGHT_NP = 0x1EC - SYS_PTHREAD_CANCEL = 0x1EE - SYS_PTHREAD_CLEANUP_POP = 0x1F0 - SYS_PTHREAD_CLEANUP_PUSH = 0x1EF - SYS_PTHREAD_CONDATTR_DESTROY = 0x1F2 - SYS_PTHREAD_CONDATTR_INIT = 0x1F1 - SYS_PTHREAD_COND_BROADCAST = 0x1F6 - SYS_PTHREAD_COND_DESTROY = 0x1F4 - SYS_PTHREAD_COND_INIT = 0x1F3 - SYS_PTHREAD_COND_SIGNAL = 0x1F5 - SYS_PTHREAD_COND_TIMEDWAIT = 0x1F8 - SYS_PTHREAD_COND_WAIT = 0x1F7 - SYS_PTHREAD_CREATE = 0x1F9 - SYS_PTHREAD_DETACH = 0x1FA - SYS_PTHREAD_EQUAL = 0x1FB - SYS_PTHREAD_EXIT = 0x1E4 - SYS_PTHREAD_GETSPECIFIC = 0x1FC - SYS_PTHREAD_JOIN = 0x1FD - SYS_PTHREAD_KEY_CREATE = 0x1FE - SYS_PTHREAD_KILL = 0x1E5 - SYS_PTHREAD_MUTEXATTR_INIT = 0x1FF - SYS_READ = 0x1B2 - SYS_READDIR = 0x1B3 - SYS_READLINK = 0x1B4 - SYS_REWINDDIR = 0x1B5 - SYS_RMDIR = 0x1B6 - SYS_SETEGID = 0x1B7 - SYS_SETEUID = 0x1B8 - SYS_SETGID = 0x1B9 - SYS_SETPGID = 0x1BA - SYS_SETSID = 0x1BB - SYS_SETUID = 0x1BC - SYS_SIGACTION = 0x1BD - SYS_SIGADDSET = 0x1BE - SYS_SIGDELSET = 0x1BF - SYS_SIGEMPTYSET = 0x1C0 - SYS_SIGFILLSET = 0x1C1 - SYS_SIGISMEMBER = 0x1C2 - SYS_SIGLONGJMP = 0x1C3 - SYS_SIGPENDING = 0x1C4 - SYS_SIGPROCMASK = 0x1C5 - SYS_SIGSETJMP = 0x1C6 - SYS_SIGSUSPEND = 0x1C7 - SYS_SIGWAIT = 0x1E3 - SYS_SLEEP = 0x1C8 - SYS_STAT = 0x1C9 - SYS_SYMLINK = 0x1CB - SYS_SYSCONF = 0x1CC - SYS_TCDRAIN = 0x1CD - SYS_TCFLOW = 0x1CE - SYS_TCFLUSH = 0x1CF - SYS_TCGETATTR = 0x1D0 - SYS_TCGETPGRP = 0x1D1 - SYS_TCSENDBREAK = 0x1D2 - SYS_TCSETATTR = 0x1D3 - SYS_TCSETPGRP = 0x1D4 - SYS_TIMES = 0x1D5 - SYS_TTYNAME = 0x1D6 - SYS_TZSET = 0x1D7 - SYS_UMASK = 0x1D8 - SYS_UMOUNT = 0x1D9 - SYS_UNAME = 0x1DA - SYS_UNLINK = 0x1DB - SYS_UTIME = 0x1DC - SYS_WAIT = 0x1DD - SYS_WAITPID = 0x1DE - SYS_WRITE = 0x1DF - SYS_W_GETPSENT = 0x1B1 - SYS_W_IOCTL = 0x1A2 - SYS_W_STATFS = 0x1CA - SYS_A64L = 0x2EF - SYS_BCMP = 0x2B9 - SYS_BCOPY = 0x2BA - SYS_BZERO = 0x2BB - SYS_CATCLOSE = 0x2B6 - SYS_CATGETS = 0x2B7 - SYS_CATOPEN = 0x2B8 - SYS_CRYPT = 0x2AC - SYS_DBM_CLEARERR = 0x2F7 - SYS_DBM_CLOSE = 0x2F8 - SYS_DBM_DELETE = 0x2F9 - SYS_DBM_ERROR = 0x2FA - SYS_DBM_FETCH = 0x2FB - SYS_DBM_FIRSTKEY = 0x2FC - SYS_DBM_NEXTKEY = 0x2FD - SYS_DBM_OPEN = 0x2FE - SYS_DBM_STORE = 0x2FF - SYS_DRAND48 = 0x2B2 - SYS_ENCRYPT = 0x2AD - SYS_ENDUTXENT = 0x2E1 - SYS_ERAND48 = 0x2B3 - SYS_ERF = 0x02C - SYS_ERFC = 0x02D - SYS_FCHDIR = 0x2D9 - SYS_FFS = 0x2BC - SYS_FMTMSG = 0x2E5 - SYS_FSTATVFS = 0x2B4 - SYS_FTIME = 0x2F5 - SYS_GAMMA = 0x02E - SYS_GETDATE = 0x2A6 - SYS_GETPAGESIZE = 0x2D8 - SYS_GETTIMEOFDAY = 0x2F6 - SYS_GETUTXENT = 0x2E0 - SYS_GETUTXID = 0x2E2 - SYS_GETUTXLINE = 0x2E3 - SYS_HCREATE = 0x2C6 - SYS_HDESTROY = 0x2C7 - SYS_HSEARCH = 0x2C8 - SYS_HYPOT = 0x02B - SYS_INDEX = 0x2BD - SYS_INITSTATE = 0x2C2 - SYS_INSQUE = 0x2CF - SYS_ISASCII = 0x2ED - SYS_JRAND48 = 0x2E6 - SYS_L64A = 0x2F0 - SYS_LCONG48 = 0x2EA - SYS_LFIND = 0x2C9 - SYS_LRAND48 = 0x2E7 - SYS_LSEARCH = 0x2CA - SYS_MEMCCPY = 0x2D4 - SYS_MRAND48 = 0x2E8 - SYS_NRAND48 = 0x2E9 - SYS_PCLOSE = 0x2D2 - SYS_POPEN = 0x2D1 - SYS_PUTUTXLINE = 0x2E4 - SYS_RANDOM = 0x2C4 - SYS_REMQUE = 0x2D0 - SYS_RINDEX = 0x2BE - SYS_SEED48 = 0x2EC - SYS_SETKEY = 0x2AE - SYS_SETSTATE = 0x2C3 - SYS_SETUTXENT = 0x2DF - SYS_SRAND48 = 0x2EB - SYS_SRANDOM = 0x2C5 - SYS_STATVFS = 0x2B5 - SYS_STRCASECMP = 0x2BF - SYS_STRDUP = 0x2C0 - SYS_STRNCASECMP = 0x2C1 - SYS_SWAB = 0x2D3 - SYS_TDELETE = 0x2CB - SYS_TFIND = 0x2CC - SYS_TOASCII = 0x2EE - SYS_TSEARCH = 0x2CD - SYS_TWALK = 0x2CE - SYS_UALARM = 0x2F1 - SYS_USLEEP = 0x2F2 - SYS_WAIT3 = 0x2A7 - SYS_WAITID = 0x2A8 - SYS_Y1 = 0x02A - SYS___ATOE = 0x2DB - SYS___ATOE_L = 0x2DC - SYS___CATTRM = 0x2A9 - SYS___CNVBLK = 0x2AF - SYS___CRYTRM = 0x2B0 - SYS___DLGHT = 0x2A1 - SYS___ECRTRM = 0x2B1 - SYS___ETOA = 0x2DD - SYS___ETOA_L = 0x2DE - SYS___GDTRM = 0x2AA - SYS___OCLCK = 0x2DA - SYS___OPARGF = 0x2A2 - SYS___OPERRF = 0x2A5 - SYS___OPINDF = 0x2A4 - SYS___OPOPTF = 0x2A3 - SYS___RNDTRM = 0x2AB - SYS___SRCTRM = 0x2F4 - SYS___TZONE = 0x2A0 - SYS___UTXTRM = 0x2F3 - SYS_ASIN = 0x03E - SYS_ISXDIGIT = 0x03B - SYS_SETLOCAL = 0x03A - SYS_SETLOCALE = 0x03A - SYS_SIN = 0x03F - SYS_TOLOWER = 0x03C - SYS_TOUPPER = 0x03D - SYS_ACCEPT_AND_RECV = 0x4F7 - SYS_ATOL = 0x04E - SYS_CHECKSCH = 0x4BC - SYS_CHECKSCHENV = 0x4BC - SYS_CLEARERR = 0x04C - SYS_CONNECTS = 0x4B5 - SYS_CONNECTSERVER = 0x4B5 - SYS_CONNECTW = 0x4B4 - SYS_CONNECTWORKMGR = 0x4B4 - SYS_CONTINUE = 0x4B3 - SYS_CONTINUEWORKUNIT = 0x4B3 - SYS_COPYSIGN = 0x4C2 - SYS_CREATEWO = 0x4B2 - SYS_CREATEWORKUNIT = 0x4B2 - SYS_DELETEWO = 0x4B9 - SYS_DELETEWORKUNIT = 0x4B9 - SYS_DISCONNE = 0x4B6 - SYS_DISCONNECTSERVER = 0x4B6 - SYS_FEOF = 0x04D - SYS_FERROR = 0x04A - SYS_FINITE = 0x4C8 - SYS_GAMMA_R = 0x4E2 - SYS_JOINWORK = 0x4B7 - SYS_JOINWORKUNIT = 0x4B7 - SYS_LEAVEWOR = 0x4B8 - SYS_LEAVEWORKUNIT = 0x4B8 - SYS_LGAMMA_R = 0x4EB - SYS_MATHERR = 0x4D0 - SYS_PERROR = 0x04F - SYS_QUERYMET = 0x4BA - SYS_QUERYMETRICS = 0x4BA - SYS_QUERYSCH = 0x4BB - SYS_QUERYSCHENV = 0x4BB - SYS_REWIND = 0x04B - SYS_SCALBN = 0x4D4 - SYS_SIGNIFIC = 0x4D5 - SYS_SIGNIFICAND = 0x4D5 - SYS___ACOSH_B = 0x4DA - SYS___ACOS_B = 0x4D9 - SYS___ASINH_B = 0x4BE - SYS___ASIN_B = 0x4DB - SYS___ATAN2_B = 0x4DC - SYS___ATANH_B = 0x4DD - SYS___ATAN_B = 0x4BF - SYS___CBRT_B = 0x4C0 - SYS___CEIL_B = 0x4C1 - SYS___COSH_B = 0x4DE - SYS___COS_B = 0x4C3 - SYS___DGHT = 0x4A8 - SYS___ENVN = 0x4B0 - SYS___ERFC_B = 0x4C5 - SYS___ERF_B = 0x4C4 - SYS___EXPM1_B = 0x4C6 - SYS___EXP_B = 0x4DF - SYS___FABS_B = 0x4C7 - SYS___FLOOR_B = 0x4C9 - SYS___FMOD_B = 0x4E0 - SYS___FP_SETMODE = 0x4F8 - SYS___FREXP_B = 0x4CA - SYS___GAMMA_B = 0x4E1 - SYS___GDRR = 0x4A1 - SYS___HRRNO = 0x4A2 - SYS___HYPOT_B = 0x4E3 - SYS___ILOGB_B = 0x4CB - SYS___ISNAN_B = 0x4CC - SYS___J0_B = 0x4E4 - SYS___J1_B = 0x4E6 - SYS___JN_B = 0x4E8 - SYS___LDEXP_B = 0x4CD - SYS___LGAMMA_B = 0x4EA - SYS___LOG10_B = 0x4ED - SYS___LOG1P_B = 0x4CE - SYS___LOGB_B = 0x4CF - SYS___LOGIN = 0x4F5 - SYS___LOG_B = 0x4EC - SYS___MLOCKALL = 0x4B1 - SYS___MODF_B = 0x4D1 - SYS___NEXTAFTER_B = 0x4D2 - SYS___OPENDIR2 = 0x4F3 - SYS___OPEN_STAT = 0x4F6 - SYS___OPND = 0x4A5 - SYS___OPPT = 0x4A6 - SYS___OPRG = 0x4A3 - SYS___OPRR = 0x4A4 - SYS___PID_AFFINITY = 0x4BD - SYS___POW_B = 0x4EE - SYS___READDIR2 = 0x4F4 - SYS___REMAINDER_B = 0x4EF - SYS___RINT_B = 0x4D3 - SYS___SCALB_B = 0x4F0 - SYS___SIGACTIONSET = 0x4FB - SYS___SIGGM = 0x4A7 - SYS___SINH_B = 0x4F1 - SYS___SIN_B = 0x4D6 - SYS___SQRT_B = 0x4F2 - SYS___TANH_B = 0x4D8 - SYS___TAN_B = 0x4D7 - SYS___TRRNO = 0x4AF - SYS___TZNE = 0x4A9 - SYS___TZZN = 0x4AA - SYS___UCREATE = 0x4FC - SYS___UFREE = 0x4FE - SYS___UHEAPREPORT = 0x4FF - SYS___UMALLOC = 0x4FD - SYS___Y0_B = 0x4E5 - SYS___Y1_B = 0x4E7 - SYS___YN_B = 0x4E9 - SYS_ABORT = 0x05C - SYS_ASCTIME_R = 0x5E0 - SYS_ATEXIT = 0x05D - SYS_CONNECTE = 0x5AE - SYS_CONNECTEXPORTIMPORT = 0x5AE - SYS_CTIME_R = 0x5E1 - SYS_DN_COMP = 0x5DF - SYS_DN_EXPAND = 0x5DD - SYS_DN_SKIPNAME = 0x5DE - SYS_EXIT = 0x05A - SYS_EXPORTWO = 0x5A1 - SYS_EXPORTWORKUNIT = 0x5A1 - SYS_EXTRACTW = 0x5A5 - SYS_EXTRACTWORKUNIT = 0x5A5 - SYS_FSEEKO = 0x5C9 - SYS_FTELLO = 0x5C8 - SYS_GETGRGID_R = 0x5E7 - SYS_GETGRNAM_R = 0x5E8 - SYS_GETLOGIN_R = 0x5E9 - SYS_GETPWNAM_R = 0x5EA - SYS_GETPWUID_R = 0x5EB - SYS_GMTIME_R = 0x5E2 - SYS_IMPORTWO = 0x5A3 - SYS_IMPORTWORKUNIT = 0x5A3 - SYS_INET_NTOP = 0x5D3 - SYS_INET_PTON = 0x5D4 - SYS_LLABS = 0x5CE - SYS_LLDIV = 0x5CB - SYS_LOCALTIME_R = 0x5E3 - SYS_PTHREAD_ATFORK = 0x5ED - SYS_PTHREAD_ATTR_GETDETACHSTATE_U98 = 0x5FB - SYS_PTHREAD_ATTR_GETGUARDSIZE = 0x5EE - SYS_PTHREAD_ATTR_GETSCHEDPARAM = 0x5F9 - SYS_PTHREAD_ATTR_GETSTACKADDR = 0x5EF - SYS_PTHREAD_ATTR_SETDETACHSTATE_U98 = 0x5FC - SYS_PTHREAD_ATTR_SETGUARDSIZE = 0x5F0 - SYS_PTHREAD_ATTR_SETSCHEDPARAM = 0x5FA - SYS_PTHREAD_ATTR_SETSTACKADDR = 0x5F1 - SYS_PTHREAD_CONDATTR_GETPSHARED = 0x5F2 - SYS_PTHREAD_CONDATTR_SETPSHARED = 0x5F3 - SYS_PTHREAD_DETACH_U98 = 0x5FD - SYS_PTHREAD_GETCONCURRENCY = 0x5F4 - SYS_PTHREAD_GETSPECIFIC_U98 = 0x5FE - SYS_PTHREAD_KEY_DELETE = 0x5F5 - SYS_PTHREAD_SETCANCELSTATE = 0x5FF - SYS_PTHREAD_SETCONCURRENCY = 0x5F6 - SYS_PTHREAD_SIGMASK = 0x5F7 - SYS_QUERYENC = 0x5AD - SYS_QUERYWORKUNITCLASSIFICATION = 0x5AD - SYS_RAISE = 0x05E - SYS_RAND_R = 0x5E4 - SYS_READDIR_R = 0x5E6 - SYS_REALLOC = 0x05B - SYS_RES_INIT = 0x5D8 - SYS_RES_MKQUERY = 0x5D7 - SYS_RES_QUERY = 0x5D9 - SYS_RES_QUERYDOMAIN = 0x5DC - SYS_RES_SEARCH = 0x5DA - SYS_RES_SEND = 0x5DB - SYS_SETJMP = 0x05F - SYS_SIGQUEUE = 0x5A9 - SYS_STRTOK_R = 0x5E5 - SYS_STRTOLL = 0x5B0 - SYS_STRTOULL = 0x5B1 - SYS_TTYNAME_R = 0x5EC - SYS_UNDOEXPO = 0x5A2 - SYS_UNDOEXPORTWORKUNIT = 0x5A2 - SYS_UNDOIMPO = 0x5A4 - SYS_UNDOIMPORTWORKUNIT = 0x5A4 - SYS_WCSTOLL = 0x5CC - SYS_WCSTOULL = 0x5CD - SYS___ABORT = 0x05C - SYS___CONSOLE2 = 0x5D2 - SYS___CPL = 0x5A6 - SYS___DISCARDDATA = 0x5F8 - SYS___DSA_PREV = 0x5B2 - SYS___EP_FIND = 0x5B3 - SYS___FP_SWAPMODE = 0x5AF - SYS___GETUSERID = 0x5AB - SYS___GET_CPUID = 0x5B9 - SYS___GET_SYSTEM_SETTINGS = 0x5BA - SYS___IPDOMAINNAME = 0x5AC - SYS___MAP_INIT = 0x5A7 - SYS___MAP_SERVICE = 0x5A8 - SYS___MOUNT = 0x5AA - SYS___MSGRCV_TIMED = 0x5B7 - SYS___RES = 0x5D6 - SYS___SEMOP_TIMED = 0x5B8 - SYS___SERVER_THREADS_QUERY = 0x5B4 - SYS_FPRINTF = 0x06D - SYS_FSCANF = 0x06A - SYS_PRINTF = 0x06F - SYS_SETBUF = 0x06B - SYS_SETVBUF = 0x06C - SYS_SSCANF = 0x06E - SYS___CATGETS_A = 0x6C0 - SYS___CHAUDIT_A = 0x6F4 - SYS___CHMOD_A = 0x6E8 - SYS___COLLATE_INIT_A = 0x6AC - SYS___CREAT_A = 0x6F6 - SYS___CTYPE_INIT_A = 0x6AF - SYS___DLLLOAD_A = 0x6DF - SYS___DLLQUERYFN_A = 0x6E0 - SYS___DLLQUERYVAR_A = 0x6E1 - SYS___E2A_L = 0x6E3 - SYS___EXECLE_A = 0x6A0 - SYS___EXECLP_A = 0x6A4 - SYS___EXECVE_A = 0x6C1 - SYS___EXECVP_A = 0x6C2 - SYS___EXECV_A = 0x6B1 - SYS___FPRINTF_A = 0x6FA - SYS___GETADDRINFO_A = 0x6BF - SYS___GETNAMEINFO_A = 0x6C4 - SYS___GET_WCTYPE_STD_A = 0x6AE - SYS___ICONV_OPEN_A = 0x6DE - SYS___IF_INDEXTONAME_A = 0x6DC - SYS___IF_NAMETOINDEX_A = 0x6DB - SYS___ISWCTYPE_A = 0x6B0 - SYS___IS_WCTYPE_STD_A = 0x6B2 - SYS___LOCALECONV_A = 0x6B8 - SYS___LOCALECONV_STD_A = 0x6B9 - SYS___LOCALE_INIT_A = 0x6B7 - SYS___LSTAT_A = 0x6EE - SYS___LSTAT_O_A = 0x6EF - SYS___MKDIR_A = 0x6E9 - SYS___MKFIFO_A = 0x6EC - SYS___MKNOD_A = 0x6F0 - SYS___MONETARY_INIT_A = 0x6BC - SYS___MOUNT_A = 0x6F1 - SYS___NL_CSINFO_A = 0x6D6 - SYS___NL_LANGINFO_A = 0x6BA - SYS___NL_LNAGINFO_STD_A = 0x6BB - SYS___NL_MONINFO_A = 0x6D7 - SYS___NL_NUMINFO_A = 0x6D8 - SYS___NL_RESPINFO_A = 0x6D9 - SYS___NL_TIMINFO_A = 0x6DA - SYS___NUMERIC_INIT_A = 0x6C6 - SYS___OPEN_A = 0x6F7 - SYS___PRINTF_A = 0x6DD - SYS___RESP_INIT_A = 0x6C7 - SYS___RPMATCH_A = 0x6C8 - SYS___RPMATCH_C_A = 0x6C9 - SYS___RPMATCH_STD_A = 0x6CA - SYS___SETLOCALE_A = 0x6F9 - SYS___SPAWNP_A = 0x6C5 - SYS___SPAWN_A = 0x6C3 - SYS___SPRINTF_A = 0x6FB - SYS___STAT_A = 0x6EA - SYS___STAT_O_A = 0x6EB - SYS___STRCOLL_STD_A = 0x6A1 - SYS___STRFMON_A = 0x6BD - SYS___STRFMON_STD_A = 0x6BE - SYS___STRFTIME_A = 0x6CC - SYS___STRFTIME_STD_A = 0x6CD - SYS___STRPTIME_A = 0x6CE - SYS___STRPTIME_STD_A = 0x6CF - SYS___STRXFRM_A = 0x6A2 - SYS___STRXFRM_C_A = 0x6A3 - SYS___STRXFRM_STD_A = 0x6A5 - SYS___SYNTAX_INIT_A = 0x6D4 - SYS___TIME_INIT_A = 0x6CB - SYS___TOD_INIT_A = 0x6D5 - SYS___TOWLOWER_A = 0x6B3 - SYS___TOWLOWER_STD_A = 0x6B4 - SYS___TOWUPPER_A = 0x6B5 - SYS___TOWUPPER_STD_A = 0x6B6 - SYS___UMOUNT_A = 0x6F2 - SYS___VFPRINTF_A = 0x6FC - SYS___VPRINTF_A = 0x6FD - SYS___VSPRINTF_A = 0x6FE - SYS___VSWPRINTF_A = 0x6FF - SYS___WCSCOLL_A = 0x6A6 - SYS___WCSCOLL_C_A = 0x6A7 - SYS___WCSCOLL_STD_A = 0x6A8 - SYS___WCSFTIME_A = 0x6D0 - SYS___WCSFTIME_STD_A = 0x6D1 - SYS___WCSXFRM_A = 0x6A9 - SYS___WCSXFRM_C_A = 0x6AA - SYS___WCSXFRM_STD_A = 0x6AB - SYS___WCTYPE_A = 0x6AD - SYS___W_GETMNTENT_A = 0x6F5 - SYS_____CCSIDTYPE_A = 0x6E6 - SYS_____CHATTR_A = 0x6E2 - SYS_____CSNAMETYPE_A = 0x6E7 - SYS_____OPEN_STAT_A = 0x6ED - SYS_____SPAWN2_A = 0x6D2 - SYS_____SPAWNP2_A = 0x6D3 - SYS_____TOCCSID_A = 0x6E4 - SYS_____TOCSNAME_A = 0x6E5 - SYS_ACL_FREE = 0x7FF - SYS_ACL_INIT = 0x7FE - SYS_FWIDE = 0x7DF - SYS_FWPRINTF = 0x7D1 - SYS_FWRITE = 0x07E - SYS_FWSCANF = 0x7D5 - SYS_GETCHAR = 0x07B - SYS_GETS = 0x07C - SYS_M_CREATE_LAYOUT = 0x7C9 - SYS_M_DESTROY_LAYOUT = 0x7CA - SYS_M_GETVALUES_LAYOUT = 0x7CB - SYS_M_SETVALUES_LAYOUT = 0x7CC - SYS_M_TRANSFORM_LAYOUT = 0x7CD - SYS_M_WTRANSFORM_LAYOUT = 0x7CE - SYS_PREAD = 0x7C7 - SYS_PUTC = 0x07D - SYS_PUTCHAR = 0x07A - SYS_PUTS = 0x07F - SYS_PWRITE = 0x7C8 - SYS_TOWCTRAN = 0x7D8 - SYS_TOWCTRANS = 0x7D8 - SYS_UNATEXIT = 0x7B5 - SYS_VFWPRINT = 0x7D3 - SYS_VFWPRINTF = 0x7D3 - SYS_VWPRINTF = 0x7D4 - SYS_WCTRANS = 0x7D7 - SYS_WPRINTF = 0x7D2 - SYS_WSCANF = 0x7D6 - SYS___ASCTIME_R_A = 0x7A1 - SYS___BASENAME_A = 0x7DC - SYS___BTOWC_A = 0x7E4 - SYS___CDUMP_A = 0x7B7 - SYS___CEE3DMP_A = 0x7B6 - SYS___CEILF_H = 0x7F4 - SYS___CEILL_H = 0x7F5 - SYS___CEIL_H = 0x7EA - SYS___CRYPT_A = 0x7BE - SYS___CSNAP_A = 0x7B8 - SYS___CTEST_A = 0x7B9 - SYS___CTIME_R_A = 0x7A2 - SYS___CTRACE_A = 0x7BA - SYS___DBM_OPEN_A = 0x7E6 - SYS___DIRNAME_A = 0x7DD - SYS___FABSF_H = 0x7FA - SYS___FABSL_H = 0x7FB - SYS___FABS_H = 0x7ED - SYS___FGETWC_A = 0x7AA - SYS___FGETWS_A = 0x7AD - SYS___FLOORF_H = 0x7F6 - SYS___FLOORL_H = 0x7F7 - SYS___FLOOR_H = 0x7EB - SYS___FPUTWC_A = 0x7A5 - SYS___FPUTWS_A = 0x7A8 - SYS___GETTIMEOFDAY_A = 0x7AE - SYS___GETWCHAR_A = 0x7AC - SYS___GETWC_A = 0x7AB - SYS___GLOB_A = 0x7DE - SYS___GMTIME_A = 0x7AF - SYS___GMTIME_R_A = 0x7B0 - SYS___INET_PTON_A = 0x7BC - SYS___J0_H = 0x7EE - SYS___J1_H = 0x7EF - SYS___JN_H = 0x7F0 - SYS___LOCALTIME_A = 0x7B1 - SYS___LOCALTIME_R_A = 0x7B2 - SYS___MALLOC24 = 0x7FC - SYS___MALLOC31 = 0x7FD - SYS___MKTIME_A = 0x7B3 - SYS___MODFF_H = 0x7F8 - SYS___MODFL_H = 0x7F9 - SYS___MODF_H = 0x7EC - SYS___OPENDIR_A = 0x7C2 - SYS___OSNAME = 0x7E0 - SYS___PUTWCHAR_A = 0x7A7 - SYS___PUTWC_A = 0x7A6 - SYS___READDIR_A = 0x7C3 - SYS___STRTOLL_A = 0x7A3 - SYS___STRTOULL_A = 0x7A4 - SYS___SYSLOG_A = 0x7BD - SYS___TZZNA = 0x7B4 - SYS___UNGETWC_A = 0x7A9 - SYS___UTIME_A = 0x7A0 - SYS___VFPRINTF2_A = 0x7E7 - SYS___VPRINTF2_A = 0x7E8 - SYS___VSPRINTF2_A = 0x7E9 - SYS___VSWPRNTF2_A = 0x7BB - SYS___WCSTOD_A = 0x7D9 - SYS___WCSTOL_A = 0x7DA - SYS___WCSTOUL_A = 0x7DB - SYS___WCTOB_A = 0x7E5 - SYS___Y0_H = 0x7F1 - SYS___Y1_H = 0x7F2 - SYS___YN_H = 0x7F3 - SYS_____OPENDIR2_A = 0x7BF - SYS_____OSNAME_A = 0x7E1 - SYS_____READDIR2_A = 0x7C0 - SYS_DLCLOSE = 0x8DF - SYS_DLERROR = 0x8E0 - SYS_DLOPEN = 0x8DD - SYS_DLSYM = 0x8DE - SYS_FLOCKFILE = 0x8D3 - SYS_FTRYLOCKFILE = 0x8D4 - SYS_FUNLOCKFILE = 0x8D5 - SYS_GETCHAR_UNLOCKED = 0x8D7 - SYS_GETC_UNLOCKED = 0x8D6 - SYS_PUTCHAR_UNLOCKED = 0x8D9 - SYS_PUTC_UNLOCKED = 0x8D8 - SYS_SNPRINTF = 0x8DA - SYS_VSNPRINTF = 0x8DB - SYS_WCSCSPN = 0x08B - SYS_WCSLEN = 0x08C - SYS_WCSNCAT = 0x08D - SYS_WCSNCMP = 0x08A - SYS_WCSNCPY = 0x08F - SYS_WCSSPN = 0x08E - SYS___ABSF_H = 0x8E7 - SYS___ABSL_H = 0x8E8 - SYS___ABS_H = 0x8E6 - SYS___ACOSF_H = 0x8EA - SYS___ACOSH_H = 0x8EC - SYS___ACOSL_H = 0x8EB - SYS___ACOS_H = 0x8E9 - SYS___ASINF_H = 0x8EE - SYS___ASINH_H = 0x8F0 - SYS___ASINL_H = 0x8EF - SYS___ASIN_H = 0x8ED - SYS___ATAN2F_H = 0x8F8 - SYS___ATAN2L_H = 0x8F9 - SYS___ATAN2_H = 0x8F7 - SYS___ATANF_H = 0x8F2 - SYS___ATANHF_H = 0x8F5 - SYS___ATANHL_H = 0x8F6 - SYS___ATANH_H = 0x8F4 - SYS___ATANL_H = 0x8F3 - SYS___ATAN_H = 0x8F1 - SYS___CBRT_H = 0x8FA - SYS___COPYSIGNF_H = 0x8FB - SYS___COPYSIGNL_H = 0x8FC - SYS___COSF_H = 0x8FE - SYS___COSL_H = 0x8FF - SYS___COS_H = 0x8FD - SYS___DLERROR_A = 0x8D2 - SYS___DLOPEN_A = 0x8D0 - SYS___DLSYM_A = 0x8D1 - SYS___GETUTXENT_A = 0x8C6 - SYS___GETUTXID_A = 0x8C7 - SYS___GETUTXLINE_A = 0x8C8 - SYS___ITOA = 0x8AA - SYS___ITOA_A = 0x8B0 - SYS___LE_CONDITION_TOKEN_BUILD = 0x8A5 - SYS___LE_MSG_ADD_INSERT = 0x8A6 - SYS___LE_MSG_GET = 0x8A7 - SYS___LE_MSG_GET_AND_WRITE = 0x8A8 - SYS___LE_MSG_WRITE = 0x8A9 - SYS___LLTOA = 0x8AE - SYS___LLTOA_A = 0x8B4 - SYS___LTOA = 0x8AC - SYS___LTOA_A = 0x8B2 - SYS___PUTCHAR_UNLOCKED_A = 0x8CC - SYS___PUTC_UNLOCKED_A = 0x8CB - SYS___PUTUTXLINE_A = 0x8C9 - SYS___RESET_EXCEPTION_HANDLER = 0x8E3 - SYS___REXEC_A = 0x8C4 - SYS___REXEC_AF_A = 0x8C5 - SYS___SET_EXCEPTION_HANDLER = 0x8E2 - SYS___SNPRINTF_A = 0x8CD - SYS___SUPERKILL = 0x8A4 - SYS___TCGETATTR_A = 0x8A1 - SYS___TCSETATTR_A = 0x8A2 - SYS___ULLTOA = 0x8AF - SYS___ULLTOA_A = 0x8B5 - SYS___ULTOA = 0x8AD - SYS___ULTOA_A = 0x8B3 - SYS___UTOA = 0x8AB - SYS___UTOA_A = 0x8B1 - SYS___VHM_EVENT = 0x8E4 - SYS___VSNPRINTF_A = 0x8CE - SYS_____GETENV_A = 0x8C3 - SYS_____UTMPXNAME_A = 0x8CA - SYS_CACOSH = 0x9A0 - SYS_CACOSHF = 0x9A3 - SYS_CACOSHL = 0x9A6 - SYS_CARG = 0x9A9 - SYS_CARGF = 0x9AC - SYS_CARGL = 0x9AF - SYS_CASIN = 0x9B2 - SYS_CASINF = 0x9B5 - SYS_CASINH = 0x9BB - SYS_CASINHF = 0x9BE - SYS_CASINHL = 0x9C1 - SYS_CASINL = 0x9B8 - SYS_CATAN = 0x9C4 - SYS_CATANF = 0x9C7 - SYS_CATANH = 0x9CD - SYS_CATANHF = 0x9D0 - SYS_CATANHL = 0x9D3 - SYS_CATANL = 0x9CA - SYS_CCOS = 0x9D6 - SYS_CCOSF = 0x9D9 - SYS_CCOSH = 0x9DF - SYS_CCOSHF = 0x9E2 - SYS_CCOSHL = 0x9E5 - SYS_CCOSL = 0x9DC - SYS_CEXP = 0x9E8 - SYS_CEXPF = 0x9EB - SYS_CEXPL = 0x9EE - SYS_CIMAG = 0x9F1 - SYS_CIMAGF = 0x9F4 - SYS_CIMAGL = 0x9F7 - SYS_CLOGF = 0x9FD - SYS_MEMCHR = 0x09B - SYS_MEMCMP = 0x09A - SYS_STRCOLL = 0x09C - SYS_STRNCMP = 0x09D - SYS_STRRCHR = 0x09F - SYS_STRXFRM = 0x09E - SYS___CACOSHF_B = 0x9A4 - SYS___CACOSHF_H = 0x9A5 - SYS___CACOSHL_B = 0x9A7 - SYS___CACOSHL_H = 0x9A8 - SYS___CACOSH_B = 0x9A1 - SYS___CACOSH_H = 0x9A2 - SYS___CARGF_B = 0x9AD - SYS___CARGF_H = 0x9AE - SYS___CARGL_B = 0x9B0 - SYS___CARGL_H = 0x9B1 - SYS___CARG_B = 0x9AA - SYS___CARG_H = 0x9AB - SYS___CASINF_B = 0x9B6 - SYS___CASINF_H = 0x9B7 - SYS___CASINHF_B = 0x9BF - SYS___CASINHF_H = 0x9C0 - SYS___CASINHL_B = 0x9C2 - SYS___CASINHL_H = 0x9C3 - SYS___CASINH_B = 0x9BC - SYS___CASINH_H = 0x9BD - SYS___CASINL_B = 0x9B9 - SYS___CASINL_H = 0x9BA - SYS___CASIN_B = 0x9B3 - SYS___CASIN_H = 0x9B4 - SYS___CATANF_B = 0x9C8 - SYS___CATANF_H = 0x9C9 - SYS___CATANHF_B = 0x9D1 - SYS___CATANHF_H = 0x9D2 - SYS___CATANHL_B = 0x9D4 - SYS___CATANHL_H = 0x9D5 - SYS___CATANH_B = 0x9CE - SYS___CATANH_H = 0x9CF - SYS___CATANL_B = 0x9CB - SYS___CATANL_H = 0x9CC - SYS___CATAN_B = 0x9C5 - SYS___CATAN_H = 0x9C6 - SYS___CCOSF_B = 0x9DA - SYS___CCOSF_H = 0x9DB - SYS___CCOSHF_B = 0x9E3 - SYS___CCOSHF_H = 0x9E4 - SYS___CCOSHL_B = 0x9E6 - SYS___CCOSHL_H = 0x9E7 - SYS___CCOSH_B = 0x9E0 - SYS___CCOSH_H = 0x9E1 - SYS___CCOSL_B = 0x9DD - SYS___CCOSL_H = 0x9DE - SYS___CCOS_B = 0x9D7 - SYS___CCOS_H = 0x9D8 - SYS___CEXPF_B = 0x9EC - SYS___CEXPF_H = 0x9ED - SYS___CEXPL_B = 0x9EF - SYS___CEXPL_H = 0x9F0 - SYS___CEXP_B = 0x9E9 - SYS___CEXP_H = 0x9EA - SYS___CIMAGF_B = 0x9F5 - SYS___CIMAGF_H = 0x9F6 - SYS___CIMAGL_B = 0x9F8 - SYS___CIMAGL_H = 0x9F9 - SYS___CIMAG_B = 0x9F2 - SYS___CIMAG_H = 0x9F3 - SYS___CLOG = 0x9FA - SYS___CLOGF_B = 0x9FE - SYS___CLOGF_H = 0x9FF - SYS___CLOG_B = 0x9FB - SYS___CLOG_H = 0x9FC - SYS_ISWCTYPE = 0x10C - SYS_ISWXDIGI = 0x10A - SYS_ISWXDIGIT = 0x10A - SYS_MBSINIT = 0x10F - SYS_TOWLOWER = 0x10D - SYS_TOWUPPER = 0x10E - SYS_WCTYPE = 0x10B - SYS_WCSSTR = 0x11B - SYS___RPMTCH = 0x11A - SYS_WCSTOD = 0x12E - SYS_WCSTOK = 0x12C - SYS_WCSTOL = 0x12D - SYS_WCSTOUL = 0x12F - SYS_FGETWC = 0x13C - SYS_FGETWS = 0x13D - SYS_FPUTWC = 0x13E - SYS_FPUTWS = 0x13F - SYS_REGERROR = 0x13B - SYS_REGFREE = 0x13A - SYS_COLLEQUIV = 0x14F - SYS_COLLTOSTR = 0x14E - SYS_ISMCCOLLEL = 0x14C - SYS_STRTOCOLL = 0x14D - SYS_DLLFREE = 0x16F - SYS_DLLQUERYFN = 0x16D - SYS_DLLQUERYVAR = 0x16E - SYS_GETMCCOLL = 0x16A - SYS_GETWMCCOLL = 0x16B - SYS___ERR2AD = 0x16C - SYS_CFSETOSPEED = 0x17A - SYS_CHDIR = 0x17B - SYS_CHMOD = 0x17C - SYS_CHOWN = 0x17D - SYS_CLOSE = 0x17E - SYS_CLOSEDIR = 0x17F - SYS_LOG = 0x017 - SYS_COSH = 0x018 - SYS_FCHMOD = 0x18A - SYS_FCHOWN = 0x18B - SYS_FCNTL = 0x18C - SYS_FILENO = 0x18D - SYS_FORK = 0x18E - SYS_FPATHCONF = 0x18F - SYS_GETLOGIN = 0x19A - SYS_GETPGRP = 0x19C - SYS_GETPID = 0x19D - SYS_GETPPID = 0x19E - SYS_GETPWNAM = 0x19F - SYS_TANH = 0x019 - SYS_W_GETMNTENT = 0x19B - SYS_POW = 0x020 - SYS_PTHREAD_SELF = 0x20A - SYS_PTHREAD_SETINTR = 0x20B - SYS_PTHREAD_SETINTRTYPE = 0x20C - SYS_PTHREAD_SETSPECIFIC = 0x20D - SYS_PTHREAD_TESTINTR = 0x20E - SYS_PTHREAD_YIELD = 0x20F - SYS_SQRT = 0x021 - SYS_FLOOR = 0x022 - SYS_J1 = 0x023 - SYS_WCSPBRK = 0x23F - SYS_BSEARCH = 0x24C - SYS_FABS = 0x024 - SYS_GETENV = 0x24A - SYS_LDIV = 0x24D - SYS_SYSTEM = 0x24B - SYS_FMOD = 0x025 - SYS___RETHROW = 0x25F - SYS___THROW = 0x25E - SYS_J0 = 0x026 - SYS_PUTENV = 0x26A - SYS___GETENV = 0x26F - SYS_SEMCTL = 0x27A - SYS_SEMGET = 0x27B - SYS_SEMOP = 0x27C - SYS_SHMAT = 0x27D - SYS_SHMCTL = 0x27E - SYS_SHMDT = 0x27F - SYS_YN = 0x027 - SYS_JN = 0x028 - SYS_SIGALTSTACK = 0x28A - SYS_SIGHOLD = 0x28B - SYS_SIGIGNORE = 0x28C - SYS_SIGINTERRUPT = 0x28D - SYS_SIGPAUSE = 0x28E - SYS_SIGRELSE = 0x28F - SYS_GETOPT = 0x29A - SYS_GETSUBOPT = 0x29D - SYS_LCHOWN = 0x29B - SYS_SETPGRP = 0x29E - SYS_TRUNCATE = 0x29C - SYS_Y0 = 0x029 - SYS___GDERR = 0x29F - SYS_ISALPHA = 0x030 - SYS_VFORK = 0x30F - SYS__LONGJMP = 0x30D - SYS__SETJMP = 0x30E - SYS_GLOB = 0x31A - SYS_GLOBFREE = 0x31B - SYS_ISALNUM = 0x031 - SYS_PUTW = 0x31C - SYS_SEEKDIR = 0x31D - SYS_TELLDIR = 0x31E - SYS_TEMPNAM = 0x31F - SYS_GETTIMEOFDAY_R = 0x32E - SYS_ISLOWER = 0x032 - SYS_LGAMMA = 0x32C - SYS_REMAINDER = 0x32A - SYS_SCALB = 0x32B - SYS_SYNC = 0x32F - SYS_TTYSLOT = 0x32D - SYS_ENDPROTOENT = 0x33A - SYS_ENDSERVENT = 0x33B - SYS_GETHOSTBYADDR = 0x33D - SYS_GETHOSTBYADDR_R = 0x33C - SYS_GETHOSTBYNAME = 0x33F - SYS_GETHOSTBYNAME_R = 0x33E - SYS_ISCNTRL = 0x033 - SYS_GETSERVBYNAME = 0x34A - SYS_GETSERVBYPORT = 0x34B - SYS_GETSERVENT = 0x34C - SYS_GETSOCKNAME = 0x34D - SYS_GETSOCKOPT = 0x34E - SYS_INET_ADDR = 0x34F - SYS_ISDIGIT = 0x034 - SYS_ISGRAPH = 0x035 - SYS_SELECT = 0x35B - SYS_SELECTEX = 0x35C - SYS_SEND = 0x35D - SYS_SENDTO = 0x35F - SYS_CHROOT = 0x36A - SYS_ISNAN = 0x36D - SYS_ISUPPER = 0x036 - SYS_ULIMIT = 0x36C - SYS_UTIMES = 0x36E - SYS_W_STATVFS = 0x36B - SYS___H_ERRNO = 0x36F - SYS_GRANTPT = 0x37A - SYS_ISPRINT = 0x037 - SYS_TCGETSID = 0x37C - SYS_UNLOCKPT = 0x37B - SYS___TCGETCP = 0x37D - SYS___TCSETCP = 0x37E - SYS___TCSETTABLES = 0x37F - SYS_ISPUNCT = 0x038 - SYS_NLIST = 0x38C - SYS___IPDBCS = 0x38D - SYS___IPDSPX = 0x38E - SYS___IPMSGC = 0x38F - SYS___STHOSTENT = 0x38B - SYS___STSERVENT = 0x38A - SYS_ISSPACE = 0x039 - SYS_COS = 0x040 - SYS_T_ALLOC = 0x40A - SYS_T_BIND = 0x40B - SYS_T_CLOSE = 0x40C - SYS_T_CONNECT = 0x40D - SYS_T_ERROR = 0x40E - SYS_T_FREE = 0x40F - SYS_TAN = 0x041 - SYS_T_RCVREL = 0x41A - SYS_T_RCVUDATA = 0x41B - SYS_T_RCVUDERR = 0x41C - SYS_T_SND = 0x41D - SYS_T_SNDDIS = 0x41E - SYS_T_SNDREL = 0x41F - SYS_GETPMSG = 0x42A - SYS_ISASTREAM = 0x42B - SYS_PUTMSG = 0x42C - SYS_PUTPMSG = 0x42D - SYS_SINH = 0x042 - SYS___ISPOSIXON = 0x42E - SYS___OPENMVSREL = 0x42F - SYS_ACOS = 0x043 - SYS_ATAN = 0x044 - SYS_ATAN2 = 0x045 - SYS_FTELL = 0x046 - SYS_FGETPOS = 0x047 - SYS_SOCK_DEBUG = 0x47A - SYS_SOCK_DO_TESTSTOR = 0x47D - SYS_TAKESOCKET = 0x47E - SYS___SERVER_INIT = 0x47F - SYS_FSEEK = 0x048 - SYS___IPHOST = 0x48B - SYS___IPNODE = 0x48C - SYS___SERVER_CLASSIFY_CREATE = 0x48D - SYS___SERVER_CLASSIFY_DESTROY = 0x48E - SYS___SERVER_CLASSIFY_RESET = 0x48F - SYS___SMF_RECORD = 0x48A - SYS_FSETPOS = 0x049 - SYS___FNWSA = 0x49B - SYS___SPAWN2 = 0x49D - SYS___SPAWNP2 = 0x49E - SYS_ATOF = 0x050 - SYS_PTHREAD_MUTEXATTR_GETPSHARED = 0x50A - SYS_PTHREAD_MUTEXATTR_SETPSHARED = 0x50B - SYS_PTHREAD_RWLOCK_DESTROY = 0x50C - SYS_PTHREAD_RWLOCK_INIT = 0x50D - SYS_PTHREAD_RWLOCK_RDLOCK = 0x50E - SYS_PTHREAD_RWLOCK_TRYRDLOCK = 0x50F - SYS_ATOI = 0x051 - SYS___FP_CLASS = 0x51D - SYS___FP_CLR_FLAG = 0x51A - SYS___FP_FINITE = 0x51E - SYS___FP_ISNAN = 0x51F - SYS___FP_RAISE_XCP = 0x51C - SYS___FP_READ_FLAG = 0x51B - SYS_RAND = 0x052 - SYS_SIGTIMEDWAIT = 0x52D - SYS_SIGWAITINFO = 0x52E - SYS___CHKBFP = 0x52F - SYS___FPC_RS = 0x52C - SYS___FPC_RW = 0x52A - SYS___FPC_SM = 0x52B - SYS_STRTOD = 0x053 - SYS_STRTOL = 0x054 - SYS_STRTOUL = 0x055 - SYS_MALLOC = 0x056 - SYS_SRAND = 0x057 - SYS_CALLOC = 0x058 - SYS_FREE = 0x059 - SYS___OSENV = 0x59F - SYS___W_PIOCTL = 0x59E - SYS_LONGJMP = 0x060 - SYS___FLOORF_B = 0x60A - SYS___FLOORL_B = 0x60B - SYS___FREXPF_B = 0x60C - SYS___FREXPL_B = 0x60D - SYS___LDEXPF_B = 0x60E - SYS___LDEXPL_B = 0x60F - SYS_SIGNAL = 0x061 - SYS___ATAN2F_B = 0x61A - SYS___ATAN2L_B = 0x61B - SYS___COSHF_B = 0x61C - SYS___COSHL_B = 0x61D - SYS___EXPF_B = 0x61E - SYS___EXPL_B = 0x61F - SYS_TMPNAM = 0x062 - SYS___ABSF_B = 0x62A - SYS___ABSL_B = 0x62C - SYS___ABS_B = 0x62B - SYS___FMODF_B = 0x62D - SYS___FMODL_B = 0x62E - SYS___MODFF_B = 0x62F - SYS_ATANL = 0x63A - SYS_CEILF = 0x63B - SYS_CEILL = 0x63C - SYS_COSF = 0x63D - SYS_COSHF = 0x63F - SYS_COSL = 0x63E - SYS_REMOVE = 0x063 - SYS_POWL = 0x64A - SYS_RENAME = 0x064 - SYS_SINF = 0x64B - SYS_SINHF = 0x64F - SYS_SINL = 0x64C - SYS_SQRTF = 0x64D - SYS_SQRTL = 0x64E - SYS_BTOWC = 0x65F - SYS_FREXPL = 0x65A - SYS_LDEXPF = 0x65B - SYS_LDEXPL = 0x65C - SYS_MODFF = 0x65D - SYS_MODFL = 0x65E - SYS_TMPFILE = 0x065 - SYS_FREOPEN = 0x066 - SYS___CHARMAP_INIT_A = 0x66E - SYS___GETHOSTBYADDR_R_A = 0x66C - SYS___GETHOSTBYNAME_A = 0x66A - SYS___GETHOSTBYNAME_R_A = 0x66D - SYS___MBLEN_A = 0x66F - SYS___RES_INIT_A = 0x66B - SYS_FCLOSE = 0x067 - SYS___GETGRGID_R_A = 0x67D - SYS___WCSTOMBS_A = 0x67A - SYS___WCSTOMBS_STD_A = 0x67B - SYS___WCSWIDTH_A = 0x67C - SYS___WCSWIDTH_ASIA = 0x67F - SYS___WCSWIDTH_STD_A = 0x67E - SYS_FFLUSH = 0x068 - SYS___GETLOGIN_R_A = 0x68E - SYS___GETPWNAM_R_A = 0x68C - SYS___GETPWUID_R_A = 0x68D - SYS___TTYNAME_R_A = 0x68F - SYS___WCWIDTH_ASIA = 0x68B - SYS___WCWIDTH_STD_A = 0x68A - SYS_FOPEN = 0x069 - SYS___REGEXEC_A = 0x69A - SYS___REGEXEC_STD_A = 0x69B - SYS___REGFREE_A = 0x69C - SYS___REGFREE_STD_A = 0x69D - SYS___STRCOLL_A = 0x69E - SYS___STRCOLL_C_A = 0x69F - SYS_SCANF = 0x070 - SYS___A64L_A = 0x70C - SYS___ECVT_A = 0x70D - SYS___FCVT_A = 0x70E - SYS___GCVT_A = 0x70F - SYS___STRTOUL_A = 0x70A - SYS_____AE_CORRESTBL_QUERY_A = 0x70B - SYS_SPRINTF = 0x071 - SYS___ACCESS_A = 0x71F - SYS___CATOPEN_A = 0x71E - SYS___GETOPT_A = 0x71D - SYS___REALPATH_A = 0x71A - SYS___SETENV_A = 0x71B - SYS___SYSTEM_A = 0x71C - SYS_FGETC = 0x072 - SYS___GAI_STRERROR_A = 0x72F - SYS___RMDIR_A = 0x72A - SYS___STATVFS_A = 0x72B - SYS___SYMLINK_A = 0x72C - SYS___TRUNCATE_A = 0x72D - SYS___UNLINK_A = 0x72E - SYS_VFPRINTF = 0x073 - SYS___ISSPACE_A = 0x73A - SYS___ISUPPER_A = 0x73B - SYS___ISWALNUM_A = 0x73F - SYS___ISXDIGIT_A = 0x73C - SYS___TOLOWER_A = 0x73D - SYS___TOUPPER_A = 0x73E - SYS_VPRINTF = 0x074 - SYS___CONFSTR_A = 0x74B - SYS___FDOPEN_A = 0x74E - SYS___FLDATA_A = 0x74F - SYS___FTOK_A = 0x74C - SYS___ISWXDIGIT_A = 0x74A - SYS___MKTEMP_A = 0x74D - SYS_VSPRINTF = 0x075 - SYS___GETGRGID_A = 0x75A - SYS___GETGRNAM_A = 0x75B - SYS___GETGROUPSBYNAME_A = 0x75C - SYS___GETHOSTENT_A = 0x75D - SYS___GETHOSTNAME_A = 0x75E - SYS___GETLOGIN_A = 0x75F - SYS_GETC = 0x076 - SYS___CREATEWORKUNIT_A = 0x76A - SYS___CTERMID_A = 0x76B - SYS___FMTMSG_A = 0x76C - SYS___INITGROUPS_A = 0x76D - SYS___MSGRCV_A = 0x76F - SYS_____LOGIN_A = 0x76E - SYS_FGETS = 0x077 - SYS___STRCASECMP_A = 0x77B - SYS___STRNCASECMP_A = 0x77C - SYS___TTYNAME_A = 0x77D - SYS___UNAME_A = 0x77E - SYS___UTIMES_A = 0x77F - SYS_____SERVER_PWU_A = 0x77A - SYS_FPUTC = 0x078 - SYS___CREAT_O_A = 0x78E - SYS___ENVNA = 0x78F - SYS___FREAD_A = 0x78A - SYS___FWRITE_A = 0x78B - SYS___ISASCII = 0x78D - SYS___OPEN_O_A = 0x78C - SYS_FPUTS = 0x079 - SYS___ASCTIME_A = 0x79C - SYS___CTIME_A = 0x79D - SYS___GETDATE_A = 0x79E - SYS___GETSERVBYPORT_A = 0x79A - SYS___GETSERVENT_A = 0x79B - SYS___TZSET_A = 0x79F - SYS_ACL_FROM_TEXT = 0x80C - SYS_ACL_SET_FD = 0x80A - SYS_ACL_SET_FILE = 0x80B - SYS_ACL_SORT = 0x80E - SYS_ACL_TO_TEXT = 0x80D - SYS_UNGETC = 0x080 - SYS___SHUTDOWN_REGISTRATION = 0x80F - SYS_FREAD = 0x081 - SYS_FREEADDRINFO = 0x81A - SYS_GAI_STRERROR = 0x81B - SYS_REXEC_AF = 0x81C - SYS___DYNALLOC_A = 0x81F - SYS___POE = 0x81D - SYS_WCSTOMBS = 0x082 - SYS___INET_ADDR_A = 0x82F - SYS___NLIST_A = 0x82A - SYS_____TCGETCP_A = 0x82B - SYS_____TCSETCP_A = 0x82C - SYS_____W_PIOCTL_A = 0x82E - SYS_MBTOWC = 0x083 - SYS___CABEND = 0x83D - SYS___LE_CIB_GET = 0x83E - SYS___RECVMSG_A = 0x83B - SYS___SENDMSG_A = 0x83A - SYS___SET_LAA_FOR_JIT = 0x83F - SYS_____LCHATTR_A = 0x83C - SYS_WCTOMB = 0x084 - SYS___CBRTL_B = 0x84A - SYS___COPYSIGNF_B = 0x84B - SYS___COPYSIGNL_B = 0x84C - SYS___COTANF_B = 0x84D - SYS___COTANL_B = 0x84F - SYS___COTAN_B = 0x84E - SYS_MBSTOWCS = 0x085 - SYS___LOG1PL_B = 0x85A - SYS___LOG2F_B = 0x85B - SYS___LOG2L_B = 0x85D - SYS___LOG2_B = 0x85C - SYS___REMAINDERF_B = 0x85E - SYS___REMAINDERL_B = 0x85F - SYS_ACOSHF = 0x86E - SYS_ACOSHL = 0x86F - SYS_WCSCPY = 0x086 - SYS___ERFCF_B = 0x86D - SYS___ERFF_B = 0x86C - SYS___LROUNDF_B = 0x86A - SYS___LROUND_B = 0x86B - SYS_COTANL = 0x87A - SYS_EXP2F = 0x87B - SYS_EXP2L = 0x87C - SYS_EXPM1F = 0x87D - SYS_EXPM1L = 0x87E - SYS_FDIMF = 0x87F - SYS_WCSCAT = 0x087 - SYS___COTANL = 0x87A - SYS_REMAINDERF = 0x88A - SYS_REMAINDERL = 0x88B - SYS_REMAINDF = 0x88A - SYS_REMAINDL = 0x88B - SYS_REMQUO = 0x88D - SYS_REMQUOF = 0x88C - SYS_REMQUOL = 0x88E - SYS_TGAMMAF = 0x88F - SYS_WCSCHR = 0x088 - SYS_ERFCF = 0x89B - SYS_ERFCL = 0x89C - SYS_ERFL = 0x89A - SYS_EXP2 = 0x89E - SYS_WCSCMP = 0x089 - SYS___EXP2_B = 0x89D - SYS___FAR_JUMP = 0x89F - SYS_ABS = 0x090 - SYS___ERFCL_H = 0x90A - SYS___EXPF_H = 0x90C - SYS___EXPL_H = 0x90D - SYS___EXPM1_H = 0x90E - SYS___EXP_H = 0x90B - SYS___FDIM_H = 0x90F - SYS_DIV = 0x091 - SYS___LOG2F_H = 0x91F - SYS___LOG2_H = 0x91E - SYS___LOGB_H = 0x91D - SYS___LOGF_H = 0x91B - SYS___LOGL_H = 0x91C - SYS___LOG_H = 0x91A - SYS_LABS = 0x092 - SYS___POWL_H = 0x92A - SYS___REMAINDER_H = 0x92B - SYS___RINT_H = 0x92C - SYS___SCALB_H = 0x92D - SYS___SINF_H = 0x92F - SYS___SIN_H = 0x92E - SYS_STRNCPY = 0x093 - SYS___TANHF_H = 0x93B - SYS___TANHL_H = 0x93C - SYS___TANH_H = 0x93A - SYS___TGAMMAF_H = 0x93E - SYS___TGAMMA_H = 0x93D - SYS___TRUNC_H = 0x93F - SYS_MEMCPY = 0x094 - SYS_VFWSCANF = 0x94A - SYS_VSWSCANF = 0x94E - SYS_VWSCANF = 0x94C - SYS_INET6_RTH_ADD = 0x95D - SYS_INET6_RTH_INIT = 0x95C - SYS_INET6_RTH_REVERSE = 0x95E - SYS_INET6_RTH_SEGMENTS = 0x95F - SYS_INET6_RTH_SPACE = 0x95B - SYS_MEMMOVE = 0x095 - SYS_WCSTOLD = 0x95A - SYS_STRCPY = 0x096 - SYS_STRCMP = 0x097 - SYS_CABS = 0x98E - SYS_STRCAT = 0x098 - SYS___CABS_B = 0x98F - SYS___POW_II = 0x98A - SYS___POW_II_B = 0x98B - SYS___POW_II_H = 0x98C - SYS_CACOSF = 0x99A - SYS_CACOSL = 0x99D - SYS_STRNCAT = 0x099 - SYS___CACOSF_B = 0x99B - SYS___CACOSF_H = 0x99C - SYS___CACOSL_B = 0x99E - SYS___CACOSL_H = 0x99F - SYS_ISWALPHA = 0x100 - SYS_ISWBLANK = 0x101 - SYS___ISWBLK = 0x101 - SYS_ISWCNTRL = 0x102 - SYS_ISWDIGIT = 0x103 - SYS_ISWGRAPH = 0x104 - SYS_ISWLOWER = 0x105 - SYS_ISWPRINT = 0x106 - SYS_ISWPUNCT = 0x107 - SYS_ISWSPACE = 0x108 - SYS_ISWUPPER = 0x109 - SYS_WCTOB = 0x110 - SYS_MBRLEN = 0x111 - SYS_MBRTOWC = 0x112 - SYS_MBSRTOWC = 0x113 - SYS_MBSRTOWCS = 0x113 - SYS_WCRTOMB = 0x114 - SYS_WCSRTOMB = 0x115 - SYS_WCSRTOMBS = 0x115 - SYS___CSID = 0x116 - SYS___WCSID = 0x117 - SYS_STRPTIME = 0x118 - SYS___STRPTM = 0x118 - SYS_STRFMON = 0x119 - SYS_WCSCOLL = 0x130 - SYS_WCSXFRM = 0x131 - SYS_WCSWIDTH = 0x132 - SYS_WCWIDTH = 0x133 - SYS_WCSFTIME = 0x134 - SYS_SWPRINTF = 0x135 - SYS_VSWPRINT = 0x136 - SYS_VSWPRINTF = 0x136 - SYS_SWSCANF = 0x137 - SYS_REGCOMP = 0x138 - SYS_REGEXEC = 0x139 - SYS_GETWC = 0x140 - SYS_GETWCHAR = 0x141 - SYS_PUTWC = 0x142 - SYS_PUTWCHAR = 0x143 - SYS_UNGETWC = 0x144 - SYS_ICONV_OPEN = 0x145 - SYS_ICONV = 0x146 - SYS_ICONV_CLOSE = 0x147 - SYS_COLLRANGE = 0x150 - SYS_CCLASS = 0x151 - SYS_COLLORDER = 0x152 - SYS___DEMANGLE = 0x154 - SYS_FDOPEN = 0x155 - SYS___ERRNO = 0x156 - SYS___ERRNO2 = 0x157 - SYS___TERROR = 0x158 - SYS_MAXCOLL = 0x169 - SYS_DLLLOAD = 0x170 - SYS__EXIT = 0x174 - SYS_ACCESS = 0x175 - SYS_ALARM = 0x176 - SYS_CFGETISPEED = 0x177 - SYS_CFGETOSPEED = 0x178 - SYS_CFSETISPEED = 0x179 - SYS_CREAT = 0x180 - SYS_CTERMID = 0x181 - SYS_DUP = 0x182 - SYS_DUP2 = 0x183 - SYS_EXECL = 0x184 - SYS_EXECLE = 0x185 - SYS_EXECLP = 0x186 - SYS_EXECV = 0x187 - SYS_EXECVE = 0x188 - SYS_EXECVP = 0x189 - SYS_FSTAT = 0x190 - SYS_FSYNC = 0x191 - SYS_FTRUNCATE = 0x192 - SYS_GETCWD = 0x193 - SYS_GETEGID = 0x194 - SYS_GETEUID = 0x195 - SYS_GETGID = 0x196 - SYS_GETGRGID = 0x197 - SYS_GETGRNAM = 0x198 - SYS_GETGROUPS = 0x199 - SYS_PTHREAD_MUTEXATTR_DESTROY = 0x200 - SYS_PTHREAD_MUTEXATTR_SETKIND_NP = 0x201 - SYS_PTHREAD_MUTEXATTR_GETKIND_NP = 0x202 - SYS_PTHREAD_MUTEX_INIT = 0x203 - SYS_PTHREAD_MUTEX_DESTROY = 0x204 - SYS_PTHREAD_MUTEX_LOCK = 0x205 - SYS_PTHREAD_MUTEX_TRYLOCK = 0x206 - SYS_PTHREAD_MUTEX_UNLOCK = 0x207 - SYS_PTHREAD_ONCE = 0x209 - SYS_TW_OPEN = 0x210 - SYS_TW_FCNTL = 0x211 - SYS_PTHREAD_JOIN_D4_NP = 0x212 - SYS_PTHREAD_CONDATTR_SETKIND_NP = 0x213 - SYS_PTHREAD_CONDATTR_GETKIND_NP = 0x214 - SYS_EXTLINK_NP = 0x215 - SYS___PASSWD = 0x216 - SYS_SETGROUPS = 0x217 - SYS_INITGROUPS = 0x218 - SYS_WCSRCHR = 0x240 - SYS_SVC99 = 0x241 - SYS___SVC99 = 0x241 - SYS_WCSWCS = 0x242 - SYS_LOCALECO = 0x243 - SYS_LOCALECONV = 0x243 - SYS___LIBREL = 0x244 - SYS_RELEASE = 0x245 - SYS___RLSE = 0x245 - SYS_FLOCATE = 0x246 - SYS___FLOCT = 0x246 - SYS_FDELREC = 0x247 - SYS___FDLREC = 0x247 - SYS_FETCH = 0x248 - SYS___FETCH = 0x248 - SYS_QSORT = 0x249 - SYS___CLEANUPCATCH = 0x260 - SYS___CATCHMATCH = 0x261 - SYS___CLEAN2UPCATCH = 0x262 - SYS_GETPRIORITY = 0x270 - SYS_NICE = 0x271 - SYS_SETPRIORITY = 0x272 - SYS_GETITIMER = 0x273 - SYS_SETITIMER = 0x274 - SYS_MSGCTL = 0x275 - SYS_MSGGET = 0x276 - SYS_MSGRCV = 0x277 - SYS_MSGSND = 0x278 - SYS_MSGXRCV = 0x279 - SYS___MSGXR = 0x279 - SYS_SHMGET = 0x280 - SYS___GETIPC = 0x281 - SYS_SETGRENT = 0x282 - SYS_GETGRENT = 0x283 - SYS_ENDGRENT = 0x284 - SYS_SETPWENT = 0x285 - SYS_GETPWENT = 0x286 - SYS_ENDPWENT = 0x287 - SYS_BSD_SIGNAL = 0x288 - SYS_KILLPG = 0x289 - SYS_SIGSET = 0x290 - SYS_SIGSTACK = 0x291 - SYS_GETRLIMIT = 0x292 - SYS_SETRLIMIT = 0x293 - SYS_GETRUSAGE = 0x294 - SYS_MMAP = 0x295 - SYS_MPROTECT = 0x296 - SYS_MSYNC = 0x297 - SYS_MUNMAP = 0x298 - SYS_CONFSTR = 0x299 - SYS___NDMTRM = 0x300 - SYS_FTOK = 0x301 - SYS_BASENAME = 0x302 - SYS_DIRNAME = 0x303 - SYS_GETDTABLESIZE = 0x304 - SYS_MKSTEMP = 0x305 - SYS_MKTEMP = 0x306 - SYS_NFTW = 0x307 - SYS_GETWD = 0x308 - SYS_LOCKF = 0x309 - SYS_WORDEXP = 0x310 - SYS_WORDFREE = 0x311 - SYS_GETPGID = 0x312 - SYS_GETSID = 0x313 - SYS___UTMPXNAME = 0x314 - SYS_CUSERID = 0x315 - SYS_GETPASS = 0x316 - SYS_FNMATCH = 0x317 - SYS_FTW = 0x318 - SYS_GETW = 0x319 - SYS_ACOSH = 0x320 - SYS_ASINH = 0x321 - SYS_ATANH = 0x322 - SYS_CBRT = 0x323 - SYS_EXPM1 = 0x324 - SYS_ILOGB = 0x325 - SYS_LOGB = 0x326 - SYS_LOG1P = 0x327 - SYS_NEXTAFTER = 0x328 - SYS_RINT = 0x329 - SYS_SPAWN = 0x330 - SYS_SPAWNP = 0x331 - SYS_GETLOGIN_UU = 0x332 - SYS_ECVT = 0x333 - SYS_FCVT = 0x334 - SYS_GCVT = 0x335 - SYS_ACCEPT = 0x336 - SYS_BIND = 0x337 - SYS_CONNECT = 0x338 - SYS_ENDHOSTENT = 0x339 - SYS_GETHOSTENT = 0x340 - SYS_GETHOSTID = 0x341 - SYS_GETHOSTNAME = 0x342 - SYS_GETNETBYADDR = 0x343 - SYS_GETNETBYNAME = 0x344 - SYS_GETNETENT = 0x345 - SYS_GETPEERNAME = 0x346 - SYS_GETPROTOBYNAME = 0x347 - SYS_GETPROTOBYNUMBER = 0x348 - SYS_GETPROTOENT = 0x349 - SYS_INET_LNAOF = 0x350 - SYS_INET_MAKEADDR = 0x351 - SYS_INET_NETOF = 0x352 - SYS_INET_NETWORK = 0x353 - SYS_INET_NTOA = 0x354 - SYS_IOCTL = 0x355 - SYS_LISTEN = 0x356 - SYS_READV = 0x357 - SYS_RECV = 0x358 - SYS_RECVFROM = 0x359 - SYS_SETHOSTENT = 0x360 - SYS_SETNETENT = 0x361 - SYS_SETPEER = 0x362 - SYS_SETPROTOENT = 0x363 - SYS_SETSERVENT = 0x364 - SYS_SETSOCKOPT = 0x365 - SYS_SHUTDOWN = 0x366 - SYS_SOCKET = 0x367 - SYS_SOCKETPAIR = 0x368 - SYS_WRITEV = 0x369 - SYS_ENDNETENT = 0x370 - SYS_CLOSELOG = 0x371 - SYS_OPENLOG = 0x372 - SYS_SETLOGMASK = 0x373 - SYS_SYSLOG = 0x374 - SYS_PTSNAME = 0x375 - SYS_SETREUID = 0x376 - SYS_SETREGID = 0x377 - SYS_REALPATH = 0x378 - SYS___SIGNGAM = 0x379 - SYS_POLL = 0x380 - SYS_REXEC = 0x381 - SYS___ISASCII2 = 0x382 - SYS___TOASCII2 = 0x383 - SYS_CHPRIORITY = 0x384 - SYS_PTHREAD_ATTR_SETSYNCTYPE_NP = 0x385 - SYS_PTHREAD_ATTR_GETSYNCTYPE_NP = 0x386 - SYS_PTHREAD_SET_LIMIT_NP = 0x387 - SYS___STNETENT = 0x388 - SYS___STPROTOENT = 0x389 - SYS___SELECT1 = 0x390 - SYS_PTHREAD_SECURITY_NP = 0x391 - SYS___CHECK_RESOURCE_AUTH_NP = 0x392 - SYS___CONVERT_ID_NP = 0x393 - SYS___OPENVMREL = 0x394 - SYS_WMEMCHR = 0x395 - SYS_WMEMCMP = 0x396 - SYS_WMEMCPY = 0x397 - SYS_WMEMMOVE = 0x398 - SYS_WMEMSET = 0x399 - SYS___FPUTWC = 0x400 - SYS___PUTWC = 0x401 - SYS___PWCHAR = 0x402 - SYS___WCSFTM = 0x403 - SYS___WCSTOK = 0x404 - SYS___WCWDTH = 0x405 - SYS_T_ACCEPT = 0x409 - SYS_T_GETINFO = 0x410 - SYS_T_GETPROTADDR = 0x411 - SYS_T_GETSTATE = 0x412 - SYS_T_LISTEN = 0x413 - SYS_T_LOOK = 0x414 - SYS_T_OPEN = 0x415 - SYS_T_OPTMGMT = 0x416 - SYS_T_RCV = 0x417 - SYS_T_RCVCONNECT = 0x418 - SYS_T_RCVDIS = 0x419 - SYS_T_SNDUDATA = 0x420 - SYS_T_STRERROR = 0x421 - SYS_T_SYNC = 0x422 - SYS_T_UNBIND = 0x423 - SYS___T_ERRNO = 0x424 - SYS___RECVMSG2 = 0x425 - SYS___SENDMSG2 = 0x426 - SYS_FATTACH = 0x427 - SYS_FDETACH = 0x428 - SYS_GETMSG = 0x429 - SYS_GETCONTEXT = 0x430 - SYS_SETCONTEXT = 0x431 - SYS_MAKECONTEXT = 0x432 - SYS_SWAPCONTEXT = 0x433 - SYS_PTHREAD_GETSPECIFIC_D8_NP = 0x434 - SYS_GETCLIENTID = 0x470 - SYS___GETCLIENTID = 0x471 - SYS_GETSTABLESIZE = 0x472 - SYS_GETIBMOPT = 0x473 - SYS_GETIBMSOCKOPT = 0x474 - SYS_GIVESOCKET = 0x475 - SYS_IBMSFLUSH = 0x476 - SYS_MAXDESC = 0x477 - SYS_SETIBMOPT = 0x478 - SYS_SETIBMSOCKOPT = 0x479 - SYS___SERVER_PWU = 0x480 - SYS_PTHREAD_TAG_NP = 0x481 - SYS___CONSOLE = 0x482 - SYS___WSINIT = 0x483 - SYS___IPTCPN = 0x489 - SYS___SERVER_CLASSIFY = 0x490 - SYS___HEAPRPT = 0x496 - SYS___ISBFP = 0x500 - SYS___FP_CAST = 0x501 - SYS___CERTIFICATE = 0x502 - SYS_SEND_FILE = 0x503 - SYS_AIO_CANCEL = 0x504 - SYS_AIO_ERROR = 0x505 - SYS_AIO_READ = 0x506 - SYS_AIO_RETURN = 0x507 - SYS_AIO_SUSPEND = 0x508 - SYS_AIO_WRITE = 0x509 - SYS_PTHREAD_RWLOCK_TRYWRLOCK = 0x510 - SYS_PTHREAD_RWLOCK_UNLOCK = 0x511 - SYS_PTHREAD_RWLOCK_WRLOCK = 0x512 - SYS_PTHREAD_RWLOCKATTR_GETPSHARED = 0x513 - SYS_PTHREAD_RWLOCKATTR_SETPSHARED = 0x514 - SYS_PTHREAD_RWLOCKATTR_INIT = 0x515 - SYS_PTHREAD_RWLOCKATTR_DESTROY = 0x516 - SYS___CTTBL = 0x517 - SYS_PTHREAD_MUTEXATTR_SETTYPE = 0x518 - SYS_PTHREAD_MUTEXATTR_GETTYPE = 0x519 - SYS___FP_UNORDERED = 0x520 - SYS___FP_READ_RND = 0x521 - SYS___FP_READ_RND_B = 0x522 - SYS___FP_SWAP_RND = 0x523 - SYS___FP_SWAP_RND_B = 0x524 - SYS___FP_LEVEL = 0x525 - SYS___FP_BTOH = 0x526 - SYS___FP_HTOB = 0x527 - SYS___FPC_RD = 0x528 - SYS___FPC_WR = 0x529 - SYS_PTHREAD_SETCANCELTYPE = 0x600 - SYS_PTHREAD_TESTCANCEL = 0x601 - SYS___ATANF_B = 0x602 - SYS___ATANL_B = 0x603 - SYS___CEILF_B = 0x604 - SYS___CEILL_B = 0x605 - SYS___COSF_B = 0x606 - SYS___COSL_B = 0x607 - SYS___FABSF_B = 0x608 - SYS___FABSL_B = 0x609 - SYS___SINF_B = 0x610 - SYS___SINL_B = 0x611 - SYS___TANF_B = 0x612 - SYS___TANL_B = 0x613 - SYS___TANHF_B = 0x614 - SYS___TANHL_B = 0x615 - SYS___ACOSF_B = 0x616 - SYS___ACOSL_B = 0x617 - SYS___ASINF_B = 0x618 - SYS___ASINL_B = 0x619 - SYS___LOGF_B = 0x620 - SYS___LOGL_B = 0x621 - SYS___LOG10F_B = 0x622 - SYS___LOG10L_B = 0x623 - SYS___POWF_B = 0x624 - SYS___POWL_B = 0x625 - SYS___SINHF_B = 0x626 - SYS___SINHL_B = 0x627 - SYS___SQRTF_B = 0x628 - SYS___SQRTL_B = 0x629 - SYS___MODFL_B = 0x630 - SYS_ABSF = 0x631 - SYS_ABSL = 0x632 - SYS_ACOSF = 0x633 - SYS_ACOSL = 0x634 - SYS_ASINF = 0x635 - SYS_ASINL = 0x636 - SYS_ATAN2F = 0x637 - SYS_ATAN2L = 0x638 - SYS_ATANF = 0x639 - SYS_COSHL = 0x640 - SYS_EXPF = 0x641 - SYS_EXPL = 0x642 - SYS_TANHF = 0x643 - SYS_TANHL = 0x644 - SYS_LOG10F = 0x645 - SYS_LOG10L = 0x646 - SYS_LOGF = 0x647 - SYS_LOGL = 0x648 - SYS_POWF = 0x649 - SYS_SINHL = 0x650 - SYS_TANF = 0x651 - SYS_TANL = 0x652 - SYS_FABSF = 0x653 - SYS_FABSL = 0x654 - SYS_FLOORF = 0x655 - SYS_FLOORL = 0x656 - SYS_FMODF = 0x657 - SYS_FMODL = 0x658 - SYS_FREXPF = 0x659 - SYS___CHATTR = 0x660 - SYS___FCHATTR = 0x661 - SYS___TOCCSID = 0x662 - SYS___CSNAMETYPE = 0x663 - SYS___TOCSNAME = 0x664 - SYS___CCSIDTYPE = 0x665 - SYS___AE_CORRESTBL_QUERY = 0x666 - SYS___AE_AUTOCONVERT_STATE = 0x667 - SYS_DN_FIND = 0x668 - SYS___GETHOSTBYADDR_A = 0x669 - SYS___MBLEN_SB_A = 0x670 - SYS___MBLEN_STD_A = 0x671 - SYS___MBLEN_UTF = 0x672 - SYS___MBSTOWCS_A = 0x673 - SYS___MBSTOWCS_STD_A = 0x674 - SYS___MBTOWC_A = 0x675 - SYS___MBTOWC_ISO1 = 0x676 - SYS___MBTOWC_SBCS = 0x677 - SYS___MBTOWC_MBCS = 0x678 - SYS___MBTOWC_UTF = 0x679 - SYS___CSID_A = 0x680 - SYS___CSID_STD_A = 0x681 - SYS___WCSID_A = 0x682 - SYS___WCSID_STD_A = 0x683 - SYS___WCTOMB_A = 0x684 - SYS___WCTOMB_ISO1 = 0x685 - SYS___WCTOMB_STD_A = 0x686 - SYS___WCTOMB_UTF = 0x687 - SYS___WCWIDTH_A = 0x688 - SYS___GETGRNAM_R_A = 0x689 - SYS___READDIR_R_A = 0x690 - SYS___E2A_S = 0x691 - SYS___FNMATCH_A = 0x692 - SYS___FNMATCH_C_A = 0x693 - SYS___EXECL_A = 0x694 - SYS___FNMATCH_STD_A = 0x695 - SYS___REGCOMP_A = 0x696 - SYS___REGCOMP_STD_A = 0x697 - SYS___REGERROR_A = 0x698 - SYS___REGERROR_STD_A = 0x699 - SYS___SWPRINTF_A = 0x700 - SYS___FSCANF_A = 0x701 - SYS___SCANF_A = 0x702 - SYS___SSCANF_A = 0x703 - SYS___SWSCANF_A = 0x704 - SYS___ATOF_A = 0x705 - SYS___ATOI_A = 0x706 - SYS___ATOL_A = 0x707 - SYS___STRTOD_A = 0x708 - SYS___STRTOL_A = 0x709 - SYS___L64A_A = 0x710 - SYS___STRERROR_A = 0x711 - SYS___PERROR_A = 0x712 - SYS___FETCH_A = 0x713 - SYS___GETENV_A = 0x714 - SYS___MKSTEMP_A = 0x717 - SYS___PTSNAME_A = 0x718 - SYS___PUTENV_A = 0x719 - SYS___CHDIR_A = 0x720 - SYS___CHOWN_A = 0x721 - SYS___CHROOT_A = 0x722 - SYS___GETCWD_A = 0x723 - SYS___GETWD_A = 0x724 - SYS___LCHOWN_A = 0x725 - SYS___LINK_A = 0x726 - SYS___PATHCONF_A = 0x727 - SYS___IF_NAMEINDEX_A = 0x728 - SYS___READLINK_A = 0x729 - SYS___EXTLINK_NP_A = 0x730 - SYS___ISALNUM_A = 0x731 - SYS___ISALPHA_A = 0x732 - SYS___A2E_S = 0x733 - SYS___ISCNTRL_A = 0x734 - SYS___ISDIGIT_A = 0x735 - SYS___ISGRAPH_A = 0x736 - SYS___ISLOWER_A = 0x737 - SYS___ISPRINT_A = 0x738 - SYS___ISPUNCT_A = 0x739 - SYS___ISWALPHA_A = 0x740 - SYS___A2E_L = 0x741 - SYS___ISWCNTRL_A = 0x742 - SYS___ISWDIGIT_A = 0x743 - SYS___ISWGRAPH_A = 0x744 - SYS___ISWLOWER_A = 0x745 - SYS___ISWPRINT_A = 0x746 - SYS___ISWPUNCT_A = 0x747 - SYS___ISWSPACE_A = 0x748 - SYS___ISWUPPER_A = 0x749 - SYS___REMOVE_A = 0x750 - SYS___RENAME_A = 0x751 - SYS___TMPNAM_A = 0x752 - SYS___FOPEN_A = 0x753 - SYS___FREOPEN_A = 0x754 - SYS___CUSERID_A = 0x755 - SYS___POPEN_A = 0x756 - SYS___TEMPNAM_A = 0x757 - SYS___FTW_A = 0x758 - SYS___GETGRENT_A = 0x759 - SYS___INET_NTOP_A = 0x760 - SYS___GETPASS_A = 0x761 - SYS___GETPWENT_A = 0x762 - SYS___GETPWNAM_A = 0x763 - SYS___GETPWUID_A = 0x764 - SYS_____CHECK_RESOURCE_AUTH_NP_A = 0x765 - SYS___CHECKSCHENV_A = 0x766 - SYS___CONNECTSERVER_A = 0x767 - SYS___CONNECTWORKMGR_A = 0x768 - SYS_____CONSOLE_A = 0x769 - SYS___MSGSND_A = 0x770 - SYS___MSGXRCV_A = 0x771 - SYS___NFTW_A = 0x772 - SYS_____PASSWD_A = 0x773 - SYS___PTHREAD_SECURITY_NP_A = 0x774 - SYS___QUERYMETRICS_A = 0x775 - SYS___QUERYSCHENV = 0x776 - SYS___READV_A = 0x777 - SYS_____SERVER_CLASSIFY_A = 0x778 - SYS_____SERVER_INIT_A = 0x779 - SYS___W_GETPSENT_A = 0x780 - SYS___WRITEV_A = 0x781 - SYS___W_STATFS_A = 0x782 - SYS___W_STATVFS_A = 0x783 - SYS___FPUTC_A = 0x784 - SYS___PUTCHAR_A = 0x785 - SYS___PUTS_A = 0x786 - SYS___FGETS_A = 0x787 - SYS___GETS_A = 0x788 - SYS___FPUTS_A = 0x789 - SYS___PUTC_A = 0x790 - SYS___AE_THREAD_SETMODE = 0x791 - SYS___AE_THREAD_SWAPMODE = 0x792 - SYS___GETNETBYADDR_A = 0x793 - SYS___GETNETBYNAME_A = 0x794 - SYS___GETNETENT_A = 0x795 - SYS___GETPROTOBYNAME_A = 0x796 - SYS___GETPROTOBYNUMBER_A = 0x797 - SYS___GETPROTOENT_A = 0x798 - SYS___GETSERVBYNAME_A = 0x799 - SYS_ACL_FIRST_ENTRY = 0x800 - SYS_ACL_GET_ENTRY = 0x801 - SYS_ACL_VALID = 0x802 - SYS_ACL_CREATE_ENTRY = 0x803 - SYS_ACL_DELETE_ENTRY = 0x804 - SYS_ACL_UPDATE_ENTRY = 0x805 - SYS_ACL_DELETE_FD = 0x806 - SYS_ACL_DELETE_FILE = 0x807 - SYS_ACL_GET_FD = 0x808 - SYS_ACL_GET_FILE = 0x809 - SYS___ERFL_B = 0x810 - SYS___ERFCL_B = 0x811 - SYS___LGAMMAL_B = 0x812 - SYS___SETHOOKEVENTS = 0x813 - SYS_IF_NAMETOINDEX = 0x814 - SYS_IF_INDEXTONAME = 0x815 - SYS_IF_NAMEINDEX = 0x816 - SYS_IF_FREENAMEINDEX = 0x817 - SYS_GETADDRINFO = 0x818 - SYS_GETNAMEINFO = 0x819 - SYS___DYNFREE_A = 0x820 - SYS___RES_QUERY_A = 0x821 - SYS___RES_SEARCH_A = 0x822 - SYS___RES_QUERYDOMAIN_A = 0x823 - SYS___RES_MKQUERY_A = 0x824 - SYS___RES_SEND_A = 0x825 - SYS___DN_EXPAND_A = 0x826 - SYS___DN_SKIPNAME_A = 0x827 - SYS___DN_COMP_A = 0x828 - SYS___DN_FIND_A = 0x829 - SYS___INET_NTOA_A = 0x830 - SYS___INET_NETWORK_A = 0x831 - SYS___ACCEPT_A = 0x832 - SYS___ACCEPT_AND_RECV_A = 0x833 - SYS___BIND_A = 0x834 - SYS___CONNECT_A = 0x835 - SYS___GETPEERNAME_A = 0x836 - SYS___GETSOCKNAME_A = 0x837 - SYS___RECVFROM_A = 0x838 - SYS___SENDTO_A = 0x839 - SYS___LCHATTR = 0x840 - SYS___WRITEDOWN = 0x841 - SYS_PTHREAD_MUTEX_INIT2 = 0x842 - SYS___ACOSHF_B = 0x843 - SYS___ACOSHL_B = 0x844 - SYS___ASINHF_B = 0x845 - SYS___ASINHL_B = 0x846 - SYS___ATANHF_B = 0x847 - SYS___ATANHL_B = 0x848 - SYS___CBRTF_B = 0x849 - SYS___EXP2F_B = 0x850 - SYS___EXP2L_B = 0x851 - SYS___EXPM1F_B = 0x852 - SYS___EXPM1L_B = 0x853 - SYS___FDIMF_B = 0x854 - SYS___FDIM_B = 0x855 - SYS___FDIML_B = 0x856 - SYS___HYPOTF_B = 0x857 - SYS___HYPOTL_B = 0x858 - SYS___LOG1PF_B = 0x859 - SYS___REMQUOF_B = 0x860 - SYS___REMQUO_B = 0x861 - SYS___REMQUOL_B = 0x862 - SYS___TGAMMAF_B = 0x863 - SYS___TGAMMA_B = 0x864 - SYS___TGAMMAL_B = 0x865 - SYS___TRUNCF_B = 0x866 - SYS___TRUNC_B = 0x867 - SYS___TRUNCL_B = 0x868 - SYS___LGAMMAF_B = 0x869 - SYS_ASINHF = 0x870 - SYS_ASINHL = 0x871 - SYS_ATANHF = 0x872 - SYS_ATANHL = 0x873 - SYS_CBRTF = 0x874 - SYS_CBRTL = 0x875 - SYS_COPYSIGNF = 0x876 - SYS_CPYSIGNF = 0x876 - SYS_COPYSIGNL = 0x877 - SYS_CPYSIGNL = 0x877 - SYS_COTANF = 0x878 - SYS___COTANF = 0x878 - SYS_COTAN = 0x879 - SYS___COTAN = 0x879 - SYS_FDIM = 0x881 - SYS_FDIML = 0x882 - SYS_HYPOTF = 0x883 - SYS_HYPOTL = 0x884 - SYS_LOG1PF = 0x885 - SYS_LOG1PL = 0x886 - SYS_LOG2F = 0x887 - SYS_LOG2 = 0x888 - SYS_LOG2L = 0x889 - SYS_TGAMMA = 0x890 - SYS_TGAMMAL = 0x891 - SYS_TRUNCF = 0x892 - SYS_TRUNC = 0x893 - SYS_TRUNCL = 0x894 - SYS_LGAMMAF = 0x895 - SYS_LGAMMAL = 0x896 - SYS_LROUNDF = 0x897 - SYS_LROUND = 0x898 - SYS_ERFF = 0x899 - SYS___COSHF_H = 0x900 - SYS___COSHL_H = 0x901 - SYS___COTAN_H = 0x902 - SYS___COTANF_H = 0x903 - SYS___COTANL_H = 0x904 - SYS___ERF_H = 0x905 - SYS___ERFF_H = 0x906 - SYS___ERFL_H = 0x907 - SYS___ERFC_H = 0x908 - SYS___ERFCF_H = 0x909 - SYS___FDIMF_H = 0x910 - SYS___FDIML_H = 0x911 - SYS___FMOD_H = 0x912 - SYS___FMODF_H = 0x913 - SYS___FMODL_H = 0x914 - SYS___GAMMA_H = 0x915 - SYS___HYPOT_H = 0x916 - SYS___ILOGB_H = 0x917 - SYS___LGAMMA_H = 0x918 - SYS___LGAMMAF_H = 0x919 - SYS___LOG2L_H = 0x920 - SYS___LOG1P_H = 0x921 - SYS___LOG10_H = 0x922 - SYS___LOG10F_H = 0x923 - SYS___LOG10L_H = 0x924 - SYS___LROUND_H = 0x925 - SYS___LROUNDF_H = 0x926 - SYS___NEXTAFTER_H = 0x927 - SYS___POW_H = 0x928 - SYS___POWF_H = 0x929 - SYS___SINL_H = 0x930 - SYS___SINH_H = 0x931 - SYS___SINHF_H = 0x932 - SYS___SINHL_H = 0x933 - SYS___SQRT_H = 0x934 - SYS___SQRTF_H = 0x935 - SYS___SQRTL_H = 0x936 - SYS___TAN_H = 0x937 - SYS___TANF_H = 0x938 - SYS___TANL_H = 0x939 - SYS___TRUNCF_H = 0x940 - SYS___TRUNCL_H = 0x941 - SYS___COSH_H = 0x942 - SYS___LE_DEBUG_SET_RESUME_MCH = 0x943 - SYS_VFSCANF = 0x944 - SYS_VSCANF = 0x946 - SYS_VSSCANF = 0x948 - SYS_IMAXABS = 0x950 - SYS_IMAXDIV = 0x951 - SYS_STRTOIMAX = 0x952 - SYS_STRTOUMAX = 0x953 - SYS_WCSTOIMAX = 0x954 - SYS_WCSTOUMAX = 0x955 - SYS_ATOLL = 0x956 - SYS_STRTOF = 0x957 - SYS_STRTOLD = 0x958 - SYS_WCSTOF = 0x959 - SYS_INET6_RTH_GETADDR = 0x960 - SYS_INET6_OPT_INIT = 0x961 - SYS_INET6_OPT_APPEND = 0x962 - SYS_INET6_OPT_FINISH = 0x963 - SYS_INET6_OPT_SET_VAL = 0x964 - SYS_INET6_OPT_NEXT = 0x965 - SYS_INET6_OPT_FIND = 0x966 - SYS_INET6_OPT_GET_VAL = 0x967 - SYS___POW_I = 0x987 - SYS___POW_I_B = 0x988 - SYS___POW_I_H = 0x989 - SYS___CABS_H = 0x990 - SYS_CABSF = 0x991 - SYS___CABSF_B = 0x992 - SYS___CABSF_H = 0x993 - SYS_CABSL = 0x994 - SYS___CABSL_B = 0x995 - SYS___CABSL_H = 0x996 - SYS_CACOS = 0x997 - SYS___CACOS_B = 0x998 - SYS___CACOS_H = 0x999 + SYS_LOG = 0x17 // 23 + SYS_COSH = 0x18 // 24 + SYS_TANH = 0x19 // 25 + SYS_EXP = 0x1A // 26 + SYS_MODF = 0x1B // 27 + SYS_LOG10 = 0x1C // 28 + SYS_FREXP = 0x1D // 29 + SYS_LDEXP = 0x1E // 30 + SYS_CEIL = 0x1F // 31 + SYS_POW = 0x20 // 32 + SYS_SQRT = 0x21 // 33 + SYS_FLOOR = 0x22 // 34 + SYS_J1 = 0x23 // 35 + SYS_FABS = 0x24 // 36 + SYS_FMOD = 0x25 // 37 + SYS_J0 = 0x26 // 38 + SYS_YN = 0x27 // 39 + SYS_JN = 0x28 // 40 + SYS_Y0 = 0x29 // 41 + SYS_Y1 = 0x2A // 42 + SYS_HYPOT = 0x2B // 43 + SYS_ERF = 0x2C // 44 + SYS_ERFC = 0x2D // 45 + SYS_GAMMA = 0x2E // 46 + SYS_ISALPHA = 0x30 // 48 + SYS_ISALNUM = 0x31 // 49 + SYS_ISLOWER = 0x32 // 50 + SYS_ISCNTRL = 0x33 // 51 + SYS_ISDIGIT = 0x34 // 52 + SYS_ISGRAPH = 0x35 // 53 + SYS_ISUPPER = 0x36 // 54 + SYS_ISPRINT = 0x37 // 55 + SYS_ISPUNCT = 0x38 // 56 + SYS_ISSPACE = 0x39 // 57 + SYS_SETLOCAL = 0x3A // 58 + SYS_SETLOCALE = 0x3A // 58 + SYS_ISXDIGIT = 0x3B // 59 + SYS_TOLOWER = 0x3C // 60 + SYS_TOUPPER = 0x3D // 61 + SYS_ASIN = 0x3E // 62 + SYS_SIN = 0x3F // 63 + SYS_COS = 0x40 // 64 + SYS_TAN = 0x41 // 65 + SYS_SINH = 0x42 // 66 + SYS_ACOS = 0x43 // 67 + SYS_ATAN = 0x44 // 68 + SYS_ATAN2 = 0x45 // 69 + SYS_FTELL = 0x46 // 70 + SYS_FGETPOS = 0x47 // 71 + SYS_FSEEK = 0x48 // 72 + SYS_FSETPOS = 0x49 // 73 + SYS_FERROR = 0x4A // 74 + SYS_REWIND = 0x4B // 75 + SYS_CLEARERR = 0x4C // 76 + SYS_FEOF = 0x4D // 77 + SYS_ATOL = 0x4E // 78 + SYS_PERROR = 0x4F // 79 + SYS_ATOF = 0x50 // 80 + SYS_ATOI = 0x51 // 81 + SYS_RAND = 0x52 // 82 + SYS_STRTOD = 0x53 // 83 + SYS_STRTOL = 0x54 // 84 + SYS_STRTOUL = 0x55 // 85 + SYS_MALLOC = 0x56 // 86 + SYS_SRAND = 0x57 // 87 + SYS_CALLOC = 0x58 // 88 + SYS_FREE = 0x59 // 89 + SYS_EXIT = 0x5A // 90 + SYS_REALLOC = 0x5B // 91 + SYS_ABORT = 0x5C // 92 + SYS___ABORT = 0x5C // 92 + SYS_ATEXIT = 0x5D // 93 + SYS_RAISE = 0x5E // 94 + SYS_SETJMP = 0x5F // 95 + SYS_LONGJMP = 0x60 // 96 + SYS_SIGNAL = 0x61 // 97 + SYS_TMPNAM = 0x62 // 98 + SYS_REMOVE = 0x63 // 99 + SYS_RENAME = 0x64 // 100 + SYS_TMPFILE = 0x65 // 101 + SYS_FREOPEN = 0x66 // 102 + SYS_FCLOSE = 0x67 // 103 + SYS_FFLUSH = 0x68 // 104 + SYS_FOPEN = 0x69 // 105 + SYS_FSCANF = 0x6A // 106 + SYS_SETBUF = 0x6B // 107 + SYS_SETVBUF = 0x6C // 108 + SYS_FPRINTF = 0x6D // 109 + SYS_SSCANF = 0x6E // 110 + SYS_PRINTF = 0x6F // 111 + SYS_SCANF = 0x70 // 112 + SYS_SPRINTF = 0x71 // 113 + SYS_FGETC = 0x72 // 114 + SYS_VFPRINTF = 0x73 // 115 + SYS_VPRINTF = 0x74 // 116 + SYS_VSPRINTF = 0x75 // 117 + SYS_GETC = 0x76 // 118 + SYS_FGETS = 0x77 // 119 + SYS_FPUTC = 0x78 // 120 + SYS_FPUTS = 0x79 // 121 + SYS_PUTCHAR = 0x7A // 122 + SYS_GETCHAR = 0x7B // 123 + SYS_GETS = 0x7C // 124 + SYS_PUTC = 0x7D // 125 + SYS_FWRITE = 0x7E // 126 + SYS_PUTS = 0x7F // 127 + SYS_UNGETC = 0x80 // 128 + SYS_FREAD = 0x81 // 129 + SYS_WCSTOMBS = 0x82 // 130 + SYS_MBTOWC = 0x83 // 131 + SYS_WCTOMB = 0x84 // 132 + SYS_MBSTOWCS = 0x85 // 133 + SYS_WCSCPY = 0x86 // 134 + SYS_WCSCAT = 0x87 // 135 + SYS_WCSCHR = 0x88 // 136 + SYS_WCSCMP = 0x89 // 137 + SYS_WCSNCMP = 0x8A // 138 + SYS_WCSCSPN = 0x8B // 139 + SYS_WCSLEN = 0x8C // 140 + SYS_WCSNCAT = 0x8D // 141 + SYS_WCSSPN = 0x8E // 142 + SYS_WCSNCPY = 0x8F // 143 + SYS_ABS = 0x90 // 144 + SYS_DIV = 0x91 // 145 + SYS_LABS = 0x92 // 146 + SYS_STRNCPY = 0x93 // 147 + SYS_MEMCPY = 0x94 // 148 + SYS_MEMMOVE = 0x95 // 149 + SYS_STRCPY = 0x96 // 150 + SYS_STRCMP = 0x97 // 151 + SYS_STRCAT = 0x98 // 152 + SYS_STRNCAT = 0x99 // 153 + SYS_MEMCMP = 0x9A // 154 + SYS_MEMCHR = 0x9B // 155 + SYS_STRCOLL = 0x9C // 156 + SYS_STRNCMP = 0x9D // 157 + SYS_STRXFRM = 0x9E // 158 + SYS_STRRCHR = 0x9F // 159 + SYS_STRCHR = 0xA0 // 160 + SYS_STRCSPN = 0xA1 // 161 + SYS_STRPBRK = 0xA2 // 162 + SYS_MEMSET = 0xA3 // 163 + SYS_STRSPN = 0xA4 // 164 + SYS_STRSTR = 0xA5 // 165 + SYS_STRTOK = 0xA6 // 166 + SYS_DIFFTIME = 0xA7 // 167 + SYS_STRERROR = 0xA8 // 168 + SYS_STRLEN = 0xA9 // 169 + SYS_CLOCK = 0xAA // 170 + SYS_CTIME = 0xAB // 171 + SYS_MKTIME = 0xAC // 172 + SYS_TIME = 0xAD // 173 + SYS_ASCTIME = 0xAE // 174 + SYS_MBLEN = 0xAF // 175 + SYS_GMTIME = 0xB0 // 176 + SYS_LOCALTIM = 0xB1 // 177 + SYS_LOCALTIME = 0xB1 // 177 + SYS_STRFTIME = 0xB2 // 178 + SYS___GETCB = 0xB4 // 180 + SYS_FUPDATE = 0xB5 // 181 + SYS___FUPDT = 0xB5 // 181 + SYS_CLRMEMF = 0xBD // 189 + SYS___CLRMF = 0xBD // 189 + SYS_FETCHEP = 0xBF // 191 + SYS___FTCHEP = 0xBF // 191 + SYS_FLDATA = 0xC1 // 193 + SYS___FLDATA = 0xC1 // 193 + SYS_DYNFREE = 0xC2 // 194 + SYS___DYNFRE = 0xC2 // 194 + SYS_DYNALLOC = 0xC3 // 195 + SYS___DYNALL = 0xC3 // 195 + SYS___CDUMP = 0xC4 // 196 + SYS_CSNAP = 0xC5 // 197 + SYS___CSNAP = 0xC5 // 197 + SYS_CTRACE = 0xC6 // 198 + SYS___CTRACE = 0xC6 // 198 + SYS___CTEST = 0xC7 // 199 + SYS_SETENV = 0xC8 // 200 + SYS___SETENV = 0xC8 // 200 + SYS_CLEARENV = 0xC9 // 201 + SYS___CLRENV = 0xC9 // 201 + SYS___REGCOMP_STD = 0xEA // 234 + SYS_NL_LANGINFO = 0xFC // 252 + SYS_GETSYNTX = 0xFD // 253 + SYS_ISBLANK = 0xFE // 254 + SYS___ISBLNK = 0xFE // 254 + SYS_ISWALNUM = 0xFF // 255 + SYS_ISWALPHA = 0x100 // 256 + SYS_ISWBLANK = 0x101 // 257 + SYS___ISWBLK = 0x101 // 257 + SYS_ISWCNTRL = 0x102 // 258 + SYS_ISWDIGIT = 0x103 // 259 + SYS_ISWGRAPH = 0x104 // 260 + SYS_ISWLOWER = 0x105 // 261 + SYS_ISWPRINT = 0x106 // 262 + SYS_ISWPUNCT = 0x107 // 263 + SYS_ISWSPACE = 0x108 // 264 + SYS_ISWUPPER = 0x109 // 265 + SYS_ISWXDIGI = 0x10A // 266 + SYS_ISWXDIGIT = 0x10A // 266 + SYS_WCTYPE = 0x10B // 267 + SYS_ISWCTYPE = 0x10C // 268 + SYS_TOWLOWER = 0x10D // 269 + SYS_TOWUPPER = 0x10E // 270 + SYS_MBSINIT = 0x10F // 271 + SYS_WCTOB = 0x110 // 272 + SYS_MBRLEN = 0x111 // 273 + SYS_MBRTOWC = 0x112 // 274 + SYS_MBSRTOWC = 0x113 // 275 + SYS_MBSRTOWCS = 0x113 // 275 + SYS_WCRTOMB = 0x114 // 276 + SYS_WCSRTOMB = 0x115 // 277 + SYS_WCSRTOMBS = 0x115 // 277 + SYS___CSID = 0x116 // 278 + SYS___WCSID = 0x117 // 279 + SYS_STRPTIME = 0x118 // 280 + SYS___STRPTM = 0x118 // 280 + SYS_STRFMON = 0x119 // 281 + SYS___RPMTCH = 0x11A // 282 + SYS_WCSSTR = 0x11B // 283 + SYS_WCSTOK = 0x12C // 300 + SYS_WCSTOL = 0x12D // 301 + SYS_WCSTOD = 0x12E // 302 + SYS_WCSTOUL = 0x12F // 303 + SYS_WCSCOLL = 0x130 // 304 + SYS_WCSXFRM = 0x131 // 305 + SYS_WCSWIDTH = 0x132 // 306 + SYS_WCWIDTH = 0x133 // 307 + SYS_WCSFTIME = 0x134 // 308 + SYS_SWPRINTF = 0x135 // 309 + SYS_VSWPRINT = 0x136 // 310 + SYS_VSWPRINTF = 0x136 // 310 + SYS_SWSCANF = 0x137 // 311 + SYS_REGCOMP = 0x138 // 312 + SYS_REGEXEC = 0x139 // 313 + SYS_REGFREE = 0x13A // 314 + SYS_REGERROR = 0x13B // 315 + SYS_FGETWC = 0x13C // 316 + SYS_FGETWS = 0x13D // 317 + SYS_FPUTWC = 0x13E // 318 + SYS_FPUTWS = 0x13F // 319 + SYS_GETWC = 0x140 // 320 + SYS_GETWCHAR = 0x141 // 321 + SYS_PUTWC = 0x142 // 322 + SYS_PUTWCHAR = 0x143 // 323 + SYS_UNGETWC = 0x144 // 324 + SYS_ICONV_OPEN = 0x145 // 325 + SYS_ICONV = 0x146 // 326 + SYS_ICONV_CLOSE = 0x147 // 327 + SYS_ISMCCOLLEL = 0x14C // 332 + SYS_STRTOCOLL = 0x14D // 333 + SYS_COLLTOSTR = 0x14E // 334 + SYS_COLLEQUIV = 0x14F // 335 + SYS_COLLRANGE = 0x150 // 336 + SYS_CCLASS = 0x151 // 337 + SYS_COLLORDER = 0x152 // 338 + SYS___DEMANGLE = 0x154 // 340 + SYS_FDOPEN = 0x155 // 341 + SYS___ERRNO = 0x156 // 342 + SYS___ERRNO2 = 0x157 // 343 + SYS___TERROR = 0x158 // 344 + SYS_MAXCOLL = 0x169 // 361 + SYS_GETMCCOLL = 0x16A // 362 + SYS_GETWMCCOLL = 0x16B // 363 + SYS___ERR2AD = 0x16C // 364 + SYS_DLLQUERYFN = 0x16D // 365 + SYS_DLLQUERYVAR = 0x16E // 366 + SYS_DLLFREE = 0x16F // 367 + SYS_DLLLOAD = 0x170 // 368 + SYS__EXIT = 0x174 // 372 + SYS_ACCESS = 0x175 // 373 + SYS_ALARM = 0x176 // 374 + SYS_CFGETISPEED = 0x177 // 375 + SYS_CFGETOSPEED = 0x178 // 376 + SYS_CFSETISPEED = 0x179 // 377 + SYS_CFSETOSPEED = 0x17A // 378 + SYS_CHDIR = 0x17B // 379 + SYS_CHMOD = 0x17C // 380 + SYS_CHOWN = 0x17D // 381 + SYS_CLOSE = 0x17E // 382 + SYS_CLOSEDIR = 0x17F // 383 + SYS_CREAT = 0x180 // 384 + SYS_CTERMID = 0x181 // 385 + SYS_DUP = 0x182 // 386 + SYS_DUP2 = 0x183 // 387 + SYS_EXECL = 0x184 // 388 + SYS_EXECLE = 0x185 // 389 + SYS_EXECLP = 0x186 // 390 + SYS_EXECV = 0x187 // 391 + SYS_EXECVE = 0x188 // 392 + SYS_EXECVP = 0x189 // 393 + SYS_FCHMOD = 0x18A // 394 + SYS_FCHOWN = 0x18B // 395 + SYS_FCNTL = 0x18C // 396 + SYS_FILENO = 0x18D // 397 + SYS_FORK = 0x18E // 398 + SYS_FPATHCONF = 0x18F // 399 + SYS_FSTAT = 0x190 // 400 + SYS_FSYNC = 0x191 // 401 + SYS_FTRUNCATE = 0x192 // 402 + SYS_GETCWD = 0x193 // 403 + SYS_GETEGID = 0x194 // 404 + SYS_GETEUID = 0x195 // 405 + SYS_GETGID = 0x196 // 406 + SYS_GETGRGID = 0x197 // 407 + SYS_GETGRNAM = 0x198 // 408 + SYS_GETGROUPS = 0x199 // 409 + SYS_GETLOGIN = 0x19A // 410 + SYS_W_GETMNTENT = 0x19B // 411 + SYS_GETPGRP = 0x19C // 412 + SYS_GETPID = 0x19D // 413 + SYS_GETPPID = 0x19E // 414 + SYS_GETPWNAM = 0x19F // 415 + SYS_GETPWUID = 0x1A0 // 416 + SYS_GETUID = 0x1A1 // 417 + SYS_W_IOCTL = 0x1A2 // 418 + SYS_ISATTY = 0x1A3 // 419 + SYS_KILL = 0x1A4 // 420 + SYS_LINK = 0x1A5 // 421 + SYS_LSEEK = 0x1A6 // 422 + SYS_LSTAT = 0x1A7 // 423 + SYS_MKDIR = 0x1A8 // 424 + SYS_MKFIFO = 0x1A9 // 425 + SYS_MKNOD = 0x1AA // 426 + SYS_MOUNT = 0x1AB // 427 + SYS_OPEN = 0x1AC // 428 + SYS_OPENDIR = 0x1AD // 429 + SYS_PATHCONF = 0x1AE // 430 + SYS_PAUSE = 0x1AF // 431 + SYS_PIPE = 0x1B0 // 432 + SYS_W_GETPSENT = 0x1B1 // 433 + SYS_READ = 0x1B2 // 434 + SYS_READDIR = 0x1B3 // 435 + SYS_READLINK = 0x1B4 // 436 + SYS_REWINDDIR = 0x1B5 // 437 + SYS_RMDIR = 0x1B6 // 438 + SYS_SETEGID = 0x1B7 // 439 + SYS_SETEUID = 0x1B8 // 440 + SYS_SETGID = 0x1B9 // 441 + SYS_SETPGID = 0x1BA // 442 + SYS_SETSID = 0x1BB // 443 + SYS_SETUID = 0x1BC // 444 + SYS_SIGACTION = 0x1BD // 445 + SYS_SIGADDSET = 0x1BE // 446 + SYS_SIGDELSET = 0x1BF // 447 + SYS_SIGEMPTYSET = 0x1C0 // 448 + SYS_SIGFILLSET = 0x1C1 // 449 + SYS_SIGISMEMBER = 0x1C2 // 450 + SYS_SIGLONGJMP = 0x1C3 // 451 + SYS_SIGPENDING = 0x1C4 // 452 + SYS_SIGPROCMASK = 0x1C5 // 453 + SYS_SIGSETJMP = 0x1C6 // 454 + SYS_SIGSUSPEND = 0x1C7 // 455 + SYS_SLEEP = 0x1C8 // 456 + SYS_STAT = 0x1C9 // 457 + SYS_W_STATFS = 0x1CA // 458 + SYS_SYMLINK = 0x1CB // 459 + SYS_SYSCONF = 0x1CC // 460 + SYS_TCDRAIN = 0x1CD // 461 + SYS_TCFLOW = 0x1CE // 462 + SYS_TCFLUSH = 0x1CF // 463 + SYS_TCGETATTR = 0x1D0 // 464 + SYS_TCGETPGRP = 0x1D1 // 465 + SYS_TCSENDBREAK = 0x1D2 // 466 + SYS_TCSETATTR = 0x1D3 // 467 + SYS_TCSETPGRP = 0x1D4 // 468 + SYS_TIMES = 0x1D5 // 469 + SYS_TTYNAME = 0x1D6 // 470 + SYS_TZSET = 0x1D7 // 471 + SYS_UMASK = 0x1D8 // 472 + SYS_UMOUNT = 0x1D9 // 473 + SYS_UNAME = 0x1DA // 474 + SYS_UNLINK = 0x1DB // 475 + SYS_UTIME = 0x1DC // 476 + SYS_WAIT = 0x1DD // 477 + SYS_WAITPID = 0x1DE // 478 + SYS_WRITE = 0x1DF // 479 + SYS_CHAUDIT = 0x1E0 // 480 + SYS_FCHAUDIT = 0x1E1 // 481 + SYS_GETGROUPSBYNAME = 0x1E2 // 482 + SYS_SIGWAIT = 0x1E3 // 483 + SYS_PTHREAD_EXIT = 0x1E4 // 484 + SYS_PTHREAD_KILL = 0x1E5 // 485 + SYS_PTHREAD_ATTR_INIT = 0x1E6 // 486 + SYS_PTHREAD_ATTR_DESTROY = 0x1E7 // 487 + SYS_PTHREAD_ATTR_SETSTACKSIZE = 0x1E8 // 488 + SYS_PTHREAD_ATTR_GETSTACKSIZE = 0x1E9 // 489 + SYS_PTHREAD_ATTR_SETDETACHSTATE = 0x1EA // 490 + SYS_PTHREAD_ATTR_GETDETACHSTATE = 0x1EB // 491 + SYS_PTHREAD_ATTR_SETWEIGHT_NP = 0x1EC // 492 + SYS_PTHREAD_ATTR_GETWEIGHT_NP = 0x1ED // 493 + SYS_PTHREAD_CANCEL = 0x1EE // 494 + SYS_PTHREAD_CLEANUP_PUSH = 0x1EF // 495 + SYS_PTHREAD_CLEANUP_POP = 0x1F0 // 496 + SYS_PTHREAD_CONDATTR_INIT = 0x1F1 // 497 + SYS_PTHREAD_CONDATTR_DESTROY = 0x1F2 // 498 + SYS_PTHREAD_COND_INIT = 0x1F3 // 499 + SYS_PTHREAD_COND_DESTROY = 0x1F4 // 500 + SYS_PTHREAD_COND_SIGNAL = 0x1F5 // 501 + SYS_PTHREAD_COND_BROADCAST = 0x1F6 // 502 + SYS_PTHREAD_COND_WAIT = 0x1F7 // 503 + SYS_PTHREAD_COND_TIMEDWAIT = 0x1F8 // 504 + SYS_PTHREAD_CREATE = 0x1F9 // 505 + SYS_PTHREAD_DETACH = 0x1FA // 506 + SYS_PTHREAD_EQUAL = 0x1FB // 507 + SYS_PTHREAD_GETSPECIFIC = 0x1FC // 508 + SYS_PTHREAD_JOIN = 0x1FD // 509 + SYS_PTHREAD_KEY_CREATE = 0x1FE // 510 + SYS_PTHREAD_MUTEXATTR_INIT = 0x1FF // 511 + SYS_PTHREAD_MUTEXATTR_DESTROY = 0x200 // 512 + SYS_PTHREAD_MUTEXATTR_SETKIND_NP = 0x201 // 513 + SYS_PTHREAD_MUTEXATTR_GETKIND_NP = 0x202 // 514 + SYS_PTHREAD_MUTEX_INIT = 0x203 // 515 + SYS_PTHREAD_MUTEX_DESTROY = 0x204 // 516 + SYS_PTHREAD_MUTEX_LOCK = 0x205 // 517 + SYS_PTHREAD_MUTEX_TRYLOCK = 0x206 // 518 + SYS_PTHREAD_MUTEX_UNLOCK = 0x207 // 519 + SYS_PTHREAD_ONCE = 0x209 // 521 + SYS_PTHREAD_SELF = 0x20A // 522 + SYS_PTHREAD_SETINTR = 0x20B // 523 + SYS_PTHREAD_SETINTRTYPE = 0x20C // 524 + SYS_PTHREAD_SETSPECIFIC = 0x20D // 525 + SYS_PTHREAD_TESTINTR = 0x20E // 526 + SYS_PTHREAD_YIELD = 0x20F // 527 + SYS_TW_OPEN = 0x210 // 528 + SYS_TW_FCNTL = 0x211 // 529 + SYS_PTHREAD_JOIN_D4_NP = 0x212 // 530 + SYS_PTHREAD_CONDATTR_SETKIND_NP = 0x213 // 531 + SYS_PTHREAD_CONDATTR_GETKIND_NP = 0x214 // 532 + SYS_EXTLINK_NP = 0x215 // 533 + SYS___PASSWD = 0x216 // 534 + SYS_SETGROUPS = 0x217 // 535 + SYS_INITGROUPS = 0x218 // 536 + SYS_WCSPBRK = 0x23F // 575 + SYS_WCSRCHR = 0x240 // 576 + SYS_SVC99 = 0x241 // 577 + SYS___SVC99 = 0x241 // 577 + SYS_WCSWCS = 0x242 // 578 + SYS_LOCALECO = 0x243 // 579 + SYS_LOCALECONV = 0x243 // 579 + SYS___LIBREL = 0x244 // 580 + SYS_RELEASE = 0x245 // 581 + SYS___RLSE = 0x245 // 581 + SYS_FLOCATE = 0x246 // 582 + SYS___FLOCT = 0x246 // 582 + SYS_FDELREC = 0x247 // 583 + SYS___FDLREC = 0x247 // 583 + SYS_FETCH = 0x248 // 584 + SYS___FETCH = 0x248 // 584 + SYS_QSORT = 0x249 // 585 + SYS_GETENV = 0x24A // 586 + SYS_SYSTEM = 0x24B // 587 + SYS_BSEARCH = 0x24C // 588 + SYS_LDIV = 0x24D // 589 + SYS___THROW = 0x25E // 606 + SYS___RETHROW = 0x25F // 607 + SYS___CLEANUPCATCH = 0x260 // 608 + SYS___CATCHMATCH = 0x261 // 609 + SYS___CLEAN2UPCATCH = 0x262 // 610 + SYS_PUTENV = 0x26A // 618 + SYS___GETENV = 0x26F // 623 + SYS_GETPRIORITY = 0x270 // 624 + SYS_NICE = 0x271 // 625 + SYS_SETPRIORITY = 0x272 // 626 + SYS_GETITIMER = 0x273 // 627 + SYS_SETITIMER = 0x274 // 628 + SYS_MSGCTL = 0x275 // 629 + SYS_MSGGET = 0x276 // 630 + SYS_MSGRCV = 0x277 // 631 + SYS_MSGSND = 0x278 // 632 + SYS_MSGXRCV = 0x279 // 633 + SYS___MSGXR = 0x279 // 633 + SYS_SEMCTL = 0x27A // 634 + SYS_SEMGET = 0x27B // 635 + SYS_SEMOP = 0x27C // 636 + SYS_SHMAT = 0x27D // 637 + SYS_SHMCTL = 0x27E // 638 + SYS_SHMDT = 0x27F // 639 + SYS_SHMGET = 0x280 // 640 + SYS___GETIPC = 0x281 // 641 + SYS_SETGRENT = 0x282 // 642 + SYS_GETGRENT = 0x283 // 643 + SYS_ENDGRENT = 0x284 // 644 + SYS_SETPWENT = 0x285 // 645 + SYS_GETPWENT = 0x286 // 646 + SYS_ENDPWENT = 0x287 // 647 + SYS_BSD_SIGNAL = 0x288 // 648 + SYS_KILLPG = 0x289 // 649 + SYS_SIGALTSTACK = 0x28A // 650 + SYS_SIGHOLD = 0x28B // 651 + SYS_SIGIGNORE = 0x28C // 652 + SYS_SIGINTERRUPT = 0x28D // 653 + SYS_SIGPAUSE = 0x28E // 654 + SYS_SIGRELSE = 0x28F // 655 + SYS_SIGSET = 0x290 // 656 + SYS_SIGSTACK = 0x291 // 657 + SYS_GETRLIMIT = 0x292 // 658 + SYS_SETRLIMIT = 0x293 // 659 + SYS_GETRUSAGE = 0x294 // 660 + SYS_MMAP = 0x295 // 661 + SYS_MPROTECT = 0x296 // 662 + SYS_MSYNC = 0x297 // 663 + SYS_MUNMAP = 0x298 // 664 + SYS_CONFSTR = 0x299 // 665 + SYS_GETOPT = 0x29A // 666 + SYS_LCHOWN = 0x29B // 667 + SYS_TRUNCATE = 0x29C // 668 + SYS_GETSUBOPT = 0x29D // 669 + SYS_SETPGRP = 0x29E // 670 + SYS___GDERR = 0x29F // 671 + SYS___TZONE = 0x2A0 // 672 + SYS___DLGHT = 0x2A1 // 673 + SYS___OPARGF = 0x2A2 // 674 + SYS___OPOPTF = 0x2A3 // 675 + SYS___OPINDF = 0x2A4 // 676 + SYS___OPERRF = 0x2A5 // 677 + SYS_GETDATE = 0x2A6 // 678 + SYS_WAIT3 = 0x2A7 // 679 + SYS_WAITID = 0x2A8 // 680 + SYS___CATTRM = 0x2A9 // 681 + SYS___GDTRM = 0x2AA // 682 + SYS___RNDTRM = 0x2AB // 683 + SYS_CRYPT = 0x2AC // 684 + SYS_ENCRYPT = 0x2AD // 685 + SYS_SETKEY = 0x2AE // 686 + SYS___CNVBLK = 0x2AF // 687 + SYS___CRYTRM = 0x2B0 // 688 + SYS___ECRTRM = 0x2B1 // 689 + SYS_DRAND48 = 0x2B2 // 690 + SYS_ERAND48 = 0x2B3 // 691 + SYS_FSTATVFS = 0x2B4 // 692 + SYS_STATVFS = 0x2B5 // 693 + SYS_CATCLOSE = 0x2B6 // 694 + SYS_CATGETS = 0x2B7 // 695 + SYS_CATOPEN = 0x2B8 // 696 + SYS_BCMP = 0x2B9 // 697 + SYS_BCOPY = 0x2BA // 698 + SYS_BZERO = 0x2BB // 699 + SYS_FFS = 0x2BC // 700 + SYS_INDEX = 0x2BD // 701 + SYS_RINDEX = 0x2BE // 702 + SYS_STRCASECMP = 0x2BF // 703 + SYS_STRDUP = 0x2C0 // 704 + SYS_STRNCASECMP = 0x2C1 // 705 + SYS_INITSTATE = 0x2C2 // 706 + SYS_SETSTATE = 0x2C3 // 707 + SYS_RANDOM = 0x2C4 // 708 + SYS_SRANDOM = 0x2C5 // 709 + SYS_HCREATE = 0x2C6 // 710 + SYS_HDESTROY = 0x2C7 // 711 + SYS_HSEARCH = 0x2C8 // 712 + SYS_LFIND = 0x2C9 // 713 + SYS_LSEARCH = 0x2CA // 714 + SYS_TDELETE = 0x2CB // 715 + SYS_TFIND = 0x2CC // 716 + SYS_TSEARCH = 0x2CD // 717 + SYS_TWALK = 0x2CE // 718 + SYS_INSQUE = 0x2CF // 719 + SYS_REMQUE = 0x2D0 // 720 + SYS_POPEN = 0x2D1 // 721 + SYS_PCLOSE = 0x2D2 // 722 + SYS_SWAB = 0x2D3 // 723 + SYS_MEMCCPY = 0x2D4 // 724 + SYS_GETPAGESIZE = 0x2D8 // 728 + SYS_FCHDIR = 0x2D9 // 729 + SYS___OCLCK = 0x2DA // 730 + SYS___ATOE = 0x2DB // 731 + SYS___ATOE_L = 0x2DC // 732 + SYS___ETOA = 0x2DD // 733 + SYS___ETOA_L = 0x2DE // 734 + SYS_SETUTXENT = 0x2DF // 735 + SYS_GETUTXENT = 0x2E0 // 736 + SYS_ENDUTXENT = 0x2E1 // 737 + SYS_GETUTXID = 0x2E2 // 738 + SYS_GETUTXLINE = 0x2E3 // 739 + SYS_PUTUTXLINE = 0x2E4 // 740 + SYS_FMTMSG = 0x2E5 // 741 + SYS_JRAND48 = 0x2E6 // 742 + SYS_LRAND48 = 0x2E7 // 743 + SYS_MRAND48 = 0x2E8 // 744 + SYS_NRAND48 = 0x2E9 // 745 + SYS_LCONG48 = 0x2EA // 746 + SYS_SRAND48 = 0x2EB // 747 + SYS_SEED48 = 0x2EC // 748 + SYS_ISASCII = 0x2ED // 749 + SYS_TOASCII = 0x2EE // 750 + SYS_A64L = 0x2EF // 751 + SYS_L64A = 0x2F0 // 752 + SYS_UALARM = 0x2F1 // 753 + SYS_USLEEP = 0x2F2 // 754 + SYS___UTXTRM = 0x2F3 // 755 + SYS___SRCTRM = 0x2F4 // 756 + SYS_FTIME = 0x2F5 // 757 + SYS_GETTIMEOFDAY = 0x2F6 // 758 + SYS_DBM_CLEARERR = 0x2F7 // 759 + SYS_DBM_CLOSE = 0x2F8 // 760 + SYS_DBM_DELETE = 0x2F9 // 761 + SYS_DBM_ERROR = 0x2FA // 762 + SYS_DBM_FETCH = 0x2FB // 763 + SYS_DBM_FIRSTKEY = 0x2FC // 764 + SYS_DBM_NEXTKEY = 0x2FD // 765 + SYS_DBM_OPEN = 0x2FE // 766 + SYS_DBM_STORE = 0x2FF // 767 + SYS___NDMTRM = 0x300 // 768 + SYS_FTOK = 0x301 // 769 + SYS_BASENAME = 0x302 // 770 + SYS_DIRNAME = 0x303 // 771 + SYS_GETDTABLESIZE = 0x304 // 772 + SYS_MKSTEMP = 0x305 // 773 + SYS_MKTEMP = 0x306 // 774 + SYS_NFTW = 0x307 // 775 + SYS_GETWD = 0x308 // 776 + SYS_LOCKF = 0x309 // 777 + SYS__LONGJMP = 0x30D // 781 + SYS__SETJMP = 0x30E // 782 + SYS_VFORK = 0x30F // 783 + SYS_WORDEXP = 0x310 // 784 + SYS_WORDFREE = 0x311 // 785 + SYS_GETPGID = 0x312 // 786 + SYS_GETSID = 0x313 // 787 + SYS___UTMPXNAME = 0x314 // 788 + SYS_CUSERID = 0x315 // 789 + SYS_GETPASS = 0x316 // 790 + SYS_FNMATCH = 0x317 // 791 + SYS_FTW = 0x318 // 792 + SYS_GETW = 0x319 // 793 + SYS_GLOB = 0x31A // 794 + SYS_GLOBFREE = 0x31B // 795 + SYS_PUTW = 0x31C // 796 + SYS_SEEKDIR = 0x31D // 797 + SYS_TELLDIR = 0x31E // 798 + SYS_TEMPNAM = 0x31F // 799 + SYS_ACOSH = 0x320 // 800 + SYS_ASINH = 0x321 // 801 + SYS_ATANH = 0x322 // 802 + SYS_CBRT = 0x323 // 803 + SYS_EXPM1 = 0x324 // 804 + SYS_ILOGB = 0x325 // 805 + SYS_LOGB = 0x326 // 806 + SYS_LOG1P = 0x327 // 807 + SYS_NEXTAFTER = 0x328 // 808 + SYS_RINT = 0x329 // 809 + SYS_REMAINDER = 0x32A // 810 + SYS_SCALB = 0x32B // 811 + SYS_LGAMMA = 0x32C // 812 + SYS_TTYSLOT = 0x32D // 813 + SYS_GETTIMEOFDAY_R = 0x32E // 814 + SYS_SYNC = 0x32F // 815 + SYS_SPAWN = 0x330 // 816 + SYS_SPAWNP = 0x331 // 817 + SYS_GETLOGIN_UU = 0x332 // 818 + SYS_ECVT = 0x333 // 819 + SYS_FCVT = 0x334 // 820 + SYS_GCVT = 0x335 // 821 + SYS_ACCEPT = 0x336 // 822 + SYS_BIND = 0x337 // 823 + SYS_CONNECT = 0x338 // 824 + SYS_ENDHOSTENT = 0x339 // 825 + SYS_ENDPROTOENT = 0x33A // 826 + SYS_ENDSERVENT = 0x33B // 827 + SYS_GETHOSTBYADDR_R = 0x33C // 828 + SYS_GETHOSTBYADDR = 0x33D // 829 + SYS_GETHOSTBYNAME_R = 0x33E // 830 + SYS_GETHOSTBYNAME = 0x33F // 831 + SYS_GETHOSTENT = 0x340 // 832 + SYS_GETHOSTID = 0x341 // 833 + SYS_GETHOSTNAME = 0x342 // 834 + SYS_GETNETBYADDR = 0x343 // 835 + SYS_GETNETBYNAME = 0x344 // 836 + SYS_GETNETENT = 0x345 // 837 + SYS_GETPEERNAME = 0x346 // 838 + SYS_GETPROTOBYNAME = 0x347 // 839 + SYS_GETPROTOBYNUMBER = 0x348 // 840 + SYS_GETPROTOENT = 0x349 // 841 + SYS_GETSERVBYNAME = 0x34A // 842 + SYS_GETSERVBYPORT = 0x34B // 843 + SYS_GETSERVENT = 0x34C // 844 + SYS_GETSOCKNAME = 0x34D // 845 + SYS_GETSOCKOPT = 0x34E // 846 + SYS_INET_ADDR = 0x34F // 847 + SYS_INET_LNAOF = 0x350 // 848 + SYS_INET_MAKEADDR = 0x351 // 849 + SYS_INET_NETOF = 0x352 // 850 + SYS_INET_NETWORK = 0x353 // 851 + SYS_INET_NTOA = 0x354 // 852 + SYS_IOCTL = 0x355 // 853 + SYS_LISTEN = 0x356 // 854 + SYS_READV = 0x357 // 855 + SYS_RECV = 0x358 // 856 + SYS_RECVFROM = 0x359 // 857 + SYS_SELECT = 0x35B // 859 + SYS_SELECTEX = 0x35C // 860 + SYS_SEND = 0x35D // 861 + SYS_SENDTO = 0x35F // 863 + SYS_SETHOSTENT = 0x360 // 864 + SYS_SETNETENT = 0x361 // 865 + SYS_SETPEER = 0x362 // 866 + SYS_SETPROTOENT = 0x363 // 867 + SYS_SETSERVENT = 0x364 // 868 + SYS_SETSOCKOPT = 0x365 // 869 + SYS_SHUTDOWN = 0x366 // 870 + SYS_SOCKET = 0x367 // 871 + SYS_SOCKETPAIR = 0x368 // 872 + SYS_WRITEV = 0x369 // 873 + SYS_CHROOT = 0x36A // 874 + SYS_W_STATVFS = 0x36B // 875 + SYS_ULIMIT = 0x36C // 876 + SYS_ISNAN = 0x36D // 877 + SYS_UTIMES = 0x36E // 878 + SYS___H_ERRNO = 0x36F // 879 + SYS_ENDNETENT = 0x370 // 880 + SYS_CLOSELOG = 0x371 // 881 + SYS_OPENLOG = 0x372 // 882 + SYS_SETLOGMASK = 0x373 // 883 + SYS_SYSLOG = 0x374 // 884 + SYS_PTSNAME = 0x375 // 885 + SYS_SETREUID = 0x376 // 886 + SYS_SETREGID = 0x377 // 887 + SYS_REALPATH = 0x378 // 888 + SYS___SIGNGAM = 0x379 // 889 + SYS_GRANTPT = 0x37A // 890 + SYS_UNLOCKPT = 0x37B // 891 + SYS_TCGETSID = 0x37C // 892 + SYS___TCGETCP = 0x37D // 893 + SYS___TCSETCP = 0x37E // 894 + SYS___TCSETTABLES = 0x37F // 895 + SYS_POLL = 0x380 // 896 + SYS_REXEC = 0x381 // 897 + SYS___ISASCII2 = 0x382 // 898 + SYS___TOASCII2 = 0x383 // 899 + SYS_CHPRIORITY = 0x384 // 900 + SYS_PTHREAD_ATTR_SETSYNCTYPE_NP = 0x385 // 901 + SYS_PTHREAD_ATTR_GETSYNCTYPE_NP = 0x386 // 902 + SYS_PTHREAD_SET_LIMIT_NP = 0x387 // 903 + SYS___STNETENT = 0x388 // 904 + SYS___STPROTOENT = 0x389 // 905 + SYS___STSERVENT = 0x38A // 906 + SYS___STHOSTENT = 0x38B // 907 + SYS_NLIST = 0x38C // 908 + SYS___IPDBCS = 0x38D // 909 + SYS___IPDSPX = 0x38E // 910 + SYS___IPMSGC = 0x38F // 911 + SYS___SELECT1 = 0x390 // 912 + SYS_PTHREAD_SECURITY_NP = 0x391 // 913 + SYS___CHECK_RESOURCE_AUTH_NP = 0x392 // 914 + SYS___CONVERT_ID_NP = 0x393 // 915 + SYS___OPENVMREL = 0x394 // 916 + SYS_WMEMCHR = 0x395 // 917 + SYS_WMEMCMP = 0x396 // 918 + SYS_WMEMCPY = 0x397 // 919 + SYS_WMEMMOVE = 0x398 // 920 + SYS_WMEMSET = 0x399 // 921 + SYS___FPUTWC = 0x400 // 1024 + SYS___PUTWC = 0x401 // 1025 + SYS___PWCHAR = 0x402 // 1026 + SYS___WCSFTM = 0x403 // 1027 + SYS___WCSTOK = 0x404 // 1028 + SYS___WCWDTH = 0x405 // 1029 + SYS_T_ACCEPT = 0x409 // 1033 + SYS_T_ALLOC = 0x40A // 1034 + SYS_T_BIND = 0x40B // 1035 + SYS_T_CLOSE = 0x40C // 1036 + SYS_T_CONNECT = 0x40D // 1037 + SYS_T_ERROR = 0x40E // 1038 + SYS_T_FREE = 0x40F // 1039 + SYS_T_GETINFO = 0x410 // 1040 + SYS_T_GETPROTADDR = 0x411 // 1041 + SYS_T_GETSTATE = 0x412 // 1042 + SYS_T_LISTEN = 0x413 // 1043 + SYS_T_LOOK = 0x414 // 1044 + SYS_T_OPEN = 0x415 // 1045 + SYS_T_OPTMGMT = 0x416 // 1046 + SYS_T_RCV = 0x417 // 1047 + SYS_T_RCVCONNECT = 0x418 // 1048 + SYS_T_RCVDIS = 0x419 // 1049 + SYS_T_RCVREL = 0x41A // 1050 + SYS_T_RCVUDATA = 0x41B // 1051 + SYS_T_RCVUDERR = 0x41C // 1052 + SYS_T_SND = 0x41D // 1053 + SYS_T_SNDDIS = 0x41E // 1054 + SYS_T_SNDREL = 0x41F // 1055 + SYS_T_SNDUDATA = 0x420 // 1056 + SYS_T_STRERROR = 0x421 // 1057 + SYS_T_SYNC = 0x422 // 1058 + SYS_T_UNBIND = 0x423 // 1059 + SYS___T_ERRNO = 0x424 // 1060 + SYS___RECVMSG2 = 0x425 // 1061 + SYS___SENDMSG2 = 0x426 // 1062 + SYS_FATTACH = 0x427 // 1063 + SYS_FDETACH = 0x428 // 1064 + SYS_GETMSG = 0x429 // 1065 + SYS_GETPMSG = 0x42A // 1066 + SYS_ISASTREAM = 0x42B // 1067 + SYS_PUTMSG = 0x42C // 1068 + SYS_PUTPMSG = 0x42D // 1069 + SYS___ISPOSIXON = 0x42E // 1070 + SYS___OPENMVSREL = 0x42F // 1071 + SYS_GETCONTEXT = 0x430 // 1072 + SYS_SETCONTEXT = 0x431 // 1073 + SYS_MAKECONTEXT = 0x432 // 1074 + SYS_SWAPCONTEXT = 0x433 // 1075 + SYS_PTHREAD_GETSPECIFIC_D8_NP = 0x434 // 1076 + SYS_GETCLIENTID = 0x470 // 1136 + SYS___GETCLIENTID = 0x471 // 1137 + SYS_GETSTABLESIZE = 0x472 // 1138 + SYS_GETIBMOPT = 0x473 // 1139 + SYS_GETIBMSOCKOPT = 0x474 // 1140 + SYS_GIVESOCKET = 0x475 // 1141 + SYS_IBMSFLUSH = 0x476 // 1142 + SYS_MAXDESC = 0x477 // 1143 + SYS_SETIBMOPT = 0x478 // 1144 + SYS_SETIBMSOCKOPT = 0x479 // 1145 + SYS_SOCK_DEBUG = 0x47A // 1146 + SYS_SOCK_DO_TESTSTOR = 0x47D // 1149 + SYS_TAKESOCKET = 0x47E // 1150 + SYS___SERVER_INIT = 0x47F // 1151 + SYS___SERVER_PWU = 0x480 // 1152 + SYS_PTHREAD_TAG_NP = 0x481 // 1153 + SYS___CONSOLE = 0x482 // 1154 + SYS___WSINIT = 0x483 // 1155 + SYS___IPTCPN = 0x489 // 1161 + SYS___SMF_RECORD = 0x48A // 1162 + SYS___IPHOST = 0x48B // 1163 + SYS___IPNODE = 0x48C // 1164 + SYS___SERVER_CLASSIFY_CREATE = 0x48D // 1165 + SYS___SERVER_CLASSIFY_DESTROY = 0x48E // 1166 + SYS___SERVER_CLASSIFY_RESET = 0x48F // 1167 + SYS___SERVER_CLASSIFY = 0x490 // 1168 + SYS___HEAPRPT = 0x496 // 1174 + SYS___FNWSA = 0x49B // 1179 + SYS___SPAWN2 = 0x49D // 1181 + SYS___SPAWNP2 = 0x49E // 1182 + SYS___GDRR = 0x4A1 // 1185 + SYS___HRRNO = 0x4A2 // 1186 + SYS___OPRG = 0x4A3 // 1187 + SYS___OPRR = 0x4A4 // 1188 + SYS___OPND = 0x4A5 // 1189 + SYS___OPPT = 0x4A6 // 1190 + SYS___SIGGM = 0x4A7 // 1191 + SYS___DGHT = 0x4A8 // 1192 + SYS___TZNE = 0x4A9 // 1193 + SYS___TZZN = 0x4AA // 1194 + SYS___TRRNO = 0x4AF // 1199 + SYS___ENVN = 0x4B0 // 1200 + SYS___MLOCKALL = 0x4B1 // 1201 + SYS_CREATEWO = 0x4B2 // 1202 + SYS_CREATEWORKUNIT = 0x4B2 // 1202 + SYS_CONTINUE = 0x4B3 // 1203 + SYS_CONTINUEWORKUNIT = 0x4B3 // 1203 + SYS_CONNECTW = 0x4B4 // 1204 + SYS_CONNECTWORKMGR = 0x4B4 // 1204 + SYS_CONNECTS = 0x4B5 // 1205 + SYS_CONNECTSERVER = 0x4B5 // 1205 + SYS_DISCONNE = 0x4B6 // 1206 + SYS_DISCONNECTSERVER = 0x4B6 // 1206 + SYS_JOINWORK = 0x4B7 // 1207 + SYS_JOINWORKUNIT = 0x4B7 // 1207 + SYS_LEAVEWOR = 0x4B8 // 1208 + SYS_LEAVEWORKUNIT = 0x4B8 // 1208 + SYS_DELETEWO = 0x4B9 // 1209 + SYS_DELETEWORKUNIT = 0x4B9 // 1209 + SYS_QUERYMET = 0x4BA // 1210 + SYS_QUERYMETRICS = 0x4BA // 1210 + SYS_QUERYSCH = 0x4BB // 1211 + SYS_QUERYSCHENV = 0x4BB // 1211 + SYS_CHECKSCH = 0x4BC // 1212 + SYS_CHECKSCHENV = 0x4BC // 1212 + SYS___PID_AFFINITY = 0x4BD // 1213 + SYS___ASINH_B = 0x4BE // 1214 + SYS___ATAN_B = 0x4BF // 1215 + SYS___CBRT_B = 0x4C0 // 1216 + SYS___CEIL_B = 0x4C1 // 1217 + SYS_COPYSIGN = 0x4C2 // 1218 + SYS___COS_B = 0x4C3 // 1219 + SYS___ERF_B = 0x4C4 // 1220 + SYS___ERFC_B = 0x4C5 // 1221 + SYS___EXPM1_B = 0x4C6 // 1222 + SYS___FABS_B = 0x4C7 // 1223 + SYS_FINITE = 0x4C8 // 1224 + SYS___FLOOR_B = 0x4C9 // 1225 + SYS___FREXP_B = 0x4CA // 1226 + SYS___ILOGB_B = 0x4CB // 1227 + SYS___ISNAN_B = 0x4CC // 1228 + SYS___LDEXP_B = 0x4CD // 1229 + SYS___LOG1P_B = 0x4CE // 1230 + SYS___LOGB_B = 0x4CF // 1231 + SYS_MATHERR = 0x4D0 // 1232 + SYS___MODF_B = 0x4D1 // 1233 + SYS___NEXTAFTER_B = 0x4D2 // 1234 + SYS___RINT_B = 0x4D3 // 1235 + SYS_SCALBN = 0x4D4 // 1236 + SYS_SIGNIFIC = 0x4D5 // 1237 + SYS_SIGNIFICAND = 0x4D5 // 1237 + SYS___SIN_B = 0x4D6 // 1238 + SYS___TAN_B = 0x4D7 // 1239 + SYS___TANH_B = 0x4D8 // 1240 + SYS___ACOS_B = 0x4D9 // 1241 + SYS___ACOSH_B = 0x4DA // 1242 + SYS___ASIN_B = 0x4DB // 1243 + SYS___ATAN2_B = 0x4DC // 1244 + SYS___ATANH_B = 0x4DD // 1245 + SYS___COSH_B = 0x4DE // 1246 + SYS___EXP_B = 0x4DF // 1247 + SYS___FMOD_B = 0x4E0 // 1248 + SYS___GAMMA_B = 0x4E1 // 1249 + SYS_GAMMA_R = 0x4E2 // 1250 + SYS___HYPOT_B = 0x4E3 // 1251 + SYS___J0_B = 0x4E4 // 1252 + SYS___Y0_B = 0x4E5 // 1253 + SYS___J1_B = 0x4E6 // 1254 + SYS___Y1_B = 0x4E7 // 1255 + SYS___JN_B = 0x4E8 // 1256 + SYS___YN_B = 0x4E9 // 1257 + SYS___LGAMMA_B = 0x4EA // 1258 + SYS_LGAMMA_R = 0x4EB // 1259 + SYS___LOG_B = 0x4EC // 1260 + SYS___LOG10_B = 0x4ED // 1261 + SYS___POW_B = 0x4EE // 1262 + SYS___REMAINDER_B = 0x4EF // 1263 + SYS___SCALB_B = 0x4F0 // 1264 + SYS___SINH_B = 0x4F1 // 1265 + SYS___SQRT_B = 0x4F2 // 1266 + SYS___OPENDIR2 = 0x4F3 // 1267 + SYS___READDIR2 = 0x4F4 // 1268 + SYS___LOGIN = 0x4F5 // 1269 + SYS___OPEN_STAT = 0x4F6 // 1270 + SYS_ACCEPT_AND_RECV = 0x4F7 // 1271 + SYS___FP_SETMODE = 0x4F8 // 1272 + SYS___SIGACTIONSET = 0x4FB // 1275 + SYS___UCREATE = 0x4FC // 1276 + SYS___UMALLOC = 0x4FD // 1277 + SYS___UFREE = 0x4FE // 1278 + SYS___UHEAPREPORT = 0x4FF // 1279 + SYS___ISBFP = 0x500 // 1280 + SYS___FP_CAST = 0x501 // 1281 + SYS___CERTIFICATE = 0x502 // 1282 + SYS_SEND_FILE = 0x503 // 1283 + SYS_AIO_CANCEL = 0x504 // 1284 + SYS_AIO_ERROR = 0x505 // 1285 + SYS_AIO_READ = 0x506 // 1286 + SYS_AIO_RETURN = 0x507 // 1287 + SYS_AIO_SUSPEND = 0x508 // 1288 + SYS_AIO_WRITE = 0x509 // 1289 + SYS_PTHREAD_MUTEXATTR_GETPSHARED = 0x50A // 1290 + SYS_PTHREAD_MUTEXATTR_SETPSHARED = 0x50B // 1291 + SYS_PTHREAD_RWLOCK_DESTROY = 0x50C // 1292 + SYS_PTHREAD_RWLOCK_INIT = 0x50D // 1293 + SYS_PTHREAD_RWLOCK_RDLOCK = 0x50E // 1294 + SYS_PTHREAD_RWLOCK_TRYRDLOCK = 0x50F // 1295 + SYS_PTHREAD_RWLOCK_TRYWRLOCK = 0x510 // 1296 + SYS_PTHREAD_RWLOCK_UNLOCK = 0x511 // 1297 + SYS_PTHREAD_RWLOCK_WRLOCK = 0x512 // 1298 + SYS_PTHREAD_RWLOCKATTR_GETPSHARED = 0x513 // 1299 + SYS_PTHREAD_RWLOCKATTR_SETPSHARED = 0x514 // 1300 + SYS_PTHREAD_RWLOCKATTR_INIT = 0x515 // 1301 + SYS_PTHREAD_RWLOCKATTR_DESTROY = 0x516 // 1302 + SYS___CTTBL = 0x517 // 1303 + SYS_PTHREAD_MUTEXATTR_SETTYPE = 0x518 // 1304 + SYS_PTHREAD_MUTEXATTR_GETTYPE = 0x519 // 1305 + SYS___FP_CLR_FLAG = 0x51A // 1306 + SYS___FP_READ_FLAG = 0x51B // 1307 + SYS___FP_RAISE_XCP = 0x51C // 1308 + SYS___FP_CLASS = 0x51D // 1309 + SYS___FP_FINITE = 0x51E // 1310 + SYS___FP_ISNAN = 0x51F // 1311 + SYS___FP_UNORDERED = 0x520 // 1312 + SYS___FP_READ_RND = 0x521 // 1313 + SYS___FP_READ_RND_B = 0x522 // 1314 + SYS___FP_SWAP_RND = 0x523 // 1315 + SYS___FP_SWAP_RND_B = 0x524 // 1316 + SYS___FP_LEVEL = 0x525 // 1317 + SYS___FP_BTOH = 0x526 // 1318 + SYS___FP_HTOB = 0x527 // 1319 + SYS___FPC_RD = 0x528 // 1320 + SYS___FPC_WR = 0x529 // 1321 + SYS___FPC_RW = 0x52A // 1322 + SYS___FPC_SM = 0x52B // 1323 + SYS___FPC_RS = 0x52C // 1324 + SYS_SIGTIMEDWAIT = 0x52D // 1325 + SYS_SIGWAITINFO = 0x52E // 1326 + SYS___CHKBFP = 0x52F // 1327 + SYS___W_PIOCTL = 0x59E // 1438 + SYS___OSENV = 0x59F // 1439 + SYS_EXPORTWO = 0x5A1 // 1441 + SYS_EXPORTWORKUNIT = 0x5A1 // 1441 + SYS_UNDOEXPO = 0x5A2 // 1442 + SYS_UNDOEXPORTWORKUNIT = 0x5A2 // 1442 + SYS_IMPORTWO = 0x5A3 // 1443 + SYS_IMPORTWORKUNIT = 0x5A3 // 1443 + SYS_UNDOIMPO = 0x5A4 // 1444 + SYS_UNDOIMPORTWORKUNIT = 0x5A4 // 1444 + SYS_EXTRACTW = 0x5A5 // 1445 + SYS_EXTRACTWORKUNIT = 0x5A5 // 1445 + SYS___CPL = 0x5A6 // 1446 + SYS___MAP_INIT = 0x5A7 // 1447 + SYS___MAP_SERVICE = 0x5A8 // 1448 + SYS_SIGQUEUE = 0x5A9 // 1449 + SYS___MOUNT = 0x5AA // 1450 + SYS___GETUSERID = 0x5AB // 1451 + SYS___IPDOMAINNAME = 0x5AC // 1452 + SYS_QUERYENC = 0x5AD // 1453 + SYS_QUERYWORKUNITCLASSIFICATION = 0x5AD // 1453 + SYS_CONNECTE = 0x5AE // 1454 + SYS_CONNECTEXPORTIMPORT = 0x5AE // 1454 + SYS___FP_SWAPMODE = 0x5AF // 1455 + SYS_STRTOLL = 0x5B0 // 1456 + SYS_STRTOULL = 0x5B1 // 1457 + SYS___DSA_PREV = 0x5B2 // 1458 + SYS___EP_FIND = 0x5B3 // 1459 + SYS___SERVER_THREADS_QUERY = 0x5B4 // 1460 + SYS___MSGRCV_TIMED = 0x5B7 // 1463 + SYS___SEMOP_TIMED = 0x5B8 // 1464 + SYS___GET_CPUID = 0x5B9 // 1465 + SYS___GET_SYSTEM_SETTINGS = 0x5BA // 1466 + SYS_FTELLO = 0x5C8 // 1480 + SYS_FSEEKO = 0x5C9 // 1481 + SYS_LLDIV = 0x5CB // 1483 + SYS_WCSTOLL = 0x5CC // 1484 + SYS_WCSTOULL = 0x5CD // 1485 + SYS_LLABS = 0x5CE // 1486 + SYS___CONSOLE2 = 0x5D2 // 1490 + SYS_INET_NTOP = 0x5D3 // 1491 + SYS_INET_PTON = 0x5D4 // 1492 + SYS___RES = 0x5D6 // 1494 + SYS_RES_MKQUERY = 0x5D7 // 1495 + SYS_RES_INIT = 0x5D8 // 1496 + SYS_RES_QUERY = 0x5D9 // 1497 + SYS_RES_SEARCH = 0x5DA // 1498 + SYS_RES_SEND = 0x5DB // 1499 + SYS_RES_QUERYDOMAIN = 0x5DC // 1500 + SYS_DN_EXPAND = 0x5DD // 1501 + SYS_DN_SKIPNAME = 0x5DE // 1502 + SYS_DN_COMP = 0x5DF // 1503 + SYS_ASCTIME_R = 0x5E0 // 1504 + SYS_CTIME_R = 0x5E1 // 1505 + SYS_GMTIME_R = 0x5E2 // 1506 + SYS_LOCALTIME_R = 0x5E3 // 1507 + SYS_RAND_R = 0x5E4 // 1508 + SYS_STRTOK_R = 0x5E5 // 1509 + SYS_READDIR_R = 0x5E6 // 1510 + SYS_GETGRGID_R = 0x5E7 // 1511 + SYS_GETGRNAM_R = 0x5E8 // 1512 + SYS_GETLOGIN_R = 0x5E9 // 1513 + SYS_GETPWNAM_R = 0x5EA // 1514 + SYS_GETPWUID_R = 0x5EB // 1515 + SYS_TTYNAME_R = 0x5EC // 1516 + SYS_PTHREAD_ATFORK = 0x5ED // 1517 + SYS_PTHREAD_ATTR_GETGUARDSIZE = 0x5EE // 1518 + SYS_PTHREAD_ATTR_GETSTACKADDR = 0x5EF // 1519 + SYS_PTHREAD_ATTR_SETGUARDSIZE = 0x5F0 // 1520 + SYS_PTHREAD_ATTR_SETSTACKADDR = 0x5F1 // 1521 + SYS_PTHREAD_CONDATTR_GETPSHARED = 0x5F2 // 1522 + SYS_PTHREAD_CONDATTR_SETPSHARED = 0x5F3 // 1523 + SYS_PTHREAD_GETCONCURRENCY = 0x5F4 // 1524 + SYS_PTHREAD_KEY_DELETE = 0x5F5 // 1525 + SYS_PTHREAD_SETCONCURRENCY = 0x5F6 // 1526 + SYS_PTHREAD_SIGMASK = 0x5F7 // 1527 + SYS___DISCARDDATA = 0x5F8 // 1528 + SYS_PTHREAD_ATTR_GETSCHEDPARAM = 0x5F9 // 1529 + SYS_PTHREAD_ATTR_SETSCHEDPARAM = 0x5FA // 1530 + SYS_PTHREAD_ATTR_GETDETACHSTATE_U98 = 0x5FB // 1531 + SYS_PTHREAD_ATTR_SETDETACHSTATE_U98 = 0x5FC // 1532 + SYS_PTHREAD_DETACH_U98 = 0x5FD // 1533 + SYS_PTHREAD_GETSPECIFIC_U98 = 0x5FE // 1534 + SYS_PTHREAD_SETCANCELSTATE = 0x5FF // 1535 + SYS_PTHREAD_SETCANCELTYPE = 0x600 // 1536 + SYS_PTHREAD_TESTCANCEL = 0x601 // 1537 + SYS___ATANF_B = 0x602 // 1538 + SYS___ATANL_B = 0x603 // 1539 + SYS___CEILF_B = 0x604 // 1540 + SYS___CEILL_B = 0x605 // 1541 + SYS___COSF_B = 0x606 // 1542 + SYS___COSL_B = 0x607 // 1543 + SYS___FABSF_B = 0x608 // 1544 + SYS___FABSL_B = 0x609 // 1545 + SYS___FLOORF_B = 0x60A // 1546 + SYS___FLOORL_B = 0x60B // 1547 + SYS___FREXPF_B = 0x60C // 1548 + SYS___FREXPL_B = 0x60D // 1549 + SYS___LDEXPF_B = 0x60E // 1550 + SYS___LDEXPL_B = 0x60F // 1551 + SYS___SINF_B = 0x610 // 1552 + SYS___SINL_B = 0x611 // 1553 + SYS___TANF_B = 0x612 // 1554 + SYS___TANL_B = 0x613 // 1555 + SYS___TANHF_B = 0x614 // 1556 + SYS___TANHL_B = 0x615 // 1557 + SYS___ACOSF_B = 0x616 // 1558 + SYS___ACOSL_B = 0x617 // 1559 + SYS___ASINF_B = 0x618 // 1560 + SYS___ASINL_B = 0x619 // 1561 + SYS___ATAN2F_B = 0x61A // 1562 + SYS___ATAN2L_B = 0x61B // 1563 + SYS___COSHF_B = 0x61C // 1564 + SYS___COSHL_B = 0x61D // 1565 + SYS___EXPF_B = 0x61E // 1566 + SYS___EXPL_B = 0x61F // 1567 + SYS___LOGF_B = 0x620 // 1568 + SYS___LOGL_B = 0x621 // 1569 + SYS___LOG10F_B = 0x622 // 1570 + SYS___LOG10L_B = 0x623 // 1571 + SYS___POWF_B = 0x624 // 1572 + SYS___POWL_B = 0x625 // 1573 + SYS___SINHF_B = 0x626 // 1574 + SYS___SINHL_B = 0x627 // 1575 + SYS___SQRTF_B = 0x628 // 1576 + SYS___SQRTL_B = 0x629 // 1577 + SYS___ABSF_B = 0x62A // 1578 + SYS___ABS_B = 0x62B // 1579 + SYS___ABSL_B = 0x62C // 1580 + SYS___FMODF_B = 0x62D // 1581 + SYS___FMODL_B = 0x62E // 1582 + SYS___MODFF_B = 0x62F // 1583 + SYS___MODFL_B = 0x630 // 1584 + SYS_ABSF = 0x631 // 1585 + SYS_ABSL = 0x632 // 1586 + SYS_ACOSF = 0x633 // 1587 + SYS_ACOSL = 0x634 // 1588 + SYS_ASINF = 0x635 // 1589 + SYS_ASINL = 0x636 // 1590 + SYS_ATAN2F = 0x637 // 1591 + SYS_ATAN2L = 0x638 // 1592 + SYS_ATANF = 0x639 // 1593 + SYS_ATANL = 0x63A // 1594 + SYS_CEILF = 0x63B // 1595 + SYS_CEILL = 0x63C // 1596 + SYS_COSF = 0x63D // 1597 + SYS_COSL = 0x63E // 1598 + SYS_COSHF = 0x63F // 1599 + SYS_COSHL = 0x640 // 1600 + SYS_EXPF = 0x641 // 1601 + SYS_EXPL = 0x642 // 1602 + SYS_TANHF = 0x643 // 1603 + SYS_TANHL = 0x644 // 1604 + SYS_LOG10F = 0x645 // 1605 + SYS_LOG10L = 0x646 // 1606 + SYS_LOGF = 0x647 // 1607 + SYS_LOGL = 0x648 // 1608 + SYS_POWF = 0x649 // 1609 + SYS_POWL = 0x64A // 1610 + SYS_SINF = 0x64B // 1611 + SYS_SINL = 0x64C // 1612 + SYS_SQRTF = 0x64D // 1613 + SYS_SQRTL = 0x64E // 1614 + SYS_SINHF = 0x64F // 1615 + SYS_SINHL = 0x650 // 1616 + SYS_TANF = 0x651 // 1617 + SYS_TANL = 0x652 // 1618 + SYS_FABSF = 0x653 // 1619 + SYS_FABSL = 0x654 // 1620 + SYS_FLOORF = 0x655 // 1621 + SYS_FLOORL = 0x656 // 1622 + SYS_FMODF = 0x657 // 1623 + SYS_FMODL = 0x658 // 1624 + SYS_FREXPF = 0x659 // 1625 + SYS_FREXPL = 0x65A // 1626 + SYS_LDEXPF = 0x65B // 1627 + SYS_LDEXPL = 0x65C // 1628 + SYS_MODFF = 0x65D // 1629 + SYS_MODFL = 0x65E // 1630 + SYS_BTOWC = 0x65F // 1631 + SYS___CHATTR = 0x660 // 1632 + SYS___FCHATTR = 0x661 // 1633 + SYS___TOCCSID = 0x662 // 1634 + SYS___CSNAMETYPE = 0x663 // 1635 + SYS___TOCSNAME = 0x664 // 1636 + SYS___CCSIDTYPE = 0x665 // 1637 + SYS___AE_CORRESTBL_QUERY = 0x666 // 1638 + SYS___AE_AUTOCONVERT_STATE = 0x667 // 1639 + SYS_DN_FIND = 0x668 // 1640 + SYS___GETHOSTBYADDR_A = 0x669 // 1641 + SYS___GETHOSTBYNAME_A = 0x66A // 1642 + SYS___RES_INIT_A = 0x66B // 1643 + SYS___GETHOSTBYADDR_R_A = 0x66C // 1644 + SYS___GETHOSTBYNAME_R_A = 0x66D // 1645 + SYS___CHARMAP_INIT_A = 0x66E // 1646 + SYS___MBLEN_A = 0x66F // 1647 + SYS___MBLEN_SB_A = 0x670 // 1648 + SYS___MBLEN_STD_A = 0x671 // 1649 + SYS___MBLEN_UTF = 0x672 // 1650 + SYS___MBSTOWCS_A = 0x673 // 1651 + SYS___MBSTOWCS_STD_A = 0x674 // 1652 + SYS___MBTOWC_A = 0x675 // 1653 + SYS___MBTOWC_ISO1 = 0x676 // 1654 + SYS___MBTOWC_SBCS = 0x677 // 1655 + SYS___MBTOWC_MBCS = 0x678 // 1656 + SYS___MBTOWC_UTF = 0x679 // 1657 + SYS___WCSTOMBS_A = 0x67A // 1658 + SYS___WCSTOMBS_STD_A = 0x67B // 1659 + SYS___WCSWIDTH_A = 0x67C // 1660 + SYS___GETGRGID_R_A = 0x67D // 1661 + SYS___WCSWIDTH_STD_A = 0x67E // 1662 + SYS___WCSWIDTH_ASIA = 0x67F // 1663 + SYS___CSID_A = 0x680 // 1664 + SYS___CSID_STD_A = 0x681 // 1665 + SYS___WCSID_A = 0x682 // 1666 + SYS___WCSID_STD_A = 0x683 // 1667 + SYS___WCTOMB_A = 0x684 // 1668 + SYS___WCTOMB_ISO1 = 0x685 // 1669 + SYS___WCTOMB_STD_A = 0x686 // 1670 + SYS___WCTOMB_UTF = 0x687 // 1671 + SYS___WCWIDTH_A = 0x688 // 1672 + SYS___GETGRNAM_R_A = 0x689 // 1673 + SYS___WCWIDTH_STD_A = 0x68A // 1674 + SYS___WCWIDTH_ASIA = 0x68B // 1675 + SYS___GETPWNAM_R_A = 0x68C // 1676 + SYS___GETPWUID_R_A = 0x68D // 1677 + SYS___GETLOGIN_R_A = 0x68E // 1678 + SYS___TTYNAME_R_A = 0x68F // 1679 + SYS___READDIR_R_A = 0x690 // 1680 + SYS___E2A_S = 0x691 // 1681 + SYS___FNMATCH_A = 0x692 // 1682 + SYS___FNMATCH_C_A = 0x693 // 1683 + SYS___EXECL_A = 0x694 // 1684 + SYS___FNMATCH_STD_A = 0x695 // 1685 + SYS___REGCOMP_A = 0x696 // 1686 + SYS___REGCOMP_STD_A = 0x697 // 1687 + SYS___REGERROR_A = 0x698 // 1688 + SYS___REGERROR_STD_A = 0x699 // 1689 + SYS___REGEXEC_A = 0x69A // 1690 + SYS___REGEXEC_STD_A = 0x69B // 1691 + SYS___REGFREE_A = 0x69C // 1692 + SYS___REGFREE_STD_A = 0x69D // 1693 + SYS___STRCOLL_A = 0x69E // 1694 + SYS___STRCOLL_C_A = 0x69F // 1695 + SYS___EXECLE_A = 0x6A0 // 1696 + SYS___STRCOLL_STD_A = 0x6A1 // 1697 + SYS___STRXFRM_A = 0x6A2 // 1698 + SYS___STRXFRM_C_A = 0x6A3 // 1699 + SYS___EXECLP_A = 0x6A4 // 1700 + SYS___STRXFRM_STD_A = 0x6A5 // 1701 + SYS___WCSCOLL_A = 0x6A6 // 1702 + SYS___WCSCOLL_C_A = 0x6A7 // 1703 + SYS___WCSCOLL_STD_A = 0x6A8 // 1704 + SYS___WCSXFRM_A = 0x6A9 // 1705 + SYS___WCSXFRM_C_A = 0x6AA // 1706 + SYS___WCSXFRM_STD_A = 0x6AB // 1707 + SYS___COLLATE_INIT_A = 0x6AC // 1708 + SYS___WCTYPE_A = 0x6AD // 1709 + SYS___GET_WCTYPE_STD_A = 0x6AE // 1710 + SYS___CTYPE_INIT_A = 0x6AF // 1711 + SYS___ISWCTYPE_A = 0x6B0 // 1712 + SYS___EXECV_A = 0x6B1 // 1713 + SYS___IS_WCTYPE_STD_A = 0x6B2 // 1714 + SYS___TOWLOWER_A = 0x6B3 // 1715 + SYS___TOWLOWER_STD_A = 0x6B4 // 1716 + SYS___TOWUPPER_A = 0x6B5 // 1717 + SYS___TOWUPPER_STD_A = 0x6B6 // 1718 + SYS___LOCALE_INIT_A = 0x6B7 // 1719 + SYS___LOCALECONV_A = 0x6B8 // 1720 + SYS___LOCALECONV_STD_A = 0x6B9 // 1721 + SYS___NL_LANGINFO_A = 0x6BA // 1722 + SYS___NL_LNAGINFO_STD_A = 0x6BB // 1723 + SYS___MONETARY_INIT_A = 0x6BC // 1724 + SYS___STRFMON_A = 0x6BD // 1725 + SYS___STRFMON_STD_A = 0x6BE // 1726 + SYS___GETADDRINFO_A = 0x6BF // 1727 + SYS___CATGETS_A = 0x6C0 // 1728 + SYS___EXECVE_A = 0x6C1 // 1729 + SYS___EXECVP_A = 0x6C2 // 1730 + SYS___SPAWN_A = 0x6C3 // 1731 + SYS___GETNAMEINFO_A = 0x6C4 // 1732 + SYS___SPAWNP_A = 0x6C5 // 1733 + SYS___NUMERIC_INIT_A = 0x6C6 // 1734 + SYS___RESP_INIT_A = 0x6C7 // 1735 + SYS___RPMATCH_A = 0x6C8 // 1736 + SYS___RPMATCH_C_A = 0x6C9 // 1737 + SYS___RPMATCH_STD_A = 0x6CA // 1738 + SYS___TIME_INIT_A = 0x6CB // 1739 + SYS___STRFTIME_A = 0x6CC // 1740 + SYS___STRFTIME_STD_A = 0x6CD // 1741 + SYS___STRPTIME_A = 0x6CE // 1742 + SYS___STRPTIME_STD_A = 0x6CF // 1743 + SYS___WCSFTIME_A = 0x6D0 // 1744 + SYS___WCSFTIME_STD_A = 0x6D1 // 1745 + SYS_____SPAWN2_A = 0x6D2 // 1746 + SYS_____SPAWNP2_A = 0x6D3 // 1747 + SYS___SYNTAX_INIT_A = 0x6D4 // 1748 + SYS___TOD_INIT_A = 0x6D5 // 1749 + SYS___NL_CSINFO_A = 0x6D6 // 1750 + SYS___NL_MONINFO_A = 0x6D7 // 1751 + SYS___NL_NUMINFO_A = 0x6D8 // 1752 + SYS___NL_RESPINFO_A = 0x6D9 // 1753 + SYS___NL_TIMINFO_A = 0x6DA // 1754 + SYS___IF_NAMETOINDEX_A = 0x6DB // 1755 + SYS___IF_INDEXTONAME_A = 0x6DC // 1756 + SYS___PRINTF_A = 0x6DD // 1757 + SYS___ICONV_OPEN_A = 0x6DE // 1758 + SYS___DLLLOAD_A = 0x6DF // 1759 + SYS___DLLQUERYFN_A = 0x6E0 // 1760 + SYS___DLLQUERYVAR_A = 0x6E1 // 1761 + SYS_____CHATTR_A = 0x6E2 // 1762 + SYS___E2A_L = 0x6E3 // 1763 + SYS_____TOCCSID_A = 0x6E4 // 1764 + SYS_____TOCSNAME_A = 0x6E5 // 1765 + SYS_____CCSIDTYPE_A = 0x6E6 // 1766 + SYS_____CSNAMETYPE_A = 0x6E7 // 1767 + SYS___CHMOD_A = 0x6E8 // 1768 + SYS___MKDIR_A = 0x6E9 // 1769 + SYS___STAT_A = 0x6EA // 1770 + SYS___STAT_O_A = 0x6EB // 1771 + SYS___MKFIFO_A = 0x6EC // 1772 + SYS_____OPEN_STAT_A = 0x6ED // 1773 + SYS___LSTAT_A = 0x6EE // 1774 + SYS___LSTAT_O_A = 0x6EF // 1775 + SYS___MKNOD_A = 0x6F0 // 1776 + SYS___MOUNT_A = 0x6F1 // 1777 + SYS___UMOUNT_A = 0x6F2 // 1778 + SYS___CHAUDIT_A = 0x6F4 // 1780 + SYS___W_GETMNTENT_A = 0x6F5 // 1781 + SYS___CREAT_A = 0x6F6 // 1782 + SYS___OPEN_A = 0x6F7 // 1783 + SYS___SETLOCALE_A = 0x6F9 // 1785 + SYS___FPRINTF_A = 0x6FA // 1786 + SYS___SPRINTF_A = 0x6FB // 1787 + SYS___VFPRINTF_A = 0x6FC // 1788 + SYS___VPRINTF_A = 0x6FD // 1789 + SYS___VSPRINTF_A = 0x6FE // 1790 + SYS___VSWPRINTF_A = 0x6FF // 1791 + SYS___SWPRINTF_A = 0x700 // 1792 + SYS___FSCANF_A = 0x701 // 1793 + SYS___SCANF_A = 0x702 // 1794 + SYS___SSCANF_A = 0x703 // 1795 + SYS___SWSCANF_A = 0x704 // 1796 + SYS___ATOF_A = 0x705 // 1797 + SYS___ATOI_A = 0x706 // 1798 + SYS___ATOL_A = 0x707 // 1799 + SYS___STRTOD_A = 0x708 // 1800 + SYS___STRTOL_A = 0x709 // 1801 + SYS___STRTOUL_A = 0x70A // 1802 + SYS_____AE_CORRESTBL_QUERY_A = 0x70B // 1803 + SYS___A64L_A = 0x70C // 1804 + SYS___ECVT_A = 0x70D // 1805 + SYS___FCVT_A = 0x70E // 1806 + SYS___GCVT_A = 0x70F // 1807 + SYS___L64A_A = 0x710 // 1808 + SYS___STRERROR_A = 0x711 // 1809 + SYS___PERROR_A = 0x712 // 1810 + SYS___FETCH_A = 0x713 // 1811 + SYS___GETENV_A = 0x714 // 1812 + SYS___MKSTEMP_A = 0x717 // 1815 + SYS___PTSNAME_A = 0x718 // 1816 + SYS___PUTENV_A = 0x719 // 1817 + SYS___REALPATH_A = 0x71A // 1818 + SYS___SETENV_A = 0x71B // 1819 + SYS___SYSTEM_A = 0x71C // 1820 + SYS___GETOPT_A = 0x71D // 1821 + SYS___CATOPEN_A = 0x71E // 1822 + SYS___ACCESS_A = 0x71F // 1823 + SYS___CHDIR_A = 0x720 // 1824 + SYS___CHOWN_A = 0x721 // 1825 + SYS___CHROOT_A = 0x722 // 1826 + SYS___GETCWD_A = 0x723 // 1827 + SYS___GETWD_A = 0x724 // 1828 + SYS___LCHOWN_A = 0x725 // 1829 + SYS___LINK_A = 0x726 // 1830 + SYS___PATHCONF_A = 0x727 // 1831 + SYS___IF_NAMEINDEX_A = 0x728 // 1832 + SYS___READLINK_A = 0x729 // 1833 + SYS___RMDIR_A = 0x72A // 1834 + SYS___STATVFS_A = 0x72B // 1835 + SYS___SYMLINK_A = 0x72C // 1836 + SYS___TRUNCATE_A = 0x72D // 1837 + SYS___UNLINK_A = 0x72E // 1838 + SYS___GAI_STRERROR_A = 0x72F // 1839 + SYS___EXTLINK_NP_A = 0x730 // 1840 + SYS___ISALNUM_A = 0x731 // 1841 + SYS___ISALPHA_A = 0x732 // 1842 + SYS___A2E_S = 0x733 // 1843 + SYS___ISCNTRL_A = 0x734 // 1844 + SYS___ISDIGIT_A = 0x735 // 1845 + SYS___ISGRAPH_A = 0x736 // 1846 + SYS___ISLOWER_A = 0x737 // 1847 + SYS___ISPRINT_A = 0x738 // 1848 + SYS___ISPUNCT_A = 0x739 // 1849 + SYS___ISSPACE_A = 0x73A // 1850 + SYS___ISUPPER_A = 0x73B // 1851 + SYS___ISXDIGIT_A = 0x73C // 1852 + SYS___TOLOWER_A = 0x73D // 1853 + SYS___TOUPPER_A = 0x73E // 1854 + SYS___ISWALNUM_A = 0x73F // 1855 + SYS___ISWALPHA_A = 0x740 // 1856 + SYS___A2E_L = 0x741 // 1857 + SYS___ISWCNTRL_A = 0x742 // 1858 + SYS___ISWDIGIT_A = 0x743 // 1859 + SYS___ISWGRAPH_A = 0x744 // 1860 + SYS___ISWLOWER_A = 0x745 // 1861 + SYS___ISWPRINT_A = 0x746 // 1862 + SYS___ISWPUNCT_A = 0x747 // 1863 + SYS___ISWSPACE_A = 0x748 // 1864 + SYS___ISWUPPER_A = 0x749 // 1865 + SYS___ISWXDIGIT_A = 0x74A // 1866 + SYS___CONFSTR_A = 0x74B // 1867 + SYS___FTOK_A = 0x74C // 1868 + SYS___MKTEMP_A = 0x74D // 1869 + SYS___FDOPEN_A = 0x74E // 1870 + SYS___FLDATA_A = 0x74F // 1871 + SYS___REMOVE_A = 0x750 // 1872 + SYS___RENAME_A = 0x751 // 1873 + SYS___TMPNAM_A = 0x752 // 1874 + SYS___FOPEN_A = 0x753 // 1875 + SYS___FREOPEN_A = 0x754 // 1876 + SYS___CUSERID_A = 0x755 // 1877 + SYS___POPEN_A = 0x756 // 1878 + SYS___TEMPNAM_A = 0x757 // 1879 + SYS___FTW_A = 0x758 // 1880 + SYS___GETGRENT_A = 0x759 // 1881 + SYS___GETGRGID_A = 0x75A // 1882 + SYS___GETGRNAM_A = 0x75B // 1883 + SYS___GETGROUPSBYNAME_A = 0x75C // 1884 + SYS___GETHOSTENT_A = 0x75D // 1885 + SYS___GETHOSTNAME_A = 0x75E // 1886 + SYS___GETLOGIN_A = 0x75F // 1887 + SYS___INET_NTOP_A = 0x760 // 1888 + SYS___GETPASS_A = 0x761 // 1889 + SYS___GETPWENT_A = 0x762 // 1890 + SYS___GETPWNAM_A = 0x763 // 1891 + SYS___GETPWUID_A = 0x764 // 1892 + SYS_____CHECK_RESOURCE_AUTH_NP_A = 0x765 // 1893 + SYS___CHECKSCHENV_A = 0x766 // 1894 + SYS___CONNECTSERVER_A = 0x767 // 1895 + SYS___CONNECTWORKMGR_A = 0x768 // 1896 + SYS_____CONSOLE_A = 0x769 // 1897 + SYS___CREATEWORKUNIT_A = 0x76A // 1898 + SYS___CTERMID_A = 0x76B // 1899 + SYS___FMTMSG_A = 0x76C // 1900 + SYS___INITGROUPS_A = 0x76D // 1901 + SYS_____LOGIN_A = 0x76E // 1902 + SYS___MSGRCV_A = 0x76F // 1903 + SYS___MSGSND_A = 0x770 // 1904 + SYS___MSGXRCV_A = 0x771 // 1905 + SYS___NFTW_A = 0x772 // 1906 + SYS_____PASSWD_A = 0x773 // 1907 + SYS___PTHREAD_SECURITY_NP_A = 0x774 // 1908 + SYS___QUERYMETRICS_A = 0x775 // 1909 + SYS___QUERYSCHENV = 0x776 // 1910 + SYS___READV_A = 0x777 // 1911 + SYS_____SERVER_CLASSIFY_A = 0x778 // 1912 + SYS_____SERVER_INIT_A = 0x779 // 1913 + SYS_____SERVER_PWU_A = 0x77A // 1914 + SYS___STRCASECMP_A = 0x77B // 1915 + SYS___STRNCASECMP_A = 0x77C // 1916 + SYS___TTYNAME_A = 0x77D // 1917 + SYS___UNAME_A = 0x77E // 1918 + SYS___UTIMES_A = 0x77F // 1919 + SYS___W_GETPSENT_A = 0x780 // 1920 + SYS___WRITEV_A = 0x781 // 1921 + SYS___W_STATFS_A = 0x782 // 1922 + SYS___W_STATVFS_A = 0x783 // 1923 + SYS___FPUTC_A = 0x784 // 1924 + SYS___PUTCHAR_A = 0x785 // 1925 + SYS___PUTS_A = 0x786 // 1926 + SYS___FGETS_A = 0x787 // 1927 + SYS___GETS_A = 0x788 // 1928 + SYS___FPUTS_A = 0x789 // 1929 + SYS___FREAD_A = 0x78A // 1930 + SYS___FWRITE_A = 0x78B // 1931 + SYS___OPEN_O_A = 0x78C // 1932 + SYS___ISASCII = 0x78D // 1933 + SYS___CREAT_O_A = 0x78E // 1934 + SYS___ENVNA = 0x78F // 1935 + SYS___PUTC_A = 0x790 // 1936 + SYS___AE_THREAD_SETMODE = 0x791 // 1937 + SYS___AE_THREAD_SWAPMODE = 0x792 // 1938 + SYS___GETNETBYADDR_A = 0x793 // 1939 + SYS___GETNETBYNAME_A = 0x794 // 1940 + SYS___GETNETENT_A = 0x795 // 1941 + SYS___GETPROTOBYNAME_A = 0x796 // 1942 + SYS___GETPROTOBYNUMBER_A = 0x797 // 1943 + SYS___GETPROTOENT_A = 0x798 // 1944 + SYS___GETSERVBYNAME_A = 0x799 // 1945 + SYS___GETSERVBYPORT_A = 0x79A // 1946 + SYS___GETSERVENT_A = 0x79B // 1947 + SYS___ASCTIME_A = 0x79C // 1948 + SYS___CTIME_A = 0x79D // 1949 + SYS___GETDATE_A = 0x79E // 1950 + SYS___TZSET_A = 0x79F // 1951 + SYS___UTIME_A = 0x7A0 // 1952 + SYS___ASCTIME_R_A = 0x7A1 // 1953 + SYS___CTIME_R_A = 0x7A2 // 1954 + SYS___STRTOLL_A = 0x7A3 // 1955 + SYS___STRTOULL_A = 0x7A4 // 1956 + SYS___FPUTWC_A = 0x7A5 // 1957 + SYS___PUTWC_A = 0x7A6 // 1958 + SYS___PUTWCHAR_A = 0x7A7 // 1959 + SYS___FPUTWS_A = 0x7A8 // 1960 + SYS___UNGETWC_A = 0x7A9 // 1961 + SYS___FGETWC_A = 0x7AA // 1962 + SYS___GETWC_A = 0x7AB // 1963 + SYS___GETWCHAR_A = 0x7AC // 1964 + SYS___FGETWS_A = 0x7AD // 1965 + SYS___GETTIMEOFDAY_A = 0x7AE // 1966 + SYS___GMTIME_A = 0x7AF // 1967 + SYS___GMTIME_R_A = 0x7B0 // 1968 + SYS___LOCALTIME_A = 0x7B1 // 1969 + SYS___LOCALTIME_R_A = 0x7B2 // 1970 + SYS___MKTIME_A = 0x7B3 // 1971 + SYS___TZZNA = 0x7B4 // 1972 + SYS_UNATEXIT = 0x7B5 // 1973 + SYS___CEE3DMP_A = 0x7B6 // 1974 + SYS___CDUMP_A = 0x7B7 // 1975 + SYS___CSNAP_A = 0x7B8 // 1976 + SYS___CTEST_A = 0x7B9 // 1977 + SYS___CTRACE_A = 0x7BA // 1978 + SYS___VSWPRNTF2_A = 0x7BB // 1979 + SYS___INET_PTON_A = 0x7BC // 1980 + SYS___SYSLOG_A = 0x7BD // 1981 + SYS___CRYPT_A = 0x7BE // 1982 + SYS_____OPENDIR2_A = 0x7BF // 1983 + SYS_____READDIR2_A = 0x7C0 // 1984 + SYS___OPENDIR_A = 0x7C2 // 1986 + SYS___READDIR_A = 0x7C3 // 1987 + SYS_PREAD = 0x7C7 // 1991 + SYS_PWRITE = 0x7C8 // 1992 + SYS_M_CREATE_LAYOUT = 0x7C9 // 1993 + SYS_M_DESTROY_LAYOUT = 0x7CA // 1994 + SYS_M_GETVALUES_LAYOUT = 0x7CB // 1995 + SYS_M_SETVALUES_LAYOUT = 0x7CC // 1996 + SYS_M_TRANSFORM_LAYOUT = 0x7CD // 1997 + SYS_M_WTRANSFORM_LAYOUT = 0x7CE // 1998 + SYS_FWPRINTF = 0x7D1 // 2001 + SYS_WPRINTF = 0x7D2 // 2002 + SYS_VFWPRINT = 0x7D3 // 2003 + SYS_VFWPRINTF = 0x7D3 // 2003 + SYS_VWPRINTF = 0x7D4 // 2004 + SYS_FWSCANF = 0x7D5 // 2005 + SYS_WSCANF = 0x7D6 // 2006 + SYS_WCTRANS = 0x7D7 // 2007 + SYS_TOWCTRAN = 0x7D8 // 2008 + SYS_TOWCTRANS = 0x7D8 // 2008 + SYS___WCSTOD_A = 0x7D9 // 2009 + SYS___WCSTOL_A = 0x7DA // 2010 + SYS___WCSTOUL_A = 0x7DB // 2011 + SYS___BASENAME_A = 0x7DC // 2012 + SYS___DIRNAME_A = 0x7DD // 2013 + SYS___GLOB_A = 0x7DE // 2014 + SYS_FWIDE = 0x7DF // 2015 + SYS___OSNAME = 0x7E0 // 2016 + SYS_____OSNAME_A = 0x7E1 // 2017 + SYS___BTOWC_A = 0x7E4 // 2020 + SYS___WCTOB_A = 0x7E5 // 2021 + SYS___DBM_OPEN_A = 0x7E6 // 2022 + SYS___VFPRINTF2_A = 0x7E7 // 2023 + SYS___VPRINTF2_A = 0x7E8 // 2024 + SYS___VSPRINTF2_A = 0x7E9 // 2025 + SYS___CEIL_H = 0x7EA // 2026 + SYS___FLOOR_H = 0x7EB // 2027 + SYS___MODF_H = 0x7EC // 2028 + SYS___FABS_H = 0x7ED // 2029 + SYS___J0_H = 0x7EE // 2030 + SYS___J1_H = 0x7EF // 2031 + SYS___JN_H = 0x7F0 // 2032 + SYS___Y0_H = 0x7F1 // 2033 + SYS___Y1_H = 0x7F2 // 2034 + SYS___YN_H = 0x7F3 // 2035 + SYS___CEILF_H = 0x7F4 // 2036 + SYS___CEILL_H = 0x7F5 // 2037 + SYS___FLOORF_H = 0x7F6 // 2038 + SYS___FLOORL_H = 0x7F7 // 2039 + SYS___MODFF_H = 0x7F8 // 2040 + SYS___MODFL_H = 0x7F9 // 2041 + SYS___FABSF_H = 0x7FA // 2042 + SYS___FABSL_H = 0x7FB // 2043 + SYS___MALLOC24 = 0x7FC // 2044 + SYS___MALLOC31 = 0x7FD // 2045 + SYS_ACL_INIT = 0x7FE // 2046 + SYS_ACL_FREE = 0x7FF // 2047 + SYS_ACL_FIRST_ENTRY = 0x800 // 2048 + SYS_ACL_GET_ENTRY = 0x801 // 2049 + SYS_ACL_VALID = 0x802 // 2050 + SYS_ACL_CREATE_ENTRY = 0x803 // 2051 + SYS_ACL_DELETE_ENTRY = 0x804 // 2052 + SYS_ACL_UPDATE_ENTRY = 0x805 // 2053 + SYS_ACL_DELETE_FD = 0x806 // 2054 + SYS_ACL_DELETE_FILE = 0x807 // 2055 + SYS_ACL_GET_FD = 0x808 // 2056 + SYS_ACL_GET_FILE = 0x809 // 2057 + SYS_ACL_SET_FD = 0x80A // 2058 + SYS_ACL_SET_FILE = 0x80B // 2059 + SYS_ACL_FROM_TEXT = 0x80C // 2060 + SYS_ACL_TO_TEXT = 0x80D // 2061 + SYS_ACL_SORT = 0x80E // 2062 + SYS___SHUTDOWN_REGISTRATION = 0x80F // 2063 + SYS___ERFL_B = 0x810 // 2064 + SYS___ERFCL_B = 0x811 // 2065 + SYS___LGAMMAL_B = 0x812 // 2066 + SYS___SETHOOKEVENTS = 0x813 // 2067 + SYS_IF_NAMETOINDEX = 0x814 // 2068 + SYS_IF_INDEXTONAME = 0x815 // 2069 + SYS_IF_NAMEINDEX = 0x816 // 2070 + SYS_IF_FREENAMEINDEX = 0x817 // 2071 + SYS_GETADDRINFO = 0x818 // 2072 + SYS_GETNAMEINFO = 0x819 // 2073 + SYS_FREEADDRINFO = 0x81A // 2074 + SYS_GAI_STRERROR = 0x81B // 2075 + SYS_REXEC_AF = 0x81C // 2076 + SYS___POE = 0x81D // 2077 + SYS___DYNALLOC_A = 0x81F // 2079 + SYS___DYNFREE_A = 0x820 // 2080 + SYS___RES_QUERY_A = 0x821 // 2081 + SYS___RES_SEARCH_A = 0x822 // 2082 + SYS___RES_QUERYDOMAIN_A = 0x823 // 2083 + SYS___RES_MKQUERY_A = 0x824 // 2084 + SYS___RES_SEND_A = 0x825 // 2085 + SYS___DN_EXPAND_A = 0x826 // 2086 + SYS___DN_SKIPNAME_A = 0x827 // 2087 + SYS___DN_COMP_A = 0x828 // 2088 + SYS___DN_FIND_A = 0x829 // 2089 + SYS___NLIST_A = 0x82A // 2090 + SYS_____TCGETCP_A = 0x82B // 2091 + SYS_____TCSETCP_A = 0x82C // 2092 + SYS_____W_PIOCTL_A = 0x82E // 2094 + SYS___INET_ADDR_A = 0x82F // 2095 + SYS___INET_NTOA_A = 0x830 // 2096 + SYS___INET_NETWORK_A = 0x831 // 2097 + SYS___ACCEPT_A = 0x832 // 2098 + SYS___ACCEPT_AND_RECV_A = 0x833 // 2099 + SYS___BIND_A = 0x834 // 2100 + SYS___CONNECT_A = 0x835 // 2101 + SYS___GETPEERNAME_A = 0x836 // 2102 + SYS___GETSOCKNAME_A = 0x837 // 2103 + SYS___RECVFROM_A = 0x838 // 2104 + SYS___SENDTO_A = 0x839 // 2105 + SYS___SENDMSG_A = 0x83A // 2106 + SYS___RECVMSG_A = 0x83B // 2107 + SYS_____LCHATTR_A = 0x83C // 2108 + SYS___CABEND = 0x83D // 2109 + SYS___LE_CIB_GET = 0x83E // 2110 + SYS___SET_LAA_FOR_JIT = 0x83F // 2111 + SYS___LCHATTR = 0x840 // 2112 + SYS___WRITEDOWN = 0x841 // 2113 + SYS_PTHREAD_MUTEX_INIT2 = 0x842 // 2114 + SYS___ACOSHF_B = 0x843 // 2115 + SYS___ACOSHL_B = 0x844 // 2116 + SYS___ASINHF_B = 0x845 // 2117 + SYS___ASINHL_B = 0x846 // 2118 + SYS___ATANHF_B = 0x847 // 2119 + SYS___ATANHL_B = 0x848 // 2120 + SYS___CBRTF_B = 0x849 // 2121 + SYS___CBRTL_B = 0x84A // 2122 + SYS___COPYSIGNF_B = 0x84B // 2123 + SYS___COPYSIGNL_B = 0x84C // 2124 + SYS___COTANF_B = 0x84D // 2125 + SYS___COTAN_B = 0x84E // 2126 + SYS___COTANL_B = 0x84F // 2127 + SYS___EXP2F_B = 0x850 // 2128 + SYS___EXP2L_B = 0x851 // 2129 + SYS___EXPM1F_B = 0x852 // 2130 + SYS___EXPM1L_B = 0x853 // 2131 + SYS___FDIMF_B = 0x854 // 2132 + SYS___FDIM_B = 0x855 // 2133 + SYS___FDIML_B = 0x856 // 2134 + SYS___HYPOTF_B = 0x857 // 2135 + SYS___HYPOTL_B = 0x858 // 2136 + SYS___LOG1PF_B = 0x859 // 2137 + SYS___LOG1PL_B = 0x85A // 2138 + SYS___LOG2F_B = 0x85B // 2139 + SYS___LOG2_B = 0x85C // 2140 + SYS___LOG2L_B = 0x85D // 2141 + SYS___REMAINDERF_B = 0x85E // 2142 + SYS___REMAINDERL_B = 0x85F // 2143 + SYS___REMQUOF_B = 0x860 // 2144 + SYS___REMQUO_B = 0x861 // 2145 + SYS___REMQUOL_B = 0x862 // 2146 + SYS___TGAMMAF_B = 0x863 // 2147 + SYS___TGAMMA_B = 0x864 // 2148 + SYS___TGAMMAL_B = 0x865 // 2149 + SYS___TRUNCF_B = 0x866 // 2150 + SYS___TRUNC_B = 0x867 // 2151 + SYS___TRUNCL_B = 0x868 // 2152 + SYS___LGAMMAF_B = 0x869 // 2153 + SYS___LROUNDF_B = 0x86A // 2154 + SYS___LROUND_B = 0x86B // 2155 + SYS___ERFF_B = 0x86C // 2156 + SYS___ERFCF_B = 0x86D // 2157 + SYS_ACOSHF = 0x86E // 2158 + SYS_ACOSHL = 0x86F // 2159 + SYS_ASINHF = 0x870 // 2160 + SYS_ASINHL = 0x871 // 2161 + SYS_ATANHF = 0x872 // 2162 + SYS_ATANHL = 0x873 // 2163 + SYS_CBRTF = 0x874 // 2164 + SYS_CBRTL = 0x875 // 2165 + SYS_COPYSIGNF = 0x876 // 2166 + SYS_CPYSIGNF = 0x876 // 2166 + SYS_COPYSIGNL = 0x877 // 2167 + SYS_CPYSIGNL = 0x877 // 2167 + SYS_COTANF = 0x878 // 2168 + SYS___COTANF = 0x878 // 2168 + SYS_COTAN = 0x879 // 2169 + SYS___COTAN = 0x879 // 2169 + SYS_COTANL = 0x87A // 2170 + SYS___COTANL = 0x87A // 2170 + SYS_EXP2F = 0x87B // 2171 + SYS_EXP2L = 0x87C // 2172 + SYS_EXPM1F = 0x87D // 2173 + SYS_EXPM1L = 0x87E // 2174 + SYS_FDIMF = 0x87F // 2175 + SYS_FDIM = 0x881 // 2177 + SYS_FDIML = 0x882 // 2178 + SYS_HYPOTF = 0x883 // 2179 + SYS_HYPOTL = 0x884 // 2180 + SYS_LOG1PF = 0x885 // 2181 + SYS_LOG1PL = 0x886 // 2182 + SYS_LOG2F = 0x887 // 2183 + SYS_LOG2 = 0x888 // 2184 + SYS_LOG2L = 0x889 // 2185 + SYS_REMAINDERF = 0x88A // 2186 + SYS_REMAINDF = 0x88A // 2186 + SYS_REMAINDERL = 0x88B // 2187 + SYS_REMAINDL = 0x88B // 2187 + SYS_REMQUOF = 0x88C // 2188 + SYS_REMQUO = 0x88D // 2189 + SYS_REMQUOL = 0x88E // 2190 + SYS_TGAMMAF = 0x88F // 2191 + SYS_TGAMMA = 0x890 // 2192 + SYS_TGAMMAL = 0x891 // 2193 + SYS_TRUNCF = 0x892 // 2194 + SYS_TRUNC = 0x893 // 2195 + SYS_TRUNCL = 0x894 // 2196 + SYS_LGAMMAF = 0x895 // 2197 + SYS_LGAMMAL = 0x896 // 2198 + SYS_LROUNDF = 0x897 // 2199 + SYS_LROUND = 0x898 // 2200 + SYS_ERFF = 0x899 // 2201 + SYS_ERFL = 0x89A // 2202 + SYS_ERFCF = 0x89B // 2203 + SYS_ERFCL = 0x89C // 2204 + SYS___EXP2_B = 0x89D // 2205 + SYS_EXP2 = 0x89E // 2206 + SYS___FAR_JUMP = 0x89F // 2207 + SYS___TCGETATTR_A = 0x8A1 // 2209 + SYS___TCSETATTR_A = 0x8A2 // 2210 + SYS___SUPERKILL = 0x8A4 // 2212 + SYS___LE_CONDITION_TOKEN_BUILD = 0x8A5 // 2213 + SYS___LE_MSG_ADD_INSERT = 0x8A6 // 2214 + SYS___LE_MSG_GET = 0x8A7 // 2215 + SYS___LE_MSG_GET_AND_WRITE = 0x8A8 // 2216 + SYS___LE_MSG_WRITE = 0x8A9 // 2217 + SYS___ITOA = 0x8AA // 2218 + SYS___UTOA = 0x8AB // 2219 + SYS___LTOA = 0x8AC // 2220 + SYS___ULTOA = 0x8AD // 2221 + SYS___LLTOA = 0x8AE // 2222 + SYS___ULLTOA = 0x8AF // 2223 + SYS___ITOA_A = 0x8B0 // 2224 + SYS___UTOA_A = 0x8B1 // 2225 + SYS___LTOA_A = 0x8B2 // 2226 + SYS___ULTOA_A = 0x8B3 // 2227 + SYS___LLTOA_A = 0x8B4 // 2228 + SYS___ULLTOA_A = 0x8B5 // 2229 + SYS_____GETENV_A = 0x8C3 // 2243 + SYS___REXEC_A = 0x8C4 // 2244 + SYS___REXEC_AF_A = 0x8C5 // 2245 + SYS___GETUTXENT_A = 0x8C6 // 2246 + SYS___GETUTXID_A = 0x8C7 // 2247 + SYS___GETUTXLINE_A = 0x8C8 // 2248 + SYS___PUTUTXLINE_A = 0x8C9 // 2249 + SYS_____UTMPXNAME_A = 0x8CA // 2250 + SYS___PUTC_UNLOCKED_A = 0x8CB // 2251 + SYS___PUTCHAR_UNLOCKED_A = 0x8CC // 2252 + SYS___SNPRINTF_A = 0x8CD // 2253 + SYS___VSNPRINTF_A = 0x8CE // 2254 + SYS___DLOPEN_A = 0x8D0 // 2256 + SYS___DLSYM_A = 0x8D1 // 2257 + SYS___DLERROR_A = 0x8D2 // 2258 + SYS_FLOCKFILE = 0x8D3 // 2259 + SYS_FTRYLOCKFILE = 0x8D4 // 2260 + SYS_FUNLOCKFILE = 0x8D5 // 2261 + SYS_GETC_UNLOCKED = 0x8D6 // 2262 + SYS_GETCHAR_UNLOCKED = 0x8D7 // 2263 + SYS_PUTC_UNLOCKED = 0x8D8 // 2264 + SYS_PUTCHAR_UNLOCKED = 0x8D9 // 2265 + SYS_SNPRINTF = 0x8DA // 2266 + SYS_VSNPRINTF = 0x8DB // 2267 + SYS_DLOPEN = 0x8DD // 2269 + SYS_DLSYM = 0x8DE // 2270 + SYS_DLCLOSE = 0x8DF // 2271 + SYS_DLERROR = 0x8E0 // 2272 + SYS___SET_EXCEPTION_HANDLER = 0x8E2 // 2274 + SYS___RESET_EXCEPTION_HANDLER = 0x8E3 // 2275 + SYS___VHM_EVENT = 0x8E4 // 2276 + SYS___ABS_H = 0x8E6 // 2278 + SYS___ABSF_H = 0x8E7 // 2279 + SYS___ABSL_H = 0x8E8 // 2280 + SYS___ACOS_H = 0x8E9 // 2281 + SYS___ACOSF_H = 0x8EA // 2282 + SYS___ACOSL_H = 0x8EB // 2283 + SYS___ACOSH_H = 0x8EC // 2284 + SYS___ASIN_H = 0x8ED // 2285 + SYS___ASINF_H = 0x8EE // 2286 + SYS___ASINL_H = 0x8EF // 2287 + SYS___ASINH_H = 0x8F0 // 2288 + SYS___ATAN_H = 0x8F1 // 2289 + SYS___ATANF_H = 0x8F2 // 2290 + SYS___ATANL_H = 0x8F3 // 2291 + SYS___ATANH_H = 0x8F4 // 2292 + SYS___ATANHF_H = 0x8F5 // 2293 + SYS___ATANHL_H = 0x8F6 // 2294 + SYS___ATAN2_H = 0x8F7 // 2295 + SYS___ATAN2F_H = 0x8F8 // 2296 + SYS___ATAN2L_H = 0x8F9 // 2297 + SYS___CBRT_H = 0x8FA // 2298 + SYS___COPYSIGNF_H = 0x8FB // 2299 + SYS___COPYSIGNL_H = 0x8FC // 2300 + SYS___COS_H = 0x8FD // 2301 + SYS___COSF_H = 0x8FE // 2302 + SYS___COSL_H = 0x8FF // 2303 + SYS___COSHF_H = 0x900 // 2304 + SYS___COSHL_H = 0x901 // 2305 + SYS___COTAN_H = 0x902 // 2306 + SYS___COTANF_H = 0x903 // 2307 + SYS___COTANL_H = 0x904 // 2308 + SYS___ERF_H = 0x905 // 2309 + SYS___ERFF_H = 0x906 // 2310 + SYS___ERFL_H = 0x907 // 2311 + SYS___ERFC_H = 0x908 // 2312 + SYS___ERFCF_H = 0x909 // 2313 + SYS___ERFCL_H = 0x90A // 2314 + SYS___EXP_H = 0x90B // 2315 + SYS___EXPF_H = 0x90C // 2316 + SYS___EXPL_H = 0x90D // 2317 + SYS___EXPM1_H = 0x90E // 2318 + SYS___FDIM_H = 0x90F // 2319 + SYS___FDIMF_H = 0x910 // 2320 + SYS___FDIML_H = 0x911 // 2321 + SYS___FMOD_H = 0x912 // 2322 + SYS___FMODF_H = 0x913 // 2323 + SYS___FMODL_H = 0x914 // 2324 + SYS___GAMMA_H = 0x915 // 2325 + SYS___HYPOT_H = 0x916 // 2326 + SYS___ILOGB_H = 0x917 // 2327 + SYS___LGAMMA_H = 0x918 // 2328 + SYS___LGAMMAF_H = 0x919 // 2329 + SYS___LOG_H = 0x91A // 2330 + SYS___LOGF_H = 0x91B // 2331 + SYS___LOGL_H = 0x91C // 2332 + SYS___LOGB_H = 0x91D // 2333 + SYS___LOG2_H = 0x91E // 2334 + SYS___LOG2F_H = 0x91F // 2335 + SYS___LOG2L_H = 0x920 // 2336 + SYS___LOG1P_H = 0x921 // 2337 + SYS___LOG10_H = 0x922 // 2338 + SYS___LOG10F_H = 0x923 // 2339 + SYS___LOG10L_H = 0x924 // 2340 + SYS___LROUND_H = 0x925 // 2341 + SYS___LROUNDF_H = 0x926 // 2342 + SYS___NEXTAFTER_H = 0x927 // 2343 + SYS___POW_H = 0x928 // 2344 + SYS___POWF_H = 0x929 // 2345 + SYS___POWL_H = 0x92A // 2346 + SYS___REMAINDER_H = 0x92B // 2347 + SYS___RINT_H = 0x92C // 2348 + SYS___SCALB_H = 0x92D // 2349 + SYS___SIN_H = 0x92E // 2350 + SYS___SINF_H = 0x92F // 2351 + SYS___SINL_H = 0x930 // 2352 + SYS___SINH_H = 0x931 // 2353 + SYS___SINHF_H = 0x932 // 2354 + SYS___SINHL_H = 0x933 // 2355 + SYS___SQRT_H = 0x934 // 2356 + SYS___SQRTF_H = 0x935 // 2357 + SYS___SQRTL_H = 0x936 // 2358 + SYS___TAN_H = 0x937 // 2359 + SYS___TANF_H = 0x938 // 2360 + SYS___TANL_H = 0x939 // 2361 + SYS___TANH_H = 0x93A // 2362 + SYS___TANHF_H = 0x93B // 2363 + SYS___TANHL_H = 0x93C // 2364 + SYS___TGAMMA_H = 0x93D // 2365 + SYS___TGAMMAF_H = 0x93E // 2366 + SYS___TRUNC_H = 0x93F // 2367 + SYS___TRUNCF_H = 0x940 // 2368 + SYS___TRUNCL_H = 0x941 // 2369 + SYS___COSH_H = 0x942 // 2370 + SYS___LE_DEBUG_SET_RESUME_MCH = 0x943 // 2371 + SYS_VFSCANF = 0x944 // 2372 + SYS_VSCANF = 0x946 // 2374 + SYS_VSSCANF = 0x948 // 2376 + SYS_VFWSCANF = 0x94A // 2378 + SYS_VWSCANF = 0x94C // 2380 + SYS_VSWSCANF = 0x94E // 2382 + SYS_IMAXABS = 0x950 // 2384 + SYS_IMAXDIV = 0x951 // 2385 + SYS_STRTOIMAX = 0x952 // 2386 + SYS_STRTOUMAX = 0x953 // 2387 + SYS_WCSTOIMAX = 0x954 // 2388 + SYS_WCSTOUMAX = 0x955 // 2389 + SYS_ATOLL = 0x956 // 2390 + SYS_STRTOF = 0x957 // 2391 + SYS_STRTOLD = 0x958 // 2392 + SYS_WCSTOF = 0x959 // 2393 + SYS_WCSTOLD = 0x95A // 2394 + SYS_INET6_RTH_SPACE = 0x95B // 2395 + SYS_INET6_RTH_INIT = 0x95C // 2396 + SYS_INET6_RTH_ADD = 0x95D // 2397 + SYS_INET6_RTH_REVERSE = 0x95E // 2398 + SYS_INET6_RTH_SEGMENTS = 0x95F // 2399 + SYS_INET6_RTH_GETADDR = 0x960 // 2400 + SYS_INET6_OPT_INIT = 0x961 // 2401 + SYS_INET6_OPT_APPEND = 0x962 // 2402 + SYS_INET6_OPT_FINISH = 0x963 // 2403 + SYS_INET6_OPT_SET_VAL = 0x964 // 2404 + SYS_INET6_OPT_NEXT = 0x965 // 2405 + SYS_INET6_OPT_FIND = 0x966 // 2406 + SYS_INET6_OPT_GET_VAL = 0x967 // 2407 + SYS___POW_I = 0x987 // 2439 + SYS___POW_I_B = 0x988 // 2440 + SYS___POW_I_H = 0x989 // 2441 + SYS___POW_II = 0x98A // 2442 + SYS___POW_II_B = 0x98B // 2443 + SYS___POW_II_H = 0x98C // 2444 + SYS_CABS = 0x98E // 2446 + SYS___CABS_B = 0x98F // 2447 + SYS___CABS_H = 0x990 // 2448 + SYS_CABSF = 0x991 // 2449 + SYS___CABSF_B = 0x992 // 2450 + SYS___CABSF_H = 0x993 // 2451 + SYS_CABSL = 0x994 // 2452 + SYS___CABSL_B = 0x995 // 2453 + SYS___CABSL_H = 0x996 // 2454 + SYS_CACOS = 0x997 // 2455 + SYS___CACOS_B = 0x998 // 2456 + SYS___CACOS_H = 0x999 // 2457 + SYS_CACOSF = 0x99A // 2458 + SYS___CACOSF_B = 0x99B // 2459 + SYS___CACOSF_H = 0x99C // 2460 + SYS_CACOSL = 0x99D // 2461 + SYS___CACOSL_B = 0x99E // 2462 + SYS___CACOSL_H = 0x99F // 2463 + SYS_CACOSH = 0x9A0 // 2464 + SYS___CACOSH_B = 0x9A1 // 2465 + SYS___CACOSH_H = 0x9A2 // 2466 + SYS_CACOSHF = 0x9A3 // 2467 + SYS___CACOSHF_B = 0x9A4 // 2468 + SYS___CACOSHF_H = 0x9A5 // 2469 + SYS_CACOSHL = 0x9A6 // 2470 + SYS___CACOSHL_B = 0x9A7 // 2471 + SYS___CACOSHL_H = 0x9A8 // 2472 + SYS_CARG = 0x9A9 // 2473 + SYS___CARG_B = 0x9AA // 2474 + SYS___CARG_H = 0x9AB // 2475 + SYS_CARGF = 0x9AC // 2476 + SYS___CARGF_B = 0x9AD // 2477 + SYS___CARGF_H = 0x9AE // 2478 + SYS_CARGL = 0x9AF // 2479 + SYS___CARGL_B = 0x9B0 // 2480 + SYS___CARGL_H = 0x9B1 // 2481 + SYS_CASIN = 0x9B2 // 2482 + SYS___CASIN_B = 0x9B3 // 2483 + SYS___CASIN_H = 0x9B4 // 2484 + SYS_CASINF = 0x9B5 // 2485 + SYS___CASINF_B = 0x9B6 // 2486 + SYS___CASINF_H = 0x9B7 // 2487 + SYS_CASINL = 0x9B8 // 2488 + SYS___CASINL_B = 0x9B9 // 2489 + SYS___CASINL_H = 0x9BA // 2490 + SYS_CASINH = 0x9BB // 2491 + SYS___CASINH_B = 0x9BC // 2492 + SYS___CASINH_H = 0x9BD // 2493 + SYS_CASINHF = 0x9BE // 2494 + SYS___CASINHF_B = 0x9BF // 2495 + SYS___CASINHF_H = 0x9C0 // 2496 + SYS_CASINHL = 0x9C1 // 2497 + SYS___CASINHL_B = 0x9C2 // 2498 + SYS___CASINHL_H = 0x9C3 // 2499 + SYS_CATAN = 0x9C4 // 2500 + SYS___CATAN_B = 0x9C5 // 2501 + SYS___CATAN_H = 0x9C6 // 2502 + SYS_CATANF = 0x9C7 // 2503 + SYS___CATANF_B = 0x9C8 // 2504 + SYS___CATANF_H = 0x9C9 // 2505 + SYS_CATANL = 0x9CA // 2506 + SYS___CATANL_B = 0x9CB // 2507 + SYS___CATANL_H = 0x9CC // 2508 + SYS_CATANH = 0x9CD // 2509 + SYS___CATANH_B = 0x9CE // 2510 + SYS___CATANH_H = 0x9CF // 2511 + SYS_CATANHF = 0x9D0 // 2512 + SYS___CATANHF_B = 0x9D1 // 2513 + SYS___CATANHF_H = 0x9D2 // 2514 + SYS_CATANHL = 0x9D3 // 2515 + SYS___CATANHL_B = 0x9D4 // 2516 + SYS___CATANHL_H = 0x9D5 // 2517 + SYS_CCOS = 0x9D6 // 2518 + SYS___CCOS_B = 0x9D7 // 2519 + SYS___CCOS_H = 0x9D8 // 2520 + SYS_CCOSF = 0x9D9 // 2521 + SYS___CCOSF_B = 0x9DA // 2522 + SYS___CCOSF_H = 0x9DB // 2523 + SYS_CCOSL = 0x9DC // 2524 + SYS___CCOSL_B = 0x9DD // 2525 + SYS___CCOSL_H = 0x9DE // 2526 + SYS_CCOSH = 0x9DF // 2527 + SYS___CCOSH_B = 0x9E0 // 2528 + SYS___CCOSH_H = 0x9E1 // 2529 + SYS_CCOSHF = 0x9E2 // 2530 + SYS___CCOSHF_B = 0x9E3 // 2531 + SYS___CCOSHF_H = 0x9E4 // 2532 + SYS_CCOSHL = 0x9E5 // 2533 + SYS___CCOSHL_B = 0x9E6 // 2534 + SYS___CCOSHL_H = 0x9E7 // 2535 + SYS_CEXP = 0x9E8 // 2536 + SYS___CEXP_B = 0x9E9 // 2537 + SYS___CEXP_H = 0x9EA // 2538 + SYS_CEXPF = 0x9EB // 2539 + SYS___CEXPF_B = 0x9EC // 2540 + SYS___CEXPF_H = 0x9ED // 2541 + SYS_CEXPL = 0x9EE // 2542 + SYS___CEXPL_B = 0x9EF // 2543 + SYS___CEXPL_H = 0x9F0 // 2544 + SYS_CIMAG = 0x9F1 // 2545 + SYS___CIMAG_B = 0x9F2 // 2546 + SYS___CIMAG_H = 0x9F3 // 2547 + SYS_CIMAGF = 0x9F4 // 2548 + SYS___CIMAGF_B = 0x9F5 // 2549 + SYS___CIMAGF_H = 0x9F6 // 2550 + SYS_CIMAGL = 0x9F7 // 2551 + SYS___CIMAGL_B = 0x9F8 // 2552 + SYS___CIMAGL_H = 0x9F9 // 2553 + SYS___CLOG = 0x9FA // 2554 + SYS___CLOG_B = 0x9FB // 2555 + SYS___CLOG_H = 0x9FC // 2556 + SYS_CLOGF = 0x9FD // 2557 + SYS___CLOGF_B = 0x9FE // 2558 + SYS___CLOGF_H = 0x9FF // 2559 + SYS_CLOGL = 0xA00 // 2560 + SYS___CLOGL_B = 0xA01 // 2561 + SYS___CLOGL_H = 0xA02 // 2562 + SYS_CONJ = 0xA03 // 2563 + SYS___CONJ_B = 0xA04 // 2564 + SYS___CONJ_H = 0xA05 // 2565 + SYS_CONJF = 0xA06 // 2566 + SYS___CONJF_B = 0xA07 // 2567 + SYS___CONJF_H = 0xA08 // 2568 + SYS_CONJL = 0xA09 // 2569 + SYS___CONJL_B = 0xA0A // 2570 + SYS___CONJL_H = 0xA0B // 2571 + SYS_CPOW = 0xA0C // 2572 + SYS___CPOW_B = 0xA0D // 2573 + SYS___CPOW_H = 0xA0E // 2574 + SYS_CPOWF = 0xA0F // 2575 + SYS___CPOWF_B = 0xA10 // 2576 + SYS___CPOWF_H = 0xA11 // 2577 + SYS_CPOWL = 0xA12 // 2578 + SYS___CPOWL_B = 0xA13 // 2579 + SYS___CPOWL_H = 0xA14 // 2580 + SYS_CPROJ = 0xA15 // 2581 + SYS___CPROJ_B = 0xA16 // 2582 + SYS___CPROJ_H = 0xA17 // 2583 + SYS_CPROJF = 0xA18 // 2584 + SYS___CPROJF_B = 0xA19 // 2585 + SYS___CPROJF_H = 0xA1A // 2586 + SYS_CPROJL = 0xA1B // 2587 + SYS___CPROJL_B = 0xA1C // 2588 + SYS___CPROJL_H = 0xA1D // 2589 + SYS_CREAL = 0xA1E // 2590 + SYS___CREAL_B = 0xA1F // 2591 + SYS___CREAL_H = 0xA20 // 2592 + SYS_CREALF = 0xA21 // 2593 + SYS___CREALF_B = 0xA22 // 2594 + SYS___CREALF_H = 0xA23 // 2595 + SYS_CREALL = 0xA24 // 2596 + SYS___CREALL_B = 0xA25 // 2597 + SYS___CREALL_H = 0xA26 // 2598 + SYS_CSIN = 0xA27 // 2599 + SYS___CSIN_B = 0xA28 // 2600 + SYS___CSIN_H = 0xA29 // 2601 + SYS_CSINF = 0xA2A // 2602 + SYS___CSINF_B = 0xA2B // 2603 + SYS___CSINF_H = 0xA2C // 2604 + SYS_CSINL = 0xA2D // 2605 + SYS___CSINL_B = 0xA2E // 2606 + SYS___CSINL_H = 0xA2F // 2607 + SYS_CSINH = 0xA30 // 2608 + SYS___CSINH_B = 0xA31 // 2609 + SYS___CSINH_H = 0xA32 // 2610 + SYS_CSINHF = 0xA33 // 2611 + SYS___CSINHF_B = 0xA34 // 2612 + SYS___CSINHF_H = 0xA35 // 2613 + SYS_CSINHL = 0xA36 // 2614 + SYS___CSINHL_B = 0xA37 // 2615 + SYS___CSINHL_H = 0xA38 // 2616 + SYS_CSQRT = 0xA39 // 2617 + SYS___CSQRT_B = 0xA3A // 2618 + SYS___CSQRT_H = 0xA3B // 2619 + SYS_CSQRTF = 0xA3C // 2620 + SYS___CSQRTF_B = 0xA3D // 2621 + SYS___CSQRTF_H = 0xA3E // 2622 + SYS_CSQRTL = 0xA3F // 2623 + SYS___CSQRTL_B = 0xA40 // 2624 + SYS___CSQRTL_H = 0xA41 // 2625 + SYS_CTAN = 0xA42 // 2626 + SYS___CTAN_B = 0xA43 // 2627 + SYS___CTAN_H = 0xA44 // 2628 + SYS_CTANF = 0xA45 // 2629 + SYS___CTANF_B = 0xA46 // 2630 + SYS___CTANF_H = 0xA47 // 2631 + SYS_CTANL = 0xA48 // 2632 + SYS___CTANL_B = 0xA49 // 2633 + SYS___CTANL_H = 0xA4A // 2634 + SYS_CTANH = 0xA4B // 2635 + SYS___CTANH_B = 0xA4C // 2636 + SYS___CTANH_H = 0xA4D // 2637 + SYS_CTANHF = 0xA4E // 2638 + SYS___CTANHF_B = 0xA4F // 2639 + SYS___CTANHF_H = 0xA50 // 2640 + SYS_CTANHL = 0xA51 // 2641 + SYS___CTANHL_B = 0xA52 // 2642 + SYS___CTANHL_H = 0xA53 // 2643 + SYS___ACOSHF_H = 0xA54 // 2644 + SYS___ACOSHL_H = 0xA55 // 2645 + SYS___ASINHF_H = 0xA56 // 2646 + SYS___ASINHL_H = 0xA57 // 2647 + SYS___CBRTF_H = 0xA58 // 2648 + SYS___CBRTL_H = 0xA59 // 2649 + SYS___COPYSIGN_B = 0xA5A // 2650 + SYS___EXPM1F_H = 0xA5B // 2651 + SYS___EXPM1L_H = 0xA5C // 2652 + SYS___EXP2_H = 0xA5D // 2653 + SYS___EXP2F_H = 0xA5E // 2654 + SYS___EXP2L_H = 0xA5F // 2655 + SYS___LOG1PF_H = 0xA60 // 2656 + SYS___LOG1PL_H = 0xA61 // 2657 + SYS___LGAMMAL_H = 0xA62 // 2658 + SYS_FMA = 0xA63 // 2659 + SYS___FMA_B = 0xA64 // 2660 + SYS___FMA_H = 0xA65 // 2661 + SYS_FMAF = 0xA66 // 2662 + SYS___FMAF_B = 0xA67 // 2663 + SYS___FMAF_H = 0xA68 // 2664 + SYS_FMAL = 0xA69 // 2665 + SYS___FMAL_B = 0xA6A // 2666 + SYS___FMAL_H = 0xA6B // 2667 + SYS_FMAX = 0xA6C // 2668 + SYS___FMAX_B = 0xA6D // 2669 + SYS___FMAX_H = 0xA6E // 2670 + SYS_FMAXF = 0xA6F // 2671 + SYS___FMAXF_B = 0xA70 // 2672 + SYS___FMAXF_H = 0xA71 // 2673 + SYS_FMAXL = 0xA72 // 2674 + SYS___FMAXL_B = 0xA73 // 2675 + SYS___FMAXL_H = 0xA74 // 2676 + SYS_FMIN = 0xA75 // 2677 + SYS___FMIN_B = 0xA76 // 2678 + SYS___FMIN_H = 0xA77 // 2679 + SYS_FMINF = 0xA78 // 2680 + SYS___FMINF_B = 0xA79 // 2681 + SYS___FMINF_H = 0xA7A // 2682 + SYS_FMINL = 0xA7B // 2683 + SYS___FMINL_B = 0xA7C // 2684 + SYS___FMINL_H = 0xA7D // 2685 + SYS_ILOGBF = 0xA7E // 2686 + SYS___ILOGBF_B = 0xA7F // 2687 + SYS___ILOGBF_H = 0xA80 // 2688 + SYS_ILOGBL = 0xA81 // 2689 + SYS___ILOGBL_B = 0xA82 // 2690 + SYS___ILOGBL_H = 0xA83 // 2691 + SYS_LLRINT = 0xA84 // 2692 + SYS___LLRINT_B = 0xA85 // 2693 + SYS___LLRINT_H = 0xA86 // 2694 + SYS_LLRINTF = 0xA87 // 2695 + SYS___LLRINTF_B = 0xA88 // 2696 + SYS___LLRINTF_H = 0xA89 // 2697 + SYS_LLRINTL = 0xA8A // 2698 + SYS___LLRINTL_B = 0xA8B // 2699 + SYS___LLRINTL_H = 0xA8C // 2700 + SYS_LLROUND = 0xA8D // 2701 + SYS___LLROUND_B = 0xA8E // 2702 + SYS___LLROUND_H = 0xA8F // 2703 + SYS_LLROUNDF = 0xA90 // 2704 + SYS___LLROUNDF_B = 0xA91 // 2705 + SYS___LLROUNDF_H = 0xA92 // 2706 + SYS_LLROUNDL = 0xA93 // 2707 + SYS___LLROUNDL_B = 0xA94 // 2708 + SYS___LLROUNDL_H = 0xA95 // 2709 + SYS_LOGBF = 0xA96 // 2710 + SYS___LOGBF_B = 0xA97 // 2711 + SYS___LOGBF_H = 0xA98 // 2712 + SYS_LOGBL = 0xA99 // 2713 + SYS___LOGBL_B = 0xA9A // 2714 + SYS___LOGBL_H = 0xA9B // 2715 + SYS_LRINT = 0xA9C // 2716 + SYS___LRINT_B = 0xA9D // 2717 + SYS___LRINT_H = 0xA9E // 2718 + SYS_LRINTF = 0xA9F // 2719 + SYS___LRINTF_B = 0xAA0 // 2720 + SYS___LRINTF_H = 0xAA1 // 2721 + SYS_LRINTL = 0xAA2 // 2722 + SYS___LRINTL_B = 0xAA3 // 2723 + SYS___LRINTL_H = 0xAA4 // 2724 + SYS_LROUNDL = 0xAA5 // 2725 + SYS___LROUNDL_B = 0xAA6 // 2726 + SYS___LROUNDL_H = 0xAA7 // 2727 + SYS_NAN = 0xAA8 // 2728 + SYS___NAN_B = 0xAA9 // 2729 + SYS_NANF = 0xAAA // 2730 + SYS___NANF_B = 0xAAB // 2731 + SYS_NANL = 0xAAC // 2732 + SYS___NANL_B = 0xAAD // 2733 + SYS_NEARBYINT = 0xAAE // 2734 + SYS___NEARBYINT_B = 0xAAF // 2735 + SYS___NEARBYINT_H = 0xAB0 // 2736 + SYS_NEARBYINTF = 0xAB1 // 2737 + SYS___NEARBYINTF_B = 0xAB2 // 2738 + SYS___NEARBYINTF_H = 0xAB3 // 2739 + SYS_NEARBYINTL = 0xAB4 // 2740 + SYS___NEARBYINTL_B = 0xAB5 // 2741 + SYS___NEARBYINTL_H = 0xAB6 // 2742 + SYS_NEXTAFTERF = 0xAB7 // 2743 + SYS___NEXTAFTERF_B = 0xAB8 // 2744 + SYS___NEXTAFTERF_H = 0xAB9 // 2745 + SYS_NEXTAFTERL = 0xABA // 2746 + SYS___NEXTAFTERL_B = 0xABB // 2747 + SYS___NEXTAFTERL_H = 0xABC // 2748 + SYS_NEXTTOWARD = 0xABD // 2749 + SYS___NEXTTOWARD_B = 0xABE // 2750 + SYS___NEXTTOWARD_H = 0xABF // 2751 + SYS_NEXTTOWARDF = 0xAC0 // 2752 + SYS___NEXTTOWARDF_B = 0xAC1 // 2753 + SYS___NEXTTOWARDF_H = 0xAC2 // 2754 + SYS_NEXTTOWARDL = 0xAC3 // 2755 + SYS___NEXTTOWARDL_B = 0xAC4 // 2756 + SYS___NEXTTOWARDL_H = 0xAC5 // 2757 + SYS___REMAINDERF_H = 0xAC6 // 2758 + SYS___REMAINDERL_H = 0xAC7 // 2759 + SYS___REMQUO_H = 0xAC8 // 2760 + SYS___REMQUOF_H = 0xAC9 // 2761 + SYS___REMQUOL_H = 0xACA // 2762 + SYS_RINTF = 0xACB // 2763 + SYS___RINTF_B = 0xACC // 2764 + SYS_RINTL = 0xACD // 2765 + SYS___RINTL_B = 0xACE // 2766 + SYS_ROUND = 0xACF // 2767 + SYS___ROUND_B = 0xAD0 // 2768 + SYS___ROUND_H = 0xAD1 // 2769 + SYS_ROUNDF = 0xAD2 // 2770 + SYS___ROUNDF_B = 0xAD3 // 2771 + SYS___ROUNDF_H = 0xAD4 // 2772 + SYS_ROUNDL = 0xAD5 // 2773 + SYS___ROUNDL_B = 0xAD6 // 2774 + SYS___ROUNDL_H = 0xAD7 // 2775 + SYS_SCALBLN = 0xAD8 // 2776 + SYS___SCALBLN_B = 0xAD9 // 2777 + SYS___SCALBLN_H = 0xADA // 2778 + SYS_SCALBLNF = 0xADB // 2779 + SYS___SCALBLNF_B = 0xADC // 2780 + SYS___SCALBLNF_H = 0xADD // 2781 + SYS_SCALBLNL = 0xADE // 2782 + SYS___SCALBLNL_B = 0xADF // 2783 + SYS___SCALBLNL_H = 0xAE0 // 2784 + SYS___SCALBN_B = 0xAE1 // 2785 + SYS___SCALBN_H = 0xAE2 // 2786 + SYS_SCALBNF = 0xAE3 // 2787 + SYS___SCALBNF_B = 0xAE4 // 2788 + SYS___SCALBNF_H = 0xAE5 // 2789 + SYS_SCALBNL = 0xAE6 // 2790 + SYS___SCALBNL_B = 0xAE7 // 2791 + SYS___SCALBNL_H = 0xAE8 // 2792 + SYS___TGAMMAL_H = 0xAE9 // 2793 + SYS_FECLEAREXCEPT = 0xAEA // 2794 + SYS_FEGETENV = 0xAEB // 2795 + SYS_FEGETEXCEPTFLAG = 0xAEC // 2796 + SYS_FEGETROUND = 0xAED // 2797 + SYS_FEHOLDEXCEPT = 0xAEE // 2798 + SYS_FERAISEEXCEPT = 0xAEF // 2799 + SYS_FESETENV = 0xAF0 // 2800 + SYS_FESETEXCEPTFLAG = 0xAF1 // 2801 + SYS_FESETROUND = 0xAF2 // 2802 + SYS_FETESTEXCEPT = 0xAF3 // 2803 + SYS_FEUPDATEENV = 0xAF4 // 2804 + SYS___COPYSIGN_H = 0xAF5 // 2805 + SYS___HYPOTF_H = 0xAF6 // 2806 + SYS___HYPOTL_H = 0xAF7 // 2807 + SYS___CLASS = 0xAFA // 2810 + SYS___CLASS_B = 0xAFB // 2811 + SYS___CLASS_H = 0xAFC // 2812 + SYS___ISBLANK_A = 0xB2E // 2862 + SYS___ISWBLANK_A = 0xB2F // 2863 + SYS___LROUND_FIXUP = 0xB30 // 2864 + SYS___LROUNDF_FIXUP = 0xB31 // 2865 + SYS_SCHED_YIELD = 0xB32 // 2866 + SYS_STRERROR_R = 0xB33 // 2867 + SYS_UNSETENV = 0xB34 // 2868 + SYS___LGAMMA_H_C99 = 0xB38 // 2872 + SYS___LGAMMA_B_C99 = 0xB39 // 2873 + SYS___LGAMMA_R_C99 = 0xB3A // 2874 + SYS___FTELL2 = 0xB3B // 2875 + SYS___FSEEK2 = 0xB3C // 2876 + SYS___STATIC_REINIT = 0xB3D // 2877 + SYS_PTHREAD_ATTR_GETSTACK = 0xB3E // 2878 + SYS_PTHREAD_ATTR_SETSTACK = 0xB3F // 2879 + SYS___TGAMMA_H_C99 = 0xB78 // 2936 + SYS___TGAMMAF_H_C99 = 0xB79 // 2937 + SYS___LE_TRACEBACK = 0xB7A // 2938 + SYS___MUST_STAY_CLEAN = 0xB7C // 2940 + SYS___O_ENV = 0xB7D // 2941 + SYS_ACOSD32 = 0xB7E // 2942 + SYS_ACOSD64 = 0xB7F // 2943 + SYS_ACOSD128 = 0xB80 // 2944 + SYS_ACOSHD32 = 0xB81 // 2945 + SYS_ACOSHD64 = 0xB82 // 2946 + SYS_ACOSHD128 = 0xB83 // 2947 + SYS_ASIND32 = 0xB84 // 2948 + SYS_ASIND64 = 0xB85 // 2949 + SYS_ASIND128 = 0xB86 // 2950 + SYS_ASINHD32 = 0xB87 // 2951 + SYS_ASINHD64 = 0xB88 // 2952 + SYS_ASINHD128 = 0xB89 // 2953 + SYS_ATAND32 = 0xB8A // 2954 + SYS_ATAND64 = 0xB8B // 2955 + SYS_ATAND128 = 0xB8C // 2956 + SYS_ATAN2D32 = 0xB8D // 2957 + SYS_ATAN2D64 = 0xB8E // 2958 + SYS_ATAN2D128 = 0xB8F // 2959 + SYS_ATANHD32 = 0xB90 // 2960 + SYS_ATANHD64 = 0xB91 // 2961 + SYS_ATANHD128 = 0xB92 // 2962 + SYS_CBRTD32 = 0xB93 // 2963 + SYS_CBRTD64 = 0xB94 // 2964 + SYS_CBRTD128 = 0xB95 // 2965 + SYS_CEILD32 = 0xB96 // 2966 + SYS_CEILD64 = 0xB97 // 2967 + SYS_CEILD128 = 0xB98 // 2968 + SYS___CLASS2 = 0xB99 // 2969 + SYS___CLASS2_B = 0xB9A // 2970 + SYS___CLASS2_H = 0xB9B // 2971 + SYS_COPYSIGND32 = 0xB9C // 2972 + SYS_COPYSIGND64 = 0xB9D // 2973 + SYS_COPYSIGND128 = 0xB9E // 2974 + SYS_COSD32 = 0xB9F // 2975 + SYS_COSD64 = 0xBA0 // 2976 + SYS_COSD128 = 0xBA1 // 2977 + SYS_COSHD32 = 0xBA2 // 2978 + SYS_COSHD64 = 0xBA3 // 2979 + SYS_COSHD128 = 0xBA4 // 2980 + SYS_ERFD32 = 0xBA5 // 2981 + SYS_ERFD64 = 0xBA6 // 2982 + SYS_ERFD128 = 0xBA7 // 2983 + SYS_ERFCD32 = 0xBA8 // 2984 + SYS_ERFCD64 = 0xBA9 // 2985 + SYS_ERFCD128 = 0xBAA // 2986 + SYS_EXPD32 = 0xBAB // 2987 + SYS_EXPD64 = 0xBAC // 2988 + SYS_EXPD128 = 0xBAD // 2989 + SYS_EXP2D32 = 0xBAE // 2990 + SYS_EXP2D64 = 0xBAF // 2991 + SYS_EXP2D128 = 0xBB0 // 2992 + SYS_EXPM1D32 = 0xBB1 // 2993 + SYS_EXPM1D64 = 0xBB2 // 2994 + SYS_EXPM1D128 = 0xBB3 // 2995 + SYS_FABSD32 = 0xBB4 // 2996 + SYS_FABSD64 = 0xBB5 // 2997 + SYS_FABSD128 = 0xBB6 // 2998 + SYS_FDIMD32 = 0xBB7 // 2999 + SYS_FDIMD64 = 0xBB8 // 3000 + SYS_FDIMD128 = 0xBB9 // 3001 + SYS_FE_DEC_GETROUND = 0xBBA // 3002 + SYS_FE_DEC_SETROUND = 0xBBB // 3003 + SYS_FLOORD32 = 0xBBC // 3004 + SYS_FLOORD64 = 0xBBD // 3005 + SYS_FLOORD128 = 0xBBE // 3006 + SYS_FMAD32 = 0xBBF // 3007 + SYS_FMAD64 = 0xBC0 // 3008 + SYS_FMAD128 = 0xBC1 // 3009 + SYS_FMAXD32 = 0xBC2 // 3010 + SYS_FMAXD64 = 0xBC3 // 3011 + SYS_FMAXD128 = 0xBC4 // 3012 + SYS_FMIND32 = 0xBC5 // 3013 + SYS_FMIND64 = 0xBC6 // 3014 + SYS_FMIND128 = 0xBC7 // 3015 + SYS_FMODD32 = 0xBC8 // 3016 + SYS_FMODD64 = 0xBC9 // 3017 + SYS_FMODD128 = 0xBCA // 3018 + SYS___FP_CAST_D = 0xBCB // 3019 + SYS_FREXPD32 = 0xBCC // 3020 + SYS_FREXPD64 = 0xBCD // 3021 + SYS_FREXPD128 = 0xBCE // 3022 + SYS_HYPOTD32 = 0xBCF // 3023 + SYS_HYPOTD64 = 0xBD0 // 3024 + SYS_HYPOTD128 = 0xBD1 // 3025 + SYS_ILOGBD32 = 0xBD2 // 3026 + SYS_ILOGBD64 = 0xBD3 // 3027 + SYS_ILOGBD128 = 0xBD4 // 3028 + SYS_LDEXPD32 = 0xBD5 // 3029 + SYS_LDEXPD64 = 0xBD6 // 3030 + SYS_LDEXPD128 = 0xBD7 // 3031 + SYS_LGAMMAD32 = 0xBD8 // 3032 + SYS_LGAMMAD64 = 0xBD9 // 3033 + SYS_LGAMMAD128 = 0xBDA // 3034 + SYS_LLRINTD32 = 0xBDB // 3035 + SYS_LLRINTD64 = 0xBDC // 3036 + SYS_LLRINTD128 = 0xBDD // 3037 + SYS_LLROUNDD32 = 0xBDE // 3038 + SYS_LLROUNDD64 = 0xBDF // 3039 + SYS_LLROUNDD128 = 0xBE0 // 3040 + SYS_LOGD32 = 0xBE1 // 3041 + SYS_LOGD64 = 0xBE2 // 3042 + SYS_LOGD128 = 0xBE3 // 3043 + SYS_LOG10D32 = 0xBE4 // 3044 + SYS_LOG10D64 = 0xBE5 // 3045 + SYS_LOG10D128 = 0xBE6 // 3046 + SYS_LOG1PD32 = 0xBE7 // 3047 + SYS_LOG1PD64 = 0xBE8 // 3048 + SYS_LOG1PD128 = 0xBE9 // 3049 + SYS_LOG2D32 = 0xBEA // 3050 + SYS_LOG2D64 = 0xBEB // 3051 + SYS_LOG2D128 = 0xBEC // 3052 + SYS_LOGBD32 = 0xBED // 3053 + SYS_LOGBD64 = 0xBEE // 3054 + SYS_LOGBD128 = 0xBEF // 3055 + SYS_LRINTD32 = 0xBF0 // 3056 + SYS_LRINTD64 = 0xBF1 // 3057 + SYS_LRINTD128 = 0xBF2 // 3058 + SYS_LROUNDD32 = 0xBF3 // 3059 + SYS_LROUNDD64 = 0xBF4 // 3060 + SYS_LROUNDD128 = 0xBF5 // 3061 + SYS_MODFD32 = 0xBF6 // 3062 + SYS_MODFD64 = 0xBF7 // 3063 + SYS_MODFD128 = 0xBF8 // 3064 + SYS_NAND32 = 0xBF9 // 3065 + SYS_NAND64 = 0xBFA // 3066 + SYS_NAND128 = 0xBFB // 3067 + SYS_NEARBYINTD32 = 0xBFC // 3068 + SYS_NEARBYINTD64 = 0xBFD // 3069 + SYS_NEARBYINTD128 = 0xBFE // 3070 + SYS_NEXTAFTERD32 = 0xBFF // 3071 + SYS_NEXTAFTERD64 = 0xC00 // 3072 + SYS_NEXTAFTERD128 = 0xC01 // 3073 + SYS_NEXTTOWARDD32 = 0xC02 // 3074 + SYS_NEXTTOWARDD64 = 0xC03 // 3075 + SYS_NEXTTOWARDD128 = 0xC04 // 3076 + SYS_POWD32 = 0xC05 // 3077 + SYS_POWD64 = 0xC06 // 3078 + SYS_POWD128 = 0xC07 // 3079 + SYS_QUANTIZED32 = 0xC08 // 3080 + SYS_QUANTIZED64 = 0xC09 // 3081 + SYS_QUANTIZED128 = 0xC0A // 3082 + SYS_REMAINDERD32 = 0xC0B // 3083 + SYS_REMAINDERD64 = 0xC0C // 3084 + SYS_REMAINDERD128 = 0xC0D // 3085 + SYS___REMQUOD32 = 0xC0E // 3086 + SYS___REMQUOD64 = 0xC0F // 3087 + SYS___REMQUOD128 = 0xC10 // 3088 + SYS_RINTD32 = 0xC11 // 3089 + SYS_RINTD64 = 0xC12 // 3090 + SYS_RINTD128 = 0xC13 // 3091 + SYS_ROUNDD32 = 0xC14 // 3092 + SYS_ROUNDD64 = 0xC15 // 3093 + SYS_ROUNDD128 = 0xC16 // 3094 + SYS_SAMEQUANTUMD32 = 0xC17 // 3095 + SYS_SAMEQUANTUMD64 = 0xC18 // 3096 + SYS_SAMEQUANTUMD128 = 0xC19 // 3097 + SYS_SCALBLND32 = 0xC1A // 3098 + SYS_SCALBLND64 = 0xC1B // 3099 + SYS_SCALBLND128 = 0xC1C // 3100 + SYS_SCALBND32 = 0xC1D // 3101 + SYS_SCALBND64 = 0xC1E // 3102 + SYS_SCALBND128 = 0xC1F // 3103 + SYS_SIND32 = 0xC20 // 3104 + SYS_SIND64 = 0xC21 // 3105 + SYS_SIND128 = 0xC22 // 3106 + SYS_SINHD32 = 0xC23 // 3107 + SYS_SINHD64 = 0xC24 // 3108 + SYS_SINHD128 = 0xC25 // 3109 + SYS_SQRTD32 = 0xC26 // 3110 + SYS_SQRTD64 = 0xC27 // 3111 + SYS_SQRTD128 = 0xC28 // 3112 + SYS_STRTOD32 = 0xC29 // 3113 + SYS_STRTOD64 = 0xC2A // 3114 + SYS_STRTOD128 = 0xC2B // 3115 + SYS_TAND32 = 0xC2C // 3116 + SYS_TAND64 = 0xC2D // 3117 + SYS_TAND128 = 0xC2E // 3118 + SYS_TANHD32 = 0xC2F // 3119 + SYS_TANHD64 = 0xC30 // 3120 + SYS_TANHD128 = 0xC31 // 3121 + SYS_TGAMMAD32 = 0xC32 // 3122 + SYS_TGAMMAD64 = 0xC33 // 3123 + SYS_TGAMMAD128 = 0xC34 // 3124 + SYS_TRUNCD32 = 0xC3E // 3134 + SYS_TRUNCD64 = 0xC3F // 3135 + SYS_TRUNCD128 = 0xC40 // 3136 + SYS_WCSTOD32 = 0xC41 // 3137 + SYS_WCSTOD64 = 0xC42 // 3138 + SYS_WCSTOD128 = 0xC43 // 3139 + SYS___CODEPAGE_INFO = 0xC64 // 3172 + SYS_POSIX_OPENPT = 0xC66 // 3174 + SYS_PSELECT = 0xC67 // 3175 + SYS_SOCKATMARK = 0xC68 // 3176 + SYS_AIO_FSYNC = 0xC69 // 3177 + SYS_LIO_LISTIO = 0xC6A // 3178 + SYS___ATANPID32 = 0xC6B // 3179 + SYS___ATANPID64 = 0xC6C // 3180 + SYS___ATANPID128 = 0xC6D // 3181 + SYS___COSPID32 = 0xC6E // 3182 + SYS___COSPID64 = 0xC6F // 3183 + SYS___COSPID128 = 0xC70 // 3184 + SYS___SINPID32 = 0xC71 // 3185 + SYS___SINPID64 = 0xC72 // 3186 + SYS___SINPID128 = 0xC73 // 3187 + SYS_SETIPV4SOURCEFILTER = 0xC76 // 3190 + SYS_GETIPV4SOURCEFILTER = 0xC77 // 3191 + SYS_SETSOURCEFILTER = 0xC78 // 3192 + SYS_GETSOURCEFILTER = 0xC79 // 3193 + SYS_FWRITE_UNLOCKED = 0xC7A // 3194 + SYS_FREAD_UNLOCKED = 0xC7B // 3195 + SYS_FGETS_UNLOCKED = 0xC7C // 3196 + SYS_GETS_UNLOCKED = 0xC7D // 3197 + SYS_FPUTS_UNLOCKED = 0xC7E // 3198 + SYS_PUTS_UNLOCKED = 0xC7F // 3199 + SYS_FGETC_UNLOCKED = 0xC80 // 3200 + SYS_FPUTC_UNLOCKED = 0xC81 // 3201 + SYS_DLADDR = 0xC82 // 3202 + SYS_SHM_OPEN = 0xC8C // 3212 + SYS_SHM_UNLINK = 0xC8D // 3213 + SYS___CLASS2F = 0xC91 // 3217 + SYS___CLASS2L = 0xC92 // 3218 + SYS___CLASS2F_B = 0xC93 // 3219 + SYS___CLASS2F_H = 0xC94 // 3220 + SYS___CLASS2L_B = 0xC95 // 3221 + SYS___CLASS2L_H = 0xC96 // 3222 + SYS___CLASS2D32 = 0xC97 // 3223 + SYS___CLASS2D64 = 0xC98 // 3224 + SYS___CLASS2D128 = 0xC99 // 3225 + SYS___TOCSNAME2 = 0xC9A // 3226 + SYS___D1TOP = 0xC9B // 3227 + SYS___D2TOP = 0xC9C // 3228 + SYS___D4TOP = 0xC9D // 3229 + SYS___PTOD1 = 0xC9E // 3230 + SYS___PTOD2 = 0xC9F // 3231 + SYS___PTOD4 = 0xCA0 // 3232 + SYS_CLEARERR_UNLOCKED = 0xCA1 // 3233 + SYS_FDELREC_UNLOCKED = 0xCA2 // 3234 + SYS_FEOF_UNLOCKED = 0xCA3 // 3235 + SYS_FERROR_UNLOCKED = 0xCA4 // 3236 + SYS_FFLUSH_UNLOCKED = 0xCA5 // 3237 + SYS_FGETPOS_UNLOCKED = 0xCA6 // 3238 + SYS_FGETWC_UNLOCKED = 0xCA7 // 3239 + SYS_FGETWS_UNLOCKED = 0xCA8 // 3240 + SYS_FILENO_UNLOCKED = 0xCA9 // 3241 + SYS_FLDATA_UNLOCKED = 0xCAA // 3242 + SYS_FLOCATE_UNLOCKED = 0xCAB // 3243 + SYS_FPRINTF_UNLOCKED = 0xCAC // 3244 + SYS_FPUTWC_UNLOCKED = 0xCAD // 3245 + SYS_FPUTWS_UNLOCKED = 0xCAE // 3246 + SYS_FSCANF_UNLOCKED = 0xCAF // 3247 + SYS_FSEEK_UNLOCKED = 0xCB0 // 3248 + SYS_FSEEKO_UNLOCKED = 0xCB1 // 3249 + SYS_FSETPOS_UNLOCKED = 0xCB3 // 3251 + SYS_FTELL_UNLOCKED = 0xCB4 // 3252 + SYS_FTELLO_UNLOCKED = 0xCB5 // 3253 + SYS_FUPDATE_UNLOCKED = 0xCB7 // 3255 + SYS_FWIDE_UNLOCKED = 0xCB8 // 3256 + SYS_FWPRINTF_UNLOCKED = 0xCB9 // 3257 + SYS_FWSCANF_UNLOCKED = 0xCBA // 3258 + SYS_GETWC_UNLOCKED = 0xCBB // 3259 + SYS_GETWCHAR_UNLOCKED = 0xCBC // 3260 + SYS_PERROR_UNLOCKED = 0xCBD // 3261 + SYS_PRINTF_UNLOCKED = 0xCBE // 3262 + SYS_PUTWC_UNLOCKED = 0xCBF // 3263 + SYS_PUTWCHAR_UNLOCKED = 0xCC0 // 3264 + SYS_REWIND_UNLOCKED = 0xCC1 // 3265 + SYS_SCANF_UNLOCKED = 0xCC2 // 3266 + SYS_UNGETC_UNLOCKED = 0xCC3 // 3267 + SYS_UNGETWC_UNLOCKED = 0xCC4 // 3268 + SYS_VFPRINTF_UNLOCKED = 0xCC5 // 3269 + SYS_VFSCANF_UNLOCKED = 0xCC7 // 3271 + SYS_VFWPRINTF_UNLOCKED = 0xCC9 // 3273 + SYS_VFWSCANF_UNLOCKED = 0xCCB // 3275 + SYS_VPRINTF_UNLOCKED = 0xCCD // 3277 + SYS_VSCANF_UNLOCKED = 0xCCF // 3279 + SYS_VWPRINTF_UNLOCKED = 0xCD1 // 3281 + SYS_VWSCANF_UNLOCKED = 0xCD3 // 3283 + SYS_WPRINTF_UNLOCKED = 0xCD5 // 3285 + SYS_WSCANF_UNLOCKED = 0xCD6 // 3286 + SYS_ASCTIME64 = 0xCD7 // 3287 + SYS_ASCTIME64_R = 0xCD8 // 3288 + SYS_CTIME64 = 0xCD9 // 3289 + SYS_CTIME64_R = 0xCDA // 3290 + SYS_DIFFTIME64 = 0xCDB // 3291 + SYS_GMTIME64 = 0xCDC // 3292 + SYS_GMTIME64_R = 0xCDD // 3293 + SYS_LOCALTIME64 = 0xCDE // 3294 + SYS_LOCALTIME64_R = 0xCDF // 3295 + SYS_MKTIME64 = 0xCE0 // 3296 + SYS_TIME64 = 0xCE1 // 3297 + SYS___LOGIN_APPLID = 0xCE2 // 3298 + SYS___PASSWD_APPLID = 0xCE3 // 3299 + SYS_PTHREAD_SECURITY_APPLID_NP = 0xCE4 // 3300 + SYS___GETTHENT = 0xCE5 // 3301 + SYS_FREEIFADDRS = 0xCE6 // 3302 + SYS_GETIFADDRS = 0xCE7 // 3303 + SYS_POSIX_FALLOCATE = 0xCE8 // 3304 + SYS_POSIX_MEMALIGN = 0xCE9 // 3305 + SYS_SIZEOF_ALLOC = 0xCEA // 3306 + SYS_RESIZE_ALLOC = 0xCEB // 3307 + SYS_FREAD_NOUPDATE = 0xCEC // 3308 + SYS_FREAD_NOUPDATE_UNLOCKED = 0xCED // 3309 + SYS_FGETPOS64 = 0xCEE // 3310 + SYS_FSEEK64 = 0xCEF // 3311 + SYS_FSEEKO64 = 0xCF0 // 3312 + SYS_FSETPOS64 = 0xCF1 // 3313 + SYS_FTELL64 = 0xCF2 // 3314 + SYS_FTELLO64 = 0xCF3 // 3315 + SYS_FGETPOS64_UNLOCKED = 0xCF4 // 3316 + SYS_FSEEK64_UNLOCKED = 0xCF5 // 3317 + SYS_FSEEKO64_UNLOCKED = 0xCF6 // 3318 + SYS_FSETPOS64_UNLOCKED = 0xCF7 // 3319 + SYS_FTELL64_UNLOCKED = 0xCF8 // 3320 + SYS_FTELLO64_UNLOCKED = 0xCF9 // 3321 + SYS_FOPEN_UNLOCKED = 0xCFA // 3322 + SYS_FREOPEN_UNLOCKED = 0xCFB // 3323 + SYS_FDOPEN_UNLOCKED = 0xCFC // 3324 + SYS_TMPFILE_UNLOCKED = 0xCFD // 3325 + SYS___MOSERVICES = 0xD3D // 3389 + SYS___GETTOD = 0xD3E // 3390 + SYS_C16RTOMB = 0xD40 // 3392 + SYS_C32RTOMB = 0xD41 // 3393 + SYS_MBRTOC16 = 0xD42 // 3394 + SYS_MBRTOC32 = 0xD43 // 3395 + SYS_QUANTEXPD32 = 0xD44 // 3396 + SYS_QUANTEXPD64 = 0xD45 // 3397 + SYS_QUANTEXPD128 = 0xD46 // 3398 + SYS___LOCALE_CTL = 0xD47 // 3399 + SYS___SMF_RECORD2 = 0xD48 // 3400 + SYS_FOPEN64 = 0xD49 // 3401 + SYS_FOPEN64_UNLOCKED = 0xD4A // 3402 + SYS_FREOPEN64 = 0xD4B // 3403 + SYS_FREOPEN64_UNLOCKED = 0xD4C // 3404 + SYS_TMPFILE64 = 0xD4D // 3405 + SYS_TMPFILE64_UNLOCKED = 0xD4E // 3406 + SYS_GETDATE64 = 0xD4F // 3407 + SYS_GETTIMEOFDAY64 = 0xD50 // 3408 + SYS_BIND2ADDRSEL = 0xD59 // 3417 + SYS_INET6_IS_SRCADDR = 0xD5A // 3418 + SYS___GETGRGID1 = 0xD5B // 3419 + SYS___GETGRNAM1 = 0xD5C // 3420 + SYS___FBUFSIZE = 0xD60 // 3424 + SYS___FPENDING = 0xD61 // 3425 + SYS___FLBF = 0xD62 // 3426 + SYS___FREADABLE = 0xD63 // 3427 + SYS___FWRITABLE = 0xD64 // 3428 + SYS___FREADING = 0xD65 // 3429 + SYS___FWRITING = 0xD66 // 3430 + SYS___FSETLOCKING = 0xD67 // 3431 + SYS__FLUSHLBF = 0xD68 // 3432 + SYS___FPURGE = 0xD69 // 3433 + SYS___FREADAHEAD = 0xD6A // 3434 + SYS___FSETERR = 0xD6B // 3435 + SYS___FPENDING_UNLOCKED = 0xD6C // 3436 + SYS___FREADING_UNLOCKED = 0xD6D // 3437 + SYS___FWRITING_UNLOCKED = 0xD6E // 3438 + SYS__FLUSHLBF_UNLOCKED = 0xD6F // 3439 + SYS___FPURGE_UNLOCKED = 0xD70 // 3440 + SYS___FREADAHEAD_UNLOCKED = 0xD71 // 3441 + SYS___LE_CEEGTJS = 0xD72 // 3442 + SYS___LE_RECORD_DUMP = 0xD73 // 3443 + SYS_FSTAT64 = 0xD74 // 3444 + SYS_LSTAT64 = 0xD75 // 3445 + SYS_STAT64 = 0xD76 // 3446 + SYS___READDIR2_64 = 0xD77 // 3447 + SYS___OPEN_STAT64 = 0xD78 // 3448 + SYS_FTW64 = 0xD79 // 3449 + SYS_NFTW64 = 0xD7A // 3450 + SYS_UTIME64 = 0xD7B // 3451 + SYS_UTIMES64 = 0xD7C // 3452 + SYS___GETIPC64 = 0xD7D // 3453 + SYS_MSGCTL64 = 0xD7E // 3454 + SYS_SEMCTL64 = 0xD7F // 3455 + SYS_SHMCTL64 = 0xD80 // 3456 + SYS_MSGXRCV64 = 0xD81 // 3457 + SYS___MGXR64 = 0xD81 // 3457 + SYS_W_GETPSENT64 = 0xD82 // 3458 + SYS_PTHREAD_COND_TIMEDWAIT64 = 0xD83 // 3459 + SYS_FTIME64 = 0xD85 // 3461 + SYS_GETUTXENT64 = 0xD86 // 3462 + SYS_GETUTXID64 = 0xD87 // 3463 + SYS_GETUTXLINE64 = 0xD88 // 3464 + SYS_PUTUTXLINE64 = 0xD89 // 3465 + SYS_NEWLOCALE = 0xD8A // 3466 + SYS_FREELOCALE = 0xD8B // 3467 + SYS_USELOCALE = 0xD8C // 3468 + SYS_DUPLOCALE = 0xD8D // 3469 + SYS___CHATTR64 = 0xD9C // 3484 + SYS___LCHATTR64 = 0xD9D // 3485 + SYS___FCHATTR64 = 0xD9E // 3486 + SYS_____CHATTR64_A = 0xD9F // 3487 + SYS_____LCHATTR64_A = 0xDA0 // 3488 + SYS___LE_CEEUSGD = 0xDA1 // 3489 + SYS___LE_IFAM_CON = 0xDA2 // 3490 + SYS___LE_IFAM_DSC = 0xDA3 // 3491 + SYS___LE_IFAM_GET = 0xDA4 // 3492 + SYS___LE_IFAM_QRY = 0xDA5 // 3493 + SYS_ALIGNED_ALLOC = 0xDA6 // 3494 + SYS_ACCEPT4 = 0xDA7 // 3495 + SYS___ACCEPT4_A = 0xDA8 // 3496 + SYS_COPYFILERANGE = 0xDA9 // 3497 + SYS_GETLINE = 0xDAA // 3498 + SYS___GETLINE_A = 0xDAB // 3499 + SYS_DIRFD = 0xDAC // 3500 + SYS_CLOCK_GETTIME = 0xDAD // 3501 + SYS_DUP3 = 0xDAE // 3502 + SYS_EPOLL_CREATE = 0xDAF // 3503 + SYS_EPOLL_CREATE1 = 0xDB0 // 3504 + SYS_EPOLL_CTL = 0xDB1 // 3505 + SYS_EPOLL_WAIT = 0xDB2 // 3506 + SYS_EPOLL_PWAIT = 0xDB3 // 3507 + SYS_EVENTFD = 0xDB4 // 3508 + SYS_STATFS = 0xDB5 // 3509 + SYS___STATFS_A = 0xDB6 // 3510 + SYS_FSTATFS = 0xDB7 // 3511 + SYS_INOTIFY_INIT = 0xDB8 // 3512 + SYS_INOTIFY_INIT1 = 0xDB9 // 3513 + SYS_INOTIFY_ADD_WATCH = 0xDBA // 3514 + SYS___INOTIFY_ADD_WATCH_A = 0xDBB // 3515 + SYS_INOTIFY_RM_WATCH = 0xDBC // 3516 + SYS_PIPE2 = 0xDBD // 3517 + SYS_PIVOT_ROOT = 0xDBE // 3518 + SYS___PIVOT_ROOT_A = 0xDBF // 3519 + SYS_PRCTL = 0xDC0 // 3520 + SYS_PRLIMIT = 0xDC1 // 3521 + SYS_SETHOSTNAME = 0xDC2 // 3522 + SYS___SETHOSTNAME_A = 0xDC3 // 3523 + SYS_SETRESUID = 0xDC4 // 3524 + SYS_SETRESGID = 0xDC5 // 3525 + SYS_PTHREAD_CONDATTR_GETCLOCK = 0xDC6 // 3526 + SYS_FLOCK = 0xDC7 // 3527 + SYS_FGETXATTR = 0xDC8 // 3528 + SYS___FGETXATTR_A = 0xDC9 // 3529 + SYS_FLISTXATTR = 0xDCA // 3530 + SYS___FLISTXATTR_A = 0xDCB // 3531 + SYS_FREMOVEXATTR = 0xDCC // 3532 + SYS___FREMOVEXATTR_A = 0xDCD // 3533 + SYS_FSETXATTR = 0xDCE // 3534 + SYS___FSETXATTR_A = 0xDCF // 3535 + SYS_GETXATTR = 0xDD0 // 3536 + SYS___GETXATTR_A = 0xDD1 // 3537 + SYS_LGETXATTR = 0xDD2 // 3538 + SYS___LGETXATTR_A = 0xDD3 // 3539 + SYS_LISTXATTR = 0xDD4 // 3540 + SYS___LISTXATTR_A = 0xDD5 // 3541 + SYS_LLISTXATTR = 0xDD6 // 3542 + SYS___LLISTXATTR_A = 0xDD7 // 3543 + SYS_LREMOVEXATTR = 0xDD8 // 3544 + SYS___LREMOVEXATTR_A = 0xDD9 // 3545 + SYS_LSETXATTR = 0xDDA // 3546 + SYS___LSETXATTR_A = 0xDDB // 3547 + SYS_REMOVEXATTR = 0xDDC // 3548 + SYS___REMOVEXATTR_A = 0xDDD // 3549 + SYS_SETXATTR = 0xDDE // 3550 + SYS___SETXATTR_A = 0xDDF // 3551 + SYS_FDATASYNC = 0xDE0 // 3552 + SYS_SYNCFS = 0xDE1 // 3553 + SYS_FUTIMES = 0xDE2 // 3554 + SYS_FUTIMESAT = 0xDE3 // 3555 + SYS___FUTIMESAT_A = 0xDE4 // 3556 + SYS_LUTIMES = 0xDE5 // 3557 + SYS___LUTIMES_A = 0xDE6 // 3558 + SYS_INET_ATON = 0xDE7 // 3559 + SYS_GETRANDOM = 0xDE8 // 3560 + SYS_GETTID = 0xDE9 // 3561 + SYS_MEMFD_CREATE = 0xDEA // 3562 + SYS___MEMFD_CREATE_A = 0xDEB // 3563 + SYS_FACCESSAT = 0xDEC // 3564 + SYS___FACCESSAT_A = 0xDED // 3565 + SYS_FCHMODAT = 0xDEE // 3566 + SYS___FCHMODAT_A = 0xDEF // 3567 + SYS_FCHOWNAT = 0xDF0 // 3568 + SYS___FCHOWNAT_A = 0xDF1 // 3569 + SYS_FSTATAT = 0xDF2 // 3570 + SYS___FSTATAT_A = 0xDF3 // 3571 + SYS_LINKAT = 0xDF4 // 3572 + SYS___LINKAT_A = 0xDF5 // 3573 + SYS_MKDIRAT = 0xDF6 // 3574 + SYS___MKDIRAT_A = 0xDF7 // 3575 + SYS_MKFIFOAT = 0xDF8 // 3576 + SYS___MKFIFOAT_A = 0xDF9 // 3577 + SYS_MKNODAT = 0xDFA // 3578 + SYS___MKNODAT_A = 0xDFB // 3579 + SYS_OPENAT = 0xDFC // 3580 + SYS___OPENAT_A = 0xDFD // 3581 + SYS_READLINKAT = 0xDFE // 3582 + SYS___READLINKAT_A = 0xDFF // 3583 + SYS_RENAMEAT = 0xE00 // 3584 + SYS___RENAMEAT_A = 0xE01 // 3585 + SYS_RENAMEAT2 = 0xE02 // 3586 + SYS___RENAMEAT2_A = 0xE03 // 3587 + SYS_SYMLINKAT = 0xE04 // 3588 + SYS___SYMLINKAT_A = 0xE05 // 3589 + SYS_UNLINKAT = 0xE06 // 3590 + SYS___UNLINKAT_A = 0xE07 // 3591 + SYS_SYSINFO = 0xE08 // 3592 + SYS_WAIT4 = 0xE0A // 3594 + SYS_CLONE = 0xE0B // 3595 + SYS_UNSHARE = 0xE0C // 3596 + SYS_SETNS = 0xE0D // 3597 + SYS_CAPGET = 0xE0E // 3598 + SYS_CAPSET = 0xE0F // 3599 + SYS_STRCHRNUL = 0xE10 // 3600 + SYS_PTHREAD_CONDATTR_SETCLOCK = 0xE12 // 3602 + SYS_OPEN_BY_HANDLE_AT = 0xE13 // 3603 + SYS___OPEN_BY_HANDLE_AT_A = 0xE14 // 3604 + SYS___INET_ATON_A = 0xE15 // 3605 + SYS_MOUNT1 = 0xE16 // 3606 + SYS___MOUNT1_A = 0xE17 // 3607 + SYS_UMOUNT1 = 0xE18 // 3608 + SYS___UMOUNT1_A = 0xE19 // 3609 + SYS_UMOUNT2 = 0xE1A // 3610 + SYS___UMOUNT2_A = 0xE1B // 3611 + SYS___PRCTL_A = 0xE1C // 3612 + SYS_LOCALTIME_R2 = 0xE1D // 3613 + SYS___LOCALTIME_R2_A = 0xE1E // 3614 + SYS_OPENAT2 = 0xE1F // 3615 + SYS___OPENAT2_A = 0xE20 // 3616 + SYS___LE_CEEMICT = 0xE21 // 3617 + SYS_GETENTROPY = 0xE22 // 3618 + SYS_NANOSLEEP = 0xE23 // 3619 + SYS_UTIMENSAT = 0xE24 // 3620 + SYS___UTIMENSAT_A = 0xE25 // 3621 + SYS_ASPRINTF = 0xE26 // 3622 + SYS___ASPRINTF_A = 0xE27 // 3623 + SYS_VASPRINTF = 0xE28 // 3624 + SYS___VASPRINTF_A = 0xE29 // 3625 + SYS_DPRINTF = 0xE2A // 3626 + SYS___DPRINTF_A = 0xE2B // 3627 + SYS_GETOPT_LONG = 0xE2C // 3628 + SYS___GETOPT_LONG_A = 0xE2D // 3629 + SYS_PSIGNAL = 0xE2E // 3630 + SYS___PSIGNAL_A = 0xE2F // 3631 + SYS_PSIGNAL_UNLOCKED = 0xE30 // 3632 + SYS___PSIGNAL_UNLOCKED_A = 0xE31 // 3633 + SYS_FSTATAT_O = 0xE32 // 3634 + SYS___FSTATAT_O_A = 0xE33 // 3635 + SYS_FSTATAT64 = 0xE34 // 3636 + SYS___FSTATAT64_A = 0xE35 // 3637 + SYS___CHATTRAT = 0xE36 // 3638 + SYS_____CHATTRAT_A = 0xE37 // 3639 + SYS___CHATTRAT64 = 0xE38 // 3640 + SYS_____CHATTRAT64_A = 0xE39 // 3641 + SYS_MADVISE = 0xE3A // 3642 + SYS___AUTHENTICATE = 0xE3B // 3643 + ) diff --git a/vendor/golang.org/x/sys/unix/ztypes_darwin_amd64.go b/vendor/golang.org/x/sys/unix/ztypes_darwin_amd64.go index 091d107f3..d003c3d43 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_darwin_amd64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_darwin_amd64.go @@ -306,6 +306,19 @@ type XVSockPgen struct { type _Socklen uint32 +type SaeAssocID uint32 + +type SaeConnID uint32 + +type SaEndpoints struct { + Srcif uint32 + Srcaddr *RawSockaddr + Srcaddrlen uint32 + Dstaddr *RawSockaddr + Dstaddrlen uint32 + _ [4]byte +} + type Xucred struct { Version uint32 Uid uint32 diff --git a/vendor/golang.org/x/sys/unix/ztypes_darwin_arm64.go b/vendor/golang.org/x/sys/unix/ztypes_darwin_arm64.go index 28ff4ef74..0d45a941a 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_darwin_arm64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_darwin_arm64.go @@ -306,6 +306,19 @@ type XVSockPgen struct { type _Socklen uint32 +type SaeAssocID uint32 + +type SaeConnID uint32 + +type SaEndpoints struct { + Srcif uint32 + Srcaddr *RawSockaddr + Srcaddrlen uint32 + Dstaddr *RawSockaddr + Dstaddrlen uint32 + _ [4]byte +} + type Xucred struct { Version uint32 Uid uint32 diff --git a/vendor/golang.org/x/sys/unix/ztypes_freebsd_386.go b/vendor/golang.org/x/sys/unix/ztypes_freebsd_386.go index 6cbd094a3..51e13eb05 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_freebsd_386.go +++ b/vendor/golang.org/x/sys/unix/ztypes_freebsd_386.go @@ -625,6 +625,7 @@ const ( POLLRDNORM = 0x40 POLLWRBAND = 0x100 POLLWRNORM = 0x4 + POLLRDHUP = 0x4000 ) type CapRights struct { diff --git a/vendor/golang.org/x/sys/unix/ztypes_freebsd_amd64.go b/vendor/golang.org/x/sys/unix/ztypes_freebsd_amd64.go index 7c03b6ee7..d002d8ef3 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_freebsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_freebsd_amd64.go @@ -630,6 +630,7 @@ const ( POLLRDNORM = 0x40 POLLWRBAND = 0x100 POLLWRNORM = 0x4 + POLLRDHUP = 0x4000 ) type CapRights struct { diff --git a/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm.go b/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm.go index 422107ee8..3f863d898 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm.go +++ b/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm.go @@ -616,6 +616,7 @@ const ( POLLRDNORM = 0x40 POLLWRBAND = 0x100 POLLWRNORM = 0x4 + POLLRDHUP = 0x4000 ) type CapRights struct { diff --git a/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm64.go b/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm64.go index 505a12acf..61c729310 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm64.go @@ -610,6 +610,7 @@ const ( POLLRDNORM = 0x40 POLLWRBAND = 0x100 POLLWRNORM = 0x4 + POLLRDHUP = 0x4000 ) type CapRights struct { diff --git a/vendor/golang.org/x/sys/unix/ztypes_freebsd_riscv64.go b/vendor/golang.org/x/sys/unix/ztypes_freebsd_riscv64.go index cc986c790..b5d17414f 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_freebsd_riscv64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_freebsd_riscv64.go @@ -612,6 +612,7 @@ const ( POLLRDNORM = 0x40 POLLWRBAND = 0x100 POLLWRNORM = 0x4 + POLLRDHUP = 0x4000 ) type CapRights struct { diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux.go b/vendor/golang.org/x/sys/unix/ztypes_linux.go index eff6bcdef..8daaf3faf 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux.go @@ -87,30 +87,35 @@ type StatxTimestamp struct { } type Statx_t struct { - Mask uint32 - Blksize uint32 - Attributes uint64 - Nlink uint32 - Uid uint32 - Gid uint32 - Mode uint16 - _ [1]uint16 - Ino uint64 - Size uint64 - Blocks uint64 - Attributes_mask uint64 - Atime StatxTimestamp - Btime StatxTimestamp - Ctime StatxTimestamp - Mtime StatxTimestamp - Rdev_major uint32 - Rdev_minor uint32 - Dev_major uint32 - Dev_minor uint32 - Mnt_id uint64 - Dio_mem_align uint32 - Dio_offset_align uint32 - _ [12]uint64 + Mask uint32 + Blksize uint32 + Attributes uint64 + Nlink uint32 + Uid uint32 + Gid uint32 + Mode uint16 + _ [1]uint16 + Ino uint64 + Size uint64 + Blocks uint64 + Attributes_mask uint64 + Atime StatxTimestamp + Btime StatxTimestamp + Ctime StatxTimestamp + Mtime StatxTimestamp + Rdev_major uint32 + Rdev_minor uint32 + Dev_major uint32 + Dev_minor uint32 + Mnt_id uint64 + Dio_mem_align uint32 + Dio_offset_align uint32 + Subvol uint64 + Atomic_write_unit_min uint32 + Atomic_write_unit_max uint32 + Atomic_write_segments_max uint32 + _ [1]uint32 + _ [9]uint64 } type Fsid struct { @@ -515,6 +520,29 @@ type TCPInfo struct { Total_rto_time uint32 } +type TCPVegasInfo struct { + Enabled uint32 + Rttcnt uint32 + Rtt uint32 + Minrtt uint32 +} + +type TCPDCTCPInfo struct { + Enabled uint16 + Ce_state uint16 + Alpha uint32 + Ab_ecn uint32 + Ab_tot uint32 +} + +type TCPBBRInfo struct { + Bw_lo uint32 + Bw_hi uint32 + Min_rtt uint32 + Pacing_gain uint32 + Cwnd_gain uint32 +} + type CanFilter struct { Id uint32 Mask uint32 @@ -556,6 +584,7 @@ const ( SizeofICMPv6Filter = 0x20 SizeofUcred = 0xc SizeofTCPInfo = 0xf8 + SizeofTCPCCInfo = 0x14 SizeofCanFilter = 0x8 SizeofTCPRepairOpt = 0x8 ) @@ -1178,7 +1207,8 @@ const ( PERF_SAMPLE_BRANCH_TYPE_SAVE_SHIFT = 0x10 PERF_SAMPLE_BRANCH_HW_INDEX_SHIFT = 0x11 PERF_SAMPLE_BRANCH_PRIV_SAVE_SHIFT = 0x12 - PERF_SAMPLE_BRANCH_MAX_SHIFT = 0x13 + PERF_SAMPLE_BRANCH_COUNTERS = 0x80000 + PERF_SAMPLE_BRANCH_MAX_SHIFT = 0x14 PERF_SAMPLE_BRANCH_USER = 0x1 PERF_SAMPLE_BRANCH_KERNEL = 0x2 PERF_SAMPLE_BRANCH_HV = 0x4 @@ -1198,7 +1228,7 @@ const ( PERF_SAMPLE_BRANCH_TYPE_SAVE = 0x10000 PERF_SAMPLE_BRANCH_HW_INDEX = 0x20000 PERF_SAMPLE_BRANCH_PRIV_SAVE = 0x40000 - PERF_SAMPLE_BRANCH_MAX = 0x80000 + PERF_SAMPLE_BRANCH_MAX = 0x100000 PERF_BR_UNKNOWN = 0x0 PERF_BR_COND = 0x1 PERF_BR_UNCOND = 0x2 @@ -1722,12 +1752,6 @@ const ( IFLA_IPVLAN_UNSPEC = 0x0 IFLA_IPVLAN_MODE = 0x1 IFLA_IPVLAN_FLAGS = 0x2 - NETKIT_NEXT = -0x1 - NETKIT_PASS = 0x0 - NETKIT_DROP = 0x2 - NETKIT_REDIRECT = 0x7 - NETKIT_L2 = 0x0 - NETKIT_L3 = 0x1 IFLA_NETKIT_UNSPEC = 0x0 IFLA_NETKIT_PEER_INFO = 0x1 IFLA_NETKIT_PRIMARY = 0x2 @@ -1766,6 +1790,7 @@ const ( IFLA_VXLAN_DF = 0x1d IFLA_VXLAN_VNIFILTER = 0x1e IFLA_VXLAN_LOCALBYPASS = 0x1f + IFLA_VXLAN_LABEL_POLICY = 0x20 IFLA_GENEVE_UNSPEC = 0x0 IFLA_GENEVE_ID = 0x1 IFLA_GENEVE_REMOTE = 0x2 @@ -1795,6 +1820,8 @@ const ( IFLA_GTP_ROLE = 0x4 IFLA_GTP_CREATE_SOCKETS = 0x5 IFLA_GTP_RESTART_COUNT = 0x6 + IFLA_GTP_LOCAL = 0x7 + IFLA_GTP_LOCAL6 = 0x8 IFLA_BOND_UNSPEC = 0x0 IFLA_BOND_MODE = 0x1 IFLA_BOND_ACTIVE_SLAVE = 0x2 @@ -1827,6 +1854,7 @@ const ( IFLA_BOND_AD_LACP_ACTIVE = 0x1d IFLA_BOND_MISSED_MAX = 0x1e IFLA_BOND_NS_IP6_TARGET = 0x1f + IFLA_BOND_COUPLED_CONTROL = 0x20 IFLA_BOND_AD_INFO_UNSPEC = 0x0 IFLA_BOND_AD_INFO_AGGREGATOR = 0x1 IFLA_BOND_AD_INFO_NUM_PORTS = 0x2 @@ -1895,6 +1923,7 @@ const ( IFLA_HSR_SEQ_NR = 0x5 IFLA_HSR_VERSION = 0x6 IFLA_HSR_PROTOCOL = 0x7 + IFLA_HSR_INTERLINK = 0x8 IFLA_STATS_UNSPEC = 0x0 IFLA_STATS_LINK_64 = 0x1 IFLA_STATS_LINK_XSTATS = 0x2 @@ -1947,6 +1976,15 @@ const ( IFLA_DSA_MASTER = 0x1 ) +const ( + NETKIT_NEXT = -0x1 + NETKIT_PASS = 0x0 + NETKIT_DROP = 0x2 + NETKIT_REDIRECT = 0x7 + NETKIT_L2 = 0x0 + NETKIT_L3 = 0x1 +) + const ( NF_INET_PRE_ROUTING = 0x0 NF_INET_LOCAL_IN = 0x1 @@ -2481,6 +2519,15 @@ type XDPMmapOffsets struct { Cr XDPRingOffset } +type XDPUmemReg struct { + Addr uint64 + Len uint64 + Size uint32 + Headroom uint32 + Flags uint32 + Tx_metadata_len uint32 +} + type XDPStatistics struct { Rx_dropped uint64 Rx_invalid_descs uint64 @@ -2935,7 +2982,7 @@ const ( BPF_TCP_LISTEN = 0xa BPF_TCP_CLOSING = 0xb BPF_TCP_NEW_SYN_RECV = 0xc - BPF_TCP_MAX_STATES = 0xd + BPF_TCP_MAX_STATES = 0xe TCP_BPF_IW = 0x3e9 TCP_BPF_SNDCWND_CLAMP = 0x3ea TCP_BPF_DELACK_MAX = 0x3eb @@ -3211,7 +3258,7 @@ const ( DEVLINK_CMD_LINECARD_NEW = 0x50 DEVLINK_CMD_LINECARD_DEL = 0x51 DEVLINK_CMD_SELFTESTS_GET = 0x52 - DEVLINK_CMD_MAX = 0x53 + DEVLINK_CMD_MAX = 0x54 DEVLINK_PORT_TYPE_NOTSET = 0x0 DEVLINK_PORT_TYPE_AUTO = 0x1 DEVLINK_PORT_TYPE_ETH = 0x2 @@ -3463,7 +3510,7 @@ const ( DEVLINK_PORT_FN_ATTR_STATE = 0x2 DEVLINK_PORT_FN_ATTR_OPSTATE = 0x3 DEVLINK_PORT_FN_ATTR_CAPS = 0x4 - DEVLINK_PORT_FUNCTION_ATTR_MAX = 0x5 + DEVLINK_PORT_FUNCTION_ATTR_MAX = 0x6 ) type FsverityDigest struct { @@ -3755,7 +3802,7 @@ const ( ETHTOOL_MSG_PSE_GET = 0x24 ETHTOOL_MSG_PSE_SET = 0x25 ETHTOOL_MSG_RSS_GET = 0x26 - ETHTOOL_MSG_USER_MAX = 0x2b + ETHTOOL_MSG_USER_MAX = 0x2c ETHTOOL_MSG_KERNEL_NONE = 0x0 ETHTOOL_MSG_STRSET_GET_REPLY = 0x1 ETHTOOL_MSG_LINKINFO_GET_REPLY = 0x2 @@ -3795,7 +3842,10 @@ const ( ETHTOOL_MSG_MODULE_NTF = 0x24 ETHTOOL_MSG_PSE_GET_REPLY = 0x25 ETHTOOL_MSG_RSS_GET_REPLY = 0x26 - ETHTOOL_MSG_KERNEL_MAX = 0x2b + ETHTOOL_MSG_KERNEL_MAX = 0x2c + ETHTOOL_FLAG_COMPACT_BITSETS = 0x1 + ETHTOOL_FLAG_OMIT_REPLY = 0x2 + ETHTOOL_FLAG_STATS = 0x4 ETHTOOL_A_HEADER_UNSPEC = 0x0 ETHTOOL_A_HEADER_DEV_INDEX = 0x1 ETHTOOL_A_HEADER_DEV_NAME = 0x2 @@ -3937,7 +3987,7 @@ const ( ETHTOOL_A_COALESCE_RATE_SAMPLE_INTERVAL = 0x17 ETHTOOL_A_COALESCE_USE_CQE_MODE_TX = 0x18 ETHTOOL_A_COALESCE_USE_CQE_MODE_RX = 0x19 - ETHTOOL_A_COALESCE_MAX = 0x1c + ETHTOOL_A_COALESCE_MAX = 0x1e ETHTOOL_A_PAUSE_UNSPEC = 0x0 ETHTOOL_A_PAUSE_HEADER = 0x1 ETHTOOL_A_PAUSE_AUTONEG = 0x2 @@ -3965,7 +4015,7 @@ const ( ETHTOOL_A_TSINFO_TX_TYPES = 0x3 ETHTOOL_A_TSINFO_RX_FILTERS = 0x4 ETHTOOL_A_TSINFO_PHC_INDEX = 0x5 - ETHTOOL_A_TSINFO_MAX = 0x5 + ETHTOOL_A_TSINFO_MAX = 0x6 ETHTOOL_A_CABLE_TEST_UNSPEC = 0x0 ETHTOOL_A_CABLE_TEST_HEADER = 0x1 ETHTOOL_A_CABLE_TEST_MAX = 0x1 @@ -4068,6 +4118,106 @@ type EthtoolDrvinfo struct { Regdump_len uint32 } +type EthtoolTsInfo struct { + Cmd uint32 + So_timestamping uint32 + Phc_index int32 + Tx_types uint32 + Tx_reserved [3]uint32 + Rx_filters uint32 + Rx_reserved [3]uint32 +} + +type HwTstampConfig struct { + Flags int32 + Tx_type int32 + Rx_filter int32 +} + +const ( + HWTSTAMP_FILTER_NONE = 0x0 + HWTSTAMP_FILTER_ALL = 0x1 + HWTSTAMP_FILTER_SOME = 0x2 + HWTSTAMP_FILTER_PTP_V1_L4_EVENT = 0x3 + HWTSTAMP_FILTER_PTP_V2_L4_EVENT = 0x6 + HWTSTAMP_FILTER_PTP_V2_L2_EVENT = 0x9 + HWTSTAMP_FILTER_PTP_V2_EVENT = 0xc +) + +const ( + HWTSTAMP_TX_OFF = 0x0 + HWTSTAMP_TX_ON = 0x1 + HWTSTAMP_TX_ONESTEP_SYNC = 0x2 +) + +type ( + PtpClockCaps struct { + Max_adj int32 + N_alarm int32 + N_ext_ts int32 + N_per_out int32 + Pps int32 + N_pins int32 + Cross_timestamping int32 + Adjust_phase int32 + Max_phase_adj int32 + Rsv [11]int32 + } + PtpClockTime struct { + Sec int64 + Nsec uint32 + Reserved uint32 + } + PtpExttsEvent struct { + T PtpClockTime + Index uint32 + Flags uint32 + Rsv [2]uint32 + } + PtpExttsRequest struct { + Index uint32 + Flags uint32 + Rsv [2]uint32 + } + PtpPeroutRequest struct { + StartOrPhase PtpClockTime + Period PtpClockTime + Index uint32 + Flags uint32 + On PtpClockTime + } + PtpPinDesc struct { + Name [64]byte + Index uint32 + Func uint32 + Chan uint32 + Rsv [5]uint32 + } + PtpSysOffset struct { + Samples uint32 + Rsv [3]uint32 + Ts [51]PtpClockTime + } + PtpSysOffsetExtended struct { + Samples uint32 + Rsv [3]uint32 + Ts [25][3]PtpClockTime + } + PtpSysOffsetPrecise struct { + Device PtpClockTime + Realtime PtpClockTime + Monoraw PtpClockTime + Rsv [4]uint32 + } +) + +const ( + PTP_PF_NONE = 0x0 + PTP_PF_EXTTS = 0x1 + PTP_PF_PEROUT = 0x2 + PTP_PF_PHYSYNC = 0x3 +) + type ( HIDRawReportDescriptor struct { Size uint32 @@ -4595,7 +4745,7 @@ const ( NL80211_ATTR_MAC_HINT = 0xc8 NL80211_ATTR_MAC_MASK = 0xd7 NL80211_ATTR_MAX_AP_ASSOC_STA = 0xca - NL80211_ATTR_MAX = 0x146 + NL80211_ATTR_MAX = 0x14c NL80211_ATTR_MAX_CRIT_PROT_DURATION = 0xb4 NL80211_ATTR_MAX_CSA_COUNTERS = 0xce NL80211_ATTR_MAX_MATCH_SETS = 0x85 @@ -4861,7 +5011,7 @@ const ( NL80211_BSS_FREQUENCY_OFFSET = 0x14 NL80211_BSS_INFORMATION_ELEMENTS = 0x6 NL80211_BSS_LAST_SEEN_BOOTTIME = 0xf - NL80211_BSS_MAX = 0x16 + NL80211_BSS_MAX = 0x18 NL80211_BSS_MLD_ADDR = 0x16 NL80211_BSS_MLO_LINK_ID = 0x15 NL80211_BSS_PAD = 0x10 @@ -4965,7 +5115,7 @@ const ( NL80211_CMD_LEAVE_IBSS = 0x2c NL80211_CMD_LEAVE_MESH = 0x45 NL80211_CMD_LEAVE_OCB = 0x6d - NL80211_CMD_MAX = 0x9a + NL80211_CMD_MAX = 0x9b NL80211_CMD_MICHAEL_MIC_FAILURE = 0x29 NL80211_CMD_MODIFY_LINK_STA = 0x97 NL80211_CMD_NAN_MATCH = 0x78 @@ -5199,7 +5349,7 @@ const ( NL80211_FREQUENCY_ATTR_GO_CONCURRENT = 0xf NL80211_FREQUENCY_ATTR_INDOOR_ONLY = 0xe NL80211_FREQUENCY_ATTR_IR_CONCURRENT = 0xf - NL80211_FREQUENCY_ATTR_MAX = 0x1c + NL80211_FREQUENCY_ATTR_MAX = 0x21 NL80211_FREQUENCY_ATTR_MAX_TX_POWER = 0x6 NL80211_FREQUENCY_ATTR_NO_10MHZ = 0x11 NL80211_FREQUENCY_ATTR_NO_160MHZ = 0xc @@ -5693,7 +5843,7 @@ const ( NL80211_STA_FLAG_ASSOCIATED = 0x7 NL80211_STA_FLAG_AUTHENTICATED = 0x5 NL80211_STA_FLAG_AUTHORIZED = 0x1 - NL80211_STA_FLAG_MAX = 0x7 + NL80211_STA_FLAG_MAX = 0x8 NL80211_STA_FLAG_MAX_OLD_API = 0x6 NL80211_STA_FLAG_MFP = 0x4 NL80211_STA_FLAG_SHORT_PREAMBLE = 0x2 @@ -5991,3 +6141,34 @@ type CachestatRange struct { Off uint64 Len uint64 } + +const ( + SK_MEMINFO_RMEM_ALLOC = 0x0 + SK_MEMINFO_RCVBUF = 0x1 + SK_MEMINFO_WMEM_ALLOC = 0x2 + SK_MEMINFO_SNDBUF = 0x3 + SK_MEMINFO_FWD_ALLOC = 0x4 + SK_MEMINFO_WMEM_QUEUED = 0x5 + SK_MEMINFO_OPTMEM = 0x6 + SK_MEMINFO_BACKLOG = 0x7 + SK_MEMINFO_DROPS = 0x8 + SK_MEMINFO_VARS = 0x9 + SKNLGRP_NONE = 0x0 + SKNLGRP_INET_TCP_DESTROY = 0x1 + SKNLGRP_INET_UDP_DESTROY = 0x2 + SKNLGRP_INET6_TCP_DESTROY = 0x3 + SKNLGRP_INET6_UDP_DESTROY = 0x4 + SK_DIAG_BPF_STORAGE_REQ_NONE = 0x0 + SK_DIAG_BPF_STORAGE_REQ_MAP_FD = 0x1 + SK_DIAG_BPF_STORAGE_REP_NONE = 0x0 + SK_DIAG_BPF_STORAGE = 0x1 + SK_DIAG_BPF_STORAGE_NONE = 0x0 + SK_DIAG_BPF_STORAGE_PAD = 0x1 + SK_DIAG_BPF_STORAGE_MAP_ID = 0x2 + SK_DIAG_BPF_STORAGE_MAP_VALUE = 0x3 +) + +type SockDiagReq struct { + Family uint8 + Protocol uint8 +} diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_386.go b/vendor/golang.org/x/sys/unix/ztypes_linux_386.go index 438a30aff..fd402da43 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_386.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_386.go @@ -477,14 +477,6 @@ const ( BLKPG = 0x1269 ) -type XDPUmemReg struct { - Addr uint64 - Len uint64 - Size uint32 - Headroom uint32 - Flags uint32 -} - type CryptoUserAlg struct { Name [64]int8 Driver_name [64]int8 diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go index adceca355..eb7a5e186 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go @@ -492,15 +492,6 @@ const ( BLKPG = 0x1269 ) -type XDPUmemReg struct { - Addr uint64 - Len uint64 - Size uint32 - Headroom uint32 - Flags uint32 - _ [4]byte -} - type CryptoUserAlg struct { Name [64]int8 Driver_name [64]int8 diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go b/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go index eeaa00a37..d78ac108b 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go @@ -470,15 +470,6 @@ const ( BLKPG = 0x1269 ) -type XDPUmemReg struct { - Addr uint64 - Len uint64 - Size uint32 - Headroom uint32 - Flags uint32 - _ [4]byte -} - type CryptoUserAlg struct { Name [64]uint8 Driver_name [64]uint8 diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go index 6739aa91d..cd06d47f1 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go @@ -471,15 +471,6 @@ const ( BLKPG = 0x1269 ) -type XDPUmemReg struct { - Addr uint64 - Len uint64 - Size uint32 - Headroom uint32 - Flags uint32 - _ [4]byte -} - type CryptoUserAlg struct { Name [64]int8 Driver_name [64]int8 diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_loong64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_loong64.go index 9920ef631..2f28fe26c 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_loong64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_loong64.go @@ -472,15 +472,6 @@ const ( BLKPG = 0x1269 ) -type XDPUmemReg struct { - Addr uint64 - Len uint64 - Size uint32 - Headroom uint32 - Flags uint32 - _ [4]byte -} - type CryptoUserAlg struct { Name [64]int8 Driver_name [64]int8 diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go b/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go index 2923b799a..71d6cac2f 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go @@ -476,15 +476,6 @@ const ( BLKPG = 0x20001269 ) -type XDPUmemReg struct { - Addr uint64 - Len uint64 - Size uint32 - Headroom uint32 - Flags uint32 - _ [4]byte -} - type CryptoUserAlg struct { Name [64]int8 Driver_name [64]int8 diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go index ce2750ee4..8596d4535 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go @@ -474,15 +474,6 @@ const ( BLKPG = 0x20001269 ) -type XDPUmemReg struct { - Addr uint64 - Len uint64 - Size uint32 - Headroom uint32 - Flags uint32 - _ [4]byte -} - type CryptoUserAlg struct { Name [64]int8 Driver_name [64]int8 diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go b/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go index 3038811d7..cd60ea186 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go @@ -474,15 +474,6 @@ const ( BLKPG = 0x20001269 ) -type XDPUmemReg struct { - Addr uint64 - Len uint64 - Size uint32 - Headroom uint32 - Flags uint32 - _ [4]byte -} - type CryptoUserAlg struct { Name [64]int8 Driver_name [64]int8 diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go b/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go index efc6fed18..b0ae420c4 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go @@ -476,15 +476,6 @@ const ( BLKPG = 0x20001269 ) -type XDPUmemReg struct { - Addr uint64 - Len uint64 - Size uint32 - Headroom uint32 - Flags uint32 - _ [4]byte -} - type CryptoUserAlg struct { Name [64]int8 Driver_name [64]int8 diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go index 9a654b75a..835972875 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go @@ -482,15 +482,6 @@ const ( BLKPG = 0x20001269 ) -type XDPUmemReg struct { - Addr uint64 - Len uint64 - Size uint32 - Headroom uint32 - Flags uint32 - _ [4]byte -} - type CryptoUserAlg struct { Name [64]uint8 Driver_name [64]uint8 diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go index 40d358e33..69eb6a5c6 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go @@ -481,15 +481,6 @@ const ( BLKPG = 0x20001269 ) -type XDPUmemReg struct { - Addr uint64 - Len uint64 - Size uint32 - Headroom uint32 - Flags uint32 - _ [4]byte -} - type CryptoUserAlg struct { Name [64]uint8 Driver_name [64]uint8 diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go index 148c6ceb8..5f583cb62 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go @@ -481,15 +481,6 @@ const ( BLKPG = 0x20001269 ) -type XDPUmemReg struct { - Addr uint64 - Len uint64 - Size uint32 - Headroom uint32 - Flags uint32 - _ [4]byte -} - type CryptoUserAlg struct { Name [64]uint8 Driver_name [64]uint8 diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go index 72ba81543..ad05b51a6 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go @@ -499,15 +499,6 @@ const ( BLKPG = 0x1269 ) -type XDPUmemReg struct { - Addr uint64 - Len uint64 - Size uint32 - Headroom uint32 - Flags uint32 - _ [4]byte -} - type CryptoUserAlg struct { Name [64]uint8 Driver_name [64]uint8 @@ -736,6 +727,37 @@ const ( RISCV_HWPROBE_EXT_ZBA = 0x8 RISCV_HWPROBE_EXT_ZBB = 0x10 RISCV_HWPROBE_EXT_ZBS = 0x20 + RISCV_HWPROBE_EXT_ZICBOZ = 0x40 + RISCV_HWPROBE_EXT_ZBC = 0x80 + RISCV_HWPROBE_EXT_ZBKB = 0x100 + RISCV_HWPROBE_EXT_ZBKC = 0x200 + RISCV_HWPROBE_EXT_ZBKX = 0x400 + RISCV_HWPROBE_EXT_ZKND = 0x800 + RISCV_HWPROBE_EXT_ZKNE = 0x1000 + RISCV_HWPROBE_EXT_ZKNH = 0x2000 + RISCV_HWPROBE_EXT_ZKSED = 0x4000 + RISCV_HWPROBE_EXT_ZKSH = 0x8000 + RISCV_HWPROBE_EXT_ZKT = 0x10000 + RISCV_HWPROBE_EXT_ZVBB = 0x20000 + RISCV_HWPROBE_EXT_ZVBC = 0x40000 + RISCV_HWPROBE_EXT_ZVKB = 0x80000 + RISCV_HWPROBE_EXT_ZVKG = 0x100000 + RISCV_HWPROBE_EXT_ZVKNED = 0x200000 + RISCV_HWPROBE_EXT_ZVKNHA = 0x400000 + RISCV_HWPROBE_EXT_ZVKNHB = 0x800000 + RISCV_HWPROBE_EXT_ZVKSED = 0x1000000 + RISCV_HWPROBE_EXT_ZVKSH = 0x2000000 + RISCV_HWPROBE_EXT_ZVKT = 0x4000000 + RISCV_HWPROBE_EXT_ZFH = 0x8000000 + RISCV_HWPROBE_EXT_ZFHMIN = 0x10000000 + RISCV_HWPROBE_EXT_ZIHINTNTL = 0x20000000 + RISCV_HWPROBE_EXT_ZVFH = 0x40000000 + RISCV_HWPROBE_EXT_ZVFHMIN = 0x80000000 + RISCV_HWPROBE_EXT_ZFA = 0x100000000 + RISCV_HWPROBE_EXT_ZTSO = 0x200000000 + RISCV_HWPROBE_EXT_ZACAS = 0x400000000 + RISCV_HWPROBE_EXT_ZICOND = 0x800000000 + RISCV_HWPROBE_EXT_ZIHINTPAUSE = 0x1000000000 RISCV_HWPROBE_KEY_CPUPERF_0 = 0x5 RISCV_HWPROBE_MISALIGNED_UNKNOWN = 0x0 RISCV_HWPROBE_MISALIGNED_EMULATED = 0x1 @@ -743,4 +765,6 @@ const ( RISCV_HWPROBE_MISALIGNED_FAST = 0x3 RISCV_HWPROBE_MISALIGNED_UNSUPPORTED = 0x4 RISCV_HWPROBE_MISALIGNED_MASK = 0x7 + RISCV_HWPROBE_KEY_ZICBOZ_BLOCK_SIZE = 0x6 + RISCV_HWPROBE_WHICH_CPUS = 0x1 ) diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go b/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go index 71e765508..cf3ce9003 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go @@ -495,15 +495,6 @@ const ( BLKPG = 0x1269 ) -type XDPUmemReg struct { - Addr uint64 - Len uint64 - Size uint32 - Headroom uint32 - Flags uint32 - _ [4]byte -} - type CryptoUserAlg struct { Name [64]int8 Driver_name [64]int8 diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go index 4abbdb9de..590b56739 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go @@ -476,15 +476,6 @@ const ( BLKPG = 0x20001269 ) -type XDPUmemReg struct { - Addr uint64 - Len uint64 - Size uint32 - Headroom uint32 - Flags uint32 - _ [4]byte -} - type CryptoUserAlg struct { Name [64]int8 Driver_name [64]int8 diff --git a/vendor/golang.org/x/sys/unix/ztypes_zos_s390x.go b/vendor/golang.org/x/sys/unix/ztypes_zos_s390x.go index 54f31be63..2e5d5a443 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_zos_s390x.go +++ b/vendor/golang.org/x/sys/unix/ztypes_zos_s390x.go @@ -25,10 +25,13 @@ const ( SizeofIPv6Mreq = 20 SizeofICMPv6Filter = 32 SizeofIPv6MTUInfo = 32 + SizeofInet4Pktinfo = 8 + SizeofInet6Pktinfo = 20 SizeofLinger = 8 SizeofSockaddrInet4 = 16 SizeofSockaddrInet6 = 28 SizeofTCPInfo = 0x68 + SizeofUcred = 12 ) type ( @@ -69,12 +72,17 @@ type Utimbuf struct { } type Utsname struct { - Sysname [65]byte - Nodename [65]byte - Release [65]byte - Version [65]byte - Machine [65]byte - Domainname [65]byte + Sysname [16]byte + Nodename [32]byte + Release [8]byte + Version [8]byte + Machine [16]byte +} + +type Ucred struct { + Pid int32 + Uid uint32 + Gid uint32 } type RawSockaddrInet4 struct { @@ -325,7 +333,7 @@ type Statvfs_t struct { } type Statfs_t struct { - Type uint32 + Type uint64 Bsize uint64 Blocks uint64 Bfree uint64 @@ -336,6 +344,7 @@ type Statfs_t struct { Namelen uint64 Frsize uint64 Flags uint64 + _ [4]uint64 } type direntLE struct { @@ -368,6 +377,12 @@ type Flock_t struct { Pid int32 } +type F_cnvrt struct { + Cvtcmd int32 + Pccsid int16 + Fccsid int16 +} + type Termios struct { Cflag uint32 Iflag uint32 @@ -412,3 +427,126 @@ type W_Mntent struct { Quiesceowner [8]byte _ [38]byte } + +type EpollEvent struct { + Events uint32 + _ int32 + Fd int32 + Pad int32 +} + +type InotifyEvent struct { + Wd int32 + Mask uint32 + Cookie uint32 + Len uint32 + Name string +} + +const ( + SizeofInotifyEvent = 0x10 +) + +type ConsMsg2 struct { + Cm2Format uint16 + Cm2R1 uint16 + Cm2Msglength uint32 + Cm2Msg *byte + Cm2R2 [4]byte + Cm2R3 [4]byte + Cm2Routcde *uint32 + Cm2Descr *uint32 + Cm2Msgflag uint32 + Cm2Token uint32 + Cm2Msgid *uint32 + Cm2R4 [4]byte + Cm2DomToken uint32 + Cm2DomMsgid *uint32 + Cm2ModCartptr *byte + Cm2ModConsidptr *byte + Cm2MsgCart [8]byte + Cm2MsgConsid [4]byte + Cm2R5 [12]byte +} + +const ( + CC_modify = 1 + CC_stop = 2 + CONSOLE_FORMAT_2 = 2 + CONSOLE_FORMAT_3 = 3 + CONSOLE_HRDCPY = 0x80000000 +) + +type OpenHow struct { + Flags uint64 + Mode uint64 + Resolve uint64 +} + +const SizeofOpenHow = 0x18 + +const ( + RESOLVE_CACHED = 0x20 + RESOLVE_BENEATH = 0x8 + RESOLVE_IN_ROOT = 0x10 + RESOLVE_NO_MAGICLINKS = 0x2 + RESOLVE_NO_SYMLINKS = 0x4 + RESOLVE_NO_XDEV = 0x1 +) + +type Siginfo struct { + Signo int32 + Errno int32 + Code int32 + Pid int32 + Uid uint32 + _ [44]byte +} + +type SysvIpcPerm struct { + Uid uint32 + Gid uint32 + Cuid uint32 + Cgid uint32 + Mode int32 +} + +type SysvShmDesc struct { + Perm SysvIpcPerm + _ [4]byte + Lpid int32 + Cpid int32 + Nattch uint32 + _ [4]byte + _ [4]byte + _ [4]byte + _ int32 + _ uint8 + _ uint8 + _ uint16 + _ *byte + Segsz uint64 + Atime Time_t + Dtime Time_t + Ctime Time_t +} + +type SysvShmDesc64 struct { + Perm SysvIpcPerm + _ [4]byte + Lpid int32 + Cpid int32 + Nattch uint32 + _ [4]byte + _ [4]byte + _ [4]byte + _ int32 + _ byte + _ uint8 + _ uint16 + _ *byte + Segsz uint64 + Atime int64 + Dtime int64 + Ctime int64 +} diff --git a/vendor/golang.org/x/sys/windows/aliases.go b/vendor/golang.org/x/sys/windows/aliases.go index ce2d713d6..16f90560a 100644 --- a/vendor/golang.org/x/sys/windows/aliases.go +++ b/vendor/golang.org/x/sys/windows/aliases.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build windows && go1.9 +//go:build windows package windows diff --git a/vendor/golang.org/x/sys/windows/dll_windows.go b/vendor/golang.org/x/sys/windows/dll_windows.go index 115341fba..4e613cf63 100644 --- a/vendor/golang.org/x/sys/windows/dll_windows.go +++ b/vendor/golang.org/x/sys/windows/dll_windows.go @@ -65,7 +65,7 @@ func LoadDLL(name string) (dll *DLL, err error) { return d, nil } -// MustLoadDLL is like LoadDLL but panics if load operation failes. +// MustLoadDLL is like LoadDLL but panics if load operation fails. func MustLoadDLL(name string) *DLL { d, e := LoadDLL(name) if e != nil { diff --git a/vendor/golang.org/x/sys/windows/empty.s b/vendor/golang.org/x/sys/windows/empty.s deleted file mode 100644 index ba64caca5..000000000 --- a/vendor/golang.org/x/sys/windows/empty.s +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !go1.12 - -// This file is here to allow bodyless functions with go:linkname for Go 1.11 -// and earlier (see https://golang.org/issue/23311). diff --git a/vendor/golang.org/x/sys/windows/security_windows.go b/vendor/golang.org/x/sys/windows/security_windows.go index 26be94a8a..b6e1ab76f 100644 --- a/vendor/golang.org/x/sys/windows/security_windows.go +++ b/vendor/golang.org/x/sys/windows/security_windows.go @@ -68,6 +68,7 @@ type UserInfo10 struct { //sys NetUserGetInfo(serverName *uint16, userName *uint16, level uint32, buf **byte) (neterr error) = netapi32.NetUserGetInfo //sys NetGetJoinInformation(server *uint16, name **uint16, bufType *uint32) (neterr error) = netapi32.NetGetJoinInformation //sys NetApiBufferFree(buf *byte) (neterr error) = netapi32.NetApiBufferFree +//sys NetUserEnum(serverName *uint16, level uint32, filter uint32, buf **byte, prefMaxLen uint32, entriesRead *uint32, totalEntries *uint32, resumeHandle *uint32) (neterr error) = netapi32.NetUserEnum const ( // do not reorder @@ -893,7 +894,7 @@ type ACL struct { aclRevision byte sbz1 byte aclSize uint16 - aceCount uint16 + AceCount uint16 sbz2 uint16 } @@ -1086,6 +1087,27 @@ type EXPLICIT_ACCESS struct { Trustee TRUSTEE } +// https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-ace_header +type ACE_HEADER struct { + AceType uint8 + AceFlags uint8 + AceSize uint16 +} + +// https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-access_allowed_ace +type ACCESS_ALLOWED_ACE struct { + Header ACE_HEADER + Mask ACCESS_MASK + SidStart uint32 +} + +const ( + // Constants for AceType + // https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-ace_header + ACCESS_ALLOWED_ACE_TYPE = 0 + ACCESS_DENIED_ACE_TYPE = 1 +) + // This type is the union inside of TRUSTEE and must be created using one of the TrusteeValueFrom* functions. type TrusteeValue uintptr @@ -1157,6 +1179,7 @@ type OBJECTS_AND_NAME struct { //sys makeSelfRelativeSD(absoluteSD *SECURITY_DESCRIPTOR, selfRelativeSD *SECURITY_DESCRIPTOR, selfRelativeSDSize *uint32) (err error) = advapi32.MakeSelfRelativeSD //sys setEntriesInAcl(countExplicitEntries uint32, explicitEntries *EXPLICIT_ACCESS, oldACL *ACL, newACL **ACL) (ret error) = advapi32.SetEntriesInAclW +//sys GetAce(acl *ACL, aceIndex uint32, pAce **ACCESS_ALLOWED_ACE) (err error) = advapi32.GetAce // Control returns the security descriptor control bits. func (sd *SECURITY_DESCRIPTOR) Control() (control SECURITY_DESCRIPTOR_CONTROL, revision uint32, err error) { diff --git a/vendor/golang.org/x/sys/windows/syscall_windows.go b/vendor/golang.org/x/sys/windows/syscall_windows.go index 6525c62f3..4510bfc3f 100644 --- a/vendor/golang.org/x/sys/windows/syscall_windows.go +++ b/vendor/golang.org/x/sys/windows/syscall_windows.go @@ -17,8 +17,10 @@ import ( "unsafe" ) -type Handle uintptr -type HWND uintptr +type ( + Handle uintptr + HWND uintptr +) const ( InvalidHandle = ^Handle(0) @@ -211,6 +213,10 @@ func NewCallbackCDecl(fn interface{}) uintptr { //sys OpenProcess(desiredAccess uint32, inheritHandle bool, processId uint32) (handle Handle, err error) //sys ShellExecute(hwnd Handle, verb *uint16, file *uint16, args *uint16, cwd *uint16, showCmd int32) (err error) [failretval<=32] = shell32.ShellExecuteW //sys GetWindowThreadProcessId(hwnd HWND, pid *uint32) (tid uint32, err error) = user32.GetWindowThreadProcessId +//sys LoadKeyboardLayout(name *uint16, flags uint32) (hkl Handle, err error) [failretval==0] = user32.LoadKeyboardLayoutW +//sys UnloadKeyboardLayout(hkl Handle) (err error) = user32.UnloadKeyboardLayout +//sys GetKeyboardLayout(tid uint32) (hkl Handle) = user32.GetKeyboardLayout +//sys ToUnicodeEx(vkey uint32, scancode uint32, keystate *byte, pwszBuff *uint16, cchBuff int32, flags uint32, hkl Handle) (ret int32) = user32.ToUnicodeEx //sys GetShellWindow() (shellWindow HWND) = user32.GetShellWindow //sys MessageBox(hwnd HWND, text *uint16, caption *uint16, boxtype uint32) (ret int32, err error) [failretval==0] = user32.MessageBoxW //sys ExitWindowsEx(flags uint32, reason uint32) (err error) = user32.ExitWindowsEx @@ -307,6 +313,10 @@ func NewCallbackCDecl(fn interface{}) uintptr { //sys SetConsoleMode(console Handle, mode uint32) (err error) = kernel32.SetConsoleMode //sys GetConsoleScreenBufferInfo(console Handle, info *ConsoleScreenBufferInfo) (err error) = kernel32.GetConsoleScreenBufferInfo //sys setConsoleCursorPosition(console Handle, position uint32) (err error) = kernel32.SetConsoleCursorPosition +//sys GetConsoleCP() (cp uint32, err error) = kernel32.GetConsoleCP +//sys GetConsoleOutputCP() (cp uint32, err error) = kernel32.GetConsoleOutputCP +//sys SetConsoleCP(cp uint32) (err error) = kernel32.SetConsoleCP +//sys SetConsoleOutputCP(cp uint32) (err error) = kernel32.SetConsoleOutputCP //sys WriteConsole(console Handle, buf *uint16, towrite uint32, written *uint32, reserved *byte) (err error) = kernel32.WriteConsoleW //sys ReadConsole(console Handle, buf *uint16, toread uint32, read *uint32, inputControl *byte) (err error) = kernel32.ReadConsoleW //sys resizePseudoConsole(pconsole Handle, size uint32) (hr error) = kernel32.ResizePseudoConsole @@ -715,20 +725,12 @@ func DurationSinceBoot() time.Duration { } func Ftruncate(fd Handle, length int64) (err error) { - curoffset, e := Seek(fd, 0, 1) - if e != nil { - return e - } - defer Seek(fd, curoffset, 0) - _, e = Seek(fd, length, 0) - if e != nil { - return e + type _FILE_END_OF_FILE_INFO struct { + EndOfFile int64 } - e = SetEndOfFile(fd) - if e != nil { - return e - } - return nil + var info _FILE_END_OF_FILE_INFO + info.EndOfFile = length + return SetFileInformationByHandle(fd, FileEndOfFileInfo, (*byte)(unsafe.Pointer(&info)), uint32(unsafe.Sizeof(info))) } func Gettimeofday(tv *Timeval) (err error) { @@ -884,6 +886,11 @@ const socket_error = uintptr(^uint32(0)) //sys GetACP() (acp uint32) = kernel32.GetACP //sys MultiByteToWideChar(codePage uint32, dwFlags uint32, str *byte, nstr int32, wchar *uint16, nwchar int32) (nwrite int32, err error) = kernel32.MultiByteToWideChar //sys getBestInterfaceEx(sockaddr unsafe.Pointer, pdwBestIfIndex *uint32) (errcode error) = iphlpapi.GetBestInterfaceEx +//sys GetIfEntry2Ex(level uint32, row *MibIfRow2) (errcode error) = iphlpapi.GetIfEntry2Ex +//sys GetUnicastIpAddressEntry(row *MibUnicastIpAddressRow) (errcode error) = iphlpapi.GetUnicastIpAddressEntry +//sys NotifyIpInterfaceChange(family uint16, callback uintptr, callerContext unsafe.Pointer, initialNotification bool, notificationHandle *Handle) (errcode error) = iphlpapi.NotifyIpInterfaceChange +//sys NotifyUnicastIpAddressChange(family uint16, callback uintptr, callerContext unsafe.Pointer, initialNotification bool, notificationHandle *Handle) (errcode error) = iphlpapi.NotifyUnicastIpAddressChange +//sys CancelMibChangeNotify2(notificationHandle Handle) (errcode error) = iphlpapi.CancelMibChangeNotify2 // For testing: clients can set this flag to force // creation of IPv6 sockets to return EAFNOSUPPORT. @@ -1368,9 +1375,11 @@ func SetsockoptLinger(fd Handle, level, opt int, l *Linger) (err error) { func SetsockoptInet4Addr(fd Handle, level, opt int, value [4]byte) (err error) { return Setsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(&value[0])), 4) } + func SetsockoptIPMreq(fd Handle, level, opt int, mreq *IPMreq) (err error) { return Setsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(mreq)), int32(unsafe.Sizeof(*mreq))) } + func SetsockoptIPv6Mreq(fd Handle, level, opt int, mreq *IPv6Mreq) (err error) { return syscall.EWINDOWS } @@ -1673,13 +1682,16 @@ func (s NTStatus) Error() string { // do not use NTUnicodeString, and instead UTF16PtrFromString should be used for // the more common *uint16 string type. func NewNTUnicodeString(s string) (*NTUnicodeString, error) { - var u NTUnicodeString - s16, err := UTF16PtrFromString(s) + s16, err := UTF16FromString(s) if err != nil { return nil, err } - RtlInitUnicodeString(&u, s16) - return &u, nil + n := uint16(len(s16) * 2) + return &NTUnicodeString{ + Length: n - 2, // subtract 2 bytes for the NULL terminator + MaximumLength: n, + Buffer: &s16[0], + }, nil } // Slice returns a uint16 slice that aliases the data in the NTUnicodeString. diff --git a/vendor/golang.org/x/sys/windows/types_windows.go b/vendor/golang.org/x/sys/windows/types_windows.go index d8cb71db0..51311e205 100644 --- a/vendor/golang.org/x/sys/windows/types_windows.go +++ b/vendor/golang.org/x/sys/windows/types_windows.go @@ -1060,6 +1060,7 @@ const ( SIO_GET_EXTENSION_FUNCTION_POINTER = IOC_INOUT | IOC_WS2 | 6 SIO_KEEPALIVE_VALS = IOC_IN | IOC_VENDOR | 4 SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | 12 + SIO_UDP_NETRESET = IOC_IN | IOC_VENDOR | 15 // cf. http://support.microsoft.com/default.aspx?scid=kb;en-us;257460 @@ -2003,7 +2004,21 @@ const ( MOVEFILE_FAIL_IF_NOT_TRACKABLE = 0x20 ) -const GAA_FLAG_INCLUDE_PREFIX = 0x00000010 +// Flags for GetAdaptersAddresses, see +// https://learn.microsoft.com/en-us/windows/win32/api/iphlpapi/nf-iphlpapi-getadaptersaddresses. +const ( + GAA_FLAG_SKIP_UNICAST = 0x1 + GAA_FLAG_SKIP_ANYCAST = 0x2 + GAA_FLAG_SKIP_MULTICAST = 0x4 + GAA_FLAG_SKIP_DNS_SERVER = 0x8 + GAA_FLAG_INCLUDE_PREFIX = 0x10 + GAA_FLAG_SKIP_FRIENDLY_NAME = 0x20 + GAA_FLAG_INCLUDE_WINS_INFO = 0x40 + GAA_FLAG_INCLUDE_GATEWAYS = 0x80 + GAA_FLAG_INCLUDE_ALL_INTERFACES = 0x100 + GAA_FLAG_INCLUDE_ALL_COMPARTMENTS = 0x200 + GAA_FLAG_INCLUDE_TUNNEL_BINDINGORDER = 0x400 +) const ( IF_TYPE_OTHER = 1 @@ -2017,6 +2032,50 @@ const ( IF_TYPE_IEEE1394 = 144 ) +// Enum NL_PREFIX_ORIGIN for [IpAdapterUnicastAddress], see +// https://learn.microsoft.com/en-us/windows/win32/api/nldef/ne-nldef-nl_prefix_origin +const ( + IpPrefixOriginOther = 0 + IpPrefixOriginManual = 1 + IpPrefixOriginWellKnown = 2 + IpPrefixOriginDhcp = 3 + IpPrefixOriginRouterAdvertisement = 4 + IpPrefixOriginUnchanged = 1 << 4 +) + +// Enum NL_SUFFIX_ORIGIN for [IpAdapterUnicastAddress], see +// https://learn.microsoft.com/en-us/windows/win32/api/nldef/ne-nldef-nl_suffix_origin +const ( + NlsoOther = 0 + NlsoManual = 1 + NlsoWellKnown = 2 + NlsoDhcp = 3 + NlsoLinkLayerAddress = 4 + NlsoRandom = 5 + IpSuffixOriginOther = 0 + IpSuffixOriginManual = 1 + IpSuffixOriginWellKnown = 2 + IpSuffixOriginDhcp = 3 + IpSuffixOriginLinkLayerAddress = 4 + IpSuffixOriginRandom = 5 + IpSuffixOriginUnchanged = 1 << 4 +) + +// Enum NL_DAD_STATE for [IpAdapterUnicastAddress], see +// https://learn.microsoft.com/en-us/windows/win32/api/nldef/ne-nldef-nl_dad_state +const ( + NldsInvalid = 0 + NldsTentative = 1 + NldsDuplicate = 2 + NldsDeprecated = 3 + NldsPreferred = 4 + IpDadStateInvalid = 0 + IpDadStateTentative = 1 + IpDadStateDuplicate = 2 + IpDadStateDeprecated = 3 + IpDadStatePreferred = 4 +) + type SocketAddress struct { Sockaddr *syscall.RawSockaddrAny SockaddrLength int32 @@ -2144,6 +2203,132 @@ const ( IfOperStatusLowerLayerDown = 7 ) +const ( + IF_MAX_PHYS_ADDRESS_LENGTH = 32 + IF_MAX_STRING_SIZE = 256 +) + +// MIB_IF_ENTRY_LEVEL enumeration from netioapi.h or +// https://learn.microsoft.com/en-us/windows/win32/api/netioapi/nf-netioapi-getifentry2ex. +const ( + MibIfEntryNormal = 0 + MibIfEntryNormalWithoutStatistics = 2 +) + +// MIB_NOTIFICATION_TYPE enumeration from netioapi.h or +// https://learn.microsoft.com/en-us/windows/win32/api/netioapi/ne-netioapi-mib_notification_type. +const ( + MibParameterNotification = 0 + MibAddInstance = 1 + MibDeleteInstance = 2 + MibInitialNotification = 3 +) + +// MibIfRow2 stores information about a particular interface. See +// https://learn.microsoft.com/en-us/windows/win32/api/netioapi/ns-netioapi-mib_if_row2. +type MibIfRow2 struct { + InterfaceLuid uint64 + InterfaceIndex uint32 + InterfaceGuid GUID + Alias [IF_MAX_STRING_SIZE + 1]uint16 + Description [IF_MAX_STRING_SIZE + 1]uint16 + PhysicalAddressLength uint32 + PhysicalAddress [IF_MAX_PHYS_ADDRESS_LENGTH]uint8 + PermanentPhysicalAddress [IF_MAX_PHYS_ADDRESS_LENGTH]uint8 + Mtu uint32 + Type uint32 + TunnelType uint32 + MediaType uint32 + PhysicalMediumType uint32 + AccessType uint32 + DirectionType uint32 + InterfaceAndOperStatusFlags uint8 + OperStatus uint32 + AdminStatus uint32 + MediaConnectState uint32 + NetworkGuid GUID + ConnectionType uint32 + TransmitLinkSpeed uint64 + ReceiveLinkSpeed uint64 + InOctets uint64 + InUcastPkts uint64 + InNUcastPkts uint64 + InDiscards uint64 + InErrors uint64 + InUnknownProtos uint64 + InUcastOctets uint64 + InMulticastOctets uint64 + InBroadcastOctets uint64 + OutOctets uint64 + OutUcastPkts uint64 + OutNUcastPkts uint64 + OutDiscards uint64 + OutErrors uint64 + OutUcastOctets uint64 + OutMulticastOctets uint64 + OutBroadcastOctets uint64 + OutQLen uint64 +} + +// MIB_UNICASTIPADDRESS_ROW stores information about a unicast IP address. See +// https://learn.microsoft.com/en-us/windows/win32/api/netioapi/ns-netioapi-mib_unicastipaddress_row. +type MibUnicastIpAddressRow struct { + Address RawSockaddrInet6 // SOCKADDR_INET union + InterfaceLuid uint64 + InterfaceIndex uint32 + PrefixOrigin uint32 + SuffixOrigin uint32 + ValidLifetime uint32 + PreferredLifetime uint32 + OnLinkPrefixLength uint8 + SkipAsSource uint8 + DadState uint32 + ScopeId uint32 + CreationTimeStamp Filetime +} + +const ScopeLevelCount = 16 + +// MIB_IPINTERFACE_ROW stores interface management information for a particular IP address family on a network interface. +// See https://learn.microsoft.com/en-us/windows/win32/api/netioapi/ns-netioapi-mib_ipinterface_row. +type MibIpInterfaceRow struct { + Family uint16 + InterfaceLuid uint64 + InterfaceIndex uint32 + MaxReassemblySize uint32 + InterfaceIdentifier uint64 + MinRouterAdvertisementInterval uint32 + MaxRouterAdvertisementInterval uint32 + AdvertisingEnabled uint8 + ForwardingEnabled uint8 + WeakHostSend uint8 + WeakHostReceive uint8 + UseAutomaticMetric uint8 + UseNeighborUnreachabilityDetection uint8 + ManagedAddressConfigurationSupported uint8 + OtherStatefulConfigurationSupported uint8 + AdvertiseDefaultRoute uint8 + RouterDiscoveryBehavior uint32 + DadTransmits uint32 + BaseReachableTime uint32 + RetransmitTime uint32 + PathMtuDiscoveryTimeout uint32 + LinkLocalAddressBehavior uint32 + LinkLocalAddressTimeout uint32 + ZoneIndices [ScopeLevelCount]uint32 + SitePrefixLength uint32 + Metric uint32 + NlMtu uint32 + Connected uint8 + SupportsWakeUpPatterns uint8 + SupportsNeighborDiscovery uint8 + SupportsRouterDiscovery uint8 + ReachableTime uint32 + TransmitOffload uint32 + ReceiveOffload uint32 + DisableDefaultRoutes uint8 +} + // Console related constants used for the mode parameter to SetConsoleMode. See // https://docs.microsoft.com/en-us/windows/console/setconsolemode for details. @@ -3404,3 +3589,14 @@ type DCB struct { EvtChar byte wReserved1 uint16 } + +// Keyboard Layout Flags. +// See https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-loadkeyboardlayoutw +const ( + KLF_ACTIVATE = 0x00000001 + KLF_SUBSTITUTE_OK = 0x00000002 + KLF_REORDER = 0x00000008 + KLF_REPLACELANG = 0x00000010 + KLF_NOTELLSHELL = 0x00000080 + KLF_SETFORPROCESS = 0x00000100 +) diff --git a/vendor/golang.org/x/sys/windows/zsyscall_windows.go b/vendor/golang.org/x/sys/windows/zsyscall_windows.go index 5c6035ddf..6f5252880 100644 --- a/vendor/golang.org/x/sys/windows/zsyscall_windows.go +++ b/vendor/golang.org/x/sys/windows/zsyscall_windows.go @@ -91,6 +91,7 @@ var ( procEnumServicesStatusExW = modadvapi32.NewProc("EnumServicesStatusExW") procEqualSid = modadvapi32.NewProc("EqualSid") procFreeSid = modadvapi32.NewProc("FreeSid") + procGetAce = modadvapi32.NewProc("GetAce") procGetLengthSid = modadvapi32.NewProc("GetLengthSid") procGetNamedSecurityInfoW = modadvapi32.NewProc("GetNamedSecurityInfoW") procGetSecurityDescriptorControl = modadvapi32.NewProc("GetSecurityDescriptorControl") @@ -180,10 +181,15 @@ var ( procDnsRecordListFree = moddnsapi.NewProc("DnsRecordListFree") procDwmGetWindowAttribute = moddwmapi.NewProc("DwmGetWindowAttribute") procDwmSetWindowAttribute = moddwmapi.NewProc("DwmSetWindowAttribute") + procCancelMibChangeNotify2 = modiphlpapi.NewProc("CancelMibChangeNotify2") procGetAdaptersAddresses = modiphlpapi.NewProc("GetAdaptersAddresses") procGetAdaptersInfo = modiphlpapi.NewProc("GetAdaptersInfo") procGetBestInterfaceEx = modiphlpapi.NewProc("GetBestInterfaceEx") procGetIfEntry = modiphlpapi.NewProc("GetIfEntry") + procGetIfEntry2Ex = modiphlpapi.NewProc("GetIfEntry2Ex") + procGetUnicastIpAddressEntry = modiphlpapi.NewProc("GetUnicastIpAddressEntry") + procNotifyIpInterfaceChange = modiphlpapi.NewProc("NotifyIpInterfaceChange") + procNotifyUnicastIpAddressChange = modiphlpapi.NewProc("NotifyUnicastIpAddressChange") procAddDllDirectory = modkernel32.NewProc("AddDllDirectory") procAssignProcessToJobObject = modkernel32.NewProc("AssignProcessToJobObject") procCancelIo = modkernel32.NewProc("CancelIo") @@ -246,7 +252,9 @@ var ( procGetCommandLineW = modkernel32.NewProc("GetCommandLineW") procGetComputerNameExW = modkernel32.NewProc("GetComputerNameExW") procGetComputerNameW = modkernel32.NewProc("GetComputerNameW") + procGetConsoleCP = modkernel32.NewProc("GetConsoleCP") procGetConsoleMode = modkernel32.NewProc("GetConsoleMode") + procGetConsoleOutputCP = modkernel32.NewProc("GetConsoleOutputCP") procGetConsoleScreenBufferInfo = modkernel32.NewProc("GetConsoleScreenBufferInfo") procGetCurrentDirectoryW = modkernel32.NewProc("GetCurrentDirectoryW") procGetCurrentProcessId = modkernel32.NewProc("GetCurrentProcessId") @@ -346,8 +354,10 @@ var ( procSetCommMask = modkernel32.NewProc("SetCommMask") procSetCommState = modkernel32.NewProc("SetCommState") procSetCommTimeouts = modkernel32.NewProc("SetCommTimeouts") + procSetConsoleCP = modkernel32.NewProc("SetConsoleCP") procSetConsoleCursorPosition = modkernel32.NewProc("SetConsoleCursorPosition") procSetConsoleMode = modkernel32.NewProc("SetConsoleMode") + procSetConsoleOutputCP = modkernel32.NewProc("SetConsoleOutputCP") procSetCurrentDirectoryW = modkernel32.NewProc("SetCurrentDirectoryW") procSetDefaultDllDirectories = modkernel32.NewProc("SetDefaultDllDirectories") procSetDllDirectoryW = modkernel32.NewProc("SetDllDirectoryW") @@ -401,6 +411,7 @@ var ( procTransmitFile = modmswsock.NewProc("TransmitFile") procNetApiBufferFree = modnetapi32.NewProc("NetApiBufferFree") procNetGetJoinInformation = modnetapi32.NewProc("NetGetJoinInformation") + procNetUserEnum = modnetapi32.NewProc("NetUserEnum") procNetUserGetInfo = modnetapi32.NewProc("NetUserGetInfo") procNtCreateFile = modntdll.NewProc("NtCreateFile") procNtCreateNamedPipeFile = modntdll.NewProc("NtCreateNamedPipeFile") @@ -476,12 +487,16 @@ var ( procGetDesktopWindow = moduser32.NewProc("GetDesktopWindow") procGetForegroundWindow = moduser32.NewProc("GetForegroundWindow") procGetGUIThreadInfo = moduser32.NewProc("GetGUIThreadInfo") + procGetKeyboardLayout = moduser32.NewProc("GetKeyboardLayout") procGetShellWindow = moduser32.NewProc("GetShellWindow") procGetWindowThreadProcessId = moduser32.NewProc("GetWindowThreadProcessId") procIsWindow = moduser32.NewProc("IsWindow") procIsWindowUnicode = moduser32.NewProc("IsWindowUnicode") procIsWindowVisible = moduser32.NewProc("IsWindowVisible") + procLoadKeyboardLayoutW = moduser32.NewProc("LoadKeyboardLayoutW") procMessageBoxW = moduser32.NewProc("MessageBoxW") + procToUnicodeEx = moduser32.NewProc("ToUnicodeEx") + procUnloadKeyboardLayout = moduser32.NewProc("UnloadKeyboardLayout") procCreateEnvironmentBlock = moduserenv.NewProc("CreateEnvironmentBlock") procDestroyEnvironmentBlock = moduserenv.NewProc("DestroyEnvironmentBlock") procGetUserProfileDirectoryW = moduserenv.NewProc("GetUserProfileDirectoryW") @@ -787,6 +802,14 @@ func FreeSid(sid *SID) (err error) { return } +func GetAce(acl *ACL, aceIndex uint32, pAce **ACCESS_ALLOWED_ACE) (err error) { + r1, _, e1 := syscall.Syscall(procGetAce.Addr(), 3, uintptr(unsafe.Pointer(acl)), uintptr(aceIndex), uintptr(unsafe.Pointer(pAce))) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + func GetLengthSid(sid *SID) (len uint32) { r0, _, _ := syscall.Syscall(procGetLengthSid.Addr(), 1, uintptr(unsafe.Pointer(sid)), 0, 0) len = uint32(r0) @@ -1588,6 +1611,14 @@ func DwmSetWindowAttribute(hwnd HWND, attribute uint32, value unsafe.Pointer, si return } +func CancelMibChangeNotify2(notificationHandle Handle) (errcode error) { + r0, _, _ := syscall.SyscallN(procCancelMibChangeNotify2.Addr(), uintptr(notificationHandle)) + if r0 != 0 { + errcode = syscall.Errno(r0) + } + return +} + func GetAdaptersAddresses(family uint32, flags uint32, reserved uintptr, adapterAddresses *IpAdapterAddresses, sizePointer *uint32) (errcode error) { r0, _, _ := syscall.Syscall6(procGetAdaptersAddresses.Addr(), 5, uintptr(family), uintptr(flags), uintptr(reserved), uintptr(unsafe.Pointer(adapterAddresses)), uintptr(unsafe.Pointer(sizePointer)), 0) if r0 != 0 { @@ -1620,6 +1651,46 @@ func GetIfEntry(pIfRow *MibIfRow) (errcode error) { return } +func GetIfEntry2Ex(level uint32, row *MibIfRow2) (errcode error) { + r0, _, _ := syscall.SyscallN(procGetIfEntry2Ex.Addr(), uintptr(level), uintptr(unsafe.Pointer(row))) + if r0 != 0 { + errcode = syscall.Errno(r0) + } + return +} + +func GetUnicastIpAddressEntry(row *MibUnicastIpAddressRow) (errcode error) { + r0, _, _ := syscall.SyscallN(procGetUnicastIpAddressEntry.Addr(), uintptr(unsafe.Pointer(row))) + if r0 != 0 { + errcode = syscall.Errno(r0) + } + return +} + +func NotifyIpInterfaceChange(family uint16, callback uintptr, callerContext unsafe.Pointer, initialNotification bool, notificationHandle *Handle) (errcode error) { + var _p0 uint32 + if initialNotification { + _p0 = 1 + } + r0, _, _ := syscall.SyscallN(procNotifyIpInterfaceChange.Addr(), uintptr(family), uintptr(callback), uintptr(callerContext), uintptr(_p0), uintptr(unsafe.Pointer(notificationHandle))) + if r0 != 0 { + errcode = syscall.Errno(r0) + } + return +} + +func NotifyUnicastIpAddressChange(family uint16, callback uintptr, callerContext unsafe.Pointer, initialNotification bool, notificationHandle *Handle) (errcode error) { + var _p0 uint32 + if initialNotification { + _p0 = 1 + } + r0, _, _ := syscall.SyscallN(procNotifyUnicastIpAddressChange.Addr(), uintptr(family), uintptr(callback), uintptr(callerContext), uintptr(_p0), uintptr(unsafe.Pointer(notificationHandle))) + if r0 != 0 { + errcode = syscall.Errno(r0) + } + return +} + func AddDllDirectory(path *uint16) (cookie uintptr, err error) { r0, _, e1 := syscall.Syscall(procAddDllDirectory.Addr(), 1, uintptr(unsafe.Pointer(path)), 0, 0) cookie = uintptr(r0) @@ -2148,6 +2219,15 @@ func GetComputerName(buf *uint16, n *uint32) (err error) { return } +func GetConsoleCP() (cp uint32, err error) { + r0, _, e1 := syscall.Syscall(procGetConsoleCP.Addr(), 0, 0, 0, 0) + cp = uint32(r0) + if cp == 0 { + err = errnoErr(e1) + } + return +} + func GetConsoleMode(console Handle, mode *uint32) (err error) { r1, _, e1 := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(console), uintptr(unsafe.Pointer(mode)), 0) if r1 == 0 { @@ -2156,6 +2236,15 @@ func GetConsoleMode(console Handle, mode *uint32) (err error) { return } +func GetConsoleOutputCP() (cp uint32, err error) { + r0, _, e1 := syscall.Syscall(procGetConsoleOutputCP.Addr(), 0, 0, 0, 0) + cp = uint32(r0) + if cp == 0 { + err = errnoErr(e1) + } + return +} + func GetConsoleScreenBufferInfo(console Handle, info *ConsoleScreenBufferInfo) (err error) { r1, _, e1 := syscall.Syscall(procGetConsoleScreenBufferInfo.Addr(), 2, uintptr(console), uintptr(unsafe.Pointer(info)), 0) if r1 == 0 { @@ -3024,6 +3113,14 @@ func SetCommTimeouts(handle Handle, timeouts *CommTimeouts) (err error) { return } +func SetConsoleCP(cp uint32) (err error) { + r1, _, e1 := syscall.Syscall(procSetConsoleCP.Addr(), 1, uintptr(cp), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + func setConsoleCursorPosition(console Handle, position uint32) (err error) { r1, _, e1 := syscall.Syscall(procSetConsoleCursorPosition.Addr(), 2, uintptr(console), uintptr(position), 0) if r1 == 0 { @@ -3040,6 +3137,14 @@ func SetConsoleMode(console Handle, mode uint32) (err error) { return } +func SetConsoleOutputCP(cp uint32) (err error) { + r1, _, e1 := syscall.Syscall(procSetConsoleOutputCP.Addr(), 1, uintptr(cp), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + func SetCurrentDirectory(path *uint16) (err error) { r1, _, e1 := syscall.Syscall(procSetCurrentDirectoryW.Addr(), 1, uintptr(unsafe.Pointer(path)), 0, 0) if r1 == 0 { @@ -3486,6 +3591,14 @@ func NetGetJoinInformation(server *uint16, name **uint16, bufType *uint32) (nete return } +func NetUserEnum(serverName *uint16, level uint32, filter uint32, buf **byte, prefMaxLen uint32, entriesRead *uint32, totalEntries *uint32, resumeHandle *uint32) (neterr error) { + r0, _, _ := syscall.Syscall9(procNetUserEnum.Addr(), 8, uintptr(unsafe.Pointer(serverName)), uintptr(level), uintptr(filter), uintptr(unsafe.Pointer(buf)), uintptr(prefMaxLen), uintptr(unsafe.Pointer(entriesRead)), uintptr(unsafe.Pointer(totalEntries)), uintptr(unsafe.Pointer(resumeHandle)), 0) + if r0 != 0 { + neterr = syscall.Errno(r0) + } + return +} + func NetUserGetInfo(serverName *uint16, userName *uint16, level uint32, buf **byte) (neterr error) { r0, _, _ := syscall.Syscall6(procNetUserGetInfo.Addr(), 4, uintptr(unsafe.Pointer(serverName)), uintptr(unsafe.Pointer(userName)), uintptr(level), uintptr(unsafe.Pointer(buf)), 0, 0) if r0 != 0 { @@ -4064,6 +4177,12 @@ func GetGUIThreadInfo(thread uint32, info *GUIThreadInfo) (err error) { return } +func GetKeyboardLayout(tid uint32) (hkl Handle) { + r0, _, _ := syscall.Syscall(procGetKeyboardLayout.Addr(), 1, uintptr(tid), 0, 0) + hkl = Handle(r0) + return +} + func GetShellWindow() (shellWindow HWND) { r0, _, _ := syscall.Syscall(procGetShellWindow.Addr(), 0, 0, 0, 0) shellWindow = HWND(r0) @@ -4097,6 +4216,15 @@ func IsWindowVisible(hwnd HWND) (isVisible bool) { return } +func LoadKeyboardLayout(name *uint16, flags uint32) (hkl Handle, err error) { + r0, _, e1 := syscall.Syscall(procLoadKeyboardLayoutW.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(flags), 0) + hkl = Handle(r0) + if hkl == 0 { + err = errnoErr(e1) + } + return +} + func MessageBox(hwnd HWND, text *uint16, caption *uint16, boxtype uint32) (ret int32, err error) { r0, _, e1 := syscall.Syscall6(procMessageBoxW.Addr(), 4, uintptr(hwnd), uintptr(unsafe.Pointer(text)), uintptr(unsafe.Pointer(caption)), uintptr(boxtype), 0, 0) ret = int32(r0) @@ -4106,6 +4234,20 @@ func MessageBox(hwnd HWND, text *uint16, caption *uint16, boxtype uint32) (ret i return } +func ToUnicodeEx(vkey uint32, scancode uint32, keystate *byte, pwszBuff *uint16, cchBuff int32, flags uint32, hkl Handle) (ret int32) { + r0, _, _ := syscall.Syscall9(procToUnicodeEx.Addr(), 7, uintptr(vkey), uintptr(scancode), uintptr(unsafe.Pointer(keystate)), uintptr(unsafe.Pointer(pwszBuff)), uintptr(cchBuff), uintptr(flags), uintptr(hkl), 0, 0) + ret = int32(r0) + return +} + +func UnloadKeyboardLayout(hkl Handle) (err error) { + r1, _, e1 := syscall.Syscall(procUnloadKeyboardLayout.Addr(), 1, uintptr(hkl), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + func CreateEnvironmentBlock(block **uint16, token Token, inheritExisting bool) (err error) { var _p0 uint32 if inheritExisting { diff --git a/vendor/golang.org/x/term/LICENSE b/vendor/golang.org/x/term/LICENSE index 6a66aea5e..2a7cf70da 100644 --- a/vendor/golang.org/x/term/LICENSE +++ b/vendor/golang.org/x/term/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2009 The Go Authors. All rights reserved. +Copyright 2009 The Go Authors. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are @@ -10,7 +10,7 @@ notice, this list of conditions and the following disclaimer. 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 + * Neither the name of Google LLC nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. diff --git a/vendor/golang.org/x/term/README.md b/vendor/golang.org/x/term/README.md index d03d0aefe..05ff623f9 100644 --- a/vendor/golang.org/x/term/README.md +++ b/vendor/golang.org/x/term/README.md @@ -4,16 +4,13 @@ This repository provides Go terminal and console support packages. -## Download/Install - -The easiest way to install is to run `go get -u golang.org/x/term`. You can -also manually git clone the repository to `$GOPATH/src/golang.org/x/term`. - ## Report Issues / Send Patches This repository uses Gerrit for code changes. To learn how to submit changes to -this repository, see https://golang.org/doc/contribute.html. +this repository, see https://go.dev/doc/contribute. + +The git repository is https://go.googlesource.com/term. The main issue tracker for the term repository is located at -https://github.com/golang/go/issues. Prefix your issue with "x/term:" in the +https://go.dev/issues. Prefix your issue with "x/term:" in the subject line, so it is easy to find. diff --git a/vendor/golang.org/x/term/term_windows.go b/vendor/golang.org/x/term/term_windows.go index 465f56060..df6bf948e 100644 --- a/vendor/golang.org/x/term/term_windows.go +++ b/vendor/golang.org/x/term/term_windows.go @@ -26,6 +26,7 @@ func makeRaw(fd int) (*State, error) { return nil, err } raw := st &^ (windows.ENABLE_ECHO_INPUT | windows.ENABLE_PROCESSED_INPUT | windows.ENABLE_LINE_INPUT | windows.ENABLE_PROCESSED_OUTPUT) + raw |= windows.ENABLE_VIRTUAL_TERMINAL_INPUT if err := windows.SetConsoleMode(windows.Handle(fd), raw); err != nil { return nil, err } diff --git a/vendor/golang.org/x/text/LICENSE b/vendor/golang.org/x/text/LICENSE index 6a66aea5e..2a7cf70da 100644 --- a/vendor/golang.org/x/text/LICENSE +++ b/vendor/golang.org/x/text/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2009 The Go Authors. All rights reserved. +Copyright 2009 The Go Authors. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are @@ -10,7 +10,7 @@ notice, this list of conditions and the following disclaimer. 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 + * Neither the name of Google LLC nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. diff --git a/vendor/golang.org/x/time/LICENSE b/vendor/golang.org/x/time/LICENSE index 6a66aea5e..2a7cf70da 100644 --- a/vendor/golang.org/x/time/LICENSE +++ b/vendor/golang.org/x/time/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2009 The Go Authors. All rights reserved. +Copyright 2009 The Go Authors. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are @@ -10,7 +10,7 @@ notice, this list of conditions and the following disclaimer. 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 + * Neither the name of Google LLC nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. diff --git a/vendor/golang.org/x/time/rate/rate.go b/vendor/golang.org/x/time/rate/rate.go index 8f6c7f493..93a798ab6 100644 --- a/vendor/golang.org/x/time/rate/rate.go +++ b/vendor/golang.org/x/time/rate/rate.go @@ -99,8 +99,9 @@ func (lim *Limiter) Tokens() float64 { // bursts of at most b tokens. func NewLimiter(r Limit, b int) *Limiter { return &Limiter{ - limit: r, - burst: b, + limit: r, + burst: b, + tokens: float64(b), } } @@ -344,18 +345,6 @@ func (lim *Limiter) reserveN(t time.Time, n int, maxFutureReserve time.Duration) tokens: n, timeToAct: t, } - } else if lim.limit == 0 { - var ok bool - if lim.burst >= n { - ok = true - lim.burst -= n - } - return Reservation{ - ok: ok, - lim: lim, - tokens: lim.burst, - timeToAct: t, - } } t, tokens := lim.advance(t) diff --git a/vendor/golang.org/x/tools/cover/profile.go b/vendor/golang.org/x/tools/cover/profile.go new file mode 100644 index 000000000..47a9a5411 --- /dev/null +++ b/vendor/golang.org/x/tools/cover/profile.go @@ -0,0 +1,266 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package cover provides support for parsing coverage profiles +// generated by "go test -coverprofile=cover.out". +package cover // import "golang.org/x/tools/cover" + +import ( + "bufio" + "errors" + "fmt" + "io" + "math" + "os" + "sort" + "strconv" + "strings" +) + +// Profile represents the profiling data for a specific file. +type Profile struct { + FileName string + Mode string + Blocks []ProfileBlock +} + +// ProfileBlock represents a single block of profiling data. +type ProfileBlock struct { + StartLine, StartCol int + EndLine, EndCol int + NumStmt, Count int +} + +type byFileName []*Profile + +func (p byFileName) Len() int { return len(p) } +func (p byFileName) Less(i, j int) bool { return p[i].FileName < p[j].FileName } +func (p byFileName) Swap(i, j int) { p[i], p[j] = p[j], p[i] } + +// ParseProfiles parses profile data in the specified file and returns a +// Profile for each source file described therein. +func ParseProfiles(fileName string) ([]*Profile, error) { + pf, err := os.Open(fileName) + if err != nil { + return nil, err + } + defer pf.Close() + return ParseProfilesFromReader(pf) +} + +// ParseProfilesFromReader parses profile data from the Reader and +// returns a Profile for each source file described therein. +func ParseProfilesFromReader(rd io.Reader) ([]*Profile, error) { + // First line is "mode: foo", where foo is "set", "count", or "atomic". + // Rest of file is in the format + // encoding/base64/base64.go:34.44,37.40 3 1 + // where the fields are: name.go:line.column,line.column numberOfStatements count + files := make(map[string]*Profile) + s := bufio.NewScanner(rd) + mode := "" + for s.Scan() { + line := s.Text() + if mode == "" { + const p = "mode: " + if !strings.HasPrefix(line, p) || line == p { + return nil, fmt.Errorf("bad mode line: %v", line) + } + mode = line[len(p):] + continue + } + fn, b, err := parseLine(line) + if err != nil { + return nil, fmt.Errorf("line %q doesn't match expected format: %v", line, err) + } + p := files[fn] + if p == nil { + p = &Profile{ + FileName: fn, + Mode: mode, + } + files[fn] = p + } + p.Blocks = append(p.Blocks, b) + } + if err := s.Err(); err != nil { + return nil, err + } + for _, p := range files { + sort.Sort(blocksByStart(p.Blocks)) + // Merge samples from the same location. + j := 1 + for i := 1; i < len(p.Blocks); i++ { + b := p.Blocks[i] + last := p.Blocks[j-1] + if b.StartLine == last.StartLine && + b.StartCol == last.StartCol && + b.EndLine == last.EndLine && + b.EndCol == last.EndCol { + if b.NumStmt != last.NumStmt { + return nil, fmt.Errorf("inconsistent NumStmt: changed from %d to %d", last.NumStmt, b.NumStmt) + } + if mode == "set" { + p.Blocks[j-1].Count |= b.Count + } else { + p.Blocks[j-1].Count += b.Count + } + continue + } + p.Blocks[j] = b + j++ + } + p.Blocks = p.Blocks[:j] + } + // Generate a sorted slice. + profiles := make([]*Profile, 0, len(files)) + for _, profile := range files { + profiles = append(profiles, profile) + } + sort.Sort(byFileName(profiles)) + return profiles, nil +} + +// parseLine parses a line from a coverage file. +// It is equivalent to the regex +// ^(.+):([0-9]+)\.([0-9]+),([0-9]+)\.([0-9]+) ([0-9]+) ([0-9]+)$ +// +// However, it is much faster: https://golang.org/cl/179377 +func parseLine(l string) (fileName string, block ProfileBlock, err error) { + end := len(l) + + b := ProfileBlock{} + b.Count, end, err = seekBack(l, ' ', end, "Count") + if err != nil { + return "", b, err + } + b.NumStmt, end, err = seekBack(l, ' ', end, "NumStmt") + if err != nil { + return "", b, err + } + b.EndCol, end, err = seekBack(l, '.', end, "EndCol") + if err != nil { + return "", b, err + } + b.EndLine, end, err = seekBack(l, ',', end, "EndLine") + if err != nil { + return "", b, err + } + b.StartCol, end, err = seekBack(l, '.', end, "StartCol") + if err != nil { + return "", b, err + } + b.StartLine, end, err = seekBack(l, ':', end, "StartLine") + if err != nil { + return "", b, err + } + fn := l[0:end] + if fn == "" { + return "", b, errors.New("a FileName cannot be blank") + } + return fn, b, nil +} + +// seekBack searches backwards from end to find sep in l, then returns the +// value between sep and end as an integer. +// If seekBack fails, the returned error will reference what. +func seekBack(l string, sep byte, end int, what string) (value int, nextSep int, err error) { + // Since we're seeking backwards and we know only ASCII is legal for these values, + // we can ignore the possibility of non-ASCII characters. + for start := end - 1; start >= 0; start-- { + if l[start] == sep { + i, err := strconv.Atoi(l[start+1 : end]) + if err != nil { + return 0, 0, fmt.Errorf("couldn't parse %q: %v", what, err) + } + if i < 0 { + return 0, 0, fmt.Errorf("negative values are not allowed for %s, found %d", what, i) + } + return i, start, nil + } + } + return 0, 0, fmt.Errorf("couldn't find a %s before %s", string(sep), what) +} + +type blocksByStart []ProfileBlock + +func (b blocksByStart) Len() int { return len(b) } +func (b blocksByStart) Swap(i, j int) { b[i], b[j] = b[j], b[i] } +func (b blocksByStart) Less(i, j int) bool { + bi, bj := b[i], b[j] + return bi.StartLine < bj.StartLine || bi.StartLine == bj.StartLine && bi.StartCol < bj.StartCol +} + +// Boundary represents the position in a source file of the beginning or end of a +// block as reported by the coverage profile. In HTML mode, it will correspond to +// the opening or closing of a tag and will be used to colorize the source +type Boundary struct { + Offset int // Location as a byte offset in the source file. + Start bool // Is this the start of a block? + Count int // Event count from the cover profile. + Norm float64 // Count normalized to [0..1]. + Index int // Order in input file. +} + +// Boundaries returns a Profile as a set of Boundary objects within the provided src. +func (p *Profile) Boundaries(src []byte) (boundaries []Boundary) { + // Find maximum count. + max := 0 + for _, b := range p.Blocks { + if b.Count > max { + max = b.Count + } + } + // Divisor for normalization. + divisor := math.Log(float64(max)) + + // boundary returns a Boundary, populating the Norm field with a normalized Count. + index := 0 + boundary := func(offset int, start bool, count int) Boundary { + b := Boundary{Offset: offset, Start: start, Count: count, Index: index} + index++ + if !start || count == 0 { + return b + } + if max <= 1 { + b.Norm = 0.8 // Profile is in"set" mode; we want a heat map. Use cov8 in the CSS. + } else if count > 0 { + b.Norm = math.Log(float64(count)) / divisor + } + return b + } + + line, col := 1, 2 // TODO: Why is this 2? + for si, bi := 0, 0; si < len(src) && bi < len(p.Blocks); { + b := p.Blocks[bi] + if b.StartLine == line && b.StartCol == col { + boundaries = append(boundaries, boundary(si, true, b.Count)) + } + if b.EndLine == line && b.EndCol == col || line > b.EndLine { + boundaries = append(boundaries, boundary(si, false, 0)) + bi++ + continue // Don't advance through src; maybe the next block starts here. + } + if src[si] == '\n' { + line++ + col = 0 + } + col++ + si++ + } + sort.Sort(boundariesByPos(boundaries)) + return +} + +type boundariesByPos []Boundary + +func (b boundariesByPos) Len() int { return len(b) } +func (b boundariesByPos) Swap(i, j int) { b[i], b[j] = b[j], b[i] } +func (b boundariesByPos) Less(i, j int) bool { + if b[i].Offset == b[j].Offset { + // Boundaries at the same offset should be ordered according to + // their original position. + return b[i].Index < b[j].Index + } + return b[i].Offset < b[j].Offset +} diff --git a/vendor/golang.org/x/tools/go/gcexportdata/gcexportdata.go b/vendor/golang.org/x/tools/go/gcexportdata/gcexportdata.go index 03543bd4b..137cc8df1 100644 --- a/vendor/golang.org/x/tools/go/gcexportdata/gcexportdata.go +++ b/vendor/golang.org/x/tools/go/gcexportdata/gcexportdata.go @@ -47,7 +47,7 @@ import ( func Find(importPath, srcDir string) (filename, path string) { cmd := exec.Command("go", "list", "-json", "-export", "--", importPath) cmd.Dir = srcDir - out, err := cmd.CombinedOutput() + out, err := cmd.Output() if err != nil { return "", "" } diff --git a/vendor/golang.org/x/tools/go/internal/packagesdriver/sizes.go b/vendor/golang.org/x/tools/go/internal/packagesdriver/sizes.go index 333676b7c..c6e7c0d44 100644 --- a/vendor/golang.org/x/tools/go/internal/packagesdriver/sizes.go +++ b/vendor/golang.org/x/tools/go/internal/packagesdriver/sizes.go @@ -13,6 +13,7 @@ import ( "golang.org/x/tools/internal/gocommand" ) +// TODO(adonovan): move back into go/packages. func GetSizesForArgsGolist(ctx context.Context, inv gocommand.Invocation, gocmdRunner *gocommand.Runner) (string, string, error) { inv.Verb = "list" inv.Args = []string{"-f", "{{context.GOARCH}} {{context.Compiler}}", "--", "unsafe"} diff --git a/vendor/golang.org/x/tools/go/packages/doc.go b/vendor/golang.org/x/tools/go/packages/doc.go index b2a0b7c6a..3531ac8f5 100644 --- a/vendor/golang.org/x/tools/go/packages/doc.go +++ b/vendor/golang.org/x/tools/go/packages/doc.go @@ -15,22 +15,10 @@ Load passes most patterns directly to the underlying build tool. The default build tool is the go command. Its supported patterns are described at https://pkg.go.dev/cmd/go#hdr-Package_lists_and_patterns. +Other build systems may be supported by providing a "driver"; +see [The driver protocol]. -Load may be used in Go projects that use alternative build systems, by -installing an appropriate "driver" program for the build system and -specifying its location in the GOPACKAGESDRIVER environment variable. -For example, -https://github.com/bazelbuild/rules_go/wiki/Editor-and-tool-integration -explains how to use the driver for Bazel. -The driver program is responsible for interpreting patterns in its -preferred notation and reporting information about the packages that -they identify. -(See driverRequest and driverResponse types for the JSON -schema used by the protocol. -Though the protocol is supported, these types are currently unexported; -see #64608 for a proposal to publish them.) - -Regardless of driver, all patterns with the prefix "query=", where query is a +All patterns with the prefix "query=", where query is a non-empty string of letters from [a-z], are reserved and may be interpreted as query operators. @@ -86,7 +74,29 @@ for details. Most tools should pass their command-line arguments (after any flags) uninterpreted to [Load], so that it can interpret them according to the conventions of the underlying build system. + See the Example function for typical usage. + +# The driver protocol + +[Load] may be used to load Go packages even in Go projects that use +alternative build systems, by installing an appropriate "driver" +program for the build system and specifying its location in the +GOPACKAGESDRIVER environment variable. +For example, +https://github.com/bazelbuild/rules_go/wiki/Editor-and-tool-integration +explains how to use the driver for Bazel. + +The driver program is responsible for interpreting patterns in its +preferred notation and reporting information about the packages that +those patterns identify. Drivers must also support the special "file=" +and "pattern=" patterns described above. + +The patterns are provided as positional command-line arguments. A +JSON-encoded [DriverRequest] message providing additional information +is written to the driver's standard input. The driver must write a +JSON-encoded [DriverResponse] message to its standard output. (This +message differs from the JSON schema produced by 'go list'.) */ package packages // import "golang.org/x/tools/go/packages" @@ -188,14 +198,6 @@ Instead, ssadump no longer requests the runtime package, but seeks it among the dependencies of the user-specified packages, and emits an error if it is not found. -Overlays: The Overlay field in the Config allows providing alternate contents -for Go source files, by providing a mapping from file path to contents. -go/packages will pull in new imports added in overlay files when go/packages -is run in LoadImports mode or greater. -Overlay support for the go list driver isn't complete yet: if the file doesn't -exist on disk, it will only be recognized in an overlay if it is a non-test file -and the package would be reported even without the overlay. - Questions & Tasks - Add GOARCH/GOOS? diff --git a/vendor/golang.org/x/tools/go/packages/external.go b/vendor/golang.org/x/tools/go/packages/external.go index 7db1d1293..c2b4b711b 100644 --- a/vendor/golang.org/x/tools/go/packages/external.go +++ b/vendor/golang.org/x/tools/go/packages/external.go @@ -2,12 +2,11 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// This file enables an external tool to intercept package requests. -// If the tool is present then its results are used in preference to -// the go list command. - package packages +// This file defines the protocol that enables an external "driver" +// tool to supply package metadata in place of 'go list'. + import ( "bytes" "encoding/json" @@ -17,31 +16,71 @@ import ( "strings" ) -// The Driver Protocol +// DriverRequest defines the schema of a request for package metadata +// from an external driver program. The JSON-encoded DriverRequest +// message is provided to the driver program's standard input. The +// query patterns are provided as command-line arguments. // -// The driver, given the inputs to a call to Load, returns metadata about the packages specified. -// This allows for different build systems to support go/packages by telling go/packages how the -// packages' source is organized. -// The driver is a binary, either specified by the GOPACKAGESDRIVER environment variable or in -// the path as gopackagesdriver. It's given the inputs to load in its argv. See the package -// documentation in doc.go for the full description of the patterns that need to be supported. -// A driver receives as a JSON-serialized driverRequest struct in standard input and will -// produce a JSON-serialized driverResponse (see definition in packages.go) in its standard output. - -// driverRequest is used to provide the portion of Load's Config that is needed by a driver. -type driverRequest struct { +// See the package documentation for an overview. +type DriverRequest struct { Mode LoadMode `json:"mode"` + // Env specifies the environment the underlying build system should be run in. Env []string `json:"env"` + // BuildFlags are flags that should be passed to the underlying build system. BuildFlags []string `json:"build_flags"` + // Tests specifies whether the patterns should also return test packages. Tests bool `json:"tests"` - // Overlay maps file paths (relative to the driver's working directory) to the byte contents - // of overlay files. + + // Overlay maps file paths (relative to the driver's working directory) + // to the contents of overlay files (see Config.Overlay). Overlay map[string][]byte `json:"overlay"` } +// DriverResponse defines the schema of a response from an external +// driver program, providing the results of a query for package +// metadata. The driver program must write a JSON-encoded +// DriverResponse message to its standard output. +// +// See the package documentation for an overview. +type DriverResponse struct { + // NotHandled is returned if the request can't be handled by the current + // driver. If an external driver returns a response with NotHandled, the + // rest of the DriverResponse is ignored, and go/packages will fallback + // to the next driver. If go/packages is extended in the future to support + // lists of multiple drivers, go/packages will fall back to the next driver. + NotHandled bool + + // Compiler and Arch are the arguments pass of types.SizesFor + // to get a types.Sizes to use when type checking. + Compiler string + Arch string + + // Roots is the set of package IDs that make up the root packages. + // We have to encode this separately because when we encode a single package + // we cannot know if it is one of the roots as that requires knowledge of the + // graph it is part of. + Roots []string `json:",omitempty"` + + // Packages is the full set of packages in the graph. + // The packages are not connected into a graph. + // The Imports if populated will be stubs that only have their ID set. + // Imports will be connected and then type and syntax information added in a + // later pass (see refine). + Packages []*Package + + // GoVersion is the minor version number used by the driver + // (e.g. the go command on the PATH) when selecting .go files. + // Zero means unknown. + GoVersion int +} + +// driver is the type for functions that query the build system for the +// packages named by the patterns. +type driver func(cfg *Config, patterns ...string) (*DriverResponse, error) + // findExternalDriver returns the file path of a tool that supplies // the build system package structure, or "" if not found." // If GOPACKAGESDRIVER is set in the environment findExternalTool returns its @@ -64,8 +103,8 @@ func findExternalDriver(cfg *Config) driver { return nil } } - return func(cfg *Config, words ...string) (*driverResponse, error) { - req, err := json.Marshal(driverRequest{ + return func(cfg *Config, words ...string) (*DriverResponse, error) { + req, err := json.Marshal(DriverRequest{ Mode: cfg.Mode, Env: cfg.Env, BuildFlags: cfg.BuildFlags, @@ -80,7 +119,19 @@ func findExternalDriver(cfg *Config) driver { stderr := new(bytes.Buffer) cmd := exec.CommandContext(cfg.Context, tool, words...) cmd.Dir = cfg.Dir - cmd.Env = cfg.Env + // The cwd gets resolved to the real path. On Darwin, where + // /tmp is a symlink, this breaks anything that expects the + // working directory to keep the original path, including the + // go command when dealing with modules. + // + // os.Getwd stdlib has a special feature where if the + // cwd and the PWD are the same node then it trusts + // the PWD, so by setting it in the env for the child + // process we fix up all the paths returned by the go + // command. + // + // (See similar trick in Invocation.run in ../../internal/gocommand/invoke.go) + cmd.Env = append(slicesClip(cfg.Env), "PWD="+cfg.Dir) cmd.Stdin = bytes.NewReader(req) cmd.Stdout = buf cmd.Stderr = stderr @@ -92,10 +143,14 @@ func findExternalDriver(cfg *Config) driver { fmt.Fprintf(os.Stderr, "%s stderr: <<%s>>\n", cmdDebugStr(cmd), stderr) } - var response driverResponse + var response DriverResponse if err := json.Unmarshal(buf.Bytes(), &response); err != nil { return nil, err } return &response, nil } } + +// slicesClip removes unused capacity from the slice, returning s[:len(s):len(s)]. +// TODO(adonovan): use go1.21 slices.Clip. +func slicesClip[S ~[]E, E any](s S) S { return s[:len(s):len(s)] } diff --git a/vendor/golang.org/x/tools/go/packages/golist.go b/vendor/golang.org/x/tools/go/packages/golist.go index cd375fbc3..d9be410aa 100644 --- a/vendor/golang.org/x/tools/go/packages/golist.go +++ b/vendor/golang.org/x/tools/go/packages/golist.go @@ -35,23 +35,23 @@ type goTooOldError struct { error } -// responseDeduper wraps a driverResponse, deduplicating its contents. +// responseDeduper wraps a DriverResponse, deduplicating its contents. type responseDeduper struct { seenRoots map[string]bool seenPackages map[string]*Package - dr *driverResponse + dr *DriverResponse } func newDeduper() *responseDeduper { return &responseDeduper{ - dr: &driverResponse{}, + dr: &DriverResponse{}, seenRoots: map[string]bool{}, seenPackages: map[string]*Package{}, } } -// addAll fills in r with a driverResponse. -func (r *responseDeduper) addAll(dr *driverResponse) { +// addAll fills in r with a DriverResponse. +func (r *responseDeduper) addAll(dr *DriverResponse) { for _, pkg := range dr.Packages { r.addPackage(pkg) } @@ -128,7 +128,7 @@ func (state *golistState) mustGetEnv() map[string]string { // goListDriver uses the go list command to interpret the patterns and produce // the build system package structure. // See driver for more details. -func goListDriver(cfg *Config, patterns ...string) (*driverResponse, error) { +func goListDriver(cfg *Config, patterns ...string) (_ *DriverResponse, err error) { // Make sure that any asynchronous go commands are killed when we return. parentCtx := cfg.Context if parentCtx == nil { @@ -146,16 +146,18 @@ func goListDriver(cfg *Config, patterns ...string) (*driverResponse, error) { } // Fill in response.Sizes asynchronously if necessary. - var sizeserr error - var sizeswg sync.WaitGroup if cfg.Mode&NeedTypesSizes != 0 || cfg.Mode&NeedTypes != 0 { - sizeswg.Add(1) + errCh := make(chan error) go func() { compiler, arch, err := packagesdriver.GetSizesForArgsGolist(ctx, state.cfgInvocation(), cfg.gocmdRunner) - sizeserr = err response.dr.Compiler = compiler response.dr.Arch = arch - sizeswg.Done() + errCh <- err + }() + defer func() { + if sizesErr := <-errCh; sizesErr != nil { + err = sizesErr + } }() } @@ -208,10 +210,7 @@ extractQueries: } } - sizeswg.Wait() - if sizeserr != nil { - return nil, sizeserr - } + // (We may yet return an error due to defer.) return response.dr, nil } @@ -266,7 +265,7 @@ func (state *golistState) runContainsQueries(response *responseDeduper, queries // adhocPackage attempts to load or construct an ad-hoc package for a given // query, if the original call to the driver produced inadequate results. -func (state *golistState) adhocPackage(pattern, query string) (*driverResponse, error) { +func (state *golistState) adhocPackage(pattern, query string) (*DriverResponse, error) { response, err := state.createDriverResponse(query) if err != nil { return nil, err @@ -357,7 +356,7 @@ func otherFiles(p *jsonPackage) [][]string { // createDriverResponse uses the "go list" command to expand the pattern // words and return a response for the specified packages. -func (state *golistState) createDriverResponse(words ...string) (*driverResponse, error) { +func (state *golistState) createDriverResponse(words ...string) (*DriverResponse, error) { // go list uses the following identifiers in ImportPath and Imports: // // "p" -- importable package or main (command) @@ -384,7 +383,7 @@ func (state *golistState) createDriverResponse(words ...string) (*driverResponse pkgs := make(map[string]*Package) additionalErrors := make(map[string][]Error) // Decode the JSON and convert it to Package form. - response := &driverResponse{ + response := &DriverResponse{ GoVersion: goVersion, } for dec := json.NewDecoder(buf); dec.More(); { @@ -842,6 +841,7 @@ func (state *golistState) cfgInvocation() gocommand.Invocation { Env: cfg.Env, Logf: cfg.Logf, WorkingDir: cfg.Dir, + Overlay: cfg.goListOverlayFile, } } @@ -850,26 +850,6 @@ func (state *golistState) invokeGo(verb string, args ...string) (*bytes.Buffer, cfg := state.cfg inv := state.cfgInvocation() - - // For Go versions 1.16 and above, `go list` accepts overlays directly via - // the -overlay flag. Set it, if it's available. - // - // The check for "list" is not necessarily required, but we should avoid - // getting the go version if possible. - if verb == "list" { - goVersion, err := state.getGoVersion() - if err != nil { - return nil, err - } - if goVersion >= 16 { - filename, cleanup, err := state.writeOverlays() - if err != nil { - return nil, err - } - defer cleanup() - inv.Overlay = filename - } - } inv.Verb = verb inv.Args = args gocmdRunner := cfg.gocmdRunner @@ -1016,67 +996,6 @@ func (state *golistState) invokeGo(verb string, args ...string) (*bytes.Buffer, return stdout, nil } -// OverlayJSON is the format overlay files are expected to be in. -// The Replace map maps from overlaid paths to replacement paths: -// the Go command will forward all reads trying to open -// each overlaid path to its replacement path, or consider the overlaid -// path not to exist if the replacement path is empty. -// -// From golang/go#39958. -type OverlayJSON struct { - Replace map[string]string `json:"replace,omitempty"` -} - -// writeOverlays writes out files for go list's -overlay flag, as described -// above. -func (state *golistState) writeOverlays() (filename string, cleanup func(), err error) { - // Do nothing if there are no overlays in the config. - if len(state.cfg.Overlay) == 0 { - return "", func() {}, nil - } - dir, err := os.MkdirTemp("", "gopackages-*") - if err != nil { - return "", nil, err - } - // The caller must clean up this directory, unless this function returns an - // error. - cleanup = func() { - os.RemoveAll(dir) - } - defer func() { - if err != nil { - cleanup() - } - }() - overlays := map[string]string{} - for k, v := range state.cfg.Overlay { - // Create a unique filename for the overlaid files, to avoid - // creating nested directories. - noSeparator := strings.Join(strings.Split(filepath.ToSlash(k), "/"), "") - f, err := os.CreateTemp(dir, fmt.Sprintf("*-%s", noSeparator)) - if err != nil { - return "", func() {}, err - } - if _, err := f.Write(v); err != nil { - return "", func() {}, err - } - if err := f.Close(); err != nil { - return "", func() {}, err - } - overlays[k] = f.Name() - } - b, err := json.Marshal(OverlayJSON{Replace: overlays}) - if err != nil { - return "", func() {}, err - } - // Write out the overlay file that contains the filepath mappings. - filename = filepath.Join(dir, "overlay.json") - if err := os.WriteFile(filename, b, 0665); err != nil { - return "", func() {}, err - } - return filename, cleanup, nil -} - func containsGoFile(s []string) bool { for _, f := range s { if strings.HasSuffix(f, ".go") { diff --git a/vendor/golang.org/x/tools/go/packages/packages.go b/vendor/golang.org/x/tools/go/packages/packages.go index 81e9e6a72..34306ddd3 100644 --- a/vendor/golang.org/x/tools/go/packages/packages.go +++ b/vendor/golang.org/x/tools/go/packages/packages.go @@ -9,6 +9,7 @@ package packages import ( "context" "encoding/json" + "errors" "fmt" "go/ast" "go/parser" @@ -24,6 +25,8 @@ import ( "sync" "time" + "golang.org/x/sync/errgroup" + "golang.org/x/tools/go/gcexportdata" "golang.org/x/tools/internal/gocommand" "golang.org/x/tools/internal/packagesinternal" @@ -34,10 +37,20 @@ import ( // A LoadMode controls the amount of detail to return when loading. // The bits below can be combined to specify which fields should be // filled in the result packages. +// // The zero value is a special case, equivalent to combining // the NeedName, NeedFiles, and NeedCompiledGoFiles bits. +// // ID and Errors (if present) will always be filled. -// Load may return more information than requested. +// [Load] may return more information than requested. +// +// Unfortunately there are a number of open bugs related to +// interactions among the LoadMode bits: +// - https://github.com/golang/go/issues/48226 +// - https://github.com/golang/go/issues/56633 +// - https://github.com/golang/go/issues/56677 +// - https://github.com/golang/go/issues/58726 +// - https://github.com/golang/go/issues/63517 type LoadMode int const ( @@ -120,15 +133,21 @@ const ( // A Config specifies details about how packages should be loaded. // The zero value is a valid configuration. +// // Calls to Load do not modify this struct. +// +// TODO(adonovan): #67702: this is currently false: in fact, +// calls to [Load] do not modify the public fields of this struct, but +// may modify hidden fields, so concurrent calls to [Load] must not +// use the same Config. But perhaps we should reestablish the +// documented invariant. type Config struct { // Mode controls the level of information returned for each package. Mode LoadMode // Context specifies the context for the load operation. - // If the context is cancelled, the loader may stop early - // and return an ErrCancelled error. - // If Context is nil, the load cannot be cancelled. + // Cancelling the context may cause [Load] to abort and + // return an error. Context context.Context // Logf is the logger for the config. @@ -197,50 +216,23 @@ type Config struct { // setting Tests may have no effect. Tests bool - // Overlay provides a mapping of absolute file paths to file contents. - // If the file with the given path already exists, the parser will use the - // alternative file contents provided by the map. + // Overlay is a mapping from absolute file paths to file contents. + // + // For each map entry, [Load] uses the alternative file + // contents provided by the overlay mapping instead of reading + // from the file system. This mechanism can be used to enable + // editor-integrated tools to correctly analyze the contents + // of modified but unsaved buffers, for example. // - // Overlays provide incomplete support for when a given file doesn't - // already exist on disk. See the package doc above for more details. + // The overlay mapping is passed to the build system's driver + // (see "The driver protocol") so that it too can report + // consistent package metadata about unsaved files. However, + // drivers may vary in their level of support for overlays. Overlay map[string][]byte -} -// driver is the type for functions that query the build system for the -// packages named by the patterns. -type driver func(cfg *Config, patterns ...string) (*driverResponse, error) - -// driverResponse contains the results for a driver query. -type driverResponse struct { - // NotHandled is returned if the request can't be handled by the current - // driver. If an external driver returns a response with NotHandled, the - // rest of the driverResponse is ignored, and go/packages will fallback - // to the next driver. If go/packages is extended in the future to support - // lists of multiple drivers, go/packages will fall back to the next driver. - NotHandled bool - - // Compiler and Arch are the arguments pass of types.SizesFor - // to get a types.Sizes to use when type checking. - Compiler string - Arch string - - // Roots is the set of package IDs that make up the root packages. - // We have to encode this separately because when we encode a single package - // we cannot know if it is one of the roots as that requires knowledge of the - // graph it is part of. - Roots []string `json:",omitempty"` - - // Packages is the full set of packages in the graph. - // The packages are not connected into a graph. - // The Imports if populated will be stubs that only have their ID set. - // Imports will be connected and then type and syntax information added in a - // later pass (see refine). - Packages []*Package - - // GoVersion is the minor version number used by the driver - // (e.g. the go command on the PATH) when selecting .go files. - // Zero means unknown. - GoVersion int + // goListOverlayFile is the JSON file that encodes the Overlay + // mapping, used by 'go list -overlay=...' + goListOverlayFile string } // Load loads and returns the Go packages named by the given patterns. @@ -248,8 +240,22 @@ type driverResponse struct { // Config specifies loading options; // nil behaves the same as an empty Config. // -// Load returns an error if any of the patterns was invalid -// as defined by the underlying build system. +// The [Config.Mode] field is a set of bits that determine what kinds +// of information should be computed and returned. Modes that require +// more information tend to be slower. See [LoadMode] for details +// and important caveats. Its zero value is equivalent to +// NeedName | NeedFiles | NeedCompiledGoFiles. +// +// Each call to Load returns a new set of [Package] instances. +// The Packages and their Imports form a directed acyclic graph. +// +// If the [NeedTypes] mode flag was set, each call to Load uses a new +// [types.Importer], so [types.Object] and [types.Type] values from +// different calls to Load must not be mixed as they will have +// inconsistent notions of type identity. +// +// If any of the patterns was invalid as defined by the +// underlying build system, Load returns an error. // It may return an empty list of packages without an error, // for instance for an empty expansion of a valid wildcard. // Errors associated with a particular package are recorded in the @@ -291,9 +297,28 @@ func Load(cfg *Config, patterns ...string) ([]*Package, error) { // no external driver, or the driver returns a response with NotHandled set, // defaultDriver will fall back to the go list driver. // The boolean result indicates that an external driver handled the request. -func defaultDriver(cfg *Config, patterns ...string) (*driverResponse, bool, error) { +func defaultDriver(cfg *Config, patterns ...string) (*DriverResponse, bool, error) { + const ( + // windowsArgMax specifies the maximum command line length for + // the Windows' CreateProcess function. + windowsArgMax = 32767 + // maxEnvSize is a very rough estimation of the maximum environment + // size of a user. + maxEnvSize = 16384 + // safeArgMax specifies the maximum safe command line length to use + // by the underlying driver excl. the environment. We choose the Windows' + // ARG_MAX as the starting point because it's one of the lowest ARG_MAX + // constants out of the different supported platforms, + // e.g., https://www.in-ulm.de/~mascheck/various/argmax/#results. + safeArgMax = windowsArgMax - maxEnvSize + ) + chunks, err := splitIntoChunks(patterns, safeArgMax) + if err != nil { + return nil, false, err + } + if driver := findExternalDriver(cfg); driver != nil { - response, err := driver(cfg, patterns...) + response, err := callDriverOnChunks(driver, cfg, chunks) if err != nil { return nil, false, err } else if !response.NotHandled { @@ -302,11 +327,99 @@ func defaultDriver(cfg *Config, patterns ...string) (*driverResponse, bool, erro // (fall through) } - response, err := goListDriver(cfg, patterns...) + // go list fallback + // + // Write overlays once, as there are many calls + // to 'go list' (one per chunk plus others too). + overlay, cleanupOverlay, err := gocommand.WriteOverlays(cfg.Overlay) + if err != nil { + return nil, false, err + } + defer cleanupOverlay() + cfg.goListOverlayFile = overlay + + response, err := callDriverOnChunks(goListDriver, cfg, chunks) + if err != nil { + return nil, false, err + } return response, false, err } +// splitIntoChunks chunks the slice so that the total number of characters +// in a chunk is no longer than argMax. +func splitIntoChunks(patterns []string, argMax int) ([][]string, error) { + if argMax <= 0 { + return nil, errors.New("failed to split patterns into chunks, negative safe argMax value") + } + var chunks [][]string + charsInChunk := 0 + nextChunkStart := 0 + for i, v := range patterns { + vChars := len(v) + if vChars > argMax { + // a single pattern is longer than the maximum safe ARG_MAX, hardly should happen + return nil, errors.New("failed to split patterns into chunks, a pattern is too long") + } + charsInChunk += vChars + 1 // +1 is for a whitespace between patterns that has to be counted too + if charsInChunk > argMax { + chunks = append(chunks, patterns[nextChunkStart:i]) + nextChunkStart = i + charsInChunk = vChars + } + } + // add the last chunk + if nextChunkStart < len(patterns) { + chunks = append(chunks, patterns[nextChunkStart:]) + } + return chunks, nil +} + +func callDriverOnChunks(driver driver, cfg *Config, chunks [][]string) (*DriverResponse, error) { + if len(chunks) == 0 { + return driver(cfg) + } + responses := make([]*DriverResponse, len(chunks)) + errNotHandled := errors.New("driver returned NotHandled") + var g errgroup.Group + for i, chunk := range chunks { + i := i + chunk := chunk + g.Go(func() (err error) { + responses[i], err = driver(cfg, chunk...) + if responses[i] != nil && responses[i].NotHandled { + err = errNotHandled + } + return err + }) + } + if err := g.Wait(); err != nil { + if errors.Is(err, errNotHandled) { + return &DriverResponse{NotHandled: true}, nil + } + return nil, err + } + return mergeResponses(responses...), nil +} + +func mergeResponses(responses ...*DriverResponse) *DriverResponse { + if len(responses) == 0 { + return nil + } + response := newDeduper() + response.dr.NotHandled = false + response.dr.Compiler = responses[0].Compiler + response.dr.Arch = responses[0].Arch + response.dr.GoVersion = responses[0].GoVersion + for _, v := range responses { + response.addAll(v) + } + return response.dr +} + // A Package describes a loaded Go package. +// +// It also defines part of the JSON schema of [DriverResponse]. +// See the package documentation for an overview. type Package struct { // ID is a unique identifier for a package, // in a syntax provided by the underlying build system. @@ -365,19 +478,30 @@ type Package struct { // to corresponding loaded Packages. Imports map[string]*Package + // Module is the module information for the package if it exists. + // + // Note: it may be missing for std and cmd; see Go issue #65816. + Module *Module + + // -- The following fields are not part of the driver JSON schema. -- + // Types provides type information for the package. // The NeedTypes LoadMode bit sets this field for packages matching the // patterns; type information for dependencies may be missing or incomplete, // unless NeedDeps and NeedImports are also set. - Types *types.Package + // + // Each call to [Load] returns a consistent set of type + // symbols, as defined by the comment at [types.Identical]. + // Avoid mixing type information from two or more calls to [Load]. + Types *types.Package `json:"-"` // Fset provides position information for Types, TypesInfo, and Syntax. // It is set only when Types is set. - Fset *token.FileSet + Fset *token.FileSet `json:"-"` // IllTyped indicates whether the package or any dependency contains errors. // It is set only when Types is set. - IllTyped bool + IllTyped bool `json:"-"` // Syntax is the package's syntax trees, for the files listed in CompiledGoFiles. // @@ -387,26 +511,28 @@ type Package struct { // // Syntax is kept in the same order as CompiledGoFiles, with the caveat that nils are // removed. If parsing returned nil, Syntax may be shorter than CompiledGoFiles. - Syntax []*ast.File + Syntax []*ast.File `json:"-"` // TypesInfo provides type information about the package's syntax trees. // It is set only when Syntax is set. - TypesInfo *types.Info + TypesInfo *types.Info `json:"-"` // TypesSizes provides the effective size function for types in TypesInfo. - TypesSizes types.Sizes + TypesSizes types.Sizes `json:"-"` + + // -- internal -- // forTest is the package under test, if any. forTest string // depsErrors is the DepsErrors field from the go list response, if any. depsErrors []*packagesinternal.PackageError - - // module is the module information for the package if it exists. - Module *Module } // Module provides module information for a package. +// +// It also defines part of the JSON schema of [DriverResponse]. +// See the package documentation for an overview. type Module struct { Path string // module path Version string // module version @@ -539,6 +665,7 @@ func (p *Package) UnmarshalJSON(b []byte) error { OtherFiles: flat.OtherFiles, EmbedFiles: flat.EmbedFiles, EmbedPatterns: flat.EmbedPatterns, + IgnoredFiles: flat.IgnoredFiles, ExportFile: flat.ExportFile, } if len(flat.Imports) > 0 { @@ -648,7 +775,7 @@ func newLoader(cfg *Config) *loader { // refine connects the supplied packages into a graph and then adds type // and syntax information as requested by the LoadMode. -func (ld *loader) refine(response *driverResponse) ([]*Package, error) { +func (ld *loader) refine(response *DriverResponse) ([]*Package, error) { roots := response.Roots rootMap := make(map[string]int, len(roots)) for i, root := range roots { @@ -795,6 +922,12 @@ func (ld *loader) refine(response *driverResponse) ([]*Package, error) { wg.Wait() } + // If the context is done, return its error and + // throw out [likely] incomplete packages. + if err := ld.Context.Err(); err != nil { + return nil, err + } + result := make([]*Package, len(initial)) for i, lpkg := range initial { result[i] = lpkg.Package @@ -890,6 +1023,14 @@ func (ld *loader) loadPackage(lpkg *loaderPackage) { lpkg.Types = types.NewPackage(lpkg.PkgPath, lpkg.Name) lpkg.Fset = ld.Fset + // Start shutting down if the context is done and do not load + // source or export data files. + // Packages that import this one will have ld.Context.Err() != nil. + // ld.Context.Err() will be returned later by refine. + if ld.Context.Err() != nil { + return + } + // Subtle: we populate all Types fields with an empty Package // before loading export data so that export data processing // never has to create a types.Package for an indirect dependency, @@ -1009,6 +1150,13 @@ func (ld *loader) loadPackage(lpkg *loaderPackage) { return } + // Start shutting down if the context is done and do not type check. + // Packages that import this one will have ld.Context.Err() != nil. + // ld.Context.Err() will be returned later by refine. + if ld.Context.Err() != nil { + return + } + lpkg.TypesInfo = &types.Info{ Types: make(map[ast.Expr]types.TypeAndValue), Defs: make(map[*ast.Ident]types.Object), @@ -1059,7 +1207,7 @@ func (ld *loader) loadPackage(lpkg *loaderPackage) { Sizes: ld.sizes, // may be nil } if lpkg.Module != nil && lpkg.Module.GoVersion != "" { - typesinternal.SetGoVersion(tc, "go"+lpkg.Module.GoVersion) + tc.GoVersion = "go" + lpkg.Module.GoVersion } if (ld.Mode & typecheckCgo) != 0 { if !typesinternal.SetUsesCgo(tc) { @@ -1070,10 +1218,24 @@ func (ld *loader) loadPackage(lpkg *loaderPackage) { return } } - types.NewChecker(tc, ld.Fset, lpkg.Types, lpkg.TypesInfo).Files(lpkg.Syntax) + typErr := types.NewChecker(tc, ld.Fset, lpkg.Types, lpkg.TypesInfo).Files(lpkg.Syntax) lpkg.importErrors = nil // no longer needed + // In go/types go1.21 and go1.22, Checker.Files failed fast with a + // a "too new" error, without calling tc.Error and without + // proceeding to type-check the package (#66525). + // We rely on the runtimeVersion error to give the suggested remedy. + if typErr != nil && len(lpkg.Errors) == 0 && len(lpkg.Syntax) > 0 { + if msg := typErr.Error(); strings.HasPrefix(msg, "package requires newer Go version") { + appendError(types.Error{ + Fset: ld.Fset, + Pos: lpkg.Syntax[0].Package, + Msg: msg, + }) + } + } + // If !Cgo, the type-checker uses FakeImportC mode, so // it doesn't invoke the importer for import "C", // nor report an error for the import, @@ -1095,6 +1257,12 @@ func (ld *loader) loadPackage(lpkg *loaderPackage) { } } + // If types.Checker.Files had an error that was unreported, + // make sure to report the unknown error so the package is illTyped. + if typErr != nil && len(lpkg.Errors) == 0 { + appendError(typErr) + } + // Record accumulated errors. illTyped := len(lpkg.Errors) > 0 if !illTyped { @@ -1166,11 +1334,6 @@ func (ld *loader) parseFiles(filenames []string) ([]*ast.File, []error) { parsed := make([]*ast.File, n) errors := make([]error, n) for i, file := range filenames { - if ld.Config.Context.Err() != nil { - parsed[i] = nil - errors[i] = ld.Config.Context.Err() - continue - } wg.Add(1) go func(i int, filename string) { parsed[i], errors[i] = ld.parseFile(filename) diff --git a/vendor/golang.org/x/tools/go/types/objectpath/objectpath.go b/vendor/golang.org/x/tools/go/types/objectpath/objectpath.go index 11d5c8c3a..a2386c347 100644 --- a/vendor/golang.org/x/tools/go/types/objectpath/objectpath.go +++ b/vendor/golang.org/x/tools/go/types/objectpath/objectpath.go @@ -29,9 +29,12 @@ import ( "strconv" "strings" - "golang.org/x/tools/internal/typeparams" + "golang.org/x/tools/internal/aliases" + "golang.org/x/tools/internal/typesinternal" ) +// TODO(adonovan): think about generic aliases. + // A Path is an opaque name that identifies a types.Object // relative to its package. Conceptually, the name consists of a // sequence of destructuring operations applied to the package scope @@ -223,7 +226,7 @@ func (enc *Encoder) For(obj types.Object) (Path, error) { // Reject obviously non-viable cases. switch obj := obj.(type) { case *types.TypeName: - if _, ok := obj.Type().(*types.TypeParam); !ok { + if _, ok := aliases.Unalias(obj.Type()).(*types.TypeParam); !ok { // With the exception of type parameters, only package-level type names // have a path. return "", fmt.Errorf("no path for %v", obj) @@ -310,7 +313,7 @@ func (enc *Encoder) For(obj types.Object) (Path, error) { } // Inspect declared methods of defined types. - if T, ok := o.Type().(*types.Named); ok { + if T, ok := aliases.Unalias(o.Type()).(*types.Named); ok { path = append(path, opType) // The method index here is always with respect // to the underlying go/types data structures, @@ -391,17 +394,12 @@ func (enc *Encoder) concreteMethod(meth *types.Func) (Path, bool) { // of objectpath will only be giving us origin methods, anyway, as referring // to instantiated methods is usually not useful. - if typeparams.OriginMethod(meth) != meth { + if meth.Origin() != meth { return "", false } - recvT := meth.Type().(*types.Signature).Recv().Type() - if ptr, ok := recvT.(*types.Pointer); ok { - recvT = ptr.Elem() - } - - named, ok := recvT.(*types.Named) - if !ok { + _, named := typesinternal.ReceiverNamed(meth.Type().(*types.Signature).Recv()) + if named == nil { return "", false } @@ -444,6 +442,8 @@ func (enc *Encoder) concreteMethod(meth *types.Func) (Path, bool) { // nil, it will be allocated as necessary. func find(obj types.Object, T types.Type, path []byte, seen map[*types.TypeName]bool) []byte { switch T := T.(type) { + case *aliases.Alias: + return find(obj, aliases.Unalias(T), path, seen) case *types.Basic, *types.Named: // Named types belonging to pkg were handled already, // so T must belong to another package. No path. @@ -616,6 +616,7 @@ func Object(pkg *types.Package, p Path) (types.Object, error) { // Inv: t != nil, obj == nil + t = aliases.Unalias(t) switch code { case opElem: hasElem, ok := t.(hasElem) // Pointer, Slice, Array, Chan, Map diff --git a/vendor/golang.org/x/tools/internal/aliases/aliases.go b/vendor/golang.org/x/tools/internal/aliases/aliases.go new file mode 100644 index 000000000..c24c2eee4 --- /dev/null +++ b/vendor/golang.org/x/tools/internal/aliases/aliases.go @@ -0,0 +1,32 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package aliases + +import ( + "go/token" + "go/types" +) + +// Package aliases defines backward compatible shims +// for the types.Alias type representation added in 1.22. +// This defines placeholders for x/tools until 1.26. + +// NewAlias creates a new TypeName in Package pkg that +// is an alias for the type rhs. +// +// The enabled parameter determines whether the resulting [TypeName]'s +// type is an [types.Alias]. Its value must be the result of a call to +// [Enabled], which computes the effective value of +// GODEBUG=gotypesalias=... by invoking the type checker. The Enabled +// function is expensive and should be called once per task (e.g. +// package import), not once per call to NewAlias. +func NewAlias(enabled bool, pos token.Pos, pkg *types.Package, name string, rhs types.Type) *types.TypeName { + if enabled { + tname := types.NewTypeName(pos, pkg, name, nil) + newAlias(tname, rhs) + return tname + } + return types.NewTypeName(pos, pkg, name, rhs) +} diff --git a/vendor/golang.org/x/tools/internal/aliases/aliases_go121.go b/vendor/golang.org/x/tools/internal/aliases/aliases_go121.go new file mode 100644 index 000000000..c027b9f31 --- /dev/null +++ b/vendor/golang.org/x/tools/internal/aliases/aliases_go121.go @@ -0,0 +1,31 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !go1.22 +// +build !go1.22 + +package aliases + +import ( + "go/types" +) + +// Alias is a placeholder for a go/types.Alias for <=1.21. +// It will never be created by go/types. +type Alias struct{} + +func (*Alias) String() string { panic("unreachable") } +func (*Alias) Underlying() types.Type { panic("unreachable") } +func (*Alias) Obj() *types.TypeName { panic("unreachable") } +func Rhs(alias *Alias) types.Type { panic("unreachable") } + +// Unalias returns the type t for go <=1.21. +func Unalias(t types.Type) types.Type { return t } + +func newAlias(name *types.TypeName, rhs types.Type) *Alias { panic("unreachable") } + +// Enabled reports whether [NewAlias] should create [types.Alias] types. +// +// Before go1.22, this function always returns false. +func Enabled() bool { return false } diff --git a/vendor/golang.org/x/tools/internal/aliases/aliases_go122.go b/vendor/golang.org/x/tools/internal/aliases/aliases_go122.go new file mode 100644 index 000000000..b32995484 --- /dev/null +++ b/vendor/golang.org/x/tools/internal/aliases/aliases_go122.go @@ -0,0 +1,63 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build go1.22 +// +build go1.22 + +package aliases + +import ( + "go/ast" + "go/parser" + "go/token" + "go/types" +) + +// Alias is an alias of types.Alias. +type Alias = types.Alias + +// Rhs returns the type on the right-hand side of the alias declaration. +func Rhs(alias *Alias) types.Type { + if alias, ok := any(alias).(interface{ Rhs() types.Type }); ok { + return alias.Rhs() // go1.23+ + } + + // go1.22's Alias didn't have the Rhs method, + // so Unalias is the best we can do. + return Unalias(alias) +} + +// Unalias is a wrapper of types.Unalias. +func Unalias(t types.Type) types.Type { return types.Unalias(t) } + +// newAlias is an internal alias around types.NewAlias. +// Direct usage is discouraged as the moment. +// Try to use NewAlias instead. +func newAlias(tname *types.TypeName, rhs types.Type) *Alias { + a := types.NewAlias(tname, rhs) + // TODO(go.dev/issue/65455): Remove kludgy workaround to set a.actual as a side-effect. + Unalias(a) + return a +} + +// Enabled reports whether [NewAlias] should create [types.Alias] types. +// +// This function is expensive! Call it sparingly. +func Enabled() bool { + // The only reliable way to compute the answer is to invoke go/types. + // We don't parse the GODEBUG environment variable, because + // (a) it's tricky to do so in a manner that is consistent + // with the godebug package; in particular, a simple + // substring check is not good enough. The value is a + // rightmost-wins list of options. But more importantly: + // (b) it is impossible to detect changes to the effective + // setting caused by os.Setenv("GODEBUG"), as happens in + // many tests. Therefore any attempt to cache the result + // is just incorrect. + fset := token.NewFileSet() + f, _ := parser.ParseFile(fset, "a.go", "package p; type A = int", 0) + pkg, _ := new(types.Config).Check("p", fset, []*ast.File{f}, nil) + _, enabled := pkg.Scope().Lookup("A").Type().(*types.Alias) + return enabled +} diff --git a/vendor/golang.org/x/tools/internal/event/tag/tag.go b/vendor/golang.org/x/tools/internal/event/tag/tag.go deleted file mode 100644 index 581b26c20..000000000 --- a/vendor/golang.org/x/tools/internal/event/tag/tag.go +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package tag provides the labels used for telemetry throughout gopls. -package tag - -import ( - "golang.org/x/tools/internal/event/keys" -) - -var ( - // create the label keys we use - Method = keys.NewString("method", "") - StatusCode = keys.NewString("status.code", "") - StatusMessage = keys.NewString("status.message", "") - RPCID = keys.NewString("id", "") - RPCDirection = keys.NewString("direction", "") - File = keys.NewString("file", "") - Directory = keys.New("directory", "") - URI = keys.New("URI", "") - Package = keys.NewString("package", "") // sorted comma-separated list of Package IDs - PackagePath = keys.NewString("package_path", "") - Query = keys.New("query", "") - Snapshot = keys.NewUInt64("snapshot", "") - Operation = keys.NewString("operation", "") - - Position = keys.New("position", "") - Category = keys.NewString("category", "") - PackageCount = keys.NewInt("packages", "") - Files = keys.New("files", "") - Port = keys.NewInt("port", "") - Type = keys.New("type", "") - HoverKind = keys.NewString("hoverkind", "") - - NewServer = keys.NewString("new_server", "A new server was added") - EndServer = keys.NewString("end_server", "A server was shut down") - - ServerID = keys.NewString("server", "The server ID an event is related to") - Logfile = keys.NewString("logfile", "") - DebugAddress = keys.NewString("debug_address", "") - GoplsPath = keys.NewString("gopls_path", "") - ClientID = keys.NewString("client_id", "") - - Level = keys.NewInt("level", "The logging level") -) - -var ( - // create the stats we measure - Started = keys.NewInt64("started", "Count of started RPCs.") - ReceivedBytes = keys.NewInt64("received_bytes", "Bytes received.") //, unit.Bytes) - SentBytes = keys.NewInt64("sent_bytes", "Bytes sent.") //, unit.Bytes) - Latency = keys.NewFloat64("latency_ms", "Elapsed time in milliseconds") //, unit.Milliseconds) -) - -const ( - Inbound = "in" - Outbound = "out" -) diff --git a/vendor/golang.org/x/tools/internal/gcimporter/gcimporter.go b/vendor/golang.org/x/tools/internal/gcimporter/gcimporter.go index 2d078ccb1..39df91124 100644 --- a/vendor/golang.org/x/tools/internal/gcimporter/gcimporter.go +++ b/vendor/golang.org/x/tools/internal/gcimporter/gcimporter.go @@ -259,13 +259,6 @@ func Import(packages map[string]*types.Package, path, srcDir string, lookup func return } -func deref(typ types.Type) types.Type { - if p, _ := typ.(*types.Pointer); p != nil { - return p.Elem() - } - return typ -} - type byPath []*types.Package func (a byPath) Len() int { return len(a) } diff --git a/vendor/golang.org/x/tools/internal/gcimporter/iexport.go b/vendor/golang.org/x/tools/internal/gcimporter/iexport.go index 2ee8c7016..deeb67f31 100644 --- a/vendor/golang.org/x/tools/internal/gcimporter/iexport.go +++ b/vendor/golang.org/x/tools/internal/gcimporter/iexport.go @@ -23,6 +23,7 @@ import ( "strings" "golang.org/x/tools/go/types/objectpath" + "golang.org/x/tools/internal/aliases" "golang.org/x/tools/internal/tokeninternal" ) @@ -463,7 +464,7 @@ func (p *iexporter) doDecl(obj types.Object) { switch obj := obj.(type) { case *types.Var: - w.tag('V') + w.tag(varTag) w.pos(obj.Pos()) w.typ(obj.Type(), obj.Pkg()) @@ -481,9 +482,9 @@ func (p *iexporter) doDecl(obj types.Object) { // Function. if sig.TypeParams().Len() == 0 { - w.tag('F') + w.tag(funcTag) } else { - w.tag('G') + w.tag(genericFuncTag) } w.pos(obj.Pos()) // The tparam list of the function type is the declaration of the type @@ -499,20 +500,20 @@ func (p *iexporter) doDecl(obj types.Object) { w.signature(sig) case *types.Const: - w.tag('C') + w.tag(constTag) w.pos(obj.Pos()) w.value(obj.Type(), obj.Val()) case *types.TypeName: t := obj.Type() - if tparam, ok := t.(*types.TypeParam); ok { - w.tag('P') + if tparam, ok := aliases.Unalias(t).(*types.TypeParam); ok { + w.tag(typeParamTag) w.pos(obj.Pos()) constraint := tparam.Constraint() if p.version >= iexportVersionGo1_18 { implicit := false - if iface, _ := constraint.(*types.Interface); iface != nil { + if iface, _ := aliases.Unalias(constraint).(*types.Interface); iface != nil { implicit = iface.IsImplicit() } w.bool(implicit) @@ -522,8 +523,13 @@ func (p *iexporter) doDecl(obj types.Object) { } if obj.IsAlias() { - w.tag('A') + w.tag(aliasTag) w.pos(obj.Pos()) + if alias, ok := t.(*aliases.Alias); ok { + // Preserve materialized aliases, + // even of non-exported types. + t = aliases.Rhs(alias) + } w.typ(t, obj.Pkg()) break } @@ -535,9 +541,9 @@ func (p *iexporter) doDecl(obj types.Object) { } if named.TypeParams().Len() == 0 { - w.tag('T') + w.tag(typeTag) } else { - w.tag('U') + w.tag(genericTypeTag) } w.pos(obj.Pos()) @@ -547,7 +553,7 @@ func (p *iexporter) doDecl(obj types.Object) { w.tparamList(obj.Name(), named.TypeParams(), obj.Pkg()) } - underlying := obj.Type().Underlying() + underlying := named.Underlying() w.typ(underlying, obj.Pkg()) if types.IsInterface(t) { @@ -738,6 +744,11 @@ func (w *exportWriter) doTyp(t types.Type, pkg *types.Package) { }() } switch t := t.(type) { + case *aliases.Alias: + // TODO(adonovan): support parameterized aliases, following *types.Named. + w.startType(aliasType) + w.qualifiedType(t.Obj()) + case *types.Named: if targs := t.TypeArgs(); targs.Len() > 0 { w.startType(instanceType) @@ -843,7 +854,7 @@ func (w *exportWriter) doTyp(t types.Type, pkg *types.Package) { for i := 0; i < n; i++ { ft := t.EmbeddedType(i) tPkg := pkg - if named, _ := ft.(*types.Named); named != nil { + if named, _ := aliases.Unalias(ft).(*types.Named); named != nil { w.pos(named.Obj().Pos()) } else { w.pos(token.NoPos) diff --git a/vendor/golang.org/x/tools/internal/gcimporter/iimport.go b/vendor/golang.org/x/tools/internal/gcimporter/iimport.go index 9bde15e3b..136aa0365 100644 --- a/vendor/golang.org/x/tools/internal/gcimporter/iimport.go +++ b/vendor/golang.org/x/tools/internal/gcimporter/iimport.go @@ -22,6 +22,8 @@ import ( "strings" "golang.org/x/tools/go/types/objectpath" + "golang.org/x/tools/internal/aliases" + "golang.org/x/tools/internal/typesinternal" ) type intReader struct { @@ -78,6 +80,20 @@ const ( typeParamType instanceType unionType + aliasType +) + +// Object tags +const ( + varTag = 'V' + funcTag = 'F' + genericFuncTag = 'G' + constTag = 'C' + aliasTag = 'A' + genericAliasTag = 'B' + typeParamTag = 'P' + typeTag = 'T' + genericTypeTag = 'U' ) // IImportData imports a package from the serialized package data @@ -194,6 +210,7 @@ func iimportCommon(fset *token.FileSet, getPackages GetPackagesFunc, data []byte p := iimporter{ version: int(version), ipath: path, + aliases: aliases.Enabled(), shallow: shallow, reportf: reportf, @@ -224,6 +241,7 @@ func iimportCommon(fset *token.FileSet, getPackages GetPackagesFunc, data []byte // Gather the relevant packages from the manifest. items := make([]GetPackagesItem, r.uint64()) + uniquePkgPaths := make(map[string]bool) for i := range items { pkgPathOff := r.uint64() pkgPath := p.stringAt(pkgPathOff) @@ -248,6 +266,12 @@ func iimportCommon(fset *token.FileSet, getPackages GetPackagesFunc, data []byte } items[i].nameIndex = nameIndex + + uniquePkgPaths[pkgPath] = true + } + // Debugging #63822; hypothesis: there are duplicate PkgPaths. + if len(uniquePkgPaths) != len(items) { + reportf("found duplicate PkgPaths while reading export data manifest: %v", items) } // Request packages all at once from the client, @@ -315,7 +339,7 @@ func iimportCommon(fset *token.FileSet, getPackages GetPackagesFunc, data []byte } // SetConstraint can't be called if the constraint type is not yet complete. - // When type params are created in the 'P' case of (*importReader).obj(), + // When type params are created in the typeParamTag case of (*importReader).obj(), // the associated constraint type may not be complete due to recursion. // Therefore, we defer calling SetConstraint there, and call it here instead // after all types are complete. @@ -346,6 +370,7 @@ type iimporter struct { version int ipath string + aliases bool shallow bool reportf ReportFunc // if non-nil, used to report bugs @@ -515,7 +540,7 @@ func canReuse(def *types.Named, rhs types.Type) bool { if def == nil { return true } - iface, _ := rhs.(*types.Interface) + iface, _ := aliases.Unalias(rhs).(*types.Interface) if iface == nil { return true } @@ -537,25 +562,29 @@ func (r *importReader) obj(name string) { pos := r.pos() switch tag { - case 'A': + case aliasTag: typ := r.typ() - - r.declare(types.NewTypeName(pos, r.currPkg, name, typ)) - - case 'C': + // TODO(adonovan): support generic aliases: + // if tag == genericAliasTag { + // tparams := r.tparamList() + // alias.SetTypeParams(tparams) + // } + r.declare(aliases.NewAlias(r.p.aliases, pos, r.currPkg, name, typ)) + + case constTag: typ, val := r.value() r.declare(types.NewConst(pos, r.currPkg, name, typ, val)) - case 'F', 'G': + case funcTag, genericFuncTag: var tparams []*types.TypeParam - if tag == 'G' { + if tag == genericFuncTag { tparams = r.tparamList() } sig := r.signature(nil, nil, tparams) r.declare(types.NewFunc(pos, r.currPkg, name, sig)) - case 'T', 'U': + case typeTag, genericTypeTag: // Types can be recursive. We need to setup a stub // declaration before recursing. obj := types.NewTypeName(pos, r.currPkg, name, nil) @@ -563,7 +592,7 @@ func (r *importReader) obj(name string) { // Declare obj before calling r.tparamList, so the new type name is recognized // if used in the constraint of one of its own typeparams (see #48280). r.declare(obj) - if tag == 'U' { + if tag == genericTypeTag { tparams := r.tparamList() named.SetTypeParams(tparams) } @@ -580,14 +609,13 @@ func (r *importReader) obj(name string) { // If the receiver has any targs, set those as the // rparams of the method (since those are the // typeparams being used in the method sig/body). - base := baseType(recv.Type()) - assert(base != nil) - targs := base.TypeArgs() + _, recvNamed := typesinternal.ReceiverNamed(recv) + targs := recvNamed.TypeArgs() var rparams []*types.TypeParam if targs.Len() > 0 { rparams = make([]*types.TypeParam, targs.Len()) for i := range rparams { - rparams[i] = targs.At(i).(*types.TypeParam) + rparams[i] = aliases.Unalias(targs.At(i)).(*types.TypeParam) } } msig := r.signature(recv, rparams, nil) @@ -596,7 +624,7 @@ func (r *importReader) obj(name string) { } } - case 'P': + case typeParamTag: // We need to "declare" a typeparam in order to have a name that // can be referenced recursively (if needed) in the type param's // bound. @@ -617,7 +645,7 @@ func (r *importReader) obj(name string) { } constraint := r.typ() if implicit { - iface, _ := constraint.(*types.Interface) + iface, _ := aliases.Unalias(constraint).(*types.Interface) if iface == nil { errorf("non-interface constraint marked implicit") } @@ -629,7 +657,7 @@ func (r *importReader) obj(name string) { // completely set up all types in ImportData. r.p.later = append(r.p.later, setConstraintArgs{t: t, constraint: constraint}) - case 'V': + case varTag: typ := r.typ() r.declare(types.NewVar(pos, r.currPkg, name, typ)) @@ -824,7 +852,7 @@ func (r *importReader) typ() types.Type { } func isInterface(t types.Type) bool { - _, ok := t.(*types.Interface) + _, ok := aliases.Unalias(t).(*types.Interface) return ok } @@ -846,7 +874,7 @@ func (r *importReader) doType(base *types.Named) (res types.Type) { errorf("unexpected kind tag in %q: %v", r.p.ipath, k) return nil - case definedType: + case aliasType, definedType: pkg, name := r.qualifiedIdent() r.p.doDecl(pkg, name) return pkg.Scope().Lookup(name).(*types.TypeName).Type() @@ -1023,7 +1051,7 @@ func (r *importReader) tparamList() []*types.TypeParam { for i := range xs { // Note: the standard library importer is tolerant of nil types here, // though would panic in SetTypeParams. - xs[i] = r.typ().(*types.TypeParam) + xs[i] = aliases.Unalias(r.typ()).(*types.TypeParam) } return xs } @@ -1070,13 +1098,3 @@ func (r *importReader) byte() byte { } return x } - -func baseType(typ types.Type) *types.Named { - // pointer receivers are never types.Named types - if p, _ := typ.(*types.Pointer); p != nil { - typ = p.Elem() - } - // receiver base types are always (possibly generic) types.Named types - n, _ := typ.(*types.Named) - return n -} diff --git a/vendor/golang.org/x/tools/internal/gcimporter/support_go117.go b/vendor/golang.org/x/tools/internal/gcimporter/support_go117.go deleted file mode 100644 index d892273ef..000000000 --- a/vendor/golang.org/x/tools/internal/gcimporter/support_go117.go +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2021 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !go1.18 -// +build !go1.18 - -package gcimporter - -import "go/types" - -const iexportVersion = iexportVersionGo1_11 - -func additionalPredeclared() []types.Type { - return nil -} diff --git a/vendor/golang.org/x/tools/internal/gcimporter/support_go118.go b/vendor/golang.org/x/tools/internal/gcimporter/support_go118.go index edbe6ea70..0cd3b91b6 100644 --- a/vendor/golang.org/x/tools/internal/gcimporter/support_go118.go +++ b/vendor/golang.org/x/tools/internal/gcimporter/support_go118.go @@ -2,9 +2,6 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build go1.18 -// +build go1.18 - package gcimporter import "go/types" diff --git a/vendor/golang.org/x/tools/internal/gcimporter/unified_no.go b/vendor/golang.org/x/tools/internal/gcimporter/unified_no.go index 286bf4454..38b624cad 100644 --- a/vendor/golang.org/x/tools/internal/gcimporter/unified_no.go +++ b/vendor/golang.org/x/tools/internal/gcimporter/unified_no.go @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build !(go1.18 && goexperiment.unified) -// +build !go1.18 !goexperiment.unified +//go:build !goexperiment.unified +// +build !goexperiment.unified package gcimporter diff --git a/vendor/golang.org/x/tools/internal/gcimporter/unified_yes.go b/vendor/golang.org/x/tools/internal/gcimporter/unified_yes.go index b5d69ffbe..b5118d0b3 100644 --- a/vendor/golang.org/x/tools/internal/gcimporter/unified_yes.go +++ b/vendor/golang.org/x/tools/internal/gcimporter/unified_yes.go @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build go1.18 && goexperiment.unified -// +build go1.18,goexperiment.unified +//go:build goexperiment.unified +// +build goexperiment.unified package gcimporter diff --git a/vendor/golang.org/x/tools/internal/gcimporter/ureader_no.go b/vendor/golang.org/x/tools/internal/gcimporter/ureader_no.go deleted file mode 100644 index 8eb20729c..000000000 --- a/vendor/golang.org/x/tools/internal/gcimporter/ureader_no.go +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !go1.18 -// +build !go1.18 - -package gcimporter - -import ( - "fmt" - "go/token" - "go/types" -) - -func UImportData(fset *token.FileSet, imports map[string]*types.Package, data []byte, path string) (_ int, pkg *types.Package, err error) { - err = fmt.Errorf("go/tools compiled with a Go version earlier than 1.18 cannot read unified IR export data") - return -} diff --git a/vendor/golang.org/x/tools/internal/gcimporter/ureader_yes.go b/vendor/golang.org/x/tools/internal/gcimporter/ureader_yes.go index b977435f6..2c0770688 100644 --- a/vendor/golang.org/x/tools/internal/gcimporter/ureader_yes.go +++ b/vendor/golang.org/x/tools/internal/gcimporter/ureader_yes.go @@ -4,9 +4,6 @@ // Derived from go/internal/gcimporter/ureader.go -//go:build go1.18 -// +build go1.18 - package gcimporter import ( @@ -16,6 +13,7 @@ import ( "sort" "strings" + "golang.org/x/tools/internal/aliases" "golang.org/x/tools/internal/pkgbits" ) @@ -28,6 +26,7 @@ type pkgReader struct { ctxt *types.Context imports map[string]*types.Package // previously imported packages, indexed by path + aliases bool // create types.Alias nodes // lazily initialized arrays corresponding to the unified IR // PosBase, Pkg, and Type sections, respectively. @@ -101,6 +100,7 @@ func readUnifiedPackage(fset *token.FileSet, ctxt *types.Context, imports map[st ctxt: ctxt, imports: imports, + aliases: aliases.Enabled(), posBases: make([]string, input.NumElems(pkgbits.RelocPosBase)), pkgs: make([]*types.Package, input.NumElems(pkgbits.RelocPkg)), @@ -526,7 +526,7 @@ func (pr *pkgReader) objIdx(idx pkgbits.Index) (*types.Package, string) { case pkgbits.ObjAlias: pos := r.pos() typ := r.typ() - declare(types.NewTypeName(pos, objPkg, objName, typ)) + declare(aliases.NewAlias(r.p.aliases, pos, objPkg, objName, typ)) case pkgbits.ObjConst: pos := r.pos() @@ -553,7 +553,7 @@ func (pr *pkgReader) objIdx(idx pkgbits.Index) (*types.Package, string) { // If the underlying type is an interface, we need to // duplicate its methods so we can replace the receiver // parameter's type (#49906). - if iface, ok := underlying.(*types.Interface); ok && iface.NumExplicitMethods() != 0 { + if iface, ok := aliases.Unalias(underlying).(*types.Interface); ok && iface.NumExplicitMethods() != 0 { methods := make([]*types.Func, iface.NumExplicitMethods()) for i := range methods { fn := iface.ExplicitMethod(i) diff --git a/vendor/golang.org/x/tools/internal/gocommand/invoke.go b/vendor/golang.org/x/tools/internal/gocommand/invoke.go index 55312522d..af0ee6c61 100644 --- a/vendor/golang.org/x/tools/internal/gocommand/invoke.go +++ b/vendor/golang.org/x/tools/internal/gocommand/invoke.go @@ -8,12 +8,14 @@ package gocommand import ( "bytes" "context" + "encoding/json" "errors" "fmt" "io" "log" "os" "os/exec" + "path/filepath" "reflect" "regexp" "runtime" @@ -25,7 +27,6 @@ import ( "golang.org/x/tools/internal/event" "golang.org/x/tools/internal/event/keys" "golang.org/x/tools/internal/event/label" - "golang.org/x/tools/internal/event/tag" ) // An Runner will run go command invocations and serialize @@ -55,11 +56,14 @@ func (runner *Runner) initialize() { // 1.14: go: updating go.mod: existing contents have changed since last read var modConcurrencyError = regexp.MustCompile(`go:.*go.mod.*contents have changed`) -// verb is an event label for the go command verb. -var verb = keys.NewString("verb", "go command verb") +// event keys for go command invocations +var ( + verb = keys.NewString("verb", "go command verb") + directory = keys.NewString("directory", "") +) func invLabels(inv Invocation) []label.Label { - return []label.Label{verb.Of(inv.Verb), tag.Directory.Of(inv.WorkingDir)} + return []label.Label{verb.Of(inv.Verb), directory.Of(inv.WorkingDir)} } // Run is a convenience wrapper around RunRaw. @@ -158,12 +162,17 @@ type Invocation struct { BuildFlags []string // If ModFlag is set, the go command is invoked with -mod=ModFlag. + // TODO(rfindley): remove, in favor of Args. ModFlag string // If ModFile is set, the go command is invoked with -modfile=ModFile. + // TODO(rfindley): remove, in favor of Args. ModFile string - // If Overlay is set, the go command is invoked with -overlay=Overlay. + // Overlay is the name of the JSON overlay file that describes + // unsaved editor buffers; see [WriteOverlays]. + // If set, the go command is invoked with -overlay=Overlay. + // TODO(rfindley): remove, in favor of Args. Overlay string // If CleanEnv is set, the invocation will run only with the environment @@ -250,12 +259,15 @@ func (i *Invocation) run(ctx context.Context, stdout, stderr io.Writer) error { waitDelay.Set(reflect.ValueOf(30 * time.Second)) } - // On darwin the cwd gets resolved to the real path, which breaks anything that - // expects the working directory to keep the original path, including the + // The cwd gets resolved to the real path. On Darwin, where + // /tmp is a symlink, this breaks anything that expects the + // working directory to keep the original path, including the // go command when dealing with modules. - // The Go stdlib has a special feature where if the cwd and the PWD are the - // same node then it trusts the PWD, so by setting it in the env for the child - // process we fix up all the paths returned by the go command. + // + // os.Getwd has a special feature where if the cwd and the PWD + // are the same node then it trusts the PWD, so by setting it + // in the env for the child process we fix up all the paths + // returned by the go command. if !i.CleanEnv { cmd.Env = os.Environ() } @@ -346,6 +358,7 @@ func runCmdContext(ctx context.Context, cmd *exec.Cmd) (err error) { } } + startTime := time.Now() err = cmd.Start() if stdoutW != nil { // The child process has inherited the pipe file, @@ -372,7 +385,7 @@ func runCmdContext(ctx context.Context, cmd *exec.Cmd) (err error) { case err := <-resChan: return err case <-timer.C: - HandleHangingGoCommand(cmd.Process) + HandleHangingGoCommand(startTime, cmd) case <-ctx.Done(): } } else { @@ -406,7 +419,7 @@ func runCmdContext(ctx context.Context, cmd *exec.Cmd) (err error) { return <-resChan } -func HandleHangingGoCommand(proc *os.Process) { +func HandleHangingGoCommand(start time.Time, cmd *exec.Cmd) { switch runtime.GOOS { case "linux", "darwin", "freebsd", "netbsd": fmt.Fprintln(os.Stderr, `DETECTED A HANGING GO COMMAND @@ -439,7 +452,7 @@ See golang/go#54461 for more details.`) panic(fmt.Sprintf("running %s: %v", listFiles, err)) } } - panic(fmt.Sprintf("detected hanging go command (pid %d): see golang/go#54461 for more details", proc.Pid)) + panic(fmt.Sprintf("detected hanging go command (golang/go#54461); waited %s\n\tcommand:%s\n\tpid:%d", time.Since(start), cmd, cmd.Process.Pid)) } func cmdDebugStr(cmd *exec.Cmd) string { @@ -463,3 +476,73 @@ func cmdDebugStr(cmd *exec.Cmd) string { } return fmt.Sprintf("GOROOT=%v GOPATH=%v GO111MODULE=%v GOPROXY=%v PWD=%v %v", env["GOROOT"], env["GOPATH"], env["GO111MODULE"], env["GOPROXY"], env["PWD"], strings.Join(args, " ")) } + +// WriteOverlays writes each value in the overlay (see the Overlay +// field of go/packages.Config) to a temporary file and returns the name +// of a JSON file describing the mapping that is suitable for the "go +// list -overlay" flag. +// +// On success, the caller must call the cleanup function exactly once +// when the files are no longer needed. +func WriteOverlays(overlay map[string][]byte) (filename string, cleanup func(), err error) { + // Do nothing if there are no overlays in the config. + if len(overlay) == 0 { + return "", func() {}, nil + } + + dir, err := os.MkdirTemp("", "gocommand-*") + if err != nil { + return "", nil, err + } + + // The caller must clean up this directory, + // unless this function returns an error. + // (The cleanup operand of each return + // statement below is ignored.) + defer func() { + cleanup = func() { + os.RemoveAll(dir) + } + if err != nil { + cleanup() + cleanup = nil + } + }() + + // Write each map entry to a temporary file. + overlays := make(map[string]string) + for k, v := range overlay { + // Use a unique basename for each file (001-foo.go), + // to avoid creating nested directories. + base := fmt.Sprintf("%d-%s.go", 1+len(overlays), filepath.Base(k)) + filename := filepath.Join(dir, base) + err := os.WriteFile(filename, v, 0666) + if err != nil { + return "", nil, err + } + overlays[k] = filename + } + + // Write the JSON overlay file that maps logical file names to temp files. + // + // OverlayJSON is the format overlay files are expected to be in. + // The Replace map maps from overlaid paths to replacement paths: + // the Go command will forward all reads trying to open + // each overlaid path to its replacement path, or consider the overlaid + // path not to exist if the replacement path is empty. + // + // From golang/go#39958. + type OverlayJSON struct { + Replace map[string]string `json:"replace,omitempty"` + } + b, err := json.Marshal(OverlayJSON{Replace: overlays}) + if err != nil { + return "", nil, err + } + filename = filepath.Join(dir, "overlay.json") + if err := os.WriteFile(filename, b, 0666); err != nil { + return "", nil, err + } + + return filename, nil, nil +} diff --git a/vendor/golang.org/x/tools/internal/gocommand/vendor.go b/vendor/golang.org/x/tools/internal/gocommand/vendor.go index 2d3d408c0..e38d1fb48 100644 --- a/vendor/golang.org/x/tools/internal/gocommand/vendor.go +++ b/vendor/golang.org/x/tools/internal/gocommand/vendor.go @@ -107,3 +107,57 @@ func getMainModuleAnd114(ctx context.Context, inv Invocation, r *Runner) (*Modul } return mod, lines[4] == "go1.14", nil } + +// WorkspaceVendorEnabled reports whether workspace vendoring is enabled. It takes a *Runner to execute Go commands +// with the supplied context.Context and Invocation. The Invocation can contain pre-defined fields, +// of which only Verb and Args are modified to run the appropriate Go command. +// Inspired by setDefaultBuildMod in modload/init.go +func WorkspaceVendorEnabled(ctx context.Context, inv Invocation, r *Runner) (bool, []*ModuleJSON, error) { + inv.Verb = "env" + inv.Args = []string{"GOWORK"} + stdout, err := r.Run(ctx, inv) + if err != nil { + return false, nil, err + } + goWork := string(bytes.TrimSpace(stdout.Bytes())) + if fi, err := os.Stat(filepath.Join(filepath.Dir(goWork), "vendor")); err == nil && fi.IsDir() { + mainMods, err := getWorkspaceMainModules(ctx, inv, r) + if err != nil { + return false, nil, err + } + return true, mainMods, nil + } + return false, nil, nil +} + +// getWorkspaceMainModules gets the main modules' information. +// This is the information needed to figure out if vendoring should be enabled. +func getWorkspaceMainModules(ctx context.Context, inv Invocation, r *Runner) ([]*ModuleJSON, error) { + const format = `{{.Path}} +{{.Dir}} +{{.GoMod}} +{{.GoVersion}} +` + inv.Verb = "list" + inv.Args = []string{"-m", "-f", format} + stdout, err := r.Run(ctx, inv) + if err != nil { + return nil, err + } + + lines := strings.Split(strings.TrimSuffix(stdout.String(), "\n"), "\n") + if len(lines) < 4 { + return nil, fmt.Errorf("unexpected stdout: %q", stdout.String()) + } + mods := make([]*ModuleJSON, 0, len(lines)/4) + for i := 0; i < len(lines); i += 4 { + mods = append(mods, &ModuleJSON{ + Path: lines[i], + Dir: lines[i+1], + GoMod: lines[i+2], + GoVersion: lines[i+3], + Main: true, + }) + } + return mods, nil +} diff --git a/vendor/golang.org/x/tools/internal/gopathwalk/walk.go b/vendor/golang.org/x/tools/internal/gopathwalk/walk.go index 52f74e643..836151551 100644 --- a/vendor/golang.org/x/tools/internal/gopathwalk/walk.go +++ b/vendor/golang.org/x/tools/internal/gopathwalk/walk.go @@ -9,11 +9,13 @@ package gopathwalk import ( "bufio" "bytes" + "io" "io/fs" - "log" "os" "path/filepath" + "runtime" "strings" + "sync" "time" ) @@ -21,8 +23,13 @@ import ( type Options struct { // If Logf is non-nil, debug logging is enabled through this function. Logf func(format string, args ...interface{}) + // Search module caches. Also disables legacy goimports ignore rules. ModulesEnabled bool + + // Maximum number of concurrent calls to user-provided callbacks, + // or 0 for GOMAXPROCS. + Concurrency int } // RootType indicates the type of a Root. @@ -43,19 +50,28 @@ type Root struct { Type RootType } -// Walk walks Go source directories ($GOROOT, $GOPATH, etc) to find packages. +// Walk concurrently walks Go source directories ($GOROOT, $GOPATH, etc) to find packages. +// // For each package found, add will be called with the absolute // paths of the containing source directory and the package directory. +// +// Unlike filepath.WalkDir, Walk follows symbolic links +// (while guarding against cycles). func Walk(roots []Root, add func(root Root, dir string), opts Options) { WalkSkip(roots, add, func(Root, string) bool { return false }, opts) } -// WalkSkip walks Go source directories ($GOROOT, $GOPATH, etc) to find packages. +// WalkSkip concurrently walks Go source directories ($GOROOT, $GOPATH, etc) to +// find packages. +// // For each package found, add will be called with the absolute // paths of the containing source directory and the package directory. // For each directory that will be scanned, skip will be called // with the absolute paths of the containing source directory and the directory. // If skip returns false on a directory it will be processed. +// +// Unlike filepath.WalkDir, WalkSkip follows symbolic links +// (while guarding against cycles). func WalkSkip(roots []Root, add func(root Root, dir string), skip func(root Root, dir string) bool, opts Options) { for _, root := range roots { walkDir(root, add, skip, opts) @@ -64,45 +80,51 @@ func WalkSkip(roots []Root, add func(root Root, dir string), skip func(root Root // walkDir creates a walker and starts fastwalk with this walker. func walkDir(root Root, add func(Root, string), skip func(root Root, dir string) bool, opts Options) { + if opts.Logf == nil { + opts.Logf = func(format string, args ...interface{}) {} + } if _, err := os.Stat(root.Path); os.IsNotExist(err) { - if opts.Logf != nil { - opts.Logf("skipping nonexistent directory: %v", root.Path) - } + opts.Logf("skipping nonexistent directory: %v", root.Path) return } start := time.Now() - if opts.Logf != nil { - opts.Logf("scanning %s", root.Path) + opts.Logf("scanning %s", root.Path) + + concurrency := opts.Concurrency + if concurrency == 0 { + // The walk be either CPU-bound or I/O-bound, depending on what the + // caller-supplied add function does and the details of the user's platform + // and machine. Rather than trying to fine-tune the concurrency level for a + // specific environment, we default to GOMAXPROCS: it is likely to be a good + // choice for a CPU-bound add function, and if it is instead I/O-bound, then + // dealing with I/O saturation is arguably the job of the kernel and/or + // runtime. (Oversaturating I/O seems unlikely to harm performance as badly + // as failing to saturate would.) + concurrency = runtime.GOMAXPROCS(0) } - w := &walker{ - root: root, - add: add, - skip: skip, - opts: opts, - added: make(map[string]bool), + root: root, + add: add, + skip: skip, + opts: opts, + sem: make(chan struct{}, concurrency), } w.init() - // Add a trailing path separator to cause filepath.WalkDir to traverse symlinks. + w.sem <- struct{}{} path := root.Path - if len(path) == 0 { - path = "." + string(filepath.Separator) - } else if !os.IsPathSeparator(path[len(path)-1]) { - path = path + string(filepath.Separator) + if path == "" { + path = "." } - - if err := filepath.WalkDir(path, w.walk); err != nil { - logf := opts.Logf - if logf == nil { - logf = log.Printf - } - logf("scanning directory %v: %v", root.Path, err) + if fi, err := os.Lstat(path); err == nil { + w.walk(path, nil, fs.FileInfoToDirEntry(fi)) + } else { + w.opts.Logf("scanning directory %v: %v", root.Path, err) } + <-w.sem + w.walking.Wait() - if opts.Logf != nil { - opts.Logf("scanned %s in %v", root.Path, time.Since(start)) - } + opts.Logf("scanned %s in %v", root.Path, time.Since(start)) } // walker is the callback for fastwalk.Walk. @@ -112,10 +134,18 @@ type walker struct { skip func(Root, string) bool // The callback that will be invoked for every dir. dir is skipped if it returns true. opts Options // Options passed to Walk by the user. - pathSymlinks []os.FileInfo - ignoredDirs []string + walking sync.WaitGroup + sem chan struct{} // Channel of semaphore tokens; send to acquire, receive to release. + ignoredDirs []string - added map[string]bool + added sync.Map // map[string]bool +} + +// A symlinkList is a linked list of os.FileInfos for parent directories +// reached via symlinks. +type symlinkList struct { + info os.FileInfo + prev *symlinkList } // init initializes the walker based on its Options @@ -132,9 +162,7 @@ func (w *walker) init() { for _, p := range ignoredPaths { full := filepath.Join(w.root.Path, p) w.ignoredDirs = append(w.ignoredDirs, full) - if w.opts.Logf != nil { - w.opts.Logf("Directory added to ignore list: %s", full) - } + w.opts.Logf("Directory added to ignore list: %s", full) } } @@ -144,12 +172,10 @@ func (w *walker) init() { func (w *walker) getIgnoredDirs(path string) []string { file := filepath.Join(path, ".goimportsignore") slurp, err := os.ReadFile(file) - if w.opts.Logf != nil { - if err != nil { - w.opts.Logf("%v", err) - } else { - w.opts.Logf("Read %s", file) - } + if err != nil { + w.opts.Logf("%v", err) + } else { + w.opts.Logf("Read %s", file) } if err != nil { return nil @@ -183,149 +209,129 @@ func (w *walker) shouldSkipDir(dir string) bool { // walk walks through the given path. // -// Errors are logged if w.opts.Logf is non-nil, but otherwise ignored: -// walk returns only nil or fs.SkipDir. -func (w *walker) walk(path string, d fs.DirEntry, err error) error { - if err != nil { - // We have no way to report errors back through Walk or WalkSkip, - // so just log and ignore them. - if w.opts.Logf != nil { +// Errors are logged if w.opts.Logf is non-nil, but otherwise ignored. +func (w *walker) walk(path string, pathSymlinks *symlinkList, d fs.DirEntry) { + if d.Type()&os.ModeSymlink != 0 { + // Walk the symlink's target rather than the symlink itself. + // + // (Note that os.Stat, unlike the lower-lever os.Readlink, + // follows arbitrarily many layers of symlinks, so it will eventually + // reach either a non-symlink or a nonexistent target.) + // + // TODO(bcmills): 'go list all' itself ignores symlinks within GOROOT/src + // and GOPATH/src. Do we really need to traverse them here? If so, why? + + fi, err := os.Stat(path) + if err != nil { w.opts.Logf("%v", err) + return + } + + // Avoid walking symlink cycles: if we have already followed a symlink to + // this directory as a parent of itself, don't follow it again. + // + // This doesn't catch the first time through a cycle, but it also minimizes + // the number of extra stat calls we make if we *don't* encounter a cycle. + // Since we don't actually expect to encounter symlink cycles in practice, + // this seems like the right tradeoff. + for parent := pathSymlinks; parent != nil; parent = parent.prev { + if os.SameFile(fi, parent.info) { + return + } } - if d == nil { - // Nothing more to do: the error prevents us from knowing - // what path even represents. - return nil + + pathSymlinks = &symlinkList{ + info: fi, + prev: pathSymlinks, } + d = fs.FileInfoToDirEntry(fi) } if d.Type().IsRegular() { if !strings.HasSuffix(path, ".go") { - return nil + return } dir := filepath.Dir(path) if dir == w.root.Path && (w.root.Type == RootGOROOT || w.root.Type == RootGOPATH) { // Doesn't make sense to have regular files // directly in your $GOPATH/src or $GOROOT/src. - return nil + // + // TODO(bcmills): there are many levels of directory within + // RootModuleCache where this also wouldn't make sense, + // Can we generalize this to any directory without a corresponding + // import path? + return } - if !w.added[dir] { + if _, dup := w.added.LoadOrStore(dir, true); !dup { w.add(w.root, dir) - w.added[dir] = true } - return nil } - if d.IsDir() { - base := filepath.Base(path) - if base == "" || base[0] == '.' || base[0] == '_' || - base == "testdata" || - (w.root.Type == RootGOROOT && w.opts.ModulesEnabled && base == "vendor") || - (!w.opts.ModulesEnabled && base == "node_modules") { - return fs.SkipDir - } - if w.shouldSkipDir(path) { - return fs.SkipDir - } - return nil + if !d.IsDir() { + return } - if d.Type()&os.ModeSymlink != 0 { - // TODO(bcmills): 'go list all' itself ignores symlinks within GOROOT/src - // and GOPATH/src. Do we really need to traverse them here? If so, why? - - fi, err := os.Stat(path) - if err != nil || !fi.IsDir() { - // Not a directory. Just walk the file (or broken link) and be done. - return w.walk(path, fs.FileInfoToDirEntry(fi), err) - } - - // Avoid walking symlink cycles: if we have already followed a symlink to - // this directory as a parent of itself, don't follow it again. - // - // This doesn't catch the first time through a cycle, but it also minimizes - // the number of extra stat calls we make if we *don't* encounter a cycle. - // Since we don't actually expect to encounter symlink cycles in practice, - // this seems like the right tradeoff. - for _, parent := range w.pathSymlinks { - if os.SameFile(fi, parent) { - return nil - } - } + base := filepath.Base(path) + if base == "" || base[0] == '.' || base[0] == '_' || + base == "testdata" || + (w.root.Type == RootGOROOT && w.opts.ModulesEnabled && base == "vendor") || + (!w.opts.ModulesEnabled && base == "node_modules") || + w.shouldSkipDir(path) { + return + } - w.pathSymlinks = append(w.pathSymlinks, fi) - defer func() { - w.pathSymlinks = w.pathSymlinks[:len(w.pathSymlinks)-1] - }() + // Read the directory and walk its entries. - // On some platforms the OS (or the Go os package) sometimes fails to - // resolve directory symlinks before a trailing slash - // (even though POSIX requires it to do so). - // - // On macOS that failure may be caused by a known libc/kernel bug; - // see https://go.dev/issue/59586. - // - // On Windows before Go 1.21, it may be caused by a bug in - // os.Lstat (fixed in https://go.dev/cl/463177). - // - // Since we need to handle this explicitly on broken platforms anyway, - // it is simplest to just always do that and not rely on POSIX pathname - // resolution to walk the directory (such as by calling WalkDir with - // a trailing slash appended to the path). + f, err := os.Open(path) + if err != nil { + w.opts.Logf("%v", err) + return + } + defer f.Close() + + for { + // We impose an arbitrary limit on the number of ReadDir results per + // directory to limit the amount of memory consumed for stale or upcoming + // directory entries. The limit trades off CPU (number of syscalls to read + // the whole directory) against RAM (reachable directory entries other than + // the one currently being processed). // - // Instead, we make a sequence of walk calls — directly and through - // recursive calls to filepath.WalkDir — simulating what WalkDir would do - // if the symlink were a regular directory. - - // First we call walk on the path as a directory - // (instead of a symlink). - err = w.walk(path, fs.FileInfoToDirEntry(fi), nil) - if err == fs.SkipDir { - return nil - } else if err != nil { - // This should be impossible, but handle it anyway in case - // walk is changed to return other errors. - return err - } - - // Now read the directory and walk its entries. - ents, err := os.ReadDir(path) + // Since we process the directories recursively, we will end up maintaining + // a slice of entries for each level of the directory tree. + // (Compare https://go.dev/issue/36197.) + ents, err := f.ReadDir(1024) if err != nil { - // Report the ReadDir error, as filepath.WalkDir would do. - err = w.walk(path, fs.FileInfoToDirEntry(fi), err) - if err == fs.SkipDir { - return nil - } else if err != nil { - return err // Again, should be impossible. + if err != io.EOF { + w.opts.Logf("%v", err) } - // Fall through and iterate over whatever entries we did manage to get. + break } for _, d := range ents { nextPath := filepath.Join(path, d.Name()) if d.IsDir() { - // We want to walk the whole directory tree rooted at nextPath, - // not just the single entry for the directory. - err := filepath.WalkDir(nextPath, w.walk) - if err != nil && w.opts.Logf != nil { - w.opts.Logf("%v", err) - } - } else { - err := w.walk(nextPath, d, nil) - if err == fs.SkipDir { - // Skip the rest of the entries in the parent directory of nextPath - // (that is, path itself). - break - } else if err != nil { - return err // Again, should be impossible. + select { + case w.sem <- struct{}{}: + // Got a new semaphore token, so we can traverse the directory concurrently. + d := d + w.walking.Add(1) + go func() { + defer func() { + <-w.sem + w.walking.Done() + }() + w.walk(nextPath, pathSymlinks, d) + }() + continue + + default: + // No tokens available, so traverse serially. } } + + w.walk(nextPath, pathSymlinks, d) } - return nil } - - // Not a file, regular directory, or symlink; skip. - return nil } diff --git a/vendor/golang.org/x/tools/internal/imports/fix.go b/vendor/golang.org/x/tools/internal/imports/fix.go index dd369c072..4569313a0 100644 --- a/vendor/golang.org/x/tools/internal/imports/fix.go +++ b/vendor/golang.org/x/tools/internal/imports/fix.go @@ -13,6 +13,7 @@ import ( "go/build" "go/parser" "go/token" + "go/types" "io/fs" "io/ioutil" "os" @@ -30,6 +31,7 @@ import ( "golang.org/x/tools/internal/event" "golang.org/x/tools/internal/gocommand" "golang.org/x/tools/internal/gopathwalk" + "golang.org/x/tools/internal/stdlib" ) // importToGroup is a list of functions which map from an import path to @@ -102,7 +104,10 @@ type packageInfo struct { // parseOtherFiles parses all the Go files in srcDir except filename, including // test files if filename looks like a test. -func parseOtherFiles(fset *token.FileSet, srcDir, filename string) []*ast.File { +// +// It returns an error only if ctx is cancelled. Files with parse errors are +// ignored. +func parseOtherFiles(ctx context.Context, fset *token.FileSet, srcDir, filename string) ([]*ast.File, error) { // This could use go/packages but it doesn't buy much, and it fails // with https://golang.org/issue/26296 in LoadFiles mode in some cases. considerTests := strings.HasSuffix(filename, "_test.go") @@ -110,11 +115,14 @@ func parseOtherFiles(fset *token.FileSet, srcDir, filename string) []*ast.File { fileBase := filepath.Base(filename) packageFileInfos, err := os.ReadDir(srcDir) if err != nil { - return nil + return nil, ctx.Err() } var files []*ast.File for _, fi := range packageFileInfos { + if ctx.Err() != nil { + return nil, ctx.Err() + } if fi.Name() == fileBase || !strings.HasSuffix(fi.Name(), ".go") { continue } @@ -130,7 +138,7 @@ func parseOtherFiles(fset *token.FileSet, srcDir, filename string) []*ast.File { files = append(files, f) } - return files + return files, ctx.Err() } // addGlobals puts the names of package vars into the provided map. @@ -299,6 +307,20 @@ func (p *pass) loadPackageNames(imports []*ImportInfo) error { return nil } +// if there is a trailing major version, remove it +func withoutVersion(nm string) string { + if v := path.Base(nm); len(v) > 0 && v[0] == 'v' { + if _, err := strconv.Atoi(v[1:]); err == nil { + // this is, for instance, called with rand/v2 and returns rand + if len(v) < len(nm) { + xnm := nm[:len(nm)-len(v)-1] + return path.Base(xnm) + } + } + } + return nm +} + // importIdentifier returns the identifier that imp will introduce. It will // guess if the package name has not been loaded, e.g. because the source // is not available. @@ -308,7 +330,7 @@ func (p *pass) importIdentifier(imp *ImportInfo) string { } known := p.knownPackages[imp.ImportPath] if known != nil && known.name != "" { - return known.name + return withoutVersion(known.name) } return ImportPathToAssumedName(imp.ImportPath) } @@ -510,9 +532,9 @@ func (p *pass) assumeSiblingImportsValid() { } for left, rights := range refs { if imp, ok := importsByName[left]; ok { - if m, ok := stdlib[imp.ImportPath]; ok { + if m, ok := stdlib.PackageSymbols[imp.ImportPath]; ok { // We have the stdlib in memory; no need to guess. - rights = copyExports(m) + rights = symbolNameSet(m) } p.addCandidate(imp, &packageInfo{ // no name; we already know it. @@ -541,12 +563,7 @@ func (p *pass) addCandidate(imp *ImportInfo, pkg *packageInfo) { // fixImports adds and removes imports from f so that all its references are // satisfied and there are no unused imports. -// -// This is declared as a variable rather than a function so goimports can -// easily be extended by adding a file with an init function. -var fixImports = fixImportsDefault - -func fixImportsDefault(fset *token.FileSet, f *ast.File, filename string, env *ProcessEnv) error { +func fixImports(fset *token.FileSet, f *ast.File, filename string, env *ProcessEnv) error { fixes, err := getFixes(context.Background(), fset, f, filename, env) if err != nil { return err @@ -576,7 +593,10 @@ func getFixes(ctx context.Context, fset *token.FileSet, f *ast.File, filename st return fixes, nil } - otherFiles := parseOtherFiles(fset, srcDir, filename) + otherFiles, err := parseOtherFiles(ctx, fset, srcDir, filename) + if err != nil { + return nil, err + } // Second pass: add information from other files in the same package, // like their package vars and imports. @@ -640,7 +660,7 @@ func getCandidatePkgs(ctx context.Context, wrappedCallback *scanCallback, filena dupCheck := map[string]struct{}{} // Start off with the standard library. - for importPath, exports := range stdlib { + for importPath, symbols := range stdlib.PackageSymbols { p := &pkg{ dir: filepath.Join(goenv["GOROOT"], "src", importPath), importPathShort: importPath, @@ -649,6 +669,13 @@ func getCandidatePkgs(ctx context.Context, wrappedCallback *scanCallback, filena } dupCheck[importPath] = struct{}{} if notSelf(p) && wrappedCallback.dirFound(p) && wrappedCallback.packageNameLoaded(p) { + var exports []stdlib.Symbol + for _, sym := range symbols { + switch sym.Kind { + case stdlib.Func, stdlib.Type, stdlib.Var, stdlib.Const: + exports = append(exports, sym) + } + } wrappedCallback.exportsLoaded(p, exports) } } @@ -669,7 +696,7 @@ func getCandidatePkgs(ctx context.Context, wrappedCallback *scanCallback, filena dupCheck[pkg.importPathShort] = struct{}{} return notSelf(pkg) && wrappedCallback.packageNameLoaded(pkg) }, - exportsLoaded: func(pkg *pkg, exports []string) { + exportsLoaded: func(pkg *pkg, exports []stdlib.Symbol) { // If we're an x_test, load the package under test's test variant. if strings.HasSuffix(filePkg, "_test") && pkg.dir == filepath.Dir(filename) { var err error @@ -700,20 +727,21 @@ func ScoreImportPaths(ctx context.Context, env *ProcessEnv, paths []string) (map return result, nil } -func PrimeCache(ctx context.Context, env *ProcessEnv) error { +func PrimeCache(ctx context.Context, resolver Resolver) error { // Fully scan the disk for directories, but don't actually read any Go files. callback := &scanCallback{ - rootFound: func(gopathwalk.Root) bool { - return true + rootFound: func(root gopathwalk.Root) bool { + // See getCandidatePkgs: walking GOROOT is apparently expensive and + // unnecessary. + return root.Type != gopathwalk.RootGOROOT }, dirFound: func(pkg *pkg) bool { return false }, - packageNameLoaded: func(pkg *pkg) bool { - return false - }, + // packageNameLoaded and exportsLoaded must never be called. } - return getCandidatePkgs(ctx, callback, "", "", env) + + return resolver.scan(ctx, callback) } func candidateImportName(pkg *pkg) string { @@ -793,7 +821,7 @@ func GetImportPaths(ctx context.Context, wrapped func(ImportFix), searchPrefix, // A PackageExport is a package and its exports. type PackageExport struct { Fix *ImportFix - Exports []string + Exports []stdlib.Symbol } // GetPackageExports returns all known packages with name pkg and their exports. @@ -808,8 +836,8 @@ func GetPackageExports(ctx context.Context, wrapped func(PackageExport), searchP packageNameLoaded: func(pkg *pkg) bool { return pkg.packageName == searchPkg }, - exportsLoaded: func(pkg *pkg, exports []string) { - sort.Strings(exports) + exportsLoaded: func(pkg *pkg, exports []stdlib.Symbol) { + sortSymbols(exports) wrapped(PackageExport{ Fix: &ImportFix{ StmtInfo: ImportInfo{ @@ -827,16 +855,45 @@ func GetPackageExports(ctx context.Context, wrapped func(PackageExport), searchP return getCandidatePkgs(ctx, callback, filename, filePkg, env) } -var requiredGoEnvVars = []string{"GO111MODULE", "GOFLAGS", "GOINSECURE", "GOMOD", "GOMODCACHE", "GONOPROXY", "GONOSUMDB", "GOPATH", "GOPROXY", "GOROOT", "GOSUMDB", "GOWORK"} +// TODO(rfindley): we should depend on GOOS and GOARCH, to provide accurate +// imports when doing cross-platform development. +var requiredGoEnvVars = []string{ + "GO111MODULE", + "GOFLAGS", + "GOINSECURE", + "GOMOD", + "GOMODCACHE", + "GONOPROXY", + "GONOSUMDB", + "GOPATH", + "GOPROXY", + "GOROOT", + "GOSUMDB", + "GOWORK", +} // ProcessEnv contains environment variables and settings that affect the use of // the go command, the go/build package, etc. +// +// ...a ProcessEnv *also* overwrites its Env along with derived state in the +// form of the resolver. And because it is lazily initialized, an env may just +// be broken and unusable, but there is no way for the caller to detect that: +// all queries will just fail. +// +// TODO(rfindley): refactor this package so that this type (perhaps renamed to +// just Env or Config) is an immutable configuration struct, to be exchanged +// for an initialized object via a constructor that returns an error. Perhaps +// the signature should be `func NewResolver(*Env) (*Resolver, error)`, where +// resolver is a concrete type used for resolving imports. Via this +// refactoring, we can avoid the need to call ProcessEnv.init and +// ProcessEnv.GoEnv everywhere, and implicitly fix all the places where this +// these are misused. Also, we'd delegate the caller the decision of how to +// handle a broken environment. type ProcessEnv struct { GocmdRunner *gocommand.Runner BuildFlags []string ModFlag string - ModFile string // SkipPathInScan returns true if the path should be skipped from scans of // the RootCurrentModule root type. The function argument is a clean, @@ -846,7 +903,7 @@ type ProcessEnv struct { // Env overrides the OS environment, and can be used to specify // GOPROXY, GO111MODULE, etc. PATH cannot be set here, because // exec.Command will not honor it. - // Specifying all of RequiredGoEnvVars avoids a call to `go env`. + // Specifying all of requiredGoEnvVars avoids a call to `go env`. Env map[string]string WorkingDir string @@ -854,9 +911,17 @@ type ProcessEnv struct { // If Logf is non-nil, debug logging is enabled through this function. Logf func(format string, args ...interface{}) - initialized bool + // If set, ModCache holds a shared cache of directory info to use across + // multiple ProcessEnvs. + ModCache *DirInfoCache - resolver Resolver + initialized bool // see TODO above + + // resolver and resolverErr are lazily evaluated (see GetResolver). + // This is unclean, but see the big TODO in the docstring for ProcessEnv + // above: for now, we can't be sure that the ProcessEnv is fully initialized. + resolver Resolver + resolverErr error } func (e *ProcessEnv) goEnv() (map[string]string, error) { @@ -936,20 +1001,33 @@ func (e *ProcessEnv) env() []string { } func (e *ProcessEnv) GetResolver() (Resolver, error) { - if e.resolver != nil { - return e.resolver, nil - } if err := e.init(); err != nil { return nil, err } - if len(e.Env["GOMOD"]) == 0 && len(e.Env["GOWORK"]) == 0 { - e.resolver = newGopathResolver(e) - return e.resolver, nil + + if e.resolver == nil && e.resolverErr == nil { + // TODO(rfindley): we should only use a gopathResolver here if the working + // directory is actually *in* GOPATH. (I seem to recall an open gopls issue + // for this behavior, but I can't find it). + // + // For gopls, we can optionally explicitly choose a resolver type, since we + // already know the view type. + if len(e.Env["GOMOD"]) == 0 && len(e.Env["GOWORK"]) == 0 { + e.resolver = newGopathResolver(e) + } else if r, err := newModuleResolver(e, e.ModCache); err != nil { + e.resolverErr = err + } else { + e.resolver = Resolver(r) + } } - e.resolver = newModuleResolver(e) - return e.resolver, nil + + return e.resolver, e.resolverErr } +// buildContext returns the build.Context to use for matching files. +// +// TODO(rfindley): support dynamic GOOS, GOARCH here, when doing cross-platform +// development. func (e *ProcessEnv) buildContext() (*build.Context, error) { ctx := build.Default goenv, err := e.goEnv() @@ -999,24 +1077,40 @@ func addStdlibCandidates(pass *pass, refs references) error { if err != nil { return err } + localbase := func(nm string) string { + ans := path.Base(nm) + if ans[0] == 'v' { + // this is called, for instance, with math/rand/v2 and returns rand/v2 + if _, err := strconv.Atoi(ans[1:]); err == nil { + ix := strings.LastIndex(nm, ans) + more := path.Base(nm[:ix]) + ans = path.Join(more, ans) + } + } + return ans + } add := func(pkg string) { // Prevent self-imports. if path.Base(pkg) == pass.f.Name.Name && filepath.Join(goenv["GOROOT"], "src", pkg) == pass.srcDir { return } - exports := copyExports(stdlib[pkg]) + exports := symbolNameSet(stdlib.PackageSymbols[pkg]) pass.addCandidate( &ImportInfo{ImportPath: pkg}, - &packageInfo{name: path.Base(pkg), exports: exports}) + &packageInfo{name: localbase(pkg), exports: exports}) } for left := range refs { if left == "rand" { - // Make sure we try crypto/rand before math/rand. + // Make sure we try crypto/rand before any version of math/rand as both have Int() + // and our policy is to recommend crypto add("crypto/rand") - add("math/rand") + // if the user's no later than go1.21, this should be "math/rand" + // but we have no way of figuring out what the user is using + // TODO: investigate using the toolchain version to disambiguate in the stdlib + add("math/rand/v2") continue } - for importPath := range stdlib { + for importPath := range stdlib.PackageSymbols { if path.Base(importPath) == left { add(importPath) } @@ -1029,15 +1123,23 @@ func addStdlibCandidates(pass *pass, refs references) error { type Resolver interface { // loadPackageNames loads the package names in importPaths. loadPackageNames(importPaths []string, srcDir string) (map[string]string, error) + // scan works with callback to search for packages. See scanCallback for details. scan(ctx context.Context, callback *scanCallback) error + // loadExports returns the set of exported symbols in the package at dir. // loadExports may be called concurrently. - loadExports(ctx context.Context, pkg *pkg, includeTest bool) (string, []string, error) + loadExports(ctx context.Context, pkg *pkg, includeTest bool) (string, []stdlib.Symbol, error) + // scoreImportPath returns the relevance for an import path. scoreImportPath(ctx context.Context, path string) float64 - ClearForNewScan() + // ClearForNewScan returns a new Resolver based on the receiver that has + // cleared its internal caches of directory contents. + // + // The new resolver should be primed and then set via + // [ProcessEnv.UpdateResolver]. + ClearForNewScan() Resolver } // A scanCallback controls a call to scan and receives its results. @@ -1056,7 +1158,7 @@ type scanCallback struct { // If it returns true, the package's exports will be loaded. packageNameLoaded func(pkg *pkg) bool // exportsLoaded is called when a package's exports have been loaded. - exportsLoaded func(pkg *pkg, exports []string) + exportsLoaded func(pkg *pkg, exports []stdlib.Symbol) } func addExternalCandidates(ctx context.Context, pass *pass, refs references, filename string) error { @@ -1094,7 +1196,7 @@ func addExternalCandidates(ctx context.Context, pass *pass, refs references, fil if err != nil { return err } - if err = resolver.scan(context.Background(), callback); err != nil { + if err = resolver.scan(ctx, callback); err != nil { return err } @@ -1105,7 +1207,7 @@ func addExternalCandidates(ctx context.Context, pass *pass, refs references, fil } results := make(chan result, len(refs)) - ctx, cancel := context.WithCancel(context.TODO()) + ctx, cancel := context.WithCancel(ctx) var wg sync.WaitGroup defer func() { cancel() @@ -1120,7 +1222,7 @@ func addExternalCandidates(ctx context.Context, pass *pass, refs references, fil go func(pkgName string, symbols map[string]bool) { defer wg.Done() - found, err := findImport(ctx, pass, found[pkgName], pkgName, symbols, filename) + found, err := findImport(ctx, pass, found[pkgName], pkgName, symbols) if err != nil { firstErrOnce.Do(func() { @@ -1151,6 +1253,17 @@ func addExternalCandidates(ctx context.Context, pass *pass, refs references, fil }() for result := range results { + // Don't offer completions that would shadow predeclared + // names, such as github.com/coreos/etcd/error. + if types.Universe.Lookup(result.pkg.name) != nil { // predeclared + // Ideally we would skip this candidate only + // if the predeclared name is actually + // referenced by the file, but that's a lot + // trickier to compute and would still create + // an import that is likely to surprise the + // user before long. + continue + } pass.addCandidate(result.imp, result.pkg) } return firstErr @@ -1193,31 +1306,22 @@ func ImportPathToAssumedName(importPath string) string { type gopathResolver struct { env *ProcessEnv walked bool - cache *dirInfoCache + cache *DirInfoCache scanSema chan struct{} // scanSema prevents concurrent scans. } func newGopathResolver(env *ProcessEnv) *gopathResolver { r := &gopathResolver{ - env: env, - cache: &dirInfoCache{ - dirs: map[string]*directoryPackageInfo{}, - listeners: map[*int]cacheListener{}, - }, + env: env, + cache: NewDirInfoCache(), scanSema: make(chan struct{}, 1), } r.scanSema <- struct{}{} return r } -func (r *gopathResolver) ClearForNewScan() { - <-r.scanSema - r.cache = &dirInfoCache{ - dirs: map[string]*directoryPackageInfo{}, - listeners: map[*int]cacheListener{}, - } - r.walked = false - r.scanSema <- struct{}{} +func (r *gopathResolver) ClearForNewScan() Resolver { + return newGopathResolver(r.env) } func (r *gopathResolver) loadPackageNames(importPaths []string, srcDir string) (map[string]string, error) { @@ -1235,7 +1339,7 @@ func (r *gopathResolver) loadPackageNames(importPaths []string, srcDir string) ( // importPathToName finds out the actual package name, as declared in its .go files. func importPathToName(bctx *build.Context, importPath, srcDir string) string { // Fast path for standard library without going to disk. - if _, ok := stdlib[importPath]; ok { + if stdlib.HasPackage(importPath) { return path.Base(importPath) // stdlib packages always match their paths. } @@ -1433,7 +1537,7 @@ func (r *gopathResolver) scan(ctx context.Context, callback *scanCallback) error } func (r *gopathResolver) scoreImportPath(ctx context.Context, path string) float64 { - if _, ok := stdlib[path]; ok { + if stdlib.HasPackage(path) { return MaxRelevance } return MaxRelevance - 1 @@ -1450,7 +1554,7 @@ func filterRoots(roots []gopathwalk.Root, include func(gopathwalk.Root) bool) [] return result } -func (r *gopathResolver) loadExports(ctx context.Context, pkg *pkg, includeTest bool) (string, []string, error) { +func (r *gopathResolver) loadExports(ctx context.Context, pkg *pkg, includeTest bool) (string, []stdlib.Symbol, error) { if info, ok := r.cache.Load(pkg.dir); ok && !includeTest { return r.cache.CacheExports(ctx, r.env, info) } @@ -1470,7 +1574,7 @@ func VendorlessPath(ipath string) string { return ipath } -func loadExportsFromFiles(ctx context.Context, env *ProcessEnv, dir string, includeTest bool) (string, []string, error) { +func loadExportsFromFiles(ctx context.Context, env *ProcessEnv, dir string, includeTest bool) (string, []stdlib.Symbol, error) { // Look for non-test, buildable .go files which could provide exports. all, err := os.ReadDir(dir) if err != nil { @@ -1494,7 +1598,7 @@ func loadExportsFromFiles(ctx context.Context, env *ProcessEnv, dir string, incl } var pkgName string - var exports []string + var exports []stdlib.Symbol fset := token.NewFileSet() for _, fi := range files { select { @@ -1521,24 +1625,44 @@ func loadExportsFromFiles(ctx context.Context, env *ProcessEnv, dir string, incl continue } pkgName = f.Name.Name - for name := range f.Scope.Objects { + for name, obj := range f.Scope.Objects { if ast.IsExported(name) { - exports = append(exports, name) + var kind stdlib.Kind + switch obj.Kind { + case ast.Con: + kind = stdlib.Const + case ast.Typ: + kind = stdlib.Type + case ast.Var: + kind = stdlib.Var + case ast.Fun: + kind = stdlib.Func + } + exports = append(exports, stdlib.Symbol{ + Name: name, + Kind: kind, + Version: 0, // unknown; be permissive + }) } } } + sortSymbols(exports) if env.Logf != nil { - sortedExports := append([]string(nil), exports...) - sort.Strings(sortedExports) - env.Logf("loaded exports in dir %v (package %v): %v", dir, pkgName, strings.Join(sortedExports, ", ")) + env.Logf("loaded exports in dir %v (package %v): %v", dir, pkgName, exports) } return pkgName, exports, nil } +func sortSymbols(syms []stdlib.Symbol) { + sort.Slice(syms, func(i, j int) bool { + return syms[i].Name < syms[j].Name + }) +} + // findImport searches for a package with the given symbols. // If no package is found, findImport returns ("", false, nil) -func findImport(ctx context.Context, pass *pass, candidates []pkgDistance, pkgName string, symbols map[string]bool, filename string) (*pkg, error) { +func findImport(ctx context.Context, pass *pass, candidates []pkgDistance, pkgName string, symbols map[string]bool) (*pkg, error) { // Sort the candidates by their import package length, // assuming that shorter package names are better than long // ones. Note that this sorts by the de-vendored name, so @@ -1602,7 +1726,7 @@ func findImport(ctx context.Context, pass *pass, candidates []pkgDistance, pkgNa exportsMap := make(map[string]bool, len(exports)) for _, sym := range exports { - exportsMap[sym] = true + exportsMap[sym.Name] = true } // If it doesn't have the right @@ -1760,10 +1884,13 @@ func (fn visitFn) Visit(node ast.Node) ast.Visitor { return fn(node) } -func copyExports(pkg []string) map[string]bool { - m := make(map[string]bool, len(pkg)) - for _, v := range pkg { - m[v] = true +func symbolNameSet(symbols []stdlib.Symbol) map[string]bool { + names := make(map[string]bool) + for _, sym := range symbols { + switch sym.Kind { + case stdlib.Const, stdlib.Var, stdlib.Type, stdlib.Func: + names[sym.Name] = true + } } - return m + return names } diff --git a/vendor/golang.org/x/tools/internal/imports/imports.go b/vendor/golang.org/x/tools/internal/imports/imports.go index 58e637b90..f83465520 100644 --- a/vendor/golang.org/x/tools/internal/imports/imports.go +++ b/vendor/golang.org/x/tools/internal/imports/imports.go @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:generate go run mkstdlib.go - // Package imports implements a Go pretty-printer (like package "go/format") // that also adds or removes import statements as necessary. package imports @@ -109,7 +107,7 @@ func ApplyFixes(fixes []*ImportFix, filename string, src []byte, opt *Options, e } // formatFile formats the file syntax tree. -// It may mutate the token.FileSet. +// It may mutate the token.FileSet and the ast.File. // // If an adjust function is provided, it is called after formatting // with the original source (formatFile's src parameter) and the @@ -236,7 +234,7 @@ func parse(fset *token.FileSet, filename string, src []byte, opt *Options) (*ast src = src[:len(src)-len("}\n")] // Gofmt has also indented the function body one level. // Remove that indent. - src = bytes.Replace(src, []byte("\n\t"), []byte("\n"), -1) + src = bytes.ReplaceAll(src, []byte("\n\t"), []byte("\n")) return matchSpace(orig, src) } return file, adjust, nil diff --git a/vendor/golang.org/x/tools/internal/imports/mod.go b/vendor/golang.org/x/tools/internal/imports/mod.go index 5f4d435d3..82fe644a1 100644 --- a/vendor/golang.org/x/tools/internal/imports/mod.go +++ b/vendor/golang.org/x/tools/internal/imports/mod.go @@ -21,78 +21,138 @@ import ( "golang.org/x/tools/internal/event" "golang.org/x/tools/internal/gocommand" "golang.org/x/tools/internal/gopathwalk" + "golang.org/x/tools/internal/stdlib" ) -// ModuleResolver implements resolver for modules using the go command as little -// as feasible. +// Notes(rfindley): ModuleResolver appears to be heavily optimized for scanning +// as fast as possible, which is desirable for a call to goimports from the +// command line, but it doesn't work as well for gopls, where it suffers from +// slow startup (golang/go#44863) and intermittent hanging (golang/go#59216), +// both caused by populating the cache, albeit in slightly different ways. +// +// A high level list of TODOs: +// - Optimize the scan itself, as there is some redundancy statting and +// reading go.mod files. +// - Invert the relationship between ProcessEnv and Resolver (see the +// docstring of ProcessEnv). +// - Make it easier to use an external resolver implementation. +// +// Smaller TODOs are annotated in the code below. + +// ModuleResolver implements the Resolver interface for a workspace using +// modules. +// +// A goal of the ModuleResolver is to invoke the Go command as little as +// possible. To this end, it runs the Go command only for listing module +// information (i.e. `go list -m -e -json ...`). Package scanning, the process +// of loading package information for the modules, is implemented internally +// via the scan method. +// +// It has two types of state: the state derived from the go command, which +// is populated by init, and the state derived from scans, which is populated +// via scan. A root is considered scanned if it has been walked to discover +// directories. However, if the scan did not require additional information +// from the directory (such as package name or exports), the directory +// information itself may be partially populated. It will be lazily filled in +// as needed by scans, using the scanCallback. type ModuleResolver struct { - env *ProcessEnv - moduleCacheDir string - dummyVendorMod *gocommand.ModuleJSON // If vendoring is enabled, the pseudo-module that represents the /vendor directory. - roots []gopathwalk.Root - scanSema chan struct{} // scanSema prevents concurrent scans and guards scannedRoots. - scannedRoots map[gopathwalk.Root]bool - - initialized bool - mains []*gocommand.ModuleJSON - mainByDir map[string]*gocommand.ModuleJSON - modsByModPath []*gocommand.ModuleJSON // All modules, ordered by # of path components in module Path... - modsByDir []*gocommand.ModuleJSON // ...or number of path components in their Dir. - - // moduleCacheCache stores information about the module cache. - moduleCacheCache *dirInfoCache - otherCache *dirInfoCache + env *ProcessEnv + + // Module state, populated during construction + dummyVendorMod *gocommand.ModuleJSON // if vendoring is enabled, a pseudo-module to represent the /vendor directory + moduleCacheDir string // GOMODCACHE, inferred from GOPATH if unset + roots []gopathwalk.Root // roots to scan, in approximate order of importance + mains []*gocommand.ModuleJSON // main modules + mainByDir map[string]*gocommand.ModuleJSON // module information by dir, to join with roots + modsByModPath []*gocommand.ModuleJSON // all modules, ordered by # of path components in their module path + modsByDir []*gocommand.ModuleJSON // ...or by the number of path components in their Dir. + + // Scanning state, populated by scan + + // scanSema prevents concurrent scans, and guards scannedRoots and the cache + // fields below (though the caches themselves are concurrency safe). + // Receive to acquire, send to release. + scanSema chan struct{} + scannedRoots map[gopathwalk.Root]bool // if true, root has been walked + + // Caches of directory info, populated by scans and scan callbacks + // + // moduleCacheCache stores cached information about roots in the module + // cache, which are immutable and therefore do not need to be invalidated. + // + // otherCache stores information about all other roots (even GOROOT), which + // may change. + moduleCacheCache *DirInfoCache + otherCache *DirInfoCache } -func newModuleResolver(e *ProcessEnv) *ModuleResolver { +// newModuleResolver returns a new module-aware goimports resolver. +// +// Note: use caution when modifying this constructor: changes must also be +// reflected in ModuleResolver.ClearForNewScan. +func newModuleResolver(e *ProcessEnv, moduleCacheCache *DirInfoCache) (*ModuleResolver, error) { r := &ModuleResolver{ env: e, scanSema: make(chan struct{}, 1), } - r.scanSema <- struct{}{} - return r -} - -func (r *ModuleResolver) init() error { - if r.initialized { - return nil - } + r.scanSema <- struct{}{} // release goenv, err := r.env.goEnv() if err != nil { - return err + return nil, err } + + // TODO(rfindley): can we refactor to share logic with r.env.invokeGo? inv := gocommand.Invocation{ BuildFlags: r.env.BuildFlags, ModFlag: r.env.ModFlag, - ModFile: r.env.ModFile, Env: r.env.env(), Logf: r.env.Logf, WorkingDir: r.env.WorkingDir, } vendorEnabled := false - var mainModVendor *gocommand.ModuleJSON - - // Module vendor directories are ignored in workspace mode: - // https://go.googlesource.com/proposal/+/master/design/45713-workspace.md - if len(r.env.Env["GOWORK"]) == 0 { + var mainModVendor *gocommand.ModuleJSON // for module vendoring + var mainModsVendor []*gocommand.ModuleJSON // for workspace vendoring + + goWork := r.env.Env["GOWORK"] + if len(goWork) == 0 { + // TODO(rfindley): VendorEnabled runs the go command to get GOFLAGS, but + // they should be available from the ProcessEnv. Can we avoid the redundant + // invocation? vendorEnabled, mainModVendor, err = gocommand.VendorEnabled(context.TODO(), inv, r.env.GocmdRunner) if err != nil { - return err + return nil, err + } + } else { + vendorEnabled, mainModsVendor, err = gocommand.WorkspaceVendorEnabled(context.Background(), inv, r.env.GocmdRunner) + if err != nil { + return nil, err } } - if mainModVendor != nil && vendorEnabled { - // Vendor mode is on, so all the non-Main modules are irrelevant, - // and we need to search /vendor for everything. - r.mains = []*gocommand.ModuleJSON{mainModVendor} - r.dummyVendorMod = &gocommand.ModuleJSON{ - Path: "", - Dir: filepath.Join(mainModVendor.Dir, "vendor"), + if vendorEnabled { + if mainModVendor != nil { + // Module vendor mode is on, so all the non-Main modules are irrelevant, + // and we need to search /vendor for everything. + r.mains = []*gocommand.ModuleJSON{mainModVendor} + r.dummyVendorMod = &gocommand.ModuleJSON{ + Path: "", + Dir: filepath.Join(mainModVendor.Dir, "vendor"), + } + r.modsByModPath = []*gocommand.ModuleJSON{mainModVendor, r.dummyVendorMod} + r.modsByDir = []*gocommand.ModuleJSON{mainModVendor, r.dummyVendorMod} + } else { + // Workspace vendor mode is on, so all the non-Main modules are irrelevant, + // and we need to search /vendor for everything. + r.mains = mainModsVendor + r.dummyVendorMod = &gocommand.ModuleJSON{ + Path: "", + Dir: filepath.Join(filepath.Dir(goWork), "vendor"), + } + r.modsByModPath = append(append([]*gocommand.ModuleJSON{}, mainModsVendor...), r.dummyVendorMod) + r.modsByDir = append(append([]*gocommand.ModuleJSON{}, mainModsVendor...), r.dummyVendorMod) } - r.modsByModPath = []*gocommand.ModuleJSON{mainModVendor, r.dummyVendorMod} - r.modsByDir = []*gocommand.ModuleJSON{mainModVendor, r.dummyVendorMod} } else { // Vendor mode is off, so run go list -m ... to find everything. err := r.initAllMods() @@ -100,19 +160,14 @@ func (r *ModuleResolver) init() error { // GO111MODULE=on. Other errors are fatal. if err != nil { if errMsg := err.Error(); !strings.Contains(errMsg, "working directory is not part of a module") && !strings.Contains(errMsg, "go.mod file not found") { - return err + return nil, err } } } - if gmc := r.env.Env["GOMODCACHE"]; gmc != "" { - r.moduleCacheDir = gmc - } else { - gopaths := filepath.SplitList(goenv["GOPATH"]) - if len(gopaths) == 0 { - return fmt.Errorf("empty GOPATH") - } - r.moduleCacheDir = filepath.Join(gopaths[0], "/pkg/mod") + r.moduleCacheDir = gomodcacheForEnv(goenv) + if r.moduleCacheDir == "" { + return nil, fmt.Errorf("cannot resolve GOMODCACHE") } sort.Slice(r.modsByModPath, func(i, j int) bool { @@ -128,8 +183,9 @@ func (r *ModuleResolver) init() error { return count(j) < count(i) // descending order }) - r.roots = []gopathwalk.Root{ - {Path: filepath.Join(goenv["GOROOT"], "/src"), Type: gopathwalk.RootGOROOT}, + r.roots = []gopathwalk.Root{} + if goenv["GOROOT"] != "" { // "" happens in tests + r.roots = append(r.roots, gopathwalk.Root{Path: filepath.Join(goenv["GOROOT"], "/src"), Type: gopathwalk.RootGOROOT}) } r.mainByDir = make(map[string]*gocommand.ModuleJSON) for _, main := range r.mains { @@ -141,7 +197,11 @@ func (r *ModuleResolver) init() error { } else { addDep := func(mod *gocommand.ModuleJSON) { if mod.Replace == nil { - // This is redundant with the cache, but we'll skip it cheaply enough. + // This is redundant with the cache, but we'll skip it cheaply enough + // when we encounter it in the module cache scan. + // + // Including it at a lower index in r.roots than the module cache dir + // helps prioritize matches from within existing dependencies. r.roots = append(r.roots, gopathwalk.Root{Path: mod.Dir, Type: gopathwalk.RootModuleCache}) } else { r.roots = append(r.roots, gopathwalk.Root{Path: mod.Dir, Type: gopathwalk.RootOther}) @@ -158,24 +218,40 @@ func (r *ModuleResolver) init() error { addDep(mod) } } + // If provided, share the moduleCacheCache. + // + // TODO(rfindley): The module cache is immutable. However, the loaded + // exports do depend on GOOS and GOARCH. Fortunately, the + // ProcessEnv.buildContext does not adjust these from build.DefaultContext + // (even though it should). So for now, this is OK to share, but we need to + // add logic for handling GOOS/GOARCH. + r.moduleCacheCache = moduleCacheCache r.roots = append(r.roots, gopathwalk.Root{Path: r.moduleCacheDir, Type: gopathwalk.RootModuleCache}) } r.scannedRoots = map[gopathwalk.Root]bool{} if r.moduleCacheCache == nil { - r.moduleCacheCache = &dirInfoCache{ - dirs: map[string]*directoryPackageInfo{}, - listeners: map[*int]cacheListener{}, - } - } - if r.otherCache == nil { - r.otherCache = &dirInfoCache{ - dirs: map[string]*directoryPackageInfo{}, - listeners: map[*int]cacheListener{}, - } + r.moduleCacheCache = NewDirInfoCache() } - r.initialized = true - return nil + r.otherCache = NewDirInfoCache() + return r, nil +} + +// gomodcacheForEnv returns the GOMODCACHE value to use based on the given env +// map, which must have GOMODCACHE and GOPATH populated. +// +// TODO(rfindley): this is defensive refactoring. +// 1. Is this even relevant anymore? Can't we just read GOMODCACHE. +// 2. Use this to separate module cache scanning from other scanning. +func gomodcacheForEnv(goenv map[string]string) string { + if gmc := goenv["GOMODCACHE"]; gmc != "" { + return gmc + } + gopaths := filepath.SplitList(goenv["GOPATH"]) + if len(gopaths) == 0 { + return "" + } + return filepath.Join(gopaths[0], "/pkg/mod") } func (r *ModuleResolver) initAllMods() error { @@ -206,30 +282,86 @@ func (r *ModuleResolver) initAllMods() error { return nil } -func (r *ModuleResolver) ClearForNewScan() { - <-r.scanSema - r.scannedRoots = map[gopathwalk.Root]bool{} - r.otherCache = &dirInfoCache{ - dirs: map[string]*directoryPackageInfo{}, - listeners: map[*int]cacheListener{}, +// ClearForNewScan invalidates the last scan. +// +// It preserves the set of roots, but forgets about the set of directories. +// Though it forgets the set of module cache directories, it remembers their +// contents, since they are assumed to be immutable. +func (r *ModuleResolver) ClearForNewScan() Resolver { + <-r.scanSema // acquire r, to guard scannedRoots + r2 := &ModuleResolver{ + env: r.env, + dummyVendorMod: r.dummyVendorMod, + moduleCacheDir: r.moduleCacheDir, + roots: r.roots, + mains: r.mains, + mainByDir: r.mainByDir, + modsByModPath: r.modsByModPath, + + scanSema: make(chan struct{}, 1), + scannedRoots: make(map[gopathwalk.Root]bool), + otherCache: NewDirInfoCache(), + moduleCacheCache: r.moduleCacheCache, + } + r2.scanSema <- struct{}{} // r2 must start released + // Invalidate root scans. We don't need to invalidate module cache roots, + // because they are immutable. + // (We don't support a use case where GOMODCACHE is cleaned in the middle of + // e.g. a gopls session: the user must restart gopls to get accurate + // imports.) + // + // Scanning for new directories in GOMODCACHE should be handled elsewhere, + // via a call to ScanModuleCache. + for _, root := range r.roots { + if root.Type == gopathwalk.RootModuleCache && r.scannedRoots[root] { + r2.scannedRoots[root] = true + } } - r.scanSema <- struct{}{} + r.scanSema <- struct{}{} // release r + return r2 } -func (r *ModuleResolver) ClearForNewMod() { - <-r.scanSema - *r = ModuleResolver{ - env: r.env, - moduleCacheCache: r.moduleCacheCache, - otherCache: r.otherCache, - scanSema: r.scanSema, +// ClearModuleInfo invalidates resolver state that depends on go.mod file +// contents (essentially, the output of go list -m -json ...). +// +// Notably, it does not forget directory contents, which are reset +// asynchronously via ClearForNewScan. +// +// If the ProcessEnv is a GOPATH environment, ClearModuleInfo is a no op. +// +// TODO(rfindley): move this to a new env.go, consolidating ProcessEnv methods. +func (e *ProcessEnv) ClearModuleInfo() { + if r, ok := e.resolver.(*ModuleResolver); ok { + resolver, err := newModuleResolver(e, e.ModCache) + if err != nil { + e.resolver = nil + e.resolverErr = err + return + } + + <-r.scanSema // acquire (guards caches) + resolver.moduleCacheCache = r.moduleCacheCache + resolver.otherCache = r.otherCache + r.scanSema <- struct{}{} // release + + e.UpdateResolver(resolver) } - r.init() - r.scanSema <- struct{}{} } -// findPackage returns the module and directory that contains the package at -// the given import path, or returns nil, "" if no module is in scope. +// UpdateResolver sets the resolver for the ProcessEnv to use in imports +// operations. Only for use with the result of [Resolver.ClearForNewScan]. +// +// TODO(rfindley): this awkward API is a result of the (arguably) inverted +// relationship between configuration and state described in the doc comment +// for [ProcessEnv]. +func (e *ProcessEnv) UpdateResolver(r Resolver) { + e.resolver = r + e.resolverErr = nil +} + +// findPackage returns the module and directory from within the main modules +// and their dependencies that contains the package at the given import path, +// or returns nil, "" if no module is in scope. func (r *ModuleResolver) findPackage(importPath string) (*gocommand.ModuleJSON, string) { // This can't find packages in the stdlib, but that's harmless for all // the existing code paths. @@ -295,10 +427,6 @@ func (r *ModuleResolver) cacheStore(info directoryPackageInfo) { } } -func (r *ModuleResolver) cacheKeys() []string { - return append(r.moduleCacheCache.Keys(), r.otherCache.Keys()...) -} - // cachePackageName caches the package name for a dir already in the cache. func (r *ModuleResolver) cachePackageName(info directoryPackageInfo) (string, error) { if info.rootType == gopathwalk.RootModuleCache { @@ -307,7 +435,7 @@ func (r *ModuleResolver) cachePackageName(info directoryPackageInfo) (string, er return r.otherCache.CachePackageName(info) } -func (r *ModuleResolver) cacheExports(ctx context.Context, env *ProcessEnv, info directoryPackageInfo) (string, []string, error) { +func (r *ModuleResolver) cacheExports(ctx context.Context, env *ProcessEnv, info directoryPackageInfo) (string, []stdlib.Symbol, error) { if info.rootType == gopathwalk.RootModuleCache { return r.moduleCacheCache.CacheExports(ctx, env, info) } @@ -367,15 +495,15 @@ func (r *ModuleResolver) dirIsNestedModule(dir string, mod *gocommand.ModuleJSON return modDir != mod.Dir } -func (r *ModuleResolver) modInfo(dir string) (modDir string, modName string) { - readModName := func(modFile string) string { - modBytes, err := os.ReadFile(modFile) - if err != nil { - return "" - } - return modulePath(modBytes) +func readModName(modFile string) string { + modBytes, err := os.ReadFile(modFile) + if err != nil { + return "" } + return modulePath(modBytes) +} +func (r *ModuleResolver) modInfo(dir string) (modDir, modName string) { if r.dirInModuleCache(dir) { if matches := modCacheRegexp.FindStringSubmatch(dir); len(matches) == 3 { index := strings.Index(dir, matches[1]+"@"+matches[2]) @@ -409,11 +537,9 @@ func (r *ModuleResolver) dirInModuleCache(dir string) bool { } func (r *ModuleResolver) loadPackageNames(importPaths []string, srcDir string) (map[string]string, error) { - if err := r.init(); err != nil { - return nil, err - } names := map[string]string{} for _, path := range importPaths { + // TODO(rfindley): shouldn't this use the dirInfoCache? _, packageDir := r.findPackage(path) if packageDir == "" { continue @@ -431,10 +557,6 @@ func (r *ModuleResolver) scan(ctx context.Context, callback *scanCallback) error ctx, done := event.Start(ctx, "imports.ModuleResolver.scan") defer done() - if err := r.init(); err != nil { - return err - } - processDir := func(info directoryPackageInfo) { // Skip this directory if we were not able to get the package information successfully. if scanned, err := info.reachedStatus(directoryScanned); !scanned || err != nil { @@ -444,18 +566,18 @@ func (r *ModuleResolver) scan(ctx context.Context, callback *scanCallback) error if err != nil { return } - if !callback.dirFound(pkg) { return } + pkg.packageName, err = r.cachePackageName(info) if err != nil { return } - if !callback.packageNameLoaded(pkg) { return } + _, exports, err := r.loadExports(ctx, pkg, false) if err != nil { return @@ -494,7 +616,6 @@ func (r *ModuleResolver) scan(ctx context.Context, callback *scanCallback) error return packageScanned } - // Add anything new to the cache, and process it if we're still listening. add := func(root gopathwalk.Root, dir string) { r.cacheStore(r.scanDirForPackage(root, dir)) } @@ -509,9 +630,9 @@ func (r *ModuleResolver) scan(ctx context.Context, callback *scanCallback) error select { case <-ctx.Done(): return - case <-r.scanSema: + case <-r.scanSema: // acquire } - defer func() { r.scanSema <- struct{}{} }() + defer func() { r.scanSema <- struct{}{} }() // release // We have the lock on r.scannedRoots, and no other scans can run. for _, root := range roots { if ctx.Err() != nil { @@ -534,7 +655,7 @@ func (r *ModuleResolver) scan(ctx context.Context, callback *scanCallback) error } func (r *ModuleResolver) scoreImportPath(ctx context.Context, path string) float64 { - if _, ok := stdlib[path]; ok { + if stdlib.HasPackage(path) { return MaxRelevance } mod, _ := r.findPackage(path) @@ -612,10 +733,7 @@ func (r *ModuleResolver) canonicalize(info directoryPackageInfo) (*pkg, error) { return res, nil } -func (r *ModuleResolver) loadExports(ctx context.Context, pkg *pkg, includeTest bool) (string, []string, error) { - if err := r.init(); err != nil { - return "", nil, err - } +func (r *ModuleResolver) loadExports(ctx context.Context, pkg *pkg, includeTest bool) (string, []stdlib.Symbol, error) { if info, ok := r.cacheLoad(pkg.dir); ok && !includeTest { return r.cacheExports(ctx, r.env, info) } diff --git a/vendor/golang.org/x/tools/internal/imports/mod_cache.go b/vendor/golang.org/x/tools/internal/imports/mod_cache.go index 45690abbb..b1192696b 100644 --- a/vendor/golang.org/x/tools/internal/imports/mod_cache.go +++ b/vendor/golang.org/x/tools/internal/imports/mod_cache.go @@ -7,9 +7,14 @@ package imports import ( "context" "fmt" + "path" + "path/filepath" + "strings" "sync" + "golang.org/x/mod/module" "golang.org/x/tools/internal/gopathwalk" + "golang.org/x/tools/internal/stdlib" ) // To find packages to import, the resolver needs to know about all of @@ -39,6 +44,8 @@ const ( exportsLoaded ) +// directoryPackageInfo holds (possibly incomplete) information about packages +// contained in a given directory. type directoryPackageInfo struct { // status indicates the extent to which this struct has been filled in. status directoryPackageStatus @@ -63,8 +70,11 @@ type directoryPackageInfo struct { packageName string // the package name, as declared in the source. // Set when status >= exportsLoaded. - - exports []string + // TODO(rfindley): it's hard to see this, but exports depend implicitly on + // the default build context GOOS and GOARCH. + // + // We can make this explicit, and key exports by GOOS, GOARCH. + exports []stdlib.Symbol } // reachedStatus returns true when info has a status at least target and any error associated with @@ -79,7 +89,7 @@ func (info *directoryPackageInfo) reachedStatus(target directoryPackageStatus) ( return true, nil } -// dirInfoCache is a concurrency safe map for storing information about +// DirInfoCache is a concurrency-safe map for storing information about // directories that may contain packages. // // The information in this cache is built incrementally. Entries are initialized in scan. @@ -92,21 +102,26 @@ func (info *directoryPackageInfo) reachedStatus(target directoryPackageStatus) ( // The information in the cache is not expected to change for the cache's // lifetime, so there is no protection against competing writes. Users should // take care not to hold the cache across changes to the underlying files. -// -// TODO(suzmue): consider other concurrency strategies and data structures (RWLocks, sync.Map, etc) -type dirInfoCache struct { +type DirInfoCache struct { mu sync.Mutex // dirs stores information about packages in directories, keyed by absolute path. dirs map[string]*directoryPackageInfo listeners map[*int]cacheListener } +func NewDirInfoCache() *DirInfoCache { + return &DirInfoCache{ + dirs: make(map[string]*directoryPackageInfo), + listeners: make(map[*int]cacheListener), + } +} + type cacheListener func(directoryPackageInfo) // ScanAndListen calls listener on all the items in the cache, and on anything // newly added. The returned stop function waits for all in-flight callbacks to // finish and blocks new ones. -func (d *dirInfoCache) ScanAndListen(ctx context.Context, listener cacheListener) func() { +func (d *DirInfoCache) ScanAndListen(ctx context.Context, listener cacheListener) func() { ctx, cancel := context.WithCancel(ctx) // Flushing out all the callbacks is tricky without knowing how many there @@ -162,8 +177,10 @@ func (d *dirInfoCache) ScanAndListen(ctx context.Context, listener cacheListener } // Store stores the package info for dir. -func (d *dirInfoCache) Store(dir string, info directoryPackageInfo) { +func (d *DirInfoCache) Store(dir string, info directoryPackageInfo) { d.mu.Lock() + // TODO(rfindley, golang/go#59216): should we overwrite an existing entry? + // That seems incorrect as the cache should be idempotent. _, old := d.dirs[dir] d.dirs[dir] = &info var listeners []cacheListener @@ -180,7 +197,7 @@ func (d *dirInfoCache) Store(dir string, info directoryPackageInfo) { } // Load returns a copy of the directoryPackageInfo for absolute directory dir. -func (d *dirInfoCache) Load(dir string) (directoryPackageInfo, bool) { +func (d *DirInfoCache) Load(dir string) (directoryPackageInfo, bool) { d.mu.Lock() defer d.mu.Unlock() info, ok := d.dirs[dir] @@ -191,7 +208,7 @@ func (d *dirInfoCache) Load(dir string) (directoryPackageInfo, bool) { } // Keys returns the keys currently present in d. -func (d *dirInfoCache) Keys() (keys []string) { +func (d *DirInfoCache) Keys() (keys []string) { d.mu.Lock() defer d.mu.Unlock() for key := range d.dirs { @@ -200,7 +217,7 @@ func (d *dirInfoCache) Keys() (keys []string) { return keys } -func (d *dirInfoCache) CachePackageName(info directoryPackageInfo) (string, error) { +func (d *DirInfoCache) CachePackageName(info directoryPackageInfo) (string, error) { if loaded, err := info.reachedStatus(nameLoaded); loaded { return info.packageName, err } @@ -213,7 +230,7 @@ func (d *dirInfoCache) CachePackageName(info directoryPackageInfo) (string, erro return info.packageName, info.err } -func (d *dirInfoCache) CacheExports(ctx context.Context, env *ProcessEnv, info directoryPackageInfo) (string, []string, error) { +func (d *DirInfoCache) CacheExports(ctx context.Context, env *ProcessEnv, info directoryPackageInfo) (string, []stdlib.Symbol, error) { if reached, _ := info.reachedStatus(exportsLoaded); reached { return info.packageName, info.exports, info.err } @@ -234,3 +251,81 @@ func (d *dirInfoCache) CacheExports(ctx context.Context, env *ProcessEnv, info d d.Store(info.dir, info) return info.packageName, info.exports, info.err } + +// ScanModuleCache walks the given directory, which must be a GOMODCACHE value, +// for directory package information, storing the results in cache. +func ScanModuleCache(dir string, cache *DirInfoCache, logf func(string, ...any)) { + // Note(rfindley): it's hard to see, but this function attempts to implement + // just the side effects on cache of calling PrimeCache with a ProcessEnv + // that has the given dir as its GOMODCACHE. + // + // Teasing out the control flow, we see that we can avoid any handling of + // vendor/ and can infer module info entirely from the path, simplifying the + // logic here. + + root := gopathwalk.Root{ + Path: filepath.Clean(dir), + Type: gopathwalk.RootModuleCache, + } + + directoryInfo := func(root gopathwalk.Root, dir string) directoryPackageInfo { + // This is a copy of ModuleResolver.scanDirForPackage, trimmed down to + // logic that applies to a module cache directory. + + subdir := "" + if dir != root.Path { + subdir = dir[len(root.Path)+len("/"):] + } + + matches := modCacheRegexp.FindStringSubmatch(subdir) + if len(matches) == 0 { + return directoryPackageInfo{ + status: directoryScanned, + err: fmt.Errorf("invalid module cache path: %v", subdir), + } + } + modPath, err := module.UnescapePath(filepath.ToSlash(matches[1])) + if err != nil { + if logf != nil { + logf("decoding module cache path %q: %v", subdir, err) + } + return directoryPackageInfo{ + status: directoryScanned, + err: fmt.Errorf("decoding module cache path %q: %v", subdir, err), + } + } + importPath := path.Join(modPath, filepath.ToSlash(matches[3])) + index := strings.Index(dir, matches[1]+"@"+matches[2]) + modDir := filepath.Join(dir[:index], matches[1]+"@"+matches[2]) + modName := readModName(filepath.Join(modDir, "go.mod")) + return directoryPackageInfo{ + status: directoryScanned, + dir: dir, + rootType: root.Type, + nonCanonicalImportPath: importPath, + moduleDir: modDir, + moduleName: modName, + } + } + + add := func(root gopathwalk.Root, dir string) { + info := directoryInfo(root, dir) + cache.Store(info.dir, info) + } + + skip := func(_ gopathwalk.Root, dir string) bool { + // Skip directories that have already been scanned. + // + // Note that gopathwalk only adds "package" directories, which must contain + // a .go file, and all such package directories in the module cache are + // immutable. So if we can load a dir, it can be skipped. + info, ok := cache.Load(dir) + if !ok { + return false + } + packageScanned, _ := info.reachedStatus(directoryScanned) + return packageScanned + } + + gopathwalk.WalkSkip([]gopathwalk.Root{root}, add, skip, gopathwalk.Options{Logf: logf, ModulesEnabled: true}) +} diff --git a/vendor/golang.org/x/tools/internal/imports/sortimports.go b/vendor/golang.org/x/tools/internal/imports/sortimports.go index 1a0a7ebd9..da8194fd9 100644 --- a/vendor/golang.org/x/tools/internal/imports/sortimports.go +++ b/vendor/golang.org/x/tools/internal/imports/sortimports.go @@ -18,7 +18,7 @@ import ( // sortImports sorts runs of consecutive import lines in import blocks in f. // It also removes duplicate imports when it is possible to do so without data loss. // -// It may mutate the token.File. +// It may mutate the token.File and the ast.File. func sortImports(localPrefix string, tokFile *token.File, f *ast.File) { for i, d := range f.Decls { d, ok := d.(*ast.GenDecl) diff --git a/vendor/golang.org/x/tools/internal/imports/zstdlib.go b/vendor/golang.org/x/tools/internal/imports/zstdlib.go deleted file mode 100644 index 9f992c2be..000000000 --- a/vendor/golang.org/x/tools/internal/imports/zstdlib.go +++ /dev/null @@ -1,11345 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Code generated by mkstdlib.go. DO NOT EDIT. - -package imports - -var stdlib = map[string][]string{ - "archive/tar": { - "ErrFieldTooLong", - "ErrHeader", - "ErrInsecurePath", - "ErrWriteAfterClose", - "ErrWriteTooLong", - "FileInfoHeader", - "Format", - "FormatGNU", - "FormatPAX", - "FormatUSTAR", - "FormatUnknown", - "Header", - "NewReader", - "NewWriter", - "Reader", - "TypeBlock", - "TypeChar", - "TypeCont", - "TypeDir", - "TypeFifo", - "TypeGNULongLink", - "TypeGNULongName", - "TypeGNUSparse", - "TypeLink", - "TypeReg", - "TypeRegA", - "TypeSymlink", - "TypeXGlobalHeader", - "TypeXHeader", - "Writer", - }, - "archive/zip": { - "Compressor", - "Decompressor", - "Deflate", - "ErrAlgorithm", - "ErrChecksum", - "ErrFormat", - "ErrInsecurePath", - "File", - "FileHeader", - "FileInfoHeader", - "NewReader", - "NewWriter", - "OpenReader", - "ReadCloser", - "Reader", - "RegisterCompressor", - "RegisterDecompressor", - "Store", - "Writer", - }, - "bufio": { - "ErrAdvanceTooFar", - "ErrBadReadCount", - "ErrBufferFull", - "ErrFinalToken", - "ErrInvalidUnreadByte", - "ErrInvalidUnreadRune", - "ErrNegativeAdvance", - "ErrNegativeCount", - "ErrTooLong", - "MaxScanTokenSize", - "NewReadWriter", - "NewReader", - "NewReaderSize", - "NewScanner", - "NewWriter", - "NewWriterSize", - "ReadWriter", - "Reader", - "ScanBytes", - "ScanLines", - "ScanRunes", - "ScanWords", - "Scanner", - "SplitFunc", - "Writer", - }, - "bytes": { - "Buffer", - "Clone", - "Compare", - "Contains", - "ContainsAny", - "ContainsFunc", - "ContainsRune", - "Count", - "Cut", - "CutPrefix", - "CutSuffix", - "Equal", - "EqualFold", - "ErrTooLarge", - "Fields", - "FieldsFunc", - "HasPrefix", - "HasSuffix", - "Index", - "IndexAny", - "IndexByte", - "IndexFunc", - "IndexRune", - "Join", - "LastIndex", - "LastIndexAny", - "LastIndexByte", - "LastIndexFunc", - "Map", - "MinRead", - "NewBuffer", - "NewBufferString", - "NewReader", - "Reader", - "Repeat", - "Replace", - "ReplaceAll", - "Runes", - "Split", - "SplitAfter", - "SplitAfterN", - "SplitN", - "Title", - "ToLower", - "ToLowerSpecial", - "ToTitle", - "ToTitleSpecial", - "ToUpper", - "ToUpperSpecial", - "ToValidUTF8", - "Trim", - "TrimFunc", - "TrimLeft", - "TrimLeftFunc", - "TrimPrefix", - "TrimRight", - "TrimRightFunc", - "TrimSpace", - "TrimSuffix", - }, - "cmp": { - "Compare", - "Less", - "Ordered", - }, - "compress/bzip2": { - "NewReader", - "StructuralError", - }, - "compress/flate": { - "BestCompression", - "BestSpeed", - "CorruptInputError", - "DefaultCompression", - "HuffmanOnly", - "InternalError", - "NewReader", - "NewReaderDict", - "NewWriter", - "NewWriterDict", - "NoCompression", - "ReadError", - "Reader", - "Resetter", - "WriteError", - "Writer", - }, - "compress/gzip": { - "BestCompression", - "BestSpeed", - "DefaultCompression", - "ErrChecksum", - "ErrHeader", - "Header", - "HuffmanOnly", - "NewReader", - "NewWriter", - "NewWriterLevel", - "NoCompression", - "Reader", - "Writer", - }, - "compress/lzw": { - "LSB", - "MSB", - "NewReader", - "NewWriter", - "Order", - "Reader", - "Writer", - }, - "compress/zlib": { - "BestCompression", - "BestSpeed", - "DefaultCompression", - "ErrChecksum", - "ErrDictionary", - "ErrHeader", - "HuffmanOnly", - "NewReader", - "NewReaderDict", - "NewWriter", - "NewWriterLevel", - "NewWriterLevelDict", - "NoCompression", - "Resetter", - "Writer", - }, - "container/heap": { - "Fix", - "Init", - "Interface", - "Pop", - "Push", - "Remove", - }, - "container/list": { - "Element", - "List", - "New", - }, - "container/ring": { - "New", - "Ring", - }, - "context": { - "AfterFunc", - "Background", - "CancelCauseFunc", - "CancelFunc", - "Canceled", - "Cause", - "Context", - "DeadlineExceeded", - "TODO", - "WithCancel", - "WithCancelCause", - "WithDeadline", - "WithDeadlineCause", - "WithTimeout", - "WithTimeoutCause", - "WithValue", - "WithoutCancel", - }, - "crypto": { - "BLAKE2b_256", - "BLAKE2b_384", - "BLAKE2b_512", - "BLAKE2s_256", - "Decrypter", - "DecrypterOpts", - "Hash", - "MD4", - "MD5", - "MD5SHA1", - "PrivateKey", - "PublicKey", - "RIPEMD160", - "RegisterHash", - "SHA1", - "SHA224", - "SHA256", - "SHA384", - "SHA3_224", - "SHA3_256", - "SHA3_384", - "SHA3_512", - "SHA512", - "SHA512_224", - "SHA512_256", - "Signer", - "SignerOpts", - }, - "crypto/aes": { - "BlockSize", - "KeySizeError", - "NewCipher", - }, - "crypto/cipher": { - "AEAD", - "Block", - "BlockMode", - "NewCBCDecrypter", - "NewCBCEncrypter", - "NewCFBDecrypter", - "NewCFBEncrypter", - "NewCTR", - "NewGCM", - "NewGCMWithNonceSize", - "NewGCMWithTagSize", - "NewOFB", - "Stream", - "StreamReader", - "StreamWriter", - }, - "crypto/des": { - "BlockSize", - "KeySizeError", - "NewCipher", - "NewTripleDESCipher", - }, - "crypto/dsa": { - "ErrInvalidPublicKey", - "GenerateKey", - "GenerateParameters", - "L1024N160", - "L2048N224", - "L2048N256", - "L3072N256", - "ParameterSizes", - "Parameters", - "PrivateKey", - "PublicKey", - "Sign", - "Verify", - }, - "crypto/ecdh": { - "Curve", - "P256", - "P384", - "P521", - "PrivateKey", - "PublicKey", - "X25519", - }, - "crypto/ecdsa": { - "GenerateKey", - "PrivateKey", - "PublicKey", - "Sign", - "SignASN1", - "Verify", - "VerifyASN1", - }, - "crypto/ed25519": { - "GenerateKey", - "NewKeyFromSeed", - "Options", - "PrivateKey", - "PrivateKeySize", - "PublicKey", - "PublicKeySize", - "SeedSize", - "Sign", - "SignatureSize", - "Verify", - "VerifyWithOptions", - }, - "crypto/elliptic": { - "Curve", - "CurveParams", - "GenerateKey", - "Marshal", - "MarshalCompressed", - "P224", - "P256", - "P384", - "P521", - "Unmarshal", - "UnmarshalCompressed", - }, - "crypto/hmac": { - "Equal", - "New", - }, - "crypto/md5": { - "BlockSize", - "New", - "Size", - "Sum", - }, - "crypto/rand": { - "Int", - "Prime", - "Read", - "Reader", - }, - "crypto/rc4": { - "Cipher", - "KeySizeError", - "NewCipher", - }, - "crypto/rsa": { - "CRTValue", - "DecryptOAEP", - "DecryptPKCS1v15", - "DecryptPKCS1v15SessionKey", - "EncryptOAEP", - "EncryptPKCS1v15", - "ErrDecryption", - "ErrMessageTooLong", - "ErrVerification", - "GenerateKey", - "GenerateMultiPrimeKey", - "OAEPOptions", - "PKCS1v15DecryptOptions", - "PSSOptions", - "PSSSaltLengthAuto", - "PSSSaltLengthEqualsHash", - "PrecomputedValues", - "PrivateKey", - "PublicKey", - "SignPKCS1v15", - "SignPSS", - "VerifyPKCS1v15", - "VerifyPSS", - }, - "crypto/sha1": { - "BlockSize", - "New", - "Size", - "Sum", - }, - "crypto/sha256": { - "BlockSize", - "New", - "New224", - "Size", - "Size224", - "Sum224", - "Sum256", - }, - "crypto/sha512": { - "BlockSize", - "New", - "New384", - "New512_224", - "New512_256", - "Size", - "Size224", - "Size256", - "Size384", - "Sum384", - "Sum512", - "Sum512_224", - "Sum512_256", - }, - "crypto/subtle": { - "ConstantTimeByteEq", - "ConstantTimeCompare", - "ConstantTimeCopy", - "ConstantTimeEq", - "ConstantTimeLessOrEq", - "ConstantTimeSelect", - "XORBytes", - }, - "crypto/tls": { - "AlertError", - "Certificate", - "CertificateRequestInfo", - "CertificateVerificationError", - "CipherSuite", - "CipherSuiteName", - "CipherSuites", - "Client", - "ClientAuthType", - "ClientHelloInfo", - "ClientSessionCache", - "ClientSessionState", - "Config", - "Conn", - "ConnectionState", - "CurveID", - "CurveP256", - "CurveP384", - "CurveP521", - "Dial", - "DialWithDialer", - "Dialer", - "ECDSAWithP256AndSHA256", - "ECDSAWithP384AndSHA384", - "ECDSAWithP521AndSHA512", - "ECDSAWithSHA1", - "Ed25519", - "InsecureCipherSuites", - "Listen", - "LoadX509KeyPair", - "NewLRUClientSessionCache", - "NewListener", - "NewResumptionState", - "NoClientCert", - "PKCS1WithSHA1", - "PKCS1WithSHA256", - "PKCS1WithSHA384", - "PKCS1WithSHA512", - "PSSWithSHA256", - "PSSWithSHA384", - "PSSWithSHA512", - "ParseSessionState", - "QUICClient", - "QUICConfig", - "QUICConn", - "QUICEncryptionLevel", - "QUICEncryptionLevelApplication", - "QUICEncryptionLevelEarly", - "QUICEncryptionLevelHandshake", - "QUICEncryptionLevelInitial", - "QUICEvent", - "QUICEventKind", - "QUICHandshakeDone", - "QUICNoEvent", - "QUICRejectedEarlyData", - "QUICServer", - "QUICSessionTicketOptions", - "QUICSetReadSecret", - "QUICSetWriteSecret", - "QUICTransportParameters", - "QUICTransportParametersRequired", - "QUICWriteData", - "RecordHeaderError", - "RenegotiateFreelyAsClient", - "RenegotiateNever", - "RenegotiateOnceAsClient", - "RenegotiationSupport", - "RequestClientCert", - "RequireAndVerifyClientCert", - "RequireAnyClientCert", - "Server", - "SessionState", - "SignatureScheme", - "TLS_AES_128_GCM_SHA256", - "TLS_AES_256_GCM_SHA384", - "TLS_CHACHA20_POLY1305_SHA256", - "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", - "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", - "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", - "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", - "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", - "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305", - "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256", - "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA", - "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA", - "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", - "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", - "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", - "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", - "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", - "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305", - "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256", - "TLS_ECDHE_RSA_WITH_RC4_128_SHA", - "TLS_FALLBACK_SCSV", - "TLS_RSA_WITH_3DES_EDE_CBC_SHA", - "TLS_RSA_WITH_AES_128_CBC_SHA", - "TLS_RSA_WITH_AES_128_CBC_SHA256", - "TLS_RSA_WITH_AES_128_GCM_SHA256", - "TLS_RSA_WITH_AES_256_CBC_SHA", - "TLS_RSA_WITH_AES_256_GCM_SHA384", - "TLS_RSA_WITH_RC4_128_SHA", - "VerifyClientCertIfGiven", - "VersionName", - "VersionSSL30", - "VersionTLS10", - "VersionTLS11", - "VersionTLS12", - "VersionTLS13", - "X25519", - "X509KeyPair", - }, - "crypto/x509": { - "CANotAuthorizedForExtKeyUsage", - "CANotAuthorizedForThisName", - "CertPool", - "Certificate", - "CertificateInvalidError", - "CertificateRequest", - "ConstraintViolationError", - "CreateCertificate", - "CreateCertificateRequest", - "CreateRevocationList", - "DSA", - "DSAWithSHA1", - "DSAWithSHA256", - "DecryptPEMBlock", - "ECDSA", - "ECDSAWithSHA1", - "ECDSAWithSHA256", - "ECDSAWithSHA384", - "ECDSAWithSHA512", - "Ed25519", - "EncryptPEMBlock", - "ErrUnsupportedAlgorithm", - "Expired", - "ExtKeyUsage", - "ExtKeyUsageAny", - "ExtKeyUsageClientAuth", - "ExtKeyUsageCodeSigning", - "ExtKeyUsageEmailProtection", - "ExtKeyUsageIPSECEndSystem", - "ExtKeyUsageIPSECTunnel", - "ExtKeyUsageIPSECUser", - "ExtKeyUsageMicrosoftCommercialCodeSigning", - "ExtKeyUsageMicrosoftKernelCodeSigning", - "ExtKeyUsageMicrosoftServerGatedCrypto", - "ExtKeyUsageNetscapeServerGatedCrypto", - "ExtKeyUsageOCSPSigning", - "ExtKeyUsageServerAuth", - "ExtKeyUsageTimeStamping", - "HostnameError", - "IncompatibleUsage", - "IncorrectPasswordError", - "InsecureAlgorithmError", - "InvalidReason", - "IsEncryptedPEMBlock", - "KeyUsage", - "KeyUsageCRLSign", - "KeyUsageCertSign", - "KeyUsageContentCommitment", - "KeyUsageDataEncipherment", - "KeyUsageDecipherOnly", - "KeyUsageDigitalSignature", - "KeyUsageEncipherOnly", - "KeyUsageKeyAgreement", - "KeyUsageKeyEncipherment", - "MD2WithRSA", - "MD5WithRSA", - "MarshalECPrivateKey", - "MarshalPKCS1PrivateKey", - "MarshalPKCS1PublicKey", - "MarshalPKCS8PrivateKey", - "MarshalPKIXPublicKey", - "NameConstraintsWithoutSANs", - "NameMismatch", - "NewCertPool", - "NotAuthorizedToSign", - "PEMCipher", - "PEMCipher3DES", - "PEMCipherAES128", - "PEMCipherAES192", - "PEMCipherAES256", - "PEMCipherDES", - "ParseCRL", - "ParseCertificate", - "ParseCertificateRequest", - "ParseCertificates", - "ParseDERCRL", - "ParseECPrivateKey", - "ParsePKCS1PrivateKey", - "ParsePKCS1PublicKey", - "ParsePKCS8PrivateKey", - "ParsePKIXPublicKey", - "ParseRevocationList", - "PublicKeyAlgorithm", - "PureEd25519", - "RSA", - "RevocationList", - "RevocationListEntry", - "SHA1WithRSA", - "SHA256WithRSA", - "SHA256WithRSAPSS", - "SHA384WithRSA", - "SHA384WithRSAPSS", - "SHA512WithRSA", - "SHA512WithRSAPSS", - "SetFallbackRoots", - "SignatureAlgorithm", - "SystemCertPool", - "SystemRootsError", - "TooManyConstraints", - "TooManyIntermediates", - "UnconstrainedName", - "UnhandledCriticalExtension", - "UnknownAuthorityError", - "UnknownPublicKeyAlgorithm", - "UnknownSignatureAlgorithm", - "VerifyOptions", - }, - "crypto/x509/pkix": { - "AlgorithmIdentifier", - "AttributeTypeAndValue", - "AttributeTypeAndValueSET", - "CertificateList", - "Extension", - "Name", - "RDNSequence", - "RelativeDistinguishedNameSET", - "RevokedCertificate", - "TBSCertificateList", - }, - "database/sql": { - "ColumnType", - "Conn", - "DB", - "DBStats", - "Drivers", - "ErrConnDone", - "ErrNoRows", - "ErrTxDone", - "IsolationLevel", - "LevelDefault", - "LevelLinearizable", - "LevelReadCommitted", - "LevelReadUncommitted", - "LevelRepeatableRead", - "LevelSerializable", - "LevelSnapshot", - "LevelWriteCommitted", - "Named", - "NamedArg", - "NullBool", - "NullByte", - "NullFloat64", - "NullInt16", - "NullInt32", - "NullInt64", - "NullString", - "NullTime", - "Open", - "OpenDB", - "Out", - "RawBytes", - "Register", - "Result", - "Row", - "Rows", - "Scanner", - "Stmt", - "Tx", - "TxOptions", - }, - "database/sql/driver": { - "Bool", - "ColumnConverter", - "Conn", - "ConnBeginTx", - "ConnPrepareContext", - "Connector", - "DefaultParameterConverter", - "Driver", - "DriverContext", - "ErrBadConn", - "ErrRemoveArgument", - "ErrSkip", - "Execer", - "ExecerContext", - "Int32", - "IsScanValue", - "IsValue", - "IsolationLevel", - "NamedValue", - "NamedValueChecker", - "NotNull", - "Null", - "Pinger", - "Queryer", - "QueryerContext", - "Result", - "ResultNoRows", - "Rows", - "RowsAffected", - "RowsColumnTypeDatabaseTypeName", - "RowsColumnTypeLength", - "RowsColumnTypeNullable", - "RowsColumnTypePrecisionScale", - "RowsColumnTypeScanType", - "RowsNextResultSet", - "SessionResetter", - "Stmt", - "StmtExecContext", - "StmtQueryContext", - "String", - "Tx", - "TxOptions", - "Validator", - "Value", - "ValueConverter", - "Valuer", - }, - "debug/buildinfo": { - "BuildInfo", - "Read", - "ReadFile", - }, - "debug/dwarf": { - "AddrType", - "ArrayType", - "Attr", - "AttrAbstractOrigin", - "AttrAccessibility", - "AttrAddrBase", - "AttrAddrClass", - "AttrAlignment", - "AttrAllocated", - "AttrArtificial", - "AttrAssociated", - "AttrBaseTypes", - "AttrBinaryScale", - "AttrBitOffset", - "AttrBitSize", - "AttrByteSize", - "AttrCallAllCalls", - "AttrCallAllSourceCalls", - "AttrCallAllTailCalls", - "AttrCallColumn", - "AttrCallDataLocation", - "AttrCallDataValue", - "AttrCallFile", - "AttrCallLine", - "AttrCallOrigin", - "AttrCallPC", - "AttrCallParameter", - "AttrCallReturnPC", - "AttrCallTailCall", - "AttrCallTarget", - "AttrCallTargetClobbered", - "AttrCallValue", - "AttrCalling", - "AttrCommonRef", - "AttrCompDir", - "AttrConstExpr", - "AttrConstValue", - "AttrContainingType", - "AttrCount", - "AttrDataBitOffset", - "AttrDataLocation", - "AttrDataMemberLoc", - "AttrDecimalScale", - "AttrDecimalSign", - "AttrDeclColumn", - "AttrDeclFile", - "AttrDeclLine", - "AttrDeclaration", - "AttrDefaultValue", - "AttrDefaulted", - "AttrDeleted", - "AttrDescription", - "AttrDigitCount", - "AttrDiscr", - "AttrDiscrList", - "AttrDiscrValue", - "AttrDwoName", - "AttrElemental", - "AttrEncoding", - "AttrEndianity", - "AttrEntrypc", - "AttrEnumClass", - "AttrExplicit", - "AttrExportSymbols", - "AttrExtension", - "AttrExternal", - "AttrFrameBase", - "AttrFriend", - "AttrHighpc", - "AttrIdentifierCase", - "AttrImport", - "AttrInline", - "AttrIsOptional", - "AttrLanguage", - "AttrLinkageName", - "AttrLocation", - "AttrLoclistsBase", - "AttrLowerBound", - "AttrLowpc", - "AttrMacroInfo", - "AttrMacros", - "AttrMainSubprogram", - "AttrMutable", - "AttrName", - "AttrNamelistItem", - "AttrNoreturn", - "AttrObjectPointer", - "AttrOrdering", - "AttrPictureString", - "AttrPriority", - "AttrProducer", - "AttrPrototyped", - "AttrPure", - "AttrRanges", - "AttrRank", - "AttrRecursive", - "AttrReference", - "AttrReturnAddr", - "AttrRnglistsBase", - "AttrRvalueReference", - "AttrSegment", - "AttrSibling", - "AttrSignature", - "AttrSmall", - "AttrSpecification", - "AttrStartScope", - "AttrStaticLink", - "AttrStmtList", - "AttrStrOffsetsBase", - "AttrStride", - "AttrStrideSize", - "AttrStringLength", - "AttrStringLengthBitSize", - "AttrStringLengthByteSize", - "AttrThreadsScaled", - "AttrTrampoline", - "AttrType", - "AttrUpperBound", - "AttrUseLocation", - "AttrUseUTF8", - "AttrVarParam", - "AttrVirtuality", - "AttrVisibility", - "AttrVtableElemLoc", - "BasicType", - "BoolType", - "CharType", - "Class", - "ClassAddrPtr", - "ClassAddress", - "ClassBlock", - "ClassConstant", - "ClassExprLoc", - "ClassFlag", - "ClassLinePtr", - "ClassLocList", - "ClassLocListPtr", - "ClassMacPtr", - "ClassRangeListPtr", - "ClassReference", - "ClassReferenceAlt", - "ClassReferenceSig", - "ClassRngList", - "ClassRngListsPtr", - "ClassStrOffsetsPtr", - "ClassString", - "ClassStringAlt", - "ClassUnknown", - "CommonType", - "ComplexType", - "Data", - "DecodeError", - "DotDotDotType", - "Entry", - "EnumType", - "EnumValue", - "ErrUnknownPC", - "Field", - "FloatType", - "FuncType", - "IntType", - "LineEntry", - "LineFile", - "LineReader", - "LineReaderPos", - "New", - "Offset", - "PtrType", - "QualType", - "Reader", - "StructField", - "StructType", - "Tag", - "TagAccessDeclaration", - "TagArrayType", - "TagAtomicType", - "TagBaseType", - "TagCallSite", - "TagCallSiteParameter", - "TagCatchDwarfBlock", - "TagClassType", - "TagCoarrayType", - "TagCommonDwarfBlock", - "TagCommonInclusion", - "TagCompileUnit", - "TagCondition", - "TagConstType", - "TagConstant", - "TagDwarfProcedure", - "TagDynamicType", - "TagEntryPoint", - "TagEnumerationType", - "TagEnumerator", - "TagFileType", - "TagFormalParameter", - "TagFriend", - "TagGenericSubrange", - "TagImmutableType", - "TagImportedDeclaration", - "TagImportedModule", - "TagImportedUnit", - "TagInheritance", - "TagInlinedSubroutine", - "TagInterfaceType", - "TagLabel", - "TagLexDwarfBlock", - "TagMember", - "TagModule", - "TagMutableType", - "TagNamelist", - "TagNamelistItem", - "TagNamespace", - "TagPackedType", - "TagPartialUnit", - "TagPointerType", - "TagPtrToMemberType", - "TagReferenceType", - "TagRestrictType", - "TagRvalueReferenceType", - "TagSetType", - "TagSharedType", - "TagSkeletonUnit", - "TagStringType", - "TagStructType", - "TagSubprogram", - "TagSubrangeType", - "TagSubroutineType", - "TagTemplateAlias", - "TagTemplateTypeParameter", - "TagTemplateValueParameter", - "TagThrownType", - "TagTryDwarfBlock", - "TagTypeUnit", - "TagTypedef", - "TagUnionType", - "TagUnspecifiedParameters", - "TagUnspecifiedType", - "TagVariable", - "TagVariant", - "TagVariantPart", - "TagVolatileType", - "TagWithStmt", - "Type", - "TypedefType", - "UcharType", - "UintType", - "UnspecifiedType", - "UnsupportedType", - "VoidType", - }, - "debug/elf": { - "ARM_MAGIC_TRAMP_NUMBER", - "COMPRESS_HIOS", - "COMPRESS_HIPROC", - "COMPRESS_LOOS", - "COMPRESS_LOPROC", - "COMPRESS_ZLIB", - "COMPRESS_ZSTD", - "Chdr32", - "Chdr64", - "Class", - "CompressionType", - "DF_1_CONFALT", - "DF_1_DIRECT", - "DF_1_DISPRELDNE", - "DF_1_DISPRELPND", - "DF_1_EDITED", - "DF_1_ENDFILTEE", - "DF_1_GLOBAL", - "DF_1_GLOBAUDIT", - "DF_1_GROUP", - "DF_1_IGNMULDEF", - "DF_1_INITFIRST", - "DF_1_INTERPOSE", - "DF_1_KMOD", - "DF_1_LOADFLTR", - "DF_1_NOCOMMON", - "DF_1_NODEFLIB", - "DF_1_NODELETE", - "DF_1_NODIRECT", - "DF_1_NODUMP", - "DF_1_NOHDR", - "DF_1_NOKSYMS", - "DF_1_NOOPEN", - "DF_1_NORELOC", - "DF_1_NOW", - "DF_1_ORIGIN", - "DF_1_PIE", - "DF_1_SINGLETON", - "DF_1_STUB", - "DF_1_SYMINTPOSE", - "DF_1_TRANS", - "DF_1_WEAKFILTER", - "DF_BIND_NOW", - "DF_ORIGIN", - "DF_STATIC_TLS", - "DF_SYMBOLIC", - "DF_TEXTREL", - "DT_ADDRRNGHI", - "DT_ADDRRNGLO", - "DT_AUDIT", - "DT_AUXILIARY", - "DT_BIND_NOW", - "DT_CHECKSUM", - "DT_CONFIG", - "DT_DEBUG", - "DT_DEPAUDIT", - "DT_ENCODING", - "DT_FEATURE", - "DT_FILTER", - "DT_FINI", - "DT_FINI_ARRAY", - "DT_FINI_ARRAYSZ", - "DT_FLAGS", - "DT_FLAGS_1", - "DT_GNU_CONFLICT", - "DT_GNU_CONFLICTSZ", - "DT_GNU_HASH", - "DT_GNU_LIBLIST", - "DT_GNU_LIBLISTSZ", - "DT_GNU_PRELINKED", - "DT_HASH", - "DT_HIOS", - "DT_HIPROC", - "DT_INIT", - "DT_INIT_ARRAY", - "DT_INIT_ARRAYSZ", - "DT_JMPREL", - "DT_LOOS", - "DT_LOPROC", - "DT_MIPS_AUX_DYNAMIC", - "DT_MIPS_BASE_ADDRESS", - "DT_MIPS_COMPACT_SIZE", - "DT_MIPS_CONFLICT", - "DT_MIPS_CONFLICTNO", - "DT_MIPS_CXX_FLAGS", - "DT_MIPS_DELTA_CLASS", - "DT_MIPS_DELTA_CLASSSYM", - "DT_MIPS_DELTA_CLASSSYM_NO", - "DT_MIPS_DELTA_CLASS_NO", - "DT_MIPS_DELTA_INSTANCE", - "DT_MIPS_DELTA_INSTANCE_NO", - "DT_MIPS_DELTA_RELOC", - "DT_MIPS_DELTA_RELOC_NO", - "DT_MIPS_DELTA_SYM", - "DT_MIPS_DELTA_SYM_NO", - "DT_MIPS_DYNSTR_ALIGN", - "DT_MIPS_FLAGS", - "DT_MIPS_GOTSYM", - "DT_MIPS_GP_VALUE", - "DT_MIPS_HIDDEN_GOTIDX", - "DT_MIPS_HIPAGENO", - "DT_MIPS_ICHECKSUM", - "DT_MIPS_INTERFACE", - "DT_MIPS_INTERFACE_SIZE", - "DT_MIPS_IVERSION", - "DT_MIPS_LIBLIST", - "DT_MIPS_LIBLISTNO", - "DT_MIPS_LOCALPAGE_GOTIDX", - "DT_MIPS_LOCAL_GOTIDX", - "DT_MIPS_LOCAL_GOTNO", - "DT_MIPS_MSYM", - "DT_MIPS_OPTIONS", - "DT_MIPS_PERF_SUFFIX", - "DT_MIPS_PIXIE_INIT", - "DT_MIPS_PLTGOT", - "DT_MIPS_PROTECTED_GOTIDX", - "DT_MIPS_RLD_MAP", - "DT_MIPS_RLD_MAP_REL", - "DT_MIPS_RLD_TEXT_RESOLVE_ADDR", - "DT_MIPS_RLD_VERSION", - "DT_MIPS_RWPLT", - "DT_MIPS_SYMBOL_LIB", - "DT_MIPS_SYMTABNO", - "DT_MIPS_TIME_STAMP", - "DT_MIPS_UNREFEXTNO", - "DT_MOVEENT", - "DT_MOVESZ", - "DT_MOVETAB", - "DT_NEEDED", - "DT_NULL", - "DT_PLTGOT", - "DT_PLTPAD", - "DT_PLTPADSZ", - "DT_PLTREL", - "DT_PLTRELSZ", - "DT_POSFLAG_1", - "DT_PPC64_GLINK", - "DT_PPC64_OPD", - "DT_PPC64_OPDSZ", - "DT_PPC64_OPT", - "DT_PPC_GOT", - "DT_PPC_OPT", - "DT_PREINIT_ARRAY", - "DT_PREINIT_ARRAYSZ", - "DT_REL", - "DT_RELA", - "DT_RELACOUNT", - "DT_RELAENT", - "DT_RELASZ", - "DT_RELCOUNT", - "DT_RELENT", - "DT_RELSZ", - "DT_RPATH", - "DT_RUNPATH", - "DT_SONAME", - "DT_SPARC_REGISTER", - "DT_STRSZ", - "DT_STRTAB", - "DT_SYMBOLIC", - "DT_SYMENT", - "DT_SYMINENT", - "DT_SYMINFO", - "DT_SYMINSZ", - "DT_SYMTAB", - "DT_SYMTAB_SHNDX", - "DT_TEXTREL", - "DT_TLSDESC_GOT", - "DT_TLSDESC_PLT", - "DT_USED", - "DT_VALRNGHI", - "DT_VALRNGLO", - "DT_VERDEF", - "DT_VERDEFNUM", - "DT_VERNEED", - "DT_VERNEEDNUM", - "DT_VERSYM", - "Data", - "Dyn32", - "Dyn64", - "DynFlag", - "DynFlag1", - "DynTag", - "EI_ABIVERSION", - "EI_CLASS", - "EI_DATA", - "EI_NIDENT", - "EI_OSABI", - "EI_PAD", - "EI_VERSION", - "ELFCLASS32", - "ELFCLASS64", - "ELFCLASSNONE", - "ELFDATA2LSB", - "ELFDATA2MSB", - "ELFDATANONE", - "ELFMAG", - "ELFOSABI_86OPEN", - "ELFOSABI_AIX", - "ELFOSABI_ARM", - "ELFOSABI_AROS", - "ELFOSABI_CLOUDABI", - "ELFOSABI_FENIXOS", - "ELFOSABI_FREEBSD", - "ELFOSABI_HPUX", - "ELFOSABI_HURD", - "ELFOSABI_IRIX", - "ELFOSABI_LINUX", - "ELFOSABI_MODESTO", - "ELFOSABI_NETBSD", - "ELFOSABI_NONE", - "ELFOSABI_NSK", - "ELFOSABI_OPENBSD", - "ELFOSABI_OPENVMS", - "ELFOSABI_SOLARIS", - "ELFOSABI_STANDALONE", - "ELFOSABI_TRU64", - "EM_386", - "EM_486", - "EM_56800EX", - "EM_68HC05", - "EM_68HC08", - "EM_68HC11", - "EM_68HC12", - "EM_68HC16", - "EM_68K", - "EM_78KOR", - "EM_8051", - "EM_860", - "EM_88K", - "EM_960", - "EM_AARCH64", - "EM_ALPHA", - "EM_ALPHA_STD", - "EM_ALTERA_NIOS2", - "EM_AMDGPU", - "EM_ARC", - "EM_ARCA", - "EM_ARC_COMPACT", - "EM_ARC_COMPACT2", - "EM_ARM", - "EM_AVR", - "EM_AVR32", - "EM_BA1", - "EM_BA2", - "EM_BLACKFIN", - "EM_BPF", - "EM_C166", - "EM_CDP", - "EM_CE", - "EM_CLOUDSHIELD", - "EM_COGE", - "EM_COLDFIRE", - "EM_COOL", - "EM_COREA_1ST", - "EM_COREA_2ND", - "EM_CR", - "EM_CR16", - "EM_CRAYNV2", - "EM_CRIS", - "EM_CRX", - "EM_CSR_KALIMBA", - "EM_CUDA", - "EM_CYPRESS_M8C", - "EM_D10V", - "EM_D30V", - "EM_DSP24", - "EM_DSPIC30F", - "EM_DXP", - "EM_ECOG1", - "EM_ECOG16", - "EM_ECOG1X", - "EM_ECOG2", - "EM_ETPU", - "EM_EXCESS", - "EM_F2MC16", - "EM_FIREPATH", - "EM_FR20", - "EM_FR30", - "EM_FT32", - "EM_FX66", - "EM_H8S", - "EM_H8_300", - "EM_H8_300H", - "EM_H8_500", - "EM_HUANY", - "EM_IA_64", - "EM_INTEL205", - "EM_INTEL206", - "EM_INTEL207", - "EM_INTEL208", - "EM_INTEL209", - "EM_IP2K", - "EM_JAVELIN", - "EM_K10M", - "EM_KM32", - "EM_KMX16", - "EM_KMX32", - "EM_KMX8", - "EM_KVARC", - "EM_L10M", - "EM_LANAI", - "EM_LATTICEMICO32", - "EM_LOONGARCH", - "EM_M16C", - "EM_M32", - "EM_M32C", - "EM_M32R", - "EM_MANIK", - "EM_MAX", - "EM_MAXQ30", - "EM_MCHP_PIC", - "EM_MCST_ELBRUS", - "EM_ME16", - "EM_METAG", - "EM_MICROBLAZE", - "EM_MIPS", - "EM_MIPS_RS3_LE", - "EM_MIPS_RS4_BE", - "EM_MIPS_X", - "EM_MMA", - "EM_MMDSP_PLUS", - "EM_MMIX", - "EM_MN10200", - "EM_MN10300", - "EM_MOXIE", - "EM_MSP430", - "EM_NCPU", - "EM_NDR1", - "EM_NDS32", - "EM_NONE", - "EM_NORC", - "EM_NS32K", - "EM_OPEN8", - "EM_OPENRISC", - "EM_PARISC", - "EM_PCP", - "EM_PDP10", - "EM_PDP11", - "EM_PDSP", - "EM_PJ", - "EM_PPC", - "EM_PPC64", - "EM_PRISM", - "EM_QDSP6", - "EM_R32C", - "EM_RCE", - "EM_RH32", - "EM_RISCV", - "EM_RL78", - "EM_RS08", - "EM_RX", - "EM_S370", - "EM_S390", - "EM_SCORE7", - "EM_SEP", - "EM_SE_C17", - "EM_SE_C33", - "EM_SH", - "EM_SHARC", - "EM_SLE9X", - "EM_SNP1K", - "EM_SPARC", - "EM_SPARC32PLUS", - "EM_SPARCV9", - "EM_ST100", - "EM_ST19", - "EM_ST200", - "EM_ST7", - "EM_ST9PLUS", - "EM_STARCORE", - "EM_STM8", - "EM_STXP7X", - "EM_SVX", - "EM_TILE64", - "EM_TILEGX", - "EM_TILEPRO", - "EM_TINYJ", - "EM_TI_ARP32", - "EM_TI_C2000", - "EM_TI_C5500", - "EM_TI_C6000", - "EM_TI_PRU", - "EM_TMM_GPP", - "EM_TPC", - "EM_TRICORE", - "EM_TRIMEDIA", - "EM_TSK3000", - "EM_UNICORE", - "EM_V800", - "EM_V850", - "EM_VAX", - "EM_VIDEOCORE", - "EM_VIDEOCORE3", - "EM_VIDEOCORE5", - "EM_VISIUM", - "EM_VPP500", - "EM_X86_64", - "EM_XCORE", - "EM_XGATE", - "EM_XIMO16", - "EM_XTENSA", - "EM_Z80", - "EM_ZSP", - "ET_CORE", - "ET_DYN", - "ET_EXEC", - "ET_HIOS", - "ET_HIPROC", - "ET_LOOS", - "ET_LOPROC", - "ET_NONE", - "ET_REL", - "EV_CURRENT", - "EV_NONE", - "ErrNoSymbols", - "File", - "FileHeader", - "FormatError", - "Header32", - "Header64", - "ImportedSymbol", - "Machine", - "NT_FPREGSET", - "NT_PRPSINFO", - "NT_PRSTATUS", - "NType", - "NewFile", - "OSABI", - "Open", - "PF_MASKOS", - "PF_MASKPROC", - "PF_R", - "PF_W", - "PF_X", - "PT_AARCH64_ARCHEXT", - "PT_AARCH64_UNWIND", - "PT_ARM_ARCHEXT", - "PT_ARM_EXIDX", - "PT_DYNAMIC", - "PT_GNU_EH_FRAME", - "PT_GNU_MBIND_HI", - "PT_GNU_MBIND_LO", - "PT_GNU_PROPERTY", - "PT_GNU_RELRO", - "PT_GNU_STACK", - "PT_HIOS", - "PT_HIPROC", - "PT_INTERP", - "PT_LOAD", - "PT_LOOS", - "PT_LOPROC", - "PT_MIPS_ABIFLAGS", - "PT_MIPS_OPTIONS", - "PT_MIPS_REGINFO", - "PT_MIPS_RTPROC", - "PT_NOTE", - "PT_NULL", - "PT_OPENBSD_BOOTDATA", - "PT_OPENBSD_RANDOMIZE", - "PT_OPENBSD_WXNEEDED", - "PT_PAX_FLAGS", - "PT_PHDR", - "PT_S390_PGSTE", - "PT_SHLIB", - "PT_SUNWSTACK", - "PT_SUNW_EH_FRAME", - "PT_TLS", - "Prog", - "Prog32", - "Prog64", - "ProgFlag", - "ProgHeader", - "ProgType", - "R_386", - "R_386_16", - "R_386_32", - "R_386_32PLT", - "R_386_8", - "R_386_COPY", - "R_386_GLOB_DAT", - "R_386_GOT32", - "R_386_GOT32X", - "R_386_GOTOFF", - "R_386_GOTPC", - "R_386_IRELATIVE", - "R_386_JMP_SLOT", - "R_386_NONE", - "R_386_PC16", - "R_386_PC32", - "R_386_PC8", - "R_386_PLT32", - "R_386_RELATIVE", - "R_386_SIZE32", - "R_386_TLS_DESC", - "R_386_TLS_DESC_CALL", - "R_386_TLS_DTPMOD32", - "R_386_TLS_DTPOFF32", - "R_386_TLS_GD", - "R_386_TLS_GD_32", - "R_386_TLS_GD_CALL", - "R_386_TLS_GD_POP", - "R_386_TLS_GD_PUSH", - "R_386_TLS_GOTDESC", - "R_386_TLS_GOTIE", - "R_386_TLS_IE", - "R_386_TLS_IE_32", - "R_386_TLS_LDM", - "R_386_TLS_LDM_32", - "R_386_TLS_LDM_CALL", - "R_386_TLS_LDM_POP", - "R_386_TLS_LDM_PUSH", - "R_386_TLS_LDO_32", - "R_386_TLS_LE", - "R_386_TLS_LE_32", - "R_386_TLS_TPOFF", - "R_386_TLS_TPOFF32", - "R_390", - "R_390_12", - "R_390_16", - "R_390_20", - "R_390_32", - "R_390_64", - "R_390_8", - "R_390_COPY", - "R_390_GLOB_DAT", - "R_390_GOT12", - "R_390_GOT16", - "R_390_GOT20", - "R_390_GOT32", - "R_390_GOT64", - "R_390_GOTENT", - "R_390_GOTOFF", - "R_390_GOTOFF16", - "R_390_GOTOFF64", - "R_390_GOTPC", - "R_390_GOTPCDBL", - "R_390_GOTPLT12", - "R_390_GOTPLT16", - "R_390_GOTPLT20", - "R_390_GOTPLT32", - "R_390_GOTPLT64", - "R_390_GOTPLTENT", - "R_390_GOTPLTOFF16", - "R_390_GOTPLTOFF32", - "R_390_GOTPLTOFF64", - "R_390_JMP_SLOT", - "R_390_NONE", - "R_390_PC16", - "R_390_PC16DBL", - "R_390_PC32", - "R_390_PC32DBL", - "R_390_PC64", - "R_390_PLT16DBL", - "R_390_PLT32", - "R_390_PLT32DBL", - "R_390_PLT64", - "R_390_RELATIVE", - "R_390_TLS_DTPMOD", - "R_390_TLS_DTPOFF", - "R_390_TLS_GD32", - "R_390_TLS_GD64", - "R_390_TLS_GDCALL", - "R_390_TLS_GOTIE12", - "R_390_TLS_GOTIE20", - "R_390_TLS_GOTIE32", - "R_390_TLS_GOTIE64", - "R_390_TLS_IE32", - "R_390_TLS_IE64", - "R_390_TLS_IEENT", - "R_390_TLS_LDCALL", - "R_390_TLS_LDM32", - "R_390_TLS_LDM64", - "R_390_TLS_LDO32", - "R_390_TLS_LDO64", - "R_390_TLS_LE32", - "R_390_TLS_LE64", - "R_390_TLS_LOAD", - "R_390_TLS_TPOFF", - "R_AARCH64", - "R_AARCH64_ABS16", - "R_AARCH64_ABS32", - "R_AARCH64_ABS64", - "R_AARCH64_ADD_ABS_LO12_NC", - "R_AARCH64_ADR_GOT_PAGE", - "R_AARCH64_ADR_PREL_LO21", - "R_AARCH64_ADR_PREL_PG_HI21", - "R_AARCH64_ADR_PREL_PG_HI21_NC", - "R_AARCH64_CALL26", - "R_AARCH64_CONDBR19", - "R_AARCH64_COPY", - "R_AARCH64_GLOB_DAT", - "R_AARCH64_GOT_LD_PREL19", - "R_AARCH64_IRELATIVE", - "R_AARCH64_JUMP26", - "R_AARCH64_JUMP_SLOT", - "R_AARCH64_LD64_GOTOFF_LO15", - "R_AARCH64_LD64_GOTPAGE_LO15", - "R_AARCH64_LD64_GOT_LO12_NC", - "R_AARCH64_LDST128_ABS_LO12_NC", - "R_AARCH64_LDST16_ABS_LO12_NC", - "R_AARCH64_LDST32_ABS_LO12_NC", - "R_AARCH64_LDST64_ABS_LO12_NC", - "R_AARCH64_LDST8_ABS_LO12_NC", - "R_AARCH64_LD_PREL_LO19", - "R_AARCH64_MOVW_SABS_G0", - "R_AARCH64_MOVW_SABS_G1", - "R_AARCH64_MOVW_SABS_G2", - "R_AARCH64_MOVW_UABS_G0", - "R_AARCH64_MOVW_UABS_G0_NC", - "R_AARCH64_MOVW_UABS_G1", - "R_AARCH64_MOVW_UABS_G1_NC", - "R_AARCH64_MOVW_UABS_G2", - "R_AARCH64_MOVW_UABS_G2_NC", - "R_AARCH64_MOVW_UABS_G3", - "R_AARCH64_NONE", - "R_AARCH64_NULL", - "R_AARCH64_P32_ABS16", - "R_AARCH64_P32_ABS32", - "R_AARCH64_P32_ADD_ABS_LO12_NC", - "R_AARCH64_P32_ADR_GOT_PAGE", - "R_AARCH64_P32_ADR_PREL_LO21", - "R_AARCH64_P32_ADR_PREL_PG_HI21", - "R_AARCH64_P32_CALL26", - "R_AARCH64_P32_CONDBR19", - "R_AARCH64_P32_COPY", - "R_AARCH64_P32_GLOB_DAT", - "R_AARCH64_P32_GOT_LD_PREL19", - "R_AARCH64_P32_IRELATIVE", - "R_AARCH64_P32_JUMP26", - "R_AARCH64_P32_JUMP_SLOT", - "R_AARCH64_P32_LD32_GOT_LO12_NC", - "R_AARCH64_P32_LDST128_ABS_LO12_NC", - "R_AARCH64_P32_LDST16_ABS_LO12_NC", - "R_AARCH64_P32_LDST32_ABS_LO12_NC", - "R_AARCH64_P32_LDST64_ABS_LO12_NC", - "R_AARCH64_P32_LDST8_ABS_LO12_NC", - "R_AARCH64_P32_LD_PREL_LO19", - "R_AARCH64_P32_MOVW_SABS_G0", - "R_AARCH64_P32_MOVW_UABS_G0", - "R_AARCH64_P32_MOVW_UABS_G0_NC", - "R_AARCH64_P32_MOVW_UABS_G1", - "R_AARCH64_P32_PREL16", - "R_AARCH64_P32_PREL32", - "R_AARCH64_P32_RELATIVE", - "R_AARCH64_P32_TLSDESC", - "R_AARCH64_P32_TLSDESC_ADD_LO12_NC", - "R_AARCH64_P32_TLSDESC_ADR_PAGE21", - "R_AARCH64_P32_TLSDESC_ADR_PREL21", - "R_AARCH64_P32_TLSDESC_CALL", - "R_AARCH64_P32_TLSDESC_LD32_LO12_NC", - "R_AARCH64_P32_TLSDESC_LD_PREL19", - "R_AARCH64_P32_TLSGD_ADD_LO12_NC", - "R_AARCH64_P32_TLSGD_ADR_PAGE21", - "R_AARCH64_P32_TLSIE_ADR_GOTTPREL_PAGE21", - "R_AARCH64_P32_TLSIE_LD32_GOTTPREL_LO12_NC", - "R_AARCH64_P32_TLSIE_LD_GOTTPREL_PREL19", - "R_AARCH64_P32_TLSLE_ADD_TPREL_HI12", - "R_AARCH64_P32_TLSLE_ADD_TPREL_LO12", - "R_AARCH64_P32_TLSLE_ADD_TPREL_LO12_NC", - "R_AARCH64_P32_TLSLE_MOVW_TPREL_G0", - "R_AARCH64_P32_TLSLE_MOVW_TPREL_G0_NC", - "R_AARCH64_P32_TLSLE_MOVW_TPREL_G1", - "R_AARCH64_P32_TLS_DTPMOD", - "R_AARCH64_P32_TLS_DTPREL", - "R_AARCH64_P32_TLS_TPREL", - "R_AARCH64_P32_TSTBR14", - "R_AARCH64_PREL16", - "R_AARCH64_PREL32", - "R_AARCH64_PREL64", - "R_AARCH64_RELATIVE", - "R_AARCH64_TLSDESC", - "R_AARCH64_TLSDESC_ADD", - "R_AARCH64_TLSDESC_ADD_LO12_NC", - "R_AARCH64_TLSDESC_ADR_PAGE21", - "R_AARCH64_TLSDESC_ADR_PREL21", - "R_AARCH64_TLSDESC_CALL", - "R_AARCH64_TLSDESC_LD64_LO12_NC", - "R_AARCH64_TLSDESC_LDR", - "R_AARCH64_TLSDESC_LD_PREL19", - "R_AARCH64_TLSDESC_OFF_G0_NC", - "R_AARCH64_TLSDESC_OFF_G1", - "R_AARCH64_TLSGD_ADD_LO12_NC", - "R_AARCH64_TLSGD_ADR_PAGE21", - "R_AARCH64_TLSGD_ADR_PREL21", - "R_AARCH64_TLSGD_MOVW_G0_NC", - "R_AARCH64_TLSGD_MOVW_G1", - "R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21", - "R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC", - "R_AARCH64_TLSIE_LD_GOTTPREL_PREL19", - "R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC", - "R_AARCH64_TLSIE_MOVW_GOTTPREL_G1", - "R_AARCH64_TLSLD_ADR_PAGE21", - "R_AARCH64_TLSLD_ADR_PREL21", - "R_AARCH64_TLSLD_LDST128_DTPREL_LO12", - "R_AARCH64_TLSLD_LDST128_DTPREL_LO12_NC", - "R_AARCH64_TLSLE_ADD_TPREL_HI12", - "R_AARCH64_TLSLE_ADD_TPREL_LO12", - "R_AARCH64_TLSLE_ADD_TPREL_LO12_NC", - "R_AARCH64_TLSLE_LDST128_TPREL_LO12", - "R_AARCH64_TLSLE_LDST128_TPREL_LO12_NC", - "R_AARCH64_TLSLE_MOVW_TPREL_G0", - "R_AARCH64_TLSLE_MOVW_TPREL_G0_NC", - "R_AARCH64_TLSLE_MOVW_TPREL_G1", - "R_AARCH64_TLSLE_MOVW_TPREL_G1_NC", - "R_AARCH64_TLSLE_MOVW_TPREL_G2", - "R_AARCH64_TLS_DTPMOD64", - "R_AARCH64_TLS_DTPREL64", - "R_AARCH64_TLS_TPREL64", - "R_AARCH64_TSTBR14", - "R_ALPHA", - "R_ALPHA_BRADDR", - "R_ALPHA_COPY", - "R_ALPHA_GLOB_DAT", - "R_ALPHA_GPDISP", - "R_ALPHA_GPREL32", - "R_ALPHA_GPRELHIGH", - "R_ALPHA_GPRELLOW", - "R_ALPHA_GPVALUE", - "R_ALPHA_HINT", - "R_ALPHA_IMMED_BR_HI32", - "R_ALPHA_IMMED_GP_16", - "R_ALPHA_IMMED_GP_HI32", - "R_ALPHA_IMMED_LO32", - "R_ALPHA_IMMED_SCN_HI32", - "R_ALPHA_JMP_SLOT", - "R_ALPHA_LITERAL", - "R_ALPHA_LITUSE", - "R_ALPHA_NONE", - "R_ALPHA_OP_PRSHIFT", - "R_ALPHA_OP_PSUB", - "R_ALPHA_OP_PUSH", - "R_ALPHA_OP_STORE", - "R_ALPHA_REFLONG", - "R_ALPHA_REFQUAD", - "R_ALPHA_RELATIVE", - "R_ALPHA_SREL16", - "R_ALPHA_SREL32", - "R_ALPHA_SREL64", - "R_ARM", - "R_ARM_ABS12", - "R_ARM_ABS16", - "R_ARM_ABS32", - "R_ARM_ABS32_NOI", - "R_ARM_ABS8", - "R_ARM_ALU_PCREL_15_8", - "R_ARM_ALU_PCREL_23_15", - "R_ARM_ALU_PCREL_7_0", - "R_ARM_ALU_PC_G0", - "R_ARM_ALU_PC_G0_NC", - "R_ARM_ALU_PC_G1", - "R_ARM_ALU_PC_G1_NC", - "R_ARM_ALU_PC_G2", - "R_ARM_ALU_SBREL_19_12_NC", - "R_ARM_ALU_SBREL_27_20_CK", - "R_ARM_ALU_SB_G0", - "R_ARM_ALU_SB_G0_NC", - "R_ARM_ALU_SB_G1", - "R_ARM_ALU_SB_G1_NC", - "R_ARM_ALU_SB_G2", - "R_ARM_AMP_VCALL9", - "R_ARM_BASE_ABS", - "R_ARM_CALL", - "R_ARM_COPY", - "R_ARM_GLOB_DAT", - "R_ARM_GNU_VTENTRY", - "R_ARM_GNU_VTINHERIT", - "R_ARM_GOT32", - "R_ARM_GOTOFF", - "R_ARM_GOTOFF12", - "R_ARM_GOTPC", - "R_ARM_GOTRELAX", - "R_ARM_GOT_ABS", - "R_ARM_GOT_BREL12", - "R_ARM_GOT_PREL", - "R_ARM_IRELATIVE", - "R_ARM_JUMP24", - "R_ARM_JUMP_SLOT", - "R_ARM_LDC_PC_G0", - "R_ARM_LDC_PC_G1", - "R_ARM_LDC_PC_G2", - "R_ARM_LDC_SB_G0", - "R_ARM_LDC_SB_G1", - "R_ARM_LDC_SB_G2", - "R_ARM_LDRS_PC_G0", - "R_ARM_LDRS_PC_G1", - "R_ARM_LDRS_PC_G2", - "R_ARM_LDRS_SB_G0", - "R_ARM_LDRS_SB_G1", - "R_ARM_LDRS_SB_G2", - "R_ARM_LDR_PC_G1", - "R_ARM_LDR_PC_G2", - "R_ARM_LDR_SBREL_11_10_NC", - "R_ARM_LDR_SB_G0", - "R_ARM_LDR_SB_G1", - "R_ARM_LDR_SB_G2", - "R_ARM_ME_TOO", - "R_ARM_MOVT_ABS", - "R_ARM_MOVT_BREL", - "R_ARM_MOVT_PREL", - "R_ARM_MOVW_ABS_NC", - "R_ARM_MOVW_BREL", - "R_ARM_MOVW_BREL_NC", - "R_ARM_MOVW_PREL_NC", - "R_ARM_NONE", - "R_ARM_PC13", - "R_ARM_PC24", - "R_ARM_PLT32", - "R_ARM_PLT32_ABS", - "R_ARM_PREL31", - "R_ARM_PRIVATE_0", - "R_ARM_PRIVATE_1", - "R_ARM_PRIVATE_10", - "R_ARM_PRIVATE_11", - "R_ARM_PRIVATE_12", - "R_ARM_PRIVATE_13", - "R_ARM_PRIVATE_14", - "R_ARM_PRIVATE_15", - "R_ARM_PRIVATE_2", - "R_ARM_PRIVATE_3", - "R_ARM_PRIVATE_4", - "R_ARM_PRIVATE_5", - "R_ARM_PRIVATE_6", - "R_ARM_PRIVATE_7", - "R_ARM_PRIVATE_8", - "R_ARM_PRIVATE_9", - "R_ARM_RABS32", - "R_ARM_RBASE", - "R_ARM_REL32", - "R_ARM_REL32_NOI", - "R_ARM_RELATIVE", - "R_ARM_RPC24", - "R_ARM_RREL32", - "R_ARM_RSBREL32", - "R_ARM_RXPC25", - "R_ARM_SBREL31", - "R_ARM_SBREL32", - "R_ARM_SWI24", - "R_ARM_TARGET1", - "R_ARM_TARGET2", - "R_ARM_THM_ABS5", - "R_ARM_THM_ALU_ABS_G0_NC", - "R_ARM_THM_ALU_ABS_G1_NC", - "R_ARM_THM_ALU_ABS_G2_NC", - "R_ARM_THM_ALU_ABS_G3", - "R_ARM_THM_ALU_PREL_11_0", - "R_ARM_THM_GOT_BREL12", - "R_ARM_THM_JUMP11", - "R_ARM_THM_JUMP19", - "R_ARM_THM_JUMP24", - "R_ARM_THM_JUMP6", - "R_ARM_THM_JUMP8", - "R_ARM_THM_MOVT_ABS", - "R_ARM_THM_MOVT_BREL", - "R_ARM_THM_MOVT_PREL", - "R_ARM_THM_MOVW_ABS_NC", - "R_ARM_THM_MOVW_BREL", - "R_ARM_THM_MOVW_BREL_NC", - "R_ARM_THM_MOVW_PREL_NC", - "R_ARM_THM_PC12", - "R_ARM_THM_PC22", - "R_ARM_THM_PC8", - "R_ARM_THM_RPC22", - "R_ARM_THM_SWI8", - "R_ARM_THM_TLS_CALL", - "R_ARM_THM_TLS_DESCSEQ16", - "R_ARM_THM_TLS_DESCSEQ32", - "R_ARM_THM_XPC22", - "R_ARM_TLS_CALL", - "R_ARM_TLS_DESCSEQ", - "R_ARM_TLS_DTPMOD32", - "R_ARM_TLS_DTPOFF32", - "R_ARM_TLS_GD32", - "R_ARM_TLS_GOTDESC", - "R_ARM_TLS_IE12GP", - "R_ARM_TLS_IE32", - "R_ARM_TLS_LDM32", - "R_ARM_TLS_LDO12", - "R_ARM_TLS_LDO32", - "R_ARM_TLS_LE12", - "R_ARM_TLS_LE32", - "R_ARM_TLS_TPOFF32", - "R_ARM_V4BX", - "R_ARM_XPC25", - "R_INFO", - "R_INFO32", - "R_LARCH", - "R_LARCH_32", - "R_LARCH_32_PCREL", - "R_LARCH_64", - "R_LARCH_ABS64_HI12", - "R_LARCH_ABS64_LO20", - "R_LARCH_ABS_HI20", - "R_LARCH_ABS_LO12", - "R_LARCH_ADD16", - "R_LARCH_ADD24", - "R_LARCH_ADD32", - "R_LARCH_ADD64", - "R_LARCH_ADD8", - "R_LARCH_B16", - "R_LARCH_B21", - "R_LARCH_B26", - "R_LARCH_COPY", - "R_LARCH_GNU_VTENTRY", - "R_LARCH_GNU_VTINHERIT", - "R_LARCH_GOT64_HI12", - "R_LARCH_GOT64_LO20", - "R_LARCH_GOT64_PC_HI12", - "R_LARCH_GOT64_PC_LO20", - "R_LARCH_GOT_HI20", - "R_LARCH_GOT_LO12", - "R_LARCH_GOT_PC_HI20", - "R_LARCH_GOT_PC_LO12", - "R_LARCH_IRELATIVE", - "R_LARCH_JUMP_SLOT", - "R_LARCH_MARK_LA", - "R_LARCH_MARK_PCREL", - "R_LARCH_NONE", - "R_LARCH_PCALA64_HI12", - "R_LARCH_PCALA64_LO20", - "R_LARCH_PCALA_HI20", - "R_LARCH_PCALA_LO12", - "R_LARCH_RELATIVE", - "R_LARCH_RELAX", - "R_LARCH_SOP_ADD", - "R_LARCH_SOP_AND", - "R_LARCH_SOP_ASSERT", - "R_LARCH_SOP_IF_ELSE", - "R_LARCH_SOP_NOT", - "R_LARCH_SOP_POP_32_S_0_10_10_16_S2", - "R_LARCH_SOP_POP_32_S_0_5_10_16_S2", - "R_LARCH_SOP_POP_32_S_10_12", - "R_LARCH_SOP_POP_32_S_10_16", - "R_LARCH_SOP_POP_32_S_10_16_S2", - "R_LARCH_SOP_POP_32_S_10_5", - "R_LARCH_SOP_POP_32_S_5_20", - "R_LARCH_SOP_POP_32_U", - "R_LARCH_SOP_POP_32_U_10_12", - "R_LARCH_SOP_PUSH_ABSOLUTE", - "R_LARCH_SOP_PUSH_DUP", - "R_LARCH_SOP_PUSH_GPREL", - "R_LARCH_SOP_PUSH_PCREL", - "R_LARCH_SOP_PUSH_PLT_PCREL", - "R_LARCH_SOP_PUSH_TLS_GD", - "R_LARCH_SOP_PUSH_TLS_GOT", - "R_LARCH_SOP_PUSH_TLS_TPREL", - "R_LARCH_SOP_SL", - "R_LARCH_SOP_SR", - "R_LARCH_SOP_SUB", - "R_LARCH_SUB16", - "R_LARCH_SUB24", - "R_LARCH_SUB32", - "R_LARCH_SUB64", - "R_LARCH_SUB8", - "R_LARCH_TLS_DTPMOD32", - "R_LARCH_TLS_DTPMOD64", - "R_LARCH_TLS_DTPREL32", - "R_LARCH_TLS_DTPREL64", - "R_LARCH_TLS_GD_HI20", - "R_LARCH_TLS_GD_PC_HI20", - "R_LARCH_TLS_IE64_HI12", - "R_LARCH_TLS_IE64_LO20", - "R_LARCH_TLS_IE64_PC_HI12", - "R_LARCH_TLS_IE64_PC_LO20", - "R_LARCH_TLS_IE_HI20", - "R_LARCH_TLS_IE_LO12", - "R_LARCH_TLS_IE_PC_HI20", - "R_LARCH_TLS_IE_PC_LO12", - "R_LARCH_TLS_LD_HI20", - "R_LARCH_TLS_LD_PC_HI20", - "R_LARCH_TLS_LE64_HI12", - "R_LARCH_TLS_LE64_LO20", - "R_LARCH_TLS_LE_HI20", - "R_LARCH_TLS_LE_LO12", - "R_LARCH_TLS_TPREL32", - "R_LARCH_TLS_TPREL64", - "R_MIPS", - "R_MIPS_16", - "R_MIPS_26", - "R_MIPS_32", - "R_MIPS_64", - "R_MIPS_ADD_IMMEDIATE", - "R_MIPS_CALL16", - "R_MIPS_CALL_HI16", - "R_MIPS_CALL_LO16", - "R_MIPS_DELETE", - "R_MIPS_GOT16", - "R_MIPS_GOT_DISP", - "R_MIPS_GOT_HI16", - "R_MIPS_GOT_LO16", - "R_MIPS_GOT_OFST", - "R_MIPS_GOT_PAGE", - "R_MIPS_GPREL16", - "R_MIPS_GPREL32", - "R_MIPS_HI16", - "R_MIPS_HIGHER", - "R_MIPS_HIGHEST", - "R_MIPS_INSERT_A", - "R_MIPS_INSERT_B", - "R_MIPS_JALR", - "R_MIPS_LITERAL", - "R_MIPS_LO16", - "R_MIPS_NONE", - "R_MIPS_PC16", - "R_MIPS_PJUMP", - "R_MIPS_REL16", - "R_MIPS_REL32", - "R_MIPS_RELGOT", - "R_MIPS_SCN_DISP", - "R_MIPS_SHIFT5", - "R_MIPS_SHIFT6", - "R_MIPS_SUB", - "R_MIPS_TLS_DTPMOD32", - "R_MIPS_TLS_DTPMOD64", - "R_MIPS_TLS_DTPREL32", - "R_MIPS_TLS_DTPREL64", - "R_MIPS_TLS_DTPREL_HI16", - "R_MIPS_TLS_DTPREL_LO16", - "R_MIPS_TLS_GD", - "R_MIPS_TLS_GOTTPREL", - "R_MIPS_TLS_LDM", - "R_MIPS_TLS_TPREL32", - "R_MIPS_TLS_TPREL64", - "R_MIPS_TLS_TPREL_HI16", - "R_MIPS_TLS_TPREL_LO16", - "R_PPC", - "R_PPC64", - "R_PPC64_ADDR14", - "R_PPC64_ADDR14_BRNTAKEN", - "R_PPC64_ADDR14_BRTAKEN", - "R_PPC64_ADDR16", - "R_PPC64_ADDR16_DS", - "R_PPC64_ADDR16_HA", - "R_PPC64_ADDR16_HI", - "R_PPC64_ADDR16_HIGH", - "R_PPC64_ADDR16_HIGHA", - "R_PPC64_ADDR16_HIGHER", - "R_PPC64_ADDR16_HIGHER34", - "R_PPC64_ADDR16_HIGHERA", - "R_PPC64_ADDR16_HIGHERA34", - "R_PPC64_ADDR16_HIGHEST", - "R_PPC64_ADDR16_HIGHEST34", - "R_PPC64_ADDR16_HIGHESTA", - "R_PPC64_ADDR16_HIGHESTA34", - "R_PPC64_ADDR16_LO", - "R_PPC64_ADDR16_LO_DS", - "R_PPC64_ADDR24", - "R_PPC64_ADDR32", - "R_PPC64_ADDR64", - "R_PPC64_ADDR64_LOCAL", - "R_PPC64_COPY", - "R_PPC64_D28", - "R_PPC64_D34", - "R_PPC64_D34_HA30", - "R_PPC64_D34_HI30", - "R_PPC64_D34_LO", - "R_PPC64_DTPMOD64", - "R_PPC64_DTPREL16", - "R_PPC64_DTPREL16_DS", - "R_PPC64_DTPREL16_HA", - "R_PPC64_DTPREL16_HI", - "R_PPC64_DTPREL16_HIGH", - "R_PPC64_DTPREL16_HIGHA", - "R_PPC64_DTPREL16_HIGHER", - "R_PPC64_DTPREL16_HIGHERA", - "R_PPC64_DTPREL16_HIGHEST", - "R_PPC64_DTPREL16_HIGHESTA", - "R_PPC64_DTPREL16_LO", - "R_PPC64_DTPREL16_LO_DS", - "R_PPC64_DTPREL34", - "R_PPC64_DTPREL64", - "R_PPC64_ENTRY", - "R_PPC64_GLOB_DAT", - "R_PPC64_GNU_VTENTRY", - "R_PPC64_GNU_VTINHERIT", - "R_PPC64_GOT16", - "R_PPC64_GOT16_DS", - "R_PPC64_GOT16_HA", - "R_PPC64_GOT16_HI", - "R_PPC64_GOT16_LO", - "R_PPC64_GOT16_LO_DS", - "R_PPC64_GOT_DTPREL16_DS", - "R_PPC64_GOT_DTPREL16_HA", - "R_PPC64_GOT_DTPREL16_HI", - "R_PPC64_GOT_DTPREL16_LO_DS", - "R_PPC64_GOT_DTPREL_PCREL34", - "R_PPC64_GOT_PCREL34", - "R_PPC64_GOT_TLSGD16", - "R_PPC64_GOT_TLSGD16_HA", - "R_PPC64_GOT_TLSGD16_HI", - "R_PPC64_GOT_TLSGD16_LO", - "R_PPC64_GOT_TLSGD_PCREL34", - "R_PPC64_GOT_TLSLD16", - "R_PPC64_GOT_TLSLD16_HA", - "R_PPC64_GOT_TLSLD16_HI", - "R_PPC64_GOT_TLSLD16_LO", - "R_PPC64_GOT_TLSLD_PCREL34", - "R_PPC64_GOT_TPREL16_DS", - "R_PPC64_GOT_TPREL16_HA", - "R_PPC64_GOT_TPREL16_HI", - "R_PPC64_GOT_TPREL16_LO_DS", - "R_PPC64_GOT_TPREL_PCREL34", - "R_PPC64_IRELATIVE", - "R_PPC64_JMP_IREL", - "R_PPC64_JMP_SLOT", - "R_PPC64_NONE", - "R_PPC64_PCREL28", - "R_PPC64_PCREL34", - "R_PPC64_PCREL_OPT", - "R_PPC64_PLT16_HA", - "R_PPC64_PLT16_HI", - "R_PPC64_PLT16_LO", - "R_PPC64_PLT16_LO_DS", - "R_PPC64_PLT32", - "R_PPC64_PLT64", - "R_PPC64_PLTCALL", - "R_PPC64_PLTCALL_NOTOC", - "R_PPC64_PLTGOT16", - "R_PPC64_PLTGOT16_DS", - "R_PPC64_PLTGOT16_HA", - "R_PPC64_PLTGOT16_HI", - "R_PPC64_PLTGOT16_LO", - "R_PPC64_PLTGOT_LO_DS", - "R_PPC64_PLTREL32", - "R_PPC64_PLTREL64", - "R_PPC64_PLTSEQ", - "R_PPC64_PLTSEQ_NOTOC", - "R_PPC64_PLT_PCREL34", - "R_PPC64_PLT_PCREL34_NOTOC", - "R_PPC64_REL14", - "R_PPC64_REL14_BRNTAKEN", - "R_PPC64_REL14_BRTAKEN", - "R_PPC64_REL16", - "R_PPC64_REL16DX_HA", - "R_PPC64_REL16_HA", - "R_PPC64_REL16_HI", - "R_PPC64_REL16_HIGH", - "R_PPC64_REL16_HIGHA", - "R_PPC64_REL16_HIGHER", - "R_PPC64_REL16_HIGHER34", - "R_PPC64_REL16_HIGHERA", - "R_PPC64_REL16_HIGHERA34", - "R_PPC64_REL16_HIGHEST", - "R_PPC64_REL16_HIGHEST34", - "R_PPC64_REL16_HIGHESTA", - "R_PPC64_REL16_HIGHESTA34", - "R_PPC64_REL16_LO", - "R_PPC64_REL24", - "R_PPC64_REL24_NOTOC", - "R_PPC64_REL24_P9NOTOC", - "R_PPC64_REL30", - "R_PPC64_REL32", - "R_PPC64_REL64", - "R_PPC64_RELATIVE", - "R_PPC64_SECTOFF", - "R_PPC64_SECTOFF_DS", - "R_PPC64_SECTOFF_HA", - "R_PPC64_SECTOFF_HI", - "R_PPC64_SECTOFF_LO", - "R_PPC64_SECTOFF_LO_DS", - "R_PPC64_TLS", - "R_PPC64_TLSGD", - "R_PPC64_TLSLD", - "R_PPC64_TOC", - "R_PPC64_TOC16", - "R_PPC64_TOC16_DS", - "R_PPC64_TOC16_HA", - "R_PPC64_TOC16_HI", - "R_PPC64_TOC16_LO", - "R_PPC64_TOC16_LO_DS", - "R_PPC64_TOCSAVE", - "R_PPC64_TPREL16", - "R_PPC64_TPREL16_DS", - "R_PPC64_TPREL16_HA", - "R_PPC64_TPREL16_HI", - "R_PPC64_TPREL16_HIGH", - "R_PPC64_TPREL16_HIGHA", - "R_PPC64_TPREL16_HIGHER", - "R_PPC64_TPREL16_HIGHERA", - "R_PPC64_TPREL16_HIGHEST", - "R_PPC64_TPREL16_HIGHESTA", - "R_PPC64_TPREL16_LO", - "R_PPC64_TPREL16_LO_DS", - "R_PPC64_TPREL34", - "R_PPC64_TPREL64", - "R_PPC64_UADDR16", - "R_PPC64_UADDR32", - "R_PPC64_UADDR64", - "R_PPC_ADDR14", - "R_PPC_ADDR14_BRNTAKEN", - "R_PPC_ADDR14_BRTAKEN", - "R_PPC_ADDR16", - "R_PPC_ADDR16_HA", - "R_PPC_ADDR16_HI", - "R_PPC_ADDR16_LO", - "R_PPC_ADDR24", - "R_PPC_ADDR32", - "R_PPC_COPY", - "R_PPC_DTPMOD32", - "R_PPC_DTPREL16", - "R_PPC_DTPREL16_HA", - "R_PPC_DTPREL16_HI", - "R_PPC_DTPREL16_LO", - "R_PPC_DTPREL32", - "R_PPC_EMB_BIT_FLD", - "R_PPC_EMB_MRKREF", - "R_PPC_EMB_NADDR16", - "R_PPC_EMB_NADDR16_HA", - "R_PPC_EMB_NADDR16_HI", - "R_PPC_EMB_NADDR16_LO", - "R_PPC_EMB_NADDR32", - "R_PPC_EMB_RELSDA", - "R_PPC_EMB_RELSEC16", - "R_PPC_EMB_RELST_HA", - "R_PPC_EMB_RELST_HI", - "R_PPC_EMB_RELST_LO", - "R_PPC_EMB_SDA21", - "R_PPC_EMB_SDA2I16", - "R_PPC_EMB_SDA2REL", - "R_PPC_EMB_SDAI16", - "R_PPC_GLOB_DAT", - "R_PPC_GOT16", - "R_PPC_GOT16_HA", - "R_PPC_GOT16_HI", - "R_PPC_GOT16_LO", - "R_PPC_GOT_TLSGD16", - "R_PPC_GOT_TLSGD16_HA", - "R_PPC_GOT_TLSGD16_HI", - "R_PPC_GOT_TLSGD16_LO", - "R_PPC_GOT_TLSLD16", - "R_PPC_GOT_TLSLD16_HA", - "R_PPC_GOT_TLSLD16_HI", - "R_PPC_GOT_TLSLD16_LO", - "R_PPC_GOT_TPREL16", - "R_PPC_GOT_TPREL16_HA", - "R_PPC_GOT_TPREL16_HI", - "R_PPC_GOT_TPREL16_LO", - "R_PPC_JMP_SLOT", - "R_PPC_LOCAL24PC", - "R_PPC_NONE", - "R_PPC_PLT16_HA", - "R_PPC_PLT16_HI", - "R_PPC_PLT16_LO", - "R_PPC_PLT32", - "R_PPC_PLTREL24", - "R_PPC_PLTREL32", - "R_PPC_REL14", - "R_PPC_REL14_BRNTAKEN", - "R_PPC_REL14_BRTAKEN", - "R_PPC_REL24", - "R_PPC_REL32", - "R_PPC_RELATIVE", - "R_PPC_SDAREL16", - "R_PPC_SECTOFF", - "R_PPC_SECTOFF_HA", - "R_PPC_SECTOFF_HI", - "R_PPC_SECTOFF_LO", - "R_PPC_TLS", - "R_PPC_TPREL16", - "R_PPC_TPREL16_HA", - "R_PPC_TPREL16_HI", - "R_PPC_TPREL16_LO", - "R_PPC_TPREL32", - "R_PPC_UADDR16", - "R_PPC_UADDR32", - "R_RISCV", - "R_RISCV_32", - "R_RISCV_32_PCREL", - "R_RISCV_64", - "R_RISCV_ADD16", - "R_RISCV_ADD32", - "R_RISCV_ADD64", - "R_RISCV_ADD8", - "R_RISCV_ALIGN", - "R_RISCV_BRANCH", - "R_RISCV_CALL", - "R_RISCV_CALL_PLT", - "R_RISCV_COPY", - "R_RISCV_GNU_VTENTRY", - "R_RISCV_GNU_VTINHERIT", - "R_RISCV_GOT_HI20", - "R_RISCV_GPREL_I", - "R_RISCV_GPREL_S", - "R_RISCV_HI20", - "R_RISCV_JAL", - "R_RISCV_JUMP_SLOT", - "R_RISCV_LO12_I", - "R_RISCV_LO12_S", - "R_RISCV_NONE", - "R_RISCV_PCREL_HI20", - "R_RISCV_PCREL_LO12_I", - "R_RISCV_PCREL_LO12_S", - "R_RISCV_RELATIVE", - "R_RISCV_RELAX", - "R_RISCV_RVC_BRANCH", - "R_RISCV_RVC_JUMP", - "R_RISCV_RVC_LUI", - "R_RISCV_SET16", - "R_RISCV_SET32", - "R_RISCV_SET6", - "R_RISCV_SET8", - "R_RISCV_SUB16", - "R_RISCV_SUB32", - "R_RISCV_SUB6", - "R_RISCV_SUB64", - "R_RISCV_SUB8", - "R_RISCV_TLS_DTPMOD32", - "R_RISCV_TLS_DTPMOD64", - "R_RISCV_TLS_DTPREL32", - "R_RISCV_TLS_DTPREL64", - "R_RISCV_TLS_GD_HI20", - "R_RISCV_TLS_GOT_HI20", - "R_RISCV_TLS_TPREL32", - "R_RISCV_TLS_TPREL64", - "R_RISCV_TPREL_ADD", - "R_RISCV_TPREL_HI20", - "R_RISCV_TPREL_I", - "R_RISCV_TPREL_LO12_I", - "R_RISCV_TPREL_LO12_S", - "R_RISCV_TPREL_S", - "R_SPARC", - "R_SPARC_10", - "R_SPARC_11", - "R_SPARC_13", - "R_SPARC_16", - "R_SPARC_22", - "R_SPARC_32", - "R_SPARC_5", - "R_SPARC_6", - "R_SPARC_64", - "R_SPARC_7", - "R_SPARC_8", - "R_SPARC_COPY", - "R_SPARC_DISP16", - "R_SPARC_DISP32", - "R_SPARC_DISP64", - "R_SPARC_DISP8", - "R_SPARC_GLOB_DAT", - "R_SPARC_GLOB_JMP", - "R_SPARC_GOT10", - "R_SPARC_GOT13", - "R_SPARC_GOT22", - "R_SPARC_H44", - "R_SPARC_HH22", - "R_SPARC_HI22", - "R_SPARC_HIPLT22", - "R_SPARC_HIX22", - "R_SPARC_HM10", - "R_SPARC_JMP_SLOT", - "R_SPARC_L44", - "R_SPARC_LM22", - "R_SPARC_LO10", - "R_SPARC_LOPLT10", - "R_SPARC_LOX10", - "R_SPARC_M44", - "R_SPARC_NONE", - "R_SPARC_OLO10", - "R_SPARC_PC10", - "R_SPARC_PC22", - "R_SPARC_PCPLT10", - "R_SPARC_PCPLT22", - "R_SPARC_PCPLT32", - "R_SPARC_PC_HH22", - "R_SPARC_PC_HM10", - "R_SPARC_PC_LM22", - "R_SPARC_PLT32", - "R_SPARC_PLT64", - "R_SPARC_REGISTER", - "R_SPARC_RELATIVE", - "R_SPARC_UA16", - "R_SPARC_UA32", - "R_SPARC_UA64", - "R_SPARC_WDISP16", - "R_SPARC_WDISP19", - "R_SPARC_WDISP22", - "R_SPARC_WDISP30", - "R_SPARC_WPLT30", - "R_SYM32", - "R_SYM64", - "R_TYPE32", - "R_TYPE64", - "R_X86_64", - "R_X86_64_16", - "R_X86_64_32", - "R_X86_64_32S", - "R_X86_64_64", - "R_X86_64_8", - "R_X86_64_COPY", - "R_X86_64_DTPMOD64", - "R_X86_64_DTPOFF32", - "R_X86_64_DTPOFF64", - "R_X86_64_GLOB_DAT", - "R_X86_64_GOT32", - "R_X86_64_GOT64", - "R_X86_64_GOTOFF64", - "R_X86_64_GOTPC32", - "R_X86_64_GOTPC32_TLSDESC", - "R_X86_64_GOTPC64", - "R_X86_64_GOTPCREL", - "R_X86_64_GOTPCREL64", - "R_X86_64_GOTPCRELX", - "R_X86_64_GOTPLT64", - "R_X86_64_GOTTPOFF", - "R_X86_64_IRELATIVE", - "R_X86_64_JMP_SLOT", - "R_X86_64_NONE", - "R_X86_64_PC16", - "R_X86_64_PC32", - "R_X86_64_PC32_BND", - "R_X86_64_PC64", - "R_X86_64_PC8", - "R_X86_64_PLT32", - "R_X86_64_PLT32_BND", - "R_X86_64_PLTOFF64", - "R_X86_64_RELATIVE", - "R_X86_64_RELATIVE64", - "R_X86_64_REX_GOTPCRELX", - "R_X86_64_SIZE32", - "R_X86_64_SIZE64", - "R_X86_64_TLSDESC", - "R_X86_64_TLSDESC_CALL", - "R_X86_64_TLSGD", - "R_X86_64_TLSLD", - "R_X86_64_TPOFF32", - "R_X86_64_TPOFF64", - "Rel32", - "Rel64", - "Rela32", - "Rela64", - "SHF_ALLOC", - "SHF_COMPRESSED", - "SHF_EXECINSTR", - "SHF_GROUP", - "SHF_INFO_LINK", - "SHF_LINK_ORDER", - "SHF_MASKOS", - "SHF_MASKPROC", - "SHF_MERGE", - "SHF_OS_NONCONFORMING", - "SHF_STRINGS", - "SHF_TLS", - "SHF_WRITE", - "SHN_ABS", - "SHN_COMMON", - "SHN_HIOS", - "SHN_HIPROC", - "SHN_HIRESERVE", - "SHN_LOOS", - "SHN_LOPROC", - "SHN_LORESERVE", - "SHN_UNDEF", - "SHN_XINDEX", - "SHT_DYNAMIC", - "SHT_DYNSYM", - "SHT_FINI_ARRAY", - "SHT_GNU_ATTRIBUTES", - "SHT_GNU_HASH", - "SHT_GNU_LIBLIST", - "SHT_GNU_VERDEF", - "SHT_GNU_VERNEED", - "SHT_GNU_VERSYM", - "SHT_GROUP", - "SHT_HASH", - "SHT_HIOS", - "SHT_HIPROC", - "SHT_HIUSER", - "SHT_INIT_ARRAY", - "SHT_LOOS", - "SHT_LOPROC", - "SHT_LOUSER", - "SHT_MIPS_ABIFLAGS", - "SHT_NOBITS", - "SHT_NOTE", - "SHT_NULL", - "SHT_PREINIT_ARRAY", - "SHT_PROGBITS", - "SHT_REL", - "SHT_RELA", - "SHT_SHLIB", - "SHT_STRTAB", - "SHT_SYMTAB", - "SHT_SYMTAB_SHNDX", - "STB_GLOBAL", - "STB_HIOS", - "STB_HIPROC", - "STB_LOCAL", - "STB_LOOS", - "STB_LOPROC", - "STB_WEAK", - "STT_COMMON", - "STT_FILE", - "STT_FUNC", - "STT_HIOS", - "STT_HIPROC", - "STT_LOOS", - "STT_LOPROC", - "STT_NOTYPE", - "STT_OBJECT", - "STT_SECTION", - "STT_TLS", - "STV_DEFAULT", - "STV_HIDDEN", - "STV_INTERNAL", - "STV_PROTECTED", - "ST_BIND", - "ST_INFO", - "ST_TYPE", - "ST_VISIBILITY", - "Section", - "Section32", - "Section64", - "SectionFlag", - "SectionHeader", - "SectionIndex", - "SectionType", - "Sym32", - "Sym32Size", - "Sym64", - "Sym64Size", - "SymBind", - "SymType", - "SymVis", - "Symbol", - "Type", - "Version", - }, - "debug/gosym": { - "DecodingError", - "Func", - "LineTable", - "NewLineTable", - "NewTable", - "Obj", - "Sym", - "Table", - "UnknownFileError", - "UnknownLineError", - }, - "debug/macho": { - "ARM64_RELOC_ADDEND", - "ARM64_RELOC_BRANCH26", - "ARM64_RELOC_GOT_LOAD_PAGE21", - "ARM64_RELOC_GOT_LOAD_PAGEOFF12", - "ARM64_RELOC_PAGE21", - "ARM64_RELOC_PAGEOFF12", - "ARM64_RELOC_POINTER_TO_GOT", - "ARM64_RELOC_SUBTRACTOR", - "ARM64_RELOC_TLVP_LOAD_PAGE21", - "ARM64_RELOC_TLVP_LOAD_PAGEOFF12", - "ARM64_RELOC_UNSIGNED", - "ARM_RELOC_BR24", - "ARM_RELOC_HALF", - "ARM_RELOC_HALF_SECTDIFF", - "ARM_RELOC_LOCAL_SECTDIFF", - "ARM_RELOC_PAIR", - "ARM_RELOC_PB_LA_PTR", - "ARM_RELOC_SECTDIFF", - "ARM_RELOC_VANILLA", - "ARM_THUMB_32BIT_BRANCH", - "ARM_THUMB_RELOC_BR22", - "Cpu", - "Cpu386", - "CpuAmd64", - "CpuArm", - "CpuArm64", - "CpuPpc", - "CpuPpc64", - "Dylib", - "DylibCmd", - "Dysymtab", - "DysymtabCmd", - "ErrNotFat", - "FatArch", - "FatArchHeader", - "FatFile", - "File", - "FileHeader", - "FlagAllModsBound", - "FlagAllowStackExecution", - "FlagAppExtensionSafe", - "FlagBindAtLoad", - "FlagBindsToWeak", - "FlagCanonical", - "FlagDeadStrippableDylib", - "FlagDyldLink", - "FlagForceFlat", - "FlagHasTLVDescriptors", - "FlagIncrLink", - "FlagLazyInit", - "FlagNoFixPrebinding", - "FlagNoHeapExecution", - "FlagNoMultiDefs", - "FlagNoReexportedDylibs", - "FlagNoUndefs", - "FlagPIE", - "FlagPrebindable", - "FlagPrebound", - "FlagRootSafe", - "FlagSetuidSafe", - "FlagSplitSegs", - "FlagSubsectionsViaSymbols", - "FlagTwoLevel", - "FlagWeakDefines", - "FormatError", - "GENERIC_RELOC_LOCAL_SECTDIFF", - "GENERIC_RELOC_PAIR", - "GENERIC_RELOC_PB_LA_PTR", - "GENERIC_RELOC_SECTDIFF", - "GENERIC_RELOC_TLV", - "GENERIC_RELOC_VANILLA", - "Load", - "LoadBytes", - "LoadCmd", - "LoadCmdDylib", - "LoadCmdDylinker", - "LoadCmdDysymtab", - "LoadCmdRpath", - "LoadCmdSegment", - "LoadCmdSegment64", - "LoadCmdSymtab", - "LoadCmdThread", - "LoadCmdUnixThread", - "Magic32", - "Magic64", - "MagicFat", - "NewFatFile", - "NewFile", - "Nlist32", - "Nlist64", - "Open", - "OpenFat", - "Regs386", - "RegsAMD64", - "Reloc", - "RelocTypeARM", - "RelocTypeARM64", - "RelocTypeGeneric", - "RelocTypeX86_64", - "Rpath", - "RpathCmd", - "Section", - "Section32", - "Section64", - "SectionHeader", - "Segment", - "Segment32", - "Segment64", - "SegmentHeader", - "Symbol", - "Symtab", - "SymtabCmd", - "Thread", - "Type", - "TypeBundle", - "TypeDylib", - "TypeExec", - "TypeObj", - "X86_64_RELOC_BRANCH", - "X86_64_RELOC_GOT", - "X86_64_RELOC_GOT_LOAD", - "X86_64_RELOC_SIGNED", - "X86_64_RELOC_SIGNED_1", - "X86_64_RELOC_SIGNED_2", - "X86_64_RELOC_SIGNED_4", - "X86_64_RELOC_SUBTRACTOR", - "X86_64_RELOC_TLV", - "X86_64_RELOC_UNSIGNED", - }, - "debug/pe": { - "COFFSymbol", - "COFFSymbolAuxFormat5", - "COFFSymbolSize", - "DataDirectory", - "File", - "FileHeader", - "FormatError", - "IMAGE_COMDAT_SELECT_ANY", - "IMAGE_COMDAT_SELECT_ASSOCIATIVE", - "IMAGE_COMDAT_SELECT_EXACT_MATCH", - "IMAGE_COMDAT_SELECT_LARGEST", - "IMAGE_COMDAT_SELECT_NODUPLICATES", - "IMAGE_COMDAT_SELECT_SAME_SIZE", - "IMAGE_DIRECTORY_ENTRY_ARCHITECTURE", - "IMAGE_DIRECTORY_ENTRY_BASERELOC", - "IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT", - "IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR", - "IMAGE_DIRECTORY_ENTRY_DEBUG", - "IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT", - "IMAGE_DIRECTORY_ENTRY_EXCEPTION", - "IMAGE_DIRECTORY_ENTRY_EXPORT", - "IMAGE_DIRECTORY_ENTRY_GLOBALPTR", - "IMAGE_DIRECTORY_ENTRY_IAT", - "IMAGE_DIRECTORY_ENTRY_IMPORT", - "IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG", - "IMAGE_DIRECTORY_ENTRY_RESOURCE", - "IMAGE_DIRECTORY_ENTRY_SECURITY", - "IMAGE_DIRECTORY_ENTRY_TLS", - "IMAGE_DLLCHARACTERISTICS_APPCONTAINER", - "IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE", - "IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY", - "IMAGE_DLLCHARACTERISTICS_GUARD_CF", - "IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA", - "IMAGE_DLLCHARACTERISTICS_NO_BIND", - "IMAGE_DLLCHARACTERISTICS_NO_ISOLATION", - "IMAGE_DLLCHARACTERISTICS_NO_SEH", - "IMAGE_DLLCHARACTERISTICS_NX_COMPAT", - "IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE", - "IMAGE_DLLCHARACTERISTICS_WDM_DRIVER", - "IMAGE_FILE_32BIT_MACHINE", - "IMAGE_FILE_AGGRESIVE_WS_TRIM", - "IMAGE_FILE_BYTES_REVERSED_HI", - "IMAGE_FILE_BYTES_REVERSED_LO", - "IMAGE_FILE_DEBUG_STRIPPED", - "IMAGE_FILE_DLL", - "IMAGE_FILE_EXECUTABLE_IMAGE", - "IMAGE_FILE_LARGE_ADDRESS_AWARE", - "IMAGE_FILE_LINE_NUMS_STRIPPED", - "IMAGE_FILE_LOCAL_SYMS_STRIPPED", - "IMAGE_FILE_MACHINE_AM33", - "IMAGE_FILE_MACHINE_AMD64", - "IMAGE_FILE_MACHINE_ARM", - "IMAGE_FILE_MACHINE_ARM64", - "IMAGE_FILE_MACHINE_ARMNT", - "IMAGE_FILE_MACHINE_EBC", - "IMAGE_FILE_MACHINE_I386", - "IMAGE_FILE_MACHINE_IA64", - "IMAGE_FILE_MACHINE_LOONGARCH32", - "IMAGE_FILE_MACHINE_LOONGARCH64", - "IMAGE_FILE_MACHINE_M32R", - "IMAGE_FILE_MACHINE_MIPS16", - "IMAGE_FILE_MACHINE_MIPSFPU", - "IMAGE_FILE_MACHINE_MIPSFPU16", - "IMAGE_FILE_MACHINE_POWERPC", - "IMAGE_FILE_MACHINE_POWERPCFP", - "IMAGE_FILE_MACHINE_R4000", - "IMAGE_FILE_MACHINE_RISCV128", - "IMAGE_FILE_MACHINE_RISCV32", - "IMAGE_FILE_MACHINE_RISCV64", - "IMAGE_FILE_MACHINE_SH3", - "IMAGE_FILE_MACHINE_SH3DSP", - "IMAGE_FILE_MACHINE_SH4", - "IMAGE_FILE_MACHINE_SH5", - "IMAGE_FILE_MACHINE_THUMB", - "IMAGE_FILE_MACHINE_UNKNOWN", - "IMAGE_FILE_MACHINE_WCEMIPSV2", - "IMAGE_FILE_NET_RUN_FROM_SWAP", - "IMAGE_FILE_RELOCS_STRIPPED", - "IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP", - "IMAGE_FILE_SYSTEM", - "IMAGE_FILE_UP_SYSTEM_ONLY", - "IMAGE_SCN_CNT_CODE", - "IMAGE_SCN_CNT_INITIALIZED_DATA", - "IMAGE_SCN_CNT_UNINITIALIZED_DATA", - "IMAGE_SCN_LNK_COMDAT", - "IMAGE_SCN_MEM_DISCARDABLE", - "IMAGE_SCN_MEM_EXECUTE", - "IMAGE_SCN_MEM_READ", - "IMAGE_SCN_MEM_WRITE", - "IMAGE_SUBSYSTEM_EFI_APPLICATION", - "IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER", - "IMAGE_SUBSYSTEM_EFI_ROM", - "IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER", - "IMAGE_SUBSYSTEM_NATIVE", - "IMAGE_SUBSYSTEM_NATIVE_WINDOWS", - "IMAGE_SUBSYSTEM_OS2_CUI", - "IMAGE_SUBSYSTEM_POSIX_CUI", - "IMAGE_SUBSYSTEM_UNKNOWN", - "IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION", - "IMAGE_SUBSYSTEM_WINDOWS_CE_GUI", - "IMAGE_SUBSYSTEM_WINDOWS_CUI", - "IMAGE_SUBSYSTEM_WINDOWS_GUI", - "IMAGE_SUBSYSTEM_XBOX", - "ImportDirectory", - "NewFile", - "Open", - "OptionalHeader32", - "OptionalHeader64", - "Reloc", - "Section", - "SectionHeader", - "SectionHeader32", - "StringTable", - "Symbol", - }, - "debug/plan9obj": { - "ErrNoSymbols", - "File", - "FileHeader", - "Magic386", - "Magic64", - "MagicAMD64", - "MagicARM", - "NewFile", - "Open", - "Section", - "SectionHeader", - "Sym", - }, - "embed": { - "FS", - }, - "encoding": { - "BinaryMarshaler", - "BinaryUnmarshaler", - "TextMarshaler", - "TextUnmarshaler", - }, - "encoding/ascii85": { - "CorruptInputError", - "Decode", - "Encode", - "MaxEncodedLen", - "NewDecoder", - "NewEncoder", - }, - "encoding/asn1": { - "BitString", - "ClassApplication", - "ClassContextSpecific", - "ClassPrivate", - "ClassUniversal", - "Enumerated", - "Flag", - "Marshal", - "MarshalWithParams", - "NullBytes", - "NullRawValue", - "ObjectIdentifier", - "RawContent", - "RawValue", - "StructuralError", - "SyntaxError", - "TagBMPString", - "TagBitString", - "TagBoolean", - "TagEnum", - "TagGeneralString", - "TagGeneralizedTime", - "TagIA5String", - "TagInteger", - "TagNull", - "TagNumericString", - "TagOID", - "TagOctetString", - "TagPrintableString", - "TagSequence", - "TagSet", - "TagT61String", - "TagUTCTime", - "TagUTF8String", - "Unmarshal", - "UnmarshalWithParams", - }, - "encoding/base32": { - "CorruptInputError", - "Encoding", - "HexEncoding", - "NewDecoder", - "NewEncoder", - "NewEncoding", - "NoPadding", - "StdEncoding", - "StdPadding", - }, - "encoding/base64": { - "CorruptInputError", - "Encoding", - "NewDecoder", - "NewEncoder", - "NewEncoding", - "NoPadding", - "RawStdEncoding", - "RawURLEncoding", - "StdEncoding", - "StdPadding", - "URLEncoding", - }, - "encoding/binary": { - "AppendByteOrder", - "AppendUvarint", - "AppendVarint", - "BigEndian", - "ByteOrder", - "LittleEndian", - "MaxVarintLen16", - "MaxVarintLen32", - "MaxVarintLen64", - "NativeEndian", - "PutUvarint", - "PutVarint", - "Read", - "ReadUvarint", - "ReadVarint", - "Size", - "Uvarint", - "Varint", - "Write", - }, - "encoding/csv": { - "ErrBareQuote", - "ErrFieldCount", - "ErrQuote", - "ErrTrailingComma", - "NewReader", - "NewWriter", - "ParseError", - "Reader", - "Writer", - }, - "encoding/gob": { - "CommonType", - "Decoder", - "Encoder", - "GobDecoder", - "GobEncoder", - "NewDecoder", - "NewEncoder", - "Register", - "RegisterName", - }, - "encoding/hex": { - "Decode", - "DecodeString", - "DecodedLen", - "Dump", - "Dumper", - "Encode", - "EncodeToString", - "EncodedLen", - "ErrLength", - "InvalidByteError", - "NewDecoder", - "NewEncoder", - }, - "encoding/json": { - "Compact", - "Decoder", - "Delim", - "Encoder", - "HTMLEscape", - "Indent", - "InvalidUTF8Error", - "InvalidUnmarshalError", - "Marshal", - "MarshalIndent", - "Marshaler", - "MarshalerError", - "NewDecoder", - "NewEncoder", - "Number", - "RawMessage", - "SyntaxError", - "Token", - "Unmarshal", - "UnmarshalFieldError", - "UnmarshalTypeError", - "Unmarshaler", - "UnsupportedTypeError", - "UnsupportedValueError", - "Valid", - }, - "encoding/pem": { - "Block", - "Decode", - "Encode", - "EncodeToMemory", - }, - "encoding/xml": { - "Attr", - "CharData", - "Comment", - "CopyToken", - "Decoder", - "Directive", - "Encoder", - "EndElement", - "Escape", - "EscapeText", - "HTMLAutoClose", - "HTMLEntity", - "Header", - "Marshal", - "MarshalIndent", - "Marshaler", - "MarshalerAttr", - "Name", - "NewDecoder", - "NewEncoder", - "NewTokenDecoder", - "ProcInst", - "StartElement", - "SyntaxError", - "TagPathError", - "Token", - "TokenReader", - "Unmarshal", - "UnmarshalError", - "Unmarshaler", - "UnmarshalerAttr", - "UnsupportedTypeError", - }, - "errors": { - "As", - "ErrUnsupported", - "Is", - "Join", - "New", - "Unwrap", - }, - "expvar": { - "Do", - "Float", - "Func", - "Get", - "Handler", - "Int", - "KeyValue", - "Map", - "NewFloat", - "NewInt", - "NewMap", - "NewString", - "Publish", - "String", - "Var", - }, - "flag": { - "Arg", - "Args", - "Bool", - "BoolFunc", - "BoolVar", - "CommandLine", - "ContinueOnError", - "Duration", - "DurationVar", - "ErrHelp", - "ErrorHandling", - "ExitOnError", - "Flag", - "FlagSet", - "Float64", - "Float64Var", - "Func", - "Getter", - "Int", - "Int64", - "Int64Var", - "IntVar", - "Lookup", - "NArg", - "NFlag", - "NewFlagSet", - "PanicOnError", - "Parse", - "Parsed", - "PrintDefaults", - "Set", - "String", - "StringVar", - "TextVar", - "Uint", - "Uint64", - "Uint64Var", - "UintVar", - "UnquoteUsage", - "Usage", - "Value", - "Var", - "Visit", - "VisitAll", - }, - "fmt": { - "Append", - "Appendf", - "Appendln", - "Errorf", - "FormatString", - "Formatter", - "Fprint", - "Fprintf", - "Fprintln", - "Fscan", - "Fscanf", - "Fscanln", - "GoStringer", - "Print", - "Printf", - "Println", - "Scan", - "ScanState", - "Scanf", - "Scanln", - "Scanner", - "Sprint", - "Sprintf", - "Sprintln", - "Sscan", - "Sscanf", - "Sscanln", - "State", - "Stringer", - }, - "go/ast": { - "ArrayType", - "AssignStmt", - "Bad", - "BadDecl", - "BadExpr", - "BadStmt", - "BasicLit", - "BinaryExpr", - "BlockStmt", - "BranchStmt", - "CallExpr", - "CaseClause", - "ChanDir", - "ChanType", - "CommClause", - "Comment", - "CommentGroup", - "CommentMap", - "CompositeLit", - "Con", - "Decl", - "DeclStmt", - "DeferStmt", - "Ellipsis", - "EmptyStmt", - "Expr", - "ExprStmt", - "Field", - "FieldFilter", - "FieldList", - "File", - "FileExports", - "Filter", - "FilterDecl", - "FilterFile", - "FilterFuncDuplicates", - "FilterImportDuplicates", - "FilterPackage", - "FilterUnassociatedComments", - "ForStmt", - "Fprint", - "Fun", - "FuncDecl", - "FuncLit", - "FuncType", - "GenDecl", - "GoStmt", - "Ident", - "IfStmt", - "ImportSpec", - "Importer", - "IncDecStmt", - "IndexExpr", - "IndexListExpr", - "Inspect", - "InterfaceType", - "IsExported", - "IsGenerated", - "KeyValueExpr", - "LabeledStmt", - "Lbl", - "MapType", - "MergeMode", - "MergePackageFiles", - "NewCommentMap", - "NewIdent", - "NewObj", - "NewPackage", - "NewScope", - "Node", - "NotNilFilter", - "ObjKind", - "Object", - "Package", - "PackageExports", - "ParenExpr", - "Pkg", - "Print", - "RECV", - "RangeStmt", - "ReturnStmt", - "SEND", - "Scope", - "SelectStmt", - "SelectorExpr", - "SendStmt", - "SliceExpr", - "SortImports", - "Spec", - "StarExpr", - "Stmt", - "StructType", - "SwitchStmt", - "Typ", - "TypeAssertExpr", - "TypeSpec", - "TypeSwitchStmt", - "UnaryExpr", - "ValueSpec", - "Var", - "Visitor", - "Walk", - }, - "go/build": { - "AllowBinary", - "ArchChar", - "Context", - "Default", - "Directive", - "FindOnly", - "IgnoreVendor", - "Import", - "ImportComment", - "ImportDir", - "ImportMode", - "IsLocalImport", - "MultiplePackageError", - "NoGoError", - "Package", - "ToolDir", - }, - "go/build/constraint": { - "AndExpr", - "Expr", - "GoVersion", - "IsGoBuild", - "IsPlusBuild", - "NotExpr", - "OrExpr", - "Parse", - "PlusBuildLines", - "SyntaxError", - "TagExpr", - }, - "go/constant": { - "BinaryOp", - "BitLen", - "Bool", - "BoolVal", - "Bytes", - "Compare", - "Complex", - "Denom", - "Float", - "Float32Val", - "Float64Val", - "Imag", - "Int", - "Int64Val", - "Kind", - "Make", - "MakeBool", - "MakeFloat64", - "MakeFromBytes", - "MakeFromLiteral", - "MakeImag", - "MakeInt64", - "MakeString", - "MakeUint64", - "MakeUnknown", - "Num", - "Real", - "Shift", - "Sign", - "String", - "StringVal", - "ToComplex", - "ToFloat", - "ToInt", - "Uint64Val", - "UnaryOp", - "Unknown", - "Val", - "Value", - }, - "go/doc": { - "AllDecls", - "AllMethods", - "Example", - "Examples", - "Filter", - "Func", - "IllegalPrefixes", - "IsPredeclared", - "Mode", - "New", - "NewFromFiles", - "Note", - "Package", - "PreserveAST", - "Synopsis", - "ToHTML", - "ToText", - "Type", - "Value", - }, - "go/doc/comment": { - "Block", - "Code", - "DefaultLookupPackage", - "Doc", - "DocLink", - "Heading", - "Italic", - "Link", - "LinkDef", - "List", - "ListItem", - "Paragraph", - "Parser", - "Plain", - "Printer", - "Text", - }, - "go/format": { - "Node", - "Source", - }, - "go/importer": { - "Default", - "For", - "ForCompiler", - "Lookup", - }, - "go/parser": { - "AllErrors", - "DeclarationErrors", - "ImportsOnly", - "Mode", - "PackageClauseOnly", - "ParseComments", - "ParseDir", - "ParseExpr", - "ParseExprFrom", - "ParseFile", - "SkipObjectResolution", - "SpuriousErrors", - "Trace", - }, - "go/printer": { - "CommentedNode", - "Config", - "Fprint", - "Mode", - "RawFormat", - "SourcePos", - "TabIndent", - "UseSpaces", - }, - "go/scanner": { - "Error", - "ErrorHandler", - "ErrorList", - "Mode", - "PrintError", - "ScanComments", - "Scanner", - }, - "go/token": { - "ADD", - "ADD_ASSIGN", - "AND", - "AND_ASSIGN", - "AND_NOT", - "AND_NOT_ASSIGN", - "ARROW", - "ASSIGN", - "BREAK", - "CASE", - "CHAN", - "CHAR", - "COLON", - "COMMA", - "COMMENT", - "CONST", - "CONTINUE", - "DEC", - "DEFAULT", - "DEFER", - "DEFINE", - "ELLIPSIS", - "ELSE", - "EOF", - "EQL", - "FALLTHROUGH", - "FLOAT", - "FOR", - "FUNC", - "File", - "FileSet", - "GEQ", - "GO", - "GOTO", - "GTR", - "HighestPrec", - "IDENT", - "IF", - "ILLEGAL", - "IMAG", - "IMPORT", - "INC", - "INT", - "INTERFACE", - "IsExported", - "IsIdentifier", - "IsKeyword", - "LAND", - "LBRACE", - "LBRACK", - "LEQ", - "LOR", - "LPAREN", - "LSS", - "Lookup", - "LowestPrec", - "MAP", - "MUL", - "MUL_ASSIGN", - "NEQ", - "NOT", - "NewFileSet", - "NoPos", - "OR", - "OR_ASSIGN", - "PACKAGE", - "PERIOD", - "Pos", - "Position", - "QUO", - "QUO_ASSIGN", - "RANGE", - "RBRACE", - "RBRACK", - "REM", - "REM_ASSIGN", - "RETURN", - "RPAREN", - "SELECT", - "SEMICOLON", - "SHL", - "SHL_ASSIGN", - "SHR", - "SHR_ASSIGN", - "STRING", - "STRUCT", - "SUB", - "SUB_ASSIGN", - "SWITCH", - "TILDE", - "TYPE", - "Token", - "UnaryPrec", - "VAR", - "XOR", - "XOR_ASSIGN", - }, - "go/types": { - "ArgumentError", - "Array", - "AssertableTo", - "AssignableTo", - "Basic", - "BasicInfo", - "BasicKind", - "Bool", - "Builtin", - "Byte", - "Chan", - "ChanDir", - "CheckExpr", - "Checker", - "Comparable", - "Complex128", - "Complex64", - "Config", - "Const", - "Context", - "ConvertibleTo", - "DefPredeclaredTestFuncs", - "Default", - "Error", - "Eval", - "ExprString", - "FieldVal", - "Float32", - "Float64", - "Func", - "Id", - "Identical", - "IdenticalIgnoreTags", - "Implements", - "ImportMode", - "Importer", - "ImporterFrom", - "Info", - "Initializer", - "Instance", - "Instantiate", - "Int", - "Int16", - "Int32", - "Int64", - "Int8", - "Interface", - "Invalid", - "IsBoolean", - "IsComplex", - "IsConstType", - "IsFloat", - "IsInteger", - "IsInterface", - "IsNumeric", - "IsOrdered", - "IsString", - "IsUnsigned", - "IsUntyped", - "Label", - "LookupFieldOrMethod", - "Map", - "MethodExpr", - "MethodSet", - "MethodVal", - "MissingMethod", - "Named", - "NewArray", - "NewChan", - "NewChecker", - "NewConst", - "NewContext", - "NewField", - "NewFunc", - "NewInterface", - "NewInterfaceType", - "NewLabel", - "NewMap", - "NewMethodSet", - "NewNamed", - "NewPackage", - "NewParam", - "NewPkgName", - "NewPointer", - "NewScope", - "NewSignature", - "NewSignatureType", - "NewSlice", - "NewStruct", - "NewTerm", - "NewTuple", - "NewTypeName", - "NewTypeParam", - "NewUnion", - "NewVar", - "Nil", - "Object", - "ObjectString", - "Package", - "PkgName", - "Pointer", - "Qualifier", - "RecvOnly", - "RelativeTo", - "Rune", - "Satisfies", - "Scope", - "Selection", - "SelectionKind", - "SelectionString", - "SendOnly", - "SendRecv", - "Signature", - "Sizes", - "SizesFor", - "Slice", - "StdSizes", - "String", - "Struct", - "Term", - "Tuple", - "Typ", - "Type", - "TypeAndValue", - "TypeList", - "TypeName", - "TypeParam", - "TypeParamList", - "TypeString", - "Uint", - "Uint16", - "Uint32", - "Uint64", - "Uint8", - "Uintptr", - "Union", - "Universe", - "Unsafe", - "UnsafePointer", - "UntypedBool", - "UntypedComplex", - "UntypedFloat", - "UntypedInt", - "UntypedNil", - "UntypedRune", - "UntypedString", - "Var", - "WriteExpr", - "WriteSignature", - "WriteType", - }, - "hash": { - "Hash", - "Hash32", - "Hash64", - }, - "hash/adler32": { - "Checksum", - "New", - "Size", - }, - "hash/crc32": { - "Castagnoli", - "Checksum", - "ChecksumIEEE", - "IEEE", - "IEEETable", - "Koopman", - "MakeTable", - "New", - "NewIEEE", - "Size", - "Table", - "Update", - }, - "hash/crc64": { - "Checksum", - "ECMA", - "ISO", - "MakeTable", - "New", - "Size", - "Table", - "Update", - }, - "hash/fnv": { - "New128", - "New128a", - "New32", - "New32a", - "New64", - "New64a", - }, - "hash/maphash": { - "Bytes", - "Hash", - "MakeSeed", - "Seed", - "String", - }, - "html": { - "EscapeString", - "UnescapeString", - }, - "html/template": { - "CSS", - "ErrAmbigContext", - "ErrBadHTML", - "ErrBranchEnd", - "ErrEndContext", - "ErrJSTemplate", - "ErrNoSuchTemplate", - "ErrOutputContext", - "ErrPartialCharset", - "ErrPartialEscape", - "ErrPredefinedEscaper", - "ErrRangeLoopReentry", - "ErrSlashAmbig", - "Error", - "ErrorCode", - "FuncMap", - "HTML", - "HTMLAttr", - "HTMLEscape", - "HTMLEscapeString", - "HTMLEscaper", - "IsTrue", - "JS", - "JSEscape", - "JSEscapeString", - "JSEscaper", - "JSStr", - "Must", - "New", - "OK", - "ParseFS", - "ParseFiles", - "ParseGlob", - "Srcset", - "Template", - "URL", - "URLQueryEscaper", - }, - "image": { - "Alpha", - "Alpha16", - "Black", - "CMYK", - "Config", - "Decode", - "DecodeConfig", - "ErrFormat", - "Gray", - "Gray16", - "Image", - "NRGBA", - "NRGBA64", - "NYCbCrA", - "NewAlpha", - "NewAlpha16", - "NewCMYK", - "NewGray", - "NewGray16", - "NewNRGBA", - "NewNRGBA64", - "NewNYCbCrA", - "NewPaletted", - "NewRGBA", - "NewRGBA64", - "NewUniform", - "NewYCbCr", - "Opaque", - "Paletted", - "PalettedImage", - "Point", - "Pt", - "RGBA", - "RGBA64", - "RGBA64Image", - "Rect", - "Rectangle", - "RegisterFormat", - "Transparent", - "Uniform", - "White", - "YCbCr", - "YCbCrSubsampleRatio", - "YCbCrSubsampleRatio410", - "YCbCrSubsampleRatio411", - "YCbCrSubsampleRatio420", - "YCbCrSubsampleRatio422", - "YCbCrSubsampleRatio440", - "YCbCrSubsampleRatio444", - "ZP", - "ZR", - }, - "image/color": { - "Alpha", - "Alpha16", - "Alpha16Model", - "AlphaModel", - "Black", - "CMYK", - "CMYKModel", - "CMYKToRGB", - "Color", - "Gray", - "Gray16", - "Gray16Model", - "GrayModel", - "Model", - "ModelFunc", - "NRGBA", - "NRGBA64", - "NRGBA64Model", - "NRGBAModel", - "NYCbCrA", - "NYCbCrAModel", - "Opaque", - "Palette", - "RGBA", - "RGBA64", - "RGBA64Model", - "RGBAModel", - "RGBToCMYK", - "RGBToYCbCr", - "Transparent", - "White", - "YCbCr", - "YCbCrModel", - "YCbCrToRGB", - }, - "image/color/palette": { - "Plan9", - "WebSafe", - }, - "image/draw": { - "Draw", - "DrawMask", - "Drawer", - "FloydSteinberg", - "Image", - "Op", - "Over", - "Quantizer", - "RGBA64Image", - "Src", - }, - "image/gif": { - "Decode", - "DecodeAll", - "DecodeConfig", - "DisposalBackground", - "DisposalNone", - "DisposalPrevious", - "Encode", - "EncodeAll", - "GIF", - "Options", - }, - "image/jpeg": { - "Decode", - "DecodeConfig", - "DefaultQuality", - "Encode", - "FormatError", - "Options", - "Reader", - "UnsupportedError", - }, - "image/png": { - "BestCompression", - "BestSpeed", - "CompressionLevel", - "Decode", - "DecodeConfig", - "DefaultCompression", - "Encode", - "Encoder", - "EncoderBuffer", - "EncoderBufferPool", - "FormatError", - "NoCompression", - "UnsupportedError", - }, - "index/suffixarray": { - "Index", - "New", - }, - "io": { - "ByteReader", - "ByteScanner", - "ByteWriter", - "Closer", - "Copy", - "CopyBuffer", - "CopyN", - "Discard", - "EOF", - "ErrClosedPipe", - "ErrNoProgress", - "ErrShortBuffer", - "ErrShortWrite", - "ErrUnexpectedEOF", - "LimitReader", - "LimitedReader", - "MultiReader", - "MultiWriter", - "NewOffsetWriter", - "NewSectionReader", - "NopCloser", - "OffsetWriter", - "Pipe", - "PipeReader", - "PipeWriter", - "ReadAll", - "ReadAtLeast", - "ReadCloser", - "ReadFull", - "ReadSeekCloser", - "ReadSeeker", - "ReadWriteCloser", - "ReadWriteSeeker", - "ReadWriter", - "Reader", - "ReaderAt", - "ReaderFrom", - "RuneReader", - "RuneScanner", - "SectionReader", - "SeekCurrent", - "SeekEnd", - "SeekStart", - "Seeker", - "StringWriter", - "TeeReader", - "WriteCloser", - "WriteSeeker", - "WriteString", - "Writer", - "WriterAt", - "WriterTo", - }, - "io/fs": { - "DirEntry", - "ErrClosed", - "ErrExist", - "ErrInvalid", - "ErrNotExist", - "ErrPermission", - "FS", - "File", - "FileInfo", - "FileInfoToDirEntry", - "FileMode", - "FormatDirEntry", - "FormatFileInfo", - "Glob", - "GlobFS", - "ModeAppend", - "ModeCharDevice", - "ModeDevice", - "ModeDir", - "ModeExclusive", - "ModeIrregular", - "ModeNamedPipe", - "ModePerm", - "ModeSetgid", - "ModeSetuid", - "ModeSocket", - "ModeSticky", - "ModeSymlink", - "ModeTemporary", - "ModeType", - "PathError", - "ReadDir", - "ReadDirFS", - "ReadDirFile", - "ReadFile", - "ReadFileFS", - "SkipAll", - "SkipDir", - "Stat", - "StatFS", - "Sub", - "SubFS", - "ValidPath", - "WalkDir", - "WalkDirFunc", - }, - "io/ioutil": { - "Discard", - "NopCloser", - "ReadAll", - "ReadDir", - "ReadFile", - "TempDir", - "TempFile", - "WriteFile", - }, - "log": { - "Default", - "Fatal", - "Fatalf", - "Fatalln", - "Flags", - "LUTC", - "Ldate", - "Llongfile", - "Lmicroseconds", - "Lmsgprefix", - "Logger", - "Lshortfile", - "LstdFlags", - "Ltime", - "New", - "Output", - "Panic", - "Panicf", - "Panicln", - "Prefix", - "Print", - "Printf", - "Println", - "SetFlags", - "SetOutput", - "SetPrefix", - "Writer", - }, - "log/slog": { - "Any", - "AnyValue", - "Attr", - "Bool", - "BoolValue", - "Debug", - "DebugContext", - "Default", - "Duration", - "DurationValue", - "Error", - "ErrorContext", - "Float64", - "Float64Value", - "Group", - "GroupValue", - "Handler", - "HandlerOptions", - "Info", - "InfoContext", - "Int", - "Int64", - "Int64Value", - "IntValue", - "JSONHandler", - "Kind", - "KindAny", - "KindBool", - "KindDuration", - "KindFloat64", - "KindGroup", - "KindInt64", - "KindLogValuer", - "KindString", - "KindTime", - "KindUint64", - "Level", - "LevelDebug", - "LevelError", - "LevelInfo", - "LevelKey", - "LevelVar", - "LevelWarn", - "Leveler", - "Log", - "LogAttrs", - "LogValuer", - "Logger", - "MessageKey", - "New", - "NewJSONHandler", - "NewLogLogger", - "NewRecord", - "NewTextHandler", - "Record", - "SetDefault", - "Source", - "SourceKey", - "String", - "StringValue", - "TextHandler", - "Time", - "TimeKey", - "TimeValue", - "Uint64", - "Uint64Value", - "Value", - "Warn", - "WarnContext", - "With", - }, - "log/syslog": { - "Dial", - "LOG_ALERT", - "LOG_AUTH", - "LOG_AUTHPRIV", - "LOG_CRIT", - "LOG_CRON", - "LOG_DAEMON", - "LOG_DEBUG", - "LOG_EMERG", - "LOG_ERR", - "LOG_FTP", - "LOG_INFO", - "LOG_KERN", - "LOG_LOCAL0", - "LOG_LOCAL1", - "LOG_LOCAL2", - "LOG_LOCAL3", - "LOG_LOCAL4", - "LOG_LOCAL5", - "LOG_LOCAL6", - "LOG_LOCAL7", - "LOG_LPR", - "LOG_MAIL", - "LOG_NEWS", - "LOG_NOTICE", - "LOG_SYSLOG", - "LOG_USER", - "LOG_UUCP", - "LOG_WARNING", - "New", - "NewLogger", - "Priority", - "Writer", - }, - "maps": { - "Clone", - "Copy", - "DeleteFunc", - "Equal", - "EqualFunc", - }, - "math": { - "Abs", - "Acos", - "Acosh", - "Asin", - "Asinh", - "Atan", - "Atan2", - "Atanh", - "Cbrt", - "Ceil", - "Copysign", - "Cos", - "Cosh", - "Dim", - "E", - "Erf", - "Erfc", - "Erfcinv", - "Erfinv", - "Exp", - "Exp2", - "Expm1", - "FMA", - "Float32bits", - "Float32frombits", - "Float64bits", - "Float64frombits", - "Floor", - "Frexp", - "Gamma", - "Hypot", - "Ilogb", - "Inf", - "IsInf", - "IsNaN", - "J0", - "J1", - "Jn", - "Ldexp", - "Lgamma", - "Ln10", - "Ln2", - "Log", - "Log10", - "Log10E", - "Log1p", - "Log2", - "Log2E", - "Logb", - "Max", - "MaxFloat32", - "MaxFloat64", - "MaxInt", - "MaxInt16", - "MaxInt32", - "MaxInt64", - "MaxInt8", - "MaxUint", - "MaxUint16", - "MaxUint32", - "MaxUint64", - "MaxUint8", - "Min", - "MinInt", - "MinInt16", - "MinInt32", - "MinInt64", - "MinInt8", - "Mod", - "Modf", - "NaN", - "Nextafter", - "Nextafter32", - "Phi", - "Pi", - "Pow", - "Pow10", - "Remainder", - "Round", - "RoundToEven", - "Signbit", - "Sin", - "Sincos", - "Sinh", - "SmallestNonzeroFloat32", - "SmallestNonzeroFloat64", - "Sqrt", - "Sqrt2", - "SqrtE", - "SqrtPhi", - "SqrtPi", - "Tan", - "Tanh", - "Trunc", - "Y0", - "Y1", - "Yn", - }, - "math/big": { - "Above", - "Accuracy", - "AwayFromZero", - "Below", - "ErrNaN", - "Exact", - "Float", - "Int", - "Jacobi", - "MaxBase", - "MaxExp", - "MaxPrec", - "MinExp", - "NewFloat", - "NewInt", - "NewRat", - "ParseFloat", - "Rat", - "RoundingMode", - "ToNearestAway", - "ToNearestEven", - "ToNegativeInf", - "ToPositiveInf", - "ToZero", - "Word", - }, - "math/bits": { - "Add", - "Add32", - "Add64", - "Div", - "Div32", - "Div64", - "LeadingZeros", - "LeadingZeros16", - "LeadingZeros32", - "LeadingZeros64", - "LeadingZeros8", - "Len", - "Len16", - "Len32", - "Len64", - "Len8", - "Mul", - "Mul32", - "Mul64", - "OnesCount", - "OnesCount16", - "OnesCount32", - "OnesCount64", - "OnesCount8", - "Rem", - "Rem32", - "Rem64", - "Reverse", - "Reverse16", - "Reverse32", - "Reverse64", - "Reverse8", - "ReverseBytes", - "ReverseBytes16", - "ReverseBytes32", - "ReverseBytes64", - "RotateLeft", - "RotateLeft16", - "RotateLeft32", - "RotateLeft64", - "RotateLeft8", - "Sub", - "Sub32", - "Sub64", - "TrailingZeros", - "TrailingZeros16", - "TrailingZeros32", - "TrailingZeros64", - "TrailingZeros8", - "UintSize", - }, - "math/cmplx": { - "Abs", - "Acos", - "Acosh", - "Asin", - "Asinh", - "Atan", - "Atanh", - "Conj", - "Cos", - "Cosh", - "Cot", - "Exp", - "Inf", - "IsInf", - "IsNaN", - "Log", - "Log10", - "NaN", - "Phase", - "Polar", - "Pow", - "Rect", - "Sin", - "Sinh", - "Sqrt", - "Tan", - "Tanh", - }, - "math/rand": { - "ExpFloat64", - "Float32", - "Float64", - "Int", - "Int31", - "Int31n", - "Int63", - "Int63n", - "Intn", - "New", - "NewSource", - "NewZipf", - "NormFloat64", - "Perm", - "Rand", - "Read", - "Seed", - "Shuffle", - "Source", - "Source64", - "Uint32", - "Uint64", - "Zipf", - }, - "mime": { - "AddExtensionType", - "BEncoding", - "ErrInvalidMediaParameter", - "ExtensionsByType", - "FormatMediaType", - "ParseMediaType", - "QEncoding", - "TypeByExtension", - "WordDecoder", - "WordEncoder", - }, - "mime/multipart": { - "ErrMessageTooLarge", - "File", - "FileHeader", - "Form", - "NewReader", - "NewWriter", - "Part", - "Reader", - "Writer", - }, - "mime/quotedprintable": { - "NewReader", - "NewWriter", - "Reader", - "Writer", - }, - "net": { - "Addr", - "AddrError", - "Buffers", - "CIDRMask", - "Conn", - "DNSConfigError", - "DNSError", - "DefaultResolver", - "Dial", - "DialIP", - "DialTCP", - "DialTimeout", - "DialUDP", - "DialUnix", - "Dialer", - "ErrClosed", - "ErrWriteToConnected", - "Error", - "FileConn", - "FileListener", - "FilePacketConn", - "FlagBroadcast", - "FlagLoopback", - "FlagMulticast", - "FlagPointToPoint", - "FlagRunning", - "FlagUp", - "Flags", - "HardwareAddr", - "IP", - "IPAddr", - "IPConn", - "IPMask", - "IPNet", - "IPv4", - "IPv4Mask", - "IPv4allrouter", - "IPv4allsys", - "IPv4bcast", - "IPv4len", - "IPv4zero", - "IPv6interfacelocalallnodes", - "IPv6len", - "IPv6linklocalallnodes", - "IPv6linklocalallrouters", - "IPv6loopback", - "IPv6unspecified", - "IPv6zero", - "Interface", - "InterfaceAddrs", - "InterfaceByIndex", - "InterfaceByName", - "Interfaces", - "InvalidAddrError", - "JoinHostPort", - "Listen", - "ListenConfig", - "ListenIP", - "ListenMulticastUDP", - "ListenPacket", - "ListenTCP", - "ListenUDP", - "ListenUnix", - "ListenUnixgram", - "Listener", - "LookupAddr", - "LookupCNAME", - "LookupHost", - "LookupIP", - "LookupMX", - "LookupNS", - "LookupPort", - "LookupSRV", - "LookupTXT", - "MX", - "NS", - "OpError", - "PacketConn", - "ParseCIDR", - "ParseError", - "ParseIP", - "ParseMAC", - "Pipe", - "ResolveIPAddr", - "ResolveTCPAddr", - "ResolveUDPAddr", - "ResolveUnixAddr", - "Resolver", - "SRV", - "SplitHostPort", - "TCPAddr", - "TCPAddrFromAddrPort", - "TCPConn", - "TCPListener", - "UDPAddr", - "UDPAddrFromAddrPort", - "UDPConn", - "UnixAddr", - "UnixConn", - "UnixListener", - "UnknownNetworkError", - }, - "net/http": { - "AllowQuerySemicolons", - "CanonicalHeaderKey", - "Client", - "CloseNotifier", - "ConnState", - "Cookie", - "CookieJar", - "DefaultClient", - "DefaultMaxHeaderBytes", - "DefaultMaxIdleConnsPerHost", - "DefaultServeMux", - "DefaultTransport", - "DetectContentType", - "Dir", - "ErrAbortHandler", - "ErrBodyNotAllowed", - "ErrBodyReadAfterClose", - "ErrContentLength", - "ErrHandlerTimeout", - "ErrHeaderTooLong", - "ErrHijacked", - "ErrLineTooLong", - "ErrMissingBoundary", - "ErrMissingContentLength", - "ErrMissingFile", - "ErrNoCookie", - "ErrNoLocation", - "ErrNotMultipart", - "ErrNotSupported", - "ErrSchemeMismatch", - "ErrServerClosed", - "ErrShortBody", - "ErrSkipAltProtocol", - "ErrUnexpectedTrailer", - "ErrUseLastResponse", - "ErrWriteAfterFlush", - "Error", - "FS", - "File", - "FileServer", - "FileSystem", - "Flusher", - "Get", - "Handle", - "HandleFunc", - "Handler", - "HandlerFunc", - "Head", - "Header", - "Hijacker", - "ListenAndServe", - "ListenAndServeTLS", - "LocalAddrContextKey", - "MaxBytesError", - "MaxBytesHandler", - "MaxBytesReader", - "MethodConnect", - "MethodDelete", - "MethodGet", - "MethodHead", - "MethodOptions", - "MethodPatch", - "MethodPost", - "MethodPut", - "MethodTrace", - "NewFileTransport", - "NewRequest", - "NewRequestWithContext", - "NewResponseController", - "NewServeMux", - "NoBody", - "NotFound", - "NotFoundHandler", - "ParseHTTPVersion", - "ParseTime", - "Post", - "PostForm", - "ProtocolError", - "ProxyFromEnvironment", - "ProxyURL", - "PushOptions", - "Pusher", - "ReadRequest", - "ReadResponse", - "Redirect", - "RedirectHandler", - "Request", - "Response", - "ResponseController", - "ResponseWriter", - "RoundTripper", - "SameSite", - "SameSiteDefaultMode", - "SameSiteLaxMode", - "SameSiteNoneMode", - "SameSiteStrictMode", - "Serve", - "ServeContent", - "ServeFile", - "ServeMux", - "ServeTLS", - "Server", - "ServerContextKey", - "SetCookie", - "StateActive", - "StateClosed", - "StateHijacked", - "StateIdle", - "StateNew", - "StatusAccepted", - "StatusAlreadyReported", - "StatusBadGateway", - "StatusBadRequest", - "StatusConflict", - "StatusContinue", - "StatusCreated", - "StatusEarlyHints", - "StatusExpectationFailed", - "StatusFailedDependency", - "StatusForbidden", - "StatusFound", - "StatusGatewayTimeout", - "StatusGone", - "StatusHTTPVersionNotSupported", - "StatusIMUsed", - "StatusInsufficientStorage", - "StatusInternalServerError", - "StatusLengthRequired", - "StatusLocked", - "StatusLoopDetected", - "StatusMethodNotAllowed", - "StatusMisdirectedRequest", - "StatusMovedPermanently", - "StatusMultiStatus", - "StatusMultipleChoices", - "StatusNetworkAuthenticationRequired", - "StatusNoContent", - "StatusNonAuthoritativeInfo", - "StatusNotAcceptable", - "StatusNotExtended", - "StatusNotFound", - "StatusNotImplemented", - "StatusNotModified", - "StatusOK", - "StatusPartialContent", - "StatusPaymentRequired", - "StatusPermanentRedirect", - "StatusPreconditionFailed", - "StatusPreconditionRequired", - "StatusProcessing", - "StatusProxyAuthRequired", - "StatusRequestEntityTooLarge", - "StatusRequestHeaderFieldsTooLarge", - "StatusRequestTimeout", - "StatusRequestURITooLong", - "StatusRequestedRangeNotSatisfiable", - "StatusResetContent", - "StatusSeeOther", - "StatusServiceUnavailable", - "StatusSwitchingProtocols", - "StatusTeapot", - "StatusTemporaryRedirect", - "StatusText", - "StatusTooEarly", - "StatusTooManyRequests", - "StatusUnauthorized", - "StatusUnavailableForLegalReasons", - "StatusUnprocessableEntity", - "StatusUnsupportedMediaType", - "StatusUpgradeRequired", - "StatusUseProxy", - "StatusVariantAlsoNegotiates", - "StripPrefix", - "TimeFormat", - "TimeoutHandler", - "TrailerPrefix", - "Transport", - }, - "net/http/cgi": { - "Handler", - "Request", - "RequestFromMap", - "Serve", - }, - "net/http/cookiejar": { - "Jar", - "New", - "Options", - "PublicSuffixList", - }, - "net/http/fcgi": { - "ErrConnClosed", - "ErrRequestAborted", - "ProcessEnv", - "Serve", - }, - "net/http/httptest": { - "DefaultRemoteAddr", - "NewRecorder", - "NewRequest", - "NewServer", - "NewTLSServer", - "NewUnstartedServer", - "ResponseRecorder", - "Server", - }, - "net/http/httptrace": { - "ClientTrace", - "ContextClientTrace", - "DNSDoneInfo", - "DNSStartInfo", - "GotConnInfo", - "WithClientTrace", - "WroteRequestInfo", - }, - "net/http/httputil": { - "BufferPool", - "ClientConn", - "DumpRequest", - "DumpRequestOut", - "DumpResponse", - "ErrClosed", - "ErrLineTooLong", - "ErrPersistEOF", - "ErrPipeline", - "NewChunkedReader", - "NewChunkedWriter", - "NewClientConn", - "NewProxyClientConn", - "NewServerConn", - "NewSingleHostReverseProxy", - "ProxyRequest", - "ReverseProxy", - "ServerConn", - }, - "net/http/pprof": { - "Cmdline", - "Handler", - "Index", - "Profile", - "Symbol", - "Trace", - }, - "net/mail": { - "Address", - "AddressParser", - "ErrHeaderNotPresent", - "Header", - "Message", - "ParseAddress", - "ParseAddressList", - "ParseDate", - "ReadMessage", - }, - "net/netip": { - "Addr", - "AddrFrom16", - "AddrFrom4", - "AddrFromSlice", - "AddrPort", - "AddrPortFrom", - "IPv4Unspecified", - "IPv6LinkLocalAllNodes", - "IPv6LinkLocalAllRouters", - "IPv6Loopback", - "IPv6Unspecified", - "MustParseAddr", - "MustParseAddrPort", - "MustParsePrefix", - "ParseAddr", - "ParseAddrPort", - "ParsePrefix", - "Prefix", - "PrefixFrom", - }, - "net/rpc": { - "Accept", - "Call", - "Client", - "ClientCodec", - "DefaultDebugPath", - "DefaultRPCPath", - "DefaultServer", - "Dial", - "DialHTTP", - "DialHTTPPath", - "ErrShutdown", - "HandleHTTP", - "NewClient", - "NewClientWithCodec", - "NewServer", - "Register", - "RegisterName", - "Request", - "Response", - "ServeCodec", - "ServeConn", - "ServeRequest", - "Server", - "ServerCodec", - "ServerError", - }, - "net/rpc/jsonrpc": { - "Dial", - "NewClient", - "NewClientCodec", - "NewServerCodec", - "ServeConn", - }, - "net/smtp": { - "Auth", - "CRAMMD5Auth", - "Client", - "Dial", - "NewClient", - "PlainAuth", - "SendMail", - "ServerInfo", - }, - "net/textproto": { - "CanonicalMIMEHeaderKey", - "Conn", - "Dial", - "Error", - "MIMEHeader", - "NewConn", - "NewReader", - "NewWriter", - "Pipeline", - "ProtocolError", - "Reader", - "TrimBytes", - "TrimString", - "Writer", - }, - "net/url": { - "Error", - "EscapeError", - "InvalidHostError", - "JoinPath", - "Parse", - "ParseQuery", - "ParseRequestURI", - "PathEscape", - "PathUnescape", - "QueryEscape", - "QueryUnescape", - "URL", - "User", - "UserPassword", - "Userinfo", - "Values", - }, - "os": { - "Args", - "Chdir", - "Chmod", - "Chown", - "Chtimes", - "Clearenv", - "Create", - "CreateTemp", - "DevNull", - "DirEntry", - "DirFS", - "Environ", - "ErrClosed", - "ErrDeadlineExceeded", - "ErrExist", - "ErrInvalid", - "ErrNoDeadline", - "ErrNotExist", - "ErrPermission", - "ErrProcessDone", - "Executable", - "Exit", - "Expand", - "ExpandEnv", - "File", - "FileInfo", - "FileMode", - "FindProcess", - "Getegid", - "Getenv", - "Geteuid", - "Getgid", - "Getgroups", - "Getpagesize", - "Getpid", - "Getppid", - "Getuid", - "Getwd", - "Hostname", - "Interrupt", - "IsExist", - "IsNotExist", - "IsPathSeparator", - "IsPermission", - "IsTimeout", - "Kill", - "Lchown", - "Link", - "LinkError", - "LookupEnv", - "Lstat", - "Mkdir", - "MkdirAll", - "MkdirTemp", - "ModeAppend", - "ModeCharDevice", - "ModeDevice", - "ModeDir", - "ModeExclusive", - "ModeIrregular", - "ModeNamedPipe", - "ModePerm", - "ModeSetgid", - "ModeSetuid", - "ModeSocket", - "ModeSticky", - "ModeSymlink", - "ModeTemporary", - "ModeType", - "NewFile", - "NewSyscallError", - "O_APPEND", - "O_CREATE", - "O_EXCL", - "O_RDONLY", - "O_RDWR", - "O_SYNC", - "O_TRUNC", - "O_WRONLY", - "Open", - "OpenFile", - "PathError", - "PathListSeparator", - "PathSeparator", - "Pipe", - "ProcAttr", - "Process", - "ProcessState", - "ReadDir", - "ReadFile", - "Readlink", - "Remove", - "RemoveAll", - "Rename", - "SEEK_CUR", - "SEEK_END", - "SEEK_SET", - "SameFile", - "Setenv", - "Signal", - "StartProcess", - "Stat", - "Stderr", - "Stdin", - "Stdout", - "Symlink", - "SyscallError", - "TempDir", - "Truncate", - "Unsetenv", - "UserCacheDir", - "UserConfigDir", - "UserHomeDir", - "WriteFile", - }, - "os/exec": { - "Cmd", - "Command", - "CommandContext", - "ErrDot", - "ErrNotFound", - "ErrWaitDelay", - "Error", - "ExitError", - "LookPath", - }, - "os/signal": { - "Ignore", - "Ignored", - "Notify", - "NotifyContext", - "Reset", - "Stop", - }, - "os/user": { - "Current", - "Group", - "Lookup", - "LookupGroup", - "LookupGroupId", - "LookupId", - "UnknownGroupError", - "UnknownGroupIdError", - "UnknownUserError", - "UnknownUserIdError", - "User", - }, - "path": { - "Base", - "Clean", - "Dir", - "ErrBadPattern", - "Ext", - "IsAbs", - "Join", - "Match", - "Split", - }, - "path/filepath": { - "Abs", - "Base", - "Clean", - "Dir", - "ErrBadPattern", - "EvalSymlinks", - "Ext", - "FromSlash", - "Glob", - "HasPrefix", - "IsAbs", - "IsLocal", - "Join", - "ListSeparator", - "Match", - "Rel", - "Separator", - "SkipAll", - "SkipDir", - "Split", - "SplitList", - "ToSlash", - "VolumeName", - "Walk", - "WalkDir", - "WalkFunc", - }, - "plugin": { - "Open", - "Plugin", - "Symbol", - }, - "reflect": { - "Append", - "AppendSlice", - "Array", - "ArrayOf", - "Bool", - "BothDir", - "Chan", - "ChanDir", - "ChanOf", - "Complex128", - "Complex64", - "Copy", - "DeepEqual", - "Float32", - "Float64", - "Func", - "FuncOf", - "Indirect", - "Int", - "Int16", - "Int32", - "Int64", - "Int8", - "Interface", - "Invalid", - "Kind", - "MakeChan", - "MakeFunc", - "MakeMap", - "MakeMapWithSize", - "MakeSlice", - "Map", - "MapIter", - "MapOf", - "Method", - "New", - "NewAt", - "Pointer", - "PointerTo", - "Ptr", - "PtrTo", - "RecvDir", - "Select", - "SelectCase", - "SelectDefault", - "SelectDir", - "SelectRecv", - "SelectSend", - "SendDir", - "Slice", - "SliceHeader", - "SliceOf", - "String", - "StringHeader", - "Struct", - "StructField", - "StructOf", - "StructTag", - "Swapper", - "Type", - "TypeOf", - "Uint", - "Uint16", - "Uint32", - "Uint64", - "Uint8", - "Uintptr", - "UnsafePointer", - "Value", - "ValueError", - "ValueOf", - "VisibleFields", - "Zero", - }, - "regexp": { - "Compile", - "CompilePOSIX", - "Match", - "MatchReader", - "MatchString", - "MustCompile", - "MustCompilePOSIX", - "QuoteMeta", - "Regexp", - }, - "regexp/syntax": { - "ClassNL", - "Compile", - "DotNL", - "EmptyBeginLine", - "EmptyBeginText", - "EmptyEndLine", - "EmptyEndText", - "EmptyNoWordBoundary", - "EmptyOp", - "EmptyOpContext", - "EmptyWordBoundary", - "ErrInternalError", - "ErrInvalidCharClass", - "ErrInvalidCharRange", - "ErrInvalidEscape", - "ErrInvalidNamedCapture", - "ErrInvalidPerlOp", - "ErrInvalidRepeatOp", - "ErrInvalidRepeatSize", - "ErrInvalidUTF8", - "ErrLarge", - "ErrMissingBracket", - "ErrMissingParen", - "ErrMissingRepeatArgument", - "ErrNestingDepth", - "ErrTrailingBackslash", - "ErrUnexpectedParen", - "Error", - "ErrorCode", - "Flags", - "FoldCase", - "Inst", - "InstAlt", - "InstAltMatch", - "InstCapture", - "InstEmptyWidth", - "InstFail", - "InstMatch", - "InstNop", - "InstOp", - "InstRune", - "InstRune1", - "InstRuneAny", - "InstRuneAnyNotNL", - "IsWordChar", - "Literal", - "MatchNL", - "NonGreedy", - "OneLine", - "Op", - "OpAlternate", - "OpAnyChar", - "OpAnyCharNotNL", - "OpBeginLine", - "OpBeginText", - "OpCapture", - "OpCharClass", - "OpConcat", - "OpEmptyMatch", - "OpEndLine", - "OpEndText", - "OpLiteral", - "OpNoMatch", - "OpNoWordBoundary", - "OpPlus", - "OpQuest", - "OpRepeat", - "OpStar", - "OpWordBoundary", - "POSIX", - "Parse", - "Perl", - "PerlX", - "Prog", - "Regexp", - "Simple", - "UnicodeGroups", - "WasDollar", - }, - "runtime": { - "BlockProfile", - "BlockProfileRecord", - "Breakpoint", - "CPUProfile", - "Caller", - "Callers", - "CallersFrames", - "Compiler", - "Error", - "Frame", - "Frames", - "Func", - "FuncForPC", - "GC", - "GOARCH", - "GOMAXPROCS", - "GOOS", - "GOROOT", - "Goexit", - "GoroutineProfile", - "Gosched", - "KeepAlive", - "LockOSThread", - "MemProfile", - "MemProfileRate", - "MemProfileRecord", - "MemStats", - "MutexProfile", - "NumCPU", - "NumCgoCall", - "NumGoroutine", - "PanicNilError", - "Pinner", - "ReadMemStats", - "ReadTrace", - "SetBlockProfileRate", - "SetCPUProfileRate", - "SetCgoTraceback", - "SetFinalizer", - "SetMutexProfileFraction", - "Stack", - "StackRecord", - "StartTrace", - "StopTrace", - "ThreadCreateProfile", - "TypeAssertionError", - "UnlockOSThread", - "Version", - }, - "runtime/cgo": { - "Handle", - "Incomplete", - "NewHandle", - }, - "runtime/coverage": { - "ClearCounters", - "WriteCounters", - "WriteCountersDir", - "WriteMeta", - "WriteMetaDir", - }, - "runtime/debug": { - "BuildInfo", - "BuildSetting", - "FreeOSMemory", - "GCStats", - "Module", - "ParseBuildInfo", - "PrintStack", - "ReadBuildInfo", - "ReadGCStats", - "SetGCPercent", - "SetMaxStack", - "SetMaxThreads", - "SetMemoryLimit", - "SetPanicOnFault", - "SetTraceback", - "Stack", - "WriteHeapDump", - }, - "runtime/metrics": { - "All", - "Description", - "Float64Histogram", - "KindBad", - "KindFloat64", - "KindFloat64Histogram", - "KindUint64", - "Read", - "Sample", - "Value", - "ValueKind", - }, - "runtime/pprof": { - "Do", - "ForLabels", - "Label", - "LabelSet", - "Labels", - "Lookup", - "NewProfile", - "Profile", - "Profiles", - "SetGoroutineLabels", - "StartCPUProfile", - "StopCPUProfile", - "WithLabels", - "WriteHeapProfile", - }, - "runtime/trace": { - "IsEnabled", - "Log", - "Logf", - "NewTask", - "Region", - "Start", - "StartRegion", - "Stop", - "Task", - "WithRegion", - }, - "slices": { - "BinarySearch", - "BinarySearchFunc", - "Clip", - "Clone", - "Compact", - "CompactFunc", - "Compare", - "CompareFunc", - "Contains", - "ContainsFunc", - "Delete", - "DeleteFunc", - "Equal", - "EqualFunc", - "Grow", - "Index", - "IndexFunc", - "Insert", - "IsSorted", - "IsSortedFunc", - "Max", - "MaxFunc", - "Min", - "MinFunc", - "Replace", - "Reverse", - "Sort", - "SortFunc", - "SortStableFunc", - }, - "sort": { - "Find", - "Float64Slice", - "Float64s", - "Float64sAreSorted", - "IntSlice", - "Interface", - "Ints", - "IntsAreSorted", - "IsSorted", - "Reverse", - "Search", - "SearchFloat64s", - "SearchInts", - "SearchStrings", - "Slice", - "SliceIsSorted", - "SliceStable", - "Sort", - "Stable", - "StringSlice", - "Strings", - "StringsAreSorted", - }, - "strconv": { - "AppendBool", - "AppendFloat", - "AppendInt", - "AppendQuote", - "AppendQuoteRune", - "AppendQuoteRuneToASCII", - "AppendQuoteRuneToGraphic", - "AppendQuoteToASCII", - "AppendQuoteToGraphic", - "AppendUint", - "Atoi", - "CanBackquote", - "ErrRange", - "ErrSyntax", - "FormatBool", - "FormatComplex", - "FormatFloat", - "FormatInt", - "FormatUint", - "IntSize", - "IsGraphic", - "IsPrint", - "Itoa", - "NumError", - "ParseBool", - "ParseComplex", - "ParseFloat", - "ParseInt", - "ParseUint", - "Quote", - "QuoteRune", - "QuoteRuneToASCII", - "QuoteRuneToGraphic", - "QuoteToASCII", - "QuoteToGraphic", - "QuotedPrefix", - "Unquote", - "UnquoteChar", - }, - "strings": { - "Builder", - "Clone", - "Compare", - "Contains", - "ContainsAny", - "ContainsFunc", - "ContainsRune", - "Count", - "Cut", - "CutPrefix", - "CutSuffix", - "EqualFold", - "Fields", - "FieldsFunc", - "HasPrefix", - "HasSuffix", - "Index", - "IndexAny", - "IndexByte", - "IndexFunc", - "IndexRune", - "Join", - "LastIndex", - "LastIndexAny", - "LastIndexByte", - "LastIndexFunc", - "Map", - "NewReader", - "NewReplacer", - "Reader", - "Repeat", - "Replace", - "ReplaceAll", - "Replacer", - "Split", - "SplitAfter", - "SplitAfterN", - "SplitN", - "Title", - "ToLower", - "ToLowerSpecial", - "ToTitle", - "ToTitleSpecial", - "ToUpper", - "ToUpperSpecial", - "ToValidUTF8", - "Trim", - "TrimFunc", - "TrimLeft", - "TrimLeftFunc", - "TrimPrefix", - "TrimRight", - "TrimRightFunc", - "TrimSpace", - "TrimSuffix", - }, - "sync": { - "Cond", - "Locker", - "Map", - "Mutex", - "NewCond", - "Once", - "OnceFunc", - "OnceValue", - "OnceValues", - "Pool", - "RWMutex", - "WaitGroup", - }, - "sync/atomic": { - "AddInt32", - "AddInt64", - "AddUint32", - "AddUint64", - "AddUintptr", - "Bool", - "CompareAndSwapInt32", - "CompareAndSwapInt64", - "CompareAndSwapPointer", - "CompareAndSwapUint32", - "CompareAndSwapUint64", - "CompareAndSwapUintptr", - "Int32", - "Int64", - "LoadInt32", - "LoadInt64", - "LoadPointer", - "LoadUint32", - "LoadUint64", - "LoadUintptr", - "Pointer", - "StoreInt32", - "StoreInt64", - "StorePointer", - "StoreUint32", - "StoreUint64", - "StoreUintptr", - "SwapInt32", - "SwapInt64", - "SwapPointer", - "SwapUint32", - "SwapUint64", - "SwapUintptr", - "Uint32", - "Uint64", - "Uintptr", - "Value", - }, - "syscall": { - "AF_ALG", - "AF_APPLETALK", - "AF_ARP", - "AF_ASH", - "AF_ATM", - "AF_ATMPVC", - "AF_ATMSVC", - "AF_AX25", - "AF_BLUETOOTH", - "AF_BRIDGE", - "AF_CAIF", - "AF_CAN", - "AF_CCITT", - "AF_CHAOS", - "AF_CNT", - "AF_COIP", - "AF_DATAKIT", - "AF_DECnet", - "AF_DLI", - "AF_E164", - "AF_ECMA", - "AF_ECONET", - "AF_ENCAP", - "AF_FILE", - "AF_HYLINK", - "AF_IEEE80211", - "AF_IEEE802154", - "AF_IMPLINK", - "AF_INET", - "AF_INET6", - "AF_INET6_SDP", - "AF_INET_SDP", - "AF_IPX", - "AF_IRDA", - "AF_ISDN", - "AF_ISO", - "AF_IUCV", - "AF_KEY", - "AF_LAT", - "AF_LINK", - "AF_LLC", - "AF_LOCAL", - "AF_MAX", - "AF_MPLS", - "AF_NATM", - "AF_NDRV", - "AF_NETBEUI", - "AF_NETBIOS", - "AF_NETGRAPH", - "AF_NETLINK", - "AF_NETROM", - "AF_NS", - "AF_OROUTE", - "AF_OSI", - "AF_PACKET", - "AF_PHONET", - "AF_PPP", - "AF_PPPOX", - "AF_PUP", - "AF_RDS", - "AF_RESERVED_36", - "AF_ROSE", - "AF_ROUTE", - "AF_RXRPC", - "AF_SCLUSTER", - "AF_SECURITY", - "AF_SIP", - "AF_SLOW", - "AF_SNA", - "AF_SYSTEM", - "AF_TIPC", - "AF_UNIX", - "AF_UNSPEC", - "AF_UTUN", - "AF_VENDOR00", - "AF_VENDOR01", - "AF_VENDOR02", - "AF_VENDOR03", - "AF_VENDOR04", - "AF_VENDOR05", - "AF_VENDOR06", - "AF_VENDOR07", - "AF_VENDOR08", - "AF_VENDOR09", - "AF_VENDOR10", - "AF_VENDOR11", - "AF_VENDOR12", - "AF_VENDOR13", - "AF_VENDOR14", - "AF_VENDOR15", - "AF_VENDOR16", - "AF_VENDOR17", - "AF_VENDOR18", - "AF_VENDOR19", - "AF_VENDOR20", - "AF_VENDOR21", - "AF_VENDOR22", - "AF_VENDOR23", - "AF_VENDOR24", - "AF_VENDOR25", - "AF_VENDOR26", - "AF_VENDOR27", - "AF_VENDOR28", - "AF_VENDOR29", - "AF_VENDOR30", - "AF_VENDOR31", - "AF_VENDOR32", - "AF_VENDOR33", - "AF_VENDOR34", - "AF_VENDOR35", - "AF_VENDOR36", - "AF_VENDOR37", - "AF_VENDOR38", - "AF_VENDOR39", - "AF_VENDOR40", - "AF_VENDOR41", - "AF_VENDOR42", - "AF_VENDOR43", - "AF_VENDOR44", - "AF_VENDOR45", - "AF_VENDOR46", - "AF_VENDOR47", - "AF_WANPIPE", - "AF_X25", - "AI_CANONNAME", - "AI_NUMERICHOST", - "AI_PASSIVE", - "APPLICATION_ERROR", - "ARPHRD_ADAPT", - "ARPHRD_APPLETLK", - "ARPHRD_ARCNET", - "ARPHRD_ASH", - "ARPHRD_ATM", - "ARPHRD_AX25", - "ARPHRD_BIF", - "ARPHRD_CHAOS", - "ARPHRD_CISCO", - "ARPHRD_CSLIP", - "ARPHRD_CSLIP6", - "ARPHRD_DDCMP", - "ARPHRD_DLCI", - "ARPHRD_ECONET", - "ARPHRD_EETHER", - "ARPHRD_ETHER", - "ARPHRD_EUI64", - "ARPHRD_FCAL", - "ARPHRD_FCFABRIC", - "ARPHRD_FCPL", - "ARPHRD_FCPP", - "ARPHRD_FDDI", - "ARPHRD_FRAD", - "ARPHRD_FRELAY", - "ARPHRD_HDLC", - "ARPHRD_HIPPI", - "ARPHRD_HWX25", - "ARPHRD_IEEE1394", - "ARPHRD_IEEE802", - "ARPHRD_IEEE80211", - "ARPHRD_IEEE80211_PRISM", - "ARPHRD_IEEE80211_RADIOTAP", - "ARPHRD_IEEE802154", - "ARPHRD_IEEE802154_PHY", - "ARPHRD_IEEE802_TR", - "ARPHRD_INFINIBAND", - "ARPHRD_IPDDP", - "ARPHRD_IPGRE", - "ARPHRD_IRDA", - "ARPHRD_LAPB", - "ARPHRD_LOCALTLK", - "ARPHRD_LOOPBACK", - "ARPHRD_METRICOM", - "ARPHRD_NETROM", - "ARPHRD_NONE", - "ARPHRD_PIMREG", - "ARPHRD_PPP", - "ARPHRD_PRONET", - "ARPHRD_RAWHDLC", - "ARPHRD_ROSE", - "ARPHRD_RSRVD", - "ARPHRD_SIT", - "ARPHRD_SKIP", - "ARPHRD_SLIP", - "ARPHRD_SLIP6", - "ARPHRD_STRIP", - "ARPHRD_TUNNEL", - "ARPHRD_TUNNEL6", - "ARPHRD_VOID", - "ARPHRD_X25", - "AUTHTYPE_CLIENT", - "AUTHTYPE_SERVER", - "Accept", - "Accept4", - "AcceptEx", - "Access", - "Acct", - "AddrinfoW", - "Adjtime", - "Adjtimex", - "AllThreadsSyscall", - "AllThreadsSyscall6", - "AttachLsf", - "B0", - "B1000000", - "B110", - "B115200", - "B1152000", - "B1200", - "B134", - "B14400", - "B150", - "B1500000", - "B1800", - "B19200", - "B200", - "B2000000", - "B230400", - "B2400", - "B2500000", - "B28800", - "B300", - "B3000000", - "B3500000", - "B38400", - "B4000000", - "B460800", - "B4800", - "B50", - "B500000", - "B57600", - "B576000", - "B600", - "B7200", - "B75", - "B76800", - "B921600", - "B9600", - "BASE_PROTOCOL", - "BIOCFEEDBACK", - "BIOCFLUSH", - "BIOCGBLEN", - "BIOCGDIRECTION", - "BIOCGDIRFILT", - "BIOCGDLT", - "BIOCGDLTLIST", - "BIOCGETBUFMODE", - "BIOCGETIF", - "BIOCGETZMAX", - "BIOCGFEEDBACK", - "BIOCGFILDROP", - "BIOCGHDRCMPLT", - "BIOCGRSIG", - "BIOCGRTIMEOUT", - "BIOCGSEESENT", - "BIOCGSTATS", - "BIOCGSTATSOLD", - "BIOCGTSTAMP", - "BIOCIMMEDIATE", - "BIOCLOCK", - "BIOCPROMISC", - "BIOCROTZBUF", - "BIOCSBLEN", - "BIOCSDIRECTION", - "BIOCSDIRFILT", - "BIOCSDLT", - "BIOCSETBUFMODE", - "BIOCSETF", - "BIOCSETFNR", - "BIOCSETIF", - "BIOCSETWF", - "BIOCSETZBUF", - "BIOCSFEEDBACK", - "BIOCSFILDROP", - "BIOCSHDRCMPLT", - "BIOCSRSIG", - "BIOCSRTIMEOUT", - "BIOCSSEESENT", - "BIOCSTCPF", - "BIOCSTSTAMP", - "BIOCSUDPF", - "BIOCVERSION", - "BPF_A", - "BPF_ABS", - "BPF_ADD", - "BPF_ALIGNMENT", - "BPF_ALIGNMENT32", - "BPF_ALU", - "BPF_AND", - "BPF_B", - "BPF_BUFMODE_BUFFER", - "BPF_BUFMODE_ZBUF", - "BPF_DFLTBUFSIZE", - "BPF_DIRECTION_IN", - "BPF_DIRECTION_OUT", - "BPF_DIV", - "BPF_H", - "BPF_IMM", - "BPF_IND", - "BPF_JA", - "BPF_JEQ", - "BPF_JGE", - "BPF_JGT", - "BPF_JMP", - "BPF_JSET", - "BPF_K", - "BPF_LD", - "BPF_LDX", - "BPF_LEN", - "BPF_LSH", - "BPF_MAJOR_VERSION", - "BPF_MAXBUFSIZE", - "BPF_MAXINSNS", - "BPF_MEM", - "BPF_MEMWORDS", - "BPF_MINBUFSIZE", - "BPF_MINOR_VERSION", - "BPF_MISC", - "BPF_MSH", - "BPF_MUL", - "BPF_NEG", - "BPF_OR", - "BPF_RELEASE", - "BPF_RET", - "BPF_RSH", - "BPF_ST", - "BPF_STX", - "BPF_SUB", - "BPF_TAX", - "BPF_TXA", - "BPF_T_BINTIME", - "BPF_T_BINTIME_FAST", - "BPF_T_BINTIME_MONOTONIC", - "BPF_T_BINTIME_MONOTONIC_FAST", - "BPF_T_FAST", - "BPF_T_FLAG_MASK", - "BPF_T_FORMAT_MASK", - "BPF_T_MICROTIME", - "BPF_T_MICROTIME_FAST", - "BPF_T_MICROTIME_MONOTONIC", - "BPF_T_MICROTIME_MONOTONIC_FAST", - "BPF_T_MONOTONIC", - "BPF_T_MONOTONIC_FAST", - "BPF_T_NANOTIME", - "BPF_T_NANOTIME_FAST", - "BPF_T_NANOTIME_MONOTONIC", - "BPF_T_NANOTIME_MONOTONIC_FAST", - "BPF_T_NONE", - "BPF_T_NORMAL", - "BPF_W", - "BPF_X", - "BRKINT", - "Bind", - "BindToDevice", - "BpfBuflen", - "BpfDatalink", - "BpfHdr", - "BpfHeadercmpl", - "BpfInsn", - "BpfInterface", - "BpfJump", - "BpfProgram", - "BpfStat", - "BpfStats", - "BpfStmt", - "BpfTimeout", - "BpfTimeval", - "BpfVersion", - "BpfZbuf", - "BpfZbufHeader", - "ByHandleFileInformation", - "BytePtrFromString", - "ByteSliceFromString", - "CCR0_FLUSH", - "CERT_CHAIN_POLICY_AUTHENTICODE", - "CERT_CHAIN_POLICY_AUTHENTICODE_TS", - "CERT_CHAIN_POLICY_BASE", - "CERT_CHAIN_POLICY_BASIC_CONSTRAINTS", - "CERT_CHAIN_POLICY_EV", - "CERT_CHAIN_POLICY_MICROSOFT_ROOT", - "CERT_CHAIN_POLICY_NT_AUTH", - "CERT_CHAIN_POLICY_SSL", - "CERT_E_CN_NO_MATCH", - "CERT_E_EXPIRED", - "CERT_E_PURPOSE", - "CERT_E_ROLE", - "CERT_E_UNTRUSTEDROOT", - "CERT_STORE_ADD_ALWAYS", - "CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG", - "CERT_STORE_PROV_MEMORY", - "CERT_TRUST_HAS_EXCLUDED_NAME_CONSTRAINT", - "CERT_TRUST_HAS_NOT_DEFINED_NAME_CONSTRAINT", - "CERT_TRUST_HAS_NOT_PERMITTED_NAME_CONSTRAINT", - "CERT_TRUST_HAS_NOT_SUPPORTED_CRITICAL_EXT", - "CERT_TRUST_HAS_NOT_SUPPORTED_NAME_CONSTRAINT", - "CERT_TRUST_INVALID_BASIC_CONSTRAINTS", - "CERT_TRUST_INVALID_EXTENSION", - "CERT_TRUST_INVALID_NAME_CONSTRAINTS", - "CERT_TRUST_INVALID_POLICY_CONSTRAINTS", - "CERT_TRUST_IS_CYCLIC", - "CERT_TRUST_IS_EXPLICIT_DISTRUST", - "CERT_TRUST_IS_NOT_SIGNATURE_VALID", - "CERT_TRUST_IS_NOT_TIME_VALID", - "CERT_TRUST_IS_NOT_VALID_FOR_USAGE", - "CERT_TRUST_IS_OFFLINE_REVOCATION", - "CERT_TRUST_IS_REVOKED", - "CERT_TRUST_IS_UNTRUSTED_ROOT", - "CERT_TRUST_NO_ERROR", - "CERT_TRUST_NO_ISSUANCE_CHAIN_POLICY", - "CERT_TRUST_REVOCATION_STATUS_UNKNOWN", - "CFLUSH", - "CLOCAL", - "CLONE_CHILD_CLEARTID", - "CLONE_CHILD_SETTID", - "CLONE_CLEAR_SIGHAND", - "CLONE_CSIGNAL", - "CLONE_DETACHED", - "CLONE_FILES", - "CLONE_FS", - "CLONE_INTO_CGROUP", - "CLONE_IO", - "CLONE_NEWCGROUP", - "CLONE_NEWIPC", - "CLONE_NEWNET", - "CLONE_NEWNS", - "CLONE_NEWPID", - "CLONE_NEWTIME", - "CLONE_NEWUSER", - "CLONE_NEWUTS", - "CLONE_PARENT", - "CLONE_PARENT_SETTID", - "CLONE_PID", - "CLONE_PIDFD", - "CLONE_PTRACE", - "CLONE_SETTLS", - "CLONE_SIGHAND", - "CLONE_SYSVSEM", - "CLONE_THREAD", - "CLONE_UNTRACED", - "CLONE_VFORK", - "CLONE_VM", - "CPUID_CFLUSH", - "CREAD", - "CREATE_ALWAYS", - "CREATE_NEW", - "CREATE_NEW_PROCESS_GROUP", - "CREATE_UNICODE_ENVIRONMENT", - "CRYPT_DEFAULT_CONTAINER_OPTIONAL", - "CRYPT_DELETEKEYSET", - "CRYPT_MACHINE_KEYSET", - "CRYPT_NEWKEYSET", - "CRYPT_SILENT", - "CRYPT_VERIFYCONTEXT", - "CS5", - "CS6", - "CS7", - "CS8", - "CSIZE", - "CSTART", - "CSTATUS", - "CSTOP", - "CSTOPB", - "CSUSP", - "CTL_MAXNAME", - "CTL_NET", - "CTL_QUERY", - "CTRL_BREAK_EVENT", - "CTRL_CLOSE_EVENT", - "CTRL_C_EVENT", - "CTRL_LOGOFF_EVENT", - "CTRL_SHUTDOWN_EVENT", - "CancelIo", - "CancelIoEx", - "CertAddCertificateContextToStore", - "CertChainContext", - "CertChainElement", - "CertChainPara", - "CertChainPolicyPara", - "CertChainPolicyStatus", - "CertCloseStore", - "CertContext", - "CertCreateCertificateContext", - "CertEnhKeyUsage", - "CertEnumCertificatesInStore", - "CertFreeCertificateChain", - "CertFreeCertificateContext", - "CertGetCertificateChain", - "CertInfo", - "CertOpenStore", - "CertOpenSystemStore", - "CertRevocationCrlInfo", - "CertRevocationInfo", - "CertSimpleChain", - "CertTrustListInfo", - "CertTrustStatus", - "CertUsageMatch", - "CertVerifyCertificateChainPolicy", - "Chdir", - "CheckBpfVersion", - "Chflags", - "Chmod", - "Chown", - "Chroot", - "Clearenv", - "Close", - "CloseHandle", - "CloseOnExec", - "Closesocket", - "CmsgLen", - "CmsgSpace", - "Cmsghdr", - "CommandLineToArgv", - "ComputerName", - "Conn", - "Connect", - "ConnectEx", - "ConvertSidToStringSid", - "ConvertStringSidToSid", - "CopySid", - "Creat", - "CreateDirectory", - "CreateFile", - "CreateFileMapping", - "CreateHardLink", - "CreateIoCompletionPort", - "CreatePipe", - "CreateProcess", - "CreateProcessAsUser", - "CreateSymbolicLink", - "CreateToolhelp32Snapshot", - "Credential", - "CryptAcquireContext", - "CryptGenRandom", - "CryptReleaseContext", - "DIOCBSFLUSH", - "DIOCOSFPFLUSH", - "DLL", - "DLLError", - "DLT_A429", - "DLT_A653_ICM", - "DLT_AIRONET_HEADER", - "DLT_AOS", - "DLT_APPLE_IP_OVER_IEEE1394", - "DLT_ARCNET", - "DLT_ARCNET_LINUX", - "DLT_ATM_CLIP", - "DLT_ATM_RFC1483", - "DLT_AURORA", - "DLT_AX25", - "DLT_AX25_KISS", - "DLT_BACNET_MS_TP", - "DLT_BLUETOOTH_HCI_H4", - "DLT_BLUETOOTH_HCI_H4_WITH_PHDR", - "DLT_CAN20B", - "DLT_CAN_SOCKETCAN", - "DLT_CHAOS", - "DLT_CHDLC", - "DLT_CISCO_IOS", - "DLT_C_HDLC", - "DLT_C_HDLC_WITH_DIR", - "DLT_DBUS", - "DLT_DECT", - "DLT_DOCSIS", - "DLT_DVB_CI", - "DLT_ECONET", - "DLT_EN10MB", - "DLT_EN3MB", - "DLT_ENC", - "DLT_ERF", - "DLT_ERF_ETH", - "DLT_ERF_POS", - "DLT_FC_2", - "DLT_FC_2_WITH_FRAME_DELIMS", - "DLT_FDDI", - "DLT_FLEXRAY", - "DLT_FRELAY", - "DLT_FRELAY_WITH_DIR", - "DLT_GCOM_SERIAL", - "DLT_GCOM_T1E1", - "DLT_GPF_F", - "DLT_GPF_T", - "DLT_GPRS_LLC", - "DLT_GSMTAP_ABIS", - "DLT_GSMTAP_UM", - "DLT_HDLC", - "DLT_HHDLC", - "DLT_HIPPI", - "DLT_IBM_SN", - "DLT_IBM_SP", - "DLT_IEEE802", - "DLT_IEEE802_11", - "DLT_IEEE802_11_RADIO", - "DLT_IEEE802_11_RADIO_AVS", - "DLT_IEEE802_15_4", - "DLT_IEEE802_15_4_LINUX", - "DLT_IEEE802_15_4_NOFCS", - "DLT_IEEE802_15_4_NONASK_PHY", - "DLT_IEEE802_16_MAC_CPS", - "DLT_IEEE802_16_MAC_CPS_RADIO", - "DLT_IPFILTER", - "DLT_IPMB", - "DLT_IPMB_LINUX", - "DLT_IPNET", - "DLT_IPOIB", - "DLT_IPV4", - "DLT_IPV6", - "DLT_IP_OVER_FC", - "DLT_JUNIPER_ATM1", - "DLT_JUNIPER_ATM2", - "DLT_JUNIPER_ATM_CEMIC", - "DLT_JUNIPER_CHDLC", - "DLT_JUNIPER_ES", - "DLT_JUNIPER_ETHER", - "DLT_JUNIPER_FIBRECHANNEL", - "DLT_JUNIPER_FRELAY", - "DLT_JUNIPER_GGSN", - "DLT_JUNIPER_ISM", - "DLT_JUNIPER_MFR", - "DLT_JUNIPER_MLFR", - "DLT_JUNIPER_MLPPP", - "DLT_JUNIPER_MONITOR", - "DLT_JUNIPER_PIC_PEER", - "DLT_JUNIPER_PPP", - "DLT_JUNIPER_PPPOE", - "DLT_JUNIPER_PPPOE_ATM", - "DLT_JUNIPER_SERVICES", - "DLT_JUNIPER_SRX_E2E", - "DLT_JUNIPER_ST", - "DLT_JUNIPER_VP", - "DLT_JUNIPER_VS", - "DLT_LAPB_WITH_DIR", - "DLT_LAPD", - "DLT_LIN", - "DLT_LINUX_EVDEV", - "DLT_LINUX_IRDA", - "DLT_LINUX_LAPD", - "DLT_LINUX_PPP_WITHDIRECTION", - "DLT_LINUX_SLL", - "DLT_LOOP", - "DLT_LTALK", - "DLT_MATCHING_MAX", - "DLT_MATCHING_MIN", - "DLT_MFR", - "DLT_MOST", - "DLT_MPEG_2_TS", - "DLT_MPLS", - "DLT_MTP2", - "DLT_MTP2_WITH_PHDR", - "DLT_MTP3", - "DLT_MUX27010", - "DLT_NETANALYZER", - "DLT_NETANALYZER_TRANSPARENT", - "DLT_NFC_LLCP", - "DLT_NFLOG", - "DLT_NG40", - "DLT_NULL", - "DLT_PCI_EXP", - "DLT_PFLOG", - "DLT_PFSYNC", - "DLT_PPI", - "DLT_PPP", - "DLT_PPP_BSDOS", - "DLT_PPP_ETHER", - "DLT_PPP_PPPD", - "DLT_PPP_SERIAL", - "DLT_PPP_WITH_DIR", - "DLT_PPP_WITH_DIRECTION", - "DLT_PRISM_HEADER", - "DLT_PRONET", - "DLT_RAIF1", - "DLT_RAW", - "DLT_RAWAF_MASK", - "DLT_RIO", - "DLT_SCCP", - "DLT_SITA", - "DLT_SLIP", - "DLT_SLIP_BSDOS", - "DLT_STANAG_5066_D_PDU", - "DLT_SUNATM", - "DLT_SYMANTEC_FIREWALL", - "DLT_TZSP", - "DLT_USB", - "DLT_USB_LINUX", - "DLT_USB_LINUX_MMAPPED", - "DLT_USER0", - "DLT_USER1", - "DLT_USER10", - "DLT_USER11", - "DLT_USER12", - "DLT_USER13", - "DLT_USER14", - "DLT_USER15", - "DLT_USER2", - "DLT_USER3", - "DLT_USER4", - "DLT_USER5", - "DLT_USER6", - "DLT_USER7", - "DLT_USER8", - "DLT_USER9", - "DLT_WIHART", - "DLT_X2E_SERIAL", - "DLT_X2E_XORAYA", - "DNSMXData", - "DNSPTRData", - "DNSRecord", - "DNSSRVData", - "DNSTXTData", - "DNS_INFO_NO_RECORDS", - "DNS_TYPE_A", - "DNS_TYPE_A6", - "DNS_TYPE_AAAA", - "DNS_TYPE_ADDRS", - "DNS_TYPE_AFSDB", - "DNS_TYPE_ALL", - "DNS_TYPE_ANY", - "DNS_TYPE_ATMA", - "DNS_TYPE_AXFR", - "DNS_TYPE_CERT", - "DNS_TYPE_CNAME", - "DNS_TYPE_DHCID", - "DNS_TYPE_DNAME", - "DNS_TYPE_DNSKEY", - "DNS_TYPE_DS", - "DNS_TYPE_EID", - "DNS_TYPE_GID", - "DNS_TYPE_GPOS", - "DNS_TYPE_HINFO", - "DNS_TYPE_ISDN", - "DNS_TYPE_IXFR", - "DNS_TYPE_KEY", - "DNS_TYPE_KX", - "DNS_TYPE_LOC", - "DNS_TYPE_MAILA", - "DNS_TYPE_MAILB", - "DNS_TYPE_MB", - "DNS_TYPE_MD", - "DNS_TYPE_MF", - "DNS_TYPE_MG", - "DNS_TYPE_MINFO", - "DNS_TYPE_MR", - "DNS_TYPE_MX", - "DNS_TYPE_NAPTR", - "DNS_TYPE_NBSTAT", - "DNS_TYPE_NIMLOC", - "DNS_TYPE_NS", - "DNS_TYPE_NSAP", - "DNS_TYPE_NSAPPTR", - "DNS_TYPE_NSEC", - "DNS_TYPE_NULL", - "DNS_TYPE_NXT", - "DNS_TYPE_OPT", - "DNS_TYPE_PTR", - "DNS_TYPE_PX", - "DNS_TYPE_RP", - "DNS_TYPE_RRSIG", - "DNS_TYPE_RT", - "DNS_TYPE_SIG", - "DNS_TYPE_SINK", - "DNS_TYPE_SOA", - "DNS_TYPE_SRV", - "DNS_TYPE_TEXT", - "DNS_TYPE_TKEY", - "DNS_TYPE_TSIG", - "DNS_TYPE_UID", - "DNS_TYPE_UINFO", - "DNS_TYPE_UNSPEC", - "DNS_TYPE_WINS", - "DNS_TYPE_WINSR", - "DNS_TYPE_WKS", - "DNS_TYPE_X25", - "DT_BLK", - "DT_CHR", - "DT_DIR", - "DT_FIFO", - "DT_LNK", - "DT_REG", - "DT_SOCK", - "DT_UNKNOWN", - "DT_WHT", - "DUPLICATE_CLOSE_SOURCE", - "DUPLICATE_SAME_ACCESS", - "DeleteFile", - "DetachLsf", - "DeviceIoControl", - "Dirent", - "DnsNameCompare", - "DnsQuery", - "DnsRecordListFree", - "DnsSectionAdditional", - "DnsSectionAnswer", - "DnsSectionAuthority", - "DnsSectionQuestion", - "Dup", - "Dup2", - "Dup3", - "DuplicateHandle", - "E2BIG", - "EACCES", - "EADDRINUSE", - "EADDRNOTAVAIL", - "EADV", - "EAFNOSUPPORT", - "EAGAIN", - "EALREADY", - "EAUTH", - "EBADARCH", - "EBADE", - "EBADEXEC", - "EBADF", - "EBADFD", - "EBADMACHO", - "EBADMSG", - "EBADR", - "EBADRPC", - "EBADRQC", - "EBADSLT", - "EBFONT", - "EBUSY", - "ECANCELED", - "ECAPMODE", - "ECHILD", - "ECHO", - "ECHOCTL", - "ECHOE", - "ECHOK", - "ECHOKE", - "ECHONL", - "ECHOPRT", - "ECHRNG", - "ECOMM", - "ECONNABORTED", - "ECONNREFUSED", - "ECONNRESET", - "EDEADLK", - "EDEADLOCK", - "EDESTADDRREQ", - "EDEVERR", - "EDOM", - "EDOOFUS", - "EDOTDOT", - "EDQUOT", - "EEXIST", - "EFAULT", - "EFBIG", - "EFER_LMA", - "EFER_LME", - "EFER_NXE", - "EFER_SCE", - "EFTYPE", - "EHOSTDOWN", - "EHOSTUNREACH", - "EHWPOISON", - "EIDRM", - "EILSEQ", - "EINPROGRESS", - "EINTR", - "EINVAL", - "EIO", - "EIPSEC", - "EISCONN", - "EISDIR", - "EISNAM", - "EKEYEXPIRED", - "EKEYREJECTED", - "EKEYREVOKED", - "EL2HLT", - "EL2NSYNC", - "EL3HLT", - "EL3RST", - "ELAST", - "ELF_NGREG", - "ELF_PRARGSZ", - "ELIBACC", - "ELIBBAD", - "ELIBEXEC", - "ELIBMAX", - "ELIBSCN", - "ELNRNG", - "ELOOP", - "EMEDIUMTYPE", - "EMFILE", - "EMLINK", - "EMSGSIZE", - "EMT_TAGOVF", - "EMULTIHOP", - "EMUL_ENABLED", - "EMUL_LINUX", - "EMUL_LINUX32", - "EMUL_MAXID", - "EMUL_NATIVE", - "ENAMETOOLONG", - "ENAVAIL", - "ENDRUNDISC", - "ENEEDAUTH", - "ENETDOWN", - "ENETRESET", - "ENETUNREACH", - "ENFILE", - "ENOANO", - "ENOATTR", - "ENOBUFS", - "ENOCSI", - "ENODATA", - "ENODEV", - "ENOENT", - "ENOEXEC", - "ENOKEY", - "ENOLCK", - "ENOLINK", - "ENOMEDIUM", - "ENOMEM", - "ENOMSG", - "ENONET", - "ENOPKG", - "ENOPOLICY", - "ENOPROTOOPT", - "ENOSPC", - "ENOSR", - "ENOSTR", - "ENOSYS", - "ENOTBLK", - "ENOTCAPABLE", - "ENOTCONN", - "ENOTDIR", - "ENOTEMPTY", - "ENOTNAM", - "ENOTRECOVERABLE", - "ENOTSOCK", - "ENOTSUP", - "ENOTTY", - "ENOTUNIQ", - "ENXIO", - "EN_SW_CTL_INF", - "EN_SW_CTL_PREC", - "EN_SW_CTL_ROUND", - "EN_SW_DATACHAIN", - "EN_SW_DENORM", - "EN_SW_INVOP", - "EN_SW_OVERFLOW", - "EN_SW_PRECLOSS", - "EN_SW_UNDERFLOW", - "EN_SW_ZERODIV", - "EOPNOTSUPP", - "EOVERFLOW", - "EOWNERDEAD", - "EPERM", - "EPFNOSUPPORT", - "EPIPE", - "EPOLLERR", - "EPOLLET", - "EPOLLHUP", - "EPOLLIN", - "EPOLLMSG", - "EPOLLONESHOT", - "EPOLLOUT", - "EPOLLPRI", - "EPOLLRDBAND", - "EPOLLRDHUP", - "EPOLLRDNORM", - "EPOLLWRBAND", - "EPOLLWRNORM", - "EPOLL_CLOEXEC", - "EPOLL_CTL_ADD", - "EPOLL_CTL_DEL", - "EPOLL_CTL_MOD", - "EPOLL_NONBLOCK", - "EPROCLIM", - "EPROCUNAVAIL", - "EPROGMISMATCH", - "EPROGUNAVAIL", - "EPROTO", - "EPROTONOSUPPORT", - "EPROTOTYPE", - "EPWROFF", - "EQFULL", - "ERANGE", - "EREMCHG", - "EREMOTE", - "EREMOTEIO", - "ERESTART", - "ERFKILL", - "EROFS", - "ERPCMISMATCH", - "ERROR_ACCESS_DENIED", - "ERROR_ALREADY_EXISTS", - "ERROR_BROKEN_PIPE", - "ERROR_BUFFER_OVERFLOW", - "ERROR_DIR_NOT_EMPTY", - "ERROR_ENVVAR_NOT_FOUND", - "ERROR_FILE_EXISTS", - "ERROR_FILE_NOT_FOUND", - "ERROR_HANDLE_EOF", - "ERROR_INSUFFICIENT_BUFFER", - "ERROR_IO_PENDING", - "ERROR_MOD_NOT_FOUND", - "ERROR_MORE_DATA", - "ERROR_NETNAME_DELETED", - "ERROR_NOT_FOUND", - "ERROR_NO_MORE_FILES", - "ERROR_OPERATION_ABORTED", - "ERROR_PATH_NOT_FOUND", - "ERROR_PRIVILEGE_NOT_HELD", - "ERROR_PROC_NOT_FOUND", - "ESHLIBVERS", - "ESHUTDOWN", - "ESOCKTNOSUPPORT", - "ESPIPE", - "ESRCH", - "ESRMNT", - "ESTALE", - "ESTRPIPE", - "ETHERCAP_JUMBO_MTU", - "ETHERCAP_VLAN_HWTAGGING", - "ETHERCAP_VLAN_MTU", - "ETHERMIN", - "ETHERMTU", - "ETHERMTU_JUMBO", - "ETHERTYPE_8023", - "ETHERTYPE_AARP", - "ETHERTYPE_ACCTON", - "ETHERTYPE_AEONIC", - "ETHERTYPE_ALPHA", - "ETHERTYPE_AMBER", - "ETHERTYPE_AMOEBA", - "ETHERTYPE_AOE", - "ETHERTYPE_APOLLO", - "ETHERTYPE_APOLLODOMAIN", - "ETHERTYPE_APPLETALK", - "ETHERTYPE_APPLITEK", - "ETHERTYPE_ARGONAUT", - "ETHERTYPE_ARP", - "ETHERTYPE_AT", - "ETHERTYPE_ATALK", - "ETHERTYPE_ATOMIC", - "ETHERTYPE_ATT", - "ETHERTYPE_ATTSTANFORD", - "ETHERTYPE_AUTOPHON", - "ETHERTYPE_AXIS", - "ETHERTYPE_BCLOOP", - "ETHERTYPE_BOFL", - "ETHERTYPE_CABLETRON", - "ETHERTYPE_CHAOS", - "ETHERTYPE_COMDESIGN", - "ETHERTYPE_COMPUGRAPHIC", - "ETHERTYPE_COUNTERPOINT", - "ETHERTYPE_CRONUS", - "ETHERTYPE_CRONUSVLN", - "ETHERTYPE_DCA", - "ETHERTYPE_DDE", - "ETHERTYPE_DEBNI", - "ETHERTYPE_DECAM", - "ETHERTYPE_DECCUST", - "ETHERTYPE_DECDIAG", - "ETHERTYPE_DECDNS", - "ETHERTYPE_DECDTS", - "ETHERTYPE_DECEXPER", - "ETHERTYPE_DECLAST", - "ETHERTYPE_DECLTM", - "ETHERTYPE_DECMUMPS", - "ETHERTYPE_DECNETBIOS", - "ETHERTYPE_DELTACON", - "ETHERTYPE_DIDDLE", - "ETHERTYPE_DLOG1", - "ETHERTYPE_DLOG2", - "ETHERTYPE_DN", - "ETHERTYPE_DOGFIGHT", - "ETHERTYPE_DSMD", - "ETHERTYPE_ECMA", - "ETHERTYPE_ENCRYPT", - "ETHERTYPE_ES", - "ETHERTYPE_EXCELAN", - "ETHERTYPE_EXPERDATA", - "ETHERTYPE_FLIP", - "ETHERTYPE_FLOWCONTROL", - "ETHERTYPE_FRARP", - "ETHERTYPE_GENDYN", - "ETHERTYPE_HAYES", - "ETHERTYPE_HIPPI_FP", - "ETHERTYPE_HITACHI", - "ETHERTYPE_HP", - "ETHERTYPE_IEEEPUP", - "ETHERTYPE_IEEEPUPAT", - "ETHERTYPE_IMLBL", - "ETHERTYPE_IMLBLDIAG", - "ETHERTYPE_IP", - "ETHERTYPE_IPAS", - "ETHERTYPE_IPV6", - "ETHERTYPE_IPX", - "ETHERTYPE_IPXNEW", - "ETHERTYPE_KALPANA", - "ETHERTYPE_LANBRIDGE", - "ETHERTYPE_LANPROBE", - "ETHERTYPE_LAT", - "ETHERTYPE_LBACK", - "ETHERTYPE_LITTLE", - "ETHERTYPE_LLDP", - "ETHERTYPE_LOGICRAFT", - "ETHERTYPE_LOOPBACK", - "ETHERTYPE_MATRA", - "ETHERTYPE_MAX", - "ETHERTYPE_MERIT", - "ETHERTYPE_MICP", - "ETHERTYPE_MOPDL", - "ETHERTYPE_MOPRC", - "ETHERTYPE_MOTOROLA", - "ETHERTYPE_MPLS", - "ETHERTYPE_MPLS_MCAST", - "ETHERTYPE_MUMPS", - "ETHERTYPE_NBPCC", - "ETHERTYPE_NBPCLAIM", - "ETHERTYPE_NBPCLREQ", - "ETHERTYPE_NBPCLRSP", - "ETHERTYPE_NBPCREQ", - "ETHERTYPE_NBPCRSP", - "ETHERTYPE_NBPDG", - "ETHERTYPE_NBPDGB", - "ETHERTYPE_NBPDLTE", - "ETHERTYPE_NBPRAR", - "ETHERTYPE_NBPRAS", - "ETHERTYPE_NBPRST", - "ETHERTYPE_NBPSCD", - "ETHERTYPE_NBPVCD", - "ETHERTYPE_NBS", - "ETHERTYPE_NCD", - "ETHERTYPE_NESTAR", - "ETHERTYPE_NETBEUI", - "ETHERTYPE_NOVELL", - "ETHERTYPE_NS", - "ETHERTYPE_NSAT", - "ETHERTYPE_NSCOMPAT", - "ETHERTYPE_NTRAILER", - "ETHERTYPE_OS9", - "ETHERTYPE_OS9NET", - "ETHERTYPE_PACER", - "ETHERTYPE_PAE", - "ETHERTYPE_PCS", - "ETHERTYPE_PLANNING", - "ETHERTYPE_PPP", - "ETHERTYPE_PPPOE", - "ETHERTYPE_PPPOEDISC", - "ETHERTYPE_PRIMENTS", - "ETHERTYPE_PUP", - "ETHERTYPE_PUPAT", - "ETHERTYPE_QINQ", - "ETHERTYPE_RACAL", - "ETHERTYPE_RATIONAL", - "ETHERTYPE_RAWFR", - "ETHERTYPE_RCL", - "ETHERTYPE_RDP", - "ETHERTYPE_RETIX", - "ETHERTYPE_REVARP", - "ETHERTYPE_SCA", - "ETHERTYPE_SECTRA", - "ETHERTYPE_SECUREDATA", - "ETHERTYPE_SGITW", - "ETHERTYPE_SG_BOUNCE", - "ETHERTYPE_SG_DIAG", - "ETHERTYPE_SG_NETGAMES", - "ETHERTYPE_SG_RESV", - "ETHERTYPE_SIMNET", - "ETHERTYPE_SLOW", - "ETHERTYPE_SLOWPROTOCOLS", - "ETHERTYPE_SNA", - "ETHERTYPE_SNMP", - "ETHERTYPE_SONIX", - "ETHERTYPE_SPIDER", - "ETHERTYPE_SPRITE", - "ETHERTYPE_STP", - "ETHERTYPE_TALARIS", - "ETHERTYPE_TALARISMC", - "ETHERTYPE_TCPCOMP", - "ETHERTYPE_TCPSM", - "ETHERTYPE_TEC", - "ETHERTYPE_TIGAN", - "ETHERTYPE_TRAIL", - "ETHERTYPE_TRANSETHER", - "ETHERTYPE_TYMSHARE", - "ETHERTYPE_UBBST", - "ETHERTYPE_UBDEBUG", - "ETHERTYPE_UBDIAGLOOP", - "ETHERTYPE_UBDL", - "ETHERTYPE_UBNIU", - "ETHERTYPE_UBNMC", - "ETHERTYPE_VALID", - "ETHERTYPE_VARIAN", - "ETHERTYPE_VAXELN", - "ETHERTYPE_VEECO", - "ETHERTYPE_VEXP", - "ETHERTYPE_VGLAB", - "ETHERTYPE_VINES", - "ETHERTYPE_VINESECHO", - "ETHERTYPE_VINESLOOP", - "ETHERTYPE_VITAL", - "ETHERTYPE_VLAN", - "ETHERTYPE_VLTLMAN", - "ETHERTYPE_VPROD", - "ETHERTYPE_VURESERVED", - "ETHERTYPE_WATERLOO", - "ETHERTYPE_WELLFLEET", - "ETHERTYPE_X25", - "ETHERTYPE_X75", - "ETHERTYPE_XNSSM", - "ETHERTYPE_XTP", - "ETHER_ADDR_LEN", - "ETHER_ALIGN", - "ETHER_CRC_LEN", - "ETHER_CRC_POLY_BE", - "ETHER_CRC_POLY_LE", - "ETHER_HDR_LEN", - "ETHER_MAX_DIX_LEN", - "ETHER_MAX_LEN", - "ETHER_MAX_LEN_JUMBO", - "ETHER_MIN_LEN", - "ETHER_PPPOE_ENCAP_LEN", - "ETHER_TYPE_LEN", - "ETHER_VLAN_ENCAP_LEN", - "ETH_P_1588", - "ETH_P_8021Q", - "ETH_P_802_2", - "ETH_P_802_3", - "ETH_P_AARP", - "ETH_P_ALL", - "ETH_P_AOE", - "ETH_P_ARCNET", - "ETH_P_ARP", - "ETH_P_ATALK", - "ETH_P_ATMFATE", - "ETH_P_ATMMPOA", - "ETH_P_AX25", - "ETH_P_BPQ", - "ETH_P_CAIF", - "ETH_P_CAN", - "ETH_P_CONTROL", - "ETH_P_CUST", - "ETH_P_DDCMP", - "ETH_P_DEC", - "ETH_P_DIAG", - "ETH_P_DNA_DL", - "ETH_P_DNA_RC", - "ETH_P_DNA_RT", - "ETH_P_DSA", - "ETH_P_ECONET", - "ETH_P_EDSA", - "ETH_P_FCOE", - "ETH_P_FIP", - "ETH_P_HDLC", - "ETH_P_IEEE802154", - "ETH_P_IEEEPUP", - "ETH_P_IEEEPUPAT", - "ETH_P_IP", - "ETH_P_IPV6", - "ETH_P_IPX", - "ETH_P_IRDA", - "ETH_P_LAT", - "ETH_P_LINK_CTL", - "ETH_P_LOCALTALK", - "ETH_P_LOOP", - "ETH_P_MOBITEX", - "ETH_P_MPLS_MC", - "ETH_P_MPLS_UC", - "ETH_P_PAE", - "ETH_P_PAUSE", - "ETH_P_PHONET", - "ETH_P_PPPTALK", - "ETH_P_PPP_DISC", - "ETH_P_PPP_MP", - "ETH_P_PPP_SES", - "ETH_P_PUP", - "ETH_P_PUPAT", - "ETH_P_RARP", - "ETH_P_SCA", - "ETH_P_SLOW", - "ETH_P_SNAP", - "ETH_P_TEB", - "ETH_P_TIPC", - "ETH_P_TRAILER", - "ETH_P_TR_802_2", - "ETH_P_WAN_PPP", - "ETH_P_WCCP", - "ETH_P_X25", - "ETIME", - "ETIMEDOUT", - "ETOOMANYREFS", - "ETXTBSY", - "EUCLEAN", - "EUNATCH", - "EUSERS", - "EVFILT_AIO", - "EVFILT_FS", - "EVFILT_LIO", - "EVFILT_MACHPORT", - "EVFILT_PROC", - "EVFILT_READ", - "EVFILT_SIGNAL", - "EVFILT_SYSCOUNT", - "EVFILT_THREADMARKER", - "EVFILT_TIMER", - "EVFILT_USER", - "EVFILT_VM", - "EVFILT_VNODE", - "EVFILT_WRITE", - "EV_ADD", - "EV_CLEAR", - "EV_DELETE", - "EV_DISABLE", - "EV_DISPATCH", - "EV_DROP", - "EV_ENABLE", - "EV_EOF", - "EV_ERROR", - "EV_FLAG0", - "EV_FLAG1", - "EV_ONESHOT", - "EV_OOBAND", - "EV_POLL", - "EV_RECEIPT", - "EV_SYSFLAGS", - "EWINDOWS", - "EWOULDBLOCK", - "EXDEV", - "EXFULL", - "EXTA", - "EXTB", - "EXTPROC", - "Environ", - "EpollCreate", - "EpollCreate1", - "EpollCtl", - "EpollEvent", - "EpollWait", - "Errno", - "EscapeArg", - "Exchangedata", - "Exec", - "Exit", - "ExitProcess", - "FD_CLOEXEC", - "FD_SETSIZE", - "FILE_ACTION_ADDED", - "FILE_ACTION_MODIFIED", - "FILE_ACTION_REMOVED", - "FILE_ACTION_RENAMED_NEW_NAME", - "FILE_ACTION_RENAMED_OLD_NAME", - "FILE_APPEND_DATA", - "FILE_ATTRIBUTE_ARCHIVE", - "FILE_ATTRIBUTE_DIRECTORY", - "FILE_ATTRIBUTE_HIDDEN", - "FILE_ATTRIBUTE_NORMAL", - "FILE_ATTRIBUTE_READONLY", - "FILE_ATTRIBUTE_REPARSE_POINT", - "FILE_ATTRIBUTE_SYSTEM", - "FILE_BEGIN", - "FILE_CURRENT", - "FILE_END", - "FILE_FLAG_BACKUP_SEMANTICS", - "FILE_FLAG_OPEN_REPARSE_POINT", - "FILE_FLAG_OVERLAPPED", - "FILE_LIST_DIRECTORY", - "FILE_MAP_COPY", - "FILE_MAP_EXECUTE", - "FILE_MAP_READ", - "FILE_MAP_WRITE", - "FILE_NOTIFY_CHANGE_ATTRIBUTES", - "FILE_NOTIFY_CHANGE_CREATION", - "FILE_NOTIFY_CHANGE_DIR_NAME", - "FILE_NOTIFY_CHANGE_FILE_NAME", - "FILE_NOTIFY_CHANGE_LAST_ACCESS", - "FILE_NOTIFY_CHANGE_LAST_WRITE", - "FILE_NOTIFY_CHANGE_SIZE", - "FILE_SHARE_DELETE", - "FILE_SHARE_READ", - "FILE_SHARE_WRITE", - "FILE_SKIP_COMPLETION_PORT_ON_SUCCESS", - "FILE_SKIP_SET_EVENT_ON_HANDLE", - "FILE_TYPE_CHAR", - "FILE_TYPE_DISK", - "FILE_TYPE_PIPE", - "FILE_TYPE_REMOTE", - "FILE_TYPE_UNKNOWN", - "FILE_WRITE_ATTRIBUTES", - "FLUSHO", - "FORMAT_MESSAGE_ALLOCATE_BUFFER", - "FORMAT_MESSAGE_ARGUMENT_ARRAY", - "FORMAT_MESSAGE_FROM_HMODULE", - "FORMAT_MESSAGE_FROM_STRING", - "FORMAT_MESSAGE_FROM_SYSTEM", - "FORMAT_MESSAGE_IGNORE_INSERTS", - "FORMAT_MESSAGE_MAX_WIDTH_MASK", - "FSCTL_GET_REPARSE_POINT", - "F_ADDFILESIGS", - "F_ADDSIGS", - "F_ALLOCATEALL", - "F_ALLOCATECONTIG", - "F_CANCEL", - "F_CHKCLEAN", - "F_CLOSEM", - "F_DUP2FD", - "F_DUP2FD_CLOEXEC", - "F_DUPFD", - "F_DUPFD_CLOEXEC", - "F_EXLCK", - "F_FINDSIGS", - "F_FLUSH_DATA", - "F_FREEZE_FS", - "F_FSCTL", - "F_FSDIRMASK", - "F_FSIN", - "F_FSINOUT", - "F_FSOUT", - "F_FSPRIV", - "F_FSVOID", - "F_FULLFSYNC", - "F_GETCODEDIR", - "F_GETFD", - "F_GETFL", - "F_GETLEASE", - "F_GETLK", - "F_GETLK64", - "F_GETLKPID", - "F_GETNOSIGPIPE", - "F_GETOWN", - "F_GETOWN_EX", - "F_GETPATH", - "F_GETPATH_MTMINFO", - "F_GETPIPE_SZ", - "F_GETPROTECTIONCLASS", - "F_GETPROTECTIONLEVEL", - "F_GETSIG", - "F_GLOBAL_NOCACHE", - "F_LOCK", - "F_LOG2PHYS", - "F_LOG2PHYS_EXT", - "F_MARKDEPENDENCY", - "F_MAXFD", - "F_NOCACHE", - "F_NODIRECT", - "F_NOTIFY", - "F_OGETLK", - "F_OK", - "F_OSETLK", - "F_OSETLKW", - "F_PARAM_MASK", - "F_PARAM_MAX", - "F_PATHPKG_CHECK", - "F_PEOFPOSMODE", - "F_PREALLOCATE", - "F_RDADVISE", - "F_RDAHEAD", - "F_RDLCK", - "F_READAHEAD", - "F_READBOOTSTRAP", - "F_SETBACKINGSTORE", - "F_SETFD", - "F_SETFL", - "F_SETLEASE", - "F_SETLK", - "F_SETLK64", - "F_SETLKW", - "F_SETLKW64", - "F_SETLKWTIMEOUT", - "F_SETLK_REMOTE", - "F_SETNOSIGPIPE", - "F_SETOWN", - "F_SETOWN_EX", - "F_SETPIPE_SZ", - "F_SETPROTECTIONCLASS", - "F_SETSIG", - "F_SETSIZE", - "F_SHLCK", - "F_SINGLE_WRITER", - "F_TEST", - "F_THAW_FS", - "F_TLOCK", - "F_TRANSCODEKEY", - "F_ULOCK", - "F_UNLCK", - "F_UNLCKSYS", - "F_VOLPOSMODE", - "F_WRITEBOOTSTRAP", - "F_WRLCK", - "Faccessat", - "Fallocate", - "Fbootstraptransfer_t", - "Fchdir", - "Fchflags", - "Fchmod", - "Fchmodat", - "Fchown", - "Fchownat", - "FcntlFlock", - "FdSet", - "Fdatasync", - "FileNotifyInformation", - "Filetime", - "FindClose", - "FindFirstFile", - "FindNextFile", - "Flock", - "Flock_t", - "FlushBpf", - "FlushFileBuffers", - "FlushViewOfFile", - "ForkExec", - "ForkLock", - "FormatMessage", - "Fpathconf", - "FreeAddrInfoW", - "FreeEnvironmentStrings", - "FreeLibrary", - "Fsid", - "Fstat", - "Fstatat", - "Fstatfs", - "Fstore_t", - "Fsync", - "Ftruncate", - "FullPath", - "Futimes", - "Futimesat", - "GENERIC_ALL", - "GENERIC_EXECUTE", - "GENERIC_READ", - "GENERIC_WRITE", - "GUID", - "GetAcceptExSockaddrs", - "GetAdaptersInfo", - "GetAddrInfoW", - "GetCommandLine", - "GetComputerName", - "GetConsoleMode", - "GetCurrentDirectory", - "GetCurrentProcess", - "GetEnvironmentStrings", - "GetEnvironmentVariable", - "GetExitCodeProcess", - "GetFileAttributes", - "GetFileAttributesEx", - "GetFileExInfoStandard", - "GetFileExMaxInfoLevel", - "GetFileInformationByHandle", - "GetFileType", - "GetFullPathName", - "GetHostByName", - "GetIfEntry", - "GetLastError", - "GetLengthSid", - "GetLongPathName", - "GetProcAddress", - "GetProcessTimes", - "GetProtoByName", - "GetQueuedCompletionStatus", - "GetServByName", - "GetShortPathName", - "GetStartupInfo", - "GetStdHandle", - "GetSystemTimeAsFileTime", - "GetTempPath", - "GetTimeZoneInformation", - "GetTokenInformation", - "GetUserNameEx", - "GetUserProfileDirectory", - "GetVersion", - "Getcwd", - "Getdents", - "Getdirentries", - "Getdtablesize", - "Getegid", - "Getenv", - "Geteuid", - "Getfsstat", - "Getgid", - "Getgroups", - "Getpagesize", - "Getpeername", - "Getpgid", - "Getpgrp", - "Getpid", - "Getppid", - "Getpriority", - "Getrlimit", - "Getrusage", - "Getsid", - "Getsockname", - "Getsockopt", - "GetsockoptByte", - "GetsockoptICMPv6Filter", - "GetsockoptIPMreq", - "GetsockoptIPMreqn", - "GetsockoptIPv6MTUInfo", - "GetsockoptIPv6Mreq", - "GetsockoptInet4Addr", - "GetsockoptInt", - "GetsockoptUcred", - "Gettid", - "Gettimeofday", - "Getuid", - "Getwd", - "Getxattr", - "HANDLE_FLAG_INHERIT", - "HKEY_CLASSES_ROOT", - "HKEY_CURRENT_CONFIG", - "HKEY_CURRENT_USER", - "HKEY_DYN_DATA", - "HKEY_LOCAL_MACHINE", - "HKEY_PERFORMANCE_DATA", - "HKEY_USERS", - "HUPCL", - "Handle", - "Hostent", - "ICANON", - "ICMP6_FILTER", - "ICMPV6_FILTER", - "ICMPv6Filter", - "ICRNL", - "IEXTEN", - "IFAN_ARRIVAL", - "IFAN_DEPARTURE", - "IFA_ADDRESS", - "IFA_ANYCAST", - "IFA_BROADCAST", - "IFA_CACHEINFO", - "IFA_F_DADFAILED", - "IFA_F_DEPRECATED", - "IFA_F_HOMEADDRESS", - "IFA_F_NODAD", - "IFA_F_OPTIMISTIC", - "IFA_F_PERMANENT", - "IFA_F_SECONDARY", - "IFA_F_TEMPORARY", - "IFA_F_TENTATIVE", - "IFA_LABEL", - "IFA_LOCAL", - "IFA_MAX", - "IFA_MULTICAST", - "IFA_ROUTE", - "IFA_UNSPEC", - "IFF_ALLMULTI", - "IFF_ALTPHYS", - "IFF_AUTOMEDIA", - "IFF_BROADCAST", - "IFF_CANTCHANGE", - "IFF_CANTCONFIG", - "IFF_DEBUG", - "IFF_DRV_OACTIVE", - "IFF_DRV_RUNNING", - "IFF_DYING", - "IFF_DYNAMIC", - "IFF_LINK0", - "IFF_LINK1", - "IFF_LINK2", - "IFF_LOOPBACK", - "IFF_MASTER", - "IFF_MONITOR", - "IFF_MULTICAST", - "IFF_NOARP", - "IFF_NOTRAILERS", - "IFF_NO_PI", - "IFF_OACTIVE", - "IFF_ONE_QUEUE", - "IFF_POINTOPOINT", - "IFF_POINTTOPOINT", - "IFF_PORTSEL", - "IFF_PPROMISC", - "IFF_PROMISC", - "IFF_RENAMING", - "IFF_RUNNING", - "IFF_SIMPLEX", - "IFF_SLAVE", - "IFF_SMART", - "IFF_STATICARP", - "IFF_TAP", - "IFF_TUN", - "IFF_TUN_EXCL", - "IFF_UP", - "IFF_VNET_HDR", - "IFLA_ADDRESS", - "IFLA_BROADCAST", - "IFLA_COST", - "IFLA_IFALIAS", - "IFLA_IFNAME", - "IFLA_LINK", - "IFLA_LINKINFO", - "IFLA_LINKMODE", - "IFLA_MAP", - "IFLA_MASTER", - "IFLA_MAX", - "IFLA_MTU", - "IFLA_NET_NS_PID", - "IFLA_OPERSTATE", - "IFLA_PRIORITY", - "IFLA_PROTINFO", - "IFLA_QDISC", - "IFLA_STATS", - "IFLA_TXQLEN", - "IFLA_UNSPEC", - "IFLA_WEIGHT", - "IFLA_WIRELESS", - "IFNAMSIZ", - "IFT_1822", - "IFT_A12MPPSWITCH", - "IFT_AAL2", - "IFT_AAL5", - "IFT_ADSL", - "IFT_AFLANE8023", - "IFT_AFLANE8025", - "IFT_ARAP", - "IFT_ARCNET", - "IFT_ARCNETPLUS", - "IFT_ASYNC", - "IFT_ATM", - "IFT_ATMDXI", - "IFT_ATMFUNI", - "IFT_ATMIMA", - "IFT_ATMLOGICAL", - "IFT_ATMRADIO", - "IFT_ATMSUBINTERFACE", - "IFT_ATMVCIENDPT", - "IFT_ATMVIRTUAL", - "IFT_BGPPOLICYACCOUNTING", - "IFT_BLUETOOTH", - "IFT_BRIDGE", - "IFT_BSC", - "IFT_CARP", - "IFT_CCTEMUL", - "IFT_CELLULAR", - "IFT_CEPT", - "IFT_CES", - "IFT_CHANNEL", - "IFT_CNR", - "IFT_COFFEE", - "IFT_COMPOSITELINK", - "IFT_DCN", - "IFT_DIGITALPOWERLINE", - "IFT_DIGITALWRAPPEROVERHEADCHANNEL", - "IFT_DLSW", - "IFT_DOCSCABLEDOWNSTREAM", - "IFT_DOCSCABLEMACLAYER", - "IFT_DOCSCABLEUPSTREAM", - "IFT_DOCSCABLEUPSTREAMCHANNEL", - "IFT_DS0", - "IFT_DS0BUNDLE", - "IFT_DS1FDL", - "IFT_DS3", - "IFT_DTM", - "IFT_DUMMY", - "IFT_DVBASILN", - "IFT_DVBASIOUT", - "IFT_DVBRCCDOWNSTREAM", - "IFT_DVBRCCMACLAYER", - "IFT_DVBRCCUPSTREAM", - "IFT_ECONET", - "IFT_ENC", - "IFT_EON", - "IFT_EPLRS", - "IFT_ESCON", - "IFT_ETHER", - "IFT_FAITH", - "IFT_FAST", - "IFT_FASTETHER", - "IFT_FASTETHERFX", - "IFT_FDDI", - "IFT_FIBRECHANNEL", - "IFT_FRAMERELAYINTERCONNECT", - "IFT_FRAMERELAYMPI", - "IFT_FRDLCIENDPT", - "IFT_FRELAY", - "IFT_FRELAYDCE", - "IFT_FRF16MFRBUNDLE", - "IFT_FRFORWARD", - "IFT_G703AT2MB", - "IFT_G703AT64K", - "IFT_GIF", - "IFT_GIGABITETHERNET", - "IFT_GR303IDT", - "IFT_GR303RDT", - "IFT_H323GATEKEEPER", - "IFT_H323PROXY", - "IFT_HDH1822", - "IFT_HDLC", - "IFT_HDSL2", - "IFT_HIPERLAN2", - "IFT_HIPPI", - "IFT_HIPPIINTERFACE", - "IFT_HOSTPAD", - "IFT_HSSI", - "IFT_HY", - "IFT_IBM370PARCHAN", - "IFT_IDSL", - "IFT_IEEE1394", - "IFT_IEEE80211", - "IFT_IEEE80212", - "IFT_IEEE8023ADLAG", - "IFT_IFGSN", - "IFT_IMT", - "IFT_INFINIBAND", - "IFT_INTERLEAVE", - "IFT_IP", - "IFT_IPFORWARD", - "IFT_IPOVERATM", - "IFT_IPOVERCDLC", - "IFT_IPOVERCLAW", - "IFT_IPSWITCH", - "IFT_IPXIP", - "IFT_ISDN", - "IFT_ISDNBASIC", - "IFT_ISDNPRIMARY", - "IFT_ISDNS", - "IFT_ISDNU", - "IFT_ISO88022LLC", - "IFT_ISO88023", - "IFT_ISO88024", - "IFT_ISO88025", - "IFT_ISO88025CRFPINT", - "IFT_ISO88025DTR", - "IFT_ISO88025FIBER", - "IFT_ISO88026", - "IFT_ISUP", - "IFT_L2VLAN", - "IFT_L3IPVLAN", - "IFT_L3IPXVLAN", - "IFT_LAPB", - "IFT_LAPD", - "IFT_LAPF", - "IFT_LINEGROUP", - "IFT_LOCALTALK", - "IFT_LOOP", - "IFT_MEDIAMAILOVERIP", - "IFT_MFSIGLINK", - "IFT_MIOX25", - "IFT_MODEM", - "IFT_MPC", - "IFT_MPLS", - "IFT_MPLSTUNNEL", - "IFT_MSDSL", - "IFT_MVL", - "IFT_MYRINET", - "IFT_NFAS", - "IFT_NSIP", - "IFT_OPTICALCHANNEL", - "IFT_OPTICALTRANSPORT", - "IFT_OTHER", - "IFT_P10", - "IFT_P80", - "IFT_PARA", - "IFT_PDP", - "IFT_PFLOG", - "IFT_PFLOW", - "IFT_PFSYNC", - "IFT_PLC", - "IFT_PON155", - "IFT_PON622", - "IFT_POS", - "IFT_PPP", - "IFT_PPPMULTILINKBUNDLE", - "IFT_PROPATM", - "IFT_PROPBWAP2MP", - "IFT_PROPCNLS", - "IFT_PROPDOCSWIRELESSDOWNSTREAM", - "IFT_PROPDOCSWIRELESSMACLAYER", - "IFT_PROPDOCSWIRELESSUPSTREAM", - "IFT_PROPMUX", - "IFT_PROPVIRTUAL", - "IFT_PROPWIRELESSP2P", - "IFT_PTPSERIAL", - "IFT_PVC", - "IFT_Q2931", - "IFT_QLLC", - "IFT_RADIOMAC", - "IFT_RADSL", - "IFT_REACHDSL", - "IFT_RFC1483", - "IFT_RS232", - "IFT_RSRB", - "IFT_SDLC", - "IFT_SDSL", - "IFT_SHDSL", - "IFT_SIP", - "IFT_SIPSIG", - "IFT_SIPTG", - "IFT_SLIP", - "IFT_SMDSDXI", - "IFT_SMDSICIP", - "IFT_SONET", - "IFT_SONETOVERHEADCHANNEL", - "IFT_SONETPATH", - "IFT_SONETVT", - "IFT_SRP", - "IFT_SS7SIGLINK", - "IFT_STACKTOSTACK", - "IFT_STARLAN", - "IFT_STF", - "IFT_T1", - "IFT_TDLC", - "IFT_TELINK", - "IFT_TERMPAD", - "IFT_TR008", - "IFT_TRANSPHDLC", - "IFT_TUNNEL", - "IFT_ULTRA", - "IFT_USB", - "IFT_V11", - "IFT_V35", - "IFT_V36", - "IFT_V37", - "IFT_VDSL", - "IFT_VIRTUALIPADDRESS", - "IFT_VIRTUALTG", - "IFT_VOICEDID", - "IFT_VOICEEM", - "IFT_VOICEEMFGD", - "IFT_VOICEENCAP", - "IFT_VOICEFGDEANA", - "IFT_VOICEFXO", - "IFT_VOICEFXS", - "IFT_VOICEOVERATM", - "IFT_VOICEOVERCABLE", - "IFT_VOICEOVERFRAMERELAY", - "IFT_VOICEOVERIP", - "IFT_X213", - "IFT_X25", - "IFT_X25DDN", - "IFT_X25HUNTGROUP", - "IFT_X25MLP", - "IFT_X25PLE", - "IFT_XETHER", - "IGNBRK", - "IGNCR", - "IGNORE", - "IGNPAR", - "IMAXBEL", - "INFINITE", - "INLCR", - "INPCK", - "INVALID_FILE_ATTRIBUTES", - "IN_ACCESS", - "IN_ALL_EVENTS", - "IN_ATTRIB", - "IN_CLASSA_HOST", - "IN_CLASSA_MAX", - "IN_CLASSA_NET", - "IN_CLASSA_NSHIFT", - "IN_CLASSB_HOST", - "IN_CLASSB_MAX", - "IN_CLASSB_NET", - "IN_CLASSB_NSHIFT", - "IN_CLASSC_HOST", - "IN_CLASSC_NET", - "IN_CLASSC_NSHIFT", - "IN_CLASSD_HOST", - "IN_CLASSD_NET", - "IN_CLASSD_NSHIFT", - "IN_CLOEXEC", - "IN_CLOSE", - "IN_CLOSE_NOWRITE", - "IN_CLOSE_WRITE", - "IN_CREATE", - "IN_DELETE", - "IN_DELETE_SELF", - "IN_DONT_FOLLOW", - "IN_EXCL_UNLINK", - "IN_IGNORED", - "IN_ISDIR", - "IN_LINKLOCALNETNUM", - "IN_LOOPBACKNET", - "IN_MASK_ADD", - "IN_MODIFY", - "IN_MOVE", - "IN_MOVED_FROM", - "IN_MOVED_TO", - "IN_MOVE_SELF", - "IN_NONBLOCK", - "IN_ONESHOT", - "IN_ONLYDIR", - "IN_OPEN", - "IN_Q_OVERFLOW", - "IN_RFC3021_HOST", - "IN_RFC3021_MASK", - "IN_RFC3021_NET", - "IN_RFC3021_NSHIFT", - "IN_UNMOUNT", - "IOC_IN", - "IOC_INOUT", - "IOC_OUT", - "IOC_VENDOR", - "IOC_WS2", - "IO_REPARSE_TAG_SYMLINK", - "IPMreq", - "IPMreqn", - "IPPROTO_3PC", - "IPPROTO_ADFS", - "IPPROTO_AH", - "IPPROTO_AHIP", - "IPPROTO_APES", - "IPPROTO_ARGUS", - "IPPROTO_AX25", - "IPPROTO_BHA", - "IPPROTO_BLT", - "IPPROTO_BRSATMON", - "IPPROTO_CARP", - "IPPROTO_CFTP", - "IPPROTO_CHAOS", - "IPPROTO_CMTP", - "IPPROTO_COMP", - "IPPROTO_CPHB", - "IPPROTO_CPNX", - "IPPROTO_DCCP", - "IPPROTO_DDP", - "IPPROTO_DGP", - "IPPROTO_DIVERT", - "IPPROTO_DIVERT_INIT", - "IPPROTO_DIVERT_RESP", - "IPPROTO_DONE", - "IPPROTO_DSTOPTS", - "IPPROTO_EGP", - "IPPROTO_EMCON", - "IPPROTO_ENCAP", - "IPPROTO_EON", - "IPPROTO_ESP", - "IPPROTO_ETHERIP", - "IPPROTO_FRAGMENT", - "IPPROTO_GGP", - "IPPROTO_GMTP", - "IPPROTO_GRE", - "IPPROTO_HELLO", - "IPPROTO_HMP", - "IPPROTO_HOPOPTS", - "IPPROTO_ICMP", - "IPPROTO_ICMPV6", - "IPPROTO_IDP", - "IPPROTO_IDPR", - "IPPROTO_IDRP", - "IPPROTO_IGMP", - "IPPROTO_IGP", - "IPPROTO_IGRP", - "IPPROTO_IL", - "IPPROTO_INLSP", - "IPPROTO_INP", - "IPPROTO_IP", - "IPPROTO_IPCOMP", - "IPPROTO_IPCV", - "IPPROTO_IPEIP", - "IPPROTO_IPIP", - "IPPROTO_IPPC", - "IPPROTO_IPV4", - "IPPROTO_IPV6", - "IPPROTO_IPV6_ICMP", - "IPPROTO_IRTP", - "IPPROTO_KRYPTOLAN", - "IPPROTO_LARP", - "IPPROTO_LEAF1", - "IPPROTO_LEAF2", - "IPPROTO_MAX", - "IPPROTO_MAXID", - "IPPROTO_MEAS", - "IPPROTO_MH", - "IPPROTO_MHRP", - "IPPROTO_MICP", - "IPPROTO_MOBILE", - "IPPROTO_MPLS", - "IPPROTO_MTP", - "IPPROTO_MUX", - "IPPROTO_ND", - "IPPROTO_NHRP", - "IPPROTO_NONE", - "IPPROTO_NSP", - "IPPROTO_NVPII", - "IPPROTO_OLD_DIVERT", - "IPPROTO_OSPFIGP", - "IPPROTO_PFSYNC", - "IPPROTO_PGM", - "IPPROTO_PIGP", - "IPPROTO_PIM", - "IPPROTO_PRM", - "IPPROTO_PUP", - "IPPROTO_PVP", - "IPPROTO_RAW", - "IPPROTO_RCCMON", - "IPPROTO_RDP", - "IPPROTO_ROUTING", - "IPPROTO_RSVP", - "IPPROTO_RVD", - "IPPROTO_SATEXPAK", - "IPPROTO_SATMON", - "IPPROTO_SCCSP", - "IPPROTO_SCTP", - "IPPROTO_SDRP", - "IPPROTO_SEND", - "IPPROTO_SEP", - "IPPROTO_SKIP", - "IPPROTO_SPACER", - "IPPROTO_SRPC", - "IPPROTO_ST", - "IPPROTO_SVMTP", - "IPPROTO_SWIPE", - "IPPROTO_TCF", - "IPPROTO_TCP", - "IPPROTO_TLSP", - "IPPROTO_TP", - "IPPROTO_TPXX", - "IPPROTO_TRUNK1", - "IPPROTO_TRUNK2", - "IPPROTO_TTP", - "IPPROTO_UDP", - "IPPROTO_UDPLITE", - "IPPROTO_VINES", - "IPPROTO_VISA", - "IPPROTO_VMTP", - "IPPROTO_VRRP", - "IPPROTO_WBEXPAK", - "IPPROTO_WBMON", - "IPPROTO_WSN", - "IPPROTO_XNET", - "IPPROTO_XTP", - "IPV6_2292DSTOPTS", - "IPV6_2292HOPLIMIT", - "IPV6_2292HOPOPTS", - "IPV6_2292NEXTHOP", - "IPV6_2292PKTINFO", - "IPV6_2292PKTOPTIONS", - "IPV6_2292RTHDR", - "IPV6_ADDRFORM", - "IPV6_ADD_MEMBERSHIP", - "IPV6_AUTHHDR", - "IPV6_AUTH_LEVEL", - "IPV6_AUTOFLOWLABEL", - "IPV6_BINDANY", - "IPV6_BINDV6ONLY", - "IPV6_BOUND_IF", - "IPV6_CHECKSUM", - "IPV6_DEFAULT_MULTICAST_HOPS", - "IPV6_DEFAULT_MULTICAST_LOOP", - "IPV6_DEFHLIM", - "IPV6_DONTFRAG", - "IPV6_DROP_MEMBERSHIP", - "IPV6_DSTOPTS", - "IPV6_ESP_NETWORK_LEVEL", - "IPV6_ESP_TRANS_LEVEL", - "IPV6_FAITH", - "IPV6_FLOWINFO_MASK", - "IPV6_FLOWLABEL_MASK", - "IPV6_FRAGTTL", - "IPV6_FW_ADD", - "IPV6_FW_DEL", - "IPV6_FW_FLUSH", - "IPV6_FW_GET", - "IPV6_FW_ZERO", - "IPV6_HLIMDEC", - "IPV6_HOPLIMIT", - "IPV6_HOPOPTS", - "IPV6_IPCOMP_LEVEL", - "IPV6_IPSEC_POLICY", - "IPV6_JOIN_ANYCAST", - "IPV6_JOIN_GROUP", - "IPV6_LEAVE_ANYCAST", - "IPV6_LEAVE_GROUP", - "IPV6_MAXHLIM", - "IPV6_MAXOPTHDR", - "IPV6_MAXPACKET", - "IPV6_MAX_GROUP_SRC_FILTER", - "IPV6_MAX_MEMBERSHIPS", - "IPV6_MAX_SOCK_SRC_FILTER", - "IPV6_MIN_MEMBERSHIPS", - "IPV6_MMTU", - "IPV6_MSFILTER", - "IPV6_MTU", - "IPV6_MTU_DISCOVER", - "IPV6_MULTICAST_HOPS", - "IPV6_MULTICAST_IF", - "IPV6_MULTICAST_LOOP", - "IPV6_NEXTHOP", - "IPV6_OPTIONS", - "IPV6_PATHMTU", - "IPV6_PIPEX", - "IPV6_PKTINFO", - "IPV6_PMTUDISC_DO", - "IPV6_PMTUDISC_DONT", - "IPV6_PMTUDISC_PROBE", - "IPV6_PMTUDISC_WANT", - "IPV6_PORTRANGE", - "IPV6_PORTRANGE_DEFAULT", - "IPV6_PORTRANGE_HIGH", - "IPV6_PORTRANGE_LOW", - "IPV6_PREFER_TEMPADDR", - "IPV6_RECVDSTOPTS", - "IPV6_RECVDSTPORT", - "IPV6_RECVERR", - "IPV6_RECVHOPLIMIT", - "IPV6_RECVHOPOPTS", - "IPV6_RECVPATHMTU", - "IPV6_RECVPKTINFO", - "IPV6_RECVRTHDR", - "IPV6_RECVTCLASS", - "IPV6_ROUTER_ALERT", - "IPV6_RTABLE", - "IPV6_RTHDR", - "IPV6_RTHDRDSTOPTS", - "IPV6_RTHDR_LOOSE", - "IPV6_RTHDR_STRICT", - "IPV6_RTHDR_TYPE_0", - "IPV6_RXDSTOPTS", - "IPV6_RXHOPOPTS", - "IPV6_SOCKOPT_RESERVED1", - "IPV6_TCLASS", - "IPV6_UNICAST_HOPS", - "IPV6_USE_MIN_MTU", - "IPV6_V6ONLY", - "IPV6_VERSION", - "IPV6_VERSION_MASK", - "IPV6_XFRM_POLICY", - "IP_ADD_MEMBERSHIP", - "IP_ADD_SOURCE_MEMBERSHIP", - "IP_AUTH_LEVEL", - "IP_BINDANY", - "IP_BLOCK_SOURCE", - "IP_BOUND_IF", - "IP_DEFAULT_MULTICAST_LOOP", - "IP_DEFAULT_MULTICAST_TTL", - "IP_DF", - "IP_DIVERTFL", - "IP_DONTFRAG", - "IP_DROP_MEMBERSHIP", - "IP_DROP_SOURCE_MEMBERSHIP", - "IP_DUMMYNET3", - "IP_DUMMYNET_CONFIGURE", - "IP_DUMMYNET_DEL", - "IP_DUMMYNET_FLUSH", - "IP_DUMMYNET_GET", - "IP_EF", - "IP_ERRORMTU", - "IP_ESP_NETWORK_LEVEL", - "IP_ESP_TRANS_LEVEL", - "IP_FAITH", - "IP_FREEBIND", - "IP_FW3", - "IP_FW_ADD", - "IP_FW_DEL", - "IP_FW_FLUSH", - "IP_FW_GET", - "IP_FW_NAT_CFG", - "IP_FW_NAT_DEL", - "IP_FW_NAT_GET_CONFIG", - "IP_FW_NAT_GET_LOG", - "IP_FW_RESETLOG", - "IP_FW_TABLE_ADD", - "IP_FW_TABLE_DEL", - "IP_FW_TABLE_FLUSH", - "IP_FW_TABLE_GETSIZE", - "IP_FW_TABLE_LIST", - "IP_FW_ZERO", - "IP_HDRINCL", - "IP_IPCOMP_LEVEL", - "IP_IPSECFLOWINFO", - "IP_IPSEC_LOCAL_AUTH", - "IP_IPSEC_LOCAL_CRED", - "IP_IPSEC_LOCAL_ID", - "IP_IPSEC_POLICY", - "IP_IPSEC_REMOTE_AUTH", - "IP_IPSEC_REMOTE_CRED", - "IP_IPSEC_REMOTE_ID", - "IP_MAXPACKET", - "IP_MAX_GROUP_SRC_FILTER", - "IP_MAX_MEMBERSHIPS", - "IP_MAX_SOCK_MUTE_FILTER", - "IP_MAX_SOCK_SRC_FILTER", - "IP_MAX_SOURCE_FILTER", - "IP_MF", - "IP_MINFRAGSIZE", - "IP_MINTTL", - "IP_MIN_MEMBERSHIPS", - "IP_MSFILTER", - "IP_MSS", - "IP_MTU", - "IP_MTU_DISCOVER", - "IP_MULTICAST_IF", - "IP_MULTICAST_IFINDEX", - "IP_MULTICAST_LOOP", - "IP_MULTICAST_TTL", - "IP_MULTICAST_VIF", - "IP_NAT__XXX", - "IP_OFFMASK", - "IP_OLD_FW_ADD", - "IP_OLD_FW_DEL", - "IP_OLD_FW_FLUSH", - "IP_OLD_FW_GET", - "IP_OLD_FW_RESETLOG", - "IP_OLD_FW_ZERO", - "IP_ONESBCAST", - "IP_OPTIONS", - "IP_ORIGDSTADDR", - "IP_PASSSEC", - "IP_PIPEX", - "IP_PKTINFO", - "IP_PKTOPTIONS", - "IP_PMTUDISC", - "IP_PMTUDISC_DO", - "IP_PMTUDISC_DONT", - "IP_PMTUDISC_PROBE", - "IP_PMTUDISC_WANT", - "IP_PORTRANGE", - "IP_PORTRANGE_DEFAULT", - "IP_PORTRANGE_HIGH", - "IP_PORTRANGE_LOW", - "IP_RECVDSTADDR", - "IP_RECVDSTPORT", - "IP_RECVERR", - "IP_RECVIF", - "IP_RECVOPTS", - "IP_RECVORIGDSTADDR", - "IP_RECVPKTINFO", - "IP_RECVRETOPTS", - "IP_RECVRTABLE", - "IP_RECVTOS", - "IP_RECVTTL", - "IP_RETOPTS", - "IP_RF", - "IP_ROUTER_ALERT", - "IP_RSVP_OFF", - "IP_RSVP_ON", - "IP_RSVP_VIF_OFF", - "IP_RSVP_VIF_ON", - "IP_RTABLE", - "IP_SENDSRCADDR", - "IP_STRIPHDR", - "IP_TOS", - "IP_TRAFFIC_MGT_BACKGROUND", - "IP_TRANSPARENT", - "IP_TTL", - "IP_UNBLOCK_SOURCE", - "IP_XFRM_POLICY", - "IPv6MTUInfo", - "IPv6Mreq", - "ISIG", - "ISTRIP", - "IUCLC", - "IUTF8", - "IXANY", - "IXOFF", - "IXON", - "IfAddrmsg", - "IfAnnounceMsghdr", - "IfData", - "IfInfomsg", - "IfMsghdr", - "IfaMsghdr", - "IfmaMsghdr", - "IfmaMsghdr2", - "ImplementsGetwd", - "Inet4Pktinfo", - "Inet6Pktinfo", - "InotifyAddWatch", - "InotifyEvent", - "InotifyInit", - "InotifyInit1", - "InotifyRmWatch", - "InterfaceAddrMessage", - "InterfaceAnnounceMessage", - "InterfaceInfo", - "InterfaceMessage", - "InterfaceMulticastAddrMessage", - "InvalidHandle", - "Ioperm", - "Iopl", - "Iovec", - "IpAdapterInfo", - "IpAddrString", - "IpAddressString", - "IpMaskString", - "Issetugid", - "KEY_ALL_ACCESS", - "KEY_CREATE_LINK", - "KEY_CREATE_SUB_KEY", - "KEY_ENUMERATE_SUB_KEYS", - "KEY_EXECUTE", - "KEY_NOTIFY", - "KEY_QUERY_VALUE", - "KEY_READ", - "KEY_SET_VALUE", - "KEY_WOW64_32KEY", - "KEY_WOW64_64KEY", - "KEY_WRITE", - "Kevent", - "Kevent_t", - "Kill", - "Klogctl", - "Kqueue", - "LANG_ENGLISH", - "LAYERED_PROTOCOL", - "LCNT_OVERLOAD_FLUSH", - "LINUX_REBOOT_CMD_CAD_OFF", - "LINUX_REBOOT_CMD_CAD_ON", - "LINUX_REBOOT_CMD_HALT", - "LINUX_REBOOT_CMD_KEXEC", - "LINUX_REBOOT_CMD_POWER_OFF", - "LINUX_REBOOT_CMD_RESTART", - "LINUX_REBOOT_CMD_RESTART2", - "LINUX_REBOOT_CMD_SW_SUSPEND", - "LINUX_REBOOT_MAGIC1", - "LINUX_REBOOT_MAGIC2", - "LOCK_EX", - "LOCK_NB", - "LOCK_SH", - "LOCK_UN", - "LazyDLL", - "LazyProc", - "Lchown", - "Linger", - "Link", - "Listen", - "Listxattr", - "LoadCancelIoEx", - "LoadConnectEx", - "LoadCreateSymbolicLink", - "LoadDLL", - "LoadGetAddrInfo", - "LoadLibrary", - "LoadSetFileCompletionNotificationModes", - "LocalFree", - "Log2phys_t", - "LookupAccountName", - "LookupAccountSid", - "LookupSID", - "LsfJump", - "LsfSocket", - "LsfStmt", - "Lstat", - "MADV_AUTOSYNC", - "MADV_CAN_REUSE", - "MADV_CORE", - "MADV_DOFORK", - "MADV_DONTFORK", - "MADV_DONTNEED", - "MADV_FREE", - "MADV_FREE_REUSABLE", - "MADV_FREE_REUSE", - "MADV_HUGEPAGE", - "MADV_HWPOISON", - "MADV_MERGEABLE", - "MADV_NOCORE", - "MADV_NOHUGEPAGE", - "MADV_NORMAL", - "MADV_NOSYNC", - "MADV_PROTECT", - "MADV_RANDOM", - "MADV_REMOVE", - "MADV_SEQUENTIAL", - "MADV_SPACEAVAIL", - "MADV_UNMERGEABLE", - "MADV_WILLNEED", - "MADV_ZERO_WIRED_PAGES", - "MAP_32BIT", - "MAP_ALIGNED_SUPER", - "MAP_ALIGNMENT_16MB", - "MAP_ALIGNMENT_1TB", - "MAP_ALIGNMENT_256TB", - "MAP_ALIGNMENT_4GB", - "MAP_ALIGNMENT_64KB", - "MAP_ALIGNMENT_64PB", - "MAP_ALIGNMENT_MASK", - "MAP_ALIGNMENT_SHIFT", - "MAP_ANON", - "MAP_ANONYMOUS", - "MAP_COPY", - "MAP_DENYWRITE", - "MAP_EXECUTABLE", - "MAP_FILE", - "MAP_FIXED", - "MAP_FLAGMASK", - "MAP_GROWSDOWN", - "MAP_HASSEMAPHORE", - "MAP_HUGETLB", - "MAP_INHERIT", - "MAP_INHERIT_COPY", - "MAP_INHERIT_DEFAULT", - "MAP_INHERIT_DONATE_COPY", - "MAP_INHERIT_NONE", - "MAP_INHERIT_SHARE", - "MAP_JIT", - "MAP_LOCKED", - "MAP_NOCACHE", - "MAP_NOCORE", - "MAP_NOEXTEND", - "MAP_NONBLOCK", - "MAP_NORESERVE", - "MAP_NOSYNC", - "MAP_POPULATE", - "MAP_PREFAULT_READ", - "MAP_PRIVATE", - "MAP_RENAME", - "MAP_RESERVED0080", - "MAP_RESERVED0100", - "MAP_SHARED", - "MAP_STACK", - "MAP_TRYFIXED", - "MAP_TYPE", - "MAP_WIRED", - "MAXIMUM_REPARSE_DATA_BUFFER_SIZE", - "MAXLEN_IFDESCR", - "MAXLEN_PHYSADDR", - "MAX_ADAPTER_ADDRESS_LENGTH", - "MAX_ADAPTER_DESCRIPTION_LENGTH", - "MAX_ADAPTER_NAME_LENGTH", - "MAX_COMPUTERNAME_LENGTH", - "MAX_INTERFACE_NAME_LEN", - "MAX_LONG_PATH", - "MAX_PATH", - "MAX_PROTOCOL_CHAIN", - "MCL_CURRENT", - "MCL_FUTURE", - "MNT_DETACH", - "MNT_EXPIRE", - "MNT_FORCE", - "MSG_BCAST", - "MSG_CMSG_CLOEXEC", - "MSG_COMPAT", - "MSG_CONFIRM", - "MSG_CONTROLMBUF", - "MSG_CTRUNC", - "MSG_DONTROUTE", - "MSG_DONTWAIT", - "MSG_EOF", - "MSG_EOR", - "MSG_ERRQUEUE", - "MSG_FASTOPEN", - "MSG_FIN", - "MSG_FLUSH", - "MSG_HAVEMORE", - "MSG_HOLD", - "MSG_IOVUSRSPACE", - "MSG_LENUSRSPACE", - "MSG_MCAST", - "MSG_MORE", - "MSG_NAMEMBUF", - "MSG_NBIO", - "MSG_NEEDSA", - "MSG_NOSIGNAL", - "MSG_NOTIFICATION", - "MSG_OOB", - "MSG_PEEK", - "MSG_PROXY", - "MSG_RCVMORE", - "MSG_RST", - "MSG_SEND", - "MSG_SYN", - "MSG_TRUNC", - "MSG_TRYHARD", - "MSG_USERFLAGS", - "MSG_WAITALL", - "MSG_WAITFORONE", - "MSG_WAITSTREAM", - "MS_ACTIVE", - "MS_ASYNC", - "MS_BIND", - "MS_DEACTIVATE", - "MS_DIRSYNC", - "MS_INVALIDATE", - "MS_I_VERSION", - "MS_KERNMOUNT", - "MS_KILLPAGES", - "MS_MANDLOCK", - "MS_MGC_MSK", - "MS_MGC_VAL", - "MS_MOVE", - "MS_NOATIME", - "MS_NODEV", - "MS_NODIRATIME", - "MS_NOEXEC", - "MS_NOSUID", - "MS_NOUSER", - "MS_POSIXACL", - "MS_PRIVATE", - "MS_RDONLY", - "MS_REC", - "MS_RELATIME", - "MS_REMOUNT", - "MS_RMT_MASK", - "MS_SHARED", - "MS_SILENT", - "MS_SLAVE", - "MS_STRICTATIME", - "MS_SYNC", - "MS_SYNCHRONOUS", - "MS_UNBINDABLE", - "Madvise", - "MapViewOfFile", - "MaxTokenInfoClass", - "Mclpool", - "MibIfRow", - "Mkdir", - "Mkdirat", - "Mkfifo", - "Mknod", - "Mknodat", - "Mlock", - "Mlockall", - "Mmap", - "Mount", - "MoveFile", - "Mprotect", - "Msghdr", - "Munlock", - "Munlockall", - "Munmap", - "MustLoadDLL", - "NAME_MAX", - "NETLINK_ADD_MEMBERSHIP", - "NETLINK_AUDIT", - "NETLINK_BROADCAST_ERROR", - "NETLINK_CONNECTOR", - "NETLINK_DNRTMSG", - "NETLINK_DROP_MEMBERSHIP", - "NETLINK_ECRYPTFS", - "NETLINK_FIB_LOOKUP", - "NETLINK_FIREWALL", - "NETLINK_GENERIC", - "NETLINK_INET_DIAG", - "NETLINK_IP6_FW", - "NETLINK_ISCSI", - "NETLINK_KOBJECT_UEVENT", - "NETLINK_NETFILTER", - "NETLINK_NFLOG", - "NETLINK_NO_ENOBUFS", - "NETLINK_PKTINFO", - "NETLINK_RDMA", - "NETLINK_ROUTE", - "NETLINK_SCSITRANSPORT", - "NETLINK_SELINUX", - "NETLINK_UNUSED", - "NETLINK_USERSOCK", - "NETLINK_XFRM", - "NET_RT_DUMP", - "NET_RT_DUMP2", - "NET_RT_FLAGS", - "NET_RT_IFLIST", - "NET_RT_IFLIST2", - "NET_RT_IFLISTL", - "NET_RT_IFMALIST", - "NET_RT_MAXID", - "NET_RT_OIFLIST", - "NET_RT_OOIFLIST", - "NET_RT_STAT", - "NET_RT_STATS", - "NET_RT_TABLE", - "NET_RT_TRASH", - "NLA_ALIGNTO", - "NLA_F_NESTED", - "NLA_F_NET_BYTEORDER", - "NLA_HDRLEN", - "NLMSG_ALIGNTO", - "NLMSG_DONE", - "NLMSG_ERROR", - "NLMSG_HDRLEN", - "NLMSG_MIN_TYPE", - "NLMSG_NOOP", - "NLMSG_OVERRUN", - "NLM_F_ACK", - "NLM_F_APPEND", - "NLM_F_ATOMIC", - "NLM_F_CREATE", - "NLM_F_DUMP", - "NLM_F_ECHO", - "NLM_F_EXCL", - "NLM_F_MATCH", - "NLM_F_MULTI", - "NLM_F_REPLACE", - "NLM_F_REQUEST", - "NLM_F_ROOT", - "NOFLSH", - "NOTE_ABSOLUTE", - "NOTE_ATTRIB", - "NOTE_BACKGROUND", - "NOTE_CHILD", - "NOTE_CRITICAL", - "NOTE_DELETE", - "NOTE_EOF", - "NOTE_EXEC", - "NOTE_EXIT", - "NOTE_EXITSTATUS", - "NOTE_EXIT_CSERROR", - "NOTE_EXIT_DECRYPTFAIL", - "NOTE_EXIT_DETAIL", - "NOTE_EXIT_DETAIL_MASK", - "NOTE_EXIT_MEMORY", - "NOTE_EXIT_REPARENTED", - "NOTE_EXTEND", - "NOTE_FFAND", - "NOTE_FFCOPY", - "NOTE_FFCTRLMASK", - "NOTE_FFLAGSMASK", - "NOTE_FFNOP", - "NOTE_FFOR", - "NOTE_FORK", - "NOTE_LEEWAY", - "NOTE_LINK", - "NOTE_LOWAT", - "NOTE_NONE", - "NOTE_NSECONDS", - "NOTE_PCTRLMASK", - "NOTE_PDATAMASK", - "NOTE_REAP", - "NOTE_RENAME", - "NOTE_RESOURCEEND", - "NOTE_REVOKE", - "NOTE_SECONDS", - "NOTE_SIGNAL", - "NOTE_TRACK", - "NOTE_TRACKERR", - "NOTE_TRIGGER", - "NOTE_TRUNCATE", - "NOTE_USECONDS", - "NOTE_VM_ERROR", - "NOTE_VM_PRESSURE", - "NOTE_VM_PRESSURE_SUDDEN_TERMINATE", - "NOTE_VM_PRESSURE_TERMINATE", - "NOTE_WRITE", - "NameCanonical", - "NameCanonicalEx", - "NameDisplay", - "NameDnsDomain", - "NameFullyQualifiedDN", - "NameSamCompatible", - "NameServicePrincipal", - "NameUniqueId", - "NameUnknown", - "NameUserPrincipal", - "Nanosleep", - "NetApiBufferFree", - "NetGetJoinInformation", - "NetSetupDomainName", - "NetSetupUnjoined", - "NetSetupUnknownStatus", - "NetSetupWorkgroupName", - "NetUserGetInfo", - "NetlinkMessage", - "NetlinkRIB", - "NetlinkRouteAttr", - "NetlinkRouteRequest", - "NewCallback", - "NewCallbackCDecl", - "NewLazyDLL", - "NlAttr", - "NlMsgerr", - "NlMsghdr", - "NsecToFiletime", - "NsecToTimespec", - "NsecToTimeval", - "Ntohs", - "OCRNL", - "OFDEL", - "OFILL", - "OFIOGETBMAP", - "OID_PKIX_KP_SERVER_AUTH", - "OID_SERVER_GATED_CRYPTO", - "OID_SGC_NETSCAPE", - "OLCUC", - "ONLCR", - "ONLRET", - "ONOCR", - "ONOEOT", - "OPEN_ALWAYS", - "OPEN_EXISTING", - "OPOST", - "O_ACCMODE", - "O_ALERT", - "O_ALT_IO", - "O_APPEND", - "O_ASYNC", - "O_CLOEXEC", - "O_CREAT", - "O_DIRECT", - "O_DIRECTORY", - "O_DP_GETRAWENCRYPTED", - "O_DSYNC", - "O_EVTONLY", - "O_EXCL", - "O_EXEC", - "O_EXLOCK", - "O_FSYNC", - "O_LARGEFILE", - "O_NDELAY", - "O_NOATIME", - "O_NOCTTY", - "O_NOFOLLOW", - "O_NONBLOCK", - "O_NOSIGPIPE", - "O_POPUP", - "O_RDONLY", - "O_RDWR", - "O_RSYNC", - "O_SHLOCK", - "O_SYMLINK", - "O_SYNC", - "O_TRUNC", - "O_TTY_INIT", - "O_WRONLY", - "Open", - "OpenCurrentProcessToken", - "OpenProcess", - "OpenProcessToken", - "Openat", - "Overlapped", - "PACKET_ADD_MEMBERSHIP", - "PACKET_BROADCAST", - "PACKET_DROP_MEMBERSHIP", - "PACKET_FASTROUTE", - "PACKET_HOST", - "PACKET_LOOPBACK", - "PACKET_MR_ALLMULTI", - "PACKET_MR_MULTICAST", - "PACKET_MR_PROMISC", - "PACKET_MULTICAST", - "PACKET_OTHERHOST", - "PACKET_OUTGOING", - "PACKET_RECV_OUTPUT", - "PACKET_RX_RING", - "PACKET_STATISTICS", - "PAGE_EXECUTE_READ", - "PAGE_EXECUTE_READWRITE", - "PAGE_EXECUTE_WRITECOPY", - "PAGE_READONLY", - "PAGE_READWRITE", - "PAGE_WRITECOPY", - "PARENB", - "PARMRK", - "PARODD", - "PENDIN", - "PFL_HIDDEN", - "PFL_MATCHES_PROTOCOL_ZERO", - "PFL_MULTIPLE_PROTO_ENTRIES", - "PFL_NETWORKDIRECT_PROVIDER", - "PFL_RECOMMENDED_PROTO_ENTRY", - "PF_FLUSH", - "PKCS_7_ASN_ENCODING", - "PMC5_PIPELINE_FLUSH", - "PRIO_PGRP", - "PRIO_PROCESS", - "PRIO_USER", - "PRI_IOFLUSH", - "PROCESS_QUERY_INFORMATION", - "PROCESS_TERMINATE", - "PROT_EXEC", - "PROT_GROWSDOWN", - "PROT_GROWSUP", - "PROT_NONE", - "PROT_READ", - "PROT_WRITE", - "PROV_DH_SCHANNEL", - "PROV_DSS", - "PROV_DSS_DH", - "PROV_EC_ECDSA_FULL", - "PROV_EC_ECDSA_SIG", - "PROV_EC_ECNRA_FULL", - "PROV_EC_ECNRA_SIG", - "PROV_FORTEZZA", - "PROV_INTEL_SEC", - "PROV_MS_EXCHANGE", - "PROV_REPLACE_OWF", - "PROV_RNG", - "PROV_RSA_AES", - "PROV_RSA_FULL", - "PROV_RSA_SCHANNEL", - "PROV_RSA_SIG", - "PROV_SPYRUS_LYNKS", - "PROV_SSL", - "PR_CAPBSET_DROP", - "PR_CAPBSET_READ", - "PR_CLEAR_SECCOMP_FILTER", - "PR_ENDIAN_BIG", - "PR_ENDIAN_LITTLE", - "PR_ENDIAN_PPC_LITTLE", - "PR_FPEMU_NOPRINT", - "PR_FPEMU_SIGFPE", - "PR_FP_EXC_ASYNC", - "PR_FP_EXC_DISABLED", - "PR_FP_EXC_DIV", - "PR_FP_EXC_INV", - "PR_FP_EXC_NONRECOV", - "PR_FP_EXC_OVF", - "PR_FP_EXC_PRECISE", - "PR_FP_EXC_RES", - "PR_FP_EXC_SW_ENABLE", - "PR_FP_EXC_UND", - "PR_GET_DUMPABLE", - "PR_GET_ENDIAN", - "PR_GET_FPEMU", - "PR_GET_FPEXC", - "PR_GET_KEEPCAPS", - "PR_GET_NAME", - "PR_GET_PDEATHSIG", - "PR_GET_SECCOMP", - "PR_GET_SECCOMP_FILTER", - "PR_GET_SECUREBITS", - "PR_GET_TIMERSLACK", - "PR_GET_TIMING", - "PR_GET_TSC", - "PR_GET_UNALIGN", - "PR_MCE_KILL", - "PR_MCE_KILL_CLEAR", - "PR_MCE_KILL_DEFAULT", - "PR_MCE_KILL_EARLY", - "PR_MCE_KILL_GET", - "PR_MCE_KILL_LATE", - "PR_MCE_KILL_SET", - "PR_SECCOMP_FILTER_EVENT", - "PR_SECCOMP_FILTER_SYSCALL", - "PR_SET_DUMPABLE", - "PR_SET_ENDIAN", - "PR_SET_FPEMU", - "PR_SET_FPEXC", - "PR_SET_KEEPCAPS", - "PR_SET_NAME", - "PR_SET_PDEATHSIG", - "PR_SET_PTRACER", - "PR_SET_SECCOMP", - "PR_SET_SECCOMP_FILTER", - "PR_SET_SECUREBITS", - "PR_SET_TIMERSLACK", - "PR_SET_TIMING", - "PR_SET_TSC", - "PR_SET_UNALIGN", - "PR_TASK_PERF_EVENTS_DISABLE", - "PR_TASK_PERF_EVENTS_ENABLE", - "PR_TIMING_STATISTICAL", - "PR_TIMING_TIMESTAMP", - "PR_TSC_ENABLE", - "PR_TSC_SIGSEGV", - "PR_UNALIGN_NOPRINT", - "PR_UNALIGN_SIGBUS", - "PTRACE_ARCH_PRCTL", - "PTRACE_ATTACH", - "PTRACE_CONT", - "PTRACE_DETACH", - "PTRACE_EVENT_CLONE", - "PTRACE_EVENT_EXEC", - "PTRACE_EVENT_EXIT", - "PTRACE_EVENT_FORK", - "PTRACE_EVENT_VFORK", - "PTRACE_EVENT_VFORK_DONE", - "PTRACE_GETCRUNCHREGS", - "PTRACE_GETEVENTMSG", - "PTRACE_GETFPREGS", - "PTRACE_GETFPXREGS", - "PTRACE_GETHBPREGS", - "PTRACE_GETREGS", - "PTRACE_GETREGSET", - "PTRACE_GETSIGINFO", - "PTRACE_GETVFPREGS", - "PTRACE_GETWMMXREGS", - "PTRACE_GET_THREAD_AREA", - "PTRACE_KILL", - "PTRACE_OLDSETOPTIONS", - "PTRACE_O_MASK", - "PTRACE_O_TRACECLONE", - "PTRACE_O_TRACEEXEC", - "PTRACE_O_TRACEEXIT", - "PTRACE_O_TRACEFORK", - "PTRACE_O_TRACESYSGOOD", - "PTRACE_O_TRACEVFORK", - "PTRACE_O_TRACEVFORKDONE", - "PTRACE_PEEKDATA", - "PTRACE_PEEKTEXT", - "PTRACE_PEEKUSR", - "PTRACE_POKEDATA", - "PTRACE_POKETEXT", - "PTRACE_POKEUSR", - "PTRACE_SETCRUNCHREGS", - "PTRACE_SETFPREGS", - "PTRACE_SETFPXREGS", - "PTRACE_SETHBPREGS", - "PTRACE_SETOPTIONS", - "PTRACE_SETREGS", - "PTRACE_SETREGSET", - "PTRACE_SETSIGINFO", - "PTRACE_SETVFPREGS", - "PTRACE_SETWMMXREGS", - "PTRACE_SET_SYSCALL", - "PTRACE_SET_THREAD_AREA", - "PTRACE_SINGLEBLOCK", - "PTRACE_SINGLESTEP", - "PTRACE_SYSCALL", - "PTRACE_SYSEMU", - "PTRACE_SYSEMU_SINGLESTEP", - "PTRACE_TRACEME", - "PT_ATTACH", - "PT_ATTACHEXC", - "PT_CONTINUE", - "PT_DATA_ADDR", - "PT_DENY_ATTACH", - "PT_DETACH", - "PT_FIRSTMACH", - "PT_FORCEQUOTA", - "PT_KILL", - "PT_MASK", - "PT_READ_D", - "PT_READ_I", - "PT_READ_U", - "PT_SIGEXC", - "PT_STEP", - "PT_TEXT_ADDR", - "PT_TEXT_END_ADDR", - "PT_THUPDATE", - "PT_TRACE_ME", - "PT_WRITE_D", - "PT_WRITE_I", - "PT_WRITE_U", - "ParseDirent", - "ParseNetlinkMessage", - "ParseNetlinkRouteAttr", - "ParseRoutingMessage", - "ParseRoutingSockaddr", - "ParseSocketControlMessage", - "ParseUnixCredentials", - "ParseUnixRights", - "PathMax", - "Pathconf", - "Pause", - "Pipe", - "Pipe2", - "PivotRoot", - "Pointer", - "PostQueuedCompletionStatus", - "Pread", - "Proc", - "ProcAttr", - "Process32First", - "Process32Next", - "ProcessEntry32", - "ProcessInformation", - "Protoent", - "PtraceAttach", - "PtraceCont", - "PtraceDetach", - "PtraceGetEventMsg", - "PtraceGetRegs", - "PtracePeekData", - "PtracePeekText", - "PtracePokeData", - "PtracePokeText", - "PtraceRegs", - "PtraceSetOptions", - "PtraceSetRegs", - "PtraceSingleStep", - "PtraceSyscall", - "Pwrite", - "REG_BINARY", - "REG_DWORD", - "REG_DWORD_BIG_ENDIAN", - "REG_DWORD_LITTLE_ENDIAN", - "REG_EXPAND_SZ", - "REG_FULL_RESOURCE_DESCRIPTOR", - "REG_LINK", - "REG_MULTI_SZ", - "REG_NONE", - "REG_QWORD", - "REG_QWORD_LITTLE_ENDIAN", - "REG_RESOURCE_LIST", - "REG_RESOURCE_REQUIREMENTS_LIST", - "REG_SZ", - "RLIMIT_AS", - "RLIMIT_CORE", - "RLIMIT_CPU", - "RLIMIT_CPU_USAGE_MONITOR", - "RLIMIT_DATA", - "RLIMIT_FSIZE", - "RLIMIT_NOFILE", - "RLIMIT_STACK", - "RLIM_INFINITY", - "RTAX_ADVMSS", - "RTAX_AUTHOR", - "RTAX_BRD", - "RTAX_CWND", - "RTAX_DST", - "RTAX_FEATURES", - "RTAX_FEATURE_ALLFRAG", - "RTAX_FEATURE_ECN", - "RTAX_FEATURE_SACK", - "RTAX_FEATURE_TIMESTAMP", - "RTAX_GATEWAY", - "RTAX_GENMASK", - "RTAX_HOPLIMIT", - "RTAX_IFA", - "RTAX_IFP", - "RTAX_INITCWND", - "RTAX_INITRWND", - "RTAX_LABEL", - "RTAX_LOCK", - "RTAX_MAX", - "RTAX_MTU", - "RTAX_NETMASK", - "RTAX_REORDERING", - "RTAX_RTO_MIN", - "RTAX_RTT", - "RTAX_RTTVAR", - "RTAX_SRC", - "RTAX_SRCMASK", - "RTAX_SSTHRESH", - "RTAX_TAG", - "RTAX_UNSPEC", - "RTAX_WINDOW", - "RTA_ALIGNTO", - "RTA_AUTHOR", - "RTA_BRD", - "RTA_CACHEINFO", - "RTA_DST", - "RTA_FLOW", - "RTA_GATEWAY", - "RTA_GENMASK", - "RTA_IFA", - "RTA_IFP", - "RTA_IIF", - "RTA_LABEL", - "RTA_MAX", - "RTA_METRICS", - "RTA_MULTIPATH", - "RTA_NETMASK", - "RTA_OIF", - "RTA_PREFSRC", - "RTA_PRIORITY", - "RTA_SRC", - "RTA_SRCMASK", - "RTA_TABLE", - "RTA_TAG", - "RTA_UNSPEC", - "RTCF_DIRECTSRC", - "RTCF_DOREDIRECT", - "RTCF_LOG", - "RTCF_MASQ", - "RTCF_NAT", - "RTCF_VALVE", - "RTF_ADDRCLASSMASK", - "RTF_ADDRCONF", - "RTF_ALLONLINK", - "RTF_ANNOUNCE", - "RTF_BLACKHOLE", - "RTF_BROADCAST", - "RTF_CACHE", - "RTF_CLONED", - "RTF_CLONING", - "RTF_CONDEMNED", - "RTF_DEFAULT", - "RTF_DELCLONE", - "RTF_DONE", - "RTF_DYNAMIC", - "RTF_FLOW", - "RTF_FMASK", - "RTF_GATEWAY", - "RTF_GWFLAG_COMPAT", - "RTF_HOST", - "RTF_IFREF", - "RTF_IFSCOPE", - "RTF_INTERFACE", - "RTF_IRTT", - "RTF_LINKRT", - "RTF_LLDATA", - "RTF_LLINFO", - "RTF_LOCAL", - "RTF_MASK", - "RTF_MODIFIED", - "RTF_MPATH", - "RTF_MPLS", - "RTF_MSS", - "RTF_MTU", - "RTF_MULTICAST", - "RTF_NAT", - "RTF_NOFORWARD", - "RTF_NONEXTHOP", - "RTF_NOPMTUDISC", - "RTF_PERMANENT_ARP", - "RTF_PINNED", - "RTF_POLICY", - "RTF_PRCLONING", - "RTF_PROTO1", - "RTF_PROTO2", - "RTF_PROTO3", - "RTF_PROXY", - "RTF_REINSTATE", - "RTF_REJECT", - "RTF_RNH_LOCKED", - "RTF_ROUTER", - "RTF_SOURCE", - "RTF_SRC", - "RTF_STATIC", - "RTF_STICKY", - "RTF_THROW", - "RTF_TUNNEL", - "RTF_UP", - "RTF_USETRAILERS", - "RTF_WASCLONED", - "RTF_WINDOW", - "RTF_XRESOLVE", - "RTM_ADD", - "RTM_BASE", - "RTM_CHANGE", - "RTM_CHGADDR", - "RTM_DELACTION", - "RTM_DELADDR", - "RTM_DELADDRLABEL", - "RTM_DELETE", - "RTM_DELLINK", - "RTM_DELMADDR", - "RTM_DELNEIGH", - "RTM_DELQDISC", - "RTM_DELROUTE", - "RTM_DELRULE", - "RTM_DELTCLASS", - "RTM_DELTFILTER", - "RTM_DESYNC", - "RTM_F_CLONED", - "RTM_F_EQUALIZE", - "RTM_F_NOTIFY", - "RTM_F_PREFIX", - "RTM_GET", - "RTM_GET2", - "RTM_GETACTION", - "RTM_GETADDR", - "RTM_GETADDRLABEL", - "RTM_GETANYCAST", - "RTM_GETDCB", - "RTM_GETLINK", - "RTM_GETMULTICAST", - "RTM_GETNEIGH", - "RTM_GETNEIGHTBL", - "RTM_GETQDISC", - "RTM_GETROUTE", - "RTM_GETRULE", - "RTM_GETTCLASS", - "RTM_GETTFILTER", - "RTM_IEEE80211", - "RTM_IFANNOUNCE", - "RTM_IFINFO", - "RTM_IFINFO2", - "RTM_LLINFO_UPD", - "RTM_LOCK", - "RTM_LOSING", - "RTM_MAX", - "RTM_MAXSIZE", - "RTM_MISS", - "RTM_NEWACTION", - "RTM_NEWADDR", - "RTM_NEWADDRLABEL", - "RTM_NEWLINK", - "RTM_NEWMADDR", - "RTM_NEWMADDR2", - "RTM_NEWNDUSEROPT", - "RTM_NEWNEIGH", - "RTM_NEWNEIGHTBL", - "RTM_NEWPREFIX", - "RTM_NEWQDISC", - "RTM_NEWROUTE", - "RTM_NEWRULE", - "RTM_NEWTCLASS", - "RTM_NEWTFILTER", - "RTM_NR_FAMILIES", - "RTM_NR_MSGTYPES", - "RTM_OIFINFO", - "RTM_OLDADD", - "RTM_OLDDEL", - "RTM_OOIFINFO", - "RTM_REDIRECT", - "RTM_RESOLVE", - "RTM_RTTUNIT", - "RTM_SETDCB", - "RTM_SETGATE", - "RTM_SETLINK", - "RTM_SETNEIGHTBL", - "RTM_VERSION", - "RTNH_ALIGNTO", - "RTNH_F_DEAD", - "RTNH_F_ONLINK", - "RTNH_F_PERVASIVE", - "RTNLGRP_IPV4_IFADDR", - "RTNLGRP_IPV4_MROUTE", - "RTNLGRP_IPV4_ROUTE", - "RTNLGRP_IPV4_RULE", - "RTNLGRP_IPV6_IFADDR", - "RTNLGRP_IPV6_IFINFO", - "RTNLGRP_IPV6_MROUTE", - "RTNLGRP_IPV6_PREFIX", - "RTNLGRP_IPV6_ROUTE", - "RTNLGRP_IPV6_RULE", - "RTNLGRP_LINK", - "RTNLGRP_ND_USEROPT", - "RTNLGRP_NEIGH", - "RTNLGRP_NONE", - "RTNLGRP_NOTIFY", - "RTNLGRP_TC", - "RTN_ANYCAST", - "RTN_BLACKHOLE", - "RTN_BROADCAST", - "RTN_LOCAL", - "RTN_MAX", - "RTN_MULTICAST", - "RTN_NAT", - "RTN_PROHIBIT", - "RTN_THROW", - "RTN_UNICAST", - "RTN_UNREACHABLE", - "RTN_UNSPEC", - "RTN_XRESOLVE", - "RTPROT_BIRD", - "RTPROT_BOOT", - "RTPROT_DHCP", - "RTPROT_DNROUTED", - "RTPROT_GATED", - "RTPROT_KERNEL", - "RTPROT_MRT", - "RTPROT_NTK", - "RTPROT_RA", - "RTPROT_REDIRECT", - "RTPROT_STATIC", - "RTPROT_UNSPEC", - "RTPROT_XORP", - "RTPROT_ZEBRA", - "RTV_EXPIRE", - "RTV_HOPCOUNT", - "RTV_MTU", - "RTV_RPIPE", - "RTV_RTT", - "RTV_RTTVAR", - "RTV_SPIPE", - "RTV_SSTHRESH", - "RTV_WEIGHT", - "RT_CACHING_CONTEXT", - "RT_CLASS_DEFAULT", - "RT_CLASS_LOCAL", - "RT_CLASS_MAIN", - "RT_CLASS_MAX", - "RT_CLASS_UNSPEC", - "RT_DEFAULT_FIB", - "RT_NORTREF", - "RT_SCOPE_HOST", - "RT_SCOPE_LINK", - "RT_SCOPE_NOWHERE", - "RT_SCOPE_SITE", - "RT_SCOPE_UNIVERSE", - "RT_TABLEID_MAX", - "RT_TABLE_COMPAT", - "RT_TABLE_DEFAULT", - "RT_TABLE_LOCAL", - "RT_TABLE_MAIN", - "RT_TABLE_MAX", - "RT_TABLE_UNSPEC", - "RUSAGE_CHILDREN", - "RUSAGE_SELF", - "RUSAGE_THREAD", - "Radvisory_t", - "RawConn", - "RawSockaddr", - "RawSockaddrAny", - "RawSockaddrDatalink", - "RawSockaddrInet4", - "RawSockaddrInet6", - "RawSockaddrLinklayer", - "RawSockaddrNetlink", - "RawSockaddrUnix", - "RawSyscall", - "RawSyscall6", - "Read", - "ReadConsole", - "ReadDirectoryChanges", - "ReadDirent", - "ReadFile", - "Readlink", - "Reboot", - "Recvfrom", - "Recvmsg", - "RegCloseKey", - "RegEnumKeyEx", - "RegOpenKeyEx", - "RegQueryInfoKey", - "RegQueryValueEx", - "RemoveDirectory", - "Removexattr", - "Rename", - "Renameat", - "Revoke", - "Rlimit", - "Rmdir", - "RouteMessage", - "RouteRIB", - "RoutingMessage", - "RtAttr", - "RtGenmsg", - "RtMetrics", - "RtMsg", - "RtMsghdr", - "RtNexthop", - "Rusage", - "SCM_BINTIME", - "SCM_CREDENTIALS", - "SCM_CREDS", - "SCM_RIGHTS", - "SCM_TIMESTAMP", - "SCM_TIMESTAMPING", - "SCM_TIMESTAMPNS", - "SCM_TIMESTAMP_MONOTONIC", - "SHUT_RD", - "SHUT_RDWR", - "SHUT_WR", - "SID", - "SIDAndAttributes", - "SIGABRT", - "SIGALRM", - "SIGBUS", - "SIGCHLD", - "SIGCLD", - "SIGCONT", - "SIGEMT", - "SIGFPE", - "SIGHUP", - "SIGILL", - "SIGINFO", - "SIGINT", - "SIGIO", - "SIGIOT", - "SIGKILL", - "SIGLIBRT", - "SIGLWP", - "SIGPIPE", - "SIGPOLL", - "SIGPROF", - "SIGPWR", - "SIGQUIT", - "SIGSEGV", - "SIGSTKFLT", - "SIGSTOP", - "SIGSYS", - "SIGTERM", - "SIGTHR", - "SIGTRAP", - "SIGTSTP", - "SIGTTIN", - "SIGTTOU", - "SIGUNUSED", - "SIGURG", - "SIGUSR1", - "SIGUSR2", - "SIGVTALRM", - "SIGWINCH", - "SIGXCPU", - "SIGXFSZ", - "SIOCADDDLCI", - "SIOCADDMULTI", - "SIOCADDRT", - "SIOCAIFADDR", - "SIOCAIFGROUP", - "SIOCALIFADDR", - "SIOCARPIPLL", - "SIOCATMARK", - "SIOCAUTOADDR", - "SIOCAUTONETMASK", - "SIOCBRDGADD", - "SIOCBRDGADDS", - "SIOCBRDGARL", - "SIOCBRDGDADDR", - "SIOCBRDGDEL", - "SIOCBRDGDELS", - "SIOCBRDGFLUSH", - "SIOCBRDGFRL", - "SIOCBRDGGCACHE", - "SIOCBRDGGFD", - "SIOCBRDGGHT", - "SIOCBRDGGIFFLGS", - "SIOCBRDGGMA", - "SIOCBRDGGPARAM", - "SIOCBRDGGPRI", - "SIOCBRDGGRL", - "SIOCBRDGGSIFS", - "SIOCBRDGGTO", - "SIOCBRDGIFS", - "SIOCBRDGRTS", - "SIOCBRDGSADDR", - "SIOCBRDGSCACHE", - "SIOCBRDGSFD", - "SIOCBRDGSHT", - "SIOCBRDGSIFCOST", - "SIOCBRDGSIFFLGS", - "SIOCBRDGSIFPRIO", - "SIOCBRDGSMA", - "SIOCBRDGSPRI", - "SIOCBRDGSPROTO", - "SIOCBRDGSTO", - "SIOCBRDGSTXHC", - "SIOCDARP", - "SIOCDELDLCI", - "SIOCDELMULTI", - "SIOCDELRT", - "SIOCDEVPRIVATE", - "SIOCDIFADDR", - "SIOCDIFGROUP", - "SIOCDIFPHYADDR", - "SIOCDLIFADDR", - "SIOCDRARP", - "SIOCGARP", - "SIOCGDRVSPEC", - "SIOCGETKALIVE", - "SIOCGETLABEL", - "SIOCGETPFLOW", - "SIOCGETPFSYNC", - "SIOCGETSGCNT", - "SIOCGETVIFCNT", - "SIOCGETVLAN", - "SIOCGHIWAT", - "SIOCGIFADDR", - "SIOCGIFADDRPREF", - "SIOCGIFALIAS", - "SIOCGIFALTMTU", - "SIOCGIFASYNCMAP", - "SIOCGIFBOND", - "SIOCGIFBR", - "SIOCGIFBRDADDR", - "SIOCGIFCAP", - "SIOCGIFCONF", - "SIOCGIFCOUNT", - "SIOCGIFDATA", - "SIOCGIFDESCR", - "SIOCGIFDEVMTU", - "SIOCGIFDLT", - "SIOCGIFDSTADDR", - "SIOCGIFENCAP", - "SIOCGIFFIB", - "SIOCGIFFLAGS", - "SIOCGIFGATTR", - "SIOCGIFGENERIC", - "SIOCGIFGMEMB", - "SIOCGIFGROUP", - "SIOCGIFHARDMTU", - "SIOCGIFHWADDR", - "SIOCGIFINDEX", - "SIOCGIFKPI", - "SIOCGIFMAC", - "SIOCGIFMAP", - "SIOCGIFMEDIA", - "SIOCGIFMEM", - "SIOCGIFMETRIC", - "SIOCGIFMTU", - "SIOCGIFNAME", - "SIOCGIFNETMASK", - "SIOCGIFPDSTADDR", - "SIOCGIFPFLAGS", - "SIOCGIFPHYS", - "SIOCGIFPRIORITY", - "SIOCGIFPSRCADDR", - "SIOCGIFRDOMAIN", - "SIOCGIFRTLABEL", - "SIOCGIFSLAVE", - "SIOCGIFSTATUS", - "SIOCGIFTIMESLOT", - "SIOCGIFTXQLEN", - "SIOCGIFVLAN", - "SIOCGIFWAKEFLAGS", - "SIOCGIFXFLAGS", - "SIOCGLIFADDR", - "SIOCGLIFPHYADDR", - "SIOCGLIFPHYRTABLE", - "SIOCGLIFPHYTTL", - "SIOCGLINKSTR", - "SIOCGLOWAT", - "SIOCGPGRP", - "SIOCGPRIVATE_0", - "SIOCGPRIVATE_1", - "SIOCGRARP", - "SIOCGSPPPPARAMS", - "SIOCGSTAMP", - "SIOCGSTAMPNS", - "SIOCGVH", - "SIOCGVNETID", - "SIOCIFCREATE", - "SIOCIFCREATE2", - "SIOCIFDESTROY", - "SIOCIFGCLONERS", - "SIOCINITIFADDR", - "SIOCPROTOPRIVATE", - "SIOCRSLVMULTI", - "SIOCRTMSG", - "SIOCSARP", - "SIOCSDRVSPEC", - "SIOCSETKALIVE", - "SIOCSETLABEL", - "SIOCSETPFLOW", - "SIOCSETPFSYNC", - "SIOCSETVLAN", - "SIOCSHIWAT", - "SIOCSIFADDR", - "SIOCSIFADDRPREF", - "SIOCSIFALTMTU", - "SIOCSIFASYNCMAP", - "SIOCSIFBOND", - "SIOCSIFBR", - "SIOCSIFBRDADDR", - "SIOCSIFCAP", - "SIOCSIFDESCR", - "SIOCSIFDSTADDR", - "SIOCSIFENCAP", - "SIOCSIFFIB", - "SIOCSIFFLAGS", - "SIOCSIFGATTR", - "SIOCSIFGENERIC", - "SIOCSIFHWADDR", - "SIOCSIFHWBROADCAST", - "SIOCSIFKPI", - "SIOCSIFLINK", - "SIOCSIFLLADDR", - "SIOCSIFMAC", - "SIOCSIFMAP", - "SIOCSIFMEDIA", - "SIOCSIFMEM", - "SIOCSIFMETRIC", - "SIOCSIFMTU", - "SIOCSIFNAME", - "SIOCSIFNETMASK", - "SIOCSIFPFLAGS", - "SIOCSIFPHYADDR", - "SIOCSIFPHYS", - "SIOCSIFPRIORITY", - "SIOCSIFRDOMAIN", - "SIOCSIFRTLABEL", - "SIOCSIFRVNET", - "SIOCSIFSLAVE", - "SIOCSIFTIMESLOT", - "SIOCSIFTXQLEN", - "SIOCSIFVLAN", - "SIOCSIFVNET", - "SIOCSIFXFLAGS", - "SIOCSLIFPHYADDR", - "SIOCSLIFPHYRTABLE", - "SIOCSLIFPHYTTL", - "SIOCSLINKSTR", - "SIOCSLOWAT", - "SIOCSPGRP", - "SIOCSRARP", - "SIOCSSPPPPARAMS", - "SIOCSVH", - "SIOCSVNETID", - "SIOCZIFDATA", - "SIO_GET_EXTENSION_FUNCTION_POINTER", - "SIO_GET_INTERFACE_LIST", - "SIO_KEEPALIVE_VALS", - "SIO_UDP_CONNRESET", - "SOCK_CLOEXEC", - "SOCK_DCCP", - "SOCK_DGRAM", - "SOCK_FLAGS_MASK", - "SOCK_MAXADDRLEN", - "SOCK_NONBLOCK", - "SOCK_NOSIGPIPE", - "SOCK_PACKET", - "SOCK_RAW", - "SOCK_RDM", - "SOCK_SEQPACKET", - "SOCK_STREAM", - "SOL_AAL", - "SOL_ATM", - "SOL_DECNET", - "SOL_ICMPV6", - "SOL_IP", - "SOL_IPV6", - "SOL_IRDA", - "SOL_PACKET", - "SOL_RAW", - "SOL_SOCKET", - "SOL_TCP", - "SOL_X25", - "SOMAXCONN", - "SO_ACCEPTCONN", - "SO_ACCEPTFILTER", - "SO_ATTACH_FILTER", - "SO_BINDANY", - "SO_BINDTODEVICE", - "SO_BINTIME", - "SO_BROADCAST", - "SO_BSDCOMPAT", - "SO_DEBUG", - "SO_DETACH_FILTER", - "SO_DOMAIN", - "SO_DONTROUTE", - "SO_DONTTRUNC", - "SO_ERROR", - "SO_KEEPALIVE", - "SO_LABEL", - "SO_LINGER", - "SO_LINGER_SEC", - "SO_LISTENINCQLEN", - "SO_LISTENQLEN", - "SO_LISTENQLIMIT", - "SO_MARK", - "SO_NETPROC", - "SO_NKE", - "SO_NOADDRERR", - "SO_NOHEADER", - "SO_NOSIGPIPE", - "SO_NOTIFYCONFLICT", - "SO_NO_CHECK", - "SO_NO_DDP", - "SO_NO_OFFLOAD", - "SO_NP_EXTENSIONS", - "SO_NREAD", - "SO_NUMRCVPKT", - "SO_NWRITE", - "SO_OOBINLINE", - "SO_OVERFLOWED", - "SO_PASSCRED", - "SO_PASSSEC", - "SO_PEERCRED", - "SO_PEERLABEL", - "SO_PEERNAME", - "SO_PEERSEC", - "SO_PRIORITY", - "SO_PROTOCOL", - "SO_PROTOTYPE", - "SO_RANDOMPORT", - "SO_RCVBUF", - "SO_RCVBUFFORCE", - "SO_RCVLOWAT", - "SO_RCVTIMEO", - "SO_RESTRICTIONS", - "SO_RESTRICT_DENYIN", - "SO_RESTRICT_DENYOUT", - "SO_RESTRICT_DENYSET", - "SO_REUSEADDR", - "SO_REUSEPORT", - "SO_REUSESHAREUID", - "SO_RTABLE", - "SO_RXQ_OVFL", - "SO_SECURITY_AUTHENTICATION", - "SO_SECURITY_ENCRYPTION_NETWORK", - "SO_SECURITY_ENCRYPTION_TRANSPORT", - "SO_SETFIB", - "SO_SNDBUF", - "SO_SNDBUFFORCE", - "SO_SNDLOWAT", - "SO_SNDTIMEO", - "SO_SPLICE", - "SO_TIMESTAMP", - "SO_TIMESTAMPING", - "SO_TIMESTAMPNS", - "SO_TIMESTAMP_MONOTONIC", - "SO_TYPE", - "SO_UPCALLCLOSEWAIT", - "SO_UPDATE_ACCEPT_CONTEXT", - "SO_UPDATE_CONNECT_CONTEXT", - "SO_USELOOPBACK", - "SO_USER_COOKIE", - "SO_VENDOR", - "SO_WANTMORE", - "SO_WANTOOBFLAG", - "SSLExtraCertChainPolicyPara", - "STANDARD_RIGHTS_ALL", - "STANDARD_RIGHTS_EXECUTE", - "STANDARD_RIGHTS_READ", - "STANDARD_RIGHTS_REQUIRED", - "STANDARD_RIGHTS_WRITE", - "STARTF_USESHOWWINDOW", - "STARTF_USESTDHANDLES", - "STD_ERROR_HANDLE", - "STD_INPUT_HANDLE", - "STD_OUTPUT_HANDLE", - "SUBLANG_ENGLISH_US", - "SW_FORCEMINIMIZE", - "SW_HIDE", - "SW_MAXIMIZE", - "SW_MINIMIZE", - "SW_NORMAL", - "SW_RESTORE", - "SW_SHOW", - "SW_SHOWDEFAULT", - "SW_SHOWMAXIMIZED", - "SW_SHOWMINIMIZED", - "SW_SHOWMINNOACTIVE", - "SW_SHOWNA", - "SW_SHOWNOACTIVATE", - "SW_SHOWNORMAL", - "SYMBOLIC_LINK_FLAG_DIRECTORY", - "SYNCHRONIZE", - "SYSCTL_VERSION", - "SYSCTL_VERS_0", - "SYSCTL_VERS_1", - "SYSCTL_VERS_MASK", - "SYS_ABORT2", - "SYS_ACCEPT", - "SYS_ACCEPT4", - "SYS_ACCEPT_NOCANCEL", - "SYS_ACCESS", - "SYS_ACCESS_EXTENDED", - "SYS_ACCT", - "SYS_ADD_KEY", - "SYS_ADD_PROFIL", - "SYS_ADJFREQ", - "SYS_ADJTIME", - "SYS_ADJTIMEX", - "SYS_AFS_SYSCALL", - "SYS_AIO_CANCEL", - "SYS_AIO_ERROR", - "SYS_AIO_FSYNC", - "SYS_AIO_MLOCK", - "SYS_AIO_READ", - "SYS_AIO_RETURN", - "SYS_AIO_SUSPEND", - "SYS_AIO_SUSPEND_NOCANCEL", - "SYS_AIO_WAITCOMPLETE", - "SYS_AIO_WRITE", - "SYS_ALARM", - "SYS_ARCH_PRCTL", - "SYS_ARM_FADVISE64_64", - "SYS_ARM_SYNC_FILE_RANGE", - "SYS_ATGETMSG", - "SYS_ATPGETREQ", - "SYS_ATPGETRSP", - "SYS_ATPSNDREQ", - "SYS_ATPSNDRSP", - "SYS_ATPUTMSG", - "SYS_ATSOCKET", - "SYS_AUDIT", - "SYS_AUDITCTL", - "SYS_AUDITON", - "SYS_AUDIT_SESSION_JOIN", - "SYS_AUDIT_SESSION_PORT", - "SYS_AUDIT_SESSION_SELF", - "SYS_BDFLUSH", - "SYS_BIND", - "SYS_BINDAT", - "SYS_BREAK", - "SYS_BRK", - "SYS_BSDTHREAD_CREATE", - "SYS_BSDTHREAD_REGISTER", - "SYS_BSDTHREAD_TERMINATE", - "SYS_CAPGET", - "SYS_CAPSET", - "SYS_CAP_ENTER", - "SYS_CAP_FCNTLS_GET", - "SYS_CAP_FCNTLS_LIMIT", - "SYS_CAP_GETMODE", - "SYS_CAP_GETRIGHTS", - "SYS_CAP_IOCTLS_GET", - "SYS_CAP_IOCTLS_LIMIT", - "SYS_CAP_NEW", - "SYS_CAP_RIGHTS_GET", - "SYS_CAP_RIGHTS_LIMIT", - "SYS_CHDIR", - "SYS_CHFLAGS", - "SYS_CHFLAGSAT", - "SYS_CHMOD", - "SYS_CHMOD_EXTENDED", - "SYS_CHOWN", - "SYS_CHOWN32", - "SYS_CHROOT", - "SYS_CHUD", - "SYS_CLOCK_ADJTIME", - "SYS_CLOCK_GETCPUCLOCKID2", - "SYS_CLOCK_GETRES", - "SYS_CLOCK_GETTIME", - "SYS_CLOCK_NANOSLEEP", - "SYS_CLOCK_SETTIME", - "SYS_CLONE", - "SYS_CLOSE", - "SYS_CLOSEFROM", - "SYS_CLOSE_NOCANCEL", - "SYS_CONNECT", - "SYS_CONNECTAT", - "SYS_CONNECT_NOCANCEL", - "SYS_COPYFILE", - "SYS_CPUSET", - "SYS_CPUSET_GETAFFINITY", - "SYS_CPUSET_GETID", - "SYS_CPUSET_SETAFFINITY", - "SYS_CPUSET_SETID", - "SYS_CREAT", - "SYS_CREATE_MODULE", - "SYS_CSOPS", - "SYS_CSOPS_AUDITTOKEN", - "SYS_DELETE", - "SYS_DELETE_MODULE", - "SYS_DUP", - "SYS_DUP2", - "SYS_DUP3", - "SYS_EACCESS", - "SYS_EPOLL_CREATE", - "SYS_EPOLL_CREATE1", - "SYS_EPOLL_CTL", - "SYS_EPOLL_CTL_OLD", - "SYS_EPOLL_PWAIT", - "SYS_EPOLL_WAIT", - "SYS_EPOLL_WAIT_OLD", - "SYS_EVENTFD", - "SYS_EVENTFD2", - "SYS_EXCHANGEDATA", - "SYS_EXECVE", - "SYS_EXIT", - "SYS_EXIT_GROUP", - "SYS_EXTATTRCTL", - "SYS_EXTATTR_DELETE_FD", - "SYS_EXTATTR_DELETE_FILE", - "SYS_EXTATTR_DELETE_LINK", - "SYS_EXTATTR_GET_FD", - "SYS_EXTATTR_GET_FILE", - "SYS_EXTATTR_GET_LINK", - "SYS_EXTATTR_LIST_FD", - "SYS_EXTATTR_LIST_FILE", - "SYS_EXTATTR_LIST_LINK", - "SYS_EXTATTR_SET_FD", - "SYS_EXTATTR_SET_FILE", - "SYS_EXTATTR_SET_LINK", - "SYS_FACCESSAT", - "SYS_FADVISE64", - "SYS_FADVISE64_64", - "SYS_FALLOCATE", - "SYS_FANOTIFY_INIT", - "SYS_FANOTIFY_MARK", - "SYS_FCHDIR", - "SYS_FCHFLAGS", - "SYS_FCHMOD", - "SYS_FCHMODAT", - "SYS_FCHMOD_EXTENDED", - "SYS_FCHOWN", - "SYS_FCHOWN32", - "SYS_FCHOWNAT", - "SYS_FCHROOT", - "SYS_FCNTL", - "SYS_FCNTL64", - "SYS_FCNTL_NOCANCEL", - "SYS_FDATASYNC", - "SYS_FEXECVE", - "SYS_FFCLOCK_GETCOUNTER", - "SYS_FFCLOCK_GETESTIMATE", - "SYS_FFCLOCK_SETESTIMATE", - "SYS_FFSCTL", - "SYS_FGETATTRLIST", - "SYS_FGETXATTR", - "SYS_FHOPEN", - "SYS_FHSTAT", - "SYS_FHSTATFS", - "SYS_FILEPORT_MAKEFD", - "SYS_FILEPORT_MAKEPORT", - "SYS_FKTRACE", - "SYS_FLISTXATTR", - "SYS_FLOCK", - "SYS_FORK", - "SYS_FPATHCONF", - "SYS_FREEBSD6_FTRUNCATE", - "SYS_FREEBSD6_LSEEK", - "SYS_FREEBSD6_MMAP", - "SYS_FREEBSD6_PREAD", - "SYS_FREEBSD6_PWRITE", - "SYS_FREEBSD6_TRUNCATE", - "SYS_FREMOVEXATTR", - "SYS_FSCTL", - "SYS_FSETATTRLIST", - "SYS_FSETXATTR", - "SYS_FSGETPATH", - "SYS_FSTAT", - "SYS_FSTAT64", - "SYS_FSTAT64_EXTENDED", - "SYS_FSTATAT", - "SYS_FSTATAT64", - "SYS_FSTATFS", - "SYS_FSTATFS64", - "SYS_FSTATV", - "SYS_FSTATVFS1", - "SYS_FSTAT_EXTENDED", - "SYS_FSYNC", - "SYS_FSYNC_NOCANCEL", - "SYS_FSYNC_RANGE", - "SYS_FTIME", - "SYS_FTRUNCATE", - "SYS_FTRUNCATE64", - "SYS_FUTEX", - "SYS_FUTIMENS", - "SYS_FUTIMES", - "SYS_FUTIMESAT", - "SYS_GETATTRLIST", - "SYS_GETAUDIT", - "SYS_GETAUDIT_ADDR", - "SYS_GETAUID", - "SYS_GETCONTEXT", - "SYS_GETCPU", - "SYS_GETCWD", - "SYS_GETDENTS", - "SYS_GETDENTS64", - "SYS_GETDIRENTRIES", - "SYS_GETDIRENTRIES64", - "SYS_GETDIRENTRIESATTR", - "SYS_GETDTABLECOUNT", - "SYS_GETDTABLESIZE", - "SYS_GETEGID", - "SYS_GETEGID32", - "SYS_GETEUID", - "SYS_GETEUID32", - "SYS_GETFH", - "SYS_GETFSSTAT", - "SYS_GETFSSTAT64", - "SYS_GETGID", - "SYS_GETGID32", - "SYS_GETGROUPS", - "SYS_GETGROUPS32", - "SYS_GETHOSTUUID", - "SYS_GETITIMER", - "SYS_GETLCID", - "SYS_GETLOGIN", - "SYS_GETLOGINCLASS", - "SYS_GETPEERNAME", - "SYS_GETPGID", - "SYS_GETPGRP", - "SYS_GETPID", - "SYS_GETPMSG", - "SYS_GETPPID", - "SYS_GETPRIORITY", - "SYS_GETRESGID", - "SYS_GETRESGID32", - "SYS_GETRESUID", - "SYS_GETRESUID32", - "SYS_GETRLIMIT", - "SYS_GETRTABLE", - "SYS_GETRUSAGE", - "SYS_GETSGROUPS", - "SYS_GETSID", - "SYS_GETSOCKNAME", - "SYS_GETSOCKOPT", - "SYS_GETTHRID", - "SYS_GETTID", - "SYS_GETTIMEOFDAY", - "SYS_GETUID", - "SYS_GETUID32", - "SYS_GETVFSSTAT", - "SYS_GETWGROUPS", - "SYS_GETXATTR", - "SYS_GET_KERNEL_SYMS", - "SYS_GET_MEMPOLICY", - "SYS_GET_ROBUST_LIST", - "SYS_GET_THREAD_AREA", - "SYS_GSSD_SYSCALL", - "SYS_GTTY", - "SYS_IDENTITYSVC", - "SYS_IDLE", - "SYS_INITGROUPS", - "SYS_INIT_MODULE", - "SYS_INOTIFY_ADD_WATCH", - "SYS_INOTIFY_INIT", - "SYS_INOTIFY_INIT1", - "SYS_INOTIFY_RM_WATCH", - "SYS_IOCTL", - "SYS_IOPERM", - "SYS_IOPL", - "SYS_IOPOLICYSYS", - "SYS_IOPRIO_GET", - "SYS_IOPRIO_SET", - "SYS_IO_CANCEL", - "SYS_IO_DESTROY", - "SYS_IO_GETEVENTS", - "SYS_IO_SETUP", - "SYS_IO_SUBMIT", - "SYS_IPC", - "SYS_ISSETUGID", - "SYS_JAIL", - "SYS_JAIL_ATTACH", - "SYS_JAIL_GET", - "SYS_JAIL_REMOVE", - "SYS_JAIL_SET", - "SYS_KAS_INFO", - "SYS_KDEBUG_TRACE", - "SYS_KENV", - "SYS_KEVENT", - "SYS_KEVENT64", - "SYS_KEXEC_LOAD", - "SYS_KEYCTL", - "SYS_KILL", - "SYS_KLDFIND", - "SYS_KLDFIRSTMOD", - "SYS_KLDLOAD", - "SYS_KLDNEXT", - "SYS_KLDSTAT", - "SYS_KLDSYM", - "SYS_KLDUNLOAD", - "SYS_KLDUNLOADF", - "SYS_KMQ_NOTIFY", - "SYS_KMQ_OPEN", - "SYS_KMQ_SETATTR", - "SYS_KMQ_TIMEDRECEIVE", - "SYS_KMQ_TIMEDSEND", - "SYS_KMQ_UNLINK", - "SYS_KQUEUE", - "SYS_KQUEUE1", - "SYS_KSEM_CLOSE", - "SYS_KSEM_DESTROY", - "SYS_KSEM_GETVALUE", - "SYS_KSEM_INIT", - "SYS_KSEM_OPEN", - "SYS_KSEM_POST", - "SYS_KSEM_TIMEDWAIT", - "SYS_KSEM_TRYWAIT", - "SYS_KSEM_UNLINK", - "SYS_KSEM_WAIT", - "SYS_KTIMER_CREATE", - "SYS_KTIMER_DELETE", - "SYS_KTIMER_GETOVERRUN", - "SYS_KTIMER_GETTIME", - "SYS_KTIMER_SETTIME", - "SYS_KTRACE", - "SYS_LCHFLAGS", - "SYS_LCHMOD", - "SYS_LCHOWN", - "SYS_LCHOWN32", - "SYS_LEDGER", - "SYS_LGETFH", - "SYS_LGETXATTR", - "SYS_LINK", - "SYS_LINKAT", - "SYS_LIO_LISTIO", - "SYS_LISTEN", - "SYS_LISTXATTR", - "SYS_LLISTXATTR", - "SYS_LOCK", - "SYS_LOOKUP_DCOOKIE", - "SYS_LPATHCONF", - "SYS_LREMOVEXATTR", - "SYS_LSEEK", - "SYS_LSETXATTR", - "SYS_LSTAT", - "SYS_LSTAT64", - "SYS_LSTAT64_EXTENDED", - "SYS_LSTATV", - "SYS_LSTAT_EXTENDED", - "SYS_LUTIMES", - "SYS_MAC_SYSCALL", - "SYS_MADVISE", - "SYS_MADVISE1", - "SYS_MAXSYSCALL", - "SYS_MBIND", - "SYS_MIGRATE_PAGES", - "SYS_MINCORE", - "SYS_MINHERIT", - "SYS_MKCOMPLEX", - "SYS_MKDIR", - "SYS_MKDIRAT", - "SYS_MKDIR_EXTENDED", - "SYS_MKFIFO", - "SYS_MKFIFOAT", - "SYS_MKFIFO_EXTENDED", - "SYS_MKNOD", - "SYS_MKNODAT", - "SYS_MLOCK", - "SYS_MLOCKALL", - "SYS_MMAP", - "SYS_MMAP2", - "SYS_MODCTL", - "SYS_MODFIND", - "SYS_MODFNEXT", - "SYS_MODIFY_LDT", - "SYS_MODNEXT", - "SYS_MODSTAT", - "SYS_MODWATCH", - "SYS_MOUNT", - "SYS_MOVE_PAGES", - "SYS_MPROTECT", - "SYS_MPX", - "SYS_MQUERY", - "SYS_MQ_GETSETATTR", - "SYS_MQ_NOTIFY", - "SYS_MQ_OPEN", - "SYS_MQ_TIMEDRECEIVE", - "SYS_MQ_TIMEDSEND", - "SYS_MQ_UNLINK", - "SYS_MREMAP", - "SYS_MSGCTL", - "SYS_MSGGET", - "SYS_MSGRCV", - "SYS_MSGRCV_NOCANCEL", - "SYS_MSGSND", - "SYS_MSGSND_NOCANCEL", - "SYS_MSGSYS", - "SYS_MSYNC", - "SYS_MSYNC_NOCANCEL", - "SYS_MUNLOCK", - "SYS_MUNLOCKALL", - "SYS_MUNMAP", - "SYS_NAME_TO_HANDLE_AT", - "SYS_NANOSLEEP", - "SYS_NEWFSTATAT", - "SYS_NFSCLNT", - "SYS_NFSSERVCTL", - "SYS_NFSSVC", - "SYS_NFSTAT", - "SYS_NICE", - "SYS_NLM_SYSCALL", - "SYS_NLSTAT", - "SYS_NMOUNT", - "SYS_NSTAT", - "SYS_NTP_ADJTIME", - "SYS_NTP_GETTIME", - "SYS_NUMA_GETAFFINITY", - "SYS_NUMA_SETAFFINITY", - "SYS_OABI_SYSCALL_BASE", - "SYS_OBREAK", - "SYS_OLDFSTAT", - "SYS_OLDLSTAT", - "SYS_OLDOLDUNAME", - "SYS_OLDSTAT", - "SYS_OLDUNAME", - "SYS_OPEN", - "SYS_OPENAT", - "SYS_OPENBSD_POLL", - "SYS_OPEN_BY_HANDLE_AT", - "SYS_OPEN_DPROTECTED_NP", - "SYS_OPEN_EXTENDED", - "SYS_OPEN_NOCANCEL", - "SYS_OVADVISE", - "SYS_PACCEPT", - "SYS_PATHCONF", - "SYS_PAUSE", - "SYS_PCICONFIG_IOBASE", - "SYS_PCICONFIG_READ", - "SYS_PCICONFIG_WRITE", - "SYS_PDFORK", - "SYS_PDGETPID", - "SYS_PDKILL", - "SYS_PERF_EVENT_OPEN", - "SYS_PERSONALITY", - "SYS_PID_HIBERNATE", - "SYS_PID_RESUME", - "SYS_PID_SHUTDOWN_SOCKETS", - "SYS_PID_SUSPEND", - "SYS_PIPE", - "SYS_PIPE2", - "SYS_PIVOT_ROOT", - "SYS_PMC_CONTROL", - "SYS_PMC_GET_INFO", - "SYS_POLL", - "SYS_POLLTS", - "SYS_POLL_NOCANCEL", - "SYS_POSIX_FADVISE", - "SYS_POSIX_FALLOCATE", - "SYS_POSIX_OPENPT", - "SYS_POSIX_SPAWN", - "SYS_PPOLL", - "SYS_PRCTL", - "SYS_PREAD", - "SYS_PREAD64", - "SYS_PREADV", - "SYS_PREAD_NOCANCEL", - "SYS_PRLIMIT64", - "SYS_PROCCTL", - "SYS_PROCESS_POLICY", - "SYS_PROCESS_VM_READV", - "SYS_PROCESS_VM_WRITEV", - "SYS_PROC_INFO", - "SYS_PROF", - "SYS_PROFIL", - "SYS_PSELECT", - "SYS_PSELECT6", - "SYS_PSET_ASSIGN", - "SYS_PSET_CREATE", - "SYS_PSET_DESTROY", - "SYS_PSYNCH_CVBROAD", - "SYS_PSYNCH_CVCLRPREPOST", - "SYS_PSYNCH_CVSIGNAL", - "SYS_PSYNCH_CVWAIT", - "SYS_PSYNCH_MUTEXDROP", - "SYS_PSYNCH_MUTEXWAIT", - "SYS_PSYNCH_RW_DOWNGRADE", - "SYS_PSYNCH_RW_LONGRDLOCK", - "SYS_PSYNCH_RW_RDLOCK", - "SYS_PSYNCH_RW_UNLOCK", - "SYS_PSYNCH_RW_UNLOCK2", - "SYS_PSYNCH_RW_UPGRADE", - "SYS_PSYNCH_RW_WRLOCK", - "SYS_PSYNCH_RW_YIELDWRLOCK", - "SYS_PTRACE", - "SYS_PUTPMSG", - "SYS_PWRITE", - "SYS_PWRITE64", - "SYS_PWRITEV", - "SYS_PWRITE_NOCANCEL", - "SYS_QUERY_MODULE", - "SYS_QUOTACTL", - "SYS_RASCTL", - "SYS_RCTL_ADD_RULE", - "SYS_RCTL_GET_LIMITS", - "SYS_RCTL_GET_RACCT", - "SYS_RCTL_GET_RULES", - "SYS_RCTL_REMOVE_RULE", - "SYS_READ", - "SYS_READAHEAD", - "SYS_READDIR", - "SYS_READLINK", - "SYS_READLINKAT", - "SYS_READV", - "SYS_READV_NOCANCEL", - "SYS_READ_NOCANCEL", - "SYS_REBOOT", - "SYS_RECV", - "SYS_RECVFROM", - "SYS_RECVFROM_NOCANCEL", - "SYS_RECVMMSG", - "SYS_RECVMSG", - "SYS_RECVMSG_NOCANCEL", - "SYS_REMAP_FILE_PAGES", - "SYS_REMOVEXATTR", - "SYS_RENAME", - "SYS_RENAMEAT", - "SYS_REQUEST_KEY", - "SYS_RESTART_SYSCALL", - "SYS_REVOKE", - "SYS_RFORK", - "SYS_RMDIR", - "SYS_RTPRIO", - "SYS_RTPRIO_THREAD", - "SYS_RT_SIGACTION", - "SYS_RT_SIGPENDING", - "SYS_RT_SIGPROCMASK", - "SYS_RT_SIGQUEUEINFO", - "SYS_RT_SIGRETURN", - "SYS_RT_SIGSUSPEND", - "SYS_RT_SIGTIMEDWAIT", - "SYS_RT_TGSIGQUEUEINFO", - "SYS_SBRK", - "SYS_SCHED_GETAFFINITY", - "SYS_SCHED_GETPARAM", - "SYS_SCHED_GETSCHEDULER", - "SYS_SCHED_GET_PRIORITY_MAX", - "SYS_SCHED_GET_PRIORITY_MIN", - "SYS_SCHED_RR_GET_INTERVAL", - "SYS_SCHED_SETAFFINITY", - "SYS_SCHED_SETPARAM", - "SYS_SCHED_SETSCHEDULER", - "SYS_SCHED_YIELD", - "SYS_SCTP_GENERIC_RECVMSG", - "SYS_SCTP_GENERIC_SENDMSG", - "SYS_SCTP_GENERIC_SENDMSG_IOV", - "SYS_SCTP_PEELOFF", - "SYS_SEARCHFS", - "SYS_SECURITY", - "SYS_SELECT", - "SYS_SELECT_NOCANCEL", - "SYS_SEMCONFIG", - "SYS_SEMCTL", - "SYS_SEMGET", - "SYS_SEMOP", - "SYS_SEMSYS", - "SYS_SEMTIMEDOP", - "SYS_SEM_CLOSE", - "SYS_SEM_DESTROY", - "SYS_SEM_GETVALUE", - "SYS_SEM_INIT", - "SYS_SEM_OPEN", - "SYS_SEM_POST", - "SYS_SEM_TRYWAIT", - "SYS_SEM_UNLINK", - "SYS_SEM_WAIT", - "SYS_SEM_WAIT_NOCANCEL", - "SYS_SEND", - "SYS_SENDFILE", - "SYS_SENDFILE64", - "SYS_SENDMMSG", - "SYS_SENDMSG", - "SYS_SENDMSG_NOCANCEL", - "SYS_SENDTO", - "SYS_SENDTO_NOCANCEL", - "SYS_SETATTRLIST", - "SYS_SETAUDIT", - "SYS_SETAUDIT_ADDR", - "SYS_SETAUID", - "SYS_SETCONTEXT", - "SYS_SETDOMAINNAME", - "SYS_SETEGID", - "SYS_SETEUID", - "SYS_SETFIB", - "SYS_SETFSGID", - "SYS_SETFSGID32", - "SYS_SETFSUID", - "SYS_SETFSUID32", - "SYS_SETGID", - "SYS_SETGID32", - "SYS_SETGROUPS", - "SYS_SETGROUPS32", - "SYS_SETHOSTNAME", - "SYS_SETITIMER", - "SYS_SETLCID", - "SYS_SETLOGIN", - "SYS_SETLOGINCLASS", - "SYS_SETNS", - "SYS_SETPGID", - "SYS_SETPRIORITY", - "SYS_SETPRIVEXEC", - "SYS_SETREGID", - "SYS_SETREGID32", - "SYS_SETRESGID", - "SYS_SETRESGID32", - "SYS_SETRESUID", - "SYS_SETRESUID32", - "SYS_SETREUID", - "SYS_SETREUID32", - "SYS_SETRLIMIT", - "SYS_SETRTABLE", - "SYS_SETSGROUPS", - "SYS_SETSID", - "SYS_SETSOCKOPT", - "SYS_SETTID", - "SYS_SETTID_WITH_PID", - "SYS_SETTIMEOFDAY", - "SYS_SETUID", - "SYS_SETUID32", - "SYS_SETWGROUPS", - "SYS_SETXATTR", - "SYS_SET_MEMPOLICY", - "SYS_SET_ROBUST_LIST", - "SYS_SET_THREAD_AREA", - "SYS_SET_TID_ADDRESS", - "SYS_SGETMASK", - "SYS_SHARED_REGION_CHECK_NP", - "SYS_SHARED_REGION_MAP_AND_SLIDE_NP", - "SYS_SHMAT", - "SYS_SHMCTL", - "SYS_SHMDT", - "SYS_SHMGET", - "SYS_SHMSYS", - "SYS_SHM_OPEN", - "SYS_SHM_UNLINK", - "SYS_SHUTDOWN", - "SYS_SIGACTION", - "SYS_SIGALTSTACK", - "SYS_SIGNAL", - "SYS_SIGNALFD", - "SYS_SIGNALFD4", - "SYS_SIGPENDING", - "SYS_SIGPROCMASK", - "SYS_SIGQUEUE", - "SYS_SIGQUEUEINFO", - "SYS_SIGRETURN", - "SYS_SIGSUSPEND", - "SYS_SIGSUSPEND_NOCANCEL", - "SYS_SIGTIMEDWAIT", - "SYS_SIGWAIT", - "SYS_SIGWAITINFO", - "SYS_SOCKET", - "SYS_SOCKETCALL", - "SYS_SOCKETPAIR", - "SYS_SPLICE", - "SYS_SSETMASK", - "SYS_SSTK", - "SYS_STACK_SNAPSHOT", - "SYS_STAT", - "SYS_STAT64", - "SYS_STAT64_EXTENDED", - "SYS_STATFS", - "SYS_STATFS64", - "SYS_STATV", - "SYS_STATVFS1", - "SYS_STAT_EXTENDED", - "SYS_STIME", - "SYS_STTY", - "SYS_SWAPCONTEXT", - "SYS_SWAPCTL", - "SYS_SWAPOFF", - "SYS_SWAPON", - "SYS_SYMLINK", - "SYS_SYMLINKAT", - "SYS_SYNC", - "SYS_SYNCFS", - "SYS_SYNC_FILE_RANGE", - "SYS_SYSARCH", - "SYS_SYSCALL", - "SYS_SYSCALL_BASE", - "SYS_SYSFS", - "SYS_SYSINFO", - "SYS_SYSLOG", - "SYS_TEE", - "SYS_TGKILL", - "SYS_THREAD_SELFID", - "SYS_THR_CREATE", - "SYS_THR_EXIT", - "SYS_THR_KILL", - "SYS_THR_KILL2", - "SYS_THR_NEW", - "SYS_THR_SELF", - "SYS_THR_SET_NAME", - "SYS_THR_SUSPEND", - "SYS_THR_WAKE", - "SYS_TIME", - "SYS_TIMERFD_CREATE", - "SYS_TIMERFD_GETTIME", - "SYS_TIMERFD_SETTIME", - "SYS_TIMER_CREATE", - "SYS_TIMER_DELETE", - "SYS_TIMER_GETOVERRUN", - "SYS_TIMER_GETTIME", - "SYS_TIMER_SETTIME", - "SYS_TIMES", - "SYS_TKILL", - "SYS_TRUNCATE", - "SYS_TRUNCATE64", - "SYS_TUXCALL", - "SYS_UGETRLIMIT", - "SYS_ULIMIT", - "SYS_UMASK", - "SYS_UMASK_EXTENDED", - "SYS_UMOUNT", - "SYS_UMOUNT2", - "SYS_UNAME", - "SYS_UNDELETE", - "SYS_UNLINK", - "SYS_UNLINKAT", - "SYS_UNMOUNT", - "SYS_UNSHARE", - "SYS_USELIB", - "SYS_USTAT", - "SYS_UTIME", - "SYS_UTIMENSAT", - "SYS_UTIMES", - "SYS_UTRACE", - "SYS_UUIDGEN", - "SYS_VADVISE", - "SYS_VFORK", - "SYS_VHANGUP", - "SYS_VM86", - "SYS_VM86OLD", - "SYS_VMSPLICE", - "SYS_VM_PRESSURE_MONITOR", - "SYS_VSERVER", - "SYS_WAIT4", - "SYS_WAIT4_NOCANCEL", - "SYS_WAIT6", - "SYS_WAITEVENT", - "SYS_WAITID", - "SYS_WAITID_NOCANCEL", - "SYS_WAITPID", - "SYS_WATCHEVENT", - "SYS_WORKQ_KERNRETURN", - "SYS_WORKQ_OPEN", - "SYS_WRITE", - "SYS_WRITEV", - "SYS_WRITEV_NOCANCEL", - "SYS_WRITE_NOCANCEL", - "SYS_YIELD", - "SYS__LLSEEK", - "SYS__LWP_CONTINUE", - "SYS__LWP_CREATE", - "SYS__LWP_CTL", - "SYS__LWP_DETACH", - "SYS__LWP_EXIT", - "SYS__LWP_GETNAME", - "SYS__LWP_GETPRIVATE", - "SYS__LWP_KILL", - "SYS__LWP_PARK", - "SYS__LWP_SELF", - "SYS__LWP_SETNAME", - "SYS__LWP_SETPRIVATE", - "SYS__LWP_SUSPEND", - "SYS__LWP_UNPARK", - "SYS__LWP_UNPARK_ALL", - "SYS__LWP_WAIT", - "SYS__LWP_WAKEUP", - "SYS__NEWSELECT", - "SYS__PSET_BIND", - "SYS__SCHED_GETAFFINITY", - "SYS__SCHED_GETPARAM", - "SYS__SCHED_SETAFFINITY", - "SYS__SCHED_SETPARAM", - "SYS__SYSCTL", - "SYS__UMTX_LOCK", - "SYS__UMTX_OP", - "SYS__UMTX_UNLOCK", - "SYS___ACL_ACLCHECK_FD", - "SYS___ACL_ACLCHECK_FILE", - "SYS___ACL_ACLCHECK_LINK", - "SYS___ACL_DELETE_FD", - "SYS___ACL_DELETE_FILE", - "SYS___ACL_DELETE_LINK", - "SYS___ACL_GET_FD", - "SYS___ACL_GET_FILE", - "SYS___ACL_GET_LINK", - "SYS___ACL_SET_FD", - "SYS___ACL_SET_FILE", - "SYS___ACL_SET_LINK", - "SYS___CAP_RIGHTS_GET", - "SYS___CLONE", - "SYS___DISABLE_THREADSIGNAL", - "SYS___GETCWD", - "SYS___GETLOGIN", - "SYS___GET_TCB", - "SYS___MAC_EXECVE", - "SYS___MAC_GETFSSTAT", - "SYS___MAC_GET_FD", - "SYS___MAC_GET_FILE", - "SYS___MAC_GET_LCID", - "SYS___MAC_GET_LCTX", - "SYS___MAC_GET_LINK", - "SYS___MAC_GET_MOUNT", - "SYS___MAC_GET_PID", - "SYS___MAC_GET_PROC", - "SYS___MAC_MOUNT", - "SYS___MAC_SET_FD", - "SYS___MAC_SET_FILE", - "SYS___MAC_SET_LCTX", - "SYS___MAC_SET_LINK", - "SYS___MAC_SET_PROC", - "SYS___MAC_SYSCALL", - "SYS___OLD_SEMWAIT_SIGNAL", - "SYS___OLD_SEMWAIT_SIGNAL_NOCANCEL", - "SYS___POSIX_CHOWN", - "SYS___POSIX_FCHOWN", - "SYS___POSIX_LCHOWN", - "SYS___POSIX_RENAME", - "SYS___PTHREAD_CANCELED", - "SYS___PTHREAD_CHDIR", - "SYS___PTHREAD_FCHDIR", - "SYS___PTHREAD_KILL", - "SYS___PTHREAD_MARKCANCEL", - "SYS___PTHREAD_SIGMASK", - "SYS___QUOTACTL", - "SYS___SEMCTL", - "SYS___SEMWAIT_SIGNAL", - "SYS___SEMWAIT_SIGNAL_NOCANCEL", - "SYS___SETLOGIN", - "SYS___SETUGID", - "SYS___SET_TCB", - "SYS___SIGACTION_SIGTRAMP", - "SYS___SIGTIMEDWAIT", - "SYS___SIGWAIT", - "SYS___SIGWAIT_NOCANCEL", - "SYS___SYSCTL", - "SYS___TFORK", - "SYS___THREXIT", - "SYS___THRSIGDIVERT", - "SYS___THRSLEEP", - "SYS___THRWAKEUP", - "S_ARCH1", - "S_ARCH2", - "S_BLKSIZE", - "S_IEXEC", - "S_IFBLK", - "S_IFCHR", - "S_IFDIR", - "S_IFIFO", - "S_IFLNK", - "S_IFMT", - "S_IFREG", - "S_IFSOCK", - "S_IFWHT", - "S_IREAD", - "S_IRGRP", - "S_IROTH", - "S_IRUSR", - "S_IRWXG", - "S_IRWXO", - "S_IRWXU", - "S_ISGID", - "S_ISTXT", - "S_ISUID", - "S_ISVTX", - "S_IWGRP", - "S_IWOTH", - "S_IWRITE", - "S_IWUSR", - "S_IXGRP", - "S_IXOTH", - "S_IXUSR", - "S_LOGIN_SET", - "SecurityAttributes", - "Seek", - "Select", - "Sendfile", - "Sendmsg", - "SendmsgN", - "Sendto", - "Servent", - "SetBpf", - "SetBpfBuflen", - "SetBpfDatalink", - "SetBpfHeadercmpl", - "SetBpfImmediate", - "SetBpfInterface", - "SetBpfPromisc", - "SetBpfTimeout", - "SetCurrentDirectory", - "SetEndOfFile", - "SetEnvironmentVariable", - "SetFileAttributes", - "SetFileCompletionNotificationModes", - "SetFilePointer", - "SetFileTime", - "SetHandleInformation", - "SetKevent", - "SetLsfPromisc", - "SetNonblock", - "Setdomainname", - "Setegid", - "Setenv", - "Seteuid", - "Setfsgid", - "Setfsuid", - "Setgid", - "Setgroups", - "Sethostname", - "Setlogin", - "Setpgid", - "Setpriority", - "Setprivexec", - "Setregid", - "Setresgid", - "Setresuid", - "Setreuid", - "Setrlimit", - "Setsid", - "Setsockopt", - "SetsockoptByte", - "SetsockoptICMPv6Filter", - "SetsockoptIPMreq", - "SetsockoptIPMreqn", - "SetsockoptIPv6Mreq", - "SetsockoptInet4Addr", - "SetsockoptInt", - "SetsockoptLinger", - "SetsockoptString", - "SetsockoptTimeval", - "Settimeofday", - "Setuid", - "Setxattr", - "Shutdown", - "SidTypeAlias", - "SidTypeComputer", - "SidTypeDeletedAccount", - "SidTypeDomain", - "SidTypeGroup", - "SidTypeInvalid", - "SidTypeLabel", - "SidTypeUnknown", - "SidTypeUser", - "SidTypeWellKnownGroup", - "Signal", - "SizeofBpfHdr", - "SizeofBpfInsn", - "SizeofBpfProgram", - "SizeofBpfStat", - "SizeofBpfVersion", - "SizeofBpfZbuf", - "SizeofBpfZbufHeader", - "SizeofCmsghdr", - "SizeofICMPv6Filter", - "SizeofIPMreq", - "SizeofIPMreqn", - "SizeofIPv6MTUInfo", - "SizeofIPv6Mreq", - "SizeofIfAddrmsg", - "SizeofIfAnnounceMsghdr", - "SizeofIfData", - "SizeofIfInfomsg", - "SizeofIfMsghdr", - "SizeofIfaMsghdr", - "SizeofIfmaMsghdr", - "SizeofIfmaMsghdr2", - "SizeofInet4Pktinfo", - "SizeofInet6Pktinfo", - "SizeofInotifyEvent", - "SizeofLinger", - "SizeofMsghdr", - "SizeofNlAttr", - "SizeofNlMsgerr", - "SizeofNlMsghdr", - "SizeofRtAttr", - "SizeofRtGenmsg", - "SizeofRtMetrics", - "SizeofRtMsg", - "SizeofRtMsghdr", - "SizeofRtNexthop", - "SizeofSockFilter", - "SizeofSockFprog", - "SizeofSockaddrAny", - "SizeofSockaddrDatalink", - "SizeofSockaddrInet4", - "SizeofSockaddrInet6", - "SizeofSockaddrLinklayer", - "SizeofSockaddrNetlink", - "SizeofSockaddrUnix", - "SizeofTCPInfo", - "SizeofUcred", - "SlicePtrFromStrings", - "SockFilter", - "SockFprog", - "Sockaddr", - "SockaddrDatalink", - "SockaddrGen", - "SockaddrInet4", - "SockaddrInet6", - "SockaddrLinklayer", - "SockaddrNetlink", - "SockaddrUnix", - "Socket", - "SocketControlMessage", - "SocketDisableIPv6", - "Socketpair", - "Splice", - "StartProcess", - "StartupInfo", - "Stat", - "Stat_t", - "Statfs", - "Statfs_t", - "Stderr", - "Stdin", - "Stdout", - "StringBytePtr", - "StringByteSlice", - "StringSlicePtr", - "StringToSid", - "StringToUTF16", - "StringToUTF16Ptr", - "Symlink", - "Sync", - "SyncFileRange", - "SysProcAttr", - "SysProcIDMap", - "Syscall", - "Syscall12", - "Syscall15", - "Syscall18", - "Syscall6", - "Syscall9", - "SyscallN", - "Sysctl", - "SysctlUint32", - "Sysctlnode", - "Sysinfo", - "Sysinfo_t", - "Systemtime", - "TCGETS", - "TCIFLUSH", - "TCIOFLUSH", - "TCOFLUSH", - "TCPInfo", - "TCPKeepalive", - "TCP_CA_NAME_MAX", - "TCP_CONGCTL", - "TCP_CONGESTION", - "TCP_CONNECTIONTIMEOUT", - "TCP_CORK", - "TCP_DEFER_ACCEPT", - "TCP_ENABLE_ECN", - "TCP_INFO", - "TCP_KEEPALIVE", - "TCP_KEEPCNT", - "TCP_KEEPIDLE", - "TCP_KEEPINIT", - "TCP_KEEPINTVL", - "TCP_LINGER2", - "TCP_MAXBURST", - "TCP_MAXHLEN", - "TCP_MAXOLEN", - "TCP_MAXSEG", - "TCP_MAXWIN", - "TCP_MAX_SACK", - "TCP_MAX_WINSHIFT", - "TCP_MD5SIG", - "TCP_MD5SIG_MAXKEYLEN", - "TCP_MINMSS", - "TCP_MINMSSOVERLOAD", - "TCP_MSS", - "TCP_NODELAY", - "TCP_NOOPT", - "TCP_NOPUSH", - "TCP_NOTSENT_LOWAT", - "TCP_NSTATES", - "TCP_QUICKACK", - "TCP_RXT_CONNDROPTIME", - "TCP_RXT_FINDROP", - "TCP_SACK_ENABLE", - "TCP_SENDMOREACKS", - "TCP_SYNCNT", - "TCP_VENDOR", - "TCP_WINDOW_CLAMP", - "TCSAFLUSH", - "TCSETS", - "TF_DISCONNECT", - "TF_REUSE_SOCKET", - "TF_USE_DEFAULT_WORKER", - "TF_USE_KERNEL_APC", - "TF_USE_SYSTEM_THREAD", - "TF_WRITE_BEHIND", - "TH32CS_INHERIT", - "TH32CS_SNAPALL", - "TH32CS_SNAPHEAPLIST", - "TH32CS_SNAPMODULE", - "TH32CS_SNAPMODULE32", - "TH32CS_SNAPPROCESS", - "TH32CS_SNAPTHREAD", - "TIME_ZONE_ID_DAYLIGHT", - "TIME_ZONE_ID_STANDARD", - "TIME_ZONE_ID_UNKNOWN", - "TIOCCBRK", - "TIOCCDTR", - "TIOCCONS", - "TIOCDCDTIMESTAMP", - "TIOCDRAIN", - "TIOCDSIMICROCODE", - "TIOCEXCL", - "TIOCEXT", - "TIOCFLAG_CDTRCTS", - "TIOCFLAG_CLOCAL", - "TIOCFLAG_CRTSCTS", - "TIOCFLAG_MDMBUF", - "TIOCFLAG_PPS", - "TIOCFLAG_SOFTCAR", - "TIOCFLUSH", - "TIOCGDEV", - "TIOCGDRAINWAIT", - "TIOCGETA", - "TIOCGETD", - "TIOCGFLAGS", - "TIOCGICOUNT", - "TIOCGLCKTRMIOS", - "TIOCGLINED", - "TIOCGPGRP", - "TIOCGPTN", - "TIOCGQSIZE", - "TIOCGRANTPT", - "TIOCGRS485", - "TIOCGSERIAL", - "TIOCGSID", - "TIOCGSIZE", - "TIOCGSOFTCAR", - "TIOCGTSTAMP", - "TIOCGWINSZ", - "TIOCINQ", - "TIOCIXOFF", - "TIOCIXON", - "TIOCLINUX", - "TIOCMBIC", - "TIOCMBIS", - "TIOCMGDTRWAIT", - "TIOCMGET", - "TIOCMIWAIT", - "TIOCMODG", - "TIOCMODS", - "TIOCMSDTRWAIT", - "TIOCMSET", - "TIOCM_CAR", - "TIOCM_CD", - "TIOCM_CTS", - "TIOCM_DCD", - "TIOCM_DSR", - "TIOCM_DTR", - "TIOCM_LE", - "TIOCM_RI", - "TIOCM_RNG", - "TIOCM_RTS", - "TIOCM_SR", - "TIOCM_ST", - "TIOCNOTTY", - "TIOCNXCL", - "TIOCOUTQ", - "TIOCPKT", - "TIOCPKT_DATA", - "TIOCPKT_DOSTOP", - "TIOCPKT_FLUSHREAD", - "TIOCPKT_FLUSHWRITE", - "TIOCPKT_IOCTL", - "TIOCPKT_NOSTOP", - "TIOCPKT_START", - "TIOCPKT_STOP", - "TIOCPTMASTER", - "TIOCPTMGET", - "TIOCPTSNAME", - "TIOCPTYGNAME", - "TIOCPTYGRANT", - "TIOCPTYUNLK", - "TIOCRCVFRAME", - "TIOCREMOTE", - "TIOCSBRK", - "TIOCSCONS", - "TIOCSCTTY", - "TIOCSDRAINWAIT", - "TIOCSDTR", - "TIOCSERCONFIG", - "TIOCSERGETLSR", - "TIOCSERGETMULTI", - "TIOCSERGSTRUCT", - "TIOCSERGWILD", - "TIOCSERSETMULTI", - "TIOCSERSWILD", - "TIOCSER_TEMT", - "TIOCSETA", - "TIOCSETAF", - "TIOCSETAW", - "TIOCSETD", - "TIOCSFLAGS", - "TIOCSIG", - "TIOCSLCKTRMIOS", - "TIOCSLINED", - "TIOCSPGRP", - "TIOCSPTLCK", - "TIOCSQSIZE", - "TIOCSRS485", - "TIOCSSERIAL", - "TIOCSSIZE", - "TIOCSSOFTCAR", - "TIOCSTART", - "TIOCSTAT", - "TIOCSTI", - "TIOCSTOP", - "TIOCSTSTAMP", - "TIOCSWINSZ", - "TIOCTIMESTAMP", - "TIOCUCNTL", - "TIOCVHANGUP", - "TIOCXMTFRAME", - "TOKEN_ADJUST_DEFAULT", - "TOKEN_ADJUST_GROUPS", - "TOKEN_ADJUST_PRIVILEGES", - "TOKEN_ADJUST_SESSIONID", - "TOKEN_ALL_ACCESS", - "TOKEN_ASSIGN_PRIMARY", - "TOKEN_DUPLICATE", - "TOKEN_EXECUTE", - "TOKEN_IMPERSONATE", - "TOKEN_QUERY", - "TOKEN_QUERY_SOURCE", - "TOKEN_READ", - "TOKEN_WRITE", - "TOSTOP", - "TRUNCATE_EXISTING", - "TUNATTACHFILTER", - "TUNDETACHFILTER", - "TUNGETFEATURES", - "TUNGETIFF", - "TUNGETSNDBUF", - "TUNGETVNETHDRSZ", - "TUNSETDEBUG", - "TUNSETGROUP", - "TUNSETIFF", - "TUNSETLINK", - "TUNSETNOCSUM", - "TUNSETOFFLOAD", - "TUNSETOWNER", - "TUNSETPERSIST", - "TUNSETSNDBUF", - "TUNSETTXFILTER", - "TUNSETVNETHDRSZ", - "Tee", - "TerminateProcess", - "Termios", - "Tgkill", - "Time", - "Time_t", - "Times", - "Timespec", - "TimespecToNsec", - "Timeval", - "Timeval32", - "TimevalToNsec", - "Timex", - "Timezoneinformation", - "Tms", - "Token", - "TokenAccessInformation", - "TokenAuditPolicy", - "TokenDefaultDacl", - "TokenElevation", - "TokenElevationType", - "TokenGroups", - "TokenGroupsAndPrivileges", - "TokenHasRestrictions", - "TokenImpersonationLevel", - "TokenIntegrityLevel", - "TokenLinkedToken", - "TokenLogonSid", - "TokenMandatoryPolicy", - "TokenOrigin", - "TokenOwner", - "TokenPrimaryGroup", - "TokenPrivileges", - "TokenRestrictedSids", - "TokenSandBoxInert", - "TokenSessionId", - "TokenSessionReference", - "TokenSource", - "TokenStatistics", - "TokenType", - "TokenUIAccess", - "TokenUser", - "TokenVirtualizationAllowed", - "TokenVirtualizationEnabled", - "Tokenprimarygroup", - "Tokenuser", - "TranslateAccountName", - "TranslateName", - "TransmitFile", - "TransmitFileBuffers", - "Truncate", - "UNIX_PATH_MAX", - "USAGE_MATCH_TYPE_AND", - "USAGE_MATCH_TYPE_OR", - "UTF16FromString", - "UTF16PtrFromString", - "UTF16ToString", - "Ucred", - "Umask", - "Uname", - "Undelete", - "UnixCredentials", - "UnixRights", - "Unlink", - "Unlinkat", - "UnmapViewOfFile", - "Unmount", - "Unsetenv", - "Unshare", - "UserInfo10", - "Ustat", - "Ustat_t", - "Utimbuf", - "Utime", - "Utimes", - "UtimesNano", - "Utsname", - "VDISCARD", - "VDSUSP", - "VEOF", - "VEOL", - "VEOL2", - "VERASE", - "VERASE2", - "VINTR", - "VKILL", - "VLNEXT", - "VMIN", - "VQUIT", - "VREPRINT", - "VSTART", - "VSTATUS", - "VSTOP", - "VSUSP", - "VSWTC", - "VT0", - "VT1", - "VTDLY", - "VTIME", - "VWERASE", - "VirtualLock", - "VirtualUnlock", - "WAIT_ABANDONED", - "WAIT_FAILED", - "WAIT_OBJECT_0", - "WAIT_TIMEOUT", - "WALL", - "WALLSIG", - "WALTSIG", - "WCLONE", - "WCONTINUED", - "WCOREFLAG", - "WEXITED", - "WLINUXCLONE", - "WNOHANG", - "WNOTHREAD", - "WNOWAIT", - "WNOZOMBIE", - "WOPTSCHECKED", - "WORDSIZE", - "WSABuf", - "WSACleanup", - "WSADESCRIPTION_LEN", - "WSAData", - "WSAEACCES", - "WSAECONNABORTED", - "WSAECONNRESET", - "WSAEnumProtocols", - "WSAID_CONNECTEX", - "WSAIoctl", - "WSAPROTOCOL_LEN", - "WSAProtocolChain", - "WSAProtocolInfo", - "WSARecv", - "WSARecvFrom", - "WSASYS_STATUS_LEN", - "WSASend", - "WSASendTo", - "WSASendto", - "WSAStartup", - "WSTOPPED", - "WTRAPPED", - "WUNTRACED", - "Wait4", - "WaitForSingleObject", - "WaitStatus", - "Win32FileAttributeData", - "Win32finddata", - "Write", - "WriteConsole", - "WriteFile", - "X509_ASN_ENCODING", - "XCASE", - "XP1_CONNECTIONLESS", - "XP1_CONNECT_DATA", - "XP1_DISCONNECT_DATA", - "XP1_EXPEDITED_DATA", - "XP1_GRACEFUL_CLOSE", - "XP1_GUARANTEED_DELIVERY", - "XP1_GUARANTEED_ORDER", - "XP1_IFS_HANDLES", - "XP1_MESSAGE_ORIENTED", - "XP1_MULTIPOINT_CONTROL_PLANE", - "XP1_MULTIPOINT_DATA_PLANE", - "XP1_PARTIAL_MESSAGE", - "XP1_PSEUDO_STREAM", - "XP1_QOS_SUPPORTED", - "XP1_SAN_SUPPORT_SDP", - "XP1_SUPPORT_BROADCAST", - "XP1_SUPPORT_MULTIPOINT", - "XP1_UNI_RECV", - "XP1_UNI_SEND", - }, - "syscall/js": { - "CopyBytesToGo", - "CopyBytesToJS", - "Error", - "Func", - "FuncOf", - "Global", - "Null", - "Type", - "TypeBoolean", - "TypeFunction", - "TypeNull", - "TypeNumber", - "TypeObject", - "TypeString", - "TypeSymbol", - "TypeUndefined", - "Undefined", - "Value", - "ValueError", - "ValueOf", - }, - "testing": { - "AllocsPerRun", - "B", - "Benchmark", - "BenchmarkResult", - "Cover", - "CoverBlock", - "CoverMode", - "Coverage", - "F", - "Init", - "InternalBenchmark", - "InternalExample", - "InternalFuzzTarget", - "InternalTest", - "M", - "Main", - "MainStart", - "PB", - "RegisterCover", - "RunBenchmarks", - "RunExamples", - "RunTests", - "Short", - "T", - "TB", - "Testing", - "Verbose", - }, - "testing/fstest": { - "MapFS", - "MapFile", - "TestFS", - }, - "testing/iotest": { - "DataErrReader", - "ErrReader", - "ErrTimeout", - "HalfReader", - "NewReadLogger", - "NewWriteLogger", - "OneByteReader", - "TestReader", - "TimeoutReader", - "TruncateWriter", - }, - "testing/quick": { - "Check", - "CheckEqual", - "CheckEqualError", - "CheckError", - "Config", - "Generator", - "SetupError", - "Value", - }, - "testing/slogtest": { - "TestHandler", - }, - "text/scanner": { - "Char", - "Comment", - "EOF", - "Float", - "GoTokens", - "GoWhitespace", - "Ident", - "Int", - "Position", - "RawString", - "ScanChars", - "ScanComments", - "ScanFloats", - "ScanIdents", - "ScanInts", - "ScanRawStrings", - "ScanStrings", - "Scanner", - "SkipComments", - "String", - "TokenString", - }, - "text/tabwriter": { - "AlignRight", - "Debug", - "DiscardEmptyColumns", - "Escape", - "FilterHTML", - "NewWriter", - "StripEscape", - "TabIndent", - "Writer", - }, - "text/template": { - "ExecError", - "FuncMap", - "HTMLEscape", - "HTMLEscapeString", - "HTMLEscaper", - "IsTrue", - "JSEscape", - "JSEscapeString", - "JSEscaper", - "Must", - "New", - "ParseFS", - "ParseFiles", - "ParseGlob", - "Template", - "URLQueryEscaper", - }, - "text/template/parse": { - "ActionNode", - "BoolNode", - "BranchNode", - "BreakNode", - "ChainNode", - "CommandNode", - "CommentNode", - "ContinueNode", - "DotNode", - "FieldNode", - "IdentifierNode", - "IfNode", - "IsEmptyTree", - "ListNode", - "Mode", - "New", - "NewIdentifier", - "NilNode", - "Node", - "NodeAction", - "NodeBool", - "NodeBreak", - "NodeChain", - "NodeCommand", - "NodeComment", - "NodeContinue", - "NodeDot", - "NodeField", - "NodeIdentifier", - "NodeIf", - "NodeList", - "NodeNil", - "NodeNumber", - "NodePipe", - "NodeRange", - "NodeString", - "NodeTemplate", - "NodeText", - "NodeType", - "NodeVariable", - "NodeWith", - "NumberNode", - "Parse", - "ParseComments", - "PipeNode", - "Pos", - "RangeNode", - "SkipFuncCheck", - "StringNode", - "TemplateNode", - "TextNode", - "Tree", - "VariableNode", - "WithNode", - }, - "time": { - "ANSIC", - "After", - "AfterFunc", - "April", - "August", - "Date", - "DateOnly", - "DateTime", - "December", - "Duration", - "February", - "FixedZone", - "Friday", - "Hour", - "January", - "July", - "June", - "Kitchen", - "Layout", - "LoadLocation", - "LoadLocationFromTZData", - "Local", - "Location", - "March", - "May", - "Microsecond", - "Millisecond", - "Minute", - "Monday", - "Month", - "Nanosecond", - "NewTicker", - "NewTimer", - "November", - "Now", - "October", - "Parse", - "ParseDuration", - "ParseError", - "ParseInLocation", - "RFC1123", - "RFC1123Z", - "RFC3339", - "RFC3339Nano", - "RFC822", - "RFC822Z", - "RFC850", - "RubyDate", - "Saturday", - "Second", - "September", - "Since", - "Sleep", - "Stamp", - "StampMicro", - "StampMilli", - "StampNano", - "Sunday", - "Thursday", - "Tick", - "Ticker", - "Time", - "TimeOnly", - "Timer", - "Tuesday", - "UTC", - "Unix", - "UnixDate", - "UnixMicro", - "UnixMilli", - "Until", - "Wednesday", - "Weekday", - }, - "unicode": { - "ASCII_Hex_Digit", - "Adlam", - "Ahom", - "Anatolian_Hieroglyphs", - "Arabic", - "Armenian", - "Avestan", - "AzeriCase", - "Balinese", - "Bamum", - "Bassa_Vah", - "Batak", - "Bengali", - "Bhaiksuki", - "Bidi_Control", - "Bopomofo", - "Brahmi", - "Braille", - "Buginese", - "Buhid", - "C", - "Canadian_Aboriginal", - "Carian", - "CaseRange", - "CaseRanges", - "Categories", - "Caucasian_Albanian", - "Cc", - "Cf", - "Chakma", - "Cham", - "Cherokee", - "Chorasmian", - "Co", - "Common", - "Coptic", - "Cs", - "Cuneiform", - "Cypriot", - "Cypro_Minoan", - "Cyrillic", - "Dash", - "Deprecated", - "Deseret", - "Devanagari", - "Diacritic", - "Digit", - "Dives_Akuru", - "Dogra", - "Duployan", - "Egyptian_Hieroglyphs", - "Elbasan", - "Elymaic", - "Ethiopic", - "Extender", - "FoldCategory", - "FoldScript", - "Georgian", - "Glagolitic", - "Gothic", - "Grantha", - "GraphicRanges", - "Greek", - "Gujarati", - "Gunjala_Gondi", - "Gurmukhi", - "Han", - "Hangul", - "Hanifi_Rohingya", - "Hanunoo", - "Hatran", - "Hebrew", - "Hex_Digit", - "Hiragana", - "Hyphen", - "IDS_Binary_Operator", - "IDS_Trinary_Operator", - "Ideographic", - "Imperial_Aramaic", - "In", - "Inherited", - "Inscriptional_Pahlavi", - "Inscriptional_Parthian", - "Is", - "IsControl", - "IsDigit", - "IsGraphic", - "IsLetter", - "IsLower", - "IsMark", - "IsNumber", - "IsOneOf", - "IsPrint", - "IsPunct", - "IsSpace", - "IsSymbol", - "IsTitle", - "IsUpper", - "Javanese", - "Join_Control", - "Kaithi", - "Kannada", - "Katakana", - "Kawi", - "Kayah_Li", - "Kharoshthi", - "Khitan_Small_Script", - "Khmer", - "Khojki", - "Khudawadi", - "L", - "Lao", - "Latin", - "Lepcha", - "Letter", - "Limbu", - "Linear_A", - "Linear_B", - "Lisu", - "Ll", - "Lm", - "Lo", - "Logical_Order_Exception", - "Lower", - "LowerCase", - "Lt", - "Lu", - "Lycian", - "Lydian", - "M", - "Mahajani", - "Makasar", - "Malayalam", - "Mandaic", - "Manichaean", - "Marchen", - "Mark", - "Masaram_Gondi", - "MaxASCII", - "MaxCase", - "MaxLatin1", - "MaxRune", - "Mc", - "Me", - "Medefaidrin", - "Meetei_Mayek", - "Mende_Kikakui", - "Meroitic_Cursive", - "Meroitic_Hieroglyphs", - "Miao", - "Mn", - "Modi", - "Mongolian", - "Mro", - "Multani", - "Myanmar", - "N", - "Nabataean", - "Nag_Mundari", - "Nandinagari", - "Nd", - "New_Tai_Lue", - "Newa", - "Nko", - "Nl", - "No", - "Noncharacter_Code_Point", - "Number", - "Nushu", - "Nyiakeng_Puachue_Hmong", - "Ogham", - "Ol_Chiki", - "Old_Hungarian", - "Old_Italic", - "Old_North_Arabian", - "Old_Permic", - "Old_Persian", - "Old_Sogdian", - "Old_South_Arabian", - "Old_Turkic", - "Old_Uyghur", - "Oriya", - "Osage", - "Osmanya", - "Other", - "Other_Alphabetic", - "Other_Default_Ignorable_Code_Point", - "Other_Grapheme_Extend", - "Other_ID_Continue", - "Other_ID_Start", - "Other_Lowercase", - "Other_Math", - "Other_Uppercase", - "P", - "Pahawh_Hmong", - "Palmyrene", - "Pattern_Syntax", - "Pattern_White_Space", - "Pau_Cin_Hau", - "Pc", - "Pd", - "Pe", - "Pf", - "Phags_Pa", - "Phoenician", - "Pi", - "Po", - "Prepended_Concatenation_Mark", - "PrintRanges", - "Properties", - "Ps", - "Psalter_Pahlavi", - "Punct", - "Quotation_Mark", - "Radical", - "Range16", - "Range32", - "RangeTable", - "Regional_Indicator", - "Rejang", - "ReplacementChar", - "Runic", - "S", - "STerm", - "Samaritan", - "Saurashtra", - "Sc", - "Scripts", - "Sentence_Terminal", - "Sharada", - "Shavian", - "Siddham", - "SignWriting", - "SimpleFold", - "Sinhala", - "Sk", - "Sm", - "So", - "Soft_Dotted", - "Sogdian", - "Sora_Sompeng", - "Soyombo", - "Space", - "SpecialCase", - "Sundanese", - "Syloti_Nagri", - "Symbol", - "Syriac", - "Tagalog", - "Tagbanwa", - "Tai_Le", - "Tai_Tham", - "Tai_Viet", - "Takri", - "Tamil", - "Tangsa", - "Tangut", - "Telugu", - "Terminal_Punctuation", - "Thaana", - "Thai", - "Tibetan", - "Tifinagh", - "Tirhuta", - "Title", - "TitleCase", - "To", - "ToLower", - "ToTitle", - "ToUpper", - "Toto", - "TurkishCase", - "Ugaritic", - "Unified_Ideograph", - "Upper", - "UpperCase", - "UpperLower", - "Vai", - "Variation_Selector", - "Version", - "Vithkuqi", - "Wancho", - "Warang_Citi", - "White_Space", - "Yezidi", - "Yi", - "Z", - "Zanabazar_Square", - "Zl", - "Zp", - "Zs", - }, - "unicode/utf16": { - "AppendRune", - "Decode", - "DecodeRune", - "Encode", - "EncodeRune", - "IsSurrogate", - }, - "unicode/utf8": { - "AppendRune", - "DecodeLastRune", - "DecodeLastRuneInString", - "DecodeRune", - "DecodeRuneInString", - "EncodeRune", - "FullRune", - "FullRuneInString", - "MaxRune", - "RuneCount", - "RuneCountInString", - "RuneError", - "RuneLen", - "RuneSelf", - "RuneStart", - "UTFMax", - "Valid", - "ValidRune", - "ValidString", - }, - "unsafe": { - "Add", - "Alignof", - "Offsetof", - "Pointer", - "Sizeof", - "Slice", - "SliceData", - "String", - "StringData", - }, -} diff --git a/vendor/golang.org/x/tools/internal/pkgbits/decoder.go b/vendor/golang.org/x/tools/internal/pkgbits/decoder.go index b92e8e6eb..2acd85851 100644 --- a/vendor/golang.org/x/tools/internal/pkgbits/decoder.go +++ b/vendor/golang.org/x/tools/internal/pkgbits/decoder.go @@ -23,6 +23,9 @@ type PkgDecoder struct { // version is the file format version. version uint32 + // aliases determines whether types.Aliases should be created + aliases bool + // sync indicates whether the file uses sync markers. sync bool @@ -73,6 +76,7 @@ func (pr *PkgDecoder) SyncMarkers() bool { return pr.sync } func NewPkgDecoder(pkgPath, input string) PkgDecoder { pr := PkgDecoder{ pkgPath: pkgPath, + //aliases: aliases.Enabled(), } // TODO(mdempsky): Implement direct indexing of input string to diff --git a/vendor/golang.org/x/tools/internal/stdlib/manifest.go b/vendor/golang.org/x/tools/internal/stdlib/manifest.go new file mode 100644 index 000000000..fd6892075 --- /dev/null +++ b/vendor/golang.org/x/tools/internal/stdlib/manifest.go @@ -0,0 +1,17320 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Code generated by generate.go. DO NOT EDIT. + +package stdlib + +var PackageSymbols = map[string][]Symbol{ + "archive/tar": { + {"(*Header).FileInfo", Method, 1}, + {"(*Reader).Next", Method, 0}, + {"(*Reader).Read", Method, 0}, + {"(*Writer).AddFS", Method, 22}, + {"(*Writer).Close", Method, 0}, + {"(*Writer).Flush", Method, 0}, + {"(*Writer).Write", Method, 0}, + {"(*Writer).WriteHeader", Method, 0}, + {"(Format).String", Method, 10}, + {"ErrFieldTooLong", Var, 0}, + {"ErrHeader", Var, 0}, + {"ErrInsecurePath", Var, 20}, + {"ErrWriteAfterClose", Var, 0}, + {"ErrWriteTooLong", Var, 0}, + {"FileInfoHeader", Func, 1}, + {"Format", Type, 10}, + {"FormatGNU", Const, 10}, + {"FormatPAX", Const, 10}, + {"FormatUSTAR", Const, 10}, + {"FormatUnknown", Const, 10}, + {"Header", Type, 0}, + {"Header.AccessTime", Field, 0}, + {"Header.ChangeTime", Field, 0}, + {"Header.Devmajor", Field, 0}, + {"Header.Devminor", Field, 0}, + {"Header.Format", Field, 10}, + {"Header.Gid", Field, 0}, + {"Header.Gname", Field, 0}, + {"Header.Linkname", Field, 0}, + {"Header.ModTime", Field, 0}, + {"Header.Mode", Field, 0}, + {"Header.Name", Field, 0}, + {"Header.PAXRecords", Field, 10}, + {"Header.Size", Field, 0}, + {"Header.Typeflag", Field, 0}, + {"Header.Uid", Field, 0}, + {"Header.Uname", Field, 0}, + {"Header.Xattrs", Field, 3}, + {"NewReader", Func, 0}, + {"NewWriter", Func, 0}, + {"Reader", Type, 0}, + {"TypeBlock", Const, 0}, + {"TypeChar", Const, 0}, + {"TypeCont", Const, 0}, + {"TypeDir", Const, 0}, + {"TypeFifo", Const, 0}, + {"TypeGNULongLink", Const, 1}, + {"TypeGNULongName", Const, 1}, + {"TypeGNUSparse", Const, 3}, + {"TypeLink", Const, 0}, + {"TypeReg", Const, 0}, + {"TypeRegA", Const, 0}, + {"TypeSymlink", Const, 0}, + {"TypeXGlobalHeader", Const, 0}, + {"TypeXHeader", Const, 0}, + {"Writer", Type, 0}, + }, + "archive/zip": { + {"(*File).DataOffset", Method, 2}, + {"(*File).FileInfo", Method, 0}, + {"(*File).ModTime", Method, 0}, + {"(*File).Mode", Method, 0}, + {"(*File).Open", Method, 0}, + {"(*File).OpenRaw", Method, 17}, + {"(*File).SetModTime", Method, 0}, + {"(*File).SetMode", Method, 0}, + {"(*FileHeader).FileInfo", Method, 0}, + {"(*FileHeader).ModTime", Method, 0}, + {"(*FileHeader).Mode", Method, 0}, + {"(*FileHeader).SetModTime", Method, 0}, + {"(*FileHeader).SetMode", Method, 0}, + {"(*ReadCloser).Close", Method, 0}, + {"(*ReadCloser).Open", Method, 16}, + {"(*ReadCloser).RegisterDecompressor", Method, 6}, + {"(*Reader).Open", Method, 16}, + {"(*Reader).RegisterDecompressor", Method, 6}, + {"(*Writer).AddFS", Method, 22}, + {"(*Writer).Close", Method, 0}, + {"(*Writer).Copy", Method, 17}, + {"(*Writer).Create", Method, 0}, + {"(*Writer).CreateHeader", Method, 0}, + {"(*Writer).CreateRaw", Method, 17}, + {"(*Writer).Flush", Method, 4}, + {"(*Writer).RegisterCompressor", Method, 6}, + {"(*Writer).SetComment", Method, 10}, + {"(*Writer).SetOffset", Method, 5}, + {"Compressor", Type, 2}, + {"Decompressor", Type, 2}, + {"Deflate", Const, 0}, + {"ErrAlgorithm", Var, 0}, + {"ErrChecksum", Var, 0}, + {"ErrFormat", Var, 0}, + {"ErrInsecurePath", Var, 20}, + {"File", Type, 0}, + {"File.FileHeader", Field, 0}, + {"FileHeader", Type, 0}, + {"FileHeader.CRC32", Field, 0}, + {"FileHeader.Comment", Field, 0}, + {"FileHeader.CompressedSize", Field, 0}, + {"FileHeader.CompressedSize64", Field, 1}, + {"FileHeader.CreatorVersion", Field, 0}, + {"FileHeader.ExternalAttrs", Field, 0}, + {"FileHeader.Extra", Field, 0}, + {"FileHeader.Flags", Field, 0}, + {"FileHeader.Method", Field, 0}, + {"FileHeader.Modified", Field, 10}, + {"FileHeader.ModifiedDate", Field, 0}, + {"FileHeader.ModifiedTime", Field, 0}, + {"FileHeader.Name", Field, 0}, + {"FileHeader.NonUTF8", Field, 10}, + {"FileHeader.ReaderVersion", Field, 0}, + {"FileHeader.UncompressedSize", Field, 0}, + {"FileHeader.UncompressedSize64", Field, 1}, + {"FileInfoHeader", Func, 0}, + {"NewReader", Func, 0}, + {"NewWriter", Func, 0}, + {"OpenReader", Func, 0}, + {"ReadCloser", Type, 0}, + {"ReadCloser.Reader", Field, 0}, + {"Reader", Type, 0}, + {"Reader.Comment", Field, 0}, + {"Reader.File", Field, 0}, + {"RegisterCompressor", Func, 2}, + {"RegisterDecompressor", Func, 2}, + {"Store", Const, 0}, + {"Writer", Type, 0}, + }, + "bufio": { + {"(*Reader).Buffered", Method, 0}, + {"(*Reader).Discard", Method, 5}, + {"(*Reader).Peek", Method, 0}, + {"(*Reader).Read", Method, 0}, + {"(*Reader).ReadByte", Method, 0}, + {"(*Reader).ReadBytes", Method, 0}, + {"(*Reader).ReadLine", Method, 0}, + {"(*Reader).ReadRune", Method, 0}, + {"(*Reader).ReadSlice", Method, 0}, + {"(*Reader).ReadString", Method, 0}, + {"(*Reader).Reset", Method, 2}, + {"(*Reader).Size", Method, 10}, + {"(*Reader).UnreadByte", Method, 0}, + {"(*Reader).UnreadRune", Method, 0}, + {"(*Reader).WriteTo", Method, 1}, + {"(*Scanner).Buffer", Method, 6}, + {"(*Scanner).Bytes", Method, 1}, + {"(*Scanner).Err", Method, 1}, + {"(*Scanner).Scan", Method, 1}, + {"(*Scanner).Split", Method, 1}, + {"(*Scanner).Text", Method, 1}, + {"(*Writer).Available", Method, 0}, + {"(*Writer).AvailableBuffer", Method, 18}, + {"(*Writer).Buffered", Method, 0}, + {"(*Writer).Flush", Method, 0}, + {"(*Writer).ReadFrom", Method, 1}, + {"(*Writer).Reset", Method, 2}, + {"(*Writer).Size", Method, 10}, + {"(*Writer).Write", Method, 0}, + {"(*Writer).WriteByte", Method, 0}, + {"(*Writer).WriteRune", Method, 0}, + {"(*Writer).WriteString", Method, 0}, + {"(ReadWriter).Available", Method, 0}, + {"(ReadWriter).AvailableBuffer", Method, 18}, + {"(ReadWriter).Discard", Method, 5}, + {"(ReadWriter).Flush", Method, 0}, + {"(ReadWriter).Peek", Method, 0}, + {"(ReadWriter).Read", Method, 0}, + {"(ReadWriter).ReadByte", Method, 0}, + {"(ReadWriter).ReadBytes", Method, 0}, + {"(ReadWriter).ReadFrom", Method, 1}, + {"(ReadWriter).ReadLine", Method, 0}, + {"(ReadWriter).ReadRune", Method, 0}, + {"(ReadWriter).ReadSlice", Method, 0}, + {"(ReadWriter).ReadString", Method, 0}, + {"(ReadWriter).UnreadByte", Method, 0}, + {"(ReadWriter).UnreadRune", Method, 0}, + {"(ReadWriter).Write", Method, 0}, + {"(ReadWriter).WriteByte", Method, 0}, + {"(ReadWriter).WriteRune", Method, 0}, + {"(ReadWriter).WriteString", Method, 0}, + {"(ReadWriter).WriteTo", Method, 1}, + {"ErrAdvanceTooFar", Var, 1}, + {"ErrBadReadCount", Var, 15}, + {"ErrBufferFull", Var, 0}, + {"ErrFinalToken", Var, 6}, + {"ErrInvalidUnreadByte", Var, 0}, + {"ErrInvalidUnreadRune", Var, 0}, + {"ErrNegativeAdvance", Var, 1}, + {"ErrNegativeCount", Var, 0}, + {"ErrTooLong", Var, 1}, + {"MaxScanTokenSize", Const, 1}, + {"NewReadWriter", Func, 0}, + {"NewReader", Func, 0}, + {"NewReaderSize", Func, 0}, + {"NewScanner", Func, 1}, + {"NewWriter", Func, 0}, + {"NewWriterSize", Func, 0}, + {"ReadWriter", Type, 0}, + {"ReadWriter.Reader", Field, 0}, + {"ReadWriter.Writer", Field, 0}, + {"Reader", Type, 0}, + {"ScanBytes", Func, 1}, + {"ScanLines", Func, 1}, + {"ScanRunes", Func, 1}, + {"ScanWords", Func, 1}, + {"Scanner", Type, 1}, + {"SplitFunc", Type, 1}, + {"Writer", Type, 0}, + }, + "bytes": { + {"(*Buffer).Available", Method, 21}, + {"(*Buffer).AvailableBuffer", Method, 21}, + {"(*Buffer).Bytes", Method, 0}, + {"(*Buffer).Cap", Method, 5}, + {"(*Buffer).Grow", Method, 1}, + {"(*Buffer).Len", Method, 0}, + {"(*Buffer).Next", Method, 0}, + {"(*Buffer).Read", Method, 0}, + {"(*Buffer).ReadByte", Method, 0}, + {"(*Buffer).ReadBytes", Method, 0}, + {"(*Buffer).ReadFrom", Method, 0}, + {"(*Buffer).ReadRune", Method, 0}, + {"(*Buffer).ReadString", Method, 0}, + {"(*Buffer).Reset", Method, 0}, + {"(*Buffer).String", Method, 0}, + {"(*Buffer).Truncate", Method, 0}, + {"(*Buffer).UnreadByte", Method, 0}, + {"(*Buffer).UnreadRune", Method, 0}, + {"(*Buffer).Write", Method, 0}, + {"(*Buffer).WriteByte", Method, 0}, + {"(*Buffer).WriteRune", Method, 0}, + {"(*Buffer).WriteString", Method, 0}, + {"(*Buffer).WriteTo", Method, 0}, + {"(*Reader).Len", Method, 0}, + {"(*Reader).Read", Method, 0}, + {"(*Reader).ReadAt", Method, 0}, + {"(*Reader).ReadByte", Method, 0}, + {"(*Reader).ReadRune", Method, 0}, + {"(*Reader).Reset", Method, 7}, + {"(*Reader).Seek", Method, 0}, + {"(*Reader).Size", Method, 5}, + {"(*Reader).UnreadByte", Method, 0}, + {"(*Reader).UnreadRune", Method, 0}, + {"(*Reader).WriteTo", Method, 1}, + {"Buffer", Type, 0}, + {"Clone", Func, 20}, + {"Compare", Func, 0}, + {"Contains", Func, 0}, + {"ContainsAny", Func, 7}, + {"ContainsFunc", Func, 21}, + {"ContainsRune", Func, 7}, + {"Count", Func, 0}, + {"Cut", Func, 18}, + {"CutPrefix", Func, 20}, + {"CutSuffix", Func, 20}, + {"Equal", Func, 0}, + {"EqualFold", Func, 0}, + {"ErrTooLarge", Var, 0}, + {"Fields", Func, 0}, + {"FieldsFunc", Func, 0}, + {"HasPrefix", Func, 0}, + {"HasSuffix", Func, 0}, + {"Index", Func, 0}, + {"IndexAny", Func, 0}, + {"IndexByte", Func, 0}, + {"IndexFunc", Func, 0}, + {"IndexRune", Func, 0}, + {"Join", Func, 0}, + {"LastIndex", Func, 0}, + {"LastIndexAny", Func, 0}, + {"LastIndexByte", Func, 5}, + {"LastIndexFunc", Func, 0}, + {"Map", Func, 0}, + {"MinRead", Const, 0}, + {"NewBuffer", Func, 0}, + {"NewBufferString", Func, 0}, + {"NewReader", Func, 0}, + {"Reader", Type, 0}, + {"Repeat", Func, 0}, + {"Replace", Func, 0}, + {"ReplaceAll", Func, 12}, + {"Runes", Func, 0}, + {"Split", Func, 0}, + {"SplitAfter", Func, 0}, + {"SplitAfterN", Func, 0}, + {"SplitN", Func, 0}, + {"Title", Func, 0}, + {"ToLower", Func, 0}, + {"ToLowerSpecial", Func, 0}, + {"ToTitle", Func, 0}, + {"ToTitleSpecial", Func, 0}, + {"ToUpper", Func, 0}, + {"ToUpperSpecial", Func, 0}, + {"ToValidUTF8", Func, 13}, + {"Trim", Func, 0}, + {"TrimFunc", Func, 0}, + {"TrimLeft", Func, 0}, + {"TrimLeftFunc", Func, 0}, + {"TrimPrefix", Func, 1}, + {"TrimRight", Func, 0}, + {"TrimRightFunc", Func, 0}, + {"TrimSpace", Func, 0}, + {"TrimSuffix", Func, 1}, + }, + "cmp": { + {"Compare", Func, 21}, + {"Less", Func, 21}, + {"Or", Func, 22}, + {"Ordered", Type, 21}, + }, + "compress/bzip2": { + {"(StructuralError).Error", Method, 0}, + {"NewReader", Func, 0}, + {"StructuralError", Type, 0}, + }, + "compress/flate": { + {"(*ReadError).Error", Method, 0}, + {"(*WriteError).Error", Method, 0}, + {"(*Writer).Close", Method, 0}, + {"(*Writer).Flush", Method, 0}, + {"(*Writer).Reset", Method, 2}, + {"(*Writer).Write", Method, 0}, + {"(CorruptInputError).Error", Method, 0}, + {"(InternalError).Error", Method, 0}, + {"BestCompression", Const, 0}, + {"BestSpeed", Const, 0}, + {"CorruptInputError", Type, 0}, + {"DefaultCompression", Const, 0}, + {"HuffmanOnly", Const, 7}, + {"InternalError", Type, 0}, + {"NewReader", Func, 0}, + {"NewReaderDict", Func, 0}, + {"NewWriter", Func, 0}, + {"NewWriterDict", Func, 0}, + {"NoCompression", Const, 0}, + {"ReadError", Type, 0}, + {"ReadError.Err", Field, 0}, + {"ReadError.Offset", Field, 0}, + {"Reader", Type, 0}, + {"Resetter", Type, 4}, + {"WriteError", Type, 0}, + {"WriteError.Err", Field, 0}, + {"WriteError.Offset", Field, 0}, + {"Writer", Type, 0}, + }, + "compress/gzip": { + {"(*Reader).Close", Method, 0}, + {"(*Reader).Multistream", Method, 4}, + {"(*Reader).Read", Method, 0}, + {"(*Reader).Reset", Method, 3}, + {"(*Writer).Close", Method, 0}, + {"(*Writer).Flush", Method, 1}, + {"(*Writer).Reset", Method, 2}, + {"(*Writer).Write", Method, 0}, + {"BestCompression", Const, 0}, + {"BestSpeed", Const, 0}, + {"DefaultCompression", Const, 0}, + {"ErrChecksum", Var, 0}, + {"ErrHeader", Var, 0}, + {"Header", Type, 0}, + {"Header.Comment", Field, 0}, + {"Header.Extra", Field, 0}, + {"Header.ModTime", Field, 0}, + {"Header.Name", Field, 0}, + {"Header.OS", Field, 0}, + {"HuffmanOnly", Const, 8}, + {"NewReader", Func, 0}, + {"NewWriter", Func, 0}, + {"NewWriterLevel", Func, 0}, + {"NoCompression", Const, 0}, + {"Reader", Type, 0}, + {"Reader.Header", Field, 0}, + {"Writer", Type, 0}, + {"Writer.Header", Field, 0}, + }, + "compress/lzw": { + {"(*Reader).Close", Method, 17}, + {"(*Reader).Read", Method, 17}, + {"(*Reader).Reset", Method, 17}, + {"(*Writer).Close", Method, 17}, + {"(*Writer).Reset", Method, 17}, + {"(*Writer).Write", Method, 17}, + {"LSB", Const, 0}, + {"MSB", Const, 0}, + {"NewReader", Func, 0}, + {"NewWriter", Func, 0}, + {"Order", Type, 0}, + {"Reader", Type, 17}, + {"Writer", Type, 17}, + }, + "compress/zlib": { + {"(*Writer).Close", Method, 0}, + {"(*Writer).Flush", Method, 0}, + {"(*Writer).Reset", Method, 2}, + {"(*Writer).Write", Method, 0}, + {"BestCompression", Const, 0}, + {"BestSpeed", Const, 0}, + {"DefaultCompression", Const, 0}, + {"ErrChecksum", Var, 0}, + {"ErrDictionary", Var, 0}, + {"ErrHeader", Var, 0}, + {"HuffmanOnly", Const, 8}, + {"NewReader", Func, 0}, + {"NewReaderDict", Func, 0}, + {"NewWriter", Func, 0}, + {"NewWriterLevel", Func, 0}, + {"NewWriterLevelDict", Func, 0}, + {"NoCompression", Const, 0}, + {"Resetter", Type, 4}, + {"Writer", Type, 0}, + }, + "container/heap": { + {"Fix", Func, 2}, + {"Init", Func, 0}, + {"Interface", Type, 0}, + {"Pop", Func, 0}, + {"Push", Func, 0}, + {"Remove", Func, 0}, + }, + "container/list": { + {"(*Element).Next", Method, 0}, + {"(*Element).Prev", Method, 0}, + {"(*List).Back", Method, 0}, + {"(*List).Front", Method, 0}, + {"(*List).Init", Method, 0}, + {"(*List).InsertAfter", Method, 0}, + {"(*List).InsertBefore", Method, 0}, + {"(*List).Len", Method, 0}, + {"(*List).MoveAfter", Method, 2}, + {"(*List).MoveBefore", Method, 2}, + {"(*List).MoveToBack", Method, 0}, + {"(*List).MoveToFront", Method, 0}, + {"(*List).PushBack", Method, 0}, + {"(*List).PushBackList", Method, 0}, + {"(*List).PushFront", Method, 0}, + {"(*List).PushFrontList", Method, 0}, + {"(*List).Remove", Method, 0}, + {"Element", Type, 0}, + {"Element.Value", Field, 0}, + {"List", Type, 0}, + {"New", Func, 0}, + }, + "container/ring": { + {"(*Ring).Do", Method, 0}, + {"(*Ring).Len", Method, 0}, + {"(*Ring).Link", Method, 0}, + {"(*Ring).Move", Method, 0}, + {"(*Ring).Next", Method, 0}, + {"(*Ring).Prev", Method, 0}, + {"(*Ring).Unlink", Method, 0}, + {"New", Func, 0}, + {"Ring", Type, 0}, + {"Ring.Value", Field, 0}, + }, + "context": { + {"AfterFunc", Func, 21}, + {"Background", Func, 7}, + {"CancelCauseFunc", Type, 20}, + {"CancelFunc", Type, 7}, + {"Canceled", Var, 7}, + {"Cause", Func, 20}, + {"Context", Type, 7}, + {"DeadlineExceeded", Var, 7}, + {"TODO", Func, 7}, + {"WithCancel", Func, 7}, + {"WithCancelCause", Func, 20}, + {"WithDeadline", Func, 7}, + {"WithDeadlineCause", Func, 21}, + {"WithTimeout", Func, 7}, + {"WithTimeoutCause", Func, 21}, + {"WithValue", Func, 7}, + {"WithoutCancel", Func, 21}, + }, + "crypto": { + {"(Hash).Available", Method, 0}, + {"(Hash).HashFunc", Method, 4}, + {"(Hash).New", Method, 0}, + {"(Hash).Size", Method, 0}, + {"(Hash).String", Method, 15}, + {"BLAKE2b_256", Const, 9}, + {"BLAKE2b_384", Const, 9}, + {"BLAKE2b_512", Const, 9}, + {"BLAKE2s_256", Const, 9}, + {"Decrypter", Type, 5}, + {"DecrypterOpts", Type, 5}, + {"Hash", Type, 0}, + {"MD4", Const, 0}, + {"MD5", Const, 0}, + {"MD5SHA1", Const, 0}, + {"PrivateKey", Type, 0}, + {"PublicKey", Type, 2}, + {"RIPEMD160", Const, 0}, + {"RegisterHash", Func, 0}, + {"SHA1", Const, 0}, + {"SHA224", Const, 0}, + {"SHA256", Const, 0}, + {"SHA384", Const, 0}, + {"SHA3_224", Const, 4}, + {"SHA3_256", Const, 4}, + {"SHA3_384", Const, 4}, + {"SHA3_512", Const, 4}, + {"SHA512", Const, 0}, + {"SHA512_224", Const, 5}, + {"SHA512_256", Const, 5}, + {"Signer", Type, 4}, + {"SignerOpts", Type, 4}, + }, + "crypto/aes": { + {"(KeySizeError).Error", Method, 0}, + {"BlockSize", Const, 0}, + {"KeySizeError", Type, 0}, + {"NewCipher", Func, 0}, + }, + "crypto/cipher": { + {"(StreamReader).Read", Method, 0}, + {"(StreamWriter).Close", Method, 0}, + {"(StreamWriter).Write", Method, 0}, + {"AEAD", Type, 2}, + {"Block", Type, 0}, + {"BlockMode", Type, 0}, + {"NewCBCDecrypter", Func, 0}, + {"NewCBCEncrypter", Func, 0}, + {"NewCFBDecrypter", Func, 0}, + {"NewCFBEncrypter", Func, 0}, + {"NewCTR", Func, 0}, + {"NewGCM", Func, 2}, + {"NewGCMWithNonceSize", Func, 5}, + {"NewGCMWithTagSize", Func, 11}, + {"NewOFB", Func, 0}, + {"Stream", Type, 0}, + {"StreamReader", Type, 0}, + {"StreamReader.R", Field, 0}, + {"StreamReader.S", Field, 0}, + {"StreamWriter", Type, 0}, + {"StreamWriter.Err", Field, 0}, + {"StreamWriter.S", Field, 0}, + {"StreamWriter.W", Field, 0}, + }, + "crypto/des": { + {"(KeySizeError).Error", Method, 0}, + {"BlockSize", Const, 0}, + {"KeySizeError", Type, 0}, + {"NewCipher", Func, 0}, + {"NewTripleDESCipher", Func, 0}, + }, + "crypto/dsa": { + {"ErrInvalidPublicKey", Var, 0}, + {"GenerateKey", Func, 0}, + {"GenerateParameters", Func, 0}, + {"L1024N160", Const, 0}, + {"L2048N224", Const, 0}, + {"L2048N256", Const, 0}, + {"L3072N256", Const, 0}, + {"ParameterSizes", Type, 0}, + {"Parameters", Type, 0}, + {"Parameters.G", Field, 0}, + {"Parameters.P", Field, 0}, + {"Parameters.Q", Field, 0}, + {"PrivateKey", Type, 0}, + {"PrivateKey.PublicKey", Field, 0}, + {"PrivateKey.X", Field, 0}, + {"PublicKey", Type, 0}, + {"PublicKey.Parameters", Field, 0}, + {"PublicKey.Y", Field, 0}, + {"Sign", Func, 0}, + {"Verify", Func, 0}, + }, + "crypto/ecdh": { + {"(*PrivateKey).Bytes", Method, 20}, + {"(*PrivateKey).Curve", Method, 20}, + {"(*PrivateKey).ECDH", Method, 20}, + {"(*PrivateKey).Equal", Method, 20}, + {"(*PrivateKey).Public", Method, 20}, + {"(*PrivateKey).PublicKey", Method, 20}, + {"(*PublicKey).Bytes", Method, 20}, + {"(*PublicKey).Curve", Method, 20}, + {"(*PublicKey).Equal", Method, 20}, + {"Curve", Type, 20}, + {"P256", Func, 20}, + {"P384", Func, 20}, + {"P521", Func, 20}, + {"PrivateKey", Type, 20}, + {"PublicKey", Type, 20}, + {"X25519", Func, 20}, + }, + "crypto/ecdsa": { + {"(*PrivateKey).ECDH", Method, 20}, + {"(*PrivateKey).Equal", Method, 15}, + {"(*PrivateKey).Public", Method, 4}, + {"(*PrivateKey).Sign", Method, 4}, + {"(*PublicKey).ECDH", Method, 20}, + {"(*PublicKey).Equal", Method, 15}, + {"(PrivateKey).Add", Method, 0}, + {"(PrivateKey).Double", Method, 0}, + {"(PrivateKey).IsOnCurve", Method, 0}, + {"(PrivateKey).Params", Method, 0}, + {"(PrivateKey).ScalarBaseMult", Method, 0}, + {"(PrivateKey).ScalarMult", Method, 0}, + {"(PublicKey).Add", Method, 0}, + {"(PublicKey).Double", Method, 0}, + {"(PublicKey).IsOnCurve", Method, 0}, + {"(PublicKey).Params", Method, 0}, + {"(PublicKey).ScalarBaseMult", Method, 0}, + {"(PublicKey).ScalarMult", Method, 0}, + {"GenerateKey", Func, 0}, + {"PrivateKey", Type, 0}, + {"PrivateKey.D", Field, 0}, + {"PrivateKey.PublicKey", Field, 0}, + {"PublicKey", Type, 0}, + {"PublicKey.Curve", Field, 0}, + {"PublicKey.X", Field, 0}, + {"PublicKey.Y", Field, 0}, + {"Sign", Func, 0}, + {"SignASN1", Func, 15}, + {"Verify", Func, 0}, + {"VerifyASN1", Func, 15}, + }, + "crypto/ed25519": { + {"(*Options).HashFunc", Method, 20}, + {"(PrivateKey).Equal", Method, 15}, + {"(PrivateKey).Public", Method, 13}, + {"(PrivateKey).Seed", Method, 13}, + {"(PrivateKey).Sign", Method, 13}, + {"(PublicKey).Equal", Method, 15}, + {"GenerateKey", Func, 13}, + {"NewKeyFromSeed", Func, 13}, + {"Options", Type, 20}, + {"Options.Context", Field, 20}, + {"Options.Hash", Field, 20}, + {"PrivateKey", Type, 13}, + {"PrivateKeySize", Const, 13}, + {"PublicKey", Type, 13}, + {"PublicKeySize", Const, 13}, + {"SeedSize", Const, 13}, + {"Sign", Func, 13}, + {"SignatureSize", Const, 13}, + {"Verify", Func, 13}, + {"VerifyWithOptions", Func, 20}, + }, + "crypto/elliptic": { + {"(*CurveParams).Add", Method, 0}, + {"(*CurveParams).Double", Method, 0}, + {"(*CurveParams).IsOnCurve", Method, 0}, + {"(*CurveParams).Params", Method, 0}, + {"(*CurveParams).ScalarBaseMult", Method, 0}, + {"(*CurveParams).ScalarMult", Method, 0}, + {"Curve", Type, 0}, + {"CurveParams", Type, 0}, + {"CurveParams.B", Field, 0}, + {"CurveParams.BitSize", Field, 0}, + {"CurveParams.Gx", Field, 0}, + {"CurveParams.Gy", Field, 0}, + {"CurveParams.N", Field, 0}, + {"CurveParams.Name", Field, 5}, + {"CurveParams.P", Field, 0}, + {"GenerateKey", Func, 0}, + {"Marshal", Func, 0}, + {"MarshalCompressed", Func, 15}, + {"P224", Func, 0}, + {"P256", Func, 0}, + {"P384", Func, 0}, + {"P521", Func, 0}, + {"Unmarshal", Func, 0}, + {"UnmarshalCompressed", Func, 15}, + }, + "crypto/hmac": { + {"Equal", Func, 1}, + {"New", Func, 0}, + }, + "crypto/md5": { + {"BlockSize", Const, 0}, + {"New", Func, 0}, + {"Size", Const, 0}, + {"Sum", Func, 2}, + }, + "crypto/rand": { + {"Int", Func, 0}, + {"Prime", Func, 0}, + {"Read", Func, 0}, + {"Reader", Var, 0}, + }, + "crypto/rc4": { + {"(*Cipher).Reset", Method, 0}, + {"(*Cipher).XORKeyStream", Method, 0}, + {"(KeySizeError).Error", Method, 0}, + {"Cipher", Type, 0}, + {"KeySizeError", Type, 0}, + {"NewCipher", Func, 0}, + }, + "crypto/rsa": { + {"(*PSSOptions).HashFunc", Method, 4}, + {"(*PrivateKey).Decrypt", Method, 5}, + {"(*PrivateKey).Equal", Method, 15}, + {"(*PrivateKey).Precompute", Method, 0}, + {"(*PrivateKey).Public", Method, 4}, + {"(*PrivateKey).Sign", Method, 4}, + {"(*PrivateKey).Size", Method, 11}, + {"(*PrivateKey).Validate", Method, 0}, + {"(*PublicKey).Equal", Method, 15}, + {"(*PublicKey).Size", Method, 11}, + {"CRTValue", Type, 0}, + {"CRTValue.Coeff", Field, 0}, + {"CRTValue.Exp", Field, 0}, + {"CRTValue.R", Field, 0}, + {"DecryptOAEP", Func, 0}, + {"DecryptPKCS1v15", Func, 0}, + {"DecryptPKCS1v15SessionKey", Func, 0}, + {"EncryptOAEP", Func, 0}, + {"EncryptPKCS1v15", Func, 0}, + {"ErrDecryption", Var, 0}, + {"ErrMessageTooLong", Var, 0}, + {"ErrVerification", Var, 0}, + {"GenerateKey", Func, 0}, + {"GenerateMultiPrimeKey", Func, 0}, + {"OAEPOptions", Type, 5}, + {"OAEPOptions.Hash", Field, 5}, + {"OAEPOptions.Label", Field, 5}, + {"OAEPOptions.MGFHash", Field, 20}, + {"PKCS1v15DecryptOptions", Type, 5}, + {"PKCS1v15DecryptOptions.SessionKeyLen", Field, 5}, + {"PSSOptions", Type, 2}, + {"PSSOptions.Hash", Field, 4}, + {"PSSOptions.SaltLength", Field, 2}, + {"PSSSaltLengthAuto", Const, 2}, + {"PSSSaltLengthEqualsHash", Const, 2}, + {"PrecomputedValues", Type, 0}, + {"PrecomputedValues.CRTValues", Field, 0}, + {"PrecomputedValues.Dp", Field, 0}, + {"PrecomputedValues.Dq", Field, 0}, + {"PrecomputedValues.Qinv", Field, 0}, + {"PrivateKey", Type, 0}, + {"PrivateKey.D", Field, 0}, + {"PrivateKey.Precomputed", Field, 0}, + {"PrivateKey.Primes", Field, 0}, + {"PrivateKey.PublicKey", Field, 0}, + {"PublicKey", Type, 0}, + {"PublicKey.E", Field, 0}, + {"PublicKey.N", Field, 0}, + {"SignPKCS1v15", Func, 0}, + {"SignPSS", Func, 2}, + {"VerifyPKCS1v15", Func, 0}, + {"VerifyPSS", Func, 2}, + }, + "crypto/sha1": { + {"BlockSize", Const, 0}, + {"New", Func, 0}, + {"Size", Const, 0}, + {"Sum", Func, 2}, + }, + "crypto/sha256": { + {"BlockSize", Const, 0}, + {"New", Func, 0}, + {"New224", Func, 0}, + {"Size", Const, 0}, + {"Size224", Const, 0}, + {"Sum224", Func, 2}, + {"Sum256", Func, 2}, + }, + "crypto/sha512": { + {"BlockSize", Const, 0}, + {"New", Func, 0}, + {"New384", Func, 0}, + {"New512_224", Func, 5}, + {"New512_256", Func, 5}, + {"Size", Const, 0}, + {"Size224", Const, 5}, + {"Size256", Const, 5}, + {"Size384", Const, 0}, + {"Sum384", Func, 2}, + {"Sum512", Func, 2}, + {"Sum512_224", Func, 5}, + {"Sum512_256", Func, 5}, + }, + "crypto/subtle": { + {"ConstantTimeByteEq", Func, 0}, + {"ConstantTimeCompare", Func, 0}, + {"ConstantTimeCopy", Func, 0}, + {"ConstantTimeEq", Func, 0}, + {"ConstantTimeLessOrEq", Func, 2}, + {"ConstantTimeSelect", Func, 0}, + {"XORBytes", Func, 20}, + }, + "crypto/tls": { + {"(*CertificateRequestInfo).Context", Method, 17}, + {"(*CertificateRequestInfo).SupportsCertificate", Method, 14}, + {"(*CertificateVerificationError).Error", Method, 20}, + {"(*CertificateVerificationError).Unwrap", Method, 20}, + {"(*ClientHelloInfo).Context", Method, 17}, + {"(*ClientHelloInfo).SupportsCertificate", Method, 14}, + {"(*ClientSessionState).ResumptionState", Method, 21}, + {"(*Config).BuildNameToCertificate", Method, 0}, + {"(*Config).Clone", Method, 8}, + {"(*Config).DecryptTicket", Method, 21}, + {"(*Config).EncryptTicket", Method, 21}, + {"(*Config).SetSessionTicketKeys", Method, 5}, + {"(*Conn).Close", Method, 0}, + {"(*Conn).CloseWrite", Method, 8}, + {"(*Conn).ConnectionState", Method, 0}, + {"(*Conn).Handshake", Method, 0}, + {"(*Conn).HandshakeContext", Method, 17}, + {"(*Conn).LocalAddr", Method, 0}, + {"(*Conn).NetConn", Method, 18}, + {"(*Conn).OCSPResponse", Method, 0}, + {"(*Conn).Read", Method, 0}, + {"(*Conn).RemoteAddr", Method, 0}, + {"(*Conn).SetDeadline", Method, 0}, + {"(*Conn).SetReadDeadline", Method, 0}, + {"(*Conn).SetWriteDeadline", Method, 0}, + {"(*Conn).VerifyHostname", Method, 0}, + {"(*Conn).Write", Method, 0}, + {"(*ConnectionState).ExportKeyingMaterial", Method, 11}, + {"(*Dialer).Dial", Method, 15}, + {"(*Dialer).DialContext", Method, 15}, + {"(*QUICConn).Close", Method, 21}, + {"(*QUICConn).ConnectionState", Method, 21}, + {"(*QUICConn).HandleData", Method, 21}, + {"(*QUICConn).NextEvent", Method, 21}, + {"(*QUICConn).SendSessionTicket", Method, 21}, + {"(*QUICConn).SetTransportParameters", Method, 21}, + {"(*QUICConn).Start", Method, 21}, + {"(*SessionState).Bytes", Method, 21}, + {"(AlertError).Error", Method, 21}, + {"(ClientAuthType).String", Method, 15}, + {"(CurveID).String", Method, 15}, + {"(QUICEncryptionLevel).String", Method, 21}, + {"(RecordHeaderError).Error", Method, 6}, + {"(SignatureScheme).String", Method, 15}, + {"AlertError", Type, 21}, + {"Certificate", Type, 0}, + {"Certificate.Certificate", Field, 0}, + {"Certificate.Leaf", Field, 0}, + {"Certificate.OCSPStaple", Field, 0}, + {"Certificate.PrivateKey", Field, 0}, + {"Certificate.SignedCertificateTimestamps", Field, 5}, + {"Certificate.SupportedSignatureAlgorithms", Field, 14}, + {"CertificateRequestInfo", Type, 8}, + {"CertificateRequestInfo.AcceptableCAs", Field, 8}, + {"CertificateRequestInfo.SignatureSchemes", Field, 8}, + {"CertificateRequestInfo.Version", Field, 14}, + {"CertificateVerificationError", Type, 20}, + {"CertificateVerificationError.Err", Field, 20}, + {"CertificateVerificationError.UnverifiedCertificates", Field, 20}, + {"CipherSuite", Type, 14}, + {"CipherSuite.ID", Field, 14}, + {"CipherSuite.Insecure", Field, 14}, + {"CipherSuite.Name", Field, 14}, + {"CipherSuite.SupportedVersions", Field, 14}, + {"CipherSuiteName", Func, 14}, + {"CipherSuites", Func, 14}, + {"Client", Func, 0}, + {"ClientAuthType", Type, 0}, + {"ClientHelloInfo", Type, 4}, + {"ClientHelloInfo.CipherSuites", Field, 4}, + {"ClientHelloInfo.Conn", Field, 8}, + {"ClientHelloInfo.ServerName", Field, 4}, + {"ClientHelloInfo.SignatureSchemes", Field, 8}, + {"ClientHelloInfo.SupportedCurves", Field, 4}, + {"ClientHelloInfo.SupportedPoints", Field, 4}, + {"ClientHelloInfo.SupportedProtos", Field, 8}, + {"ClientHelloInfo.SupportedVersions", Field, 8}, + {"ClientSessionCache", Type, 3}, + {"ClientSessionState", Type, 3}, + {"Config", Type, 0}, + {"Config.Certificates", Field, 0}, + {"Config.CipherSuites", Field, 0}, + {"Config.ClientAuth", Field, 0}, + {"Config.ClientCAs", Field, 0}, + {"Config.ClientSessionCache", Field, 3}, + {"Config.CurvePreferences", Field, 3}, + {"Config.DynamicRecordSizingDisabled", Field, 7}, + {"Config.GetCertificate", Field, 4}, + {"Config.GetClientCertificate", Field, 8}, + {"Config.GetConfigForClient", Field, 8}, + {"Config.InsecureSkipVerify", Field, 0}, + {"Config.KeyLogWriter", Field, 8}, + {"Config.MaxVersion", Field, 2}, + {"Config.MinVersion", Field, 2}, + {"Config.NameToCertificate", Field, 0}, + {"Config.NextProtos", Field, 0}, + {"Config.PreferServerCipherSuites", Field, 1}, + {"Config.Rand", Field, 0}, + {"Config.Renegotiation", Field, 7}, + {"Config.RootCAs", Field, 0}, + {"Config.ServerName", Field, 0}, + {"Config.SessionTicketKey", Field, 1}, + {"Config.SessionTicketsDisabled", Field, 1}, + {"Config.Time", Field, 0}, + {"Config.UnwrapSession", Field, 21}, + {"Config.VerifyConnection", Field, 15}, + {"Config.VerifyPeerCertificate", Field, 8}, + {"Config.WrapSession", Field, 21}, + {"Conn", Type, 0}, + {"ConnectionState", Type, 0}, + {"ConnectionState.CipherSuite", Field, 0}, + {"ConnectionState.DidResume", Field, 1}, + {"ConnectionState.HandshakeComplete", Field, 0}, + {"ConnectionState.NegotiatedProtocol", Field, 0}, + {"ConnectionState.NegotiatedProtocolIsMutual", Field, 0}, + {"ConnectionState.OCSPResponse", Field, 5}, + {"ConnectionState.PeerCertificates", Field, 0}, + {"ConnectionState.ServerName", Field, 0}, + {"ConnectionState.SignedCertificateTimestamps", Field, 5}, + {"ConnectionState.TLSUnique", Field, 4}, + {"ConnectionState.VerifiedChains", Field, 0}, + {"ConnectionState.Version", Field, 3}, + {"CurveID", Type, 3}, + {"CurveP256", Const, 3}, + {"CurveP384", Const, 3}, + {"CurveP521", Const, 3}, + {"Dial", Func, 0}, + {"DialWithDialer", Func, 3}, + {"Dialer", Type, 15}, + {"Dialer.Config", Field, 15}, + {"Dialer.NetDialer", Field, 15}, + {"ECDSAWithP256AndSHA256", Const, 8}, + {"ECDSAWithP384AndSHA384", Const, 8}, + {"ECDSAWithP521AndSHA512", Const, 8}, + {"ECDSAWithSHA1", Const, 10}, + {"Ed25519", Const, 13}, + {"InsecureCipherSuites", Func, 14}, + {"Listen", Func, 0}, + {"LoadX509KeyPair", Func, 0}, + {"NewLRUClientSessionCache", Func, 3}, + {"NewListener", Func, 0}, + {"NewResumptionState", Func, 21}, + {"NoClientCert", Const, 0}, + {"PKCS1WithSHA1", Const, 8}, + {"PKCS1WithSHA256", Const, 8}, + {"PKCS1WithSHA384", Const, 8}, + {"PKCS1WithSHA512", Const, 8}, + {"PSSWithSHA256", Const, 8}, + {"PSSWithSHA384", Const, 8}, + {"PSSWithSHA512", Const, 8}, + {"ParseSessionState", Func, 21}, + {"QUICClient", Func, 21}, + {"QUICConfig", Type, 21}, + {"QUICConfig.TLSConfig", Field, 21}, + {"QUICConn", Type, 21}, + {"QUICEncryptionLevel", Type, 21}, + {"QUICEncryptionLevelApplication", Const, 21}, + {"QUICEncryptionLevelEarly", Const, 21}, + {"QUICEncryptionLevelHandshake", Const, 21}, + {"QUICEncryptionLevelInitial", Const, 21}, + {"QUICEvent", Type, 21}, + {"QUICEvent.Data", Field, 21}, + {"QUICEvent.Kind", Field, 21}, + {"QUICEvent.Level", Field, 21}, + {"QUICEvent.Suite", Field, 21}, + {"QUICEventKind", Type, 21}, + {"QUICHandshakeDone", Const, 21}, + {"QUICNoEvent", Const, 21}, + {"QUICRejectedEarlyData", Const, 21}, + {"QUICServer", Func, 21}, + {"QUICSessionTicketOptions", Type, 21}, + {"QUICSessionTicketOptions.EarlyData", Field, 21}, + {"QUICSetReadSecret", Const, 21}, + {"QUICSetWriteSecret", Const, 21}, + {"QUICTransportParameters", Const, 21}, + {"QUICTransportParametersRequired", Const, 21}, + {"QUICWriteData", Const, 21}, + {"RecordHeaderError", Type, 6}, + {"RecordHeaderError.Conn", Field, 12}, + {"RecordHeaderError.Msg", Field, 6}, + {"RecordHeaderError.RecordHeader", Field, 6}, + {"RenegotiateFreelyAsClient", Const, 7}, + {"RenegotiateNever", Const, 7}, + {"RenegotiateOnceAsClient", Const, 7}, + {"RenegotiationSupport", Type, 7}, + {"RequestClientCert", Const, 0}, + {"RequireAndVerifyClientCert", Const, 0}, + {"RequireAnyClientCert", Const, 0}, + {"Server", Func, 0}, + {"SessionState", Type, 21}, + {"SessionState.EarlyData", Field, 21}, + {"SessionState.Extra", Field, 21}, + {"SignatureScheme", Type, 8}, + {"TLS_AES_128_GCM_SHA256", Const, 12}, + {"TLS_AES_256_GCM_SHA384", Const, 12}, + {"TLS_CHACHA20_POLY1305_SHA256", Const, 12}, + {"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", Const, 2}, + {"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", Const, 8}, + {"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", Const, 2}, + {"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", Const, 2}, + {"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", Const, 5}, + {"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305", Const, 8}, + {"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256", Const, 14}, + {"TLS_ECDHE_ECDSA_WITH_RC4_128_SHA", Const, 2}, + {"TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA", Const, 0}, + {"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", Const, 0}, + {"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", Const, 8}, + {"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", Const, 2}, + {"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", Const, 1}, + {"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", Const, 5}, + {"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305", Const, 8}, + {"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256", Const, 14}, + {"TLS_ECDHE_RSA_WITH_RC4_128_SHA", Const, 0}, + {"TLS_FALLBACK_SCSV", Const, 4}, + {"TLS_RSA_WITH_3DES_EDE_CBC_SHA", Const, 0}, + {"TLS_RSA_WITH_AES_128_CBC_SHA", Const, 0}, + {"TLS_RSA_WITH_AES_128_CBC_SHA256", Const, 8}, + {"TLS_RSA_WITH_AES_128_GCM_SHA256", Const, 6}, + {"TLS_RSA_WITH_AES_256_CBC_SHA", Const, 1}, + {"TLS_RSA_WITH_AES_256_GCM_SHA384", Const, 6}, + {"TLS_RSA_WITH_RC4_128_SHA", Const, 0}, + {"VerifyClientCertIfGiven", Const, 0}, + {"VersionName", Func, 21}, + {"VersionSSL30", Const, 2}, + {"VersionTLS10", Const, 2}, + {"VersionTLS11", Const, 2}, + {"VersionTLS12", Const, 2}, + {"VersionTLS13", Const, 12}, + {"X25519", Const, 8}, + {"X509KeyPair", Func, 0}, + }, + "crypto/x509": { + {"(*CertPool).AddCert", Method, 0}, + {"(*CertPool).AddCertWithConstraint", Method, 22}, + {"(*CertPool).AppendCertsFromPEM", Method, 0}, + {"(*CertPool).Clone", Method, 19}, + {"(*CertPool).Equal", Method, 19}, + {"(*CertPool).Subjects", Method, 0}, + {"(*Certificate).CheckCRLSignature", Method, 0}, + {"(*Certificate).CheckSignature", Method, 0}, + {"(*Certificate).CheckSignatureFrom", Method, 0}, + {"(*Certificate).CreateCRL", Method, 0}, + {"(*Certificate).Equal", Method, 0}, + {"(*Certificate).Verify", Method, 0}, + {"(*Certificate).VerifyHostname", Method, 0}, + {"(*CertificateRequest).CheckSignature", Method, 5}, + {"(*RevocationList).CheckSignatureFrom", Method, 19}, + {"(CertificateInvalidError).Error", Method, 0}, + {"(ConstraintViolationError).Error", Method, 0}, + {"(HostnameError).Error", Method, 0}, + {"(InsecureAlgorithmError).Error", Method, 6}, + {"(OID).Equal", Method, 22}, + {"(OID).EqualASN1OID", Method, 22}, + {"(OID).String", Method, 22}, + {"(PublicKeyAlgorithm).String", Method, 10}, + {"(SignatureAlgorithm).String", Method, 6}, + {"(SystemRootsError).Error", Method, 1}, + {"(SystemRootsError).Unwrap", Method, 16}, + {"(UnhandledCriticalExtension).Error", Method, 0}, + {"(UnknownAuthorityError).Error", Method, 0}, + {"CANotAuthorizedForExtKeyUsage", Const, 10}, + {"CANotAuthorizedForThisName", Const, 0}, + {"CertPool", Type, 0}, + {"Certificate", Type, 0}, + {"Certificate.AuthorityKeyId", Field, 0}, + {"Certificate.BasicConstraintsValid", Field, 0}, + {"Certificate.CRLDistributionPoints", Field, 2}, + {"Certificate.DNSNames", Field, 0}, + {"Certificate.EmailAddresses", Field, 0}, + {"Certificate.ExcludedDNSDomains", Field, 9}, + {"Certificate.ExcludedEmailAddresses", Field, 10}, + {"Certificate.ExcludedIPRanges", Field, 10}, + {"Certificate.ExcludedURIDomains", Field, 10}, + {"Certificate.ExtKeyUsage", Field, 0}, + {"Certificate.Extensions", Field, 2}, + {"Certificate.ExtraExtensions", Field, 2}, + {"Certificate.IPAddresses", Field, 1}, + {"Certificate.IsCA", Field, 0}, + {"Certificate.Issuer", Field, 0}, + {"Certificate.IssuingCertificateURL", Field, 2}, + {"Certificate.KeyUsage", Field, 0}, + {"Certificate.MaxPathLen", Field, 0}, + {"Certificate.MaxPathLenZero", Field, 4}, + {"Certificate.NotAfter", Field, 0}, + {"Certificate.NotBefore", Field, 0}, + {"Certificate.OCSPServer", Field, 2}, + {"Certificate.PermittedDNSDomains", Field, 0}, + {"Certificate.PermittedDNSDomainsCritical", Field, 0}, + {"Certificate.PermittedEmailAddresses", Field, 10}, + {"Certificate.PermittedIPRanges", Field, 10}, + {"Certificate.PermittedURIDomains", Field, 10}, + {"Certificate.Policies", Field, 22}, + {"Certificate.PolicyIdentifiers", Field, 0}, + {"Certificate.PublicKey", Field, 0}, + {"Certificate.PublicKeyAlgorithm", Field, 0}, + {"Certificate.Raw", Field, 0}, + {"Certificate.RawIssuer", Field, 0}, + {"Certificate.RawSubject", Field, 0}, + {"Certificate.RawSubjectPublicKeyInfo", Field, 0}, + {"Certificate.RawTBSCertificate", Field, 0}, + {"Certificate.SerialNumber", Field, 0}, + {"Certificate.Signature", Field, 0}, + {"Certificate.SignatureAlgorithm", Field, 0}, + {"Certificate.Subject", Field, 0}, + {"Certificate.SubjectKeyId", Field, 0}, + {"Certificate.URIs", Field, 10}, + {"Certificate.UnhandledCriticalExtensions", Field, 5}, + {"Certificate.UnknownExtKeyUsage", Field, 0}, + {"Certificate.Version", Field, 0}, + {"CertificateInvalidError", Type, 0}, + {"CertificateInvalidError.Cert", Field, 0}, + {"CertificateInvalidError.Detail", Field, 10}, + {"CertificateInvalidError.Reason", Field, 0}, + {"CertificateRequest", Type, 3}, + {"CertificateRequest.Attributes", Field, 3}, + {"CertificateRequest.DNSNames", Field, 3}, + {"CertificateRequest.EmailAddresses", Field, 3}, + {"CertificateRequest.Extensions", Field, 3}, + {"CertificateRequest.ExtraExtensions", Field, 3}, + {"CertificateRequest.IPAddresses", Field, 3}, + {"CertificateRequest.PublicKey", Field, 3}, + {"CertificateRequest.PublicKeyAlgorithm", Field, 3}, + {"CertificateRequest.Raw", Field, 3}, + {"CertificateRequest.RawSubject", Field, 3}, + {"CertificateRequest.RawSubjectPublicKeyInfo", Field, 3}, + {"CertificateRequest.RawTBSCertificateRequest", Field, 3}, + {"CertificateRequest.Signature", Field, 3}, + {"CertificateRequest.SignatureAlgorithm", Field, 3}, + {"CertificateRequest.Subject", Field, 3}, + {"CertificateRequest.URIs", Field, 10}, + {"CertificateRequest.Version", Field, 3}, + {"ConstraintViolationError", Type, 0}, + {"CreateCertificate", Func, 0}, + {"CreateCertificateRequest", Func, 3}, + {"CreateRevocationList", Func, 15}, + {"DSA", Const, 0}, + {"DSAWithSHA1", Const, 0}, + {"DSAWithSHA256", Const, 0}, + {"DecryptPEMBlock", Func, 1}, + {"ECDSA", Const, 1}, + {"ECDSAWithSHA1", Const, 1}, + {"ECDSAWithSHA256", Const, 1}, + {"ECDSAWithSHA384", Const, 1}, + {"ECDSAWithSHA512", Const, 1}, + {"Ed25519", Const, 13}, + {"EncryptPEMBlock", Func, 1}, + {"ErrUnsupportedAlgorithm", Var, 0}, + {"Expired", Const, 0}, + {"ExtKeyUsage", Type, 0}, + {"ExtKeyUsageAny", Const, 0}, + {"ExtKeyUsageClientAuth", Const, 0}, + {"ExtKeyUsageCodeSigning", Const, 0}, + {"ExtKeyUsageEmailProtection", Const, 0}, + {"ExtKeyUsageIPSECEndSystem", Const, 1}, + {"ExtKeyUsageIPSECTunnel", Const, 1}, + {"ExtKeyUsageIPSECUser", Const, 1}, + {"ExtKeyUsageMicrosoftCommercialCodeSigning", Const, 10}, + {"ExtKeyUsageMicrosoftKernelCodeSigning", Const, 10}, + {"ExtKeyUsageMicrosoftServerGatedCrypto", Const, 1}, + {"ExtKeyUsageNetscapeServerGatedCrypto", Const, 1}, + {"ExtKeyUsageOCSPSigning", Const, 0}, + {"ExtKeyUsageServerAuth", Const, 0}, + {"ExtKeyUsageTimeStamping", Const, 0}, + {"HostnameError", Type, 0}, + {"HostnameError.Certificate", Field, 0}, + {"HostnameError.Host", Field, 0}, + {"IncompatibleUsage", Const, 1}, + {"IncorrectPasswordError", Var, 1}, + {"InsecureAlgorithmError", Type, 6}, + {"InvalidReason", Type, 0}, + {"IsEncryptedPEMBlock", Func, 1}, + {"KeyUsage", Type, 0}, + {"KeyUsageCRLSign", Const, 0}, + {"KeyUsageCertSign", Const, 0}, + {"KeyUsageContentCommitment", Const, 0}, + {"KeyUsageDataEncipherment", Const, 0}, + {"KeyUsageDecipherOnly", Const, 0}, + {"KeyUsageDigitalSignature", Const, 0}, + {"KeyUsageEncipherOnly", Const, 0}, + {"KeyUsageKeyAgreement", Const, 0}, + {"KeyUsageKeyEncipherment", Const, 0}, + {"MD2WithRSA", Const, 0}, + {"MD5WithRSA", Const, 0}, + {"MarshalECPrivateKey", Func, 2}, + {"MarshalPKCS1PrivateKey", Func, 0}, + {"MarshalPKCS1PublicKey", Func, 10}, + {"MarshalPKCS8PrivateKey", Func, 10}, + {"MarshalPKIXPublicKey", Func, 0}, + {"NameConstraintsWithoutSANs", Const, 10}, + {"NameMismatch", Const, 8}, + {"NewCertPool", Func, 0}, + {"NotAuthorizedToSign", Const, 0}, + {"OID", Type, 22}, + {"OIDFromInts", Func, 22}, + {"PEMCipher", Type, 1}, + {"PEMCipher3DES", Const, 1}, + {"PEMCipherAES128", Const, 1}, + {"PEMCipherAES192", Const, 1}, + {"PEMCipherAES256", Const, 1}, + {"PEMCipherDES", Const, 1}, + {"ParseCRL", Func, 0}, + {"ParseCertificate", Func, 0}, + {"ParseCertificateRequest", Func, 3}, + {"ParseCertificates", Func, 0}, + {"ParseDERCRL", Func, 0}, + {"ParseECPrivateKey", Func, 1}, + {"ParsePKCS1PrivateKey", Func, 0}, + {"ParsePKCS1PublicKey", Func, 10}, + {"ParsePKCS8PrivateKey", Func, 0}, + {"ParsePKIXPublicKey", Func, 0}, + {"ParseRevocationList", Func, 19}, + {"PublicKeyAlgorithm", Type, 0}, + {"PureEd25519", Const, 13}, + {"RSA", Const, 0}, + {"RevocationList", Type, 15}, + {"RevocationList.AuthorityKeyId", Field, 19}, + {"RevocationList.Extensions", Field, 19}, + {"RevocationList.ExtraExtensions", Field, 15}, + {"RevocationList.Issuer", Field, 19}, + {"RevocationList.NextUpdate", Field, 15}, + {"RevocationList.Number", Field, 15}, + {"RevocationList.Raw", Field, 19}, + {"RevocationList.RawIssuer", Field, 19}, + {"RevocationList.RawTBSRevocationList", Field, 19}, + {"RevocationList.RevokedCertificateEntries", Field, 21}, + {"RevocationList.RevokedCertificates", Field, 15}, + {"RevocationList.Signature", Field, 19}, + {"RevocationList.SignatureAlgorithm", Field, 15}, + {"RevocationList.ThisUpdate", Field, 15}, + {"RevocationListEntry", Type, 21}, + {"RevocationListEntry.Extensions", Field, 21}, + {"RevocationListEntry.ExtraExtensions", Field, 21}, + {"RevocationListEntry.Raw", Field, 21}, + {"RevocationListEntry.ReasonCode", Field, 21}, + {"RevocationListEntry.RevocationTime", Field, 21}, + {"RevocationListEntry.SerialNumber", Field, 21}, + {"SHA1WithRSA", Const, 0}, + {"SHA256WithRSA", Const, 0}, + {"SHA256WithRSAPSS", Const, 8}, + {"SHA384WithRSA", Const, 0}, + {"SHA384WithRSAPSS", Const, 8}, + {"SHA512WithRSA", Const, 0}, + {"SHA512WithRSAPSS", Const, 8}, + {"SetFallbackRoots", Func, 20}, + {"SignatureAlgorithm", Type, 0}, + {"SystemCertPool", Func, 7}, + {"SystemRootsError", Type, 1}, + {"SystemRootsError.Err", Field, 7}, + {"TooManyConstraints", Const, 10}, + {"TooManyIntermediates", Const, 0}, + {"UnconstrainedName", Const, 10}, + {"UnhandledCriticalExtension", Type, 0}, + {"UnknownAuthorityError", Type, 0}, + {"UnknownAuthorityError.Cert", Field, 8}, + {"UnknownPublicKeyAlgorithm", Const, 0}, + {"UnknownSignatureAlgorithm", Const, 0}, + {"VerifyOptions", Type, 0}, + {"VerifyOptions.CurrentTime", Field, 0}, + {"VerifyOptions.DNSName", Field, 0}, + {"VerifyOptions.Intermediates", Field, 0}, + {"VerifyOptions.KeyUsages", Field, 1}, + {"VerifyOptions.MaxConstraintComparisions", Field, 10}, + {"VerifyOptions.Roots", Field, 0}, + }, + "crypto/x509/pkix": { + {"(*CertificateList).HasExpired", Method, 0}, + {"(*Name).FillFromRDNSequence", Method, 0}, + {"(Name).String", Method, 10}, + {"(Name).ToRDNSequence", Method, 0}, + {"(RDNSequence).String", Method, 10}, + {"AlgorithmIdentifier", Type, 0}, + {"AlgorithmIdentifier.Algorithm", Field, 0}, + {"AlgorithmIdentifier.Parameters", Field, 0}, + {"AttributeTypeAndValue", Type, 0}, + {"AttributeTypeAndValue.Type", Field, 0}, + {"AttributeTypeAndValue.Value", Field, 0}, + {"AttributeTypeAndValueSET", Type, 3}, + {"AttributeTypeAndValueSET.Type", Field, 3}, + {"AttributeTypeAndValueSET.Value", Field, 3}, + {"CertificateList", Type, 0}, + {"CertificateList.SignatureAlgorithm", Field, 0}, + {"CertificateList.SignatureValue", Field, 0}, + {"CertificateList.TBSCertList", Field, 0}, + {"Extension", Type, 0}, + {"Extension.Critical", Field, 0}, + {"Extension.Id", Field, 0}, + {"Extension.Value", Field, 0}, + {"Name", Type, 0}, + {"Name.CommonName", Field, 0}, + {"Name.Country", Field, 0}, + {"Name.ExtraNames", Field, 5}, + {"Name.Locality", Field, 0}, + {"Name.Names", Field, 0}, + {"Name.Organization", Field, 0}, + {"Name.OrganizationalUnit", Field, 0}, + {"Name.PostalCode", Field, 0}, + {"Name.Province", Field, 0}, + {"Name.SerialNumber", Field, 0}, + {"Name.StreetAddress", Field, 0}, + {"RDNSequence", Type, 0}, + {"RelativeDistinguishedNameSET", Type, 0}, + {"RevokedCertificate", Type, 0}, + {"RevokedCertificate.Extensions", Field, 0}, + {"RevokedCertificate.RevocationTime", Field, 0}, + {"RevokedCertificate.SerialNumber", Field, 0}, + {"TBSCertificateList", Type, 0}, + {"TBSCertificateList.Extensions", Field, 0}, + {"TBSCertificateList.Issuer", Field, 0}, + {"TBSCertificateList.NextUpdate", Field, 0}, + {"TBSCertificateList.Raw", Field, 0}, + {"TBSCertificateList.RevokedCertificates", Field, 0}, + {"TBSCertificateList.Signature", Field, 0}, + {"TBSCertificateList.ThisUpdate", Field, 0}, + {"TBSCertificateList.Version", Field, 0}, + }, + "database/sql": { + {"(*ColumnType).DatabaseTypeName", Method, 8}, + {"(*ColumnType).DecimalSize", Method, 8}, + {"(*ColumnType).Length", Method, 8}, + {"(*ColumnType).Name", Method, 8}, + {"(*ColumnType).Nullable", Method, 8}, + {"(*ColumnType).ScanType", Method, 8}, + {"(*Conn).BeginTx", Method, 9}, + {"(*Conn).Close", Method, 9}, + {"(*Conn).ExecContext", Method, 9}, + {"(*Conn).PingContext", Method, 9}, + {"(*Conn).PrepareContext", Method, 9}, + {"(*Conn).QueryContext", Method, 9}, + {"(*Conn).QueryRowContext", Method, 9}, + {"(*Conn).Raw", Method, 13}, + {"(*DB).Begin", Method, 0}, + {"(*DB).BeginTx", Method, 8}, + {"(*DB).Close", Method, 0}, + {"(*DB).Conn", Method, 9}, + {"(*DB).Driver", Method, 0}, + {"(*DB).Exec", Method, 0}, + {"(*DB).ExecContext", Method, 8}, + {"(*DB).Ping", Method, 1}, + {"(*DB).PingContext", Method, 8}, + {"(*DB).Prepare", Method, 0}, + {"(*DB).PrepareContext", Method, 8}, + {"(*DB).Query", Method, 0}, + {"(*DB).QueryContext", Method, 8}, + {"(*DB).QueryRow", Method, 0}, + {"(*DB).QueryRowContext", Method, 8}, + {"(*DB).SetConnMaxIdleTime", Method, 15}, + {"(*DB).SetConnMaxLifetime", Method, 6}, + {"(*DB).SetMaxIdleConns", Method, 1}, + {"(*DB).SetMaxOpenConns", Method, 2}, + {"(*DB).Stats", Method, 5}, + {"(*Null).Scan", Method, 22}, + {"(*NullBool).Scan", Method, 0}, + {"(*NullByte).Scan", Method, 17}, + {"(*NullFloat64).Scan", Method, 0}, + {"(*NullInt16).Scan", Method, 17}, + {"(*NullInt32).Scan", Method, 13}, + {"(*NullInt64).Scan", Method, 0}, + {"(*NullString).Scan", Method, 0}, + {"(*NullTime).Scan", Method, 13}, + {"(*Row).Err", Method, 15}, + {"(*Row).Scan", Method, 0}, + {"(*Rows).Close", Method, 0}, + {"(*Rows).ColumnTypes", Method, 8}, + {"(*Rows).Columns", Method, 0}, + {"(*Rows).Err", Method, 0}, + {"(*Rows).Next", Method, 0}, + {"(*Rows).NextResultSet", Method, 8}, + {"(*Rows).Scan", Method, 0}, + {"(*Stmt).Close", Method, 0}, + {"(*Stmt).Exec", Method, 0}, + {"(*Stmt).ExecContext", Method, 8}, + {"(*Stmt).Query", Method, 0}, + {"(*Stmt).QueryContext", Method, 8}, + {"(*Stmt).QueryRow", Method, 0}, + {"(*Stmt).QueryRowContext", Method, 8}, + {"(*Tx).Commit", Method, 0}, + {"(*Tx).Exec", Method, 0}, + {"(*Tx).ExecContext", Method, 8}, + {"(*Tx).Prepare", Method, 0}, + {"(*Tx).PrepareContext", Method, 8}, + {"(*Tx).Query", Method, 0}, + {"(*Tx).QueryContext", Method, 8}, + {"(*Tx).QueryRow", Method, 0}, + {"(*Tx).QueryRowContext", Method, 8}, + {"(*Tx).Rollback", Method, 0}, + {"(*Tx).Stmt", Method, 0}, + {"(*Tx).StmtContext", Method, 8}, + {"(IsolationLevel).String", Method, 11}, + {"(Null).Value", Method, 22}, + {"(NullBool).Value", Method, 0}, + {"(NullByte).Value", Method, 17}, + {"(NullFloat64).Value", Method, 0}, + {"(NullInt16).Value", Method, 17}, + {"(NullInt32).Value", Method, 13}, + {"(NullInt64).Value", Method, 0}, + {"(NullString).Value", Method, 0}, + {"(NullTime).Value", Method, 13}, + {"ColumnType", Type, 8}, + {"Conn", Type, 9}, + {"DB", Type, 0}, + {"DBStats", Type, 5}, + {"DBStats.Idle", Field, 11}, + {"DBStats.InUse", Field, 11}, + {"DBStats.MaxIdleClosed", Field, 11}, + {"DBStats.MaxIdleTimeClosed", Field, 15}, + {"DBStats.MaxLifetimeClosed", Field, 11}, + {"DBStats.MaxOpenConnections", Field, 11}, + {"DBStats.OpenConnections", Field, 5}, + {"DBStats.WaitCount", Field, 11}, + {"DBStats.WaitDuration", Field, 11}, + {"Drivers", Func, 4}, + {"ErrConnDone", Var, 9}, + {"ErrNoRows", Var, 0}, + {"ErrTxDone", Var, 0}, + {"IsolationLevel", Type, 8}, + {"LevelDefault", Const, 8}, + {"LevelLinearizable", Const, 8}, + {"LevelReadCommitted", Const, 8}, + {"LevelReadUncommitted", Const, 8}, + {"LevelRepeatableRead", Const, 8}, + {"LevelSerializable", Const, 8}, + {"LevelSnapshot", Const, 8}, + {"LevelWriteCommitted", Const, 8}, + {"Named", Func, 8}, + {"NamedArg", Type, 8}, + {"NamedArg.Name", Field, 8}, + {"NamedArg.Value", Field, 8}, + {"Null", Type, 22}, + {"Null.V", Field, 22}, + {"Null.Valid", Field, 22}, + {"NullBool", Type, 0}, + {"NullBool.Bool", Field, 0}, + {"NullBool.Valid", Field, 0}, + {"NullByte", Type, 17}, + {"NullByte.Byte", Field, 17}, + {"NullByte.Valid", Field, 17}, + {"NullFloat64", Type, 0}, + {"NullFloat64.Float64", Field, 0}, + {"NullFloat64.Valid", Field, 0}, + {"NullInt16", Type, 17}, + {"NullInt16.Int16", Field, 17}, + {"NullInt16.Valid", Field, 17}, + {"NullInt32", Type, 13}, + {"NullInt32.Int32", Field, 13}, + {"NullInt32.Valid", Field, 13}, + {"NullInt64", Type, 0}, + {"NullInt64.Int64", Field, 0}, + {"NullInt64.Valid", Field, 0}, + {"NullString", Type, 0}, + {"NullString.String", Field, 0}, + {"NullString.Valid", Field, 0}, + {"NullTime", Type, 13}, + {"NullTime.Time", Field, 13}, + {"NullTime.Valid", Field, 13}, + {"Open", Func, 0}, + {"OpenDB", Func, 10}, + {"Out", Type, 9}, + {"Out.Dest", Field, 9}, + {"Out.In", Field, 9}, + {"RawBytes", Type, 0}, + {"Register", Func, 0}, + {"Result", Type, 0}, + {"Row", Type, 0}, + {"Rows", Type, 0}, + {"Scanner", Type, 0}, + {"Stmt", Type, 0}, + {"Tx", Type, 0}, + {"TxOptions", Type, 8}, + {"TxOptions.Isolation", Field, 8}, + {"TxOptions.ReadOnly", Field, 8}, + }, + "database/sql/driver": { + {"(NotNull).ConvertValue", Method, 0}, + {"(Null).ConvertValue", Method, 0}, + {"(RowsAffected).LastInsertId", Method, 0}, + {"(RowsAffected).RowsAffected", Method, 0}, + {"Bool", Var, 0}, + {"ColumnConverter", Type, 0}, + {"Conn", Type, 0}, + {"ConnBeginTx", Type, 8}, + {"ConnPrepareContext", Type, 8}, + {"Connector", Type, 10}, + {"DefaultParameterConverter", Var, 0}, + {"Driver", Type, 0}, + {"DriverContext", Type, 10}, + {"ErrBadConn", Var, 0}, + {"ErrRemoveArgument", Var, 9}, + {"ErrSkip", Var, 0}, + {"Execer", Type, 0}, + {"ExecerContext", Type, 8}, + {"Int32", Var, 0}, + {"IsScanValue", Func, 0}, + {"IsValue", Func, 0}, + {"IsolationLevel", Type, 8}, + {"NamedValue", Type, 8}, + {"NamedValue.Name", Field, 8}, + {"NamedValue.Ordinal", Field, 8}, + {"NamedValue.Value", Field, 8}, + {"NamedValueChecker", Type, 9}, + {"NotNull", Type, 0}, + {"NotNull.Converter", Field, 0}, + {"Null", Type, 0}, + {"Null.Converter", Field, 0}, + {"Pinger", Type, 8}, + {"Queryer", Type, 1}, + {"QueryerContext", Type, 8}, + {"Result", Type, 0}, + {"ResultNoRows", Var, 0}, + {"Rows", Type, 0}, + {"RowsAffected", Type, 0}, + {"RowsColumnTypeDatabaseTypeName", Type, 8}, + {"RowsColumnTypeLength", Type, 8}, + {"RowsColumnTypeNullable", Type, 8}, + {"RowsColumnTypePrecisionScale", Type, 8}, + {"RowsColumnTypeScanType", Type, 8}, + {"RowsNextResultSet", Type, 8}, + {"SessionResetter", Type, 10}, + {"Stmt", Type, 0}, + {"StmtExecContext", Type, 8}, + {"StmtQueryContext", Type, 8}, + {"String", Var, 0}, + {"Tx", Type, 0}, + {"TxOptions", Type, 8}, + {"TxOptions.Isolation", Field, 8}, + {"TxOptions.ReadOnly", Field, 8}, + {"Validator", Type, 15}, + {"Value", Type, 0}, + {"ValueConverter", Type, 0}, + {"Valuer", Type, 0}, + }, + "debug/buildinfo": { + {"BuildInfo", Type, 18}, + {"Read", Func, 18}, + {"ReadFile", Func, 18}, + }, + "debug/dwarf": { + {"(*AddrType).Basic", Method, 0}, + {"(*AddrType).Common", Method, 0}, + {"(*AddrType).Size", Method, 0}, + {"(*AddrType).String", Method, 0}, + {"(*ArrayType).Common", Method, 0}, + {"(*ArrayType).Size", Method, 0}, + {"(*ArrayType).String", Method, 0}, + {"(*BasicType).Basic", Method, 0}, + {"(*BasicType).Common", Method, 0}, + {"(*BasicType).Size", Method, 0}, + {"(*BasicType).String", Method, 0}, + {"(*BoolType).Basic", Method, 0}, + {"(*BoolType).Common", Method, 0}, + {"(*BoolType).Size", Method, 0}, + {"(*BoolType).String", Method, 0}, + {"(*CharType).Basic", Method, 0}, + {"(*CharType).Common", Method, 0}, + {"(*CharType).Size", Method, 0}, + {"(*CharType).String", Method, 0}, + {"(*CommonType).Common", Method, 0}, + {"(*CommonType).Size", Method, 0}, + {"(*ComplexType).Basic", Method, 0}, + {"(*ComplexType).Common", Method, 0}, + {"(*ComplexType).Size", Method, 0}, + {"(*ComplexType).String", Method, 0}, + {"(*Data).AddSection", Method, 14}, + {"(*Data).AddTypes", Method, 3}, + {"(*Data).LineReader", Method, 5}, + {"(*Data).Ranges", Method, 7}, + {"(*Data).Reader", Method, 0}, + {"(*Data).Type", Method, 0}, + {"(*DotDotDotType).Common", Method, 0}, + {"(*DotDotDotType).Size", Method, 0}, + {"(*DotDotDotType).String", Method, 0}, + {"(*Entry).AttrField", Method, 5}, + {"(*Entry).Val", Method, 0}, + {"(*EnumType).Common", Method, 0}, + {"(*EnumType).Size", Method, 0}, + {"(*EnumType).String", Method, 0}, + {"(*FloatType).Basic", Method, 0}, + {"(*FloatType).Common", Method, 0}, + {"(*FloatType).Size", Method, 0}, + {"(*FloatType).String", Method, 0}, + {"(*FuncType).Common", Method, 0}, + {"(*FuncType).Size", Method, 0}, + {"(*FuncType).String", Method, 0}, + {"(*IntType).Basic", Method, 0}, + {"(*IntType).Common", Method, 0}, + {"(*IntType).Size", Method, 0}, + {"(*IntType).String", Method, 0}, + {"(*LineReader).Files", Method, 14}, + {"(*LineReader).Next", Method, 5}, + {"(*LineReader).Reset", Method, 5}, + {"(*LineReader).Seek", Method, 5}, + {"(*LineReader).SeekPC", Method, 5}, + {"(*LineReader).Tell", Method, 5}, + {"(*PtrType).Common", Method, 0}, + {"(*PtrType).Size", Method, 0}, + {"(*PtrType).String", Method, 0}, + {"(*QualType).Common", Method, 0}, + {"(*QualType).Size", Method, 0}, + {"(*QualType).String", Method, 0}, + {"(*Reader).AddressSize", Method, 5}, + {"(*Reader).ByteOrder", Method, 14}, + {"(*Reader).Next", Method, 0}, + {"(*Reader).Seek", Method, 0}, + {"(*Reader).SeekPC", Method, 7}, + {"(*Reader).SkipChildren", Method, 0}, + {"(*StructType).Common", Method, 0}, + {"(*StructType).Defn", Method, 0}, + {"(*StructType).Size", Method, 0}, + {"(*StructType).String", Method, 0}, + {"(*TypedefType).Common", Method, 0}, + {"(*TypedefType).Size", Method, 0}, + {"(*TypedefType).String", Method, 0}, + {"(*UcharType).Basic", Method, 0}, + {"(*UcharType).Common", Method, 0}, + {"(*UcharType).Size", Method, 0}, + {"(*UcharType).String", Method, 0}, + {"(*UintType).Basic", Method, 0}, + {"(*UintType).Common", Method, 0}, + {"(*UintType).Size", Method, 0}, + {"(*UintType).String", Method, 0}, + {"(*UnspecifiedType).Basic", Method, 4}, + {"(*UnspecifiedType).Common", Method, 4}, + {"(*UnspecifiedType).Size", Method, 4}, + {"(*UnspecifiedType).String", Method, 4}, + {"(*UnsupportedType).Common", Method, 13}, + {"(*UnsupportedType).Size", Method, 13}, + {"(*UnsupportedType).String", Method, 13}, + {"(*VoidType).Common", Method, 0}, + {"(*VoidType).Size", Method, 0}, + {"(*VoidType).String", Method, 0}, + {"(Attr).GoString", Method, 0}, + {"(Attr).String", Method, 0}, + {"(Class).GoString", Method, 5}, + {"(Class).String", Method, 5}, + {"(DecodeError).Error", Method, 0}, + {"(Tag).GoString", Method, 0}, + {"(Tag).String", Method, 0}, + {"AddrType", Type, 0}, + {"AddrType.BasicType", Field, 0}, + {"ArrayType", Type, 0}, + {"ArrayType.CommonType", Field, 0}, + {"ArrayType.Count", Field, 0}, + {"ArrayType.StrideBitSize", Field, 0}, + {"ArrayType.Type", Field, 0}, + {"Attr", Type, 0}, + {"AttrAbstractOrigin", Const, 0}, + {"AttrAccessibility", Const, 0}, + {"AttrAddrBase", Const, 14}, + {"AttrAddrClass", Const, 0}, + {"AttrAlignment", Const, 14}, + {"AttrAllocated", Const, 0}, + {"AttrArtificial", Const, 0}, + {"AttrAssociated", Const, 0}, + {"AttrBaseTypes", Const, 0}, + {"AttrBinaryScale", Const, 14}, + {"AttrBitOffset", Const, 0}, + {"AttrBitSize", Const, 0}, + {"AttrByteSize", Const, 0}, + {"AttrCallAllCalls", Const, 14}, + {"AttrCallAllSourceCalls", Const, 14}, + {"AttrCallAllTailCalls", Const, 14}, + {"AttrCallColumn", Const, 0}, + {"AttrCallDataLocation", Const, 14}, + {"AttrCallDataValue", Const, 14}, + {"AttrCallFile", Const, 0}, + {"AttrCallLine", Const, 0}, + {"AttrCallOrigin", Const, 14}, + {"AttrCallPC", Const, 14}, + {"AttrCallParameter", Const, 14}, + {"AttrCallReturnPC", Const, 14}, + {"AttrCallTailCall", Const, 14}, + {"AttrCallTarget", Const, 14}, + {"AttrCallTargetClobbered", Const, 14}, + {"AttrCallValue", Const, 14}, + {"AttrCalling", Const, 0}, + {"AttrCommonRef", Const, 0}, + {"AttrCompDir", Const, 0}, + {"AttrConstExpr", Const, 14}, + {"AttrConstValue", Const, 0}, + {"AttrContainingType", Const, 0}, + {"AttrCount", Const, 0}, + {"AttrDataBitOffset", Const, 14}, + {"AttrDataLocation", Const, 0}, + {"AttrDataMemberLoc", Const, 0}, + {"AttrDecimalScale", Const, 14}, + {"AttrDecimalSign", Const, 14}, + {"AttrDeclColumn", Const, 0}, + {"AttrDeclFile", Const, 0}, + {"AttrDeclLine", Const, 0}, + {"AttrDeclaration", Const, 0}, + {"AttrDefaultValue", Const, 0}, + {"AttrDefaulted", Const, 14}, + {"AttrDeleted", Const, 14}, + {"AttrDescription", Const, 0}, + {"AttrDigitCount", Const, 14}, + {"AttrDiscr", Const, 0}, + {"AttrDiscrList", Const, 0}, + {"AttrDiscrValue", Const, 0}, + {"AttrDwoName", Const, 14}, + {"AttrElemental", Const, 14}, + {"AttrEncoding", Const, 0}, + {"AttrEndianity", Const, 14}, + {"AttrEntrypc", Const, 0}, + {"AttrEnumClass", Const, 14}, + {"AttrExplicit", Const, 14}, + {"AttrExportSymbols", Const, 14}, + {"AttrExtension", Const, 0}, + {"AttrExternal", Const, 0}, + {"AttrFrameBase", Const, 0}, + {"AttrFriend", Const, 0}, + {"AttrHighpc", Const, 0}, + {"AttrIdentifierCase", Const, 0}, + {"AttrImport", Const, 0}, + {"AttrInline", Const, 0}, + {"AttrIsOptional", Const, 0}, + {"AttrLanguage", Const, 0}, + {"AttrLinkageName", Const, 14}, + {"AttrLocation", Const, 0}, + {"AttrLoclistsBase", Const, 14}, + {"AttrLowerBound", Const, 0}, + {"AttrLowpc", Const, 0}, + {"AttrMacroInfo", Const, 0}, + {"AttrMacros", Const, 14}, + {"AttrMainSubprogram", Const, 14}, + {"AttrMutable", Const, 14}, + {"AttrName", Const, 0}, + {"AttrNamelistItem", Const, 0}, + {"AttrNoreturn", Const, 14}, + {"AttrObjectPointer", Const, 14}, + {"AttrOrdering", Const, 0}, + {"AttrPictureString", Const, 14}, + {"AttrPriority", Const, 0}, + {"AttrProducer", Const, 0}, + {"AttrPrototyped", Const, 0}, + {"AttrPure", Const, 14}, + {"AttrRanges", Const, 0}, + {"AttrRank", Const, 14}, + {"AttrRecursive", Const, 14}, + {"AttrReference", Const, 14}, + {"AttrReturnAddr", Const, 0}, + {"AttrRnglistsBase", Const, 14}, + {"AttrRvalueReference", Const, 14}, + {"AttrSegment", Const, 0}, + {"AttrSibling", Const, 0}, + {"AttrSignature", Const, 14}, + {"AttrSmall", Const, 14}, + {"AttrSpecification", Const, 0}, + {"AttrStartScope", Const, 0}, + {"AttrStaticLink", Const, 0}, + {"AttrStmtList", Const, 0}, + {"AttrStrOffsetsBase", Const, 14}, + {"AttrStride", Const, 0}, + {"AttrStrideSize", Const, 0}, + {"AttrStringLength", Const, 0}, + {"AttrStringLengthBitSize", Const, 14}, + {"AttrStringLengthByteSize", Const, 14}, + {"AttrThreadsScaled", Const, 14}, + {"AttrTrampoline", Const, 0}, + {"AttrType", Const, 0}, + {"AttrUpperBound", Const, 0}, + {"AttrUseLocation", Const, 0}, + {"AttrUseUTF8", Const, 0}, + {"AttrVarParam", Const, 0}, + {"AttrVirtuality", Const, 0}, + {"AttrVisibility", Const, 0}, + {"AttrVtableElemLoc", Const, 0}, + {"BasicType", Type, 0}, + {"BasicType.BitOffset", Field, 0}, + {"BasicType.BitSize", Field, 0}, + {"BasicType.CommonType", Field, 0}, + {"BasicType.DataBitOffset", Field, 18}, + {"BoolType", Type, 0}, + {"BoolType.BasicType", Field, 0}, + {"CharType", Type, 0}, + {"CharType.BasicType", Field, 0}, + {"Class", Type, 5}, + {"ClassAddrPtr", Const, 14}, + {"ClassAddress", Const, 5}, + {"ClassBlock", Const, 5}, + {"ClassConstant", Const, 5}, + {"ClassExprLoc", Const, 5}, + {"ClassFlag", Const, 5}, + {"ClassLinePtr", Const, 5}, + {"ClassLocList", Const, 14}, + {"ClassLocListPtr", Const, 5}, + {"ClassMacPtr", Const, 5}, + {"ClassRangeListPtr", Const, 5}, + {"ClassReference", Const, 5}, + {"ClassReferenceAlt", Const, 5}, + {"ClassReferenceSig", Const, 5}, + {"ClassRngList", Const, 14}, + {"ClassRngListsPtr", Const, 14}, + {"ClassStrOffsetsPtr", Const, 14}, + {"ClassString", Const, 5}, + {"ClassStringAlt", Const, 5}, + {"ClassUnknown", Const, 6}, + {"CommonType", Type, 0}, + {"CommonType.ByteSize", Field, 0}, + {"CommonType.Name", Field, 0}, + {"ComplexType", Type, 0}, + {"ComplexType.BasicType", Field, 0}, + {"Data", Type, 0}, + {"DecodeError", Type, 0}, + {"DecodeError.Err", Field, 0}, + {"DecodeError.Name", Field, 0}, + {"DecodeError.Offset", Field, 0}, + {"DotDotDotType", Type, 0}, + {"DotDotDotType.CommonType", Field, 0}, + {"Entry", Type, 0}, + {"Entry.Children", Field, 0}, + {"Entry.Field", Field, 0}, + {"Entry.Offset", Field, 0}, + {"Entry.Tag", Field, 0}, + {"EnumType", Type, 0}, + {"EnumType.CommonType", Field, 0}, + {"EnumType.EnumName", Field, 0}, + {"EnumType.Val", Field, 0}, + {"EnumValue", Type, 0}, + {"EnumValue.Name", Field, 0}, + {"EnumValue.Val", Field, 0}, + {"ErrUnknownPC", Var, 5}, + {"Field", Type, 0}, + {"Field.Attr", Field, 0}, + {"Field.Class", Field, 5}, + {"Field.Val", Field, 0}, + {"FloatType", Type, 0}, + {"FloatType.BasicType", Field, 0}, + {"FuncType", Type, 0}, + {"FuncType.CommonType", Field, 0}, + {"FuncType.ParamType", Field, 0}, + {"FuncType.ReturnType", Field, 0}, + {"IntType", Type, 0}, + {"IntType.BasicType", Field, 0}, + {"LineEntry", Type, 5}, + {"LineEntry.Address", Field, 5}, + {"LineEntry.BasicBlock", Field, 5}, + {"LineEntry.Column", Field, 5}, + {"LineEntry.Discriminator", Field, 5}, + {"LineEntry.EndSequence", Field, 5}, + {"LineEntry.EpilogueBegin", Field, 5}, + {"LineEntry.File", Field, 5}, + {"LineEntry.ISA", Field, 5}, + {"LineEntry.IsStmt", Field, 5}, + {"LineEntry.Line", Field, 5}, + {"LineEntry.OpIndex", Field, 5}, + {"LineEntry.PrologueEnd", Field, 5}, + {"LineFile", Type, 5}, + {"LineFile.Length", Field, 5}, + {"LineFile.Mtime", Field, 5}, + {"LineFile.Name", Field, 5}, + {"LineReader", Type, 5}, + {"LineReaderPos", Type, 5}, + {"New", Func, 0}, + {"Offset", Type, 0}, + {"PtrType", Type, 0}, + {"PtrType.CommonType", Field, 0}, + {"PtrType.Type", Field, 0}, + {"QualType", Type, 0}, + {"QualType.CommonType", Field, 0}, + {"QualType.Qual", Field, 0}, + {"QualType.Type", Field, 0}, + {"Reader", Type, 0}, + {"StructField", Type, 0}, + {"StructField.BitOffset", Field, 0}, + {"StructField.BitSize", Field, 0}, + {"StructField.ByteOffset", Field, 0}, + {"StructField.ByteSize", Field, 0}, + {"StructField.DataBitOffset", Field, 18}, + {"StructField.Name", Field, 0}, + {"StructField.Type", Field, 0}, + {"StructType", Type, 0}, + {"StructType.CommonType", Field, 0}, + {"StructType.Field", Field, 0}, + {"StructType.Incomplete", Field, 0}, + {"StructType.Kind", Field, 0}, + {"StructType.StructName", Field, 0}, + {"Tag", Type, 0}, + {"TagAccessDeclaration", Const, 0}, + {"TagArrayType", Const, 0}, + {"TagAtomicType", Const, 14}, + {"TagBaseType", Const, 0}, + {"TagCallSite", Const, 14}, + {"TagCallSiteParameter", Const, 14}, + {"TagCatchDwarfBlock", Const, 0}, + {"TagClassType", Const, 0}, + {"TagCoarrayType", Const, 14}, + {"TagCommonDwarfBlock", Const, 0}, + {"TagCommonInclusion", Const, 0}, + {"TagCompileUnit", Const, 0}, + {"TagCondition", Const, 3}, + {"TagConstType", Const, 0}, + {"TagConstant", Const, 0}, + {"TagDwarfProcedure", Const, 0}, + {"TagDynamicType", Const, 14}, + {"TagEntryPoint", Const, 0}, + {"TagEnumerationType", Const, 0}, + {"TagEnumerator", Const, 0}, + {"TagFileType", Const, 0}, + {"TagFormalParameter", Const, 0}, + {"TagFriend", Const, 0}, + {"TagGenericSubrange", Const, 14}, + {"TagImmutableType", Const, 14}, + {"TagImportedDeclaration", Const, 0}, + {"TagImportedModule", Const, 0}, + {"TagImportedUnit", Const, 0}, + {"TagInheritance", Const, 0}, + {"TagInlinedSubroutine", Const, 0}, + {"TagInterfaceType", Const, 0}, + {"TagLabel", Const, 0}, + {"TagLexDwarfBlock", Const, 0}, + {"TagMember", Const, 0}, + {"TagModule", Const, 0}, + {"TagMutableType", Const, 0}, + {"TagNamelist", Const, 0}, + {"TagNamelistItem", Const, 0}, + {"TagNamespace", Const, 0}, + {"TagPackedType", Const, 0}, + {"TagPartialUnit", Const, 0}, + {"TagPointerType", Const, 0}, + {"TagPtrToMemberType", Const, 0}, + {"TagReferenceType", Const, 0}, + {"TagRestrictType", Const, 0}, + {"TagRvalueReferenceType", Const, 3}, + {"TagSetType", Const, 0}, + {"TagSharedType", Const, 3}, + {"TagSkeletonUnit", Const, 14}, + {"TagStringType", Const, 0}, + {"TagStructType", Const, 0}, + {"TagSubprogram", Const, 0}, + {"TagSubrangeType", Const, 0}, + {"TagSubroutineType", Const, 0}, + {"TagTemplateAlias", Const, 3}, + {"TagTemplateTypeParameter", Const, 0}, + {"TagTemplateValueParameter", Const, 0}, + {"TagThrownType", Const, 0}, + {"TagTryDwarfBlock", Const, 0}, + {"TagTypeUnit", Const, 3}, + {"TagTypedef", Const, 0}, + {"TagUnionType", Const, 0}, + {"TagUnspecifiedParameters", Const, 0}, + {"TagUnspecifiedType", Const, 0}, + {"TagVariable", Const, 0}, + {"TagVariant", Const, 0}, + {"TagVariantPart", Const, 0}, + {"TagVolatileType", Const, 0}, + {"TagWithStmt", Const, 0}, + {"Type", Type, 0}, + {"TypedefType", Type, 0}, + {"TypedefType.CommonType", Field, 0}, + {"TypedefType.Type", Field, 0}, + {"UcharType", Type, 0}, + {"UcharType.BasicType", Field, 0}, + {"UintType", Type, 0}, + {"UintType.BasicType", Field, 0}, + {"UnspecifiedType", Type, 4}, + {"UnspecifiedType.BasicType", Field, 4}, + {"UnsupportedType", Type, 13}, + {"UnsupportedType.CommonType", Field, 13}, + {"UnsupportedType.Tag", Field, 13}, + {"VoidType", Type, 0}, + {"VoidType.CommonType", Field, 0}, + }, + "debug/elf": { + {"(*File).Close", Method, 0}, + {"(*File).DWARF", Method, 0}, + {"(*File).DynString", Method, 1}, + {"(*File).DynValue", Method, 21}, + {"(*File).DynamicSymbols", Method, 4}, + {"(*File).ImportedLibraries", Method, 0}, + {"(*File).ImportedSymbols", Method, 0}, + {"(*File).Section", Method, 0}, + {"(*File).SectionByType", Method, 0}, + {"(*File).Symbols", Method, 0}, + {"(*FormatError).Error", Method, 0}, + {"(*Prog).Open", Method, 0}, + {"(*Section).Data", Method, 0}, + {"(*Section).Open", Method, 0}, + {"(Class).GoString", Method, 0}, + {"(Class).String", Method, 0}, + {"(CompressionType).GoString", Method, 6}, + {"(CompressionType).String", Method, 6}, + {"(Data).GoString", Method, 0}, + {"(Data).String", Method, 0}, + {"(DynFlag).GoString", Method, 0}, + {"(DynFlag).String", Method, 0}, + {"(DynFlag1).GoString", Method, 21}, + {"(DynFlag1).String", Method, 21}, + {"(DynTag).GoString", Method, 0}, + {"(DynTag).String", Method, 0}, + {"(Machine).GoString", Method, 0}, + {"(Machine).String", Method, 0}, + {"(NType).GoString", Method, 0}, + {"(NType).String", Method, 0}, + {"(OSABI).GoString", Method, 0}, + {"(OSABI).String", Method, 0}, + {"(Prog).ReadAt", Method, 0}, + {"(ProgFlag).GoString", Method, 0}, + {"(ProgFlag).String", Method, 0}, + {"(ProgType).GoString", Method, 0}, + {"(ProgType).String", Method, 0}, + {"(R_386).GoString", Method, 0}, + {"(R_386).String", Method, 0}, + {"(R_390).GoString", Method, 7}, + {"(R_390).String", Method, 7}, + {"(R_AARCH64).GoString", Method, 4}, + {"(R_AARCH64).String", Method, 4}, + {"(R_ALPHA).GoString", Method, 0}, + {"(R_ALPHA).String", Method, 0}, + {"(R_ARM).GoString", Method, 0}, + {"(R_ARM).String", Method, 0}, + {"(R_LARCH).GoString", Method, 19}, + {"(R_LARCH).String", Method, 19}, + {"(R_MIPS).GoString", Method, 6}, + {"(R_MIPS).String", Method, 6}, + {"(R_PPC).GoString", Method, 0}, + {"(R_PPC).String", Method, 0}, + {"(R_PPC64).GoString", Method, 5}, + {"(R_PPC64).String", Method, 5}, + {"(R_RISCV).GoString", Method, 11}, + {"(R_RISCV).String", Method, 11}, + {"(R_SPARC).GoString", Method, 0}, + {"(R_SPARC).String", Method, 0}, + {"(R_X86_64).GoString", Method, 0}, + {"(R_X86_64).String", Method, 0}, + {"(Section).ReadAt", Method, 0}, + {"(SectionFlag).GoString", Method, 0}, + {"(SectionFlag).String", Method, 0}, + {"(SectionIndex).GoString", Method, 0}, + {"(SectionIndex).String", Method, 0}, + {"(SectionType).GoString", Method, 0}, + {"(SectionType).String", Method, 0}, + {"(SymBind).GoString", Method, 0}, + {"(SymBind).String", Method, 0}, + {"(SymType).GoString", Method, 0}, + {"(SymType).String", Method, 0}, + {"(SymVis).GoString", Method, 0}, + {"(SymVis).String", Method, 0}, + {"(Type).GoString", Method, 0}, + {"(Type).String", Method, 0}, + {"(Version).GoString", Method, 0}, + {"(Version).String", Method, 0}, + {"ARM_MAGIC_TRAMP_NUMBER", Const, 0}, + {"COMPRESS_HIOS", Const, 6}, + {"COMPRESS_HIPROC", Const, 6}, + {"COMPRESS_LOOS", Const, 6}, + {"COMPRESS_LOPROC", Const, 6}, + {"COMPRESS_ZLIB", Const, 6}, + {"COMPRESS_ZSTD", Const, 21}, + {"Chdr32", Type, 6}, + {"Chdr32.Addralign", Field, 6}, + {"Chdr32.Size", Field, 6}, + {"Chdr32.Type", Field, 6}, + {"Chdr64", Type, 6}, + {"Chdr64.Addralign", Field, 6}, + {"Chdr64.Size", Field, 6}, + {"Chdr64.Type", Field, 6}, + {"Class", Type, 0}, + {"CompressionType", Type, 6}, + {"DF_1_CONFALT", Const, 21}, + {"DF_1_DIRECT", Const, 21}, + {"DF_1_DISPRELDNE", Const, 21}, + {"DF_1_DISPRELPND", Const, 21}, + {"DF_1_EDITED", Const, 21}, + {"DF_1_ENDFILTEE", Const, 21}, + {"DF_1_GLOBAL", Const, 21}, + {"DF_1_GLOBAUDIT", Const, 21}, + {"DF_1_GROUP", Const, 21}, + {"DF_1_IGNMULDEF", Const, 21}, + {"DF_1_INITFIRST", Const, 21}, + {"DF_1_INTERPOSE", Const, 21}, + {"DF_1_KMOD", Const, 21}, + {"DF_1_LOADFLTR", Const, 21}, + {"DF_1_NOCOMMON", Const, 21}, + {"DF_1_NODEFLIB", Const, 21}, + {"DF_1_NODELETE", Const, 21}, + {"DF_1_NODIRECT", Const, 21}, + {"DF_1_NODUMP", Const, 21}, + {"DF_1_NOHDR", Const, 21}, + {"DF_1_NOKSYMS", Const, 21}, + {"DF_1_NOOPEN", Const, 21}, + {"DF_1_NORELOC", Const, 21}, + {"DF_1_NOW", Const, 21}, + {"DF_1_ORIGIN", Const, 21}, + {"DF_1_PIE", Const, 21}, + {"DF_1_SINGLETON", Const, 21}, + {"DF_1_STUB", Const, 21}, + {"DF_1_SYMINTPOSE", Const, 21}, + {"DF_1_TRANS", Const, 21}, + {"DF_1_WEAKFILTER", Const, 21}, + {"DF_BIND_NOW", Const, 0}, + {"DF_ORIGIN", Const, 0}, + {"DF_STATIC_TLS", Const, 0}, + {"DF_SYMBOLIC", Const, 0}, + {"DF_TEXTREL", Const, 0}, + {"DT_ADDRRNGHI", Const, 16}, + {"DT_ADDRRNGLO", Const, 16}, + {"DT_AUDIT", Const, 16}, + {"DT_AUXILIARY", Const, 16}, + {"DT_BIND_NOW", Const, 0}, + {"DT_CHECKSUM", Const, 16}, + {"DT_CONFIG", Const, 16}, + {"DT_DEBUG", Const, 0}, + {"DT_DEPAUDIT", Const, 16}, + {"DT_ENCODING", Const, 0}, + {"DT_FEATURE", Const, 16}, + {"DT_FILTER", Const, 16}, + {"DT_FINI", Const, 0}, + {"DT_FINI_ARRAY", Const, 0}, + {"DT_FINI_ARRAYSZ", Const, 0}, + {"DT_FLAGS", Const, 0}, + {"DT_FLAGS_1", Const, 16}, + {"DT_GNU_CONFLICT", Const, 16}, + {"DT_GNU_CONFLICTSZ", Const, 16}, + {"DT_GNU_HASH", Const, 16}, + {"DT_GNU_LIBLIST", Const, 16}, + {"DT_GNU_LIBLISTSZ", Const, 16}, + {"DT_GNU_PRELINKED", Const, 16}, + {"DT_HASH", Const, 0}, + {"DT_HIOS", Const, 0}, + {"DT_HIPROC", Const, 0}, + {"DT_INIT", Const, 0}, + {"DT_INIT_ARRAY", Const, 0}, + {"DT_INIT_ARRAYSZ", Const, 0}, + {"DT_JMPREL", Const, 0}, + {"DT_LOOS", Const, 0}, + {"DT_LOPROC", Const, 0}, + {"DT_MIPS_AUX_DYNAMIC", Const, 16}, + {"DT_MIPS_BASE_ADDRESS", Const, 16}, + {"DT_MIPS_COMPACT_SIZE", Const, 16}, + {"DT_MIPS_CONFLICT", Const, 16}, + {"DT_MIPS_CONFLICTNO", Const, 16}, + {"DT_MIPS_CXX_FLAGS", Const, 16}, + {"DT_MIPS_DELTA_CLASS", Const, 16}, + {"DT_MIPS_DELTA_CLASSSYM", Const, 16}, + {"DT_MIPS_DELTA_CLASSSYM_NO", Const, 16}, + {"DT_MIPS_DELTA_CLASS_NO", Const, 16}, + {"DT_MIPS_DELTA_INSTANCE", Const, 16}, + {"DT_MIPS_DELTA_INSTANCE_NO", Const, 16}, + {"DT_MIPS_DELTA_RELOC", Const, 16}, + {"DT_MIPS_DELTA_RELOC_NO", Const, 16}, + {"DT_MIPS_DELTA_SYM", Const, 16}, + {"DT_MIPS_DELTA_SYM_NO", Const, 16}, + {"DT_MIPS_DYNSTR_ALIGN", Const, 16}, + {"DT_MIPS_FLAGS", Const, 16}, + {"DT_MIPS_GOTSYM", Const, 16}, + {"DT_MIPS_GP_VALUE", Const, 16}, + {"DT_MIPS_HIDDEN_GOTIDX", Const, 16}, + {"DT_MIPS_HIPAGENO", Const, 16}, + {"DT_MIPS_ICHECKSUM", Const, 16}, + {"DT_MIPS_INTERFACE", Const, 16}, + {"DT_MIPS_INTERFACE_SIZE", Const, 16}, + {"DT_MIPS_IVERSION", Const, 16}, + {"DT_MIPS_LIBLIST", Const, 16}, + {"DT_MIPS_LIBLISTNO", Const, 16}, + {"DT_MIPS_LOCALPAGE_GOTIDX", Const, 16}, + {"DT_MIPS_LOCAL_GOTIDX", Const, 16}, + {"DT_MIPS_LOCAL_GOTNO", Const, 16}, + {"DT_MIPS_MSYM", Const, 16}, + {"DT_MIPS_OPTIONS", Const, 16}, + {"DT_MIPS_PERF_SUFFIX", Const, 16}, + {"DT_MIPS_PIXIE_INIT", Const, 16}, + {"DT_MIPS_PLTGOT", Const, 16}, + {"DT_MIPS_PROTECTED_GOTIDX", Const, 16}, + {"DT_MIPS_RLD_MAP", Const, 16}, + {"DT_MIPS_RLD_MAP_REL", Const, 16}, + {"DT_MIPS_RLD_TEXT_RESOLVE_ADDR", Const, 16}, + {"DT_MIPS_RLD_VERSION", Const, 16}, + {"DT_MIPS_RWPLT", Const, 16}, + {"DT_MIPS_SYMBOL_LIB", Const, 16}, + {"DT_MIPS_SYMTABNO", Const, 16}, + {"DT_MIPS_TIME_STAMP", Const, 16}, + {"DT_MIPS_UNREFEXTNO", Const, 16}, + {"DT_MOVEENT", Const, 16}, + {"DT_MOVESZ", Const, 16}, + {"DT_MOVETAB", Const, 16}, + {"DT_NEEDED", Const, 0}, + {"DT_NULL", Const, 0}, + {"DT_PLTGOT", Const, 0}, + {"DT_PLTPAD", Const, 16}, + {"DT_PLTPADSZ", Const, 16}, + {"DT_PLTREL", Const, 0}, + {"DT_PLTRELSZ", Const, 0}, + {"DT_POSFLAG_1", Const, 16}, + {"DT_PPC64_GLINK", Const, 16}, + {"DT_PPC64_OPD", Const, 16}, + {"DT_PPC64_OPDSZ", Const, 16}, + {"DT_PPC64_OPT", Const, 16}, + {"DT_PPC_GOT", Const, 16}, + {"DT_PPC_OPT", Const, 16}, + {"DT_PREINIT_ARRAY", Const, 0}, + {"DT_PREINIT_ARRAYSZ", Const, 0}, + {"DT_REL", Const, 0}, + {"DT_RELA", Const, 0}, + {"DT_RELACOUNT", Const, 16}, + {"DT_RELAENT", Const, 0}, + {"DT_RELASZ", Const, 0}, + {"DT_RELCOUNT", Const, 16}, + {"DT_RELENT", Const, 0}, + {"DT_RELSZ", Const, 0}, + {"DT_RPATH", Const, 0}, + {"DT_RUNPATH", Const, 0}, + {"DT_SONAME", Const, 0}, + {"DT_SPARC_REGISTER", Const, 16}, + {"DT_STRSZ", Const, 0}, + {"DT_STRTAB", Const, 0}, + {"DT_SYMBOLIC", Const, 0}, + {"DT_SYMENT", Const, 0}, + {"DT_SYMINENT", Const, 16}, + {"DT_SYMINFO", Const, 16}, + {"DT_SYMINSZ", Const, 16}, + {"DT_SYMTAB", Const, 0}, + {"DT_SYMTAB_SHNDX", Const, 16}, + {"DT_TEXTREL", Const, 0}, + {"DT_TLSDESC_GOT", Const, 16}, + {"DT_TLSDESC_PLT", Const, 16}, + {"DT_USED", Const, 16}, + {"DT_VALRNGHI", Const, 16}, + {"DT_VALRNGLO", Const, 16}, + {"DT_VERDEF", Const, 16}, + {"DT_VERDEFNUM", Const, 16}, + {"DT_VERNEED", Const, 0}, + {"DT_VERNEEDNUM", Const, 0}, + {"DT_VERSYM", Const, 0}, + {"Data", Type, 0}, + {"Dyn32", Type, 0}, + {"Dyn32.Tag", Field, 0}, + {"Dyn32.Val", Field, 0}, + {"Dyn64", Type, 0}, + {"Dyn64.Tag", Field, 0}, + {"Dyn64.Val", Field, 0}, + {"DynFlag", Type, 0}, + {"DynFlag1", Type, 21}, + {"DynTag", Type, 0}, + {"EI_ABIVERSION", Const, 0}, + {"EI_CLASS", Const, 0}, + {"EI_DATA", Const, 0}, + {"EI_NIDENT", Const, 0}, + {"EI_OSABI", Const, 0}, + {"EI_PAD", Const, 0}, + {"EI_VERSION", Const, 0}, + {"ELFCLASS32", Const, 0}, + {"ELFCLASS64", Const, 0}, + {"ELFCLASSNONE", Const, 0}, + {"ELFDATA2LSB", Const, 0}, + {"ELFDATA2MSB", Const, 0}, + {"ELFDATANONE", Const, 0}, + {"ELFMAG", Const, 0}, + {"ELFOSABI_86OPEN", Const, 0}, + {"ELFOSABI_AIX", Const, 0}, + {"ELFOSABI_ARM", Const, 0}, + {"ELFOSABI_AROS", Const, 11}, + {"ELFOSABI_CLOUDABI", Const, 11}, + {"ELFOSABI_FENIXOS", Const, 11}, + {"ELFOSABI_FREEBSD", Const, 0}, + {"ELFOSABI_HPUX", Const, 0}, + {"ELFOSABI_HURD", Const, 0}, + {"ELFOSABI_IRIX", Const, 0}, + {"ELFOSABI_LINUX", Const, 0}, + {"ELFOSABI_MODESTO", Const, 0}, + {"ELFOSABI_NETBSD", Const, 0}, + {"ELFOSABI_NONE", Const, 0}, + {"ELFOSABI_NSK", Const, 0}, + {"ELFOSABI_OPENBSD", Const, 0}, + {"ELFOSABI_OPENVMS", Const, 0}, + {"ELFOSABI_SOLARIS", Const, 0}, + {"ELFOSABI_STANDALONE", Const, 0}, + {"ELFOSABI_TRU64", Const, 0}, + {"EM_386", Const, 0}, + {"EM_486", Const, 0}, + {"EM_56800EX", Const, 11}, + {"EM_68HC05", Const, 11}, + {"EM_68HC08", Const, 11}, + {"EM_68HC11", Const, 11}, + {"EM_68HC12", Const, 0}, + {"EM_68HC16", Const, 11}, + {"EM_68K", Const, 0}, + {"EM_78KOR", Const, 11}, + {"EM_8051", Const, 11}, + {"EM_860", Const, 0}, + {"EM_88K", Const, 0}, + {"EM_960", Const, 0}, + {"EM_AARCH64", Const, 4}, + {"EM_ALPHA", Const, 0}, + {"EM_ALPHA_STD", Const, 0}, + {"EM_ALTERA_NIOS2", Const, 11}, + {"EM_AMDGPU", Const, 11}, + {"EM_ARC", Const, 0}, + {"EM_ARCA", Const, 11}, + {"EM_ARC_COMPACT", Const, 11}, + {"EM_ARC_COMPACT2", Const, 11}, + {"EM_ARM", Const, 0}, + {"EM_AVR", Const, 11}, + {"EM_AVR32", Const, 11}, + {"EM_BA1", Const, 11}, + {"EM_BA2", Const, 11}, + {"EM_BLACKFIN", Const, 11}, + {"EM_BPF", Const, 11}, + {"EM_C166", Const, 11}, + {"EM_CDP", Const, 11}, + {"EM_CE", Const, 11}, + {"EM_CLOUDSHIELD", Const, 11}, + {"EM_COGE", Const, 11}, + {"EM_COLDFIRE", Const, 0}, + {"EM_COOL", Const, 11}, + {"EM_COREA_1ST", Const, 11}, + {"EM_COREA_2ND", Const, 11}, + {"EM_CR", Const, 11}, + {"EM_CR16", Const, 11}, + {"EM_CRAYNV2", Const, 11}, + {"EM_CRIS", Const, 11}, + {"EM_CRX", Const, 11}, + {"EM_CSR_KALIMBA", Const, 11}, + {"EM_CUDA", Const, 11}, + {"EM_CYPRESS_M8C", Const, 11}, + {"EM_D10V", Const, 11}, + {"EM_D30V", Const, 11}, + {"EM_DSP24", Const, 11}, + {"EM_DSPIC30F", Const, 11}, + {"EM_DXP", Const, 11}, + {"EM_ECOG1", Const, 11}, + {"EM_ECOG16", Const, 11}, + {"EM_ECOG1X", Const, 11}, + {"EM_ECOG2", Const, 11}, + {"EM_ETPU", Const, 11}, + {"EM_EXCESS", Const, 11}, + {"EM_F2MC16", Const, 11}, + {"EM_FIREPATH", Const, 11}, + {"EM_FR20", Const, 0}, + {"EM_FR30", Const, 11}, + {"EM_FT32", Const, 11}, + {"EM_FX66", Const, 11}, + {"EM_H8S", Const, 0}, + {"EM_H8_300", Const, 0}, + {"EM_H8_300H", Const, 0}, + {"EM_H8_500", Const, 0}, + {"EM_HUANY", Const, 11}, + {"EM_IA_64", Const, 0}, + {"EM_INTEL205", Const, 11}, + {"EM_INTEL206", Const, 11}, + {"EM_INTEL207", Const, 11}, + {"EM_INTEL208", Const, 11}, + {"EM_INTEL209", Const, 11}, + {"EM_IP2K", Const, 11}, + {"EM_JAVELIN", Const, 11}, + {"EM_K10M", Const, 11}, + {"EM_KM32", Const, 11}, + {"EM_KMX16", Const, 11}, + {"EM_KMX32", Const, 11}, + {"EM_KMX8", Const, 11}, + {"EM_KVARC", Const, 11}, + {"EM_L10M", Const, 11}, + {"EM_LANAI", Const, 11}, + {"EM_LATTICEMICO32", Const, 11}, + {"EM_LOONGARCH", Const, 19}, + {"EM_M16C", Const, 11}, + {"EM_M32", Const, 0}, + {"EM_M32C", Const, 11}, + {"EM_M32R", Const, 11}, + {"EM_MANIK", Const, 11}, + {"EM_MAX", Const, 11}, + {"EM_MAXQ30", Const, 11}, + {"EM_MCHP_PIC", Const, 11}, + {"EM_MCST_ELBRUS", Const, 11}, + {"EM_ME16", Const, 0}, + {"EM_METAG", Const, 11}, + {"EM_MICROBLAZE", Const, 11}, + {"EM_MIPS", Const, 0}, + {"EM_MIPS_RS3_LE", Const, 0}, + {"EM_MIPS_RS4_BE", Const, 0}, + {"EM_MIPS_X", Const, 0}, + {"EM_MMA", Const, 0}, + {"EM_MMDSP_PLUS", Const, 11}, + {"EM_MMIX", Const, 11}, + {"EM_MN10200", Const, 11}, + {"EM_MN10300", Const, 11}, + {"EM_MOXIE", Const, 11}, + {"EM_MSP430", Const, 11}, + {"EM_NCPU", Const, 0}, + {"EM_NDR1", Const, 0}, + {"EM_NDS32", Const, 11}, + {"EM_NONE", Const, 0}, + {"EM_NORC", Const, 11}, + {"EM_NS32K", Const, 11}, + {"EM_OPEN8", Const, 11}, + {"EM_OPENRISC", Const, 11}, + {"EM_PARISC", Const, 0}, + {"EM_PCP", Const, 0}, + {"EM_PDP10", Const, 11}, + {"EM_PDP11", Const, 11}, + {"EM_PDSP", Const, 11}, + {"EM_PJ", Const, 11}, + {"EM_PPC", Const, 0}, + {"EM_PPC64", Const, 0}, + {"EM_PRISM", Const, 11}, + {"EM_QDSP6", Const, 11}, + {"EM_R32C", Const, 11}, + {"EM_RCE", Const, 0}, + {"EM_RH32", Const, 0}, + {"EM_RISCV", Const, 11}, + {"EM_RL78", Const, 11}, + {"EM_RS08", Const, 11}, + {"EM_RX", Const, 11}, + {"EM_S370", Const, 0}, + {"EM_S390", Const, 0}, + {"EM_SCORE7", Const, 11}, + {"EM_SEP", Const, 11}, + {"EM_SE_C17", Const, 11}, + {"EM_SE_C33", Const, 11}, + {"EM_SH", Const, 0}, + {"EM_SHARC", Const, 11}, + {"EM_SLE9X", Const, 11}, + {"EM_SNP1K", Const, 11}, + {"EM_SPARC", Const, 0}, + {"EM_SPARC32PLUS", Const, 0}, + {"EM_SPARCV9", Const, 0}, + {"EM_ST100", Const, 0}, + {"EM_ST19", Const, 11}, + {"EM_ST200", Const, 11}, + {"EM_ST7", Const, 11}, + {"EM_ST9PLUS", Const, 11}, + {"EM_STARCORE", Const, 0}, + {"EM_STM8", Const, 11}, + {"EM_STXP7X", Const, 11}, + {"EM_SVX", Const, 11}, + {"EM_TILE64", Const, 11}, + {"EM_TILEGX", Const, 11}, + {"EM_TILEPRO", Const, 11}, + {"EM_TINYJ", Const, 0}, + {"EM_TI_ARP32", Const, 11}, + {"EM_TI_C2000", Const, 11}, + {"EM_TI_C5500", Const, 11}, + {"EM_TI_C6000", Const, 11}, + {"EM_TI_PRU", Const, 11}, + {"EM_TMM_GPP", Const, 11}, + {"EM_TPC", Const, 11}, + {"EM_TRICORE", Const, 0}, + {"EM_TRIMEDIA", Const, 11}, + {"EM_TSK3000", Const, 11}, + {"EM_UNICORE", Const, 11}, + {"EM_V800", Const, 0}, + {"EM_V850", Const, 11}, + {"EM_VAX", Const, 11}, + {"EM_VIDEOCORE", Const, 11}, + {"EM_VIDEOCORE3", Const, 11}, + {"EM_VIDEOCORE5", Const, 11}, + {"EM_VISIUM", Const, 11}, + {"EM_VPP500", Const, 0}, + {"EM_X86_64", Const, 0}, + {"EM_XCORE", Const, 11}, + {"EM_XGATE", Const, 11}, + {"EM_XIMO16", Const, 11}, + {"EM_XTENSA", Const, 11}, + {"EM_Z80", Const, 11}, + {"EM_ZSP", Const, 11}, + {"ET_CORE", Const, 0}, + {"ET_DYN", Const, 0}, + {"ET_EXEC", Const, 0}, + {"ET_HIOS", Const, 0}, + {"ET_HIPROC", Const, 0}, + {"ET_LOOS", Const, 0}, + {"ET_LOPROC", Const, 0}, + {"ET_NONE", Const, 0}, + {"ET_REL", Const, 0}, + {"EV_CURRENT", Const, 0}, + {"EV_NONE", Const, 0}, + {"ErrNoSymbols", Var, 4}, + {"File", Type, 0}, + {"File.FileHeader", Field, 0}, + {"File.Progs", Field, 0}, + {"File.Sections", Field, 0}, + {"FileHeader", Type, 0}, + {"FileHeader.ABIVersion", Field, 0}, + {"FileHeader.ByteOrder", Field, 0}, + {"FileHeader.Class", Field, 0}, + {"FileHeader.Data", Field, 0}, + {"FileHeader.Entry", Field, 1}, + {"FileHeader.Machine", Field, 0}, + {"FileHeader.OSABI", Field, 0}, + {"FileHeader.Type", Field, 0}, + {"FileHeader.Version", Field, 0}, + {"FormatError", Type, 0}, + {"Header32", Type, 0}, + {"Header32.Ehsize", Field, 0}, + {"Header32.Entry", Field, 0}, + {"Header32.Flags", Field, 0}, + {"Header32.Ident", Field, 0}, + {"Header32.Machine", Field, 0}, + {"Header32.Phentsize", Field, 0}, + {"Header32.Phnum", Field, 0}, + {"Header32.Phoff", Field, 0}, + {"Header32.Shentsize", Field, 0}, + {"Header32.Shnum", Field, 0}, + {"Header32.Shoff", Field, 0}, + {"Header32.Shstrndx", Field, 0}, + {"Header32.Type", Field, 0}, + {"Header32.Version", Field, 0}, + {"Header64", Type, 0}, + {"Header64.Ehsize", Field, 0}, + {"Header64.Entry", Field, 0}, + {"Header64.Flags", Field, 0}, + {"Header64.Ident", Field, 0}, + {"Header64.Machine", Field, 0}, + {"Header64.Phentsize", Field, 0}, + {"Header64.Phnum", Field, 0}, + {"Header64.Phoff", Field, 0}, + {"Header64.Shentsize", Field, 0}, + {"Header64.Shnum", Field, 0}, + {"Header64.Shoff", Field, 0}, + {"Header64.Shstrndx", Field, 0}, + {"Header64.Type", Field, 0}, + {"Header64.Version", Field, 0}, + {"ImportedSymbol", Type, 0}, + {"ImportedSymbol.Library", Field, 0}, + {"ImportedSymbol.Name", Field, 0}, + {"ImportedSymbol.Version", Field, 0}, + {"Machine", Type, 0}, + {"NT_FPREGSET", Const, 0}, + {"NT_PRPSINFO", Const, 0}, + {"NT_PRSTATUS", Const, 0}, + {"NType", Type, 0}, + {"NewFile", Func, 0}, + {"OSABI", Type, 0}, + {"Open", Func, 0}, + {"PF_MASKOS", Const, 0}, + {"PF_MASKPROC", Const, 0}, + {"PF_R", Const, 0}, + {"PF_W", Const, 0}, + {"PF_X", Const, 0}, + {"PT_AARCH64_ARCHEXT", Const, 16}, + {"PT_AARCH64_UNWIND", Const, 16}, + {"PT_ARM_ARCHEXT", Const, 16}, + {"PT_ARM_EXIDX", Const, 16}, + {"PT_DYNAMIC", Const, 0}, + {"PT_GNU_EH_FRAME", Const, 16}, + {"PT_GNU_MBIND_HI", Const, 16}, + {"PT_GNU_MBIND_LO", Const, 16}, + {"PT_GNU_PROPERTY", Const, 16}, + {"PT_GNU_RELRO", Const, 16}, + {"PT_GNU_STACK", Const, 16}, + {"PT_HIOS", Const, 0}, + {"PT_HIPROC", Const, 0}, + {"PT_INTERP", Const, 0}, + {"PT_LOAD", Const, 0}, + {"PT_LOOS", Const, 0}, + {"PT_LOPROC", Const, 0}, + {"PT_MIPS_ABIFLAGS", Const, 16}, + {"PT_MIPS_OPTIONS", Const, 16}, + {"PT_MIPS_REGINFO", Const, 16}, + {"PT_MIPS_RTPROC", Const, 16}, + {"PT_NOTE", Const, 0}, + {"PT_NULL", Const, 0}, + {"PT_OPENBSD_BOOTDATA", Const, 16}, + {"PT_OPENBSD_RANDOMIZE", Const, 16}, + {"PT_OPENBSD_WXNEEDED", Const, 16}, + {"PT_PAX_FLAGS", Const, 16}, + {"PT_PHDR", Const, 0}, + {"PT_S390_PGSTE", Const, 16}, + {"PT_SHLIB", Const, 0}, + {"PT_SUNWSTACK", Const, 16}, + {"PT_SUNW_EH_FRAME", Const, 16}, + {"PT_TLS", Const, 0}, + {"Prog", Type, 0}, + {"Prog.ProgHeader", Field, 0}, + {"Prog.ReaderAt", Field, 0}, + {"Prog32", Type, 0}, + {"Prog32.Align", Field, 0}, + {"Prog32.Filesz", Field, 0}, + {"Prog32.Flags", Field, 0}, + {"Prog32.Memsz", Field, 0}, + {"Prog32.Off", Field, 0}, + {"Prog32.Paddr", Field, 0}, + {"Prog32.Type", Field, 0}, + {"Prog32.Vaddr", Field, 0}, + {"Prog64", Type, 0}, + {"Prog64.Align", Field, 0}, + {"Prog64.Filesz", Field, 0}, + {"Prog64.Flags", Field, 0}, + {"Prog64.Memsz", Field, 0}, + {"Prog64.Off", Field, 0}, + {"Prog64.Paddr", Field, 0}, + {"Prog64.Type", Field, 0}, + {"Prog64.Vaddr", Field, 0}, + {"ProgFlag", Type, 0}, + {"ProgHeader", Type, 0}, + {"ProgHeader.Align", Field, 0}, + {"ProgHeader.Filesz", Field, 0}, + {"ProgHeader.Flags", Field, 0}, + {"ProgHeader.Memsz", Field, 0}, + {"ProgHeader.Off", Field, 0}, + {"ProgHeader.Paddr", Field, 0}, + {"ProgHeader.Type", Field, 0}, + {"ProgHeader.Vaddr", Field, 0}, + {"ProgType", Type, 0}, + {"R_386", Type, 0}, + {"R_386_16", Const, 10}, + {"R_386_32", Const, 0}, + {"R_386_32PLT", Const, 10}, + {"R_386_8", Const, 10}, + {"R_386_COPY", Const, 0}, + {"R_386_GLOB_DAT", Const, 0}, + {"R_386_GOT32", Const, 0}, + {"R_386_GOT32X", Const, 10}, + {"R_386_GOTOFF", Const, 0}, + {"R_386_GOTPC", Const, 0}, + {"R_386_IRELATIVE", Const, 10}, + {"R_386_JMP_SLOT", Const, 0}, + {"R_386_NONE", Const, 0}, + {"R_386_PC16", Const, 10}, + {"R_386_PC32", Const, 0}, + {"R_386_PC8", Const, 10}, + {"R_386_PLT32", Const, 0}, + {"R_386_RELATIVE", Const, 0}, + {"R_386_SIZE32", Const, 10}, + {"R_386_TLS_DESC", Const, 10}, + {"R_386_TLS_DESC_CALL", Const, 10}, + {"R_386_TLS_DTPMOD32", Const, 0}, + {"R_386_TLS_DTPOFF32", Const, 0}, + {"R_386_TLS_GD", Const, 0}, + {"R_386_TLS_GD_32", Const, 0}, + {"R_386_TLS_GD_CALL", Const, 0}, + {"R_386_TLS_GD_POP", Const, 0}, + {"R_386_TLS_GD_PUSH", Const, 0}, + {"R_386_TLS_GOTDESC", Const, 10}, + {"R_386_TLS_GOTIE", Const, 0}, + {"R_386_TLS_IE", Const, 0}, + {"R_386_TLS_IE_32", Const, 0}, + {"R_386_TLS_LDM", Const, 0}, + {"R_386_TLS_LDM_32", Const, 0}, + {"R_386_TLS_LDM_CALL", Const, 0}, + {"R_386_TLS_LDM_POP", Const, 0}, + {"R_386_TLS_LDM_PUSH", Const, 0}, + {"R_386_TLS_LDO_32", Const, 0}, + {"R_386_TLS_LE", Const, 0}, + {"R_386_TLS_LE_32", Const, 0}, + {"R_386_TLS_TPOFF", Const, 0}, + {"R_386_TLS_TPOFF32", Const, 0}, + {"R_390", Type, 7}, + {"R_390_12", Const, 7}, + {"R_390_16", Const, 7}, + {"R_390_20", Const, 7}, + {"R_390_32", Const, 7}, + {"R_390_64", Const, 7}, + {"R_390_8", Const, 7}, + {"R_390_COPY", Const, 7}, + {"R_390_GLOB_DAT", Const, 7}, + {"R_390_GOT12", Const, 7}, + {"R_390_GOT16", Const, 7}, + {"R_390_GOT20", Const, 7}, + {"R_390_GOT32", Const, 7}, + {"R_390_GOT64", Const, 7}, + {"R_390_GOTENT", Const, 7}, + {"R_390_GOTOFF", Const, 7}, + {"R_390_GOTOFF16", Const, 7}, + {"R_390_GOTOFF64", Const, 7}, + {"R_390_GOTPC", Const, 7}, + {"R_390_GOTPCDBL", Const, 7}, + {"R_390_GOTPLT12", Const, 7}, + {"R_390_GOTPLT16", Const, 7}, + {"R_390_GOTPLT20", Const, 7}, + {"R_390_GOTPLT32", Const, 7}, + {"R_390_GOTPLT64", Const, 7}, + {"R_390_GOTPLTENT", Const, 7}, + {"R_390_GOTPLTOFF16", Const, 7}, + {"R_390_GOTPLTOFF32", Const, 7}, + {"R_390_GOTPLTOFF64", Const, 7}, + {"R_390_JMP_SLOT", Const, 7}, + {"R_390_NONE", Const, 7}, + {"R_390_PC16", Const, 7}, + {"R_390_PC16DBL", Const, 7}, + {"R_390_PC32", Const, 7}, + {"R_390_PC32DBL", Const, 7}, + {"R_390_PC64", Const, 7}, + {"R_390_PLT16DBL", Const, 7}, + {"R_390_PLT32", Const, 7}, + {"R_390_PLT32DBL", Const, 7}, + {"R_390_PLT64", Const, 7}, + {"R_390_RELATIVE", Const, 7}, + {"R_390_TLS_DTPMOD", Const, 7}, + {"R_390_TLS_DTPOFF", Const, 7}, + {"R_390_TLS_GD32", Const, 7}, + {"R_390_TLS_GD64", Const, 7}, + {"R_390_TLS_GDCALL", Const, 7}, + {"R_390_TLS_GOTIE12", Const, 7}, + {"R_390_TLS_GOTIE20", Const, 7}, + {"R_390_TLS_GOTIE32", Const, 7}, + {"R_390_TLS_GOTIE64", Const, 7}, + {"R_390_TLS_IE32", Const, 7}, + {"R_390_TLS_IE64", Const, 7}, + {"R_390_TLS_IEENT", Const, 7}, + {"R_390_TLS_LDCALL", Const, 7}, + {"R_390_TLS_LDM32", Const, 7}, + {"R_390_TLS_LDM64", Const, 7}, + {"R_390_TLS_LDO32", Const, 7}, + {"R_390_TLS_LDO64", Const, 7}, + {"R_390_TLS_LE32", Const, 7}, + {"R_390_TLS_LE64", Const, 7}, + {"R_390_TLS_LOAD", Const, 7}, + {"R_390_TLS_TPOFF", Const, 7}, + {"R_AARCH64", Type, 4}, + {"R_AARCH64_ABS16", Const, 4}, + {"R_AARCH64_ABS32", Const, 4}, + {"R_AARCH64_ABS64", Const, 4}, + {"R_AARCH64_ADD_ABS_LO12_NC", Const, 4}, + {"R_AARCH64_ADR_GOT_PAGE", Const, 4}, + {"R_AARCH64_ADR_PREL_LO21", Const, 4}, + {"R_AARCH64_ADR_PREL_PG_HI21", Const, 4}, + {"R_AARCH64_ADR_PREL_PG_HI21_NC", Const, 4}, + {"R_AARCH64_CALL26", Const, 4}, + {"R_AARCH64_CONDBR19", Const, 4}, + {"R_AARCH64_COPY", Const, 4}, + {"R_AARCH64_GLOB_DAT", Const, 4}, + {"R_AARCH64_GOT_LD_PREL19", Const, 4}, + {"R_AARCH64_IRELATIVE", Const, 4}, + {"R_AARCH64_JUMP26", Const, 4}, + {"R_AARCH64_JUMP_SLOT", Const, 4}, + {"R_AARCH64_LD64_GOTOFF_LO15", Const, 10}, + {"R_AARCH64_LD64_GOTPAGE_LO15", Const, 10}, + {"R_AARCH64_LD64_GOT_LO12_NC", Const, 4}, + {"R_AARCH64_LDST128_ABS_LO12_NC", Const, 4}, + {"R_AARCH64_LDST16_ABS_LO12_NC", Const, 4}, + {"R_AARCH64_LDST32_ABS_LO12_NC", Const, 4}, + {"R_AARCH64_LDST64_ABS_LO12_NC", Const, 4}, + {"R_AARCH64_LDST8_ABS_LO12_NC", Const, 4}, + {"R_AARCH64_LD_PREL_LO19", Const, 4}, + {"R_AARCH64_MOVW_SABS_G0", Const, 4}, + {"R_AARCH64_MOVW_SABS_G1", Const, 4}, + {"R_AARCH64_MOVW_SABS_G2", Const, 4}, + {"R_AARCH64_MOVW_UABS_G0", Const, 4}, + {"R_AARCH64_MOVW_UABS_G0_NC", Const, 4}, + {"R_AARCH64_MOVW_UABS_G1", Const, 4}, + {"R_AARCH64_MOVW_UABS_G1_NC", Const, 4}, + {"R_AARCH64_MOVW_UABS_G2", Const, 4}, + {"R_AARCH64_MOVW_UABS_G2_NC", Const, 4}, + {"R_AARCH64_MOVW_UABS_G3", Const, 4}, + {"R_AARCH64_NONE", Const, 4}, + {"R_AARCH64_NULL", Const, 4}, + {"R_AARCH64_P32_ABS16", Const, 4}, + {"R_AARCH64_P32_ABS32", Const, 4}, + {"R_AARCH64_P32_ADD_ABS_LO12_NC", Const, 4}, + {"R_AARCH64_P32_ADR_GOT_PAGE", Const, 4}, + {"R_AARCH64_P32_ADR_PREL_LO21", Const, 4}, + {"R_AARCH64_P32_ADR_PREL_PG_HI21", Const, 4}, + {"R_AARCH64_P32_CALL26", Const, 4}, + {"R_AARCH64_P32_CONDBR19", Const, 4}, + {"R_AARCH64_P32_COPY", Const, 4}, + {"R_AARCH64_P32_GLOB_DAT", Const, 4}, + {"R_AARCH64_P32_GOT_LD_PREL19", Const, 4}, + {"R_AARCH64_P32_IRELATIVE", Const, 4}, + {"R_AARCH64_P32_JUMP26", Const, 4}, + {"R_AARCH64_P32_JUMP_SLOT", Const, 4}, + {"R_AARCH64_P32_LD32_GOT_LO12_NC", Const, 4}, + {"R_AARCH64_P32_LDST128_ABS_LO12_NC", Const, 4}, + {"R_AARCH64_P32_LDST16_ABS_LO12_NC", Const, 4}, + {"R_AARCH64_P32_LDST32_ABS_LO12_NC", Const, 4}, + {"R_AARCH64_P32_LDST64_ABS_LO12_NC", Const, 4}, + {"R_AARCH64_P32_LDST8_ABS_LO12_NC", Const, 4}, + {"R_AARCH64_P32_LD_PREL_LO19", Const, 4}, + {"R_AARCH64_P32_MOVW_SABS_G0", Const, 4}, + {"R_AARCH64_P32_MOVW_UABS_G0", Const, 4}, + {"R_AARCH64_P32_MOVW_UABS_G0_NC", Const, 4}, + {"R_AARCH64_P32_MOVW_UABS_G1", Const, 4}, + {"R_AARCH64_P32_PREL16", Const, 4}, + {"R_AARCH64_P32_PREL32", Const, 4}, + {"R_AARCH64_P32_RELATIVE", Const, 4}, + {"R_AARCH64_P32_TLSDESC", Const, 4}, + {"R_AARCH64_P32_TLSDESC_ADD_LO12_NC", Const, 4}, + {"R_AARCH64_P32_TLSDESC_ADR_PAGE21", Const, 4}, + {"R_AARCH64_P32_TLSDESC_ADR_PREL21", Const, 4}, + {"R_AARCH64_P32_TLSDESC_CALL", Const, 4}, + {"R_AARCH64_P32_TLSDESC_LD32_LO12_NC", Const, 4}, + {"R_AARCH64_P32_TLSDESC_LD_PREL19", Const, 4}, + {"R_AARCH64_P32_TLSGD_ADD_LO12_NC", Const, 4}, + {"R_AARCH64_P32_TLSGD_ADR_PAGE21", Const, 4}, + {"R_AARCH64_P32_TLSIE_ADR_GOTTPREL_PAGE21", Const, 4}, + {"R_AARCH64_P32_TLSIE_LD32_GOTTPREL_LO12_NC", Const, 4}, + {"R_AARCH64_P32_TLSIE_LD_GOTTPREL_PREL19", Const, 4}, + {"R_AARCH64_P32_TLSLE_ADD_TPREL_HI12", Const, 4}, + {"R_AARCH64_P32_TLSLE_ADD_TPREL_LO12", Const, 4}, + {"R_AARCH64_P32_TLSLE_ADD_TPREL_LO12_NC", Const, 4}, + {"R_AARCH64_P32_TLSLE_MOVW_TPREL_G0", Const, 4}, + {"R_AARCH64_P32_TLSLE_MOVW_TPREL_G0_NC", Const, 4}, + {"R_AARCH64_P32_TLSLE_MOVW_TPREL_G1", Const, 4}, + {"R_AARCH64_P32_TLS_DTPMOD", Const, 4}, + {"R_AARCH64_P32_TLS_DTPREL", Const, 4}, + {"R_AARCH64_P32_TLS_TPREL", Const, 4}, + {"R_AARCH64_P32_TSTBR14", Const, 4}, + {"R_AARCH64_PREL16", Const, 4}, + {"R_AARCH64_PREL32", Const, 4}, + {"R_AARCH64_PREL64", Const, 4}, + {"R_AARCH64_RELATIVE", Const, 4}, + {"R_AARCH64_TLSDESC", Const, 4}, + {"R_AARCH64_TLSDESC_ADD", Const, 4}, + {"R_AARCH64_TLSDESC_ADD_LO12_NC", Const, 4}, + {"R_AARCH64_TLSDESC_ADR_PAGE21", Const, 4}, + {"R_AARCH64_TLSDESC_ADR_PREL21", Const, 4}, + {"R_AARCH64_TLSDESC_CALL", Const, 4}, + {"R_AARCH64_TLSDESC_LD64_LO12_NC", Const, 4}, + {"R_AARCH64_TLSDESC_LDR", Const, 4}, + {"R_AARCH64_TLSDESC_LD_PREL19", Const, 4}, + {"R_AARCH64_TLSDESC_OFF_G0_NC", Const, 4}, + {"R_AARCH64_TLSDESC_OFF_G1", Const, 4}, + {"R_AARCH64_TLSGD_ADD_LO12_NC", Const, 4}, + {"R_AARCH64_TLSGD_ADR_PAGE21", Const, 4}, + {"R_AARCH64_TLSGD_ADR_PREL21", Const, 10}, + {"R_AARCH64_TLSGD_MOVW_G0_NC", Const, 10}, + {"R_AARCH64_TLSGD_MOVW_G1", Const, 10}, + {"R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21", Const, 4}, + {"R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC", Const, 4}, + {"R_AARCH64_TLSIE_LD_GOTTPREL_PREL19", Const, 4}, + {"R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC", Const, 4}, + {"R_AARCH64_TLSIE_MOVW_GOTTPREL_G1", Const, 4}, + {"R_AARCH64_TLSLD_ADR_PAGE21", Const, 10}, + {"R_AARCH64_TLSLD_ADR_PREL21", Const, 10}, + {"R_AARCH64_TLSLD_LDST128_DTPREL_LO12", Const, 10}, + {"R_AARCH64_TLSLD_LDST128_DTPREL_LO12_NC", Const, 10}, + {"R_AARCH64_TLSLE_ADD_TPREL_HI12", Const, 4}, + {"R_AARCH64_TLSLE_ADD_TPREL_LO12", Const, 4}, + {"R_AARCH64_TLSLE_ADD_TPREL_LO12_NC", Const, 4}, + {"R_AARCH64_TLSLE_LDST128_TPREL_LO12", Const, 10}, + {"R_AARCH64_TLSLE_LDST128_TPREL_LO12_NC", Const, 10}, + {"R_AARCH64_TLSLE_MOVW_TPREL_G0", Const, 4}, + {"R_AARCH64_TLSLE_MOVW_TPREL_G0_NC", Const, 4}, + {"R_AARCH64_TLSLE_MOVW_TPREL_G1", Const, 4}, + {"R_AARCH64_TLSLE_MOVW_TPREL_G1_NC", Const, 4}, + {"R_AARCH64_TLSLE_MOVW_TPREL_G2", Const, 4}, + {"R_AARCH64_TLS_DTPMOD64", Const, 4}, + {"R_AARCH64_TLS_DTPREL64", Const, 4}, + {"R_AARCH64_TLS_TPREL64", Const, 4}, + {"R_AARCH64_TSTBR14", Const, 4}, + {"R_ALPHA", Type, 0}, + {"R_ALPHA_BRADDR", Const, 0}, + {"R_ALPHA_COPY", Const, 0}, + {"R_ALPHA_GLOB_DAT", Const, 0}, + {"R_ALPHA_GPDISP", Const, 0}, + {"R_ALPHA_GPREL32", Const, 0}, + {"R_ALPHA_GPRELHIGH", Const, 0}, + {"R_ALPHA_GPRELLOW", Const, 0}, + {"R_ALPHA_GPVALUE", Const, 0}, + {"R_ALPHA_HINT", Const, 0}, + {"R_ALPHA_IMMED_BR_HI32", Const, 0}, + {"R_ALPHA_IMMED_GP_16", Const, 0}, + {"R_ALPHA_IMMED_GP_HI32", Const, 0}, + {"R_ALPHA_IMMED_LO32", Const, 0}, + {"R_ALPHA_IMMED_SCN_HI32", Const, 0}, + {"R_ALPHA_JMP_SLOT", Const, 0}, + {"R_ALPHA_LITERAL", Const, 0}, + {"R_ALPHA_LITUSE", Const, 0}, + {"R_ALPHA_NONE", Const, 0}, + {"R_ALPHA_OP_PRSHIFT", Const, 0}, + {"R_ALPHA_OP_PSUB", Const, 0}, + {"R_ALPHA_OP_PUSH", Const, 0}, + {"R_ALPHA_OP_STORE", Const, 0}, + {"R_ALPHA_REFLONG", Const, 0}, + {"R_ALPHA_REFQUAD", Const, 0}, + {"R_ALPHA_RELATIVE", Const, 0}, + {"R_ALPHA_SREL16", Const, 0}, + {"R_ALPHA_SREL32", Const, 0}, + {"R_ALPHA_SREL64", Const, 0}, + {"R_ARM", Type, 0}, + {"R_ARM_ABS12", Const, 0}, + {"R_ARM_ABS16", Const, 0}, + {"R_ARM_ABS32", Const, 0}, + {"R_ARM_ABS32_NOI", Const, 10}, + {"R_ARM_ABS8", Const, 0}, + {"R_ARM_ALU_PCREL_15_8", Const, 10}, + {"R_ARM_ALU_PCREL_23_15", Const, 10}, + {"R_ARM_ALU_PCREL_7_0", Const, 10}, + {"R_ARM_ALU_PC_G0", Const, 10}, + {"R_ARM_ALU_PC_G0_NC", Const, 10}, + {"R_ARM_ALU_PC_G1", Const, 10}, + {"R_ARM_ALU_PC_G1_NC", Const, 10}, + {"R_ARM_ALU_PC_G2", Const, 10}, + {"R_ARM_ALU_SBREL_19_12_NC", Const, 10}, + {"R_ARM_ALU_SBREL_27_20_CK", Const, 10}, + {"R_ARM_ALU_SB_G0", Const, 10}, + {"R_ARM_ALU_SB_G0_NC", Const, 10}, + {"R_ARM_ALU_SB_G1", Const, 10}, + {"R_ARM_ALU_SB_G1_NC", Const, 10}, + {"R_ARM_ALU_SB_G2", Const, 10}, + {"R_ARM_AMP_VCALL9", Const, 0}, + {"R_ARM_BASE_ABS", Const, 10}, + {"R_ARM_CALL", Const, 10}, + {"R_ARM_COPY", Const, 0}, + {"R_ARM_GLOB_DAT", Const, 0}, + {"R_ARM_GNU_VTENTRY", Const, 0}, + {"R_ARM_GNU_VTINHERIT", Const, 0}, + {"R_ARM_GOT32", Const, 0}, + {"R_ARM_GOTOFF", Const, 0}, + {"R_ARM_GOTOFF12", Const, 10}, + {"R_ARM_GOTPC", Const, 0}, + {"R_ARM_GOTRELAX", Const, 10}, + {"R_ARM_GOT_ABS", Const, 10}, + {"R_ARM_GOT_BREL12", Const, 10}, + {"R_ARM_GOT_PREL", Const, 10}, + {"R_ARM_IRELATIVE", Const, 10}, + {"R_ARM_JUMP24", Const, 10}, + {"R_ARM_JUMP_SLOT", Const, 0}, + {"R_ARM_LDC_PC_G0", Const, 10}, + {"R_ARM_LDC_PC_G1", Const, 10}, + {"R_ARM_LDC_PC_G2", Const, 10}, + {"R_ARM_LDC_SB_G0", Const, 10}, + {"R_ARM_LDC_SB_G1", Const, 10}, + {"R_ARM_LDC_SB_G2", Const, 10}, + {"R_ARM_LDRS_PC_G0", Const, 10}, + {"R_ARM_LDRS_PC_G1", Const, 10}, + {"R_ARM_LDRS_PC_G2", Const, 10}, + {"R_ARM_LDRS_SB_G0", Const, 10}, + {"R_ARM_LDRS_SB_G1", Const, 10}, + {"R_ARM_LDRS_SB_G2", Const, 10}, + {"R_ARM_LDR_PC_G1", Const, 10}, + {"R_ARM_LDR_PC_G2", Const, 10}, + {"R_ARM_LDR_SBREL_11_10_NC", Const, 10}, + {"R_ARM_LDR_SB_G0", Const, 10}, + {"R_ARM_LDR_SB_G1", Const, 10}, + {"R_ARM_LDR_SB_G2", Const, 10}, + {"R_ARM_ME_TOO", Const, 10}, + {"R_ARM_MOVT_ABS", Const, 10}, + {"R_ARM_MOVT_BREL", Const, 10}, + {"R_ARM_MOVT_PREL", Const, 10}, + {"R_ARM_MOVW_ABS_NC", Const, 10}, + {"R_ARM_MOVW_BREL", Const, 10}, + {"R_ARM_MOVW_BREL_NC", Const, 10}, + {"R_ARM_MOVW_PREL_NC", Const, 10}, + {"R_ARM_NONE", Const, 0}, + {"R_ARM_PC13", Const, 0}, + {"R_ARM_PC24", Const, 0}, + {"R_ARM_PLT32", Const, 0}, + {"R_ARM_PLT32_ABS", Const, 10}, + {"R_ARM_PREL31", Const, 10}, + {"R_ARM_PRIVATE_0", Const, 10}, + {"R_ARM_PRIVATE_1", Const, 10}, + {"R_ARM_PRIVATE_10", Const, 10}, + {"R_ARM_PRIVATE_11", Const, 10}, + {"R_ARM_PRIVATE_12", Const, 10}, + {"R_ARM_PRIVATE_13", Const, 10}, + {"R_ARM_PRIVATE_14", Const, 10}, + {"R_ARM_PRIVATE_15", Const, 10}, + {"R_ARM_PRIVATE_2", Const, 10}, + {"R_ARM_PRIVATE_3", Const, 10}, + {"R_ARM_PRIVATE_4", Const, 10}, + {"R_ARM_PRIVATE_5", Const, 10}, + {"R_ARM_PRIVATE_6", Const, 10}, + {"R_ARM_PRIVATE_7", Const, 10}, + {"R_ARM_PRIVATE_8", Const, 10}, + {"R_ARM_PRIVATE_9", Const, 10}, + {"R_ARM_RABS32", Const, 0}, + {"R_ARM_RBASE", Const, 0}, + {"R_ARM_REL32", Const, 0}, + {"R_ARM_REL32_NOI", Const, 10}, + {"R_ARM_RELATIVE", Const, 0}, + {"R_ARM_RPC24", Const, 0}, + {"R_ARM_RREL32", Const, 0}, + {"R_ARM_RSBREL32", Const, 0}, + {"R_ARM_RXPC25", Const, 10}, + {"R_ARM_SBREL31", Const, 10}, + {"R_ARM_SBREL32", Const, 0}, + {"R_ARM_SWI24", Const, 0}, + {"R_ARM_TARGET1", Const, 10}, + {"R_ARM_TARGET2", Const, 10}, + {"R_ARM_THM_ABS5", Const, 0}, + {"R_ARM_THM_ALU_ABS_G0_NC", Const, 10}, + {"R_ARM_THM_ALU_ABS_G1_NC", Const, 10}, + {"R_ARM_THM_ALU_ABS_G2_NC", Const, 10}, + {"R_ARM_THM_ALU_ABS_G3", Const, 10}, + {"R_ARM_THM_ALU_PREL_11_0", Const, 10}, + {"R_ARM_THM_GOT_BREL12", Const, 10}, + {"R_ARM_THM_JUMP11", Const, 10}, + {"R_ARM_THM_JUMP19", Const, 10}, + {"R_ARM_THM_JUMP24", Const, 10}, + {"R_ARM_THM_JUMP6", Const, 10}, + {"R_ARM_THM_JUMP8", Const, 10}, + {"R_ARM_THM_MOVT_ABS", Const, 10}, + {"R_ARM_THM_MOVT_BREL", Const, 10}, + {"R_ARM_THM_MOVT_PREL", Const, 10}, + {"R_ARM_THM_MOVW_ABS_NC", Const, 10}, + {"R_ARM_THM_MOVW_BREL", Const, 10}, + {"R_ARM_THM_MOVW_BREL_NC", Const, 10}, + {"R_ARM_THM_MOVW_PREL_NC", Const, 10}, + {"R_ARM_THM_PC12", Const, 10}, + {"R_ARM_THM_PC22", Const, 0}, + {"R_ARM_THM_PC8", Const, 0}, + {"R_ARM_THM_RPC22", Const, 0}, + {"R_ARM_THM_SWI8", Const, 0}, + {"R_ARM_THM_TLS_CALL", Const, 10}, + {"R_ARM_THM_TLS_DESCSEQ16", Const, 10}, + {"R_ARM_THM_TLS_DESCSEQ32", Const, 10}, + {"R_ARM_THM_XPC22", Const, 0}, + {"R_ARM_TLS_CALL", Const, 10}, + {"R_ARM_TLS_DESCSEQ", Const, 10}, + {"R_ARM_TLS_DTPMOD32", Const, 10}, + {"R_ARM_TLS_DTPOFF32", Const, 10}, + {"R_ARM_TLS_GD32", Const, 10}, + {"R_ARM_TLS_GOTDESC", Const, 10}, + {"R_ARM_TLS_IE12GP", Const, 10}, + {"R_ARM_TLS_IE32", Const, 10}, + {"R_ARM_TLS_LDM32", Const, 10}, + {"R_ARM_TLS_LDO12", Const, 10}, + {"R_ARM_TLS_LDO32", Const, 10}, + {"R_ARM_TLS_LE12", Const, 10}, + {"R_ARM_TLS_LE32", Const, 10}, + {"R_ARM_TLS_TPOFF32", Const, 10}, + {"R_ARM_V4BX", Const, 10}, + {"R_ARM_XPC25", Const, 0}, + {"R_INFO", Func, 0}, + {"R_INFO32", Func, 0}, + {"R_LARCH", Type, 19}, + {"R_LARCH_32", Const, 19}, + {"R_LARCH_32_PCREL", Const, 20}, + {"R_LARCH_64", Const, 19}, + {"R_LARCH_64_PCREL", Const, 22}, + {"R_LARCH_ABS64_HI12", Const, 20}, + {"R_LARCH_ABS64_LO20", Const, 20}, + {"R_LARCH_ABS_HI20", Const, 20}, + {"R_LARCH_ABS_LO12", Const, 20}, + {"R_LARCH_ADD16", Const, 19}, + {"R_LARCH_ADD24", Const, 19}, + {"R_LARCH_ADD32", Const, 19}, + {"R_LARCH_ADD6", Const, 22}, + {"R_LARCH_ADD64", Const, 19}, + {"R_LARCH_ADD8", Const, 19}, + {"R_LARCH_ADD_ULEB128", Const, 22}, + {"R_LARCH_ALIGN", Const, 22}, + {"R_LARCH_B16", Const, 20}, + {"R_LARCH_B21", Const, 20}, + {"R_LARCH_B26", Const, 20}, + {"R_LARCH_CFA", Const, 22}, + {"R_LARCH_COPY", Const, 19}, + {"R_LARCH_DELETE", Const, 22}, + {"R_LARCH_GNU_VTENTRY", Const, 20}, + {"R_LARCH_GNU_VTINHERIT", Const, 20}, + {"R_LARCH_GOT64_HI12", Const, 20}, + {"R_LARCH_GOT64_LO20", Const, 20}, + {"R_LARCH_GOT64_PC_HI12", Const, 20}, + {"R_LARCH_GOT64_PC_LO20", Const, 20}, + {"R_LARCH_GOT_HI20", Const, 20}, + {"R_LARCH_GOT_LO12", Const, 20}, + {"R_LARCH_GOT_PC_HI20", Const, 20}, + {"R_LARCH_GOT_PC_LO12", Const, 20}, + {"R_LARCH_IRELATIVE", Const, 19}, + {"R_LARCH_JUMP_SLOT", Const, 19}, + {"R_LARCH_MARK_LA", Const, 19}, + {"R_LARCH_MARK_PCREL", Const, 19}, + {"R_LARCH_NONE", Const, 19}, + {"R_LARCH_PCALA64_HI12", Const, 20}, + {"R_LARCH_PCALA64_LO20", Const, 20}, + {"R_LARCH_PCALA_HI20", Const, 20}, + {"R_LARCH_PCALA_LO12", Const, 20}, + {"R_LARCH_PCREL20_S2", Const, 22}, + {"R_LARCH_RELATIVE", Const, 19}, + {"R_LARCH_RELAX", Const, 20}, + {"R_LARCH_SOP_ADD", Const, 19}, + {"R_LARCH_SOP_AND", Const, 19}, + {"R_LARCH_SOP_ASSERT", Const, 19}, + {"R_LARCH_SOP_IF_ELSE", Const, 19}, + {"R_LARCH_SOP_NOT", Const, 19}, + {"R_LARCH_SOP_POP_32_S_0_10_10_16_S2", Const, 19}, + {"R_LARCH_SOP_POP_32_S_0_5_10_16_S2", Const, 19}, + {"R_LARCH_SOP_POP_32_S_10_12", Const, 19}, + {"R_LARCH_SOP_POP_32_S_10_16", Const, 19}, + {"R_LARCH_SOP_POP_32_S_10_16_S2", Const, 19}, + {"R_LARCH_SOP_POP_32_S_10_5", Const, 19}, + {"R_LARCH_SOP_POP_32_S_5_20", Const, 19}, + {"R_LARCH_SOP_POP_32_U", Const, 19}, + {"R_LARCH_SOP_POP_32_U_10_12", Const, 19}, + {"R_LARCH_SOP_PUSH_ABSOLUTE", Const, 19}, + {"R_LARCH_SOP_PUSH_DUP", Const, 19}, + {"R_LARCH_SOP_PUSH_GPREL", Const, 19}, + {"R_LARCH_SOP_PUSH_PCREL", Const, 19}, + {"R_LARCH_SOP_PUSH_PLT_PCREL", Const, 19}, + {"R_LARCH_SOP_PUSH_TLS_GD", Const, 19}, + {"R_LARCH_SOP_PUSH_TLS_GOT", Const, 19}, + {"R_LARCH_SOP_PUSH_TLS_TPREL", Const, 19}, + {"R_LARCH_SOP_SL", Const, 19}, + {"R_LARCH_SOP_SR", Const, 19}, + {"R_LARCH_SOP_SUB", Const, 19}, + {"R_LARCH_SUB16", Const, 19}, + {"R_LARCH_SUB24", Const, 19}, + {"R_LARCH_SUB32", Const, 19}, + {"R_LARCH_SUB6", Const, 22}, + {"R_LARCH_SUB64", Const, 19}, + {"R_LARCH_SUB8", Const, 19}, + {"R_LARCH_SUB_ULEB128", Const, 22}, + {"R_LARCH_TLS_DTPMOD32", Const, 19}, + {"R_LARCH_TLS_DTPMOD64", Const, 19}, + {"R_LARCH_TLS_DTPREL32", Const, 19}, + {"R_LARCH_TLS_DTPREL64", Const, 19}, + {"R_LARCH_TLS_GD_HI20", Const, 20}, + {"R_LARCH_TLS_GD_PC_HI20", Const, 20}, + {"R_LARCH_TLS_IE64_HI12", Const, 20}, + {"R_LARCH_TLS_IE64_LO20", Const, 20}, + {"R_LARCH_TLS_IE64_PC_HI12", Const, 20}, + {"R_LARCH_TLS_IE64_PC_LO20", Const, 20}, + {"R_LARCH_TLS_IE_HI20", Const, 20}, + {"R_LARCH_TLS_IE_LO12", Const, 20}, + {"R_LARCH_TLS_IE_PC_HI20", Const, 20}, + {"R_LARCH_TLS_IE_PC_LO12", Const, 20}, + {"R_LARCH_TLS_LD_HI20", Const, 20}, + {"R_LARCH_TLS_LD_PC_HI20", Const, 20}, + {"R_LARCH_TLS_LE64_HI12", Const, 20}, + {"R_LARCH_TLS_LE64_LO20", Const, 20}, + {"R_LARCH_TLS_LE_HI20", Const, 20}, + {"R_LARCH_TLS_LE_LO12", Const, 20}, + {"R_LARCH_TLS_TPREL32", Const, 19}, + {"R_LARCH_TLS_TPREL64", Const, 19}, + {"R_MIPS", Type, 6}, + {"R_MIPS_16", Const, 6}, + {"R_MIPS_26", Const, 6}, + {"R_MIPS_32", Const, 6}, + {"R_MIPS_64", Const, 6}, + {"R_MIPS_ADD_IMMEDIATE", Const, 6}, + {"R_MIPS_CALL16", Const, 6}, + {"R_MIPS_CALL_HI16", Const, 6}, + {"R_MIPS_CALL_LO16", Const, 6}, + {"R_MIPS_DELETE", Const, 6}, + {"R_MIPS_GOT16", Const, 6}, + {"R_MIPS_GOT_DISP", Const, 6}, + {"R_MIPS_GOT_HI16", Const, 6}, + {"R_MIPS_GOT_LO16", Const, 6}, + {"R_MIPS_GOT_OFST", Const, 6}, + {"R_MIPS_GOT_PAGE", Const, 6}, + {"R_MIPS_GPREL16", Const, 6}, + {"R_MIPS_GPREL32", Const, 6}, + {"R_MIPS_HI16", Const, 6}, + {"R_MIPS_HIGHER", Const, 6}, + {"R_MIPS_HIGHEST", Const, 6}, + {"R_MIPS_INSERT_A", Const, 6}, + {"R_MIPS_INSERT_B", Const, 6}, + {"R_MIPS_JALR", Const, 6}, + {"R_MIPS_LITERAL", Const, 6}, + {"R_MIPS_LO16", Const, 6}, + {"R_MIPS_NONE", Const, 6}, + {"R_MIPS_PC16", Const, 6}, + {"R_MIPS_PC32", Const, 22}, + {"R_MIPS_PJUMP", Const, 6}, + {"R_MIPS_REL16", Const, 6}, + {"R_MIPS_REL32", Const, 6}, + {"R_MIPS_RELGOT", Const, 6}, + {"R_MIPS_SCN_DISP", Const, 6}, + {"R_MIPS_SHIFT5", Const, 6}, + {"R_MIPS_SHIFT6", Const, 6}, + {"R_MIPS_SUB", Const, 6}, + {"R_MIPS_TLS_DTPMOD32", Const, 6}, + {"R_MIPS_TLS_DTPMOD64", Const, 6}, + {"R_MIPS_TLS_DTPREL32", Const, 6}, + {"R_MIPS_TLS_DTPREL64", Const, 6}, + {"R_MIPS_TLS_DTPREL_HI16", Const, 6}, + {"R_MIPS_TLS_DTPREL_LO16", Const, 6}, + {"R_MIPS_TLS_GD", Const, 6}, + {"R_MIPS_TLS_GOTTPREL", Const, 6}, + {"R_MIPS_TLS_LDM", Const, 6}, + {"R_MIPS_TLS_TPREL32", Const, 6}, + {"R_MIPS_TLS_TPREL64", Const, 6}, + {"R_MIPS_TLS_TPREL_HI16", Const, 6}, + {"R_MIPS_TLS_TPREL_LO16", Const, 6}, + {"R_PPC", Type, 0}, + {"R_PPC64", Type, 5}, + {"R_PPC64_ADDR14", Const, 5}, + {"R_PPC64_ADDR14_BRNTAKEN", Const, 5}, + {"R_PPC64_ADDR14_BRTAKEN", Const, 5}, + {"R_PPC64_ADDR16", Const, 5}, + {"R_PPC64_ADDR16_DS", Const, 5}, + {"R_PPC64_ADDR16_HA", Const, 5}, + {"R_PPC64_ADDR16_HI", Const, 5}, + {"R_PPC64_ADDR16_HIGH", Const, 10}, + {"R_PPC64_ADDR16_HIGHA", Const, 10}, + {"R_PPC64_ADDR16_HIGHER", Const, 5}, + {"R_PPC64_ADDR16_HIGHER34", Const, 20}, + {"R_PPC64_ADDR16_HIGHERA", Const, 5}, + {"R_PPC64_ADDR16_HIGHERA34", Const, 20}, + {"R_PPC64_ADDR16_HIGHEST", Const, 5}, + {"R_PPC64_ADDR16_HIGHEST34", Const, 20}, + {"R_PPC64_ADDR16_HIGHESTA", Const, 5}, + {"R_PPC64_ADDR16_HIGHESTA34", Const, 20}, + {"R_PPC64_ADDR16_LO", Const, 5}, + {"R_PPC64_ADDR16_LO_DS", Const, 5}, + {"R_PPC64_ADDR24", Const, 5}, + {"R_PPC64_ADDR32", Const, 5}, + {"R_PPC64_ADDR64", Const, 5}, + {"R_PPC64_ADDR64_LOCAL", Const, 10}, + {"R_PPC64_COPY", Const, 20}, + {"R_PPC64_D28", Const, 20}, + {"R_PPC64_D34", Const, 20}, + {"R_PPC64_D34_HA30", Const, 20}, + {"R_PPC64_D34_HI30", Const, 20}, + {"R_PPC64_D34_LO", Const, 20}, + {"R_PPC64_DTPMOD64", Const, 5}, + {"R_PPC64_DTPREL16", Const, 5}, + {"R_PPC64_DTPREL16_DS", Const, 5}, + {"R_PPC64_DTPREL16_HA", Const, 5}, + {"R_PPC64_DTPREL16_HI", Const, 5}, + {"R_PPC64_DTPREL16_HIGH", Const, 10}, + {"R_PPC64_DTPREL16_HIGHA", Const, 10}, + {"R_PPC64_DTPREL16_HIGHER", Const, 5}, + {"R_PPC64_DTPREL16_HIGHERA", Const, 5}, + {"R_PPC64_DTPREL16_HIGHEST", Const, 5}, + {"R_PPC64_DTPREL16_HIGHESTA", Const, 5}, + {"R_PPC64_DTPREL16_LO", Const, 5}, + {"R_PPC64_DTPREL16_LO_DS", Const, 5}, + {"R_PPC64_DTPREL34", Const, 20}, + {"R_PPC64_DTPREL64", Const, 5}, + {"R_PPC64_ENTRY", Const, 10}, + {"R_PPC64_GLOB_DAT", Const, 20}, + {"R_PPC64_GNU_VTENTRY", Const, 20}, + {"R_PPC64_GNU_VTINHERIT", Const, 20}, + {"R_PPC64_GOT16", Const, 5}, + {"R_PPC64_GOT16_DS", Const, 5}, + {"R_PPC64_GOT16_HA", Const, 5}, + {"R_PPC64_GOT16_HI", Const, 5}, + {"R_PPC64_GOT16_LO", Const, 5}, + {"R_PPC64_GOT16_LO_DS", Const, 5}, + {"R_PPC64_GOT_DTPREL16_DS", Const, 5}, + {"R_PPC64_GOT_DTPREL16_HA", Const, 5}, + {"R_PPC64_GOT_DTPREL16_HI", Const, 5}, + {"R_PPC64_GOT_DTPREL16_LO_DS", Const, 5}, + {"R_PPC64_GOT_DTPREL_PCREL34", Const, 20}, + {"R_PPC64_GOT_PCREL34", Const, 20}, + {"R_PPC64_GOT_TLSGD16", Const, 5}, + {"R_PPC64_GOT_TLSGD16_HA", Const, 5}, + {"R_PPC64_GOT_TLSGD16_HI", Const, 5}, + {"R_PPC64_GOT_TLSGD16_LO", Const, 5}, + {"R_PPC64_GOT_TLSGD_PCREL34", Const, 20}, + {"R_PPC64_GOT_TLSLD16", Const, 5}, + {"R_PPC64_GOT_TLSLD16_HA", Const, 5}, + {"R_PPC64_GOT_TLSLD16_HI", Const, 5}, + {"R_PPC64_GOT_TLSLD16_LO", Const, 5}, + {"R_PPC64_GOT_TLSLD_PCREL34", Const, 20}, + {"R_PPC64_GOT_TPREL16_DS", Const, 5}, + {"R_PPC64_GOT_TPREL16_HA", Const, 5}, + {"R_PPC64_GOT_TPREL16_HI", Const, 5}, + {"R_PPC64_GOT_TPREL16_LO_DS", Const, 5}, + {"R_PPC64_GOT_TPREL_PCREL34", Const, 20}, + {"R_PPC64_IRELATIVE", Const, 10}, + {"R_PPC64_JMP_IREL", Const, 10}, + {"R_PPC64_JMP_SLOT", Const, 5}, + {"R_PPC64_NONE", Const, 5}, + {"R_PPC64_PCREL28", Const, 20}, + {"R_PPC64_PCREL34", Const, 20}, + {"R_PPC64_PCREL_OPT", Const, 20}, + {"R_PPC64_PLT16_HA", Const, 20}, + {"R_PPC64_PLT16_HI", Const, 20}, + {"R_PPC64_PLT16_LO", Const, 20}, + {"R_PPC64_PLT16_LO_DS", Const, 10}, + {"R_PPC64_PLT32", Const, 20}, + {"R_PPC64_PLT64", Const, 20}, + {"R_PPC64_PLTCALL", Const, 20}, + {"R_PPC64_PLTCALL_NOTOC", Const, 20}, + {"R_PPC64_PLTGOT16", Const, 10}, + {"R_PPC64_PLTGOT16_DS", Const, 10}, + {"R_PPC64_PLTGOT16_HA", Const, 10}, + {"R_PPC64_PLTGOT16_HI", Const, 10}, + {"R_PPC64_PLTGOT16_LO", Const, 10}, + {"R_PPC64_PLTGOT_LO_DS", Const, 10}, + {"R_PPC64_PLTREL32", Const, 20}, + {"R_PPC64_PLTREL64", Const, 20}, + {"R_PPC64_PLTSEQ", Const, 20}, + {"R_PPC64_PLTSEQ_NOTOC", Const, 20}, + {"R_PPC64_PLT_PCREL34", Const, 20}, + {"R_PPC64_PLT_PCREL34_NOTOC", Const, 20}, + {"R_PPC64_REL14", Const, 5}, + {"R_PPC64_REL14_BRNTAKEN", Const, 5}, + {"R_PPC64_REL14_BRTAKEN", Const, 5}, + {"R_PPC64_REL16", Const, 5}, + {"R_PPC64_REL16DX_HA", Const, 10}, + {"R_PPC64_REL16_HA", Const, 5}, + {"R_PPC64_REL16_HI", Const, 5}, + {"R_PPC64_REL16_HIGH", Const, 20}, + {"R_PPC64_REL16_HIGHA", Const, 20}, + {"R_PPC64_REL16_HIGHER", Const, 20}, + {"R_PPC64_REL16_HIGHER34", Const, 20}, + {"R_PPC64_REL16_HIGHERA", Const, 20}, + {"R_PPC64_REL16_HIGHERA34", Const, 20}, + {"R_PPC64_REL16_HIGHEST", Const, 20}, + {"R_PPC64_REL16_HIGHEST34", Const, 20}, + {"R_PPC64_REL16_HIGHESTA", Const, 20}, + {"R_PPC64_REL16_HIGHESTA34", Const, 20}, + {"R_PPC64_REL16_LO", Const, 5}, + {"R_PPC64_REL24", Const, 5}, + {"R_PPC64_REL24_NOTOC", Const, 10}, + {"R_PPC64_REL24_P9NOTOC", Const, 21}, + {"R_PPC64_REL30", Const, 20}, + {"R_PPC64_REL32", Const, 5}, + {"R_PPC64_REL64", Const, 5}, + {"R_PPC64_RELATIVE", Const, 18}, + {"R_PPC64_SECTOFF", Const, 20}, + {"R_PPC64_SECTOFF_DS", Const, 10}, + {"R_PPC64_SECTOFF_HA", Const, 20}, + {"R_PPC64_SECTOFF_HI", Const, 20}, + {"R_PPC64_SECTOFF_LO", Const, 20}, + {"R_PPC64_SECTOFF_LO_DS", Const, 10}, + {"R_PPC64_TLS", Const, 5}, + {"R_PPC64_TLSGD", Const, 5}, + {"R_PPC64_TLSLD", Const, 5}, + {"R_PPC64_TOC", Const, 5}, + {"R_PPC64_TOC16", Const, 5}, + {"R_PPC64_TOC16_DS", Const, 5}, + {"R_PPC64_TOC16_HA", Const, 5}, + {"R_PPC64_TOC16_HI", Const, 5}, + {"R_PPC64_TOC16_LO", Const, 5}, + {"R_PPC64_TOC16_LO_DS", Const, 5}, + {"R_PPC64_TOCSAVE", Const, 10}, + {"R_PPC64_TPREL16", Const, 5}, + {"R_PPC64_TPREL16_DS", Const, 5}, + {"R_PPC64_TPREL16_HA", Const, 5}, + {"R_PPC64_TPREL16_HI", Const, 5}, + {"R_PPC64_TPREL16_HIGH", Const, 10}, + {"R_PPC64_TPREL16_HIGHA", Const, 10}, + {"R_PPC64_TPREL16_HIGHER", Const, 5}, + {"R_PPC64_TPREL16_HIGHERA", Const, 5}, + {"R_PPC64_TPREL16_HIGHEST", Const, 5}, + {"R_PPC64_TPREL16_HIGHESTA", Const, 5}, + {"R_PPC64_TPREL16_LO", Const, 5}, + {"R_PPC64_TPREL16_LO_DS", Const, 5}, + {"R_PPC64_TPREL34", Const, 20}, + {"R_PPC64_TPREL64", Const, 5}, + {"R_PPC64_UADDR16", Const, 20}, + {"R_PPC64_UADDR32", Const, 20}, + {"R_PPC64_UADDR64", Const, 20}, + {"R_PPC_ADDR14", Const, 0}, + {"R_PPC_ADDR14_BRNTAKEN", Const, 0}, + {"R_PPC_ADDR14_BRTAKEN", Const, 0}, + {"R_PPC_ADDR16", Const, 0}, + {"R_PPC_ADDR16_HA", Const, 0}, + {"R_PPC_ADDR16_HI", Const, 0}, + {"R_PPC_ADDR16_LO", Const, 0}, + {"R_PPC_ADDR24", Const, 0}, + {"R_PPC_ADDR32", Const, 0}, + {"R_PPC_COPY", Const, 0}, + {"R_PPC_DTPMOD32", Const, 0}, + {"R_PPC_DTPREL16", Const, 0}, + {"R_PPC_DTPREL16_HA", Const, 0}, + {"R_PPC_DTPREL16_HI", Const, 0}, + {"R_PPC_DTPREL16_LO", Const, 0}, + {"R_PPC_DTPREL32", Const, 0}, + {"R_PPC_EMB_BIT_FLD", Const, 0}, + {"R_PPC_EMB_MRKREF", Const, 0}, + {"R_PPC_EMB_NADDR16", Const, 0}, + {"R_PPC_EMB_NADDR16_HA", Const, 0}, + {"R_PPC_EMB_NADDR16_HI", Const, 0}, + {"R_PPC_EMB_NADDR16_LO", Const, 0}, + {"R_PPC_EMB_NADDR32", Const, 0}, + {"R_PPC_EMB_RELSDA", Const, 0}, + {"R_PPC_EMB_RELSEC16", Const, 0}, + {"R_PPC_EMB_RELST_HA", Const, 0}, + {"R_PPC_EMB_RELST_HI", Const, 0}, + {"R_PPC_EMB_RELST_LO", Const, 0}, + {"R_PPC_EMB_SDA21", Const, 0}, + {"R_PPC_EMB_SDA2I16", Const, 0}, + {"R_PPC_EMB_SDA2REL", Const, 0}, + {"R_PPC_EMB_SDAI16", Const, 0}, + {"R_PPC_GLOB_DAT", Const, 0}, + {"R_PPC_GOT16", Const, 0}, + {"R_PPC_GOT16_HA", Const, 0}, + {"R_PPC_GOT16_HI", Const, 0}, + {"R_PPC_GOT16_LO", Const, 0}, + {"R_PPC_GOT_TLSGD16", Const, 0}, + {"R_PPC_GOT_TLSGD16_HA", Const, 0}, + {"R_PPC_GOT_TLSGD16_HI", Const, 0}, + {"R_PPC_GOT_TLSGD16_LO", Const, 0}, + {"R_PPC_GOT_TLSLD16", Const, 0}, + {"R_PPC_GOT_TLSLD16_HA", Const, 0}, + {"R_PPC_GOT_TLSLD16_HI", Const, 0}, + {"R_PPC_GOT_TLSLD16_LO", Const, 0}, + {"R_PPC_GOT_TPREL16", Const, 0}, + {"R_PPC_GOT_TPREL16_HA", Const, 0}, + {"R_PPC_GOT_TPREL16_HI", Const, 0}, + {"R_PPC_GOT_TPREL16_LO", Const, 0}, + {"R_PPC_JMP_SLOT", Const, 0}, + {"R_PPC_LOCAL24PC", Const, 0}, + {"R_PPC_NONE", Const, 0}, + {"R_PPC_PLT16_HA", Const, 0}, + {"R_PPC_PLT16_HI", Const, 0}, + {"R_PPC_PLT16_LO", Const, 0}, + {"R_PPC_PLT32", Const, 0}, + {"R_PPC_PLTREL24", Const, 0}, + {"R_PPC_PLTREL32", Const, 0}, + {"R_PPC_REL14", Const, 0}, + {"R_PPC_REL14_BRNTAKEN", Const, 0}, + {"R_PPC_REL14_BRTAKEN", Const, 0}, + {"R_PPC_REL24", Const, 0}, + {"R_PPC_REL32", Const, 0}, + {"R_PPC_RELATIVE", Const, 0}, + {"R_PPC_SDAREL16", Const, 0}, + {"R_PPC_SECTOFF", Const, 0}, + {"R_PPC_SECTOFF_HA", Const, 0}, + {"R_PPC_SECTOFF_HI", Const, 0}, + {"R_PPC_SECTOFF_LO", Const, 0}, + {"R_PPC_TLS", Const, 0}, + {"R_PPC_TPREL16", Const, 0}, + {"R_PPC_TPREL16_HA", Const, 0}, + {"R_PPC_TPREL16_HI", Const, 0}, + {"R_PPC_TPREL16_LO", Const, 0}, + {"R_PPC_TPREL32", Const, 0}, + {"R_PPC_UADDR16", Const, 0}, + {"R_PPC_UADDR32", Const, 0}, + {"R_RISCV", Type, 11}, + {"R_RISCV_32", Const, 11}, + {"R_RISCV_32_PCREL", Const, 12}, + {"R_RISCV_64", Const, 11}, + {"R_RISCV_ADD16", Const, 11}, + {"R_RISCV_ADD32", Const, 11}, + {"R_RISCV_ADD64", Const, 11}, + {"R_RISCV_ADD8", Const, 11}, + {"R_RISCV_ALIGN", Const, 11}, + {"R_RISCV_BRANCH", Const, 11}, + {"R_RISCV_CALL", Const, 11}, + {"R_RISCV_CALL_PLT", Const, 11}, + {"R_RISCV_COPY", Const, 11}, + {"R_RISCV_GNU_VTENTRY", Const, 11}, + {"R_RISCV_GNU_VTINHERIT", Const, 11}, + {"R_RISCV_GOT_HI20", Const, 11}, + {"R_RISCV_GPREL_I", Const, 11}, + {"R_RISCV_GPREL_S", Const, 11}, + {"R_RISCV_HI20", Const, 11}, + {"R_RISCV_JAL", Const, 11}, + {"R_RISCV_JUMP_SLOT", Const, 11}, + {"R_RISCV_LO12_I", Const, 11}, + {"R_RISCV_LO12_S", Const, 11}, + {"R_RISCV_NONE", Const, 11}, + {"R_RISCV_PCREL_HI20", Const, 11}, + {"R_RISCV_PCREL_LO12_I", Const, 11}, + {"R_RISCV_PCREL_LO12_S", Const, 11}, + {"R_RISCV_RELATIVE", Const, 11}, + {"R_RISCV_RELAX", Const, 11}, + {"R_RISCV_RVC_BRANCH", Const, 11}, + {"R_RISCV_RVC_JUMP", Const, 11}, + {"R_RISCV_RVC_LUI", Const, 11}, + {"R_RISCV_SET16", Const, 11}, + {"R_RISCV_SET32", Const, 11}, + {"R_RISCV_SET6", Const, 11}, + {"R_RISCV_SET8", Const, 11}, + {"R_RISCV_SUB16", Const, 11}, + {"R_RISCV_SUB32", Const, 11}, + {"R_RISCV_SUB6", Const, 11}, + {"R_RISCV_SUB64", Const, 11}, + {"R_RISCV_SUB8", Const, 11}, + {"R_RISCV_TLS_DTPMOD32", Const, 11}, + {"R_RISCV_TLS_DTPMOD64", Const, 11}, + {"R_RISCV_TLS_DTPREL32", Const, 11}, + {"R_RISCV_TLS_DTPREL64", Const, 11}, + {"R_RISCV_TLS_GD_HI20", Const, 11}, + {"R_RISCV_TLS_GOT_HI20", Const, 11}, + {"R_RISCV_TLS_TPREL32", Const, 11}, + {"R_RISCV_TLS_TPREL64", Const, 11}, + {"R_RISCV_TPREL_ADD", Const, 11}, + {"R_RISCV_TPREL_HI20", Const, 11}, + {"R_RISCV_TPREL_I", Const, 11}, + {"R_RISCV_TPREL_LO12_I", Const, 11}, + {"R_RISCV_TPREL_LO12_S", Const, 11}, + {"R_RISCV_TPREL_S", Const, 11}, + {"R_SPARC", Type, 0}, + {"R_SPARC_10", Const, 0}, + {"R_SPARC_11", Const, 0}, + {"R_SPARC_13", Const, 0}, + {"R_SPARC_16", Const, 0}, + {"R_SPARC_22", Const, 0}, + {"R_SPARC_32", Const, 0}, + {"R_SPARC_5", Const, 0}, + {"R_SPARC_6", Const, 0}, + {"R_SPARC_64", Const, 0}, + {"R_SPARC_7", Const, 0}, + {"R_SPARC_8", Const, 0}, + {"R_SPARC_COPY", Const, 0}, + {"R_SPARC_DISP16", Const, 0}, + {"R_SPARC_DISP32", Const, 0}, + {"R_SPARC_DISP64", Const, 0}, + {"R_SPARC_DISP8", Const, 0}, + {"R_SPARC_GLOB_DAT", Const, 0}, + {"R_SPARC_GLOB_JMP", Const, 0}, + {"R_SPARC_GOT10", Const, 0}, + {"R_SPARC_GOT13", Const, 0}, + {"R_SPARC_GOT22", Const, 0}, + {"R_SPARC_H44", Const, 0}, + {"R_SPARC_HH22", Const, 0}, + {"R_SPARC_HI22", Const, 0}, + {"R_SPARC_HIPLT22", Const, 0}, + {"R_SPARC_HIX22", Const, 0}, + {"R_SPARC_HM10", Const, 0}, + {"R_SPARC_JMP_SLOT", Const, 0}, + {"R_SPARC_L44", Const, 0}, + {"R_SPARC_LM22", Const, 0}, + {"R_SPARC_LO10", Const, 0}, + {"R_SPARC_LOPLT10", Const, 0}, + {"R_SPARC_LOX10", Const, 0}, + {"R_SPARC_M44", Const, 0}, + {"R_SPARC_NONE", Const, 0}, + {"R_SPARC_OLO10", Const, 0}, + {"R_SPARC_PC10", Const, 0}, + {"R_SPARC_PC22", Const, 0}, + {"R_SPARC_PCPLT10", Const, 0}, + {"R_SPARC_PCPLT22", Const, 0}, + {"R_SPARC_PCPLT32", Const, 0}, + {"R_SPARC_PC_HH22", Const, 0}, + {"R_SPARC_PC_HM10", Const, 0}, + {"R_SPARC_PC_LM22", Const, 0}, + {"R_SPARC_PLT32", Const, 0}, + {"R_SPARC_PLT64", Const, 0}, + {"R_SPARC_REGISTER", Const, 0}, + {"R_SPARC_RELATIVE", Const, 0}, + {"R_SPARC_UA16", Const, 0}, + {"R_SPARC_UA32", Const, 0}, + {"R_SPARC_UA64", Const, 0}, + {"R_SPARC_WDISP16", Const, 0}, + {"R_SPARC_WDISP19", Const, 0}, + {"R_SPARC_WDISP22", Const, 0}, + {"R_SPARC_WDISP30", Const, 0}, + {"R_SPARC_WPLT30", Const, 0}, + {"R_SYM32", Func, 0}, + {"R_SYM64", Func, 0}, + {"R_TYPE32", Func, 0}, + {"R_TYPE64", Func, 0}, + {"R_X86_64", Type, 0}, + {"R_X86_64_16", Const, 0}, + {"R_X86_64_32", Const, 0}, + {"R_X86_64_32S", Const, 0}, + {"R_X86_64_64", Const, 0}, + {"R_X86_64_8", Const, 0}, + {"R_X86_64_COPY", Const, 0}, + {"R_X86_64_DTPMOD64", Const, 0}, + {"R_X86_64_DTPOFF32", Const, 0}, + {"R_X86_64_DTPOFF64", Const, 0}, + {"R_X86_64_GLOB_DAT", Const, 0}, + {"R_X86_64_GOT32", Const, 0}, + {"R_X86_64_GOT64", Const, 10}, + {"R_X86_64_GOTOFF64", Const, 10}, + {"R_X86_64_GOTPC32", Const, 10}, + {"R_X86_64_GOTPC32_TLSDESC", Const, 10}, + {"R_X86_64_GOTPC64", Const, 10}, + {"R_X86_64_GOTPCREL", Const, 0}, + {"R_X86_64_GOTPCREL64", Const, 10}, + {"R_X86_64_GOTPCRELX", Const, 10}, + {"R_X86_64_GOTPLT64", Const, 10}, + {"R_X86_64_GOTTPOFF", Const, 0}, + {"R_X86_64_IRELATIVE", Const, 10}, + {"R_X86_64_JMP_SLOT", Const, 0}, + {"R_X86_64_NONE", Const, 0}, + {"R_X86_64_PC16", Const, 0}, + {"R_X86_64_PC32", Const, 0}, + {"R_X86_64_PC32_BND", Const, 10}, + {"R_X86_64_PC64", Const, 10}, + {"R_X86_64_PC8", Const, 0}, + {"R_X86_64_PLT32", Const, 0}, + {"R_X86_64_PLT32_BND", Const, 10}, + {"R_X86_64_PLTOFF64", Const, 10}, + {"R_X86_64_RELATIVE", Const, 0}, + {"R_X86_64_RELATIVE64", Const, 10}, + {"R_X86_64_REX_GOTPCRELX", Const, 10}, + {"R_X86_64_SIZE32", Const, 10}, + {"R_X86_64_SIZE64", Const, 10}, + {"R_X86_64_TLSDESC", Const, 10}, + {"R_X86_64_TLSDESC_CALL", Const, 10}, + {"R_X86_64_TLSGD", Const, 0}, + {"R_X86_64_TLSLD", Const, 0}, + {"R_X86_64_TPOFF32", Const, 0}, + {"R_X86_64_TPOFF64", Const, 0}, + {"Rel32", Type, 0}, + {"Rel32.Info", Field, 0}, + {"Rel32.Off", Field, 0}, + {"Rel64", Type, 0}, + {"Rel64.Info", Field, 0}, + {"Rel64.Off", Field, 0}, + {"Rela32", Type, 0}, + {"Rela32.Addend", Field, 0}, + {"Rela32.Info", Field, 0}, + {"Rela32.Off", Field, 0}, + {"Rela64", Type, 0}, + {"Rela64.Addend", Field, 0}, + {"Rela64.Info", Field, 0}, + {"Rela64.Off", Field, 0}, + {"SHF_ALLOC", Const, 0}, + {"SHF_COMPRESSED", Const, 6}, + {"SHF_EXECINSTR", Const, 0}, + {"SHF_GROUP", Const, 0}, + {"SHF_INFO_LINK", Const, 0}, + {"SHF_LINK_ORDER", Const, 0}, + {"SHF_MASKOS", Const, 0}, + {"SHF_MASKPROC", Const, 0}, + {"SHF_MERGE", Const, 0}, + {"SHF_OS_NONCONFORMING", Const, 0}, + {"SHF_STRINGS", Const, 0}, + {"SHF_TLS", Const, 0}, + {"SHF_WRITE", Const, 0}, + {"SHN_ABS", Const, 0}, + {"SHN_COMMON", Const, 0}, + {"SHN_HIOS", Const, 0}, + {"SHN_HIPROC", Const, 0}, + {"SHN_HIRESERVE", Const, 0}, + {"SHN_LOOS", Const, 0}, + {"SHN_LOPROC", Const, 0}, + {"SHN_LORESERVE", Const, 0}, + {"SHN_UNDEF", Const, 0}, + {"SHN_XINDEX", Const, 0}, + {"SHT_DYNAMIC", Const, 0}, + {"SHT_DYNSYM", Const, 0}, + {"SHT_FINI_ARRAY", Const, 0}, + {"SHT_GNU_ATTRIBUTES", Const, 0}, + {"SHT_GNU_HASH", Const, 0}, + {"SHT_GNU_LIBLIST", Const, 0}, + {"SHT_GNU_VERDEF", Const, 0}, + {"SHT_GNU_VERNEED", Const, 0}, + {"SHT_GNU_VERSYM", Const, 0}, + {"SHT_GROUP", Const, 0}, + {"SHT_HASH", Const, 0}, + {"SHT_HIOS", Const, 0}, + {"SHT_HIPROC", Const, 0}, + {"SHT_HIUSER", Const, 0}, + {"SHT_INIT_ARRAY", Const, 0}, + {"SHT_LOOS", Const, 0}, + {"SHT_LOPROC", Const, 0}, + {"SHT_LOUSER", Const, 0}, + {"SHT_MIPS_ABIFLAGS", Const, 17}, + {"SHT_NOBITS", Const, 0}, + {"SHT_NOTE", Const, 0}, + {"SHT_NULL", Const, 0}, + {"SHT_PREINIT_ARRAY", Const, 0}, + {"SHT_PROGBITS", Const, 0}, + {"SHT_REL", Const, 0}, + {"SHT_RELA", Const, 0}, + {"SHT_SHLIB", Const, 0}, + {"SHT_STRTAB", Const, 0}, + {"SHT_SYMTAB", Const, 0}, + {"SHT_SYMTAB_SHNDX", Const, 0}, + {"STB_GLOBAL", Const, 0}, + {"STB_HIOS", Const, 0}, + {"STB_HIPROC", Const, 0}, + {"STB_LOCAL", Const, 0}, + {"STB_LOOS", Const, 0}, + {"STB_LOPROC", Const, 0}, + {"STB_WEAK", Const, 0}, + {"STT_COMMON", Const, 0}, + {"STT_FILE", Const, 0}, + {"STT_FUNC", Const, 0}, + {"STT_HIOS", Const, 0}, + {"STT_HIPROC", Const, 0}, + {"STT_LOOS", Const, 0}, + {"STT_LOPROC", Const, 0}, + {"STT_NOTYPE", Const, 0}, + {"STT_OBJECT", Const, 0}, + {"STT_SECTION", Const, 0}, + {"STT_TLS", Const, 0}, + {"STV_DEFAULT", Const, 0}, + {"STV_HIDDEN", Const, 0}, + {"STV_INTERNAL", Const, 0}, + {"STV_PROTECTED", Const, 0}, + {"ST_BIND", Func, 0}, + {"ST_INFO", Func, 0}, + {"ST_TYPE", Func, 0}, + {"ST_VISIBILITY", Func, 0}, + {"Section", Type, 0}, + {"Section.ReaderAt", Field, 0}, + {"Section.SectionHeader", Field, 0}, + {"Section32", Type, 0}, + {"Section32.Addr", Field, 0}, + {"Section32.Addralign", Field, 0}, + {"Section32.Entsize", Field, 0}, + {"Section32.Flags", Field, 0}, + {"Section32.Info", Field, 0}, + {"Section32.Link", Field, 0}, + {"Section32.Name", Field, 0}, + {"Section32.Off", Field, 0}, + {"Section32.Size", Field, 0}, + {"Section32.Type", Field, 0}, + {"Section64", Type, 0}, + {"Section64.Addr", Field, 0}, + {"Section64.Addralign", Field, 0}, + {"Section64.Entsize", Field, 0}, + {"Section64.Flags", Field, 0}, + {"Section64.Info", Field, 0}, + {"Section64.Link", Field, 0}, + {"Section64.Name", Field, 0}, + {"Section64.Off", Field, 0}, + {"Section64.Size", Field, 0}, + {"Section64.Type", Field, 0}, + {"SectionFlag", Type, 0}, + {"SectionHeader", Type, 0}, + {"SectionHeader.Addr", Field, 0}, + {"SectionHeader.Addralign", Field, 0}, + {"SectionHeader.Entsize", Field, 0}, + {"SectionHeader.FileSize", Field, 6}, + {"SectionHeader.Flags", Field, 0}, + {"SectionHeader.Info", Field, 0}, + {"SectionHeader.Link", Field, 0}, + {"SectionHeader.Name", Field, 0}, + {"SectionHeader.Offset", Field, 0}, + {"SectionHeader.Size", Field, 0}, + {"SectionHeader.Type", Field, 0}, + {"SectionIndex", Type, 0}, + {"SectionType", Type, 0}, + {"Sym32", Type, 0}, + {"Sym32.Info", Field, 0}, + {"Sym32.Name", Field, 0}, + {"Sym32.Other", Field, 0}, + {"Sym32.Shndx", Field, 0}, + {"Sym32.Size", Field, 0}, + {"Sym32.Value", Field, 0}, + {"Sym32Size", Const, 0}, + {"Sym64", Type, 0}, + {"Sym64.Info", Field, 0}, + {"Sym64.Name", Field, 0}, + {"Sym64.Other", Field, 0}, + {"Sym64.Shndx", Field, 0}, + {"Sym64.Size", Field, 0}, + {"Sym64.Value", Field, 0}, + {"Sym64Size", Const, 0}, + {"SymBind", Type, 0}, + {"SymType", Type, 0}, + {"SymVis", Type, 0}, + {"Symbol", Type, 0}, + {"Symbol.Info", Field, 0}, + {"Symbol.Library", Field, 13}, + {"Symbol.Name", Field, 0}, + {"Symbol.Other", Field, 0}, + {"Symbol.Section", Field, 0}, + {"Symbol.Size", Field, 0}, + {"Symbol.Value", Field, 0}, + {"Symbol.Version", Field, 13}, + {"Type", Type, 0}, + {"Version", Type, 0}, + }, + "debug/gosym": { + {"(*DecodingError).Error", Method, 0}, + {"(*LineTable).LineToPC", Method, 0}, + {"(*LineTable).PCToLine", Method, 0}, + {"(*Sym).BaseName", Method, 0}, + {"(*Sym).PackageName", Method, 0}, + {"(*Sym).ReceiverName", Method, 0}, + {"(*Sym).Static", Method, 0}, + {"(*Table).LineToPC", Method, 0}, + {"(*Table).LookupFunc", Method, 0}, + {"(*Table).LookupSym", Method, 0}, + {"(*Table).PCToFunc", Method, 0}, + {"(*Table).PCToLine", Method, 0}, + {"(*Table).SymByAddr", Method, 0}, + {"(*UnknownLineError).Error", Method, 0}, + {"(Func).BaseName", Method, 0}, + {"(Func).PackageName", Method, 0}, + {"(Func).ReceiverName", Method, 0}, + {"(Func).Static", Method, 0}, + {"(UnknownFileError).Error", Method, 0}, + {"DecodingError", Type, 0}, + {"Func", Type, 0}, + {"Func.End", Field, 0}, + {"Func.Entry", Field, 0}, + {"Func.FrameSize", Field, 0}, + {"Func.LineTable", Field, 0}, + {"Func.Locals", Field, 0}, + {"Func.Obj", Field, 0}, + {"Func.Params", Field, 0}, + {"Func.Sym", Field, 0}, + {"LineTable", Type, 0}, + {"LineTable.Data", Field, 0}, + {"LineTable.Line", Field, 0}, + {"LineTable.PC", Field, 0}, + {"NewLineTable", Func, 0}, + {"NewTable", Func, 0}, + {"Obj", Type, 0}, + {"Obj.Funcs", Field, 0}, + {"Obj.Paths", Field, 0}, + {"Sym", Type, 0}, + {"Sym.Func", Field, 0}, + {"Sym.GoType", Field, 0}, + {"Sym.Name", Field, 0}, + {"Sym.Type", Field, 0}, + {"Sym.Value", Field, 0}, + {"Table", Type, 0}, + {"Table.Files", Field, 0}, + {"Table.Funcs", Field, 0}, + {"Table.Objs", Field, 0}, + {"Table.Syms", Field, 0}, + {"UnknownFileError", Type, 0}, + {"UnknownLineError", Type, 0}, + {"UnknownLineError.File", Field, 0}, + {"UnknownLineError.Line", Field, 0}, + }, + "debug/macho": { + {"(*FatFile).Close", Method, 3}, + {"(*File).Close", Method, 0}, + {"(*File).DWARF", Method, 0}, + {"(*File).ImportedLibraries", Method, 0}, + {"(*File).ImportedSymbols", Method, 0}, + {"(*File).Section", Method, 0}, + {"(*File).Segment", Method, 0}, + {"(*FormatError).Error", Method, 0}, + {"(*Section).Data", Method, 0}, + {"(*Section).Open", Method, 0}, + {"(*Segment).Data", Method, 0}, + {"(*Segment).Open", Method, 0}, + {"(Cpu).GoString", Method, 0}, + {"(Cpu).String", Method, 0}, + {"(Dylib).Raw", Method, 0}, + {"(Dysymtab).Raw", Method, 0}, + {"(FatArch).Close", Method, 3}, + {"(FatArch).DWARF", Method, 3}, + {"(FatArch).ImportedLibraries", Method, 3}, + {"(FatArch).ImportedSymbols", Method, 3}, + {"(FatArch).Section", Method, 3}, + {"(FatArch).Segment", Method, 3}, + {"(LoadBytes).Raw", Method, 0}, + {"(LoadCmd).GoString", Method, 0}, + {"(LoadCmd).String", Method, 0}, + {"(RelocTypeARM).GoString", Method, 10}, + {"(RelocTypeARM).String", Method, 10}, + {"(RelocTypeARM64).GoString", Method, 10}, + {"(RelocTypeARM64).String", Method, 10}, + {"(RelocTypeGeneric).GoString", Method, 10}, + {"(RelocTypeGeneric).String", Method, 10}, + {"(RelocTypeX86_64).GoString", Method, 10}, + {"(RelocTypeX86_64).String", Method, 10}, + {"(Rpath).Raw", Method, 10}, + {"(Section).ReadAt", Method, 0}, + {"(Segment).Raw", Method, 0}, + {"(Segment).ReadAt", Method, 0}, + {"(Symtab).Raw", Method, 0}, + {"(Type).GoString", Method, 10}, + {"(Type).String", Method, 10}, + {"ARM64_RELOC_ADDEND", Const, 10}, + {"ARM64_RELOC_BRANCH26", Const, 10}, + {"ARM64_RELOC_GOT_LOAD_PAGE21", Const, 10}, + {"ARM64_RELOC_GOT_LOAD_PAGEOFF12", Const, 10}, + {"ARM64_RELOC_PAGE21", Const, 10}, + {"ARM64_RELOC_PAGEOFF12", Const, 10}, + {"ARM64_RELOC_POINTER_TO_GOT", Const, 10}, + {"ARM64_RELOC_SUBTRACTOR", Const, 10}, + {"ARM64_RELOC_TLVP_LOAD_PAGE21", Const, 10}, + {"ARM64_RELOC_TLVP_LOAD_PAGEOFF12", Const, 10}, + {"ARM64_RELOC_UNSIGNED", Const, 10}, + {"ARM_RELOC_BR24", Const, 10}, + {"ARM_RELOC_HALF", Const, 10}, + {"ARM_RELOC_HALF_SECTDIFF", Const, 10}, + {"ARM_RELOC_LOCAL_SECTDIFF", Const, 10}, + {"ARM_RELOC_PAIR", Const, 10}, + {"ARM_RELOC_PB_LA_PTR", Const, 10}, + {"ARM_RELOC_SECTDIFF", Const, 10}, + {"ARM_RELOC_VANILLA", Const, 10}, + {"ARM_THUMB_32BIT_BRANCH", Const, 10}, + {"ARM_THUMB_RELOC_BR22", Const, 10}, + {"Cpu", Type, 0}, + {"Cpu386", Const, 0}, + {"CpuAmd64", Const, 0}, + {"CpuArm", Const, 3}, + {"CpuArm64", Const, 11}, + {"CpuPpc", Const, 3}, + {"CpuPpc64", Const, 3}, + {"Dylib", Type, 0}, + {"Dylib.CompatVersion", Field, 0}, + {"Dylib.CurrentVersion", Field, 0}, + {"Dylib.LoadBytes", Field, 0}, + {"Dylib.Name", Field, 0}, + {"Dylib.Time", Field, 0}, + {"DylibCmd", Type, 0}, + {"DylibCmd.Cmd", Field, 0}, + {"DylibCmd.CompatVersion", Field, 0}, + {"DylibCmd.CurrentVersion", Field, 0}, + {"DylibCmd.Len", Field, 0}, + {"DylibCmd.Name", Field, 0}, + {"DylibCmd.Time", Field, 0}, + {"Dysymtab", Type, 0}, + {"Dysymtab.DysymtabCmd", Field, 0}, + {"Dysymtab.IndirectSyms", Field, 0}, + {"Dysymtab.LoadBytes", Field, 0}, + {"DysymtabCmd", Type, 0}, + {"DysymtabCmd.Cmd", Field, 0}, + {"DysymtabCmd.Extrefsymoff", Field, 0}, + {"DysymtabCmd.Extreloff", Field, 0}, + {"DysymtabCmd.Iextdefsym", Field, 0}, + {"DysymtabCmd.Ilocalsym", Field, 0}, + {"DysymtabCmd.Indirectsymoff", Field, 0}, + {"DysymtabCmd.Iundefsym", Field, 0}, + {"DysymtabCmd.Len", Field, 0}, + {"DysymtabCmd.Locreloff", Field, 0}, + {"DysymtabCmd.Modtaboff", Field, 0}, + {"DysymtabCmd.Nextdefsym", Field, 0}, + {"DysymtabCmd.Nextrefsyms", Field, 0}, + {"DysymtabCmd.Nextrel", Field, 0}, + {"DysymtabCmd.Nindirectsyms", Field, 0}, + {"DysymtabCmd.Nlocalsym", Field, 0}, + {"DysymtabCmd.Nlocrel", Field, 0}, + {"DysymtabCmd.Nmodtab", Field, 0}, + {"DysymtabCmd.Ntoc", Field, 0}, + {"DysymtabCmd.Nundefsym", Field, 0}, + {"DysymtabCmd.Tocoffset", Field, 0}, + {"ErrNotFat", Var, 3}, + {"FatArch", Type, 3}, + {"FatArch.FatArchHeader", Field, 3}, + {"FatArch.File", Field, 3}, + {"FatArchHeader", Type, 3}, + {"FatArchHeader.Align", Field, 3}, + {"FatArchHeader.Cpu", Field, 3}, + {"FatArchHeader.Offset", Field, 3}, + {"FatArchHeader.Size", Field, 3}, + {"FatArchHeader.SubCpu", Field, 3}, + {"FatFile", Type, 3}, + {"FatFile.Arches", Field, 3}, + {"FatFile.Magic", Field, 3}, + {"File", Type, 0}, + {"File.ByteOrder", Field, 0}, + {"File.Dysymtab", Field, 0}, + {"File.FileHeader", Field, 0}, + {"File.Loads", Field, 0}, + {"File.Sections", Field, 0}, + {"File.Symtab", Field, 0}, + {"FileHeader", Type, 0}, + {"FileHeader.Cmdsz", Field, 0}, + {"FileHeader.Cpu", Field, 0}, + {"FileHeader.Flags", Field, 0}, + {"FileHeader.Magic", Field, 0}, + {"FileHeader.Ncmd", Field, 0}, + {"FileHeader.SubCpu", Field, 0}, + {"FileHeader.Type", Field, 0}, + {"FlagAllModsBound", Const, 10}, + {"FlagAllowStackExecution", Const, 10}, + {"FlagAppExtensionSafe", Const, 10}, + {"FlagBindAtLoad", Const, 10}, + {"FlagBindsToWeak", Const, 10}, + {"FlagCanonical", Const, 10}, + {"FlagDeadStrippableDylib", Const, 10}, + {"FlagDyldLink", Const, 10}, + {"FlagForceFlat", Const, 10}, + {"FlagHasTLVDescriptors", Const, 10}, + {"FlagIncrLink", Const, 10}, + {"FlagLazyInit", Const, 10}, + {"FlagNoFixPrebinding", Const, 10}, + {"FlagNoHeapExecution", Const, 10}, + {"FlagNoMultiDefs", Const, 10}, + {"FlagNoReexportedDylibs", Const, 10}, + {"FlagNoUndefs", Const, 10}, + {"FlagPIE", Const, 10}, + {"FlagPrebindable", Const, 10}, + {"FlagPrebound", Const, 10}, + {"FlagRootSafe", Const, 10}, + {"FlagSetuidSafe", Const, 10}, + {"FlagSplitSegs", Const, 10}, + {"FlagSubsectionsViaSymbols", Const, 10}, + {"FlagTwoLevel", Const, 10}, + {"FlagWeakDefines", Const, 10}, + {"FormatError", Type, 0}, + {"GENERIC_RELOC_LOCAL_SECTDIFF", Const, 10}, + {"GENERIC_RELOC_PAIR", Const, 10}, + {"GENERIC_RELOC_PB_LA_PTR", Const, 10}, + {"GENERIC_RELOC_SECTDIFF", Const, 10}, + {"GENERIC_RELOC_TLV", Const, 10}, + {"GENERIC_RELOC_VANILLA", Const, 10}, + {"Load", Type, 0}, + {"LoadBytes", Type, 0}, + {"LoadCmd", Type, 0}, + {"LoadCmdDylib", Const, 0}, + {"LoadCmdDylinker", Const, 0}, + {"LoadCmdDysymtab", Const, 0}, + {"LoadCmdRpath", Const, 10}, + {"LoadCmdSegment", Const, 0}, + {"LoadCmdSegment64", Const, 0}, + {"LoadCmdSymtab", Const, 0}, + {"LoadCmdThread", Const, 0}, + {"LoadCmdUnixThread", Const, 0}, + {"Magic32", Const, 0}, + {"Magic64", Const, 0}, + {"MagicFat", Const, 3}, + {"NewFatFile", Func, 3}, + {"NewFile", Func, 0}, + {"Nlist32", Type, 0}, + {"Nlist32.Desc", Field, 0}, + {"Nlist32.Name", Field, 0}, + {"Nlist32.Sect", Field, 0}, + {"Nlist32.Type", Field, 0}, + {"Nlist32.Value", Field, 0}, + {"Nlist64", Type, 0}, + {"Nlist64.Desc", Field, 0}, + {"Nlist64.Name", Field, 0}, + {"Nlist64.Sect", Field, 0}, + {"Nlist64.Type", Field, 0}, + {"Nlist64.Value", Field, 0}, + {"Open", Func, 0}, + {"OpenFat", Func, 3}, + {"Regs386", Type, 0}, + {"Regs386.AX", Field, 0}, + {"Regs386.BP", Field, 0}, + {"Regs386.BX", Field, 0}, + {"Regs386.CS", Field, 0}, + {"Regs386.CX", Field, 0}, + {"Regs386.DI", Field, 0}, + {"Regs386.DS", Field, 0}, + {"Regs386.DX", Field, 0}, + {"Regs386.ES", Field, 0}, + {"Regs386.FLAGS", Field, 0}, + {"Regs386.FS", Field, 0}, + {"Regs386.GS", Field, 0}, + {"Regs386.IP", Field, 0}, + {"Regs386.SI", Field, 0}, + {"Regs386.SP", Field, 0}, + {"Regs386.SS", Field, 0}, + {"RegsAMD64", Type, 0}, + {"RegsAMD64.AX", Field, 0}, + {"RegsAMD64.BP", Field, 0}, + {"RegsAMD64.BX", Field, 0}, + {"RegsAMD64.CS", Field, 0}, + {"RegsAMD64.CX", Field, 0}, + {"RegsAMD64.DI", Field, 0}, + {"RegsAMD64.DX", Field, 0}, + {"RegsAMD64.FLAGS", Field, 0}, + {"RegsAMD64.FS", Field, 0}, + {"RegsAMD64.GS", Field, 0}, + {"RegsAMD64.IP", Field, 0}, + {"RegsAMD64.R10", Field, 0}, + {"RegsAMD64.R11", Field, 0}, + {"RegsAMD64.R12", Field, 0}, + {"RegsAMD64.R13", Field, 0}, + {"RegsAMD64.R14", Field, 0}, + {"RegsAMD64.R15", Field, 0}, + {"RegsAMD64.R8", Field, 0}, + {"RegsAMD64.R9", Field, 0}, + {"RegsAMD64.SI", Field, 0}, + {"RegsAMD64.SP", Field, 0}, + {"Reloc", Type, 10}, + {"Reloc.Addr", Field, 10}, + {"Reloc.Extern", Field, 10}, + {"Reloc.Len", Field, 10}, + {"Reloc.Pcrel", Field, 10}, + {"Reloc.Scattered", Field, 10}, + {"Reloc.Type", Field, 10}, + {"Reloc.Value", Field, 10}, + {"RelocTypeARM", Type, 10}, + {"RelocTypeARM64", Type, 10}, + {"RelocTypeGeneric", Type, 10}, + {"RelocTypeX86_64", Type, 10}, + {"Rpath", Type, 10}, + {"Rpath.LoadBytes", Field, 10}, + {"Rpath.Path", Field, 10}, + {"RpathCmd", Type, 10}, + {"RpathCmd.Cmd", Field, 10}, + {"RpathCmd.Len", Field, 10}, + {"RpathCmd.Path", Field, 10}, + {"Section", Type, 0}, + {"Section.ReaderAt", Field, 0}, + {"Section.Relocs", Field, 10}, + {"Section.SectionHeader", Field, 0}, + {"Section32", Type, 0}, + {"Section32.Addr", Field, 0}, + {"Section32.Align", Field, 0}, + {"Section32.Flags", Field, 0}, + {"Section32.Name", Field, 0}, + {"Section32.Nreloc", Field, 0}, + {"Section32.Offset", Field, 0}, + {"Section32.Reloff", Field, 0}, + {"Section32.Reserve1", Field, 0}, + {"Section32.Reserve2", Field, 0}, + {"Section32.Seg", Field, 0}, + {"Section32.Size", Field, 0}, + {"Section64", Type, 0}, + {"Section64.Addr", Field, 0}, + {"Section64.Align", Field, 0}, + {"Section64.Flags", Field, 0}, + {"Section64.Name", Field, 0}, + {"Section64.Nreloc", Field, 0}, + {"Section64.Offset", Field, 0}, + {"Section64.Reloff", Field, 0}, + {"Section64.Reserve1", Field, 0}, + {"Section64.Reserve2", Field, 0}, + {"Section64.Reserve3", Field, 0}, + {"Section64.Seg", Field, 0}, + {"Section64.Size", Field, 0}, + {"SectionHeader", Type, 0}, + {"SectionHeader.Addr", Field, 0}, + {"SectionHeader.Align", Field, 0}, + {"SectionHeader.Flags", Field, 0}, + {"SectionHeader.Name", Field, 0}, + {"SectionHeader.Nreloc", Field, 0}, + {"SectionHeader.Offset", Field, 0}, + {"SectionHeader.Reloff", Field, 0}, + {"SectionHeader.Seg", Field, 0}, + {"SectionHeader.Size", Field, 0}, + {"Segment", Type, 0}, + {"Segment.LoadBytes", Field, 0}, + {"Segment.ReaderAt", Field, 0}, + {"Segment.SegmentHeader", Field, 0}, + {"Segment32", Type, 0}, + {"Segment32.Addr", Field, 0}, + {"Segment32.Cmd", Field, 0}, + {"Segment32.Filesz", Field, 0}, + {"Segment32.Flag", Field, 0}, + {"Segment32.Len", Field, 0}, + {"Segment32.Maxprot", Field, 0}, + {"Segment32.Memsz", Field, 0}, + {"Segment32.Name", Field, 0}, + {"Segment32.Nsect", Field, 0}, + {"Segment32.Offset", Field, 0}, + {"Segment32.Prot", Field, 0}, + {"Segment64", Type, 0}, + {"Segment64.Addr", Field, 0}, + {"Segment64.Cmd", Field, 0}, + {"Segment64.Filesz", Field, 0}, + {"Segment64.Flag", Field, 0}, + {"Segment64.Len", Field, 0}, + {"Segment64.Maxprot", Field, 0}, + {"Segment64.Memsz", Field, 0}, + {"Segment64.Name", Field, 0}, + {"Segment64.Nsect", Field, 0}, + {"Segment64.Offset", Field, 0}, + {"Segment64.Prot", Field, 0}, + {"SegmentHeader", Type, 0}, + {"SegmentHeader.Addr", Field, 0}, + {"SegmentHeader.Cmd", Field, 0}, + {"SegmentHeader.Filesz", Field, 0}, + {"SegmentHeader.Flag", Field, 0}, + {"SegmentHeader.Len", Field, 0}, + {"SegmentHeader.Maxprot", Field, 0}, + {"SegmentHeader.Memsz", Field, 0}, + {"SegmentHeader.Name", Field, 0}, + {"SegmentHeader.Nsect", Field, 0}, + {"SegmentHeader.Offset", Field, 0}, + {"SegmentHeader.Prot", Field, 0}, + {"Symbol", Type, 0}, + {"Symbol.Desc", Field, 0}, + {"Symbol.Name", Field, 0}, + {"Symbol.Sect", Field, 0}, + {"Symbol.Type", Field, 0}, + {"Symbol.Value", Field, 0}, + {"Symtab", Type, 0}, + {"Symtab.LoadBytes", Field, 0}, + {"Symtab.Syms", Field, 0}, + {"Symtab.SymtabCmd", Field, 0}, + {"SymtabCmd", Type, 0}, + {"SymtabCmd.Cmd", Field, 0}, + {"SymtabCmd.Len", Field, 0}, + {"SymtabCmd.Nsyms", Field, 0}, + {"SymtabCmd.Stroff", Field, 0}, + {"SymtabCmd.Strsize", Field, 0}, + {"SymtabCmd.Symoff", Field, 0}, + {"Thread", Type, 0}, + {"Thread.Cmd", Field, 0}, + {"Thread.Data", Field, 0}, + {"Thread.Len", Field, 0}, + {"Thread.Type", Field, 0}, + {"Type", Type, 0}, + {"TypeBundle", Const, 3}, + {"TypeDylib", Const, 3}, + {"TypeExec", Const, 0}, + {"TypeObj", Const, 0}, + {"X86_64_RELOC_BRANCH", Const, 10}, + {"X86_64_RELOC_GOT", Const, 10}, + {"X86_64_RELOC_GOT_LOAD", Const, 10}, + {"X86_64_RELOC_SIGNED", Const, 10}, + {"X86_64_RELOC_SIGNED_1", Const, 10}, + {"X86_64_RELOC_SIGNED_2", Const, 10}, + {"X86_64_RELOC_SIGNED_4", Const, 10}, + {"X86_64_RELOC_SUBTRACTOR", Const, 10}, + {"X86_64_RELOC_TLV", Const, 10}, + {"X86_64_RELOC_UNSIGNED", Const, 10}, + }, + "debug/pe": { + {"(*COFFSymbol).FullName", Method, 8}, + {"(*File).COFFSymbolReadSectionDefAux", Method, 19}, + {"(*File).Close", Method, 0}, + {"(*File).DWARF", Method, 0}, + {"(*File).ImportedLibraries", Method, 0}, + {"(*File).ImportedSymbols", Method, 0}, + {"(*File).Section", Method, 0}, + {"(*FormatError).Error", Method, 0}, + {"(*Section).Data", Method, 0}, + {"(*Section).Open", Method, 0}, + {"(Section).ReadAt", Method, 0}, + {"(StringTable).String", Method, 8}, + {"COFFSymbol", Type, 1}, + {"COFFSymbol.Name", Field, 1}, + {"COFFSymbol.NumberOfAuxSymbols", Field, 1}, + {"COFFSymbol.SectionNumber", Field, 1}, + {"COFFSymbol.StorageClass", Field, 1}, + {"COFFSymbol.Type", Field, 1}, + {"COFFSymbol.Value", Field, 1}, + {"COFFSymbolAuxFormat5", Type, 19}, + {"COFFSymbolAuxFormat5.Checksum", Field, 19}, + {"COFFSymbolAuxFormat5.NumLineNumbers", Field, 19}, + {"COFFSymbolAuxFormat5.NumRelocs", Field, 19}, + {"COFFSymbolAuxFormat5.SecNum", Field, 19}, + {"COFFSymbolAuxFormat5.Selection", Field, 19}, + {"COFFSymbolAuxFormat5.Size", Field, 19}, + {"COFFSymbolSize", Const, 1}, + {"DataDirectory", Type, 3}, + {"DataDirectory.Size", Field, 3}, + {"DataDirectory.VirtualAddress", Field, 3}, + {"File", Type, 0}, + {"File.COFFSymbols", Field, 8}, + {"File.FileHeader", Field, 0}, + {"File.OptionalHeader", Field, 3}, + {"File.Sections", Field, 0}, + {"File.StringTable", Field, 8}, + {"File.Symbols", Field, 1}, + {"FileHeader", Type, 0}, + {"FileHeader.Characteristics", Field, 0}, + {"FileHeader.Machine", Field, 0}, + {"FileHeader.NumberOfSections", Field, 0}, + {"FileHeader.NumberOfSymbols", Field, 0}, + {"FileHeader.PointerToSymbolTable", Field, 0}, + {"FileHeader.SizeOfOptionalHeader", Field, 0}, + {"FileHeader.TimeDateStamp", Field, 0}, + {"FormatError", Type, 0}, + {"IMAGE_COMDAT_SELECT_ANY", Const, 19}, + {"IMAGE_COMDAT_SELECT_ASSOCIATIVE", Const, 19}, + {"IMAGE_COMDAT_SELECT_EXACT_MATCH", Const, 19}, + {"IMAGE_COMDAT_SELECT_LARGEST", Const, 19}, + {"IMAGE_COMDAT_SELECT_NODUPLICATES", Const, 19}, + {"IMAGE_COMDAT_SELECT_SAME_SIZE", Const, 19}, + {"IMAGE_DIRECTORY_ENTRY_ARCHITECTURE", Const, 11}, + {"IMAGE_DIRECTORY_ENTRY_BASERELOC", Const, 11}, + {"IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT", Const, 11}, + {"IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR", Const, 11}, + {"IMAGE_DIRECTORY_ENTRY_DEBUG", Const, 11}, + {"IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT", Const, 11}, + {"IMAGE_DIRECTORY_ENTRY_EXCEPTION", Const, 11}, + {"IMAGE_DIRECTORY_ENTRY_EXPORT", Const, 11}, + {"IMAGE_DIRECTORY_ENTRY_GLOBALPTR", Const, 11}, + {"IMAGE_DIRECTORY_ENTRY_IAT", Const, 11}, + {"IMAGE_DIRECTORY_ENTRY_IMPORT", Const, 11}, + {"IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG", Const, 11}, + {"IMAGE_DIRECTORY_ENTRY_RESOURCE", Const, 11}, + {"IMAGE_DIRECTORY_ENTRY_SECURITY", Const, 11}, + {"IMAGE_DIRECTORY_ENTRY_TLS", Const, 11}, + {"IMAGE_DLLCHARACTERISTICS_APPCONTAINER", Const, 15}, + {"IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE", Const, 15}, + {"IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY", Const, 15}, + {"IMAGE_DLLCHARACTERISTICS_GUARD_CF", Const, 15}, + {"IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA", Const, 15}, + {"IMAGE_DLLCHARACTERISTICS_NO_BIND", Const, 15}, + {"IMAGE_DLLCHARACTERISTICS_NO_ISOLATION", Const, 15}, + {"IMAGE_DLLCHARACTERISTICS_NO_SEH", Const, 15}, + {"IMAGE_DLLCHARACTERISTICS_NX_COMPAT", Const, 15}, + {"IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE", Const, 15}, + {"IMAGE_DLLCHARACTERISTICS_WDM_DRIVER", Const, 15}, + {"IMAGE_FILE_32BIT_MACHINE", Const, 15}, + {"IMAGE_FILE_AGGRESIVE_WS_TRIM", Const, 15}, + {"IMAGE_FILE_BYTES_REVERSED_HI", Const, 15}, + {"IMAGE_FILE_BYTES_REVERSED_LO", Const, 15}, + {"IMAGE_FILE_DEBUG_STRIPPED", Const, 15}, + {"IMAGE_FILE_DLL", Const, 15}, + {"IMAGE_FILE_EXECUTABLE_IMAGE", Const, 15}, + {"IMAGE_FILE_LARGE_ADDRESS_AWARE", Const, 15}, + {"IMAGE_FILE_LINE_NUMS_STRIPPED", Const, 15}, + {"IMAGE_FILE_LOCAL_SYMS_STRIPPED", Const, 15}, + {"IMAGE_FILE_MACHINE_AM33", Const, 0}, + {"IMAGE_FILE_MACHINE_AMD64", Const, 0}, + {"IMAGE_FILE_MACHINE_ARM", Const, 0}, + {"IMAGE_FILE_MACHINE_ARM64", Const, 11}, + {"IMAGE_FILE_MACHINE_ARMNT", Const, 12}, + {"IMAGE_FILE_MACHINE_EBC", Const, 0}, + {"IMAGE_FILE_MACHINE_I386", Const, 0}, + {"IMAGE_FILE_MACHINE_IA64", Const, 0}, + {"IMAGE_FILE_MACHINE_LOONGARCH32", Const, 19}, + {"IMAGE_FILE_MACHINE_LOONGARCH64", Const, 19}, + {"IMAGE_FILE_MACHINE_M32R", Const, 0}, + {"IMAGE_FILE_MACHINE_MIPS16", Const, 0}, + {"IMAGE_FILE_MACHINE_MIPSFPU", Const, 0}, + {"IMAGE_FILE_MACHINE_MIPSFPU16", Const, 0}, + {"IMAGE_FILE_MACHINE_POWERPC", Const, 0}, + {"IMAGE_FILE_MACHINE_POWERPCFP", Const, 0}, + {"IMAGE_FILE_MACHINE_R4000", Const, 0}, + {"IMAGE_FILE_MACHINE_RISCV128", Const, 20}, + {"IMAGE_FILE_MACHINE_RISCV32", Const, 20}, + {"IMAGE_FILE_MACHINE_RISCV64", Const, 20}, + {"IMAGE_FILE_MACHINE_SH3", Const, 0}, + {"IMAGE_FILE_MACHINE_SH3DSP", Const, 0}, + {"IMAGE_FILE_MACHINE_SH4", Const, 0}, + {"IMAGE_FILE_MACHINE_SH5", Const, 0}, + {"IMAGE_FILE_MACHINE_THUMB", Const, 0}, + {"IMAGE_FILE_MACHINE_UNKNOWN", Const, 0}, + {"IMAGE_FILE_MACHINE_WCEMIPSV2", Const, 0}, + {"IMAGE_FILE_NET_RUN_FROM_SWAP", Const, 15}, + {"IMAGE_FILE_RELOCS_STRIPPED", Const, 15}, + {"IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP", Const, 15}, + {"IMAGE_FILE_SYSTEM", Const, 15}, + {"IMAGE_FILE_UP_SYSTEM_ONLY", Const, 15}, + {"IMAGE_SCN_CNT_CODE", Const, 19}, + {"IMAGE_SCN_CNT_INITIALIZED_DATA", Const, 19}, + {"IMAGE_SCN_CNT_UNINITIALIZED_DATA", Const, 19}, + {"IMAGE_SCN_LNK_COMDAT", Const, 19}, + {"IMAGE_SCN_MEM_DISCARDABLE", Const, 19}, + {"IMAGE_SCN_MEM_EXECUTE", Const, 19}, + {"IMAGE_SCN_MEM_READ", Const, 19}, + {"IMAGE_SCN_MEM_WRITE", Const, 19}, + {"IMAGE_SUBSYSTEM_EFI_APPLICATION", Const, 15}, + {"IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER", Const, 15}, + {"IMAGE_SUBSYSTEM_EFI_ROM", Const, 15}, + {"IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER", Const, 15}, + {"IMAGE_SUBSYSTEM_NATIVE", Const, 15}, + {"IMAGE_SUBSYSTEM_NATIVE_WINDOWS", Const, 15}, + {"IMAGE_SUBSYSTEM_OS2_CUI", Const, 15}, + {"IMAGE_SUBSYSTEM_POSIX_CUI", Const, 15}, + {"IMAGE_SUBSYSTEM_UNKNOWN", Const, 15}, + {"IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION", Const, 15}, + {"IMAGE_SUBSYSTEM_WINDOWS_CE_GUI", Const, 15}, + {"IMAGE_SUBSYSTEM_WINDOWS_CUI", Const, 15}, + {"IMAGE_SUBSYSTEM_WINDOWS_GUI", Const, 15}, + {"IMAGE_SUBSYSTEM_XBOX", Const, 15}, + {"ImportDirectory", Type, 0}, + {"ImportDirectory.FirstThunk", Field, 0}, + {"ImportDirectory.ForwarderChain", Field, 0}, + {"ImportDirectory.Name", Field, 0}, + {"ImportDirectory.OriginalFirstThunk", Field, 0}, + {"ImportDirectory.TimeDateStamp", Field, 0}, + {"NewFile", Func, 0}, + {"Open", Func, 0}, + {"OptionalHeader32", Type, 3}, + {"OptionalHeader32.AddressOfEntryPoint", Field, 3}, + {"OptionalHeader32.BaseOfCode", Field, 3}, + {"OptionalHeader32.BaseOfData", Field, 3}, + {"OptionalHeader32.CheckSum", Field, 3}, + {"OptionalHeader32.DataDirectory", Field, 3}, + {"OptionalHeader32.DllCharacteristics", Field, 3}, + {"OptionalHeader32.FileAlignment", Field, 3}, + {"OptionalHeader32.ImageBase", Field, 3}, + {"OptionalHeader32.LoaderFlags", Field, 3}, + {"OptionalHeader32.Magic", Field, 3}, + {"OptionalHeader32.MajorImageVersion", Field, 3}, + {"OptionalHeader32.MajorLinkerVersion", Field, 3}, + {"OptionalHeader32.MajorOperatingSystemVersion", Field, 3}, + {"OptionalHeader32.MajorSubsystemVersion", Field, 3}, + {"OptionalHeader32.MinorImageVersion", Field, 3}, + {"OptionalHeader32.MinorLinkerVersion", Field, 3}, + {"OptionalHeader32.MinorOperatingSystemVersion", Field, 3}, + {"OptionalHeader32.MinorSubsystemVersion", Field, 3}, + {"OptionalHeader32.NumberOfRvaAndSizes", Field, 3}, + {"OptionalHeader32.SectionAlignment", Field, 3}, + {"OptionalHeader32.SizeOfCode", Field, 3}, + {"OptionalHeader32.SizeOfHeaders", Field, 3}, + {"OptionalHeader32.SizeOfHeapCommit", Field, 3}, + {"OptionalHeader32.SizeOfHeapReserve", Field, 3}, + {"OptionalHeader32.SizeOfImage", Field, 3}, + {"OptionalHeader32.SizeOfInitializedData", Field, 3}, + {"OptionalHeader32.SizeOfStackCommit", Field, 3}, + {"OptionalHeader32.SizeOfStackReserve", Field, 3}, + {"OptionalHeader32.SizeOfUninitializedData", Field, 3}, + {"OptionalHeader32.Subsystem", Field, 3}, + {"OptionalHeader32.Win32VersionValue", Field, 3}, + {"OptionalHeader64", Type, 3}, + {"OptionalHeader64.AddressOfEntryPoint", Field, 3}, + {"OptionalHeader64.BaseOfCode", Field, 3}, + {"OptionalHeader64.CheckSum", Field, 3}, + {"OptionalHeader64.DataDirectory", Field, 3}, + {"OptionalHeader64.DllCharacteristics", Field, 3}, + {"OptionalHeader64.FileAlignment", Field, 3}, + {"OptionalHeader64.ImageBase", Field, 3}, + {"OptionalHeader64.LoaderFlags", Field, 3}, + {"OptionalHeader64.Magic", Field, 3}, + {"OptionalHeader64.MajorImageVersion", Field, 3}, + {"OptionalHeader64.MajorLinkerVersion", Field, 3}, + {"OptionalHeader64.MajorOperatingSystemVersion", Field, 3}, + {"OptionalHeader64.MajorSubsystemVersion", Field, 3}, + {"OptionalHeader64.MinorImageVersion", Field, 3}, + {"OptionalHeader64.MinorLinkerVersion", Field, 3}, + {"OptionalHeader64.MinorOperatingSystemVersion", Field, 3}, + {"OptionalHeader64.MinorSubsystemVersion", Field, 3}, + {"OptionalHeader64.NumberOfRvaAndSizes", Field, 3}, + {"OptionalHeader64.SectionAlignment", Field, 3}, + {"OptionalHeader64.SizeOfCode", Field, 3}, + {"OptionalHeader64.SizeOfHeaders", Field, 3}, + {"OptionalHeader64.SizeOfHeapCommit", Field, 3}, + {"OptionalHeader64.SizeOfHeapReserve", Field, 3}, + {"OptionalHeader64.SizeOfImage", Field, 3}, + {"OptionalHeader64.SizeOfInitializedData", Field, 3}, + {"OptionalHeader64.SizeOfStackCommit", Field, 3}, + {"OptionalHeader64.SizeOfStackReserve", Field, 3}, + {"OptionalHeader64.SizeOfUninitializedData", Field, 3}, + {"OptionalHeader64.Subsystem", Field, 3}, + {"OptionalHeader64.Win32VersionValue", Field, 3}, + {"Reloc", Type, 8}, + {"Reloc.SymbolTableIndex", Field, 8}, + {"Reloc.Type", Field, 8}, + {"Reloc.VirtualAddress", Field, 8}, + {"Section", Type, 0}, + {"Section.ReaderAt", Field, 0}, + {"Section.Relocs", Field, 8}, + {"Section.SectionHeader", Field, 0}, + {"SectionHeader", Type, 0}, + {"SectionHeader.Characteristics", Field, 0}, + {"SectionHeader.Name", Field, 0}, + {"SectionHeader.NumberOfLineNumbers", Field, 0}, + {"SectionHeader.NumberOfRelocations", Field, 0}, + {"SectionHeader.Offset", Field, 0}, + {"SectionHeader.PointerToLineNumbers", Field, 0}, + {"SectionHeader.PointerToRelocations", Field, 0}, + {"SectionHeader.Size", Field, 0}, + {"SectionHeader.VirtualAddress", Field, 0}, + {"SectionHeader.VirtualSize", Field, 0}, + {"SectionHeader32", Type, 0}, + {"SectionHeader32.Characteristics", Field, 0}, + {"SectionHeader32.Name", Field, 0}, + {"SectionHeader32.NumberOfLineNumbers", Field, 0}, + {"SectionHeader32.NumberOfRelocations", Field, 0}, + {"SectionHeader32.PointerToLineNumbers", Field, 0}, + {"SectionHeader32.PointerToRawData", Field, 0}, + {"SectionHeader32.PointerToRelocations", Field, 0}, + {"SectionHeader32.SizeOfRawData", Field, 0}, + {"SectionHeader32.VirtualAddress", Field, 0}, + {"SectionHeader32.VirtualSize", Field, 0}, + {"StringTable", Type, 8}, + {"Symbol", Type, 1}, + {"Symbol.Name", Field, 1}, + {"Symbol.SectionNumber", Field, 1}, + {"Symbol.StorageClass", Field, 1}, + {"Symbol.Type", Field, 1}, + {"Symbol.Value", Field, 1}, + }, + "debug/plan9obj": { + {"(*File).Close", Method, 3}, + {"(*File).Section", Method, 3}, + {"(*File).Symbols", Method, 3}, + {"(*Section).Data", Method, 3}, + {"(*Section).Open", Method, 3}, + {"(Section).ReadAt", Method, 3}, + {"ErrNoSymbols", Var, 18}, + {"File", Type, 3}, + {"File.FileHeader", Field, 3}, + {"File.Sections", Field, 3}, + {"FileHeader", Type, 3}, + {"FileHeader.Bss", Field, 3}, + {"FileHeader.Entry", Field, 3}, + {"FileHeader.HdrSize", Field, 4}, + {"FileHeader.LoadAddress", Field, 4}, + {"FileHeader.Magic", Field, 3}, + {"FileHeader.PtrSize", Field, 3}, + {"Magic386", Const, 3}, + {"Magic64", Const, 3}, + {"MagicAMD64", Const, 3}, + {"MagicARM", Const, 3}, + {"NewFile", Func, 3}, + {"Open", Func, 3}, + {"Section", Type, 3}, + {"Section.ReaderAt", Field, 3}, + {"Section.SectionHeader", Field, 3}, + {"SectionHeader", Type, 3}, + {"SectionHeader.Name", Field, 3}, + {"SectionHeader.Offset", Field, 3}, + {"SectionHeader.Size", Field, 3}, + {"Sym", Type, 3}, + {"Sym.Name", Field, 3}, + {"Sym.Type", Field, 3}, + {"Sym.Value", Field, 3}, + }, + "embed": { + {"(FS).Open", Method, 16}, + {"(FS).ReadDir", Method, 16}, + {"(FS).ReadFile", Method, 16}, + {"FS", Type, 16}, + }, + "encoding": { + {"BinaryMarshaler", Type, 2}, + {"BinaryUnmarshaler", Type, 2}, + {"TextMarshaler", Type, 2}, + {"TextUnmarshaler", Type, 2}, + }, + "encoding/ascii85": { + {"(CorruptInputError).Error", Method, 0}, + {"CorruptInputError", Type, 0}, + {"Decode", Func, 0}, + {"Encode", Func, 0}, + {"MaxEncodedLen", Func, 0}, + {"NewDecoder", Func, 0}, + {"NewEncoder", Func, 0}, + }, + "encoding/asn1": { + {"(BitString).At", Method, 0}, + {"(BitString).RightAlign", Method, 0}, + {"(ObjectIdentifier).Equal", Method, 0}, + {"(ObjectIdentifier).String", Method, 3}, + {"(StructuralError).Error", Method, 0}, + {"(SyntaxError).Error", Method, 0}, + {"BitString", Type, 0}, + {"BitString.BitLength", Field, 0}, + {"BitString.Bytes", Field, 0}, + {"ClassApplication", Const, 6}, + {"ClassContextSpecific", Const, 6}, + {"ClassPrivate", Const, 6}, + {"ClassUniversal", Const, 6}, + {"Enumerated", Type, 0}, + {"Flag", Type, 0}, + {"Marshal", Func, 0}, + {"MarshalWithParams", Func, 10}, + {"NullBytes", Var, 9}, + {"NullRawValue", Var, 9}, + {"ObjectIdentifier", Type, 0}, + {"RawContent", Type, 0}, + {"RawValue", Type, 0}, + {"RawValue.Bytes", Field, 0}, + {"RawValue.Class", Field, 0}, + {"RawValue.FullBytes", Field, 0}, + {"RawValue.IsCompound", Field, 0}, + {"RawValue.Tag", Field, 0}, + {"StructuralError", Type, 0}, + {"StructuralError.Msg", Field, 0}, + {"SyntaxError", Type, 0}, + {"SyntaxError.Msg", Field, 0}, + {"TagBMPString", Const, 14}, + {"TagBitString", Const, 6}, + {"TagBoolean", Const, 6}, + {"TagEnum", Const, 6}, + {"TagGeneralString", Const, 6}, + {"TagGeneralizedTime", Const, 6}, + {"TagIA5String", Const, 6}, + {"TagInteger", Const, 6}, + {"TagNull", Const, 9}, + {"TagNumericString", Const, 10}, + {"TagOID", Const, 6}, + {"TagOctetString", Const, 6}, + {"TagPrintableString", Const, 6}, + {"TagSequence", Const, 6}, + {"TagSet", Const, 6}, + {"TagT61String", Const, 6}, + {"TagUTCTime", Const, 6}, + {"TagUTF8String", Const, 6}, + {"Unmarshal", Func, 0}, + {"UnmarshalWithParams", Func, 0}, + }, + "encoding/base32": { + {"(*Encoding).AppendDecode", Method, 22}, + {"(*Encoding).AppendEncode", Method, 22}, + {"(*Encoding).Decode", Method, 0}, + {"(*Encoding).DecodeString", Method, 0}, + {"(*Encoding).DecodedLen", Method, 0}, + {"(*Encoding).Encode", Method, 0}, + {"(*Encoding).EncodeToString", Method, 0}, + {"(*Encoding).EncodedLen", Method, 0}, + {"(CorruptInputError).Error", Method, 0}, + {"(Encoding).WithPadding", Method, 9}, + {"CorruptInputError", Type, 0}, + {"Encoding", Type, 0}, + {"HexEncoding", Var, 0}, + {"NewDecoder", Func, 0}, + {"NewEncoder", Func, 0}, + {"NewEncoding", Func, 0}, + {"NoPadding", Const, 9}, + {"StdEncoding", Var, 0}, + {"StdPadding", Const, 9}, + }, + "encoding/base64": { + {"(*Encoding).AppendDecode", Method, 22}, + {"(*Encoding).AppendEncode", Method, 22}, + {"(*Encoding).Decode", Method, 0}, + {"(*Encoding).DecodeString", Method, 0}, + {"(*Encoding).DecodedLen", Method, 0}, + {"(*Encoding).Encode", Method, 0}, + {"(*Encoding).EncodeToString", Method, 0}, + {"(*Encoding).EncodedLen", Method, 0}, + {"(CorruptInputError).Error", Method, 0}, + {"(Encoding).Strict", Method, 8}, + {"(Encoding).WithPadding", Method, 5}, + {"CorruptInputError", Type, 0}, + {"Encoding", Type, 0}, + {"NewDecoder", Func, 0}, + {"NewEncoder", Func, 0}, + {"NewEncoding", Func, 0}, + {"NoPadding", Const, 5}, + {"RawStdEncoding", Var, 5}, + {"RawURLEncoding", Var, 5}, + {"StdEncoding", Var, 0}, + {"StdPadding", Const, 5}, + {"URLEncoding", Var, 0}, + }, + "encoding/binary": { + {"AppendByteOrder", Type, 19}, + {"AppendUvarint", Func, 19}, + {"AppendVarint", Func, 19}, + {"BigEndian", Var, 0}, + {"ByteOrder", Type, 0}, + {"LittleEndian", Var, 0}, + {"MaxVarintLen16", Const, 0}, + {"MaxVarintLen32", Const, 0}, + {"MaxVarintLen64", Const, 0}, + {"NativeEndian", Var, 21}, + {"PutUvarint", Func, 0}, + {"PutVarint", Func, 0}, + {"Read", Func, 0}, + {"ReadUvarint", Func, 0}, + {"ReadVarint", Func, 0}, + {"Size", Func, 0}, + {"Uvarint", Func, 0}, + {"Varint", Func, 0}, + {"Write", Func, 0}, + }, + "encoding/csv": { + {"(*ParseError).Error", Method, 0}, + {"(*ParseError).Unwrap", Method, 13}, + {"(*Reader).FieldPos", Method, 17}, + {"(*Reader).InputOffset", Method, 19}, + {"(*Reader).Read", Method, 0}, + {"(*Reader).ReadAll", Method, 0}, + {"(*Writer).Error", Method, 1}, + {"(*Writer).Flush", Method, 0}, + {"(*Writer).Write", Method, 0}, + {"(*Writer).WriteAll", Method, 0}, + {"ErrBareQuote", Var, 0}, + {"ErrFieldCount", Var, 0}, + {"ErrQuote", Var, 0}, + {"ErrTrailingComma", Var, 0}, + {"NewReader", Func, 0}, + {"NewWriter", Func, 0}, + {"ParseError", Type, 0}, + {"ParseError.Column", Field, 0}, + {"ParseError.Err", Field, 0}, + {"ParseError.Line", Field, 0}, + {"ParseError.StartLine", Field, 10}, + {"Reader", Type, 0}, + {"Reader.Comma", Field, 0}, + {"Reader.Comment", Field, 0}, + {"Reader.FieldsPerRecord", Field, 0}, + {"Reader.LazyQuotes", Field, 0}, + {"Reader.ReuseRecord", Field, 9}, + {"Reader.TrailingComma", Field, 0}, + {"Reader.TrimLeadingSpace", Field, 0}, + {"Writer", Type, 0}, + {"Writer.Comma", Field, 0}, + {"Writer.UseCRLF", Field, 0}, + }, + "encoding/gob": { + {"(*Decoder).Decode", Method, 0}, + {"(*Decoder).DecodeValue", Method, 0}, + {"(*Encoder).Encode", Method, 0}, + {"(*Encoder).EncodeValue", Method, 0}, + {"CommonType", Type, 0}, + {"CommonType.Id", Field, 0}, + {"CommonType.Name", Field, 0}, + {"Decoder", Type, 0}, + {"Encoder", Type, 0}, + {"GobDecoder", Type, 0}, + {"GobEncoder", Type, 0}, + {"NewDecoder", Func, 0}, + {"NewEncoder", Func, 0}, + {"Register", Func, 0}, + {"RegisterName", Func, 0}, + }, + "encoding/hex": { + {"(InvalidByteError).Error", Method, 0}, + {"AppendDecode", Func, 22}, + {"AppendEncode", Func, 22}, + {"Decode", Func, 0}, + {"DecodeString", Func, 0}, + {"DecodedLen", Func, 0}, + {"Dump", Func, 0}, + {"Dumper", Func, 0}, + {"Encode", Func, 0}, + {"EncodeToString", Func, 0}, + {"EncodedLen", Func, 0}, + {"ErrLength", Var, 0}, + {"InvalidByteError", Type, 0}, + {"NewDecoder", Func, 10}, + {"NewEncoder", Func, 10}, + }, + "encoding/json": { + {"(*Decoder).Buffered", Method, 1}, + {"(*Decoder).Decode", Method, 0}, + {"(*Decoder).DisallowUnknownFields", Method, 10}, + {"(*Decoder).InputOffset", Method, 14}, + {"(*Decoder).More", Method, 5}, + {"(*Decoder).Token", Method, 5}, + {"(*Decoder).UseNumber", Method, 1}, + {"(*Encoder).Encode", Method, 0}, + {"(*Encoder).SetEscapeHTML", Method, 7}, + {"(*Encoder).SetIndent", Method, 7}, + {"(*InvalidUTF8Error).Error", Method, 0}, + {"(*InvalidUnmarshalError).Error", Method, 0}, + {"(*MarshalerError).Error", Method, 0}, + {"(*MarshalerError).Unwrap", Method, 13}, + {"(*RawMessage).MarshalJSON", Method, 0}, + {"(*RawMessage).UnmarshalJSON", Method, 0}, + {"(*SyntaxError).Error", Method, 0}, + {"(*UnmarshalFieldError).Error", Method, 0}, + {"(*UnmarshalTypeError).Error", Method, 0}, + {"(*UnsupportedTypeError).Error", Method, 0}, + {"(*UnsupportedValueError).Error", Method, 0}, + {"(Delim).String", Method, 5}, + {"(Number).Float64", Method, 1}, + {"(Number).Int64", Method, 1}, + {"(Number).String", Method, 1}, + {"(RawMessage).MarshalJSON", Method, 8}, + {"Compact", Func, 0}, + {"Decoder", Type, 0}, + {"Delim", Type, 5}, + {"Encoder", Type, 0}, + {"HTMLEscape", Func, 0}, + {"Indent", Func, 0}, + {"InvalidUTF8Error", Type, 0}, + {"InvalidUTF8Error.S", Field, 0}, + {"InvalidUnmarshalError", Type, 0}, + {"InvalidUnmarshalError.Type", Field, 0}, + {"Marshal", Func, 0}, + {"MarshalIndent", Func, 0}, + {"Marshaler", Type, 0}, + {"MarshalerError", Type, 0}, + {"MarshalerError.Err", Field, 0}, + {"MarshalerError.Type", Field, 0}, + {"NewDecoder", Func, 0}, + {"NewEncoder", Func, 0}, + {"Number", Type, 1}, + {"RawMessage", Type, 0}, + {"SyntaxError", Type, 0}, + {"SyntaxError.Offset", Field, 0}, + {"Token", Type, 5}, + {"Unmarshal", Func, 0}, + {"UnmarshalFieldError", Type, 0}, + {"UnmarshalFieldError.Field", Field, 0}, + {"UnmarshalFieldError.Key", Field, 0}, + {"UnmarshalFieldError.Type", Field, 0}, + {"UnmarshalTypeError", Type, 0}, + {"UnmarshalTypeError.Field", Field, 8}, + {"UnmarshalTypeError.Offset", Field, 5}, + {"UnmarshalTypeError.Struct", Field, 8}, + {"UnmarshalTypeError.Type", Field, 0}, + {"UnmarshalTypeError.Value", Field, 0}, + {"Unmarshaler", Type, 0}, + {"UnsupportedTypeError", Type, 0}, + {"UnsupportedTypeError.Type", Field, 0}, + {"UnsupportedValueError", Type, 0}, + {"UnsupportedValueError.Str", Field, 0}, + {"UnsupportedValueError.Value", Field, 0}, + {"Valid", Func, 9}, + }, + "encoding/pem": { + {"Block", Type, 0}, + {"Block.Bytes", Field, 0}, + {"Block.Headers", Field, 0}, + {"Block.Type", Field, 0}, + {"Decode", Func, 0}, + {"Encode", Func, 0}, + {"EncodeToMemory", Func, 0}, + }, + "encoding/xml": { + {"(*Decoder).Decode", Method, 0}, + {"(*Decoder).DecodeElement", Method, 0}, + {"(*Decoder).InputOffset", Method, 4}, + {"(*Decoder).InputPos", Method, 19}, + {"(*Decoder).RawToken", Method, 0}, + {"(*Decoder).Skip", Method, 0}, + {"(*Decoder).Token", Method, 0}, + {"(*Encoder).Close", Method, 20}, + {"(*Encoder).Encode", Method, 0}, + {"(*Encoder).EncodeElement", Method, 2}, + {"(*Encoder).EncodeToken", Method, 2}, + {"(*Encoder).Flush", Method, 2}, + {"(*Encoder).Indent", Method, 1}, + {"(*SyntaxError).Error", Method, 0}, + {"(*TagPathError).Error", Method, 0}, + {"(*UnsupportedTypeError).Error", Method, 0}, + {"(CharData).Copy", Method, 0}, + {"(Comment).Copy", Method, 0}, + {"(Directive).Copy", Method, 0}, + {"(ProcInst).Copy", Method, 0}, + {"(StartElement).Copy", Method, 0}, + {"(StartElement).End", Method, 2}, + {"(UnmarshalError).Error", Method, 0}, + {"Attr", Type, 0}, + {"Attr.Name", Field, 0}, + {"Attr.Value", Field, 0}, + {"CharData", Type, 0}, + {"Comment", Type, 0}, + {"CopyToken", Func, 0}, + {"Decoder", Type, 0}, + {"Decoder.AutoClose", Field, 0}, + {"Decoder.CharsetReader", Field, 0}, + {"Decoder.DefaultSpace", Field, 1}, + {"Decoder.Entity", Field, 0}, + {"Decoder.Strict", Field, 0}, + {"Directive", Type, 0}, + {"Encoder", Type, 0}, + {"EndElement", Type, 0}, + {"EndElement.Name", Field, 0}, + {"Escape", Func, 0}, + {"EscapeText", Func, 1}, + {"HTMLAutoClose", Var, 0}, + {"HTMLEntity", Var, 0}, + {"Header", Const, 0}, + {"Marshal", Func, 0}, + {"MarshalIndent", Func, 0}, + {"Marshaler", Type, 2}, + {"MarshalerAttr", Type, 2}, + {"Name", Type, 0}, + {"Name.Local", Field, 0}, + {"Name.Space", Field, 0}, + {"NewDecoder", Func, 0}, + {"NewEncoder", Func, 0}, + {"NewTokenDecoder", Func, 10}, + {"ProcInst", Type, 0}, + {"ProcInst.Inst", Field, 0}, + {"ProcInst.Target", Field, 0}, + {"StartElement", Type, 0}, + {"StartElement.Attr", Field, 0}, + {"StartElement.Name", Field, 0}, + {"SyntaxError", Type, 0}, + {"SyntaxError.Line", Field, 0}, + {"SyntaxError.Msg", Field, 0}, + {"TagPathError", Type, 0}, + {"TagPathError.Field1", Field, 0}, + {"TagPathError.Field2", Field, 0}, + {"TagPathError.Struct", Field, 0}, + {"TagPathError.Tag1", Field, 0}, + {"TagPathError.Tag2", Field, 0}, + {"Token", Type, 0}, + {"TokenReader", Type, 10}, + {"Unmarshal", Func, 0}, + {"UnmarshalError", Type, 0}, + {"Unmarshaler", Type, 2}, + {"UnmarshalerAttr", Type, 2}, + {"UnsupportedTypeError", Type, 0}, + {"UnsupportedTypeError.Type", Field, 0}, + }, + "errors": { + {"As", Func, 13}, + {"ErrUnsupported", Var, 21}, + {"Is", Func, 13}, + {"Join", Func, 20}, + {"New", Func, 0}, + {"Unwrap", Func, 13}, + }, + "expvar": { + {"(*Float).Add", Method, 0}, + {"(*Float).Set", Method, 0}, + {"(*Float).String", Method, 0}, + {"(*Float).Value", Method, 8}, + {"(*Int).Add", Method, 0}, + {"(*Int).Set", Method, 0}, + {"(*Int).String", Method, 0}, + {"(*Int).Value", Method, 8}, + {"(*Map).Add", Method, 0}, + {"(*Map).AddFloat", Method, 0}, + {"(*Map).Delete", Method, 12}, + {"(*Map).Do", Method, 0}, + {"(*Map).Get", Method, 0}, + {"(*Map).Init", Method, 0}, + {"(*Map).Set", Method, 0}, + {"(*Map).String", Method, 0}, + {"(*String).Set", Method, 0}, + {"(*String).String", Method, 0}, + {"(*String).Value", Method, 8}, + {"(Func).String", Method, 0}, + {"(Func).Value", Method, 8}, + {"Do", Func, 0}, + {"Float", Type, 0}, + {"Func", Type, 0}, + {"Get", Func, 0}, + {"Handler", Func, 8}, + {"Int", Type, 0}, + {"KeyValue", Type, 0}, + {"KeyValue.Key", Field, 0}, + {"KeyValue.Value", Field, 0}, + {"Map", Type, 0}, + {"NewFloat", Func, 0}, + {"NewInt", Func, 0}, + {"NewMap", Func, 0}, + {"NewString", Func, 0}, + {"Publish", Func, 0}, + {"String", Type, 0}, + {"Var", Type, 0}, + }, + "flag": { + {"(*FlagSet).Arg", Method, 0}, + {"(*FlagSet).Args", Method, 0}, + {"(*FlagSet).Bool", Method, 0}, + {"(*FlagSet).BoolFunc", Method, 21}, + {"(*FlagSet).BoolVar", Method, 0}, + {"(*FlagSet).Duration", Method, 0}, + {"(*FlagSet).DurationVar", Method, 0}, + {"(*FlagSet).ErrorHandling", Method, 10}, + {"(*FlagSet).Float64", Method, 0}, + {"(*FlagSet).Float64Var", Method, 0}, + {"(*FlagSet).Func", Method, 16}, + {"(*FlagSet).Init", Method, 0}, + {"(*FlagSet).Int", Method, 0}, + {"(*FlagSet).Int64", Method, 0}, + {"(*FlagSet).Int64Var", Method, 0}, + {"(*FlagSet).IntVar", Method, 0}, + {"(*FlagSet).Lookup", Method, 0}, + {"(*FlagSet).NArg", Method, 0}, + {"(*FlagSet).NFlag", Method, 0}, + {"(*FlagSet).Name", Method, 10}, + {"(*FlagSet).Output", Method, 10}, + {"(*FlagSet).Parse", Method, 0}, + {"(*FlagSet).Parsed", Method, 0}, + {"(*FlagSet).PrintDefaults", Method, 0}, + {"(*FlagSet).Set", Method, 0}, + {"(*FlagSet).SetOutput", Method, 0}, + {"(*FlagSet).String", Method, 0}, + {"(*FlagSet).StringVar", Method, 0}, + {"(*FlagSet).TextVar", Method, 19}, + {"(*FlagSet).Uint", Method, 0}, + {"(*FlagSet).Uint64", Method, 0}, + {"(*FlagSet).Uint64Var", Method, 0}, + {"(*FlagSet).UintVar", Method, 0}, + {"(*FlagSet).Var", Method, 0}, + {"(*FlagSet).Visit", Method, 0}, + {"(*FlagSet).VisitAll", Method, 0}, + {"Arg", Func, 0}, + {"Args", Func, 0}, + {"Bool", Func, 0}, + {"BoolFunc", Func, 21}, + {"BoolVar", Func, 0}, + {"CommandLine", Var, 2}, + {"ContinueOnError", Const, 0}, + {"Duration", Func, 0}, + {"DurationVar", Func, 0}, + {"ErrHelp", Var, 0}, + {"ErrorHandling", Type, 0}, + {"ExitOnError", Const, 0}, + {"Flag", Type, 0}, + {"Flag.DefValue", Field, 0}, + {"Flag.Name", Field, 0}, + {"Flag.Usage", Field, 0}, + {"Flag.Value", Field, 0}, + {"FlagSet", Type, 0}, + {"FlagSet.Usage", Field, 0}, + {"Float64", Func, 0}, + {"Float64Var", Func, 0}, + {"Func", Func, 16}, + {"Getter", Type, 2}, + {"Int", Func, 0}, + {"Int64", Func, 0}, + {"Int64Var", Func, 0}, + {"IntVar", Func, 0}, + {"Lookup", Func, 0}, + {"NArg", Func, 0}, + {"NFlag", Func, 0}, + {"NewFlagSet", Func, 0}, + {"PanicOnError", Const, 0}, + {"Parse", Func, 0}, + {"Parsed", Func, 0}, + {"PrintDefaults", Func, 0}, + {"Set", Func, 0}, + {"String", Func, 0}, + {"StringVar", Func, 0}, + {"TextVar", Func, 19}, + {"Uint", Func, 0}, + {"Uint64", Func, 0}, + {"Uint64Var", Func, 0}, + {"UintVar", Func, 0}, + {"UnquoteUsage", Func, 5}, + {"Usage", Var, 0}, + {"Value", Type, 0}, + {"Var", Func, 0}, + {"Visit", Func, 0}, + {"VisitAll", Func, 0}, + }, + "fmt": { + {"Append", Func, 19}, + {"Appendf", Func, 19}, + {"Appendln", Func, 19}, + {"Errorf", Func, 0}, + {"FormatString", Func, 20}, + {"Formatter", Type, 0}, + {"Fprint", Func, 0}, + {"Fprintf", Func, 0}, + {"Fprintln", Func, 0}, + {"Fscan", Func, 0}, + {"Fscanf", Func, 0}, + {"Fscanln", Func, 0}, + {"GoStringer", Type, 0}, + {"Print", Func, 0}, + {"Printf", Func, 0}, + {"Println", Func, 0}, + {"Scan", Func, 0}, + {"ScanState", Type, 0}, + {"Scanf", Func, 0}, + {"Scanln", Func, 0}, + {"Scanner", Type, 0}, + {"Sprint", Func, 0}, + {"Sprintf", Func, 0}, + {"Sprintln", Func, 0}, + {"Sscan", Func, 0}, + {"Sscanf", Func, 0}, + {"Sscanln", Func, 0}, + {"State", Type, 0}, + {"Stringer", Type, 0}, + }, + "go/ast": { + {"(*ArrayType).End", Method, 0}, + {"(*ArrayType).Pos", Method, 0}, + {"(*AssignStmt).End", Method, 0}, + {"(*AssignStmt).Pos", Method, 0}, + {"(*BadDecl).End", Method, 0}, + {"(*BadDecl).Pos", Method, 0}, + {"(*BadExpr).End", Method, 0}, + {"(*BadExpr).Pos", Method, 0}, + {"(*BadStmt).End", Method, 0}, + {"(*BadStmt).Pos", Method, 0}, + {"(*BasicLit).End", Method, 0}, + {"(*BasicLit).Pos", Method, 0}, + {"(*BinaryExpr).End", Method, 0}, + {"(*BinaryExpr).Pos", Method, 0}, + {"(*BlockStmt).End", Method, 0}, + {"(*BlockStmt).Pos", Method, 0}, + {"(*BranchStmt).End", Method, 0}, + {"(*BranchStmt).Pos", Method, 0}, + {"(*CallExpr).End", Method, 0}, + {"(*CallExpr).Pos", Method, 0}, + {"(*CaseClause).End", Method, 0}, + {"(*CaseClause).Pos", Method, 0}, + {"(*ChanType).End", Method, 0}, + {"(*ChanType).Pos", Method, 0}, + {"(*CommClause).End", Method, 0}, + {"(*CommClause).Pos", Method, 0}, + {"(*Comment).End", Method, 0}, + {"(*Comment).Pos", Method, 0}, + {"(*CommentGroup).End", Method, 0}, + {"(*CommentGroup).Pos", Method, 0}, + {"(*CommentGroup).Text", Method, 0}, + {"(*CompositeLit).End", Method, 0}, + {"(*CompositeLit).Pos", Method, 0}, + {"(*DeclStmt).End", Method, 0}, + {"(*DeclStmt).Pos", Method, 0}, + {"(*DeferStmt).End", Method, 0}, + {"(*DeferStmt).Pos", Method, 0}, + {"(*Ellipsis).End", Method, 0}, + {"(*Ellipsis).Pos", Method, 0}, + {"(*EmptyStmt).End", Method, 0}, + {"(*EmptyStmt).Pos", Method, 0}, + {"(*ExprStmt).End", Method, 0}, + {"(*ExprStmt).Pos", Method, 0}, + {"(*Field).End", Method, 0}, + {"(*Field).Pos", Method, 0}, + {"(*FieldList).End", Method, 0}, + {"(*FieldList).NumFields", Method, 0}, + {"(*FieldList).Pos", Method, 0}, + {"(*File).End", Method, 0}, + {"(*File).Pos", Method, 0}, + {"(*ForStmt).End", Method, 0}, + {"(*ForStmt).Pos", Method, 0}, + {"(*FuncDecl).End", Method, 0}, + {"(*FuncDecl).Pos", Method, 0}, + {"(*FuncLit).End", Method, 0}, + {"(*FuncLit).Pos", Method, 0}, + {"(*FuncType).End", Method, 0}, + {"(*FuncType).Pos", Method, 0}, + {"(*GenDecl).End", Method, 0}, + {"(*GenDecl).Pos", Method, 0}, + {"(*GoStmt).End", Method, 0}, + {"(*GoStmt).Pos", Method, 0}, + {"(*Ident).End", Method, 0}, + {"(*Ident).IsExported", Method, 0}, + {"(*Ident).Pos", Method, 0}, + {"(*Ident).String", Method, 0}, + {"(*IfStmt).End", Method, 0}, + {"(*IfStmt).Pos", Method, 0}, + {"(*ImportSpec).End", Method, 0}, + {"(*ImportSpec).Pos", Method, 0}, + {"(*IncDecStmt).End", Method, 0}, + {"(*IncDecStmt).Pos", Method, 0}, + {"(*IndexExpr).End", Method, 0}, + {"(*IndexExpr).Pos", Method, 0}, + {"(*IndexListExpr).End", Method, 18}, + {"(*IndexListExpr).Pos", Method, 18}, + {"(*InterfaceType).End", Method, 0}, + {"(*InterfaceType).Pos", Method, 0}, + {"(*KeyValueExpr).End", Method, 0}, + {"(*KeyValueExpr).Pos", Method, 0}, + {"(*LabeledStmt).End", Method, 0}, + {"(*LabeledStmt).Pos", Method, 0}, + {"(*MapType).End", Method, 0}, + {"(*MapType).Pos", Method, 0}, + {"(*Object).Pos", Method, 0}, + {"(*Package).End", Method, 0}, + {"(*Package).Pos", Method, 0}, + {"(*ParenExpr).End", Method, 0}, + {"(*ParenExpr).Pos", Method, 0}, + {"(*RangeStmt).End", Method, 0}, + {"(*RangeStmt).Pos", Method, 0}, + {"(*ReturnStmt).End", Method, 0}, + {"(*ReturnStmt).Pos", Method, 0}, + {"(*Scope).Insert", Method, 0}, + {"(*Scope).Lookup", Method, 0}, + {"(*Scope).String", Method, 0}, + {"(*SelectStmt).End", Method, 0}, + {"(*SelectStmt).Pos", Method, 0}, + {"(*SelectorExpr).End", Method, 0}, + {"(*SelectorExpr).Pos", Method, 0}, + {"(*SendStmt).End", Method, 0}, + {"(*SendStmt).Pos", Method, 0}, + {"(*SliceExpr).End", Method, 0}, + {"(*SliceExpr).Pos", Method, 0}, + {"(*StarExpr).End", Method, 0}, + {"(*StarExpr).Pos", Method, 0}, + {"(*StructType).End", Method, 0}, + {"(*StructType).Pos", Method, 0}, + {"(*SwitchStmt).End", Method, 0}, + {"(*SwitchStmt).Pos", Method, 0}, + {"(*TypeAssertExpr).End", Method, 0}, + {"(*TypeAssertExpr).Pos", Method, 0}, + {"(*TypeSpec).End", Method, 0}, + {"(*TypeSpec).Pos", Method, 0}, + {"(*TypeSwitchStmt).End", Method, 0}, + {"(*TypeSwitchStmt).Pos", Method, 0}, + {"(*UnaryExpr).End", Method, 0}, + {"(*UnaryExpr).Pos", Method, 0}, + {"(*ValueSpec).End", Method, 0}, + {"(*ValueSpec).Pos", Method, 0}, + {"(CommentMap).Comments", Method, 1}, + {"(CommentMap).Filter", Method, 1}, + {"(CommentMap).String", Method, 1}, + {"(CommentMap).Update", Method, 1}, + {"(ObjKind).String", Method, 0}, + {"ArrayType", Type, 0}, + {"ArrayType.Elt", Field, 0}, + {"ArrayType.Lbrack", Field, 0}, + {"ArrayType.Len", Field, 0}, + {"AssignStmt", Type, 0}, + {"AssignStmt.Lhs", Field, 0}, + {"AssignStmt.Rhs", Field, 0}, + {"AssignStmt.Tok", Field, 0}, + {"AssignStmt.TokPos", Field, 0}, + {"Bad", Const, 0}, + {"BadDecl", Type, 0}, + {"BadDecl.From", Field, 0}, + {"BadDecl.To", Field, 0}, + {"BadExpr", Type, 0}, + {"BadExpr.From", Field, 0}, + {"BadExpr.To", Field, 0}, + {"BadStmt", Type, 0}, + {"BadStmt.From", Field, 0}, + {"BadStmt.To", Field, 0}, + {"BasicLit", Type, 0}, + {"BasicLit.Kind", Field, 0}, + {"BasicLit.Value", Field, 0}, + {"BasicLit.ValuePos", Field, 0}, + {"BinaryExpr", Type, 0}, + {"BinaryExpr.Op", Field, 0}, + {"BinaryExpr.OpPos", Field, 0}, + {"BinaryExpr.X", Field, 0}, + {"BinaryExpr.Y", Field, 0}, + {"BlockStmt", Type, 0}, + {"BlockStmt.Lbrace", Field, 0}, + {"BlockStmt.List", Field, 0}, + {"BlockStmt.Rbrace", Field, 0}, + {"BranchStmt", Type, 0}, + {"BranchStmt.Label", Field, 0}, + {"BranchStmt.Tok", Field, 0}, + {"BranchStmt.TokPos", Field, 0}, + {"CallExpr", Type, 0}, + {"CallExpr.Args", Field, 0}, + {"CallExpr.Ellipsis", Field, 0}, + {"CallExpr.Fun", Field, 0}, + {"CallExpr.Lparen", Field, 0}, + {"CallExpr.Rparen", Field, 0}, + {"CaseClause", Type, 0}, + {"CaseClause.Body", Field, 0}, + {"CaseClause.Case", Field, 0}, + {"CaseClause.Colon", Field, 0}, + {"CaseClause.List", Field, 0}, + {"ChanDir", Type, 0}, + {"ChanType", Type, 0}, + {"ChanType.Arrow", Field, 1}, + {"ChanType.Begin", Field, 0}, + {"ChanType.Dir", Field, 0}, + {"ChanType.Value", Field, 0}, + {"CommClause", Type, 0}, + {"CommClause.Body", Field, 0}, + {"CommClause.Case", Field, 0}, + {"CommClause.Colon", Field, 0}, + {"CommClause.Comm", Field, 0}, + {"Comment", Type, 0}, + {"Comment.Slash", Field, 0}, + {"Comment.Text", Field, 0}, + {"CommentGroup", Type, 0}, + {"CommentGroup.List", Field, 0}, + {"CommentMap", Type, 1}, + {"CompositeLit", Type, 0}, + {"CompositeLit.Elts", Field, 0}, + {"CompositeLit.Incomplete", Field, 11}, + {"CompositeLit.Lbrace", Field, 0}, + {"CompositeLit.Rbrace", Field, 0}, + {"CompositeLit.Type", Field, 0}, + {"Con", Const, 0}, + {"Decl", Type, 0}, + {"DeclStmt", Type, 0}, + {"DeclStmt.Decl", Field, 0}, + {"DeferStmt", Type, 0}, + {"DeferStmt.Call", Field, 0}, + {"DeferStmt.Defer", Field, 0}, + {"Ellipsis", Type, 0}, + {"Ellipsis.Ellipsis", Field, 0}, + {"Ellipsis.Elt", Field, 0}, + {"EmptyStmt", Type, 0}, + {"EmptyStmt.Implicit", Field, 5}, + {"EmptyStmt.Semicolon", Field, 0}, + {"Expr", Type, 0}, + {"ExprStmt", Type, 0}, + {"ExprStmt.X", Field, 0}, + {"Field", Type, 0}, + {"Field.Comment", Field, 0}, + {"Field.Doc", Field, 0}, + {"Field.Names", Field, 0}, + {"Field.Tag", Field, 0}, + {"Field.Type", Field, 0}, + {"FieldFilter", Type, 0}, + {"FieldList", Type, 0}, + {"FieldList.Closing", Field, 0}, + {"FieldList.List", Field, 0}, + {"FieldList.Opening", Field, 0}, + {"File", Type, 0}, + {"File.Comments", Field, 0}, + {"File.Decls", Field, 0}, + {"File.Doc", Field, 0}, + {"File.FileEnd", Field, 20}, + {"File.FileStart", Field, 20}, + {"File.GoVersion", Field, 21}, + {"File.Imports", Field, 0}, + {"File.Name", Field, 0}, + {"File.Package", Field, 0}, + {"File.Scope", Field, 0}, + {"File.Unresolved", Field, 0}, + {"FileExports", Func, 0}, + {"Filter", Type, 0}, + {"FilterDecl", Func, 0}, + {"FilterFile", Func, 0}, + {"FilterFuncDuplicates", Const, 0}, + {"FilterImportDuplicates", Const, 0}, + {"FilterPackage", Func, 0}, + {"FilterUnassociatedComments", Const, 0}, + {"ForStmt", Type, 0}, + {"ForStmt.Body", Field, 0}, + {"ForStmt.Cond", Field, 0}, + {"ForStmt.For", Field, 0}, + {"ForStmt.Init", Field, 0}, + {"ForStmt.Post", Field, 0}, + {"Fprint", Func, 0}, + {"Fun", Const, 0}, + {"FuncDecl", Type, 0}, + {"FuncDecl.Body", Field, 0}, + {"FuncDecl.Doc", Field, 0}, + {"FuncDecl.Name", Field, 0}, + {"FuncDecl.Recv", Field, 0}, + {"FuncDecl.Type", Field, 0}, + {"FuncLit", Type, 0}, + {"FuncLit.Body", Field, 0}, + {"FuncLit.Type", Field, 0}, + {"FuncType", Type, 0}, + {"FuncType.Func", Field, 0}, + {"FuncType.Params", Field, 0}, + {"FuncType.Results", Field, 0}, + {"FuncType.TypeParams", Field, 18}, + {"GenDecl", Type, 0}, + {"GenDecl.Doc", Field, 0}, + {"GenDecl.Lparen", Field, 0}, + {"GenDecl.Rparen", Field, 0}, + {"GenDecl.Specs", Field, 0}, + {"GenDecl.Tok", Field, 0}, + {"GenDecl.TokPos", Field, 0}, + {"GoStmt", Type, 0}, + {"GoStmt.Call", Field, 0}, + {"GoStmt.Go", Field, 0}, + {"Ident", Type, 0}, + {"Ident.Name", Field, 0}, + {"Ident.NamePos", Field, 0}, + {"Ident.Obj", Field, 0}, + {"IfStmt", Type, 0}, + {"IfStmt.Body", Field, 0}, + {"IfStmt.Cond", Field, 0}, + {"IfStmt.Else", Field, 0}, + {"IfStmt.If", Field, 0}, + {"IfStmt.Init", Field, 0}, + {"ImportSpec", Type, 0}, + {"ImportSpec.Comment", Field, 0}, + {"ImportSpec.Doc", Field, 0}, + {"ImportSpec.EndPos", Field, 0}, + {"ImportSpec.Name", Field, 0}, + {"ImportSpec.Path", Field, 0}, + {"Importer", Type, 0}, + {"IncDecStmt", Type, 0}, + {"IncDecStmt.Tok", Field, 0}, + {"IncDecStmt.TokPos", Field, 0}, + {"IncDecStmt.X", Field, 0}, + {"IndexExpr", Type, 0}, + {"IndexExpr.Index", Field, 0}, + {"IndexExpr.Lbrack", Field, 0}, + {"IndexExpr.Rbrack", Field, 0}, + {"IndexExpr.X", Field, 0}, + {"IndexListExpr", Type, 18}, + {"IndexListExpr.Indices", Field, 18}, + {"IndexListExpr.Lbrack", Field, 18}, + {"IndexListExpr.Rbrack", Field, 18}, + {"IndexListExpr.X", Field, 18}, + {"Inspect", Func, 0}, + {"InterfaceType", Type, 0}, + {"InterfaceType.Incomplete", Field, 0}, + {"InterfaceType.Interface", Field, 0}, + {"InterfaceType.Methods", Field, 0}, + {"IsExported", Func, 0}, + {"IsGenerated", Func, 21}, + {"KeyValueExpr", Type, 0}, + {"KeyValueExpr.Colon", Field, 0}, + {"KeyValueExpr.Key", Field, 0}, + {"KeyValueExpr.Value", Field, 0}, + {"LabeledStmt", Type, 0}, + {"LabeledStmt.Colon", Field, 0}, + {"LabeledStmt.Label", Field, 0}, + {"LabeledStmt.Stmt", Field, 0}, + {"Lbl", Const, 0}, + {"MapType", Type, 0}, + {"MapType.Key", Field, 0}, + {"MapType.Map", Field, 0}, + {"MapType.Value", Field, 0}, + {"MergeMode", Type, 0}, + {"MergePackageFiles", Func, 0}, + {"NewCommentMap", Func, 1}, + {"NewIdent", Func, 0}, + {"NewObj", Func, 0}, + {"NewPackage", Func, 0}, + {"NewScope", Func, 0}, + {"Node", Type, 0}, + {"NotNilFilter", Func, 0}, + {"ObjKind", Type, 0}, + {"Object", Type, 0}, + {"Object.Data", Field, 0}, + {"Object.Decl", Field, 0}, + {"Object.Kind", Field, 0}, + {"Object.Name", Field, 0}, + {"Object.Type", Field, 0}, + {"Package", Type, 0}, + {"Package.Files", Field, 0}, + {"Package.Imports", Field, 0}, + {"Package.Name", Field, 0}, + {"Package.Scope", Field, 0}, + {"PackageExports", Func, 0}, + {"ParenExpr", Type, 0}, + {"ParenExpr.Lparen", Field, 0}, + {"ParenExpr.Rparen", Field, 0}, + {"ParenExpr.X", Field, 0}, + {"Pkg", Const, 0}, + {"Print", Func, 0}, + {"RECV", Const, 0}, + {"RangeStmt", Type, 0}, + {"RangeStmt.Body", Field, 0}, + {"RangeStmt.For", Field, 0}, + {"RangeStmt.Key", Field, 0}, + {"RangeStmt.Range", Field, 20}, + {"RangeStmt.Tok", Field, 0}, + {"RangeStmt.TokPos", Field, 0}, + {"RangeStmt.Value", Field, 0}, + {"RangeStmt.X", Field, 0}, + {"ReturnStmt", Type, 0}, + {"ReturnStmt.Results", Field, 0}, + {"ReturnStmt.Return", Field, 0}, + {"SEND", Const, 0}, + {"Scope", Type, 0}, + {"Scope.Objects", Field, 0}, + {"Scope.Outer", Field, 0}, + {"SelectStmt", Type, 0}, + {"SelectStmt.Body", Field, 0}, + {"SelectStmt.Select", Field, 0}, + {"SelectorExpr", Type, 0}, + {"SelectorExpr.Sel", Field, 0}, + {"SelectorExpr.X", Field, 0}, + {"SendStmt", Type, 0}, + {"SendStmt.Arrow", Field, 0}, + {"SendStmt.Chan", Field, 0}, + {"SendStmt.Value", Field, 0}, + {"SliceExpr", Type, 0}, + {"SliceExpr.High", Field, 0}, + {"SliceExpr.Lbrack", Field, 0}, + {"SliceExpr.Low", Field, 0}, + {"SliceExpr.Max", Field, 2}, + {"SliceExpr.Rbrack", Field, 0}, + {"SliceExpr.Slice3", Field, 2}, + {"SliceExpr.X", Field, 0}, + {"SortImports", Func, 0}, + {"Spec", Type, 0}, + {"StarExpr", Type, 0}, + {"StarExpr.Star", Field, 0}, + {"StarExpr.X", Field, 0}, + {"Stmt", Type, 0}, + {"StructType", Type, 0}, + {"StructType.Fields", Field, 0}, + {"StructType.Incomplete", Field, 0}, + {"StructType.Struct", Field, 0}, + {"SwitchStmt", Type, 0}, + {"SwitchStmt.Body", Field, 0}, + {"SwitchStmt.Init", Field, 0}, + {"SwitchStmt.Switch", Field, 0}, + {"SwitchStmt.Tag", Field, 0}, + {"Typ", Const, 0}, + {"TypeAssertExpr", Type, 0}, + {"TypeAssertExpr.Lparen", Field, 2}, + {"TypeAssertExpr.Rparen", Field, 2}, + {"TypeAssertExpr.Type", Field, 0}, + {"TypeAssertExpr.X", Field, 0}, + {"TypeSpec", Type, 0}, + {"TypeSpec.Assign", Field, 9}, + {"TypeSpec.Comment", Field, 0}, + {"TypeSpec.Doc", Field, 0}, + {"TypeSpec.Name", Field, 0}, + {"TypeSpec.Type", Field, 0}, + {"TypeSpec.TypeParams", Field, 18}, + {"TypeSwitchStmt", Type, 0}, + {"TypeSwitchStmt.Assign", Field, 0}, + {"TypeSwitchStmt.Body", Field, 0}, + {"TypeSwitchStmt.Init", Field, 0}, + {"TypeSwitchStmt.Switch", Field, 0}, + {"UnaryExpr", Type, 0}, + {"UnaryExpr.Op", Field, 0}, + {"UnaryExpr.OpPos", Field, 0}, + {"UnaryExpr.X", Field, 0}, + {"Unparen", Func, 22}, + {"ValueSpec", Type, 0}, + {"ValueSpec.Comment", Field, 0}, + {"ValueSpec.Doc", Field, 0}, + {"ValueSpec.Names", Field, 0}, + {"ValueSpec.Type", Field, 0}, + {"ValueSpec.Values", Field, 0}, + {"Var", Const, 0}, + {"Visitor", Type, 0}, + {"Walk", Func, 0}, + }, + "go/build": { + {"(*Context).Import", Method, 0}, + {"(*Context).ImportDir", Method, 0}, + {"(*Context).MatchFile", Method, 2}, + {"(*Context).SrcDirs", Method, 0}, + {"(*MultiplePackageError).Error", Method, 4}, + {"(*NoGoError).Error", Method, 0}, + {"(*Package).IsCommand", Method, 0}, + {"AllowBinary", Const, 0}, + {"ArchChar", Func, 0}, + {"Context", Type, 0}, + {"Context.BuildTags", Field, 0}, + {"Context.CgoEnabled", Field, 0}, + {"Context.Compiler", Field, 0}, + {"Context.Dir", Field, 14}, + {"Context.GOARCH", Field, 0}, + {"Context.GOOS", Field, 0}, + {"Context.GOPATH", Field, 0}, + {"Context.GOROOT", Field, 0}, + {"Context.HasSubdir", Field, 0}, + {"Context.InstallSuffix", Field, 1}, + {"Context.IsAbsPath", Field, 0}, + {"Context.IsDir", Field, 0}, + {"Context.JoinPath", Field, 0}, + {"Context.OpenFile", Field, 0}, + {"Context.ReadDir", Field, 0}, + {"Context.ReleaseTags", Field, 1}, + {"Context.SplitPathList", Field, 0}, + {"Context.ToolTags", Field, 17}, + {"Context.UseAllFiles", Field, 0}, + {"Default", Var, 0}, + {"Directive", Type, 21}, + {"Directive.Pos", Field, 21}, + {"Directive.Text", Field, 21}, + {"FindOnly", Const, 0}, + {"IgnoreVendor", Const, 6}, + {"Import", Func, 0}, + {"ImportComment", Const, 4}, + {"ImportDir", Func, 0}, + {"ImportMode", Type, 0}, + {"IsLocalImport", Func, 0}, + {"MultiplePackageError", Type, 4}, + {"MultiplePackageError.Dir", Field, 4}, + {"MultiplePackageError.Files", Field, 4}, + {"MultiplePackageError.Packages", Field, 4}, + {"NoGoError", Type, 0}, + {"NoGoError.Dir", Field, 0}, + {"Package", Type, 0}, + {"Package.AllTags", Field, 2}, + {"Package.BinDir", Field, 0}, + {"Package.BinaryOnly", Field, 7}, + {"Package.CFiles", Field, 0}, + {"Package.CXXFiles", Field, 2}, + {"Package.CgoCFLAGS", Field, 0}, + {"Package.CgoCPPFLAGS", Field, 2}, + {"Package.CgoCXXFLAGS", Field, 2}, + {"Package.CgoFFLAGS", Field, 7}, + {"Package.CgoFiles", Field, 0}, + {"Package.CgoLDFLAGS", Field, 0}, + {"Package.CgoPkgConfig", Field, 0}, + {"Package.ConflictDir", Field, 2}, + {"Package.Dir", Field, 0}, + {"Package.Directives", Field, 21}, + {"Package.Doc", Field, 0}, + {"Package.EmbedPatternPos", Field, 16}, + {"Package.EmbedPatterns", Field, 16}, + {"Package.FFiles", Field, 7}, + {"Package.GoFiles", Field, 0}, + {"Package.Goroot", Field, 0}, + {"Package.HFiles", Field, 0}, + {"Package.IgnoredGoFiles", Field, 1}, + {"Package.IgnoredOtherFiles", Field, 16}, + {"Package.ImportComment", Field, 4}, + {"Package.ImportPath", Field, 0}, + {"Package.ImportPos", Field, 0}, + {"Package.Imports", Field, 0}, + {"Package.InvalidGoFiles", Field, 6}, + {"Package.MFiles", Field, 3}, + {"Package.Name", Field, 0}, + {"Package.PkgObj", Field, 0}, + {"Package.PkgRoot", Field, 0}, + {"Package.PkgTargetRoot", Field, 5}, + {"Package.Root", Field, 0}, + {"Package.SFiles", Field, 0}, + {"Package.SrcRoot", Field, 0}, + {"Package.SwigCXXFiles", Field, 1}, + {"Package.SwigFiles", Field, 1}, + {"Package.SysoFiles", Field, 0}, + {"Package.TestDirectives", Field, 21}, + {"Package.TestEmbedPatternPos", Field, 16}, + {"Package.TestEmbedPatterns", Field, 16}, + {"Package.TestGoFiles", Field, 0}, + {"Package.TestImportPos", Field, 0}, + {"Package.TestImports", Field, 0}, + {"Package.XTestDirectives", Field, 21}, + {"Package.XTestEmbedPatternPos", Field, 16}, + {"Package.XTestEmbedPatterns", Field, 16}, + {"Package.XTestGoFiles", Field, 0}, + {"Package.XTestImportPos", Field, 0}, + {"Package.XTestImports", Field, 0}, + {"ToolDir", Var, 0}, + }, + "go/build/constraint": { + {"(*AndExpr).Eval", Method, 16}, + {"(*AndExpr).String", Method, 16}, + {"(*NotExpr).Eval", Method, 16}, + {"(*NotExpr).String", Method, 16}, + {"(*OrExpr).Eval", Method, 16}, + {"(*OrExpr).String", Method, 16}, + {"(*SyntaxError).Error", Method, 16}, + {"(*TagExpr).Eval", Method, 16}, + {"(*TagExpr).String", Method, 16}, + {"AndExpr", Type, 16}, + {"AndExpr.X", Field, 16}, + {"AndExpr.Y", Field, 16}, + {"Expr", Type, 16}, + {"GoVersion", Func, 21}, + {"IsGoBuild", Func, 16}, + {"IsPlusBuild", Func, 16}, + {"NotExpr", Type, 16}, + {"NotExpr.X", Field, 16}, + {"OrExpr", Type, 16}, + {"OrExpr.X", Field, 16}, + {"OrExpr.Y", Field, 16}, + {"Parse", Func, 16}, + {"PlusBuildLines", Func, 16}, + {"SyntaxError", Type, 16}, + {"SyntaxError.Err", Field, 16}, + {"SyntaxError.Offset", Field, 16}, + {"TagExpr", Type, 16}, + {"TagExpr.Tag", Field, 16}, + }, + "go/constant": { + {"(Kind).String", Method, 18}, + {"BinaryOp", Func, 5}, + {"BitLen", Func, 5}, + {"Bool", Const, 5}, + {"BoolVal", Func, 5}, + {"Bytes", Func, 5}, + {"Compare", Func, 5}, + {"Complex", Const, 5}, + {"Denom", Func, 5}, + {"Float", Const, 5}, + {"Float32Val", Func, 5}, + {"Float64Val", Func, 5}, + {"Imag", Func, 5}, + {"Int", Const, 5}, + {"Int64Val", Func, 5}, + {"Kind", Type, 5}, + {"Make", Func, 13}, + {"MakeBool", Func, 5}, + {"MakeFloat64", Func, 5}, + {"MakeFromBytes", Func, 5}, + {"MakeFromLiteral", Func, 5}, + {"MakeImag", Func, 5}, + {"MakeInt64", Func, 5}, + {"MakeString", Func, 5}, + {"MakeUint64", Func, 5}, + {"MakeUnknown", Func, 5}, + {"Num", Func, 5}, + {"Real", Func, 5}, + {"Shift", Func, 5}, + {"Sign", Func, 5}, + {"String", Const, 5}, + {"StringVal", Func, 5}, + {"ToComplex", Func, 6}, + {"ToFloat", Func, 6}, + {"ToInt", Func, 6}, + {"Uint64Val", Func, 5}, + {"UnaryOp", Func, 5}, + {"Unknown", Const, 5}, + {"Val", Func, 13}, + {"Value", Type, 5}, + }, + "go/doc": { + {"(*Package).Filter", Method, 0}, + {"(*Package).HTML", Method, 19}, + {"(*Package).Markdown", Method, 19}, + {"(*Package).Parser", Method, 19}, + {"(*Package).Printer", Method, 19}, + {"(*Package).Synopsis", Method, 19}, + {"(*Package).Text", Method, 19}, + {"AllDecls", Const, 0}, + {"AllMethods", Const, 0}, + {"Example", Type, 0}, + {"Example.Code", Field, 0}, + {"Example.Comments", Field, 0}, + {"Example.Doc", Field, 0}, + {"Example.EmptyOutput", Field, 1}, + {"Example.Name", Field, 0}, + {"Example.Order", Field, 1}, + {"Example.Output", Field, 0}, + {"Example.Play", Field, 1}, + {"Example.Suffix", Field, 14}, + {"Example.Unordered", Field, 7}, + {"Examples", Func, 0}, + {"Filter", Type, 0}, + {"Func", Type, 0}, + {"Func.Decl", Field, 0}, + {"Func.Doc", Field, 0}, + {"Func.Examples", Field, 14}, + {"Func.Level", Field, 0}, + {"Func.Name", Field, 0}, + {"Func.Orig", Field, 0}, + {"Func.Recv", Field, 0}, + {"IllegalPrefixes", Var, 1}, + {"IsPredeclared", Func, 8}, + {"Mode", Type, 0}, + {"New", Func, 0}, + {"NewFromFiles", Func, 14}, + {"Note", Type, 1}, + {"Note.Body", Field, 1}, + {"Note.End", Field, 1}, + {"Note.Pos", Field, 1}, + {"Note.UID", Field, 1}, + {"Package", Type, 0}, + {"Package.Bugs", Field, 0}, + {"Package.Consts", Field, 0}, + {"Package.Doc", Field, 0}, + {"Package.Examples", Field, 14}, + {"Package.Filenames", Field, 0}, + {"Package.Funcs", Field, 0}, + {"Package.ImportPath", Field, 0}, + {"Package.Imports", Field, 0}, + {"Package.Name", Field, 0}, + {"Package.Notes", Field, 1}, + {"Package.Types", Field, 0}, + {"Package.Vars", Field, 0}, + {"PreserveAST", Const, 12}, + {"Synopsis", Func, 0}, + {"ToHTML", Func, 0}, + {"ToText", Func, 0}, + {"Type", Type, 0}, + {"Type.Consts", Field, 0}, + {"Type.Decl", Field, 0}, + {"Type.Doc", Field, 0}, + {"Type.Examples", Field, 14}, + {"Type.Funcs", Field, 0}, + {"Type.Methods", Field, 0}, + {"Type.Name", Field, 0}, + {"Type.Vars", Field, 0}, + {"Value", Type, 0}, + {"Value.Decl", Field, 0}, + {"Value.Doc", Field, 0}, + {"Value.Names", Field, 0}, + }, + "go/doc/comment": { + {"(*DocLink).DefaultURL", Method, 19}, + {"(*Heading).DefaultID", Method, 19}, + {"(*List).BlankBefore", Method, 19}, + {"(*List).BlankBetween", Method, 19}, + {"(*Parser).Parse", Method, 19}, + {"(*Printer).Comment", Method, 19}, + {"(*Printer).HTML", Method, 19}, + {"(*Printer).Markdown", Method, 19}, + {"(*Printer).Text", Method, 19}, + {"Block", Type, 19}, + {"Code", Type, 19}, + {"Code.Text", Field, 19}, + {"DefaultLookupPackage", Func, 19}, + {"Doc", Type, 19}, + {"Doc.Content", Field, 19}, + {"Doc.Links", Field, 19}, + {"DocLink", Type, 19}, + {"DocLink.ImportPath", Field, 19}, + {"DocLink.Name", Field, 19}, + {"DocLink.Recv", Field, 19}, + {"DocLink.Text", Field, 19}, + {"Heading", Type, 19}, + {"Heading.Text", Field, 19}, + {"Italic", Type, 19}, + {"Link", Type, 19}, + {"Link.Auto", Field, 19}, + {"Link.Text", Field, 19}, + {"Link.URL", Field, 19}, + {"LinkDef", Type, 19}, + {"LinkDef.Text", Field, 19}, + {"LinkDef.URL", Field, 19}, + {"LinkDef.Used", Field, 19}, + {"List", Type, 19}, + {"List.ForceBlankBefore", Field, 19}, + {"List.ForceBlankBetween", Field, 19}, + {"List.Items", Field, 19}, + {"ListItem", Type, 19}, + {"ListItem.Content", Field, 19}, + {"ListItem.Number", Field, 19}, + {"Paragraph", Type, 19}, + {"Paragraph.Text", Field, 19}, + {"Parser", Type, 19}, + {"Parser.LookupPackage", Field, 19}, + {"Parser.LookupSym", Field, 19}, + {"Parser.Words", Field, 19}, + {"Plain", Type, 19}, + {"Printer", Type, 19}, + {"Printer.DocLinkBaseURL", Field, 19}, + {"Printer.DocLinkURL", Field, 19}, + {"Printer.HeadingID", Field, 19}, + {"Printer.HeadingLevel", Field, 19}, + {"Printer.TextCodePrefix", Field, 19}, + {"Printer.TextPrefix", Field, 19}, + {"Printer.TextWidth", Field, 19}, + {"Text", Type, 19}, + }, + "go/format": { + {"Node", Func, 1}, + {"Source", Func, 1}, + }, + "go/importer": { + {"Default", Func, 5}, + {"For", Func, 5}, + {"ForCompiler", Func, 12}, + {"Lookup", Type, 5}, + }, + "go/parser": { + {"AllErrors", Const, 1}, + {"DeclarationErrors", Const, 0}, + {"ImportsOnly", Const, 0}, + {"Mode", Type, 0}, + {"PackageClauseOnly", Const, 0}, + {"ParseComments", Const, 0}, + {"ParseDir", Func, 0}, + {"ParseExpr", Func, 0}, + {"ParseExprFrom", Func, 5}, + {"ParseFile", Func, 0}, + {"SkipObjectResolution", Const, 17}, + {"SpuriousErrors", Const, 0}, + {"Trace", Const, 0}, + }, + "go/printer": { + {"(*Config).Fprint", Method, 0}, + {"CommentedNode", Type, 0}, + {"CommentedNode.Comments", Field, 0}, + {"CommentedNode.Node", Field, 0}, + {"Config", Type, 0}, + {"Config.Indent", Field, 1}, + {"Config.Mode", Field, 0}, + {"Config.Tabwidth", Field, 0}, + {"Fprint", Func, 0}, + {"Mode", Type, 0}, + {"RawFormat", Const, 0}, + {"SourcePos", Const, 0}, + {"TabIndent", Const, 0}, + {"UseSpaces", Const, 0}, + }, + "go/scanner": { + {"(*ErrorList).Add", Method, 0}, + {"(*ErrorList).RemoveMultiples", Method, 0}, + {"(*ErrorList).Reset", Method, 0}, + {"(*Scanner).Init", Method, 0}, + {"(*Scanner).Scan", Method, 0}, + {"(Error).Error", Method, 0}, + {"(ErrorList).Err", Method, 0}, + {"(ErrorList).Error", Method, 0}, + {"(ErrorList).Len", Method, 0}, + {"(ErrorList).Less", Method, 0}, + {"(ErrorList).Sort", Method, 0}, + {"(ErrorList).Swap", Method, 0}, + {"Error", Type, 0}, + {"Error.Msg", Field, 0}, + {"Error.Pos", Field, 0}, + {"ErrorHandler", Type, 0}, + {"ErrorList", Type, 0}, + {"Mode", Type, 0}, + {"PrintError", Func, 0}, + {"ScanComments", Const, 0}, + {"Scanner", Type, 0}, + {"Scanner.ErrorCount", Field, 0}, + }, + "go/token": { + {"(*File).AddLine", Method, 0}, + {"(*File).AddLineColumnInfo", Method, 11}, + {"(*File).AddLineInfo", Method, 0}, + {"(*File).Base", Method, 0}, + {"(*File).Line", Method, 0}, + {"(*File).LineCount", Method, 0}, + {"(*File).LineStart", Method, 12}, + {"(*File).Lines", Method, 21}, + {"(*File).MergeLine", Method, 2}, + {"(*File).Name", Method, 0}, + {"(*File).Offset", Method, 0}, + {"(*File).Pos", Method, 0}, + {"(*File).Position", Method, 0}, + {"(*File).PositionFor", Method, 4}, + {"(*File).SetLines", Method, 0}, + {"(*File).SetLinesForContent", Method, 0}, + {"(*File).Size", Method, 0}, + {"(*FileSet).AddFile", Method, 0}, + {"(*FileSet).Base", Method, 0}, + {"(*FileSet).File", Method, 0}, + {"(*FileSet).Iterate", Method, 0}, + {"(*FileSet).Position", Method, 0}, + {"(*FileSet).PositionFor", Method, 4}, + {"(*FileSet).Read", Method, 0}, + {"(*FileSet).RemoveFile", Method, 20}, + {"(*FileSet).Write", Method, 0}, + {"(*Position).IsValid", Method, 0}, + {"(Pos).IsValid", Method, 0}, + {"(Position).String", Method, 0}, + {"(Token).IsKeyword", Method, 0}, + {"(Token).IsLiteral", Method, 0}, + {"(Token).IsOperator", Method, 0}, + {"(Token).Precedence", Method, 0}, + {"(Token).String", Method, 0}, + {"ADD", Const, 0}, + {"ADD_ASSIGN", Const, 0}, + {"AND", Const, 0}, + {"AND_ASSIGN", Const, 0}, + {"AND_NOT", Const, 0}, + {"AND_NOT_ASSIGN", Const, 0}, + {"ARROW", Const, 0}, + {"ASSIGN", Const, 0}, + {"BREAK", Const, 0}, + {"CASE", Const, 0}, + {"CHAN", Const, 0}, + {"CHAR", Const, 0}, + {"COLON", Const, 0}, + {"COMMA", Const, 0}, + {"COMMENT", Const, 0}, + {"CONST", Const, 0}, + {"CONTINUE", Const, 0}, + {"DEC", Const, 0}, + {"DEFAULT", Const, 0}, + {"DEFER", Const, 0}, + {"DEFINE", Const, 0}, + {"ELLIPSIS", Const, 0}, + {"ELSE", Const, 0}, + {"EOF", Const, 0}, + {"EQL", Const, 0}, + {"FALLTHROUGH", Const, 0}, + {"FLOAT", Const, 0}, + {"FOR", Const, 0}, + {"FUNC", Const, 0}, + {"File", Type, 0}, + {"FileSet", Type, 0}, + {"GEQ", Const, 0}, + {"GO", Const, 0}, + {"GOTO", Const, 0}, + {"GTR", Const, 0}, + {"HighestPrec", Const, 0}, + {"IDENT", Const, 0}, + {"IF", Const, 0}, + {"ILLEGAL", Const, 0}, + {"IMAG", Const, 0}, + {"IMPORT", Const, 0}, + {"INC", Const, 0}, + {"INT", Const, 0}, + {"INTERFACE", Const, 0}, + {"IsExported", Func, 13}, + {"IsIdentifier", Func, 13}, + {"IsKeyword", Func, 13}, + {"LAND", Const, 0}, + {"LBRACE", Const, 0}, + {"LBRACK", Const, 0}, + {"LEQ", Const, 0}, + {"LOR", Const, 0}, + {"LPAREN", Const, 0}, + {"LSS", Const, 0}, + {"Lookup", Func, 0}, + {"LowestPrec", Const, 0}, + {"MAP", Const, 0}, + {"MUL", Const, 0}, + {"MUL_ASSIGN", Const, 0}, + {"NEQ", Const, 0}, + {"NOT", Const, 0}, + {"NewFileSet", Func, 0}, + {"NoPos", Const, 0}, + {"OR", Const, 0}, + {"OR_ASSIGN", Const, 0}, + {"PACKAGE", Const, 0}, + {"PERIOD", Const, 0}, + {"Pos", Type, 0}, + {"Position", Type, 0}, + {"Position.Column", Field, 0}, + {"Position.Filename", Field, 0}, + {"Position.Line", Field, 0}, + {"Position.Offset", Field, 0}, + {"QUO", Const, 0}, + {"QUO_ASSIGN", Const, 0}, + {"RANGE", Const, 0}, + {"RBRACE", Const, 0}, + {"RBRACK", Const, 0}, + {"REM", Const, 0}, + {"REM_ASSIGN", Const, 0}, + {"RETURN", Const, 0}, + {"RPAREN", Const, 0}, + {"SELECT", Const, 0}, + {"SEMICOLON", Const, 0}, + {"SHL", Const, 0}, + {"SHL_ASSIGN", Const, 0}, + {"SHR", Const, 0}, + {"SHR_ASSIGN", Const, 0}, + {"STRING", Const, 0}, + {"STRUCT", Const, 0}, + {"SUB", Const, 0}, + {"SUB_ASSIGN", Const, 0}, + {"SWITCH", Const, 0}, + {"TILDE", Const, 18}, + {"TYPE", Const, 0}, + {"Token", Type, 0}, + {"UnaryPrec", Const, 0}, + {"VAR", Const, 0}, + {"XOR", Const, 0}, + {"XOR_ASSIGN", Const, 0}, + }, + "go/types": { + {"(*Alias).Obj", Method, 22}, + {"(*Alias).String", Method, 22}, + {"(*Alias).Underlying", Method, 22}, + {"(*ArgumentError).Error", Method, 18}, + {"(*ArgumentError).Unwrap", Method, 18}, + {"(*Array).Elem", Method, 5}, + {"(*Array).Len", Method, 5}, + {"(*Array).String", Method, 5}, + {"(*Array).Underlying", Method, 5}, + {"(*Basic).Info", Method, 5}, + {"(*Basic).Kind", Method, 5}, + {"(*Basic).Name", Method, 5}, + {"(*Basic).String", Method, 5}, + {"(*Basic).Underlying", Method, 5}, + {"(*Builtin).Exported", Method, 5}, + {"(*Builtin).Id", Method, 5}, + {"(*Builtin).Name", Method, 5}, + {"(*Builtin).Parent", Method, 5}, + {"(*Builtin).Pkg", Method, 5}, + {"(*Builtin).Pos", Method, 5}, + {"(*Builtin).String", Method, 5}, + {"(*Builtin).Type", Method, 5}, + {"(*Chan).Dir", Method, 5}, + {"(*Chan).Elem", Method, 5}, + {"(*Chan).String", Method, 5}, + {"(*Chan).Underlying", Method, 5}, + {"(*Checker).Files", Method, 5}, + {"(*Config).Check", Method, 5}, + {"(*Const).Exported", Method, 5}, + {"(*Const).Id", Method, 5}, + {"(*Const).Name", Method, 5}, + {"(*Const).Parent", Method, 5}, + {"(*Const).Pkg", Method, 5}, + {"(*Const).Pos", Method, 5}, + {"(*Const).String", Method, 5}, + {"(*Const).Type", Method, 5}, + {"(*Const).Val", Method, 5}, + {"(*Func).Exported", Method, 5}, + {"(*Func).FullName", Method, 5}, + {"(*Func).Id", Method, 5}, + {"(*Func).Name", Method, 5}, + {"(*Func).Origin", Method, 19}, + {"(*Func).Parent", Method, 5}, + {"(*Func).Pkg", Method, 5}, + {"(*Func).Pos", Method, 5}, + {"(*Func).Scope", Method, 5}, + {"(*Func).String", Method, 5}, + {"(*Func).Type", Method, 5}, + {"(*Info).ObjectOf", Method, 5}, + {"(*Info).PkgNameOf", Method, 22}, + {"(*Info).TypeOf", Method, 5}, + {"(*Initializer).String", Method, 5}, + {"(*Interface).Complete", Method, 5}, + {"(*Interface).Embedded", Method, 5}, + {"(*Interface).EmbeddedType", Method, 11}, + {"(*Interface).Empty", Method, 5}, + {"(*Interface).ExplicitMethod", Method, 5}, + {"(*Interface).IsComparable", Method, 18}, + {"(*Interface).IsImplicit", Method, 18}, + {"(*Interface).IsMethodSet", Method, 18}, + {"(*Interface).MarkImplicit", Method, 18}, + {"(*Interface).Method", Method, 5}, + {"(*Interface).NumEmbeddeds", Method, 5}, + {"(*Interface).NumExplicitMethods", Method, 5}, + {"(*Interface).NumMethods", Method, 5}, + {"(*Interface).String", Method, 5}, + {"(*Interface).Underlying", Method, 5}, + {"(*Label).Exported", Method, 5}, + {"(*Label).Id", Method, 5}, + {"(*Label).Name", Method, 5}, + {"(*Label).Parent", Method, 5}, + {"(*Label).Pkg", Method, 5}, + {"(*Label).Pos", Method, 5}, + {"(*Label).String", Method, 5}, + {"(*Label).Type", Method, 5}, + {"(*Map).Elem", Method, 5}, + {"(*Map).Key", Method, 5}, + {"(*Map).String", Method, 5}, + {"(*Map).Underlying", Method, 5}, + {"(*MethodSet).At", Method, 5}, + {"(*MethodSet).Len", Method, 5}, + {"(*MethodSet).Lookup", Method, 5}, + {"(*MethodSet).String", Method, 5}, + {"(*Named).AddMethod", Method, 5}, + {"(*Named).Method", Method, 5}, + {"(*Named).NumMethods", Method, 5}, + {"(*Named).Obj", Method, 5}, + {"(*Named).Origin", Method, 18}, + {"(*Named).SetTypeParams", Method, 18}, + {"(*Named).SetUnderlying", Method, 5}, + {"(*Named).String", Method, 5}, + {"(*Named).TypeArgs", Method, 18}, + {"(*Named).TypeParams", Method, 18}, + {"(*Named).Underlying", Method, 5}, + {"(*Nil).Exported", Method, 5}, + {"(*Nil).Id", Method, 5}, + {"(*Nil).Name", Method, 5}, + {"(*Nil).Parent", Method, 5}, + {"(*Nil).Pkg", Method, 5}, + {"(*Nil).Pos", Method, 5}, + {"(*Nil).String", Method, 5}, + {"(*Nil).Type", Method, 5}, + {"(*Package).Complete", Method, 5}, + {"(*Package).GoVersion", Method, 21}, + {"(*Package).Imports", Method, 5}, + {"(*Package).MarkComplete", Method, 5}, + {"(*Package).Name", Method, 5}, + {"(*Package).Path", Method, 5}, + {"(*Package).Scope", Method, 5}, + {"(*Package).SetImports", Method, 5}, + {"(*Package).SetName", Method, 6}, + {"(*Package).String", Method, 5}, + {"(*PkgName).Exported", Method, 5}, + {"(*PkgName).Id", Method, 5}, + {"(*PkgName).Imported", Method, 5}, + {"(*PkgName).Name", Method, 5}, + {"(*PkgName).Parent", Method, 5}, + {"(*PkgName).Pkg", Method, 5}, + {"(*PkgName).Pos", Method, 5}, + {"(*PkgName).String", Method, 5}, + {"(*PkgName).Type", Method, 5}, + {"(*Pointer).Elem", Method, 5}, + {"(*Pointer).String", Method, 5}, + {"(*Pointer).Underlying", Method, 5}, + {"(*Scope).Child", Method, 5}, + {"(*Scope).Contains", Method, 5}, + {"(*Scope).End", Method, 5}, + {"(*Scope).Innermost", Method, 5}, + {"(*Scope).Insert", Method, 5}, + {"(*Scope).Len", Method, 5}, + {"(*Scope).Lookup", Method, 5}, + {"(*Scope).LookupParent", Method, 5}, + {"(*Scope).Names", Method, 5}, + {"(*Scope).NumChildren", Method, 5}, + {"(*Scope).Parent", Method, 5}, + {"(*Scope).Pos", Method, 5}, + {"(*Scope).String", Method, 5}, + {"(*Scope).WriteTo", Method, 5}, + {"(*Selection).Index", Method, 5}, + {"(*Selection).Indirect", Method, 5}, + {"(*Selection).Kind", Method, 5}, + {"(*Selection).Obj", Method, 5}, + {"(*Selection).Recv", Method, 5}, + {"(*Selection).String", Method, 5}, + {"(*Selection).Type", Method, 5}, + {"(*Signature).Params", Method, 5}, + {"(*Signature).Recv", Method, 5}, + {"(*Signature).RecvTypeParams", Method, 18}, + {"(*Signature).Results", Method, 5}, + {"(*Signature).String", Method, 5}, + {"(*Signature).TypeParams", Method, 18}, + {"(*Signature).Underlying", Method, 5}, + {"(*Signature).Variadic", Method, 5}, + {"(*Slice).Elem", Method, 5}, + {"(*Slice).String", Method, 5}, + {"(*Slice).Underlying", Method, 5}, + {"(*StdSizes).Alignof", Method, 5}, + {"(*StdSizes).Offsetsof", Method, 5}, + {"(*StdSizes).Sizeof", Method, 5}, + {"(*Struct).Field", Method, 5}, + {"(*Struct).NumFields", Method, 5}, + {"(*Struct).String", Method, 5}, + {"(*Struct).Tag", Method, 5}, + {"(*Struct).Underlying", Method, 5}, + {"(*Term).String", Method, 18}, + {"(*Term).Tilde", Method, 18}, + {"(*Term).Type", Method, 18}, + {"(*Tuple).At", Method, 5}, + {"(*Tuple).Len", Method, 5}, + {"(*Tuple).String", Method, 5}, + {"(*Tuple).Underlying", Method, 5}, + {"(*TypeList).At", Method, 18}, + {"(*TypeList).Len", Method, 18}, + {"(*TypeName).Exported", Method, 5}, + {"(*TypeName).Id", Method, 5}, + {"(*TypeName).IsAlias", Method, 9}, + {"(*TypeName).Name", Method, 5}, + {"(*TypeName).Parent", Method, 5}, + {"(*TypeName).Pkg", Method, 5}, + {"(*TypeName).Pos", Method, 5}, + {"(*TypeName).String", Method, 5}, + {"(*TypeName).Type", Method, 5}, + {"(*TypeParam).Constraint", Method, 18}, + {"(*TypeParam).Index", Method, 18}, + {"(*TypeParam).Obj", Method, 18}, + {"(*TypeParam).SetConstraint", Method, 18}, + {"(*TypeParam).String", Method, 18}, + {"(*TypeParam).Underlying", Method, 18}, + {"(*TypeParamList).At", Method, 18}, + {"(*TypeParamList).Len", Method, 18}, + {"(*Union).Len", Method, 18}, + {"(*Union).String", Method, 18}, + {"(*Union).Term", Method, 18}, + {"(*Union).Underlying", Method, 18}, + {"(*Var).Anonymous", Method, 5}, + {"(*Var).Embedded", Method, 11}, + {"(*Var).Exported", Method, 5}, + {"(*Var).Id", Method, 5}, + {"(*Var).IsField", Method, 5}, + {"(*Var).Name", Method, 5}, + {"(*Var).Origin", Method, 19}, + {"(*Var).Parent", Method, 5}, + {"(*Var).Pkg", Method, 5}, + {"(*Var).Pos", Method, 5}, + {"(*Var).String", Method, 5}, + {"(*Var).Type", Method, 5}, + {"(Checker).ObjectOf", Method, 5}, + {"(Checker).PkgNameOf", Method, 22}, + {"(Checker).TypeOf", Method, 5}, + {"(Error).Error", Method, 5}, + {"(TypeAndValue).Addressable", Method, 5}, + {"(TypeAndValue).Assignable", Method, 5}, + {"(TypeAndValue).HasOk", Method, 5}, + {"(TypeAndValue).IsBuiltin", Method, 5}, + {"(TypeAndValue).IsNil", Method, 5}, + {"(TypeAndValue).IsType", Method, 5}, + {"(TypeAndValue).IsValue", Method, 5}, + {"(TypeAndValue).IsVoid", Method, 5}, + {"Alias", Type, 22}, + {"ArgumentError", Type, 18}, + {"ArgumentError.Err", Field, 18}, + {"ArgumentError.Index", Field, 18}, + {"Array", Type, 5}, + {"AssertableTo", Func, 5}, + {"AssignableTo", Func, 5}, + {"Basic", Type, 5}, + {"BasicInfo", Type, 5}, + {"BasicKind", Type, 5}, + {"Bool", Const, 5}, + {"Builtin", Type, 5}, + {"Byte", Const, 5}, + {"Chan", Type, 5}, + {"ChanDir", Type, 5}, + {"CheckExpr", Func, 13}, + {"Checker", Type, 5}, + {"Checker.Info", Field, 5}, + {"Comparable", Func, 5}, + {"Complex128", Const, 5}, + {"Complex64", Const, 5}, + {"Config", Type, 5}, + {"Config.Context", Field, 18}, + {"Config.DisableUnusedImportCheck", Field, 5}, + {"Config.Error", Field, 5}, + {"Config.FakeImportC", Field, 5}, + {"Config.GoVersion", Field, 18}, + {"Config.IgnoreFuncBodies", Field, 5}, + {"Config.Importer", Field, 5}, + {"Config.Sizes", Field, 5}, + {"Const", Type, 5}, + {"Context", Type, 18}, + {"ConvertibleTo", Func, 5}, + {"DefPredeclaredTestFuncs", Func, 5}, + {"Default", Func, 8}, + {"Error", Type, 5}, + {"Error.Fset", Field, 5}, + {"Error.Msg", Field, 5}, + {"Error.Pos", Field, 5}, + {"Error.Soft", Field, 5}, + {"Eval", Func, 5}, + {"ExprString", Func, 5}, + {"FieldVal", Const, 5}, + {"Float32", Const, 5}, + {"Float64", Const, 5}, + {"Func", Type, 5}, + {"Id", Func, 5}, + {"Identical", Func, 5}, + {"IdenticalIgnoreTags", Func, 8}, + {"Implements", Func, 5}, + {"ImportMode", Type, 6}, + {"Importer", Type, 5}, + {"ImporterFrom", Type, 6}, + {"Info", Type, 5}, + {"Info.Defs", Field, 5}, + {"Info.FileVersions", Field, 22}, + {"Info.Implicits", Field, 5}, + {"Info.InitOrder", Field, 5}, + {"Info.Instances", Field, 18}, + {"Info.Scopes", Field, 5}, + {"Info.Selections", Field, 5}, + {"Info.Types", Field, 5}, + {"Info.Uses", Field, 5}, + {"Initializer", Type, 5}, + {"Initializer.Lhs", Field, 5}, + {"Initializer.Rhs", Field, 5}, + {"Instance", Type, 18}, + {"Instance.Type", Field, 18}, + {"Instance.TypeArgs", Field, 18}, + {"Instantiate", Func, 18}, + {"Int", Const, 5}, + {"Int16", Const, 5}, + {"Int32", Const, 5}, + {"Int64", Const, 5}, + {"Int8", Const, 5}, + {"Interface", Type, 5}, + {"Invalid", Const, 5}, + {"IsBoolean", Const, 5}, + {"IsComplex", Const, 5}, + {"IsConstType", Const, 5}, + {"IsFloat", Const, 5}, + {"IsInteger", Const, 5}, + {"IsInterface", Func, 5}, + {"IsNumeric", Const, 5}, + {"IsOrdered", Const, 5}, + {"IsString", Const, 5}, + {"IsUnsigned", Const, 5}, + {"IsUntyped", Const, 5}, + {"Label", Type, 5}, + {"LookupFieldOrMethod", Func, 5}, + {"Map", Type, 5}, + {"MethodExpr", Const, 5}, + {"MethodSet", Type, 5}, + {"MethodVal", Const, 5}, + {"MissingMethod", Func, 5}, + {"Named", Type, 5}, + {"NewAlias", Func, 22}, + {"NewArray", Func, 5}, + {"NewChan", Func, 5}, + {"NewChecker", Func, 5}, + {"NewConst", Func, 5}, + {"NewContext", Func, 18}, + {"NewField", Func, 5}, + {"NewFunc", Func, 5}, + {"NewInterface", Func, 5}, + {"NewInterfaceType", Func, 11}, + {"NewLabel", Func, 5}, + {"NewMap", Func, 5}, + {"NewMethodSet", Func, 5}, + {"NewNamed", Func, 5}, + {"NewPackage", Func, 5}, + {"NewParam", Func, 5}, + {"NewPkgName", Func, 5}, + {"NewPointer", Func, 5}, + {"NewScope", Func, 5}, + {"NewSignature", Func, 5}, + {"NewSignatureType", Func, 18}, + {"NewSlice", Func, 5}, + {"NewStruct", Func, 5}, + {"NewTerm", Func, 18}, + {"NewTuple", Func, 5}, + {"NewTypeName", Func, 5}, + {"NewTypeParam", Func, 18}, + {"NewUnion", Func, 18}, + {"NewVar", Func, 5}, + {"Nil", Type, 5}, + {"Object", Type, 5}, + {"ObjectString", Func, 5}, + {"Package", Type, 5}, + {"PkgName", Type, 5}, + {"Pointer", Type, 5}, + {"Qualifier", Type, 5}, + {"RecvOnly", Const, 5}, + {"RelativeTo", Func, 5}, + {"Rune", Const, 5}, + {"Satisfies", Func, 20}, + {"Scope", Type, 5}, + {"Selection", Type, 5}, + {"SelectionKind", Type, 5}, + {"SelectionString", Func, 5}, + {"SendOnly", Const, 5}, + {"SendRecv", Const, 5}, + {"Signature", Type, 5}, + {"Sizes", Type, 5}, + {"SizesFor", Func, 9}, + {"Slice", Type, 5}, + {"StdSizes", Type, 5}, + {"StdSizes.MaxAlign", Field, 5}, + {"StdSizes.WordSize", Field, 5}, + {"String", Const, 5}, + {"Struct", Type, 5}, + {"Term", Type, 18}, + {"Tuple", Type, 5}, + {"Typ", Var, 5}, + {"Type", Type, 5}, + {"TypeAndValue", Type, 5}, + {"TypeAndValue.Type", Field, 5}, + {"TypeAndValue.Value", Field, 5}, + {"TypeList", Type, 18}, + {"TypeName", Type, 5}, + {"TypeParam", Type, 18}, + {"TypeParamList", Type, 18}, + {"TypeString", Func, 5}, + {"Uint", Const, 5}, + {"Uint16", Const, 5}, + {"Uint32", Const, 5}, + {"Uint64", Const, 5}, + {"Uint8", Const, 5}, + {"Uintptr", Const, 5}, + {"Unalias", Func, 22}, + {"Union", Type, 18}, + {"Universe", Var, 5}, + {"Unsafe", Var, 5}, + {"UnsafePointer", Const, 5}, + {"UntypedBool", Const, 5}, + {"UntypedComplex", Const, 5}, + {"UntypedFloat", Const, 5}, + {"UntypedInt", Const, 5}, + {"UntypedNil", Const, 5}, + {"UntypedRune", Const, 5}, + {"UntypedString", Const, 5}, + {"Var", Type, 5}, + {"WriteExpr", Func, 5}, + {"WriteSignature", Func, 5}, + {"WriteType", Func, 5}, + }, + "go/version": { + {"Compare", Func, 22}, + {"IsValid", Func, 22}, + {"Lang", Func, 22}, + }, + "hash": { + {"Hash", Type, 0}, + {"Hash32", Type, 0}, + {"Hash64", Type, 0}, + }, + "hash/adler32": { + {"Checksum", Func, 0}, + {"New", Func, 0}, + {"Size", Const, 0}, + }, + "hash/crc32": { + {"Castagnoli", Const, 0}, + {"Checksum", Func, 0}, + {"ChecksumIEEE", Func, 0}, + {"IEEE", Const, 0}, + {"IEEETable", Var, 0}, + {"Koopman", Const, 0}, + {"MakeTable", Func, 0}, + {"New", Func, 0}, + {"NewIEEE", Func, 0}, + {"Size", Const, 0}, + {"Table", Type, 0}, + {"Update", Func, 0}, + }, + "hash/crc64": { + {"Checksum", Func, 0}, + {"ECMA", Const, 0}, + {"ISO", Const, 0}, + {"MakeTable", Func, 0}, + {"New", Func, 0}, + {"Size", Const, 0}, + {"Table", Type, 0}, + {"Update", Func, 0}, + }, + "hash/fnv": { + {"New128", Func, 9}, + {"New128a", Func, 9}, + {"New32", Func, 0}, + {"New32a", Func, 0}, + {"New64", Func, 0}, + {"New64a", Func, 0}, + }, + "hash/maphash": { + {"(*Hash).BlockSize", Method, 14}, + {"(*Hash).Reset", Method, 14}, + {"(*Hash).Seed", Method, 14}, + {"(*Hash).SetSeed", Method, 14}, + {"(*Hash).Size", Method, 14}, + {"(*Hash).Sum", Method, 14}, + {"(*Hash).Sum64", Method, 14}, + {"(*Hash).Write", Method, 14}, + {"(*Hash).WriteByte", Method, 14}, + {"(*Hash).WriteString", Method, 14}, + {"Bytes", Func, 19}, + {"Hash", Type, 14}, + {"MakeSeed", Func, 14}, + {"Seed", Type, 14}, + {"String", Func, 19}, + }, + "html": { + {"EscapeString", Func, 0}, + {"UnescapeString", Func, 0}, + }, + "html/template": { + {"(*Error).Error", Method, 0}, + {"(*Template).AddParseTree", Method, 0}, + {"(*Template).Clone", Method, 0}, + {"(*Template).DefinedTemplates", Method, 6}, + {"(*Template).Delims", Method, 0}, + {"(*Template).Execute", Method, 0}, + {"(*Template).ExecuteTemplate", Method, 0}, + {"(*Template).Funcs", Method, 0}, + {"(*Template).Lookup", Method, 0}, + {"(*Template).Name", Method, 0}, + {"(*Template).New", Method, 0}, + {"(*Template).Option", Method, 5}, + {"(*Template).Parse", Method, 0}, + {"(*Template).ParseFS", Method, 16}, + {"(*Template).ParseFiles", Method, 0}, + {"(*Template).ParseGlob", Method, 0}, + {"(*Template).Templates", Method, 0}, + {"CSS", Type, 0}, + {"ErrAmbigContext", Const, 0}, + {"ErrBadHTML", Const, 0}, + {"ErrBranchEnd", Const, 0}, + {"ErrEndContext", Const, 0}, + {"ErrJSTemplate", Const, 21}, + {"ErrNoSuchTemplate", Const, 0}, + {"ErrOutputContext", Const, 0}, + {"ErrPartialCharset", Const, 0}, + {"ErrPartialEscape", Const, 0}, + {"ErrPredefinedEscaper", Const, 9}, + {"ErrRangeLoopReentry", Const, 0}, + {"ErrSlashAmbig", Const, 0}, + {"Error", Type, 0}, + {"Error.Description", Field, 0}, + {"Error.ErrorCode", Field, 0}, + {"Error.Line", Field, 0}, + {"Error.Name", Field, 0}, + {"Error.Node", Field, 4}, + {"ErrorCode", Type, 0}, + {"FuncMap", Type, 0}, + {"HTML", Type, 0}, + {"HTMLAttr", Type, 0}, + {"HTMLEscape", Func, 0}, + {"HTMLEscapeString", Func, 0}, + {"HTMLEscaper", Func, 0}, + {"IsTrue", Func, 6}, + {"JS", Type, 0}, + {"JSEscape", Func, 0}, + {"JSEscapeString", Func, 0}, + {"JSEscaper", Func, 0}, + {"JSStr", Type, 0}, + {"Must", Func, 0}, + {"New", Func, 0}, + {"OK", Const, 0}, + {"ParseFS", Func, 16}, + {"ParseFiles", Func, 0}, + {"ParseGlob", Func, 0}, + {"Srcset", Type, 10}, + {"Template", Type, 0}, + {"Template.Tree", Field, 2}, + {"URL", Type, 0}, + {"URLQueryEscaper", Func, 0}, + }, + "image": { + {"(*Alpha).AlphaAt", Method, 4}, + {"(*Alpha).At", Method, 0}, + {"(*Alpha).Bounds", Method, 0}, + {"(*Alpha).ColorModel", Method, 0}, + {"(*Alpha).Opaque", Method, 0}, + {"(*Alpha).PixOffset", Method, 0}, + {"(*Alpha).RGBA64At", Method, 17}, + {"(*Alpha).Set", Method, 0}, + {"(*Alpha).SetAlpha", Method, 0}, + {"(*Alpha).SetRGBA64", Method, 17}, + {"(*Alpha).SubImage", Method, 0}, + {"(*Alpha16).Alpha16At", Method, 4}, + {"(*Alpha16).At", Method, 0}, + {"(*Alpha16).Bounds", Method, 0}, + {"(*Alpha16).ColorModel", Method, 0}, + {"(*Alpha16).Opaque", Method, 0}, + {"(*Alpha16).PixOffset", Method, 0}, + {"(*Alpha16).RGBA64At", Method, 17}, + {"(*Alpha16).Set", Method, 0}, + {"(*Alpha16).SetAlpha16", Method, 0}, + {"(*Alpha16).SetRGBA64", Method, 17}, + {"(*Alpha16).SubImage", Method, 0}, + {"(*CMYK).At", Method, 5}, + {"(*CMYK).Bounds", Method, 5}, + {"(*CMYK).CMYKAt", Method, 5}, + {"(*CMYK).ColorModel", Method, 5}, + {"(*CMYK).Opaque", Method, 5}, + {"(*CMYK).PixOffset", Method, 5}, + {"(*CMYK).RGBA64At", Method, 17}, + {"(*CMYK).Set", Method, 5}, + {"(*CMYK).SetCMYK", Method, 5}, + {"(*CMYK).SetRGBA64", Method, 17}, + {"(*CMYK).SubImage", Method, 5}, + {"(*Gray).At", Method, 0}, + {"(*Gray).Bounds", Method, 0}, + {"(*Gray).ColorModel", Method, 0}, + {"(*Gray).GrayAt", Method, 4}, + {"(*Gray).Opaque", Method, 0}, + {"(*Gray).PixOffset", Method, 0}, + {"(*Gray).RGBA64At", Method, 17}, + {"(*Gray).Set", Method, 0}, + {"(*Gray).SetGray", Method, 0}, + {"(*Gray).SetRGBA64", Method, 17}, + {"(*Gray).SubImage", Method, 0}, + {"(*Gray16).At", Method, 0}, + {"(*Gray16).Bounds", Method, 0}, + {"(*Gray16).ColorModel", Method, 0}, + {"(*Gray16).Gray16At", Method, 4}, + {"(*Gray16).Opaque", Method, 0}, + {"(*Gray16).PixOffset", Method, 0}, + {"(*Gray16).RGBA64At", Method, 17}, + {"(*Gray16).Set", Method, 0}, + {"(*Gray16).SetGray16", Method, 0}, + {"(*Gray16).SetRGBA64", Method, 17}, + {"(*Gray16).SubImage", Method, 0}, + {"(*NRGBA).At", Method, 0}, + {"(*NRGBA).Bounds", Method, 0}, + {"(*NRGBA).ColorModel", Method, 0}, + {"(*NRGBA).NRGBAAt", Method, 4}, + {"(*NRGBA).Opaque", Method, 0}, + {"(*NRGBA).PixOffset", Method, 0}, + {"(*NRGBA).RGBA64At", Method, 17}, + {"(*NRGBA).Set", Method, 0}, + {"(*NRGBA).SetNRGBA", Method, 0}, + {"(*NRGBA).SetRGBA64", Method, 17}, + {"(*NRGBA).SubImage", Method, 0}, + {"(*NRGBA64).At", Method, 0}, + {"(*NRGBA64).Bounds", Method, 0}, + {"(*NRGBA64).ColorModel", Method, 0}, + {"(*NRGBA64).NRGBA64At", Method, 4}, + {"(*NRGBA64).Opaque", Method, 0}, + {"(*NRGBA64).PixOffset", Method, 0}, + {"(*NRGBA64).RGBA64At", Method, 17}, + {"(*NRGBA64).Set", Method, 0}, + {"(*NRGBA64).SetNRGBA64", Method, 0}, + {"(*NRGBA64).SetRGBA64", Method, 17}, + {"(*NRGBA64).SubImage", Method, 0}, + {"(*NYCbCrA).AOffset", Method, 6}, + {"(*NYCbCrA).At", Method, 6}, + {"(*NYCbCrA).Bounds", Method, 6}, + {"(*NYCbCrA).COffset", Method, 6}, + {"(*NYCbCrA).ColorModel", Method, 6}, + {"(*NYCbCrA).NYCbCrAAt", Method, 6}, + {"(*NYCbCrA).Opaque", Method, 6}, + {"(*NYCbCrA).RGBA64At", Method, 17}, + {"(*NYCbCrA).SubImage", Method, 6}, + {"(*NYCbCrA).YCbCrAt", Method, 6}, + {"(*NYCbCrA).YOffset", Method, 6}, + {"(*Paletted).At", Method, 0}, + {"(*Paletted).Bounds", Method, 0}, + {"(*Paletted).ColorIndexAt", Method, 0}, + {"(*Paletted).ColorModel", Method, 0}, + {"(*Paletted).Opaque", Method, 0}, + {"(*Paletted).PixOffset", Method, 0}, + {"(*Paletted).RGBA64At", Method, 17}, + {"(*Paletted).Set", Method, 0}, + {"(*Paletted).SetColorIndex", Method, 0}, + {"(*Paletted).SetRGBA64", Method, 17}, + {"(*Paletted).SubImage", Method, 0}, + {"(*RGBA).At", Method, 0}, + {"(*RGBA).Bounds", Method, 0}, + {"(*RGBA).ColorModel", Method, 0}, + {"(*RGBA).Opaque", Method, 0}, + {"(*RGBA).PixOffset", Method, 0}, + {"(*RGBA).RGBA64At", Method, 17}, + {"(*RGBA).RGBAAt", Method, 4}, + {"(*RGBA).Set", Method, 0}, + {"(*RGBA).SetRGBA", Method, 0}, + {"(*RGBA).SetRGBA64", Method, 17}, + {"(*RGBA).SubImage", Method, 0}, + {"(*RGBA64).At", Method, 0}, + {"(*RGBA64).Bounds", Method, 0}, + {"(*RGBA64).ColorModel", Method, 0}, + {"(*RGBA64).Opaque", Method, 0}, + {"(*RGBA64).PixOffset", Method, 0}, + {"(*RGBA64).RGBA64At", Method, 4}, + {"(*RGBA64).Set", Method, 0}, + {"(*RGBA64).SetRGBA64", Method, 0}, + {"(*RGBA64).SubImage", Method, 0}, + {"(*Uniform).At", Method, 0}, + {"(*Uniform).Bounds", Method, 0}, + {"(*Uniform).ColorModel", Method, 0}, + {"(*Uniform).Convert", Method, 0}, + {"(*Uniform).Opaque", Method, 0}, + {"(*Uniform).RGBA", Method, 0}, + {"(*Uniform).RGBA64At", Method, 17}, + {"(*YCbCr).At", Method, 0}, + {"(*YCbCr).Bounds", Method, 0}, + {"(*YCbCr).COffset", Method, 0}, + {"(*YCbCr).ColorModel", Method, 0}, + {"(*YCbCr).Opaque", Method, 0}, + {"(*YCbCr).RGBA64At", Method, 17}, + {"(*YCbCr).SubImage", Method, 0}, + {"(*YCbCr).YCbCrAt", Method, 4}, + {"(*YCbCr).YOffset", Method, 0}, + {"(Point).Add", Method, 0}, + {"(Point).Div", Method, 0}, + {"(Point).Eq", Method, 0}, + {"(Point).In", Method, 0}, + {"(Point).Mod", Method, 0}, + {"(Point).Mul", Method, 0}, + {"(Point).String", Method, 0}, + {"(Point).Sub", Method, 0}, + {"(Rectangle).Add", Method, 0}, + {"(Rectangle).At", Method, 5}, + {"(Rectangle).Bounds", Method, 5}, + {"(Rectangle).Canon", Method, 0}, + {"(Rectangle).ColorModel", Method, 5}, + {"(Rectangle).Dx", Method, 0}, + {"(Rectangle).Dy", Method, 0}, + {"(Rectangle).Empty", Method, 0}, + {"(Rectangle).Eq", Method, 0}, + {"(Rectangle).In", Method, 0}, + {"(Rectangle).Inset", Method, 0}, + {"(Rectangle).Intersect", Method, 0}, + {"(Rectangle).Overlaps", Method, 0}, + {"(Rectangle).RGBA64At", Method, 17}, + {"(Rectangle).Size", Method, 0}, + {"(Rectangle).String", Method, 0}, + {"(Rectangle).Sub", Method, 0}, + {"(Rectangle).Union", Method, 0}, + {"(YCbCrSubsampleRatio).String", Method, 0}, + {"Alpha", Type, 0}, + {"Alpha.Pix", Field, 0}, + {"Alpha.Rect", Field, 0}, + {"Alpha.Stride", Field, 0}, + {"Alpha16", Type, 0}, + {"Alpha16.Pix", Field, 0}, + {"Alpha16.Rect", Field, 0}, + {"Alpha16.Stride", Field, 0}, + {"Black", Var, 0}, + {"CMYK", Type, 5}, + {"CMYK.Pix", Field, 5}, + {"CMYK.Rect", Field, 5}, + {"CMYK.Stride", Field, 5}, + {"Config", Type, 0}, + {"Config.ColorModel", Field, 0}, + {"Config.Height", Field, 0}, + {"Config.Width", Field, 0}, + {"Decode", Func, 0}, + {"DecodeConfig", Func, 0}, + {"ErrFormat", Var, 0}, + {"Gray", Type, 0}, + {"Gray.Pix", Field, 0}, + {"Gray.Rect", Field, 0}, + {"Gray.Stride", Field, 0}, + {"Gray16", Type, 0}, + {"Gray16.Pix", Field, 0}, + {"Gray16.Rect", Field, 0}, + {"Gray16.Stride", Field, 0}, + {"Image", Type, 0}, + {"NRGBA", Type, 0}, + {"NRGBA.Pix", Field, 0}, + {"NRGBA.Rect", Field, 0}, + {"NRGBA.Stride", Field, 0}, + {"NRGBA64", Type, 0}, + {"NRGBA64.Pix", Field, 0}, + {"NRGBA64.Rect", Field, 0}, + {"NRGBA64.Stride", Field, 0}, + {"NYCbCrA", Type, 6}, + {"NYCbCrA.A", Field, 6}, + {"NYCbCrA.AStride", Field, 6}, + {"NYCbCrA.YCbCr", Field, 6}, + {"NewAlpha", Func, 0}, + {"NewAlpha16", Func, 0}, + {"NewCMYK", Func, 5}, + {"NewGray", Func, 0}, + {"NewGray16", Func, 0}, + {"NewNRGBA", Func, 0}, + {"NewNRGBA64", Func, 0}, + {"NewNYCbCrA", Func, 6}, + {"NewPaletted", Func, 0}, + {"NewRGBA", Func, 0}, + {"NewRGBA64", Func, 0}, + {"NewUniform", Func, 0}, + {"NewYCbCr", Func, 0}, + {"Opaque", Var, 0}, + {"Paletted", Type, 0}, + {"Paletted.Palette", Field, 0}, + {"Paletted.Pix", Field, 0}, + {"Paletted.Rect", Field, 0}, + {"Paletted.Stride", Field, 0}, + {"PalettedImage", Type, 0}, + {"Point", Type, 0}, + {"Point.X", Field, 0}, + {"Point.Y", Field, 0}, + {"Pt", Func, 0}, + {"RGBA", Type, 0}, + {"RGBA.Pix", Field, 0}, + {"RGBA.Rect", Field, 0}, + {"RGBA.Stride", Field, 0}, + {"RGBA64", Type, 0}, + {"RGBA64.Pix", Field, 0}, + {"RGBA64.Rect", Field, 0}, + {"RGBA64.Stride", Field, 0}, + {"RGBA64Image", Type, 17}, + {"Rect", Func, 0}, + {"Rectangle", Type, 0}, + {"Rectangle.Max", Field, 0}, + {"Rectangle.Min", Field, 0}, + {"RegisterFormat", Func, 0}, + {"Transparent", Var, 0}, + {"Uniform", Type, 0}, + {"Uniform.C", Field, 0}, + {"White", Var, 0}, + {"YCbCr", Type, 0}, + {"YCbCr.CStride", Field, 0}, + {"YCbCr.Cb", Field, 0}, + {"YCbCr.Cr", Field, 0}, + {"YCbCr.Rect", Field, 0}, + {"YCbCr.SubsampleRatio", Field, 0}, + {"YCbCr.Y", Field, 0}, + {"YCbCr.YStride", Field, 0}, + {"YCbCrSubsampleRatio", Type, 0}, + {"YCbCrSubsampleRatio410", Const, 5}, + {"YCbCrSubsampleRatio411", Const, 5}, + {"YCbCrSubsampleRatio420", Const, 0}, + {"YCbCrSubsampleRatio422", Const, 0}, + {"YCbCrSubsampleRatio440", Const, 1}, + {"YCbCrSubsampleRatio444", Const, 0}, + {"ZP", Var, 0}, + {"ZR", Var, 0}, + }, + "image/color": { + {"(Alpha).RGBA", Method, 0}, + {"(Alpha16).RGBA", Method, 0}, + {"(CMYK).RGBA", Method, 5}, + {"(Gray).RGBA", Method, 0}, + {"(Gray16).RGBA", Method, 0}, + {"(NRGBA).RGBA", Method, 0}, + {"(NRGBA64).RGBA", Method, 0}, + {"(NYCbCrA).RGBA", Method, 6}, + {"(Palette).Convert", Method, 0}, + {"(Palette).Index", Method, 0}, + {"(RGBA).RGBA", Method, 0}, + {"(RGBA64).RGBA", Method, 0}, + {"(YCbCr).RGBA", Method, 0}, + {"Alpha", Type, 0}, + {"Alpha.A", Field, 0}, + {"Alpha16", Type, 0}, + {"Alpha16.A", Field, 0}, + {"Alpha16Model", Var, 0}, + {"AlphaModel", Var, 0}, + {"Black", Var, 0}, + {"CMYK", Type, 5}, + {"CMYK.C", Field, 5}, + {"CMYK.K", Field, 5}, + {"CMYK.M", Field, 5}, + {"CMYK.Y", Field, 5}, + {"CMYKModel", Var, 5}, + {"CMYKToRGB", Func, 5}, + {"Color", Type, 0}, + {"Gray", Type, 0}, + {"Gray.Y", Field, 0}, + {"Gray16", Type, 0}, + {"Gray16.Y", Field, 0}, + {"Gray16Model", Var, 0}, + {"GrayModel", Var, 0}, + {"Model", Type, 0}, + {"ModelFunc", Func, 0}, + {"NRGBA", Type, 0}, + {"NRGBA.A", Field, 0}, + {"NRGBA.B", Field, 0}, + {"NRGBA.G", Field, 0}, + {"NRGBA.R", Field, 0}, + {"NRGBA64", Type, 0}, + {"NRGBA64.A", Field, 0}, + {"NRGBA64.B", Field, 0}, + {"NRGBA64.G", Field, 0}, + {"NRGBA64.R", Field, 0}, + {"NRGBA64Model", Var, 0}, + {"NRGBAModel", Var, 0}, + {"NYCbCrA", Type, 6}, + {"NYCbCrA.A", Field, 6}, + {"NYCbCrA.YCbCr", Field, 6}, + {"NYCbCrAModel", Var, 6}, + {"Opaque", Var, 0}, + {"Palette", Type, 0}, + {"RGBA", Type, 0}, + {"RGBA.A", Field, 0}, + {"RGBA.B", Field, 0}, + {"RGBA.G", Field, 0}, + {"RGBA.R", Field, 0}, + {"RGBA64", Type, 0}, + {"RGBA64.A", Field, 0}, + {"RGBA64.B", Field, 0}, + {"RGBA64.G", Field, 0}, + {"RGBA64.R", Field, 0}, + {"RGBA64Model", Var, 0}, + {"RGBAModel", Var, 0}, + {"RGBToCMYK", Func, 5}, + {"RGBToYCbCr", Func, 0}, + {"Transparent", Var, 0}, + {"White", Var, 0}, + {"YCbCr", Type, 0}, + {"YCbCr.Cb", Field, 0}, + {"YCbCr.Cr", Field, 0}, + {"YCbCr.Y", Field, 0}, + {"YCbCrModel", Var, 0}, + {"YCbCrToRGB", Func, 0}, + }, + "image/color/palette": { + {"Plan9", Var, 2}, + {"WebSafe", Var, 2}, + }, + "image/draw": { + {"(Op).Draw", Method, 2}, + {"Draw", Func, 0}, + {"DrawMask", Func, 0}, + {"Drawer", Type, 2}, + {"FloydSteinberg", Var, 2}, + {"Image", Type, 0}, + {"Op", Type, 0}, + {"Over", Const, 0}, + {"Quantizer", Type, 2}, + {"RGBA64Image", Type, 17}, + {"Src", Const, 0}, + }, + "image/gif": { + {"Decode", Func, 0}, + {"DecodeAll", Func, 0}, + {"DecodeConfig", Func, 0}, + {"DisposalBackground", Const, 5}, + {"DisposalNone", Const, 5}, + {"DisposalPrevious", Const, 5}, + {"Encode", Func, 2}, + {"EncodeAll", Func, 2}, + {"GIF", Type, 0}, + {"GIF.BackgroundIndex", Field, 5}, + {"GIF.Config", Field, 5}, + {"GIF.Delay", Field, 0}, + {"GIF.Disposal", Field, 5}, + {"GIF.Image", Field, 0}, + {"GIF.LoopCount", Field, 0}, + {"Options", Type, 2}, + {"Options.Drawer", Field, 2}, + {"Options.NumColors", Field, 2}, + {"Options.Quantizer", Field, 2}, + }, + "image/jpeg": { + {"(FormatError).Error", Method, 0}, + {"(UnsupportedError).Error", Method, 0}, + {"Decode", Func, 0}, + {"DecodeConfig", Func, 0}, + {"DefaultQuality", Const, 0}, + {"Encode", Func, 0}, + {"FormatError", Type, 0}, + {"Options", Type, 0}, + {"Options.Quality", Field, 0}, + {"Reader", Type, 0}, + {"UnsupportedError", Type, 0}, + }, + "image/png": { + {"(*Encoder).Encode", Method, 4}, + {"(FormatError).Error", Method, 0}, + {"(UnsupportedError).Error", Method, 0}, + {"BestCompression", Const, 4}, + {"BestSpeed", Const, 4}, + {"CompressionLevel", Type, 4}, + {"Decode", Func, 0}, + {"DecodeConfig", Func, 0}, + {"DefaultCompression", Const, 4}, + {"Encode", Func, 0}, + {"Encoder", Type, 4}, + {"Encoder.BufferPool", Field, 9}, + {"Encoder.CompressionLevel", Field, 4}, + {"EncoderBuffer", Type, 9}, + {"EncoderBufferPool", Type, 9}, + {"FormatError", Type, 0}, + {"NoCompression", Const, 4}, + {"UnsupportedError", Type, 0}, + }, + "index/suffixarray": { + {"(*Index).Bytes", Method, 0}, + {"(*Index).FindAllIndex", Method, 0}, + {"(*Index).Lookup", Method, 0}, + {"(*Index).Read", Method, 0}, + {"(*Index).Write", Method, 0}, + {"Index", Type, 0}, + {"New", Func, 0}, + }, + "io": { + {"(*LimitedReader).Read", Method, 0}, + {"(*OffsetWriter).Seek", Method, 20}, + {"(*OffsetWriter).Write", Method, 20}, + {"(*OffsetWriter).WriteAt", Method, 20}, + {"(*PipeReader).Close", Method, 0}, + {"(*PipeReader).CloseWithError", Method, 0}, + {"(*PipeReader).Read", Method, 0}, + {"(*PipeWriter).Close", Method, 0}, + {"(*PipeWriter).CloseWithError", Method, 0}, + {"(*PipeWriter).Write", Method, 0}, + {"(*SectionReader).Outer", Method, 22}, + {"(*SectionReader).Read", Method, 0}, + {"(*SectionReader).ReadAt", Method, 0}, + {"(*SectionReader).Seek", Method, 0}, + {"(*SectionReader).Size", Method, 0}, + {"ByteReader", Type, 0}, + {"ByteScanner", Type, 0}, + {"ByteWriter", Type, 1}, + {"Closer", Type, 0}, + {"Copy", Func, 0}, + {"CopyBuffer", Func, 5}, + {"CopyN", Func, 0}, + {"Discard", Var, 16}, + {"EOF", Var, 0}, + {"ErrClosedPipe", Var, 0}, + {"ErrNoProgress", Var, 1}, + {"ErrShortBuffer", Var, 0}, + {"ErrShortWrite", Var, 0}, + {"ErrUnexpectedEOF", Var, 0}, + {"LimitReader", Func, 0}, + {"LimitedReader", Type, 0}, + {"LimitedReader.N", Field, 0}, + {"LimitedReader.R", Field, 0}, + {"MultiReader", Func, 0}, + {"MultiWriter", Func, 0}, + {"NewOffsetWriter", Func, 20}, + {"NewSectionReader", Func, 0}, + {"NopCloser", Func, 16}, + {"OffsetWriter", Type, 20}, + {"Pipe", Func, 0}, + {"PipeReader", Type, 0}, + {"PipeWriter", Type, 0}, + {"ReadAll", Func, 16}, + {"ReadAtLeast", Func, 0}, + {"ReadCloser", Type, 0}, + {"ReadFull", Func, 0}, + {"ReadSeekCloser", Type, 16}, + {"ReadSeeker", Type, 0}, + {"ReadWriteCloser", Type, 0}, + {"ReadWriteSeeker", Type, 0}, + {"ReadWriter", Type, 0}, + {"Reader", Type, 0}, + {"ReaderAt", Type, 0}, + {"ReaderFrom", Type, 0}, + {"RuneReader", Type, 0}, + {"RuneScanner", Type, 0}, + {"SectionReader", Type, 0}, + {"SeekCurrent", Const, 7}, + {"SeekEnd", Const, 7}, + {"SeekStart", Const, 7}, + {"Seeker", Type, 0}, + {"StringWriter", Type, 12}, + {"TeeReader", Func, 0}, + {"WriteCloser", Type, 0}, + {"WriteSeeker", Type, 0}, + {"WriteString", Func, 0}, + {"Writer", Type, 0}, + {"WriterAt", Type, 0}, + {"WriterTo", Type, 0}, + }, + "io/fs": { + {"(*PathError).Error", Method, 16}, + {"(*PathError).Timeout", Method, 16}, + {"(*PathError).Unwrap", Method, 16}, + {"(FileMode).IsDir", Method, 16}, + {"(FileMode).IsRegular", Method, 16}, + {"(FileMode).Perm", Method, 16}, + {"(FileMode).String", Method, 16}, + {"(FileMode).Type", Method, 16}, + {"DirEntry", Type, 16}, + {"ErrClosed", Var, 16}, + {"ErrExist", Var, 16}, + {"ErrInvalid", Var, 16}, + {"ErrNotExist", Var, 16}, + {"ErrPermission", Var, 16}, + {"FS", Type, 16}, + {"File", Type, 16}, + {"FileInfo", Type, 16}, + {"FileInfoToDirEntry", Func, 17}, + {"FileMode", Type, 16}, + {"FormatDirEntry", Func, 21}, + {"FormatFileInfo", Func, 21}, + {"Glob", Func, 16}, + {"GlobFS", Type, 16}, + {"ModeAppend", Const, 16}, + {"ModeCharDevice", Const, 16}, + {"ModeDevice", Const, 16}, + {"ModeDir", Const, 16}, + {"ModeExclusive", Const, 16}, + {"ModeIrregular", Const, 16}, + {"ModeNamedPipe", Const, 16}, + {"ModePerm", Const, 16}, + {"ModeSetgid", Const, 16}, + {"ModeSetuid", Const, 16}, + {"ModeSocket", Const, 16}, + {"ModeSticky", Const, 16}, + {"ModeSymlink", Const, 16}, + {"ModeTemporary", Const, 16}, + {"ModeType", Const, 16}, + {"PathError", Type, 16}, + {"PathError.Err", Field, 16}, + {"PathError.Op", Field, 16}, + {"PathError.Path", Field, 16}, + {"ReadDir", Func, 16}, + {"ReadDirFS", Type, 16}, + {"ReadDirFile", Type, 16}, + {"ReadFile", Func, 16}, + {"ReadFileFS", Type, 16}, + {"SkipAll", Var, 20}, + {"SkipDir", Var, 16}, + {"Stat", Func, 16}, + {"StatFS", Type, 16}, + {"Sub", Func, 16}, + {"SubFS", Type, 16}, + {"ValidPath", Func, 16}, + {"WalkDir", Func, 16}, + {"WalkDirFunc", Type, 16}, + }, + "io/ioutil": { + {"Discard", Var, 0}, + {"NopCloser", Func, 0}, + {"ReadAll", Func, 0}, + {"ReadDir", Func, 0}, + {"ReadFile", Func, 0}, + {"TempDir", Func, 0}, + {"TempFile", Func, 0}, + {"WriteFile", Func, 0}, + }, + "log": { + {"(*Logger).Fatal", Method, 0}, + {"(*Logger).Fatalf", Method, 0}, + {"(*Logger).Fatalln", Method, 0}, + {"(*Logger).Flags", Method, 0}, + {"(*Logger).Output", Method, 0}, + {"(*Logger).Panic", Method, 0}, + {"(*Logger).Panicf", Method, 0}, + {"(*Logger).Panicln", Method, 0}, + {"(*Logger).Prefix", Method, 0}, + {"(*Logger).Print", Method, 0}, + {"(*Logger).Printf", Method, 0}, + {"(*Logger).Println", Method, 0}, + {"(*Logger).SetFlags", Method, 0}, + {"(*Logger).SetOutput", Method, 5}, + {"(*Logger).SetPrefix", Method, 0}, + {"(*Logger).Writer", Method, 12}, + {"Default", Func, 16}, + {"Fatal", Func, 0}, + {"Fatalf", Func, 0}, + {"Fatalln", Func, 0}, + {"Flags", Func, 0}, + {"LUTC", Const, 5}, + {"Ldate", Const, 0}, + {"Llongfile", Const, 0}, + {"Lmicroseconds", Const, 0}, + {"Lmsgprefix", Const, 14}, + {"Logger", Type, 0}, + {"Lshortfile", Const, 0}, + {"LstdFlags", Const, 0}, + {"Ltime", Const, 0}, + {"New", Func, 0}, + {"Output", Func, 5}, + {"Panic", Func, 0}, + {"Panicf", Func, 0}, + {"Panicln", Func, 0}, + {"Prefix", Func, 0}, + {"Print", Func, 0}, + {"Printf", Func, 0}, + {"Println", Func, 0}, + {"SetFlags", Func, 0}, + {"SetOutput", Func, 0}, + {"SetPrefix", Func, 0}, + {"Writer", Func, 13}, + }, + "log/slog": { + {"(*JSONHandler).Enabled", Method, 21}, + {"(*JSONHandler).Handle", Method, 21}, + {"(*JSONHandler).WithAttrs", Method, 21}, + {"(*JSONHandler).WithGroup", Method, 21}, + {"(*Level).UnmarshalJSON", Method, 21}, + {"(*Level).UnmarshalText", Method, 21}, + {"(*LevelVar).Level", Method, 21}, + {"(*LevelVar).MarshalText", Method, 21}, + {"(*LevelVar).Set", Method, 21}, + {"(*LevelVar).String", Method, 21}, + {"(*LevelVar).UnmarshalText", Method, 21}, + {"(*Logger).Debug", Method, 21}, + {"(*Logger).DebugContext", Method, 21}, + {"(*Logger).Enabled", Method, 21}, + {"(*Logger).Error", Method, 21}, + {"(*Logger).ErrorContext", Method, 21}, + {"(*Logger).Handler", Method, 21}, + {"(*Logger).Info", Method, 21}, + {"(*Logger).InfoContext", Method, 21}, + {"(*Logger).Log", Method, 21}, + {"(*Logger).LogAttrs", Method, 21}, + {"(*Logger).Warn", Method, 21}, + {"(*Logger).WarnContext", Method, 21}, + {"(*Logger).With", Method, 21}, + {"(*Logger).WithGroup", Method, 21}, + {"(*Record).Add", Method, 21}, + {"(*Record).AddAttrs", Method, 21}, + {"(*TextHandler).Enabled", Method, 21}, + {"(*TextHandler).Handle", Method, 21}, + {"(*TextHandler).WithAttrs", Method, 21}, + {"(*TextHandler).WithGroup", Method, 21}, + {"(Attr).Equal", Method, 21}, + {"(Attr).String", Method, 21}, + {"(Kind).String", Method, 21}, + {"(Level).Level", Method, 21}, + {"(Level).MarshalJSON", Method, 21}, + {"(Level).MarshalText", Method, 21}, + {"(Level).String", Method, 21}, + {"(Record).Attrs", Method, 21}, + {"(Record).Clone", Method, 21}, + {"(Record).NumAttrs", Method, 21}, + {"(Value).Any", Method, 21}, + {"(Value).Bool", Method, 21}, + {"(Value).Duration", Method, 21}, + {"(Value).Equal", Method, 21}, + {"(Value).Float64", Method, 21}, + {"(Value).Group", Method, 21}, + {"(Value).Int64", Method, 21}, + {"(Value).Kind", Method, 21}, + {"(Value).LogValuer", Method, 21}, + {"(Value).Resolve", Method, 21}, + {"(Value).String", Method, 21}, + {"(Value).Time", Method, 21}, + {"(Value).Uint64", Method, 21}, + {"Any", Func, 21}, + {"AnyValue", Func, 21}, + {"Attr", Type, 21}, + {"Attr.Key", Field, 21}, + {"Attr.Value", Field, 21}, + {"Bool", Func, 21}, + {"BoolValue", Func, 21}, + {"Debug", Func, 21}, + {"DebugContext", Func, 21}, + {"Default", Func, 21}, + {"Duration", Func, 21}, + {"DurationValue", Func, 21}, + {"Error", Func, 21}, + {"ErrorContext", Func, 21}, + {"Float64", Func, 21}, + {"Float64Value", Func, 21}, + {"Group", Func, 21}, + {"GroupValue", Func, 21}, + {"Handler", Type, 21}, + {"HandlerOptions", Type, 21}, + {"HandlerOptions.AddSource", Field, 21}, + {"HandlerOptions.Level", Field, 21}, + {"HandlerOptions.ReplaceAttr", Field, 21}, + {"Info", Func, 21}, + {"InfoContext", Func, 21}, + {"Int", Func, 21}, + {"Int64", Func, 21}, + {"Int64Value", Func, 21}, + {"IntValue", Func, 21}, + {"JSONHandler", Type, 21}, + {"Kind", Type, 21}, + {"KindAny", Const, 21}, + {"KindBool", Const, 21}, + {"KindDuration", Const, 21}, + {"KindFloat64", Const, 21}, + {"KindGroup", Const, 21}, + {"KindInt64", Const, 21}, + {"KindLogValuer", Const, 21}, + {"KindString", Const, 21}, + {"KindTime", Const, 21}, + {"KindUint64", Const, 21}, + {"Level", Type, 21}, + {"LevelDebug", Const, 21}, + {"LevelError", Const, 21}, + {"LevelInfo", Const, 21}, + {"LevelKey", Const, 21}, + {"LevelVar", Type, 21}, + {"LevelWarn", Const, 21}, + {"Leveler", Type, 21}, + {"Log", Func, 21}, + {"LogAttrs", Func, 21}, + {"LogValuer", Type, 21}, + {"Logger", Type, 21}, + {"MessageKey", Const, 21}, + {"New", Func, 21}, + {"NewJSONHandler", Func, 21}, + {"NewLogLogger", Func, 21}, + {"NewRecord", Func, 21}, + {"NewTextHandler", Func, 21}, + {"Record", Type, 21}, + {"Record.Level", Field, 21}, + {"Record.Message", Field, 21}, + {"Record.PC", Field, 21}, + {"Record.Time", Field, 21}, + {"SetDefault", Func, 21}, + {"SetLogLoggerLevel", Func, 22}, + {"Source", Type, 21}, + {"Source.File", Field, 21}, + {"Source.Function", Field, 21}, + {"Source.Line", Field, 21}, + {"SourceKey", Const, 21}, + {"String", Func, 21}, + {"StringValue", Func, 21}, + {"TextHandler", Type, 21}, + {"Time", Func, 21}, + {"TimeKey", Const, 21}, + {"TimeValue", Func, 21}, + {"Uint64", Func, 21}, + {"Uint64Value", Func, 21}, + {"Value", Type, 21}, + {"Warn", Func, 21}, + {"WarnContext", Func, 21}, + {"With", Func, 21}, + }, + "log/syslog": { + {"(*Writer).Alert", Method, 0}, + {"(*Writer).Close", Method, 0}, + {"(*Writer).Crit", Method, 0}, + {"(*Writer).Debug", Method, 0}, + {"(*Writer).Emerg", Method, 0}, + {"(*Writer).Err", Method, 0}, + {"(*Writer).Info", Method, 0}, + {"(*Writer).Notice", Method, 0}, + {"(*Writer).Warning", Method, 0}, + {"(*Writer).Write", Method, 0}, + {"Dial", Func, 0}, + {"LOG_ALERT", Const, 0}, + {"LOG_AUTH", Const, 1}, + {"LOG_AUTHPRIV", Const, 1}, + {"LOG_CRIT", Const, 0}, + {"LOG_CRON", Const, 1}, + {"LOG_DAEMON", Const, 1}, + {"LOG_DEBUG", Const, 0}, + {"LOG_EMERG", Const, 0}, + {"LOG_ERR", Const, 0}, + {"LOG_FTP", Const, 1}, + {"LOG_INFO", Const, 0}, + {"LOG_KERN", Const, 1}, + {"LOG_LOCAL0", Const, 1}, + {"LOG_LOCAL1", Const, 1}, + {"LOG_LOCAL2", Const, 1}, + {"LOG_LOCAL3", Const, 1}, + {"LOG_LOCAL4", Const, 1}, + {"LOG_LOCAL5", Const, 1}, + {"LOG_LOCAL6", Const, 1}, + {"LOG_LOCAL7", Const, 1}, + {"LOG_LPR", Const, 1}, + {"LOG_MAIL", Const, 1}, + {"LOG_NEWS", Const, 1}, + {"LOG_NOTICE", Const, 0}, + {"LOG_SYSLOG", Const, 1}, + {"LOG_USER", Const, 1}, + {"LOG_UUCP", Const, 1}, + {"LOG_WARNING", Const, 0}, + {"New", Func, 0}, + {"NewLogger", Func, 0}, + {"Priority", Type, 0}, + {"Writer", Type, 0}, + }, + "maps": { + {"Clone", Func, 21}, + {"Copy", Func, 21}, + {"DeleteFunc", Func, 21}, + {"Equal", Func, 21}, + {"EqualFunc", Func, 21}, + }, + "math": { + {"Abs", Func, 0}, + {"Acos", Func, 0}, + {"Acosh", Func, 0}, + {"Asin", Func, 0}, + {"Asinh", Func, 0}, + {"Atan", Func, 0}, + {"Atan2", Func, 0}, + {"Atanh", Func, 0}, + {"Cbrt", Func, 0}, + {"Ceil", Func, 0}, + {"Copysign", Func, 0}, + {"Cos", Func, 0}, + {"Cosh", Func, 0}, + {"Dim", Func, 0}, + {"E", Const, 0}, + {"Erf", Func, 0}, + {"Erfc", Func, 0}, + {"Erfcinv", Func, 10}, + {"Erfinv", Func, 10}, + {"Exp", Func, 0}, + {"Exp2", Func, 0}, + {"Expm1", Func, 0}, + {"FMA", Func, 14}, + {"Float32bits", Func, 0}, + {"Float32frombits", Func, 0}, + {"Float64bits", Func, 0}, + {"Float64frombits", Func, 0}, + {"Floor", Func, 0}, + {"Frexp", Func, 0}, + {"Gamma", Func, 0}, + {"Hypot", Func, 0}, + {"Ilogb", Func, 0}, + {"Inf", Func, 0}, + {"IsInf", Func, 0}, + {"IsNaN", Func, 0}, + {"J0", Func, 0}, + {"J1", Func, 0}, + {"Jn", Func, 0}, + {"Ldexp", Func, 0}, + {"Lgamma", Func, 0}, + {"Ln10", Const, 0}, + {"Ln2", Const, 0}, + {"Log", Func, 0}, + {"Log10", Func, 0}, + {"Log10E", Const, 0}, + {"Log1p", Func, 0}, + {"Log2", Func, 0}, + {"Log2E", Const, 0}, + {"Logb", Func, 0}, + {"Max", Func, 0}, + {"MaxFloat32", Const, 0}, + {"MaxFloat64", Const, 0}, + {"MaxInt", Const, 17}, + {"MaxInt16", Const, 0}, + {"MaxInt32", Const, 0}, + {"MaxInt64", Const, 0}, + {"MaxInt8", Const, 0}, + {"MaxUint", Const, 17}, + {"MaxUint16", Const, 0}, + {"MaxUint32", Const, 0}, + {"MaxUint64", Const, 0}, + {"MaxUint8", Const, 0}, + {"Min", Func, 0}, + {"MinInt", Const, 17}, + {"MinInt16", Const, 0}, + {"MinInt32", Const, 0}, + {"MinInt64", Const, 0}, + {"MinInt8", Const, 0}, + {"Mod", Func, 0}, + {"Modf", Func, 0}, + {"NaN", Func, 0}, + {"Nextafter", Func, 0}, + {"Nextafter32", Func, 4}, + {"Phi", Const, 0}, + {"Pi", Const, 0}, + {"Pow", Func, 0}, + {"Pow10", Func, 0}, + {"Remainder", Func, 0}, + {"Round", Func, 10}, + {"RoundToEven", Func, 10}, + {"Signbit", Func, 0}, + {"Sin", Func, 0}, + {"Sincos", Func, 0}, + {"Sinh", Func, 0}, + {"SmallestNonzeroFloat32", Const, 0}, + {"SmallestNonzeroFloat64", Const, 0}, + {"Sqrt", Func, 0}, + {"Sqrt2", Const, 0}, + {"SqrtE", Const, 0}, + {"SqrtPhi", Const, 0}, + {"SqrtPi", Const, 0}, + {"Tan", Func, 0}, + {"Tanh", Func, 0}, + {"Trunc", Func, 0}, + {"Y0", Func, 0}, + {"Y1", Func, 0}, + {"Yn", Func, 0}, + }, + "math/big": { + {"(*Float).Abs", Method, 5}, + {"(*Float).Acc", Method, 5}, + {"(*Float).Add", Method, 5}, + {"(*Float).Append", Method, 5}, + {"(*Float).Cmp", Method, 5}, + {"(*Float).Copy", Method, 5}, + {"(*Float).Float32", Method, 5}, + {"(*Float).Float64", Method, 5}, + {"(*Float).Format", Method, 5}, + {"(*Float).GobDecode", Method, 7}, + {"(*Float).GobEncode", Method, 7}, + {"(*Float).Int", Method, 5}, + {"(*Float).Int64", Method, 5}, + {"(*Float).IsInf", Method, 5}, + {"(*Float).IsInt", Method, 5}, + {"(*Float).MantExp", Method, 5}, + {"(*Float).MarshalText", Method, 6}, + {"(*Float).MinPrec", Method, 5}, + {"(*Float).Mode", Method, 5}, + {"(*Float).Mul", Method, 5}, + {"(*Float).Neg", Method, 5}, + {"(*Float).Parse", Method, 5}, + {"(*Float).Prec", Method, 5}, + {"(*Float).Quo", Method, 5}, + {"(*Float).Rat", Method, 5}, + {"(*Float).Scan", Method, 8}, + {"(*Float).Set", Method, 5}, + {"(*Float).SetFloat64", Method, 5}, + {"(*Float).SetInf", Method, 5}, + {"(*Float).SetInt", Method, 5}, + {"(*Float).SetInt64", Method, 5}, + {"(*Float).SetMantExp", Method, 5}, + {"(*Float).SetMode", Method, 5}, + {"(*Float).SetPrec", Method, 5}, + {"(*Float).SetRat", Method, 5}, + {"(*Float).SetString", Method, 5}, + {"(*Float).SetUint64", Method, 5}, + {"(*Float).Sign", Method, 5}, + {"(*Float).Signbit", Method, 5}, + {"(*Float).Sqrt", Method, 10}, + {"(*Float).String", Method, 5}, + {"(*Float).Sub", Method, 5}, + {"(*Float).Text", Method, 5}, + {"(*Float).Uint64", Method, 5}, + {"(*Float).UnmarshalText", Method, 6}, + {"(*Int).Abs", Method, 0}, + {"(*Int).Add", Method, 0}, + {"(*Int).And", Method, 0}, + {"(*Int).AndNot", Method, 0}, + {"(*Int).Append", Method, 6}, + {"(*Int).Binomial", Method, 0}, + {"(*Int).Bit", Method, 0}, + {"(*Int).BitLen", Method, 0}, + {"(*Int).Bits", Method, 0}, + {"(*Int).Bytes", Method, 0}, + {"(*Int).Cmp", Method, 0}, + {"(*Int).CmpAbs", Method, 10}, + {"(*Int).Div", Method, 0}, + {"(*Int).DivMod", Method, 0}, + {"(*Int).Exp", Method, 0}, + {"(*Int).FillBytes", Method, 15}, + {"(*Int).Float64", Method, 21}, + {"(*Int).Format", Method, 0}, + {"(*Int).GCD", Method, 0}, + {"(*Int).GobDecode", Method, 0}, + {"(*Int).GobEncode", Method, 0}, + {"(*Int).Int64", Method, 0}, + {"(*Int).IsInt64", Method, 9}, + {"(*Int).IsUint64", Method, 9}, + {"(*Int).Lsh", Method, 0}, + {"(*Int).MarshalJSON", Method, 1}, + {"(*Int).MarshalText", Method, 3}, + {"(*Int).Mod", Method, 0}, + {"(*Int).ModInverse", Method, 0}, + {"(*Int).ModSqrt", Method, 5}, + {"(*Int).Mul", Method, 0}, + {"(*Int).MulRange", Method, 0}, + {"(*Int).Neg", Method, 0}, + {"(*Int).Not", Method, 0}, + {"(*Int).Or", Method, 0}, + {"(*Int).ProbablyPrime", Method, 0}, + {"(*Int).Quo", Method, 0}, + {"(*Int).QuoRem", Method, 0}, + {"(*Int).Rand", Method, 0}, + {"(*Int).Rem", Method, 0}, + {"(*Int).Rsh", Method, 0}, + {"(*Int).Scan", Method, 0}, + {"(*Int).Set", Method, 0}, + {"(*Int).SetBit", Method, 0}, + {"(*Int).SetBits", Method, 0}, + {"(*Int).SetBytes", Method, 0}, + {"(*Int).SetInt64", Method, 0}, + {"(*Int).SetString", Method, 0}, + {"(*Int).SetUint64", Method, 1}, + {"(*Int).Sign", Method, 0}, + {"(*Int).Sqrt", Method, 8}, + {"(*Int).String", Method, 0}, + {"(*Int).Sub", Method, 0}, + {"(*Int).Text", Method, 6}, + {"(*Int).TrailingZeroBits", Method, 13}, + {"(*Int).Uint64", Method, 1}, + {"(*Int).UnmarshalJSON", Method, 1}, + {"(*Int).UnmarshalText", Method, 3}, + {"(*Int).Xor", Method, 0}, + {"(*Rat).Abs", Method, 0}, + {"(*Rat).Add", Method, 0}, + {"(*Rat).Cmp", Method, 0}, + {"(*Rat).Denom", Method, 0}, + {"(*Rat).Float32", Method, 4}, + {"(*Rat).Float64", Method, 1}, + {"(*Rat).FloatPrec", Method, 22}, + {"(*Rat).FloatString", Method, 0}, + {"(*Rat).GobDecode", Method, 0}, + {"(*Rat).GobEncode", Method, 0}, + {"(*Rat).Inv", Method, 0}, + {"(*Rat).IsInt", Method, 0}, + {"(*Rat).MarshalText", Method, 3}, + {"(*Rat).Mul", Method, 0}, + {"(*Rat).Neg", Method, 0}, + {"(*Rat).Num", Method, 0}, + {"(*Rat).Quo", Method, 0}, + {"(*Rat).RatString", Method, 0}, + {"(*Rat).Scan", Method, 0}, + {"(*Rat).Set", Method, 0}, + {"(*Rat).SetFloat64", Method, 1}, + {"(*Rat).SetFrac", Method, 0}, + {"(*Rat).SetFrac64", Method, 0}, + {"(*Rat).SetInt", Method, 0}, + {"(*Rat).SetInt64", Method, 0}, + {"(*Rat).SetString", Method, 0}, + {"(*Rat).SetUint64", Method, 13}, + {"(*Rat).Sign", Method, 0}, + {"(*Rat).String", Method, 0}, + {"(*Rat).Sub", Method, 0}, + {"(*Rat).UnmarshalText", Method, 3}, + {"(Accuracy).String", Method, 5}, + {"(ErrNaN).Error", Method, 5}, + {"(RoundingMode).String", Method, 5}, + {"Above", Const, 5}, + {"Accuracy", Type, 5}, + {"AwayFromZero", Const, 5}, + {"Below", Const, 5}, + {"ErrNaN", Type, 5}, + {"Exact", Const, 5}, + {"Float", Type, 5}, + {"Int", Type, 0}, + {"Jacobi", Func, 5}, + {"MaxBase", Const, 0}, + {"MaxExp", Const, 5}, + {"MaxPrec", Const, 5}, + {"MinExp", Const, 5}, + {"NewFloat", Func, 5}, + {"NewInt", Func, 0}, + {"NewRat", Func, 0}, + {"ParseFloat", Func, 5}, + {"Rat", Type, 0}, + {"RoundingMode", Type, 5}, + {"ToNearestAway", Const, 5}, + {"ToNearestEven", Const, 5}, + {"ToNegativeInf", Const, 5}, + {"ToPositiveInf", Const, 5}, + {"ToZero", Const, 5}, + {"Word", Type, 0}, + }, + "math/bits": { + {"Add", Func, 12}, + {"Add32", Func, 12}, + {"Add64", Func, 12}, + {"Div", Func, 12}, + {"Div32", Func, 12}, + {"Div64", Func, 12}, + {"LeadingZeros", Func, 9}, + {"LeadingZeros16", Func, 9}, + {"LeadingZeros32", Func, 9}, + {"LeadingZeros64", Func, 9}, + {"LeadingZeros8", Func, 9}, + {"Len", Func, 9}, + {"Len16", Func, 9}, + {"Len32", Func, 9}, + {"Len64", Func, 9}, + {"Len8", Func, 9}, + {"Mul", Func, 12}, + {"Mul32", Func, 12}, + {"Mul64", Func, 12}, + {"OnesCount", Func, 9}, + {"OnesCount16", Func, 9}, + {"OnesCount32", Func, 9}, + {"OnesCount64", Func, 9}, + {"OnesCount8", Func, 9}, + {"Rem", Func, 14}, + {"Rem32", Func, 14}, + {"Rem64", Func, 14}, + {"Reverse", Func, 9}, + {"Reverse16", Func, 9}, + {"Reverse32", Func, 9}, + {"Reverse64", Func, 9}, + {"Reverse8", Func, 9}, + {"ReverseBytes", Func, 9}, + {"ReverseBytes16", Func, 9}, + {"ReverseBytes32", Func, 9}, + {"ReverseBytes64", Func, 9}, + {"RotateLeft", Func, 9}, + {"RotateLeft16", Func, 9}, + {"RotateLeft32", Func, 9}, + {"RotateLeft64", Func, 9}, + {"RotateLeft8", Func, 9}, + {"Sub", Func, 12}, + {"Sub32", Func, 12}, + {"Sub64", Func, 12}, + {"TrailingZeros", Func, 9}, + {"TrailingZeros16", Func, 9}, + {"TrailingZeros32", Func, 9}, + {"TrailingZeros64", Func, 9}, + {"TrailingZeros8", Func, 9}, + {"UintSize", Const, 9}, + }, + "math/cmplx": { + {"Abs", Func, 0}, + {"Acos", Func, 0}, + {"Acosh", Func, 0}, + {"Asin", Func, 0}, + {"Asinh", Func, 0}, + {"Atan", Func, 0}, + {"Atanh", Func, 0}, + {"Conj", Func, 0}, + {"Cos", Func, 0}, + {"Cosh", Func, 0}, + {"Cot", Func, 0}, + {"Exp", Func, 0}, + {"Inf", Func, 0}, + {"IsInf", Func, 0}, + {"IsNaN", Func, 0}, + {"Log", Func, 0}, + {"Log10", Func, 0}, + {"NaN", Func, 0}, + {"Phase", Func, 0}, + {"Polar", Func, 0}, + {"Pow", Func, 0}, + {"Rect", Func, 0}, + {"Sin", Func, 0}, + {"Sinh", Func, 0}, + {"Sqrt", Func, 0}, + {"Tan", Func, 0}, + {"Tanh", Func, 0}, + }, + "math/rand": { + {"(*Rand).ExpFloat64", Method, 0}, + {"(*Rand).Float32", Method, 0}, + {"(*Rand).Float64", Method, 0}, + {"(*Rand).Int", Method, 0}, + {"(*Rand).Int31", Method, 0}, + {"(*Rand).Int31n", Method, 0}, + {"(*Rand).Int63", Method, 0}, + {"(*Rand).Int63n", Method, 0}, + {"(*Rand).Intn", Method, 0}, + {"(*Rand).NormFloat64", Method, 0}, + {"(*Rand).Perm", Method, 0}, + {"(*Rand).Read", Method, 6}, + {"(*Rand).Seed", Method, 0}, + {"(*Rand).Shuffle", Method, 10}, + {"(*Rand).Uint32", Method, 0}, + {"(*Rand).Uint64", Method, 8}, + {"(*Zipf).Uint64", Method, 0}, + {"ExpFloat64", Func, 0}, + {"Float32", Func, 0}, + {"Float64", Func, 0}, + {"Int", Func, 0}, + {"Int31", Func, 0}, + {"Int31n", Func, 0}, + {"Int63", Func, 0}, + {"Int63n", Func, 0}, + {"Intn", Func, 0}, + {"New", Func, 0}, + {"NewSource", Func, 0}, + {"NewZipf", Func, 0}, + {"NormFloat64", Func, 0}, + {"Perm", Func, 0}, + {"Rand", Type, 0}, + {"Read", Func, 6}, + {"Seed", Func, 0}, + {"Shuffle", Func, 10}, + {"Source", Type, 0}, + {"Source64", Type, 8}, + {"Uint32", Func, 0}, + {"Uint64", Func, 8}, + {"Zipf", Type, 0}, + }, + "math/rand/v2": { + {"(*ChaCha8).MarshalBinary", Method, 22}, + {"(*ChaCha8).Seed", Method, 22}, + {"(*ChaCha8).Uint64", Method, 22}, + {"(*ChaCha8).UnmarshalBinary", Method, 22}, + {"(*PCG).MarshalBinary", Method, 22}, + {"(*PCG).Seed", Method, 22}, + {"(*PCG).Uint64", Method, 22}, + {"(*PCG).UnmarshalBinary", Method, 22}, + {"(*Rand).ExpFloat64", Method, 22}, + {"(*Rand).Float32", Method, 22}, + {"(*Rand).Float64", Method, 22}, + {"(*Rand).Int", Method, 22}, + {"(*Rand).Int32", Method, 22}, + {"(*Rand).Int32N", Method, 22}, + {"(*Rand).Int64", Method, 22}, + {"(*Rand).Int64N", Method, 22}, + {"(*Rand).IntN", Method, 22}, + {"(*Rand).NormFloat64", Method, 22}, + {"(*Rand).Perm", Method, 22}, + {"(*Rand).Shuffle", Method, 22}, + {"(*Rand).Uint32", Method, 22}, + {"(*Rand).Uint32N", Method, 22}, + {"(*Rand).Uint64", Method, 22}, + {"(*Rand).Uint64N", Method, 22}, + {"(*Rand).UintN", Method, 22}, + {"(*Zipf).Uint64", Method, 22}, + {"ChaCha8", Type, 22}, + {"ExpFloat64", Func, 22}, + {"Float32", Func, 22}, + {"Float64", Func, 22}, + {"Int", Func, 22}, + {"Int32", Func, 22}, + {"Int32N", Func, 22}, + {"Int64", Func, 22}, + {"Int64N", Func, 22}, + {"IntN", Func, 22}, + {"N", Func, 22}, + {"New", Func, 22}, + {"NewChaCha8", Func, 22}, + {"NewPCG", Func, 22}, + {"NewZipf", Func, 22}, + {"NormFloat64", Func, 22}, + {"PCG", Type, 22}, + {"Perm", Func, 22}, + {"Rand", Type, 22}, + {"Shuffle", Func, 22}, + {"Source", Type, 22}, + {"Uint32", Func, 22}, + {"Uint32N", Func, 22}, + {"Uint64", Func, 22}, + {"Uint64N", Func, 22}, + {"UintN", Func, 22}, + {"Zipf", Type, 22}, + }, + "mime": { + {"(*WordDecoder).Decode", Method, 5}, + {"(*WordDecoder).DecodeHeader", Method, 5}, + {"(WordEncoder).Encode", Method, 5}, + {"AddExtensionType", Func, 0}, + {"BEncoding", Const, 5}, + {"ErrInvalidMediaParameter", Var, 9}, + {"ExtensionsByType", Func, 5}, + {"FormatMediaType", Func, 0}, + {"ParseMediaType", Func, 0}, + {"QEncoding", Const, 5}, + {"TypeByExtension", Func, 0}, + {"WordDecoder", Type, 5}, + {"WordDecoder.CharsetReader", Field, 5}, + {"WordEncoder", Type, 5}, + }, + "mime/multipart": { + {"(*FileHeader).Open", Method, 0}, + {"(*Form).RemoveAll", Method, 0}, + {"(*Part).Close", Method, 0}, + {"(*Part).FileName", Method, 0}, + {"(*Part).FormName", Method, 0}, + {"(*Part).Read", Method, 0}, + {"(*Reader).NextPart", Method, 0}, + {"(*Reader).NextRawPart", Method, 14}, + {"(*Reader).ReadForm", Method, 0}, + {"(*Writer).Boundary", Method, 0}, + {"(*Writer).Close", Method, 0}, + {"(*Writer).CreateFormField", Method, 0}, + {"(*Writer).CreateFormFile", Method, 0}, + {"(*Writer).CreatePart", Method, 0}, + {"(*Writer).FormDataContentType", Method, 0}, + {"(*Writer).SetBoundary", Method, 1}, + {"(*Writer).WriteField", Method, 0}, + {"ErrMessageTooLarge", Var, 9}, + {"File", Type, 0}, + {"FileHeader", Type, 0}, + {"FileHeader.Filename", Field, 0}, + {"FileHeader.Header", Field, 0}, + {"FileHeader.Size", Field, 9}, + {"Form", Type, 0}, + {"Form.File", Field, 0}, + {"Form.Value", Field, 0}, + {"NewReader", Func, 0}, + {"NewWriter", Func, 0}, + {"Part", Type, 0}, + {"Part.Header", Field, 0}, + {"Reader", Type, 0}, + {"Writer", Type, 0}, + }, + "mime/quotedprintable": { + {"(*Reader).Read", Method, 5}, + {"(*Writer).Close", Method, 5}, + {"(*Writer).Write", Method, 5}, + {"NewReader", Func, 5}, + {"NewWriter", Func, 5}, + {"Reader", Type, 5}, + {"Writer", Type, 5}, + {"Writer.Binary", Field, 5}, + }, + "net": { + {"(*AddrError).Error", Method, 0}, + {"(*AddrError).Temporary", Method, 0}, + {"(*AddrError).Timeout", Method, 0}, + {"(*Buffers).Read", Method, 8}, + {"(*Buffers).WriteTo", Method, 8}, + {"(*DNSConfigError).Error", Method, 0}, + {"(*DNSConfigError).Temporary", Method, 0}, + {"(*DNSConfigError).Timeout", Method, 0}, + {"(*DNSConfigError).Unwrap", Method, 13}, + {"(*DNSError).Error", Method, 0}, + {"(*DNSError).Temporary", Method, 0}, + {"(*DNSError).Timeout", Method, 0}, + {"(*Dialer).Dial", Method, 1}, + {"(*Dialer).DialContext", Method, 7}, + {"(*Dialer).MultipathTCP", Method, 21}, + {"(*Dialer).SetMultipathTCP", Method, 21}, + {"(*IP).UnmarshalText", Method, 2}, + {"(*IPAddr).Network", Method, 0}, + {"(*IPAddr).String", Method, 0}, + {"(*IPConn).Close", Method, 0}, + {"(*IPConn).File", Method, 0}, + {"(*IPConn).LocalAddr", Method, 0}, + {"(*IPConn).Read", Method, 0}, + {"(*IPConn).ReadFrom", Method, 0}, + {"(*IPConn).ReadFromIP", Method, 0}, + {"(*IPConn).ReadMsgIP", Method, 1}, + {"(*IPConn).RemoteAddr", Method, 0}, + {"(*IPConn).SetDeadline", Method, 0}, + {"(*IPConn).SetReadBuffer", Method, 0}, + {"(*IPConn).SetReadDeadline", Method, 0}, + {"(*IPConn).SetWriteBuffer", Method, 0}, + {"(*IPConn).SetWriteDeadline", Method, 0}, + {"(*IPConn).SyscallConn", Method, 9}, + {"(*IPConn).Write", Method, 0}, + {"(*IPConn).WriteMsgIP", Method, 1}, + {"(*IPConn).WriteTo", Method, 0}, + {"(*IPConn).WriteToIP", Method, 0}, + {"(*IPNet).Contains", Method, 0}, + {"(*IPNet).Network", Method, 0}, + {"(*IPNet).String", Method, 0}, + {"(*Interface).Addrs", Method, 0}, + {"(*Interface).MulticastAddrs", Method, 0}, + {"(*ListenConfig).Listen", Method, 11}, + {"(*ListenConfig).ListenPacket", Method, 11}, + {"(*ListenConfig).MultipathTCP", Method, 21}, + {"(*ListenConfig).SetMultipathTCP", Method, 21}, + {"(*OpError).Error", Method, 0}, + {"(*OpError).Temporary", Method, 0}, + {"(*OpError).Timeout", Method, 0}, + {"(*OpError).Unwrap", Method, 13}, + {"(*ParseError).Error", Method, 0}, + {"(*ParseError).Temporary", Method, 17}, + {"(*ParseError).Timeout", Method, 17}, + {"(*Resolver).LookupAddr", Method, 8}, + {"(*Resolver).LookupCNAME", Method, 8}, + {"(*Resolver).LookupHost", Method, 8}, + {"(*Resolver).LookupIP", Method, 15}, + {"(*Resolver).LookupIPAddr", Method, 8}, + {"(*Resolver).LookupMX", Method, 8}, + {"(*Resolver).LookupNS", Method, 8}, + {"(*Resolver).LookupNetIP", Method, 18}, + {"(*Resolver).LookupPort", Method, 8}, + {"(*Resolver).LookupSRV", Method, 8}, + {"(*Resolver).LookupTXT", Method, 8}, + {"(*TCPAddr).AddrPort", Method, 18}, + {"(*TCPAddr).Network", Method, 0}, + {"(*TCPAddr).String", Method, 0}, + {"(*TCPConn).Close", Method, 0}, + {"(*TCPConn).CloseRead", Method, 0}, + {"(*TCPConn).CloseWrite", Method, 0}, + {"(*TCPConn).File", Method, 0}, + {"(*TCPConn).LocalAddr", Method, 0}, + {"(*TCPConn).MultipathTCP", Method, 21}, + {"(*TCPConn).Read", Method, 0}, + {"(*TCPConn).ReadFrom", Method, 0}, + {"(*TCPConn).RemoteAddr", Method, 0}, + {"(*TCPConn).SetDeadline", Method, 0}, + {"(*TCPConn).SetKeepAlive", Method, 0}, + {"(*TCPConn).SetKeepAlivePeriod", Method, 2}, + {"(*TCPConn).SetLinger", Method, 0}, + {"(*TCPConn).SetNoDelay", Method, 0}, + {"(*TCPConn).SetReadBuffer", Method, 0}, + {"(*TCPConn).SetReadDeadline", Method, 0}, + {"(*TCPConn).SetWriteBuffer", Method, 0}, + {"(*TCPConn).SetWriteDeadline", Method, 0}, + {"(*TCPConn).SyscallConn", Method, 9}, + {"(*TCPConn).Write", Method, 0}, + {"(*TCPConn).WriteTo", Method, 22}, + {"(*TCPListener).Accept", Method, 0}, + {"(*TCPListener).AcceptTCP", Method, 0}, + {"(*TCPListener).Addr", Method, 0}, + {"(*TCPListener).Close", Method, 0}, + {"(*TCPListener).File", Method, 0}, + {"(*TCPListener).SetDeadline", Method, 0}, + {"(*TCPListener).SyscallConn", Method, 10}, + {"(*UDPAddr).AddrPort", Method, 18}, + {"(*UDPAddr).Network", Method, 0}, + {"(*UDPAddr).String", Method, 0}, + {"(*UDPConn).Close", Method, 0}, + {"(*UDPConn).File", Method, 0}, + {"(*UDPConn).LocalAddr", Method, 0}, + {"(*UDPConn).Read", Method, 0}, + {"(*UDPConn).ReadFrom", Method, 0}, + {"(*UDPConn).ReadFromUDP", Method, 0}, + {"(*UDPConn).ReadFromUDPAddrPort", Method, 18}, + {"(*UDPConn).ReadMsgUDP", Method, 1}, + {"(*UDPConn).ReadMsgUDPAddrPort", Method, 18}, + {"(*UDPConn).RemoteAddr", Method, 0}, + {"(*UDPConn).SetDeadline", Method, 0}, + {"(*UDPConn).SetReadBuffer", Method, 0}, + {"(*UDPConn).SetReadDeadline", Method, 0}, + {"(*UDPConn).SetWriteBuffer", Method, 0}, + {"(*UDPConn).SetWriteDeadline", Method, 0}, + {"(*UDPConn).SyscallConn", Method, 9}, + {"(*UDPConn).Write", Method, 0}, + {"(*UDPConn).WriteMsgUDP", Method, 1}, + {"(*UDPConn).WriteMsgUDPAddrPort", Method, 18}, + {"(*UDPConn).WriteTo", Method, 0}, + {"(*UDPConn).WriteToUDP", Method, 0}, + {"(*UDPConn).WriteToUDPAddrPort", Method, 18}, + {"(*UnixAddr).Network", Method, 0}, + {"(*UnixAddr).String", Method, 0}, + {"(*UnixConn).Close", Method, 0}, + {"(*UnixConn).CloseRead", Method, 1}, + {"(*UnixConn).CloseWrite", Method, 1}, + {"(*UnixConn).File", Method, 0}, + {"(*UnixConn).LocalAddr", Method, 0}, + {"(*UnixConn).Read", Method, 0}, + {"(*UnixConn).ReadFrom", Method, 0}, + {"(*UnixConn).ReadFromUnix", Method, 0}, + {"(*UnixConn).ReadMsgUnix", Method, 0}, + {"(*UnixConn).RemoteAddr", Method, 0}, + {"(*UnixConn).SetDeadline", Method, 0}, + {"(*UnixConn).SetReadBuffer", Method, 0}, + {"(*UnixConn).SetReadDeadline", Method, 0}, + {"(*UnixConn).SetWriteBuffer", Method, 0}, + {"(*UnixConn).SetWriteDeadline", Method, 0}, + {"(*UnixConn).SyscallConn", Method, 9}, + {"(*UnixConn).Write", Method, 0}, + {"(*UnixConn).WriteMsgUnix", Method, 0}, + {"(*UnixConn).WriteTo", Method, 0}, + {"(*UnixConn).WriteToUnix", Method, 0}, + {"(*UnixListener).Accept", Method, 0}, + {"(*UnixListener).AcceptUnix", Method, 0}, + {"(*UnixListener).Addr", Method, 0}, + {"(*UnixListener).Close", Method, 0}, + {"(*UnixListener).File", Method, 0}, + {"(*UnixListener).SetDeadline", Method, 0}, + {"(*UnixListener).SetUnlinkOnClose", Method, 8}, + {"(*UnixListener).SyscallConn", Method, 10}, + {"(Flags).String", Method, 0}, + {"(HardwareAddr).String", Method, 0}, + {"(IP).DefaultMask", Method, 0}, + {"(IP).Equal", Method, 0}, + {"(IP).IsGlobalUnicast", Method, 0}, + {"(IP).IsInterfaceLocalMulticast", Method, 0}, + {"(IP).IsLinkLocalMulticast", Method, 0}, + {"(IP).IsLinkLocalUnicast", Method, 0}, + {"(IP).IsLoopback", Method, 0}, + {"(IP).IsMulticast", Method, 0}, + {"(IP).IsPrivate", Method, 17}, + {"(IP).IsUnspecified", Method, 0}, + {"(IP).MarshalText", Method, 2}, + {"(IP).Mask", Method, 0}, + {"(IP).String", Method, 0}, + {"(IP).To16", Method, 0}, + {"(IP).To4", Method, 0}, + {"(IPMask).Size", Method, 0}, + {"(IPMask).String", Method, 0}, + {"(InvalidAddrError).Error", Method, 0}, + {"(InvalidAddrError).Temporary", Method, 0}, + {"(InvalidAddrError).Timeout", Method, 0}, + {"(UnknownNetworkError).Error", Method, 0}, + {"(UnknownNetworkError).Temporary", Method, 0}, + {"(UnknownNetworkError).Timeout", Method, 0}, + {"Addr", Type, 0}, + {"AddrError", Type, 0}, + {"AddrError.Addr", Field, 0}, + {"AddrError.Err", Field, 0}, + {"Buffers", Type, 8}, + {"CIDRMask", Func, 0}, + {"Conn", Type, 0}, + {"DNSConfigError", Type, 0}, + {"DNSConfigError.Err", Field, 0}, + {"DNSError", Type, 0}, + {"DNSError.Err", Field, 0}, + {"DNSError.IsNotFound", Field, 13}, + {"DNSError.IsTemporary", Field, 6}, + {"DNSError.IsTimeout", Field, 0}, + {"DNSError.Name", Field, 0}, + {"DNSError.Server", Field, 0}, + {"DefaultResolver", Var, 8}, + {"Dial", Func, 0}, + {"DialIP", Func, 0}, + {"DialTCP", Func, 0}, + {"DialTimeout", Func, 0}, + {"DialUDP", Func, 0}, + {"DialUnix", Func, 0}, + {"Dialer", Type, 1}, + {"Dialer.Cancel", Field, 6}, + {"Dialer.Control", Field, 11}, + {"Dialer.ControlContext", Field, 20}, + {"Dialer.Deadline", Field, 1}, + {"Dialer.DualStack", Field, 2}, + {"Dialer.FallbackDelay", Field, 5}, + {"Dialer.KeepAlive", Field, 3}, + {"Dialer.LocalAddr", Field, 1}, + {"Dialer.Resolver", Field, 8}, + {"Dialer.Timeout", Field, 1}, + {"ErrClosed", Var, 16}, + {"ErrWriteToConnected", Var, 0}, + {"Error", Type, 0}, + {"FileConn", Func, 0}, + {"FileListener", Func, 0}, + {"FilePacketConn", Func, 0}, + {"FlagBroadcast", Const, 0}, + {"FlagLoopback", Const, 0}, + {"FlagMulticast", Const, 0}, + {"FlagPointToPoint", Const, 0}, + {"FlagRunning", Const, 20}, + {"FlagUp", Const, 0}, + {"Flags", Type, 0}, + {"HardwareAddr", Type, 0}, + {"IP", Type, 0}, + {"IPAddr", Type, 0}, + {"IPAddr.IP", Field, 0}, + {"IPAddr.Zone", Field, 1}, + {"IPConn", Type, 0}, + {"IPMask", Type, 0}, + {"IPNet", Type, 0}, + {"IPNet.IP", Field, 0}, + {"IPNet.Mask", Field, 0}, + {"IPv4", Func, 0}, + {"IPv4Mask", Func, 0}, + {"IPv4allrouter", Var, 0}, + {"IPv4allsys", Var, 0}, + {"IPv4bcast", Var, 0}, + {"IPv4len", Const, 0}, + {"IPv4zero", Var, 0}, + {"IPv6interfacelocalallnodes", Var, 0}, + {"IPv6len", Const, 0}, + {"IPv6linklocalallnodes", Var, 0}, + {"IPv6linklocalallrouters", Var, 0}, + {"IPv6loopback", Var, 0}, + {"IPv6unspecified", Var, 0}, + {"IPv6zero", Var, 0}, + {"Interface", Type, 0}, + {"Interface.Flags", Field, 0}, + {"Interface.HardwareAddr", Field, 0}, + {"Interface.Index", Field, 0}, + {"Interface.MTU", Field, 0}, + {"Interface.Name", Field, 0}, + {"InterfaceAddrs", Func, 0}, + {"InterfaceByIndex", Func, 0}, + {"InterfaceByName", Func, 0}, + {"Interfaces", Func, 0}, + {"InvalidAddrError", Type, 0}, + {"JoinHostPort", Func, 0}, + {"Listen", Func, 0}, + {"ListenConfig", Type, 11}, + {"ListenConfig.Control", Field, 11}, + {"ListenConfig.KeepAlive", Field, 13}, + {"ListenIP", Func, 0}, + {"ListenMulticastUDP", Func, 0}, + {"ListenPacket", Func, 0}, + {"ListenTCP", Func, 0}, + {"ListenUDP", Func, 0}, + {"ListenUnix", Func, 0}, + {"ListenUnixgram", Func, 0}, + {"Listener", Type, 0}, + {"LookupAddr", Func, 0}, + {"LookupCNAME", Func, 0}, + {"LookupHost", Func, 0}, + {"LookupIP", Func, 0}, + {"LookupMX", Func, 0}, + {"LookupNS", Func, 1}, + {"LookupPort", Func, 0}, + {"LookupSRV", Func, 0}, + {"LookupTXT", Func, 0}, + {"MX", Type, 0}, + {"MX.Host", Field, 0}, + {"MX.Pref", Field, 0}, + {"NS", Type, 1}, + {"NS.Host", Field, 1}, + {"OpError", Type, 0}, + {"OpError.Addr", Field, 0}, + {"OpError.Err", Field, 0}, + {"OpError.Net", Field, 0}, + {"OpError.Op", Field, 0}, + {"OpError.Source", Field, 5}, + {"PacketConn", Type, 0}, + {"ParseCIDR", Func, 0}, + {"ParseError", Type, 0}, + {"ParseError.Text", Field, 0}, + {"ParseError.Type", Field, 0}, + {"ParseIP", Func, 0}, + {"ParseMAC", Func, 0}, + {"Pipe", Func, 0}, + {"ResolveIPAddr", Func, 0}, + {"ResolveTCPAddr", Func, 0}, + {"ResolveUDPAddr", Func, 0}, + {"ResolveUnixAddr", Func, 0}, + {"Resolver", Type, 8}, + {"Resolver.Dial", Field, 9}, + {"Resolver.PreferGo", Field, 8}, + {"Resolver.StrictErrors", Field, 9}, + {"SRV", Type, 0}, + {"SRV.Port", Field, 0}, + {"SRV.Priority", Field, 0}, + {"SRV.Target", Field, 0}, + {"SRV.Weight", Field, 0}, + {"SplitHostPort", Func, 0}, + {"TCPAddr", Type, 0}, + {"TCPAddr.IP", Field, 0}, + {"TCPAddr.Port", Field, 0}, + {"TCPAddr.Zone", Field, 1}, + {"TCPAddrFromAddrPort", Func, 18}, + {"TCPConn", Type, 0}, + {"TCPListener", Type, 0}, + {"UDPAddr", Type, 0}, + {"UDPAddr.IP", Field, 0}, + {"UDPAddr.Port", Field, 0}, + {"UDPAddr.Zone", Field, 1}, + {"UDPAddrFromAddrPort", Func, 18}, + {"UDPConn", Type, 0}, + {"UnixAddr", Type, 0}, + {"UnixAddr.Name", Field, 0}, + {"UnixAddr.Net", Field, 0}, + {"UnixConn", Type, 0}, + {"UnixListener", Type, 0}, + {"UnknownNetworkError", Type, 0}, + }, + "net/http": { + {"(*Client).CloseIdleConnections", Method, 12}, + {"(*Client).Do", Method, 0}, + {"(*Client).Get", Method, 0}, + {"(*Client).Head", Method, 0}, + {"(*Client).Post", Method, 0}, + {"(*Client).PostForm", Method, 0}, + {"(*Cookie).String", Method, 0}, + {"(*Cookie).Valid", Method, 18}, + {"(*MaxBytesError).Error", Method, 19}, + {"(*ProtocolError).Error", Method, 0}, + {"(*ProtocolError).Is", Method, 21}, + {"(*Request).AddCookie", Method, 0}, + {"(*Request).BasicAuth", Method, 4}, + {"(*Request).Clone", Method, 13}, + {"(*Request).Context", Method, 7}, + {"(*Request).Cookie", Method, 0}, + {"(*Request).Cookies", Method, 0}, + {"(*Request).FormFile", Method, 0}, + {"(*Request).FormValue", Method, 0}, + {"(*Request).MultipartReader", Method, 0}, + {"(*Request).ParseForm", Method, 0}, + {"(*Request).ParseMultipartForm", Method, 0}, + {"(*Request).PathValue", Method, 22}, + {"(*Request).PostFormValue", Method, 1}, + {"(*Request).ProtoAtLeast", Method, 0}, + {"(*Request).Referer", Method, 0}, + {"(*Request).SetBasicAuth", Method, 0}, + {"(*Request).SetPathValue", Method, 22}, + {"(*Request).UserAgent", Method, 0}, + {"(*Request).WithContext", Method, 7}, + {"(*Request).Write", Method, 0}, + {"(*Request).WriteProxy", Method, 0}, + {"(*Response).Cookies", Method, 0}, + {"(*Response).Location", Method, 0}, + {"(*Response).ProtoAtLeast", Method, 0}, + {"(*Response).Write", Method, 0}, + {"(*ResponseController).EnableFullDuplex", Method, 21}, + {"(*ResponseController).Flush", Method, 20}, + {"(*ResponseController).Hijack", Method, 20}, + {"(*ResponseController).SetReadDeadline", Method, 20}, + {"(*ResponseController).SetWriteDeadline", Method, 20}, + {"(*ServeMux).Handle", Method, 0}, + {"(*ServeMux).HandleFunc", Method, 0}, + {"(*ServeMux).Handler", Method, 1}, + {"(*ServeMux).ServeHTTP", Method, 0}, + {"(*Server).Close", Method, 8}, + {"(*Server).ListenAndServe", Method, 0}, + {"(*Server).ListenAndServeTLS", Method, 0}, + {"(*Server).RegisterOnShutdown", Method, 9}, + {"(*Server).Serve", Method, 0}, + {"(*Server).ServeTLS", Method, 9}, + {"(*Server).SetKeepAlivesEnabled", Method, 3}, + {"(*Server).Shutdown", Method, 8}, + {"(*Transport).CancelRequest", Method, 1}, + {"(*Transport).Clone", Method, 13}, + {"(*Transport).CloseIdleConnections", Method, 0}, + {"(*Transport).RegisterProtocol", Method, 0}, + {"(*Transport).RoundTrip", Method, 0}, + {"(ConnState).String", Method, 3}, + {"(Dir).Open", Method, 0}, + {"(HandlerFunc).ServeHTTP", Method, 0}, + {"(Header).Add", Method, 0}, + {"(Header).Clone", Method, 13}, + {"(Header).Del", Method, 0}, + {"(Header).Get", Method, 0}, + {"(Header).Set", Method, 0}, + {"(Header).Values", Method, 14}, + {"(Header).Write", Method, 0}, + {"(Header).WriteSubset", Method, 0}, + {"AllowQuerySemicolons", Func, 17}, + {"CanonicalHeaderKey", Func, 0}, + {"Client", Type, 0}, + {"Client.CheckRedirect", Field, 0}, + {"Client.Jar", Field, 0}, + {"Client.Timeout", Field, 3}, + {"Client.Transport", Field, 0}, + {"CloseNotifier", Type, 1}, + {"ConnState", Type, 3}, + {"Cookie", Type, 0}, + {"Cookie.Domain", Field, 0}, + {"Cookie.Expires", Field, 0}, + {"Cookie.HttpOnly", Field, 0}, + {"Cookie.MaxAge", Field, 0}, + {"Cookie.Name", Field, 0}, + {"Cookie.Path", Field, 0}, + {"Cookie.Raw", Field, 0}, + {"Cookie.RawExpires", Field, 0}, + {"Cookie.SameSite", Field, 11}, + {"Cookie.Secure", Field, 0}, + {"Cookie.Unparsed", Field, 0}, + {"Cookie.Value", Field, 0}, + {"CookieJar", Type, 0}, + {"DefaultClient", Var, 0}, + {"DefaultMaxHeaderBytes", Const, 0}, + {"DefaultMaxIdleConnsPerHost", Const, 0}, + {"DefaultServeMux", Var, 0}, + {"DefaultTransport", Var, 0}, + {"DetectContentType", Func, 0}, + {"Dir", Type, 0}, + {"ErrAbortHandler", Var, 8}, + {"ErrBodyNotAllowed", Var, 0}, + {"ErrBodyReadAfterClose", Var, 0}, + {"ErrContentLength", Var, 0}, + {"ErrHandlerTimeout", Var, 0}, + {"ErrHeaderTooLong", Var, 0}, + {"ErrHijacked", Var, 0}, + {"ErrLineTooLong", Var, 0}, + {"ErrMissingBoundary", Var, 0}, + {"ErrMissingContentLength", Var, 0}, + {"ErrMissingFile", Var, 0}, + {"ErrNoCookie", Var, 0}, + {"ErrNoLocation", Var, 0}, + {"ErrNotMultipart", Var, 0}, + {"ErrNotSupported", Var, 0}, + {"ErrSchemeMismatch", Var, 21}, + {"ErrServerClosed", Var, 8}, + {"ErrShortBody", Var, 0}, + {"ErrSkipAltProtocol", Var, 6}, + {"ErrUnexpectedTrailer", Var, 0}, + {"ErrUseLastResponse", Var, 7}, + {"ErrWriteAfterFlush", Var, 0}, + {"Error", Func, 0}, + {"FS", Func, 16}, + {"File", Type, 0}, + {"FileServer", Func, 0}, + {"FileServerFS", Func, 22}, + {"FileSystem", Type, 0}, + {"Flusher", Type, 0}, + {"Get", Func, 0}, + {"Handle", Func, 0}, + {"HandleFunc", Func, 0}, + {"Handler", Type, 0}, + {"HandlerFunc", Type, 0}, + {"Head", Func, 0}, + {"Header", Type, 0}, + {"Hijacker", Type, 0}, + {"ListenAndServe", Func, 0}, + {"ListenAndServeTLS", Func, 0}, + {"LocalAddrContextKey", Var, 7}, + {"MaxBytesError", Type, 19}, + {"MaxBytesError.Limit", Field, 19}, + {"MaxBytesHandler", Func, 18}, + {"MaxBytesReader", Func, 0}, + {"MethodConnect", Const, 6}, + {"MethodDelete", Const, 6}, + {"MethodGet", Const, 6}, + {"MethodHead", Const, 6}, + {"MethodOptions", Const, 6}, + {"MethodPatch", Const, 6}, + {"MethodPost", Const, 6}, + {"MethodPut", Const, 6}, + {"MethodTrace", Const, 6}, + {"NewFileTransport", Func, 0}, + {"NewFileTransportFS", Func, 22}, + {"NewRequest", Func, 0}, + {"NewRequestWithContext", Func, 13}, + {"NewResponseController", Func, 20}, + {"NewServeMux", Func, 0}, + {"NoBody", Var, 8}, + {"NotFound", Func, 0}, + {"NotFoundHandler", Func, 0}, + {"ParseHTTPVersion", Func, 0}, + {"ParseTime", Func, 1}, + {"Post", Func, 0}, + {"PostForm", Func, 0}, + {"ProtocolError", Type, 0}, + {"ProtocolError.ErrorString", Field, 0}, + {"ProxyFromEnvironment", Func, 0}, + {"ProxyURL", Func, 0}, + {"PushOptions", Type, 8}, + {"PushOptions.Header", Field, 8}, + {"PushOptions.Method", Field, 8}, + {"Pusher", Type, 8}, + {"ReadRequest", Func, 0}, + {"ReadResponse", Func, 0}, + {"Redirect", Func, 0}, + {"RedirectHandler", Func, 0}, + {"Request", Type, 0}, + {"Request.Body", Field, 0}, + {"Request.Cancel", Field, 5}, + {"Request.Close", Field, 0}, + {"Request.ContentLength", Field, 0}, + {"Request.Form", Field, 0}, + {"Request.GetBody", Field, 8}, + {"Request.Header", Field, 0}, + {"Request.Host", Field, 0}, + {"Request.Method", Field, 0}, + {"Request.MultipartForm", Field, 0}, + {"Request.PostForm", Field, 1}, + {"Request.Proto", Field, 0}, + {"Request.ProtoMajor", Field, 0}, + {"Request.ProtoMinor", Field, 0}, + {"Request.RemoteAddr", Field, 0}, + {"Request.RequestURI", Field, 0}, + {"Request.Response", Field, 7}, + {"Request.TLS", Field, 0}, + {"Request.Trailer", Field, 0}, + {"Request.TransferEncoding", Field, 0}, + {"Request.URL", Field, 0}, + {"Response", Type, 0}, + {"Response.Body", Field, 0}, + {"Response.Close", Field, 0}, + {"Response.ContentLength", Field, 0}, + {"Response.Header", Field, 0}, + {"Response.Proto", Field, 0}, + {"Response.ProtoMajor", Field, 0}, + {"Response.ProtoMinor", Field, 0}, + {"Response.Request", Field, 0}, + {"Response.Status", Field, 0}, + {"Response.StatusCode", Field, 0}, + {"Response.TLS", Field, 3}, + {"Response.Trailer", Field, 0}, + {"Response.TransferEncoding", Field, 0}, + {"Response.Uncompressed", Field, 7}, + {"ResponseController", Type, 20}, + {"ResponseWriter", Type, 0}, + {"RoundTripper", Type, 0}, + {"SameSite", Type, 11}, + {"SameSiteDefaultMode", Const, 11}, + {"SameSiteLaxMode", Const, 11}, + {"SameSiteNoneMode", Const, 13}, + {"SameSiteStrictMode", Const, 11}, + {"Serve", Func, 0}, + {"ServeContent", Func, 0}, + {"ServeFile", Func, 0}, + {"ServeFileFS", Func, 22}, + {"ServeMux", Type, 0}, + {"ServeTLS", Func, 9}, + {"Server", Type, 0}, + {"Server.Addr", Field, 0}, + {"Server.BaseContext", Field, 13}, + {"Server.ConnContext", Field, 13}, + {"Server.ConnState", Field, 3}, + {"Server.DisableGeneralOptionsHandler", Field, 20}, + {"Server.ErrorLog", Field, 3}, + {"Server.Handler", Field, 0}, + {"Server.IdleTimeout", Field, 8}, + {"Server.MaxHeaderBytes", Field, 0}, + {"Server.ReadHeaderTimeout", Field, 8}, + {"Server.ReadTimeout", Field, 0}, + {"Server.TLSConfig", Field, 0}, + {"Server.TLSNextProto", Field, 1}, + {"Server.WriteTimeout", Field, 0}, + {"ServerContextKey", Var, 7}, + {"SetCookie", Func, 0}, + {"StateActive", Const, 3}, + {"StateClosed", Const, 3}, + {"StateHijacked", Const, 3}, + {"StateIdle", Const, 3}, + {"StateNew", Const, 3}, + {"StatusAccepted", Const, 0}, + {"StatusAlreadyReported", Const, 7}, + {"StatusBadGateway", Const, 0}, + {"StatusBadRequest", Const, 0}, + {"StatusConflict", Const, 0}, + {"StatusContinue", Const, 0}, + {"StatusCreated", Const, 0}, + {"StatusEarlyHints", Const, 13}, + {"StatusExpectationFailed", Const, 0}, + {"StatusFailedDependency", Const, 7}, + {"StatusForbidden", Const, 0}, + {"StatusFound", Const, 0}, + {"StatusGatewayTimeout", Const, 0}, + {"StatusGone", Const, 0}, + {"StatusHTTPVersionNotSupported", Const, 0}, + {"StatusIMUsed", Const, 7}, + {"StatusInsufficientStorage", Const, 7}, + {"StatusInternalServerError", Const, 0}, + {"StatusLengthRequired", Const, 0}, + {"StatusLocked", Const, 7}, + {"StatusLoopDetected", Const, 7}, + {"StatusMethodNotAllowed", Const, 0}, + {"StatusMisdirectedRequest", Const, 11}, + {"StatusMovedPermanently", Const, 0}, + {"StatusMultiStatus", Const, 7}, + {"StatusMultipleChoices", Const, 0}, + {"StatusNetworkAuthenticationRequired", Const, 6}, + {"StatusNoContent", Const, 0}, + {"StatusNonAuthoritativeInfo", Const, 0}, + {"StatusNotAcceptable", Const, 0}, + {"StatusNotExtended", Const, 7}, + {"StatusNotFound", Const, 0}, + {"StatusNotImplemented", Const, 0}, + {"StatusNotModified", Const, 0}, + {"StatusOK", Const, 0}, + {"StatusPartialContent", Const, 0}, + {"StatusPaymentRequired", Const, 0}, + {"StatusPermanentRedirect", Const, 7}, + {"StatusPreconditionFailed", Const, 0}, + {"StatusPreconditionRequired", Const, 6}, + {"StatusProcessing", Const, 7}, + {"StatusProxyAuthRequired", Const, 0}, + {"StatusRequestEntityTooLarge", Const, 0}, + {"StatusRequestHeaderFieldsTooLarge", Const, 6}, + {"StatusRequestTimeout", Const, 0}, + {"StatusRequestURITooLong", Const, 0}, + {"StatusRequestedRangeNotSatisfiable", Const, 0}, + {"StatusResetContent", Const, 0}, + {"StatusSeeOther", Const, 0}, + {"StatusServiceUnavailable", Const, 0}, + {"StatusSwitchingProtocols", Const, 0}, + {"StatusTeapot", Const, 0}, + {"StatusTemporaryRedirect", Const, 0}, + {"StatusText", Func, 0}, + {"StatusTooEarly", Const, 12}, + {"StatusTooManyRequests", Const, 6}, + {"StatusUnauthorized", Const, 0}, + {"StatusUnavailableForLegalReasons", Const, 6}, + {"StatusUnprocessableEntity", Const, 7}, + {"StatusUnsupportedMediaType", Const, 0}, + {"StatusUpgradeRequired", Const, 7}, + {"StatusUseProxy", Const, 0}, + {"StatusVariantAlsoNegotiates", Const, 7}, + {"StripPrefix", Func, 0}, + {"TimeFormat", Const, 0}, + {"TimeoutHandler", Func, 0}, + {"TrailerPrefix", Const, 8}, + {"Transport", Type, 0}, + {"Transport.Dial", Field, 0}, + {"Transport.DialContext", Field, 7}, + {"Transport.DialTLS", Field, 4}, + {"Transport.DialTLSContext", Field, 14}, + {"Transport.DisableCompression", Field, 0}, + {"Transport.DisableKeepAlives", Field, 0}, + {"Transport.ExpectContinueTimeout", Field, 6}, + {"Transport.ForceAttemptHTTP2", Field, 13}, + {"Transport.GetProxyConnectHeader", Field, 16}, + {"Transport.IdleConnTimeout", Field, 7}, + {"Transport.MaxConnsPerHost", Field, 11}, + {"Transport.MaxIdleConns", Field, 7}, + {"Transport.MaxIdleConnsPerHost", Field, 0}, + {"Transport.MaxResponseHeaderBytes", Field, 7}, + {"Transport.OnProxyConnectResponse", Field, 20}, + {"Transport.Proxy", Field, 0}, + {"Transport.ProxyConnectHeader", Field, 8}, + {"Transport.ReadBufferSize", Field, 13}, + {"Transport.ResponseHeaderTimeout", Field, 1}, + {"Transport.TLSClientConfig", Field, 0}, + {"Transport.TLSHandshakeTimeout", Field, 3}, + {"Transport.TLSNextProto", Field, 6}, + {"Transport.WriteBufferSize", Field, 13}, + }, + "net/http/cgi": { + {"(*Handler).ServeHTTP", Method, 0}, + {"Handler", Type, 0}, + {"Handler.Args", Field, 0}, + {"Handler.Dir", Field, 0}, + {"Handler.Env", Field, 0}, + {"Handler.InheritEnv", Field, 0}, + {"Handler.Logger", Field, 0}, + {"Handler.Path", Field, 0}, + {"Handler.PathLocationHandler", Field, 0}, + {"Handler.Root", Field, 0}, + {"Handler.Stderr", Field, 7}, + {"Request", Func, 0}, + {"RequestFromMap", Func, 0}, + {"Serve", Func, 0}, + }, + "net/http/cookiejar": { + {"(*Jar).Cookies", Method, 1}, + {"(*Jar).SetCookies", Method, 1}, + {"Jar", Type, 1}, + {"New", Func, 1}, + {"Options", Type, 1}, + {"Options.PublicSuffixList", Field, 1}, + {"PublicSuffixList", Type, 1}, + }, + "net/http/fcgi": { + {"ErrConnClosed", Var, 5}, + {"ErrRequestAborted", Var, 5}, + {"ProcessEnv", Func, 9}, + {"Serve", Func, 0}, + }, + "net/http/httptest": { + {"(*ResponseRecorder).Flush", Method, 0}, + {"(*ResponseRecorder).Header", Method, 0}, + {"(*ResponseRecorder).Result", Method, 7}, + {"(*ResponseRecorder).Write", Method, 0}, + {"(*ResponseRecorder).WriteHeader", Method, 0}, + {"(*ResponseRecorder).WriteString", Method, 6}, + {"(*Server).Certificate", Method, 9}, + {"(*Server).Client", Method, 9}, + {"(*Server).Close", Method, 0}, + {"(*Server).CloseClientConnections", Method, 0}, + {"(*Server).Start", Method, 0}, + {"(*Server).StartTLS", Method, 0}, + {"DefaultRemoteAddr", Const, 0}, + {"NewRecorder", Func, 0}, + {"NewRequest", Func, 7}, + {"NewServer", Func, 0}, + {"NewTLSServer", Func, 0}, + {"NewUnstartedServer", Func, 0}, + {"ResponseRecorder", Type, 0}, + {"ResponseRecorder.Body", Field, 0}, + {"ResponseRecorder.Code", Field, 0}, + {"ResponseRecorder.Flushed", Field, 0}, + {"ResponseRecorder.HeaderMap", Field, 0}, + {"Server", Type, 0}, + {"Server.Config", Field, 0}, + {"Server.EnableHTTP2", Field, 14}, + {"Server.Listener", Field, 0}, + {"Server.TLS", Field, 0}, + {"Server.URL", Field, 0}, + }, + "net/http/httptrace": { + {"ClientTrace", Type, 7}, + {"ClientTrace.ConnectDone", Field, 7}, + {"ClientTrace.ConnectStart", Field, 7}, + {"ClientTrace.DNSDone", Field, 7}, + {"ClientTrace.DNSStart", Field, 7}, + {"ClientTrace.GetConn", Field, 7}, + {"ClientTrace.Got100Continue", Field, 7}, + {"ClientTrace.Got1xxResponse", Field, 11}, + {"ClientTrace.GotConn", Field, 7}, + {"ClientTrace.GotFirstResponseByte", Field, 7}, + {"ClientTrace.PutIdleConn", Field, 7}, + {"ClientTrace.TLSHandshakeDone", Field, 8}, + {"ClientTrace.TLSHandshakeStart", Field, 8}, + {"ClientTrace.Wait100Continue", Field, 7}, + {"ClientTrace.WroteHeaderField", Field, 11}, + {"ClientTrace.WroteHeaders", Field, 7}, + {"ClientTrace.WroteRequest", Field, 7}, + {"ContextClientTrace", Func, 7}, + {"DNSDoneInfo", Type, 7}, + {"DNSDoneInfo.Addrs", Field, 7}, + {"DNSDoneInfo.Coalesced", Field, 7}, + {"DNSDoneInfo.Err", Field, 7}, + {"DNSStartInfo", Type, 7}, + {"DNSStartInfo.Host", Field, 7}, + {"GotConnInfo", Type, 7}, + {"GotConnInfo.Conn", Field, 7}, + {"GotConnInfo.IdleTime", Field, 7}, + {"GotConnInfo.Reused", Field, 7}, + {"GotConnInfo.WasIdle", Field, 7}, + {"WithClientTrace", Func, 7}, + {"WroteRequestInfo", Type, 7}, + {"WroteRequestInfo.Err", Field, 7}, + }, + "net/http/httputil": { + {"(*ClientConn).Close", Method, 0}, + {"(*ClientConn).Do", Method, 0}, + {"(*ClientConn).Hijack", Method, 0}, + {"(*ClientConn).Pending", Method, 0}, + {"(*ClientConn).Read", Method, 0}, + {"(*ClientConn).Write", Method, 0}, + {"(*ProxyRequest).SetURL", Method, 20}, + {"(*ProxyRequest).SetXForwarded", Method, 20}, + {"(*ReverseProxy).ServeHTTP", Method, 0}, + {"(*ServerConn).Close", Method, 0}, + {"(*ServerConn).Hijack", Method, 0}, + {"(*ServerConn).Pending", Method, 0}, + {"(*ServerConn).Read", Method, 0}, + {"(*ServerConn).Write", Method, 0}, + {"BufferPool", Type, 6}, + {"ClientConn", Type, 0}, + {"DumpRequest", Func, 0}, + {"DumpRequestOut", Func, 0}, + {"DumpResponse", Func, 0}, + {"ErrClosed", Var, 0}, + {"ErrLineTooLong", Var, 0}, + {"ErrPersistEOF", Var, 0}, + {"ErrPipeline", Var, 0}, + {"NewChunkedReader", Func, 0}, + {"NewChunkedWriter", Func, 0}, + {"NewClientConn", Func, 0}, + {"NewProxyClientConn", Func, 0}, + {"NewServerConn", Func, 0}, + {"NewSingleHostReverseProxy", Func, 0}, + {"ProxyRequest", Type, 20}, + {"ProxyRequest.In", Field, 20}, + {"ProxyRequest.Out", Field, 20}, + {"ReverseProxy", Type, 0}, + {"ReverseProxy.BufferPool", Field, 6}, + {"ReverseProxy.Director", Field, 0}, + {"ReverseProxy.ErrorHandler", Field, 11}, + {"ReverseProxy.ErrorLog", Field, 4}, + {"ReverseProxy.FlushInterval", Field, 0}, + {"ReverseProxy.ModifyResponse", Field, 8}, + {"ReverseProxy.Rewrite", Field, 20}, + {"ReverseProxy.Transport", Field, 0}, + {"ServerConn", Type, 0}, + }, + "net/http/pprof": { + {"Cmdline", Func, 0}, + {"Handler", Func, 0}, + {"Index", Func, 0}, + {"Profile", Func, 0}, + {"Symbol", Func, 0}, + {"Trace", Func, 5}, + }, + "net/mail": { + {"(*Address).String", Method, 0}, + {"(*AddressParser).Parse", Method, 5}, + {"(*AddressParser).ParseList", Method, 5}, + {"(Header).AddressList", Method, 0}, + {"(Header).Date", Method, 0}, + {"(Header).Get", Method, 0}, + {"Address", Type, 0}, + {"Address.Address", Field, 0}, + {"Address.Name", Field, 0}, + {"AddressParser", Type, 5}, + {"AddressParser.WordDecoder", Field, 5}, + {"ErrHeaderNotPresent", Var, 0}, + {"Header", Type, 0}, + {"Message", Type, 0}, + {"Message.Body", Field, 0}, + {"Message.Header", Field, 0}, + {"ParseAddress", Func, 1}, + {"ParseAddressList", Func, 1}, + {"ParseDate", Func, 8}, + {"ReadMessage", Func, 0}, + }, + "net/netip": { + {"(*Addr).UnmarshalBinary", Method, 18}, + {"(*Addr).UnmarshalText", Method, 18}, + {"(*AddrPort).UnmarshalBinary", Method, 18}, + {"(*AddrPort).UnmarshalText", Method, 18}, + {"(*Prefix).UnmarshalBinary", Method, 18}, + {"(*Prefix).UnmarshalText", Method, 18}, + {"(Addr).AppendTo", Method, 18}, + {"(Addr).As16", Method, 18}, + {"(Addr).As4", Method, 18}, + {"(Addr).AsSlice", Method, 18}, + {"(Addr).BitLen", Method, 18}, + {"(Addr).Compare", Method, 18}, + {"(Addr).Is4", Method, 18}, + {"(Addr).Is4In6", Method, 18}, + {"(Addr).Is6", Method, 18}, + {"(Addr).IsGlobalUnicast", Method, 18}, + {"(Addr).IsInterfaceLocalMulticast", Method, 18}, + {"(Addr).IsLinkLocalMulticast", Method, 18}, + {"(Addr).IsLinkLocalUnicast", Method, 18}, + {"(Addr).IsLoopback", Method, 18}, + {"(Addr).IsMulticast", Method, 18}, + {"(Addr).IsPrivate", Method, 18}, + {"(Addr).IsUnspecified", Method, 18}, + {"(Addr).IsValid", Method, 18}, + {"(Addr).Less", Method, 18}, + {"(Addr).MarshalBinary", Method, 18}, + {"(Addr).MarshalText", Method, 18}, + {"(Addr).Next", Method, 18}, + {"(Addr).Prefix", Method, 18}, + {"(Addr).Prev", Method, 18}, + {"(Addr).String", Method, 18}, + {"(Addr).StringExpanded", Method, 18}, + {"(Addr).Unmap", Method, 18}, + {"(Addr).WithZone", Method, 18}, + {"(Addr).Zone", Method, 18}, + {"(AddrPort).Addr", Method, 18}, + {"(AddrPort).AppendTo", Method, 18}, + {"(AddrPort).Compare", Method, 22}, + {"(AddrPort).IsValid", Method, 18}, + {"(AddrPort).MarshalBinary", Method, 18}, + {"(AddrPort).MarshalText", Method, 18}, + {"(AddrPort).Port", Method, 18}, + {"(AddrPort).String", Method, 18}, + {"(Prefix).Addr", Method, 18}, + {"(Prefix).AppendTo", Method, 18}, + {"(Prefix).Bits", Method, 18}, + {"(Prefix).Contains", Method, 18}, + {"(Prefix).IsSingleIP", Method, 18}, + {"(Prefix).IsValid", Method, 18}, + {"(Prefix).MarshalBinary", Method, 18}, + {"(Prefix).MarshalText", Method, 18}, + {"(Prefix).Masked", Method, 18}, + {"(Prefix).Overlaps", Method, 18}, + {"(Prefix).String", Method, 18}, + {"Addr", Type, 18}, + {"AddrFrom16", Func, 18}, + {"AddrFrom4", Func, 18}, + {"AddrFromSlice", Func, 18}, + {"AddrPort", Type, 18}, + {"AddrPortFrom", Func, 18}, + {"IPv4Unspecified", Func, 18}, + {"IPv6LinkLocalAllNodes", Func, 18}, + {"IPv6LinkLocalAllRouters", Func, 20}, + {"IPv6Loopback", Func, 20}, + {"IPv6Unspecified", Func, 18}, + {"MustParseAddr", Func, 18}, + {"MustParseAddrPort", Func, 18}, + {"MustParsePrefix", Func, 18}, + {"ParseAddr", Func, 18}, + {"ParseAddrPort", Func, 18}, + {"ParsePrefix", Func, 18}, + {"Prefix", Type, 18}, + {"PrefixFrom", Func, 18}, + }, + "net/rpc": { + {"(*Client).Call", Method, 0}, + {"(*Client).Close", Method, 0}, + {"(*Client).Go", Method, 0}, + {"(*Server).Accept", Method, 0}, + {"(*Server).HandleHTTP", Method, 0}, + {"(*Server).Register", Method, 0}, + {"(*Server).RegisterName", Method, 0}, + {"(*Server).ServeCodec", Method, 0}, + {"(*Server).ServeConn", Method, 0}, + {"(*Server).ServeHTTP", Method, 0}, + {"(*Server).ServeRequest", Method, 0}, + {"(ServerError).Error", Method, 0}, + {"Accept", Func, 0}, + {"Call", Type, 0}, + {"Call.Args", Field, 0}, + {"Call.Done", Field, 0}, + {"Call.Error", Field, 0}, + {"Call.Reply", Field, 0}, + {"Call.ServiceMethod", Field, 0}, + {"Client", Type, 0}, + {"ClientCodec", Type, 0}, + {"DefaultDebugPath", Const, 0}, + {"DefaultRPCPath", Const, 0}, + {"DefaultServer", Var, 0}, + {"Dial", Func, 0}, + {"DialHTTP", Func, 0}, + {"DialHTTPPath", Func, 0}, + {"ErrShutdown", Var, 0}, + {"HandleHTTP", Func, 0}, + {"NewClient", Func, 0}, + {"NewClientWithCodec", Func, 0}, + {"NewServer", Func, 0}, + {"Register", Func, 0}, + {"RegisterName", Func, 0}, + {"Request", Type, 0}, + {"Request.Seq", Field, 0}, + {"Request.ServiceMethod", Field, 0}, + {"Response", Type, 0}, + {"Response.Error", Field, 0}, + {"Response.Seq", Field, 0}, + {"Response.ServiceMethod", Field, 0}, + {"ServeCodec", Func, 0}, + {"ServeConn", Func, 0}, + {"ServeRequest", Func, 0}, + {"Server", Type, 0}, + {"ServerCodec", Type, 0}, + {"ServerError", Type, 0}, + }, + "net/rpc/jsonrpc": { + {"Dial", Func, 0}, + {"NewClient", Func, 0}, + {"NewClientCodec", Func, 0}, + {"NewServerCodec", Func, 0}, + {"ServeConn", Func, 0}, + }, + "net/smtp": { + {"(*Client).Auth", Method, 0}, + {"(*Client).Close", Method, 2}, + {"(*Client).Data", Method, 0}, + {"(*Client).Extension", Method, 0}, + {"(*Client).Hello", Method, 1}, + {"(*Client).Mail", Method, 0}, + {"(*Client).Noop", Method, 10}, + {"(*Client).Quit", Method, 0}, + {"(*Client).Rcpt", Method, 0}, + {"(*Client).Reset", Method, 0}, + {"(*Client).StartTLS", Method, 0}, + {"(*Client).TLSConnectionState", Method, 5}, + {"(*Client).Verify", Method, 0}, + {"Auth", Type, 0}, + {"CRAMMD5Auth", Func, 0}, + {"Client", Type, 0}, + {"Client.Text", Field, 0}, + {"Dial", Func, 0}, + {"NewClient", Func, 0}, + {"PlainAuth", Func, 0}, + {"SendMail", Func, 0}, + {"ServerInfo", Type, 0}, + {"ServerInfo.Auth", Field, 0}, + {"ServerInfo.Name", Field, 0}, + {"ServerInfo.TLS", Field, 0}, + }, + "net/textproto": { + {"(*Conn).Close", Method, 0}, + {"(*Conn).Cmd", Method, 0}, + {"(*Conn).DotReader", Method, 0}, + {"(*Conn).DotWriter", Method, 0}, + {"(*Conn).EndRequest", Method, 0}, + {"(*Conn).EndResponse", Method, 0}, + {"(*Conn).Next", Method, 0}, + {"(*Conn).PrintfLine", Method, 0}, + {"(*Conn).ReadCodeLine", Method, 0}, + {"(*Conn).ReadContinuedLine", Method, 0}, + {"(*Conn).ReadContinuedLineBytes", Method, 0}, + {"(*Conn).ReadDotBytes", Method, 0}, + {"(*Conn).ReadDotLines", Method, 0}, + {"(*Conn).ReadLine", Method, 0}, + {"(*Conn).ReadLineBytes", Method, 0}, + {"(*Conn).ReadMIMEHeader", Method, 0}, + {"(*Conn).ReadResponse", Method, 0}, + {"(*Conn).StartRequest", Method, 0}, + {"(*Conn).StartResponse", Method, 0}, + {"(*Error).Error", Method, 0}, + {"(*Pipeline).EndRequest", Method, 0}, + {"(*Pipeline).EndResponse", Method, 0}, + {"(*Pipeline).Next", Method, 0}, + {"(*Pipeline).StartRequest", Method, 0}, + {"(*Pipeline).StartResponse", Method, 0}, + {"(*Reader).DotReader", Method, 0}, + {"(*Reader).ReadCodeLine", Method, 0}, + {"(*Reader).ReadContinuedLine", Method, 0}, + {"(*Reader).ReadContinuedLineBytes", Method, 0}, + {"(*Reader).ReadDotBytes", Method, 0}, + {"(*Reader).ReadDotLines", Method, 0}, + {"(*Reader).ReadLine", Method, 0}, + {"(*Reader).ReadLineBytes", Method, 0}, + {"(*Reader).ReadMIMEHeader", Method, 0}, + {"(*Reader).ReadResponse", Method, 0}, + {"(*Writer).DotWriter", Method, 0}, + {"(*Writer).PrintfLine", Method, 0}, + {"(MIMEHeader).Add", Method, 0}, + {"(MIMEHeader).Del", Method, 0}, + {"(MIMEHeader).Get", Method, 0}, + {"(MIMEHeader).Set", Method, 0}, + {"(MIMEHeader).Values", Method, 14}, + {"(ProtocolError).Error", Method, 0}, + {"CanonicalMIMEHeaderKey", Func, 0}, + {"Conn", Type, 0}, + {"Conn.Pipeline", Field, 0}, + {"Conn.Reader", Field, 0}, + {"Conn.Writer", Field, 0}, + {"Dial", Func, 0}, + {"Error", Type, 0}, + {"Error.Code", Field, 0}, + {"Error.Msg", Field, 0}, + {"MIMEHeader", Type, 0}, + {"NewConn", Func, 0}, + {"NewReader", Func, 0}, + {"NewWriter", Func, 0}, + {"Pipeline", Type, 0}, + {"ProtocolError", Type, 0}, + {"Reader", Type, 0}, + {"Reader.R", Field, 0}, + {"TrimBytes", Func, 1}, + {"TrimString", Func, 1}, + {"Writer", Type, 0}, + {"Writer.W", Field, 0}, + }, + "net/url": { + {"(*Error).Error", Method, 0}, + {"(*Error).Temporary", Method, 6}, + {"(*Error).Timeout", Method, 6}, + {"(*Error).Unwrap", Method, 13}, + {"(*URL).EscapedFragment", Method, 15}, + {"(*URL).EscapedPath", Method, 5}, + {"(*URL).Hostname", Method, 8}, + {"(*URL).IsAbs", Method, 0}, + {"(*URL).JoinPath", Method, 19}, + {"(*URL).MarshalBinary", Method, 8}, + {"(*URL).Parse", Method, 0}, + {"(*URL).Port", Method, 8}, + {"(*URL).Query", Method, 0}, + {"(*URL).Redacted", Method, 15}, + {"(*URL).RequestURI", Method, 0}, + {"(*URL).ResolveReference", Method, 0}, + {"(*URL).String", Method, 0}, + {"(*URL).UnmarshalBinary", Method, 8}, + {"(*Userinfo).Password", Method, 0}, + {"(*Userinfo).String", Method, 0}, + {"(*Userinfo).Username", Method, 0}, + {"(EscapeError).Error", Method, 0}, + {"(InvalidHostError).Error", Method, 6}, + {"(Values).Add", Method, 0}, + {"(Values).Del", Method, 0}, + {"(Values).Encode", Method, 0}, + {"(Values).Get", Method, 0}, + {"(Values).Has", Method, 17}, + {"(Values).Set", Method, 0}, + {"Error", Type, 0}, + {"Error.Err", Field, 0}, + {"Error.Op", Field, 0}, + {"Error.URL", Field, 0}, + {"EscapeError", Type, 0}, + {"InvalidHostError", Type, 6}, + {"JoinPath", Func, 19}, + {"Parse", Func, 0}, + {"ParseQuery", Func, 0}, + {"ParseRequestURI", Func, 0}, + {"PathEscape", Func, 8}, + {"PathUnescape", Func, 8}, + {"QueryEscape", Func, 0}, + {"QueryUnescape", Func, 0}, + {"URL", Type, 0}, + {"URL.ForceQuery", Field, 7}, + {"URL.Fragment", Field, 0}, + {"URL.Host", Field, 0}, + {"URL.OmitHost", Field, 19}, + {"URL.Opaque", Field, 0}, + {"URL.Path", Field, 0}, + {"URL.RawFragment", Field, 15}, + {"URL.RawPath", Field, 5}, + {"URL.RawQuery", Field, 0}, + {"URL.Scheme", Field, 0}, + {"URL.User", Field, 0}, + {"User", Func, 0}, + {"UserPassword", Func, 0}, + {"Userinfo", Type, 0}, + {"Values", Type, 0}, + }, + "os": { + {"(*File).Chdir", Method, 0}, + {"(*File).Chmod", Method, 0}, + {"(*File).Chown", Method, 0}, + {"(*File).Close", Method, 0}, + {"(*File).Fd", Method, 0}, + {"(*File).Name", Method, 0}, + {"(*File).Read", Method, 0}, + {"(*File).ReadAt", Method, 0}, + {"(*File).ReadDir", Method, 16}, + {"(*File).ReadFrom", Method, 15}, + {"(*File).Readdir", Method, 0}, + {"(*File).Readdirnames", Method, 0}, + {"(*File).Seek", Method, 0}, + {"(*File).SetDeadline", Method, 10}, + {"(*File).SetReadDeadline", Method, 10}, + {"(*File).SetWriteDeadline", Method, 10}, + {"(*File).Stat", Method, 0}, + {"(*File).Sync", Method, 0}, + {"(*File).SyscallConn", Method, 12}, + {"(*File).Truncate", Method, 0}, + {"(*File).Write", Method, 0}, + {"(*File).WriteAt", Method, 0}, + {"(*File).WriteString", Method, 0}, + {"(*File).WriteTo", Method, 22}, + {"(*LinkError).Error", Method, 0}, + {"(*LinkError).Unwrap", Method, 13}, + {"(*PathError).Error", Method, 0}, + {"(*PathError).Timeout", Method, 10}, + {"(*PathError).Unwrap", Method, 13}, + {"(*Process).Kill", Method, 0}, + {"(*Process).Release", Method, 0}, + {"(*Process).Signal", Method, 0}, + {"(*Process).Wait", Method, 0}, + {"(*ProcessState).ExitCode", Method, 12}, + {"(*ProcessState).Exited", Method, 0}, + {"(*ProcessState).Pid", Method, 0}, + {"(*ProcessState).String", Method, 0}, + {"(*ProcessState).Success", Method, 0}, + {"(*ProcessState).Sys", Method, 0}, + {"(*ProcessState).SysUsage", Method, 0}, + {"(*ProcessState).SystemTime", Method, 0}, + {"(*ProcessState).UserTime", Method, 0}, + {"(*SyscallError).Error", Method, 0}, + {"(*SyscallError).Timeout", Method, 10}, + {"(*SyscallError).Unwrap", Method, 13}, + {"(FileMode).IsDir", Method, 0}, + {"(FileMode).IsRegular", Method, 1}, + {"(FileMode).Perm", Method, 0}, + {"(FileMode).String", Method, 0}, + {"Args", Var, 0}, + {"Chdir", Func, 0}, + {"Chmod", Func, 0}, + {"Chown", Func, 0}, + {"Chtimes", Func, 0}, + {"Clearenv", Func, 0}, + {"Create", Func, 0}, + {"CreateTemp", Func, 16}, + {"DevNull", Const, 0}, + {"DirEntry", Type, 16}, + {"DirFS", Func, 16}, + {"Environ", Func, 0}, + {"ErrClosed", Var, 8}, + {"ErrDeadlineExceeded", Var, 15}, + {"ErrExist", Var, 0}, + {"ErrInvalid", Var, 0}, + {"ErrNoDeadline", Var, 10}, + {"ErrNotExist", Var, 0}, + {"ErrPermission", Var, 0}, + {"ErrProcessDone", Var, 16}, + {"Executable", Func, 8}, + {"Exit", Func, 0}, + {"Expand", Func, 0}, + {"ExpandEnv", Func, 0}, + {"File", Type, 0}, + {"FileInfo", Type, 0}, + {"FileMode", Type, 0}, + {"FindProcess", Func, 0}, + {"Getegid", Func, 0}, + {"Getenv", Func, 0}, + {"Geteuid", Func, 0}, + {"Getgid", Func, 0}, + {"Getgroups", Func, 0}, + {"Getpagesize", Func, 0}, + {"Getpid", Func, 0}, + {"Getppid", Func, 0}, + {"Getuid", Func, 0}, + {"Getwd", Func, 0}, + {"Hostname", Func, 0}, + {"Interrupt", Var, 0}, + {"IsExist", Func, 0}, + {"IsNotExist", Func, 0}, + {"IsPathSeparator", Func, 0}, + {"IsPermission", Func, 0}, + {"IsTimeout", Func, 10}, + {"Kill", Var, 0}, + {"Lchown", Func, 0}, + {"Link", Func, 0}, + {"LinkError", Type, 0}, + {"LinkError.Err", Field, 0}, + {"LinkError.New", Field, 0}, + {"LinkError.Old", Field, 0}, + {"LinkError.Op", Field, 0}, + {"LookupEnv", Func, 5}, + {"Lstat", Func, 0}, + {"Mkdir", Func, 0}, + {"MkdirAll", Func, 0}, + {"MkdirTemp", Func, 16}, + {"ModeAppend", Const, 0}, + {"ModeCharDevice", Const, 0}, + {"ModeDevice", Const, 0}, + {"ModeDir", Const, 0}, + {"ModeExclusive", Const, 0}, + {"ModeIrregular", Const, 11}, + {"ModeNamedPipe", Const, 0}, + {"ModePerm", Const, 0}, + {"ModeSetgid", Const, 0}, + {"ModeSetuid", Const, 0}, + {"ModeSocket", Const, 0}, + {"ModeSticky", Const, 0}, + {"ModeSymlink", Const, 0}, + {"ModeTemporary", Const, 0}, + {"ModeType", Const, 0}, + {"NewFile", Func, 0}, + {"NewSyscallError", Func, 0}, + {"O_APPEND", Const, 0}, + {"O_CREATE", Const, 0}, + {"O_EXCL", Const, 0}, + {"O_RDONLY", Const, 0}, + {"O_RDWR", Const, 0}, + {"O_SYNC", Const, 0}, + {"O_TRUNC", Const, 0}, + {"O_WRONLY", Const, 0}, + {"Open", Func, 0}, + {"OpenFile", Func, 0}, + {"PathError", Type, 0}, + {"PathError.Err", Field, 0}, + {"PathError.Op", Field, 0}, + {"PathError.Path", Field, 0}, + {"PathListSeparator", Const, 0}, + {"PathSeparator", Const, 0}, + {"Pipe", Func, 0}, + {"ProcAttr", Type, 0}, + {"ProcAttr.Dir", Field, 0}, + {"ProcAttr.Env", Field, 0}, + {"ProcAttr.Files", Field, 0}, + {"ProcAttr.Sys", Field, 0}, + {"Process", Type, 0}, + {"Process.Pid", Field, 0}, + {"ProcessState", Type, 0}, + {"ReadDir", Func, 16}, + {"ReadFile", Func, 16}, + {"Readlink", Func, 0}, + {"Remove", Func, 0}, + {"RemoveAll", Func, 0}, + {"Rename", Func, 0}, + {"SEEK_CUR", Const, 0}, + {"SEEK_END", Const, 0}, + {"SEEK_SET", Const, 0}, + {"SameFile", Func, 0}, + {"Setenv", Func, 0}, + {"Signal", Type, 0}, + {"StartProcess", Func, 0}, + {"Stat", Func, 0}, + {"Stderr", Var, 0}, + {"Stdin", Var, 0}, + {"Stdout", Var, 0}, + {"Symlink", Func, 0}, + {"SyscallError", Type, 0}, + {"SyscallError.Err", Field, 0}, + {"SyscallError.Syscall", Field, 0}, + {"TempDir", Func, 0}, + {"Truncate", Func, 0}, + {"Unsetenv", Func, 4}, + {"UserCacheDir", Func, 11}, + {"UserConfigDir", Func, 13}, + {"UserHomeDir", Func, 12}, + {"WriteFile", Func, 16}, + }, + "os/exec": { + {"(*Cmd).CombinedOutput", Method, 0}, + {"(*Cmd).Environ", Method, 19}, + {"(*Cmd).Output", Method, 0}, + {"(*Cmd).Run", Method, 0}, + {"(*Cmd).Start", Method, 0}, + {"(*Cmd).StderrPipe", Method, 0}, + {"(*Cmd).StdinPipe", Method, 0}, + {"(*Cmd).StdoutPipe", Method, 0}, + {"(*Cmd).String", Method, 13}, + {"(*Cmd).Wait", Method, 0}, + {"(*Error).Error", Method, 0}, + {"(*Error).Unwrap", Method, 13}, + {"(*ExitError).Error", Method, 0}, + {"(ExitError).ExitCode", Method, 12}, + {"(ExitError).Exited", Method, 0}, + {"(ExitError).Pid", Method, 0}, + {"(ExitError).String", Method, 0}, + {"(ExitError).Success", Method, 0}, + {"(ExitError).Sys", Method, 0}, + {"(ExitError).SysUsage", Method, 0}, + {"(ExitError).SystemTime", Method, 0}, + {"(ExitError).UserTime", Method, 0}, + {"Cmd", Type, 0}, + {"Cmd.Args", Field, 0}, + {"Cmd.Cancel", Field, 20}, + {"Cmd.Dir", Field, 0}, + {"Cmd.Env", Field, 0}, + {"Cmd.Err", Field, 19}, + {"Cmd.ExtraFiles", Field, 0}, + {"Cmd.Path", Field, 0}, + {"Cmd.Process", Field, 0}, + {"Cmd.ProcessState", Field, 0}, + {"Cmd.Stderr", Field, 0}, + {"Cmd.Stdin", Field, 0}, + {"Cmd.Stdout", Field, 0}, + {"Cmd.SysProcAttr", Field, 0}, + {"Cmd.WaitDelay", Field, 20}, + {"Command", Func, 0}, + {"CommandContext", Func, 7}, + {"ErrDot", Var, 19}, + {"ErrNotFound", Var, 0}, + {"ErrWaitDelay", Var, 20}, + {"Error", Type, 0}, + {"Error.Err", Field, 0}, + {"Error.Name", Field, 0}, + {"ExitError", Type, 0}, + {"ExitError.ProcessState", Field, 0}, + {"ExitError.Stderr", Field, 6}, + {"LookPath", Func, 0}, + }, + "os/signal": { + {"Ignore", Func, 5}, + {"Ignored", Func, 11}, + {"Notify", Func, 0}, + {"NotifyContext", Func, 16}, + {"Reset", Func, 5}, + {"Stop", Func, 1}, + }, + "os/user": { + {"(*User).GroupIds", Method, 7}, + {"(UnknownGroupError).Error", Method, 7}, + {"(UnknownGroupIdError).Error", Method, 7}, + {"(UnknownUserError).Error", Method, 0}, + {"(UnknownUserIdError).Error", Method, 0}, + {"Current", Func, 0}, + {"Group", Type, 7}, + {"Group.Gid", Field, 7}, + {"Group.Name", Field, 7}, + {"Lookup", Func, 0}, + {"LookupGroup", Func, 7}, + {"LookupGroupId", Func, 7}, + {"LookupId", Func, 0}, + {"UnknownGroupError", Type, 7}, + {"UnknownGroupIdError", Type, 7}, + {"UnknownUserError", Type, 0}, + {"UnknownUserIdError", Type, 0}, + {"User", Type, 0}, + {"User.Gid", Field, 0}, + {"User.HomeDir", Field, 0}, + {"User.Name", Field, 0}, + {"User.Uid", Field, 0}, + {"User.Username", Field, 0}, + }, + "path": { + {"Base", Func, 0}, + {"Clean", Func, 0}, + {"Dir", Func, 0}, + {"ErrBadPattern", Var, 0}, + {"Ext", Func, 0}, + {"IsAbs", Func, 0}, + {"Join", Func, 0}, + {"Match", Func, 0}, + {"Split", Func, 0}, + }, + "path/filepath": { + {"Abs", Func, 0}, + {"Base", Func, 0}, + {"Clean", Func, 0}, + {"Dir", Func, 0}, + {"ErrBadPattern", Var, 0}, + {"EvalSymlinks", Func, 0}, + {"Ext", Func, 0}, + {"FromSlash", Func, 0}, + {"Glob", Func, 0}, + {"HasPrefix", Func, 0}, + {"IsAbs", Func, 0}, + {"IsLocal", Func, 20}, + {"Join", Func, 0}, + {"ListSeparator", Const, 0}, + {"Match", Func, 0}, + {"Rel", Func, 0}, + {"Separator", Const, 0}, + {"SkipAll", Var, 20}, + {"SkipDir", Var, 0}, + {"Split", Func, 0}, + {"SplitList", Func, 0}, + {"ToSlash", Func, 0}, + {"VolumeName", Func, 0}, + {"Walk", Func, 0}, + {"WalkDir", Func, 16}, + {"WalkFunc", Type, 0}, + }, + "plugin": { + {"(*Plugin).Lookup", Method, 8}, + {"Open", Func, 8}, + {"Plugin", Type, 8}, + {"Symbol", Type, 8}, + }, + "reflect": { + {"(*MapIter).Key", Method, 12}, + {"(*MapIter).Next", Method, 12}, + {"(*MapIter).Reset", Method, 18}, + {"(*MapIter).Value", Method, 12}, + {"(*ValueError).Error", Method, 0}, + {"(ChanDir).String", Method, 0}, + {"(Kind).String", Method, 0}, + {"(Method).IsExported", Method, 17}, + {"(StructField).IsExported", Method, 17}, + {"(StructTag).Get", Method, 0}, + {"(StructTag).Lookup", Method, 7}, + {"(Value).Addr", Method, 0}, + {"(Value).Bool", Method, 0}, + {"(Value).Bytes", Method, 0}, + {"(Value).Call", Method, 0}, + {"(Value).CallSlice", Method, 0}, + {"(Value).CanAddr", Method, 0}, + {"(Value).CanComplex", Method, 18}, + {"(Value).CanConvert", Method, 17}, + {"(Value).CanFloat", Method, 18}, + {"(Value).CanInt", Method, 18}, + {"(Value).CanInterface", Method, 0}, + {"(Value).CanSet", Method, 0}, + {"(Value).CanUint", Method, 18}, + {"(Value).Cap", Method, 0}, + {"(Value).Clear", Method, 21}, + {"(Value).Close", Method, 0}, + {"(Value).Comparable", Method, 20}, + {"(Value).Complex", Method, 0}, + {"(Value).Convert", Method, 1}, + {"(Value).Elem", Method, 0}, + {"(Value).Equal", Method, 20}, + {"(Value).Field", Method, 0}, + {"(Value).FieldByIndex", Method, 0}, + {"(Value).FieldByIndexErr", Method, 18}, + {"(Value).FieldByName", Method, 0}, + {"(Value).FieldByNameFunc", Method, 0}, + {"(Value).Float", Method, 0}, + {"(Value).Grow", Method, 20}, + {"(Value).Index", Method, 0}, + {"(Value).Int", Method, 0}, + {"(Value).Interface", Method, 0}, + {"(Value).InterfaceData", Method, 0}, + {"(Value).IsNil", Method, 0}, + {"(Value).IsValid", Method, 0}, + {"(Value).IsZero", Method, 13}, + {"(Value).Kind", Method, 0}, + {"(Value).Len", Method, 0}, + {"(Value).MapIndex", Method, 0}, + {"(Value).MapKeys", Method, 0}, + {"(Value).MapRange", Method, 12}, + {"(Value).Method", Method, 0}, + {"(Value).MethodByName", Method, 0}, + {"(Value).NumField", Method, 0}, + {"(Value).NumMethod", Method, 0}, + {"(Value).OverflowComplex", Method, 0}, + {"(Value).OverflowFloat", Method, 0}, + {"(Value).OverflowInt", Method, 0}, + {"(Value).OverflowUint", Method, 0}, + {"(Value).Pointer", Method, 0}, + {"(Value).Recv", Method, 0}, + {"(Value).Send", Method, 0}, + {"(Value).Set", Method, 0}, + {"(Value).SetBool", Method, 0}, + {"(Value).SetBytes", Method, 0}, + {"(Value).SetCap", Method, 2}, + {"(Value).SetComplex", Method, 0}, + {"(Value).SetFloat", Method, 0}, + {"(Value).SetInt", Method, 0}, + {"(Value).SetIterKey", Method, 18}, + {"(Value).SetIterValue", Method, 18}, + {"(Value).SetLen", Method, 0}, + {"(Value).SetMapIndex", Method, 0}, + {"(Value).SetPointer", Method, 0}, + {"(Value).SetString", Method, 0}, + {"(Value).SetUint", Method, 0}, + {"(Value).SetZero", Method, 20}, + {"(Value).Slice", Method, 0}, + {"(Value).Slice3", Method, 2}, + {"(Value).String", Method, 0}, + {"(Value).TryRecv", Method, 0}, + {"(Value).TrySend", Method, 0}, + {"(Value).Type", Method, 0}, + {"(Value).Uint", Method, 0}, + {"(Value).UnsafeAddr", Method, 0}, + {"(Value).UnsafePointer", Method, 18}, + {"Append", Func, 0}, + {"AppendSlice", Func, 0}, + {"Array", Const, 0}, + {"ArrayOf", Func, 5}, + {"Bool", Const, 0}, + {"BothDir", Const, 0}, + {"Chan", Const, 0}, + {"ChanDir", Type, 0}, + {"ChanOf", Func, 1}, + {"Complex128", Const, 0}, + {"Complex64", Const, 0}, + {"Copy", Func, 0}, + {"DeepEqual", Func, 0}, + {"Float32", Const, 0}, + {"Float64", Const, 0}, + {"Func", Const, 0}, + {"FuncOf", Func, 5}, + {"Indirect", Func, 0}, + {"Int", Const, 0}, + {"Int16", Const, 0}, + {"Int32", Const, 0}, + {"Int64", Const, 0}, + {"Int8", Const, 0}, + {"Interface", Const, 0}, + {"Invalid", Const, 0}, + {"Kind", Type, 0}, + {"MakeChan", Func, 0}, + {"MakeFunc", Func, 1}, + {"MakeMap", Func, 0}, + {"MakeMapWithSize", Func, 9}, + {"MakeSlice", Func, 0}, + {"Map", Const, 0}, + {"MapIter", Type, 12}, + {"MapOf", Func, 1}, + {"Method", Type, 0}, + {"Method.Func", Field, 0}, + {"Method.Index", Field, 0}, + {"Method.Name", Field, 0}, + {"Method.PkgPath", Field, 0}, + {"Method.Type", Field, 0}, + {"New", Func, 0}, + {"NewAt", Func, 0}, + {"Pointer", Const, 18}, + {"PointerTo", Func, 18}, + {"Ptr", Const, 0}, + {"PtrTo", Func, 0}, + {"RecvDir", Const, 0}, + {"Select", Func, 1}, + {"SelectCase", Type, 1}, + {"SelectCase.Chan", Field, 1}, + {"SelectCase.Dir", Field, 1}, + {"SelectCase.Send", Field, 1}, + {"SelectDefault", Const, 1}, + {"SelectDir", Type, 1}, + {"SelectRecv", Const, 1}, + {"SelectSend", Const, 1}, + {"SendDir", Const, 0}, + {"Slice", Const, 0}, + {"SliceHeader", Type, 0}, + {"SliceHeader.Cap", Field, 0}, + {"SliceHeader.Data", Field, 0}, + {"SliceHeader.Len", Field, 0}, + {"SliceOf", Func, 1}, + {"String", Const, 0}, + {"StringHeader", Type, 0}, + {"StringHeader.Data", Field, 0}, + {"StringHeader.Len", Field, 0}, + {"Struct", Const, 0}, + {"StructField", Type, 0}, + {"StructField.Anonymous", Field, 0}, + {"StructField.Index", Field, 0}, + {"StructField.Name", Field, 0}, + {"StructField.Offset", Field, 0}, + {"StructField.PkgPath", Field, 0}, + {"StructField.Tag", Field, 0}, + {"StructField.Type", Field, 0}, + {"StructOf", Func, 7}, + {"StructTag", Type, 0}, + {"Swapper", Func, 8}, + {"Type", Type, 0}, + {"TypeFor", Func, 22}, + {"TypeOf", Func, 0}, + {"Uint", Const, 0}, + {"Uint16", Const, 0}, + {"Uint32", Const, 0}, + {"Uint64", Const, 0}, + {"Uint8", Const, 0}, + {"Uintptr", Const, 0}, + {"UnsafePointer", Const, 0}, + {"Value", Type, 0}, + {"ValueError", Type, 0}, + {"ValueError.Kind", Field, 0}, + {"ValueError.Method", Field, 0}, + {"ValueOf", Func, 0}, + {"VisibleFields", Func, 17}, + {"Zero", Func, 0}, + }, + "regexp": { + {"(*Regexp).Copy", Method, 6}, + {"(*Regexp).Expand", Method, 0}, + {"(*Regexp).ExpandString", Method, 0}, + {"(*Regexp).Find", Method, 0}, + {"(*Regexp).FindAll", Method, 0}, + {"(*Regexp).FindAllIndex", Method, 0}, + {"(*Regexp).FindAllString", Method, 0}, + {"(*Regexp).FindAllStringIndex", Method, 0}, + {"(*Regexp).FindAllStringSubmatch", Method, 0}, + {"(*Regexp).FindAllStringSubmatchIndex", Method, 0}, + {"(*Regexp).FindAllSubmatch", Method, 0}, + {"(*Regexp).FindAllSubmatchIndex", Method, 0}, + {"(*Regexp).FindIndex", Method, 0}, + {"(*Regexp).FindReaderIndex", Method, 0}, + {"(*Regexp).FindReaderSubmatchIndex", Method, 0}, + {"(*Regexp).FindString", Method, 0}, + {"(*Regexp).FindStringIndex", Method, 0}, + {"(*Regexp).FindStringSubmatch", Method, 0}, + {"(*Regexp).FindStringSubmatchIndex", Method, 0}, + {"(*Regexp).FindSubmatch", Method, 0}, + {"(*Regexp).FindSubmatchIndex", Method, 0}, + {"(*Regexp).LiteralPrefix", Method, 0}, + {"(*Regexp).Longest", Method, 1}, + {"(*Regexp).MarshalText", Method, 21}, + {"(*Regexp).Match", Method, 0}, + {"(*Regexp).MatchReader", Method, 0}, + {"(*Regexp).MatchString", Method, 0}, + {"(*Regexp).NumSubexp", Method, 0}, + {"(*Regexp).ReplaceAll", Method, 0}, + {"(*Regexp).ReplaceAllFunc", Method, 0}, + {"(*Regexp).ReplaceAllLiteral", Method, 0}, + {"(*Regexp).ReplaceAllLiteralString", Method, 0}, + {"(*Regexp).ReplaceAllString", Method, 0}, + {"(*Regexp).ReplaceAllStringFunc", Method, 0}, + {"(*Regexp).Split", Method, 1}, + {"(*Regexp).String", Method, 0}, + {"(*Regexp).SubexpIndex", Method, 15}, + {"(*Regexp).SubexpNames", Method, 0}, + {"(*Regexp).UnmarshalText", Method, 21}, + {"Compile", Func, 0}, + {"CompilePOSIX", Func, 0}, + {"Match", Func, 0}, + {"MatchReader", Func, 0}, + {"MatchString", Func, 0}, + {"MustCompile", Func, 0}, + {"MustCompilePOSIX", Func, 0}, + {"QuoteMeta", Func, 0}, + {"Regexp", Type, 0}, + }, + "regexp/syntax": { + {"(*Error).Error", Method, 0}, + {"(*Inst).MatchEmptyWidth", Method, 0}, + {"(*Inst).MatchRune", Method, 0}, + {"(*Inst).MatchRunePos", Method, 3}, + {"(*Inst).String", Method, 0}, + {"(*Prog).Prefix", Method, 0}, + {"(*Prog).StartCond", Method, 0}, + {"(*Prog).String", Method, 0}, + {"(*Regexp).CapNames", Method, 0}, + {"(*Regexp).Equal", Method, 0}, + {"(*Regexp).MaxCap", Method, 0}, + {"(*Regexp).Simplify", Method, 0}, + {"(*Regexp).String", Method, 0}, + {"(ErrorCode).String", Method, 0}, + {"(InstOp).String", Method, 3}, + {"(Op).String", Method, 11}, + {"ClassNL", Const, 0}, + {"Compile", Func, 0}, + {"DotNL", Const, 0}, + {"EmptyBeginLine", Const, 0}, + {"EmptyBeginText", Const, 0}, + {"EmptyEndLine", Const, 0}, + {"EmptyEndText", Const, 0}, + {"EmptyNoWordBoundary", Const, 0}, + {"EmptyOp", Type, 0}, + {"EmptyOpContext", Func, 0}, + {"EmptyWordBoundary", Const, 0}, + {"ErrInternalError", Const, 0}, + {"ErrInvalidCharClass", Const, 0}, + {"ErrInvalidCharRange", Const, 0}, + {"ErrInvalidEscape", Const, 0}, + {"ErrInvalidNamedCapture", Const, 0}, + {"ErrInvalidPerlOp", Const, 0}, + {"ErrInvalidRepeatOp", Const, 0}, + {"ErrInvalidRepeatSize", Const, 0}, + {"ErrInvalidUTF8", Const, 0}, + {"ErrLarge", Const, 20}, + {"ErrMissingBracket", Const, 0}, + {"ErrMissingParen", Const, 0}, + {"ErrMissingRepeatArgument", Const, 0}, + {"ErrNestingDepth", Const, 19}, + {"ErrTrailingBackslash", Const, 0}, + {"ErrUnexpectedParen", Const, 1}, + {"Error", Type, 0}, + {"Error.Code", Field, 0}, + {"Error.Expr", Field, 0}, + {"ErrorCode", Type, 0}, + {"Flags", Type, 0}, + {"FoldCase", Const, 0}, + {"Inst", Type, 0}, + {"Inst.Arg", Field, 0}, + {"Inst.Op", Field, 0}, + {"Inst.Out", Field, 0}, + {"Inst.Rune", Field, 0}, + {"InstAlt", Const, 0}, + {"InstAltMatch", Const, 0}, + {"InstCapture", Const, 0}, + {"InstEmptyWidth", Const, 0}, + {"InstFail", Const, 0}, + {"InstMatch", Const, 0}, + {"InstNop", Const, 0}, + {"InstOp", Type, 0}, + {"InstRune", Const, 0}, + {"InstRune1", Const, 0}, + {"InstRuneAny", Const, 0}, + {"InstRuneAnyNotNL", Const, 0}, + {"IsWordChar", Func, 0}, + {"Literal", Const, 0}, + {"MatchNL", Const, 0}, + {"NonGreedy", Const, 0}, + {"OneLine", Const, 0}, + {"Op", Type, 0}, + {"OpAlternate", Const, 0}, + {"OpAnyChar", Const, 0}, + {"OpAnyCharNotNL", Const, 0}, + {"OpBeginLine", Const, 0}, + {"OpBeginText", Const, 0}, + {"OpCapture", Const, 0}, + {"OpCharClass", Const, 0}, + {"OpConcat", Const, 0}, + {"OpEmptyMatch", Const, 0}, + {"OpEndLine", Const, 0}, + {"OpEndText", Const, 0}, + {"OpLiteral", Const, 0}, + {"OpNoMatch", Const, 0}, + {"OpNoWordBoundary", Const, 0}, + {"OpPlus", Const, 0}, + {"OpQuest", Const, 0}, + {"OpRepeat", Const, 0}, + {"OpStar", Const, 0}, + {"OpWordBoundary", Const, 0}, + {"POSIX", Const, 0}, + {"Parse", Func, 0}, + {"Perl", Const, 0}, + {"PerlX", Const, 0}, + {"Prog", Type, 0}, + {"Prog.Inst", Field, 0}, + {"Prog.NumCap", Field, 0}, + {"Prog.Start", Field, 0}, + {"Regexp", Type, 0}, + {"Regexp.Cap", Field, 0}, + {"Regexp.Flags", Field, 0}, + {"Regexp.Max", Field, 0}, + {"Regexp.Min", Field, 0}, + {"Regexp.Name", Field, 0}, + {"Regexp.Op", Field, 0}, + {"Regexp.Rune", Field, 0}, + {"Regexp.Rune0", Field, 0}, + {"Regexp.Sub", Field, 0}, + {"Regexp.Sub0", Field, 0}, + {"Simple", Const, 0}, + {"UnicodeGroups", Const, 0}, + {"WasDollar", Const, 0}, + }, + "runtime": { + {"(*BlockProfileRecord).Stack", Method, 1}, + {"(*Frames).Next", Method, 7}, + {"(*Func).Entry", Method, 0}, + {"(*Func).FileLine", Method, 0}, + {"(*Func).Name", Method, 0}, + {"(*MemProfileRecord).InUseBytes", Method, 0}, + {"(*MemProfileRecord).InUseObjects", Method, 0}, + {"(*MemProfileRecord).Stack", Method, 0}, + {"(*PanicNilError).Error", Method, 21}, + {"(*PanicNilError).RuntimeError", Method, 21}, + {"(*Pinner).Pin", Method, 21}, + {"(*Pinner).Unpin", Method, 21}, + {"(*StackRecord).Stack", Method, 0}, + {"(*TypeAssertionError).Error", Method, 0}, + {"(*TypeAssertionError).RuntimeError", Method, 0}, + {"BlockProfile", Func, 1}, + {"BlockProfileRecord", Type, 1}, + {"BlockProfileRecord.Count", Field, 1}, + {"BlockProfileRecord.Cycles", Field, 1}, + {"BlockProfileRecord.StackRecord", Field, 1}, + {"Breakpoint", Func, 0}, + {"CPUProfile", Func, 0}, + {"Caller", Func, 0}, + {"Callers", Func, 0}, + {"CallersFrames", Func, 7}, + {"Compiler", Const, 0}, + {"Error", Type, 0}, + {"Frame", Type, 7}, + {"Frame.Entry", Field, 7}, + {"Frame.File", Field, 7}, + {"Frame.Func", Field, 7}, + {"Frame.Function", Field, 7}, + {"Frame.Line", Field, 7}, + {"Frame.PC", Field, 7}, + {"Frames", Type, 7}, + {"Func", Type, 0}, + {"FuncForPC", Func, 0}, + {"GC", Func, 0}, + {"GOARCH", Const, 0}, + {"GOMAXPROCS", Func, 0}, + {"GOOS", Const, 0}, + {"GOROOT", Func, 0}, + {"Goexit", Func, 0}, + {"GoroutineProfile", Func, 0}, + {"Gosched", Func, 0}, + {"KeepAlive", Func, 7}, + {"LockOSThread", Func, 0}, + {"MemProfile", Func, 0}, + {"MemProfileRate", Var, 0}, + {"MemProfileRecord", Type, 0}, + {"MemProfileRecord.AllocBytes", Field, 0}, + {"MemProfileRecord.AllocObjects", Field, 0}, + {"MemProfileRecord.FreeBytes", Field, 0}, + {"MemProfileRecord.FreeObjects", Field, 0}, + {"MemProfileRecord.Stack0", Field, 0}, + {"MemStats", Type, 0}, + {"MemStats.Alloc", Field, 0}, + {"MemStats.BuckHashSys", Field, 0}, + {"MemStats.BySize", Field, 0}, + {"MemStats.DebugGC", Field, 0}, + {"MemStats.EnableGC", Field, 0}, + {"MemStats.Frees", Field, 0}, + {"MemStats.GCCPUFraction", Field, 5}, + {"MemStats.GCSys", Field, 2}, + {"MemStats.HeapAlloc", Field, 0}, + {"MemStats.HeapIdle", Field, 0}, + {"MemStats.HeapInuse", Field, 0}, + {"MemStats.HeapObjects", Field, 0}, + {"MemStats.HeapReleased", Field, 0}, + {"MemStats.HeapSys", Field, 0}, + {"MemStats.LastGC", Field, 0}, + {"MemStats.Lookups", Field, 0}, + {"MemStats.MCacheInuse", Field, 0}, + {"MemStats.MCacheSys", Field, 0}, + {"MemStats.MSpanInuse", Field, 0}, + {"MemStats.MSpanSys", Field, 0}, + {"MemStats.Mallocs", Field, 0}, + {"MemStats.NextGC", Field, 0}, + {"MemStats.NumForcedGC", Field, 8}, + {"MemStats.NumGC", Field, 0}, + {"MemStats.OtherSys", Field, 2}, + {"MemStats.PauseEnd", Field, 4}, + {"MemStats.PauseNs", Field, 0}, + {"MemStats.PauseTotalNs", Field, 0}, + {"MemStats.StackInuse", Field, 0}, + {"MemStats.StackSys", Field, 0}, + {"MemStats.Sys", Field, 0}, + {"MemStats.TotalAlloc", Field, 0}, + {"MutexProfile", Func, 8}, + {"NumCPU", Func, 0}, + {"NumCgoCall", Func, 0}, + {"NumGoroutine", Func, 0}, + {"PanicNilError", Type, 21}, + {"Pinner", Type, 21}, + {"ReadMemStats", Func, 0}, + {"ReadTrace", Func, 5}, + {"SetBlockProfileRate", Func, 1}, + {"SetCPUProfileRate", Func, 0}, + {"SetCgoTraceback", Func, 7}, + {"SetFinalizer", Func, 0}, + {"SetMutexProfileFraction", Func, 8}, + {"Stack", Func, 0}, + {"StackRecord", Type, 0}, + {"StackRecord.Stack0", Field, 0}, + {"StartTrace", Func, 5}, + {"StopTrace", Func, 5}, + {"ThreadCreateProfile", Func, 0}, + {"TypeAssertionError", Type, 0}, + {"UnlockOSThread", Func, 0}, + {"Version", Func, 0}, + }, + "runtime/cgo": { + {"(Handle).Delete", Method, 17}, + {"(Handle).Value", Method, 17}, + {"Handle", Type, 17}, + {"Incomplete", Type, 20}, + {"NewHandle", Func, 17}, + }, + "runtime/coverage": { + {"ClearCounters", Func, 20}, + {"WriteCounters", Func, 20}, + {"WriteCountersDir", Func, 20}, + {"WriteMeta", Func, 20}, + {"WriteMetaDir", Func, 20}, + }, + "runtime/debug": { + {"(*BuildInfo).String", Method, 18}, + {"BuildInfo", Type, 12}, + {"BuildInfo.Deps", Field, 12}, + {"BuildInfo.GoVersion", Field, 18}, + {"BuildInfo.Main", Field, 12}, + {"BuildInfo.Path", Field, 12}, + {"BuildInfo.Settings", Field, 18}, + {"BuildSetting", Type, 18}, + {"BuildSetting.Key", Field, 18}, + {"BuildSetting.Value", Field, 18}, + {"FreeOSMemory", Func, 1}, + {"GCStats", Type, 1}, + {"GCStats.LastGC", Field, 1}, + {"GCStats.NumGC", Field, 1}, + {"GCStats.Pause", Field, 1}, + {"GCStats.PauseEnd", Field, 4}, + {"GCStats.PauseQuantiles", Field, 1}, + {"GCStats.PauseTotal", Field, 1}, + {"Module", Type, 12}, + {"Module.Path", Field, 12}, + {"Module.Replace", Field, 12}, + {"Module.Sum", Field, 12}, + {"Module.Version", Field, 12}, + {"ParseBuildInfo", Func, 18}, + {"PrintStack", Func, 0}, + {"ReadBuildInfo", Func, 12}, + {"ReadGCStats", Func, 1}, + {"SetGCPercent", Func, 1}, + {"SetMaxStack", Func, 2}, + {"SetMaxThreads", Func, 2}, + {"SetMemoryLimit", Func, 19}, + {"SetPanicOnFault", Func, 3}, + {"SetTraceback", Func, 6}, + {"Stack", Func, 0}, + {"WriteHeapDump", Func, 3}, + }, + "runtime/metrics": { + {"(Value).Float64", Method, 16}, + {"(Value).Float64Histogram", Method, 16}, + {"(Value).Kind", Method, 16}, + {"(Value).Uint64", Method, 16}, + {"All", Func, 16}, + {"Description", Type, 16}, + {"Description.Cumulative", Field, 16}, + {"Description.Description", Field, 16}, + {"Description.Kind", Field, 16}, + {"Description.Name", Field, 16}, + {"Float64Histogram", Type, 16}, + {"Float64Histogram.Buckets", Field, 16}, + {"Float64Histogram.Counts", Field, 16}, + {"KindBad", Const, 16}, + {"KindFloat64", Const, 16}, + {"KindFloat64Histogram", Const, 16}, + {"KindUint64", Const, 16}, + {"Read", Func, 16}, + {"Sample", Type, 16}, + {"Sample.Name", Field, 16}, + {"Sample.Value", Field, 16}, + {"Value", Type, 16}, + {"ValueKind", Type, 16}, + }, + "runtime/pprof": { + {"(*Profile).Add", Method, 0}, + {"(*Profile).Count", Method, 0}, + {"(*Profile).Name", Method, 0}, + {"(*Profile).Remove", Method, 0}, + {"(*Profile).WriteTo", Method, 0}, + {"Do", Func, 9}, + {"ForLabels", Func, 9}, + {"Label", Func, 9}, + {"LabelSet", Type, 9}, + {"Labels", Func, 9}, + {"Lookup", Func, 0}, + {"NewProfile", Func, 0}, + {"Profile", Type, 0}, + {"Profiles", Func, 0}, + {"SetGoroutineLabels", Func, 9}, + {"StartCPUProfile", Func, 0}, + {"StopCPUProfile", Func, 0}, + {"WithLabels", Func, 9}, + {"WriteHeapProfile", Func, 0}, + }, + "runtime/trace": { + {"(*Region).End", Method, 11}, + {"(*Task).End", Method, 11}, + {"IsEnabled", Func, 11}, + {"Log", Func, 11}, + {"Logf", Func, 11}, + {"NewTask", Func, 11}, + {"Region", Type, 11}, + {"Start", Func, 5}, + {"StartRegion", Func, 11}, + {"Stop", Func, 5}, + {"Task", Type, 11}, + {"WithRegion", Func, 11}, + }, + "slices": { + {"BinarySearch", Func, 21}, + {"BinarySearchFunc", Func, 21}, + {"Clip", Func, 21}, + {"Clone", Func, 21}, + {"Compact", Func, 21}, + {"CompactFunc", Func, 21}, + {"Compare", Func, 21}, + {"CompareFunc", Func, 21}, + {"Concat", Func, 22}, + {"Contains", Func, 21}, + {"ContainsFunc", Func, 21}, + {"Delete", Func, 21}, + {"DeleteFunc", Func, 21}, + {"Equal", Func, 21}, + {"EqualFunc", Func, 21}, + {"Grow", Func, 21}, + {"Index", Func, 21}, + {"IndexFunc", Func, 21}, + {"Insert", Func, 21}, + {"IsSorted", Func, 21}, + {"IsSortedFunc", Func, 21}, + {"Max", Func, 21}, + {"MaxFunc", Func, 21}, + {"Min", Func, 21}, + {"MinFunc", Func, 21}, + {"Replace", Func, 21}, + {"Reverse", Func, 21}, + {"Sort", Func, 21}, + {"SortFunc", Func, 21}, + {"SortStableFunc", Func, 21}, + }, + "sort": { + {"(Float64Slice).Len", Method, 0}, + {"(Float64Slice).Less", Method, 0}, + {"(Float64Slice).Search", Method, 0}, + {"(Float64Slice).Sort", Method, 0}, + {"(Float64Slice).Swap", Method, 0}, + {"(IntSlice).Len", Method, 0}, + {"(IntSlice).Less", Method, 0}, + {"(IntSlice).Search", Method, 0}, + {"(IntSlice).Sort", Method, 0}, + {"(IntSlice).Swap", Method, 0}, + {"(StringSlice).Len", Method, 0}, + {"(StringSlice).Less", Method, 0}, + {"(StringSlice).Search", Method, 0}, + {"(StringSlice).Sort", Method, 0}, + {"(StringSlice).Swap", Method, 0}, + {"Find", Func, 19}, + {"Float64Slice", Type, 0}, + {"Float64s", Func, 0}, + {"Float64sAreSorted", Func, 0}, + {"IntSlice", Type, 0}, + {"Interface", Type, 0}, + {"Ints", Func, 0}, + {"IntsAreSorted", Func, 0}, + {"IsSorted", Func, 0}, + {"Reverse", Func, 1}, + {"Search", Func, 0}, + {"SearchFloat64s", Func, 0}, + {"SearchInts", Func, 0}, + {"SearchStrings", Func, 0}, + {"Slice", Func, 8}, + {"SliceIsSorted", Func, 8}, + {"SliceStable", Func, 8}, + {"Sort", Func, 0}, + {"Stable", Func, 2}, + {"StringSlice", Type, 0}, + {"Strings", Func, 0}, + {"StringsAreSorted", Func, 0}, + }, + "strconv": { + {"(*NumError).Error", Method, 0}, + {"(*NumError).Unwrap", Method, 14}, + {"AppendBool", Func, 0}, + {"AppendFloat", Func, 0}, + {"AppendInt", Func, 0}, + {"AppendQuote", Func, 0}, + {"AppendQuoteRune", Func, 0}, + {"AppendQuoteRuneToASCII", Func, 0}, + {"AppendQuoteRuneToGraphic", Func, 6}, + {"AppendQuoteToASCII", Func, 0}, + {"AppendQuoteToGraphic", Func, 6}, + {"AppendUint", Func, 0}, + {"Atoi", Func, 0}, + {"CanBackquote", Func, 0}, + {"ErrRange", Var, 0}, + {"ErrSyntax", Var, 0}, + {"FormatBool", Func, 0}, + {"FormatComplex", Func, 15}, + {"FormatFloat", Func, 0}, + {"FormatInt", Func, 0}, + {"FormatUint", Func, 0}, + {"IntSize", Const, 0}, + {"IsGraphic", Func, 6}, + {"IsPrint", Func, 0}, + {"Itoa", Func, 0}, + {"NumError", Type, 0}, + {"NumError.Err", Field, 0}, + {"NumError.Func", Field, 0}, + {"NumError.Num", Field, 0}, + {"ParseBool", Func, 0}, + {"ParseComplex", Func, 15}, + {"ParseFloat", Func, 0}, + {"ParseInt", Func, 0}, + {"ParseUint", Func, 0}, + {"Quote", Func, 0}, + {"QuoteRune", Func, 0}, + {"QuoteRuneToASCII", Func, 0}, + {"QuoteRuneToGraphic", Func, 6}, + {"QuoteToASCII", Func, 0}, + {"QuoteToGraphic", Func, 6}, + {"QuotedPrefix", Func, 17}, + {"Unquote", Func, 0}, + {"UnquoteChar", Func, 0}, + }, + "strings": { + {"(*Builder).Cap", Method, 12}, + {"(*Builder).Grow", Method, 10}, + {"(*Builder).Len", Method, 10}, + {"(*Builder).Reset", Method, 10}, + {"(*Builder).String", Method, 10}, + {"(*Builder).Write", Method, 10}, + {"(*Builder).WriteByte", Method, 10}, + {"(*Builder).WriteRune", Method, 10}, + {"(*Builder).WriteString", Method, 10}, + {"(*Reader).Len", Method, 0}, + {"(*Reader).Read", Method, 0}, + {"(*Reader).ReadAt", Method, 0}, + {"(*Reader).ReadByte", Method, 0}, + {"(*Reader).ReadRune", Method, 0}, + {"(*Reader).Reset", Method, 7}, + {"(*Reader).Seek", Method, 0}, + {"(*Reader).Size", Method, 5}, + {"(*Reader).UnreadByte", Method, 0}, + {"(*Reader).UnreadRune", Method, 0}, + {"(*Reader).WriteTo", Method, 1}, + {"(*Replacer).Replace", Method, 0}, + {"(*Replacer).WriteString", Method, 0}, + {"Builder", Type, 10}, + {"Clone", Func, 18}, + {"Compare", Func, 5}, + {"Contains", Func, 0}, + {"ContainsAny", Func, 0}, + {"ContainsFunc", Func, 21}, + {"ContainsRune", Func, 0}, + {"Count", Func, 0}, + {"Cut", Func, 18}, + {"CutPrefix", Func, 20}, + {"CutSuffix", Func, 20}, + {"EqualFold", Func, 0}, + {"Fields", Func, 0}, + {"FieldsFunc", Func, 0}, + {"HasPrefix", Func, 0}, + {"HasSuffix", Func, 0}, + {"Index", Func, 0}, + {"IndexAny", Func, 0}, + {"IndexByte", Func, 2}, + {"IndexFunc", Func, 0}, + {"IndexRune", Func, 0}, + {"Join", Func, 0}, + {"LastIndex", Func, 0}, + {"LastIndexAny", Func, 0}, + {"LastIndexByte", Func, 5}, + {"LastIndexFunc", Func, 0}, + {"Map", Func, 0}, + {"NewReader", Func, 0}, + {"NewReplacer", Func, 0}, + {"Reader", Type, 0}, + {"Repeat", Func, 0}, + {"Replace", Func, 0}, + {"ReplaceAll", Func, 12}, + {"Replacer", Type, 0}, + {"Split", Func, 0}, + {"SplitAfter", Func, 0}, + {"SplitAfterN", Func, 0}, + {"SplitN", Func, 0}, + {"Title", Func, 0}, + {"ToLower", Func, 0}, + {"ToLowerSpecial", Func, 0}, + {"ToTitle", Func, 0}, + {"ToTitleSpecial", Func, 0}, + {"ToUpper", Func, 0}, + {"ToUpperSpecial", Func, 0}, + {"ToValidUTF8", Func, 13}, + {"Trim", Func, 0}, + {"TrimFunc", Func, 0}, + {"TrimLeft", Func, 0}, + {"TrimLeftFunc", Func, 0}, + {"TrimPrefix", Func, 1}, + {"TrimRight", Func, 0}, + {"TrimRightFunc", Func, 0}, + {"TrimSpace", Func, 0}, + {"TrimSuffix", Func, 1}, + }, + "sync": { + {"(*Cond).Broadcast", Method, 0}, + {"(*Cond).Signal", Method, 0}, + {"(*Cond).Wait", Method, 0}, + {"(*Map).CompareAndDelete", Method, 20}, + {"(*Map).CompareAndSwap", Method, 20}, + {"(*Map).Delete", Method, 9}, + {"(*Map).Load", Method, 9}, + {"(*Map).LoadAndDelete", Method, 15}, + {"(*Map).LoadOrStore", Method, 9}, + {"(*Map).Range", Method, 9}, + {"(*Map).Store", Method, 9}, + {"(*Map).Swap", Method, 20}, + {"(*Mutex).Lock", Method, 0}, + {"(*Mutex).TryLock", Method, 18}, + {"(*Mutex).Unlock", Method, 0}, + {"(*Once).Do", Method, 0}, + {"(*Pool).Get", Method, 3}, + {"(*Pool).Put", Method, 3}, + {"(*RWMutex).Lock", Method, 0}, + {"(*RWMutex).RLock", Method, 0}, + {"(*RWMutex).RLocker", Method, 0}, + {"(*RWMutex).RUnlock", Method, 0}, + {"(*RWMutex).TryLock", Method, 18}, + {"(*RWMutex).TryRLock", Method, 18}, + {"(*RWMutex).Unlock", Method, 0}, + {"(*WaitGroup).Add", Method, 0}, + {"(*WaitGroup).Done", Method, 0}, + {"(*WaitGroup).Wait", Method, 0}, + {"Cond", Type, 0}, + {"Cond.L", Field, 0}, + {"Locker", Type, 0}, + {"Map", Type, 9}, + {"Mutex", Type, 0}, + {"NewCond", Func, 0}, + {"Once", Type, 0}, + {"OnceFunc", Func, 21}, + {"OnceValue", Func, 21}, + {"OnceValues", Func, 21}, + {"Pool", Type, 3}, + {"Pool.New", Field, 3}, + {"RWMutex", Type, 0}, + {"WaitGroup", Type, 0}, + }, + "sync/atomic": { + {"(*Bool).CompareAndSwap", Method, 19}, + {"(*Bool).Load", Method, 19}, + {"(*Bool).Store", Method, 19}, + {"(*Bool).Swap", Method, 19}, + {"(*Int32).Add", Method, 19}, + {"(*Int32).CompareAndSwap", Method, 19}, + {"(*Int32).Load", Method, 19}, + {"(*Int32).Store", Method, 19}, + {"(*Int32).Swap", Method, 19}, + {"(*Int64).Add", Method, 19}, + {"(*Int64).CompareAndSwap", Method, 19}, + {"(*Int64).Load", Method, 19}, + {"(*Int64).Store", Method, 19}, + {"(*Int64).Swap", Method, 19}, + {"(*Pointer).CompareAndSwap", Method, 19}, + {"(*Pointer).Load", Method, 19}, + {"(*Pointer).Store", Method, 19}, + {"(*Pointer).Swap", Method, 19}, + {"(*Uint32).Add", Method, 19}, + {"(*Uint32).CompareAndSwap", Method, 19}, + {"(*Uint32).Load", Method, 19}, + {"(*Uint32).Store", Method, 19}, + {"(*Uint32).Swap", Method, 19}, + {"(*Uint64).Add", Method, 19}, + {"(*Uint64).CompareAndSwap", Method, 19}, + {"(*Uint64).Load", Method, 19}, + {"(*Uint64).Store", Method, 19}, + {"(*Uint64).Swap", Method, 19}, + {"(*Uintptr).Add", Method, 19}, + {"(*Uintptr).CompareAndSwap", Method, 19}, + {"(*Uintptr).Load", Method, 19}, + {"(*Uintptr).Store", Method, 19}, + {"(*Uintptr).Swap", Method, 19}, + {"(*Value).CompareAndSwap", Method, 17}, + {"(*Value).Load", Method, 4}, + {"(*Value).Store", Method, 4}, + {"(*Value).Swap", Method, 17}, + {"AddInt32", Func, 0}, + {"AddInt64", Func, 0}, + {"AddUint32", Func, 0}, + {"AddUint64", Func, 0}, + {"AddUintptr", Func, 0}, + {"Bool", Type, 19}, + {"CompareAndSwapInt32", Func, 0}, + {"CompareAndSwapInt64", Func, 0}, + {"CompareAndSwapPointer", Func, 0}, + {"CompareAndSwapUint32", Func, 0}, + {"CompareAndSwapUint64", Func, 0}, + {"CompareAndSwapUintptr", Func, 0}, + {"Int32", Type, 19}, + {"Int64", Type, 19}, + {"LoadInt32", Func, 0}, + {"LoadInt64", Func, 0}, + {"LoadPointer", Func, 0}, + {"LoadUint32", Func, 0}, + {"LoadUint64", Func, 0}, + {"LoadUintptr", Func, 0}, + {"Pointer", Type, 19}, + {"StoreInt32", Func, 0}, + {"StoreInt64", Func, 0}, + {"StorePointer", Func, 0}, + {"StoreUint32", Func, 0}, + {"StoreUint64", Func, 0}, + {"StoreUintptr", Func, 0}, + {"SwapInt32", Func, 2}, + {"SwapInt64", Func, 2}, + {"SwapPointer", Func, 2}, + {"SwapUint32", Func, 2}, + {"SwapUint64", Func, 2}, + {"SwapUintptr", Func, 2}, + {"Uint32", Type, 19}, + {"Uint64", Type, 19}, + {"Uintptr", Type, 19}, + {"Value", Type, 4}, + }, + "syscall": { + {"(*Cmsghdr).SetLen", Method, 0}, + {"(*DLL).FindProc", Method, 0}, + {"(*DLL).MustFindProc", Method, 0}, + {"(*DLL).Release", Method, 0}, + {"(*DLLError).Error", Method, 0}, + {"(*DLLError).Unwrap", Method, 16}, + {"(*Filetime).Nanoseconds", Method, 0}, + {"(*Iovec).SetLen", Method, 0}, + {"(*LazyDLL).Handle", Method, 0}, + {"(*LazyDLL).Load", Method, 0}, + {"(*LazyDLL).NewProc", Method, 0}, + {"(*LazyProc).Addr", Method, 0}, + {"(*LazyProc).Call", Method, 0}, + {"(*LazyProc).Find", Method, 0}, + {"(*Msghdr).SetControllen", Method, 0}, + {"(*Proc).Addr", Method, 0}, + {"(*Proc).Call", Method, 0}, + {"(*PtraceRegs).PC", Method, 0}, + {"(*PtraceRegs).SetPC", Method, 0}, + {"(*RawSockaddrAny).Sockaddr", Method, 0}, + {"(*SID).Copy", Method, 0}, + {"(*SID).Len", Method, 0}, + {"(*SID).LookupAccount", Method, 0}, + {"(*SID).String", Method, 0}, + {"(*Timespec).Nano", Method, 0}, + {"(*Timespec).Unix", Method, 0}, + {"(*Timeval).Nano", Method, 0}, + {"(*Timeval).Nanoseconds", Method, 0}, + {"(*Timeval).Unix", Method, 0}, + {"(Errno).Error", Method, 0}, + {"(Errno).Is", Method, 13}, + {"(Errno).Temporary", Method, 0}, + {"(Errno).Timeout", Method, 0}, + {"(Signal).Signal", Method, 0}, + {"(Signal).String", Method, 0}, + {"(Token).Close", Method, 0}, + {"(Token).GetTokenPrimaryGroup", Method, 0}, + {"(Token).GetTokenUser", Method, 0}, + {"(Token).GetUserProfileDirectory", Method, 0}, + {"(WaitStatus).Continued", Method, 0}, + {"(WaitStatus).CoreDump", Method, 0}, + {"(WaitStatus).ExitStatus", Method, 0}, + {"(WaitStatus).Exited", Method, 0}, + {"(WaitStatus).Signal", Method, 0}, + {"(WaitStatus).Signaled", Method, 0}, + {"(WaitStatus).StopSignal", Method, 0}, + {"(WaitStatus).Stopped", Method, 0}, + {"(WaitStatus).TrapCause", Method, 0}, + {"AF_ALG", Const, 0}, + {"AF_APPLETALK", Const, 0}, + {"AF_ARP", Const, 0}, + {"AF_ASH", Const, 0}, + {"AF_ATM", Const, 0}, + {"AF_ATMPVC", Const, 0}, + {"AF_ATMSVC", Const, 0}, + {"AF_AX25", Const, 0}, + {"AF_BLUETOOTH", Const, 0}, + {"AF_BRIDGE", Const, 0}, + {"AF_CAIF", Const, 0}, + {"AF_CAN", Const, 0}, + {"AF_CCITT", Const, 0}, + {"AF_CHAOS", Const, 0}, + {"AF_CNT", Const, 0}, + {"AF_COIP", Const, 0}, + {"AF_DATAKIT", Const, 0}, + {"AF_DECnet", Const, 0}, + {"AF_DLI", Const, 0}, + {"AF_E164", Const, 0}, + {"AF_ECMA", Const, 0}, + {"AF_ECONET", Const, 0}, + {"AF_ENCAP", Const, 1}, + {"AF_FILE", Const, 0}, + {"AF_HYLINK", Const, 0}, + {"AF_IEEE80211", Const, 0}, + {"AF_IEEE802154", Const, 0}, + {"AF_IMPLINK", Const, 0}, + {"AF_INET", Const, 0}, + {"AF_INET6", Const, 0}, + {"AF_INET6_SDP", Const, 3}, + {"AF_INET_SDP", Const, 3}, + {"AF_IPX", Const, 0}, + {"AF_IRDA", Const, 0}, + {"AF_ISDN", Const, 0}, + {"AF_ISO", Const, 0}, + {"AF_IUCV", Const, 0}, + {"AF_KEY", Const, 0}, + {"AF_LAT", Const, 0}, + {"AF_LINK", Const, 0}, + {"AF_LLC", Const, 0}, + {"AF_LOCAL", Const, 0}, + {"AF_MAX", Const, 0}, + {"AF_MPLS", Const, 1}, + {"AF_NATM", Const, 0}, + {"AF_NDRV", Const, 0}, + {"AF_NETBEUI", Const, 0}, + {"AF_NETBIOS", Const, 0}, + {"AF_NETGRAPH", Const, 0}, + {"AF_NETLINK", Const, 0}, + {"AF_NETROM", Const, 0}, + {"AF_NS", Const, 0}, + {"AF_OROUTE", Const, 1}, + {"AF_OSI", Const, 0}, + {"AF_PACKET", Const, 0}, + {"AF_PHONET", Const, 0}, + {"AF_PPP", Const, 0}, + {"AF_PPPOX", Const, 0}, + {"AF_PUP", Const, 0}, + {"AF_RDS", Const, 0}, + {"AF_RESERVED_36", Const, 0}, + {"AF_ROSE", Const, 0}, + {"AF_ROUTE", Const, 0}, + {"AF_RXRPC", Const, 0}, + {"AF_SCLUSTER", Const, 0}, + {"AF_SECURITY", Const, 0}, + {"AF_SIP", Const, 0}, + {"AF_SLOW", Const, 0}, + {"AF_SNA", Const, 0}, + {"AF_SYSTEM", Const, 0}, + {"AF_TIPC", Const, 0}, + {"AF_UNIX", Const, 0}, + {"AF_UNSPEC", Const, 0}, + {"AF_UTUN", Const, 16}, + {"AF_VENDOR00", Const, 0}, + {"AF_VENDOR01", Const, 0}, + {"AF_VENDOR02", Const, 0}, + {"AF_VENDOR03", Const, 0}, + {"AF_VENDOR04", Const, 0}, + {"AF_VENDOR05", Const, 0}, + {"AF_VENDOR06", Const, 0}, + {"AF_VENDOR07", Const, 0}, + {"AF_VENDOR08", Const, 0}, + {"AF_VENDOR09", Const, 0}, + {"AF_VENDOR10", Const, 0}, + {"AF_VENDOR11", Const, 0}, + {"AF_VENDOR12", Const, 0}, + {"AF_VENDOR13", Const, 0}, + {"AF_VENDOR14", Const, 0}, + {"AF_VENDOR15", Const, 0}, + {"AF_VENDOR16", Const, 0}, + {"AF_VENDOR17", Const, 0}, + {"AF_VENDOR18", Const, 0}, + {"AF_VENDOR19", Const, 0}, + {"AF_VENDOR20", Const, 0}, + {"AF_VENDOR21", Const, 0}, + {"AF_VENDOR22", Const, 0}, + {"AF_VENDOR23", Const, 0}, + {"AF_VENDOR24", Const, 0}, + {"AF_VENDOR25", Const, 0}, + {"AF_VENDOR26", Const, 0}, + {"AF_VENDOR27", Const, 0}, + {"AF_VENDOR28", Const, 0}, + {"AF_VENDOR29", Const, 0}, + {"AF_VENDOR30", Const, 0}, + {"AF_VENDOR31", Const, 0}, + {"AF_VENDOR32", Const, 0}, + {"AF_VENDOR33", Const, 0}, + {"AF_VENDOR34", Const, 0}, + {"AF_VENDOR35", Const, 0}, + {"AF_VENDOR36", Const, 0}, + {"AF_VENDOR37", Const, 0}, + {"AF_VENDOR38", Const, 0}, + {"AF_VENDOR39", Const, 0}, + {"AF_VENDOR40", Const, 0}, + {"AF_VENDOR41", Const, 0}, + {"AF_VENDOR42", Const, 0}, + {"AF_VENDOR43", Const, 0}, + {"AF_VENDOR44", Const, 0}, + {"AF_VENDOR45", Const, 0}, + {"AF_VENDOR46", Const, 0}, + {"AF_VENDOR47", Const, 0}, + {"AF_WANPIPE", Const, 0}, + {"AF_X25", Const, 0}, + {"AI_CANONNAME", Const, 1}, + {"AI_NUMERICHOST", Const, 1}, + {"AI_PASSIVE", Const, 1}, + {"APPLICATION_ERROR", Const, 0}, + {"ARPHRD_ADAPT", Const, 0}, + {"ARPHRD_APPLETLK", Const, 0}, + {"ARPHRD_ARCNET", Const, 0}, + {"ARPHRD_ASH", Const, 0}, + {"ARPHRD_ATM", Const, 0}, + {"ARPHRD_AX25", Const, 0}, + {"ARPHRD_BIF", Const, 0}, + {"ARPHRD_CHAOS", Const, 0}, + {"ARPHRD_CISCO", Const, 0}, + {"ARPHRD_CSLIP", Const, 0}, + {"ARPHRD_CSLIP6", Const, 0}, + {"ARPHRD_DDCMP", Const, 0}, + {"ARPHRD_DLCI", Const, 0}, + {"ARPHRD_ECONET", Const, 0}, + {"ARPHRD_EETHER", Const, 0}, + {"ARPHRD_ETHER", Const, 0}, + {"ARPHRD_EUI64", Const, 0}, + {"ARPHRD_FCAL", Const, 0}, + {"ARPHRD_FCFABRIC", Const, 0}, + {"ARPHRD_FCPL", Const, 0}, + {"ARPHRD_FCPP", Const, 0}, + {"ARPHRD_FDDI", Const, 0}, + {"ARPHRD_FRAD", Const, 0}, + {"ARPHRD_FRELAY", Const, 1}, + {"ARPHRD_HDLC", Const, 0}, + {"ARPHRD_HIPPI", Const, 0}, + {"ARPHRD_HWX25", Const, 0}, + {"ARPHRD_IEEE1394", Const, 0}, + {"ARPHRD_IEEE802", Const, 0}, + {"ARPHRD_IEEE80211", Const, 0}, + {"ARPHRD_IEEE80211_PRISM", Const, 0}, + {"ARPHRD_IEEE80211_RADIOTAP", Const, 0}, + {"ARPHRD_IEEE802154", Const, 0}, + {"ARPHRD_IEEE802154_PHY", Const, 0}, + {"ARPHRD_IEEE802_TR", Const, 0}, + {"ARPHRD_INFINIBAND", Const, 0}, + {"ARPHRD_IPDDP", Const, 0}, + {"ARPHRD_IPGRE", Const, 0}, + {"ARPHRD_IRDA", Const, 0}, + {"ARPHRD_LAPB", Const, 0}, + {"ARPHRD_LOCALTLK", Const, 0}, + {"ARPHRD_LOOPBACK", Const, 0}, + {"ARPHRD_METRICOM", Const, 0}, + {"ARPHRD_NETROM", Const, 0}, + {"ARPHRD_NONE", Const, 0}, + {"ARPHRD_PIMREG", Const, 0}, + {"ARPHRD_PPP", Const, 0}, + {"ARPHRD_PRONET", Const, 0}, + {"ARPHRD_RAWHDLC", Const, 0}, + {"ARPHRD_ROSE", Const, 0}, + {"ARPHRD_RSRVD", Const, 0}, + {"ARPHRD_SIT", Const, 0}, + {"ARPHRD_SKIP", Const, 0}, + {"ARPHRD_SLIP", Const, 0}, + {"ARPHRD_SLIP6", Const, 0}, + {"ARPHRD_STRIP", Const, 1}, + {"ARPHRD_TUNNEL", Const, 0}, + {"ARPHRD_TUNNEL6", Const, 0}, + {"ARPHRD_VOID", Const, 0}, + {"ARPHRD_X25", Const, 0}, + {"AUTHTYPE_CLIENT", Const, 0}, + {"AUTHTYPE_SERVER", Const, 0}, + {"Accept", Func, 0}, + {"Accept4", Func, 1}, + {"AcceptEx", Func, 0}, + {"Access", Func, 0}, + {"Acct", Func, 0}, + {"AddrinfoW", Type, 1}, + {"AddrinfoW.Addr", Field, 1}, + {"AddrinfoW.Addrlen", Field, 1}, + {"AddrinfoW.Canonname", Field, 1}, + {"AddrinfoW.Family", Field, 1}, + {"AddrinfoW.Flags", Field, 1}, + {"AddrinfoW.Next", Field, 1}, + {"AddrinfoW.Protocol", Field, 1}, + {"AddrinfoW.Socktype", Field, 1}, + {"Adjtime", Func, 0}, + {"Adjtimex", Func, 0}, + {"AllThreadsSyscall", Func, 16}, + {"AllThreadsSyscall6", Func, 16}, + {"AttachLsf", Func, 0}, + {"B0", Const, 0}, + {"B1000000", Const, 0}, + {"B110", Const, 0}, + {"B115200", Const, 0}, + {"B1152000", Const, 0}, + {"B1200", Const, 0}, + {"B134", Const, 0}, + {"B14400", Const, 1}, + {"B150", Const, 0}, + {"B1500000", Const, 0}, + {"B1800", Const, 0}, + {"B19200", Const, 0}, + {"B200", Const, 0}, + {"B2000000", Const, 0}, + {"B230400", Const, 0}, + {"B2400", Const, 0}, + {"B2500000", Const, 0}, + {"B28800", Const, 1}, + {"B300", Const, 0}, + {"B3000000", Const, 0}, + {"B3500000", Const, 0}, + {"B38400", Const, 0}, + {"B4000000", Const, 0}, + {"B460800", Const, 0}, + {"B4800", Const, 0}, + {"B50", Const, 0}, + {"B500000", Const, 0}, + {"B57600", Const, 0}, + {"B576000", Const, 0}, + {"B600", Const, 0}, + {"B7200", Const, 1}, + {"B75", Const, 0}, + {"B76800", Const, 1}, + {"B921600", Const, 0}, + {"B9600", Const, 0}, + {"BASE_PROTOCOL", Const, 2}, + {"BIOCFEEDBACK", Const, 0}, + {"BIOCFLUSH", Const, 0}, + {"BIOCGBLEN", Const, 0}, + {"BIOCGDIRECTION", Const, 0}, + {"BIOCGDIRFILT", Const, 1}, + {"BIOCGDLT", Const, 0}, + {"BIOCGDLTLIST", Const, 0}, + {"BIOCGETBUFMODE", Const, 0}, + {"BIOCGETIF", Const, 0}, + {"BIOCGETZMAX", Const, 0}, + {"BIOCGFEEDBACK", Const, 1}, + {"BIOCGFILDROP", Const, 1}, + {"BIOCGHDRCMPLT", Const, 0}, + {"BIOCGRSIG", Const, 0}, + {"BIOCGRTIMEOUT", Const, 0}, + {"BIOCGSEESENT", Const, 0}, + {"BIOCGSTATS", Const, 0}, + {"BIOCGSTATSOLD", Const, 1}, + {"BIOCGTSTAMP", Const, 1}, + {"BIOCIMMEDIATE", Const, 0}, + {"BIOCLOCK", Const, 0}, + {"BIOCPROMISC", Const, 0}, + {"BIOCROTZBUF", Const, 0}, + {"BIOCSBLEN", Const, 0}, + {"BIOCSDIRECTION", Const, 0}, + {"BIOCSDIRFILT", Const, 1}, + {"BIOCSDLT", Const, 0}, + {"BIOCSETBUFMODE", Const, 0}, + {"BIOCSETF", Const, 0}, + {"BIOCSETFNR", Const, 0}, + {"BIOCSETIF", Const, 0}, + {"BIOCSETWF", Const, 0}, + {"BIOCSETZBUF", Const, 0}, + {"BIOCSFEEDBACK", Const, 1}, + {"BIOCSFILDROP", Const, 1}, + {"BIOCSHDRCMPLT", Const, 0}, + {"BIOCSRSIG", Const, 0}, + {"BIOCSRTIMEOUT", Const, 0}, + {"BIOCSSEESENT", Const, 0}, + {"BIOCSTCPF", Const, 1}, + {"BIOCSTSTAMP", Const, 1}, + {"BIOCSUDPF", Const, 1}, + {"BIOCVERSION", Const, 0}, + {"BPF_A", Const, 0}, + {"BPF_ABS", Const, 0}, + {"BPF_ADD", Const, 0}, + {"BPF_ALIGNMENT", Const, 0}, + {"BPF_ALIGNMENT32", Const, 1}, + {"BPF_ALU", Const, 0}, + {"BPF_AND", Const, 0}, + {"BPF_B", Const, 0}, + {"BPF_BUFMODE_BUFFER", Const, 0}, + {"BPF_BUFMODE_ZBUF", Const, 0}, + {"BPF_DFLTBUFSIZE", Const, 1}, + {"BPF_DIRECTION_IN", Const, 1}, + {"BPF_DIRECTION_OUT", Const, 1}, + {"BPF_DIV", Const, 0}, + {"BPF_H", Const, 0}, + {"BPF_IMM", Const, 0}, + {"BPF_IND", Const, 0}, + {"BPF_JA", Const, 0}, + {"BPF_JEQ", Const, 0}, + {"BPF_JGE", Const, 0}, + {"BPF_JGT", Const, 0}, + {"BPF_JMP", Const, 0}, + {"BPF_JSET", Const, 0}, + {"BPF_K", Const, 0}, + {"BPF_LD", Const, 0}, + {"BPF_LDX", Const, 0}, + {"BPF_LEN", Const, 0}, + {"BPF_LSH", Const, 0}, + {"BPF_MAJOR_VERSION", Const, 0}, + {"BPF_MAXBUFSIZE", Const, 0}, + {"BPF_MAXINSNS", Const, 0}, + {"BPF_MEM", Const, 0}, + {"BPF_MEMWORDS", Const, 0}, + {"BPF_MINBUFSIZE", Const, 0}, + {"BPF_MINOR_VERSION", Const, 0}, + {"BPF_MISC", Const, 0}, + {"BPF_MSH", Const, 0}, + {"BPF_MUL", Const, 0}, + {"BPF_NEG", Const, 0}, + {"BPF_OR", Const, 0}, + {"BPF_RELEASE", Const, 0}, + {"BPF_RET", Const, 0}, + {"BPF_RSH", Const, 0}, + {"BPF_ST", Const, 0}, + {"BPF_STX", Const, 0}, + {"BPF_SUB", Const, 0}, + {"BPF_TAX", Const, 0}, + {"BPF_TXA", Const, 0}, + {"BPF_T_BINTIME", Const, 1}, + {"BPF_T_BINTIME_FAST", Const, 1}, + {"BPF_T_BINTIME_MONOTONIC", Const, 1}, + {"BPF_T_BINTIME_MONOTONIC_FAST", Const, 1}, + {"BPF_T_FAST", Const, 1}, + {"BPF_T_FLAG_MASK", Const, 1}, + {"BPF_T_FORMAT_MASK", Const, 1}, + {"BPF_T_MICROTIME", Const, 1}, + {"BPF_T_MICROTIME_FAST", Const, 1}, + {"BPF_T_MICROTIME_MONOTONIC", Const, 1}, + {"BPF_T_MICROTIME_MONOTONIC_FAST", Const, 1}, + {"BPF_T_MONOTONIC", Const, 1}, + {"BPF_T_MONOTONIC_FAST", Const, 1}, + {"BPF_T_NANOTIME", Const, 1}, + {"BPF_T_NANOTIME_FAST", Const, 1}, + {"BPF_T_NANOTIME_MONOTONIC", Const, 1}, + {"BPF_T_NANOTIME_MONOTONIC_FAST", Const, 1}, + {"BPF_T_NONE", Const, 1}, + {"BPF_T_NORMAL", Const, 1}, + {"BPF_W", Const, 0}, + {"BPF_X", Const, 0}, + {"BRKINT", Const, 0}, + {"Bind", Func, 0}, + {"BindToDevice", Func, 0}, + {"BpfBuflen", Func, 0}, + {"BpfDatalink", Func, 0}, + {"BpfHdr", Type, 0}, + {"BpfHdr.Caplen", Field, 0}, + {"BpfHdr.Datalen", Field, 0}, + {"BpfHdr.Hdrlen", Field, 0}, + {"BpfHdr.Pad_cgo_0", Field, 0}, + {"BpfHdr.Tstamp", Field, 0}, + {"BpfHeadercmpl", Func, 0}, + {"BpfInsn", Type, 0}, + {"BpfInsn.Code", Field, 0}, + {"BpfInsn.Jf", Field, 0}, + {"BpfInsn.Jt", Field, 0}, + {"BpfInsn.K", Field, 0}, + {"BpfInterface", Func, 0}, + {"BpfJump", Func, 0}, + {"BpfProgram", Type, 0}, + {"BpfProgram.Insns", Field, 0}, + {"BpfProgram.Len", Field, 0}, + {"BpfProgram.Pad_cgo_0", Field, 0}, + {"BpfStat", Type, 0}, + {"BpfStat.Capt", Field, 2}, + {"BpfStat.Drop", Field, 0}, + {"BpfStat.Padding", Field, 2}, + {"BpfStat.Recv", Field, 0}, + {"BpfStats", Func, 0}, + {"BpfStmt", Func, 0}, + {"BpfTimeout", Func, 0}, + {"BpfTimeval", Type, 2}, + {"BpfTimeval.Sec", Field, 2}, + {"BpfTimeval.Usec", Field, 2}, + {"BpfVersion", Type, 0}, + {"BpfVersion.Major", Field, 0}, + {"BpfVersion.Minor", Field, 0}, + {"BpfZbuf", Type, 0}, + {"BpfZbuf.Bufa", Field, 0}, + {"BpfZbuf.Bufb", Field, 0}, + {"BpfZbuf.Buflen", Field, 0}, + {"BpfZbufHeader", Type, 0}, + {"BpfZbufHeader.Kernel_gen", Field, 0}, + {"BpfZbufHeader.Kernel_len", Field, 0}, + {"BpfZbufHeader.User_gen", Field, 0}, + {"BpfZbufHeader.X_bzh_pad", Field, 0}, + {"ByHandleFileInformation", Type, 0}, + {"ByHandleFileInformation.CreationTime", Field, 0}, + {"ByHandleFileInformation.FileAttributes", Field, 0}, + {"ByHandleFileInformation.FileIndexHigh", Field, 0}, + {"ByHandleFileInformation.FileIndexLow", Field, 0}, + {"ByHandleFileInformation.FileSizeHigh", Field, 0}, + {"ByHandleFileInformation.FileSizeLow", Field, 0}, + {"ByHandleFileInformation.LastAccessTime", Field, 0}, + {"ByHandleFileInformation.LastWriteTime", Field, 0}, + {"ByHandleFileInformation.NumberOfLinks", Field, 0}, + {"ByHandleFileInformation.VolumeSerialNumber", Field, 0}, + {"BytePtrFromString", Func, 1}, + {"ByteSliceFromString", Func, 1}, + {"CCR0_FLUSH", Const, 1}, + {"CERT_CHAIN_POLICY_AUTHENTICODE", Const, 0}, + {"CERT_CHAIN_POLICY_AUTHENTICODE_TS", Const, 0}, + {"CERT_CHAIN_POLICY_BASE", Const, 0}, + {"CERT_CHAIN_POLICY_BASIC_CONSTRAINTS", Const, 0}, + {"CERT_CHAIN_POLICY_EV", Const, 0}, + {"CERT_CHAIN_POLICY_MICROSOFT_ROOT", Const, 0}, + {"CERT_CHAIN_POLICY_NT_AUTH", Const, 0}, + {"CERT_CHAIN_POLICY_SSL", Const, 0}, + {"CERT_E_CN_NO_MATCH", Const, 0}, + {"CERT_E_EXPIRED", Const, 0}, + {"CERT_E_PURPOSE", Const, 0}, + {"CERT_E_ROLE", Const, 0}, + {"CERT_E_UNTRUSTEDROOT", Const, 0}, + {"CERT_STORE_ADD_ALWAYS", Const, 0}, + {"CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG", Const, 0}, + {"CERT_STORE_PROV_MEMORY", Const, 0}, + {"CERT_TRUST_HAS_EXCLUDED_NAME_CONSTRAINT", Const, 0}, + {"CERT_TRUST_HAS_NOT_DEFINED_NAME_CONSTRAINT", Const, 0}, + {"CERT_TRUST_HAS_NOT_PERMITTED_NAME_CONSTRAINT", Const, 0}, + {"CERT_TRUST_HAS_NOT_SUPPORTED_CRITICAL_EXT", Const, 0}, + {"CERT_TRUST_HAS_NOT_SUPPORTED_NAME_CONSTRAINT", Const, 0}, + {"CERT_TRUST_INVALID_BASIC_CONSTRAINTS", Const, 0}, + {"CERT_TRUST_INVALID_EXTENSION", Const, 0}, + {"CERT_TRUST_INVALID_NAME_CONSTRAINTS", Const, 0}, + {"CERT_TRUST_INVALID_POLICY_CONSTRAINTS", Const, 0}, + {"CERT_TRUST_IS_CYCLIC", Const, 0}, + {"CERT_TRUST_IS_EXPLICIT_DISTRUST", Const, 0}, + {"CERT_TRUST_IS_NOT_SIGNATURE_VALID", Const, 0}, + {"CERT_TRUST_IS_NOT_TIME_VALID", Const, 0}, + {"CERT_TRUST_IS_NOT_VALID_FOR_USAGE", Const, 0}, + {"CERT_TRUST_IS_OFFLINE_REVOCATION", Const, 0}, + {"CERT_TRUST_IS_REVOKED", Const, 0}, + {"CERT_TRUST_IS_UNTRUSTED_ROOT", Const, 0}, + {"CERT_TRUST_NO_ERROR", Const, 0}, + {"CERT_TRUST_NO_ISSUANCE_CHAIN_POLICY", Const, 0}, + {"CERT_TRUST_REVOCATION_STATUS_UNKNOWN", Const, 0}, + {"CFLUSH", Const, 1}, + {"CLOCAL", Const, 0}, + {"CLONE_CHILD_CLEARTID", Const, 2}, + {"CLONE_CHILD_SETTID", Const, 2}, + {"CLONE_CLEAR_SIGHAND", Const, 20}, + {"CLONE_CSIGNAL", Const, 3}, + {"CLONE_DETACHED", Const, 2}, + {"CLONE_FILES", Const, 2}, + {"CLONE_FS", Const, 2}, + {"CLONE_INTO_CGROUP", Const, 20}, + {"CLONE_IO", Const, 2}, + {"CLONE_NEWCGROUP", Const, 20}, + {"CLONE_NEWIPC", Const, 2}, + {"CLONE_NEWNET", Const, 2}, + {"CLONE_NEWNS", Const, 2}, + {"CLONE_NEWPID", Const, 2}, + {"CLONE_NEWTIME", Const, 20}, + {"CLONE_NEWUSER", Const, 2}, + {"CLONE_NEWUTS", Const, 2}, + {"CLONE_PARENT", Const, 2}, + {"CLONE_PARENT_SETTID", Const, 2}, + {"CLONE_PID", Const, 3}, + {"CLONE_PIDFD", Const, 20}, + {"CLONE_PTRACE", Const, 2}, + {"CLONE_SETTLS", Const, 2}, + {"CLONE_SIGHAND", Const, 2}, + {"CLONE_SYSVSEM", Const, 2}, + {"CLONE_THREAD", Const, 2}, + {"CLONE_UNTRACED", Const, 2}, + {"CLONE_VFORK", Const, 2}, + {"CLONE_VM", Const, 2}, + {"CPUID_CFLUSH", Const, 1}, + {"CREAD", Const, 0}, + {"CREATE_ALWAYS", Const, 0}, + {"CREATE_NEW", Const, 0}, + {"CREATE_NEW_PROCESS_GROUP", Const, 1}, + {"CREATE_UNICODE_ENVIRONMENT", Const, 0}, + {"CRYPT_DEFAULT_CONTAINER_OPTIONAL", Const, 0}, + {"CRYPT_DELETEKEYSET", Const, 0}, + {"CRYPT_MACHINE_KEYSET", Const, 0}, + {"CRYPT_NEWKEYSET", Const, 0}, + {"CRYPT_SILENT", Const, 0}, + {"CRYPT_VERIFYCONTEXT", Const, 0}, + {"CS5", Const, 0}, + {"CS6", Const, 0}, + {"CS7", Const, 0}, + {"CS8", Const, 0}, + {"CSIZE", Const, 0}, + {"CSTART", Const, 1}, + {"CSTATUS", Const, 1}, + {"CSTOP", Const, 1}, + {"CSTOPB", Const, 0}, + {"CSUSP", Const, 1}, + {"CTL_MAXNAME", Const, 0}, + {"CTL_NET", Const, 0}, + {"CTL_QUERY", Const, 1}, + {"CTRL_BREAK_EVENT", Const, 1}, + {"CTRL_CLOSE_EVENT", Const, 14}, + {"CTRL_C_EVENT", Const, 1}, + {"CTRL_LOGOFF_EVENT", Const, 14}, + {"CTRL_SHUTDOWN_EVENT", Const, 14}, + {"CancelIo", Func, 0}, + {"CancelIoEx", Func, 1}, + {"CertAddCertificateContextToStore", Func, 0}, + {"CertChainContext", Type, 0}, + {"CertChainContext.ChainCount", Field, 0}, + {"CertChainContext.Chains", Field, 0}, + {"CertChainContext.HasRevocationFreshnessTime", Field, 0}, + {"CertChainContext.LowerQualityChainCount", Field, 0}, + {"CertChainContext.LowerQualityChains", Field, 0}, + {"CertChainContext.RevocationFreshnessTime", Field, 0}, + {"CertChainContext.Size", Field, 0}, + {"CertChainContext.TrustStatus", Field, 0}, + {"CertChainElement", Type, 0}, + {"CertChainElement.ApplicationUsage", Field, 0}, + {"CertChainElement.CertContext", Field, 0}, + {"CertChainElement.ExtendedErrorInfo", Field, 0}, + {"CertChainElement.IssuanceUsage", Field, 0}, + {"CertChainElement.RevocationInfo", Field, 0}, + {"CertChainElement.Size", Field, 0}, + {"CertChainElement.TrustStatus", Field, 0}, + {"CertChainPara", Type, 0}, + {"CertChainPara.CacheResync", Field, 0}, + {"CertChainPara.CheckRevocationFreshnessTime", Field, 0}, + {"CertChainPara.RequestedUsage", Field, 0}, + {"CertChainPara.RequstedIssuancePolicy", Field, 0}, + {"CertChainPara.RevocationFreshnessTime", Field, 0}, + {"CertChainPara.Size", Field, 0}, + {"CertChainPara.URLRetrievalTimeout", Field, 0}, + {"CertChainPolicyPara", Type, 0}, + {"CertChainPolicyPara.ExtraPolicyPara", Field, 0}, + {"CertChainPolicyPara.Flags", Field, 0}, + {"CertChainPolicyPara.Size", Field, 0}, + {"CertChainPolicyStatus", Type, 0}, + {"CertChainPolicyStatus.ChainIndex", Field, 0}, + {"CertChainPolicyStatus.ElementIndex", Field, 0}, + {"CertChainPolicyStatus.Error", Field, 0}, + {"CertChainPolicyStatus.ExtraPolicyStatus", Field, 0}, + {"CertChainPolicyStatus.Size", Field, 0}, + {"CertCloseStore", Func, 0}, + {"CertContext", Type, 0}, + {"CertContext.CertInfo", Field, 0}, + {"CertContext.EncodedCert", Field, 0}, + {"CertContext.EncodingType", Field, 0}, + {"CertContext.Length", Field, 0}, + {"CertContext.Store", Field, 0}, + {"CertCreateCertificateContext", Func, 0}, + {"CertEnhKeyUsage", Type, 0}, + {"CertEnhKeyUsage.Length", Field, 0}, + {"CertEnhKeyUsage.UsageIdentifiers", Field, 0}, + {"CertEnumCertificatesInStore", Func, 0}, + {"CertFreeCertificateChain", Func, 0}, + {"CertFreeCertificateContext", Func, 0}, + {"CertGetCertificateChain", Func, 0}, + {"CertInfo", Type, 11}, + {"CertOpenStore", Func, 0}, + {"CertOpenSystemStore", Func, 0}, + {"CertRevocationCrlInfo", Type, 11}, + {"CertRevocationInfo", Type, 0}, + {"CertRevocationInfo.CrlInfo", Field, 0}, + {"CertRevocationInfo.FreshnessTime", Field, 0}, + {"CertRevocationInfo.HasFreshnessTime", Field, 0}, + {"CertRevocationInfo.OidSpecificInfo", Field, 0}, + {"CertRevocationInfo.RevocationOid", Field, 0}, + {"CertRevocationInfo.RevocationResult", Field, 0}, + {"CertRevocationInfo.Size", Field, 0}, + {"CertSimpleChain", Type, 0}, + {"CertSimpleChain.Elements", Field, 0}, + {"CertSimpleChain.HasRevocationFreshnessTime", Field, 0}, + {"CertSimpleChain.NumElements", Field, 0}, + {"CertSimpleChain.RevocationFreshnessTime", Field, 0}, + {"CertSimpleChain.Size", Field, 0}, + {"CertSimpleChain.TrustListInfo", Field, 0}, + {"CertSimpleChain.TrustStatus", Field, 0}, + {"CertTrustListInfo", Type, 11}, + {"CertTrustStatus", Type, 0}, + {"CertTrustStatus.ErrorStatus", Field, 0}, + {"CertTrustStatus.InfoStatus", Field, 0}, + {"CertUsageMatch", Type, 0}, + {"CertUsageMatch.Type", Field, 0}, + {"CertUsageMatch.Usage", Field, 0}, + {"CertVerifyCertificateChainPolicy", Func, 0}, + {"Chdir", Func, 0}, + {"CheckBpfVersion", Func, 0}, + {"Chflags", Func, 0}, + {"Chmod", Func, 0}, + {"Chown", Func, 0}, + {"Chroot", Func, 0}, + {"Clearenv", Func, 0}, + {"Close", Func, 0}, + {"CloseHandle", Func, 0}, + {"CloseOnExec", Func, 0}, + {"Closesocket", Func, 0}, + {"CmsgLen", Func, 0}, + {"CmsgSpace", Func, 0}, + {"Cmsghdr", Type, 0}, + {"Cmsghdr.Len", Field, 0}, + {"Cmsghdr.Level", Field, 0}, + {"Cmsghdr.Type", Field, 0}, + {"Cmsghdr.X__cmsg_data", Field, 0}, + {"CommandLineToArgv", Func, 0}, + {"ComputerName", Func, 0}, + {"Conn", Type, 9}, + {"Connect", Func, 0}, + {"ConnectEx", Func, 1}, + {"ConvertSidToStringSid", Func, 0}, + {"ConvertStringSidToSid", Func, 0}, + {"CopySid", Func, 0}, + {"Creat", Func, 0}, + {"CreateDirectory", Func, 0}, + {"CreateFile", Func, 0}, + {"CreateFileMapping", Func, 0}, + {"CreateHardLink", Func, 4}, + {"CreateIoCompletionPort", Func, 0}, + {"CreatePipe", Func, 0}, + {"CreateProcess", Func, 0}, + {"CreateProcessAsUser", Func, 10}, + {"CreateSymbolicLink", Func, 4}, + {"CreateToolhelp32Snapshot", Func, 4}, + {"Credential", Type, 0}, + {"Credential.Gid", Field, 0}, + {"Credential.Groups", Field, 0}, + {"Credential.NoSetGroups", Field, 9}, + {"Credential.Uid", Field, 0}, + {"CryptAcquireContext", Func, 0}, + {"CryptGenRandom", Func, 0}, + {"CryptReleaseContext", Func, 0}, + {"DIOCBSFLUSH", Const, 1}, + {"DIOCOSFPFLUSH", Const, 1}, + {"DLL", Type, 0}, + {"DLL.Handle", Field, 0}, + {"DLL.Name", Field, 0}, + {"DLLError", Type, 0}, + {"DLLError.Err", Field, 0}, + {"DLLError.Msg", Field, 0}, + {"DLLError.ObjName", Field, 0}, + {"DLT_A429", Const, 0}, + {"DLT_A653_ICM", Const, 0}, + {"DLT_AIRONET_HEADER", Const, 0}, + {"DLT_AOS", Const, 1}, + {"DLT_APPLE_IP_OVER_IEEE1394", Const, 0}, + {"DLT_ARCNET", Const, 0}, + {"DLT_ARCNET_LINUX", Const, 0}, + {"DLT_ATM_CLIP", Const, 0}, + {"DLT_ATM_RFC1483", Const, 0}, + {"DLT_AURORA", Const, 0}, + {"DLT_AX25", Const, 0}, + {"DLT_AX25_KISS", Const, 0}, + {"DLT_BACNET_MS_TP", Const, 0}, + {"DLT_BLUETOOTH_HCI_H4", Const, 0}, + {"DLT_BLUETOOTH_HCI_H4_WITH_PHDR", Const, 0}, + {"DLT_CAN20B", Const, 0}, + {"DLT_CAN_SOCKETCAN", Const, 1}, + {"DLT_CHAOS", Const, 0}, + {"DLT_CHDLC", Const, 0}, + {"DLT_CISCO_IOS", Const, 0}, + {"DLT_C_HDLC", Const, 0}, + {"DLT_C_HDLC_WITH_DIR", Const, 0}, + {"DLT_DBUS", Const, 1}, + {"DLT_DECT", Const, 1}, + {"DLT_DOCSIS", Const, 0}, + {"DLT_DVB_CI", Const, 1}, + {"DLT_ECONET", Const, 0}, + {"DLT_EN10MB", Const, 0}, + {"DLT_EN3MB", Const, 0}, + {"DLT_ENC", Const, 0}, + {"DLT_ERF", Const, 0}, + {"DLT_ERF_ETH", Const, 0}, + {"DLT_ERF_POS", Const, 0}, + {"DLT_FC_2", Const, 1}, + {"DLT_FC_2_WITH_FRAME_DELIMS", Const, 1}, + {"DLT_FDDI", Const, 0}, + {"DLT_FLEXRAY", Const, 0}, + {"DLT_FRELAY", Const, 0}, + {"DLT_FRELAY_WITH_DIR", Const, 0}, + {"DLT_GCOM_SERIAL", Const, 0}, + {"DLT_GCOM_T1E1", Const, 0}, + {"DLT_GPF_F", Const, 0}, + {"DLT_GPF_T", Const, 0}, + {"DLT_GPRS_LLC", Const, 0}, + {"DLT_GSMTAP_ABIS", Const, 1}, + {"DLT_GSMTAP_UM", Const, 1}, + {"DLT_HDLC", Const, 1}, + {"DLT_HHDLC", Const, 0}, + {"DLT_HIPPI", Const, 1}, + {"DLT_IBM_SN", Const, 0}, + {"DLT_IBM_SP", Const, 0}, + {"DLT_IEEE802", Const, 0}, + {"DLT_IEEE802_11", Const, 0}, + {"DLT_IEEE802_11_RADIO", Const, 0}, + {"DLT_IEEE802_11_RADIO_AVS", Const, 0}, + {"DLT_IEEE802_15_4", Const, 0}, + {"DLT_IEEE802_15_4_LINUX", Const, 0}, + {"DLT_IEEE802_15_4_NOFCS", Const, 1}, + {"DLT_IEEE802_15_4_NONASK_PHY", Const, 0}, + {"DLT_IEEE802_16_MAC_CPS", Const, 0}, + {"DLT_IEEE802_16_MAC_CPS_RADIO", Const, 0}, + {"DLT_IPFILTER", Const, 0}, + {"DLT_IPMB", Const, 0}, + {"DLT_IPMB_LINUX", Const, 0}, + {"DLT_IPNET", Const, 1}, + {"DLT_IPOIB", Const, 1}, + {"DLT_IPV4", Const, 1}, + {"DLT_IPV6", Const, 1}, + {"DLT_IP_OVER_FC", Const, 0}, + {"DLT_JUNIPER_ATM1", Const, 0}, + {"DLT_JUNIPER_ATM2", Const, 0}, + {"DLT_JUNIPER_ATM_CEMIC", Const, 1}, + {"DLT_JUNIPER_CHDLC", Const, 0}, + {"DLT_JUNIPER_ES", Const, 0}, + {"DLT_JUNIPER_ETHER", Const, 0}, + {"DLT_JUNIPER_FIBRECHANNEL", Const, 1}, + {"DLT_JUNIPER_FRELAY", Const, 0}, + {"DLT_JUNIPER_GGSN", Const, 0}, + {"DLT_JUNIPER_ISM", Const, 0}, + {"DLT_JUNIPER_MFR", Const, 0}, + {"DLT_JUNIPER_MLFR", Const, 0}, + {"DLT_JUNIPER_MLPPP", Const, 0}, + {"DLT_JUNIPER_MONITOR", Const, 0}, + {"DLT_JUNIPER_PIC_PEER", Const, 0}, + {"DLT_JUNIPER_PPP", Const, 0}, + {"DLT_JUNIPER_PPPOE", Const, 0}, + {"DLT_JUNIPER_PPPOE_ATM", Const, 0}, + {"DLT_JUNIPER_SERVICES", Const, 0}, + {"DLT_JUNIPER_SRX_E2E", Const, 1}, + {"DLT_JUNIPER_ST", Const, 0}, + {"DLT_JUNIPER_VP", Const, 0}, + {"DLT_JUNIPER_VS", Const, 1}, + {"DLT_LAPB_WITH_DIR", Const, 0}, + {"DLT_LAPD", Const, 0}, + {"DLT_LIN", Const, 0}, + {"DLT_LINUX_EVDEV", Const, 1}, + {"DLT_LINUX_IRDA", Const, 0}, + {"DLT_LINUX_LAPD", Const, 0}, + {"DLT_LINUX_PPP_WITHDIRECTION", Const, 0}, + {"DLT_LINUX_SLL", Const, 0}, + {"DLT_LOOP", Const, 0}, + {"DLT_LTALK", Const, 0}, + {"DLT_MATCHING_MAX", Const, 1}, + {"DLT_MATCHING_MIN", Const, 1}, + {"DLT_MFR", Const, 0}, + {"DLT_MOST", Const, 0}, + {"DLT_MPEG_2_TS", Const, 1}, + {"DLT_MPLS", Const, 1}, + {"DLT_MTP2", Const, 0}, + {"DLT_MTP2_WITH_PHDR", Const, 0}, + {"DLT_MTP3", Const, 0}, + {"DLT_MUX27010", Const, 1}, + {"DLT_NETANALYZER", Const, 1}, + {"DLT_NETANALYZER_TRANSPARENT", Const, 1}, + {"DLT_NFC_LLCP", Const, 1}, + {"DLT_NFLOG", Const, 1}, + {"DLT_NG40", Const, 1}, + {"DLT_NULL", Const, 0}, + {"DLT_PCI_EXP", Const, 0}, + {"DLT_PFLOG", Const, 0}, + {"DLT_PFSYNC", Const, 0}, + {"DLT_PPI", Const, 0}, + {"DLT_PPP", Const, 0}, + {"DLT_PPP_BSDOS", Const, 0}, + {"DLT_PPP_ETHER", Const, 0}, + {"DLT_PPP_PPPD", Const, 0}, + {"DLT_PPP_SERIAL", Const, 0}, + {"DLT_PPP_WITH_DIR", Const, 0}, + {"DLT_PPP_WITH_DIRECTION", Const, 0}, + {"DLT_PRISM_HEADER", Const, 0}, + {"DLT_PRONET", Const, 0}, + {"DLT_RAIF1", Const, 0}, + {"DLT_RAW", Const, 0}, + {"DLT_RAWAF_MASK", Const, 1}, + {"DLT_RIO", Const, 0}, + {"DLT_SCCP", Const, 0}, + {"DLT_SITA", Const, 0}, + {"DLT_SLIP", Const, 0}, + {"DLT_SLIP_BSDOS", Const, 0}, + {"DLT_STANAG_5066_D_PDU", Const, 1}, + {"DLT_SUNATM", Const, 0}, + {"DLT_SYMANTEC_FIREWALL", Const, 0}, + {"DLT_TZSP", Const, 0}, + {"DLT_USB", Const, 0}, + {"DLT_USB_LINUX", Const, 0}, + {"DLT_USB_LINUX_MMAPPED", Const, 1}, + {"DLT_USER0", Const, 0}, + {"DLT_USER1", Const, 0}, + {"DLT_USER10", Const, 0}, + {"DLT_USER11", Const, 0}, + {"DLT_USER12", Const, 0}, + {"DLT_USER13", Const, 0}, + {"DLT_USER14", Const, 0}, + {"DLT_USER15", Const, 0}, + {"DLT_USER2", Const, 0}, + {"DLT_USER3", Const, 0}, + {"DLT_USER4", Const, 0}, + {"DLT_USER5", Const, 0}, + {"DLT_USER6", Const, 0}, + {"DLT_USER7", Const, 0}, + {"DLT_USER8", Const, 0}, + {"DLT_USER9", Const, 0}, + {"DLT_WIHART", Const, 1}, + {"DLT_X2E_SERIAL", Const, 0}, + {"DLT_X2E_XORAYA", Const, 0}, + {"DNSMXData", Type, 0}, + {"DNSMXData.NameExchange", Field, 0}, + {"DNSMXData.Pad", Field, 0}, + {"DNSMXData.Preference", Field, 0}, + {"DNSPTRData", Type, 0}, + {"DNSPTRData.Host", Field, 0}, + {"DNSRecord", Type, 0}, + {"DNSRecord.Data", Field, 0}, + {"DNSRecord.Dw", Field, 0}, + {"DNSRecord.Length", Field, 0}, + {"DNSRecord.Name", Field, 0}, + {"DNSRecord.Next", Field, 0}, + {"DNSRecord.Reserved", Field, 0}, + {"DNSRecord.Ttl", Field, 0}, + {"DNSRecord.Type", Field, 0}, + {"DNSSRVData", Type, 0}, + {"DNSSRVData.Pad", Field, 0}, + {"DNSSRVData.Port", Field, 0}, + {"DNSSRVData.Priority", Field, 0}, + {"DNSSRVData.Target", Field, 0}, + {"DNSSRVData.Weight", Field, 0}, + {"DNSTXTData", Type, 0}, + {"DNSTXTData.StringArray", Field, 0}, + {"DNSTXTData.StringCount", Field, 0}, + {"DNS_INFO_NO_RECORDS", Const, 4}, + {"DNS_TYPE_A", Const, 0}, + {"DNS_TYPE_A6", Const, 0}, + {"DNS_TYPE_AAAA", Const, 0}, + {"DNS_TYPE_ADDRS", Const, 0}, + {"DNS_TYPE_AFSDB", Const, 0}, + {"DNS_TYPE_ALL", Const, 0}, + {"DNS_TYPE_ANY", Const, 0}, + {"DNS_TYPE_ATMA", Const, 0}, + {"DNS_TYPE_AXFR", Const, 0}, + {"DNS_TYPE_CERT", Const, 0}, + {"DNS_TYPE_CNAME", Const, 0}, + {"DNS_TYPE_DHCID", Const, 0}, + {"DNS_TYPE_DNAME", Const, 0}, + {"DNS_TYPE_DNSKEY", Const, 0}, + {"DNS_TYPE_DS", Const, 0}, + {"DNS_TYPE_EID", Const, 0}, + {"DNS_TYPE_GID", Const, 0}, + {"DNS_TYPE_GPOS", Const, 0}, + {"DNS_TYPE_HINFO", Const, 0}, + {"DNS_TYPE_ISDN", Const, 0}, + {"DNS_TYPE_IXFR", Const, 0}, + {"DNS_TYPE_KEY", Const, 0}, + {"DNS_TYPE_KX", Const, 0}, + {"DNS_TYPE_LOC", Const, 0}, + {"DNS_TYPE_MAILA", Const, 0}, + {"DNS_TYPE_MAILB", Const, 0}, + {"DNS_TYPE_MB", Const, 0}, + {"DNS_TYPE_MD", Const, 0}, + {"DNS_TYPE_MF", Const, 0}, + {"DNS_TYPE_MG", Const, 0}, + {"DNS_TYPE_MINFO", Const, 0}, + {"DNS_TYPE_MR", Const, 0}, + {"DNS_TYPE_MX", Const, 0}, + {"DNS_TYPE_NAPTR", Const, 0}, + {"DNS_TYPE_NBSTAT", Const, 0}, + {"DNS_TYPE_NIMLOC", Const, 0}, + {"DNS_TYPE_NS", Const, 0}, + {"DNS_TYPE_NSAP", Const, 0}, + {"DNS_TYPE_NSAPPTR", Const, 0}, + {"DNS_TYPE_NSEC", Const, 0}, + {"DNS_TYPE_NULL", Const, 0}, + {"DNS_TYPE_NXT", Const, 0}, + {"DNS_TYPE_OPT", Const, 0}, + {"DNS_TYPE_PTR", Const, 0}, + {"DNS_TYPE_PX", Const, 0}, + {"DNS_TYPE_RP", Const, 0}, + {"DNS_TYPE_RRSIG", Const, 0}, + {"DNS_TYPE_RT", Const, 0}, + {"DNS_TYPE_SIG", Const, 0}, + {"DNS_TYPE_SINK", Const, 0}, + {"DNS_TYPE_SOA", Const, 0}, + {"DNS_TYPE_SRV", Const, 0}, + {"DNS_TYPE_TEXT", Const, 0}, + {"DNS_TYPE_TKEY", Const, 0}, + {"DNS_TYPE_TSIG", Const, 0}, + {"DNS_TYPE_UID", Const, 0}, + {"DNS_TYPE_UINFO", Const, 0}, + {"DNS_TYPE_UNSPEC", Const, 0}, + {"DNS_TYPE_WINS", Const, 0}, + {"DNS_TYPE_WINSR", Const, 0}, + {"DNS_TYPE_WKS", Const, 0}, + {"DNS_TYPE_X25", Const, 0}, + {"DT_BLK", Const, 0}, + {"DT_CHR", Const, 0}, + {"DT_DIR", Const, 0}, + {"DT_FIFO", Const, 0}, + {"DT_LNK", Const, 0}, + {"DT_REG", Const, 0}, + {"DT_SOCK", Const, 0}, + {"DT_UNKNOWN", Const, 0}, + {"DT_WHT", Const, 0}, + {"DUPLICATE_CLOSE_SOURCE", Const, 0}, + {"DUPLICATE_SAME_ACCESS", Const, 0}, + {"DeleteFile", Func, 0}, + {"DetachLsf", Func, 0}, + {"DeviceIoControl", Func, 4}, + {"Dirent", Type, 0}, + {"Dirent.Fileno", Field, 0}, + {"Dirent.Ino", Field, 0}, + {"Dirent.Name", Field, 0}, + {"Dirent.Namlen", Field, 0}, + {"Dirent.Off", Field, 0}, + {"Dirent.Pad0", Field, 12}, + {"Dirent.Pad1", Field, 12}, + {"Dirent.Pad_cgo_0", Field, 0}, + {"Dirent.Reclen", Field, 0}, + {"Dirent.Seekoff", Field, 0}, + {"Dirent.Type", Field, 0}, + {"Dirent.X__d_padding", Field, 3}, + {"DnsNameCompare", Func, 4}, + {"DnsQuery", Func, 0}, + {"DnsRecordListFree", Func, 0}, + {"DnsSectionAdditional", Const, 4}, + {"DnsSectionAnswer", Const, 4}, + {"DnsSectionAuthority", Const, 4}, + {"DnsSectionQuestion", Const, 4}, + {"Dup", Func, 0}, + {"Dup2", Func, 0}, + {"Dup3", Func, 2}, + {"DuplicateHandle", Func, 0}, + {"E2BIG", Const, 0}, + {"EACCES", Const, 0}, + {"EADDRINUSE", Const, 0}, + {"EADDRNOTAVAIL", Const, 0}, + {"EADV", Const, 0}, + {"EAFNOSUPPORT", Const, 0}, + {"EAGAIN", Const, 0}, + {"EALREADY", Const, 0}, + {"EAUTH", Const, 0}, + {"EBADARCH", Const, 0}, + {"EBADE", Const, 0}, + {"EBADEXEC", Const, 0}, + {"EBADF", Const, 0}, + {"EBADFD", Const, 0}, + {"EBADMACHO", Const, 0}, + {"EBADMSG", Const, 0}, + {"EBADR", Const, 0}, + {"EBADRPC", Const, 0}, + {"EBADRQC", Const, 0}, + {"EBADSLT", Const, 0}, + {"EBFONT", Const, 0}, + {"EBUSY", Const, 0}, + {"ECANCELED", Const, 0}, + {"ECAPMODE", Const, 1}, + {"ECHILD", Const, 0}, + {"ECHO", Const, 0}, + {"ECHOCTL", Const, 0}, + {"ECHOE", Const, 0}, + {"ECHOK", Const, 0}, + {"ECHOKE", Const, 0}, + {"ECHONL", Const, 0}, + {"ECHOPRT", Const, 0}, + {"ECHRNG", Const, 0}, + {"ECOMM", Const, 0}, + {"ECONNABORTED", Const, 0}, + {"ECONNREFUSED", Const, 0}, + {"ECONNRESET", Const, 0}, + {"EDEADLK", Const, 0}, + {"EDEADLOCK", Const, 0}, + {"EDESTADDRREQ", Const, 0}, + {"EDEVERR", Const, 0}, + {"EDOM", Const, 0}, + {"EDOOFUS", Const, 0}, + {"EDOTDOT", Const, 0}, + {"EDQUOT", Const, 0}, + {"EEXIST", Const, 0}, + {"EFAULT", Const, 0}, + {"EFBIG", Const, 0}, + {"EFER_LMA", Const, 1}, + {"EFER_LME", Const, 1}, + {"EFER_NXE", Const, 1}, + {"EFER_SCE", Const, 1}, + {"EFTYPE", Const, 0}, + {"EHOSTDOWN", Const, 0}, + {"EHOSTUNREACH", Const, 0}, + {"EHWPOISON", Const, 0}, + {"EIDRM", Const, 0}, + {"EILSEQ", Const, 0}, + {"EINPROGRESS", Const, 0}, + {"EINTR", Const, 0}, + {"EINVAL", Const, 0}, + {"EIO", Const, 0}, + {"EIPSEC", Const, 1}, + {"EISCONN", Const, 0}, + {"EISDIR", Const, 0}, + {"EISNAM", Const, 0}, + {"EKEYEXPIRED", Const, 0}, + {"EKEYREJECTED", Const, 0}, + {"EKEYREVOKED", Const, 0}, + {"EL2HLT", Const, 0}, + {"EL2NSYNC", Const, 0}, + {"EL3HLT", Const, 0}, + {"EL3RST", Const, 0}, + {"ELAST", Const, 0}, + {"ELF_NGREG", Const, 0}, + {"ELF_PRARGSZ", Const, 0}, + {"ELIBACC", Const, 0}, + {"ELIBBAD", Const, 0}, + {"ELIBEXEC", Const, 0}, + {"ELIBMAX", Const, 0}, + {"ELIBSCN", Const, 0}, + {"ELNRNG", Const, 0}, + {"ELOOP", Const, 0}, + {"EMEDIUMTYPE", Const, 0}, + {"EMFILE", Const, 0}, + {"EMLINK", Const, 0}, + {"EMSGSIZE", Const, 0}, + {"EMT_TAGOVF", Const, 1}, + {"EMULTIHOP", Const, 0}, + {"EMUL_ENABLED", Const, 1}, + {"EMUL_LINUX", Const, 1}, + {"EMUL_LINUX32", Const, 1}, + {"EMUL_MAXID", Const, 1}, + {"EMUL_NATIVE", Const, 1}, + {"ENAMETOOLONG", Const, 0}, + {"ENAVAIL", Const, 0}, + {"ENDRUNDISC", Const, 1}, + {"ENEEDAUTH", Const, 0}, + {"ENETDOWN", Const, 0}, + {"ENETRESET", Const, 0}, + {"ENETUNREACH", Const, 0}, + {"ENFILE", Const, 0}, + {"ENOANO", Const, 0}, + {"ENOATTR", Const, 0}, + {"ENOBUFS", Const, 0}, + {"ENOCSI", Const, 0}, + {"ENODATA", Const, 0}, + {"ENODEV", Const, 0}, + {"ENOENT", Const, 0}, + {"ENOEXEC", Const, 0}, + {"ENOKEY", Const, 0}, + {"ENOLCK", Const, 0}, + {"ENOLINK", Const, 0}, + {"ENOMEDIUM", Const, 0}, + {"ENOMEM", Const, 0}, + {"ENOMSG", Const, 0}, + {"ENONET", Const, 0}, + {"ENOPKG", Const, 0}, + {"ENOPOLICY", Const, 0}, + {"ENOPROTOOPT", Const, 0}, + {"ENOSPC", Const, 0}, + {"ENOSR", Const, 0}, + {"ENOSTR", Const, 0}, + {"ENOSYS", Const, 0}, + {"ENOTBLK", Const, 0}, + {"ENOTCAPABLE", Const, 0}, + {"ENOTCONN", Const, 0}, + {"ENOTDIR", Const, 0}, + {"ENOTEMPTY", Const, 0}, + {"ENOTNAM", Const, 0}, + {"ENOTRECOVERABLE", Const, 0}, + {"ENOTSOCK", Const, 0}, + {"ENOTSUP", Const, 0}, + {"ENOTTY", Const, 0}, + {"ENOTUNIQ", Const, 0}, + {"ENXIO", Const, 0}, + {"EN_SW_CTL_INF", Const, 1}, + {"EN_SW_CTL_PREC", Const, 1}, + {"EN_SW_CTL_ROUND", Const, 1}, + {"EN_SW_DATACHAIN", Const, 1}, + {"EN_SW_DENORM", Const, 1}, + {"EN_SW_INVOP", Const, 1}, + {"EN_SW_OVERFLOW", Const, 1}, + {"EN_SW_PRECLOSS", Const, 1}, + {"EN_SW_UNDERFLOW", Const, 1}, + {"EN_SW_ZERODIV", Const, 1}, + {"EOPNOTSUPP", Const, 0}, + {"EOVERFLOW", Const, 0}, + {"EOWNERDEAD", Const, 0}, + {"EPERM", Const, 0}, + {"EPFNOSUPPORT", Const, 0}, + {"EPIPE", Const, 0}, + {"EPOLLERR", Const, 0}, + {"EPOLLET", Const, 0}, + {"EPOLLHUP", Const, 0}, + {"EPOLLIN", Const, 0}, + {"EPOLLMSG", Const, 0}, + {"EPOLLONESHOT", Const, 0}, + {"EPOLLOUT", Const, 0}, + {"EPOLLPRI", Const, 0}, + {"EPOLLRDBAND", Const, 0}, + {"EPOLLRDHUP", Const, 0}, + {"EPOLLRDNORM", Const, 0}, + {"EPOLLWRBAND", Const, 0}, + {"EPOLLWRNORM", Const, 0}, + {"EPOLL_CLOEXEC", Const, 0}, + {"EPOLL_CTL_ADD", Const, 0}, + {"EPOLL_CTL_DEL", Const, 0}, + {"EPOLL_CTL_MOD", Const, 0}, + {"EPOLL_NONBLOCK", Const, 0}, + {"EPROCLIM", Const, 0}, + {"EPROCUNAVAIL", Const, 0}, + {"EPROGMISMATCH", Const, 0}, + {"EPROGUNAVAIL", Const, 0}, + {"EPROTO", Const, 0}, + {"EPROTONOSUPPORT", Const, 0}, + {"EPROTOTYPE", Const, 0}, + {"EPWROFF", Const, 0}, + {"EQFULL", Const, 16}, + {"ERANGE", Const, 0}, + {"EREMCHG", Const, 0}, + {"EREMOTE", Const, 0}, + {"EREMOTEIO", Const, 0}, + {"ERESTART", Const, 0}, + {"ERFKILL", Const, 0}, + {"EROFS", Const, 0}, + {"ERPCMISMATCH", Const, 0}, + {"ERROR_ACCESS_DENIED", Const, 0}, + {"ERROR_ALREADY_EXISTS", Const, 0}, + {"ERROR_BROKEN_PIPE", Const, 0}, + {"ERROR_BUFFER_OVERFLOW", Const, 0}, + {"ERROR_DIR_NOT_EMPTY", Const, 8}, + {"ERROR_ENVVAR_NOT_FOUND", Const, 0}, + {"ERROR_FILE_EXISTS", Const, 0}, + {"ERROR_FILE_NOT_FOUND", Const, 0}, + {"ERROR_HANDLE_EOF", Const, 2}, + {"ERROR_INSUFFICIENT_BUFFER", Const, 0}, + {"ERROR_IO_PENDING", Const, 0}, + {"ERROR_MOD_NOT_FOUND", Const, 0}, + {"ERROR_MORE_DATA", Const, 3}, + {"ERROR_NETNAME_DELETED", Const, 3}, + {"ERROR_NOT_FOUND", Const, 1}, + {"ERROR_NO_MORE_FILES", Const, 0}, + {"ERROR_OPERATION_ABORTED", Const, 0}, + {"ERROR_PATH_NOT_FOUND", Const, 0}, + {"ERROR_PRIVILEGE_NOT_HELD", Const, 4}, + {"ERROR_PROC_NOT_FOUND", Const, 0}, + {"ESHLIBVERS", Const, 0}, + {"ESHUTDOWN", Const, 0}, + {"ESOCKTNOSUPPORT", Const, 0}, + {"ESPIPE", Const, 0}, + {"ESRCH", Const, 0}, + {"ESRMNT", Const, 0}, + {"ESTALE", Const, 0}, + {"ESTRPIPE", Const, 0}, + {"ETHERCAP_JUMBO_MTU", Const, 1}, + {"ETHERCAP_VLAN_HWTAGGING", Const, 1}, + {"ETHERCAP_VLAN_MTU", Const, 1}, + {"ETHERMIN", Const, 1}, + {"ETHERMTU", Const, 1}, + {"ETHERMTU_JUMBO", Const, 1}, + {"ETHERTYPE_8023", Const, 1}, + {"ETHERTYPE_AARP", Const, 1}, + {"ETHERTYPE_ACCTON", Const, 1}, + {"ETHERTYPE_AEONIC", Const, 1}, + {"ETHERTYPE_ALPHA", Const, 1}, + {"ETHERTYPE_AMBER", Const, 1}, + {"ETHERTYPE_AMOEBA", Const, 1}, + {"ETHERTYPE_AOE", Const, 1}, + {"ETHERTYPE_APOLLO", Const, 1}, + {"ETHERTYPE_APOLLODOMAIN", Const, 1}, + {"ETHERTYPE_APPLETALK", Const, 1}, + {"ETHERTYPE_APPLITEK", Const, 1}, + {"ETHERTYPE_ARGONAUT", Const, 1}, + {"ETHERTYPE_ARP", Const, 1}, + {"ETHERTYPE_AT", Const, 1}, + {"ETHERTYPE_ATALK", Const, 1}, + {"ETHERTYPE_ATOMIC", Const, 1}, + {"ETHERTYPE_ATT", Const, 1}, + {"ETHERTYPE_ATTSTANFORD", Const, 1}, + {"ETHERTYPE_AUTOPHON", Const, 1}, + {"ETHERTYPE_AXIS", Const, 1}, + {"ETHERTYPE_BCLOOP", Const, 1}, + {"ETHERTYPE_BOFL", Const, 1}, + {"ETHERTYPE_CABLETRON", Const, 1}, + {"ETHERTYPE_CHAOS", Const, 1}, + {"ETHERTYPE_COMDESIGN", Const, 1}, + {"ETHERTYPE_COMPUGRAPHIC", Const, 1}, + {"ETHERTYPE_COUNTERPOINT", Const, 1}, + {"ETHERTYPE_CRONUS", Const, 1}, + {"ETHERTYPE_CRONUSVLN", Const, 1}, + {"ETHERTYPE_DCA", Const, 1}, + {"ETHERTYPE_DDE", Const, 1}, + {"ETHERTYPE_DEBNI", Const, 1}, + {"ETHERTYPE_DECAM", Const, 1}, + {"ETHERTYPE_DECCUST", Const, 1}, + {"ETHERTYPE_DECDIAG", Const, 1}, + {"ETHERTYPE_DECDNS", Const, 1}, + {"ETHERTYPE_DECDTS", Const, 1}, + {"ETHERTYPE_DECEXPER", Const, 1}, + {"ETHERTYPE_DECLAST", Const, 1}, + {"ETHERTYPE_DECLTM", Const, 1}, + {"ETHERTYPE_DECMUMPS", Const, 1}, + {"ETHERTYPE_DECNETBIOS", Const, 1}, + {"ETHERTYPE_DELTACON", Const, 1}, + {"ETHERTYPE_DIDDLE", Const, 1}, + {"ETHERTYPE_DLOG1", Const, 1}, + {"ETHERTYPE_DLOG2", Const, 1}, + {"ETHERTYPE_DN", Const, 1}, + {"ETHERTYPE_DOGFIGHT", Const, 1}, + {"ETHERTYPE_DSMD", Const, 1}, + {"ETHERTYPE_ECMA", Const, 1}, + {"ETHERTYPE_ENCRYPT", Const, 1}, + {"ETHERTYPE_ES", Const, 1}, + {"ETHERTYPE_EXCELAN", Const, 1}, + {"ETHERTYPE_EXPERDATA", Const, 1}, + {"ETHERTYPE_FLIP", Const, 1}, + {"ETHERTYPE_FLOWCONTROL", Const, 1}, + {"ETHERTYPE_FRARP", Const, 1}, + {"ETHERTYPE_GENDYN", Const, 1}, + {"ETHERTYPE_HAYES", Const, 1}, + {"ETHERTYPE_HIPPI_FP", Const, 1}, + {"ETHERTYPE_HITACHI", Const, 1}, + {"ETHERTYPE_HP", Const, 1}, + {"ETHERTYPE_IEEEPUP", Const, 1}, + {"ETHERTYPE_IEEEPUPAT", Const, 1}, + {"ETHERTYPE_IMLBL", Const, 1}, + {"ETHERTYPE_IMLBLDIAG", Const, 1}, + {"ETHERTYPE_IP", Const, 1}, + {"ETHERTYPE_IPAS", Const, 1}, + {"ETHERTYPE_IPV6", Const, 1}, + {"ETHERTYPE_IPX", Const, 1}, + {"ETHERTYPE_IPXNEW", Const, 1}, + {"ETHERTYPE_KALPANA", Const, 1}, + {"ETHERTYPE_LANBRIDGE", Const, 1}, + {"ETHERTYPE_LANPROBE", Const, 1}, + {"ETHERTYPE_LAT", Const, 1}, + {"ETHERTYPE_LBACK", Const, 1}, + {"ETHERTYPE_LITTLE", Const, 1}, + {"ETHERTYPE_LLDP", Const, 1}, + {"ETHERTYPE_LOGICRAFT", Const, 1}, + {"ETHERTYPE_LOOPBACK", Const, 1}, + {"ETHERTYPE_MATRA", Const, 1}, + {"ETHERTYPE_MAX", Const, 1}, + {"ETHERTYPE_MERIT", Const, 1}, + {"ETHERTYPE_MICP", Const, 1}, + {"ETHERTYPE_MOPDL", Const, 1}, + {"ETHERTYPE_MOPRC", Const, 1}, + {"ETHERTYPE_MOTOROLA", Const, 1}, + {"ETHERTYPE_MPLS", Const, 1}, + {"ETHERTYPE_MPLS_MCAST", Const, 1}, + {"ETHERTYPE_MUMPS", Const, 1}, + {"ETHERTYPE_NBPCC", Const, 1}, + {"ETHERTYPE_NBPCLAIM", Const, 1}, + {"ETHERTYPE_NBPCLREQ", Const, 1}, + {"ETHERTYPE_NBPCLRSP", Const, 1}, + {"ETHERTYPE_NBPCREQ", Const, 1}, + {"ETHERTYPE_NBPCRSP", Const, 1}, + {"ETHERTYPE_NBPDG", Const, 1}, + {"ETHERTYPE_NBPDGB", Const, 1}, + {"ETHERTYPE_NBPDLTE", Const, 1}, + {"ETHERTYPE_NBPRAR", Const, 1}, + {"ETHERTYPE_NBPRAS", Const, 1}, + {"ETHERTYPE_NBPRST", Const, 1}, + {"ETHERTYPE_NBPSCD", Const, 1}, + {"ETHERTYPE_NBPVCD", Const, 1}, + {"ETHERTYPE_NBS", Const, 1}, + {"ETHERTYPE_NCD", Const, 1}, + {"ETHERTYPE_NESTAR", Const, 1}, + {"ETHERTYPE_NETBEUI", Const, 1}, + {"ETHERTYPE_NOVELL", Const, 1}, + {"ETHERTYPE_NS", Const, 1}, + {"ETHERTYPE_NSAT", Const, 1}, + {"ETHERTYPE_NSCOMPAT", Const, 1}, + {"ETHERTYPE_NTRAILER", Const, 1}, + {"ETHERTYPE_OS9", Const, 1}, + {"ETHERTYPE_OS9NET", Const, 1}, + {"ETHERTYPE_PACER", Const, 1}, + {"ETHERTYPE_PAE", Const, 1}, + {"ETHERTYPE_PCS", Const, 1}, + {"ETHERTYPE_PLANNING", Const, 1}, + {"ETHERTYPE_PPP", Const, 1}, + {"ETHERTYPE_PPPOE", Const, 1}, + {"ETHERTYPE_PPPOEDISC", Const, 1}, + {"ETHERTYPE_PRIMENTS", Const, 1}, + {"ETHERTYPE_PUP", Const, 1}, + {"ETHERTYPE_PUPAT", Const, 1}, + {"ETHERTYPE_QINQ", Const, 1}, + {"ETHERTYPE_RACAL", Const, 1}, + {"ETHERTYPE_RATIONAL", Const, 1}, + {"ETHERTYPE_RAWFR", Const, 1}, + {"ETHERTYPE_RCL", Const, 1}, + {"ETHERTYPE_RDP", Const, 1}, + {"ETHERTYPE_RETIX", Const, 1}, + {"ETHERTYPE_REVARP", Const, 1}, + {"ETHERTYPE_SCA", Const, 1}, + {"ETHERTYPE_SECTRA", Const, 1}, + {"ETHERTYPE_SECUREDATA", Const, 1}, + {"ETHERTYPE_SGITW", Const, 1}, + {"ETHERTYPE_SG_BOUNCE", Const, 1}, + {"ETHERTYPE_SG_DIAG", Const, 1}, + {"ETHERTYPE_SG_NETGAMES", Const, 1}, + {"ETHERTYPE_SG_RESV", Const, 1}, + {"ETHERTYPE_SIMNET", Const, 1}, + {"ETHERTYPE_SLOW", Const, 1}, + {"ETHERTYPE_SLOWPROTOCOLS", Const, 1}, + {"ETHERTYPE_SNA", Const, 1}, + {"ETHERTYPE_SNMP", Const, 1}, + {"ETHERTYPE_SONIX", Const, 1}, + {"ETHERTYPE_SPIDER", Const, 1}, + {"ETHERTYPE_SPRITE", Const, 1}, + {"ETHERTYPE_STP", Const, 1}, + {"ETHERTYPE_TALARIS", Const, 1}, + {"ETHERTYPE_TALARISMC", Const, 1}, + {"ETHERTYPE_TCPCOMP", Const, 1}, + {"ETHERTYPE_TCPSM", Const, 1}, + {"ETHERTYPE_TEC", Const, 1}, + {"ETHERTYPE_TIGAN", Const, 1}, + {"ETHERTYPE_TRAIL", Const, 1}, + {"ETHERTYPE_TRANSETHER", Const, 1}, + {"ETHERTYPE_TYMSHARE", Const, 1}, + {"ETHERTYPE_UBBST", Const, 1}, + {"ETHERTYPE_UBDEBUG", Const, 1}, + {"ETHERTYPE_UBDIAGLOOP", Const, 1}, + {"ETHERTYPE_UBDL", Const, 1}, + {"ETHERTYPE_UBNIU", Const, 1}, + {"ETHERTYPE_UBNMC", Const, 1}, + {"ETHERTYPE_VALID", Const, 1}, + {"ETHERTYPE_VARIAN", Const, 1}, + {"ETHERTYPE_VAXELN", Const, 1}, + {"ETHERTYPE_VEECO", Const, 1}, + {"ETHERTYPE_VEXP", Const, 1}, + {"ETHERTYPE_VGLAB", Const, 1}, + {"ETHERTYPE_VINES", Const, 1}, + {"ETHERTYPE_VINESECHO", Const, 1}, + {"ETHERTYPE_VINESLOOP", Const, 1}, + {"ETHERTYPE_VITAL", Const, 1}, + {"ETHERTYPE_VLAN", Const, 1}, + {"ETHERTYPE_VLTLMAN", Const, 1}, + {"ETHERTYPE_VPROD", Const, 1}, + {"ETHERTYPE_VURESERVED", Const, 1}, + {"ETHERTYPE_WATERLOO", Const, 1}, + {"ETHERTYPE_WELLFLEET", Const, 1}, + {"ETHERTYPE_X25", Const, 1}, + {"ETHERTYPE_X75", Const, 1}, + {"ETHERTYPE_XNSSM", Const, 1}, + {"ETHERTYPE_XTP", Const, 1}, + {"ETHER_ADDR_LEN", Const, 1}, + {"ETHER_ALIGN", Const, 1}, + {"ETHER_CRC_LEN", Const, 1}, + {"ETHER_CRC_POLY_BE", Const, 1}, + {"ETHER_CRC_POLY_LE", Const, 1}, + {"ETHER_HDR_LEN", Const, 1}, + {"ETHER_MAX_DIX_LEN", Const, 1}, + {"ETHER_MAX_LEN", Const, 1}, + {"ETHER_MAX_LEN_JUMBO", Const, 1}, + {"ETHER_MIN_LEN", Const, 1}, + {"ETHER_PPPOE_ENCAP_LEN", Const, 1}, + {"ETHER_TYPE_LEN", Const, 1}, + {"ETHER_VLAN_ENCAP_LEN", Const, 1}, + {"ETH_P_1588", Const, 0}, + {"ETH_P_8021Q", Const, 0}, + {"ETH_P_802_2", Const, 0}, + {"ETH_P_802_3", Const, 0}, + {"ETH_P_AARP", Const, 0}, + {"ETH_P_ALL", Const, 0}, + {"ETH_P_AOE", Const, 0}, + {"ETH_P_ARCNET", Const, 0}, + {"ETH_P_ARP", Const, 0}, + {"ETH_P_ATALK", Const, 0}, + {"ETH_P_ATMFATE", Const, 0}, + {"ETH_P_ATMMPOA", Const, 0}, + {"ETH_P_AX25", Const, 0}, + {"ETH_P_BPQ", Const, 0}, + {"ETH_P_CAIF", Const, 0}, + {"ETH_P_CAN", Const, 0}, + {"ETH_P_CONTROL", Const, 0}, + {"ETH_P_CUST", Const, 0}, + {"ETH_P_DDCMP", Const, 0}, + {"ETH_P_DEC", Const, 0}, + {"ETH_P_DIAG", Const, 0}, + {"ETH_P_DNA_DL", Const, 0}, + {"ETH_P_DNA_RC", Const, 0}, + {"ETH_P_DNA_RT", Const, 0}, + {"ETH_P_DSA", Const, 0}, + {"ETH_P_ECONET", Const, 0}, + {"ETH_P_EDSA", Const, 0}, + {"ETH_P_FCOE", Const, 0}, + {"ETH_P_FIP", Const, 0}, + {"ETH_P_HDLC", Const, 0}, + {"ETH_P_IEEE802154", Const, 0}, + {"ETH_P_IEEEPUP", Const, 0}, + {"ETH_P_IEEEPUPAT", Const, 0}, + {"ETH_P_IP", Const, 0}, + {"ETH_P_IPV6", Const, 0}, + {"ETH_P_IPX", Const, 0}, + {"ETH_P_IRDA", Const, 0}, + {"ETH_P_LAT", Const, 0}, + {"ETH_P_LINK_CTL", Const, 0}, + {"ETH_P_LOCALTALK", Const, 0}, + {"ETH_P_LOOP", Const, 0}, + {"ETH_P_MOBITEX", Const, 0}, + {"ETH_P_MPLS_MC", Const, 0}, + {"ETH_P_MPLS_UC", Const, 0}, + {"ETH_P_PAE", Const, 0}, + {"ETH_P_PAUSE", Const, 0}, + {"ETH_P_PHONET", Const, 0}, + {"ETH_P_PPPTALK", Const, 0}, + {"ETH_P_PPP_DISC", Const, 0}, + {"ETH_P_PPP_MP", Const, 0}, + {"ETH_P_PPP_SES", Const, 0}, + {"ETH_P_PUP", Const, 0}, + {"ETH_P_PUPAT", Const, 0}, + {"ETH_P_RARP", Const, 0}, + {"ETH_P_SCA", Const, 0}, + {"ETH_P_SLOW", Const, 0}, + {"ETH_P_SNAP", Const, 0}, + {"ETH_P_TEB", Const, 0}, + {"ETH_P_TIPC", Const, 0}, + {"ETH_P_TRAILER", Const, 0}, + {"ETH_P_TR_802_2", Const, 0}, + {"ETH_P_WAN_PPP", Const, 0}, + {"ETH_P_WCCP", Const, 0}, + {"ETH_P_X25", Const, 0}, + {"ETIME", Const, 0}, + {"ETIMEDOUT", Const, 0}, + {"ETOOMANYREFS", Const, 0}, + {"ETXTBSY", Const, 0}, + {"EUCLEAN", Const, 0}, + {"EUNATCH", Const, 0}, + {"EUSERS", Const, 0}, + {"EVFILT_AIO", Const, 0}, + {"EVFILT_FS", Const, 0}, + {"EVFILT_LIO", Const, 0}, + {"EVFILT_MACHPORT", Const, 0}, + {"EVFILT_PROC", Const, 0}, + {"EVFILT_READ", Const, 0}, + {"EVFILT_SIGNAL", Const, 0}, + {"EVFILT_SYSCOUNT", Const, 0}, + {"EVFILT_THREADMARKER", Const, 0}, + {"EVFILT_TIMER", Const, 0}, + {"EVFILT_USER", Const, 0}, + {"EVFILT_VM", Const, 0}, + {"EVFILT_VNODE", Const, 0}, + {"EVFILT_WRITE", Const, 0}, + {"EV_ADD", Const, 0}, + {"EV_CLEAR", Const, 0}, + {"EV_DELETE", Const, 0}, + {"EV_DISABLE", Const, 0}, + {"EV_DISPATCH", Const, 0}, + {"EV_DROP", Const, 3}, + {"EV_ENABLE", Const, 0}, + {"EV_EOF", Const, 0}, + {"EV_ERROR", Const, 0}, + {"EV_FLAG0", Const, 0}, + {"EV_FLAG1", Const, 0}, + {"EV_ONESHOT", Const, 0}, + {"EV_OOBAND", Const, 0}, + {"EV_POLL", Const, 0}, + {"EV_RECEIPT", Const, 0}, + {"EV_SYSFLAGS", Const, 0}, + {"EWINDOWS", Const, 0}, + {"EWOULDBLOCK", Const, 0}, + {"EXDEV", Const, 0}, + {"EXFULL", Const, 0}, + {"EXTA", Const, 0}, + {"EXTB", Const, 0}, + {"EXTPROC", Const, 0}, + {"Environ", Func, 0}, + {"EpollCreate", Func, 0}, + {"EpollCreate1", Func, 0}, + {"EpollCtl", Func, 0}, + {"EpollEvent", Type, 0}, + {"EpollEvent.Events", Field, 0}, + {"EpollEvent.Fd", Field, 0}, + {"EpollEvent.Pad", Field, 0}, + {"EpollEvent.PadFd", Field, 0}, + {"EpollWait", Func, 0}, + {"Errno", Type, 0}, + {"EscapeArg", Func, 0}, + {"Exchangedata", Func, 0}, + {"Exec", Func, 0}, + {"Exit", Func, 0}, + {"ExitProcess", Func, 0}, + {"FD_CLOEXEC", Const, 0}, + {"FD_SETSIZE", Const, 0}, + {"FILE_ACTION_ADDED", Const, 0}, + {"FILE_ACTION_MODIFIED", Const, 0}, + {"FILE_ACTION_REMOVED", Const, 0}, + {"FILE_ACTION_RENAMED_NEW_NAME", Const, 0}, + {"FILE_ACTION_RENAMED_OLD_NAME", Const, 0}, + {"FILE_APPEND_DATA", Const, 0}, + {"FILE_ATTRIBUTE_ARCHIVE", Const, 0}, + {"FILE_ATTRIBUTE_DIRECTORY", Const, 0}, + {"FILE_ATTRIBUTE_HIDDEN", Const, 0}, + {"FILE_ATTRIBUTE_NORMAL", Const, 0}, + {"FILE_ATTRIBUTE_READONLY", Const, 0}, + {"FILE_ATTRIBUTE_REPARSE_POINT", Const, 4}, + {"FILE_ATTRIBUTE_SYSTEM", Const, 0}, + {"FILE_BEGIN", Const, 0}, + {"FILE_CURRENT", Const, 0}, + {"FILE_END", Const, 0}, + {"FILE_FLAG_BACKUP_SEMANTICS", Const, 0}, + {"FILE_FLAG_OPEN_REPARSE_POINT", Const, 4}, + {"FILE_FLAG_OVERLAPPED", Const, 0}, + {"FILE_LIST_DIRECTORY", Const, 0}, + {"FILE_MAP_COPY", Const, 0}, + {"FILE_MAP_EXECUTE", Const, 0}, + {"FILE_MAP_READ", Const, 0}, + {"FILE_MAP_WRITE", Const, 0}, + {"FILE_NOTIFY_CHANGE_ATTRIBUTES", Const, 0}, + {"FILE_NOTIFY_CHANGE_CREATION", Const, 0}, + {"FILE_NOTIFY_CHANGE_DIR_NAME", Const, 0}, + {"FILE_NOTIFY_CHANGE_FILE_NAME", Const, 0}, + {"FILE_NOTIFY_CHANGE_LAST_ACCESS", Const, 0}, + {"FILE_NOTIFY_CHANGE_LAST_WRITE", Const, 0}, + {"FILE_NOTIFY_CHANGE_SIZE", Const, 0}, + {"FILE_SHARE_DELETE", Const, 0}, + {"FILE_SHARE_READ", Const, 0}, + {"FILE_SHARE_WRITE", Const, 0}, + {"FILE_SKIP_COMPLETION_PORT_ON_SUCCESS", Const, 2}, + {"FILE_SKIP_SET_EVENT_ON_HANDLE", Const, 2}, + {"FILE_TYPE_CHAR", Const, 0}, + {"FILE_TYPE_DISK", Const, 0}, + {"FILE_TYPE_PIPE", Const, 0}, + {"FILE_TYPE_REMOTE", Const, 0}, + {"FILE_TYPE_UNKNOWN", Const, 0}, + {"FILE_WRITE_ATTRIBUTES", Const, 0}, + {"FLUSHO", Const, 0}, + {"FORMAT_MESSAGE_ALLOCATE_BUFFER", Const, 0}, + {"FORMAT_MESSAGE_ARGUMENT_ARRAY", Const, 0}, + {"FORMAT_MESSAGE_FROM_HMODULE", Const, 0}, + {"FORMAT_MESSAGE_FROM_STRING", Const, 0}, + {"FORMAT_MESSAGE_FROM_SYSTEM", Const, 0}, + {"FORMAT_MESSAGE_IGNORE_INSERTS", Const, 0}, + {"FORMAT_MESSAGE_MAX_WIDTH_MASK", Const, 0}, + {"FSCTL_GET_REPARSE_POINT", Const, 4}, + {"F_ADDFILESIGS", Const, 0}, + {"F_ADDSIGS", Const, 0}, + {"F_ALLOCATEALL", Const, 0}, + {"F_ALLOCATECONTIG", Const, 0}, + {"F_CANCEL", Const, 0}, + {"F_CHKCLEAN", Const, 0}, + {"F_CLOSEM", Const, 1}, + {"F_DUP2FD", Const, 0}, + {"F_DUP2FD_CLOEXEC", Const, 1}, + {"F_DUPFD", Const, 0}, + {"F_DUPFD_CLOEXEC", Const, 0}, + {"F_EXLCK", Const, 0}, + {"F_FINDSIGS", Const, 16}, + {"F_FLUSH_DATA", Const, 0}, + {"F_FREEZE_FS", Const, 0}, + {"F_FSCTL", Const, 1}, + {"F_FSDIRMASK", Const, 1}, + {"F_FSIN", Const, 1}, + {"F_FSINOUT", Const, 1}, + {"F_FSOUT", Const, 1}, + {"F_FSPRIV", Const, 1}, + {"F_FSVOID", Const, 1}, + {"F_FULLFSYNC", Const, 0}, + {"F_GETCODEDIR", Const, 16}, + {"F_GETFD", Const, 0}, + {"F_GETFL", Const, 0}, + {"F_GETLEASE", Const, 0}, + {"F_GETLK", Const, 0}, + {"F_GETLK64", Const, 0}, + {"F_GETLKPID", Const, 0}, + {"F_GETNOSIGPIPE", Const, 0}, + {"F_GETOWN", Const, 0}, + {"F_GETOWN_EX", Const, 0}, + {"F_GETPATH", Const, 0}, + {"F_GETPATH_MTMINFO", Const, 0}, + {"F_GETPIPE_SZ", Const, 0}, + {"F_GETPROTECTIONCLASS", Const, 0}, + {"F_GETPROTECTIONLEVEL", Const, 16}, + {"F_GETSIG", Const, 0}, + {"F_GLOBAL_NOCACHE", Const, 0}, + {"F_LOCK", Const, 0}, + {"F_LOG2PHYS", Const, 0}, + {"F_LOG2PHYS_EXT", Const, 0}, + {"F_MARKDEPENDENCY", Const, 0}, + {"F_MAXFD", Const, 1}, + {"F_NOCACHE", Const, 0}, + {"F_NODIRECT", Const, 0}, + {"F_NOTIFY", Const, 0}, + {"F_OGETLK", Const, 0}, + {"F_OK", Const, 0}, + {"F_OSETLK", Const, 0}, + {"F_OSETLKW", Const, 0}, + {"F_PARAM_MASK", Const, 1}, + {"F_PARAM_MAX", Const, 1}, + {"F_PATHPKG_CHECK", Const, 0}, + {"F_PEOFPOSMODE", Const, 0}, + {"F_PREALLOCATE", Const, 0}, + {"F_RDADVISE", Const, 0}, + {"F_RDAHEAD", Const, 0}, + {"F_RDLCK", Const, 0}, + {"F_READAHEAD", Const, 0}, + {"F_READBOOTSTRAP", Const, 0}, + {"F_SETBACKINGSTORE", Const, 0}, + {"F_SETFD", Const, 0}, + {"F_SETFL", Const, 0}, + {"F_SETLEASE", Const, 0}, + {"F_SETLK", Const, 0}, + {"F_SETLK64", Const, 0}, + {"F_SETLKW", Const, 0}, + {"F_SETLKW64", Const, 0}, + {"F_SETLKWTIMEOUT", Const, 16}, + {"F_SETLK_REMOTE", Const, 0}, + {"F_SETNOSIGPIPE", Const, 0}, + {"F_SETOWN", Const, 0}, + {"F_SETOWN_EX", Const, 0}, + {"F_SETPIPE_SZ", Const, 0}, + {"F_SETPROTECTIONCLASS", Const, 0}, + {"F_SETSIG", Const, 0}, + {"F_SETSIZE", Const, 0}, + {"F_SHLCK", Const, 0}, + {"F_SINGLE_WRITER", Const, 16}, + {"F_TEST", Const, 0}, + {"F_THAW_FS", Const, 0}, + {"F_TLOCK", Const, 0}, + {"F_TRANSCODEKEY", Const, 16}, + {"F_ULOCK", Const, 0}, + {"F_UNLCK", Const, 0}, + {"F_UNLCKSYS", Const, 0}, + {"F_VOLPOSMODE", Const, 0}, + {"F_WRITEBOOTSTRAP", Const, 0}, + {"F_WRLCK", Const, 0}, + {"Faccessat", Func, 0}, + {"Fallocate", Func, 0}, + {"Fbootstraptransfer_t", Type, 0}, + {"Fbootstraptransfer_t.Buffer", Field, 0}, + {"Fbootstraptransfer_t.Length", Field, 0}, + {"Fbootstraptransfer_t.Offset", Field, 0}, + {"Fchdir", Func, 0}, + {"Fchflags", Func, 0}, + {"Fchmod", Func, 0}, + {"Fchmodat", Func, 0}, + {"Fchown", Func, 0}, + {"Fchownat", Func, 0}, + {"FcntlFlock", Func, 3}, + {"FdSet", Type, 0}, + {"FdSet.Bits", Field, 0}, + {"FdSet.X__fds_bits", Field, 0}, + {"Fdatasync", Func, 0}, + {"FileNotifyInformation", Type, 0}, + {"FileNotifyInformation.Action", Field, 0}, + {"FileNotifyInformation.FileName", Field, 0}, + {"FileNotifyInformation.FileNameLength", Field, 0}, + {"FileNotifyInformation.NextEntryOffset", Field, 0}, + {"Filetime", Type, 0}, + {"Filetime.HighDateTime", Field, 0}, + {"Filetime.LowDateTime", Field, 0}, + {"FindClose", Func, 0}, + {"FindFirstFile", Func, 0}, + {"FindNextFile", Func, 0}, + {"Flock", Func, 0}, + {"Flock_t", Type, 0}, + {"Flock_t.Len", Field, 0}, + {"Flock_t.Pad_cgo_0", Field, 0}, + {"Flock_t.Pad_cgo_1", Field, 3}, + {"Flock_t.Pid", Field, 0}, + {"Flock_t.Start", Field, 0}, + {"Flock_t.Sysid", Field, 0}, + {"Flock_t.Type", Field, 0}, + {"Flock_t.Whence", Field, 0}, + {"FlushBpf", Func, 0}, + {"FlushFileBuffers", Func, 0}, + {"FlushViewOfFile", Func, 0}, + {"ForkExec", Func, 0}, + {"ForkLock", Var, 0}, + {"FormatMessage", Func, 0}, + {"Fpathconf", Func, 0}, + {"FreeAddrInfoW", Func, 1}, + {"FreeEnvironmentStrings", Func, 0}, + {"FreeLibrary", Func, 0}, + {"Fsid", Type, 0}, + {"Fsid.Val", Field, 0}, + {"Fsid.X__fsid_val", Field, 2}, + {"Fsid.X__val", Field, 0}, + {"Fstat", Func, 0}, + {"Fstatat", Func, 12}, + {"Fstatfs", Func, 0}, + {"Fstore_t", Type, 0}, + {"Fstore_t.Bytesalloc", Field, 0}, + {"Fstore_t.Flags", Field, 0}, + {"Fstore_t.Length", Field, 0}, + {"Fstore_t.Offset", Field, 0}, + {"Fstore_t.Posmode", Field, 0}, + {"Fsync", Func, 0}, + {"Ftruncate", Func, 0}, + {"FullPath", Func, 4}, + {"Futimes", Func, 0}, + {"Futimesat", Func, 0}, + {"GENERIC_ALL", Const, 0}, + {"GENERIC_EXECUTE", Const, 0}, + {"GENERIC_READ", Const, 0}, + {"GENERIC_WRITE", Const, 0}, + {"GUID", Type, 1}, + {"GUID.Data1", Field, 1}, + {"GUID.Data2", Field, 1}, + {"GUID.Data3", Field, 1}, + {"GUID.Data4", Field, 1}, + {"GetAcceptExSockaddrs", Func, 0}, + {"GetAdaptersInfo", Func, 0}, + {"GetAddrInfoW", Func, 1}, + {"GetCommandLine", Func, 0}, + {"GetComputerName", Func, 0}, + {"GetConsoleMode", Func, 1}, + {"GetCurrentDirectory", Func, 0}, + {"GetCurrentProcess", Func, 0}, + {"GetEnvironmentStrings", Func, 0}, + {"GetEnvironmentVariable", Func, 0}, + {"GetExitCodeProcess", Func, 0}, + {"GetFileAttributes", Func, 0}, + {"GetFileAttributesEx", Func, 0}, + {"GetFileExInfoStandard", Const, 0}, + {"GetFileExMaxInfoLevel", Const, 0}, + {"GetFileInformationByHandle", Func, 0}, + {"GetFileType", Func, 0}, + {"GetFullPathName", Func, 0}, + {"GetHostByName", Func, 0}, + {"GetIfEntry", Func, 0}, + {"GetLastError", Func, 0}, + {"GetLengthSid", Func, 0}, + {"GetLongPathName", Func, 0}, + {"GetProcAddress", Func, 0}, + {"GetProcessTimes", Func, 0}, + {"GetProtoByName", Func, 0}, + {"GetQueuedCompletionStatus", Func, 0}, + {"GetServByName", Func, 0}, + {"GetShortPathName", Func, 0}, + {"GetStartupInfo", Func, 0}, + {"GetStdHandle", Func, 0}, + {"GetSystemTimeAsFileTime", Func, 0}, + {"GetTempPath", Func, 0}, + {"GetTimeZoneInformation", Func, 0}, + {"GetTokenInformation", Func, 0}, + {"GetUserNameEx", Func, 0}, + {"GetUserProfileDirectory", Func, 0}, + {"GetVersion", Func, 0}, + {"Getcwd", Func, 0}, + {"Getdents", Func, 0}, + {"Getdirentries", Func, 0}, + {"Getdtablesize", Func, 0}, + {"Getegid", Func, 0}, + {"Getenv", Func, 0}, + {"Geteuid", Func, 0}, + {"Getfsstat", Func, 0}, + {"Getgid", Func, 0}, + {"Getgroups", Func, 0}, + {"Getpagesize", Func, 0}, + {"Getpeername", Func, 0}, + {"Getpgid", Func, 0}, + {"Getpgrp", Func, 0}, + {"Getpid", Func, 0}, + {"Getppid", Func, 0}, + {"Getpriority", Func, 0}, + {"Getrlimit", Func, 0}, + {"Getrusage", Func, 0}, + {"Getsid", Func, 0}, + {"Getsockname", Func, 0}, + {"Getsockopt", Func, 1}, + {"GetsockoptByte", Func, 0}, + {"GetsockoptICMPv6Filter", Func, 2}, + {"GetsockoptIPMreq", Func, 0}, + {"GetsockoptIPMreqn", Func, 0}, + {"GetsockoptIPv6MTUInfo", Func, 2}, + {"GetsockoptIPv6Mreq", Func, 0}, + {"GetsockoptInet4Addr", Func, 0}, + {"GetsockoptInt", Func, 0}, + {"GetsockoptUcred", Func, 1}, + {"Gettid", Func, 0}, + {"Gettimeofday", Func, 0}, + {"Getuid", Func, 0}, + {"Getwd", Func, 0}, + {"Getxattr", Func, 1}, + {"HANDLE_FLAG_INHERIT", Const, 0}, + {"HKEY_CLASSES_ROOT", Const, 0}, + {"HKEY_CURRENT_CONFIG", Const, 0}, + {"HKEY_CURRENT_USER", Const, 0}, + {"HKEY_DYN_DATA", Const, 0}, + {"HKEY_LOCAL_MACHINE", Const, 0}, + {"HKEY_PERFORMANCE_DATA", Const, 0}, + {"HKEY_USERS", Const, 0}, + {"HUPCL", Const, 0}, + {"Handle", Type, 0}, + {"Hostent", Type, 0}, + {"Hostent.AddrList", Field, 0}, + {"Hostent.AddrType", Field, 0}, + {"Hostent.Aliases", Field, 0}, + {"Hostent.Length", Field, 0}, + {"Hostent.Name", Field, 0}, + {"ICANON", Const, 0}, + {"ICMP6_FILTER", Const, 2}, + {"ICMPV6_FILTER", Const, 2}, + {"ICMPv6Filter", Type, 2}, + {"ICMPv6Filter.Data", Field, 2}, + {"ICMPv6Filter.Filt", Field, 2}, + {"ICRNL", Const, 0}, + {"IEXTEN", Const, 0}, + {"IFAN_ARRIVAL", Const, 1}, + {"IFAN_DEPARTURE", Const, 1}, + {"IFA_ADDRESS", Const, 0}, + {"IFA_ANYCAST", Const, 0}, + {"IFA_BROADCAST", Const, 0}, + {"IFA_CACHEINFO", Const, 0}, + {"IFA_F_DADFAILED", Const, 0}, + {"IFA_F_DEPRECATED", Const, 0}, + {"IFA_F_HOMEADDRESS", Const, 0}, + {"IFA_F_NODAD", Const, 0}, + {"IFA_F_OPTIMISTIC", Const, 0}, + {"IFA_F_PERMANENT", Const, 0}, + {"IFA_F_SECONDARY", Const, 0}, + {"IFA_F_TEMPORARY", Const, 0}, + {"IFA_F_TENTATIVE", Const, 0}, + {"IFA_LABEL", Const, 0}, + {"IFA_LOCAL", Const, 0}, + {"IFA_MAX", Const, 0}, + {"IFA_MULTICAST", Const, 0}, + {"IFA_ROUTE", Const, 1}, + {"IFA_UNSPEC", Const, 0}, + {"IFF_ALLMULTI", Const, 0}, + {"IFF_ALTPHYS", Const, 0}, + {"IFF_AUTOMEDIA", Const, 0}, + {"IFF_BROADCAST", Const, 0}, + {"IFF_CANTCHANGE", Const, 0}, + {"IFF_CANTCONFIG", Const, 1}, + {"IFF_DEBUG", Const, 0}, + {"IFF_DRV_OACTIVE", Const, 0}, + {"IFF_DRV_RUNNING", Const, 0}, + {"IFF_DYING", Const, 0}, + {"IFF_DYNAMIC", Const, 0}, + {"IFF_LINK0", Const, 0}, + {"IFF_LINK1", Const, 0}, + {"IFF_LINK2", Const, 0}, + {"IFF_LOOPBACK", Const, 0}, + {"IFF_MASTER", Const, 0}, + {"IFF_MONITOR", Const, 0}, + {"IFF_MULTICAST", Const, 0}, + {"IFF_NOARP", Const, 0}, + {"IFF_NOTRAILERS", Const, 0}, + {"IFF_NO_PI", Const, 0}, + {"IFF_OACTIVE", Const, 0}, + {"IFF_ONE_QUEUE", Const, 0}, + {"IFF_POINTOPOINT", Const, 0}, + {"IFF_POINTTOPOINT", Const, 0}, + {"IFF_PORTSEL", Const, 0}, + {"IFF_PPROMISC", Const, 0}, + {"IFF_PROMISC", Const, 0}, + {"IFF_RENAMING", Const, 0}, + {"IFF_RUNNING", Const, 0}, + {"IFF_SIMPLEX", Const, 0}, + {"IFF_SLAVE", Const, 0}, + {"IFF_SMART", Const, 0}, + {"IFF_STATICARP", Const, 0}, + {"IFF_TAP", Const, 0}, + {"IFF_TUN", Const, 0}, + {"IFF_TUN_EXCL", Const, 0}, + {"IFF_UP", Const, 0}, + {"IFF_VNET_HDR", Const, 0}, + {"IFLA_ADDRESS", Const, 0}, + {"IFLA_BROADCAST", Const, 0}, + {"IFLA_COST", Const, 0}, + {"IFLA_IFALIAS", Const, 0}, + {"IFLA_IFNAME", Const, 0}, + {"IFLA_LINK", Const, 0}, + {"IFLA_LINKINFO", Const, 0}, + {"IFLA_LINKMODE", Const, 0}, + {"IFLA_MAP", Const, 0}, + {"IFLA_MASTER", Const, 0}, + {"IFLA_MAX", Const, 0}, + {"IFLA_MTU", Const, 0}, + {"IFLA_NET_NS_PID", Const, 0}, + {"IFLA_OPERSTATE", Const, 0}, + {"IFLA_PRIORITY", Const, 0}, + {"IFLA_PROTINFO", Const, 0}, + {"IFLA_QDISC", Const, 0}, + {"IFLA_STATS", Const, 0}, + {"IFLA_TXQLEN", Const, 0}, + {"IFLA_UNSPEC", Const, 0}, + {"IFLA_WEIGHT", Const, 0}, + {"IFLA_WIRELESS", Const, 0}, + {"IFNAMSIZ", Const, 0}, + {"IFT_1822", Const, 0}, + {"IFT_A12MPPSWITCH", Const, 0}, + {"IFT_AAL2", Const, 0}, + {"IFT_AAL5", Const, 0}, + {"IFT_ADSL", Const, 0}, + {"IFT_AFLANE8023", Const, 0}, + {"IFT_AFLANE8025", Const, 0}, + {"IFT_ARAP", Const, 0}, + {"IFT_ARCNET", Const, 0}, + {"IFT_ARCNETPLUS", Const, 0}, + {"IFT_ASYNC", Const, 0}, + {"IFT_ATM", Const, 0}, + {"IFT_ATMDXI", Const, 0}, + {"IFT_ATMFUNI", Const, 0}, + {"IFT_ATMIMA", Const, 0}, + {"IFT_ATMLOGICAL", Const, 0}, + {"IFT_ATMRADIO", Const, 0}, + {"IFT_ATMSUBINTERFACE", Const, 0}, + {"IFT_ATMVCIENDPT", Const, 0}, + {"IFT_ATMVIRTUAL", Const, 0}, + {"IFT_BGPPOLICYACCOUNTING", Const, 0}, + {"IFT_BLUETOOTH", Const, 1}, + {"IFT_BRIDGE", Const, 0}, + {"IFT_BSC", Const, 0}, + {"IFT_CARP", Const, 0}, + {"IFT_CCTEMUL", Const, 0}, + {"IFT_CELLULAR", Const, 0}, + {"IFT_CEPT", Const, 0}, + {"IFT_CES", Const, 0}, + {"IFT_CHANNEL", Const, 0}, + {"IFT_CNR", Const, 0}, + {"IFT_COFFEE", Const, 0}, + {"IFT_COMPOSITELINK", Const, 0}, + {"IFT_DCN", Const, 0}, + {"IFT_DIGITALPOWERLINE", Const, 0}, + {"IFT_DIGITALWRAPPEROVERHEADCHANNEL", Const, 0}, + {"IFT_DLSW", Const, 0}, + {"IFT_DOCSCABLEDOWNSTREAM", Const, 0}, + {"IFT_DOCSCABLEMACLAYER", Const, 0}, + {"IFT_DOCSCABLEUPSTREAM", Const, 0}, + {"IFT_DOCSCABLEUPSTREAMCHANNEL", Const, 1}, + {"IFT_DS0", Const, 0}, + {"IFT_DS0BUNDLE", Const, 0}, + {"IFT_DS1FDL", Const, 0}, + {"IFT_DS3", Const, 0}, + {"IFT_DTM", Const, 0}, + {"IFT_DUMMY", Const, 1}, + {"IFT_DVBASILN", Const, 0}, + {"IFT_DVBASIOUT", Const, 0}, + {"IFT_DVBRCCDOWNSTREAM", Const, 0}, + {"IFT_DVBRCCMACLAYER", Const, 0}, + {"IFT_DVBRCCUPSTREAM", Const, 0}, + {"IFT_ECONET", Const, 1}, + {"IFT_ENC", Const, 0}, + {"IFT_EON", Const, 0}, + {"IFT_EPLRS", Const, 0}, + {"IFT_ESCON", Const, 0}, + {"IFT_ETHER", Const, 0}, + {"IFT_FAITH", Const, 0}, + {"IFT_FAST", Const, 0}, + {"IFT_FASTETHER", Const, 0}, + {"IFT_FASTETHERFX", Const, 0}, + {"IFT_FDDI", Const, 0}, + {"IFT_FIBRECHANNEL", Const, 0}, + {"IFT_FRAMERELAYINTERCONNECT", Const, 0}, + {"IFT_FRAMERELAYMPI", Const, 0}, + {"IFT_FRDLCIENDPT", Const, 0}, + {"IFT_FRELAY", Const, 0}, + {"IFT_FRELAYDCE", Const, 0}, + {"IFT_FRF16MFRBUNDLE", Const, 0}, + {"IFT_FRFORWARD", Const, 0}, + {"IFT_G703AT2MB", Const, 0}, + {"IFT_G703AT64K", Const, 0}, + {"IFT_GIF", Const, 0}, + {"IFT_GIGABITETHERNET", Const, 0}, + {"IFT_GR303IDT", Const, 0}, + {"IFT_GR303RDT", Const, 0}, + {"IFT_H323GATEKEEPER", Const, 0}, + {"IFT_H323PROXY", Const, 0}, + {"IFT_HDH1822", Const, 0}, + {"IFT_HDLC", Const, 0}, + {"IFT_HDSL2", Const, 0}, + {"IFT_HIPERLAN2", Const, 0}, + {"IFT_HIPPI", Const, 0}, + {"IFT_HIPPIINTERFACE", Const, 0}, + {"IFT_HOSTPAD", Const, 0}, + {"IFT_HSSI", Const, 0}, + {"IFT_HY", Const, 0}, + {"IFT_IBM370PARCHAN", Const, 0}, + {"IFT_IDSL", Const, 0}, + {"IFT_IEEE1394", Const, 0}, + {"IFT_IEEE80211", Const, 0}, + {"IFT_IEEE80212", Const, 0}, + {"IFT_IEEE8023ADLAG", Const, 0}, + {"IFT_IFGSN", Const, 0}, + {"IFT_IMT", Const, 0}, + {"IFT_INFINIBAND", Const, 1}, + {"IFT_INTERLEAVE", Const, 0}, + {"IFT_IP", Const, 0}, + {"IFT_IPFORWARD", Const, 0}, + {"IFT_IPOVERATM", Const, 0}, + {"IFT_IPOVERCDLC", Const, 0}, + {"IFT_IPOVERCLAW", Const, 0}, + {"IFT_IPSWITCH", Const, 0}, + {"IFT_IPXIP", Const, 0}, + {"IFT_ISDN", Const, 0}, + {"IFT_ISDNBASIC", Const, 0}, + {"IFT_ISDNPRIMARY", Const, 0}, + {"IFT_ISDNS", Const, 0}, + {"IFT_ISDNU", Const, 0}, + {"IFT_ISO88022LLC", Const, 0}, + {"IFT_ISO88023", Const, 0}, + {"IFT_ISO88024", Const, 0}, + {"IFT_ISO88025", Const, 0}, + {"IFT_ISO88025CRFPINT", Const, 0}, + {"IFT_ISO88025DTR", Const, 0}, + {"IFT_ISO88025FIBER", Const, 0}, + {"IFT_ISO88026", Const, 0}, + {"IFT_ISUP", Const, 0}, + {"IFT_L2VLAN", Const, 0}, + {"IFT_L3IPVLAN", Const, 0}, + {"IFT_L3IPXVLAN", Const, 0}, + {"IFT_LAPB", Const, 0}, + {"IFT_LAPD", Const, 0}, + {"IFT_LAPF", Const, 0}, + {"IFT_LINEGROUP", Const, 1}, + {"IFT_LOCALTALK", Const, 0}, + {"IFT_LOOP", Const, 0}, + {"IFT_MEDIAMAILOVERIP", Const, 0}, + {"IFT_MFSIGLINK", Const, 0}, + {"IFT_MIOX25", Const, 0}, + {"IFT_MODEM", Const, 0}, + {"IFT_MPC", Const, 0}, + {"IFT_MPLS", Const, 0}, + {"IFT_MPLSTUNNEL", Const, 0}, + {"IFT_MSDSL", Const, 0}, + {"IFT_MVL", Const, 0}, + {"IFT_MYRINET", Const, 0}, + {"IFT_NFAS", Const, 0}, + {"IFT_NSIP", Const, 0}, + {"IFT_OPTICALCHANNEL", Const, 0}, + {"IFT_OPTICALTRANSPORT", Const, 0}, + {"IFT_OTHER", Const, 0}, + {"IFT_P10", Const, 0}, + {"IFT_P80", Const, 0}, + {"IFT_PARA", Const, 0}, + {"IFT_PDP", Const, 0}, + {"IFT_PFLOG", Const, 0}, + {"IFT_PFLOW", Const, 1}, + {"IFT_PFSYNC", Const, 0}, + {"IFT_PLC", Const, 0}, + {"IFT_PON155", Const, 1}, + {"IFT_PON622", Const, 1}, + {"IFT_POS", Const, 0}, + {"IFT_PPP", Const, 0}, + {"IFT_PPPMULTILINKBUNDLE", Const, 0}, + {"IFT_PROPATM", Const, 1}, + {"IFT_PROPBWAP2MP", Const, 0}, + {"IFT_PROPCNLS", Const, 0}, + {"IFT_PROPDOCSWIRELESSDOWNSTREAM", Const, 0}, + {"IFT_PROPDOCSWIRELESSMACLAYER", Const, 0}, + {"IFT_PROPDOCSWIRELESSUPSTREAM", Const, 0}, + {"IFT_PROPMUX", Const, 0}, + {"IFT_PROPVIRTUAL", Const, 0}, + {"IFT_PROPWIRELESSP2P", Const, 0}, + {"IFT_PTPSERIAL", Const, 0}, + {"IFT_PVC", Const, 0}, + {"IFT_Q2931", Const, 1}, + {"IFT_QLLC", Const, 0}, + {"IFT_RADIOMAC", Const, 0}, + {"IFT_RADSL", Const, 0}, + {"IFT_REACHDSL", Const, 0}, + {"IFT_RFC1483", Const, 0}, + {"IFT_RS232", Const, 0}, + {"IFT_RSRB", Const, 0}, + {"IFT_SDLC", Const, 0}, + {"IFT_SDSL", Const, 0}, + {"IFT_SHDSL", Const, 0}, + {"IFT_SIP", Const, 0}, + {"IFT_SIPSIG", Const, 1}, + {"IFT_SIPTG", Const, 1}, + {"IFT_SLIP", Const, 0}, + {"IFT_SMDSDXI", Const, 0}, + {"IFT_SMDSICIP", Const, 0}, + {"IFT_SONET", Const, 0}, + {"IFT_SONETOVERHEADCHANNEL", Const, 0}, + {"IFT_SONETPATH", Const, 0}, + {"IFT_SONETVT", Const, 0}, + {"IFT_SRP", Const, 0}, + {"IFT_SS7SIGLINK", Const, 0}, + {"IFT_STACKTOSTACK", Const, 0}, + {"IFT_STARLAN", Const, 0}, + {"IFT_STF", Const, 0}, + {"IFT_T1", Const, 0}, + {"IFT_TDLC", Const, 0}, + {"IFT_TELINK", Const, 1}, + {"IFT_TERMPAD", Const, 0}, + {"IFT_TR008", Const, 0}, + {"IFT_TRANSPHDLC", Const, 0}, + {"IFT_TUNNEL", Const, 0}, + {"IFT_ULTRA", Const, 0}, + {"IFT_USB", Const, 0}, + {"IFT_V11", Const, 0}, + {"IFT_V35", Const, 0}, + {"IFT_V36", Const, 0}, + {"IFT_V37", Const, 0}, + {"IFT_VDSL", Const, 0}, + {"IFT_VIRTUALIPADDRESS", Const, 0}, + {"IFT_VIRTUALTG", Const, 1}, + {"IFT_VOICEDID", Const, 1}, + {"IFT_VOICEEM", Const, 0}, + {"IFT_VOICEEMFGD", Const, 1}, + {"IFT_VOICEENCAP", Const, 0}, + {"IFT_VOICEFGDEANA", Const, 1}, + {"IFT_VOICEFXO", Const, 0}, + {"IFT_VOICEFXS", Const, 0}, + {"IFT_VOICEOVERATM", Const, 0}, + {"IFT_VOICEOVERCABLE", Const, 1}, + {"IFT_VOICEOVERFRAMERELAY", Const, 0}, + {"IFT_VOICEOVERIP", Const, 0}, + {"IFT_X213", Const, 0}, + {"IFT_X25", Const, 0}, + {"IFT_X25DDN", Const, 0}, + {"IFT_X25HUNTGROUP", Const, 0}, + {"IFT_X25MLP", Const, 0}, + {"IFT_X25PLE", Const, 0}, + {"IFT_XETHER", Const, 0}, + {"IGNBRK", Const, 0}, + {"IGNCR", Const, 0}, + {"IGNORE", Const, 0}, + {"IGNPAR", Const, 0}, + {"IMAXBEL", Const, 0}, + {"INFINITE", Const, 0}, + {"INLCR", Const, 0}, + {"INPCK", Const, 0}, + {"INVALID_FILE_ATTRIBUTES", Const, 0}, + {"IN_ACCESS", Const, 0}, + {"IN_ALL_EVENTS", Const, 0}, + {"IN_ATTRIB", Const, 0}, + {"IN_CLASSA_HOST", Const, 0}, + {"IN_CLASSA_MAX", Const, 0}, + {"IN_CLASSA_NET", Const, 0}, + {"IN_CLASSA_NSHIFT", Const, 0}, + {"IN_CLASSB_HOST", Const, 0}, + {"IN_CLASSB_MAX", Const, 0}, + {"IN_CLASSB_NET", Const, 0}, + {"IN_CLASSB_NSHIFT", Const, 0}, + {"IN_CLASSC_HOST", Const, 0}, + {"IN_CLASSC_NET", Const, 0}, + {"IN_CLASSC_NSHIFT", Const, 0}, + {"IN_CLASSD_HOST", Const, 0}, + {"IN_CLASSD_NET", Const, 0}, + {"IN_CLASSD_NSHIFT", Const, 0}, + {"IN_CLOEXEC", Const, 0}, + {"IN_CLOSE", Const, 0}, + {"IN_CLOSE_NOWRITE", Const, 0}, + {"IN_CLOSE_WRITE", Const, 0}, + {"IN_CREATE", Const, 0}, + {"IN_DELETE", Const, 0}, + {"IN_DELETE_SELF", Const, 0}, + {"IN_DONT_FOLLOW", Const, 0}, + {"IN_EXCL_UNLINK", Const, 0}, + {"IN_IGNORED", Const, 0}, + {"IN_ISDIR", Const, 0}, + {"IN_LINKLOCALNETNUM", Const, 0}, + {"IN_LOOPBACKNET", Const, 0}, + {"IN_MASK_ADD", Const, 0}, + {"IN_MODIFY", Const, 0}, + {"IN_MOVE", Const, 0}, + {"IN_MOVED_FROM", Const, 0}, + {"IN_MOVED_TO", Const, 0}, + {"IN_MOVE_SELF", Const, 0}, + {"IN_NONBLOCK", Const, 0}, + {"IN_ONESHOT", Const, 0}, + {"IN_ONLYDIR", Const, 0}, + {"IN_OPEN", Const, 0}, + {"IN_Q_OVERFLOW", Const, 0}, + {"IN_RFC3021_HOST", Const, 1}, + {"IN_RFC3021_MASK", Const, 1}, + {"IN_RFC3021_NET", Const, 1}, + {"IN_RFC3021_NSHIFT", Const, 1}, + {"IN_UNMOUNT", Const, 0}, + {"IOC_IN", Const, 1}, + {"IOC_INOUT", Const, 1}, + {"IOC_OUT", Const, 1}, + {"IOC_VENDOR", Const, 3}, + {"IOC_WS2", Const, 1}, + {"IO_REPARSE_TAG_SYMLINK", Const, 4}, + {"IPMreq", Type, 0}, + {"IPMreq.Interface", Field, 0}, + {"IPMreq.Multiaddr", Field, 0}, + {"IPMreqn", Type, 0}, + {"IPMreqn.Address", Field, 0}, + {"IPMreqn.Ifindex", Field, 0}, + {"IPMreqn.Multiaddr", Field, 0}, + {"IPPROTO_3PC", Const, 0}, + {"IPPROTO_ADFS", Const, 0}, + {"IPPROTO_AH", Const, 0}, + {"IPPROTO_AHIP", Const, 0}, + {"IPPROTO_APES", Const, 0}, + {"IPPROTO_ARGUS", Const, 0}, + {"IPPROTO_AX25", Const, 0}, + {"IPPROTO_BHA", Const, 0}, + {"IPPROTO_BLT", Const, 0}, + {"IPPROTO_BRSATMON", Const, 0}, + {"IPPROTO_CARP", Const, 0}, + {"IPPROTO_CFTP", Const, 0}, + {"IPPROTO_CHAOS", Const, 0}, + {"IPPROTO_CMTP", Const, 0}, + {"IPPROTO_COMP", Const, 0}, + {"IPPROTO_CPHB", Const, 0}, + {"IPPROTO_CPNX", Const, 0}, + {"IPPROTO_DCCP", Const, 0}, + {"IPPROTO_DDP", Const, 0}, + {"IPPROTO_DGP", Const, 0}, + {"IPPROTO_DIVERT", Const, 0}, + {"IPPROTO_DIVERT_INIT", Const, 3}, + {"IPPROTO_DIVERT_RESP", Const, 3}, + {"IPPROTO_DONE", Const, 0}, + {"IPPROTO_DSTOPTS", Const, 0}, + {"IPPROTO_EGP", Const, 0}, + {"IPPROTO_EMCON", Const, 0}, + {"IPPROTO_ENCAP", Const, 0}, + {"IPPROTO_EON", Const, 0}, + {"IPPROTO_ESP", Const, 0}, + {"IPPROTO_ETHERIP", Const, 0}, + {"IPPROTO_FRAGMENT", Const, 0}, + {"IPPROTO_GGP", Const, 0}, + {"IPPROTO_GMTP", Const, 0}, + {"IPPROTO_GRE", Const, 0}, + {"IPPROTO_HELLO", Const, 0}, + {"IPPROTO_HMP", Const, 0}, + {"IPPROTO_HOPOPTS", Const, 0}, + {"IPPROTO_ICMP", Const, 0}, + {"IPPROTO_ICMPV6", Const, 0}, + {"IPPROTO_IDP", Const, 0}, + {"IPPROTO_IDPR", Const, 0}, + {"IPPROTO_IDRP", Const, 0}, + {"IPPROTO_IGMP", Const, 0}, + {"IPPROTO_IGP", Const, 0}, + {"IPPROTO_IGRP", Const, 0}, + {"IPPROTO_IL", Const, 0}, + {"IPPROTO_INLSP", Const, 0}, + {"IPPROTO_INP", Const, 0}, + {"IPPROTO_IP", Const, 0}, + {"IPPROTO_IPCOMP", Const, 0}, + {"IPPROTO_IPCV", Const, 0}, + {"IPPROTO_IPEIP", Const, 0}, + {"IPPROTO_IPIP", Const, 0}, + {"IPPROTO_IPPC", Const, 0}, + {"IPPROTO_IPV4", Const, 0}, + {"IPPROTO_IPV6", Const, 0}, + {"IPPROTO_IPV6_ICMP", Const, 1}, + {"IPPROTO_IRTP", Const, 0}, + {"IPPROTO_KRYPTOLAN", Const, 0}, + {"IPPROTO_LARP", Const, 0}, + {"IPPROTO_LEAF1", Const, 0}, + {"IPPROTO_LEAF2", Const, 0}, + {"IPPROTO_MAX", Const, 0}, + {"IPPROTO_MAXID", Const, 0}, + {"IPPROTO_MEAS", Const, 0}, + {"IPPROTO_MH", Const, 1}, + {"IPPROTO_MHRP", Const, 0}, + {"IPPROTO_MICP", Const, 0}, + {"IPPROTO_MOBILE", Const, 0}, + {"IPPROTO_MPLS", Const, 1}, + {"IPPROTO_MTP", Const, 0}, + {"IPPROTO_MUX", Const, 0}, + {"IPPROTO_ND", Const, 0}, + {"IPPROTO_NHRP", Const, 0}, + {"IPPROTO_NONE", Const, 0}, + {"IPPROTO_NSP", Const, 0}, + {"IPPROTO_NVPII", Const, 0}, + {"IPPROTO_OLD_DIVERT", Const, 0}, + {"IPPROTO_OSPFIGP", Const, 0}, + {"IPPROTO_PFSYNC", Const, 0}, + {"IPPROTO_PGM", Const, 0}, + {"IPPROTO_PIGP", Const, 0}, + {"IPPROTO_PIM", Const, 0}, + {"IPPROTO_PRM", Const, 0}, + {"IPPROTO_PUP", Const, 0}, + {"IPPROTO_PVP", Const, 0}, + {"IPPROTO_RAW", Const, 0}, + {"IPPROTO_RCCMON", Const, 0}, + {"IPPROTO_RDP", Const, 0}, + {"IPPROTO_ROUTING", Const, 0}, + {"IPPROTO_RSVP", Const, 0}, + {"IPPROTO_RVD", Const, 0}, + {"IPPROTO_SATEXPAK", Const, 0}, + {"IPPROTO_SATMON", Const, 0}, + {"IPPROTO_SCCSP", Const, 0}, + {"IPPROTO_SCTP", Const, 0}, + {"IPPROTO_SDRP", Const, 0}, + {"IPPROTO_SEND", Const, 1}, + {"IPPROTO_SEP", Const, 0}, + {"IPPROTO_SKIP", Const, 0}, + {"IPPROTO_SPACER", Const, 0}, + {"IPPROTO_SRPC", Const, 0}, + {"IPPROTO_ST", Const, 0}, + {"IPPROTO_SVMTP", Const, 0}, + {"IPPROTO_SWIPE", Const, 0}, + {"IPPROTO_TCF", Const, 0}, + {"IPPROTO_TCP", Const, 0}, + {"IPPROTO_TLSP", Const, 0}, + {"IPPROTO_TP", Const, 0}, + {"IPPROTO_TPXX", Const, 0}, + {"IPPROTO_TRUNK1", Const, 0}, + {"IPPROTO_TRUNK2", Const, 0}, + {"IPPROTO_TTP", Const, 0}, + {"IPPROTO_UDP", Const, 0}, + {"IPPROTO_UDPLITE", Const, 0}, + {"IPPROTO_VINES", Const, 0}, + {"IPPROTO_VISA", Const, 0}, + {"IPPROTO_VMTP", Const, 0}, + {"IPPROTO_VRRP", Const, 1}, + {"IPPROTO_WBEXPAK", Const, 0}, + {"IPPROTO_WBMON", Const, 0}, + {"IPPROTO_WSN", Const, 0}, + {"IPPROTO_XNET", Const, 0}, + {"IPPROTO_XTP", Const, 0}, + {"IPV6_2292DSTOPTS", Const, 0}, + {"IPV6_2292HOPLIMIT", Const, 0}, + {"IPV6_2292HOPOPTS", Const, 0}, + {"IPV6_2292NEXTHOP", Const, 0}, + {"IPV6_2292PKTINFO", Const, 0}, + {"IPV6_2292PKTOPTIONS", Const, 0}, + {"IPV6_2292RTHDR", Const, 0}, + {"IPV6_ADDRFORM", Const, 0}, + {"IPV6_ADD_MEMBERSHIP", Const, 0}, + {"IPV6_AUTHHDR", Const, 0}, + {"IPV6_AUTH_LEVEL", Const, 1}, + {"IPV6_AUTOFLOWLABEL", Const, 0}, + {"IPV6_BINDANY", Const, 0}, + {"IPV6_BINDV6ONLY", Const, 0}, + {"IPV6_BOUND_IF", Const, 0}, + {"IPV6_CHECKSUM", Const, 0}, + {"IPV6_DEFAULT_MULTICAST_HOPS", Const, 0}, + {"IPV6_DEFAULT_MULTICAST_LOOP", Const, 0}, + {"IPV6_DEFHLIM", Const, 0}, + {"IPV6_DONTFRAG", Const, 0}, + {"IPV6_DROP_MEMBERSHIP", Const, 0}, + {"IPV6_DSTOPTS", Const, 0}, + {"IPV6_ESP_NETWORK_LEVEL", Const, 1}, + {"IPV6_ESP_TRANS_LEVEL", Const, 1}, + {"IPV6_FAITH", Const, 0}, + {"IPV6_FLOWINFO_MASK", Const, 0}, + {"IPV6_FLOWLABEL_MASK", Const, 0}, + {"IPV6_FRAGTTL", Const, 0}, + {"IPV6_FW_ADD", Const, 0}, + {"IPV6_FW_DEL", Const, 0}, + {"IPV6_FW_FLUSH", Const, 0}, + {"IPV6_FW_GET", Const, 0}, + {"IPV6_FW_ZERO", Const, 0}, + {"IPV6_HLIMDEC", Const, 0}, + {"IPV6_HOPLIMIT", Const, 0}, + {"IPV6_HOPOPTS", Const, 0}, + {"IPV6_IPCOMP_LEVEL", Const, 1}, + {"IPV6_IPSEC_POLICY", Const, 0}, + {"IPV6_JOIN_ANYCAST", Const, 0}, + {"IPV6_JOIN_GROUP", Const, 0}, + {"IPV6_LEAVE_ANYCAST", Const, 0}, + {"IPV6_LEAVE_GROUP", Const, 0}, + {"IPV6_MAXHLIM", Const, 0}, + {"IPV6_MAXOPTHDR", Const, 0}, + {"IPV6_MAXPACKET", Const, 0}, + {"IPV6_MAX_GROUP_SRC_FILTER", Const, 0}, + {"IPV6_MAX_MEMBERSHIPS", Const, 0}, + {"IPV6_MAX_SOCK_SRC_FILTER", Const, 0}, + {"IPV6_MIN_MEMBERSHIPS", Const, 0}, + {"IPV6_MMTU", Const, 0}, + {"IPV6_MSFILTER", Const, 0}, + {"IPV6_MTU", Const, 0}, + {"IPV6_MTU_DISCOVER", Const, 0}, + {"IPV6_MULTICAST_HOPS", Const, 0}, + {"IPV6_MULTICAST_IF", Const, 0}, + {"IPV6_MULTICAST_LOOP", Const, 0}, + {"IPV6_NEXTHOP", Const, 0}, + {"IPV6_OPTIONS", Const, 1}, + {"IPV6_PATHMTU", Const, 0}, + {"IPV6_PIPEX", Const, 1}, + {"IPV6_PKTINFO", Const, 0}, + {"IPV6_PMTUDISC_DO", Const, 0}, + {"IPV6_PMTUDISC_DONT", Const, 0}, + {"IPV6_PMTUDISC_PROBE", Const, 0}, + {"IPV6_PMTUDISC_WANT", Const, 0}, + {"IPV6_PORTRANGE", Const, 0}, + {"IPV6_PORTRANGE_DEFAULT", Const, 0}, + {"IPV6_PORTRANGE_HIGH", Const, 0}, + {"IPV6_PORTRANGE_LOW", Const, 0}, + {"IPV6_PREFER_TEMPADDR", Const, 0}, + {"IPV6_RECVDSTOPTS", Const, 0}, + {"IPV6_RECVDSTPORT", Const, 3}, + {"IPV6_RECVERR", Const, 0}, + {"IPV6_RECVHOPLIMIT", Const, 0}, + {"IPV6_RECVHOPOPTS", Const, 0}, + {"IPV6_RECVPATHMTU", Const, 0}, + {"IPV6_RECVPKTINFO", Const, 0}, + {"IPV6_RECVRTHDR", Const, 0}, + {"IPV6_RECVTCLASS", Const, 0}, + {"IPV6_ROUTER_ALERT", Const, 0}, + {"IPV6_RTABLE", Const, 1}, + {"IPV6_RTHDR", Const, 0}, + {"IPV6_RTHDRDSTOPTS", Const, 0}, + {"IPV6_RTHDR_LOOSE", Const, 0}, + {"IPV6_RTHDR_STRICT", Const, 0}, + {"IPV6_RTHDR_TYPE_0", Const, 0}, + {"IPV6_RXDSTOPTS", Const, 0}, + {"IPV6_RXHOPOPTS", Const, 0}, + {"IPV6_SOCKOPT_RESERVED1", Const, 0}, + {"IPV6_TCLASS", Const, 0}, + {"IPV6_UNICAST_HOPS", Const, 0}, + {"IPV6_USE_MIN_MTU", Const, 0}, + {"IPV6_V6ONLY", Const, 0}, + {"IPV6_VERSION", Const, 0}, + {"IPV6_VERSION_MASK", Const, 0}, + {"IPV6_XFRM_POLICY", Const, 0}, + {"IP_ADD_MEMBERSHIP", Const, 0}, + {"IP_ADD_SOURCE_MEMBERSHIP", Const, 0}, + {"IP_AUTH_LEVEL", Const, 1}, + {"IP_BINDANY", Const, 0}, + {"IP_BLOCK_SOURCE", Const, 0}, + {"IP_BOUND_IF", Const, 0}, + {"IP_DEFAULT_MULTICAST_LOOP", Const, 0}, + {"IP_DEFAULT_MULTICAST_TTL", Const, 0}, + {"IP_DF", Const, 0}, + {"IP_DIVERTFL", Const, 3}, + {"IP_DONTFRAG", Const, 0}, + {"IP_DROP_MEMBERSHIP", Const, 0}, + {"IP_DROP_SOURCE_MEMBERSHIP", Const, 0}, + {"IP_DUMMYNET3", Const, 0}, + {"IP_DUMMYNET_CONFIGURE", Const, 0}, + {"IP_DUMMYNET_DEL", Const, 0}, + {"IP_DUMMYNET_FLUSH", Const, 0}, + {"IP_DUMMYNET_GET", Const, 0}, + {"IP_EF", Const, 1}, + {"IP_ERRORMTU", Const, 1}, + {"IP_ESP_NETWORK_LEVEL", Const, 1}, + {"IP_ESP_TRANS_LEVEL", Const, 1}, + {"IP_FAITH", Const, 0}, + {"IP_FREEBIND", Const, 0}, + {"IP_FW3", Const, 0}, + {"IP_FW_ADD", Const, 0}, + {"IP_FW_DEL", Const, 0}, + {"IP_FW_FLUSH", Const, 0}, + {"IP_FW_GET", Const, 0}, + {"IP_FW_NAT_CFG", Const, 0}, + {"IP_FW_NAT_DEL", Const, 0}, + {"IP_FW_NAT_GET_CONFIG", Const, 0}, + {"IP_FW_NAT_GET_LOG", Const, 0}, + {"IP_FW_RESETLOG", Const, 0}, + {"IP_FW_TABLE_ADD", Const, 0}, + {"IP_FW_TABLE_DEL", Const, 0}, + {"IP_FW_TABLE_FLUSH", Const, 0}, + {"IP_FW_TABLE_GETSIZE", Const, 0}, + {"IP_FW_TABLE_LIST", Const, 0}, + {"IP_FW_ZERO", Const, 0}, + {"IP_HDRINCL", Const, 0}, + {"IP_IPCOMP_LEVEL", Const, 1}, + {"IP_IPSECFLOWINFO", Const, 1}, + {"IP_IPSEC_LOCAL_AUTH", Const, 1}, + {"IP_IPSEC_LOCAL_CRED", Const, 1}, + {"IP_IPSEC_LOCAL_ID", Const, 1}, + {"IP_IPSEC_POLICY", Const, 0}, + {"IP_IPSEC_REMOTE_AUTH", Const, 1}, + {"IP_IPSEC_REMOTE_CRED", Const, 1}, + {"IP_IPSEC_REMOTE_ID", Const, 1}, + {"IP_MAXPACKET", Const, 0}, + {"IP_MAX_GROUP_SRC_FILTER", Const, 0}, + {"IP_MAX_MEMBERSHIPS", Const, 0}, + {"IP_MAX_SOCK_MUTE_FILTER", Const, 0}, + {"IP_MAX_SOCK_SRC_FILTER", Const, 0}, + {"IP_MAX_SOURCE_FILTER", Const, 0}, + {"IP_MF", Const, 0}, + {"IP_MINFRAGSIZE", Const, 1}, + {"IP_MINTTL", Const, 0}, + {"IP_MIN_MEMBERSHIPS", Const, 0}, + {"IP_MSFILTER", Const, 0}, + {"IP_MSS", Const, 0}, + {"IP_MTU", Const, 0}, + {"IP_MTU_DISCOVER", Const, 0}, + {"IP_MULTICAST_IF", Const, 0}, + {"IP_MULTICAST_IFINDEX", Const, 0}, + {"IP_MULTICAST_LOOP", Const, 0}, + {"IP_MULTICAST_TTL", Const, 0}, + {"IP_MULTICAST_VIF", Const, 0}, + {"IP_NAT__XXX", Const, 0}, + {"IP_OFFMASK", Const, 0}, + {"IP_OLD_FW_ADD", Const, 0}, + {"IP_OLD_FW_DEL", Const, 0}, + {"IP_OLD_FW_FLUSH", Const, 0}, + {"IP_OLD_FW_GET", Const, 0}, + {"IP_OLD_FW_RESETLOG", Const, 0}, + {"IP_OLD_FW_ZERO", Const, 0}, + {"IP_ONESBCAST", Const, 0}, + {"IP_OPTIONS", Const, 0}, + {"IP_ORIGDSTADDR", Const, 0}, + {"IP_PASSSEC", Const, 0}, + {"IP_PIPEX", Const, 1}, + {"IP_PKTINFO", Const, 0}, + {"IP_PKTOPTIONS", Const, 0}, + {"IP_PMTUDISC", Const, 0}, + {"IP_PMTUDISC_DO", Const, 0}, + {"IP_PMTUDISC_DONT", Const, 0}, + {"IP_PMTUDISC_PROBE", Const, 0}, + {"IP_PMTUDISC_WANT", Const, 0}, + {"IP_PORTRANGE", Const, 0}, + {"IP_PORTRANGE_DEFAULT", Const, 0}, + {"IP_PORTRANGE_HIGH", Const, 0}, + {"IP_PORTRANGE_LOW", Const, 0}, + {"IP_RECVDSTADDR", Const, 0}, + {"IP_RECVDSTPORT", Const, 1}, + {"IP_RECVERR", Const, 0}, + {"IP_RECVIF", Const, 0}, + {"IP_RECVOPTS", Const, 0}, + {"IP_RECVORIGDSTADDR", Const, 0}, + {"IP_RECVPKTINFO", Const, 0}, + {"IP_RECVRETOPTS", Const, 0}, + {"IP_RECVRTABLE", Const, 1}, + {"IP_RECVTOS", Const, 0}, + {"IP_RECVTTL", Const, 0}, + {"IP_RETOPTS", Const, 0}, + {"IP_RF", Const, 0}, + {"IP_ROUTER_ALERT", Const, 0}, + {"IP_RSVP_OFF", Const, 0}, + {"IP_RSVP_ON", Const, 0}, + {"IP_RSVP_VIF_OFF", Const, 0}, + {"IP_RSVP_VIF_ON", Const, 0}, + {"IP_RTABLE", Const, 1}, + {"IP_SENDSRCADDR", Const, 0}, + {"IP_STRIPHDR", Const, 0}, + {"IP_TOS", Const, 0}, + {"IP_TRAFFIC_MGT_BACKGROUND", Const, 0}, + {"IP_TRANSPARENT", Const, 0}, + {"IP_TTL", Const, 0}, + {"IP_UNBLOCK_SOURCE", Const, 0}, + {"IP_XFRM_POLICY", Const, 0}, + {"IPv6MTUInfo", Type, 2}, + {"IPv6MTUInfo.Addr", Field, 2}, + {"IPv6MTUInfo.Mtu", Field, 2}, + {"IPv6Mreq", Type, 0}, + {"IPv6Mreq.Interface", Field, 0}, + {"IPv6Mreq.Multiaddr", Field, 0}, + {"ISIG", Const, 0}, + {"ISTRIP", Const, 0}, + {"IUCLC", Const, 0}, + {"IUTF8", Const, 0}, + {"IXANY", Const, 0}, + {"IXOFF", Const, 0}, + {"IXON", Const, 0}, + {"IfAddrmsg", Type, 0}, + {"IfAddrmsg.Family", Field, 0}, + {"IfAddrmsg.Flags", Field, 0}, + {"IfAddrmsg.Index", Field, 0}, + {"IfAddrmsg.Prefixlen", Field, 0}, + {"IfAddrmsg.Scope", Field, 0}, + {"IfAnnounceMsghdr", Type, 1}, + {"IfAnnounceMsghdr.Hdrlen", Field, 2}, + {"IfAnnounceMsghdr.Index", Field, 1}, + {"IfAnnounceMsghdr.Msglen", Field, 1}, + {"IfAnnounceMsghdr.Name", Field, 1}, + {"IfAnnounceMsghdr.Type", Field, 1}, + {"IfAnnounceMsghdr.Version", Field, 1}, + {"IfAnnounceMsghdr.What", Field, 1}, + {"IfData", Type, 0}, + {"IfData.Addrlen", Field, 0}, + {"IfData.Baudrate", Field, 0}, + {"IfData.Capabilities", Field, 2}, + {"IfData.Collisions", Field, 0}, + {"IfData.Datalen", Field, 0}, + {"IfData.Epoch", Field, 0}, + {"IfData.Hdrlen", Field, 0}, + {"IfData.Hwassist", Field, 0}, + {"IfData.Ibytes", Field, 0}, + {"IfData.Ierrors", Field, 0}, + {"IfData.Imcasts", Field, 0}, + {"IfData.Ipackets", Field, 0}, + {"IfData.Iqdrops", Field, 0}, + {"IfData.Lastchange", Field, 0}, + {"IfData.Link_state", Field, 0}, + {"IfData.Mclpool", Field, 2}, + {"IfData.Metric", Field, 0}, + {"IfData.Mtu", Field, 0}, + {"IfData.Noproto", Field, 0}, + {"IfData.Obytes", Field, 0}, + {"IfData.Oerrors", Field, 0}, + {"IfData.Omcasts", Field, 0}, + {"IfData.Opackets", Field, 0}, + {"IfData.Pad", Field, 2}, + {"IfData.Pad_cgo_0", Field, 2}, + {"IfData.Pad_cgo_1", Field, 2}, + {"IfData.Physical", Field, 0}, + {"IfData.Recvquota", Field, 0}, + {"IfData.Recvtiming", Field, 0}, + {"IfData.Reserved1", Field, 0}, + {"IfData.Reserved2", Field, 0}, + {"IfData.Spare_char1", Field, 0}, + {"IfData.Spare_char2", Field, 0}, + {"IfData.Type", Field, 0}, + {"IfData.Typelen", Field, 0}, + {"IfData.Unused1", Field, 0}, + {"IfData.Unused2", Field, 0}, + {"IfData.Xmitquota", Field, 0}, + {"IfData.Xmittiming", Field, 0}, + {"IfInfomsg", Type, 0}, + {"IfInfomsg.Change", Field, 0}, + {"IfInfomsg.Family", Field, 0}, + {"IfInfomsg.Flags", Field, 0}, + {"IfInfomsg.Index", Field, 0}, + {"IfInfomsg.Type", Field, 0}, + {"IfInfomsg.X__ifi_pad", Field, 0}, + {"IfMsghdr", Type, 0}, + {"IfMsghdr.Addrs", Field, 0}, + {"IfMsghdr.Data", Field, 0}, + {"IfMsghdr.Flags", Field, 0}, + {"IfMsghdr.Hdrlen", Field, 2}, + {"IfMsghdr.Index", Field, 0}, + {"IfMsghdr.Msglen", Field, 0}, + {"IfMsghdr.Pad1", Field, 2}, + {"IfMsghdr.Pad2", Field, 2}, + {"IfMsghdr.Pad_cgo_0", Field, 0}, + {"IfMsghdr.Pad_cgo_1", Field, 2}, + {"IfMsghdr.Tableid", Field, 2}, + {"IfMsghdr.Type", Field, 0}, + {"IfMsghdr.Version", Field, 0}, + {"IfMsghdr.Xflags", Field, 2}, + {"IfaMsghdr", Type, 0}, + {"IfaMsghdr.Addrs", Field, 0}, + {"IfaMsghdr.Flags", Field, 0}, + {"IfaMsghdr.Hdrlen", Field, 2}, + {"IfaMsghdr.Index", Field, 0}, + {"IfaMsghdr.Metric", Field, 0}, + {"IfaMsghdr.Msglen", Field, 0}, + {"IfaMsghdr.Pad1", Field, 2}, + {"IfaMsghdr.Pad2", Field, 2}, + {"IfaMsghdr.Pad_cgo_0", Field, 0}, + {"IfaMsghdr.Tableid", Field, 2}, + {"IfaMsghdr.Type", Field, 0}, + {"IfaMsghdr.Version", Field, 0}, + {"IfmaMsghdr", Type, 0}, + {"IfmaMsghdr.Addrs", Field, 0}, + {"IfmaMsghdr.Flags", Field, 0}, + {"IfmaMsghdr.Index", Field, 0}, + {"IfmaMsghdr.Msglen", Field, 0}, + {"IfmaMsghdr.Pad_cgo_0", Field, 0}, + {"IfmaMsghdr.Type", Field, 0}, + {"IfmaMsghdr.Version", Field, 0}, + {"IfmaMsghdr2", Type, 0}, + {"IfmaMsghdr2.Addrs", Field, 0}, + {"IfmaMsghdr2.Flags", Field, 0}, + {"IfmaMsghdr2.Index", Field, 0}, + {"IfmaMsghdr2.Msglen", Field, 0}, + {"IfmaMsghdr2.Pad_cgo_0", Field, 0}, + {"IfmaMsghdr2.Refcount", Field, 0}, + {"IfmaMsghdr2.Type", Field, 0}, + {"IfmaMsghdr2.Version", Field, 0}, + {"ImplementsGetwd", Const, 0}, + {"Inet4Pktinfo", Type, 0}, + {"Inet4Pktinfo.Addr", Field, 0}, + {"Inet4Pktinfo.Ifindex", Field, 0}, + {"Inet4Pktinfo.Spec_dst", Field, 0}, + {"Inet6Pktinfo", Type, 0}, + {"Inet6Pktinfo.Addr", Field, 0}, + {"Inet6Pktinfo.Ifindex", Field, 0}, + {"InotifyAddWatch", Func, 0}, + {"InotifyEvent", Type, 0}, + {"InotifyEvent.Cookie", Field, 0}, + {"InotifyEvent.Len", Field, 0}, + {"InotifyEvent.Mask", Field, 0}, + {"InotifyEvent.Name", Field, 0}, + {"InotifyEvent.Wd", Field, 0}, + {"InotifyInit", Func, 0}, + {"InotifyInit1", Func, 0}, + {"InotifyRmWatch", Func, 0}, + {"InterfaceAddrMessage", Type, 0}, + {"InterfaceAddrMessage.Data", Field, 0}, + {"InterfaceAddrMessage.Header", Field, 0}, + {"InterfaceAnnounceMessage", Type, 1}, + {"InterfaceAnnounceMessage.Header", Field, 1}, + {"InterfaceInfo", Type, 0}, + {"InterfaceInfo.Address", Field, 0}, + {"InterfaceInfo.BroadcastAddress", Field, 0}, + {"InterfaceInfo.Flags", Field, 0}, + {"InterfaceInfo.Netmask", Field, 0}, + {"InterfaceMessage", Type, 0}, + {"InterfaceMessage.Data", Field, 0}, + {"InterfaceMessage.Header", Field, 0}, + {"InterfaceMulticastAddrMessage", Type, 0}, + {"InterfaceMulticastAddrMessage.Data", Field, 0}, + {"InterfaceMulticastAddrMessage.Header", Field, 0}, + {"InvalidHandle", Const, 0}, + {"Ioperm", Func, 0}, + {"Iopl", Func, 0}, + {"Iovec", Type, 0}, + {"Iovec.Base", Field, 0}, + {"Iovec.Len", Field, 0}, + {"IpAdapterInfo", Type, 0}, + {"IpAdapterInfo.AdapterName", Field, 0}, + {"IpAdapterInfo.Address", Field, 0}, + {"IpAdapterInfo.AddressLength", Field, 0}, + {"IpAdapterInfo.ComboIndex", Field, 0}, + {"IpAdapterInfo.CurrentIpAddress", Field, 0}, + {"IpAdapterInfo.Description", Field, 0}, + {"IpAdapterInfo.DhcpEnabled", Field, 0}, + {"IpAdapterInfo.DhcpServer", Field, 0}, + {"IpAdapterInfo.GatewayList", Field, 0}, + {"IpAdapterInfo.HaveWins", Field, 0}, + {"IpAdapterInfo.Index", Field, 0}, + {"IpAdapterInfo.IpAddressList", Field, 0}, + {"IpAdapterInfo.LeaseExpires", Field, 0}, + {"IpAdapterInfo.LeaseObtained", Field, 0}, + {"IpAdapterInfo.Next", Field, 0}, + {"IpAdapterInfo.PrimaryWinsServer", Field, 0}, + {"IpAdapterInfo.SecondaryWinsServer", Field, 0}, + {"IpAdapterInfo.Type", Field, 0}, + {"IpAddrString", Type, 0}, + {"IpAddrString.Context", Field, 0}, + {"IpAddrString.IpAddress", Field, 0}, + {"IpAddrString.IpMask", Field, 0}, + {"IpAddrString.Next", Field, 0}, + {"IpAddressString", Type, 0}, + {"IpAddressString.String", Field, 0}, + {"IpMaskString", Type, 0}, + {"IpMaskString.String", Field, 2}, + {"Issetugid", Func, 0}, + {"KEY_ALL_ACCESS", Const, 0}, + {"KEY_CREATE_LINK", Const, 0}, + {"KEY_CREATE_SUB_KEY", Const, 0}, + {"KEY_ENUMERATE_SUB_KEYS", Const, 0}, + {"KEY_EXECUTE", Const, 0}, + {"KEY_NOTIFY", Const, 0}, + {"KEY_QUERY_VALUE", Const, 0}, + {"KEY_READ", Const, 0}, + {"KEY_SET_VALUE", Const, 0}, + {"KEY_WOW64_32KEY", Const, 0}, + {"KEY_WOW64_64KEY", Const, 0}, + {"KEY_WRITE", Const, 0}, + {"Kevent", Func, 0}, + {"Kevent_t", Type, 0}, + {"Kevent_t.Data", Field, 0}, + {"Kevent_t.Fflags", Field, 0}, + {"Kevent_t.Filter", Field, 0}, + {"Kevent_t.Flags", Field, 0}, + {"Kevent_t.Ident", Field, 0}, + {"Kevent_t.Pad_cgo_0", Field, 2}, + {"Kevent_t.Udata", Field, 0}, + {"Kill", Func, 0}, + {"Klogctl", Func, 0}, + {"Kqueue", Func, 0}, + {"LANG_ENGLISH", Const, 0}, + {"LAYERED_PROTOCOL", Const, 2}, + {"LCNT_OVERLOAD_FLUSH", Const, 1}, + {"LINUX_REBOOT_CMD_CAD_OFF", Const, 0}, + {"LINUX_REBOOT_CMD_CAD_ON", Const, 0}, + {"LINUX_REBOOT_CMD_HALT", Const, 0}, + {"LINUX_REBOOT_CMD_KEXEC", Const, 0}, + {"LINUX_REBOOT_CMD_POWER_OFF", Const, 0}, + {"LINUX_REBOOT_CMD_RESTART", Const, 0}, + {"LINUX_REBOOT_CMD_RESTART2", Const, 0}, + {"LINUX_REBOOT_CMD_SW_SUSPEND", Const, 0}, + {"LINUX_REBOOT_MAGIC1", Const, 0}, + {"LINUX_REBOOT_MAGIC2", Const, 0}, + {"LOCK_EX", Const, 0}, + {"LOCK_NB", Const, 0}, + {"LOCK_SH", Const, 0}, + {"LOCK_UN", Const, 0}, + {"LazyDLL", Type, 0}, + {"LazyDLL.Name", Field, 0}, + {"LazyProc", Type, 0}, + {"LazyProc.Name", Field, 0}, + {"Lchown", Func, 0}, + {"Linger", Type, 0}, + {"Linger.Linger", Field, 0}, + {"Linger.Onoff", Field, 0}, + {"Link", Func, 0}, + {"Listen", Func, 0}, + {"Listxattr", Func, 1}, + {"LoadCancelIoEx", Func, 1}, + {"LoadConnectEx", Func, 1}, + {"LoadCreateSymbolicLink", Func, 4}, + {"LoadDLL", Func, 0}, + {"LoadGetAddrInfo", Func, 1}, + {"LoadLibrary", Func, 0}, + {"LoadSetFileCompletionNotificationModes", Func, 2}, + {"LocalFree", Func, 0}, + {"Log2phys_t", Type, 0}, + {"Log2phys_t.Contigbytes", Field, 0}, + {"Log2phys_t.Devoffset", Field, 0}, + {"Log2phys_t.Flags", Field, 0}, + {"LookupAccountName", Func, 0}, + {"LookupAccountSid", Func, 0}, + {"LookupSID", Func, 0}, + {"LsfJump", Func, 0}, + {"LsfSocket", Func, 0}, + {"LsfStmt", Func, 0}, + {"Lstat", Func, 0}, + {"MADV_AUTOSYNC", Const, 1}, + {"MADV_CAN_REUSE", Const, 0}, + {"MADV_CORE", Const, 1}, + {"MADV_DOFORK", Const, 0}, + {"MADV_DONTFORK", Const, 0}, + {"MADV_DONTNEED", Const, 0}, + {"MADV_FREE", Const, 0}, + {"MADV_FREE_REUSABLE", Const, 0}, + {"MADV_FREE_REUSE", Const, 0}, + {"MADV_HUGEPAGE", Const, 0}, + {"MADV_HWPOISON", Const, 0}, + {"MADV_MERGEABLE", Const, 0}, + {"MADV_NOCORE", Const, 1}, + {"MADV_NOHUGEPAGE", Const, 0}, + {"MADV_NORMAL", Const, 0}, + {"MADV_NOSYNC", Const, 1}, + {"MADV_PROTECT", Const, 1}, + {"MADV_RANDOM", Const, 0}, + {"MADV_REMOVE", Const, 0}, + {"MADV_SEQUENTIAL", Const, 0}, + {"MADV_SPACEAVAIL", Const, 3}, + {"MADV_UNMERGEABLE", Const, 0}, + {"MADV_WILLNEED", Const, 0}, + {"MADV_ZERO_WIRED_PAGES", Const, 0}, + {"MAP_32BIT", Const, 0}, + {"MAP_ALIGNED_SUPER", Const, 3}, + {"MAP_ALIGNMENT_16MB", Const, 3}, + {"MAP_ALIGNMENT_1TB", Const, 3}, + {"MAP_ALIGNMENT_256TB", Const, 3}, + {"MAP_ALIGNMENT_4GB", Const, 3}, + {"MAP_ALIGNMENT_64KB", Const, 3}, + {"MAP_ALIGNMENT_64PB", Const, 3}, + {"MAP_ALIGNMENT_MASK", Const, 3}, + {"MAP_ALIGNMENT_SHIFT", Const, 3}, + {"MAP_ANON", Const, 0}, + {"MAP_ANONYMOUS", Const, 0}, + {"MAP_COPY", Const, 0}, + {"MAP_DENYWRITE", Const, 0}, + {"MAP_EXECUTABLE", Const, 0}, + {"MAP_FILE", Const, 0}, + {"MAP_FIXED", Const, 0}, + {"MAP_FLAGMASK", Const, 3}, + {"MAP_GROWSDOWN", Const, 0}, + {"MAP_HASSEMAPHORE", Const, 0}, + {"MAP_HUGETLB", Const, 0}, + {"MAP_INHERIT", Const, 3}, + {"MAP_INHERIT_COPY", Const, 3}, + {"MAP_INHERIT_DEFAULT", Const, 3}, + {"MAP_INHERIT_DONATE_COPY", Const, 3}, + {"MAP_INHERIT_NONE", Const, 3}, + {"MAP_INHERIT_SHARE", Const, 3}, + {"MAP_JIT", Const, 0}, + {"MAP_LOCKED", Const, 0}, + {"MAP_NOCACHE", Const, 0}, + {"MAP_NOCORE", Const, 1}, + {"MAP_NOEXTEND", Const, 0}, + {"MAP_NONBLOCK", Const, 0}, + {"MAP_NORESERVE", Const, 0}, + {"MAP_NOSYNC", Const, 1}, + {"MAP_POPULATE", Const, 0}, + {"MAP_PREFAULT_READ", Const, 1}, + {"MAP_PRIVATE", Const, 0}, + {"MAP_RENAME", Const, 0}, + {"MAP_RESERVED0080", Const, 0}, + {"MAP_RESERVED0100", Const, 1}, + {"MAP_SHARED", Const, 0}, + {"MAP_STACK", Const, 0}, + {"MAP_TRYFIXED", Const, 3}, + {"MAP_TYPE", Const, 0}, + {"MAP_WIRED", Const, 3}, + {"MAXIMUM_REPARSE_DATA_BUFFER_SIZE", Const, 4}, + {"MAXLEN_IFDESCR", Const, 0}, + {"MAXLEN_PHYSADDR", Const, 0}, + {"MAX_ADAPTER_ADDRESS_LENGTH", Const, 0}, + {"MAX_ADAPTER_DESCRIPTION_LENGTH", Const, 0}, + {"MAX_ADAPTER_NAME_LENGTH", Const, 0}, + {"MAX_COMPUTERNAME_LENGTH", Const, 0}, + {"MAX_INTERFACE_NAME_LEN", Const, 0}, + {"MAX_LONG_PATH", Const, 0}, + {"MAX_PATH", Const, 0}, + {"MAX_PROTOCOL_CHAIN", Const, 2}, + {"MCL_CURRENT", Const, 0}, + {"MCL_FUTURE", Const, 0}, + {"MNT_DETACH", Const, 0}, + {"MNT_EXPIRE", Const, 0}, + {"MNT_FORCE", Const, 0}, + {"MSG_BCAST", Const, 1}, + {"MSG_CMSG_CLOEXEC", Const, 0}, + {"MSG_COMPAT", Const, 0}, + {"MSG_CONFIRM", Const, 0}, + {"MSG_CONTROLMBUF", Const, 1}, + {"MSG_CTRUNC", Const, 0}, + {"MSG_DONTROUTE", Const, 0}, + {"MSG_DONTWAIT", Const, 0}, + {"MSG_EOF", Const, 0}, + {"MSG_EOR", Const, 0}, + {"MSG_ERRQUEUE", Const, 0}, + {"MSG_FASTOPEN", Const, 1}, + {"MSG_FIN", Const, 0}, + {"MSG_FLUSH", Const, 0}, + {"MSG_HAVEMORE", Const, 0}, + {"MSG_HOLD", Const, 0}, + {"MSG_IOVUSRSPACE", Const, 1}, + {"MSG_LENUSRSPACE", Const, 1}, + {"MSG_MCAST", Const, 1}, + {"MSG_MORE", Const, 0}, + {"MSG_NAMEMBUF", Const, 1}, + {"MSG_NBIO", Const, 0}, + {"MSG_NEEDSA", Const, 0}, + {"MSG_NOSIGNAL", Const, 0}, + {"MSG_NOTIFICATION", Const, 0}, + {"MSG_OOB", Const, 0}, + {"MSG_PEEK", Const, 0}, + {"MSG_PROXY", Const, 0}, + {"MSG_RCVMORE", Const, 0}, + {"MSG_RST", Const, 0}, + {"MSG_SEND", Const, 0}, + {"MSG_SYN", Const, 0}, + {"MSG_TRUNC", Const, 0}, + {"MSG_TRYHARD", Const, 0}, + {"MSG_USERFLAGS", Const, 1}, + {"MSG_WAITALL", Const, 0}, + {"MSG_WAITFORONE", Const, 0}, + {"MSG_WAITSTREAM", Const, 0}, + {"MS_ACTIVE", Const, 0}, + {"MS_ASYNC", Const, 0}, + {"MS_BIND", Const, 0}, + {"MS_DEACTIVATE", Const, 0}, + {"MS_DIRSYNC", Const, 0}, + {"MS_INVALIDATE", Const, 0}, + {"MS_I_VERSION", Const, 0}, + {"MS_KERNMOUNT", Const, 0}, + {"MS_KILLPAGES", Const, 0}, + {"MS_MANDLOCK", Const, 0}, + {"MS_MGC_MSK", Const, 0}, + {"MS_MGC_VAL", Const, 0}, + {"MS_MOVE", Const, 0}, + {"MS_NOATIME", Const, 0}, + {"MS_NODEV", Const, 0}, + {"MS_NODIRATIME", Const, 0}, + {"MS_NOEXEC", Const, 0}, + {"MS_NOSUID", Const, 0}, + {"MS_NOUSER", Const, 0}, + {"MS_POSIXACL", Const, 0}, + {"MS_PRIVATE", Const, 0}, + {"MS_RDONLY", Const, 0}, + {"MS_REC", Const, 0}, + {"MS_RELATIME", Const, 0}, + {"MS_REMOUNT", Const, 0}, + {"MS_RMT_MASK", Const, 0}, + {"MS_SHARED", Const, 0}, + {"MS_SILENT", Const, 0}, + {"MS_SLAVE", Const, 0}, + {"MS_STRICTATIME", Const, 0}, + {"MS_SYNC", Const, 0}, + {"MS_SYNCHRONOUS", Const, 0}, + {"MS_UNBINDABLE", Const, 0}, + {"Madvise", Func, 0}, + {"MapViewOfFile", Func, 0}, + {"MaxTokenInfoClass", Const, 0}, + {"Mclpool", Type, 2}, + {"Mclpool.Alive", Field, 2}, + {"Mclpool.Cwm", Field, 2}, + {"Mclpool.Grown", Field, 2}, + {"Mclpool.Hwm", Field, 2}, + {"Mclpool.Lwm", Field, 2}, + {"MibIfRow", Type, 0}, + {"MibIfRow.AdminStatus", Field, 0}, + {"MibIfRow.Descr", Field, 0}, + {"MibIfRow.DescrLen", Field, 0}, + {"MibIfRow.InDiscards", Field, 0}, + {"MibIfRow.InErrors", Field, 0}, + {"MibIfRow.InNUcastPkts", Field, 0}, + {"MibIfRow.InOctets", Field, 0}, + {"MibIfRow.InUcastPkts", Field, 0}, + {"MibIfRow.InUnknownProtos", Field, 0}, + {"MibIfRow.Index", Field, 0}, + {"MibIfRow.LastChange", Field, 0}, + {"MibIfRow.Mtu", Field, 0}, + {"MibIfRow.Name", Field, 0}, + {"MibIfRow.OperStatus", Field, 0}, + {"MibIfRow.OutDiscards", Field, 0}, + {"MibIfRow.OutErrors", Field, 0}, + {"MibIfRow.OutNUcastPkts", Field, 0}, + {"MibIfRow.OutOctets", Field, 0}, + {"MibIfRow.OutQLen", Field, 0}, + {"MibIfRow.OutUcastPkts", Field, 0}, + {"MibIfRow.PhysAddr", Field, 0}, + {"MibIfRow.PhysAddrLen", Field, 0}, + {"MibIfRow.Speed", Field, 0}, + {"MibIfRow.Type", Field, 0}, + {"Mkdir", Func, 0}, + {"Mkdirat", Func, 0}, + {"Mkfifo", Func, 0}, + {"Mknod", Func, 0}, + {"Mknodat", Func, 0}, + {"Mlock", Func, 0}, + {"Mlockall", Func, 0}, + {"Mmap", Func, 0}, + {"Mount", Func, 0}, + {"MoveFile", Func, 0}, + {"Mprotect", Func, 0}, + {"Msghdr", Type, 0}, + {"Msghdr.Control", Field, 0}, + {"Msghdr.Controllen", Field, 0}, + {"Msghdr.Flags", Field, 0}, + {"Msghdr.Iov", Field, 0}, + {"Msghdr.Iovlen", Field, 0}, + {"Msghdr.Name", Field, 0}, + {"Msghdr.Namelen", Field, 0}, + {"Msghdr.Pad_cgo_0", Field, 0}, + {"Msghdr.Pad_cgo_1", Field, 0}, + {"Munlock", Func, 0}, + {"Munlockall", Func, 0}, + {"Munmap", Func, 0}, + {"MustLoadDLL", Func, 0}, + {"NAME_MAX", Const, 0}, + {"NETLINK_ADD_MEMBERSHIP", Const, 0}, + {"NETLINK_AUDIT", Const, 0}, + {"NETLINK_BROADCAST_ERROR", Const, 0}, + {"NETLINK_CONNECTOR", Const, 0}, + {"NETLINK_DNRTMSG", Const, 0}, + {"NETLINK_DROP_MEMBERSHIP", Const, 0}, + {"NETLINK_ECRYPTFS", Const, 0}, + {"NETLINK_FIB_LOOKUP", Const, 0}, + {"NETLINK_FIREWALL", Const, 0}, + {"NETLINK_GENERIC", Const, 0}, + {"NETLINK_INET_DIAG", Const, 0}, + {"NETLINK_IP6_FW", Const, 0}, + {"NETLINK_ISCSI", Const, 0}, + {"NETLINK_KOBJECT_UEVENT", Const, 0}, + {"NETLINK_NETFILTER", Const, 0}, + {"NETLINK_NFLOG", Const, 0}, + {"NETLINK_NO_ENOBUFS", Const, 0}, + {"NETLINK_PKTINFO", Const, 0}, + {"NETLINK_RDMA", Const, 0}, + {"NETLINK_ROUTE", Const, 0}, + {"NETLINK_SCSITRANSPORT", Const, 0}, + {"NETLINK_SELINUX", Const, 0}, + {"NETLINK_UNUSED", Const, 0}, + {"NETLINK_USERSOCK", Const, 0}, + {"NETLINK_XFRM", Const, 0}, + {"NET_RT_DUMP", Const, 0}, + {"NET_RT_DUMP2", Const, 0}, + {"NET_RT_FLAGS", Const, 0}, + {"NET_RT_IFLIST", Const, 0}, + {"NET_RT_IFLIST2", Const, 0}, + {"NET_RT_IFLISTL", Const, 1}, + {"NET_RT_IFMALIST", Const, 0}, + {"NET_RT_MAXID", Const, 0}, + {"NET_RT_OIFLIST", Const, 1}, + {"NET_RT_OOIFLIST", Const, 1}, + {"NET_RT_STAT", Const, 0}, + {"NET_RT_STATS", Const, 1}, + {"NET_RT_TABLE", Const, 1}, + {"NET_RT_TRASH", Const, 0}, + {"NLA_ALIGNTO", Const, 0}, + {"NLA_F_NESTED", Const, 0}, + {"NLA_F_NET_BYTEORDER", Const, 0}, + {"NLA_HDRLEN", Const, 0}, + {"NLMSG_ALIGNTO", Const, 0}, + {"NLMSG_DONE", Const, 0}, + {"NLMSG_ERROR", Const, 0}, + {"NLMSG_HDRLEN", Const, 0}, + {"NLMSG_MIN_TYPE", Const, 0}, + {"NLMSG_NOOP", Const, 0}, + {"NLMSG_OVERRUN", Const, 0}, + {"NLM_F_ACK", Const, 0}, + {"NLM_F_APPEND", Const, 0}, + {"NLM_F_ATOMIC", Const, 0}, + {"NLM_F_CREATE", Const, 0}, + {"NLM_F_DUMP", Const, 0}, + {"NLM_F_ECHO", Const, 0}, + {"NLM_F_EXCL", Const, 0}, + {"NLM_F_MATCH", Const, 0}, + {"NLM_F_MULTI", Const, 0}, + {"NLM_F_REPLACE", Const, 0}, + {"NLM_F_REQUEST", Const, 0}, + {"NLM_F_ROOT", Const, 0}, + {"NOFLSH", Const, 0}, + {"NOTE_ABSOLUTE", Const, 0}, + {"NOTE_ATTRIB", Const, 0}, + {"NOTE_BACKGROUND", Const, 16}, + {"NOTE_CHILD", Const, 0}, + {"NOTE_CRITICAL", Const, 16}, + {"NOTE_DELETE", Const, 0}, + {"NOTE_EOF", Const, 1}, + {"NOTE_EXEC", Const, 0}, + {"NOTE_EXIT", Const, 0}, + {"NOTE_EXITSTATUS", Const, 0}, + {"NOTE_EXIT_CSERROR", Const, 16}, + {"NOTE_EXIT_DECRYPTFAIL", Const, 16}, + {"NOTE_EXIT_DETAIL", Const, 16}, + {"NOTE_EXIT_DETAIL_MASK", Const, 16}, + {"NOTE_EXIT_MEMORY", Const, 16}, + {"NOTE_EXIT_REPARENTED", Const, 16}, + {"NOTE_EXTEND", Const, 0}, + {"NOTE_FFAND", Const, 0}, + {"NOTE_FFCOPY", Const, 0}, + {"NOTE_FFCTRLMASK", Const, 0}, + {"NOTE_FFLAGSMASK", Const, 0}, + {"NOTE_FFNOP", Const, 0}, + {"NOTE_FFOR", Const, 0}, + {"NOTE_FORK", Const, 0}, + {"NOTE_LEEWAY", Const, 16}, + {"NOTE_LINK", Const, 0}, + {"NOTE_LOWAT", Const, 0}, + {"NOTE_NONE", Const, 0}, + {"NOTE_NSECONDS", Const, 0}, + {"NOTE_PCTRLMASK", Const, 0}, + {"NOTE_PDATAMASK", Const, 0}, + {"NOTE_REAP", Const, 0}, + {"NOTE_RENAME", Const, 0}, + {"NOTE_RESOURCEEND", Const, 0}, + {"NOTE_REVOKE", Const, 0}, + {"NOTE_SECONDS", Const, 0}, + {"NOTE_SIGNAL", Const, 0}, + {"NOTE_TRACK", Const, 0}, + {"NOTE_TRACKERR", Const, 0}, + {"NOTE_TRIGGER", Const, 0}, + {"NOTE_TRUNCATE", Const, 1}, + {"NOTE_USECONDS", Const, 0}, + {"NOTE_VM_ERROR", Const, 0}, + {"NOTE_VM_PRESSURE", Const, 0}, + {"NOTE_VM_PRESSURE_SUDDEN_TERMINATE", Const, 0}, + {"NOTE_VM_PRESSURE_TERMINATE", Const, 0}, + {"NOTE_WRITE", Const, 0}, + {"NameCanonical", Const, 0}, + {"NameCanonicalEx", Const, 0}, + {"NameDisplay", Const, 0}, + {"NameDnsDomain", Const, 0}, + {"NameFullyQualifiedDN", Const, 0}, + {"NameSamCompatible", Const, 0}, + {"NameServicePrincipal", Const, 0}, + {"NameUniqueId", Const, 0}, + {"NameUnknown", Const, 0}, + {"NameUserPrincipal", Const, 0}, + {"Nanosleep", Func, 0}, + {"NetApiBufferFree", Func, 0}, + {"NetGetJoinInformation", Func, 2}, + {"NetSetupDomainName", Const, 2}, + {"NetSetupUnjoined", Const, 2}, + {"NetSetupUnknownStatus", Const, 2}, + {"NetSetupWorkgroupName", Const, 2}, + {"NetUserGetInfo", Func, 0}, + {"NetlinkMessage", Type, 0}, + {"NetlinkMessage.Data", Field, 0}, + {"NetlinkMessage.Header", Field, 0}, + {"NetlinkRIB", Func, 0}, + {"NetlinkRouteAttr", Type, 0}, + {"NetlinkRouteAttr.Attr", Field, 0}, + {"NetlinkRouteAttr.Value", Field, 0}, + {"NetlinkRouteRequest", Type, 0}, + {"NetlinkRouteRequest.Data", Field, 0}, + {"NetlinkRouteRequest.Header", Field, 0}, + {"NewCallback", Func, 0}, + {"NewCallbackCDecl", Func, 3}, + {"NewLazyDLL", Func, 0}, + {"NlAttr", Type, 0}, + {"NlAttr.Len", Field, 0}, + {"NlAttr.Type", Field, 0}, + {"NlMsgerr", Type, 0}, + {"NlMsgerr.Error", Field, 0}, + {"NlMsgerr.Msg", Field, 0}, + {"NlMsghdr", Type, 0}, + {"NlMsghdr.Flags", Field, 0}, + {"NlMsghdr.Len", Field, 0}, + {"NlMsghdr.Pid", Field, 0}, + {"NlMsghdr.Seq", Field, 0}, + {"NlMsghdr.Type", Field, 0}, + {"NsecToFiletime", Func, 0}, + {"NsecToTimespec", Func, 0}, + {"NsecToTimeval", Func, 0}, + {"Ntohs", Func, 0}, + {"OCRNL", Const, 0}, + {"OFDEL", Const, 0}, + {"OFILL", Const, 0}, + {"OFIOGETBMAP", Const, 1}, + {"OID_PKIX_KP_SERVER_AUTH", Var, 0}, + {"OID_SERVER_GATED_CRYPTO", Var, 0}, + {"OID_SGC_NETSCAPE", Var, 0}, + {"OLCUC", Const, 0}, + {"ONLCR", Const, 0}, + {"ONLRET", Const, 0}, + {"ONOCR", Const, 0}, + {"ONOEOT", Const, 1}, + {"OPEN_ALWAYS", Const, 0}, + {"OPEN_EXISTING", Const, 0}, + {"OPOST", Const, 0}, + {"O_ACCMODE", Const, 0}, + {"O_ALERT", Const, 0}, + {"O_ALT_IO", Const, 1}, + {"O_APPEND", Const, 0}, + {"O_ASYNC", Const, 0}, + {"O_CLOEXEC", Const, 0}, + {"O_CREAT", Const, 0}, + {"O_DIRECT", Const, 0}, + {"O_DIRECTORY", Const, 0}, + {"O_DP_GETRAWENCRYPTED", Const, 16}, + {"O_DSYNC", Const, 0}, + {"O_EVTONLY", Const, 0}, + {"O_EXCL", Const, 0}, + {"O_EXEC", Const, 0}, + {"O_EXLOCK", Const, 0}, + {"O_FSYNC", Const, 0}, + {"O_LARGEFILE", Const, 0}, + {"O_NDELAY", Const, 0}, + {"O_NOATIME", Const, 0}, + {"O_NOCTTY", Const, 0}, + {"O_NOFOLLOW", Const, 0}, + {"O_NONBLOCK", Const, 0}, + {"O_NOSIGPIPE", Const, 1}, + {"O_POPUP", Const, 0}, + {"O_RDONLY", Const, 0}, + {"O_RDWR", Const, 0}, + {"O_RSYNC", Const, 0}, + {"O_SHLOCK", Const, 0}, + {"O_SYMLINK", Const, 0}, + {"O_SYNC", Const, 0}, + {"O_TRUNC", Const, 0}, + {"O_TTY_INIT", Const, 0}, + {"O_WRONLY", Const, 0}, + {"Open", Func, 0}, + {"OpenCurrentProcessToken", Func, 0}, + {"OpenProcess", Func, 0}, + {"OpenProcessToken", Func, 0}, + {"Openat", Func, 0}, + {"Overlapped", Type, 0}, + {"Overlapped.HEvent", Field, 0}, + {"Overlapped.Internal", Field, 0}, + {"Overlapped.InternalHigh", Field, 0}, + {"Overlapped.Offset", Field, 0}, + {"Overlapped.OffsetHigh", Field, 0}, + {"PACKET_ADD_MEMBERSHIP", Const, 0}, + {"PACKET_BROADCAST", Const, 0}, + {"PACKET_DROP_MEMBERSHIP", Const, 0}, + {"PACKET_FASTROUTE", Const, 0}, + {"PACKET_HOST", Const, 0}, + {"PACKET_LOOPBACK", Const, 0}, + {"PACKET_MR_ALLMULTI", Const, 0}, + {"PACKET_MR_MULTICAST", Const, 0}, + {"PACKET_MR_PROMISC", Const, 0}, + {"PACKET_MULTICAST", Const, 0}, + {"PACKET_OTHERHOST", Const, 0}, + {"PACKET_OUTGOING", Const, 0}, + {"PACKET_RECV_OUTPUT", Const, 0}, + {"PACKET_RX_RING", Const, 0}, + {"PACKET_STATISTICS", Const, 0}, + {"PAGE_EXECUTE_READ", Const, 0}, + {"PAGE_EXECUTE_READWRITE", Const, 0}, + {"PAGE_EXECUTE_WRITECOPY", Const, 0}, + {"PAGE_READONLY", Const, 0}, + {"PAGE_READWRITE", Const, 0}, + {"PAGE_WRITECOPY", Const, 0}, + {"PARENB", Const, 0}, + {"PARMRK", Const, 0}, + {"PARODD", Const, 0}, + {"PENDIN", Const, 0}, + {"PFL_HIDDEN", Const, 2}, + {"PFL_MATCHES_PROTOCOL_ZERO", Const, 2}, + {"PFL_MULTIPLE_PROTO_ENTRIES", Const, 2}, + {"PFL_NETWORKDIRECT_PROVIDER", Const, 2}, + {"PFL_RECOMMENDED_PROTO_ENTRY", Const, 2}, + {"PF_FLUSH", Const, 1}, + {"PKCS_7_ASN_ENCODING", Const, 0}, + {"PMC5_PIPELINE_FLUSH", Const, 1}, + {"PRIO_PGRP", Const, 2}, + {"PRIO_PROCESS", Const, 2}, + {"PRIO_USER", Const, 2}, + {"PRI_IOFLUSH", Const, 1}, + {"PROCESS_QUERY_INFORMATION", Const, 0}, + {"PROCESS_TERMINATE", Const, 2}, + {"PROT_EXEC", Const, 0}, + {"PROT_GROWSDOWN", Const, 0}, + {"PROT_GROWSUP", Const, 0}, + {"PROT_NONE", Const, 0}, + {"PROT_READ", Const, 0}, + {"PROT_WRITE", Const, 0}, + {"PROV_DH_SCHANNEL", Const, 0}, + {"PROV_DSS", Const, 0}, + {"PROV_DSS_DH", Const, 0}, + {"PROV_EC_ECDSA_FULL", Const, 0}, + {"PROV_EC_ECDSA_SIG", Const, 0}, + {"PROV_EC_ECNRA_FULL", Const, 0}, + {"PROV_EC_ECNRA_SIG", Const, 0}, + {"PROV_FORTEZZA", Const, 0}, + {"PROV_INTEL_SEC", Const, 0}, + {"PROV_MS_EXCHANGE", Const, 0}, + {"PROV_REPLACE_OWF", Const, 0}, + {"PROV_RNG", Const, 0}, + {"PROV_RSA_AES", Const, 0}, + {"PROV_RSA_FULL", Const, 0}, + {"PROV_RSA_SCHANNEL", Const, 0}, + {"PROV_RSA_SIG", Const, 0}, + {"PROV_SPYRUS_LYNKS", Const, 0}, + {"PROV_SSL", Const, 0}, + {"PR_CAPBSET_DROP", Const, 0}, + {"PR_CAPBSET_READ", Const, 0}, + {"PR_CLEAR_SECCOMP_FILTER", Const, 0}, + {"PR_ENDIAN_BIG", Const, 0}, + {"PR_ENDIAN_LITTLE", Const, 0}, + {"PR_ENDIAN_PPC_LITTLE", Const, 0}, + {"PR_FPEMU_NOPRINT", Const, 0}, + {"PR_FPEMU_SIGFPE", Const, 0}, + {"PR_FP_EXC_ASYNC", Const, 0}, + {"PR_FP_EXC_DISABLED", Const, 0}, + {"PR_FP_EXC_DIV", Const, 0}, + {"PR_FP_EXC_INV", Const, 0}, + {"PR_FP_EXC_NONRECOV", Const, 0}, + {"PR_FP_EXC_OVF", Const, 0}, + {"PR_FP_EXC_PRECISE", Const, 0}, + {"PR_FP_EXC_RES", Const, 0}, + {"PR_FP_EXC_SW_ENABLE", Const, 0}, + {"PR_FP_EXC_UND", Const, 0}, + {"PR_GET_DUMPABLE", Const, 0}, + {"PR_GET_ENDIAN", Const, 0}, + {"PR_GET_FPEMU", Const, 0}, + {"PR_GET_FPEXC", Const, 0}, + {"PR_GET_KEEPCAPS", Const, 0}, + {"PR_GET_NAME", Const, 0}, + {"PR_GET_PDEATHSIG", Const, 0}, + {"PR_GET_SECCOMP", Const, 0}, + {"PR_GET_SECCOMP_FILTER", Const, 0}, + {"PR_GET_SECUREBITS", Const, 0}, + {"PR_GET_TIMERSLACK", Const, 0}, + {"PR_GET_TIMING", Const, 0}, + {"PR_GET_TSC", Const, 0}, + {"PR_GET_UNALIGN", Const, 0}, + {"PR_MCE_KILL", Const, 0}, + {"PR_MCE_KILL_CLEAR", Const, 0}, + {"PR_MCE_KILL_DEFAULT", Const, 0}, + {"PR_MCE_KILL_EARLY", Const, 0}, + {"PR_MCE_KILL_GET", Const, 0}, + {"PR_MCE_KILL_LATE", Const, 0}, + {"PR_MCE_KILL_SET", Const, 0}, + {"PR_SECCOMP_FILTER_EVENT", Const, 0}, + {"PR_SECCOMP_FILTER_SYSCALL", Const, 0}, + {"PR_SET_DUMPABLE", Const, 0}, + {"PR_SET_ENDIAN", Const, 0}, + {"PR_SET_FPEMU", Const, 0}, + {"PR_SET_FPEXC", Const, 0}, + {"PR_SET_KEEPCAPS", Const, 0}, + {"PR_SET_NAME", Const, 0}, + {"PR_SET_PDEATHSIG", Const, 0}, + {"PR_SET_PTRACER", Const, 0}, + {"PR_SET_SECCOMP", Const, 0}, + {"PR_SET_SECCOMP_FILTER", Const, 0}, + {"PR_SET_SECUREBITS", Const, 0}, + {"PR_SET_TIMERSLACK", Const, 0}, + {"PR_SET_TIMING", Const, 0}, + {"PR_SET_TSC", Const, 0}, + {"PR_SET_UNALIGN", Const, 0}, + {"PR_TASK_PERF_EVENTS_DISABLE", Const, 0}, + {"PR_TASK_PERF_EVENTS_ENABLE", Const, 0}, + {"PR_TIMING_STATISTICAL", Const, 0}, + {"PR_TIMING_TIMESTAMP", Const, 0}, + {"PR_TSC_ENABLE", Const, 0}, + {"PR_TSC_SIGSEGV", Const, 0}, + {"PR_UNALIGN_NOPRINT", Const, 0}, + {"PR_UNALIGN_SIGBUS", Const, 0}, + {"PTRACE_ARCH_PRCTL", Const, 0}, + {"PTRACE_ATTACH", Const, 0}, + {"PTRACE_CONT", Const, 0}, + {"PTRACE_DETACH", Const, 0}, + {"PTRACE_EVENT_CLONE", Const, 0}, + {"PTRACE_EVENT_EXEC", Const, 0}, + {"PTRACE_EVENT_EXIT", Const, 0}, + {"PTRACE_EVENT_FORK", Const, 0}, + {"PTRACE_EVENT_VFORK", Const, 0}, + {"PTRACE_EVENT_VFORK_DONE", Const, 0}, + {"PTRACE_GETCRUNCHREGS", Const, 0}, + {"PTRACE_GETEVENTMSG", Const, 0}, + {"PTRACE_GETFPREGS", Const, 0}, + {"PTRACE_GETFPXREGS", Const, 0}, + {"PTRACE_GETHBPREGS", Const, 0}, + {"PTRACE_GETREGS", Const, 0}, + {"PTRACE_GETREGSET", Const, 0}, + {"PTRACE_GETSIGINFO", Const, 0}, + {"PTRACE_GETVFPREGS", Const, 0}, + {"PTRACE_GETWMMXREGS", Const, 0}, + {"PTRACE_GET_THREAD_AREA", Const, 0}, + {"PTRACE_KILL", Const, 0}, + {"PTRACE_OLDSETOPTIONS", Const, 0}, + {"PTRACE_O_MASK", Const, 0}, + {"PTRACE_O_TRACECLONE", Const, 0}, + {"PTRACE_O_TRACEEXEC", Const, 0}, + {"PTRACE_O_TRACEEXIT", Const, 0}, + {"PTRACE_O_TRACEFORK", Const, 0}, + {"PTRACE_O_TRACESYSGOOD", Const, 0}, + {"PTRACE_O_TRACEVFORK", Const, 0}, + {"PTRACE_O_TRACEVFORKDONE", Const, 0}, + {"PTRACE_PEEKDATA", Const, 0}, + {"PTRACE_PEEKTEXT", Const, 0}, + {"PTRACE_PEEKUSR", Const, 0}, + {"PTRACE_POKEDATA", Const, 0}, + {"PTRACE_POKETEXT", Const, 0}, + {"PTRACE_POKEUSR", Const, 0}, + {"PTRACE_SETCRUNCHREGS", Const, 0}, + {"PTRACE_SETFPREGS", Const, 0}, + {"PTRACE_SETFPXREGS", Const, 0}, + {"PTRACE_SETHBPREGS", Const, 0}, + {"PTRACE_SETOPTIONS", Const, 0}, + {"PTRACE_SETREGS", Const, 0}, + {"PTRACE_SETREGSET", Const, 0}, + {"PTRACE_SETSIGINFO", Const, 0}, + {"PTRACE_SETVFPREGS", Const, 0}, + {"PTRACE_SETWMMXREGS", Const, 0}, + {"PTRACE_SET_SYSCALL", Const, 0}, + {"PTRACE_SET_THREAD_AREA", Const, 0}, + {"PTRACE_SINGLEBLOCK", Const, 0}, + {"PTRACE_SINGLESTEP", Const, 0}, + {"PTRACE_SYSCALL", Const, 0}, + {"PTRACE_SYSEMU", Const, 0}, + {"PTRACE_SYSEMU_SINGLESTEP", Const, 0}, + {"PTRACE_TRACEME", Const, 0}, + {"PT_ATTACH", Const, 0}, + {"PT_ATTACHEXC", Const, 0}, + {"PT_CONTINUE", Const, 0}, + {"PT_DATA_ADDR", Const, 0}, + {"PT_DENY_ATTACH", Const, 0}, + {"PT_DETACH", Const, 0}, + {"PT_FIRSTMACH", Const, 0}, + {"PT_FORCEQUOTA", Const, 0}, + {"PT_KILL", Const, 0}, + {"PT_MASK", Const, 1}, + {"PT_READ_D", Const, 0}, + {"PT_READ_I", Const, 0}, + {"PT_READ_U", Const, 0}, + {"PT_SIGEXC", Const, 0}, + {"PT_STEP", Const, 0}, + {"PT_TEXT_ADDR", Const, 0}, + {"PT_TEXT_END_ADDR", Const, 0}, + {"PT_THUPDATE", Const, 0}, + {"PT_TRACE_ME", Const, 0}, + {"PT_WRITE_D", Const, 0}, + {"PT_WRITE_I", Const, 0}, + {"PT_WRITE_U", Const, 0}, + {"ParseDirent", Func, 0}, + {"ParseNetlinkMessage", Func, 0}, + {"ParseNetlinkRouteAttr", Func, 0}, + {"ParseRoutingMessage", Func, 0}, + {"ParseRoutingSockaddr", Func, 0}, + {"ParseSocketControlMessage", Func, 0}, + {"ParseUnixCredentials", Func, 0}, + {"ParseUnixRights", Func, 0}, + {"PathMax", Const, 0}, + {"Pathconf", Func, 0}, + {"Pause", Func, 0}, + {"Pipe", Func, 0}, + {"Pipe2", Func, 1}, + {"PivotRoot", Func, 0}, + {"Pointer", Type, 11}, + {"PostQueuedCompletionStatus", Func, 0}, + {"Pread", Func, 0}, + {"Proc", Type, 0}, + {"Proc.Dll", Field, 0}, + {"Proc.Name", Field, 0}, + {"ProcAttr", Type, 0}, + {"ProcAttr.Dir", Field, 0}, + {"ProcAttr.Env", Field, 0}, + {"ProcAttr.Files", Field, 0}, + {"ProcAttr.Sys", Field, 0}, + {"Process32First", Func, 4}, + {"Process32Next", Func, 4}, + {"ProcessEntry32", Type, 4}, + {"ProcessEntry32.DefaultHeapID", Field, 4}, + {"ProcessEntry32.ExeFile", Field, 4}, + {"ProcessEntry32.Flags", Field, 4}, + {"ProcessEntry32.ModuleID", Field, 4}, + {"ProcessEntry32.ParentProcessID", Field, 4}, + {"ProcessEntry32.PriClassBase", Field, 4}, + {"ProcessEntry32.ProcessID", Field, 4}, + {"ProcessEntry32.Size", Field, 4}, + {"ProcessEntry32.Threads", Field, 4}, + {"ProcessEntry32.Usage", Field, 4}, + {"ProcessInformation", Type, 0}, + {"ProcessInformation.Process", Field, 0}, + {"ProcessInformation.ProcessId", Field, 0}, + {"ProcessInformation.Thread", Field, 0}, + {"ProcessInformation.ThreadId", Field, 0}, + {"Protoent", Type, 0}, + {"Protoent.Aliases", Field, 0}, + {"Protoent.Name", Field, 0}, + {"Protoent.Proto", Field, 0}, + {"PtraceAttach", Func, 0}, + {"PtraceCont", Func, 0}, + {"PtraceDetach", Func, 0}, + {"PtraceGetEventMsg", Func, 0}, + {"PtraceGetRegs", Func, 0}, + {"PtracePeekData", Func, 0}, + {"PtracePeekText", Func, 0}, + {"PtracePokeData", Func, 0}, + {"PtracePokeText", Func, 0}, + {"PtraceRegs", Type, 0}, + {"PtraceRegs.Cs", Field, 0}, + {"PtraceRegs.Ds", Field, 0}, + {"PtraceRegs.Eax", Field, 0}, + {"PtraceRegs.Ebp", Field, 0}, + {"PtraceRegs.Ebx", Field, 0}, + {"PtraceRegs.Ecx", Field, 0}, + {"PtraceRegs.Edi", Field, 0}, + {"PtraceRegs.Edx", Field, 0}, + {"PtraceRegs.Eflags", Field, 0}, + {"PtraceRegs.Eip", Field, 0}, + {"PtraceRegs.Es", Field, 0}, + {"PtraceRegs.Esi", Field, 0}, + {"PtraceRegs.Esp", Field, 0}, + {"PtraceRegs.Fs", Field, 0}, + {"PtraceRegs.Fs_base", Field, 0}, + {"PtraceRegs.Gs", Field, 0}, + {"PtraceRegs.Gs_base", Field, 0}, + {"PtraceRegs.Orig_eax", Field, 0}, + {"PtraceRegs.Orig_rax", Field, 0}, + {"PtraceRegs.R10", Field, 0}, + {"PtraceRegs.R11", Field, 0}, + {"PtraceRegs.R12", Field, 0}, + {"PtraceRegs.R13", Field, 0}, + {"PtraceRegs.R14", Field, 0}, + {"PtraceRegs.R15", Field, 0}, + {"PtraceRegs.R8", Field, 0}, + {"PtraceRegs.R9", Field, 0}, + {"PtraceRegs.Rax", Field, 0}, + {"PtraceRegs.Rbp", Field, 0}, + {"PtraceRegs.Rbx", Field, 0}, + {"PtraceRegs.Rcx", Field, 0}, + {"PtraceRegs.Rdi", Field, 0}, + {"PtraceRegs.Rdx", Field, 0}, + {"PtraceRegs.Rip", Field, 0}, + {"PtraceRegs.Rsi", Field, 0}, + {"PtraceRegs.Rsp", Field, 0}, + {"PtraceRegs.Ss", Field, 0}, + {"PtraceRegs.Uregs", Field, 0}, + {"PtraceRegs.Xcs", Field, 0}, + {"PtraceRegs.Xds", Field, 0}, + {"PtraceRegs.Xes", Field, 0}, + {"PtraceRegs.Xfs", Field, 0}, + {"PtraceRegs.Xgs", Field, 0}, + {"PtraceRegs.Xss", Field, 0}, + {"PtraceSetOptions", Func, 0}, + {"PtraceSetRegs", Func, 0}, + {"PtraceSingleStep", Func, 0}, + {"PtraceSyscall", Func, 1}, + {"Pwrite", Func, 0}, + {"REG_BINARY", Const, 0}, + {"REG_DWORD", Const, 0}, + {"REG_DWORD_BIG_ENDIAN", Const, 0}, + {"REG_DWORD_LITTLE_ENDIAN", Const, 0}, + {"REG_EXPAND_SZ", Const, 0}, + {"REG_FULL_RESOURCE_DESCRIPTOR", Const, 0}, + {"REG_LINK", Const, 0}, + {"REG_MULTI_SZ", Const, 0}, + {"REG_NONE", Const, 0}, + {"REG_QWORD", Const, 0}, + {"REG_QWORD_LITTLE_ENDIAN", Const, 0}, + {"REG_RESOURCE_LIST", Const, 0}, + {"REG_RESOURCE_REQUIREMENTS_LIST", Const, 0}, + {"REG_SZ", Const, 0}, + {"RLIMIT_AS", Const, 0}, + {"RLIMIT_CORE", Const, 0}, + {"RLIMIT_CPU", Const, 0}, + {"RLIMIT_CPU_USAGE_MONITOR", Const, 16}, + {"RLIMIT_DATA", Const, 0}, + {"RLIMIT_FSIZE", Const, 0}, + {"RLIMIT_NOFILE", Const, 0}, + {"RLIMIT_STACK", Const, 0}, + {"RLIM_INFINITY", Const, 0}, + {"RTAX_ADVMSS", Const, 0}, + {"RTAX_AUTHOR", Const, 0}, + {"RTAX_BRD", Const, 0}, + {"RTAX_CWND", Const, 0}, + {"RTAX_DST", Const, 0}, + {"RTAX_FEATURES", Const, 0}, + {"RTAX_FEATURE_ALLFRAG", Const, 0}, + {"RTAX_FEATURE_ECN", Const, 0}, + {"RTAX_FEATURE_SACK", Const, 0}, + {"RTAX_FEATURE_TIMESTAMP", Const, 0}, + {"RTAX_GATEWAY", Const, 0}, + {"RTAX_GENMASK", Const, 0}, + {"RTAX_HOPLIMIT", Const, 0}, + {"RTAX_IFA", Const, 0}, + {"RTAX_IFP", Const, 0}, + {"RTAX_INITCWND", Const, 0}, + {"RTAX_INITRWND", Const, 0}, + {"RTAX_LABEL", Const, 1}, + {"RTAX_LOCK", Const, 0}, + {"RTAX_MAX", Const, 0}, + {"RTAX_MTU", Const, 0}, + {"RTAX_NETMASK", Const, 0}, + {"RTAX_REORDERING", Const, 0}, + {"RTAX_RTO_MIN", Const, 0}, + {"RTAX_RTT", Const, 0}, + {"RTAX_RTTVAR", Const, 0}, + {"RTAX_SRC", Const, 1}, + {"RTAX_SRCMASK", Const, 1}, + {"RTAX_SSTHRESH", Const, 0}, + {"RTAX_TAG", Const, 1}, + {"RTAX_UNSPEC", Const, 0}, + {"RTAX_WINDOW", Const, 0}, + {"RTA_ALIGNTO", Const, 0}, + {"RTA_AUTHOR", Const, 0}, + {"RTA_BRD", Const, 0}, + {"RTA_CACHEINFO", Const, 0}, + {"RTA_DST", Const, 0}, + {"RTA_FLOW", Const, 0}, + {"RTA_GATEWAY", Const, 0}, + {"RTA_GENMASK", Const, 0}, + {"RTA_IFA", Const, 0}, + {"RTA_IFP", Const, 0}, + {"RTA_IIF", Const, 0}, + {"RTA_LABEL", Const, 1}, + {"RTA_MAX", Const, 0}, + {"RTA_METRICS", Const, 0}, + {"RTA_MULTIPATH", Const, 0}, + {"RTA_NETMASK", Const, 0}, + {"RTA_OIF", Const, 0}, + {"RTA_PREFSRC", Const, 0}, + {"RTA_PRIORITY", Const, 0}, + {"RTA_SRC", Const, 0}, + {"RTA_SRCMASK", Const, 1}, + {"RTA_TABLE", Const, 0}, + {"RTA_TAG", Const, 1}, + {"RTA_UNSPEC", Const, 0}, + {"RTCF_DIRECTSRC", Const, 0}, + {"RTCF_DOREDIRECT", Const, 0}, + {"RTCF_LOG", Const, 0}, + {"RTCF_MASQ", Const, 0}, + {"RTCF_NAT", Const, 0}, + {"RTCF_VALVE", Const, 0}, + {"RTF_ADDRCLASSMASK", Const, 0}, + {"RTF_ADDRCONF", Const, 0}, + {"RTF_ALLONLINK", Const, 0}, + {"RTF_ANNOUNCE", Const, 1}, + {"RTF_BLACKHOLE", Const, 0}, + {"RTF_BROADCAST", Const, 0}, + {"RTF_CACHE", Const, 0}, + {"RTF_CLONED", Const, 1}, + {"RTF_CLONING", Const, 0}, + {"RTF_CONDEMNED", Const, 0}, + {"RTF_DEFAULT", Const, 0}, + {"RTF_DELCLONE", Const, 0}, + {"RTF_DONE", Const, 0}, + {"RTF_DYNAMIC", Const, 0}, + {"RTF_FLOW", Const, 0}, + {"RTF_FMASK", Const, 0}, + {"RTF_GATEWAY", Const, 0}, + {"RTF_GWFLAG_COMPAT", Const, 3}, + {"RTF_HOST", Const, 0}, + {"RTF_IFREF", Const, 0}, + {"RTF_IFSCOPE", Const, 0}, + {"RTF_INTERFACE", Const, 0}, + {"RTF_IRTT", Const, 0}, + {"RTF_LINKRT", Const, 0}, + {"RTF_LLDATA", Const, 0}, + {"RTF_LLINFO", Const, 0}, + {"RTF_LOCAL", Const, 0}, + {"RTF_MASK", Const, 1}, + {"RTF_MODIFIED", Const, 0}, + {"RTF_MPATH", Const, 1}, + {"RTF_MPLS", Const, 1}, + {"RTF_MSS", Const, 0}, + {"RTF_MTU", Const, 0}, + {"RTF_MULTICAST", Const, 0}, + {"RTF_NAT", Const, 0}, + {"RTF_NOFORWARD", Const, 0}, + {"RTF_NONEXTHOP", Const, 0}, + {"RTF_NOPMTUDISC", Const, 0}, + {"RTF_PERMANENT_ARP", Const, 1}, + {"RTF_PINNED", Const, 0}, + {"RTF_POLICY", Const, 0}, + {"RTF_PRCLONING", Const, 0}, + {"RTF_PROTO1", Const, 0}, + {"RTF_PROTO2", Const, 0}, + {"RTF_PROTO3", Const, 0}, + {"RTF_PROXY", Const, 16}, + {"RTF_REINSTATE", Const, 0}, + {"RTF_REJECT", Const, 0}, + {"RTF_RNH_LOCKED", Const, 0}, + {"RTF_ROUTER", Const, 16}, + {"RTF_SOURCE", Const, 1}, + {"RTF_SRC", Const, 1}, + {"RTF_STATIC", Const, 0}, + {"RTF_STICKY", Const, 0}, + {"RTF_THROW", Const, 0}, + {"RTF_TUNNEL", Const, 1}, + {"RTF_UP", Const, 0}, + {"RTF_USETRAILERS", Const, 1}, + {"RTF_WASCLONED", Const, 0}, + {"RTF_WINDOW", Const, 0}, + {"RTF_XRESOLVE", Const, 0}, + {"RTM_ADD", Const, 0}, + {"RTM_BASE", Const, 0}, + {"RTM_CHANGE", Const, 0}, + {"RTM_CHGADDR", Const, 1}, + {"RTM_DELACTION", Const, 0}, + {"RTM_DELADDR", Const, 0}, + {"RTM_DELADDRLABEL", Const, 0}, + {"RTM_DELETE", Const, 0}, + {"RTM_DELLINK", Const, 0}, + {"RTM_DELMADDR", Const, 0}, + {"RTM_DELNEIGH", Const, 0}, + {"RTM_DELQDISC", Const, 0}, + {"RTM_DELROUTE", Const, 0}, + {"RTM_DELRULE", Const, 0}, + {"RTM_DELTCLASS", Const, 0}, + {"RTM_DELTFILTER", Const, 0}, + {"RTM_DESYNC", Const, 1}, + {"RTM_F_CLONED", Const, 0}, + {"RTM_F_EQUALIZE", Const, 0}, + {"RTM_F_NOTIFY", Const, 0}, + {"RTM_F_PREFIX", Const, 0}, + {"RTM_GET", Const, 0}, + {"RTM_GET2", Const, 0}, + {"RTM_GETACTION", Const, 0}, + {"RTM_GETADDR", Const, 0}, + {"RTM_GETADDRLABEL", Const, 0}, + {"RTM_GETANYCAST", Const, 0}, + {"RTM_GETDCB", Const, 0}, + {"RTM_GETLINK", Const, 0}, + {"RTM_GETMULTICAST", Const, 0}, + {"RTM_GETNEIGH", Const, 0}, + {"RTM_GETNEIGHTBL", Const, 0}, + {"RTM_GETQDISC", Const, 0}, + {"RTM_GETROUTE", Const, 0}, + {"RTM_GETRULE", Const, 0}, + {"RTM_GETTCLASS", Const, 0}, + {"RTM_GETTFILTER", Const, 0}, + {"RTM_IEEE80211", Const, 0}, + {"RTM_IFANNOUNCE", Const, 0}, + {"RTM_IFINFO", Const, 0}, + {"RTM_IFINFO2", Const, 0}, + {"RTM_LLINFO_UPD", Const, 1}, + {"RTM_LOCK", Const, 0}, + {"RTM_LOSING", Const, 0}, + {"RTM_MAX", Const, 0}, + {"RTM_MAXSIZE", Const, 1}, + {"RTM_MISS", Const, 0}, + {"RTM_NEWACTION", Const, 0}, + {"RTM_NEWADDR", Const, 0}, + {"RTM_NEWADDRLABEL", Const, 0}, + {"RTM_NEWLINK", Const, 0}, + {"RTM_NEWMADDR", Const, 0}, + {"RTM_NEWMADDR2", Const, 0}, + {"RTM_NEWNDUSEROPT", Const, 0}, + {"RTM_NEWNEIGH", Const, 0}, + {"RTM_NEWNEIGHTBL", Const, 0}, + {"RTM_NEWPREFIX", Const, 0}, + {"RTM_NEWQDISC", Const, 0}, + {"RTM_NEWROUTE", Const, 0}, + {"RTM_NEWRULE", Const, 0}, + {"RTM_NEWTCLASS", Const, 0}, + {"RTM_NEWTFILTER", Const, 0}, + {"RTM_NR_FAMILIES", Const, 0}, + {"RTM_NR_MSGTYPES", Const, 0}, + {"RTM_OIFINFO", Const, 1}, + {"RTM_OLDADD", Const, 0}, + {"RTM_OLDDEL", Const, 0}, + {"RTM_OOIFINFO", Const, 1}, + {"RTM_REDIRECT", Const, 0}, + {"RTM_RESOLVE", Const, 0}, + {"RTM_RTTUNIT", Const, 0}, + {"RTM_SETDCB", Const, 0}, + {"RTM_SETGATE", Const, 1}, + {"RTM_SETLINK", Const, 0}, + {"RTM_SETNEIGHTBL", Const, 0}, + {"RTM_VERSION", Const, 0}, + {"RTNH_ALIGNTO", Const, 0}, + {"RTNH_F_DEAD", Const, 0}, + {"RTNH_F_ONLINK", Const, 0}, + {"RTNH_F_PERVASIVE", Const, 0}, + {"RTNLGRP_IPV4_IFADDR", Const, 1}, + {"RTNLGRP_IPV4_MROUTE", Const, 1}, + {"RTNLGRP_IPV4_ROUTE", Const, 1}, + {"RTNLGRP_IPV4_RULE", Const, 1}, + {"RTNLGRP_IPV6_IFADDR", Const, 1}, + {"RTNLGRP_IPV6_IFINFO", Const, 1}, + {"RTNLGRP_IPV6_MROUTE", Const, 1}, + {"RTNLGRP_IPV6_PREFIX", Const, 1}, + {"RTNLGRP_IPV6_ROUTE", Const, 1}, + {"RTNLGRP_IPV6_RULE", Const, 1}, + {"RTNLGRP_LINK", Const, 1}, + {"RTNLGRP_ND_USEROPT", Const, 1}, + {"RTNLGRP_NEIGH", Const, 1}, + {"RTNLGRP_NONE", Const, 1}, + {"RTNLGRP_NOTIFY", Const, 1}, + {"RTNLGRP_TC", Const, 1}, + {"RTN_ANYCAST", Const, 0}, + {"RTN_BLACKHOLE", Const, 0}, + {"RTN_BROADCAST", Const, 0}, + {"RTN_LOCAL", Const, 0}, + {"RTN_MAX", Const, 0}, + {"RTN_MULTICAST", Const, 0}, + {"RTN_NAT", Const, 0}, + {"RTN_PROHIBIT", Const, 0}, + {"RTN_THROW", Const, 0}, + {"RTN_UNICAST", Const, 0}, + {"RTN_UNREACHABLE", Const, 0}, + {"RTN_UNSPEC", Const, 0}, + {"RTN_XRESOLVE", Const, 0}, + {"RTPROT_BIRD", Const, 0}, + {"RTPROT_BOOT", Const, 0}, + {"RTPROT_DHCP", Const, 0}, + {"RTPROT_DNROUTED", Const, 0}, + {"RTPROT_GATED", Const, 0}, + {"RTPROT_KERNEL", Const, 0}, + {"RTPROT_MRT", Const, 0}, + {"RTPROT_NTK", Const, 0}, + {"RTPROT_RA", Const, 0}, + {"RTPROT_REDIRECT", Const, 0}, + {"RTPROT_STATIC", Const, 0}, + {"RTPROT_UNSPEC", Const, 0}, + {"RTPROT_XORP", Const, 0}, + {"RTPROT_ZEBRA", Const, 0}, + {"RTV_EXPIRE", Const, 0}, + {"RTV_HOPCOUNT", Const, 0}, + {"RTV_MTU", Const, 0}, + {"RTV_RPIPE", Const, 0}, + {"RTV_RTT", Const, 0}, + {"RTV_RTTVAR", Const, 0}, + {"RTV_SPIPE", Const, 0}, + {"RTV_SSTHRESH", Const, 0}, + {"RTV_WEIGHT", Const, 0}, + {"RT_CACHING_CONTEXT", Const, 1}, + {"RT_CLASS_DEFAULT", Const, 0}, + {"RT_CLASS_LOCAL", Const, 0}, + {"RT_CLASS_MAIN", Const, 0}, + {"RT_CLASS_MAX", Const, 0}, + {"RT_CLASS_UNSPEC", Const, 0}, + {"RT_DEFAULT_FIB", Const, 1}, + {"RT_NORTREF", Const, 1}, + {"RT_SCOPE_HOST", Const, 0}, + {"RT_SCOPE_LINK", Const, 0}, + {"RT_SCOPE_NOWHERE", Const, 0}, + {"RT_SCOPE_SITE", Const, 0}, + {"RT_SCOPE_UNIVERSE", Const, 0}, + {"RT_TABLEID_MAX", Const, 1}, + {"RT_TABLE_COMPAT", Const, 0}, + {"RT_TABLE_DEFAULT", Const, 0}, + {"RT_TABLE_LOCAL", Const, 0}, + {"RT_TABLE_MAIN", Const, 0}, + {"RT_TABLE_MAX", Const, 0}, + {"RT_TABLE_UNSPEC", Const, 0}, + {"RUSAGE_CHILDREN", Const, 0}, + {"RUSAGE_SELF", Const, 0}, + {"RUSAGE_THREAD", Const, 0}, + {"Radvisory_t", Type, 0}, + {"Radvisory_t.Count", Field, 0}, + {"Radvisory_t.Offset", Field, 0}, + {"Radvisory_t.Pad_cgo_0", Field, 0}, + {"RawConn", Type, 9}, + {"RawSockaddr", Type, 0}, + {"RawSockaddr.Data", Field, 0}, + {"RawSockaddr.Family", Field, 0}, + {"RawSockaddr.Len", Field, 0}, + {"RawSockaddrAny", Type, 0}, + {"RawSockaddrAny.Addr", Field, 0}, + {"RawSockaddrAny.Pad", Field, 0}, + {"RawSockaddrDatalink", Type, 0}, + {"RawSockaddrDatalink.Alen", Field, 0}, + {"RawSockaddrDatalink.Data", Field, 0}, + {"RawSockaddrDatalink.Family", Field, 0}, + {"RawSockaddrDatalink.Index", Field, 0}, + {"RawSockaddrDatalink.Len", Field, 0}, + {"RawSockaddrDatalink.Nlen", Field, 0}, + {"RawSockaddrDatalink.Pad_cgo_0", Field, 2}, + {"RawSockaddrDatalink.Slen", Field, 0}, + {"RawSockaddrDatalink.Type", Field, 0}, + {"RawSockaddrInet4", Type, 0}, + {"RawSockaddrInet4.Addr", Field, 0}, + {"RawSockaddrInet4.Family", Field, 0}, + {"RawSockaddrInet4.Len", Field, 0}, + {"RawSockaddrInet4.Port", Field, 0}, + {"RawSockaddrInet4.Zero", Field, 0}, + {"RawSockaddrInet6", Type, 0}, + {"RawSockaddrInet6.Addr", Field, 0}, + {"RawSockaddrInet6.Family", Field, 0}, + {"RawSockaddrInet6.Flowinfo", Field, 0}, + {"RawSockaddrInet6.Len", Field, 0}, + {"RawSockaddrInet6.Port", Field, 0}, + {"RawSockaddrInet6.Scope_id", Field, 0}, + {"RawSockaddrLinklayer", Type, 0}, + {"RawSockaddrLinklayer.Addr", Field, 0}, + {"RawSockaddrLinklayer.Family", Field, 0}, + {"RawSockaddrLinklayer.Halen", Field, 0}, + {"RawSockaddrLinklayer.Hatype", Field, 0}, + {"RawSockaddrLinklayer.Ifindex", Field, 0}, + {"RawSockaddrLinklayer.Pkttype", Field, 0}, + {"RawSockaddrLinklayer.Protocol", Field, 0}, + {"RawSockaddrNetlink", Type, 0}, + {"RawSockaddrNetlink.Family", Field, 0}, + {"RawSockaddrNetlink.Groups", Field, 0}, + {"RawSockaddrNetlink.Pad", Field, 0}, + {"RawSockaddrNetlink.Pid", Field, 0}, + {"RawSockaddrUnix", Type, 0}, + {"RawSockaddrUnix.Family", Field, 0}, + {"RawSockaddrUnix.Len", Field, 0}, + {"RawSockaddrUnix.Pad_cgo_0", Field, 2}, + {"RawSockaddrUnix.Path", Field, 0}, + {"RawSyscall", Func, 0}, + {"RawSyscall6", Func, 0}, + {"Read", Func, 0}, + {"ReadConsole", Func, 1}, + {"ReadDirectoryChanges", Func, 0}, + {"ReadDirent", Func, 0}, + {"ReadFile", Func, 0}, + {"Readlink", Func, 0}, + {"Reboot", Func, 0}, + {"Recvfrom", Func, 0}, + {"Recvmsg", Func, 0}, + {"RegCloseKey", Func, 0}, + {"RegEnumKeyEx", Func, 0}, + {"RegOpenKeyEx", Func, 0}, + {"RegQueryInfoKey", Func, 0}, + {"RegQueryValueEx", Func, 0}, + {"RemoveDirectory", Func, 0}, + {"Removexattr", Func, 1}, + {"Rename", Func, 0}, + {"Renameat", Func, 0}, + {"Revoke", Func, 0}, + {"Rlimit", Type, 0}, + {"Rlimit.Cur", Field, 0}, + {"Rlimit.Max", Field, 0}, + {"Rmdir", Func, 0}, + {"RouteMessage", Type, 0}, + {"RouteMessage.Data", Field, 0}, + {"RouteMessage.Header", Field, 0}, + {"RouteRIB", Func, 0}, + {"RoutingMessage", Type, 0}, + {"RtAttr", Type, 0}, + {"RtAttr.Len", Field, 0}, + {"RtAttr.Type", Field, 0}, + {"RtGenmsg", Type, 0}, + {"RtGenmsg.Family", Field, 0}, + {"RtMetrics", Type, 0}, + {"RtMetrics.Expire", Field, 0}, + {"RtMetrics.Filler", Field, 0}, + {"RtMetrics.Hopcount", Field, 0}, + {"RtMetrics.Locks", Field, 0}, + {"RtMetrics.Mtu", Field, 0}, + {"RtMetrics.Pad", Field, 3}, + {"RtMetrics.Pksent", Field, 0}, + {"RtMetrics.Recvpipe", Field, 0}, + {"RtMetrics.Refcnt", Field, 2}, + {"RtMetrics.Rtt", Field, 0}, + {"RtMetrics.Rttvar", Field, 0}, + {"RtMetrics.Sendpipe", Field, 0}, + {"RtMetrics.Ssthresh", Field, 0}, + {"RtMetrics.Weight", Field, 0}, + {"RtMsg", Type, 0}, + {"RtMsg.Dst_len", Field, 0}, + {"RtMsg.Family", Field, 0}, + {"RtMsg.Flags", Field, 0}, + {"RtMsg.Protocol", Field, 0}, + {"RtMsg.Scope", Field, 0}, + {"RtMsg.Src_len", Field, 0}, + {"RtMsg.Table", Field, 0}, + {"RtMsg.Tos", Field, 0}, + {"RtMsg.Type", Field, 0}, + {"RtMsghdr", Type, 0}, + {"RtMsghdr.Addrs", Field, 0}, + {"RtMsghdr.Errno", Field, 0}, + {"RtMsghdr.Flags", Field, 0}, + {"RtMsghdr.Fmask", Field, 0}, + {"RtMsghdr.Hdrlen", Field, 2}, + {"RtMsghdr.Index", Field, 0}, + {"RtMsghdr.Inits", Field, 0}, + {"RtMsghdr.Mpls", Field, 2}, + {"RtMsghdr.Msglen", Field, 0}, + {"RtMsghdr.Pad_cgo_0", Field, 0}, + {"RtMsghdr.Pad_cgo_1", Field, 2}, + {"RtMsghdr.Pid", Field, 0}, + {"RtMsghdr.Priority", Field, 2}, + {"RtMsghdr.Rmx", Field, 0}, + {"RtMsghdr.Seq", Field, 0}, + {"RtMsghdr.Tableid", Field, 2}, + {"RtMsghdr.Type", Field, 0}, + {"RtMsghdr.Use", Field, 0}, + {"RtMsghdr.Version", Field, 0}, + {"RtNexthop", Type, 0}, + {"RtNexthop.Flags", Field, 0}, + {"RtNexthop.Hops", Field, 0}, + {"RtNexthop.Ifindex", Field, 0}, + {"RtNexthop.Len", Field, 0}, + {"Rusage", Type, 0}, + {"Rusage.CreationTime", Field, 0}, + {"Rusage.ExitTime", Field, 0}, + {"Rusage.Idrss", Field, 0}, + {"Rusage.Inblock", Field, 0}, + {"Rusage.Isrss", Field, 0}, + {"Rusage.Ixrss", Field, 0}, + {"Rusage.KernelTime", Field, 0}, + {"Rusage.Majflt", Field, 0}, + {"Rusage.Maxrss", Field, 0}, + {"Rusage.Minflt", Field, 0}, + {"Rusage.Msgrcv", Field, 0}, + {"Rusage.Msgsnd", Field, 0}, + {"Rusage.Nivcsw", Field, 0}, + {"Rusage.Nsignals", Field, 0}, + {"Rusage.Nswap", Field, 0}, + {"Rusage.Nvcsw", Field, 0}, + {"Rusage.Oublock", Field, 0}, + {"Rusage.Stime", Field, 0}, + {"Rusage.UserTime", Field, 0}, + {"Rusage.Utime", Field, 0}, + {"SCM_BINTIME", Const, 0}, + {"SCM_CREDENTIALS", Const, 0}, + {"SCM_CREDS", Const, 0}, + {"SCM_RIGHTS", Const, 0}, + {"SCM_TIMESTAMP", Const, 0}, + {"SCM_TIMESTAMPING", Const, 0}, + {"SCM_TIMESTAMPNS", Const, 0}, + {"SCM_TIMESTAMP_MONOTONIC", Const, 0}, + {"SHUT_RD", Const, 0}, + {"SHUT_RDWR", Const, 0}, + {"SHUT_WR", Const, 0}, + {"SID", Type, 0}, + {"SIDAndAttributes", Type, 0}, + {"SIDAndAttributes.Attributes", Field, 0}, + {"SIDAndAttributes.Sid", Field, 0}, + {"SIGABRT", Const, 0}, + {"SIGALRM", Const, 0}, + {"SIGBUS", Const, 0}, + {"SIGCHLD", Const, 0}, + {"SIGCLD", Const, 0}, + {"SIGCONT", Const, 0}, + {"SIGEMT", Const, 0}, + {"SIGFPE", Const, 0}, + {"SIGHUP", Const, 0}, + {"SIGILL", Const, 0}, + {"SIGINFO", Const, 0}, + {"SIGINT", Const, 0}, + {"SIGIO", Const, 0}, + {"SIGIOT", Const, 0}, + {"SIGKILL", Const, 0}, + {"SIGLIBRT", Const, 1}, + {"SIGLWP", Const, 0}, + {"SIGPIPE", Const, 0}, + {"SIGPOLL", Const, 0}, + {"SIGPROF", Const, 0}, + {"SIGPWR", Const, 0}, + {"SIGQUIT", Const, 0}, + {"SIGSEGV", Const, 0}, + {"SIGSTKFLT", Const, 0}, + {"SIGSTOP", Const, 0}, + {"SIGSYS", Const, 0}, + {"SIGTERM", Const, 0}, + {"SIGTHR", Const, 0}, + {"SIGTRAP", Const, 0}, + {"SIGTSTP", Const, 0}, + {"SIGTTIN", Const, 0}, + {"SIGTTOU", Const, 0}, + {"SIGUNUSED", Const, 0}, + {"SIGURG", Const, 0}, + {"SIGUSR1", Const, 0}, + {"SIGUSR2", Const, 0}, + {"SIGVTALRM", Const, 0}, + {"SIGWINCH", Const, 0}, + {"SIGXCPU", Const, 0}, + {"SIGXFSZ", Const, 0}, + {"SIOCADDDLCI", Const, 0}, + {"SIOCADDMULTI", Const, 0}, + {"SIOCADDRT", Const, 0}, + {"SIOCAIFADDR", Const, 0}, + {"SIOCAIFGROUP", Const, 0}, + {"SIOCALIFADDR", Const, 0}, + {"SIOCARPIPLL", Const, 0}, + {"SIOCATMARK", Const, 0}, + {"SIOCAUTOADDR", Const, 0}, + {"SIOCAUTONETMASK", Const, 0}, + {"SIOCBRDGADD", Const, 1}, + {"SIOCBRDGADDS", Const, 1}, + {"SIOCBRDGARL", Const, 1}, + {"SIOCBRDGDADDR", Const, 1}, + {"SIOCBRDGDEL", Const, 1}, + {"SIOCBRDGDELS", Const, 1}, + {"SIOCBRDGFLUSH", Const, 1}, + {"SIOCBRDGFRL", Const, 1}, + {"SIOCBRDGGCACHE", Const, 1}, + {"SIOCBRDGGFD", Const, 1}, + {"SIOCBRDGGHT", Const, 1}, + {"SIOCBRDGGIFFLGS", Const, 1}, + {"SIOCBRDGGMA", Const, 1}, + {"SIOCBRDGGPARAM", Const, 1}, + {"SIOCBRDGGPRI", Const, 1}, + {"SIOCBRDGGRL", Const, 1}, + {"SIOCBRDGGSIFS", Const, 1}, + {"SIOCBRDGGTO", Const, 1}, + {"SIOCBRDGIFS", Const, 1}, + {"SIOCBRDGRTS", Const, 1}, + {"SIOCBRDGSADDR", Const, 1}, + {"SIOCBRDGSCACHE", Const, 1}, + {"SIOCBRDGSFD", Const, 1}, + {"SIOCBRDGSHT", Const, 1}, + {"SIOCBRDGSIFCOST", Const, 1}, + {"SIOCBRDGSIFFLGS", Const, 1}, + {"SIOCBRDGSIFPRIO", Const, 1}, + {"SIOCBRDGSMA", Const, 1}, + {"SIOCBRDGSPRI", Const, 1}, + {"SIOCBRDGSPROTO", Const, 1}, + {"SIOCBRDGSTO", Const, 1}, + {"SIOCBRDGSTXHC", Const, 1}, + {"SIOCDARP", Const, 0}, + {"SIOCDELDLCI", Const, 0}, + {"SIOCDELMULTI", Const, 0}, + {"SIOCDELRT", Const, 0}, + {"SIOCDEVPRIVATE", Const, 0}, + {"SIOCDIFADDR", Const, 0}, + {"SIOCDIFGROUP", Const, 0}, + {"SIOCDIFPHYADDR", Const, 0}, + {"SIOCDLIFADDR", Const, 0}, + {"SIOCDRARP", Const, 0}, + {"SIOCGARP", Const, 0}, + {"SIOCGDRVSPEC", Const, 0}, + {"SIOCGETKALIVE", Const, 1}, + {"SIOCGETLABEL", Const, 1}, + {"SIOCGETPFLOW", Const, 1}, + {"SIOCGETPFSYNC", Const, 1}, + {"SIOCGETSGCNT", Const, 0}, + {"SIOCGETVIFCNT", Const, 0}, + {"SIOCGETVLAN", Const, 0}, + {"SIOCGHIWAT", Const, 0}, + {"SIOCGIFADDR", Const, 0}, + {"SIOCGIFADDRPREF", Const, 1}, + {"SIOCGIFALIAS", Const, 1}, + {"SIOCGIFALTMTU", Const, 0}, + {"SIOCGIFASYNCMAP", Const, 0}, + {"SIOCGIFBOND", Const, 0}, + {"SIOCGIFBR", Const, 0}, + {"SIOCGIFBRDADDR", Const, 0}, + {"SIOCGIFCAP", Const, 0}, + {"SIOCGIFCONF", Const, 0}, + {"SIOCGIFCOUNT", Const, 0}, + {"SIOCGIFDATA", Const, 1}, + {"SIOCGIFDESCR", Const, 0}, + {"SIOCGIFDEVMTU", Const, 0}, + {"SIOCGIFDLT", Const, 1}, + {"SIOCGIFDSTADDR", Const, 0}, + {"SIOCGIFENCAP", Const, 0}, + {"SIOCGIFFIB", Const, 1}, + {"SIOCGIFFLAGS", Const, 0}, + {"SIOCGIFGATTR", Const, 1}, + {"SIOCGIFGENERIC", Const, 0}, + {"SIOCGIFGMEMB", Const, 0}, + {"SIOCGIFGROUP", Const, 0}, + {"SIOCGIFHARDMTU", Const, 3}, + {"SIOCGIFHWADDR", Const, 0}, + {"SIOCGIFINDEX", Const, 0}, + {"SIOCGIFKPI", Const, 0}, + {"SIOCGIFMAC", Const, 0}, + {"SIOCGIFMAP", Const, 0}, + {"SIOCGIFMEDIA", Const, 0}, + {"SIOCGIFMEM", Const, 0}, + {"SIOCGIFMETRIC", Const, 0}, + {"SIOCGIFMTU", Const, 0}, + {"SIOCGIFNAME", Const, 0}, + {"SIOCGIFNETMASK", Const, 0}, + {"SIOCGIFPDSTADDR", Const, 0}, + {"SIOCGIFPFLAGS", Const, 0}, + {"SIOCGIFPHYS", Const, 0}, + {"SIOCGIFPRIORITY", Const, 1}, + {"SIOCGIFPSRCADDR", Const, 0}, + {"SIOCGIFRDOMAIN", Const, 1}, + {"SIOCGIFRTLABEL", Const, 1}, + {"SIOCGIFSLAVE", Const, 0}, + {"SIOCGIFSTATUS", Const, 0}, + {"SIOCGIFTIMESLOT", Const, 1}, + {"SIOCGIFTXQLEN", Const, 0}, + {"SIOCGIFVLAN", Const, 0}, + {"SIOCGIFWAKEFLAGS", Const, 0}, + {"SIOCGIFXFLAGS", Const, 1}, + {"SIOCGLIFADDR", Const, 0}, + {"SIOCGLIFPHYADDR", Const, 0}, + {"SIOCGLIFPHYRTABLE", Const, 1}, + {"SIOCGLIFPHYTTL", Const, 3}, + {"SIOCGLINKSTR", Const, 1}, + {"SIOCGLOWAT", Const, 0}, + {"SIOCGPGRP", Const, 0}, + {"SIOCGPRIVATE_0", Const, 0}, + {"SIOCGPRIVATE_1", Const, 0}, + {"SIOCGRARP", Const, 0}, + {"SIOCGSPPPPARAMS", Const, 3}, + {"SIOCGSTAMP", Const, 0}, + {"SIOCGSTAMPNS", Const, 0}, + {"SIOCGVH", Const, 1}, + {"SIOCGVNETID", Const, 3}, + {"SIOCIFCREATE", Const, 0}, + {"SIOCIFCREATE2", Const, 0}, + {"SIOCIFDESTROY", Const, 0}, + {"SIOCIFGCLONERS", Const, 0}, + {"SIOCINITIFADDR", Const, 1}, + {"SIOCPROTOPRIVATE", Const, 0}, + {"SIOCRSLVMULTI", Const, 0}, + {"SIOCRTMSG", Const, 0}, + {"SIOCSARP", Const, 0}, + {"SIOCSDRVSPEC", Const, 0}, + {"SIOCSETKALIVE", Const, 1}, + {"SIOCSETLABEL", Const, 1}, + {"SIOCSETPFLOW", Const, 1}, + {"SIOCSETPFSYNC", Const, 1}, + {"SIOCSETVLAN", Const, 0}, + {"SIOCSHIWAT", Const, 0}, + {"SIOCSIFADDR", Const, 0}, + {"SIOCSIFADDRPREF", Const, 1}, + {"SIOCSIFALTMTU", Const, 0}, + {"SIOCSIFASYNCMAP", Const, 0}, + {"SIOCSIFBOND", Const, 0}, + {"SIOCSIFBR", Const, 0}, + {"SIOCSIFBRDADDR", Const, 0}, + {"SIOCSIFCAP", Const, 0}, + {"SIOCSIFDESCR", Const, 0}, + {"SIOCSIFDSTADDR", Const, 0}, + {"SIOCSIFENCAP", Const, 0}, + {"SIOCSIFFIB", Const, 1}, + {"SIOCSIFFLAGS", Const, 0}, + {"SIOCSIFGATTR", Const, 1}, + {"SIOCSIFGENERIC", Const, 0}, + {"SIOCSIFHWADDR", Const, 0}, + {"SIOCSIFHWBROADCAST", Const, 0}, + {"SIOCSIFKPI", Const, 0}, + {"SIOCSIFLINK", Const, 0}, + {"SIOCSIFLLADDR", Const, 0}, + {"SIOCSIFMAC", Const, 0}, + {"SIOCSIFMAP", Const, 0}, + {"SIOCSIFMEDIA", Const, 0}, + {"SIOCSIFMEM", Const, 0}, + {"SIOCSIFMETRIC", Const, 0}, + {"SIOCSIFMTU", Const, 0}, + {"SIOCSIFNAME", Const, 0}, + {"SIOCSIFNETMASK", Const, 0}, + {"SIOCSIFPFLAGS", Const, 0}, + {"SIOCSIFPHYADDR", Const, 0}, + {"SIOCSIFPHYS", Const, 0}, + {"SIOCSIFPRIORITY", Const, 1}, + {"SIOCSIFRDOMAIN", Const, 1}, + {"SIOCSIFRTLABEL", Const, 1}, + {"SIOCSIFRVNET", Const, 0}, + {"SIOCSIFSLAVE", Const, 0}, + {"SIOCSIFTIMESLOT", Const, 1}, + {"SIOCSIFTXQLEN", Const, 0}, + {"SIOCSIFVLAN", Const, 0}, + {"SIOCSIFVNET", Const, 0}, + {"SIOCSIFXFLAGS", Const, 1}, + {"SIOCSLIFPHYADDR", Const, 0}, + {"SIOCSLIFPHYRTABLE", Const, 1}, + {"SIOCSLIFPHYTTL", Const, 3}, + {"SIOCSLINKSTR", Const, 1}, + {"SIOCSLOWAT", Const, 0}, + {"SIOCSPGRP", Const, 0}, + {"SIOCSRARP", Const, 0}, + {"SIOCSSPPPPARAMS", Const, 3}, + {"SIOCSVH", Const, 1}, + {"SIOCSVNETID", Const, 3}, + {"SIOCZIFDATA", Const, 1}, + {"SIO_GET_EXTENSION_FUNCTION_POINTER", Const, 1}, + {"SIO_GET_INTERFACE_LIST", Const, 0}, + {"SIO_KEEPALIVE_VALS", Const, 3}, + {"SIO_UDP_CONNRESET", Const, 4}, + {"SOCK_CLOEXEC", Const, 0}, + {"SOCK_DCCP", Const, 0}, + {"SOCK_DGRAM", Const, 0}, + {"SOCK_FLAGS_MASK", Const, 1}, + {"SOCK_MAXADDRLEN", Const, 0}, + {"SOCK_NONBLOCK", Const, 0}, + {"SOCK_NOSIGPIPE", Const, 1}, + {"SOCK_PACKET", Const, 0}, + {"SOCK_RAW", Const, 0}, + {"SOCK_RDM", Const, 0}, + {"SOCK_SEQPACKET", Const, 0}, + {"SOCK_STREAM", Const, 0}, + {"SOL_AAL", Const, 0}, + {"SOL_ATM", Const, 0}, + {"SOL_DECNET", Const, 0}, + {"SOL_ICMPV6", Const, 0}, + {"SOL_IP", Const, 0}, + {"SOL_IPV6", Const, 0}, + {"SOL_IRDA", Const, 0}, + {"SOL_PACKET", Const, 0}, + {"SOL_RAW", Const, 0}, + {"SOL_SOCKET", Const, 0}, + {"SOL_TCP", Const, 0}, + {"SOL_X25", Const, 0}, + {"SOMAXCONN", Const, 0}, + {"SO_ACCEPTCONN", Const, 0}, + {"SO_ACCEPTFILTER", Const, 0}, + {"SO_ATTACH_FILTER", Const, 0}, + {"SO_BINDANY", Const, 1}, + {"SO_BINDTODEVICE", Const, 0}, + {"SO_BINTIME", Const, 0}, + {"SO_BROADCAST", Const, 0}, + {"SO_BSDCOMPAT", Const, 0}, + {"SO_DEBUG", Const, 0}, + {"SO_DETACH_FILTER", Const, 0}, + {"SO_DOMAIN", Const, 0}, + {"SO_DONTROUTE", Const, 0}, + {"SO_DONTTRUNC", Const, 0}, + {"SO_ERROR", Const, 0}, + {"SO_KEEPALIVE", Const, 0}, + {"SO_LABEL", Const, 0}, + {"SO_LINGER", Const, 0}, + {"SO_LINGER_SEC", Const, 0}, + {"SO_LISTENINCQLEN", Const, 0}, + {"SO_LISTENQLEN", Const, 0}, + {"SO_LISTENQLIMIT", Const, 0}, + {"SO_MARK", Const, 0}, + {"SO_NETPROC", Const, 1}, + {"SO_NKE", Const, 0}, + {"SO_NOADDRERR", Const, 0}, + {"SO_NOHEADER", Const, 1}, + {"SO_NOSIGPIPE", Const, 0}, + {"SO_NOTIFYCONFLICT", Const, 0}, + {"SO_NO_CHECK", Const, 0}, + {"SO_NO_DDP", Const, 0}, + {"SO_NO_OFFLOAD", Const, 0}, + {"SO_NP_EXTENSIONS", Const, 0}, + {"SO_NREAD", Const, 0}, + {"SO_NUMRCVPKT", Const, 16}, + {"SO_NWRITE", Const, 0}, + {"SO_OOBINLINE", Const, 0}, + {"SO_OVERFLOWED", Const, 1}, + {"SO_PASSCRED", Const, 0}, + {"SO_PASSSEC", Const, 0}, + {"SO_PEERCRED", Const, 0}, + {"SO_PEERLABEL", Const, 0}, + {"SO_PEERNAME", Const, 0}, + {"SO_PEERSEC", Const, 0}, + {"SO_PRIORITY", Const, 0}, + {"SO_PROTOCOL", Const, 0}, + {"SO_PROTOTYPE", Const, 1}, + {"SO_RANDOMPORT", Const, 0}, + {"SO_RCVBUF", Const, 0}, + {"SO_RCVBUFFORCE", Const, 0}, + {"SO_RCVLOWAT", Const, 0}, + {"SO_RCVTIMEO", Const, 0}, + {"SO_RESTRICTIONS", Const, 0}, + {"SO_RESTRICT_DENYIN", Const, 0}, + {"SO_RESTRICT_DENYOUT", Const, 0}, + {"SO_RESTRICT_DENYSET", Const, 0}, + {"SO_REUSEADDR", Const, 0}, + {"SO_REUSEPORT", Const, 0}, + {"SO_REUSESHAREUID", Const, 0}, + {"SO_RTABLE", Const, 1}, + {"SO_RXQ_OVFL", Const, 0}, + {"SO_SECURITY_AUTHENTICATION", Const, 0}, + {"SO_SECURITY_ENCRYPTION_NETWORK", Const, 0}, + {"SO_SECURITY_ENCRYPTION_TRANSPORT", Const, 0}, + {"SO_SETFIB", Const, 0}, + {"SO_SNDBUF", Const, 0}, + {"SO_SNDBUFFORCE", Const, 0}, + {"SO_SNDLOWAT", Const, 0}, + {"SO_SNDTIMEO", Const, 0}, + {"SO_SPLICE", Const, 1}, + {"SO_TIMESTAMP", Const, 0}, + {"SO_TIMESTAMPING", Const, 0}, + {"SO_TIMESTAMPNS", Const, 0}, + {"SO_TIMESTAMP_MONOTONIC", Const, 0}, + {"SO_TYPE", Const, 0}, + {"SO_UPCALLCLOSEWAIT", Const, 0}, + {"SO_UPDATE_ACCEPT_CONTEXT", Const, 0}, + {"SO_UPDATE_CONNECT_CONTEXT", Const, 1}, + {"SO_USELOOPBACK", Const, 0}, + {"SO_USER_COOKIE", Const, 1}, + {"SO_VENDOR", Const, 3}, + {"SO_WANTMORE", Const, 0}, + {"SO_WANTOOBFLAG", Const, 0}, + {"SSLExtraCertChainPolicyPara", Type, 0}, + {"SSLExtraCertChainPolicyPara.AuthType", Field, 0}, + {"SSLExtraCertChainPolicyPara.Checks", Field, 0}, + {"SSLExtraCertChainPolicyPara.ServerName", Field, 0}, + {"SSLExtraCertChainPolicyPara.Size", Field, 0}, + {"STANDARD_RIGHTS_ALL", Const, 0}, + {"STANDARD_RIGHTS_EXECUTE", Const, 0}, + {"STANDARD_RIGHTS_READ", Const, 0}, + {"STANDARD_RIGHTS_REQUIRED", Const, 0}, + {"STANDARD_RIGHTS_WRITE", Const, 0}, + {"STARTF_USESHOWWINDOW", Const, 0}, + {"STARTF_USESTDHANDLES", Const, 0}, + {"STD_ERROR_HANDLE", Const, 0}, + {"STD_INPUT_HANDLE", Const, 0}, + {"STD_OUTPUT_HANDLE", Const, 0}, + {"SUBLANG_ENGLISH_US", Const, 0}, + {"SW_FORCEMINIMIZE", Const, 0}, + {"SW_HIDE", Const, 0}, + {"SW_MAXIMIZE", Const, 0}, + {"SW_MINIMIZE", Const, 0}, + {"SW_NORMAL", Const, 0}, + {"SW_RESTORE", Const, 0}, + {"SW_SHOW", Const, 0}, + {"SW_SHOWDEFAULT", Const, 0}, + {"SW_SHOWMAXIMIZED", Const, 0}, + {"SW_SHOWMINIMIZED", Const, 0}, + {"SW_SHOWMINNOACTIVE", Const, 0}, + {"SW_SHOWNA", Const, 0}, + {"SW_SHOWNOACTIVATE", Const, 0}, + {"SW_SHOWNORMAL", Const, 0}, + {"SYMBOLIC_LINK_FLAG_DIRECTORY", Const, 4}, + {"SYNCHRONIZE", Const, 0}, + {"SYSCTL_VERSION", Const, 1}, + {"SYSCTL_VERS_0", Const, 1}, + {"SYSCTL_VERS_1", Const, 1}, + {"SYSCTL_VERS_MASK", Const, 1}, + {"SYS_ABORT2", Const, 0}, + {"SYS_ACCEPT", Const, 0}, + {"SYS_ACCEPT4", Const, 0}, + {"SYS_ACCEPT_NOCANCEL", Const, 0}, + {"SYS_ACCESS", Const, 0}, + {"SYS_ACCESS_EXTENDED", Const, 0}, + {"SYS_ACCT", Const, 0}, + {"SYS_ADD_KEY", Const, 0}, + {"SYS_ADD_PROFIL", Const, 0}, + {"SYS_ADJFREQ", Const, 1}, + {"SYS_ADJTIME", Const, 0}, + {"SYS_ADJTIMEX", Const, 0}, + {"SYS_AFS_SYSCALL", Const, 0}, + {"SYS_AIO_CANCEL", Const, 0}, + {"SYS_AIO_ERROR", Const, 0}, + {"SYS_AIO_FSYNC", Const, 0}, + {"SYS_AIO_MLOCK", Const, 14}, + {"SYS_AIO_READ", Const, 0}, + {"SYS_AIO_RETURN", Const, 0}, + {"SYS_AIO_SUSPEND", Const, 0}, + {"SYS_AIO_SUSPEND_NOCANCEL", Const, 0}, + {"SYS_AIO_WAITCOMPLETE", Const, 14}, + {"SYS_AIO_WRITE", Const, 0}, + {"SYS_ALARM", Const, 0}, + {"SYS_ARCH_PRCTL", Const, 0}, + {"SYS_ARM_FADVISE64_64", Const, 0}, + {"SYS_ARM_SYNC_FILE_RANGE", Const, 0}, + {"SYS_ATGETMSG", Const, 0}, + {"SYS_ATPGETREQ", Const, 0}, + {"SYS_ATPGETRSP", Const, 0}, + {"SYS_ATPSNDREQ", Const, 0}, + {"SYS_ATPSNDRSP", Const, 0}, + {"SYS_ATPUTMSG", Const, 0}, + {"SYS_ATSOCKET", Const, 0}, + {"SYS_AUDIT", Const, 0}, + {"SYS_AUDITCTL", Const, 0}, + {"SYS_AUDITON", Const, 0}, + {"SYS_AUDIT_SESSION_JOIN", Const, 0}, + {"SYS_AUDIT_SESSION_PORT", Const, 0}, + {"SYS_AUDIT_SESSION_SELF", Const, 0}, + {"SYS_BDFLUSH", Const, 0}, + {"SYS_BIND", Const, 0}, + {"SYS_BINDAT", Const, 3}, + {"SYS_BREAK", Const, 0}, + {"SYS_BRK", Const, 0}, + {"SYS_BSDTHREAD_CREATE", Const, 0}, + {"SYS_BSDTHREAD_REGISTER", Const, 0}, + {"SYS_BSDTHREAD_TERMINATE", Const, 0}, + {"SYS_CAPGET", Const, 0}, + {"SYS_CAPSET", Const, 0}, + {"SYS_CAP_ENTER", Const, 0}, + {"SYS_CAP_FCNTLS_GET", Const, 1}, + {"SYS_CAP_FCNTLS_LIMIT", Const, 1}, + {"SYS_CAP_GETMODE", Const, 0}, + {"SYS_CAP_GETRIGHTS", Const, 0}, + {"SYS_CAP_IOCTLS_GET", Const, 1}, + {"SYS_CAP_IOCTLS_LIMIT", Const, 1}, + {"SYS_CAP_NEW", Const, 0}, + {"SYS_CAP_RIGHTS_GET", Const, 1}, + {"SYS_CAP_RIGHTS_LIMIT", Const, 1}, + {"SYS_CHDIR", Const, 0}, + {"SYS_CHFLAGS", Const, 0}, + {"SYS_CHFLAGSAT", Const, 3}, + {"SYS_CHMOD", Const, 0}, + {"SYS_CHMOD_EXTENDED", Const, 0}, + {"SYS_CHOWN", Const, 0}, + {"SYS_CHOWN32", Const, 0}, + {"SYS_CHROOT", Const, 0}, + {"SYS_CHUD", Const, 0}, + {"SYS_CLOCK_ADJTIME", Const, 0}, + {"SYS_CLOCK_GETCPUCLOCKID2", Const, 1}, + {"SYS_CLOCK_GETRES", Const, 0}, + {"SYS_CLOCK_GETTIME", Const, 0}, + {"SYS_CLOCK_NANOSLEEP", Const, 0}, + {"SYS_CLOCK_SETTIME", Const, 0}, + {"SYS_CLONE", Const, 0}, + {"SYS_CLOSE", Const, 0}, + {"SYS_CLOSEFROM", Const, 0}, + {"SYS_CLOSE_NOCANCEL", Const, 0}, + {"SYS_CONNECT", Const, 0}, + {"SYS_CONNECTAT", Const, 3}, + {"SYS_CONNECT_NOCANCEL", Const, 0}, + {"SYS_COPYFILE", Const, 0}, + {"SYS_CPUSET", Const, 0}, + {"SYS_CPUSET_GETAFFINITY", Const, 0}, + {"SYS_CPUSET_GETID", Const, 0}, + {"SYS_CPUSET_SETAFFINITY", Const, 0}, + {"SYS_CPUSET_SETID", Const, 0}, + {"SYS_CREAT", Const, 0}, + {"SYS_CREATE_MODULE", Const, 0}, + {"SYS_CSOPS", Const, 0}, + {"SYS_CSOPS_AUDITTOKEN", Const, 16}, + {"SYS_DELETE", Const, 0}, + {"SYS_DELETE_MODULE", Const, 0}, + {"SYS_DUP", Const, 0}, + {"SYS_DUP2", Const, 0}, + {"SYS_DUP3", Const, 0}, + {"SYS_EACCESS", Const, 0}, + {"SYS_EPOLL_CREATE", Const, 0}, + {"SYS_EPOLL_CREATE1", Const, 0}, + {"SYS_EPOLL_CTL", Const, 0}, + {"SYS_EPOLL_CTL_OLD", Const, 0}, + {"SYS_EPOLL_PWAIT", Const, 0}, + {"SYS_EPOLL_WAIT", Const, 0}, + {"SYS_EPOLL_WAIT_OLD", Const, 0}, + {"SYS_EVENTFD", Const, 0}, + {"SYS_EVENTFD2", Const, 0}, + {"SYS_EXCHANGEDATA", Const, 0}, + {"SYS_EXECVE", Const, 0}, + {"SYS_EXIT", Const, 0}, + {"SYS_EXIT_GROUP", Const, 0}, + {"SYS_EXTATTRCTL", Const, 0}, + {"SYS_EXTATTR_DELETE_FD", Const, 0}, + {"SYS_EXTATTR_DELETE_FILE", Const, 0}, + {"SYS_EXTATTR_DELETE_LINK", Const, 0}, + {"SYS_EXTATTR_GET_FD", Const, 0}, + {"SYS_EXTATTR_GET_FILE", Const, 0}, + {"SYS_EXTATTR_GET_LINK", Const, 0}, + {"SYS_EXTATTR_LIST_FD", Const, 0}, + {"SYS_EXTATTR_LIST_FILE", Const, 0}, + {"SYS_EXTATTR_LIST_LINK", Const, 0}, + {"SYS_EXTATTR_SET_FD", Const, 0}, + {"SYS_EXTATTR_SET_FILE", Const, 0}, + {"SYS_EXTATTR_SET_LINK", Const, 0}, + {"SYS_FACCESSAT", Const, 0}, + {"SYS_FADVISE64", Const, 0}, + {"SYS_FADVISE64_64", Const, 0}, + {"SYS_FALLOCATE", Const, 0}, + {"SYS_FANOTIFY_INIT", Const, 0}, + {"SYS_FANOTIFY_MARK", Const, 0}, + {"SYS_FCHDIR", Const, 0}, + {"SYS_FCHFLAGS", Const, 0}, + {"SYS_FCHMOD", Const, 0}, + {"SYS_FCHMODAT", Const, 0}, + {"SYS_FCHMOD_EXTENDED", Const, 0}, + {"SYS_FCHOWN", Const, 0}, + {"SYS_FCHOWN32", Const, 0}, + {"SYS_FCHOWNAT", Const, 0}, + {"SYS_FCHROOT", Const, 1}, + {"SYS_FCNTL", Const, 0}, + {"SYS_FCNTL64", Const, 0}, + {"SYS_FCNTL_NOCANCEL", Const, 0}, + {"SYS_FDATASYNC", Const, 0}, + {"SYS_FEXECVE", Const, 0}, + {"SYS_FFCLOCK_GETCOUNTER", Const, 0}, + {"SYS_FFCLOCK_GETESTIMATE", Const, 0}, + {"SYS_FFCLOCK_SETESTIMATE", Const, 0}, + {"SYS_FFSCTL", Const, 0}, + {"SYS_FGETATTRLIST", Const, 0}, + {"SYS_FGETXATTR", Const, 0}, + {"SYS_FHOPEN", Const, 0}, + {"SYS_FHSTAT", Const, 0}, + {"SYS_FHSTATFS", Const, 0}, + {"SYS_FILEPORT_MAKEFD", Const, 0}, + {"SYS_FILEPORT_MAKEPORT", Const, 0}, + {"SYS_FKTRACE", Const, 1}, + {"SYS_FLISTXATTR", Const, 0}, + {"SYS_FLOCK", Const, 0}, + {"SYS_FORK", Const, 0}, + {"SYS_FPATHCONF", Const, 0}, + {"SYS_FREEBSD6_FTRUNCATE", Const, 0}, + {"SYS_FREEBSD6_LSEEK", Const, 0}, + {"SYS_FREEBSD6_MMAP", Const, 0}, + {"SYS_FREEBSD6_PREAD", Const, 0}, + {"SYS_FREEBSD6_PWRITE", Const, 0}, + {"SYS_FREEBSD6_TRUNCATE", Const, 0}, + {"SYS_FREMOVEXATTR", Const, 0}, + {"SYS_FSCTL", Const, 0}, + {"SYS_FSETATTRLIST", Const, 0}, + {"SYS_FSETXATTR", Const, 0}, + {"SYS_FSGETPATH", Const, 0}, + {"SYS_FSTAT", Const, 0}, + {"SYS_FSTAT64", Const, 0}, + {"SYS_FSTAT64_EXTENDED", Const, 0}, + {"SYS_FSTATAT", Const, 0}, + {"SYS_FSTATAT64", Const, 0}, + {"SYS_FSTATFS", Const, 0}, + {"SYS_FSTATFS64", Const, 0}, + {"SYS_FSTATV", Const, 0}, + {"SYS_FSTATVFS1", Const, 1}, + {"SYS_FSTAT_EXTENDED", Const, 0}, + {"SYS_FSYNC", Const, 0}, + {"SYS_FSYNC_NOCANCEL", Const, 0}, + {"SYS_FSYNC_RANGE", Const, 1}, + {"SYS_FTIME", Const, 0}, + {"SYS_FTRUNCATE", Const, 0}, + {"SYS_FTRUNCATE64", Const, 0}, + {"SYS_FUTEX", Const, 0}, + {"SYS_FUTIMENS", Const, 1}, + {"SYS_FUTIMES", Const, 0}, + {"SYS_FUTIMESAT", Const, 0}, + {"SYS_GETATTRLIST", Const, 0}, + {"SYS_GETAUDIT", Const, 0}, + {"SYS_GETAUDIT_ADDR", Const, 0}, + {"SYS_GETAUID", Const, 0}, + {"SYS_GETCONTEXT", Const, 0}, + {"SYS_GETCPU", Const, 0}, + {"SYS_GETCWD", Const, 0}, + {"SYS_GETDENTS", Const, 0}, + {"SYS_GETDENTS64", Const, 0}, + {"SYS_GETDIRENTRIES", Const, 0}, + {"SYS_GETDIRENTRIES64", Const, 0}, + {"SYS_GETDIRENTRIESATTR", Const, 0}, + {"SYS_GETDTABLECOUNT", Const, 1}, + {"SYS_GETDTABLESIZE", Const, 0}, + {"SYS_GETEGID", Const, 0}, + {"SYS_GETEGID32", Const, 0}, + {"SYS_GETEUID", Const, 0}, + {"SYS_GETEUID32", Const, 0}, + {"SYS_GETFH", Const, 0}, + {"SYS_GETFSSTAT", Const, 0}, + {"SYS_GETFSSTAT64", Const, 0}, + {"SYS_GETGID", Const, 0}, + {"SYS_GETGID32", Const, 0}, + {"SYS_GETGROUPS", Const, 0}, + {"SYS_GETGROUPS32", Const, 0}, + {"SYS_GETHOSTUUID", Const, 0}, + {"SYS_GETITIMER", Const, 0}, + {"SYS_GETLCID", Const, 0}, + {"SYS_GETLOGIN", Const, 0}, + {"SYS_GETLOGINCLASS", Const, 0}, + {"SYS_GETPEERNAME", Const, 0}, + {"SYS_GETPGID", Const, 0}, + {"SYS_GETPGRP", Const, 0}, + {"SYS_GETPID", Const, 0}, + {"SYS_GETPMSG", Const, 0}, + {"SYS_GETPPID", Const, 0}, + {"SYS_GETPRIORITY", Const, 0}, + {"SYS_GETRESGID", Const, 0}, + {"SYS_GETRESGID32", Const, 0}, + {"SYS_GETRESUID", Const, 0}, + {"SYS_GETRESUID32", Const, 0}, + {"SYS_GETRLIMIT", Const, 0}, + {"SYS_GETRTABLE", Const, 1}, + {"SYS_GETRUSAGE", Const, 0}, + {"SYS_GETSGROUPS", Const, 0}, + {"SYS_GETSID", Const, 0}, + {"SYS_GETSOCKNAME", Const, 0}, + {"SYS_GETSOCKOPT", Const, 0}, + {"SYS_GETTHRID", Const, 1}, + {"SYS_GETTID", Const, 0}, + {"SYS_GETTIMEOFDAY", Const, 0}, + {"SYS_GETUID", Const, 0}, + {"SYS_GETUID32", Const, 0}, + {"SYS_GETVFSSTAT", Const, 1}, + {"SYS_GETWGROUPS", Const, 0}, + {"SYS_GETXATTR", Const, 0}, + {"SYS_GET_KERNEL_SYMS", Const, 0}, + {"SYS_GET_MEMPOLICY", Const, 0}, + {"SYS_GET_ROBUST_LIST", Const, 0}, + {"SYS_GET_THREAD_AREA", Const, 0}, + {"SYS_GSSD_SYSCALL", Const, 14}, + {"SYS_GTTY", Const, 0}, + {"SYS_IDENTITYSVC", Const, 0}, + {"SYS_IDLE", Const, 0}, + {"SYS_INITGROUPS", Const, 0}, + {"SYS_INIT_MODULE", Const, 0}, + {"SYS_INOTIFY_ADD_WATCH", Const, 0}, + {"SYS_INOTIFY_INIT", Const, 0}, + {"SYS_INOTIFY_INIT1", Const, 0}, + {"SYS_INOTIFY_RM_WATCH", Const, 0}, + {"SYS_IOCTL", Const, 0}, + {"SYS_IOPERM", Const, 0}, + {"SYS_IOPL", Const, 0}, + {"SYS_IOPOLICYSYS", Const, 0}, + {"SYS_IOPRIO_GET", Const, 0}, + {"SYS_IOPRIO_SET", Const, 0}, + {"SYS_IO_CANCEL", Const, 0}, + {"SYS_IO_DESTROY", Const, 0}, + {"SYS_IO_GETEVENTS", Const, 0}, + {"SYS_IO_SETUP", Const, 0}, + {"SYS_IO_SUBMIT", Const, 0}, + {"SYS_IPC", Const, 0}, + {"SYS_ISSETUGID", Const, 0}, + {"SYS_JAIL", Const, 0}, + {"SYS_JAIL_ATTACH", Const, 0}, + {"SYS_JAIL_GET", Const, 0}, + {"SYS_JAIL_REMOVE", Const, 0}, + {"SYS_JAIL_SET", Const, 0}, + {"SYS_KAS_INFO", Const, 16}, + {"SYS_KDEBUG_TRACE", Const, 0}, + {"SYS_KENV", Const, 0}, + {"SYS_KEVENT", Const, 0}, + {"SYS_KEVENT64", Const, 0}, + {"SYS_KEXEC_LOAD", Const, 0}, + {"SYS_KEYCTL", Const, 0}, + {"SYS_KILL", Const, 0}, + {"SYS_KLDFIND", Const, 0}, + {"SYS_KLDFIRSTMOD", Const, 0}, + {"SYS_KLDLOAD", Const, 0}, + {"SYS_KLDNEXT", Const, 0}, + {"SYS_KLDSTAT", Const, 0}, + {"SYS_KLDSYM", Const, 0}, + {"SYS_KLDUNLOAD", Const, 0}, + {"SYS_KLDUNLOADF", Const, 0}, + {"SYS_KMQ_NOTIFY", Const, 14}, + {"SYS_KMQ_OPEN", Const, 14}, + {"SYS_KMQ_SETATTR", Const, 14}, + {"SYS_KMQ_TIMEDRECEIVE", Const, 14}, + {"SYS_KMQ_TIMEDSEND", Const, 14}, + {"SYS_KMQ_UNLINK", Const, 14}, + {"SYS_KQUEUE", Const, 0}, + {"SYS_KQUEUE1", Const, 1}, + {"SYS_KSEM_CLOSE", Const, 14}, + {"SYS_KSEM_DESTROY", Const, 14}, + {"SYS_KSEM_GETVALUE", Const, 14}, + {"SYS_KSEM_INIT", Const, 14}, + {"SYS_KSEM_OPEN", Const, 14}, + {"SYS_KSEM_POST", Const, 14}, + {"SYS_KSEM_TIMEDWAIT", Const, 14}, + {"SYS_KSEM_TRYWAIT", Const, 14}, + {"SYS_KSEM_UNLINK", Const, 14}, + {"SYS_KSEM_WAIT", Const, 14}, + {"SYS_KTIMER_CREATE", Const, 0}, + {"SYS_KTIMER_DELETE", Const, 0}, + {"SYS_KTIMER_GETOVERRUN", Const, 0}, + {"SYS_KTIMER_GETTIME", Const, 0}, + {"SYS_KTIMER_SETTIME", Const, 0}, + {"SYS_KTRACE", Const, 0}, + {"SYS_LCHFLAGS", Const, 0}, + {"SYS_LCHMOD", Const, 0}, + {"SYS_LCHOWN", Const, 0}, + {"SYS_LCHOWN32", Const, 0}, + {"SYS_LEDGER", Const, 16}, + {"SYS_LGETFH", Const, 0}, + {"SYS_LGETXATTR", Const, 0}, + {"SYS_LINK", Const, 0}, + {"SYS_LINKAT", Const, 0}, + {"SYS_LIO_LISTIO", Const, 0}, + {"SYS_LISTEN", Const, 0}, + {"SYS_LISTXATTR", Const, 0}, + {"SYS_LLISTXATTR", Const, 0}, + {"SYS_LOCK", Const, 0}, + {"SYS_LOOKUP_DCOOKIE", Const, 0}, + {"SYS_LPATHCONF", Const, 0}, + {"SYS_LREMOVEXATTR", Const, 0}, + {"SYS_LSEEK", Const, 0}, + {"SYS_LSETXATTR", Const, 0}, + {"SYS_LSTAT", Const, 0}, + {"SYS_LSTAT64", Const, 0}, + {"SYS_LSTAT64_EXTENDED", Const, 0}, + {"SYS_LSTATV", Const, 0}, + {"SYS_LSTAT_EXTENDED", Const, 0}, + {"SYS_LUTIMES", Const, 0}, + {"SYS_MAC_SYSCALL", Const, 0}, + {"SYS_MADVISE", Const, 0}, + {"SYS_MADVISE1", Const, 0}, + {"SYS_MAXSYSCALL", Const, 0}, + {"SYS_MBIND", Const, 0}, + {"SYS_MIGRATE_PAGES", Const, 0}, + {"SYS_MINCORE", Const, 0}, + {"SYS_MINHERIT", Const, 0}, + {"SYS_MKCOMPLEX", Const, 0}, + {"SYS_MKDIR", Const, 0}, + {"SYS_MKDIRAT", Const, 0}, + {"SYS_MKDIR_EXTENDED", Const, 0}, + {"SYS_MKFIFO", Const, 0}, + {"SYS_MKFIFOAT", Const, 0}, + {"SYS_MKFIFO_EXTENDED", Const, 0}, + {"SYS_MKNOD", Const, 0}, + {"SYS_MKNODAT", Const, 0}, + {"SYS_MLOCK", Const, 0}, + {"SYS_MLOCKALL", Const, 0}, + {"SYS_MMAP", Const, 0}, + {"SYS_MMAP2", Const, 0}, + {"SYS_MODCTL", Const, 1}, + {"SYS_MODFIND", Const, 0}, + {"SYS_MODFNEXT", Const, 0}, + {"SYS_MODIFY_LDT", Const, 0}, + {"SYS_MODNEXT", Const, 0}, + {"SYS_MODSTAT", Const, 0}, + {"SYS_MODWATCH", Const, 0}, + {"SYS_MOUNT", Const, 0}, + {"SYS_MOVE_PAGES", Const, 0}, + {"SYS_MPROTECT", Const, 0}, + {"SYS_MPX", Const, 0}, + {"SYS_MQUERY", Const, 1}, + {"SYS_MQ_GETSETATTR", Const, 0}, + {"SYS_MQ_NOTIFY", Const, 0}, + {"SYS_MQ_OPEN", Const, 0}, + {"SYS_MQ_TIMEDRECEIVE", Const, 0}, + {"SYS_MQ_TIMEDSEND", Const, 0}, + {"SYS_MQ_UNLINK", Const, 0}, + {"SYS_MREMAP", Const, 0}, + {"SYS_MSGCTL", Const, 0}, + {"SYS_MSGGET", Const, 0}, + {"SYS_MSGRCV", Const, 0}, + {"SYS_MSGRCV_NOCANCEL", Const, 0}, + {"SYS_MSGSND", Const, 0}, + {"SYS_MSGSND_NOCANCEL", Const, 0}, + {"SYS_MSGSYS", Const, 0}, + {"SYS_MSYNC", Const, 0}, + {"SYS_MSYNC_NOCANCEL", Const, 0}, + {"SYS_MUNLOCK", Const, 0}, + {"SYS_MUNLOCKALL", Const, 0}, + {"SYS_MUNMAP", Const, 0}, + {"SYS_NAME_TO_HANDLE_AT", Const, 0}, + {"SYS_NANOSLEEP", Const, 0}, + {"SYS_NEWFSTATAT", Const, 0}, + {"SYS_NFSCLNT", Const, 0}, + {"SYS_NFSSERVCTL", Const, 0}, + {"SYS_NFSSVC", Const, 0}, + {"SYS_NFSTAT", Const, 0}, + {"SYS_NICE", Const, 0}, + {"SYS_NLM_SYSCALL", Const, 14}, + {"SYS_NLSTAT", Const, 0}, + {"SYS_NMOUNT", Const, 0}, + {"SYS_NSTAT", Const, 0}, + {"SYS_NTP_ADJTIME", Const, 0}, + {"SYS_NTP_GETTIME", Const, 0}, + {"SYS_NUMA_GETAFFINITY", Const, 14}, + {"SYS_NUMA_SETAFFINITY", Const, 14}, + {"SYS_OABI_SYSCALL_BASE", Const, 0}, + {"SYS_OBREAK", Const, 0}, + {"SYS_OLDFSTAT", Const, 0}, + {"SYS_OLDLSTAT", Const, 0}, + {"SYS_OLDOLDUNAME", Const, 0}, + {"SYS_OLDSTAT", Const, 0}, + {"SYS_OLDUNAME", Const, 0}, + {"SYS_OPEN", Const, 0}, + {"SYS_OPENAT", Const, 0}, + {"SYS_OPENBSD_POLL", Const, 0}, + {"SYS_OPEN_BY_HANDLE_AT", Const, 0}, + {"SYS_OPEN_DPROTECTED_NP", Const, 16}, + {"SYS_OPEN_EXTENDED", Const, 0}, + {"SYS_OPEN_NOCANCEL", Const, 0}, + {"SYS_OVADVISE", Const, 0}, + {"SYS_PACCEPT", Const, 1}, + {"SYS_PATHCONF", Const, 0}, + {"SYS_PAUSE", Const, 0}, + {"SYS_PCICONFIG_IOBASE", Const, 0}, + {"SYS_PCICONFIG_READ", Const, 0}, + {"SYS_PCICONFIG_WRITE", Const, 0}, + {"SYS_PDFORK", Const, 0}, + {"SYS_PDGETPID", Const, 0}, + {"SYS_PDKILL", Const, 0}, + {"SYS_PERF_EVENT_OPEN", Const, 0}, + {"SYS_PERSONALITY", Const, 0}, + {"SYS_PID_HIBERNATE", Const, 0}, + {"SYS_PID_RESUME", Const, 0}, + {"SYS_PID_SHUTDOWN_SOCKETS", Const, 0}, + {"SYS_PID_SUSPEND", Const, 0}, + {"SYS_PIPE", Const, 0}, + {"SYS_PIPE2", Const, 0}, + {"SYS_PIVOT_ROOT", Const, 0}, + {"SYS_PMC_CONTROL", Const, 1}, + {"SYS_PMC_GET_INFO", Const, 1}, + {"SYS_POLL", Const, 0}, + {"SYS_POLLTS", Const, 1}, + {"SYS_POLL_NOCANCEL", Const, 0}, + {"SYS_POSIX_FADVISE", Const, 0}, + {"SYS_POSIX_FALLOCATE", Const, 0}, + {"SYS_POSIX_OPENPT", Const, 0}, + {"SYS_POSIX_SPAWN", Const, 0}, + {"SYS_PPOLL", Const, 0}, + {"SYS_PRCTL", Const, 0}, + {"SYS_PREAD", Const, 0}, + {"SYS_PREAD64", Const, 0}, + {"SYS_PREADV", Const, 0}, + {"SYS_PREAD_NOCANCEL", Const, 0}, + {"SYS_PRLIMIT64", Const, 0}, + {"SYS_PROCCTL", Const, 3}, + {"SYS_PROCESS_POLICY", Const, 0}, + {"SYS_PROCESS_VM_READV", Const, 0}, + {"SYS_PROCESS_VM_WRITEV", Const, 0}, + {"SYS_PROC_INFO", Const, 0}, + {"SYS_PROF", Const, 0}, + {"SYS_PROFIL", Const, 0}, + {"SYS_PSELECT", Const, 0}, + {"SYS_PSELECT6", Const, 0}, + {"SYS_PSET_ASSIGN", Const, 1}, + {"SYS_PSET_CREATE", Const, 1}, + {"SYS_PSET_DESTROY", Const, 1}, + {"SYS_PSYNCH_CVBROAD", Const, 0}, + {"SYS_PSYNCH_CVCLRPREPOST", Const, 0}, + {"SYS_PSYNCH_CVSIGNAL", Const, 0}, + {"SYS_PSYNCH_CVWAIT", Const, 0}, + {"SYS_PSYNCH_MUTEXDROP", Const, 0}, + {"SYS_PSYNCH_MUTEXWAIT", Const, 0}, + {"SYS_PSYNCH_RW_DOWNGRADE", Const, 0}, + {"SYS_PSYNCH_RW_LONGRDLOCK", Const, 0}, + {"SYS_PSYNCH_RW_RDLOCK", Const, 0}, + {"SYS_PSYNCH_RW_UNLOCK", Const, 0}, + {"SYS_PSYNCH_RW_UNLOCK2", Const, 0}, + {"SYS_PSYNCH_RW_UPGRADE", Const, 0}, + {"SYS_PSYNCH_RW_WRLOCK", Const, 0}, + {"SYS_PSYNCH_RW_YIELDWRLOCK", Const, 0}, + {"SYS_PTRACE", Const, 0}, + {"SYS_PUTPMSG", Const, 0}, + {"SYS_PWRITE", Const, 0}, + {"SYS_PWRITE64", Const, 0}, + {"SYS_PWRITEV", Const, 0}, + {"SYS_PWRITE_NOCANCEL", Const, 0}, + {"SYS_QUERY_MODULE", Const, 0}, + {"SYS_QUOTACTL", Const, 0}, + {"SYS_RASCTL", Const, 1}, + {"SYS_RCTL_ADD_RULE", Const, 0}, + {"SYS_RCTL_GET_LIMITS", Const, 0}, + {"SYS_RCTL_GET_RACCT", Const, 0}, + {"SYS_RCTL_GET_RULES", Const, 0}, + {"SYS_RCTL_REMOVE_RULE", Const, 0}, + {"SYS_READ", Const, 0}, + {"SYS_READAHEAD", Const, 0}, + {"SYS_READDIR", Const, 0}, + {"SYS_READLINK", Const, 0}, + {"SYS_READLINKAT", Const, 0}, + {"SYS_READV", Const, 0}, + {"SYS_READV_NOCANCEL", Const, 0}, + {"SYS_READ_NOCANCEL", Const, 0}, + {"SYS_REBOOT", Const, 0}, + {"SYS_RECV", Const, 0}, + {"SYS_RECVFROM", Const, 0}, + {"SYS_RECVFROM_NOCANCEL", Const, 0}, + {"SYS_RECVMMSG", Const, 0}, + {"SYS_RECVMSG", Const, 0}, + {"SYS_RECVMSG_NOCANCEL", Const, 0}, + {"SYS_REMAP_FILE_PAGES", Const, 0}, + {"SYS_REMOVEXATTR", Const, 0}, + {"SYS_RENAME", Const, 0}, + {"SYS_RENAMEAT", Const, 0}, + {"SYS_REQUEST_KEY", Const, 0}, + {"SYS_RESTART_SYSCALL", Const, 0}, + {"SYS_REVOKE", Const, 0}, + {"SYS_RFORK", Const, 0}, + {"SYS_RMDIR", Const, 0}, + {"SYS_RTPRIO", Const, 0}, + {"SYS_RTPRIO_THREAD", Const, 0}, + {"SYS_RT_SIGACTION", Const, 0}, + {"SYS_RT_SIGPENDING", Const, 0}, + {"SYS_RT_SIGPROCMASK", Const, 0}, + {"SYS_RT_SIGQUEUEINFO", Const, 0}, + {"SYS_RT_SIGRETURN", Const, 0}, + {"SYS_RT_SIGSUSPEND", Const, 0}, + {"SYS_RT_SIGTIMEDWAIT", Const, 0}, + {"SYS_RT_TGSIGQUEUEINFO", Const, 0}, + {"SYS_SBRK", Const, 0}, + {"SYS_SCHED_GETAFFINITY", Const, 0}, + {"SYS_SCHED_GETPARAM", Const, 0}, + {"SYS_SCHED_GETSCHEDULER", Const, 0}, + {"SYS_SCHED_GET_PRIORITY_MAX", Const, 0}, + {"SYS_SCHED_GET_PRIORITY_MIN", Const, 0}, + {"SYS_SCHED_RR_GET_INTERVAL", Const, 0}, + {"SYS_SCHED_SETAFFINITY", Const, 0}, + {"SYS_SCHED_SETPARAM", Const, 0}, + {"SYS_SCHED_SETSCHEDULER", Const, 0}, + {"SYS_SCHED_YIELD", Const, 0}, + {"SYS_SCTP_GENERIC_RECVMSG", Const, 0}, + {"SYS_SCTP_GENERIC_SENDMSG", Const, 0}, + {"SYS_SCTP_GENERIC_SENDMSG_IOV", Const, 0}, + {"SYS_SCTP_PEELOFF", Const, 0}, + {"SYS_SEARCHFS", Const, 0}, + {"SYS_SECURITY", Const, 0}, + {"SYS_SELECT", Const, 0}, + {"SYS_SELECT_NOCANCEL", Const, 0}, + {"SYS_SEMCONFIG", Const, 1}, + {"SYS_SEMCTL", Const, 0}, + {"SYS_SEMGET", Const, 0}, + {"SYS_SEMOP", Const, 0}, + {"SYS_SEMSYS", Const, 0}, + {"SYS_SEMTIMEDOP", Const, 0}, + {"SYS_SEM_CLOSE", Const, 0}, + {"SYS_SEM_DESTROY", Const, 0}, + {"SYS_SEM_GETVALUE", Const, 0}, + {"SYS_SEM_INIT", Const, 0}, + {"SYS_SEM_OPEN", Const, 0}, + {"SYS_SEM_POST", Const, 0}, + {"SYS_SEM_TRYWAIT", Const, 0}, + {"SYS_SEM_UNLINK", Const, 0}, + {"SYS_SEM_WAIT", Const, 0}, + {"SYS_SEM_WAIT_NOCANCEL", Const, 0}, + {"SYS_SEND", Const, 0}, + {"SYS_SENDFILE", Const, 0}, + {"SYS_SENDFILE64", Const, 0}, + {"SYS_SENDMMSG", Const, 0}, + {"SYS_SENDMSG", Const, 0}, + {"SYS_SENDMSG_NOCANCEL", Const, 0}, + {"SYS_SENDTO", Const, 0}, + {"SYS_SENDTO_NOCANCEL", Const, 0}, + {"SYS_SETATTRLIST", Const, 0}, + {"SYS_SETAUDIT", Const, 0}, + {"SYS_SETAUDIT_ADDR", Const, 0}, + {"SYS_SETAUID", Const, 0}, + {"SYS_SETCONTEXT", Const, 0}, + {"SYS_SETDOMAINNAME", Const, 0}, + {"SYS_SETEGID", Const, 0}, + {"SYS_SETEUID", Const, 0}, + {"SYS_SETFIB", Const, 0}, + {"SYS_SETFSGID", Const, 0}, + {"SYS_SETFSGID32", Const, 0}, + {"SYS_SETFSUID", Const, 0}, + {"SYS_SETFSUID32", Const, 0}, + {"SYS_SETGID", Const, 0}, + {"SYS_SETGID32", Const, 0}, + {"SYS_SETGROUPS", Const, 0}, + {"SYS_SETGROUPS32", Const, 0}, + {"SYS_SETHOSTNAME", Const, 0}, + {"SYS_SETITIMER", Const, 0}, + {"SYS_SETLCID", Const, 0}, + {"SYS_SETLOGIN", Const, 0}, + {"SYS_SETLOGINCLASS", Const, 0}, + {"SYS_SETNS", Const, 0}, + {"SYS_SETPGID", Const, 0}, + {"SYS_SETPRIORITY", Const, 0}, + {"SYS_SETPRIVEXEC", Const, 0}, + {"SYS_SETREGID", Const, 0}, + {"SYS_SETREGID32", Const, 0}, + {"SYS_SETRESGID", Const, 0}, + {"SYS_SETRESGID32", Const, 0}, + {"SYS_SETRESUID", Const, 0}, + {"SYS_SETRESUID32", Const, 0}, + {"SYS_SETREUID", Const, 0}, + {"SYS_SETREUID32", Const, 0}, + {"SYS_SETRLIMIT", Const, 0}, + {"SYS_SETRTABLE", Const, 1}, + {"SYS_SETSGROUPS", Const, 0}, + {"SYS_SETSID", Const, 0}, + {"SYS_SETSOCKOPT", Const, 0}, + {"SYS_SETTID", Const, 0}, + {"SYS_SETTID_WITH_PID", Const, 0}, + {"SYS_SETTIMEOFDAY", Const, 0}, + {"SYS_SETUID", Const, 0}, + {"SYS_SETUID32", Const, 0}, + {"SYS_SETWGROUPS", Const, 0}, + {"SYS_SETXATTR", Const, 0}, + {"SYS_SET_MEMPOLICY", Const, 0}, + {"SYS_SET_ROBUST_LIST", Const, 0}, + {"SYS_SET_THREAD_AREA", Const, 0}, + {"SYS_SET_TID_ADDRESS", Const, 0}, + {"SYS_SGETMASK", Const, 0}, + {"SYS_SHARED_REGION_CHECK_NP", Const, 0}, + {"SYS_SHARED_REGION_MAP_AND_SLIDE_NP", Const, 0}, + {"SYS_SHMAT", Const, 0}, + {"SYS_SHMCTL", Const, 0}, + {"SYS_SHMDT", Const, 0}, + {"SYS_SHMGET", Const, 0}, + {"SYS_SHMSYS", Const, 0}, + {"SYS_SHM_OPEN", Const, 0}, + {"SYS_SHM_UNLINK", Const, 0}, + {"SYS_SHUTDOWN", Const, 0}, + {"SYS_SIGACTION", Const, 0}, + {"SYS_SIGALTSTACK", Const, 0}, + {"SYS_SIGNAL", Const, 0}, + {"SYS_SIGNALFD", Const, 0}, + {"SYS_SIGNALFD4", Const, 0}, + {"SYS_SIGPENDING", Const, 0}, + {"SYS_SIGPROCMASK", Const, 0}, + {"SYS_SIGQUEUE", Const, 0}, + {"SYS_SIGQUEUEINFO", Const, 1}, + {"SYS_SIGRETURN", Const, 0}, + {"SYS_SIGSUSPEND", Const, 0}, + {"SYS_SIGSUSPEND_NOCANCEL", Const, 0}, + {"SYS_SIGTIMEDWAIT", Const, 0}, + {"SYS_SIGWAIT", Const, 0}, + {"SYS_SIGWAITINFO", Const, 0}, + {"SYS_SOCKET", Const, 0}, + {"SYS_SOCKETCALL", Const, 0}, + {"SYS_SOCKETPAIR", Const, 0}, + {"SYS_SPLICE", Const, 0}, + {"SYS_SSETMASK", Const, 0}, + {"SYS_SSTK", Const, 0}, + {"SYS_STACK_SNAPSHOT", Const, 0}, + {"SYS_STAT", Const, 0}, + {"SYS_STAT64", Const, 0}, + {"SYS_STAT64_EXTENDED", Const, 0}, + {"SYS_STATFS", Const, 0}, + {"SYS_STATFS64", Const, 0}, + {"SYS_STATV", Const, 0}, + {"SYS_STATVFS1", Const, 1}, + {"SYS_STAT_EXTENDED", Const, 0}, + {"SYS_STIME", Const, 0}, + {"SYS_STTY", Const, 0}, + {"SYS_SWAPCONTEXT", Const, 0}, + {"SYS_SWAPCTL", Const, 1}, + {"SYS_SWAPOFF", Const, 0}, + {"SYS_SWAPON", Const, 0}, + {"SYS_SYMLINK", Const, 0}, + {"SYS_SYMLINKAT", Const, 0}, + {"SYS_SYNC", Const, 0}, + {"SYS_SYNCFS", Const, 0}, + {"SYS_SYNC_FILE_RANGE", Const, 0}, + {"SYS_SYSARCH", Const, 0}, + {"SYS_SYSCALL", Const, 0}, + {"SYS_SYSCALL_BASE", Const, 0}, + {"SYS_SYSFS", Const, 0}, + {"SYS_SYSINFO", Const, 0}, + {"SYS_SYSLOG", Const, 0}, + {"SYS_TEE", Const, 0}, + {"SYS_TGKILL", Const, 0}, + {"SYS_THREAD_SELFID", Const, 0}, + {"SYS_THR_CREATE", Const, 0}, + {"SYS_THR_EXIT", Const, 0}, + {"SYS_THR_KILL", Const, 0}, + {"SYS_THR_KILL2", Const, 0}, + {"SYS_THR_NEW", Const, 0}, + {"SYS_THR_SELF", Const, 0}, + {"SYS_THR_SET_NAME", Const, 0}, + {"SYS_THR_SUSPEND", Const, 0}, + {"SYS_THR_WAKE", Const, 0}, + {"SYS_TIME", Const, 0}, + {"SYS_TIMERFD_CREATE", Const, 0}, + {"SYS_TIMERFD_GETTIME", Const, 0}, + {"SYS_TIMERFD_SETTIME", Const, 0}, + {"SYS_TIMER_CREATE", Const, 0}, + {"SYS_TIMER_DELETE", Const, 0}, + {"SYS_TIMER_GETOVERRUN", Const, 0}, + {"SYS_TIMER_GETTIME", Const, 0}, + {"SYS_TIMER_SETTIME", Const, 0}, + {"SYS_TIMES", Const, 0}, + {"SYS_TKILL", Const, 0}, + {"SYS_TRUNCATE", Const, 0}, + {"SYS_TRUNCATE64", Const, 0}, + {"SYS_TUXCALL", Const, 0}, + {"SYS_UGETRLIMIT", Const, 0}, + {"SYS_ULIMIT", Const, 0}, + {"SYS_UMASK", Const, 0}, + {"SYS_UMASK_EXTENDED", Const, 0}, + {"SYS_UMOUNT", Const, 0}, + {"SYS_UMOUNT2", Const, 0}, + {"SYS_UNAME", Const, 0}, + {"SYS_UNDELETE", Const, 0}, + {"SYS_UNLINK", Const, 0}, + {"SYS_UNLINKAT", Const, 0}, + {"SYS_UNMOUNT", Const, 0}, + {"SYS_UNSHARE", Const, 0}, + {"SYS_USELIB", Const, 0}, + {"SYS_USTAT", Const, 0}, + {"SYS_UTIME", Const, 0}, + {"SYS_UTIMENSAT", Const, 0}, + {"SYS_UTIMES", Const, 0}, + {"SYS_UTRACE", Const, 0}, + {"SYS_UUIDGEN", Const, 0}, + {"SYS_VADVISE", Const, 1}, + {"SYS_VFORK", Const, 0}, + {"SYS_VHANGUP", Const, 0}, + {"SYS_VM86", Const, 0}, + {"SYS_VM86OLD", Const, 0}, + {"SYS_VMSPLICE", Const, 0}, + {"SYS_VM_PRESSURE_MONITOR", Const, 0}, + {"SYS_VSERVER", Const, 0}, + {"SYS_WAIT4", Const, 0}, + {"SYS_WAIT4_NOCANCEL", Const, 0}, + {"SYS_WAIT6", Const, 1}, + {"SYS_WAITEVENT", Const, 0}, + {"SYS_WAITID", Const, 0}, + {"SYS_WAITID_NOCANCEL", Const, 0}, + {"SYS_WAITPID", Const, 0}, + {"SYS_WATCHEVENT", Const, 0}, + {"SYS_WORKQ_KERNRETURN", Const, 0}, + {"SYS_WORKQ_OPEN", Const, 0}, + {"SYS_WRITE", Const, 0}, + {"SYS_WRITEV", Const, 0}, + {"SYS_WRITEV_NOCANCEL", Const, 0}, + {"SYS_WRITE_NOCANCEL", Const, 0}, + {"SYS_YIELD", Const, 0}, + {"SYS__LLSEEK", Const, 0}, + {"SYS__LWP_CONTINUE", Const, 1}, + {"SYS__LWP_CREATE", Const, 1}, + {"SYS__LWP_CTL", Const, 1}, + {"SYS__LWP_DETACH", Const, 1}, + {"SYS__LWP_EXIT", Const, 1}, + {"SYS__LWP_GETNAME", Const, 1}, + {"SYS__LWP_GETPRIVATE", Const, 1}, + {"SYS__LWP_KILL", Const, 1}, + {"SYS__LWP_PARK", Const, 1}, + {"SYS__LWP_SELF", Const, 1}, + {"SYS__LWP_SETNAME", Const, 1}, + {"SYS__LWP_SETPRIVATE", Const, 1}, + {"SYS__LWP_SUSPEND", Const, 1}, + {"SYS__LWP_UNPARK", Const, 1}, + {"SYS__LWP_UNPARK_ALL", Const, 1}, + {"SYS__LWP_WAIT", Const, 1}, + {"SYS__LWP_WAKEUP", Const, 1}, + {"SYS__NEWSELECT", Const, 0}, + {"SYS__PSET_BIND", Const, 1}, + {"SYS__SCHED_GETAFFINITY", Const, 1}, + {"SYS__SCHED_GETPARAM", Const, 1}, + {"SYS__SCHED_SETAFFINITY", Const, 1}, + {"SYS__SCHED_SETPARAM", Const, 1}, + {"SYS__SYSCTL", Const, 0}, + {"SYS__UMTX_LOCK", Const, 0}, + {"SYS__UMTX_OP", Const, 0}, + {"SYS__UMTX_UNLOCK", Const, 0}, + {"SYS___ACL_ACLCHECK_FD", Const, 0}, + {"SYS___ACL_ACLCHECK_FILE", Const, 0}, + {"SYS___ACL_ACLCHECK_LINK", Const, 0}, + {"SYS___ACL_DELETE_FD", Const, 0}, + {"SYS___ACL_DELETE_FILE", Const, 0}, + {"SYS___ACL_DELETE_LINK", Const, 0}, + {"SYS___ACL_GET_FD", Const, 0}, + {"SYS___ACL_GET_FILE", Const, 0}, + {"SYS___ACL_GET_LINK", Const, 0}, + {"SYS___ACL_SET_FD", Const, 0}, + {"SYS___ACL_SET_FILE", Const, 0}, + {"SYS___ACL_SET_LINK", Const, 0}, + {"SYS___CAP_RIGHTS_GET", Const, 14}, + {"SYS___CLONE", Const, 1}, + {"SYS___DISABLE_THREADSIGNAL", Const, 0}, + {"SYS___GETCWD", Const, 0}, + {"SYS___GETLOGIN", Const, 1}, + {"SYS___GET_TCB", Const, 1}, + {"SYS___MAC_EXECVE", Const, 0}, + {"SYS___MAC_GETFSSTAT", Const, 0}, + {"SYS___MAC_GET_FD", Const, 0}, + {"SYS___MAC_GET_FILE", Const, 0}, + {"SYS___MAC_GET_LCID", Const, 0}, + {"SYS___MAC_GET_LCTX", Const, 0}, + {"SYS___MAC_GET_LINK", Const, 0}, + {"SYS___MAC_GET_MOUNT", Const, 0}, + {"SYS___MAC_GET_PID", Const, 0}, + {"SYS___MAC_GET_PROC", Const, 0}, + {"SYS___MAC_MOUNT", Const, 0}, + {"SYS___MAC_SET_FD", Const, 0}, + {"SYS___MAC_SET_FILE", Const, 0}, + {"SYS___MAC_SET_LCTX", Const, 0}, + {"SYS___MAC_SET_LINK", Const, 0}, + {"SYS___MAC_SET_PROC", Const, 0}, + {"SYS___MAC_SYSCALL", Const, 0}, + {"SYS___OLD_SEMWAIT_SIGNAL", Const, 0}, + {"SYS___OLD_SEMWAIT_SIGNAL_NOCANCEL", Const, 0}, + {"SYS___POSIX_CHOWN", Const, 1}, + {"SYS___POSIX_FCHOWN", Const, 1}, + {"SYS___POSIX_LCHOWN", Const, 1}, + {"SYS___POSIX_RENAME", Const, 1}, + {"SYS___PTHREAD_CANCELED", Const, 0}, + {"SYS___PTHREAD_CHDIR", Const, 0}, + {"SYS___PTHREAD_FCHDIR", Const, 0}, + {"SYS___PTHREAD_KILL", Const, 0}, + {"SYS___PTHREAD_MARKCANCEL", Const, 0}, + {"SYS___PTHREAD_SIGMASK", Const, 0}, + {"SYS___QUOTACTL", Const, 1}, + {"SYS___SEMCTL", Const, 1}, + {"SYS___SEMWAIT_SIGNAL", Const, 0}, + {"SYS___SEMWAIT_SIGNAL_NOCANCEL", Const, 0}, + {"SYS___SETLOGIN", Const, 1}, + {"SYS___SETUGID", Const, 0}, + {"SYS___SET_TCB", Const, 1}, + {"SYS___SIGACTION_SIGTRAMP", Const, 1}, + {"SYS___SIGTIMEDWAIT", Const, 1}, + {"SYS___SIGWAIT", Const, 0}, + {"SYS___SIGWAIT_NOCANCEL", Const, 0}, + {"SYS___SYSCTL", Const, 0}, + {"SYS___TFORK", Const, 1}, + {"SYS___THREXIT", Const, 1}, + {"SYS___THRSIGDIVERT", Const, 1}, + {"SYS___THRSLEEP", Const, 1}, + {"SYS___THRWAKEUP", Const, 1}, + {"S_ARCH1", Const, 1}, + {"S_ARCH2", Const, 1}, + {"S_BLKSIZE", Const, 0}, + {"S_IEXEC", Const, 0}, + {"S_IFBLK", Const, 0}, + {"S_IFCHR", Const, 0}, + {"S_IFDIR", Const, 0}, + {"S_IFIFO", Const, 0}, + {"S_IFLNK", Const, 0}, + {"S_IFMT", Const, 0}, + {"S_IFREG", Const, 0}, + {"S_IFSOCK", Const, 0}, + {"S_IFWHT", Const, 0}, + {"S_IREAD", Const, 0}, + {"S_IRGRP", Const, 0}, + {"S_IROTH", Const, 0}, + {"S_IRUSR", Const, 0}, + {"S_IRWXG", Const, 0}, + {"S_IRWXO", Const, 0}, + {"S_IRWXU", Const, 0}, + {"S_ISGID", Const, 0}, + {"S_ISTXT", Const, 0}, + {"S_ISUID", Const, 0}, + {"S_ISVTX", Const, 0}, + {"S_IWGRP", Const, 0}, + {"S_IWOTH", Const, 0}, + {"S_IWRITE", Const, 0}, + {"S_IWUSR", Const, 0}, + {"S_IXGRP", Const, 0}, + {"S_IXOTH", Const, 0}, + {"S_IXUSR", Const, 0}, + {"S_LOGIN_SET", Const, 1}, + {"SecurityAttributes", Type, 0}, + {"SecurityAttributes.InheritHandle", Field, 0}, + {"SecurityAttributes.Length", Field, 0}, + {"SecurityAttributes.SecurityDescriptor", Field, 0}, + {"Seek", Func, 0}, + {"Select", Func, 0}, + {"Sendfile", Func, 0}, + {"Sendmsg", Func, 0}, + {"SendmsgN", Func, 3}, + {"Sendto", Func, 0}, + {"Servent", Type, 0}, + {"Servent.Aliases", Field, 0}, + {"Servent.Name", Field, 0}, + {"Servent.Port", Field, 0}, + {"Servent.Proto", Field, 0}, + {"SetBpf", Func, 0}, + {"SetBpfBuflen", Func, 0}, + {"SetBpfDatalink", Func, 0}, + {"SetBpfHeadercmpl", Func, 0}, + {"SetBpfImmediate", Func, 0}, + {"SetBpfInterface", Func, 0}, + {"SetBpfPromisc", Func, 0}, + {"SetBpfTimeout", Func, 0}, + {"SetCurrentDirectory", Func, 0}, + {"SetEndOfFile", Func, 0}, + {"SetEnvironmentVariable", Func, 0}, + {"SetFileAttributes", Func, 0}, + {"SetFileCompletionNotificationModes", Func, 2}, + {"SetFilePointer", Func, 0}, + {"SetFileTime", Func, 0}, + {"SetHandleInformation", Func, 0}, + {"SetKevent", Func, 0}, + {"SetLsfPromisc", Func, 0}, + {"SetNonblock", Func, 0}, + {"Setdomainname", Func, 0}, + {"Setegid", Func, 0}, + {"Setenv", Func, 0}, + {"Seteuid", Func, 0}, + {"Setfsgid", Func, 0}, + {"Setfsuid", Func, 0}, + {"Setgid", Func, 0}, + {"Setgroups", Func, 0}, + {"Sethostname", Func, 0}, + {"Setlogin", Func, 0}, + {"Setpgid", Func, 0}, + {"Setpriority", Func, 0}, + {"Setprivexec", Func, 0}, + {"Setregid", Func, 0}, + {"Setresgid", Func, 0}, + {"Setresuid", Func, 0}, + {"Setreuid", Func, 0}, + {"Setrlimit", Func, 0}, + {"Setsid", Func, 0}, + {"Setsockopt", Func, 0}, + {"SetsockoptByte", Func, 0}, + {"SetsockoptICMPv6Filter", Func, 2}, + {"SetsockoptIPMreq", Func, 0}, + {"SetsockoptIPMreqn", Func, 0}, + {"SetsockoptIPv6Mreq", Func, 0}, + {"SetsockoptInet4Addr", Func, 0}, + {"SetsockoptInt", Func, 0}, + {"SetsockoptLinger", Func, 0}, + {"SetsockoptString", Func, 0}, + {"SetsockoptTimeval", Func, 0}, + {"Settimeofday", Func, 0}, + {"Setuid", Func, 0}, + {"Setxattr", Func, 1}, + {"Shutdown", Func, 0}, + {"SidTypeAlias", Const, 0}, + {"SidTypeComputer", Const, 0}, + {"SidTypeDeletedAccount", Const, 0}, + {"SidTypeDomain", Const, 0}, + {"SidTypeGroup", Const, 0}, + {"SidTypeInvalid", Const, 0}, + {"SidTypeLabel", Const, 0}, + {"SidTypeUnknown", Const, 0}, + {"SidTypeUser", Const, 0}, + {"SidTypeWellKnownGroup", Const, 0}, + {"Signal", Type, 0}, + {"SizeofBpfHdr", Const, 0}, + {"SizeofBpfInsn", Const, 0}, + {"SizeofBpfProgram", Const, 0}, + {"SizeofBpfStat", Const, 0}, + {"SizeofBpfVersion", Const, 0}, + {"SizeofBpfZbuf", Const, 0}, + {"SizeofBpfZbufHeader", Const, 0}, + {"SizeofCmsghdr", Const, 0}, + {"SizeofICMPv6Filter", Const, 2}, + {"SizeofIPMreq", Const, 0}, + {"SizeofIPMreqn", Const, 0}, + {"SizeofIPv6MTUInfo", Const, 2}, + {"SizeofIPv6Mreq", Const, 0}, + {"SizeofIfAddrmsg", Const, 0}, + {"SizeofIfAnnounceMsghdr", Const, 1}, + {"SizeofIfData", Const, 0}, + {"SizeofIfInfomsg", Const, 0}, + {"SizeofIfMsghdr", Const, 0}, + {"SizeofIfaMsghdr", Const, 0}, + {"SizeofIfmaMsghdr", Const, 0}, + {"SizeofIfmaMsghdr2", Const, 0}, + {"SizeofInet4Pktinfo", Const, 0}, + {"SizeofInet6Pktinfo", Const, 0}, + {"SizeofInotifyEvent", Const, 0}, + {"SizeofLinger", Const, 0}, + {"SizeofMsghdr", Const, 0}, + {"SizeofNlAttr", Const, 0}, + {"SizeofNlMsgerr", Const, 0}, + {"SizeofNlMsghdr", Const, 0}, + {"SizeofRtAttr", Const, 0}, + {"SizeofRtGenmsg", Const, 0}, + {"SizeofRtMetrics", Const, 0}, + {"SizeofRtMsg", Const, 0}, + {"SizeofRtMsghdr", Const, 0}, + {"SizeofRtNexthop", Const, 0}, + {"SizeofSockFilter", Const, 0}, + {"SizeofSockFprog", Const, 0}, + {"SizeofSockaddrAny", Const, 0}, + {"SizeofSockaddrDatalink", Const, 0}, + {"SizeofSockaddrInet4", Const, 0}, + {"SizeofSockaddrInet6", Const, 0}, + {"SizeofSockaddrLinklayer", Const, 0}, + {"SizeofSockaddrNetlink", Const, 0}, + {"SizeofSockaddrUnix", Const, 0}, + {"SizeofTCPInfo", Const, 1}, + {"SizeofUcred", Const, 0}, + {"SlicePtrFromStrings", Func, 1}, + {"SockFilter", Type, 0}, + {"SockFilter.Code", Field, 0}, + {"SockFilter.Jf", Field, 0}, + {"SockFilter.Jt", Field, 0}, + {"SockFilter.K", Field, 0}, + {"SockFprog", Type, 0}, + {"SockFprog.Filter", Field, 0}, + {"SockFprog.Len", Field, 0}, + {"SockFprog.Pad_cgo_0", Field, 0}, + {"Sockaddr", Type, 0}, + {"SockaddrDatalink", Type, 0}, + {"SockaddrDatalink.Alen", Field, 0}, + {"SockaddrDatalink.Data", Field, 0}, + {"SockaddrDatalink.Family", Field, 0}, + {"SockaddrDatalink.Index", Field, 0}, + {"SockaddrDatalink.Len", Field, 0}, + {"SockaddrDatalink.Nlen", Field, 0}, + {"SockaddrDatalink.Slen", Field, 0}, + {"SockaddrDatalink.Type", Field, 0}, + {"SockaddrGen", Type, 0}, + {"SockaddrInet4", Type, 0}, + {"SockaddrInet4.Addr", Field, 0}, + {"SockaddrInet4.Port", Field, 0}, + {"SockaddrInet6", Type, 0}, + {"SockaddrInet6.Addr", Field, 0}, + {"SockaddrInet6.Port", Field, 0}, + {"SockaddrInet6.ZoneId", Field, 0}, + {"SockaddrLinklayer", Type, 0}, + {"SockaddrLinklayer.Addr", Field, 0}, + {"SockaddrLinklayer.Halen", Field, 0}, + {"SockaddrLinklayer.Hatype", Field, 0}, + {"SockaddrLinklayer.Ifindex", Field, 0}, + {"SockaddrLinklayer.Pkttype", Field, 0}, + {"SockaddrLinklayer.Protocol", Field, 0}, + {"SockaddrNetlink", Type, 0}, + {"SockaddrNetlink.Family", Field, 0}, + {"SockaddrNetlink.Groups", Field, 0}, + {"SockaddrNetlink.Pad", Field, 0}, + {"SockaddrNetlink.Pid", Field, 0}, + {"SockaddrUnix", Type, 0}, + {"SockaddrUnix.Name", Field, 0}, + {"Socket", Func, 0}, + {"SocketControlMessage", Type, 0}, + {"SocketControlMessage.Data", Field, 0}, + {"SocketControlMessage.Header", Field, 0}, + {"SocketDisableIPv6", Var, 0}, + {"Socketpair", Func, 0}, + {"Splice", Func, 0}, + {"StartProcess", Func, 0}, + {"StartupInfo", Type, 0}, + {"StartupInfo.Cb", Field, 0}, + {"StartupInfo.Desktop", Field, 0}, + {"StartupInfo.FillAttribute", Field, 0}, + {"StartupInfo.Flags", Field, 0}, + {"StartupInfo.ShowWindow", Field, 0}, + {"StartupInfo.StdErr", Field, 0}, + {"StartupInfo.StdInput", Field, 0}, + {"StartupInfo.StdOutput", Field, 0}, + {"StartupInfo.Title", Field, 0}, + {"StartupInfo.X", Field, 0}, + {"StartupInfo.XCountChars", Field, 0}, + {"StartupInfo.XSize", Field, 0}, + {"StartupInfo.Y", Field, 0}, + {"StartupInfo.YCountChars", Field, 0}, + {"StartupInfo.YSize", Field, 0}, + {"Stat", Func, 0}, + {"Stat_t", Type, 0}, + {"Stat_t.Atim", Field, 0}, + {"Stat_t.Atim_ext", Field, 12}, + {"Stat_t.Atimespec", Field, 0}, + {"Stat_t.Birthtimespec", Field, 0}, + {"Stat_t.Blksize", Field, 0}, + {"Stat_t.Blocks", Field, 0}, + {"Stat_t.Btim_ext", Field, 12}, + {"Stat_t.Ctim", Field, 0}, + {"Stat_t.Ctim_ext", Field, 12}, + {"Stat_t.Ctimespec", Field, 0}, + {"Stat_t.Dev", Field, 0}, + {"Stat_t.Flags", Field, 0}, + {"Stat_t.Gen", Field, 0}, + {"Stat_t.Gid", Field, 0}, + {"Stat_t.Ino", Field, 0}, + {"Stat_t.Lspare", Field, 0}, + {"Stat_t.Lspare0", Field, 2}, + {"Stat_t.Lspare1", Field, 2}, + {"Stat_t.Mode", Field, 0}, + {"Stat_t.Mtim", Field, 0}, + {"Stat_t.Mtim_ext", Field, 12}, + {"Stat_t.Mtimespec", Field, 0}, + {"Stat_t.Nlink", Field, 0}, + {"Stat_t.Pad_cgo_0", Field, 0}, + {"Stat_t.Pad_cgo_1", Field, 0}, + {"Stat_t.Pad_cgo_2", Field, 0}, + {"Stat_t.Padding0", Field, 12}, + {"Stat_t.Padding1", Field, 12}, + {"Stat_t.Qspare", Field, 0}, + {"Stat_t.Rdev", Field, 0}, + {"Stat_t.Size", Field, 0}, + {"Stat_t.Spare", Field, 2}, + {"Stat_t.Uid", Field, 0}, + {"Stat_t.X__pad0", Field, 0}, + {"Stat_t.X__pad1", Field, 0}, + {"Stat_t.X__pad2", Field, 0}, + {"Stat_t.X__st_birthtim", Field, 2}, + {"Stat_t.X__st_ino", Field, 0}, + {"Stat_t.X__unused", Field, 0}, + {"Statfs", Func, 0}, + {"Statfs_t", Type, 0}, + {"Statfs_t.Asyncreads", Field, 0}, + {"Statfs_t.Asyncwrites", Field, 0}, + {"Statfs_t.Bavail", Field, 0}, + {"Statfs_t.Bfree", Field, 0}, + {"Statfs_t.Blocks", Field, 0}, + {"Statfs_t.Bsize", Field, 0}, + {"Statfs_t.Charspare", Field, 0}, + {"Statfs_t.F_asyncreads", Field, 2}, + {"Statfs_t.F_asyncwrites", Field, 2}, + {"Statfs_t.F_bavail", Field, 2}, + {"Statfs_t.F_bfree", Field, 2}, + {"Statfs_t.F_blocks", Field, 2}, + {"Statfs_t.F_bsize", Field, 2}, + {"Statfs_t.F_ctime", Field, 2}, + {"Statfs_t.F_favail", Field, 2}, + {"Statfs_t.F_ffree", Field, 2}, + {"Statfs_t.F_files", Field, 2}, + {"Statfs_t.F_flags", Field, 2}, + {"Statfs_t.F_fsid", Field, 2}, + {"Statfs_t.F_fstypename", Field, 2}, + {"Statfs_t.F_iosize", Field, 2}, + {"Statfs_t.F_mntfromname", Field, 2}, + {"Statfs_t.F_mntfromspec", Field, 3}, + {"Statfs_t.F_mntonname", Field, 2}, + {"Statfs_t.F_namemax", Field, 2}, + {"Statfs_t.F_owner", Field, 2}, + {"Statfs_t.F_spare", Field, 2}, + {"Statfs_t.F_syncreads", Field, 2}, + {"Statfs_t.F_syncwrites", Field, 2}, + {"Statfs_t.Ffree", Field, 0}, + {"Statfs_t.Files", Field, 0}, + {"Statfs_t.Flags", Field, 0}, + {"Statfs_t.Frsize", Field, 0}, + {"Statfs_t.Fsid", Field, 0}, + {"Statfs_t.Fssubtype", Field, 0}, + {"Statfs_t.Fstypename", Field, 0}, + {"Statfs_t.Iosize", Field, 0}, + {"Statfs_t.Mntfromname", Field, 0}, + {"Statfs_t.Mntonname", Field, 0}, + {"Statfs_t.Mount_info", Field, 2}, + {"Statfs_t.Namelen", Field, 0}, + {"Statfs_t.Namemax", Field, 0}, + {"Statfs_t.Owner", Field, 0}, + {"Statfs_t.Pad_cgo_0", Field, 0}, + {"Statfs_t.Pad_cgo_1", Field, 2}, + {"Statfs_t.Reserved", Field, 0}, + {"Statfs_t.Spare", Field, 0}, + {"Statfs_t.Syncreads", Field, 0}, + {"Statfs_t.Syncwrites", Field, 0}, + {"Statfs_t.Type", Field, 0}, + {"Statfs_t.Version", Field, 0}, + {"Stderr", Var, 0}, + {"Stdin", Var, 0}, + {"Stdout", Var, 0}, + {"StringBytePtr", Func, 0}, + {"StringByteSlice", Func, 0}, + {"StringSlicePtr", Func, 0}, + {"StringToSid", Func, 0}, + {"StringToUTF16", Func, 0}, + {"StringToUTF16Ptr", Func, 0}, + {"Symlink", Func, 0}, + {"Sync", Func, 0}, + {"SyncFileRange", Func, 0}, + {"SysProcAttr", Type, 0}, + {"SysProcAttr.AdditionalInheritedHandles", Field, 17}, + {"SysProcAttr.AmbientCaps", Field, 9}, + {"SysProcAttr.CgroupFD", Field, 20}, + {"SysProcAttr.Chroot", Field, 0}, + {"SysProcAttr.Cloneflags", Field, 2}, + {"SysProcAttr.CmdLine", Field, 0}, + {"SysProcAttr.CreationFlags", Field, 1}, + {"SysProcAttr.Credential", Field, 0}, + {"SysProcAttr.Ctty", Field, 1}, + {"SysProcAttr.Foreground", Field, 5}, + {"SysProcAttr.GidMappings", Field, 4}, + {"SysProcAttr.GidMappingsEnableSetgroups", Field, 5}, + {"SysProcAttr.HideWindow", Field, 0}, + {"SysProcAttr.Jail", Field, 21}, + {"SysProcAttr.NoInheritHandles", Field, 16}, + {"SysProcAttr.Noctty", Field, 0}, + {"SysProcAttr.ParentProcess", Field, 17}, + {"SysProcAttr.Pdeathsig", Field, 0}, + {"SysProcAttr.Pgid", Field, 5}, + {"SysProcAttr.PidFD", Field, 22}, + {"SysProcAttr.ProcessAttributes", Field, 13}, + {"SysProcAttr.Ptrace", Field, 0}, + {"SysProcAttr.Setctty", Field, 0}, + {"SysProcAttr.Setpgid", Field, 0}, + {"SysProcAttr.Setsid", Field, 0}, + {"SysProcAttr.ThreadAttributes", Field, 13}, + {"SysProcAttr.Token", Field, 10}, + {"SysProcAttr.UidMappings", Field, 4}, + {"SysProcAttr.Unshareflags", Field, 7}, + {"SysProcAttr.UseCgroupFD", Field, 20}, + {"SysProcIDMap", Type, 4}, + {"SysProcIDMap.ContainerID", Field, 4}, + {"SysProcIDMap.HostID", Field, 4}, + {"SysProcIDMap.Size", Field, 4}, + {"Syscall", Func, 0}, + {"Syscall12", Func, 0}, + {"Syscall15", Func, 0}, + {"Syscall18", Func, 12}, + {"Syscall6", Func, 0}, + {"Syscall9", Func, 0}, + {"SyscallN", Func, 18}, + {"Sysctl", Func, 0}, + {"SysctlUint32", Func, 0}, + {"Sysctlnode", Type, 2}, + {"Sysctlnode.Flags", Field, 2}, + {"Sysctlnode.Name", Field, 2}, + {"Sysctlnode.Num", Field, 2}, + {"Sysctlnode.Un", Field, 2}, + {"Sysctlnode.Ver", Field, 2}, + {"Sysctlnode.X__rsvd", Field, 2}, + {"Sysctlnode.X_sysctl_desc", Field, 2}, + {"Sysctlnode.X_sysctl_func", Field, 2}, + {"Sysctlnode.X_sysctl_parent", Field, 2}, + {"Sysctlnode.X_sysctl_size", Field, 2}, + {"Sysinfo", Func, 0}, + {"Sysinfo_t", Type, 0}, + {"Sysinfo_t.Bufferram", Field, 0}, + {"Sysinfo_t.Freehigh", Field, 0}, + {"Sysinfo_t.Freeram", Field, 0}, + {"Sysinfo_t.Freeswap", Field, 0}, + {"Sysinfo_t.Loads", Field, 0}, + {"Sysinfo_t.Pad", Field, 0}, + {"Sysinfo_t.Pad_cgo_0", Field, 0}, + {"Sysinfo_t.Pad_cgo_1", Field, 0}, + {"Sysinfo_t.Procs", Field, 0}, + {"Sysinfo_t.Sharedram", Field, 0}, + {"Sysinfo_t.Totalhigh", Field, 0}, + {"Sysinfo_t.Totalram", Field, 0}, + {"Sysinfo_t.Totalswap", Field, 0}, + {"Sysinfo_t.Unit", Field, 0}, + {"Sysinfo_t.Uptime", Field, 0}, + {"Sysinfo_t.X_f", Field, 0}, + {"Systemtime", Type, 0}, + {"Systemtime.Day", Field, 0}, + {"Systemtime.DayOfWeek", Field, 0}, + {"Systemtime.Hour", Field, 0}, + {"Systemtime.Milliseconds", Field, 0}, + {"Systemtime.Minute", Field, 0}, + {"Systemtime.Month", Field, 0}, + {"Systemtime.Second", Field, 0}, + {"Systemtime.Year", Field, 0}, + {"TCGETS", Const, 0}, + {"TCIFLUSH", Const, 1}, + {"TCIOFLUSH", Const, 1}, + {"TCOFLUSH", Const, 1}, + {"TCPInfo", Type, 1}, + {"TCPInfo.Advmss", Field, 1}, + {"TCPInfo.Ato", Field, 1}, + {"TCPInfo.Backoff", Field, 1}, + {"TCPInfo.Ca_state", Field, 1}, + {"TCPInfo.Fackets", Field, 1}, + {"TCPInfo.Last_ack_recv", Field, 1}, + {"TCPInfo.Last_ack_sent", Field, 1}, + {"TCPInfo.Last_data_recv", Field, 1}, + {"TCPInfo.Last_data_sent", Field, 1}, + {"TCPInfo.Lost", Field, 1}, + {"TCPInfo.Options", Field, 1}, + {"TCPInfo.Pad_cgo_0", Field, 1}, + {"TCPInfo.Pmtu", Field, 1}, + {"TCPInfo.Probes", Field, 1}, + {"TCPInfo.Rcv_mss", Field, 1}, + {"TCPInfo.Rcv_rtt", Field, 1}, + {"TCPInfo.Rcv_space", Field, 1}, + {"TCPInfo.Rcv_ssthresh", Field, 1}, + {"TCPInfo.Reordering", Field, 1}, + {"TCPInfo.Retrans", Field, 1}, + {"TCPInfo.Retransmits", Field, 1}, + {"TCPInfo.Rto", Field, 1}, + {"TCPInfo.Rtt", Field, 1}, + {"TCPInfo.Rttvar", Field, 1}, + {"TCPInfo.Sacked", Field, 1}, + {"TCPInfo.Snd_cwnd", Field, 1}, + {"TCPInfo.Snd_mss", Field, 1}, + {"TCPInfo.Snd_ssthresh", Field, 1}, + {"TCPInfo.State", Field, 1}, + {"TCPInfo.Total_retrans", Field, 1}, + {"TCPInfo.Unacked", Field, 1}, + {"TCPKeepalive", Type, 3}, + {"TCPKeepalive.Interval", Field, 3}, + {"TCPKeepalive.OnOff", Field, 3}, + {"TCPKeepalive.Time", Field, 3}, + {"TCP_CA_NAME_MAX", Const, 0}, + {"TCP_CONGCTL", Const, 1}, + {"TCP_CONGESTION", Const, 0}, + {"TCP_CONNECTIONTIMEOUT", Const, 0}, + {"TCP_CORK", Const, 0}, + {"TCP_DEFER_ACCEPT", Const, 0}, + {"TCP_ENABLE_ECN", Const, 16}, + {"TCP_INFO", Const, 0}, + {"TCP_KEEPALIVE", Const, 0}, + {"TCP_KEEPCNT", Const, 0}, + {"TCP_KEEPIDLE", Const, 0}, + {"TCP_KEEPINIT", Const, 1}, + {"TCP_KEEPINTVL", Const, 0}, + {"TCP_LINGER2", Const, 0}, + {"TCP_MAXBURST", Const, 0}, + {"TCP_MAXHLEN", Const, 0}, + {"TCP_MAXOLEN", Const, 0}, + {"TCP_MAXSEG", Const, 0}, + {"TCP_MAXWIN", Const, 0}, + {"TCP_MAX_SACK", Const, 0}, + {"TCP_MAX_WINSHIFT", Const, 0}, + {"TCP_MD5SIG", Const, 0}, + {"TCP_MD5SIG_MAXKEYLEN", Const, 0}, + {"TCP_MINMSS", Const, 0}, + {"TCP_MINMSSOVERLOAD", Const, 0}, + {"TCP_MSS", Const, 0}, + {"TCP_NODELAY", Const, 0}, + {"TCP_NOOPT", Const, 0}, + {"TCP_NOPUSH", Const, 0}, + {"TCP_NOTSENT_LOWAT", Const, 16}, + {"TCP_NSTATES", Const, 1}, + {"TCP_QUICKACK", Const, 0}, + {"TCP_RXT_CONNDROPTIME", Const, 0}, + {"TCP_RXT_FINDROP", Const, 0}, + {"TCP_SACK_ENABLE", Const, 1}, + {"TCP_SENDMOREACKS", Const, 16}, + {"TCP_SYNCNT", Const, 0}, + {"TCP_VENDOR", Const, 3}, + {"TCP_WINDOW_CLAMP", Const, 0}, + {"TCSAFLUSH", Const, 1}, + {"TCSETS", Const, 0}, + {"TF_DISCONNECT", Const, 0}, + {"TF_REUSE_SOCKET", Const, 0}, + {"TF_USE_DEFAULT_WORKER", Const, 0}, + {"TF_USE_KERNEL_APC", Const, 0}, + {"TF_USE_SYSTEM_THREAD", Const, 0}, + {"TF_WRITE_BEHIND", Const, 0}, + {"TH32CS_INHERIT", Const, 4}, + {"TH32CS_SNAPALL", Const, 4}, + {"TH32CS_SNAPHEAPLIST", Const, 4}, + {"TH32CS_SNAPMODULE", Const, 4}, + {"TH32CS_SNAPMODULE32", Const, 4}, + {"TH32CS_SNAPPROCESS", Const, 4}, + {"TH32CS_SNAPTHREAD", Const, 4}, + {"TIME_ZONE_ID_DAYLIGHT", Const, 0}, + {"TIME_ZONE_ID_STANDARD", Const, 0}, + {"TIME_ZONE_ID_UNKNOWN", Const, 0}, + {"TIOCCBRK", Const, 0}, + {"TIOCCDTR", Const, 0}, + {"TIOCCONS", Const, 0}, + {"TIOCDCDTIMESTAMP", Const, 0}, + {"TIOCDRAIN", Const, 0}, + {"TIOCDSIMICROCODE", Const, 0}, + {"TIOCEXCL", Const, 0}, + {"TIOCEXT", Const, 0}, + {"TIOCFLAG_CDTRCTS", Const, 1}, + {"TIOCFLAG_CLOCAL", Const, 1}, + {"TIOCFLAG_CRTSCTS", Const, 1}, + {"TIOCFLAG_MDMBUF", Const, 1}, + {"TIOCFLAG_PPS", Const, 1}, + {"TIOCFLAG_SOFTCAR", Const, 1}, + {"TIOCFLUSH", Const, 0}, + {"TIOCGDEV", Const, 0}, + {"TIOCGDRAINWAIT", Const, 0}, + {"TIOCGETA", Const, 0}, + {"TIOCGETD", Const, 0}, + {"TIOCGFLAGS", Const, 1}, + {"TIOCGICOUNT", Const, 0}, + {"TIOCGLCKTRMIOS", Const, 0}, + {"TIOCGLINED", Const, 1}, + {"TIOCGPGRP", Const, 0}, + {"TIOCGPTN", Const, 0}, + {"TIOCGQSIZE", Const, 1}, + {"TIOCGRANTPT", Const, 1}, + {"TIOCGRS485", Const, 0}, + {"TIOCGSERIAL", Const, 0}, + {"TIOCGSID", Const, 0}, + {"TIOCGSIZE", Const, 1}, + {"TIOCGSOFTCAR", Const, 0}, + {"TIOCGTSTAMP", Const, 1}, + {"TIOCGWINSZ", Const, 0}, + {"TIOCINQ", Const, 0}, + {"TIOCIXOFF", Const, 0}, + {"TIOCIXON", Const, 0}, + {"TIOCLINUX", Const, 0}, + {"TIOCMBIC", Const, 0}, + {"TIOCMBIS", Const, 0}, + {"TIOCMGDTRWAIT", Const, 0}, + {"TIOCMGET", Const, 0}, + {"TIOCMIWAIT", Const, 0}, + {"TIOCMODG", Const, 0}, + {"TIOCMODS", Const, 0}, + {"TIOCMSDTRWAIT", Const, 0}, + {"TIOCMSET", Const, 0}, + {"TIOCM_CAR", Const, 0}, + {"TIOCM_CD", Const, 0}, + {"TIOCM_CTS", Const, 0}, + {"TIOCM_DCD", Const, 0}, + {"TIOCM_DSR", Const, 0}, + {"TIOCM_DTR", Const, 0}, + {"TIOCM_LE", Const, 0}, + {"TIOCM_RI", Const, 0}, + {"TIOCM_RNG", Const, 0}, + {"TIOCM_RTS", Const, 0}, + {"TIOCM_SR", Const, 0}, + {"TIOCM_ST", Const, 0}, + {"TIOCNOTTY", Const, 0}, + {"TIOCNXCL", Const, 0}, + {"TIOCOUTQ", Const, 0}, + {"TIOCPKT", Const, 0}, + {"TIOCPKT_DATA", Const, 0}, + {"TIOCPKT_DOSTOP", Const, 0}, + {"TIOCPKT_FLUSHREAD", Const, 0}, + {"TIOCPKT_FLUSHWRITE", Const, 0}, + {"TIOCPKT_IOCTL", Const, 0}, + {"TIOCPKT_NOSTOP", Const, 0}, + {"TIOCPKT_START", Const, 0}, + {"TIOCPKT_STOP", Const, 0}, + {"TIOCPTMASTER", Const, 0}, + {"TIOCPTMGET", Const, 1}, + {"TIOCPTSNAME", Const, 1}, + {"TIOCPTYGNAME", Const, 0}, + {"TIOCPTYGRANT", Const, 0}, + {"TIOCPTYUNLK", Const, 0}, + {"TIOCRCVFRAME", Const, 1}, + {"TIOCREMOTE", Const, 0}, + {"TIOCSBRK", Const, 0}, + {"TIOCSCONS", Const, 0}, + {"TIOCSCTTY", Const, 0}, + {"TIOCSDRAINWAIT", Const, 0}, + {"TIOCSDTR", Const, 0}, + {"TIOCSERCONFIG", Const, 0}, + {"TIOCSERGETLSR", Const, 0}, + {"TIOCSERGETMULTI", Const, 0}, + {"TIOCSERGSTRUCT", Const, 0}, + {"TIOCSERGWILD", Const, 0}, + {"TIOCSERSETMULTI", Const, 0}, + {"TIOCSERSWILD", Const, 0}, + {"TIOCSER_TEMT", Const, 0}, + {"TIOCSETA", Const, 0}, + {"TIOCSETAF", Const, 0}, + {"TIOCSETAW", Const, 0}, + {"TIOCSETD", Const, 0}, + {"TIOCSFLAGS", Const, 1}, + {"TIOCSIG", Const, 0}, + {"TIOCSLCKTRMIOS", Const, 0}, + {"TIOCSLINED", Const, 1}, + {"TIOCSPGRP", Const, 0}, + {"TIOCSPTLCK", Const, 0}, + {"TIOCSQSIZE", Const, 1}, + {"TIOCSRS485", Const, 0}, + {"TIOCSSERIAL", Const, 0}, + {"TIOCSSIZE", Const, 1}, + {"TIOCSSOFTCAR", Const, 0}, + {"TIOCSTART", Const, 0}, + {"TIOCSTAT", Const, 0}, + {"TIOCSTI", Const, 0}, + {"TIOCSTOP", Const, 0}, + {"TIOCSTSTAMP", Const, 1}, + {"TIOCSWINSZ", Const, 0}, + {"TIOCTIMESTAMP", Const, 0}, + {"TIOCUCNTL", Const, 0}, + {"TIOCVHANGUP", Const, 0}, + {"TIOCXMTFRAME", Const, 1}, + {"TOKEN_ADJUST_DEFAULT", Const, 0}, + {"TOKEN_ADJUST_GROUPS", Const, 0}, + {"TOKEN_ADJUST_PRIVILEGES", Const, 0}, + {"TOKEN_ADJUST_SESSIONID", Const, 11}, + {"TOKEN_ALL_ACCESS", Const, 0}, + {"TOKEN_ASSIGN_PRIMARY", Const, 0}, + {"TOKEN_DUPLICATE", Const, 0}, + {"TOKEN_EXECUTE", Const, 0}, + {"TOKEN_IMPERSONATE", Const, 0}, + {"TOKEN_QUERY", Const, 0}, + {"TOKEN_QUERY_SOURCE", Const, 0}, + {"TOKEN_READ", Const, 0}, + {"TOKEN_WRITE", Const, 0}, + {"TOSTOP", Const, 0}, + {"TRUNCATE_EXISTING", Const, 0}, + {"TUNATTACHFILTER", Const, 0}, + {"TUNDETACHFILTER", Const, 0}, + {"TUNGETFEATURES", Const, 0}, + {"TUNGETIFF", Const, 0}, + {"TUNGETSNDBUF", Const, 0}, + {"TUNGETVNETHDRSZ", Const, 0}, + {"TUNSETDEBUG", Const, 0}, + {"TUNSETGROUP", Const, 0}, + {"TUNSETIFF", Const, 0}, + {"TUNSETLINK", Const, 0}, + {"TUNSETNOCSUM", Const, 0}, + {"TUNSETOFFLOAD", Const, 0}, + {"TUNSETOWNER", Const, 0}, + {"TUNSETPERSIST", Const, 0}, + {"TUNSETSNDBUF", Const, 0}, + {"TUNSETTXFILTER", Const, 0}, + {"TUNSETVNETHDRSZ", Const, 0}, + {"Tee", Func, 0}, + {"TerminateProcess", Func, 0}, + {"Termios", Type, 0}, + {"Termios.Cc", Field, 0}, + {"Termios.Cflag", Field, 0}, + {"Termios.Iflag", Field, 0}, + {"Termios.Ispeed", Field, 0}, + {"Termios.Lflag", Field, 0}, + {"Termios.Line", Field, 0}, + {"Termios.Oflag", Field, 0}, + {"Termios.Ospeed", Field, 0}, + {"Termios.Pad_cgo_0", Field, 0}, + {"Tgkill", Func, 0}, + {"Time", Func, 0}, + {"Time_t", Type, 0}, + {"Times", Func, 0}, + {"Timespec", Type, 0}, + {"Timespec.Nsec", Field, 0}, + {"Timespec.Pad_cgo_0", Field, 2}, + {"Timespec.Sec", Field, 0}, + {"TimespecToNsec", Func, 0}, + {"Timeval", Type, 0}, + {"Timeval.Pad_cgo_0", Field, 0}, + {"Timeval.Sec", Field, 0}, + {"Timeval.Usec", Field, 0}, + {"Timeval32", Type, 0}, + {"Timeval32.Sec", Field, 0}, + {"Timeval32.Usec", Field, 0}, + {"TimevalToNsec", Func, 0}, + {"Timex", Type, 0}, + {"Timex.Calcnt", Field, 0}, + {"Timex.Constant", Field, 0}, + {"Timex.Errcnt", Field, 0}, + {"Timex.Esterror", Field, 0}, + {"Timex.Freq", Field, 0}, + {"Timex.Jitcnt", Field, 0}, + {"Timex.Jitter", Field, 0}, + {"Timex.Maxerror", Field, 0}, + {"Timex.Modes", Field, 0}, + {"Timex.Offset", Field, 0}, + {"Timex.Pad_cgo_0", Field, 0}, + {"Timex.Pad_cgo_1", Field, 0}, + {"Timex.Pad_cgo_2", Field, 0}, + {"Timex.Pad_cgo_3", Field, 0}, + {"Timex.Ppsfreq", Field, 0}, + {"Timex.Precision", Field, 0}, + {"Timex.Shift", Field, 0}, + {"Timex.Stabil", Field, 0}, + {"Timex.Status", Field, 0}, + {"Timex.Stbcnt", Field, 0}, + {"Timex.Tai", Field, 0}, + {"Timex.Tick", Field, 0}, + {"Timex.Time", Field, 0}, + {"Timex.Tolerance", Field, 0}, + {"Timezoneinformation", Type, 0}, + {"Timezoneinformation.Bias", Field, 0}, + {"Timezoneinformation.DaylightBias", Field, 0}, + {"Timezoneinformation.DaylightDate", Field, 0}, + {"Timezoneinformation.DaylightName", Field, 0}, + {"Timezoneinformation.StandardBias", Field, 0}, + {"Timezoneinformation.StandardDate", Field, 0}, + {"Timezoneinformation.StandardName", Field, 0}, + {"Tms", Type, 0}, + {"Tms.Cstime", Field, 0}, + {"Tms.Cutime", Field, 0}, + {"Tms.Stime", Field, 0}, + {"Tms.Utime", Field, 0}, + {"Token", Type, 0}, + {"TokenAccessInformation", Const, 0}, + {"TokenAuditPolicy", Const, 0}, + {"TokenDefaultDacl", Const, 0}, + {"TokenElevation", Const, 0}, + {"TokenElevationType", Const, 0}, + {"TokenGroups", Const, 0}, + {"TokenGroupsAndPrivileges", Const, 0}, + {"TokenHasRestrictions", Const, 0}, + {"TokenImpersonationLevel", Const, 0}, + {"TokenIntegrityLevel", Const, 0}, + {"TokenLinkedToken", Const, 0}, + {"TokenLogonSid", Const, 0}, + {"TokenMandatoryPolicy", Const, 0}, + {"TokenOrigin", Const, 0}, + {"TokenOwner", Const, 0}, + {"TokenPrimaryGroup", Const, 0}, + {"TokenPrivileges", Const, 0}, + {"TokenRestrictedSids", Const, 0}, + {"TokenSandBoxInert", Const, 0}, + {"TokenSessionId", Const, 0}, + {"TokenSessionReference", Const, 0}, + {"TokenSource", Const, 0}, + {"TokenStatistics", Const, 0}, + {"TokenType", Const, 0}, + {"TokenUIAccess", Const, 0}, + {"TokenUser", Const, 0}, + {"TokenVirtualizationAllowed", Const, 0}, + {"TokenVirtualizationEnabled", Const, 0}, + {"Tokenprimarygroup", Type, 0}, + {"Tokenprimarygroup.PrimaryGroup", Field, 0}, + {"Tokenuser", Type, 0}, + {"Tokenuser.User", Field, 0}, + {"TranslateAccountName", Func, 0}, + {"TranslateName", Func, 0}, + {"TransmitFile", Func, 0}, + {"TransmitFileBuffers", Type, 0}, + {"TransmitFileBuffers.Head", Field, 0}, + {"TransmitFileBuffers.HeadLength", Field, 0}, + {"TransmitFileBuffers.Tail", Field, 0}, + {"TransmitFileBuffers.TailLength", Field, 0}, + {"Truncate", Func, 0}, + {"UNIX_PATH_MAX", Const, 12}, + {"USAGE_MATCH_TYPE_AND", Const, 0}, + {"USAGE_MATCH_TYPE_OR", Const, 0}, + {"UTF16FromString", Func, 1}, + {"UTF16PtrFromString", Func, 1}, + {"UTF16ToString", Func, 0}, + {"Ucred", Type, 0}, + {"Ucred.Gid", Field, 0}, + {"Ucred.Pid", Field, 0}, + {"Ucred.Uid", Field, 0}, + {"Umask", Func, 0}, + {"Uname", Func, 0}, + {"Undelete", Func, 0}, + {"UnixCredentials", Func, 0}, + {"UnixRights", Func, 0}, + {"Unlink", Func, 0}, + {"Unlinkat", Func, 0}, + {"UnmapViewOfFile", Func, 0}, + {"Unmount", Func, 0}, + {"Unsetenv", Func, 4}, + {"Unshare", Func, 0}, + {"UserInfo10", Type, 0}, + {"UserInfo10.Comment", Field, 0}, + {"UserInfo10.FullName", Field, 0}, + {"UserInfo10.Name", Field, 0}, + {"UserInfo10.UsrComment", Field, 0}, + {"Ustat", Func, 0}, + {"Ustat_t", Type, 0}, + {"Ustat_t.Fname", Field, 0}, + {"Ustat_t.Fpack", Field, 0}, + {"Ustat_t.Pad_cgo_0", Field, 0}, + {"Ustat_t.Pad_cgo_1", Field, 0}, + {"Ustat_t.Tfree", Field, 0}, + {"Ustat_t.Tinode", Field, 0}, + {"Utimbuf", Type, 0}, + {"Utimbuf.Actime", Field, 0}, + {"Utimbuf.Modtime", Field, 0}, + {"Utime", Func, 0}, + {"Utimes", Func, 0}, + {"UtimesNano", Func, 1}, + {"Utsname", Type, 0}, + {"Utsname.Domainname", Field, 0}, + {"Utsname.Machine", Field, 0}, + {"Utsname.Nodename", Field, 0}, + {"Utsname.Release", Field, 0}, + {"Utsname.Sysname", Field, 0}, + {"Utsname.Version", Field, 0}, + {"VDISCARD", Const, 0}, + {"VDSUSP", Const, 1}, + {"VEOF", Const, 0}, + {"VEOL", Const, 0}, + {"VEOL2", Const, 0}, + {"VERASE", Const, 0}, + {"VERASE2", Const, 1}, + {"VINTR", Const, 0}, + {"VKILL", Const, 0}, + {"VLNEXT", Const, 0}, + {"VMIN", Const, 0}, + {"VQUIT", Const, 0}, + {"VREPRINT", Const, 0}, + {"VSTART", Const, 0}, + {"VSTATUS", Const, 1}, + {"VSTOP", Const, 0}, + {"VSUSP", Const, 0}, + {"VSWTC", Const, 0}, + {"VT0", Const, 1}, + {"VT1", Const, 1}, + {"VTDLY", Const, 1}, + {"VTIME", Const, 0}, + {"VWERASE", Const, 0}, + {"VirtualLock", Func, 0}, + {"VirtualUnlock", Func, 0}, + {"WAIT_ABANDONED", Const, 0}, + {"WAIT_FAILED", Const, 0}, + {"WAIT_OBJECT_0", Const, 0}, + {"WAIT_TIMEOUT", Const, 0}, + {"WALL", Const, 0}, + {"WALLSIG", Const, 1}, + {"WALTSIG", Const, 1}, + {"WCLONE", Const, 0}, + {"WCONTINUED", Const, 0}, + {"WCOREFLAG", Const, 0}, + {"WEXITED", Const, 0}, + {"WLINUXCLONE", Const, 0}, + {"WNOHANG", Const, 0}, + {"WNOTHREAD", Const, 0}, + {"WNOWAIT", Const, 0}, + {"WNOZOMBIE", Const, 1}, + {"WOPTSCHECKED", Const, 1}, + {"WORDSIZE", Const, 0}, + {"WSABuf", Type, 0}, + {"WSABuf.Buf", Field, 0}, + {"WSABuf.Len", Field, 0}, + {"WSACleanup", Func, 0}, + {"WSADESCRIPTION_LEN", Const, 0}, + {"WSAData", Type, 0}, + {"WSAData.Description", Field, 0}, + {"WSAData.HighVersion", Field, 0}, + {"WSAData.MaxSockets", Field, 0}, + {"WSAData.MaxUdpDg", Field, 0}, + {"WSAData.SystemStatus", Field, 0}, + {"WSAData.VendorInfo", Field, 0}, + {"WSAData.Version", Field, 0}, + {"WSAEACCES", Const, 2}, + {"WSAECONNABORTED", Const, 9}, + {"WSAECONNRESET", Const, 3}, + {"WSAEnumProtocols", Func, 2}, + {"WSAID_CONNECTEX", Var, 1}, + {"WSAIoctl", Func, 0}, + {"WSAPROTOCOL_LEN", Const, 2}, + {"WSAProtocolChain", Type, 2}, + {"WSAProtocolChain.ChainEntries", Field, 2}, + {"WSAProtocolChain.ChainLen", Field, 2}, + {"WSAProtocolInfo", Type, 2}, + {"WSAProtocolInfo.AddressFamily", Field, 2}, + {"WSAProtocolInfo.CatalogEntryId", Field, 2}, + {"WSAProtocolInfo.MaxSockAddr", Field, 2}, + {"WSAProtocolInfo.MessageSize", Field, 2}, + {"WSAProtocolInfo.MinSockAddr", Field, 2}, + {"WSAProtocolInfo.NetworkByteOrder", Field, 2}, + {"WSAProtocolInfo.Protocol", Field, 2}, + {"WSAProtocolInfo.ProtocolChain", Field, 2}, + {"WSAProtocolInfo.ProtocolMaxOffset", Field, 2}, + {"WSAProtocolInfo.ProtocolName", Field, 2}, + {"WSAProtocolInfo.ProviderFlags", Field, 2}, + {"WSAProtocolInfo.ProviderId", Field, 2}, + {"WSAProtocolInfo.ProviderReserved", Field, 2}, + {"WSAProtocolInfo.SecurityScheme", Field, 2}, + {"WSAProtocolInfo.ServiceFlags1", Field, 2}, + {"WSAProtocolInfo.ServiceFlags2", Field, 2}, + {"WSAProtocolInfo.ServiceFlags3", Field, 2}, + {"WSAProtocolInfo.ServiceFlags4", Field, 2}, + {"WSAProtocolInfo.SocketType", Field, 2}, + {"WSAProtocolInfo.Version", Field, 2}, + {"WSARecv", Func, 0}, + {"WSARecvFrom", Func, 0}, + {"WSASYS_STATUS_LEN", Const, 0}, + {"WSASend", Func, 0}, + {"WSASendTo", Func, 0}, + {"WSASendto", Func, 0}, + {"WSAStartup", Func, 0}, + {"WSTOPPED", Const, 0}, + {"WTRAPPED", Const, 1}, + {"WUNTRACED", Const, 0}, + {"Wait4", Func, 0}, + {"WaitForSingleObject", Func, 0}, + {"WaitStatus", Type, 0}, + {"WaitStatus.ExitCode", Field, 0}, + {"Win32FileAttributeData", Type, 0}, + {"Win32FileAttributeData.CreationTime", Field, 0}, + {"Win32FileAttributeData.FileAttributes", Field, 0}, + {"Win32FileAttributeData.FileSizeHigh", Field, 0}, + {"Win32FileAttributeData.FileSizeLow", Field, 0}, + {"Win32FileAttributeData.LastAccessTime", Field, 0}, + {"Win32FileAttributeData.LastWriteTime", Field, 0}, + {"Win32finddata", Type, 0}, + {"Win32finddata.AlternateFileName", Field, 0}, + {"Win32finddata.CreationTime", Field, 0}, + {"Win32finddata.FileAttributes", Field, 0}, + {"Win32finddata.FileName", Field, 0}, + {"Win32finddata.FileSizeHigh", Field, 0}, + {"Win32finddata.FileSizeLow", Field, 0}, + {"Win32finddata.LastAccessTime", Field, 0}, + {"Win32finddata.LastWriteTime", Field, 0}, + {"Win32finddata.Reserved0", Field, 0}, + {"Win32finddata.Reserved1", Field, 0}, + {"Write", Func, 0}, + {"WriteConsole", Func, 1}, + {"WriteFile", Func, 0}, + {"X509_ASN_ENCODING", Const, 0}, + {"XCASE", Const, 0}, + {"XP1_CONNECTIONLESS", Const, 2}, + {"XP1_CONNECT_DATA", Const, 2}, + {"XP1_DISCONNECT_DATA", Const, 2}, + {"XP1_EXPEDITED_DATA", Const, 2}, + {"XP1_GRACEFUL_CLOSE", Const, 2}, + {"XP1_GUARANTEED_DELIVERY", Const, 2}, + {"XP1_GUARANTEED_ORDER", Const, 2}, + {"XP1_IFS_HANDLES", Const, 2}, + {"XP1_MESSAGE_ORIENTED", Const, 2}, + {"XP1_MULTIPOINT_CONTROL_PLANE", Const, 2}, + {"XP1_MULTIPOINT_DATA_PLANE", Const, 2}, + {"XP1_PARTIAL_MESSAGE", Const, 2}, + {"XP1_PSEUDO_STREAM", Const, 2}, + {"XP1_QOS_SUPPORTED", Const, 2}, + {"XP1_SAN_SUPPORT_SDP", Const, 2}, + {"XP1_SUPPORT_BROADCAST", Const, 2}, + {"XP1_SUPPORT_MULTIPOINT", Const, 2}, + {"XP1_UNI_RECV", Const, 2}, + {"XP1_UNI_SEND", Const, 2}, + }, + "syscall/js": { + {"CopyBytesToGo", Func, 0}, + {"CopyBytesToJS", Func, 0}, + {"Error", Type, 0}, + {"Func", Type, 0}, + {"FuncOf", Func, 0}, + {"Global", Func, 0}, + {"Null", Func, 0}, + {"Type", Type, 0}, + {"TypeBoolean", Const, 0}, + {"TypeFunction", Const, 0}, + {"TypeNull", Const, 0}, + {"TypeNumber", Const, 0}, + {"TypeObject", Const, 0}, + {"TypeString", Const, 0}, + {"TypeSymbol", Const, 0}, + {"TypeUndefined", Const, 0}, + {"Undefined", Func, 0}, + {"Value", Type, 0}, + {"ValueError", Type, 0}, + {"ValueOf", Func, 0}, + }, + "testing": { + {"(*B).Cleanup", Method, 14}, + {"(*B).Elapsed", Method, 20}, + {"(*B).Error", Method, 0}, + {"(*B).Errorf", Method, 0}, + {"(*B).Fail", Method, 0}, + {"(*B).FailNow", Method, 0}, + {"(*B).Failed", Method, 0}, + {"(*B).Fatal", Method, 0}, + {"(*B).Fatalf", Method, 0}, + {"(*B).Helper", Method, 9}, + {"(*B).Log", Method, 0}, + {"(*B).Logf", Method, 0}, + {"(*B).Name", Method, 8}, + {"(*B).ReportAllocs", Method, 1}, + {"(*B).ReportMetric", Method, 13}, + {"(*B).ResetTimer", Method, 0}, + {"(*B).Run", Method, 7}, + {"(*B).RunParallel", Method, 3}, + {"(*B).SetBytes", Method, 0}, + {"(*B).SetParallelism", Method, 3}, + {"(*B).Setenv", Method, 17}, + {"(*B).Skip", Method, 1}, + {"(*B).SkipNow", Method, 1}, + {"(*B).Skipf", Method, 1}, + {"(*B).Skipped", Method, 1}, + {"(*B).StartTimer", Method, 0}, + {"(*B).StopTimer", Method, 0}, + {"(*B).TempDir", Method, 15}, + {"(*F).Add", Method, 18}, + {"(*F).Cleanup", Method, 18}, + {"(*F).Error", Method, 18}, + {"(*F).Errorf", Method, 18}, + {"(*F).Fail", Method, 18}, + {"(*F).FailNow", Method, 18}, + {"(*F).Failed", Method, 18}, + {"(*F).Fatal", Method, 18}, + {"(*F).Fatalf", Method, 18}, + {"(*F).Fuzz", Method, 18}, + {"(*F).Helper", Method, 18}, + {"(*F).Log", Method, 18}, + {"(*F).Logf", Method, 18}, + {"(*F).Name", Method, 18}, + {"(*F).Setenv", Method, 18}, + {"(*F).Skip", Method, 18}, + {"(*F).SkipNow", Method, 18}, + {"(*F).Skipf", Method, 18}, + {"(*F).Skipped", Method, 18}, + {"(*F).TempDir", Method, 18}, + {"(*M).Run", Method, 4}, + {"(*PB).Next", Method, 3}, + {"(*T).Cleanup", Method, 14}, + {"(*T).Deadline", Method, 15}, + {"(*T).Error", Method, 0}, + {"(*T).Errorf", Method, 0}, + {"(*T).Fail", Method, 0}, + {"(*T).FailNow", Method, 0}, + {"(*T).Failed", Method, 0}, + {"(*T).Fatal", Method, 0}, + {"(*T).Fatalf", Method, 0}, + {"(*T).Helper", Method, 9}, + {"(*T).Log", Method, 0}, + {"(*T).Logf", Method, 0}, + {"(*T).Name", Method, 8}, + {"(*T).Parallel", Method, 0}, + {"(*T).Run", Method, 7}, + {"(*T).Setenv", Method, 17}, + {"(*T).Skip", Method, 1}, + {"(*T).SkipNow", Method, 1}, + {"(*T).Skipf", Method, 1}, + {"(*T).Skipped", Method, 1}, + {"(*T).TempDir", Method, 15}, + {"(BenchmarkResult).AllocedBytesPerOp", Method, 1}, + {"(BenchmarkResult).AllocsPerOp", Method, 1}, + {"(BenchmarkResult).MemString", Method, 1}, + {"(BenchmarkResult).NsPerOp", Method, 0}, + {"(BenchmarkResult).String", Method, 0}, + {"AllocsPerRun", Func, 1}, + {"B", Type, 0}, + {"B.N", Field, 0}, + {"Benchmark", Func, 0}, + {"BenchmarkResult", Type, 0}, + {"BenchmarkResult.Bytes", Field, 0}, + {"BenchmarkResult.Extra", Field, 13}, + {"BenchmarkResult.MemAllocs", Field, 1}, + {"BenchmarkResult.MemBytes", Field, 1}, + {"BenchmarkResult.N", Field, 0}, + {"BenchmarkResult.T", Field, 0}, + {"Cover", Type, 2}, + {"Cover.Blocks", Field, 2}, + {"Cover.Counters", Field, 2}, + {"Cover.CoveredPackages", Field, 2}, + {"Cover.Mode", Field, 2}, + {"CoverBlock", Type, 2}, + {"CoverBlock.Col0", Field, 2}, + {"CoverBlock.Col1", Field, 2}, + {"CoverBlock.Line0", Field, 2}, + {"CoverBlock.Line1", Field, 2}, + {"CoverBlock.Stmts", Field, 2}, + {"CoverMode", Func, 8}, + {"Coverage", Func, 4}, + {"F", Type, 18}, + {"Init", Func, 13}, + {"InternalBenchmark", Type, 0}, + {"InternalBenchmark.F", Field, 0}, + {"InternalBenchmark.Name", Field, 0}, + {"InternalExample", Type, 0}, + {"InternalExample.F", Field, 0}, + {"InternalExample.Name", Field, 0}, + {"InternalExample.Output", Field, 0}, + {"InternalExample.Unordered", Field, 7}, + {"InternalFuzzTarget", Type, 18}, + {"InternalFuzzTarget.Fn", Field, 18}, + {"InternalFuzzTarget.Name", Field, 18}, + {"InternalTest", Type, 0}, + {"InternalTest.F", Field, 0}, + {"InternalTest.Name", Field, 0}, + {"M", Type, 4}, + {"Main", Func, 0}, + {"MainStart", Func, 4}, + {"PB", Type, 3}, + {"RegisterCover", Func, 2}, + {"RunBenchmarks", Func, 0}, + {"RunExamples", Func, 0}, + {"RunTests", Func, 0}, + {"Short", Func, 0}, + {"T", Type, 0}, + {"TB", Type, 2}, + {"Testing", Func, 21}, + {"Verbose", Func, 1}, + }, + "testing/fstest": { + {"(MapFS).Glob", Method, 16}, + {"(MapFS).Open", Method, 16}, + {"(MapFS).ReadDir", Method, 16}, + {"(MapFS).ReadFile", Method, 16}, + {"(MapFS).Stat", Method, 16}, + {"(MapFS).Sub", Method, 16}, + {"MapFS", Type, 16}, + {"MapFile", Type, 16}, + {"MapFile.Data", Field, 16}, + {"MapFile.ModTime", Field, 16}, + {"MapFile.Mode", Field, 16}, + {"MapFile.Sys", Field, 16}, + {"TestFS", Func, 16}, + }, + "testing/iotest": { + {"DataErrReader", Func, 0}, + {"ErrReader", Func, 16}, + {"ErrTimeout", Var, 0}, + {"HalfReader", Func, 0}, + {"NewReadLogger", Func, 0}, + {"NewWriteLogger", Func, 0}, + {"OneByteReader", Func, 0}, + {"TestReader", Func, 16}, + {"TimeoutReader", Func, 0}, + {"TruncateWriter", Func, 0}, + }, + "testing/quick": { + {"(*CheckEqualError).Error", Method, 0}, + {"(*CheckError).Error", Method, 0}, + {"(SetupError).Error", Method, 0}, + {"Check", Func, 0}, + {"CheckEqual", Func, 0}, + {"CheckEqualError", Type, 0}, + {"CheckEqualError.CheckError", Field, 0}, + {"CheckEqualError.Out1", Field, 0}, + {"CheckEqualError.Out2", Field, 0}, + {"CheckError", Type, 0}, + {"CheckError.Count", Field, 0}, + {"CheckError.In", Field, 0}, + {"Config", Type, 0}, + {"Config.MaxCount", Field, 0}, + {"Config.MaxCountScale", Field, 0}, + {"Config.Rand", Field, 0}, + {"Config.Values", Field, 0}, + {"Generator", Type, 0}, + {"SetupError", Type, 0}, + {"Value", Func, 0}, + }, + "testing/slogtest": { + {"Run", Func, 22}, + {"TestHandler", Func, 21}, + }, + "text/scanner": { + {"(*Position).IsValid", Method, 0}, + {"(*Scanner).Init", Method, 0}, + {"(*Scanner).IsValid", Method, 0}, + {"(*Scanner).Next", Method, 0}, + {"(*Scanner).Peek", Method, 0}, + {"(*Scanner).Pos", Method, 0}, + {"(*Scanner).Scan", Method, 0}, + {"(*Scanner).TokenText", Method, 0}, + {"(Position).String", Method, 0}, + {"(Scanner).String", Method, 0}, + {"Char", Const, 0}, + {"Comment", Const, 0}, + {"EOF", Const, 0}, + {"Float", Const, 0}, + {"GoTokens", Const, 0}, + {"GoWhitespace", Const, 0}, + {"Ident", Const, 0}, + {"Int", Const, 0}, + {"Position", Type, 0}, + {"Position.Column", Field, 0}, + {"Position.Filename", Field, 0}, + {"Position.Line", Field, 0}, + {"Position.Offset", Field, 0}, + {"RawString", Const, 0}, + {"ScanChars", Const, 0}, + {"ScanComments", Const, 0}, + {"ScanFloats", Const, 0}, + {"ScanIdents", Const, 0}, + {"ScanInts", Const, 0}, + {"ScanRawStrings", Const, 0}, + {"ScanStrings", Const, 0}, + {"Scanner", Type, 0}, + {"Scanner.Error", Field, 0}, + {"Scanner.ErrorCount", Field, 0}, + {"Scanner.IsIdentRune", Field, 4}, + {"Scanner.Mode", Field, 0}, + {"Scanner.Position", Field, 0}, + {"Scanner.Whitespace", Field, 0}, + {"SkipComments", Const, 0}, + {"String", Const, 0}, + {"TokenString", Func, 0}, + }, + "text/tabwriter": { + {"(*Writer).Flush", Method, 0}, + {"(*Writer).Init", Method, 0}, + {"(*Writer).Write", Method, 0}, + {"AlignRight", Const, 0}, + {"Debug", Const, 0}, + {"DiscardEmptyColumns", Const, 0}, + {"Escape", Const, 0}, + {"FilterHTML", Const, 0}, + {"NewWriter", Func, 0}, + {"StripEscape", Const, 0}, + {"TabIndent", Const, 0}, + {"Writer", Type, 0}, + }, + "text/template": { + {"(*Template).AddParseTree", Method, 0}, + {"(*Template).Clone", Method, 0}, + {"(*Template).DefinedTemplates", Method, 5}, + {"(*Template).Delims", Method, 0}, + {"(*Template).Execute", Method, 0}, + {"(*Template).ExecuteTemplate", Method, 0}, + {"(*Template).Funcs", Method, 0}, + {"(*Template).Lookup", Method, 0}, + {"(*Template).Name", Method, 0}, + {"(*Template).New", Method, 0}, + {"(*Template).Option", Method, 5}, + {"(*Template).Parse", Method, 0}, + {"(*Template).ParseFS", Method, 16}, + {"(*Template).ParseFiles", Method, 0}, + {"(*Template).ParseGlob", Method, 0}, + {"(*Template).Templates", Method, 0}, + {"(ExecError).Error", Method, 6}, + {"(ExecError).Unwrap", Method, 13}, + {"(Template).Copy", Method, 2}, + {"(Template).ErrorContext", Method, 1}, + {"ExecError", Type, 6}, + {"ExecError.Err", Field, 6}, + {"ExecError.Name", Field, 6}, + {"FuncMap", Type, 0}, + {"HTMLEscape", Func, 0}, + {"HTMLEscapeString", Func, 0}, + {"HTMLEscaper", Func, 0}, + {"IsTrue", Func, 6}, + {"JSEscape", Func, 0}, + {"JSEscapeString", Func, 0}, + {"JSEscaper", Func, 0}, + {"Must", Func, 0}, + {"New", Func, 0}, + {"ParseFS", Func, 16}, + {"ParseFiles", Func, 0}, + {"ParseGlob", Func, 0}, + {"Template", Type, 0}, + {"Template.Tree", Field, 0}, + {"URLQueryEscaper", Func, 0}, + }, + "text/template/parse": { + {"(*ActionNode).Copy", Method, 0}, + {"(*ActionNode).String", Method, 0}, + {"(*BoolNode).Copy", Method, 0}, + {"(*BoolNode).String", Method, 0}, + {"(*BranchNode).Copy", Method, 4}, + {"(*BranchNode).String", Method, 0}, + {"(*BreakNode).Copy", Method, 18}, + {"(*BreakNode).String", Method, 18}, + {"(*ChainNode).Add", Method, 1}, + {"(*ChainNode).Copy", Method, 1}, + {"(*ChainNode).String", Method, 1}, + {"(*CommandNode).Copy", Method, 0}, + {"(*CommandNode).String", Method, 0}, + {"(*CommentNode).Copy", Method, 16}, + {"(*CommentNode).String", Method, 16}, + {"(*ContinueNode).Copy", Method, 18}, + {"(*ContinueNode).String", Method, 18}, + {"(*DotNode).Copy", Method, 0}, + {"(*DotNode).String", Method, 0}, + {"(*DotNode).Type", Method, 0}, + {"(*FieldNode).Copy", Method, 0}, + {"(*FieldNode).String", Method, 0}, + {"(*IdentifierNode).Copy", Method, 0}, + {"(*IdentifierNode).SetPos", Method, 1}, + {"(*IdentifierNode).SetTree", Method, 4}, + {"(*IdentifierNode).String", Method, 0}, + {"(*IfNode).Copy", Method, 0}, + {"(*IfNode).String", Method, 0}, + {"(*ListNode).Copy", Method, 0}, + {"(*ListNode).CopyList", Method, 0}, + {"(*ListNode).String", Method, 0}, + {"(*NilNode).Copy", Method, 1}, + {"(*NilNode).String", Method, 1}, + {"(*NilNode).Type", Method, 1}, + {"(*NumberNode).Copy", Method, 0}, + {"(*NumberNode).String", Method, 0}, + {"(*PipeNode).Copy", Method, 0}, + {"(*PipeNode).CopyPipe", Method, 0}, + {"(*PipeNode).String", Method, 0}, + {"(*RangeNode).Copy", Method, 0}, + {"(*RangeNode).String", Method, 0}, + {"(*StringNode).Copy", Method, 0}, + {"(*StringNode).String", Method, 0}, + {"(*TemplateNode).Copy", Method, 0}, + {"(*TemplateNode).String", Method, 0}, + {"(*TextNode).Copy", Method, 0}, + {"(*TextNode).String", Method, 0}, + {"(*Tree).Copy", Method, 2}, + {"(*Tree).ErrorContext", Method, 1}, + {"(*Tree).Parse", Method, 0}, + {"(*VariableNode).Copy", Method, 0}, + {"(*VariableNode).String", Method, 0}, + {"(*WithNode).Copy", Method, 0}, + {"(*WithNode).String", Method, 0}, + {"(ActionNode).Position", Method, 1}, + {"(ActionNode).Type", Method, 0}, + {"(BoolNode).Position", Method, 1}, + {"(BoolNode).Type", Method, 0}, + {"(BranchNode).Position", Method, 1}, + {"(BranchNode).Type", Method, 0}, + {"(BreakNode).Position", Method, 18}, + {"(BreakNode).Type", Method, 18}, + {"(ChainNode).Position", Method, 1}, + {"(ChainNode).Type", Method, 1}, + {"(CommandNode).Position", Method, 1}, + {"(CommandNode).Type", Method, 0}, + {"(CommentNode).Position", Method, 16}, + {"(CommentNode).Type", Method, 16}, + {"(ContinueNode).Position", Method, 18}, + {"(ContinueNode).Type", Method, 18}, + {"(DotNode).Position", Method, 1}, + {"(FieldNode).Position", Method, 1}, + {"(FieldNode).Type", Method, 0}, + {"(IdentifierNode).Position", Method, 1}, + {"(IdentifierNode).Type", Method, 0}, + {"(IfNode).Position", Method, 1}, + {"(IfNode).Type", Method, 0}, + {"(ListNode).Position", Method, 1}, + {"(ListNode).Type", Method, 0}, + {"(NilNode).Position", Method, 1}, + {"(NodeType).Type", Method, 0}, + {"(NumberNode).Position", Method, 1}, + {"(NumberNode).Type", Method, 0}, + {"(PipeNode).Position", Method, 1}, + {"(PipeNode).Type", Method, 0}, + {"(Pos).Position", Method, 1}, + {"(RangeNode).Position", Method, 1}, + {"(RangeNode).Type", Method, 0}, + {"(StringNode).Position", Method, 1}, + {"(StringNode).Type", Method, 0}, + {"(TemplateNode).Position", Method, 1}, + {"(TemplateNode).Type", Method, 0}, + {"(TextNode).Position", Method, 1}, + {"(TextNode).Type", Method, 0}, + {"(VariableNode).Position", Method, 1}, + {"(VariableNode).Type", Method, 0}, + {"(WithNode).Position", Method, 1}, + {"(WithNode).Type", Method, 0}, + {"ActionNode", Type, 0}, + {"ActionNode.Line", Field, 0}, + {"ActionNode.NodeType", Field, 0}, + {"ActionNode.Pipe", Field, 0}, + {"ActionNode.Pos", Field, 1}, + {"BoolNode", Type, 0}, + {"BoolNode.NodeType", Field, 0}, + {"BoolNode.Pos", Field, 1}, + {"BoolNode.True", Field, 0}, + {"BranchNode", Type, 0}, + {"BranchNode.ElseList", Field, 0}, + {"BranchNode.Line", Field, 0}, + {"BranchNode.List", Field, 0}, + {"BranchNode.NodeType", Field, 0}, + {"BranchNode.Pipe", Field, 0}, + {"BranchNode.Pos", Field, 1}, + {"BreakNode", Type, 18}, + {"BreakNode.Line", Field, 18}, + {"BreakNode.NodeType", Field, 18}, + {"BreakNode.Pos", Field, 18}, + {"ChainNode", Type, 1}, + {"ChainNode.Field", Field, 1}, + {"ChainNode.Node", Field, 1}, + {"ChainNode.NodeType", Field, 1}, + {"ChainNode.Pos", Field, 1}, + {"CommandNode", Type, 0}, + {"CommandNode.Args", Field, 0}, + {"CommandNode.NodeType", Field, 0}, + {"CommandNode.Pos", Field, 1}, + {"CommentNode", Type, 16}, + {"CommentNode.NodeType", Field, 16}, + {"CommentNode.Pos", Field, 16}, + {"CommentNode.Text", Field, 16}, + {"ContinueNode", Type, 18}, + {"ContinueNode.Line", Field, 18}, + {"ContinueNode.NodeType", Field, 18}, + {"ContinueNode.Pos", Field, 18}, + {"DotNode", Type, 0}, + {"DotNode.NodeType", Field, 4}, + {"DotNode.Pos", Field, 1}, + {"FieldNode", Type, 0}, + {"FieldNode.Ident", Field, 0}, + {"FieldNode.NodeType", Field, 0}, + {"FieldNode.Pos", Field, 1}, + {"IdentifierNode", Type, 0}, + {"IdentifierNode.Ident", Field, 0}, + {"IdentifierNode.NodeType", Field, 0}, + {"IdentifierNode.Pos", Field, 1}, + {"IfNode", Type, 0}, + {"IfNode.BranchNode", Field, 0}, + {"IsEmptyTree", Func, 0}, + {"ListNode", Type, 0}, + {"ListNode.NodeType", Field, 0}, + {"ListNode.Nodes", Field, 0}, + {"ListNode.Pos", Field, 1}, + {"Mode", Type, 16}, + {"New", Func, 0}, + {"NewIdentifier", Func, 0}, + {"NilNode", Type, 1}, + {"NilNode.NodeType", Field, 4}, + {"NilNode.Pos", Field, 1}, + {"Node", Type, 0}, + {"NodeAction", Const, 0}, + {"NodeBool", Const, 0}, + {"NodeBreak", Const, 18}, + {"NodeChain", Const, 1}, + {"NodeCommand", Const, 0}, + {"NodeComment", Const, 16}, + {"NodeContinue", Const, 18}, + {"NodeDot", Const, 0}, + {"NodeField", Const, 0}, + {"NodeIdentifier", Const, 0}, + {"NodeIf", Const, 0}, + {"NodeList", Const, 0}, + {"NodeNil", Const, 1}, + {"NodeNumber", Const, 0}, + {"NodePipe", Const, 0}, + {"NodeRange", Const, 0}, + {"NodeString", Const, 0}, + {"NodeTemplate", Const, 0}, + {"NodeText", Const, 0}, + {"NodeType", Type, 0}, + {"NodeVariable", Const, 0}, + {"NodeWith", Const, 0}, + {"NumberNode", Type, 0}, + {"NumberNode.Complex128", Field, 0}, + {"NumberNode.Float64", Field, 0}, + {"NumberNode.Int64", Field, 0}, + {"NumberNode.IsComplex", Field, 0}, + {"NumberNode.IsFloat", Field, 0}, + {"NumberNode.IsInt", Field, 0}, + {"NumberNode.IsUint", Field, 0}, + {"NumberNode.NodeType", Field, 0}, + {"NumberNode.Pos", Field, 1}, + {"NumberNode.Text", Field, 0}, + {"NumberNode.Uint64", Field, 0}, + {"Parse", Func, 0}, + {"ParseComments", Const, 16}, + {"PipeNode", Type, 0}, + {"PipeNode.Cmds", Field, 0}, + {"PipeNode.Decl", Field, 0}, + {"PipeNode.IsAssign", Field, 11}, + {"PipeNode.Line", Field, 0}, + {"PipeNode.NodeType", Field, 0}, + {"PipeNode.Pos", Field, 1}, + {"Pos", Type, 1}, + {"RangeNode", Type, 0}, + {"RangeNode.BranchNode", Field, 0}, + {"SkipFuncCheck", Const, 17}, + {"StringNode", Type, 0}, + {"StringNode.NodeType", Field, 0}, + {"StringNode.Pos", Field, 1}, + {"StringNode.Quoted", Field, 0}, + {"StringNode.Text", Field, 0}, + {"TemplateNode", Type, 0}, + {"TemplateNode.Line", Field, 0}, + {"TemplateNode.Name", Field, 0}, + {"TemplateNode.NodeType", Field, 0}, + {"TemplateNode.Pipe", Field, 0}, + {"TemplateNode.Pos", Field, 1}, + {"TextNode", Type, 0}, + {"TextNode.NodeType", Field, 0}, + {"TextNode.Pos", Field, 1}, + {"TextNode.Text", Field, 0}, + {"Tree", Type, 0}, + {"Tree.Mode", Field, 16}, + {"Tree.Name", Field, 0}, + {"Tree.ParseName", Field, 1}, + {"Tree.Root", Field, 0}, + {"VariableNode", Type, 0}, + {"VariableNode.Ident", Field, 0}, + {"VariableNode.NodeType", Field, 0}, + {"VariableNode.Pos", Field, 1}, + {"WithNode", Type, 0}, + {"WithNode.BranchNode", Field, 0}, + }, + "time": { + {"(*Location).String", Method, 0}, + {"(*ParseError).Error", Method, 0}, + {"(*Ticker).Reset", Method, 15}, + {"(*Ticker).Stop", Method, 0}, + {"(*Time).GobDecode", Method, 0}, + {"(*Time).UnmarshalBinary", Method, 2}, + {"(*Time).UnmarshalJSON", Method, 0}, + {"(*Time).UnmarshalText", Method, 2}, + {"(*Timer).Reset", Method, 1}, + {"(*Timer).Stop", Method, 0}, + {"(Duration).Abs", Method, 19}, + {"(Duration).Hours", Method, 0}, + {"(Duration).Microseconds", Method, 13}, + {"(Duration).Milliseconds", Method, 13}, + {"(Duration).Minutes", Method, 0}, + {"(Duration).Nanoseconds", Method, 0}, + {"(Duration).Round", Method, 9}, + {"(Duration).Seconds", Method, 0}, + {"(Duration).String", Method, 0}, + {"(Duration).Truncate", Method, 9}, + {"(Month).String", Method, 0}, + {"(Time).Add", Method, 0}, + {"(Time).AddDate", Method, 0}, + {"(Time).After", Method, 0}, + {"(Time).AppendFormat", Method, 5}, + {"(Time).Before", Method, 0}, + {"(Time).Clock", Method, 0}, + {"(Time).Compare", Method, 20}, + {"(Time).Date", Method, 0}, + {"(Time).Day", Method, 0}, + {"(Time).Equal", Method, 0}, + {"(Time).Format", Method, 0}, + {"(Time).GoString", Method, 17}, + {"(Time).GobEncode", Method, 0}, + {"(Time).Hour", Method, 0}, + {"(Time).ISOWeek", Method, 0}, + {"(Time).In", Method, 0}, + {"(Time).IsDST", Method, 17}, + {"(Time).IsZero", Method, 0}, + {"(Time).Local", Method, 0}, + {"(Time).Location", Method, 0}, + {"(Time).MarshalBinary", Method, 2}, + {"(Time).MarshalJSON", Method, 0}, + {"(Time).MarshalText", Method, 2}, + {"(Time).Minute", Method, 0}, + {"(Time).Month", Method, 0}, + {"(Time).Nanosecond", Method, 0}, + {"(Time).Round", Method, 1}, + {"(Time).Second", Method, 0}, + {"(Time).String", Method, 0}, + {"(Time).Sub", Method, 0}, + {"(Time).Truncate", Method, 1}, + {"(Time).UTC", Method, 0}, + {"(Time).Unix", Method, 0}, + {"(Time).UnixMicro", Method, 17}, + {"(Time).UnixMilli", Method, 17}, + {"(Time).UnixNano", Method, 0}, + {"(Time).Weekday", Method, 0}, + {"(Time).Year", Method, 0}, + {"(Time).YearDay", Method, 1}, + {"(Time).Zone", Method, 0}, + {"(Time).ZoneBounds", Method, 19}, + {"(Weekday).String", Method, 0}, + {"ANSIC", Const, 0}, + {"After", Func, 0}, + {"AfterFunc", Func, 0}, + {"April", Const, 0}, + {"August", Const, 0}, + {"Date", Func, 0}, + {"DateOnly", Const, 20}, + {"DateTime", Const, 20}, + {"December", Const, 0}, + {"Duration", Type, 0}, + {"February", Const, 0}, + {"FixedZone", Func, 0}, + {"Friday", Const, 0}, + {"Hour", Const, 0}, + {"January", Const, 0}, + {"July", Const, 0}, + {"June", Const, 0}, + {"Kitchen", Const, 0}, + {"Layout", Const, 17}, + {"LoadLocation", Func, 0}, + {"LoadLocationFromTZData", Func, 10}, + {"Local", Var, 0}, + {"Location", Type, 0}, + {"March", Const, 0}, + {"May", Const, 0}, + {"Microsecond", Const, 0}, + {"Millisecond", Const, 0}, + {"Minute", Const, 0}, + {"Monday", Const, 0}, + {"Month", Type, 0}, + {"Nanosecond", Const, 0}, + {"NewTicker", Func, 0}, + {"NewTimer", Func, 0}, + {"November", Const, 0}, + {"Now", Func, 0}, + {"October", Const, 0}, + {"Parse", Func, 0}, + {"ParseDuration", Func, 0}, + {"ParseError", Type, 0}, + {"ParseError.Layout", Field, 0}, + {"ParseError.LayoutElem", Field, 0}, + {"ParseError.Message", Field, 0}, + {"ParseError.Value", Field, 0}, + {"ParseError.ValueElem", Field, 0}, + {"ParseInLocation", Func, 1}, + {"RFC1123", Const, 0}, + {"RFC1123Z", Const, 0}, + {"RFC3339", Const, 0}, + {"RFC3339Nano", Const, 0}, + {"RFC822", Const, 0}, + {"RFC822Z", Const, 0}, + {"RFC850", Const, 0}, + {"RubyDate", Const, 0}, + {"Saturday", Const, 0}, + {"Second", Const, 0}, + {"September", Const, 0}, + {"Since", Func, 0}, + {"Sleep", Func, 0}, + {"Stamp", Const, 0}, + {"StampMicro", Const, 0}, + {"StampMilli", Const, 0}, + {"StampNano", Const, 0}, + {"Sunday", Const, 0}, + {"Thursday", Const, 0}, + {"Tick", Func, 0}, + {"Ticker", Type, 0}, + {"Ticker.C", Field, 0}, + {"Time", Type, 0}, + {"TimeOnly", Const, 20}, + {"Timer", Type, 0}, + {"Timer.C", Field, 0}, + {"Tuesday", Const, 0}, + {"UTC", Var, 0}, + {"Unix", Func, 0}, + {"UnixDate", Const, 0}, + {"UnixMicro", Func, 17}, + {"UnixMilli", Func, 17}, + {"Until", Func, 8}, + {"Wednesday", Const, 0}, + {"Weekday", Type, 0}, + }, + "unicode": { + {"(SpecialCase).ToLower", Method, 0}, + {"(SpecialCase).ToTitle", Method, 0}, + {"(SpecialCase).ToUpper", Method, 0}, + {"ASCII_Hex_Digit", Var, 0}, + {"Adlam", Var, 7}, + {"Ahom", Var, 5}, + {"Anatolian_Hieroglyphs", Var, 5}, + {"Arabic", Var, 0}, + {"Armenian", Var, 0}, + {"Avestan", Var, 0}, + {"AzeriCase", Var, 0}, + {"Balinese", Var, 0}, + {"Bamum", Var, 0}, + {"Bassa_Vah", Var, 4}, + {"Batak", Var, 0}, + {"Bengali", Var, 0}, + {"Bhaiksuki", Var, 7}, + {"Bidi_Control", Var, 0}, + {"Bopomofo", Var, 0}, + {"Brahmi", Var, 0}, + {"Braille", Var, 0}, + {"Buginese", Var, 0}, + {"Buhid", Var, 0}, + {"C", Var, 0}, + {"Canadian_Aboriginal", Var, 0}, + {"Carian", Var, 0}, + {"CaseRange", Type, 0}, + {"CaseRange.Delta", Field, 0}, + {"CaseRange.Hi", Field, 0}, + {"CaseRange.Lo", Field, 0}, + {"CaseRanges", Var, 0}, + {"Categories", Var, 0}, + {"Caucasian_Albanian", Var, 4}, + {"Cc", Var, 0}, + {"Cf", Var, 0}, + {"Chakma", Var, 1}, + {"Cham", Var, 0}, + {"Cherokee", Var, 0}, + {"Chorasmian", Var, 16}, + {"Co", Var, 0}, + {"Common", Var, 0}, + {"Coptic", Var, 0}, + {"Cs", Var, 0}, + {"Cuneiform", Var, 0}, + {"Cypriot", Var, 0}, + {"Cypro_Minoan", Var, 21}, + {"Cyrillic", Var, 0}, + {"Dash", Var, 0}, + {"Deprecated", Var, 0}, + {"Deseret", Var, 0}, + {"Devanagari", Var, 0}, + {"Diacritic", Var, 0}, + {"Digit", Var, 0}, + {"Dives_Akuru", Var, 16}, + {"Dogra", Var, 13}, + {"Duployan", Var, 4}, + {"Egyptian_Hieroglyphs", Var, 0}, + {"Elbasan", Var, 4}, + {"Elymaic", Var, 14}, + {"Ethiopic", Var, 0}, + {"Extender", Var, 0}, + {"FoldCategory", Var, 0}, + {"FoldScript", Var, 0}, + {"Georgian", Var, 0}, + {"Glagolitic", Var, 0}, + {"Gothic", Var, 0}, + {"Grantha", Var, 4}, + {"GraphicRanges", Var, 0}, + {"Greek", Var, 0}, + {"Gujarati", Var, 0}, + {"Gunjala_Gondi", Var, 13}, + {"Gurmukhi", Var, 0}, + {"Han", Var, 0}, + {"Hangul", Var, 0}, + {"Hanifi_Rohingya", Var, 13}, + {"Hanunoo", Var, 0}, + {"Hatran", Var, 5}, + {"Hebrew", Var, 0}, + {"Hex_Digit", Var, 0}, + {"Hiragana", Var, 0}, + {"Hyphen", Var, 0}, + {"IDS_Binary_Operator", Var, 0}, + {"IDS_Trinary_Operator", Var, 0}, + {"Ideographic", Var, 0}, + {"Imperial_Aramaic", Var, 0}, + {"In", Func, 2}, + {"Inherited", Var, 0}, + {"Inscriptional_Pahlavi", Var, 0}, + {"Inscriptional_Parthian", Var, 0}, + {"Is", Func, 0}, + {"IsControl", Func, 0}, + {"IsDigit", Func, 0}, + {"IsGraphic", Func, 0}, + {"IsLetter", Func, 0}, + {"IsLower", Func, 0}, + {"IsMark", Func, 0}, + {"IsNumber", Func, 0}, + {"IsOneOf", Func, 0}, + {"IsPrint", Func, 0}, + {"IsPunct", Func, 0}, + {"IsSpace", Func, 0}, + {"IsSymbol", Func, 0}, + {"IsTitle", Func, 0}, + {"IsUpper", Func, 0}, + {"Javanese", Var, 0}, + {"Join_Control", Var, 0}, + {"Kaithi", Var, 0}, + {"Kannada", Var, 0}, + {"Katakana", Var, 0}, + {"Kawi", Var, 21}, + {"Kayah_Li", Var, 0}, + {"Kharoshthi", Var, 0}, + {"Khitan_Small_Script", Var, 16}, + {"Khmer", Var, 0}, + {"Khojki", Var, 4}, + {"Khudawadi", Var, 4}, + {"L", Var, 0}, + {"Lao", Var, 0}, + {"Latin", Var, 0}, + {"Lepcha", Var, 0}, + {"Letter", Var, 0}, + {"Limbu", Var, 0}, + {"Linear_A", Var, 4}, + {"Linear_B", Var, 0}, + {"Lisu", Var, 0}, + {"Ll", Var, 0}, + {"Lm", Var, 0}, + {"Lo", Var, 0}, + {"Logical_Order_Exception", Var, 0}, + {"Lower", Var, 0}, + {"LowerCase", Const, 0}, + {"Lt", Var, 0}, + {"Lu", Var, 0}, + {"Lycian", Var, 0}, + {"Lydian", Var, 0}, + {"M", Var, 0}, + {"Mahajani", Var, 4}, + {"Makasar", Var, 13}, + {"Malayalam", Var, 0}, + {"Mandaic", Var, 0}, + {"Manichaean", Var, 4}, + {"Marchen", Var, 7}, + {"Mark", Var, 0}, + {"Masaram_Gondi", Var, 10}, + {"MaxASCII", Const, 0}, + {"MaxCase", Const, 0}, + {"MaxLatin1", Const, 0}, + {"MaxRune", Const, 0}, + {"Mc", Var, 0}, + {"Me", Var, 0}, + {"Medefaidrin", Var, 13}, + {"Meetei_Mayek", Var, 0}, + {"Mende_Kikakui", Var, 4}, + {"Meroitic_Cursive", Var, 1}, + {"Meroitic_Hieroglyphs", Var, 1}, + {"Miao", Var, 1}, + {"Mn", Var, 0}, + {"Modi", Var, 4}, + {"Mongolian", Var, 0}, + {"Mro", Var, 4}, + {"Multani", Var, 5}, + {"Myanmar", Var, 0}, + {"N", Var, 0}, + {"Nabataean", Var, 4}, + {"Nag_Mundari", Var, 21}, + {"Nandinagari", Var, 14}, + {"Nd", Var, 0}, + {"New_Tai_Lue", Var, 0}, + {"Newa", Var, 7}, + {"Nko", Var, 0}, + {"Nl", Var, 0}, + {"No", Var, 0}, + {"Noncharacter_Code_Point", Var, 0}, + {"Number", Var, 0}, + {"Nushu", Var, 10}, + {"Nyiakeng_Puachue_Hmong", Var, 14}, + {"Ogham", Var, 0}, + {"Ol_Chiki", Var, 0}, + {"Old_Hungarian", Var, 5}, + {"Old_Italic", Var, 0}, + {"Old_North_Arabian", Var, 4}, + {"Old_Permic", Var, 4}, + {"Old_Persian", Var, 0}, + {"Old_Sogdian", Var, 13}, + {"Old_South_Arabian", Var, 0}, + {"Old_Turkic", Var, 0}, + {"Old_Uyghur", Var, 21}, + {"Oriya", Var, 0}, + {"Osage", Var, 7}, + {"Osmanya", Var, 0}, + {"Other", Var, 0}, + {"Other_Alphabetic", Var, 0}, + {"Other_Default_Ignorable_Code_Point", Var, 0}, + {"Other_Grapheme_Extend", Var, 0}, + {"Other_ID_Continue", Var, 0}, + {"Other_ID_Start", Var, 0}, + {"Other_Lowercase", Var, 0}, + {"Other_Math", Var, 0}, + {"Other_Uppercase", Var, 0}, + {"P", Var, 0}, + {"Pahawh_Hmong", Var, 4}, + {"Palmyrene", Var, 4}, + {"Pattern_Syntax", Var, 0}, + {"Pattern_White_Space", Var, 0}, + {"Pau_Cin_Hau", Var, 4}, + {"Pc", Var, 0}, + {"Pd", Var, 0}, + {"Pe", Var, 0}, + {"Pf", Var, 0}, + {"Phags_Pa", Var, 0}, + {"Phoenician", Var, 0}, + {"Pi", Var, 0}, + {"Po", Var, 0}, + {"Prepended_Concatenation_Mark", Var, 7}, + {"PrintRanges", Var, 0}, + {"Properties", Var, 0}, + {"Ps", Var, 0}, + {"Psalter_Pahlavi", Var, 4}, + {"Punct", Var, 0}, + {"Quotation_Mark", Var, 0}, + {"Radical", Var, 0}, + {"Range16", Type, 0}, + {"Range16.Hi", Field, 0}, + {"Range16.Lo", Field, 0}, + {"Range16.Stride", Field, 0}, + {"Range32", Type, 0}, + {"Range32.Hi", Field, 0}, + {"Range32.Lo", Field, 0}, + {"Range32.Stride", Field, 0}, + {"RangeTable", Type, 0}, + {"RangeTable.LatinOffset", Field, 1}, + {"RangeTable.R16", Field, 0}, + {"RangeTable.R32", Field, 0}, + {"Regional_Indicator", Var, 10}, + {"Rejang", Var, 0}, + {"ReplacementChar", Const, 0}, + {"Runic", Var, 0}, + {"S", Var, 0}, + {"STerm", Var, 0}, + {"Samaritan", Var, 0}, + {"Saurashtra", Var, 0}, + {"Sc", Var, 0}, + {"Scripts", Var, 0}, + {"Sentence_Terminal", Var, 7}, + {"Sharada", Var, 1}, + {"Shavian", Var, 0}, + {"Siddham", Var, 4}, + {"SignWriting", Var, 5}, + {"SimpleFold", Func, 0}, + {"Sinhala", Var, 0}, + {"Sk", Var, 0}, + {"Sm", Var, 0}, + {"So", Var, 0}, + {"Soft_Dotted", Var, 0}, + {"Sogdian", Var, 13}, + {"Sora_Sompeng", Var, 1}, + {"Soyombo", Var, 10}, + {"Space", Var, 0}, + {"SpecialCase", Type, 0}, + {"Sundanese", Var, 0}, + {"Syloti_Nagri", Var, 0}, + {"Symbol", Var, 0}, + {"Syriac", Var, 0}, + {"Tagalog", Var, 0}, + {"Tagbanwa", Var, 0}, + {"Tai_Le", Var, 0}, + {"Tai_Tham", Var, 0}, + {"Tai_Viet", Var, 0}, + {"Takri", Var, 1}, + {"Tamil", Var, 0}, + {"Tangsa", Var, 21}, + {"Tangut", Var, 7}, + {"Telugu", Var, 0}, + {"Terminal_Punctuation", Var, 0}, + {"Thaana", Var, 0}, + {"Thai", Var, 0}, + {"Tibetan", Var, 0}, + {"Tifinagh", Var, 0}, + {"Tirhuta", Var, 4}, + {"Title", Var, 0}, + {"TitleCase", Const, 0}, + {"To", Func, 0}, + {"ToLower", Func, 0}, + {"ToTitle", Func, 0}, + {"ToUpper", Func, 0}, + {"Toto", Var, 21}, + {"TurkishCase", Var, 0}, + {"Ugaritic", Var, 0}, + {"Unified_Ideograph", Var, 0}, + {"Upper", Var, 0}, + {"UpperCase", Const, 0}, + {"UpperLower", Const, 0}, + {"Vai", Var, 0}, + {"Variation_Selector", Var, 0}, + {"Version", Const, 0}, + {"Vithkuqi", Var, 21}, + {"Wancho", Var, 14}, + {"Warang_Citi", Var, 4}, + {"White_Space", Var, 0}, + {"Yezidi", Var, 16}, + {"Yi", Var, 0}, + {"Z", Var, 0}, + {"Zanabazar_Square", Var, 10}, + {"Zl", Var, 0}, + {"Zp", Var, 0}, + {"Zs", Var, 0}, + }, + "unicode/utf16": { + {"AppendRune", Func, 20}, + {"Decode", Func, 0}, + {"DecodeRune", Func, 0}, + {"Encode", Func, 0}, + {"EncodeRune", Func, 0}, + {"IsSurrogate", Func, 0}, + }, + "unicode/utf8": { + {"AppendRune", Func, 18}, + {"DecodeLastRune", Func, 0}, + {"DecodeLastRuneInString", Func, 0}, + {"DecodeRune", Func, 0}, + {"DecodeRuneInString", Func, 0}, + {"EncodeRune", Func, 0}, + {"FullRune", Func, 0}, + {"FullRuneInString", Func, 0}, + {"MaxRune", Const, 0}, + {"RuneCount", Func, 0}, + {"RuneCountInString", Func, 0}, + {"RuneError", Const, 0}, + {"RuneLen", Func, 0}, + {"RuneSelf", Const, 0}, + {"RuneStart", Func, 0}, + {"UTFMax", Const, 0}, + {"Valid", Func, 0}, + {"ValidRune", Func, 1}, + {"ValidString", Func, 0}, + }, + "unsafe": { + {"Add", Func, 0}, + {"Alignof", Func, 0}, + {"Offsetof", Func, 0}, + {"Pointer", Type, 0}, + {"Sizeof", Func, 0}, + {"Slice", Func, 0}, + {"SliceData", Func, 0}, + {"String", Func, 0}, + {"StringData", Func, 0}, + }, +} diff --git a/vendor/golang.org/x/tools/internal/stdlib/stdlib.go b/vendor/golang.org/x/tools/internal/stdlib/stdlib.go new file mode 100644 index 000000000..98904017f --- /dev/null +++ b/vendor/golang.org/x/tools/internal/stdlib/stdlib.go @@ -0,0 +1,97 @@ +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:generate go run generate.go + +// Package stdlib provides a table of all exported symbols in the +// standard library, along with the version at which they first +// appeared. +package stdlib + +import ( + "fmt" + "strings" +) + +type Symbol struct { + Name string + Kind Kind + Version Version // Go version that first included the symbol +} + +// A Kind indicates the kind of a symbol: +// function, variable, constant, type, and so on. +type Kind int8 + +const ( + Invalid Kind = iota // Example name: + Type // "Buffer" + Func // "Println" + Var // "EOF" + Const // "Pi" + Field // "Point.X" + Method // "(*Buffer).Grow" +) + +func (kind Kind) String() string { + return [...]string{ + Invalid: "invalid", + Type: "type", + Func: "func", + Var: "var", + Const: "const", + Field: "field", + Method: "method", + }[kind] +} + +// A Version represents a version of Go of the form "go1.%d". +type Version int8 + +// String returns a version string of the form "go1.23", without allocating. +func (v Version) String() string { return versions[v] } + +var versions [30]string // (increase constant as needed) + +func init() { + for i := range versions { + versions[i] = fmt.Sprintf("go1.%d", i) + } +} + +// HasPackage reports whether the specified package path is part of +// the standard library's public API. +func HasPackage(path string) bool { + _, ok := PackageSymbols[path] + return ok +} + +// SplitField splits the field symbol name into type and field +// components. It must be called only on Field symbols. +// +// Example: "File.Package" -> ("File", "Package") +func (sym *Symbol) SplitField() (typename, name string) { + if sym.Kind != Field { + panic("not a field") + } + typename, name, _ = strings.Cut(sym.Name, ".") + return +} + +// SplitMethod splits the method symbol name into pointer, receiver, +// and method components. It must be called only on Method symbols. +// +// Example: "(*Buffer).Grow" -> (true, "Buffer", "Grow") +func (sym *Symbol) SplitMethod() (ptr bool, recv, name string) { + if sym.Kind != Method { + panic("not a method") + } + recv, name, _ = strings.Cut(sym.Name, ".") + recv = recv[len("(") : len(recv)-len(")")] + ptr = recv[0] == '*' + if ptr { + recv = recv[len("*"):] + } + return +} diff --git a/vendor/golang.org/x/tools/internal/tokeninternal/tokeninternal.go b/vendor/golang.org/x/tools/internal/tokeninternal/tokeninternal.go index 7e638ec24..ff9437a36 100644 --- a/vendor/golang.org/x/tools/internal/tokeninternal/tokeninternal.go +++ b/vendor/golang.org/x/tools/internal/tokeninternal/tokeninternal.go @@ -34,30 +34,16 @@ func GetLines(file *token.File) []int { lines []int _ []struct{} } - type tokenFile118 struct { - _ *token.FileSet // deleted in go1.19 - tokenFile119 - } - - type uP = unsafe.Pointer - switch unsafe.Sizeof(*file) { - case unsafe.Sizeof(tokenFile118{}): - var ptr *tokenFile118 - *(*uP)(uP(&ptr)) = uP(file) - ptr.mu.Lock() - defer ptr.mu.Unlock() - return ptr.lines - case unsafe.Sizeof(tokenFile119{}): - var ptr *tokenFile119 - *(*uP)(uP(&ptr)) = uP(file) - ptr.mu.Lock() - defer ptr.mu.Unlock() - return ptr.lines - - default: + if unsafe.Sizeof(*file) != unsafe.Sizeof(tokenFile119{}) { panic("unexpected token.File size") } + var ptr *tokenFile119 + type uP = unsafe.Pointer + *(*uP)(uP(&ptr)) = uP(file) + ptr.mu.Lock() + defer ptr.mu.Unlock() + return ptr.lines } // AddExistingFiles adds the specified files to the FileSet if they diff --git a/vendor/golang.org/x/tools/internal/typeparams/common.go b/vendor/golang.org/x/tools/internal/typeparams/common.go deleted file mode 100644 index cdab98853..000000000 --- a/vendor/golang.org/x/tools/internal/typeparams/common.go +++ /dev/null @@ -1,204 +0,0 @@ -// Copyright 2021 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package typeparams contains common utilities for writing tools that interact -// with generic Go code, as introduced with Go 1.18. -// -// Many of the types and functions in this package are proxies for the new APIs -// introduced in the standard library with Go 1.18. For example, the -// typeparams.Union type is an alias for go/types.Union, and the ForTypeSpec -// function returns the value of the go/ast.TypeSpec.TypeParams field. At Go -// versions older than 1.18 these helpers are implemented as stubs, allowing -// users of this package to write code that handles generic constructs inline, -// even if the Go version being used to compile does not support generics. -// -// Additionally, this package contains common utilities for working with the -// new generic constructs, to supplement the standard library APIs. Notably, -// the StructuralTerms API computes a minimal representation of the structural -// restrictions on a type parameter. -// -// An external version of these APIs is available in the -// golang.org/x/exp/typeparams module. -package typeparams - -import ( - "fmt" - "go/ast" - "go/token" - "go/types" -) - -// UnpackIndexExpr extracts data from AST nodes that represent index -// expressions. -// -// For an ast.IndexExpr, the resulting indices slice will contain exactly one -// index expression. For an ast.IndexListExpr (go1.18+), it may have a variable -// number of index expressions. -// -// For nodes that don't represent index expressions, the first return value of -// UnpackIndexExpr will be nil. -func UnpackIndexExpr(n ast.Node) (x ast.Expr, lbrack token.Pos, indices []ast.Expr, rbrack token.Pos) { - switch e := n.(type) { - case *ast.IndexExpr: - return e.X, e.Lbrack, []ast.Expr{e.Index}, e.Rbrack - case *ast.IndexListExpr: - return e.X, e.Lbrack, e.Indices, e.Rbrack - } - return nil, token.NoPos, nil, token.NoPos -} - -// PackIndexExpr returns an *ast.IndexExpr or *ast.IndexListExpr, depending on -// the cardinality of indices. Calling PackIndexExpr with len(indices) == 0 -// will panic. -func PackIndexExpr(x ast.Expr, lbrack token.Pos, indices []ast.Expr, rbrack token.Pos) ast.Expr { - switch len(indices) { - case 0: - panic("empty indices") - case 1: - return &ast.IndexExpr{ - X: x, - Lbrack: lbrack, - Index: indices[0], - Rbrack: rbrack, - } - default: - return &ast.IndexListExpr{ - X: x, - Lbrack: lbrack, - Indices: indices, - Rbrack: rbrack, - } - } -} - -// IsTypeParam reports whether t is a type parameter. -func IsTypeParam(t types.Type) bool { - _, ok := t.(*types.TypeParam) - return ok -} - -// OriginMethod returns the origin method associated with the method fn. -// For methods on a non-generic receiver base type, this is just -// fn. However, for methods with a generic receiver, OriginMethod returns the -// corresponding method in the method set of the origin type. -// -// As a special case, if fn is not a method (has no receiver), OriginMethod -// returns fn. -func OriginMethod(fn *types.Func) *types.Func { - recv := fn.Type().(*types.Signature).Recv() - if recv == nil { - return fn - } - base := recv.Type() - p, isPtr := base.(*types.Pointer) - if isPtr { - base = p.Elem() - } - named, isNamed := base.(*types.Named) - if !isNamed { - // Receiver is a *types.Interface. - return fn - } - if named.TypeParams().Len() == 0 { - // Receiver base has no type parameters, so we can avoid the lookup below. - return fn - } - orig := named.Origin() - gfn, _, _ := types.LookupFieldOrMethod(orig, true, fn.Pkg(), fn.Name()) - - // This is a fix for a gopls crash (#60628) due to a go/types bug (#60634). In: - // package p - // type T *int - // func (*T) f() {} - // LookupFieldOrMethod(T, true, p, f)=nil, but NewMethodSet(*T)={(*T).f}. - // Here we make them consistent by force. - // (The go/types bug is general, but this workaround is reached only - // for generic T thanks to the early return above.) - if gfn == nil { - mset := types.NewMethodSet(types.NewPointer(orig)) - for i := 0; i < mset.Len(); i++ { - m := mset.At(i) - if m.Obj().Id() == fn.Id() { - gfn = m.Obj() - break - } - } - } - - // In golang/go#61196, we observe another crash, this time inexplicable. - if gfn == nil { - panic(fmt.Sprintf("missing origin method for %s.%s; named == origin: %t, named.NumMethods(): %d, origin.NumMethods(): %d", named, fn, named == orig, named.NumMethods(), orig.NumMethods())) - } - - return gfn.(*types.Func) -} - -// GenericAssignableTo is a generalization of types.AssignableTo that -// implements the following rule for uninstantiated generic types: -// -// If V and T are generic named types, then V is considered assignable to T if, -// for every possible instantation of V[A_1, ..., A_N], the instantiation -// T[A_1, ..., A_N] is valid and V[A_1, ..., A_N] implements T[A_1, ..., A_N]. -// -// If T has structural constraints, they must be satisfied by V. -// -// For example, consider the following type declarations: -// -// type Interface[T any] interface { -// Accept(T) -// } -// -// type Container[T any] struct { -// Element T -// } -// -// func (c Container[T]) Accept(t T) { c.Element = t } -// -// In this case, GenericAssignableTo reports that instantiations of Container -// are assignable to the corresponding instantiation of Interface. -func GenericAssignableTo(ctxt *types.Context, V, T types.Type) bool { - // If V and T are not both named, or do not have matching non-empty type - // parameter lists, fall back on types.AssignableTo. - - VN, Vnamed := V.(*types.Named) - TN, Tnamed := T.(*types.Named) - if !Vnamed || !Tnamed { - return types.AssignableTo(V, T) - } - - vtparams := VN.TypeParams() - ttparams := TN.TypeParams() - if vtparams.Len() == 0 || vtparams.Len() != ttparams.Len() || VN.TypeArgs().Len() != 0 || TN.TypeArgs().Len() != 0 { - return types.AssignableTo(V, T) - } - - // V and T have the same (non-zero) number of type params. Instantiate both - // with the type parameters of V. This must always succeed for V, and will - // succeed for T if and only if the type set of each type parameter of V is a - // subset of the type set of the corresponding type parameter of T, meaning - // that every instantiation of V corresponds to a valid instantiation of T. - - // Minor optimization: ensure we share a context across the two - // instantiations below. - if ctxt == nil { - ctxt = types.NewContext() - } - - var targs []types.Type - for i := 0; i < vtparams.Len(); i++ { - targs = append(targs, vtparams.At(i)) - } - - vinst, err := types.Instantiate(ctxt, V, targs, true) - if err != nil { - panic("type parameters should satisfy their own constraints") - } - - tinst, err := types.Instantiate(ctxt, T, targs, true) - if err != nil { - return false - } - - return types.AssignableTo(vinst, tinst) -} diff --git a/vendor/golang.org/x/tools/internal/typeparams/coretype.go b/vendor/golang.org/x/tools/internal/typeparams/coretype.go deleted file mode 100644 index 7ea8840ea..000000000 --- a/vendor/golang.org/x/tools/internal/typeparams/coretype.go +++ /dev/null @@ -1,122 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package typeparams - -import ( - "go/types" -) - -// CoreType returns the core type of T or nil if T does not have a core type. -// -// See https://go.dev/ref/spec#Core_types for the definition of a core type. -func CoreType(T types.Type) types.Type { - U := T.Underlying() - if _, ok := U.(*types.Interface); !ok { - return U // for non-interface types, - } - - terms, err := _NormalTerms(U) - if len(terms) == 0 || err != nil { - // len(terms) -> empty type set of interface. - // err != nil => U is invalid, exceeds complexity bounds, or has an empty type set. - return nil // no core type. - } - - U = terms[0].Type().Underlying() - var identical int // i in [0,identical) => Identical(U, terms[i].Type().Underlying()) - for identical = 1; identical < len(terms); identical++ { - if !types.Identical(U, terms[identical].Type().Underlying()) { - break - } - } - - if identical == len(terms) { - // https://go.dev/ref/spec#Core_types - // "There is a single type U which is the underlying type of all types in the type set of T" - return U - } - ch, ok := U.(*types.Chan) - if !ok { - return nil // no core type as identical < len(terms) and U is not a channel. - } - // https://go.dev/ref/spec#Core_types - // "the type chan E if T contains only bidirectional channels, or the type chan<- E or - // <-chan E depending on the direction of the directional channels present." - for chans := identical; chans < len(terms); chans++ { - curr, ok := terms[chans].Type().Underlying().(*types.Chan) - if !ok { - return nil - } - if !types.Identical(ch.Elem(), curr.Elem()) { - return nil // channel elements are not identical. - } - if ch.Dir() == types.SendRecv { - // ch is bidirectional. We can safely always use curr's direction. - ch = curr - } else if curr.Dir() != types.SendRecv && ch.Dir() != curr.Dir() { - // ch and curr are not bidirectional and not the same direction. - return nil - } - } - return ch -} - -// _NormalTerms returns a slice of terms representing the normalized structural -// type restrictions of a type, if any. -// -// For all types other than *types.TypeParam, *types.Interface, and -// *types.Union, this is just a single term with Tilde() == false and -// Type() == typ. For *types.TypeParam, *types.Interface, and *types.Union, see -// below. -// -// Structural type restrictions of a type parameter are created via -// non-interface types embedded in its constraint interface (directly, or via a -// chain of interface embeddings). For example, in the declaration type -// T[P interface{~int; m()}] int the structural restriction of the type -// parameter P is ~int. -// -// With interface embedding and unions, the specification of structural type -// restrictions may be arbitrarily complex. For example, consider the -// following: -// -// type A interface{ ~string|~[]byte } -// -// type B interface{ int|string } -// -// type C interface { ~string|~int } -// -// type T[P interface{ A|B; C }] int -// -// In this example, the structural type restriction of P is ~string|int: A|B -// expands to ~string|~[]byte|int|string, which reduces to ~string|~[]byte|int, -// which when intersected with C (~string|~int) yields ~string|int. -// -// _NormalTerms computes these expansions and reductions, producing a -// "normalized" form of the embeddings. A structural restriction is normalized -// if it is a single union containing no interface terms, and is minimal in the -// sense that removing any term changes the set of types satisfying the -// constraint. It is left as a proof for the reader that, modulo sorting, there -// is exactly one such normalized form. -// -// Because the minimal representation always takes this form, _NormalTerms -// returns a slice of tilde terms corresponding to the terms of the union in -// the normalized structural restriction. An error is returned if the type is -// invalid, exceeds complexity bounds, or has an empty type set. In the latter -// case, _NormalTerms returns ErrEmptyTypeSet. -// -// _NormalTerms makes no guarantees about the order of terms, except that it -// is deterministic. -func _NormalTerms(typ types.Type) ([]*types.Term, error) { - switch typ := typ.(type) { - case *types.TypeParam: - return StructuralTerms(typ) - case *types.Union: - return UnionTermSet(typ) - case *types.Interface: - return InterfaceTermSet(typ) - default: - return []*types.Term{types.NewTerm(false, typ)}, nil - } -} diff --git a/vendor/golang.org/x/tools/internal/typeparams/normalize.go b/vendor/golang.org/x/tools/internal/typeparams/normalize.go deleted file mode 100644 index 93c80fdc9..000000000 --- a/vendor/golang.org/x/tools/internal/typeparams/normalize.go +++ /dev/null @@ -1,218 +0,0 @@ -// Copyright 2021 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package typeparams - -import ( - "errors" - "fmt" - "go/types" - "os" - "strings" -) - -//go:generate go run copytermlist.go - -const debug = false - -var ErrEmptyTypeSet = errors.New("empty type set") - -// StructuralTerms returns a slice of terms representing the normalized -// structural type restrictions of a type parameter, if any. -// -// Structural type restrictions of a type parameter are created via -// non-interface types embedded in its constraint interface (directly, or via a -// chain of interface embeddings). For example, in the declaration -// -// type T[P interface{~int; m()}] int -// -// the structural restriction of the type parameter P is ~int. -// -// With interface embedding and unions, the specification of structural type -// restrictions may be arbitrarily complex. For example, consider the -// following: -// -// type A interface{ ~string|~[]byte } -// -// type B interface{ int|string } -// -// type C interface { ~string|~int } -// -// type T[P interface{ A|B; C }] int -// -// In this example, the structural type restriction of P is ~string|int: A|B -// expands to ~string|~[]byte|int|string, which reduces to ~string|~[]byte|int, -// which when intersected with C (~string|~int) yields ~string|int. -// -// StructuralTerms computes these expansions and reductions, producing a -// "normalized" form of the embeddings. A structural restriction is normalized -// if it is a single union containing no interface terms, and is minimal in the -// sense that removing any term changes the set of types satisfying the -// constraint. It is left as a proof for the reader that, modulo sorting, there -// is exactly one such normalized form. -// -// Because the minimal representation always takes this form, StructuralTerms -// returns a slice of tilde terms corresponding to the terms of the union in -// the normalized structural restriction. An error is returned if the -// constraint interface is invalid, exceeds complexity bounds, or has an empty -// type set. In the latter case, StructuralTerms returns ErrEmptyTypeSet. -// -// StructuralTerms makes no guarantees about the order of terms, except that it -// is deterministic. -func StructuralTerms(tparam *types.TypeParam) ([]*types.Term, error) { - constraint := tparam.Constraint() - if constraint == nil { - return nil, fmt.Errorf("%s has nil constraint", tparam) - } - iface, _ := constraint.Underlying().(*types.Interface) - if iface == nil { - return nil, fmt.Errorf("constraint is %T, not *types.Interface", constraint.Underlying()) - } - return InterfaceTermSet(iface) -} - -// InterfaceTermSet computes the normalized terms for a constraint interface, -// returning an error if the term set cannot be computed or is empty. In the -// latter case, the error will be ErrEmptyTypeSet. -// -// See the documentation of StructuralTerms for more information on -// normalization. -func InterfaceTermSet(iface *types.Interface) ([]*types.Term, error) { - return computeTermSet(iface) -} - -// UnionTermSet computes the normalized terms for a union, returning an error -// if the term set cannot be computed or is empty. In the latter case, the -// error will be ErrEmptyTypeSet. -// -// See the documentation of StructuralTerms for more information on -// normalization. -func UnionTermSet(union *types.Union) ([]*types.Term, error) { - return computeTermSet(union) -} - -func computeTermSet(typ types.Type) ([]*types.Term, error) { - tset, err := computeTermSetInternal(typ, make(map[types.Type]*termSet), 0) - if err != nil { - return nil, err - } - if tset.terms.isEmpty() { - return nil, ErrEmptyTypeSet - } - if tset.terms.isAll() { - return nil, nil - } - var terms []*types.Term - for _, term := range tset.terms { - terms = append(terms, types.NewTerm(term.tilde, term.typ)) - } - return terms, nil -} - -// A termSet holds the normalized set of terms for a given type. -// -// The name termSet is intentionally distinct from 'type set': a type set is -// all types that implement a type (and includes method restrictions), whereas -// a term set just represents the structural restrictions on a type. -type termSet struct { - complete bool - terms termlist -} - -func indentf(depth int, format string, args ...interface{}) { - fmt.Fprintf(os.Stderr, strings.Repeat(".", depth)+format+"\n", args...) -} - -func computeTermSetInternal(t types.Type, seen map[types.Type]*termSet, depth int) (res *termSet, err error) { - if t == nil { - panic("nil type") - } - - if debug { - indentf(depth, "%s", t.String()) - defer func() { - if err != nil { - indentf(depth, "=> %s", err) - } else { - indentf(depth, "=> %s", res.terms.String()) - } - }() - } - - const maxTermCount = 100 - if tset, ok := seen[t]; ok { - if !tset.complete { - return nil, fmt.Errorf("cycle detected in the declaration of %s", t) - } - return tset, nil - } - - // Mark the current type as seen to avoid infinite recursion. - tset := new(termSet) - defer func() { - tset.complete = true - }() - seen[t] = tset - - switch u := t.Underlying().(type) { - case *types.Interface: - // The term set of an interface is the intersection of the term sets of its - // embedded types. - tset.terms = allTermlist - for i := 0; i < u.NumEmbeddeds(); i++ { - embedded := u.EmbeddedType(i) - if _, ok := embedded.Underlying().(*types.TypeParam); ok { - return nil, fmt.Errorf("invalid embedded type %T", embedded) - } - tset2, err := computeTermSetInternal(embedded, seen, depth+1) - if err != nil { - return nil, err - } - tset.terms = tset.terms.intersect(tset2.terms) - } - case *types.Union: - // The term set of a union is the union of term sets of its terms. - tset.terms = nil - for i := 0; i < u.Len(); i++ { - t := u.Term(i) - var terms termlist - switch t.Type().Underlying().(type) { - case *types.Interface: - tset2, err := computeTermSetInternal(t.Type(), seen, depth+1) - if err != nil { - return nil, err - } - terms = tset2.terms - case *types.TypeParam, *types.Union: - // A stand-alone type parameter or union is not permitted as union - // term. - return nil, fmt.Errorf("invalid union term %T", t) - default: - if t.Type() == types.Typ[types.Invalid] { - continue - } - terms = termlist{{t.Tilde(), t.Type()}} - } - tset.terms = tset.terms.union(terms) - if len(tset.terms) > maxTermCount { - return nil, fmt.Errorf("exceeded max term count %d", maxTermCount) - } - } - case *types.TypeParam: - panic("unreachable") - default: - // For all other types, the term set is just a single non-tilde term - // holding the type itself. - if u != types.Typ[types.Invalid] { - tset.terms = termlist{{false, t}} - } - } - return tset, nil -} - -// under is a facade for the go/types internal function of the same name. It is -// used by typeterm.go. -func under(t types.Type) types.Type { - return t.Underlying() -} diff --git a/vendor/golang.org/x/tools/internal/typeparams/termlist.go b/vendor/golang.org/x/tools/internal/typeparams/termlist.go deleted file mode 100644 index cbd12f801..000000000 --- a/vendor/golang.org/x/tools/internal/typeparams/termlist.go +++ /dev/null @@ -1,163 +0,0 @@ -// Copyright 2021 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Code generated by copytermlist.go DO NOT EDIT. - -package typeparams - -import ( - "bytes" - "go/types" -) - -// A termlist represents the type set represented by the union -// t1 ∪ y2 ∪ ... tn of the type sets of the terms t1 to tn. -// A termlist is in normal form if all terms are disjoint. -// termlist operations don't require the operands to be in -// normal form. -type termlist []*term - -// allTermlist represents the set of all types. -// It is in normal form. -var allTermlist = termlist{new(term)} - -// String prints the termlist exactly (without normalization). -func (xl termlist) String() string { - if len(xl) == 0 { - return "∅" - } - var buf bytes.Buffer - for i, x := range xl { - if i > 0 { - buf.WriteString(" | ") - } - buf.WriteString(x.String()) - } - return buf.String() -} - -// isEmpty reports whether the termlist xl represents the empty set of types. -func (xl termlist) isEmpty() bool { - // If there's a non-nil term, the entire list is not empty. - // If the termlist is in normal form, this requires at most - // one iteration. - for _, x := range xl { - if x != nil { - return false - } - } - return true -} - -// isAll reports whether the termlist xl represents the set of all types. -func (xl termlist) isAll() bool { - // If there's a 𝓤 term, the entire list is 𝓤. - // If the termlist is in normal form, this requires at most - // one iteration. - for _, x := range xl { - if x != nil && x.typ == nil { - return true - } - } - return false -} - -// norm returns the normal form of xl. -func (xl termlist) norm() termlist { - // Quadratic algorithm, but good enough for now. - // TODO(gri) fix asymptotic performance - used := make([]bool, len(xl)) - var rl termlist - for i, xi := range xl { - if xi == nil || used[i] { - continue - } - for j := i + 1; j < len(xl); j++ { - xj := xl[j] - if xj == nil || used[j] { - continue - } - if u1, u2 := xi.union(xj); u2 == nil { - // If we encounter a 𝓤 term, the entire list is 𝓤. - // Exit early. - // (Note that this is not just an optimization; - // if we continue, we may end up with a 𝓤 term - // and other terms and the result would not be - // in normal form.) - if u1.typ == nil { - return allTermlist - } - xi = u1 - used[j] = true // xj is now unioned into xi - ignore it in future iterations - } - } - rl = append(rl, xi) - } - return rl -} - -// union returns the union xl ∪ yl. -func (xl termlist) union(yl termlist) termlist { - return append(xl, yl...).norm() -} - -// intersect returns the intersection xl ∩ yl. -func (xl termlist) intersect(yl termlist) termlist { - if xl.isEmpty() || yl.isEmpty() { - return nil - } - - // Quadratic algorithm, but good enough for now. - // TODO(gri) fix asymptotic performance - var rl termlist - for _, x := range xl { - for _, y := range yl { - if r := x.intersect(y); r != nil { - rl = append(rl, r) - } - } - } - return rl.norm() -} - -// equal reports whether xl and yl represent the same type set. -func (xl termlist) equal(yl termlist) bool { - // TODO(gri) this should be more efficient - return xl.subsetOf(yl) && yl.subsetOf(xl) -} - -// includes reports whether t ∈ xl. -func (xl termlist) includes(t types.Type) bool { - for _, x := range xl { - if x.includes(t) { - return true - } - } - return false -} - -// supersetOf reports whether y ⊆ xl. -func (xl termlist) supersetOf(y *term) bool { - for _, x := range xl { - if y.subsetOf(x) { - return true - } - } - return false -} - -// subsetOf reports whether xl ⊆ yl. -func (xl termlist) subsetOf(yl termlist) bool { - if yl.isEmpty() { - return xl.isEmpty() - } - - // each term x of xl must be a subset of yl - for _, x := range xl { - if !yl.supersetOf(x) { - return false // x is not a subset yl - } - } - return true -} diff --git a/vendor/golang.org/x/tools/internal/typeparams/typeterm.go b/vendor/golang.org/x/tools/internal/typeparams/typeterm.go deleted file mode 100644 index 7350bb702..000000000 --- a/vendor/golang.org/x/tools/internal/typeparams/typeterm.go +++ /dev/null @@ -1,169 +0,0 @@ -// Copyright 2021 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Code generated by copytermlist.go DO NOT EDIT. - -package typeparams - -import "go/types" - -// A term describes elementary type sets: -// -// ∅: (*term)(nil) == ∅ // set of no types (empty set) -// 𝓤: &term{} == 𝓤 // set of all types (𝓤niverse) -// T: &term{false, T} == {T} // set of type T -// ~t: &term{true, t} == {t' | under(t') == t} // set of types with underlying type t -type term struct { - tilde bool // valid if typ != nil - typ types.Type -} - -func (x *term) String() string { - switch { - case x == nil: - return "∅" - case x.typ == nil: - return "𝓤" - case x.tilde: - return "~" + x.typ.String() - default: - return x.typ.String() - } -} - -// equal reports whether x and y represent the same type set. -func (x *term) equal(y *term) bool { - // easy cases - switch { - case x == nil || y == nil: - return x == y - case x.typ == nil || y.typ == nil: - return x.typ == y.typ - } - // ∅ ⊂ x, y ⊂ 𝓤 - - return x.tilde == y.tilde && types.Identical(x.typ, y.typ) -} - -// union returns the union x ∪ y: zero, one, or two non-nil terms. -func (x *term) union(y *term) (_, _ *term) { - // easy cases - switch { - case x == nil && y == nil: - return nil, nil // ∅ ∪ ∅ == ∅ - case x == nil: - return y, nil // ∅ ∪ y == y - case y == nil: - return x, nil // x ∪ ∅ == x - case x.typ == nil: - return x, nil // 𝓤 ∪ y == 𝓤 - case y.typ == nil: - return y, nil // x ∪ 𝓤 == 𝓤 - } - // ∅ ⊂ x, y ⊂ 𝓤 - - if x.disjoint(y) { - return x, y // x ∪ y == (x, y) if x ∩ y == ∅ - } - // x.typ == y.typ - - // ~t ∪ ~t == ~t - // ~t ∪ T == ~t - // T ∪ ~t == ~t - // T ∪ T == T - if x.tilde || !y.tilde { - return x, nil - } - return y, nil -} - -// intersect returns the intersection x ∩ y. -func (x *term) intersect(y *term) *term { - // easy cases - switch { - case x == nil || y == nil: - return nil // ∅ ∩ y == ∅ and ∩ ∅ == ∅ - case x.typ == nil: - return y // 𝓤 ∩ y == y - case y.typ == nil: - return x // x ∩ 𝓤 == x - } - // ∅ ⊂ x, y ⊂ 𝓤 - - if x.disjoint(y) { - return nil // x ∩ y == ∅ if x ∩ y == ∅ - } - // x.typ == y.typ - - // ~t ∩ ~t == ~t - // ~t ∩ T == T - // T ∩ ~t == T - // T ∩ T == T - if !x.tilde || y.tilde { - return x - } - return y -} - -// includes reports whether t ∈ x. -func (x *term) includes(t types.Type) bool { - // easy cases - switch { - case x == nil: - return false // t ∈ ∅ == false - case x.typ == nil: - return true // t ∈ 𝓤 == true - } - // ∅ ⊂ x ⊂ 𝓤 - - u := t - if x.tilde { - u = under(u) - } - return types.Identical(x.typ, u) -} - -// subsetOf reports whether x ⊆ y. -func (x *term) subsetOf(y *term) bool { - // easy cases - switch { - case x == nil: - return true // ∅ ⊆ y == true - case y == nil: - return false // x ⊆ ∅ == false since x != ∅ - case y.typ == nil: - return true // x ⊆ 𝓤 == true - case x.typ == nil: - return false // 𝓤 ⊆ y == false since y != 𝓤 - } - // ∅ ⊂ x, y ⊂ 𝓤 - - if x.disjoint(y) { - return false // x ⊆ y == false if x ∩ y == ∅ - } - // x.typ == y.typ - - // ~t ⊆ ~t == true - // ~t ⊆ T == false - // T ⊆ ~t == true - // T ⊆ T == true - return !x.tilde || y.tilde -} - -// disjoint reports whether x ∩ y == ∅. -// x.typ and y.typ must not be nil. -func (x *term) disjoint(y *term) bool { - if debug && (x.typ == nil || y.typ == nil) { - panic("invalid argument(s)") - } - ux := x.typ - if y.tilde { - ux = under(ux) - } - uy := y.typ - if x.tilde { - uy = under(uy) - } - return !types.Identical(ux, uy) -} diff --git a/vendor/golang.org/x/tools/internal/typesinternal/errorcode.go b/vendor/golang.org/x/tools/internal/typesinternal/errorcode.go index 07484073a..834e05381 100644 --- a/vendor/golang.org/x/tools/internal/typesinternal/errorcode.go +++ b/vendor/golang.org/x/tools/internal/typesinternal/errorcode.go @@ -167,7 +167,7 @@ const ( UntypedNilUse // WrongAssignCount occurs when the number of values on the right-hand side - // of an assignment or or initialization expression does not match the number + // of an assignment or initialization expression does not match the number // of variables on the left-hand side. // // Example: @@ -1449,10 +1449,10 @@ const ( NotAGenericType // WrongTypeArgCount occurs when a type or function is instantiated with an - // incorrent number of type arguments, including when a generic type or + // incorrect number of type arguments, including when a generic type or // function is used without instantiation. // - // Errors inolving failed type inference are assigned other error codes. + // Errors involving failed type inference are assigned other error codes. // // Example: // type T[p any] int diff --git a/vendor/golang.org/x/tools/internal/typesinternal/recv.go b/vendor/golang.org/x/tools/internal/typesinternal/recv.go new file mode 100644 index 000000000..fea7c8b75 --- /dev/null +++ b/vendor/golang.org/x/tools/internal/typesinternal/recv.go @@ -0,0 +1,43 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package typesinternal + +import ( + "go/types" + + "golang.org/x/tools/internal/aliases" +) + +// ReceiverNamed returns the named type (if any) associated with the +// type of recv, which may be of the form N or *N, or aliases thereof. +// It also reports whether a Pointer was present. +func ReceiverNamed(recv *types.Var) (isPtr bool, named *types.Named) { + t := recv.Type() + if ptr, ok := aliases.Unalias(t).(*types.Pointer); ok { + isPtr = true + t = ptr.Elem() + } + named, _ = aliases.Unalias(t).(*types.Named) + return +} + +// Unpointer returns T given *T or an alias thereof. +// For all other types it is the identity function. +// It does not look at underlying types. +// The result may be an alias. +// +// Use this function to strip off the optional pointer on a receiver +// in a field or method selection, without losing the named type +// (which is needed to compute the method set). +// +// See also [typeparams.MustDeref], which removes one level of +// indirection from the type, regardless of named types (analogous to +// a LOAD instruction). +func Unpointer(t types.Type) types.Type { + if ptr, ok := aliases.Unalias(t).(*types.Pointer); ok { + return ptr.Elem() + } + return t +} diff --git a/vendor/golang.org/x/tools/internal/typesinternal/toonew.go b/vendor/golang.org/x/tools/internal/typesinternal/toonew.go new file mode 100644 index 000000000..cc86487ea --- /dev/null +++ b/vendor/golang.org/x/tools/internal/typesinternal/toonew.go @@ -0,0 +1,89 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package typesinternal + +import ( + "go/types" + + "golang.org/x/tools/internal/stdlib" + "golang.org/x/tools/internal/versions" +) + +// TooNewStdSymbols computes the set of package-level symbols +// exported by pkg that are not available at the specified version. +// The result maps each symbol to its minimum version. +// +// The pkg is allowed to contain type errors. +func TooNewStdSymbols(pkg *types.Package, version string) map[types.Object]string { + disallowed := make(map[types.Object]string) + + // Pass 1: package-level symbols. + symbols := stdlib.PackageSymbols[pkg.Path()] + for _, sym := range symbols { + symver := sym.Version.String() + if versions.Before(version, symver) { + switch sym.Kind { + case stdlib.Func, stdlib.Var, stdlib.Const, stdlib.Type: + disallowed[pkg.Scope().Lookup(sym.Name)] = symver + } + } + } + + // Pass 2: fields and methods. + // + // We allow fields and methods if their associated type is + // disallowed, as otherwise we would report false positives + // for compatibility shims. Consider: + // + // //go:build go1.22 + // type T struct { F std.Real } // correct new API + // + // //go:build !go1.22 + // type T struct { F fake } // shim + // type fake struct { ... } + // func (fake) M () {} + // + // These alternative declarations of T use either the std.Real + // type, introduced in go1.22, or a fake type, for the field + // F. (The fakery could be arbitrarily deep, involving more + // nested fields and methods than are shown here.) Clients + // that use the compatibility shim T will compile with any + // version of go, whether older or newer than go1.22, but only + // the newer version will use the std.Real implementation. + // + // Now consider a reference to method M in new(T).F.M() in a + // module that requires a minimum of go1.21. The analysis may + // occur using a version of Go higher than 1.21, selecting the + // first version of T, so the method M is Real.M. This would + // spuriously cause the analyzer to report a reference to a + // too-new symbol even though this expression compiles just + // fine (with the fake implementation) using go1.21. + for _, sym := range symbols { + symVersion := sym.Version.String() + if !versions.Before(version, symVersion) { + continue // allowed + } + + var obj types.Object + switch sym.Kind { + case stdlib.Field: + typename, name := sym.SplitField() + if t := pkg.Scope().Lookup(typename); t != nil && disallowed[t] == "" { + obj, _, _ = types.LookupFieldOrMethod(t.Type(), false, pkg, name) + } + + case stdlib.Method: + ptr, recvname, name := sym.SplitMethod() + if t := pkg.Scope().Lookup(recvname); t != nil && disallowed[t] == "" { + obj, _, _ = types.LookupFieldOrMethod(t.Type(), ptr, pkg, name) + } + } + if obj != nil { + disallowed[obj] = symVersion + } + } + + return disallowed +} diff --git a/vendor/golang.org/x/tools/internal/typesinternal/types.go b/vendor/golang.org/x/tools/internal/typesinternal/types.go index ce7d4351b..7c77c2fbc 100644 --- a/vendor/golang.org/x/tools/internal/typesinternal/types.go +++ b/vendor/golang.org/x/tools/internal/typesinternal/types.go @@ -48,5 +48,3 @@ func ReadGo116ErrorData(err types.Error) (code ErrorCode, start, end token.Pos, } return ErrorCode(data[0]), token.Pos(data[1]), token.Pos(data[2]), true } - -var SetGoVersion = func(conf *types.Config, version string) bool { return false } diff --git a/vendor/golang.org/x/tools/internal/typesinternal/types_118.go b/vendor/golang.org/x/tools/internal/typesinternal/types_118.go deleted file mode 100644 index a42b072a6..000000000 --- a/vendor/golang.org/x/tools/internal/typesinternal/types_118.go +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2021 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build go1.18 -// +build go1.18 - -package typesinternal - -import ( - "go/types" -) - -func init() { - SetGoVersion = func(conf *types.Config, version string) bool { - conf.GoVersion = version - return true - } -} diff --git a/vendor/golang.org/x/tools/internal/versions/features.go b/vendor/golang.org/x/tools/internal/versions/features.go new file mode 100644 index 000000000..b53f17861 --- /dev/null +++ b/vendor/golang.org/x/tools/internal/versions/features.go @@ -0,0 +1,43 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package versions + +// This file contains predicates for working with file versions to +// decide when a tool should consider a language feature enabled. + +// GoVersions that features in x/tools can be gated to. +const ( + Go1_18 = "go1.18" + Go1_19 = "go1.19" + Go1_20 = "go1.20" + Go1_21 = "go1.21" + Go1_22 = "go1.22" +) + +// Future is an invalid unknown Go version sometime in the future. +// Do not use directly with Compare. +const Future = "" + +// AtLeast reports whether the file version v comes after a Go release. +// +// Use this predicate to enable a behavior once a certain Go release +// has happened (and stays enabled in the future). +func AtLeast(v, release string) bool { + if v == Future { + return true // an unknown future version is always after y. + } + return Compare(Lang(v), Lang(release)) >= 0 +} + +// Before reports whether the file version v is strictly before a Go release. +// +// Use this predicate to disable a behavior once a certain Go release +// has happened (and stays enabled in the future). +func Before(v, release string) bool { + if v == Future { + return false // an unknown future version happens after y. + } + return Compare(Lang(v), Lang(release)) < 0 +} diff --git a/vendor/golang.org/x/tools/internal/versions/toolchain.go b/vendor/golang.org/x/tools/internal/versions/toolchain.go new file mode 100644 index 000000000..377bf7a53 --- /dev/null +++ b/vendor/golang.org/x/tools/internal/versions/toolchain.go @@ -0,0 +1,14 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package versions + +// toolchain is maximum version (<1.22) that the go toolchain used +// to build the current tool is known to support. +// +// When a tool is built with >=1.22, the value of toolchain is unused. +// +// x/tools does not support building with go <1.18. So we take this +// as the minimum possible maximum. +var toolchain string = Go1_18 diff --git a/vendor/golang.org/x/tools/internal/versions/toolchain_go119.go b/vendor/golang.org/x/tools/internal/versions/toolchain_go119.go new file mode 100644 index 000000000..f65beed9d --- /dev/null +++ b/vendor/golang.org/x/tools/internal/versions/toolchain_go119.go @@ -0,0 +1,14 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build go1.19 +// +build go1.19 + +package versions + +func init() { + if Compare(toolchain, Go1_19) < 0 { + toolchain = Go1_19 + } +} diff --git a/vendor/golang.org/x/tools/internal/versions/toolchain_go120.go b/vendor/golang.org/x/tools/internal/versions/toolchain_go120.go new file mode 100644 index 000000000..1a9efa126 --- /dev/null +++ b/vendor/golang.org/x/tools/internal/versions/toolchain_go120.go @@ -0,0 +1,14 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build go1.20 +// +build go1.20 + +package versions + +func init() { + if Compare(toolchain, Go1_20) < 0 { + toolchain = Go1_20 + } +} diff --git a/vendor/golang.org/x/tools/internal/versions/toolchain_go121.go b/vendor/golang.org/x/tools/internal/versions/toolchain_go121.go new file mode 100644 index 000000000..b7ef216df --- /dev/null +++ b/vendor/golang.org/x/tools/internal/versions/toolchain_go121.go @@ -0,0 +1,14 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build go1.21 +// +build go1.21 + +package versions + +func init() { + if Compare(toolchain, Go1_21) < 0 { + toolchain = Go1_21 + } +} diff --git a/vendor/golang.org/x/tools/internal/versions/types_go121.go b/vendor/golang.org/x/tools/internal/versions/types_go121.go index a7b79207a..b4345d334 100644 --- a/vendor/golang.org/x/tools/internal/versions/types_go121.go +++ b/vendor/golang.org/x/tools/internal/versions/types_go121.go @@ -12,9 +12,19 @@ import ( "go/types" ) -// FileVersions always reports the a file's Go version as the -// zero version at this Go version. -func FileVersions(info *types.Info, file *ast.File) string { return "" } +// FileVersion returns a language version (<=1.21) derived from runtime.Version() +// or an unknown future version. +func FileVersion(info *types.Info, file *ast.File) string { + // In x/tools built with Go <= 1.21, we do not have Info.FileVersions + // available. We use a go version derived from the toolchain used to + // compile the tool by default. + // This will be <= go1.21. We take this as the maximum version that + // this tool can support. + // + // There are no features currently in x/tools that need to tell fine grained + // differences for versions <1.22. + return toolchain +} -// InitFileVersions is a noop at this Go version. +// InitFileVersions is a noop when compiled with this Go version. func InitFileVersions(*types.Info) {} diff --git a/vendor/golang.org/x/tools/internal/versions/types_go122.go b/vendor/golang.org/x/tools/internal/versions/types_go122.go index 7b9ba89a8..aac5db62c 100644 --- a/vendor/golang.org/x/tools/internal/versions/types_go122.go +++ b/vendor/golang.org/x/tools/internal/versions/types_go122.go @@ -12,10 +12,27 @@ import ( "go/types" ) -// FileVersions maps a file to the file's semantic Go version. -// The reported version is the zero version if a version cannot be determined. -func FileVersions(info *types.Info, file *ast.File) string { - return info.FileVersions[file] +// FileVersion returns a file's Go version. +// The reported version is an unknown Future version if a +// version cannot be determined. +func FileVersion(info *types.Info, file *ast.File) string { + // In tools built with Go >= 1.22, the Go version of a file + // follow a cascades of sources: + // 1) types.Info.FileVersion, which follows the cascade: + // 1.a) file version (ast.File.GoVersion), + // 1.b) the package version (types.Config.GoVersion), or + // 2) is some unknown Future version. + // + // File versions require a valid package version to be provided to types + // in Config.GoVersion. Config.GoVersion is either from the package's module + // or the toolchain (go run). This value should be provided by go/packages + // or unitchecker.Config.GoVersion. + if v := info.FileVersions[file]; IsValid(v) { + return v + } + // Note: we could instead return runtime.Version() [if valid]. + // This would act as a max version on what a tool can support. + return Future } // InitFileVersions initializes info to record Go versions for Go files. diff --git a/vendor/golang.org/x/tools/internal/versions/versions.go b/vendor/golang.org/x/tools/internal/versions/versions.go index e16f6c33a..8d1f7453d 100644 --- a/vendor/golang.org/x/tools/internal/versions/versions.go +++ b/vendor/golang.org/x/tools/internal/versions/versions.go @@ -4,6 +4,10 @@ package versions +import ( + "strings" +) + // Note: If we use build tags to use go/versions when go >=1.22, // we run into go.dev/issue/53737. Under some operations users would see an // import of "go/versions" even if they would not compile the file. @@ -45,6 +49,7 @@ func IsValid(x string) bool { return isValid(stripGo(x)) } // stripGo converts from a "go1.21" version to a "1.21" version. // If v does not start with "go", stripGo returns the empty string (a known invalid version). func stripGo(v string) string { + v, _, _ = strings.Cut(v, "-") // strip -bigcorp suffix. if len(v) < 2 || v[:2] != "go" { return "" } diff --git a/vendor/google.golang.org/appengine/internal/api.go b/vendor/google.golang.org/appengine/internal/api.go deleted file mode 100644 index 0569f5dd4..000000000 --- a/vendor/google.golang.org/appengine/internal/api.go +++ /dev/null @@ -1,653 +0,0 @@ -// Copyright 2011 Google Inc. All rights reserved. -// Use of this source code is governed by the Apache 2.0 -// license that can be found in the LICENSE file. - -//go:build !appengine -// +build !appengine - -package internal - -import ( - "bytes" - "context" - "errors" - "fmt" - "io/ioutil" - "log" - "net" - "net/http" - "net/url" - "os" - "runtime" - "strconv" - "strings" - "sync" - "sync/atomic" - "time" - - "github.com/golang/protobuf/proto" - - basepb "google.golang.org/appengine/internal/base" - logpb "google.golang.org/appengine/internal/log" - remotepb "google.golang.org/appengine/internal/remote_api" -) - -const ( - apiPath = "/rpc_http" -) - -var ( - // Incoming headers. - ticketHeader = http.CanonicalHeaderKey("X-AppEngine-API-Ticket") - dapperHeader = http.CanonicalHeaderKey("X-Google-DapperTraceInfo") - traceHeader = http.CanonicalHeaderKey("X-Cloud-Trace-Context") - curNamespaceHeader = http.CanonicalHeaderKey("X-AppEngine-Current-Namespace") - userIPHeader = http.CanonicalHeaderKey("X-AppEngine-User-IP") - remoteAddrHeader = http.CanonicalHeaderKey("X-AppEngine-Remote-Addr") - devRequestIdHeader = http.CanonicalHeaderKey("X-Appengine-Dev-Request-Id") - - // Outgoing headers. - apiEndpointHeader = http.CanonicalHeaderKey("X-Google-RPC-Service-Endpoint") - apiEndpointHeaderValue = []string{"app-engine-apis"} - apiMethodHeader = http.CanonicalHeaderKey("X-Google-RPC-Service-Method") - apiMethodHeaderValue = []string{"/VMRemoteAPI.CallRemoteAPI"} - apiDeadlineHeader = http.CanonicalHeaderKey("X-Google-RPC-Service-Deadline") - apiContentType = http.CanonicalHeaderKey("Content-Type") - apiContentTypeValue = []string{"application/octet-stream"} - logFlushHeader = http.CanonicalHeaderKey("X-AppEngine-Log-Flush-Count") - - apiHTTPClient = &http.Client{ - Transport: &http.Transport{ - Proxy: http.ProxyFromEnvironment, - Dial: limitDial, - MaxIdleConns: 1000, - MaxIdleConnsPerHost: 10000, - IdleConnTimeout: 90 * time.Second, - }, - } -) - -func apiURL(ctx context.Context) *url.URL { - host, port := "appengine.googleapis.internal", "10001" - if h := os.Getenv("API_HOST"); h != "" { - host = h - } - if hostOverride := ctx.Value(apiHostOverrideKey); hostOverride != nil { - host = hostOverride.(string) - } - if p := os.Getenv("API_PORT"); p != "" { - port = p - } - if portOverride := ctx.Value(apiPortOverrideKey); portOverride != nil { - port = portOverride.(string) - } - return &url.URL{ - Scheme: "http", - Host: host + ":" + port, - Path: apiPath, - } -} - -// Middleware wraps an http handler so that it can make GAE API calls -func Middleware(next http.Handler) http.Handler { - return handleHTTPMiddleware(executeRequestSafelyMiddleware(next)) -} - -func handleHTTPMiddleware(next http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - c := &aeContext{ - req: r, - outHeader: w.Header(), - } - r = r.WithContext(withContext(r.Context(), c)) - c.req = r - - stopFlushing := make(chan int) - - // Patch up RemoteAddr so it looks reasonable. - if addr := r.Header.Get(userIPHeader); addr != "" { - r.RemoteAddr = addr - } else if addr = r.Header.Get(remoteAddrHeader); addr != "" { - r.RemoteAddr = addr - } else { - // Should not normally reach here, but pick a sensible default anyway. - r.RemoteAddr = "127.0.0.1" - } - // The address in the headers will most likely be of these forms: - // 123.123.123.123 - // 2001:db8::1 - // net/http.Request.RemoteAddr is specified to be in "IP:port" form. - if _, _, err := net.SplitHostPort(r.RemoteAddr); err != nil { - // Assume the remote address is only a host; add a default port. - r.RemoteAddr = net.JoinHostPort(r.RemoteAddr, "80") - } - - if logToLogservice() { - // Start goroutine responsible for flushing app logs. - // This is done after adding c to ctx.m (and stopped before removing it) - // because flushing logs requires making an API call. - go c.logFlusher(stopFlushing) - } - - next.ServeHTTP(c, r) - c.outHeader = nil // make sure header changes aren't respected any more - - flushed := make(chan struct{}) - if logToLogservice() { - stopFlushing <- 1 // any logging beyond this point will be dropped - - // Flush any pending logs asynchronously. - c.pendingLogs.Lock() - flushes := c.pendingLogs.flushes - if len(c.pendingLogs.lines) > 0 { - flushes++ - } - c.pendingLogs.Unlock() - go func() { - defer close(flushed) - // Force a log flush, because with very short requests we - // may not ever flush logs. - c.flushLog(true) - }() - w.Header().Set(logFlushHeader, strconv.Itoa(flushes)) - } - - // Avoid nil Write call if c.Write is never called. - if c.outCode != 0 { - w.WriteHeader(c.outCode) - } - if c.outBody != nil { - w.Write(c.outBody) - } - if logToLogservice() { - // Wait for the last flush to complete before returning, - // otherwise the security ticket will not be valid. - <-flushed - } - }) -} - -func executeRequestSafelyMiddleware(next http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - defer func() { - if x := recover(); x != nil { - c := w.(*aeContext) - logf(c, 4, "%s", renderPanic(x)) // 4 == critical - c.outCode = 500 - } - }() - - next.ServeHTTP(w, r) - }) -} - -func renderPanic(x interface{}) string { - buf := make([]byte, 16<<10) // 16 KB should be plenty - buf = buf[:runtime.Stack(buf, false)] - - // Remove the first few stack frames: - // this func - // the recover closure in the caller - // That will root the stack trace at the site of the panic. - const ( - skipStart = "internal.renderPanic" - skipFrames = 2 - ) - start := bytes.Index(buf, []byte(skipStart)) - p := start - for i := 0; i < skipFrames*2 && p+1 < len(buf); i++ { - p = bytes.IndexByte(buf[p+1:], '\n') + p + 1 - if p < 0 { - break - } - } - if p >= 0 { - // buf[start:p+1] is the block to remove. - // Copy buf[p+1:] over buf[start:] and shrink buf. - copy(buf[start:], buf[p+1:]) - buf = buf[:len(buf)-(p+1-start)] - } - - // Add panic heading. - head := fmt.Sprintf("panic: %v\n\n", x) - if len(head) > len(buf) { - // Extremely unlikely to happen. - return head - } - copy(buf[len(head):], buf) - copy(buf, head) - - return string(buf) -} - -// aeContext represents the aeContext of an in-flight HTTP request. -// It implements the appengine.Context and http.ResponseWriter interfaces. -type aeContext struct { - req *http.Request - - outCode int - outHeader http.Header - outBody []byte - - pendingLogs struct { - sync.Mutex - lines []*logpb.UserAppLogLine - flushes int - } -} - -var contextKey = "holds a *context" - -// jointContext joins two contexts in a superficial way. -// It takes values and timeouts from a base context, and only values from another context. -type jointContext struct { - base context.Context - valuesOnly context.Context -} - -func (c jointContext) Deadline() (time.Time, bool) { - return c.base.Deadline() -} - -func (c jointContext) Done() <-chan struct{} { - return c.base.Done() -} - -func (c jointContext) Err() error { - return c.base.Err() -} - -func (c jointContext) Value(key interface{}) interface{} { - if val := c.base.Value(key); val != nil { - return val - } - return c.valuesOnly.Value(key) -} - -// fromContext returns the App Engine context or nil if ctx is not -// derived from an App Engine context. -func fromContext(ctx context.Context) *aeContext { - c, _ := ctx.Value(&contextKey).(*aeContext) - return c -} - -func withContext(parent context.Context, c *aeContext) context.Context { - ctx := context.WithValue(parent, &contextKey, c) - if ns := c.req.Header.Get(curNamespaceHeader); ns != "" { - ctx = withNamespace(ctx, ns) - } - return ctx -} - -func toContext(c *aeContext) context.Context { - return withContext(context.Background(), c) -} - -func IncomingHeaders(ctx context.Context) http.Header { - if c := fromContext(ctx); c != nil { - return c.req.Header - } - return nil -} - -func ReqContext(req *http.Request) context.Context { - return req.Context() -} - -func WithContext(parent context.Context, req *http.Request) context.Context { - return jointContext{ - base: parent, - valuesOnly: req.Context(), - } -} - -// RegisterTestRequest registers the HTTP request req for testing, such that -// any API calls are sent to the provided URL. -// It should only be used by aetest package. -func RegisterTestRequest(req *http.Request, apiURL *url.URL, appID string) *http.Request { - ctx := req.Context() - ctx = withAPIHostOverride(ctx, apiURL.Hostname()) - ctx = withAPIPortOverride(ctx, apiURL.Port()) - ctx = WithAppIDOverride(ctx, appID) - - // use the unregistered request as a placeholder so that withContext can read the headers - c := &aeContext{req: req} - c.req = req.WithContext(withContext(ctx, c)) - return c.req -} - -var errTimeout = &CallError{ - Detail: "Deadline exceeded", - Code: int32(remotepb.RpcError_CANCELLED), - Timeout: true, -} - -func (c *aeContext) Header() http.Header { return c.outHeader } - -// Copied from $GOROOT/src/pkg/net/http/transfer.go. Some response status -// codes do not permit a response body (nor response entity headers such as -// Content-Length, Content-Type, etc). -func bodyAllowedForStatus(status int) bool { - switch { - case status >= 100 && status <= 199: - return false - case status == 204: - return false - case status == 304: - return false - } - return true -} - -func (c *aeContext) Write(b []byte) (int, error) { - if c.outCode == 0 { - c.WriteHeader(http.StatusOK) - } - if len(b) > 0 && !bodyAllowedForStatus(c.outCode) { - return 0, http.ErrBodyNotAllowed - } - c.outBody = append(c.outBody, b...) - return len(b), nil -} - -func (c *aeContext) WriteHeader(code int) { - if c.outCode != 0 { - logf(c, 3, "WriteHeader called multiple times on request.") // error level - return - } - c.outCode = code -} - -func post(ctx context.Context, body []byte, timeout time.Duration) (b []byte, err error) { - apiURL := apiURL(ctx) - hreq := &http.Request{ - Method: "POST", - URL: apiURL, - Header: http.Header{ - apiEndpointHeader: apiEndpointHeaderValue, - apiMethodHeader: apiMethodHeaderValue, - apiContentType: apiContentTypeValue, - apiDeadlineHeader: []string{strconv.FormatFloat(timeout.Seconds(), 'f', -1, 64)}, - }, - Body: ioutil.NopCloser(bytes.NewReader(body)), - ContentLength: int64(len(body)), - Host: apiURL.Host, - } - c := fromContext(ctx) - if c != nil { - if info := c.req.Header.Get(dapperHeader); info != "" { - hreq.Header.Set(dapperHeader, info) - } - if info := c.req.Header.Get(traceHeader); info != "" { - hreq.Header.Set(traceHeader, info) - } - } - - tr := apiHTTPClient.Transport.(*http.Transport) - - var timedOut int32 // atomic; set to 1 if timed out - t := time.AfterFunc(timeout, func() { - atomic.StoreInt32(&timedOut, 1) - tr.CancelRequest(hreq) - }) - defer t.Stop() - defer func() { - // Check if timeout was exceeded. - if atomic.LoadInt32(&timedOut) != 0 { - err = errTimeout - } - }() - - hresp, err := apiHTTPClient.Do(hreq) - if err != nil { - return nil, &CallError{ - Detail: fmt.Sprintf("service bridge HTTP failed: %v", err), - Code: int32(remotepb.RpcError_UNKNOWN), - } - } - defer hresp.Body.Close() - hrespBody, err := ioutil.ReadAll(hresp.Body) - if hresp.StatusCode != 200 { - return nil, &CallError{ - Detail: fmt.Sprintf("service bridge returned HTTP %d (%q)", hresp.StatusCode, hrespBody), - Code: int32(remotepb.RpcError_UNKNOWN), - } - } - if err != nil { - return nil, &CallError{ - Detail: fmt.Sprintf("service bridge response bad: %v", err), - Code: int32(remotepb.RpcError_UNKNOWN), - } - } - return hrespBody, nil -} - -func Call(ctx context.Context, service, method string, in, out proto.Message) error { - if ns := NamespaceFromContext(ctx); ns != "" { - if fn, ok := NamespaceMods[service]; ok { - fn(in, ns) - } - } - - if f, ctx, ok := callOverrideFromContext(ctx); ok { - return f(ctx, service, method, in, out) - } - - // Handle already-done contexts quickly. - select { - case <-ctx.Done(): - return ctx.Err() - default: - } - - c := fromContext(ctx) - - // Apply transaction modifications if we're in a transaction. - if t := transactionFromContext(ctx); t != nil { - if t.finished { - return errors.New("transaction aeContext has expired") - } - applyTransaction(in, &t.transaction) - } - - // Default RPC timeout is 60s. - timeout := 60 * time.Second - if deadline, ok := ctx.Deadline(); ok { - timeout = deadline.Sub(time.Now()) - } - - data, err := proto.Marshal(in) - if err != nil { - return err - } - - ticket := "" - if c != nil { - ticket = c.req.Header.Get(ticketHeader) - if dri := c.req.Header.Get(devRequestIdHeader); IsDevAppServer() && dri != "" { - ticket = dri - } - } - req := &remotepb.Request{ - ServiceName: &service, - Method: &method, - Request: data, - RequestId: &ticket, - } - hreqBody, err := proto.Marshal(req) - if err != nil { - return err - } - - hrespBody, err := post(ctx, hreqBody, timeout) - if err != nil { - return err - } - - res := &remotepb.Response{} - if err := proto.Unmarshal(hrespBody, res); err != nil { - return err - } - if res.RpcError != nil { - ce := &CallError{ - Detail: res.RpcError.GetDetail(), - Code: *res.RpcError.Code, - } - switch remotepb.RpcError_ErrorCode(ce.Code) { - case remotepb.RpcError_CANCELLED, remotepb.RpcError_DEADLINE_EXCEEDED: - ce.Timeout = true - } - return ce - } - if res.ApplicationError != nil { - return &APIError{ - Service: *req.ServiceName, - Detail: res.ApplicationError.GetDetail(), - Code: *res.ApplicationError.Code, - } - } - if res.Exception != nil || res.JavaException != nil { - // This shouldn't happen, but let's be defensive. - return &CallError{ - Detail: "service bridge returned exception", - Code: int32(remotepb.RpcError_UNKNOWN), - } - } - return proto.Unmarshal(res.Response, out) -} - -func (c *aeContext) Request() *http.Request { - return c.req -} - -func (c *aeContext) addLogLine(ll *logpb.UserAppLogLine) { - // Truncate long log lines. - // TODO(dsymonds): Check if this is still necessary. - const lim = 8 << 10 - if len(*ll.Message) > lim { - suffix := fmt.Sprintf("...(length %d)", len(*ll.Message)) - ll.Message = proto.String((*ll.Message)[:lim-len(suffix)] + suffix) - } - - c.pendingLogs.Lock() - c.pendingLogs.lines = append(c.pendingLogs.lines, ll) - c.pendingLogs.Unlock() -} - -var logLevelName = map[int64]string{ - 0: "DEBUG", - 1: "INFO", - 2: "WARNING", - 3: "ERROR", - 4: "CRITICAL", -} - -func logf(c *aeContext, level int64, format string, args ...interface{}) { - if c == nil { - panic("not an App Engine aeContext") - } - s := fmt.Sprintf(format, args...) - s = strings.TrimRight(s, "\n") // Remove any trailing newline characters. - if logToLogservice() { - c.addLogLine(&logpb.UserAppLogLine{ - TimestampUsec: proto.Int64(time.Now().UnixNano() / 1e3), - Level: &level, - Message: &s, - }) - } - // Log to stdout if not deployed - if !IsSecondGen() { - log.Print(logLevelName[level] + ": " + s) - } -} - -// flushLog attempts to flush any pending logs to the appserver. -// It should not be called concurrently. -func (c *aeContext) flushLog(force bool) (flushed bool) { - c.pendingLogs.Lock() - // Grab up to 30 MB. We can get away with up to 32 MB, but let's be cautious. - n, rem := 0, 30<<20 - for ; n < len(c.pendingLogs.lines); n++ { - ll := c.pendingLogs.lines[n] - // Each log line will require about 3 bytes of overhead. - nb := proto.Size(ll) + 3 - if nb > rem { - break - } - rem -= nb - } - lines := c.pendingLogs.lines[:n] - c.pendingLogs.lines = c.pendingLogs.lines[n:] - c.pendingLogs.Unlock() - - if len(lines) == 0 && !force { - // Nothing to flush. - return false - } - - rescueLogs := false - defer func() { - if rescueLogs { - c.pendingLogs.Lock() - c.pendingLogs.lines = append(lines, c.pendingLogs.lines...) - c.pendingLogs.Unlock() - } - }() - - buf, err := proto.Marshal(&logpb.UserAppLogGroup{ - LogLine: lines, - }) - if err != nil { - log.Printf("internal.flushLog: marshaling UserAppLogGroup: %v", err) - rescueLogs = true - return false - } - - req := &logpb.FlushRequest{ - Logs: buf, - } - res := &basepb.VoidProto{} - c.pendingLogs.Lock() - c.pendingLogs.flushes++ - c.pendingLogs.Unlock() - if err := Call(toContext(c), "logservice", "Flush", req, res); err != nil { - log.Printf("internal.flushLog: Flush RPC: %v", err) - rescueLogs = true - return false - } - return true -} - -const ( - // Log flushing parameters. - flushInterval = 1 * time.Second - forceFlushInterval = 60 * time.Second -) - -func (c *aeContext) logFlusher(stop <-chan int) { - lastFlush := time.Now() - tick := time.NewTicker(flushInterval) - for { - select { - case <-stop: - // Request finished. - tick.Stop() - return - case <-tick.C: - force := time.Now().Sub(lastFlush) > forceFlushInterval - if c.flushLog(force) { - lastFlush = time.Now() - } - } - } -} - -func ContextForTesting(req *http.Request) context.Context { - return toContext(&aeContext{req: req}) -} - -func logToLogservice() bool { - // TODO: replace logservice with json structured logs to $LOG_DIR/app.log.json - // where $LOG_DIR is /var/log in prod and some tmpdir in dev - return os.Getenv("LOG_TO_LOGSERVICE") != "0" -} diff --git a/vendor/google.golang.org/appengine/internal/api_classic.go b/vendor/google.golang.org/appengine/internal/api_classic.go deleted file mode 100644 index 87c33c798..000000000 --- a/vendor/google.golang.org/appengine/internal/api_classic.go +++ /dev/null @@ -1,170 +0,0 @@ -// Copyright 2015 Google Inc. All rights reserved. -// Use of this source code is governed by the Apache 2.0 -// license that can be found in the LICENSE file. - -//go:build appengine -// +build appengine - -package internal - -import ( - "context" - "errors" - "fmt" - "net/http" - "time" - - "appengine" - "appengine_internal" - basepb "appengine_internal/base" - - "github.com/golang/protobuf/proto" -) - -var contextKey = "holds an appengine.Context" - -// fromContext returns the App Engine context or nil if ctx is not -// derived from an App Engine context. -func fromContext(ctx context.Context) appengine.Context { - c, _ := ctx.Value(&contextKey).(appengine.Context) - return c -} - -// This is only for classic App Engine adapters. -func ClassicContextFromContext(ctx context.Context) (appengine.Context, error) { - c := fromContext(ctx) - if c == nil { - return nil, errNotAppEngineContext - } - return c, nil -} - -func withContext(parent context.Context, c appengine.Context) context.Context { - ctx := context.WithValue(parent, &contextKey, c) - - s := &basepb.StringProto{} - c.Call("__go__", "GetNamespace", &basepb.VoidProto{}, s, nil) - if ns := s.GetValue(); ns != "" { - ctx = NamespacedContext(ctx, ns) - } - - return ctx -} - -func IncomingHeaders(ctx context.Context) http.Header { - if c := fromContext(ctx); c != nil { - if req, ok := c.Request().(*http.Request); ok { - return req.Header - } - } - return nil -} - -func ReqContext(req *http.Request) context.Context { - return WithContext(context.Background(), req) -} - -func WithContext(parent context.Context, req *http.Request) context.Context { - c := appengine.NewContext(req) - return withContext(parent, c) -} - -type testingContext struct { - appengine.Context - - req *http.Request -} - -func (t *testingContext) FullyQualifiedAppID() string { return "dev~testcontext" } -func (t *testingContext) Call(service, method string, _, _ appengine_internal.ProtoMessage, _ *appengine_internal.CallOptions) error { - if service == "__go__" && method == "GetNamespace" { - return nil - } - return fmt.Errorf("testingContext: unsupported Call") -} -func (t *testingContext) Request() interface{} { return t.req } - -func ContextForTesting(req *http.Request) context.Context { - return withContext(context.Background(), &testingContext{req: req}) -} - -func Call(ctx context.Context, service, method string, in, out proto.Message) error { - if ns := NamespaceFromContext(ctx); ns != "" { - if fn, ok := NamespaceMods[service]; ok { - fn(in, ns) - } - } - - if f, ctx, ok := callOverrideFromContext(ctx); ok { - return f(ctx, service, method, in, out) - } - - // Handle already-done contexts quickly. - select { - case <-ctx.Done(): - return ctx.Err() - default: - } - - c := fromContext(ctx) - if c == nil { - // Give a good error message rather than a panic lower down. - return errNotAppEngineContext - } - - // Apply transaction modifications if we're in a transaction. - if t := transactionFromContext(ctx); t != nil { - if t.finished { - return errors.New("transaction context has expired") - } - applyTransaction(in, &t.transaction) - } - - var opts *appengine_internal.CallOptions - if d, ok := ctx.Deadline(); ok { - opts = &appengine_internal.CallOptions{ - Timeout: d.Sub(time.Now()), - } - } - - err := c.Call(service, method, in, out, opts) - switch v := err.(type) { - case *appengine_internal.APIError: - return &APIError{ - Service: v.Service, - Detail: v.Detail, - Code: v.Code, - } - case *appengine_internal.CallError: - return &CallError{ - Detail: v.Detail, - Code: v.Code, - Timeout: v.Timeout, - } - } - return err -} - -func Middleware(next http.Handler) http.Handler { - panic("Middleware called; this should be impossible") -} - -func logf(c appengine.Context, level int64, format string, args ...interface{}) { - var fn func(format string, args ...interface{}) - switch level { - case 0: - fn = c.Debugf - case 1: - fn = c.Infof - case 2: - fn = c.Warningf - case 3: - fn = c.Errorf - case 4: - fn = c.Criticalf - default: - // This shouldn't happen. - fn = c.Criticalf - } - fn(format, args...) -} diff --git a/vendor/google.golang.org/appengine/internal/api_common.go b/vendor/google.golang.org/appengine/internal/api_common.go deleted file mode 100644 index 5b95c13d9..000000000 --- a/vendor/google.golang.org/appengine/internal/api_common.go +++ /dev/null @@ -1,141 +0,0 @@ -// Copyright 2015 Google Inc. All rights reserved. -// Use of this source code is governed by the Apache 2.0 -// license that can be found in the LICENSE file. - -package internal - -import ( - "context" - "errors" - "os" - - "github.com/golang/protobuf/proto" -) - -type ctxKey string - -func (c ctxKey) String() string { - return "appengine context key: " + string(c) -} - -var errNotAppEngineContext = errors.New("not an App Engine context") - -type CallOverrideFunc func(ctx context.Context, service, method string, in, out proto.Message) error - -var callOverrideKey = "holds []CallOverrideFunc" - -func WithCallOverride(ctx context.Context, f CallOverrideFunc) context.Context { - // We avoid appending to any existing call override - // so we don't risk overwriting a popped stack below. - var cofs []CallOverrideFunc - if uf, ok := ctx.Value(&callOverrideKey).([]CallOverrideFunc); ok { - cofs = append(cofs, uf...) - } - cofs = append(cofs, f) - return context.WithValue(ctx, &callOverrideKey, cofs) -} - -func callOverrideFromContext(ctx context.Context) (CallOverrideFunc, context.Context, bool) { - cofs, _ := ctx.Value(&callOverrideKey).([]CallOverrideFunc) - if len(cofs) == 0 { - return nil, nil, false - } - // We found a list of overrides; grab the last, and reconstitute a - // context that will hide it. - f := cofs[len(cofs)-1] - ctx = context.WithValue(ctx, &callOverrideKey, cofs[:len(cofs)-1]) - return f, ctx, true -} - -type logOverrideFunc func(level int64, format string, args ...interface{}) - -var logOverrideKey = "holds a logOverrideFunc" - -func WithLogOverride(ctx context.Context, f logOverrideFunc) context.Context { - return context.WithValue(ctx, &logOverrideKey, f) -} - -var appIDOverrideKey = "holds a string, being the full app ID" - -func WithAppIDOverride(ctx context.Context, appID string) context.Context { - return context.WithValue(ctx, &appIDOverrideKey, appID) -} - -var apiHostOverrideKey = ctxKey("holds a string, being the alternate API_HOST") - -func withAPIHostOverride(ctx context.Context, apiHost string) context.Context { - return context.WithValue(ctx, apiHostOverrideKey, apiHost) -} - -var apiPortOverrideKey = ctxKey("holds a string, being the alternate API_PORT") - -func withAPIPortOverride(ctx context.Context, apiPort string) context.Context { - return context.WithValue(ctx, apiPortOverrideKey, apiPort) -} - -var namespaceKey = "holds the namespace string" - -func withNamespace(ctx context.Context, ns string) context.Context { - return context.WithValue(ctx, &namespaceKey, ns) -} - -func NamespaceFromContext(ctx context.Context) string { - // If there's no namespace, return the empty string. - ns, _ := ctx.Value(&namespaceKey).(string) - return ns -} - -// FullyQualifiedAppID returns the fully-qualified application ID. -// This may contain a partition prefix (e.g. "s~" for High Replication apps), -// or a domain prefix (e.g. "example.com:"). -func FullyQualifiedAppID(ctx context.Context) string { - if id, ok := ctx.Value(&appIDOverrideKey).(string); ok { - return id - } - return fullyQualifiedAppID(ctx) -} - -func Logf(ctx context.Context, level int64, format string, args ...interface{}) { - if f, ok := ctx.Value(&logOverrideKey).(logOverrideFunc); ok { - f(level, format, args...) - return - } - c := fromContext(ctx) - if c == nil { - panic(errNotAppEngineContext) - } - logf(c, level, format, args...) -} - -// NamespacedContext wraps a Context to support namespaces. -func NamespacedContext(ctx context.Context, namespace string) context.Context { - return withNamespace(ctx, namespace) -} - -// SetTestEnv sets the env variables for testing background ticket in Flex. -func SetTestEnv() func() { - var environ = []struct { - key, value string - }{ - {"GAE_LONG_APP_ID", "my-app-id"}, - {"GAE_MINOR_VERSION", "067924799508853122"}, - {"GAE_MODULE_INSTANCE", "0"}, - {"GAE_MODULE_NAME", "default"}, - {"GAE_MODULE_VERSION", "20150612t184001"}, - } - - for _, v := range environ { - old := os.Getenv(v.key) - os.Setenv(v.key, v.value) - v.value = old - } - return func() { // Restore old environment after the test completes. - for _, v := range environ { - if v.value == "" { - os.Unsetenv(v.key) - continue - } - os.Setenv(v.key, v.value) - } - } -} diff --git a/vendor/google.golang.org/appengine/internal/app_id.go b/vendor/google.golang.org/appengine/internal/app_id.go deleted file mode 100644 index 11df8c07b..000000000 --- a/vendor/google.golang.org/appengine/internal/app_id.go +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2011 Google Inc. All rights reserved. -// Use of this source code is governed by the Apache 2.0 -// license that can be found in the LICENSE file. - -package internal - -import ( - "strings" -) - -func parseFullAppID(appid string) (partition, domain, displayID string) { - if i := strings.Index(appid, "~"); i != -1 { - partition, appid = appid[:i], appid[i+1:] - } - if i := strings.Index(appid, ":"); i != -1 { - domain, appid = appid[:i], appid[i+1:] - } - return partition, domain, appid -} - -// appID returns "appid" or "domain.com:appid". -func appID(fullAppID string) string { - _, dom, dis := parseFullAppID(fullAppID) - if dom != "" { - return dom + ":" + dis - } - return dis -} diff --git a/vendor/google.golang.org/appengine/internal/base/api_base.pb.go b/vendor/google.golang.org/appengine/internal/base/api_base.pb.go deleted file mode 100644 index db4777e68..000000000 --- a/vendor/google.golang.org/appengine/internal/base/api_base.pb.go +++ /dev/null @@ -1,308 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// source: google.golang.org/appengine/internal/base/api_base.proto - -package base - -import proto "github.com/golang/protobuf/proto" -import fmt "fmt" -import math "math" - -// Reference imports to suppress errors if they are not otherwise used. -var _ = proto.Marshal -var _ = fmt.Errorf -var _ = math.Inf - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the proto package it is being compiled against. -// A compilation error at this line likely means your copy of the -// proto package needs to be updated. -const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package - -type StringProto struct { - Value *string `protobuf:"bytes,1,req,name=value" json:"value,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *StringProto) Reset() { *m = StringProto{} } -func (m *StringProto) String() string { return proto.CompactTextString(m) } -func (*StringProto) ProtoMessage() {} -func (*StringProto) Descriptor() ([]byte, []int) { - return fileDescriptor_api_base_9d49f8792e0c1140, []int{0} -} -func (m *StringProto) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_StringProto.Unmarshal(m, b) -} -func (m *StringProto) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_StringProto.Marshal(b, m, deterministic) -} -func (dst *StringProto) XXX_Merge(src proto.Message) { - xxx_messageInfo_StringProto.Merge(dst, src) -} -func (m *StringProto) XXX_Size() int { - return xxx_messageInfo_StringProto.Size(m) -} -func (m *StringProto) XXX_DiscardUnknown() { - xxx_messageInfo_StringProto.DiscardUnknown(m) -} - -var xxx_messageInfo_StringProto proto.InternalMessageInfo - -func (m *StringProto) GetValue() string { - if m != nil && m.Value != nil { - return *m.Value - } - return "" -} - -type Integer32Proto struct { - Value *int32 `protobuf:"varint,1,req,name=value" json:"value,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *Integer32Proto) Reset() { *m = Integer32Proto{} } -func (m *Integer32Proto) String() string { return proto.CompactTextString(m) } -func (*Integer32Proto) ProtoMessage() {} -func (*Integer32Proto) Descriptor() ([]byte, []int) { - return fileDescriptor_api_base_9d49f8792e0c1140, []int{1} -} -func (m *Integer32Proto) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_Integer32Proto.Unmarshal(m, b) -} -func (m *Integer32Proto) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_Integer32Proto.Marshal(b, m, deterministic) -} -func (dst *Integer32Proto) XXX_Merge(src proto.Message) { - xxx_messageInfo_Integer32Proto.Merge(dst, src) -} -func (m *Integer32Proto) XXX_Size() int { - return xxx_messageInfo_Integer32Proto.Size(m) -} -func (m *Integer32Proto) XXX_DiscardUnknown() { - xxx_messageInfo_Integer32Proto.DiscardUnknown(m) -} - -var xxx_messageInfo_Integer32Proto proto.InternalMessageInfo - -func (m *Integer32Proto) GetValue() int32 { - if m != nil && m.Value != nil { - return *m.Value - } - return 0 -} - -type Integer64Proto struct { - Value *int64 `protobuf:"varint,1,req,name=value" json:"value,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *Integer64Proto) Reset() { *m = Integer64Proto{} } -func (m *Integer64Proto) String() string { return proto.CompactTextString(m) } -func (*Integer64Proto) ProtoMessage() {} -func (*Integer64Proto) Descriptor() ([]byte, []int) { - return fileDescriptor_api_base_9d49f8792e0c1140, []int{2} -} -func (m *Integer64Proto) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_Integer64Proto.Unmarshal(m, b) -} -func (m *Integer64Proto) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_Integer64Proto.Marshal(b, m, deterministic) -} -func (dst *Integer64Proto) XXX_Merge(src proto.Message) { - xxx_messageInfo_Integer64Proto.Merge(dst, src) -} -func (m *Integer64Proto) XXX_Size() int { - return xxx_messageInfo_Integer64Proto.Size(m) -} -func (m *Integer64Proto) XXX_DiscardUnknown() { - xxx_messageInfo_Integer64Proto.DiscardUnknown(m) -} - -var xxx_messageInfo_Integer64Proto proto.InternalMessageInfo - -func (m *Integer64Proto) GetValue() int64 { - if m != nil && m.Value != nil { - return *m.Value - } - return 0 -} - -type BoolProto struct { - Value *bool `protobuf:"varint,1,req,name=value" json:"value,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *BoolProto) Reset() { *m = BoolProto{} } -func (m *BoolProto) String() string { return proto.CompactTextString(m) } -func (*BoolProto) ProtoMessage() {} -func (*BoolProto) Descriptor() ([]byte, []int) { - return fileDescriptor_api_base_9d49f8792e0c1140, []int{3} -} -func (m *BoolProto) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_BoolProto.Unmarshal(m, b) -} -func (m *BoolProto) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_BoolProto.Marshal(b, m, deterministic) -} -func (dst *BoolProto) XXX_Merge(src proto.Message) { - xxx_messageInfo_BoolProto.Merge(dst, src) -} -func (m *BoolProto) XXX_Size() int { - return xxx_messageInfo_BoolProto.Size(m) -} -func (m *BoolProto) XXX_DiscardUnknown() { - xxx_messageInfo_BoolProto.DiscardUnknown(m) -} - -var xxx_messageInfo_BoolProto proto.InternalMessageInfo - -func (m *BoolProto) GetValue() bool { - if m != nil && m.Value != nil { - return *m.Value - } - return false -} - -type DoubleProto struct { - Value *float64 `protobuf:"fixed64,1,req,name=value" json:"value,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *DoubleProto) Reset() { *m = DoubleProto{} } -func (m *DoubleProto) String() string { return proto.CompactTextString(m) } -func (*DoubleProto) ProtoMessage() {} -func (*DoubleProto) Descriptor() ([]byte, []int) { - return fileDescriptor_api_base_9d49f8792e0c1140, []int{4} -} -func (m *DoubleProto) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_DoubleProto.Unmarshal(m, b) -} -func (m *DoubleProto) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_DoubleProto.Marshal(b, m, deterministic) -} -func (dst *DoubleProto) XXX_Merge(src proto.Message) { - xxx_messageInfo_DoubleProto.Merge(dst, src) -} -func (m *DoubleProto) XXX_Size() int { - return xxx_messageInfo_DoubleProto.Size(m) -} -func (m *DoubleProto) XXX_DiscardUnknown() { - xxx_messageInfo_DoubleProto.DiscardUnknown(m) -} - -var xxx_messageInfo_DoubleProto proto.InternalMessageInfo - -func (m *DoubleProto) GetValue() float64 { - if m != nil && m.Value != nil { - return *m.Value - } - return 0 -} - -type BytesProto struct { - Value []byte `protobuf:"bytes,1,req,name=value" json:"value,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *BytesProto) Reset() { *m = BytesProto{} } -func (m *BytesProto) String() string { return proto.CompactTextString(m) } -func (*BytesProto) ProtoMessage() {} -func (*BytesProto) Descriptor() ([]byte, []int) { - return fileDescriptor_api_base_9d49f8792e0c1140, []int{5} -} -func (m *BytesProto) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_BytesProto.Unmarshal(m, b) -} -func (m *BytesProto) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_BytesProto.Marshal(b, m, deterministic) -} -func (dst *BytesProto) XXX_Merge(src proto.Message) { - xxx_messageInfo_BytesProto.Merge(dst, src) -} -func (m *BytesProto) XXX_Size() int { - return xxx_messageInfo_BytesProto.Size(m) -} -func (m *BytesProto) XXX_DiscardUnknown() { - xxx_messageInfo_BytesProto.DiscardUnknown(m) -} - -var xxx_messageInfo_BytesProto proto.InternalMessageInfo - -func (m *BytesProto) GetValue() []byte { - if m != nil { - return m.Value - } - return nil -} - -type VoidProto struct { - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *VoidProto) Reset() { *m = VoidProto{} } -func (m *VoidProto) String() string { return proto.CompactTextString(m) } -func (*VoidProto) ProtoMessage() {} -func (*VoidProto) Descriptor() ([]byte, []int) { - return fileDescriptor_api_base_9d49f8792e0c1140, []int{6} -} -func (m *VoidProto) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_VoidProto.Unmarshal(m, b) -} -func (m *VoidProto) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_VoidProto.Marshal(b, m, deterministic) -} -func (dst *VoidProto) XXX_Merge(src proto.Message) { - xxx_messageInfo_VoidProto.Merge(dst, src) -} -func (m *VoidProto) XXX_Size() int { - return xxx_messageInfo_VoidProto.Size(m) -} -func (m *VoidProto) XXX_DiscardUnknown() { - xxx_messageInfo_VoidProto.DiscardUnknown(m) -} - -var xxx_messageInfo_VoidProto proto.InternalMessageInfo - -func init() { - proto.RegisterType((*StringProto)(nil), "appengine.base.StringProto") - proto.RegisterType((*Integer32Proto)(nil), "appengine.base.Integer32Proto") - proto.RegisterType((*Integer64Proto)(nil), "appengine.base.Integer64Proto") - proto.RegisterType((*BoolProto)(nil), "appengine.base.BoolProto") - proto.RegisterType((*DoubleProto)(nil), "appengine.base.DoubleProto") - proto.RegisterType((*BytesProto)(nil), "appengine.base.BytesProto") - proto.RegisterType((*VoidProto)(nil), "appengine.base.VoidProto") -} - -func init() { - proto.RegisterFile("google.golang.org/appengine/internal/base/api_base.proto", fileDescriptor_api_base_9d49f8792e0c1140) -} - -var fileDescriptor_api_base_9d49f8792e0c1140 = []byte{ - // 199 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0xcf, 0x3f, 0x4b, 0xc6, 0x30, - 0x10, 0x06, 0x70, 0x5a, 0xad, 0xb4, 0x57, 0xe9, 0x20, 0x0e, 0x1d, 0xb5, 0x05, 0x71, 0x4a, 0x40, - 0x45, 0x9c, 0x83, 0x8b, 0x9b, 0x28, 0x38, 0xb8, 0x48, 0x8a, 0xc7, 0x11, 0x08, 0xb9, 0x90, 0xa6, - 0x82, 0xdf, 0x5e, 0xda, 0xd2, 0xfa, 0xc2, 0x9b, 0xed, 0xfe, 0xfc, 0xe0, 0xe1, 0x81, 0x27, 0x62, - 0x26, 0x8b, 0x82, 0xd8, 0x6a, 0x47, 0x82, 0x03, 0x49, 0xed, 0x3d, 0x3a, 0x32, 0x0e, 0xa5, 0x71, - 0x11, 0x83, 0xd3, 0x56, 0x0e, 0x7a, 0x44, 0xa9, 0xbd, 0xf9, 0x9a, 0x07, 0xe1, 0x03, 0x47, 0xbe, - 0x68, 0x76, 0x27, 0xe6, 0x6b, 0xd7, 0x43, 0xfd, 0x1e, 0x83, 0x71, 0xf4, 0xba, 0xbc, 0x2f, 0xa1, - 0xf8, 0xd1, 0x76, 0xc2, 0x36, 0xbb, 0xca, 0x6f, 0xab, 0xb7, 0x75, 0xe9, 0x6e, 0xa0, 0x79, 0x71, - 0x11, 0x09, 0xc3, 0xfd, 0x5d, 0xc2, 0x15, 0xc7, 0xee, 0xf1, 0x21, 0xe1, 0x4e, 0x36, 0x77, 0x0d, - 0x95, 0x62, 0xb6, 0x09, 0x52, 0x6e, 0xa4, 0x87, 0xfa, 0x99, 0xa7, 0xc1, 0x62, 0x02, 0x65, 0xff, - 0x79, 0xa0, 0x7e, 0x23, 0x8e, 0xab, 0x69, 0x0f, 0xcd, 0xb9, 0xca, 0xcb, 0xdd, 0xd5, 0x50, 0x7d, - 0xb0, 0xf9, 0x5e, 0x98, 0x3a, 0xfb, 0x3c, 0x9d, 0x9b, 0xff, 0x05, 0x00, 0x00, 0xff, 0xff, 0xba, - 0x37, 0x25, 0xea, 0x44, 0x01, 0x00, 0x00, -} diff --git a/vendor/google.golang.org/appengine/internal/base/api_base.proto b/vendor/google.golang.org/appengine/internal/base/api_base.proto deleted file mode 100644 index 56cd7a3ca..000000000 --- a/vendor/google.golang.org/appengine/internal/base/api_base.proto +++ /dev/null @@ -1,33 +0,0 @@ -// Built-in base types for API calls. Primarily useful as return types. - -syntax = "proto2"; -option go_package = "base"; - -package appengine.base; - -message StringProto { - required string value = 1; -} - -message Integer32Proto { - required int32 value = 1; -} - -message Integer64Proto { - required int64 value = 1; -} - -message BoolProto { - required bool value = 1; -} - -message DoubleProto { - required double value = 1; -} - -message BytesProto { - required bytes value = 1 [ctype=CORD]; -} - -message VoidProto { -} diff --git a/vendor/google.golang.org/appengine/internal/datastore/datastore_v3.pb.go b/vendor/google.golang.org/appengine/internal/datastore/datastore_v3.pb.go deleted file mode 100644 index 2fb748289..000000000 --- a/vendor/google.golang.org/appengine/internal/datastore/datastore_v3.pb.go +++ /dev/null @@ -1,4367 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// source: google.golang.org/appengine/internal/datastore/datastore_v3.proto - -package datastore - -import proto "github.com/golang/protobuf/proto" -import fmt "fmt" -import math "math" - -// Reference imports to suppress errors if they are not otherwise used. -var _ = proto.Marshal -var _ = fmt.Errorf -var _ = math.Inf - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the proto package it is being compiled against. -// A compilation error at this line likely means your copy of the -// proto package needs to be updated. -const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package - -type Property_Meaning int32 - -const ( - Property_NO_MEANING Property_Meaning = 0 - Property_BLOB Property_Meaning = 14 - Property_TEXT Property_Meaning = 15 - Property_BYTESTRING Property_Meaning = 16 - Property_ATOM_CATEGORY Property_Meaning = 1 - Property_ATOM_LINK Property_Meaning = 2 - Property_ATOM_TITLE Property_Meaning = 3 - Property_ATOM_CONTENT Property_Meaning = 4 - Property_ATOM_SUMMARY Property_Meaning = 5 - Property_ATOM_AUTHOR Property_Meaning = 6 - Property_GD_WHEN Property_Meaning = 7 - Property_GD_EMAIL Property_Meaning = 8 - Property_GEORSS_POINT Property_Meaning = 9 - Property_GD_IM Property_Meaning = 10 - Property_GD_PHONENUMBER Property_Meaning = 11 - Property_GD_POSTALADDRESS Property_Meaning = 12 - Property_GD_RATING Property_Meaning = 13 - Property_BLOBKEY Property_Meaning = 17 - Property_ENTITY_PROTO Property_Meaning = 19 - Property_INDEX_VALUE Property_Meaning = 18 -) - -var Property_Meaning_name = map[int32]string{ - 0: "NO_MEANING", - 14: "BLOB", - 15: "TEXT", - 16: "BYTESTRING", - 1: "ATOM_CATEGORY", - 2: "ATOM_LINK", - 3: "ATOM_TITLE", - 4: "ATOM_CONTENT", - 5: "ATOM_SUMMARY", - 6: "ATOM_AUTHOR", - 7: "GD_WHEN", - 8: "GD_EMAIL", - 9: "GEORSS_POINT", - 10: "GD_IM", - 11: "GD_PHONENUMBER", - 12: "GD_POSTALADDRESS", - 13: "GD_RATING", - 17: "BLOBKEY", - 19: "ENTITY_PROTO", - 18: "INDEX_VALUE", -} -var Property_Meaning_value = map[string]int32{ - "NO_MEANING": 0, - "BLOB": 14, - "TEXT": 15, - "BYTESTRING": 16, - "ATOM_CATEGORY": 1, - "ATOM_LINK": 2, - "ATOM_TITLE": 3, - "ATOM_CONTENT": 4, - "ATOM_SUMMARY": 5, - "ATOM_AUTHOR": 6, - "GD_WHEN": 7, - "GD_EMAIL": 8, - "GEORSS_POINT": 9, - "GD_IM": 10, - "GD_PHONENUMBER": 11, - "GD_POSTALADDRESS": 12, - "GD_RATING": 13, - "BLOBKEY": 17, - "ENTITY_PROTO": 19, - "INDEX_VALUE": 18, -} - -func (x Property_Meaning) Enum() *Property_Meaning { - p := new(Property_Meaning) - *p = x - return p -} -func (x Property_Meaning) String() string { - return proto.EnumName(Property_Meaning_name, int32(x)) -} -func (x *Property_Meaning) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(Property_Meaning_value, data, "Property_Meaning") - if err != nil { - return err - } - *x = Property_Meaning(value) - return nil -} -func (Property_Meaning) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_datastore_v3_83b17b80c34f6179, []int{2, 0} -} - -type Property_FtsTokenizationOption int32 - -const ( - Property_HTML Property_FtsTokenizationOption = 1 - Property_ATOM Property_FtsTokenizationOption = 2 -) - -var Property_FtsTokenizationOption_name = map[int32]string{ - 1: "HTML", - 2: "ATOM", -} -var Property_FtsTokenizationOption_value = map[string]int32{ - "HTML": 1, - "ATOM": 2, -} - -func (x Property_FtsTokenizationOption) Enum() *Property_FtsTokenizationOption { - p := new(Property_FtsTokenizationOption) - *p = x - return p -} -func (x Property_FtsTokenizationOption) String() string { - return proto.EnumName(Property_FtsTokenizationOption_name, int32(x)) -} -func (x *Property_FtsTokenizationOption) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(Property_FtsTokenizationOption_value, data, "Property_FtsTokenizationOption") - if err != nil { - return err - } - *x = Property_FtsTokenizationOption(value) - return nil -} -func (Property_FtsTokenizationOption) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_datastore_v3_83b17b80c34f6179, []int{2, 1} -} - -type EntityProto_Kind int32 - -const ( - EntityProto_GD_CONTACT EntityProto_Kind = 1 - EntityProto_GD_EVENT EntityProto_Kind = 2 - EntityProto_GD_MESSAGE EntityProto_Kind = 3 -) - -var EntityProto_Kind_name = map[int32]string{ - 1: "GD_CONTACT", - 2: "GD_EVENT", - 3: "GD_MESSAGE", -} -var EntityProto_Kind_value = map[string]int32{ - "GD_CONTACT": 1, - "GD_EVENT": 2, - "GD_MESSAGE": 3, -} - -func (x EntityProto_Kind) Enum() *EntityProto_Kind { - p := new(EntityProto_Kind) - *p = x - return p -} -func (x EntityProto_Kind) String() string { - return proto.EnumName(EntityProto_Kind_name, int32(x)) -} -func (x *EntityProto_Kind) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(EntityProto_Kind_value, data, "EntityProto_Kind") - if err != nil { - return err - } - *x = EntityProto_Kind(value) - return nil -} -func (EntityProto_Kind) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_datastore_v3_83b17b80c34f6179, []int{6, 0} -} - -type Index_Property_Direction int32 - -const ( - Index_Property_ASCENDING Index_Property_Direction = 1 - Index_Property_DESCENDING Index_Property_Direction = 2 -) - -var Index_Property_Direction_name = map[int32]string{ - 1: "ASCENDING", - 2: "DESCENDING", -} -var Index_Property_Direction_value = map[string]int32{ - "ASCENDING": 1, - "DESCENDING": 2, -} - -func (x Index_Property_Direction) Enum() *Index_Property_Direction { - p := new(Index_Property_Direction) - *p = x - return p -} -func (x Index_Property_Direction) String() string { - return proto.EnumName(Index_Property_Direction_name, int32(x)) -} -func (x *Index_Property_Direction) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(Index_Property_Direction_value, data, "Index_Property_Direction") - if err != nil { - return err - } - *x = Index_Property_Direction(value) - return nil -} -func (Index_Property_Direction) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_datastore_v3_83b17b80c34f6179, []int{8, 0, 0} -} - -type CompositeIndex_State int32 - -const ( - CompositeIndex_WRITE_ONLY CompositeIndex_State = 1 - CompositeIndex_READ_WRITE CompositeIndex_State = 2 - CompositeIndex_DELETED CompositeIndex_State = 3 - CompositeIndex_ERROR CompositeIndex_State = 4 -) - -var CompositeIndex_State_name = map[int32]string{ - 1: "WRITE_ONLY", - 2: "READ_WRITE", - 3: "DELETED", - 4: "ERROR", -} -var CompositeIndex_State_value = map[string]int32{ - "WRITE_ONLY": 1, - "READ_WRITE": 2, - "DELETED": 3, - "ERROR": 4, -} - -func (x CompositeIndex_State) Enum() *CompositeIndex_State { - p := new(CompositeIndex_State) - *p = x - return p -} -func (x CompositeIndex_State) String() string { - return proto.EnumName(CompositeIndex_State_name, int32(x)) -} -func (x *CompositeIndex_State) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(CompositeIndex_State_value, data, "CompositeIndex_State") - if err != nil { - return err - } - *x = CompositeIndex_State(value) - return nil -} -func (CompositeIndex_State) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_datastore_v3_83b17b80c34f6179, []int{9, 0} -} - -type Snapshot_Status int32 - -const ( - Snapshot_INACTIVE Snapshot_Status = 0 - Snapshot_ACTIVE Snapshot_Status = 1 -) - -var Snapshot_Status_name = map[int32]string{ - 0: "INACTIVE", - 1: "ACTIVE", -} -var Snapshot_Status_value = map[string]int32{ - "INACTIVE": 0, - "ACTIVE": 1, -} - -func (x Snapshot_Status) Enum() *Snapshot_Status { - p := new(Snapshot_Status) - *p = x - return p -} -func (x Snapshot_Status) String() string { - return proto.EnumName(Snapshot_Status_name, int32(x)) -} -func (x *Snapshot_Status) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(Snapshot_Status_value, data, "Snapshot_Status") - if err != nil { - return err - } - *x = Snapshot_Status(value) - return nil -} -func (Snapshot_Status) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_datastore_v3_83b17b80c34f6179, []int{12, 0} -} - -type Query_Hint int32 - -const ( - Query_ORDER_FIRST Query_Hint = 1 - Query_ANCESTOR_FIRST Query_Hint = 2 - Query_FILTER_FIRST Query_Hint = 3 -) - -var Query_Hint_name = map[int32]string{ - 1: "ORDER_FIRST", - 2: "ANCESTOR_FIRST", - 3: "FILTER_FIRST", -} -var Query_Hint_value = map[string]int32{ - "ORDER_FIRST": 1, - "ANCESTOR_FIRST": 2, - "FILTER_FIRST": 3, -} - -func (x Query_Hint) Enum() *Query_Hint { - p := new(Query_Hint) - *p = x - return p -} -func (x Query_Hint) String() string { - return proto.EnumName(Query_Hint_name, int32(x)) -} -func (x *Query_Hint) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(Query_Hint_value, data, "Query_Hint") - if err != nil { - return err - } - *x = Query_Hint(value) - return nil -} -func (Query_Hint) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_datastore_v3_83b17b80c34f6179, []int{15, 0} -} - -type Query_Filter_Operator int32 - -const ( - Query_Filter_LESS_THAN Query_Filter_Operator = 1 - Query_Filter_LESS_THAN_OR_EQUAL Query_Filter_Operator = 2 - Query_Filter_GREATER_THAN Query_Filter_Operator = 3 - Query_Filter_GREATER_THAN_OR_EQUAL Query_Filter_Operator = 4 - Query_Filter_EQUAL Query_Filter_Operator = 5 - Query_Filter_IN Query_Filter_Operator = 6 - Query_Filter_EXISTS Query_Filter_Operator = 7 -) - -var Query_Filter_Operator_name = map[int32]string{ - 1: "LESS_THAN", - 2: "LESS_THAN_OR_EQUAL", - 3: "GREATER_THAN", - 4: "GREATER_THAN_OR_EQUAL", - 5: "EQUAL", - 6: "IN", - 7: "EXISTS", -} -var Query_Filter_Operator_value = map[string]int32{ - "LESS_THAN": 1, - "LESS_THAN_OR_EQUAL": 2, - "GREATER_THAN": 3, - "GREATER_THAN_OR_EQUAL": 4, - "EQUAL": 5, - "IN": 6, - "EXISTS": 7, -} - -func (x Query_Filter_Operator) Enum() *Query_Filter_Operator { - p := new(Query_Filter_Operator) - *p = x - return p -} -func (x Query_Filter_Operator) String() string { - return proto.EnumName(Query_Filter_Operator_name, int32(x)) -} -func (x *Query_Filter_Operator) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(Query_Filter_Operator_value, data, "Query_Filter_Operator") - if err != nil { - return err - } - *x = Query_Filter_Operator(value) - return nil -} -func (Query_Filter_Operator) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_datastore_v3_83b17b80c34f6179, []int{15, 0, 0} -} - -type Query_Order_Direction int32 - -const ( - Query_Order_ASCENDING Query_Order_Direction = 1 - Query_Order_DESCENDING Query_Order_Direction = 2 -) - -var Query_Order_Direction_name = map[int32]string{ - 1: "ASCENDING", - 2: "DESCENDING", -} -var Query_Order_Direction_value = map[string]int32{ - "ASCENDING": 1, - "DESCENDING": 2, -} - -func (x Query_Order_Direction) Enum() *Query_Order_Direction { - p := new(Query_Order_Direction) - *p = x - return p -} -func (x Query_Order_Direction) String() string { - return proto.EnumName(Query_Order_Direction_name, int32(x)) -} -func (x *Query_Order_Direction) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(Query_Order_Direction_value, data, "Query_Order_Direction") - if err != nil { - return err - } - *x = Query_Order_Direction(value) - return nil -} -func (Query_Order_Direction) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_datastore_v3_83b17b80c34f6179, []int{15, 1, 0} -} - -type Error_ErrorCode int32 - -const ( - Error_BAD_REQUEST Error_ErrorCode = 1 - Error_CONCURRENT_TRANSACTION Error_ErrorCode = 2 - Error_INTERNAL_ERROR Error_ErrorCode = 3 - Error_NEED_INDEX Error_ErrorCode = 4 - Error_TIMEOUT Error_ErrorCode = 5 - Error_PERMISSION_DENIED Error_ErrorCode = 6 - Error_BIGTABLE_ERROR Error_ErrorCode = 7 - Error_COMMITTED_BUT_STILL_APPLYING Error_ErrorCode = 8 - Error_CAPABILITY_DISABLED Error_ErrorCode = 9 - Error_TRY_ALTERNATE_BACKEND Error_ErrorCode = 10 - Error_SAFE_TIME_TOO_OLD Error_ErrorCode = 11 -) - -var Error_ErrorCode_name = map[int32]string{ - 1: "BAD_REQUEST", - 2: "CONCURRENT_TRANSACTION", - 3: "INTERNAL_ERROR", - 4: "NEED_INDEX", - 5: "TIMEOUT", - 6: "PERMISSION_DENIED", - 7: "BIGTABLE_ERROR", - 8: "COMMITTED_BUT_STILL_APPLYING", - 9: "CAPABILITY_DISABLED", - 10: "TRY_ALTERNATE_BACKEND", - 11: "SAFE_TIME_TOO_OLD", -} -var Error_ErrorCode_value = map[string]int32{ - "BAD_REQUEST": 1, - "CONCURRENT_TRANSACTION": 2, - "INTERNAL_ERROR": 3, - "NEED_INDEX": 4, - "TIMEOUT": 5, - "PERMISSION_DENIED": 6, - "BIGTABLE_ERROR": 7, - "COMMITTED_BUT_STILL_APPLYING": 8, - "CAPABILITY_DISABLED": 9, - "TRY_ALTERNATE_BACKEND": 10, - "SAFE_TIME_TOO_OLD": 11, -} - -func (x Error_ErrorCode) Enum() *Error_ErrorCode { - p := new(Error_ErrorCode) - *p = x - return p -} -func (x Error_ErrorCode) String() string { - return proto.EnumName(Error_ErrorCode_name, int32(x)) -} -func (x *Error_ErrorCode) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(Error_ErrorCode_value, data, "Error_ErrorCode") - if err != nil { - return err - } - *x = Error_ErrorCode(value) - return nil -} -func (Error_ErrorCode) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_datastore_v3_83b17b80c34f6179, []int{19, 0} -} - -type PutRequest_AutoIdPolicy int32 - -const ( - PutRequest_CURRENT PutRequest_AutoIdPolicy = 0 - PutRequest_SEQUENTIAL PutRequest_AutoIdPolicy = 1 -) - -var PutRequest_AutoIdPolicy_name = map[int32]string{ - 0: "CURRENT", - 1: "SEQUENTIAL", -} -var PutRequest_AutoIdPolicy_value = map[string]int32{ - "CURRENT": 0, - "SEQUENTIAL": 1, -} - -func (x PutRequest_AutoIdPolicy) Enum() *PutRequest_AutoIdPolicy { - p := new(PutRequest_AutoIdPolicy) - *p = x - return p -} -func (x PutRequest_AutoIdPolicy) String() string { - return proto.EnumName(PutRequest_AutoIdPolicy_name, int32(x)) -} -func (x *PutRequest_AutoIdPolicy) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(PutRequest_AutoIdPolicy_value, data, "PutRequest_AutoIdPolicy") - if err != nil { - return err - } - *x = PutRequest_AutoIdPolicy(value) - return nil -} -func (PutRequest_AutoIdPolicy) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_datastore_v3_83b17b80c34f6179, []int{23, 0} -} - -type BeginTransactionRequest_TransactionMode int32 - -const ( - BeginTransactionRequest_UNKNOWN BeginTransactionRequest_TransactionMode = 0 - BeginTransactionRequest_READ_ONLY BeginTransactionRequest_TransactionMode = 1 - BeginTransactionRequest_READ_WRITE BeginTransactionRequest_TransactionMode = 2 -) - -var BeginTransactionRequest_TransactionMode_name = map[int32]string{ - 0: "UNKNOWN", - 1: "READ_ONLY", - 2: "READ_WRITE", -} -var BeginTransactionRequest_TransactionMode_value = map[string]int32{ - "UNKNOWN": 0, - "READ_ONLY": 1, - "READ_WRITE": 2, -} - -func (x BeginTransactionRequest_TransactionMode) Enum() *BeginTransactionRequest_TransactionMode { - p := new(BeginTransactionRequest_TransactionMode) - *p = x - return p -} -func (x BeginTransactionRequest_TransactionMode) String() string { - return proto.EnumName(BeginTransactionRequest_TransactionMode_name, int32(x)) -} -func (x *BeginTransactionRequest_TransactionMode) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(BeginTransactionRequest_TransactionMode_value, data, "BeginTransactionRequest_TransactionMode") - if err != nil { - return err - } - *x = BeginTransactionRequest_TransactionMode(value) - return nil -} -func (BeginTransactionRequest_TransactionMode) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_datastore_v3_83b17b80c34f6179, []int{36, 0} -} - -type Action struct { - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *Action) Reset() { *m = Action{} } -func (m *Action) String() string { return proto.CompactTextString(m) } -func (*Action) ProtoMessage() {} -func (*Action) Descriptor() ([]byte, []int) { - return fileDescriptor_datastore_v3_83b17b80c34f6179, []int{0} -} -func (m *Action) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_Action.Unmarshal(m, b) -} -func (m *Action) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_Action.Marshal(b, m, deterministic) -} -func (dst *Action) XXX_Merge(src proto.Message) { - xxx_messageInfo_Action.Merge(dst, src) -} -func (m *Action) XXX_Size() int { - return xxx_messageInfo_Action.Size(m) -} -func (m *Action) XXX_DiscardUnknown() { - xxx_messageInfo_Action.DiscardUnknown(m) -} - -var xxx_messageInfo_Action proto.InternalMessageInfo - -type PropertyValue struct { - Int64Value *int64 `protobuf:"varint,1,opt,name=int64Value" json:"int64Value,omitempty"` - BooleanValue *bool `protobuf:"varint,2,opt,name=booleanValue" json:"booleanValue,omitempty"` - StringValue *string `protobuf:"bytes,3,opt,name=stringValue" json:"stringValue,omitempty"` - DoubleValue *float64 `protobuf:"fixed64,4,opt,name=doubleValue" json:"doubleValue,omitempty"` - Pointvalue *PropertyValue_PointValue `protobuf:"group,5,opt,name=PointValue,json=pointvalue" json:"pointvalue,omitempty"` - Uservalue *PropertyValue_UserValue `protobuf:"group,8,opt,name=UserValue,json=uservalue" json:"uservalue,omitempty"` - Referencevalue *PropertyValue_ReferenceValue `protobuf:"group,12,opt,name=ReferenceValue,json=referencevalue" json:"referencevalue,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *PropertyValue) Reset() { *m = PropertyValue{} } -func (m *PropertyValue) String() string { return proto.CompactTextString(m) } -func (*PropertyValue) ProtoMessage() {} -func (*PropertyValue) Descriptor() ([]byte, []int) { - return fileDescriptor_datastore_v3_83b17b80c34f6179, []int{1} -} -func (m *PropertyValue) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_PropertyValue.Unmarshal(m, b) -} -func (m *PropertyValue) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_PropertyValue.Marshal(b, m, deterministic) -} -func (dst *PropertyValue) XXX_Merge(src proto.Message) { - xxx_messageInfo_PropertyValue.Merge(dst, src) -} -func (m *PropertyValue) XXX_Size() int { - return xxx_messageInfo_PropertyValue.Size(m) -} -func (m *PropertyValue) XXX_DiscardUnknown() { - xxx_messageInfo_PropertyValue.DiscardUnknown(m) -} - -var xxx_messageInfo_PropertyValue proto.InternalMessageInfo - -func (m *PropertyValue) GetInt64Value() int64 { - if m != nil && m.Int64Value != nil { - return *m.Int64Value - } - return 0 -} - -func (m *PropertyValue) GetBooleanValue() bool { - if m != nil && m.BooleanValue != nil { - return *m.BooleanValue - } - return false -} - -func (m *PropertyValue) GetStringValue() string { - if m != nil && m.StringValue != nil { - return *m.StringValue - } - return "" -} - -func (m *PropertyValue) GetDoubleValue() float64 { - if m != nil && m.DoubleValue != nil { - return *m.DoubleValue - } - return 0 -} - -func (m *PropertyValue) GetPointvalue() *PropertyValue_PointValue { - if m != nil { - return m.Pointvalue - } - return nil -} - -func (m *PropertyValue) GetUservalue() *PropertyValue_UserValue { - if m != nil { - return m.Uservalue - } - return nil -} - -func (m *PropertyValue) GetReferencevalue() *PropertyValue_ReferenceValue { - if m != nil { - return m.Referencevalue - } - return nil -} - -type PropertyValue_PointValue struct { - X *float64 `protobuf:"fixed64,6,req,name=x" json:"x,omitempty"` - Y *float64 `protobuf:"fixed64,7,req,name=y" json:"y,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *PropertyValue_PointValue) Reset() { *m = PropertyValue_PointValue{} } -func (m *PropertyValue_PointValue) String() string { return proto.CompactTextString(m) } -func (*PropertyValue_PointValue) ProtoMessage() {} -func (*PropertyValue_PointValue) Descriptor() ([]byte, []int) { - return fileDescriptor_datastore_v3_83b17b80c34f6179, []int{1, 0} -} -func (m *PropertyValue_PointValue) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_PropertyValue_PointValue.Unmarshal(m, b) -} -func (m *PropertyValue_PointValue) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_PropertyValue_PointValue.Marshal(b, m, deterministic) -} -func (dst *PropertyValue_PointValue) XXX_Merge(src proto.Message) { - xxx_messageInfo_PropertyValue_PointValue.Merge(dst, src) -} -func (m *PropertyValue_PointValue) XXX_Size() int { - return xxx_messageInfo_PropertyValue_PointValue.Size(m) -} -func (m *PropertyValue_PointValue) XXX_DiscardUnknown() { - xxx_messageInfo_PropertyValue_PointValue.DiscardUnknown(m) -} - -var xxx_messageInfo_PropertyValue_PointValue proto.InternalMessageInfo - -func (m *PropertyValue_PointValue) GetX() float64 { - if m != nil && m.X != nil { - return *m.X - } - return 0 -} - -func (m *PropertyValue_PointValue) GetY() float64 { - if m != nil && m.Y != nil { - return *m.Y - } - return 0 -} - -type PropertyValue_UserValue struct { - Email *string `protobuf:"bytes,9,req,name=email" json:"email,omitempty"` - AuthDomain *string `protobuf:"bytes,10,req,name=auth_domain,json=authDomain" json:"auth_domain,omitempty"` - Nickname *string `protobuf:"bytes,11,opt,name=nickname" json:"nickname,omitempty"` - FederatedIdentity *string `protobuf:"bytes,21,opt,name=federated_identity,json=federatedIdentity" json:"federated_identity,omitempty"` - FederatedProvider *string `protobuf:"bytes,22,opt,name=federated_provider,json=federatedProvider" json:"federated_provider,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *PropertyValue_UserValue) Reset() { *m = PropertyValue_UserValue{} } -func (m *PropertyValue_UserValue) String() string { return proto.CompactTextString(m) } -func (*PropertyValue_UserValue) ProtoMessage() {} -func (*PropertyValue_UserValue) Descriptor() ([]byte, []int) { - return fileDescriptor_datastore_v3_83b17b80c34f6179, []int{1, 1} -} -func (m *PropertyValue_UserValue) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_PropertyValue_UserValue.Unmarshal(m, b) -} -func (m *PropertyValue_UserValue) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_PropertyValue_UserValue.Marshal(b, m, deterministic) -} -func (dst *PropertyValue_UserValue) XXX_Merge(src proto.Message) { - xxx_messageInfo_PropertyValue_UserValue.Merge(dst, src) -} -func (m *PropertyValue_UserValue) XXX_Size() int { - return xxx_messageInfo_PropertyValue_UserValue.Size(m) -} -func (m *PropertyValue_UserValue) XXX_DiscardUnknown() { - xxx_messageInfo_PropertyValue_UserValue.DiscardUnknown(m) -} - -var xxx_messageInfo_PropertyValue_UserValue proto.InternalMessageInfo - -func (m *PropertyValue_UserValue) GetEmail() string { - if m != nil && m.Email != nil { - return *m.Email - } - return "" -} - -func (m *PropertyValue_UserValue) GetAuthDomain() string { - if m != nil && m.AuthDomain != nil { - return *m.AuthDomain - } - return "" -} - -func (m *PropertyValue_UserValue) GetNickname() string { - if m != nil && m.Nickname != nil { - return *m.Nickname - } - return "" -} - -func (m *PropertyValue_UserValue) GetFederatedIdentity() string { - if m != nil && m.FederatedIdentity != nil { - return *m.FederatedIdentity - } - return "" -} - -func (m *PropertyValue_UserValue) GetFederatedProvider() string { - if m != nil && m.FederatedProvider != nil { - return *m.FederatedProvider - } - return "" -} - -type PropertyValue_ReferenceValue struct { - App *string `protobuf:"bytes,13,req,name=app" json:"app,omitempty"` - NameSpace *string `protobuf:"bytes,20,opt,name=name_space,json=nameSpace" json:"name_space,omitempty"` - Pathelement []*PropertyValue_ReferenceValue_PathElement `protobuf:"group,14,rep,name=PathElement,json=pathelement" json:"pathelement,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *PropertyValue_ReferenceValue) Reset() { *m = PropertyValue_ReferenceValue{} } -func (m *PropertyValue_ReferenceValue) String() string { return proto.CompactTextString(m) } -func (*PropertyValue_ReferenceValue) ProtoMessage() {} -func (*PropertyValue_ReferenceValue) Descriptor() ([]byte, []int) { - return fileDescriptor_datastore_v3_83b17b80c34f6179, []int{1, 2} -} -func (m *PropertyValue_ReferenceValue) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_PropertyValue_ReferenceValue.Unmarshal(m, b) -} -func (m *PropertyValue_ReferenceValue) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_PropertyValue_ReferenceValue.Marshal(b, m, deterministic) -} -func (dst *PropertyValue_ReferenceValue) XXX_Merge(src proto.Message) { - xxx_messageInfo_PropertyValue_ReferenceValue.Merge(dst, src) -} -func (m *PropertyValue_ReferenceValue) XXX_Size() int { - return xxx_messageInfo_PropertyValue_ReferenceValue.Size(m) -} -func (m *PropertyValue_ReferenceValue) XXX_DiscardUnknown() { - xxx_messageInfo_PropertyValue_ReferenceValue.DiscardUnknown(m) -} - -var xxx_messageInfo_PropertyValue_ReferenceValue proto.InternalMessageInfo - -func (m *PropertyValue_ReferenceValue) GetApp() string { - if m != nil && m.App != nil { - return *m.App - } - return "" -} - -func (m *PropertyValue_ReferenceValue) GetNameSpace() string { - if m != nil && m.NameSpace != nil { - return *m.NameSpace - } - return "" -} - -func (m *PropertyValue_ReferenceValue) GetPathelement() []*PropertyValue_ReferenceValue_PathElement { - if m != nil { - return m.Pathelement - } - return nil -} - -type PropertyValue_ReferenceValue_PathElement struct { - Type *string `protobuf:"bytes,15,req,name=type" json:"type,omitempty"` - Id *int64 `protobuf:"varint,16,opt,name=id" json:"id,omitempty"` - Name *string `protobuf:"bytes,17,opt,name=name" json:"name,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *PropertyValue_ReferenceValue_PathElement) Reset() { - *m = PropertyValue_ReferenceValue_PathElement{} -} -func (m *PropertyValue_ReferenceValue_PathElement) String() string { return proto.CompactTextString(m) } -func (*PropertyValue_ReferenceValue_PathElement) ProtoMessage() {} -func (*PropertyValue_ReferenceValue_PathElement) Descriptor() ([]byte, []int) { - return fileDescriptor_datastore_v3_83b17b80c34f6179, []int{1, 2, 0} -} -func (m *PropertyValue_ReferenceValue_PathElement) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_PropertyValue_ReferenceValue_PathElement.Unmarshal(m, b) -} -func (m *PropertyValue_ReferenceValue_PathElement) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_PropertyValue_ReferenceValue_PathElement.Marshal(b, m, deterministic) -} -func (dst *PropertyValue_ReferenceValue_PathElement) XXX_Merge(src proto.Message) { - xxx_messageInfo_PropertyValue_ReferenceValue_PathElement.Merge(dst, src) -} -func (m *PropertyValue_ReferenceValue_PathElement) XXX_Size() int { - return xxx_messageInfo_PropertyValue_ReferenceValue_PathElement.Size(m) -} -func (m *PropertyValue_ReferenceValue_PathElement) XXX_DiscardUnknown() { - xxx_messageInfo_PropertyValue_ReferenceValue_PathElement.DiscardUnknown(m) -} - -var xxx_messageInfo_PropertyValue_ReferenceValue_PathElement proto.InternalMessageInfo - -func (m *PropertyValue_ReferenceValue_PathElement) GetType() string { - if m != nil && m.Type != nil { - return *m.Type - } - return "" -} - -func (m *PropertyValue_ReferenceValue_PathElement) GetId() int64 { - if m != nil && m.Id != nil { - return *m.Id - } - return 0 -} - -func (m *PropertyValue_ReferenceValue_PathElement) GetName() string { - if m != nil && m.Name != nil { - return *m.Name - } - return "" -} - -type Property struct { - Meaning *Property_Meaning `protobuf:"varint,1,opt,name=meaning,enum=appengine.Property_Meaning,def=0" json:"meaning,omitempty"` - MeaningUri *string `protobuf:"bytes,2,opt,name=meaning_uri,json=meaningUri" json:"meaning_uri,omitempty"` - Name *string `protobuf:"bytes,3,req,name=name" json:"name,omitempty"` - Value *PropertyValue `protobuf:"bytes,5,req,name=value" json:"value,omitempty"` - Multiple *bool `protobuf:"varint,4,req,name=multiple" json:"multiple,omitempty"` - Searchable *bool `protobuf:"varint,6,opt,name=searchable,def=0" json:"searchable,omitempty"` - FtsTokenizationOption *Property_FtsTokenizationOption `protobuf:"varint,8,opt,name=fts_tokenization_option,json=ftsTokenizationOption,enum=appengine.Property_FtsTokenizationOption" json:"fts_tokenization_option,omitempty"` - Locale *string `protobuf:"bytes,9,opt,name=locale,def=en" json:"locale,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *Property) Reset() { *m = Property{} } -func (m *Property) String() string { return proto.CompactTextString(m) } -func (*Property) ProtoMessage() {} -func (*Property) Descriptor() ([]byte, []int) { - return fileDescriptor_datastore_v3_83b17b80c34f6179, []int{2} -} -func (m *Property) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_Property.Unmarshal(m, b) -} -func (m *Property) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_Property.Marshal(b, m, deterministic) -} -func (dst *Property) XXX_Merge(src proto.Message) { - xxx_messageInfo_Property.Merge(dst, src) -} -func (m *Property) XXX_Size() int { - return xxx_messageInfo_Property.Size(m) -} -func (m *Property) XXX_DiscardUnknown() { - xxx_messageInfo_Property.DiscardUnknown(m) -} - -var xxx_messageInfo_Property proto.InternalMessageInfo - -const Default_Property_Meaning Property_Meaning = Property_NO_MEANING -const Default_Property_Searchable bool = false -const Default_Property_Locale string = "en" - -func (m *Property) GetMeaning() Property_Meaning { - if m != nil && m.Meaning != nil { - return *m.Meaning - } - return Default_Property_Meaning -} - -func (m *Property) GetMeaningUri() string { - if m != nil && m.MeaningUri != nil { - return *m.MeaningUri - } - return "" -} - -func (m *Property) GetName() string { - if m != nil && m.Name != nil { - return *m.Name - } - return "" -} - -func (m *Property) GetValue() *PropertyValue { - if m != nil { - return m.Value - } - return nil -} - -func (m *Property) GetMultiple() bool { - if m != nil && m.Multiple != nil { - return *m.Multiple - } - return false -} - -func (m *Property) GetSearchable() bool { - if m != nil && m.Searchable != nil { - return *m.Searchable - } - return Default_Property_Searchable -} - -func (m *Property) GetFtsTokenizationOption() Property_FtsTokenizationOption { - if m != nil && m.FtsTokenizationOption != nil { - return *m.FtsTokenizationOption - } - return Property_HTML -} - -func (m *Property) GetLocale() string { - if m != nil && m.Locale != nil { - return *m.Locale - } - return Default_Property_Locale -} - -type Path struct { - Element []*Path_Element `protobuf:"group,1,rep,name=Element,json=element" json:"element,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *Path) Reset() { *m = Path{} } -func (m *Path) String() string { return proto.CompactTextString(m) } -func (*Path) ProtoMessage() {} -func (*Path) Descriptor() ([]byte, []int) { - return fileDescriptor_datastore_v3_83b17b80c34f6179, []int{3} -} -func (m *Path) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_Path.Unmarshal(m, b) -} -func (m *Path) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_Path.Marshal(b, m, deterministic) -} -func (dst *Path) XXX_Merge(src proto.Message) { - xxx_messageInfo_Path.Merge(dst, src) -} -func (m *Path) XXX_Size() int { - return xxx_messageInfo_Path.Size(m) -} -func (m *Path) XXX_DiscardUnknown() { - xxx_messageInfo_Path.DiscardUnknown(m) -} - -var xxx_messageInfo_Path proto.InternalMessageInfo - -func (m *Path) GetElement() []*Path_Element { - if m != nil { - return m.Element - } - return nil -} - -type Path_Element struct { - Type *string `protobuf:"bytes,2,req,name=type" json:"type,omitempty"` - Id *int64 `protobuf:"varint,3,opt,name=id" json:"id,omitempty"` - Name *string `protobuf:"bytes,4,opt,name=name" json:"name,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *Path_Element) Reset() { *m = Path_Element{} } -func (m *Path_Element) String() string { return proto.CompactTextString(m) } -func (*Path_Element) ProtoMessage() {} -func (*Path_Element) Descriptor() ([]byte, []int) { - return fileDescriptor_datastore_v3_83b17b80c34f6179, []int{3, 0} -} -func (m *Path_Element) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_Path_Element.Unmarshal(m, b) -} -func (m *Path_Element) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_Path_Element.Marshal(b, m, deterministic) -} -func (dst *Path_Element) XXX_Merge(src proto.Message) { - xxx_messageInfo_Path_Element.Merge(dst, src) -} -func (m *Path_Element) XXX_Size() int { - return xxx_messageInfo_Path_Element.Size(m) -} -func (m *Path_Element) XXX_DiscardUnknown() { - xxx_messageInfo_Path_Element.DiscardUnknown(m) -} - -var xxx_messageInfo_Path_Element proto.InternalMessageInfo - -func (m *Path_Element) GetType() string { - if m != nil && m.Type != nil { - return *m.Type - } - return "" -} - -func (m *Path_Element) GetId() int64 { - if m != nil && m.Id != nil { - return *m.Id - } - return 0 -} - -func (m *Path_Element) GetName() string { - if m != nil && m.Name != nil { - return *m.Name - } - return "" -} - -type Reference struct { - App *string `protobuf:"bytes,13,req,name=app" json:"app,omitempty"` - NameSpace *string `protobuf:"bytes,20,opt,name=name_space,json=nameSpace" json:"name_space,omitempty"` - Path *Path `protobuf:"bytes,14,req,name=path" json:"path,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *Reference) Reset() { *m = Reference{} } -func (m *Reference) String() string { return proto.CompactTextString(m) } -func (*Reference) ProtoMessage() {} -func (*Reference) Descriptor() ([]byte, []int) { - return fileDescriptor_datastore_v3_83b17b80c34f6179, []int{4} -} -func (m *Reference) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_Reference.Unmarshal(m, b) -} -func (m *Reference) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_Reference.Marshal(b, m, deterministic) -} -func (dst *Reference) XXX_Merge(src proto.Message) { - xxx_messageInfo_Reference.Merge(dst, src) -} -func (m *Reference) XXX_Size() int { - return xxx_messageInfo_Reference.Size(m) -} -func (m *Reference) XXX_DiscardUnknown() { - xxx_messageInfo_Reference.DiscardUnknown(m) -} - -var xxx_messageInfo_Reference proto.InternalMessageInfo - -func (m *Reference) GetApp() string { - if m != nil && m.App != nil { - return *m.App - } - return "" -} - -func (m *Reference) GetNameSpace() string { - if m != nil && m.NameSpace != nil { - return *m.NameSpace - } - return "" -} - -func (m *Reference) GetPath() *Path { - if m != nil { - return m.Path - } - return nil -} - -type User struct { - Email *string `protobuf:"bytes,1,req,name=email" json:"email,omitempty"` - AuthDomain *string `protobuf:"bytes,2,req,name=auth_domain,json=authDomain" json:"auth_domain,omitempty"` - Nickname *string `protobuf:"bytes,3,opt,name=nickname" json:"nickname,omitempty"` - FederatedIdentity *string `protobuf:"bytes,6,opt,name=federated_identity,json=federatedIdentity" json:"federated_identity,omitempty"` - FederatedProvider *string `protobuf:"bytes,7,opt,name=federated_provider,json=federatedProvider" json:"federated_provider,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *User) Reset() { *m = User{} } -func (m *User) String() string { return proto.CompactTextString(m) } -func (*User) ProtoMessage() {} -func (*User) Descriptor() ([]byte, []int) { - return fileDescriptor_datastore_v3_83b17b80c34f6179, []int{5} -} -func (m *User) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_User.Unmarshal(m, b) -} -func (m *User) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_User.Marshal(b, m, deterministic) -} -func (dst *User) XXX_Merge(src proto.Message) { - xxx_messageInfo_User.Merge(dst, src) -} -func (m *User) XXX_Size() int { - return xxx_messageInfo_User.Size(m) -} -func (m *User) XXX_DiscardUnknown() { - xxx_messageInfo_User.DiscardUnknown(m) -} - -var xxx_messageInfo_User proto.InternalMessageInfo - -func (m *User) GetEmail() string { - if m != nil && m.Email != nil { - return *m.Email - } - return "" -} - -func (m *User) GetAuthDomain() string { - if m != nil && m.AuthDomain != nil { - return *m.AuthDomain - } - return "" -} - -func (m *User) GetNickname() string { - if m != nil && m.Nickname != nil { - return *m.Nickname - } - return "" -} - -func (m *User) GetFederatedIdentity() string { - if m != nil && m.FederatedIdentity != nil { - return *m.FederatedIdentity - } - return "" -} - -func (m *User) GetFederatedProvider() string { - if m != nil && m.FederatedProvider != nil { - return *m.FederatedProvider - } - return "" -} - -type EntityProto struct { - Key *Reference `protobuf:"bytes,13,req,name=key" json:"key,omitempty"` - EntityGroup *Path `protobuf:"bytes,16,req,name=entity_group,json=entityGroup" json:"entity_group,omitempty"` - Owner *User `protobuf:"bytes,17,opt,name=owner" json:"owner,omitempty"` - Kind *EntityProto_Kind `protobuf:"varint,4,opt,name=kind,enum=appengine.EntityProto_Kind" json:"kind,omitempty"` - KindUri *string `protobuf:"bytes,5,opt,name=kind_uri,json=kindUri" json:"kind_uri,omitempty"` - Property []*Property `protobuf:"bytes,14,rep,name=property" json:"property,omitempty"` - RawProperty []*Property `protobuf:"bytes,15,rep,name=raw_property,json=rawProperty" json:"raw_property,omitempty"` - Rank *int32 `protobuf:"varint,18,opt,name=rank" json:"rank,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *EntityProto) Reset() { *m = EntityProto{} } -func (m *EntityProto) String() string { return proto.CompactTextString(m) } -func (*EntityProto) ProtoMessage() {} -func (*EntityProto) Descriptor() ([]byte, []int) { - return fileDescriptor_datastore_v3_83b17b80c34f6179, []int{6} -} -func (m *EntityProto) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_EntityProto.Unmarshal(m, b) -} -func (m *EntityProto) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_EntityProto.Marshal(b, m, deterministic) -} -func (dst *EntityProto) XXX_Merge(src proto.Message) { - xxx_messageInfo_EntityProto.Merge(dst, src) -} -func (m *EntityProto) XXX_Size() int { - return xxx_messageInfo_EntityProto.Size(m) -} -func (m *EntityProto) XXX_DiscardUnknown() { - xxx_messageInfo_EntityProto.DiscardUnknown(m) -} - -var xxx_messageInfo_EntityProto proto.InternalMessageInfo - -func (m *EntityProto) GetKey() *Reference { - if m != nil { - return m.Key - } - return nil -} - -func (m *EntityProto) GetEntityGroup() *Path { - if m != nil { - return m.EntityGroup - } - return nil -} - -func (m *EntityProto) GetOwner() *User { - if m != nil { - return m.Owner - } - return nil -} - -func (m *EntityProto) GetKind() EntityProto_Kind { - if m != nil && m.Kind != nil { - return *m.Kind - } - return EntityProto_GD_CONTACT -} - -func (m *EntityProto) GetKindUri() string { - if m != nil && m.KindUri != nil { - return *m.KindUri - } - return "" -} - -func (m *EntityProto) GetProperty() []*Property { - if m != nil { - return m.Property - } - return nil -} - -func (m *EntityProto) GetRawProperty() []*Property { - if m != nil { - return m.RawProperty - } - return nil -} - -func (m *EntityProto) GetRank() int32 { - if m != nil && m.Rank != nil { - return *m.Rank - } - return 0 -} - -type CompositeProperty struct { - IndexId *int64 `protobuf:"varint,1,req,name=index_id,json=indexId" json:"index_id,omitempty"` - Value []string `protobuf:"bytes,2,rep,name=value" json:"value,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *CompositeProperty) Reset() { *m = CompositeProperty{} } -func (m *CompositeProperty) String() string { return proto.CompactTextString(m) } -func (*CompositeProperty) ProtoMessage() {} -func (*CompositeProperty) Descriptor() ([]byte, []int) { - return fileDescriptor_datastore_v3_83b17b80c34f6179, []int{7} -} -func (m *CompositeProperty) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_CompositeProperty.Unmarshal(m, b) -} -func (m *CompositeProperty) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_CompositeProperty.Marshal(b, m, deterministic) -} -func (dst *CompositeProperty) XXX_Merge(src proto.Message) { - xxx_messageInfo_CompositeProperty.Merge(dst, src) -} -func (m *CompositeProperty) XXX_Size() int { - return xxx_messageInfo_CompositeProperty.Size(m) -} -func (m *CompositeProperty) XXX_DiscardUnknown() { - xxx_messageInfo_CompositeProperty.DiscardUnknown(m) -} - -var xxx_messageInfo_CompositeProperty proto.InternalMessageInfo - -func (m *CompositeProperty) GetIndexId() int64 { - if m != nil && m.IndexId != nil { - return *m.IndexId - } - return 0 -} - -func (m *CompositeProperty) GetValue() []string { - if m != nil { - return m.Value - } - return nil -} - -type Index struct { - EntityType *string `protobuf:"bytes,1,req,name=entity_type,json=entityType" json:"entity_type,omitempty"` - Ancestor *bool `protobuf:"varint,5,req,name=ancestor" json:"ancestor,omitempty"` - Property []*Index_Property `protobuf:"group,2,rep,name=Property,json=property" json:"property,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *Index) Reset() { *m = Index{} } -func (m *Index) String() string { return proto.CompactTextString(m) } -func (*Index) ProtoMessage() {} -func (*Index) Descriptor() ([]byte, []int) { - return fileDescriptor_datastore_v3_83b17b80c34f6179, []int{8} -} -func (m *Index) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_Index.Unmarshal(m, b) -} -func (m *Index) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_Index.Marshal(b, m, deterministic) -} -func (dst *Index) XXX_Merge(src proto.Message) { - xxx_messageInfo_Index.Merge(dst, src) -} -func (m *Index) XXX_Size() int { - return xxx_messageInfo_Index.Size(m) -} -func (m *Index) XXX_DiscardUnknown() { - xxx_messageInfo_Index.DiscardUnknown(m) -} - -var xxx_messageInfo_Index proto.InternalMessageInfo - -func (m *Index) GetEntityType() string { - if m != nil && m.EntityType != nil { - return *m.EntityType - } - return "" -} - -func (m *Index) GetAncestor() bool { - if m != nil && m.Ancestor != nil { - return *m.Ancestor - } - return false -} - -func (m *Index) GetProperty() []*Index_Property { - if m != nil { - return m.Property - } - return nil -} - -type Index_Property struct { - Name *string `protobuf:"bytes,3,req,name=name" json:"name,omitempty"` - Direction *Index_Property_Direction `protobuf:"varint,4,opt,name=direction,enum=appengine.Index_Property_Direction,def=1" json:"direction,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *Index_Property) Reset() { *m = Index_Property{} } -func (m *Index_Property) String() string { return proto.CompactTextString(m) } -func (*Index_Property) ProtoMessage() {} -func (*Index_Property) Descriptor() ([]byte, []int) { - return fileDescriptor_datastore_v3_83b17b80c34f6179, []int{8, 0} -} -func (m *Index_Property) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_Index_Property.Unmarshal(m, b) -} -func (m *Index_Property) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_Index_Property.Marshal(b, m, deterministic) -} -func (dst *Index_Property) XXX_Merge(src proto.Message) { - xxx_messageInfo_Index_Property.Merge(dst, src) -} -func (m *Index_Property) XXX_Size() int { - return xxx_messageInfo_Index_Property.Size(m) -} -func (m *Index_Property) XXX_DiscardUnknown() { - xxx_messageInfo_Index_Property.DiscardUnknown(m) -} - -var xxx_messageInfo_Index_Property proto.InternalMessageInfo - -const Default_Index_Property_Direction Index_Property_Direction = Index_Property_ASCENDING - -func (m *Index_Property) GetName() string { - if m != nil && m.Name != nil { - return *m.Name - } - return "" -} - -func (m *Index_Property) GetDirection() Index_Property_Direction { - if m != nil && m.Direction != nil { - return *m.Direction - } - return Default_Index_Property_Direction -} - -type CompositeIndex struct { - AppId *string `protobuf:"bytes,1,req,name=app_id,json=appId" json:"app_id,omitempty"` - Id *int64 `protobuf:"varint,2,req,name=id" json:"id,omitempty"` - Definition *Index `protobuf:"bytes,3,req,name=definition" json:"definition,omitempty"` - State *CompositeIndex_State `protobuf:"varint,4,req,name=state,enum=appengine.CompositeIndex_State" json:"state,omitempty"` - OnlyUseIfRequired *bool `protobuf:"varint,6,opt,name=only_use_if_required,json=onlyUseIfRequired,def=0" json:"only_use_if_required,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *CompositeIndex) Reset() { *m = CompositeIndex{} } -func (m *CompositeIndex) String() string { return proto.CompactTextString(m) } -func (*CompositeIndex) ProtoMessage() {} -func (*CompositeIndex) Descriptor() ([]byte, []int) { - return fileDescriptor_datastore_v3_83b17b80c34f6179, []int{9} -} -func (m *CompositeIndex) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_CompositeIndex.Unmarshal(m, b) -} -func (m *CompositeIndex) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_CompositeIndex.Marshal(b, m, deterministic) -} -func (dst *CompositeIndex) XXX_Merge(src proto.Message) { - xxx_messageInfo_CompositeIndex.Merge(dst, src) -} -func (m *CompositeIndex) XXX_Size() int { - return xxx_messageInfo_CompositeIndex.Size(m) -} -func (m *CompositeIndex) XXX_DiscardUnknown() { - xxx_messageInfo_CompositeIndex.DiscardUnknown(m) -} - -var xxx_messageInfo_CompositeIndex proto.InternalMessageInfo - -const Default_CompositeIndex_OnlyUseIfRequired bool = false - -func (m *CompositeIndex) GetAppId() string { - if m != nil && m.AppId != nil { - return *m.AppId - } - return "" -} - -func (m *CompositeIndex) GetId() int64 { - if m != nil && m.Id != nil { - return *m.Id - } - return 0 -} - -func (m *CompositeIndex) GetDefinition() *Index { - if m != nil { - return m.Definition - } - return nil -} - -func (m *CompositeIndex) GetState() CompositeIndex_State { - if m != nil && m.State != nil { - return *m.State - } - return CompositeIndex_WRITE_ONLY -} - -func (m *CompositeIndex) GetOnlyUseIfRequired() bool { - if m != nil && m.OnlyUseIfRequired != nil { - return *m.OnlyUseIfRequired - } - return Default_CompositeIndex_OnlyUseIfRequired -} - -type IndexPostfix struct { - IndexValue []*IndexPostfix_IndexValue `protobuf:"bytes,1,rep,name=index_value,json=indexValue" json:"index_value,omitempty"` - Key *Reference `protobuf:"bytes,2,opt,name=key" json:"key,omitempty"` - Before *bool `protobuf:"varint,3,opt,name=before,def=1" json:"before,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *IndexPostfix) Reset() { *m = IndexPostfix{} } -func (m *IndexPostfix) String() string { return proto.CompactTextString(m) } -func (*IndexPostfix) ProtoMessage() {} -func (*IndexPostfix) Descriptor() ([]byte, []int) { - return fileDescriptor_datastore_v3_83b17b80c34f6179, []int{10} -} -func (m *IndexPostfix) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_IndexPostfix.Unmarshal(m, b) -} -func (m *IndexPostfix) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_IndexPostfix.Marshal(b, m, deterministic) -} -func (dst *IndexPostfix) XXX_Merge(src proto.Message) { - xxx_messageInfo_IndexPostfix.Merge(dst, src) -} -func (m *IndexPostfix) XXX_Size() int { - return xxx_messageInfo_IndexPostfix.Size(m) -} -func (m *IndexPostfix) XXX_DiscardUnknown() { - xxx_messageInfo_IndexPostfix.DiscardUnknown(m) -} - -var xxx_messageInfo_IndexPostfix proto.InternalMessageInfo - -const Default_IndexPostfix_Before bool = true - -func (m *IndexPostfix) GetIndexValue() []*IndexPostfix_IndexValue { - if m != nil { - return m.IndexValue - } - return nil -} - -func (m *IndexPostfix) GetKey() *Reference { - if m != nil { - return m.Key - } - return nil -} - -func (m *IndexPostfix) GetBefore() bool { - if m != nil && m.Before != nil { - return *m.Before - } - return Default_IndexPostfix_Before -} - -type IndexPostfix_IndexValue struct { - PropertyName *string `protobuf:"bytes,1,req,name=property_name,json=propertyName" json:"property_name,omitempty"` - Value *PropertyValue `protobuf:"bytes,2,req,name=value" json:"value,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *IndexPostfix_IndexValue) Reset() { *m = IndexPostfix_IndexValue{} } -func (m *IndexPostfix_IndexValue) String() string { return proto.CompactTextString(m) } -func (*IndexPostfix_IndexValue) ProtoMessage() {} -func (*IndexPostfix_IndexValue) Descriptor() ([]byte, []int) { - return fileDescriptor_datastore_v3_83b17b80c34f6179, []int{10, 0} -} -func (m *IndexPostfix_IndexValue) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_IndexPostfix_IndexValue.Unmarshal(m, b) -} -func (m *IndexPostfix_IndexValue) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_IndexPostfix_IndexValue.Marshal(b, m, deterministic) -} -func (dst *IndexPostfix_IndexValue) XXX_Merge(src proto.Message) { - xxx_messageInfo_IndexPostfix_IndexValue.Merge(dst, src) -} -func (m *IndexPostfix_IndexValue) XXX_Size() int { - return xxx_messageInfo_IndexPostfix_IndexValue.Size(m) -} -func (m *IndexPostfix_IndexValue) XXX_DiscardUnknown() { - xxx_messageInfo_IndexPostfix_IndexValue.DiscardUnknown(m) -} - -var xxx_messageInfo_IndexPostfix_IndexValue proto.InternalMessageInfo - -func (m *IndexPostfix_IndexValue) GetPropertyName() string { - if m != nil && m.PropertyName != nil { - return *m.PropertyName - } - return "" -} - -func (m *IndexPostfix_IndexValue) GetValue() *PropertyValue { - if m != nil { - return m.Value - } - return nil -} - -type IndexPosition struct { - Key *string `protobuf:"bytes,1,opt,name=key" json:"key,omitempty"` - Before *bool `protobuf:"varint,2,opt,name=before,def=1" json:"before,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *IndexPosition) Reset() { *m = IndexPosition{} } -func (m *IndexPosition) String() string { return proto.CompactTextString(m) } -func (*IndexPosition) ProtoMessage() {} -func (*IndexPosition) Descriptor() ([]byte, []int) { - return fileDescriptor_datastore_v3_83b17b80c34f6179, []int{11} -} -func (m *IndexPosition) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_IndexPosition.Unmarshal(m, b) -} -func (m *IndexPosition) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_IndexPosition.Marshal(b, m, deterministic) -} -func (dst *IndexPosition) XXX_Merge(src proto.Message) { - xxx_messageInfo_IndexPosition.Merge(dst, src) -} -func (m *IndexPosition) XXX_Size() int { - return xxx_messageInfo_IndexPosition.Size(m) -} -func (m *IndexPosition) XXX_DiscardUnknown() { - xxx_messageInfo_IndexPosition.DiscardUnknown(m) -} - -var xxx_messageInfo_IndexPosition proto.InternalMessageInfo - -const Default_IndexPosition_Before bool = true - -func (m *IndexPosition) GetKey() string { - if m != nil && m.Key != nil { - return *m.Key - } - return "" -} - -func (m *IndexPosition) GetBefore() bool { - if m != nil && m.Before != nil { - return *m.Before - } - return Default_IndexPosition_Before -} - -type Snapshot struct { - Ts *int64 `protobuf:"varint,1,req,name=ts" json:"ts,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *Snapshot) Reset() { *m = Snapshot{} } -func (m *Snapshot) String() string { return proto.CompactTextString(m) } -func (*Snapshot) ProtoMessage() {} -func (*Snapshot) Descriptor() ([]byte, []int) { - return fileDescriptor_datastore_v3_83b17b80c34f6179, []int{12} -} -func (m *Snapshot) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_Snapshot.Unmarshal(m, b) -} -func (m *Snapshot) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_Snapshot.Marshal(b, m, deterministic) -} -func (dst *Snapshot) XXX_Merge(src proto.Message) { - xxx_messageInfo_Snapshot.Merge(dst, src) -} -func (m *Snapshot) XXX_Size() int { - return xxx_messageInfo_Snapshot.Size(m) -} -func (m *Snapshot) XXX_DiscardUnknown() { - xxx_messageInfo_Snapshot.DiscardUnknown(m) -} - -var xxx_messageInfo_Snapshot proto.InternalMessageInfo - -func (m *Snapshot) GetTs() int64 { - if m != nil && m.Ts != nil { - return *m.Ts - } - return 0 -} - -type InternalHeader struct { - Qos *string `protobuf:"bytes,1,opt,name=qos" json:"qos,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *InternalHeader) Reset() { *m = InternalHeader{} } -func (m *InternalHeader) String() string { return proto.CompactTextString(m) } -func (*InternalHeader) ProtoMessage() {} -func (*InternalHeader) Descriptor() ([]byte, []int) { - return fileDescriptor_datastore_v3_83b17b80c34f6179, []int{13} -} -func (m *InternalHeader) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_InternalHeader.Unmarshal(m, b) -} -func (m *InternalHeader) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_InternalHeader.Marshal(b, m, deterministic) -} -func (dst *InternalHeader) XXX_Merge(src proto.Message) { - xxx_messageInfo_InternalHeader.Merge(dst, src) -} -func (m *InternalHeader) XXX_Size() int { - return xxx_messageInfo_InternalHeader.Size(m) -} -func (m *InternalHeader) XXX_DiscardUnknown() { - xxx_messageInfo_InternalHeader.DiscardUnknown(m) -} - -var xxx_messageInfo_InternalHeader proto.InternalMessageInfo - -func (m *InternalHeader) GetQos() string { - if m != nil && m.Qos != nil { - return *m.Qos - } - return "" -} - -type Transaction struct { - Header *InternalHeader `protobuf:"bytes,4,opt,name=header" json:"header,omitempty"` - Handle *uint64 `protobuf:"fixed64,1,req,name=handle" json:"handle,omitempty"` - App *string `protobuf:"bytes,2,req,name=app" json:"app,omitempty"` - MarkChanges *bool `protobuf:"varint,3,opt,name=mark_changes,json=markChanges,def=0" json:"mark_changes,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *Transaction) Reset() { *m = Transaction{} } -func (m *Transaction) String() string { return proto.CompactTextString(m) } -func (*Transaction) ProtoMessage() {} -func (*Transaction) Descriptor() ([]byte, []int) { - return fileDescriptor_datastore_v3_83b17b80c34f6179, []int{14} -} -func (m *Transaction) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_Transaction.Unmarshal(m, b) -} -func (m *Transaction) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_Transaction.Marshal(b, m, deterministic) -} -func (dst *Transaction) XXX_Merge(src proto.Message) { - xxx_messageInfo_Transaction.Merge(dst, src) -} -func (m *Transaction) XXX_Size() int { - return xxx_messageInfo_Transaction.Size(m) -} -func (m *Transaction) XXX_DiscardUnknown() { - xxx_messageInfo_Transaction.DiscardUnknown(m) -} - -var xxx_messageInfo_Transaction proto.InternalMessageInfo - -const Default_Transaction_MarkChanges bool = false - -func (m *Transaction) GetHeader() *InternalHeader { - if m != nil { - return m.Header - } - return nil -} - -func (m *Transaction) GetHandle() uint64 { - if m != nil && m.Handle != nil { - return *m.Handle - } - return 0 -} - -func (m *Transaction) GetApp() string { - if m != nil && m.App != nil { - return *m.App - } - return "" -} - -func (m *Transaction) GetMarkChanges() bool { - if m != nil && m.MarkChanges != nil { - return *m.MarkChanges - } - return Default_Transaction_MarkChanges -} - -type Query struct { - Header *InternalHeader `protobuf:"bytes,39,opt,name=header" json:"header,omitempty"` - App *string `protobuf:"bytes,1,req,name=app" json:"app,omitempty"` - NameSpace *string `protobuf:"bytes,29,opt,name=name_space,json=nameSpace" json:"name_space,omitempty"` - Kind *string `protobuf:"bytes,3,opt,name=kind" json:"kind,omitempty"` - Ancestor *Reference `protobuf:"bytes,17,opt,name=ancestor" json:"ancestor,omitempty"` - Filter []*Query_Filter `protobuf:"group,4,rep,name=Filter,json=filter" json:"filter,omitempty"` - SearchQuery *string `protobuf:"bytes,8,opt,name=search_query,json=searchQuery" json:"search_query,omitempty"` - Order []*Query_Order `protobuf:"group,9,rep,name=Order,json=order" json:"order,omitempty"` - Hint *Query_Hint `protobuf:"varint,18,opt,name=hint,enum=appengine.Query_Hint" json:"hint,omitempty"` - Count *int32 `protobuf:"varint,23,opt,name=count" json:"count,omitempty"` - Offset *int32 `protobuf:"varint,12,opt,name=offset,def=0" json:"offset,omitempty"` - Limit *int32 `protobuf:"varint,16,opt,name=limit" json:"limit,omitempty"` - CompiledCursor *CompiledCursor `protobuf:"bytes,30,opt,name=compiled_cursor,json=compiledCursor" json:"compiled_cursor,omitempty"` - EndCompiledCursor *CompiledCursor `protobuf:"bytes,31,opt,name=end_compiled_cursor,json=endCompiledCursor" json:"end_compiled_cursor,omitempty"` - CompositeIndex []*CompositeIndex `protobuf:"bytes,19,rep,name=composite_index,json=compositeIndex" json:"composite_index,omitempty"` - RequirePerfectPlan *bool `protobuf:"varint,20,opt,name=require_perfect_plan,json=requirePerfectPlan,def=0" json:"require_perfect_plan,omitempty"` - KeysOnly *bool `protobuf:"varint,21,opt,name=keys_only,json=keysOnly,def=0" json:"keys_only,omitempty"` - Transaction *Transaction `protobuf:"bytes,22,opt,name=transaction" json:"transaction,omitempty"` - Compile *bool `protobuf:"varint,25,opt,name=compile,def=0" json:"compile,omitempty"` - FailoverMs *int64 `protobuf:"varint,26,opt,name=failover_ms,json=failoverMs" json:"failover_ms,omitempty"` - Strong *bool `protobuf:"varint,32,opt,name=strong" json:"strong,omitempty"` - PropertyName []string `protobuf:"bytes,33,rep,name=property_name,json=propertyName" json:"property_name,omitempty"` - GroupByPropertyName []string `protobuf:"bytes,34,rep,name=group_by_property_name,json=groupByPropertyName" json:"group_by_property_name,omitempty"` - Distinct *bool `protobuf:"varint,24,opt,name=distinct" json:"distinct,omitempty"` - MinSafeTimeSeconds *int64 `protobuf:"varint,35,opt,name=min_safe_time_seconds,json=minSafeTimeSeconds" json:"min_safe_time_seconds,omitempty"` - SafeReplicaName []string `protobuf:"bytes,36,rep,name=safe_replica_name,json=safeReplicaName" json:"safe_replica_name,omitempty"` - PersistOffset *bool `protobuf:"varint,37,opt,name=persist_offset,json=persistOffset,def=0" json:"persist_offset,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *Query) Reset() { *m = Query{} } -func (m *Query) String() string { return proto.CompactTextString(m) } -func (*Query) ProtoMessage() {} -func (*Query) Descriptor() ([]byte, []int) { - return fileDescriptor_datastore_v3_83b17b80c34f6179, []int{15} -} -func (m *Query) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_Query.Unmarshal(m, b) -} -func (m *Query) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_Query.Marshal(b, m, deterministic) -} -func (dst *Query) XXX_Merge(src proto.Message) { - xxx_messageInfo_Query.Merge(dst, src) -} -func (m *Query) XXX_Size() int { - return xxx_messageInfo_Query.Size(m) -} -func (m *Query) XXX_DiscardUnknown() { - xxx_messageInfo_Query.DiscardUnknown(m) -} - -var xxx_messageInfo_Query proto.InternalMessageInfo - -const Default_Query_Offset int32 = 0 -const Default_Query_RequirePerfectPlan bool = false -const Default_Query_KeysOnly bool = false -const Default_Query_Compile bool = false -const Default_Query_PersistOffset bool = false - -func (m *Query) GetHeader() *InternalHeader { - if m != nil { - return m.Header - } - return nil -} - -func (m *Query) GetApp() string { - if m != nil && m.App != nil { - return *m.App - } - return "" -} - -func (m *Query) GetNameSpace() string { - if m != nil && m.NameSpace != nil { - return *m.NameSpace - } - return "" -} - -func (m *Query) GetKind() string { - if m != nil && m.Kind != nil { - return *m.Kind - } - return "" -} - -func (m *Query) GetAncestor() *Reference { - if m != nil { - return m.Ancestor - } - return nil -} - -func (m *Query) GetFilter() []*Query_Filter { - if m != nil { - return m.Filter - } - return nil -} - -func (m *Query) GetSearchQuery() string { - if m != nil && m.SearchQuery != nil { - return *m.SearchQuery - } - return "" -} - -func (m *Query) GetOrder() []*Query_Order { - if m != nil { - return m.Order - } - return nil -} - -func (m *Query) GetHint() Query_Hint { - if m != nil && m.Hint != nil { - return *m.Hint - } - return Query_ORDER_FIRST -} - -func (m *Query) GetCount() int32 { - if m != nil && m.Count != nil { - return *m.Count - } - return 0 -} - -func (m *Query) GetOffset() int32 { - if m != nil && m.Offset != nil { - return *m.Offset - } - return Default_Query_Offset -} - -func (m *Query) GetLimit() int32 { - if m != nil && m.Limit != nil { - return *m.Limit - } - return 0 -} - -func (m *Query) GetCompiledCursor() *CompiledCursor { - if m != nil { - return m.CompiledCursor - } - return nil -} - -func (m *Query) GetEndCompiledCursor() *CompiledCursor { - if m != nil { - return m.EndCompiledCursor - } - return nil -} - -func (m *Query) GetCompositeIndex() []*CompositeIndex { - if m != nil { - return m.CompositeIndex - } - return nil -} - -func (m *Query) GetRequirePerfectPlan() bool { - if m != nil && m.RequirePerfectPlan != nil { - return *m.RequirePerfectPlan - } - return Default_Query_RequirePerfectPlan -} - -func (m *Query) GetKeysOnly() bool { - if m != nil && m.KeysOnly != nil { - return *m.KeysOnly - } - return Default_Query_KeysOnly -} - -func (m *Query) GetTransaction() *Transaction { - if m != nil { - return m.Transaction - } - return nil -} - -func (m *Query) GetCompile() bool { - if m != nil && m.Compile != nil { - return *m.Compile - } - return Default_Query_Compile -} - -func (m *Query) GetFailoverMs() int64 { - if m != nil && m.FailoverMs != nil { - return *m.FailoverMs - } - return 0 -} - -func (m *Query) GetStrong() bool { - if m != nil && m.Strong != nil { - return *m.Strong - } - return false -} - -func (m *Query) GetPropertyName() []string { - if m != nil { - return m.PropertyName - } - return nil -} - -func (m *Query) GetGroupByPropertyName() []string { - if m != nil { - return m.GroupByPropertyName - } - return nil -} - -func (m *Query) GetDistinct() bool { - if m != nil && m.Distinct != nil { - return *m.Distinct - } - return false -} - -func (m *Query) GetMinSafeTimeSeconds() int64 { - if m != nil && m.MinSafeTimeSeconds != nil { - return *m.MinSafeTimeSeconds - } - return 0 -} - -func (m *Query) GetSafeReplicaName() []string { - if m != nil { - return m.SafeReplicaName - } - return nil -} - -func (m *Query) GetPersistOffset() bool { - if m != nil && m.PersistOffset != nil { - return *m.PersistOffset - } - return Default_Query_PersistOffset -} - -type Query_Filter struct { - Op *Query_Filter_Operator `protobuf:"varint,6,req,name=op,enum=appengine.Query_Filter_Operator" json:"op,omitempty"` - Property []*Property `protobuf:"bytes,14,rep,name=property" json:"property,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *Query_Filter) Reset() { *m = Query_Filter{} } -func (m *Query_Filter) String() string { return proto.CompactTextString(m) } -func (*Query_Filter) ProtoMessage() {} -func (*Query_Filter) Descriptor() ([]byte, []int) { - return fileDescriptor_datastore_v3_83b17b80c34f6179, []int{15, 0} -} -func (m *Query_Filter) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_Query_Filter.Unmarshal(m, b) -} -func (m *Query_Filter) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_Query_Filter.Marshal(b, m, deterministic) -} -func (dst *Query_Filter) XXX_Merge(src proto.Message) { - xxx_messageInfo_Query_Filter.Merge(dst, src) -} -func (m *Query_Filter) XXX_Size() int { - return xxx_messageInfo_Query_Filter.Size(m) -} -func (m *Query_Filter) XXX_DiscardUnknown() { - xxx_messageInfo_Query_Filter.DiscardUnknown(m) -} - -var xxx_messageInfo_Query_Filter proto.InternalMessageInfo - -func (m *Query_Filter) GetOp() Query_Filter_Operator { - if m != nil && m.Op != nil { - return *m.Op - } - return Query_Filter_LESS_THAN -} - -func (m *Query_Filter) GetProperty() []*Property { - if m != nil { - return m.Property - } - return nil -} - -type Query_Order struct { - Property *string `protobuf:"bytes,10,req,name=property" json:"property,omitempty"` - Direction *Query_Order_Direction `protobuf:"varint,11,opt,name=direction,enum=appengine.Query_Order_Direction,def=1" json:"direction,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *Query_Order) Reset() { *m = Query_Order{} } -func (m *Query_Order) String() string { return proto.CompactTextString(m) } -func (*Query_Order) ProtoMessage() {} -func (*Query_Order) Descriptor() ([]byte, []int) { - return fileDescriptor_datastore_v3_83b17b80c34f6179, []int{15, 1} -} -func (m *Query_Order) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_Query_Order.Unmarshal(m, b) -} -func (m *Query_Order) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_Query_Order.Marshal(b, m, deterministic) -} -func (dst *Query_Order) XXX_Merge(src proto.Message) { - xxx_messageInfo_Query_Order.Merge(dst, src) -} -func (m *Query_Order) XXX_Size() int { - return xxx_messageInfo_Query_Order.Size(m) -} -func (m *Query_Order) XXX_DiscardUnknown() { - xxx_messageInfo_Query_Order.DiscardUnknown(m) -} - -var xxx_messageInfo_Query_Order proto.InternalMessageInfo - -const Default_Query_Order_Direction Query_Order_Direction = Query_Order_ASCENDING - -func (m *Query_Order) GetProperty() string { - if m != nil && m.Property != nil { - return *m.Property - } - return "" -} - -func (m *Query_Order) GetDirection() Query_Order_Direction { - if m != nil && m.Direction != nil { - return *m.Direction - } - return Default_Query_Order_Direction -} - -type CompiledQuery struct { - Primaryscan *CompiledQuery_PrimaryScan `protobuf:"group,1,req,name=PrimaryScan,json=primaryscan" json:"primaryscan,omitempty"` - Mergejoinscan []*CompiledQuery_MergeJoinScan `protobuf:"group,7,rep,name=MergeJoinScan,json=mergejoinscan" json:"mergejoinscan,omitempty"` - IndexDef *Index `protobuf:"bytes,21,opt,name=index_def,json=indexDef" json:"index_def,omitempty"` - Offset *int32 `protobuf:"varint,10,opt,name=offset,def=0" json:"offset,omitempty"` - Limit *int32 `protobuf:"varint,11,opt,name=limit" json:"limit,omitempty"` - KeysOnly *bool `protobuf:"varint,12,req,name=keys_only,json=keysOnly" json:"keys_only,omitempty"` - PropertyName []string `protobuf:"bytes,24,rep,name=property_name,json=propertyName" json:"property_name,omitempty"` - DistinctInfixSize *int32 `protobuf:"varint,25,opt,name=distinct_infix_size,json=distinctInfixSize" json:"distinct_infix_size,omitempty"` - Entityfilter *CompiledQuery_EntityFilter `protobuf:"group,13,opt,name=EntityFilter,json=entityfilter" json:"entityfilter,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *CompiledQuery) Reset() { *m = CompiledQuery{} } -func (m *CompiledQuery) String() string { return proto.CompactTextString(m) } -func (*CompiledQuery) ProtoMessage() {} -func (*CompiledQuery) Descriptor() ([]byte, []int) { - return fileDescriptor_datastore_v3_83b17b80c34f6179, []int{16} -} -func (m *CompiledQuery) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_CompiledQuery.Unmarshal(m, b) -} -func (m *CompiledQuery) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_CompiledQuery.Marshal(b, m, deterministic) -} -func (dst *CompiledQuery) XXX_Merge(src proto.Message) { - xxx_messageInfo_CompiledQuery.Merge(dst, src) -} -func (m *CompiledQuery) XXX_Size() int { - return xxx_messageInfo_CompiledQuery.Size(m) -} -func (m *CompiledQuery) XXX_DiscardUnknown() { - xxx_messageInfo_CompiledQuery.DiscardUnknown(m) -} - -var xxx_messageInfo_CompiledQuery proto.InternalMessageInfo - -const Default_CompiledQuery_Offset int32 = 0 - -func (m *CompiledQuery) GetPrimaryscan() *CompiledQuery_PrimaryScan { - if m != nil { - return m.Primaryscan - } - return nil -} - -func (m *CompiledQuery) GetMergejoinscan() []*CompiledQuery_MergeJoinScan { - if m != nil { - return m.Mergejoinscan - } - return nil -} - -func (m *CompiledQuery) GetIndexDef() *Index { - if m != nil { - return m.IndexDef - } - return nil -} - -func (m *CompiledQuery) GetOffset() int32 { - if m != nil && m.Offset != nil { - return *m.Offset - } - return Default_CompiledQuery_Offset -} - -func (m *CompiledQuery) GetLimit() int32 { - if m != nil && m.Limit != nil { - return *m.Limit - } - return 0 -} - -func (m *CompiledQuery) GetKeysOnly() bool { - if m != nil && m.KeysOnly != nil { - return *m.KeysOnly - } - return false -} - -func (m *CompiledQuery) GetPropertyName() []string { - if m != nil { - return m.PropertyName - } - return nil -} - -func (m *CompiledQuery) GetDistinctInfixSize() int32 { - if m != nil && m.DistinctInfixSize != nil { - return *m.DistinctInfixSize - } - return 0 -} - -func (m *CompiledQuery) GetEntityfilter() *CompiledQuery_EntityFilter { - if m != nil { - return m.Entityfilter - } - return nil -} - -type CompiledQuery_PrimaryScan struct { - IndexName *string `protobuf:"bytes,2,opt,name=index_name,json=indexName" json:"index_name,omitempty"` - StartKey *string `protobuf:"bytes,3,opt,name=start_key,json=startKey" json:"start_key,omitempty"` - StartInclusive *bool `protobuf:"varint,4,opt,name=start_inclusive,json=startInclusive" json:"start_inclusive,omitempty"` - EndKey *string `protobuf:"bytes,5,opt,name=end_key,json=endKey" json:"end_key,omitempty"` - EndInclusive *bool `protobuf:"varint,6,opt,name=end_inclusive,json=endInclusive" json:"end_inclusive,omitempty"` - StartPostfixValue []string `protobuf:"bytes,22,rep,name=start_postfix_value,json=startPostfixValue" json:"start_postfix_value,omitempty"` - EndPostfixValue []string `protobuf:"bytes,23,rep,name=end_postfix_value,json=endPostfixValue" json:"end_postfix_value,omitempty"` - EndUnappliedLogTimestampUs *int64 `protobuf:"varint,19,opt,name=end_unapplied_log_timestamp_us,json=endUnappliedLogTimestampUs" json:"end_unapplied_log_timestamp_us,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *CompiledQuery_PrimaryScan) Reset() { *m = CompiledQuery_PrimaryScan{} } -func (m *CompiledQuery_PrimaryScan) String() string { return proto.CompactTextString(m) } -func (*CompiledQuery_PrimaryScan) ProtoMessage() {} -func (*CompiledQuery_PrimaryScan) Descriptor() ([]byte, []int) { - return fileDescriptor_datastore_v3_83b17b80c34f6179, []int{16, 0} -} -func (m *CompiledQuery_PrimaryScan) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_CompiledQuery_PrimaryScan.Unmarshal(m, b) -} -func (m *CompiledQuery_PrimaryScan) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_CompiledQuery_PrimaryScan.Marshal(b, m, deterministic) -} -func (dst *CompiledQuery_PrimaryScan) XXX_Merge(src proto.Message) { - xxx_messageInfo_CompiledQuery_PrimaryScan.Merge(dst, src) -} -func (m *CompiledQuery_PrimaryScan) XXX_Size() int { - return xxx_messageInfo_CompiledQuery_PrimaryScan.Size(m) -} -func (m *CompiledQuery_PrimaryScan) XXX_DiscardUnknown() { - xxx_messageInfo_CompiledQuery_PrimaryScan.DiscardUnknown(m) -} - -var xxx_messageInfo_CompiledQuery_PrimaryScan proto.InternalMessageInfo - -func (m *CompiledQuery_PrimaryScan) GetIndexName() string { - if m != nil && m.IndexName != nil { - return *m.IndexName - } - return "" -} - -func (m *CompiledQuery_PrimaryScan) GetStartKey() string { - if m != nil && m.StartKey != nil { - return *m.StartKey - } - return "" -} - -func (m *CompiledQuery_PrimaryScan) GetStartInclusive() bool { - if m != nil && m.StartInclusive != nil { - return *m.StartInclusive - } - return false -} - -func (m *CompiledQuery_PrimaryScan) GetEndKey() string { - if m != nil && m.EndKey != nil { - return *m.EndKey - } - return "" -} - -func (m *CompiledQuery_PrimaryScan) GetEndInclusive() bool { - if m != nil && m.EndInclusive != nil { - return *m.EndInclusive - } - return false -} - -func (m *CompiledQuery_PrimaryScan) GetStartPostfixValue() []string { - if m != nil { - return m.StartPostfixValue - } - return nil -} - -func (m *CompiledQuery_PrimaryScan) GetEndPostfixValue() []string { - if m != nil { - return m.EndPostfixValue - } - return nil -} - -func (m *CompiledQuery_PrimaryScan) GetEndUnappliedLogTimestampUs() int64 { - if m != nil && m.EndUnappliedLogTimestampUs != nil { - return *m.EndUnappliedLogTimestampUs - } - return 0 -} - -type CompiledQuery_MergeJoinScan struct { - IndexName *string `protobuf:"bytes,8,req,name=index_name,json=indexName" json:"index_name,omitempty"` - PrefixValue []string `protobuf:"bytes,9,rep,name=prefix_value,json=prefixValue" json:"prefix_value,omitempty"` - ValuePrefix *bool `protobuf:"varint,20,opt,name=value_prefix,json=valuePrefix,def=0" json:"value_prefix,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *CompiledQuery_MergeJoinScan) Reset() { *m = CompiledQuery_MergeJoinScan{} } -func (m *CompiledQuery_MergeJoinScan) String() string { return proto.CompactTextString(m) } -func (*CompiledQuery_MergeJoinScan) ProtoMessage() {} -func (*CompiledQuery_MergeJoinScan) Descriptor() ([]byte, []int) { - return fileDescriptor_datastore_v3_83b17b80c34f6179, []int{16, 1} -} -func (m *CompiledQuery_MergeJoinScan) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_CompiledQuery_MergeJoinScan.Unmarshal(m, b) -} -func (m *CompiledQuery_MergeJoinScan) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_CompiledQuery_MergeJoinScan.Marshal(b, m, deterministic) -} -func (dst *CompiledQuery_MergeJoinScan) XXX_Merge(src proto.Message) { - xxx_messageInfo_CompiledQuery_MergeJoinScan.Merge(dst, src) -} -func (m *CompiledQuery_MergeJoinScan) XXX_Size() int { - return xxx_messageInfo_CompiledQuery_MergeJoinScan.Size(m) -} -func (m *CompiledQuery_MergeJoinScan) XXX_DiscardUnknown() { - xxx_messageInfo_CompiledQuery_MergeJoinScan.DiscardUnknown(m) -} - -var xxx_messageInfo_CompiledQuery_MergeJoinScan proto.InternalMessageInfo - -const Default_CompiledQuery_MergeJoinScan_ValuePrefix bool = false - -func (m *CompiledQuery_MergeJoinScan) GetIndexName() string { - if m != nil && m.IndexName != nil { - return *m.IndexName - } - return "" -} - -func (m *CompiledQuery_MergeJoinScan) GetPrefixValue() []string { - if m != nil { - return m.PrefixValue - } - return nil -} - -func (m *CompiledQuery_MergeJoinScan) GetValuePrefix() bool { - if m != nil && m.ValuePrefix != nil { - return *m.ValuePrefix - } - return Default_CompiledQuery_MergeJoinScan_ValuePrefix -} - -type CompiledQuery_EntityFilter struct { - Distinct *bool `protobuf:"varint,14,opt,name=distinct,def=0" json:"distinct,omitempty"` - Kind *string `protobuf:"bytes,17,opt,name=kind" json:"kind,omitempty"` - Ancestor *Reference `protobuf:"bytes,18,opt,name=ancestor" json:"ancestor,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *CompiledQuery_EntityFilter) Reset() { *m = CompiledQuery_EntityFilter{} } -func (m *CompiledQuery_EntityFilter) String() string { return proto.CompactTextString(m) } -func (*CompiledQuery_EntityFilter) ProtoMessage() {} -func (*CompiledQuery_EntityFilter) Descriptor() ([]byte, []int) { - return fileDescriptor_datastore_v3_83b17b80c34f6179, []int{16, 2} -} -func (m *CompiledQuery_EntityFilter) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_CompiledQuery_EntityFilter.Unmarshal(m, b) -} -func (m *CompiledQuery_EntityFilter) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_CompiledQuery_EntityFilter.Marshal(b, m, deterministic) -} -func (dst *CompiledQuery_EntityFilter) XXX_Merge(src proto.Message) { - xxx_messageInfo_CompiledQuery_EntityFilter.Merge(dst, src) -} -func (m *CompiledQuery_EntityFilter) XXX_Size() int { - return xxx_messageInfo_CompiledQuery_EntityFilter.Size(m) -} -func (m *CompiledQuery_EntityFilter) XXX_DiscardUnknown() { - xxx_messageInfo_CompiledQuery_EntityFilter.DiscardUnknown(m) -} - -var xxx_messageInfo_CompiledQuery_EntityFilter proto.InternalMessageInfo - -const Default_CompiledQuery_EntityFilter_Distinct bool = false - -func (m *CompiledQuery_EntityFilter) GetDistinct() bool { - if m != nil && m.Distinct != nil { - return *m.Distinct - } - return Default_CompiledQuery_EntityFilter_Distinct -} - -func (m *CompiledQuery_EntityFilter) GetKind() string { - if m != nil && m.Kind != nil { - return *m.Kind - } - return "" -} - -func (m *CompiledQuery_EntityFilter) GetAncestor() *Reference { - if m != nil { - return m.Ancestor - } - return nil -} - -type CompiledCursor struct { - Position *CompiledCursor_Position `protobuf:"group,2,opt,name=Position,json=position" json:"position,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *CompiledCursor) Reset() { *m = CompiledCursor{} } -func (m *CompiledCursor) String() string { return proto.CompactTextString(m) } -func (*CompiledCursor) ProtoMessage() {} -func (*CompiledCursor) Descriptor() ([]byte, []int) { - return fileDescriptor_datastore_v3_83b17b80c34f6179, []int{17} -} -func (m *CompiledCursor) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_CompiledCursor.Unmarshal(m, b) -} -func (m *CompiledCursor) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_CompiledCursor.Marshal(b, m, deterministic) -} -func (dst *CompiledCursor) XXX_Merge(src proto.Message) { - xxx_messageInfo_CompiledCursor.Merge(dst, src) -} -func (m *CompiledCursor) XXX_Size() int { - return xxx_messageInfo_CompiledCursor.Size(m) -} -func (m *CompiledCursor) XXX_DiscardUnknown() { - xxx_messageInfo_CompiledCursor.DiscardUnknown(m) -} - -var xxx_messageInfo_CompiledCursor proto.InternalMessageInfo - -func (m *CompiledCursor) GetPosition() *CompiledCursor_Position { - if m != nil { - return m.Position - } - return nil -} - -type CompiledCursor_Position struct { - StartKey *string `protobuf:"bytes,27,opt,name=start_key,json=startKey" json:"start_key,omitempty"` - Indexvalue []*CompiledCursor_Position_IndexValue `protobuf:"group,29,rep,name=IndexValue,json=indexvalue" json:"indexvalue,omitempty"` - Key *Reference `protobuf:"bytes,32,opt,name=key" json:"key,omitempty"` - StartInclusive *bool `protobuf:"varint,28,opt,name=start_inclusive,json=startInclusive,def=1" json:"start_inclusive,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *CompiledCursor_Position) Reset() { *m = CompiledCursor_Position{} } -func (m *CompiledCursor_Position) String() string { return proto.CompactTextString(m) } -func (*CompiledCursor_Position) ProtoMessage() {} -func (*CompiledCursor_Position) Descriptor() ([]byte, []int) { - return fileDescriptor_datastore_v3_83b17b80c34f6179, []int{17, 0} -} -func (m *CompiledCursor_Position) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_CompiledCursor_Position.Unmarshal(m, b) -} -func (m *CompiledCursor_Position) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_CompiledCursor_Position.Marshal(b, m, deterministic) -} -func (dst *CompiledCursor_Position) XXX_Merge(src proto.Message) { - xxx_messageInfo_CompiledCursor_Position.Merge(dst, src) -} -func (m *CompiledCursor_Position) XXX_Size() int { - return xxx_messageInfo_CompiledCursor_Position.Size(m) -} -func (m *CompiledCursor_Position) XXX_DiscardUnknown() { - xxx_messageInfo_CompiledCursor_Position.DiscardUnknown(m) -} - -var xxx_messageInfo_CompiledCursor_Position proto.InternalMessageInfo - -const Default_CompiledCursor_Position_StartInclusive bool = true - -func (m *CompiledCursor_Position) GetStartKey() string { - if m != nil && m.StartKey != nil { - return *m.StartKey - } - return "" -} - -func (m *CompiledCursor_Position) GetIndexvalue() []*CompiledCursor_Position_IndexValue { - if m != nil { - return m.Indexvalue - } - return nil -} - -func (m *CompiledCursor_Position) GetKey() *Reference { - if m != nil { - return m.Key - } - return nil -} - -func (m *CompiledCursor_Position) GetStartInclusive() bool { - if m != nil && m.StartInclusive != nil { - return *m.StartInclusive - } - return Default_CompiledCursor_Position_StartInclusive -} - -type CompiledCursor_Position_IndexValue struct { - Property *string `protobuf:"bytes,30,opt,name=property" json:"property,omitempty"` - Value *PropertyValue `protobuf:"bytes,31,req,name=value" json:"value,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *CompiledCursor_Position_IndexValue) Reset() { *m = CompiledCursor_Position_IndexValue{} } -func (m *CompiledCursor_Position_IndexValue) String() string { return proto.CompactTextString(m) } -func (*CompiledCursor_Position_IndexValue) ProtoMessage() {} -func (*CompiledCursor_Position_IndexValue) Descriptor() ([]byte, []int) { - return fileDescriptor_datastore_v3_83b17b80c34f6179, []int{17, 0, 0} -} -func (m *CompiledCursor_Position_IndexValue) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_CompiledCursor_Position_IndexValue.Unmarshal(m, b) -} -func (m *CompiledCursor_Position_IndexValue) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_CompiledCursor_Position_IndexValue.Marshal(b, m, deterministic) -} -func (dst *CompiledCursor_Position_IndexValue) XXX_Merge(src proto.Message) { - xxx_messageInfo_CompiledCursor_Position_IndexValue.Merge(dst, src) -} -func (m *CompiledCursor_Position_IndexValue) XXX_Size() int { - return xxx_messageInfo_CompiledCursor_Position_IndexValue.Size(m) -} -func (m *CompiledCursor_Position_IndexValue) XXX_DiscardUnknown() { - xxx_messageInfo_CompiledCursor_Position_IndexValue.DiscardUnknown(m) -} - -var xxx_messageInfo_CompiledCursor_Position_IndexValue proto.InternalMessageInfo - -func (m *CompiledCursor_Position_IndexValue) GetProperty() string { - if m != nil && m.Property != nil { - return *m.Property - } - return "" -} - -func (m *CompiledCursor_Position_IndexValue) GetValue() *PropertyValue { - if m != nil { - return m.Value - } - return nil -} - -type Cursor struct { - Cursor *uint64 `protobuf:"fixed64,1,req,name=cursor" json:"cursor,omitempty"` - App *string `protobuf:"bytes,2,opt,name=app" json:"app,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *Cursor) Reset() { *m = Cursor{} } -func (m *Cursor) String() string { return proto.CompactTextString(m) } -func (*Cursor) ProtoMessage() {} -func (*Cursor) Descriptor() ([]byte, []int) { - return fileDescriptor_datastore_v3_83b17b80c34f6179, []int{18} -} -func (m *Cursor) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_Cursor.Unmarshal(m, b) -} -func (m *Cursor) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_Cursor.Marshal(b, m, deterministic) -} -func (dst *Cursor) XXX_Merge(src proto.Message) { - xxx_messageInfo_Cursor.Merge(dst, src) -} -func (m *Cursor) XXX_Size() int { - return xxx_messageInfo_Cursor.Size(m) -} -func (m *Cursor) XXX_DiscardUnknown() { - xxx_messageInfo_Cursor.DiscardUnknown(m) -} - -var xxx_messageInfo_Cursor proto.InternalMessageInfo - -func (m *Cursor) GetCursor() uint64 { - if m != nil && m.Cursor != nil { - return *m.Cursor - } - return 0 -} - -func (m *Cursor) GetApp() string { - if m != nil && m.App != nil { - return *m.App - } - return "" -} - -type Error struct { - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *Error) Reset() { *m = Error{} } -func (m *Error) String() string { return proto.CompactTextString(m) } -func (*Error) ProtoMessage() {} -func (*Error) Descriptor() ([]byte, []int) { - return fileDescriptor_datastore_v3_83b17b80c34f6179, []int{19} -} -func (m *Error) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_Error.Unmarshal(m, b) -} -func (m *Error) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_Error.Marshal(b, m, deterministic) -} -func (dst *Error) XXX_Merge(src proto.Message) { - xxx_messageInfo_Error.Merge(dst, src) -} -func (m *Error) XXX_Size() int { - return xxx_messageInfo_Error.Size(m) -} -func (m *Error) XXX_DiscardUnknown() { - xxx_messageInfo_Error.DiscardUnknown(m) -} - -var xxx_messageInfo_Error proto.InternalMessageInfo - -type Cost struct { - IndexWrites *int32 `protobuf:"varint,1,opt,name=index_writes,json=indexWrites" json:"index_writes,omitempty"` - IndexWriteBytes *int32 `protobuf:"varint,2,opt,name=index_write_bytes,json=indexWriteBytes" json:"index_write_bytes,omitempty"` - EntityWrites *int32 `protobuf:"varint,3,opt,name=entity_writes,json=entityWrites" json:"entity_writes,omitempty"` - EntityWriteBytes *int32 `protobuf:"varint,4,opt,name=entity_write_bytes,json=entityWriteBytes" json:"entity_write_bytes,omitempty"` - Commitcost *Cost_CommitCost `protobuf:"group,5,opt,name=CommitCost,json=commitcost" json:"commitcost,omitempty"` - ApproximateStorageDelta *int32 `protobuf:"varint,8,opt,name=approximate_storage_delta,json=approximateStorageDelta" json:"approximate_storage_delta,omitempty"` - IdSequenceUpdates *int32 `protobuf:"varint,9,opt,name=id_sequence_updates,json=idSequenceUpdates" json:"id_sequence_updates,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *Cost) Reset() { *m = Cost{} } -func (m *Cost) String() string { return proto.CompactTextString(m) } -func (*Cost) ProtoMessage() {} -func (*Cost) Descriptor() ([]byte, []int) { - return fileDescriptor_datastore_v3_83b17b80c34f6179, []int{20} -} -func (m *Cost) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_Cost.Unmarshal(m, b) -} -func (m *Cost) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_Cost.Marshal(b, m, deterministic) -} -func (dst *Cost) XXX_Merge(src proto.Message) { - xxx_messageInfo_Cost.Merge(dst, src) -} -func (m *Cost) XXX_Size() int { - return xxx_messageInfo_Cost.Size(m) -} -func (m *Cost) XXX_DiscardUnknown() { - xxx_messageInfo_Cost.DiscardUnknown(m) -} - -var xxx_messageInfo_Cost proto.InternalMessageInfo - -func (m *Cost) GetIndexWrites() int32 { - if m != nil && m.IndexWrites != nil { - return *m.IndexWrites - } - return 0 -} - -func (m *Cost) GetIndexWriteBytes() int32 { - if m != nil && m.IndexWriteBytes != nil { - return *m.IndexWriteBytes - } - return 0 -} - -func (m *Cost) GetEntityWrites() int32 { - if m != nil && m.EntityWrites != nil { - return *m.EntityWrites - } - return 0 -} - -func (m *Cost) GetEntityWriteBytes() int32 { - if m != nil && m.EntityWriteBytes != nil { - return *m.EntityWriteBytes - } - return 0 -} - -func (m *Cost) GetCommitcost() *Cost_CommitCost { - if m != nil { - return m.Commitcost - } - return nil -} - -func (m *Cost) GetApproximateStorageDelta() int32 { - if m != nil && m.ApproximateStorageDelta != nil { - return *m.ApproximateStorageDelta - } - return 0 -} - -func (m *Cost) GetIdSequenceUpdates() int32 { - if m != nil && m.IdSequenceUpdates != nil { - return *m.IdSequenceUpdates - } - return 0 -} - -type Cost_CommitCost struct { - RequestedEntityPuts *int32 `protobuf:"varint,6,opt,name=requested_entity_puts,json=requestedEntityPuts" json:"requested_entity_puts,omitempty"` - RequestedEntityDeletes *int32 `protobuf:"varint,7,opt,name=requested_entity_deletes,json=requestedEntityDeletes" json:"requested_entity_deletes,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *Cost_CommitCost) Reset() { *m = Cost_CommitCost{} } -func (m *Cost_CommitCost) String() string { return proto.CompactTextString(m) } -func (*Cost_CommitCost) ProtoMessage() {} -func (*Cost_CommitCost) Descriptor() ([]byte, []int) { - return fileDescriptor_datastore_v3_83b17b80c34f6179, []int{20, 0} -} -func (m *Cost_CommitCost) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_Cost_CommitCost.Unmarshal(m, b) -} -func (m *Cost_CommitCost) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_Cost_CommitCost.Marshal(b, m, deterministic) -} -func (dst *Cost_CommitCost) XXX_Merge(src proto.Message) { - xxx_messageInfo_Cost_CommitCost.Merge(dst, src) -} -func (m *Cost_CommitCost) XXX_Size() int { - return xxx_messageInfo_Cost_CommitCost.Size(m) -} -func (m *Cost_CommitCost) XXX_DiscardUnknown() { - xxx_messageInfo_Cost_CommitCost.DiscardUnknown(m) -} - -var xxx_messageInfo_Cost_CommitCost proto.InternalMessageInfo - -func (m *Cost_CommitCost) GetRequestedEntityPuts() int32 { - if m != nil && m.RequestedEntityPuts != nil { - return *m.RequestedEntityPuts - } - return 0 -} - -func (m *Cost_CommitCost) GetRequestedEntityDeletes() int32 { - if m != nil && m.RequestedEntityDeletes != nil { - return *m.RequestedEntityDeletes - } - return 0 -} - -type GetRequest struct { - Header *InternalHeader `protobuf:"bytes,6,opt,name=header" json:"header,omitempty"` - Key []*Reference `protobuf:"bytes,1,rep,name=key" json:"key,omitempty"` - Transaction *Transaction `protobuf:"bytes,2,opt,name=transaction" json:"transaction,omitempty"` - FailoverMs *int64 `protobuf:"varint,3,opt,name=failover_ms,json=failoverMs" json:"failover_ms,omitempty"` - Strong *bool `protobuf:"varint,4,opt,name=strong" json:"strong,omitempty"` - AllowDeferred *bool `protobuf:"varint,5,opt,name=allow_deferred,json=allowDeferred,def=0" json:"allow_deferred,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *GetRequest) Reset() { *m = GetRequest{} } -func (m *GetRequest) String() string { return proto.CompactTextString(m) } -func (*GetRequest) ProtoMessage() {} -func (*GetRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_datastore_v3_83b17b80c34f6179, []int{21} -} -func (m *GetRequest) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_GetRequest.Unmarshal(m, b) -} -func (m *GetRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_GetRequest.Marshal(b, m, deterministic) -} -func (dst *GetRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_GetRequest.Merge(dst, src) -} -func (m *GetRequest) XXX_Size() int { - return xxx_messageInfo_GetRequest.Size(m) -} -func (m *GetRequest) XXX_DiscardUnknown() { - xxx_messageInfo_GetRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_GetRequest proto.InternalMessageInfo - -const Default_GetRequest_AllowDeferred bool = false - -func (m *GetRequest) GetHeader() *InternalHeader { - if m != nil { - return m.Header - } - return nil -} - -func (m *GetRequest) GetKey() []*Reference { - if m != nil { - return m.Key - } - return nil -} - -func (m *GetRequest) GetTransaction() *Transaction { - if m != nil { - return m.Transaction - } - return nil -} - -func (m *GetRequest) GetFailoverMs() int64 { - if m != nil && m.FailoverMs != nil { - return *m.FailoverMs - } - return 0 -} - -func (m *GetRequest) GetStrong() bool { - if m != nil && m.Strong != nil { - return *m.Strong - } - return false -} - -func (m *GetRequest) GetAllowDeferred() bool { - if m != nil && m.AllowDeferred != nil { - return *m.AllowDeferred - } - return Default_GetRequest_AllowDeferred -} - -type GetResponse struct { - Entity []*GetResponse_Entity `protobuf:"group,1,rep,name=Entity,json=entity" json:"entity,omitempty"` - Deferred []*Reference `protobuf:"bytes,5,rep,name=deferred" json:"deferred,omitempty"` - InOrder *bool `protobuf:"varint,6,opt,name=in_order,json=inOrder,def=1" json:"in_order,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *GetResponse) Reset() { *m = GetResponse{} } -func (m *GetResponse) String() string { return proto.CompactTextString(m) } -func (*GetResponse) ProtoMessage() {} -func (*GetResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_datastore_v3_83b17b80c34f6179, []int{22} -} -func (m *GetResponse) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_GetResponse.Unmarshal(m, b) -} -func (m *GetResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_GetResponse.Marshal(b, m, deterministic) -} -func (dst *GetResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_GetResponse.Merge(dst, src) -} -func (m *GetResponse) XXX_Size() int { - return xxx_messageInfo_GetResponse.Size(m) -} -func (m *GetResponse) XXX_DiscardUnknown() { - xxx_messageInfo_GetResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_GetResponse proto.InternalMessageInfo - -const Default_GetResponse_InOrder bool = true - -func (m *GetResponse) GetEntity() []*GetResponse_Entity { - if m != nil { - return m.Entity - } - return nil -} - -func (m *GetResponse) GetDeferred() []*Reference { - if m != nil { - return m.Deferred - } - return nil -} - -func (m *GetResponse) GetInOrder() bool { - if m != nil && m.InOrder != nil { - return *m.InOrder - } - return Default_GetResponse_InOrder -} - -type GetResponse_Entity struct { - Entity *EntityProto `protobuf:"bytes,2,opt,name=entity" json:"entity,omitempty"` - Key *Reference `protobuf:"bytes,4,opt,name=key" json:"key,omitempty"` - Version *int64 `protobuf:"varint,3,opt,name=version" json:"version,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *GetResponse_Entity) Reset() { *m = GetResponse_Entity{} } -func (m *GetResponse_Entity) String() string { return proto.CompactTextString(m) } -func (*GetResponse_Entity) ProtoMessage() {} -func (*GetResponse_Entity) Descriptor() ([]byte, []int) { - return fileDescriptor_datastore_v3_83b17b80c34f6179, []int{22, 0} -} -func (m *GetResponse_Entity) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_GetResponse_Entity.Unmarshal(m, b) -} -func (m *GetResponse_Entity) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_GetResponse_Entity.Marshal(b, m, deterministic) -} -func (dst *GetResponse_Entity) XXX_Merge(src proto.Message) { - xxx_messageInfo_GetResponse_Entity.Merge(dst, src) -} -func (m *GetResponse_Entity) XXX_Size() int { - return xxx_messageInfo_GetResponse_Entity.Size(m) -} -func (m *GetResponse_Entity) XXX_DiscardUnknown() { - xxx_messageInfo_GetResponse_Entity.DiscardUnknown(m) -} - -var xxx_messageInfo_GetResponse_Entity proto.InternalMessageInfo - -func (m *GetResponse_Entity) GetEntity() *EntityProto { - if m != nil { - return m.Entity - } - return nil -} - -func (m *GetResponse_Entity) GetKey() *Reference { - if m != nil { - return m.Key - } - return nil -} - -func (m *GetResponse_Entity) GetVersion() int64 { - if m != nil && m.Version != nil { - return *m.Version - } - return 0 -} - -type PutRequest struct { - Header *InternalHeader `protobuf:"bytes,11,opt,name=header" json:"header,omitempty"` - Entity []*EntityProto `protobuf:"bytes,1,rep,name=entity" json:"entity,omitempty"` - Transaction *Transaction `protobuf:"bytes,2,opt,name=transaction" json:"transaction,omitempty"` - CompositeIndex []*CompositeIndex `protobuf:"bytes,3,rep,name=composite_index,json=compositeIndex" json:"composite_index,omitempty"` - Trusted *bool `protobuf:"varint,4,opt,name=trusted,def=0" json:"trusted,omitempty"` - Force *bool `protobuf:"varint,7,opt,name=force,def=0" json:"force,omitempty"` - MarkChanges *bool `protobuf:"varint,8,opt,name=mark_changes,json=markChanges,def=0" json:"mark_changes,omitempty"` - Snapshot []*Snapshot `protobuf:"bytes,9,rep,name=snapshot" json:"snapshot,omitempty"` - AutoIdPolicy *PutRequest_AutoIdPolicy `protobuf:"varint,10,opt,name=auto_id_policy,json=autoIdPolicy,enum=appengine.PutRequest_AutoIdPolicy,def=0" json:"auto_id_policy,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *PutRequest) Reset() { *m = PutRequest{} } -func (m *PutRequest) String() string { return proto.CompactTextString(m) } -func (*PutRequest) ProtoMessage() {} -func (*PutRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_datastore_v3_83b17b80c34f6179, []int{23} -} -func (m *PutRequest) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_PutRequest.Unmarshal(m, b) -} -func (m *PutRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_PutRequest.Marshal(b, m, deterministic) -} -func (dst *PutRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_PutRequest.Merge(dst, src) -} -func (m *PutRequest) XXX_Size() int { - return xxx_messageInfo_PutRequest.Size(m) -} -func (m *PutRequest) XXX_DiscardUnknown() { - xxx_messageInfo_PutRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_PutRequest proto.InternalMessageInfo - -const Default_PutRequest_Trusted bool = false -const Default_PutRequest_Force bool = false -const Default_PutRequest_MarkChanges bool = false -const Default_PutRequest_AutoIdPolicy PutRequest_AutoIdPolicy = PutRequest_CURRENT - -func (m *PutRequest) GetHeader() *InternalHeader { - if m != nil { - return m.Header - } - return nil -} - -func (m *PutRequest) GetEntity() []*EntityProto { - if m != nil { - return m.Entity - } - return nil -} - -func (m *PutRequest) GetTransaction() *Transaction { - if m != nil { - return m.Transaction - } - return nil -} - -func (m *PutRequest) GetCompositeIndex() []*CompositeIndex { - if m != nil { - return m.CompositeIndex - } - return nil -} - -func (m *PutRequest) GetTrusted() bool { - if m != nil && m.Trusted != nil { - return *m.Trusted - } - return Default_PutRequest_Trusted -} - -func (m *PutRequest) GetForce() bool { - if m != nil && m.Force != nil { - return *m.Force - } - return Default_PutRequest_Force -} - -func (m *PutRequest) GetMarkChanges() bool { - if m != nil && m.MarkChanges != nil { - return *m.MarkChanges - } - return Default_PutRequest_MarkChanges -} - -func (m *PutRequest) GetSnapshot() []*Snapshot { - if m != nil { - return m.Snapshot - } - return nil -} - -func (m *PutRequest) GetAutoIdPolicy() PutRequest_AutoIdPolicy { - if m != nil && m.AutoIdPolicy != nil { - return *m.AutoIdPolicy - } - return Default_PutRequest_AutoIdPolicy -} - -type PutResponse struct { - Key []*Reference `protobuf:"bytes,1,rep,name=key" json:"key,omitempty"` - Cost *Cost `protobuf:"bytes,2,opt,name=cost" json:"cost,omitempty"` - Version []int64 `protobuf:"varint,3,rep,name=version" json:"version,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *PutResponse) Reset() { *m = PutResponse{} } -func (m *PutResponse) String() string { return proto.CompactTextString(m) } -func (*PutResponse) ProtoMessage() {} -func (*PutResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_datastore_v3_83b17b80c34f6179, []int{24} -} -func (m *PutResponse) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_PutResponse.Unmarshal(m, b) -} -func (m *PutResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_PutResponse.Marshal(b, m, deterministic) -} -func (dst *PutResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_PutResponse.Merge(dst, src) -} -func (m *PutResponse) XXX_Size() int { - return xxx_messageInfo_PutResponse.Size(m) -} -func (m *PutResponse) XXX_DiscardUnknown() { - xxx_messageInfo_PutResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_PutResponse proto.InternalMessageInfo - -func (m *PutResponse) GetKey() []*Reference { - if m != nil { - return m.Key - } - return nil -} - -func (m *PutResponse) GetCost() *Cost { - if m != nil { - return m.Cost - } - return nil -} - -func (m *PutResponse) GetVersion() []int64 { - if m != nil { - return m.Version - } - return nil -} - -type TouchRequest struct { - Header *InternalHeader `protobuf:"bytes,10,opt,name=header" json:"header,omitempty"` - Key []*Reference `protobuf:"bytes,1,rep,name=key" json:"key,omitempty"` - CompositeIndex []*CompositeIndex `protobuf:"bytes,2,rep,name=composite_index,json=compositeIndex" json:"composite_index,omitempty"` - Force *bool `protobuf:"varint,3,opt,name=force,def=0" json:"force,omitempty"` - Snapshot []*Snapshot `protobuf:"bytes,9,rep,name=snapshot" json:"snapshot,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *TouchRequest) Reset() { *m = TouchRequest{} } -func (m *TouchRequest) String() string { return proto.CompactTextString(m) } -func (*TouchRequest) ProtoMessage() {} -func (*TouchRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_datastore_v3_83b17b80c34f6179, []int{25} -} -func (m *TouchRequest) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_TouchRequest.Unmarshal(m, b) -} -func (m *TouchRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_TouchRequest.Marshal(b, m, deterministic) -} -func (dst *TouchRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_TouchRequest.Merge(dst, src) -} -func (m *TouchRequest) XXX_Size() int { - return xxx_messageInfo_TouchRequest.Size(m) -} -func (m *TouchRequest) XXX_DiscardUnknown() { - xxx_messageInfo_TouchRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_TouchRequest proto.InternalMessageInfo - -const Default_TouchRequest_Force bool = false - -func (m *TouchRequest) GetHeader() *InternalHeader { - if m != nil { - return m.Header - } - return nil -} - -func (m *TouchRequest) GetKey() []*Reference { - if m != nil { - return m.Key - } - return nil -} - -func (m *TouchRequest) GetCompositeIndex() []*CompositeIndex { - if m != nil { - return m.CompositeIndex - } - return nil -} - -func (m *TouchRequest) GetForce() bool { - if m != nil && m.Force != nil { - return *m.Force - } - return Default_TouchRequest_Force -} - -func (m *TouchRequest) GetSnapshot() []*Snapshot { - if m != nil { - return m.Snapshot - } - return nil -} - -type TouchResponse struct { - Cost *Cost `protobuf:"bytes,1,opt,name=cost" json:"cost,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *TouchResponse) Reset() { *m = TouchResponse{} } -func (m *TouchResponse) String() string { return proto.CompactTextString(m) } -func (*TouchResponse) ProtoMessage() {} -func (*TouchResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_datastore_v3_83b17b80c34f6179, []int{26} -} -func (m *TouchResponse) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_TouchResponse.Unmarshal(m, b) -} -func (m *TouchResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_TouchResponse.Marshal(b, m, deterministic) -} -func (dst *TouchResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_TouchResponse.Merge(dst, src) -} -func (m *TouchResponse) XXX_Size() int { - return xxx_messageInfo_TouchResponse.Size(m) -} -func (m *TouchResponse) XXX_DiscardUnknown() { - xxx_messageInfo_TouchResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_TouchResponse proto.InternalMessageInfo - -func (m *TouchResponse) GetCost() *Cost { - if m != nil { - return m.Cost - } - return nil -} - -type DeleteRequest struct { - Header *InternalHeader `protobuf:"bytes,10,opt,name=header" json:"header,omitempty"` - Key []*Reference `protobuf:"bytes,6,rep,name=key" json:"key,omitempty"` - Transaction *Transaction `protobuf:"bytes,5,opt,name=transaction" json:"transaction,omitempty"` - Trusted *bool `protobuf:"varint,4,opt,name=trusted,def=0" json:"trusted,omitempty"` - Force *bool `protobuf:"varint,7,opt,name=force,def=0" json:"force,omitempty"` - MarkChanges *bool `protobuf:"varint,8,opt,name=mark_changes,json=markChanges,def=0" json:"mark_changes,omitempty"` - Snapshot []*Snapshot `protobuf:"bytes,9,rep,name=snapshot" json:"snapshot,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *DeleteRequest) Reset() { *m = DeleteRequest{} } -func (m *DeleteRequest) String() string { return proto.CompactTextString(m) } -func (*DeleteRequest) ProtoMessage() {} -func (*DeleteRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_datastore_v3_83b17b80c34f6179, []int{27} -} -func (m *DeleteRequest) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_DeleteRequest.Unmarshal(m, b) -} -func (m *DeleteRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_DeleteRequest.Marshal(b, m, deterministic) -} -func (dst *DeleteRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_DeleteRequest.Merge(dst, src) -} -func (m *DeleteRequest) XXX_Size() int { - return xxx_messageInfo_DeleteRequest.Size(m) -} -func (m *DeleteRequest) XXX_DiscardUnknown() { - xxx_messageInfo_DeleteRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_DeleteRequest proto.InternalMessageInfo - -const Default_DeleteRequest_Trusted bool = false -const Default_DeleteRequest_Force bool = false -const Default_DeleteRequest_MarkChanges bool = false - -func (m *DeleteRequest) GetHeader() *InternalHeader { - if m != nil { - return m.Header - } - return nil -} - -func (m *DeleteRequest) GetKey() []*Reference { - if m != nil { - return m.Key - } - return nil -} - -func (m *DeleteRequest) GetTransaction() *Transaction { - if m != nil { - return m.Transaction - } - return nil -} - -func (m *DeleteRequest) GetTrusted() bool { - if m != nil && m.Trusted != nil { - return *m.Trusted - } - return Default_DeleteRequest_Trusted -} - -func (m *DeleteRequest) GetForce() bool { - if m != nil && m.Force != nil { - return *m.Force - } - return Default_DeleteRequest_Force -} - -func (m *DeleteRequest) GetMarkChanges() bool { - if m != nil && m.MarkChanges != nil { - return *m.MarkChanges - } - return Default_DeleteRequest_MarkChanges -} - -func (m *DeleteRequest) GetSnapshot() []*Snapshot { - if m != nil { - return m.Snapshot - } - return nil -} - -type DeleteResponse struct { - Cost *Cost `protobuf:"bytes,1,opt,name=cost" json:"cost,omitempty"` - Version []int64 `protobuf:"varint,3,rep,name=version" json:"version,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *DeleteResponse) Reset() { *m = DeleteResponse{} } -func (m *DeleteResponse) String() string { return proto.CompactTextString(m) } -func (*DeleteResponse) ProtoMessage() {} -func (*DeleteResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_datastore_v3_83b17b80c34f6179, []int{28} -} -func (m *DeleteResponse) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_DeleteResponse.Unmarshal(m, b) -} -func (m *DeleteResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_DeleteResponse.Marshal(b, m, deterministic) -} -func (dst *DeleteResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_DeleteResponse.Merge(dst, src) -} -func (m *DeleteResponse) XXX_Size() int { - return xxx_messageInfo_DeleteResponse.Size(m) -} -func (m *DeleteResponse) XXX_DiscardUnknown() { - xxx_messageInfo_DeleteResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_DeleteResponse proto.InternalMessageInfo - -func (m *DeleteResponse) GetCost() *Cost { - if m != nil { - return m.Cost - } - return nil -} - -func (m *DeleteResponse) GetVersion() []int64 { - if m != nil { - return m.Version - } - return nil -} - -type NextRequest struct { - Header *InternalHeader `protobuf:"bytes,5,opt,name=header" json:"header,omitempty"` - Cursor *Cursor `protobuf:"bytes,1,req,name=cursor" json:"cursor,omitempty"` - Count *int32 `protobuf:"varint,2,opt,name=count" json:"count,omitempty"` - Offset *int32 `protobuf:"varint,4,opt,name=offset,def=0" json:"offset,omitempty"` - Compile *bool `protobuf:"varint,3,opt,name=compile,def=0" json:"compile,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *NextRequest) Reset() { *m = NextRequest{} } -func (m *NextRequest) String() string { return proto.CompactTextString(m) } -func (*NextRequest) ProtoMessage() {} -func (*NextRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_datastore_v3_83b17b80c34f6179, []int{29} -} -func (m *NextRequest) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_NextRequest.Unmarshal(m, b) -} -func (m *NextRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_NextRequest.Marshal(b, m, deterministic) -} -func (dst *NextRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_NextRequest.Merge(dst, src) -} -func (m *NextRequest) XXX_Size() int { - return xxx_messageInfo_NextRequest.Size(m) -} -func (m *NextRequest) XXX_DiscardUnknown() { - xxx_messageInfo_NextRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_NextRequest proto.InternalMessageInfo - -const Default_NextRequest_Offset int32 = 0 -const Default_NextRequest_Compile bool = false - -func (m *NextRequest) GetHeader() *InternalHeader { - if m != nil { - return m.Header - } - return nil -} - -func (m *NextRequest) GetCursor() *Cursor { - if m != nil { - return m.Cursor - } - return nil -} - -func (m *NextRequest) GetCount() int32 { - if m != nil && m.Count != nil { - return *m.Count - } - return 0 -} - -func (m *NextRequest) GetOffset() int32 { - if m != nil && m.Offset != nil { - return *m.Offset - } - return Default_NextRequest_Offset -} - -func (m *NextRequest) GetCompile() bool { - if m != nil && m.Compile != nil { - return *m.Compile - } - return Default_NextRequest_Compile -} - -type QueryResult struct { - Cursor *Cursor `protobuf:"bytes,1,opt,name=cursor" json:"cursor,omitempty"` - Result []*EntityProto `protobuf:"bytes,2,rep,name=result" json:"result,omitempty"` - SkippedResults *int32 `protobuf:"varint,7,opt,name=skipped_results,json=skippedResults" json:"skipped_results,omitempty"` - MoreResults *bool `protobuf:"varint,3,req,name=more_results,json=moreResults" json:"more_results,omitempty"` - KeysOnly *bool `protobuf:"varint,4,opt,name=keys_only,json=keysOnly" json:"keys_only,omitempty"` - IndexOnly *bool `protobuf:"varint,9,opt,name=index_only,json=indexOnly" json:"index_only,omitempty"` - SmallOps *bool `protobuf:"varint,10,opt,name=small_ops,json=smallOps" json:"small_ops,omitempty"` - CompiledQuery *CompiledQuery `protobuf:"bytes,5,opt,name=compiled_query,json=compiledQuery" json:"compiled_query,omitempty"` - CompiledCursor *CompiledCursor `protobuf:"bytes,6,opt,name=compiled_cursor,json=compiledCursor" json:"compiled_cursor,omitempty"` - Index []*CompositeIndex `protobuf:"bytes,8,rep,name=index" json:"index,omitempty"` - Version []int64 `protobuf:"varint,11,rep,name=version" json:"version,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *QueryResult) Reset() { *m = QueryResult{} } -func (m *QueryResult) String() string { return proto.CompactTextString(m) } -func (*QueryResult) ProtoMessage() {} -func (*QueryResult) Descriptor() ([]byte, []int) { - return fileDescriptor_datastore_v3_83b17b80c34f6179, []int{30} -} -func (m *QueryResult) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_QueryResult.Unmarshal(m, b) -} -func (m *QueryResult) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_QueryResult.Marshal(b, m, deterministic) -} -func (dst *QueryResult) XXX_Merge(src proto.Message) { - xxx_messageInfo_QueryResult.Merge(dst, src) -} -func (m *QueryResult) XXX_Size() int { - return xxx_messageInfo_QueryResult.Size(m) -} -func (m *QueryResult) XXX_DiscardUnknown() { - xxx_messageInfo_QueryResult.DiscardUnknown(m) -} - -var xxx_messageInfo_QueryResult proto.InternalMessageInfo - -func (m *QueryResult) GetCursor() *Cursor { - if m != nil { - return m.Cursor - } - return nil -} - -func (m *QueryResult) GetResult() []*EntityProto { - if m != nil { - return m.Result - } - return nil -} - -func (m *QueryResult) GetSkippedResults() int32 { - if m != nil && m.SkippedResults != nil { - return *m.SkippedResults - } - return 0 -} - -func (m *QueryResult) GetMoreResults() bool { - if m != nil && m.MoreResults != nil { - return *m.MoreResults - } - return false -} - -func (m *QueryResult) GetKeysOnly() bool { - if m != nil && m.KeysOnly != nil { - return *m.KeysOnly - } - return false -} - -func (m *QueryResult) GetIndexOnly() bool { - if m != nil && m.IndexOnly != nil { - return *m.IndexOnly - } - return false -} - -func (m *QueryResult) GetSmallOps() bool { - if m != nil && m.SmallOps != nil { - return *m.SmallOps - } - return false -} - -func (m *QueryResult) GetCompiledQuery() *CompiledQuery { - if m != nil { - return m.CompiledQuery - } - return nil -} - -func (m *QueryResult) GetCompiledCursor() *CompiledCursor { - if m != nil { - return m.CompiledCursor - } - return nil -} - -func (m *QueryResult) GetIndex() []*CompositeIndex { - if m != nil { - return m.Index - } - return nil -} - -func (m *QueryResult) GetVersion() []int64 { - if m != nil { - return m.Version - } - return nil -} - -type AllocateIdsRequest struct { - Header *InternalHeader `protobuf:"bytes,4,opt,name=header" json:"header,omitempty"` - ModelKey *Reference `protobuf:"bytes,1,opt,name=model_key,json=modelKey" json:"model_key,omitempty"` - Size *int64 `protobuf:"varint,2,opt,name=size" json:"size,omitempty"` - Max *int64 `protobuf:"varint,3,opt,name=max" json:"max,omitempty"` - Reserve []*Reference `protobuf:"bytes,5,rep,name=reserve" json:"reserve,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *AllocateIdsRequest) Reset() { *m = AllocateIdsRequest{} } -func (m *AllocateIdsRequest) String() string { return proto.CompactTextString(m) } -func (*AllocateIdsRequest) ProtoMessage() {} -func (*AllocateIdsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_datastore_v3_83b17b80c34f6179, []int{31} -} -func (m *AllocateIdsRequest) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_AllocateIdsRequest.Unmarshal(m, b) -} -func (m *AllocateIdsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_AllocateIdsRequest.Marshal(b, m, deterministic) -} -func (dst *AllocateIdsRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_AllocateIdsRequest.Merge(dst, src) -} -func (m *AllocateIdsRequest) XXX_Size() int { - return xxx_messageInfo_AllocateIdsRequest.Size(m) -} -func (m *AllocateIdsRequest) XXX_DiscardUnknown() { - xxx_messageInfo_AllocateIdsRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_AllocateIdsRequest proto.InternalMessageInfo - -func (m *AllocateIdsRequest) GetHeader() *InternalHeader { - if m != nil { - return m.Header - } - return nil -} - -func (m *AllocateIdsRequest) GetModelKey() *Reference { - if m != nil { - return m.ModelKey - } - return nil -} - -func (m *AllocateIdsRequest) GetSize() int64 { - if m != nil && m.Size != nil { - return *m.Size - } - return 0 -} - -func (m *AllocateIdsRequest) GetMax() int64 { - if m != nil && m.Max != nil { - return *m.Max - } - return 0 -} - -func (m *AllocateIdsRequest) GetReserve() []*Reference { - if m != nil { - return m.Reserve - } - return nil -} - -type AllocateIdsResponse struct { - Start *int64 `protobuf:"varint,1,req,name=start" json:"start,omitempty"` - End *int64 `protobuf:"varint,2,req,name=end" json:"end,omitempty"` - Cost *Cost `protobuf:"bytes,3,opt,name=cost" json:"cost,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *AllocateIdsResponse) Reset() { *m = AllocateIdsResponse{} } -func (m *AllocateIdsResponse) String() string { return proto.CompactTextString(m) } -func (*AllocateIdsResponse) ProtoMessage() {} -func (*AllocateIdsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_datastore_v3_83b17b80c34f6179, []int{32} -} -func (m *AllocateIdsResponse) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_AllocateIdsResponse.Unmarshal(m, b) -} -func (m *AllocateIdsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_AllocateIdsResponse.Marshal(b, m, deterministic) -} -func (dst *AllocateIdsResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_AllocateIdsResponse.Merge(dst, src) -} -func (m *AllocateIdsResponse) XXX_Size() int { - return xxx_messageInfo_AllocateIdsResponse.Size(m) -} -func (m *AllocateIdsResponse) XXX_DiscardUnknown() { - xxx_messageInfo_AllocateIdsResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_AllocateIdsResponse proto.InternalMessageInfo - -func (m *AllocateIdsResponse) GetStart() int64 { - if m != nil && m.Start != nil { - return *m.Start - } - return 0 -} - -func (m *AllocateIdsResponse) GetEnd() int64 { - if m != nil && m.End != nil { - return *m.End - } - return 0 -} - -func (m *AllocateIdsResponse) GetCost() *Cost { - if m != nil { - return m.Cost - } - return nil -} - -type CompositeIndices struct { - Index []*CompositeIndex `protobuf:"bytes,1,rep,name=index" json:"index,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *CompositeIndices) Reset() { *m = CompositeIndices{} } -func (m *CompositeIndices) String() string { return proto.CompactTextString(m) } -func (*CompositeIndices) ProtoMessage() {} -func (*CompositeIndices) Descriptor() ([]byte, []int) { - return fileDescriptor_datastore_v3_83b17b80c34f6179, []int{33} -} -func (m *CompositeIndices) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_CompositeIndices.Unmarshal(m, b) -} -func (m *CompositeIndices) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_CompositeIndices.Marshal(b, m, deterministic) -} -func (dst *CompositeIndices) XXX_Merge(src proto.Message) { - xxx_messageInfo_CompositeIndices.Merge(dst, src) -} -func (m *CompositeIndices) XXX_Size() int { - return xxx_messageInfo_CompositeIndices.Size(m) -} -func (m *CompositeIndices) XXX_DiscardUnknown() { - xxx_messageInfo_CompositeIndices.DiscardUnknown(m) -} - -var xxx_messageInfo_CompositeIndices proto.InternalMessageInfo - -func (m *CompositeIndices) GetIndex() []*CompositeIndex { - if m != nil { - return m.Index - } - return nil -} - -type AddActionsRequest struct { - Header *InternalHeader `protobuf:"bytes,3,opt,name=header" json:"header,omitempty"` - Transaction *Transaction `protobuf:"bytes,1,req,name=transaction" json:"transaction,omitempty"` - Action []*Action `protobuf:"bytes,2,rep,name=action" json:"action,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *AddActionsRequest) Reset() { *m = AddActionsRequest{} } -func (m *AddActionsRequest) String() string { return proto.CompactTextString(m) } -func (*AddActionsRequest) ProtoMessage() {} -func (*AddActionsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_datastore_v3_83b17b80c34f6179, []int{34} -} -func (m *AddActionsRequest) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_AddActionsRequest.Unmarshal(m, b) -} -func (m *AddActionsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_AddActionsRequest.Marshal(b, m, deterministic) -} -func (dst *AddActionsRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_AddActionsRequest.Merge(dst, src) -} -func (m *AddActionsRequest) XXX_Size() int { - return xxx_messageInfo_AddActionsRequest.Size(m) -} -func (m *AddActionsRequest) XXX_DiscardUnknown() { - xxx_messageInfo_AddActionsRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_AddActionsRequest proto.InternalMessageInfo - -func (m *AddActionsRequest) GetHeader() *InternalHeader { - if m != nil { - return m.Header - } - return nil -} - -func (m *AddActionsRequest) GetTransaction() *Transaction { - if m != nil { - return m.Transaction - } - return nil -} - -func (m *AddActionsRequest) GetAction() []*Action { - if m != nil { - return m.Action - } - return nil -} - -type AddActionsResponse struct { - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *AddActionsResponse) Reset() { *m = AddActionsResponse{} } -func (m *AddActionsResponse) String() string { return proto.CompactTextString(m) } -func (*AddActionsResponse) ProtoMessage() {} -func (*AddActionsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_datastore_v3_83b17b80c34f6179, []int{35} -} -func (m *AddActionsResponse) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_AddActionsResponse.Unmarshal(m, b) -} -func (m *AddActionsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_AddActionsResponse.Marshal(b, m, deterministic) -} -func (dst *AddActionsResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_AddActionsResponse.Merge(dst, src) -} -func (m *AddActionsResponse) XXX_Size() int { - return xxx_messageInfo_AddActionsResponse.Size(m) -} -func (m *AddActionsResponse) XXX_DiscardUnknown() { - xxx_messageInfo_AddActionsResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_AddActionsResponse proto.InternalMessageInfo - -type BeginTransactionRequest struct { - Header *InternalHeader `protobuf:"bytes,3,opt,name=header" json:"header,omitempty"` - App *string `protobuf:"bytes,1,req,name=app" json:"app,omitempty"` - AllowMultipleEg *bool `protobuf:"varint,2,opt,name=allow_multiple_eg,json=allowMultipleEg,def=0" json:"allow_multiple_eg,omitempty"` - DatabaseId *string `protobuf:"bytes,4,opt,name=database_id,json=databaseId" json:"database_id,omitempty"` - Mode *BeginTransactionRequest_TransactionMode `protobuf:"varint,5,opt,name=mode,enum=appengine.BeginTransactionRequest_TransactionMode,def=0" json:"mode,omitempty"` - PreviousTransaction *Transaction `protobuf:"bytes,7,opt,name=previous_transaction,json=previousTransaction" json:"previous_transaction,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *BeginTransactionRequest) Reset() { *m = BeginTransactionRequest{} } -func (m *BeginTransactionRequest) String() string { return proto.CompactTextString(m) } -func (*BeginTransactionRequest) ProtoMessage() {} -func (*BeginTransactionRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_datastore_v3_83b17b80c34f6179, []int{36} -} -func (m *BeginTransactionRequest) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_BeginTransactionRequest.Unmarshal(m, b) -} -func (m *BeginTransactionRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_BeginTransactionRequest.Marshal(b, m, deterministic) -} -func (dst *BeginTransactionRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_BeginTransactionRequest.Merge(dst, src) -} -func (m *BeginTransactionRequest) XXX_Size() int { - return xxx_messageInfo_BeginTransactionRequest.Size(m) -} -func (m *BeginTransactionRequest) XXX_DiscardUnknown() { - xxx_messageInfo_BeginTransactionRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_BeginTransactionRequest proto.InternalMessageInfo - -const Default_BeginTransactionRequest_AllowMultipleEg bool = false -const Default_BeginTransactionRequest_Mode BeginTransactionRequest_TransactionMode = BeginTransactionRequest_UNKNOWN - -func (m *BeginTransactionRequest) GetHeader() *InternalHeader { - if m != nil { - return m.Header - } - return nil -} - -func (m *BeginTransactionRequest) GetApp() string { - if m != nil && m.App != nil { - return *m.App - } - return "" -} - -func (m *BeginTransactionRequest) GetAllowMultipleEg() bool { - if m != nil && m.AllowMultipleEg != nil { - return *m.AllowMultipleEg - } - return Default_BeginTransactionRequest_AllowMultipleEg -} - -func (m *BeginTransactionRequest) GetDatabaseId() string { - if m != nil && m.DatabaseId != nil { - return *m.DatabaseId - } - return "" -} - -func (m *BeginTransactionRequest) GetMode() BeginTransactionRequest_TransactionMode { - if m != nil && m.Mode != nil { - return *m.Mode - } - return Default_BeginTransactionRequest_Mode -} - -func (m *BeginTransactionRequest) GetPreviousTransaction() *Transaction { - if m != nil { - return m.PreviousTransaction - } - return nil -} - -type CommitResponse struct { - Cost *Cost `protobuf:"bytes,1,opt,name=cost" json:"cost,omitempty"` - Version []*CommitResponse_Version `protobuf:"group,3,rep,name=Version,json=version" json:"version,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *CommitResponse) Reset() { *m = CommitResponse{} } -func (m *CommitResponse) String() string { return proto.CompactTextString(m) } -func (*CommitResponse) ProtoMessage() {} -func (*CommitResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_datastore_v3_83b17b80c34f6179, []int{37} -} -func (m *CommitResponse) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_CommitResponse.Unmarshal(m, b) -} -func (m *CommitResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_CommitResponse.Marshal(b, m, deterministic) -} -func (dst *CommitResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_CommitResponse.Merge(dst, src) -} -func (m *CommitResponse) XXX_Size() int { - return xxx_messageInfo_CommitResponse.Size(m) -} -func (m *CommitResponse) XXX_DiscardUnknown() { - xxx_messageInfo_CommitResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_CommitResponse proto.InternalMessageInfo - -func (m *CommitResponse) GetCost() *Cost { - if m != nil { - return m.Cost - } - return nil -} - -func (m *CommitResponse) GetVersion() []*CommitResponse_Version { - if m != nil { - return m.Version - } - return nil -} - -type CommitResponse_Version struct { - RootEntityKey *Reference `protobuf:"bytes,4,req,name=root_entity_key,json=rootEntityKey" json:"root_entity_key,omitempty"` - Version *int64 `protobuf:"varint,5,req,name=version" json:"version,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *CommitResponse_Version) Reset() { *m = CommitResponse_Version{} } -func (m *CommitResponse_Version) String() string { return proto.CompactTextString(m) } -func (*CommitResponse_Version) ProtoMessage() {} -func (*CommitResponse_Version) Descriptor() ([]byte, []int) { - return fileDescriptor_datastore_v3_83b17b80c34f6179, []int{37, 0} -} -func (m *CommitResponse_Version) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_CommitResponse_Version.Unmarshal(m, b) -} -func (m *CommitResponse_Version) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_CommitResponse_Version.Marshal(b, m, deterministic) -} -func (dst *CommitResponse_Version) XXX_Merge(src proto.Message) { - xxx_messageInfo_CommitResponse_Version.Merge(dst, src) -} -func (m *CommitResponse_Version) XXX_Size() int { - return xxx_messageInfo_CommitResponse_Version.Size(m) -} -func (m *CommitResponse_Version) XXX_DiscardUnknown() { - xxx_messageInfo_CommitResponse_Version.DiscardUnknown(m) -} - -var xxx_messageInfo_CommitResponse_Version proto.InternalMessageInfo - -func (m *CommitResponse_Version) GetRootEntityKey() *Reference { - if m != nil { - return m.RootEntityKey - } - return nil -} - -func (m *CommitResponse_Version) GetVersion() int64 { - if m != nil && m.Version != nil { - return *m.Version - } - return 0 -} - -func init() { - proto.RegisterType((*Action)(nil), "appengine.Action") - proto.RegisterType((*PropertyValue)(nil), "appengine.PropertyValue") - proto.RegisterType((*PropertyValue_PointValue)(nil), "appengine.PropertyValue.PointValue") - proto.RegisterType((*PropertyValue_UserValue)(nil), "appengine.PropertyValue.UserValue") - proto.RegisterType((*PropertyValue_ReferenceValue)(nil), "appengine.PropertyValue.ReferenceValue") - proto.RegisterType((*PropertyValue_ReferenceValue_PathElement)(nil), "appengine.PropertyValue.ReferenceValue.PathElement") - proto.RegisterType((*Property)(nil), "appengine.Property") - proto.RegisterType((*Path)(nil), "appengine.Path") - proto.RegisterType((*Path_Element)(nil), "appengine.Path.Element") - proto.RegisterType((*Reference)(nil), "appengine.Reference") - proto.RegisterType((*User)(nil), "appengine.User") - proto.RegisterType((*EntityProto)(nil), "appengine.EntityProto") - proto.RegisterType((*CompositeProperty)(nil), "appengine.CompositeProperty") - proto.RegisterType((*Index)(nil), "appengine.Index") - proto.RegisterType((*Index_Property)(nil), "appengine.Index.Property") - proto.RegisterType((*CompositeIndex)(nil), "appengine.CompositeIndex") - proto.RegisterType((*IndexPostfix)(nil), "appengine.IndexPostfix") - proto.RegisterType((*IndexPostfix_IndexValue)(nil), "appengine.IndexPostfix.IndexValue") - proto.RegisterType((*IndexPosition)(nil), "appengine.IndexPosition") - proto.RegisterType((*Snapshot)(nil), "appengine.Snapshot") - proto.RegisterType((*InternalHeader)(nil), "appengine.InternalHeader") - proto.RegisterType((*Transaction)(nil), "appengine.Transaction") - proto.RegisterType((*Query)(nil), "appengine.Query") - proto.RegisterType((*Query_Filter)(nil), "appengine.Query.Filter") - proto.RegisterType((*Query_Order)(nil), "appengine.Query.Order") - proto.RegisterType((*CompiledQuery)(nil), "appengine.CompiledQuery") - proto.RegisterType((*CompiledQuery_PrimaryScan)(nil), "appengine.CompiledQuery.PrimaryScan") - proto.RegisterType((*CompiledQuery_MergeJoinScan)(nil), "appengine.CompiledQuery.MergeJoinScan") - proto.RegisterType((*CompiledQuery_EntityFilter)(nil), "appengine.CompiledQuery.EntityFilter") - proto.RegisterType((*CompiledCursor)(nil), "appengine.CompiledCursor") - proto.RegisterType((*CompiledCursor_Position)(nil), "appengine.CompiledCursor.Position") - proto.RegisterType((*CompiledCursor_Position_IndexValue)(nil), "appengine.CompiledCursor.Position.IndexValue") - proto.RegisterType((*Cursor)(nil), "appengine.Cursor") - proto.RegisterType((*Error)(nil), "appengine.Error") - proto.RegisterType((*Cost)(nil), "appengine.Cost") - proto.RegisterType((*Cost_CommitCost)(nil), "appengine.Cost.CommitCost") - proto.RegisterType((*GetRequest)(nil), "appengine.GetRequest") - proto.RegisterType((*GetResponse)(nil), "appengine.GetResponse") - proto.RegisterType((*GetResponse_Entity)(nil), "appengine.GetResponse.Entity") - proto.RegisterType((*PutRequest)(nil), "appengine.PutRequest") - proto.RegisterType((*PutResponse)(nil), "appengine.PutResponse") - proto.RegisterType((*TouchRequest)(nil), "appengine.TouchRequest") - proto.RegisterType((*TouchResponse)(nil), "appengine.TouchResponse") - proto.RegisterType((*DeleteRequest)(nil), "appengine.DeleteRequest") - proto.RegisterType((*DeleteResponse)(nil), "appengine.DeleteResponse") - proto.RegisterType((*NextRequest)(nil), "appengine.NextRequest") - proto.RegisterType((*QueryResult)(nil), "appengine.QueryResult") - proto.RegisterType((*AllocateIdsRequest)(nil), "appengine.AllocateIdsRequest") - proto.RegisterType((*AllocateIdsResponse)(nil), "appengine.AllocateIdsResponse") - proto.RegisterType((*CompositeIndices)(nil), "appengine.CompositeIndices") - proto.RegisterType((*AddActionsRequest)(nil), "appengine.AddActionsRequest") - proto.RegisterType((*AddActionsResponse)(nil), "appengine.AddActionsResponse") - proto.RegisterType((*BeginTransactionRequest)(nil), "appengine.BeginTransactionRequest") - proto.RegisterType((*CommitResponse)(nil), "appengine.CommitResponse") - proto.RegisterType((*CommitResponse_Version)(nil), "appengine.CommitResponse.Version") -} - -func init() { - proto.RegisterFile("google.golang.org/appengine/internal/datastore/datastore_v3.proto", fileDescriptor_datastore_v3_83b17b80c34f6179) -} - -var fileDescriptor_datastore_v3_83b17b80c34f6179 = []byte{ - // 4156 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x5a, 0xcd, 0x73, 0xe3, 0x46, - 0x76, 0x37, 0xc1, 0xef, 0x47, 0x89, 0x82, 0x5a, 0xf3, 0xc1, 0xa1, 0x3f, 0x46, 0xc6, 0xac, 0x6d, - 0xd9, 0x6b, 0x73, 0x6c, 0xf9, 0x23, 0x5b, 0x4a, 0x76, 0x1d, 0x4a, 0xc4, 0x68, 0x90, 0xa1, 0x48, - 0xb9, 0x09, 0xd9, 0x9e, 0x5c, 0x50, 0x18, 0xa2, 0x29, 0x21, 0x43, 0x02, 0x30, 0x00, 0x6a, 0x46, - 0x93, 0xe4, 0x90, 0x4b, 0x2a, 0x55, 0x5b, 0xa9, 0x1c, 0x92, 0x4a, 0x25, 0xf9, 0x07, 0x72, 0xc8, - 0x39, 0x95, 0xaa, 0x54, 0xf6, 0x98, 0x5b, 0x0e, 0x7b, 0xc9, 0x31, 0x95, 0x73, 0xf2, 0x27, 0x24, - 0x39, 0xa4, 0xfa, 0x75, 0x03, 0x02, 0x28, 0x4a, 0x23, 0x6d, 0xf6, 0x90, 0x13, 0xd1, 0xef, 0xfd, - 0xba, 0xf1, 0xfa, 0xf5, 0xfb, 0x6c, 0x10, 0xba, 0xc7, 0xbe, 0x7f, 0x3c, 0x65, 0x9d, 0x63, 0x7f, - 0x6a, 0x7b, 0xc7, 0x1d, 0x3f, 0x3c, 0x7e, 0x68, 0x07, 0x01, 0xf3, 0x8e, 0x5d, 0x8f, 0x3d, 0x74, - 0xbd, 0x98, 0x85, 0x9e, 0x3d, 0x7d, 0xe8, 0xd8, 0xb1, 0x1d, 0xc5, 0x7e, 0xc8, 0xce, 0x9f, 0xac, - 0xd3, 0xcf, 0x3b, 0x41, 0xe8, 0xc7, 0x3e, 0xa9, 0xa7, 0x13, 0xb4, 0x1a, 0x54, 0xba, 0xe3, 0xd8, - 0xf5, 0x3d, 0xed, 0x1f, 0x2b, 0xb0, 0x7a, 0x18, 0xfa, 0x01, 0x0b, 0xe3, 0xb3, 0x6f, 0xed, 0xe9, - 0x9c, 0x91, 0x77, 0x00, 0x5c, 0x2f, 0xfe, 0xea, 0x0b, 0x1c, 0xb5, 0x0a, 0x9b, 0x85, 0xad, 0x22, - 0xcd, 0x50, 0x88, 0x06, 0x2b, 0xcf, 0x7c, 0x7f, 0xca, 0x6c, 0x4f, 0x20, 0x94, 0xcd, 0xc2, 0x56, - 0x8d, 0xe6, 0x68, 0x64, 0x13, 0x1a, 0x51, 0x1c, 0xba, 0xde, 0xb1, 0x80, 0x14, 0x37, 0x0b, 0x5b, - 0x75, 0x9a, 0x25, 0x71, 0x84, 0xe3, 0xcf, 0x9f, 0x4d, 0x99, 0x40, 0x94, 0x36, 0x0b, 0x5b, 0x05, - 0x9a, 0x25, 0x91, 0x3d, 0x80, 0xc0, 0x77, 0xbd, 0xf8, 0x14, 0x01, 0xe5, 0xcd, 0xc2, 0x16, 0x6c, - 0x3f, 0xe8, 0xa4, 0x7b, 0xe8, 0xe4, 0xa4, 0xee, 0x1c, 0x72, 0x28, 0x3e, 0xd2, 0xcc, 0x34, 0xf2, - 0xdb, 0x50, 0x9f, 0x47, 0x2c, 0x14, 0x6b, 0xd4, 0x70, 0x0d, 0xed, 0xd2, 0x35, 0x8e, 0x22, 0x16, - 0x8a, 0x25, 0xce, 0x27, 0x91, 0x21, 0x34, 0x43, 0x36, 0x61, 0x21, 0xf3, 0xc6, 0x4c, 0x2c, 0xb3, - 0x82, 0xcb, 0x7c, 0x70, 0xe9, 0x32, 0x34, 0x81, 0x8b, 0xb5, 0x16, 0xa6, 0xb7, 0xb7, 0x00, 0xce, - 0x85, 0x25, 0x2b, 0x50, 0x78, 0xd9, 0xaa, 0x6c, 0x2a, 0x5b, 0x05, 0x5a, 0x78, 0xc9, 0x47, 0x67, - 0xad, 0xaa, 0x18, 0x9d, 0xb5, 0xff, 0xa9, 0x00, 0xf5, 0x54, 0x26, 0x72, 0x0b, 0xca, 0x6c, 0x66, - 0xbb, 0xd3, 0x56, 0x7d, 0x53, 0xd9, 0xaa, 0x53, 0x31, 0x20, 0xf7, 0xa1, 0x61, 0xcf, 0xe3, 0x13, - 0xcb, 0xf1, 0x67, 0xb6, 0xeb, 0xb5, 0x00, 0x79, 0xc0, 0x49, 0x3d, 0xa4, 0x90, 0x36, 0xd4, 0x3c, - 0x77, 0xfc, 0xdc, 0xb3, 0x67, 0xac, 0xd5, 0xc0, 0x73, 0x48, 0xc7, 0xe4, 0x13, 0x20, 0x13, 0xe6, - 0xb0, 0xd0, 0x8e, 0x99, 0x63, 0xb9, 0x0e, 0xf3, 0x62, 0x37, 0x3e, 0x6b, 0xdd, 0x46, 0xd4, 0x7a, - 0xca, 0x31, 0x24, 0x23, 0x0f, 0x0f, 0x42, 0xff, 0xd4, 0x75, 0x58, 0xd8, 0xba, 0xb3, 0x00, 0x3f, - 0x94, 0x8c, 0xf6, 0xbf, 0x17, 0xa0, 0x99, 0xd7, 0x05, 0x51, 0xa1, 0x68, 0x07, 0x41, 0x6b, 0x15, - 0xa5, 0xe4, 0x8f, 0xe4, 0x6d, 0x00, 0x2e, 0x8a, 0x15, 0x05, 0xf6, 0x98, 0xb5, 0x6e, 0xe1, 0x5a, - 0x75, 0x4e, 0x19, 0x71, 0x02, 0x39, 0x82, 0x46, 0x60, 0xc7, 0x27, 0x6c, 0xca, 0x66, 0xcc, 0x8b, - 0x5b, 0xcd, 0xcd, 0xe2, 0x16, 0x6c, 0x7f, 0x7e, 0x4d, 0xd5, 0x77, 0x0e, 0xed, 0xf8, 0x44, 0x17, - 0x53, 0x69, 0x76, 0x9d, 0xb6, 0x0e, 0x8d, 0x0c, 0x8f, 0x10, 0x28, 0xc5, 0x67, 0x01, 0x6b, 0xad, - 0xa1, 0x5c, 0xf8, 0x4c, 0x9a, 0xa0, 0xb8, 0x4e, 0x4b, 0x45, 0xf3, 0x57, 0x5c, 0x87, 0x63, 0x50, - 0x87, 0xeb, 0x28, 0x22, 0x3e, 0x6b, 0xff, 0x51, 0x86, 0x5a, 0x22, 0x00, 0xe9, 0x42, 0x75, 0xc6, - 0x6c, 0xcf, 0xf5, 0x8e, 0xd1, 0x69, 0x9a, 0xdb, 0x6f, 0x2e, 0x11, 0xb3, 0x73, 0x20, 0x20, 0x3b, - 0x30, 0x18, 0x5a, 0x07, 0x7a, 0x77, 0x60, 0x0c, 0xf6, 0x69, 0x32, 0x8f, 0x1f, 0xa6, 0x7c, 0xb4, - 0xe6, 0xa1, 0x8b, 0x9e, 0x55, 0xa7, 0x20, 0x49, 0x47, 0xa1, 0x9b, 0x0a, 0x51, 0x14, 0x82, 0xe2, - 0x21, 0x76, 0xa0, 0x9c, 0xb8, 0x88, 0xb2, 0xd5, 0xd8, 0x6e, 0x5d, 0xa6, 0x1c, 0x2a, 0x60, 0xdc, - 0x20, 0x66, 0xf3, 0x69, 0xec, 0x06, 0x53, 0xee, 0x76, 0xca, 0x56, 0x8d, 0xa6, 0x63, 0xf2, 0x1e, - 0x40, 0xc4, 0xec, 0x70, 0x7c, 0x62, 0x3f, 0x9b, 0xb2, 0x56, 0x85, 0x7b, 0xf6, 0x4e, 0x79, 0x62, - 0x4f, 0x23, 0x46, 0x33, 0x0c, 0x62, 0xc3, 0xdd, 0x49, 0x1c, 0x59, 0xb1, 0xff, 0x9c, 0x79, 0xee, - 0x2b, 0x9b, 0x07, 0x12, 0xcb, 0x0f, 0xf8, 0x0f, 0xfa, 0x58, 0x73, 0xfb, 0xc3, 0x65, 0x5b, 0x7f, - 0x14, 0x47, 0x66, 0x66, 0xc6, 0x10, 0x27, 0xd0, 0xdb, 0x93, 0x65, 0x64, 0xd2, 0x86, 0xca, 0xd4, - 0x1f, 0xdb, 0x53, 0xd6, 0xaa, 0x73, 0x2d, 0xec, 0x28, 0xcc, 0xa3, 0x92, 0xa2, 0xfd, 0xb3, 0x02, - 0x55, 0xa9, 0x47, 0xd2, 0x84, 0x8c, 0x26, 0xd5, 0x37, 0x48, 0x0d, 0x4a, 0xbb, 0xfd, 0xe1, 0xae, - 0xda, 0xe4, 0x4f, 0xa6, 0xfe, 0xbd, 0xa9, 0xae, 0x71, 0xcc, 0xee, 0x53, 0x53, 0x1f, 0x99, 0x94, - 0x63, 0x54, 0xb2, 0x0e, 0xab, 0x5d, 0x73, 0x78, 0x60, 0xed, 0x75, 0x4d, 0x7d, 0x7f, 0x48, 0x9f, - 0xaa, 0x05, 0xb2, 0x0a, 0x75, 0x24, 0xf5, 0x8d, 0xc1, 0x13, 0x55, 0xe1, 0x33, 0x70, 0x68, 0x1a, - 0x66, 0x5f, 0x57, 0x8b, 0x44, 0x85, 0x15, 0x31, 0x63, 0x38, 0x30, 0xf5, 0x81, 0xa9, 0x96, 0x52, - 0xca, 0xe8, 0xe8, 0xe0, 0xa0, 0x4b, 0x9f, 0xaa, 0x65, 0xb2, 0x06, 0x0d, 0xa4, 0x74, 0x8f, 0xcc, - 0xc7, 0x43, 0xaa, 0x56, 0x48, 0x03, 0xaa, 0xfb, 0x3d, 0xeb, 0xbb, 0xc7, 0xfa, 0x40, 0xad, 0x92, - 0x15, 0xa8, 0xed, 0xf7, 0x2c, 0xfd, 0xa0, 0x6b, 0xf4, 0xd5, 0x1a, 0x9f, 0xbd, 0xaf, 0x0f, 0xe9, - 0x68, 0x64, 0x1d, 0x0e, 0x8d, 0x81, 0xa9, 0xd6, 0x49, 0x1d, 0xca, 0xfb, 0x3d, 0xcb, 0x38, 0x50, - 0x81, 0x10, 0x68, 0xee, 0xf7, 0xac, 0xc3, 0xc7, 0xc3, 0x81, 0x3e, 0x38, 0x3a, 0xd8, 0xd5, 0xa9, - 0xda, 0x20, 0xb7, 0x40, 0xe5, 0xb4, 0xe1, 0xc8, 0xec, 0xf6, 0xbb, 0xbd, 0x1e, 0xd5, 0x47, 0x23, - 0x75, 0x85, 0x4b, 0xbd, 0xdf, 0xb3, 0x68, 0xd7, 0xe4, 0xfb, 0x5a, 0xe5, 0x2f, 0xe4, 0x7b, 0x7f, - 0xa2, 0x3f, 0x55, 0xd7, 0xf9, 0x2b, 0xf4, 0x81, 0x69, 0x98, 0x4f, 0xad, 0x43, 0x3a, 0x34, 0x87, - 0xea, 0x06, 0x17, 0xd0, 0x18, 0xf4, 0xf4, 0xef, 0xad, 0x6f, 0xbb, 0xfd, 0x23, 0x5d, 0x25, 0xda, - 0x8f, 0xe1, 0xf6, 0xd2, 0x33, 0xe1, 0xaa, 0x7b, 0x6c, 0x1e, 0xf4, 0xd5, 0x02, 0x7f, 0xe2, 0x9b, - 0x52, 0x15, 0xed, 0x0f, 0xa0, 0xc4, 0x5d, 0x86, 0x7c, 0x06, 0xd5, 0xc4, 0x1b, 0x0b, 0xe8, 0x8d, - 0x77, 0xb3, 0x67, 0x6d, 0xc7, 0x27, 0x9d, 0xc4, 0xe3, 0x12, 0x5c, 0xbb, 0x0b, 0xd5, 0x45, 0x4f, - 0x53, 0x2e, 0x78, 0x5a, 0xf1, 0x82, 0xa7, 0x95, 0x32, 0x9e, 0x66, 0x43, 0x3d, 0xf5, 0xed, 0x9b, - 0x47, 0x91, 0x07, 0x50, 0xe2, 0xde, 0xdf, 0x6a, 0xa2, 0x87, 0xac, 0x2d, 0x08, 0x4c, 0x91, 0xa9, - 0xfd, 0x43, 0x01, 0x4a, 0x3c, 0xda, 0x9e, 0x07, 0xda, 0xc2, 0x15, 0x81, 0x56, 0xb9, 0x32, 0xd0, - 0x16, 0xaf, 0x15, 0x68, 0x2b, 0x37, 0x0b, 0xb4, 0xd5, 0x4b, 0x02, 0xad, 0xf6, 0x67, 0x45, 0x68, - 0xe8, 0x38, 0xf3, 0x10, 0x13, 0xfd, 0xfb, 0x50, 0x7c, 0xce, 0xce, 0x50, 0x3f, 0x8d, 0xed, 0x5b, - 0x99, 0xdd, 0xa6, 0x2a, 0xa4, 0x1c, 0x40, 0xb6, 0x61, 0x45, 0xbc, 0xd0, 0x3a, 0x0e, 0xfd, 0x79, - 0xd0, 0x52, 0x97, 0xab, 0xa7, 0x21, 0x40, 0xfb, 0x1c, 0x43, 0xde, 0x83, 0xb2, 0xff, 0xc2, 0x63, - 0x21, 0xc6, 0xc1, 0x3c, 0x98, 0x2b, 0x8f, 0x0a, 0x2e, 0x79, 0x08, 0xa5, 0xe7, 0xae, 0xe7, 0xe0, - 0x19, 0xe6, 0x23, 0x61, 0x46, 0xd0, 0xce, 0x13, 0xd7, 0x73, 0x28, 0x02, 0xc9, 0x3d, 0xa8, 0xf1, - 0x5f, 0x8c, 0x7b, 0x65, 0xdc, 0x68, 0x95, 0x8f, 0x79, 0xd0, 0x7b, 0x08, 0xb5, 0x40, 0xc6, 0x10, - 0x4c, 0x00, 0x8d, 0xed, 0x8d, 0x25, 0xe1, 0x85, 0xa6, 0x20, 0xf2, 0x15, 0xac, 0x84, 0xf6, 0x0b, - 0x2b, 0x9d, 0xb4, 0x76, 0xf9, 0xa4, 0x46, 0x68, 0xbf, 0x48, 0x23, 0x38, 0x81, 0x52, 0x68, 0x7b, - 0xcf, 0x5b, 0x64, 0xb3, 0xb0, 0x55, 0xa6, 0xf8, 0xac, 0x7d, 0x01, 0x25, 0x2e, 0x25, 0x8f, 0x08, - 0xfb, 0x3d, 0xf4, 0xff, 0xee, 0x9e, 0xa9, 0x16, 0x12, 0x7f, 0xfe, 0x96, 0x47, 0x03, 0x45, 0x72, - 0x0f, 0xf4, 0xd1, 0xa8, 0xbb, 0xaf, 0xab, 0x45, 0xad, 0x07, 0xeb, 0x7b, 0xfe, 0x2c, 0xf0, 0x23, - 0x37, 0x66, 0xe9, 0xf2, 0xf7, 0xa0, 0xe6, 0x7a, 0x0e, 0x7b, 0x69, 0xb9, 0x0e, 0x9a, 0x56, 0x91, - 0x56, 0x71, 0x6c, 0x38, 0xdc, 0xe4, 0x4e, 0x65, 0x31, 0x55, 0xe4, 0x26, 0x87, 0x03, 0xed, 0x2f, - 0x15, 0x28, 0x1b, 0x1c, 0xc1, 0x8d, 0x4f, 0x9e, 0x14, 0x7a, 0x8f, 0x30, 0x4c, 0x10, 0x24, 0x93, - 0xfb, 0x50, 0x1b, 0x6a, 0xb6, 0x37, 0x66, 0xbc, 0xe2, 0xc3, 0x3c, 0x50, 0xa3, 0xe9, 0x98, 0x7c, - 0x99, 0xd1, 0x9f, 0x82, 0x2e, 0x7b, 0x2f, 0xa3, 0x0a, 0x7c, 0xc1, 0x12, 0x2d, 0xb6, 0xff, 0xaa, - 0x90, 0x49, 0x6e, 0xcb, 0x12, 0x4f, 0x1f, 0xea, 0x8e, 0x1b, 0x32, 0xac, 0x23, 0xe5, 0x41, 0x3f, - 0xb8, 0x74, 0xe1, 0x4e, 0x2f, 0x81, 0xee, 0xd4, 0xbb, 0xa3, 0x3d, 0x7d, 0xd0, 0xe3, 0x99, 0xef, - 0x7c, 0x01, 0xed, 0x23, 0xa8, 0xa7, 0x10, 0x0c, 0xc7, 0x09, 0x48, 0x2d, 0x70, 0xf5, 0xf6, 0xf4, - 0x74, 0xac, 0x68, 0x7f, 0xad, 0x40, 0x33, 0xd5, 0xaf, 0xd0, 0xd0, 0x6d, 0xa8, 0xd8, 0x41, 0x90, - 0xa8, 0xb6, 0x4e, 0xcb, 0x76, 0x10, 0x18, 0x8e, 0x8c, 0x2d, 0x0a, 0x6a, 0x9b, 0xc7, 0x96, 0x4f, - 0x01, 0x1c, 0x36, 0x71, 0x3d, 0x17, 0x85, 0x2e, 0xa2, 0xc1, 0xab, 0x8b, 0x42, 0xd3, 0x0c, 0x86, - 0x7c, 0x09, 0xe5, 0x28, 0xb6, 0x63, 0x91, 0x2b, 0x9b, 0xdb, 0xf7, 0x33, 0xe0, 0xbc, 0x08, 0x9d, - 0x11, 0x87, 0x51, 0x81, 0x26, 0x5f, 0xc1, 0x2d, 0xdf, 0x9b, 0x9e, 0x59, 0xf3, 0x88, 0x59, 0xee, - 0xc4, 0x0a, 0xd9, 0x0f, 0x73, 0x37, 0x64, 0x4e, 0x3e, 0xa7, 0xae, 0x73, 0xc8, 0x51, 0xc4, 0x8c, - 0x09, 0x95, 0x7c, 0xed, 0x6b, 0x28, 0xe3, 0x3a, 0x7c, 0xcf, 0xdf, 0x51, 0xc3, 0xd4, 0xad, 0xe1, - 0xa0, 0xff, 0x54, 0xe8, 0x80, 0xea, 0xdd, 0x9e, 0x85, 0x44, 0x55, 0xe1, 0xc1, 0xbe, 0xa7, 0xf7, - 0x75, 0x53, 0xef, 0xa9, 0x45, 0x9e, 0x3d, 0x74, 0x4a, 0x87, 0x54, 0x2d, 0x69, 0xff, 0x53, 0x80, - 0x15, 0x94, 0xe7, 0xd0, 0x8f, 0xe2, 0x89, 0xfb, 0x92, 0xec, 0x41, 0x43, 0x98, 0xdd, 0xa9, 0x2c, - 0xe8, 0xb9, 0x33, 0x68, 0x8b, 0x7b, 0x96, 0x68, 0x31, 0x90, 0x75, 0xb4, 0x9b, 0x3e, 0x27, 0x21, - 0x45, 0x41, 0xa7, 0xbf, 0x22, 0xa4, 0xbc, 0x05, 0x95, 0x67, 0x6c, 0xe2, 0x87, 0x22, 0x04, 0xd6, - 0x76, 0x4a, 0x71, 0x38, 0x67, 0x54, 0xd2, 0xda, 0x36, 0xc0, 0xf9, 0xfa, 0xe4, 0x01, 0xac, 0x26, - 0xc6, 0x66, 0xa1, 0x71, 0x89, 0x93, 0x5b, 0x49, 0x88, 0x83, 0x5c, 0x75, 0xa3, 0x5c, 0xab, 0xba, - 0xd1, 0xbe, 0x86, 0xd5, 0x64, 0x3f, 0xe2, 0xfc, 0x54, 0x21, 0x79, 0x01, 0x63, 0xca, 0x82, 0x8c, - 0xca, 0x45, 0x19, 0xb5, 0x9f, 0x41, 0x6d, 0xe4, 0xd9, 0x41, 0x74, 0xe2, 0xc7, 0xdc, 0x7a, 0xe2, - 0x48, 0xfa, 0xaa, 0x12, 0x47, 0x9a, 0x06, 0x15, 0x7e, 0x38, 0xf3, 0x88, 0xbb, 0xbf, 0x31, 0xe8, - 0xee, 0x99, 0xc6, 0xb7, 0xba, 0xfa, 0x06, 0x01, 0xa8, 0xc8, 0xe7, 0x82, 0xa6, 0x41, 0xd3, 0x90, - 0xed, 0xd8, 0x63, 0x66, 0x3b, 0x2c, 0xe4, 0x12, 0xfc, 0xe0, 0x47, 0x89, 0x04, 0x3f, 0xf8, 0x91, - 0xf6, 0x17, 0x05, 0x68, 0x98, 0xa1, 0xed, 0x45, 0xb6, 0x30, 0xf7, 0xcf, 0xa0, 0x72, 0x82, 0x58, - 0x74, 0xa3, 0xc6, 0x82, 0x7f, 0x66, 0x17, 0xa3, 0x12, 0x48, 0xee, 0x40, 0xe5, 0xc4, 0xf6, 0x9c, - 0xa9, 0xd0, 0x5a, 0x85, 0xca, 0x51, 0x92, 0x1b, 0x95, 0xf3, 0xdc, 0xb8, 0x05, 0x2b, 0x33, 0x3b, - 0x7c, 0x6e, 0x8d, 0x4f, 0x6c, 0xef, 0x98, 0x45, 0xf2, 0x60, 0xa4, 0x05, 0x36, 0x38, 0x6b, 0x4f, - 0x70, 0xb4, 0xbf, 0x5f, 0x81, 0xf2, 0x37, 0x73, 0x16, 0x9e, 0x65, 0x04, 0xfa, 0xe0, 0xba, 0x02, - 0xc9, 0x17, 0x17, 0x2e, 0x4b, 0xca, 0x6f, 0x2f, 0x26, 0x65, 0x22, 0x53, 0x84, 0xc8, 0x95, 0x22, - 0x0b, 0x7c, 0x9a, 0x09, 0x63, 0xeb, 0x57, 0xd8, 0xda, 0x79, 0x70, 0x7b, 0x08, 0x95, 0x89, 0x3b, - 0x8d, 0x51, 0x75, 0x8b, 0xd5, 0x08, 0xee, 0xa5, 0xf3, 0x08, 0xd9, 0x54, 0xc2, 0xc8, 0xbb, 0xb0, - 0x22, 0x2a, 0x59, 0xeb, 0x07, 0xce, 0xc6, 0x82, 0x95, 0xf7, 0xa6, 0x48, 0x13, 0xbb, 0xff, 0x18, - 0xca, 0x7e, 0xc8, 0x37, 0x5f, 0xc7, 0x25, 0xef, 0x5c, 0x58, 0x72, 0xc8, 0xb9, 0x54, 0x80, 0xc8, - 0x87, 0x50, 0x3a, 0x71, 0xbd, 0x18, 0xb3, 0x46, 0x73, 0xfb, 0xf6, 0x05, 0xf0, 0x63, 0xd7, 0x8b, - 0x29, 0x42, 0x78, 0x98, 0x1f, 0xfb, 0x73, 0x2f, 0x6e, 0xdd, 0xc5, 0x0c, 0x23, 0x06, 0xe4, 0x1e, - 0x54, 0xfc, 0xc9, 0x24, 0x62, 0x31, 0x76, 0x96, 0xe5, 0x9d, 0xc2, 0xa7, 0x54, 0x12, 0xf8, 0x84, - 0xa9, 0x3b, 0x73, 0x63, 0xec, 0x43, 0xca, 0x54, 0x0c, 0xc8, 0x2e, 0xac, 0x8d, 0xfd, 0x59, 0xe0, - 0x4e, 0x99, 0x63, 0x8d, 0xe7, 0x61, 0xe4, 0x87, 0xad, 0x77, 0x2e, 0x1c, 0xd3, 0x9e, 0x44, 0xec, - 0x21, 0x80, 0x36, 0xc7, 0xb9, 0x31, 0x31, 0x60, 0x83, 0x79, 0x8e, 0xb5, 0xb8, 0xce, 0xfd, 0xd7, - 0xad, 0xb3, 0xce, 0x3c, 0x27, 0x4f, 0x4a, 0xc4, 0xc1, 0x48, 0x68, 0x61, 0xcc, 0x68, 0x6d, 0x60, - 0x90, 0xb9, 0x77, 0x69, 0xac, 0x14, 0xe2, 0x64, 0xc2, 0xf7, 0x6f, 0xc0, 0x2d, 0x19, 0x22, 0xad, - 0x80, 0x85, 0x13, 0x36, 0x8e, 0xad, 0x60, 0x6a, 0x7b, 0x58, 0xca, 0xa5, 0xc6, 0x4a, 0x24, 0xe4, - 0x50, 0x20, 0x0e, 0xa7, 0xb6, 0x47, 0x34, 0xa8, 0x3f, 0x67, 0x67, 0x91, 0xc5, 0x23, 0x29, 0x76, - 0xae, 0x29, 0xba, 0xc6, 0xe9, 0x43, 0x6f, 0x7a, 0x46, 0x7e, 0x02, 0x8d, 0xf8, 0xdc, 0xdb, 0xb0, - 0x61, 0x6d, 0xe4, 0x4e, 0x35, 0xe3, 0x8b, 0x34, 0x0b, 0x25, 0xf7, 0xa1, 0x2a, 0x35, 0xd4, 0xba, - 0x97, 0x5d, 0x3b, 0xa1, 0xf2, 0xc4, 0x3c, 0xb1, 0xdd, 0xa9, 0x7f, 0xca, 0x42, 0x6b, 0x16, 0xb5, - 0xda, 0xe2, 0xb6, 0x24, 0x21, 0x1d, 0x44, 0xdc, 0x4f, 0xa3, 0x38, 0xf4, 0xbd, 0xe3, 0xd6, 0x26, - 0xde, 0x93, 0xc8, 0xd1, 0xc5, 0xe0, 0xf7, 0x2e, 0x66, 0xfe, 0x7c, 0xf0, 0xfb, 0x1c, 0xee, 0x60, - 0x65, 0x66, 0x3d, 0x3b, 0xb3, 0xf2, 0x68, 0x0d, 0xd1, 0x1b, 0xc8, 0xdd, 0x3d, 0x3b, 0xcc, 0x4e, - 0x6a, 0x43, 0xcd, 0x71, 0xa3, 0xd8, 0xf5, 0xc6, 0x71, 0xab, 0x85, 0xef, 0x4c, 0xc7, 0xe4, 0x33, - 0xb8, 0x3d, 0x73, 0x3d, 0x2b, 0xb2, 0x27, 0xcc, 0x8a, 0x5d, 0xee, 0x9b, 0x6c, 0xec, 0x7b, 0x4e, - 0xd4, 0x7a, 0x80, 0x82, 0x93, 0x99, 0xeb, 0x8d, 0xec, 0x09, 0x33, 0xdd, 0x19, 0x1b, 0x09, 0x0e, - 0xf9, 0x08, 0xd6, 0x11, 0x1e, 0xb2, 0x60, 0xea, 0x8e, 0x6d, 0xf1, 0xfa, 0x1f, 0xe1, 0xeb, 0xd7, - 0x38, 0x83, 0x0a, 0x3a, 0xbe, 0xfa, 0x63, 0x68, 0x06, 0x2c, 0x8c, 0xdc, 0x28, 0xb6, 0xa4, 0x45, - 0xbf, 0x97, 0xd5, 0xda, 0xaa, 0x64, 0x0e, 0x91, 0xd7, 0xfe, 0xcf, 0x02, 0x54, 0x84, 0x73, 0x92, - 0x4f, 0x41, 0xf1, 0x03, 0xbc, 0x06, 0x69, 0x6e, 0x6f, 0x5e, 0xe2, 0xc1, 0x9d, 0x61, 0xc0, 0xeb, - 0x5e, 0x3f, 0xa4, 0x8a, 0x1f, 0xdc, 0xb8, 0x28, 0xd4, 0xfe, 0x10, 0x6a, 0xc9, 0x02, 0xbc, 0xbc, - 0xe8, 0xeb, 0xa3, 0x91, 0x65, 0x3e, 0xee, 0x0e, 0xd4, 0x02, 0xb9, 0x03, 0x24, 0x1d, 0x5a, 0x43, - 0x6a, 0xe9, 0xdf, 0x1c, 0x75, 0xfb, 0xaa, 0x82, 0x5d, 0x1a, 0xd5, 0xbb, 0xa6, 0x4e, 0x05, 0xb2, - 0x48, 0xee, 0xc1, 0xed, 0x2c, 0xe5, 0x1c, 0x5c, 0xc2, 0x14, 0x8c, 0x8f, 0x65, 0x52, 0x01, 0xc5, - 0x18, 0xa8, 0x15, 0x9e, 0x16, 0xf4, 0xef, 0x8d, 0x91, 0x39, 0x52, 0xab, 0xed, 0xbf, 0x29, 0x40, - 0x19, 0xc3, 0x06, 0x3f, 0x9f, 0x54, 0x72, 0x71, 0x5d, 0x73, 0x5e, 0xb9, 0x1a, 0xd9, 0x92, 0xaa, - 0x81, 0x01, 0x65, 0x73, 0x79, 0xf4, 0xf9, 0xb5, 0xd6, 0x53, 0x3f, 0x85, 0x12, 0x8f, 0x52, 0xbc, - 0x43, 0x1c, 0xd2, 0x9e, 0x4e, 0xad, 0x47, 0x06, 0x1d, 0xf1, 0x2a, 0x97, 0x40, 0xb3, 0x3b, 0xd8, - 0xd3, 0x47, 0xe6, 0x30, 0xa1, 0xa1, 0x56, 0x1e, 0x19, 0x7d, 0x33, 0x45, 0x15, 0xb5, 0x9f, 0xd7, - 0x60, 0x35, 0x89, 0x09, 0x22, 0x82, 0x3e, 0x82, 0x46, 0x10, 0xba, 0x33, 0x3b, 0x3c, 0x8b, 0xc6, - 0xb6, 0x87, 0x49, 0x01, 0xb6, 0x7f, 0xb4, 0x24, 0xaa, 0x88, 0x1d, 0x1d, 0x0a, 0xec, 0x68, 0x6c, - 0x7b, 0x34, 0x3b, 0x91, 0xf4, 0x61, 0x75, 0xc6, 0xc2, 0x63, 0xf6, 0x7b, 0xbe, 0xeb, 0xe1, 0x4a, - 0x55, 0x8c, 0xc8, 0xef, 0x5f, 0xba, 0xd2, 0x01, 0x47, 0xff, 0x8e, 0xef, 0x7a, 0xb8, 0x56, 0x7e, - 0x32, 0xf9, 0x04, 0xea, 0xa2, 0x12, 0x72, 0xd8, 0x04, 0x63, 0xc5, 0xb2, 0xda, 0x4f, 0xd4, 0xe8, - 0x3d, 0x36, 0xc9, 0xc4, 0x65, 0xb8, 0x34, 0x2e, 0x37, 0xb2, 0x71, 0xf9, 0xcd, 0x6c, 0x2c, 0x5a, - 0x11, 0x55, 0x78, 0x1a, 0x84, 0x2e, 0x38, 0x7c, 0x6b, 0x89, 0xc3, 0x77, 0x60, 0x23, 0xf1, 0x55, - 0xcb, 0xf5, 0x26, 0xee, 0x4b, 0x2b, 0x72, 0x5f, 0x89, 0xd8, 0x53, 0xa6, 0xeb, 0x09, 0xcb, 0xe0, - 0x9c, 0x91, 0xfb, 0x8a, 0x11, 0x23, 0xe9, 0xe0, 0x64, 0x0e, 0x5c, 0xc5, 0xab, 0xc9, 0xf7, 0x2e, - 0x55, 0x8f, 0x68, 0xbe, 0x64, 0x46, 0xcc, 0x4d, 0x6d, 0xff, 0x52, 0x81, 0x46, 0xe6, 0x1c, 0x78, - 0xf6, 0x16, 0xca, 0x42, 0x61, 0xc5, 0x55, 0x94, 0x50, 0x1f, 0x4a, 0xfa, 0x26, 0xd4, 0xa3, 0xd8, - 0x0e, 0x63, 0x8b, 0x17, 0x57, 0xb2, 0xdd, 0x45, 0xc2, 0x13, 0x76, 0x46, 0x3e, 0x80, 0x35, 0xc1, - 0x74, 0xbd, 0xf1, 0x74, 0x1e, 0xb9, 0xa7, 0xa2, 0x99, 0xaf, 0xd1, 0x26, 0x92, 0x8d, 0x84, 0x4a, - 0xee, 0x42, 0x95, 0x67, 0x21, 0xbe, 0x86, 0x68, 0xfa, 0x2a, 0xcc, 0x73, 0xf8, 0x0a, 0x0f, 0x60, - 0x95, 0x33, 0xce, 0xe7, 0x57, 0xc4, 0x2d, 0x33, 0xf3, 0x9c, 0xf3, 0xd9, 0x1d, 0xd8, 0x10, 0xaf, - 0x09, 0x44, 0xf1, 0x2a, 0x2b, 0xdc, 0x3b, 0xa8, 0xd8, 0x75, 0x64, 0xc9, 0xb2, 0x56, 0x14, 0x9c, - 0x1f, 0x01, 0xcf, 0x5e, 0x0b, 0xe8, 0xbb, 0x22, 0x94, 0x31, 0xcf, 0xc9, 0x61, 0x77, 0xe1, 0x1d, - 0x8e, 0x9d, 0x7b, 0x76, 0x10, 0x4c, 0x5d, 0xe6, 0x58, 0x53, 0xff, 0x18, 0x43, 0x66, 0x14, 0xdb, - 0xb3, 0xc0, 0x9a, 0x47, 0xad, 0x0d, 0x0c, 0x99, 0x6d, 0xe6, 0x39, 0x47, 0x09, 0xa8, 0xef, 0x1f, - 0x9b, 0x09, 0xe4, 0x28, 0x6a, 0xff, 0x3e, 0xac, 0xe6, 0xec, 0x71, 0x41, 0xa7, 0x35, 0x74, 0xfe, - 0x8c, 0x4e, 0xdf, 0x85, 0x95, 0x20, 0x64, 0xe7, 0xa2, 0xd5, 0x51, 0xb4, 0x86, 0xa0, 0x09, 0xb1, - 0xb6, 0x60, 0x05, 0x79, 0x96, 0x20, 0xe6, 0xf3, 0x63, 0x03, 0x59, 0x87, 0xc8, 0x69, 0xbf, 0x80, - 0x95, 0xec, 0x69, 0x93, 0x77, 0x33, 0x69, 0xa1, 0x99, 0xcb, 0x93, 0x69, 0x76, 0x48, 0x2a, 0xb2, - 0xf5, 0x4b, 0x2a, 0x32, 0x72, 0x9d, 0x8a, 0x4c, 0xfb, 0x2f, 0xd9, 0x9c, 0x65, 0x2a, 0x84, 0x9f, - 0x41, 0x2d, 0x90, 0xf5, 0x38, 0x5a, 0x52, 0xfe, 0x12, 0x3e, 0x0f, 0xee, 0x24, 0x95, 0x3b, 0x4d, - 0xe7, 0xb4, 0xff, 0x56, 0x81, 0x5a, 0x5a, 0xd0, 0xe7, 0x2c, 0xef, 0xcd, 0x05, 0xcb, 0x3b, 0x90, - 0x1a, 0x16, 0x0a, 0x7c, 0x1b, 0xa3, 0xc5, 0x27, 0xaf, 0x7f, 0xd7, 0xc5, 0xb6, 0xe7, 0x34, 0xdb, - 0xf6, 0x6c, 0xbe, 0xae, 0xed, 0xf9, 0xe4, 0xa2, 0xc1, 0xbf, 0x95, 0xe9, 0x2d, 0x16, 0xcc, 0xbe, - 0xfd, 0x7d, 0xae, 0x0f, 0xca, 0x26, 0x84, 0x77, 0xc4, 0x7e, 0xd2, 0x84, 0x90, 0xb6, 0x3f, 0xf7, - 0xaf, 0xd7, 0xfe, 0x6c, 0x43, 0x45, 0xea, 0xfc, 0x0e, 0x54, 0x64, 0x4d, 0x27, 0x1b, 0x04, 0x31, - 0x3a, 0x6f, 0x10, 0x0a, 0xb2, 0x4e, 0xd7, 0x7e, 0xae, 0x40, 0x59, 0x0f, 0x43, 0x3f, 0xd4, 0xfe, - 0x48, 0x81, 0x3a, 0x3e, 0xed, 0xf9, 0x0e, 0xe3, 0xd9, 0x60, 0xb7, 0xdb, 0xb3, 0xa8, 0xfe, 0xcd, - 0x91, 0x8e, 0xd9, 0xa0, 0x0d, 0x77, 0xf6, 0x86, 0x83, 0xbd, 0x23, 0x4a, 0xf5, 0x81, 0x69, 0x99, - 0xb4, 0x3b, 0x18, 0xf1, 0xb6, 0x67, 0x38, 0x50, 0x15, 0x9e, 0x29, 0x8c, 0x81, 0xa9, 0xd3, 0x41, - 0xb7, 0x6f, 0x89, 0x56, 0xb4, 0x88, 0x77, 0xb3, 0xba, 0xde, 0xb3, 0xf0, 0xd6, 0x51, 0x2d, 0xf1, - 0x96, 0xd5, 0x34, 0x0e, 0xf4, 0xe1, 0x91, 0xa9, 0x96, 0xc9, 0x6d, 0x58, 0x3f, 0xd4, 0xe9, 0x81, - 0x31, 0x1a, 0x19, 0xc3, 0x81, 0xd5, 0xd3, 0x07, 0x86, 0xde, 0x53, 0x2b, 0x7c, 0x9d, 0x5d, 0x63, - 0xdf, 0xec, 0xee, 0xf6, 0x75, 0xb9, 0x4e, 0x95, 0x6c, 0xc2, 0x5b, 0x7b, 0xc3, 0x83, 0x03, 0xc3, - 0x34, 0xf5, 0x9e, 0xb5, 0x7b, 0x64, 0x5a, 0x23, 0xd3, 0xe8, 0xf7, 0xad, 0xee, 0xe1, 0x61, 0xff, - 0x29, 0x4f, 0x60, 0x35, 0x72, 0x17, 0x36, 0xf6, 0xba, 0x87, 0xdd, 0x5d, 0xa3, 0x6f, 0x98, 0x4f, - 0xad, 0x9e, 0x31, 0xe2, 0xf3, 0x7b, 0x6a, 0x9d, 0x27, 0x6c, 0x93, 0x3e, 0xb5, 0xba, 0x7d, 0x14, - 0xcd, 0xd4, 0xad, 0xdd, 0xee, 0xde, 0x13, 0x7d, 0xd0, 0x53, 0x81, 0x0b, 0x30, 0xea, 0x3e, 0xd2, - 0x2d, 0x2e, 0x92, 0x65, 0x0e, 0x87, 0xd6, 0xb0, 0xdf, 0x53, 0x1b, 0xda, 0xbf, 0x14, 0xa1, 0xb4, - 0xe7, 0x47, 0x31, 0xf7, 0x46, 0xe1, 0xac, 0x2f, 0x42, 0x37, 0x66, 0xa2, 0x7f, 0x2b, 0x53, 0xd1, - 0x4b, 0x7f, 0x87, 0x24, 0x1e, 0x50, 0x32, 0x10, 0xeb, 0xd9, 0x19, 0xc7, 0x29, 0x88, 0x5b, 0x3b, - 0xc7, 0xed, 0x72, 0xb2, 0x88, 0x68, 0x78, 0x85, 0x23, 0xd7, 0x2b, 0x22, 0x4e, 0x06, 0x61, 0xb9, - 0xe0, 0xc7, 0x40, 0xb2, 0x20, 0xb9, 0x62, 0x09, 0x91, 0x6a, 0x06, 0x29, 0x96, 0xdc, 0x01, 0x18, - 0xfb, 0xb3, 0x99, 0x1b, 0x8f, 0xfd, 0x28, 0x96, 0x5f, 0xc8, 0xda, 0x39, 0x63, 0x8f, 0x62, 0x6e, - 0xf1, 0x33, 0x37, 0xe6, 0x8f, 0x34, 0x83, 0x26, 0x3b, 0x70, 0xcf, 0x0e, 0x82, 0xd0, 0x7f, 0xe9, - 0xce, 0xec, 0x98, 0x59, 0xdc, 0x73, 0xed, 0x63, 0x66, 0x39, 0x6c, 0x1a, 0xdb, 0xd8, 0x13, 0x95, - 0xe9, 0xdd, 0x0c, 0x60, 0x24, 0xf8, 0x3d, 0xce, 0xe6, 0x71, 0xd7, 0x75, 0xac, 0x88, 0xfd, 0x30, - 0xe7, 0x1e, 0x60, 0xcd, 0x03, 0xc7, 0xe6, 0x62, 0xd6, 0x45, 0x96, 0x72, 0x9d, 0x91, 0xe4, 0x1c, - 0x09, 0x46, 0xfb, 0x15, 0xc0, 0xb9, 0x14, 0x64, 0x1b, 0x6e, 0xf3, 0x3a, 0x9e, 0x45, 0x31, 0x73, - 0x2c, 0xb9, 0xdb, 0x60, 0x1e, 0x47, 0x18, 0xe2, 0xcb, 0x74, 0x23, 0x65, 0xca, 0x9b, 0xc2, 0x79, - 0x1c, 0x91, 0x9f, 0x40, 0xeb, 0xc2, 0x1c, 0x87, 0x4d, 0x19, 0x7f, 0x6d, 0x15, 0xa7, 0xdd, 0x59, - 0x98, 0xd6, 0x13, 0x5c, 0xed, 0x4f, 0x14, 0x80, 0x7d, 0x16, 0x53, 0xc1, 0xcd, 0x34, 0xb6, 0x95, - 0xeb, 0x36, 0xb6, 0xef, 0x27, 0x17, 0x08, 0xc5, 0xab, 0x63, 0xc0, 0x42, 0x97, 0xa1, 0xdc, 0xa4, - 0xcb, 0xc8, 0x35, 0x11, 0xc5, 0x2b, 0x9a, 0x88, 0x52, 0xae, 0x89, 0xf8, 0x18, 0x9a, 0xf6, 0x74, - 0xea, 0xbf, 0xe0, 0x05, 0x0d, 0x0b, 0x43, 0xe6, 0xa0, 0x11, 0x9c, 0xd7, 0xdb, 0xc8, 0xec, 0x49, - 0x9e, 0xf6, 0xe7, 0x0a, 0x34, 0x50, 0x15, 0x51, 0xe0, 0x7b, 0x11, 0x23, 0x5f, 0x42, 0x45, 0x5e, - 0x44, 0x8b, 0x8b, 0xfc, 0xb7, 0x33, 0xb2, 0x66, 0x70, 0xb2, 0x68, 0xa0, 0x12, 0xcc, 0x33, 0x42, - 0xe6, 0x75, 0x97, 0x2b, 0x25, 0x45, 0x91, 0xfb, 0x50, 0x73, 0x3d, 0x4b, 0xb4, 0xd4, 0x95, 0x4c, - 0x58, 0xac, 0xba, 0x1e, 0xd6, 0xb2, 0xed, 0x57, 0x50, 0x11, 0x2f, 0x21, 0x9d, 0x54, 0xa6, 0x8b, - 0xfa, 0xcb, 0xdc, 0x1c, 0xa7, 0xc2, 0xc8, 0xc3, 0x29, 0xbd, 0x2e, 0x40, 0xb7, 0xa0, 0x7a, 0xca, - 0x9b, 0x0f, 0xbc, 0xf4, 0xe3, 0xea, 0x4d, 0x86, 0xda, 0x1f, 0x97, 0x00, 0x0e, 0xe7, 0x4b, 0x0c, - 0xa4, 0x71, 0x5d, 0x03, 0xe9, 0xe4, 0xf4, 0xf8, 0x7a, 0x99, 0x7f, 0x75, 0x43, 0x59, 0xd2, 0x69, - 0x17, 0x6f, 0xda, 0x69, 0xdf, 0x87, 0x6a, 0x1c, 0xce, 0xb9, 0xa3, 0x08, 0x63, 0x4a, 0x5b, 0x5a, - 0x49, 0x25, 0x6f, 0x42, 0x79, 0xe2, 0x87, 0x63, 0x86, 0x8e, 0x95, 0xb2, 0x05, 0xed, 0xc2, 0x65, - 0x52, 0xed, 0xb2, 0xcb, 0x24, 0xde, 0xa0, 0x45, 0xf2, 0x1e, 0x0d, 0x0b, 0x99, 0x7c, 0x83, 0x96, - 0x5c, 0xb1, 0xd1, 0x14, 0x44, 0xbe, 0x81, 0xa6, 0x3d, 0x8f, 0x7d, 0xcb, 0xe5, 0x15, 0xda, 0xd4, - 0x1d, 0x9f, 0x61, 0xd9, 0xdd, 0xcc, 0x7f, 0xaf, 0x4f, 0x0f, 0xaa, 0xd3, 0x9d, 0xc7, 0xbe, 0xe1, - 0x1c, 0x22, 0x72, 0xa7, 0x2a, 0x93, 0x12, 0x5d, 0xb1, 0x33, 0x64, 0xed, 0xc7, 0xb0, 0x92, 0x85, - 0xf1, 0x04, 0x24, 0x81, 0xea, 0x1b, 0x3c, 0x3b, 0x8d, 0x78, 0x6a, 0x1b, 0x98, 0x46, 0xb7, 0xaf, - 0x16, 0xb4, 0x18, 0x1a, 0xb8, 0xbc, 0xf4, 0x8e, 0xeb, 0xba, 0xfd, 0x03, 0x28, 0x61, 0xf8, 0x55, - 0x2e, 0x7c, 0x0f, 0xc1, 0x98, 0x8b, 0xcc, 0xbc, 0xf9, 0x15, 0xb3, 0xe6, 0xf7, 0xdf, 0x05, 0x58, - 0x31, 0xfd, 0xf9, 0xf8, 0xe4, 0xa2, 0x01, 0xc2, 0xaf, 0x3b, 0x42, 0x2d, 0x31, 0x1f, 0xe5, 0xa6, - 0xe6, 0x93, 0x5a, 0x47, 0x71, 0x89, 0x75, 0xdc, 0xf4, 0xcc, 0xb5, 0x2f, 0x60, 0x55, 0x6e, 0x5e, - 0x6a, 0x3d, 0xd1, 0x66, 0xe1, 0x0a, 0x6d, 0x6a, 0xbf, 0x50, 0x60, 0x55, 0xc4, 0xf7, 0xff, 0xbb, - 0xd2, 0x2a, 0x37, 0x0c, 0xeb, 0xe5, 0x1b, 0x5d, 0x1e, 0xfd, 0xbf, 0xf4, 0x34, 0x6d, 0x08, 0xcd, - 0x44, 0x7d, 0x37, 0x50, 0xfb, 0x15, 0x46, 0xfc, 0x8b, 0x02, 0x34, 0x06, 0xec, 0xe5, 0x92, 0x20, - 0x5a, 0xbe, 0xee, 0x71, 0x7c, 0x98, 0x2b, 0x57, 0x1b, 0xdb, 0xeb, 0x59, 0x19, 0xc4, 0xd5, 0x63, - 0x52, 0xc1, 0xa6, 0xb7, 0xa8, 0xca, 0xf2, 0x5b, 0xd4, 0xd2, 0x62, 0xb7, 0x9e, 0xb9, 0xc5, 0x2b, - 0x2e, 0xbb, 0xc5, 0xd3, 0xfe, 0xad, 0x08, 0x0d, 0x6c, 0x90, 0x29, 0x8b, 0xe6, 0xd3, 0x38, 0x27, - 0x4c, 0xe1, 0x6a, 0x61, 0x3a, 0x50, 0x09, 0x71, 0x92, 0x74, 0xa5, 0x4b, 0x83, 0xbf, 0x40, 0x61, - 0x6b, 0xfc, 0xdc, 0x0d, 0x02, 0xe6, 0x58, 0x82, 0x92, 0x14, 0x30, 0x4d, 0x49, 0x16, 0x22, 0x44, - 0xbc, 0xfc, 0x9c, 0xf9, 0x21, 0x4b, 0x51, 0x45, 0xbc, 0x4f, 0x68, 0x70, 0x5a, 0x02, 0xc9, 0xdd, - 0x37, 0x88, 0xca, 0xe0, 0xfc, 0xbe, 0x21, 0xed, 0x35, 0x91, 0x5b, 0x47, 0xae, 0xe8, 0x35, 0x91, - 0xcd, 0xbb, 0xa8, 0x99, 0x3d, 0x9d, 0x5a, 0x7e, 0x10, 0xa1, 0xd3, 0xd4, 0x68, 0x0d, 0x09, 0xc3, - 0x20, 0x22, 0x5f, 0x43, 0x7a, 0x5d, 0x2c, 0x6f, 0xc9, 0xc5, 0x39, 0xb6, 0x2e, 0xbb, 0x58, 0xa0, - 0xab, 0xe3, 0xdc, 0xfd, 0xcf, 0x92, 0x1b, 0xea, 0xca, 0x4d, 0x6f, 0xa8, 0x1f, 0x42, 0x59, 0xc4, - 0xa8, 0xda, 0xeb, 0x62, 0x94, 0xc0, 0x65, 0xed, 0xb3, 0x91, 0xb7, 0xcf, 0x5f, 0x16, 0x80, 0x74, - 0xa7, 0x53, 0x7f, 0x6c, 0xc7, 0xcc, 0x70, 0xa2, 0x8b, 0x66, 0x7a, 0xed, 0xcf, 0x2e, 0x9f, 0x41, - 0x7d, 0xe6, 0x3b, 0x6c, 0x6a, 0x25, 0xdf, 0x94, 0x2e, 0xad, 0x7e, 0x10, 0xc6, 0x5b, 0x52, 0x02, - 0x25, 0xbc, 0xc4, 0x51, 0xb0, 0xee, 0xc0, 0x67, 0xde, 0x84, 0xcd, 0xec, 0x97, 0xb2, 0x14, 0xe1, - 0x8f, 0xa4, 0x03, 0xd5, 0x90, 0x45, 0x2c, 0x3c, 0x65, 0x57, 0x16, 0x55, 0x09, 0x48, 0x7b, 0x06, - 0x1b, 0xb9, 0x1d, 0x49, 0x47, 0xbe, 0x85, 0x5f, 0x2b, 0xc3, 0x58, 0x7e, 0xb4, 0x12, 0x03, 0xfe, - 0x3a, 0xe6, 0x25, 0x9f, 0x41, 0xf9, 0x63, 0xea, 0xf0, 0xc5, 0xab, 0xe2, 0xec, 0x1e, 0xa8, 0x59, - 0x4d, 0xbb, 0x63, 0x0c, 0x36, 0xf2, 0x54, 0x0a, 0xd7, 0x3b, 0x15, 0xed, 0xef, 0x0a, 0xb0, 0xde, - 0x75, 0x1c, 0xf1, 0x77, 0xc3, 0x25, 0xaa, 0x2f, 0x5e, 0x57, 0xf5, 0x0b, 0x81, 0x58, 0x84, 0x89, - 0x6b, 0x05, 0xe2, 0x0f, 0xa1, 0x92, 0xd6, 0x5a, 0xc5, 0x05, 0x77, 0x16, 0x72, 0x51, 0x09, 0xd0, - 0x6e, 0x01, 0xc9, 0x0a, 0x2b, 0xb4, 0xaa, 0xfd, 0x69, 0x11, 0xee, 0xee, 0xb2, 0x63, 0xd7, 0xcb, - 0xbe, 0xe2, 0x57, 0xdf, 0xc9, 0xc5, 0x4f, 0x65, 0x9f, 0xc1, 0xba, 0x28, 0xe4, 0x93, 0x7f, 0x62, - 0x59, 0xec, 0x58, 0x7e, 0x9d, 0x94, 0xb1, 0x6a, 0x0d, 0xf9, 0x07, 0x92, 0xad, 0xe3, 0x7f, 0xc5, - 0x1c, 0x3b, 0xb6, 0x9f, 0xd9, 0x11, 0xb3, 0x5c, 0x47, 0xfe, 0x59, 0x06, 0x12, 0x92, 0xe1, 0x90, - 0x21, 0x94, 0xb8, 0x0d, 0xa2, 0xeb, 0x36, 0xb7, 0xb7, 0x33, 0x62, 0x5d, 0xb2, 0x95, 0xac, 0x02, - 0x0f, 0x7c, 0x87, 0xed, 0x54, 0x8f, 0x06, 0x4f, 0x06, 0xc3, 0xef, 0x06, 0x14, 0x17, 0x22, 0x06, - 0xdc, 0x0a, 0x42, 0x76, 0xea, 0xfa, 0xf3, 0xc8, 0xca, 0x9e, 0x44, 0xf5, 0xca, 0x94, 0xb8, 0x91, - 0xcc, 0xc9, 0x10, 0xb5, 0x9f, 0xc2, 0xda, 0xc2, 0xcb, 0x78, 0x6d, 0x26, 0x5f, 0xa7, 0xbe, 0x41, - 0x56, 0xa1, 0x8e, 0x1f, 0xbb, 0x97, 0x7f, 0xfb, 0xd6, 0xfe, 0xb5, 0x80, 0x57, 0x4c, 0x33, 0x37, - 0xbe, 0x59, 0x06, 0xfb, 0xcd, 0x7c, 0x06, 0x83, 0xed, 0x77, 0xf3, 0xe6, 0x9b, 0x59, 0xb0, 0xf3, - 0xad, 0x00, 0xa6, 0x41, 0xa4, 0x6d, 0x43, 0x55, 0xd2, 0xc8, 0x6f, 0xc1, 0x5a, 0xe8, 0xfb, 0x71, - 0xd2, 0x89, 0x8a, 0x0e, 0xe4, 0xf2, 0x3f, 0xdb, 0xac, 0x72, 0xb0, 0x48, 0x06, 0x4f, 0xf2, 0xbd, - 0x48, 0x59, 0xfc, 0x0d, 0x44, 0x0e, 0x77, 0x1b, 0xbf, 0x5b, 0x4f, 0xff, 0xb7, 0xfb, 0xbf, 0x01, - 0x00, 0x00, 0xff, 0xff, 0x35, 0x9f, 0x30, 0x98, 0xf2, 0x2b, 0x00, 0x00, -} diff --git a/vendor/google.golang.org/appengine/internal/datastore/datastore_v3.proto b/vendor/google.golang.org/appengine/internal/datastore/datastore_v3.proto deleted file mode 100644 index 497b4d9a9..000000000 --- a/vendor/google.golang.org/appengine/internal/datastore/datastore_v3.proto +++ /dev/null @@ -1,551 +0,0 @@ -syntax = "proto2"; -option go_package = "datastore"; - -package appengine; - -message Action{} - -message PropertyValue { - optional int64 int64Value = 1; - optional bool booleanValue = 2; - optional string stringValue = 3; - optional double doubleValue = 4; - - optional group PointValue = 5 { - required double x = 6; - required double y = 7; - } - - optional group UserValue = 8 { - required string email = 9; - required string auth_domain = 10; - optional string nickname = 11; - optional string federated_identity = 21; - optional string federated_provider = 22; - } - - optional group ReferenceValue = 12 { - required string app = 13; - optional string name_space = 20; - repeated group PathElement = 14 { - required string type = 15; - optional int64 id = 16; - optional string name = 17; - } - } -} - -message Property { - enum Meaning { - NO_MEANING = 0; - BLOB = 14; - TEXT = 15; - BYTESTRING = 16; - - ATOM_CATEGORY = 1; - ATOM_LINK = 2; - ATOM_TITLE = 3; - ATOM_CONTENT = 4; - ATOM_SUMMARY = 5; - ATOM_AUTHOR = 6; - - GD_WHEN = 7; - GD_EMAIL = 8; - GEORSS_POINT = 9; - GD_IM = 10; - - GD_PHONENUMBER = 11; - GD_POSTALADDRESS = 12; - - GD_RATING = 13; - - BLOBKEY = 17; - ENTITY_PROTO = 19; - - INDEX_VALUE = 18; - }; - - optional Meaning meaning = 1 [default = NO_MEANING]; - optional string meaning_uri = 2; - - required string name = 3; - - required PropertyValue value = 5; - - required bool multiple = 4; - - optional bool searchable = 6 [default=false]; - - enum FtsTokenizationOption { - HTML = 1; - ATOM = 2; - } - - optional FtsTokenizationOption fts_tokenization_option = 8; - - optional string locale = 9 [default = "en"]; -} - -message Path { - repeated group Element = 1 { - required string type = 2; - optional int64 id = 3; - optional string name = 4; - } -} - -message Reference { - required string app = 13; - optional string name_space = 20; - required Path path = 14; -} - -message User { - required string email = 1; - required string auth_domain = 2; - optional string nickname = 3; - optional string federated_identity = 6; - optional string federated_provider = 7; -} - -message EntityProto { - required Reference key = 13; - required Path entity_group = 16; - optional User owner = 17; - - enum Kind { - GD_CONTACT = 1; - GD_EVENT = 2; - GD_MESSAGE = 3; - } - optional Kind kind = 4; - optional string kind_uri = 5; - - repeated Property property = 14; - repeated Property raw_property = 15; - - optional int32 rank = 18; -} - -message CompositeProperty { - required int64 index_id = 1; - repeated string value = 2; -} - -message Index { - required string entity_type = 1; - required bool ancestor = 5; - repeated group Property = 2 { - required string name = 3; - enum Direction { - ASCENDING = 1; - DESCENDING = 2; - } - optional Direction direction = 4 [default = ASCENDING]; - } -} - -message CompositeIndex { - required string app_id = 1; - required int64 id = 2; - required Index definition = 3; - - enum State { - WRITE_ONLY = 1; - READ_WRITE = 2; - DELETED = 3; - ERROR = 4; - } - required State state = 4; - - optional bool only_use_if_required = 6 [default = false]; -} - -message IndexPostfix { - message IndexValue { - required string property_name = 1; - required PropertyValue value = 2; - } - - repeated IndexValue index_value = 1; - - optional Reference key = 2; - - optional bool before = 3 [default=true]; -} - -message IndexPosition { - optional string key = 1; - - optional bool before = 2 [default=true]; -} - -message Snapshot { - enum Status { - INACTIVE = 0; - ACTIVE = 1; - } - - required int64 ts = 1; -} - -message InternalHeader { - optional string qos = 1; -} - -message Transaction { - optional InternalHeader header = 4; - required fixed64 handle = 1; - required string app = 2; - optional bool mark_changes = 3 [default = false]; -} - -message Query { - optional InternalHeader header = 39; - - required string app = 1; - optional string name_space = 29; - - optional string kind = 3; - optional Reference ancestor = 17; - - repeated group Filter = 4 { - enum Operator { - LESS_THAN = 1; - LESS_THAN_OR_EQUAL = 2; - GREATER_THAN = 3; - GREATER_THAN_OR_EQUAL = 4; - EQUAL = 5; - IN = 6; - EXISTS = 7; - } - - required Operator op = 6; - repeated Property property = 14; - } - - optional string search_query = 8; - - repeated group Order = 9 { - enum Direction { - ASCENDING = 1; - DESCENDING = 2; - } - - required string property = 10; - optional Direction direction = 11 [default = ASCENDING]; - } - - enum Hint { - ORDER_FIRST = 1; - ANCESTOR_FIRST = 2; - FILTER_FIRST = 3; - } - optional Hint hint = 18; - - optional int32 count = 23; - - optional int32 offset = 12 [default = 0]; - - optional int32 limit = 16; - - optional CompiledCursor compiled_cursor = 30; - optional CompiledCursor end_compiled_cursor = 31; - - repeated CompositeIndex composite_index = 19; - - optional bool require_perfect_plan = 20 [default = false]; - - optional bool keys_only = 21 [default = false]; - - optional Transaction transaction = 22; - - optional bool compile = 25 [default = false]; - - optional int64 failover_ms = 26; - - optional bool strong = 32; - - repeated string property_name = 33; - - repeated string group_by_property_name = 34; - - optional bool distinct = 24; - - optional int64 min_safe_time_seconds = 35; - - repeated string safe_replica_name = 36; - - optional bool persist_offset = 37 [default=false]; -} - -message CompiledQuery { - required group PrimaryScan = 1 { - optional string index_name = 2; - - optional string start_key = 3; - optional bool start_inclusive = 4; - optional string end_key = 5; - optional bool end_inclusive = 6; - - repeated string start_postfix_value = 22; - repeated string end_postfix_value = 23; - - optional int64 end_unapplied_log_timestamp_us = 19; - } - - repeated group MergeJoinScan = 7 { - required string index_name = 8; - - repeated string prefix_value = 9; - - optional bool value_prefix = 20 [default=false]; - } - - optional Index index_def = 21; - - optional int32 offset = 10 [default = 0]; - - optional int32 limit = 11; - - required bool keys_only = 12; - - repeated string property_name = 24; - - optional int32 distinct_infix_size = 25; - - optional group EntityFilter = 13 { - optional bool distinct = 14 [default=false]; - - optional string kind = 17; - optional Reference ancestor = 18; - } -} - -message CompiledCursor { - optional group Position = 2 { - optional string start_key = 27; - - repeated group IndexValue = 29 { - optional string property = 30; - required PropertyValue value = 31; - } - - optional Reference key = 32; - - optional bool start_inclusive = 28 [default=true]; - } -} - -message Cursor { - required fixed64 cursor = 1; - - optional string app = 2; -} - -message Error { - enum ErrorCode { - BAD_REQUEST = 1; - CONCURRENT_TRANSACTION = 2; - INTERNAL_ERROR = 3; - NEED_INDEX = 4; - TIMEOUT = 5; - PERMISSION_DENIED = 6; - BIGTABLE_ERROR = 7; - COMMITTED_BUT_STILL_APPLYING = 8; - CAPABILITY_DISABLED = 9; - TRY_ALTERNATE_BACKEND = 10; - SAFE_TIME_TOO_OLD = 11; - } -} - -message Cost { - optional int32 index_writes = 1; - optional int32 index_write_bytes = 2; - optional int32 entity_writes = 3; - optional int32 entity_write_bytes = 4; - optional group CommitCost = 5 { - optional int32 requested_entity_puts = 6; - optional int32 requested_entity_deletes = 7; - }; - optional int32 approximate_storage_delta = 8; - optional int32 id_sequence_updates = 9; -} - -message GetRequest { - optional InternalHeader header = 6; - - repeated Reference key = 1; - optional Transaction transaction = 2; - - optional int64 failover_ms = 3; - - optional bool strong = 4; - - optional bool allow_deferred = 5 [default=false]; -} - -message GetResponse { - repeated group Entity = 1 { - optional EntityProto entity = 2; - optional Reference key = 4; - - optional int64 version = 3; - } - - repeated Reference deferred = 5; - - optional bool in_order = 6 [default=true]; -} - -message PutRequest { - optional InternalHeader header = 11; - - repeated EntityProto entity = 1; - optional Transaction transaction = 2; - repeated CompositeIndex composite_index = 3; - - optional bool trusted = 4 [default = false]; - - optional bool force = 7 [default = false]; - - optional bool mark_changes = 8 [default = false]; - repeated Snapshot snapshot = 9; - - enum AutoIdPolicy { - CURRENT = 0; - SEQUENTIAL = 1; - } - optional AutoIdPolicy auto_id_policy = 10 [default = CURRENT]; -} - -message PutResponse { - repeated Reference key = 1; - optional Cost cost = 2; - repeated int64 version = 3; -} - -message TouchRequest { - optional InternalHeader header = 10; - - repeated Reference key = 1; - repeated CompositeIndex composite_index = 2; - optional bool force = 3 [default = false]; - repeated Snapshot snapshot = 9; -} - -message TouchResponse { - optional Cost cost = 1; -} - -message DeleteRequest { - optional InternalHeader header = 10; - - repeated Reference key = 6; - optional Transaction transaction = 5; - - optional bool trusted = 4 [default = false]; - - optional bool force = 7 [default = false]; - - optional bool mark_changes = 8 [default = false]; - repeated Snapshot snapshot = 9; -} - -message DeleteResponse { - optional Cost cost = 1; - repeated int64 version = 3; -} - -message NextRequest { - optional InternalHeader header = 5; - - required Cursor cursor = 1; - optional int32 count = 2; - - optional int32 offset = 4 [default = 0]; - - optional bool compile = 3 [default = false]; -} - -message QueryResult { - optional Cursor cursor = 1; - - repeated EntityProto result = 2; - - optional int32 skipped_results = 7; - - required bool more_results = 3; - - optional bool keys_only = 4; - - optional bool index_only = 9; - - optional bool small_ops = 10; - - optional CompiledQuery compiled_query = 5; - - optional CompiledCursor compiled_cursor = 6; - - repeated CompositeIndex index = 8; - - repeated int64 version = 11; -} - -message AllocateIdsRequest { - optional InternalHeader header = 4; - - optional Reference model_key = 1; - - optional int64 size = 2; - - optional int64 max = 3; - - repeated Reference reserve = 5; -} - -message AllocateIdsResponse { - required int64 start = 1; - required int64 end = 2; - optional Cost cost = 3; -} - -message CompositeIndices { - repeated CompositeIndex index = 1; -} - -message AddActionsRequest { - optional InternalHeader header = 3; - - required Transaction transaction = 1; - repeated Action action = 2; -} - -message AddActionsResponse { -} - -message BeginTransactionRequest { - optional InternalHeader header = 3; - - required string app = 1; - optional bool allow_multiple_eg = 2 [default = false]; - optional string database_id = 4; - - enum TransactionMode { - UNKNOWN = 0; - READ_ONLY = 1; - READ_WRITE = 2; - } - optional TransactionMode mode = 5 [default = UNKNOWN]; - - optional Transaction previous_transaction = 7; -} - -message CommitResponse { - optional Cost cost = 1; - - repeated group Version = 3 { - required Reference root_entity_key = 4; - required int64 version = 5; - } -} diff --git a/vendor/google.golang.org/appengine/internal/identity.go b/vendor/google.golang.org/appengine/internal/identity.go deleted file mode 100644 index 0f95aa91d..000000000 --- a/vendor/google.golang.org/appengine/internal/identity.go +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2011 Google Inc. All rights reserved. -// Use of this source code is governed by the Apache 2.0 -// license that can be found in the LICENSE file. - -package internal - -import ( - "context" - "os" -) - -var ( - // This is set to true in identity_classic.go, which is behind the appengine build tag. - // The appengine build tag is set for the first generation runtimes (<= Go 1.9) but not - // the second generation runtimes (>= Go 1.11), so this indicates whether we're on a - // first-gen runtime. See IsStandard below for the second-gen check. - appengineStandard bool - - // This is set to true in identity_flex.go, which is behind the appenginevm build tag. - appengineFlex bool -) - -// AppID is the implementation of the wrapper function of the same name in -// ../identity.go. See that file for commentary. -func AppID(c context.Context) string { - return appID(FullyQualifiedAppID(c)) -} - -// IsStandard is the implementation of the wrapper function of the same name in -// ../appengine.go. See that file for commentary. -func IsStandard() bool { - // appengineStandard will be true for first-gen runtimes (<= Go 1.9) but not - // second-gen (>= Go 1.11). - return appengineStandard || IsSecondGen() -} - -// IsSecondGen is the implementation of the wrapper function of the same name in -// ../appengine.go. See that file for commentary. -func IsSecondGen() bool { - // Second-gen runtimes set $GAE_ENV so we use that to check if we're on a second-gen runtime. - return os.Getenv("GAE_ENV") == "standard" -} - -// IsFlex is the implementation of the wrapper function of the same name in -// ../appengine.go. See that file for commentary. -func IsFlex() bool { - return appengineFlex -} - -// IsAppEngine is the implementation of the wrapper function of the same name in -// ../appengine.go. See that file for commentary. -func IsAppEngine() bool { - return IsStandard() || IsFlex() -} diff --git a/vendor/google.golang.org/appengine/internal/identity_classic.go b/vendor/google.golang.org/appengine/internal/identity_classic.go deleted file mode 100644 index 5ad3548bf..000000000 --- a/vendor/google.golang.org/appengine/internal/identity_classic.go +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright 2015 Google Inc. All rights reserved. -// Use of this source code is governed by the Apache 2.0 -// license that can be found in the LICENSE file. - -//go:build appengine -// +build appengine - -package internal - -import ( - "context" - - "appengine" -) - -func init() { - appengineStandard = true -} - -func DefaultVersionHostname(ctx context.Context) string { - c := fromContext(ctx) - if c == nil { - panic(errNotAppEngineContext) - } - return appengine.DefaultVersionHostname(c) -} - -func Datacenter(_ context.Context) string { return appengine.Datacenter() } -func ServerSoftware() string { return appengine.ServerSoftware() } -func InstanceID() string { return appengine.InstanceID() } -func IsDevAppServer() bool { return appengine.IsDevAppServer() } - -func RequestID(ctx context.Context) string { - c := fromContext(ctx) - if c == nil { - panic(errNotAppEngineContext) - } - return appengine.RequestID(c) -} - -func ModuleName(ctx context.Context) string { - c := fromContext(ctx) - if c == nil { - panic(errNotAppEngineContext) - } - return appengine.ModuleName(c) -} -func VersionID(ctx context.Context) string { - c := fromContext(ctx) - if c == nil { - panic(errNotAppEngineContext) - } - return appengine.VersionID(c) -} - -func fullyQualifiedAppID(ctx context.Context) string { - c := fromContext(ctx) - if c == nil { - panic(errNotAppEngineContext) - } - return c.FullyQualifiedAppID() -} diff --git a/vendor/google.golang.org/appengine/internal/identity_flex.go b/vendor/google.golang.org/appengine/internal/identity_flex.go deleted file mode 100644 index 4201b6b58..000000000 --- a/vendor/google.golang.org/appengine/internal/identity_flex.go +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright 2018 Google LLC. All rights reserved. -// Use of this source code is governed by the Apache 2.0 -// license that can be found in the LICENSE file. - -//go:build appenginevm -// +build appenginevm - -package internal - -func init() { - appengineFlex = true -} diff --git a/vendor/google.golang.org/appengine/internal/identity_vm.go b/vendor/google.golang.org/appengine/internal/identity_vm.go deleted file mode 100644 index 18ddda3a4..000000000 --- a/vendor/google.golang.org/appengine/internal/identity_vm.go +++ /dev/null @@ -1,134 +0,0 @@ -// Copyright 2011 Google Inc. All rights reserved. -// Use of this source code is governed by the Apache 2.0 -// license that can be found in the LICENSE file. - -//go:build !appengine -// +build !appengine - -package internal - -import ( - "context" - "log" - "net/http" - "os" - "strings" -) - -// These functions are implementations of the wrapper functions -// in ../appengine/identity.go. See that file for commentary. - -const ( - hDefaultVersionHostname = "X-AppEngine-Default-Version-Hostname" - hRequestLogId = "X-AppEngine-Request-Log-Id" - hDatacenter = "X-AppEngine-Datacenter" -) - -func ctxHeaders(ctx context.Context) http.Header { - c := fromContext(ctx) - if c == nil { - return nil - } - return c.Request().Header -} - -func DefaultVersionHostname(ctx context.Context) string { - return ctxHeaders(ctx).Get(hDefaultVersionHostname) -} - -func RequestID(ctx context.Context) string { - return ctxHeaders(ctx).Get(hRequestLogId) -} - -func Datacenter(ctx context.Context) string { - if dc := ctxHeaders(ctx).Get(hDatacenter); dc != "" { - return dc - } - // If the header isn't set, read zone from the metadata service. - // It has the format projects/[NUMERIC_PROJECT_ID]/zones/[ZONE] - zone, err := getMetadata("instance/zone") - if err != nil { - log.Printf("Datacenter: %v", err) - return "" - } - parts := strings.Split(string(zone), "/") - if len(parts) == 0 { - return "" - } - return parts[len(parts)-1] -} - -func ServerSoftware() string { - // TODO(dsymonds): Remove fallback when we've verified this. - if s := os.Getenv("SERVER_SOFTWARE"); s != "" { - return s - } - if s := os.Getenv("GAE_ENV"); s != "" { - return s - } - return "Google App Engine/1.x.x" -} - -// TODO(dsymonds): Remove the metadata fetches. - -func ModuleName(_ context.Context) string { - if s := os.Getenv("GAE_MODULE_NAME"); s != "" { - return s - } - if s := os.Getenv("GAE_SERVICE"); s != "" { - return s - } - return string(mustGetMetadata("instance/attributes/gae_backend_name")) -} - -func VersionID(_ context.Context) string { - if s1, s2 := os.Getenv("GAE_MODULE_VERSION"), os.Getenv("GAE_MINOR_VERSION"); s1 != "" && s2 != "" { - return s1 + "." + s2 - } - if s1, s2 := os.Getenv("GAE_VERSION"), os.Getenv("GAE_DEPLOYMENT_ID"); s1 != "" && s2 != "" { - return s1 + "." + s2 - } - return string(mustGetMetadata("instance/attributes/gae_backend_version")) + "." + string(mustGetMetadata("instance/attributes/gae_backend_minor_version")) -} - -func InstanceID() string { - if s := os.Getenv("GAE_MODULE_INSTANCE"); s != "" { - return s - } - if s := os.Getenv("GAE_INSTANCE"); s != "" { - return s - } - return string(mustGetMetadata("instance/attributes/gae_backend_instance")) -} - -func partitionlessAppID() string { - // gae_project has everything except the partition prefix. - if appID := os.Getenv("GAE_LONG_APP_ID"); appID != "" { - return appID - } - if project := os.Getenv("GOOGLE_CLOUD_PROJECT"); project != "" { - return project - } - return string(mustGetMetadata("instance/attributes/gae_project")) -} - -func fullyQualifiedAppID(_ context.Context) string { - if s := os.Getenv("GAE_APPLICATION"); s != "" { - return s - } - appID := partitionlessAppID() - - part := os.Getenv("GAE_PARTITION") - if part == "" { - part = string(mustGetMetadata("instance/attributes/gae_partition")) - } - - if part != "" { - appID = part + "~" + appID - } - return appID -} - -func IsDevAppServer() bool { - return os.Getenv("RUN_WITH_DEVAPPSERVER") != "" || os.Getenv("GAE_ENV") == "localdev" -} diff --git a/vendor/google.golang.org/appengine/internal/internal.go b/vendor/google.golang.org/appengine/internal/internal.go deleted file mode 100644 index 051ea3980..000000000 --- a/vendor/google.golang.org/appengine/internal/internal.go +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright 2011 Google Inc. All rights reserved. -// Use of this source code is governed by the Apache 2.0 -// license that can be found in the LICENSE file. - -// Package internal provides support for package appengine. -// -// Programs should not use this package directly. Its API is not stable. -// Use packages appengine and appengine/* instead. -package internal - -import ( - "fmt" - - "github.com/golang/protobuf/proto" - - remotepb "google.golang.org/appengine/internal/remote_api" -) - -// errorCodeMaps is a map of service name to the error code map for the service. -var errorCodeMaps = make(map[string]map[int32]string) - -// RegisterErrorCodeMap is called from API implementations to register their -// error code map. This should only be called from init functions. -func RegisterErrorCodeMap(service string, m map[int32]string) { - errorCodeMaps[service] = m -} - -type timeoutCodeKey struct { - service string - code int32 -} - -// timeoutCodes is the set of service+code pairs that represent timeouts. -var timeoutCodes = make(map[timeoutCodeKey]bool) - -func RegisterTimeoutErrorCode(service string, code int32) { - timeoutCodes[timeoutCodeKey{service, code}] = true -} - -// APIError is the type returned by appengine.Context's Call method -// when an API call fails in an API-specific way. This may be, for instance, -// a taskqueue API call failing with TaskQueueServiceError::UNKNOWN_QUEUE. -type APIError struct { - Service string - Detail string - Code int32 // API-specific error code -} - -func (e *APIError) Error() string { - if e.Code == 0 { - if e.Detail == "" { - return "APIError " - } - return e.Detail - } - s := fmt.Sprintf("API error %d", e.Code) - if m, ok := errorCodeMaps[e.Service]; ok { - s += " (" + e.Service + ": " + m[e.Code] + ")" - } else { - // Shouldn't happen, but provide a bit more detail if it does. - s = e.Service + " " + s - } - if e.Detail != "" { - s += ": " + e.Detail - } - return s -} - -func (e *APIError) IsTimeout() bool { - return timeoutCodes[timeoutCodeKey{e.Service, e.Code}] -} - -// CallError is the type returned by appengine.Context's Call method when an -// API call fails in a generic way, such as RpcError::CAPABILITY_DISABLED. -type CallError struct { - Detail string - Code int32 - // TODO: Remove this if we get a distinguishable error code. - Timeout bool -} - -func (e *CallError) Error() string { - var msg string - switch remotepb.RpcError_ErrorCode(e.Code) { - case remotepb.RpcError_UNKNOWN: - return e.Detail - case remotepb.RpcError_OVER_QUOTA: - msg = "Over quota" - case remotepb.RpcError_CAPABILITY_DISABLED: - msg = "Capability disabled" - case remotepb.RpcError_CANCELLED: - msg = "Canceled" - default: - msg = fmt.Sprintf("Call error %d", e.Code) - } - s := msg + ": " + e.Detail - if e.Timeout { - s += " (timeout)" - } - return s -} - -func (e *CallError) IsTimeout() bool { - return e.Timeout -} - -// NamespaceMods is a map from API service to a function that will mutate an RPC request to attach a namespace. -// The function should be prepared to be called on the same message more than once; it should only modify the -// RPC request the first time. -var NamespaceMods = make(map[string]func(m proto.Message, namespace string)) diff --git a/vendor/google.golang.org/appengine/internal/log/log_service.pb.go b/vendor/google.golang.org/appengine/internal/log/log_service.pb.go deleted file mode 100644 index 8545ac4ad..000000000 --- a/vendor/google.golang.org/appengine/internal/log/log_service.pb.go +++ /dev/null @@ -1,1313 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// source: google.golang.org/appengine/internal/log/log_service.proto - -package log - -import proto "github.com/golang/protobuf/proto" -import fmt "fmt" -import math "math" - -// Reference imports to suppress errors if they are not otherwise used. -var _ = proto.Marshal -var _ = fmt.Errorf -var _ = math.Inf - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the proto package it is being compiled against. -// A compilation error at this line likely means your copy of the -// proto package needs to be updated. -const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package - -type LogServiceError_ErrorCode int32 - -const ( - LogServiceError_OK LogServiceError_ErrorCode = 0 - LogServiceError_INVALID_REQUEST LogServiceError_ErrorCode = 1 - LogServiceError_STORAGE_ERROR LogServiceError_ErrorCode = 2 -) - -var LogServiceError_ErrorCode_name = map[int32]string{ - 0: "OK", - 1: "INVALID_REQUEST", - 2: "STORAGE_ERROR", -} -var LogServiceError_ErrorCode_value = map[string]int32{ - "OK": 0, - "INVALID_REQUEST": 1, - "STORAGE_ERROR": 2, -} - -func (x LogServiceError_ErrorCode) Enum() *LogServiceError_ErrorCode { - p := new(LogServiceError_ErrorCode) - *p = x - return p -} -func (x LogServiceError_ErrorCode) String() string { - return proto.EnumName(LogServiceError_ErrorCode_name, int32(x)) -} -func (x *LogServiceError_ErrorCode) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(LogServiceError_ErrorCode_value, data, "LogServiceError_ErrorCode") - if err != nil { - return err - } - *x = LogServiceError_ErrorCode(value) - return nil -} -func (LogServiceError_ErrorCode) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_log_service_f054fd4b5012319d, []int{0, 0} -} - -type LogServiceError struct { - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *LogServiceError) Reset() { *m = LogServiceError{} } -func (m *LogServiceError) String() string { return proto.CompactTextString(m) } -func (*LogServiceError) ProtoMessage() {} -func (*LogServiceError) Descriptor() ([]byte, []int) { - return fileDescriptor_log_service_f054fd4b5012319d, []int{0} -} -func (m *LogServiceError) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_LogServiceError.Unmarshal(m, b) -} -func (m *LogServiceError) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_LogServiceError.Marshal(b, m, deterministic) -} -func (dst *LogServiceError) XXX_Merge(src proto.Message) { - xxx_messageInfo_LogServiceError.Merge(dst, src) -} -func (m *LogServiceError) XXX_Size() int { - return xxx_messageInfo_LogServiceError.Size(m) -} -func (m *LogServiceError) XXX_DiscardUnknown() { - xxx_messageInfo_LogServiceError.DiscardUnknown(m) -} - -var xxx_messageInfo_LogServiceError proto.InternalMessageInfo - -type UserAppLogLine struct { - TimestampUsec *int64 `protobuf:"varint,1,req,name=timestamp_usec,json=timestampUsec" json:"timestamp_usec,omitempty"` - Level *int64 `protobuf:"varint,2,req,name=level" json:"level,omitempty"` - Message *string `protobuf:"bytes,3,req,name=message" json:"message,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *UserAppLogLine) Reset() { *m = UserAppLogLine{} } -func (m *UserAppLogLine) String() string { return proto.CompactTextString(m) } -func (*UserAppLogLine) ProtoMessage() {} -func (*UserAppLogLine) Descriptor() ([]byte, []int) { - return fileDescriptor_log_service_f054fd4b5012319d, []int{1} -} -func (m *UserAppLogLine) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_UserAppLogLine.Unmarshal(m, b) -} -func (m *UserAppLogLine) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_UserAppLogLine.Marshal(b, m, deterministic) -} -func (dst *UserAppLogLine) XXX_Merge(src proto.Message) { - xxx_messageInfo_UserAppLogLine.Merge(dst, src) -} -func (m *UserAppLogLine) XXX_Size() int { - return xxx_messageInfo_UserAppLogLine.Size(m) -} -func (m *UserAppLogLine) XXX_DiscardUnknown() { - xxx_messageInfo_UserAppLogLine.DiscardUnknown(m) -} - -var xxx_messageInfo_UserAppLogLine proto.InternalMessageInfo - -func (m *UserAppLogLine) GetTimestampUsec() int64 { - if m != nil && m.TimestampUsec != nil { - return *m.TimestampUsec - } - return 0 -} - -func (m *UserAppLogLine) GetLevel() int64 { - if m != nil && m.Level != nil { - return *m.Level - } - return 0 -} - -func (m *UserAppLogLine) GetMessage() string { - if m != nil && m.Message != nil { - return *m.Message - } - return "" -} - -type UserAppLogGroup struct { - LogLine []*UserAppLogLine `protobuf:"bytes,2,rep,name=log_line,json=logLine" json:"log_line,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *UserAppLogGroup) Reset() { *m = UserAppLogGroup{} } -func (m *UserAppLogGroup) String() string { return proto.CompactTextString(m) } -func (*UserAppLogGroup) ProtoMessage() {} -func (*UserAppLogGroup) Descriptor() ([]byte, []int) { - return fileDescriptor_log_service_f054fd4b5012319d, []int{2} -} -func (m *UserAppLogGroup) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_UserAppLogGroup.Unmarshal(m, b) -} -func (m *UserAppLogGroup) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_UserAppLogGroup.Marshal(b, m, deterministic) -} -func (dst *UserAppLogGroup) XXX_Merge(src proto.Message) { - xxx_messageInfo_UserAppLogGroup.Merge(dst, src) -} -func (m *UserAppLogGroup) XXX_Size() int { - return xxx_messageInfo_UserAppLogGroup.Size(m) -} -func (m *UserAppLogGroup) XXX_DiscardUnknown() { - xxx_messageInfo_UserAppLogGroup.DiscardUnknown(m) -} - -var xxx_messageInfo_UserAppLogGroup proto.InternalMessageInfo - -func (m *UserAppLogGroup) GetLogLine() []*UserAppLogLine { - if m != nil { - return m.LogLine - } - return nil -} - -type FlushRequest struct { - Logs []byte `protobuf:"bytes,1,opt,name=logs" json:"logs,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *FlushRequest) Reset() { *m = FlushRequest{} } -func (m *FlushRequest) String() string { return proto.CompactTextString(m) } -func (*FlushRequest) ProtoMessage() {} -func (*FlushRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_log_service_f054fd4b5012319d, []int{3} -} -func (m *FlushRequest) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_FlushRequest.Unmarshal(m, b) -} -func (m *FlushRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_FlushRequest.Marshal(b, m, deterministic) -} -func (dst *FlushRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_FlushRequest.Merge(dst, src) -} -func (m *FlushRequest) XXX_Size() int { - return xxx_messageInfo_FlushRequest.Size(m) -} -func (m *FlushRequest) XXX_DiscardUnknown() { - xxx_messageInfo_FlushRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_FlushRequest proto.InternalMessageInfo - -func (m *FlushRequest) GetLogs() []byte { - if m != nil { - return m.Logs - } - return nil -} - -type SetStatusRequest struct { - Status *string `protobuf:"bytes,1,req,name=status" json:"status,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *SetStatusRequest) Reset() { *m = SetStatusRequest{} } -func (m *SetStatusRequest) String() string { return proto.CompactTextString(m) } -func (*SetStatusRequest) ProtoMessage() {} -func (*SetStatusRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_log_service_f054fd4b5012319d, []int{4} -} -func (m *SetStatusRequest) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_SetStatusRequest.Unmarshal(m, b) -} -func (m *SetStatusRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_SetStatusRequest.Marshal(b, m, deterministic) -} -func (dst *SetStatusRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_SetStatusRequest.Merge(dst, src) -} -func (m *SetStatusRequest) XXX_Size() int { - return xxx_messageInfo_SetStatusRequest.Size(m) -} -func (m *SetStatusRequest) XXX_DiscardUnknown() { - xxx_messageInfo_SetStatusRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_SetStatusRequest proto.InternalMessageInfo - -func (m *SetStatusRequest) GetStatus() string { - if m != nil && m.Status != nil { - return *m.Status - } - return "" -} - -type LogOffset struct { - RequestId []byte `protobuf:"bytes,1,opt,name=request_id,json=requestId" json:"request_id,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *LogOffset) Reset() { *m = LogOffset{} } -func (m *LogOffset) String() string { return proto.CompactTextString(m) } -func (*LogOffset) ProtoMessage() {} -func (*LogOffset) Descriptor() ([]byte, []int) { - return fileDescriptor_log_service_f054fd4b5012319d, []int{5} -} -func (m *LogOffset) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_LogOffset.Unmarshal(m, b) -} -func (m *LogOffset) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_LogOffset.Marshal(b, m, deterministic) -} -func (dst *LogOffset) XXX_Merge(src proto.Message) { - xxx_messageInfo_LogOffset.Merge(dst, src) -} -func (m *LogOffset) XXX_Size() int { - return xxx_messageInfo_LogOffset.Size(m) -} -func (m *LogOffset) XXX_DiscardUnknown() { - xxx_messageInfo_LogOffset.DiscardUnknown(m) -} - -var xxx_messageInfo_LogOffset proto.InternalMessageInfo - -func (m *LogOffset) GetRequestId() []byte { - if m != nil { - return m.RequestId - } - return nil -} - -type LogLine struct { - Time *int64 `protobuf:"varint,1,req,name=time" json:"time,omitempty"` - Level *int32 `protobuf:"varint,2,req,name=level" json:"level,omitempty"` - LogMessage *string `protobuf:"bytes,3,req,name=log_message,json=logMessage" json:"log_message,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *LogLine) Reset() { *m = LogLine{} } -func (m *LogLine) String() string { return proto.CompactTextString(m) } -func (*LogLine) ProtoMessage() {} -func (*LogLine) Descriptor() ([]byte, []int) { - return fileDescriptor_log_service_f054fd4b5012319d, []int{6} -} -func (m *LogLine) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_LogLine.Unmarshal(m, b) -} -func (m *LogLine) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_LogLine.Marshal(b, m, deterministic) -} -func (dst *LogLine) XXX_Merge(src proto.Message) { - xxx_messageInfo_LogLine.Merge(dst, src) -} -func (m *LogLine) XXX_Size() int { - return xxx_messageInfo_LogLine.Size(m) -} -func (m *LogLine) XXX_DiscardUnknown() { - xxx_messageInfo_LogLine.DiscardUnknown(m) -} - -var xxx_messageInfo_LogLine proto.InternalMessageInfo - -func (m *LogLine) GetTime() int64 { - if m != nil && m.Time != nil { - return *m.Time - } - return 0 -} - -func (m *LogLine) GetLevel() int32 { - if m != nil && m.Level != nil { - return *m.Level - } - return 0 -} - -func (m *LogLine) GetLogMessage() string { - if m != nil && m.LogMessage != nil { - return *m.LogMessage - } - return "" -} - -type RequestLog struct { - AppId *string `protobuf:"bytes,1,req,name=app_id,json=appId" json:"app_id,omitempty"` - ModuleId *string `protobuf:"bytes,37,opt,name=module_id,json=moduleId,def=default" json:"module_id,omitempty"` - VersionId *string `protobuf:"bytes,2,req,name=version_id,json=versionId" json:"version_id,omitempty"` - RequestId []byte `protobuf:"bytes,3,req,name=request_id,json=requestId" json:"request_id,omitempty"` - Offset *LogOffset `protobuf:"bytes,35,opt,name=offset" json:"offset,omitempty"` - Ip *string `protobuf:"bytes,4,req,name=ip" json:"ip,omitempty"` - Nickname *string `protobuf:"bytes,5,opt,name=nickname" json:"nickname,omitempty"` - StartTime *int64 `protobuf:"varint,6,req,name=start_time,json=startTime" json:"start_time,omitempty"` - EndTime *int64 `protobuf:"varint,7,req,name=end_time,json=endTime" json:"end_time,omitempty"` - Latency *int64 `protobuf:"varint,8,req,name=latency" json:"latency,omitempty"` - Mcycles *int64 `protobuf:"varint,9,req,name=mcycles" json:"mcycles,omitempty"` - Method *string `protobuf:"bytes,10,req,name=method" json:"method,omitempty"` - Resource *string `protobuf:"bytes,11,req,name=resource" json:"resource,omitempty"` - HttpVersion *string `protobuf:"bytes,12,req,name=http_version,json=httpVersion" json:"http_version,omitempty"` - Status *int32 `protobuf:"varint,13,req,name=status" json:"status,omitempty"` - ResponseSize *int64 `protobuf:"varint,14,req,name=response_size,json=responseSize" json:"response_size,omitempty"` - Referrer *string `protobuf:"bytes,15,opt,name=referrer" json:"referrer,omitempty"` - UserAgent *string `protobuf:"bytes,16,opt,name=user_agent,json=userAgent" json:"user_agent,omitempty"` - UrlMapEntry *string `protobuf:"bytes,17,req,name=url_map_entry,json=urlMapEntry" json:"url_map_entry,omitempty"` - Combined *string `protobuf:"bytes,18,req,name=combined" json:"combined,omitempty"` - ApiMcycles *int64 `protobuf:"varint,19,opt,name=api_mcycles,json=apiMcycles" json:"api_mcycles,omitempty"` - Host *string `protobuf:"bytes,20,opt,name=host" json:"host,omitempty"` - Cost *float64 `protobuf:"fixed64,21,opt,name=cost" json:"cost,omitempty"` - TaskQueueName *string `protobuf:"bytes,22,opt,name=task_queue_name,json=taskQueueName" json:"task_queue_name,omitempty"` - TaskName *string `protobuf:"bytes,23,opt,name=task_name,json=taskName" json:"task_name,omitempty"` - WasLoadingRequest *bool `protobuf:"varint,24,opt,name=was_loading_request,json=wasLoadingRequest" json:"was_loading_request,omitempty"` - PendingTime *int64 `protobuf:"varint,25,opt,name=pending_time,json=pendingTime" json:"pending_time,omitempty"` - ReplicaIndex *int32 `protobuf:"varint,26,opt,name=replica_index,json=replicaIndex,def=-1" json:"replica_index,omitempty"` - Finished *bool `protobuf:"varint,27,opt,name=finished,def=1" json:"finished,omitempty"` - CloneKey []byte `protobuf:"bytes,28,opt,name=clone_key,json=cloneKey" json:"clone_key,omitempty"` - Line []*LogLine `protobuf:"bytes,29,rep,name=line" json:"line,omitempty"` - LinesIncomplete *bool `protobuf:"varint,36,opt,name=lines_incomplete,json=linesIncomplete" json:"lines_incomplete,omitempty"` - AppEngineRelease []byte `protobuf:"bytes,38,opt,name=app_engine_release,json=appEngineRelease" json:"app_engine_release,omitempty"` - ExitReason *int32 `protobuf:"varint,30,opt,name=exit_reason,json=exitReason" json:"exit_reason,omitempty"` - WasThrottledForTime *bool `protobuf:"varint,31,opt,name=was_throttled_for_time,json=wasThrottledForTime" json:"was_throttled_for_time,omitempty"` - WasThrottledForRequests *bool `protobuf:"varint,32,opt,name=was_throttled_for_requests,json=wasThrottledForRequests" json:"was_throttled_for_requests,omitempty"` - ThrottledTime *int64 `protobuf:"varint,33,opt,name=throttled_time,json=throttledTime" json:"throttled_time,omitempty"` - ServerName []byte `protobuf:"bytes,34,opt,name=server_name,json=serverName" json:"server_name,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *RequestLog) Reset() { *m = RequestLog{} } -func (m *RequestLog) String() string { return proto.CompactTextString(m) } -func (*RequestLog) ProtoMessage() {} -func (*RequestLog) Descriptor() ([]byte, []int) { - return fileDescriptor_log_service_f054fd4b5012319d, []int{7} -} -func (m *RequestLog) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_RequestLog.Unmarshal(m, b) -} -func (m *RequestLog) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_RequestLog.Marshal(b, m, deterministic) -} -func (dst *RequestLog) XXX_Merge(src proto.Message) { - xxx_messageInfo_RequestLog.Merge(dst, src) -} -func (m *RequestLog) XXX_Size() int { - return xxx_messageInfo_RequestLog.Size(m) -} -func (m *RequestLog) XXX_DiscardUnknown() { - xxx_messageInfo_RequestLog.DiscardUnknown(m) -} - -var xxx_messageInfo_RequestLog proto.InternalMessageInfo - -const Default_RequestLog_ModuleId string = "default" -const Default_RequestLog_ReplicaIndex int32 = -1 -const Default_RequestLog_Finished bool = true - -func (m *RequestLog) GetAppId() string { - if m != nil && m.AppId != nil { - return *m.AppId - } - return "" -} - -func (m *RequestLog) GetModuleId() string { - if m != nil && m.ModuleId != nil { - return *m.ModuleId - } - return Default_RequestLog_ModuleId -} - -func (m *RequestLog) GetVersionId() string { - if m != nil && m.VersionId != nil { - return *m.VersionId - } - return "" -} - -func (m *RequestLog) GetRequestId() []byte { - if m != nil { - return m.RequestId - } - return nil -} - -func (m *RequestLog) GetOffset() *LogOffset { - if m != nil { - return m.Offset - } - return nil -} - -func (m *RequestLog) GetIp() string { - if m != nil && m.Ip != nil { - return *m.Ip - } - return "" -} - -func (m *RequestLog) GetNickname() string { - if m != nil && m.Nickname != nil { - return *m.Nickname - } - return "" -} - -func (m *RequestLog) GetStartTime() int64 { - if m != nil && m.StartTime != nil { - return *m.StartTime - } - return 0 -} - -func (m *RequestLog) GetEndTime() int64 { - if m != nil && m.EndTime != nil { - return *m.EndTime - } - return 0 -} - -func (m *RequestLog) GetLatency() int64 { - if m != nil && m.Latency != nil { - return *m.Latency - } - return 0 -} - -func (m *RequestLog) GetMcycles() int64 { - if m != nil && m.Mcycles != nil { - return *m.Mcycles - } - return 0 -} - -func (m *RequestLog) GetMethod() string { - if m != nil && m.Method != nil { - return *m.Method - } - return "" -} - -func (m *RequestLog) GetResource() string { - if m != nil && m.Resource != nil { - return *m.Resource - } - return "" -} - -func (m *RequestLog) GetHttpVersion() string { - if m != nil && m.HttpVersion != nil { - return *m.HttpVersion - } - return "" -} - -func (m *RequestLog) GetStatus() int32 { - if m != nil && m.Status != nil { - return *m.Status - } - return 0 -} - -func (m *RequestLog) GetResponseSize() int64 { - if m != nil && m.ResponseSize != nil { - return *m.ResponseSize - } - return 0 -} - -func (m *RequestLog) GetReferrer() string { - if m != nil && m.Referrer != nil { - return *m.Referrer - } - return "" -} - -func (m *RequestLog) GetUserAgent() string { - if m != nil && m.UserAgent != nil { - return *m.UserAgent - } - return "" -} - -func (m *RequestLog) GetUrlMapEntry() string { - if m != nil && m.UrlMapEntry != nil { - return *m.UrlMapEntry - } - return "" -} - -func (m *RequestLog) GetCombined() string { - if m != nil && m.Combined != nil { - return *m.Combined - } - return "" -} - -func (m *RequestLog) GetApiMcycles() int64 { - if m != nil && m.ApiMcycles != nil { - return *m.ApiMcycles - } - return 0 -} - -func (m *RequestLog) GetHost() string { - if m != nil && m.Host != nil { - return *m.Host - } - return "" -} - -func (m *RequestLog) GetCost() float64 { - if m != nil && m.Cost != nil { - return *m.Cost - } - return 0 -} - -func (m *RequestLog) GetTaskQueueName() string { - if m != nil && m.TaskQueueName != nil { - return *m.TaskQueueName - } - return "" -} - -func (m *RequestLog) GetTaskName() string { - if m != nil && m.TaskName != nil { - return *m.TaskName - } - return "" -} - -func (m *RequestLog) GetWasLoadingRequest() bool { - if m != nil && m.WasLoadingRequest != nil { - return *m.WasLoadingRequest - } - return false -} - -func (m *RequestLog) GetPendingTime() int64 { - if m != nil && m.PendingTime != nil { - return *m.PendingTime - } - return 0 -} - -func (m *RequestLog) GetReplicaIndex() int32 { - if m != nil && m.ReplicaIndex != nil { - return *m.ReplicaIndex - } - return Default_RequestLog_ReplicaIndex -} - -func (m *RequestLog) GetFinished() bool { - if m != nil && m.Finished != nil { - return *m.Finished - } - return Default_RequestLog_Finished -} - -func (m *RequestLog) GetCloneKey() []byte { - if m != nil { - return m.CloneKey - } - return nil -} - -func (m *RequestLog) GetLine() []*LogLine { - if m != nil { - return m.Line - } - return nil -} - -func (m *RequestLog) GetLinesIncomplete() bool { - if m != nil && m.LinesIncomplete != nil { - return *m.LinesIncomplete - } - return false -} - -func (m *RequestLog) GetAppEngineRelease() []byte { - if m != nil { - return m.AppEngineRelease - } - return nil -} - -func (m *RequestLog) GetExitReason() int32 { - if m != nil && m.ExitReason != nil { - return *m.ExitReason - } - return 0 -} - -func (m *RequestLog) GetWasThrottledForTime() bool { - if m != nil && m.WasThrottledForTime != nil { - return *m.WasThrottledForTime - } - return false -} - -func (m *RequestLog) GetWasThrottledForRequests() bool { - if m != nil && m.WasThrottledForRequests != nil { - return *m.WasThrottledForRequests - } - return false -} - -func (m *RequestLog) GetThrottledTime() int64 { - if m != nil && m.ThrottledTime != nil { - return *m.ThrottledTime - } - return 0 -} - -func (m *RequestLog) GetServerName() []byte { - if m != nil { - return m.ServerName - } - return nil -} - -type LogModuleVersion struct { - ModuleId *string `protobuf:"bytes,1,opt,name=module_id,json=moduleId,def=default" json:"module_id,omitempty"` - VersionId *string `protobuf:"bytes,2,opt,name=version_id,json=versionId" json:"version_id,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *LogModuleVersion) Reset() { *m = LogModuleVersion{} } -func (m *LogModuleVersion) String() string { return proto.CompactTextString(m) } -func (*LogModuleVersion) ProtoMessage() {} -func (*LogModuleVersion) Descriptor() ([]byte, []int) { - return fileDescriptor_log_service_f054fd4b5012319d, []int{8} -} -func (m *LogModuleVersion) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_LogModuleVersion.Unmarshal(m, b) -} -func (m *LogModuleVersion) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_LogModuleVersion.Marshal(b, m, deterministic) -} -func (dst *LogModuleVersion) XXX_Merge(src proto.Message) { - xxx_messageInfo_LogModuleVersion.Merge(dst, src) -} -func (m *LogModuleVersion) XXX_Size() int { - return xxx_messageInfo_LogModuleVersion.Size(m) -} -func (m *LogModuleVersion) XXX_DiscardUnknown() { - xxx_messageInfo_LogModuleVersion.DiscardUnknown(m) -} - -var xxx_messageInfo_LogModuleVersion proto.InternalMessageInfo - -const Default_LogModuleVersion_ModuleId string = "default" - -func (m *LogModuleVersion) GetModuleId() string { - if m != nil && m.ModuleId != nil { - return *m.ModuleId - } - return Default_LogModuleVersion_ModuleId -} - -func (m *LogModuleVersion) GetVersionId() string { - if m != nil && m.VersionId != nil { - return *m.VersionId - } - return "" -} - -type LogReadRequest struct { - AppId *string `protobuf:"bytes,1,req,name=app_id,json=appId" json:"app_id,omitempty"` - VersionId []string `protobuf:"bytes,2,rep,name=version_id,json=versionId" json:"version_id,omitempty"` - ModuleVersion []*LogModuleVersion `protobuf:"bytes,19,rep,name=module_version,json=moduleVersion" json:"module_version,omitempty"` - StartTime *int64 `protobuf:"varint,3,opt,name=start_time,json=startTime" json:"start_time,omitempty"` - EndTime *int64 `protobuf:"varint,4,opt,name=end_time,json=endTime" json:"end_time,omitempty"` - Offset *LogOffset `protobuf:"bytes,5,opt,name=offset" json:"offset,omitempty"` - RequestId [][]byte `protobuf:"bytes,6,rep,name=request_id,json=requestId" json:"request_id,omitempty"` - MinimumLogLevel *int32 `protobuf:"varint,7,opt,name=minimum_log_level,json=minimumLogLevel" json:"minimum_log_level,omitempty"` - IncludeIncomplete *bool `protobuf:"varint,8,opt,name=include_incomplete,json=includeIncomplete" json:"include_incomplete,omitempty"` - Count *int64 `protobuf:"varint,9,opt,name=count" json:"count,omitempty"` - CombinedLogRegex *string `protobuf:"bytes,14,opt,name=combined_log_regex,json=combinedLogRegex" json:"combined_log_regex,omitempty"` - HostRegex *string `protobuf:"bytes,15,opt,name=host_regex,json=hostRegex" json:"host_regex,omitempty"` - ReplicaIndex *int32 `protobuf:"varint,16,opt,name=replica_index,json=replicaIndex" json:"replica_index,omitempty"` - IncludeAppLogs *bool `protobuf:"varint,10,opt,name=include_app_logs,json=includeAppLogs" json:"include_app_logs,omitempty"` - AppLogsPerRequest *int32 `protobuf:"varint,17,opt,name=app_logs_per_request,json=appLogsPerRequest" json:"app_logs_per_request,omitempty"` - IncludeHost *bool `protobuf:"varint,11,opt,name=include_host,json=includeHost" json:"include_host,omitempty"` - IncludeAll *bool `protobuf:"varint,12,opt,name=include_all,json=includeAll" json:"include_all,omitempty"` - CacheIterator *bool `protobuf:"varint,13,opt,name=cache_iterator,json=cacheIterator" json:"cache_iterator,omitempty"` - NumShards *int32 `protobuf:"varint,18,opt,name=num_shards,json=numShards" json:"num_shards,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *LogReadRequest) Reset() { *m = LogReadRequest{} } -func (m *LogReadRequest) String() string { return proto.CompactTextString(m) } -func (*LogReadRequest) ProtoMessage() {} -func (*LogReadRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_log_service_f054fd4b5012319d, []int{9} -} -func (m *LogReadRequest) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_LogReadRequest.Unmarshal(m, b) -} -func (m *LogReadRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_LogReadRequest.Marshal(b, m, deterministic) -} -func (dst *LogReadRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_LogReadRequest.Merge(dst, src) -} -func (m *LogReadRequest) XXX_Size() int { - return xxx_messageInfo_LogReadRequest.Size(m) -} -func (m *LogReadRequest) XXX_DiscardUnknown() { - xxx_messageInfo_LogReadRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_LogReadRequest proto.InternalMessageInfo - -func (m *LogReadRequest) GetAppId() string { - if m != nil && m.AppId != nil { - return *m.AppId - } - return "" -} - -func (m *LogReadRequest) GetVersionId() []string { - if m != nil { - return m.VersionId - } - return nil -} - -func (m *LogReadRequest) GetModuleVersion() []*LogModuleVersion { - if m != nil { - return m.ModuleVersion - } - return nil -} - -func (m *LogReadRequest) GetStartTime() int64 { - if m != nil && m.StartTime != nil { - return *m.StartTime - } - return 0 -} - -func (m *LogReadRequest) GetEndTime() int64 { - if m != nil && m.EndTime != nil { - return *m.EndTime - } - return 0 -} - -func (m *LogReadRequest) GetOffset() *LogOffset { - if m != nil { - return m.Offset - } - return nil -} - -func (m *LogReadRequest) GetRequestId() [][]byte { - if m != nil { - return m.RequestId - } - return nil -} - -func (m *LogReadRequest) GetMinimumLogLevel() int32 { - if m != nil && m.MinimumLogLevel != nil { - return *m.MinimumLogLevel - } - return 0 -} - -func (m *LogReadRequest) GetIncludeIncomplete() bool { - if m != nil && m.IncludeIncomplete != nil { - return *m.IncludeIncomplete - } - return false -} - -func (m *LogReadRequest) GetCount() int64 { - if m != nil && m.Count != nil { - return *m.Count - } - return 0 -} - -func (m *LogReadRequest) GetCombinedLogRegex() string { - if m != nil && m.CombinedLogRegex != nil { - return *m.CombinedLogRegex - } - return "" -} - -func (m *LogReadRequest) GetHostRegex() string { - if m != nil && m.HostRegex != nil { - return *m.HostRegex - } - return "" -} - -func (m *LogReadRequest) GetReplicaIndex() int32 { - if m != nil && m.ReplicaIndex != nil { - return *m.ReplicaIndex - } - return 0 -} - -func (m *LogReadRequest) GetIncludeAppLogs() bool { - if m != nil && m.IncludeAppLogs != nil { - return *m.IncludeAppLogs - } - return false -} - -func (m *LogReadRequest) GetAppLogsPerRequest() int32 { - if m != nil && m.AppLogsPerRequest != nil { - return *m.AppLogsPerRequest - } - return 0 -} - -func (m *LogReadRequest) GetIncludeHost() bool { - if m != nil && m.IncludeHost != nil { - return *m.IncludeHost - } - return false -} - -func (m *LogReadRequest) GetIncludeAll() bool { - if m != nil && m.IncludeAll != nil { - return *m.IncludeAll - } - return false -} - -func (m *LogReadRequest) GetCacheIterator() bool { - if m != nil && m.CacheIterator != nil { - return *m.CacheIterator - } - return false -} - -func (m *LogReadRequest) GetNumShards() int32 { - if m != nil && m.NumShards != nil { - return *m.NumShards - } - return 0 -} - -type LogReadResponse struct { - Log []*RequestLog `protobuf:"bytes,1,rep,name=log" json:"log,omitempty"` - Offset *LogOffset `protobuf:"bytes,2,opt,name=offset" json:"offset,omitempty"` - LastEndTime *int64 `protobuf:"varint,3,opt,name=last_end_time,json=lastEndTime" json:"last_end_time,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *LogReadResponse) Reset() { *m = LogReadResponse{} } -func (m *LogReadResponse) String() string { return proto.CompactTextString(m) } -func (*LogReadResponse) ProtoMessage() {} -func (*LogReadResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_log_service_f054fd4b5012319d, []int{10} -} -func (m *LogReadResponse) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_LogReadResponse.Unmarshal(m, b) -} -func (m *LogReadResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_LogReadResponse.Marshal(b, m, deterministic) -} -func (dst *LogReadResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_LogReadResponse.Merge(dst, src) -} -func (m *LogReadResponse) XXX_Size() int { - return xxx_messageInfo_LogReadResponse.Size(m) -} -func (m *LogReadResponse) XXX_DiscardUnknown() { - xxx_messageInfo_LogReadResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_LogReadResponse proto.InternalMessageInfo - -func (m *LogReadResponse) GetLog() []*RequestLog { - if m != nil { - return m.Log - } - return nil -} - -func (m *LogReadResponse) GetOffset() *LogOffset { - if m != nil { - return m.Offset - } - return nil -} - -func (m *LogReadResponse) GetLastEndTime() int64 { - if m != nil && m.LastEndTime != nil { - return *m.LastEndTime - } - return 0 -} - -type LogUsageRecord struct { - VersionId *string `protobuf:"bytes,1,opt,name=version_id,json=versionId" json:"version_id,omitempty"` - StartTime *int32 `protobuf:"varint,2,opt,name=start_time,json=startTime" json:"start_time,omitempty"` - EndTime *int32 `protobuf:"varint,3,opt,name=end_time,json=endTime" json:"end_time,omitempty"` - Count *int64 `protobuf:"varint,4,opt,name=count" json:"count,omitempty"` - TotalSize *int64 `protobuf:"varint,5,opt,name=total_size,json=totalSize" json:"total_size,omitempty"` - Records *int32 `protobuf:"varint,6,opt,name=records" json:"records,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *LogUsageRecord) Reset() { *m = LogUsageRecord{} } -func (m *LogUsageRecord) String() string { return proto.CompactTextString(m) } -func (*LogUsageRecord) ProtoMessage() {} -func (*LogUsageRecord) Descriptor() ([]byte, []int) { - return fileDescriptor_log_service_f054fd4b5012319d, []int{11} -} -func (m *LogUsageRecord) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_LogUsageRecord.Unmarshal(m, b) -} -func (m *LogUsageRecord) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_LogUsageRecord.Marshal(b, m, deterministic) -} -func (dst *LogUsageRecord) XXX_Merge(src proto.Message) { - xxx_messageInfo_LogUsageRecord.Merge(dst, src) -} -func (m *LogUsageRecord) XXX_Size() int { - return xxx_messageInfo_LogUsageRecord.Size(m) -} -func (m *LogUsageRecord) XXX_DiscardUnknown() { - xxx_messageInfo_LogUsageRecord.DiscardUnknown(m) -} - -var xxx_messageInfo_LogUsageRecord proto.InternalMessageInfo - -func (m *LogUsageRecord) GetVersionId() string { - if m != nil && m.VersionId != nil { - return *m.VersionId - } - return "" -} - -func (m *LogUsageRecord) GetStartTime() int32 { - if m != nil && m.StartTime != nil { - return *m.StartTime - } - return 0 -} - -func (m *LogUsageRecord) GetEndTime() int32 { - if m != nil && m.EndTime != nil { - return *m.EndTime - } - return 0 -} - -func (m *LogUsageRecord) GetCount() int64 { - if m != nil && m.Count != nil { - return *m.Count - } - return 0 -} - -func (m *LogUsageRecord) GetTotalSize() int64 { - if m != nil && m.TotalSize != nil { - return *m.TotalSize - } - return 0 -} - -func (m *LogUsageRecord) GetRecords() int32 { - if m != nil && m.Records != nil { - return *m.Records - } - return 0 -} - -type LogUsageRequest struct { - AppId *string `protobuf:"bytes,1,req,name=app_id,json=appId" json:"app_id,omitempty"` - VersionId []string `protobuf:"bytes,2,rep,name=version_id,json=versionId" json:"version_id,omitempty"` - StartTime *int32 `protobuf:"varint,3,opt,name=start_time,json=startTime" json:"start_time,omitempty"` - EndTime *int32 `protobuf:"varint,4,opt,name=end_time,json=endTime" json:"end_time,omitempty"` - ResolutionHours *uint32 `protobuf:"varint,5,opt,name=resolution_hours,json=resolutionHours,def=1" json:"resolution_hours,omitempty"` - CombineVersions *bool `protobuf:"varint,6,opt,name=combine_versions,json=combineVersions" json:"combine_versions,omitempty"` - UsageVersion *int32 `protobuf:"varint,7,opt,name=usage_version,json=usageVersion" json:"usage_version,omitempty"` - VersionsOnly *bool `protobuf:"varint,8,opt,name=versions_only,json=versionsOnly" json:"versions_only,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *LogUsageRequest) Reset() { *m = LogUsageRequest{} } -func (m *LogUsageRequest) String() string { return proto.CompactTextString(m) } -func (*LogUsageRequest) ProtoMessage() {} -func (*LogUsageRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_log_service_f054fd4b5012319d, []int{12} -} -func (m *LogUsageRequest) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_LogUsageRequest.Unmarshal(m, b) -} -func (m *LogUsageRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_LogUsageRequest.Marshal(b, m, deterministic) -} -func (dst *LogUsageRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_LogUsageRequest.Merge(dst, src) -} -func (m *LogUsageRequest) XXX_Size() int { - return xxx_messageInfo_LogUsageRequest.Size(m) -} -func (m *LogUsageRequest) XXX_DiscardUnknown() { - xxx_messageInfo_LogUsageRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_LogUsageRequest proto.InternalMessageInfo - -const Default_LogUsageRequest_ResolutionHours uint32 = 1 - -func (m *LogUsageRequest) GetAppId() string { - if m != nil && m.AppId != nil { - return *m.AppId - } - return "" -} - -func (m *LogUsageRequest) GetVersionId() []string { - if m != nil { - return m.VersionId - } - return nil -} - -func (m *LogUsageRequest) GetStartTime() int32 { - if m != nil && m.StartTime != nil { - return *m.StartTime - } - return 0 -} - -func (m *LogUsageRequest) GetEndTime() int32 { - if m != nil && m.EndTime != nil { - return *m.EndTime - } - return 0 -} - -func (m *LogUsageRequest) GetResolutionHours() uint32 { - if m != nil && m.ResolutionHours != nil { - return *m.ResolutionHours - } - return Default_LogUsageRequest_ResolutionHours -} - -func (m *LogUsageRequest) GetCombineVersions() bool { - if m != nil && m.CombineVersions != nil { - return *m.CombineVersions - } - return false -} - -func (m *LogUsageRequest) GetUsageVersion() int32 { - if m != nil && m.UsageVersion != nil { - return *m.UsageVersion - } - return 0 -} - -func (m *LogUsageRequest) GetVersionsOnly() bool { - if m != nil && m.VersionsOnly != nil { - return *m.VersionsOnly - } - return false -} - -type LogUsageResponse struct { - Usage []*LogUsageRecord `protobuf:"bytes,1,rep,name=usage" json:"usage,omitempty"` - Summary *LogUsageRecord `protobuf:"bytes,2,opt,name=summary" json:"summary,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *LogUsageResponse) Reset() { *m = LogUsageResponse{} } -func (m *LogUsageResponse) String() string { return proto.CompactTextString(m) } -func (*LogUsageResponse) ProtoMessage() {} -func (*LogUsageResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_log_service_f054fd4b5012319d, []int{13} -} -func (m *LogUsageResponse) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_LogUsageResponse.Unmarshal(m, b) -} -func (m *LogUsageResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_LogUsageResponse.Marshal(b, m, deterministic) -} -func (dst *LogUsageResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_LogUsageResponse.Merge(dst, src) -} -func (m *LogUsageResponse) XXX_Size() int { - return xxx_messageInfo_LogUsageResponse.Size(m) -} -func (m *LogUsageResponse) XXX_DiscardUnknown() { - xxx_messageInfo_LogUsageResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_LogUsageResponse proto.InternalMessageInfo - -func (m *LogUsageResponse) GetUsage() []*LogUsageRecord { - if m != nil { - return m.Usage - } - return nil -} - -func (m *LogUsageResponse) GetSummary() *LogUsageRecord { - if m != nil { - return m.Summary - } - return nil -} - -func init() { - proto.RegisterType((*LogServiceError)(nil), "appengine.LogServiceError") - proto.RegisterType((*UserAppLogLine)(nil), "appengine.UserAppLogLine") - proto.RegisterType((*UserAppLogGroup)(nil), "appengine.UserAppLogGroup") - proto.RegisterType((*FlushRequest)(nil), "appengine.FlushRequest") - proto.RegisterType((*SetStatusRequest)(nil), "appengine.SetStatusRequest") - proto.RegisterType((*LogOffset)(nil), "appengine.LogOffset") - proto.RegisterType((*LogLine)(nil), "appengine.LogLine") - proto.RegisterType((*RequestLog)(nil), "appengine.RequestLog") - proto.RegisterType((*LogModuleVersion)(nil), "appengine.LogModuleVersion") - proto.RegisterType((*LogReadRequest)(nil), "appengine.LogReadRequest") - proto.RegisterType((*LogReadResponse)(nil), "appengine.LogReadResponse") - proto.RegisterType((*LogUsageRecord)(nil), "appengine.LogUsageRecord") - proto.RegisterType((*LogUsageRequest)(nil), "appengine.LogUsageRequest") - proto.RegisterType((*LogUsageResponse)(nil), "appengine.LogUsageResponse") -} - -func init() { - proto.RegisterFile("google.golang.org/appengine/internal/log/log_service.proto", fileDescriptor_log_service_f054fd4b5012319d) -} - -var fileDescriptor_log_service_f054fd4b5012319d = []byte{ - // 1553 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x56, 0xdd, 0x72, 0xdb, 0xc6, - 0x15, 0x2e, 0x48, 0x51, 0x24, 0x0f, 0x49, 0x91, 0x5a, 0xcb, 0xce, 0xda, 0xae, 0x6b, 0x1a, 0x4e, - 0x1c, 0xd6, 0x93, 0x48, 0x93, 0xa4, 0x57, 0xca, 0x95, 0xd3, 0x2a, 0x8e, 0x26, 0xb4, 0xd5, 0x40, - 0x72, 0x3a, 0xd3, 0x1b, 0x0c, 0x0a, 0x1c, 0x81, 0x18, 0x2f, 0xb1, 0xc8, 0xee, 0xc2, 0x91, 0x72, - 0xdb, 0xdb, 0x3e, 0x46, 0x1f, 0xa2, 0xaf, 0xd2, 0xb7, 0xe9, 0xec, 0xd9, 0x05, 0x44, 0x2a, 0x4d, - 0xc6, 0x33, 0xb9, 0xe0, 0x10, 0xfb, 0x9d, 0x83, 0xdd, 0xf3, 0xf3, 0x9d, 0x6f, 0x01, 0xc7, 0xb9, - 0x94, 0xb9, 0xc0, 0xc3, 0x5c, 0x8a, 0xa4, 0xcc, 0x0f, 0xa5, 0xca, 0x8f, 0x92, 0xaa, 0xc2, 0x32, - 0x2f, 0x4a, 0x3c, 0x2a, 0x4a, 0x83, 0xaa, 0x4c, 0xc4, 0x91, 0x90, 0xb9, 0xfd, 0xc5, 0x1a, 0xd5, - 0xbb, 0x22, 0xc5, 0xc3, 0x4a, 0x49, 0x23, 0xd9, 0xb0, 0xf5, 0x0c, 0x5f, 0xc3, 0x74, 0x29, 0xf3, - 0x73, 0x67, 0x3e, 0x51, 0x4a, 0xaa, 0xf0, 0x4b, 0x18, 0xd2, 0xc3, 0x9f, 0x65, 0x86, 0x6c, 0x17, - 0x3a, 0x67, 0xdf, 0xce, 0x7e, 0xc7, 0xee, 0xc0, 0xf4, 0xf4, 0xf5, 0xf7, 0x2f, 0x96, 0xa7, 0x7f, - 0x89, 0xa3, 0x93, 0xef, 0xde, 0x9c, 0x9c, 0x5f, 0xcc, 0x02, 0xb6, 0x0f, 0x93, 0xf3, 0x8b, 0xb3, - 0xe8, 0xc5, 0xcb, 0x93, 0xf8, 0x24, 0x8a, 0xce, 0xa2, 0x59, 0x27, 0xcc, 0x61, 0xef, 0x8d, 0x46, - 0xf5, 0xa2, 0xaa, 0x96, 0x32, 0x5f, 0x16, 0x25, 0xb2, 0x8f, 0x60, 0xcf, 0x14, 0x6b, 0xd4, 0x26, - 0x59, 0x57, 0x71, 0xad, 0x31, 0xe5, 0xc1, 0xbc, 0xb3, 0xe8, 0x46, 0x93, 0x16, 0x7d, 0xa3, 0x31, - 0x65, 0x07, 0xd0, 0x13, 0xf8, 0x0e, 0x05, 0xef, 0x90, 0xd5, 0x2d, 0x18, 0x87, 0xfe, 0x1a, 0xb5, - 0x4e, 0x72, 0xe4, 0xdd, 0x79, 0x67, 0x31, 0x8c, 0x9a, 0x65, 0xf8, 0x12, 0xa6, 0x37, 0x07, 0xbd, - 0x54, 0xb2, 0xae, 0xd8, 0x9f, 0x60, 0x60, 0x73, 0x15, 0x45, 0x89, 0xbc, 0x33, 0xef, 0x2e, 0x46, - 0x9f, 0xdf, 0x3f, 0x6c, 0x33, 0x3d, 0xdc, 0x0e, 0x2b, 0xea, 0x0b, 0xf7, 0x10, 0x86, 0x30, 0xfe, - 0x5a, 0xd4, 0x7a, 0x15, 0xe1, 0x0f, 0x35, 0x6a, 0xc3, 0x18, 0xec, 0x08, 0x99, 0x6b, 0x1e, 0xcc, - 0x83, 0xc5, 0x38, 0xa2, 0xe7, 0xf0, 0x39, 0xcc, 0xce, 0xd1, 0x9c, 0x9b, 0xc4, 0xd4, 0xba, 0xf1, - 0xbb, 0x07, 0xbb, 0x9a, 0x00, 0xca, 0x67, 0x18, 0xf9, 0x55, 0xf8, 0x1c, 0x86, 0x4b, 0x99, 0x9f, - 0x5d, 0x5e, 0x6a, 0x34, 0xec, 0x11, 0x80, 0x72, 0xfe, 0x71, 0x91, 0xf9, 0x2d, 0x87, 0x1e, 0x39, - 0xcd, 0xc2, 0x0b, 0xe8, 0x37, 0x65, 0x62, 0xb0, 0x63, 0x0b, 0xe2, 0x8b, 0x43, 0xcf, 0xdb, 0x35, - 0xe9, 0x35, 0x35, 0x79, 0x0c, 0x23, 0x9b, 0xe6, 0x76, 0x5d, 0x40, 0xc8, 0xfc, 0x95, 0x2f, 0xcd, - 0x3f, 0x01, 0xc0, 0x47, 0xb9, 0x94, 0x39, 0xbb, 0x0b, 0xbb, 0x49, 0x55, 0xb9, 0xf3, 0xad, 0x6b, - 0x2f, 0xa9, 0xaa, 0xd3, 0x8c, 0x7d, 0x08, 0xc3, 0xb5, 0xcc, 0x6a, 0x81, 0xd6, 0xf2, 0xd1, 0x3c, - 0x58, 0x0c, 0x8f, 0xfb, 0x19, 0x5e, 0x26, 0xb5, 0x30, 0xd1, 0xc0, 0x59, 0x4e, 0x33, 0x9b, 0xc0, - 0x3b, 0x54, 0xba, 0x90, 0xa5, 0x75, 0xeb, 0xd0, 0x06, 0x43, 0x8f, 0x38, 0xf3, 0x46, 0x7e, 0x36, - 0x94, 0xcd, 0xfc, 0xd8, 0x27, 0xb0, 0x2b, 0xa9, 0x10, 0xfc, 0xe9, 0x3c, 0x58, 0x8c, 0x3e, 0x3f, - 0xd8, 0xe8, 0x47, 0x5b, 0xa4, 0xc8, 0xfb, 0xb0, 0x3d, 0xe8, 0x14, 0x15, 0xdf, 0xa1, 0x33, 0x3a, - 0x45, 0xc5, 0x1e, 0xc0, 0xa0, 0x2c, 0xd2, 0xb7, 0x65, 0xb2, 0x46, 0xde, 0xb3, 0x01, 0x46, 0xed, - 0xda, 0x1e, 0xac, 0x4d, 0xa2, 0x4c, 0x4c, 0x45, 0xdb, 0xa5, 0xa2, 0x0d, 0x09, 0xb9, 0xb0, 0x95, - 0xbb, 0x0f, 0x03, 0x2c, 0x33, 0x67, 0xec, 0x93, 0xb1, 0x8f, 0x65, 0x46, 0x26, 0x0e, 0x7d, 0x91, - 0x18, 0x2c, 0xd3, 0x6b, 0x3e, 0x70, 0x16, 0xbf, 0x24, 0xb2, 0xa5, 0xd7, 0xa9, 0x40, 0xcd, 0x87, - 0xce, 0xe2, 0x97, 0xb6, 0xd7, 0x6b, 0x34, 0x2b, 0x99, 0x71, 0x70, 0xbd, 0x76, 0x2b, 0x1b, 0xa1, - 0x42, 0x2d, 0x6b, 0x95, 0x22, 0x1f, 0x91, 0xa5, 0x5d, 0xb3, 0x27, 0x30, 0x5e, 0x19, 0x53, 0xc5, - 0xbe, 0x58, 0x7c, 0x4c, 0xf6, 0x91, 0xc5, 0xbe, 0x77, 0xd0, 0x06, 0x85, 0x26, 0xd4, 0x60, 0xbf, - 0x62, 0x4f, 0x61, 0xa2, 0x50, 0x57, 0xb2, 0xd4, 0x18, 0xeb, 0xe2, 0x27, 0xe4, 0x7b, 0x14, 0xce, - 0xb8, 0x01, 0xcf, 0x8b, 0x9f, 0xd0, 0x9d, 0x7d, 0x89, 0x4a, 0xa1, 0xe2, 0x53, 0x57, 0x9d, 0x66, - 0x6d, 0xab, 0x53, 0x6b, 0x54, 0x71, 0x92, 0x63, 0x69, 0xf8, 0x8c, 0xac, 0x43, 0x8b, 0xbc, 0xb0, - 0x00, 0x0b, 0x61, 0x52, 0x2b, 0x11, 0xaf, 0x93, 0x2a, 0xc6, 0xd2, 0xa8, 0x6b, 0xbe, 0xef, 0x62, - 0xab, 0x95, 0x78, 0x95, 0x54, 0x27, 0x16, 0xb2, 0xdb, 0xa7, 0x72, 0xfd, 0x8f, 0xa2, 0xc4, 0x8c, - 0x33, 0x97, 0x5a, 0xb3, 0xb6, 0x0c, 0x4c, 0xaa, 0x22, 0x6e, 0x8a, 0x75, 0x67, 0x1e, 0x2c, 0xba, - 0x11, 0x24, 0x55, 0xf1, 0xca, 0xd7, 0x8b, 0xc1, 0xce, 0x4a, 0x6a, 0xc3, 0x0f, 0xe8, 0x64, 0x7a, - 0xb6, 0x58, 0x6a, 0xb1, 0xbb, 0xf3, 0x60, 0x11, 0x44, 0xf4, 0xcc, 0x9e, 0xc1, 0xd4, 0x24, 0xfa, - 0x6d, 0xfc, 0x43, 0x8d, 0x35, 0xc6, 0xd4, 0xe8, 0x7b, 0xf4, 0xca, 0xc4, 0xc2, 0xdf, 0x59, 0xf4, - 0xb5, 0xed, 0xf6, 0x43, 0x18, 0x92, 0x1f, 0x79, 0x7c, 0xe0, 0x92, 0xb5, 0x00, 0x19, 0x0f, 0xe1, - 0xce, 0x8f, 0x89, 0x8e, 0x85, 0x4c, 0xb2, 0xa2, 0xcc, 0x63, 0xcf, 0x3e, 0xce, 0xe7, 0xc1, 0x62, - 0x10, 0xed, 0xff, 0x98, 0xe8, 0xa5, 0xb3, 0x34, 0x83, 0xfb, 0x04, 0xc6, 0x15, 0x96, 0xe4, 0x4b, - 0xfc, 0xb8, 0x4f, 0xe1, 0x8f, 0x3c, 0x46, 0x1c, 0xf9, 0xd8, 0x36, 0xa0, 0x12, 0x45, 0x9a, 0xc4, - 0x45, 0x99, 0xe1, 0x15, 0x7f, 0x30, 0x0f, 0x16, 0xbd, 0xe3, 0xce, 0xa7, 0x9f, 0xd9, 0x26, 0x90, - 0xe1, 0xd4, 0xe2, 0x6c, 0x0e, 0x83, 0xcb, 0xa2, 0x2c, 0xf4, 0x0a, 0x33, 0xfe, 0xd0, 0x1e, 0x78, - 0xbc, 0x63, 0x54, 0x8d, 0x51, 0x8b, 0xda, 0xd0, 0x53, 0x21, 0x4b, 0x8c, 0xdf, 0xe2, 0x35, 0xff, - 0x3d, 0x09, 0xc0, 0x80, 0x80, 0x6f, 0xf1, 0x9a, 0x3d, 0x83, 0x1d, 0x52, 0xab, 0x47, 0xa4, 0x56, - 0x6c, 0x7b, 0x3a, 0x48, 0xa6, 0xc8, 0xce, 0xfe, 0x08, 0x33, 0xfb, 0xaf, 0xe3, 0xa2, 0x4c, 0xe5, - 0xba, 0x12, 0x68, 0x90, 0x7f, 0x48, 0xf9, 0x4d, 0x09, 0x3f, 0x6d, 0x61, 0xf6, 0x09, 0x30, 0x3b, - 0xed, 0x6e, 0x9b, 0x58, 0xa1, 0xc0, 0x44, 0x23, 0x7f, 0x46, 0x07, 0xcf, 0x92, 0xaa, 0x3a, 0x21, - 0x43, 0xe4, 0x70, 0xdb, 0x49, 0xbc, 0x2a, 0x4c, 0xac, 0x30, 0xd1, 0xb2, 0xe4, 0x7f, 0xb0, 0x69, - 0x46, 0x60, 0xa1, 0x88, 0x10, 0xf6, 0x05, 0xdc, 0xb3, 0xc5, 0x35, 0x2b, 0x25, 0x8d, 0x11, 0x98, - 0xc5, 0x97, 0x52, 0xb9, 0xb2, 0x3d, 0xa6, 0xf3, 0x6d, 0xe9, 0x2f, 0x1a, 0xe3, 0xd7, 0x52, 0x51, - 0xf9, 0xbe, 0x84, 0x07, 0x3f, 0x7f, 0xc9, 0xf7, 0x45, 0xf3, 0x39, 0xbd, 0xf8, 0xc1, 0xad, 0x17, - 0x7d, 0x77, 0x34, 0xdd, 0x17, 0xed, 0x8b, 0x74, 0xd2, 0x13, 0x6a, 0xd0, 0xa4, 0x45, 0xe9, 0x8c, - 0xc7, 0x30, 0xb2, 0x97, 0x1a, 0x2a, 0x47, 0x8a, 0x90, 0x12, 0x04, 0x07, 0x59, 0x5a, 0x84, 0x7f, - 0x83, 0xd9, 0x52, 0xe6, 0xaf, 0x48, 0xc8, 0x9a, 0x81, 0xdb, 0xd2, 0xbc, 0xe0, 0x7d, 0x35, 0x2f, - 0xd8, 0xd2, 0xbc, 0xf0, 0xbf, 0x3d, 0xd8, 0x5b, 0xca, 0x3c, 0xc2, 0x24, 0x6b, 0x28, 0xf5, 0x0b, - 0x12, 0x7b, 0x7b, 0xa3, 0xee, 0xb6, 0x78, 0x7e, 0x05, 0x7b, 0x3e, 0x9a, 0x46, 0x23, 0xee, 0x10, - 0x0f, 0x1e, 0x6e, 0xf3, 0x60, 0x2b, 0x85, 0x68, 0xb2, 0xde, 0xca, 0x68, 0x5b, 0x07, 0xbb, 0x54, - 0xa9, 0x5f, 0xd0, 0xc1, 0x1d, 0x32, 0xb6, 0x3a, 0x78, 0xa3, 0xcd, 0xbd, 0xf7, 0xd0, 0xe6, 0x6d, - 0xa1, 0xdf, 0x9d, 0x77, 0xb7, 0x85, 0xfe, 0x39, 0xec, 0xaf, 0x8b, 0xb2, 0x58, 0xd7, 0xeb, 0x98, - 0xae, 0x60, 0xba, 0xb5, 0xfa, 0xc4, 0xa6, 0xa9, 0x37, 0x58, 0x46, 0xd3, 0xfd, 0xf5, 0x29, 0xb0, - 0xa2, 0x4c, 0x45, 0x9d, 0xe1, 0x26, 0x9d, 0x07, 0x6e, 0x5c, 0xbd, 0x65, 0x83, 0xd0, 0x07, 0xd0, - 0x4b, 0x65, 0x5d, 0x1a, 0x3e, 0xa4, 0xf8, 0xdd, 0xc2, 0xd2, 0xbc, 0x91, 0x23, 0x3a, 0x51, 0x61, - 0x8e, 0x57, 0x7c, 0x8f, 0x7a, 0x35, 0x6b, 0x2c, 0xd4, 0xa5, 0x1c, 0xaf, 0x6c, 0xf4, 0x56, 0x83, - 0xbc, 0x97, 0x53, 0xcb, 0xa1, 0x45, 0x9c, 0xf9, 0xe9, 0xed, 0x71, 0x9f, 0x51, 0xe4, 0xdb, 0xa3, - 0xbe, 0x80, 0x59, 0x13, 0xb6, 0xed, 0x35, 0x7d, 0x23, 0x00, 0x05, 0xbd, 0xe7, 0x71, 0xf7, 0x75, - 0xa1, 0xd9, 0x11, 0x1c, 0x34, 0x1e, 0x71, 0x85, 0x2d, 0xf3, 0xf9, 0x3e, 0xed, 0xba, 0x9f, 0x38, - 0xb7, 0xbf, 0xa2, 0xda, 0x50, 0xa4, 0x66, 0x6b, 0x92, 0xcd, 0x11, 0x6d, 0x3b, 0xf2, 0xd8, 0x37, - 0x56, 0x29, 0x1f, 0xc3, 0xa8, 0x3d, 0x5d, 0x08, 0x3e, 0x26, 0x0f, 0x68, 0x0e, 0x16, 0xc2, 0x8e, - 0x4d, 0x9a, 0xa4, 0x2b, 0x8c, 0x0b, 0x83, 0x2a, 0x31, 0x52, 0xf1, 0x09, 0xf9, 0x4c, 0x08, 0x3d, - 0xf5, 0xa0, 0xad, 0x44, 0x59, 0xaf, 0x63, 0xbd, 0x4a, 0x54, 0xa6, 0x39, 0xa3, 0x88, 0x86, 0x65, - 0xbd, 0x3e, 0x27, 0x20, 0xfc, 0x57, 0x40, 0xdf, 0x83, 0x8e, 0xdb, 0xee, 0xb2, 0x61, 0x1f, 0x43, - 0x57, 0xc8, 0x9c, 0x07, 0xc4, 0xcd, 0xbb, 0x1b, 0x2c, 0xb9, 0xf9, 0xc6, 0x88, 0xac, 0xc7, 0x06, - 0xa3, 0x3a, 0xef, 0xc1, 0xa8, 0x10, 0x26, 0x22, 0xd1, 0x26, 0x6e, 0xf9, 0xe9, 0xc8, 0x3b, 0xb2, - 0xe0, 0x89, 0xe3, 0x68, 0xf8, 0x9f, 0x80, 0x46, 0xed, 0x8d, 0xfd, 0xac, 0x89, 0x30, 0x95, 0xea, - 0xf6, 0x4c, 0x05, 0xb7, 0x86, 0xf3, 0xd6, 0x3c, 0x74, 0x5c, 0x7e, 0xff, 0x7f, 0x1e, 0xba, 0x64, - 0x6c, 0xe7, 0xa1, 0xe5, 0xd9, 0xce, 0x26, 0xcf, 0x1e, 0x01, 0x18, 0x69, 0x12, 0xe1, 0xee, 0xe1, - 0x9e, 0x9b, 0x2f, 0x42, 0xe8, 0x12, 0xe6, 0xd0, 0x57, 0x14, 0x97, 0xe6, 0xbb, 0x6e, 0x3b, 0xbf, - 0x0c, 0xff, 0xdd, 0xa1, 0x4a, 0xfa, 0xd0, 0x7f, 0x8b, 0x4c, 0xfc, 0x7c, 0xc4, 0x7b, 0xbf, 0x36, - 0xe2, 0xbd, 0xcd, 0x11, 0x9f, 0xd9, 0xcf, 0x11, 0x51, 0x1b, 0xbb, 0xf7, 0x4a, 0xd6, 0x4a, 0x53, - 0x0a, 0x93, 0xe3, 0xe0, 0xb3, 0x68, 0x7a, 0x63, 0xfa, 0xc6, 0x5a, 0xec, 0x25, 0xe3, 0x07, 0xa7, - 0xd1, 0x23, 0x97, 0xd4, 0x20, 0x9a, 0x7a, 0xdc, 0x8b, 0x0e, 0x7d, 0xa0, 0xd4, 0x36, 0xb1, 0x56, - 0xb8, 0xdc, 0xa8, 0x8f, 0x09, 0x6c, 0xa4, 0xe9, 0x29, 0x4c, 0x9a, 0x7d, 0x62, 0x59, 0x8a, 0x6b, - 0x3f, 0xe2, 0xe3, 0x06, 0x3c, 0x2b, 0xc5, 0x75, 0x78, 0x45, 0x2a, 0xed, 0xab, 0xe4, 0x09, 0x77, - 0x04, 0x3d, 0xda, 0xc8, 0x53, 0xee, 0xfe, 0x36, 0x8d, 0x36, 0xc8, 0x10, 0x39, 0x3f, 0xf6, 0x05, - 0xf4, 0x75, 0xbd, 0x5e, 0x27, 0xea, 0xda, 0x33, 0xef, 0x57, 0x5e, 0x69, 0x3c, 0xbf, 0xea, 0xfd, - 0xdd, 0x92, 0xf6, 0x7f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x70, 0xd9, 0xa0, 0xf8, 0x48, 0x0d, 0x00, - 0x00, -} diff --git a/vendor/google.golang.org/appengine/internal/log/log_service.proto b/vendor/google.golang.org/appengine/internal/log/log_service.proto deleted file mode 100644 index 8981dc475..000000000 --- a/vendor/google.golang.org/appengine/internal/log/log_service.proto +++ /dev/null @@ -1,150 +0,0 @@ -syntax = "proto2"; -option go_package = "log"; - -package appengine; - -message LogServiceError { - enum ErrorCode { - OK = 0; - INVALID_REQUEST = 1; - STORAGE_ERROR = 2; - } -} - -message UserAppLogLine { - required int64 timestamp_usec = 1; - required int64 level = 2; - required string message = 3; -} - -message UserAppLogGroup { - repeated UserAppLogLine log_line = 2; -} - -message FlushRequest { - optional bytes logs = 1; -} - -message SetStatusRequest { - required string status = 1; -} - - -message LogOffset { - optional bytes request_id = 1; -} - -message LogLine { - required int64 time = 1; - required int32 level = 2; - required string log_message = 3; -} - -message RequestLog { - required string app_id = 1; - optional string module_id = 37 [default="default"]; - required string version_id = 2; - required bytes request_id = 3; - optional LogOffset offset = 35; - required string ip = 4; - optional string nickname = 5; - required int64 start_time = 6; - required int64 end_time = 7; - required int64 latency = 8; - required int64 mcycles = 9; - required string method = 10; - required string resource = 11; - required string http_version = 12; - required int32 status = 13; - required int64 response_size = 14; - optional string referrer = 15; - optional string user_agent = 16; - required string url_map_entry = 17; - required string combined = 18; - optional int64 api_mcycles = 19; - optional string host = 20; - optional double cost = 21; - - optional string task_queue_name = 22; - optional string task_name = 23; - - optional bool was_loading_request = 24; - optional int64 pending_time = 25; - optional int32 replica_index = 26 [default = -1]; - optional bool finished = 27 [default = true]; - optional bytes clone_key = 28; - - repeated LogLine line = 29; - - optional bool lines_incomplete = 36; - optional bytes app_engine_release = 38; - - optional int32 exit_reason = 30; - optional bool was_throttled_for_time = 31; - optional bool was_throttled_for_requests = 32; - optional int64 throttled_time = 33; - - optional bytes server_name = 34; -} - -message LogModuleVersion { - optional string module_id = 1 [default="default"]; - optional string version_id = 2; -} - -message LogReadRequest { - required string app_id = 1; - repeated string version_id = 2; - repeated LogModuleVersion module_version = 19; - - optional int64 start_time = 3; - optional int64 end_time = 4; - optional LogOffset offset = 5; - repeated bytes request_id = 6; - - optional int32 minimum_log_level = 7; - optional bool include_incomplete = 8; - optional int64 count = 9; - - optional string combined_log_regex = 14; - optional string host_regex = 15; - optional int32 replica_index = 16; - - optional bool include_app_logs = 10; - optional int32 app_logs_per_request = 17; - optional bool include_host = 11; - optional bool include_all = 12; - optional bool cache_iterator = 13; - optional int32 num_shards = 18; -} - -message LogReadResponse { - repeated RequestLog log = 1; - optional LogOffset offset = 2; - optional int64 last_end_time = 3; -} - -message LogUsageRecord { - optional string version_id = 1; - optional int32 start_time = 2; - optional int32 end_time = 3; - optional int64 count = 4; - optional int64 total_size = 5; - optional int32 records = 6; -} - -message LogUsageRequest { - required string app_id = 1; - repeated string version_id = 2; - optional int32 start_time = 3; - optional int32 end_time = 4; - optional uint32 resolution_hours = 5 [default = 1]; - optional bool combine_versions = 6; - optional int32 usage_version = 7; - optional bool versions_only = 8; -} - -message LogUsageResponse { - repeated LogUsageRecord usage = 1; - optional LogUsageRecord summary = 2; -} diff --git a/vendor/google.golang.org/appengine/internal/main.go b/vendor/google.golang.org/appengine/internal/main.go deleted file mode 100644 index afd0ae84f..000000000 --- a/vendor/google.golang.org/appengine/internal/main.go +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2011 Google Inc. All rights reserved. -// Use of this source code is governed by the Apache 2.0 -// license that can be found in the LICENSE file. - -//go:build appengine -// +build appengine - -package internal - -import ( - "appengine_internal" -) - -func Main() { - MainPath = "" - appengine_internal.Main() -} diff --git a/vendor/google.golang.org/appengine/internal/main_common.go b/vendor/google.golang.org/appengine/internal/main_common.go deleted file mode 100644 index 357dce4dd..000000000 --- a/vendor/google.golang.org/appengine/internal/main_common.go +++ /dev/null @@ -1,7 +0,0 @@ -package internal - -// MainPath stores the file path of the main package. On App Engine Standard -// using Go version 1.9 and below, this will be unset. On App Engine Flex and -// App Engine Standard second-gen (Go 1.11 and above), this will be the -// filepath to package main. -var MainPath string diff --git a/vendor/google.golang.org/appengine/internal/main_vm.go b/vendor/google.golang.org/appengine/internal/main_vm.go deleted file mode 100644 index 86a8caf06..000000000 --- a/vendor/google.golang.org/appengine/internal/main_vm.go +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright 2011 Google Inc. All rights reserved. -// Use of this source code is governed by the Apache 2.0 -// license that can be found in the LICENSE file. - -//go:build !appengine -// +build !appengine - -package internal - -import ( - "io" - "log" - "net/http" - "net/url" - "os" - "path/filepath" - "runtime" -) - -func Main() { - MainPath = filepath.Dir(findMainPath()) - installHealthChecker(http.DefaultServeMux) - - port := "8080" - if s := os.Getenv("PORT"); s != "" { - port = s - } - - host := "" - if IsDevAppServer() { - host = "127.0.0.1" - } - if err := http.ListenAndServe(host+":"+port, Middleware(http.DefaultServeMux)); err != nil { - log.Fatalf("http.ListenAndServe: %v", err) - } -} - -// Find the path to package main by looking at the root Caller. -func findMainPath() string { - pc := make([]uintptr, 100) - n := runtime.Callers(2, pc) - frames := runtime.CallersFrames(pc[:n]) - for { - frame, more := frames.Next() - // Tests won't have package main, instead they have testing.tRunner - if frame.Function == "main.main" || frame.Function == "testing.tRunner" { - return frame.File - } - if !more { - break - } - } - return "" -} - -func installHealthChecker(mux *http.ServeMux) { - // If no health check handler has been installed by this point, add a trivial one. - const healthPath = "/_ah/health" - hreq := &http.Request{ - Method: "GET", - URL: &url.URL{ - Path: healthPath, - }, - } - if _, pat := mux.Handler(hreq); pat != healthPath { - mux.HandleFunc(healthPath, func(w http.ResponseWriter, r *http.Request) { - io.WriteString(w, "ok") - }) - } -} diff --git a/vendor/google.golang.org/appengine/internal/metadata.go b/vendor/google.golang.org/appengine/internal/metadata.go deleted file mode 100644 index c4ba63bb4..000000000 --- a/vendor/google.golang.org/appengine/internal/metadata.go +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright 2014 Google Inc. All rights reserved. -// Use of this source code is governed by the Apache 2.0 -// license that can be found in the LICENSE file. - -package internal - -// This file has code for accessing metadata. -// -// References: -// https://cloud.google.com/compute/docs/metadata - -import ( - "fmt" - "io/ioutil" - "net/http" - "net/url" -) - -const ( - metadataHost = "metadata" - metadataPath = "/computeMetadata/v1/" -) - -var ( - metadataRequestHeaders = http.Header{ - "Metadata-Flavor": []string{"Google"}, - } -) - -// TODO(dsymonds): Do we need to support default values, like Python? -func mustGetMetadata(key string) []byte { - b, err := getMetadata(key) - if err != nil { - panic(fmt.Sprintf("Metadata fetch failed for '%s': %v", key, err)) - } - return b -} - -func getMetadata(key string) ([]byte, error) { - // TODO(dsymonds): May need to use url.Parse to support keys with query args. - req := &http.Request{ - Method: "GET", - URL: &url.URL{ - Scheme: "http", - Host: metadataHost, - Path: metadataPath + key, - }, - Header: metadataRequestHeaders, - Host: metadataHost, - } - resp, err := http.DefaultClient.Do(req) - if err != nil { - return nil, err - } - defer resp.Body.Close() - if resp.StatusCode != 200 { - return nil, fmt.Errorf("metadata server returned HTTP %d", resp.StatusCode) - } - return ioutil.ReadAll(resp.Body) -} diff --git a/vendor/google.golang.org/appengine/internal/net.go b/vendor/google.golang.org/appengine/internal/net.go deleted file mode 100644 index fe429720e..000000000 --- a/vendor/google.golang.org/appengine/internal/net.go +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2014 Google Inc. All rights reserved. -// Use of this source code is governed by the Apache 2.0 -// license that can be found in the LICENSE file. - -package internal - -// This file implements a network dialer that limits the number of concurrent connections. -// It is only used for API calls. - -import ( - "log" - "net" - "runtime" - "sync" - "time" -) - -var limitSem = make(chan int, 100) // TODO(dsymonds): Use environment variable. - -func limitRelease() { - // non-blocking - select { - case <-limitSem: - default: - // This should not normally happen. - log.Print("appengine: unbalanced limitSem release!") - } -} - -func limitDial(network, addr string) (net.Conn, error) { - limitSem <- 1 - - // Dial with a timeout in case the API host is MIA. - // The connection should normally be very fast. - conn, err := net.DialTimeout(network, addr, 10*time.Second) - if err != nil { - limitRelease() - return nil, err - } - lc := &limitConn{Conn: conn} - runtime.SetFinalizer(lc, (*limitConn).Close) // shouldn't usually be required - return lc, nil -} - -type limitConn struct { - close sync.Once - net.Conn -} - -func (lc *limitConn) Close() error { - defer lc.close.Do(func() { - limitRelease() - runtime.SetFinalizer(lc, nil) - }) - return lc.Conn.Close() -} diff --git a/vendor/google.golang.org/appengine/internal/regen.sh b/vendor/google.golang.org/appengine/internal/regen.sh deleted file mode 100644 index 2fdb546a6..000000000 --- a/vendor/google.golang.org/appengine/internal/regen.sh +++ /dev/null @@ -1,40 +0,0 @@ -#!/bin/bash -e -# -# This script rebuilds the generated code for the protocol buffers. -# To run this you will need protoc and goprotobuf installed; -# see https://github.com/golang/protobuf for instructions. - -PKG=google.golang.org/appengine - -function die() { - echo 1>&2 $* - exit 1 -} - -# Sanity check that the right tools are accessible. -for tool in go protoc protoc-gen-go; do - q=$(which $tool) || die "didn't find $tool" - echo 1>&2 "$tool: $q" -done - -echo -n 1>&2 "finding package dir... " -pkgdir=$(go list -f '{{.Dir}}' $PKG) -echo 1>&2 $pkgdir -base=$(echo $pkgdir | sed "s,/$PKG\$,,") -echo 1>&2 "base: $base" -cd $base - -# Run protoc once per package. -for dir in $(find $PKG/internal -name '*.proto' | xargs dirname | sort | uniq); do - echo 1>&2 "* $dir" - protoc --go_out=. $dir/*.proto -done - -for f in $(find $PKG/internal -name '*.pb.go'); do - # Remove proto.RegisterEnum calls. - # These cause duplicate registration panics when these packages - # are used on classic App Engine. proto.RegisterEnum only affects - # parsing the text format; we don't care about that. - # https://code.google.com/p/googleappengine/issues/detail?id=11670#c17 - sed -i '/proto.RegisterEnum/d' $f -done diff --git a/vendor/google.golang.org/appengine/internal/remote_api/remote_api.pb.go b/vendor/google.golang.org/appengine/internal/remote_api/remote_api.pb.go deleted file mode 100644 index 8d782a38e..000000000 --- a/vendor/google.golang.org/appengine/internal/remote_api/remote_api.pb.go +++ /dev/null @@ -1,361 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// source: google.golang.org/appengine/internal/remote_api/remote_api.proto - -package remote_api - -import proto "github.com/golang/protobuf/proto" -import fmt "fmt" -import math "math" - -// Reference imports to suppress errors if they are not otherwise used. -var _ = proto.Marshal -var _ = fmt.Errorf -var _ = math.Inf - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the proto package it is being compiled against. -// A compilation error at this line likely means your copy of the -// proto package needs to be updated. -const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package - -type RpcError_ErrorCode int32 - -const ( - RpcError_UNKNOWN RpcError_ErrorCode = 0 - RpcError_CALL_NOT_FOUND RpcError_ErrorCode = 1 - RpcError_PARSE_ERROR RpcError_ErrorCode = 2 - RpcError_SECURITY_VIOLATION RpcError_ErrorCode = 3 - RpcError_OVER_QUOTA RpcError_ErrorCode = 4 - RpcError_REQUEST_TOO_LARGE RpcError_ErrorCode = 5 - RpcError_CAPABILITY_DISABLED RpcError_ErrorCode = 6 - RpcError_FEATURE_DISABLED RpcError_ErrorCode = 7 - RpcError_BAD_REQUEST RpcError_ErrorCode = 8 - RpcError_RESPONSE_TOO_LARGE RpcError_ErrorCode = 9 - RpcError_CANCELLED RpcError_ErrorCode = 10 - RpcError_REPLAY_ERROR RpcError_ErrorCode = 11 - RpcError_DEADLINE_EXCEEDED RpcError_ErrorCode = 12 -) - -var RpcError_ErrorCode_name = map[int32]string{ - 0: "UNKNOWN", - 1: "CALL_NOT_FOUND", - 2: "PARSE_ERROR", - 3: "SECURITY_VIOLATION", - 4: "OVER_QUOTA", - 5: "REQUEST_TOO_LARGE", - 6: "CAPABILITY_DISABLED", - 7: "FEATURE_DISABLED", - 8: "BAD_REQUEST", - 9: "RESPONSE_TOO_LARGE", - 10: "CANCELLED", - 11: "REPLAY_ERROR", - 12: "DEADLINE_EXCEEDED", -} -var RpcError_ErrorCode_value = map[string]int32{ - "UNKNOWN": 0, - "CALL_NOT_FOUND": 1, - "PARSE_ERROR": 2, - "SECURITY_VIOLATION": 3, - "OVER_QUOTA": 4, - "REQUEST_TOO_LARGE": 5, - "CAPABILITY_DISABLED": 6, - "FEATURE_DISABLED": 7, - "BAD_REQUEST": 8, - "RESPONSE_TOO_LARGE": 9, - "CANCELLED": 10, - "REPLAY_ERROR": 11, - "DEADLINE_EXCEEDED": 12, -} - -func (x RpcError_ErrorCode) Enum() *RpcError_ErrorCode { - p := new(RpcError_ErrorCode) - *p = x - return p -} -func (x RpcError_ErrorCode) String() string { - return proto.EnumName(RpcError_ErrorCode_name, int32(x)) -} -func (x *RpcError_ErrorCode) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(RpcError_ErrorCode_value, data, "RpcError_ErrorCode") - if err != nil { - return err - } - *x = RpcError_ErrorCode(value) - return nil -} -func (RpcError_ErrorCode) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_remote_api_1978114ec33a273d, []int{2, 0} -} - -type Request struct { - ServiceName *string `protobuf:"bytes,2,req,name=service_name,json=serviceName" json:"service_name,omitempty"` - Method *string `protobuf:"bytes,3,req,name=method" json:"method,omitempty"` - Request []byte `protobuf:"bytes,4,req,name=request" json:"request,omitempty"` - RequestId *string `protobuf:"bytes,5,opt,name=request_id,json=requestId" json:"request_id,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *Request) Reset() { *m = Request{} } -func (m *Request) String() string { return proto.CompactTextString(m) } -func (*Request) ProtoMessage() {} -func (*Request) Descriptor() ([]byte, []int) { - return fileDescriptor_remote_api_1978114ec33a273d, []int{0} -} -func (m *Request) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_Request.Unmarshal(m, b) -} -func (m *Request) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_Request.Marshal(b, m, deterministic) -} -func (dst *Request) XXX_Merge(src proto.Message) { - xxx_messageInfo_Request.Merge(dst, src) -} -func (m *Request) XXX_Size() int { - return xxx_messageInfo_Request.Size(m) -} -func (m *Request) XXX_DiscardUnknown() { - xxx_messageInfo_Request.DiscardUnknown(m) -} - -var xxx_messageInfo_Request proto.InternalMessageInfo - -func (m *Request) GetServiceName() string { - if m != nil && m.ServiceName != nil { - return *m.ServiceName - } - return "" -} - -func (m *Request) GetMethod() string { - if m != nil && m.Method != nil { - return *m.Method - } - return "" -} - -func (m *Request) GetRequest() []byte { - if m != nil { - return m.Request - } - return nil -} - -func (m *Request) GetRequestId() string { - if m != nil && m.RequestId != nil { - return *m.RequestId - } - return "" -} - -type ApplicationError struct { - Code *int32 `protobuf:"varint,1,req,name=code" json:"code,omitempty"` - Detail *string `protobuf:"bytes,2,req,name=detail" json:"detail,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *ApplicationError) Reset() { *m = ApplicationError{} } -func (m *ApplicationError) String() string { return proto.CompactTextString(m) } -func (*ApplicationError) ProtoMessage() {} -func (*ApplicationError) Descriptor() ([]byte, []int) { - return fileDescriptor_remote_api_1978114ec33a273d, []int{1} -} -func (m *ApplicationError) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_ApplicationError.Unmarshal(m, b) -} -func (m *ApplicationError) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_ApplicationError.Marshal(b, m, deterministic) -} -func (dst *ApplicationError) XXX_Merge(src proto.Message) { - xxx_messageInfo_ApplicationError.Merge(dst, src) -} -func (m *ApplicationError) XXX_Size() int { - return xxx_messageInfo_ApplicationError.Size(m) -} -func (m *ApplicationError) XXX_DiscardUnknown() { - xxx_messageInfo_ApplicationError.DiscardUnknown(m) -} - -var xxx_messageInfo_ApplicationError proto.InternalMessageInfo - -func (m *ApplicationError) GetCode() int32 { - if m != nil && m.Code != nil { - return *m.Code - } - return 0 -} - -func (m *ApplicationError) GetDetail() string { - if m != nil && m.Detail != nil { - return *m.Detail - } - return "" -} - -type RpcError struct { - Code *int32 `protobuf:"varint,1,req,name=code" json:"code,omitempty"` - Detail *string `protobuf:"bytes,2,opt,name=detail" json:"detail,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *RpcError) Reset() { *m = RpcError{} } -func (m *RpcError) String() string { return proto.CompactTextString(m) } -func (*RpcError) ProtoMessage() {} -func (*RpcError) Descriptor() ([]byte, []int) { - return fileDescriptor_remote_api_1978114ec33a273d, []int{2} -} -func (m *RpcError) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_RpcError.Unmarshal(m, b) -} -func (m *RpcError) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_RpcError.Marshal(b, m, deterministic) -} -func (dst *RpcError) XXX_Merge(src proto.Message) { - xxx_messageInfo_RpcError.Merge(dst, src) -} -func (m *RpcError) XXX_Size() int { - return xxx_messageInfo_RpcError.Size(m) -} -func (m *RpcError) XXX_DiscardUnknown() { - xxx_messageInfo_RpcError.DiscardUnknown(m) -} - -var xxx_messageInfo_RpcError proto.InternalMessageInfo - -func (m *RpcError) GetCode() int32 { - if m != nil && m.Code != nil { - return *m.Code - } - return 0 -} - -func (m *RpcError) GetDetail() string { - if m != nil && m.Detail != nil { - return *m.Detail - } - return "" -} - -type Response struct { - Response []byte `protobuf:"bytes,1,opt,name=response" json:"response,omitempty"` - Exception []byte `protobuf:"bytes,2,opt,name=exception" json:"exception,omitempty"` - ApplicationError *ApplicationError `protobuf:"bytes,3,opt,name=application_error,json=applicationError" json:"application_error,omitempty"` - JavaException []byte `protobuf:"bytes,4,opt,name=java_exception,json=javaException" json:"java_exception,omitempty"` - RpcError *RpcError `protobuf:"bytes,5,opt,name=rpc_error,json=rpcError" json:"rpc_error,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *Response) Reset() { *m = Response{} } -func (m *Response) String() string { return proto.CompactTextString(m) } -func (*Response) ProtoMessage() {} -func (*Response) Descriptor() ([]byte, []int) { - return fileDescriptor_remote_api_1978114ec33a273d, []int{3} -} -func (m *Response) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_Response.Unmarshal(m, b) -} -func (m *Response) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_Response.Marshal(b, m, deterministic) -} -func (dst *Response) XXX_Merge(src proto.Message) { - xxx_messageInfo_Response.Merge(dst, src) -} -func (m *Response) XXX_Size() int { - return xxx_messageInfo_Response.Size(m) -} -func (m *Response) XXX_DiscardUnknown() { - xxx_messageInfo_Response.DiscardUnknown(m) -} - -var xxx_messageInfo_Response proto.InternalMessageInfo - -func (m *Response) GetResponse() []byte { - if m != nil { - return m.Response - } - return nil -} - -func (m *Response) GetException() []byte { - if m != nil { - return m.Exception - } - return nil -} - -func (m *Response) GetApplicationError() *ApplicationError { - if m != nil { - return m.ApplicationError - } - return nil -} - -func (m *Response) GetJavaException() []byte { - if m != nil { - return m.JavaException - } - return nil -} - -func (m *Response) GetRpcError() *RpcError { - if m != nil { - return m.RpcError - } - return nil -} - -func init() { - proto.RegisterType((*Request)(nil), "remote_api.Request") - proto.RegisterType((*ApplicationError)(nil), "remote_api.ApplicationError") - proto.RegisterType((*RpcError)(nil), "remote_api.RpcError") - proto.RegisterType((*Response)(nil), "remote_api.Response") -} - -func init() { - proto.RegisterFile("google.golang.org/appengine/internal/remote_api/remote_api.proto", fileDescriptor_remote_api_1978114ec33a273d) -} - -var fileDescriptor_remote_api_1978114ec33a273d = []byte{ - // 531 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x93, 0x51, 0x6e, 0xd3, 0x40, - 0x10, 0x86, 0xb1, 0x9b, 0x34, 0xf1, 0xc4, 0x2d, 0xdb, 0xa5, 0x14, 0x0b, 0x15, 0x29, 0x44, 0x42, - 0xca, 0x53, 0x2a, 0x38, 0x00, 0x62, 0x63, 0x6f, 0x91, 0x85, 0x65, 0xa7, 0x6b, 0xbb, 0x50, 0x5e, - 0x56, 0x2b, 0x67, 0x65, 0x8c, 0x12, 0xaf, 0xd9, 0x98, 0x8a, 0x17, 0x6e, 0xc0, 0xb5, 0x38, 0x0c, - 0xb7, 0x40, 0x36, 0x6e, 0x63, 0xf5, 0x89, 0xb7, 0x7f, 0x7e, 0x7b, 0xe6, 0x1b, 0xcd, 0xcc, 0xc2, - 0xbb, 0x5c, 0xa9, 0x7c, 0x23, 0x17, 0xb9, 0xda, 0x88, 0x32, 0x5f, 0x28, 0x9d, 0x5f, 0x88, 0xaa, - 0x92, 0x65, 0x5e, 0x94, 0xf2, 0xa2, 0x28, 0x6b, 0xa9, 0x4b, 0xb1, 0xb9, 0xd0, 0x72, 0xab, 0x6a, - 0xc9, 0x45, 0x55, 0xf4, 0xe4, 0xa2, 0xd2, 0xaa, 0x56, 0x18, 0xf6, 0xce, 0xec, 0x27, 0x8c, 0x98, - 0xfc, 0xf6, 0x5d, 0xee, 0x6a, 0xfc, 0x12, 0xec, 0x9d, 0xd4, 0xb7, 0x45, 0x26, 0x79, 0x29, 0xb6, - 0xd2, 0x31, 0xa7, 0xe6, 0xdc, 0x62, 0x93, 0xce, 0x0b, 0xc5, 0x56, 0xe2, 0x33, 0x38, 0xdc, 0xca, - 0xfa, 0x8b, 0x5a, 0x3b, 0x07, 0xed, 0xc7, 0x2e, 0xc2, 0x0e, 0x8c, 0xf4, 0xbf, 0x2a, 0xce, 0x60, - 0x6a, 0xce, 0x6d, 0x76, 0x17, 0xe2, 0x17, 0x00, 0x9d, 0xe4, 0xc5, 0xda, 0x19, 0x4e, 0x8d, 0xb9, - 0xc5, 0xac, 0xce, 0xf1, 0xd7, 0xb3, 0xb7, 0x80, 0x48, 0x55, 0x6d, 0x8a, 0x4c, 0xd4, 0x85, 0x2a, - 0xa9, 0xd6, 0x4a, 0x63, 0x0c, 0x83, 0x4c, 0xad, 0xa5, 0x63, 0x4c, 0xcd, 0xf9, 0x90, 0xb5, 0xba, - 0x01, 0xaf, 0x65, 0x2d, 0x8a, 0x4d, 0xd7, 0x55, 0x17, 0xcd, 0x7e, 0x9b, 0x30, 0x66, 0x55, 0xf6, - 0x7f, 0x89, 0x46, 0x2f, 0xf1, 0x97, 0x09, 0x56, 0x9b, 0xe5, 0x36, 0x7f, 0x4d, 0x60, 0x94, 0x86, - 0x1f, 0xc2, 0xe8, 0x63, 0x88, 0x1e, 0x61, 0x0c, 0xc7, 0x2e, 0x09, 0x02, 0x1e, 0x46, 0x09, 0xbf, - 0x8c, 0xd2, 0xd0, 0x43, 0x06, 0x7e, 0x0c, 0x93, 0x15, 0x61, 0x31, 0xe5, 0x94, 0xb1, 0x88, 0x21, - 0x13, 0x9f, 0x01, 0x8e, 0xa9, 0x9b, 0x32, 0x3f, 0xb9, 0xe1, 0xd7, 0x7e, 0x14, 0x90, 0xc4, 0x8f, - 0x42, 0x74, 0x80, 0x8f, 0x01, 0xa2, 0x6b, 0xca, 0xf8, 0x55, 0x1a, 0x25, 0x04, 0x0d, 0xf0, 0x53, - 0x38, 0x61, 0xf4, 0x2a, 0xa5, 0x71, 0xc2, 0x93, 0x28, 0xe2, 0x01, 0x61, 0xef, 0x29, 0x1a, 0xe2, - 0x67, 0xf0, 0xc4, 0x25, 0x2b, 0xb2, 0xf4, 0x83, 0xa6, 0x80, 0xe7, 0xc7, 0x64, 0x19, 0x50, 0x0f, - 0x1d, 0xe2, 0x53, 0x40, 0x97, 0x94, 0x24, 0x29, 0xa3, 0x7b, 0x77, 0xd4, 0xe0, 0x97, 0xc4, 0xe3, - 0x5d, 0x25, 0x34, 0x6e, 0xf0, 0x8c, 0xc6, 0xab, 0x28, 0x8c, 0x69, 0xaf, 0xae, 0x85, 0x8f, 0xc0, - 0x72, 0x49, 0xe8, 0xd2, 0xa0, 0xc9, 0x03, 0x8c, 0xc0, 0x66, 0x74, 0x15, 0x90, 0x9b, 0xae, 0xef, - 0x49, 0xd3, 0x8f, 0x47, 0x89, 0x17, 0xf8, 0x21, 0xe5, 0xf4, 0x93, 0x4b, 0xa9, 0x47, 0x3d, 0x64, - 0xcf, 0xfe, 0x18, 0x30, 0x66, 0x72, 0x57, 0xa9, 0x72, 0x27, 0xf1, 0x73, 0x18, 0xeb, 0x4e, 0x3b, - 0xc6, 0xd4, 0x98, 0xdb, 0xec, 0x3e, 0xc6, 0xe7, 0x60, 0xc9, 0x1f, 0x99, 0xac, 0x9a, 0x75, 0xb5, - 0x23, 0xb5, 0xd9, 0xde, 0xc0, 0x3e, 0x9c, 0x88, 0xfd, 0x3a, 0xb9, 0x6c, 0x06, 0xec, 0x1c, 0x4c, - 0x8d, 0xf9, 0xe4, 0xcd, 0xf9, 0xa2, 0x77, 0x87, 0x0f, 0x77, 0xce, 0x90, 0x78, 0x78, 0x05, 0xaf, - 0xe0, 0xf8, 0xab, 0xb8, 0x15, 0x7c, 0x4f, 0x1b, 0xb4, 0xb4, 0xa3, 0xc6, 0xa5, 0xf7, 0xc4, 0xd7, - 0x60, 0xe9, 0x2a, 0xeb, 0x48, 0xc3, 0x96, 0x74, 0xda, 0x27, 0xdd, 0x1d, 0x07, 0x1b, 0xeb, 0x4e, - 0x2d, 0xed, 0xcf, 0xbd, 0x07, 0xf0, 0x37, 0x00, 0x00, 0xff, 0xff, 0x38, 0xd1, 0x0f, 0x22, 0x4f, - 0x03, 0x00, 0x00, -} diff --git a/vendor/google.golang.org/appengine/internal/remote_api/remote_api.proto b/vendor/google.golang.org/appengine/internal/remote_api/remote_api.proto deleted file mode 100644 index f21763a4e..000000000 --- a/vendor/google.golang.org/appengine/internal/remote_api/remote_api.proto +++ /dev/null @@ -1,44 +0,0 @@ -syntax = "proto2"; -option go_package = "remote_api"; - -package remote_api; - -message Request { - required string service_name = 2; - required string method = 3; - required bytes request = 4; - optional string request_id = 5; -} - -message ApplicationError { - required int32 code = 1; - required string detail = 2; -} - -message RpcError { - enum ErrorCode { - UNKNOWN = 0; - CALL_NOT_FOUND = 1; - PARSE_ERROR = 2; - SECURITY_VIOLATION = 3; - OVER_QUOTA = 4; - REQUEST_TOO_LARGE = 5; - CAPABILITY_DISABLED = 6; - FEATURE_DISABLED = 7; - BAD_REQUEST = 8; - RESPONSE_TOO_LARGE = 9; - CANCELLED = 10; - REPLAY_ERROR = 11; - DEADLINE_EXCEEDED = 12; - } - required int32 code = 1; - optional string detail = 2; -} - -message Response { - optional bytes response = 1; - optional bytes exception = 2; - optional ApplicationError application_error = 3; - optional bytes java_exception = 4; - optional RpcError rpc_error = 5; -} diff --git a/vendor/google.golang.org/appengine/internal/transaction.go b/vendor/google.golang.org/appengine/internal/transaction.go deleted file mode 100644 index 2ae8ab9fa..000000000 --- a/vendor/google.golang.org/appengine/internal/transaction.go +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright 2014 Google Inc. All rights reserved. -// Use of this source code is governed by the Apache 2.0 -// license that can be found in the LICENSE file. - -package internal - -// This file implements hooks for applying datastore transactions. - -import ( - "context" - "errors" - "reflect" - - "github.com/golang/protobuf/proto" - - basepb "google.golang.org/appengine/internal/base" - pb "google.golang.org/appengine/internal/datastore" -) - -var transactionSetters = make(map[reflect.Type]reflect.Value) - -// RegisterTransactionSetter registers a function that sets transaction information -// in a protocol buffer message. f should be a function with two arguments, -// the first being a protocol buffer type, and the second being *datastore.Transaction. -func RegisterTransactionSetter(f interface{}) { - v := reflect.ValueOf(f) - transactionSetters[v.Type().In(0)] = v -} - -// applyTransaction applies the transaction t to message pb -// by using the relevant setter passed to RegisterTransactionSetter. -func applyTransaction(pb proto.Message, t *pb.Transaction) { - v := reflect.ValueOf(pb) - if f, ok := transactionSetters[v.Type()]; ok { - f.Call([]reflect.Value{v, reflect.ValueOf(t)}) - } -} - -var transactionKey = "used for *Transaction" - -func transactionFromContext(ctx context.Context) *transaction { - t, _ := ctx.Value(&transactionKey).(*transaction) - return t -} - -func withTransaction(ctx context.Context, t *transaction) context.Context { - return context.WithValue(ctx, &transactionKey, t) -} - -type transaction struct { - transaction pb.Transaction - finished bool -} - -var ErrConcurrentTransaction = errors.New("internal: concurrent transaction") - -func RunTransactionOnce(c context.Context, f func(context.Context) error, xg bool, readOnly bool, previousTransaction *pb.Transaction) (*pb.Transaction, error) { - if transactionFromContext(c) != nil { - return nil, errors.New("nested transactions are not supported") - } - - // Begin the transaction. - t := &transaction{} - req := &pb.BeginTransactionRequest{ - App: proto.String(FullyQualifiedAppID(c)), - } - if xg { - req.AllowMultipleEg = proto.Bool(true) - } - if previousTransaction != nil { - req.PreviousTransaction = previousTransaction - } - if readOnly { - req.Mode = pb.BeginTransactionRequest_READ_ONLY.Enum() - } else { - req.Mode = pb.BeginTransactionRequest_READ_WRITE.Enum() - } - if err := Call(c, "datastore_v3", "BeginTransaction", req, &t.transaction); err != nil { - return nil, err - } - - // Call f, rolling back the transaction if f returns a non-nil error, or panics. - // The panic is not recovered. - defer func() { - if t.finished { - return - } - t.finished = true - // Ignore the error return value, since we are already returning a non-nil - // error (or we're panicking). - Call(c, "datastore_v3", "Rollback", &t.transaction, &basepb.VoidProto{}) - }() - if err := f(withTransaction(c, t)); err != nil { - return &t.transaction, err - } - t.finished = true - - // Commit the transaction. - res := &pb.CommitResponse{} - err := Call(c, "datastore_v3", "Commit", &t.transaction, res) - if ae, ok := err.(*APIError); ok { - /* TODO: restore this conditional - if appengine.IsDevAppServer() { - */ - // The Python Dev AppServer raises an ApplicationError with error code 2 (which is - // Error.CONCURRENT_TRANSACTION) and message "Concurrency exception.". - if ae.Code == int32(pb.Error_BAD_REQUEST) && ae.Detail == "ApplicationError: 2 Concurrency exception." { - return &t.transaction, ErrConcurrentTransaction - } - if ae.Code == int32(pb.Error_CONCURRENT_TRANSACTION) { - return &t.transaction, ErrConcurrentTransaction - } - } - return &t.transaction, err -} diff --git a/vendor/google.golang.org/appengine/internal/urlfetch/urlfetch_service.pb.go b/vendor/google.golang.org/appengine/internal/urlfetch/urlfetch_service.pb.go deleted file mode 100644 index 5f727750a..000000000 --- a/vendor/google.golang.org/appengine/internal/urlfetch/urlfetch_service.pb.go +++ /dev/null @@ -1,527 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// source: google.golang.org/appengine/internal/urlfetch/urlfetch_service.proto - -package urlfetch - -import proto "github.com/golang/protobuf/proto" -import fmt "fmt" -import math "math" - -// Reference imports to suppress errors if they are not otherwise used. -var _ = proto.Marshal -var _ = fmt.Errorf -var _ = math.Inf - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the proto package it is being compiled against. -// A compilation error at this line likely means your copy of the -// proto package needs to be updated. -const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package - -type URLFetchServiceError_ErrorCode int32 - -const ( - URLFetchServiceError_OK URLFetchServiceError_ErrorCode = 0 - URLFetchServiceError_INVALID_URL URLFetchServiceError_ErrorCode = 1 - URLFetchServiceError_FETCH_ERROR URLFetchServiceError_ErrorCode = 2 - URLFetchServiceError_UNSPECIFIED_ERROR URLFetchServiceError_ErrorCode = 3 - URLFetchServiceError_RESPONSE_TOO_LARGE URLFetchServiceError_ErrorCode = 4 - URLFetchServiceError_DEADLINE_EXCEEDED URLFetchServiceError_ErrorCode = 5 - URLFetchServiceError_SSL_CERTIFICATE_ERROR URLFetchServiceError_ErrorCode = 6 - URLFetchServiceError_DNS_ERROR URLFetchServiceError_ErrorCode = 7 - URLFetchServiceError_CLOSED URLFetchServiceError_ErrorCode = 8 - URLFetchServiceError_INTERNAL_TRANSIENT_ERROR URLFetchServiceError_ErrorCode = 9 - URLFetchServiceError_TOO_MANY_REDIRECTS URLFetchServiceError_ErrorCode = 10 - URLFetchServiceError_MALFORMED_REPLY URLFetchServiceError_ErrorCode = 11 - URLFetchServiceError_CONNECTION_ERROR URLFetchServiceError_ErrorCode = 12 -) - -var URLFetchServiceError_ErrorCode_name = map[int32]string{ - 0: "OK", - 1: "INVALID_URL", - 2: "FETCH_ERROR", - 3: "UNSPECIFIED_ERROR", - 4: "RESPONSE_TOO_LARGE", - 5: "DEADLINE_EXCEEDED", - 6: "SSL_CERTIFICATE_ERROR", - 7: "DNS_ERROR", - 8: "CLOSED", - 9: "INTERNAL_TRANSIENT_ERROR", - 10: "TOO_MANY_REDIRECTS", - 11: "MALFORMED_REPLY", - 12: "CONNECTION_ERROR", -} -var URLFetchServiceError_ErrorCode_value = map[string]int32{ - "OK": 0, - "INVALID_URL": 1, - "FETCH_ERROR": 2, - "UNSPECIFIED_ERROR": 3, - "RESPONSE_TOO_LARGE": 4, - "DEADLINE_EXCEEDED": 5, - "SSL_CERTIFICATE_ERROR": 6, - "DNS_ERROR": 7, - "CLOSED": 8, - "INTERNAL_TRANSIENT_ERROR": 9, - "TOO_MANY_REDIRECTS": 10, - "MALFORMED_REPLY": 11, - "CONNECTION_ERROR": 12, -} - -func (x URLFetchServiceError_ErrorCode) Enum() *URLFetchServiceError_ErrorCode { - p := new(URLFetchServiceError_ErrorCode) - *p = x - return p -} -func (x URLFetchServiceError_ErrorCode) String() string { - return proto.EnumName(URLFetchServiceError_ErrorCode_name, int32(x)) -} -func (x *URLFetchServiceError_ErrorCode) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(URLFetchServiceError_ErrorCode_value, data, "URLFetchServiceError_ErrorCode") - if err != nil { - return err - } - *x = URLFetchServiceError_ErrorCode(value) - return nil -} -func (URLFetchServiceError_ErrorCode) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_urlfetch_service_b245a7065f33bced, []int{0, 0} -} - -type URLFetchRequest_RequestMethod int32 - -const ( - URLFetchRequest_GET URLFetchRequest_RequestMethod = 1 - URLFetchRequest_POST URLFetchRequest_RequestMethod = 2 - URLFetchRequest_HEAD URLFetchRequest_RequestMethod = 3 - URLFetchRequest_PUT URLFetchRequest_RequestMethod = 4 - URLFetchRequest_DELETE URLFetchRequest_RequestMethod = 5 - URLFetchRequest_PATCH URLFetchRequest_RequestMethod = 6 -) - -var URLFetchRequest_RequestMethod_name = map[int32]string{ - 1: "GET", - 2: "POST", - 3: "HEAD", - 4: "PUT", - 5: "DELETE", - 6: "PATCH", -} -var URLFetchRequest_RequestMethod_value = map[string]int32{ - "GET": 1, - "POST": 2, - "HEAD": 3, - "PUT": 4, - "DELETE": 5, - "PATCH": 6, -} - -func (x URLFetchRequest_RequestMethod) Enum() *URLFetchRequest_RequestMethod { - p := new(URLFetchRequest_RequestMethod) - *p = x - return p -} -func (x URLFetchRequest_RequestMethod) String() string { - return proto.EnumName(URLFetchRequest_RequestMethod_name, int32(x)) -} -func (x *URLFetchRequest_RequestMethod) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(URLFetchRequest_RequestMethod_value, data, "URLFetchRequest_RequestMethod") - if err != nil { - return err - } - *x = URLFetchRequest_RequestMethod(value) - return nil -} -func (URLFetchRequest_RequestMethod) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_urlfetch_service_b245a7065f33bced, []int{1, 0} -} - -type URLFetchServiceError struct { - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *URLFetchServiceError) Reset() { *m = URLFetchServiceError{} } -func (m *URLFetchServiceError) String() string { return proto.CompactTextString(m) } -func (*URLFetchServiceError) ProtoMessage() {} -func (*URLFetchServiceError) Descriptor() ([]byte, []int) { - return fileDescriptor_urlfetch_service_b245a7065f33bced, []int{0} -} -func (m *URLFetchServiceError) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_URLFetchServiceError.Unmarshal(m, b) -} -func (m *URLFetchServiceError) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_URLFetchServiceError.Marshal(b, m, deterministic) -} -func (dst *URLFetchServiceError) XXX_Merge(src proto.Message) { - xxx_messageInfo_URLFetchServiceError.Merge(dst, src) -} -func (m *URLFetchServiceError) XXX_Size() int { - return xxx_messageInfo_URLFetchServiceError.Size(m) -} -func (m *URLFetchServiceError) XXX_DiscardUnknown() { - xxx_messageInfo_URLFetchServiceError.DiscardUnknown(m) -} - -var xxx_messageInfo_URLFetchServiceError proto.InternalMessageInfo - -type URLFetchRequest struct { - Method *URLFetchRequest_RequestMethod `protobuf:"varint,1,req,name=Method,enum=appengine.URLFetchRequest_RequestMethod" json:"Method,omitempty"` - Url *string `protobuf:"bytes,2,req,name=Url" json:"Url,omitempty"` - Header []*URLFetchRequest_Header `protobuf:"group,3,rep,name=Header,json=header" json:"header,omitempty"` - Payload []byte `protobuf:"bytes,6,opt,name=Payload" json:"Payload,omitempty"` - FollowRedirects *bool `protobuf:"varint,7,opt,name=FollowRedirects,def=1" json:"FollowRedirects,omitempty"` - Deadline *float64 `protobuf:"fixed64,8,opt,name=Deadline" json:"Deadline,omitempty"` - MustValidateServerCertificate *bool `protobuf:"varint,9,opt,name=MustValidateServerCertificate,def=1" json:"MustValidateServerCertificate,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *URLFetchRequest) Reset() { *m = URLFetchRequest{} } -func (m *URLFetchRequest) String() string { return proto.CompactTextString(m) } -func (*URLFetchRequest) ProtoMessage() {} -func (*URLFetchRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_urlfetch_service_b245a7065f33bced, []int{1} -} -func (m *URLFetchRequest) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_URLFetchRequest.Unmarshal(m, b) -} -func (m *URLFetchRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_URLFetchRequest.Marshal(b, m, deterministic) -} -func (dst *URLFetchRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_URLFetchRequest.Merge(dst, src) -} -func (m *URLFetchRequest) XXX_Size() int { - return xxx_messageInfo_URLFetchRequest.Size(m) -} -func (m *URLFetchRequest) XXX_DiscardUnknown() { - xxx_messageInfo_URLFetchRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_URLFetchRequest proto.InternalMessageInfo - -const Default_URLFetchRequest_FollowRedirects bool = true -const Default_URLFetchRequest_MustValidateServerCertificate bool = true - -func (m *URLFetchRequest) GetMethod() URLFetchRequest_RequestMethod { - if m != nil && m.Method != nil { - return *m.Method - } - return URLFetchRequest_GET -} - -func (m *URLFetchRequest) GetUrl() string { - if m != nil && m.Url != nil { - return *m.Url - } - return "" -} - -func (m *URLFetchRequest) GetHeader() []*URLFetchRequest_Header { - if m != nil { - return m.Header - } - return nil -} - -func (m *URLFetchRequest) GetPayload() []byte { - if m != nil { - return m.Payload - } - return nil -} - -func (m *URLFetchRequest) GetFollowRedirects() bool { - if m != nil && m.FollowRedirects != nil { - return *m.FollowRedirects - } - return Default_URLFetchRequest_FollowRedirects -} - -func (m *URLFetchRequest) GetDeadline() float64 { - if m != nil && m.Deadline != nil { - return *m.Deadline - } - return 0 -} - -func (m *URLFetchRequest) GetMustValidateServerCertificate() bool { - if m != nil && m.MustValidateServerCertificate != nil { - return *m.MustValidateServerCertificate - } - return Default_URLFetchRequest_MustValidateServerCertificate -} - -type URLFetchRequest_Header struct { - Key *string `protobuf:"bytes,4,req,name=Key" json:"Key,omitempty"` - Value *string `protobuf:"bytes,5,req,name=Value" json:"Value,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *URLFetchRequest_Header) Reset() { *m = URLFetchRequest_Header{} } -func (m *URLFetchRequest_Header) String() string { return proto.CompactTextString(m) } -func (*URLFetchRequest_Header) ProtoMessage() {} -func (*URLFetchRequest_Header) Descriptor() ([]byte, []int) { - return fileDescriptor_urlfetch_service_b245a7065f33bced, []int{1, 0} -} -func (m *URLFetchRequest_Header) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_URLFetchRequest_Header.Unmarshal(m, b) -} -func (m *URLFetchRequest_Header) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_URLFetchRequest_Header.Marshal(b, m, deterministic) -} -func (dst *URLFetchRequest_Header) XXX_Merge(src proto.Message) { - xxx_messageInfo_URLFetchRequest_Header.Merge(dst, src) -} -func (m *URLFetchRequest_Header) XXX_Size() int { - return xxx_messageInfo_URLFetchRequest_Header.Size(m) -} -func (m *URLFetchRequest_Header) XXX_DiscardUnknown() { - xxx_messageInfo_URLFetchRequest_Header.DiscardUnknown(m) -} - -var xxx_messageInfo_URLFetchRequest_Header proto.InternalMessageInfo - -func (m *URLFetchRequest_Header) GetKey() string { - if m != nil && m.Key != nil { - return *m.Key - } - return "" -} - -func (m *URLFetchRequest_Header) GetValue() string { - if m != nil && m.Value != nil { - return *m.Value - } - return "" -} - -type URLFetchResponse struct { - Content []byte `protobuf:"bytes,1,opt,name=Content" json:"Content,omitempty"` - StatusCode *int32 `protobuf:"varint,2,req,name=StatusCode" json:"StatusCode,omitempty"` - Header []*URLFetchResponse_Header `protobuf:"group,3,rep,name=Header,json=header" json:"header,omitempty"` - ContentWasTruncated *bool `protobuf:"varint,6,opt,name=ContentWasTruncated,def=0" json:"ContentWasTruncated,omitempty"` - ExternalBytesSent *int64 `protobuf:"varint,7,opt,name=ExternalBytesSent" json:"ExternalBytesSent,omitempty"` - ExternalBytesReceived *int64 `protobuf:"varint,8,opt,name=ExternalBytesReceived" json:"ExternalBytesReceived,omitempty"` - FinalUrl *string `protobuf:"bytes,9,opt,name=FinalUrl" json:"FinalUrl,omitempty"` - ApiCpuMilliseconds *int64 `protobuf:"varint,10,opt,name=ApiCpuMilliseconds,def=0" json:"ApiCpuMilliseconds,omitempty"` - ApiBytesSent *int64 `protobuf:"varint,11,opt,name=ApiBytesSent,def=0" json:"ApiBytesSent,omitempty"` - ApiBytesReceived *int64 `protobuf:"varint,12,opt,name=ApiBytesReceived,def=0" json:"ApiBytesReceived,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *URLFetchResponse) Reset() { *m = URLFetchResponse{} } -func (m *URLFetchResponse) String() string { return proto.CompactTextString(m) } -func (*URLFetchResponse) ProtoMessage() {} -func (*URLFetchResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_urlfetch_service_b245a7065f33bced, []int{2} -} -func (m *URLFetchResponse) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_URLFetchResponse.Unmarshal(m, b) -} -func (m *URLFetchResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_URLFetchResponse.Marshal(b, m, deterministic) -} -func (dst *URLFetchResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_URLFetchResponse.Merge(dst, src) -} -func (m *URLFetchResponse) XXX_Size() int { - return xxx_messageInfo_URLFetchResponse.Size(m) -} -func (m *URLFetchResponse) XXX_DiscardUnknown() { - xxx_messageInfo_URLFetchResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_URLFetchResponse proto.InternalMessageInfo - -const Default_URLFetchResponse_ContentWasTruncated bool = false -const Default_URLFetchResponse_ApiCpuMilliseconds int64 = 0 -const Default_URLFetchResponse_ApiBytesSent int64 = 0 -const Default_URLFetchResponse_ApiBytesReceived int64 = 0 - -func (m *URLFetchResponse) GetContent() []byte { - if m != nil { - return m.Content - } - return nil -} - -func (m *URLFetchResponse) GetStatusCode() int32 { - if m != nil && m.StatusCode != nil { - return *m.StatusCode - } - return 0 -} - -func (m *URLFetchResponse) GetHeader() []*URLFetchResponse_Header { - if m != nil { - return m.Header - } - return nil -} - -func (m *URLFetchResponse) GetContentWasTruncated() bool { - if m != nil && m.ContentWasTruncated != nil { - return *m.ContentWasTruncated - } - return Default_URLFetchResponse_ContentWasTruncated -} - -func (m *URLFetchResponse) GetExternalBytesSent() int64 { - if m != nil && m.ExternalBytesSent != nil { - return *m.ExternalBytesSent - } - return 0 -} - -func (m *URLFetchResponse) GetExternalBytesReceived() int64 { - if m != nil && m.ExternalBytesReceived != nil { - return *m.ExternalBytesReceived - } - return 0 -} - -func (m *URLFetchResponse) GetFinalUrl() string { - if m != nil && m.FinalUrl != nil { - return *m.FinalUrl - } - return "" -} - -func (m *URLFetchResponse) GetApiCpuMilliseconds() int64 { - if m != nil && m.ApiCpuMilliseconds != nil { - return *m.ApiCpuMilliseconds - } - return Default_URLFetchResponse_ApiCpuMilliseconds -} - -func (m *URLFetchResponse) GetApiBytesSent() int64 { - if m != nil && m.ApiBytesSent != nil { - return *m.ApiBytesSent - } - return Default_URLFetchResponse_ApiBytesSent -} - -func (m *URLFetchResponse) GetApiBytesReceived() int64 { - if m != nil && m.ApiBytesReceived != nil { - return *m.ApiBytesReceived - } - return Default_URLFetchResponse_ApiBytesReceived -} - -type URLFetchResponse_Header struct { - Key *string `protobuf:"bytes,4,req,name=Key" json:"Key,omitempty"` - Value *string `protobuf:"bytes,5,req,name=Value" json:"Value,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *URLFetchResponse_Header) Reset() { *m = URLFetchResponse_Header{} } -func (m *URLFetchResponse_Header) String() string { return proto.CompactTextString(m) } -func (*URLFetchResponse_Header) ProtoMessage() {} -func (*URLFetchResponse_Header) Descriptor() ([]byte, []int) { - return fileDescriptor_urlfetch_service_b245a7065f33bced, []int{2, 0} -} -func (m *URLFetchResponse_Header) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_URLFetchResponse_Header.Unmarshal(m, b) -} -func (m *URLFetchResponse_Header) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_URLFetchResponse_Header.Marshal(b, m, deterministic) -} -func (dst *URLFetchResponse_Header) XXX_Merge(src proto.Message) { - xxx_messageInfo_URLFetchResponse_Header.Merge(dst, src) -} -func (m *URLFetchResponse_Header) XXX_Size() int { - return xxx_messageInfo_URLFetchResponse_Header.Size(m) -} -func (m *URLFetchResponse_Header) XXX_DiscardUnknown() { - xxx_messageInfo_URLFetchResponse_Header.DiscardUnknown(m) -} - -var xxx_messageInfo_URLFetchResponse_Header proto.InternalMessageInfo - -func (m *URLFetchResponse_Header) GetKey() string { - if m != nil && m.Key != nil { - return *m.Key - } - return "" -} - -func (m *URLFetchResponse_Header) GetValue() string { - if m != nil && m.Value != nil { - return *m.Value - } - return "" -} - -func init() { - proto.RegisterType((*URLFetchServiceError)(nil), "appengine.URLFetchServiceError") - proto.RegisterType((*URLFetchRequest)(nil), "appengine.URLFetchRequest") - proto.RegisterType((*URLFetchRequest_Header)(nil), "appengine.URLFetchRequest.Header") - proto.RegisterType((*URLFetchResponse)(nil), "appengine.URLFetchResponse") - proto.RegisterType((*URLFetchResponse_Header)(nil), "appengine.URLFetchResponse.Header") -} - -func init() { - proto.RegisterFile("google.golang.org/appengine/internal/urlfetch/urlfetch_service.proto", fileDescriptor_urlfetch_service_b245a7065f33bced) -} - -var fileDescriptor_urlfetch_service_b245a7065f33bced = []byte{ - // 770 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x54, 0xdd, 0x6e, 0xe3, 0x54, - 0x10, 0xc6, 0x76, 0x7e, 0xa7, 0x5d, 0x7a, 0x76, 0xb6, 0x45, 0x66, 0xb5, 0xa0, 0x10, 0x09, 0x29, - 0x17, 0x90, 0x2e, 0x2b, 0x24, 0x44, 0xaf, 0x70, 0xed, 0x93, 0xad, 0xa9, 0x63, 0x47, 0xc7, 0x4e, - 0x61, 0xb9, 0xb1, 0xac, 0x78, 0x9a, 0x5a, 0xb2, 0xec, 0x60, 0x9f, 0x2c, 0xf4, 0x35, 0x78, 0x0d, - 0xde, 0x87, 0xa7, 0xe1, 0x02, 0x9d, 0xc4, 0xc9, 0x6e, 0xbb, 0xd1, 0x4a, 0x5c, 0x65, 0xe6, 0x9b, - 0xef, 0xcc, 0x99, 0x7c, 0xdf, 0xf8, 0x80, 0xb3, 0x2c, 0xcb, 0x65, 0x4e, 0xe3, 0x65, 0x99, 0x27, - 0xc5, 0x72, 0x5c, 0x56, 0xcb, 0xf3, 0x64, 0xb5, 0xa2, 0x62, 0x99, 0x15, 0x74, 0x9e, 0x15, 0x92, - 0xaa, 0x22, 0xc9, 0xcf, 0xd7, 0x55, 0x7e, 0x4b, 0x72, 0x71, 0xb7, 0x0f, 0xe2, 0x9a, 0xaa, 0xb7, - 0xd9, 0x82, 0xc6, 0xab, 0xaa, 0x94, 0x25, 0xf6, 0xf7, 0x67, 0x86, 0x7f, 0xeb, 0x70, 0x3a, 0x17, - 0xde, 0x44, 0xb1, 0xc2, 0x2d, 0x89, 0x57, 0x55, 0x59, 0x0d, 0xff, 0xd2, 0xa1, 0xbf, 0x89, 0xec, - 0x32, 0x25, 0xec, 0x80, 0x1e, 0x5c, 0xb3, 0x4f, 0xf0, 0x04, 0x8e, 0x5c, 0xff, 0xc6, 0xf2, 0x5c, - 0x27, 0x9e, 0x0b, 0x8f, 0x69, 0x0a, 0x98, 0xf0, 0xc8, 0xbe, 0x8a, 0xb9, 0x10, 0x81, 0x60, 0x3a, - 0x9e, 0xc1, 0xd3, 0xb9, 0x1f, 0xce, 0xb8, 0xed, 0x4e, 0x5c, 0xee, 0x34, 0xb0, 0x81, 0x9f, 0x01, - 0x0a, 0x1e, 0xce, 0x02, 0x3f, 0xe4, 0x71, 0x14, 0x04, 0xb1, 0x67, 0x89, 0xd7, 0x9c, 0xb5, 0x14, - 0xdd, 0xe1, 0x96, 0xe3, 0xb9, 0x3e, 0x8f, 0xf9, 0xaf, 0x36, 0xe7, 0x0e, 0x77, 0x58, 0x1b, 0x3f, - 0x87, 0xb3, 0x30, 0xf4, 0x62, 0x9b, 0x8b, 0xc8, 0x9d, 0xb8, 0xb6, 0x15, 0xf1, 0xa6, 0x53, 0x07, - 0x9f, 0x40, 0xdf, 0xf1, 0xc3, 0x26, 0xed, 0x22, 0x40, 0xc7, 0xf6, 0x82, 0x90, 0x3b, 0xac, 0x87, - 0x2f, 0xc0, 0x74, 0xfd, 0x88, 0x0b, 0xdf, 0xf2, 0xe2, 0x48, 0x58, 0x7e, 0xe8, 0x72, 0x3f, 0x6a, - 0x98, 0x7d, 0x35, 0x82, 0xba, 0x79, 0x6a, 0xf9, 0x6f, 0x62, 0xc1, 0x1d, 0x57, 0x70, 0x3b, 0x0a, - 0x19, 0xe0, 0x33, 0x38, 0x99, 0x5a, 0xde, 0x24, 0x10, 0x53, 0xee, 0xc4, 0x82, 0xcf, 0xbc, 0x37, - 0xec, 0x08, 0x4f, 0x81, 0xd9, 0x81, 0xef, 0x73, 0x3b, 0x72, 0x03, 0xbf, 0x69, 0x71, 0x3c, 0xfc, - 0xc7, 0x80, 0x93, 0x9d, 0x5a, 0x82, 0x7e, 0x5f, 0x53, 0x2d, 0xf1, 0x27, 0xe8, 0x4c, 0x49, 0xde, - 0x95, 0xa9, 0xa9, 0x0d, 0xf4, 0xd1, 0xa7, 0xaf, 0x46, 0xe3, 0xbd, 0xba, 0xe3, 0x47, 0xdc, 0x71, - 0xf3, 0xbb, 0xe5, 0x8b, 0xe6, 0x1c, 0x32, 0x30, 0xe6, 0x55, 0x6e, 0xea, 0x03, 0x7d, 0xd4, 0x17, - 0x2a, 0xc4, 0x1f, 0xa1, 0x73, 0x47, 0x49, 0x4a, 0x95, 0x69, 0x0c, 0x8c, 0x11, 0xbc, 0xfa, 0xea, - 0x23, 0x3d, 0xaf, 0x36, 0x44, 0xd1, 0x1c, 0xc0, 0x17, 0xd0, 0x9d, 0x25, 0xf7, 0x79, 0x99, 0xa4, - 0x66, 0x67, 0xa0, 0x8d, 0x8e, 0x2f, 0xf5, 0x9e, 0x26, 0x76, 0x10, 0x8e, 0xe1, 0x64, 0x52, 0xe6, - 0x79, 0xf9, 0x87, 0xa0, 0x34, 0xab, 0x68, 0x21, 0x6b, 0xb3, 0x3b, 0xd0, 0x46, 0xbd, 0x8b, 0x96, - 0xac, 0xd6, 0x24, 0x1e, 0x17, 0xf1, 0x39, 0xf4, 0x1c, 0x4a, 0xd2, 0x3c, 0x2b, 0xc8, 0xec, 0x0d, - 0xb4, 0x91, 0x26, 0xf6, 0x39, 0xfe, 0x0c, 0x5f, 0x4c, 0xd7, 0xb5, 0xbc, 0x49, 0xf2, 0x2c, 0x4d, - 0x24, 0xa9, 0xed, 0xa1, 0xca, 0xa6, 0x4a, 0x66, 0xb7, 0xd9, 0x22, 0x91, 0x64, 0xf6, 0xdf, 0xeb, - 0xfc, 0x71, 0xea, 0xf3, 0x97, 0xd0, 0xd9, 0xfe, 0x0f, 0x25, 0xc6, 0x35, 0xdd, 0x9b, 0xad, 0xad, - 0x18, 0xd7, 0x74, 0x8f, 0xa7, 0xd0, 0xbe, 0x49, 0xf2, 0x35, 0x99, 0xed, 0x0d, 0xb6, 0x4d, 0x86, - 0x1e, 0x3c, 0x79, 0xa0, 0x26, 0x76, 0xc1, 0x78, 0xcd, 0x23, 0xa6, 0x61, 0x0f, 0x5a, 0xb3, 0x20, - 0x8c, 0x98, 0xae, 0xa2, 0x2b, 0x6e, 0x39, 0xcc, 0x50, 0xc5, 0xd9, 0x3c, 0x62, 0x2d, 0xb5, 0x2e, - 0x0e, 0xf7, 0x78, 0xc4, 0x59, 0x1b, 0xfb, 0xd0, 0x9e, 0x59, 0x91, 0x7d, 0xc5, 0x3a, 0xc3, 0x7f, - 0x0d, 0x60, 0xef, 0x84, 0xad, 0x57, 0x65, 0x51, 0x13, 0x9a, 0xd0, 0xb5, 0xcb, 0x42, 0x52, 0x21, - 0x4d, 0x4d, 0x49, 0x29, 0x76, 0x29, 0x7e, 0x09, 0x10, 0xca, 0x44, 0xae, 0x6b, 0xf5, 0x71, 0x6c, - 0x8c, 0x6b, 0x8b, 0xf7, 0x10, 0xbc, 0x78, 0xe4, 0xdf, 0xf0, 0xa0, 0x7f, 0xdb, 0x6b, 0x1e, 0x1b, - 0xf8, 0x03, 0x3c, 0x6b, 0xae, 0xf9, 0x25, 0xa9, 0xa3, 0x6a, 0x5d, 0x28, 0x81, 0xb6, 0x66, 0xf6, - 0x2e, 0xda, 0xb7, 0x49, 0x5e, 0x93, 0x38, 0xc4, 0xc0, 0x6f, 0xe0, 0x29, 0xff, 0x73, 0xfb, 0x02, - 0x5c, 0xde, 0x4b, 0xaa, 0x43, 0x35, 0xb8, 0x72, 0xd7, 0x10, 0x1f, 0x16, 0xf0, 0x7b, 0x38, 0x7b, - 0x00, 0x0a, 0x5a, 0x50, 0xf6, 0x96, 0xd2, 0x8d, 0xcd, 0x86, 0x38, 0x5c, 0x54, 0xfb, 0x30, 0xc9, - 0x8a, 0x24, 0x57, 0xfb, 0xaa, 0xec, 0xed, 0x8b, 0x7d, 0x8e, 0xdf, 0x01, 0x5a, 0xab, 0xcc, 0x5e, - 0xad, 0xa7, 0x59, 0x9e, 0x67, 0x35, 0x2d, 0xca, 0x22, 0xad, 0x4d, 0x50, 0xed, 0x2e, 0xb4, 0x97, - 0xe2, 0x40, 0x11, 0xbf, 0x86, 0x63, 0x6b, 0x95, 0xbd, 0x9b, 0xf6, 0x68, 0x47, 0x7e, 0x00, 0xe3, - 0xb7, 0xc0, 0x76, 0xf9, 0x7e, 0xcc, 0xe3, 0x1d, 0xf5, 0x83, 0xd2, 0xff, 0x5f, 0xa6, 0x4b, 0xf8, - 0xad, 0xb7, 0x7b, 0x2a, 0xff, 0x0b, 0x00, 0x00, 0xff, 0xff, 0x1d, 0x9f, 0x6d, 0x24, 0x63, 0x05, - 0x00, 0x00, -} diff --git a/vendor/google.golang.org/appengine/internal/urlfetch/urlfetch_service.proto b/vendor/google.golang.org/appengine/internal/urlfetch/urlfetch_service.proto deleted file mode 100644 index f695edf6a..000000000 --- a/vendor/google.golang.org/appengine/internal/urlfetch/urlfetch_service.proto +++ /dev/null @@ -1,64 +0,0 @@ -syntax = "proto2"; -option go_package = "urlfetch"; - -package appengine; - -message URLFetchServiceError { - enum ErrorCode { - OK = 0; - INVALID_URL = 1; - FETCH_ERROR = 2; - UNSPECIFIED_ERROR = 3; - RESPONSE_TOO_LARGE = 4; - DEADLINE_EXCEEDED = 5; - SSL_CERTIFICATE_ERROR = 6; - DNS_ERROR = 7; - CLOSED = 8; - INTERNAL_TRANSIENT_ERROR = 9; - TOO_MANY_REDIRECTS = 10; - MALFORMED_REPLY = 11; - CONNECTION_ERROR = 12; - } -} - -message URLFetchRequest { - enum RequestMethod { - GET = 1; - POST = 2; - HEAD = 3; - PUT = 4; - DELETE = 5; - PATCH = 6; - } - required RequestMethod Method = 1; - required string Url = 2; - repeated group Header = 3 { - required string Key = 4; - required string Value = 5; - } - optional bytes Payload = 6 [ctype=CORD]; - - optional bool FollowRedirects = 7 [default=true]; - - optional double Deadline = 8; - - optional bool MustValidateServerCertificate = 9 [default=true]; -} - -message URLFetchResponse { - optional bytes Content = 1; - required int32 StatusCode = 2; - repeated group Header = 3 { - required string Key = 4; - required string Value = 5; - } - optional bool ContentWasTruncated = 6 [default=false]; - optional int64 ExternalBytesSent = 7; - optional int64 ExternalBytesReceived = 8; - - optional string FinalUrl = 9; - - optional int64 ApiCpuMilliseconds = 10 [default=0]; - optional int64 ApiBytesSent = 11 [default=0]; - optional int64 ApiBytesReceived = 12 [default=0]; -} diff --git a/vendor/google.golang.org/appengine/urlfetch/urlfetch.go b/vendor/google.golang.org/appengine/urlfetch/urlfetch.go deleted file mode 100644 index 6c0d72418..000000000 --- a/vendor/google.golang.org/appengine/urlfetch/urlfetch.go +++ /dev/null @@ -1,209 +0,0 @@ -// Copyright 2011 Google Inc. All rights reserved. -// Use of this source code is governed by the Apache 2.0 -// license that can be found in the LICENSE file. - -// Package urlfetch provides an http.RoundTripper implementation -// for fetching URLs via App Engine's urlfetch service. -package urlfetch // import "google.golang.org/appengine/urlfetch" - -import ( - "context" - "errors" - "fmt" - "io" - "io/ioutil" - "net/http" - "net/url" - "strconv" - "strings" - "time" - - "github.com/golang/protobuf/proto" - - "google.golang.org/appengine/internal" - pb "google.golang.org/appengine/internal/urlfetch" -) - -// Transport is an implementation of http.RoundTripper for -// App Engine. Users should generally create an http.Client using -// this transport and use the Client rather than using this transport -// directly. -type Transport struct { - Context context.Context - - // Controls whether the application checks the validity of SSL certificates - // over HTTPS connections. A value of false (the default) instructs the - // application to send a request to the server only if the certificate is - // valid and signed by a trusted certificate authority (CA), and also - // includes a hostname that matches the certificate. A value of true - // instructs the application to perform no certificate validation. - AllowInvalidServerCertificate bool -} - -// Verify statically that *Transport implements http.RoundTripper. -var _ http.RoundTripper = (*Transport)(nil) - -// Client returns an *http.Client using a default urlfetch Transport. This -// client will check the validity of SSL certificates. -// -// Any deadline of the provided context will be used for requests through this client. -// If the client does not have a deadline, then an App Engine default of 60 second is used. -func Client(ctx context.Context) *http.Client { - return &http.Client{ - Transport: &Transport{ - Context: ctx, - }, - } -} - -type bodyReader struct { - content []byte - truncated bool - closed bool -} - -// ErrTruncatedBody is the error returned after the final Read() from a -// response's Body if the body has been truncated by App Engine's proxy. -var ErrTruncatedBody = errors.New("urlfetch: truncated body") - -func statusCodeToText(code int) string { - if t := http.StatusText(code); t != "" { - return t - } - return strconv.Itoa(code) -} - -func (br *bodyReader) Read(p []byte) (n int, err error) { - if br.closed { - if br.truncated { - return 0, ErrTruncatedBody - } - return 0, io.EOF - } - n = copy(p, br.content) - if n > 0 { - br.content = br.content[n:] - return - } - if br.truncated { - br.closed = true - return 0, ErrTruncatedBody - } - return 0, io.EOF -} - -func (br *bodyReader) Close() error { - br.closed = true - br.content = nil - return nil -} - -// A map of the URL Fetch-accepted methods that take a request body. -var methodAcceptsRequestBody = map[string]bool{ - "POST": true, - "PUT": true, - "PATCH": true, -} - -// urlString returns a valid string given a URL. This function is necessary because -// the String method of URL doesn't correctly handle URLs with non-empty Opaque values. -// See http://code.google.com/p/go/issues/detail?id=4860. -func urlString(u *url.URL) string { - if u.Opaque == "" || strings.HasPrefix(u.Opaque, "//") { - return u.String() - } - aux := *u - aux.Opaque = "//" + aux.Host + aux.Opaque - return aux.String() -} - -// RoundTrip issues a single HTTP request and returns its response. Per the -// http.RoundTripper interface, RoundTrip only returns an error if there -// was an unsupported request or the URL Fetch proxy fails. -// Note that HTTP response codes such as 5xx, 403, 404, etc are not -// errors as far as the transport is concerned and will be returned -// with err set to nil. -func (t *Transport) RoundTrip(req *http.Request) (res *http.Response, err error) { - methNum, ok := pb.URLFetchRequest_RequestMethod_value[req.Method] - if !ok { - return nil, fmt.Errorf("urlfetch: unsupported HTTP method %q", req.Method) - } - - method := pb.URLFetchRequest_RequestMethod(methNum) - - freq := &pb.URLFetchRequest{ - Method: &method, - Url: proto.String(urlString(req.URL)), - FollowRedirects: proto.Bool(false), // http.Client's responsibility - MustValidateServerCertificate: proto.Bool(!t.AllowInvalidServerCertificate), - } - if deadline, ok := t.Context.Deadline(); ok { - freq.Deadline = proto.Float64(deadline.Sub(time.Now()).Seconds()) - } - - for k, vals := range req.Header { - for _, val := range vals { - freq.Header = append(freq.Header, &pb.URLFetchRequest_Header{ - Key: proto.String(k), - Value: proto.String(val), - }) - } - } - if methodAcceptsRequestBody[req.Method] && req.Body != nil { - // Avoid a []byte copy if req.Body has a Bytes method. - switch b := req.Body.(type) { - case interface { - Bytes() []byte - }: - freq.Payload = b.Bytes() - default: - freq.Payload, err = ioutil.ReadAll(req.Body) - if err != nil { - return nil, err - } - } - } - - fres := &pb.URLFetchResponse{} - if err := internal.Call(t.Context, "urlfetch", "Fetch", freq, fres); err != nil { - return nil, err - } - - res = &http.Response{} - res.StatusCode = int(*fres.StatusCode) - res.Status = fmt.Sprintf("%d %s", res.StatusCode, statusCodeToText(res.StatusCode)) - res.Header = make(http.Header) - res.Request = req - - // Faked: - res.ProtoMajor = 1 - res.ProtoMinor = 1 - res.Proto = "HTTP/1.1" - res.Close = true - - for _, h := range fres.Header { - hkey := http.CanonicalHeaderKey(*h.Key) - hval := *h.Value - if hkey == "Content-Length" { - // Will get filled in below for all but HEAD requests. - if req.Method == "HEAD" { - res.ContentLength, _ = strconv.ParseInt(hval, 10, 64) - } - continue - } - res.Header.Add(hkey, hval) - } - - if req.Method != "HEAD" { - res.ContentLength = int64(len(fres.Content)) - } - - truncated := fres.GetContentWasTruncated() - res.Body = &bodyReader{content: fres.Content, truncated: truncated} - return -} - -func init() { - internal.RegisterErrorCodeMap("urlfetch", pb.URLFetchServiceError_ErrorCode_name) - internal.RegisterTimeoutErrorCode("urlfetch", int32(pb.URLFetchServiceError_DEADLINE_EXCEEDED)) -} diff --git a/vendor/google.golang.org/genproto/googleapis/api/annotations/annotations.pb.go b/vendor/google.golang.org/genproto/googleapis/api/annotations/annotations.pb.go index 191bea48c..8b462f3df 100644 --- a/vendor/google.golang.org/genproto/googleapis/api/annotations/annotations.pb.go +++ b/vendor/google.golang.org/genproto/googleapis/api/annotations/annotations.pb.go @@ -1,4 +1,4 @@ -// Copyright 2015 Google LLC +// Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -15,7 +15,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.26.0 -// protoc v3.12.2 +// protoc v4.24.4 // source: google/api/annotations.proto package annotations diff --git a/vendor/google.golang.org/genproto/googleapis/api/annotations/client.pb.go b/vendor/google.golang.org/genproto/googleapis/api/annotations/client.pb.go index 10f35d10e..aa69fb4d5 100644 --- a/vendor/google.golang.org/genproto/googleapis/api/annotations/client.pb.go +++ b/vendor/google.golang.org/genproto/googleapis/api/annotations/client.pb.go @@ -1,4 +1,4 @@ -// Copyright 2023 Google LLC +// Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -719,6 +719,8 @@ type PythonSettings struct { // Some settings. Common *CommonLanguageSettings `protobuf:"bytes,1,opt,name=common,proto3" json:"common,omitempty"` + // Experimental features to be included during client library generation. + ExperimentalFeatures *PythonSettings_ExperimentalFeatures `protobuf:"bytes,2,opt,name=experimental_features,json=experimentalFeatures,proto3" json:"experimental_features,omitempty"` } func (x *PythonSettings) Reset() { @@ -760,6 +762,13 @@ func (x *PythonSettings) GetCommon() *CommonLanguageSettings { return nil } +func (x *PythonSettings) GetExperimentalFeatures() *PythonSettings_ExperimentalFeatures { + if x != nil { + return x.ExperimentalFeatures + } + return nil +} + // Settings for Node client libraries. type NodeSettings struct { state protoimpl.MessageState @@ -1024,6 +1033,13 @@ type MethodSettings struct { // The fully qualified name of the method, for which the options below apply. // This is used to find the method to apply the options. + // + // Example: + // + // publishing: + // method_settings: + // - selector: google.storage.control.v2.StorageControl.CreateFolder + // # method settings for CreateFolder... Selector string `protobuf:"bytes,1,opt,name=selector,proto3" json:"selector,omitempty"` // Describes settings to use for long-running operations when generating // API methods for RPCs. Complements RPCs that use the annotations in @@ -1033,15 +1049,12 @@ type MethodSettings struct { // // publishing: // method_settings: - // - selector: google.cloud.speech.v2.Speech.BatchRecognize - // long_running: - // initial_poll_delay: - // seconds: 60 # 1 minute - // poll_delay_multiplier: 1.5 - // max_poll_delay: - // seconds: 360 # 6 minutes - // total_poll_timeout: - // seconds: 54000 # 90 minutes + // - selector: google.cloud.speech.v2.Speech.BatchRecognize + // long_running: + // initial_poll_delay: 60s # 1 minute + // poll_delay_multiplier: 1.5 + // max_poll_delay: 360s # 6 minutes + // total_poll_timeout: 54000s # 90 minutes LongRunning *MethodSettings_LongRunning `protobuf:"bytes,2,opt,name=long_running,json=longRunning,proto3" json:"long_running,omitempty"` // List of top-level fields of the request message, that should be // automatically populated by the client libraries based on their @@ -1051,9 +1064,9 @@ type MethodSettings struct { // // publishing: // method_settings: - // - selector: google.example.v1.ExampleService.CreateExample - // auto_populated_fields: - // - request_id + // - selector: google.example.v1.ExampleService.CreateExample + // auto_populated_fields: + // - request_id AutoPopulatedFields []string `protobuf:"bytes,3,rep,name=auto_populated_fields,json=autoPopulatedFields,proto3" json:"auto_populated_fields,omitempty"` } @@ -1110,6 +1123,60 @@ func (x *MethodSettings) GetAutoPopulatedFields() []string { return nil } +// Experimental features to be included during client library generation. +// These fields will be deprecated once the feature graduates and is enabled +// by default. +type PythonSettings_ExperimentalFeatures struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Enables generation of asynchronous REST clients if `rest` transport is + // enabled. By default, asynchronous REST clients will not be generated. + // This feature will be enabled by default 1 month after launching the + // feature in preview packages. + RestAsyncIoEnabled bool `protobuf:"varint,1,opt,name=rest_async_io_enabled,json=restAsyncIoEnabled,proto3" json:"rest_async_io_enabled,omitempty"` +} + +func (x *PythonSettings_ExperimentalFeatures) Reset() { + *x = PythonSettings_ExperimentalFeatures{} + if protoimpl.UnsafeEnabled { + mi := &file_google_api_client_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PythonSettings_ExperimentalFeatures) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PythonSettings_ExperimentalFeatures) ProtoMessage() {} + +func (x *PythonSettings_ExperimentalFeatures) ProtoReflect() protoreflect.Message { + mi := &file_google_api_client_proto_msgTypes[13] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PythonSettings_ExperimentalFeatures.ProtoReflect.Descriptor instead. +func (*PythonSettings_ExperimentalFeatures) Descriptor() ([]byte, []int) { + return file_google_api_client_proto_rawDescGZIP(), []int{6, 0} +} + +func (x *PythonSettings_ExperimentalFeatures) GetRestAsyncIoEnabled() bool { + if x != nil { + return x.RestAsyncIoEnabled + } + return false +} + // Describes settings to use when generating API methods that use the // long-running operation pattern. // All default values below are from those used in the client library @@ -1138,7 +1205,7 @@ type MethodSettings_LongRunning struct { func (x *MethodSettings_LongRunning) Reset() { *x = MethodSettings_LongRunning{} if protoimpl.UnsafeEnabled { - mi := &file_google_api_client_proto_msgTypes[15] + mi := &file_google_api_client_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1151,7 +1218,7 @@ func (x *MethodSettings_LongRunning) String() string { func (*MethodSettings_LongRunning) ProtoMessage() {} func (x *MethodSettings_LongRunning) ProtoReflect() protoreflect.Message { - mi := &file_google_api_client_proto_msgTypes[15] + mi := &file_google_api_client_proto_msgTypes[16] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1456,132 +1523,143 @@ var file_google_api_client_proto_rawDesc = []byte{ 0x73, 0x12, 0x3a, 0x0a, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x4c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x53, 0x65, 0x74, - 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x22, 0x4c, 0x0a, - 0x0e, 0x50, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, - 0x3a, 0x0a, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x22, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x6f, 0x6d, - 0x6d, 0x6f, 0x6e, 0x4c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x53, 0x65, 0x74, 0x74, 0x69, - 0x6e, 0x67, 0x73, 0x52, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x22, 0x4a, 0x0a, 0x0c, 0x4e, - 0x6f, 0x64, 0x65, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x3a, 0x0a, 0x06, 0x63, - 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x4c, - 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, - 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x22, 0xae, 0x04, 0x0a, 0x0e, 0x44, 0x6f, 0x74, 0x6e, - 0x65, 0x74, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x3a, 0x0a, 0x06, 0x63, 0x6f, + 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x22, 0xfd, 0x01, + 0x0a, 0x0e, 0x50, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, + 0x12, 0x3a, 0x0a, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x22, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x6f, + 0x6d, 0x6d, 0x6f, 0x6e, 0x4c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x53, 0x65, 0x74, 0x74, + 0x69, 0x6e, 0x67, 0x73, 0x52, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x12, 0x64, 0x0a, 0x15, + 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x5f, 0x66, 0x65, 0x61, + 0x74, 0x75, 0x72, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x50, 0x79, 0x74, 0x68, 0x6f, 0x6e, 0x53, + 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x45, 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, + 0x6e, 0x74, 0x61, 0x6c, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x14, 0x65, 0x78, + 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x73, 0x1a, 0x49, 0x0a, 0x14, 0x45, 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, + 0x61, 0x6c, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x31, 0x0a, 0x15, 0x72, 0x65, + 0x73, 0x74, 0x5f, 0x61, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x69, 0x6f, 0x5f, 0x65, 0x6e, 0x61, 0x62, + 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x72, 0x65, 0x73, 0x74, 0x41, + 0x73, 0x79, 0x6e, 0x63, 0x49, 0x6f, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x22, 0x4a, 0x0a, + 0x0c, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x3a, 0x0a, + 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, + 0x6e, 0x4c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, + 0x73, 0x52, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x22, 0xae, 0x04, 0x0a, 0x0e, 0x44, 0x6f, + 0x74, 0x6e, 0x65, 0x74, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x3a, 0x0a, 0x06, + 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, + 0x4c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, + 0x52, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x12, 0x5a, 0x0a, 0x10, 0x72, 0x65, 0x6e, 0x61, + 0x6d, 0x65, 0x64, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x61, 0x70, 0x69, 0x2e, + 0x44, 0x6f, 0x74, 0x6e, 0x65, 0x74, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x52, + 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x52, 0x0f, 0x72, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x73, 0x12, 0x5d, 0x0a, 0x11, 0x72, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x64, 0x5f, + 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x30, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x44, 0x6f, 0x74, + 0x6e, 0x65, 0x74, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x52, 0x65, 0x6e, 0x61, + 0x6d, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, + 0x79, 0x52, 0x10, 0x72, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x64, 0x5f, 0x72, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, + 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, + 0x12, 0x38, 0x0a, 0x18, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, + 0x70, 0x61, 0x63, 0x65, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, + 0x28, 0x09, 0x52, 0x16, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, + 0x61, 0x63, 0x65, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x65, 0x73, 0x12, 0x35, 0x0a, 0x16, 0x68, 0x61, + 0x6e, 0x64, 0x77, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, + 0x75, 0x72, 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x15, 0x68, 0x61, 0x6e, 0x64, + 0x77, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x73, 0x1a, 0x42, 0x0a, 0x14, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x43, 0x0a, 0x15, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x64, + 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, + 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, + 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x4a, 0x0a, 0x0c, 0x52, 0x75, + 0x62, 0x79, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x3a, 0x0a, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x4c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x06, - 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x12, 0x5a, 0x0a, 0x10, 0x72, 0x65, 0x6e, 0x61, 0x6d, 0x65, - 0x64, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x2f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x44, 0x6f, - 0x74, 0x6e, 0x65, 0x74, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x52, 0x65, 0x6e, - 0x61, 0x6d, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, - 0x79, 0x52, 0x0f, 0x72, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x73, 0x12, 0x5d, 0x0a, 0x11, 0x72, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x64, 0x5f, 0x72, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x30, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x44, 0x6f, 0x74, 0x6e, 0x65, - 0x74, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, - 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, - 0x10, 0x72, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x64, 0x5f, 0x72, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x69, 0x67, - 0x6e, 0x6f, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x38, - 0x0a, 0x18, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, - 0x63, 0x65, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, - 0x52, 0x16, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, - 0x65, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x65, 0x73, 0x12, 0x35, 0x0a, 0x16, 0x68, 0x61, 0x6e, 0x64, - 0x77, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x15, 0x68, 0x61, 0x6e, 0x64, 0x77, 0x72, - 0x69, 0x74, 0x74, 0x65, 0x6e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x1a, - 0x42, 0x0a, 0x14, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, - 0x02, 0x38, 0x01, 0x1a, 0x43, 0x0a, 0x15, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x64, 0x52, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, - 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, - 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x4a, 0x0a, 0x0c, 0x52, 0x75, 0x62, 0x79, - 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x3a, 0x0a, 0x06, 0x63, 0x6f, 0x6d, 0x6d, - 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x4c, 0x61, 0x6e, 0x67, - 0x75, 0x61, 0x67, 0x65, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x06, 0x63, 0x6f, - 0x6d, 0x6d, 0x6f, 0x6e, 0x22, 0x48, 0x0a, 0x0a, 0x47, 0x6f, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, - 0x67, 0x73, 0x12, 0x3a, 0x0a, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x61, 0x70, 0x69, 0x2e, - 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x4c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x53, 0x65, - 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x22, 0xc2, - 0x03, 0x0a, 0x0e, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, - 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x49, 0x0a, - 0x0c, 0x6c, 0x6f, 0x6e, 0x67, 0x5f, 0x72, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x61, 0x70, 0x69, - 0x2e, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, - 0x4c, 0x6f, 0x6e, 0x67, 0x52, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x52, 0x0b, 0x6c, 0x6f, 0x6e, - 0x67, 0x52, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x12, 0x32, 0x0a, 0x15, 0x61, 0x75, 0x74, 0x6f, - 0x5f, 0x70, 0x6f, 0x70, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, - 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x13, 0x61, 0x75, 0x74, 0x6f, 0x50, 0x6f, 0x70, - 0x75, 0x6c, 0x61, 0x74, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x1a, 0x94, 0x02, 0x0a, - 0x0b, 0x4c, 0x6f, 0x6e, 0x67, 0x52, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x12, 0x47, 0x0a, 0x12, - 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x70, 0x6f, 0x6c, 0x6c, 0x5f, 0x64, 0x65, 0x6c, - 0x61, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x22, 0x48, 0x0a, 0x0a, 0x47, 0x6f, 0x53, 0x65, 0x74, 0x74, + 0x69, 0x6e, 0x67, 0x73, 0x12, 0x3a, 0x0a, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x61, 0x70, + 0x69, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x4c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, + 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, + 0x22, 0xc2, 0x03, 0x0a, 0x0e, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x53, 0x65, 0x74, 0x74, 0x69, + 0x6e, 0x67, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, + 0x49, 0x0a, 0x0c, 0x6c, 0x6f, 0x6e, 0x67, 0x5f, 0x72, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x61, + 0x70, 0x69, 0x2e, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, + 0x73, 0x2e, 0x4c, 0x6f, 0x6e, 0x67, 0x52, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x52, 0x0b, 0x6c, + 0x6f, 0x6e, 0x67, 0x52, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x12, 0x32, 0x0a, 0x15, 0x61, 0x75, + 0x74, 0x6f, 0x5f, 0x70, 0x6f, 0x70, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x66, 0x69, 0x65, + 0x6c, 0x64, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x13, 0x61, 0x75, 0x74, 0x6f, 0x50, + 0x6f, 0x70, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x1a, 0x94, + 0x02, 0x0a, 0x0b, 0x4c, 0x6f, 0x6e, 0x67, 0x52, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x12, 0x47, + 0x0a, 0x12, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x70, 0x6f, 0x6c, 0x6c, 0x5f, 0x64, + 0x65, 0x6c, 0x61, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x10, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x50, 0x6f, + 0x6c, 0x6c, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x12, 0x32, 0x0a, 0x15, 0x70, 0x6f, 0x6c, 0x6c, 0x5f, + 0x64, 0x65, 0x6c, 0x61, 0x79, 0x5f, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x69, 0x65, 0x72, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x02, 0x52, 0x13, 0x70, 0x6f, 0x6c, 0x6c, 0x44, 0x65, 0x6c, 0x61, + 0x79, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x69, 0x65, 0x72, 0x12, 0x3f, 0x0a, 0x0e, 0x6d, + 0x61, 0x78, 0x5f, 0x70, 0x6f, 0x6c, 0x6c, 0x5f, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c, + 0x6d, 0x61, 0x78, 0x50, 0x6f, 0x6c, 0x6c, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x12, 0x47, 0x0a, 0x12, + 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x70, 0x6f, 0x6c, 0x6c, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, + 0x75, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x10, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x50, 0x6f, 0x6c, 0x6c, - 0x44, 0x65, 0x6c, 0x61, 0x79, 0x12, 0x32, 0x0a, 0x15, 0x70, 0x6f, 0x6c, 0x6c, 0x5f, 0x64, 0x65, - 0x6c, 0x61, 0x79, 0x5f, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x69, 0x65, 0x72, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x02, 0x52, 0x13, 0x70, 0x6f, 0x6c, 0x6c, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x4d, - 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x69, 0x65, 0x72, 0x12, 0x3f, 0x0a, 0x0e, 0x6d, 0x61, 0x78, - 0x5f, 0x70, 0x6f, 0x6c, 0x6c, 0x5f, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x6d, 0x61, - 0x78, 0x50, 0x6f, 0x6c, 0x6c, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x12, 0x47, 0x0a, 0x12, 0x74, 0x6f, - 0x74, 0x61, 0x6c, 0x5f, 0x70, 0x6f, 0x6c, 0x6c, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x52, 0x10, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x50, 0x6f, 0x6c, 0x6c, 0x54, 0x69, 0x6d, 0x65, - 0x6f, 0x75, 0x74, 0x2a, 0xa3, 0x01, 0x0a, 0x19, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x4c, 0x69, - 0x62, 0x72, 0x61, 0x72, 0x79, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x12, 0x2b, 0x0a, 0x27, 0x43, 0x4c, 0x49, 0x45, 0x4e, 0x54, 0x5f, 0x4c, 0x49, 0x42, 0x52, - 0x41, 0x52, 0x59, 0x5f, 0x4f, 0x52, 0x47, 0x41, 0x4e, 0x49, 0x5a, 0x41, 0x54, 0x49, 0x4f, 0x4e, - 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x09, - 0x0a, 0x05, 0x43, 0x4c, 0x4f, 0x55, 0x44, 0x10, 0x01, 0x12, 0x07, 0x0a, 0x03, 0x41, 0x44, 0x53, - 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06, 0x50, 0x48, 0x4f, 0x54, 0x4f, 0x53, 0x10, 0x03, 0x12, 0x0f, - 0x0a, 0x0b, 0x53, 0x54, 0x52, 0x45, 0x45, 0x54, 0x5f, 0x56, 0x49, 0x45, 0x57, 0x10, 0x04, 0x12, - 0x0c, 0x0a, 0x08, 0x53, 0x48, 0x4f, 0x50, 0x50, 0x49, 0x4e, 0x47, 0x10, 0x05, 0x12, 0x07, 0x0a, - 0x03, 0x47, 0x45, 0x4f, 0x10, 0x06, 0x12, 0x11, 0x0a, 0x0d, 0x47, 0x45, 0x4e, 0x45, 0x52, 0x41, - 0x54, 0x49, 0x56, 0x45, 0x5f, 0x41, 0x49, 0x10, 0x07, 0x2a, 0x67, 0x0a, 0x18, 0x43, 0x6c, 0x69, - 0x65, 0x6e, 0x74, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2a, 0x0a, 0x26, 0x43, 0x4c, 0x49, 0x45, 0x4e, 0x54, 0x5f, - 0x4c, 0x49, 0x42, 0x52, 0x41, 0x52, 0x59, 0x5f, 0x44, 0x45, 0x53, 0x54, 0x49, 0x4e, 0x41, 0x54, - 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, - 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x47, 0x49, 0x54, 0x48, 0x55, 0x42, 0x10, 0x0a, 0x12, 0x13, 0x0a, - 0x0f, 0x50, 0x41, 0x43, 0x4b, 0x41, 0x47, 0x45, 0x5f, 0x4d, 0x41, 0x4e, 0x41, 0x47, 0x45, 0x52, - 0x10, 0x14, 0x3a, 0x4a, 0x0a, 0x10, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x5f, 0x73, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x1e, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x4f, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x9b, 0x08, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x6d, - 0x65, 0x74, 0x68, 0x6f, 0x64, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x3a, 0x43, - 0x0a, 0x0c, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x12, 0x1f, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, - 0x99, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x48, - 0x6f, 0x73, 0x74, 0x3a, 0x43, 0x0a, 0x0c, 0x6f, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x73, 0x63, 0x6f, - 0x70, 0x65, 0x73, 0x12, 0x1f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4f, 0x70, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x9a, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6f, 0x61, 0x75, - 0x74, 0x68, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x3a, 0x44, 0x0a, 0x0b, 0x61, 0x70, 0x69, 0x5f, - 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xc1, 0xba, 0xab, 0xfa, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0a, 0x61, 0x70, 0x69, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x42, 0x69, - 0x0a, 0x0e, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x61, 0x70, 0x69, - 0x42, 0x0b, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, - 0x41, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2e, 0x6f, - 0x72, 0x67, 0x2f, 0x67, 0x65, 0x6e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x3b, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0xa2, 0x02, 0x04, 0x47, 0x41, 0x50, 0x49, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x33, + 0x69, 0x6f, 0x6e, 0x52, 0x10, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x50, 0x6f, 0x6c, 0x6c, 0x54, 0x69, + 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x2a, 0xa3, 0x01, 0x0a, 0x19, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, + 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x12, 0x2b, 0x0a, 0x27, 0x43, 0x4c, 0x49, 0x45, 0x4e, 0x54, 0x5f, 0x4c, 0x49, + 0x42, 0x52, 0x41, 0x52, 0x59, 0x5f, 0x4f, 0x52, 0x47, 0x41, 0x4e, 0x49, 0x5a, 0x41, 0x54, 0x49, + 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, + 0x12, 0x09, 0x0a, 0x05, 0x43, 0x4c, 0x4f, 0x55, 0x44, 0x10, 0x01, 0x12, 0x07, 0x0a, 0x03, 0x41, + 0x44, 0x53, 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06, 0x50, 0x48, 0x4f, 0x54, 0x4f, 0x53, 0x10, 0x03, + 0x12, 0x0f, 0x0a, 0x0b, 0x53, 0x54, 0x52, 0x45, 0x45, 0x54, 0x5f, 0x56, 0x49, 0x45, 0x57, 0x10, + 0x04, 0x12, 0x0c, 0x0a, 0x08, 0x53, 0x48, 0x4f, 0x50, 0x50, 0x49, 0x4e, 0x47, 0x10, 0x05, 0x12, + 0x07, 0x0a, 0x03, 0x47, 0x45, 0x4f, 0x10, 0x06, 0x12, 0x11, 0x0a, 0x0d, 0x47, 0x45, 0x4e, 0x45, + 0x52, 0x41, 0x54, 0x49, 0x56, 0x45, 0x5f, 0x41, 0x49, 0x10, 0x07, 0x2a, 0x67, 0x0a, 0x18, 0x43, + 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x44, 0x65, 0x73, 0x74, + 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2a, 0x0a, 0x26, 0x43, 0x4c, 0x49, 0x45, 0x4e, + 0x54, 0x5f, 0x4c, 0x49, 0x42, 0x52, 0x41, 0x52, 0x59, 0x5f, 0x44, 0x45, 0x53, 0x54, 0x49, 0x4e, + 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, + 0x44, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x47, 0x49, 0x54, 0x48, 0x55, 0x42, 0x10, 0x0a, 0x12, + 0x13, 0x0a, 0x0f, 0x50, 0x41, 0x43, 0x4b, 0x41, 0x47, 0x45, 0x5f, 0x4d, 0x41, 0x4e, 0x41, 0x47, + 0x45, 0x52, 0x10, 0x14, 0x3a, 0x4a, 0x0a, 0x10, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x5f, 0x73, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x1e, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65, 0x74, 0x68, 0x6f, + 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x9b, 0x08, 0x20, 0x03, 0x28, 0x09, 0x52, + 0x0f, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x3a, 0x43, 0x0a, 0x0c, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x68, 0x6f, 0x73, 0x74, + 0x12, 0x1f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x18, 0x99, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, + 0x74, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x43, 0x0a, 0x0c, 0x6f, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x73, + 0x63, 0x6f, 0x70, 0x65, 0x73, 0x12, 0x1f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4f, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x9a, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6f, + 0x61, 0x75, 0x74, 0x68, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x3a, 0x44, 0x0a, 0x0b, 0x61, 0x70, + 0x69, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xc1, 0xba, 0xab, 0xfa, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x61, 0x70, 0x69, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x42, 0x69, 0x0a, 0x0e, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x61, + 0x70, 0x69, 0x42, 0x0b, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, + 0x01, 0x5a, 0x41, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, + 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x67, 0x65, 0x6e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61, 0x6e, 0x6e, + 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x3b, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0xa2, 0x02, 0x04, 0x47, 0x41, 0x50, 0x49, 0x62, 0x06, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x33, } var ( @@ -1597,34 +1675,35 @@ func file_google_api_client_proto_rawDescGZIP() []byte { } var file_google_api_client_proto_enumTypes = make([]protoimpl.EnumInfo, 2) -var file_google_api_client_proto_msgTypes = make([]protoimpl.MessageInfo, 16) +var file_google_api_client_proto_msgTypes = make([]protoimpl.MessageInfo, 17) var file_google_api_client_proto_goTypes = []interface{}{ - (ClientLibraryOrganization)(0), // 0: google.api.ClientLibraryOrganization - (ClientLibraryDestination)(0), // 1: google.api.ClientLibraryDestination - (*CommonLanguageSettings)(nil), // 2: google.api.CommonLanguageSettings - (*ClientLibrarySettings)(nil), // 3: google.api.ClientLibrarySettings - (*Publishing)(nil), // 4: google.api.Publishing - (*JavaSettings)(nil), // 5: google.api.JavaSettings - (*CppSettings)(nil), // 6: google.api.CppSettings - (*PhpSettings)(nil), // 7: google.api.PhpSettings - (*PythonSettings)(nil), // 8: google.api.PythonSettings - (*NodeSettings)(nil), // 9: google.api.NodeSettings - (*DotnetSettings)(nil), // 10: google.api.DotnetSettings - (*RubySettings)(nil), // 11: google.api.RubySettings - (*GoSettings)(nil), // 12: google.api.GoSettings - (*MethodSettings)(nil), // 13: google.api.MethodSettings - nil, // 14: google.api.JavaSettings.ServiceClassNamesEntry - nil, // 15: google.api.DotnetSettings.RenamedServicesEntry - nil, // 16: google.api.DotnetSettings.RenamedResourcesEntry - (*MethodSettings_LongRunning)(nil), // 17: google.api.MethodSettings.LongRunning - (api.LaunchStage)(0), // 18: google.api.LaunchStage - (*durationpb.Duration)(nil), // 19: google.protobuf.Duration - (*descriptorpb.MethodOptions)(nil), // 20: google.protobuf.MethodOptions - (*descriptorpb.ServiceOptions)(nil), // 21: google.protobuf.ServiceOptions + (ClientLibraryOrganization)(0), // 0: google.api.ClientLibraryOrganization + (ClientLibraryDestination)(0), // 1: google.api.ClientLibraryDestination + (*CommonLanguageSettings)(nil), // 2: google.api.CommonLanguageSettings + (*ClientLibrarySettings)(nil), // 3: google.api.ClientLibrarySettings + (*Publishing)(nil), // 4: google.api.Publishing + (*JavaSettings)(nil), // 5: google.api.JavaSettings + (*CppSettings)(nil), // 6: google.api.CppSettings + (*PhpSettings)(nil), // 7: google.api.PhpSettings + (*PythonSettings)(nil), // 8: google.api.PythonSettings + (*NodeSettings)(nil), // 9: google.api.NodeSettings + (*DotnetSettings)(nil), // 10: google.api.DotnetSettings + (*RubySettings)(nil), // 11: google.api.RubySettings + (*GoSettings)(nil), // 12: google.api.GoSettings + (*MethodSettings)(nil), // 13: google.api.MethodSettings + nil, // 14: google.api.JavaSettings.ServiceClassNamesEntry + (*PythonSettings_ExperimentalFeatures)(nil), // 15: google.api.PythonSettings.ExperimentalFeatures + nil, // 16: google.api.DotnetSettings.RenamedServicesEntry + nil, // 17: google.api.DotnetSettings.RenamedResourcesEntry + (*MethodSettings_LongRunning)(nil), // 18: google.api.MethodSettings.LongRunning + (api.LaunchStage)(0), // 19: google.api.LaunchStage + (*durationpb.Duration)(nil), // 20: google.protobuf.Duration + (*descriptorpb.MethodOptions)(nil), // 21: google.protobuf.MethodOptions + (*descriptorpb.ServiceOptions)(nil), // 22: google.protobuf.ServiceOptions } var file_google_api_client_proto_depIdxs = []int32{ 1, // 0: google.api.CommonLanguageSettings.destinations:type_name -> google.api.ClientLibraryDestination - 18, // 1: google.api.ClientLibrarySettings.launch_stage:type_name -> google.api.LaunchStage + 19, // 1: google.api.ClientLibrarySettings.launch_stage:type_name -> google.api.LaunchStage 5, // 2: google.api.ClientLibrarySettings.java_settings:type_name -> google.api.JavaSettings 6, // 3: google.api.ClientLibrarySettings.cpp_settings:type_name -> google.api.CppSettings 7, // 4: google.api.ClientLibrarySettings.php_settings:type_name -> google.api.PhpSettings @@ -1641,25 +1720,26 @@ var file_google_api_client_proto_depIdxs = []int32{ 2, // 15: google.api.CppSettings.common:type_name -> google.api.CommonLanguageSettings 2, // 16: google.api.PhpSettings.common:type_name -> google.api.CommonLanguageSettings 2, // 17: google.api.PythonSettings.common:type_name -> google.api.CommonLanguageSettings - 2, // 18: google.api.NodeSettings.common:type_name -> google.api.CommonLanguageSettings - 2, // 19: google.api.DotnetSettings.common:type_name -> google.api.CommonLanguageSettings - 15, // 20: google.api.DotnetSettings.renamed_services:type_name -> google.api.DotnetSettings.RenamedServicesEntry - 16, // 21: google.api.DotnetSettings.renamed_resources:type_name -> google.api.DotnetSettings.RenamedResourcesEntry - 2, // 22: google.api.RubySettings.common:type_name -> google.api.CommonLanguageSettings - 2, // 23: google.api.GoSettings.common:type_name -> google.api.CommonLanguageSettings - 17, // 24: google.api.MethodSettings.long_running:type_name -> google.api.MethodSettings.LongRunning - 19, // 25: google.api.MethodSettings.LongRunning.initial_poll_delay:type_name -> google.protobuf.Duration - 19, // 26: google.api.MethodSettings.LongRunning.max_poll_delay:type_name -> google.protobuf.Duration - 19, // 27: google.api.MethodSettings.LongRunning.total_poll_timeout:type_name -> google.protobuf.Duration - 20, // 28: google.api.method_signature:extendee -> google.protobuf.MethodOptions - 21, // 29: google.api.default_host:extendee -> google.protobuf.ServiceOptions - 21, // 30: google.api.oauth_scopes:extendee -> google.protobuf.ServiceOptions - 21, // 31: google.api.api_version:extendee -> google.protobuf.ServiceOptions - 32, // [32:32] is the sub-list for method output_type - 32, // [32:32] is the sub-list for method input_type - 32, // [32:32] is the sub-list for extension type_name - 28, // [28:32] is the sub-list for extension extendee - 0, // [0:28] is the sub-list for field type_name + 15, // 18: google.api.PythonSettings.experimental_features:type_name -> google.api.PythonSettings.ExperimentalFeatures + 2, // 19: google.api.NodeSettings.common:type_name -> google.api.CommonLanguageSettings + 2, // 20: google.api.DotnetSettings.common:type_name -> google.api.CommonLanguageSettings + 16, // 21: google.api.DotnetSettings.renamed_services:type_name -> google.api.DotnetSettings.RenamedServicesEntry + 17, // 22: google.api.DotnetSettings.renamed_resources:type_name -> google.api.DotnetSettings.RenamedResourcesEntry + 2, // 23: google.api.RubySettings.common:type_name -> google.api.CommonLanguageSettings + 2, // 24: google.api.GoSettings.common:type_name -> google.api.CommonLanguageSettings + 18, // 25: google.api.MethodSettings.long_running:type_name -> google.api.MethodSettings.LongRunning + 20, // 26: google.api.MethodSettings.LongRunning.initial_poll_delay:type_name -> google.protobuf.Duration + 20, // 27: google.api.MethodSettings.LongRunning.max_poll_delay:type_name -> google.protobuf.Duration + 20, // 28: google.api.MethodSettings.LongRunning.total_poll_timeout:type_name -> google.protobuf.Duration + 21, // 29: google.api.method_signature:extendee -> google.protobuf.MethodOptions + 22, // 30: google.api.default_host:extendee -> google.protobuf.ServiceOptions + 22, // 31: google.api.oauth_scopes:extendee -> google.protobuf.ServiceOptions + 22, // 32: google.api.api_version:extendee -> google.protobuf.ServiceOptions + 33, // [33:33] is the sub-list for method output_type + 33, // [33:33] is the sub-list for method input_type + 33, // [33:33] is the sub-list for extension type_name + 29, // [29:33] is the sub-list for extension extendee + 0, // [0:29] is the sub-list for field type_name } func init() { file_google_api_client_proto_init() } @@ -1812,7 +1892,19 @@ func file_google_api_client_proto_init() { return nil } } - file_google_api_client_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { + file_google_api_client_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PythonSettings_ExperimentalFeatures); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_google_api_client_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*MethodSettings_LongRunning); i { case 0: return &v.state @@ -1831,7 +1923,7 @@ func file_google_api_client_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_google_api_client_proto_rawDesc, NumEnums: 2, - NumMessages: 16, + NumMessages: 17, NumExtensions: 4, NumServices: 0, }, diff --git a/vendor/google.golang.org/genproto/googleapis/api/annotations/field_behavior.pb.go b/vendor/google.golang.org/genproto/googleapis/api/annotations/field_behavior.pb.go index 312d7eb49..08505ba3f 100644 --- a/vendor/google.golang.org/genproto/googleapis/api/annotations/field_behavior.pb.go +++ b/vendor/google.golang.org/genproto/googleapis/api/annotations/field_behavior.pb.go @@ -1,4 +1,4 @@ -// Copyright 2023 Google LLC +// Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/vendor/google.golang.org/genproto/googleapis/api/annotations/field_info.pb.go b/vendor/google.golang.org/genproto/googleapis/api/annotations/field_info.pb.go index 6ff36206d..a462e7d01 100644 --- a/vendor/google.golang.org/genproto/googleapis/api/annotations/field_info.pb.go +++ b/vendor/google.golang.org/genproto/googleapis/api/annotations/field_info.pb.go @@ -1,4 +1,4 @@ -// Copyright 2023 Google LLC +// Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -121,6 +121,11 @@ type FieldInfo struct { // any API consumer, just documents the API's format for the field it is // applied to. Format FieldInfo_Format `protobuf:"varint,1,opt,name=format,proto3,enum=google.api.FieldInfo_Format" json:"format,omitempty"` + // The type(s) that the annotated, generic field may represent. + // + // Currently, this must only be used on fields of type `google.protobuf.Any`. + // Supporting other generic types may be considered in the future. + ReferencedTypes []*TypeReference `protobuf:"bytes,2,rep,name=referenced_types,json=referencedTypes,proto3" json:"referenced_types,omitempty"` } func (x *FieldInfo) Reset() { @@ -162,6 +167,70 @@ func (x *FieldInfo) GetFormat() FieldInfo_Format { return FieldInfo_FORMAT_UNSPECIFIED } +func (x *FieldInfo) GetReferencedTypes() []*TypeReference { + if x != nil { + return x.ReferencedTypes + } + return nil +} + +// A reference to a message type, for use in [FieldInfo][google.api.FieldInfo]. +type TypeReference struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // The name of the type that the annotated, generic field may represent. + // If the type is in the same protobuf package, the value can be the simple + // message name e.g., `"MyMessage"`. Otherwise, the value must be the + // fully-qualified message name e.g., `"google.library.v1.Book"`. + // + // If the type(s) are unknown to the service (e.g. the field accepts generic + // user input), use the wildcard `"*"` to denote this behavior. + // + // See [AIP-202](https://google.aip.dev/202#type-references) for more details. + TypeName string `protobuf:"bytes,1,opt,name=type_name,json=typeName,proto3" json:"type_name,omitempty"` +} + +func (x *TypeReference) Reset() { + *x = TypeReference{} + if protoimpl.UnsafeEnabled { + mi := &file_google_api_field_info_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TypeReference) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TypeReference) ProtoMessage() {} + +func (x *TypeReference) ProtoReflect() protoreflect.Message { + mi := &file_google_api_field_info_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TypeReference.ProtoReflect.Descriptor instead. +func (*TypeReference) Descriptor() ([]byte, []int) { + return file_google_api_field_info_proto_rawDescGZIP(), []int{1} +} + +func (x *TypeReference) GetTypeName() string { + if x != nil { + return x.TypeName + } + return "" +} + var file_google_api_field_info_proto_extTypes = []protoimpl.ExtensionInfo{ { ExtendedType: (*descriptorpb.FieldOptions)(nil), @@ -185,6 +254,13 @@ var ( // string actual_ip_address = 4 [ // (google.api.field_info).format = IPV4_OR_IPV6 // ]; + // google.protobuf.Any generic_field = 5 [ + // (google.api.field_info).referenced_types = {type_name: "ActualType"}, + // (google.api.field_info).referenced_types = {type_name: "OtherType"}, + // ]; + // google.protobuf.Any generic_user_input = 5 [ + // (google.api.field_info).referenced_types = {type_name: "*"}, + // ]; // // optional google.api.FieldInfo field_info = 291403980; E_FieldInfo = &file_google_api_field_info_proto_extTypes[0] @@ -197,30 +273,37 @@ var file_google_api_field_info_proto_rawDesc = []byte{ 0x6c, 0x64, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0a, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x61, 0x70, 0x69, 0x1a, 0x20, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x65, 0x73, 0x63, 0x72, - 0x69, 0x70, 0x74, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x94, 0x01, 0x0a, 0x09, + 0x69, 0x70, 0x74, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xda, 0x01, 0x0a, 0x09, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x34, 0x0a, 0x06, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x49, 0x6e, 0x66, 0x6f, - 0x2e, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x52, 0x06, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x22, - 0x51, 0x0a, 0x06, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x16, 0x0a, 0x12, 0x46, 0x4f, 0x52, - 0x4d, 0x41, 0x54, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, - 0x00, 0x12, 0x09, 0x0a, 0x05, 0x55, 0x55, 0x49, 0x44, 0x34, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, - 0x49, 0x50, 0x56, 0x34, 0x10, 0x02, 0x12, 0x08, 0x0a, 0x04, 0x49, 0x50, 0x56, 0x36, 0x10, 0x03, - 0x12, 0x10, 0x0a, 0x0c, 0x49, 0x50, 0x56, 0x34, 0x5f, 0x4f, 0x52, 0x5f, 0x49, 0x50, 0x56, 0x36, - 0x10, 0x04, 0x3a, 0x57, 0x0a, 0x0a, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x69, 0x6e, 0x66, 0x6f, - 0x12, 0x1d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, - 0xcc, 0xf1, 0xf9, 0x8a, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x49, 0x6e, 0x66, 0x6f, - 0x52, 0x09, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x49, 0x6e, 0x66, 0x6f, 0x42, 0x6c, 0x0a, 0x0e, 0x63, - 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x61, 0x70, 0x69, 0x42, 0x0e, 0x46, - 0x69, 0x65, 0x6c, 0x64, 0x49, 0x6e, 0x66, 0x6f, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, - 0x41, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2e, 0x6f, - 0x72, 0x67, 0x2f, 0x67, 0x65, 0x6e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x3b, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0xa2, 0x02, 0x04, 0x47, 0x41, 0x50, 0x49, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x33, + 0x2e, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x52, 0x06, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, + 0x44, 0x0a, 0x10, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x64, 0x5f, 0x74, 0x79, + 0x70, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x65, 0x66, 0x65, 0x72, + 0x65, 0x6e, 0x63, 0x65, 0x52, 0x0f, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x64, + 0x54, 0x79, 0x70, 0x65, 0x73, 0x22, 0x51, 0x0a, 0x06, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, + 0x16, 0x0a, 0x12, 0x46, 0x4f, 0x52, 0x4d, 0x41, 0x54, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, + 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x55, 0x55, 0x49, 0x44, 0x34, + 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x49, 0x50, 0x56, 0x34, 0x10, 0x02, 0x12, 0x08, 0x0a, 0x04, + 0x49, 0x50, 0x56, 0x36, 0x10, 0x03, 0x12, 0x10, 0x0a, 0x0c, 0x49, 0x50, 0x56, 0x34, 0x5f, 0x4f, + 0x52, 0x5f, 0x49, 0x50, 0x56, 0x36, 0x10, 0x04, 0x22, 0x2c, 0x0a, 0x0d, 0x54, 0x79, 0x70, 0x65, + 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x79, 0x70, + 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x79, + 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x3a, 0x57, 0x0a, 0x0a, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, + 0x69, 0x6e, 0x66, 0x6f, 0x12, 0x1d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x18, 0xcc, 0xf1, 0xf9, 0x8a, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, + 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x09, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x49, 0x6e, 0x66, 0x6f, 0x42, + 0x6c, 0x0a, 0x0e, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x61, 0x70, + 0x69, 0x42, 0x0e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x49, 0x6e, 0x66, 0x6f, 0x50, 0x72, 0x6f, 0x74, + 0x6f, 0x50, 0x01, 0x5a, 0x41, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x67, 0x6f, 0x6c, 0x61, + 0x6e, 0x67, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x67, 0x65, 0x6e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61, + 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x3b, 0x61, 0x6e, 0x6e, 0x6f, 0x74, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0xa2, 0x02, 0x04, 0x47, 0x41, 0x50, 0x49, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -236,21 +319,23 @@ func file_google_api_field_info_proto_rawDescGZIP() []byte { } var file_google_api_field_info_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_google_api_field_info_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_google_api_field_info_proto_msgTypes = make([]protoimpl.MessageInfo, 2) var file_google_api_field_info_proto_goTypes = []interface{}{ (FieldInfo_Format)(0), // 0: google.api.FieldInfo.Format (*FieldInfo)(nil), // 1: google.api.FieldInfo - (*descriptorpb.FieldOptions)(nil), // 2: google.protobuf.FieldOptions + (*TypeReference)(nil), // 2: google.api.TypeReference + (*descriptorpb.FieldOptions)(nil), // 3: google.protobuf.FieldOptions } var file_google_api_field_info_proto_depIdxs = []int32{ 0, // 0: google.api.FieldInfo.format:type_name -> google.api.FieldInfo.Format - 2, // 1: google.api.field_info:extendee -> google.protobuf.FieldOptions - 1, // 2: google.api.field_info:type_name -> google.api.FieldInfo - 3, // [3:3] is the sub-list for method output_type - 3, // [3:3] is the sub-list for method input_type - 2, // [2:3] is the sub-list for extension type_name - 1, // [1:2] is the sub-list for extension extendee - 0, // [0:1] is the sub-list for field type_name + 2, // 1: google.api.FieldInfo.referenced_types:type_name -> google.api.TypeReference + 3, // 2: google.api.field_info:extendee -> google.protobuf.FieldOptions + 1, // 3: google.api.field_info:type_name -> google.api.FieldInfo + 4, // [4:4] is the sub-list for method output_type + 4, // [4:4] is the sub-list for method input_type + 3, // [3:4] is the sub-list for extension type_name + 2, // [2:3] is the sub-list for extension extendee + 0, // [0:2] is the sub-list for field type_name } func init() { file_google_api_field_info_proto_init() } @@ -271,6 +356,18 @@ func file_google_api_field_info_proto_init() { return nil } } + file_google_api_field_info_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TypeReference); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } type x struct{} out := protoimpl.TypeBuilder{ @@ -278,7 +375,7 @@ func file_google_api_field_info_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_google_api_field_info_proto_rawDesc, NumEnums: 1, - NumMessages: 1, + NumMessages: 2, NumExtensions: 1, NumServices: 0, }, diff --git a/vendor/google.golang.org/genproto/googleapis/api/annotations/http.pb.go b/vendor/google.golang.org/genproto/googleapis/api/annotations/http.pb.go index 8a0e1c345..ffb5838cb 100644 --- a/vendor/google.golang.org/genproto/googleapis/api/annotations/http.pb.go +++ b/vendor/google.golang.org/genproto/googleapis/api/annotations/http.pb.go @@ -1,4 +1,4 @@ -// Copyright 2023 Google LLC +// Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -15,7 +15,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.26.0 -// protoc v3.21.9 +// protoc v4.24.4 // source: google/api/http.proto package annotations @@ -102,7 +102,7 @@ func (x *Http) GetFullyDecodeReservedExpansion() bool { return false } -// # gRPC Transcoding +// gRPC Transcoding // // gRPC Transcoding is a feature for mapping between a gRPC method and one or // more HTTP REST endpoints. It allows developers to build a single API service @@ -143,9 +143,8 @@ func (x *Http) GetFullyDecodeReservedExpansion() bool { // // This enables an HTTP REST to gRPC mapping as below: // -// HTTP | gRPC -// -----|----- -// `GET /v1/messages/123456` | `GetMessage(name: "messages/123456")` +// - HTTP: `GET /v1/messages/123456` +// - gRPC: `GetMessage(name: "messages/123456")` // // Any fields in the request message which are not bound by the path template // automatically become HTTP query parameters if there is no HTTP request body. @@ -169,11 +168,9 @@ func (x *Http) GetFullyDecodeReservedExpansion() bool { // // This enables a HTTP JSON to RPC mapping as below: // -// HTTP | gRPC -// -----|----- -// `GET /v1/messages/123456?revision=2&sub.subfield=foo` | -// `GetMessage(message_id: "123456" revision: 2 sub: SubMessage(subfield: -// "foo"))` +// - HTTP: `GET /v1/messages/123456?revision=2&sub.subfield=foo` +// - gRPC: `GetMessage(message_id: "123456" revision: 2 sub: +// SubMessage(subfield: "foo"))` // // Note that fields which are mapped to URL query parameters must have a // primitive type or a repeated primitive type or a non-repeated message type. @@ -203,10 +200,8 @@ func (x *Http) GetFullyDecodeReservedExpansion() bool { // representation of the JSON in the request body is determined by // protos JSON encoding: // -// HTTP | gRPC -// -----|----- -// `PATCH /v1/messages/123456 { "text": "Hi!" }` | `UpdateMessage(message_id: -// "123456" message { text: "Hi!" })` +// - HTTP: `PATCH /v1/messages/123456 { "text": "Hi!" }` +// - gRPC: `UpdateMessage(message_id: "123456" message { text: "Hi!" })` // // The special name `*` can be used in the body mapping to define that // every field not bound by the path template should be mapped to the @@ -228,10 +223,8 @@ func (x *Http) GetFullyDecodeReservedExpansion() bool { // // The following HTTP JSON to RPC mapping is enabled: // -// HTTP | gRPC -// -----|----- -// `PATCH /v1/messages/123456 { "text": "Hi!" }` | `UpdateMessage(message_id: -// "123456" text: "Hi!")` +// - HTTP: `PATCH /v1/messages/123456 { "text": "Hi!" }` +// - gRPC: `UpdateMessage(message_id: "123456" text: "Hi!")` // // Note that when using `*` in the body mapping, it is not possible to // have HTTP parameters, as all fields not bound by the path end in @@ -259,13 +252,13 @@ func (x *Http) GetFullyDecodeReservedExpansion() bool { // // This enables the following two alternative HTTP JSON to RPC mappings: // -// HTTP | gRPC -// -----|----- -// `GET /v1/messages/123456` | `GetMessage(message_id: "123456")` -// `GET /v1/users/me/messages/123456` | `GetMessage(user_id: "me" message_id: -// "123456")` +// - HTTP: `GET /v1/messages/123456` +// - gRPC: `GetMessage(message_id: "123456")` // -// ## Rules for HTTP mapping +// - HTTP: `GET /v1/users/me/messages/123456` +// - gRPC: `GetMessage(user_id: "me" message_id: "123456")` +// +// # Rules for HTTP mapping // // 1. Leaf request fields (recursive expansion nested messages in the request // message) are classified into three categories: @@ -284,7 +277,7 @@ func (x *Http) GetFullyDecodeReservedExpansion() bool { // request body, all // fields are passed via URL path and URL query parameters. // -// ### Path template syntax +// Path template syntax // // Template = "/" Segments [ Verb ] ; // Segments = Segment { "/" Segment } ; @@ -323,7 +316,7 @@ func (x *Http) GetFullyDecodeReservedExpansion() bool { // Document](https://developers.google.com/discovery/v1/reference/apis) as // `{+var}`. // -// ## Using gRPC API Service Configuration +// # Using gRPC API Service Configuration // // gRPC API Service Configuration (service config) is a configuration language // for configuring a gRPC service to become a user-facing product. The @@ -338,15 +331,14 @@ func (x *Http) GetFullyDecodeReservedExpansion() bool { // specified in the service config will override any matching transcoding // configuration in the proto. // -// Example: +// The following example selects a gRPC method and applies an `HttpRule` to it: // // http: // rules: -// # Selects a gRPC method and applies HttpRule to it. // - selector: example.v1.Messaging.GetMessage // get: /v1/messages/{message_id}/{sub.subfield} // -// ## Special notes +// # Special notes // // When gRPC Transcoding is used to map a gRPC to JSON REST endpoints, the // proto to JSON conversion must follow the [proto3 diff --git a/vendor/google.golang.org/genproto/googleapis/api/annotations/resource.pb.go b/vendor/google.golang.org/genproto/googleapis/api/annotations/resource.pb.go index bbcc12d29..b5db279ae 100644 --- a/vendor/google.golang.org/genproto/googleapis/api/annotations/resource.pb.go +++ b/vendor/google.golang.org/genproto/googleapis/api/annotations/resource.pb.go @@ -1,4 +1,4 @@ -// Copyright 2023 Google LLC +// Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -15,7 +15,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.26.0 -// protoc v3.21.9 +// protoc v4.24.4 // source: google/api/resource.proto package annotations @@ -253,8 +253,13 @@ type ResourceDescriptor struct { History ResourceDescriptor_History `protobuf:"varint,4,opt,name=history,proto3,enum=google.api.ResourceDescriptor_History" json:"history,omitempty"` // The plural name used in the resource name and permission names, such as // 'projects' for the resource name of 'projects/{project}' and the permission - // name of 'cloudresourcemanager.googleapis.com/projects.get'. It is the same - // concept of the `plural` field in k8s CRD spec + // name of 'cloudresourcemanager.googleapis.com/projects.get'. One exception + // to this is for Nested Collections that have stuttering names, as defined + // in [AIP-122](https://google.aip.dev/122#nested-collections), where the + // collection ID in the resource name pattern does not necessarily directly + // match the `plural` value. + // + // It is the same concept of the `plural` field in k8s CRD spec // https://kubernetes.io/docs/tasks/access-kubernetes-api/custom-resources/custom-resource-definitions/ // // Note: The plural form is required even for singleton resources. See diff --git a/vendor/google.golang.org/genproto/googleapis/api/annotations/routing.pb.go b/vendor/google.golang.org/genproto/googleapis/api/annotations/routing.pb.go index 9a9ae04c2..1d8397b02 100644 --- a/vendor/google.golang.org/genproto/googleapis/api/annotations/routing.pb.go +++ b/vendor/google.golang.org/genproto/googleapis/api/annotations/routing.pb.go @@ -1,4 +1,4 @@ -// Copyright 2023 Google LLC +// Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -15,7 +15,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.26.0 -// protoc v3.21.9 +// protoc v4.24.4 // source: google/api/routing.proto package annotations diff --git a/vendor/google.golang.org/genproto/googleapis/api/launch_stage.pb.go b/vendor/google.golang.org/genproto/googleapis/api/launch_stage.pb.go index 454948669..498020e33 100644 --- a/vendor/google.golang.org/genproto/googleapis/api/launch_stage.pb.go +++ b/vendor/google.golang.org/genproto/googleapis/api/launch_stage.pb.go @@ -1,4 +1,4 @@ -// Copyright 2023 Google LLC +// Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -15,7 +15,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.26.0 -// protoc v3.21.9 +// protoc v4.24.4 // source: google/api/launch_stage.proto package api diff --git a/vendor/google.golang.org/genproto/googleapis/rpc/status/status.pb.go b/vendor/google.golang.org/genproto/googleapis/rpc/status/status.pb.go index a6b508188..6ad1b1c1d 100644 --- a/vendor/google.golang.org/genproto/googleapis/rpc/status/status.pb.go +++ b/vendor/google.golang.org/genproto/googleapis/rpc/status/status.pb.go @@ -1,4 +1,4 @@ -// Copyright 2022 Google LLC +// Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -15,7 +15,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.26.0 -// protoc v3.21.9 +// protoc v4.24.4 // source: google/rpc/status.proto package status diff --git a/vendor/google.golang.org/grpc/CONTRIBUTING.md b/vendor/google.golang.org/grpc/CONTRIBUTING.md index 608aa6e1a..d9bfa6e1e 100644 --- a/vendor/google.golang.org/grpc/CONTRIBUTING.md +++ b/vendor/google.golang.org/grpc/CONTRIBUTING.md @@ -4,7 +4,7 @@ We definitely welcome your patches and contributions to gRPC! Please read the gR organization's [governance rules](https://github.com/grpc/grpc-community/blob/master/governance.md) and [contribution guidelines](https://github.com/grpc/grpc-community/blob/master/CONTRIBUTING.md) before proceeding. -If you are new to github, please start by reading [Pull Request howto](https://help.github.com/articles/about-pull-requests/) +If you are new to GitHub, please start by reading [Pull Request howto](https://help.github.com/articles/about-pull-requests/) ## Legal requirements @@ -25,8 +25,8 @@ How to get your contributions merged smoothly and quickly. is a great place to start. These issues are well-documented and usually can be resolved with a single pull request. -- If you are adding a new file, make sure it has the copyright message template - at the top as a comment. You can copy over the message from an existing file +- If you are adding a new file, make sure it has the copyright message template + at the top as a comment. You can copy over the message from an existing file and update the year. - The grpc package should only depend on standard Go packages and a small number @@ -39,12 +39,12 @@ How to get your contributions merged smoothly and quickly. proposal](https://github.com/grpc/proposal). - Provide a good **PR description** as a record of **what** change is being made - and **why** it was made. Link to a github issue if it exists. + and **why** it was made. Link to a GitHub issue if it exists. -- If you want to fix formatting or style, consider whether your changes are an - obvious improvement or might be considered a personal preference. If a style - change is based on preference, it likely will not be accepted. If it corrects - widely agreed-upon anti-patterns, then please do create a PR and explain the +- If you want to fix formatting or style, consider whether your changes are an + obvious improvement or might be considered a personal preference. If a style + change is based on preference, it likely will not be accepted. If it corrects + widely agreed-upon anti-patterns, then please do create a PR and explain the benefits of the change. - Unless your PR is trivial, you should expect there will be reviewer comments @@ -66,7 +66,7 @@ How to get your contributions merged smoothly and quickly. - **All tests need to be passing** before your change can be merged. We recommend you **run tests locally** before creating your PR to catch breakages early on. - - `VET_SKIP_PROTO=1 ./vet.sh` to catch vet errors + - `./scripts/vet.sh` to catch vet errors - `go test -cpu 1,4 -timeout 7m ./...` to run the tests - `go test -race -cpu 1,4 -timeout 7m ./...` to run tests in race mode diff --git a/vendor/google.golang.org/grpc/MAINTAINERS.md b/vendor/google.golang.org/grpc/MAINTAINERS.md index c6672c0a3..5d4096d46 100644 --- a/vendor/google.golang.org/grpc/MAINTAINERS.md +++ b/vendor/google.golang.org/grpc/MAINTAINERS.md @@ -9,20 +9,28 @@ for general contribution guidelines. ## Maintainers (in alphabetical order) -- [cesarghali](https://github.com/cesarghali), Google LLC +- [aranjans](https://github.com/aranjans), Google LLC +- [arjan-bal](https://github.com/arjan-bal), Google LLC +- [arvindbr8](https://github.com/arvindbr8), Google LLC +- [atollena](https://github.com/atollena), Datadog, Inc. - [dfawley](https://github.com/dfawley), Google LLC - [easwars](https://github.com/easwars), Google LLC -- [menghanl](https://github.com/menghanl), Google LLC -- [srini100](https://github.com/srini100), Google LLC +- [erm-g](https://github.com/erm-g), Google LLC +- [gtcooke94](https://github.com/gtcooke94), Google LLC +- [purnesh42h](https://github.com/purnesh42h), Google LLC +- [zasweq](https://github.com/zasweq), Google LLC ## Emeritus Maintainers (in alphabetical order) -- [adelez](https://github.com/adelez), Google LLC -- [canguler](https://github.com/canguler), Google LLC -- [iamqizhao](https://github.com/iamqizhao), Google LLC -- [jadekler](https://github.com/jadekler), Google LLC -- [jtattermusch](https://github.com/jtattermusch), Google LLC -- [lyuxuan](https://github.com/lyuxuan), Google LLC -- [makmukhi](https://github.com/makmukhi), Google LLC -- [matt-kwong](https://github.com/matt-kwong), Google LLC -- [nicolasnoble](https://github.com/nicolasnoble), Google LLC -- [yongni](https://github.com/yongni), Google LLC +- [adelez](https://github.com/adelez) +- [canguler](https://github.com/canguler) +- [cesarghali](https://github.com/cesarghali) +- [iamqizhao](https://github.com/iamqizhao) +- [jeanbza](https://github.com/jeanbza) +- [jtattermusch](https://github.com/jtattermusch) +- [lyuxuan](https://github.com/lyuxuan) +- [makmukhi](https://github.com/makmukhi) +- [matt-kwong](https://github.com/matt-kwong) +- [menghanl](https://github.com/menghanl) +- [nicolasnoble](https://github.com/nicolasnoble) +- [srini100](https://github.com/srini100) +- [yongni](https://github.com/yongni) diff --git a/vendor/google.golang.org/grpc/Makefile b/vendor/google.golang.org/grpc/Makefile index 1f8960922..be38384ff 100644 --- a/vendor/google.golang.org/grpc/Makefile +++ b/vendor/google.golang.org/grpc/Makefile @@ -30,17 +30,20 @@ testdeps: GO111MODULE=on go get -d -v -t google.golang.org/grpc/... vet: vetdeps - ./vet.sh + ./scripts/vet.sh vetdeps: - ./vet.sh -install + ./scripts/vet.sh -install .PHONY: \ all \ build \ clean \ + deps \ proto \ test \ + testsubmodule \ testrace \ + testdeps \ vet \ vetdeps diff --git a/vendor/google.golang.org/grpc/README.md b/vendor/google.golang.org/grpc/README.md index ab0fbb79b..b572707c6 100644 --- a/vendor/google.golang.org/grpc/README.md +++ b/vendor/google.golang.org/grpc/README.md @@ -10,7 +10,7 @@ RPC framework that puts mobile and HTTP/2 first. For more information see the ## Prerequisites -- **[Go][]**: any one of the **three latest major** [releases][go-releases]. +- **[Go][]**: any one of the **two latest major** [releases][go-releases]. ## Installation diff --git a/vendor/google.golang.org/grpc/SECURITY.md b/vendor/google.golang.org/grpc/SECURITY.md index be6e10870..abab27937 100644 --- a/vendor/google.golang.org/grpc/SECURITY.md +++ b/vendor/google.golang.org/grpc/SECURITY.md @@ -1,3 +1,3 @@ # Security Policy -For information on gRPC Security Policy and reporting potentional security issues, please see [gRPC CVE Process](https://github.com/grpc/proposal/blob/master/P4-grpc-cve-process.md). +For information on gRPC Security Policy and reporting potential security issues, please see [gRPC CVE Process](https://github.com/grpc/proposal/blob/master/P4-grpc-cve-process.md). diff --git a/vendor/google.golang.org/grpc/backoff/backoff.go b/vendor/google.golang.org/grpc/backoff/backoff.go index 0787d0b50..d7b40b7cb 100644 --- a/vendor/google.golang.org/grpc/backoff/backoff.go +++ b/vendor/google.golang.org/grpc/backoff/backoff.go @@ -39,7 +39,7 @@ type Config struct { MaxDelay time.Duration } -// DefaultConfig is a backoff configuration with the default values specfied +// DefaultConfig is a backoff configuration with the default values specified // at https://github.com/grpc/grpc/blob/master/doc/connection-backoff.md. // // This should be useful for callers who want to configure backoff with diff --git a/vendor/google.golang.org/grpc/balancer/balancer.go b/vendor/google.golang.org/grpc/balancer/balancer.go index f391744f7..3a2092f10 100644 --- a/vendor/google.golang.org/grpc/balancer/balancer.go +++ b/vendor/google.golang.org/grpc/balancer/balancer.go @@ -30,6 +30,7 @@ import ( "google.golang.org/grpc/channelz" "google.golang.org/grpc/connectivity" "google.golang.org/grpc/credentials" + estats "google.golang.org/grpc/experimental/stats" "google.golang.org/grpc/grpclog" "google.golang.org/grpc/internal" "google.golang.org/grpc/metadata" @@ -72,8 +73,21 @@ func unregisterForTesting(name string) { delete(m, name) } +// connectedAddress returns the connected address for a SubConnState. The +// address is only valid if the state is READY. +func connectedAddress(scs SubConnState) resolver.Address { + return scs.connectedAddress +} + +// setConnectedAddress sets the connected address for a SubConnState. +func setConnectedAddress(scs *SubConnState, addr resolver.Address) { + scs.connectedAddress = addr +} + func init() { internal.BalancerUnregister = unregisterForTesting + internal.ConnectedAddress = connectedAddress + internal.SetConnectedAddress = setConnectedAddress } // Get returns the resolver builder registered with the given name. @@ -116,7 +130,7 @@ type SubConn interface { // UpdateAddresses updates the addresses used in this SubConn. // gRPC checks if currently-connected address is still in the new list. // If it's in the list, the connection will be kept. - // If it's not in the list, the connection will gracefully closed, and + // If it's not in the list, the connection will gracefully close, and // a new connection will be created. // // This will trigger a state transition for the SubConn. @@ -128,8 +142,11 @@ type SubConn interface { Connect() // GetOrBuildProducer returns a reference to the existing Producer for this // ProducerBuilder in this SubConn, or, if one does not currently exist, - // creates a new one and returns it. Returns a close function which must - // be called when the Producer is no longer needed. + // creates a new one and returns it. Returns a close function which may be + // called when the Producer is no longer needed. Otherwise the producer + // will automatically be closed upon connection loss or subchannel close. + // Should only be called on a SubConn in state Ready. Otherwise the + // producer will be unable to create streams. GetOrBuildProducer(ProducerBuilder) (p Producer, close func()) // Shutdown shuts down the SubConn gracefully. Any started RPCs will be // allowed to complete. No future calls should be made on the SubConn. @@ -243,6 +260,10 @@ type BuildOptions struct { // same resolver.Target as passed to the resolver. See the documentation for // the resolver.Target type for details about what it contains. Target resolver.Target + // MetricsRecorder is the metrics recorder that balancers can use to record + // metrics. Balancer implementations which do not register metrics on + // metrics registry and record on them can ignore this field. + MetricsRecorder estats.MetricsRecorder } // Builder creates a balancer. @@ -410,6 +431,9 @@ type SubConnState struct { // ConnectionError is set if the ConnectivityState is TransientFailure, // describing the reason the SubConn failed. Otherwise, it is nil. ConnectionError error + // connectedAddr contains the connected address when ConnectivityState is + // Ready. Otherwise, it is indeterminate. + connectedAddress resolver.Address } // ClientConnState describes the state of a ClientConn relevant to the @@ -431,8 +455,10 @@ type ProducerBuilder interface { // Build creates a Producer. The first parameter is always a // grpc.ClientConnInterface (a type to allow creating RPCs/streams on the // associated SubConn), but is declared as `any` to avoid a dependency - // cycle. Should also return a close function that will be called when all - // references to the Producer have been given up. + // cycle. Build also returns a close function that will be called when all + // references to the Producer have been given up for a SubConn, or when a + // connectivity state change occurs on the SubConn. The close function + // should always block until all asynchronous cleanup work is completed. Build(grpcClientConnInterface any) (p Producer, close func()) } diff --git a/vendor/google.golang.org/grpc/balancer/base/balancer.go b/vendor/google.golang.org/grpc/balancer/base/balancer.go index a7f1eeec8..d5ed172ae 100644 --- a/vendor/google.golang.org/grpc/balancer/base/balancer.go +++ b/vendor/google.golang.org/grpc/balancer/base/balancer.go @@ -36,7 +36,7 @@ type baseBuilder struct { config Config } -func (bb *baseBuilder) Build(cc balancer.ClientConn, opt balancer.BuildOptions) balancer.Balancer { +func (bb *baseBuilder) Build(cc balancer.ClientConn, _ balancer.BuildOptions) balancer.Balancer { bal := &baseBalancer{ cc: cc, pickerBuilder: bb.pickerBuilder, @@ -133,7 +133,7 @@ func (b *baseBalancer) UpdateClientConnState(s balancer.ClientConnState) error { } } // If resolver state contains no addresses, return an error so ClientConn - // will trigger re-resolve. Also records this as an resolver error, so when + // will trigger re-resolve. Also records this as a resolver error, so when // the overall state turns transient failure, the error message will have // the zero address information. if len(s.ResolverState.Addresses) == 0 { @@ -259,6 +259,6 @@ type errPicker struct { err error // Pick() always returns this err. } -func (p *errPicker) Pick(info balancer.PickInfo) (balancer.PickResult, error) { +func (p *errPicker) Pick(balancer.PickInfo) (balancer.PickResult, error) { return balancer.PickResult{}, p.err } diff --git a/vendor/google.golang.org/grpc/balancer/pickfirst/internal/internal.go b/vendor/google.golang.org/grpc/balancer/pickfirst/internal/internal.go new file mode 100644 index 000000000..c51978945 --- /dev/null +++ b/vendor/google.golang.org/grpc/balancer/pickfirst/internal/internal.go @@ -0,0 +1,24 @@ +/* + * Copyright 2024 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. + * + */ + +// Package internal contains code internal to the pickfirst package. +package internal + +import "math/rand" + +// RandShuffle pseudo-randomizes the order of addresses. +var RandShuffle = rand.Shuffle diff --git a/vendor/google.golang.org/grpc/pickfirst.go b/vendor/google.golang.org/grpc/balancer/pickfirst/pickfirst.go similarity index 70% rename from vendor/google.golang.org/grpc/pickfirst.go rename to vendor/google.golang.org/grpc/balancer/pickfirst/pickfirst.go index e3ea42ba9..e069346a7 100644 --- a/vendor/google.golang.org/grpc/pickfirst.go +++ b/vendor/google.golang.org/grpc/balancer/pickfirst/pickfirst.go @@ -16,45 +16,60 @@ * */ -package grpc +// Package pickfirst contains the pick_first load balancing policy. +package pickfirst import ( "encoding/json" "errors" "fmt" + "math/rand" "google.golang.org/grpc/balancer" + "google.golang.org/grpc/balancer/pickfirst/internal" "google.golang.org/grpc/connectivity" + "google.golang.org/grpc/grpclog" + "google.golang.org/grpc/internal/envconfig" internalgrpclog "google.golang.org/grpc/internal/grpclog" - "google.golang.org/grpc/internal/grpcrand" "google.golang.org/grpc/internal/pretty" "google.golang.org/grpc/resolver" "google.golang.org/grpc/serviceconfig" + + _ "google.golang.org/grpc/balancer/pickfirst/pickfirstleaf" // For automatically registering the new pickfirst if required. ) +func init() { + if envconfig.NewPickFirstEnabled { + return + } + balancer.Register(pickfirstBuilder{}) +} + +var logger = grpclog.Component("pick-first-lb") + const ( - // PickFirstBalancerName is the name of the pick_first balancer. - PickFirstBalancerName = "pick_first" - logPrefix = "[pick-first-lb %p] " + // Name is the name of the pick_first balancer. + Name = "pick_first" + logPrefix = "[pick-first-lb %p] " ) type pickfirstBuilder struct{} -func (pickfirstBuilder) Build(cc balancer.ClientConn, opt balancer.BuildOptions) balancer.Balancer { +func (pickfirstBuilder) Build(cc balancer.ClientConn, _ balancer.BuildOptions) balancer.Balancer { b := &pickfirstBalancer{cc: cc} b.logger = internalgrpclog.NewPrefixLogger(logger, fmt.Sprintf(logPrefix, b)) return b } func (pickfirstBuilder) Name() string { - return PickFirstBalancerName + return Name } type pfConfig struct { serviceconfig.LoadBalancingConfig `json:"-"` // If set to true, instructs the LB policy to shuffle the order of the list - // of addresses received from the name resolver before attempting to + // of endpoints received from the name resolver before attempting to // connect to them. ShuffleAddressList bool `json:"shuffleAddressList"` } @@ -93,9 +108,17 @@ func (b *pickfirstBalancer) ResolverError(err error) { }) } +// Shuffler is an interface for shuffling an address list. +type Shuffler interface { + ShuffleAddressListForTesting(n int, swap func(i, j int)) +} + +// ShuffleAddressListForTesting pseudo-randomizes the order of addresses. n +// is the number of elements. swap swaps the elements with indexes i and j. +func ShuffleAddressListForTesting(n int, swap func(i, j int)) { rand.Shuffle(n, swap) } + func (b *pickfirstBalancer) UpdateClientConnState(state balancer.ClientConnState) error { - addrs := state.ResolverState.Addresses - if len(addrs) == 0 { + if len(state.ResolverState.Addresses) == 0 && len(state.ResolverState.Endpoints) == 0 { // The resolver reported an empty address list. Treat it like an error by // calling b.ResolverError. if b.subConn != nil { @@ -107,22 +130,49 @@ func (b *pickfirstBalancer) UpdateClientConnState(state balancer.ClientConnState b.ResolverError(errors.New("produced zero addresses")) return balancer.ErrBadResolverState } - // We don't have to guard this block with the env var because ParseConfig // already does so. cfg, ok := state.BalancerConfig.(pfConfig) if state.BalancerConfig != nil && !ok { return fmt.Errorf("pickfirst: received illegal BalancerConfig (type %T): %v", state.BalancerConfig, state.BalancerConfig) } - if cfg.ShuffleAddressList { - addrs = append([]resolver.Address{}, addrs...) - grpcrand.Shuffle(len(addrs), func(i, j int) { addrs[i], addrs[j] = addrs[j], addrs[i] }) - } if b.logger.V(2) { b.logger.Infof("Received new config %s, resolver state %s", pretty.ToJSON(cfg), pretty.ToJSON(state.ResolverState)) } + var addrs []resolver.Address + if endpoints := state.ResolverState.Endpoints; len(endpoints) != 0 { + // Perform the optional shuffling described in gRFC A62. The shuffling will + // change the order of endpoints but not touch the order of the addresses + // within each endpoint. - A61 + if cfg.ShuffleAddressList { + endpoints = append([]resolver.Endpoint{}, endpoints...) + internal.RandShuffle(len(endpoints), func(i, j int) { endpoints[i], endpoints[j] = endpoints[j], endpoints[i] }) + } + + // "Flatten the list by concatenating the ordered list of addresses for each + // of the endpoints, in order." - A61 + for _, endpoint := range endpoints { + // "In the flattened list, interleave addresses from the two address + // families, as per RFC-8304 section 4." - A61 + // TODO: support the above language. + addrs = append(addrs, endpoint.Addresses...) + } + } else { + // Endpoints not set, process addresses until we migrate resolver + // emissions fully to Endpoints. The top channel does wrap emitted + // addresses with endpoints, however some balancers such as weighted + // target do not forward the corresponding correct endpoints down/split + // endpoints properly. Once all balancers correctly forward endpoints + // down, can delete this else conditional. + addrs = state.ResolverState.Addresses + if cfg.ShuffleAddressList { + addrs = append([]resolver.Address{}, addrs...) + rand.Shuffle(len(addrs), func(i, j int) { addrs[i], addrs[j] = addrs[j], addrs[i] }) + } + } + if b.subConn != nil { b.cc.UpdateAddresses(b.subConn, addrs) return nil diff --git a/vendor/google.golang.org/grpc/balancer/pickfirst/pickfirstleaf/pickfirstleaf.go b/vendor/google.golang.org/grpc/balancer/pickfirst/pickfirstleaf/pickfirstleaf.go new file mode 100644 index 000000000..985b6edc7 --- /dev/null +++ b/vendor/google.golang.org/grpc/balancer/pickfirst/pickfirstleaf/pickfirstleaf.go @@ -0,0 +1,625 @@ +/* + * + * Copyright 2024 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. + * + */ + +// Package pickfirstleaf contains the pick_first load balancing policy which +// will be the universal leaf policy after dualstack changes are implemented. +// +// # Experimental +// +// Notice: This package is EXPERIMENTAL and may be changed or removed in a +// later release. +package pickfirstleaf + +import ( + "encoding/json" + "errors" + "fmt" + "sync" + + "google.golang.org/grpc/balancer" + "google.golang.org/grpc/balancer/pickfirst/internal" + "google.golang.org/grpc/connectivity" + "google.golang.org/grpc/grpclog" + "google.golang.org/grpc/internal/envconfig" + internalgrpclog "google.golang.org/grpc/internal/grpclog" + "google.golang.org/grpc/internal/pretty" + "google.golang.org/grpc/resolver" + "google.golang.org/grpc/serviceconfig" +) + +func init() { + if envconfig.NewPickFirstEnabled { + // Register as the default pick_first balancer. + Name = "pick_first" + } + balancer.Register(pickfirstBuilder{}) +} + +var ( + logger = grpclog.Component("pick-first-leaf-lb") + // Name is the name of the pick_first_leaf balancer. + // It is changed to "pick_first" in init() if this balancer is to be + // registered as the default pickfirst. + Name = "pick_first_leaf" +) + +// TODO: change to pick-first when this becomes the default pick_first policy. +const logPrefix = "[pick-first-leaf-lb %p] " + +type pickfirstBuilder struct{} + +func (pickfirstBuilder) Build(cc balancer.ClientConn, _ balancer.BuildOptions) balancer.Balancer { + b := &pickfirstBalancer{ + cc: cc, + addressList: addressList{}, + subConns: resolver.NewAddressMap(), + state: connectivity.Connecting, + mu: sync.Mutex{}, + } + b.logger = internalgrpclog.NewPrefixLogger(logger, fmt.Sprintf(logPrefix, b)) + return b +} + +func (b pickfirstBuilder) Name() string { + return Name +} + +func (pickfirstBuilder) ParseConfig(js json.RawMessage) (serviceconfig.LoadBalancingConfig, error) { + var cfg pfConfig + if err := json.Unmarshal(js, &cfg); err != nil { + return nil, fmt.Errorf("pickfirst: unable to unmarshal LB policy config: %s, error: %v", string(js), err) + } + return cfg, nil +} + +type pfConfig struct { + serviceconfig.LoadBalancingConfig `json:"-"` + + // If set to true, instructs the LB policy to shuffle the order of the list + // of endpoints received from the name resolver before attempting to + // connect to them. + ShuffleAddressList bool `json:"shuffleAddressList"` +} + +// scData keeps track of the current state of the subConn. +// It is not safe for concurrent access. +type scData struct { + // The following fields are initialized at build time and read-only after + // that. + subConn balancer.SubConn + addr resolver.Address + + state connectivity.State + lastErr error +} + +func (b *pickfirstBalancer) newSCData(addr resolver.Address) (*scData, error) { + sd := &scData{ + state: connectivity.Idle, + addr: addr, + } + sc, err := b.cc.NewSubConn([]resolver.Address{addr}, balancer.NewSubConnOptions{ + StateListener: func(state balancer.SubConnState) { + b.updateSubConnState(sd, state) + }, + }) + if err != nil { + return nil, err + } + sd.subConn = sc + return sd, nil +} + +type pickfirstBalancer struct { + // The following fields are initialized at build time and read-only after + // that and therefore do not need to be guarded by a mutex. + logger *internalgrpclog.PrefixLogger + cc balancer.ClientConn + + // The mutex is used to ensure synchronization of updates triggered + // from the idle picker and the already serialized resolver, + // SubConn state updates. + mu sync.Mutex + state connectivity.State + // scData for active subonns mapped by address. + subConns *resolver.AddressMap + addressList addressList + firstPass bool + numTF int +} + +// ResolverError is called by the ClientConn when the name resolver produces +// an error or when pickfirst determined the resolver update to be invalid. +func (b *pickfirstBalancer) ResolverError(err error) { + b.mu.Lock() + defer b.mu.Unlock() + b.resolverErrorLocked(err) +} + +func (b *pickfirstBalancer) resolverErrorLocked(err error) { + if b.logger.V(2) { + b.logger.Infof("Received error from the name resolver: %v", err) + } + + // The picker will not change since the balancer does not currently + // report an error. If the balancer hasn't received a single good resolver + // update yet, transition to TRANSIENT_FAILURE. + if b.state != connectivity.TransientFailure && b.addressList.size() > 0 { + if b.logger.V(2) { + b.logger.Infof("Ignoring resolver error because balancer is using a previous good update.") + } + return + } + + b.cc.UpdateState(balancer.State{ + ConnectivityState: connectivity.TransientFailure, + Picker: &picker{err: fmt.Errorf("name resolver error: %v", err)}, + }) +} + +func (b *pickfirstBalancer) UpdateClientConnState(state balancer.ClientConnState) error { + b.mu.Lock() + defer b.mu.Unlock() + if len(state.ResolverState.Addresses) == 0 && len(state.ResolverState.Endpoints) == 0 { + // Cleanup state pertaining to the previous resolver state. + // Treat an empty address list like an error by calling b.ResolverError. + b.state = connectivity.TransientFailure + b.closeSubConnsLocked() + b.addressList.updateAddrs(nil) + b.resolverErrorLocked(errors.New("produced zero addresses")) + return balancer.ErrBadResolverState + } + cfg, ok := state.BalancerConfig.(pfConfig) + if state.BalancerConfig != nil && !ok { + return fmt.Errorf("pickfirst: received illegal BalancerConfig (type %T): %v: %w", state.BalancerConfig, state.BalancerConfig, balancer.ErrBadResolverState) + } + + if b.logger.V(2) { + b.logger.Infof("Received new config %s, resolver state %s", pretty.ToJSON(cfg), pretty.ToJSON(state.ResolverState)) + } + + var newAddrs []resolver.Address + if endpoints := state.ResolverState.Endpoints; len(endpoints) != 0 { + // Perform the optional shuffling described in gRFC A62. The shuffling + // will change the order of endpoints but not touch the order of the + // addresses within each endpoint. - A61 + if cfg.ShuffleAddressList { + endpoints = append([]resolver.Endpoint{}, endpoints...) + internal.RandShuffle(len(endpoints), func(i, j int) { endpoints[i], endpoints[j] = endpoints[j], endpoints[i] }) + } + + // "Flatten the list by concatenating the ordered list of addresses for + // each of the endpoints, in order." - A61 + for _, endpoint := range endpoints { + // "In the flattened list, interleave addresses from the two address + // families, as per RFC-8305 section 4." - A61 + // TODO: support the above language. + newAddrs = append(newAddrs, endpoint.Addresses...) + } + } else { + // Endpoints not set, process addresses until we migrate resolver + // emissions fully to Endpoints. The top channel does wrap emitted + // addresses with endpoints, however some balancers such as weighted + // target do not forward the corresponding correct endpoints down/split + // endpoints properly. Once all balancers correctly forward endpoints + // down, can delete this else conditional. + newAddrs = state.ResolverState.Addresses + if cfg.ShuffleAddressList { + newAddrs = append([]resolver.Address{}, newAddrs...) + internal.RandShuffle(len(endpoints), func(i, j int) { endpoints[i], endpoints[j] = endpoints[j], endpoints[i] }) + } + } + + // If an address appears in multiple endpoints or in the same endpoint + // multiple times, we keep it only once. We will create only one SubConn + // for the address because an AddressMap is used to store SubConns. + // Not de-duplicating would result in attempting to connect to the same + // SubConn multiple times in the same pass. We don't want this. + newAddrs = deDupAddresses(newAddrs) + + // Since we have a new set of addresses, we are again at first pass. + b.firstPass = true + + // If the previous ready SubConn exists in new address list, + // keep this connection and don't create new SubConns. + prevAddr := b.addressList.currentAddress() + prevAddrsCount := b.addressList.size() + b.addressList.updateAddrs(newAddrs) + if b.state == connectivity.Ready && b.addressList.seekTo(prevAddr) { + return nil + } + + b.reconcileSubConnsLocked(newAddrs) + // If it's the first resolver update or the balancer was already READY + // (but the new address list does not contain the ready SubConn) or + // CONNECTING, enter CONNECTING. + // We may be in TRANSIENT_FAILURE due to a previous empty address list, + // we should still enter CONNECTING because the sticky TF behaviour + // mentioned in A62 applies only when the TRANSIENT_FAILURE is reported + // due to connectivity failures. + if b.state == connectivity.Ready || b.state == connectivity.Connecting || prevAddrsCount == 0 { + // Start connection attempt at first address. + b.state = connectivity.Connecting + b.cc.UpdateState(balancer.State{ + ConnectivityState: connectivity.Connecting, + Picker: &picker{err: balancer.ErrNoSubConnAvailable}, + }) + b.requestConnectionLocked() + } else if b.state == connectivity.TransientFailure { + // If we're in TRANSIENT_FAILURE, we stay in TRANSIENT_FAILURE until + // we're READY. See A62. + b.requestConnectionLocked() + } + return nil +} + +// UpdateSubConnState is unused as a StateListener is always registered when +// creating SubConns. +func (b *pickfirstBalancer) UpdateSubConnState(subConn balancer.SubConn, state balancer.SubConnState) { + b.logger.Errorf("UpdateSubConnState(%v, %+v) called unexpectedly", subConn, state) +} + +func (b *pickfirstBalancer) Close() { + b.mu.Lock() + defer b.mu.Unlock() + b.closeSubConnsLocked() + b.state = connectivity.Shutdown +} + +// ExitIdle moves the balancer out of idle state. It can be called concurrently +// by the idlePicker and clientConn so access to variables should be +// synchronized. +func (b *pickfirstBalancer) ExitIdle() { + b.mu.Lock() + defer b.mu.Unlock() + if b.state == connectivity.Idle && b.addressList.currentAddress() == b.addressList.first() { + b.firstPass = true + b.requestConnectionLocked() + } +} + +func (b *pickfirstBalancer) closeSubConnsLocked() { + for _, sd := range b.subConns.Values() { + sd.(*scData).subConn.Shutdown() + } + b.subConns = resolver.NewAddressMap() +} + +// deDupAddresses ensures that each address appears only once in the slice. +func deDupAddresses(addrs []resolver.Address) []resolver.Address { + seenAddrs := resolver.NewAddressMap() + retAddrs := []resolver.Address{} + + for _, addr := range addrs { + if _, ok := seenAddrs.Get(addr); ok { + continue + } + retAddrs = append(retAddrs, addr) + } + return retAddrs +} + +// reconcileSubConnsLocked updates the active subchannels based on a new address +// list from the resolver. It does this by: +// - closing subchannels: any existing subchannels associated with addresses +// that are no longer in the updated list are shut down. +// - removing subchannels: entries for these closed subchannels are removed +// from the subchannel map. +// +// This ensures that the subchannel map accurately reflects the current set of +// addresses received from the name resolver. +func (b *pickfirstBalancer) reconcileSubConnsLocked(newAddrs []resolver.Address) { + newAddrsMap := resolver.NewAddressMap() + for _, addr := range newAddrs { + newAddrsMap.Set(addr, true) + } + + for _, oldAddr := range b.subConns.Keys() { + if _, ok := newAddrsMap.Get(oldAddr); ok { + continue + } + val, _ := b.subConns.Get(oldAddr) + val.(*scData).subConn.Shutdown() + b.subConns.Delete(oldAddr) + } +} + +// shutdownRemainingLocked shuts down remaining subConns. Called when a subConn +// becomes ready, which means that all other subConn must be shutdown. +func (b *pickfirstBalancer) shutdownRemainingLocked(selected *scData) { + for _, v := range b.subConns.Values() { + sd := v.(*scData) + if sd.subConn != selected.subConn { + sd.subConn.Shutdown() + } + } + b.subConns = resolver.NewAddressMap() + b.subConns.Set(selected.addr, selected) +} + +// requestConnectionLocked starts connecting on the subchannel corresponding to +// the current address. If no subchannel exists, one is created. If the current +// subchannel is in TransientFailure, a connection to the next address is +// attempted until a subchannel is found. +func (b *pickfirstBalancer) requestConnectionLocked() { + if !b.addressList.isValid() { + return + } + var lastErr error + for valid := true; valid; valid = b.addressList.increment() { + curAddr := b.addressList.currentAddress() + sd, ok := b.subConns.Get(curAddr) + if !ok { + var err error + // We want to assign the new scData to sd from the outer scope, + // hence we can't use := below. + sd, err = b.newSCData(curAddr) + if err != nil { + // This should never happen, unless the clientConn is being shut + // down. + if b.logger.V(2) { + b.logger.Infof("Failed to create a subConn for address %v: %v", curAddr.String(), err) + } + // Do nothing, the LB policy will be closed soon. + return + } + b.subConns.Set(curAddr, sd) + } + + scd := sd.(*scData) + switch scd.state { + case connectivity.Idle: + scd.subConn.Connect() + case connectivity.TransientFailure: + // Try the next address. + lastErr = scd.lastErr + continue + case connectivity.Ready: + // Should never happen. + b.logger.Errorf("Requesting a connection even though we have a READY SubConn") + case connectivity.Shutdown: + // Should never happen. + b.logger.Errorf("SubConn with state SHUTDOWN present in SubConns map") + case connectivity.Connecting: + // Wait for the SubConn to report success or failure. + } + return + } + // All the remaining addresses in the list are in TRANSIENT_FAILURE, end the + // first pass. + b.endFirstPassLocked(lastErr) +} + +func (b *pickfirstBalancer) updateSubConnState(sd *scData, newState balancer.SubConnState) { + b.mu.Lock() + defer b.mu.Unlock() + oldState := sd.state + sd.state = newState.ConnectivityState + // Previously relevant SubConns can still callback with state updates. + // To prevent pickers from returning these obsolete SubConns, this logic + // is included to check if the current list of active SubConns includes this + // SubConn. + if activeSD, found := b.subConns.Get(sd.addr); !found || activeSD != sd { + return + } + if newState.ConnectivityState == connectivity.Shutdown { + return + } + + if newState.ConnectivityState == connectivity.Ready { + b.shutdownRemainingLocked(sd) + if !b.addressList.seekTo(sd.addr) { + // This should not fail as we should have only one SubConn after + // entering READY. The SubConn should be present in the addressList. + b.logger.Errorf("Address %q not found address list in %v", sd.addr, b.addressList.addresses) + return + } + b.state = connectivity.Ready + b.cc.UpdateState(balancer.State{ + ConnectivityState: connectivity.Ready, + Picker: &picker{result: balancer.PickResult{SubConn: sd.subConn}}, + }) + return + } + + // If the LB policy is READY, and it receives a subchannel state change, + // it means that the READY subchannel has failed. + // A SubConn can also transition from CONNECTING directly to IDLE when + // a transport is successfully created, but the connection fails + // before the SubConn can send the notification for READY. We treat + // this as a successful connection and transition to IDLE. + if (b.state == connectivity.Ready && newState.ConnectivityState != connectivity.Ready) || (oldState == connectivity.Connecting && newState.ConnectivityState == connectivity.Idle) { + // Once a transport fails, the balancer enters IDLE and starts from + // the first address when the picker is used. + b.shutdownRemainingLocked(sd) + b.state = connectivity.Idle + b.addressList.reset() + b.cc.UpdateState(balancer.State{ + ConnectivityState: connectivity.Idle, + Picker: &idlePicker{exitIdle: sync.OnceFunc(b.ExitIdle)}, + }) + return + } + + if b.firstPass { + switch newState.ConnectivityState { + case connectivity.Connecting: + // The balancer can be in either IDLE, CONNECTING or + // TRANSIENT_FAILURE. If it's in TRANSIENT_FAILURE, stay in + // TRANSIENT_FAILURE until it's READY. See A62. + // If the balancer is already in CONNECTING, no update is needed. + if b.state == connectivity.Idle { + b.state = connectivity.Connecting + b.cc.UpdateState(balancer.State{ + ConnectivityState: connectivity.Connecting, + Picker: &picker{err: balancer.ErrNoSubConnAvailable}, + }) + } + case connectivity.TransientFailure: + sd.lastErr = newState.ConnectionError + // Since we're re-using common SubConns while handling resolver + // updates, we could receive an out of turn TRANSIENT_FAILURE from + // a pass over the previous address list. We ignore such updates. + + if curAddr := b.addressList.currentAddress(); !equalAddressIgnoringBalAttributes(&curAddr, &sd.addr) { + return + } + if b.addressList.increment() { + b.requestConnectionLocked() + return + } + // End of the first pass. + b.endFirstPassLocked(newState.ConnectionError) + } + return + } + + // We have finished the first pass, keep re-connecting failing SubConns. + switch newState.ConnectivityState { + case connectivity.TransientFailure: + b.numTF = (b.numTF + 1) % b.subConns.Len() + sd.lastErr = newState.ConnectionError + if b.numTF%b.subConns.Len() == 0 { + b.cc.UpdateState(balancer.State{ + ConnectivityState: connectivity.TransientFailure, + Picker: &picker{err: newState.ConnectionError}, + }) + } + // We don't need to request re-resolution since the SubConn already + // does that before reporting TRANSIENT_FAILURE. + // TODO: #7534 - Move re-resolution requests from SubConn into + // pick_first. + case connectivity.Idle: + sd.subConn.Connect() + } +} + +func (b *pickfirstBalancer) endFirstPassLocked(lastErr error) { + b.firstPass = false + b.numTF = 0 + b.state = connectivity.TransientFailure + + b.cc.UpdateState(balancer.State{ + ConnectivityState: connectivity.TransientFailure, + Picker: &picker{err: lastErr}, + }) + // Start re-connecting all the SubConns that are already in IDLE. + for _, v := range b.subConns.Values() { + sd := v.(*scData) + if sd.state == connectivity.Idle { + sd.subConn.Connect() + } + } +} + +type picker struct { + result balancer.PickResult + err error +} + +func (p *picker) Pick(balancer.PickInfo) (balancer.PickResult, error) { + return p.result, p.err +} + +// idlePicker is used when the SubConn is IDLE and kicks the SubConn into +// CONNECTING when Pick is called. +type idlePicker struct { + exitIdle func() +} + +func (i *idlePicker) Pick(balancer.PickInfo) (balancer.PickResult, error) { + i.exitIdle() + return balancer.PickResult{}, balancer.ErrNoSubConnAvailable +} + +// addressList manages sequentially iterating over addresses present in a list +// of endpoints. It provides a 1 dimensional view of the addresses present in +// the endpoints. +// This type is not safe for concurrent access. +type addressList struct { + addresses []resolver.Address + idx int +} + +func (al *addressList) isValid() bool { + return al.idx < len(al.addresses) +} + +func (al *addressList) size() int { + return len(al.addresses) +} + +// increment moves to the next index in the address list. +// This method returns false if it went off the list, true otherwise. +func (al *addressList) increment() bool { + if !al.isValid() { + return false + } + al.idx++ + return al.idx < len(al.addresses) +} + +// currentAddress returns the current address pointed to in the addressList. +// If the list is in an invalid state, it returns an empty address instead. +func (al *addressList) currentAddress() resolver.Address { + if !al.isValid() { + return resolver.Address{} + } + return al.addresses[al.idx] +} + +// first returns the first address in the list. If the list is empty, it returns +// an empty address instead. +func (al *addressList) first() resolver.Address { + if len(al.addresses) == 0 { + return resolver.Address{} + } + return al.addresses[0] +} + +func (al *addressList) reset() { + al.idx = 0 +} + +func (al *addressList) updateAddrs(addrs []resolver.Address) { + al.addresses = addrs + al.reset() +} + +// seekTo returns false if the needle was not found and the current index was +// left unchanged. +func (al *addressList) seekTo(needle resolver.Address) bool { + for ai, addr := range al.addresses { + if !equalAddressIgnoringBalAttributes(&addr, &needle) { + continue + } + al.idx = ai + return true + } + return false +} + +// equalAddressIgnoringBalAttributes returns true is a and b are considered +// equal. This is different from the Equal method on the resolver.Address type +// which considers all fields to determine equality. Here, we only consider +// fields that are meaningful to the SubConn. +func equalAddressIgnoringBalAttributes(a, b *resolver.Address) bool { + return a.Addr == b.Addr && a.ServerName == b.ServerName && + a.Attributes.Equal(b.Attributes) && + a.Metadata == b.Metadata +} diff --git a/vendor/google.golang.org/grpc/balancer/roundrobin/roundrobin.go b/vendor/google.golang.org/grpc/balancer/roundrobin/roundrobin.go index f7031ad22..260255d31 100644 --- a/vendor/google.golang.org/grpc/balancer/roundrobin/roundrobin.go +++ b/vendor/google.golang.org/grpc/balancer/roundrobin/roundrobin.go @@ -22,12 +22,12 @@ package roundrobin import ( + "math/rand" "sync/atomic" "google.golang.org/grpc/balancer" "google.golang.org/grpc/balancer/base" "google.golang.org/grpc/grpclog" - "google.golang.org/grpc/internal/grpcrand" ) // Name is the name of round_robin balancer. @@ -60,7 +60,7 @@ func (*rrPickerBuilder) Build(info base.PickerBuildInfo) balancer.Picker { // Start at a random index, as the same RR balancer rebuilds a new // picker when SubConn states change, and we don't want to apply excess // load to the first server in the list. - next: uint32(grpcrand.Intn(len(scs))), + next: uint32(rand.Intn(len(scs))), } } diff --git a/vendor/google.golang.org/grpc/balancer_wrapper.go b/vendor/google.golang.org/grpc/balancer_wrapper.go index af39b8a4c..2a4f2878a 100644 --- a/vendor/google.golang.org/grpc/balancer_wrapper.go +++ b/vendor/google.golang.org/grpc/balancer_wrapper.go @@ -24,13 +24,18 @@ import ( "sync" "google.golang.org/grpc/balancer" + "google.golang.org/grpc/codes" "google.golang.org/grpc/connectivity" + "google.golang.org/grpc/internal" "google.golang.org/grpc/internal/balancer/gracefulswitch" "google.golang.org/grpc/internal/channelz" "google.golang.org/grpc/internal/grpcsync" "google.golang.org/grpc/resolver" + "google.golang.org/grpc/status" ) +var setConnectedAddress = internal.SetConnectedAddress.(func(*balancer.SubConnState, resolver.Address)) + // ccBalancerWrapper sits between the ClientConn and the Balancer. // // ccBalancerWrapper implements methods corresponding to the ones on the @@ -79,6 +84,7 @@ func newCCBalancerWrapper(cc *ClientConn) *ccBalancerWrapper { CustomUserAgent: cc.dopts.copts.UserAgent, ChannelzParent: cc.channelz, Target: cc.parsedTarget, + MetricsRecorder: cc.metricsRecorderList, }, serializer: grpcsync.NewCallbackSerializer(ctx), serializerCancel: cancel, @@ -92,7 +98,7 @@ func newCCBalancerWrapper(cc *ClientConn) *ccBalancerWrapper { // it is safe to call into the balancer here. func (ccb *ccBalancerWrapper) updateClientConnState(ccs *balancer.ClientConnState) error { errCh := make(chan error) - ok := ccb.serializer.Schedule(func(ctx context.Context) { + uccs := func(ctx context.Context) { defer close(errCh) if ctx.Err() != nil || ccb.balancer == nil { return @@ -107,17 +113,23 @@ func (ccb *ccBalancerWrapper) updateClientConnState(ccs *balancer.ClientConnStat logger.Infof("error from balancer.UpdateClientConnState: %v", err) } errCh <- err - }) - if !ok { - return nil } + onFailure := func() { close(errCh) } + + // UpdateClientConnState can race with Close, and when the latter wins, the + // serializer is closed, and the attempt to schedule the callback will fail. + // It is acceptable to ignore this failure. But since we want to handle the + // state update in a blocking fashion (when we successfully schedule the + // callback), we have to use the ScheduleOr method and not the MaybeSchedule + // method on the serializer. + ccb.serializer.ScheduleOr(uccs, onFailure) return <-errCh } // resolverError is invoked by grpc to push a resolver error to the underlying // balancer. The call to the balancer is executed from the serializer. func (ccb *ccBalancerWrapper) resolverError(err error) { - ccb.serializer.Schedule(func(ctx context.Context) { + ccb.serializer.TrySchedule(func(ctx context.Context) { if ctx.Err() != nil || ccb.balancer == nil { return } @@ -133,7 +145,7 @@ func (ccb *ccBalancerWrapper) close() { ccb.closed = true ccb.mu.Unlock() channelz.Info(logger, ccb.cc.channelz, "ccBalancerWrapper: closing") - ccb.serializer.Schedule(func(context.Context) { + ccb.serializer.TrySchedule(func(context.Context) { if ccb.balancer == nil { return } @@ -145,7 +157,7 @@ func (ccb *ccBalancerWrapper) close() { // exitIdle invokes the balancer's exitIdle method in the serializer. func (ccb *ccBalancerWrapper) exitIdle() { - ccb.serializer.Schedule(func(ctx context.Context) { + ccb.serializer.TrySchedule(func(ctx context.Context) { if ctx.Err() != nil || ccb.balancer == nil { return } @@ -182,7 +194,7 @@ func (ccb *ccBalancerWrapper) NewSubConn(addrs []resolver.Address, opts balancer return acbw, nil } -func (ccb *ccBalancerWrapper) RemoveSubConn(sc balancer.SubConn) { +func (ccb *ccBalancerWrapper) RemoveSubConn(balancer.SubConn) { // The graceful switch balancer will never call this. logger.Errorf("ccb RemoveSubConn(%v) called unexpectedly, sc") } @@ -198,6 +210,10 @@ func (ccb *ccBalancerWrapper) UpdateAddresses(sc balancer.SubConn, addrs []resol func (ccb *ccBalancerWrapper) UpdateState(s balancer.State) { ccb.cc.mu.Lock() defer ccb.cc.mu.Unlock() + if ccb.cc.conns == nil { + // The CC has been closed; ignore this update. + return + } ccb.mu.Lock() if ccb.closed { @@ -242,21 +258,28 @@ type acBalancerWrapper struct { ccb *ccBalancerWrapper // read-only stateListener func(balancer.SubConnState) - mu sync.Mutex - producers map[balancer.ProducerBuilder]*refCountedProducer + producersMu sync.Mutex + producers map[balancer.ProducerBuilder]*refCountedProducer } // updateState is invoked by grpc to push a subConn state update to the // underlying balancer. -func (acbw *acBalancerWrapper) updateState(s connectivity.State, err error) { - acbw.ccb.serializer.Schedule(func(ctx context.Context) { +func (acbw *acBalancerWrapper) updateState(s connectivity.State, curAddr resolver.Address, err error) { + acbw.ccb.serializer.TrySchedule(func(ctx context.Context) { if ctx.Err() != nil || acbw.ccb.balancer == nil { return } + // Invalidate all producers on any state change. + acbw.closeProducers() + // Even though it is optional for balancers, gracefulswitch ensures // opts.StateListener is set, so this cannot ever be nil. // TODO: delete this comment when UpdateSubConnState is removed. - acbw.stateListener(balancer.SubConnState{ConnectivityState: s, ConnectionError: err}) + scs := balancer.SubConnState{ConnectivityState: s, ConnectionError: err} + if s == connectivity.Ready { + setConnectedAddress(&scs, curAddr) + } + acbw.stateListener(scs) }) } @@ -273,6 +296,7 @@ func (acbw *acBalancerWrapper) Connect() { } func (acbw *acBalancerWrapper) Shutdown() { + acbw.closeProducers() acbw.ccb.cc.removeAddrConn(acbw.ac, errConnDrain) } @@ -280,9 +304,10 @@ func (acbw *acBalancerWrapper) Shutdown() { // ready, blocks until it is or ctx expires. Returns an error when the context // expires or the addrConn is shut down. func (acbw *acBalancerWrapper) NewStream(ctx context.Context, desc *StreamDesc, method string, opts ...CallOption) (ClientStream, error) { - transport, err := acbw.ac.getTransport(ctx) - if err != nil { - return nil, err + transport := acbw.ac.getReadyTransport() + if transport == nil { + return nil, status.Errorf(codes.Unavailable, "SubConn state is not Ready") + } return newNonRetryClientStream(ctx, desc, method, transport, acbw.ac, opts...) } @@ -307,15 +332,15 @@ type refCountedProducer struct { } func (acbw *acBalancerWrapper) GetOrBuildProducer(pb balancer.ProducerBuilder) (balancer.Producer, func()) { - acbw.mu.Lock() - defer acbw.mu.Unlock() + acbw.producersMu.Lock() + defer acbw.producersMu.Unlock() // Look up existing producer from this builder. pData := acbw.producers[pb] if pData == nil { // Not found; create a new one and add it to the producers map. - p, close := pb.Build(acbw) - pData = &refCountedProducer{producer: p, close: close} + p, closeFn := pb.Build(acbw) + pData = &refCountedProducer{producer: p, close: closeFn} acbw.producers[pb] = pData } // Account for this new reference. @@ -325,13 +350,26 @@ func (acbw *acBalancerWrapper) GetOrBuildProducer(pb balancer.ProducerBuilder) ( // and delete the refCountedProducer from the map if the total reference // count goes to zero. unref := func() { - acbw.mu.Lock() + acbw.producersMu.Lock() + // If closeProducers has already closed this producer instance, refs is + // set to 0, so the check after decrementing will never pass, and the + // producer will not be double-closed. pData.refs-- if pData.refs == 0 { defer pData.close() // Run outside the acbw mutex delete(acbw.producers, pb) } - acbw.mu.Unlock() + acbw.producersMu.Unlock() } return pData.producer, grpcsync.OnceFunc(unref) } + +func (acbw *acBalancerWrapper) closeProducers() { + acbw.producersMu.Lock() + defer acbw.producersMu.Unlock() + for pb, pData := range acbw.producers { + pData.refs = 0 + pData.close() + delete(acbw.producers, pb) + } +} diff --git a/vendor/google.golang.org/grpc/binarylog/grpc_binarylog_v1/binarylog.pb.go b/vendor/google.golang.org/grpc/binarylog/grpc_binarylog_v1/binarylog.pb.go index 856c75dd4..55bffaa77 100644 --- a/vendor/google.golang.org/grpc/binarylog/grpc_binarylog_v1/binarylog.pb.go +++ b/vendor/google.golang.org/grpc/binarylog/grpc_binarylog_v1/binarylog.pb.go @@ -18,8 +18,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.32.0 -// protoc v4.25.2 +// protoc-gen-go v1.34.2 +// protoc v5.27.1 // source: grpc/binlog/v1/binarylog.proto package grpc_binarylog_v1 @@ -1015,7 +1015,7 @@ func file_grpc_binlog_v1_binarylog_proto_rawDescGZIP() []byte { var file_grpc_binlog_v1_binarylog_proto_enumTypes = make([]protoimpl.EnumInfo, 3) var file_grpc_binlog_v1_binarylog_proto_msgTypes = make([]protoimpl.MessageInfo, 8) -var file_grpc_binlog_v1_binarylog_proto_goTypes = []interface{}{ +var file_grpc_binlog_v1_binarylog_proto_goTypes = []any{ (GrpcLogEntry_EventType)(0), // 0: grpc.binarylog.v1.GrpcLogEntry.EventType (GrpcLogEntry_Logger)(0), // 1: grpc.binarylog.v1.GrpcLogEntry.Logger (Address_Type)(0), // 2: grpc.binarylog.v1.Address.Type @@ -1058,7 +1058,7 @@ func file_grpc_binlog_v1_binarylog_proto_init() { return } if !protoimpl.UnsafeEnabled { - file_grpc_binlog_v1_binarylog_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + file_grpc_binlog_v1_binarylog_proto_msgTypes[0].Exporter = func(v any, i int) any { switch v := v.(*GrpcLogEntry); i { case 0: return &v.state @@ -1070,7 +1070,7 @@ func file_grpc_binlog_v1_binarylog_proto_init() { return nil } } - file_grpc_binlog_v1_binarylog_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + file_grpc_binlog_v1_binarylog_proto_msgTypes[1].Exporter = func(v any, i int) any { switch v := v.(*ClientHeader); i { case 0: return &v.state @@ -1082,7 +1082,7 @@ func file_grpc_binlog_v1_binarylog_proto_init() { return nil } } - file_grpc_binlog_v1_binarylog_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + file_grpc_binlog_v1_binarylog_proto_msgTypes[2].Exporter = func(v any, i int) any { switch v := v.(*ServerHeader); i { case 0: return &v.state @@ -1094,7 +1094,7 @@ func file_grpc_binlog_v1_binarylog_proto_init() { return nil } } - file_grpc_binlog_v1_binarylog_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + file_grpc_binlog_v1_binarylog_proto_msgTypes[3].Exporter = func(v any, i int) any { switch v := v.(*Trailer); i { case 0: return &v.state @@ -1106,7 +1106,7 @@ func file_grpc_binlog_v1_binarylog_proto_init() { return nil } } - file_grpc_binlog_v1_binarylog_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + file_grpc_binlog_v1_binarylog_proto_msgTypes[4].Exporter = func(v any, i int) any { switch v := v.(*Message); i { case 0: return &v.state @@ -1118,7 +1118,7 @@ func file_grpc_binlog_v1_binarylog_proto_init() { return nil } } - file_grpc_binlog_v1_binarylog_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + file_grpc_binlog_v1_binarylog_proto_msgTypes[5].Exporter = func(v any, i int) any { switch v := v.(*Metadata); i { case 0: return &v.state @@ -1130,7 +1130,7 @@ func file_grpc_binlog_v1_binarylog_proto_init() { return nil } } - file_grpc_binlog_v1_binarylog_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + file_grpc_binlog_v1_binarylog_proto_msgTypes[6].Exporter = func(v any, i int) any { switch v := v.(*MetadataEntry); i { case 0: return &v.state @@ -1142,7 +1142,7 @@ func file_grpc_binlog_v1_binarylog_proto_init() { return nil } } - file_grpc_binlog_v1_binarylog_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + file_grpc_binlog_v1_binarylog_proto_msgTypes[7].Exporter = func(v any, i int) any { switch v := v.(*Address); i { case 0: return &v.state @@ -1155,7 +1155,7 @@ func file_grpc_binlog_v1_binarylog_proto_init() { } } } - file_grpc_binlog_v1_binarylog_proto_msgTypes[0].OneofWrappers = []interface{}{ + file_grpc_binlog_v1_binarylog_proto_msgTypes[0].OneofWrappers = []any{ (*GrpcLogEntry_ClientHeader)(nil), (*GrpcLogEntry_ServerHeader)(nil), (*GrpcLogEntry_Message)(nil), diff --git a/vendor/google.golang.org/grpc/clientconn.go b/vendor/google.golang.org/grpc/clientconn.go index c7f260711..19763f8ed 100644 --- a/vendor/google.golang.org/grpc/clientconn.go +++ b/vendor/google.golang.org/grpc/clientconn.go @@ -24,6 +24,7 @@ import ( "fmt" "math" "net/url" + "slices" "strings" "sync" "sync/atomic" @@ -31,14 +32,15 @@ import ( "google.golang.org/grpc/balancer" "google.golang.org/grpc/balancer/base" + "google.golang.org/grpc/balancer/pickfirst" "google.golang.org/grpc/codes" "google.golang.org/grpc/connectivity" "google.golang.org/grpc/internal" "google.golang.org/grpc/internal/channelz" "google.golang.org/grpc/internal/grpcsync" "google.golang.org/grpc/internal/idle" - "google.golang.org/grpc/internal/pretty" iresolver "google.golang.org/grpc/internal/resolver" + "google.golang.org/grpc/internal/stats" "google.golang.org/grpc/internal/transport" "google.golang.org/grpc/keepalive" "google.golang.org/grpc/resolver" @@ -73,6 +75,8 @@ var ( // invalidDefaultServiceConfigErrPrefix is used to prefix the json parsing error for the default // service config. invalidDefaultServiceConfigErrPrefix = "grpc: the provided default service config is invalid" + // PickFirstBalancerName is the name of the pick_first balancer. + PickFirstBalancerName = pickfirst.Name ) // The following errors are returned from Dial and DialContext @@ -121,8 +125,9 @@ func (dcs *defaultConfigSelector) SelectConfig(rpcInfo iresolver.RPCInfo) (*ires // https://github.com/grpc/grpc/blob/master/doc/naming.md. e.g. to use dns // resolver, a "dns:///" prefix should be applied to the target. // -// The DialOptions returned by WithBlock, WithTimeout, and -// WithReturnConnectionError are ignored by this function. +// The DialOptions returned by WithBlock, WithTimeout, +// WithReturnConnectionError, and FailOnNonTempDialError are ignored by this +// function. func NewClient(target string, opts ...DialOption) (conn *ClientConn, err error) { cc := &ClientConn{ target: target, @@ -152,6 +157,16 @@ func NewClient(target string, opts ...DialOption) (conn *ClientConn, err error) for _, opt := range opts { opt.apply(&cc.dopts) } + + // Determine the resolver to use. + if err := cc.initParsedTargetAndResolverBuilder(); err != nil { + return nil, err + } + + for _, opt := range globalPerTargetDialOptions { + opt.DialOptionForTarget(cc.parsedTarget.URL).apply(&cc.dopts) + } + chainUnaryClientInterceptors(cc) chainStreamClientInterceptors(cc) @@ -160,7 +175,7 @@ func NewClient(target string, opts ...DialOption) (conn *ClientConn, err error) } if cc.dopts.defaultServiceConfigRawJSON != nil { - scpr := parseServiceConfig(*cc.dopts.defaultServiceConfigRawJSON) + scpr := parseServiceConfig(*cc.dopts.defaultServiceConfigRawJSON, cc.dopts.maxCallAttempts) if scpr.Err != nil { return nil, fmt.Errorf("%s: %v", invalidDefaultServiceConfigErrPrefix, scpr.Err) } @@ -168,34 +183,30 @@ func NewClient(target string, opts ...DialOption) (conn *ClientConn, err error) } cc.mkp = cc.dopts.copts.KeepaliveParams - // Register ClientConn with channelz. - cc.channelzRegistration(target) - - // TODO: Ideally it should be impossible to error from this function after - // channelz registration. This will require removing some channelz logs - // from the following functions that can error. Errors can be returned to - // the user, and successful logs can be emitted here, after the checks have - // passed and channelz is subsequently registered. - - // Determine the resolver to use. - if err := cc.parseTargetAndFindResolver(); err != nil { - channelz.RemoveEntry(cc.channelz.ID) - return nil, err - } - if err = cc.determineAuthority(); err != nil { - channelz.RemoveEntry(cc.channelz.ID) + if err = cc.initAuthority(); err != nil { return nil, err } + // Register ClientConn with channelz. Note that this is only done after + // channel creation cannot fail. + cc.channelzRegistration(target) + channelz.Infof(logger, cc.channelz, "parsed dial target is: %#v", cc.parsedTarget) + channelz.Infof(logger, cc.channelz, "Channel authority set to %q", cc.authority) + cc.csMgr = newConnectivityStateManager(cc.ctx, cc.channelz) cc.pickerWrapper = newPickerWrapper(cc.dopts.copts.StatsHandlers) + cc.metricsRecorderList = stats.NewMetricsRecorderList(cc.dopts.copts.StatsHandlers) + cc.initIdleStateLocked() // Safe to call without the lock, since nothing else has a reference to cc. cc.idlenessMgr = idle.NewManager((*idler)(cc), cc.dopts.idleTimeout) + return cc, nil } // Dial calls DialContext(context.Background(), target, opts...). +// +// Deprecated: use NewClient instead. Will be supported throughout 1.x. func Dial(target string, opts ...DialOption) (*ClientConn, error) { return DialContext(context.Background(), target, opts...) } @@ -209,6 +220,8 @@ func Dial(target string, opts ...DialOption) (*ClientConn, error) { // "passthrough" for backward compatibility. This distinction should not matter // to most users, but could matter to legacy users that specify a custom dialer // and expect it to receive the target string directly. +// +// Deprecated: use NewClient instead. Will be supported throughout 1.x. func DialContext(ctx context.Context, target string, opts ...DialOption) (conn *ClientConn, err error) { // At the end of this method, we kick the channel out of idle, rather than // waiting for the first rpc. @@ -582,13 +595,14 @@ type ClientConn struct { cancel context.CancelFunc // Cancelled on close. // The following are initialized at dial time, and are read-only after that. - target string // User's dial target. - parsedTarget resolver.Target // See parseTargetAndFindResolver(). - authority string // See determineAuthority(). - dopts dialOptions // Default and user specified dial options. - channelz *channelz.Channel // Channelz object. - resolverBuilder resolver.Builder // See parseTargetAndFindResolver(). - idlenessMgr *idle.Manager + target string // User's dial target. + parsedTarget resolver.Target // See initParsedTargetAndResolverBuilder(). + authority string // See initAuthority(). + dopts dialOptions // Default and user specified dial options. + channelz *channelz.Channel // Channelz object. + resolverBuilder resolver.Builder // See initParsedTargetAndResolverBuilder(). + idlenessMgr *idle.Manager + metricsRecorderList *stats.MetricsRecorderList // The following provide their own synchronization, and therefore don't // require cc.mu to be held to access them. @@ -618,11 +632,6 @@ type ClientConn struct { // WaitForStateChange waits until the connectivity.State of ClientConn changes from sourceState or // ctx expires. A true value is returned in former case and false in latter. -// -// # Experimental -// -// Notice: This API is EXPERIMENTAL and may be changed or removed in a -// later release. func (cc *ClientConn) WaitForStateChange(ctx context.Context, sourceState connectivity.State) bool { ch := cc.csMgr.getNotifyChan() if cc.csMgr.getState() != sourceState { @@ -637,11 +646,6 @@ func (cc *ClientConn) WaitForStateChange(ctx context.Context, sourceState connec } // GetState returns the connectivity.State of ClientConn. -// -// # Experimental -// -// Notice: This API is EXPERIMENTAL and may be changed or removed in a later -// release. func (cc *ClientConn) GetState() connectivity.State { return cc.csMgr.getState() } @@ -688,8 +692,7 @@ func (cc *ClientConn) waitForResolvedAddrs(ctx context.Context) error { var emptyServiceConfig *ServiceConfig func init() { - balancer.Register(pickfirstBuilder{}) - cfg := parseServiceConfig("{}") + cfg := parseServiceConfig("{}", defaultMaxCallAttempts) if cfg.Err != nil { panic(fmt.Sprintf("impossible error parsing empty service config: %v", cfg.Err)) } @@ -805,17 +808,11 @@ func (cc *ClientConn) applyFailingLBLocked(sc *serviceconfig.ParseResult) { cc.csMgr.updateState(connectivity.TransientFailure) } -// Makes a copy of the input addresses slice and clears out the balancer -// attributes field. Addresses are passed during subconn creation and address -// update operations. In both cases, we will clear the balancer attributes by -// calling this function, and therefore we will be able to use the Equal method -// provided by the resolver.Address type for comparison. -func copyAddressesWithoutBalancerAttributes(in []resolver.Address) []resolver.Address { +// Makes a copy of the input addresses slice. Addresses are passed during +// subconn creation and address update operations. +func copyAddresses(in []resolver.Address) []resolver.Address { out := make([]resolver.Address, len(in)) - for i := range in { - out[i] = in[i] - out[i].BalancerAttributes = nil - } + copy(out, in) return out } @@ -830,14 +827,16 @@ func (cc *ClientConn) newAddrConnLocked(addrs []resolver.Address, opts balancer. ac := &addrConn{ state: connectivity.Idle, cc: cc, - addrs: copyAddressesWithoutBalancerAttributes(addrs), + addrs: copyAddresses(addrs), scopts: opts, dopts: cc.dopts, channelz: channelz.RegisterSubChannel(cc.channelz, ""), resetBackoff: make(chan struct{}), - stateChan: make(chan struct{}), } ac.ctx, ac.cancel = context.WithCancel(cc.ctx) + // Start with our address set to the first address; this may be updated if + // we connect to different addresses. + ac.channelz.ChannelMetrics.Target.Store(&addrs[0].Addr) channelz.AddTraceEvent(logger, ac.channelz, 0, &channelz.TraceEvent{ Desc: "Subchannel created", @@ -908,32 +907,37 @@ func (ac *addrConn) connect() error { ac.mu.Unlock() return nil } - ac.mu.Unlock() - ac.resetTransport() + ac.resetTransportAndUnlock() return nil } -func equalAddresses(a, b []resolver.Address) bool { - if len(a) != len(b) { - return false - } - for i, v := range a { - if !v.Equal(b[i]) { - return false - } - } - return true +// equalAddressIgnoringBalAttributes returns true is a and b are considered equal. +// This is different from the Equal method on the resolver.Address type which +// considers all fields to determine equality. Here, we only consider fields +// that are meaningful to the subConn. +func equalAddressIgnoringBalAttributes(a, b *resolver.Address) bool { + return a.Addr == b.Addr && a.ServerName == b.ServerName && + a.Attributes.Equal(b.Attributes) && + a.Metadata == b.Metadata +} + +func equalAddressesIgnoringBalAttributes(a, b []resolver.Address) bool { + return slices.EqualFunc(a, b, func(a, b resolver.Address) bool { return equalAddressIgnoringBalAttributes(&a, &b) }) } // updateAddrs updates ac.addrs with the new addresses list and handles active // connections or connection attempts. func (ac *addrConn) updateAddrs(addrs []resolver.Address) { - ac.mu.Lock() - channelz.Infof(logger, ac.channelz, "addrConn: updateAddrs curAddr: %v, addrs: %v", pretty.ToJSON(ac.curAddr), pretty.ToJSON(addrs)) + addrs = copyAddresses(addrs) + limit := len(addrs) + if limit > 5 { + limit = 5 + } + channelz.Infof(logger, ac.channelz, "addrConn: updateAddrs addrs (%d of %d): %v", limit, len(addrs), addrs[:limit]) - addrs = copyAddressesWithoutBalancerAttributes(addrs) - if equalAddresses(ac.addrs, addrs) { + ac.mu.Lock() + if equalAddressesIgnoringBalAttributes(ac.addrs, addrs) { ac.mu.Unlock() return } @@ -952,7 +956,7 @@ func (ac *addrConn) updateAddrs(addrs []resolver.Address) { // Try to find the connected address. for _, a := range addrs { a.ServerName = ac.cc.getServerName(a) - if a.Equal(ac.curAddr) { + if equalAddressIgnoringBalAttributes(&a, &ac.curAddr) { // We are connected to a valid address, so do nothing but // update the addresses. ac.mu.Unlock() @@ -978,11 +982,9 @@ func (ac *addrConn) updateAddrs(addrs []resolver.Address) { ac.updateConnectivityState(connectivity.Idle, nil) } - ac.mu.Unlock() - // Since we were connecting/connected, we should start a new connection // attempt. - go ac.resetTransport() + go ac.resetTransportAndUnlock() } // getServerName determines the serverName to be used in the connection @@ -1138,10 +1140,15 @@ func (cc *ClientConn) Close() error { <-cc.resolverWrapper.serializer.Done() <-cc.balancerWrapper.serializer.Done() - + var wg sync.WaitGroup for ac := range conns { - ac.tearDown(ErrClientConnClosing) + wg.Add(1) + go func(ac *addrConn) { + defer wg.Done() + ac.tearDown(ErrClientConnClosing) + }(ac) } + wg.Wait() cc.addTraceEvent("deleted") // TraceEvent needs to be called before RemoveEntry, as TraceEvent may add // trace reference to the entity being deleted, and thus prevent it from being @@ -1167,13 +1174,16 @@ type addrConn struct { // is received, transport is closed, ac has been torn down). transport transport.ClientTransport // The current transport. + // This mutex is used on the RPC path, so its usage should be minimized as + // much as possible. + // TODO: Find a lock-free way to retrieve the transport and state from the + // addrConn. mu sync.Mutex curAddr resolver.Address // The current address. addrs []resolver.Address // All addresses that the resolver resolved to. // Use updateConnectivityState for updating addrConn's connectivity state. - state connectivity.State - stateChan chan struct{} // closed and recreated on every state change. + state connectivity.State backoffIdx int // Needs to be stateful for resetConnectBackoff. resetBackoff chan struct{} @@ -1186,9 +1196,6 @@ func (ac *addrConn) updateConnectivityState(s connectivity.State, lastErr error) if ac.state == s { return } - // When changing states, reset the state change channel. - close(ac.stateChan) - ac.stateChan = make(chan struct{}) ac.state = s ac.channelz.ChannelMetrics.State.Store(&s) if lastErr == nil { @@ -1196,7 +1203,7 @@ func (ac *addrConn) updateConnectivityState(s connectivity.State, lastErr error) } else { channelz.Infof(logger, ac.channelz, "Subchannel Connectivity change to %v, last error: %s", s, lastErr) } - ac.acbw.updateState(s, lastErr) + ac.acbw.updateState(s, ac.curAddr, lastErr) } // adjustParams updates parameters used to create transports upon @@ -1213,8 +1220,10 @@ func (ac *addrConn) adjustParams(r transport.GoAwayReason) { } } -func (ac *addrConn) resetTransport() { - ac.mu.Lock() +// resetTransportAndUnlock unconditionally connects the addrConn. +// +// ac.mu must be held by the caller, and this function will guarantee it is released. +func (ac *addrConn) resetTransportAndUnlock() { acCtx := ac.ctx if acCtx.Err() != nil { ac.mu.Unlock() @@ -1245,6 +1254,8 @@ func (ac *addrConn) resetTransport() { ac.mu.Unlock() if err := ac.tryAllAddrs(acCtx, addrs, connectDeadline); err != nil { + // TODO: #7534 - Move re-resolution requests into the pick_first LB policy + // to ensure one resolution request per pass instead of per subconn failure. ac.cc.resolveNow(resolver.ResolveNowOptions{}) ac.mu.Lock() if acCtx.Err() != nil { @@ -1286,12 +1297,13 @@ func (ac *addrConn) resetTransport() { ac.mu.Unlock() } -// tryAllAddrs tries to creates a connection to the addresses, and stop when at +// tryAllAddrs tries to create a connection to the addresses, and stop when at // the first successful one. It returns an error if no address was successfully // connected, or updates ac appropriately with the new transport. func (ac *addrConn) tryAllAddrs(ctx context.Context, addrs []resolver.Address, connectDeadline time.Time) error { var firstConnErr error for _, addr := range addrs { + ac.channelz.ChannelMetrics.Target.Store(&addr.Addr) if ctx.Err() != nil { return errConnClosing } @@ -1497,29 +1509,6 @@ func (ac *addrConn) getReadyTransport() transport.ClientTransport { return nil } -// getTransport waits until the addrconn is ready and returns the transport. -// If the context expires first, returns an appropriate status. If the -// addrConn is stopped first, returns an Unavailable status error. -func (ac *addrConn) getTransport(ctx context.Context) (transport.ClientTransport, error) { - for ctx.Err() == nil { - ac.mu.Lock() - t, state, sc := ac.transport, ac.state, ac.stateChan - ac.mu.Unlock() - if state == connectivity.Ready { - return t, nil - } - if state == connectivity.Shutdown { - return nil, status.Errorf(codes.Unavailable, "SubConn shutting down") - } - - select { - case <-ctx.Done(): - case <-sc: - } - } - return nil, status.FromContextError(ctx.Err()).Err() -} - // tearDown starts to tear down the addrConn. // // Note that tearDown doesn't remove ac from ac.cc.conns, so the addrConn struct @@ -1566,7 +1555,7 @@ func (ac *addrConn) tearDown(err error) { } else { // Hard close the transport when the channel is entering idle or is // being shutdown. In the case where the channel is being shutdown, - // closing of transports is also taken care of by cancelation of cc.ctx. + // closing of transports is also taken care of by cancellation of cc.ctx. // But in the case where the channel is entering idle, we need to // explicitly close the transports here. Instead of distinguishing // between these two cases, it is simpler to close the transport @@ -1657,22 +1646,19 @@ func (cc *ClientConn) connectionError() error { return cc.lastConnectionError } -// parseTargetAndFindResolver parses the user's dial target and stores the -// parsed target in `cc.parsedTarget`. +// initParsedTargetAndResolverBuilder parses the user's dial target and stores +// the parsed target in `cc.parsedTarget`. // // The resolver to use is determined based on the scheme in the parsed target // and the same is stored in `cc.resolverBuilder`. // // Doesn't grab cc.mu as this method is expected to be called only at Dial time. -func (cc *ClientConn) parseTargetAndFindResolver() error { - channelz.Infof(logger, cc.channelz, "original dial target is: %q", cc.target) +func (cc *ClientConn) initParsedTargetAndResolverBuilder() error { + logger.Infof("original dial target is: %q", cc.target) var rb resolver.Builder parsedTarget, err := parseTarget(cc.target) - if err != nil { - channelz.Infof(logger, cc.channelz, "dial target %q parse failed: %v", cc.target, err) - } else { - channelz.Infof(logger, cc.channelz, "parsed dial target is: %#v", parsedTarget) + if err == nil { rb = cc.getResolver(parsedTarget.URL.Scheme) if rb != nil { cc.parsedTarget = parsedTarget @@ -1691,15 +1677,12 @@ func (cc *ClientConn) parseTargetAndFindResolver() error { defScheme = resolver.GetDefaultScheme() } - channelz.Infof(logger, cc.channelz, "fallback to scheme %q", defScheme) canonicalTarget := defScheme + ":///" + cc.target parsedTarget, err = parseTarget(canonicalTarget) if err != nil { - channelz.Infof(logger, cc.channelz, "dial target %q parse failed: %v", canonicalTarget, err) return err } - channelz.Infof(logger, cc.channelz, "parsed dial target is: %+v", parsedTarget) rb = cc.getResolver(parsedTarget.URL.Scheme) if rb == nil { return fmt.Errorf("could not get resolver for default scheme: %q", parsedTarget.URL.Scheme) @@ -1739,7 +1722,7 @@ func encodeAuthority(authority string) string { return false case '!', '$', '&', '\'', '(', ')', '*', '+', ',', ';', '=': // Subdelim characters return false - case ':', '[', ']', '@': // Authority related delimeters + case ':', '[', ']', '@': // Authority related delimiters return false } // Everything else must be escaped. @@ -1789,7 +1772,7 @@ func encodeAuthority(authority string) string { // credentials do not match the authority configured through the dial option. // // Doesn't grab cc.mu as this method is expected to be called only at Dial time. -func (cc *ClientConn) determineAuthority() error { +func (cc *ClientConn) initAuthority() error { dopts := cc.dopts // Historically, we had two options for users to specify the serverName or // authority for a channel. One was through the transport credentials @@ -1822,6 +1805,5 @@ func (cc *ClientConn) determineAuthority() error { } else { cc.authority = encodeAuthority(endpoint) } - channelz.Infof(logger, cc.channelz, "Channel authority set to %q", cc.authority) return nil } diff --git a/vendor/google.golang.org/grpc/codec.go b/vendor/google.golang.org/grpc/codec.go index 411e3dfd4..e840858b7 100644 --- a/vendor/google.golang.org/grpc/codec.go +++ b/vendor/google.golang.org/grpc/codec.go @@ -21,18 +21,73 @@ package grpc import ( "google.golang.org/grpc/encoding" _ "google.golang.org/grpc/encoding/proto" // to register the Codec for "proto" + "google.golang.org/grpc/mem" ) -// baseCodec contains the functionality of both Codec and encoding.Codec, but -// omits the name/string, which vary between the two and are not needed for -// anything besides the registry in the encoding package. +// baseCodec captures the new encoding.CodecV2 interface without the Name +// function, allowing it to be implemented by older Codec and encoding.Codec +// implementations. The omitted Name function is only needed for the register in +// the encoding package and is not part of the core functionality. type baseCodec interface { - Marshal(v any) ([]byte, error) - Unmarshal(data []byte, v any) error + Marshal(v any) (mem.BufferSlice, error) + Unmarshal(data mem.BufferSlice, v any) error +} + +// getCodec returns an encoding.CodecV2 for the codec of the given name (if +// registered). Initially checks the V2 registry with encoding.GetCodecV2 and +// returns the V2 codec if it is registered. Otherwise, it checks the V1 registry +// with encoding.GetCodec and if it is registered wraps it with newCodecV1Bridge +// to turn it into an encoding.CodecV2. Returns nil otherwise. +func getCodec(name string) encoding.CodecV2 { + if codecV1 := encoding.GetCodec(name); codecV1 != nil { + return newCodecV1Bridge(codecV1) + } + + return encoding.GetCodecV2(name) +} + +func newCodecV0Bridge(c Codec) baseCodec { + return codecV0Bridge{codec: c} +} + +func newCodecV1Bridge(c encoding.Codec) encoding.CodecV2 { + return codecV1Bridge{ + codecV0Bridge: codecV0Bridge{codec: c}, + name: c.Name(), + } +} + +var _ baseCodec = codecV0Bridge{} + +type codecV0Bridge struct { + codec interface { + Marshal(v any) ([]byte, error) + Unmarshal(data []byte, v any) error + } +} + +func (c codecV0Bridge) Marshal(v any) (mem.BufferSlice, error) { + data, err := c.codec.Marshal(v) + if err != nil { + return nil, err + } + return mem.BufferSlice{mem.NewBuffer(&data, nil)}, nil +} + +func (c codecV0Bridge) Unmarshal(data mem.BufferSlice, v any) (err error) { + return c.codec.Unmarshal(data.Materialize(), v) } -var _ baseCodec = Codec(nil) -var _ baseCodec = encoding.Codec(nil) +var _ encoding.CodecV2 = codecV1Bridge{} + +type codecV1Bridge struct { + codecV0Bridge + name string +} + +func (c codecV1Bridge) Name() string { + return c.name +} // Codec defines the interface gRPC uses to encode and decode messages. // Note that implementations of this interface must be thread safe; diff --git a/vendor/google.golang.org/grpc/codegen.sh b/vendor/google.golang.org/grpc/codegen.sh deleted file mode 100644 index 4cdc6ba7c..000000000 --- a/vendor/google.golang.org/grpc/codegen.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env bash - -# This script serves as an example to demonstrate how to generate the gRPC-Go -# interface and the related messages from .proto file. -# -# It assumes the installation of i) Google proto buffer compiler at -# https://github.com/google/protobuf (after v2.6.1) and ii) the Go codegen -# plugin at https://github.com/golang/protobuf (after 2015-02-20). If you have -# not, please install them first. -# -# We recommend running this script at $GOPATH/src. -# -# If this is not what you need, feel free to make your own scripts. Again, this -# script is for demonstration purpose. -# -proto=$1 -protoc --go_out=plugins=grpc:. $proto diff --git a/vendor/google.golang.org/grpc/codes/codes.go b/vendor/google.golang.org/grpc/codes/codes.go index 08476ad1f..0b42c302b 100644 --- a/vendor/google.golang.org/grpc/codes/codes.go +++ b/vendor/google.golang.org/grpc/codes/codes.go @@ -235,7 +235,7 @@ func (c *Code) UnmarshalJSON(b []byte) error { if ci, err := strconv.ParseUint(string(b), 10, 32); err == nil { if ci >= _maxCode { - return fmt.Errorf("invalid code: %q", ci) + return fmt.Errorf("invalid code: %d", ci) } *c = Code(ci) diff --git a/vendor/google.golang.org/grpc/credentials/credentials.go b/vendor/google.golang.org/grpc/credentials/credentials.go index f6b55c68b..665e790bb 100644 --- a/vendor/google.golang.org/grpc/credentials/credentials.go +++ b/vendor/google.golang.org/grpc/credentials/credentials.go @@ -30,7 +30,7 @@ import ( "google.golang.org/grpc/attributes" icredentials "google.golang.org/grpc/internal/credentials" - "google.golang.org/protobuf/protoadapt" + "google.golang.org/protobuf/proto" ) // PerRPCCredentials defines the common interface for the credentials which need to @@ -237,7 +237,7 @@ func ClientHandshakeInfoFromContext(ctx context.Context) ClientHandshakeInfo { } // CheckSecurityLevel checks if a connection's security level is greater than or equal to the specified one. -// It returns success if 1) the condition is satisified or 2) AuthInfo struct does not implement GetCommonAuthInfo() method +// It returns success if 1) the condition is satisfied or 2) AuthInfo struct does not implement GetCommonAuthInfo() method // or 3) CommonAuthInfo.SecurityLevel has an invalid zero value. For 2) and 3), it is for the purpose of backward-compatibility. // // This API is experimental. @@ -287,5 +287,5 @@ type ChannelzSecurityValue interface { type OtherChannelzSecurityValue struct { ChannelzSecurityValue Name string - Value protoadapt.MessageV1 + Value proto.Message } diff --git a/vendor/google.golang.org/grpc/credentials/insecure/insecure.go b/vendor/google.golang.org/grpc/credentials/insecure/insecure.go index 82bee1443..4c805c644 100644 --- a/vendor/google.golang.org/grpc/credentials/insecure/insecure.go +++ b/vendor/google.golang.org/grpc/credentials/insecure/insecure.go @@ -40,7 +40,7 @@ func NewCredentials() credentials.TransportCredentials { // NoSecurity. type insecureTC struct{} -func (insecureTC) ClientHandshake(ctx context.Context, _ string, conn net.Conn) (net.Conn, credentials.AuthInfo, error) { +func (insecureTC) ClientHandshake(_ context.Context, _ string, conn net.Conn) (net.Conn, credentials.AuthInfo, error) { return conn, info{credentials.CommonAuthInfo{SecurityLevel: credentials.NoSecurity}}, nil } diff --git a/vendor/google.golang.org/grpc/credentials/tls.go b/vendor/google.golang.org/grpc/credentials/tls.go index 5dafd34ed..e163a473d 100644 --- a/vendor/google.golang.org/grpc/credentials/tls.go +++ b/vendor/google.golang.org/grpc/credentials/tls.go @@ -27,9 +27,13 @@ import ( "net/url" "os" + "google.golang.org/grpc/grpclog" credinternal "google.golang.org/grpc/internal/credentials" + "google.golang.org/grpc/internal/envconfig" ) +var logger = grpclog.Component("credentials") + // TLSInfo contains the auth information for a TLS authenticated connection. // It implements the AuthInfo interface. type TLSInfo struct { @@ -112,6 +116,22 @@ func (c *tlsCreds) ClientHandshake(ctx context.Context, authority string, rawCon conn.Close() return nil, nil, ctx.Err() } + + // The negotiated protocol can be either of the following: + // 1. h2: When the server supports ALPN. Only HTTP/2 can be negotiated since + // it is the only protocol advertised by the client during the handshake. + // The tls library ensures that the server chooses a protocol advertised + // by the client. + // 2. "" (empty string): If the server doesn't support ALPN. ALPN is a requirement + // for using HTTP/2 over TLS. We can terminate the connection immediately. + np := conn.ConnectionState().NegotiatedProtocol + if np == "" { + if envconfig.EnforceALPNEnabled { + conn.Close() + return nil, nil, fmt.Errorf("credentials: cannot check peer: missing selected ALPN property") + } + logger.Warningf("Allowing TLS connection to server %q with ALPN disabled. TLS connections to servers with ALPN disabled will be disallowed in future grpc-go releases", cfg.ServerName) + } tlsInfo := TLSInfo{ State: conn.ConnectionState(), CommonAuthInfo: CommonAuthInfo{ @@ -131,8 +151,20 @@ func (c *tlsCreds) ServerHandshake(rawConn net.Conn) (net.Conn, AuthInfo, error) conn.Close() return nil, nil, err } + cs := conn.ConnectionState() + // The negotiated application protocol can be empty only if the client doesn't + // support ALPN. In such cases, we can close the connection since ALPN is required + // for using HTTP/2 over TLS. + if cs.NegotiatedProtocol == "" { + if envconfig.EnforceALPNEnabled { + conn.Close() + return nil, nil, fmt.Errorf("credentials: cannot check peer: missing selected ALPN property") + } else if logger.V(2) { + logger.Info("Allowing TLS connection from client with ALPN disabled. TLS connections with ALPN disabled will be disallowed in future grpc-go releases") + } + } tlsInfo := TLSInfo{ - State: conn.ConnectionState(), + State: cs, CommonAuthInfo: CommonAuthInfo{ SecurityLevel: PrivacyAndIntegrity, }, @@ -168,25 +200,40 @@ var tls12ForbiddenCipherSuites = map[uint16]struct{}{ // NewTLS uses c to construct a TransportCredentials based on TLS. func NewTLS(c *tls.Config) TransportCredentials { - tc := &tlsCreds{credinternal.CloneTLSConfig(c)} - tc.config.NextProtos = credinternal.AppendH2ToNextProtos(tc.config.NextProtos) + config := applyDefaults(c) + if config.GetConfigForClient != nil { + oldFn := config.GetConfigForClient + config.GetConfigForClient = func(hello *tls.ClientHelloInfo) (*tls.Config, error) { + cfgForClient, err := oldFn(hello) + if err != nil || cfgForClient == nil { + return cfgForClient, err + } + return applyDefaults(cfgForClient), nil + } + } + return &tlsCreds{config: config} +} + +func applyDefaults(c *tls.Config) *tls.Config { + config := credinternal.CloneTLSConfig(c) + config.NextProtos = credinternal.AppendH2ToNextProtos(config.NextProtos) // If the user did not configure a MinVersion and did not configure a // MaxVersion < 1.2, use MinVersion=1.2, which is required by // https://datatracker.ietf.org/doc/html/rfc7540#section-9.2 - if tc.config.MinVersion == 0 && (tc.config.MaxVersion == 0 || tc.config.MaxVersion >= tls.VersionTLS12) { - tc.config.MinVersion = tls.VersionTLS12 + if config.MinVersion == 0 && (config.MaxVersion == 0 || config.MaxVersion >= tls.VersionTLS12) { + config.MinVersion = tls.VersionTLS12 } // If the user did not configure CipherSuites, use all "secure" cipher // suites reported by the TLS package, but remove some explicitly forbidden // by https://datatracker.ietf.org/doc/html/rfc7540#appendix-A - if tc.config.CipherSuites == nil { + if config.CipherSuites == nil { for _, cs := range tls.CipherSuites() { if _, ok := tls12ForbiddenCipherSuites[cs.ID]; !ok { - tc.config.CipherSuites = append(tc.config.CipherSuites, cs.ID) + config.CipherSuites = append(config.CipherSuites, cs.ID) } } } - return tc + return config } // NewClientTLSFromCert constructs TLS credentials from the provided root diff --git a/vendor/google.golang.org/grpc/dialoptions.go b/vendor/google.golang.org/grpc/dialoptions.go index 402493224..518692c3a 100644 --- a/vendor/google.golang.org/grpc/dialoptions.go +++ b/vendor/google.golang.org/grpc/dialoptions.go @@ -21,6 +21,7 @@ package grpc import ( "context" "net" + "net/url" "time" "google.golang.org/grpc/backoff" @@ -32,10 +33,16 @@ import ( "google.golang.org/grpc/internal/binarylog" "google.golang.org/grpc/internal/transport" "google.golang.org/grpc/keepalive" + "google.golang.org/grpc/mem" "google.golang.org/grpc/resolver" "google.golang.org/grpc/stats" ) +const ( + // https://github.com/grpc/proposal/blob/master/A6-client-retries.md#limits-on-retries-and-hedges + defaultMaxCallAttempts = 5 +) + func init() { internal.AddGlobalDialOptions = func(opt ...DialOption) { globalDialOptions = append(globalDialOptions, opt...) @@ -43,10 +50,18 @@ func init() { internal.ClearGlobalDialOptions = func() { globalDialOptions = nil } + internal.AddGlobalPerTargetDialOptions = func(opt any) { + if ptdo, ok := opt.(perTargetDialOption); ok { + globalPerTargetDialOptions = append(globalPerTargetDialOptions, ptdo) + } + } + internal.ClearGlobalPerTargetDialOptions = func() { + globalPerTargetDialOptions = nil + } internal.WithBinaryLogger = withBinaryLogger internal.JoinDialOptions = newJoinDialOption internal.DisableGlobalDialOptions = newDisableGlobalDialOptions - internal.WithRecvBufferPool = withRecvBufferPool + internal.WithBufferPool = withBufferPool } // dialOptions configure a Dial call. dialOptions are set by the DialOption @@ -78,8 +93,8 @@ type dialOptions struct { defaultServiceConfigRawJSON *string resolvers []resolver.Builder idleTimeout time.Duration - recvBufferPool SharedBufferPool defaultScheme string + maxCallAttempts int } // DialOption configures how we set up the connection. @@ -89,6 +104,19 @@ type DialOption interface { var globalDialOptions []DialOption +// perTargetDialOption takes a parsed target and returns a dial option to apply. +// +// This gets called after NewClient() parses the target, and allows per target +// configuration set through a returned DialOption. The DialOption will not take +// effect if specifies a resolver builder, as that Dial Option is factored in +// while parsing target. +type perTargetDialOption interface { + // DialOption returns a Dial Option to apply. + DialOptionForTarget(parsedTarget url.URL) DialOption +} + +var globalPerTargetDialOptions []perTargetDialOption + // EmptyDialOption does not alter the dial configuration. It can be embedded in // another structure to build custom dial options. // @@ -300,6 +328,9 @@ func withBackoff(bs internalbackoff.Strategy) DialOption { // // Use of this feature is not recommended. For more information, please see: // https://github.com/grpc/grpc-go/blob/master/Documentation/anti-patterns.md +// +// Deprecated: this DialOption is not supported by NewClient. +// Will be supported throughout 1.x. func WithBlock() DialOption { return newFuncDialOption(func(o *dialOptions) { o.block = true @@ -314,10 +345,8 @@ func WithBlock() DialOption { // Use of this feature is not recommended. For more information, please see: // https://github.com/grpc/grpc-go/blob/master/Documentation/anti-patterns.md // -// # Experimental -// -// Notice: This API is EXPERIMENTAL and may be changed or removed in a -// later release. +// Deprecated: this DialOption is not supported by NewClient. +// Will be supported throughout 1.x. func WithReturnConnectionError() DialOption { return newFuncDialOption(func(o *dialOptions) { o.block = true @@ -387,8 +416,8 @@ func WithCredentialsBundle(b credentials.Bundle) DialOption { // WithTimeout returns a DialOption that configures a timeout for dialing a // ClientConn initially. This is valid if and only if WithBlock() is present. // -// Deprecated: use DialContext instead of Dial and context.WithTimeout -// instead. Will be supported throughout 1.x. +// Deprecated: this DialOption is not supported by NewClient. +// Will be supported throughout 1.x. func WithTimeout(d time.Duration) DialOption { return newFuncDialOption(func(o *dialOptions) { o.timeout = d @@ -407,7 +436,7 @@ func WithTimeout(d time.Duration) DialOption { // option to true from the Control field. For a concrete example of how to do // this, see internal.NetDialerWithTCPKeepalive(). // -// For more information, please see [issue 23459] in the Go github repo. +// For more information, please see [issue 23459] in the Go GitHub repo. // // [issue 23459]: https://github.com/golang/go/issues/23459 func WithContextDialer(f func(context.Context, string) (net.Conn, error)) DialOption { @@ -470,9 +499,8 @@ func withBinaryLogger(bl binarylog.Logger) DialOption { // Use of this feature is not recommended. For more information, please see: // https://github.com/grpc/grpc-go/blob/master/Documentation/anti-patterns.md // -// # Experimental -// -// Notice: This API is EXPERIMENTAL and may be changed or removed in a +// Deprecated: this DialOption is not supported by NewClient. +// This API may be changed or removed in a // later release. func FailOnNonTempDialError(f bool) DialOption { return newFuncDialOption(func(o *dialOptions) { @@ -490,6 +518,8 @@ func WithUserAgent(s string) DialOption { // WithKeepaliveParams returns a DialOption that specifies keepalive parameters // for the client transport. +// +// Keepalive is disabled by default. func WithKeepaliveParams(kp keepalive.ClientParameters) DialOption { if kp.Time < internal.KeepaliveMinPingTime { logger.Warningf("Adjusting keepalive ping interval to minimum period of %v", internal.KeepaliveMinPingTime) @@ -601,12 +631,22 @@ func WithDisableRetry() DialOption { }) } +// MaxHeaderListSizeDialOption is a DialOption that specifies the maximum +// (uncompressed) size of header list that the client is prepared to accept. +type MaxHeaderListSizeDialOption struct { + MaxHeaderListSize uint32 +} + +func (o MaxHeaderListSizeDialOption) apply(do *dialOptions) { + do.copts.MaxHeaderListSize = &o.MaxHeaderListSize +} + // WithMaxHeaderListSize returns a DialOption that specifies the maximum // (uncompressed) size of header list that the client is prepared to accept. func WithMaxHeaderListSize(s uint32) DialOption { - return newFuncDialOption(func(o *dialOptions) { - o.copts.MaxHeaderListSize = &s - }) + return MaxHeaderListSizeDialOption{ + MaxHeaderListSize: s, + } } // WithDisableHealthCheck disables the LB channel health checking for all @@ -639,16 +679,17 @@ func defaultDialOptions() dialOptions { WriteBufferSize: defaultWriteBufSize, UseProxy: true, UserAgent: grpcUA, + BufferPool: mem.DefaultBufferPool(), }, bs: internalbackoff.DefaultExponential, healthCheckFunc: internal.HealthCheckFunc, idleTimeout: 30 * time.Minute, - recvBufferPool: nopBufferPool{}, defaultScheme: "dns", + maxCallAttempts: defaultMaxCallAttempts, } } -// withGetMinConnectDeadline specifies the function that clientconn uses to +// withMinConnectDeadline specifies the function that clientconn uses to // get minConnectDeadline. This can be used to make connection attempts happen // faster/slower. // @@ -702,25 +743,25 @@ func WithIdleTimeout(d time.Duration) DialOption { }) } -// WithRecvBufferPool returns a DialOption that configures the ClientConn -// to use the provided shared buffer pool for parsing incoming messages. Depending -// on the application's workload, this could result in reduced memory allocation. -// -// If you are unsure about how to implement a memory pool but want to utilize one, -// begin with grpc.NewSharedBufferPool. -// -// Note: The shared buffer pool feature will not be active if any of the following -// options are used: WithStatsHandler, EnableTracing, or binary logging. In such -// cases, the shared buffer pool will be ignored. +// WithMaxCallAttempts returns a DialOption that configures the maximum number +// of attempts per call (including retries and hedging) using the channel. +// Service owners may specify a higher value for these parameters, but higher +// values will be treated as equal to the maximum value by the client +// implementation. This mitigates security concerns related to the service +// config being transferred to the client via DNS. // -// Deprecated: use experimental.WithRecvBufferPool instead. Will be deleted in -// v1.60.0 or later. -func WithRecvBufferPool(bufferPool SharedBufferPool) DialOption { - return withRecvBufferPool(bufferPool) +// A value of 5 will be used if this dial option is not set or n < 2. +func WithMaxCallAttempts(n int) DialOption { + return newFuncDialOption(func(o *dialOptions) { + if n < 2 { + n = defaultMaxCallAttempts + } + o.maxCallAttempts = n + }) } -func withRecvBufferPool(bufferPool SharedBufferPool) DialOption { +func withBufferPool(bufferPool mem.BufferPool) DialOption { return newFuncDialOption(func(o *dialOptions) { - o.recvBufferPool = bufferPool + o.copts.BufferPool = bufferPool }) } diff --git a/vendor/google.golang.org/grpc/doc.go b/vendor/google.golang.org/grpc/doc.go index 0022859ad..e7b532b6f 100644 --- a/vendor/google.golang.org/grpc/doc.go +++ b/vendor/google.golang.org/grpc/doc.go @@ -16,7 +16,7 @@ * */ -//go:generate ./regenerate.sh +//go:generate ./scripts/regenerate.sh /* Package grpc implements an RPC system called gRPC. diff --git a/vendor/google.golang.org/grpc/encoding/encoding.go b/vendor/google.golang.org/grpc/encoding/encoding.go index 5ebf88d71..11d0ae142 100644 --- a/vendor/google.golang.org/grpc/encoding/encoding.go +++ b/vendor/google.golang.org/grpc/encoding/encoding.go @@ -94,7 +94,7 @@ type Codec interface { Name() string } -var registeredCodecs = make(map[string]Codec) +var registeredCodecs = make(map[string]any) // RegisterCodec registers the provided Codec for use with all gRPC clients and // servers. @@ -126,5 +126,6 @@ func RegisterCodec(codec Codec) { // // The content-subtype is expected to be lowercase. func GetCodec(contentSubtype string) Codec { - return registeredCodecs[contentSubtype] + c, _ := registeredCodecs[contentSubtype].(Codec) + return c } diff --git a/vendor/google.golang.org/grpc/encoding/encoding_v2.go b/vendor/google.golang.org/grpc/encoding/encoding_v2.go new file mode 100644 index 000000000..074c5e234 --- /dev/null +++ b/vendor/google.golang.org/grpc/encoding/encoding_v2.go @@ -0,0 +1,81 @@ +/* + * + * Copyright 2024 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. + * + */ + +package encoding + +import ( + "strings" + + "google.golang.org/grpc/mem" +) + +// CodecV2 defines the interface gRPC uses to encode and decode messages. Note +// that implementations of this interface must be thread safe; a CodecV2's +// methods can be called from concurrent goroutines. +type CodecV2 interface { + // Marshal returns the wire format of v. The buffers in the returned + // [mem.BufferSlice] must have at least one reference each, which will be freed + // by gRPC when they are no longer needed. + Marshal(v any) (out mem.BufferSlice, err error) + // Unmarshal parses the wire format into v. Note that data will be freed as soon + // as this function returns. If the codec wishes to guarantee access to the data + // after this function, it must take its own reference that it frees when it is + // no longer needed. + Unmarshal(data mem.BufferSlice, v any) error + // Name returns the name of the Codec implementation. The returned string + // will be used as part of content type in transmission. The result must be + // static; the result cannot change between calls. + Name() string +} + +// RegisterCodecV2 registers the provided CodecV2 for use with all gRPC clients and +// servers. +// +// The CodecV2 will be stored and looked up by result of its Name() method, which +// should match the content-subtype of the encoding handled by the CodecV2. This +// is case-insensitive, and is stored and looked up as lowercase. If the +// result of calling Name() is an empty string, RegisterCodecV2 will panic. See +// Content-Type on +// https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md#requests for +// more details. +// +// If both a Codec and CodecV2 are registered with the same name, the CodecV2 +// will be used. +// +// NOTE: this function must only be called during initialization time (i.e. in +// an init() function), and is not thread-safe. If multiple Codecs are +// registered with the same name, the one registered last will take effect. +func RegisterCodecV2(codec CodecV2) { + if codec == nil { + panic("cannot register a nil CodecV2") + } + if codec.Name() == "" { + panic("cannot register CodecV2 with empty string result for Name()") + } + contentSubtype := strings.ToLower(codec.Name()) + registeredCodecs[contentSubtype] = codec +} + +// GetCodecV2 gets a registered CodecV2 by content-subtype, or nil if no CodecV2 is +// registered for the content-subtype. +// +// The content-subtype is expected to be lowercase. +func GetCodecV2(contentSubtype string) CodecV2 { + c, _ := registeredCodecs[contentSubtype].(CodecV2) + return c +} diff --git a/vendor/google.golang.org/grpc/encoding/proto/proto.go b/vendor/google.golang.org/grpc/encoding/proto/proto.go index 66d5cdf03..ceec319dd 100644 --- a/vendor/google.golang.org/grpc/encoding/proto/proto.go +++ b/vendor/google.golang.org/grpc/encoding/proto/proto.go @@ -1,6 +1,6 @@ /* * - * Copyright 2018 gRPC authors. + * Copyright 2024 gRPC authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,6 +24,7 @@ import ( "fmt" "google.golang.org/grpc/encoding" + "google.golang.org/grpc/mem" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/protoadapt" ) @@ -32,28 +33,51 @@ import ( const Name = "proto" func init() { - encoding.RegisterCodec(codec{}) + encoding.RegisterCodecV2(&codecV2{}) } -// codec is a Codec implementation with protobuf. It is the default codec for gRPC. -type codec struct{} +// codec is a CodecV2 implementation with protobuf. It is the default codec for +// gRPC. +type codecV2 struct{} -func (codec) Marshal(v any) ([]byte, error) { +func (c *codecV2) Marshal(v any) (data mem.BufferSlice, err error) { vv := messageV2Of(v) if vv == nil { - return nil, fmt.Errorf("failed to marshal, message is %T, want proto.Message", v) + return nil, fmt.Errorf("proto: failed to marshal, message is %T, want proto.Message", v) } - return proto.Marshal(vv) + size := proto.Size(vv) + if mem.IsBelowBufferPoolingThreshold(size) { + buf, err := proto.Marshal(vv) + if err != nil { + return nil, err + } + data = append(data, mem.SliceBuffer(buf)) + } else { + pool := mem.DefaultBufferPool() + buf := pool.Get(size) + if _, err := (proto.MarshalOptions{}).MarshalAppend((*buf)[:0], vv); err != nil { + pool.Put(buf) + return nil, err + } + data = append(data, mem.NewBuffer(buf, pool)) + } + + return data, nil } -func (codec) Unmarshal(data []byte, v any) error { +func (c *codecV2) Unmarshal(data mem.BufferSlice, v any) (err error) { vv := messageV2Of(v) if vv == nil { return fmt.Errorf("failed to unmarshal, message is %T, want proto.Message", v) } - return proto.Unmarshal(data, vv) + buf := data.MaterializeToBuffer(mem.DefaultBufferPool()) + defer buf.Free() + // TODO: Upgrade proto.Unmarshal to support mem.BufferSlice. Right now, it's not + // really possible without a major overhaul of the proto package, but the + // vtprotobuf library may be able to support this. + return proto.Unmarshal(buf.ReadOnlyData(), vv) } func messageV2Of(v any) proto.Message { @@ -67,6 +91,6 @@ func messageV2Of(v any) proto.Message { return nil } -func (codec) Name() string { +func (c *codecV2) Name() string { return Name } diff --git a/vendor/google.golang.org/grpc/experimental/stats/metricregistry.go b/vendor/google.golang.org/grpc/experimental/stats/metricregistry.go new file mode 100644 index 000000000..1d827dd5d --- /dev/null +++ b/vendor/google.golang.org/grpc/experimental/stats/metricregistry.go @@ -0,0 +1,269 @@ +/* + * + * Copyright 2024 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. + * + */ + +package stats + +import ( + "maps" + + "google.golang.org/grpc/grpclog" + "google.golang.org/grpc/internal" +) + +func init() { + internal.SnapshotMetricRegistryForTesting = snapshotMetricsRegistryForTesting +} + +var logger = grpclog.Component("metrics-registry") + +// DefaultMetrics are the default metrics registered through global metrics +// registry. This is written to at initialization time only, and is read only +// after initialization. +var DefaultMetrics = NewMetrics() + +// MetricDescriptor is the data for a registered metric. +type MetricDescriptor struct { + // The name of this metric. This name must be unique across the whole binary + // (including any per call metrics). See + // https://github.com/grpc/proposal/blob/master/A79-non-per-call-metrics-architecture.md#metric-instrument-naming-conventions + // for metric naming conventions. + Name Metric + // The description of this metric. + Description string + // The unit (e.g. entries, seconds) of this metric. + Unit string + // The required label keys for this metric. These are intended to + // metrics emitted from a stats handler. + Labels []string + // The optional label keys for this metric. These are intended to attached + // to metrics emitted from a stats handler if configured. + OptionalLabels []string + // Whether this metric is on by default. + Default bool + // The type of metric. This is set by the metric registry, and not intended + // to be set by a component registering a metric. + Type MetricType + // Bounds are the bounds of this metric. This only applies to histogram + // metrics. If unset or set with length 0, stats handlers will fall back to + // default bounds. + Bounds []float64 +} + +// MetricType is the type of metric. +type MetricType int + +// Type of metric supported by this instrument registry. +const ( + MetricTypeIntCount MetricType = iota + MetricTypeFloatCount + MetricTypeIntHisto + MetricTypeFloatHisto + MetricTypeIntGauge +) + +// Int64CountHandle is a typed handle for a int count metric. This handle +// is passed at the recording point in order to know which metric to record +// on. +type Int64CountHandle MetricDescriptor + +// Descriptor returns the int64 count handle typecast to a pointer to a +// MetricDescriptor. +func (h *Int64CountHandle) Descriptor() *MetricDescriptor { + return (*MetricDescriptor)(h) +} + +// Record records the int64 count value on the metrics recorder provided. +func (h *Int64CountHandle) Record(recorder MetricsRecorder, incr int64, labels ...string) { + recorder.RecordInt64Count(h, incr, labels...) +} + +// Float64CountHandle is a typed handle for a float count metric. This handle is +// passed at the recording point in order to know which metric to record on. +type Float64CountHandle MetricDescriptor + +// Descriptor returns the float64 count handle typecast to a pointer to a +// MetricDescriptor. +func (h *Float64CountHandle) Descriptor() *MetricDescriptor { + return (*MetricDescriptor)(h) +} + +// Record records the float64 count value on the metrics recorder provided. +func (h *Float64CountHandle) Record(recorder MetricsRecorder, incr float64, labels ...string) { + recorder.RecordFloat64Count(h, incr, labels...) +} + +// Int64HistoHandle is a typed handle for an int histogram metric. This handle +// is passed at the recording point in order to know which metric to record on. +type Int64HistoHandle MetricDescriptor + +// Descriptor returns the int64 histo handle typecast to a pointer to a +// MetricDescriptor. +func (h *Int64HistoHandle) Descriptor() *MetricDescriptor { + return (*MetricDescriptor)(h) +} + +// Record records the int64 histo value on the metrics recorder provided. +func (h *Int64HistoHandle) Record(recorder MetricsRecorder, incr int64, labels ...string) { + recorder.RecordInt64Histo(h, incr, labels...) +} + +// Float64HistoHandle is a typed handle for a float histogram metric. This +// handle is passed at the recording point in order to know which metric to +// record on. +type Float64HistoHandle MetricDescriptor + +// Descriptor returns the float64 histo handle typecast to a pointer to a +// MetricDescriptor. +func (h *Float64HistoHandle) Descriptor() *MetricDescriptor { + return (*MetricDescriptor)(h) +} + +// Record records the float64 histo value on the metrics recorder provided. +func (h *Float64HistoHandle) Record(recorder MetricsRecorder, incr float64, labels ...string) { + recorder.RecordFloat64Histo(h, incr, labels...) +} + +// Int64GaugeHandle is a typed handle for an int gauge metric. This handle is +// passed at the recording point in order to know which metric to record on. +type Int64GaugeHandle MetricDescriptor + +// Descriptor returns the int64 gauge handle typecast to a pointer to a +// MetricDescriptor. +func (h *Int64GaugeHandle) Descriptor() *MetricDescriptor { + return (*MetricDescriptor)(h) +} + +// Record records the int64 histo value on the metrics recorder provided. +func (h *Int64GaugeHandle) Record(recorder MetricsRecorder, incr int64, labels ...string) { + recorder.RecordInt64Gauge(h, incr, labels...) +} + +// registeredMetrics are the registered metric descriptor names. +var registeredMetrics = make(map[Metric]bool) + +// metricsRegistry contains all of the registered metrics. +// +// This is written to only at init time, and read only after that. +var metricsRegistry = make(map[Metric]*MetricDescriptor) + +// DescriptorForMetric returns the MetricDescriptor from the global registry. +// +// Returns nil if MetricDescriptor not present. +func DescriptorForMetric(metric Metric) *MetricDescriptor { + return metricsRegistry[metric] +} + +func registerMetric(name Metric, def bool) { + if registeredMetrics[name] { + logger.Fatalf("metric %v already registered", name) + } + registeredMetrics[name] = true + if def { + DefaultMetrics = DefaultMetrics.Add(name) + } +} + +// RegisterInt64Count registers the metric description onto the global registry. +// It returns a typed handle to use to recording data. +// +// NOTE: this function must only be called during initialization time (i.e. in +// an init() function), and is not thread-safe. If multiple metrics are +// registered with the same name, this function will panic. +func RegisterInt64Count(descriptor MetricDescriptor) *Int64CountHandle { + registerMetric(descriptor.Name, descriptor.Default) + descriptor.Type = MetricTypeIntCount + descPtr := &descriptor + metricsRegistry[descriptor.Name] = descPtr + return (*Int64CountHandle)(descPtr) +} + +// RegisterFloat64Count registers the metric description onto the global +// registry. It returns a typed handle to use to recording data. +// +// NOTE: this function must only be called during initialization time (i.e. in +// an init() function), and is not thread-safe. If multiple metrics are +// registered with the same name, this function will panic. +func RegisterFloat64Count(descriptor MetricDescriptor) *Float64CountHandle { + registerMetric(descriptor.Name, descriptor.Default) + descriptor.Type = MetricTypeFloatCount + descPtr := &descriptor + metricsRegistry[descriptor.Name] = descPtr + return (*Float64CountHandle)(descPtr) +} + +// RegisterInt64Histo registers the metric description onto the global registry. +// It returns a typed handle to use to recording data. +// +// NOTE: this function must only be called during initialization time (i.e. in +// an init() function), and is not thread-safe. If multiple metrics are +// registered with the same name, this function will panic. +func RegisterInt64Histo(descriptor MetricDescriptor) *Int64HistoHandle { + registerMetric(descriptor.Name, descriptor.Default) + descriptor.Type = MetricTypeIntHisto + descPtr := &descriptor + metricsRegistry[descriptor.Name] = descPtr + return (*Int64HistoHandle)(descPtr) +} + +// RegisterFloat64Histo registers the metric description onto the global +// registry. It returns a typed handle to use to recording data. +// +// NOTE: this function must only be called during initialization time (i.e. in +// an init() function), and is not thread-safe. If multiple metrics are +// registered with the same name, this function will panic. +func RegisterFloat64Histo(descriptor MetricDescriptor) *Float64HistoHandle { + registerMetric(descriptor.Name, descriptor.Default) + descriptor.Type = MetricTypeFloatHisto + descPtr := &descriptor + metricsRegistry[descriptor.Name] = descPtr + return (*Float64HistoHandle)(descPtr) +} + +// RegisterInt64Gauge registers the metric description onto the global registry. +// It returns a typed handle to use to recording data. +// +// NOTE: this function must only be called during initialization time (i.e. in +// an init() function), and is not thread-safe. If multiple metrics are +// registered with the same name, this function will panic. +func RegisterInt64Gauge(descriptor MetricDescriptor) *Int64GaugeHandle { + registerMetric(descriptor.Name, descriptor.Default) + descriptor.Type = MetricTypeIntGauge + descPtr := &descriptor + metricsRegistry[descriptor.Name] = descPtr + return (*Int64GaugeHandle)(descPtr) +} + +// snapshotMetricsRegistryForTesting snapshots the global data of the metrics +// registry. Returns a cleanup function that sets the metrics registry to its +// original state. +func snapshotMetricsRegistryForTesting() func() { + oldDefaultMetrics := DefaultMetrics + oldRegisteredMetrics := registeredMetrics + oldMetricsRegistry := metricsRegistry + + registeredMetrics = make(map[Metric]bool) + metricsRegistry = make(map[Metric]*MetricDescriptor) + maps.Copy(registeredMetrics, registeredMetrics) + maps.Copy(metricsRegistry, metricsRegistry) + + return func() { + DefaultMetrics = oldDefaultMetrics + registeredMetrics = oldRegisteredMetrics + metricsRegistry = oldMetricsRegistry + } +} diff --git a/vendor/google.golang.org/grpc/experimental/stats/metrics.go b/vendor/google.golang.org/grpc/experimental/stats/metrics.go new file mode 100644 index 000000000..3221f7a63 --- /dev/null +++ b/vendor/google.golang.org/grpc/experimental/stats/metrics.go @@ -0,0 +1,114 @@ +/* + * + * Copyright 2024 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. + * + */ + +// Package stats contains experimental metrics/stats API's. +package stats + +import "maps" + +// MetricsRecorder records on metrics derived from metric registry. +type MetricsRecorder interface { + // RecordInt64Count records the measurement alongside labels on the int + // count associated with the provided handle. + RecordInt64Count(handle *Int64CountHandle, incr int64, labels ...string) + // RecordFloat64Count records the measurement alongside labels on the float + // count associated with the provided handle. + RecordFloat64Count(handle *Float64CountHandle, incr float64, labels ...string) + // RecordInt64Histo records the measurement alongside labels on the int + // histo associated with the provided handle. + RecordInt64Histo(handle *Int64HistoHandle, incr int64, labels ...string) + // RecordFloat64Histo records the measurement alongside labels on the float + // histo associated with the provided handle. + RecordFloat64Histo(handle *Float64HistoHandle, incr float64, labels ...string) + // RecordInt64Gauge records the measurement alongside labels on the int + // gauge associated with the provided handle. + RecordInt64Gauge(handle *Int64GaugeHandle, incr int64, labels ...string) +} + +// Metric is an identifier for a metric. +type Metric string + +// Metrics is a set of metrics to record. Once created, Metrics is immutable, +// however Add and Remove can make copies with specific metrics added or +// removed, respectively. +// +// Do not construct directly; use NewMetrics instead. +type Metrics struct { + // metrics are the set of metrics to initialize. + metrics map[Metric]bool +} + +// NewMetrics returns a Metrics containing Metrics. +func NewMetrics(metrics ...Metric) *Metrics { + newMetrics := make(map[Metric]bool) + for _, metric := range metrics { + newMetrics[metric] = true + } + return &Metrics{ + metrics: newMetrics, + } +} + +// Metrics returns the metrics set. The returned map is read-only and must not +// be modified. +func (m *Metrics) Metrics() map[Metric]bool { + return m.metrics +} + +// Add adds the metrics to the metrics set and returns a new copy with the +// additional metrics. +func (m *Metrics) Add(metrics ...Metric) *Metrics { + newMetrics := make(map[Metric]bool) + for metric := range m.metrics { + newMetrics[metric] = true + } + + for _, metric := range metrics { + newMetrics[metric] = true + } + return &Metrics{ + metrics: newMetrics, + } +} + +// Join joins the metrics passed in with the metrics set, and returns a new copy +// with the merged metrics. +func (m *Metrics) Join(metrics *Metrics) *Metrics { + newMetrics := make(map[Metric]bool) + maps.Copy(newMetrics, m.metrics) + maps.Copy(newMetrics, metrics.metrics) + return &Metrics{ + metrics: newMetrics, + } +} + +// Remove removes the metrics from the metrics set and returns a new copy with +// the metrics removed. +func (m *Metrics) Remove(metrics ...Metric) *Metrics { + newMetrics := make(map[Metric]bool) + for metric := range m.metrics { + newMetrics[metric] = true + } + + for _, metric := range metrics { + delete(newMetrics, metric) + } + return &Metrics{ + metrics: newMetrics, + } +} diff --git a/vendor/google.golang.org/grpc/grpclog/component.go b/vendor/google.golang.org/grpc/grpclog/component.go index ac73c9ced..f1ae080dc 100644 --- a/vendor/google.golang.org/grpc/grpclog/component.go +++ b/vendor/google.golang.org/grpc/grpclog/component.go @@ -20,8 +20,6 @@ package grpclog import ( "fmt" - - "google.golang.org/grpc/internal/grpclog" ) // componentData records the settings for a component. @@ -33,22 +31,22 @@ var cache = map[string]*componentData{} func (c *componentData) InfoDepth(depth int, args ...any) { args = append([]any{"[" + string(c.name) + "]"}, args...) - grpclog.InfoDepth(depth+1, args...) + InfoDepth(depth+1, args...) } func (c *componentData) WarningDepth(depth int, args ...any) { args = append([]any{"[" + string(c.name) + "]"}, args...) - grpclog.WarningDepth(depth+1, args...) + WarningDepth(depth+1, args...) } func (c *componentData) ErrorDepth(depth int, args ...any) { args = append([]any{"[" + string(c.name) + "]"}, args...) - grpclog.ErrorDepth(depth+1, args...) + ErrorDepth(depth+1, args...) } func (c *componentData) FatalDepth(depth int, args ...any) { args = append([]any{"[" + string(c.name) + "]"}, args...) - grpclog.FatalDepth(depth+1, args...) + FatalDepth(depth+1, args...) } func (c *componentData) Info(args ...any) { diff --git a/vendor/google.golang.org/grpc/grpclog/grpclog.go b/vendor/google.golang.org/grpc/grpclog/grpclog.go index 16928c9cb..db320105e 100644 --- a/vendor/google.golang.org/grpc/grpclog/grpclog.go +++ b/vendor/google.golang.org/grpc/grpclog/grpclog.go @@ -18,18 +18,15 @@ // Package grpclog defines logging for grpc. // -// All logs in transport and grpclb packages only go to verbose level 2. -// All logs in other packages in grpc are logged in spite of the verbosity level. -// -// In the default logger, -// severity level can be set by environment variable GRPC_GO_LOG_SEVERITY_LEVEL, -// verbosity level can be set by GRPC_GO_LOG_VERBOSITY_LEVEL. -package grpclog // import "google.golang.org/grpc/grpclog" +// In the default logger, severity level can be set by environment variable +// GRPC_GO_LOG_SEVERITY_LEVEL, verbosity level can be set by +// GRPC_GO_LOG_VERBOSITY_LEVEL. +package grpclog import ( "os" - "google.golang.org/grpc/internal/grpclog" + "google.golang.org/grpc/grpclog/internal" ) func init() { @@ -38,58 +35,58 @@ func init() { // V reports whether verbosity level l is at least the requested verbose level. func V(l int) bool { - return grpclog.Logger.V(l) + return internal.LoggerV2Impl.V(l) } // Info logs to the INFO log. func Info(args ...any) { - grpclog.Logger.Info(args...) + internal.LoggerV2Impl.Info(args...) } // Infof logs to the INFO log. Arguments are handled in the manner of fmt.Printf. func Infof(format string, args ...any) { - grpclog.Logger.Infof(format, args...) + internal.LoggerV2Impl.Infof(format, args...) } // Infoln logs to the INFO log. Arguments are handled in the manner of fmt.Println. func Infoln(args ...any) { - grpclog.Logger.Infoln(args...) + internal.LoggerV2Impl.Infoln(args...) } // Warning logs to the WARNING log. func Warning(args ...any) { - grpclog.Logger.Warning(args...) + internal.LoggerV2Impl.Warning(args...) } // Warningf logs to the WARNING log. Arguments are handled in the manner of fmt.Printf. func Warningf(format string, args ...any) { - grpclog.Logger.Warningf(format, args...) + internal.LoggerV2Impl.Warningf(format, args...) } // Warningln logs to the WARNING log. Arguments are handled in the manner of fmt.Println. func Warningln(args ...any) { - grpclog.Logger.Warningln(args...) + internal.LoggerV2Impl.Warningln(args...) } // Error logs to the ERROR log. func Error(args ...any) { - grpclog.Logger.Error(args...) + internal.LoggerV2Impl.Error(args...) } // Errorf logs to the ERROR log. Arguments are handled in the manner of fmt.Printf. func Errorf(format string, args ...any) { - grpclog.Logger.Errorf(format, args...) + internal.LoggerV2Impl.Errorf(format, args...) } // Errorln logs to the ERROR log. Arguments are handled in the manner of fmt.Println. func Errorln(args ...any) { - grpclog.Logger.Errorln(args...) + internal.LoggerV2Impl.Errorln(args...) } // Fatal logs to the FATAL log. Arguments are handled in the manner of fmt.Print. // It calls os.Exit() with exit code 1. func Fatal(args ...any) { - grpclog.Logger.Fatal(args...) + internal.LoggerV2Impl.Fatal(args...) // Make sure fatal logs will exit. os.Exit(1) } @@ -97,15 +94,15 @@ func Fatal(args ...any) { // Fatalf logs to the FATAL log. Arguments are handled in the manner of fmt.Printf. // It calls os.Exit() with exit code 1. func Fatalf(format string, args ...any) { - grpclog.Logger.Fatalf(format, args...) + internal.LoggerV2Impl.Fatalf(format, args...) // Make sure fatal logs will exit. os.Exit(1) } // Fatalln logs to the FATAL log. Arguments are handled in the manner of fmt.Println. -// It calle os.Exit()) with exit code 1. +// It calls os.Exit() with exit code 1. func Fatalln(args ...any) { - grpclog.Logger.Fatalln(args...) + internal.LoggerV2Impl.Fatalln(args...) // Make sure fatal logs will exit. os.Exit(1) } @@ -114,19 +111,76 @@ func Fatalln(args ...any) { // // Deprecated: use Info. func Print(args ...any) { - grpclog.Logger.Info(args...) + internal.LoggerV2Impl.Info(args...) } // Printf prints to the logger. Arguments are handled in the manner of fmt.Printf. // // Deprecated: use Infof. func Printf(format string, args ...any) { - grpclog.Logger.Infof(format, args...) + internal.LoggerV2Impl.Infof(format, args...) } // Println prints to the logger. Arguments are handled in the manner of fmt.Println. // // Deprecated: use Infoln. func Println(args ...any) { - grpclog.Logger.Infoln(args...) + internal.LoggerV2Impl.Infoln(args...) +} + +// InfoDepth logs to the INFO log at the specified depth. +// +// # Experimental +// +// Notice: This API is EXPERIMENTAL and may be changed or removed in a +// later release. +func InfoDepth(depth int, args ...any) { + if internal.DepthLoggerV2Impl != nil { + internal.DepthLoggerV2Impl.InfoDepth(depth, args...) + } else { + internal.LoggerV2Impl.Infoln(args...) + } +} + +// WarningDepth logs to the WARNING log at the specified depth. +// +// # Experimental +// +// Notice: This API is EXPERIMENTAL and may be changed or removed in a +// later release. +func WarningDepth(depth int, args ...any) { + if internal.DepthLoggerV2Impl != nil { + internal.DepthLoggerV2Impl.WarningDepth(depth, args...) + } else { + internal.LoggerV2Impl.Warningln(args...) + } +} + +// ErrorDepth logs to the ERROR log at the specified depth. +// +// # Experimental +// +// Notice: This API is EXPERIMENTAL and may be changed or removed in a +// later release. +func ErrorDepth(depth int, args ...any) { + if internal.DepthLoggerV2Impl != nil { + internal.DepthLoggerV2Impl.ErrorDepth(depth, args...) + } else { + internal.LoggerV2Impl.Errorln(args...) + } +} + +// FatalDepth logs to the FATAL log at the specified depth. +// +// # Experimental +// +// Notice: This API is EXPERIMENTAL and may be changed or removed in a +// later release. +func FatalDepth(depth int, args ...any) { + if internal.DepthLoggerV2Impl != nil { + internal.DepthLoggerV2Impl.FatalDepth(depth, args...) + } else { + internal.LoggerV2Impl.Fatalln(args...) + } + os.Exit(1) } diff --git a/vendor/google.golang.org/grpc/grpclog/internal/grpclog.go b/vendor/google.golang.org/grpc/grpclog/internal/grpclog.go new file mode 100644 index 000000000..59c03bc14 --- /dev/null +++ b/vendor/google.golang.org/grpc/grpclog/internal/grpclog.go @@ -0,0 +1,26 @@ +/* + * + * Copyright 2024 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. + * + */ + +// Package internal contains functionality internal to the grpclog package. +package internal + +// LoggerV2Impl is the logger used for the non-depth log functions. +var LoggerV2Impl LoggerV2 + +// DepthLoggerV2Impl is the logger used for the depth log functions. +var DepthLoggerV2Impl DepthLoggerV2 diff --git a/vendor/google.golang.org/grpc/grpclog/internal/logger.go b/vendor/google.golang.org/grpc/grpclog/internal/logger.go new file mode 100644 index 000000000..e524fdd40 --- /dev/null +++ b/vendor/google.golang.org/grpc/grpclog/internal/logger.go @@ -0,0 +1,87 @@ +/* + * + * Copyright 2024 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. + * + */ + +package internal + +// Logger mimics golang's standard Logger as an interface. +// +// Deprecated: use LoggerV2. +type Logger interface { + Fatal(args ...any) + Fatalf(format string, args ...any) + Fatalln(args ...any) + Print(args ...any) + Printf(format string, args ...any) + Println(args ...any) +} + +// LoggerWrapper wraps Logger into a LoggerV2. +type LoggerWrapper struct { + Logger +} + +// Info logs to INFO log. Arguments are handled in the manner of fmt.Print. +func (l *LoggerWrapper) Info(args ...any) { + l.Logger.Print(args...) +} + +// Infoln logs to INFO log. Arguments are handled in the manner of fmt.Println. +func (l *LoggerWrapper) Infoln(args ...any) { + l.Logger.Println(args...) +} + +// Infof logs to INFO log. Arguments are handled in the manner of fmt.Printf. +func (l *LoggerWrapper) Infof(format string, args ...any) { + l.Logger.Printf(format, args...) +} + +// Warning logs to WARNING log. Arguments are handled in the manner of fmt.Print. +func (l *LoggerWrapper) Warning(args ...any) { + l.Logger.Print(args...) +} + +// Warningln logs to WARNING log. Arguments are handled in the manner of fmt.Println. +func (l *LoggerWrapper) Warningln(args ...any) { + l.Logger.Println(args...) +} + +// Warningf logs to WARNING log. Arguments are handled in the manner of fmt.Printf. +func (l *LoggerWrapper) Warningf(format string, args ...any) { + l.Logger.Printf(format, args...) +} + +// Error logs to ERROR log. Arguments are handled in the manner of fmt.Print. +func (l *LoggerWrapper) Error(args ...any) { + l.Logger.Print(args...) +} + +// Errorln logs to ERROR log. Arguments are handled in the manner of fmt.Println. +func (l *LoggerWrapper) Errorln(args ...any) { + l.Logger.Println(args...) +} + +// Errorf logs to ERROR log. Arguments are handled in the manner of fmt.Printf. +func (l *LoggerWrapper) Errorf(format string, args ...any) { + l.Logger.Printf(format, args...) +} + +// V reports whether verbosity level l is at least the requested verbose level. +func (*LoggerWrapper) V(int) bool { + // Returns true for all verbose level. + return true +} diff --git a/vendor/google.golang.org/grpc/internal/grpclog/grpclog.go b/vendor/google.golang.org/grpc/grpclog/internal/loggerv2.go similarity index 52% rename from vendor/google.golang.org/grpc/internal/grpclog/grpclog.go rename to vendor/google.golang.org/grpc/grpclog/internal/loggerv2.go index bfc45102a..07df71e98 100644 --- a/vendor/google.golang.org/grpc/internal/grpclog/grpclog.go +++ b/vendor/google.golang.org/grpc/grpclog/internal/loggerv2.go @@ -1,6 +1,6 @@ /* * - * Copyright 2020 gRPC authors. + * Copyright 2024 gRPC authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,59 +16,17 @@ * */ -// Package grpclog (internal) defines depth logging for grpc. -package grpclog +package internal import ( + "encoding/json" + "fmt" + "io" + "log" "os" ) -// Logger is the logger used for the non-depth log functions. -var Logger LoggerV2 - -// DepthLogger is the logger used for the depth log functions. -var DepthLogger DepthLoggerV2 - -// InfoDepth logs to the INFO log at the specified depth. -func InfoDepth(depth int, args ...any) { - if DepthLogger != nil { - DepthLogger.InfoDepth(depth, args...) - } else { - Logger.Infoln(args...) - } -} - -// WarningDepth logs to the WARNING log at the specified depth. -func WarningDepth(depth int, args ...any) { - if DepthLogger != nil { - DepthLogger.WarningDepth(depth, args...) - } else { - Logger.Warningln(args...) - } -} - -// ErrorDepth logs to the ERROR log at the specified depth. -func ErrorDepth(depth int, args ...any) { - if DepthLogger != nil { - DepthLogger.ErrorDepth(depth, args...) - } else { - Logger.Errorln(args...) - } -} - -// FatalDepth logs to the FATAL log at the specified depth. -func FatalDepth(depth int, args ...any) { - if DepthLogger != nil { - DepthLogger.FatalDepth(depth, args...) - } else { - Logger.Fatalln(args...) - } - os.Exit(1) -} - // LoggerV2 does underlying logging work for grpclog. -// This is a copy of the LoggerV2 defined in the external grpclog package. It -// is defined here to avoid a circular dependency. type LoggerV2 interface { // Info logs to INFO log. Arguments are handled in the manner of fmt.Print. Info(args ...any) @@ -107,14 +65,13 @@ type LoggerV2 interface { // DepthLoggerV2 logs at a specified call frame. If a LoggerV2 also implements // DepthLoggerV2, the below functions will be called with the appropriate stack // depth set for trivial functions the logger may ignore. -// This is a copy of the DepthLoggerV2 defined in the external grpclog package. -// It is defined here to avoid a circular dependency. // // # Experimental // // Notice: This type is EXPERIMENTAL and may be changed or removed in a // later release. type DepthLoggerV2 interface { + LoggerV2 // InfoDepth logs to INFO log at the specified depth. Arguments are handled in the manner of fmt.Println. InfoDepth(depth int, args ...any) // WarningDepth logs to WARNING log at the specified depth. Arguments are handled in the manner of fmt.Println. @@ -124,3 +81,124 @@ type DepthLoggerV2 interface { // FatalDepth logs to FATAL log at the specified depth. Arguments are handled in the manner of fmt.Println. FatalDepth(depth int, args ...any) } + +const ( + // infoLog indicates Info severity. + infoLog int = iota + // warningLog indicates Warning severity. + warningLog + // errorLog indicates Error severity. + errorLog + // fatalLog indicates Fatal severity. + fatalLog +) + +// severityName contains the string representation of each severity. +var severityName = []string{ + infoLog: "INFO", + warningLog: "WARNING", + errorLog: "ERROR", + fatalLog: "FATAL", +} + +// loggerT is the default logger used by grpclog. +type loggerT struct { + m []*log.Logger + v int + jsonFormat bool +} + +func (g *loggerT) output(severity int, s string) { + sevStr := severityName[severity] + if !g.jsonFormat { + g.m[severity].Output(2, fmt.Sprintf("%v: %v", sevStr, s)) + return + } + // TODO: we can also include the logging component, but that needs more + // (API) changes. + b, _ := json.Marshal(map[string]string{ + "severity": sevStr, + "message": s, + }) + g.m[severity].Output(2, string(b)) +} + +func (g *loggerT) Info(args ...any) { + g.output(infoLog, fmt.Sprint(args...)) +} + +func (g *loggerT) Infoln(args ...any) { + g.output(infoLog, fmt.Sprintln(args...)) +} + +func (g *loggerT) Infof(format string, args ...any) { + g.output(infoLog, fmt.Sprintf(format, args...)) +} + +func (g *loggerT) Warning(args ...any) { + g.output(warningLog, fmt.Sprint(args...)) +} + +func (g *loggerT) Warningln(args ...any) { + g.output(warningLog, fmt.Sprintln(args...)) +} + +func (g *loggerT) Warningf(format string, args ...any) { + g.output(warningLog, fmt.Sprintf(format, args...)) +} + +func (g *loggerT) Error(args ...any) { + g.output(errorLog, fmt.Sprint(args...)) +} + +func (g *loggerT) Errorln(args ...any) { + g.output(errorLog, fmt.Sprintln(args...)) +} + +func (g *loggerT) Errorf(format string, args ...any) { + g.output(errorLog, fmt.Sprintf(format, args...)) +} + +func (g *loggerT) Fatal(args ...any) { + g.output(fatalLog, fmt.Sprint(args...)) + os.Exit(1) +} + +func (g *loggerT) Fatalln(args ...any) { + g.output(fatalLog, fmt.Sprintln(args...)) + os.Exit(1) +} + +func (g *loggerT) Fatalf(format string, args ...any) { + g.output(fatalLog, fmt.Sprintf(format, args...)) + os.Exit(1) +} + +func (g *loggerT) V(l int) bool { + return l <= g.v +} + +// LoggerV2Config configures the LoggerV2 implementation. +type LoggerV2Config struct { + // Verbosity sets the verbosity level of the logger. + Verbosity int + // FormatJSON controls whether the logger should output logs in JSON format. + FormatJSON bool +} + +// NewLoggerV2 creates a new LoggerV2 instance with the provided configuration. +// The infoW, warningW, and errorW writers are used to write log messages of +// different severity levels. +func NewLoggerV2(infoW, warningW, errorW io.Writer, c LoggerV2Config) LoggerV2 { + var m []*log.Logger + flag := log.LstdFlags + if c.FormatJSON { + flag = 0 + } + m = append(m, log.New(infoW, "", flag)) + m = append(m, log.New(io.MultiWriter(infoW, warningW), "", flag)) + ew := io.MultiWriter(infoW, warningW, errorW) // ew will be used for error and fatal. + m = append(m, log.New(ew, "", flag)) + m = append(m, log.New(ew, "", flag)) + return &loggerT{m: m, v: c.Verbosity, jsonFormat: c.FormatJSON} +} diff --git a/vendor/google.golang.org/grpc/grpclog/logger.go b/vendor/google.golang.org/grpc/grpclog/logger.go index b1674d826..4b2035857 100644 --- a/vendor/google.golang.org/grpc/grpclog/logger.go +++ b/vendor/google.golang.org/grpc/grpclog/logger.go @@ -18,70 +18,17 @@ package grpclog -import "google.golang.org/grpc/internal/grpclog" +import "google.golang.org/grpc/grpclog/internal" // Logger mimics golang's standard Logger as an interface. // // Deprecated: use LoggerV2. -type Logger interface { - Fatal(args ...any) - Fatalf(format string, args ...any) - Fatalln(args ...any) - Print(args ...any) - Printf(format string, args ...any) - Println(args ...any) -} +type Logger internal.Logger // SetLogger sets the logger that is used in grpc. Call only from // init() functions. // // Deprecated: use SetLoggerV2. func SetLogger(l Logger) { - grpclog.Logger = &loggerWrapper{Logger: l} -} - -// loggerWrapper wraps Logger into a LoggerV2. -type loggerWrapper struct { - Logger -} - -func (g *loggerWrapper) Info(args ...any) { - g.Logger.Print(args...) -} - -func (g *loggerWrapper) Infoln(args ...any) { - g.Logger.Println(args...) -} - -func (g *loggerWrapper) Infof(format string, args ...any) { - g.Logger.Printf(format, args...) -} - -func (g *loggerWrapper) Warning(args ...any) { - g.Logger.Print(args...) -} - -func (g *loggerWrapper) Warningln(args ...any) { - g.Logger.Println(args...) -} - -func (g *loggerWrapper) Warningf(format string, args ...any) { - g.Logger.Printf(format, args...) -} - -func (g *loggerWrapper) Error(args ...any) { - g.Logger.Print(args...) -} - -func (g *loggerWrapper) Errorln(args ...any) { - g.Logger.Println(args...) -} - -func (g *loggerWrapper) Errorf(format string, args ...any) { - g.Logger.Printf(format, args...) -} - -func (g *loggerWrapper) V(l int) bool { - // Returns true for all verbose level. - return true + internal.LoggerV2Impl = &internal.LoggerWrapper{Logger: l} } diff --git a/vendor/google.golang.org/grpc/grpclog/loggerv2.go b/vendor/google.golang.org/grpc/grpclog/loggerv2.go index ecfd36d71..892dc13d1 100644 --- a/vendor/google.golang.org/grpc/grpclog/loggerv2.go +++ b/vendor/google.golang.org/grpc/grpclog/loggerv2.go @@ -19,52 +19,16 @@ package grpclog import ( - "encoding/json" - "fmt" "io" - "log" "os" "strconv" "strings" - "google.golang.org/grpc/internal/grpclog" + "google.golang.org/grpc/grpclog/internal" ) // LoggerV2 does underlying logging work for grpclog. -type LoggerV2 interface { - // Info logs to INFO log. Arguments are handled in the manner of fmt.Print. - Info(args ...any) - // Infoln logs to INFO log. Arguments are handled in the manner of fmt.Println. - Infoln(args ...any) - // Infof logs to INFO log. Arguments are handled in the manner of fmt.Printf. - Infof(format string, args ...any) - // Warning logs to WARNING log. Arguments are handled in the manner of fmt.Print. - Warning(args ...any) - // Warningln logs to WARNING log. Arguments are handled in the manner of fmt.Println. - Warningln(args ...any) - // Warningf logs to WARNING log. Arguments are handled in the manner of fmt.Printf. - Warningf(format string, args ...any) - // Error logs to ERROR log. Arguments are handled in the manner of fmt.Print. - Error(args ...any) - // Errorln logs to ERROR log. Arguments are handled in the manner of fmt.Println. - Errorln(args ...any) - // Errorf logs to ERROR log. Arguments are handled in the manner of fmt.Printf. - Errorf(format string, args ...any) - // Fatal logs to ERROR log. Arguments are handled in the manner of fmt.Print. - // gRPC ensures that all Fatal logs will exit with os.Exit(1). - // Implementations may also call os.Exit() with a non-zero exit code. - Fatal(args ...any) - // Fatalln logs to ERROR log. Arguments are handled in the manner of fmt.Println. - // gRPC ensures that all Fatal logs will exit with os.Exit(1). - // Implementations may also call os.Exit() with a non-zero exit code. - Fatalln(args ...any) - // Fatalf logs to ERROR log. Arguments are handled in the manner of fmt.Printf. - // gRPC ensures that all Fatal logs will exit with os.Exit(1). - // Implementations may also call os.Exit() with a non-zero exit code. - Fatalf(format string, args ...any) - // V reports whether verbosity level l is at least the requested verbose level. - V(l int) bool -} +type LoggerV2 internal.LoggerV2 // SetLoggerV2 sets logger that is used in grpc to a V2 logger. // Not mutex-protected, should be called before any gRPC functions. @@ -72,34 +36,8 @@ func SetLoggerV2(l LoggerV2) { if _, ok := l.(*componentData); ok { panic("cannot use component logger as grpclog logger") } - grpclog.Logger = l - grpclog.DepthLogger, _ = l.(grpclog.DepthLoggerV2) -} - -const ( - // infoLog indicates Info severity. - infoLog int = iota - // warningLog indicates Warning severity. - warningLog - // errorLog indicates Error severity. - errorLog - // fatalLog indicates Fatal severity. - fatalLog -) - -// severityName contains the string representation of each severity. -var severityName = []string{ - infoLog: "INFO", - warningLog: "WARNING", - errorLog: "ERROR", - fatalLog: "FATAL", -} - -// loggerT is the default logger used by grpclog. -type loggerT struct { - m []*log.Logger - v int - jsonFormat bool + internal.LoggerV2Impl = l + internal.DepthLoggerV2Impl, _ = l.(internal.DepthLoggerV2) } // NewLoggerV2 creates a loggerV2 with the provided writers. @@ -108,32 +46,13 @@ type loggerT struct { // Warning logs will be written to warningW and infoW. // Info logs will be written to infoW. func NewLoggerV2(infoW, warningW, errorW io.Writer) LoggerV2 { - return newLoggerV2WithConfig(infoW, warningW, errorW, loggerV2Config{}) + return internal.NewLoggerV2(infoW, warningW, errorW, internal.LoggerV2Config{}) } // NewLoggerV2WithVerbosity creates a loggerV2 with the provided writers and // verbosity level. func NewLoggerV2WithVerbosity(infoW, warningW, errorW io.Writer, v int) LoggerV2 { - return newLoggerV2WithConfig(infoW, warningW, errorW, loggerV2Config{verbose: v}) -} - -type loggerV2Config struct { - verbose int - jsonFormat bool -} - -func newLoggerV2WithConfig(infoW, warningW, errorW io.Writer, c loggerV2Config) LoggerV2 { - var m []*log.Logger - flag := log.LstdFlags - if c.jsonFormat { - flag = 0 - } - m = append(m, log.New(infoW, "", flag)) - m = append(m, log.New(io.MultiWriter(infoW, warningW), "", flag)) - ew := io.MultiWriter(infoW, warningW, errorW) // ew will be used for error and fatal. - m = append(m, log.New(ew, "", flag)) - m = append(m, log.New(ew, "", flag)) - return &loggerT{m: m, v: c.verbose, jsonFormat: c.jsonFormat} + return internal.NewLoggerV2(infoW, warningW, errorW, internal.LoggerV2Config{Verbosity: v}) } // newLoggerV2 creates a loggerV2 to be used as default logger. @@ -161,80 +80,10 @@ func newLoggerV2() LoggerV2 { jsonFormat := strings.EqualFold(os.Getenv("GRPC_GO_LOG_FORMATTER"), "json") - return newLoggerV2WithConfig(infoW, warningW, errorW, loggerV2Config{ - verbose: v, - jsonFormat: jsonFormat, - }) -} - -func (g *loggerT) output(severity int, s string) { - sevStr := severityName[severity] - if !g.jsonFormat { - g.m[severity].Output(2, fmt.Sprintf("%v: %v", sevStr, s)) - return - } - // TODO: we can also include the logging component, but that needs more - // (API) changes. - b, _ := json.Marshal(map[string]string{ - "severity": sevStr, - "message": s, + return internal.NewLoggerV2(infoW, warningW, errorW, internal.LoggerV2Config{ + Verbosity: v, + FormatJSON: jsonFormat, }) - g.m[severity].Output(2, string(b)) -} - -func (g *loggerT) Info(args ...any) { - g.output(infoLog, fmt.Sprint(args...)) -} - -func (g *loggerT) Infoln(args ...any) { - g.output(infoLog, fmt.Sprintln(args...)) -} - -func (g *loggerT) Infof(format string, args ...any) { - g.output(infoLog, fmt.Sprintf(format, args...)) -} - -func (g *loggerT) Warning(args ...any) { - g.output(warningLog, fmt.Sprint(args...)) -} - -func (g *loggerT) Warningln(args ...any) { - g.output(warningLog, fmt.Sprintln(args...)) -} - -func (g *loggerT) Warningf(format string, args ...any) { - g.output(warningLog, fmt.Sprintf(format, args...)) -} - -func (g *loggerT) Error(args ...any) { - g.output(errorLog, fmt.Sprint(args...)) -} - -func (g *loggerT) Errorln(args ...any) { - g.output(errorLog, fmt.Sprintln(args...)) -} - -func (g *loggerT) Errorf(format string, args ...any) { - g.output(errorLog, fmt.Sprintf(format, args...)) -} - -func (g *loggerT) Fatal(args ...any) { - g.output(fatalLog, fmt.Sprint(args...)) - os.Exit(1) -} - -func (g *loggerT) Fatalln(args ...any) { - g.output(fatalLog, fmt.Sprintln(args...)) - os.Exit(1) -} - -func (g *loggerT) Fatalf(format string, args ...any) { - g.output(fatalLog, fmt.Sprintf(format, args...)) - os.Exit(1) -} - -func (g *loggerT) V(l int) bool { - return l <= g.v } // DepthLoggerV2 logs at a specified call frame. If a LoggerV2 also implements @@ -245,14 +94,4 @@ func (g *loggerT) V(l int) bool { // // Notice: This type is EXPERIMENTAL and may be changed or removed in a // later release. -type DepthLoggerV2 interface { - LoggerV2 - // InfoDepth logs to INFO log at the specified depth. Arguments are handled in the manner of fmt.Println. - InfoDepth(depth int, args ...any) - // WarningDepth logs to WARNING log at the specified depth. Arguments are handled in the manner of fmt.Println. - WarningDepth(depth int, args ...any) - // ErrorDepth logs to ERROR log at the specified depth. Arguments are handled in the manner of fmt.Println. - ErrorDepth(depth int, args ...any) - // FatalDepth logs to FATAL log at the specified depth. Arguments are handled in the manner of fmt.Println. - FatalDepth(depth int, args ...any) -} +type DepthLoggerV2 internal.DepthLoggerV2 diff --git a/vendor/google.golang.org/grpc/internal/backoff/backoff.go b/vendor/google.golang.org/grpc/internal/backoff/backoff.go index fed1c011a..b15cf482d 100644 --- a/vendor/google.golang.org/grpc/internal/backoff/backoff.go +++ b/vendor/google.golang.org/grpc/internal/backoff/backoff.go @@ -25,10 +25,10 @@ package backoff import ( "context" "errors" + "math/rand" "time" grpcbackoff "google.golang.org/grpc/backoff" - "google.golang.org/grpc/internal/grpcrand" ) // Strategy defines the methodology for backing off after a grpc connection @@ -67,7 +67,7 @@ func (bc Exponential) Backoff(retries int) time.Duration { } // Randomize backoff delays so that if a cluster of requests start at // the same time, they won't operate in lockstep. - backoff *= 1 + bc.Config.Jitter*(grpcrand.Float64()*2-1) + backoff *= 1 + bc.Config.Jitter*(rand.Float64()*2-1) if backoff < 0 { return 0 } diff --git a/vendor/google.golang.org/grpc/internal/balancer/gracefulswitch/config.go b/vendor/google.golang.org/grpc/internal/balancer/gracefulswitch/config.go index 6bf7f8739..85540f86a 100644 --- a/vendor/google.golang.org/grpc/internal/balancer/gracefulswitch/config.go +++ b/vendor/google.golang.org/grpc/internal/balancer/gracefulswitch/config.go @@ -33,6 +33,8 @@ type lbConfig struct { childConfig serviceconfig.LoadBalancingConfig } +// ChildName returns the name of the child balancer of the gracefulswitch +// Balancer. func ChildName(l serviceconfig.LoadBalancingConfig) string { return l.(*lbConfig).childBuilder.Name() } @@ -75,7 +77,6 @@ func ParseConfig(cfg json.RawMessage) (serviceconfig.LoadBalancingConfig, error) if err != nil { return nil, fmt.Errorf("error parsing config for policy %q: %v", name, err) } - return &lbConfig{childBuilder: builder, childConfig: cfg}, nil } diff --git a/vendor/google.golang.org/grpc/internal/balancer/gracefulswitch/gracefulswitch.go b/vendor/google.golang.org/grpc/internal/balancer/gracefulswitch/gracefulswitch.go index 45d5e50ea..73bb4c4ee 100644 --- a/vendor/google.golang.org/grpc/internal/balancer/gracefulswitch/gracefulswitch.go +++ b/vendor/google.golang.org/grpc/internal/balancer/gracefulswitch/gracefulswitch.go @@ -169,7 +169,6 @@ func (gsb *Balancer) latestBalancer() *balancerWrapper { func (gsb *Balancer) UpdateClientConnState(state balancer.ClientConnState) error { // The resolver data is only relevant to the most recent LB Policy. balToUpdate := gsb.latestBalancer() - gsbCfg, ok := state.BalancerConfig.(*lbConfig) if ok { // Switch to the child in the config unless it is already active. diff --git a/vendor/google.golang.org/grpc/internal/binarylog/method_logger.go b/vendor/google.golang.org/grpc/internal/binarylog/method_logger.go index e8456a77c..966932891 100644 --- a/vendor/google.golang.org/grpc/internal/binarylog/method_logger.go +++ b/vendor/google.golang.org/grpc/internal/binarylog/method_logger.go @@ -65,7 +65,7 @@ type TruncatingMethodLogger struct { callID uint64 idWithinCallGen *callIDGenerator - sink Sink // TODO(blog): make this plugable. + sink Sink // TODO(blog): make this pluggable. } // NewTruncatingMethodLogger returns a new truncating method logger. @@ -80,7 +80,7 @@ func NewTruncatingMethodLogger(h, m uint64) *TruncatingMethodLogger { callID: idGen.next(), idWithinCallGen: &callIDGenerator{}, - sink: DefaultSink, // TODO(blog): make it plugable. + sink: DefaultSink, // TODO(blog): make it pluggable. } } @@ -106,7 +106,7 @@ func (ml *TruncatingMethodLogger) Build(c LogEntryConfig) *binlogpb.GrpcLogEntry } // Log creates a proto binary log entry, and logs it to the sink. -func (ml *TruncatingMethodLogger) Log(ctx context.Context, c LogEntryConfig) { +func (ml *TruncatingMethodLogger) Log(_ context.Context, c LogEntryConfig) { ml.sink.Write(ml.Build(c)) } @@ -397,7 +397,7 @@ func metadataKeyOmit(key string) bool { switch key { case "lb-token", ":path", ":authority", "content-encoding", "content-type", "user-agent", "te": return true - case "grpc-trace-bin": // grpc-trace-bin is special because it's visiable to users. + case "grpc-trace-bin": // grpc-trace-bin is special because it's visible to users. return false } return strings.HasPrefix(key, "grpc-") diff --git a/vendor/google.golang.org/grpc/internal/channelz/channel.go b/vendor/google.golang.org/grpc/internal/channelz/channel.go index d7e9e1d54..3ec662799 100644 --- a/vendor/google.golang.org/grpc/internal/channelz/channel.go +++ b/vendor/google.golang.org/grpc/internal/channelz/channel.go @@ -43,6 +43,8 @@ type Channel struct { // Non-zero traceRefCount means the trace of this channel cannot be deleted. traceRefCount int32 + // ChannelMetrics holds connectivity state, target and call metrics for the + // channel within channelz. ChannelMetrics ChannelMetrics } @@ -50,6 +52,8 @@ type Channel struct { // nesting. func (c *Channel) channelzIdentifier() {} +// String returns a string representation of the Channel, including its parent +// entity and ID. func (c *Channel) String() string { if c.Parent == nil { return fmt.Sprintf("Channel #%d", c.ID) @@ -61,24 +65,31 @@ func (c *Channel) id() int64 { return c.ID } +// SubChans returns a copy of the map of sub-channels associated with the +// Channel. func (c *Channel) SubChans() map[int64]string { db.mu.RLock() defer db.mu.RUnlock() return copyMap(c.subChans) } +// NestedChans returns a copy of the map of nested channels associated with the +// Channel. func (c *Channel) NestedChans() map[int64]string { db.mu.RLock() defer db.mu.RUnlock() return copyMap(c.nestedChans) } +// Trace returns a copy of the Channel's trace data. func (c *Channel) Trace() *ChannelTrace { db.mu.RLock() defer db.mu.RUnlock() return c.trace.copy() } +// ChannelMetrics holds connectivity state, target and call metrics for the +// channel within channelz. type ChannelMetrics struct { // The current connectivity state of the channel. State atomic.Pointer[connectivity.State] @@ -136,12 +147,16 @@ func strFromPointer(s *string) string { return *s } +// String returns a string representation of the ChannelMetrics, including its +// state, target, and call metrics. func (c *ChannelMetrics) String() string { return fmt.Sprintf("State: %v, Target: %s, CallsStarted: %v, CallsSucceeded: %v, CallsFailed: %v, LastCallStartedTimestamp: %v", c.State.Load(), strFromPointer(c.Target.Load()), c.CallsStarted.Load(), c.CallsSucceeded.Load(), c.CallsFailed.Load(), c.LastCallStartedTimestamp.Load(), ) } +// NewChannelMetricForTesting creates a new instance of ChannelMetrics with +// specified initial values for testing purposes. func NewChannelMetricForTesting(state connectivity.State, target string, started, succeeded, failed, timestamp int64) *ChannelMetrics { c := &ChannelMetrics{} c.State.Store(&state) diff --git a/vendor/google.golang.org/grpc/internal/channelz/channelmap.go b/vendor/google.golang.org/grpc/internal/channelz/channelmap.go index dfe18b089..64c791953 100644 --- a/vendor/google.golang.org/grpc/internal/channelz/channelmap.go +++ b/vendor/google.golang.org/grpc/internal/channelz/channelmap.go @@ -46,7 +46,7 @@ type entry interface { // channelMap is the storage data structure for channelz. // -// Methods of channelMap can be divided in two two categories with respect to +// Methods of channelMap can be divided into two categories with respect to // locking. // // 1. Methods acquire the global lock. @@ -234,13 +234,6 @@ func copyMap(m map[int64]string) map[int64]string { return n } -func min(a, b int) int { - if a < b { - return a - } - return b -} - func (c *channelMap) getTopChannels(id int64, maxResults int) ([]*Channel, bool) { if maxResults <= 0 { maxResults = EntriesPerPage diff --git a/vendor/google.golang.org/grpc/internal/channelz/funcs.go b/vendor/google.golang.org/grpc/internal/channelz/funcs.go index 03e24e150..078bb8123 100644 --- a/vendor/google.golang.org/grpc/internal/channelz/funcs.go +++ b/vendor/google.golang.org/grpc/internal/channelz/funcs.go @@ -33,7 +33,7 @@ var ( // outside this package except by tests. IDGen IDGenerator - db *channelMap = newChannelMap() + db = newChannelMap() // EntriesPerPage defines the number of channelz entries to be shown on a web page. EntriesPerPage = 50 curState int32 diff --git a/vendor/google.golang.org/grpc/internal/channelz/server.go b/vendor/google.golang.org/grpc/internal/channelz/server.go index cdfc49d6e..b5a824992 100644 --- a/vendor/google.golang.org/grpc/internal/channelz/server.go +++ b/vendor/google.golang.org/grpc/internal/channelz/server.go @@ -59,6 +59,8 @@ func NewServerMetricsForTesting(started, succeeded, failed, timestamp int64) *Se return sm } +// CopyFrom copies the metrics data from the provided ServerMetrics +// instance into the current instance. func (sm *ServerMetrics) CopyFrom(o *ServerMetrics) { sm.CallsStarted.Store(o.CallsStarted.Load()) sm.CallsSucceeded.Store(o.CallsSucceeded.Load()) diff --git a/vendor/google.golang.org/grpc/internal/channelz/socket.go b/vendor/google.golang.org/grpc/internal/channelz/socket.go index fa64834b2..90103847c 100644 --- a/vendor/google.golang.org/grpc/internal/channelz/socket.go +++ b/vendor/google.golang.org/grpc/internal/channelz/socket.go @@ -70,13 +70,18 @@ type EphemeralSocketMetrics struct { RemoteFlowControlWindow int64 } +// SocketType represents the type of socket. type SocketType string +// SocketType can be one of these. const ( SocketTypeNormal = "NormalSocket" SocketTypeListen = "ListenSocket" ) +// Socket represents a socket within channelz which includes socket +// metrics and data related to socket activity and provides methods +// for managing and interacting with sockets. type Socket struct { Entity SocketType SocketType @@ -100,6 +105,8 @@ type Socket struct { Security credentials.ChannelzSecurityValue } +// String returns a string representation of the Socket, including its parent +// entity, socket type, and ID. func (ls *Socket) String() string { return fmt.Sprintf("%s %s #%d", ls.Parent, ls.SocketType, ls.ID) } diff --git a/vendor/google.golang.org/grpc/internal/channelz/subchannel.go b/vendor/google.golang.org/grpc/internal/channelz/subchannel.go index 3b88e4cba..b20802e6e 100644 --- a/vendor/google.golang.org/grpc/internal/channelz/subchannel.go +++ b/vendor/google.golang.org/grpc/internal/channelz/subchannel.go @@ -47,12 +47,14 @@ func (sc *SubChannel) id() int64 { return sc.ID } +// Sockets returns a copy of the sockets map associated with the SubChannel. func (sc *SubChannel) Sockets() map[int64]string { db.mu.RLock() defer db.mu.RUnlock() return copyMap(sc.sockets) } +// Trace returns a copy of the ChannelTrace associated with the SubChannel. func (sc *SubChannel) Trace() *ChannelTrace { db.mu.RLock() defer db.mu.RUnlock() diff --git a/vendor/google.golang.org/grpc/internal/channelz/syscall_nonlinux.go b/vendor/google.golang.org/grpc/internal/channelz/syscall_nonlinux.go index d1ed8df6a..0e6e18e18 100644 --- a/vendor/google.golang.org/grpc/internal/channelz/syscall_nonlinux.go +++ b/vendor/google.golang.org/grpc/internal/channelz/syscall_nonlinux.go @@ -35,13 +35,13 @@ type SocketOptionData struct { // Getsockopt defines the function to get socket options requested by channelz. // It is to be passed to syscall.RawConn.Control(). // Windows OS doesn't support Socket Option -func (s *SocketOptionData) Getsockopt(fd uintptr) { +func (s *SocketOptionData) Getsockopt(uintptr) { once.Do(func() { logger.Warning("Channelz: socket options are not supported on non-linux environments") }) } // GetSocketOption gets the socket option info of the conn. -func GetSocketOption(c any) *SocketOptionData { +func GetSocketOption(any) *SocketOptionData { return nil } diff --git a/vendor/google.golang.org/grpc/internal/channelz/trace.go b/vendor/google.golang.org/grpc/internal/channelz/trace.go index 36b867403..2bffe4777 100644 --- a/vendor/google.golang.org/grpc/internal/channelz/trace.go +++ b/vendor/google.golang.org/grpc/internal/channelz/trace.go @@ -79,13 +79,21 @@ type TraceEvent struct { Parent *TraceEvent } +// ChannelTrace provides tracing information for a channel. +// It tracks various events and metadata related to the channel's lifecycle +// and operations. type ChannelTrace struct { - cm *channelMap - clearCalled bool + cm *channelMap + clearCalled bool + // The time when the trace was created. CreationTime time.Time - EventNum int64 - mu sync.Mutex - Events []*traceEvent + // A counter for the number of events recorded in the + // trace. + EventNum int64 + mu sync.Mutex + // A slice of traceEvent pointers representing the events recorded for + // this channel. + Events []*traceEvent } func (c *ChannelTrace) copy() *ChannelTrace { @@ -175,6 +183,7 @@ var refChannelTypeToString = map[RefChannelType]string{ RefNormalSocket: "NormalSocket", } +// String returns a string representation of the RefChannelType func (r RefChannelType) String() string { return refChannelTypeToString[r] } diff --git a/vendor/google.golang.org/grpc/internal/envconfig/envconfig.go b/vendor/google.golang.org/grpc/internal/envconfig/envconfig.go index 685a3cb41..6e7dd6b77 100644 --- a/vendor/google.golang.org/grpc/internal/envconfig/envconfig.go +++ b/vendor/google.golang.org/grpc/internal/envconfig/envconfig.go @@ -28,9 +28,6 @@ import ( var ( // TXTErrIgnore is set if TXT errors should be ignored ("GRPC_GO_IGNORE_TXT_ERRORS" is not "false"). TXTErrIgnore = boolFromEnv("GRPC_GO_IGNORE_TXT_ERRORS", true) - // AdvertiseCompressors is set if registered compressor should be advertised - // ("GRPC_GO_ADVERTISE_COMPRESSORS" is not "false"). - AdvertiseCompressors = boolFromEnv("GRPC_GO_ADVERTISE_COMPRESSORS", true) // RingHashCap indicates the maximum ring size which defaults to 4096 // entries but may be overridden by setting the environment variable // "GRPC_RING_HASH_CAP". This does not override the default bounds @@ -43,6 +40,21 @@ var ( // ALTSMaxConcurrentHandshakes is the maximum number of concurrent ALTS // handshakes that can be performed. ALTSMaxConcurrentHandshakes = uint64FromEnv("GRPC_ALTS_MAX_CONCURRENT_HANDSHAKES", 100, 1, 100) + // EnforceALPNEnabled is set if TLS connections to servers with ALPN disabled + // should be rejected. The HTTP/2 protocol requires ALPN to be enabled, this + // option is present for backward compatibility. This option may be overridden + // by setting the environment variable "GRPC_ENFORCE_ALPN_ENABLED" to "true" + // or "false". + EnforceALPNEnabled = boolFromEnv("GRPC_ENFORCE_ALPN_ENABLED", true) + // XDSFallbackSupport is the env variable that controls whether support for + // xDS fallback is turned on. If this is unset or is false, only the first + // xDS server in the list of server configs will be used. + XDSFallbackSupport = boolFromEnv("GRPC_EXPERIMENTAL_XDS_FALLBACK", false) + // NewPickFirstEnabled is set if the new pickfirst leaf policy is to be used + // instead of the exiting pickfirst implementation. This can be enabled by + // setting the environment variable "GRPC_EXPERIMENTAL_ENABLE_NEW_PICK_FIRST" + // to "true". + NewPickFirstEnabled = boolFromEnv("GRPC_EXPERIMENTAL_ENABLE_NEW_PICK_FIRST", false) ) func boolFromEnv(envVar string, def bool) bool { diff --git a/vendor/google.golang.org/grpc/internal/experimental.go b/vendor/google.golang.org/grpc/internal/experimental.go index 7f7044e17..7617be215 100644 --- a/vendor/google.golang.org/grpc/internal/experimental.go +++ b/vendor/google.golang.org/grpc/internal/experimental.go @@ -18,11 +18,11 @@ package internal var ( - // WithRecvBufferPool is implemented by the grpc package and returns a dial + // WithBufferPool is implemented by the grpc package and returns a dial // option to configure a shared buffer pool for a grpc.ClientConn. - WithRecvBufferPool any // func (grpc.SharedBufferPool) grpc.DialOption + WithBufferPool any // func (grpc.SharedBufferPool) grpc.DialOption - // RecvBufferPool is implemented by the grpc package and returns a server + // BufferPool is implemented by the grpc package and returns a server // option to configure a shared buffer pool for a grpc.Server. - RecvBufferPool any // func (grpc.SharedBufferPool) grpc.ServerOption + BufferPool any // func (grpc.SharedBufferPool) grpc.ServerOption ) diff --git a/vendor/google.golang.org/grpc/internal/grpclog/prefixLogger.go b/vendor/google.golang.org/grpc/internal/grpclog/prefix_logger.go similarity index 63% rename from vendor/google.golang.org/grpc/internal/grpclog/prefixLogger.go rename to vendor/google.golang.org/grpc/internal/grpclog/prefix_logger.go index faa998de7..092ad187a 100644 --- a/vendor/google.golang.org/grpc/internal/grpclog/prefixLogger.go +++ b/vendor/google.golang.org/grpc/internal/grpclog/prefix_logger.go @@ -16,17 +16,21 @@ * */ +// Package grpclog provides logging functionality for internal gRPC packages, +// outside of the functionality provided by the external `grpclog` package. package grpclog import ( "fmt" + + "google.golang.org/grpc/grpclog" ) // PrefixLogger does logging with a prefix. // // Logging method on a nil logs without any prefix. type PrefixLogger struct { - logger DepthLoggerV2 + logger grpclog.DepthLoggerV2 prefix string } @@ -38,7 +42,7 @@ func (pl *PrefixLogger) Infof(format string, args ...any) { pl.logger.InfoDepth(1, fmt.Sprintf(format, args...)) return } - InfoDepth(1, fmt.Sprintf(format, args...)) + grpclog.InfoDepth(1, fmt.Sprintf(format, args...)) } // Warningf does warning logging. @@ -48,7 +52,7 @@ func (pl *PrefixLogger) Warningf(format string, args ...any) { pl.logger.WarningDepth(1, fmt.Sprintf(format, args...)) return } - WarningDepth(1, fmt.Sprintf(format, args...)) + grpclog.WarningDepth(1, fmt.Sprintf(format, args...)) } // Errorf does error logging. @@ -58,36 +62,18 @@ func (pl *PrefixLogger) Errorf(format string, args ...any) { pl.logger.ErrorDepth(1, fmt.Sprintf(format, args...)) return } - ErrorDepth(1, fmt.Sprintf(format, args...)) -} - -// Debugf does info logging at verbose level 2. -func (pl *PrefixLogger) Debugf(format string, args ...any) { - // TODO(6044): Refactor interfaces LoggerV2 and DepthLogger, and maybe - // rewrite PrefixLogger a little to ensure that we don't use the global - // `Logger` here, and instead use the `logger` field. - if !Logger.V(2) { - return - } - if pl != nil { - // Handle nil, so the tests can pass in a nil logger. - format = pl.prefix + format - pl.logger.InfoDepth(1, fmt.Sprintf(format, args...)) - return - } - InfoDepth(1, fmt.Sprintf(format, args...)) - + grpclog.ErrorDepth(1, fmt.Sprintf(format, args...)) } // V reports whether verbosity level l is at least the requested verbose level. func (pl *PrefixLogger) V(l int) bool { - // TODO(6044): Refactor interfaces LoggerV2 and DepthLogger, and maybe - // rewrite PrefixLogger a little to ensure that we don't use the global - // `Logger` here, and instead use the `logger` field. - return Logger.V(l) + if pl != nil { + return pl.logger.V(l) + } + return true } // NewPrefixLogger creates a prefix logger with the given prefix. -func NewPrefixLogger(logger DepthLoggerV2, prefix string) *PrefixLogger { +func NewPrefixLogger(logger grpclog.DepthLoggerV2, prefix string) *PrefixLogger { return &PrefixLogger{logger: logger, prefix: prefix} } diff --git a/vendor/google.golang.org/grpc/internal/grpcrand/grpcrand.go b/vendor/google.golang.org/grpc/internal/grpcrand/grpcrand.go deleted file mode 100644 index 0126d6b51..000000000 --- a/vendor/google.golang.org/grpc/internal/grpcrand/grpcrand.go +++ /dev/null @@ -1,100 +0,0 @@ -//go:build !go1.21 - -// TODO: when this file is deleted (after Go 1.20 support is dropped), delete -// all of grpcrand and call the rand package directly. - -/* - * - * Copyright 2018 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. - * - */ - -// Package grpcrand implements math/rand functions in a concurrent-safe way -// with a global random source, independent of math/rand's global source. -package grpcrand - -import ( - "math/rand" - "sync" - "time" -) - -var ( - r = rand.New(rand.NewSource(time.Now().UnixNano())) - mu sync.Mutex -) - -// Int implements rand.Int on the grpcrand global source. -func Int() int { - mu.Lock() - defer mu.Unlock() - return r.Int() -} - -// Int63n implements rand.Int63n on the grpcrand global source. -func Int63n(n int64) int64 { - mu.Lock() - defer mu.Unlock() - return r.Int63n(n) -} - -// Intn implements rand.Intn on the grpcrand global source. -func Intn(n int) int { - mu.Lock() - defer mu.Unlock() - return r.Intn(n) -} - -// Int31n implements rand.Int31n on the grpcrand global source. -func Int31n(n int32) int32 { - mu.Lock() - defer mu.Unlock() - return r.Int31n(n) -} - -// Float64 implements rand.Float64 on the grpcrand global source. -func Float64() float64 { - mu.Lock() - defer mu.Unlock() - return r.Float64() -} - -// Uint64 implements rand.Uint64 on the grpcrand global source. -func Uint64() uint64 { - mu.Lock() - defer mu.Unlock() - return r.Uint64() -} - -// Uint32 implements rand.Uint32 on the grpcrand global source. -func Uint32() uint32 { - mu.Lock() - defer mu.Unlock() - return r.Uint32() -} - -// ExpFloat64 implements rand.ExpFloat64 on the grpcrand global source. -func ExpFloat64() float64 { - mu.Lock() - defer mu.Unlock() - return r.ExpFloat64() -} - -// Shuffle implements rand.Shuffle on the grpcrand global source. -var Shuffle = func(n int, f func(int, int)) { - mu.Lock() - defer mu.Unlock() - r.Shuffle(n, f) -} diff --git a/vendor/google.golang.org/grpc/internal/grpcrand/grpcrand_go1.21.go b/vendor/google.golang.org/grpc/internal/grpcrand/grpcrand_go1.21.go deleted file mode 100644 index c37299af1..000000000 --- a/vendor/google.golang.org/grpc/internal/grpcrand/grpcrand_go1.21.go +++ /dev/null @@ -1,73 +0,0 @@ -//go:build go1.21 - -/* - * - * Copyright 2024 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. - * - */ - -// Package grpcrand implements math/rand functions in a concurrent-safe way -// with a global random source, independent of math/rand's global source. -package grpcrand - -import "math/rand" - -// This implementation will be used for Go version 1.21 or newer. -// For older versions, the original implementation with mutex will be used. - -// Int implements rand.Int on the grpcrand global source. -func Int() int { - return rand.Int() -} - -// Int63n implements rand.Int63n on the grpcrand global source. -func Int63n(n int64) int64 { - return rand.Int63n(n) -} - -// Intn implements rand.Intn on the grpcrand global source. -func Intn(n int) int { - return rand.Intn(n) -} - -// Int31n implements rand.Int31n on the grpcrand global source. -func Int31n(n int32) int32 { - return rand.Int31n(n) -} - -// Float64 implements rand.Float64 on the grpcrand global source. -func Float64() float64 { - return rand.Float64() -} - -// Uint64 implements rand.Uint64 on the grpcrand global source. -func Uint64() uint64 { - return rand.Uint64() -} - -// Uint32 implements rand.Uint32 on the grpcrand global source. -func Uint32() uint32 { - return rand.Uint32() -} - -// ExpFloat64 implements rand.ExpFloat64 on the grpcrand global source. -func ExpFloat64() float64 { - return rand.ExpFloat64() -} - -// Shuffle implements rand.Shuffle on the grpcrand global source. -var Shuffle = func(n int, f func(int, int)) { - rand.Shuffle(n, f) -} diff --git a/vendor/google.golang.org/grpc/internal/grpcsync/callback_serializer.go b/vendor/google.golang.org/grpc/internal/grpcsync/callback_serializer.go index f7f40a16a..8e8e86128 100644 --- a/vendor/google.golang.org/grpc/internal/grpcsync/callback_serializer.go +++ b/vendor/google.golang.org/grpc/internal/grpcsync/callback_serializer.go @@ -53,16 +53,28 @@ func NewCallbackSerializer(ctx context.Context) *CallbackSerializer { return cs } -// Schedule adds a callback to be scheduled after existing callbacks are run. +// TrySchedule tries to schedule the provided callback function f to be +// executed in the order it was added. This is a best-effort operation. If the +// context passed to NewCallbackSerializer was canceled before this method is +// called, the callback will not be scheduled. // // Callbacks are expected to honor the context when performing any blocking // operations, and should return early when the context is canceled. +func (cs *CallbackSerializer) TrySchedule(f func(ctx context.Context)) { + cs.callbacks.Put(f) +} + +// ScheduleOr schedules the provided callback function f to be executed in the +// order it was added. If the context passed to NewCallbackSerializer has been +// canceled before this method is called, the onFailure callback will be +// executed inline instead. // -// Return value indicates if the callback was successfully added to the list of -// callbacks to be executed by the serializer. It is not possible to add -// callbacks once the context passed to NewCallbackSerializer is cancelled. -func (cs *CallbackSerializer) Schedule(f func(ctx context.Context)) bool { - return cs.callbacks.Put(f) == nil +// Callbacks are expected to honor the context when performing any blocking +// operations, and should return early when the context is canceled. +func (cs *CallbackSerializer) ScheduleOr(f func(ctx context.Context), onFailure func()) { + if cs.callbacks.Put(f) != nil { + onFailure() + } } func (cs *CallbackSerializer) run(ctx context.Context) { diff --git a/vendor/google.golang.org/grpc/internal/grpcsync/pubsub.go b/vendor/google.golang.org/grpc/internal/grpcsync/pubsub.go index aef8cec1a..6d8c2f518 100644 --- a/vendor/google.golang.org/grpc/internal/grpcsync/pubsub.go +++ b/vendor/google.golang.org/grpc/internal/grpcsync/pubsub.go @@ -77,7 +77,7 @@ func (ps *PubSub) Subscribe(sub Subscriber) (cancel func()) { if ps.msg != nil { msg := ps.msg - ps.cs.Schedule(func(context.Context) { + ps.cs.TrySchedule(func(context.Context) { ps.mu.Lock() defer ps.mu.Unlock() if !ps.subscribers[sub] { @@ -103,7 +103,7 @@ func (ps *PubSub) Publish(msg any) { ps.msg = msg for sub := range ps.subscribers { s := sub - ps.cs.Schedule(func(context.Context) { + ps.cs.TrySchedule(func(context.Context) { ps.mu.Lock() defer ps.mu.Unlock() if !ps.subscribers[s] { diff --git a/vendor/google.golang.org/grpc/internal/grpcutil/compressor.go b/vendor/google.golang.org/grpc/internal/grpcutil/compressor.go index 9f4090967..e8d866984 100644 --- a/vendor/google.golang.org/grpc/internal/grpcutil/compressor.go +++ b/vendor/google.golang.org/grpc/internal/grpcutil/compressor.go @@ -20,8 +20,6 @@ package grpcutil import ( "strings" - - "google.golang.org/grpc/internal/envconfig" ) // RegisteredCompressorNames holds names of the registered compressors. @@ -40,8 +38,5 @@ func IsCompressorNameRegistered(name string) bool { // RegisteredCompressors returns a string of registered compressor names // separated by comma. func RegisteredCompressors() string { - if !envconfig.AdvertiseCompressors { - return "" - } return strings.Join(RegisteredCompressorNames, ",") } diff --git a/vendor/google.golang.org/grpc/internal/grpcutil/method.go b/vendor/google.golang.org/grpc/internal/grpcutil/method.go index ec62b4775..683d1955c 100644 --- a/vendor/google.golang.org/grpc/internal/grpcutil/method.go +++ b/vendor/google.golang.org/grpc/internal/grpcutil/method.go @@ -39,7 +39,7 @@ func ParseMethod(methodName string) (service, method string, _ error) { } // baseContentType is the base content-type for gRPC. This is a valid -// content-type on it's own, but can also include a content-subtype such as +// content-type on its own, but can also include a content-subtype such as // "proto" as a suffix after "+" or ";". See // https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md#requests // for more details. diff --git a/vendor/google.golang.org/grpc/internal/idle/idle.go b/vendor/google.golang.org/grpc/internal/idle/idle.go index fe49cb74c..2c13ee9da 100644 --- a/vendor/google.golang.org/grpc/internal/idle/idle.go +++ b/vendor/google.golang.org/grpc/internal/idle/idle.go @@ -182,6 +182,7 @@ func (m *Manager) tryEnterIdleMode() bool { return true } +// EnterIdleModeForTesting instructs the channel to enter idle mode. func (m *Manager) EnterIdleModeForTesting() { m.tryEnterIdleMode() } @@ -225,7 +226,7 @@ func (m *Manager) ExitIdleMode() error { // came in and OnCallBegin() noticed that the calls count is negative. // - Channel is in idle mode, and multiple new RPCs come in at the same // time, all of them notice a negative calls count in OnCallBegin and get - // here. The first one to get the lock would got the channel to exit idle. + // here. The first one to get the lock would get the channel to exit idle. // - Channel is not in idle mode, and the user calls Connect which calls // m.ExitIdleMode. // @@ -266,6 +267,7 @@ func (m *Manager) isClosed() bool { return atomic.LoadInt32(&m.closed) == 1 } +// Close stops the timer associated with the Manager, if it exists. func (m *Manager) Close() { atomic.StoreInt32(&m.closed, 1) diff --git a/vendor/google.golang.org/grpc/internal/internal.go b/vendor/google.golang.org/grpc/internal/internal.go index 48d24bdb4..20b4dc3d3 100644 --- a/vendor/google.golang.org/grpc/internal/internal.go +++ b/vendor/google.golang.org/grpc/internal/internal.go @@ -106,6 +106,14 @@ var ( // This is used in the 1.0 release of gcp/observability, and thus must not be // deleted or changed. ClearGlobalDialOptions func() + + // AddGlobalPerTargetDialOptions adds a PerTargetDialOption that will be + // configured for newly created ClientConns. + AddGlobalPerTargetDialOptions any // func (opt any) + // ClearGlobalPerTargetDialOptions clears the slice of global late apply + // dial options. + ClearGlobalPerTargetDialOptions func() + // JoinDialOptions combines the dial options passed as arguments into a // single dial option. JoinDialOptions any // func(...grpc.DialOption) grpc.DialOption @@ -126,7 +134,8 @@ var ( // deleted or changed. BinaryLogger any // func(binarylog.Logger) grpc.ServerOption - // SubscribeToConnectivityStateChanges adds a grpcsync.Subscriber to a provided grpc.ClientConn + // SubscribeToConnectivityStateChanges adds a grpcsync.Subscriber to a + // provided grpc.ClientConn. SubscribeToConnectivityStateChanges any // func(*grpc.ClientConn, grpcsync.Subscriber) // NewXDSResolverWithConfigForTesting creates a new xds resolver builder using @@ -174,7 +183,7 @@ var ( // GRPCResolverSchemeExtraMetadata determines when gRPC will add extra // metadata to RPCs. - GRPCResolverSchemeExtraMetadata string = "xds" + GRPCResolverSchemeExtraMetadata = "xds" // EnterIdleModeForTesting gets the ClientConn to enter IDLE mode. EnterIdleModeForTesting any // func(*grpc.ClientConn) @@ -182,31 +191,49 @@ var ( // ExitIdleModeForTesting gets the ClientConn to exit IDLE mode. ExitIdleModeForTesting any // func(*grpc.ClientConn) error + // ChannelzTurnOffForTesting disables the Channelz service for testing + // purposes. ChannelzTurnOffForTesting func() - // TriggerXDSResourceNameNotFoundForTesting triggers the resource-not-found - // error for a given resource type and name. This is usually triggered when - // the associated watch timer fires. For testing purposes, having this - // function makes events more predictable than relying on timer events. - TriggerXDSResourceNameNotFoundForTesting any // func(func(xdsresource.Type, string), string, string) error + // TriggerXDSResourceNotFoundForTesting causes the provided xDS Client to + // invoke resource-not-found error for the given resource type and name. + TriggerXDSResourceNotFoundForTesting any // func(xdsclient.XDSClient, xdsresource.Type, string) error - // TriggerXDSResourceNameNotFoundClient invokes the testing xDS Client - // singleton to invoke resource not found for a resource type name and - // resource name. - TriggerXDSResourceNameNotFoundClient any // func(string, string) error - - // FromOutgoingContextRaw returns the un-merged, intermediary contents of metadata.rawMD. + // FromOutgoingContextRaw returns the un-merged, intermediary contents of + // metadata.rawMD. FromOutgoingContextRaw any // func(context.Context) (metadata.MD, [][]string, bool) - // UserSetDefaultScheme is set to true if the user has overridden the default resolver scheme. - UserSetDefaultScheme bool = false + // UserSetDefaultScheme is set to true if the user has overridden the + // default resolver scheme. + UserSetDefaultScheme = false + + // ConnectedAddress returns the connected address for a SubConnState. The + // address is only valid if the state is READY. + ConnectedAddress any // func (scs SubConnState) resolver.Address + + // SetConnectedAddress sets the connected address for a SubConnState. + SetConnectedAddress any // func(scs *SubConnState, addr resolver.Address) + + // SnapshotMetricRegistryForTesting snapshots the global data of the metric + // registry. Returns a cleanup function that sets the metric registry to its + // original state. Only called in testing functions. + SnapshotMetricRegistryForTesting func() func() + + // SetDefaultBufferPoolForTesting updates the default buffer pool, for + // testing purposes. + SetDefaultBufferPoolForTesting any // func(mem.BufferPool) + + // SetBufferPoolingThresholdForTesting updates the buffer pooling threshold, for + // testing purposes. + SetBufferPoolingThresholdForTesting any // func(int) ) -// HealthChecker defines the signature of the client-side LB channel health checking function. +// HealthChecker defines the signature of the client-side LB channel health +// checking function. // // The implementation is expected to create a health checking RPC stream by // calling newStream(), watch for the health status of serviceName, and report -// it's health back by calling setConnectivityState(). +// its health back by calling setConnectivityState(). // // The health checking protocol is defined at: // https://github.com/grpc/grpc/blob/master/doc/health-checking.md diff --git a/vendor/google.golang.org/grpc/internal/resolver/dns/dns_resolver.go b/vendor/google.golang.org/grpc/internal/resolver/dns/dns_resolver.go index abab35e25..8691698ef 100644 --- a/vendor/google.golang.org/grpc/internal/resolver/dns/dns_resolver.go +++ b/vendor/google.golang.org/grpc/internal/resolver/dns/dns_resolver.go @@ -24,6 +24,7 @@ import ( "context" "encoding/json" "fmt" + "math/rand" "net" "os" "strconv" @@ -35,28 +36,35 @@ import ( "google.golang.org/grpc/grpclog" "google.golang.org/grpc/internal/backoff" "google.golang.org/grpc/internal/envconfig" - "google.golang.org/grpc/internal/grpcrand" "google.golang.org/grpc/internal/resolver/dns/internal" "google.golang.org/grpc/resolver" "google.golang.org/grpc/serviceconfig" ) -// EnableSRVLookups controls whether the DNS resolver attempts to fetch gRPCLB -// addresses from SRV records. Must not be changed after init time. -var EnableSRVLookups = false +var ( + // EnableSRVLookups controls whether the DNS resolver attempts to fetch gRPCLB + // addresses from SRV records. Must not be changed after init time. + EnableSRVLookups = false -// ResolvingTimeout specifies the maximum duration for a DNS resolution request. -// If the timeout expires before a response is received, the request will be canceled. -// -// It is recommended to set this value at application startup. Avoid modifying this variable -// after initialization as it's not thread-safe for concurrent modification. -var ResolvingTimeout = 30 * time.Second + // MinResolutionInterval is the minimum interval at which re-resolutions are + // allowed. This helps to prevent excessive re-resolution. + MinResolutionInterval = 30 * time.Second -var logger = grpclog.Component("dns") + // ResolvingTimeout specifies the maximum duration for a DNS resolution request. + // If the timeout expires before a response is received, the request will be canceled. + // + // It is recommended to set this value at application startup. Avoid modifying this variable + // after initialization as it's not thread-safe for concurrent modification. + ResolvingTimeout = 30 * time.Second + + logger = grpclog.Component("dns") +) func init() { resolver.Register(NewBuilder()) internal.TimeAfterFunc = time.After + internal.TimeNowFunc = time.Now + internal.TimeUntilFunc = time.Until internal.NewNetResolver = newNetResolver internal.AddressDialer = addressDialer } @@ -169,7 +177,7 @@ type dnsResolver struct { // finished. Otherwise, data race will be possible. [Race Example] in // dns_resolver_test we replace the real lookup functions with mocked ones to // facilitate testing. If Close() doesn't wait for watcher() goroutine - // finishes, race detector sometimes will warns lookup (READ the lookup + // finishes, race detector sometimes will warn lookup (READ the lookup // function pointers) inside watcher() goroutine has data race with // replaceNetFunc (WRITE the lookup function pointers). wg sync.WaitGroup @@ -203,12 +211,12 @@ func (d *dnsResolver) watcher() { err = d.cc.UpdateState(*state) } - var waitTime time.Duration + var nextResolutionTime time.Time if err == nil { // Success resolving, wait for the next ResolveNow. However, also wait 30 // seconds at the very least to prevent constantly re-resolving. backoffIndex = 1 - waitTime = internal.MinResolutionRate + nextResolutionTime = internal.TimeNowFunc().Add(MinResolutionInterval) select { case <-d.ctx.Done(): return @@ -217,13 +225,13 @@ func (d *dnsResolver) watcher() { } else { // Poll on an error found in DNS Resolver or an error received from // ClientConn. - waitTime = backoff.DefaultExponential.Backoff(backoffIndex) + nextResolutionTime = internal.TimeNowFunc().Add(backoff.DefaultExponential.Backoff(backoffIndex)) backoffIndex++ } select { case <-d.ctx.Done(): return - case <-internal.TimeAfterFunc(waitTime): + case <-internal.TimeAfterFunc(internal.TimeUntilFunc(nextResolutionTime)): } } } @@ -417,7 +425,7 @@ func chosenByPercentage(a *int) bool { if a == nil { return true } - return grpcrand.Intn(100)+1 <= *a + return rand.Intn(100)+1 <= *a } func canaryingSC(js string) string { diff --git a/vendor/google.golang.org/grpc/internal/resolver/dns/internal/internal.go b/vendor/google.golang.org/grpc/internal/resolver/dns/internal/internal.go index c7fc557d0..c0eae4f5f 100644 --- a/vendor/google.golang.org/grpc/internal/resolver/dns/internal/internal.go +++ b/vendor/google.golang.org/grpc/internal/resolver/dns/internal/internal.go @@ -28,7 +28,7 @@ import ( // NetResolver groups the methods on net.Resolver that are used by the DNS // resolver implementation. This allows the default net.Resolver instance to be -// overidden from tests. +// overridden from tests. type NetResolver interface { LookupHost(ctx context.Context, host string) (addrs []string, err error) LookupSRV(ctx context.Context, service, proto, name string) (cname string, addrs []*net.SRV, err error) @@ -50,16 +50,23 @@ var ( // The following vars are overridden from tests. var ( - // MinResolutionRate is the minimum rate at which re-resolutions are - // allowed. This helps to prevent excessive re-resolution. - MinResolutionRate = 30 * time.Second - // TimeAfterFunc is used by the DNS resolver to wait for the given duration - // to elapse. In non-test code, this is implemented by time.After. In test + // to elapse. In non-test code, this is implemented by time.After. In test // code, this can be used to control the amount of time the resolver is // blocked waiting for the duration to elapse. TimeAfterFunc func(time.Duration) <-chan time.Time + // TimeNowFunc is used by the DNS resolver to get the current time. + // In non-test code, this is implemented by time.Now. In test code, + // this can be used to control the current time for the resolver. + TimeNowFunc func() time.Time + + // TimeUntilFunc is used by the DNS resolver to calculate the remaining + // wait time for re-resolution. In non-test code, this is implemented by + // time.Until. In test code, this can be used to control the remaining + // time for resolver to wait for re-resolution. + TimeUntilFunc func(time.Time) time.Duration + // NewNetResolver returns the net.Resolver instance for the given target. NewNetResolver func(string) (NetResolver, error) diff --git a/vendor/google.golang.org/grpc/internal/resolver/passthrough/passthrough.go b/vendor/google.golang.org/grpc/internal/resolver/passthrough/passthrough.go index afac56572..b901c7bac 100644 --- a/vendor/google.golang.org/grpc/internal/resolver/passthrough/passthrough.go +++ b/vendor/google.golang.org/grpc/internal/resolver/passthrough/passthrough.go @@ -55,7 +55,7 @@ func (r *passthroughResolver) start() { r.cc.UpdateState(resolver.State{Addresses: []resolver.Address{{Addr: r.target.Endpoint()}}}) } -func (*passthroughResolver) ResolveNow(o resolver.ResolveNowOptions) {} +func (*passthroughResolver) ResolveNow(resolver.ResolveNowOptions) {} func (*passthroughResolver) Close() {} diff --git a/vendor/google.golang.org/grpc/internal/stats/labels.go b/vendor/google.golang.org/grpc/internal/stats/labels.go new file mode 100644 index 000000000..fd33af51a --- /dev/null +++ b/vendor/google.golang.org/grpc/internal/stats/labels.go @@ -0,0 +1,42 @@ +/* + * + * Copyright 2024 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. + * + */ + +// Package stats provides internal stats related functionality. +package stats + +import "context" + +// Labels are the labels for metrics. +type Labels struct { + // TelemetryLabels are the telemetry labels to record. + TelemetryLabels map[string]string +} + +type labelsKey struct{} + +// GetLabels returns the Labels stored in the context, or nil if there is one. +func GetLabels(ctx context.Context) *Labels { + labels, _ := ctx.Value(labelsKey{}).(*Labels) + return labels +} + +// SetLabels sets the Labels in the context. +func SetLabels(ctx context.Context, labels *Labels) context.Context { + // could also append + return context.WithValue(ctx, labelsKey{}, labels) +} diff --git a/vendor/google.golang.org/grpc/internal/stats/metrics_recorder_list.go b/vendor/google.golang.org/grpc/internal/stats/metrics_recorder_list.go new file mode 100644 index 000000000..79044657b --- /dev/null +++ b/vendor/google.golang.org/grpc/internal/stats/metrics_recorder_list.go @@ -0,0 +1,105 @@ +/* + * Copyright 2024 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. + */ + +package stats + +import ( + "fmt" + + estats "google.golang.org/grpc/experimental/stats" + "google.golang.org/grpc/stats" +) + +// MetricsRecorderList forwards Record calls to all of its metricsRecorders. +// +// It eats any record calls where the label values provided do not match the +// number of label keys. +type MetricsRecorderList struct { + // metricsRecorders are the metrics recorders this list will forward to. + metricsRecorders []estats.MetricsRecorder +} + +// NewMetricsRecorderList creates a new metric recorder list with all the stats +// handlers provided which implement the MetricsRecorder interface. +// If no stats handlers provided implement the MetricsRecorder interface, +// the MetricsRecorder list returned is a no-op. +func NewMetricsRecorderList(shs []stats.Handler) *MetricsRecorderList { + var mrs []estats.MetricsRecorder + for _, sh := range shs { + if mr, ok := sh.(estats.MetricsRecorder); ok { + mrs = append(mrs, mr) + } + } + return &MetricsRecorderList{ + metricsRecorders: mrs, + } +} + +func verifyLabels(desc *estats.MetricDescriptor, labelsRecv ...string) { + if got, want := len(labelsRecv), len(desc.Labels)+len(desc.OptionalLabels); got != want { + panic(fmt.Sprintf("Received %d labels in call to record metric %q, but expected %d.", got, desc.Name, want)) + } +} + +// RecordInt64Count records the measurement alongside labels on the int +// count associated with the provided handle. +func (l *MetricsRecorderList) RecordInt64Count(handle *estats.Int64CountHandle, incr int64, labels ...string) { + verifyLabels(handle.Descriptor(), labels...) + + for _, metricRecorder := range l.metricsRecorders { + metricRecorder.RecordInt64Count(handle, incr, labels...) + } +} + +// RecordFloat64Count records the measurement alongside labels on the float +// count associated with the provided handle. +func (l *MetricsRecorderList) RecordFloat64Count(handle *estats.Float64CountHandle, incr float64, labels ...string) { + verifyLabels(handle.Descriptor(), labels...) + + for _, metricRecorder := range l.metricsRecorders { + metricRecorder.RecordFloat64Count(handle, incr, labels...) + } +} + +// RecordInt64Histo records the measurement alongside labels on the int +// histo associated with the provided handle. +func (l *MetricsRecorderList) RecordInt64Histo(handle *estats.Int64HistoHandle, incr int64, labels ...string) { + verifyLabels(handle.Descriptor(), labels...) + + for _, metricRecorder := range l.metricsRecorders { + metricRecorder.RecordInt64Histo(handle, incr, labels...) + } +} + +// RecordFloat64Histo records the measurement alongside labels on the float +// histo associated with the provided handle. +func (l *MetricsRecorderList) RecordFloat64Histo(handle *estats.Float64HistoHandle, incr float64, labels ...string) { + verifyLabels(handle.Descriptor(), labels...) + + for _, metricRecorder := range l.metricsRecorders { + metricRecorder.RecordFloat64Histo(handle, incr, labels...) + } +} + +// RecordInt64Gauge records the measurement alongside labels on the int +// gauge associated with the provided handle. +func (l *MetricsRecorderList) RecordInt64Gauge(handle *estats.Int64GaugeHandle, incr int64, labels ...string) { + verifyLabels(handle.Descriptor(), labels...) + + for _, metricRecorder := range l.metricsRecorders { + metricRecorder.RecordInt64Gauge(handle, incr, labels...) + } +} diff --git a/vendor/google.golang.org/grpc/internal/status/status.go b/vendor/google.golang.org/grpc/internal/status/status.go index c7dbc8205..1186f1e9a 100644 --- a/vendor/google.golang.org/grpc/internal/status/status.go +++ b/vendor/google.golang.org/grpc/internal/status/status.go @@ -138,17 +138,19 @@ func (s *Status) WithDetails(details ...protoadapt.MessageV1) (*Status, error) { // s.Code() != OK implies that s.Proto() != nil. p := s.Proto() for _, detail := range details { - any, err := anypb.New(protoadapt.MessageV2Of(detail)) + m, err := anypb.New(protoadapt.MessageV2Of(detail)) if err != nil { return nil, err } - p.Details = append(p.Details, any) + p.Details = append(p.Details, m) } return &Status{s: p}, nil } // Details returns a slice of details messages attached to the status. // If a detail cannot be decoded, the error is returned in place of the detail. +// If the detail can be decoded, the proto message returned is of the same +// type that was given to WithDetails(). func (s *Status) Details() []any { if s == nil || s.s == nil { return nil @@ -160,7 +162,38 @@ func (s *Status) Details() []any { details = append(details, err) continue } - details = append(details, detail) + // The call to MessageV1Of is required to unwrap the proto message if + // it implemented only the MessageV1 API. The proto message would have + // been wrapped in a V2 wrapper in Status.WithDetails. V2 messages are + // added to a global registry used by any.UnmarshalNew(). + // MessageV1Of has the following behaviour: + // 1. If the given message is a wrapped MessageV1, it returns the + // unwrapped value. + // 2. If the given message already implements MessageV1, it returns it + // as is. + // 3. Else, it wraps the MessageV2 in a MessageV1 wrapper. + // + // Since the Status.WithDetails() API only accepts MessageV1, calling + // MessageV1Of ensures we return the same type that was given to + // WithDetails: + // * If the give type implemented only MessageV1, the unwrapping from + // point 1 above will restore the type. + // * If the given type implemented both MessageV1 and MessageV2, point 2 + // above will ensure no wrapping is performed. + // * If the given type implemented only MessageV2 and was wrapped using + // MessageV1Of before passing to WithDetails(), it would be unwrapped + // in WithDetails by calling MessageV2Of(). Point 3 above will ensure + // that the type is wrapped in a MessageV1 wrapper again before + // returning. Note that protoc-gen-go doesn't generate code which + // implements ONLY MessageV2 at the time of writing. + // + // NOTE: Status details can also be added using the FromProto method. + // This could theoretically allow passing a Detail message that only + // implements the V2 API. In such a case the message will be wrapped in + // a MessageV1 wrapper when fetched using Details(). + // Since protoc-gen-go generates only code that implements both V1 and + // V2 APIs for backward compatibility, this is not a concern. + details = append(details, protoadapt.MessageV1Of(detail)) } return details } diff --git a/vendor/google.golang.org/grpc/internal/syscall/syscall_nonlinux.go b/vendor/google.golang.org/grpc/internal/syscall/syscall_nonlinux.go index 999f52cd7..54c24c2ff 100644 --- a/vendor/google.golang.org/grpc/internal/syscall/syscall_nonlinux.go +++ b/vendor/google.golang.org/grpc/internal/syscall/syscall_nonlinux.go @@ -58,20 +58,20 @@ func GetRusage() *Rusage { // CPUTimeDiff returns the differences of user CPU time and system CPU time used // between two Rusage structs. It a no-op function for non-linux environments. -func CPUTimeDiff(first *Rusage, latest *Rusage) (float64, float64) { +func CPUTimeDiff(*Rusage, *Rusage) (float64, float64) { log() return 0, 0 } // SetTCPUserTimeout is a no-op function under non-linux environments. -func SetTCPUserTimeout(conn net.Conn, timeout time.Duration) error { +func SetTCPUserTimeout(net.Conn, time.Duration) error { log() return nil } // GetTCPUserTimeout is a no-op function under non-linux environments. // A negative return value indicates the operation is not supported -func GetTCPUserTimeout(conn net.Conn) (int, error) { +func GetTCPUserTimeout(net.Conn) (int, error) { log() return -1, nil } diff --git a/vendor/google.golang.org/grpc/internal/tcp_keepalive_unix.go b/vendor/google.golang.org/grpc/internal/tcp_keepalive_unix.go index 078137b7f..7e7aaa546 100644 --- a/vendor/google.golang.org/grpc/internal/tcp_keepalive_unix.go +++ b/vendor/google.golang.org/grpc/internal/tcp_keepalive_unix.go @@ -44,7 +44,7 @@ func NetDialerWithTCPKeepalive() *net.Dialer { // combination of unconditionally enabling TCP keepalives here, and // disabling the overriding of TCP keepalive parameters by setting the // KeepAlive field to a negative value above, results in OS defaults for - // the TCP keealive interval and time parameters. + // the TCP keepalive interval and time parameters. Control: func(_, _ string, c syscall.RawConn) error { return c.Control(func(fd uintptr) { unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_KEEPALIVE, 1) diff --git a/vendor/google.golang.org/grpc/internal/tcp_keepalive_windows.go b/vendor/google.golang.org/grpc/internal/tcp_keepalive_windows.go index fd7d43a89..d5c1085ee 100644 --- a/vendor/google.golang.org/grpc/internal/tcp_keepalive_windows.go +++ b/vendor/google.golang.org/grpc/internal/tcp_keepalive_windows.go @@ -44,7 +44,7 @@ func NetDialerWithTCPKeepalive() *net.Dialer { // combination of unconditionally enabling TCP keepalives here, and // disabling the overriding of TCP keepalive parameters by setting the // KeepAlive field to a negative value above, results in OS defaults for - // the TCP keealive interval and time parameters. + // the TCP keepalive interval and time parameters. Control: func(_, _ string, c syscall.RawConn) error { return c.Control(func(fd uintptr) { windows.SetsockoptInt(windows.Handle(fd), windows.SOL_SOCKET, windows.SO_KEEPALIVE, 1) diff --git a/vendor/google.golang.org/grpc/internal/transport/controlbuf.go b/vendor/google.golang.org/grpc/internal/transport/controlbuf.go index 83c382982..ef72fbb3a 100644 --- a/vendor/google.golang.org/grpc/internal/transport/controlbuf.go +++ b/vendor/google.golang.org/grpc/internal/transport/controlbuf.go @@ -32,6 +32,7 @@ import ( "golang.org/x/net/http2/hpack" "google.golang.org/grpc/internal/grpclog" "google.golang.org/grpc/internal/grpcutil" + "google.golang.org/grpc/mem" "google.golang.org/grpc/status" ) @@ -148,9 +149,9 @@ type dataFrame struct { streamID uint32 endStream bool h []byte - d []byte + reader mem.Reader // onEachWrite is called every time - // a part of d is written out. + // a part of data is written out. onEachWrite func() } @@ -193,7 +194,7 @@ type goAway struct { code http2.ErrCode debugData []byte headsUp bool - closeConn error // if set, loopyWriter will exit, resulting in conn closure + closeConn error // if set, loopyWriter will exit with this error } func (*goAway) isTransportResponseFrame() bool { return false } @@ -289,18 +290,22 @@ func (l *outStreamList) dequeue() *outStream { } // controlBuffer is a way to pass information to loopy. -// Information is passed as specific struct types called control frames. -// A control frame not only represents data, messages or headers to be sent out -// but can also be used to instruct loopy to update its internal state. -// It shouldn't be confused with an HTTP2 frame, although some of the control frames -// like dataFrame and headerFrame do go out on wire as HTTP2 frames. +// +// Information is passed as specific struct types called control frames. A +// control frame not only represents data, messages or headers to be sent out +// but can also be used to instruct loopy to update its internal state. It +// shouldn't be confused with an HTTP2 frame, although some of the control +// frames like dataFrame and headerFrame do go out on wire as HTTP2 frames. type controlBuffer struct { - ch chan struct{} - done <-chan struct{} + wakeupCh chan struct{} // Unblocks readers waiting for something to read. + done <-chan struct{} // Closed when the transport is done. + + // Mutex guards all the fields below, except trfChan which can be read + // atomically without holding mu. mu sync.Mutex - consumerWaiting bool - list *itemList - err error + consumerWaiting bool // True when readers are blocked waiting for new data. + closed bool // True when the controlbuf is finished. + list *itemList // List of queued control frames. // transportResponseFrames counts the number of queued items that represent // the response of an action initiated by the peer. trfChan is created @@ -308,47 +313,59 @@ type controlBuffer struct { // closed and nilled when transportResponseFrames drops below the // threshold. Both fields are protected by mu. transportResponseFrames int - trfChan atomic.Value // chan struct{} + trfChan atomic.Pointer[chan struct{}] } func newControlBuffer(done <-chan struct{}) *controlBuffer { return &controlBuffer{ - ch: make(chan struct{}, 1), - list: &itemList{}, - done: done, + wakeupCh: make(chan struct{}, 1), + list: &itemList{}, + done: done, } } -// throttle blocks if there are too many incomingSettings/cleanupStreams in the -// controlbuf. +// throttle blocks if there are too many frames in the control buf that +// represent the response of an action initiated by the peer, like +// incomingSettings cleanupStreams etc. func (c *controlBuffer) throttle() { - ch, _ := c.trfChan.Load().(chan struct{}) - if ch != nil { + if ch := c.trfChan.Load(); ch != nil { select { - case <-ch: + case <-(*ch): case <-c.done: } } } +// put adds an item to the controlbuf. func (c *controlBuffer) put(it cbItem) error { _, err := c.executeAndPut(nil, it) return err } -func (c *controlBuffer) executeAndPut(f func(it any) bool, it cbItem) (bool, error) { - var wakeUp bool +// executeAndPut runs f, and if the return value is true, adds the given item to +// the controlbuf. The item could be nil, in which case, this method simply +// executes f and does not add the item to the controlbuf. +// +// The first return value indicates whether the item was successfully added to +// the control buffer. A non-nil error, specifically ErrConnClosing, is returned +// if the control buffer is already closed. +func (c *controlBuffer) executeAndPut(f func() bool, it cbItem) (bool, error) { c.mu.Lock() - if c.err != nil { - c.mu.Unlock() - return false, c.err + defer c.mu.Unlock() + + if c.closed { + return false, ErrConnClosing } if f != nil { - if !f(it) { // f wasn't successful - c.mu.Unlock() + if !f() { // f wasn't successful return false, nil } } + if it == nil { + return true, nil + } + + var wakeUp bool if c.consumerWaiting { wakeUp = true c.consumerWaiting = false @@ -359,98 +376,102 @@ func (c *controlBuffer) executeAndPut(f func(it any) bool, it cbItem) (bool, err if c.transportResponseFrames == maxQueuedTransportResponseFrames { // We are adding the frame that puts us over the threshold; create // a throttling channel. - c.trfChan.Store(make(chan struct{})) + ch := make(chan struct{}) + c.trfChan.Store(&ch) } } - c.mu.Unlock() if wakeUp { select { - case c.ch <- struct{}{}: + case c.wakeupCh <- struct{}{}: default: } } return true, nil } -// Note argument f should never be nil. -func (c *controlBuffer) execute(f func(it any) bool, it any) (bool, error) { - c.mu.Lock() - if c.err != nil { - c.mu.Unlock() - return false, c.err - } - if !f(it) { // f wasn't successful - c.mu.Unlock() - return false, nil - } - c.mu.Unlock() - return true, nil -} - +// get returns the next control frame from the control buffer. If block is true +// **and** there are no control frames in the control buffer, the call blocks +// until one of the conditions is met: there is a frame to return or the +// transport is closed. func (c *controlBuffer) get(block bool) (any, error) { for { c.mu.Lock() - if c.err != nil { + frame, err := c.getOnceLocked() + if frame != nil || err != nil || !block { + // If we read a frame or an error, we can return to the caller. The + // call to getOnceLocked() returns a nil frame and a nil error if + // there is nothing to read, and in that case, if the caller asked + // us not to block, we can return now as well. c.mu.Unlock() - return nil, c.err - } - if !c.list.isEmpty() { - h := c.list.dequeue().(cbItem) - if h.isTransportResponseFrame() { - if c.transportResponseFrames == maxQueuedTransportResponseFrames { - // We are removing the frame that put us over the - // threshold; close and clear the throttling channel. - ch := c.trfChan.Load().(chan struct{}) - close(ch) - c.trfChan.Store((chan struct{})(nil)) - } - c.transportResponseFrames-- - } - c.mu.Unlock() - return h, nil - } - if !block { - c.mu.Unlock() - return nil, nil + return frame, err } c.consumerWaiting = true c.mu.Unlock() + + // Release the lock above and wait to be woken up. select { - case <-c.ch: + case <-c.wakeupCh: case <-c.done: return nil, errors.New("transport closed by client") } } } +// Callers must not use this method, but should instead use get(). +// +// Caller must hold c.mu. +func (c *controlBuffer) getOnceLocked() (any, error) { + if c.closed { + return false, ErrConnClosing + } + if c.list.isEmpty() { + return nil, nil + } + h := c.list.dequeue().(cbItem) + if h.isTransportResponseFrame() { + if c.transportResponseFrames == maxQueuedTransportResponseFrames { + // We are removing the frame that put us over the + // threshold; close and clear the throttling channel. + ch := c.trfChan.Swap(nil) + close(*ch) + } + c.transportResponseFrames-- + } + return h, nil +} + +// finish closes the control buffer, cleaning up any streams that have queued +// header frames. Once this method returns, no more frames can be added to the +// control buffer, and attempts to do so will return ErrConnClosing. func (c *controlBuffer) finish() { c.mu.Lock() - if c.err != nil { - c.mu.Unlock() + defer c.mu.Unlock() + + if c.closed { return } - c.err = ErrConnClosing + c.closed = true // There may be headers for streams in the control buffer. // These streams need to be cleaned out since the transport // is still not aware of these yet. for head := c.list.dequeueAll(); head != nil; head = head.next { - hdr, ok := head.it.(*headerFrame) - if !ok { - continue - } - if hdr.onOrphaned != nil { // It will be nil on the server-side. - hdr.onOrphaned(ErrConnClosing) + switch v := head.it.(type) { + case *headerFrame: + if v.onOrphaned != nil { // It will be nil on the server-side. + v.onOrphaned(ErrConnClosing) + } + case *dataFrame: + _ = v.reader.Close() } } + // In case throttle() is currently in flight, it needs to be unblocked. // Otherwise, the transport may not close, since the transport is closed by // the reader encountering the connection error. - ch, _ := c.trfChan.Load().(chan struct{}) + ch := c.trfChan.Swap(nil) if ch != nil { - close(ch) + close(*ch) } - c.trfChan.Store((chan struct{})(nil)) - c.mu.Unlock() } type side int @@ -466,7 +487,7 @@ const ( // stream maintains a queue of data frames; as loopy receives data frames // it gets added to the queue of the relevant stream. // Loopy goes over this list of active streams by processing one node every iteration, -// thereby closely resemebling to a round-robin scheduling over all streams. While +// thereby closely resembling a round-robin scheduling over all streams. While // processing a stream, loopy writes out data bytes from this stream capped by the min // of http2MaxFrameLen, connection-level flow control and stream-level flow control. type loopyWriter struct { @@ -490,26 +511,29 @@ type loopyWriter struct { draining bool conn net.Conn logger *grpclog.PrefixLogger + bufferPool mem.BufferPool // Side-specific handlers ssGoAwayHandler func(*goAway) (bool, error) } -func newLoopyWriter(s side, fr *framer, cbuf *controlBuffer, bdpEst *bdpEstimator, conn net.Conn, logger *grpclog.PrefixLogger) *loopyWriter { +func newLoopyWriter(s side, fr *framer, cbuf *controlBuffer, bdpEst *bdpEstimator, conn net.Conn, logger *grpclog.PrefixLogger, goAwayHandler func(*goAway) (bool, error), bufferPool mem.BufferPool) *loopyWriter { var buf bytes.Buffer l := &loopyWriter{ - side: s, - cbuf: cbuf, - sendQuota: defaultWindowSize, - oiws: defaultWindowSize, - estdStreams: make(map[uint32]*outStream), - activeStreams: newOutStreamList(), - framer: fr, - hBuf: &buf, - hEnc: hpack.NewEncoder(&buf), - bdpEst: bdpEst, - conn: conn, - logger: logger, + side: s, + cbuf: cbuf, + sendQuota: defaultWindowSize, + oiws: defaultWindowSize, + estdStreams: make(map[uint32]*outStream), + activeStreams: newOutStreamList(), + framer: fr, + hBuf: &buf, + hEnc: hpack.NewEncoder(&buf), + bdpEst: bdpEst, + conn: conn, + logger: logger, + ssGoAwayHandler: goAwayHandler, + bufferPool: bufferPool, } return l } @@ -767,6 +791,11 @@ func (l *loopyWriter) cleanupStreamHandler(c *cleanupStream) error { // not be established yet. delete(l.estdStreams, c.streamID) str.deleteSelf() + for head := str.itl.dequeueAll(); head != nil; head = head.next { + if df, ok := head.it.(*dataFrame); ok { + _ = df.reader.Close() + } + } } if c.rst { // If RST_STREAM needs to be sent. if err := l.framer.fr.WriteRSTStream(c.streamID, c.rstCode); err != nil { @@ -902,16 +931,18 @@ func (l *loopyWriter) processData() (bool, error) { dataItem := str.itl.peek().(*dataFrame) // Peek at the first data item this stream. // A data item is represented by a dataFrame, since it later translates into // multiple HTTP2 data frames. - // Every dataFrame has two buffers; h that keeps grpc-message header and d that is actual data. - // As an optimization to keep wire traffic low, data from d is copied to h to make as big as the - // maximum possible HTTP2 frame size. + // Every dataFrame has two buffers; h that keeps grpc-message header and data + // that is the actual message. As an optimization to keep wire traffic low, data + // from data is copied to h to make as big as the maximum possible HTTP2 frame + // size. - if len(dataItem.h) == 0 && len(dataItem.d) == 0 { // Empty data frame + if len(dataItem.h) == 0 && dataItem.reader.Remaining() == 0 { // Empty data frame // Client sends out empty data frame with endStream = true if err := l.framer.fr.WriteData(dataItem.streamID, dataItem.endStream, nil); err != nil { return false, err } str.itl.dequeue() // remove the empty data item from stream + _ = dataItem.reader.Close() if str.itl.isEmpty() { str.state = empty } else if trailer, ok := str.itl.peek().(*headerFrame); ok { // the next item is trailers. @@ -926,9 +957,7 @@ func (l *loopyWriter) processData() (bool, error) { } return false, nil } - var ( - buf []byte - ) + // Figure out the maximum size we can send maxSize := http2MaxFrameLen if strQuota := int(l.oiws) - str.bytesOutStanding; strQuota <= 0 { // stream-level flow control. @@ -942,43 +971,50 @@ func (l *loopyWriter) processData() (bool, error) { } // Compute how much of the header and data we can send within quota and max frame length hSize := min(maxSize, len(dataItem.h)) - dSize := min(maxSize-hSize, len(dataItem.d)) - if hSize != 0 { - if dSize == 0 { - buf = dataItem.h - } else { - // We can add some data to grpc message header to distribute bytes more equally across frames. - // Copy on the stack to avoid generating garbage - var localBuf [http2MaxFrameLen]byte - copy(localBuf[:hSize], dataItem.h) - copy(localBuf[hSize:], dataItem.d[:dSize]) - buf = localBuf[:hSize+dSize] - } + dSize := min(maxSize-hSize, dataItem.reader.Remaining()) + remainingBytes := len(dataItem.h) + dataItem.reader.Remaining() - hSize - dSize + size := hSize + dSize + + var buf *[]byte + + if hSize != 0 && dSize == 0 { + buf = &dataItem.h } else { - buf = dataItem.d - } + // Note: this is only necessary because the http2.Framer does not support + // partially writing a frame, so the sequence must be materialized into a buffer. + // TODO: Revisit once https://github.com/golang/go/issues/66655 is addressed. + pool := l.bufferPool + if pool == nil { + // Note that this is only supposed to be nil in tests. Otherwise, stream is + // always initialized with a BufferPool. + pool = mem.DefaultBufferPool() + } + buf = pool.Get(size) + defer pool.Put(buf) - size := hSize + dSize + copy((*buf)[:hSize], dataItem.h) + _, _ = dataItem.reader.Read((*buf)[hSize:]) + } // Now that outgoing flow controls are checked we can replenish str's write quota str.wq.replenish(size) var endStream bool // If this is the last data message on this stream and all of it can be written in this iteration. - if dataItem.endStream && len(dataItem.h)+len(dataItem.d) <= size { + if dataItem.endStream && remainingBytes == 0 { endStream = true } if dataItem.onEachWrite != nil { dataItem.onEachWrite() } - if err := l.framer.fr.WriteData(dataItem.streamID, endStream, buf[:size]); err != nil { + if err := l.framer.fr.WriteData(dataItem.streamID, endStream, (*buf)[:size]); err != nil { return false, err } str.bytesOutStanding += size l.sendQuota -= uint32(size) dataItem.h = dataItem.h[hSize:] - dataItem.d = dataItem.d[dSize:] - if len(dataItem.h) == 0 && len(dataItem.d) == 0 { // All the data from that message was written out. + if remainingBytes == 0 { // All the data from that message was written out. + _ = dataItem.reader.Close() str.itl.dequeue() } if str.itl.isEmpty() { @@ -997,10 +1033,3 @@ func (l *loopyWriter) processData() (bool, error) { } return false, nil } - -func min(a, b int) int { - if a < b { - return a - } - return b -} diff --git a/vendor/google.golang.org/grpc/internal/transport/handler_server.go b/vendor/google.golang.org/grpc/internal/transport/handler_server.go index 4a3ddce29..ce878693b 100644 --- a/vendor/google.golang.org/grpc/internal/transport/handler_server.go +++ b/vendor/google.golang.org/grpc/internal/transport/handler_server.go @@ -24,7 +24,6 @@ package transport import ( - "bytes" "context" "errors" "fmt" @@ -40,6 +39,7 @@ import ( "google.golang.org/grpc/credentials" "google.golang.org/grpc/internal/grpclog" "google.golang.org/grpc/internal/grpcutil" + "google.golang.org/grpc/mem" "google.golang.org/grpc/metadata" "google.golang.org/grpc/peer" "google.golang.org/grpc/stats" @@ -50,7 +50,7 @@ import ( // NewServerHandlerTransport returns a ServerTransport handling gRPC from // inside an http.Handler, or writes an HTTP error to w and returns an error. // It requires that the http Server supports HTTP/2. -func NewServerHandlerTransport(w http.ResponseWriter, r *http.Request, stats []stats.Handler) (ServerTransport, error) { +func NewServerHandlerTransport(w http.ResponseWriter, r *http.Request, stats []stats.Handler, bufferPool mem.BufferPool) (ServerTransport, error) { if r.Method != http.MethodPost { w.Header().Set("Allow", http.MethodPost) msg := fmt.Sprintf("invalid gRPC request method %q", r.Method) @@ -98,6 +98,7 @@ func NewServerHandlerTransport(w http.ResponseWriter, r *http.Request, stats []s contentType: contentType, contentSubtype: contentSubtype, stats: stats, + bufferPool: bufferPool, } st.logger = prefixLoggerForServerHandlerTransport(st) @@ -171,6 +172,8 @@ type serverHandlerTransport struct { stats []stats.Handler logger *grpclog.PrefixLogger + + bufferPool mem.BufferPool } func (ht *serverHandlerTransport) Close(err error) { @@ -244,6 +247,7 @@ func (ht *serverHandlerTransport) WriteStatus(s *Stream, st *status.Status) erro } s.hdrMu.Lock() + defer s.hdrMu.Unlock() if p := st.Proto(); p != nil && len(p.Details) > 0 { delete(s.trailer, grpcStatusDetailsBinHeader) stBytes, err := proto.Marshal(p) @@ -268,7 +272,6 @@ func (ht *serverHandlerTransport) WriteStatus(s *Stream, st *status.Status) erro } } } - s.hdrMu.Unlock() }) if err == nil { // transport has not been closed @@ -330,16 +333,28 @@ func (ht *serverHandlerTransport) writeCustomHeaders(s *Stream) { s.hdrMu.Unlock() } -func (ht *serverHandlerTransport) Write(s *Stream, hdr []byte, data []byte, opts *Options) error { +func (ht *serverHandlerTransport) Write(s *Stream, hdr []byte, data mem.BufferSlice, _ *Options) error { + // Always take a reference because otherwise there is no guarantee the data will + // be available after this function returns. This is what callers to Write + // expect. + data.Ref() headersWritten := s.updateHeaderSent() - return ht.do(func() { + err := ht.do(func() { + defer data.Free() if !headersWritten { ht.writePendingHeaders(s) } ht.rw.Write(hdr) - ht.rw.Write(data) + for _, b := range data { + _, _ = ht.rw.Write(b.ReadOnlyData()) + } ht.rw.(http.Flusher).Flush() }) + if err != nil { + data.Free() + return err + } + return nil } func (ht *serverHandlerTransport) WriteHeader(s *Stream, md metadata.MD) error { @@ -406,7 +421,7 @@ func (ht *serverHandlerTransport) HandleStreams(ctx context.Context, startStream headerWireLength: 0, // won't have access to header wire length until golang/go#18997. } s.trReader = &transportReader{ - reader: &recvBufferReader{ctx: s.ctx, ctxDone: s.ctx.Done(), recv: s.buf, freeBuffer: func(*bytes.Buffer) {}}, + reader: &recvBufferReader{ctx: s.ctx, ctxDone: s.ctx.Done(), recv: s.buf}, windowHandler: func(int) {}, } @@ -415,21 +430,19 @@ func (ht *serverHandlerTransport) HandleStreams(ctx context.Context, startStream go func() { defer close(readerDone) - // TODO: minimize garbage, optimize recvBuffer code/ownership - const readSize = 8196 - for buf := make([]byte, readSize); ; { - n, err := req.Body.Read(buf) + for { + buf := ht.bufferPool.Get(http2MaxFrameLen) + n, err := req.Body.Read(*buf) if n > 0 { - s.buf.put(recvMsg{buffer: bytes.NewBuffer(buf[:n:n])}) - buf = buf[n:] + *buf = (*buf)[:n] + s.buf.put(recvMsg{buffer: mem.NewBuffer(buf, ht.bufferPool)}) + } else { + ht.bufferPool.Put(buf) } if err != nil { s.buf.put(recvMsg{err: mapRecvMsgError(err)}) return } - if len(buf) == 0 { - buf = make([]byte, readSize) - } } }() @@ -462,7 +475,7 @@ func (ht *serverHandlerTransport) IncrMsgSent() {} func (ht *serverHandlerTransport) IncrMsgRecv() {} -func (ht *serverHandlerTransport) Drain(debugData string) { +func (ht *serverHandlerTransport) Drain(string) { panic("Drain() is not implemented") } diff --git a/vendor/google.golang.org/grpc/internal/transport/http2_client.go b/vendor/google.golang.org/grpc/internal/transport/http2_client.go index deba0c4d9..62b81885d 100644 --- a/vendor/google.golang.org/grpc/internal/transport/http2_client.go +++ b/vendor/google.golang.org/grpc/internal/transport/http2_client.go @@ -47,6 +47,7 @@ import ( isyscall "google.golang.org/grpc/internal/syscall" "google.golang.org/grpc/internal/transport/networktype" "google.golang.org/grpc/keepalive" + "google.golang.org/grpc/mem" "google.golang.org/grpc/metadata" "google.golang.org/grpc/peer" "google.golang.org/grpc/resolver" @@ -59,6 +60,8 @@ import ( // atomically. var clientConnectionCounter uint64 +var goAwayLoopyWriterTimeout = 5 * time.Second + var metadataFromOutgoingContextRaw = internal.FromOutgoingContextRaw.(func(context.Context) (metadata.MD, [][]string, bool)) // http2Client implements the ClientTransport interface with HTTP2. @@ -83,9 +86,9 @@ type http2Client struct { writerDone chan struct{} // sync point to enable testing. // goAway is closed to notify the upper layer (i.e., addrConn.transportMonitor) // that the server sent GoAway on this transport. - goAway chan struct{} - - framer *framer + goAway chan struct{} + keepaliveDone chan struct{} // Closed when the keepalive goroutine exits. + framer *framer // controlBuf delivers all the control related tasks (e.g., window // updates, reset streams, and various settings) to the controller. // Do not access controlBuf with mu held. @@ -114,11 +117,11 @@ type http2Client struct { streamQuota int64 streamsQuotaAvailable chan struct{} waitingStreams uint32 - nextID uint32 registeredCompressors string // Do not access controlBuf with mu held. mu sync.Mutex // guard the following variables + nextID uint32 state transportState activeStreams map[uint32]*Stream // prevGoAway ID records the Last-Stream-ID in the previous GOAway frame. @@ -144,7 +147,7 @@ type http2Client struct { onClose func(GoAwayReason) - bufferPool *bufferPool + bufferPool mem.BufferPool connectionID uint64 logger *grpclog.PrefixLogger @@ -229,7 +232,7 @@ func newHTTP2Client(connectCtx, ctx context.Context, addr resolver.Address, opts } }(conn) - // The following defer and goroutine monitor the connectCtx for cancelation + // The following defer and goroutine monitor the connectCtx for cancellation // and deadline. On context expiration, the connection is hard closed and // this function will naturally fail as a result. Otherwise, the defer // waits for the goroutine to exit to prevent the context from being @@ -332,6 +335,7 @@ func newHTTP2Client(connectCtx, ctx context.Context, addr resolver.Address, opts readerDone: make(chan struct{}), writerDone: make(chan struct{}), goAway: make(chan struct{}), + keepaliveDone: make(chan struct{}), framer: newFramer(conn, writeBufSize, readBufSize, opts.SharedWriteBuffer, maxHeaderListSize), fc: &trInFlow{limit: uint32(icwz)}, scheme: scheme, @@ -346,7 +350,7 @@ func newHTTP2Client(connectCtx, ctx context.Context, addr resolver.Address, opts streamQuota: defaultMaxStreamsClient, streamsQuotaAvailable: make(chan struct{}, 1), keepaliveEnabled: keepaliveEnabled, - bufferPool: newBufferPool(), + bufferPool: opts.BufferPool, onClose: onClose, } var czSecurity credentials.ChannelzSecurityValue @@ -408,10 +412,10 @@ func newHTTP2Client(connectCtx, ctx context.Context, addr resolver.Address, opts readerErrCh := make(chan error, 1) go t.reader(readerErrCh) defer func() { - if err == nil { - err = <-readerErrCh - } if err != nil { + // writerDone should be closed since the loopy goroutine + // wouldn't have started in the case this function returns an error. + close(t.writerDone) t.Close(err) } }() @@ -458,8 +462,12 @@ func newHTTP2Client(connectCtx, ctx context.Context, addr resolver.Address, opts if err := t.framer.writer.Flush(); err != nil { return nil, err } + // Block until the server preface is received successfully or an error occurs. + if err = <-readerErrCh; err != nil { + return nil, err + } go func() { - t.loopy = newLoopyWriter(clientSide, t.framer, t.controlBuf, t.bdpEst, t.conn, t.logger) + t.loopy = newLoopyWriter(clientSide, t.framer, t.controlBuf, t.bdpEst, t.conn, t.logger, t.outgoingGoAwayHandler, t.bufferPool) if err := t.loopy.run(); !isIOError(err) { // Immediately close the connection, as the loopy writer returns // when there are no more active streams and we were draining (the @@ -500,7 +508,6 @@ func (t *http2Client) newStream(ctx context.Context, callHdr *CallHdr) *Stream { closeStream: func(err error) { t.CloseStream(s, err) }, - freeBuffer: t.bufferPool.put, }, windowHandler: func(n int) { t.updateWindow(s, uint32(n)) @@ -517,6 +524,18 @@ func (t *http2Client) getPeer() *peer.Peer { } } +// OutgoingGoAwayHandler writes a GOAWAY to the connection. Always returns (false, err) as we want the GoAway +// to be the last frame loopy writes to the transport. +func (t *http2Client) outgoingGoAwayHandler(g *goAway) (bool, error) { + t.mu.Lock() + maxStreamID := t.nextID - 2 + t.mu.Unlock() + if err := t.framer.fr.WriteGoAway(maxStreamID, http2.ErrCodeNo, g.debugData); err != nil { + return false, err + } + return false, g.closeConn +} + func (t *http2Client) createHeaderFields(ctx context.Context, callHdr *CallHdr) ([]hpack.HeaderField, error) { aud := t.createAudience(callHdr) ri := credentials.RequestInfo{ @@ -755,7 +774,7 @@ func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr) (*Stream, hdr := &headerFrame{ hf: headerFields, endStream: false, - initStream: func(id uint32) error { + initStream: func(uint32) error { t.mu.Lock() // TODO: handle transport closure in loopy instead and remove this // initStream is never called when transport is draining. @@ -781,7 +800,7 @@ func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr) (*Stream, firstTry := true var ch chan struct{} transportDrainRequired := false - checkForStreamQuota := func(it any) bool { + checkForStreamQuota := func() bool { if t.streamQuota <= 0 { // Can go negative if server decreases it. if firstTry { t.waitingStreams++ @@ -793,23 +812,24 @@ func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr) (*Stream, t.waitingStreams-- } t.streamQuota-- - h := it.(*headerFrame) - h.streamID = t.nextID - t.nextID += 2 - - // Drain client transport if nextID > MaxStreamID which signals gRPC that - // the connection is closed and a new one must be created for subsequent RPCs. - transportDrainRequired = t.nextID > MaxStreamID - s.id = h.streamID - s.fc = &inFlow{limit: uint32(t.initialWindowSize)} t.mu.Lock() if t.state == draining || t.activeStreams == nil { // Can be niled from Close(). t.mu.Unlock() return false // Don't create a stream if the transport is already closed. } + + hdr.streamID = t.nextID + t.nextID += 2 + // Drain client transport if nextID > MaxStreamID which signals gRPC that + // the connection is closed and a new one must be created for subsequent RPCs. + transportDrainRequired = t.nextID > MaxStreamID + + s.id = hdr.streamID + s.fc = &inFlow{limit: uint32(t.initialWindowSize)} t.activeStreams[s.id] = s t.mu.Unlock() + if t.streamQuota > 0 && t.waitingStreams > 0 { select { case t.streamsQuotaAvailable <- struct{}{}: @@ -819,13 +839,12 @@ func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr) (*Stream, return true } var hdrListSizeErr error - checkForHeaderListSize := func(it any) bool { + checkForHeaderListSize := func() bool { if t.maxSendHeaderListSize == nil { return true } - hdrFrame := it.(*headerFrame) var sz int64 - for _, f := range hdrFrame.hf { + for _, f := range hdr.hf { if sz += int64(f.Size()); sz > int64(*t.maxSendHeaderListSize) { hdrListSizeErr = status.Errorf(codes.Internal, "header list size to send violates the maximum size (%d bytes) set by server", *t.maxSendHeaderListSize) return false @@ -834,8 +853,8 @@ func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr) (*Stream, return true } for { - success, err := t.controlBuf.executeAndPut(func(it any) bool { - return checkForHeaderListSize(it) && checkForStreamQuota(it) + success, err := t.controlBuf.executeAndPut(func() bool { + return checkForHeaderListSize() && checkForStreamQuota() }, hdr) if err != nil { // Connection closed. @@ -946,7 +965,7 @@ func (t *http2Client) closeStream(s *Stream, err error, rst bool, rstCode http2. rst: rst, rstCode: rstCode, } - addBackStreamQuota := func(any) bool { + addBackStreamQuota := func() bool { t.streamQuota++ if t.streamQuota > 0 && t.waitingStreams > 0 { select { @@ -966,8 +985,9 @@ func (t *http2Client) closeStream(s *Stream, err error, rst bool, rstCode http2. // Close kicks off the shutdown process of the transport. This should be called // only once on a transport. Once it is called, the transport should not be -// accessed any more. +// accessed anymore. func (t *http2Client) Close(err error) { + t.conn.SetWriteDeadline(time.Now().Add(time.Second * 10)) t.mu.Lock() // Make sure we only close once. if t.state == closing { @@ -990,15 +1010,33 @@ func (t *http2Client) Close(err error) { // should unblock it so that the goroutine eventually exits. t.kpDormancyCond.Signal() } + // Append info about previous goaways if there were any, since this may be important + // for understanding the root cause for this connection to be closed. + goAwayDebugMessage := t.goAwayDebugMessage t.mu.Unlock() - t.controlBuf.finish() + + // Per HTTP/2 spec, a GOAWAY frame must be sent before closing the + // connection. See https://httpwg.org/specs/rfc7540.html#GOAWAY. It + // also waits for loopyWriter to be closed with a timer to avoid the + // long blocking in case the connection is blackholed, i.e. TCP is + // just stuck. + t.controlBuf.put(&goAway{code: http2.ErrCodeNo, debugData: []byte("client transport shutdown"), closeConn: err}) + timer := time.NewTimer(goAwayLoopyWriterTimeout) + defer timer.Stop() + select { + case <-t.writerDone: // success + case <-timer.C: + t.logger.Infof("Failed to write a GOAWAY frame as part of connection close after %s. Giving up and closing the transport.", goAwayLoopyWriterTimeout) + } t.cancel() t.conn.Close() + // Waits for the reader and keepalive goroutines to exit before returning to + // ensure all resources are cleaned up before Close can return. + <-t.readerDone + if t.keepaliveEnabled { + <-t.keepaliveDone + } channelz.RemoveEntry(t.channelz.ID) - // Append info about previous goaways if there were any, since this may be important - // for understanding the root cause for this connection to be closed. - _, goAwayDebugMessage := t.GetGoAwayReason() - var st *status.Status if len(goAwayDebugMessage) > 0 { st = status.Newf(codes.Unavailable, "closing transport due to: %v, received prior goaway: %v", err, goAwayDebugMessage) @@ -1047,27 +1085,36 @@ func (t *http2Client) GracefulClose() { // Write formats the data into HTTP2 data frame(s) and sends it out. The caller // should proceed only if Write returns nil. -func (t *http2Client) Write(s *Stream, hdr []byte, data []byte, opts *Options) error { +func (t *http2Client) Write(s *Stream, hdr []byte, data mem.BufferSlice, opts *Options) error { + reader := data.Reader() + if opts.Last { // If it's the last message, update stream state. if !s.compareAndSwapState(streamActive, streamWriteDone) { + _ = reader.Close() return errStreamDone } } else if s.getState() != streamActive { + _ = reader.Close() return errStreamDone } df := &dataFrame{ streamID: s.id, endStream: opts.Last, h: hdr, - d: data, + reader: reader, } - if hdr != nil || data != nil { // If it's not an empty data frame, check quota. - if err := s.wq.get(int32(len(hdr) + len(data))); err != nil { + if hdr != nil || df.reader.Remaining() != 0 { // If it's not an empty data frame, check quota. + if err := s.wq.get(int32(len(hdr) + df.reader.Remaining())); err != nil { + _ = reader.Close() return err } } - return t.controlBuf.put(df) + if err := t.controlBuf.put(df); err != nil { + _ = reader.Close() + return err + } + return nil } func (t *http2Client) getStream(f http2.Frame) *Stream { @@ -1099,7 +1146,7 @@ func (t *http2Client) updateWindow(s *Stream, n uint32) { // for the transport and the stream based on the current bdp // estimation. func (t *http2Client) updateFlowControl(n uint32) { - updateIWS := func(any) bool { + updateIWS := func() bool { t.initialWindowSize = int32(n) t.mu.Lock() for _, s := range t.activeStreams { @@ -1172,10 +1219,13 @@ func (t *http2Client) handleData(f *http2.DataFrame) { // guarantee f.Data() is consumed before the arrival of next frame. // Can this copy be eliminated? if len(f.Data()) > 0 { - buffer := t.bufferPool.get() - buffer.Reset() - buffer.Write(f.Data()) - s.write(recvMsg{buffer: buffer}) + pool := t.bufferPool + if pool == nil { + // Note that this is only supposed to be nil in tests. Otherwise, stream is + // always initialized with a BufferPool. + pool = mem.DefaultBufferPool() + } + s.write(recvMsg{buffer: mem.Copy(f.Data(), pool)}) } } // The server has closed the stream without sending trailers. Record that @@ -1204,7 +1254,7 @@ func (t *http2Client) handleRSTStream(f *http2.RSTStreamFrame) { if statusCode == codes.Canceled { if d, ok := s.ctx.Deadline(); ok && !d.After(time.Now()) { // Our deadline was already exceeded, and that was likely the cause - // of this cancelation. Alter the status code accordingly. + // of this cancellation. Alter the status code accordingly. statusCode = codes.DeadlineExceeded } } @@ -1252,7 +1302,7 @@ func (t *http2Client) handleSettings(f *http2.SettingsFrame, isFirst bool) { } updateFuncs = append(updateFuncs, updateStreamQuota) } - t.controlBuf.executeAndPut(func(any) bool { + t.controlBuf.executeAndPut(func() bool { for _, f := range updateFuncs { f() } @@ -1273,11 +1323,11 @@ func (t *http2Client) handlePing(f *http2.PingFrame) { t.controlBuf.put(pingAck) } -func (t *http2Client) handleGoAway(f *http2.GoAwayFrame) { +func (t *http2Client) handleGoAway(f *http2.GoAwayFrame) error { t.mu.Lock() if t.state == closing { t.mu.Unlock() - return + return nil } if f.ErrCode == http2.ErrCodeEnhanceYourCalm && string(f.DebugData()) == "too_many_pings" { // When a client receives a GOAWAY with error code ENHANCE_YOUR_CALM and debug @@ -1289,8 +1339,7 @@ func (t *http2Client) handleGoAway(f *http2.GoAwayFrame) { id := f.LastStreamID if id > 0 && id%2 == 0 { t.mu.Unlock() - t.Close(connectionErrorf(true, nil, "received goaway with non-zero even-numbered numbered stream id: %v", id)) - return + return connectionErrorf(true, nil, "received goaway with non-zero even-numbered stream id: %v", id) } // A client can receive multiple GoAways from the server (see // https://github.com/grpc/grpc-go/issues/1387). The idea is that the first @@ -1307,8 +1356,7 @@ func (t *http2Client) handleGoAway(f *http2.GoAwayFrame) { // If there are multiple GoAways the first one should always have an ID greater than the following ones. if id > t.prevGoAwayID { t.mu.Unlock() - t.Close(connectionErrorf(true, nil, "received goaway with stream id: %v, which exceeds stream id of previous goaway: %v", id, t.prevGoAwayID)) - return + return connectionErrorf(true, nil, "received goaway with stream id: %v, which exceeds stream id of previous goaway: %v", id, t.prevGoAwayID) } default: t.setGoAwayReason(f) @@ -1332,8 +1380,7 @@ func (t *http2Client) handleGoAway(f *http2.GoAwayFrame) { t.prevGoAwayID = id if len(t.activeStreams) == 0 { t.mu.Unlock() - t.Close(connectionErrorf(true, nil, "received goaway and there are no active streams")) - return + return connectionErrorf(true, nil, "received goaway and there are no active streams") } streamsToClose := make([]*Stream, 0) @@ -1350,6 +1397,7 @@ func (t *http2Client) handleGoAway(f *http2.GoAwayFrame) { for _, stream := range streamsToClose { t.closeStream(stream, errStreamDrain, false, http2.ErrCodeNo, statusGoAway, nil, false) } + return nil } // setGoAwayReason sets the value of t.goAwayReason based @@ -1585,7 +1633,13 @@ func (t *http2Client) readServerPreface() error { // network connection. If the server preface is not read successfully, an // error is pushed to errCh; otherwise errCh is closed with no error. func (t *http2Client) reader(errCh chan<- error) { - defer close(t.readerDone) + var errClose error + defer func() { + close(t.readerDone) + if errClose != nil { + t.Close(errClose) + } + }() if err := t.readServerPreface(); err != nil { errCh <- err @@ -1624,11 +1678,10 @@ func (t *http2Client) reader(errCh chan<- error) { t.closeStream(s, status.Error(code, msg), true, http2.ErrCodeProtocol, status.New(code, msg), nil, false) } continue - } else { - // Transport error. - t.Close(connectionErrorf(true, err, "error reading from server: %v", err)) - return } + // Transport error. + errClose = connectionErrorf(true, err, "error reading from server: %v", err) + return } switch frame := frame.(type) { case *http2.MetaHeadersFrame: @@ -1642,7 +1695,7 @@ func (t *http2Client) reader(errCh chan<- error) { case *http2.PingFrame: t.handlePing(frame) case *http2.GoAwayFrame: - t.handleGoAway(frame) + errClose = t.handleGoAway(frame) case *http2.WindowUpdateFrame: t.handleWindowUpdate(frame) default: @@ -1653,15 +1706,15 @@ func (t *http2Client) reader(errCh chan<- error) { } } -func minTime(a, b time.Duration) time.Duration { - if a < b { - return a - } - return b -} - // keepalive running in a separate goroutine makes sure the connection is alive by sending pings. func (t *http2Client) keepalive() { + var err error + defer func() { + close(t.keepaliveDone) + if err != nil { + t.Close(err) + } + }() p := &ping{data: [8]byte{}} // True iff a ping has been sent, and no data has been received since then. outstandingPing := false @@ -1685,7 +1738,7 @@ func (t *http2Client) keepalive() { continue } if outstandingPing && timeoutLeft <= 0 { - t.Close(connectionErrorf(true, nil, "keepalive ping failed to receive ACK within timeout")) + err = connectionErrorf(true, nil, "keepalive ping failed to receive ACK within timeout") return } t.mu.Lock() @@ -1727,7 +1780,7 @@ func (t *http2Client) keepalive() { // timeoutLeft. This will ensure that we wait only for kp.Time // before sending out the next ping (for cases where the ping is // acked). - sleepDuration := minTime(t.kp.Time, timeoutLeft) + sleepDuration := min(t.kp.Time, timeoutLeft) timeoutLeft -= sleepDuration timer.Reset(sleepDuration) case <-t.ctx.Done(): diff --git a/vendor/google.golang.org/grpc/internal/transport/http2_server.go b/vendor/google.golang.org/grpc/internal/transport/http2_server.go index d582e0471..584b50fe5 100644 --- a/vendor/google.golang.org/grpc/internal/transport/http2_server.go +++ b/vendor/google.golang.org/grpc/internal/transport/http2_server.go @@ -25,6 +25,7 @@ import ( "fmt" "io" "math" + "math/rand" "net" "net/http" "strconv" @@ -38,12 +39,12 @@ import ( "google.golang.org/grpc/internal/grpcutil" "google.golang.org/grpc/internal/pretty" "google.golang.org/grpc/internal/syscall" + "google.golang.org/grpc/mem" "google.golang.org/protobuf/proto" "google.golang.org/grpc/codes" "google.golang.org/grpc/credentials" "google.golang.org/grpc/internal/channelz" - "google.golang.org/grpc/internal/grpcrand" "google.golang.org/grpc/internal/grpcsync" "google.golang.org/grpc/keepalive" "google.golang.org/grpc/metadata" @@ -119,7 +120,7 @@ type http2Server struct { // Fields below are for channelz metric collection. channelz *channelz.Socket - bufferPool *bufferPool + bufferPool mem.BufferPool connectionID uint64 @@ -261,7 +262,7 @@ func NewServerTransport(conn net.Conn, config *ServerConfig) (_ ServerTransport, idle: time.Now(), kep: kep, initialWindowSize: iwz, - bufferPool: newBufferPool(), + bufferPool: config.BufferPool, } var czSecurity credentials.ChannelzSecurityValue if au, ok := authInfo.(credentials.ChannelzSecurityInfo); ok { @@ -330,8 +331,7 @@ func NewServerTransport(conn net.Conn, config *ServerConfig) (_ ServerTransport, t.handleSettings(sf) go func() { - t.loopy = newLoopyWriter(serverSide, t.framer, t.controlBuf, t.bdpEst, t.conn, t.logger) - t.loopy.ssGoAwayHandler = t.outgoingGoAwayHandler + t.loopy = newLoopyWriter(serverSide, t.framer, t.controlBuf, t.bdpEst, t.conn, t.logger, t.outgoingGoAwayHandler, t.bufferPool) err := t.loopy.run() close(t.loopyWriterDone) if !isIOError(err) { @@ -614,10 +614,9 @@ func (t *http2Server) operateHeaders(ctx context.Context, frame *http2.MetaHeade s.wq = newWriteQuota(defaultWriteQuota, s.ctxDone) s.trReader = &transportReader{ reader: &recvBufferReader{ - ctx: s.ctx, - ctxDone: s.ctxDone, - recv: s.buf, - freeBuffer: t.bufferPool.put, + ctx: s.ctx, + ctxDone: s.ctxDone, + recv: s.buf, }, windowHandler: func(n int) { t.updateWindow(s, uint32(n)) @@ -814,10 +813,13 @@ func (t *http2Server) handleData(f *http2.DataFrame) { // guarantee f.Data() is consumed before the arrival of next frame. // Can this copy be eliminated? if len(f.Data()) > 0 { - buffer := t.bufferPool.get() - buffer.Reset() - buffer.Write(f.Data()) - s.write(recvMsg{buffer: buffer}) + pool := t.bufferPool + if pool == nil { + // Note that this is only supposed to be nil in tests. Otherwise, stream is + // always initialized with a BufferPool. + pool = mem.DefaultBufferPool() + } + s.write(recvMsg{buffer: mem.Copy(f.Data(), pool)}) } } if f.StreamEnded() { @@ -860,7 +862,7 @@ func (t *http2Server) handleSettings(f *http2.SettingsFrame) { } return nil }) - t.controlBuf.executeAndPut(func(any) bool { + t.controlBuf.executeAndPut(func() bool { for _, f := range updateFuncs { f() } @@ -1014,12 +1016,13 @@ func (t *http2Server) writeHeaderLocked(s *Stream) error { headerFields = append(headerFields, hpack.HeaderField{Name: "grpc-encoding", Value: s.sendCompress}) } headerFields = appendHeaderFieldsFromMD(headerFields, s.header) - success, err := t.controlBuf.executeAndPut(t.checkForHeaderListSize, &headerFrame{ + hf := &headerFrame{ streamID: s.id, hf: headerFields, endStream: false, onWrite: t.setResetPingStrikes, - }) + } + success, err := t.controlBuf.executeAndPut(func() bool { return t.checkForHeaderListSize(hf) }, hf) if !success { if err != nil { return err @@ -1089,7 +1092,9 @@ func (t *http2Server) WriteStatus(s *Stream, st *status.Status) error { onWrite: t.setResetPingStrikes, } - success, err := t.controlBuf.execute(t.checkForHeaderListSize, trailingHeader) + success, err := t.controlBuf.executeAndPut(func() bool { + return t.checkForHeaderListSize(trailingHeader) + }, nil) if !success { if err != nil { return err @@ -1112,27 +1117,37 @@ func (t *http2Server) WriteStatus(s *Stream, st *status.Status) error { // Write converts the data into HTTP2 data frame and sends it out. Non-nil error // is returns if it fails (e.g., framing error, transport error). -func (t *http2Server) Write(s *Stream, hdr []byte, data []byte, opts *Options) error { +func (t *http2Server) Write(s *Stream, hdr []byte, data mem.BufferSlice, _ *Options) error { + reader := data.Reader() + if !s.isHeaderSent() { // Headers haven't been written yet. if err := t.WriteHeader(s, nil); err != nil { + _ = reader.Close() return err } } else { // Writing headers checks for this condition. if s.getState() == streamDone { + _ = reader.Close() return t.streamContextErr(s) } } + df := &dataFrame{ streamID: s.id, h: hdr, - d: data, + reader: reader, onEachWrite: t.setResetPingStrikes, } - if err := s.wq.get(int32(len(hdr) + len(data))); err != nil { + if err := s.wq.get(int32(len(hdr) + df.reader.Remaining())); err != nil { + _ = reader.Close() return t.streamContextErr(s) } - return t.controlBuf.put(df) + if err := t.controlBuf.put(df); err != nil { + _ = reader.Close() + return err + } + return nil } // keepalive running in a separate goroutine does the following: @@ -1208,7 +1223,7 @@ func (t *http2Server) keepalive() { continue } if outstandingPing && kpTimeoutLeft <= 0 { - t.Close(fmt.Errorf("keepalive ping not acked within timeout %s", t.kp.Time)) + t.Close(fmt.Errorf("keepalive ping not acked within timeout %s", t.kp.Timeout)) return } if !outstandingPing { @@ -1223,7 +1238,7 @@ func (t *http2Server) keepalive() { // timeoutLeft. This will ensure that we wait only for kp.Time // before sending out the next ping (for cases where the ping is // acked). - sleepDuration := minTime(t.kp.Time, kpTimeoutLeft) + sleepDuration := min(t.kp.Time, kpTimeoutLeft) kpTimeoutLeft -= sleepDuration kpTimer.Reset(sleepDuration) case <-t.done: @@ -1440,7 +1455,7 @@ func getJitter(v time.Duration) time.Duration { } // Generate a jitter between +/- 10% of the value. r := int64(v / 10) - j := grpcrand.Int63n(2*r) - r + j := rand.Int63n(2*r) - r return time.Duration(j) } diff --git a/vendor/google.golang.org/grpc/internal/transport/http_util.go b/vendor/google.golang.org/grpc/internal/transport/http_util.go index 39cef3bd4..3613d7b64 100644 --- a/vendor/google.golang.org/grpc/internal/transport/http_util.go +++ b/vendor/google.golang.org/grpc/internal/transport/http_util.go @@ -317,28 +317,32 @@ func newBufWriter(conn net.Conn, batchSize int, pool *sync.Pool) *bufWriter { return w } -func (w *bufWriter) Write(b []byte) (n int, err error) { +func (w *bufWriter) Write(b []byte) (int, error) { if w.err != nil { return 0, w.err } if w.batchSize == 0 { // Buffer has been disabled. - n, err = w.conn.Write(b) + n, err := w.conn.Write(b) return n, toIOError(err) } if w.buf == nil { b := w.pool.Get().(*[]byte) w.buf = *b } + written := 0 for len(b) > 0 { - nn := copy(w.buf[w.offset:], b) - b = b[nn:] - w.offset += nn - n += nn - if w.offset >= w.batchSize { - err = w.flushKeepBuffer() + copied := copy(w.buf[w.offset:], b) + b = b[copied:] + written += copied + w.offset += copied + if w.offset < w.batchSize { + continue + } + if err := w.flushKeepBuffer(); err != nil { + return written, err } } - return n, err + return written, nil } func (w *bufWriter) Flush() error { @@ -389,7 +393,7 @@ type framer struct { fr *http2.Framer } -var writeBufferPoolMap map[int]*sync.Pool = make(map[int]*sync.Pool) +var writeBufferPoolMap = make(map[int]*sync.Pool) var writeBufferMutex sync.Mutex func newFramer(conn net.Conn, writeBufferSize, readBufferSize int, sharedWriteBuffer bool, maxHeaderListSize uint32) *framer { diff --git a/vendor/google.golang.org/grpc/internal/transport/proxy.go b/vendor/google.golang.org/grpc/internal/transport/proxy.go index 24fa10325..54b224436 100644 --- a/vendor/google.golang.org/grpc/internal/transport/proxy.go +++ b/vendor/google.golang.org/grpc/internal/transport/proxy.go @@ -107,8 +107,14 @@ func doHTTPConnectHandshake(ctx context.Context, conn net.Conn, backendAddr stri } return nil, fmt.Errorf("failed to do connect handshake, response: %q", dump) } - - return &bufConn{Conn: conn, r: r}, nil + // The buffer could contain extra bytes from the target server, so we can't + // discard it. However, in many cases where the server waits for the client + // to send the first message (e.g. when TLS is being used), the buffer will + // be empty, so we can avoid the overhead of reading through this buffer. + if r.Buffered() != 0 { + return &bufConn{Conn: conn, r: r}, nil + } + return conn, nil } // proxyDial dials, connecting to a proxy first if necessary. Checks if a proxy diff --git a/vendor/google.golang.org/grpc/internal/transport/transport.go b/vendor/google.golang.org/grpc/internal/transport/transport.go index 0d2a6e47f..e12cb0bc9 100644 --- a/vendor/google.golang.org/grpc/internal/transport/transport.go +++ b/vendor/google.golang.org/grpc/internal/transport/transport.go @@ -22,7 +22,6 @@ package transport import ( - "bytes" "context" "errors" "fmt" @@ -37,6 +36,7 @@ import ( "google.golang.org/grpc/credentials" "google.golang.org/grpc/internal/channelz" "google.golang.org/grpc/keepalive" + "google.golang.org/grpc/mem" "google.golang.org/grpc/metadata" "google.golang.org/grpc/peer" "google.golang.org/grpc/resolver" @@ -47,32 +47,10 @@ import ( const logLevel = 2 -type bufferPool struct { - pool sync.Pool -} - -func newBufferPool() *bufferPool { - return &bufferPool{ - pool: sync.Pool{ - New: func() any { - return new(bytes.Buffer) - }, - }, - } -} - -func (p *bufferPool) get() *bytes.Buffer { - return p.pool.Get().(*bytes.Buffer) -} - -func (p *bufferPool) put(b *bytes.Buffer) { - p.pool.Put(b) -} - // recvMsg represents the received msg from the transport. All transport // protocol specific info has been removed. type recvMsg struct { - buffer *bytes.Buffer + buffer mem.Buffer // nil: received some data // io.EOF: stream is completed. data is nil. // other non-nil error: transport failure. data is nil. @@ -102,6 +80,9 @@ func newRecvBuffer() *recvBuffer { func (b *recvBuffer) put(r recvMsg) { b.mu.Lock() if b.err != nil { + // drop the buffer on the floor. Since b.err is not nil, any subsequent reads + // will always return an error, making this buffer inaccessible. + r.buffer.Free() b.mu.Unlock() // An error had occurred earlier, don't accept more // data or errors. @@ -148,45 +129,97 @@ type recvBufferReader struct { ctx context.Context ctxDone <-chan struct{} // cache of ctx.Done() (for performance). recv *recvBuffer - last *bytes.Buffer // Stores the remaining data in the previous calls. + last mem.Buffer // Stores the remaining data in the previous calls. err error - freeBuffer func(*bytes.Buffer) } -// Read reads the next len(p) bytes from last. If last is drained, it tries to -// read additional data from recv. It blocks if there no additional data available -// in recv. If Read returns any non-nil error, it will continue to return that error. -func (r *recvBufferReader) Read(p []byte) (n int, err error) { +func (r *recvBufferReader) ReadHeader(header []byte) (n int, err error) { if r.err != nil { return 0, r.err } if r.last != nil { - // Read remaining data left in last call. - copied, _ := r.last.Read(p) - if r.last.Len() == 0 { - r.freeBuffer(r.last) + n, r.last = mem.ReadUnsafe(header, r.last) + return n, nil + } + if r.closeStream != nil { + n, r.err = r.readHeaderClient(header) + } else { + n, r.err = r.readHeader(header) + } + return n, r.err +} + +// Read reads the next n bytes from last. If last is drained, it tries to read +// additional data from recv. It blocks if there no additional data available in +// recv. If Read returns any non-nil error, it will continue to return that +// error. +func (r *recvBufferReader) Read(n int) (buf mem.Buffer, err error) { + if r.err != nil { + return nil, r.err + } + if r.last != nil { + buf = r.last + if r.last.Len() > n { + buf, r.last = mem.SplitUnsafe(buf, n) + } else { r.last = nil } - return copied, nil + return buf, nil } if r.closeStream != nil { - n, r.err = r.readClient(p) + buf, r.err = r.readClient(n) } else { - n, r.err = r.read(p) + buf, r.err = r.read(n) } - return n, r.err + return buf, r.err } -func (r *recvBufferReader) read(p []byte) (n int, err error) { +func (r *recvBufferReader) readHeader(header []byte) (n int, err error) { select { case <-r.ctxDone: return 0, ContextErr(r.ctx.Err()) case m := <-r.recv.get(): - return r.readAdditional(m, p) + return r.readHeaderAdditional(m, header) + } +} + +func (r *recvBufferReader) read(n int) (buf mem.Buffer, err error) { + select { + case <-r.ctxDone: + return nil, ContextErr(r.ctx.Err()) + case m := <-r.recv.get(): + return r.readAdditional(m, n) + } +} + +func (r *recvBufferReader) readHeaderClient(header []byte) (n int, err error) { + // If the context is canceled, then closes the stream with nil metadata. + // closeStream writes its error parameter to r.recv as a recvMsg. + // r.readAdditional acts on that message and returns the necessary error. + select { + case <-r.ctxDone: + // Note that this adds the ctx error to the end of recv buffer, and + // reads from the head. This will delay the error until recv buffer is + // empty, thus will delay ctx cancellation in Recv(). + // + // It's done this way to fix a race between ctx cancel and trailer. The + // race was, stream.Recv() may return ctx error if ctxDone wins the + // race, but stream.Trailer() may return a non-nil md because the stream + // was not marked as done when trailer is received. This closeStream + // call will mark stream as done, thus fix the race. + // + // TODO: delaying ctx error seems like a unnecessary side effect. What + // we really want is to mark the stream as done, and return ctx error + // faster. + r.closeStream(ContextErr(r.ctx.Err())) + m := <-r.recv.get() + return r.readHeaderAdditional(m, header) + case m := <-r.recv.get(): + return r.readHeaderAdditional(m, header) } } -func (r *recvBufferReader) readClient(p []byte) (n int, err error) { +func (r *recvBufferReader) readClient(n int) (buf mem.Buffer, err error) { // If the context is canceled, then closes the stream with nil metadata. // closeStream writes its error parameter to r.recv as a recvMsg. // r.readAdditional acts on that message and returns the necessary error. @@ -207,25 +240,40 @@ func (r *recvBufferReader) readClient(p []byte) (n int, err error) { // faster. r.closeStream(ContextErr(r.ctx.Err())) m := <-r.recv.get() - return r.readAdditional(m, p) + return r.readAdditional(m, n) case m := <-r.recv.get(): - return r.readAdditional(m, p) + return r.readAdditional(m, n) } } -func (r *recvBufferReader) readAdditional(m recvMsg, p []byte) (n int, err error) { +func (r *recvBufferReader) readHeaderAdditional(m recvMsg, header []byte) (n int, err error) { r.recv.load() if m.err != nil { + if m.buffer != nil { + m.buffer.Free() + } return 0, m.err } - copied, _ := m.buffer.Read(p) - if m.buffer.Len() == 0 { - r.freeBuffer(m.buffer) - r.last = nil - } else { - r.last = m.buffer + + n, r.last = mem.ReadUnsafe(header, m.buffer) + + return n, nil +} + +func (r *recvBufferReader) readAdditional(m recvMsg, n int) (b mem.Buffer, err error) { + r.recv.load() + if m.err != nil { + if m.buffer != nil { + m.buffer.Free() + } + return nil, m.err + } + + if m.buffer.Len() > n { + m.buffer, r.last = mem.SplitUnsafe(m.buffer, n) } - return copied, nil + + return m.buffer, nil } type streamState uint32 @@ -241,7 +289,7 @@ const ( type Stream struct { id uint32 st ServerTransport // nil for client side Stream - ct *http2Client // nil for server side Stream + ct ClientTransport // nil for server side Stream ctx context.Context // the associated context of the stream cancel context.CancelFunc // always nil for client side Stream done chan struct{} // closed at the end of stream to unblock writers. On the client side. @@ -251,7 +299,7 @@ type Stream struct { recvCompress string sendCompress string buf *recvBuffer - trReader io.Reader + trReader *transportReader fc *inFlow wq *writeQuota @@ -304,7 +352,7 @@ func (s *Stream) isHeaderSent() bool { } // updateHeaderSent updates headerSent and returns true -// if it was alreay set. It is valid only on server-side. +// if it was already set. It is valid only on server-side. func (s *Stream) updateHeaderSent() bool { return atomic.SwapUint32(&s.headerSent, 1) == 1 } @@ -408,7 +456,7 @@ func (s *Stream) TrailersOnly() bool { return s.noHeaders } -// Trailer returns the cached trailer metedata. Note that if it is not called +// Trailer returns the cached trailer metadata. Note that if it is not called // after the entire stream is done, it could return an empty MD. Client // side only. // It can be safely read only after stream has ended that is either read @@ -499,36 +547,96 @@ func (s *Stream) write(m recvMsg) { s.buf.put(m) } -// Read reads all p bytes from the wire for this stream. -func (s *Stream) Read(p []byte) (n int, err error) { +// ReadHeader reads data into the provided header slice from the stream. It +// first checks if there was an error during a previous read operation and +// returns it if present. It then requests a read operation for the length of +// the header. It continues to read from the stream until the entire header +// slice is filled or an error occurs. If an `io.EOF` error is encountered +// with partially read data, it is converted to `io.ErrUnexpectedEOF` to +// indicate an unexpected end of the stream. The method returns any error +// encountered during the read process or nil if the header was successfully +// read. +func (s *Stream) ReadHeader(header []byte) (err error) { + // Don't request a read if there was an error earlier + if er := s.trReader.er; er != nil { + return er + } + s.requestRead(len(header)) + for len(header) != 0 { + n, err := s.trReader.ReadHeader(header) + header = header[n:] + if len(header) == 0 { + err = nil + } + if err != nil { + if n > 0 && err == io.EOF { + err = io.ErrUnexpectedEOF + } + return err + } + } + return nil +} + +// Read reads n bytes from the wire for this stream. +func (s *Stream) Read(n int) (data mem.BufferSlice, err error) { // Don't request a read if there was an error earlier - if er := s.trReader.(*transportReader).er; er != nil { - return 0, er + if er := s.trReader.er; er != nil { + return nil, er } - s.requestRead(len(p)) - return io.ReadFull(s.trReader, p) + s.requestRead(n) + for n != 0 { + buf, err := s.trReader.Read(n) + var bufLen int + if buf != nil { + bufLen = buf.Len() + } + n -= bufLen + if n == 0 { + err = nil + } + if err != nil { + if bufLen > 0 && err == io.EOF { + err = io.ErrUnexpectedEOF + } + data.Free() + return nil, err + } + data = append(data, buf) + } + return data, nil } -// tranportReader reads all the data available for this Stream from the transport and +// transportReader reads all the data available for this Stream from the transport and // passes them into the decoder, which converts them into a gRPC message stream. // The error is io.EOF when the stream is done or another non-nil error if // the stream broke. type transportReader struct { - reader io.Reader + reader *recvBufferReader // The handler to control the window update procedure for both this // particular stream and the associated transport. windowHandler func(int) er error } -func (t *transportReader) Read(p []byte) (n int, err error) { - n, err = t.reader.Read(p) +func (t *transportReader) ReadHeader(header []byte) (int, error) { + n, err := t.reader.ReadHeader(header) if err != nil { t.er = err - return + return 0, err } t.windowHandler(n) - return + return n, nil +} + +func (t *transportReader) Read(n int) (mem.Buffer, error) { + buf, err := t.reader.Read(n) + if err != nil { + t.er = err + return buf, err + } + t.windowHandler(buf.Len()) + return buf, nil } // BytesReceived indicates whether any bytes have been received on this stream. @@ -574,6 +682,7 @@ type ServerConfig struct { ChannelzParent *channelz.Server MaxHeaderListSize *uint32 HeaderTableSize *uint32 + BufferPool mem.BufferPool } // ConnectOptions covers all relevant options for communicating with the server. @@ -612,6 +721,8 @@ type ConnectOptions struct { MaxHeaderListSize *uint32 // UseProxy specifies if a proxy should be used. UseProxy bool + // The mem.BufferPool to use when reading/writing to the wire. + BufferPool mem.BufferPool } // NewClientTransport establishes the transport with the required ConnectOptions @@ -673,7 +784,7 @@ type ClientTransport interface { // Write sends the data for the given stream. A nil stream indicates // the write is to be performed on the transport as a whole. - Write(s *Stream, hdr []byte, data []byte, opts *Options) error + Write(s *Stream, hdr []byte, data mem.BufferSlice, opts *Options) error // NewStream creates a Stream for an RPC. NewStream(ctx context.Context, callHdr *CallHdr) (*Stream, error) @@ -725,7 +836,7 @@ type ServerTransport interface { // Write sends the data for the given stream. // Write may not be called on all streams. - Write(s *Stream, hdr []byte, data []byte, opts *Options) error + Write(s *Stream, hdr []byte, data mem.BufferSlice, opts *Options) error // WriteStatus sends the status of a stream to the client. WriteStatus is // the final call made on a stream and always occurs. @@ -798,7 +909,7 @@ var ( // connection is draining. This could be caused by goaway or balancer // removing the address. errStreamDrain = status.Error(codes.Unavailable, "the connection is draining") - // errStreamDone is returned from write at the client side to indiacte application + // errStreamDone is returned from write at the client side to indicate application // layer of an error. errStreamDone = errors.New("the stream is done") // StatusGoAway indicates that the server sent a GOAWAY that included this diff --git a/vendor/google.golang.org/grpc/keepalive/keepalive.go b/vendor/google.golang.org/grpc/keepalive/keepalive.go index 34d31b5e7..eb42b19fb 100644 --- a/vendor/google.golang.org/grpc/keepalive/keepalive.go +++ b/vendor/google.golang.org/grpc/keepalive/keepalive.go @@ -34,15 +34,29 @@ type ClientParameters struct { // After a duration of this time if the client doesn't see any activity it // pings the server to see if the transport is still alive. // If set below 10s, a minimum value of 10s will be used instead. - Time time.Duration // The current default value is infinity. + // + // Note that gRPC servers have a default EnforcementPolicy.MinTime of 5 + // minutes (which means the client shouldn't ping more frequently than every + // 5 minutes). + // + // Though not ideal, it's not a strong requirement for Time to be less than + // EnforcementPolicy.MinTime. Time will automatically double if the server + // disconnects due to its enforcement policy. + // + // For more details, see + // https://github.com/grpc/proposal/blob/master/A8-client-side-keepalive.md + Time time.Duration // After having pinged for keepalive check, the client waits for a duration // of Timeout and if no activity is seen even after that the connection is // closed. - Timeout time.Duration // The current default value is 20 seconds. + // + // If keepalive is enabled, and this value is not explicitly set, the default + // is 20 seconds. + Timeout time.Duration // If true, client sends keepalive pings even with no active RPCs. If false, // when there are no active RPCs, Time and Timeout will be ignored and no // keepalive pings will be sent. - PermitWithoutStream bool // false by default. + PermitWithoutStream bool } // ServerParameters is used to set keepalive and max-age parameters on the diff --git a/vendor/google.golang.org/grpc/mem/buffer_pool.go b/vendor/google.golang.org/grpc/mem/buffer_pool.go new file mode 100644 index 000000000..c37c58c02 --- /dev/null +++ b/vendor/google.golang.org/grpc/mem/buffer_pool.go @@ -0,0 +1,194 @@ +/* + * + * Copyright 2024 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. + * + */ + +package mem + +import ( + "sort" + "sync" + + "google.golang.org/grpc/internal" +) + +// BufferPool is a pool of buffers that can be shared and reused, resulting in +// decreased memory allocation. +type BufferPool interface { + // Get returns a buffer with specified length from the pool. + Get(length int) *[]byte + + // Put returns a buffer to the pool. + Put(*[]byte) +} + +var defaultBufferPoolSizes = []int{ + 256, + 4 << 10, // 4KB (go page size) + 16 << 10, // 16KB (max HTTP/2 frame size used by gRPC) + 32 << 10, // 32KB (default buffer size for io.Copy) + 1 << 20, // 1MB +} + +var defaultBufferPool BufferPool + +func init() { + defaultBufferPool = NewTieredBufferPool(defaultBufferPoolSizes...) + + internal.SetDefaultBufferPoolForTesting = func(pool BufferPool) { + defaultBufferPool = pool + } + + internal.SetBufferPoolingThresholdForTesting = func(threshold int) { + bufferPoolingThreshold = threshold + } +} + +// DefaultBufferPool returns the current default buffer pool. It is a BufferPool +// created with NewBufferPool that uses a set of default sizes optimized for +// expected workflows. +func DefaultBufferPool() BufferPool { + return defaultBufferPool +} + +// NewTieredBufferPool returns a BufferPool implementation that uses multiple +// underlying pools of the given pool sizes. +func NewTieredBufferPool(poolSizes ...int) BufferPool { + sort.Ints(poolSizes) + pools := make([]*sizedBufferPool, len(poolSizes)) + for i, s := range poolSizes { + pools[i] = newSizedBufferPool(s) + } + return &tieredBufferPool{ + sizedPools: pools, + } +} + +// tieredBufferPool implements the BufferPool interface with multiple tiers of +// buffer pools for different sizes of buffers. +type tieredBufferPool struct { + sizedPools []*sizedBufferPool + fallbackPool simpleBufferPool +} + +func (p *tieredBufferPool) Get(size int) *[]byte { + return p.getPool(size).Get(size) +} + +func (p *tieredBufferPool) Put(buf *[]byte) { + p.getPool(cap(*buf)).Put(buf) +} + +func (p *tieredBufferPool) getPool(size int) BufferPool { + poolIdx := sort.Search(len(p.sizedPools), func(i int) bool { + return p.sizedPools[i].defaultSize >= size + }) + + if poolIdx == len(p.sizedPools) { + return &p.fallbackPool + } + + return p.sizedPools[poolIdx] +} + +// sizedBufferPool is a BufferPool implementation that is optimized for specific +// buffer sizes. For example, HTTP/2 frames within gRPC have a default max size +// of 16kb and a sizedBufferPool can be configured to only return buffers with a +// capacity of 16kb. Note that however it does not support returning larger +// buffers and in fact panics if such a buffer is requested. Because of this, +// this BufferPool implementation is not meant to be used on its own and rather +// is intended to be embedded in a tieredBufferPool such that Get is only +// invoked when the required size is smaller than or equal to defaultSize. +type sizedBufferPool struct { + pool sync.Pool + defaultSize int +} + +func (p *sizedBufferPool) Get(size int) *[]byte { + buf := p.pool.Get().(*[]byte) + b := *buf + clear(b[:cap(b)]) + *buf = b[:size] + return buf +} + +func (p *sizedBufferPool) Put(buf *[]byte) { + if cap(*buf) < p.defaultSize { + // Ignore buffers that are too small to fit in the pool. Otherwise, when + // Get is called it will panic as it tries to index outside the bounds + // of the buffer. + return + } + p.pool.Put(buf) +} + +func newSizedBufferPool(size int) *sizedBufferPool { + return &sizedBufferPool{ + pool: sync.Pool{ + New: func() any { + buf := make([]byte, size) + return &buf + }, + }, + defaultSize: size, + } +} + +var _ BufferPool = (*simpleBufferPool)(nil) + +// simpleBufferPool is an implementation of the BufferPool interface that +// attempts to pool buffers with a sync.Pool. When Get is invoked, it tries to +// acquire a buffer from the pool but if that buffer is too small, it returns it +// to the pool and creates a new one. +type simpleBufferPool struct { + pool sync.Pool +} + +func (p *simpleBufferPool) Get(size int) *[]byte { + bs, ok := p.pool.Get().(*[]byte) + if ok && cap(*bs) >= size { + *bs = (*bs)[:size] + return bs + } + + // A buffer was pulled from the pool, but it is too small. Put it back in + // the pool and create one large enough. + if ok { + p.pool.Put(bs) + } + + b := make([]byte, size) + return &b +} + +func (p *simpleBufferPool) Put(buf *[]byte) { + p.pool.Put(buf) +} + +var _ BufferPool = NopBufferPool{} + +// NopBufferPool is a buffer pool that returns new buffers without pooling. +type NopBufferPool struct{} + +// Get returns a buffer with specified length from the pool. +func (NopBufferPool) Get(length int) *[]byte { + b := make([]byte, length) + return &b +} + +// Put returns a buffer to the pool. +func (NopBufferPool) Put(*[]byte) { +} diff --git a/vendor/google.golang.org/grpc/mem/buffer_slice.go b/vendor/google.golang.org/grpc/mem/buffer_slice.go new file mode 100644 index 000000000..228e9c2f2 --- /dev/null +++ b/vendor/google.golang.org/grpc/mem/buffer_slice.go @@ -0,0 +1,226 @@ +/* + * + * Copyright 2024 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. + * + */ + +package mem + +import ( + "io" +) + +// BufferSlice offers a means to represent data that spans one or more Buffer +// instances. A BufferSlice is meant to be immutable after creation, and methods +// like Ref create and return copies of the slice. This is why all methods have +// value receivers rather than pointer receivers. +// +// Note that any of the methods that read the underlying buffers such as Ref, +// Len or CopyTo etc., will panic if any underlying buffers have already been +// freed. It is recommended to not directly interact with any of the underlying +// buffers directly, rather such interactions should be mediated through the +// various methods on this type. +// +// By convention, any APIs that return (mem.BufferSlice, error) should reduce +// the burden on the caller by never returning a mem.BufferSlice that needs to +// be freed if the error is non-nil, unless explicitly stated. +type BufferSlice []Buffer + +// Len returns the sum of the length of all the Buffers in this slice. +// +// # Warning +// +// Invoking the built-in len on a BufferSlice will return the number of buffers +// in the slice, and *not* the value returned by this function. +func (s BufferSlice) Len() int { + var length int + for _, b := range s { + length += b.Len() + } + return length +} + +// Ref invokes Ref on each buffer in the slice. +func (s BufferSlice) Ref() { + for _, b := range s { + b.Ref() + } +} + +// Free invokes Buffer.Free() on each Buffer in the slice. +func (s BufferSlice) Free() { + for _, b := range s { + b.Free() + } +} + +// CopyTo copies each of the underlying Buffer's data into the given buffer, +// returning the number of bytes copied. Has the same semantics as the copy +// builtin in that it will copy as many bytes as it can, stopping when either dst +// is full or s runs out of data, returning the minimum of s.Len() and len(dst). +func (s BufferSlice) CopyTo(dst []byte) int { + off := 0 + for _, b := range s { + off += copy(dst[off:], b.ReadOnlyData()) + } + return off +} + +// Materialize concatenates all the underlying Buffer's data into a single +// contiguous buffer using CopyTo. +func (s BufferSlice) Materialize() []byte { + l := s.Len() + if l == 0 { + return nil + } + out := make([]byte, l) + s.CopyTo(out) + return out +} + +// MaterializeToBuffer functions like Materialize except that it writes the data +// to a single Buffer pulled from the given BufferPool. +// +// As a special case, if the input BufferSlice only actually has one Buffer, this +// function simply increases the refcount before returning said Buffer. Freeing this +// buffer won't release it until the BufferSlice is itself released. +func (s BufferSlice) MaterializeToBuffer(pool BufferPool) Buffer { + if len(s) == 1 { + s[0].Ref() + return s[0] + } + sLen := s.Len() + if sLen == 0 { + return emptyBuffer{} + } + buf := pool.Get(sLen) + s.CopyTo(*buf) + return NewBuffer(buf, pool) +} + +// Reader returns a new Reader for the input slice after taking references to +// each underlying buffer. +func (s BufferSlice) Reader() Reader { + s.Ref() + return &sliceReader{ + data: s, + len: s.Len(), + } +} + +// Reader exposes a BufferSlice's data as an io.Reader, allowing it to interface +// with other parts systems. It also provides an additional convenience method +// Remaining(), which returns the number of unread bytes remaining in the slice. +// Buffers will be freed as they are read. +type Reader interface { + io.Reader + io.ByteReader + // Close frees the underlying BufferSlice and never returns an error. Subsequent + // calls to Read will return (0, io.EOF). + Close() error + // Remaining returns the number of unread bytes remaining in the slice. + Remaining() int +} + +type sliceReader struct { + data BufferSlice + len int + // The index into data[0].ReadOnlyData(). + bufferIdx int +} + +func (r *sliceReader) Remaining() int { + return r.len +} + +func (r *sliceReader) Close() error { + r.data.Free() + r.data = nil + r.len = 0 + return nil +} + +func (r *sliceReader) freeFirstBufferIfEmpty() bool { + if len(r.data) == 0 || r.bufferIdx != len(r.data[0].ReadOnlyData()) { + return false + } + + r.data[0].Free() + r.data = r.data[1:] + r.bufferIdx = 0 + return true +} + +func (r *sliceReader) Read(buf []byte) (n int, _ error) { + if r.len == 0 { + return 0, io.EOF + } + + for len(buf) != 0 && r.len != 0 { + // Copy as much as possible from the first Buffer in the slice into the + // given byte slice. + data := r.data[0].ReadOnlyData() + copied := copy(buf, data[r.bufferIdx:]) + r.len -= copied // Reduce len by the number of bytes copied. + r.bufferIdx += copied // Increment the buffer index. + n += copied // Increment the total number of bytes read. + buf = buf[copied:] // Shrink the given byte slice. + + // If we have copied all the data from the first Buffer, free it and advance to + // the next in the slice. + r.freeFirstBufferIfEmpty() + } + + return n, nil +} + +func (r *sliceReader) ReadByte() (byte, error) { + if r.len == 0 { + return 0, io.EOF + } + + // There may be any number of empty buffers in the slice, clear them all until a + // non-empty buffer is reached. This is guaranteed to exit since r.len is not 0. + for r.freeFirstBufferIfEmpty() { + } + + b := r.data[0].ReadOnlyData()[r.bufferIdx] + r.len-- + r.bufferIdx++ + // Free the first buffer in the slice if the last byte was read + r.freeFirstBufferIfEmpty() + return b, nil +} + +var _ io.Writer = (*writer)(nil) + +type writer struct { + buffers *BufferSlice + pool BufferPool +} + +func (w *writer) Write(p []byte) (n int, err error) { + b := Copy(p, w.pool) + *w.buffers = append(*w.buffers, b) + return b.Len(), nil +} + +// NewWriter wraps the given BufferSlice and BufferPool to implement the +// io.Writer interface. Every call to Write copies the contents of the given +// buffer into a new Buffer pulled from the given pool and the Buffer is added to +// the given BufferSlice. +func NewWriter(buffers *BufferSlice, pool BufferPool) io.Writer { + return &writer{buffers: buffers, pool: pool} +} diff --git a/vendor/google.golang.org/grpc/mem/buffers.go b/vendor/google.golang.org/grpc/mem/buffers.go new file mode 100644 index 000000000..ecbf0b9a7 --- /dev/null +++ b/vendor/google.golang.org/grpc/mem/buffers.go @@ -0,0 +1,268 @@ +/* + * + * Copyright 2024 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. + * + */ + +// Package mem provides utilities that facilitate memory reuse in byte slices +// that are used as buffers. +// +// # Experimental +// +// Notice: All APIs in this package are EXPERIMENTAL and may be changed or +// removed in a later release. +package mem + +import ( + "fmt" + "sync" + "sync/atomic" +) + +// A Buffer represents a reference counted piece of data (in bytes) that can be +// acquired by a call to NewBuffer() or Copy(). A reference to a Buffer may be +// released by calling Free(), which invokes the free function given at creation +// only after all references are released. +// +// Note that a Buffer is not safe for concurrent access and instead each +// goroutine should use its own reference to the data, which can be acquired via +// a call to Ref(). +// +// Attempts to access the underlying data after releasing the reference to the +// Buffer will panic. +type Buffer interface { + // ReadOnlyData returns the underlying byte slice. Note that it is undefined + // behavior to modify the contents of this slice in any way. + ReadOnlyData() []byte + // Ref increases the reference counter for this Buffer. + Ref() + // Free decrements this Buffer's reference counter and frees the underlying + // byte slice if the counter reaches 0 as a result of this call. + Free() + // Len returns the Buffer's size. + Len() int + + split(n int) (left, right Buffer) + read(buf []byte) (int, Buffer) +} + +var ( + bufferPoolingThreshold = 1 << 10 + + bufferObjectPool = sync.Pool{New: func() any { return new(buffer) }} + refObjectPool = sync.Pool{New: func() any { return new(atomic.Int32) }} +) + +// IsBelowBufferPoolingThreshold returns true if the given size is less than or +// equal to the threshold for buffer pooling. This is used to determine whether +// to pool buffers or allocate them directly. +func IsBelowBufferPoolingThreshold(size int) bool { + return size <= bufferPoolingThreshold +} + +type buffer struct { + origData *[]byte + data []byte + refs *atomic.Int32 + pool BufferPool +} + +func newBuffer() *buffer { + return bufferObjectPool.Get().(*buffer) +} + +// NewBuffer creates a new Buffer from the given data, initializing the reference +// counter to 1. The data will then be returned to the given pool when all +// references to the returned Buffer are released. As a special case to avoid +// additional allocations, if the given buffer pool is nil, the returned buffer +// will be a "no-op" Buffer where invoking Buffer.Free() does nothing and the +// underlying data is never freed. +// +// Note that the backing array of the given data is not copied. +func NewBuffer(data *[]byte, pool BufferPool) Buffer { + // Use the buffer's capacity instead of the length, otherwise buffers may + // not be reused under certain conditions. For example, if a large buffer + // is acquired from the pool, but fewer bytes than the buffering threshold + // are written to it, the buffer will not be returned to the pool. + if pool == nil || IsBelowBufferPoolingThreshold(cap(*data)) { + return (SliceBuffer)(*data) + } + b := newBuffer() + b.origData = data + b.data = *data + b.pool = pool + b.refs = refObjectPool.Get().(*atomic.Int32) + b.refs.Add(1) + return b +} + +// Copy creates a new Buffer from the given data, initializing the reference +// counter to 1. +// +// It acquires a []byte from the given pool and copies over the backing array +// of the given data. The []byte acquired from the pool is returned to the +// pool when all references to the returned Buffer are released. +func Copy(data []byte, pool BufferPool) Buffer { + if IsBelowBufferPoolingThreshold(len(data)) { + buf := make(SliceBuffer, len(data)) + copy(buf, data) + return buf + } + + buf := pool.Get(len(data)) + copy(*buf, data) + return NewBuffer(buf, pool) +} + +func (b *buffer) ReadOnlyData() []byte { + if b.refs == nil { + panic("Cannot read freed buffer") + } + return b.data +} + +func (b *buffer) Ref() { + if b.refs == nil { + panic("Cannot ref freed buffer") + } + b.refs.Add(1) +} + +func (b *buffer) Free() { + if b.refs == nil { + panic("Cannot free freed buffer") + } + + refs := b.refs.Add(-1) + switch { + case refs > 0: + return + case refs == 0: + if b.pool != nil { + b.pool.Put(b.origData) + } + + refObjectPool.Put(b.refs) + b.origData = nil + b.data = nil + b.refs = nil + b.pool = nil + bufferObjectPool.Put(b) + default: + panic("Cannot free freed buffer") + } +} + +func (b *buffer) Len() int { + return len(b.ReadOnlyData()) +} + +func (b *buffer) split(n int) (Buffer, Buffer) { + if b.refs == nil { + panic("Cannot split freed buffer") + } + + b.refs.Add(1) + split := newBuffer() + split.origData = b.origData + split.data = b.data[n:] + split.refs = b.refs + split.pool = b.pool + + b.data = b.data[:n] + + return b, split +} + +func (b *buffer) read(buf []byte) (int, Buffer) { + if b.refs == nil { + panic("Cannot read freed buffer") + } + + n := copy(buf, b.data) + if n == len(b.data) { + b.Free() + return n, nil + } + + b.data = b.data[n:] + return n, b +} + +func (b *buffer) String() string { + return fmt.Sprintf("mem.Buffer(%p, data: %p, length: %d)", b, b.ReadOnlyData(), len(b.ReadOnlyData())) +} + +// ReadUnsafe reads bytes from the given Buffer into the provided slice. +// It does not perform safety checks. +func ReadUnsafe(dst []byte, buf Buffer) (int, Buffer) { + return buf.read(dst) +} + +// SplitUnsafe modifies the receiver to point to the first n bytes while it +// returns a new reference to the remaining bytes. The returned Buffer +// functions just like a normal reference acquired using Ref(). +func SplitUnsafe(buf Buffer, n int) (left, right Buffer) { + return buf.split(n) +} + +type emptyBuffer struct{} + +func (e emptyBuffer) ReadOnlyData() []byte { + return nil +} + +func (e emptyBuffer) Ref() {} +func (e emptyBuffer) Free() {} + +func (e emptyBuffer) Len() int { + return 0 +} + +func (e emptyBuffer) split(int) (left, right Buffer) { + return e, e +} + +func (e emptyBuffer) read([]byte) (int, Buffer) { + return 0, e +} + +// SliceBuffer is a Buffer implementation that wraps a byte slice. It provides +// methods for reading, splitting, and managing the byte slice. +type SliceBuffer []byte + +// ReadOnlyData returns the byte slice. +func (s SliceBuffer) ReadOnlyData() []byte { return s } + +// Ref is a noop implementation of Ref. +func (s SliceBuffer) Ref() {} + +// Free is a noop implementation of Free. +func (s SliceBuffer) Free() {} + +// Len is a noop implementation of Len. +func (s SliceBuffer) Len() int { return len(s) } + +func (s SliceBuffer) split(n int) (left, right Buffer) { + return s[:n], s[n:] +} + +func (s SliceBuffer) read(buf []byte) (int, Buffer) { + n := copy(buf, s) + if n == len(s) { + return n, nil + } + return n, s[n:] +} diff --git a/vendor/google.golang.org/grpc/metadata/metadata.go b/vendor/google.golang.org/grpc/metadata/metadata.go index 1e9485fd6..d2e15253b 100644 --- a/vendor/google.golang.org/grpc/metadata/metadata.go +++ b/vendor/google.golang.org/grpc/metadata/metadata.go @@ -213,11 +213,6 @@ func FromIncomingContext(ctx context.Context) (MD, bool) { // ValueFromIncomingContext returns the metadata value corresponding to the metadata // key from the incoming metadata if it exists. Keys are matched in a case insensitive // manner. -// -// # Experimental -// -// Notice: This API is EXPERIMENTAL and may be changed or removed in a -// later release. func ValueFromIncomingContext(ctx context.Context, key string) []string { md, ok := ctx.Value(mdIncomingKey{}).(MD) if !ok { @@ -228,7 +223,7 @@ func ValueFromIncomingContext(ctx context.Context, key string) []string { return copyOf(v) } for k, v := range md { - // Case insenitive comparison: MD is a map, and there's no guarantee + // Case insensitive comparison: MD is a map, and there's no guarantee // that the MD attached to the context is created using our helper // functions. if strings.EqualFold(k, key) { diff --git a/vendor/google.golang.org/grpc/peer/peer.go b/vendor/google.golang.org/grpc/peer/peer.go index a821ff9b2..499a49c8c 100644 --- a/vendor/google.golang.org/grpc/peer/peer.go +++ b/vendor/google.golang.org/grpc/peer/peer.go @@ -22,7 +22,9 @@ package peer import ( "context" + "fmt" "net" + "strings" "google.golang.org/grpc/credentials" ) @@ -39,6 +41,34 @@ type Peer struct { AuthInfo credentials.AuthInfo } +// String ensures the Peer types implements the Stringer interface in order to +// allow to print a context with a peerKey value effectively. +func (p *Peer) String() string { + if p == nil { + return "Peer" + } + sb := &strings.Builder{} + sb.WriteString("Peer{") + if p.Addr != nil { + fmt.Fprintf(sb, "Addr: '%s', ", p.Addr.String()) + } else { + fmt.Fprintf(sb, "Addr: , ") + } + if p.LocalAddr != nil { + fmt.Fprintf(sb, "LocalAddr: '%s', ", p.LocalAddr.String()) + } else { + fmt.Fprintf(sb, "LocalAddr: , ") + } + if p.AuthInfo != nil { + fmt.Fprintf(sb, "AuthInfo: '%s'", p.AuthInfo.AuthType()) + } else { + fmt.Fprintf(sb, "AuthInfo: ") + } + sb.WriteString("}") + + return sb.String() +} + type peerKey struct{} // NewContext creates a new context with peer information attached. diff --git a/vendor/google.golang.org/grpc/picker_wrapper.go b/vendor/google.golang.org/grpc/picker_wrapper.go index bf56faa76..bdaa2130e 100644 --- a/vendor/google.golang.org/grpc/picker_wrapper.go +++ b/vendor/google.golang.org/grpc/picker_wrapper.go @@ -20,8 +20,9 @@ package grpc import ( "context" + "fmt" "io" - "sync" + "sync/atomic" "google.golang.org/grpc/balancer" "google.golang.org/grpc/codes" @@ -32,35 +33,43 @@ import ( "google.golang.org/grpc/status" ) +// pickerGeneration stores a picker and a channel used to signal that a picker +// newer than this one is available. +type pickerGeneration struct { + // picker is the picker produced by the LB policy. May be nil if a picker + // has never been produced. + picker balancer.Picker + // blockingCh is closed when the picker has been invalidated because there + // is a new one available. + blockingCh chan struct{} +} + // pickerWrapper is a wrapper of balancer.Picker. It blocks on certain pick // actions and unblock when there's a picker update. type pickerWrapper struct { - mu sync.Mutex - done bool - blockingCh chan struct{} - picker balancer.Picker + // If pickerGen holds a nil pointer, the pickerWrapper is closed. + pickerGen atomic.Pointer[pickerGeneration] statsHandlers []stats.Handler // to record blocking picker calls } func newPickerWrapper(statsHandlers []stats.Handler) *pickerWrapper { - return &pickerWrapper{ - blockingCh: make(chan struct{}), + pw := &pickerWrapper{ statsHandlers: statsHandlers, } + pw.pickerGen.Store(&pickerGeneration{ + blockingCh: make(chan struct{}), + }) + return pw } -// updatePicker is called by UpdateBalancerState. It unblocks all blocked pick. +// updatePicker is called by UpdateState calls from the LB policy. It +// unblocks all blocked pick. func (pw *pickerWrapper) updatePicker(p balancer.Picker) { - pw.mu.Lock() - if pw.done { - pw.mu.Unlock() - return - } - pw.picker = p - // pw.blockingCh should never be nil. - close(pw.blockingCh) - pw.blockingCh = make(chan struct{}) - pw.mu.Unlock() + old := pw.pickerGen.Swap(&pickerGeneration{ + picker: p, + blockingCh: make(chan struct{}), + }) + close(old.blockingCh) } // doneChannelzWrapper performs the following: @@ -97,27 +106,24 @@ func (pw *pickerWrapper) pick(ctx context.Context, failfast bool, info balancer. var lastPickErr error for { - pw.mu.Lock() - if pw.done { - pw.mu.Unlock() + pg := pw.pickerGen.Load() + if pg == nil { return nil, balancer.PickResult{}, ErrClientConnClosing } - - if pw.picker == nil { - ch = pw.blockingCh + if pg.picker == nil { + ch = pg.blockingCh } - if ch == pw.blockingCh { + if ch == pg.blockingCh { // This could happen when either: // - pw.picker is nil (the previous if condition), or - // - has called pick on the current picker. - pw.mu.Unlock() + // - we have already called pick on the current picker. select { case <-ctx.Done(): var errStr string if lastPickErr != nil { errStr = "latest balancer error: " + lastPickErr.Error() } else { - errStr = ctx.Err().Error() + errStr = fmt.Sprintf("received context error while waiting for new LB policy update: %s", ctx.Err().Error()) } switch ctx.Err() { case context.DeadlineExceeded: @@ -144,9 +150,8 @@ func (pw *pickerWrapper) pick(ctx context.Context, failfast bool, info balancer. } } - ch = pw.blockingCh - p := pw.picker - pw.mu.Unlock() + ch = pg.blockingCh + p := pg.picker pickResult, err := p.Pick(info) if err != nil { @@ -196,24 +201,15 @@ func (pw *pickerWrapper) pick(ctx context.Context, failfast bool, info balancer. } func (pw *pickerWrapper) close() { - pw.mu.Lock() - defer pw.mu.Unlock() - if pw.done { - return - } - pw.done = true - close(pw.blockingCh) + old := pw.pickerGen.Swap(nil) + close(old.blockingCh) } // reset clears the pickerWrapper and prepares it for being used again when idle // mode is exited. func (pw *pickerWrapper) reset() { - pw.mu.Lock() - defer pw.mu.Unlock() - if pw.done { - return - } - pw.blockingCh = make(chan struct{}) + old := pw.pickerGen.Swap(&pickerGeneration{blockingCh: make(chan struct{})}) + close(old.blockingCh) } // dropError is a wrapper error that indicates the LB policy wishes to drop the diff --git a/vendor/google.golang.org/grpc/preloader.go b/vendor/google.golang.org/grpc/preloader.go index 73bd63364..e87a17f36 100644 --- a/vendor/google.golang.org/grpc/preloader.go +++ b/vendor/google.golang.org/grpc/preloader.go @@ -20,6 +20,7 @@ package grpc import ( "google.golang.org/grpc/codes" + "google.golang.org/grpc/mem" "google.golang.org/grpc/status" ) @@ -31,9 +32,10 @@ import ( // later release. type PreparedMsg struct { // Struct for preparing msg before sending them - encodedData []byte + encodedData mem.BufferSlice hdr []byte - payload []byte + payload mem.BufferSlice + pf payloadFormat } // Encode marshalls and compresses the message using the codec and compressor for the stream. @@ -57,11 +59,27 @@ func (p *PreparedMsg) Encode(s Stream, msg any) error { if err != nil { return err } - p.encodedData = data - compData, err := compress(data, rpcInfo.preloaderInfo.cp, rpcInfo.preloaderInfo.comp) + + materializedData := data.Materialize() + data.Free() + p.encodedData = mem.BufferSlice{mem.NewBuffer(&materializedData, nil)} + + // TODO: it should be possible to grab the bufferPool from the underlying + // stream implementation with a type cast to its actual type (such as + // addrConnStream) and accessing the buffer pool directly. + var compData mem.BufferSlice + compData, p.pf, err = compress(p.encodedData, rpcInfo.preloaderInfo.cp, rpcInfo.preloaderInfo.comp, mem.DefaultBufferPool()) if err != nil { return err } - p.hdr, p.payload = msgHeader(data, compData) + + if p.pf.isCompressed() { + materializedCompData := compData.Materialize() + compData.Free() + compData = mem.BufferSlice{mem.NewBuffer(&materializedCompData, nil)} + } + + p.hdr, p.payload = msgHeader(p.encodedData, compData, p.pf) + return nil } diff --git a/vendor/google.golang.org/grpc/regenerate.sh b/vendor/google.golang.org/grpc/regenerate.sh deleted file mode 100644 index a6f26c8ab..000000000 --- a/vendor/google.golang.org/grpc/regenerate.sh +++ /dev/null @@ -1,123 +0,0 @@ -#!/bin/bash -# Copyright 2020 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. - -set -eu -o pipefail - -WORKDIR=$(mktemp -d) - -function finish { - rm -rf "$WORKDIR" -} -trap finish EXIT - -export GOBIN=${WORKDIR}/bin -export PATH=${GOBIN}:${PATH} -mkdir -p ${GOBIN} - -echo "remove existing generated files" -# grpc_testing_not_regenerate/*.pb.go is not re-generated, -# see grpc_testing_not_regenerate/README.md for details. -rm -f $(find . -name '*.pb.go' | grep -v 'grpc_testing_not_regenerate') - -echo "go install google.golang.org/protobuf/cmd/protoc-gen-go" -(cd test/tools && go install google.golang.org/protobuf/cmd/protoc-gen-go) - -echo "go install cmd/protoc-gen-go-grpc" -(cd cmd/protoc-gen-go-grpc && go install .) - -echo "git clone https://github.com/grpc/grpc-proto" -git clone --quiet https://github.com/grpc/grpc-proto ${WORKDIR}/grpc-proto - -echo "git clone https://github.com/protocolbuffers/protobuf" -git clone --quiet https://github.com/protocolbuffers/protobuf ${WORKDIR}/protobuf - -# Pull in code.proto as a proto dependency -mkdir -p ${WORKDIR}/googleapis/google/rpc -echo "curl https://raw.githubusercontent.com/googleapis/googleapis/master/google/rpc/code.proto" -curl --silent https://raw.githubusercontent.com/googleapis/googleapis/master/google/rpc/code.proto > ${WORKDIR}/googleapis/google/rpc/code.proto - -mkdir -p ${WORKDIR}/out - -# Generates sources without the embed requirement -LEGACY_SOURCES=( - ${WORKDIR}/grpc-proto/grpc/binlog/v1/binarylog.proto - ${WORKDIR}/grpc-proto/grpc/channelz/v1/channelz.proto - ${WORKDIR}/grpc-proto/grpc/health/v1/health.proto - ${WORKDIR}/grpc-proto/grpc/lb/v1/load_balancer.proto - profiling/proto/service.proto - ${WORKDIR}/grpc-proto/grpc/reflection/v1alpha/reflection.proto - ${WORKDIR}/grpc-proto/grpc/reflection/v1/reflection.proto -) - -# Generates only the new gRPC Service symbols -SOURCES=( - $(git ls-files --exclude-standard --cached --others "*.proto" | grep -v '^\(profiling/proto/service.proto\|reflection/grpc_reflection_v1alpha/reflection.proto\)$') - ${WORKDIR}/grpc-proto/grpc/gcp/altscontext.proto - ${WORKDIR}/grpc-proto/grpc/gcp/handshaker.proto - ${WORKDIR}/grpc-proto/grpc/gcp/transport_security_common.proto - ${WORKDIR}/grpc-proto/grpc/lookup/v1/rls.proto - ${WORKDIR}/grpc-proto/grpc/lookup/v1/rls_config.proto - ${WORKDIR}/grpc-proto/grpc/testing/*.proto - ${WORKDIR}/grpc-proto/grpc/core/*.proto -) - -# These options of the form 'Mfoo.proto=bar' instruct the codegen to use an -# import path of 'bar' in the generated code when 'foo.proto' is imported in -# one of the sources. -# -# Note that the protos listed here are all for testing purposes. All protos to -# be used externally should have a go_package option (and they don't need to be -# listed here). -OPTS=Mgrpc/core/stats.proto=google.golang.org/grpc/interop/grpc_testing/core,\ -Mgrpc/testing/benchmark_service.proto=google.golang.org/grpc/interop/grpc_testing,\ -Mgrpc/testing/stats.proto=google.golang.org/grpc/interop/grpc_testing,\ -Mgrpc/testing/report_qps_scenario_service.proto=google.golang.org/grpc/interop/grpc_testing,\ -Mgrpc/testing/messages.proto=google.golang.org/grpc/interop/grpc_testing,\ -Mgrpc/testing/worker_service.proto=google.golang.org/grpc/interop/grpc_testing,\ -Mgrpc/testing/control.proto=google.golang.org/grpc/interop/grpc_testing,\ -Mgrpc/testing/test.proto=google.golang.org/grpc/interop/grpc_testing,\ -Mgrpc/testing/payloads.proto=google.golang.org/grpc/interop/grpc_testing,\ -Mgrpc/testing/empty.proto=google.golang.org/grpc/interop/grpc_testing - -for src in ${SOURCES[@]}; do - echo "protoc ${src}" - protoc --go_out=${OPTS}:${WORKDIR}/out --go-grpc_out=${OPTS}:${WORKDIR}/out \ - -I"." \ - -I${WORKDIR}/grpc-proto \ - -I${WORKDIR}/googleapis \ - -I${WORKDIR}/protobuf/src \ - ${src} -done - -for src in ${LEGACY_SOURCES[@]}; do - echo "protoc ${src}" - protoc --go_out=${OPTS}:${WORKDIR}/out --go-grpc_out=${OPTS},require_unimplemented_servers=false:${WORKDIR}/out \ - -I"." \ - -I${WORKDIR}/grpc-proto \ - -I${WORKDIR}/googleapis \ - -I${WORKDIR}/protobuf/src \ - ${src} -done - -# The go_package option in grpc/lookup/v1/rls.proto doesn't match the -# current location. Move it into the right place. -mkdir -p ${WORKDIR}/out/google.golang.org/grpc/internal/proto/grpc_lookup_v1 -mv ${WORKDIR}/out/google.golang.org/grpc/lookup/grpc_lookup_v1/* ${WORKDIR}/out/google.golang.org/grpc/internal/proto/grpc_lookup_v1 - -# grpc_testing_not_regenerate/*.pb.go are not re-generated, -# see grpc_testing_not_regenerate/README.md for details. -rm ${WORKDIR}/out/google.golang.org/grpc/reflection/grpc_testing_not_regenerate/*.pb.go - -cp -R ${WORKDIR}/out/google.golang.org/grpc/* . diff --git a/vendor/google.golang.org/grpc/resolver/dns/dns_resolver.go b/vendor/google.golang.org/grpc/resolver/dns/dns_resolver.go index b54a3a322..ef3d6ed6c 100644 --- a/vendor/google.golang.org/grpc/resolver/dns/dns_resolver.go +++ b/vendor/google.golang.org/grpc/resolver/dns/dns_resolver.go @@ -18,9 +18,6 @@ // Package dns implements a dns resolver to be installed as the default resolver // in grpc. -// -// Deprecated: this package is imported by grpc and should not need to be -// imported directly by users. package dns import ( @@ -52,3 +49,12 @@ func SetResolvingTimeout(timeout time.Duration) { func NewBuilder() resolver.Builder { return dns.NewBuilder() } + +// SetMinResolutionInterval sets the default minimum interval at which DNS +// re-resolutions are allowed. This helps to prevent excessive re-resolution. +// +// It must be called only at application startup, before any gRPC calls are +// made. Modifying this value after initialization is not thread-safe. +func SetMinResolutionInterval(d time.Duration) { + dns.MinResolutionInterval = d +} diff --git a/vendor/google.golang.org/grpc/resolver/manual/manual.go b/vendor/google.golang.org/grpc/resolver/manual/manual.go index f2efa2a2c..09e864a89 100644 --- a/vendor/google.golang.org/grpc/resolver/manual/manual.go +++ b/vendor/google.golang.org/grpc/resolver/manual/manual.go @@ -76,9 +76,11 @@ func (r *Resolver) InitialState(s resolver.State) { // Build returns itself for Resolver, because it's both a builder and a resolver. func (r *Resolver) Build(target resolver.Target, cc resolver.ClientConn, opts resolver.BuildOptions) (resolver.Resolver, error) { - r.BuildCallback(target, cc, opts) r.mu.Lock() defer r.mu.Unlock() + // Call BuildCallback after locking to avoid a race when UpdateState + // or ReportError is called before Build returns. + r.BuildCallback(target, cc, opts) r.CC = cc if r.lastSeenState != nil { err := r.CC.UpdateState(*r.lastSeenState) diff --git a/vendor/google.golang.org/grpc/resolver_wrapper.go b/vendor/google.golang.org/grpc/resolver_wrapper.go index 9dcc9780f..23bb3fb25 100644 --- a/vendor/google.golang.org/grpc/resolver_wrapper.go +++ b/vendor/google.golang.org/grpc/resolver_wrapper.go @@ -66,7 +66,7 @@ func newCCResolverWrapper(cc *ClientConn) *ccResolverWrapper { // any newly created ccResolverWrapper, except that close may be called instead. func (ccr *ccResolverWrapper) start() error { errCh := make(chan error) - ccr.serializer.Schedule(func(ctx context.Context) { + ccr.serializer.TrySchedule(func(ctx context.Context) { if ctx.Err() != nil { return } @@ -85,7 +85,7 @@ func (ccr *ccResolverWrapper) start() error { } func (ccr *ccResolverWrapper) resolveNow(o resolver.ResolveNowOptions) { - ccr.serializer.Schedule(func(ctx context.Context) { + ccr.serializer.TrySchedule(func(ctx context.Context) { if ctx.Err() != nil || ccr.resolver == nil { return } @@ -102,7 +102,7 @@ func (ccr *ccResolverWrapper) close() { ccr.closed = true ccr.mu.Unlock() - ccr.serializer.Schedule(func(context.Context) { + ccr.serializer.TrySchedule(func(context.Context) { if ccr.resolver == nil { return } @@ -171,12 +171,15 @@ func (ccr *ccResolverWrapper) NewAddress(addrs []resolver.Address) { // ParseServiceConfig is called by resolver implementations to parse a JSON // representation of the service config. func (ccr *ccResolverWrapper) ParseServiceConfig(scJSON string) *serviceconfig.ParseResult { - return parseServiceConfig(scJSON) + return parseServiceConfig(scJSON, ccr.cc.dopts.maxCallAttempts) } // addChannelzTraceEvent adds a channelz trace event containing the new // state received from resolver implementations. func (ccr *ccResolverWrapper) addChannelzTraceEvent(s resolver.State) { + if !logger.V(0) && !channelz.IsOn() { + return + } var updates []string var oldSC, newSC *ServiceConfig var oldOK, newOK bool diff --git a/vendor/google.golang.org/grpc/rpc_util.go b/vendor/google.golang.org/grpc/rpc_util.go index 998e251dd..aba1ae3e6 100644 --- a/vendor/google.golang.org/grpc/rpc_util.go +++ b/vendor/google.golang.org/grpc/rpc_util.go @@ -19,7 +19,6 @@ package grpc import ( - "bytes" "compress/gzip" "context" "encoding/binary" @@ -35,6 +34,7 @@ import ( "google.golang.org/grpc/encoding" "google.golang.org/grpc/encoding/proto" "google.golang.org/grpc/internal/transport" + "google.golang.org/grpc/mem" "google.golang.org/grpc/metadata" "google.golang.org/grpc/peer" "google.golang.org/grpc/stats" @@ -220,8 +220,8 @@ type HeaderCallOption struct { HeaderAddr *metadata.MD } -func (o HeaderCallOption) before(c *callInfo) error { return nil } -func (o HeaderCallOption) after(c *callInfo, attempt *csAttempt) { +func (o HeaderCallOption) before(*callInfo) error { return nil } +func (o HeaderCallOption) after(_ *callInfo, attempt *csAttempt) { *o.HeaderAddr, _ = attempt.s.Header() } @@ -242,8 +242,8 @@ type TrailerCallOption struct { TrailerAddr *metadata.MD } -func (o TrailerCallOption) before(c *callInfo) error { return nil } -func (o TrailerCallOption) after(c *callInfo, attempt *csAttempt) { +func (o TrailerCallOption) before(*callInfo) error { return nil } +func (o TrailerCallOption) after(_ *callInfo, attempt *csAttempt) { *o.TrailerAddr = attempt.s.Trailer() } @@ -264,24 +264,20 @@ type PeerCallOption struct { PeerAddr *peer.Peer } -func (o PeerCallOption) before(c *callInfo) error { return nil } -func (o PeerCallOption) after(c *callInfo, attempt *csAttempt) { +func (o PeerCallOption) before(*callInfo) error { return nil } +func (o PeerCallOption) after(_ *callInfo, attempt *csAttempt) { if x, ok := peer.FromContext(attempt.s.Context()); ok { *o.PeerAddr = *x } } -// WaitForReady configures the action to take when an RPC is attempted on broken -// connections or unreachable servers. If waitForReady is false and the -// connection is in the TRANSIENT_FAILURE state, the RPC will fail -// immediately. Otherwise, the RPC client will block the call until a -// connection is available (or the call is canceled or times out) and will -// retry the call if it fails due to a transient error. gRPC will not retry if -// data was written to the wire unless the server indicates it did not process -// the data. Please refer to -// https://github.com/grpc/grpc/blob/master/doc/wait-for-ready.md. +// WaitForReady configures the RPC's behavior when the client is in +// TRANSIENT_FAILURE, which occurs when all addresses fail to connect. If +// waitForReady is false, the RPC will fail immediately. Otherwise, the client +// will wait until a connection becomes available or the RPC's deadline is +// reached. // -// By default, RPCs don't "wait for ready". +// By default, RPCs do not "wait for ready". func WaitForReady(waitForReady bool) CallOption { return FailFastCallOption{FailFast: !waitForReady} } @@ -308,7 +304,7 @@ func (o FailFastCallOption) before(c *callInfo) error { c.failFast = o.FailFast return nil } -func (o FailFastCallOption) after(c *callInfo, attempt *csAttempt) {} +func (o FailFastCallOption) after(*callInfo, *csAttempt) {} // OnFinish returns a CallOption that configures a callback to be called when // the call completes. The error passed to the callback is the status of the @@ -343,7 +339,7 @@ func (o OnFinishCallOption) before(c *callInfo) error { return nil } -func (o OnFinishCallOption) after(c *callInfo, attempt *csAttempt) {} +func (o OnFinishCallOption) after(*callInfo, *csAttempt) {} // MaxCallRecvMsgSize returns a CallOption which sets the maximum message size // in bytes the client can receive. If this is not set, gRPC uses the default @@ -367,7 +363,7 @@ func (o MaxRecvMsgSizeCallOption) before(c *callInfo) error { c.maxReceiveMessageSize = &o.MaxRecvMsgSize return nil } -func (o MaxRecvMsgSizeCallOption) after(c *callInfo, attempt *csAttempt) {} +func (o MaxRecvMsgSizeCallOption) after(*callInfo, *csAttempt) {} // MaxCallSendMsgSize returns a CallOption which sets the maximum message size // in bytes the client can send. If this is not set, gRPC uses the default @@ -391,7 +387,7 @@ func (o MaxSendMsgSizeCallOption) before(c *callInfo) error { c.maxSendMessageSize = &o.MaxSendMsgSize return nil } -func (o MaxSendMsgSizeCallOption) after(c *callInfo, attempt *csAttempt) {} +func (o MaxSendMsgSizeCallOption) after(*callInfo, *csAttempt) {} // PerRPCCredentials returns a CallOption that sets credentials.PerRPCCredentials // for a call. @@ -414,7 +410,7 @@ func (o PerRPCCredsCallOption) before(c *callInfo) error { c.creds = o.Creds return nil } -func (o PerRPCCredsCallOption) after(c *callInfo, attempt *csAttempt) {} +func (o PerRPCCredsCallOption) after(*callInfo, *csAttempt) {} // UseCompressor returns a CallOption which sets the compressor used when // sending the request. If WithCompressor is also set, UseCompressor has @@ -442,7 +438,7 @@ func (o CompressorCallOption) before(c *callInfo) error { c.compressorType = o.CompressorType return nil } -func (o CompressorCallOption) after(c *callInfo, attempt *csAttempt) {} +func (o CompressorCallOption) after(*callInfo, *csAttempt) {} // CallContentSubtype returns a CallOption that will set the content-subtype // for a call. For example, if content-subtype is "json", the Content-Type over @@ -479,7 +475,7 @@ func (o ContentSubtypeCallOption) before(c *callInfo) error { c.contentSubtype = o.ContentSubtype return nil } -func (o ContentSubtypeCallOption) after(c *callInfo, attempt *csAttempt) {} +func (o ContentSubtypeCallOption) after(*callInfo, *csAttempt) {} // ForceCodec returns a CallOption that will set codec to be used for all // request and response messages for a call. The result of calling Name() will @@ -515,10 +511,50 @@ type ForceCodecCallOption struct { } func (o ForceCodecCallOption) before(c *callInfo) error { - c.codec = o.Codec + c.codec = newCodecV1Bridge(o.Codec) return nil } -func (o ForceCodecCallOption) after(c *callInfo, attempt *csAttempt) {} +func (o ForceCodecCallOption) after(*callInfo, *csAttempt) {} + +// ForceCodecV2 returns a CallOption that will set codec to be used for all +// request and response messages for a call. The result of calling Name() will +// be used as the content-subtype after converting to lowercase, unless +// CallContentSubtype is also used. +// +// See Content-Type on +// https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md#requests for +// more details. Also see the documentation on RegisterCodec and +// CallContentSubtype for more details on the interaction between Codec and +// content-subtype. +// +// This function is provided for advanced users; prefer to use only +// CallContentSubtype to select a registered codec instead. +// +// # Experimental +// +// Notice: This API is EXPERIMENTAL and may be changed or removed in a +// later release. +func ForceCodecV2(codec encoding.CodecV2) CallOption { + return ForceCodecV2CallOption{CodecV2: codec} +} + +// ForceCodecV2CallOption is a CallOption that indicates the codec used for +// marshaling messages. +// +// # Experimental +// +// Notice: This type is EXPERIMENTAL and may be changed or removed in a +// later release. +type ForceCodecV2CallOption struct { + CodecV2 encoding.CodecV2 +} + +func (o ForceCodecV2CallOption) before(c *callInfo) error { + c.codec = o.CodecV2 + return nil +} + +func (o ForceCodecV2CallOption) after(*callInfo, *csAttempt) {} // CallCustomCodec behaves like ForceCodec, but accepts a grpc.Codec instead of // an encoding.Codec. @@ -540,10 +576,10 @@ type CustomCodecCallOption struct { } func (o CustomCodecCallOption) before(c *callInfo) error { - c.codec = o.Codec + c.codec = newCodecV0Bridge(o.Codec) return nil } -func (o CustomCodecCallOption) after(c *callInfo, attempt *csAttempt) {} +func (o CustomCodecCallOption) after(*callInfo, *csAttempt) {} // MaxRetryRPCBufferSize returns a CallOption that limits the amount of memory // used for buffering this RPC's requests for retry purposes. @@ -571,7 +607,7 @@ func (o MaxRetryRPCBufferSizeCallOption) before(c *callInfo) error { c.maxRetryRPCBufferSize = o.MaxRetryRPCBufferSize return nil } -func (o MaxRetryRPCBufferSizeCallOption) after(c *callInfo, attempt *csAttempt) {} +func (o MaxRetryRPCBufferSizeCallOption) after(*callInfo, *csAttempt) {} // The format of the payload: compressed or not? type payloadFormat uint8 @@ -581,19 +617,28 @@ const ( compressionMade payloadFormat = 1 // compressed ) +func (pf payloadFormat) isCompressed() bool { + return pf == compressionMade +} + +type streamReader interface { + ReadHeader(header []byte) error + Read(n int) (mem.BufferSlice, error) +} + // parser reads complete gRPC messages from the underlying reader. type parser struct { // r is the underlying reader. // See the comment on recvMsg for the permissible // error types. - r io.Reader + r streamReader // The header of a gRPC message. Find more detail at // https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md header [5]byte - // recvBufferPool is the pool of shared receive buffers. - recvBufferPool SharedBufferPool + // bufferPool is the pool of shared receive buffers. + bufferPool mem.BufferPool } // recvMsg reads a complete gRPC message from the stream. @@ -608,14 +653,15 @@ type parser struct { // - an error from the status package // // No other error values or types must be returned, which also means -// that the underlying io.Reader must not return an incompatible +// that the underlying streamReader must not return an incompatible // error. -func (p *parser) recvMsg(maxReceiveMessageSize int) (pf payloadFormat, msg []byte, err error) { - if _, err := p.r.Read(p.header[:]); err != nil { +func (p *parser) recvMsg(maxReceiveMessageSize int) (payloadFormat, mem.BufferSlice, error) { + err := p.r.ReadHeader(p.header[:]) + if err != nil { return 0, nil, err } - pf = payloadFormat(p.header[0]) + pf := payloadFormat(p.header[0]) length := binary.BigEndian.Uint32(p.header[1:]) if length == 0 { @@ -627,20 +673,21 @@ func (p *parser) recvMsg(maxReceiveMessageSize int) (pf payloadFormat, msg []byt if int(length) > maxReceiveMessageSize { return 0, nil, status.Errorf(codes.ResourceExhausted, "grpc: received message larger than max (%d vs. %d)", length, maxReceiveMessageSize) } - msg = p.recvBufferPool.Get(int(length)) - if _, err := p.r.Read(msg); err != nil { + + data, err := p.r.Read(int(length)) + if err != nil { if err == io.EOF { err = io.ErrUnexpectedEOF } return 0, nil, err } - return pf, msg, nil + return pf, data, nil } // encode serializes msg and returns a buffer containing the message, or an // error if it is too large to be transmitted by grpc. If msg is nil, it // generates an empty message. -func encode(c baseCodec, msg any) ([]byte, error) { +func encode(c baseCodec, msg any) (mem.BufferSlice, error) { if msg == nil { // NOTE: typed nils will not be caught by this check return nil, nil } @@ -648,7 +695,8 @@ func encode(c baseCodec, msg any) ([]byte, error) { if err != nil { return nil, status.Errorf(codes.Internal, "grpc: error while marshaling: %v", err.Error()) } - if uint(len(b)) > math.MaxUint32 { + if uint(b.Len()) > math.MaxUint32 { + b.Free() return nil, status.Errorf(codes.ResourceExhausted, "grpc: message too large (%d bytes)", len(b)) } return b, nil @@ -659,34 +707,41 @@ func encode(c baseCodec, msg any) ([]byte, error) { // indicating no compression was done. // // TODO(dfawley): eliminate cp parameter by wrapping Compressor in an encoding.Compressor. -func compress(in []byte, cp Compressor, compressor encoding.Compressor) ([]byte, error) { - if compressor == nil && cp == nil { - return nil, nil - } - if len(in) == 0 { - return nil, nil +func compress(in mem.BufferSlice, cp Compressor, compressor encoding.Compressor, pool mem.BufferPool) (mem.BufferSlice, payloadFormat, error) { + if (compressor == nil && cp == nil) || in.Len() == 0 { + return nil, compressionNone, nil } + var out mem.BufferSlice + w := mem.NewWriter(&out, pool) wrapErr := func(err error) error { + out.Free() return status.Errorf(codes.Internal, "grpc: error while compressing: %v", err.Error()) } - cbuf := &bytes.Buffer{} if compressor != nil { - z, err := compressor.Compress(cbuf) + z, err := compressor.Compress(w) if err != nil { - return nil, wrapErr(err) + return nil, 0, wrapErr(err) } - if _, err := z.Write(in); err != nil { - return nil, wrapErr(err) + for _, b := range in { + if _, err := z.Write(b.ReadOnlyData()); err != nil { + return nil, 0, wrapErr(err) + } } if err := z.Close(); err != nil { - return nil, wrapErr(err) + return nil, 0, wrapErr(err) } } else { - if err := cp.Do(cbuf, in); err != nil { - return nil, wrapErr(err) + // This is obviously really inefficient since it fully materializes the data, but + // there is no way around this with the old Compressor API. At least it attempts + // to return the buffer to the provider, in the hopes it can be reused (maybe + // even by a subsequent call to this very function). + buf := in.MaterializeToBuffer(pool) + defer buf.Free() + if err := cp.Do(w, buf.ReadOnlyData()); err != nil { + return nil, 0, wrapErr(err) } } - return cbuf.Bytes(), nil + return out, compressionMade, nil } const ( @@ -697,33 +752,36 @@ const ( // msgHeader returns a 5-byte header for the message being transmitted and the // payload, which is compData if non-nil or data otherwise. -func msgHeader(data, compData []byte) (hdr []byte, payload []byte) { +func msgHeader(data, compData mem.BufferSlice, pf payloadFormat) (hdr []byte, payload mem.BufferSlice) { hdr = make([]byte, headerLen) - if compData != nil { - hdr[0] = byte(compressionMade) - data = compData + hdr[0] = byte(pf) + + var length uint32 + if pf.isCompressed() { + length = uint32(compData.Len()) + payload = compData } else { - hdr[0] = byte(compressionNone) + length = uint32(data.Len()) + payload = data } // Write length of payload into buf - binary.BigEndian.PutUint32(hdr[payloadLen:], uint32(len(data))) - return hdr, data + binary.BigEndian.PutUint32(hdr[payloadLen:], length) + return hdr, payload } -func outPayload(client bool, msg any, data, payload []byte, t time.Time) *stats.OutPayload { +func outPayload(client bool, msg any, dataLength, payloadLength int, t time.Time) *stats.OutPayload { return &stats.OutPayload{ Client: client, Payload: msg, - Data: data, - Length: len(data), - WireLength: len(payload) + headerLen, - CompressedLength: len(payload), + Length: dataLength, + WireLength: payloadLength + headerLen, + CompressedLength: payloadLength, SentTime: t, } } -func checkRecvPayload(pf payloadFormat, recvCompress string, haveCompressor bool) *status.Status { +func checkRecvPayload(pf payloadFormat, recvCompress string, haveCompressor bool, isServer bool) *status.Status { switch pf { case compressionNone: case compressionMade: @@ -731,7 +789,10 @@ func checkRecvPayload(pf payloadFormat, recvCompress string, haveCompressor bool return status.New(codes.Internal, "grpc: compressed flag set with identity or empty encoding") } if !haveCompressor { - return status.Newf(codes.Unimplemented, "grpc: Decompressor is not installed for grpc-encoding %q", recvCompress) + if isServer { + return status.Newf(codes.Unimplemented, "grpc: Decompressor is not installed for grpc-encoding %q", recvCompress) + } + return status.Newf(codes.Internal, "grpc: Decompressor is not installed for grpc-encoding %q", recvCompress) } default: return status.Newf(codes.Internal, "grpc: received unexpected payload format %d", pf) @@ -741,104 +802,129 @@ func checkRecvPayload(pf payloadFormat, recvCompress string, haveCompressor bool type payloadInfo struct { compressedLength int // The compressed length got from wire. - uncompressedBytes []byte + uncompressedBytes mem.BufferSlice +} + +func (p *payloadInfo) free() { + if p != nil && p.uncompressedBytes != nil { + p.uncompressedBytes.Free() + } } // recvAndDecompress reads a message from the stream, decompressing it if necessary. // // Cancelling the returned cancel function releases the buffer back to the pool. So the caller should cancel as soon as // the buffer is no longer needed. -func recvAndDecompress(p *parser, s *transport.Stream, dc Decompressor, maxReceiveMessageSize int, payInfo *payloadInfo, compressor encoding.Compressor, -) (uncompressedBuf []byte, cancel func(), err error) { - pf, compressedBuf, err := p.recvMsg(maxReceiveMessageSize) +// TODO: Refactor this function to reduce the number of arguments. +// See: https://google.github.io/styleguide/go/best-practices.html#function-argument-lists +func recvAndDecompress(p *parser, s *transport.Stream, dc Decompressor, maxReceiveMessageSize int, payInfo *payloadInfo, compressor encoding.Compressor, isServer bool, +) (out mem.BufferSlice, err error) { + pf, compressed, err := p.recvMsg(maxReceiveMessageSize) if err != nil { - return nil, nil, err + return nil, err } - if st := checkRecvPayload(pf, s.RecvCompress(), compressor != nil || dc != nil); st != nil { - return nil, nil, st.Err() + compressedLength := compressed.Len() + + if st := checkRecvPayload(pf, s.RecvCompress(), compressor != nil || dc != nil, isServer); st != nil { + compressed.Free() + return nil, st.Err() } var size int - if pf == compressionMade { + if pf.isCompressed() { + defer compressed.Free() + // To match legacy behavior, if the decompressor is set by WithDecompressor or RPCDecompressor, // use this decompressor as the default. if dc != nil { - uncompressedBuf, err = dc.Do(bytes.NewReader(compressedBuf)) + var uncompressedBuf []byte + uncompressedBuf, err = dc.Do(compressed.Reader()) + if err == nil { + out = mem.BufferSlice{mem.NewBuffer(&uncompressedBuf, nil)} + } size = len(uncompressedBuf) } else { - uncompressedBuf, size, err = decompress(compressor, compressedBuf, maxReceiveMessageSize) + out, size, err = decompress(compressor, compressed, maxReceiveMessageSize, p.bufferPool) } if err != nil { - return nil, nil, status.Errorf(codes.Internal, "grpc: failed to decompress the received message: %v", err) + return nil, status.Errorf(codes.Internal, "grpc: failed to decompress the received message: %v", err) } if size > maxReceiveMessageSize { + out.Free() // TODO: Revisit the error code. Currently keep it consistent with java // implementation. - return nil, nil, status.Errorf(codes.ResourceExhausted, "grpc: received message after decompression larger than max (%d vs. %d)", size, maxReceiveMessageSize) + return nil, status.Errorf(codes.ResourceExhausted, "grpc: received message after decompression larger than max (%d vs. %d)", size, maxReceiveMessageSize) } } else { - uncompressedBuf = compressedBuf + out = compressed } if payInfo != nil { - payInfo.compressedLength = len(compressedBuf) - payInfo.uncompressedBytes = uncompressedBuf - - cancel = func() {} - } else { - cancel = func() { - p.recvBufferPool.Put(&compressedBuf) - } + payInfo.compressedLength = compressedLength + out.Ref() + payInfo.uncompressedBytes = out } - return uncompressedBuf, cancel, nil + return out, nil } // Using compressor, decompress d, returning data and size. // Optionally, if data will be over maxReceiveMessageSize, just return the size. -func decompress(compressor encoding.Compressor, d []byte, maxReceiveMessageSize int) ([]byte, int, error) { - dcReader, err := compressor.Decompress(bytes.NewReader(d)) +func decompress(compressor encoding.Compressor, d mem.BufferSlice, maxReceiveMessageSize int, pool mem.BufferPool) (mem.BufferSlice, int, error) { + dcReader, err := compressor.Decompress(d.Reader()) if err != nil { return nil, 0, err } - if sizer, ok := compressor.(interface { - DecompressedSize(compressedBytes []byte) int - }); ok { - if size := sizer.DecompressedSize(d); size >= 0 { - if size > maxReceiveMessageSize { - return nil, size, nil - } - // size is used as an estimate to size the buffer, but we - // will read more data if available. - // +MinRead so ReadFrom will not reallocate if size is correct. - // - // TODO: If we ensure that the buffer size is the same as the DecompressedSize, - // we can also utilize the recv buffer pool here. - buf := bytes.NewBuffer(make([]byte, 0, size+bytes.MinRead)) - bytesRead, err := buf.ReadFrom(io.LimitReader(dcReader, int64(maxReceiveMessageSize)+1)) - return buf.Bytes(), int(bytesRead), err - } + + // TODO: Can/should this still be preserved with the new BufferSlice API? Are + // there any actual benefits to allocating a single large buffer instead of + // multiple smaller ones? + //if sizer, ok := compressor.(interface { + // DecompressedSize(compressedBytes []byte) int + //}); ok { + // if size := sizer.DecompressedSize(d); size >= 0 { + // if size > maxReceiveMessageSize { + // return nil, size, nil + // } + // // size is used as an estimate to size the buffer, but we + // // will read more data if available. + // // +MinRead so ReadFrom will not reallocate if size is correct. + // // + // // TODO: If we ensure that the buffer size is the same as the DecompressedSize, + // // we can also utilize the recv buffer pool here. + // buf := bytes.NewBuffer(make([]byte, 0, size+bytes.MinRead)) + // bytesRead, err := buf.ReadFrom(io.LimitReader(dcReader, int64(maxReceiveMessageSize)+1)) + // return buf.Bytes(), int(bytesRead), err + // } + //} + + var out mem.BufferSlice + _, err = io.Copy(mem.NewWriter(&out, pool), io.LimitReader(dcReader, int64(maxReceiveMessageSize)+1)) + if err != nil { + out.Free() + return nil, 0, err } - // Read from LimitReader with limit max+1. So if the underlying - // reader is over limit, the result will be bigger than max. - d, err = io.ReadAll(io.LimitReader(dcReader, int64(maxReceiveMessageSize)+1)) - return d, len(d), err + return out, out.Len(), nil } // For the two compressor parameters, both should not be set, but if they are, // dc takes precedence over compressor. // TODO(dfawley): wrap the old compressor/decompressor using the new API? -func recv(p *parser, c baseCodec, s *transport.Stream, dc Decompressor, m any, maxReceiveMessageSize int, payInfo *payloadInfo, compressor encoding.Compressor) error { - buf, cancel, err := recvAndDecompress(p, s, dc, maxReceiveMessageSize, payInfo, compressor) +func recv(p *parser, c baseCodec, s *transport.Stream, dc Decompressor, m any, maxReceiveMessageSize int, payInfo *payloadInfo, compressor encoding.Compressor, isServer bool) error { + data, err := recvAndDecompress(p, s, dc, maxReceiveMessageSize, payInfo, compressor, isServer) if err != nil { return err } - defer cancel() - if err := c.Unmarshal(buf, m); err != nil { + // If the codec wants its own reference to the data, it can get it. Otherwise, always + // free the buffers. + defer data.Free() + + if err := c.Unmarshal(data, m); err != nil { return status.Errorf(codes.Internal, "grpc: failed to unmarshal the received message: %v", err) } + return nil } @@ -941,7 +1027,7 @@ func setCallInfoCodec(c *callInfo) error { // encoding.Codec (Name vs. String method name). We only support // setting content subtype from encoding.Codec to avoid a behavior // change with the deprecated version. - if ec, ok := c.codec.(encoding.Codec); ok { + if ec, ok := c.codec.(encoding.CodecV2); ok { c.contentSubtype = strings.ToLower(ec.Name()) } } @@ -950,12 +1036,12 @@ func setCallInfoCodec(c *callInfo) error { if c.contentSubtype == "" { // No codec specified in CallOptions; use proto by default. - c.codec = encoding.GetCodec(proto.Name) + c.codec = getCodec(proto.Name) return nil } // c.contentSubtype is already lowercased in CallContentSubtype - c.codec = encoding.GetCodec(c.contentSubtype) + c.codec = getCodec(c.contentSubtype) if c.codec == nil { return status.Errorf(codes.Internal, "no codec registered for content-subtype %s", c.contentSubtype) } @@ -964,7 +1050,7 @@ func setCallInfoCodec(c *callInfo) error { // The SupportPackageIsVersion variables are referenced from generated protocol // buffer files to ensure compatibility with the gRPC version used. The latest -// support package version is 7. +// support package version is 9. // // Older versions are kept for compatibility. // @@ -976,6 +1062,7 @@ const ( SupportPackageIsVersion6 = true SupportPackageIsVersion7 = true SupportPackageIsVersion8 = true + SupportPackageIsVersion9 = true ) const grpcUA = "grpc-go/" + Version diff --git a/vendor/google.golang.org/grpc/server.go b/vendor/google.golang.org/grpc/server.go index fd4558daa..d1e1415a4 100644 --- a/vendor/google.golang.org/grpc/server.go +++ b/vendor/google.golang.org/grpc/server.go @@ -45,6 +45,7 @@ import ( "google.golang.org/grpc/internal/grpcutil" "google.golang.org/grpc/internal/transport" "google.golang.org/grpc/keepalive" + "google.golang.org/grpc/mem" "google.golang.org/grpc/metadata" "google.golang.org/grpc/peer" "google.golang.org/grpc/stats" @@ -80,7 +81,7 @@ func init() { } internal.BinaryLogger = binaryLogger internal.JoinServerOptions = newJoinServerOption - internal.RecvBufferPool = recvBufferPool + internal.BufferPool = bufferPool } var statusOK = status.New(codes.OK, "") @@ -170,7 +171,7 @@ type serverOptions struct { maxHeaderListSize *uint32 headerTableSize *uint32 numServerWorkers uint32 - recvBufferPool SharedBufferPool + bufferPool mem.BufferPool waitForHandlers bool } @@ -181,7 +182,7 @@ var defaultServerOptions = serverOptions{ connectionTimeout: 120 * time.Second, writeBufferSize: defaultWriteBufSize, readBufferSize: defaultReadBufSize, - recvBufferPool: nopBufferPool{}, + bufferPool: mem.DefaultBufferPool(), } var globalServerOptions []ServerOption @@ -313,7 +314,7 @@ func KeepaliveEnforcementPolicy(kep keepalive.EnforcementPolicy) ServerOption { // Will be supported throughout 1.x. func CustomCodec(codec Codec) ServerOption { return newFuncServerOption(func(o *serverOptions) { - o.codec = codec + o.codec = newCodecV0Bridge(codec) }) } @@ -342,7 +343,22 @@ func CustomCodec(codec Codec) ServerOption { // later release. func ForceServerCodec(codec encoding.Codec) ServerOption { return newFuncServerOption(func(o *serverOptions) { - o.codec = codec + o.codec = newCodecV1Bridge(codec) + }) +} + +// ForceServerCodecV2 is the equivalent of ForceServerCodec, but for the new +// CodecV2 interface. +// +// Will be supported throughout 1.x. +// +// # Experimental +// +// Notice: This API is EXPERIMENTAL and may be changed or removed in a +// later release. +func ForceServerCodecV2(codecV2 encoding.CodecV2) ServerOption { + return newFuncServerOption(func(o *serverOptions) { + o.codec = codecV2 }) } @@ -527,12 +543,22 @@ func ConnectionTimeout(d time.Duration) ServerOption { }) } +// MaxHeaderListSizeServerOption is a ServerOption that sets the max +// (uncompressed) size of header list that the server is prepared to accept. +type MaxHeaderListSizeServerOption struct { + MaxHeaderListSize uint32 +} + +func (o MaxHeaderListSizeServerOption) apply(so *serverOptions) { + so.maxHeaderListSize = &o.MaxHeaderListSize +} + // MaxHeaderListSize returns a ServerOption that sets the max (uncompressed) size // of header list that the server is prepared to accept. func MaxHeaderListSize(s uint32) ServerOption { - return newFuncServerOption(func(o *serverOptions) { - o.maxHeaderListSize = &s - }) + return MaxHeaderListSizeServerOption{ + MaxHeaderListSize: s, + } } // HeaderTableSize returns a ServerOption that sets the size of dynamic @@ -582,26 +608,9 @@ func WaitForHandlers(w bool) ServerOption { }) } -// RecvBufferPool returns a ServerOption that configures the server -// to use the provided shared buffer pool for parsing incoming messages. Depending -// on the application's workload, this could result in reduced memory allocation. -// -// If you are unsure about how to implement a memory pool but want to utilize one, -// begin with grpc.NewSharedBufferPool. -// -// Note: The shared buffer pool feature will not be active if any of the following -// options are used: StatsHandler, EnableTracing, or binary logging. In such -// cases, the shared buffer pool will be ignored. -// -// Deprecated: use experimental.WithRecvBufferPool instead. Will be deleted in -// v1.60.0 or later. -func RecvBufferPool(bufferPool SharedBufferPool) ServerOption { - return recvBufferPool(bufferPool) -} - -func recvBufferPool(bufferPool SharedBufferPool) ServerOption { +func bufferPool(bufferPool mem.BufferPool) ServerOption { return newFuncServerOption(func(o *serverOptions) { - o.recvBufferPool = bufferPool + o.bufferPool = bufferPool }) } @@ -612,7 +621,7 @@ func recvBufferPool(bufferPool SharedBufferPool) ServerOption { // workload (assuming a QPS of a few thousand requests/sec). const serverWorkerResetThreshold = 1 << 16 -// serverWorkers blocks on a *transport.Stream channel forever and waits for +// serverWorker blocks on a *transport.Stream channel forever and waits for // data to be fed by serveStreams. This allows multiple requests to be // processed by the same goroutine, removing the need for expensive stack // re-allocations (see the runtime.morestack problem [1]). @@ -970,6 +979,7 @@ func (s *Server) newHTTP2Transport(c net.Conn) transport.ServerTransport { ChannelzParent: s.channelz, MaxHeaderListSize: s.opts.maxHeaderListSize, HeaderTableSize: s.opts.headerTableSize, + BufferPool: s.opts.bufferPool, } st, err := transport.NewServerTransport(c, config) if err != nil { @@ -1062,7 +1072,7 @@ var _ http.Handler = (*Server)(nil) // Notice: This API is EXPERIMENTAL and may be changed or removed in a // later release. func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { - st, err := transport.NewServerHandlerTransport(w, r, s.opts.statsHandlers) + st, err := transport.NewServerHandlerTransport(w, r, s.opts.statsHandlers, s.opts.bufferPool) if err != nil { // Errors returned from transport.NewServerHandlerTransport have // already been written to w. @@ -1132,20 +1142,35 @@ func (s *Server) sendResponse(ctx context.Context, t transport.ServerTransport, channelz.Error(logger, s.channelz, "grpc: server failed to encode response: ", err) return err } - compData, err := compress(data, cp, comp) + + compData, pf, err := compress(data, cp, comp, s.opts.bufferPool) if err != nil { + data.Free() channelz.Error(logger, s.channelz, "grpc: server failed to compress response: ", err) return err } - hdr, payload := msgHeader(data, compData) + + hdr, payload := msgHeader(data, compData, pf) + + defer func() { + compData.Free() + data.Free() + // payload does not need to be freed here, it is either data or compData, both of + // which are already freed. + }() + + dataLen := data.Len() + payloadLen := payload.Len() // TODO(dfawley): should we be checking len(data) instead? - if len(payload) > s.opts.maxSendMessageSize { - return status.Errorf(codes.ResourceExhausted, "grpc: trying to send message larger than max (%d vs. %d)", len(payload), s.opts.maxSendMessageSize) + if payloadLen > s.opts.maxSendMessageSize { + return status.Errorf(codes.ResourceExhausted, "grpc: trying to send message larger than max (%d vs. %d)", payloadLen, s.opts.maxSendMessageSize) } err = t.Write(stream, hdr, payload, opts) if err == nil { - for _, sh := range s.opts.statsHandlers { - sh.HandleRPC(ctx, outPayload(false, msg, data, payload, time.Now())) + if len(s.opts.statsHandlers) != 0 { + for _, sh := range s.opts.statsHandlers { + sh.HandleRPC(ctx, outPayload(false, msg, dataLen, payloadLen, time.Now())) + } } } return err @@ -1324,37 +1349,37 @@ func (s *Server) processUnaryRPC(ctx context.Context, t transport.ServerTranspor var payInfo *payloadInfo if len(shs) != 0 || len(binlogs) != 0 { payInfo = &payloadInfo{} + defer payInfo.free() } - d, cancel, err := recvAndDecompress(&parser{r: stream, recvBufferPool: s.opts.recvBufferPool}, stream, dc, s.opts.maxReceiveMessageSize, payInfo, decomp) + d, err := recvAndDecompress(&parser{r: stream, bufferPool: s.opts.bufferPool}, stream, dc, s.opts.maxReceiveMessageSize, payInfo, decomp, true) if err != nil { if e := t.WriteStatus(stream, status.Convert(err)); e != nil { channelz.Warningf(logger, s.channelz, "grpc: Server.processUnaryRPC failed to write status: %v", e) } return err } + defer d.Free() if channelz.IsOn() { t.IncrMsgRecv() } df := func(v any) error { - defer cancel() - if err := s.getCodec(stream.ContentSubtype()).Unmarshal(d, v); err != nil { return status.Errorf(codes.Internal, "grpc: error unmarshalling request: %v", err) } + for _, sh := range shs { sh.HandleRPC(ctx, &stats.InPayload{ RecvTime: time.Now(), Payload: v, - Length: len(d), + Length: d.Len(), WireLength: payInfo.compressedLength + headerLen, CompressedLength: payInfo.compressedLength, - Data: d, }) } if len(binlogs) != 0 { cm := &binarylog.ClientMessage{ - Message: d, + Message: d.Materialize(), } for _, binlog := range binlogs { binlog.Log(ctx, cm) @@ -1538,7 +1563,7 @@ func (s *Server) processStreamingRPC(ctx context.Context, t transport.ServerTran ctx: ctx, t: t, s: stream, - p: &parser{r: stream, recvBufferPool: s.opts.recvBufferPool}, + p: &parser{r: stream, bufferPool: s.opts.bufferPool}, codec: s.getCodec(stream.ContentSubtype()), maxReceiveMessageSize: s.opts.maxReceiveMessageSize, maxSendMessageSize: s.opts.maxSendMessageSize, @@ -1953,12 +1978,12 @@ func (s *Server) getCodec(contentSubtype string) baseCodec { return s.opts.codec } if contentSubtype == "" { - return encoding.GetCodec(proto.Name) + return getCodec(proto.Name) } - codec := encoding.GetCodec(contentSubtype) + codec := getCodec(contentSubtype) if codec == nil { logger.Warningf("Unsupported codec %q. Defaulting to %q for now. This will start to fail in future releases.", contentSubtype, proto.Name) - return encoding.GetCodec(proto.Name) + return getCodec(proto.Name) } return codec } diff --git a/vendor/google.golang.org/grpc/service_config.go b/vendor/google.golang.org/grpc/service_config.go index 2b35c5d21..2671c5ef6 100644 --- a/vendor/google.golang.org/grpc/service_config.go +++ b/vendor/google.golang.org/grpc/service_config.go @@ -26,6 +26,7 @@ import ( "time" "google.golang.org/grpc/balancer" + "google.golang.org/grpc/balancer/pickfirst" "google.golang.org/grpc/codes" "google.golang.org/grpc/internal" "google.golang.org/grpc/internal/balancer/gracefulswitch" @@ -163,16 +164,18 @@ type jsonSC struct { } func init() { - internal.ParseServiceConfig = parseServiceConfig + internal.ParseServiceConfig = func(js string) *serviceconfig.ParseResult { + return parseServiceConfig(js, defaultMaxCallAttempts) + } } -func parseServiceConfig(js string) *serviceconfig.ParseResult { +func parseServiceConfig(js string, maxAttempts int) *serviceconfig.ParseResult { if len(js) == 0 { return &serviceconfig.ParseResult{Err: fmt.Errorf("no JSON service config provided")} } var rsc jsonSC err := json.Unmarshal([]byte(js), &rsc) if err != nil { - logger.Warningf("grpc: unmarshaling service config %s: %v", js, err) + logger.Warningf("grpc: unmarshalling service config %s: %v", js, err) return &serviceconfig.ParseResult{Err: err} } sc := ServiceConfig{ @@ -183,12 +186,12 @@ func parseServiceConfig(js string) *serviceconfig.ParseResult { } c := rsc.LoadBalancingConfig if c == nil { - name := PickFirstBalancerName + name := pickfirst.Name if rsc.LoadBalancingPolicy != nil { name = *rsc.LoadBalancingPolicy } if balancer.Get(name) == nil { - name = PickFirstBalancerName + name = pickfirst.Name } cfg := []map[string]any{{name: struct{}{}}} strCfg, err := json.Marshal(cfg) @@ -218,8 +221,8 @@ func parseServiceConfig(js string) *serviceconfig.ParseResult { WaitForReady: m.WaitForReady, Timeout: (*time.Duration)(m.Timeout), } - if mc.RetryPolicy, err = convertRetryPolicy(m.RetryPolicy); err != nil { - logger.Warningf("grpc: unmarshaling service config %s: %v", js, err) + if mc.RetryPolicy, err = convertRetryPolicy(m.RetryPolicy, maxAttempts); err != nil { + logger.Warningf("grpc: unmarshalling service config %s: %v", js, err) return &serviceconfig.ParseResult{Err: err} } if m.MaxRequestMessageBytes != nil { @@ -239,13 +242,13 @@ func parseServiceConfig(js string) *serviceconfig.ParseResult { for i, n := range *m.Name { path, err := n.generatePath() if err != nil { - logger.Warningf("grpc: error unmarshaling service config %s due to methodConfig[%d]: %v", js, i, err) + logger.Warningf("grpc: error unmarshalling service config %s due to methodConfig[%d]: %v", js, i, err) return &serviceconfig.ParseResult{Err: err} } if _, ok := paths[path]; ok { err = errDuplicatedName - logger.Warningf("grpc: error unmarshaling service config %s due to methodConfig[%d]: %v", js, i, err) + logger.Warningf("grpc: error unmarshalling service config %s due to methodConfig[%d]: %v", js, i, err) return &serviceconfig.ParseResult{Err: err} } paths[path] = struct{}{} @@ -264,7 +267,7 @@ func parseServiceConfig(js string) *serviceconfig.ParseResult { return &serviceconfig.ParseResult{Config: &sc} } -func convertRetryPolicy(jrp *jsonRetryPolicy) (p *internalserviceconfig.RetryPolicy, err error) { +func convertRetryPolicy(jrp *jsonRetryPolicy, maxAttempts int) (p *internalserviceconfig.RetryPolicy, err error) { if jrp == nil { return nil, nil } @@ -278,17 +281,16 @@ func convertRetryPolicy(jrp *jsonRetryPolicy) (p *internalserviceconfig.RetryPol return nil, nil } + if jrp.MaxAttempts < maxAttempts { + maxAttempts = jrp.MaxAttempts + } rp := &internalserviceconfig.RetryPolicy{ - MaxAttempts: jrp.MaxAttempts, + MaxAttempts: maxAttempts, InitialBackoff: time.Duration(jrp.InitialBackoff), MaxBackoff: time.Duration(jrp.MaxBackoff), BackoffMultiplier: jrp.BackoffMultiplier, RetryableStatusCodes: make(map[codes.Code]bool), } - if rp.MaxAttempts > 5 { - // TODO(retry): Make the max maxAttempts configurable. - rp.MaxAttempts = 5 - } for _, code := range jrp.RetryableStatusCodes { rp.RetryableStatusCodes[code] = true } diff --git a/vendor/google.golang.org/grpc/shared_buffer_pool.go b/vendor/google.golang.org/grpc/shared_buffer_pool.go deleted file mode 100644 index 48a64cfe8..000000000 --- a/vendor/google.golang.org/grpc/shared_buffer_pool.go +++ /dev/null @@ -1,154 +0,0 @@ -/* - * - * Copyright 2023 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. - * - */ - -package grpc - -import "sync" - -// SharedBufferPool is a pool of buffers that can be shared, resulting in -// decreased memory allocation. Currently, in gRPC-go, it is only utilized -// for parsing incoming messages. -// -// # Experimental -// -// Notice: This API is EXPERIMENTAL and may be changed or removed in a -// later release. -type SharedBufferPool interface { - // Get returns a buffer with specified length from the pool. - // - // The returned byte slice may be not zero initialized. - Get(length int) []byte - - // Put returns a buffer to the pool. - Put(*[]byte) -} - -// NewSharedBufferPool creates a simple SharedBufferPool with buckets -// of different sizes to optimize memory usage. This prevents the pool from -// wasting large amounts of memory, even when handling messages of varying sizes. -// -// # Experimental -// -// Notice: This API is EXPERIMENTAL and may be changed or removed in a -// later release. -func NewSharedBufferPool() SharedBufferPool { - return &simpleSharedBufferPool{ - pools: [poolArraySize]simpleSharedBufferChildPool{ - newBytesPool(level0PoolMaxSize), - newBytesPool(level1PoolMaxSize), - newBytesPool(level2PoolMaxSize), - newBytesPool(level3PoolMaxSize), - newBytesPool(level4PoolMaxSize), - newBytesPool(0), - }, - } -} - -// simpleSharedBufferPool is a simple implementation of SharedBufferPool. -type simpleSharedBufferPool struct { - pools [poolArraySize]simpleSharedBufferChildPool -} - -func (p *simpleSharedBufferPool) Get(size int) []byte { - return p.pools[p.poolIdx(size)].Get(size) -} - -func (p *simpleSharedBufferPool) Put(bs *[]byte) { - p.pools[p.poolIdx(cap(*bs))].Put(bs) -} - -func (p *simpleSharedBufferPool) poolIdx(size int) int { - switch { - case size <= level0PoolMaxSize: - return level0PoolIdx - case size <= level1PoolMaxSize: - return level1PoolIdx - case size <= level2PoolMaxSize: - return level2PoolIdx - case size <= level3PoolMaxSize: - return level3PoolIdx - case size <= level4PoolMaxSize: - return level4PoolIdx - default: - return levelMaxPoolIdx - } -} - -const ( - level0PoolMaxSize = 16 // 16 B - level1PoolMaxSize = level0PoolMaxSize * 16 // 256 B - level2PoolMaxSize = level1PoolMaxSize * 16 // 4 KB - level3PoolMaxSize = level2PoolMaxSize * 16 // 64 KB - level4PoolMaxSize = level3PoolMaxSize * 16 // 1 MB -) - -const ( - level0PoolIdx = iota - level1PoolIdx - level2PoolIdx - level3PoolIdx - level4PoolIdx - levelMaxPoolIdx - poolArraySize -) - -type simpleSharedBufferChildPool interface { - Get(size int) []byte - Put(any) -} - -type bufferPool struct { - sync.Pool - - defaultSize int -} - -func (p *bufferPool) Get(size int) []byte { - bs := p.Pool.Get().(*[]byte) - - if cap(*bs) < size { - p.Pool.Put(bs) - - return make([]byte, size) - } - - return (*bs)[:size] -} - -func newBytesPool(size int) simpleSharedBufferChildPool { - return &bufferPool{ - Pool: sync.Pool{ - New: func() any { - bs := make([]byte, size) - return &bs - }, - }, - defaultSize: size, - } -} - -// nopBufferPool is a buffer pool just makes new buffer without pooling. -type nopBufferPool struct { -} - -func (nopBufferPool) Get(length int) []byte { - return make([]byte, length) -} - -func (nopBufferPool) Put(*[]byte) { -} diff --git a/vendor/google.golang.org/grpc/stats/stats.go b/vendor/google.golang.org/grpc/stats/stats.go index 4ab70e2d4..71195c494 100644 --- a/vendor/google.golang.org/grpc/stats/stats.go +++ b/vendor/google.golang.org/grpc/stats/stats.go @@ -73,10 +73,10 @@ func (*PickerUpdated) isRPCStats() {} type InPayload struct { // Client is true if this InPayload is from client side. Client bool - // Payload is the payload with original type. + // Payload is the payload with original type. This may be modified after + // the call to HandleRPC which provides the InPayload returns and must be + // copied if needed later. Payload any - // Data is the serialized message payload. - Data []byte // Length is the size of the uncompressed payload data. Does not include any // framing (gRPC or HTTP/2). @@ -143,10 +143,10 @@ func (s *InTrailer) isRPCStats() {} type OutPayload struct { // Client is true if this OutPayload is from client side. Client bool - // Payload is the payload with original type. + // Payload is the payload with original type. This may be modified after + // the call to HandleRPC which provides the OutPayload returns and must be + // copied if needed later. Payload any - // Data is the serialized message payload. - Data []byte // Length is the size of the uncompressed payload data. Does not include any // framing (gRPC or HTTP/2). Length int diff --git a/vendor/google.golang.org/grpc/stream.go b/vendor/google.golang.org/grpc/stream.go index d939ffc63..bb2b2a216 100644 --- a/vendor/google.golang.org/grpc/stream.go +++ b/vendor/google.golang.org/grpc/stream.go @@ -23,6 +23,7 @@ import ( "errors" "io" "math" + "math/rand" "strconv" "sync" "time" @@ -34,13 +35,13 @@ import ( "google.golang.org/grpc/internal/balancerload" "google.golang.org/grpc/internal/binarylog" "google.golang.org/grpc/internal/channelz" - "google.golang.org/grpc/internal/grpcrand" "google.golang.org/grpc/internal/grpcutil" imetadata "google.golang.org/grpc/internal/metadata" iresolver "google.golang.org/grpc/internal/resolver" "google.golang.org/grpc/internal/serviceconfig" istatus "google.golang.org/grpc/internal/status" "google.golang.org/grpc/internal/transport" + "google.golang.org/grpc/mem" "google.golang.org/grpc/metadata" "google.golang.org/grpc/peer" "google.golang.org/grpc/stats" @@ -359,7 +360,7 @@ func newClientStreamWithParams(ctx context.Context, desc *StreamDesc, cc *Client cs.attempt = a return nil } - if err := cs.withRetry(op, func() { cs.bufferForRetryLocked(0, op) }); err != nil { + if err := cs.withRetry(op, func() { cs.bufferForRetryLocked(0, op, nil) }); err != nil { return nil, err } @@ -516,7 +517,8 @@ func (a *csAttempt) newStream() error { return toRPCErr(nse.Err) } a.s = s - a.p = &parser{r: s, recvBufferPool: a.cs.cc.dopts.recvBufferPool} + a.ctx = s.Context() + a.p = &parser{r: s, bufferPool: a.cs.cc.dopts.copts.BufferPool} return nil } @@ -565,10 +567,15 @@ type clientStream struct { // place where we need to check if the attempt is nil. attempt *csAttempt // TODO(hedging): hedging will have multiple attempts simultaneously. - committed bool // active attempt committed for retry? - onCommit func() - buffer []func(a *csAttempt) error // operations to replay on retry - bufferSize int // current size of buffer + committed bool // active attempt committed for retry? + onCommit func() + replayBuffer []replayOp // operations to replay on retry + replayBufferSize int // current size of replayBuffer +} + +type replayOp struct { + op func(a *csAttempt) error + cleanup func() } // csAttempt implements a single transport stream attempt within a @@ -606,7 +613,12 @@ func (cs *clientStream) commitAttemptLocked() { cs.onCommit() } cs.committed = true - cs.buffer = nil + for _, op := range cs.replayBuffer { + if op.cleanup != nil { + op.cleanup() + } + } + cs.replayBuffer = nil } func (cs *clientStream) commitAttempt() { @@ -698,7 +710,7 @@ func (a *csAttempt) shouldRetry(err error) (bool, error) { if max := float64(rp.MaxBackoff); cur > max { cur = max } - dur = time.Duration(grpcrand.Int63n(int64(cur))) + dur = time.Duration(rand.Int63n(int64(cur))) cs.numRetriesSincePushback++ } @@ -731,7 +743,7 @@ func (cs *clientStream) retryLocked(attempt *csAttempt, lastErr error) error { // the stream is canceled. return err } - // Note that the first op in the replay buffer always sets cs.attempt + // Note that the first op in replayBuffer always sets cs.attempt // if it is able to pick a transport and create a stream. if lastErr = cs.replayBufferLocked(attempt); lastErr == nil { return nil @@ -760,7 +772,7 @@ func (cs *clientStream) withRetry(op func(a *csAttempt) error, onSuccess func()) // already be status errors. return toRPCErr(op(cs.attempt)) } - if len(cs.buffer) == 0 { + if len(cs.replayBuffer) == 0 { // For the first op, which controls creation of the stream and // assigns cs.attempt, we need to create a new attempt inline // before executing the first op. On subsequent ops, the attempt @@ -850,25 +862,26 @@ func (cs *clientStream) Trailer() metadata.MD { } func (cs *clientStream) replayBufferLocked(attempt *csAttempt) error { - for _, f := range cs.buffer { - if err := f(attempt); err != nil { + for _, f := range cs.replayBuffer { + if err := f.op(attempt); err != nil { return err } } return nil } -func (cs *clientStream) bufferForRetryLocked(sz int, op func(a *csAttempt) error) { +func (cs *clientStream) bufferForRetryLocked(sz int, op func(a *csAttempt) error, cleanup func()) { // Note: we still will buffer if retry is disabled (for transparent retries). if cs.committed { return } - cs.bufferSize += sz - if cs.bufferSize > cs.callInfo.maxRetryRPCBufferSize { + cs.replayBufferSize += sz + if cs.replayBufferSize > cs.callInfo.maxRetryRPCBufferSize { cs.commitAttemptLocked() + cleanup() return } - cs.buffer = append(cs.buffer, op) + cs.replayBuffer = append(cs.replayBuffer, replayOp{op: op, cleanup: cleanup}) } func (cs *clientStream) SendMsg(m any) (err error) { @@ -890,23 +903,50 @@ func (cs *clientStream) SendMsg(m any) (err error) { } // load hdr, payload, data - hdr, payload, data, err := prepareMsg(m, cs.codec, cs.cp, cs.comp) + hdr, data, payload, pf, err := prepareMsg(m, cs.codec, cs.cp, cs.comp, cs.cc.dopts.copts.BufferPool) if err != nil { return err } + defer func() { + data.Free() + // only free payload if compression was made, and therefore it is a different set + // of buffers from data. + if pf.isCompressed() { + payload.Free() + } + }() + + dataLen := data.Len() + payloadLen := payload.Len() // TODO(dfawley): should we be checking len(data) instead? - if len(payload) > *cs.callInfo.maxSendMessageSize { - return status.Errorf(codes.ResourceExhausted, "trying to send message larger than max (%d vs. %d)", len(payload), *cs.callInfo.maxSendMessageSize) + if payloadLen > *cs.callInfo.maxSendMessageSize { + return status.Errorf(codes.ResourceExhausted, "trying to send message larger than max (%d vs. %d)", payloadLen, *cs.callInfo.maxSendMessageSize) } + + // always take an extra ref in case data == payload (i.e. when the data isn't + // compressed). The original ref will always be freed by the deferred free above. + payload.Ref() op := func(a *csAttempt) error { - return a.sendMsg(m, hdr, payload, data) + return a.sendMsg(m, hdr, payload, dataLen, payloadLen) + } + + // onSuccess is invoked when the op is captured for a subsequent retry. If the + // stream was established by a previous message and therefore retries are + // disabled, onSuccess will not be invoked, and payloadRef can be freed + // immediately. + onSuccessCalled := false + err = cs.withRetry(op, func() { + cs.bufferForRetryLocked(len(hdr)+payloadLen, op, payload.Free) + onSuccessCalled = true + }) + if !onSuccessCalled { + payload.Free() } - err = cs.withRetry(op, func() { cs.bufferForRetryLocked(len(hdr)+len(payload), op) }) if len(cs.binlogs) != 0 && err == nil { cm := &binarylog.ClientMessage{ OnClientSide: true, - Message: data, + Message: data.Materialize(), } for _, binlog := range cs.binlogs { binlog.Log(cs.ctx, cm) @@ -923,6 +963,7 @@ func (cs *clientStream) RecvMsg(m any) error { var recvInfo *payloadInfo if len(cs.binlogs) != 0 { recvInfo = &payloadInfo{} + defer recvInfo.free() } err := cs.withRetry(func(a *csAttempt) error { return a.recvMsg(m, recvInfo) @@ -930,7 +971,7 @@ func (cs *clientStream) RecvMsg(m any) error { if len(cs.binlogs) != 0 && err == nil { sm := &binarylog.ServerMessage{ OnClientSide: true, - Message: recvInfo.uncompressedBytes, + Message: recvInfo.uncompressedBytes.Materialize(), } for _, binlog := range cs.binlogs { binlog.Log(cs.ctx, sm) @@ -957,7 +998,7 @@ func (cs *clientStream) CloseSend() error { // RecvMsg. This also matches historical behavior. return nil } - cs.withRetry(op, func() { cs.bufferForRetryLocked(0, op) }) + cs.withRetry(op, func() { cs.bufferForRetryLocked(0, op, nil) }) if len(cs.binlogs) != 0 { chc := &binarylog.ClientHalfClose{ OnClientSide: true, @@ -1033,7 +1074,7 @@ func (cs *clientStream) finish(err error) { cs.cancel() } -func (a *csAttempt) sendMsg(m any, hdr, payld, data []byte) error { +func (a *csAttempt) sendMsg(m any, hdr []byte, payld mem.BufferSlice, dataLength, payloadLength int) error { cs := a.cs if a.trInfo != nil { a.mu.Lock() @@ -1051,8 +1092,10 @@ func (a *csAttempt) sendMsg(m any, hdr, payld, data []byte) error { } return io.EOF } - for _, sh := range a.statsHandlers { - sh.HandleRPC(a.ctx, outPayload(true, m, data, payld, time.Now())) + if len(a.statsHandlers) != 0 { + for _, sh := range a.statsHandlers { + sh.HandleRPC(a.ctx, outPayload(true, m, dataLength, payloadLength, time.Now())) + } } if channelz.IsOn() { a.t.IncrMsgSent() @@ -1064,6 +1107,7 @@ func (a *csAttempt) recvMsg(m any, payInfo *payloadInfo) (err error) { cs := a.cs if len(a.statsHandlers) != 0 && payInfo == nil { payInfo = &payloadInfo{} + defer payInfo.free() } if !a.decompSet { @@ -1082,8 +1126,7 @@ func (a *csAttempt) recvMsg(m any, payInfo *payloadInfo) (err error) { // Only initialize this state once per stream. a.decompSet = true } - err = recv(a.p, cs.codec, a.s, a.dc, m, *cs.callInfo.maxReceiveMessageSize, payInfo, a.decomp) - if err != nil { + if err := recv(a.p, cs.codec, a.s, a.dc, m, *cs.callInfo.maxReceiveMessageSize, payInfo, a.decomp, false); err != nil { if err == io.EOF { if statusErr := a.s.Status().Err(); statusErr != nil { return statusErr @@ -1102,14 +1145,12 @@ func (a *csAttempt) recvMsg(m any, payInfo *payloadInfo) (err error) { } for _, sh := range a.statsHandlers { sh.HandleRPC(a.ctx, &stats.InPayload{ - Client: true, - RecvTime: time.Now(), - Payload: m, - // TODO truncate large payload. - Data: payInfo.uncompressedBytes, + Client: true, + RecvTime: time.Now(), + Payload: m, WireLength: payInfo.compressedLength + headerLen, CompressedLength: payInfo.compressedLength, - Length: len(payInfo.uncompressedBytes), + Length: payInfo.uncompressedBytes.Len(), }) } if channelz.IsOn() { @@ -1121,14 +1162,12 @@ func (a *csAttempt) recvMsg(m any, payInfo *payloadInfo) (err error) { } // Special handling for non-server-stream rpcs. // This recv expects EOF or errors, so we don't collect inPayload. - err = recv(a.p, cs.codec, a.s, a.dc, m, *cs.callInfo.maxReceiveMessageSize, nil, a.decomp) - if err == nil { - return toRPCErr(errors.New("grpc: client streaming protocol violation: get , want ")) - } - if err == io.EOF { + if err := recv(a.p, cs.codec, a.s, a.dc, m, *cs.callInfo.maxReceiveMessageSize, nil, a.decomp, false); err == io.EOF { return a.s.Status().Err() // non-server streaming Recv returns nil on success + } else if err != nil { + return toRPCErr(err) } - return toRPCErr(err) + return toRPCErr(errors.New("grpc: client streaming protocol violation: get , want ")) } func (a *csAttempt) finish(err error) { @@ -1184,12 +1223,12 @@ func (a *csAttempt) finish(err error) { a.mu.Unlock() } -// newClientStream creates a ClientStream with the specified transport, on the +// newNonRetryClientStream creates a ClientStream with the specified transport, on the // given addrConn. // // It's expected that the given transport is either the same one in addrConn, or // is already closed. To avoid race, transport is specified separately, instead -// of using ac.transpot. +// of using ac.transport. // // Main difference between this and ClientConn.NewStream: // - no retry @@ -1275,7 +1314,7 @@ func newNonRetryClientStream(ctx context.Context, desc *StreamDesc, method strin return nil, err } as.s = s - as.p = &parser{r: s, recvBufferPool: ac.dopts.recvBufferPool} + as.p = &parser{r: s, bufferPool: ac.dopts.copts.BufferPool} ac.incrCallsStarted() if desc != unaryStreamDesc { // Listen on stream context to cleanup when the stream context is @@ -1372,17 +1411,26 @@ func (as *addrConnStream) SendMsg(m any) (err error) { } // load hdr, payload, data - hdr, payld, _, err := prepareMsg(m, as.codec, as.cp, as.comp) + hdr, data, payload, pf, err := prepareMsg(m, as.codec, as.cp, as.comp, as.ac.dopts.copts.BufferPool) if err != nil { return err } + defer func() { + data.Free() + // only free payload if compression was made, and therefore it is a different set + // of buffers from data. + if pf.isCompressed() { + payload.Free() + } + }() + // TODO(dfawley): should we be checking len(data) instead? - if len(payld) > *as.callInfo.maxSendMessageSize { - return status.Errorf(codes.ResourceExhausted, "trying to send message larger than max (%d vs. %d)", len(payld), *as.callInfo.maxSendMessageSize) + if payload.Len() > *as.callInfo.maxSendMessageSize { + return status.Errorf(codes.ResourceExhausted, "trying to send message larger than max (%d vs. %d)", payload.Len(), *as.callInfo.maxSendMessageSize) } - if err := as.t.Write(as.s, hdr, payld, &transport.Options{Last: !as.desc.ClientStreams}); err != nil { + if err := as.t.Write(as.s, hdr, payload, &transport.Options{Last: !as.desc.ClientStreams}); err != nil { if !as.desc.ClientStreams { // For non-client-streaming RPCs, we return nil instead of EOF on error // because the generated code requires it. finish is not called; RecvMsg() @@ -1422,8 +1470,7 @@ func (as *addrConnStream) RecvMsg(m any) (err error) { // Only initialize this state once per stream. as.decompSet = true } - err = recv(as.p, as.codec, as.s, as.dc, m, *as.callInfo.maxReceiveMessageSize, nil, as.decomp) - if err != nil { + if err := recv(as.p, as.codec, as.s, as.dc, m, *as.callInfo.maxReceiveMessageSize, nil, as.decomp, false); err != nil { if err == io.EOF { if statusErr := as.s.Status().Err(); statusErr != nil { return statusErr @@ -1443,14 +1490,12 @@ func (as *addrConnStream) RecvMsg(m any) (err error) { // Special handling for non-server-stream rpcs. // This recv expects EOF or errors, so we don't collect inPayload. - err = recv(as.p, as.codec, as.s, as.dc, m, *as.callInfo.maxReceiveMessageSize, nil, as.decomp) - if err == nil { - return toRPCErr(errors.New("grpc: client streaming protocol violation: get , want ")) - } - if err == io.EOF { + if err := recv(as.p, as.codec, as.s, as.dc, m, *as.callInfo.maxReceiveMessageSize, nil, as.decomp, false); err == io.EOF { return as.s.Status().Err() // non-server streaming Recv returns nil on success + } else if err != nil { + return toRPCErr(err) } - return toRPCErr(err) + return toRPCErr(errors.New("grpc: client streaming protocol violation: get , want ")) } func (as *addrConnStream) finish(err error) { @@ -1644,18 +1689,31 @@ func (ss *serverStream) SendMsg(m any) (err error) { } // load hdr, payload, data - hdr, payload, data, err := prepareMsg(m, ss.codec, ss.cp, ss.comp) + hdr, data, payload, pf, err := prepareMsg(m, ss.codec, ss.cp, ss.comp, ss.p.bufferPool) if err != nil { return err } + defer func() { + data.Free() + // only free payload if compression was made, and therefore it is a different set + // of buffers from data. + if pf.isCompressed() { + payload.Free() + } + }() + + dataLen := data.Len() + payloadLen := payload.Len() + // TODO(dfawley): should we be checking len(data) instead? - if len(payload) > ss.maxSendMessageSize { - return status.Errorf(codes.ResourceExhausted, "trying to send message larger than max (%d vs. %d)", len(payload), ss.maxSendMessageSize) + if payloadLen > ss.maxSendMessageSize { + return status.Errorf(codes.ResourceExhausted, "trying to send message larger than max (%d vs. %d)", payloadLen, ss.maxSendMessageSize) } if err := ss.t.Write(ss.s, hdr, payload, &transport.Options{Last: false}); err != nil { return toRPCErr(err) } + if len(ss.binlogs) != 0 { if !ss.serverHeaderBinlogged { h, _ := ss.s.Header() @@ -1668,7 +1726,7 @@ func (ss *serverStream) SendMsg(m any) (err error) { } } sm := &binarylog.ServerMessage{ - Message: data, + Message: data.Materialize(), } for _, binlog := range ss.binlogs { binlog.Log(ss.ctx, sm) @@ -1676,7 +1734,7 @@ func (ss *serverStream) SendMsg(m any) (err error) { } if len(ss.statsHandler) != 0 { for _, sh := range ss.statsHandler { - sh.HandleRPC(ss.s.Context(), outPayload(false, m, data, payload, time.Now())) + sh.HandleRPC(ss.s.Context(), outPayload(false, m, dataLen, payloadLen, time.Now())) } } return nil @@ -1713,8 +1771,9 @@ func (ss *serverStream) RecvMsg(m any) (err error) { var payInfo *payloadInfo if len(ss.statsHandler) != 0 || len(ss.binlogs) != 0 { payInfo = &payloadInfo{} + defer payInfo.free() } - if err := recv(ss.p, ss.codec, ss.s, ss.dc, m, ss.maxReceiveMessageSize, payInfo, ss.decomp); err != nil { + if err := recv(ss.p, ss.codec, ss.s, ss.dc, m, ss.maxReceiveMessageSize, payInfo, ss.decomp, true); err != nil { if err == io.EOF { if len(ss.binlogs) != 0 { chc := &binarylog.ClientHalfClose{} @@ -1732,11 +1791,9 @@ func (ss *serverStream) RecvMsg(m any) (err error) { if len(ss.statsHandler) != 0 { for _, sh := range ss.statsHandler { sh.HandleRPC(ss.s.Context(), &stats.InPayload{ - RecvTime: time.Now(), - Payload: m, - // TODO truncate large payload. - Data: payInfo.uncompressedBytes, - Length: len(payInfo.uncompressedBytes), + RecvTime: time.Now(), + Payload: m, + Length: payInfo.uncompressedBytes.Len(), WireLength: payInfo.compressedLength + headerLen, CompressedLength: payInfo.compressedLength, }) @@ -1744,7 +1801,7 @@ func (ss *serverStream) RecvMsg(m any) (err error) { } if len(ss.binlogs) != 0 { cm := &binarylog.ClientMessage{ - Message: payInfo.uncompressedBytes, + Message: payInfo.uncompressedBytes.Materialize(), } for _, binlog := range ss.binlogs { binlog.Log(ss.ctx, cm) @@ -1759,23 +1816,26 @@ func MethodFromServerStream(stream ServerStream) (string, bool) { return Method(stream.Context()) } -// prepareMsg returns the hdr, payload and data -// using the compressors passed or using the -// passed preparedmsg -func prepareMsg(m any, codec baseCodec, cp Compressor, comp encoding.Compressor) (hdr, payload, data []byte, err error) { +// prepareMsg returns the hdr, payload and data using the compressors passed or +// using the passed preparedmsg. The returned boolean indicates whether +// compression was made and therefore whether the payload needs to be freed in +// addition to the returned data. Freeing the payload if the returned boolean is +// false can lead to undefined behavior. +func prepareMsg(m any, codec baseCodec, cp Compressor, comp encoding.Compressor, pool mem.BufferPool) (hdr []byte, data, payload mem.BufferSlice, pf payloadFormat, err error) { if preparedMsg, ok := m.(*PreparedMsg); ok { - return preparedMsg.hdr, preparedMsg.payload, preparedMsg.encodedData, nil + return preparedMsg.hdr, preparedMsg.encodedData, preparedMsg.payload, preparedMsg.pf, nil } // The input interface is not a prepared msg. // Marshal and Compress the data at this point data, err = encode(codec, m) if err != nil { - return nil, nil, nil, err + return nil, nil, nil, 0, err } - compData, err := compress(data, cp, comp) + compData, pf, err := compress(data, cp, comp, pool) if err != nil { - return nil, nil, nil, err + data.Free() + return nil, nil, nil, 0, err } - hdr, payload = msgHeader(data, compData) - return hdr, payload, data, nil + hdr, payload = msgHeader(data, compData, pf) + return hdr, data, payload, pf, nil } diff --git a/vendor/google.golang.org/grpc/stream_interfaces.go b/vendor/google.golang.org/grpc/stream_interfaces.go new file mode 100644 index 000000000..0037fee0b --- /dev/null +++ b/vendor/google.golang.org/grpc/stream_interfaces.go @@ -0,0 +1,238 @@ +/* + * + * Copyright 2024 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. + * + */ + +package grpc + +// ServerStreamingClient represents the client side of a server-streaming (one +// request, many responses) RPC. It is generic over the type of the response +// message. It is used in generated code. +type ServerStreamingClient[Res any] interface { + // Recv receives the next response message from the server. The client may + // repeatedly call Recv to read messages from the response stream. If + // io.EOF is returned, the stream has terminated with an OK status. Any + // other error is compatible with the status package and indicates the + // RPC's status code and message. + Recv() (*Res, error) + + // ClientStream is embedded to provide Context, Header, and Trailer + // functionality. No other methods in the ClientStream should be called + // directly. + ClientStream +} + +// ServerStreamingServer represents the server side of a server-streaming (one +// request, many responses) RPC. It is generic over the type of the response +// message. It is used in generated code. +// +// To terminate the response stream, return from the handler method and return +// an error from the status package, or use nil to indicate an OK status code. +type ServerStreamingServer[Res any] interface { + // Send sends a response message to the client. The server handler may + // call Send multiple times to send multiple messages to the client. An + // error is returned if the stream was terminated unexpectedly, and the + // handler method should return, as the stream is no longer usable. + Send(*Res) error + + // ServerStream is embedded to provide Context, SetHeader, SendHeader, and + // SetTrailer functionality. No other methods in the ServerStream should + // be called directly. + ServerStream +} + +// ClientStreamingClient represents the client side of a client-streaming (many +// requests, one response) RPC. It is generic over both the type of the request +// message stream and the type of the unary response message. It is used in +// generated code. +type ClientStreamingClient[Req any, Res any] interface { + // Send sends a request message to the server. The client may call Send + // multiple times to send multiple messages to the server. On error, Send + // aborts the stream. If the error was generated by the client, the status + // is returned directly. Otherwise, io.EOF is returned, and the status of + // the stream may be discovered using CloseAndRecv(). + Send(*Req) error + + // CloseAndRecv closes the request stream and waits for the server's + // response. This method must be called once and only once after sending + // all request messages. Any error returned is implemented by the status + // package. + CloseAndRecv() (*Res, error) + + // ClientStream is embedded to provide Context, Header, and Trailer + // functionality. No other methods in the ClientStream should be called + // directly. + ClientStream +} + +// ClientStreamingServer represents the server side of a client-streaming (many +// requests, one response) RPC. It is generic over both the type of the request +// message stream and the type of the unary response message. It is used in +// generated code. +// +// To terminate the RPC, call SendAndClose and return nil from the method +// handler or do not call SendAndClose and return an error from the status +// package. +type ClientStreamingServer[Req any, Res any] interface { + // Recv receives the next request message from the client. The server may + // repeatedly call Recv to read messages from the request stream. If + // io.EOF is returned, it indicates the client called CloseAndRecv on its + // ClientStreamingClient. Any other error indicates the stream was + // terminated unexpectedly, and the handler method should return, as the + // stream is no longer usable. + Recv() (*Req, error) + + // SendAndClose sends a single response message to the client and closes + // the stream. This method must be called once and only once after all + // request messages have been processed. Recv should not be called after + // calling SendAndClose. + SendAndClose(*Res) error + + // ServerStream is embedded to provide Context, SetHeader, SendHeader, and + // SetTrailer functionality. No other methods in the ServerStream should + // be called directly. + ServerStream +} + +// BidiStreamingClient represents the client side of a bidirectional-streaming +// (many requests, many responses) RPC. It is generic over both the type of the +// request message stream and the type of the response message stream. It is +// used in generated code. +type BidiStreamingClient[Req any, Res any] interface { + // Send sends a request message to the server. The client may call Send + // multiple times to send multiple messages to the server. On error, Send + // aborts the stream. If the error was generated by the client, the status + // is returned directly. Otherwise, io.EOF is returned, and the status of + // the stream may be discovered using Recv(). + Send(*Req) error + + // Recv receives the next response message from the server. The client may + // repeatedly call Recv to read messages from the response stream. If + // io.EOF is returned, the stream has terminated with an OK status. Any + // other error is compatible with the status package and indicates the + // RPC's status code and message. + Recv() (*Res, error) + + // ClientStream is embedded to provide Context, Header, Trailer, and + // CloseSend functionality. No other methods in the ClientStream should be + // called directly. + ClientStream +} + +// BidiStreamingServer represents the server side of a bidirectional-streaming +// (many requests, many responses) RPC. It is generic over both the type of the +// request message stream and the type of the response message stream. It is +// used in generated code. +// +// To terminate the stream, return from the handler method and return +// an error from the status package, or use nil to indicate an OK status code. +type BidiStreamingServer[Req any, Res any] interface { + // Recv receives the next request message from the client. The server may + // repeatedly call Recv to read messages from the request stream. If + // io.EOF is returned, it indicates the client called CloseSend on its + // BidiStreamingClient. Any other error indicates the stream was + // terminated unexpectedly, and the handler method should return, as the + // stream is no longer usable. + Recv() (*Req, error) + + // Send sends a response message to the client. The server handler may + // call Send multiple times to send multiple messages to the client. An + // error is returned if the stream was terminated unexpectedly, and the + // handler method should return, as the stream is no longer usable. + Send(*Res) error + + // ServerStream is embedded to provide Context, SetHeader, SendHeader, and + // SetTrailer functionality. No other methods in the ServerStream should + // be called directly. + ServerStream +} + +// GenericClientStream implements the ServerStreamingClient, ClientStreamingClient, +// and BidiStreamingClient interfaces. It is used in generated code. +type GenericClientStream[Req any, Res any] struct { + ClientStream +} + +var _ ServerStreamingClient[string] = (*GenericClientStream[int, string])(nil) +var _ ClientStreamingClient[int, string] = (*GenericClientStream[int, string])(nil) +var _ BidiStreamingClient[int, string] = (*GenericClientStream[int, string])(nil) + +// Send pushes one message into the stream of requests to be consumed by the +// server. The type of message which can be sent is determined by the Req type +// parameter of the GenericClientStream receiver. +func (x *GenericClientStream[Req, Res]) Send(m *Req) error { + return x.ClientStream.SendMsg(m) +} + +// Recv reads one message from the stream of responses generated by the server. +// The type of the message returned is determined by the Res type parameter +// of the GenericClientStream receiver. +func (x *GenericClientStream[Req, Res]) Recv() (*Res, error) { + m := new(Res) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +// CloseAndRecv closes the sending side of the stream, then receives the unary +// response from the server. The type of message which it returns is determined +// by the Res type parameter of the GenericClientStream receiver. +func (x *GenericClientStream[Req, Res]) CloseAndRecv() (*Res, error) { + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + m := new(Res) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +// GenericServerStream implements the ServerStreamingServer, ClientStreamingServer, +// and BidiStreamingServer interfaces. It is used in generated code. +type GenericServerStream[Req any, Res any] struct { + ServerStream +} + +var _ ServerStreamingServer[string] = (*GenericServerStream[int, string])(nil) +var _ ClientStreamingServer[int, string] = (*GenericServerStream[int, string])(nil) +var _ BidiStreamingServer[int, string] = (*GenericServerStream[int, string])(nil) + +// Send pushes one message into the stream of responses to be consumed by the +// client. The type of message which can be sent is determined by the Res +// type parameter of the serverStreamServer receiver. +func (x *GenericServerStream[Req, Res]) Send(m *Res) error { + return x.ServerStream.SendMsg(m) +} + +// SendAndClose pushes the unary response to the client. The type of message +// which can be sent is determined by the Res type parameter of the +// clientStreamServer receiver. +func (x *GenericServerStream[Req, Res]) SendAndClose(m *Res) error { + return x.ServerStream.SendMsg(m) +} + +// Recv reads one message from the stream of requests generated by the client. +// The type of the message returned is determined by the Req type parameter +// of the clientStreamServer receiver. +func (x *GenericServerStream[Req, Res]) Recv() (*Req, error) { + m := new(Req) + if err := x.ServerStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} diff --git a/vendor/google.golang.org/grpc/version.go b/vendor/google.golang.org/grpc/version.go index 2556f7583..d50e84359 100644 --- a/vendor/google.golang.org/grpc/version.go +++ b/vendor/google.golang.org/grpc/version.go @@ -19,4 +19,4 @@ package grpc // Version is the current grpc version. -const Version = "1.63.2" +const Version = "1.68.0" diff --git a/vendor/google.golang.org/grpc/vet.sh b/vendor/google.golang.org/grpc/vet.sh deleted file mode 100644 index 7e6b92e49..000000000 --- a/vendor/google.golang.org/grpc/vet.sh +++ /dev/null @@ -1,195 +0,0 @@ -#!/bin/bash - -set -ex # Exit on error; debugging enabled. -set -o pipefail # Fail a pipe if any sub-command fails. - -# not makes sure the command passed to it does not exit with a return code of 0. -not() { - # This is required instead of the earlier (! $COMMAND) because subshells and - # pipefail don't work the same on Darwin as in Linux. - ! "$@" -} - -die() { - echo "$@" >&2 - exit 1 -} - -fail_on_output() { - tee /dev/stderr | not read -} - -# Check to make sure it's safe to modify the user's git repo. -git status --porcelain | fail_on_output - -# Undo any edits made by this script. -cleanup() { - git reset --hard HEAD -} -trap cleanup EXIT - -PATH="${HOME}/go/bin:${GOROOT}/bin:${PATH}" -go version - -if [[ "$1" = "-install" ]]; then - # Install the pinned versions as defined in module tools. - pushd ./test/tools - go install \ - golang.org/x/tools/cmd/goimports \ - honnef.co/go/tools/cmd/staticcheck \ - github.com/client9/misspell/cmd/misspell - popd - if [[ -z "${VET_SKIP_PROTO}" ]]; then - if [[ "${GITHUB_ACTIONS}" = "true" ]]; then - PROTOBUF_VERSION=25.2 # a.k.a. v4.22.0 in pb.go files. - PROTOC_FILENAME=protoc-${PROTOBUF_VERSION}-linux-x86_64.zip - pushd /home/runner/go - wget https://github.com/google/protobuf/releases/download/v${PROTOBUF_VERSION}/${PROTOC_FILENAME} - unzip ${PROTOC_FILENAME} - bin/protoc --version - popd - elif not which protoc > /dev/null; then - die "Please install protoc into your path" - fi - fi - exit 0 -elif [[ "$#" -ne 0 ]]; then - die "Unknown argument(s): $*" -fi - -# - Check that generated proto files are up to date. -if [[ -z "${VET_SKIP_PROTO}" ]]; then - make proto && git status --porcelain 2>&1 | fail_on_output || \ - (git status; git --no-pager diff; exit 1) -fi - -if [[ -n "${VET_ONLY_PROTO}" ]]; then - exit 0 -fi - -# - Ensure all source files contain a copyright message. -# (Done in two parts because Darwin "git grep" has broken support for compound -# exclusion matches.) -(grep -L "DO NOT EDIT" $(git grep -L "\(Copyright [0-9]\{4,\} gRPC authors\)" -- '*.go') || true) | fail_on_output - -# - Make sure all tests in grpc and grpc/test use leakcheck via Teardown. -not grep 'func Test[^(]' *_test.go -not grep 'func Test[^(]' test/*.go - -# - Check for typos in test function names -git grep 'func (s) ' -- "*_test.go" | not grep -v 'func (s) Test' -git grep 'func [A-Z]' -- "*_test.go" | not grep -v 'func Test\|Benchmark\|Example' - -# - Do not import x/net/context. -not git grep -l 'x/net/context' -- "*.go" - -# - Do not use time.After except in tests. It has the potential to leak the -# timer since there is no way to stop it early. -git grep -l 'time.After(' -- "*.go" | not grep -v '_test.go\|test_utils\|testutils' - -# - Do not import math/rand for real library code. Use internal/grpcrand for -# thread safety. -git grep -l '"math/rand"' -- "*.go" 2>&1 | not grep -v '^examples\|^interop/stress\|grpcrand\|^benchmark\|wrr_test' - -# - Do not use "interface{}"; use "any" instead. -git grep -l 'interface{}' -- "*.go" 2>&1 | not grep -v '\.pb\.go\|protoc-gen-go-grpc\|grpc_testing_not_regenerate' - -# - Do not call grpclog directly. Use grpclog.Component instead. -git grep -l -e 'grpclog.I' --or -e 'grpclog.W' --or -e 'grpclog.E' --or -e 'grpclog.F' --or -e 'grpclog.V' -- "*.go" | not grep -v '^grpclog/component.go\|^internal/grpctest/tlogger_test.go' - -# - Ensure all ptypes proto packages are renamed when importing. -not git grep "\(import \|^\s*\)\"github.com/golang/protobuf/ptypes/" -- "*.go" - -# - Ensure all usages of grpc_testing package are renamed when importing. -not git grep "\(import \|^\s*\)\"google.golang.org/grpc/interop/grpc_testing" -- "*.go" - -# - Ensure all xds proto imports are renamed to *pb or *grpc. -git grep '"github.com/envoyproxy/go-control-plane/envoy' -- '*.go' ':(exclude)*.pb.go' | not grep -v 'pb "\|grpc "' - -misspell -error . - -# - gofmt, goimports, go vet, go mod tidy. -# Perform these checks on each module inside gRPC. -for MOD_FILE in $(find . -name 'go.mod'); do - MOD_DIR=$(dirname ${MOD_FILE}) - pushd ${MOD_DIR} - go vet -all ./... | fail_on_output - gofmt -s -d -l . 2>&1 | fail_on_output - goimports -l . 2>&1 | not grep -vE "\.pb\.go" - - go mod tidy -compat=1.19 - git status --porcelain 2>&1 | fail_on_output || \ - (git status; git --no-pager diff; exit 1) - popd -done - -# - Collection of static analysis checks -SC_OUT="$(mktemp)" -staticcheck -go 1.19 -checks 'all' ./... > "${SC_OUT}" || true - -# Error for anything other than checks that need exclusions. -grep -v "(ST1000)" "${SC_OUT}" | grep -v "(SA1019)" | grep -v "(ST1003)" | not grep -v "(ST1019)\|\(other import of\)" - -# Exclude underscore checks for generated code. -grep "(ST1003)" "${SC_OUT}" | not grep -v '\(.pb.go:\)\|\(code_string_test.go:\)\|\(grpc_testing_not_regenerate\)' - -# Error for duplicate imports not including grpc protos. -grep "(ST1019)\|\(other import of\)" "${SC_OUT}" | not grep -Fv 'XXXXX PleaseIgnoreUnused -channelz/grpc_channelz_v1" -go-control-plane/envoy -grpclb/grpc_lb_v1" -health/grpc_health_v1" -interop/grpc_testing" -orca/v3" -proto/grpc_gcp" -proto/grpc_lookup_v1" -reflection/grpc_reflection_v1" -reflection/grpc_reflection_v1alpha" -XXXXX PleaseIgnoreUnused' - -# Error for any package comments not in generated code. -grep "(ST1000)" "${SC_OUT}" | not grep -v "\.pb\.go:" - -# Only ignore the following deprecated types/fields/functions and exclude -# generated code. -grep "(SA1019)" "${SC_OUT}" | not grep -Fv 'XXXXX PleaseIgnoreUnused -XXXXX Protobuf related deprecation errors: -"github.com/golang/protobuf -.pb.go: -grpc_testing_not_regenerate -: ptypes. -proto.RegisterType -XXXXX gRPC internal usage deprecation errors: -"google.golang.org/grpc -: grpc. -: v1alpha. -: v1alphareflectionpb. -BalancerAttributes is deprecated: -CredsBundle is deprecated: -Metadata is deprecated: use Attributes instead. -NewSubConn is deprecated: -OverrideServerName is deprecated: -RemoveSubConn is deprecated: -SecurityVersion is deprecated: -Target is deprecated: Use the Target field in the BuildOptions instead. -UpdateAddresses is deprecated: -UpdateSubConnState is deprecated: -balancer.ErrTransientFailure is deprecated: -grpc/reflection/v1alpha/reflection.proto -SwitchTo is deprecated: -XXXXX xDS deprecated fields we support -.ExactMatch -.PrefixMatch -.SafeRegexMatch -.SuffixMatch -GetContainsMatch -GetExactMatch -GetMatchSubjectAltNames -GetPrefixMatch -GetSafeRegexMatch -GetSuffixMatch -GetTlsCertificateCertificateProviderInstance -GetValidationContextCertificateProviderInstance -XXXXX PleaseIgnoreUnused' - -echo SUCCESS diff --git a/vendor/google.golang.org/protobuf/encoding/protojson/decode.go b/vendor/google.golang.org/protobuf/encoding/protojson/decode.go index f47902371..8f9e592f8 100644 --- a/vendor/google.golang.org/protobuf/encoding/protojson/decode.go +++ b/vendor/google.golang.org/protobuf/encoding/protojson/decode.go @@ -102,7 +102,7 @@ type decoder struct { } // newError returns an error object with position info. -func (d decoder) newError(pos int, f string, x ...interface{}) error { +func (d decoder) newError(pos int, f string, x ...any) error { line, column := d.Position(pos) head := fmt.Sprintf("(line %d:%d): ", line, column) return errors.New(head+f, x...) @@ -114,7 +114,7 @@ func (d decoder) unexpectedTokenError(tok json.Token) error { } // syntaxError returns a syntax error for given position. -func (d decoder) syntaxError(pos int, f string, x ...interface{}) error { +func (d decoder) syntaxError(pos int, f string, x ...any) error { line, column := d.Position(pos) head := fmt.Sprintf("syntax error (line %d:%d): ", line, column) return errors.New(head+f, x...) @@ -351,7 +351,7 @@ func (d decoder) unmarshalScalar(fd protoreflect.FieldDescriptor) (protoreflect. panic(fmt.Sprintf("unmarshalScalar: invalid scalar kind %v", kind)) } - return protoreflect.Value{}, d.newError(tok.Pos(), "invalid value for %v type: %v", kind, tok.RawString()) + return protoreflect.Value{}, d.newError(tok.Pos(), "invalid value for %v field %v: %v", kind, fd.JSONName(), tok.RawString()) } func unmarshalInt(tok json.Token, bitSize int) (protoreflect.Value, bool) { diff --git a/vendor/google.golang.org/protobuf/encoding/protojson/encode.go b/vendor/google.golang.org/protobuf/encoding/protojson/encode.go index 3f75098b6..0e72d8537 100644 --- a/vendor/google.golang.org/protobuf/encoding/protojson/encode.go +++ b/vendor/google.golang.org/protobuf/encoding/protojson/encode.go @@ -25,15 +25,17 @@ const defaultIndent = " " // Format formats the message as a multiline string. // This function is only intended for human consumption and ignores errors. -// Do not depend on the output being stable. It may change over time across -// different versions of the program. +// Do not depend on the output being stable. Its output will change across +// different builds of your program, even when using the same version of the +// protobuf module. func Format(m proto.Message) string { return MarshalOptions{Multiline: true}.Format(m) } // Marshal writes the given [proto.Message] in JSON format using default options. -// Do not depend on the output being stable. It may change over time across -// different versions of the program. +// Do not depend on the output being stable. Its output will change across +// different builds of your program, even when using the same version of the +// protobuf module. func Marshal(m proto.Message) ([]byte, error) { return MarshalOptions{}.Marshal(m) } @@ -110,8 +112,9 @@ type MarshalOptions struct { // Format formats the message as a string. // This method is only intended for human consumption and ignores errors. -// Do not depend on the output being stable. It may change over time across -// different versions of the program. +// Do not depend on the output being stable. Its output will change across +// different builds of your program, even when using the same version of the +// protobuf module. func (o MarshalOptions) Format(m proto.Message) string { if m == nil || !m.ProtoReflect().IsValid() { return "" // invalid syntax, but okay since this is for debugging @@ -122,8 +125,9 @@ func (o MarshalOptions) Format(m proto.Message) string { } // Marshal marshals the given [proto.Message] in the JSON format using options in -// MarshalOptions. Do not depend on the output being stable. It may change over -// time across different versions of the program. +// Do not depend on the output being stable. Its output will change across +// different builds of your program, even when using the same version of the +// protobuf module. func (o MarshalOptions) Marshal(m proto.Message) ([]byte, error) { return o.marshal(nil, m) } @@ -212,9 +216,7 @@ func (m unpopulatedFieldRanger) Range(f func(protoreflect.FieldDescriptor, proto } v := m.Get(fd) - isProto2Scalar := fd.Syntax() == protoreflect.Proto2 && fd.Default().IsValid() - isSingularMessage := fd.Cardinality() != protoreflect.Repeated && fd.Message() != nil - if isProto2Scalar || isSingularMessage { + if fd.HasPresence() { if m.skipNull { continue } diff --git a/vendor/google.golang.org/protobuf/encoding/protojson/well_known_types.go b/vendor/google.golang.org/protobuf/encoding/protojson/well_known_types.go index 4b177c820..e9fe10394 100644 --- a/vendor/google.golang.org/protobuf/encoding/protojson/well_known_types.go +++ b/vendor/google.golang.org/protobuf/encoding/protojson/well_known_types.go @@ -348,7 +348,11 @@ func (d decoder) unmarshalAnyValue(unmarshal unmarshalFunc, m protoreflect.Messa switch tok.Kind() { case json.ObjectClose: if !found { - return d.newError(tok.Pos(), `missing "value" field`) + // We tolerate an omitted `value` field with the google.protobuf.Empty Well-Known-Type, + // for compatibility with other proto runtimes that have interpreted the spec differently. + if m.Descriptor().FullName() != genid.Empty_message_fullname { + return d.newError(tok.Pos(), `missing "value" field`) + } } return nil diff --git a/vendor/google.golang.org/protobuf/encoding/prototext/decode.go b/vendor/google.golang.org/protobuf/encoding/prototext/decode.go index a45f112bc..24bc98ac4 100644 --- a/vendor/google.golang.org/protobuf/encoding/prototext/decode.go +++ b/vendor/google.golang.org/protobuf/encoding/prototext/decode.go @@ -84,7 +84,7 @@ type decoder struct { } // newError returns an error object with position info. -func (d decoder) newError(pos int, f string, x ...interface{}) error { +func (d decoder) newError(pos int, f string, x ...any) error { line, column := d.Position(pos) head := fmt.Sprintf("(line %d:%d): ", line, column) return errors.New(head+f, x...) @@ -96,7 +96,7 @@ func (d decoder) unexpectedTokenError(tok text.Token) error { } // syntaxError returns a syntax error for given position. -func (d decoder) syntaxError(pos int, f string, x ...interface{}) error { +func (d decoder) syntaxError(pos int, f string, x ...any) error { line, column := d.Position(pos) head := fmt.Sprintf("syntax error (line %d:%d): ", line, column) return errors.New(head+f, x...) diff --git a/vendor/google.golang.org/protobuf/encoding/prototext/encode.go b/vendor/google.golang.org/protobuf/encoding/prototext/encode.go index 95967e811..1f57e6610 100644 --- a/vendor/google.golang.org/protobuf/encoding/prototext/encode.go +++ b/vendor/google.golang.org/protobuf/encoding/prototext/encode.go @@ -27,15 +27,17 @@ const defaultIndent = " " // Format formats the message as a multiline string. // This function is only intended for human consumption and ignores errors. -// Do not depend on the output being stable. It may change over time across -// different versions of the program. +// Do not depend on the output being stable. Its output will change across +// different builds of your program, even when using the same version of the +// protobuf module. func Format(m proto.Message) string { return MarshalOptions{Multiline: true}.Format(m) } // Marshal writes the given [proto.Message] in textproto format using default -// options. Do not depend on the output being stable. It may change over time -// across different versions of the program. +// options. Do not depend on the output being stable. Its output will change +// across different builds of your program, even when using the same version of +// the protobuf module. func Marshal(m proto.Message) ([]byte, error) { return MarshalOptions{}.Marshal(m) } @@ -84,8 +86,9 @@ type MarshalOptions struct { // Format formats the message as a string. // This method is only intended for human consumption and ignores errors. -// Do not depend on the output being stable. It may change over time across -// different versions of the program. +// Do not depend on the output being stable. Its output will change across +// different builds of your program, even when using the same version of the +// protobuf module. func (o MarshalOptions) Format(m proto.Message) string { if m == nil || !m.ProtoReflect().IsValid() { return "" // invalid syntax, but okay since this is for debugging @@ -98,8 +101,9 @@ func (o MarshalOptions) Format(m proto.Message) string { } // Marshal writes the given [proto.Message] in textproto format using options in -// MarshalOptions object. Do not depend on the output being stable. It may -// change over time across different versions of the program. +// MarshalOptions object. Do not depend on the output being stable. Its output +// will change across different builds of your program, even when using the +// same version of the protobuf module. func (o MarshalOptions) Marshal(m proto.Message) ([]byte, error) { return o.marshal(nil, m) } diff --git a/vendor/google.golang.org/protobuf/internal/descfmt/stringer.go b/vendor/google.golang.org/protobuf/internal/descfmt/stringer.go index a45625c8d..87e46bd4d 100644 --- a/vendor/google.golang.org/protobuf/internal/descfmt/stringer.go +++ b/vendor/google.golang.org/protobuf/internal/descfmt/stringer.go @@ -252,6 +252,7 @@ func formatDescOpt(t protoreflect.Descriptor, isRoot, allowMulti bool, record fu {rv.MethodByName("Values"), "Values"}, {rv.MethodByName("ReservedNames"), "ReservedNames"}, {rv.MethodByName("ReservedRanges"), "ReservedRanges"}, + {rv.MethodByName("IsClosed"), "IsClosed"}, }...) case protoreflect.EnumValueDescriptor: diff --git a/vendor/google.golang.org/protobuf/internal/descopts/options.go b/vendor/google.golang.org/protobuf/internal/descopts/options.go index 8401be8c8..024ffebd3 100644 --- a/vendor/google.golang.org/protobuf/internal/descopts/options.go +++ b/vendor/google.golang.org/protobuf/internal/descopts/options.go @@ -9,7 +9,7 @@ // dependency on the descriptor proto package). package descopts -import pref "google.golang.org/protobuf/reflect/protoreflect" +import "google.golang.org/protobuf/reflect/protoreflect" // These variables are set by the init function in descriptor.pb.go via logic // in internal/filetype. In other words, so long as the descriptor proto package @@ -17,13 +17,13 @@ import pref "google.golang.org/protobuf/reflect/protoreflect" // // Each variable is populated with a nil pointer to the options struct. var ( - File pref.ProtoMessage - Enum pref.ProtoMessage - EnumValue pref.ProtoMessage - Message pref.ProtoMessage - Field pref.ProtoMessage - Oneof pref.ProtoMessage - ExtensionRange pref.ProtoMessage - Service pref.ProtoMessage - Method pref.ProtoMessage + File protoreflect.ProtoMessage + Enum protoreflect.ProtoMessage + EnumValue protoreflect.ProtoMessage + Message protoreflect.ProtoMessage + Field protoreflect.ProtoMessage + Oneof protoreflect.ProtoMessage + ExtensionRange protoreflect.ProtoMessage + Service protoreflect.ProtoMessage + Method protoreflect.ProtoMessage ) diff --git a/vendor/google.golang.org/protobuf/internal/editiondefaults/editions_defaults.binpb b/vendor/google.golang.org/protobuf/internal/editiondefaults/editions_defaults.binpb index 18f0756874367adcdb790ffde125b6a7388b4eaa..2c0693d7abbf532f021dafc96e7568f57214b8e7 100644 GIT binary patch literal 99 zcmd;*m3YRk#C*w)K}(o}QGiK;Nr72|(SYfa9SaAe1S6NM#B;bblK@aefe9$h2$E(1 dOTS=O5(H{Ql40Ut&|548XQ literal 63 zcmd-Q6yo7v6kw8IQef6#G+>f=#?A#2ViI7KU{qiN3NcDNhX^qu3B6!fc*d^rf*k<7 Cln3+x diff --git a/vendor/google.golang.org/protobuf/internal/editionssupport/editions.go b/vendor/google.golang.org/protobuf/internal/editionssupport/editions.go new file mode 100644 index 000000000..bf1aba0e8 --- /dev/null +++ b/vendor/google.golang.org/protobuf/internal/editionssupport/editions.go @@ -0,0 +1,18 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package editionssupport defines constants for editions that are supported. +package editionssupport + +import "google.golang.org/protobuf/types/descriptorpb" + +const ( + Minimum = descriptorpb.Edition_EDITION_PROTO2 + Maximum = descriptorpb.Edition_EDITION_2023 + + // MaximumKnown is the maximum edition that is known to Go Protobuf, but not + // declared as supported. In other words: end users cannot use it, but + // testprotos inside Go Protobuf can. + MaximumKnown = descriptorpb.Edition_EDITION_2024 +) diff --git a/vendor/google.golang.org/protobuf/internal/encoding/json/decode.go b/vendor/google.golang.org/protobuf/internal/encoding/json/decode.go index d2b3ac031..ea1d3e65a 100644 --- a/vendor/google.golang.org/protobuf/internal/encoding/json/decode.go +++ b/vendor/google.golang.org/protobuf/internal/encoding/json/decode.go @@ -214,7 +214,7 @@ func (d *Decoder) parseNext() (Token, error) { // newSyntaxError returns an error with line and column information useful for // syntax errors. -func (d *Decoder) newSyntaxError(pos int, f string, x ...interface{}) error { +func (d *Decoder) newSyntaxError(pos int, f string, x ...any) error { e := errors.New(f, x...) line, column := d.Position(pos) return errors.New("syntax error (line %d:%d): %v", line, column, e) diff --git a/vendor/google.golang.org/protobuf/internal/encoding/tag/tag.go b/vendor/google.golang.org/protobuf/internal/encoding/tag/tag.go index 373d20837..7e87c7604 100644 --- a/vendor/google.golang.org/protobuf/internal/encoding/tag/tag.go +++ b/vendor/google.golang.org/protobuf/internal/encoding/tag/tag.go @@ -32,6 +32,7 @@ var byteType = reflect.TypeOf(byte(0)) func Unmarshal(tag string, goType reflect.Type, evs protoreflect.EnumValueDescriptors) protoreflect.FieldDescriptor { f := new(filedesc.Field) f.L0.ParentFile = filedesc.SurrogateProto2 + f.L1.EditionFeatures = f.L0.ParentFile.L1.EditionFeatures for len(tag) > 0 { i := strings.IndexByte(tag, ',') if i < 0 { @@ -107,8 +108,7 @@ func Unmarshal(tag string, goType reflect.Type, evs protoreflect.EnumValueDescri f.L1.StringName.InitJSON(jsonName) } case s == "packed": - f.L1.HasPacked = true - f.L1.IsPacked = true + f.L1.EditionFeatures.IsPacked = true case strings.HasPrefix(s, "weak="): f.L1.IsWeak = true f.L1.Message = filedesc.PlaceholderMessage(protoreflect.FullName(s[len("weak="):])) diff --git a/vendor/google.golang.org/protobuf/internal/encoding/text/decode.go b/vendor/google.golang.org/protobuf/internal/encoding/text/decode.go index 87853e786..099b2bf45 100644 --- a/vendor/google.golang.org/protobuf/internal/encoding/text/decode.go +++ b/vendor/google.golang.org/protobuf/internal/encoding/text/decode.go @@ -601,7 +601,7 @@ func (d *Decoder) consumeToken(kind Kind, size int, attrs uint8) Token { // newSyntaxError returns a syntax error with line and column information for // current position. -func (d *Decoder) newSyntaxError(f string, x ...interface{}) error { +func (d *Decoder) newSyntaxError(f string, x ...any) error { e := errors.New(f, x...) line, column := d.Position(len(d.orig) - len(d.in)) return errors.New("syntax error (line %d:%d): %v", line, column, e) diff --git a/vendor/google.golang.org/protobuf/internal/errors/errors.go b/vendor/google.golang.org/protobuf/internal/errors/errors.go index 20c17b35e..c2d6bd526 100644 --- a/vendor/google.golang.org/protobuf/internal/errors/errors.go +++ b/vendor/google.golang.org/protobuf/internal/errors/errors.go @@ -17,7 +17,7 @@ var Error = errors.New("protobuf error") // New formats a string according to the format specifier and arguments and // returns an error that has a "proto" prefix. -func New(f string, x ...interface{}) error { +func New(f string, x ...any) error { return &prefixError{s: format(f, x...)} } @@ -43,7 +43,7 @@ func (e *prefixError) Unwrap() error { // Wrap returns an error that has a "proto" prefix, the formatted string described // by the format specifier and arguments, and a suffix of err. The error wraps err. -func Wrap(err error, f string, x ...interface{}) error { +func Wrap(err error, f string, x ...any) error { return &wrapError{ s: format(f, x...), err: err, @@ -67,7 +67,7 @@ func (e *wrapError) Is(target error) bool { return target == Error } -func format(f string, x ...interface{}) string { +func format(f string, x ...any) string { // avoid "proto: " prefix when chaining for i := 0; i < len(x); i++ { switch e := x[i].(type) { @@ -87,3 +87,18 @@ func InvalidUTF8(name string) error { func RequiredNotSet(name string) error { return New("required field %v not set", name) } + +type SizeMismatchError struct { + Calculated, Measured int +} + +func (e *SizeMismatchError) Error() string { + return fmt.Sprintf("size mismatch (see https://github.com/golang/protobuf/issues/1609): calculated=%d, measured=%d", e.Calculated, e.Measured) +} + +func MismatchedSizeCalculation(calculated, measured int) error { + return &SizeMismatchError{ + Calculated: calculated, + Measured: measured, + } +} diff --git a/vendor/google.golang.org/protobuf/internal/filedesc/desc.go b/vendor/google.golang.org/protobuf/internal/filedesc/desc.go index 8826bcf40..f32529856 100644 --- a/vendor/google.golang.org/protobuf/internal/filedesc/desc.go +++ b/vendor/google.golang.org/protobuf/internal/filedesc/desc.go @@ -7,6 +7,7 @@ package filedesc import ( "bytes" "fmt" + "strings" "sync" "sync/atomic" @@ -31,6 +32,7 @@ const ( EditionProto2 Edition = 998 EditionProto3 Edition = 999 Edition2023 Edition = 1000 + Edition2024 Edition = 1001 EditionUnsupported Edition = 100000 ) @@ -76,28 +78,42 @@ type ( Locations SourceLocations } + // EditionFeatures is a frequently-instantiated struct, so please take care + // to minimize padding when adding new fields to this struct (add them in + // the right place/order). EditionFeatures struct { + // StripEnumPrefix determines if the plugin generates enum value + // constants as-is, with their prefix stripped, or both variants. + StripEnumPrefix int + // IsFieldPresence is true if field_presence is EXPLICIT // https://protobuf.dev/editions/features/#field_presence IsFieldPresence bool + // IsFieldPresence is true if field_presence is LEGACY_REQUIRED // https://protobuf.dev/editions/features/#field_presence IsLegacyRequired bool + // IsOpenEnum is true if enum_type is OPEN // https://protobuf.dev/editions/features/#enum_type IsOpenEnum bool + // IsPacked is true if repeated_field_encoding is PACKED // https://protobuf.dev/editions/features/#repeated_field_encoding IsPacked bool + // IsUTF8Validated is true if utf_validation is VERIFY // https://protobuf.dev/editions/features/#utf8_validation IsUTF8Validated bool + // IsDelimitedEncoded is true if message_encoding is DELIMITED // https://protobuf.dev/editions/features/#message_encoding IsDelimitedEncoded bool + // IsJSONCompliant is true if json_format is ALLOW // https://protobuf.dev/editions/features/#json_format IsJSONCompliant bool + // GenerateLegacyUnmarshalJSON determines if the plugin generates the // UnmarshalJSON([]byte) error method for enums. GenerateLegacyUnmarshalJSON bool @@ -108,9 +124,12 @@ func (fd *File) ParentFile() protoreflect.FileDescriptor { return fd } func (fd *File) Parent() protoreflect.Descriptor { return nil } func (fd *File) Index() int { return 0 } func (fd *File) Syntax() protoreflect.Syntax { return fd.L1.Syntax } -func (fd *File) Name() protoreflect.Name { return fd.L1.Package.Name() } -func (fd *File) FullName() protoreflect.FullName { return fd.L1.Package } -func (fd *File) IsPlaceholder() bool { return false } + +// Not exported and just used to reconstruct the original FileDescriptor proto +func (fd *File) Edition() int32 { return int32(fd.L1.Edition) } +func (fd *File) Name() protoreflect.Name { return fd.L1.Package.Name() } +func (fd *File) FullName() protoreflect.FullName { return fd.L1.Package } +func (fd *File) IsPlaceholder() bool { return false } func (fd *File) Options() protoreflect.ProtoMessage { if f := fd.lazyInit().Options; f != nil { return f() @@ -202,6 +221,9 @@ func (ed *Enum) lazyInit() *EnumL2 { ed.L0.ParentFile.lazyInit() // implicitly initializes L2 return ed.L2 } +func (ed *Enum) IsClosed() bool { + return !ed.L1.EditionFeatures.IsOpenEnum +} func (ed *EnumValue) Options() protoreflect.ProtoMessage { if f := ed.L1.Options; f != nil { @@ -251,10 +273,7 @@ type ( StringName stringName IsProto3Optional bool // promoted from google.protobuf.FieldDescriptorProto IsWeak bool // promoted from google.protobuf.FieldOptions - HasPacked bool // promoted from google.protobuf.FieldOptions - IsPacked bool // promoted from google.protobuf.FieldOptions - HasEnforceUTF8 bool // promoted from google.protobuf.FieldOptions - EnforceUTF8 bool // promoted from google.protobuf.FieldOptions + IsLazy bool // promoted from google.protobuf.FieldOptions Default defaultValue ContainingOneof protoreflect.OneofDescriptor // must be consistent with Message.Oneofs.Fields Enum protoreflect.EnumDescriptor @@ -331,8 +350,7 @@ func (fd *Field) HasPresence() bool { if fd.L1.Cardinality == protoreflect.Repeated { return false } - explicitFieldPresence := fd.Syntax() == protoreflect.Editions && fd.L1.EditionFeatures.IsFieldPresence - return fd.Syntax() == protoreflect.Proto2 || explicitFieldPresence || fd.L1.Message != nil || fd.L1.ContainingOneof != nil + return fd.IsExtension() || fd.L1.EditionFeatures.IsFieldPresence || fd.L1.Message != nil || fd.L1.ContainingOneof != nil } func (fd *Field) HasOptionalKeyword() bool { return (fd.L0.ParentFile.L1.Syntax == protoreflect.Proto2 && fd.L1.Cardinality == protoreflect.Optional && fd.L1.ContainingOneof == nil) || fd.L1.IsProto3Optional @@ -345,17 +363,11 @@ func (fd *Field) IsPacked() bool { case protoreflect.StringKind, protoreflect.BytesKind, protoreflect.MessageKind, protoreflect.GroupKind: return false } - if fd.L0.ParentFile.L1.Syntax == protoreflect.Editions { - return fd.L1.EditionFeatures.IsPacked - } - if fd.L0.ParentFile.L1.Syntax == protoreflect.Proto3 { - // proto3 repeated fields are packed by default. - return !fd.L1.HasPacked || fd.L1.IsPacked - } - return fd.L1.IsPacked + return fd.L1.EditionFeatures.IsPacked } func (fd *Field) IsExtension() bool { return false } func (fd *Field) IsWeak() bool { return fd.L1.IsWeak } +func (fd *Field) IsLazy() bool { return fd.L1.IsLazy } func (fd *Field) IsList() bool { return fd.Cardinality() == protoreflect.Repeated && !fd.IsMap() } func (fd *Field) IsMap() bool { return fd.Message() != nil && fd.Message().IsMapEntry() } func (fd *Field) MapKey() protoreflect.FieldDescriptor { @@ -388,6 +400,10 @@ func (fd *Field) Message() protoreflect.MessageDescriptor { } return fd.L1.Message } +func (fd *Field) IsMapEntry() bool { + parent, ok := fd.L0.Parent.(protoreflect.MessageDescriptor) + return ok && parent.IsMapEntry() +} func (fd *Field) Format(s fmt.State, r rune) { descfmt.FormatDesc(s, r, fd) } func (fd *Field) ProtoType(protoreflect.FieldDescriptor) {} @@ -399,13 +415,7 @@ func (fd *Field) ProtoType(protoreflect.FieldDescriptor) {} // WARNING: This method is exempt from the compatibility promise and may be // removed in the future without warning. func (fd *Field) EnforceUTF8() bool { - if fd.L0.ParentFile.L1.Syntax == protoreflect.Editions { - return fd.L1.EditionFeatures.IsUTF8Validated - } - if fd.L1.HasEnforceUTF8 { - return fd.L1.EnforceUTF8 - } - return fd.L0.ParentFile.L1.Syntax == protoreflect.Proto3 + return fd.L1.EditionFeatures.IsUTF8Validated } func (od *Oneof) IsSynthetic() bool { @@ -432,13 +442,13 @@ type ( Extendee protoreflect.MessageDescriptor Cardinality protoreflect.Cardinality Kind protoreflect.Kind + IsLazy bool EditionFeatures EditionFeatures } ExtensionL2 struct { Options func() protoreflect.ProtoMessage StringName stringName IsProto3Optional bool // promoted from google.protobuf.FieldDescriptorProto - IsPacked bool // promoted from google.protobuf.FieldOptions Default defaultValue Enum protoreflect.EnumDescriptor Message protoreflect.MessageDescriptor @@ -461,9 +471,19 @@ func (xd *Extension) HasPresence() bool { return xd.L1.Cardi func (xd *Extension) HasOptionalKeyword() bool { return (xd.L0.ParentFile.L1.Syntax == protoreflect.Proto2 && xd.L1.Cardinality == protoreflect.Optional) || xd.lazyInit().IsProto3Optional } -func (xd *Extension) IsPacked() bool { return xd.lazyInit().IsPacked } +func (xd *Extension) IsPacked() bool { + if xd.L1.Cardinality != protoreflect.Repeated { + return false + } + switch xd.L1.Kind { + case protoreflect.StringKind, protoreflect.BytesKind, protoreflect.MessageKind, protoreflect.GroupKind: + return false + } + return xd.L1.EditionFeatures.IsPacked +} func (xd *Extension) IsExtension() bool { return true } func (xd *Extension) IsWeak() bool { return false } +func (xd *Extension) IsLazy() bool { return xd.L1.IsLazy } func (xd *Extension) IsList() bool { return xd.Cardinality() == protoreflect.Repeated } func (xd *Extension) IsMap() bool { return false } func (xd *Extension) MapKey() protoreflect.FieldDescriptor { return nil } @@ -542,8 +562,9 @@ func (md *Method) ProtoInternal(pragma.DoNotImplement) {} // Surrogate files are can be used to create standalone descriptors // where the syntax is only information derived from the parent file. var ( - SurrogateProto2 = &File{L1: FileL1{Syntax: protoreflect.Proto2}, L2: &FileL2{}} - SurrogateProto3 = &File{L1: FileL1{Syntax: protoreflect.Proto3}, L2: &FileL2{}} + SurrogateProto2 = &File{L1: FileL1{Syntax: protoreflect.Proto2}, L2: &FileL2{}} + SurrogateProto3 = &File{L1: FileL1{Syntax: protoreflect.Proto3}, L2: &FileL2{}} + SurrogateEdition2023 = &File{L1: FileL1{Syntax: protoreflect.Editions, Edition: Edition2023}, L2: &FileL2{}} ) type ( @@ -585,6 +606,34 @@ func (s *stringName) InitJSON(name string) { s.nameJSON = name } +// Returns true if this field is structured like the synthetic field of a proto2 +// group. This allows us to expand our treatment of delimited fields without +// breaking proto2 files that have been upgraded to editions. +func isGroupLike(fd protoreflect.FieldDescriptor) bool { + // Groups are always group types. + if fd.Kind() != protoreflect.GroupKind { + return false + } + + // Group fields are always the lowercase type name. + if strings.ToLower(string(fd.Message().Name())) != string(fd.Name()) { + return false + } + + // Groups could only be defined in the same file they're used. + if fd.Message().ParentFile() != fd.ParentFile() { + return false + } + + // Group messages are always defined in the same scope as the field. File + // level extensions will compare NULL == NULL here, which is why the file + // comparison above is necessary to ensure both come from the same file. + if fd.IsExtension() { + return fd.Parent() == fd.Message().Parent() + } + return fd.ContainingMessage() == fd.Message().Parent() +} + func (s *stringName) lazyInit(fd protoreflect.FieldDescriptor) *stringName { s.once.Do(func() { if fd.IsExtension() { @@ -605,7 +654,7 @@ func (s *stringName) lazyInit(fd protoreflect.FieldDescriptor) *stringName { // Format the text name. s.nameText = string(fd.Name()) - if fd.Kind() == protoreflect.GroupKind { + if isGroupLike(fd) { s.nameText = string(fd.Message().Name()) } } diff --git a/vendor/google.golang.org/protobuf/internal/filedesc/desc_init.go b/vendor/google.golang.org/protobuf/internal/filedesc/desc_init.go index 237e64fd2..d2f549497 100644 --- a/vendor/google.golang.org/protobuf/internal/filedesc/desc_init.go +++ b/vendor/google.golang.org/protobuf/internal/filedesc/desc_init.go @@ -113,8 +113,10 @@ func (fd *File) unmarshalSeed(b []byte) { switch string(v) { case "proto2": fd.L1.Syntax = protoreflect.Proto2 + fd.L1.Edition = EditionProto2 case "proto3": fd.L1.Syntax = protoreflect.Proto3 + fd.L1.Edition = EditionProto3 case "editions": fd.L1.Syntax = protoreflect.Editions default: @@ -177,11 +179,10 @@ func (fd *File) unmarshalSeed(b []byte) { // If syntax is missing, it is assumed to be proto2. if fd.L1.Syntax == 0 { fd.L1.Syntax = protoreflect.Proto2 + fd.L1.Edition = EditionProto2 } - if fd.L1.Syntax == protoreflect.Editions { - fd.L1.EditionFeatures = getFeaturesFor(fd.L1.Edition) - } + fd.L1.EditionFeatures = getFeaturesFor(fd.L1.Edition) // Parse editions features from options if any if options != nil { @@ -267,6 +268,7 @@ func (ed *Enum) unmarshalSeed(b []byte, sb *strs.Builder, pf *File, pd protorefl ed.L0.ParentFile = pf ed.L0.Parent = pd ed.L0.Index = i + ed.L1.EditionFeatures = featuresFromParentDesc(ed.Parent()) var numValues int for b := b; len(b) > 0; { @@ -443,6 +445,7 @@ func (xd *Extension) unmarshalSeed(b []byte, sb *strs.Builder, pf *File, pd prot xd.L0.ParentFile = pf xd.L0.Parent = pd xd.L0.Index = i + xd.L1.EditionFeatures = featuresFromParentDesc(pd) for len(b) > 0 { num, typ, n := protowire.ConsumeTag(b) @@ -467,6 +470,40 @@ func (xd *Extension) unmarshalSeed(b []byte, sb *strs.Builder, pf *File, pd prot xd.L0.FullName = appendFullName(sb, pd.FullName(), v) case genid.FieldDescriptorProto_Extendee_field_number: xd.L1.Extendee = PlaceholderMessage(makeFullName(sb, v)) + case genid.FieldDescriptorProto_Options_field_number: + xd.unmarshalOptions(v) + } + default: + m := protowire.ConsumeFieldValue(num, typ, b) + b = b[m:] + } + } + + if xd.L1.Kind == protoreflect.MessageKind && xd.L1.EditionFeatures.IsDelimitedEncoded { + xd.L1.Kind = protoreflect.GroupKind + } +} + +func (xd *Extension) unmarshalOptions(b []byte) { + for len(b) > 0 { + num, typ, n := protowire.ConsumeTag(b) + b = b[n:] + switch typ { + case protowire.VarintType: + v, m := protowire.ConsumeVarint(b) + b = b[m:] + switch num { + case genid.FieldOptions_Packed_field_number: + xd.L1.EditionFeatures.IsPacked = protowire.DecodeBool(v) + case genid.FieldOptions_Lazy_field_number: + xd.L1.IsLazy = protowire.DecodeBool(v) + } + case protowire.BytesType: + v, m := protowire.ConsumeBytes(b) + b = b[m:] + switch num { + case genid.FieldOptions_Features_field_number: + xd.L1.EditionFeatures = unmarshalFeatureSet(v, xd.L1.EditionFeatures) } default: m := protowire.ConsumeFieldValue(num, typ, b) @@ -499,7 +536,7 @@ func (sd *Service) unmarshalSeed(b []byte, sb *strs.Builder, pf *File, pd protor } var nameBuilderPool = sync.Pool{ - New: func() interface{} { return new(strs.Builder) }, + New: func() any { return new(strs.Builder) }, } func getBuilder() *strs.Builder { diff --git a/vendor/google.golang.org/protobuf/internal/filedesc/desc_lazy.go b/vendor/google.golang.org/protobuf/internal/filedesc/desc_lazy.go index 482a61cc1..67a51b327 100644 --- a/vendor/google.golang.org/protobuf/internal/filedesc/desc_lazy.go +++ b/vendor/google.golang.org/protobuf/internal/filedesc/desc_lazy.go @@ -45,6 +45,11 @@ func (file *File) resolveMessages() { case protoreflect.MessageKind, protoreflect.GroupKind: fd.L1.Message = file.resolveMessageDependency(fd.L1.Message, listFieldDeps, depIdx) depIdx++ + if fd.L1.Kind == protoreflect.GroupKind && (fd.IsMap() || fd.IsMapEntry()) { + // A map field might inherit delimited encoding from a file-wide default feature. + // But maps never actually use delimited encoding. (At least for now...) + fd.L1.Kind = protoreflect.MessageKind + } } // Default is resolved here since it depends on Enum being resolved. @@ -466,10 +471,10 @@ func (fd *Field) unmarshalFull(b []byte, sb *strs.Builder, pf *File, pd protoref b = b[m:] } } - if fd.Syntax() == protoreflect.Editions && fd.L1.Kind == protoreflect.MessageKind && fd.L1.EditionFeatures.IsDelimitedEncoded { + if fd.L1.Kind == protoreflect.MessageKind && fd.L1.EditionFeatures.IsDelimitedEncoded { fd.L1.Kind = protoreflect.GroupKind } - if fd.Syntax() == protoreflect.Editions && fd.L1.EditionFeatures.IsLegacyRequired { + if fd.L1.EditionFeatures.IsLegacyRequired { fd.L1.Cardinality = protoreflect.Required } if rawTypeName != nil { @@ -496,13 +501,13 @@ func (fd *Field) unmarshalOptions(b []byte) { b = b[m:] switch num { case genid.FieldOptions_Packed_field_number: - fd.L1.HasPacked = true - fd.L1.IsPacked = protowire.DecodeBool(v) + fd.L1.EditionFeatures.IsPacked = protowire.DecodeBool(v) case genid.FieldOptions_Weak_field_number: fd.L1.IsWeak = protowire.DecodeBool(v) + case genid.FieldOptions_Lazy_field_number: + fd.L1.IsLazy = protowire.DecodeBool(v) case FieldOptions_EnforceUTF8: - fd.L1.HasEnforceUTF8 = true - fd.L1.EnforceUTF8 = protowire.DecodeBool(v) + fd.L1.EditionFeatures.IsUTF8Validated = protowire.DecodeBool(v) } case protowire.BytesType: v, m := protowire.ConsumeBytes(b) @@ -548,7 +553,6 @@ func (od *Oneof) unmarshalFull(b []byte, sb *strs.Builder, pf *File, pd protoref func (xd *Extension) unmarshalFull(b []byte, sb *strs.Builder) { var rawTypeName []byte var rawOptions []byte - xd.L1.EditionFeatures = featuresFromParentDesc(xd.L1.Extendee) xd.L2 = new(ExtensionL2) for len(b) > 0 { num, typ, n := protowire.ConsumeTag(b) @@ -572,7 +576,6 @@ func (xd *Extension) unmarshalFull(b []byte, sb *strs.Builder) { case genid.FieldDescriptorProto_TypeName_field_number: rawTypeName = v case genid.FieldDescriptorProto_Options_field_number: - xd.unmarshalOptions(v) rawOptions = appendOptions(rawOptions, v) } default: @@ -580,12 +583,6 @@ func (xd *Extension) unmarshalFull(b []byte, sb *strs.Builder) { b = b[m:] } } - if xd.Syntax() == protoreflect.Editions && xd.L1.Kind == protoreflect.MessageKind && xd.L1.EditionFeatures.IsDelimitedEncoded { - xd.L1.Kind = protoreflect.GroupKind - } - if xd.Syntax() == protoreflect.Editions && xd.L1.EditionFeatures.IsLegacyRequired { - xd.L1.Cardinality = protoreflect.Required - } if rawTypeName != nil { name := makeFullName(sb, rawTypeName) switch xd.L1.Kind { @@ -598,32 +595,6 @@ func (xd *Extension) unmarshalFull(b []byte, sb *strs.Builder) { xd.L2.Options = xd.L0.ParentFile.builder.optionsUnmarshaler(&descopts.Field, rawOptions) } -func (xd *Extension) unmarshalOptions(b []byte) { - for len(b) > 0 { - num, typ, n := protowire.ConsumeTag(b) - b = b[n:] - switch typ { - case protowire.VarintType: - v, m := protowire.ConsumeVarint(b) - b = b[m:] - switch num { - case genid.FieldOptions_Packed_field_number: - xd.L2.IsPacked = protowire.DecodeBool(v) - } - case protowire.BytesType: - v, m := protowire.ConsumeBytes(b) - b = b[m:] - switch num { - case genid.FieldOptions_Features_field_number: - xd.L1.EditionFeatures = unmarshalFeatureSet(v, xd.L1.EditionFeatures) - } - default: - m := protowire.ConsumeFieldValue(num, typ, b) - b = b[m:] - } - } -} - func (sd *Service) unmarshalFull(b []byte, sb *strs.Builder) { var rawMethods [][]byte var rawOptions []byte diff --git a/vendor/google.golang.org/protobuf/internal/filedesc/desc_list_gen.go b/vendor/google.golang.org/protobuf/internal/filedesc/desc_list_gen.go index 30db19fdc..f4107c05f 100644 --- a/vendor/google.golang.org/protobuf/internal/filedesc/desc_list_gen.go +++ b/vendor/google.golang.org/protobuf/internal/filedesc/desc_list_gen.go @@ -8,6 +8,7 @@ package filedesc import ( "fmt" + "strings" "sync" "google.golang.org/protobuf/internal/descfmt" @@ -198,6 +199,16 @@ func (p *Fields) lazyInit() *Fields { if _, ok := p.byText[d.TextName()]; !ok { p.byText[d.TextName()] = d } + if isGroupLike(d) { + lowerJSONName := strings.ToLower(d.JSONName()) + if _, ok := p.byJSON[lowerJSONName]; !ok { + p.byJSON[lowerJSONName] = d + } + lowerTextName := strings.ToLower(d.TextName()) + if _, ok := p.byText[lowerTextName]; !ok { + p.byText[lowerTextName] = d + } + } if _, ok := p.byNum[d.Number()]; !ok { p.byNum[d.Number()] = d } diff --git a/vendor/google.golang.org/protobuf/internal/filedesc/editions.go b/vendor/google.golang.org/protobuf/internal/filedesc/editions.go index 0375a49d4..7611796e8 100644 --- a/vendor/google.golang.org/protobuf/internal/filedesc/editions.go +++ b/vendor/google.golang.org/protobuf/internal/filedesc/editions.go @@ -14,9 +14,13 @@ import ( ) var defaultsCache = make(map[Edition]EditionFeatures) +var defaultsKeys = []Edition{} func init() { unmarshalEditionDefaults(editiondefaults.Defaults) + SurrogateProto2.L1.EditionFeatures = getFeaturesFor(EditionProto2) + SurrogateProto3.L1.EditionFeatures = getFeaturesFor(EditionProto3) + SurrogateEdition2023.L1.EditionFeatures = getFeaturesFor(Edition2023) } func unmarshalGoFeature(b []byte, parent EditionFeatures) EditionFeatures { @@ -28,6 +32,10 @@ func unmarshalGoFeature(b []byte, parent EditionFeatures) EditionFeatures { v, m := protowire.ConsumeVarint(b) b = b[m:] parent.GenerateLegacyUnmarshalJSON = protowire.DecodeBool(v) + case genid.GoFeatures_StripEnumPrefix_field_number: + v, m := protowire.ConsumeVarint(b) + b = b[m:] + parent.StripEnumPrefix = int(v) default: panic(fmt.Sprintf("unkown field number %d while unmarshalling GoFeatures", num)) } @@ -64,7 +72,7 @@ func unmarshalFeatureSet(b []byte, parent EditionFeatures) EditionFeatures { v, m := protowire.ConsumeBytes(b) b = b[m:] switch num { - case genid.GoFeatures_LegacyUnmarshalJsonEnum_field_number: + case genid.FeatureSet_Go_ext_number: parent = unmarshalGoFeature(v, parent) } } @@ -104,12 +112,15 @@ func unmarshalEditionDefault(b []byte) { v, m := protowire.ConsumeBytes(b) b = b[m:] switch num { - case genid.FeatureSetDefaults_FeatureSetEditionDefault_Features_field_number: + case genid.FeatureSetDefaults_FeatureSetEditionDefault_FixedFeatures_field_number: + fs = unmarshalFeatureSet(v, fs) + case genid.FeatureSetDefaults_FeatureSetEditionDefault_OverridableFeatures_field_number: fs = unmarshalFeatureSet(v, fs) } } } defaultsCache[ed] = fs + defaultsKeys = append(defaultsKeys, ed) } func unmarshalEditionDefaults(b []byte) { @@ -135,8 +146,15 @@ func unmarshalEditionDefaults(b []byte) { } func getFeaturesFor(ed Edition) EditionFeatures { - if def, ok := defaultsCache[ed]; ok { - return def + match := EditionUnknown + for _, key := range defaultsKeys { + if key > ed { + break + } + match = key + } + if match == EditionUnknown { + panic(fmt.Sprintf("unsupported edition: %v", ed)) } - panic(fmt.Sprintf("unsupported edition: %v", ed)) + return defaultsCache[match] } diff --git a/vendor/google.golang.org/protobuf/internal/filedesc/placeholder.go b/vendor/google.golang.org/protobuf/internal/filedesc/placeholder.go index 28240ebc5..bfb3b8417 100644 --- a/vendor/google.golang.org/protobuf/internal/filedesc/placeholder.go +++ b/vendor/google.golang.org/protobuf/internal/filedesc/placeholder.go @@ -63,6 +63,7 @@ func (e PlaceholderEnum) Options() protoreflect.ProtoMessage { return des func (e PlaceholderEnum) Values() protoreflect.EnumValueDescriptors { return emptyEnumValues } func (e PlaceholderEnum) ReservedNames() protoreflect.Names { return emptyNames } func (e PlaceholderEnum) ReservedRanges() protoreflect.EnumRanges { return emptyEnumRanges } +func (e PlaceholderEnum) IsClosed() bool { return false } func (e PlaceholderEnum) ProtoType(protoreflect.EnumDescriptor) { return } func (e PlaceholderEnum) ProtoInternal(pragma.DoNotImplement) { return } diff --git a/vendor/google.golang.org/protobuf/internal/filetype/build.go b/vendor/google.golang.org/protobuf/internal/filetype/build.go index f0e38c4ef..ba83fea44 100644 --- a/vendor/google.golang.org/protobuf/internal/filetype/build.go +++ b/vendor/google.golang.org/protobuf/internal/filetype/build.go @@ -68,7 +68,7 @@ type Builder struct { // and for input and output messages referenced by service methods. // Dependencies must come after declarations, but the ordering of // dependencies themselves is unspecified. - GoTypes []interface{} + GoTypes []any // DependencyIndexes is an ordered list of indexes into GoTypes for the // dependencies of messages, extensions, or services. @@ -268,7 +268,7 @@ func (x depIdxs) Get(i, j int32) int32 { type ( resolverByIndex struct { - goTypes []interface{} + goTypes []any depIdxs depIdxs fileRegistry } diff --git a/vendor/google.golang.org/protobuf/internal/genid/descriptor_gen.go b/vendor/google.golang.org/protobuf/internal/genid/descriptor_gen.go index 40272c893..f30ab6b58 100644 --- a/vendor/google.golang.org/protobuf/internal/genid/descriptor_gen.go +++ b/vendor/google.golang.org/protobuf/internal/genid/descriptor_gen.go @@ -21,6 +21,7 @@ const ( // Enum values for google.protobuf.Edition. const ( Edition_EDITION_UNKNOWN_enum_value = 0 + Edition_EDITION_LEGACY_enum_value = 900 Edition_EDITION_PROTO2_enum_value = 998 Edition_EDITION_PROTO3_enum_value = 999 Edition_EDITION_2023_enum_value = 1000 @@ -653,6 +654,7 @@ const ( FieldOptions_Targets_field_name protoreflect.Name = "targets" FieldOptions_EditionDefaults_field_name protoreflect.Name = "edition_defaults" FieldOptions_Features_field_name protoreflect.Name = "features" + FieldOptions_FeatureSupport_field_name protoreflect.Name = "feature_support" FieldOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option" FieldOptions_Ctype_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.ctype" @@ -667,6 +669,7 @@ const ( FieldOptions_Targets_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.targets" FieldOptions_EditionDefaults_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.edition_defaults" FieldOptions_Features_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.features" + FieldOptions_FeatureSupport_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.feature_support" FieldOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.uninterpreted_option" ) @@ -684,6 +687,7 @@ const ( FieldOptions_Targets_field_number protoreflect.FieldNumber = 19 FieldOptions_EditionDefaults_field_number protoreflect.FieldNumber = 20 FieldOptions_Features_field_number protoreflect.FieldNumber = 21 + FieldOptions_FeatureSupport_field_number protoreflect.FieldNumber = 22 FieldOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999 ) @@ -767,6 +771,33 @@ const ( FieldOptions_EditionDefault_Value_field_number protoreflect.FieldNumber = 2 ) +// Names for google.protobuf.FieldOptions.FeatureSupport. +const ( + FieldOptions_FeatureSupport_message_name protoreflect.Name = "FeatureSupport" + FieldOptions_FeatureSupport_message_fullname protoreflect.FullName = "google.protobuf.FieldOptions.FeatureSupport" +) + +// Field names for google.protobuf.FieldOptions.FeatureSupport. +const ( + FieldOptions_FeatureSupport_EditionIntroduced_field_name protoreflect.Name = "edition_introduced" + FieldOptions_FeatureSupport_EditionDeprecated_field_name protoreflect.Name = "edition_deprecated" + FieldOptions_FeatureSupport_DeprecationWarning_field_name protoreflect.Name = "deprecation_warning" + FieldOptions_FeatureSupport_EditionRemoved_field_name protoreflect.Name = "edition_removed" + + FieldOptions_FeatureSupport_EditionIntroduced_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.FeatureSupport.edition_introduced" + FieldOptions_FeatureSupport_EditionDeprecated_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.FeatureSupport.edition_deprecated" + FieldOptions_FeatureSupport_DeprecationWarning_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.FeatureSupport.deprecation_warning" + FieldOptions_FeatureSupport_EditionRemoved_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.FeatureSupport.edition_removed" +) + +// Field numbers for google.protobuf.FieldOptions.FeatureSupport. +const ( + FieldOptions_FeatureSupport_EditionIntroduced_field_number protoreflect.FieldNumber = 1 + FieldOptions_FeatureSupport_EditionDeprecated_field_number protoreflect.FieldNumber = 2 + FieldOptions_FeatureSupport_DeprecationWarning_field_number protoreflect.FieldNumber = 3 + FieldOptions_FeatureSupport_EditionRemoved_field_number protoreflect.FieldNumber = 4 +) + // Names for google.protobuf.OneofOptions. const ( OneofOptions_message_name protoreflect.Name = "OneofOptions" @@ -829,11 +860,13 @@ const ( EnumValueOptions_Deprecated_field_name protoreflect.Name = "deprecated" EnumValueOptions_Features_field_name protoreflect.Name = "features" EnumValueOptions_DebugRedact_field_name protoreflect.Name = "debug_redact" + EnumValueOptions_FeatureSupport_field_name protoreflect.Name = "feature_support" EnumValueOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option" EnumValueOptions_Deprecated_field_fullname protoreflect.FullName = "google.protobuf.EnumValueOptions.deprecated" EnumValueOptions_Features_field_fullname protoreflect.FullName = "google.protobuf.EnumValueOptions.features" EnumValueOptions_DebugRedact_field_fullname protoreflect.FullName = "google.protobuf.EnumValueOptions.debug_redact" + EnumValueOptions_FeatureSupport_field_fullname protoreflect.FullName = "google.protobuf.EnumValueOptions.feature_support" EnumValueOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.EnumValueOptions.uninterpreted_option" ) @@ -842,6 +875,7 @@ const ( EnumValueOptions_Deprecated_field_number protoreflect.FieldNumber = 1 EnumValueOptions_Features_field_number protoreflect.FieldNumber = 2 EnumValueOptions_DebugRedact_field_number protoreflect.FieldNumber = 3 + EnumValueOptions_FeatureSupport_field_number protoreflect.FieldNumber = 4 EnumValueOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999 ) @@ -1110,17 +1144,20 @@ const ( // Field names for google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault. const ( - FeatureSetDefaults_FeatureSetEditionDefault_Edition_field_name protoreflect.Name = "edition" - FeatureSetDefaults_FeatureSetEditionDefault_Features_field_name protoreflect.Name = "features" + FeatureSetDefaults_FeatureSetEditionDefault_Edition_field_name protoreflect.Name = "edition" + FeatureSetDefaults_FeatureSetEditionDefault_OverridableFeatures_field_name protoreflect.Name = "overridable_features" + FeatureSetDefaults_FeatureSetEditionDefault_FixedFeatures_field_name protoreflect.Name = "fixed_features" - FeatureSetDefaults_FeatureSetEditionDefault_Edition_field_fullname protoreflect.FullName = "google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault.edition" - FeatureSetDefaults_FeatureSetEditionDefault_Features_field_fullname protoreflect.FullName = "google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault.features" + FeatureSetDefaults_FeatureSetEditionDefault_Edition_field_fullname protoreflect.FullName = "google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault.edition" + FeatureSetDefaults_FeatureSetEditionDefault_OverridableFeatures_field_fullname protoreflect.FullName = "google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault.overridable_features" + FeatureSetDefaults_FeatureSetEditionDefault_FixedFeatures_field_fullname protoreflect.FullName = "google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault.fixed_features" ) // Field numbers for google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault. const ( - FeatureSetDefaults_FeatureSetEditionDefault_Edition_field_number protoreflect.FieldNumber = 3 - FeatureSetDefaults_FeatureSetEditionDefault_Features_field_number protoreflect.FieldNumber = 2 + FeatureSetDefaults_FeatureSetEditionDefault_Edition_field_number protoreflect.FieldNumber = 3 + FeatureSetDefaults_FeatureSetEditionDefault_OverridableFeatures_field_number protoreflect.FieldNumber = 4 + FeatureSetDefaults_FeatureSetEditionDefault_FixedFeatures_field_number protoreflect.FieldNumber = 5 ) // Names for google.protobuf.SourceCodeInfo. diff --git a/vendor/google.golang.org/protobuf/internal/genid/doc.go b/vendor/google.golang.org/protobuf/internal/genid/doc.go index 45ccd0121..d9b9d916a 100644 --- a/vendor/google.golang.org/protobuf/internal/genid/doc.go +++ b/vendor/google.golang.org/protobuf/internal/genid/doc.go @@ -6,6 +6,6 @@ // and the well-known types. package genid -import protoreflect "google.golang.org/protobuf/reflect/protoreflect" +import "google.golang.org/protobuf/reflect/protoreflect" const GoogleProtobuf_package protoreflect.FullName = "google.protobuf" diff --git a/vendor/google.golang.org/protobuf/internal/genid/go_features_gen.go b/vendor/google.golang.org/protobuf/internal/genid/go_features_gen.go index fd9015e8e..09792d96f 100644 --- a/vendor/google.golang.org/protobuf/internal/genid/go_features_gen.go +++ b/vendor/google.golang.org/protobuf/internal/genid/go_features_gen.go @@ -10,22 +10,44 @@ import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" ) -const File_reflect_protodesc_proto_go_features_proto = "reflect/protodesc/proto/go_features.proto" +const File_google_protobuf_go_features_proto = "google/protobuf/go_features.proto" -// Names for google.protobuf.GoFeatures. +// Names for pb.GoFeatures. const ( GoFeatures_message_name protoreflect.Name = "GoFeatures" - GoFeatures_message_fullname protoreflect.FullName = "google.protobuf.GoFeatures" + GoFeatures_message_fullname protoreflect.FullName = "pb.GoFeatures" ) -// Field names for google.protobuf.GoFeatures. +// Field names for pb.GoFeatures. const ( GoFeatures_LegacyUnmarshalJsonEnum_field_name protoreflect.Name = "legacy_unmarshal_json_enum" + GoFeatures_StripEnumPrefix_field_name protoreflect.Name = "strip_enum_prefix" - GoFeatures_LegacyUnmarshalJsonEnum_field_fullname protoreflect.FullName = "google.protobuf.GoFeatures.legacy_unmarshal_json_enum" + GoFeatures_LegacyUnmarshalJsonEnum_field_fullname protoreflect.FullName = "pb.GoFeatures.legacy_unmarshal_json_enum" + GoFeatures_StripEnumPrefix_field_fullname protoreflect.FullName = "pb.GoFeatures.strip_enum_prefix" ) -// Field numbers for google.protobuf.GoFeatures. +// Field numbers for pb.GoFeatures. const ( GoFeatures_LegacyUnmarshalJsonEnum_field_number protoreflect.FieldNumber = 1 + GoFeatures_StripEnumPrefix_field_number protoreflect.FieldNumber = 3 +) + +// Full and short names for pb.GoFeatures.StripEnumPrefix. +const ( + GoFeatures_StripEnumPrefix_enum_fullname = "pb.GoFeatures.StripEnumPrefix" + GoFeatures_StripEnumPrefix_enum_name = "StripEnumPrefix" +) + +// Enum values for pb.GoFeatures.StripEnumPrefix. +const ( + GoFeatures_STRIP_ENUM_PREFIX_UNSPECIFIED_enum_value = 0 + GoFeatures_STRIP_ENUM_PREFIX_KEEP_enum_value = 1 + GoFeatures_STRIP_ENUM_PREFIX_GENERATE_BOTH_enum_value = 2 + GoFeatures_STRIP_ENUM_PREFIX_STRIP_enum_value = 3 +) + +// Extension numbers +const ( + FeatureSet_Go_ext_number protoreflect.FieldNumber = 1002 ) diff --git a/vendor/google.golang.org/protobuf/internal/genid/map_entry.go b/vendor/google.golang.org/protobuf/internal/genid/map_entry.go index 8f9ea02ff..bef5a25fb 100644 --- a/vendor/google.golang.org/protobuf/internal/genid/map_entry.go +++ b/vendor/google.golang.org/protobuf/internal/genid/map_entry.go @@ -4,7 +4,7 @@ package genid -import protoreflect "google.golang.org/protobuf/reflect/protoreflect" +import "google.golang.org/protobuf/reflect/protoreflect" // Generic field names and numbers for synthetic map entry messages. const ( diff --git a/vendor/google.golang.org/protobuf/internal/genid/wrappers.go b/vendor/google.golang.org/protobuf/internal/genid/wrappers.go index 429384b85..9404270de 100644 --- a/vendor/google.golang.org/protobuf/internal/genid/wrappers.go +++ b/vendor/google.golang.org/protobuf/internal/genid/wrappers.go @@ -4,7 +4,7 @@ package genid -import protoreflect "google.golang.org/protobuf/reflect/protoreflect" +import "google.golang.org/protobuf/reflect/protoreflect" // Generic field name and number for messages in wrappers.proto. const ( diff --git a/vendor/google.golang.org/protobuf/internal/impl/api_export.go b/vendor/google.golang.org/protobuf/internal/impl/api_export.go index a371f98de..5d5771c2e 100644 --- a/vendor/google.golang.org/protobuf/internal/impl/api_export.go +++ b/vendor/google.golang.org/protobuf/internal/impl/api_export.go @@ -22,13 +22,13 @@ type Export struct{} // NewError formats a string according to the format specifier and arguments and // returns an error that has a "proto" prefix. -func (Export) NewError(f string, x ...interface{}) error { +func (Export) NewError(f string, x ...any) error { return errors.New(f, x...) } // enum is any enum type generated by protoc-gen-go // and must be a named int32 type. -type enum = interface{} +type enum = any // EnumOf returns the protoreflect.Enum interface over e. // It returns nil if e is nil. @@ -81,7 +81,7 @@ func (Export) EnumStringOf(ed protoreflect.EnumDescriptor, n protoreflect.EnumNu // message is any message type generated by protoc-gen-go // and must be a pointer to a named struct type. -type message = interface{} +type message = any // legacyMessageWrapper wraps a v2 message as a v1 message. type legacyMessageWrapper struct{ m protoreflect.ProtoMessage } diff --git a/vendor/google.golang.org/protobuf/internal/impl/checkinit.go b/vendor/google.golang.org/protobuf/internal/impl/checkinit.go index bff041edc..f29e6a8fa 100644 --- a/vendor/google.golang.org/protobuf/internal/impl/checkinit.go +++ b/vendor/google.golang.org/protobuf/internal/impl/checkinit.go @@ -68,7 +68,7 @@ func (mi *MessageInfo) isInitExtensions(ext *map[int32]ExtensionField) error { } for _, x := range *ext { ei := getExtensionFieldInfo(x.Type()) - if ei.funcs.isInit == nil { + if ei.funcs.isInit == nil || x.isUnexpandedLazy() { continue } v := x.Value() diff --git a/vendor/google.golang.org/protobuf/internal/impl/codec_extension.go b/vendor/google.golang.org/protobuf/internal/impl/codec_extension.go index 2b8f122c2..0d5b546e0 100644 --- a/vendor/google.golang.org/protobuf/internal/impl/codec_extension.go +++ b/vendor/google.golang.org/protobuf/internal/impl/codec_extension.go @@ -67,7 +67,6 @@ type lazyExtensionValue struct { xi *extensionFieldInfo value protoreflect.Value b []byte - fn func() protoreflect.Value } type ExtensionField struct { @@ -99,6 +98,28 @@ func (f *ExtensionField) canLazy(xt protoreflect.ExtensionType) bool { return false } +// isUnexpandedLazy returns true if the ExensionField is lazy and not +// yet expanded, which means it's present and already checked for +// initialized required fields. +func (f *ExtensionField) isUnexpandedLazy() bool { + return f.lazy != nil && atomic.LoadUint32(&f.lazy.atomicOnce) == 0 +} + +// lazyBuffer retrieves the buffer for a lazy extension if it's not yet expanded. +// +// The returned buffer has to be kept over whatever operation we're planning, +// as re-retrieving it will fail after the message is lazily decoded. +func (f *ExtensionField) lazyBuffer() []byte { + // This function might be in the critical path, so check the atomic without + // taking a look first, then only take the lock if needed. + if !f.isUnexpandedLazy() { + return nil + } + f.lazy.mu.Lock() + defer f.lazy.mu.Unlock() + return f.lazy.b +} + func (f *ExtensionField) lazyInit() { f.lazy.mu.Lock() defer f.lazy.mu.Unlock() @@ -136,10 +157,9 @@ func (f *ExtensionField) lazyInit() { } f.lazy.value = val } else { - f.lazy.value = f.lazy.fn() + panic("No support for lazy fns for ExtensionField") } f.lazy.xi = nil - f.lazy.fn = nil f.lazy.b = nil atomic.StoreUint32(&f.lazy.atomicOnce, 1) } @@ -152,13 +172,6 @@ func (f *ExtensionField) Set(t protoreflect.ExtensionType, v protoreflect.Value) f.lazy = nil } -// SetLazy sets the type and a value that is to be lazily evaluated upon first use. -// This must not be called concurrently. -func (f *ExtensionField) SetLazy(t protoreflect.ExtensionType, fn func() protoreflect.Value) { - f.typ = t - f.lazy = &lazyExtensionValue{fn: fn} -} - // Value returns the value of the extension field. // This may be called concurrently. func (f *ExtensionField) Value() protoreflect.Value { diff --git a/vendor/google.golang.org/protobuf/internal/impl/codec_field.go b/vendor/google.golang.org/protobuf/internal/impl/codec_field.go index 3fadd241e..7c1f66c8c 100644 --- a/vendor/google.golang.org/protobuf/internal/impl/codec_field.go +++ b/vendor/google.golang.org/protobuf/internal/impl/codec_field.go @@ -65,6 +65,9 @@ func (mi *MessageInfo) initOneofFieldCoders(od protoreflect.OneofDescriptor, si if err != nil { return out, err } + if cf.funcs.isInit == nil { + out.initialized = true + } vi.Set(vw) return out, nil } @@ -233,9 +236,15 @@ func sizeMessageInfo(p pointer, f *coderFieldInfo, opts marshalOptions) int { } func appendMessageInfo(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { + calculatedSize := f.mi.sizePointer(p.Elem(), opts) b = protowire.AppendVarint(b, f.wiretag) - b = protowire.AppendVarint(b, uint64(f.mi.sizePointer(p.Elem(), opts))) - return f.mi.marshalAppendPointer(b, p.Elem(), opts) + b = protowire.AppendVarint(b, uint64(calculatedSize)) + before := len(b) + b, err := f.mi.marshalAppendPointer(b, p.Elem(), opts) + if measuredSize := len(b) - before; calculatedSize != measuredSize && err == nil { + return nil, errors.MismatchedSizeCalculation(calculatedSize, measuredSize) + } + return b, err } func consumeMessageInfo(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { @@ -262,14 +271,21 @@ func isInitMessageInfo(p pointer, f *coderFieldInfo) error { return f.mi.checkInitializedPointer(p.Elem()) } -func sizeMessage(m proto.Message, tagsize int, _ marshalOptions) int { - return protowire.SizeBytes(proto.Size(m)) + tagsize +func sizeMessage(m proto.Message, tagsize int, opts marshalOptions) int { + return protowire.SizeBytes(opts.Options().Size(m)) + tagsize } func appendMessage(b []byte, m proto.Message, wiretag uint64, opts marshalOptions) ([]byte, error) { + mopts := opts.Options() + calculatedSize := mopts.Size(m) b = protowire.AppendVarint(b, wiretag) - b = protowire.AppendVarint(b, uint64(proto.Size(m))) - return opts.Options().MarshalAppend(b, m) + b = protowire.AppendVarint(b, uint64(calculatedSize)) + before := len(b) + b, err := mopts.MarshalAppend(b, m) + if measuredSize := len(b) - before; calculatedSize != measuredSize && err == nil { + return nil, errors.MismatchedSizeCalculation(calculatedSize, measuredSize) + } + return b, err } func consumeMessage(b []byte, m proto.Message, wtyp protowire.Type, opts unmarshalOptions) (out unmarshalOutput, err error) { @@ -405,8 +421,8 @@ func consumeGroupType(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInf return f.mi.unmarshalPointer(b, p.Elem(), f.num, opts) } -func sizeGroup(m proto.Message, tagsize int, _ marshalOptions) int { - return 2*tagsize + proto.Size(m) +func sizeGroup(m proto.Message, tagsize int, opts marshalOptions) int { + return 2*tagsize + opts.Options().Size(m) } func appendGroup(b []byte, m proto.Message, wiretag uint64, opts marshalOptions) ([]byte, error) { @@ -482,10 +498,14 @@ func appendMessageSliceInfo(b []byte, p pointer, f *coderFieldInfo, opts marshal b = protowire.AppendVarint(b, f.wiretag) siz := f.mi.sizePointer(v, opts) b = protowire.AppendVarint(b, uint64(siz)) + before := len(b) b, err = f.mi.marshalAppendPointer(b, v, opts) if err != nil { return b, err } + if measuredSize := len(b) - before; siz != measuredSize { + return nil, errors.MismatchedSizeCalculation(siz, measuredSize) + } } return b, nil } @@ -520,28 +540,34 @@ func isInitMessageSliceInfo(p pointer, f *coderFieldInfo) error { return nil } -func sizeMessageSlice(p pointer, goType reflect.Type, tagsize int, _ marshalOptions) int { +func sizeMessageSlice(p pointer, goType reflect.Type, tagsize int, opts marshalOptions) int { + mopts := opts.Options() s := p.PointerSlice() n := 0 for _, v := range s { m := asMessage(v.AsValueOf(goType.Elem())) - n += protowire.SizeBytes(proto.Size(m)) + tagsize + n += protowire.SizeBytes(mopts.Size(m)) + tagsize } return n } func appendMessageSlice(b []byte, p pointer, wiretag uint64, goType reflect.Type, opts marshalOptions) ([]byte, error) { + mopts := opts.Options() s := p.PointerSlice() var err error for _, v := range s { m := asMessage(v.AsValueOf(goType.Elem())) b = protowire.AppendVarint(b, wiretag) - siz := proto.Size(m) + siz := mopts.Size(m) b = protowire.AppendVarint(b, uint64(siz)) - b, err = opts.Options().MarshalAppend(b, m) + before := len(b) + b, err = mopts.MarshalAppend(b, m) if err != nil { return b, err } + if measuredSize := len(b) - before; siz != measuredSize { + return nil, errors.MismatchedSizeCalculation(siz, measuredSize) + } } return b, nil } @@ -582,11 +608,12 @@ func isInitMessageSlice(p pointer, goType reflect.Type) error { // Slices of messages func sizeMessageSliceValue(listv protoreflect.Value, tagsize int, opts marshalOptions) int { + mopts := opts.Options() list := listv.List() n := 0 for i, llen := 0, list.Len(); i < llen; i++ { m := list.Get(i).Message().Interface() - n += protowire.SizeBytes(proto.Size(m)) + tagsize + n += protowire.SizeBytes(mopts.Size(m)) + tagsize } return n } @@ -597,13 +624,17 @@ func appendMessageSliceValue(b []byte, listv protoreflect.Value, wiretag uint64, for i, llen := 0, list.Len(); i < llen; i++ { m := list.Get(i).Message().Interface() b = protowire.AppendVarint(b, wiretag) - siz := proto.Size(m) + siz := mopts.Size(m) b = protowire.AppendVarint(b, uint64(siz)) + before := len(b) var err error b, err = mopts.MarshalAppend(b, m) if err != nil { return b, err } + if measuredSize := len(b) - before; siz != measuredSize { + return nil, errors.MismatchedSizeCalculation(siz, measuredSize) + } } return b, nil } @@ -651,11 +682,12 @@ var coderMessageSliceValue = valueCoderFuncs{ } func sizeGroupSliceValue(listv protoreflect.Value, tagsize int, opts marshalOptions) int { + mopts := opts.Options() list := listv.List() n := 0 for i, llen := 0, list.Len(); i < llen; i++ { m := list.Get(i).Message().Interface() - n += 2*tagsize + proto.Size(m) + n += 2*tagsize + mopts.Size(m) } return n } @@ -738,12 +770,13 @@ func makeGroupSliceFieldCoder(fd protoreflect.FieldDescriptor, ft reflect.Type) } } -func sizeGroupSlice(p pointer, messageType reflect.Type, tagsize int, _ marshalOptions) int { +func sizeGroupSlice(p pointer, messageType reflect.Type, tagsize int, opts marshalOptions) int { + mopts := opts.Options() s := p.PointerSlice() n := 0 for _, v := range s { m := asMessage(v.AsValueOf(messageType.Elem())) - n += 2*tagsize + proto.Size(m) + n += 2*tagsize + mopts.Size(m) } return n } diff --git a/vendor/google.golang.org/protobuf/internal/impl/codec_map.go b/vendor/google.golang.org/protobuf/internal/impl/codec_map.go index 111b9d16f..fb35f0bae 100644 --- a/vendor/google.golang.org/protobuf/internal/impl/codec_map.go +++ b/vendor/google.golang.org/protobuf/internal/impl/codec_map.go @@ -9,6 +9,7 @@ import ( "sort" "google.golang.org/protobuf/encoding/protowire" + "google.golang.org/protobuf/internal/errors" "google.golang.org/protobuf/internal/genid" "google.golang.org/protobuf/reflect/protoreflect" ) @@ -240,11 +241,16 @@ func appendMapItem(b []byte, keyrv, valrv reflect.Value, mapi *mapInfo, f *coder size += mapi.keyFuncs.size(key.Value(), mapKeyTagSize, opts) size += mapi.valFuncs.size(val, mapValTagSize, opts) b = protowire.AppendVarint(b, uint64(size)) + before := len(b) b, err := mapi.keyFuncs.marshal(b, key.Value(), mapi.keyWiretag, opts) if err != nil { return nil, err } - return mapi.valFuncs.marshal(b, val, mapi.valWiretag, opts) + b, err = mapi.valFuncs.marshal(b, val, mapi.valWiretag, opts) + if measuredSize := len(b) - before; size != measuredSize && err == nil { + return nil, errors.MismatchedSizeCalculation(size, measuredSize) + } + return b, err } else { key := mapi.conv.keyConv.PBValueOf(keyrv).MapKey() val := pointerOfValue(valrv) @@ -259,7 +265,12 @@ func appendMapItem(b []byte, keyrv, valrv reflect.Value, mapi *mapInfo, f *coder } b = protowire.AppendVarint(b, mapi.valWiretag) b = protowire.AppendVarint(b, uint64(valSize)) - return f.mi.marshalAppendPointer(b, val, opts) + before := len(b) + b, err = f.mi.marshalAppendPointer(b, val, opts) + if measuredSize := len(b) - before; valSize != measuredSize && err == nil { + return nil, errors.MismatchedSizeCalculation(valSize, measuredSize) + } + return b, err } } diff --git a/vendor/google.golang.org/protobuf/internal/impl/codec_message.go b/vendor/google.golang.org/protobuf/internal/impl/codec_message.go index 6b2fdbb73..78be9df34 100644 --- a/vendor/google.golang.org/protobuf/internal/impl/codec_message.go +++ b/vendor/google.golang.org/protobuf/internal/impl/codec_message.go @@ -189,6 +189,9 @@ func (mi *MessageInfo) makeCoderMethods(t reflect.Type, si structInfo) { if mi.methods.Merge == nil { mi.methods.Merge = mi.merge } + if mi.methods.Equal == nil { + mi.methods.Equal = equal + } } // getUnknownBytes returns a *[]byte for the unknown fields. diff --git a/vendor/google.golang.org/protobuf/internal/impl/codec_messageset.go b/vendor/google.golang.org/protobuf/internal/impl/codec_messageset.go index b7a23faf1..7a16ec13d 100644 --- a/vendor/google.golang.org/protobuf/internal/impl/codec_messageset.go +++ b/vendor/google.golang.org/protobuf/internal/impl/codec_messageset.go @@ -26,6 +26,15 @@ func sizeMessageSet(mi *MessageInfo, p pointer, opts marshalOptions) (size int) } num, _ := protowire.DecodeTag(xi.wiretag) size += messageset.SizeField(num) + if fullyLazyExtensions(opts) { + // Don't expand the extension, instead use the buffer to calculate size + if lb := x.lazyBuffer(); lb != nil { + // We got hold of the buffer, so it's still lazy. + // Don't count the tag size in the extension buffer, it's already added. + size += protowire.SizeTag(messageset.FieldMessage) + len(lb) - xi.tagsize + continue + } + } size += xi.funcs.size(x.Value(), protowire.SizeTag(messageset.FieldMessage), opts) } @@ -85,6 +94,19 @@ func marshalMessageSetField(mi *MessageInfo, b []byte, x ExtensionField, opts ma xi := getExtensionFieldInfo(x.Type()) num, _ := protowire.DecodeTag(xi.wiretag) b = messageset.AppendFieldStart(b, num) + + if fullyLazyExtensions(opts) { + // Don't expand the extension if it's still in wire format, instead use the buffer content. + if lb := x.lazyBuffer(); lb != nil { + // The tag inside the lazy buffer is a different tag (the extension + // number), but what we need here is the tag for FieldMessage: + b = protowire.AppendVarint(b, protowire.EncodeTag(messageset.FieldMessage, protowire.BytesType)) + b = append(b, lb[xi.tagsize:]...) + b = messageset.AppendFieldEnd(b) + return b, nil + } + } + b, err := xi.funcs.marshal(b, x.Value(), protowire.EncodeTag(messageset.FieldMessage, protowire.BytesType), opts) if err != nil { return b, err diff --git a/vendor/google.golang.org/protobuf/internal/impl/codec_reflect.go b/vendor/google.golang.org/protobuf/internal/impl/codec_reflect.go deleted file mode 100644 index 145c577bd..000000000 --- a/vendor/google.golang.org/protobuf/internal/impl/codec_reflect.go +++ /dev/null @@ -1,210 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build purego || appengine -// +build purego appengine - -package impl - -import ( - "reflect" - - "google.golang.org/protobuf/encoding/protowire" -) - -func sizeEnum(p pointer, f *coderFieldInfo, _ marshalOptions) (size int) { - v := p.v.Elem().Int() - return f.tagsize + protowire.SizeVarint(uint64(v)) -} - -func appendEnum(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { - v := p.v.Elem().Int() - b = protowire.AppendVarint(b, f.wiretag) - b = protowire.AppendVarint(b, uint64(v)) - return b, nil -} - -func consumeEnum(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, _ unmarshalOptions) (out unmarshalOutput, err error) { - if wtyp != protowire.VarintType { - return out, errUnknown - } - v, n := protowire.ConsumeVarint(b) - if n < 0 { - return out, errDecode - } - p.v.Elem().SetInt(int64(v)) - out.n = n - return out, nil -} - -func mergeEnum(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { - dst.v.Elem().Set(src.v.Elem()) -} - -var coderEnum = pointerCoderFuncs{ - size: sizeEnum, - marshal: appendEnum, - unmarshal: consumeEnum, - merge: mergeEnum, -} - -func sizeEnumNoZero(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { - if p.v.Elem().Int() == 0 { - return 0 - } - return sizeEnum(p, f, opts) -} - -func appendEnumNoZero(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { - if p.v.Elem().Int() == 0 { - return b, nil - } - return appendEnum(b, p, f, opts) -} - -func mergeEnumNoZero(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { - if src.v.Elem().Int() != 0 { - dst.v.Elem().Set(src.v.Elem()) - } -} - -var coderEnumNoZero = pointerCoderFuncs{ - size: sizeEnumNoZero, - marshal: appendEnumNoZero, - unmarshal: consumeEnum, - merge: mergeEnumNoZero, -} - -func sizeEnumPtr(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { - return sizeEnum(pointer{p.v.Elem()}, f, opts) -} - -func appendEnumPtr(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { - return appendEnum(b, pointer{p.v.Elem()}, f, opts) -} - -func consumeEnumPtr(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { - if wtyp != protowire.VarintType { - return out, errUnknown - } - if p.v.Elem().IsNil() { - p.v.Elem().Set(reflect.New(p.v.Elem().Type().Elem())) - } - return consumeEnum(b, pointer{p.v.Elem()}, wtyp, f, opts) -} - -func mergeEnumPtr(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { - if !src.v.Elem().IsNil() { - v := reflect.New(dst.v.Type().Elem().Elem()) - v.Elem().Set(src.v.Elem().Elem()) - dst.v.Elem().Set(v) - } -} - -var coderEnumPtr = pointerCoderFuncs{ - size: sizeEnumPtr, - marshal: appendEnumPtr, - unmarshal: consumeEnumPtr, - merge: mergeEnumPtr, -} - -func sizeEnumSlice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { - s := p.v.Elem() - for i, llen := 0, s.Len(); i < llen; i++ { - size += protowire.SizeVarint(uint64(s.Index(i).Int())) + f.tagsize - } - return size -} - -func appendEnumSlice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { - s := p.v.Elem() - for i, llen := 0, s.Len(); i < llen; i++ { - b = protowire.AppendVarint(b, f.wiretag) - b = protowire.AppendVarint(b, uint64(s.Index(i).Int())) - } - return b, nil -} - -func consumeEnumSlice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { - s := p.v.Elem() - if wtyp == protowire.BytesType { - b, n := protowire.ConsumeBytes(b) - if n < 0 { - return out, errDecode - } - for len(b) > 0 { - v, n := protowire.ConsumeVarint(b) - if n < 0 { - return out, errDecode - } - rv := reflect.New(s.Type().Elem()).Elem() - rv.SetInt(int64(v)) - s.Set(reflect.Append(s, rv)) - b = b[n:] - } - out.n = n - return out, nil - } - if wtyp != protowire.VarintType { - return out, errUnknown - } - v, n := protowire.ConsumeVarint(b) - if n < 0 { - return out, errDecode - } - rv := reflect.New(s.Type().Elem()).Elem() - rv.SetInt(int64(v)) - s.Set(reflect.Append(s, rv)) - out.n = n - return out, nil -} - -func mergeEnumSlice(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { - dst.v.Elem().Set(reflect.AppendSlice(dst.v.Elem(), src.v.Elem())) -} - -var coderEnumSlice = pointerCoderFuncs{ - size: sizeEnumSlice, - marshal: appendEnumSlice, - unmarshal: consumeEnumSlice, - merge: mergeEnumSlice, -} - -func sizeEnumPackedSlice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { - s := p.v.Elem() - llen := s.Len() - if llen == 0 { - return 0 - } - n := 0 - for i := 0; i < llen; i++ { - n += protowire.SizeVarint(uint64(s.Index(i).Int())) - } - return f.tagsize + protowire.SizeBytes(n) -} - -func appendEnumPackedSlice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { - s := p.v.Elem() - llen := s.Len() - if llen == 0 { - return b, nil - } - b = protowire.AppendVarint(b, f.wiretag) - n := 0 - for i := 0; i < llen; i++ { - n += protowire.SizeVarint(uint64(s.Index(i).Int())) - } - b = protowire.AppendVarint(b, uint64(n)) - for i := 0; i < llen; i++ { - b = protowire.AppendVarint(b, uint64(s.Index(i).Int())) - } - return b, nil -} - -var coderEnumPackedSlice = pointerCoderFuncs{ - size: sizeEnumPackedSlice, - marshal: appendEnumPackedSlice, - unmarshal: consumeEnumSlice, - merge: mergeEnumSlice, -} diff --git a/vendor/google.golang.org/protobuf/internal/impl/codec_unsafe.go b/vendor/google.golang.org/protobuf/internal/impl/codec_unsafe.go index 757642e23..077712c2c 100644 --- a/vendor/google.golang.org/protobuf/internal/impl/codec_unsafe.go +++ b/vendor/google.golang.org/protobuf/internal/impl/codec_unsafe.go @@ -2,9 +2,6 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build !purego && !appengine -// +build !purego,!appengine - package impl // When using unsafe pointers, we can just treat enum values as int32s. diff --git a/vendor/google.golang.org/protobuf/internal/impl/convert.go b/vendor/google.golang.org/protobuf/internal/impl/convert.go index 185ef2efa..f72ddd882 100644 --- a/vendor/google.golang.org/protobuf/internal/impl/convert.go +++ b/vendor/google.golang.org/protobuf/internal/impl/convert.go @@ -14,7 +14,7 @@ import ( // unwrapper unwraps the value to the underlying value. // This is implemented by List and Map. type unwrapper interface { - protoUnwrap() interface{} + protoUnwrap() any } // A Converter coverts to/from Go reflect.Value types and protobuf protoreflect.Value types. @@ -322,7 +322,7 @@ func (c *stringConverter) PBValueOf(v reflect.Value) protoreflect.Value { return protoreflect.ValueOfString(v.Convert(stringType).String()) } func (c *stringConverter) GoValueOf(v protoreflect.Value) reflect.Value { - // pref.Value.String never panics, so we go through an interface + // protoreflect.Value.String never panics, so we go through an interface // conversion here to check the type. s := v.Interface().(string) if c.goType.Kind() == reflect.Slice && s == "" { diff --git a/vendor/google.golang.org/protobuf/internal/impl/convert_list.go b/vendor/google.golang.org/protobuf/internal/impl/convert_list.go index f89136516..18cb96fd7 100644 --- a/vendor/google.golang.org/protobuf/internal/impl/convert_list.go +++ b/vendor/google.golang.org/protobuf/internal/impl/convert_list.go @@ -136,6 +136,6 @@ func (ls *listReflect) NewElement() protoreflect.Value { func (ls *listReflect) IsValid() bool { return !ls.v.IsNil() } -func (ls *listReflect) protoUnwrap() interface{} { +func (ls *listReflect) protoUnwrap() any { return ls.v.Interface() } diff --git a/vendor/google.golang.org/protobuf/internal/impl/convert_map.go b/vendor/google.golang.org/protobuf/internal/impl/convert_map.go index f30b0a057..304244a65 100644 --- a/vendor/google.golang.org/protobuf/internal/impl/convert_map.go +++ b/vendor/google.golang.org/protobuf/internal/impl/convert_map.go @@ -116,6 +116,6 @@ func (ms *mapReflect) NewValue() protoreflect.Value { func (ms *mapReflect) IsValid() bool { return !ms.v.IsNil() } -func (ms *mapReflect) protoUnwrap() interface{} { +func (ms *mapReflect) protoUnwrap() any { return ms.v.Interface() } diff --git a/vendor/google.golang.org/protobuf/internal/impl/encode.go b/vendor/google.golang.org/protobuf/internal/impl/encode.go index 845c67d6e..6254f5de4 100644 --- a/vendor/google.golang.org/protobuf/internal/impl/encode.go +++ b/vendor/google.golang.org/protobuf/internal/impl/encode.go @@ -10,7 +10,7 @@ import ( "sync/atomic" "google.golang.org/protobuf/internal/flags" - proto "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/proto" piface "google.golang.org/protobuf/runtime/protoiface" ) @@ -49,8 +49,11 @@ func (mi *MessageInfo) sizePointer(p pointer, opts marshalOptions) (size int) { return 0 } if opts.UseCachedSize() && mi.sizecacheOffset.IsValid() { - if size := atomic.LoadInt32(p.Apply(mi.sizecacheOffset).Int32()); size >= 0 { - return int(size) + // The size cache contains the size + 1, to allow the + // zero value to be invalid, while also allowing for a + // 0 size to be cached. + if size := atomic.LoadInt32(p.Apply(mi.sizecacheOffset).Int32()); size > 0 { + return int(size - 1) } } return mi.sizePointerSlow(p, opts) @@ -60,7 +63,7 @@ func (mi *MessageInfo) sizePointerSlow(p pointer, opts marshalOptions) (size int if flags.ProtoLegacy && mi.isMessageSet { size = sizeMessageSet(mi, p, opts) if mi.sizecacheOffset.IsValid() { - atomic.StoreInt32(p.Apply(mi.sizecacheOffset).Int32(), int32(size)) + atomic.StoreInt32(p.Apply(mi.sizecacheOffset).Int32(), int32(size+1)) } return size } @@ -84,13 +87,16 @@ func (mi *MessageInfo) sizePointerSlow(p pointer, opts marshalOptions) (size int } } if mi.sizecacheOffset.IsValid() { - if size > math.MaxInt32 { + if size > (math.MaxInt32 - 1) { // The size is too large for the int32 sizecache field. // We will need to recompute the size when encoding; // unfortunately expensive, but better than invalid output. - atomic.StoreInt32(p.Apply(mi.sizecacheOffset).Int32(), -1) + atomic.StoreInt32(p.Apply(mi.sizecacheOffset).Int32(), 0) } else { - atomic.StoreInt32(p.Apply(mi.sizecacheOffset).Int32(), int32(size)) + // The size cache contains the size + 1, to allow the + // zero value to be invalid, while also allowing for a + // 0 size to be cached. + atomic.StoreInt32(p.Apply(mi.sizecacheOffset).Int32(), int32(size+1)) } } return size @@ -149,6 +155,14 @@ func (mi *MessageInfo) marshalAppendPointer(b []byte, p pointer, opts marshalOpt return b, nil } +// fullyLazyExtensions returns true if we should attempt to keep extensions lazy over size and marshal. +func fullyLazyExtensions(opts marshalOptions) bool { + // When deterministic marshaling is requested, force an unmarshal for lazy + // extensions to produce a deterministic result, instead of passing through + // bytes lazily that may or may not match what Go Protobuf would produce. + return opts.flags&piface.MarshalDeterministic == 0 +} + func (mi *MessageInfo) sizeExtensions(ext *map[int32]ExtensionField, opts marshalOptions) (n int) { if ext == nil { return 0 @@ -158,6 +172,14 @@ func (mi *MessageInfo) sizeExtensions(ext *map[int32]ExtensionField, opts marsha if xi.funcs.size == nil { continue } + if fullyLazyExtensions(opts) { + // Don't expand the extension, instead use the buffer to calculate size + if lb := x.lazyBuffer(); lb != nil { + // We got hold of the buffer, so it's still lazy. + n += len(lb) + continue + } + } n += xi.funcs.size(x.Value(), xi.tagsize, opts) } return n @@ -176,6 +198,13 @@ func (mi *MessageInfo) appendExtensions(b []byte, ext *map[int32]ExtensionField, var err error for _, x := range *ext { xi := getExtensionFieldInfo(x.Type()) + if fullyLazyExtensions(opts) { + // Don't expand the extension if it's still in wire format, instead use the buffer content. + if lb := x.lazyBuffer(); lb != nil { + b = append(b, lb...) + continue + } + } b, err = xi.funcs.marshal(b, x.Value(), xi.wiretag, opts) } return b, err @@ -191,6 +220,13 @@ func (mi *MessageInfo) appendExtensions(b []byte, ext *map[int32]ExtensionField, for _, k := range keys { x := (*ext)[int32(k)] xi := getExtensionFieldInfo(x.Type()) + if fullyLazyExtensions(opts) { + // Don't expand the extension if it's still in wire format, instead use the buffer content. + if lb := x.lazyBuffer(); lb != nil { + b = append(b, lb...) + continue + } + } b, err = xi.funcs.marshal(b, x.Value(), xi.wiretag, opts) if err != nil { return b, err diff --git a/vendor/google.golang.org/protobuf/internal/impl/equal.go b/vendor/google.golang.org/protobuf/internal/impl/equal.go new file mode 100644 index 000000000..9f6c32a7d --- /dev/null +++ b/vendor/google.golang.org/protobuf/internal/impl/equal.go @@ -0,0 +1,224 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package impl + +import ( + "bytes" + + "google.golang.org/protobuf/encoding/protowire" + "google.golang.org/protobuf/reflect/protoreflect" + "google.golang.org/protobuf/runtime/protoiface" +) + +func equal(in protoiface.EqualInput) protoiface.EqualOutput { + return protoiface.EqualOutput{Equal: equalMessage(in.MessageA, in.MessageB)} +} + +// equalMessage is a fast-path variant of protoreflect.equalMessage. +// It takes advantage of the internal messageState type to avoid +// unnecessary allocations, type assertions. +func equalMessage(mx, my protoreflect.Message) bool { + if mx == nil || my == nil { + return mx == my + } + if mx.Descriptor() != my.Descriptor() { + return false + } + + msx, ok := mx.(*messageState) + if !ok { + return protoreflect.ValueOfMessage(mx).Equal(protoreflect.ValueOfMessage(my)) + } + msy, ok := my.(*messageState) + if !ok { + return protoreflect.ValueOfMessage(mx).Equal(protoreflect.ValueOfMessage(my)) + } + + mi := msx.messageInfo() + miy := msy.messageInfo() + if mi != miy { + return protoreflect.ValueOfMessage(mx).Equal(protoreflect.ValueOfMessage(my)) + } + mi.init() + // Compares regular fields + // Modified Message.Range code that compares two messages of the same type + // while going over the fields. + for _, ri := range mi.rangeInfos { + var fd protoreflect.FieldDescriptor + var vx, vy protoreflect.Value + + switch ri := ri.(type) { + case *fieldInfo: + hx := ri.has(msx.pointer()) + hy := ri.has(msy.pointer()) + if hx != hy { + return false + } + if !hx { + continue + } + fd = ri.fieldDesc + vx = ri.get(msx.pointer()) + vy = ri.get(msy.pointer()) + case *oneofInfo: + fnx := ri.which(msx.pointer()) + fny := ri.which(msy.pointer()) + if fnx != fny { + return false + } + if fnx <= 0 { + continue + } + fi := mi.fields[fnx] + fd = fi.fieldDesc + vx = fi.get(msx.pointer()) + vy = fi.get(msy.pointer()) + } + + if !equalValue(fd, vx, vy) { + return false + } + } + + // Compare extensions. + // This is more complicated because mx or my could have empty/nil extension maps, + // however some populated extension map values are equal to nil extension maps. + emx := mi.extensionMap(msx.pointer()) + emy := mi.extensionMap(msy.pointer()) + if emx != nil { + for k, x := range *emx { + xd := x.Type().TypeDescriptor() + xv := x.Value() + var y ExtensionField + ok := false + if emy != nil { + y, ok = (*emy)[k] + } + // We need to treat empty lists as equal to nil values + if emy == nil || !ok { + if xd.IsList() && xv.List().Len() == 0 { + continue + } + return false + } + + if !equalValue(xd, xv, y.Value()) { + return false + } + } + } + if emy != nil { + // emy may have extensions emx does not have, need to check them as well + for k, y := range *emy { + if emx != nil { + // emx has the field, so we already checked it + if _, ok := (*emx)[k]; ok { + continue + } + } + // Empty lists are equal to nil + if y.Type().TypeDescriptor().IsList() && y.Value().List().Len() == 0 { + continue + } + + // Cant be equal if the extension is populated + return false + } + } + + return equalUnknown(mx.GetUnknown(), my.GetUnknown()) +} + +func equalValue(fd protoreflect.FieldDescriptor, vx, vy protoreflect.Value) bool { + // slow path + if fd.Kind() != protoreflect.MessageKind { + return vx.Equal(vy) + } + + // fast path special cases + if fd.IsMap() { + if fd.MapValue().Kind() == protoreflect.MessageKind { + return equalMessageMap(vx.Map(), vy.Map()) + } + return vx.Equal(vy) + } + + if fd.IsList() { + return equalMessageList(vx.List(), vy.List()) + } + + return equalMessage(vx.Message(), vy.Message()) +} + +// Mostly copied from protoreflect.equalMap. +// This variant only works for messages as map types. +// All other map types should be handled via Value.Equal. +func equalMessageMap(mx, my protoreflect.Map) bool { + if mx.Len() != my.Len() { + return false + } + equal := true + mx.Range(func(k protoreflect.MapKey, vx protoreflect.Value) bool { + if !my.Has(k) { + equal = false + return false + } + vy := my.Get(k) + equal = equalMessage(vx.Message(), vy.Message()) + return equal + }) + return equal +} + +// Mostly copied from protoreflect.equalList. +// The only change is the usage of equalImpl instead of protoreflect.equalValue. +func equalMessageList(lx, ly protoreflect.List) bool { + if lx.Len() != ly.Len() { + return false + } + for i := 0; i < lx.Len(); i++ { + // We only operate on messages here since equalImpl will not call us in any other case. + if !equalMessage(lx.Get(i).Message(), ly.Get(i).Message()) { + return false + } + } + return true +} + +// equalUnknown compares unknown fields by direct comparison on the raw bytes +// of each individual field number. +// Copied from protoreflect.equalUnknown. +func equalUnknown(x, y protoreflect.RawFields) bool { + if len(x) != len(y) { + return false + } + if bytes.Equal([]byte(x), []byte(y)) { + return true + } + + mx := make(map[protoreflect.FieldNumber]protoreflect.RawFields) + my := make(map[protoreflect.FieldNumber]protoreflect.RawFields) + for len(x) > 0 { + fnum, _, n := protowire.ConsumeField(x) + mx[fnum] = append(mx[fnum], x[:n]...) + x = x[n:] + } + for len(y) > 0 { + fnum, _, n := protowire.ConsumeField(y) + my[fnum] = append(my[fnum], y[:n]...) + y = y[n:] + } + if len(mx) != len(my) { + return false + } + + for k, v1 := range mx { + if v2, ok := my[k]; !ok || !bytes.Equal([]byte(v1), []byte(v2)) { + return false + } + } + + return true +} diff --git a/vendor/google.golang.org/protobuf/internal/impl/extension.go b/vendor/google.golang.org/protobuf/internal/impl/extension.go index cb25b0bae..e31249f64 100644 --- a/vendor/google.golang.org/protobuf/internal/impl/extension.go +++ b/vendor/google.golang.org/protobuf/internal/impl/extension.go @@ -53,7 +53,7 @@ type ExtensionInfo struct { // type returned by InterfaceOf may not be identical. // // Deprecated: Use InterfaceOf(xt.Zero()) instead. - ExtensionType interface{} + ExtensionType any // Field is the field number of the extension. // @@ -95,16 +95,16 @@ func (xi *ExtensionInfo) New() protoreflect.Value { func (xi *ExtensionInfo) Zero() protoreflect.Value { return xi.lazyInit().Zero() } -func (xi *ExtensionInfo) ValueOf(v interface{}) protoreflect.Value { +func (xi *ExtensionInfo) ValueOf(v any) protoreflect.Value { return xi.lazyInit().PBValueOf(reflect.ValueOf(v)) } -func (xi *ExtensionInfo) InterfaceOf(v protoreflect.Value) interface{} { +func (xi *ExtensionInfo) InterfaceOf(v protoreflect.Value) any { return xi.lazyInit().GoValueOf(v).Interface() } func (xi *ExtensionInfo) IsValidValue(v protoreflect.Value) bool { return xi.lazyInit().IsValidPB(v) } -func (xi *ExtensionInfo) IsValidInterface(v interface{}) bool { +func (xi *ExtensionInfo) IsValidInterface(v any) bool { return xi.lazyInit().IsValidGo(reflect.ValueOf(v)) } func (xi *ExtensionInfo) TypeDescriptor() protoreflect.ExtensionTypeDescriptor { diff --git a/vendor/google.golang.org/protobuf/internal/impl/legacy_enum.go b/vendor/google.golang.org/protobuf/internal/impl/legacy_enum.go index c2a803bb2..81b2b1a76 100644 --- a/vendor/google.golang.org/protobuf/internal/impl/legacy_enum.go +++ b/vendor/google.golang.org/protobuf/internal/impl/legacy_enum.go @@ -97,7 +97,7 @@ func (e *legacyEnumWrapper) Number() protoreflect.EnumNumber { func (e *legacyEnumWrapper) ProtoReflect() protoreflect.Enum { return e } -func (e *legacyEnumWrapper) protoUnwrap() interface{} { +func (e *legacyEnumWrapper) protoUnwrap() any { v := reflect.New(e.goTyp).Elem() v.SetInt(int64(e.num)) return v.Interface() @@ -167,6 +167,7 @@ func aberrantLoadEnumDesc(t reflect.Type) protoreflect.EnumDescriptor { ed := &filedesc.Enum{L2: new(filedesc.EnumL2)} ed.L0.FullName = AberrantDeriveFullName(t) // e.g., github_com.user.repo.MyEnum ed.L0.ParentFile = filedesc.SurrogateProto3 + ed.L1.EditionFeatures = ed.L0.ParentFile.L1.EditionFeatures ed.L2.Values.List = append(ed.L2.Values.List, filedesc.EnumValue{}) // TODO: Use the presence of a UnmarshalJSON method to determine proto2? diff --git a/vendor/google.golang.org/protobuf/internal/impl/legacy_extension.go b/vendor/google.golang.org/protobuf/internal/impl/legacy_extension.go index 87b30d050..b6849d669 100644 --- a/vendor/google.golang.org/protobuf/internal/impl/legacy_extension.go +++ b/vendor/google.golang.org/protobuf/internal/impl/legacy_extension.go @@ -118,7 +118,7 @@ func (xi *ExtensionInfo) initFromLegacy() { xd.L1.Number = protoreflect.FieldNumber(xi.Field) xd.L1.Cardinality = fd.L1.Cardinality xd.L1.Kind = fd.L1.Kind - xd.L2.IsPacked = fd.L1.IsPacked + xd.L1.EditionFeatures = fd.L1.EditionFeatures xd.L2.Default = fd.L1.Default xd.L1.Extendee = Export{}.MessageDescriptorOf(xi.ExtendedType) xd.L2.Enum = ed @@ -160,6 +160,7 @@ func (x placeholderExtension) HasPresence() bool func (x placeholderExtension) HasOptionalKeyword() bool { return false } func (x placeholderExtension) IsExtension() bool { return true } func (x placeholderExtension) IsWeak() bool { return false } +func (x placeholderExtension) IsLazy() bool { return false } func (x placeholderExtension) IsPacked() bool { return false } func (x placeholderExtension) IsList() bool { return false } func (x placeholderExtension) IsMap() bool { return false } diff --git a/vendor/google.golang.org/protobuf/internal/impl/legacy_file.go b/vendor/google.golang.org/protobuf/internal/impl/legacy_file.go index 9ab091086..b649f1124 100644 --- a/vendor/google.golang.org/protobuf/internal/impl/legacy_file.go +++ b/vendor/google.golang.org/protobuf/internal/impl/legacy_file.go @@ -7,7 +7,7 @@ package impl import ( "bytes" "compress/gzip" - "io/ioutil" + "io" "sync" "google.golang.org/protobuf/internal/filedesc" @@ -51,7 +51,7 @@ func legacyLoadFileDesc(b []byte) protoreflect.FileDescriptor { if err != nil { panic(err) } - b2, err := ioutil.ReadAll(zr) + b2, err := io.ReadAll(zr) if err != nil { panic(err) } diff --git a/vendor/google.golang.org/protobuf/internal/impl/legacy_message.go b/vendor/google.golang.org/protobuf/internal/impl/legacy_message.go index 2ab2c6297..bf0b6049b 100644 --- a/vendor/google.golang.org/protobuf/internal/impl/legacy_message.go +++ b/vendor/google.golang.org/protobuf/internal/impl/legacy_message.go @@ -204,6 +204,7 @@ func aberrantLoadMessageDescReentrant(t reflect.Type, name protoreflect.FullName } } + md.L1.EditionFeatures = md.L0.ParentFile.L1.EditionFeatures // Obtain a list of oneof wrapper types. var oneofWrappers []reflect.Type methods := make([]reflect.Method, 0, 2) @@ -215,7 +216,7 @@ func aberrantLoadMessageDescReentrant(t reflect.Type, name protoreflect.FullName } for _, fn := range methods { for _, v := range fn.Func.Call([]reflect.Value{reflect.Zero(fn.Type.In(0))}) { - if vs, ok := v.Interface().([]interface{}); ok { + if vs, ok := v.Interface().([]any); ok { for _, v := range vs { oneofWrappers = append(oneofWrappers, reflect.TypeOf(v)) } @@ -250,6 +251,7 @@ func aberrantLoadMessageDescReentrant(t reflect.Type, name protoreflect.FullName od := &md.L2.Oneofs.List[n] od.L0.FullName = md.FullName().Append(protoreflect.Name(tag)) od.L0.ParentFile = md.L0.ParentFile + od.L1.EditionFeatures = md.L1.EditionFeatures od.L0.Parent = md od.L0.Index = n @@ -260,6 +262,7 @@ func aberrantLoadMessageDescReentrant(t reflect.Type, name protoreflect.FullName aberrantAppendField(md, f.Type, tag, "", "") fd := &md.L2.Fields.List[len(md.L2.Fields.List)-1] fd.L1.ContainingOneof = od + fd.L1.EditionFeatures = od.L1.EditionFeatures od.L1.Fields.List = append(od.L1.Fields.List, fd) } } @@ -307,14 +310,14 @@ func aberrantAppendField(md *filedesc.Message, goType reflect.Type, tag, tagKey, fd.L0.Parent = md fd.L0.Index = n - if fd.L1.IsWeak || fd.L1.HasPacked { + if fd.L1.IsWeak || fd.L1.EditionFeatures.IsPacked { fd.L1.Options = func() protoreflect.ProtoMessage { opts := descopts.Field.ProtoReflect().New() if fd.L1.IsWeak { opts.Set(opts.Descriptor().Fields().ByName("weak"), protoreflect.ValueOfBool(true)) } - if fd.L1.HasPacked { - opts.Set(opts.Descriptor().Fields().ByName("packed"), protoreflect.ValueOfBool(fd.L1.IsPacked)) + if fd.L1.EditionFeatures.IsPacked { + opts.Set(opts.Descriptor().Fields().ByName("packed"), protoreflect.ValueOfBool(fd.L1.EditionFeatures.IsPacked)) } return opts.Interface() } @@ -344,6 +347,7 @@ func aberrantAppendField(md *filedesc.Message, goType reflect.Type, tag, tagKey, md2.L0.ParentFile = md.L0.ParentFile md2.L0.Parent = md md2.L0.Index = n + md2.L1.EditionFeatures = md.L1.EditionFeatures md2.L1.IsMapEntry = true md2.L2.Options = func() protoreflect.ProtoMessage { @@ -563,6 +567,6 @@ func (m aberrantMessage) IsValid() bool { func (m aberrantMessage) ProtoMethods() *protoiface.Methods { return aberrantProtoMethods } -func (m aberrantMessage) protoUnwrap() interface{} { +func (m aberrantMessage) protoUnwrap() any { return m.v.Interface() } diff --git a/vendor/google.golang.org/protobuf/internal/impl/message.go b/vendor/google.golang.org/protobuf/internal/impl/message.go index 629bacdce..741b5ed29 100644 --- a/vendor/google.golang.org/protobuf/internal/impl/message.go +++ b/vendor/google.golang.org/protobuf/internal/impl/message.go @@ -30,12 +30,12 @@ type MessageInfo struct { // Desc is the underlying message descriptor type and must be populated. Desc protoreflect.MessageDescriptor - // Exporter must be provided in a purego environment in order to provide - // access to unexported fields. + // Deprecated: Exporter will be removed the next time we bump + // protoimpl.GenVersion. See https://github.com/golang/protobuf/issues/1640 Exporter exporter // OneofWrappers is list of pointers to oneof wrapper struct types. - OneofWrappers []interface{} + OneofWrappers []any initMu sync.Mutex // protects all unexported fields initDone uint32 @@ -47,7 +47,7 @@ type MessageInfo struct { // exporter is a function that returns a reference to the ith field of v, // where v is a pointer to a struct. It returns nil if it does not support // exporting the requested field (e.g., already exported). -type exporter func(v interface{}, i int) interface{} +type exporter func(v any, i int) any // getMessageInfo returns the MessageInfo for any message type that // is generated by our implementation of protoc-gen-go (for v2 and on). @@ -201,7 +201,7 @@ fieldLoop: } for _, fn := range methods { for _, v := range fn.Func.Call([]reflect.Value{reflect.Zero(fn.Type.In(0))}) { - if vs, ok := v.Interface().([]interface{}); ok { + if vs, ok := v.Interface().([]any); ok { oneofWrappers = vs } } @@ -256,7 +256,7 @@ func (mi *MessageInfo) Message(i int) protoreflect.MessageType { type mapEntryType struct { desc protoreflect.MessageDescriptor - valType interface{} // zero value of enum or message type + valType any // zero value of enum or message type } func (mt mapEntryType) New() protoreflect.Message { diff --git a/vendor/google.golang.org/protobuf/internal/impl/message_reflect.go b/vendor/google.golang.org/protobuf/internal/impl/message_reflect.go index d9ea010be..ecb4623d7 100644 --- a/vendor/google.golang.org/protobuf/internal/impl/message_reflect.go +++ b/vendor/google.golang.org/protobuf/internal/impl/message_reflect.go @@ -20,7 +20,7 @@ type reflectMessageInfo struct { // fieldTypes contains the zero value of an enum or message field. // For lists, it contains the element type. // For maps, it contains the entry value type. - fieldTypes map[protoreflect.FieldNumber]interface{} + fieldTypes map[protoreflect.FieldNumber]any // denseFields is a subset of fields where: // 0 < fieldDesc.Number() < len(denseFields) @@ -28,7 +28,7 @@ type reflectMessageInfo struct { denseFields []*fieldInfo // rangeInfos is a list of all fields (not belonging to a oneof) and oneofs. - rangeInfos []interface{} // either *fieldInfo or *oneofInfo + rangeInfos []any // either *fieldInfo or *oneofInfo getUnknown func(pointer) protoreflect.RawFields setUnknown func(pointer, protoreflect.RawFields) @@ -224,7 +224,7 @@ func (mi *MessageInfo) makeFieldTypes(si structInfo) { } if ft != nil { if mi.fieldTypes == nil { - mi.fieldTypes = make(map[protoreflect.FieldNumber]interface{}) + mi.fieldTypes = make(map[protoreflect.FieldNumber]any) } mi.fieldTypes[fd.Number()] = reflect.Zero(ft).Interface() } @@ -247,39 +247,39 @@ func (m *extensionMap) Range(f func(protoreflect.FieldDescriptor, protoreflect.V } } } -func (m *extensionMap) Has(xt protoreflect.ExtensionType) (ok bool) { +func (m *extensionMap) Has(xd protoreflect.ExtensionTypeDescriptor) (ok bool) { if m == nil { return false } - xd := xt.TypeDescriptor() x, ok := (*m)[int32(xd.Number())] if !ok { return false } + if x.isUnexpandedLazy() { + // Avoid calling x.Value(), which triggers a lazy unmarshal. + return true + } switch { case xd.IsList(): return x.Value().List().Len() > 0 case xd.IsMap(): return x.Value().Map().Len() > 0 - case xd.Message() != nil: - return x.Value().Message().IsValid() } return true } -func (m *extensionMap) Clear(xt protoreflect.ExtensionType) { - delete(*m, int32(xt.TypeDescriptor().Number())) +func (m *extensionMap) Clear(xd protoreflect.ExtensionTypeDescriptor) { + delete(*m, int32(xd.Number())) } -func (m *extensionMap) Get(xt protoreflect.ExtensionType) protoreflect.Value { - xd := xt.TypeDescriptor() +func (m *extensionMap) Get(xd protoreflect.ExtensionTypeDescriptor) protoreflect.Value { if m != nil { if x, ok := (*m)[int32(xd.Number())]; ok { return x.Value() } } - return xt.Zero() + return xd.Type().Zero() } -func (m *extensionMap) Set(xt protoreflect.ExtensionType, v protoreflect.Value) { - xd := xt.TypeDescriptor() +func (m *extensionMap) Set(xd protoreflect.ExtensionTypeDescriptor, v protoreflect.Value) { + xt := xd.Type() isValid := true switch { case !xt.IsValidValue(v): @@ -292,7 +292,7 @@ func (m *extensionMap) Set(xt protoreflect.ExtensionType, v protoreflect.Value) isValid = v.Message().IsValid() } if !isValid { - panic(fmt.Sprintf("%v: assigning invalid value", xt.TypeDescriptor().FullName())) + panic(fmt.Sprintf("%v: assigning invalid value", xd.FullName())) } if *m == nil { @@ -302,16 +302,15 @@ func (m *extensionMap) Set(xt protoreflect.ExtensionType, v protoreflect.Value) x.Set(xt, v) (*m)[int32(xd.Number())] = x } -func (m *extensionMap) Mutable(xt protoreflect.ExtensionType) protoreflect.Value { - xd := xt.TypeDescriptor() +func (m *extensionMap) Mutable(xd protoreflect.ExtensionTypeDescriptor) protoreflect.Value { if xd.Kind() != protoreflect.MessageKind && xd.Kind() != protoreflect.GroupKind && !xd.IsList() && !xd.IsMap() { panic("invalid Mutable on field with non-composite type") } if x, ok := (*m)[int32(xd.Number())]; ok { return x.Value() } - v := xt.New() - m.Set(xt, v) + v := xd.Type().New() + m.Set(xd, v) return v } @@ -394,7 +393,7 @@ var ( // MessageOf returns a reflective view over a message. The input must be a // pointer to a named Go struct. If the provided type has a ProtoReflect method, // it must be implemented by calling this method. -func (mi *MessageInfo) MessageOf(m interface{}) protoreflect.Message { +func (mi *MessageInfo) MessageOf(m any) protoreflect.Message { if reflect.TypeOf(m) != mi.GoReflectType { panic(fmt.Sprintf("type mismatch: got %T, want %v", m, mi.GoReflectType)) } @@ -422,13 +421,13 @@ func (m *messageIfaceWrapper) Reset() { func (m *messageIfaceWrapper) ProtoReflect() protoreflect.Message { return (*messageReflectWrapper)(m) } -func (m *messageIfaceWrapper) protoUnwrap() interface{} { +func (m *messageIfaceWrapper) protoUnwrap() any { return m.p.AsIfaceOf(m.mi.GoReflectType.Elem()) } // checkField verifies that the provided field descriptor is valid. // Exactly one of the returned values is populated. -func (mi *MessageInfo) checkField(fd protoreflect.FieldDescriptor) (*fieldInfo, protoreflect.ExtensionType) { +func (mi *MessageInfo) checkField(fd protoreflect.FieldDescriptor) (*fieldInfo, protoreflect.ExtensionTypeDescriptor) { var fi *fieldInfo if n := fd.Number(); 0 < n && int(n) < len(mi.denseFields) { fi = mi.denseFields[n] @@ -457,7 +456,7 @@ func (mi *MessageInfo) checkField(fd protoreflect.FieldDescriptor) (*fieldInfo, if !ok { panic(fmt.Sprintf("extension %v does not implement protoreflect.ExtensionTypeDescriptor", fd.FullName())) } - return nil, xtd.Type() + return nil, xtd } panic(fmt.Sprintf("field %v is invalid", fd.FullName())) } diff --git a/vendor/google.golang.org/protobuf/internal/impl/message_reflect_gen.go b/vendor/google.golang.org/protobuf/internal/impl/message_reflect_gen.go index 741d6e5b6..99dc23c6f 100644 --- a/vendor/google.golang.org/protobuf/internal/impl/message_reflect_gen.go +++ b/vendor/google.golang.org/protobuf/internal/impl/message_reflect_gen.go @@ -23,12 +23,13 @@ func (m *messageState) New() protoreflect.Message { func (m *messageState) Interface() protoreflect.ProtoMessage { return m.protoUnwrap().(protoreflect.ProtoMessage) } -func (m *messageState) protoUnwrap() interface{} { +func (m *messageState) protoUnwrap() any { return m.pointer().AsIfaceOf(m.messageInfo().GoReflectType.Elem()) } func (m *messageState) ProtoMethods() *protoiface.Methods { - m.messageInfo().init() - return &m.messageInfo().methods + mi := m.messageInfo() + mi.init() + return &mi.methods } // ProtoMessageInfo is a pseudo-internal API for allowing the v1 code @@ -41,8 +42,9 @@ func (m *messageState) ProtoMessageInfo() *MessageInfo { } func (m *messageState) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) { - m.messageInfo().init() - for _, ri := range m.messageInfo().rangeInfos { + mi := m.messageInfo() + mi.init() + for _, ri := range mi.rangeInfos { switch ri := ri.(type) { case *fieldInfo: if ri.has(m.pointer()) { @@ -52,77 +54,86 @@ func (m *messageState) Range(f func(protoreflect.FieldDescriptor, protoreflect.V } case *oneofInfo: if n := ri.which(m.pointer()); n > 0 { - fi := m.messageInfo().fields[n] + fi := mi.fields[n] if !f(fi.fieldDesc, fi.get(m.pointer())) { return } } } } - m.messageInfo().extensionMap(m.pointer()).Range(f) + mi.extensionMap(m.pointer()).Range(f) } func (m *messageState) Has(fd protoreflect.FieldDescriptor) bool { - m.messageInfo().init() - if fi, xt := m.messageInfo().checkField(fd); fi != nil { + mi := m.messageInfo() + mi.init() + if fi, xd := mi.checkField(fd); fi != nil { return fi.has(m.pointer()) } else { - return m.messageInfo().extensionMap(m.pointer()).Has(xt) + return mi.extensionMap(m.pointer()).Has(xd) } } func (m *messageState) Clear(fd protoreflect.FieldDescriptor) { - m.messageInfo().init() - if fi, xt := m.messageInfo().checkField(fd); fi != nil { + mi := m.messageInfo() + mi.init() + if fi, xd := mi.checkField(fd); fi != nil { fi.clear(m.pointer()) } else { - m.messageInfo().extensionMap(m.pointer()).Clear(xt) + mi.extensionMap(m.pointer()).Clear(xd) } } func (m *messageState) Get(fd protoreflect.FieldDescriptor) protoreflect.Value { - m.messageInfo().init() - if fi, xt := m.messageInfo().checkField(fd); fi != nil { + mi := m.messageInfo() + mi.init() + if fi, xd := mi.checkField(fd); fi != nil { return fi.get(m.pointer()) } else { - return m.messageInfo().extensionMap(m.pointer()).Get(xt) + return mi.extensionMap(m.pointer()).Get(xd) } } func (m *messageState) Set(fd protoreflect.FieldDescriptor, v protoreflect.Value) { - m.messageInfo().init() - if fi, xt := m.messageInfo().checkField(fd); fi != nil { + mi := m.messageInfo() + mi.init() + if fi, xd := mi.checkField(fd); fi != nil { fi.set(m.pointer(), v) } else { - m.messageInfo().extensionMap(m.pointer()).Set(xt, v) + mi.extensionMap(m.pointer()).Set(xd, v) } } func (m *messageState) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value { - m.messageInfo().init() - if fi, xt := m.messageInfo().checkField(fd); fi != nil { + mi := m.messageInfo() + mi.init() + if fi, xd := mi.checkField(fd); fi != nil { return fi.mutable(m.pointer()) } else { - return m.messageInfo().extensionMap(m.pointer()).Mutable(xt) + return mi.extensionMap(m.pointer()).Mutable(xd) } } func (m *messageState) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value { - m.messageInfo().init() - if fi, xt := m.messageInfo().checkField(fd); fi != nil { + mi := m.messageInfo() + mi.init() + if fi, xd := mi.checkField(fd); fi != nil { return fi.newField() } else { - return xt.New() + return xd.Type().New() } } func (m *messageState) WhichOneof(od protoreflect.OneofDescriptor) protoreflect.FieldDescriptor { - m.messageInfo().init() - if oi := m.messageInfo().oneofs[od.Name()]; oi != nil && oi.oneofDesc == od { + mi := m.messageInfo() + mi.init() + if oi := mi.oneofs[od.Name()]; oi != nil && oi.oneofDesc == od { return od.Fields().ByNumber(oi.which(m.pointer())) } panic("invalid oneof descriptor " + string(od.FullName()) + " for message " + string(m.Descriptor().FullName())) } func (m *messageState) GetUnknown() protoreflect.RawFields { - m.messageInfo().init() - return m.messageInfo().getUnknown(m.pointer()) + mi := m.messageInfo() + mi.init() + return mi.getUnknown(m.pointer()) } func (m *messageState) SetUnknown(b protoreflect.RawFields) { - m.messageInfo().init() - m.messageInfo().setUnknown(m.pointer(), b) + mi := m.messageInfo() + mi.init() + mi.setUnknown(m.pointer(), b) } func (m *messageState) IsValid() bool { return !m.pointer().IsNil() @@ -143,12 +154,13 @@ func (m *messageReflectWrapper) Interface() protoreflect.ProtoMessage { } return (*messageIfaceWrapper)(m) } -func (m *messageReflectWrapper) protoUnwrap() interface{} { +func (m *messageReflectWrapper) protoUnwrap() any { return m.pointer().AsIfaceOf(m.messageInfo().GoReflectType.Elem()) } func (m *messageReflectWrapper) ProtoMethods() *protoiface.Methods { - m.messageInfo().init() - return &m.messageInfo().methods + mi := m.messageInfo() + mi.init() + return &mi.methods } // ProtoMessageInfo is a pseudo-internal API for allowing the v1 code @@ -161,8 +173,9 @@ func (m *messageReflectWrapper) ProtoMessageInfo() *MessageInfo { } func (m *messageReflectWrapper) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) { - m.messageInfo().init() - for _, ri := range m.messageInfo().rangeInfos { + mi := m.messageInfo() + mi.init() + for _, ri := range mi.rangeInfos { switch ri := ri.(type) { case *fieldInfo: if ri.has(m.pointer()) { @@ -172,77 +185,86 @@ func (m *messageReflectWrapper) Range(f func(protoreflect.FieldDescriptor, proto } case *oneofInfo: if n := ri.which(m.pointer()); n > 0 { - fi := m.messageInfo().fields[n] + fi := mi.fields[n] if !f(fi.fieldDesc, fi.get(m.pointer())) { return } } } } - m.messageInfo().extensionMap(m.pointer()).Range(f) + mi.extensionMap(m.pointer()).Range(f) } func (m *messageReflectWrapper) Has(fd protoreflect.FieldDescriptor) bool { - m.messageInfo().init() - if fi, xt := m.messageInfo().checkField(fd); fi != nil { + mi := m.messageInfo() + mi.init() + if fi, xd := mi.checkField(fd); fi != nil { return fi.has(m.pointer()) } else { - return m.messageInfo().extensionMap(m.pointer()).Has(xt) + return mi.extensionMap(m.pointer()).Has(xd) } } func (m *messageReflectWrapper) Clear(fd protoreflect.FieldDescriptor) { - m.messageInfo().init() - if fi, xt := m.messageInfo().checkField(fd); fi != nil { + mi := m.messageInfo() + mi.init() + if fi, xd := mi.checkField(fd); fi != nil { fi.clear(m.pointer()) } else { - m.messageInfo().extensionMap(m.pointer()).Clear(xt) + mi.extensionMap(m.pointer()).Clear(xd) } } func (m *messageReflectWrapper) Get(fd protoreflect.FieldDescriptor) protoreflect.Value { - m.messageInfo().init() - if fi, xt := m.messageInfo().checkField(fd); fi != nil { + mi := m.messageInfo() + mi.init() + if fi, xd := mi.checkField(fd); fi != nil { return fi.get(m.pointer()) } else { - return m.messageInfo().extensionMap(m.pointer()).Get(xt) + return mi.extensionMap(m.pointer()).Get(xd) } } func (m *messageReflectWrapper) Set(fd protoreflect.FieldDescriptor, v protoreflect.Value) { - m.messageInfo().init() - if fi, xt := m.messageInfo().checkField(fd); fi != nil { + mi := m.messageInfo() + mi.init() + if fi, xd := mi.checkField(fd); fi != nil { fi.set(m.pointer(), v) } else { - m.messageInfo().extensionMap(m.pointer()).Set(xt, v) + mi.extensionMap(m.pointer()).Set(xd, v) } } func (m *messageReflectWrapper) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value { - m.messageInfo().init() - if fi, xt := m.messageInfo().checkField(fd); fi != nil { + mi := m.messageInfo() + mi.init() + if fi, xd := mi.checkField(fd); fi != nil { return fi.mutable(m.pointer()) } else { - return m.messageInfo().extensionMap(m.pointer()).Mutable(xt) + return mi.extensionMap(m.pointer()).Mutable(xd) } } func (m *messageReflectWrapper) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value { - m.messageInfo().init() - if fi, xt := m.messageInfo().checkField(fd); fi != nil { + mi := m.messageInfo() + mi.init() + if fi, xd := mi.checkField(fd); fi != nil { return fi.newField() } else { - return xt.New() + return xd.Type().New() } } func (m *messageReflectWrapper) WhichOneof(od protoreflect.OneofDescriptor) protoreflect.FieldDescriptor { - m.messageInfo().init() - if oi := m.messageInfo().oneofs[od.Name()]; oi != nil && oi.oneofDesc == od { + mi := m.messageInfo() + mi.init() + if oi := mi.oneofs[od.Name()]; oi != nil && oi.oneofDesc == od { return od.Fields().ByNumber(oi.which(m.pointer())) } panic("invalid oneof descriptor " + string(od.FullName()) + " for message " + string(m.Descriptor().FullName())) } func (m *messageReflectWrapper) GetUnknown() protoreflect.RawFields { - m.messageInfo().init() - return m.messageInfo().getUnknown(m.pointer()) + mi := m.messageInfo() + mi.init() + return mi.getUnknown(m.pointer()) } func (m *messageReflectWrapper) SetUnknown(b protoreflect.RawFields) { - m.messageInfo().init() - m.messageInfo().setUnknown(m.pointer(), b) + mi := m.messageInfo() + mi.init() + mi.setUnknown(m.pointer(), b) } func (m *messageReflectWrapper) IsValid() bool { return !m.pointer().IsNil() diff --git a/vendor/google.golang.org/protobuf/internal/impl/pointer_reflect.go b/vendor/google.golang.org/protobuf/internal/impl/pointer_reflect.go deleted file mode 100644 index 517e94434..000000000 --- a/vendor/google.golang.org/protobuf/internal/impl/pointer_reflect.go +++ /dev/null @@ -1,215 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build purego || appengine -// +build purego appengine - -package impl - -import ( - "fmt" - "reflect" - "sync" -) - -const UnsafeEnabled = false - -// Pointer is an opaque pointer type. -type Pointer interface{} - -// offset represents the offset to a struct field, accessible from a pointer. -// The offset is the field index into a struct. -type offset struct { - index int - export exporter -} - -// offsetOf returns a field offset for the struct field. -func offsetOf(f reflect.StructField, x exporter) offset { - if len(f.Index) != 1 { - panic("embedded structs are not supported") - } - if f.PkgPath == "" { - return offset{index: f.Index[0]} // field is already exported - } - if x == nil { - panic("exporter must be provided for unexported field") - } - return offset{index: f.Index[0], export: x} -} - -// IsValid reports whether the offset is valid. -func (f offset) IsValid() bool { return f.index >= 0 } - -// invalidOffset is an invalid field offset. -var invalidOffset = offset{index: -1} - -// zeroOffset is a noop when calling pointer.Apply. -var zeroOffset = offset{index: 0} - -// pointer is an abstract representation of a pointer to a struct or field. -type pointer struct{ v reflect.Value } - -// pointerOf returns p as a pointer. -func pointerOf(p Pointer) pointer { - return pointerOfIface(p) -} - -// pointerOfValue returns v as a pointer. -func pointerOfValue(v reflect.Value) pointer { - return pointer{v: v} -} - -// pointerOfIface returns the pointer portion of an interface. -func pointerOfIface(v interface{}) pointer { - return pointer{v: reflect.ValueOf(v)} -} - -// IsNil reports whether the pointer is nil. -func (p pointer) IsNil() bool { - return p.v.IsNil() -} - -// Apply adds an offset to the pointer to derive a new pointer -// to a specified field. The current pointer must be pointing at a struct. -func (p pointer) Apply(f offset) pointer { - if f.export != nil { - if v := reflect.ValueOf(f.export(p.v.Interface(), f.index)); v.IsValid() { - return pointer{v: v} - } - } - return pointer{v: p.v.Elem().Field(f.index).Addr()} -} - -// AsValueOf treats p as a pointer to an object of type t and returns the value. -// It is equivalent to reflect.ValueOf(p.AsIfaceOf(t)) -func (p pointer) AsValueOf(t reflect.Type) reflect.Value { - if got := p.v.Type().Elem(); got != t { - panic(fmt.Sprintf("invalid type: got %v, want %v", got, t)) - } - return p.v -} - -// AsIfaceOf treats p as a pointer to an object of type t and returns the value. -// It is equivalent to p.AsValueOf(t).Interface() -func (p pointer) AsIfaceOf(t reflect.Type) interface{} { - return p.AsValueOf(t).Interface() -} - -func (p pointer) Bool() *bool { return p.v.Interface().(*bool) } -func (p pointer) BoolPtr() **bool { return p.v.Interface().(**bool) } -func (p pointer) BoolSlice() *[]bool { return p.v.Interface().(*[]bool) } -func (p pointer) Int32() *int32 { return p.v.Interface().(*int32) } -func (p pointer) Int32Ptr() **int32 { return p.v.Interface().(**int32) } -func (p pointer) Int32Slice() *[]int32 { return p.v.Interface().(*[]int32) } -func (p pointer) Int64() *int64 { return p.v.Interface().(*int64) } -func (p pointer) Int64Ptr() **int64 { return p.v.Interface().(**int64) } -func (p pointer) Int64Slice() *[]int64 { return p.v.Interface().(*[]int64) } -func (p pointer) Uint32() *uint32 { return p.v.Interface().(*uint32) } -func (p pointer) Uint32Ptr() **uint32 { return p.v.Interface().(**uint32) } -func (p pointer) Uint32Slice() *[]uint32 { return p.v.Interface().(*[]uint32) } -func (p pointer) Uint64() *uint64 { return p.v.Interface().(*uint64) } -func (p pointer) Uint64Ptr() **uint64 { return p.v.Interface().(**uint64) } -func (p pointer) Uint64Slice() *[]uint64 { return p.v.Interface().(*[]uint64) } -func (p pointer) Float32() *float32 { return p.v.Interface().(*float32) } -func (p pointer) Float32Ptr() **float32 { return p.v.Interface().(**float32) } -func (p pointer) Float32Slice() *[]float32 { return p.v.Interface().(*[]float32) } -func (p pointer) Float64() *float64 { return p.v.Interface().(*float64) } -func (p pointer) Float64Ptr() **float64 { return p.v.Interface().(**float64) } -func (p pointer) Float64Slice() *[]float64 { return p.v.Interface().(*[]float64) } -func (p pointer) String() *string { return p.v.Interface().(*string) } -func (p pointer) StringPtr() **string { return p.v.Interface().(**string) } -func (p pointer) StringSlice() *[]string { return p.v.Interface().(*[]string) } -func (p pointer) Bytes() *[]byte { return p.v.Interface().(*[]byte) } -func (p pointer) BytesPtr() **[]byte { return p.v.Interface().(**[]byte) } -func (p pointer) BytesSlice() *[][]byte { return p.v.Interface().(*[][]byte) } -func (p pointer) WeakFields() *weakFields { return (*weakFields)(p.v.Interface().(*WeakFields)) } -func (p pointer) Extensions() *map[int32]ExtensionField { - return p.v.Interface().(*map[int32]ExtensionField) -} - -func (p pointer) Elem() pointer { - return pointer{v: p.v.Elem()} -} - -// PointerSlice copies []*T from p as a new []pointer. -// This behavior differs from the implementation in pointer_unsafe.go. -func (p pointer) PointerSlice() []pointer { - // TODO: reconsider this - if p.v.IsNil() { - return nil - } - n := p.v.Elem().Len() - s := make([]pointer, n) - for i := 0; i < n; i++ { - s[i] = pointer{v: p.v.Elem().Index(i)} - } - return s -} - -// AppendPointerSlice appends v to p, which must be a []*T. -func (p pointer) AppendPointerSlice(v pointer) { - sp := p.v.Elem() - sp.Set(reflect.Append(sp, v.v)) -} - -// SetPointer sets *p to v. -func (p pointer) SetPointer(v pointer) { - p.v.Elem().Set(v.v) -} - -func growSlice(p pointer, addCap int) { - // TODO: Once we only support Go 1.20 and newer, use reflect.Grow. - in := p.v.Elem() - out := reflect.MakeSlice(in.Type(), in.Len(), in.Len()+addCap) - reflect.Copy(out, in) - p.v.Elem().Set(out) -} - -func (p pointer) growBoolSlice(addCap int) { - growSlice(p, addCap) -} - -func (p pointer) growInt32Slice(addCap int) { - growSlice(p, addCap) -} - -func (p pointer) growUint32Slice(addCap int) { - growSlice(p, addCap) -} - -func (p pointer) growInt64Slice(addCap int) { - growSlice(p, addCap) -} - -func (p pointer) growUint64Slice(addCap int) { - growSlice(p, addCap) -} - -func (p pointer) growFloat64Slice(addCap int) { - growSlice(p, addCap) -} - -func (p pointer) growFloat32Slice(addCap int) { - growSlice(p, addCap) -} - -func (Export) MessageStateOf(p Pointer) *messageState { panic("not supported") } -func (ms *messageState) pointer() pointer { panic("not supported") } -func (ms *messageState) messageInfo() *MessageInfo { panic("not supported") } -func (ms *messageState) LoadMessageInfo() *MessageInfo { panic("not supported") } -func (ms *messageState) StoreMessageInfo(mi *MessageInfo) { panic("not supported") } - -type atomicNilMessage struct { - once sync.Once - m messageReflectWrapper -} - -func (m *atomicNilMessage) Init(mi *MessageInfo) *messageReflectWrapper { - m.once.Do(func() { - m.m.p = pointerOfIface(reflect.Zero(mi.GoReflectType).Interface()) - m.m.mi = mi - }) - return &m.m -} diff --git a/vendor/google.golang.org/protobuf/internal/impl/pointer_unsafe.go b/vendor/google.golang.org/protobuf/internal/impl/pointer_unsafe.go index 4b020e311..79e186667 100644 --- a/vendor/google.golang.org/protobuf/internal/impl/pointer_unsafe.go +++ b/vendor/google.golang.org/protobuf/internal/impl/pointer_unsafe.go @@ -2,9 +2,6 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build !purego && !appengine -// +build !purego,!appengine - package impl import ( @@ -50,7 +47,7 @@ func pointerOfValue(v reflect.Value) pointer { } // pointerOfIface returns the pointer portion of an interface. -func pointerOfIface(v interface{}) pointer { +func pointerOfIface(v any) pointer { type ifaceHeader struct { Type unsafe.Pointer Data unsafe.Pointer @@ -80,7 +77,7 @@ func (p pointer) AsValueOf(t reflect.Type) reflect.Value { // AsIfaceOf treats p as a pointer to an object of type t and returns the value. // It is equivalent to p.AsValueOf(t).Interface() -func (p pointer) AsIfaceOf(t reflect.Type) interface{} { +func (p pointer) AsIfaceOf(t reflect.Type) any { // TODO: Use tricky unsafe magic to directly create ifaceHeader. return p.AsValueOf(t).Interface() } diff --git a/vendor/google.golang.org/protobuf/internal/order/range.go b/vendor/google.golang.org/protobuf/internal/order/range.go index 1665a68e5..a1f09162d 100644 --- a/vendor/google.golang.org/protobuf/internal/order/range.go +++ b/vendor/google.golang.org/protobuf/internal/order/range.go @@ -18,7 +18,7 @@ type messageField struct { } var messageFieldPool = sync.Pool{ - New: func() interface{} { return new([]messageField) }, + New: func() any { return new([]messageField) }, } type ( @@ -69,7 +69,7 @@ type mapEntry struct { } var mapEntryPool = sync.Pool{ - New: func() interface{} { return new([]mapEntry) }, + New: func() any { return new([]mapEntry) }, } type ( diff --git a/vendor/google.golang.org/protobuf/internal/strs/strings_pure.go b/vendor/google.golang.org/protobuf/internal/strs/strings_pure.go deleted file mode 100644 index a1f6f3338..000000000 --- a/vendor/google.golang.org/protobuf/internal/strs/strings_pure.go +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build purego || appengine -// +build purego appengine - -package strs - -import pref "google.golang.org/protobuf/reflect/protoreflect" - -func UnsafeString(b []byte) string { - return string(b) -} - -func UnsafeBytes(s string) []byte { - return []byte(s) -} - -type Builder struct{} - -func (*Builder) AppendFullName(prefix pref.FullName, name pref.Name) pref.FullName { - return prefix.Append(name) -} - -func (*Builder) MakeString(b []byte) string { - return string(b) -} diff --git a/vendor/google.golang.org/protobuf/internal/strs/strings_unsafe_go120.go b/vendor/google.golang.org/protobuf/internal/strs/strings_unsafe_go120.go index a008acd09..832a7988f 100644 --- a/vendor/google.golang.org/protobuf/internal/strs/strings_unsafe_go120.go +++ b/vendor/google.golang.org/protobuf/internal/strs/strings_unsafe_go120.go @@ -2,8 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build !purego && !appengine && !go1.21 -// +build !purego,!appengine,!go1.21 +//go:build !go1.21 package strs diff --git a/vendor/google.golang.org/protobuf/internal/strs/strings_unsafe_go121.go b/vendor/google.golang.org/protobuf/internal/strs/strings_unsafe_go121.go index 60166f2ba..1ffddf687 100644 --- a/vendor/google.golang.org/protobuf/internal/strs/strings_unsafe_go121.go +++ b/vendor/google.golang.org/protobuf/internal/strs/strings_unsafe_go121.go @@ -2,8 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build !purego && !appengine && go1.21 -// +build !purego,!appengine,go1.21 +//go:build go1.21 package strs diff --git a/vendor/google.golang.org/protobuf/internal/version/version.go b/vendor/google.golang.org/protobuf/internal/version/version.go index a50fcfb49..62a52a40a 100644 --- a/vendor/google.golang.org/protobuf/internal/version/version.go +++ b/vendor/google.golang.org/protobuf/internal/version/version.go @@ -51,8 +51,8 @@ import ( // 10. Send out the CL for review and submit it. const ( Major = 1 - Minor = 33 - Patch = 0 + Minor = 35 + Patch = 2 PreRelease = "" ) diff --git a/vendor/google.golang.org/protobuf/proto/decode.go b/vendor/google.golang.org/protobuf/proto/decode.go index e5b03b567..d75a6534c 100644 --- a/vendor/google.golang.org/protobuf/proto/decode.go +++ b/vendor/google.golang.org/protobuf/proto/decode.go @@ -51,6 +51,8 @@ type UnmarshalOptions struct { // Unmarshal parses the wire-format message in b and places the result in m. // The provided message must be mutable (e.g., a non-nil pointer to a message). +// +// See the [UnmarshalOptions] type if you need more control. func Unmarshal(b []byte, m Message) error { _, err := UnmarshalOptions{RecursionLimit: protowire.DefaultRecursionLimit}.unmarshal(b, m.ProtoReflect()) return err diff --git a/vendor/google.golang.org/protobuf/proto/encode.go b/vendor/google.golang.org/protobuf/proto/encode.go index 4fed202f9..1f847bcc3 100644 --- a/vendor/google.golang.org/protobuf/proto/encode.go +++ b/vendor/google.golang.org/protobuf/proto/encode.go @@ -5,12 +5,17 @@ package proto import ( + "errors" + "fmt" + "google.golang.org/protobuf/encoding/protowire" "google.golang.org/protobuf/internal/encoding/messageset" "google.golang.org/protobuf/internal/order" "google.golang.org/protobuf/internal/pragma" "google.golang.org/protobuf/reflect/protoreflect" "google.golang.org/protobuf/runtime/protoiface" + + protoerrors "google.golang.org/protobuf/internal/errors" ) // MarshalOptions configures the marshaler. @@ -70,7 +75,32 @@ type MarshalOptions struct { UseCachedSize bool } +// flags turns the specified MarshalOptions (user-facing) into +// protoiface.MarshalInputFlags (used internally by the marshaler). +// +// See impl.marshalOptions.Options for the inverse operation. +func (o MarshalOptions) flags() protoiface.MarshalInputFlags { + var flags protoiface.MarshalInputFlags + + // Note: o.AllowPartial is always forced to true by MarshalOptions.marshal, + // which is why it is not a part of MarshalInputFlags. + + if o.Deterministic { + flags |= protoiface.MarshalDeterministic + } + + if o.UseCachedSize { + flags |= protoiface.MarshalUseCachedSize + } + + return flags +} + // Marshal returns the wire-format encoding of m. +// +// This is the most common entry point for encoding a Protobuf message. +// +// See the [MarshalOptions] type if you need more control. func Marshal(m Message) ([]byte, error) { // Treat nil message interface as an empty message; nothing to output. if m == nil { @@ -116,6 +146,9 @@ func emptyBytesForMessage(m Message) []byte { // MarshalAppend appends the wire-format encoding of m to b, // returning the result. +// +// This is a less common entry point than [Marshal], which is only needed if you +// need to supply your own buffers for performance reasons. func (o MarshalOptions) MarshalAppend(b []byte, m Message) ([]byte, error) { // Treat nil message interface as an empty message; nothing to append. if m == nil { @@ -145,12 +178,7 @@ func (o MarshalOptions) marshal(b []byte, m protoreflect.Message) (out protoifac in := protoiface.MarshalInput{ Message: m, Buf: b, - } - if o.Deterministic { - in.Flags |= protoiface.MarshalDeterministic - } - if o.UseCachedSize { - in.Flags |= protoiface.MarshalUseCachedSize + Flags: o.flags(), } if methods.Size != nil { sout := methods.Size(protoiface.SizeInput{ @@ -168,6 +196,10 @@ func (o MarshalOptions) marshal(b []byte, m protoreflect.Message) (out protoifac out.Buf, err = o.marshalMessageSlow(b, m) } if err != nil { + var mismatch *protoerrors.SizeMismatchError + if errors.As(err, &mismatch) { + return out, fmt.Errorf("marshaling %s: %v", string(m.Descriptor().FullName()), err) + } return out, err } if allowPartial { diff --git a/vendor/google.golang.org/protobuf/proto/equal.go b/vendor/google.golang.org/protobuf/proto/equal.go index 1a0be1b03..c36d4a9cd 100644 --- a/vendor/google.golang.org/protobuf/proto/equal.go +++ b/vendor/google.golang.org/protobuf/proto/equal.go @@ -8,6 +8,7 @@ import ( "reflect" "google.golang.org/protobuf/reflect/protoreflect" + "google.golang.org/protobuf/runtime/protoiface" ) // Equal reports whether two messages are equal, @@ -51,6 +52,14 @@ func Equal(x, y Message) bool { if mx.IsValid() != my.IsValid() { return false } + + // Only one of the messages needs to implement the fast-path for it to work. + pmx := protoMethods(mx) + pmy := protoMethods(my) + if pmx != nil && pmy != nil && pmx.Equal != nil && pmy.Equal != nil { + return pmx.Equal(protoiface.EqualInput{MessageA: mx, MessageB: my}).Equal + } + vx := protoreflect.ValueOfMessage(mx) vy := protoreflect.ValueOfMessage(my) return vx.Equal(vy) diff --git a/vendor/google.golang.org/protobuf/proto/extension.go b/vendor/google.golang.org/protobuf/proto/extension.go index 17899a3a7..78445d116 100644 --- a/vendor/google.golang.org/protobuf/proto/extension.go +++ b/vendor/google.golang.org/protobuf/proto/extension.go @@ -11,18 +11,21 @@ import ( // HasExtension reports whether an extension field is populated. // It returns false if m is invalid or if xt does not extend m. func HasExtension(m Message, xt protoreflect.ExtensionType) bool { - // Treat nil message interface as an empty message; no populated fields. - if m == nil { + // Treat nil message interface or descriptor as an empty message; no populated + // fields. + if m == nil || xt == nil { return false } // As a special-case, we reports invalid or mismatching descriptors // as always not being populated (since they aren't). - if xt == nil || m.ProtoReflect().Descriptor() != xt.TypeDescriptor().ContainingMessage() { + mr := m.ProtoReflect() + xd := xt.TypeDescriptor() + if mr.Descriptor() != xd.ContainingMessage() { return false } - return m.ProtoReflect().Has(xt.TypeDescriptor()) + return mr.Has(xd) } // ClearExtension clears an extension field such that subsequent @@ -36,7 +39,49 @@ func ClearExtension(m Message, xt protoreflect.ExtensionType) { // If the field is unpopulated, it returns the default value for // scalars and an immutable, empty value for lists or messages. // It panics if xt does not extend m. -func GetExtension(m Message, xt protoreflect.ExtensionType) interface{} { +// +// The type of the value is dependent on the field type of the extension. +// For extensions generated by protoc-gen-go, the Go type is as follows: +// +// ╔═══════════════════╤═════════════════════════╗ +// ║ Go type │ Protobuf kind ║ +// ╠═══════════════════╪═════════════════════════╣ +// ║ bool │ bool ║ +// ║ int32 │ int32, sint32, sfixed32 ║ +// ║ int64 │ int64, sint64, sfixed64 ║ +// ║ uint32 │ uint32, fixed32 ║ +// ║ uint64 │ uint64, fixed64 ║ +// ║ float32 │ float ║ +// ║ float64 │ double ║ +// ║ string │ string ║ +// ║ []byte │ bytes ║ +// ║ protoreflect.Enum │ enum ║ +// ║ proto.Message │ message, group ║ +// ╚═══════════════════╧═════════════════════════╝ +// +// The protoreflect.Enum and proto.Message types are the concrete Go type +// associated with the named enum or message. Repeated fields are represented +// using a Go slice of the base element type. +// +// If a generated extension descriptor variable is directly passed to +// GetExtension, then the call should be followed immediately by a +// type assertion to the expected output value. For example: +// +// mm := proto.GetExtension(m, foopb.E_MyExtension).(*foopb.MyMessage) +// +// This pattern enables static analysis tools to verify that the asserted type +// matches the Go type associated with the extension field and +// also enables a possible future migration to a type-safe extension API. +// +// Since singular messages are the most common extension type, the pattern of +// calling HasExtension followed by GetExtension may be simplified to: +// +// if mm := proto.GetExtension(m, foopb.E_MyExtension).(*foopb.MyMessage); mm != nil { +// ... // make use of mm +// } +// +// The mm variable is non-nil if and only if HasExtension reports true. +func GetExtension(m Message, xt protoreflect.ExtensionType) any { // Treat nil message interface as an empty message; return the default. if m == nil { return xt.InterfaceOf(xt.Zero()) @@ -48,7 +93,36 @@ func GetExtension(m Message, xt protoreflect.ExtensionType) interface{} { // SetExtension stores the value of an extension field. // It panics if m is invalid, xt does not extend m, or if type of v // is invalid for the specified extension field. -func SetExtension(m Message, xt protoreflect.ExtensionType, v interface{}) { +// +// The type of the value is dependent on the field type of the extension. +// For extensions generated by protoc-gen-go, the Go type is as follows: +// +// ╔═══════════════════╤═════════════════════════╗ +// ║ Go type │ Protobuf kind ║ +// ╠═══════════════════╪═════════════════════════╣ +// ║ bool │ bool ║ +// ║ int32 │ int32, sint32, sfixed32 ║ +// ║ int64 │ int64, sint64, sfixed64 ║ +// ║ uint32 │ uint32, fixed32 ║ +// ║ uint64 │ uint64, fixed64 ║ +// ║ float32 │ float ║ +// ║ float64 │ double ║ +// ║ string │ string ║ +// ║ []byte │ bytes ║ +// ║ protoreflect.Enum │ enum ║ +// ║ proto.Message │ message, group ║ +// ╚═══════════════════╧═════════════════════════╝ +// +// The protoreflect.Enum and proto.Message types are the concrete Go type +// associated with the named enum or message. Repeated fields are represented +// using a Go slice of the base element type. +// +// If a generated extension descriptor variable is directly passed to +// SetExtension (e.g., foopb.E_MyExtension), then the value should be a +// concrete type that matches the expected Go type for the extension descriptor +// so that static analysis tools can verify type correctness. +// This also enables a possible future migration to a type-safe extension API. +func SetExtension(m Message, xt protoreflect.ExtensionType, v any) { xd := xt.TypeDescriptor() pv := xt.ValueOf(v) @@ -75,7 +149,7 @@ func SetExtension(m Message, xt protoreflect.ExtensionType, v interface{}) { // It returns immediately if f returns false. // While iterating, mutating operations may only be performed // on the current extension field. -func RangeExtensions(m Message, f func(protoreflect.ExtensionType, interface{}) bool) { +func RangeExtensions(m Message, f func(protoreflect.ExtensionType, any) bool) { // Treat nil message interface as an empty message; nothing to range over. if m == nil { return diff --git a/vendor/google.golang.org/protobuf/proto/messageset.go b/vendor/google.golang.org/protobuf/proto/messageset.go index 312d5d45c..575d14831 100644 --- a/vendor/google.golang.org/protobuf/proto/messageset.go +++ b/vendor/google.golang.org/protobuf/proto/messageset.go @@ -47,11 +47,16 @@ func (o MarshalOptions) marshalMessageSet(b []byte, m protoreflect.Message) ([]b func (o MarshalOptions) marshalMessageSetField(b []byte, fd protoreflect.FieldDescriptor, value protoreflect.Value) ([]byte, error) { b = messageset.AppendFieldStart(b, fd.Number()) b = protowire.AppendTag(b, messageset.FieldMessage, protowire.BytesType) - b = protowire.AppendVarint(b, uint64(o.Size(value.Message().Interface()))) + calculatedSize := o.Size(value.Message().Interface()) + b = protowire.AppendVarint(b, uint64(calculatedSize)) + before := len(b) b, err := o.marshalMessage(b, value.Message()) if err != nil { return b, err } + if measuredSize := len(b) - before; calculatedSize != measuredSize { + return nil, errors.MismatchedSizeCalculation(calculatedSize, measuredSize) + } b = messageset.AppendFieldEnd(b) return b, nil } diff --git a/vendor/google.golang.org/protobuf/proto/size.go b/vendor/google.golang.org/protobuf/proto/size.go index f1692b49b..052fb5ae3 100644 --- a/vendor/google.golang.org/protobuf/proto/size.go +++ b/vendor/google.golang.org/protobuf/proto/size.go @@ -34,6 +34,7 @@ func (o MarshalOptions) size(m protoreflect.Message) (size int) { if methods != nil && methods.Size != nil { out := methods.Size(protoiface.SizeInput{ Message: m, + Flags: o.flags(), }) return out.Size } @@ -42,6 +43,7 @@ func (o MarshalOptions) size(m protoreflect.Message) (size int) { // This case is mainly used for legacy types with a Marshal method. out, _ := methods.Marshal(protoiface.MarshalInput{ Message: m, + Flags: o.flags(), }) return len(out.Buf) } diff --git a/vendor/google.golang.org/protobuf/reflect/protodesc/desc.go b/vendor/google.golang.org/protobuf/reflect/protodesc/desc.go index baa0cc621..69a050509 100644 --- a/vendor/google.golang.org/protobuf/reflect/protodesc/desc.go +++ b/vendor/google.golang.org/protobuf/reflect/protodesc/desc.go @@ -13,6 +13,9 @@ package protodesc import ( + "strings" + + "google.golang.org/protobuf/internal/editionssupport" "google.golang.org/protobuf/internal/errors" "google.golang.org/protobuf/internal/filedesc" "google.golang.org/protobuf/internal/pragma" @@ -91,21 +94,27 @@ func (o FileOptions) New(fd *descriptorpb.FileDescriptorProto, r Resolver) (prot switch fd.GetSyntax() { case "proto2", "": f.L1.Syntax = protoreflect.Proto2 + f.L1.Edition = filedesc.EditionProto2 case "proto3": f.L1.Syntax = protoreflect.Proto3 + f.L1.Edition = filedesc.EditionProto3 case "editions": f.L1.Syntax = protoreflect.Editions f.L1.Edition = fromEditionProto(fd.GetEdition()) default: return nil, errors.New("invalid syntax: %q", fd.GetSyntax()) } - if f.L1.Syntax == protoreflect.Editions && (fd.GetEdition() < SupportedEditionsMinimum || fd.GetEdition() > SupportedEditionsMaximum) { - return nil, errors.New("use of edition %v not yet supported by the Go Protobuf runtime", fd.GetEdition()) - } f.L1.Path = fd.GetName() if f.L1.Path == "" { return nil, errors.New("file path must be populated") } + if f.L1.Syntax == protoreflect.Editions && (fd.GetEdition() < editionssupport.Minimum || fd.GetEdition() > editionssupport.Maximum) { + // Allow cmd/protoc-gen-go/testdata to use any edition for easier + // testing of upcoming edition features. + if !strings.HasPrefix(fd.GetName(), "cmd/protoc-gen-go/testdata/") { + return nil, errors.New("use of edition %v not yet supported by the Go Protobuf runtime", fd.GetEdition()) + } + } f.L1.Package = protoreflect.FullName(fd.GetPackage()) if !f.L1.Package.IsValid() && f.L1.Package != "" { return nil, errors.New("invalid package: %q", f.L1.Package) @@ -114,9 +123,7 @@ func (o FileOptions) New(fd *descriptorpb.FileDescriptorProto, r Resolver) (prot opts = proto.Clone(opts).(*descriptorpb.FileOptions) f.L2.Options = func() protoreflect.ProtoMessage { return opts } } - if f.L1.Syntax == protoreflect.Editions { - initFileDescFromFeatureSet(f, fd.GetOptions().GetFeatures()) - } + initFileDescFromFeatureSet(f, fd.GetOptions().GetFeatures()) f.L2.Imports = make(filedesc.FileImports, len(fd.GetDependency())) for _, i := range fd.GetPublicDependency() { @@ -219,10 +226,10 @@ func (o FileOptions) New(fd *descriptorpb.FileDescriptorProto, r Resolver) (prot if err := validateEnumDeclarations(f.L1.Enums.List, fd.GetEnumType()); err != nil { return nil, err } - if err := validateMessageDeclarations(f.L1.Messages.List, fd.GetMessageType()); err != nil { + if err := validateMessageDeclarations(f, f.L1.Messages.List, fd.GetMessageType()); err != nil { return nil, err } - if err := validateExtensionDeclarations(f.L1.Extensions.List, fd.GetExtension()); err != nil { + if err := validateExtensionDeclarations(f, f.L1.Extensions.List, fd.GetExtension()); err != nil { return nil, err } diff --git a/vendor/google.golang.org/protobuf/reflect/protodesc/desc_init.go b/vendor/google.golang.org/protobuf/reflect/protodesc/desc_init.go index b3278163c..ebcb4a8ab 100644 --- a/vendor/google.golang.org/protobuf/reflect/protodesc/desc_init.go +++ b/vendor/google.golang.org/protobuf/reflect/protodesc/desc_init.go @@ -69,9 +69,7 @@ func (r descsByName) initMessagesDeclarations(mds []*descriptorpb.DescriptorProt if m.L0, err = r.makeBase(m, parent, md.GetName(), i, sb); err != nil { return nil, err } - if m.Base.L0.ParentFile.Syntax() == protoreflect.Editions { - m.L1.EditionFeatures = mergeEditionFeatures(parent, md.GetOptions().GetFeatures()) - } + m.L1.EditionFeatures = mergeEditionFeatures(parent, md.GetOptions().GetFeatures()) if opts := md.GetOptions(); opts != nil { opts = proto.Clone(opts).(*descriptorpb.MessageOptions) m.L2.Options = func() protoreflect.ProtoMessage { return opts } @@ -146,13 +144,16 @@ func (r descsByName) initFieldsFromDescriptorProto(fds []*descriptorpb.FieldDesc if f.L0, err = r.makeBase(f, parent, fd.GetName(), i, sb); err != nil { return nil, err } + f.L1.EditionFeatures = mergeEditionFeatures(parent, fd.GetOptions().GetFeatures()) f.L1.IsProto3Optional = fd.GetProto3Optional() if opts := fd.GetOptions(); opts != nil { opts = proto.Clone(opts).(*descriptorpb.FieldOptions) f.L1.Options = func() protoreflect.ProtoMessage { return opts } f.L1.IsWeak = opts.GetWeak() - f.L1.HasPacked = opts.Packed != nil - f.L1.IsPacked = opts.GetPacked() + f.L1.IsLazy = opts.GetLazy() + if opts.Packed != nil { + f.L1.EditionFeatures.IsPacked = opts.GetPacked() + } } f.L1.Number = protoreflect.FieldNumber(fd.GetNumber()) f.L1.Cardinality = protoreflect.Cardinality(fd.GetLabel()) @@ -163,32 +164,12 @@ func (r descsByName) initFieldsFromDescriptorProto(fds []*descriptorpb.FieldDesc f.L1.StringName.InitJSON(fd.GetJsonName()) } - if f.Base.L0.ParentFile.Syntax() == protoreflect.Editions { - f.L1.EditionFeatures = mergeEditionFeatures(parent, fd.GetOptions().GetFeatures()) - - if f.L1.EditionFeatures.IsLegacyRequired { - f.L1.Cardinality = protoreflect.Required - } - // We reuse the existing field because the old option `[packed = - // true]` is mutually exclusive with the editions feature. - if canBePacked(fd) { - f.L1.HasPacked = true - f.L1.IsPacked = f.L1.EditionFeatures.IsPacked - } - - // We pretend this option is always explicitly set because the only - // use of HasEnforceUTF8 is to determine whether to use EnforceUTF8 - // or to return the appropriate default. - // When using editions we either parse the option or resolve the - // appropriate default here (instead of later when this option is - // requested from the descriptor). - // In proto2/proto3 syntax HasEnforceUTF8 might be false. - f.L1.HasEnforceUTF8 = true - f.L1.EnforceUTF8 = f.L1.EditionFeatures.IsUTF8Validated + if f.L1.EditionFeatures.IsLegacyRequired { + f.L1.Cardinality = protoreflect.Required + } - if f.L1.Kind == protoreflect.MessageKind && f.L1.EditionFeatures.IsDelimitedEncoded { - f.L1.Kind = protoreflect.GroupKind - } + if f.L1.Kind == protoreflect.MessageKind && f.L1.EditionFeatures.IsDelimitedEncoded { + f.L1.Kind = protoreflect.GroupKind } } return fs, nil @@ -201,12 +182,10 @@ func (r descsByName) initOneofsFromDescriptorProto(ods []*descriptorpb.OneofDesc if o.L0, err = r.makeBase(o, parent, od.GetName(), i, sb); err != nil { return nil, err } + o.L1.EditionFeatures = mergeEditionFeatures(parent, od.GetOptions().GetFeatures()) if opts := od.GetOptions(); opts != nil { opts = proto.Clone(opts).(*descriptorpb.OneofOptions) o.L1.Options = func() protoreflect.ProtoMessage { return opts } - if parent.Syntax() == protoreflect.Editions { - o.L1.EditionFeatures = mergeEditionFeatures(parent, opts.GetFeatures()) - } } } return os, nil @@ -220,10 +199,13 @@ func (r descsByName) initExtensionDeclarations(xds []*descriptorpb.FieldDescript if x.L0, err = r.makeBase(x, parent, xd.GetName(), i, sb); err != nil { return nil, err } + x.L1.EditionFeatures = mergeEditionFeatures(parent, xd.GetOptions().GetFeatures()) if opts := xd.GetOptions(); opts != nil { opts = proto.Clone(opts).(*descriptorpb.FieldOptions) x.L2.Options = func() protoreflect.ProtoMessage { return opts } - x.L2.IsPacked = opts.GetPacked() + if opts.Packed != nil { + x.L1.EditionFeatures.IsPacked = opts.GetPacked() + } } x.L1.Number = protoreflect.FieldNumber(xd.GetNumber()) x.L1.Cardinality = protoreflect.Cardinality(xd.GetLabel()) @@ -233,6 +215,9 @@ func (r descsByName) initExtensionDeclarations(xds []*descriptorpb.FieldDescript if xd.JsonName != nil { x.L2.StringName.InitJSON(xd.GetJsonName()) } + if x.L1.Kind == protoreflect.MessageKind && x.L1.EditionFeatures.IsDelimitedEncoded { + x.L1.Kind = protoreflect.GroupKind + } } return xs, nil } diff --git a/vendor/google.golang.org/protobuf/reflect/protodesc/desc_resolve.go b/vendor/google.golang.org/protobuf/reflect/protodesc/desc_resolve.go index 254ca5854..f3cebab29 100644 --- a/vendor/google.golang.org/protobuf/reflect/protodesc/desc_resolve.go +++ b/vendor/google.golang.org/protobuf/reflect/protodesc/desc_resolve.go @@ -46,6 +46,11 @@ func (r *resolver) resolveMessageDependencies(ms []filedesc.Message, mds []*desc if f.L1.Kind, f.L1.Enum, f.L1.Message, err = r.findTarget(f.Kind(), f.Parent().FullName(), partialName(fd.GetTypeName()), f.IsWeak()); err != nil { return errors.New("message field %q cannot resolve type: %v", f.FullName(), err) } + if f.L1.Kind == protoreflect.GroupKind && (f.IsMap() || f.IsMapEntry()) { + // A map field might inherit delimited encoding from a file-wide default feature. + // But maps never actually use delimited encoding. (At least for now...) + f.L1.Kind = protoreflect.MessageKind + } if fd.DefaultValue != nil { v, ev, err := unmarshalDefault(fd.GetDefaultValue(), f, r.allowUnresolvable) if err != nil { diff --git a/vendor/google.golang.org/protobuf/reflect/protodesc/desc_validate.go b/vendor/google.golang.org/protobuf/reflect/protodesc/desc_validate.go index e4dcaf876..6de31c2eb 100644 --- a/vendor/google.golang.org/protobuf/reflect/protodesc/desc_validate.go +++ b/vendor/google.golang.org/protobuf/reflect/protodesc/desc_validate.go @@ -45,11 +45,11 @@ func validateEnumDeclarations(es []filedesc.Enum, eds []*descriptorpb.EnumDescri if allowAlias && !foundAlias { return errors.New("enum %q allows aliases, but none were found", e.FullName()) } - if e.Syntax() == protoreflect.Proto3 { + if !e.IsClosed() { if v := e.Values().Get(0); v.Number() != 0 { - return errors.New("enum %q using proto3 semantics must have zero number for the first value", v.FullName()) + return errors.New("enum %q using open semantics must have zero number for the first value", v.FullName()) } - // Verify that value names in proto3 do not conflict if the + // Verify that value names in open enums do not conflict if the // case-insensitive prefix is removed. // See protoc v3.8.0: src/google/protobuf/descriptor.cc:4991-5055 names := map[string]protoreflect.EnumValueDescriptor{} @@ -58,7 +58,7 @@ func validateEnumDeclarations(es []filedesc.Enum, eds []*descriptorpb.EnumDescri v1 := e.Values().Get(i) s := strs.EnumValueName(strs.TrimEnumPrefix(string(v1.Name()), prefix)) if v2, ok := names[s]; ok && v1.Number() != v2.Number() { - return errors.New("enum %q using proto3 semantics has conflict: %q with %q", e.FullName(), v1.Name(), v2.Name()) + return errors.New("enum %q using open semantics has conflict: %q with %q", e.FullName(), v1.Name(), v2.Name()) } names[s] = v1 } @@ -80,7 +80,9 @@ func validateEnumDeclarations(es []filedesc.Enum, eds []*descriptorpb.EnumDescri return nil } -func validateMessageDeclarations(ms []filedesc.Message, mds []*descriptorpb.DescriptorProto) error { +func validateMessageDeclarations(file *filedesc.File, ms []filedesc.Message, mds []*descriptorpb.DescriptorProto) error { + // There are a few limited exceptions only for proto3 + isProto3 := file.L1.Edition == fromEditionProto(descriptorpb.Edition_EDITION_PROTO3) for i, md := range mds { m := &ms[i] @@ -107,25 +109,13 @@ func validateMessageDeclarations(ms []filedesc.Message, mds []*descriptorpb.Desc if isMessageSet && !flags.ProtoLegacy { return errors.New("message %q is a MessageSet, which is a legacy proto1 feature that is no longer supported", m.FullName()) } - if isMessageSet && (m.Syntax() == protoreflect.Proto3 || m.Fields().Len() > 0 || m.ExtensionRanges().Len() == 0) { + if isMessageSet && (isProto3 || m.Fields().Len() > 0 || m.ExtensionRanges().Len() == 0) { return errors.New("message %q is an invalid proto1 MessageSet", m.FullName()) } - if m.Syntax() == protoreflect.Proto3 { + if isProto3 { if m.ExtensionRanges().Len() > 0 { return errors.New("message %q using proto3 semantics cannot have extension ranges", m.FullName()) } - // Verify that field names in proto3 do not conflict if lowercased - // with all underscores removed. - // See protoc v3.8.0: src/google/protobuf/descriptor.cc:5830-5847 - names := map[string]protoreflect.FieldDescriptor{} - for i := 0; i < m.Fields().Len(); i++ { - f1 := m.Fields().Get(i) - s := strings.Replace(strings.ToLower(string(f1.Name())), "_", "", -1) - if f2, ok := names[s]; ok { - return errors.New("message %q using proto3 semantics has conflict: %q with %q", m.FullName(), f1.Name(), f2.Name()) - } - names[s] = f1 - } } for j, fd := range md.GetField() { @@ -149,7 +139,7 @@ func validateMessageDeclarations(ms []filedesc.Message, mds []*descriptorpb.Desc return errors.New("message field %q may not have extendee: %q", f.FullName(), fd.GetExtendee()) } if f.L1.IsProto3Optional { - if f.Syntax() != protoreflect.Proto3 { + if !isProto3 { return errors.New("message field %q under proto3 optional semantics must be specified in the proto3 syntax", f.FullName()) } if f.Cardinality() != protoreflect.Optional { @@ -162,26 +152,29 @@ func validateMessageDeclarations(ms []filedesc.Message, mds []*descriptorpb.Desc if f.IsWeak() && !flags.ProtoLegacy { return errors.New("message field %q is a weak field, which is a legacy proto1 feature that is no longer supported", f.FullName()) } - if f.IsWeak() && (f.Syntax() != protoreflect.Proto2 || !isOptionalMessage(f) || f.ContainingOneof() != nil) { + if f.IsWeak() && (!f.HasPresence() || !isOptionalMessage(f) || f.ContainingOneof() != nil) { return errors.New("message field %q may only be weak for an optional message", f.FullName()) } if f.IsPacked() && !isPackable(f) { return errors.New("message field %q is not packable", f.FullName()) } - if err := checkValidGroup(f); err != nil { + if err := checkValidGroup(file, f); err != nil { return errors.New("message field %q is an invalid group: %v", f.FullName(), err) } if err := checkValidMap(f); err != nil { return errors.New("message field %q is an invalid map: %v", f.FullName(), err) } - if f.Syntax() == protoreflect.Proto3 { + if isProto3 { if f.Cardinality() == protoreflect.Required { return errors.New("message field %q using proto3 semantics cannot be required", f.FullName()) } - if f.Enum() != nil && !f.Enum().IsPlaceholder() && f.Enum().Syntax() != protoreflect.Proto3 { - return errors.New("message field %q using proto3 semantics may only depend on a proto3 enum", f.FullName()) + if f.Enum() != nil && !f.Enum().IsPlaceholder() && f.Enum().IsClosed() { + return errors.New("message field %q using proto3 semantics may only depend on open enums", f.FullName()) } } + if f.Cardinality() == protoreflect.Optional && !f.HasPresence() && f.Enum() != nil && !f.Enum().IsPlaceholder() && f.Enum().IsClosed() { + return errors.New("message field %q with implicit presence may only use open enums", f.FullName()) + } } seenSynthetic := false // synthetic oneofs for proto3 optional must come after real oneofs for j := range md.GetOneofDecl() { @@ -215,17 +208,17 @@ func validateMessageDeclarations(ms []filedesc.Message, mds []*descriptorpb.Desc if err := validateEnumDeclarations(m.L1.Enums.List, md.GetEnumType()); err != nil { return err } - if err := validateMessageDeclarations(m.L1.Messages.List, md.GetNestedType()); err != nil { + if err := validateMessageDeclarations(file, m.L1.Messages.List, md.GetNestedType()); err != nil { return err } - if err := validateExtensionDeclarations(m.L1.Extensions.List, md.GetExtension()); err != nil { + if err := validateExtensionDeclarations(file, m.L1.Extensions.List, md.GetExtension()); err != nil { return err } } return nil } -func validateExtensionDeclarations(xs []filedesc.Extension, xds []*descriptorpb.FieldDescriptorProto) error { +func validateExtensionDeclarations(f *filedesc.File, xs []filedesc.Extension, xds []*descriptorpb.FieldDescriptorProto) error { for i, xd := range xds { x := &xs[i] // NOTE: Avoid using the IsValid method since extensions to MessageSet @@ -267,13 +260,13 @@ func validateExtensionDeclarations(xs []filedesc.Extension, xds []*descriptorpb. if x.IsPacked() && !isPackable(x) { return errors.New("extension field %q is not packable", x.FullName()) } - if err := checkValidGroup(x); err != nil { + if err := checkValidGroup(f, x); err != nil { return errors.New("extension field %q is an invalid group: %v", x.FullName(), err) } if md := x.Message(); md != nil && md.IsMapEntry() { return errors.New("extension field %q cannot be a map entry", x.FullName()) } - if x.Syntax() == protoreflect.Proto3 { + if f.L1.Edition == fromEditionProto(descriptorpb.Edition_EDITION_PROTO3) { switch x.ContainingMessage().FullName() { case (*descriptorpb.FileOptions)(nil).ProtoReflect().Descriptor().FullName(): case (*descriptorpb.EnumOptions)(nil).ProtoReflect().Descriptor().FullName(): @@ -309,21 +302,25 @@ func isPackable(fd protoreflect.FieldDescriptor) bool { // checkValidGroup reports whether fd is a valid group according to the same // rules that protoc imposes. -func checkValidGroup(fd protoreflect.FieldDescriptor) error { +func checkValidGroup(f *filedesc.File, fd protoreflect.FieldDescriptor) error { md := fd.Message() switch { case fd.Kind() != protoreflect.GroupKind: return nil - case fd.Syntax() == protoreflect.Proto3: + case f.L1.Edition == fromEditionProto(descriptorpb.Edition_EDITION_PROTO3): return errors.New("invalid under proto3 semantics") case md == nil || md.IsPlaceholder(): return errors.New("message must be resolvable") - case fd.FullName().Parent() != md.FullName().Parent(): - return errors.New("message and field must be declared in the same scope") - case !unicode.IsUpper(rune(md.Name()[0])): - return errors.New("message name must start with an uppercase") - case fd.Name() != protoreflect.Name(strings.ToLower(string(md.Name()))): - return errors.New("field name must be lowercased form of the message name") + } + if f.L1.Edition < fromEditionProto(descriptorpb.Edition_EDITION_2023) { + switch { + case fd.FullName().Parent() != md.FullName().Parent(): + return errors.New("message and field must be declared in the same scope") + case !unicode.IsUpper(rune(md.Name()[0])): + return errors.New("message name must start with an uppercase") + case fd.Name() != protoreflect.Name(strings.ToLower(string(md.Name()))): + return errors.New("field name must be lowercased form of the message name") + } } return nil } diff --git a/vendor/google.golang.org/protobuf/reflect/protodesc/editions.go b/vendor/google.golang.org/protobuf/reflect/protodesc/editions.go index 2a6b29d17..d0aeab958 100644 --- a/vendor/google.golang.org/protobuf/reflect/protodesc/editions.go +++ b/vendor/google.golang.org/protobuf/reflect/protodesc/editions.go @@ -14,12 +14,7 @@ import ( "google.golang.org/protobuf/proto" "google.golang.org/protobuf/reflect/protoreflect" "google.golang.org/protobuf/types/descriptorpb" - gofeaturespb "google.golang.org/protobuf/types/gofeaturespb" -) - -const ( - SupportedEditionsMinimum = descriptorpb.Edition_EDITION_PROTO2 - SupportedEditionsMaximum = descriptorpb.Edition_EDITION_2023 + "google.golang.org/protobuf/types/gofeaturespb" ) var defaults = &descriptorpb.FeatureSetDefaults{} @@ -48,6 +43,8 @@ func toEditionProto(ed filedesc.Edition) descriptorpb.Edition { return descriptorpb.Edition_EDITION_PROTO3 case filedesc.Edition2023: return descriptorpb.Edition_EDITION_2023 + case filedesc.Edition2024: + return descriptorpb.Edition_EDITION_2024 default: panic(fmt.Sprintf("unknown value for edition: %v", ed)) } @@ -67,18 +64,20 @@ func getFeatureSetFor(ed filedesc.Edition) *descriptorpb.FeatureSet { fmt.Fprintf(os.Stderr, "internal error: unsupported edition %v (did you forget to update the embedded defaults (i.e. the bootstrap descriptor proto)?)\n", edpb) os.Exit(1) } - fs := defaults.GetDefaults()[0].GetFeatures() + fsed := defaults.GetDefaults()[0] // Using a linear search for now. // Editions are guaranteed to be sorted and thus we could use a binary search. // Given that there are only a handful of editions (with one more per year) // there is not much reason to use a binary search. for _, def := range defaults.GetDefaults() { if def.GetEdition() <= edpb { - fs = def.GetFeatures() + fsed = def } else { break } } + fs := proto.Clone(fsed.GetFixedFeatures()).(*descriptorpb.FeatureSet) + proto.Merge(fs, fsed.GetOverridableFeatures()) defaultsCache[ed] = fs return fs } @@ -130,6 +129,9 @@ func mergeEditionFeatures(parentDesc protoreflect.Descriptor, child *descriptorp if luje := goFeatures.LegacyUnmarshalJsonEnum; luje != nil { parentFS.GenerateLegacyUnmarshalJSON = *luje } + if sep := goFeatures.StripEnumPrefix; sep != nil { + parentFS.StripEnumPrefix = int(*sep) + } } return parentFS diff --git a/vendor/google.golang.org/protobuf/reflect/protodesc/proto.go b/vendor/google.golang.org/protobuf/reflect/protodesc/proto.go index 9d6e05420..a5de8d400 100644 --- a/vendor/google.golang.org/protobuf/reflect/protodesc/proto.go +++ b/vendor/google.golang.org/protobuf/reflect/protodesc/proto.go @@ -73,6 +73,16 @@ func ToFileDescriptorProto(file protoreflect.FileDescriptor) *descriptorpb.FileD if syntax := file.Syntax(); syntax != protoreflect.Proto2 && syntax.IsValid() { p.Syntax = proto.String(file.Syntax().String()) } + if file.Syntax() == protoreflect.Editions { + desc := file + if fileImportDesc, ok := file.(protoreflect.FileImport); ok { + desc = fileImportDesc.FileDescriptor + } + + if editionsInterface, ok := desc.(interface{ Edition() int32 }); ok { + p.Edition = descriptorpb.Edition(editionsInterface.Edition()).Enum() + } + } return p } @@ -153,6 +163,18 @@ func ToFieldDescriptorProto(field protoreflect.FieldDescriptor) *descriptorpb.Fi if field.Syntax() == protoreflect.Proto3 && field.HasOptionalKeyword() { p.Proto3Optional = proto.Bool(true) } + if field.Syntax() == protoreflect.Editions { + // Editions have no group keyword, this type is only set so that downstream users continue + // treating this as delimited encoding. + if p.GetType() == descriptorpb.FieldDescriptorProto_TYPE_GROUP { + p.Type = descriptorpb.FieldDescriptorProto_TYPE_MESSAGE.Enum() + } + // Editions have no required keyword, this label is only set so that downstream users continue + // treating it as required. + if p.GetLabel() == descriptorpb.FieldDescriptorProto_LABEL_REQUIRED { + p.Label = descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL.Enum() + } + } if field.HasDefault() { def, err := defval.Marshal(field.Default(), field.DefaultEnumValue(), field.Kind(), defval.Descriptor) if err != nil && field.DefaultEnumValue() != nil { diff --git a/vendor/google.golang.org/protobuf/reflect/protoreflect/methods.go b/vendor/google.golang.org/protobuf/reflect/protoreflect/methods.go index d5d5af6eb..742cb518c 100644 --- a/vendor/google.golang.org/protobuf/reflect/protoreflect/methods.go +++ b/vendor/google.golang.org/protobuf/reflect/protoreflect/methods.go @@ -23,6 +23,7 @@ type ( Unmarshal func(unmarshalInput) (unmarshalOutput, error) Merge func(mergeInput) mergeOutput CheckInitialized func(checkInitializedInput) (checkInitializedOutput, error) + Equal func(equalInput) equalOutput } supportFlags = uint64 sizeInput = struct { @@ -75,4 +76,13 @@ type ( checkInitializedOutput = struct { pragma.NoUnkeyedLiterals } + equalInput = struct { + pragma.NoUnkeyedLiterals + MessageA Message + MessageB Message + } + equalOutput = struct { + pragma.NoUnkeyedLiterals + Equal bool + } ) diff --git a/vendor/google.golang.org/protobuf/reflect/protoreflect/proto.go b/vendor/google.golang.org/protobuf/reflect/protoreflect/proto.go index 00b01fbd8..c85bfaa5b 100644 --- a/vendor/google.golang.org/protobuf/reflect/protoreflect/proto.go +++ b/vendor/google.golang.org/protobuf/reflect/protoreflect/proto.go @@ -161,7 +161,7 @@ const ( // IsValid reports whether the syntax is valid. func (s Syntax) IsValid() bool { switch s { - case Proto2, Proto3: + case Proto2, Proto3, Editions: return true default: return false diff --git a/vendor/google.golang.org/protobuf/reflect/protoreflect/source_gen.go b/vendor/google.golang.org/protobuf/reflect/protoreflect/source_gen.go index 7dcc2ff09..ea154eec4 100644 --- a/vendor/google.golang.org/protobuf/reflect/protoreflect/source_gen.go +++ b/vendor/google.golang.org/protobuf/reflect/protoreflect/source_gen.go @@ -373,6 +373,8 @@ func (p *SourcePath) appendFieldOptions(b []byte) []byte { b = p.appendRepeatedField(b, "edition_defaults", (*SourcePath).appendFieldOptions_EditionDefault) case 21: b = p.appendSingularField(b, "features", (*SourcePath).appendFeatureSet) + case 22: + b = p.appendSingularField(b, "feature_support", (*SourcePath).appendFieldOptions_FeatureSupport) case 999: b = p.appendRepeatedField(b, "uninterpreted_option", (*SourcePath).appendUninterpretedOption) } @@ -483,6 +485,8 @@ func (p *SourcePath) appendEnumValueOptions(b []byte) []byte { b = p.appendSingularField(b, "features", (*SourcePath).appendFeatureSet) case 3: b = p.appendSingularField(b, "debug_redact", nil) + case 4: + b = p.appendSingularField(b, "feature_support", (*SourcePath).appendFieldOptions_FeatureSupport) case 999: b = p.appendRepeatedField(b, "uninterpreted_option", (*SourcePath).appendUninterpretedOption) } @@ -519,6 +523,23 @@ func (p *SourcePath) appendFieldOptions_EditionDefault(b []byte) []byte { return b } +func (p *SourcePath) appendFieldOptions_FeatureSupport(b []byte) []byte { + if len(*p) == 0 { + return b + } + switch (*p)[0] { + case 1: + b = p.appendSingularField(b, "edition_introduced", nil) + case 2: + b = p.appendSingularField(b, "edition_deprecated", nil) + case 3: + b = p.appendSingularField(b, "deprecation_warning", nil) + case 4: + b = p.appendSingularField(b, "edition_removed", nil) + } + return b +} + func (p *SourcePath) appendUninterpretedOption_NamePart(b []byte) []byte { if len(*p) == 0 { return b diff --git a/vendor/google.golang.org/protobuf/reflect/protoreflect/type.go b/vendor/google.golang.org/protobuf/reflect/protoreflect/type.go index 60ff62b4c..cd8fadbaf 100644 --- a/vendor/google.golang.org/protobuf/reflect/protoreflect/type.go +++ b/vendor/google.golang.org/protobuf/reflect/protoreflect/type.go @@ -510,7 +510,7 @@ type ExtensionType interface { // // ValueOf is more extensive than protoreflect.ValueOf for a given field's // value as it has more type information available. - ValueOf(interface{}) Value + ValueOf(any) Value // InterfaceOf completely unwraps the Value to the underlying Go type. // InterfaceOf panics if the input is nil or does not represent the @@ -519,13 +519,13 @@ type ExtensionType interface { // // InterfaceOf is able to unwrap the Value further than Value.Interface // as it has more type information available. - InterfaceOf(Value) interface{} + InterfaceOf(Value) any // IsValidValue reports whether the Value is valid to assign to the field. IsValidValue(Value) bool // IsValidInterface reports whether the input is valid to assign to the field. - IsValidInterface(interface{}) bool + IsValidInterface(any) bool } // EnumDescriptor describes an enum and @@ -544,6 +544,12 @@ type EnumDescriptor interface { // ReservedRanges is a list of reserved ranges of enum numbers. ReservedRanges() EnumRanges + // IsClosed reports whether this enum uses closed semantics. + // See https://protobuf.dev/programming-guides/enum/#definitions. + // Note: the Go protobuf implementation is not spec compliant and treats + // all enums as open enums. + IsClosed() bool + isEnumDescriptor } type isEnumDescriptor interface{ ProtoType(EnumDescriptor) } diff --git a/vendor/google.golang.org/protobuf/reflect/protoreflect/value_pure.go b/vendor/google.golang.org/protobuf/reflect/protoreflect/value_pure.go deleted file mode 100644 index 7ced876f4..000000000 --- a/vendor/google.golang.org/protobuf/reflect/protoreflect/value_pure.go +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build purego || appengine -// +build purego appengine - -package protoreflect - -import "google.golang.org/protobuf/internal/pragma" - -type valueType int - -const ( - nilType valueType = iota - boolType - int32Type - int64Type - uint32Type - uint64Type - float32Type - float64Type - stringType - bytesType - enumType - ifaceType -) - -// value is a union where only one type can be represented at a time. -// This uses a distinct field for each type. This is type safe in Go, but -// occupies more memory than necessary (72B). -type value struct { - pragma.DoNotCompare // 0B - - typ valueType // 8B - num uint64 // 8B - str string // 16B - bin []byte // 24B - iface interface{} // 16B -} - -func valueOfString(v string) Value { - return Value{typ: stringType, str: v} -} -func valueOfBytes(v []byte) Value { - return Value{typ: bytesType, bin: v} -} -func valueOfIface(v interface{}) Value { - return Value{typ: ifaceType, iface: v} -} - -func (v Value) getString() string { - return v.str -} -func (v Value) getBytes() []byte { - return v.bin -} -func (v Value) getIface() interface{} { - return v.iface -} diff --git a/vendor/google.golang.org/protobuf/reflect/protoreflect/value_union.go b/vendor/google.golang.org/protobuf/reflect/protoreflect/value_union.go index 160309731..9fe83cef5 100644 --- a/vendor/google.golang.org/protobuf/reflect/protoreflect/value_union.go +++ b/vendor/google.golang.org/protobuf/reflect/protoreflect/value_union.go @@ -69,8 +69,8 @@ import ( // composite Value. Modifying an empty, read-only value panics. type Value value -// The protoreflect API uses a custom Value union type instead of interface{} -// to keep the future open for performance optimizations. Using an interface{} +// The protoreflect API uses a custom Value union type instead of any +// to keep the future open for performance optimizations. Using an any // always incurs an allocation for primitives (e.g., int64) since it needs to // be boxed on the heap (as interfaces can only contain pointers natively). // Instead, we represent the Value union as a flat struct that internally keeps @@ -85,7 +85,7 @@ type Value value // ValueOf returns a Value initialized with the concrete value stored in v. // This panics if the type does not match one of the allowed types in the // Value union. -func ValueOf(v interface{}) Value { +func ValueOf(v any) Value { switch v := v.(type) { case nil: return Value{} @@ -192,10 +192,10 @@ func (v Value) IsValid() bool { return v.typ != nilType } -// Interface returns v as an interface{}. +// Interface returns v as an any. // // Invariant: v == ValueOf(v).Interface() -func (v Value) Interface() interface{} { +func (v Value) Interface() any { switch v.typ { case nilType: return nil @@ -406,8 +406,8 @@ func (k MapKey) IsValid() bool { return Value(k).IsValid() } -// Interface returns k as an interface{}. -func (k MapKey) Interface() interface{} { +// Interface returns k as an any. +func (k MapKey) Interface() any { return Value(k).Interface() } diff --git a/vendor/google.golang.org/protobuf/reflect/protoreflect/value_unsafe_go120.go b/vendor/google.golang.org/protobuf/reflect/protoreflect/value_unsafe_go120.go index b1fdbe3e8..0015fcb35 100644 --- a/vendor/google.golang.org/protobuf/reflect/protoreflect/value_unsafe_go120.go +++ b/vendor/google.golang.org/protobuf/reflect/protoreflect/value_unsafe_go120.go @@ -2,8 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build !purego && !appengine && !go1.21 -// +build !purego,!appengine,!go1.21 +//go:build !go1.21 package protoreflect @@ -45,7 +44,7 @@ var ( // typeOf returns a pointer to the Go type information. // The pointer is comparable and equal if and only if the types are identical. -func typeOf(t interface{}) unsafe.Pointer { +func typeOf(t any) unsafe.Pointer { return (*ifaceHeader)(unsafe.Pointer(&t)).Type } @@ -80,7 +79,7 @@ func valueOfBytes(v []byte) Value { p := (*sliceHeader)(unsafe.Pointer(&v)) return Value{typ: bytesType, ptr: p.Data, num: uint64(len(v))} } -func valueOfIface(v interface{}) Value { +func valueOfIface(v any) Value { p := (*ifaceHeader)(unsafe.Pointer(&v)) return Value{typ: p.Type, ptr: p.Data} } @@ -93,7 +92,7 @@ func (v Value) getBytes() (x []byte) { *(*sliceHeader)(unsafe.Pointer(&x)) = sliceHeader{Data: v.ptr, Len: int(v.num), Cap: int(v.num)} return x } -func (v Value) getIface() (x interface{}) { +func (v Value) getIface() (x any) { *(*ifaceHeader)(unsafe.Pointer(&x)) = ifaceHeader{Type: v.typ, Data: v.ptr} return x } diff --git a/vendor/google.golang.org/protobuf/reflect/protoreflect/value_unsafe_go121.go b/vendor/google.golang.org/protobuf/reflect/protoreflect/value_unsafe_go121.go index 435470111..479527b58 100644 --- a/vendor/google.golang.org/protobuf/reflect/protoreflect/value_unsafe_go121.go +++ b/vendor/google.golang.org/protobuf/reflect/protoreflect/value_unsafe_go121.go @@ -2,8 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build !purego && !appengine && go1.21 -// +build !purego,!appengine,go1.21 +//go:build go1.21 package protoreflect @@ -15,7 +14,7 @@ import ( type ( ifaceHeader struct { - _ [0]interface{} // if interfaces have greater alignment than unsafe.Pointer, this will enforce it. + _ [0]any // if interfaces have greater alignment than unsafe.Pointer, this will enforce it. Type unsafe.Pointer Data unsafe.Pointer } @@ -37,7 +36,7 @@ var ( // typeOf returns a pointer to the Go type information. // The pointer is comparable and equal if and only if the types are identical. -func typeOf(t interface{}) unsafe.Pointer { +func typeOf(t any) unsafe.Pointer { return (*ifaceHeader)(unsafe.Pointer(&t)).Type } @@ -70,7 +69,7 @@ func valueOfString(v string) Value { func valueOfBytes(v []byte) Value { return Value{typ: bytesType, ptr: unsafe.Pointer(unsafe.SliceData(v)), num: uint64(len(v))} } -func valueOfIface(v interface{}) Value { +func valueOfIface(v any) Value { p := (*ifaceHeader)(unsafe.Pointer(&v)) return Value{typ: p.Type, ptr: p.Data} } @@ -81,7 +80,7 @@ func (v Value) getString() string { func (v Value) getBytes() []byte { return unsafe.Slice((*byte)(v.ptr), v.num) } -func (v Value) getIface() (x interface{}) { +func (v Value) getIface() (x any) { *(*ifaceHeader)(unsafe.Pointer(&x)) = ifaceHeader{Type: v.typ, Data: v.ptr} return x } diff --git a/vendor/google.golang.org/protobuf/reflect/protoregistry/registry.go b/vendor/google.golang.org/protobuf/reflect/protoregistry/registry.go index 6267dc52a..de1777339 100644 --- a/vendor/google.golang.org/protobuf/reflect/protoregistry/registry.go +++ b/vendor/google.golang.org/protobuf/reflect/protoregistry/registry.go @@ -95,7 +95,7 @@ type Files struct { // multiple files. Only top-level declarations are registered. // Note that enum values are in the top-level since that are in the same // scope as the parent enum. - descsByName map[protoreflect.FullName]interface{} + descsByName map[protoreflect.FullName]any filesByPath map[string][]protoreflect.FileDescriptor numFiles int } @@ -117,7 +117,7 @@ func (r *Files) RegisterFile(file protoreflect.FileDescriptor) error { defer globalMutex.Unlock() } if r.descsByName == nil { - r.descsByName = map[protoreflect.FullName]interface{}{ + r.descsByName = map[protoreflect.FullName]any{ "": &packageDescriptor{}, } r.filesByPath = make(map[string][]protoreflect.FileDescriptor) @@ -485,7 +485,7 @@ type Types struct { } type ( - typesByName map[protoreflect.FullName]interface{} + typesByName map[protoreflect.FullName]any extensionsByMessage map[protoreflect.FullName]extensionsByNumber extensionsByNumber map[protoreflect.FieldNumber]protoreflect.ExtensionType ) @@ -570,7 +570,7 @@ func (r *Types) RegisterExtension(xt protoreflect.ExtensionType) error { return nil } -func (r *Types) register(kind string, desc protoreflect.Descriptor, typ interface{}) error { +func (r *Types) register(kind string, desc protoreflect.Descriptor, typ any) error { name := desc.FullName() prev := r.typesByName[name] if prev != nil { @@ -841,7 +841,7 @@ func (r *Types) RangeExtensionsByMessage(message protoreflect.FullName, f func(p } } -func typeName(t interface{}) string { +func typeName(t any) string { switch t.(type) { case protoreflect.EnumType: return "enum" @@ -854,7 +854,7 @@ func typeName(t interface{}) string { } } -func amendErrorWithCaller(err error, prev, curr interface{}) error { +func amendErrorWithCaller(err error, prev, curr any) error { prevPkg := goPackage(prev) currPkg := goPackage(curr) if prevPkg == "" || currPkg == "" || prevPkg == currPkg { @@ -863,7 +863,7 @@ func amendErrorWithCaller(err error, prev, curr interface{}) error { return errors.New("%s\n\tpreviously from: %q\n\tcurrently from: %q", err, prevPkg, currPkg) } -func goPackage(v interface{}) string { +func goPackage(v any) string { switch d := v.(type) { case protoreflect.EnumType: v = d.Descriptor() diff --git a/vendor/google.golang.org/protobuf/runtime/protoiface/methods.go b/vendor/google.golang.org/protobuf/runtime/protoiface/methods.go index 44cf467d8..246156561 100644 --- a/vendor/google.golang.org/protobuf/runtime/protoiface/methods.go +++ b/vendor/google.golang.org/protobuf/runtime/protoiface/methods.go @@ -39,6 +39,9 @@ type Methods = struct { // CheckInitialized returns an error if any required fields in the message are not set. CheckInitialized func(CheckInitializedInput) (CheckInitializedOutput, error) + + // Equal compares two messages and returns EqualOutput.Equal == true if they are equal. + Equal func(EqualInput) EqualOutput } // SupportFlags indicate support for optional features. @@ -166,3 +169,18 @@ type CheckInitializedInput = struct { type CheckInitializedOutput = struct { pragma.NoUnkeyedLiterals } + +// EqualInput is input to the Equal method. +type EqualInput = struct { + pragma.NoUnkeyedLiterals + + MessageA protoreflect.Message + MessageB protoreflect.Message +} + +// EqualOutput is output from the Equal method. +type EqualOutput = struct { + pragma.NoUnkeyedLiterals + + Equal bool +} diff --git a/vendor/google.golang.org/protobuf/types/descriptorpb/descriptor.pb.go b/vendor/google.golang.org/protobuf/types/descriptorpb/descriptor.pb.go index 78624cf60..6dea75cd5 100644 --- a/vendor/google.golang.org/protobuf/types/descriptorpb/descriptor.pb.go +++ b/vendor/google.golang.org/protobuf/types/descriptorpb/descriptor.pb.go @@ -54,6 +54,9 @@ type Edition int32 const ( // A placeholder for an unknown edition value. Edition_EDITION_UNKNOWN Edition = 0 + // A placeholder edition for specifying default behaviors *before* a feature + // was first introduced. This is effectively an "infinite past". + Edition_EDITION_LEGACY Edition = 900 // Legacy syntax "editions". These pre-date editions, but behave much like // distinct editions. These can't be used to specify the edition of proto // files, but feature definitions must supply proto2/proto3 defaults for @@ -82,6 +85,7 @@ const ( var ( Edition_name = map[int32]string{ 0: "EDITION_UNKNOWN", + 900: "EDITION_LEGACY", 998: "EDITION_PROTO2", 999: "EDITION_PROTO3", 1000: "EDITION_2023", @@ -95,6 +99,7 @@ var ( } Edition_value = map[string]int32{ "EDITION_UNKNOWN": 0, + "EDITION_LEGACY": 900, "EDITION_PROTO2": 998, "EDITION_PROTO3": 999, "EDITION_2023": 1000, @@ -1212,11 +1217,9 @@ type FileDescriptorSet struct { func (x *FileDescriptorSet) Reset() { *x = FileDescriptorSet{} - if protoimpl.UnsafeEnabled { - mi := &file_google_protobuf_descriptor_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_google_protobuf_descriptor_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *FileDescriptorSet) String() string { @@ -1227,7 +1230,7 @@ func (*FileDescriptorSet) ProtoMessage() {} func (x *FileDescriptorSet) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -1286,11 +1289,9 @@ type FileDescriptorProto struct { func (x *FileDescriptorProto) Reset() { *x = FileDescriptorProto{} - if protoimpl.UnsafeEnabled { - mi := &file_google_protobuf_descriptor_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_google_protobuf_descriptor_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *FileDescriptorProto) String() string { @@ -1301,7 +1302,7 @@ func (*FileDescriptorProto) ProtoMessage() {} func (x *FileDescriptorProto) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -1429,11 +1430,9 @@ type DescriptorProto struct { func (x *DescriptorProto) Reset() { *x = DescriptorProto{} - if protoimpl.UnsafeEnabled { - mi := &file_google_protobuf_descriptor_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_google_protobuf_descriptor_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *DescriptorProto) String() string { @@ -1444,7 +1443,7 @@ func (*DescriptorProto) ProtoMessage() {} func (x *DescriptorProto) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -1556,11 +1555,9 @@ const ( func (x *ExtensionRangeOptions) Reset() { *x = ExtensionRangeOptions{} - if protoimpl.UnsafeEnabled { - mi := &file_google_protobuf_descriptor_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_google_protobuf_descriptor_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *ExtensionRangeOptions) String() string { @@ -1571,7 +1568,7 @@ func (*ExtensionRangeOptions) ProtoMessage() {} func (x *ExtensionRangeOptions) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -1675,11 +1672,9 @@ type FieldDescriptorProto struct { func (x *FieldDescriptorProto) Reset() { *x = FieldDescriptorProto{} - if protoimpl.UnsafeEnabled { - mi := &file_google_protobuf_descriptor_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_google_protobuf_descriptor_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *FieldDescriptorProto) String() string { @@ -1690,7 +1685,7 @@ func (*FieldDescriptorProto) ProtoMessage() {} func (x *FieldDescriptorProto) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -1794,11 +1789,9 @@ type OneofDescriptorProto struct { func (x *OneofDescriptorProto) Reset() { *x = OneofDescriptorProto{} - if protoimpl.UnsafeEnabled { - mi := &file_google_protobuf_descriptor_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_google_protobuf_descriptor_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *OneofDescriptorProto) String() string { @@ -1809,7 +1802,7 @@ func (*OneofDescriptorProto) ProtoMessage() {} func (x *OneofDescriptorProto) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[5] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -1858,11 +1851,9 @@ type EnumDescriptorProto struct { func (x *EnumDescriptorProto) Reset() { *x = EnumDescriptorProto{} - if protoimpl.UnsafeEnabled { - mi := &file_google_protobuf_descriptor_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_google_protobuf_descriptor_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *EnumDescriptorProto) String() string { @@ -1873,7 +1864,7 @@ func (*EnumDescriptorProto) ProtoMessage() {} func (x *EnumDescriptorProto) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[6] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -1936,11 +1927,9 @@ type EnumValueDescriptorProto struct { func (x *EnumValueDescriptorProto) Reset() { *x = EnumValueDescriptorProto{} - if protoimpl.UnsafeEnabled { - mi := &file_google_protobuf_descriptor_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_google_protobuf_descriptor_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *EnumValueDescriptorProto) String() string { @@ -1951,7 +1940,7 @@ func (*EnumValueDescriptorProto) ProtoMessage() {} func (x *EnumValueDescriptorProto) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[7] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -2000,11 +1989,9 @@ type ServiceDescriptorProto struct { func (x *ServiceDescriptorProto) Reset() { *x = ServiceDescriptorProto{} - if protoimpl.UnsafeEnabled { - mi := &file_google_protobuf_descriptor_proto_msgTypes[8] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_google_protobuf_descriptor_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *ServiceDescriptorProto) String() string { @@ -2015,7 +2002,7 @@ func (*ServiceDescriptorProto) ProtoMessage() {} func (x *ServiceDescriptorProto) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[8] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -2077,11 +2064,9 @@ const ( func (x *MethodDescriptorProto) Reset() { *x = MethodDescriptorProto{} - if protoimpl.UnsafeEnabled { - mi := &file_google_protobuf_descriptor_proto_msgTypes[9] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_google_protobuf_descriptor_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *MethodDescriptorProto) String() string { @@ -2092,7 +2077,7 @@ func (*MethodDescriptorProto) ProtoMessage() {} func (x *MethodDescriptorProto) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[9] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -2177,12 +2162,16 @@ type FileOptions struct { // // Deprecated: Marked as deprecated in google/protobuf/descriptor.proto. JavaGenerateEqualsAndHash *bool `protobuf:"varint,20,opt,name=java_generate_equals_and_hash,json=javaGenerateEqualsAndHash" json:"java_generate_equals_and_hash,omitempty"` - // If set true, then the Java2 code generator will generate code that - // throws an exception whenever an attempt is made to assign a non-UTF-8 - // byte sequence to a string field. - // Message reflection will do the same. - // However, an extension field still accepts non-UTF-8 byte sequences. - // This option has no effect on when used with the lite runtime. + // A proto2 file can set this to true to opt in to UTF-8 checking for Java, + // which will throw an exception if invalid UTF-8 is parsed from the wire or + // assigned to a string field. + // + // TODO: clarify exactly what kinds of field types this option + // applies to, and update these docs accordingly. + // + // Proto3 files already perform these checks. Setting the option explicitly to + // false has no effect: it cannot be used to opt proto3 files out of UTF-8 + // checks. JavaStringCheckUtf8 *bool `protobuf:"varint,27,opt,name=java_string_check_utf8,json=javaStringCheckUtf8,def=0" json:"java_string_check_utf8,omitempty"` OptimizeFor *FileOptions_OptimizeMode `protobuf:"varint,9,opt,name=optimize_for,json=optimizeFor,enum=google.protobuf.FileOptions_OptimizeMode,def=1" json:"optimize_for,omitempty"` // Sets the Go package where structs generated from this .proto will be @@ -2258,11 +2247,9 @@ const ( func (x *FileOptions) Reset() { *x = FileOptions{} - if protoimpl.UnsafeEnabled { - mi := &file_google_protobuf_descriptor_proto_msgTypes[10] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_google_protobuf_descriptor_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *FileOptions) String() string { @@ -2273,7 +2260,7 @@ func (*FileOptions) ProtoMessage() {} func (x *FileOptions) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[10] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -2525,11 +2512,9 @@ const ( func (x *MessageOptions) Reset() { *x = MessageOptions{} - if protoimpl.UnsafeEnabled { - mi := &file_google_protobuf_descriptor_proto_msgTypes[11] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_google_protobuf_descriptor_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *MessageOptions) String() string { @@ -2540,7 +2525,7 @@ func (*MessageOptions) ProtoMessage() {} func (x *MessageOptions) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[11] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -2679,7 +2664,8 @@ type FieldOptions struct { Targets []FieldOptions_OptionTargetType `protobuf:"varint,19,rep,name=targets,enum=google.protobuf.FieldOptions_OptionTargetType" json:"targets,omitempty"` EditionDefaults []*FieldOptions_EditionDefault `protobuf:"bytes,20,rep,name=edition_defaults,json=editionDefaults" json:"edition_defaults,omitempty"` // Any features defined in the specific edition. - Features *FeatureSet `protobuf:"bytes,21,opt,name=features" json:"features,omitempty"` + Features *FeatureSet `protobuf:"bytes,21,opt,name=features" json:"features,omitempty"` + FeatureSupport *FieldOptions_FeatureSupport `protobuf:"bytes,22,opt,name=feature_support,json=featureSupport" json:"feature_support,omitempty"` // The parser stores options it doesn't recognize here. See above. UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` } @@ -2697,11 +2683,9 @@ const ( func (x *FieldOptions) Reset() { *x = FieldOptions{} - if protoimpl.UnsafeEnabled { - mi := &file_google_protobuf_descriptor_proto_msgTypes[12] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_google_protobuf_descriptor_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *FieldOptions) String() string { @@ -2712,7 +2696,7 @@ func (*FieldOptions) ProtoMessage() {} func (x *FieldOptions) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[12] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -2811,6 +2795,13 @@ func (x *FieldOptions) GetFeatures() *FeatureSet { return nil } +func (x *FieldOptions) GetFeatureSupport() *FieldOptions_FeatureSupport { + if x != nil { + return x.FeatureSupport + } + return nil +} + func (x *FieldOptions) GetUninterpretedOption() []*UninterpretedOption { if x != nil { return x.UninterpretedOption @@ -2832,11 +2823,9 @@ type OneofOptions struct { func (x *OneofOptions) Reset() { *x = OneofOptions{} - if protoimpl.UnsafeEnabled { - mi := &file_google_protobuf_descriptor_proto_msgTypes[13] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_google_protobuf_descriptor_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *OneofOptions) String() string { @@ -2847,7 +2836,7 @@ func (*OneofOptions) ProtoMessage() {} func (x *OneofOptions) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[13] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -2912,11 +2901,9 @@ const ( func (x *EnumOptions) Reset() { *x = EnumOptions{} - if protoimpl.UnsafeEnabled { - mi := &file_google_protobuf_descriptor_proto_msgTypes[14] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_google_protobuf_descriptor_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *EnumOptions) String() string { @@ -2927,7 +2914,7 @@ func (*EnumOptions) ProtoMessage() {} func (x *EnumOptions) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[14] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -2995,6 +2982,8 @@ type EnumValueOptions struct { // out when using debug formats, e.g. when the field contains sensitive // credentials. DebugRedact *bool `protobuf:"varint,3,opt,name=debug_redact,json=debugRedact,def=0" json:"debug_redact,omitempty"` + // Information about the support window of a feature value. + FeatureSupport *FieldOptions_FeatureSupport `protobuf:"bytes,4,opt,name=feature_support,json=featureSupport" json:"feature_support,omitempty"` // The parser stores options it doesn't recognize here. See above. UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` } @@ -3007,11 +2996,9 @@ const ( func (x *EnumValueOptions) Reset() { *x = EnumValueOptions{} - if protoimpl.UnsafeEnabled { - mi := &file_google_protobuf_descriptor_proto_msgTypes[15] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_google_protobuf_descriptor_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *EnumValueOptions) String() string { @@ -3022,7 +3009,7 @@ func (*EnumValueOptions) ProtoMessage() {} func (x *EnumValueOptions) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[15] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -3058,6 +3045,13 @@ func (x *EnumValueOptions) GetDebugRedact() bool { return Default_EnumValueOptions_DebugRedact } +func (x *EnumValueOptions) GetFeatureSupport() *FieldOptions_FeatureSupport { + if x != nil { + return x.FeatureSupport + } + return nil +} + func (x *EnumValueOptions) GetUninterpretedOption() []*UninterpretedOption { if x != nil { return x.UninterpretedOption @@ -3089,11 +3083,9 @@ const ( func (x *ServiceOptions) Reset() { *x = ServiceOptions{} - if protoimpl.UnsafeEnabled { - mi := &file_google_protobuf_descriptor_proto_msgTypes[16] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_google_protobuf_descriptor_proto_msgTypes[16] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *ServiceOptions) String() string { @@ -3104,7 +3096,7 @@ func (*ServiceOptions) ProtoMessage() {} func (x *ServiceOptions) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[16] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -3166,11 +3158,9 @@ const ( func (x *MethodOptions) Reset() { *x = MethodOptions{} - if protoimpl.UnsafeEnabled { - mi := &file_google_protobuf_descriptor_proto_msgTypes[17] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_google_protobuf_descriptor_proto_msgTypes[17] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *MethodOptions) String() string { @@ -3181,7 +3171,7 @@ func (*MethodOptions) ProtoMessage() {} func (x *MethodOptions) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[17] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -3248,11 +3238,9 @@ type UninterpretedOption struct { func (x *UninterpretedOption) Reset() { *x = UninterpretedOption{} - if protoimpl.UnsafeEnabled { - mi := &file_google_protobuf_descriptor_proto_msgTypes[18] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_google_protobuf_descriptor_proto_msgTypes[18] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *UninterpretedOption) String() string { @@ -3263,7 +3251,7 @@ func (*UninterpretedOption) ProtoMessage() {} func (x *UninterpretedOption) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[18] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -3349,11 +3337,9 @@ type FeatureSet struct { func (x *FeatureSet) Reset() { *x = FeatureSet{} - if protoimpl.UnsafeEnabled { - mi := &file_google_protobuf_descriptor_proto_msgTypes[19] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_google_protobuf_descriptor_proto_msgTypes[19] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *FeatureSet) String() string { @@ -3364,7 +3350,7 @@ func (*FeatureSet) ProtoMessage() {} func (x *FeatureSet) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[19] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -3441,11 +3427,9 @@ type FeatureSetDefaults struct { func (x *FeatureSetDefaults) Reset() { *x = FeatureSetDefaults{} - if protoimpl.UnsafeEnabled { - mi := &file_google_protobuf_descriptor_proto_msgTypes[20] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_google_protobuf_descriptor_proto_msgTypes[20] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *FeatureSetDefaults) String() string { @@ -3456,7 +3440,7 @@ func (*FeatureSetDefaults) ProtoMessage() {} func (x *FeatureSetDefaults) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[20] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -3552,11 +3536,9 @@ type SourceCodeInfo struct { func (x *SourceCodeInfo) Reset() { *x = SourceCodeInfo{} - if protoimpl.UnsafeEnabled { - mi := &file_google_protobuf_descriptor_proto_msgTypes[21] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_google_protobuf_descriptor_proto_msgTypes[21] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *SourceCodeInfo) String() string { @@ -3567,7 +3549,7 @@ func (*SourceCodeInfo) ProtoMessage() {} func (x *SourceCodeInfo) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[21] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -3604,11 +3586,9 @@ type GeneratedCodeInfo struct { func (x *GeneratedCodeInfo) Reset() { *x = GeneratedCodeInfo{} - if protoimpl.UnsafeEnabled { - mi := &file_google_protobuf_descriptor_proto_msgTypes[22] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_google_protobuf_descriptor_proto_msgTypes[22] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *GeneratedCodeInfo) String() string { @@ -3619,7 +3599,7 @@ func (*GeneratedCodeInfo) ProtoMessage() {} func (x *GeneratedCodeInfo) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[22] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -3653,11 +3633,9 @@ type DescriptorProto_ExtensionRange struct { func (x *DescriptorProto_ExtensionRange) Reset() { *x = DescriptorProto_ExtensionRange{} - if protoimpl.UnsafeEnabled { - mi := &file_google_protobuf_descriptor_proto_msgTypes[23] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_google_protobuf_descriptor_proto_msgTypes[23] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *DescriptorProto_ExtensionRange) String() string { @@ -3668,7 +3646,7 @@ func (*DescriptorProto_ExtensionRange) ProtoMessage() {} func (x *DescriptorProto_ExtensionRange) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[23] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -3718,11 +3696,9 @@ type DescriptorProto_ReservedRange struct { func (x *DescriptorProto_ReservedRange) Reset() { *x = DescriptorProto_ReservedRange{} - if protoimpl.UnsafeEnabled { - mi := &file_google_protobuf_descriptor_proto_msgTypes[24] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_google_protobuf_descriptor_proto_msgTypes[24] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *DescriptorProto_ReservedRange) String() string { @@ -3733,7 +3709,7 @@ func (*DescriptorProto_ReservedRange) ProtoMessage() {} func (x *DescriptorProto_ReservedRange) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[24] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -3787,11 +3763,9 @@ type ExtensionRangeOptions_Declaration struct { func (x *ExtensionRangeOptions_Declaration) Reset() { *x = ExtensionRangeOptions_Declaration{} - if protoimpl.UnsafeEnabled { - mi := &file_google_protobuf_descriptor_proto_msgTypes[25] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_google_protobuf_descriptor_proto_msgTypes[25] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *ExtensionRangeOptions_Declaration) String() string { @@ -3802,7 +3776,7 @@ func (*ExtensionRangeOptions_Declaration) ProtoMessage() {} func (x *ExtensionRangeOptions_Declaration) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[25] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -3869,11 +3843,9 @@ type EnumDescriptorProto_EnumReservedRange struct { func (x *EnumDescriptorProto_EnumReservedRange) Reset() { *x = EnumDescriptorProto_EnumReservedRange{} - if protoimpl.UnsafeEnabled { - mi := &file_google_protobuf_descriptor_proto_msgTypes[26] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_google_protobuf_descriptor_proto_msgTypes[26] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *EnumDescriptorProto_EnumReservedRange) String() string { @@ -3884,7 +3856,7 @@ func (*EnumDescriptorProto_EnumReservedRange) ProtoMessage() {} func (x *EnumDescriptorProto_EnumReservedRange) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[26] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -3924,11 +3896,9 @@ type FieldOptions_EditionDefault struct { func (x *FieldOptions_EditionDefault) Reset() { *x = FieldOptions_EditionDefault{} - if protoimpl.UnsafeEnabled { - mi := &file_google_protobuf_descriptor_proto_msgTypes[27] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_google_protobuf_descriptor_proto_msgTypes[27] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *FieldOptions_EditionDefault) String() string { @@ -3939,7 +3909,7 @@ func (*FieldOptions_EditionDefault) ProtoMessage() {} func (x *FieldOptions_EditionDefault) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[27] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -3968,6 +3938,86 @@ func (x *FieldOptions_EditionDefault) GetValue() string { return "" } +// Information about the support window of a feature. +type FieldOptions_FeatureSupport struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // The edition that this feature was first available in. In editions + // earlier than this one, the default assigned to EDITION_LEGACY will be + // used, and proto files will not be able to override it. + EditionIntroduced *Edition `protobuf:"varint,1,opt,name=edition_introduced,json=editionIntroduced,enum=google.protobuf.Edition" json:"edition_introduced,omitempty"` + // The edition this feature becomes deprecated in. Using this after this + // edition may trigger warnings. + EditionDeprecated *Edition `protobuf:"varint,2,opt,name=edition_deprecated,json=editionDeprecated,enum=google.protobuf.Edition" json:"edition_deprecated,omitempty"` + // The deprecation warning text if this feature is used after the edition it + // was marked deprecated in. + DeprecationWarning *string `protobuf:"bytes,3,opt,name=deprecation_warning,json=deprecationWarning" json:"deprecation_warning,omitempty"` + // The edition this feature is no longer available in. In editions after + // this one, the last default assigned will be used, and proto files will + // not be able to override it. + EditionRemoved *Edition `protobuf:"varint,4,opt,name=edition_removed,json=editionRemoved,enum=google.protobuf.Edition" json:"edition_removed,omitempty"` +} + +func (x *FieldOptions_FeatureSupport) Reset() { + *x = FieldOptions_FeatureSupport{} + mi := &file_google_protobuf_descriptor_proto_msgTypes[28] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *FieldOptions_FeatureSupport) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FieldOptions_FeatureSupport) ProtoMessage() {} + +func (x *FieldOptions_FeatureSupport) ProtoReflect() protoreflect.Message { + mi := &file_google_protobuf_descriptor_proto_msgTypes[28] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FieldOptions_FeatureSupport.ProtoReflect.Descriptor instead. +func (*FieldOptions_FeatureSupport) Descriptor() ([]byte, []int) { + return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{12, 1} +} + +func (x *FieldOptions_FeatureSupport) GetEditionIntroduced() Edition { + if x != nil && x.EditionIntroduced != nil { + return *x.EditionIntroduced + } + return Edition_EDITION_UNKNOWN +} + +func (x *FieldOptions_FeatureSupport) GetEditionDeprecated() Edition { + if x != nil && x.EditionDeprecated != nil { + return *x.EditionDeprecated + } + return Edition_EDITION_UNKNOWN +} + +func (x *FieldOptions_FeatureSupport) GetDeprecationWarning() string { + if x != nil && x.DeprecationWarning != nil { + return *x.DeprecationWarning + } + return "" +} + +func (x *FieldOptions_FeatureSupport) GetEditionRemoved() Edition { + if x != nil && x.EditionRemoved != nil { + return *x.EditionRemoved + } + return Edition_EDITION_UNKNOWN +} + // The name of the uninterpreted option. Each string represents a segment in // a dot-separated name. is_extension is true iff a segment represents an // extension (denoted with parentheses in options specs in .proto files). @@ -3984,11 +4034,9 @@ type UninterpretedOption_NamePart struct { func (x *UninterpretedOption_NamePart) Reset() { *x = UninterpretedOption_NamePart{} - if protoimpl.UnsafeEnabled { - mi := &file_google_protobuf_descriptor_proto_msgTypes[28] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_google_protobuf_descriptor_proto_msgTypes[29] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *UninterpretedOption_NamePart) String() string { @@ -3998,8 +4046,8 @@ func (x *UninterpretedOption_NamePart) String() string { func (*UninterpretedOption_NamePart) ProtoMessage() {} func (x *UninterpretedOption_NamePart) ProtoReflect() protoreflect.Message { - mi := &file_google_protobuf_descriptor_proto_msgTypes[28] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_google_protobuf_descriptor_proto_msgTypes[29] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -4037,17 +4085,18 @@ type FeatureSetDefaults_FeatureSetEditionDefault struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Edition *Edition `protobuf:"varint,3,opt,name=edition,enum=google.protobuf.Edition" json:"edition,omitempty"` - Features *FeatureSet `protobuf:"bytes,2,opt,name=features" json:"features,omitempty"` + Edition *Edition `protobuf:"varint,3,opt,name=edition,enum=google.protobuf.Edition" json:"edition,omitempty"` + // Defaults of features that can be overridden in this edition. + OverridableFeatures *FeatureSet `protobuf:"bytes,4,opt,name=overridable_features,json=overridableFeatures" json:"overridable_features,omitempty"` + // Defaults of features that can't be overridden in this edition. + FixedFeatures *FeatureSet `protobuf:"bytes,5,opt,name=fixed_features,json=fixedFeatures" json:"fixed_features,omitempty"` } func (x *FeatureSetDefaults_FeatureSetEditionDefault) Reset() { *x = FeatureSetDefaults_FeatureSetEditionDefault{} - if protoimpl.UnsafeEnabled { - mi := &file_google_protobuf_descriptor_proto_msgTypes[29] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_google_protobuf_descriptor_proto_msgTypes[30] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *FeatureSetDefaults_FeatureSetEditionDefault) String() string { @@ -4057,8 +4106,8 @@ func (x *FeatureSetDefaults_FeatureSetEditionDefault) String() string { func (*FeatureSetDefaults_FeatureSetEditionDefault) ProtoMessage() {} func (x *FeatureSetDefaults_FeatureSetEditionDefault) ProtoReflect() protoreflect.Message { - mi := &file_google_protobuf_descriptor_proto_msgTypes[29] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_google_protobuf_descriptor_proto_msgTypes[30] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -4080,9 +4129,16 @@ func (x *FeatureSetDefaults_FeatureSetEditionDefault) GetEdition() Edition { return Edition_EDITION_UNKNOWN } -func (x *FeatureSetDefaults_FeatureSetEditionDefault) GetFeatures() *FeatureSet { +func (x *FeatureSetDefaults_FeatureSetEditionDefault) GetOverridableFeatures() *FeatureSet { if x != nil { - return x.Features + return x.OverridableFeatures + } + return nil +} + +func (x *FeatureSetDefaults_FeatureSetEditionDefault) GetFixedFeatures() *FeatureSet { + if x != nil { + return x.FixedFeatures } return nil } @@ -4187,11 +4243,9 @@ type SourceCodeInfo_Location struct { func (x *SourceCodeInfo_Location) Reset() { *x = SourceCodeInfo_Location{} - if protoimpl.UnsafeEnabled { - mi := &file_google_protobuf_descriptor_proto_msgTypes[30] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_google_protobuf_descriptor_proto_msgTypes[31] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *SourceCodeInfo_Location) String() string { @@ -4201,8 +4255,8 @@ func (x *SourceCodeInfo_Location) String() string { func (*SourceCodeInfo_Location) ProtoMessage() {} func (x *SourceCodeInfo_Location) ProtoReflect() protoreflect.Message { - mi := &file_google_protobuf_descriptor_proto_msgTypes[30] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_google_protobuf_descriptor_proto_msgTypes[31] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -4274,11 +4328,9 @@ type GeneratedCodeInfo_Annotation struct { func (x *GeneratedCodeInfo_Annotation) Reset() { *x = GeneratedCodeInfo_Annotation{} - if protoimpl.UnsafeEnabled { - mi := &file_google_protobuf_descriptor_proto_msgTypes[31] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_google_protobuf_descriptor_proto_msgTypes[32] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *GeneratedCodeInfo_Annotation) String() string { @@ -4288,8 +4340,8 @@ func (x *GeneratedCodeInfo_Annotation) String() string { func (*GeneratedCodeInfo_Annotation) ProtoMessage() {} func (x *GeneratedCodeInfo_Annotation) ProtoReflect() protoreflect.Message { - mi := &file_google_protobuf_descriptor_proto_msgTypes[31] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_google_protobuf_descriptor_proto_msgTypes[32] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -4597,7 +4649,7 @@ var file_google_protobuf_descriptor_proto_rawDesc = []byte{ 0x67, 0x12, 0x30, 0x0a, 0x10, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, - 0x69, 0x6e, 0x67, 0x22, 0x97, 0x09, 0x0a, 0x0b, 0x46, 0x69, 0x6c, 0x65, 0x4f, 0x70, 0x74, 0x69, + 0x69, 0x6e, 0x67, 0x22, 0xad, 0x09, 0x0a, 0x0b, 0x46, 0x69, 0x6c, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6a, 0x61, 0x76, 0x61, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x30, 0x0a, 0x14, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x6f, @@ -4670,405 +4722,445 @@ var file_google_protobuf_descriptor_proto_rawDesc = []byte{ 0x45, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x43, 0x4f, 0x44, 0x45, 0x5f, 0x53, 0x49, 0x5a, 0x45, 0x10, 0x02, 0x12, 0x10, 0x0a, 0x0c, 0x4c, 0x49, 0x54, 0x45, 0x5f, 0x52, 0x55, 0x4e, 0x54, 0x49, 0x4d, 0x45, 0x10, 0x03, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, - 0x02, 0x4a, 0x04, 0x08, 0x2a, 0x10, 0x2b, 0x4a, 0x04, 0x08, 0x26, 0x10, 0x27, 0x22, 0xf4, 0x03, - 0x0a, 0x0e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x12, 0x3c, 0x0a, 0x17, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x65, 0x74, 0x5f, - 0x77, 0x69, 0x72, 0x65, 0x5f, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x14, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x53, 0x65, 0x74, 0x57, 0x69, 0x72, 0x65, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x4c, - 0x0a, 0x1f, 0x6e, 0x6f, 0x5f, 0x73, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x5f, 0x64, 0x65, - 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6f, - 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x1c, - 0x6e, 0x6f, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, - 0x70, 0x74, 0x6f, 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6f, 0x72, 0x12, 0x25, 0x0a, 0x0a, - 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, - 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, - 0x74, 0x65, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x61, 0x70, 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x79, - 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x6d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, - 0x12, 0x56, 0x0a, 0x26, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x6c, - 0x65, 0x67, 0x61, 0x63, 0x79, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, - 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08, - 0x42, 0x02, 0x18, 0x01, 0x52, 0x22, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, - 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x4a, 0x73, 0x6f, 0x6e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x43, - 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x73, 0x12, 0x37, 0x0a, 0x08, 0x66, 0x65, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x65, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x52, 0x08, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x73, 0x12, 0x58, 0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, - 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, - 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, - 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2a, 0x09, 0x08, 0xe8, 0x07, - 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, 0x4a, 0x04, 0x08, 0x05, - 0x10, 0x06, 0x4a, 0x04, 0x08, 0x06, 0x10, 0x07, 0x4a, 0x04, 0x08, 0x08, 0x10, 0x09, 0x4a, 0x04, - 0x08, 0x09, 0x10, 0x0a, 0x22, 0xad, 0x0a, 0x0a, 0x0c, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x41, 0x0a, 0x05, 0x63, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0e, 0x32, 0x23, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x2e, 0x43, 0x54, 0x79, 0x70, 0x65, 0x3a, 0x06, 0x53, 0x54, 0x52, 0x49, 0x4e, - 0x47, 0x52, 0x05, 0x63, 0x74, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x61, 0x63, 0x6b, - 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x64, - 0x12, 0x47, 0x0a, 0x06, 0x6a, 0x73, 0x74, 0x79, 0x70, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, - 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, - 0x4a, 0x53, 0x54, 0x79, 0x70, 0x65, 0x3a, 0x09, 0x4a, 0x53, 0x5f, 0x4e, 0x4f, 0x52, 0x4d, 0x41, - 0x4c, 0x52, 0x06, 0x6a, 0x73, 0x74, 0x79, 0x70, 0x65, 0x12, 0x19, 0x0a, 0x04, 0x6c, 0x61, 0x7a, - 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x04, - 0x6c, 0x61, 0x7a, 0x79, 0x12, 0x2e, 0x0a, 0x0f, 0x75, 0x6e, 0x76, 0x65, 0x72, 0x69, 0x66, 0x69, - 0x65, 0x64, 0x5f, 0x6c, 0x61, 0x7a, 0x79, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, - 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0e, 0x75, 0x6e, 0x76, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, - 0x4c, 0x61, 0x7a, 0x79, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, - 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, - 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x19, 0x0a, 0x04, 0x77, - 0x65, 0x61, 0x6b, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, - 0x52, 0x04, 0x77, 0x65, 0x61, 0x6b, 0x12, 0x28, 0x0a, 0x0c, 0x64, 0x65, 0x62, 0x75, 0x67, 0x5f, - 0x72, 0x65, 0x64, 0x61, 0x63, 0x74, 0x18, 0x10, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, - 0x6c, 0x73, 0x65, 0x52, 0x0b, 0x64, 0x65, 0x62, 0x75, 0x67, 0x52, 0x65, 0x64, 0x61, 0x63, 0x74, - 0x12, 0x4b, 0x0a, 0x09, 0x72, 0x65, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x11, 0x20, - 0x01, 0x28, 0x0e, 0x32, 0x2d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x74, 0x65, 0x6e, 0x74, 0x69, - 0x6f, 0x6e, 0x52, 0x09, 0x72, 0x65, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x48, 0x0a, - 0x07, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x18, 0x13, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x2e, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x4f, 0x70, - 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x07, - 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x12, 0x57, 0x0a, 0x10, 0x65, 0x64, 0x69, 0x74, 0x69, - 0x6f, 0x6e, 0x5f, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x14, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x2c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x2e, 0x45, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x52, - 0x0f, 0x65, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, - 0x12, 0x37, 0x0a, 0x08, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x18, 0x15, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x52, - 0x08, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x58, 0x0a, 0x14, 0x75, 0x6e, 0x69, - 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, - 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, - 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, - 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, - 0x69, 0x6f, 0x6e, 0x1a, 0x5a, 0x0a, 0x0e, 0x45, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x65, - 0x66, 0x61, 0x75, 0x6c, 0x74, 0x12, 0x32, 0x0a, 0x07, 0x65, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, - 0x52, 0x07, 0x65, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, - 0x2f, 0x0a, 0x05, 0x43, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x54, 0x52, 0x49, - 0x4e, 0x47, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x43, 0x4f, 0x52, 0x44, 0x10, 0x01, 0x12, 0x10, - 0x0a, 0x0c, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x5f, 0x50, 0x49, 0x45, 0x43, 0x45, 0x10, 0x02, - 0x22, 0x35, 0x0a, 0x06, 0x4a, 0x53, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0d, 0x0a, 0x09, 0x4a, 0x53, - 0x5f, 0x4e, 0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x4a, 0x53, 0x5f, - 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x4a, 0x53, 0x5f, 0x4e, - 0x55, 0x4d, 0x42, 0x45, 0x52, 0x10, 0x02, 0x22, 0x55, 0x0a, 0x0f, 0x4f, 0x70, 0x74, 0x69, 0x6f, - 0x6e, 0x52, 0x65, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x15, 0x0a, 0x11, 0x52, 0x45, - 0x54, 0x45, 0x4e, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, - 0x00, 0x12, 0x15, 0x0a, 0x11, 0x52, 0x45, 0x54, 0x45, 0x4e, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x52, - 0x55, 0x4e, 0x54, 0x49, 0x4d, 0x45, 0x10, 0x01, 0x12, 0x14, 0x0a, 0x10, 0x52, 0x45, 0x54, 0x45, - 0x4e, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x10, 0x02, 0x22, 0x8c, - 0x02, 0x0a, 0x10, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x54, - 0x79, 0x70, 0x65, 0x12, 0x17, 0x0a, 0x13, 0x54, 0x41, 0x52, 0x47, 0x45, 0x54, 0x5f, 0x54, 0x59, - 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, - 0x54, 0x41, 0x52, 0x47, 0x45, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x46, 0x49, 0x4c, 0x45, - 0x10, 0x01, 0x12, 0x1f, 0x0a, 0x1b, 0x54, 0x41, 0x52, 0x47, 0x45, 0x54, 0x5f, 0x54, 0x59, 0x50, - 0x45, 0x5f, 0x45, 0x58, 0x54, 0x45, 0x4e, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x52, 0x41, 0x4e, 0x47, - 0x45, 0x10, 0x02, 0x12, 0x17, 0x0a, 0x13, 0x54, 0x41, 0x52, 0x47, 0x45, 0x54, 0x5f, 0x54, 0x59, - 0x50, 0x45, 0x5f, 0x4d, 0x45, 0x53, 0x53, 0x41, 0x47, 0x45, 0x10, 0x03, 0x12, 0x15, 0x0a, 0x11, - 0x54, 0x41, 0x52, 0x47, 0x45, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x46, 0x49, 0x45, 0x4c, - 0x44, 0x10, 0x04, 0x12, 0x15, 0x0a, 0x11, 0x54, 0x41, 0x52, 0x47, 0x45, 0x54, 0x5f, 0x54, 0x59, - 0x50, 0x45, 0x5f, 0x4f, 0x4e, 0x45, 0x4f, 0x46, 0x10, 0x05, 0x12, 0x14, 0x0a, 0x10, 0x54, 0x41, - 0x52, 0x47, 0x45, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x45, 0x4e, 0x55, 0x4d, 0x10, 0x06, - 0x12, 0x1a, 0x0a, 0x16, 0x54, 0x41, 0x52, 0x47, 0x45, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, - 0x45, 0x4e, 0x55, 0x4d, 0x5f, 0x45, 0x4e, 0x54, 0x52, 0x59, 0x10, 0x07, 0x12, 0x17, 0x0a, 0x13, - 0x54, 0x41, 0x52, 0x47, 0x45, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x45, 0x52, 0x56, - 0x49, 0x43, 0x45, 0x10, 0x08, 0x12, 0x16, 0x0a, 0x12, 0x54, 0x41, 0x52, 0x47, 0x45, 0x54, 0x5f, - 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4d, 0x45, 0x54, 0x48, 0x4f, 0x44, 0x10, 0x09, 0x2a, 0x09, 0x08, - 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, 0x4a, 0x04, - 0x08, 0x12, 0x10, 0x13, 0x22, 0xac, 0x01, 0x0a, 0x0c, 0x4f, 0x6e, 0x65, 0x6f, 0x66, 0x4f, 0x70, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x37, 0x0a, 0x08, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x53, 0x65, 0x74, 0x52, 0x08, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x58, - 0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f, - 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, - 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, - 0x80, 0x80, 0x02, 0x22, 0xd1, 0x02, 0x0a, 0x0b, 0x45, 0x6e, 0x75, 0x6d, 0x4f, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x61, 0x6c, 0x69, - 0x61, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x41, - 0x6c, 0x69, 0x61, 0x73, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, - 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, - 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x56, 0x0a, 0x26, 0x64, - 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, - 0x5f, 0x6a, 0x73, 0x6f, 0x6e, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x66, - 0x6c, 0x69, 0x63, 0x74, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x42, 0x02, 0x18, 0x01, 0x52, - 0x22, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x4c, 0x65, 0x67, 0x61, 0x63, - 0x79, 0x4a, 0x73, 0x6f, 0x6e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x6c, 0x69, - 0x63, 0x74, 0x73, 0x12, 0x37, 0x0a, 0x08, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x18, - 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, - 0x65, 0x74, 0x52, 0x08, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x58, 0x0a, 0x14, - 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, - 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, + 0x02, 0x4a, 0x04, 0x08, 0x2a, 0x10, 0x2b, 0x4a, 0x04, 0x08, 0x26, 0x10, 0x27, 0x52, 0x14, 0x70, + 0x68, 0x70, 0x5f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x73, 0x22, 0xf4, 0x03, 0x0a, 0x0e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x4f, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x3c, 0x0a, 0x17, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x77, 0x69, 0x72, 0x65, 0x5f, 0x66, 0x6f, 0x72, 0x6d, 0x61, + 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x14, + 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x53, 0x65, 0x74, 0x57, 0x69, 0x72, 0x65, 0x46, 0x6f, + 0x72, 0x6d, 0x61, 0x74, 0x12, 0x4c, 0x0a, 0x1f, 0x6e, 0x6f, 0x5f, 0x73, 0x74, 0x61, 0x6e, 0x64, + 0x61, 0x72, 0x64, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x5f, 0x61, + 0x63, 0x63, 0x65, 0x73, 0x73, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, + 0x61, 0x6c, 0x73, 0x65, 0x52, 0x1c, 0x6e, 0x6f, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, + 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, + 0x6f, 0x72, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64, + 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x61, 0x70, + 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x6d, 0x61, + 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x56, 0x0a, 0x26, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, + 0x61, 0x74, 0x65, 0x64, 0x5f, 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, + 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x73, + 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08, 0x42, 0x02, 0x18, 0x01, 0x52, 0x22, 0x64, 0x65, 0x70, 0x72, + 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x4a, 0x73, 0x6f, 0x6e, + 0x46, 0x69, 0x65, 0x6c, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x73, 0x12, 0x37, + 0x0a, 0x08, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x52, 0x08, 0x66, + 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x58, 0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, + 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, + 0xe7, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, + 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, - 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, - 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, - 0x02, 0x4a, 0x04, 0x08, 0x05, 0x10, 0x06, 0x22, 0x81, 0x02, 0x0a, 0x10, 0x45, 0x6e, 0x75, 0x6d, - 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x25, 0x0a, 0x0a, - 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, - 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, - 0x74, 0x65, 0x64, 0x12, 0x37, 0x0a, 0x08, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, - 0x65, 0x74, 0x52, 0x08, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x28, 0x0a, 0x0c, - 0x64, 0x65, 0x62, 0x75, 0x67, 0x5f, 0x72, 0x65, 0x64, 0x61, 0x63, 0x74, 0x18, 0x03, 0x20, 0x01, + 0x6e, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x4a, 0x04, 0x08, 0x04, + 0x10, 0x05, 0x4a, 0x04, 0x08, 0x05, 0x10, 0x06, 0x4a, 0x04, 0x08, 0x06, 0x10, 0x07, 0x4a, 0x04, + 0x08, 0x08, 0x10, 0x09, 0x4a, 0x04, 0x08, 0x09, 0x10, 0x0a, 0x22, 0x9d, 0x0d, 0x0a, 0x0c, 0x46, + 0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x41, 0x0a, 0x05, 0x63, + 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x23, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, + 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x43, 0x54, 0x79, 0x70, 0x65, 0x3a, + 0x06, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x52, 0x05, 0x63, 0x74, 0x79, 0x70, 0x65, 0x12, 0x16, + 0x0a, 0x06, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, + 0x70, 0x61, 0x63, 0x6b, 0x65, 0x64, 0x12, 0x47, 0x0a, 0x06, 0x6a, 0x73, 0x74, 0x79, 0x70, 0x65, + 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x4a, 0x53, 0x54, 0x79, 0x70, 0x65, 0x3a, 0x09, 0x4a, 0x53, + 0x5f, 0x4e, 0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x52, 0x06, 0x6a, 0x73, 0x74, 0x79, 0x70, 0x65, 0x12, + 0x19, 0x0a, 0x04, 0x6c, 0x61, 0x7a, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, + 0x61, 0x6c, 0x73, 0x65, 0x52, 0x04, 0x6c, 0x61, 0x7a, 0x79, 0x12, 0x2e, 0x0a, 0x0f, 0x75, 0x6e, + 0x76, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, 0x5f, 0x6c, 0x61, 0x7a, 0x79, 0x18, 0x0f, 0x20, + 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0e, 0x75, 0x6e, 0x76, 0x65, + 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, 0x4c, 0x61, 0x7a, 0x79, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65, + 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, + 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, + 0x64, 0x12, 0x19, 0x0a, 0x04, 0x77, 0x65, 0x61, 0x6b, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x3a, + 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x04, 0x77, 0x65, 0x61, 0x6b, 0x12, 0x28, 0x0a, 0x0c, + 0x64, 0x65, 0x62, 0x75, 0x67, 0x5f, 0x72, 0x65, 0x64, 0x61, 0x63, 0x74, 0x18, 0x10, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0b, 0x64, 0x65, 0x62, 0x75, 0x67, - 0x52, 0x65, 0x64, 0x61, 0x63, 0x74, 0x12, 0x58, 0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, + 0x52, 0x65, 0x64, 0x61, 0x63, 0x74, 0x12, 0x4b, 0x0a, 0x09, 0x72, 0x65, 0x74, 0x65, 0x6e, 0x74, + 0x69, 0x6f, 0x6e, 0x18, 0x11, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, + 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, + 0x65, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x72, 0x65, 0x74, 0x65, 0x6e, 0x74, + 0x69, 0x6f, 0x6e, 0x12, 0x48, 0x0a, 0x07, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x18, 0x13, + 0x20, 0x03, 0x28, 0x0e, 0x32, 0x2e, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, + 0x54, 0x79, 0x70, 0x65, 0x52, 0x07, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x12, 0x57, 0x0a, + 0x10, 0x65, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, + 0x73, 0x18, 0x14, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x45, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x65, + 0x66, 0x61, 0x75, 0x6c, 0x74, 0x52, 0x0f, 0x65, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x65, + 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x37, 0x0a, 0x08, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x73, 0x18, 0x15, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, + 0x72, 0x65, 0x53, 0x65, 0x74, 0x52, 0x08, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, + 0x55, 0x0a, 0x0f, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x73, 0x75, 0x70, 0x70, 0x6f, + 0x72, 0x74, 0x18, 0x16, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, + 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, + 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x0e, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, + 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x58, 0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, - 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x22, 0xd5, 0x01, 0x0a, 0x0e, - 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x37, - 0x0a, 0x08, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x18, 0x22, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x52, 0x08, 0x66, - 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, - 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x21, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, - 0x73, 0x65, 0x52, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x58, - 0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f, - 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, + 0x1a, 0x5a, 0x0a, 0x0e, 0x45, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x65, 0x66, 0x61, 0x75, + 0x6c, 0x74, 0x12, 0x32, 0x0a, 0x07, 0x65, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x65, + 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x96, 0x02, 0x0a, + 0x0e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x12, + 0x47, 0x0a, 0x12, 0x65, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x6e, 0x74, 0x72, 0x6f, + 0x64, 0x75, 0x63, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x64, + 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x11, 0x65, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, + 0x74, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x64, 0x12, 0x47, 0x0a, 0x12, 0x65, 0x64, 0x69, 0x74, + 0x69, 0x6f, 0x6e, 0x5f, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x11, + 0x65, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, + 0x64, 0x12, 0x2f, 0x0a, 0x13, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x5f, 0x77, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, + 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x57, 0x61, 0x72, 0x6e, 0x69, + 0x6e, 0x67, 0x12, 0x41, 0x0a, 0x0f, 0x65, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x65, + 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x64, + 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x65, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, + 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x22, 0x2f, 0x0a, 0x05, 0x43, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0a, + 0x0a, 0x06, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x43, 0x4f, + 0x52, 0x44, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x5f, 0x50, + 0x49, 0x45, 0x43, 0x45, 0x10, 0x02, 0x22, 0x35, 0x0a, 0x06, 0x4a, 0x53, 0x54, 0x79, 0x70, 0x65, + 0x12, 0x0d, 0x0a, 0x09, 0x4a, 0x53, 0x5f, 0x4e, 0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x10, 0x00, 0x12, + 0x0d, 0x0a, 0x09, 0x4a, 0x53, 0x5f, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x0d, + 0x0a, 0x09, 0x4a, 0x53, 0x5f, 0x4e, 0x55, 0x4d, 0x42, 0x45, 0x52, 0x10, 0x02, 0x22, 0x55, 0x0a, + 0x0f, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x15, 0x0a, 0x11, 0x52, 0x45, 0x54, 0x45, 0x4e, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, + 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x15, 0x0a, 0x11, 0x52, 0x45, 0x54, 0x45, 0x4e, + 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x52, 0x55, 0x4e, 0x54, 0x49, 0x4d, 0x45, 0x10, 0x01, 0x12, 0x14, + 0x0a, 0x10, 0x52, 0x45, 0x54, 0x45, 0x4e, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x53, 0x4f, 0x55, 0x52, + 0x43, 0x45, 0x10, 0x02, 0x22, 0x8c, 0x02, 0x0a, 0x10, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x54, + 0x61, 0x72, 0x67, 0x65, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x17, 0x0a, 0x13, 0x54, 0x41, 0x52, + 0x47, 0x45, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, + 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x54, 0x41, 0x52, 0x47, 0x45, 0x54, 0x5f, 0x54, 0x59, 0x50, + 0x45, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x10, 0x01, 0x12, 0x1f, 0x0a, 0x1b, 0x54, 0x41, 0x52, 0x47, + 0x45, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x45, 0x58, 0x54, 0x45, 0x4e, 0x53, 0x49, 0x4f, + 0x4e, 0x5f, 0x52, 0x41, 0x4e, 0x47, 0x45, 0x10, 0x02, 0x12, 0x17, 0x0a, 0x13, 0x54, 0x41, 0x52, + 0x47, 0x45, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4d, 0x45, 0x53, 0x53, 0x41, 0x47, 0x45, + 0x10, 0x03, 0x12, 0x15, 0x0a, 0x11, 0x54, 0x41, 0x52, 0x47, 0x45, 0x54, 0x5f, 0x54, 0x59, 0x50, + 0x45, 0x5f, 0x46, 0x49, 0x45, 0x4c, 0x44, 0x10, 0x04, 0x12, 0x15, 0x0a, 0x11, 0x54, 0x41, 0x52, + 0x47, 0x45, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4f, 0x4e, 0x45, 0x4f, 0x46, 0x10, 0x05, + 0x12, 0x14, 0x0a, 0x10, 0x54, 0x41, 0x52, 0x47, 0x45, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, + 0x45, 0x4e, 0x55, 0x4d, 0x10, 0x06, 0x12, 0x1a, 0x0a, 0x16, 0x54, 0x41, 0x52, 0x47, 0x45, 0x54, + 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x45, 0x4e, 0x55, 0x4d, 0x5f, 0x45, 0x4e, 0x54, 0x52, 0x59, + 0x10, 0x07, 0x12, 0x17, 0x0a, 0x13, 0x54, 0x41, 0x52, 0x47, 0x45, 0x54, 0x5f, 0x54, 0x59, 0x50, + 0x45, 0x5f, 0x53, 0x45, 0x52, 0x56, 0x49, 0x43, 0x45, 0x10, 0x08, 0x12, 0x16, 0x0a, 0x12, 0x54, + 0x41, 0x52, 0x47, 0x45, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4d, 0x45, 0x54, 0x48, 0x4f, + 0x44, 0x10, 0x09, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x4a, 0x04, + 0x08, 0x04, 0x10, 0x05, 0x4a, 0x04, 0x08, 0x12, 0x10, 0x13, 0x22, 0xac, 0x01, 0x0a, 0x0c, 0x4f, + 0x6e, 0x65, 0x6f, 0x66, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x37, 0x0a, 0x08, 0x66, + 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, - 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, - 0x80, 0x80, 0x02, 0x22, 0x99, 0x03, 0x0a, 0x0d, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x4f, 0x70, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, - 0x74, 0x65, 0x64, 0x18, 0x21, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, - 0x52, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x71, 0x0a, 0x11, - 0x69, 0x64, 0x65, 0x6d, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x5f, 0x6c, 0x65, 0x76, 0x65, - 0x6c, 0x18, 0x22, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, - 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x49, 0x64, 0x65, 0x6d, 0x70, 0x6f, 0x74, 0x65, - 0x6e, 0x63, 0x79, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x3a, 0x13, 0x49, 0x44, 0x45, 0x4d, 0x50, 0x4f, - 0x54, 0x45, 0x4e, 0x43, 0x59, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x52, 0x10, 0x69, - 0x64, 0x65, 0x6d, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, - 0x37, 0x0a, 0x08, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x18, 0x23, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x52, 0x08, - 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x58, 0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, - 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, - 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, - 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, - 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x22, 0x50, 0x0a, 0x10, 0x49, 0x64, 0x65, 0x6d, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x63, - 0x79, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x17, 0x0a, 0x13, 0x49, 0x44, 0x45, 0x4d, 0x50, 0x4f, - 0x54, 0x45, 0x4e, 0x43, 0x59, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, - 0x13, 0x0a, 0x0f, 0x4e, 0x4f, 0x5f, 0x53, 0x49, 0x44, 0x45, 0x5f, 0x45, 0x46, 0x46, 0x45, 0x43, - 0x54, 0x53, 0x10, 0x01, 0x12, 0x0e, 0x0a, 0x0a, 0x49, 0x44, 0x45, 0x4d, 0x50, 0x4f, 0x54, 0x45, - 0x4e, 0x54, 0x10, 0x02, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x22, - 0x9a, 0x03, 0x0a, 0x13, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, - 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x41, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, - 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, - 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x4e, 0x61, 0x6d, 0x65, - 0x50, 0x61, 0x72, 0x74, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x29, 0x0a, 0x10, 0x69, 0x64, - 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, - 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2c, 0x0a, 0x12, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x76, - 0x65, 0x5f, 0x69, 0x6e, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x04, 0x52, 0x10, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x49, 0x6e, 0x74, 0x56, 0x61, - 0x6c, 0x75, 0x65, 0x12, 0x2c, 0x0a, 0x12, 0x6e, 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5f, - 0x69, 0x6e, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x10, 0x6e, 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x49, 0x6e, 0x74, 0x56, 0x61, 0x6c, 0x75, - 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0b, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x56, - 0x61, 0x6c, 0x75, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x73, 0x74, 0x72, 0x69, - 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x61, 0x67, 0x67, 0x72, 0x65, - 0x67, 0x61, 0x74, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0e, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x1a, 0x4a, 0x0a, 0x08, 0x4e, 0x61, 0x6d, 0x65, 0x50, 0x61, 0x72, 0x74, 0x12, 0x1b, 0x0a, 0x09, - 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x18, 0x01, 0x20, 0x02, 0x28, 0x09, 0x52, - 0x08, 0x6e, 0x61, 0x6d, 0x65, 0x50, 0x61, 0x72, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x73, 0x5f, - 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x02, 0x28, 0x08, 0x52, - 0x0b, 0x69, 0x73, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x8c, 0x0a, 0x0a, - 0x0a, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x12, 0x8b, 0x01, 0x0a, 0x0e, - 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0e, 0x32, 0x29, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, - 0x74, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x63, 0x65, 0x42, - 0x39, 0x88, 0x01, 0x01, 0x98, 0x01, 0x04, 0x98, 0x01, 0x01, 0xa2, 0x01, 0x0d, 0x12, 0x08, 0x45, - 0x58, 0x50, 0x4c, 0x49, 0x43, 0x49, 0x54, 0x18, 0xe6, 0x07, 0xa2, 0x01, 0x0d, 0x12, 0x08, 0x49, - 0x4d, 0x50, 0x4c, 0x49, 0x43, 0x49, 0x54, 0x18, 0xe7, 0x07, 0xa2, 0x01, 0x0d, 0x12, 0x08, 0x45, - 0x58, 0x50, 0x4c, 0x49, 0x43, 0x49, 0x54, 0x18, 0xe8, 0x07, 0x52, 0x0d, 0x66, 0x69, 0x65, 0x6c, - 0x64, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x66, 0x0a, 0x09, 0x65, 0x6e, 0x75, - 0x6d, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x24, 0x2e, 0x67, + 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x52, 0x08, 0x66, 0x65, 0x61, 0x74, + 0x75, 0x72, 0x65, 0x73, 0x12, 0x58, 0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, + 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, + 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74, + 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2a, 0x09, + 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x22, 0xd1, 0x02, 0x0a, 0x0b, 0x45, 0x6e, + 0x75, 0x6d, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x61, 0x6c, 0x6c, + 0x6f, 0x77, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, + 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65, + 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, + 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, + 0x64, 0x12, 0x56, 0x0a, 0x26, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x5f, + 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, 0x5f, 0x66, 0x69, 0x65, 0x6c, + 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, + 0x08, 0x42, 0x02, 0x18, 0x01, 0x52, 0x22, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, + 0x64, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x4a, 0x73, 0x6f, 0x6e, 0x46, 0x69, 0x65, 0x6c, 0x64, + 0x43, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x73, 0x12, 0x37, 0x0a, 0x08, 0x66, 0x65, 0x61, + 0x74, 0x75, 0x72, 0x65, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x65, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x52, 0x08, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x73, 0x12, 0x58, 0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, + 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, + 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, + 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2a, 0x09, 0x08, 0xe8, + 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x4a, 0x04, 0x08, 0x05, 0x10, 0x06, 0x22, 0xd8, 0x02, + 0x0a, 0x10, 0x45, 0x6e, 0x75, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64, + 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x37, 0x0a, 0x08, 0x66, 0x65, 0x61, + 0x74, 0x75, 0x72, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x65, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x52, 0x08, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x73, 0x12, 0x28, 0x0a, 0x0c, 0x64, 0x65, 0x62, 0x75, 0x67, 0x5f, 0x72, 0x65, 0x64, 0x61, + 0x63, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, + 0x0b, 0x64, 0x65, 0x62, 0x75, 0x67, 0x52, 0x65, 0x64, 0x61, 0x63, 0x74, 0x12, 0x55, 0x0a, 0x0f, + 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x75, 0x70, 0x70, + 0x6f, 0x72, 0x74, 0x52, 0x0e, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x75, 0x70, 0x70, + 0x6f, 0x72, 0x74, 0x12, 0x58, 0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, + 0x65, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, + 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, + 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2a, 0x09, 0x08, + 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x22, 0xd5, 0x01, 0x0a, 0x0e, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x37, 0x0a, 0x08, 0x66, + 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x18, 0x22, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x52, 0x08, 0x66, 0x65, 0x61, 0x74, + 0x75, 0x72, 0x65, 0x73, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, + 0x65, 0x64, 0x18, 0x21, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, + 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x58, 0x0a, 0x14, 0x75, + 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, + 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, + 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, + 0x22, 0x99, 0x03, 0x0a, 0x0d, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, + 0x18, 0x21, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64, + 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x71, 0x0a, 0x11, 0x69, 0x64, 0x65, + 0x6d, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x22, + 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x4f, 0x70, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x49, 0x64, 0x65, 0x6d, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x63, 0x79, + 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x3a, 0x13, 0x49, 0x44, 0x45, 0x4d, 0x50, 0x4f, 0x54, 0x45, 0x4e, + 0x43, 0x59, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x52, 0x10, 0x69, 0x64, 0x65, 0x6d, + 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x37, 0x0a, 0x08, + 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x18, 0x23, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x52, 0x08, 0x66, 0x65, 0x61, + 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x58, 0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, + 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, + 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, + 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, + 0x50, 0x0a, 0x10, 0x49, 0x64, 0x65, 0x6d, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x4c, 0x65, + 0x76, 0x65, 0x6c, 0x12, 0x17, 0x0a, 0x13, 0x49, 0x44, 0x45, 0x4d, 0x50, 0x4f, 0x54, 0x45, 0x4e, + 0x43, 0x59, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x13, 0x0a, 0x0f, + 0x4e, 0x4f, 0x5f, 0x53, 0x49, 0x44, 0x45, 0x5f, 0x45, 0x46, 0x46, 0x45, 0x43, 0x54, 0x53, 0x10, + 0x01, 0x12, 0x0e, 0x0a, 0x0a, 0x49, 0x44, 0x45, 0x4d, 0x50, 0x4f, 0x54, 0x45, 0x4e, 0x54, 0x10, + 0x02, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x22, 0x9a, 0x03, 0x0a, + 0x13, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x41, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, + 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x50, 0x61, 0x72, + 0x74, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x29, 0x0a, 0x10, 0x69, 0x64, 0x65, 0x6e, 0x74, + 0x69, 0x66, 0x69, 0x65, 0x72, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x12, 0x2c, 0x0a, 0x12, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x69, + 0x6e, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x10, + 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x49, 0x6e, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, + 0x12, 0x2c, 0x0a, 0x12, 0x6e, 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x69, 0x6e, 0x74, + 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x6e, 0x65, + 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x49, 0x6e, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x21, + 0x0a, 0x0c, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x01, 0x52, 0x0b, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, + 0x61, 0x6c, 0x75, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, + 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x61, + 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x4a, 0x0a, + 0x08, 0x4e, 0x61, 0x6d, 0x65, 0x50, 0x61, 0x72, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x6e, 0x61, 0x6d, + 0x65, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x18, 0x01, 0x20, 0x02, 0x28, 0x09, 0x52, 0x08, 0x6e, 0x61, + 0x6d, 0x65, 0x50, 0x61, 0x72, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x73, 0x5f, 0x65, 0x78, 0x74, + 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x02, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x73, + 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0xa7, 0x0a, 0x0a, 0x0a, 0x46, 0x65, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x12, 0x91, 0x01, 0x0a, 0x0e, 0x66, 0x69, 0x65, + 0x6c, 0x64, 0x5f, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0e, 0x32, 0x29, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x2e, 0x46, + 0x69, 0x65, 0x6c, 0x64, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x63, 0x65, 0x42, 0x3f, 0x88, 0x01, + 0x01, 0x98, 0x01, 0x04, 0x98, 0x01, 0x01, 0xa2, 0x01, 0x0d, 0x12, 0x08, 0x45, 0x58, 0x50, 0x4c, + 0x49, 0x43, 0x49, 0x54, 0x18, 0xe6, 0x07, 0xa2, 0x01, 0x0d, 0x12, 0x08, 0x49, 0x4d, 0x50, 0x4c, + 0x49, 0x43, 0x49, 0x54, 0x18, 0xe7, 0x07, 0xa2, 0x01, 0x0d, 0x12, 0x08, 0x45, 0x58, 0x50, 0x4c, + 0x49, 0x43, 0x49, 0x54, 0x18, 0xe8, 0x07, 0xb2, 0x01, 0x03, 0x08, 0xe8, 0x07, 0x52, 0x0d, 0x66, + 0x69, 0x65, 0x6c, 0x64, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x6c, 0x0a, 0x09, + 0x65, 0x6e, 0x75, 0x6d, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, + 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x2e, 0x45, 0x6e, 0x75, + 0x6d, 0x54, 0x79, 0x70, 0x65, 0x42, 0x29, 0x88, 0x01, 0x01, 0x98, 0x01, 0x06, 0x98, 0x01, 0x01, + 0xa2, 0x01, 0x0b, 0x12, 0x06, 0x43, 0x4c, 0x4f, 0x53, 0x45, 0x44, 0x18, 0xe6, 0x07, 0xa2, 0x01, + 0x09, 0x12, 0x04, 0x4f, 0x50, 0x45, 0x4e, 0x18, 0xe7, 0x07, 0xb2, 0x01, 0x03, 0x08, 0xe8, 0x07, + 0x52, 0x08, 0x65, 0x6e, 0x75, 0x6d, 0x54, 0x79, 0x70, 0x65, 0x12, 0x98, 0x01, 0x0a, 0x17, 0x72, + 0x65, 0x70, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x65, 0x6e, + 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x31, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, - 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x54, 0x79, - 0x70, 0x65, 0x42, 0x23, 0x88, 0x01, 0x01, 0x98, 0x01, 0x06, 0x98, 0x01, 0x01, 0xa2, 0x01, 0x0b, - 0x12, 0x06, 0x43, 0x4c, 0x4f, 0x53, 0x45, 0x44, 0x18, 0xe6, 0x07, 0xa2, 0x01, 0x09, 0x12, 0x04, - 0x4f, 0x50, 0x45, 0x4e, 0x18, 0xe7, 0x07, 0x52, 0x08, 0x65, 0x6e, 0x75, 0x6d, 0x54, 0x79, 0x70, - 0x65, 0x12, 0x92, 0x01, 0x0a, 0x17, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x66, - 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x0e, 0x32, 0x31, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, - 0x2e, 0x52, 0x65, 0x70, 0x65, 0x61, 0x74, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x45, 0x6e, - 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x42, 0x27, 0x88, 0x01, 0x01, 0x98, 0x01, 0x04, 0x98, 0x01, - 0x01, 0xa2, 0x01, 0x0d, 0x12, 0x08, 0x45, 0x58, 0x50, 0x41, 0x4e, 0x44, 0x45, 0x44, 0x18, 0xe6, - 0x07, 0xa2, 0x01, 0x0b, 0x12, 0x06, 0x50, 0x41, 0x43, 0x4b, 0x45, 0x44, 0x18, 0xe7, 0x07, 0x52, - 0x15, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x45, 0x6e, - 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x78, 0x0a, 0x0f, 0x75, 0x74, 0x66, 0x38, 0x5f, 0x76, - 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, - 0x2a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x2e, 0x55, 0x74, 0x66, - 0x38, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x23, 0x88, 0x01, 0x01, - 0x98, 0x01, 0x04, 0x98, 0x01, 0x01, 0xa2, 0x01, 0x09, 0x12, 0x04, 0x4e, 0x4f, 0x4e, 0x45, 0x18, - 0xe6, 0x07, 0xa2, 0x01, 0x0b, 0x12, 0x06, 0x56, 0x45, 0x52, 0x49, 0x46, 0x59, 0x18, 0xe7, 0x07, - 0x52, 0x0e, 0x75, 0x74, 0x66, 0x38, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x12, 0x78, 0x0a, 0x10, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x65, 0x6e, 0x63, 0x6f, - 0x64, 0x69, 0x6e, 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2b, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x65, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x45, - 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x42, 0x20, 0x88, 0x01, 0x01, 0x98, 0x01, 0x04, 0x98, - 0x01, 0x01, 0xa2, 0x01, 0x14, 0x12, 0x0f, 0x4c, 0x45, 0x4e, 0x47, 0x54, 0x48, 0x5f, 0x50, 0x52, - 0x45, 0x46, 0x49, 0x58, 0x45, 0x44, 0x18, 0xe6, 0x07, 0x52, 0x0f, 0x6d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x7c, 0x0a, 0x0b, 0x6a, 0x73, - 0x6f, 0x6e, 0x5f, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, - 0x26, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x2e, 0x4a, 0x73, 0x6f, - 0x6e, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x42, 0x33, 0x88, 0x01, 0x01, 0x98, 0x01, 0x03, 0x98, - 0x01, 0x06, 0x98, 0x01, 0x01, 0xa2, 0x01, 0x17, 0x12, 0x12, 0x4c, 0x45, 0x47, 0x41, 0x43, 0x59, - 0x5f, 0x42, 0x45, 0x53, 0x54, 0x5f, 0x45, 0x46, 0x46, 0x4f, 0x52, 0x54, 0x18, 0xe6, 0x07, 0xa2, - 0x01, 0x0a, 0x12, 0x05, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x18, 0xe7, 0x07, 0x52, 0x0a, 0x6a, 0x73, - 0x6f, 0x6e, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x22, 0x5c, 0x0a, 0x0d, 0x46, 0x69, 0x65, 0x6c, - 0x64, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x1a, 0x0a, 0x16, 0x46, 0x49, 0x45, - 0x4c, 0x44, 0x5f, 0x50, 0x52, 0x45, 0x53, 0x45, 0x4e, 0x43, 0x45, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, - 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x45, 0x58, 0x50, 0x4c, 0x49, 0x43, 0x49, - 0x54, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x49, 0x4d, 0x50, 0x4c, 0x49, 0x43, 0x49, 0x54, 0x10, - 0x02, 0x12, 0x13, 0x0a, 0x0f, 0x4c, 0x45, 0x47, 0x41, 0x43, 0x59, 0x5f, 0x52, 0x45, 0x51, 0x55, - 0x49, 0x52, 0x45, 0x44, 0x10, 0x03, 0x22, 0x37, 0x0a, 0x08, 0x45, 0x6e, 0x75, 0x6d, 0x54, 0x79, - 0x70, 0x65, 0x12, 0x15, 0x0a, 0x11, 0x45, 0x4e, 0x55, 0x4d, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, - 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x4f, 0x50, 0x45, - 0x4e, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x43, 0x4c, 0x4f, 0x53, 0x45, 0x44, 0x10, 0x02, 0x22, - 0x56, 0x0a, 0x15, 0x52, 0x65, 0x70, 0x65, 0x61, 0x74, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, - 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x23, 0x0a, 0x1f, 0x52, 0x45, 0x50, 0x45, - 0x41, 0x54, 0x45, 0x44, 0x5f, 0x46, 0x49, 0x45, 0x4c, 0x44, 0x5f, 0x45, 0x4e, 0x43, 0x4f, 0x44, - 0x49, 0x4e, 0x47, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x0a, 0x0a, - 0x06, 0x50, 0x41, 0x43, 0x4b, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x45, 0x58, 0x50, - 0x41, 0x4e, 0x44, 0x45, 0x44, 0x10, 0x02, 0x22, 0x43, 0x0a, 0x0e, 0x55, 0x74, 0x66, 0x38, 0x56, - 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1b, 0x0a, 0x17, 0x55, 0x54, 0x46, - 0x38, 0x5f, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x4b, - 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x56, 0x45, 0x52, 0x49, 0x46, 0x59, - 0x10, 0x02, 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x4f, 0x4e, 0x45, 0x10, 0x03, 0x22, 0x53, 0x0a, 0x0f, - 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x12, - 0x1c, 0x0a, 0x18, 0x4d, 0x45, 0x53, 0x53, 0x41, 0x47, 0x45, 0x5f, 0x45, 0x4e, 0x43, 0x4f, 0x44, - 0x49, 0x4e, 0x47, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x13, 0x0a, - 0x0f, 0x4c, 0x45, 0x4e, 0x47, 0x54, 0x48, 0x5f, 0x50, 0x52, 0x45, 0x46, 0x49, 0x58, 0x45, 0x44, - 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x44, 0x45, 0x4c, 0x49, 0x4d, 0x49, 0x54, 0x45, 0x44, 0x10, - 0x02, 0x22, 0x48, 0x0a, 0x0a, 0x4a, 0x73, 0x6f, 0x6e, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, - 0x17, 0x0a, 0x13, 0x4a, 0x53, 0x4f, 0x4e, 0x5f, 0x46, 0x4f, 0x52, 0x4d, 0x41, 0x54, 0x5f, 0x55, - 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x41, 0x4c, 0x4c, 0x4f, - 0x57, 0x10, 0x01, 0x12, 0x16, 0x0a, 0x12, 0x4c, 0x45, 0x47, 0x41, 0x43, 0x59, 0x5f, 0x42, 0x45, - 0x53, 0x54, 0x5f, 0x45, 0x46, 0x46, 0x4f, 0x52, 0x54, 0x10, 0x02, 0x2a, 0x06, 0x08, 0xe8, 0x07, - 0x10, 0xe9, 0x07, 0x2a, 0x06, 0x08, 0xe9, 0x07, 0x10, 0xea, 0x07, 0x2a, 0x06, 0x08, 0xea, 0x07, - 0x10, 0xeb, 0x07, 0x2a, 0x06, 0x08, 0x8b, 0x4e, 0x10, 0x90, 0x4e, 0x2a, 0x06, 0x08, 0x90, 0x4e, - 0x10, 0x91, 0x4e, 0x4a, 0x06, 0x08, 0xe7, 0x07, 0x10, 0xe8, 0x07, 0x22, 0xfe, 0x02, 0x0a, 0x12, - 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, - 0x74, 0x73, 0x12, 0x58, 0x0a, 0x08, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x01, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, - 0x74, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x53, 0x65, 0x74, 0x45, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x65, 0x66, 0x61, 0x75, - 0x6c, 0x74, 0x52, 0x08, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x41, 0x0a, 0x0f, - 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x5f, 0x65, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, - 0x0e, 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x45, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, - 0x41, 0x0a, 0x0f, 0x6d, 0x61, 0x78, 0x69, 0x6d, 0x75, 0x6d, 0x5f, 0x65, 0x64, 0x69, 0x74, 0x69, - 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x64, 0x69, 0x74, 0x69, - 0x6f, 0x6e, 0x52, 0x0e, 0x6d, 0x61, 0x78, 0x69, 0x6d, 0x75, 0x6d, 0x45, 0x64, 0x69, 0x74, 0x69, - 0x6f, 0x6e, 0x1a, 0x87, 0x01, 0x0a, 0x18, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, - 0x74, 0x45, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x12, - 0x32, 0x0a, 0x07, 0x65, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, - 0x32, 0x18, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x45, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x65, 0x64, 0x69, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x37, 0x0a, 0x08, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, - 0x65, 0x74, 0x52, 0x08, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x22, 0xa7, 0x02, 0x0a, - 0x0e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, - 0x44, 0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x28, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, - 0x66, 0x6f, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x6c, 0x6f, 0x63, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0xce, 0x01, 0x0a, 0x08, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x03, 0x28, 0x05, - 0x42, 0x02, 0x10, 0x01, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x16, 0x0a, 0x04, 0x73, 0x70, - 0x61, 0x6e, 0x18, 0x02, 0x20, 0x03, 0x28, 0x05, 0x42, 0x02, 0x10, 0x01, 0x52, 0x04, 0x73, 0x70, - 0x61, 0x6e, 0x12, 0x29, 0x0a, 0x10, 0x6c, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x6f, - 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x6c, 0x65, - 0x61, 0x64, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x2b, 0x0a, - 0x11, 0x74, 0x72, 0x61, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, - 0x74, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x74, 0x72, 0x61, 0x69, 0x6c, 0x69, - 0x6e, 0x67, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x3a, 0x0a, 0x19, 0x6c, 0x65, - 0x61, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x64, 0x65, 0x74, 0x61, 0x63, 0x68, 0x65, 0x64, 0x5f, 0x63, - 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x17, 0x6c, - 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x65, 0x64, 0x43, 0x6f, - 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0xd0, 0x02, 0x0a, 0x11, 0x47, 0x65, 0x6e, 0x65, 0x72, - 0x61, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x4d, 0x0a, 0x0a, - 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x2d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x64, 0x65, - 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, - 0x0a, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0xeb, 0x01, 0x0a, 0x0a, - 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x04, 0x70, 0x61, - 0x74, 0x68, 0x18, 0x01, 0x20, 0x03, 0x28, 0x05, 0x42, 0x02, 0x10, 0x01, 0x52, 0x04, 0x70, 0x61, - 0x74, 0x68, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x66, 0x69, 0x6c, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x46, - 0x69, 0x6c, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x05, 0x52, 0x05, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x6e, 0x64, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x65, 0x6e, 0x64, 0x12, 0x52, 0x0a, 0x08, 0x73, - 0x65, 0x6d, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x36, 0x2e, + 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x2e, 0x52, 0x65, 0x70, 0x65, 0x61, 0x74, + 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x42, + 0x2d, 0x88, 0x01, 0x01, 0x98, 0x01, 0x04, 0x98, 0x01, 0x01, 0xa2, 0x01, 0x0d, 0x12, 0x08, 0x45, + 0x58, 0x50, 0x41, 0x4e, 0x44, 0x45, 0x44, 0x18, 0xe6, 0x07, 0xa2, 0x01, 0x0b, 0x12, 0x06, 0x50, + 0x41, 0x43, 0x4b, 0x45, 0x44, 0x18, 0xe7, 0x07, 0xb2, 0x01, 0x03, 0x08, 0xe8, 0x07, 0x52, 0x15, + 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x65, 0x64, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x45, 0x6e, 0x63, + 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x7e, 0x0a, 0x0f, 0x75, 0x74, 0x66, 0x38, 0x5f, 0x76, 0x61, + 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2a, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x2e, 0x55, 0x74, 0x66, 0x38, + 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x29, 0x88, 0x01, 0x01, 0x98, + 0x01, 0x04, 0x98, 0x01, 0x01, 0xa2, 0x01, 0x09, 0x12, 0x04, 0x4e, 0x4f, 0x4e, 0x45, 0x18, 0xe6, + 0x07, 0xa2, 0x01, 0x0b, 0x12, 0x06, 0x56, 0x45, 0x52, 0x49, 0x46, 0x59, 0x18, 0xe7, 0x07, 0xb2, + 0x01, 0x03, 0x08, 0xe8, 0x07, 0x52, 0x0e, 0x75, 0x74, 0x66, 0x38, 0x56, 0x61, 0x6c, 0x69, 0x64, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x7e, 0x0a, 0x10, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x5f, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, + 0x2b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x2e, 0x4d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x42, 0x26, 0x88, 0x01, + 0x01, 0x98, 0x01, 0x04, 0x98, 0x01, 0x01, 0xa2, 0x01, 0x14, 0x12, 0x0f, 0x4c, 0x45, 0x4e, 0x47, + 0x54, 0x48, 0x5f, 0x50, 0x52, 0x45, 0x46, 0x49, 0x58, 0x45, 0x44, 0x18, 0xe6, 0x07, 0xb2, 0x01, + 0x03, 0x08, 0xe8, 0x07, 0x52, 0x0f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x45, 0x6e, 0x63, + 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x82, 0x01, 0x0a, 0x0b, 0x6a, 0x73, 0x6f, 0x6e, 0x5f, 0x66, + 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x26, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x65, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x2e, 0x4a, 0x73, 0x6f, 0x6e, 0x46, 0x6f, 0x72, + 0x6d, 0x61, 0x74, 0x42, 0x39, 0x88, 0x01, 0x01, 0x98, 0x01, 0x03, 0x98, 0x01, 0x06, 0x98, 0x01, + 0x01, 0xa2, 0x01, 0x17, 0x12, 0x12, 0x4c, 0x45, 0x47, 0x41, 0x43, 0x59, 0x5f, 0x42, 0x45, 0x53, + 0x54, 0x5f, 0x45, 0x46, 0x46, 0x4f, 0x52, 0x54, 0x18, 0xe6, 0x07, 0xa2, 0x01, 0x0a, 0x12, 0x05, + 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x18, 0xe7, 0x07, 0xb2, 0x01, 0x03, 0x08, 0xe8, 0x07, 0x52, 0x0a, + 0x6a, 0x73, 0x6f, 0x6e, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x22, 0x5c, 0x0a, 0x0d, 0x46, 0x69, + 0x65, 0x6c, 0x64, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x1a, 0x0a, 0x16, 0x46, + 0x49, 0x45, 0x4c, 0x44, 0x5f, 0x50, 0x52, 0x45, 0x53, 0x45, 0x4e, 0x43, 0x45, 0x5f, 0x55, 0x4e, + 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x45, 0x58, 0x50, 0x4c, 0x49, + 0x43, 0x49, 0x54, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x49, 0x4d, 0x50, 0x4c, 0x49, 0x43, 0x49, + 0x54, 0x10, 0x02, 0x12, 0x13, 0x0a, 0x0f, 0x4c, 0x45, 0x47, 0x41, 0x43, 0x59, 0x5f, 0x52, 0x45, + 0x51, 0x55, 0x49, 0x52, 0x45, 0x44, 0x10, 0x03, 0x22, 0x37, 0x0a, 0x08, 0x45, 0x6e, 0x75, 0x6d, + 0x54, 0x79, 0x70, 0x65, 0x12, 0x15, 0x0a, 0x11, 0x45, 0x4e, 0x55, 0x4d, 0x5f, 0x54, 0x59, 0x50, + 0x45, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x4f, + 0x50, 0x45, 0x4e, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x43, 0x4c, 0x4f, 0x53, 0x45, 0x44, 0x10, + 0x02, 0x22, 0x56, 0x0a, 0x15, 0x52, 0x65, 0x70, 0x65, 0x61, 0x74, 0x65, 0x64, 0x46, 0x69, 0x65, + 0x6c, 0x64, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x23, 0x0a, 0x1f, 0x52, 0x45, + 0x50, 0x45, 0x41, 0x54, 0x45, 0x44, 0x5f, 0x46, 0x49, 0x45, 0x4c, 0x44, 0x5f, 0x45, 0x4e, 0x43, + 0x4f, 0x44, 0x49, 0x4e, 0x47, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, + 0x0a, 0x0a, 0x06, 0x50, 0x41, 0x43, 0x4b, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x45, + 0x58, 0x50, 0x41, 0x4e, 0x44, 0x45, 0x44, 0x10, 0x02, 0x22, 0x49, 0x0a, 0x0e, 0x55, 0x74, 0x66, + 0x38, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1b, 0x0a, 0x17, 0x55, + 0x54, 0x46, 0x38, 0x5f, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, + 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x56, 0x45, 0x52, 0x49, + 0x46, 0x59, 0x10, 0x02, 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x4f, 0x4e, 0x45, 0x10, 0x03, 0x22, 0x04, + 0x08, 0x01, 0x10, 0x01, 0x22, 0x53, 0x0a, 0x0f, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x45, + 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x1c, 0x0a, 0x18, 0x4d, 0x45, 0x53, 0x53, 0x41, + 0x47, 0x45, 0x5f, 0x45, 0x4e, 0x43, 0x4f, 0x44, 0x49, 0x4e, 0x47, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, + 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x13, 0x0a, 0x0f, 0x4c, 0x45, 0x4e, 0x47, 0x54, 0x48, 0x5f, + 0x50, 0x52, 0x45, 0x46, 0x49, 0x58, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x44, 0x45, + 0x4c, 0x49, 0x4d, 0x49, 0x54, 0x45, 0x44, 0x10, 0x02, 0x22, 0x48, 0x0a, 0x0a, 0x4a, 0x73, 0x6f, + 0x6e, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x17, 0x0a, 0x13, 0x4a, 0x53, 0x4f, 0x4e, 0x5f, + 0x46, 0x4f, 0x52, 0x4d, 0x41, 0x54, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, + 0x12, 0x09, 0x0a, 0x05, 0x41, 0x4c, 0x4c, 0x4f, 0x57, 0x10, 0x01, 0x12, 0x16, 0x0a, 0x12, 0x4c, + 0x45, 0x47, 0x41, 0x43, 0x59, 0x5f, 0x42, 0x45, 0x53, 0x54, 0x5f, 0x45, 0x46, 0x46, 0x4f, 0x52, + 0x54, 0x10, 0x02, 0x2a, 0x06, 0x08, 0xe8, 0x07, 0x10, 0x8b, 0x4e, 0x2a, 0x06, 0x08, 0x8b, 0x4e, + 0x10, 0x90, 0x4e, 0x2a, 0x06, 0x08, 0x90, 0x4e, 0x10, 0x91, 0x4e, 0x4a, 0x06, 0x08, 0xe7, 0x07, + 0x10, 0xe8, 0x07, 0x22, 0xef, 0x03, 0x0a, 0x12, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, + 0x65, 0x74, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x58, 0x0a, 0x08, 0x64, 0x65, + 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, + 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, + 0x73, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x45, 0x64, 0x69, 0x74, + 0x69, 0x6f, 0x6e, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x52, 0x08, 0x64, 0x65, 0x66, 0x61, + 0x75, 0x6c, 0x74, 0x73, 0x12, 0x41, 0x0a, 0x0f, 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x5f, + 0x65, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, - 0x6f, 0x2e, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x53, 0x65, 0x6d, - 0x61, 0x6e, 0x74, 0x69, 0x63, 0x52, 0x08, 0x73, 0x65, 0x6d, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x22, - 0x28, 0x0a, 0x08, 0x53, 0x65, 0x6d, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x12, 0x08, 0x0a, 0x04, 0x4e, - 0x4f, 0x4e, 0x45, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x53, 0x45, 0x54, 0x10, 0x01, 0x12, 0x09, - 0x0a, 0x05, 0x41, 0x4c, 0x49, 0x41, 0x53, 0x10, 0x02, 0x2a, 0x92, 0x02, 0x0a, 0x07, 0x45, 0x64, - 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x13, 0x0a, 0x0f, 0x45, 0x44, 0x49, 0x54, 0x49, 0x4f, 0x4e, - 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x13, 0x0a, 0x0e, 0x45, 0x44, - 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x32, 0x10, 0xe6, 0x07, 0x12, - 0x13, 0x0a, 0x0e, 0x45, 0x44, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x50, 0x52, 0x4f, 0x54, 0x4f, - 0x33, 0x10, 0xe7, 0x07, 0x12, 0x11, 0x0a, 0x0c, 0x45, 0x44, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, - 0x32, 0x30, 0x32, 0x33, 0x10, 0xe8, 0x07, 0x12, 0x11, 0x0a, 0x0c, 0x45, 0x44, 0x49, 0x54, 0x49, - 0x4f, 0x4e, 0x5f, 0x32, 0x30, 0x32, 0x34, 0x10, 0xe9, 0x07, 0x12, 0x17, 0x0a, 0x13, 0x45, 0x44, - 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x31, 0x5f, 0x54, 0x45, 0x53, 0x54, 0x5f, 0x4f, 0x4e, 0x4c, - 0x59, 0x10, 0x01, 0x12, 0x17, 0x0a, 0x13, 0x45, 0x44, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x32, - 0x5f, 0x54, 0x45, 0x53, 0x54, 0x5f, 0x4f, 0x4e, 0x4c, 0x59, 0x10, 0x02, 0x12, 0x1d, 0x0a, 0x17, - 0x45, 0x44, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x39, 0x39, 0x39, 0x39, 0x37, 0x5f, 0x54, 0x45, - 0x53, 0x54, 0x5f, 0x4f, 0x4e, 0x4c, 0x59, 0x10, 0x9d, 0x8d, 0x06, 0x12, 0x1d, 0x0a, 0x17, 0x45, - 0x44, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x39, 0x39, 0x39, 0x39, 0x38, 0x5f, 0x54, 0x45, 0x53, - 0x54, 0x5f, 0x4f, 0x4e, 0x4c, 0x59, 0x10, 0x9e, 0x8d, 0x06, 0x12, 0x1d, 0x0a, 0x17, 0x45, 0x44, - 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x39, 0x39, 0x39, 0x39, 0x39, 0x5f, 0x54, 0x45, 0x53, 0x54, - 0x5f, 0x4f, 0x4e, 0x4c, 0x59, 0x10, 0x9f, 0x8d, 0x06, 0x12, 0x13, 0x0a, 0x0b, 0x45, 0x44, 0x49, - 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4d, 0x41, 0x58, 0x10, 0xff, 0xff, 0xff, 0xff, 0x07, 0x42, 0x7e, - 0x0a, 0x13, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x42, 0x10, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, - 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x48, 0x01, 0x5a, 0x2d, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x64, 0x65, 0x73, 0x63, - 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x70, 0x62, 0xf8, 0x01, 0x01, 0xa2, 0x02, 0x03, 0x47, 0x50, - 0x42, 0xaa, 0x02, 0x1a, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x52, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x45, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, + 0x45, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x41, 0x0a, 0x0f, 0x6d, 0x61, 0x78, 0x69, 0x6d, + 0x75, 0x6d, 0x5f, 0x65, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, + 0x32, 0x18, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x45, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x6d, 0x61, 0x78, 0x69, + 0x6d, 0x75, 0x6d, 0x45, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0xf8, 0x01, 0x0a, 0x18, 0x46, + 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x45, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, + 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x12, 0x32, 0x0a, 0x07, 0x65, 0x64, 0x69, 0x74, 0x69, + 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x64, 0x69, 0x74, 0x69, + 0x6f, 0x6e, 0x52, 0x07, 0x65, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x4e, 0x0a, 0x14, 0x6f, + 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x66, 0x65, 0x61, 0x74, 0x75, + 0x72, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x65, 0x61, 0x74, + 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x52, 0x13, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x61, + 0x62, 0x6c, 0x65, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x42, 0x0a, 0x0e, 0x66, + 0x69, 0x78, 0x65, 0x64, 0x5f, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, + 0x52, 0x0d, 0x66, 0x69, 0x78, 0x65, 0x64, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x4a, + 0x04, 0x08, 0x01, 0x10, 0x02, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x52, 0x08, 0x66, 0x65, 0x61, + 0x74, 0x75, 0x72, 0x65, 0x73, 0x22, 0xa7, 0x02, 0x0a, 0x0e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x44, 0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x4c, 0x6f, 0x63, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0xce, + 0x01, 0x0a, 0x08, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x04, 0x70, + 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x03, 0x28, 0x05, 0x42, 0x02, 0x10, 0x01, 0x52, 0x04, 0x70, + 0x61, 0x74, 0x68, 0x12, 0x16, 0x0a, 0x04, 0x73, 0x70, 0x61, 0x6e, 0x18, 0x02, 0x20, 0x03, 0x28, + 0x05, 0x42, 0x02, 0x10, 0x01, 0x52, 0x04, 0x73, 0x70, 0x61, 0x6e, 0x12, 0x29, 0x0a, 0x10, 0x6c, + 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x6c, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x43, 0x6f, + 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x74, 0x72, 0x61, 0x69, 0x6c, 0x69, + 0x6e, 0x67, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x10, 0x74, 0x72, 0x61, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6d, 0x6d, 0x65, + 0x6e, 0x74, 0x73, 0x12, 0x3a, 0x0a, 0x19, 0x6c, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x64, + 0x65, 0x74, 0x61, 0x63, 0x68, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, + 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x17, 0x6c, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x44, + 0x65, 0x74, 0x61, 0x63, 0x68, 0x65, 0x64, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, + 0xd0, 0x02, 0x0a, 0x11, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x64, + 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x4d, 0x0a, 0x0a, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x47, 0x65, 0x6e, 0x65, + 0x72, 0x61, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x41, 0x6e, + 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0xeb, 0x01, 0x0a, 0x0a, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x03, 0x28, + 0x05, 0x42, 0x02, 0x10, 0x01, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x1f, 0x0a, 0x0b, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0a, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x14, 0x0a, 0x05, + 0x62, 0x65, 0x67, 0x69, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x62, 0x65, 0x67, + 0x69, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, + 0x03, 0x65, 0x6e, 0x64, 0x12, 0x52, 0x0a, 0x08, 0x73, 0x65, 0x6d, 0x61, 0x6e, 0x74, 0x69, 0x63, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x36, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, + 0x65, 0x64, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x41, 0x6e, 0x6e, 0x6f, 0x74, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x53, 0x65, 0x6d, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x52, 0x08, + 0x73, 0x65, 0x6d, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x22, 0x28, 0x0a, 0x08, 0x53, 0x65, 0x6d, 0x61, + 0x6e, 0x74, 0x69, 0x63, 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x4f, 0x4e, 0x45, 0x10, 0x00, 0x12, 0x07, + 0x0a, 0x03, 0x53, 0x45, 0x54, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x41, 0x4c, 0x49, 0x41, 0x53, + 0x10, 0x02, 0x2a, 0xa7, 0x02, 0x0a, 0x07, 0x45, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x13, + 0x0a, 0x0f, 0x45, 0x44, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, + 0x4e, 0x10, 0x00, 0x12, 0x13, 0x0a, 0x0e, 0x45, 0x44, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4c, + 0x45, 0x47, 0x41, 0x43, 0x59, 0x10, 0x84, 0x07, 0x12, 0x13, 0x0a, 0x0e, 0x45, 0x44, 0x49, 0x54, + 0x49, 0x4f, 0x4e, 0x5f, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x32, 0x10, 0xe6, 0x07, 0x12, 0x13, 0x0a, + 0x0e, 0x45, 0x44, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x33, 0x10, + 0xe7, 0x07, 0x12, 0x11, 0x0a, 0x0c, 0x45, 0x44, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x32, 0x30, + 0x32, 0x33, 0x10, 0xe8, 0x07, 0x12, 0x11, 0x0a, 0x0c, 0x45, 0x44, 0x49, 0x54, 0x49, 0x4f, 0x4e, + 0x5f, 0x32, 0x30, 0x32, 0x34, 0x10, 0xe9, 0x07, 0x12, 0x17, 0x0a, 0x13, 0x45, 0x44, 0x49, 0x54, + 0x49, 0x4f, 0x4e, 0x5f, 0x31, 0x5f, 0x54, 0x45, 0x53, 0x54, 0x5f, 0x4f, 0x4e, 0x4c, 0x59, 0x10, + 0x01, 0x12, 0x17, 0x0a, 0x13, 0x45, 0x44, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x32, 0x5f, 0x54, + 0x45, 0x53, 0x54, 0x5f, 0x4f, 0x4e, 0x4c, 0x59, 0x10, 0x02, 0x12, 0x1d, 0x0a, 0x17, 0x45, 0x44, + 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x39, 0x39, 0x39, 0x39, 0x37, 0x5f, 0x54, 0x45, 0x53, 0x54, + 0x5f, 0x4f, 0x4e, 0x4c, 0x59, 0x10, 0x9d, 0x8d, 0x06, 0x12, 0x1d, 0x0a, 0x17, 0x45, 0x44, 0x49, + 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x39, 0x39, 0x39, 0x39, 0x38, 0x5f, 0x54, 0x45, 0x53, 0x54, 0x5f, + 0x4f, 0x4e, 0x4c, 0x59, 0x10, 0x9e, 0x8d, 0x06, 0x12, 0x1d, 0x0a, 0x17, 0x45, 0x44, 0x49, 0x54, + 0x49, 0x4f, 0x4e, 0x5f, 0x39, 0x39, 0x39, 0x39, 0x39, 0x5f, 0x54, 0x45, 0x53, 0x54, 0x5f, 0x4f, + 0x4e, 0x4c, 0x59, 0x10, 0x9f, 0x8d, 0x06, 0x12, 0x13, 0x0a, 0x0b, 0x45, 0x44, 0x49, 0x54, 0x49, + 0x4f, 0x4e, 0x5f, 0x4d, 0x41, 0x58, 0x10, 0xff, 0xff, 0xff, 0xff, 0x07, 0x42, 0x7e, 0x0a, 0x13, + 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x42, 0x10, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, + 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x48, 0x01, 0x5a, 0x2d, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, + 0x70, 0x74, 0x6f, 0x72, 0x70, 0x62, 0xf8, 0x01, 0x01, 0xa2, 0x02, 0x03, 0x47, 0x50, 0x42, 0xaa, + 0x02, 0x1a, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x52, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, } var ( @@ -5084,8 +5176,8 @@ func file_google_protobuf_descriptor_proto_rawDescGZIP() []byte { } var file_google_protobuf_descriptor_proto_enumTypes = make([]protoimpl.EnumInfo, 17) -var file_google_protobuf_descriptor_proto_msgTypes = make([]protoimpl.MessageInfo, 32) -var file_google_protobuf_descriptor_proto_goTypes = []interface{}{ +var file_google_protobuf_descriptor_proto_msgTypes = make([]protoimpl.MessageInfo, 33) +var file_google_protobuf_descriptor_proto_goTypes = []any{ (Edition)(0), // 0: google.protobuf.Edition (ExtensionRangeOptions_VerificationState)(0), // 1: google.protobuf.ExtensionRangeOptions.VerificationState (FieldDescriptorProto_Type)(0), // 2: google.protobuf.FieldDescriptorProto.Type @@ -5131,10 +5223,11 @@ var file_google_protobuf_descriptor_proto_goTypes = []interface{}{ (*ExtensionRangeOptions_Declaration)(nil), // 42: google.protobuf.ExtensionRangeOptions.Declaration (*EnumDescriptorProto_EnumReservedRange)(nil), // 43: google.protobuf.EnumDescriptorProto.EnumReservedRange (*FieldOptions_EditionDefault)(nil), // 44: google.protobuf.FieldOptions.EditionDefault - (*UninterpretedOption_NamePart)(nil), // 45: google.protobuf.UninterpretedOption.NamePart - (*FeatureSetDefaults_FeatureSetEditionDefault)(nil), // 46: google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault - (*SourceCodeInfo_Location)(nil), // 47: google.protobuf.SourceCodeInfo.Location - (*GeneratedCodeInfo_Annotation)(nil), // 48: google.protobuf.GeneratedCodeInfo.Annotation + (*FieldOptions_FeatureSupport)(nil), // 45: google.protobuf.FieldOptions.FeatureSupport + (*UninterpretedOption_NamePart)(nil), // 46: google.protobuf.UninterpretedOption.NamePart + (*FeatureSetDefaults_FeatureSetEditionDefault)(nil), // 47: google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault + (*SourceCodeInfo_Location)(nil), // 48: google.protobuf.SourceCodeInfo.Location + (*GeneratedCodeInfo_Annotation)(nil), // 49: google.protobuf.GeneratedCodeInfo.Annotation } var file_google_protobuf_descriptor_proto_depIdxs = []int32{ 18, // 0: google.protobuf.FileDescriptorSet.file:type_name -> google.protobuf.FileDescriptorProto @@ -5179,40 +5272,46 @@ var file_google_protobuf_descriptor_proto_depIdxs = []int32{ 8, // 39: google.protobuf.FieldOptions.targets:type_name -> google.protobuf.FieldOptions.OptionTargetType 44, // 40: google.protobuf.FieldOptions.edition_defaults:type_name -> google.protobuf.FieldOptions.EditionDefault 36, // 41: google.protobuf.FieldOptions.features:type_name -> google.protobuf.FeatureSet - 35, // 42: google.protobuf.FieldOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption - 36, // 43: google.protobuf.OneofOptions.features:type_name -> google.protobuf.FeatureSet - 35, // 44: google.protobuf.OneofOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption - 36, // 45: google.protobuf.EnumOptions.features:type_name -> google.protobuf.FeatureSet - 35, // 46: google.protobuf.EnumOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption - 36, // 47: google.protobuf.EnumValueOptions.features:type_name -> google.protobuf.FeatureSet - 35, // 48: google.protobuf.EnumValueOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption - 36, // 49: google.protobuf.ServiceOptions.features:type_name -> google.protobuf.FeatureSet - 35, // 50: google.protobuf.ServiceOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption - 9, // 51: google.protobuf.MethodOptions.idempotency_level:type_name -> google.protobuf.MethodOptions.IdempotencyLevel - 36, // 52: google.protobuf.MethodOptions.features:type_name -> google.protobuf.FeatureSet - 35, // 53: google.protobuf.MethodOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption - 45, // 54: google.protobuf.UninterpretedOption.name:type_name -> google.protobuf.UninterpretedOption.NamePart - 10, // 55: google.protobuf.FeatureSet.field_presence:type_name -> google.protobuf.FeatureSet.FieldPresence - 11, // 56: google.protobuf.FeatureSet.enum_type:type_name -> google.protobuf.FeatureSet.EnumType - 12, // 57: google.protobuf.FeatureSet.repeated_field_encoding:type_name -> google.protobuf.FeatureSet.RepeatedFieldEncoding - 13, // 58: google.protobuf.FeatureSet.utf8_validation:type_name -> google.protobuf.FeatureSet.Utf8Validation - 14, // 59: google.protobuf.FeatureSet.message_encoding:type_name -> google.protobuf.FeatureSet.MessageEncoding - 15, // 60: google.protobuf.FeatureSet.json_format:type_name -> google.protobuf.FeatureSet.JsonFormat - 46, // 61: google.protobuf.FeatureSetDefaults.defaults:type_name -> google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault - 0, // 62: google.protobuf.FeatureSetDefaults.minimum_edition:type_name -> google.protobuf.Edition - 0, // 63: google.protobuf.FeatureSetDefaults.maximum_edition:type_name -> google.protobuf.Edition - 47, // 64: google.protobuf.SourceCodeInfo.location:type_name -> google.protobuf.SourceCodeInfo.Location - 48, // 65: google.protobuf.GeneratedCodeInfo.annotation:type_name -> google.protobuf.GeneratedCodeInfo.Annotation - 20, // 66: google.protobuf.DescriptorProto.ExtensionRange.options:type_name -> google.protobuf.ExtensionRangeOptions - 0, // 67: google.protobuf.FieldOptions.EditionDefault.edition:type_name -> google.protobuf.Edition - 0, // 68: google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault.edition:type_name -> google.protobuf.Edition - 36, // 69: google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault.features:type_name -> google.protobuf.FeatureSet - 16, // 70: google.protobuf.GeneratedCodeInfo.Annotation.semantic:type_name -> google.protobuf.GeneratedCodeInfo.Annotation.Semantic - 71, // [71:71] is the sub-list for method output_type - 71, // [71:71] is the sub-list for method input_type - 71, // [71:71] is the sub-list for extension type_name - 71, // [71:71] is the sub-list for extension extendee - 0, // [0:71] is the sub-list for field type_name + 45, // 42: google.protobuf.FieldOptions.feature_support:type_name -> google.protobuf.FieldOptions.FeatureSupport + 35, // 43: google.protobuf.FieldOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption + 36, // 44: google.protobuf.OneofOptions.features:type_name -> google.protobuf.FeatureSet + 35, // 45: google.protobuf.OneofOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption + 36, // 46: google.protobuf.EnumOptions.features:type_name -> google.protobuf.FeatureSet + 35, // 47: google.protobuf.EnumOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption + 36, // 48: google.protobuf.EnumValueOptions.features:type_name -> google.protobuf.FeatureSet + 45, // 49: google.protobuf.EnumValueOptions.feature_support:type_name -> google.protobuf.FieldOptions.FeatureSupport + 35, // 50: google.protobuf.EnumValueOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption + 36, // 51: google.protobuf.ServiceOptions.features:type_name -> google.protobuf.FeatureSet + 35, // 52: google.protobuf.ServiceOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption + 9, // 53: google.protobuf.MethodOptions.idempotency_level:type_name -> google.protobuf.MethodOptions.IdempotencyLevel + 36, // 54: google.protobuf.MethodOptions.features:type_name -> google.protobuf.FeatureSet + 35, // 55: google.protobuf.MethodOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption + 46, // 56: google.protobuf.UninterpretedOption.name:type_name -> google.protobuf.UninterpretedOption.NamePart + 10, // 57: google.protobuf.FeatureSet.field_presence:type_name -> google.protobuf.FeatureSet.FieldPresence + 11, // 58: google.protobuf.FeatureSet.enum_type:type_name -> google.protobuf.FeatureSet.EnumType + 12, // 59: google.protobuf.FeatureSet.repeated_field_encoding:type_name -> google.protobuf.FeatureSet.RepeatedFieldEncoding + 13, // 60: google.protobuf.FeatureSet.utf8_validation:type_name -> google.protobuf.FeatureSet.Utf8Validation + 14, // 61: google.protobuf.FeatureSet.message_encoding:type_name -> google.protobuf.FeatureSet.MessageEncoding + 15, // 62: google.protobuf.FeatureSet.json_format:type_name -> google.protobuf.FeatureSet.JsonFormat + 47, // 63: google.protobuf.FeatureSetDefaults.defaults:type_name -> google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault + 0, // 64: google.protobuf.FeatureSetDefaults.minimum_edition:type_name -> google.protobuf.Edition + 0, // 65: google.protobuf.FeatureSetDefaults.maximum_edition:type_name -> google.protobuf.Edition + 48, // 66: google.protobuf.SourceCodeInfo.location:type_name -> google.protobuf.SourceCodeInfo.Location + 49, // 67: google.protobuf.GeneratedCodeInfo.annotation:type_name -> google.protobuf.GeneratedCodeInfo.Annotation + 20, // 68: google.protobuf.DescriptorProto.ExtensionRange.options:type_name -> google.protobuf.ExtensionRangeOptions + 0, // 69: google.protobuf.FieldOptions.EditionDefault.edition:type_name -> google.protobuf.Edition + 0, // 70: google.protobuf.FieldOptions.FeatureSupport.edition_introduced:type_name -> google.protobuf.Edition + 0, // 71: google.protobuf.FieldOptions.FeatureSupport.edition_deprecated:type_name -> google.protobuf.Edition + 0, // 72: google.protobuf.FieldOptions.FeatureSupport.edition_removed:type_name -> google.protobuf.Edition + 0, // 73: google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault.edition:type_name -> google.protobuf.Edition + 36, // 74: google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault.overridable_features:type_name -> google.protobuf.FeatureSet + 36, // 75: google.protobuf.FeatureSetDefaults.FeatureSetEditionDefault.fixed_features:type_name -> google.protobuf.FeatureSet + 16, // 76: google.protobuf.GeneratedCodeInfo.Annotation.semantic:type_name -> google.protobuf.GeneratedCodeInfo.Annotation.Semantic + 77, // [77:77] is the sub-list for method output_type + 77, // [77:77] is the sub-list for method input_type + 77, // [77:77] is the sub-list for extension type_name + 77, // [77:77] is the sub-list for extension extendee + 0, // [0:77] is the sub-list for field type_name } func init() { file_google_protobuf_descriptor_proto_init() } @@ -5220,419 +5319,13 @@ func file_google_protobuf_descriptor_proto_init() { if File_google_protobuf_descriptor_proto != nil { return } - if !protoimpl.UnsafeEnabled { - file_google_protobuf_descriptor_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FileDescriptorSet); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_google_protobuf_descriptor_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FileDescriptorProto); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_google_protobuf_descriptor_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DescriptorProto); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_google_protobuf_descriptor_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ExtensionRangeOptions); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - case 3: - return &v.extensionFields - default: - return nil - } - } - file_google_protobuf_descriptor_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FieldDescriptorProto); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_google_protobuf_descriptor_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*OneofDescriptorProto); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_google_protobuf_descriptor_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EnumDescriptorProto); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_google_protobuf_descriptor_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EnumValueDescriptorProto); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_google_protobuf_descriptor_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ServiceDescriptorProto); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_google_protobuf_descriptor_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*MethodDescriptorProto); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_google_protobuf_descriptor_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FileOptions); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - case 3: - return &v.extensionFields - default: - return nil - } - } - file_google_protobuf_descriptor_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*MessageOptions); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - case 3: - return &v.extensionFields - default: - return nil - } - } - file_google_protobuf_descriptor_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FieldOptions); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - case 3: - return &v.extensionFields - default: - return nil - } - } - file_google_protobuf_descriptor_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*OneofOptions); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - case 3: - return &v.extensionFields - default: - return nil - } - } - file_google_protobuf_descriptor_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EnumOptions); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - case 3: - return &v.extensionFields - default: - return nil - } - } - file_google_protobuf_descriptor_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EnumValueOptions); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - case 3: - return &v.extensionFields - default: - return nil - } - } - file_google_protobuf_descriptor_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ServiceOptions); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - case 3: - return &v.extensionFields - default: - return nil - } - } - file_google_protobuf_descriptor_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*MethodOptions); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - case 3: - return &v.extensionFields - default: - return nil - } - } - file_google_protobuf_descriptor_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*UninterpretedOption); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_google_protobuf_descriptor_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FeatureSet); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - case 3: - return &v.extensionFields - default: - return nil - } - } - file_google_protobuf_descriptor_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FeatureSetDefaults); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_google_protobuf_descriptor_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SourceCodeInfo); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_google_protobuf_descriptor_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GeneratedCodeInfo); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_google_protobuf_descriptor_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DescriptorProto_ExtensionRange); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_google_protobuf_descriptor_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DescriptorProto_ReservedRange); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_google_protobuf_descriptor_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ExtensionRangeOptions_Declaration); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_google_protobuf_descriptor_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EnumDescriptorProto_EnumReservedRange); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_google_protobuf_descriptor_proto_msgTypes[27].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FieldOptions_EditionDefault); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_google_protobuf_descriptor_proto_msgTypes[28].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*UninterpretedOption_NamePart); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_google_protobuf_descriptor_proto_msgTypes[29].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FeatureSetDefaults_FeatureSetEditionDefault); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_google_protobuf_descriptor_proto_msgTypes[30].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SourceCodeInfo_Location); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_google_protobuf_descriptor_proto_msgTypes[31].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GeneratedCodeInfo_Annotation); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_google_protobuf_descriptor_proto_rawDesc, NumEnums: 17, - NumMessages: 32, + NumMessages: 33, NumExtensions: 0, NumServices: 0, }, diff --git a/vendor/google.golang.org/protobuf/types/gofeaturespb/go_features.pb.go b/vendor/google.golang.org/protobuf/types/gofeaturespb/go_features.pb.go index 25de5ae00..5067b89e9 100644 --- a/vendor/google.golang.org/protobuf/types/gofeaturespb/go_features.pb.go +++ b/vendor/google.golang.org/protobuf/types/gofeaturespb/go_features.pb.go @@ -6,9 +6,9 @@ // https://developers.google.com/open-source/licenses/bsd // Code generated by protoc-gen-go. DO NOT EDIT. -// source: reflect/protodesc/proto/go_features.proto +// source: google/protobuf/go_features.proto -package proto +package gofeaturespb import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" @@ -18,22 +18,83 @@ import ( sync "sync" ) +type GoFeatures_StripEnumPrefix int32 + +const ( + GoFeatures_STRIP_ENUM_PREFIX_UNSPECIFIED GoFeatures_StripEnumPrefix = 0 + GoFeatures_STRIP_ENUM_PREFIX_KEEP GoFeatures_StripEnumPrefix = 1 + GoFeatures_STRIP_ENUM_PREFIX_GENERATE_BOTH GoFeatures_StripEnumPrefix = 2 + GoFeatures_STRIP_ENUM_PREFIX_STRIP GoFeatures_StripEnumPrefix = 3 +) + +// Enum value maps for GoFeatures_StripEnumPrefix. +var ( + GoFeatures_StripEnumPrefix_name = map[int32]string{ + 0: "STRIP_ENUM_PREFIX_UNSPECIFIED", + 1: "STRIP_ENUM_PREFIX_KEEP", + 2: "STRIP_ENUM_PREFIX_GENERATE_BOTH", + 3: "STRIP_ENUM_PREFIX_STRIP", + } + GoFeatures_StripEnumPrefix_value = map[string]int32{ + "STRIP_ENUM_PREFIX_UNSPECIFIED": 0, + "STRIP_ENUM_PREFIX_KEEP": 1, + "STRIP_ENUM_PREFIX_GENERATE_BOTH": 2, + "STRIP_ENUM_PREFIX_STRIP": 3, + } +) + +func (x GoFeatures_StripEnumPrefix) Enum() *GoFeatures_StripEnumPrefix { + p := new(GoFeatures_StripEnumPrefix) + *p = x + return p +} + +func (x GoFeatures_StripEnumPrefix) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (GoFeatures_StripEnumPrefix) Descriptor() protoreflect.EnumDescriptor { + return file_google_protobuf_go_features_proto_enumTypes[0].Descriptor() +} + +func (GoFeatures_StripEnumPrefix) Type() protoreflect.EnumType { + return &file_google_protobuf_go_features_proto_enumTypes[0] +} + +func (x GoFeatures_StripEnumPrefix) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Do not use. +func (x *GoFeatures_StripEnumPrefix) UnmarshalJSON(b []byte) error { + num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b) + if err != nil { + return err + } + *x = GoFeatures_StripEnumPrefix(num) + return nil +} + +// Deprecated: Use GoFeatures_StripEnumPrefix.Descriptor instead. +func (GoFeatures_StripEnumPrefix) EnumDescriptor() ([]byte, []int) { + return file_google_protobuf_go_features_proto_rawDescGZIP(), []int{0, 0} +} + type GoFeatures struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Whether or not to generate the deprecated UnmarshalJSON method for enums. - LegacyUnmarshalJsonEnum *bool `protobuf:"varint,1,opt,name=legacy_unmarshal_json_enum,json=legacyUnmarshalJsonEnum" json:"legacy_unmarshal_json_enum,omitempty"` + LegacyUnmarshalJsonEnum *bool `protobuf:"varint,1,opt,name=legacy_unmarshal_json_enum,json=legacyUnmarshalJsonEnum" json:"legacy_unmarshal_json_enum,omitempty"` + StripEnumPrefix *GoFeatures_StripEnumPrefix `protobuf:"varint,3,opt,name=strip_enum_prefix,json=stripEnumPrefix,enum=pb.GoFeatures_StripEnumPrefix" json:"strip_enum_prefix,omitempty"` } func (x *GoFeatures) Reset() { *x = GoFeatures{} - if protoimpl.UnsafeEnabled { - mi := &file_reflect_protodesc_proto_go_features_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_google_protobuf_go_features_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *GoFeatures) String() string { @@ -43,8 +104,8 @@ func (x *GoFeatures) String() string { func (*GoFeatures) ProtoMessage() {} func (x *GoFeatures) ProtoReflect() protoreflect.Message { - mi := &file_reflect_protodesc_proto_go_features_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { + mi := &file_google_protobuf_go_features_proto_msgTypes[0] + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -56,7 +117,7 @@ func (x *GoFeatures) ProtoReflect() protoreflect.Message { // Deprecated: Use GoFeatures.ProtoReflect.Descriptor instead. func (*GoFeatures) Descriptor() ([]byte, []int) { - return file_reflect_protodesc_proto_go_features_proto_rawDescGZIP(), []int{0} + return file_google_protobuf_go_features_proto_rawDescGZIP(), []int{0} } func (x *GoFeatures) GetLegacyUnmarshalJsonEnum() bool { @@ -66,112 +127,130 @@ func (x *GoFeatures) GetLegacyUnmarshalJsonEnum() bool { return false } -var file_reflect_protodesc_proto_go_features_proto_extTypes = []protoimpl.ExtensionInfo{ +func (x *GoFeatures) GetStripEnumPrefix() GoFeatures_StripEnumPrefix { + if x != nil && x.StripEnumPrefix != nil { + return *x.StripEnumPrefix + } + return GoFeatures_STRIP_ENUM_PREFIX_UNSPECIFIED +} + +var file_google_protobuf_go_features_proto_extTypes = []protoimpl.ExtensionInfo{ { ExtendedType: (*descriptorpb.FeatureSet)(nil), ExtensionType: (*GoFeatures)(nil), Field: 1002, - Name: "google.protobuf.go", + Name: "pb.go", Tag: "bytes,1002,opt,name=go", - Filename: "reflect/protodesc/proto/go_features.proto", + Filename: "google/protobuf/go_features.proto", }, } // Extension fields to descriptorpb.FeatureSet. var ( - // optional google.protobuf.GoFeatures go = 1002; - E_Go = &file_reflect_protodesc_proto_go_features_proto_extTypes[0] + // optional pb.GoFeatures go = 1002; + E_Go = &file_google_protobuf_go_features_proto_extTypes[0] ) -var File_reflect_protodesc_proto_go_features_proto protoreflect.FileDescriptor - -var file_reflect_protodesc_proto_go_features_proto_rawDesc = []byte{ - 0x0a, 0x29, 0x72, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x64, - 0x65, 0x73, 0x63, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x5f, 0x66, 0x65, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x1a, 0x20, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x65, - 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x6a, - 0x0a, 0x0a, 0x47, 0x6f, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x5c, 0x0a, 0x1a, - 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x5f, 0x75, 0x6e, 0x6d, 0x61, 0x72, 0x73, 0x68, 0x61, 0x6c, - 0x5f, 0x6a, 0x73, 0x6f, 0x6e, 0x5f, 0x65, 0x6e, 0x75, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, - 0x42, 0x1f, 0x88, 0x01, 0x01, 0x98, 0x01, 0x06, 0xa2, 0x01, 0x09, 0x12, 0x04, 0x74, 0x72, 0x75, - 0x65, 0x18, 0xe6, 0x07, 0xa2, 0x01, 0x0a, 0x12, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x18, 0xe7, - 0x07, 0x52, 0x17, 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x55, 0x6e, 0x6d, 0x61, 0x72, 0x73, 0x68, - 0x61, 0x6c, 0x4a, 0x73, 0x6f, 0x6e, 0x45, 0x6e, 0x75, 0x6d, 0x3a, 0x49, 0x0a, 0x02, 0x67, 0x6f, - 0x12, 0x1b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x18, 0xea, 0x07, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x47, 0x6f, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x73, 0x52, 0x02, 0x67, 0x6f, 0x42, 0x34, 0x5a, 0x32, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2f, 0x72, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x2f, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x64, 0x65, 0x73, 0x63, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, +var File_google_protobuf_go_features_proto protoreflect.FileDescriptor + +var file_google_protobuf_go_features_proto_rawDesc = []byte{ + 0x0a, 0x21, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2f, 0x67, 0x6f, 0x5f, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x12, 0x02, 0x70, 0x62, 0x1a, 0x20, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, + 0x74, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xe0, 0x03, 0x0a, 0x0a, 0x47, 0x6f, + 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0xbe, 0x01, 0x0a, 0x1a, 0x6c, 0x65, 0x67, + 0x61, 0x63, 0x79, 0x5f, 0x75, 0x6e, 0x6d, 0x61, 0x72, 0x73, 0x68, 0x61, 0x6c, 0x5f, 0x6a, 0x73, + 0x6f, 0x6e, 0x5f, 0x65, 0x6e, 0x75, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x42, 0x80, 0x01, + 0x88, 0x01, 0x01, 0x98, 0x01, 0x06, 0x98, 0x01, 0x01, 0xa2, 0x01, 0x09, 0x12, 0x04, 0x74, 0x72, + 0x75, 0x65, 0x18, 0x84, 0x07, 0xa2, 0x01, 0x0a, 0x12, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x18, + 0xe7, 0x07, 0xb2, 0x01, 0x5b, 0x08, 0xe8, 0x07, 0x10, 0xe8, 0x07, 0x1a, 0x53, 0x54, 0x68, 0x65, + 0x20, 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x20, 0x55, 0x6e, 0x6d, 0x61, 0x72, 0x73, 0x68, 0x61, + 0x6c, 0x4a, 0x53, 0x4f, 0x4e, 0x20, 0x41, 0x50, 0x49, 0x20, 0x69, 0x73, 0x20, 0x64, 0x65, 0x70, + 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x69, 0x6c, 0x6c, + 0x20, 0x62, 0x65, 0x20, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x61, + 0x20, 0x66, 0x75, 0x74, 0x75, 0x72, 0x65, 0x20, 0x65, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x2e, + 0x52, 0x17, 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x55, 0x6e, 0x6d, 0x61, 0x72, 0x73, 0x68, 0x61, + 0x6c, 0x4a, 0x73, 0x6f, 0x6e, 0x45, 0x6e, 0x75, 0x6d, 0x12, 0x7c, 0x0a, 0x11, 0x73, 0x74, 0x72, + 0x69, 0x70, 0x5f, 0x65, 0x6e, 0x75, 0x6d, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1e, 0x2e, 0x70, 0x62, 0x2e, 0x47, 0x6f, 0x46, 0x65, 0x61, 0x74, + 0x75, 0x72, 0x65, 0x73, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x70, 0x45, 0x6e, 0x75, 0x6d, 0x50, 0x72, + 0x65, 0x66, 0x69, 0x78, 0x42, 0x30, 0x88, 0x01, 0x01, 0x98, 0x01, 0x06, 0x98, 0x01, 0x07, 0x98, + 0x01, 0x01, 0xa2, 0x01, 0x1b, 0x12, 0x16, 0x53, 0x54, 0x52, 0x49, 0x50, 0x5f, 0x45, 0x4e, 0x55, + 0x4d, 0x5f, 0x50, 0x52, 0x45, 0x46, 0x49, 0x58, 0x5f, 0x4b, 0x45, 0x45, 0x50, 0x18, 0x84, 0x07, + 0xb2, 0x01, 0x03, 0x08, 0xe9, 0x07, 0x52, 0x0f, 0x73, 0x74, 0x72, 0x69, 0x70, 0x45, 0x6e, 0x75, + 0x6d, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x22, 0x92, 0x01, 0x0a, 0x0f, 0x53, 0x74, 0x72, 0x69, + 0x70, 0x45, 0x6e, 0x75, 0x6d, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x21, 0x0a, 0x1d, 0x53, + 0x54, 0x52, 0x49, 0x50, 0x5f, 0x45, 0x4e, 0x55, 0x4d, 0x5f, 0x50, 0x52, 0x45, 0x46, 0x49, 0x58, + 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1a, + 0x0a, 0x16, 0x53, 0x54, 0x52, 0x49, 0x50, 0x5f, 0x45, 0x4e, 0x55, 0x4d, 0x5f, 0x50, 0x52, 0x45, + 0x46, 0x49, 0x58, 0x5f, 0x4b, 0x45, 0x45, 0x50, 0x10, 0x01, 0x12, 0x23, 0x0a, 0x1f, 0x53, 0x54, + 0x52, 0x49, 0x50, 0x5f, 0x45, 0x4e, 0x55, 0x4d, 0x5f, 0x50, 0x52, 0x45, 0x46, 0x49, 0x58, 0x5f, + 0x47, 0x45, 0x4e, 0x45, 0x52, 0x41, 0x54, 0x45, 0x5f, 0x42, 0x4f, 0x54, 0x48, 0x10, 0x02, 0x12, + 0x1b, 0x0a, 0x17, 0x53, 0x54, 0x52, 0x49, 0x50, 0x5f, 0x45, 0x4e, 0x55, 0x4d, 0x5f, 0x50, 0x52, + 0x45, 0x46, 0x49, 0x58, 0x5f, 0x53, 0x54, 0x52, 0x49, 0x50, 0x10, 0x03, 0x3a, 0x3c, 0x0a, 0x02, + 0x67, 0x6f, 0x12, 0x1b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x53, 0x65, 0x74, 0x18, + 0xea, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x62, 0x2e, 0x47, 0x6f, 0x46, 0x65, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x02, 0x67, 0x6f, 0x42, 0x2f, 0x5a, 0x2d, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2e, 0x6f, 0x72, 0x67, 0x2f, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x67, + 0x6f, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x70, 0x62, } var ( - file_reflect_protodesc_proto_go_features_proto_rawDescOnce sync.Once - file_reflect_protodesc_proto_go_features_proto_rawDescData = file_reflect_protodesc_proto_go_features_proto_rawDesc + file_google_protobuf_go_features_proto_rawDescOnce sync.Once + file_google_protobuf_go_features_proto_rawDescData = file_google_protobuf_go_features_proto_rawDesc ) -func file_reflect_protodesc_proto_go_features_proto_rawDescGZIP() []byte { - file_reflect_protodesc_proto_go_features_proto_rawDescOnce.Do(func() { - file_reflect_protodesc_proto_go_features_proto_rawDescData = protoimpl.X.CompressGZIP(file_reflect_protodesc_proto_go_features_proto_rawDescData) +func file_google_protobuf_go_features_proto_rawDescGZIP() []byte { + file_google_protobuf_go_features_proto_rawDescOnce.Do(func() { + file_google_protobuf_go_features_proto_rawDescData = protoimpl.X.CompressGZIP(file_google_protobuf_go_features_proto_rawDescData) }) - return file_reflect_protodesc_proto_go_features_proto_rawDescData + return file_google_protobuf_go_features_proto_rawDescData } -var file_reflect_protodesc_proto_go_features_proto_msgTypes = make([]protoimpl.MessageInfo, 1) -var file_reflect_protodesc_proto_go_features_proto_goTypes = []interface{}{ - (*GoFeatures)(nil), // 0: google.protobuf.GoFeatures - (*descriptorpb.FeatureSet)(nil), // 1: google.protobuf.FeatureSet +var file_google_protobuf_go_features_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_google_protobuf_go_features_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_google_protobuf_go_features_proto_goTypes = []any{ + (GoFeatures_StripEnumPrefix)(0), // 0: pb.GoFeatures.StripEnumPrefix + (*GoFeatures)(nil), // 1: pb.GoFeatures + (*descriptorpb.FeatureSet)(nil), // 2: google.protobuf.FeatureSet } -var file_reflect_protodesc_proto_go_features_proto_depIdxs = []int32{ - 1, // 0: google.protobuf.go:extendee -> google.protobuf.FeatureSet - 0, // 1: google.protobuf.go:type_name -> google.protobuf.GoFeatures - 2, // [2:2] is the sub-list for method output_type - 2, // [2:2] is the sub-list for method input_type - 1, // [1:2] is the sub-list for extension type_name - 0, // [0:1] is the sub-list for extension extendee - 0, // [0:0] is the sub-list for field type_name +var file_google_protobuf_go_features_proto_depIdxs = []int32{ + 0, // 0: pb.GoFeatures.strip_enum_prefix:type_name -> pb.GoFeatures.StripEnumPrefix + 2, // 1: pb.go:extendee -> google.protobuf.FeatureSet + 1, // 2: pb.go:type_name -> pb.GoFeatures + 3, // [3:3] is the sub-list for method output_type + 3, // [3:3] is the sub-list for method input_type + 2, // [2:3] is the sub-list for extension type_name + 1, // [1:2] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name } -func init() { file_reflect_protodesc_proto_go_features_proto_init() } -func file_reflect_protodesc_proto_go_features_proto_init() { - if File_reflect_protodesc_proto_go_features_proto != nil { +func init() { file_google_protobuf_go_features_proto_init() } +func file_google_protobuf_go_features_proto_init() { + if File_google_protobuf_go_features_proto != nil { return } - if !protoimpl.UnsafeEnabled { - file_reflect_protodesc_proto_go_features_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GoFeatures); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_reflect_protodesc_proto_go_features_proto_rawDesc, - NumEnums: 0, + RawDescriptor: file_google_protobuf_go_features_proto_rawDesc, + NumEnums: 1, NumMessages: 1, NumExtensions: 1, NumServices: 0, }, - GoTypes: file_reflect_protodesc_proto_go_features_proto_goTypes, - DependencyIndexes: file_reflect_protodesc_proto_go_features_proto_depIdxs, - MessageInfos: file_reflect_protodesc_proto_go_features_proto_msgTypes, - ExtensionInfos: file_reflect_protodesc_proto_go_features_proto_extTypes, + GoTypes: file_google_protobuf_go_features_proto_goTypes, + DependencyIndexes: file_google_protobuf_go_features_proto_depIdxs, + EnumInfos: file_google_protobuf_go_features_proto_enumTypes, + MessageInfos: file_google_protobuf_go_features_proto_msgTypes, + ExtensionInfos: file_google_protobuf_go_features_proto_extTypes, }.Build() - File_reflect_protodesc_proto_go_features_proto = out.File - file_reflect_protodesc_proto_go_features_proto_rawDesc = nil - file_reflect_protodesc_proto_go_features_proto_goTypes = nil - file_reflect_protodesc_proto_go_features_proto_depIdxs = nil + File_google_protobuf_go_features_proto = out.File + file_google_protobuf_go_features_proto_rawDesc = nil + file_google_protobuf_go_features_proto_goTypes = nil + file_google_protobuf_go_features_proto_depIdxs = nil } diff --git a/vendor/google.golang.org/protobuf/types/gofeaturespb/go_features.proto b/vendor/google.golang.org/protobuf/types/gofeaturespb/go_features.proto deleted file mode 100644 index d24657129..000000000 --- a/vendor/google.golang.org/protobuf/types/gofeaturespb/go_features.proto +++ /dev/null @@ -1,28 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2023 Google Inc. All rights reserved. -// -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file or at -// https://developers.google.com/open-source/licenses/bsd - -syntax = "proto2"; - -package google.protobuf; - -import "google/protobuf/descriptor.proto"; - -option go_package = "google.golang.org/protobuf/types/gofeaturespb"; - -extend google.protobuf.FeatureSet { - optional GoFeatures go = 1002; -} - -message GoFeatures { - // Whether or not to generate the deprecated UnmarshalJSON method for enums. - optional bool legacy_unmarshal_json_enum = 1 [ - retention = RETENTION_RUNTIME, - targets = TARGET_TYPE_ENUM, - edition_defaults = { edition: EDITION_PROTO2, value: "true" }, - edition_defaults = { edition: EDITION_PROTO3, value: "false" } - ]; -} diff --git a/vendor/google.golang.org/protobuf/types/known/anypb/any.pb.go b/vendor/google.golang.org/protobuf/types/known/anypb/any.pb.go index 9de51be54..87da199a3 100644 --- a/vendor/google.golang.org/protobuf/types/known/anypb/any.pb.go +++ b/vendor/google.golang.org/protobuf/types/known/anypb/any.pb.go @@ -368,11 +368,9 @@ func (x *Any) UnmarshalNew() (proto.Message, error) { func (x *Any) Reset() { *x = Any{} - if protoimpl.UnsafeEnabled { - mi := &file_google_protobuf_any_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_google_protobuf_any_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *Any) String() string { @@ -383,7 +381,7 @@ func (*Any) ProtoMessage() {} func (x *Any) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_any_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -445,7 +443,7 @@ func file_google_protobuf_any_proto_rawDescGZIP() []byte { } var file_google_protobuf_any_proto_msgTypes = make([]protoimpl.MessageInfo, 1) -var file_google_protobuf_any_proto_goTypes = []interface{}{ +var file_google_protobuf_any_proto_goTypes = []any{ (*Any)(nil), // 0: google.protobuf.Any } var file_google_protobuf_any_proto_depIdxs = []int32{ @@ -461,20 +459,6 @@ func file_google_protobuf_any_proto_init() { if File_google_protobuf_any_proto != nil { return } - if !protoimpl.UnsafeEnabled { - file_google_protobuf_any_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Any); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ diff --git a/vendor/google.golang.org/protobuf/types/known/durationpb/duration.pb.go b/vendor/google.golang.org/protobuf/types/known/durationpb/duration.pb.go index df709a8dd..b99d4d241 100644 --- a/vendor/google.golang.org/protobuf/types/known/durationpb/duration.pb.go +++ b/vendor/google.golang.org/protobuf/types/known/durationpb/duration.pb.go @@ -245,11 +245,9 @@ func (x *Duration) check() uint { func (x *Duration) Reset() { *x = Duration{} - if protoimpl.UnsafeEnabled { - mi := &file_google_protobuf_duration_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_google_protobuf_duration_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *Duration) String() string { @@ -260,7 +258,7 @@ func (*Duration) ProtoMessage() {} func (x *Duration) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_duration_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -323,7 +321,7 @@ func file_google_protobuf_duration_proto_rawDescGZIP() []byte { } var file_google_protobuf_duration_proto_msgTypes = make([]protoimpl.MessageInfo, 1) -var file_google_protobuf_duration_proto_goTypes = []interface{}{ +var file_google_protobuf_duration_proto_goTypes = []any{ (*Duration)(nil), // 0: google.protobuf.Duration } var file_google_protobuf_duration_proto_depIdxs = []int32{ @@ -339,20 +337,6 @@ func file_google_protobuf_duration_proto_init() { if File_google_protobuf_duration_proto != nil { return } - if !protoimpl.UnsafeEnabled { - file_google_protobuf_duration_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Duration); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ diff --git a/vendor/google.golang.org/protobuf/types/known/timestamppb/timestamp.pb.go b/vendor/google.golang.org/protobuf/types/known/timestamppb/timestamp.pb.go index 81511a336..0d20722d7 100644 --- a/vendor/google.golang.org/protobuf/types/known/timestamppb/timestamp.pb.go +++ b/vendor/google.golang.org/protobuf/types/known/timestamppb/timestamp.pb.go @@ -254,11 +254,9 @@ func (x *Timestamp) check() uint { func (x *Timestamp) Reset() { *x = Timestamp{} - if protoimpl.UnsafeEnabled { - mi := &file_google_protobuf_timestamp_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } + mi := &file_google_protobuf_timestamp_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } func (x *Timestamp) String() string { @@ -269,7 +267,7 @@ func (*Timestamp) ProtoMessage() {} func (x *Timestamp) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_timestamp_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { + if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { ms.StoreMessageInfo(mi) @@ -332,7 +330,7 @@ func file_google_protobuf_timestamp_proto_rawDescGZIP() []byte { } var file_google_protobuf_timestamp_proto_msgTypes = make([]protoimpl.MessageInfo, 1) -var file_google_protobuf_timestamp_proto_goTypes = []interface{}{ +var file_google_protobuf_timestamp_proto_goTypes = []any{ (*Timestamp)(nil), // 0: google.protobuf.Timestamp } var file_google_protobuf_timestamp_proto_depIdxs = []int32{ @@ -348,20 +346,6 @@ func file_google_protobuf_timestamp_proto_init() { if File_google_protobuf_timestamp_proto != nil { return } - if !protoimpl.UnsafeEnabled { - file_google_protobuf_timestamp_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Timestamp); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/appsec/events/block.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/appsec/events/block.go new file mode 100644 index 000000000..b405bdd97 --- /dev/null +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/appsec/events/block.go @@ -0,0 +1,32 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2022 Datadog, Inc. + +// Package events provides security event types that appsec can return in function calls it monitors when blocking them. +// It allows finer-grained integrations of appsec into your Go errors' management logic. +package events + +import "errors" + +var _ error = (*BlockingSecurityEvent)(nil) + +// BlockingSecurityEvent is the error type returned by function calls blocked by appsec. +// Even though appsec takes care of responding automatically to the blocked requests, it +// is your duty to abort the request handlers that are calling functions blocked by appsec. +// For instance, if a gRPC handler performs a SQL query blocked by appsec, the SQL query +// function call gets blocked and aborted by returning an error of type SecurityBlockingEvent. +// This allows you to safely abort your request handlers, and to be able to leverage errors.As if +// necessary in your Go error management logic to be able to tell if the error is a blocking security +// event or not (eg. to avoid retrying an HTTP client request). +type BlockingSecurityEvent struct{} + +func (*BlockingSecurityEvent) Error() string { + return "request blocked by WAF" +} + +// IsSecurityError returns true if the error is a security event. +func IsSecurityError(err error) bool { + var secErr *BlockingSecurityEvent + return errors.As(err, &secErr) +} diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/ext/db.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/ext/db.go index 8074342d1..c9a046f86 100644 --- a/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/ext/db.go +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/ext/db.go @@ -73,6 +73,9 @@ const ( // CassandraCluster specifies the tag name that is used to set the cluster. CassandraCluster = "cassandra.cluster" + // CassandraDatacenter specifies the tag name that is used to set the datacenter. + CassandraDatacenter = "cassandra.datacenter" + // CassandraRowCount specifies the tag name to use when settings the row count. CassandraRowCount = "cassandra.row_count" @@ -84,4 +87,7 @@ const ( // CassandraContactPoints holds the list of cassandra initial seed nodes used to discover the cluster. CassandraContactPoints = "db.cassandra.contact.points" + + // CassandraHostID represents the host ID for this operation. + CassandraHostID = "db.cassandra.host.id" ) diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/ext/log_key.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/ext/log_key.go new file mode 100644 index 000000000..b17e098ff --- /dev/null +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/ext/log_key.go @@ -0,0 +1,13 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2016 Datadog, Inc. + +package ext + +const ( + // LogKeyTraceID is used by log integrations to correlate logs with a given trace. + LogKeyTraceID = "dd.trace_id" + // LogKeySpanID is used by log integrations to correlate logs with a given span. + LogKeySpanID = "dd.span_id" +) diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/civisibility_payload.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/civisibility_payload.go new file mode 100644 index 000000000..ce8cc0c2f --- /dev/null +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/civisibility_payload.go @@ -0,0 +1,141 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. + +package tracer + +import ( + "bytes" + "sync/atomic" + + "github.com/tinylib/msgp/msgp" + "gopkg.in/DataDog/dd-trace-go.v1/internal/civisibility/constants" + "gopkg.in/DataDog/dd-trace-go.v1/internal/civisibility/utils" + "gopkg.in/DataDog/dd-trace-go.v1/internal/globalconfig" + "gopkg.in/DataDog/dd-trace-go.v1/internal/log" + "gopkg.in/DataDog/dd-trace-go.v1/internal/version" +) + +// ciVisibilityPayload represents a payload specifically designed for CI Visibility events. +// It embeds the generic payload structure and adds methods to handle CI Visibility specific data. +type ciVisibilityPayload struct { + *payload +} + +// push adds a new CI Visibility event to the payload buffer. +// It grows the buffer to accommodate the new event, encodes the event in MessagePack format, and updates the event count. +// +// Parameters: +// +// event - The CI Visibility event to be added to the payload. +// +// Returns: +// +// An error if encoding the event fails. +func (p *ciVisibilityPayload) push(event *ciVisibilityEvent) error { + p.buf.Grow(event.Msgsize()) + if err := msgp.Encode(&p.buf, event); err != nil { + return err + } + atomic.AddUint32(&p.count, 1) + p.updateHeader() + return nil +} + +// newCiVisibilityPayload creates a new instance of civisibilitypayload. +// +// Returns: +// +// A pointer to a newly initialized civisibilitypayload instance. +func newCiVisibilityPayload() *ciVisibilityPayload { + log.Debug("ciVisibilityPayload: creating payload instance") + return &ciVisibilityPayload{newPayload()} +} + +// getBuffer retrieves the complete body of the CI Visibility payload, including metadata. +// It reads the current payload buffer, adds metadata, and encodes the entire payload in MessagePack format. +// +// Parameters: +// +// config - A pointer to the config structure containing environment settings. +// +// Returns: +// +// A pointer to a bytes.Buffer containing the encoded CI Visibility payload. +// An error if reading from the buffer or encoding the payload fails. +func (p *ciVisibilityPayload) getBuffer(config *config) (*bytes.Buffer, error) { + log.Debug("ciVisibilityPayload: .getBuffer (count: %v)", p.itemCount()) + + // Create a buffer to read the current payload + payloadBuf := new(bytes.Buffer) + if _, err := payloadBuf.ReadFrom(p.payload); err != nil { + return nil, err + } + + // Create the visibility payload + visibilityPayload := p.writeEnvelope(config.env, payloadBuf.Bytes()) + + // Create a new buffer to encode the visibility payload in MessagePack format + encodedBuf := new(bytes.Buffer) + if err := msgp.Encode(encodedBuf, visibilityPayload); err != nil { + return nil, err + } + + return encodedBuf, nil +} + +func (p *ciVisibilityPayload) writeEnvelope(env string, events []byte) *ciTestCyclePayload { + + /* + The Payload format in the CI Visibility protocol is like this: + { + "version": 1, + "metadata": { + "*": { + "runtime-id": "...", + "language": "...", + "library_version": "...", + "env": "..." + } + }, + "events": [ + // ... + ] + } + + The event format can be found in the `civisibility_tslv.go` file in the ciVisibilityEvent documentation + */ + + // Create the metadata map + allMetadata := map[string]string{ + "language": "go", + "runtime-id": globalconfig.RuntimeID(), + "library_version": version.Tag, + } + if env != "" { + allMetadata["env"] = env + } + + // Create the visibility payload + visibilityPayload := &ciTestCyclePayload{ + Version: 1, + Metadata: map[string]map[string]string{ + "*": allMetadata, + }, + Events: events, + } + + // Check for the test session name and append the tag at the metadata level + if testSessionName, ok := utils.GetCITags()[constants.TestSessionName]; ok { + testSessionMap := map[string]string{ + constants.TestSessionName: testSessionName, + } + visibilityPayload.Metadata["test_session_end"] = testSessionMap + visibilityPayload.Metadata["test_module_end"] = testSessionMap + visibilityPayload.Metadata["test_suite_end"] = testSessionMap + visibilityPayload.Metadata["test"] = testSessionMap + } + + return visibilityPayload +} diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/civisibility_transport.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/civisibility_transport.go new file mode 100644 index 000000000..073133202 --- /dev/null +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/civisibility_transport.go @@ -0,0 +1,203 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. + +package tracer + +import ( + "bytes" + "compress/gzip" + "fmt" + "io" + "net/http" + "os" + "runtime" + "strconv" + "strings" + + "gopkg.in/DataDog/dd-trace-go.v1/internal" + "gopkg.in/DataDog/dd-trace-go.v1/internal/civisibility/constants" + "gopkg.in/DataDog/dd-trace-go.v1/internal/log" + "gopkg.in/DataDog/dd-trace-go.v1/internal/version" +) + +// Constants for CI Visibility API paths and subdomains. +const ( + TestCycleSubdomain = "citestcycle-intake" // Subdomain for test cycle intake. + TestCyclePath = "api/v2/citestcycle" // API path for test cycle. + EvpProxyPath = "evp_proxy/v2" // Path for EVP proxy. +) + +// Ensure that civisibilityTransport implements the transport interface. +var _ transport = (*ciVisibilityTransport)(nil) + +// ciVisibilityTransport is a structure that handles sending CI Visibility payloads +// to the Datadog endpoint, either in agentless mode or through the EVP proxy. +type ciVisibilityTransport struct { + config *config // Configuration for the tracer. + testCycleURLPath string // URL path for the test cycle endpoint. + headers map[string]string // HTTP headers to be included in the requests. + agentless bool // Gets if the transport is configured in agentless mode (eg: Gzip support) +} + +// newCiVisibilityTransport creates and initializes a new civisibilityTransport +// based on the provided tracer configuration. It sets up the appropriate headers +// and determines the URL path based on whether agentless mode is enabled. +// +// Parameters: +// +// config - The tracer configuration. +// +// Returns: +// +// A pointer to an initialized civisibilityTransport instance. +func newCiVisibilityTransport(config *config) *ciVisibilityTransport { + // Initialize the default headers with encoder metadata. + defaultHeaders := map[string]string{ + "Datadog-Meta-Lang": "go", + "Datadog-Meta-Lang-Version": strings.TrimPrefix(runtime.Version(), "go"), + "Datadog-Meta-Lang-Interpreter": runtime.Compiler + "-" + runtime.GOARCH + "-" + runtime.GOOS, + "Datadog-Meta-Tracer-Version": version.Tag, + "Content-Type": "application/msgpack", + } + if cid := internal.ContainerID(); cid != "" { + defaultHeaders["Datadog-Container-ID"] = cid + } + if eid := internal.EntityID(); eid != "" { + defaultHeaders["Datadog-Entity-ID"] = eid + } + + // Determine if agentless mode is enabled through an environment variable. + agentlessEnabled := internal.BoolEnv(constants.CIVisibilityAgentlessEnabledEnvironmentVariable, false) + + testCycleURL := "" + if agentlessEnabled { + // Agentless mode is enabled. + APIKeyValue := os.Getenv(constants.APIKeyEnvironmentVariable) + if APIKeyValue == "" { + log.Error("An API key is required for agentless mode. Use the DD_API_KEY env variable to set it") + } + + defaultHeaders["dd-api-key"] = APIKeyValue + + // Check for a custom agentless URL. + agentlessURL := "" + if v := os.Getenv(constants.CIVisibilityAgentlessURLEnvironmentVariable); v != "" { + agentlessURL = v + } + + if agentlessURL == "" { + // Use the standard agentless URL format. + site := "datadoghq.com" + if v := os.Getenv("DD_SITE"); v != "" { + site = v + } + + testCycleURL = fmt.Sprintf("https://%s.%s/%s", TestCycleSubdomain, site, TestCyclePath) + } else { + // Use the custom agentless URL. + testCycleURL = fmt.Sprintf("%s/%s", agentlessURL, TestCyclePath) + } + } else { + // Use agent mode with the EVP proxy. + defaultHeaders["X-Datadog-EVP-Subdomain"] = TestCycleSubdomain + testCycleURL = fmt.Sprintf("%s/%s/%s", config.agentURL.String(), EvpProxyPath, TestCyclePath) + } + + log.Debug("ciVisibilityTransport: creating transport instance [agentless: %v, testcycleurl: %v]", agentlessEnabled, testCycleURL) + + return &ciVisibilityTransport{ + config: config, + testCycleURLPath: testCycleURL, + headers: defaultHeaders, + agentless: agentlessEnabled, + } +} + +// send sends the CI Visibility payload to the Datadog endpoint. +// It prepares the payload, creates the HTTP request, and handles the response. +// +// Parameters: +// +// p - The payload to be sent. +// +// Returns: +// +// An io.ReadCloser for reading the response body, and an error if the operation fails. +func (t *ciVisibilityTransport) send(p *payload) (body io.ReadCloser, err error) { + ciVisibilityPayload := &ciVisibilityPayload{p} + buffer, bufferErr := ciVisibilityPayload.getBuffer(t.config) + if bufferErr != nil { + return nil, fmt.Errorf("cannot create buffer payload: %v", bufferErr) + } + + if t.agentless { + // Compress payload + var gzipBuffer bytes.Buffer + gzipWriter := gzip.NewWriter(&gzipBuffer) + _, err = io.Copy(gzipWriter, buffer) + if err != nil { + return nil, fmt.Errorf("cannot compress request body: %v", err) + } + err = gzipWriter.Close() + if err != nil { + return nil, fmt.Errorf("cannot compress request body: %v", err) + } + buffer = &gzipBuffer + } + + req, err := http.NewRequest("POST", t.testCycleURLPath, buffer) + if err != nil { + return nil, fmt.Errorf("cannot create http request: %v", err) + } + for header, value := range t.headers { + req.Header.Set(header, value) + } + req.Header.Set("Content-Length", strconv.Itoa(buffer.Len())) + if t.agentless { + req.Header.Set("Content-Encoding", "gzip") + } + + log.Debug("ciVisibilityTransport: sending transport request: %v bytes", buffer.Len()) + response, err := t.config.httpClient.Do(req) + if err != nil { + return nil, err + } + if code := response.StatusCode; code >= 400 { + // error, check the body for context information and + // return a nice error. + msg := make([]byte, 1000) + n, _ := response.Body.Read(msg) + _ = response.Body.Close() + txt := http.StatusText(code) + if n > 0 { + return nil, fmt.Errorf("%s (Status: %s)", msg[:n], txt) + } + return nil, fmt.Errorf("%s", txt) + } + return response.Body, nil +} + +// sendStats is a no-op for CI Visibility transport as it does not support sending stats payloads. +// +// Parameters: +// +// payload - The stats payload to be sent. +// +// Returns: +// +// An error indicating that stats are not supported. +func (t *ciVisibilityTransport) sendStats(*statsPayload) error { + // Stats are not supported by CI Visibility agentless / EVP proxy. + return nil +} + +// endpoint returns the URL path of the test cycle endpoint. +// +// Returns: +// +// The URL path as a string. +func (t *ciVisibilityTransport) endpoint() string { + return t.testCycleURLPath +} diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/civisibility_tslv.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/civisibility_tslv.go new file mode 100644 index 000000000..ef6614d48 --- /dev/null +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/civisibility_tslv.go @@ -0,0 +1,445 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. + +//go:generate msgp -unexported -marshal=false -o=civisibility_tslv_msgp.go -tests=false + +package tracer + +import ( + "strconv" + + "github.com/tinylib/msgp/msgp" + "gopkg.in/DataDog/dd-trace-go.v1/ddtrace" + "gopkg.in/DataDog/dd-trace-go.v1/internal/civisibility/constants" +) + +type ( + // ciTestCyclePayloadList implements msgp.Decodable on top of a slice of ciVisibilityPayloads. + // This type is only used in tests. + ciTestCyclePayloadList []*ciTestCyclePayload + + // ciVisibilityEvents is a slice of ciVisibilityEvent pointers. + ciVisibilityEvents []*ciVisibilityEvent +) + +// Ensure that ciVisibilityEvent and related types implement necessary interfaces. +var ( + _ ddtrace.Span = (*ciVisibilityEvent)(nil) + _ msgp.Encodable = (*ciVisibilityEvent)(nil) + _ msgp.Decodable = (*ciVisibilityEvent)(nil) + + _ msgp.Encodable = (*ciVisibilityEvents)(nil) + _ msgp.Decodable = (*ciVisibilityEvents)(nil) + + _ msgp.Encodable = (*ciTestCyclePayload)(nil) + _ msgp.Decodable = (*ciTestCyclePayloadList)(nil) +) + +// ciTestCyclePayload represents the payload for CI test cycles, including version, metadata, and events. +type ciTestCyclePayload struct { + Version int32 `msg:"version"` // Version of the payload format + Metadata map[string]map[string]string `msg:"metadata"` // Metadata associated with the payload + Events msgp.Raw `msg:"events"` // Encoded events data +} + +// ciVisibilityEvent represents a CI visibility event, including type, version, and content. +// It implements the ddtrace.Span interface. +// According to the CI Visibility event specification it has the following format for tests: +// +// { +// "type": "test", +// "version": 2, +// "content": { +// "type": "test", +// "trace_id": 123456, +// "span_id": 654321, +// "parent_id": 0, +// "test_session_id": 123456789, +// "test_module_id": 234567890, +// "test_suite_id": 123123123, +// "name": "...", +// "resource": "...", +// "error": 0, +// "meta": { +// ... +// }, +// "metrics": { +// ... +// }, +// "start": 1654698415668011500, +// "duration": 796143, +// "service": "..." +// } +// } +// +// For test suites: +// +// { +// "type": "test_suite_end", +// "version": 1, +// "content": { +// "type": "test_suite_end", +// "test_module_id": 234567890, +// "test_session_id": 123456789, +// "test_suite_id": 123123123, +// "name": "...", +// "resource": "...", +// "error": 0, +// "meta": { +// ... +// }, +// "metrics": { +// ... +// }, +// "start": 1654698415668011500, +// "duration": 796143, +// "service": "..." +// } +// } +// +// For test modules: +// +// { +// "type": "test_module_end", +// "version": 1, +// "content": { +// "type": "test_module_end", +// "test_session_id": 123456789, +// "test_module_id": 234567890, +// "error": 0, +// "name": "...", +// "resource": "...", +// "meta": { +// ... +// }, +// "metrics": { +// ... +// }, +// "start": 1654698415668011500, +// "duration": 796143, +// "service": "..." +// } +// } +// +// For test sessions: +// +// { +// "type": "test_session_end", +// "version": 1, +// "content": { +// "type": "test_session_end", +// "test_session_id": 123456789, +// "name": "...", +// "resource": "...", +// "error": 0, +// "meta": { +// ... +// }, +// "metrics": { +// ... +// }, +// "start": 1654698415668011500, +// "duration": 796143, +// "service": "..." +// } +// } +// +// A complete specification for the meta and metrics maps for each type can be found at: https://github.com/DataDog/datadog-ci-spec/tree/main/spec/citest +type ciVisibilityEvent struct { + Type string `msg:"type"` // Type of the CI visibility event + Version int32 `msg:"version"` // Version of the event type + Content tslvSpan `msg:"content"` // Content of the event + + span *span `msg:"-"` // Associated span (not marshaled) +} + +// SetTag sets a tag on the event's span and updates the content metadata and metrics. +// +// Parameters: +// +// key - The tag key. +// value - The tag value. +func (e *ciVisibilityEvent) SetTag(key string, value interface{}) { + e.span.SetTag(key, value) + e.Content.Meta = e.span.Meta + e.Content.Metrics = e.span.Metrics +} + +// SetOperationName sets the operation name of the event's span and updates the content name. +// +// Parameters: +// +// operationName - The new operation name. +func (e *ciVisibilityEvent) SetOperationName(operationName string) { + e.span.SetOperationName(operationName) + e.Content.Name = e.span.Name +} + +// BaggageItem retrieves the baggage item associated with the given key from the event's span. +// +// Parameters: +// +// key - The baggage item key. +// +// Returns: +// +// The baggage item value. +func (e *ciVisibilityEvent) BaggageItem(key string) string { + return e.span.BaggageItem(key) +} + +// SetBaggageItem sets a baggage item on the event's span. +// +// Parameters: +// +// key - The baggage item key. +// val - The baggage item value. +func (e *ciVisibilityEvent) SetBaggageItem(key, val string) { + e.span.SetBaggageItem(key, val) +} + +// Finish completes the event's span with optional finish options. +// +// Parameters: +// +// opts - Optional finish options. +func (e *ciVisibilityEvent) Finish(opts ...ddtrace.FinishOption) { + e.span.Finish(opts...) +} + +// Context returns the span context of the event's span. +// +// Returns: +// +// The span context. +func (e *ciVisibilityEvent) Context() ddtrace.SpanContext { + return e.span.Context() +} + +// tslvSpan represents the detailed information of a span for CI visibility. +type tslvSpan struct { + SessionID uint64 `msg:"test_session_id,omitempty"` // identifier of this session + ModuleID uint64 `msg:"test_module_id,omitempty"` // identifier of this module + SuiteID uint64 `msg:"test_suite_id,omitempty"` // identifier of this suite + CorrelationID string `msg:"itr_correlation_id,omitempty"` // Correlation Id for Intelligent Test Runner transactions + Name string `msg:"name"` // operation name + Service string `msg:"service"` // service name (i.e. "grpc.server", "http.request") + Resource string `msg:"resource"` // resource name (i.e. "/user?id=123", "SELECT * FROM users") + Type string `msg:"type"` // protocol associated with the span (i.e. "web", "db", "cache") + Start int64 `msg:"start"` // span start time expressed in nanoseconds since epoch + Duration int64 `msg:"duration"` // duration of the span expressed in nanoseconds + SpanID uint64 `msg:"span_id,omitempty"` // identifier of this span + TraceID uint64 `msg:"trace_id,omitempty"` // lower 64-bits of the root span identifier + ParentID uint64 `msg:"parent_id,omitempty"` // identifier of the span's direct parent + Error int32 `msg:"error"` // error status of the span; 0 means no errors + Meta map[string]string `msg:"meta,omitempty"` // arbitrary map of metadata + Metrics map[string]float64 `msg:"metrics,omitempty"` // arbitrary map of numeric metrics +} + +// getCiVisibilityEvent creates a ciVisibilityEvent from a span based on the span type. +// +// Parameters: +// +// span - The span to convert into a ciVisibilityEvent. +// +// Returns: +// +// A pointer to the created ciVisibilityEvent. +func getCiVisibilityEvent(span *span) *ciVisibilityEvent { + switch span.Type { + case constants.SpanTypeTest: + return createTestEventFromSpan(span) + case constants.SpanTypeTestSuite: + return createTestSuiteEventFromSpan(span) + case constants.SpanTypeTestModule: + return createTestModuleEventFromSpan(span) + case constants.SpanTypeTestSession: + return createTestSessionEventFromSpan(span) + default: + return createSpanEventFromSpan(span) + } +} + +// createTestEventFromSpan creates a ciVisibilityEvent of type Test from a span. +// +// Parameters: +// +// span - The span to convert. +// +// Returns: +// +// A pointer to the created ciVisibilityEvent. +func createTestEventFromSpan(span *span) *ciVisibilityEvent { + tSpan := createTslvSpan(span) + tSpan.ParentID = 0 + tSpan.SessionID = getAndRemoveMetaToUInt64(span, constants.TestSessionIDTag) + tSpan.ModuleID = getAndRemoveMetaToUInt64(span, constants.TestModuleIDTag) + tSpan.SuiteID = getAndRemoveMetaToUInt64(span, constants.TestSuiteIDTag) + tSpan.CorrelationID = getAndRemoveMeta(span, constants.ItrCorrelationIDTag) + tSpan.SpanID = span.SpanID + tSpan.TraceID = span.TraceID + return &ciVisibilityEvent{ + span: span, + Type: constants.SpanTypeTest, + Version: 2, + Content: tSpan, + } +} + +// createTestSuiteEventFromSpan creates a ciVisibilityEvent of type TestSuite from a span. +// +// Parameters: +// +// span - The span to convert. +// +// Returns: +// +// A pointer to the created ciVisibilityEvent. +func createTestSuiteEventFromSpan(span *span) *ciVisibilityEvent { + tSpan := createTslvSpan(span) + tSpan.ParentID = 0 + tSpan.SessionID = getAndRemoveMetaToUInt64(span, constants.TestSessionIDTag) + tSpan.ModuleID = getAndRemoveMetaToUInt64(span, constants.TestModuleIDTag) + tSpan.SuiteID = getAndRemoveMetaToUInt64(span, constants.TestSuiteIDTag) + return &ciVisibilityEvent{ + span: span, + Type: constants.SpanTypeTestSuite, + Version: 1, + Content: tSpan, + } +} + +// createTestModuleEventFromSpan creates a ciVisibilityEvent of type TestModule from a span. +// +// Parameters: +// +// span - The span to convert. +// +// Returns: +// +// A pointer to the created ciVisibilityEvent. +func createTestModuleEventFromSpan(span *span) *ciVisibilityEvent { + tSpan := createTslvSpan(span) + tSpan.ParentID = 0 + tSpan.SessionID = getAndRemoveMetaToUInt64(span, constants.TestSessionIDTag) + tSpan.ModuleID = getAndRemoveMetaToUInt64(span, constants.TestModuleIDTag) + return &ciVisibilityEvent{ + span: span, + Type: constants.SpanTypeTestModule, + Version: 1, + Content: tSpan, + } +} + +// createTestSessionEventFromSpan creates a ciVisibilityEvent of type TestSession from a span. +// +// Parameters: +// +// span - The span to convert. +// +// Returns: +// +// A pointer to the created ciVisibilityEvent. +func createTestSessionEventFromSpan(span *span) *ciVisibilityEvent { + tSpan := createTslvSpan(span) + tSpan.ParentID = 0 + tSpan.SessionID = getAndRemoveMetaToUInt64(span, constants.TestSessionIDTag) + return &ciVisibilityEvent{ + span: span, + Type: constants.SpanTypeTestSession, + Version: 1, + Content: tSpan, + } +} + +// createSpanEventFromSpan creates a ciVisibilityEvent of type Span from a span. +// +// Parameters: +// +// span - The span to convert. +// +// Returns: +// +// A pointer to the created ciVisibilityEvent. +func createSpanEventFromSpan(span *span) *ciVisibilityEvent { + tSpan := createTslvSpan(span) + tSpan.SpanID = span.SpanID + tSpan.TraceID = span.TraceID + return &ciVisibilityEvent{ + span: span, + Type: constants.SpanTypeSpan, + Version: 1, + Content: tSpan, + } +} + +// createTslvSpan creates a tslvSpan from a span. +// +// Parameters: +// +// span - The span to convert. +// +// Returns: +// +// The created tslvSpan. +func createTslvSpan(span *span) tslvSpan { + return tslvSpan{ + Name: span.Name, + Service: span.Service, + Resource: span.Resource, + Type: span.Type, + Start: span.Start, + Duration: span.Duration, + ParentID: span.ParentID, + Error: span.Error, + Meta: span.Meta, + Metrics: span.Metrics, + } +} + +// getAndRemoveMeta retrieves a metadata value from a span and removes it from the span's metadata and metrics. +// +// Parameters: +// +// span - The span to modify. +// key - The metadata key to retrieve and remove. +// +// Returns: +// +// The retrieved metadata value. +func getAndRemoveMeta(span *span, key string) string { + span.Lock() + defer span.Unlock() + if span.Meta == nil { + span.Meta = make(map[string]string, 1) + } + + if v, ok := span.Meta[key]; ok { + delete(span.Meta, key) + delete(span.Metrics, key) + return v + } + + return "" +} + +// getAndRemoveMetaToUInt64 retrieves a metadata value from a span, removes it, and converts it to a uint64. +// +// Parameters: +// +// span - The span to modify. +// key - The metadata key to retrieve and convert. +// +// Returns: +// +// The retrieved and converted metadata value as a uint64. +func getAndRemoveMetaToUInt64(span *span, key string) uint64 { + strValue := getAndRemoveMeta(span, key) + i, err := strconv.ParseUint(strValue, 10, 64) + if err != nil { + return 0 + } + return i +} diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/civisibility_tslv_msgp.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/civisibility_tslv_msgp.go new file mode 100644 index 000000000..63fa4b849 --- /dev/null +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/civisibility_tslv_msgp.go @@ -0,0 +1,924 @@ +package tracer + +// Code generated by github.com/tinylib/msgp DO NOT EDIT. + +import ( + "github.com/tinylib/msgp/msgp" +) + +// DecodeMsg implements msgp.Decodable +func (z *ciTestCyclePayload) DecodeMsg(dc *msgp.Reader) (err error) { + var field []byte + _ = field + var zb0001 uint32 + zb0001, err = dc.ReadMapHeader() + if err != nil { + err = msgp.WrapError(err) + return + } + for zb0001 > 0 { + zb0001-- + field, err = dc.ReadMapKeyPtr() + if err != nil { + err = msgp.WrapError(err) + return + } + switch msgp.UnsafeString(field) { + case "version": + z.Version, err = dc.ReadInt32() + if err != nil { + err = msgp.WrapError(err, "Version") + return + } + case "metadata": + var zb0002 uint32 + zb0002, err = dc.ReadMapHeader() + if err != nil { + err = msgp.WrapError(err, "Metadata") + return + } + if z.Metadata == nil { + z.Metadata = make(map[string]map[string]string, zb0002) + } else if len(z.Metadata) > 0 { + for key := range z.Metadata { + delete(z.Metadata, key) + } + } + for zb0002 > 0 { + zb0002-- + var za0001 string + var za0002 map[string]string + za0001, err = dc.ReadString() + if err != nil { + err = msgp.WrapError(err, "Metadata") + return + } + var zb0003 uint32 + zb0003, err = dc.ReadMapHeader() + if err != nil { + err = msgp.WrapError(err, "Metadata", za0001) + return + } + if za0002 == nil { + za0002 = make(map[string]string, zb0003) + } else if len(za0002) > 0 { + for key := range za0002 { + delete(za0002, key) + } + } + for zb0003 > 0 { + zb0003-- + var za0003 string + var za0004 string + za0003, err = dc.ReadString() + if err != nil { + err = msgp.WrapError(err, "Metadata", za0001) + return + } + za0004, err = dc.ReadString() + if err != nil { + err = msgp.WrapError(err, "Metadata", za0001, za0003) + return + } + za0002[za0003] = za0004 + } + z.Metadata[za0001] = za0002 + } + case "events": + err = z.Events.DecodeMsg(dc) + if err != nil { + err = msgp.WrapError(err, "Events") + return + } + default: + err = dc.Skip() + if err != nil { + err = msgp.WrapError(err) + return + } + } + } + return +} + +// EncodeMsg implements msgp.Encodable +func (z *ciTestCyclePayload) EncodeMsg(en *msgp.Writer) (err error) { + // map header, size 3 + // write "version" + err = en.Append(0x83, 0xa7, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e) + if err != nil { + return + } + err = en.WriteInt32(z.Version) + if err != nil { + err = msgp.WrapError(err, "Version") + return + } + // write "metadata" + err = en.Append(0xa8, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61) + if err != nil { + return + } + err = en.WriteMapHeader(uint32(len(z.Metadata))) + if err != nil { + err = msgp.WrapError(err, "Metadata") + return + } + for za0001, za0002 := range z.Metadata { + err = en.WriteString(za0001) + if err != nil { + err = msgp.WrapError(err, "Metadata") + return + } + err = en.WriteMapHeader(uint32(len(za0002))) + if err != nil { + err = msgp.WrapError(err, "Metadata", za0001) + return + } + for za0003, za0004 := range za0002 { + err = en.WriteString(za0003) + if err != nil { + err = msgp.WrapError(err, "Metadata", za0001) + return + } + err = en.WriteString(za0004) + if err != nil { + err = msgp.WrapError(err, "Metadata", za0001, za0003) + return + } + } + } + // write "events" + err = en.Append(0xa6, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73) + if err != nil { + return + } + err = z.Events.EncodeMsg(en) + if err != nil { + err = msgp.WrapError(err, "Events") + return + } + return +} + +// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message +func (z *ciTestCyclePayload) Msgsize() (s int) { + s = 1 + 8 + msgp.Int32Size + 9 + msgp.MapHeaderSize + if z.Metadata != nil { + for za0001, za0002 := range z.Metadata { + _ = za0002 + s += msgp.StringPrefixSize + len(za0001) + msgp.MapHeaderSize + if za0002 != nil { + for za0003, za0004 := range za0002 { + _ = za0004 + s += msgp.StringPrefixSize + len(za0003) + msgp.StringPrefixSize + len(za0004) + } + } + } + } + s += 7 + z.Events.Msgsize() + return +} + +// DecodeMsg implements msgp.Decodable +func (z *ciTestCyclePayloadList) DecodeMsg(dc *msgp.Reader) (err error) { + var zb0002 uint32 + zb0002, err = dc.ReadArrayHeader() + if err != nil { + err = msgp.WrapError(err) + return + } + if cap((*z)) >= int(zb0002) { + (*z) = (*z)[:zb0002] + } else { + (*z) = make(ciTestCyclePayloadList, zb0002) + } + for zb0001 := range *z { + if dc.IsNil() { + err = dc.ReadNil() + if err != nil { + err = msgp.WrapError(err, zb0001) + return + } + (*z)[zb0001] = nil + } else { + if (*z)[zb0001] == nil { + (*z)[zb0001] = new(ciTestCyclePayload) + } + err = (*z)[zb0001].DecodeMsg(dc) + if err != nil { + err = msgp.WrapError(err, zb0001) + return + } + } + } + return +} + +// EncodeMsg implements msgp.Encodable +func (z ciTestCyclePayloadList) EncodeMsg(en *msgp.Writer) (err error) { + err = en.WriteArrayHeader(uint32(len(z))) + if err != nil { + err = msgp.WrapError(err) + return + } + for zb0003 := range z { + if z[zb0003] == nil { + err = en.WriteNil() + if err != nil { + return + } + } else { + err = z[zb0003].EncodeMsg(en) + if err != nil { + err = msgp.WrapError(err, zb0003) + return + } + } + } + return +} + +// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message +func (z ciTestCyclePayloadList) Msgsize() (s int) { + s = msgp.ArrayHeaderSize + for zb0003 := range z { + if z[zb0003] == nil { + s += msgp.NilSize + } else { + s += z[zb0003].Msgsize() + } + } + return +} + +// DecodeMsg implements msgp.Decodable +func (z *ciVisibilityEvent) DecodeMsg(dc *msgp.Reader) (err error) { + var field []byte + _ = field + var zb0001 uint32 + zb0001, err = dc.ReadMapHeader() + if err != nil { + err = msgp.WrapError(err) + return + } + for zb0001 > 0 { + zb0001-- + field, err = dc.ReadMapKeyPtr() + if err != nil { + err = msgp.WrapError(err) + return + } + switch msgp.UnsafeString(field) { + case "type": + z.Type, err = dc.ReadString() + if err != nil { + err = msgp.WrapError(err, "Type") + return + } + case "version": + z.Version, err = dc.ReadInt32() + if err != nil { + err = msgp.WrapError(err, "Version") + return + } + case "content": + err = z.Content.DecodeMsg(dc) + if err != nil { + err = msgp.WrapError(err, "Content") + return + } + default: + err = dc.Skip() + if err != nil { + err = msgp.WrapError(err) + return + } + } + } + return +} + +// EncodeMsg implements msgp.Encodable +func (z *ciVisibilityEvent) EncodeMsg(en *msgp.Writer) (err error) { + // map header, size 3 + // write "type" + err = en.Append(0x83, 0xa4, 0x74, 0x79, 0x70, 0x65) + if err != nil { + return + } + err = en.WriteString(z.Type) + if err != nil { + err = msgp.WrapError(err, "Type") + return + } + // write "version" + err = en.Append(0xa7, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e) + if err != nil { + return + } + err = en.WriteInt32(z.Version) + if err != nil { + err = msgp.WrapError(err, "Version") + return + } + // write "content" + err = en.Append(0xa7, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74) + if err != nil { + return + } + err = z.Content.EncodeMsg(en) + if err != nil { + err = msgp.WrapError(err, "Content") + return + } + return +} + +// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message +func (z *ciVisibilityEvent) Msgsize() (s int) { + s = 1 + 5 + msgp.StringPrefixSize + len(z.Type) + 8 + msgp.Int32Size + 8 + z.Content.Msgsize() + return +} + +// DecodeMsg implements msgp.Decodable +func (z *ciVisibilityEvents) DecodeMsg(dc *msgp.Reader) (err error) { + var zb0002 uint32 + zb0002, err = dc.ReadArrayHeader() + if err != nil { + err = msgp.WrapError(err) + return + } + if cap((*z)) >= int(zb0002) { + (*z) = (*z)[:zb0002] + } else { + (*z) = make(ciVisibilityEvents, zb0002) + } + for zb0001 := range *z { + if dc.IsNil() { + err = dc.ReadNil() + if err != nil { + err = msgp.WrapError(err, zb0001) + return + } + (*z)[zb0001] = nil + } else { + if (*z)[zb0001] == nil { + (*z)[zb0001] = new(ciVisibilityEvent) + } + var field []byte + _ = field + var zb0003 uint32 + zb0003, err = dc.ReadMapHeader() + if err != nil { + err = msgp.WrapError(err, zb0001) + return + } + for zb0003 > 0 { + zb0003-- + field, err = dc.ReadMapKeyPtr() + if err != nil { + err = msgp.WrapError(err, zb0001) + return + } + switch msgp.UnsafeString(field) { + case "type": + (*z)[zb0001].Type, err = dc.ReadString() + if err != nil { + err = msgp.WrapError(err, zb0001, "Type") + return + } + case "version": + (*z)[zb0001].Version, err = dc.ReadInt32() + if err != nil { + err = msgp.WrapError(err, zb0001, "Version") + return + } + case "content": + err = (*z)[zb0001].Content.DecodeMsg(dc) + if err != nil { + err = msgp.WrapError(err, zb0001, "Content") + return + } + default: + err = dc.Skip() + if err != nil { + err = msgp.WrapError(err, zb0001) + return + } + } + } + } + } + return +} + +// EncodeMsg implements msgp.Encodable +func (z ciVisibilityEvents) EncodeMsg(en *msgp.Writer) (err error) { + err = en.WriteArrayHeader(uint32(len(z))) + if err != nil { + err = msgp.WrapError(err) + return + } + for zb0004 := range z { + if z[zb0004] == nil { + err = en.WriteNil() + if err != nil { + return + } + } else { + // map header, size 3 + // write "type" + err = en.Append(0x83, 0xa4, 0x74, 0x79, 0x70, 0x65) + if err != nil { + return + } + err = en.WriteString(z[zb0004].Type) + if err != nil { + err = msgp.WrapError(err, zb0004, "Type") + return + } + // write "version" + err = en.Append(0xa7, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e) + if err != nil { + return + } + err = en.WriteInt32(z[zb0004].Version) + if err != nil { + err = msgp.WrapError(err, zb0004, "Version") + return + } + // write "content" + err = en.Append(0xa7, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74) + if err != nil { + return + } + err = z[zb0004].Content.EncodeMsg(en) + if err != nil { + err = msgp.WrapError(err, zb0004, "Content") + return + } + } + } + return +} + +// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message +func (z ciVisibilityEvents) Msgsize() (s int) { + s = msgp.ArrayHeaderSize + for zb0004 := range z { + if z[zb0004] == nil { + s += msgp.NilSize + } else { + s += 1 + 5 + msgp.StringPrefixSize + len(z[zb0004].Type) + 8 + msgp.Int32Size + 8 + z[zb0004].Content.Msgsize() + } + } + return +} + +// DecodeMsg implements msgp.Decodable +func (z *tslvSpan) DecodeMsg(dc *msgp.Reader) (err error) { + var field []byte + _ = field + var zb0001 uint32 + zb0001, err = dc.ReadMapHeader() + if err != nil { + err = msgp.WrapError(err) + return + } + for zb0001 > 0 { + zb0001-- + field, err = dc.ReadMapKeyPtr() + if err != nil { + err = msgp.WrapError(err) + return + } + switch msgp.UnsafeString(field) { + case "test_session_id": + z.SessionID, err = dc.ReadUint64() + if err != nil { + err = msgp.WrapError(err, "SessionId") + return + } + case "test_module_id": + z.ModuleID, err = dc.ReadUint64() + if err != nil { + err = msgp.WrapError(err, "ModuleId") + return + } + case "test_suite_id": + z.SuiteID, err = dc.ReadUint64() + if err != nil { + err = msgp.WrapError(err, "SuiteId") + return + } + case "itr_correlation_id": + z.CorrelationID, err = dc.ReadString() + if err != nil { + err = msgp.WrapError(err, "CorrelationId") + return + } + case "name": + z.Name, err = dc.ReadString() + if err != nil { + err = msgp.WrapError(err, "Name") + return + } + case "service": + z.Service, err = dc.ReadString() + if err != nil { + err = msgp.WrapError(err, "Service") + return + } + case "resource": + z.Resource, err = dc.ReadString() + if err != nil { + err = msgp.WrapError(err, "Resource") + return + } + case "type": + z.Type, err = dc.ReadString() + if err != nil { + err = msgp.WrapError(err, "Type") + return + } + case "start": + z.Start, err = dc.ReadInt64() + if err != nil { + err = msgp.WrapError(err, "Start") + return + } + case "duration": + z.Duration, err = dc.ReadInt64() + if err != nil { + err = msgp.WrapError(err, "Duration") + return + } + case "span_id": + z.SpanID, err = dc.ReadUint64() + if err != nil { + err = msgp.WrapError(err, "SpanID") + return + } + case "trace_id": + z.TraceID, err = dc.ReadUint64() + if err != nil { + err = msgp.WrapError(err, "TraceID") + return + } + case "parent_id": + z.ParentID, err = dc.ReadUint64() + if err != nil { + err = msgp.WrapError(err, "ParentID") + return + } + case "error": + z.Error, err = dc.ReadInt32() + if err != nil { + err = msgp.WrapError(err, "Error") + return + } + case "meta": + var zb0002 uint32 + zb0002, err = dc.ReadMapHeader() + if err != nil { + err = msgp.WrapError(err, "Meta") + return + } + if z.Meta == nil { + z.Meta = make(map[string]string, zb0002) + } else if len(z.Meta) > 0 { + for key := range z.Meta { + delete(z.Meta, key) + } + } + for zb0002 > 0 { + zb0002-- + var za0001 string + var za0002 string + za0001, err = dc.ReadString() + if err != nil { + err = msgp.WrapError(err, "Meta") + return + } + za0002, err = dc.ReadString() + if err != nil { + err = msgp.WrapError(err, "Meta", za0001) + return + } + z.Meta[za0001] = za0002 + } + case "metrics": + var zb0003 uint32 + zb0003, err = dc.ReadMapHeader() + if err != nil { + err = msgp.WrapError(err, "Metrics") + return + } + if z.Metrics == nil { + z.Metrics = make(map[string]float64, zb0003) + } else if len(z.Metrics) > 0 { + for key := range z.Metrics { + delete(z.Metrics, key) + } + } + for zb0003 > 0 { + zb0003-- + var za0003 string + var za0004 float64 + za0003, err = dc.ReadString() + if err != nil { + err = msgp.WrapError(err, "Metrics") + return + } + za0004, err = dc.ReadFloat64() + if err != nil { + err = msgp.WrapError(err, "Metrics", za0003) + return + } + z.Metrics[za0003] = za0004 + } + default: + err = dc.Skip() + if err != nil { + err = msgp.WrapError(err) + return + } + } + } + return +} + +// EncodeMsg implements msgp.Encodable +func (z *tslvSpan) EncodeMsg(en *msgp.Writer) (err error) { + // omitempty: check for empty values + zb0001Len := uint32(16) + var zb0001Mask uint16 /* 16 bits */ + _ = zb0001Mask + if z.SessionID == 0 { + zb0001Len-- + zb0001Mask |= 0x1 + } + if z.ModuleID == 0 { + zb0001Len-- + zb0001Mask |= 0x2 + } + if z.SuiteID == 0 { + zb0001Len-- + zb0001Mask |= 0x4 + } + if z.CorrelationID == "" { + zb0001Len-- + zb0001Mask |= 0x8 + } + if z.SpanID == 0 { + zb0001Len-- + zb0001Mask |= 0x400 + } + if z.TraceID == 0 { + zb0001Len-- + zb0001Mask |= 0x800 + } + if z.ParentID == 0 { + zb0001Len-- + zb0001Mask |= 0x1000 + } + if z.Meta == nil { + zb0001Len-- + zb0001Mask |= 0x4000 + } + if z.Metrics == nil { + zb0001Len-- + zb0001Mask |= 0x8000 + } + // variable map header, size zb0001Len + err = en.WriteMapHeader(zb0001Len) + if err != nil { + return + } + if zb0001Len == 0 { + return + } + if (zb0001Mask & 0x1) == 0 { // if not empty + // write "test_session_id" + err = en.Append(0xaf, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64) + if err != nil { + return + } + err = en.WriteUint64(z.SessionID) + if err != nil { + err = msgp.WrapError(err, "SessionID") + return + } + } + if (zb0001Mask & 0x2) == 0 { // if not empty + // write "test_module_id" + err = en.Append(0xae, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x5f, 0x69, 0x64) + if err != nil { + return + } + err = en.WriteUint64(z.ModuleID) + if err != nil { + err = msgp.WrapError(err, "ModuleID") + return + } + } + if (zb0001Mask & 0x4) == 0 { // if not empty + // write "test_suite_id" + err = en.Append(0xad, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x75, 0x69, 0x74, 0x65, 0x5f, 0x69, 0x64) + if err != nil { + return + } + err = en.WriteUint64(z.SuiteID) + if err != nil { + err = msgp.WrapError(err, "SuiteID") + return + } + } + if (zb0001Mask & 0x8) == 0 { // if not empty + // write "itr_correlation_id" + err = en.Append(0xb2, 0x69, 0x74, 0x72, 0x5f, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64) + if err != nil { + return + } + err = en.WriteString(z.CorrelationID) + if err != nil { + err = msgp.WrapError(err, "CorrelationID") + return + } + } + // write "name" + err = en.Append(0xa4, 0x6e, 0x61, 0x6d, 0x65) + if err != nil { + return + } + err = en.WriteString(z.Name) + if err != nil { + err = msgp.WrapError(err, "Name") + return + } + // write "service" + err = en.Append(0xa7, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65) + if err != nil { + return + } + err = en.WriteString(z.Service) + if err != nil { + err = msgp.WrapError(err, "Service") + return + } + // write "resource" + err = en.Append(0xa8, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65) + if err != nil { + return + } + err = en.WriteString(z.Resource) + if err != nil { + err = msgp.WrapError(err, "Resource") + return + } + // write "type" + err = en.Append(0xa4, 0x74, 0x79, 0x70, 0x65) + if err != nil { + return + } + err = en.WriteString(z.Type) + if err != nil { + err = msgp.WrapError(err, "Type") + return + } + // write "start" + err = en.Append(0xa5, 0x73, 0x74, 0x61, 0x72, 0x74) + if err != nil { + return + } + err = en.WriteInt64(z.Start) + if err != nil { + err = msgp.WrapError(err, "Start") + return + } + // write "duration" + err = en.Append(0xa8, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e) + if err != nil { + return + } + err = en.WriteInt64(z.Duration) + if err != nil { + err = msgp.WrapError(err, "Duration") + return + } + if (zb0001Mask & 0x400) == 0 { // if not empty + // write "span_id" + err = en.Append(0xa7, 0x73, 0x70, 0x61, 0x6e, 0x5f, 0x69, 0x64) + if err != nil { + return + } + err = en.WriteUint64(z.SpanID) + if err != nil { + err = msgp.WrapError(err, "SpanID") + return + } + } + if (zb0001Mask & 0x800) == 0 { // if not empty + // write "trace_id" + err = en.Append(0xa8, 0x74, 0x72, 0x61, 0x63, 0x65, 0x5f, 0x69, 0x64) + if err != nil { + return + } + err = en.WriteUint64(z.TraceID) + if err != nil { + err = msgp.WrapError(err, "TraceID") + return + } + } + if (zb0001Mask & 0x1000) == 0 { // if not empty + // write "parent_id" + err = en.Append(0xa9, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64) + if err != nil { + return + } + err = en.WriteUint64(z.ParentID) + if err != nil { + err = msgp.WrapError(err, "ParentID") + return + } + } + // write "error" + err = en.Append(0xa5, 0x65, 0x72, 0x72, 0x6f, 0x72) + if err != nil { + return + } + err = en.WriteInt32(z.Error) + if err != nil { + err = msgp.WrapError(err, "Error") + return + } + if (zb0001Mask & 0x4000) == 0 { // if not empty + // write "meta" + err = en.Append(0xa4, 0x6d, 0x65, 0x74, 0x61) + if err != nil { + return + } + err = en.WriteMapHeader(uint32(len(z.Meta))) + if err != nil { + err = msgp.WrapError(err, "Meta") + return + } + for za0001, za0002 := range z.Meta { + err = en.WriteString(za0001) + if err != nil { + err = msgp.WrapError(err, "Meta") + return + } + err = en.WriteString(za0002) + if err != nil { + err = msgp.WrapError(err, "Meta", za0001) + return + } + } + } + if (zb0001Mask & 0x8000) == 0 { // if not empty + // write "metrics" + err = en.Append(0xa7, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73) + if err != nil { + return + } + err = en.WriteMapHeader(uint32(len(z.Metrics))) + if err != nil { + err = msgp.WrapError(err, "Metrics") + return + } + for za0003, za0004 := range z.Metrics { + err = en.WriteString(za0003) + if err != nil { + err = msgp.WrapError(err, "Metrics") + return + } + err = en.WriteFloat64(za0004) + if err != nil { + err = msgp.WrapError(err, "Metrics", za0003) + return + } + } + } + return +} + +// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message +func (z *tslvSpan) Msgsize() (s int) { + s = 3 + 16 + msgp.Uint64Size + 15 + msgp.Uint64Size + 14 + msgp.Uint64Size + 19 + msgp.StringPrefixSize + len(z.CorrelationID) + 5 + msgp.StringPrefixSize + len(z.Name) + 8 + msgp.StringPrefixSize + len(z.Service) + 9 + msgp.StringPrefixSize + len(z.Resource) + 5 + msgp.StringPrefixSize + len(z.Type) + 6 + msgp.Int64Size + 9 + msgp.Int64Size + 8 + msgp.Uint64Size + 9 + msgp.Uint64Size + 10 + msgp.Uint64Size + 6 + msgp.Int32Size + 5 + msgp.MapHeaderSize + if z.Meta != nil { + for za0001, za0002 := range z.Meta { + _ = za0002 + s += msgp.StringPrefixSize + len(za0001) + msgp.StringPrefixSize + len(za0002) + } + } + s += 8 + msgp.MapHeaderSize + if z.Metrics != nil { + for za0003, za0004 := range z.Metrics { + _ = za0004 + s += msgp.StringPrefixSize + len(za0003) + msgp.Float64Size + } + } + return +} diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/civisibility_writer.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/civisibility_writer.go new file mode 100644 index 000000000..969b5edea --- /dev/null +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/civisibility_writer.go @@ -0,0 +1,120 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. + +package tracer + +import ( + "sync" + "time" + + "gopkg.in/DataDog/dd-trace-go.v1/internal/log" +) + +// Constants defining the payload size limits for agentless mode. +const ( + // agentlessPayloadMaxLimit is the maximum payload size allowed, indicating the + // maximum size of the package that the intake can receive. + agentlessPayloadMaxLimit = 5 * 1024 * 1024 // 5 MB + + // agentlessPayloadSizeLimit specifies the maximum allowed size of the payload before + // it triggers a flush to the transport. + agentlessPayloadSizeLimit = agentlessPayloadMaxLimit / 2 +) + +// Ensure that ciVisibilityTraceWriter implements the traceWriter interface. +var _ traceWriter = (*ciVisibilityTraceWriter)(nil) + +// ciVisibilityTraceWriter is responsible for buffering and sending CI visibility trace data +// to the Datadog backend. It manages the payload size and flushes the data when necessary. +type ciVisibilityTraceWriter struct { + config *config // Configuration for the tracer. + payload *ciVisibilityPayload // Encodes and buffers events in msgpack format. + climit chan struct{} // Limits the number of concurrent outgoing connections. + wg sync.WaitGroup // Waits for all uploads to finish. +} + +// newCiVisibilityTraceWriter creates a new instance of ciVisibilityTraceWriter. +// +// Parameters: +// +// c - The tracer configuration. +// +// Returns: +// +// A pointer to an initialized ciVisibilityTraceWriter. +func newCiVisibilityTraceWriter(c *config) *ciVisibilityTraceWriter { + log.Debug("ciVisibilityTraceWriter: creating trace writer instance") + return &ciVisibilityTraceWriter{ + config: c, + payload: newCiVisibilityPayload(), + climit: make(chan struct{}, concurrentConnectionLimit), + } +} + +// add adds a new trace to the payload. If the payload size exceeds the limit, +// it triggers a flush to send the data. +// +// Parameters: +// +// trace - A slice of spans representing the trace to be added. +func (w *ciVisibilityTraceWriter) add(trace []*span) { + for _, s := range trace { + cvEvent := getCiVisibilityEvent(s) + if err := w.payload.push(cvEvent); err != nil { + log.Error("ciVisibilityTraceWriter: Error encoding msgpack: %v", err) + } + if w.payload.size() > agentlessPayloadSizeLimit { + w.flush() + } + } +} + +// stop stops the trace writer, ensuring all data is flushed and all uploads are completed. +func (w *ciVisibilityTraceWriter) stop() { + w.flush() + w.wg.Wait() +} + +// flush sends the current payload to the transport. It ensures that the payload is reset +// and the resources are freed after the flush operation is completed. +func (w *ciVisibilityTraceWriter) flush() { + if w.payload.itemCount() == 0 { + return + } + + w.wg.Add(1) + w.climit <- struct{}{} + oldp := w.payload + w.payload = newCiVisibilityPayload() + + go func(p *ciVisibilityPayload) { + defer func(start time.Time) { + // Once the payload has been used, clear the buffer for garbage + // collection to avoid a memory leak when references to this object + // may still be kept by faulty transport implementations or the + // standard library. See dd-trace-go#976 + p.clear() + + <-w.climit + w.wg.Done() + }(time.Now()) + + var count, size int + var err error + for attempt := 0; attempt <= w.config.sendRetries; attempt++ { + size, count = p.size(), p.itemCount() + log.Debug("ciVisibilityTraceWriter: sending payload: size: %d events: %d\n", size, count) + _, err = w.config.transport.send(p.payload) + if err == nil { + log.Debug("ciVisibilityTraceWriter: sent events after %d attempts", attempt+1) + return + } + log.Error("ciVisibilityTraceWriter: failure sending events (attempt %d), will retry: %v", attempt+1, err) + p.reset() + time.Sleep(time.Millisecond) + } + log.Error("ciVisibilityTraceWriter: lost %d events: %v", count, err) + }(oldp) +} diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/context.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/context.go index 5698dea68..ee29dca37 100644 --- a/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/context.go +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/context.go @@ -11,11 +11,12 @@ import ( "gopkg.in/DataDog/dd-trace-go.v1/ddtrace" traceinternal "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/internal" "gopkg.in/DataDog/dd-trace-go.v1/internal" + "gopkg.in/DataDog/dd-trace-go.v1/internal/orchestrion" ) // ContextWithSpan returns a copy of the given context which includes the span s. func ContextWithSpan(ctx context.Context, s Span) context.Context { - return context.WithValue(ctx, internal.ActiveSpanKey, s) + return orchestrion.CtxWithValue(ctx, internal.ActiveSpanKey, s) } // SpanFromContext returns the span contained in the given context. A second return @@ -25,7 +26,7 @@ func SpanFromContext(ctx context.Context) (Span, bool) { if ctx == nil { return &traceinternal.NoopSpan{}, false } - v := ctx.Value(internal.ActiveSpanKey) + v := orchestrion.WrapContext(ctx).Value(internal.ActiveSpanKey) if s, ok := v.(ddtrace.Span); ok { return s, true } diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/dynamic_config.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/dynamic_config.go index 919b4f722..db48be5a7 100644 --- a/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/dynamic_config.go +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/dynamic_config.go @@ -19,7 +19,7 @@ type dynamicConfig[T any] struct { current T // holds the current configuration value startup T // holds the startup configuration value cfgName string // holds the name of the configuration, has to be compatible with telemetry.Configuration.Name - cfgOrigin string // holds the origin of the current configuration value (currently only supports remote_config, empty otherwise) + cfgOrigin telemetry.Origin // holds the origin of the current configuration value (currently only supports remote_config, empty otherwise) apply func(T) bool // executes any config-specific operations to propagate the update properly, returns whether the update was applied equal func(x, y T) bool // compares two configuration values, this is used to avoid unnecessary config and telemetry updates } @@ -42,7 +42,7 @@ func (dc *dynamicConfig[T]) get() T { } // update applies a new configuration value -func (dc *dynamicConfig[T]) update(val T, origin string) bool { +func (dc *dynamicConfig[T]) update(val T, origin telemetry.Origin) bool { dc.Lock() defer dc.Unlock() if dc.equal(dc.current, val) { @@ -61,7 +61,8 @@ func (dc *dynamicConfig[T]) reset() bool { return false } dc.current = dc.startup - dc.cfgOrigin = "" + // TODO: set the origin to the startup value's origin + dc.cfgOrigin = telemetry.OriginDefault return dc.apply(dc.startup) } @@ -69,7 +70,7 @@ func (dc *dynamicConfig[T]) reset() bool { // Returns whether the configuration value has been updated or not func (dc *dynamicConfig[T]) handleRC(val *T) bool { if val != nil { - return dc.update(*val, "remote_config") + return dc.update(*val, telemetry.OriginRemoteConfig) } return dc.reset() } diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/log.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/log.go index bf4b46b6d..b88d477c9 100644 --- a/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/log.go +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/log.go @@ -37,7 +37,8 @@ type startupInfo struct { AnalyticsEnabled bool `json:"analytics_enabled"` // True if there is a global analytics rate set SampleRate string `json:"sample_rate"` // The default sampling rate for the rules sampler SampleRateLimit string `json:"sample_rate_limit"` // The rate limit configured with the rules sampler - SamplingRules []SamplingRule `json:"sampling_rules"` // Rules used by the rules sampler + TraceSamplingRules []SamplingRule `json:"trace_sampling_rules"` // Trace rules used by the rules sampler + SpanSamplingRules []SamplingRule `json:"span_sampling_rules"` // Span rules used by the rules sampler SamplingRulesError string `json:"sampling_rules_error"` // Any errors that occurred while parsing sampling rules ServiceMappings map[string]string `json:"service_mappings"` // Service Mappings Tags map[string]string `json:"tags"` // Global tags @@ -56,6 +57,8 @@ type startupInfo struct { PartialFlushMinSpans int `json:"partial_flush_min_spans"` // The min number of spans to trigger a partial flush Orchestrion orchestrionConfig `json:"orchestrion"` // Orchestrion (auto-instrumentation) configuration. FeatureFlags []string `json:"feature_flags"` + PropagationStyleInject string `json:"propagation_style_inject"` // Propagation style for inject + PropagationStyleExtract string `json:"propagation_style_extract"` // Propagation style for extract } // checkEndpoint tries to connect to the URL specified by endpoint. @@ -89,6 +92,19 @@ func logStartup(t *tracer) { featureFlags = append(featureFlags, f) } + var injectorNames, extractorNames string + switch v := t.config.propagator.(type) { + case *chainedPropagator: + injectorNames = v.injectorNames + extractorNames = v.extractorsNames + case nil: + injectorNames = "" + extractorNames = "" + default: + injectorNames = "custom" + extractorNames = "custom" + } + info := startupInfo{ Date: time.Now().Format(time.RFC3339), OSName: osinfo.OSName(), @@ -103,7 +119,8 @@ func logStartup(t *tracer) { AnalyticsEnabled: !math.IsNaN(globalconfig.AnalyticsRate()), SampleRate: fmt.Sprintf("%f", t.rulesSampling.traces.globalRate), SampleRateLimit: "disabled", - SamplingRules: append(t.config.traceRules, t.config.spanRules...), + TraceSamplingRules: t.config.traceRules, + SpanSamplingRules: t.config.spanRules, ServiceMappings: t.config.serviceMappings, Tags: tags, RuntimeMetricsEnabled: t.config.runtimeMetrics, @@ -121,6 +138,8 @@ func logStartup(t *tracer) { PartialFlushMinSpans: t.config.partialFlushMinSpans, Orchestrion: t.config.orchestrionCfg, FeatureFlags: featureFlags, + PropagationStyleInject: injectorNames, + PropagationStyleExtract: extractorNames, } if _, _, err := samplingRulesFromEnv(); err != nil { info.SamplingRulesError = fmt.Sprintf("%s", err) diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/meta_struct.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/meta_struct.go new file mode 100644 index 000000000..2f564da07 --- /dev/null +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/meta_struct.go @@ -0,0 +1,88 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2016 Datadog, Inc. + +package tracer + +import ( + "github.com/tinylib/msgp/msgp" +) + +var ( + _ msgp.Encodable = (*metaStructMap)(nil) + _ msgp.Decodable = (*metaStructMap)(nil) + _ msgp.Sizer = (*metaStructMap)(nil) +) + +// metaStructMap is a map of string to any of metadata embedded in each span +// We export special messagepack methods to handle the encoding and decoding of the map +// Because the agent expects the metadata to be a map of string to byte array, we have to create sub-messages of messagepack for each value +type metaStructMap map[string]any + +// EncodeMsg transforms the map[string]any into a map[string][]byte agent-side (which is parsed back into a map[string]any in the backend) +func (m *metaStructMap) EncodeMsg(en *msgp.Writer) error { + err := en.WriteMapHeader(uint32(len(*m))) + if err != nil { + return msgp.WrapError(err, "MetaStruct") + } + + for key, value := range *m { + err = en.WriteString(key) + if err != nil { + return msgp.WrapError(err, "MetaStruct") + } + + // Wrap the encoded value in a byte array that will not be parsed by the agent + msg, err := msgp.AppendIntf(nil, value) + if err != nil { + return msgp.WrapError(err, "MetaStruct", key) + } + + err = en.WriteBytes(msg) + if err != nil { + return msgp.WrapError(err, "MetaStruct", key) + } + } + + return nil +} + +// DecodeMsg transforms the map[string][]byte agent-side into a map[string]any where values are sub-messages in messagepack +func (m *metaStructMap) DecodeMsg(de *msgp.Reader) error { + header, err := de.ReadMapHeader() + if err != nil { + return msgp.WrapError(err, "MetaStruct") + } + + *m = make(metaStructMap, header) + for i := uint32(0); i < header; i++ { + var key string + key, err = de.ReadString() + if err != nil { + return msgp.WrapError(err, "MetaStruct") + } + + subMsg, err := de.ReadBytes(nil) + if err != nil { + return msgp.WrapError(err, "MetaStruct", key) + } + + (*m)[key], _, err = msgp.ReadIntfBytes(subMsg) + if err != nil { + return msgp.WrapError(err, "MetaStruct", key) + } + } + + return nil +} + +// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message +func (m *metaStructMap) Msgsize() int { + size := msgp.MapHeaderSize + for key, value := range *m { + size += msgp.StringPrefixSize + len(key) + size += msgp.BytesPrefixSize + msgp.GuessSize(value) + } + return size +} diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/option.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/option.go index 7f974d614..0c787261f 100644 --- a/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/option.go +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/option.go @@ -15,20 +15,23 @@ import ( "net/url" "os" "path/filepath" - "regexp" "runtime" "runtime/debug" "strconv" "strings" "time" + "golang.org/x/mod/semver" + "gopkg.in/DataDog/dd-trace-go.v1/ddtrace" "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/ext" "gopkg.in/DataDog/dd-trace-go.v1/internal" + "gopkg.in/DataDog/dd-trace-go.v1/internal/civisibility/constants" "gopkg.in/DataDog/dd-trace-go.v1/internal/globalconfig" "gopkg.in/DataDog/dd-trace-go.v1/internal/log" "gopkg.in/DataDog/dd-trace-go.v1/internal/namingschema" "gopkg.in/DataDog/dd-trace-go.v1/internal/normalizer" + "gopkg.in/DataDog/dd-trace-go.v1/internal/telemetry" "gopkg.in/DataDog/dd-trace-go.v1/internal/traceprof" "gopkg.in/DataDog/dd-trace-go.v1/internal/version" @@ -66,7 +69,6 @@ var contribIntegrations = map[string]struct { "github.com/gomodule/redigo": {"Redigo", false}, "google.golang.org/api": {"Google API", false}, "google.golang.org/grpc": {"gRPC", false}, - "google.golang.org/grpc/v12": {"gRPC v12", false}, "gopkg.in/jinzhu/gorm.v1": {"Gorm (gopkg)", false}, "github.com/gorilla/mux": {"Gorilla Mux", false}, "gorm.io/gorm.v1": {"Gorm v1", false}, @@ -94,13 +96,11 @@ var contribIntegrations = map[string]struct { "github.com/urfave/negroni": {"Negroni", false}, "github.com/valyala/fasthttp": {"FastHTTP", false}, "github.com/zenazn/goji": {"Goji", false}, + "log/slog": {"log/slog", false}, + "github.com/uptrace/bun": {"Bun", false}, } var ( - // defaultSocketAPM specifies the socket path to use for connecting to the trace-agent. - // Replaced in tests - defaultSocketAPM = "/var/run/datadog/apm.socket" - // defaultSocketDSD specifies the socket path to use for connecting to the statsd server. // Replaced in tests defaultSocketDSD = "/var/run/datadog/dsd.socket" @@ -166,6 +166,9 @@ type config struct { // transport specifies the Transport interface which will be used to send data to the agent. transport transport + // httpClientTimeout specifies the timeout for the HTTP client. + httpClientTimeout time.Duration + // propagator propagates span context cross-process propagator Propagator @@ -258,14 +261,21 @@ type config struct { // traceSampleRate holds the trace sample rate. traceSampleRate dynamicConfig[float64] + // traceSampleRules holds the trace sampling rules + traceSampleRules dynamicConfig[[]SamplingRule] + // headerAsTags holds the header as tags configuration. headerAsTags dynamicConfig[[]string] - contribStats bool - // dynamicInstrumentationEnabled controls if the target application can be modified by Dynamic Instrumentation or not. // Value from DD_DYNAMIC_INSTRUMENTATION_ENABLED, default false. dynamicInstrumentationEnabled bool + + // globalSampleRate holds sample rate read from environment variables. + globalSampleRate float64 + + // ciVisibilityEnabled controls if the tracer is loaded with CI Visibility mode. default false + ciVisibilityEnabled bool } // orchestrionConfig contains Orchestrion configuration. @@ -297,7 +307,24 @@ const partialFlushMinSpansDefault = 1000 func newConfig(opts ...StartOption) *config { c := new(config) c.sampler = NewAllSampler() + sampleRate := math.NaN() + if r := getDDorOtelConfig("sampleRate"); r != "" { + var err error + sampleRate, err = strconv.ParseFloat(r, 64) + if err != nil { + log.Warn("ignoring DD_TRACE_SAMPLE_RATE, error: %v", err) + sampleRate = math.NaN() + } else if sampleRate < 0.0 || sampleRate > 1.0 { + log.Warn("ignoring DD_TRACE_SAMPLE_RATE: out of range %f", sampleRate) + sampleRate = math.NaN() + } + } + c.globalSampleRate = sampleRate + c.httpClientTimeout = time.Second * 10 // 10 seconds + if v := os.Getenv("OTEL_LOGS_EXPORTER"); v != "" { + log.Warn("OTEL_LOGS_EXPORTER is not supported") + } if internal.BoolEnv("DD_TRACE_ANALYTICS_ENABLED", false) { globalconfig.SetAnalyticsRate(1.0) } @@ -319,7 +346,7 @@ func newConfig(opts ...StartOption) *config { return r == ',' || r == ' ' })...)(c) } - if v := os.Getenv("DD_SERVICE"); v != "" { + if v := getDDorOtelConfig("service"); v != "" { c.serviceName = v globalconfig.SetServiceName(v) } @@ -327,18 +354,22 @@ func newConfig(opts ...StartOption) *config { c.version = ver } if v := os.Getenv("DD_SERVICE_MAPPING"); v != "" { - internal.ForEachStringTag(v, func(key, val string) { WithServiceMapping(key, val)(c) }) + internal.ForEachStringTag(v, internal.DDTagsDelimiter, func(key, val string) { WithServiceMapping(key, val)(c) }) } c.headerAsTags = newDynamicConfig("trace_header_tags", nil, setHeaderTags, equalSlice[string]) if v := os.Getenv("DD_TRACE_HEADER_TAGS"); v != "" { - WithHeaderTags(strings.Split(v, ","))(c) + c.headerAsTags.update(strings.Split(v, ","), telemetry.OriginEnvVar) + // Required to ensure that the startup header tags are set on reset. + c.headerAsTags.startup = c.headerAsTags.current } - if v := os.Getenv("DD_TAGS"); v != "" { + if v := getDDorOtelConfig("resourceAttributes"); v != "" { tags := internal.ParseTagString(v) internal.CleanGitMetadataTags(tags) for key, val := range tags { WithGlobalTag(key, val)(c) } + // TODO: should we track the origin of these tags individually? + c.globalTags.cfgOrigin = telemetry.OriginEnvVar } if _, ok := os.LookupEnv("AWS_LAMBDA_FUNCTION_NAME"); ok { // AWS_LAMBDA_FUNCTION_NAME being set indicates that we're running in an AWS Lambda environment. @@ -346,13 +377,21 @@ func newConfig(opts ...StartOption) *config { c.logToStdout = true } c.logStartup = internal.BoolEnv("DD_TRACE_STARTUP_LOGS", true) - c.contribStats = internal.BoolEnv("DD_TRACE_CONTRIB_STATS_ENABLED", true) - c.runtimeMetrics = internal.BoolEnv("DD_RUNTIME_METRICS_ENABLED", false) - c.debug = internal.BoolEnv("DD_TRACE_DEBUG", false) - c.enabled = newDynamicConfig("tracing_enabled", internal.BoolEnv("DD_TRACE_ENABLED", true), func(b bool) bool { return true }, equal[bool]) + c.runtimeMetrics = internal.BoolVal(getDDorOtelConfig("metrics"), false) + c.debug = internal.BoolVal(getDDorOtelConfig("debugMode"), false) + c.enabled = newDynamicConfig("tracing_enabled", internal.BoolVal(getDDorOtelConfig("enabled"), true), func(b bool) bool { return true }, equal[bool]) + if _, ok := os.LookupEnv("DD_TRACE_ENABLED"); ok { + c.enabled.cfgOrigin = telemetry.OriginEnvVar + } c.profilerEndpoints = internal.BoolEnv(traceprof.EndpointEnvVar, true) c.profilerHotspots = internal.BoolEnv(traceprof.CodeHotspotsEnvVar, true) - c.enableHostnameDetection = internal.BoolEnv("DD_CLIENT_HOSTNAME_ENABLED", true) + if compatMode := os.Getenv("DD_TRACE_CLIENT_HOSTNAME_COMPAT"); compatMode != "" { + if semver.IsValid(compatMode) { + c.enableHostnameDetection = semver.Compare(semver.MajorMinor(compatMode), "v1.66") <= 0 + } else { + log.Warn("ignoring DD_TRACE_CLIENT_HOSTNAME_COMPAT, invalid version %q", compatMode) + } + } c.debugAbandonedSpans = internal.BoolEnv("DD_TRACE_DEBUG_ABANDONED_SPANS", false) if c.debugAbandonedSpans { c.spanTimeout = internal.DurationEnv("DD_TRACE_ABANDONED_SPAN_TIMEOUT", 10*time.Minute) @@ -394,29 +433,25 @@ func newConfig(opts ...StartOption) *config { } c.peerServiceMappings = make(map[string]string) if v := os.Getenv("DD_TRACE_PEER_SERVICE_MAPPING"); v != "" { - internal.ForEachStringTag(v, func(key, val string) { c.peerServiceMappings[key] = val }) + internal.ForEachStringTag(v, internal.DDTagsDelimiter, func(key, val string) { c.peerServiceMappings[key] = val }) } for _, fn := range opts { fn(c) } if c.agentURL == nil { - c.agentURL = resolveAgentAddr() - if url := internal.AgentURLFromEnv(); url != nil { - c.agentURL = url - } + c.agentURL = internal.AgentURLFromEnv() } if c.agentURL.Scheme == "unix" { // If we're connecting over UDS we can just rely on the agent to provide the hostname log.Debug("connecting to agent over unix, do not set hostname on any traces") - c.enableHostnameDetection = false - c.httpClient = udsClient(c.agentURL.Path) + c.httpClient = udsClient(c.agentURL.Path, c.httpClientTimeout) c.agentURL = &url.URL{ Scheme: "http", Host: fmt.Sprintf("UDS_%s", strings.NewReplacer(":", "_", "/", "_", `\`, "_").Replace(c.agentURL.Path)), } } else if c.httpClient == nil { - c.httpClient = defaultClient + c.httpClient = defaultHTTPClient(c.httpClientTimeout) } WithGlobalTag(ext.RuntimeID, globalconfig.RuntimeID())(c) globalTags := c.globalTags.get() @@ -470,7 +505,10 @@ func newConfig(opts ...StartOption) *config { if c.debug { log.SetLevel(log.LevelDebug) } - c.agent = loadAgentFeatures(c.logToStdout, c.agentURL, c.httpClient) + + // if using stdout or traces are disabled, agent is disabled + agentDisabled := c.logToStdout || !c.enabled.current + c.agent = loadAgentFeatures(agentDisabled, c.agentURL, c.httpClient) info, ok := debug.ReadBuildInfo() if !ok { c.loadContribIntegrations([]*debug.Module{}) @@ -497,11 +535,21 @@ func newConfig(opts ...StartOption) *config { } // not a valid TCP address, leave it as it is (could be a socket connection) } + globalconfig.SetDogstatsdAddr(addr) c.dogstatsdAddr = addr } // Re-initialize the globalTags config with the value constructed from the environment and start options // This allows persisting the initial value of globalTags for future resets and updates. - c.initGlobalTags(c.globalTags.get()) + globalTagsOrigin := c.globalTags.cfgOrigin + c.initGlobalTags(c.globalTags.get(), globalTagsOrigin) + + // Check if CI Visibility mode is enabled + if internal.BoolEnv(constants.CIVisibilityEnabledEnvironmentVariable, false) { + c.ciVisibilityEnabled = true // Enable CI Visibility mode + c.httpClientTimeout = time.Second * 45 // Increase timeout up to 45 seconds (same as other tracers in CIVis mode) + c.logStartup = false // If we are in CI Visibility mode we don't want to log the startup to stdout to avoid polluting the output + c.transport = newCiVisibilityTransport(c) // Replace the default transport with the CI Visibility transport + } return c } @@ -510,25 +558,14 @@ func newStatsdClient(c *config) (internal.StatsdClient, error) { if c.statsdClient != nil { return c.statsdClient, nil } - - client, err := statsd.New(c.dogstatsdAddr, statsd.WithMaxMessagesPerPayload(40), statsd.WithTags(statsTags(c))) - if err != nil { - return &statsd.NoOpClient{}, err - } - return client, nil -} - -// defaultHTTPClient returns the default http.Client to start the tracer with. -func defaultHTTPClient() *http.Client { - if _, err := os.Stat(defaultSocketAPM); err == nil { - // we have the UDS socket file, use it - return udsClient(defaultSocketAPM) - } - return defaultClient + return internal.NewStatsdClient(c.dogstatsdAddr, statsTags(c)) } // udsClient returns a new http.Client which connects using the given UDS socket path. -func udsClient(socketPath string) *http.Client { +func udsClient(socketPath string, timeout time.Duration) *http.Client { + if timeout == 0 { + timeout = defaultHTTPTimeout + } return &http.Client{ Transport: &http.Transport{ Proxy: http.ProxyFromEnvironment, @@ -543,7 +580,7 @@ func udsClient(socketPath string) *http.Client { TLSHandshakeTimeout: 10 * time.Second, ExpectContinueTimeout: 1 * time.Second, }, - Timeout: defaultHTTPTimeout, + Timeout: timeout, } } @@ -582,10 +619,6 @@ type agentFeatures struct { // the /v0.6/stats endpoint. Stats bool - // DataStreams reports whether the agent can receive data streams stats on - // the /v0.1/pipeline_stats endpoint. - DataStreams bool - // StatsdPort specifies the Dogstatsd port as provided by the agent. // If it's the default, it will be 0, which means 8125. StatsdPort int @@ -602,8 +635,8 @@ func (a *agentFeatures) HasFlag(feat string) bool { // loadAgentFeatures queries the trace-agent for its capabilities and updates // the tracer's behaviour. -func loadAgentFeatures(logToStdout bool, agentURL *url.URL, httpClient *http.Client) (features agentFeatures) { - if logToStdout { +func loadAgentFeatures(agentDisabled bool, agentURL *url.URL, httpClient *http.Client) (features agentFeatures) { + if agentDisabled { // there is no agent; all features off return } @@ -634,8 +667,6 @@ func loadAgentFeatures(logToStdout bool, agentURL *url.URL, httpClient *http.Cli switch endpoint { case "/v0.6/stats": features.Stats = true - case "/v0.1/pipeline_stats": - features.DataStreams = true } } features.featureFlags = make(map[string]struct{}, len(info.FeatureFlags)) @@ -665,23 +696,6 @@ func (c *config) loadContribIntegrations(deps []*debug.Module) { } for _, d := range deps { p := d.Path - // special use case, since gRPC does not update version number - if p == "google.golang.org/grpc" { - re := regexp.MustCompile(`v(\d.\d)\d*`) - match := re.FindStringSubmatch(d.Version) - if match == nil { - log.Warn("Unable to parse version of GRPC %v", d.Version) - continue - } - ver, err := strconv.ParseFloat(match[1], 32) - if err != nil { - log.Warn("Unable to parse version of GRPC %v as a float", d.Version) - continue - } - if ver <= 1.2 { - p = p + "/v12" - } - } s, ok := contribIntegrations[p] if !ok { continue @@ -705,12 +719,8 @@ func (c *config) canDropP0s() bool { func statsTags(c *config) []string { tags := []string{ "lang:go", - "version:" + version.Tag, "lang_version:" + runtime.Version(), } - if c.serviceName != "" { - tags = append(tags, "service:"+c.serviceName) - } if c.env != "" { tags = append(tags, "env:"+c.env) } @@ -722,6 +732,11 @@ func statsTags(c *config) []string { tags = append(tags, k+":"+vstr) } } + globalconfig.SetStatsTags(tags) + tags = append(tags, "tracer_version:"+version.Tag) + if c.serviceName != "" { + tags = append(tags, "service:"+c.serviceName) + } return tags } @@ -851,6 +866,13 @@ func WithAgentAddr(addr string) StartOption { } } +// WithAgentTimeout sets the timeout for the agent connection. Timeout is in seconds. +func WithAgentTimeout(timeout int) StartOption { + return func(c *config) { + c.httpClientTimeout = time.Duration(timeout) * time.Second + } +} + // WithEnv sets the environment to which all traces started by the tracer will be submitted. // The default value is the environment variable DD_ENV, if it is set. func WithEnv(env string) StartOption { @@ -871,8 +893,8 @@ func WithServiceMapping(from, to string) StartOption { } // WithPeerServiceDefaults sets default calculation for peer.service. +// Related documentation: https://docs.datadoghq.com/tracing/guide/inferred-service-opt-in/?tab=go#apm-tracer-configuration func WithPeerServiceDefaults(enabled bool) StartOption { - // TODO: add link to public docs return func(c *config) { c.peerServiceDefaultsEnabled = enabled } @@ -893,7 +915,7 @@ func WithPeerServiceMapping(from, to string) StartOption { func WithGlobalTag(k string, v interface{}) StartOption { return func(c *config) { if c.globalTags.get() == nil { - c.initGlobalTags(map[string]interface{}{}) + c.initGlobalTags(map[string]interface{}{}, telemetry.OriginDefault) } c.globalTags.Lock() defer c.globalTags.Unlock() @@ -902,13 +924,14 @@ func WithGlobalTag(k string, v interface{}) StartOption { } // initGlobalTags initializes the globalTags config with the provided init value -func (c *config) initGlobalTags(init map[string]interface{}) { +func (c *config) initGlobalTags(init map[string]interface{}, origin telemetry.Origin) { apply := func(map[string]interface{}) bool { // always set the runtime ID on updates c.globalTags.current[ext.RuntimeID] = globalconfig.RuntimeID() return true } - c.globalTags = newDynamicConfig[map[string]interface{}]("trace_tags", init, apply, equalMap[string]) + c.globalTags = newDynamicConfig("trace_tags", init, apply, equalMap[string]) + c.globalTags.cfgOrigin = origin } // WithSampler sets the given sampler to be used with the tracer. By default @@ -986,6 +1009,7 @@ func WithRuntimeMetrics() StartOption { func WithDogstatsdAddress(addr string) StartOption { return func(cfg *config) { cfg.dogstatsdAddr = addr + globalconfig.SetDogstatsdAddr(addr) } } @@ -1265,24 +1289,16 @@ func WithHeaderTags(headerAsTags []string) StartOption { func setHeaderTags(headerAsTags []string) bool { globalconfig.ClearHeaderTags() for _, h := range headerAsTags { - if strings.HasPrefix(h, "x-datadog-") { + header, tag := normalizer.HeaderTag(h) + if len(header) == 0 || len(tag) == 0 { + log.Debug("Header-tag input is in unsupported format; dropping input value %v", h) continue } - header, tag := normalizer.HeaderTag(h) globalconfig.SetHeaderTag(header, tag) } return true } -// WithContribStats opens up a channel of communication between tracer and contrib libraries -// for submitting stats from contribs to Datadog via the tracer's statsd client -// It is enabled by default but can be disabled with `WithContribStats(false)` -func WithContribStats(enabled bool) StartOption { - return func(c *config) { - c.contribStats = enabled - } -} - // UserMonitoringConfig is used to configure what is used to identify a user. // This configuration can be set by combining one or several UserMonitoringOption with a call to SetUser(). type UserMonitoringConfig struct { diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/otel_dd_mappings.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/otel_dd_mappings.go new file mode 100644 index 000000000..1b17d8656 --- /dev/null +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/otel_dd_mappings.go @@ -0,0 +1,202 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2016 Datadog, Inc. +package tracer + +import ( + "fmt" + "os" + "strings" + + "gopkg.in/DataDog/dd-trace-go.v1/internal" + "gopkg.in/DataDog/dd-trace-go.v1/internal/log" + "gopkg.in/DataDog/dd-trace-go.v1/internal/telemetry" +) + +// otelDDEnv contains env vars from both dd (DD) and ot (OTEL) that map to the same tracer configuration +// remapper contains functionality to remap OTEL values to DD values +type otelDDEnv struct { + dd string + ot string + remapper func(string) (string, error) +} + +var otelDDConfigs = map[string]*otelDDEnv{ + "service": { + dd: "DD_SERVICE", + ot: "OTEL_SERVICE_NAME", + remapper: mapService, + }, + "metrics": { + dd: "DD_RUNTIME_METRICS_ENABLED", + ot: "OTEL_METRICS_EXPORTER", + remapper: mapMetrics, + }, + "debugMode": { + dd: "DD_TRACE_DEBUG", + ot: "OTEL_LOG_LEVEL", + remapper: mapLogLevel, + }, + "enabled": { + dd: "DD_TRACE_ENABLED", + ot: "OTEL_TRACES_EXPORTER", + remapper: mapEnabled, + }, + "sampleRate": { + dd: "DD_TRACE_SAMPLE_RATE", + ot: "OTEL_TRACES_SAMPLER", + remapper: mapSampleRate, + }, + "propagationStyle": { + dd: "DD_TRACE_PROPAGATION_STYLE", + ot: "OTEL_PROPAGATORS", + remapper: mapPropagationStyle, + }, + "resourceAttributes": { + dd: "DD_TAGS", + ot: "OTEL_RESOURCE_ATTRIBUTES", + remapper: mapDDTags, + }, +} + +var ddTagsMapping = map[string]string{ + "service.name": "service", + "deployment.environment": "env", + "service.version": "version", +} + +var unsupportedSamplerMapping = map[string]string{ + "always_on": "parentbased_always_on", + "always_off": "parentbased_always_off", + "traceidratio": "parentbased_traceidratio", +} + +var propagationMapping = map[string]string{ + "tracecontext": "tracecontext", + "b3": "b3 single header", + "b3multi": "b3multi", + "datadog": "datadog", + "none": "none", +} + +// getDDorOtelConfig determines whether the provided otelDDOpt will be set via DD or OTEL env vars, and returns the value +func getDDorOtelConfig(configName string) string { + config, ok := otelDDConfigs[configName] + if !ok { + panic(fmt.Sprintf("Programming Error: %v not found in supported configurations", configName)) + } + + val := os.Getenv(config.dd) + if otVal := os.Getenv(config.ot); otVal != "" { + ddPrefix := "config_datadog:" + otelPrefix := "config_opentelemetry:" + if val != "" { + log.Warn("Both %v and %v are set, using %v=%v", config.ot, config.dd, config.dd, val) + telemetryTags := []string{ddPrefix + strings.ToLower(config.dd), otelPrefix + strings.ToLower(config.ot)} + telemetry.GlobalClient.Count(telemetry.NamespaceTracers, "otel.env.hiding", 1.0, telemetryTags, true) + } else { + v, err := config.remapper(otVal) + if err != nil { + log.Warn(err.Error()) + telemetryTags := []string{ddPrefix + strings.ToLower(config.dd), otelPrefix + strings.ToLower(config.ot)} + telemetry.GlobalClient.Count(telemetry.NamespaceTracers, "otel.env.invalid", 1.0, telemetryTags, true) + } + val = v + } + } + return val +} + +// mapDDTags maps OTEL_RESOURCE_ATTRIBUTES to DD_TAGS +func mapDDTags(ot string) (string, error) { + ddTags := make([]string, 0) + internal.ForEachStringTag(ot, internal.OtelTagsDelimeter, func(key, val string) { + // replace otel delimiter with dd delimiter and normalize tag names + if ddkey, ok := ddTagsMapping[key]; ok { + // map reserved otel tag names to dd tag names + ddTags = append([]string{ddkey + internal.DDTagsDelimiter + val}, ddTags...) + } else { + ddTags = append(ddTags, key+internal.DDTagsDelimiter+val) + } + }) + + if len(ddTags) > 10 { + log.Warn("The following resource attributes have been dropped: %v. Only the first 10 resource attributes will be applied: %v", ddTags[10:], ddTags[:10]) + ddTags = ddTags[:10] + } + + return strings.Join(ddTags, ","), nil +} + +// mapService maps OTEL_SERVICE_NAME to DD_SERVICE +func mapService(ot string) (string, error) { + return ot, nil +} + +// mapMetrics maps OTEL_METRICS_EXPORTER to DD_RUNTIME_METRICS_ENABLED +func mapMetrics(ot string) (string, error) { + ot = strings.TrimSpace(strings.ToLower(ot)) + if ot == "none" { + return "false", nil + } + return "", fmt.Errorf("The following configuration is not supported: OTEL_METRICS_EXPORTER=%v", ot) +} + +// mapLogLevel maps OTEL_LOG_LEVEL to DD_TRACE_DEBUG +func mapLogLevel(ot string) (string, error) { + if strings.TrimSpace(strings.ToLower(ot)) == "debug" { + return "true", nil + } + return "", fmt.Errorf("The following configuration is not supported: OTEL_LOG_LEVEL=%v", ot) +} + +// mapEnabled maps OTEL_TRACES_EXPORTER to DD_TRACE_ENABLED +func mapEnabled(ot string) (string, error) { + if strings.TrimSpace(strings.ToLower(ot)) == "none" { + return "false", nil + } + return "", fmt.Errorf("The following configuration is not supported: OTEL_METRICS_EXPORTER=%v", ot) +} + +// mapSampleRate maps OTEL_TRACES_SAMPLER to DD_TRACE_SAMPLE_RATE +func otelTraceIDRatio() string { + if v := os.Getenv("OTEL_TRACES_SAMPLER_ARG"); v != "" { + return v + } + return "1.0" +} + +// mapSampleRate maps OTEL_TRACES_SAMPLER to DD_TRACE_SAMPLE_RATE +func mapSampleRate(ot string) (string, error) { + ot = strings.TrimSpace(strings.ToLower(ot)) + if v, ok := unsupportedSamplerMapping[ot]; ok { + log.Warn("The following configuration is not supported: OTEL_TRACES_SAMPLER=%v. %v will be used", ot, v) + ot = v + } + + var samplerMapping = map[string]string{ + "parentbased_always_on": "1.0", + "parentbased_always_off": "0.0", + "parentbased_traceidratio": otelTraceIDRatio(), + } + if v, ok := samplerMapping[ot]; ok { + return v, nil + } + return "", fmt.Errorf("unknown sampling configuration %v", ot) +} + +// mapPropagationStyle maps OTEL_PROPAGATORS to DD_TRACE_PROPAGATION_STYLE +func mapPropagationStyle(ot string) (string, error) { + ot = strings.TrimSpace(strings.ToLower(ot)) + supportedStyles := make([]string, 0) + for _, otStyle := range strings.Split(ot, ",") { + otStyle = strings.TrimSpace(otStyle) + if _, ok := propagationMapping[otStyle]; ok { + supportedStyles = append(supportedStyles, propagationMapping[otStyle]) + } else { + log.Warn("Invalid configuration: %v is not supported. This propagation style will be ignored.", otStyle) + } + } + return strings.Join(supportedStyles, ","), nil +} diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/rand.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/rand.go index ecedc3ed1..192a6725f 100644 --- a/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/rand.go +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/rand.go @@ -6,51 +6,14 @@ package tracer import ( - cryptorand "crypto/rand" "math" - "math/big" - "math/rand" - "sync" - "time" - - "gopkg.in/DataDog/dd-trace-go.v1/internal/log" + "math/rand/v2" ) -// random holds a thread-safe source of random numbers. -var random *rand.Rand - -func init() { - var seed int64 - n, err := cryptorand.Int(cryptorand.Reader, big.NewInt(math.MaxInt64)) - if err == nil { - seed = n.Int64() - } else { - log.Warn("cannot generate random seed: %v; using current time", err) - seed = time.Now().UnixNano() - } - random = rand.New(&safeSource{ - source: rand.NewSource(seed), - }) -} - -// safeSource holds a thread-safe implementation of rand.Source64. -type safeSource struct { - source rand.Source - sync.Mutex +func randUint64() uint64 { + return rand.Uint64() } -func (rs *safeSource) Int63() int64 { - rs.Lock() - n := rs.source.Int63() - rs.Unlock() - - return n -} - -func (rs *safeSource) Uint64() uint64 { return uint64(rs.Int63()) } - -func (rs *safeSource) Seed(seed int64) { - rs.Lock() - rs.source.Seed(seed) - rs.Unlock() +func generateSpanID(startTime int64) uint64 { + return rand.Uint64() & math.MaxInt64 } diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/remote_config.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/remote_config.go index f3a8abd39..bc317d6b8 100644 --- a/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/remote_config.go +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/remote_config.go @@ -8,8 +8,12 @@ package tracer import ( "encoding/json" "fmt" + "regexp" "strings" + "sync" + "time" + "gopkg.in/DataDog/dd-trace-go.v1/internal/globalconfig" "gopkg.in/DataDog/dd-trace-go.v1/internal/log" "gopkg.in/DataDog/dd-trace-go.v1/internal/remoteconfig" "gopkg.in/DataDog/dd-trace-go.v1/internal/telemetry" @@ -29,10 +33,70 @@ type target struct { } type libConfig struct { - Enabled *bool `json:"tracing_enabled,omitempty"` - SamplingRate *float64 `json:"tracing_sampling_rate,omitempty"` - HeaderTags *headerTags `json:"tracing_header_tags,omitempty"` - Tags *tags `json:"tracing_tags,omitempty"` + Enabled *bool `json:"tracing_enabled,omitempty"` + SamplingRate *float64 `json:"tracing_sampling_rate,omitempty"` + TraceSamplingRules *[]rcSamplingRule `json:"tracing_sampling_rules,omitempty"` + HeaderTags *headerTags `json:"tracing_header_tags,omitempty"` + Tags *tags `json:"tracing_tags,omitempty"` +} + +type rcTag struct { + Key string `json:"key"` + ValueGlob string `json:"value_glob"` +} + +// Sampling rules provided by the remote config define tags differently other than using a map. +type rcSamplingRule struct { + Service string `json:"service"` + Provenance provenance `json:"provenance"` + Name string `json:"name,omitempty"` + Resource string `json:"resource"` + Tags []rcTag `json:"tags,omitempty"` + SampleRate float64 `json:"sample_rate"` +} + +func convertRemoteSamplingRules(rules *[]rcSamplingRule) *[]SamplingRule { + if rules == nil { + return nil + } + var convertedRules []SamplingRule + for _, rule := range *rules { + if rule.Tags != nil && len(rule.Tags) != 0 { + tags := make(map[string]*regexp.Regexp, len(rule.Tags)) + tagsStrs := make(map[string]string, len(rule.Tags)) + for _, tag := range rule.Tags { + tags[tag.Key] = globMatch(tag.ValueGlob) + tagsStrs[tag.Key] = tag.ValueGlob + } + x := SamplingRule{ + Service: globMatch(rule.Service), + Name: globMatch(rule.Name), + Resource: globMatch(rule.Resource), + Rate: rule.SampleRate, + Tags: tags, + Provenance: rule.Provenance, + globRule: &jsonRule{ + Name: rule.Name, + Service: rule.Service, + Resource: rule.Resource, + Tags: tagsStrs, + }, + } + + convertedRules = append(convertedRules, x) + } else { + x := SamplingRule{ + Service: globMatch(rule.Service), + Name: globMatch(rule.Name), + Resource: globMatch(rule.Resource), + Rate: rule.SampleRate, + Provenance: rule.Provenance, + globRule: &jsonRule{Name: rule.Name, Service: rule.Service, Resource: rule.Resource}, + } + convertedRules = append(convertedRules, x) + } + } + return &convertedRules } type headerTags []headerTag @@ -76,25 +140,6 @@ func (t *tags) toMap() *map[string]interface{} { return &m } -func (t *tracer) dynamicInstrumentationRCUpdate(u remoteconfig.ProductUpdate) map[string]state.ApplyStatus { - - applyStatus := map[string]state.ApplyStatus{} - - for k, v := range u { - log.Debug("Received dynamic instrumentation RC configuration for %s\n", k) - applyStatus[k] = state.ApplyStatus{State: state.ApplyStateUnknown} - passFullConfiguration(k, string(v)) - } - - return applyStatus -} - -// passFullConfiguration is used as a stable interface to find the configuration in via bpf. Go-DI attaches -// a bpf program to this function and extracts the raw bytes accordingly. -// -//go:noinline -func passFullConfiguration(_, _ string) {} - // onRemoteConfigUpdate is a remote config callaback responsible for processing APM_TRACING RC-product updates. func (t *tracer) onRemoteConfigUpdate(u remoteconfig.ProductUpdate) map[string]state.ApplyStatus { statuses := map[string]state.ApplyStatus{} @@ -123,6 +168,10 @@ func (t *tracer) onRemoteConfigUpdate(u remoteconfig.ProductUpdate) map[string]s if updated { telemConfigs = append(telemConfigs, t.config.traceSampleRate.toTelemetry()) } + updated = t.config.traceSampleRules.reset() + if updated { + telemConfigs = append(telemConfigs, t.config.traceSampleRules.toTelemetry()) + } updated = t.config.headerAsTags.reset() if updated { telemConfigs = append(telemConfigs, t.config.headerAsTags.toTelemetry()) @@ -152,7 +201,11 @@ func (t *tracer) onRemoteConfigUpdate(u remoteconfig.ProductUpdate) map[string]s continue } if c.ServiceTarget.Service != t.config.serviceName { - log.Debug("Skipping config for service %s. Current service is %s", c.ServiceTarget.Service, t.config.serviceName) + log.Debug( + "Skipping config for service %s. Current service is %s", + c.ServiceTarget.Service, + t.config.serviceName, + ) statuses[path] = state.ApplyStatus{State: state.ApplyStateError, Error: "service mismatch"} continue } @@ -166,6 +219,10 @@ func (t *tracer) onRemoteConfigUpdate(u remoteconfig.ProductUpdate) map[string]s if updated { telemConfigs = append(telemConfigs, t.config.traceSampleRate.toTelemetry()) } + updated = t.config.traceSampleRules.handleRC(convertRemoteSamplingRules(c.LibConfig.TraceSamplingRules)) + if updated { + telemConfigs = append(telemConfigs, t.config.traceSampleRules.toTelemetry()) + } updated = t.config.headerAsTags.handleRC(c.LibConfig.HeaderTags.toSlice()) if updated { telemConfigs = append(telemConfigs, t.config.headerAsTags.toTelemetry()) @@ -191,6 +248,63 @@ func (t *tracer) onRemoteConfigUpdate(u remoteconfig.ProductUpdate) map[string]s return statuses } +type dynamicInstrumentationRCProbeConfig struct { + runtimeID string + configPath string + configContent string +} + +type dynamicInstrumentationRCState struct { + sync.Mutex + state map[string]dynamicInstrumentationRCProbeConfig +} + +var ( + diRCState dynamicInstrumentationRCState + initalizeRC sync.Once +) + +func (t *tracer) dynamicInstrumentationRCUpdate(u remoteconfig.ProductUpdate) map[string]state.ApplyStatus { + applyStatus := map[string]state.ApplyStatus{} + + diRCState.Lock() + for k, v := range u { + log.Debug("Received dynamic instrumentation RC configuration for %s\n", k) + applyStatus[k] = state.ApplyStatus{State: state.ApplyStateUnknown} + diRCState.state[k] = dynamicInstrumentationRCProbeConfig{ + runtimeID: globalconfig.RuntimeID(), + configPath: k, + configContent: string(v), + } + } + diRCState.Unlock() + return applyStatus +} + +// passProbeConfiguration is used as a stable interface to find the configuration in via bpf. Go-DI attaches +// a bpf program to this function and extracts the raw bytes accordingly. +// +//nolint:all +//go:noinline +func passProbeConfiguration(runtimeID, configPath, configContent string) {} + +func initalizeDynamicInstrumentationRemoteConfigState() { + diRCState = dynamicInstrumentationRCState{ + state: map[string]dynamicInstrumentationRCProbeConfig{}, + } + + go func() { + for { + time.Sleep(time.Second * 5) + diRCState.Lock() + for _, v := range diRCState.state { + passProbeConfiguration(v.runtimeID, v.configPath, v.configContent) + } + diRCState.Unlock() + } + }() +} + // startRemoteConfig starts the remote config client. // It registers the APM_TRACING product with a callback, // and the LIVE_DEBUGGING product without a callback. @@ -206,6 +320,8 @@ func (t *tracer) startRemoteConfig(rcConfig remoteconfig.ClientConfig) error { dynamicInstrumentationError = remoteconfig.Subscribe("LIVE_DEBUGGING", t.dynamicInstrumentationRCUpdate) } + initalizeRC.Do(initalizeDynamicInstrumentationRemoteConfigState) + apmTracingError = remoteconfig.Subscribe( state.ProductAPMTracing, t.onRemoteConfigUpdate, @@ -213,6 +329,7 @@ func (t *tracer) startRemoteConfig(rcConfig remoteconfig.ClientConfig) error { remoteconfig.APMTracingHTTPHeaderTags, remoteconfig.APMTracingCustomTags, remoteconfig.APMTracingEnabled, + remoteconfig.APMTracingSampleRules, ) if apmTracingError != nil || dynamicInstrumentationError != nil { diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/rules_sampler.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/rules_sampler.go index 85b8d9cf5..037e39364 100644 --- a/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/rules_sampler.go +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/rules_sampler.go @@ -19,6 +19,7 @@ import ( "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/ext" "gopkg.in/DataDog/dd-trace-go.v1/internal/log" "gopkg.in/DataDog/dd-trace-go.v1/internal/samplernames" + "gopkg.in/DataDog/dd-trace-go.v1/internal/telemetry" "golang.org/x/time/rate" ) @@ -54,6 +55,54 @@ func (r *rulesSampler) HasSpanRules() bool { return r.spans.enabled() } func (r *rulesSampler) TraceRateLimit() (float64, bool) { return r.traces.limit() } +type provenance int32 + +const ( + Local provenance = iota + Customer provenance = 1 + Dynamic provenance = 2 +) + +var provenances = []provenance{Local, Customer, Dynamic} + +func (p provenance) String() string { + switch p { + case Local: + return "local" + case Customer: + return "customer" + case Dynamic: + return "dynamic" + default: + return "" + } +} + +func (p provenance) MarshalJSON() ([]byte, error) { + return json.Marshal(p.String()) +} + +func (p *provenance) UnmarshalJSON(data []byte) error { + var prov string + var err error + if err = json.Unmarshal(data, &prov); err != nil { + return err + } + if *p, err = parseProvenance(prov); err != nil { + return err + } + return nil +} + +func parseProvenance(p string) (provenance, error) { + for _, v := range provenances { + if strings.EqualFold(strings.TrimSpace(strings.ToLower(p)), v.String()) { + return v, nil + } + } + return Customer, fmt.Errorf("Invalid Provenance: \"%v\"", p) +} + // SamplingRule is used for applying sampling rates to spans that match // the service name, operation name or both. // For basic usage, consider using the helper functions ServiceRule, NameRule, etc. @@ -78,8 +127,48 @@ type SamplingRule struct { // Tags specifies the map of key-value patterns that span tags must match. Tags map[string]*regexp.Regexp + Provenance provenance + ruleType SamplingRuleType limiter *rateLimiter + + globRule *jsonRule +} + +// Poor-man's comparison of two regex for equality without resorting to fancy symbolic computation. +// The result is false negative: whenever the function returns true, we know the two regex must be +// equal. The reverse is not true. Two regex can be equivalent while reported as not. +// This is good for use as an indication of optimization that applies when two regex are equals. +func regexEqualsFalseNegative(a, b *regexp.Regexp) bool { + if (a == nil) != (b == nil) { + return false + } + if a == nil { + return true + } + return a.String() == b.String() +} + +func (sr *SamplingRule) EqualsFalseNegative(other *SamplingRule) bool { + if (sr == nil) != (other == nil) { + return false + } + if sr == nil { + return true + } + if sr.Rate != other.Rate || sr.ruleType != other.ruleType || + !regexEqualsFalseNegative(sr.Service, other.Service) || + !regexEqualsFalseNegative(sr.Name, other.Name) || + !regexEqualsFalseNegative(sr.Resource, other.Resource) || + len(sr.Tags) != len(other.Tags) { + return false + } + for k, v := range sr.Tags { + if vo, ok := other.Tags[k]; !ok || !regexEqualsFalseNegative(v, vo) { + return false + } + } + return true } // match returns true when the span's details match all the expected values in the rule. @@ -95,11 +184,24 @@ func (sr *SamplingRule) match(s *span) bool { } s.Lock() defer s.Unlock() - if sr.Tags != nil && s.Meta != nil { + if sr.Tags != nil { for k, regex := range sr.Tags { - v, ok := s.Meta[k] - if !ok || !regex.MatchString(v) { - return false + if regex == nil { + continue + } + if s.Meta != nil { + v, ok := s.Meta[k] + if ok && regex.MatchString(v) { + continue + } + } + if s.Metrics != nil { + v, ok := s.Metrics[k] + // sampling on numbers with floating point is not supported, + // thus 'math.Floor(v) != v' + if !ok || math.Floor(v) != v || !regex.MatchString(strconv.FormatFloat(v, 'g', -1, 64)) { + return false + } } } } @@ -143,6 +245,7 @@ func ServiceRule(service string, rate float64) SamplingRule { Service: globMatch(service), ruleType: SamplingRuleTrace, Rate: rate, + globRule: &jsonRule{Service: service}, } } @@ -153,6 +256,7 @@ func NameRule(name string, rate float64) SamplingRule { Name: globMatch(name), ruleType: SamplingRuleTrace, Rate: rate, + globRule: &jsonRule{Name: name}, } } @@ -163,6 +267,7 @@ func NameServiceRule(name string, service string, rate float64) SamplingRule { Service: globMatch(service), Name: globMatch(name), ruleType: SamplingRuleTrace, + globRule: &jsonRule{Name: name, Service: service}, Rate: rate, } } @@ -177,13 +282,20 @@ func RateRule(rate float64) SamplingRule { // TagsResourceRule returns a SamplingRule that applies the provided sampling rate to traces with spans that match // resource, name, service and tags provided. -func TagsResourceRule(tags map[string]*regexp.Regexp, resource, name, service string, rate float64) SamplingRule { +func TagsResourceRule(tags map[string]string, resource, name, service string, rate float64) SamplingRule { + globTags := make(map[string]*regexp.Regexp, len(tags)) + for k, v := range tags { + if g := globMatch(v); g != nil { + globTags[k] = g + } + } return SamplingRule{ Service: globMatch(service), Name: globMatch(name), Resource: globMatch(resource), Rate: rate, - Tags: tags, + Tags: globTags, + globRule: &jsonRule{Name: name, Service: service, Resource: resource, Tags: tags}, ruleType: SamplingRuleTrace, } } @@ -204,6 +316,7 @@ func SpanTagsResourceRule(tags map[string]string, resource, name, service string Rate: rate, Tags: globTags, ruleType: SamplingRuleSpan, + globRule: &jsonRule{Name: name, Service: service, Resource: resource, Tags: tags}, } } @@ -217,6 +330,7 @@ func SpanNameServiceRule(name, service string, rate float64) SamplingRule { Rate: rate, ruleType: SamplingRuleSpan, limiter: newSingleSpanRateLimiter(0), + globRule: &jsonRule{Name: name, Service: service}, } } @@ -232,6 +346,7 @@ func SpanNameServiceMPSRule(name, service string, rate, limit float64) SamplingR Rate: rate, ruleType: SamplingRuleSpan, limiter: newSingleSpanRateLimiter(limit), + globRule: &jsonRule{Name: name, Service: service}, } } @@ -266,32 +381,30 @@ func newTraceRulesSampler(rules []SamplingRule, traceSampleRate float64) *traceR } } -// globalSampleRate returns the sampling rate found in the DD_TRACE_SAMPLE_RATE environment variable. -// If it is invalid or not within the 0-1 range, NaN is returned. -func globalSampleRate() float64 { - defaultRate := math.NaN() - v := os.Getenv("DD_TRACE_SAMPLE_RATE") - if v == "" { - return defaultRate - } - r, err := strconv.ParseFloat(v, 64) - if err != nil { - log.Warn("ignoring DD_TRACE_SAMPLE_RATE: error: %v", err) - return defaultRate - } - if r >= 0.0 && r <= 1.0 { - return r - } - log.Warn("ignoring DD_TRACE_SAMPLE_RATE: out of range %f", r) - return defaultRate -} - func (rs *traceRulesSampler) enabled() bool { rs.m.RLock() defer rs.m.RUnlock() return len(rs.rules) > 0 || !math.IsNaN(rs.globalRate) } +// Tests whether two sets of the rules are the same. +// This returns result that can be false negative. If the result is true, then the two sets of rules +// are guaranteed to be the same. +// On the other hand, false can be returned while the two rulesets are logically the same. +// This function can be used to detect optimization opportunities when two rulesets are the same. +// For example, an update of one ruleset is not needed if it's the same as the previous one. +func EqualsFalseNegative(a, b []SamplingRule) bool { + if len(a) != len(b) { + return false + } + for i, r := range a { + if !r.EqualsFalseNegative(&b[i]) { + return false + } + } + return true +} + // setGlobalSampleRate sets the global sample rate to the given value. // Returns whether the value was changed or not. func (rs *traceRulesSampler) setGlobalSampleRate(rate float64) bool { @@ -313,6 +426,15 @@ func (rs *traceRulesSampler) setGlobalSampleRate(rate float64) bool { return true } +// Assumes the new rules are different from the old rules. +func (rs *traceRulesSampler) setTraceSampleRules(rules []SamplingRule) bool { + if EqualsFalseNegative(rs.rules, rules) { + return false + } + rs.rules = rules + return true +} + // sampleGlobalRate applies the global trace sampling rate to the span. If the rate is Nan, // the function return false, then it returns false and the span is not // modified. @@ -330,7 +452,13 @@ func (rs *traceRulesSampler) sampleGlobalRate(span *span) bool { return false } - rs.applyRate(span, rate, time.Now()) + // global rate is a degenerated case of rule rate. + // Technically speaking, global rate also has two possible provenance: local or remote. + // We just apply the the sampler name corresponding to local rule rate because global rate is + // being deprecated in favor of sampling rules. + // Note that this just preserves an existing behavior even though it is not correct. + sampler := samplernames.RuleRate + rs.applyRate(span, rate, time.Now(), sampler) return true } @@ -347,10 +475,16 @@ func (rs *traceRulesSampler) sampleRules(span *span) bool { rs.m.RLock() rate := rs.globalRate rs.m.RUnlock() + sampler := samplernames.RuleRate for _, rule := range rs.rules { if rule.match(span) { matched = true rate = rule.Rate + if rule.Provenance == Customer { + sampler = samplernames.RemoteUserRule + } else if rule.Provenance == Dynamic { + sampler = samplernames.RemoteDynamicRule + } break } } @@ -360,24 +494,28 @@ func (rs *traceRulesSampler) sampleRules(span *span) bool { return false } - rs.applyRate(span, rate, time.Now()) + rs.applyRate(span, rate, time.Now(), sampler) return true } -func (rs *traceRulesSampler) applyRate(span *span, rate float64, now time.Time) { - span.SetTag(keyRulesSamplerAppliedRate, rate) +func (rs *traceRulesSampler) applyRate(span *span, rate float64, now time.Time, sampler samplernames.SamplerName) { + span.Lock() + defer span.Unlock() + + span.setMetric(keyRulesSamplerAppliedRate, rate) + delete(span.Metrics, keySamplingPriorityRate) if !sampledByRate(span.TraceID, rate) { - span.setSamplingPriority(ext.PriorityUserReject, samplernames.RuleRate) + span.setSamplingPriorityLocked(ext.PriorityUserReject, sampler) return } sampled, rate := rs.limiter.allowOne(now) if sampled { - span.setSamplingPriority(ext.PriorityUserKeep, samplernames.RuleRate) + span.setSamplingPriorityLocked(ext.PriorityUserKeep, sampler) } else { - span.setSamplingPriority(ext.PriorityUserReject, samplernames.RuleRate) + span.setSamplingPriorityLocked(ext.PriorityUserReject, sampler) } - span.SetTag(keyRulesSamplerLimiterRate, rate) + span.setMetric(keyRulesSamplerLimiterRate, rate) } // limit returns the rate limit set in the rules sampler, controlled by DD_TRACE_RATE_LIMIT, and @@ -396,6 +534,7 @@ const defaultRateLimit = 100.0 // The limit is DD_TRACE_RATE_LIMIT if set, `defaultRateLimit` otherwise. func newRateLimiter() *rateLimiter { limit := defaultRateLimit + origin := telemetry.OriginDefault v := os.Getenv("DD_TRACE_RATE_LIMIT") if v != "" { l, err := strconv.ParseFloat(v, 64) @@ -405,9 +544,11 @@ func newRateLimiter() *rateLimiter { log.Warn("DD_TRACE_RATE_LIMIT negative, using default value %f", limit) } else { // override the default limit + origin = telemetry.OriginEnvVar limit = l } } + reportTelemetryOnAppStarted(telemetry.Configuration{Name: "trace_rate_limit", Value: limit, Origin: origin}) return &rateLimiter{ limiter: rate.NewLimiter(rate.Limit(limit), int(math.Ceil(limit))), prevTime: time.Now(), @@ -461,6 +602,7 @@ func (rs *singleSpanRulesSampler) apply(span *span) bool { return false } } + delete(span.Metrics, keySamplingPriorityRate) span.setMetric(keySpanSamplingMechanism, float64(samplernames.SingleSpan)) span.setMetric(keySingleSpanSamplingRuleRate, rate) if rule.MaxPerSecond != 0 { @@ -533,7 +675,7 @@ func newSingleSpanRateLimiter(mps float64) *rateLimiter { // globMatch compiles pattern string into glob format, i.e. regular expressions with only '?' // and '*' treated as regex metacharacters. func globMatch(pattern string) *regexp.Regexp { - if pattern == "" { + if pattern == "" || pattern == "*" { return nil } // escaping regex characters @@ -542,7 +684,7 @@ func globMatch(pattern string) *regexp.Regexp { pattern = strings.Replace(pattern, "\\?", ".", -1) pattern = strings.Replace(pattern, "\\*", ".*", -1) // pattern must match an entire string - return regexp.MustCompile(fmt.Sprintf("^%s$", pattern)) + return regexp.MustCompile(fmt.Sprintf("(?i)^%s$", pattern)) } // samplingRulesFromEnv parses sampling rules from @@ -619,6 +761,7 @@ type jsonRule struct { Resource string `json:"resource"` Tags map[string]string `json:"tags"` Type *SamplingRuleType `json:"type,omitempty"` + Provenance provenance `json:"provenance,omitempty"` } func (j jsonRule) String() string { @@ -644,6 +787,9 @@ func (j jsonRule) String() string { if j.Type != nil { s = append(s, fmt.Sprintf("Type: %v", *j.Type)) } + if j.Provenance != Local { + s = append(s, fmt.Sprintf("Provenance: %v", j.Provenance.String())) + } return fmt.Sprintf("{%s}", strings.Join(s, " ")) } @@ -678,7 +824,10 @@ func validateRules(jsonRules []jsonRule, spanType SamplingRuleType) ([]SamplingR continue } if rate < 0.0 || rate > 1.0 { - errs = append(errs, fmt.Sprintf("at index %d: ignoring rule %s: rate is out of [0.0, 1.0] range", i, v.String())) + errs = append( + errs, + fmt.Sprintf("at index %d: ignoring rule %s: rate is out of [0.0, 1.0] range", i, v.String()), + ) continue } tagGlobs := make(map[string]*regexp.Regexp, len(v.Tags)) @@ -692,8 +841,10 @@ func validateRules(jsonRules []jsonRule, spanType SamplingRuleType) ([]SamplingR MaxPerSecond: v.MaxPerSecond, Resource: globMatch(v.Resource), Tags: tagGlobs, + Provenance: v.Provenance, ruleType: spanType, limiter: newSingleSpanRateLimiter(v.MaxPerSecond), + globRule: &jsonRules[i], }) } if len(errs) != 0 { @@ -703,38 +854,52 @@ func validateRules(jsonRules []jsonRule, spanType SamplingRuleType) ([]SamplingR } // MarshalJSON implements the json.Marshaler interface. -func (sr *SamplingRule) MarshalJSON() ([]byte, error) { +func (sr SamplingRule) MarshalJSON() ([]byte, error) { s := struct { Service string `json:"service,omitempty"` Name string `json:"name,omitempty"` Resource string `json:"resource,omitempty"` Rate float64 `json:"sample_rate"` Tags map[string]string `json:"tags,omitempty"` - Type *string `json:"type,omitempty"` MaxPerSecond *float64 `json:"max_per_second,omitempty"` + Provenance string `json:"provenance,omitempty"` }{} - if sr.Service != nil { - s.Service = sr.Service.String() - } - if sr.Name != nil { - s.Name = sr.Name.String() + if sr.globRule != nil { + s.Service = sr.globRule.Service + s.Name = sr.globRule.Name + s.Resource = sr.globRule.Resource + s.Tags = sr.globRule.Tags + } else { + if sr.Service != nil { + s.Service = sr.Service.String() + } + if sr.Name != nil { + s.Name = sr.Name.String() + } + if sr.Resource != nil { + s.Resource = sr.Resource.String() + } + s.Tags = make(map[string]string, len(sr.Tags)) + for k, v := range sr.Tags { + if v != nil { + s.Tags[k] = v.String() + } + } } if sr.MaxPerSecond != 0 { s.MaxPerSecond = &sr.MaxPerSecond } - if sr.Resource != nil { - s.Resource = sr.Resource.String() - } s.Rate = sr.Rate - if v := sr.ruleType.String(); v != "" { - t := fmt.Sprintf("%v(%d)", v, sr.ruleType) - s.Type = &t - } - s.Tags = make(map[string]string, len(sr.Tags)) - for k, v := range sr.Tags { - if v != nil { - s.Tags[k] = v.String() - } + if sr.Provenance != Local { + s.Provenance = sr.Provenance.String() } return json.Marshal(&s) } + +func (sr SamplingRule) String() string { + s, err := sr.MarshalJSON() + if err != nil { + log.Error("Error marshalling SamplingRule to json: %v", err) + } + return string(s) +} diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/span.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/span.go index 574f7ce3c..c37af7d5c 100644 --- a/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/span.go +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/span.go @@ -29,6 +29,7 @@ import ( sharedinternal "gopkg.in/DataDog/dd-trace-go.v1/internal" "gopkg.in/DataDog/dd-trace-go.v1/internal/globalconfig" "gopkg.in/DataDog/dd-trace-go.v1/internal/log" + "gopkg.in/DataDog/dd-trace-go.v1/internal/orchestrion" "gopkg.in/DataDog/dd-trace-go.v1/internal/samplernames" "gopkg.in/DataDog/dd-trace-go.v1/internal/traceprof" @@ -64,19 +65,20 @@ type errorConfig struct { type span struct { sync.RWMutex `msg:"-"` // all fields are protected by this RWMutex - Name string `msg:"name"` // operation name - Service string `msg:"service"` // service name (i.e. "grpc.server", "http.request") - Resource string `msg:"resource"` // resource name (i.e. "/user?id=123", "SELECT * FROM users") - Type string `msg:"type"` // protocol associated with the span (i.e. "web", "db", "cache") - Start int64 `msg:"start"` // span start time expressed in nanoseconds since epoch - Duration int64 `msg:"duration"` // duration of the span expressed in nanoseconds - Meta map[string]string `msg:"meta,omitempty"` // arbitrary map of metadata - Metrics map[string]float64 `msg:"metrics,omitempty"` // arbitrary map of numeric metrics - SpanID uint64 `msg:"span_id"` // identifier of this span - TraceID uint64 `msg:"trace_id"` // lower 64-bits of the root span identifier - ParentID uint64 `msg:"parent_id"` // identifier of the span's direct parent - Error int32 `msg:"error"` // error status of the span; 0 means no errors - SpanLinks []ddtrace.SpanLink `msg:"span_links"` // links to other spans + Name string `msg:"name"` // operation name + Service string `msg:"service"` // service name (i.e. "grpc.server", "http.request") + Resource string `msg:"resource"` // resource name (i.e. "/user?id=123", "SELECT * FROM users") + Type string `msg:"type"` // protocol associated with the span (i.e. "web", "db", "cache") + Start int64 `msg:"start"` // span start time expressed in nanoseconds since epoch + Duration int64 `msg:"duration"` // duration of the span expressed in nanoseconds + Meta map[string]string `msg:"meta,omitempty"` // arbitrary map of metadata + MetaStruct metaStructMap `msg:"meta_struct,omitempty"` // arbitrary map of metadata with structured values + Metrics map[string]float64 `msg:"metrics,omitempty"` // arbitrary map of numeric metrics + SpanID uint64 `msg:"span_id"` // identifier of this span + TraceID uint64 `msg:"trace_id"` // lower 64-bits of the root span identifier + ParentID uint64 `msg:"parent_id"` // identifier of the span's direct parent + Error int32 `msg:"error"` // error status of the span; 0 means no errors + SpanLinks []ddtrace.SpanLink `msg:"span_links"` // links to other spans goExecTraced bool `msg:"-"` noDebugStack bool `msg:"-"` // disables debug stack traces @@ -109,6 +111,9 @@ func (s *span) BaggageItem(key string) string { // SetTag adds a set of key/value metadata to the span. func (s *span) SetTag(key string, value interface{}) { + // To avoid dumping the memory address in case value is a pointer, we dereference it. + // Any pointer value that is a pointer to a pointer will be dumped as a string. + value = dereference(value) s.Lock() defer s.Unlock() // We don't lock spans when flushing, so we could have a data race when @@ -162,6 +167,7 @@ func (s *span) SetTag(key string, value interface{}) { s.setMeta(key, v.String()) return } + if value != nil { // Arrays will be translated to dot notation. e.g. // {"myarr.0": "foo", "myarr.1": "bar"} @@ -180,7 +186,15 @@ func (s *span) SetTag(key string, value interface{}) { } return } + + // Can be sent as messagepack in `meta_struct` instead of `meta` + // reserved for internal use only + if v, ok := value.(sharedinternal.MetaStructValue); ok { + s.setMetaStruct(key, v.Value) + return + } } + // not numeric, not a string, not a fmt.Stringer, not a bool, and not an error s.setMeta(key, fmt.Sprint(value)) } @@ -390,6 +404,13 @@ func (s *span) setMeta(key, v string) { } } +func (s *span) setMetaStruct(key string, v any) { + if s.MetaStruct == nil { + s.MetaStruct = make(metaStructMap, 1) + } + s.MetaStruct[key] = v +} + // setTagBool sets a boolean tag on the span. func (s *span) setTagBool(key string, v bool) { switch key { @@ -461,9 +482,7 @@ func (s *span) Finish(opts ...ddtrace.FinishOption) { s.Unlock() } } - if s.taskEnd != nil { - s.taskEnd() - } + if s.goExecTraced && rt.IsEnabled() { // Only tag spans as traced if they both started & ended with // execution tracing enabled. This is technically not sufficient @@ -481,19 +500,16 @@ func (s *span) Finish(opts ...ddtrace.FinishOption) { s.SetTag("go_execution_traced", "partial") } - if tr, ok := internal.GetGlobalTracer().(*tracer); ok && tr.rulesSampling.traces.enabled() { - if !s.context.trace.isLocked() { - tr.rulesSampling.SampleTrace(s) + if s.root() == s { + if tr, ok := internal.GetGlobalTracer().(*tracer); ok && tr.rulesSampling.traces.enabled() { + if !s.context.trace.isLocked() && s.context.trace.propagatingTag(keyDecisionMaker) != "-4" { + tr.rulesSampling.SampleTrace(s) + } } } s.finish(t) - - if s.pprofCtxRestore != nil { - // Restore the labels of the parent span so any CPU samples after this - // point are attributed correctly. - pprof.SetGoroutineLabels(s.pprofCtxRestore) - } + orchestrion.GLSPopValue(sharedinternal.ActiveSpanKey) } // SetOperationName sets or changes the operation name. @@ -526,6 +542,9 @@ func (s *span) finish(finishTime int64) { if s.Duration < 0 { s.Duration = 0 } + if s.taskEnd != nil { + s.taskEnd() + } keep := true if t, ok := internal.GetGlobalTracer().(*tracer); ok { @@ -566,6 +585,12 @@ func (s *span) finish(finishTime int64) { s, s.Name, s.Resource, s.Meta, s.Metrics) } s.context.finish() + + if s.pprofCtxRestore != nil { + // Restore the labels of the parent span so any CPU samples after this + // point are attributed correctly. + pprof.SetGoroutineLabels(s.pprofCtxRestore) + } } // newAggregableSpan creates a new summary for the span s, within an application @@ -577,13 +602,21 @@ func newAggregableSpan(s *span, obfuscator *obfuscate.Obfuscator) *aggregableSpa statusCode = uint32(c) } } + var isTraceRoot trilean + if s.ParentID == 0 { + isTraceRoot = trileanTrue + } else { + isTraceRoot = trileanFalse + } + key := aggregation{ - Name: s.Name, - Resource: obfuscatedResource(obfuscator, s.Type, s.Resource), - Service: s.Service, - Type: s.Type, - Synthetics: strings.HasPrefix(s.Meta[keyOrigin], "synthetics"), - StatusCode: statusCode, + Name: s.Name, + Resource: obfuscatedResource(obfuscator, s.Type, s.Resource), + Service: s.Service, + Type: s.Type, + Synthetics: strings.HasPrefix(s.Meta[keyOrigin], "synthetics"), + StatusCode: statusCode, + IsTraceRoot: isTraceRoot, } return &aggregableSpan{ key: key, @@ -720,6 +753,7 @@ const ( keyDecisionMaker = "_dd.p.dm" keyServiceHash = "_dd.dm.service_hash" keyOrigin = "_dd.origin" + keyReparentID = "_dd.parent_id" // keyHostname can be used to override the agent's hostname detection when using `WithHostname`. Not to be confused with keyTracerHostname // which is set via auto-detection. keyHostname = "_dd.hostname" diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/span_msgp.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/span_msgp.go index 219711387..c6cb8274a 100644 --- a/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/span_msgp.go +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/span_msgp.go @@ -181,6 +181,12 @@ func (z *span) DecodeMsg(dc *msgp.Reader) (err error) { } z.Meta[za0001] = za0002 } + case "meta_struct": + err = z.MetaStruct.DecodeMsg(dc) + if err != nil { + err = msgp.WrapError(err, "MetaStruct") + return + } case "metrics": var zb0003 uint32 zb0003, err = dc.ReadMapHeader() @@ -268,15 +274,16 @@ func (z *span) DecodeMsg(dc *msgp.Reader) (err error) { // EncodeMsg implements msgp.Encodable func (z *span) EncodeMsg(en *msgp.Writer) (err error) { // omitempty: check for empty values - zb0001Len := uint32(13) - var zb0001Mask uint16 /* 13 bits */ + zb0001Len := uint32(14) + var zb0001Mask uint16 /* 14 bits */ + _ = zb0001Mask if z.Meta == nil { zb0001Len-- zb0001Mask |= 0x40 } if z.Metrics == nil { zb0001Len-- - zb0001Mask |= 0x80 + zb0001Mask |= 0x100 } // variable map header, size zb0001Len err = en.Append(0x80 | uint8(zb0001Len)) @@ -370,7 +377,17 @@ func (z *span) EncodeMsg(en *msgp.Writer) (err error) { } } } - if (zb0001Mask & 0x80) == 0 { // if not empty + // write "meta_struct" + err = en.Append(0xab, 0x6d, 0x65, 0x74, 0x61, 0x5f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74) + if err != nil { + return + } + err = z.MetaStruct.EncodeMsg(en) + if err != nil { + err = msgp.WrapError(err, "MetaStruct") + return + } + if (zb0001Mask & 0x100) == 0 { // if not empty // write "metrics" err = en.Append(0xa7, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73) if err != nil { @@ -463,7 +480,7 @@ func (z *span) Msgsize() (s int) { s += msgp.StringPrefixSize + len(za0001) + msgp.StringPrefixSize + len(za0002) } } - s += 8 + msgp.MapHeaderSize + s += 12 + z.MetaStruct.Msgsize() + 8 + msgp.MapHeaderSize if z.Metrics != nil { for za0003, za0004 := range z.Metrics { _ = za0004 diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/spancontext.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/spancontext.go index eea659e1e..29da1b80b 100644 --- a/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/spancontext.go +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/spancontext.go @@ -91,6 +91,17 @@ type spanContext struct { span *span // reference to the span that hosts this context errors int32 // number of spans with errors in this trace + // The 16-character hex string of the last seen Datadog Span ID + // this value will be added as the _dd.parent_id tag to spans + // created from this spanContext. + // This value is extracted from the `p` sub-key within the tracestate. + // The backend will use the _dd.parent_id tag to reparent spans in + // distributed traces if they were missing their parent span. + // Missing parent span could occur when a W3C-compliant tracer + // propagated this context, but didn't send any spans to Datadog. + reparentID string + isRemote bool + // the below group should propagate cross-process traceID traceID @@ -112,6 +123,7 @@ func newSpanContext(span *span, parent *spanContext) *spanContext { spanID: span.SpanID, span: span, } + context.traceID.SetLower(span.TraceID) if parent != nil { context.traceID.SetUpper(parent.traceID.Upper()) @@ -181,12 +193,13 @@ func (c *spanContext) ForeachBaggageItem(handler func(k, v string) bool) { } } +// sets the sampling priority and decision maker (based on `sampler`). func (c *spanContext) setSamplingPriority(p int, sampler samplernames.SamplerName) { if c.trace == nil { c.trace = newTrace() } if c.trace.setSamplingPriority(p, sampler) { - // the trace's sampling priority was updated: mark this as updated + // the trace's sampling priority or sampler was updated: mark this as updated c.updated = true } } @@ -293,7 +306,8 @@ func (t *trace) samplingPriority() (p int, ok bool) { return t.samplingPriorityLocked() } -// setSamplingPriority sets the sampling priority and returns true if it was modified. +// setSamplingPriority sets the sampling priority and the decision maker +// and returns true if it was modified. func (t *trace) setSamplingPriority(p int, sampler samplernames.SamplerName) bool { t.mu.Lock() defer t.mu.Unlock() @@ -321,6 +335,10 @@ func (t *trace) setTagLocked(key, value string) { t.tags[key] = value } +func samplerToDM(sampler samplernames.SamplerName) string { + return "-" + strconv.Itoa(int(sampler)) +} + func (t *trace) setSamplingPriorityLocked(p int, sampler samplernames.SamplerName) bool { if t.locked { return false @@ -332,13 +350,23 @@ func (t *trace) setSamplingPriorityLocked(p int, sampler samplernames.SamplerNam t.priority = new(float64) } *t.priority = float64(p) - _, ok := t.propagatingTags[keyDecisionMaker] - if p > 0 && !ok && sampler != samplernames.Unknown { + curDM, existed := t.propagatingTags[keyDecisionMaker] + if p > 0 && sampler != samplernames.Unknown { // We have a positive priority and the sampling mechanism isn't set. // Send nothing when sampler is `Unknown` for RFC compliance. - t.setPropagatingTagLocked(keyDecisionMaker, "-"+strconv.Itoa(int(sampler))) + // If a global sampling rate is set, it was always applied first. And this call can be + // triggered again by applying a rule sampler. The sampling priority will be the same, but + // the decision maker will be different. So we compare the decision makers as well. + // Note that once global rate sampling is deprecated, we no longer need to compare + // the DMs. Sampling priority is sufficient to distinguish a change in DM. + dm := samplerToDM(sampler) + updatedDM := !existed || dm != curDM + if updatedDM { + t.setPropagatingTagLocked(keyDecisionMaker, dm) + return true + } } - if p <= 0 && ok { + if p <= 0 && existed { delete(t.propagatingTags, keyDecisionMaker) } @@ -578,3 +606,33 @@ func setPeerServiceFromSource(s *span) string { } return "" } + +const hexEncodingDigits = "0123456789abcdef" + +// spanIDHexEncoded returns the hex encoded string of the given span ID `u` +// with the given padding. +// +// Code is borrowed from `fmt.fmtInteger` in the standard library. +func spanIDHexEncoded(u uint64, padding int) string { + // The allocated intbuf with a capacity of 68 bytes + // is large enough for integer formatting. + var intbuf [68]byte + buf := intbuf[0:] + if padding > 68 { + buf = make([]byte, padding) + } + // Because printing is easier right-to-left: format u into buf, ending at buf[i]. + i := len(buf) + for u >= 16 { + i-- + buf[i] = hexEncodingDigits[u&0xF] + u >>= 4 + } + i-- + buf[i] = hexEncodingDigits[u] + for i > 0 && padding > len(buf)-i { + i-- + buf[i] = '0' + } + return string(buf[i:]) +} diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/sqlcomment.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/sqlcomment.go index 72ad4229b..99232e269 100644 --- a/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/sqlcomment.go +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/sqlcomment.go @@ -61,6 +61,8 @@ const ( // "Peer" is the OpenTelemetry nomenclature for "thing I am talking to" sqlCommentPeerHostname = "ddh" sqlCommentPeerDBName = "dddb" + // This is for when peer.service is explicitly set as a tag + sqlCommentPeerService = "ddprs" ) // Current trace context version (see https://www.w3.org/TR/trace-context/#version) @@ -76,6 +78,7 @@ type SQLCommentCarrier struct { SpanID uint64 PeerDBHostname string PeerDBName string + PeerService string } // Inject injects a span context in the carrier's Query field as a comment. @@ -117,6 +120,11 @@ func (c *SQLCommentCarrier) Inject(spanCtx ddtrace.SpanContext) error { if c.PeerDBHostname != "" { tags[sqlCommentPeerHostname] = c.PeerDBHostname } + if v, ok := ctx.meta(ext.PeerService); ok && v != "" { + tags[sqlCommentPeerService] = v + } else if c.PeerService != "" { + tags[sqlCommentPeerService] = c.PeerService + } } if globalconfig.ServiceName() != "" { tags[sqlCommentParentService] = globalconfig.ServiceName() @@ -167,7 +175,7 @@ func commentQuery(query string, tags map[string]string) string { var b strings.Builder // the sqlcommenter specification dictates that tags should be sorted. Since we know all injected keys, // we skip a sorting operation by specifying the order of keys statically - orderedKeys := []string{sqlCommentDBService, sqlCommentEnv, sqlCommentParentService, sqlCommentParentVersion, sqlCommentTraceParent, sqlCommentPeerHostname, sqlCommentPeerDBName} + orderedKeys := []string{sqlCommentDBService, sqlCommentEnv, sqlCommentParentService, sqlCommentParentVersion, sqlCommentTraceParent, sqlCommentPeerHostname, sqlCommentPeerDBName, sqlCommentPeerService} first := true for _, k := range orderedKeys { if v, ok := tags[k]; ok { diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/stats.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/stats.go index 720a2a023..8ad5da46e 100644 --- a/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/stats.go +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/stats.go @@ -214,12 +214,13 @@ func (c *concentrator) flushAndSend(timenow time.Time, includeCurrent bool) { // aggregation specifies a uniquely identifiable key under which a certain set // of stats are grouped inside a bucket. type aggregation struct { - Name string - Type string - Resource string - Service string - StatusCode uint32 - Synthetics bool + Name string + Type string + Resource string + Service string + StatusCode uint32 + Synthetics bool + IsTraceRoot trilean } type rawBucket struct { @@ -278,6 +279,14 @@ func (sb *rawBucket) Export() statsBucket { return csb } +type trilean int32 + +const ( + trileanNotSet trilean = iota + trileanTrue + trileanFalse +) + type rawGroupedStats struct { hits uint64 topLevelHits uint64 @@ -285,6 +294,7 @@ type rawGroupedStats struct { duration uint64 okDistribution *ddsketch.DDSketch errDistribution *ddsketch.DDSketch + IsTraceRoot trilean } func newRawGroupedStats() *rawGroupedStats { @@ -335,6 +345,7 @@ func (s *rawGroupedStats) export(k aggregation) (groupedStats, error) { OkSummary: okSummary, ErrorSummary: errSummary, Synthetics: k.Synthetics, + IsTraceRoot: int32(k.IsTraceRoot), }, nil } diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/stats_payload.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/stats_payload.go index 35a68b46b..3b77128b7 100644 --- a/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/stats_payload.go +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/stats_payload.go @@ -53,4 +53,5 @@ type groupedStats struct { ErrorSummary []byte `json:"errorSummary,omitempty"` Synthetics bool `json:"synthetics,omitempty"` TopLevelHits uint64 `json:"topLevelHits,omitempty"` + IsTraceRoot int32 `json:"isTraceRoot,omitempty"` } diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/stats_payload_msgp.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/stats_payload_msgp.go index 7d15d036e..70a3a0b4c 100644 --- a/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/stats_payload_msgp.go +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/stats_payload_msgp.go @@ -2,12 +2,9 @@ // under the Apache License Version 2.0. // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2016 Datadog, Inc. - package tracer -// NOTE: THIS FILE WAS PRODUCED BY THE -// MSGP CODE GENERATION TOOL (github.com/tinylib/msgp) -// DO NOT EDIT +// Code generated by github.com/tinylib/msgp DO NOT EDIT. import ( "github.com/tinylib/msgp/msgp" @@ -20,83 +17,105 @@ func (z *groupedStats) DecodeMsg(dc *msgp.Reader) (err error) { var zb0001 uint32 zb0001, err = dc.ReadMapHeader() if err != nil { + err = msgp.WrapError(err) return } for zb0001 > 0 { zb0001-- field, err = dc.ReadMapKeyPtr() if err != nil { + err = msgp.WrapError(err) return } switch msgp.UnsafeString(field) { case "Service": z.Service, err = dc.ReadString() if err != nil { + err = msgp.WrapError(err, "Service") return } case "Name": z.Name, err = dc.ReadString() if err != nil { + err = msgp.WrapError(err, "Name") return } case "Resource": z.Resource, err = dc.ReadString() if err != nil { + err = msgp.WrapError(err, "Resource") return } case "HTTPStatusCode": z.HTTPStatusCode, err = dc.ReadUint32() if err != nil { + err = msgp.WrapError(err, "HTTPStatusCode") return } case "Type": z.Type, err = dc.ReadString() if err != nil { + err = msgp.WrapError(err, "Type") return } case "DBType": z.DBType, err = dc.ReadString() if err != nil { + err = msgp.WrapError(err, "DBType") return } case "Hits": z.Hits, err = dc.ReadUint64() if err != nil { + err = msgp.WrapError(err, "Hits") return } case "Errors": z.Errors, err = dc.ReadUint64() if err != nil { + err = msgp.WrapError(err, "Errors") return } case "Duration": z.Duration, err = dc.ReadUint64() if err != nil { + err = msgp.WrapError(err, "Duration") return } case "OkSummary": z.OkSummary, err = dc.ReadBytes(z.OkSummary) if err != nil { + err = msgp.WrapError(err, "OkSummary") return } case "ErrorSummary": z.ErrorSummary, err = dc.ReadBytes(z.ErrorSummary) if err != nil { + err = msgp.WrapError(err, "ErrorSummary") return } case "Synthetics": z.Synthetics, err = dc.ReadBool() if err != nil { + err = msgp.WrapError(err, "Synthetics") return } case "TopLevelHits": z.TopLevelHits, err = dc.ReadUint64() if err != nil { + err = msgp.WrapError(err, "TopLevelHits") + return + } + case "IsTraceRoot": + z.IsTraceRoot, err = dc.ReadInt32() + if err != nil { + err = msgp.WrapError(err, "IsTraceRoot") return } default: err = dc.Skip() if err != nil { + err = msgp.WrapError(err) return } } @@ -106,14 +125,15 @@ func (z *groupedStats) DecodeMsg(dc *msgp.Reader) (err error) { // EncodeMsg implements msgp.Encodable func (z *groupedStats) EncodeMsg(en *msgp.Writer) (err error) { - // map header, size 13 + // map header, size 14 // write "Service" - err = en.Append(0x8d, 0xa7, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65) + err = en.Append(0x8e, 0xa7, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65) if err != nil { return } err = en.WriteString(z.Service) if err != nil { + err = msgp.WrapError(err, "Service") return } // write "Name" @@ -123,6 +143,7 @@ func (z *groupedStats) EncodeMsg(en *msgp.Writer) (err error) { } err = en.WriteString(z.Name) if err != nil { + err = msgp.WrapError(err, "Name") return } // write "Resource" @@ -132,6 +153,7 @@ func (z *groupedStats) EncodeMsg(en *msgp.Writer) (err error) { } err = en.WriteString(z.Resource) if err != nil { + err = msgp.WrapError(err, "Resource") return } // write "HTTPStatusCode" @@ -141,6 +163,7 @@ func (z *groupedStats) EncodeMsg(en *msgp.Writer) (err error) { } err = en.WriteUint32(z.HTTPStatusCode) if err != nil { + err = msgp.WrapError(err, "HTTPStatusCode") return } // write "Type" @@ -150,6 +173,7 @@ func (z *groupedStats) EncodeMsg(en *msgp.Writer) (err error) { } err = en.WriteString(z.Type) if err != nil { + err = msgp.WrapError(err, "Type") return } // write "DBType" @@ -159,6 +183,7 @@ func (z *groupedStats) EncodeMsg(en *msgp.Writer) (err error) { } err = en.WriteString(z.DBType) if err != nil { + err = msgp.WrapError(err, "DBType") return } // write "Hits" @@ -168,6 +193,7 @@ func (z *groupedStats) EncodeMsg(en *msgp.Writer) (err error) { } err = en.WriteUint64(z.Hits) if err != nil { + err = msgp.WrapError(err, "Hits") return } // write "Errors" @@ -177,6 +203,7 @@ func (z *groupedStats) EncodeMsg(en *msgp.Writer) (err error) { } err = en.WriteUint64(z.Errors) if err != nil { + err = msgp.WrapError(err, "Errors") return } // write "Duration" @@ -186,6 +213,7 @@ func (z *groupedStats) EncodeMsg(en *msgp.Writer) (err error) { } err = en.WriteUint64(z.Duration) if err != nil { + err = msgp.WrapError(err, "Duration") return } // write "OkSummary" @@ -195,6 +223,7 @@ func (z *groupedStats) EncodeMsg(en *msgp.Writer) (err error) { } err = en.WriteBytes(z.OkSummary) if err != nil { + err = msgp.WrapError(err, "OkSummary") return } // write "ErrorSummary" @@ -204,6 +233,7 @@ func (z *groupedStats) EncodeMsg(en *msgp.Writer) (err error) { } err = en.WriteBytes(z.ErrorSummary) if err != nil { + err = msgp.WrapError(err, "ErrorSummary") return } // write "Synthetics" @@ -213,6 +243,7 @@ func (z *groupedStats) EncodeMsg(en *msgp.Writer) (err error) { } err = en.WriteBool(z.Synthetics) if err != nil { + err = msgp.WrapError(err, "Synthetics") return } // write "TopLevelHits" @@ -222,6 +253,17 @@ func (z *groupedStats) EncodeMsg(en *msgp.Writer) (err error) { } err = en.WriteUint64(z.TopLevelHits) if err != nil { + err = msgp.WrapError(err, "TopLevelHits") + return + } + // write "IsTraceRoot" + err = en.Append(0xab, 0x49, 0x73, 0x54, 0x72, 0x61, 0x63, 0x65, 0x52, 0x6f, 0x6f, 0x74) + if err != nil { + return + } + err = en.WriteInt32(z.IsTraceRoot) + if err != nil { + err = msgp.WrapError(err, "IsTraceRoot") return } return @@ -229,7 +271,7 @@ func (z *groupedStats) EncodeMsg(en *msgp.Writer) (err error) { // Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message func (z *groupedStats) Msgsize() (s int) { - s = 1 + 8 + msgp.StringPrefixSize + len(z.Service) + 5 + msgp.StringPrefixSize + len(z.Name) + 9 + msgp.StringPrefixSize + len(z.Resource) + 15 + msgp.Uint32Size + 5 + msgp.StringPrefixSize + len(z.Type) + 7 + msgp.StringPrefixSize + len(z.DBType) + 5 + msgp.Uint64Size + 7 + msgp.Uint64Size + 9 + msgp.Uint64Size + 10 + msgp.BytesPrefixSize + len(z.OkSummary) + 13 + msgp.BytesPrefixSize + len(z.ErrorSummary) + 11 + msgp.BoolSize + 13 + msgp.Uint64Size + s = 1 + 8 + msgp.StringPrefixSize + len(z.Service) + 5 + msgp.StringPrefixSize + len(z.Name) + 9 + msgp.StringPrefixSize + len(z.Resource) + 15 + msgp.Uint32Size + 5 + msgp.StringPrefixSize + len(z.Type) + 7 + msgp.StringPrefixSize + len(z.DBType) + 5 + msgp.Uint64Size + 7 + msgp.Uint64Size + 9 + msgp.Uint64Size + 10 + msgp.BytesPrefixSize + len(z.OkSummary) + 13 + msgp.BytesPrefixSize + len(z.ErrorSummary) + 11 + msgp.BoolSize + 13 + msgp.Uint64Size + 12 + msgp.Int32Size return } @@ -240,29 +282,34 @@ func (z *statsBucket) DecodeMsg(dc *msgp.Reader) (err error) { var zb0001 uint32 zb0001, err = dc.ReadMapHeader() if err != nil { + err = msgp.WrapError(err) return } for zb0001 > 0 { zb0001-- field, err = dc.ReadMapKeyPtr() if err != nil { + err = msgp.WrapError(err) return } switch msgp.UnsafeString(field) { case "Start": z.Start, err = dc.ReadUint64() if err != nil { + err = msgp.WrapError(err, "Start") return } case "Duration": z.Duration, err = dc.ReadUint64() if err != nil { + err = msgp.WrapError(err, "Duration") return } case "Stats": var zb0002 uint32 zb0002, err = dc.ReadArrayHeader() if err != nil { + err = msgp.WrapError(err, "Stats") return } if cap(z.Stats) >= int(zb0002) { @@ -273,12 +320,14 @@ func (z *statsBucket) DecodeMsg(dc *msgp.Reader) (err error) { for za0001 := range z.Stats { err = z.Stats[za0001].DecodeMsg(dc) if err != nil { + err = msgp.WrapError(err, "Stats", za0001) return } } default: err = dc.Skip() if err != nil { + err = msgp.WrapError(err) return } } @@ -296,6 +345,7 @@ func (z *statsBucket) EncodeMsg(en *msgp.Writer) (err error) { } err = en.WriteUint64(z.Start) if err != nil { + err = msgp.WrapError(err, "Start") return } // write "Duration" @@ -305,6 +355,7 @@ func (z *statsBucket) EncodeMsg(en *msgp.Writer) (err error) { } err = en.WriteUint64(z.Duration) if err != nil { + err = msgp.WrapError(err, "Duration") return } // write "Stats" @@ -314,11 +365,13 @@ func (z *statsBucket) EncodeMsg(en *msgp.Writer) (err error) { } err = en.WriteArrayHeader(uint32(len(z.Stats))) if err != nil { + err = msgp.WrapError(err, "Stats") return } for za0001 := range z.Stats { err = z.Stats[za0001].EncodeMsg(en) if err != nil { + err = msgp.WrapError(err, "Stats", za0001) return } } @@ -341,34 +394,40 @@ func (z *statsPayload) DecodeMsg(dc *msgp.Reader) (err error) { var zb0001 uint32 zb0001, err = dc.ReadMapHeader() if err != nil { + err = msgp.WrapError(err) return } for zb0001 > 0 { zb0001-- field, err = dc.ReadMapKeyPtr() if err != nil { + err = msgp.WrapError(err) return } switch msgp.UnsafeString(field) { case "Hostname": z.Hostname, err = dc.ReadString() if err != nil { + err = msgp.WrapError(err, "Hostname") return } case "Env": z.Env, err = dc.ReadString() if err != nil { + err = msgp.WrapError(err, "Env") return } case "Version": z.Version, err = dc.ReadString() if err != nil { + err = msgp.WrapError(err, "Version") return } case "Stats": var zb0002 uint32 zb0002, err = dc.ReadArrayHeader() if err != nil { + err = msgp.WrapError(err, "Stats") return } if cap(z.Stats) >= int(zb0002) { @@ -379,12 +438,14 @@ func (z *statsPayload) DecodeMsg(dc *msgp.Reader) (err error) { for za0001 := range z.Stats { err = z.Stats[za0001].DecodeMsg(dc) if err != nil { + err = msgp.WrapError(err, "Stats", za0001) return } } default: err = dc.Skip() if err != nil { + err = msgp.WrapError(err) return } } @@ -402,6 +463,7 @@ func (z *statsPayload) EncodeMsg(en *msgp.Writer) (err error) { } err = en.WriteString(z.Hostname) if err != nil { + err = msgp.WrapError(err, "Hostname") return } // write "Env" @@ -411,6 +473,7 @@ func (z *statsPayload) EncodeMsg(en *msgp.Writer) (err error) { } err = en.WriteString(z.Env) if err != nil { + err = msgp.WrapError(err, "Env") return } // write "Version" @@ -420,6 +483,7 @@ func (z *statsPayload) EncodeMsg(en *msgp.Writer) (err error) { } err = en.WriteString(z.Version) if err != nil { + err = msgp.WrapError(err, "Version") return } // write "Stats" @@ -429,11 +493,13 @@ func (z *statsPayload) EncodeMsg(en *msgp.Writer) (err error) { } err = en.WriteArrayHeader(uint32(len(z.Stats))) if err != nil { + err = msgp.WrapError(err, "Stats") return } for za0001 := range z.Stats { err = z.Stats[za0001].EncodeMsg(en) if err != nil { + err = msgp.WrapError(err, "Stats", za0001) return } } diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/telemetry.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/telemetry.go index 30927b116..3fa70b4e9 100644 --- a/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/telemetry.go +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/telemetry.go @@ -12,6 +12,12 @@ import ( "gopkg.in/DataDog/dd-trace-go.v1/internal/telemetry" ) +var additionalConfigs []telemetry.Configuration + +func reportTelemetryOnAppStarted(c telemetry.Configuration) { + additionalConfigs = append(additionalConfigs, c) +} + // startTelemetry starts the global instrumentation telemetry client with tracer data // unless instrumentation telemetry is disabled via the DD_INSTRUMENTATION_TELEMETRY_ENABLED // env var. @@ -44,20 +50,23 @@ func startTelemetry(c *config) { {Name: "service", Value: c.serviceName}, {Name: "universal_version", Value: c.universalVersion}, {Name: "env", Value: c.env}, - {Name: "agent_url", Value: c.agentURL.String()}, + {Name: "version", Value: c.version}, + {Name: "trace_agent_url", Value: c.agentURL.String()}, {Name: "agent_hostname", Value: c.hostname}, {Name: "runtime_metrics_enabled", Value: c.runtimeMetrics}, {Name: "dogstatsd_addr", Value: c.dogstatsdAddr}, - {Name: "trace_debug_enabled", Value: !c.noDebugStack}, + {Name: "debug_stack_enabled", Value: !c.noDebugStack}, {Name: "profiling_hotspots_enabled", Value: c.profilerHotspots}, {Name: "profiling_endpoints_enabled", Value: c.profilerEndpoints}, {Name: "trace_span_attribute_schema", Value: c.spanAttributeSchemaVersion}, {Name: "trace_peer_service_defaults_enabled", Value: c.peerServiceDefaultsEnabled}, {Name: "orchestrion_enabled", Value: c.orchestrionCfg.Enabled}, - {Name: "trace_enabled", Value: c.enabled.current}, + {Name: "trace_enabled", Value: c.enabled.current, Origin: c.enabled.cfgOrigin}, c.traceSampleRate.toTelemetry(), c.headerAsTags.toTelemetry(), c.globalTags.toTelemetry(), + c.traceSampleRules.toTelemetry(), + telemetry.Sanitize(telemetry.Configuration{Name: "span_sample_rules", Value: c.spanRules}), } var peerServiceMapping []string for key, value := range c.peerServiceMappings { @@ -100,5 +109,6 @@ func startTelemetry(c *config) { telemetryConfigs = append(telemetryConfigs, telemetry.Configuration{Name: "orchestrion_" + k, Value: v}) } } + telemetryConfigs = append(telemetryConfigs, additionalConfigs...) telemetry.GlobalClient.ProductChange(telemetry.NamespaceTracers, true, telemetryConfigs) } diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/textmap.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/textmap.go index 76d540b97..1fee0ba68 100644 --- a/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/textmap.go +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/textmap.go @@ -9,7 +9,6 @@ import ( "fmt" "net/http" "os" - "regexp" "strconv" "strings" @@ -204,7 +203,7 @@ func getPropagators(cfg *PropagatorConfig, ps string) ([]Propagator, string) { defaultPsName += ",b3" } if ps == "" { - if prop := os.Getenv(headerPropagationStyle); prop != "" { + if prop := getDDorOtelConfig("propagationStyle"); prop != "" { ps = prop // use the generic DD_TRACE_PROPAGATION_STYLE if set } else { return defaultPs, defaultPsName // no env set, so use default from configuration @@ -274,11 +273,23 @@ func (p *chainedPropagator) Extract(carrier interface{}) (ddtrace.SpanContext, e for _, v := range p.extractors { if ctx != nil { // A local trace context has already been extracted. - p, isW3C := v.(*propagatorW3c) + pw3c, isW3C := v.(*propagatorW3c) if !isW3C { continue // Ignore other propagators. } - p.propagateTracestate(ctx.(*spanContext), carrier) + w3cCtx, err := pw3c.Extract(carrier) + if err == nil && w3cCtx.(*spanContext).TraceID128() == ctx.(*spanContext).TraceID128() { + pw3c.propagateTracestate(ctx.(*spanContext), w3cCtx.(*spanContext)) + if w3cCtx.SpanID() != ctx.SpanID() { + var ddCtx *spanContext + if ddp := getDatadogPropagator(p); ddp != nil { + if ddSpanCtx, err := ddp.Extract(carrier); err == nil { + ddCtx, _ = ddSpanCtx.(*spanContext) + } + } + overrideDatadogParentID(ctx.(*spanContext), w3cCtx.(*spanContext), ddCtx) + } + } break } var err error @@ -306,15 +317,8 @@ func (p *chainedPropagator) Extract(carrier interface{}) (ddtrace.SpanContext, e // provided by the given *spanContext. If it matches, then the tracestate // will be re-composed based on the composition of the given *spanContext, // but will include the non-DD vendors in the W3C trace context's tracestate. -func (p *propagatorW3c) propagateTracestate(ctx *spanContext, carrier interface{}) { - w3cCtx, _ := p.Extract(carrier) - if w3cCtx == nil { - return // It's not valid, so ignore it. - } - if ctx.TraceID() != w3cCtx.TraceID() { - return // The trace-ids must match. - } - if w3cCtx.(*spanContext).trace == nil { +func (p *propagatorW3c) propagateTracestate(ctx *spanContext, w3cCtx *spanContext) { + if w3cCtx.trace == nil { return // this shouldn't happen, since it should have a propagating tag already } if ctx.trace == nil { @@ -324,9 +328,10 @@ func (p *propagatorW3c) propagateTracestate(ctx *spanContext, carrier interface{ // it to the span context that will be returned. // Note: Other trace context fields like sampling priority, propagated tags, // and origin will remain unchanged. - ts := w3cCtx.(*spanContext).trace.propagatingTag(tracestateHeader) + ts := w3cCtx.trace.propagatingTag(tracestateHeader) priority, _ := ctx.SamplingPriority() setPropagatingTag(ctx, tracestateHeader, composeTracestate(ctx, priority, ts)) + ctx.isRemote = (w3cCtx.isRemote) } // propagator implements Propagator and injects/extracts span contexts @@ -487,6 +492,29 @@ func validateTID(tid string) error { return nil } +// getDatadogPropagator returns the Datadog Propagator +func getDatadogPropagator(cp *chainedPropagator) *propagator { + for _, e := range cp.extractors { + p, isDatadog := (e).(*propagator) + if isDatadog { + return p + } + } + return nil +} + +// overrideDatadogParentID overrides the span ID of a context with the ID extracted from tracecontext headers +// if the reparenting ID is not set on the context, the span ID from datadog headers is used. +func overrideDatadogParentID(ctx, w3cCtx, ddCtx *spanContext) { + ctx.spanID = w3cCtx.spanID + if w3cCtx.reparentID != "" { + ctx.reparentID = w3cCtx.reparentID + } else if ddCtx != nil { + // NIT: could be done without using fmt.Sprintf? Is it worth it? + ctx.reparentID = fmt.Sprintf("%016x", ddCtx.SpanID()) + } +} + // unmarshalPropagatingTags unmarshals tags from v into ctx func unmarshalPropagatingTags(ctx *spanContext, v string) { if ctx.trace == nil { @@ -750,43 +778,136 @@ func (*propagatorW3c) injectTextMap(spanCtx ddtrace.SpanContext, writer TextMapW } writer.Set(traceparentHeader, fmt.Sprintf("00-%s-%016x-%v", traceID, ctx.spanID, flags)) // if context priority / origin / tags were updated after extraction, + // or if there is a span on the trace // or the tracestateHeader doesn't start with `dd=` // we need to recreate tracestate if ctx.updated || + (!ctx.isRemote || ctx.isRemote && ctx.trace != nil && ctx.trace.root != nil) || (ctx.trace != nil && !strings.HasPrefix(ctx.trace.propagatingTag(tracestateHeader), "dd=")) || ctx.trace.propagatingTagsLen() == 0 { + // compose a new value for the tracestate writer.Set(tracestateHeader, composeTracestate(ctx, p, ctx.trace.propagatingTag(tracestateHeader))) } else { + // use a cached value for the tracestate (e.g., no updating p: key) writer.Set(tracestateHeader, ctx.trace.propagatingTag(tracestateHeader)) } return nil } +// stringMutator maps characters in a string to new characters. It is a state machine intended +// to replace regex patterns for simple character replacement, including collapsing runs of a +// specific range. +// +// It's designed after the `hash#Hash` interface, and to work with `strings.Map`. +type stringMutator struct { + // n is the current state of the mutator. It is used to track runs of characters that should + // be collapsed. + n bool + // fn is the function that implements the character replacement logic. + // It returns the rune to use as replacement and a bool to tell if next consecutive + // characters must be dropped if they fall in the currently matched character set. + // It's possible to return `-1` to immediately drop the current rune. + // + // This logic allows for: + // - Replace only the current rune: return , false + // - Drop only the current rune: return -1, false + // - Replace the current rune and drop the next consecutive runes if they match the same case: return , true + // - Drop all the consecutive runes matching the same case as the current one: return -1, true + // + // A known limitation is that we can only support a single case of consecutive runes. + fn func(rune) (rune, bool) +} + +// Mutate the mapped string using `strings.Map` and the provided function implementing the character +// replacement logic. +func (sm *stringMutator) Mutate(fn func(rune) (rune, bool), s string) string { + sm.fn = fn + rs := strings.Map(sm.mapping, s) + sm.reset() + + return rs +} + +func (sm *stringMutator) mapping(r rune) rune { + v, dropConsecutiveMatches := sm.fn(r) + if v < 0 { + // We reset the state machine in any match that is not related to a consecutive run + sm.reset() + return -1 + } + if dropConsecutiveMatches { + if !sm.n { + sm.n = true + return v + } + return -1 + } + // We reset the state machine in any match that is not related to a consecutive run + sm.reset() + return v +} + +// reset resets the state of the mutator. +func (sm *stringMutator) reset() { + sm.n = false +} + var ( - // keyRgx is used to sanitize the keys of the datadog propagating tags. + // keyDisallowedFn is used to sanitize the keys of the datadog propagating tags. // Disallowed characters are comma (reserved as a list-member separator), // equals (reserved for list-member key-value separator), // space and characters outside the ASCII range 0x20 to 0x7E. // Disallowed characters must be replaced with the underscore. - keyRgx = regexp.MustCompile(",|=|[^\\x20-\\x7E]+") + // Equivalent to regexp.MustCompile(",|=|[^\\x20-\\x7E]+") + keyDisallowedFn = func(r rune) (rune, bool) { + switch { + case r == ',' || r == '=': + return '_', false + case r < 0x20 || r > 0x7E: + return '_', true + } + return r, false + } - // valueRgx is used to sanitize the values of the datadog propagating tags. + // valueDisallowedFn is used to sanitize the values of the datadog propagating tags. // Disallowed characters are comma (reserved as a list-member separator), // semi-colon (reserved for separator between entries in the dd list-member), // tilde (reserved, will represent 0x3D (equals) in the encoded tag value, // and characters outside the ASCII range 0x20 to 0x7E. // Equals character must be encoded with a tilde. // Other disallowed characters must be replaced with the underscore. - valueRgx = regexp.MustCompile(",|;|~|[^\\x20-\\x7E]+") + // Equivalent to regexp.MustCompile(",|;|~|[^\\x20-\\x7E]+") + valueDisallowedFn = func(r rune) (rune, bool) { + switch { + case r == '=': + return '~', false + case r == ',' || r == '~' || r == ';': + return '_', false + case r < 0x20 || r > 0x7E: + return '_', true + } + return r, false + } - // originRgx is used to sanitize the value of the datadog origin tag. + // originDisallowedFn is used to sanitize the value of the datadog origin tag. // Disallowed characters are comma (reserved as a list-member separator), // semi-colon (reserved for separator between entries in the dd list-member), // equals (reserved for list-member key-value separator), // and characters outside the ASCII range 0x21 to 0x7E. // Equals character must be encoded with a tilde. // Other disallowed characters must be replaced with the underscore. - originRgx = regexp.MustCompile(",|~|;|[^\\x21-\\x7E]+") + // Equivalent to regexp.MustCompile(",|~|;|[^\\x21-\\x7E]+") + originDisallowedFn = func(r rune) (rune, bool) { + switch { + case r == '=': + return '~', false + case r == ',' || r == '~' || r == ';': + return '_', false + case r < 0x21 || r > 0x7E: + return '_', true + } + return r, false + } ) const ( @@ -819,17 +940,36 @@ func isValidID(id string) bool { // composeTracestate creates a tracestateHeader from the spancontext. // The Datadog tracing library is only responsible for managing the list member with key dd, // which holds the values of the sampling decision(`s:`), origin(`o:`), +// the last parent ID of a Datadog span (`p:`), // and propagated tags prefixed with `t.`(e.g. _dd.p.usr.id:usr_id tag will become `t.usr.id:usr_id`). func composeTracestate(ctx *spanContext, priority int, oldState string) string { - var b strings.Builder + var ( + b strings.Builder + sm = &stringMutator{} + ) + b.Grow(128) - b.WriteString(fmt.Sprintf("dd=s:%d", priority)) + b.WriteString("dd=s:") + b.WriteString(strconv.Itoa(priority)) listLength := 1 if ctx.origin != "" { - oWithSub := originRgx.ReplaceAllString(ctx.origin, "_") - b.WriteString(fmt.Sprintf(";o:%s", - strings.ReplaceAll(oWithSub, "=", "~"))) + oWithSub := sm.Mutate(originDisallowedFn, ctx.origin) + b.WriteString(";o:") + b.WriteString(oWithSub) + } + + // if the context is remote and there is a reparentID, set p as reparentId + // if the context is remote and there is no reparentID, don't set p + // if the context is not remote, set p as context.spanId + // this ID can be used by downstream tracers to set a _dd.parent_id tag + // to allow the backend to reparent orphaned spans if necessary + if !ctx.isRemote { + b.WriteString(";p:") + b.WriteString(spanIDHexEncoded(ctx.SpanID(), 16)) + } else if ctx.reparentID != "" { + b.WriteString(";p:") + b.WriteString(ctx.reparentID) } ctx.trace.iteratePropagatingTags(func(k, v string) bool { @@ -838,14 +978,15 @@ func composeTracestate(ctx *spanContext, priority int, oldState string) string { } // Datadog propagating tags must be appended to the tracestateHeader // with the `t.` prefix. Tag value must have all `=` signs replaced with a tilde (`~`). - tag := fmt.Sprintf("t.%s:%s", - keyRgx.ReplaceAllString(k[len("_dd.p."):], "_"), - strings.ReplaceAll(valueRgx.ReplaceAllString(v, "_"), "=", "~")) - if b.Len()+len(tag) > 256 { + key := sm.Mutate(keyDisallowedFn, k[len("_dd.p."):]) + value := sm.Mutate(valueDisallowedFn, v) + if b.Len()+len(key)+len(value)+4 > 256 { // the +4 here is to account for the `t.` prefix, the `;` needed between the tags, and the `:` between the key and value return false } - b.WriteString(";") - b.WriteString(tag) + b.WriteString(";t.") + b.WriteString(key) + b.WriteString(":") + b.WriteString(value) return true }) // the old state is split by vendors, must be concatenated with a `,` @@ -862,7 +1003,8 @@ func composeTracestate(ctx *spanContext, priority int, oldState string) string { if listLength > 32 { break } - b.WriteString("," + strings.Trim(s, " \t")) + b.WriteString(",") + b.WriteString(strings.Trim(s, " \t")) } return b.String() } @@ -880,6 +1022,7 @@ func (*propagatorW3c) extractTextMap(reader TextMapReader) (ddtrace.SpanContext, var parentHeader string var stateHeader string var ctx spanContext + ctx.isRemote = true // to avoid parsing tracestate header(s) if traceparent is invalid if err := reader.ForeachKey(func(k, v string) error { key := strings.ToLower(k) @@ -995,6 +1138,7 @@ func parseTraceparent(ctx *spanContext, header string) error { // The keys to the “dd“ values have been shortened as follows to save space: // `sampling_priority` = `s` // `origin` = `o` +// `last parent` = `p` // `_dd.p.` prefix = `t.` func parseTracestate(ctx *spanContext, header string) { if header == "" { @@ -1011,6 +1155,7 @@ func parseTracestate(ctx *spanContext, header string) { } ddMembers := strings.Split(group[len("dd="):], ";") dropDM := false + // indicate that backend could reparent this as a root for _, member := range ddMembers { keyVal := strings.SplitN(member, ":", 2) if len(keyVal) != 2 { @@ -1044,6 +1189,8 @@ func parseTracestate(ctx *spanContext, header string) { ctx.setSamplingPriority(0, samplernames.Unknown) dropDM = true } + } else if key == "p" { + ctx.reparentID = val } else if strings.HasPrefix(key, "t.dm") { if ctx.trace.hasPropagatingTag(keyDecisionMaker) || dropDM { continue diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/tracer.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/tracer.go index c8cf41d2d..a52c65f4f 100644 --- a/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/tracer.go +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/tracer.go @@ -8,6 +8,7 @@ package tracer import ( gocontext "context" "encoding/binary" + "math" "os" "runtime/pprof" rt "runtime/trace" @@ -23,7 +24,6 @@ import ( "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec" appsecConfig "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/config" "gopkg.in/DataDog/dd-trace-go.v1/internal/datastreams" - "gopkg.in/DataDog/dd-trace-go.v1/internal/globalconfig" "gopkg.in/DataDog/dd-trace-go.v1/internal/hostname" "gopkg.in/DataDog/dd-trace-go.v1/internal/log" "gopkg.in/DataDog/dd-trace-go.v1/internal/remoteconfig" @@ -81,6 +81,11 @@ type tracer struct { // finished, and dropped spansStarted, spansFinished, tracesDropped uint32 + // Keeps track of the total number of traces dropped for accurate logging. + totalTracesDropped uint32 + + logDroppedTraces *time.Ticker + // Records the number of dropped P0 traces and spans. droppedP0Traces, droppedP0Spans uint32 @@ -106,8 +111,6 @@ type tracer struct { // abandonedSpansDebugger specifies where and how potentially abandoned spans are stored // when abandoned spans debugging is enabled. abandonedSpansDebugger *abandonedSpansDebugger - - statsCarrier *globalinternal.StatsCarrier } const ( @@ -237,7 +240,9 @@ func newUnstartedTracer(opts ...StartOption) *tracer { log.Warn("Runtime and health metrics disabled: %v", err) } var writer traceWriter - if c.logToStdout { + if c.ciVisibilityEnabled { + writer = newCiVisibilityTraceWriter(c) + } else if c.logToStdout { writer = newLogTraceWriter(c, statsd) } else { writer = newAgentTraceWriter(c, sampler, statsd) @@ -252,19 +257,20 @@ func newUnstartedTracer(opts ...StartOption) *tracer { if spans != nil { c.spanRules = spans } - globalRate := globalSampleRate() - rulesSampler := newRulesSampler(c.traceRules, c.spanRules, globalRate) - c.traceSampleRate = newDynamicConfig("trace_sample_rate", globalRate, rulesSampler.traces.setGlobalSampleRate, equal[float64]) + rulesSampler := newRulesSampler(c.traceRules, c.spanRules, c.globalSampleRate) + c.traceSampleRate = newDynamicConfig("trace_sample_rate", c.globalSampleRate, rulesSampler.traces.setGlobalSampleRate, equal[float64]) + // If globalSampleRate returns NaN, it means the environment variable was not set or valid. + // We could always set the origin to "env_var" inconditionally, but then it wouldn't be possible + // to distinguish between the case where the environment variable was not set and the case where + // it default to NaN. + if !math.IsNaN(c.globalSampleRate) { + c.traceSampleRate.cfgOrigin = telemetry.OriginEnvVar + } + c.traceSampleRules = newDynamicConfig("trace_sample_rules", c.traceRules, + rulesSampler.traces.setTraceSampleRules, EqualsFalseNegative) var dataStreamsProcessor *datastreams.Processor if c.dataStreamsMonitoringEnabled { - dataStreamsProcessor = datastreams.NewProcessor(statsd, c.env, c.serviceName, c.version, c.agentURL, c.httpClient, func() bool { - f := loadAgentFeatures(c.logToStdout, c.agentURL, c.httpClient) - return f.DataStreams - }) - } - var statsCarrier *globalinternal.StatsCarrier - if c.contribStats { - statsCarrier = globalinternal.NewStatsCarrier(statsd) + dataStreamsProcessor = datastreams.NewProcessor(statsd, c.env, c.serviceName, c.version, c.agentURL, c.httpClient) } t := &tracer{ config: c, @@ -275,6 +281,7 @@ func newUnstartedTracer(opts ...StartOption) *tracer { rulesSampling: rulesSampler, prioritySampling: sampler, pid: os.Getpid(), + logDroppedTraces: time.NewTicker(1 * time.Second), stats: newConcentrator(c, defaultStatsBucketSize), obfuscator: obfuscate.NewObfuscator(obfuscate.Config{ SQL: obfuscate.SQLConfig{ @@ -285,9 +292,8 @@ func newUnstartedTracer(opts ...StartOption) *tracer { Cache: c.agent.HasFlag("sql_cache"), }, }), - statsd: statsd, - dataStreams: dataStreamsProcessor, - statsCarrier: statsCarrier, + statsd: statsd, + dataStreams: dataStreamsProcessor, } return t } @@ -331,10 +337,6 @@ func newTracer(opts ...StartOption) *tracer { t.reportHealthMetrics(statsInterval) }() t.stats.Start() - if sc := t.statsCarrier; sc != nil { - sc.Start() - globalconfig.SetStatsCarrier(sc) - } return t } @@ -437,11 +439,11 @@ func (t *tracer) sampleChunk(c *chunk) { atomic.AddUint32(&t.partialTraces, 1) } } - if len(kept) == 0 { - atomic.AddUint32(&t.droppedP0Traces, 1) - } atomic.AddUint32(&t.droppedP0Spans, uint32(len(c.spans)-len(kept))) if !c.willSend { + if len(kept) == 0 { + atomic.AddUint32(&t.droppedP0Traces, 1) + } c.spans = kept } } @@ -455,7 +457,15 @@ func (t *tracer) pushChunk(trace *chunk) { select { case t.out <- trace: default: - log.Error("payload queue full, dropping %d traces", len(trace.spans)) + log.Debug("payload queue full, trace dropped %d spans", len(trace.spans)) + atomic.AddUint32(&t.totalTracesDropped, 1) + } + select { + case <-t.logDroppedTraces.C: + if t := atomic.SwapUint32(&t.totalTracesDropped, 0); t > 0 { + log.Error("%d traces dropped through payload queue", t) + } + default: } } @@ -518,9 +528,8 @@ func (t *tracer) StartSpan(operationName string, options ...ddtrace.StartSpanOpt Start: startTime, noDebugStack: t.config.noDebugStack, } - for _, link := range opts.SpanLinks { - span.SpanLinks = append(span.SpanLinks, link) - } + + span.SpanLinks = append(span.SpanLinks, opts.SpanLinks...) if t.config.hostname != "" { span.setMeta(keyHostname, t.config.hostname) @@ -544,6 +553,11 @@ func (t *tracer) StartSpan(operationName string, options ...ddtrace.StartSpanOpt span.setMeta(keyOrigin, context.origin) } } + + if context.reparentID != "" { + span.setMeta(keyReparentID, context.reparentID) + } + } span.context = newSpanContext(span, context) span.setMetric(ext.Pid, float64(t.pid)) @@ -609,13 +623,6 @@ func (t *tracer) StartSpan(operationName string, options ...ddtrace.StartSpanOpt return span } -// generateSpanID returns a random uint64 that has been XORd with the startTime. -// This is done to get around the 32-bit random seed limitation that may create collisions if there is a large number -// of go services all generating spans. -func generateSpanID(startTime int64) uint64 { - return random.Uint64() ^ uint64(startTime) -} - // applyPPROFLabels applies pprof labels for the profiler's code hotspots and // endpoint filtering feature to span. When span finishes, any pprof labels // found in ctx are restored. Additionally, this func informs the profiler how @@ -670,9 +677,6 @@ func (t *tracer) Stop() { if t.dataStreams != nil { t.dataStreams.Stop() } - if t.statsCarrier != nil { - t.statsCarrier.Stop() - } appsec.Stop() remoteconfig.Stop() } @@ -706,6 +710,10 @@ func (t *tracer) updateSampling(ctx ddtrace.SpanContext) { return } + // the span was sampled with ManualKeep rules shouldn't override + if sctx.trace.propagatingTag(keyDecisionMaker) == "-4" { + return + } // if sampling was successful, need to lock the trace to prevent further re-sampling if t.rulesSampling.SampleTrace(sctx.trace.root) { sctx.trace.setLocked(true) @@ -741,6 +749,9 @@ func (t *tracer) sample(span *span) { if t.rulesSampling.SampleTraceGlobalRate(span) { return } + if t.rulesSampling.SampleTrace(span) { + return + } t.prioritySampling.apply(span) } diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/transport.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/transport.go index d6cac1c1f..c6a900c05 100644 --- a/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/transport.go +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/transport.go @@ -11,8 +11,6 @@ import ( "io" "net" "net/http" - "net/url" - "os" "runtime" "strconv" "strings" @@ -38,19 +36,21 @@ var defaultDialer = &net.Dialer{ DualStack: true, } -var defaultClient = &http.Client{ - // We copy the transport to avoid using the default one, as it might be - // augmented with tracing and we don't want these calls to be recorded. - // See https://golang.org/pkg/net/http/#DefaultTransport . - Transport: &http.Transport{ - Proxy: http.ProxyFromEnvironment, - DialContext: defaultDialer.DialContext, - MaxIdleConns: 100, - IdleConnTimeout: 90 * time.Second, - TLSHandshakeTimeout: 10 * time.Second, - ExpectContinueTimeout: 1 * time.Second, - }, - Timeout: defaultHTTPTimeout, +func defaultHTTPClient(timeout time.Duration) *http.Client { + if timeout == 0 { + timeout = defaultHTTPTimeout + } + return &http.Client{ + Transport: &http.Transport{ + Proxy: http.ProxyFromEnvironment, + DialContext: defaultDialer.DialContext, + MaxIdleConns: 100, + IdleConnTimeout: 90 * time.Second, + TLSHandshakeTimeout: 10 * time.Second, + ExpectContinueTimeout: 1 * time.Second, + }, + Timeout: timeout, + } } const ( @@ -58,7 +58,7 @@ const ( defaultPort = "8126" defaultAddress = defaultHostname + ":" + defaultPort defaultURL = "http://" + defaultAddress - defaultHTTPTimeout = 2 * time.Second // defines the current timeout before giving up with the send process + defaultHTTPTimeout = 10 * time.Second // defines the current timeout before giving up with the send process traceCountHeader = "X-Datadog-Trace-Count" // header containing the number of traces in the payload ) @@ -186,32 +186,3 @@ func (t *httpTransport) send(p *payload) (body io.ReadCloser, err error) { func (t *httpTransport) endpoint() string { return t.traceURL } - -// resolveAgentAddr resolves the given agent address and fills in any missing host -// and port using the defaults. Some environment variable settings will -// take precedence over configuration. -func resolveAgentAddr() *url.URL { - var host, port string - if v := os.Getenv("DD_AGENT_HOST"); v != "" { - host = v - } - if v := os.Getenv("DD_TRACE_AGENT_PORT"); v != "" { - port = v - } - if _, err := os.Stat(defaultSocketAPM); host == "" && port == "" && err == nil { - return &url.URL{ - Scheme: "unix", - Path: defaultSocketAPM, - } - } - if host == "" { - host = defaultHostname - } - if port == "" { - port = defaultPort - } - return &url.URL{ - Scheme: "http", - Host: fmt.Sprintf("%s:%s", host, port), - } -} diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/util.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/util.go index 67ee16149..bd3c03a84 100644 --- a/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/util.go +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/util.go @@ -20,6 +20,8 @@ import ( func toFloat64(value interface{}) (f float64, ok bool) { const max = (int64(1) << 53) - 1 const min = -max + // If any other type is added here, remember to add it to the type switch in + // the `span.SetTag` function to handle pointers to these supported types. switch i := value.(type) { case byte: return float64(i), true @@ -122,3 +124,54 @@ func parsePropagatableTraceTags(s string) (map[string]string, error) { tags[key] = s[start:] return tags, nil } + +func dereference(value any) any { + // Falling into one of the cases will dereference the pointer and return the + // value of the pointer. It adds one allocation due to casting. + switch value.(type) { + case *bool: + return dereferenceGeneric(value.(*bool)) + case *string: + return dereferenceGeneric(value.(*string)) + // Supported type by toFloat64 + case *byte: + return dereferenceGeneric(value.(*byte)) + case *float32: + return dereferenceGeneric(value.(*float32)) + case *float64: + return dereferenceGeneric(value.(*float64)) + case *int: + return dereferenceGeneric(value.(*int)) + case *int8: + return dereferenceGeneric(value.(*int8)) + case *int16: + return dereferenceGeneric(value.(*int16)) + case *int32: + return dereferenceGeneric(value.(*int32)) + case *int64: + return dereferenceGeneric(value.(*int64)) + case *uint: + return dereferenceGeneric(value.(*uint)) + case *uint16: + return dereferenceGeneric(value.(*uint16)) + case *uint32: + return dereferenceGeneric(value.(*uint32)) + case *uint64: + return dereferenceGeneric(value.(*uint64)) + case *samplernames.SamplerName: + v := value.(*samplernames.SamplerName) + if v == nil { + return samplernames.Unknown + } + return *v + } + return value +} + +func dereferenceGeneric[T any](value *T) T { + if value == nil { + var v T + return v + } + return *value +} diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/writer.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/writer.go index 877c8ada2..04d9c25d9 100644 --- a/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/writer.go +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer/writer.go @@ -219,6 +219,22 @@ func (h *logTraceWriter) encodeSpan(s *span) { h.buf.WriteString(":") h.marshalString(v) } + // We cannot pack messagepack into JSON, so we need to marshal the meta struct as JSON, and send them through the `meta` field + for k, v := range s.MetaStruct { + if first { + first = false + } else { + h.buf.WriteString(`,`) + } + h.marshalString(k) + h.buf.WriteString(":") + jsonValue, err := json.Marshal(v) + if err != nil { + log.Error("Error marshaling value %q: %v", v, err) + continue + } + h.marshalString(string(jsonValue)) + } h.buf.WriteString(`},"metrics":{`) first = true for k, v := range s.Metrics { diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/agent.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/agent.go index c8f835166..f4bcdce8b 100644 --- a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/agent.go +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/agent.go @@ -6,31 +6,70 @@ package internal import ( + "net" "net/url" "os" "gopkg.in/DataDog/dd-trace-go.v1/internal/log" ) -// AgentURLFromEnv determines the trace agent URL from environment variable -// DD_TRACE_AGENT_URL. If the determined value is valid and the scheme is -// supported (unix, http or https), it will return an *url.URL. Otherwise, -// it returns nil. +const ( + DefaultAgentHostname = "localhost" + DefaultTraceAgentPort = "8126" +) + +// This is a variable rather than a constant so it can be replaced in unit tests +var DefaultTraceAgentUDSPath = "/var/run/datadog/apm.socket" + +// AgentURLFromEnv resolves the URL for the trace agent based on +// the default host/port and UDS path, and via standard environment variables. +// AgentURLFromEnv has the following priority order: +// - First, DD_TRACE_AGENT_URL if it is set +// - Then, if either of DD_AGENT_HOST and DD_TRACE_AGENT_PORT are set, +// use http://DD_AGENT_HOST:DD_TRACE_AGENT_PORT, +// defaulting to localhost and 8126, respectively +// - Then, DefaultTraceAgentUDSPath, if the path exists +// - Finally, localhost:8126 func AgentURLFromEnv() *url.URL { - agentURL := os.Getenv("DD_TRACE_AGENT_URL") - if agentURL == "" { - return nil + if agentURL := os.Getenv("DD_TRACE_AGENT_URL"); agentURL != "" { + u, err := url.Parse(agentURL) + if err != nil { + log.Warn("Failed to parse DD_TRACE_AGENT_URL: %v", err) + } else { + switch u.Scheme { + case "unix", "http", "https": + return u + default: + log.Warn("Unsupported protocol %q in Agent URL %q. Must be one of: http, https, unix.", u.Scheme, agentURL) + } + } + } + + host, providedHost := os.LookupEnv("DD_AGENT_HOST") + port, providedPort := os.LookupEnv("DD_TRACE_AGENT_PORT") + if host == "" { + // We treat set but empty the same as unset + providedHost = false + host = DefaultAgentHostname + } + if port == "" { + // We treat set but empty the same as unset + providedPort = false + port = DefaultTraceAgentPort } - u, err := url.Parse(agentURL) - if err != nil { - log.Warn("Failed to parse DD_TRACE_AGENT_URL: %v", err) - return nil + httpURL := &url.URL{ + Scheme: "http", + Host: net.JoinHostPort(host, port), } - switch u.Scheme { - case "unix", "http", "https": - return u - default: - log.Warn("Unsupported protocol %q in Agent URL %q. Must be one of: http, https, unix.", u.Scheme, agentURL) - return nil + if providedHost || providedPort { + return httpURL + } + + if _, err := os.Stat(DefaultTraceAgentUDSPath); err == nil { + return &url.URL{ + Scheme: "unix", + Path: DefaultTraceAgentUDSPath, + } } + return httpURL } diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/README.md b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/README.md new file mode 100644 index 000000000..d693d883f --- /dev/null +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/README.md @@ -0,0 +1,147 @@ +# Appsec Go Design + +This document describes the design of the `internal/appsec` package and everything under it. This package is responsible +for securing the application by monitoring the operations that are executed by the application and applying actions in +case a security threats is detected. + +Most of the work is to forward information to the module `github.com/DataDog/go-libddwaf` which contains the WAF +(Web Application Firewall) engine. The WAF does most of the decision making about events and actions. Our goal is to +connect the different parts of the application and the WAF engine while keeping up to date the various sources of +configuration that the WAF engine uses. + +### Instrumentation Gateway: Dyngo + +Having the customer (or orchestrion) instrument their code is the hardest part of the job. That's why we want to provide +the simplest API possible for them to use. This means loosing the flexibility or enabling and disabling multiple +products and features at runtime. Flexibility that we still want to provide to the customer, that's why behind every +API entrypoint present in `dd-trace-go/contrib` that support appsec is a call to the `internal/appsec/dyngo` package. + +```mermaid +flowchart LR + +UserCode[User Code] --> Instrumentation --> IG{Instrumentation Gateway} -----> Listener +``` + +Dyngo is a context-scoped event listener system that provide a way to listen dynamically to events that are happening in +the customer code and to react to configuration changes and hot-swap event listeners at runtime. + +```mermaid +flowchart LR + +UserCode[User Code] --> appsec/emitter --> IG{dyngo} -----> appsec/listener +``` + +### Operation definition requirements + +* Each operation must have a `Start*` and a `Finish` method covering calls to dyngo. +* The content of the arguments and results should not require any external package, at most the standard library. + +Example operation: + +```go +package main + +import ( + "context" + + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/dyngo" + "gopkg.in/DataDog/dd-trace-go.v1/internal/log" +) + +type ( + ExampleOperation struct { + dyngo.Operation + } + + ExampleOperationArgs struct { + Type string + } + + ExampleOperationResult struct { + Code int + } +) + +func (ExampleOperationArgs) IsArgOf(*ExampleOperation) {} +func (ExampleOperationResult) IsResultOf(*ExampleOperation) {} + +func StartExampleOperation(ctx context.Context, args ExampleOperationArgs) *ExampleOperation { + parent, ok := dyngo.FromContext(ctx) + if !ok { + log.Error("No parent operation found") + return nil + } + op := &ExampleOperation{ + Operation: dyngo.NewOperation(parent), + } + return dyngo.StartOperation(op, args) +} + +func (op *ExampleOperation) Finish(result ExampleOperationResult) { + dyngo.FinishOperation(op, result) +} +``` + +> [!CAUTION] +> Importing external packages in the operation definition will probably cause circular dependencies. This is because +> the operation definition can be used in the package is will instrument, and the package that will instrument it will +> probably import the operation definition. + +### Operation Stack + +Current state of the possible operation stacks + +```mermaid +flowchart TD + + subgraph Top Level Operation + SES[trace.ServiceEntrySpanOperation] + + Context[waf.ContextOperation] + + HTTPH[httpsec.HandlerOperation] + GRPCH[grpcsec.HandlerOperation] + GQL[graphqlsec.RequestOperation] + end + + subgraph HTTP + RequestBody([httpsec.MonitorRequestBody]) + Roundtripper[httpsec.RoundTripOperation] + end + + subgraph GRPC + RequestMessage([grpcsec.MonitorRequestMessage]) + ResponseMessage([grpcsec.MonitorResponseMessage]) + end + + subgraph GraphQL + Exec[graphqlsec.ExecutionOperation] + Resolve[graphqlsec.ResolveOperation] + end + + Code{User Code} + + SES --> Context + Context --> HTTPH --> Code + Context --> GRPCH --> Code + Context --> GQL + + GQL --> Exec --> Resolve --> Code + + Code --> RequestBody + + Code --> RequestMessage + Code --> ResponseMessage + + Code --> Span[trace.SpanOperation] + + Span --> Roundtripper + Span --> OS[ossec.OpenOperation] + Span --> SQL[sqlsec.SQLOperation] + Span --> User[usersec.UserOperation] +``` + +> [!IMPORTANT] +> Please note that this is how the operation SHOULD be stacked. If the user code does not have a Top Level Operation +> then nothing will be monitored. In this case an error log should be produced to explain thouroughly the issue to +> the user. diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/appsec.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/appsec.go index ecc1d59f0..0dc042caa 100644 --- a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/appsec.go +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/appsec.go @@ -9,12 +9,13 @@ import ( "fmt" "sync" - "github.com/DataDog/appsec-internal-go/limiter" - appsecLog "github.com/DataDog/appsec-internal-go/log" - waf "github.com/DataDog/go-libddwaf/v2" "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/config" "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/dyngo" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener" "gopkg.in/DataDog/dd-trace-go.v1/internal/log" + + appsecLog "github.com/DataDog/appsec-internal-go/log" + waf "github.com/DataDog/go-libddwaf/v3" ) // Enabled returns true when AppSec is up and running. Meaning that the appsec build tag is enabled, the env var @@ -25,6 +26,13 @@ func Enabled() bool { return activeAppSec != nil && activeAppSec.started } +// RASPEnabled returns true when DD_APPSEC_RASP_ENABLED=true or is unset. Granted that AppSec is enabled. +func RASPEnabled() bool { + mu.RLock() + defer mu.RUnlock() + return activeAppSec != nil && activeAppSec.started && activeAppSec.cfg.RASP +} + // Start AppSec when enabled is enabled by both using the appsec build tag and // setting the environment variable DD_APPSEC_ENABLED to true. func Start(opts ...config.StartOption) { @@ -126,10 +134,10 @@ func setActiveAppSec(a *appsec) { } type appsec struct { - cfg *config.Config - limiter *limiter.TokenTicker - wafHandle *wafHandle - started bool + cfg *config.Config + features []listener.Feature + featuresMu sync.Mutex + started bool } func newAppSec(cfg *config.Config) *appsec { @@ -152,15 +160,13 @@ func (a *appsec) start(telemetry *appsecTelemetry) error { log.Error("appsec: non-critical error while loading libddwaf: %v", err) } - a.limiter = limiter.NewTokenTicker(a.cfg.TraceRateLimit, a.cfg.TraceRateLimit) - a.limiter.Start() - - // Register the WAF operation event listener - if err := a.swapWAF(a.cfg.RulesManager.Latest); err != nil { + // Register dyngo listeners + if err := a.SwapRootOperation(); err != nil { return err } a.enableRCBlocking() + a.enableRASP() a.started = true log.Info("appsec: up and running") @@ -184,15 +190,23 @@ func (a *appsec) stop() { // Disable RC blocking first so that the following is guaranteed not to be concurrent anymore. a.disableRCBlocking() + a.featuresMu.Lock() + defer a.featuresMu.Unlock() + // Disable the currently applied instrumentation dyngo.SwapRootOperation(nil) - if a.wafHandle != nil { - a.wafHandle.Close() - a.wafHandle = nil - } + + // Reset rules edits received from the remote configuration + // We skip the error because we can't do anything about and it was already logged in config.NewRulesManager + a.cfg.RulesManager, _ = config.NewRulesManager(nil) + // TODO: block until no more requests are using dyngo operations - a.limiter.Stop() + for _, feature := range a.features { + feature.Stop() + } + + a.features = nil } func init() { diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/config/config.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/config/config.go index b660d7a02..6ffcbafcf 100644 --- a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/config/config.go +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/config/config.go @@ -12,11 +12,42 @@ import ( "time" internal "github.com/DataDog/appsec-internal-go/appsec" + + "gopkg.in/DataDog/dd-trace-go.v1/internal/log" "gopkg.in/DataDog/dd-trace-go.v1/internal/remoteconfig" + "gopkg.in/DataDog/dd-trace-go.v1/internal/telemetry" ) -// EnvEnabled is the env var used to enable/disable appsec -const EnvEnabled = "DD_APPSEC_ENABLED" +func init() { + registerAppConfigTelemetry() +} + +// Register the global app telemetry configuration. +func registerAppConfigTelemetry() { + registerSCAAppConfigTelemetry(telemetry.GlobalClient) +} + +// Register the global app telemetry configuration related to the Software Composition Analysis (SCA) product. +// Report over telemetry whether SCA's enablement env var was set or not along with its value. Nothing is reported in +// case of an error or if the env var is not set. +func registerSCAAppConfigTelemetry(client telemetry.Client) { + val, defined, err := parseBoolEnvVar(EnvSCAEnabled) + if err != nil { + log.Error("appsec: %v", err) + return + } + if defined { + client.RegisterAppConfig(EnvSCAEnabled, val, telemetry.OriginEnvVar) + } +} + +// The following environment variables dictate the enablement of different the ASM products. +const ( + // EnvEnabled controls ASM Threats Protection's enablement. + EnvEnabled = "DD_APPSEC_ENABLED" + // EnvSCAEnabled controls ASM Software Composition Analysis (SCA)'s enablement. + EnvSCAEnabled = "DD_APPSEC_SCA_ENABLED" +) // StartOption is used to customize the AppSec configuration when invoked with appsec.Start() type StartOption func(c *Config) @@ -35,7 +66,32 @@ type Config struct { // APISec configuration APISec internal.APISecConfig // RC is the remote configuration client used to receive product configuration updates. Nil if RC is disabled (default) - RC *remoteconfig.ClientConfig + RC *remoteconfig.ClientConfig + RASP bool + // SupportedAddresses are the addresses that the AppSec listener will bind to. + SupportedAddresses AddressSet +} + +// AddressSet is a set of WAF addresses. +type AddressSet map[string]struct{} + +func NewAddressSet(addrs []string) AddressSet { + set := make(AddressSet, len(addrs)) + for _, addr := range addrs { + set[addr] = struct{}{} + } + return set +} + +// AnyOf returns true if any of the addresses in the set are in the given list. +func (set AddressSet) AnyOf(anyOf ...string) bool { + for _, addr := range anyOf { + if _, ok := set[addr]; ok { + return true + } + } + + return false } // WithRCConfig sets the AppSec remote config client configuration to the specified cfg @@ -45,15 +101,22 @@ func WithRCConfig(cfg remoteconfig.ClientConfig) StartOption { } } -// IsEnabled returns true when appsec is enabled when the environment variable -// DD_APPSEC_ENABLED is set to true. -// It also returns whether the env var is actually set in the env or not. +// IsEnabled returns true when appsec is enabled by the environment variable DD_APPSEC_ENABLED (as of strconv's boolean +// parsing rules). When false, it also returns whether the env var was actually set or not. +// In case of a parsing error, it returns a detailed error. func IsEnabled() (enabled bool, set bool, err error) { - enabledStr, set := os.LookupEnv(EnvEnabled) - if enabledStr == "" { + return parseBoolEnvVar(EnvEnabled) +} + +// Return true when the given environment variable is defined and set to true (as of strconv's +// parsing rules). When false, it also returns whether the env var was actually set or not. +// In case of a parsing error, it returns a detailed error. +func parseBoolEnvVar(env string) (enabled bool, set bool, err error) { + str, set := os.LookupEnv(env) + if str == "" { return false, set, nil - } else if enabled, err = strconv.ParseBool(enabledStr); err != nil { - return false, set, fmt.Errorf("could not parse %s value `%s` as a boolean value", EnvEnabled, enabledStr) + } else if enabled, err = strconv.ParseBool(str); err != nil { + return false, set, fmt.Errorf("could not parse %s value `%s` as a boolean value", env, str) } return enabled, set, nil @@ -66,7 +129,7 @@ func NewConfig() (*Config, error) { return nil, err } - r, err := NewRulesManeger(rules) + r, err := NewRulesManager(rules) if err != nil { return nil, err } @@ -77,5 +140,6 @@ func NewConfig() (*Config, error) { TraceRateLimit: int64(internal.RateLimitFromEnv()), Obfuscator: internal.NewObfuscatorConfig(), APISec: internal.NewAPISecConfig(), + RASP: internal.RASPEnabled(), }, nil } diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/config/rules_manager.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/config/rules_manager.go index 46d22b389..e4e003eda 100644 --- a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/config/rules_manager.go +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/config/rules_manager.go @@ -8,6 +8,7 @@ package config import ( "encoding/json" "fmt" + "slices" "gopkg.in/DataDog/dd-trace-go.v1/internal/log" @@ -28,36 +29,21 @@ type ( } // RulesFragment can represent a full ruleset or a fragment of it. RulesFragment struct { - Version string `json:"version,omitempty"` - Metadata interface{} `json:"metadata,omitempty"` - Rules []interface{} `json:"rules,omitempty"` - Overrides []interface{} `json:"rules_override,omitempty"` - Exclusions []interface{} `json:"exclusions,omitempty"` - RulesData []RuleDataEntry `json:"rules_data,omitempty"` - Actions []ActionEntry `json:"actions,omitempty"` - CustomRules []interface{} `json:"custom_rules,omitempty"` - Processors []interface{} `json:"processors,omitempty"` - Scanners []interface{} `json:"scanners,omitempty"` + Version string `json:"version,omitempty"` + Metadata any `json:"metadata,omitempty"` + Rules []any `json:"rules,omitempty"` + Overrides []any `json:"rules_override,omitempty"` + Exclusions []any `json:"exclusions,omitempty"` + ExclusionData []DataEntry `json:"exclusion_data,omitempty"` + RulesData []DataEntry `json:"rules_data,omitempty"` + Actions []any `json:"actions,omitempty"` + CustomRules []any `json:"custom_rules,omitempty"` + Processors []any `json:"processors,omitempty"` + Scanners []any `json:"scanners,omitempty"` } - // RuleDataEntry represents an entry in the "rules_data" top level field of a rules file - RuleDataEntry rc.ASMDataRuleData - // RulesData is a slice of RulesDataEntry - RulesData struct { - RulesData []RuleDataEntry `json:"rules_data"` - } - - // ActionEntry represents an entry in the "actions" top level field of a rules file - ActionEntry struct { - ID string `json:"id"` - Type string `json:"type"` - Parameters struct { - StatusCode int `json:"status_code"` - GRPCStatusCode *int `json:"grpc_status_code,omitempty"` - Type string `json:"type,omitempty"` - Location string `json:"location,omitempty"` - } `json:"parameters,omitempty"` - } + // DataEntry represents an entry in the "rules_data" top level field of a rules file + DataEntry rc.ASMDataRuleData ) // DefaultRulesFragment returns a RulesFragment created using the default static recommended rules @@ -72,27 +58,20 @@ func DefaultRulesFragment() RulesFragment { func (f *RulesFragment) clone() (clone RulesFragment) { clone.Version = f.Version clone.Metadata = f.Metadata - clone.Overrides = cloneSlice(f.Overrides) - clone.Exclusions = cloneSlice(f.Exclusions) - clone.RulesData = cloneSlice(f.RulesData) - clone.CustomRules = cloneSlice(f.CustomRules) - clone.Processors = cloneSlice(f.Processors) - clone.Scanners = cloneSlice(f.Scanners) - // TODO (Francois Mazeau): copy more fields once we handle them + clone.Overrides = slices.Clone(f.Overrides) + clone.Exclusions = slices.Clone(f.Exclusions) + clone.ExclusionData = slices.Clone(f.ExclusionData) + clone.RulesData = slices.Clone(f.RulesData) + clone.CustomRules = slices.Clone(f.CustomRules) + clone.Processors = slices.Clone(f.Processors) + clone.Scanners = slices.Clone(f.Scanners) return } -func cloneSlice[T any](slice []T) []T { - // TODO: use slices.Clone once go1.21 is the min supported go runtime. - clone := make([]T, len(slice), cap(slice)) - copy(clone, slice) - return clone -} - -// NewRulesManeger initializes and returns a new RulesManager using the provided rules. +// NewRulesManager initializes and returns a new RulesManager using the provided rules. // If no rules are provided (nil), the default rules are used instead. // If the provided rules are invalid, an error is returned -func NewRulesManeger(rules []byte) (*RulesManager, error) { +func NewRulesManager(rules []byte) (*RulesManager, error) { var f RulesFragment if rules == nil { f = DefaultRulesFragment() @@ -147,6 +126,7 @@ func (r *RulesManager) Compile() { for _, v := range r.Edits { r.Latest.Overrides = append(r.Latest.Overrides, v.Overrides...) r.Latest.Exclusions = append(r.Latest.Exclusions, v.Exclusions...) + r.Latest.ExclusionData = append(r.Latest.ExclusionData, v.ExclusionData...) r.Latest.Actions = append(r.Latest.Actions, v.Actions...) r.Latest.RulesData = append(r.Latest.RulesData, v.RulesData...) r.Latest.CustomRules = append(r.Latest.CustomRules, v.CustomRules...) diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/dyngo/operation.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/dyngo/operation.go index e16d357e9..b5c0a1683 100644 --- a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/dyngo/operation.go +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/dyngo/operation.go @@ -21,13 +21,19 @@ package dyngo import ( + "context" "sync" + "sync/atomic" - "gopkg.in/DataDog/dd-trace-go.v1/internal/log" - - "go.uber.org/atomic" + "gopkg.in/DataDog/dd-trace-go.v1/internal/orchestrion" ) +// LogError is the function used to log errors in the dyngo package. +// This is required because we really want to be able to log errors from dyngo +// but the log package depend on too much packages that we want to instrument. +// So we need to do this to avoid dependency cycles. +var LogError = func(string, ...any) {} + // Operation interface type allowing to register event listeners to the // operation. The event listeners will be automatically removed from the // operation once it finishes so that it no longer can be called on finished @@ -61,6 +67,9 @@ type ResultOf[O Operation] interface { // dispatch calls to the underlying event listener function. type EventListener[O Operation, T any] func(O, T) +// contextKey is used to store in a context.Context the ongoing Operation +type contextKey struct{} + // Atomic *Operation so we can atomically read or swap it. var rootOperation atomic.Pointer[Operation] @@ -86,6 +95,10 @@ type operation struct { disabled bool mu sync.RWMutex + + // inContext is used to determine if RegisterOperation was called to put the Operation in the context tree. + // If so we need to remove it from the context tree when the Operation is finished. + inContext bool } func (o *operation) Parent() Operation { @@ -140,6 +153,17 @@ func NewOperation(parent Operation) Operation { return &operation{parent: parentOp} } +// FromContext looks into the given context (or the GLS if orchestrion is enabled) for a parent Operation and returns it. +func FromContext(ctx context.Context) (Operation, bool) { + ctx = orchestrion.WrapContext(ctx) + if ctx == nil { + return nil, false + } + + op, ok := ctx.Value(contextKey{}).(Operation) + return op, ok +} + // StartOperation starts a new operation along with its arguments and emits a // start event with the operation arguments. func StartOperation[O Operation, E ArgOf[O]](op O, args E) { @@ -150,6 +174,19 @@ func StartOperation[O Operation, E ArgOf[O]](op O, args E) { } } +// StartAndRegisterOperation calls StartOperation and returns RegisterOperation result +func StartAndRegisterOperation[O Operation, E ArgOf[O]](ctx context.Context, op O, args E) context.Context { + StartOperation(op, args) + return RegisterOperation(ctx, op) +} + +// RegisterOperation registers the operation in the context tree. All operations that plan to have children operations +// should call this function to ensure the operation is properly linked in the context tree. +func RegisterOperation(ctx context.Context, op Operation) context.Context { + op.unwrap().inContext = true + return orchestrion.CtxWithValue(ctx, contextKey{}, op) +} + // FinishOperation finishes the operation along with its results and emits a // finish event with the operation results. // The operation is then disabled and its event listeners removed. @@ -160,6 +197,10 @@ func FinishOperation[O Operation, E ResultOf[O]](op O, results E) { o.mu.RLock() defer o.mu.RUnlock() // Deferred and stacked on top of the previously deferred call to o.disable() + if o.inContext { + orchestrion.GLSPopValue(contextKey{}) + } + if o.disabled { return } @@ -281,7 +322,7 @@ func (b *dataBroadcaster) clear() { func emitData[T any](b *dataBroadcaster, v T) { defer func() { if r := recover(); r != nil { - log.Error("appsec: recovered from an unexpected panic from an event listener: %+v", r) + LogError("appsec: recovered from an unexpected panic from an event listener: %+v", r) } }() b.mu.RLock() @@ -312,7 +353,7 @@ func (r *eventRegister) clear() { func emitEvent[O Operation, T any](r *eventRegister, op O, v T) { defer func() { if r := recover(); r != nil { - log.Error("appsec: recovered from an unexpected panic from an event listener: %+v", r) + LogError("appsec: recovered from an unexpected panic from an event listener: %+v", r) } }() r.mu.RLock() diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/graphqlsec/README.md b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/graphqlsec/README.md new file mode 100644 index 000000000..c350c3c34 --- /dev/null +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/graphqlsec/README.md @@ -0,0 +1,25 @@ +## GraphQL Threat Monitoring + +This package provides `dyngo` support for GraphQL operations, which are listened +to according to the following sequence diagram: + +```mermaid +sequenceDiagram + participant Root + participant Request + participant Execution + participant Field + + Root ->>+ Request: graphqlsec.StartRequest(...) + + Request ->>+ Execution: grapgqlsec.StartExecution(...) + + par for each field + Execution ->>+ Field: graphqlsec.StartField(...) + Field -->>- Execution: field.Finish(...) + end + + Execution -->>- Request: execution.Finish(...) + + Request -->>- Root: request.Finish(...) +``` diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/graphqlsec/execution.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/graphqlsec/execution.go new file mode 100644 index 000000000..0599d5e18 --- /dev/null +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/graphqlsec/execution.go @@ -0,0 +1,66 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2016 Datadog, Inc. + +// Package graphql is the GraphQL instrumentation API and contract for AppSec +// defining an abstract run-time representation of AppSec middleware. GraphQL +// integrations must use this package to enable AppSec features for GraphQL, +// which listens to this package's operation events. +package graphqlsec + +import ( + "context" + + "gopkg.in/DataDog/dd-trace-go.v1/internal/log" + + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/dyngo" +) + +type ( + ExecutionOperation struct { + dyngo.Operation + } + + // ExecutionOperationArgs describes arguments passed to a GraphQL query operation. + ExecutionOperationArgs struct { + // Variables is the user-provided variables object for the query. + Variables map[string]any + // Query is the query that is being executed. + Query string + // OperationName is the user-provided operation name for the query. + OperationName string + } + + ExecutionOperationRes struct { + // Data is the data returned from processing the GraphQL operation. + Data any + // Error is the error returned by processing the GraphQL Operation, if any. + Error error + } +) + +// Finish the GraphQL query operation, along with the given results, and emit a finish event up in +// the operation stack. +func (q *ExecutionOperation) Finish(res ExecutionOperationRes) { + dyngo.FinishOperation(q, res) +} + +func (ExecutionOperationArgs) IsArgOf(*ExecutionOperation) {} +func (ExecutionOperationRes) IsResultOf(*ExecutionOperation) {} + +// StartExecutionOperation starts a new GraphQL query operation, along with the given arguments, and +// emits a start event up in the operation stack. The operation is tracked on the returned context, +// and can be extracted later on using FromContext. +func StartExecutionOperation(ctx context.Context, args ExecutionOperationArgs) (context.Context, *ExecutionOperation) { + parent, ok := dyngo.FromContext(ctx) + if !ok { + log.Debug("appsec: StartExecutionOperation: no parent operation found in context") + } + + op := &ExecutionOperation{ + Operation: dyngo.NewOperation(parent), + } + + return dyngo.StartAndRegisterOperation(ctx, op, args), op +} diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/graphqlsec/request.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/graphqlsec/request.go new file mode 100644 index 000000000..70e1f6dff --- /dev/null +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/graphqlsec/request.go @@ -0,0 +1,69 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2016 Datadog, Inc. + +// Package graphql is the GraphQL instrumentation API and contract for AppSec +// defining an abstract run-time representation of AppSec middleware. GraphQL +// integrations must use this package to enable AppSec features for GraphQL, +// which listens to this package's operation events. +package graphqlsec + +import ( + "context" + + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/dyngo" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/trace" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/waf" +) + +type ( + RequestOperation struct { + dyngo.Operation + // used in case we don't have a parent operation + *waf.ContextOperation + } + + // RequestOperationArgs describes arguments passed to a GraphQL request. + RequestOperationArgs struct { + RawQuery string // The raw, not-yet-parsed GraphQL query + OperationName string // The user-provided operation name for the query + Variables map[string]any // The user-provided variables object for this request + } + + RequestOperationRes struct { + // Data is the data returned from processing the GraphQL operation. + Data any + // Error is the error returned by processing the GraphQL Operation, if any. + Error error + } +) + +// Finish the GraphQL query operation, along with the given results, and emit a finish event up in +// the operation stack. +func (op *RequestOperation) Finish(span trace.TagSetter, res RequestOperationRes) { + dyngo.FinishOperation(op, res) + if op.ContextOperation != nil { + op.ContextOperation.Finish(span) + } +} + +func (RequestOperationArgs) IsArgOf(*RequestOperation) {} +func (RequestOperationRes) IsResultOf(*RequestOperation) {} + +// StartRequestOperation starts a new GraphQL request operation, along with the given arguments, and +// emits a start event up in the operation stack. The operation is usually linked to tge global root +// operation. The operation is tracked on the returned context, and can be extracted later on using +// FromContext. +func StartRequestOperation(ctx context.Context, args RequestOperationArgs) (context.Context, *RequestOperation) { + parent, ok := dyngo.FromContext(ctx) + op := &RequestOperation{} + if !ok { // Usually we can find the HTTP Handler Operation as the parent but it's technically optional + op.ContextOperation, ctx = waf.StartContextOperation(ctx) + op.Operation = dyngo.NewOperation(op.ContextOperation) + } else { + op.Operation = dyngo.NewOperation(parent) + } + + return dyngo.StartAndRegisterOperation(ctx, op, args), op +} diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/graphqlsec/resolve.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/graphqlsec/resolve.go new file mode 100644 index 000000000..b7f5fe067 --- /dev/null +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/graphqlsec/resolve.go @@ -0,0 +1,63 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2016 Datadog, Inc. + +package graphqlsec + +import ( + "context" + + "gopkg.in/DataDog/dd-trace-go.v1/internal/log" + + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/dyngo" +) + +type ( + ResolveOperation struct { + dyngo.Operation + } + + // ResolveOperationArgs describes arguments passed to a GraphQL field operation. + ResolveOperationArgs struct { + // TypeName is the name of the field's type + TypeName string + // FieldName is the name of the field + FieldName string + // Arguments is the arguments provided to the field resolver + Arguments map[string]any + // Trivial determines whether the resolution is trivial or not. Leave as false if undetermined. + Trivial bool + } + + ResolveOperationRes struct { + // Data is the data returned from processing the GraphQL operation. + Data any + // Error is the error returned by processing the GraphQL Operation, if any. + Error error + } +) + +// Finish the GraphQL Field operation, along with the given results, and emit a finish event up in +// the operation stack. +func (q *ResolveOperation) Finish(res ResolveOperationRes) { + dyngo.FinishOperation(q, res) +} + +func (ResolveOperationArgs) IsArgOf(*ResolveOperation) {} +func (ResolveOperationRes) IsResultOf(*ResolveOperation) {} + +// StartResolveOperation starts a new GraphQL Resolve operation, along with the given arguments, and +// emits a start event up in the operation stack. The operation is tracked on the returned context, +// and can be extracted later on using FromContext. +func StartResolveOperation(ctx context.Context, args ResolveOperationArgs) (context.Context, *ResolveOperation) { + parent, ok := dyngo.FromContext(ctx) + if !ok { + log.Debug("appsec: StartResolveOperation: no parent operation found in context") + } + + op := &ResolveOperation{ + Operation: dyngo.NewOperation(parent), + } + return dyngo.StartAndRegisterOperation(ctx, op, args), op +} diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/grpcsec/grpc.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/grpcsec/grpc.go new file mode 100644 index 000000000..e6b28e312 --- /dev/null +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/grpcsec/grpc.go @@ -0,0 +1,116 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2016 Datadog, Inc. + +// Package grpcsec is the gRPC instrumentation API and contract for AppSec +// defining an abstract run-time representation of gRPC handlers. +// gRPC integrations must use this package to enable AppSec features for gRPC, +// which listens to this package's operation events. +// +// Abstract gRPC server handler operation definitions. It is based on two +// operations allowing to describe every type of RPC: the HandlerOperation type +// which represents the RPC handler, and the ReceiveOperation type which +// represents the messages the RPC handler receives during its lifetime. +// This means that the ReceiveOperation(s) will happen within the +// HandlerOperation. +// Every type of RPC, unary, client streaming, server streaming, and +// bidirectional streaming RPCs, can be all represented with a HandlerOperation +// having one or several ReceiveOperation. +// The send operation is not required for now and therefore not defined, which +// means that server and bidirectional streaming RPCs currently have the same +// run-time representation as unary and client streaming RPCs. +package grpcsec + +import ( + "context" + "sync/atomic" + + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/dyngo" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/trace" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/waf" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/waf/actions" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/waf/addresses" +) + +type ( + // HandlerOperation represents a gRPC server handler operation. + // It must be created with StartHandlerOperation() and finished with its + // Finish() method. + // Security events observed during the operation lifetime should be added + // to the operation using its AddSecurityEvent() method. + HandlerOperation struct { + dyngo.Operation + *waf.ContextOperation + } + + // HandlerOperationArgs is the grpc handler arguments. + HandlerOperationArgs struct { + // Method is the gRPC method name. + // Corresponds to the address `grpc.server.method`. + Method string + + // RPC metadata received by the gRPC handler. + // Corresponds to the address `grpc.server.request.metadata`. + Metadata map[string][]string + + // RemoteAddr is the IP address of the client that initiated the gRPC request. + // May be used as the address `http.client_ip`. + RemoteAddr string + } + + // HandlerOperationRes is the grpc handler results. Empty as of today. + HandlerOperationRes struct { + // Raw gRPC status code. + // Corresponds to the address `grpc.server.response.status`. + StatusCode int + } +) + +func (HandlerOperationArgs) IsArgOf(*HandlerOperation) {} +func (HandlerOperationRes) IsResultOf(*HandlerOperation) {} + +// StartHandlerOperation starts an gRPC server handler operation, along with the +// given arguments and parent operation, and emits a start event up in the +// operation stack. When parent is nil, the operation is linked to the global +// root operation. +func StartHandlerOperation(ctx context.Context, args HandlerOperationArgs) (context.Context, *HandlerOperation, *atomic.Pointer[actions.BlockGRPC]) { + wafOp, ctx := waf.StartContextOperation(ctx) + op := &HandlerOperation{ + Operation: dyngo.NewOperation(wafOp), + ContextOperation: wafOp, + } + + var block atomic.Pointer[actions.BlockGRPC] + dyngo.OnData(op, func(err *actions.BlockGRPC) { + block.Store(err) + }) + + return dyngo.StartAndRegisterOperation(ctx, op, args), op, &block +} + +// MonitorRequestMessage monitors the gRPC request message body as the WAF address `grpc.server.request.message`. +func MonitorRequestMessage(ctx context.Context, msg any) error { + return waf.RunSimple(ctx, + addresses.NewAddressesBuilder(). + WithGRPCRequestMessage(msg). + Build(), + "appsec: failed to monitor gRPC request message body") +} + +// MonitorResponseMessage monitors the gRPC response message body as the WAF address `grpc.server.response.message`. +func MonitorResponseMessage(ctx context.Context, msg any) error { + return waf.RunSimple(ctx, + addresses.NewAddressesBuilder(). + WithGRPCResponseMessage(msg). + Build(), + "appsec: failed to monitor gRPC response message body") + +} + +// Finish the gRPC handler operation, along with the given results, and emit a +// finish event up in the operation stack. +func (op *HandlerOperation) Finish(span trace.TagSetter, res HandlerOperationRes) { + dyngo.FinishOperation(op, res) + op.ContextOperation.Finish(span) +} diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/httpsec/config.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/httpsec/config.go new file mode 100644 index 000000000..bdbf3af31 --- /dev/null +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/httpsec/config.go @@ -0,0 +1,24 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2016 Datadog, Inc. + +package httpsec + +import "net/http" + +type Config struct { + // OnBlock is a list of callbacks to be invoked when a block decision is made. + OnBlock []func() + // ResponseHeaderCopier provides a way to access response headers for reading + // purposes (the value may be provided by copy). This allows customers to + // apply synchronization if they allow http.ResponseWriter objects to be + // accessed by multiple goroutines. + ResponseHeaderCopier func(http.ResponseWriter) http.Header +} + +var defaultWrapHandlerConfig = &Config{ + ResponseHeaderCopier: func(w http.ResponseWriter) http.Header { + return w.Header() + }, +} diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/httpsec/http.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/httpsec/http.go new file mode 100644 index 000000000..9f81cdc20 --- /dev/null +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/httpsec/http.go @@ -0,0 +1,190 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2016 Datadog, Inc. + +// Package httpsec defines is the HTTP instrumentation API and contract for +// AppSec. It defines an abstract representation of HTTP handlers, along with +// helper functions to wrap (aka. instrument) standard net/http handlers. +// HTTP integrations must use this package to enable AppSec features for HTTP, +// which listens to this package's operation events. +package httpsec + +import ( + "context" + // Blank import needed to use embed for the default blocked response payloads + _ "embed" + "net/http" + "sync" + "sync/atomic" + + "gopkg.in/DataDog/dd-trace-go.v1/ddtrace" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/dyngo" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/waf" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/waf/actions" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/waf/addresses" +) + +// HandlerOperation type representing an HTTP operation. It must be created with +// StartOperation() and finished with its Finish(). +type ( + HandlerOperation struct { + dyngo.Operation + *waf.ContextOperation + mu sync.RWMutex + } + + // HandlerOperationArgs is the HTTP handler operation arguments. + HandlerOperationArgs struct { + Method string + RequestURI string + Host string + RemoteAddr string + Headers map[string][]string + Cookies map[string][]string + QueryParams map[string][]string + PathParams map[string]string + } + + // HandlerOperationRes is the HTTP handler operation results. + HandlerOperationRes struct { + Headers map[string][]string + StatusCode int + } +) + +func (HandlerOperationArgs) IsArgOf(*HandlerOperation) {} +func (HandlerOperationRes) IsResultOf(*HandlerOperation) {} + +func StartOperation(ctx context.Context, args HandlerOperationArgs) (*HandlerOperation, *atomic.Pointer[actions.BlockHTTP], context.Context) { + wafOp, ctx := waf.StartContextOperation(ctx) + op := &HandlerOperation{ + Operation: dyngo.NewOperation(wafOp), + ContextOperation: wafOp, + } + + // We need to use an atomic pointer to store the action because the action may be created asynchronously in the future + var action atomic.Pointer[actions.BlockHTTP] + dyngo.OnData(op, func(a *actions.BlockHTTP) { + action.Store(a) + }) + + return op, &action, dyngo.StartAndRegisterOperation(ctx, op, args) +} + +// Finish the HTTP handler operation and its children operations and write everything to the service entry span. +func (op *HandlerOperation) Finish(res HandlerOperationRes, span ddtrace.Span) { + dyngo.FinishOperation(op, res) + op.ContextOperation.Finish(span) +} + +const monitorBodyErrorLog = ` +"appsec: parsed http body monitoring ignored: could not find the http handler instrumentation metadata in the request context: + the request handler is not being monitored by a middleware function or the provided context is not the expected request context +` + +// MonitorParsedBody starts and finishes the SDK body operation. +// This function should not be called when AppSec is disabled in order to +// get preciser error logs. +func MonitorParsedBody(ctx context.Context, body any) error { + return waf.RunSimple(ctx, + addresses.NewAddressesBuilder(). + WithRequestBody(body). + Build(), + monitorBodyErrorLog, + ) +} + +// Return the map of parsed cookies if any and following the specification of +// the rule address `server.request.cookies`. +func makeCookies(parsed []*http.Cookie) map[string][]string { + if len(parsed) == 0 { + return nil + } + cookies := make(map[string][]string, len(parsed)) + for _, c := range parsed { + cookies[c.Name] = append(cookies[c.Name], c.Value) + } + return cookies +} + +// BeforeHandle contains the appsec functionality that should be executed before a http.Handler runs. +// It returns the modified http.ResponseWriter and http.Request, an additional afterHandle function +// that should be executed after the Handler runs, and a handled bool that instructs if the request has been handled +// or not - in case it was handled, the original handler should not run. +func BeforeHandle( + w http.ResponseWriter, + r *http.Request, + span ddtrace.Span, + pathParams map[string]string, + opts *Config, +) (http.ResponseWriter, *http.Request, func(), bool) { + if opts == nil { + opts = defaultWrapHandlerConfig + } else if opts.ResponseHeaderCopier == nil { + opts.ResponseHeaderCopier = defaultWrapHandlerConfig.ResponseHeaderCopier + } + + op, blockAtomic, ctx := StartOperation(r.Context(), HandlerOperationArgs{ + Method: r.Method, + RequestURI: r.RequestURI, + Host: r.Host, + RemoteAddr: r.RemoteAddr, + Headers: r.Header, + Cookies: makeCookies(r.Cookies()), + QueryParams: r.URL.Query(), + PathParams: pathParams, + }) + tr := r.WithContext(ctx) + + afterHandle := func() { + var statusCode int + if res, ok := w.(interface{ Status() int }); ok { + statusCode = res.Status() + } + op.Finish(HandlerOperationRes{ + Headers: opts.ResponseHeaderCopier(w), + StatusCode: statusCode, + }, span) + + // Execute the onBlock functions to make sure blocking works properly + // in case we are instrumenting the Gin framework + if blockPtr := blockAtomic.Load(); blockPtr != nil { + for _, f := range opts.OnBlock { + f() + } + + if blockPtr.Handler != nil { + blockPtr.Handler.ServeHTTP(w, tr) + } + } + } + + handled := false + if blockPtr := blockAtomic.Load(); blockPtr != nil && blockPtr.Handler != nil { + // handler is replaced + blockPtr.Handler.ServeHTTP(w, tr) + blockPtr.Handler = nil + handled = true + } + return w, tr, afterHandle, handled +} + +// WrapHandler wraps the given HTTP handler with the abstract HTTP operation defined by HandlerOperationArgs and +// HandlerOperationRes. +// The onBlock params are used to cleanup the context when needed. +// It is a specific patch meant for Gin, for which we must abort the +// context since it uses a queue of handlers and it's the only way to make +// sure other queued handlers don't get executed. +// TODO: this patch must be removed/improved when we rework our actions/operations system +func WrapHandler(handler http.Handler, span ddtrace.Span, pathParams map[string]string, opts *Config) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + tw, tr, afterHandle, handled := BeforeHandle(w, r, span, pathParams, opts) + defer afterHandle() + if handled { + return + } + + handler.ServeHTTP(tw, tr) + }) +} diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/httpsec/roundtripper.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/httpsec/roundtripper.go new file mode 100644 index 000000000..8a7f1f244 --- /dev/null +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/httpsec/roundtripper.go @@ -0,0 +1,71 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2016 Datadog, Inc. + +package httpsec + +import ( + "context" + "sync" + + "gopkg.in/DataDog/dd-trace-go.v1/appsec/events" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/dyngo" + "gopkg.in/DataDog/dd-trace-go.v1/internal/log" +) + +var badInputContextOnce sync.Once + +type ( + RoundTripOperation struct { + dyngo.Operation + } + + // RoundTripOperationArgs is the round trip operation arguments. + RoundTripOperationArgs struct { + // URL corresponds to the address `server.io.net.url`. + URL string + } + + // RoundTripOperationRes is the round trip operation results. + RoundTripOperationRes struct{} +) + +func (RoundTripOperationArgs) IsArgOf(*RoundTripOperation) {} +func (RoundTripOperationRes) IsResultOf(*RoundTripOperation) {} + +func ProtectRoundTrip(ctx context.Context, url string) error { + opArgs := RoundTripOperationArgs{ + URL: url, + } + + parent, _ := dyngo.FromContext(ctx) + if parent == nil { // No parent operation => we can't monitor the request + badInputContextOnce.Do(func() { + log.Debug("appsec: outgoing http request monitoring ignored: could not find the handler " + + "instrumentation metadata in the request context: the request handler is not being monitored by a " + + "middleware function or the incoming request context has not be forwarded correctly to the roundtripper") + }) + return nil + } + + op := &RoundTripOperation{ + Operation: dyngo.NewOperation(parent), + } + + var err *events.BlockingSecurityEvent + // TODO: move the data listener as a setup function of httpsec.StartRoundTripperOperation(ars, ) + dyngo.OnData(op, func(e *events.BlockingSecurityEvent) { + err = e + }) + + dyngo.StartOperation(op, opArgs) + dyngo.FinishOperation(op, RoundTripOperationRes{}) + + if err != nil { + log.Debug("appsec: outgoing http request blocked by the WAF on URL: %s", url) + return err + } + + return nil +} diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/ossec/lfi.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/ossec/lfi.go new file mode 100644 index 000000000..b769d4c40 --- /dev/null +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/ossec/lfi.go @@ -0,0 +1,41 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. + +package ossec + +import ( + "io/fs" + + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/dyngo" +) + +type ( + // OpenOperation type embodies any kind of function calls that will result in a call to an open(2) syscall + OpenOperation struct { + dyngo.Operation + blockErr error + } + + // OpenOperationArgs is the arguments for an open operation + OpenOperationArgs struct { + // Path is the path to the file to be opened + Path string + // Flags are the flags passed to the open(2) syscall + Flags int + // Perms are the permissions passed to the open(2) syscall if the creation of a file is required + Perms fs.FileMode + } + + // OpenOperationRes is the result of an open operation + OpenOperationRes[File any] struct { + // File is the file descriptor returned by the open(2) syscall + File *File + // Err is the error returned by the function + Err *error + } +) + +func (OpenOperationArgs) IsArgOf(*OpenOperation) {} +func (OpenOperationRes[File]) IsResultOf(*OpenOperation) {} diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/sharedsec/actions.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/sharedsec/actions.go deleted file mode 100644 index c082f2542..000000000 --- a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/sharedsec/actions.go +++ /dev/null @@ -1,138 +0,0 @@ -// Unless explicitly stated otherwise all files in this repository are licensed -// under the Apache License Version 2.0. -// This product includes software developed at Datadog (https://www.datadoghq.com/). -// Copyright 2022 Datadog, Inc. - -package sharedsec - -import ( - _ "embed" // Blank import - "errors" - "net/http" - "os" - "strings" - - "gopkg.in/DataDog/dd-trace-go.v1/internal/log" -) - -// blockedTemplateJSON is the default JSON template used to write responses for blocked requests -// -//go:embed blocked-template.json -var blockedTemplateJSON []byte - -// blockedTemplateHTML is the default HTML template used to write responses for blocked requests -// -//go:embed blocked-template.html -var blockedTemplateHTML []byte - -const ( - envBlockedTemplateHTML = "DD_APPSEC_HTTP_BLOCKED_TEMPLATE_HTML" - envBlockedTemplateJSON = "DD_APPSEC_HTTP_BLOCKED_TEMPLATE_JSON" -) - -func init() { - for env, template := range map[string]*[]byte{envBlockedTemplateJSON: &blockedTemplateJSON, envBlockedTemplateHTML: &blockedTemplateHTML} { - if path, ok := os.LookupEnv(env); ok { - if t, err := os.ReadFile(path); err != nil { - log.Error("Could not read template at %s: %v", path, err) - } else { - *template = t - } - } - - } -} - -type ( - // Action represents a WAF action. - // It holds the HTTP and gRPC handlers to be used instead of the regular - // request handler when said action is executed. - Action struct { - http http.Handler - grpc GRPCWrapper - blocking bool - } - - // Actions represents a set of action bindings to an action name. - Actions map[string]*Action - - // GRPCWrapper is an opaque prototype abstraction for a gRPC handler (to avoid importing grpc) - // that takes metadata as input and returns a status code and an error - // TODO: rely on strongly typed actions (with the actual grpc types) by introducing WAF constructors - // living in the contrib packages, along with their dependencies - something like `appsec.RegisterWAFConstructor(newGRPCWAF)` - // Such constructors would receive the full appsec config and rules, so that they would be able to build - // specific blocking actions. - GRPCWrapper func(map[string][]string) (uint32, error) -) - -// Blocking returns true if the action object represents a request blocking action -func (a *Action) Blocking() bool { - return a.blocking -} - -// NewBlockHandler creates, initializes and returns a new BlockRequestAction -func NewBlockHandler(status int, template string) http.Handler { - htmlHandler := newBlockRequestHandler(status, "text/html", blockedTemplateHTML) - jsonHandler := newBlockRequestHandler(status, "application/json", blockedTemplateJSON) - switch template { - case "json": - return jsonHandler - case "html": - return htmlHandler - default: - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - h := jsonHandler - hdr := r.Header.Get("Accept") - htmlIdx := strings.Index(hdr, "text/html") - jsonIdx := strings.Index(hdr, "application/json") - // Switch to html handler if text/html comes before application/json in the Accept header - if htmlIdx != -1 && (jsonIdx == -1 || htmlIdx < jsonIdx) { - h = htmlHandler - } - h.ServeHTTP(w, r) - }) - } -} - -func newBlockRequestHandler(status int, ct string, payload []byte) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", ct) - w.WriteHeader(status) - w.Write(payload) - }) -} - -func newGRPCBlockHandler(status int) GRPCWrapper { - return func(_ map[string][]string) (uint32, error) { - return uint32(status), errors.New("Request blocked") - } -} - -// NewBlockRequestAction creates an action for the "block" action type -func NewBlockRequestAction(httpStatus, grpcStatus int, template string) *Action { - return &Action{ - http: NewBlockHandler(httpStatus, template), - grpc: newGRPCBlockHandler(grpcStatus), - blocking: true, - } -} - -// NewRedirectRequestAction creates an action for the "redirect" action type -func NewRedirectRequestAction(status int, loc string) *Action { - return &Action{ - http: http.RedirectHandler(loc, status), - // gRPC is not handled by our SRB RFCs so far - // Use the default block handler for now - grpc: newGRPCBlockHandler(10), - } -} - -// HTTP returns the HTTP handler linked to the action object -func (a *Action) HTTP() http.Handler { - return a.http -} - -// GRPC returns the gRPC handler linked to the action object -func (a *Action) GRPC() GRPCWrapper { - return a.grpc -} diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/sharedsec/shared.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/sharedsec/shared.go deleted file mode 100644 index 715afc45c..000000000 --- a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/sharedsec/shared.go +++ /dev/null @@ -1,71 +0,0 @@ -// Unless explicitly stated otherwise all files in this repository are licensed -// under the Apache License Version 2.0. -// This product includes software developed at Datadog (https://www.datadoghq.com/). -// Copyright 2023 Datadog, Inc. - -package sharedsec - -import ( - "context" - "reflect" - - "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/dyngo" - "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener" - "gopkg.in/DataDog/dd-trace-go.v1/internal/log" -) - -type ( - // UserIDOperation type representing a call to appsec.SetUser(). It gets both created and destroyed in a single - // call to ExecuteUserIDOperation - UserIDOperation struct { - dyngo.Operation - } - // UserIDOperationArgs is the user ID operation arguments. - UserIDOperationArgs struct { - UserID string - } - // UserIDOperationRes is the user ID operation results. - UserIDOperationRes struct{} - - // OnUserIDOperationStart function type, called when a user ID - // operation starts. - OnUserIDOperationStart func(operation *UserIDOperation, args UserIDOperationArgs) -) - -var userIDOperationArgsType = reflect.TypeOf((*UserIDOperationArgs)(nil)).Elem() - -// ExecuteUserIDOperation starts and finishes the UserID operation by emitting a dyngo start and finish events -// An error is returned if the user associated to that operation must be blocked -func ExecuteUserIDOperation(parent dyngo.Operation, args UserIDOperationArgs) error { - var err error - op := &UserIDOperation{Operation: dyngo.NewOperation(parent)} - dyngo.OnData(op, func(e error) { err = e }) - dyngo.StartOperation(op, args) - dyngo.FinishOperation(op, UserIDOperationRes{}) - return err -} - -// ListenedType returns the type a OnUserIDOperationStart event listener -// listens to, which is the UserIDOperationStartArgs type. -func (OnUserIDOperationStart) ListenedType() reflect.Type { return userIDOperationArgsType } - -// Call the underlying event listener function by performing the type-assertion -// on v whose type is the one returned by ListenedType(). -func (f OnUserIDOperationStart) Call(op dyngo.Operation, v interface{}) { - f(op.(*UserIDOperation), v.(UserIDOperationArgs)) -} - -// MonitorUser starts and finishes a UserID operation. -// A call to the WAF is made to check the user ID and an error is returned if the -// user should be blocked. The return value is nil otherwise. -func MonitorUser(ctx context.Context, userID string) error { - if parent, ok := ctx.Value(listener.ContextKey{}).(dyngo.Operation); ok { - return ExecuteUserIDOperation(parent, UserIDOperationArgs{UserID: userID}) - } - log.Error("appsec: user ID monitoring ignored: could not find the http handler instrumentation metadata in the request context: the request handler is not being monitored by a middleware function or the provided context is not the expected request context") - return nil - -} - -func (UserIDOperationArgs) IsArgOf(*UserIDOperation) {} -func (UserIDOperationRes) IsResultOf(*UserIDOperation) {} diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/sqlsec/sql.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/sqlsec/sql.go new file mode 100644 index 000000000..1c888d9f8 --- /dev/null +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/sqlsec/sql.go @@ -0,0 +1,71 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2016 Datadog, Inc. + +package sqlsec + +import ( + "context" + "sync" + + "gopkg.in/DataDog/dd-trace-go.v1/appsec/events" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/dyngo" + "gopkg.in/DataDog/dd-trace-go.v1/internal/log" +) + +var badInputContextOnce sync.Once + +type ( + SQLOperation struct { + dyngo.Operation + } + + SQLOperationArgs struct { + // Query corresponds to the addres `server.db.statement` + Query string + // Driver corresponds to the addres `server.db.system` + Driver string + } + SQLOperationRes struct{} +) + +func (SQLOperationArgs) IsArgOf(*SQLOperation) {} +func (SQLOperationRes) IsResultOf(*SQLOperation) {} + +func ProtectSQLOperation(ctx context.Context, query, driver string) error { + opArgs := SQLOperationArgs{ + Query: query, + Driver: driver, + } + + parent, _ := dyngo.FromContext(ctx) + if parent == nil { // No parent operation => we can't monitor the request + badInputContextOnce.Do(func() { + log.Debug("appsec: outgoing SQL operation monitoring ignored: could not find the handler " + + "instrumentation metadata in the request context: the request handler is not being monitored by a " + + "middleware function or the incoming request context has not be forwarded correctly to the SQL connection") + }) + return nil + } + + op := &SQLOperation{ + Operation: dyngo.NewOperation(parent), + } + + var err *events.BlockingSecurityEvent + // TODO: move the data listener as a setup function of SQLsec.StartSQLOperation(ars, ) + dyngo.OnData(op, func(e *events.BlockingSecurityEvent) { + err = e + }) + + dyngo.StartOperation(op, opArgs) + dyngo.FinishOperation(op, SQLOperationRes{}) + + if err != nil { + log.Debug("appsec: outgoing SQL operation blocked by the WAF") + return err + } + + return nil +} diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/trace/service_entry_span.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/trace/service_entry_span.go new file mode 100644 index 000000000..98e14b092 --- /dev/null +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/trace/service_entry_span.go @@ -0,0 +1,158 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. + +package trace + +import ( + "context" + "encoding/json" + "sync" + + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/dyngo" + "gopkg.in/DataDog/dd-trace-go.v1/internal/log" +) + +type ( + // ServiceEntrySpanOperation is a dyngo.Operation that holds a the first span of a service. Usually a http or grpc span. + ServiceEntrySpanOperation struct { + dyngo.Operation + tags map[string]any + jsonTags map[string]any + mu sync.Mutex + } + + // ServiceEntrySpanArgs is the arguments for a ServiceEntrySpanOperation + ServiceEntrySpanArgs struct{} + + // ServiceEntrySpanTag is a key value pair event that is used to tag a service entry span + ServiceEntrySpanTag struct { + Key string + Value any + } + + // JSONServiceEntrySpanTag is a key value pair event that is used to tag a service entry span + // It will be serialized as JSON when added to the span + JSONServiceEntrySpanTag struct { + Key string + Value any + } + + // ServiceEntrySpanTagsBulk is a bulk event that is used to send tags to a service entry span + ServiceEntrySpanTagsBulk struct { + Tags []JSONServiceEntrySpanTag + SerializableTags []JSONServiceEntrySpanTag + } +) + +func (ServiceEntrySpanArgs) IsArgOf(*ServiceEntrySpanOperation) {} + +// SetTag adds the key/value pair to the tags to add to the service entry span +func (op *ServiceEntrySpanOperation) SetTag(key string, value any) { + op.mu.Lock() + defer op.mu.Unlock() + op.tags[key] = value +} + +// SetSerializableTag adds the key/value pair to the tags to add to the service entry span. +// The value MAY be serialized as JSON if necessary but simple types will not be serialized. +func (op *ServiceEntrySpanOperation) SetSerializableTag(key string, value any) { + op.mu.Lock() + defer op.mu.Unlock() + op.setSerializableTag(key, value) +} + +// SetSerializableTags adds the key/value pairs to the tags to add to the service entry span. +// Values MAY be serialized as JSON if necessary but simple types will not be serialized. +func (op *ServiceEntrySpanOperation) SetSerializableTags(tags map[string]any) { + op.mu.Lock() + defer op.mu.Unlock() + for key, value := range tags { + op.setSerializableTag(key, value) + } +} + +func (op *ServiceEntrySpanOperation) setSerializableTag(key string, value any) { + switch value.(type) { + case string, int8, int16, int32, int64, uint8, uint16, uint32, uint64, float32, float64, bool: + op.tags[key] = value + default: + op.jsonTags[key] = value + } +} + +// SetTags fills the span tags using the key/value pairs found in `tags` +func (op *ServiceEntrySpanOperation) SetTags(tags map[string]any) { + op.mu.Lock() + defer op.mu.Unlock() + for k, v := range tags { + op.tags[k] = v + } +} + +// SetStringTags fills the span tags using the key/value pairs found in `tags` +func (op *ServiceEntrySpanOperation) SetStringTags(tags map[string]string) { + op.mu.Lock() + defer op.mu.Unlock() + for k, v := range tags { + op.tags[k] = v + } +} + +// OnServiceEntrySpanTagEvent is a callback that is called when a dyngo.OnData is triggered with a ServiceEntrySpanTag event +func (op *ServiceEntrySpanOperation) OnServiceEntrySpanTagEvent(tag ServiceEntrySpanTag) { + op.SetTag(tag.Key, tag.Value) +} + +// OnJSONServiceEntrySpanTagEvent is a callback that is called when a dyngo.OnData is triggered with a JSONServiceEntrySpanTag event +func (op *ServiceEntrySpanOperation) OnJSONServiceEntrySpanTagEvent(tag JSONServiceEntrySpanTag) { + op.SetSerializableTag(tag.Key, tag.Value) +} + +// OnServiceEntrySpanTagsBulkEvent is a callback that is called when a dyngo.OnData is triggered with a ServiceEntrySpanTagsBulk event +func (op *ServiceEntrySpanOperation) OnServiceEntrySpanTagsBulkEvent(bulk ServiceEntrySpanTagsBulk) { + for _, v := range bulk.Tags { + op.SetTag(v.Key, v.Value) + } + + for _, v := range bulk.SerializableTags { + op.SetSerializableTag(v.Key, v.Value) + } +} + +// OnSpanTagEvent is a listener for SpanTag events. +func (op *ServiceEntrySpanOperation) OnSpanTagEvent(tag SpanTag) { + op.SetTag(tag.Key, tag.Value) +} + +func StartServiceEntrySpanOperation(ctx context.Context) (*ServiceEntrySpanOperation, context.Context) { + parent, _ := dyngo.FromContext(ctx) + op := &ServiceEntrySpanOperation{ + Operation: dyngo.NewOperation(parent), + tags: make(map[string]any), + jsonTags: make(map[string]any), + } + return op, dyngo.StartAndRegisterOperation(ctx, op, ServiceEntrySpanArgs{}) +} + +func (op *ServiceEntrySpanOperation) Finish(span TagSetter) { + if _, ok := span.(*NoopTagSetter); ok { // If the span is a NoopTagSetter or is nil, we don't need to set any tags + return + } + + op.mu.Lock() + defer op.mu.Unlock() + + for k, v := range op.tags { + span.SetTag(k, v) + } + + for k, v := range op.jsonTags { + strValue, err := json.Marshal(v) + if err != nil { + log.Debug("appsec: failed to marshal tag %s: %v", k, err) + } + span.SetTag(k, string(strValue)) + } +} diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/trace/span.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/trace/span.go new file mode 100644 index 000000000..d6614f90d --- /dev/null +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/trace/span.go @@ -0,0 +1,67 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. + +package trace + +import ( + "context" + "sync" + + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/dyngo" +) + +type ( + // SpanOperation is a dyngo.Operation that holds a ddtrace.Span. + // It used as a middleware for appsec code and the tracer code + // hopefully some day this operation will create spans instead of simply using them + SpanOperation struct { + dyngo.Operation + tags map[string]any + mu sync.Mutex + } + + // SpanArgs is the arguments for a SpanOperation + SpanArgs struct{} + + // SpanTag is a key value pair event that is used to tag the current span + SpanTag struct { + Key string + Value any + } +) + +func (SpanArgs) IsArgOf(*SpanOperation) {} + +// SetTag adds the key/value pair to the tags to add to the span +func (op *SpanOperation) SetTag(key string, value any) { + op.mu.Lock() + defer op.mu.Unlock() + op.tags[key] = value +} + +// OnSpanTagEvent is a listener for SpanTag events. +func (op *SpanOperation) OnSpanTagEvent(tag SpanTag) { + op.SetTag(tag.Key, tag.Value) +} + +func StartSpanOperation(ctx context.Context) (*SpanOperation, context.Context) { + op := &SpanOperation{ + tags: make(map[string]any), + } + return op, dyngo.StartAndRegisterOperation(ctx, op, SpanArgs{}) +} + +func (op *SpanOperation) Finish(span TagSetter) { + if _, ok := span.(*NoopTagSetter); ok { // If the span is a NoopTagSetter or is nil, we don't need to set any tags + return + } + + op.mu.Lock() + defer op.mu.Unlock() + + for k, v := range op.tags { + span.SetTag(k, v) + } +} diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/trace/tag_setter.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/trace/tag_setter.go new file mode 100644 index 000000000..a7f5bc194 --- /dev/null +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/trace/tag_setter.go @@ -0,0 +1,29 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. + +package trace + +// TagSetter is the interface needed to set a span tag. +type TagSetter interface { + SetTag(string, any) +} + +// NoopTagSetter is a TagSetter that does nothing. Useful when no tracer +// Span is available, but a TagSetter is assumed. +type NoopTagSetter struct{} + +func (NoopTagSetter) SetTag(string, any) { + // Do nothing +} + +type TestTagSetter map[string]any + +func (t TestTagSetter) SetTag(key string, value any) { + t[key] = value +} + +func (t TestTagSetter) Tags() map[string]any { + return t +} diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/usersec/user.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/usersec/user.go new file mode 100644 index 000000000..50a4352e6 --- /dev/null +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/usersec/user.go @@ -0,0 +1,51 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. + +package usersec + +import ( + "context" + + "gopkg.in/DataDog/dd-trace-go.v1/appsec/events" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/dyngo" +) + +const errorLog = ` +appsec: user login monitoring ignored: could not find the http handler instrumentation metadata in the request context: + the request handler is not being monitored by a middleware function or the provided context is not the expected request context +` + +type ( + // UserLoginOperation type representing a call to appsec.SetUser(). It gets both created and destroyed in a single + // call to ExecuteUserIDOperation + UserLoginOperation struct { + dyngo.Operation + } + // UserLoginOperationArgs is the user ID operation arguments. + UserLoginOperationArgs struct{} + + // UserLoginOperationRes is the user ID operation results. + UserLoginOperationRes struct { + UserID string + SessionID string + Success bool + } +) + +func StartUserLoginOperation(ctx context.Context, args UserLoginOperationArgs) (*UserLoginOperation, *error) { + parent, _ := dyngo.FromContext(ctx) + op := &UserLoginOperation{Operation: dyngo.NewOperation(parent)} + var err error + dyngo.OnData(op, func(e *events.BlockingSecurityEvent) { err = e }) + dyngo.StartOperation(op, args) + return op, &err +} + +func (op *UserLoginOperation) Finish(args UserLoginOperationRes) { + dyngo.FinishOperation(op, args) +} + +func (UserLoginOperationArgs) IsArgOf(*UserLoginOperation) {} +func (UserLoginOperationRes) IsResultOf(*UserLoginOperation) {} diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/waf/actions/actions.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/waf/actions/actions.go new file mode 100644 index 000000000..4eabcfaff --- /dev/null +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/waf/actions/actions.go @@ -0,0 +1,56 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. + +package actions + +import ( + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/dyngo" + "gopkg.in/DataDog/dd-trace-go.v1/internal/log" +) + +type ( + // Action is a generic interface that represents any WAF action + Action interface { + EmitData(op dyngo.Operation) + } +) + +type actionHandler func(map[string]any) []Action + +// actionHandlers is a map of action types to their respective handler functions +// It is populated by the init functions of the actions packages +var actionHandlers = map[string]actionHandler{} + +func registerActionHandler(aType string, handler actionHandler) { + if _, ok := actionHandlers[aType]; ok { + log.Warn("appsec: action type `%s` already registered", aType) + return + } + actionHandlers[aType] = handler +} + +// SendActionEvents sends the relevant actions to the operation's data listener. +// It returns true if at least one of those actions require interrupting the request handler +// When SDKError is not nil, this error is sent to the op with EmitData so that the invoked SDK can return it +func SendActionEvents(op dyngo.Operation, actions map[string]any) { + for aType, params := range actions { + log.Debug("appsec: processing %s action with params %v", aType, params) + params, ok := params.(map[string]any) + if !ok { + log.Debug("appsec: could not cast action params to map[string]any from %T", params) + continue + } + + actionHandler, ok := actionHandlers[aType] + if !ok { + log.Debug("appsec: unknown action type `%s`", aType) + continue + } + + for _, a := range actionHandler(params) { + a.EmitData(op) + } + } +} diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/waf/actions/block.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/waf/actions/block.go new file mode 100644 index 000000000..ae802b60b --- /dev/null +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/waf/actions/block.go @@ -0,0 +1,161 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. + +package actions + +import ( + _ "embed" // embed is used to embed the blocked-template.json and blocked-template.html files + "net/http" + "os" + "strings" + + "github.com/mitchellh/mapstructure" + + "gopkg.in/DataDog/dd-trace-go.v1/appsec/events" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/dyngo" + "gopkg.in/DataDog/dd-trace-go.v1/internal/log" +) + +// blockedTemplateJSON is the default JSON template used to write responses for blocked requests +// +//go:embed blocked-template.json +var blockedTemplateJSON []byte + +// blockedTemplateHTML is the default HTML template used to write responses for blocked requests +// +//go:embed blocked-template.html +var blockedTemplateHTML []byte + +const ( + envBlockedTemplateHTML = "DD_APPSEC_HTTP_BLOCKED_TEMPLATE_HTML" + envBlockedTemplateJSON = "DD_APPSEC_HTTP_BLOCKED_TEMPLATE_JSON" +) + +func init() { + for env, template := range map[string]*[]byte{envBlockedTemplateJSON: &blockedTemplateJSON, envBlockedTemplateHTML: &blockedTemplateHTML} { + if path, ok := os.LookupEnv(env); ok { + if t, err := os.ReadFile(path); err != nil { + log.Error("Could not read template at %s: %v", path, err) + } else { + *template = t + } + } + } + + registerActionHandler("block_request", NewBlockAction) +} + +type ( + // blockActionParams are the dynamic parameters to be provided to a "block_request" + // action type upon invocation + blockActionParams struct { + // GRPCStatusCode is the gRPC status code to be returned. Since 0 is the OK status, the value is nullable to + // be able to distinguish between unset and defaulting to Abort (10), or set to OK (0). + GRPCStatusCode *int `mapstructure:"grpc_status_code,omitempty"` + StatusCode int `mapstructure:"status_code"` + Type string `mapstructure:"type,omitempty"` + } + // GRPCWrapper is an opaque prototype abstraction for a gRPC handler (to avoid importing grpc) + // that returns a status code and an error + GRPCWrapper func() (uint32, error) + + // BlockGRPC are actions that interact with a GRPC request flow + BlockGRPC struct { + GRPCWrapper + } + + // BlockHTTP are actions that interact with an HTTP request flow + BlockHTTP struct { + http.Handler + } +) + +func (a *BlockGRPC) EmitData(op dyngo.Operation) { + dyngo.EmitData(op, a) + dyngo.EmitData(op, &events.BlockingSecurityEvent{}) +} + +func (a *BlockHTTP) EmitData(op dyngo.Operation) { + dyngo.EmitData(op, a) + dyngo.EmitData(op, &events.BlockingSecurityEvent{}) +} + +func newGRPCBlockRequestAction(status int) *BlockGRPC { + return &BlockGRPC{GRPCWrapper: newGRPCBlockHandler(status)} +} + +func newGRPCBlockHandler(status int) GRPCWrapper { + return func() (uint32, error) { + return uint32(status), &events.BlockingSecurityEvent{} + } +} + +func blockParamsFromMap(params map[string]any) (blockActionParams, error) { + grpcCode := 10 + p := blockActionParams{ + Type: "auto", + StatusCode: 403, + GRPCStatusCode: &grpcCode, + } + + if err := mapstructure.WeakDecode(params, &p); err != nil { + return p, err + } + + if p.GRPCStatusCode == nil { + p.GRPCStatusCode = &grpcCode + } + + return p, nil +} + +// NewBlockAction creates an action for the "block_request" action type +func NewBlockAction(params map[string]any) []Action { + p, err := blockParamsFromMap(params) + if err != nil { + log.Debug("appsec: couldn't decode redirect action parameters") + return nil + } + return []Action{ + newHTTPBlockRequestAction(p.StatusCode, p.Type), + newGRPCBlockRequestAction(*p.GRPCStatusCode), + } +} + +func newHTTPBlockRequestAction(status int, template string) *BlockHTTP { + return &BlockHTTP{Handler: newBlockHandler(status, template)} +} + +// newBlockHandler creates, initializes and returns a new BlockRequestAction +func newBlockHandler(status int, template string) http.Handler { + htmlHandler := newBlockRequestHandler(status, "text/html", blockedTemplateHTML) + jsonHandler := newBlockRequestHandler(status, "application/json", blockedTemplateJSON) + switch template { + case "json": + return jsonHandler + case "html": + return htmlHandler + default: + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + h := jsonHandler + hdr := r.Header.Get("Accept") + htmlIdx := strings.Index(hdr, "text/html") + jsonIdx := strings.Index(hdr, "application/json") + // Switch to html handler if text/html comes before application/json in the Accept header + if htmlIdx != -1 && (jsonIdx == -1 || htmlIdx < jsonIdx) { + h = htmlHandler + } + h.ServeHTTP(w, r) + }) + } +} + +func newBlockRequestHandler(status int, ct string, payload []byte) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", ct) + w.WriteHeader(status) + w.Write(payload) + }) +} diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/sharedsec/blocked-template.html b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/waf/actions/blocked-template.html similarity index 100% rename from vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/sharedsec/blocked-template.html rename to vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/waf/actions/blocked-template.html diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/sharedsec/blocked-template.json b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/waf/actions/blocked-template.json similarity index 78% rename from vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/sharedsec/blocked-template.json rename to vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/waf/actions/blocked-template.json index 885d766c1..12ae29696 100644 --- a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/sharedsec/blocked-template.json +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/waf/actions/blocked-template.json @@ -1 +1 @@ -{"errors":[{"title":"You've been blocked","detail":"Sorry, you cannot access this page. Please contact the customer service team. Security provided by Datadog."}]} +{"errors":[{"title":"You've been blocked","detail":"Sorry, you cannot access this page. Please contact the customer service team. Security provided by Datadog."}]} \ No newline at end of file diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/waf/actions/http_redirect.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/waf/actions/http_redirect.go new file mode 100644 index 000000000..3cdca4c81 --- /dev/null +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/waf/actions/http_redirect.go @@ -0,0 +1,54 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. + +package actions + +import ( + "net/http" + + "github.com/mitchellh/mapstructure" + + "gopkg.in/DataDog/dd-trace-go.v1/internal/log" +) + +// redirectActionParams are the dynamic parameters to be provided to a "redirect_request" +// action type upon invocation +type redirectActionParams struct { + Location string `mapstructure:"location,omitempty"` + StatusCode int `mapstructure:"status_code"` +} + +func init() { + registerActionHandler("redirect_request", NewRedirectAction) +} + +func redirectParamsFromMap(params map[string]any) (redirectActionParams, error) { + var p redirectActionParams + err := mapstructure.WeakDecode(params, &p) + return p, err +} + +func newRedirectRequestAction(status int, loc string) *BlockHTTP { + // Default to 303 if status is out of redirection codes bounds + if status < http.StatusMultipleChoices || status >= http.StatusBadRequest { + status = http.StatusSeeOther + } + + // If location is not set we fall back on a default block action + if loc == "" { + return &BlockHTTP{Handler: newBlockHandler(http.StatusForbidden, string(blockedTemplateJSON))} + } + return &BlockHTTP{Handler: http.RedirectHandler(loc, status)} +} + +// NewRedirectAction creates an action for the "redirect_request" action type +func NewRedirectAction(params map[string]any) []Action { + p, err := redirectParamsFromMap(params) + if err != nil { + log.Debug("appsec: couldn't decode redirect action parameters") + return nil + } + return []Action{newRedirectRequestAction(p.StatusCode, p.Location)} +} diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/waf/actions/stacktrace.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/waf/actions/stacktrace.go new file mode 100644 index 000000000..47b4dd607 --- /dev/null +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/waf/actions/stacktrace.go @@ -0,0 +1,44 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. + +package actions + +import ( + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/dyngo" + "gopkg.in/DataDog/dd-trace-go.v1/internal/log" + "gopkg.in/DataDog/dd-trace-go.v1/internal/stacktrace" +) + +func init() { + registerActionHandler("generate_stack", NewStackTraceAction) +} + +// StackTraceAction are actions that generate a stacktrace +type StackTraceAction struct { + Event *stacktrace.Event +} + +func (a *StackTraceAction) EmitData(op dyngo.Operation) { dyngo.EmitData(op, a) } + +// NewStackTraceAction creates an action for the "stacktrace" action type +func NewStackTraceAction(params map[string]any) []Action { + id, ok := params["stack_id"] + if !ok { + log.Debug("appsec: could not read stack_id parameter for generate_stack action") + return nil + } + + strID, ok := id.(string) + if !ok { + log.Debug("appsec: could not cast stacktrace ID to string") + return nil + } + + return []Action{ + &StackTraceAction{ + stacktrace.NewEvent(stacktrace.ExploitEvent, stacktrace.WithID(strID)), + }, + } +} diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/waf/addresses/addresses.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/waf/addresses/addresses.go new file mode 100644 index 000000000..03163df23 --- /dev/null +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/waf/addresses/addresses.go @@ -0,0 +1,40 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. + +package addresses + +const ( + ServerRequestMethodAddr = "server.request.method" + ServerRequestRawURIAddr = "server.request.uri.raw" + ServerRequestHeadersNoCookiesAddr = "server.request.headers.no_cookies" + ServerRequestCookiesAddr = "server.request.cookies" + ServerRequestQueryAddr = "server.request.query" + ServerRequestPathParamsAddr = "server.request.path_params" + ServerRequestBodyAddr = "server.request.body" + ServerResponseStatusAddr = "server.response.status" + ServerResponseHeadersNoCookiesAddr = "server.response.headers.no_cookies" + + ClientIPAddr = "http.client_ip" + + UserIDAddr = "usr.id" + UserSessionIDAddr = "usr.session_id" + UserLoginSuccessAddr = "server.business_logic.users.login.success" + UserLoginFailureAddr = "server.business_logic.users.login.failure" + + ServerIoNetURLAddr = "server.io.net.url" + ServerIOFSFileAddr = "server.io.fs.file" + ServerDBStatementAddr = "server.db.statement" + ServerDBTypeAddr = "server.db.system" + + GRPCServerMethodAddr = "grpc.server.method" + GRPCServerRequestMetadataAddr = "grpc.server.request.metadata" + GRPCServerRequestMessageAddr = "grpc.server.request.message" + GRPCServerResponseMessageAddr = "grpc.server.response.message" + GRPCServerResponseMetadataHeadersAddr = "grpc.server.response.metadata.headers" + GRPCServerResponseMetadataTrailersAddr = "grpc.server.response.metadata.trailers" + GRPCServerResponseStatusCodeAddr = "grpc.server.response.status" + + GraphQLServerResolverAddr = "graphql.server.resolver" +) diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/waf/addresses/builder.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/waf/addresses/builder.go new file mode 100644 index 000000000..946a62bcf --- /dev/null +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/waf/addresses/builder.go @@ -0,0 +1,243 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. + +package addresses + +import ( + "net/netip" + "strconv" + + waf "github.com/DataDog/go-libddwaf/v3" +) + +const contextProcessKey = "waf.context.processor" + +type RunAddressDataBuilder struct { + waf.RunAddressData +} + +func NewAddressesBuilder() *RunAddressDataBuilder { + return &RunAddressDataBuilder{ + RunAddressData: waf.RunAddressData{ + Persistent: make(map[string]any, 1), + Ephemeral: make(map[string]any, 1), + }, + } +} + +func (b *RunAddressDataBuilder) WithMethod(method string) *RunAddressDataBuilder { + b.Persistent[ServerRequestMethodAddr] = method + return b +} + +func (b *RunAddressDataBuilder) WithRawURI(uri string) *RunAddressDataBuilder { + b.Persistent[ServerRequestRawURIAddr] = uri + return b +} + +func (b *RunAddressDataBuilder) WithHeadersNoCookies(headers map[string][]string) *RunAddressDataBuilder { + if len(headers) == 0 { + headers = nil + } + b.Persistent[ServerRequestHeadersNoCookiesAddr] = headers + return b +} + +func (b *RunAddressDataBuilder) WithCookies(cookies map[string][]string) *RunAddressDataBuilder { + if len(cookies) == 0 { + cookies = nil + } + b.Persistent[ServerRequestCookiesAddr] = cookies + return b +} + +func (b *RunAddressDataBuilder) WithQuery(query map[string][]string) *RunAddressDataBuilder { + if len(query) == 0 { + query = nil + } + b.Persistent[ServerRequestQueryAddr] = query + return b +} + +func (b *RunAddressDataBuilder) WithPathParams(params map[string]string) *RunAddressDataBuilder { + if len(params) == 0 { + return b + } + b.Persistent[ServerRequestPathParamsAddr] = params + return b +} + +func (b *RunAddressDataBuilder) WithRequestBody(body any) *RunAddressDataBuilder { + if body == nil { + return b + } + b.Persistent[ServerRequestBodyAddr] = body + return b +} + +func (b *RunAddressDataBuilder) WithResponseStatus(status int) *RunAddressDataBuilder { + if status == 0 { + return b + } + b.Persistent[ServerResponseStatusAddr] = strconv.Itoa(status) + return b +} + +func (b *RunAddressDataBuilder) WithResponseHeadersNoCookies(headers map[string][]string) *RunAddressDataBuilder { + if len(headers) == 0 { + return b + } + b.Persistent[ServerResponseHeadersNoCookiesAddr] = headers + return b +} + +func (b *RunAddressDataBuilder) WithClientIP(ip netip.Addr) *RunAddressDataBuilder { + if !ip.IsValid() { + return b + } + b.Persistent[ClientIPAddr] = ip.String() + return b +} + +func (b *RunAddressDataBuilder) WithUserID(id string) *RunAddressDataBuilder { + if id == "" { + return b + } + b.Persistent[UserIDAddr] = id + return b +} + +func (b *RunAddressDataBuilder) WithUserSessionID(id string) *RunAddressDataBuilder { + if id == "" { + return b + } + b.Persistent[UserSessionIDAddr] = id + return b + +} + +func (b *RunAddressDataBuilder) WithUserLoginSuccess() *RunAddressDataBuilder { + b.Persistent[UserLoginSuccessAddr] = nil + return b +} + +func (b *RunAddressDataBuilder) WithUserLoginFailure() *RunAddressDataBuilder { + b.Persistent[UserLoginFailureAddr] = nil + return b +} + +func (b *RunAddressDataBuilder) WithFilePath(file string) *RunAddressDataBuilder { + if file == "" { + return b + } + b.Ephemeral[ServerIOFSFileAddr] = file + b.Scope = waf.RASPScope + return b +} + +func (b *RunAddressDataBuilder) WithURL(url string) *RunAddressDataBuilder { + if url == "" { + return b + } + b.Ephemeral[ServerIoNetURLAddr] = url + b.Scope = waf.RASPScope + return b +} + +func (b *RunAddressDataBuilder) WithDBStatement(statement string) *RunAddressDataBuilder { + if statement == "" { + return b + } + b.Ephemeral[ServerDBStatementAddr] = statement + b.Scope = waf.RASPScope + return b +} + +func (b *RunAddressDataBuilder) WithDBType(driver string) *RunAddressDataBuilder { + if driver == "" { + return b + } + b.Ephemeral[ServerDBTypeAddr] = driver + b.Scope = waf.RASPScope + return b +} + +func (b *RunAddressDataBuilder) WithGRPCMethod(method string) *RunAddressDataBuilder { + if method == "" { + return b + } + b.Persistent[GRPCServerMethodAddr] = method + return b +} + +func (b *RunAddressDataBuilder) WithGRPCRequestMessage(message any) *RunAddressDataBuilder { + if message == nil { + return b + } + b.Ephemeral[GRPCServerRequestMessageAddr] = message + return b +} + +func (b *RunAddressDataBuilder) WithGRPCRequestMetadata(metadata map[string][]string) *RunAddressDataBuilder { + if len(metadata) == 0 { + return b + } + b.Persistent[GRPCServerRequestMetadataAddr] = metadata + return b +} + +func (b *RunAddressDataBuilder) WithGRPCResponseMessage(message any) *RunAddressDataBuilder { + if message == nil { + return b + } + b.Ephemeral[GRPCServerResponseMessageAddr] = message + return b +} + +func (b *RunAddressDataBuilder) WithGRPCResponseMetadataHeaders(headers map[string][]string) *RunAddressDataBuilder { + if len(headers) == 0 { + return b + } + b.Persistent[GRPCServerResponseMetadataHeadersAddr] = headers + return b +} + +func (b *RunAddressDataBuilder) WithGRPCResponseMetadataTrailers(trailers map[string][]string) *RunAddressDataBuilder { + if len(trailers) == 0 { + return b + } + b.Persistent[GRPCServerResponseMetadataTrailersAddr] = trailers + return b +} + +func (b *RunAddressDataBuilder) WithGRPCResponseStatusCode(status int) *RunAddressDataBuilder { + if status == 0 { + return b + } + b.Persistent[GRPCServerResponseStatusCodeAddr] = strconv.Itoa(status) + return b +} + +func (b *RunAddressDataBuilder) WithGraphQLResolver(fieldName string, args map[string]any) *RunAddressDataBuilder { + if _, ok := b.Ephemeral[GraphQLServerResolverAddr]; !ok { + b.Ephemeral[GraphQLServerResolverAddr] = map[string]any{} + } + + b.Ephemeral[GraphQLServerResolverAddr].(map[string]any)[fieldName] = args + return b +} + +func (b *RunAddressDataBuilder) ExtractSchema() *RunAddressDataBuilder { + if _, ok := b.Persistent[contextProcessKey]; !ok { + b.Persistent[contextProcessKey] = map[string]bool{} + } + + b.Persistent[contextProcessKey].(map[string]bool)["extract-schema"] = true + return b +} + +func (b *RunAddressDataBuilder) Build() waf.RunAddressData { + return b.RunAddressData +} diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/waf/context.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/waf/context.go new file mode 100644 index 000000000..698e72188 --- /dev/null +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/waf/context.go @@ -0,0 +1,160 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. + +package waf + +import ( + "context" + "maps" + "slices" + "sync" + "sync/atomic" + + "github.com/DataDog/appsec-internal-go/limiter" + waf "github.com/DataDog/go-libddwaf/v3" + + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/config" + "gopkg.in/DataDog/dd-trace-go.v1/internal/log" + "gopkg.in/DataDog/dd-trace-go.v1/internal/stacktrace" + + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/dyngo" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/trace" +) + +type ( + ContextOperation struct { + dyngo.Operation + *trace.ServiceEntrySpanOperation + + // context is an atomic pointer to the current WAF context. + // Makes sure the calls to context.Run are safe. + context atomic.Pointer[waf.Context] + // limiter comes from the WAF feature and is used to limit the number of events as a whole. + limiter limiter.Limiter + // events is where we store WAF events received from the WAF over the course of the request. + events []any + // stacks is where we store stack traces received from the WAF over the course of the request. + stacks []*stacktrace.Event + // derivatives is where we store any span tags generated by the WAF over the course of the request. + derivatives map[string]any + // supportedAddresses is the set of addresses supported by the WAF. + supportedAddresses config.AddressSet + // mu protects the events, stacks, and derivatives, supportedAddresses slices. + mu sync.Mutex + // logOnce is used to log a warning once when a request has too many WAF events via the built-in limiter or the max value. + logOnce sync.Once + } + + ContextArgs struct{} + + ContextRes struct{} + + // RunEvent is the type of event that should be emitted to child operations to run the WAF + RunEvent struct { + waf.RunAddressData + dyngo.Operation + } +) + +func (ContextArgs) IsArgOf(*ContextOperation) {} +func (ContextRes) IsResultOf(*ContextOperation) {} + +func StartContextOperation(ctx context.Context) (*ContextOperation, context.Context) { + entrySpanOp, ctx := trace.StartServiceEntrySpanOperation(ctx) + op := &ContextOperation{ + Operation: dyngo.NewOperation(entrySpanOp), + ServiceEntrySpanOperation: entrySpanOp, + } + return op, dyngo.StartAndRegisterOperation(ctx, op, ContextArgs{}) +} + +func (op *ContextOperation) Finish(span trace.TagSetter) { + dyngo.FinishOperation(op, ContextRes{}) + op.ServiceEntrySpanOperation.Finish(span) +} + +func (op *ContextOperation) SwapContext(ctx *waf.Context) *waf.Context { + return op.context.Swap(ctx) +} + +func (op *ContextOperation) SetLimiter(limiter limiter.Limiter) { + op.limiter = limiter +} + +func (op *ContextOperation) AddEvents(events ...any) { + if len(events) == 0 { + return + } + + if !op.limiter.Allow() { + log.Warn("appsec: too many WAF events, stopping further reporting") + return + } + + op.mu.Lock() + defer op.mu.Unlock() + + const maxWAFEventsPerRequest = 10 + if len(op.events) >= maxWAFEventsPerRequest { + op.logOnce.Do(func() { + log.Warn("appsec: ignoring new WAF event due to the maximum number of security events per request was reached") + }) + return + } + + op.events = append(op.events, events...) +} + +func (op *ContextOperation) AddStackTraces(stacks ...*stacktrace.Event) { + if len(stacks) == 0 { + return + } + + op.mu.Lock() + defer op.mu.Unlock() + op.stacks = append(op.stacks, stacks...) +} + +func (op *ContextOperation) AbsorbDerivatives(derivatives map[string]any) { + if len(derivatives) == 0 { + return + } + + op.mu.Lock() + defer op.mu.Unlock() + if op.derivatives == nil { + op.derivatives = make(map[string]any) + } + + for k, v := range derivatives { + op.derivatives[k] = v + } +} + +func (op *ContextOperation) Derivatives() map[string]any { + op.mu.Lock() + defer op.mu.Unlock() + return maps.Clone(op.derivatives) +} + +func (op *ContextOperation) Events() []any { + op.mu.Lock() + defer op.mu.Unlock() + return slices.Clone(op.events) +} + +func (op *ContextOperation) StackTraces() []*stacktrace.Event { + op.mu.Lock() + defer op.mu.Unlock() + return slices.Clone(op.stacks) +} + +func (op *ContextOperation) OnEvent(event RunEvent) { + op.Run(event.Operation, event.RunAddressData) +} + +func (op *ContextOperation) SetSupportedAddresses(addrs config.AddressSet) { + op.supportedAddresses = addrs +} diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/waf/run.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/waf/run.go new file mode 100644 index 000000000..a77abd5b2 --- /dev/null +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/waf/run.go @@ -0,0 +1,78 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. + +package waf + +import ( + "context" + "errors" + "maps" + + waf "github.com/DataDog/go-libddwaf/v3" + wafErrors "github.com/DataDog/go-libddwaf/v3/errors" + + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/waf/actions" + + "gopkg.in/DataDog/dd-trace-go.v1/appsec/events" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/dyngo" + "gopkg.in/DataDog/dd-trace-go.v1/internal/log" +) + +// Run runs the WAF with the given address data and sends the results to the event receiver +// the event receiver can be the same os the method receiver but not always +// the event receiver is the one that will receive the actions events generated by the WAF +func (op *ContextOperation) Run(eventReceiver dyngo.Operation, addrs waf.RunAddressData) { + ctx := op.context.Load() + if ctx == nil { // Context was closed concurrently + return + } + + // Remove unsupported addresses in case the listener was registered but some addresses are still unsupported + // Technically the WAF does this step for us but doing this check before calling the WAF makes us skip encoding huge + // values that may be discarded by the WAF afterward. + // e.g. gRPC response body address that is not in the default ruleset but will still be sent to the WAF and may be huge + for _, addrType := range []map[string]any{addrs.Persistent, addrs.Ephemeral} { + maps.DeleteFunc(addrType, func(key string, _ any) bool { + _, ok := op.supportedAddresses[key] + return !ok + }) + } + + result, err := ctx.Run(addrs) + if errors.Is(err, wafErrors.ErrTimeout) { + log.Debug("appsec: WAF timeout value reached: %v", err) + } else if err != nil { + log.Error("appsec: unexpected WAF error: %v", err) + } + + op.AddEvents(result.Events...) + op.AbsorbDerivatives(result.Derivatives) + + actions.SendActionEvents(eventReceiver, result.Actions) + + if result.HasEvents() { + log.Debug("appsec: WAF detected a suspicious event") + } +} + +// RunSimple runs the WAF with the given address data and returns an error that should be forwarded to the caller +func RunSimple(ctx context.Context, addrs waf.RunAddressData, errorLog string) error { + parent, _ := dyngo.FromContext(ctx) + if parent == nil { + log.Error(errorLog) + return nil + } + + var err error + op := dyngo.NewOperation(parent) + dyngo.OnData(op, func(e *events.BlockingSecurityEvent) { + err = e + }) + dyngo.EmitData(op, RunEvent{ + Operation: op, + RunAddressData: addrs, + }) + return err +} diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/features.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/features.go new file mode 100644 index 000000000..ca286de74 --- /dev/null +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/features.go @@ -0,0 +1,81 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. + +package appsec + +import ( + "errors" + + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/dyngo" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener/graphqlsec" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener/grpcsec" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener/httpsec" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener/ossec" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener/sqlsec" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener/trace" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener/usersec" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener/waf" + "gopkg.in/DataDog/dd-trace-go.v1/internal/log" +) + +var features = []listener.NewFeature{ + trace.NewAppsecSpanTransport, + waf.NewWAFFeature, + httpsec.NewHTTPSecFeature, + grpcsec.NewGRPCSecFeature, + graphqlsec.NewGraphQLSecFeature, + usersec.NewUserSecFeature, + sqlsec.NewSQLSecFeature, + ossec.NewOSSecFeature, + httpsec.NewSSRFProtectionFeature, +} + +func (a *appsec) SwapRootOperation() error { + newRoot := dyngo.NewRootOperation() + newFeatures := make([]listener.Feature, 0, len(features)) + var featureErrors []error + for _, newFeature := range features { + feature, err := newFeature(a.cfg, newRoot) + if err != nil { + featureErrors = append(featureErrors, err) + continue + } + + // If error is nil and feature is nil, it means the feature did not activate itself + if feature == nil { + continue + } + + newFeatures = append(newFeatures, feature) + } + + err := errors.Join(featureErrors...) + if err != nil { + for _, feature := range newFeatures { + feature.Stop() + } + return err + } + + a.featuresMu.Lock() + defer a.featuresMu.Unlock() + + oldFeatures := a.features + a.features = newFeatures + + log.Debug("appsec: stopping the following features: %v", oldFeatures) + log.Debug("appsec: starting the following features: %v", newFeatures) + + dyngo.SwapRootOperation(newRoot) + + log.Debug("appsec: swapped root operation") + + for _, oldFeature := range oldFeatures { + oldFeature.Stop() + } + + return nil +} diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener/feature.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener/feature.go new file mode 100644 index 000000000..6f07e2cd5 --- /dev/null +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener/feature.go @@ -0,0 +1,24 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. + +package listener + +import ( + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/config" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/dyngo" +) + +// Feature is an interface that represents a feature that can be started and stopped. +type Feature interface { + // String should return a user-friendly name for the feature. + String() string + // Stop stops the feature. + Stop() +} + +// NewFeature is a function that creates a new feature. +// The error returned will be fatal for the application if not nil. +// If both the feature and the error are nil, the feature will be considered inactive. +type NewFeature func(*config.Config, dyngo.Operation) (Feature, error) diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener/graphqlsec/graphql.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener/graphqlsec/graphql.go new file mode 100644 index 000000000..cb97baf3e --- /dev/null +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener/graphqlsec/graphql.go @@ -0,0 +1,43 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. + +package graphqlsec + +import ( + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/config" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/dyngo" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/graphqlsec" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/waf" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/waf/addresses" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener" +) + +type Feature struct{} + +func (*Feature) String() string { + return "GraphQL Security" +} + +func (*Feature) Stop() {} + +func (f *Feature) OnResolveField(op *graphqlsec.ResolveOperation, args graphqlsec.ResolveOperationArgs) { + dyngo.EmitData(op, waf.RunEvent{ + Operation: op, + RunAddressData: addresses.NewAddressesBuilder(). + WithGraphQLResolver(args.FieldName, args.Arguments). + Build(), + }) +} + +func NewGraphQLSecFeature(config *config.Config, rootOp dyngo.Operation) (listener.Feature, error) { + if !config.SupportedAddresses.AnyOf(addresses.GraphQLServerResolverAddr) { + return nil, nil + } + + feature := &Feature{} + dyngo.On(rootOp, feature.OnResolveField) + + return feature, nil +} diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener/grpcsec/grpc.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener/grpcsec/grpc.go new file mode 100644 index 000000000..52bb2c0fb --- /dev/null +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener/grpcsec/grpc.go @@ -0,0 +1,75 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. + +package grpcsec + +import ( + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/config" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/dyngo" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/grpcsec" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/trace" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/waf/addresses" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener/httpsec" + "gopkg.in/DataDog/dd-trace-go.v1/internal/log" +) + +type Feature struct{} + +func (*Feature) String() string { + return "gRPC Security" +} + +func (*Feature) Stop() {} + +func NewGRPCSecFeature(config *config.Config, rootOp dyngo.Operation) (listener.Feature, error) { + if !config.SupportedAddresses.AnyOf( + addresses.ClientIPAddr, + addresses.GRPCServerMethodAddr, + addresses.GRPCServerRequestMessageAddr, + addresses.GRPCServerRequestMetadataAddr, + addresses.GRPCServerResponseMessageAddr, + addresses.GRPCServerResponseMetadataHeadersAddr, + addresses.GRPCServerResponseMetadataTrailersAddr, + addresses.GRPCServerResponseStatusCodeAddr) { + return nil, nil + } + + feature := &Feature{} + dyngo.On(rootOp, feature.OnStart) + dyngo.OnFinish(rootOp, feature.OnFinish) + return feature, nil +} + +func (f *Feature) OnStart(op *grpcsec.HandlerOperation, args grpcsec.HandlerOperationArgs) { + ipTags, clientIP := httpsec.ClientIPTags(args.Metadata, false, args.RemoteAddr) + log.Debug("appsec: http client ip detection returned `%s`", clientIP) + + op.SetStringTags(ipTags) + + SetRequestMetadataTags(op, args.Metadata) + + op.Run(op, + addresses.NewAddressesBuilder(). + WithGRPCMethod(args.Method). + WithGRPCRequestMetadata(args.Metadata). + WithClientIP(clientIP). + Build(), + ) +} + +func (f *Feature) OnFinish(op *grpcsec.HandlerOperation, res grpcsec.HandlerOperationRes) { + op.Run(op, + addresses.NewAddressesBuilder(). + WithGRPCResponseStatusCode(res.StatusCode). + Build(), + ) +} + +func SetRequestMetadataTags(span trace.TagSetter, metadata map[string][]string) { + for h, v := range httpsec.NormalizeHTTPHeaders(metadata) { + span.SetTag("grpc.metadata."+h, v) + } +} diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener/httpsec/http.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener/httpsec/http.go new file mode 100644 index 000000000..08b9e853d --- /dev/null +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener/httpsec/http.go @@ -0,0 +1,96 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. + +package httpsec + +import ( + "math/rand" + + "github.com/DataDog/appsec-internal-go/appsec" + + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener" + + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/config" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/dyngo" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/httpsec" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/waf/addresses" + "gopkg.in/DataDog/dd-trace-go.v1/internal/log" +) + +type Feature struct { + APISec appsec.APISecConfig +} + +func (*Feature) String() string { + return "HTTP Security" +} + +func (*Feature) Stop() {} + +func NewHTTPSecFeature(config *config.Config, rootOp dyngo.Operation) (listener.Feature, error) { + if !config.SupportedAddresses.AnyOf(addresses.ServerRequestMethodAddr, + addresses.ServerRequestRawURIAddr, + addresses.ServerRequestHeadersNoCookiesAddr, + addresses.ServerRequestCookiesAddr, + addresses.ServerRequestQueryAddr, + addresses.ServerRequestPathParamsAddr, + addresses.ServerRequestBodyAddr, + addresses.ServerResponseStatusAddr, + addresses.ServerResponseHeadersNoCookiesAddr) { + return nil, nil + } + + feature := &Feature{ + APISec: config.APISec, + } + + dyngo.On(rootOp, feature.OnRequest) + dyngo.OnFinish(rootOp, feature.OnResponse) + return feature, nil +} + +func (feature *Feature) OnRequest(op *httpsec.HandlerOperation, args httpsec.HandlerOperationArgs) { + tags, ip := ClientIPTags(args.Headers, true, args.RemoteAddr) + log.Debug("appsec: http client ip detection returned `%s` given the http headers `%v`", ip, args.Headers) + + op.SetStringTags(tags) + headers := headersRemoveCookies(args.Headers) + headers["host"] = []string{args.Host} + + setRequestHeadersTags(op, headers) + + op.Run(op, + addresses.NewAddressesBuilder(). + WithMethod(args.Method). + WithRawURI(args.RequestURI). + WithHeadersNoCookies(headers). + WithCookies(args.Cookies). + WithQuery(args.QueryParams). + WithPathParams(args.PathParams). + WithClientIP(ip). + Build(), + ) +} + +func (feature *Feature) OnResponse(op *httpsec.HandlerOperation, resp httpsec.HandlerOperationRes) { + headers := headersRemoveCookies(resp.Headers) + setResponseHeadersTags(op, headers) + + builder := addresses.NewAddressesBuilder(). + WithResponseHeadersNoCookies(headers). + WithResponseStatus(resp.StatusCode) + + if feature.canExtractSchemas() { + builder = builder.ExtractSchema() + } + + op.Run(op, builder.Build()) +} + +// canExtractSchemas checks that API Security is enabled and that sampling rate +// allows extracting schemas +func (feature *Feature) canExtractSchemas() bool { + return feature.APISec.Enabled && feature.APISec.SampleRate >= rand.Float64() +} diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener/httpsec/request.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener/httpsec/request.go new file mode 100644 index 000000000..abd398318 --- /dev/null +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener/httpsec/request.go @@ -0,0 +1,167 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. + +package httpsec + +import ( + "net/http" + "net/netip" + "os" + "strings" + + "github.com/DataDog/appsec-internal-go/httpsec" + + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/trace" +) + +const ( + // envClientIPHeader is the name of the env var used to specify the IP header to be used for client IP collection. + envClientIPHeader = "DD_TRACE_CLIENT_IP_HEADER" +) + +var ( + // defaultIPHeaders is the default list of IP-related headers leveraged to + // retrieve the public client IP address in RemoteAddr. + defaultIPHeaders = []string{ + "x-forwarded-for", + "x-real-ip", + "true-client-ip", + "x-client-ip", + "x-forwarded", + "forwarded-for", + "x-cluster-client-ip", + "fastly-client-ip", + "cf-connecting-ip", + "cf-connecting-ipv6", + } + + // defaultCollectedHeaders is the default list of HTTP headers collected as + // request span tags when appsec is enabled. + defaultCollectedHeaders = append([]string{ + "host", + "content-length", + "content-type", + "content-encoding", + "content-language", + "forwarded", + "via", + "user-agent", + "accept", + "accept-encoding", + "accept-language", + "x-amzn-trace-id", + "cloudfront-viewer-ja3-fingerprint", + "cf-ray", + "x-cloud-trace-context", + "x-appgw-trace-id", + "akamai-user-risk", + "x-sigsci-requestid", + "x-sigsci-tags", + }, defaultIPHeaders...) + + // collectedHeadersLookupMap is a helper lookup map of HTTP headers to + // collect as request span tags when appsec is enabled. It is computed at + // init-time based on defaultCollectedHeaders and leveraged by NormalizeHTTPHeaders. + collectedHeadersLookupMap map[string]struct{} + + // monitoredClientIPHeadersCfg is the list of IP-related headers leveraged to + // retrieve the public client IP address in RemoteAddr. This is defined at init + // time in function of the value of the envClientIPHeader environment variable. + monitoredClientIPHeadersCfg []string +) + +// ClientIPTags returns the resulting Datadog span tags `http.client_ip` +// containing the client IP and `network.client.ip` containing the remote IP. +// The tags are present only if a valid ip address has been returned by +// RemoteAddr(). +func ClientIPTags(headers map[string][]string, hasCanonicalHeaders bool, remoteAddr string) (tags map[string]string, clientIP netip.Addr) { + remoteIP, clientIP := httpsec.ClientIP(headers, hasCanonicalHeaders, remoteAddr, monitoredClientIPHeadersCfg) + tags = httpsec.ClientIPTags(remoteIP, clientIP) + return tags, clientIP +} + +// NormalizeHTTPHeaders returns the HTTP headers following Datadog's +// normalization format. +func NormalizeHTTPHeaders(headers map[string][]string) (normalized map[string]string) { + if len(headers) == 0 { + return nil + } + normalized = make(map[string]string, len(collectedHeadersLookupMap)) + for k, v := range headers { + k = normalizeHTTPHeaderName(k) + if _, found := collectedHeadersLookupMap[k]; found { + normalized[k] = normalizeHTTPHeaderValue(v) + } + } + if len(normalized) == 0 { + return nil + } + return normalized +} + +// Remove cookies from the request headers and return the map of headers +// Used from `server.request.headers.no_cookies` and server.response.headers.no_cookies` addresses for the WAF +func headersRemoveCookies(headers http.Header) map[string][]string { + headersNoCookies := make(http.Header, len(headers)) + for k, v := range headers { + k := strings.ToLower(k) + if k == "cookie" { + continue + } + headersNoCookies[k] = v + } + return headersNoCookies +} + +func normalizeHTTPHeaderName(name string) string { + return strings.ToLower(name) +} + +func normalizeHTTPHeaderValue(values []string) string { + return strings.Join(values, ",") +} + +func init() { + makeCollectedHTTPHeadersLookupMap() + readMonitoredClientIPHeadersConfig() +} + +func makeCollectedHTTPHeadersLookupMap() { + collectedHeadersLookupMap = make(map[string]struct{}, len(defaultCollectedHeaders)) + for _, h := range defaultCollectedHeaders { + collectedHeadersLookupMap[h] = struct{}{} + } +} + +func readMonitoredClientIPHeadersConfig() { + if header := os.Getenv(envClientIPHeader); header != "" { + // Make this header the only one to consider in RemoteAddr + monitoredClientIPHeadersCfg = []string{header} + + // Add this header to the list of collected headers + header = normalizeHTTPHeaderName(header) + collectedHeadersLookupMap[header] = struct{}{} + } else { + // No specific IP header was configured, use the default list + monitoredClientIPHeadersCfg = defaultIPHeaders + } +} + +// setRequestHeadersTags sets the AppSec-specific request headers span tags. +func setRequestHeadersTags(span trace.TagSetter, headers map[string][]string) { + setHeadersTags(span, "http.request.headers.", headers) +} + +// setResponseHeadersTags sets the AppSec-specific response headers span tags. +func setResponseHeadersTags(span trace.TagSetter, headers map[string][]string) { + setHeadersTags(span, "http.response.headers.", headers) +} + +// setHeadersTags sets the AppSec-specific headers span tags. +func setHeadersTags(span trace.TagSetter, tagPrefix string, headers map[string][]string) { + for h, v := range NormalizeHTTPHeaders(headers) { + span.SetTag(tagPrefix+h, v) + } +} diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener/httpsec/roundtripper.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener/httpsec/roundtripper.go new file mode 100644 index 000000000..b72e8e832 --- /dev/null +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener/httpsec/roundtripper.go @@ -0,0 +1,40 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2016 Datadog, Inc. + +package httpsec + +import ( + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/config" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/dyngo" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/httpsec" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/waf" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/waf/addresses" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener" +) + +type SSRFProtectionFeature struct{} + +func (*SSRFProtectionFeature) String() string { + return "SSRF Protection" +} + +func (*SSRFProtectionFeature) Stop() {} + +func NewSSRFProtectionFeature(config *config.Config, rootOp dyngo.Operation) (listener.Feature, error) { + if !config.RASP || !config.SupportedAddresses.AnyOf(addresses.ServerIoNetURLAddr) { + return nil, nil + } + + feature := &SSRFProtectionFeature{} + dyngo.On(rootOp, feature.OnStart) + return feature, nil +} + +func (*SSRFProtectionFeature) OnStart(op *httpsec.RoundTripOperation, args httpsec.RoundTripOperationArgs) { + dyngo.EmitData(op, waf.RunEvent{ + Operation: op, + RunAddressData: addresses.NewAddressesBuilder().WithURL(args.URL).Build(), + }) +} diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener/listener.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener/listener.go deleted file mode 100644 index f1668152e..000000000 --- a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener/listener.go +++ /dev/null @@ -1,31 +0,0 @@ -// Unless explicitly stated otherwise all files in this repository are licensed -// under the Apache License Version 2.0. -// This product includes software developed at Datadog (https://www.datadoghq.com/). -// Copyright 2016 Datadog, Inc. - -// Package listener provides functions and types used to listen to AppSec -// instrumentation events produced by code usintrumented using the functions and -// types found in gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter. -package listener - -import waf "github.com/DataDog/go-libddwaf/v2" - -// ContextKey is used as a key to store operations in the request's context (gRPC/HTTP) -type ContextKey struct{} - -// AddressSet is a set of WAF addresses. -type AddressSet map[string]struct{} - -// FilterAddressSet filters the supplied `supported` address set to only include -// entries referenced by the supplied waf.Handle. -func FilterAddressSet(supported AddressSet, handle *waf.Handle) AddressSet { - result := make(AddressSet, len(supported)) - - for _, addr := range handle.Addresses() { - if _, found := supported[addr]; found { - result[addr] = struct{}{} - } - } - - return result -} diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener/ossec/lfi.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener/ossec/lfi.go new file mode 100644 index 000000000..316165114 --- /dev/null +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener/ossec/lfi.go @@ -0,0 +1,53 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. + +package ossec + +import ( + "os" + + "gopkg.in/DataDog/dd-trace-go.v1/appsec/events" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/config" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/dyngo" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/ossec" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/waf" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/waf/addresses" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener" +) + +type Feature struct{} + +func (*Feature) String() string { + return "LFI Protection" +} + +func (*Feature) Stop() {} + +func NewOSSecFeature(cfg *config.Config, rootOp dyngo.Operation) (listener.Feature, error) { + if !cfg.RASP || !cfg.SupportedAddresses.AnyOf(addresses.ServerIOFSFileAddr) { + return nil, nil + } + + feature := &Feature{} + dyngo.On(rootOp, feature.OnStart) + return feature, nil +} + +func (*Feature) OnStart(op *ossec.OpenOperation, args ossec.OpenOperationArgs) { + dyngo.OnData(op, func(err *events.BlockingSecurityEvent) { + dyngo.OnFinish(op, func(_ *ossec.OpenOperation, res ossec.OpenOperationRes[*os.File]) { + if res.Err != nil { + *res.Err = err + } + }) + }) + + dyngo.EmitData(op, waf.RunEvent{ + Operation: op, + RunAddressData: addresses.NewAddressesBuilder(). + WithFilePath(args.Path). + Build(), + }) +} diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener/sqlsec/sql.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener/sqlsec/sql.go new file mode 100644 index 000000000..3a6fbc076 --- /dev/null +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener/sqlsec/sql.go @@ -0,0 +1,43 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2016 Datadog, Inc. + +package sqlsec + +import ( + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/config" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/dyngo" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/sqlsec" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/waf" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/waf/addresses" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener" +) + +type Feature struct{} + +func (*Feature) String() string { + return "SQLi Protection" +} + +func (*Feature) Stop() {} + +func NewSQLSecFeature(cfg *config.Config, rootOp dyngo.Operation) (listener.Feature, error) { + if !cfg.RASP || !cfg.SupportedAddresses.AnyOf(addresses.ServerDBTypeAddr, addresses.ServerDBStatementAddr) { + return nil, nil + } + + feature := &Feature{} + dyngo.On(rootOp, feature.OnStart) + return feature, nil +} + +func (*Feature) OnStart(op *sqlsec.SQLOperation, args sqlsec.SQLOperationArgs) { + dyngo.EmitData(op, waf.RunEvent{ + Operation: op, + RunAddressData: addresses.NewAddressesBuilder(). + WithDBStatement(args.Query). + WithDBType(args.Driver). + Build(), + }) +} diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener/trace/trace.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener/trace/trace.go new file mode 100644 index 000000000..45fb28e99 --- /dev/null +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener/trace/trace.go @@ -0,0 +1,53 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. + +package trace + +import ( + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/config" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/dyngo" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/trace" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener" +) + +// AppSec-specific span tags that are expected to +// be in the web service entry span (span of type `web`) when AppSec is enabled. +var staticAppsecTags = map[string]any{ + "_dd.appsec.enabled": 1, + "_dd.runtime_family": "go", +} + +type AppsecSpanTransport struct{} + +func (*AppsecSpanTransport) String() string { + return "Appsec Span Transport" +} + +func (*AppsecSpanTransport) Stop() {} + +func NewAppsecSpanTransport(_ *config.Config, rootOp dyngo.Operation) (listener.Feature, error) { + ast := &AppsecSpanTransport{} + + dyngo.On(rootOp, ast.OnServiceEntryStart) + dyngo.On(rootOp, ast.OnSpanStart) + + return ast, nil +} + +// OnServiceEntryStart is the start listener of the trace.ServiceEntrySpanOperation start event. +// It listens for tags and serializable tags and sets them on the span when finishing the operation. +func (*AppsecSpanTransport) OnServiceEntryStart(op *trace.ServiceEntrySpanOperation, _ trace.ServiceEntrySpanArgs) { + op.SetTags(staticAppsecTags) + dyngo.OnData(op, op.OnSpanTagEvent) + dyngo.OnData(op, op.OnServiceEntrySpanTagEvent) + dyngo.OnData(op, op.OnJSONServiceEntrySpanTagEvent) + dyngo.OnData(op, op.OnServiceEntrySpanTagsBulkEvent) +} + +// OnSpanStart is the start listener of the trace.SpanOperation start event. +// It listens for tags and sets them on the current span when finishing the operation. +func (*AppsecSpanTransport) OnSpanStart(op *trace.SpanOperation, _ trace.SpanArgs) { + dyngo.OnData(op, op.OnSpanTagEvent) +} diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener/usersec/usec.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener/usersec/usec.go new file mode 100644 index 000000000..c8a645801 --- /dev/null +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener/usersec/usec.go @@ -0,0 +1,54 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. + +package usersec + +import ( + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/config" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/dyngo" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/usersec" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/waf" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/waf/addresses" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener" +) + +type Feature struct{} + +func (*Feature) String() string { + return "User Security" +} + +func (*Feature) Stop() {} + +func NewUserSecFeature(cfg *config.Config, rootOp dyngo.Operation) (listener.Feature, error) { + if !cfg.SupportedAddresses.AnyOf( + addresses.UserIDAddr, + addresses.UserSessionIDAddr, + addresses.UserLoginSuccessAddr, + addresses.UserLoginFailureAddr) { + return nil, nil + } + + feature := &Feature{} + dyngo.OnFinish(rootOp, feature.OnFinish) + return feature, nil +} + +func (*Feature) OnFinish(op *usersec.UserLoginOperation, res usersec.UserLoginOperationRes) { + builder := addresses.NewAddressesBuilder(). + WithUserID(res.UserID). + WithUserSessionID(res.SessionID) + + if res.Success { + builder = builder.WithUserLoginSuccess() + } else { + builder = builder.WithUserLoginFailure() + } + + dyngo.EmitData(op, waf.RunEvent{ + Operation: op, + RunAddressData: builder.Build(), + }) +} diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener/waf/tags.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener/waf/tags.go new file mode 100644 index 000000000..bac41ce5e --- /dev/null +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener/waf/tags.go @@ -0,0 +1,101 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. + +package waf + +import ( + "encoding/json" + "fmt" + + waf "github.com/DataDog/go-libddwaf/v3" + + "gopkg.in/DataDog/dd-trace-go.v1/internal/log" + + "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/ext" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/trace" + "gopkg.in/DataDog/dd-trace-go.v1/internal/samplernames" +) + +const ( + wafSpanTagPrefix = "_dd.appsec." + eventRulesVersionTag = wafSpanTagPrefix + "event_rules.version" + eventRulesErrorsTag = wafSpanTagPrefix + "event_rules.errors" + eventRulesLoadedTag = wafSpanTagPrefix + "event_rules.loaded" + eventRulesFailedTag = wafSpanTagPrefix + "event_rules.error_count" + wafVersionTag = wafSpanTagPrefix + "waf.version" + + // BlockedRequestTag used to convey whether a request is blocked + BlockedRequestTag = "appsec.blocked" +) + +// AddRulesMonitoringTags adds the tags related to security rules monitoring +func AddRulesMonitoringTags(th trace.TagSetter, wafDiags waf.Diagnostics) { + rInfo := wafDiags.Rules + if rInfo == nil { + return + } + + var rulesetErrors []byte + var err error + rulesetErrors, err = json.Marshal(wafDiags.Rules.Errors) + if err != nil { + log.Error("appsec: could not marshal the waf ruleset info errors to json") + } + th.SetTag(eventRulesErrorsTag, string(rulesetErrors)) + th.SetTag(eventRulesLoadedTag, len(rInfo.Loaded)) + th.SetTag(eventRulesFailedTag, len(rInfo.Failed)) + th.SetTag(wafVersionTag, waf.Version()) + th.SetTag(ext.ManualKeep, samplernames.AppSec) +} + +// AddWAFMonitoringTags adds the tags related to the monitoring of the Feature +func AddWAFMonitoringTags(th trace.TagSetter, rulesVersion string, stats map[string]any) { + // Rules version is set for every request to help the backend associate Feature duration metrics with rule version + th.SetTag(eventRulesVersionTag, rulesVersion) + + // Report the stats sent by the Feature + for k, v := range stats { + th.SetTag(wafSpanTagPrefix+k, v) + } +} + +// SetEventSpanTags sets the security event span tags into the service entry span. +func SetEventSpanTags(span trace.TagSetter, events []any) error { + if len(events) == 0 { + return nil + } + + // Set the appsec event span tag + val, err := makeEventTagValue(events) + if err != nil { + return err + } + span.SetTag("_dd.appsec.json", string(val)) + // Keep this span due to the security event + // + // This is a workaround to tell the tracer that the trace was kept by AppSec. + // Passing any other value than `appsec.SamplerAppSec` has no effect. + // Customers should use `span.SetTag(ext.ManualKeep, true)` pattern + // to keep the trace, manually. + span.SetTag(ext.ManualKeep, samplernames.AppSec) + span.SetTag("_dd.origin", "appsec") + // Set the appsec.event tag needed by the appsec backend + span.SetTag("appsec.event", true) + return nil +} + +// Create the value of the security event tag. +func makeEventTagValue(events []any) (json.RawMessage, error) { + type eventTagValue struct { + Triggers []any `json:"triggers"` + } + + tag, err := json.Marshal(eventTagValue{events}) + if err != nil { + return nil, fmt.Errorf("unexpected error while serializing the appsec event span tag: %v", err) + } + + return tag, nil +} diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener/waf/waf.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener/waf/waf.go new file mode 100644 index 000000000..308eaa25d --- /dev/null +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener/waf/waf.go @@ -0,0 +1,128 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. + +package waf + +import ( + "fmt" + "sync" + "time" + + "github.com/DataDog/appsec-internal-go/limiter" + wafv3 "github.com/DataDog/go-libddwaf/v3" + + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener" + + "gopkg.in/DataDog/dd-trace-go.v1/appsec/events" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/config" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/dyngo" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/waf" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/waf/actions" + "gopkg.in/DataDog/dd-trace-go.v1/internal/log" + "gopkg.in/DataDog/dd-trace-go.v1/internal/stacktrace" +) + +type Feature struct { + timeout time.Duration + limiter *limiter.TokenTicker + handle *wafv3.Handle + supportedAddrs config.AddressSet + reportRulesTags sync.Once +} + +func NewWAFFeature(cfg *config.Config, rootOp dyngo.Operation) (listener.Feature, error) { + if ok, err := wafv3.Load(); err != nil { + // 1. If there is an error and the loading is not ok: log as an unexpected error case and quit appsec + // Note that we assume here that the test for the unsupported target has been done before calling + // this method, so it is now considered an error for this method + if !ok { + return nil, fmt.Errorf("error while loading libddwaf: %w", err) + } + // 2. If there is an error and the loading is ok: log as an informative error where appsec can be used + log.Error("appsec: non-critical error while loading libddwaf: %v", err) + } + + newHandle, err := wafv3.NewHandle(cfg.RulesManager.Latest, cfg.Obfuscator.KeyRegex, cfg.Obfuscator.ValueRegex) + if err != nil { + return nil, err + } + + cfg.SupportedAddresses = config.NewAddressSet(newHandle.Addresses()) + + tokenTicker := limiter.NewTokenTicker(cfg.TraceRateLimit, cfg.TraceRateLimit) + tokenTicker.Start() + + feature := &Feature{ + handle: newHandle, + timeout: cfg.WAFTimeout, + limiter: tokenTicker, + supportedAddrs: cfg.SupportedAddresses, + } + + dyngo.On(rootOp, feature.onStart) + dyngo.OnFinish(rootOp, feature.onFinish) + + return feature, nil +} + +func (waf *Feature) onStart(op *waf.ContextOperation, _ waf.ContextArgs) { + waf.reportRulesTags.Do(func() { + AddRulesMonitoringTags(op, waf.handle.Diagnostics()) + }) + + ctx, err := waf.handle.NewContextWithBudget(waf.timeout) + if err != nil { + log.Debug("appsec: failed to create Feature context: %v", err) + } + + op.SwapContext(ctx) + op.SetLimiter(waf.limiter) + op.SetSupportedAddresses(waf.supportedAddrs) + + // Run the WAF with the given address data + dyngo.OnData(op, op.OnEvent) + + waf.SetupActionHandlers(op) +} + +func (waf *Feature) SetupActionHandlers(op *waf.ContextOperation) { + // Set the blocking tag on the operation when a blocking event is received + dyngo.OnData(op, func(_ *events.BlockingSecurityEvent) { + op.SetTag(BlockedRequestTag, true) + }) + + // Register the stacktrace if one is requested by a WAF action + dyngo.OnData(op, func(err *actions.StackTraceAction) { + op.AddStackTraces(err.Event) + }) +} + +func (waf *Feature) onFinish(op *waf.ContextOperation, _ waf.ContextRes) { + ctx := op.SwapContext(nil) + if ctx == nil { + return + } + + ctx.Close() + + AddWAFMonitoringTags(op, waf.handle.Diagnostics().Version, ctx.Stats().Metrics()) + if err := SetEventSpanTags(op, op.Events()); err != nil { + log.Debug("appsec: failed to set event span tags: %v", err) + } + + op.SetSerializableTags(op.Derivatives()) + if stacks := op.StackTraces(); len(stacks) > 0 { + op.SetTag(stacktrace.SpanKey, stacktrace.GetSpanValue(stacks...)) + } +} + +func (*Feature) String() string { + return "Web Application Firewall" +} + +func (waf *Feature) Stop() { + waf.limiter.Stop() + waf.handle.Close() +} diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/remoteconfig.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/remoteconfig.go index 0db534d38..ccf6fe763 100644 --- a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/remoteconfig.go +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/remoteconfig.go @@ -9,10 +9,12 @@ import ( "encoding/json" "errors" "fmt" + "maps" "os" "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/config" "gopkg.in/DataDog/dd-trace-go.v1/internal/log" + "gopkg.in/DataDog/dd-trace-go.v1/internal/orchestrion" "gopkg.in/DataDog/dd-trace-go.v1/internal/remoteconfig" internal "github.com/DataDog/appsec-internal-go/appsec" @@ -41,20 +43,13 @@ func statusesFromUpdate(u remoteconfig.ProductUpdate, ack bool, err error) map[s return statuses } -func mergeMaps[K comparable, V any](m1 map[K]V, m2 map[K]V) map[K]V { - for key, value := range m2 { - m1[key] = value - } - return m1 -} - // combineRCRulesUpdates updates the state of the given RulesManager with the combination of all the provided rules updates func combineRCRulesUpdates(r *config.RulesManager, updates map[string]remoteconfig.ProductUpdate) (statuses map[string]rc.ApplyStatus, err error) { // Spare some re-allocations (but there may still be some because 1 update may contain N configs) statuses = make(map[string]rc.ApplyStatus, len(updates)) // Set the default statuses for all updates to unacknowledged for _, u := range updates { - statuses = mergeMaps(statuses, statusesFromUpdate(u, false, nil)) + maps.Copy(statuses, statusesFromUpdate(u, false, nil)) } updateLoop: @@ -66,9 +61,9 @@ updateLoop: switch p { case rc.ProductASMData: // Merge all rules data entries together and store them as a RulesManager edit entry - rulesData, status := mergeRulesData(u) - statuses = mergeMaps(statuses, status) - r.AddEdit("asmdata", config.RulesFragment{RulesData: rulesData}) + fragment, status := mergeASMDataUpdates(u) + maps.Copy(statuses, status) + r.AddEdit("asmdata", fragment) case rc.ProductASMDD: var ( removalFound = false @@ -83,7 +78,7 @@ updateLoop: } // Already seen a removal or an update, return an error if err != nil { - statuses = mergeMaps(statuses, statusesFromUpdate(u, true, err)) + maps.Copy(statuses, statusesFromUpdate(u, true, err)) break updateLoop } @@ -103,7 +98,7 @@ updateLoop: if removalFound { log.Debug("appsec: Remote config: ASM_DD config removed. Switching back to default rules") r.ChangeBase(config.DefaultRulesFragment(), "") - statuses = mergeMaps(statuses, statusesFromUpdate(u, true, nil)) + maps.Copy(statuses, statusesFromUpdate(u, true, nil)) } continue } @@ -145,7 +140,7 @@ updateLoop: // Set all statuses to ack if no error occured if err == nil { for _, u := range updates { - statuses = mergeMaps(statuses, statusesFromUpdate(u, true, nil)) + maps.Copy(statuses, statusesFromUpdate(u, true, nil)) } } @@ -182,17 +177,18 @@ func (a *appsec) onRCRulesUpdate(updates map[string]remoteconfig.ProductUpdate) r.Compile() log.Debug("appsec: Remote config: final compiled rules: %s", r.String()) + // Replace the RulesManager with the new one holding the new state + a.cfg.RulesManager = &r + // If an error occurs while updating the WAF handle, don't swap the RulesManager and propagate the error // to all config statuses since we can't know which config is the faulty one - if err = a.swapWAF(r.Latest); err != nil { + if err = a.SwapRootOperation(); err != nil { log.Error("appsec: Remote config: could not apply the new security rules: %v", err) for k := range statuses { statuses[k] = genApplyStatus(true, err) } return statuses } - // Replace the RulesManager with the new one holding the new state - a.cfg.RulesManager = &r return statuses } @@ -240,12 +236,41 @@ func (a *appsec) handleASMFeatures(u remoteconfig.ProductUpdate) map[string]rc.A return statuses } -func mergeRulesData(u remoteconfig.ProductUpdate) ([]config.RuleDataEntry, map[string]rc.ApplyStatus) { +func mergeASMDataUpdates(u remoteconfig.ProductUpdate) (config.RulesFragment, map[string]rc.ApplyStatus) { // Following the RFC, merging should only happen when two rules data with the same ID and same Type are received - // allRulesData[ID][Type] will return the rules data of said id and type, if it exists - allRulesData := make(map[string]map[string]config.RuleDataEntry) + type mapKey struct { + id string + typ string + } + mergedRulesData := make(map[mapKey]config.DataEntry) + mergedExclusionData := make(map[mapKey]config.DataEntry) statuses := statusesFromUpdate(u, true, nil) + mergeUpdateEntry := func(mergeMap map[mapKey]config.DataEntry, data []config.DataEntry) { + for _, ruleData := range data { + key := mapKey{id: ruleData.ID, typ: ruleData.Type} + if data, ok := mergeMap[key]; ok { + // Merge rules data entries with the same ID and Type + mergeMap[key] = config.DataEntry{ + ID: data.ID, + Type: data.Type, + Data: mergeRulesDataEntries(data.Data, ruleData.Data), + } + continue + } + + mergeMap[key] = ruleData + } + } + + mapValues := func(m map[mapKey]config.DataEntry) []config.DataEntry { + values := make([]config.DataEntry, 0, len(m)) + for _, v := range m { + values = append(values, v) + } + return values + } + for path, raw := range u { log.Debug("appsec: Remote config: processing %s", path) @@ -257,36 +282,30 @@ func mergeRulesData(u remoteconfig.ProductUpdate) ([]config.RuleDataEntry, map[s continue } - var rulesData config.RulesData - if err := json.Unmarshal(raw, &rulesData); err != nil { + var asmdataUpdate struct { + RulesData []config.DataEntry `json:"rules_data,omitempty"` + ExclusionData []config.DataEntry `json:"exclusion_data,omitempty"` + } + if err := json.Unmarshal(raw, &asmdataUpdate); err != nil { log.Debug("appsec: Remote config: error while unmarshalling payload for %s: %v. Configuration won't be applied.", path, err) statuses[path] = genApplyStatus(false, err) continue } - // Check each entry against allRulesData to see if merging is necessary - for _, ruleData := range rulesData.RulesData { - if allRulesData[ruleData.ID] == nil { - allRulesData[ruleData.ID] = make(map[string]config.RuleDataEntry) - } - if data, ok := allRulesData[ruleData.ID][ruleData.Type]; ok { - // Merge rules data entries with the same ID and Type - data.Data = mergeRulesDataEntries(data.Data, ruleData.Data) - allRulesData[ruleData.ID][ruleData.Type] = data - } else { - allRulesData[ruleData.ID][ruleData.Type] = ruleData - } - } + mergeUpdateEntry(mergedExclusionData, asmdataUpdate.ExclusionData) + mergeUpdateEntry(mergedRulesData, asmdataUpdate.RulesData) } - // Aggregate all the rules data before passing it over to the WAF - var rulesData []config.RuleDataEntry - for _, m := range allRulesData { - for _, data := range m { - rulesData = append(rulesData, data) - } + var fragment config.RulesFragment + if len(mergedRulesData) > 0 { + fragment.RulesData = mapValues(mergedRulesData) } - return rulesData, statuses + + if len(mergedExclusionData) > 0 { + fragment.ExclusionData = mapValues(mergedExclusionData) + } + + return fragment, statuses } // mergeRulesDataEntries merges two slices of rules data entries together, removing duplicates and @@ -372,6 +391,11 @@ var blockingCapabilities = [...]remoteconfig.Capability{ remoteconfig.ASMCustomRules, remoteconfig.ASMCustomBlockingResponse, remoteconfig.ASMTrustedIPs, + remoteconfig.ASMExclusionData, + remoteconfig.ASMEndpointFingerprinting, + remoteconfig.ASMSessionFingerprinting, + remoteconfig.ASMNetworkFingerprinting, + remoteconfig.ASMHeaderFingerprinting, } func (a *appsec) enableRCBlocking() { @@ -379,6 +403,10 @@ func (a *appsec) enableRCBlocking() { log.Debug("appsec: Remote config: no valid remote configuration client") return } + if _, isSet := os.LookupEnv(internal.EnvRules); isSet { + log.Debug("appsec: Remote config: using rules from %s, blocking capabilities won't be enabled", a.cfg.RulesManager.BasePath) + return + } products := []string{rc.ProductASM, rc.ProductASMDD, rc.ProductASMData} for _, p := range products { @@ -391,11 +419,26 @@ func (a *appsec) enableRCBlocking() { log.Debug("appsec: Remote config: couldn't register callback: %v", err) } - if _, isSet := os.LookupEnv(internal.EnvRules); !isSet { - for _, c := range blockingCapabilities { - if err := a.registerRCCapability(c); err != nil { - log.Debug("appsec: Remote config: couldn't register capability %v: %v", c, err) - } + for _, c := range blockingCapabilities { + if err := a.registerRCCapability(c); err != nil { + log.Debug("appsec: Remote config: couldn't register capability %v: %v", c, err) + } + } +} + +func (a *appsec) enableRASP() { + if !a.cfg.RASP { + return + } + if err := remoteconfig.RegisterCapability(remoteconfig.ASMRASPSSRF); err != nil { + log.Debug("appsec: Remote config: couldn't register RASP SSRF: %v", err) + } + if err := remoteconfig.RegisterCapability(remoteconfig.ASMRASPSQLI); err != nil { + log.Debug("appsec: Remote config: couldn't register RASP SQLI: %v", err) + } + if orchestrion.Enabled() { + if err := remoteconfig.RegisterCapability(remoteconfig.ASMRASPLFI); err != nil { + log.Debug("appsec: Remote config: couldn't register RASP LFI: %v", err) } } } diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/telemetry.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/telemetry.go index 229b52aed..2b07117bd 100644 --- a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/telemetry.go +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/telemetry.go @@ -8,7 +8,7 @@ package appsec import ( "runtime" - waf "github.com/DataDog/go-libddwaf/v2" + waf "github.com/DataDog/go-libddwaf/v3" "gopkg.in/DataDog/dd-trace-go.v1/internal/telemetry" ) @@ -26,10 +26,10 @@ var ( wafSupported, _ = waf.SupportsTarget() wafHealthy, _ = waf.Health() staticConfigs = []telemetry.Configuration{ - {Name: "goos", Value: runtime.GOOS, Origin: "code"}, - {Name: "goarch", Value: runtime.GOARCH, Origin: "code"}, - {Name: "waf_supports_target", Value: wafSupported, Origin: "code"}, - {Name: "waf_healthy", Value: wafHealthy, Origin: "code"}, + {Name: "goos", Value: runtime.GOOS, Origin: telemetry.OriginCode}, + {Name: "goarch", Value: runtime.GOARCH, Origin: telemetry.OriginCode}, + {Name: "waf_supports_target", Value: wafSupported, Origin: telemetry.OriginCode}, + {Name: "waf_healthy", Value: wafHealthy, Origin: telemetry.OriginCode}, } ) @@ -62,7 +62,7 @@ func (a *appsecTelemetry) addEnvConfig(name string, value any) { if a == nil { return } - a.configs = append(a.configs, telemetry.Configuration{Name: name, Value: value, Origin: "env_var"}) + a.configs = append(a.configs, telemetry.Configuration{Name: name, Value: value, Origin: telemetry.OriginEnvVar}) } // setEnabled makes AppSec as having effectively been enabled. diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/waf.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/waf.go deleted file mode 100644 index 8e74bfca8..000000000 --- a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/waf.go +++ /dev/null @@ -1,109 +0,0 @@ -// Unless explicitly stated otherwise all files in this repository are licensed -// under the Apache License Version 2.0. -// This product includes software developed at Datadog (https://www.datadoghq.com/). -// Copyright 2016 Datadog, Inc. - -package appsec - -import ( - "github.com/DataDog/appsec-internal-go/limiter" - waf "github.com/DataDog/go-libddwaf/v2" - "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/config" - "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/dyngo" - "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/sharedsec" - "gopkg.in/DataDog/dd-trace-go.v1/internal/log" -) - -type wafHandle struct { - *waf.Handle - // actions are tightly link to a ruleset, which is linked to a waf handle - actions sharedsec.Actions -} - -func (a *appsec) swapWAF(rules config.RulesFragment) (err error) { - // Instantiate a new WAF handle and verify its state - newHandle, err := newWAFHandle(rules, a.cfg) - if err != nil { - return err - } - - // Close the WAF handle in case of an error in what's following - defer func() { - if err != nil { - newHandle.Close() - } - }() - - newRoot := dyngo.NewRootOperation() - for _, fn := range wafEventListeners { - fn(newHandle.Handle, newHandle.actions, a.cfg, a.limiter, newRoot) - } - - // Hot-swap dyngo's root operation - dyngo.SwapRootOperation(newRoot) - - // Close old handle. - // Note that concurrent requests are still using it, and it will be released - // only when no more requests use it. - // TODO: implement in dyngo ref-counting of the root operation so we can - // rely on a Finish event listener on the root operation instead? - // Avoiding saving the current WAF handle would guarantee no one is - // accessing a.wafHandle while we swap - oldHandle := a.wafHandle - a.wafHandle = newHandle - if oldHandle != nil { - oldHandle.Close() - } - - return nil -} - -func actionFromEntry(e *config.ActionEntry) *sharedsec.Action { - switch e.Type { - case "block_request": - grpcCode := 10 // use the grpc.Codes value for "Aborted" by default - if e.Parameters.GRPCStatusCode != nil { - grpcCode = *e.Parameters.GRPCStatusCode - } - return sharedsec.NewBlockRequestAction(e.Parameters.StatusCode, grpcCode, e.Parameters.Type) - case "redirect_request": - return sharedsec.NewRedirectRequestAction(e.Parameters.StatusCode, e.Parameters.Location) - default: - log.Debug("appsec: unknown action type `%s`", e.Type) - return nil - } -} - -func newWAFHandle(rules config.RulesFragment, cfg *config.Config) (*wafHandle, error) { - handle, err := waf.NewHandle(rules, cfg.Obfuscator.KeyRegex, cfg.Obfuscator.ValueRegex) - actions := sharedsec.Actions{ - // Default built-in block action - "block": sharedsec.NewBlockRequestAction(403, 10, "auto"), - } - - for _, entry := range rules.Actions { - a := actionFromEntry(&entry) - if a != nil { - actions[entry.ID] = a - } - } - return &wafHandle{ - Handle: handle, - actions: actions, - }, err -} - -type wafEventListener func(*waf.Handle, sharedsec.Actions, *config.Config, limiter.Limiter, dyngo.Operation) - -// wafEventListeners is the global list of event listeners registered by contribs at init time. This -// is thread-safe assuming all writes (via AddWAFEventListener) are performed within `init` -// functions; so this is written to only during initialization, and is read from concurrently only -// during runtime when no writes are happening anymore. -var wafEventListeners []wafEventListener - -// AddWAFEventListener adds a new WAF event listener to be registered whenever a new root operation -// is created. The normal way to use this is to call it from a `func init() {}` so that it is -// guaranteed to have happened before any listened to event may be emitted. -func AddWAFEventListener(fn wafEventListener) { - wafEventListeners = append(wafEventListeners, fn) -} diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/civisibility/constants/ci.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/civisibility/constants/ci.go new file mode 100644 index 000000000..d1ca2e80b --- /dev/null +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/civisibility/constants/ci.go @@ -0,0 +1,44 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. + +package constants + +const ( + // CIJobName indicates the name of the CI job. + CIJobName = "ci.job.name" + + // CIJobURL indicates the URL of the CI job. + CIJobURL = "ci.job.url" + + // CIPipelineID indicates the ID of the CI pipeline. + CIPipelineID = "ci.pipeline.id" + + // CIPipelineName indicates the name of the CI pipeline. + CIPipelineName = "ci.pipeline.name" + + // CIPipelineNumber indicates the number of the CI pipeline. + CIPipelineNumber = "ci.pipeline.number" + + // CIPipelineURL indicates the URL of the CI pipeline. + CIPipelineURL = "ci.pipeline.url" + + // CIProviderName indicates the name of the CI provider. + CIProviderName = "ci.provider.name" + + // CIStageName indicates the name of the CI stage. + CIStageName = "ci.stage.name" + + // CINodeName indicates the name of the node in the CI environment. + CINodeName = "ci.node.name" + + // CINodeLabels indicates the labels associated with the node in the CI environment. + CINodeLabels = "ci.node.labels" + + // CIWorkspacePath records an absolute path to the directory where the project has been checked out. + CIWorkspacePath = "ci.workspace_path" + + // CIEnvVars contains environment variables used to get the pipeline correlation ID. + CIEnvVars = "_dd.ci.env_vars" +) diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/civisibility/constants/env.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/civisibility/constants/env.go new file mode 100644 index 000000000..66e6de763 --- /dev/null +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/civisibility/constants/env.go @@ -0,0 +1,40 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. + +package constants + +const ( + // CIVisibilityEnabledEnvironmentVariable indicates if CI Visibility mode is enabled. + // This environment variable should be set to "1" or "true" to enable CI Visibility mode, which activates tracing and other + // features related to CI Visibility in the Datadog platform. + CIVisibilityEnabledEnvironmentVariable = "DD_CIVISIBILITY_ENABLED" + + // CIVisibilityAgentlessEnabledEnvironmentVariable indicates if CI Visibility agentless mode is enabled. + // This environment variable should be set to "1" or "true" to enable agentless mode for CI Visibility, where traces + // are sent directly to Datadog without using a local agent. + CIVisibilityAgentlessEnabledEnvironmentVariable = "DD_CIVISIBILITY_AGENTLESS_ENABLED" + + // CIVisibilityAgentlessURLEnvironmentVariable forces the agentless URL to a custom one. + // This environment variable allows you to specify a custom URL for the agentless intake in CI Visibility mode. + CIVisibilityAgentlessURLEnvironmentVariable = "DD_CIVISIBILITY_AGENTLESS_URL" + + // APIKeyEnvironmentVariable indicates the API key to be used for agentless intake. + // This environment variable should be set to your Datadog API key, allowing the agentless mode to authenticate and + // send data directly to the Datadog platform. + APIKeyEnvironmentVariable = "DD_API_KEY" + + // CIVisibilityTestSessionNameEnvironmentVariable indicate the test session name to be used on CI Visibility payloads + CIVisibilityTestSessionNameEnvironmentVariable = "DD_TEST_SESSION_NAME" + + // CIVisibilityFlakyRetryEnabledEnvironmentVariable kill-switch that allows to explicitly disable retries even if the remote setting is enabled. + // This environment variable should be set to "0" or "false" to disable the flaky retry feature. + CIVisibilityFlakyRetryEnabledEnvironmentVariable = "DD_CIVISIBILITY_FLAKY_RETRY_ENABLED" + + // CIVisibilityFlakyRetryCountEnvironmentVariable indicates the maximum number of retry attempts for a single test case. + CIVisibilityFlakyRetryCountEnvironmentVariable = "DD_CIVISIBILITY_FLAKY_RETRY_COUNT" + + // CIVisibilityTotalFlakyRetryCountEnvironmentVariable indicates the maximum number of retry attempts for the entire session. + CIVisibilityTotalFlakyRetryCountEnvironmentVariable = "DD_CIVISIBILITY_TOTAL_FLAKY_RETRY_COUNT" +) diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/civisibility/constants/git.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/civisibility/constants/git.go new file mode 100644 index 000000000..6265be391 --- /dev/null +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/civisibility/constants/git.go @@ -0,0 +1,52 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. + +package constants + +const ( + // GitBranch indicates the current git branch. + // This constant is used to tag traces with the branch name being used in the CI/CD process. + GitBranch = "git.branch" + + // GitCommitAuthorDate indicates the git commit author date related to the build. + // This constant is used to tag traces with the date when the author created the commit. + GitCommitAuthorDate = "git.commit.author.date" + + // GitCommitAuthorEmail indicates the git commit author email related to the build. + // This constant is used to tag traces with the email of the author who created the commit. + GitCommitAuthorEmail = "git.commit.author.email" + + // GitCommitAuthorName indicates the git commit author name related to the build. + // This constant is used to tag traces with the name of the author who created the commit. + GitCommitAuthorName = "git.commit.author.name" + + // GitCommitCommitterDate indicates the git commit committer date related to the build. + // This constant is used to tag traces with the date when the committer applied the commit. + GitCommitCommitterDate = "git.commit.committer.date" + + // GitCommitCommitterEmail indicates the git commit committer email related to the build. + // This constant is used to tag traces with the email of the committer who applied the commit. + GitCommitCommitterEmail = "git.commit.committer.email" + + // GitCommitCommitterName indicates the git commit committer name related to the build. + // This constant is used to tag traces with the name of the committer who applied the commit. + GitCommitCommitterName = "git.commit.committer.name" + + // GitCommitMessage indicates the git commit message related to the build. + // This constant is used to tag traces with the message associated with the commit. + GitCommitMessage = "git.commit.message" + + // GitCommitSHA indicates the git commit SHA1 hash related to the build. + // This constant is used to tag traces with the SHA1 hash of the commit. + GitCommitSHA = "git.commit.sha" + + // GitRepositoryURL indicates the git repository URL related to the build. + // This constant is used to tag traces with the URL of the repository where the commit is stored. + GitRepositoryURL = "git.repository_url" + + // GitTag indicates the current git tag. + // This constant is used to tag traces with the tag name associated with the current commit. + GitTag = "git.tag" +) diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/civisibility/constants/os.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/civisibility/constants/os.go new file mode 100644 index 000000000..e065f179f --- /dev/null +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/civisibility/constants/os.go @@ -0,0 +1,21 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. + +package constants + +const ( + // OSPlatform indicates the operating system family (e.g., linux, windows, darwin). + // This constant is used to tag traces with the operating system family on which the tests are running. + OSPlatform = "os.platform" + + // OSVersion indicates the version of the operating system. + // This constant is used to tag traces with the specific version of the operating system on which the tests are running. + OSVersion = "os.version" + + // OSArchitecture indicates the architecture this SDK is built for (e.g., amd64, 386, arm). + // This constant is used to tag traces with the architecture of the operating system for which the tests are built. + // Note: This could be 32-bit on a 64-bit system. + OSArchitecture = "os.architecture" +) diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/civisibility/constants/runtime.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/civisibility/constants/runtime.go new file mode 100644 index 000000000..15257ef25 --- /dev/null +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/civisibility/constants/runtime.go @@ -0,0 +1,16 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. + +package constants + +const ( + // RuntimeName indicates the name of the runtime compiler. + // This constant is used to tag traces with the name of the runtime compiler being used (e.g., Go, JVM). + RuntimeName = "runtime.name" + + // RuntimeVersion indicates the version of the runtime compiler. + // This constant is used to tag traces with the specific version of the runtime compiler being used. + RuntimeVersion = "runtime.version" +) diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/civisibility/constants/span_types.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/civisibility/constants/span_types.go new file mode 100644 index 000000000..55f3fe58e --- /dev/null +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/civisibility/constants/span_types.go @@ -0,0 +1,28 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. + +package constants + +const ( + // SpanTypeTest marks a span as a test execution. + // This constant is used to indicate that the span represents a test execution. + SpanTypeTest = "test" + + // SpanTypeTestSuite marks a span as a test suite. + // This constant is used to indicate that the span represents the end of a test suite. + SpanTypeTestSuite = "test_suite_end" + + // SpanTypeTestModule marks a span as a test module. + // This constant is used to indicate that the span represents the end of a test module. + SpanTypeTestModule = "test_module_end" + + // SpanTypeTestSession marks a span as a test session. + // This constant is used to indicate that the span represents the end of a test session. + SpanTypeTestSession = "test_session_end" + + // SpanTypeSpan marks a span as a span event. + // This constant is used to indicate that the span represents a general span event. + SpanTypeSpan = "span" +) diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/civisibility/constants/tags.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/civisibility/constants/tags.go new file mode 100644 index 000000000..0a6d69083 --- /dev/null +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/civisibility/constants/tags.go @@ -0,0 +1,47 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. + +package constants + +const ( + // Origin is a tag used to indicate the origin of the data. + // This tag helps in identifying the source of the trace data. + Origin = "_dd.origin" + + // LogicalCPUCores is a tag used to indicate the number of logical cpu cores + // This tag is used by the backend to perform calculations + LogicalCPUCores = "_dd.host.vcpu_count" + + // CIAppTestOrigin defines the CIApp test origin value. + // This constant is used to tag traces that originate from CIApp test executions. + CIAppTestOrigin = "ciapp-test" + + // TestSessionIDTag defines the test session ID tag for the CI Visibility Protocol. + // This constant is used to tag traces with the ID of the test session. + TestSessionIDTag string = "test_session_id" + + // TestModuleIDTag defines the test module ID tag for the CI Visibility Protocol. + // This constant is used to tag traces with the ID of the test module. + TestModuleIDTag string = "test_module_id" + + // TestSuiteIDTag defines the test suite ID tag for the CI Visibility Protocol. + // This constant is used to tag traces with the ID of the test suite. + TestSuiteIDTag string = "test_suite_id" + + // ItrCorrelationIDTag defines the correlation ID for the intelligent test runner tag for the CI Visibility Protocol. + // This constant is used to tag traces with the correlation ID for intelligent test runs. + ItrCorrelationIDTag string = "itr_correlation_id" +) + +// Coverage tags +const ( + // CodeCoverageEnabledTag defines if code coverage has been enabled. + // This constant is used to tag traces to indicate whether code coverage measurement is enabled. + CodeCoverageEnabledTag string = "test.code_coverage.enabled" + + // CodeCoveragePercentageOfTotalLines defines the percentage of total code coverage by a session. + // This constant is used to tag traces with the percentage of code lines covered during the test session. + CodeCoveragePercentageOfTotalLines string = "test.code_coverage.lines_pct" +) diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/civisibility/constants/test_tags.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/civisibility/constants/test_tags.go new file mode 100644 index 000000000..7248d8245 --- /dev/null +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/civisibility/constants/test_tags.go @@ -0,0 +1,109 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. + +package constants + +const ( + // TestModule indicates the test module name. + // This constant is used to tag traces with the name of the test module. + TestModule = "test.module" + + // TestSuite indicates the test suite name. + // This constant is used to tag traces with the name of the test suite. + TestSuite = "test.suite" + + // TestName indicates the test name. + // This constant is used to tag traces with the name of the test. + TestName = "test.name" + + // TestType indicates the type of the test (e.g., test, benchmark). + // This constant is used to tag traces with the type of the test. + TestType = "test.type" + + // TestFramework indicates the test framework name. + // This constant is used to tag traces with the name of the test framework. + TestFramework = "test.framework" + + // TestFrameworkVersion indicates the test framework version. + // This constant is used to tag traces with the version of the test framework. + TestFrameworkVersion = "test.framework_version" + + // TestStatus indicates the test execution status. + // This constant is used to tag traces with the execution status of the test. + TestStatus = "test.status" + + // TestSkipReason indicates the skip reason of the test. + // This constant is used to tag traces with the reason why the test was skipped. + TestSkipReason = "test.skip_reason" + + // TestSourceFile indicates the source file where the test is located. + // This constant is used to tag traces with the file path of the test source code. + TestSourceFile = "test.source.file" + + // TestSourceStartLine indicates the line of the source file where the test starts. + // This constant is used to tag traces with the line number in the source file where the test starts. + TestSourceStartLine = "test.source.start" + + // TestSourceEndLine indicates the line of the source file where the test ends. + // This constant is used to tag traces with the line number in the source file where the test ends. + TestSourceEndLine = "test.source.end" + + // TestCodeOwners indicates the test code owners. + // This constant is used to tag traces with the code owners responsible for the test. + TestCodeOwners = "test.codeowners" + + // TestCommand indicates the test command. + // This constant is used to tag traces with the command used to execute the test. + TestCommand = "test.command" + + // TestCommandExitCode indicates the test command exit code. + // This constant is used to tag traces with the exit code of the test command. + TestCommandExitCode = "test.exit_code" + + // TestCommandWorkingDirectory indicates the test command working directory relative to the source root. + // This constant is used to tag traces with the working directory path relative to the source root. + TestCommandWorkingDirectory = "test.working_directory" + + // TestSessionName indicates the test session name + // This constant is used to tag traces with the test session name + TestSessionName = "test_session.name" + + // TestIsNew indicates a new test + // This constant is used to tag test events that are detected as new by early flake detection + TestIsNew = "test.is_new" + + // TestIsRetry indicates a retry execution + // This constant is used to tag test events that are part of a retry execution + TestIsRetry = "test.is_retry" + + // TestEarlyFlakeDetectionRetryAborted indicates a retry abort reason by the early flake detection feature + TestEarlyFlakeDetectionRetryAborted = "test.early_flake.abort_reason" +) + +// Define valid test status types. +const ( + // TestStatusPass marks test execution as passed. + // This constant is used to tag traces with a status indicating that the test passed. + TestStatusPass = "pass" + + // TestStatusFail marks test execution as failed. + // This constant is used to tag traces with a status indicating that the test failed. + TestStatusFail = "fail" + + // TestStatusSkip marks test execution as skipped. + // This constant is used to tag traces with a status indicating that the test was skipped. + TestStatusSkip = "skip" +) + +// Define valid test types. +const ( + // TestTypeTest defines test type as test. + // This constant is used to tag traces indicating that the type of test is a standard test. + TestTypeTest = "test" + + // TestTypeBenchmark defines test type as benchmark. + // This constant is used to tag traces indicating that the type of test is a benchmark. + TestTypeBenchmark = "benchmark" +) diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/civisibility/utils/ci_providers.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/civisibility/utils/ci_providers.go new file mode 100644 index 000000000..9b714ce59 --- /dev/null +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/civisibility/utils/ci_providers.go @@ -0,0 +1,578 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. + +package utils + +import ( + "encoding/json" + "fmt" + "os" + "regexp" + "sort" + "strings" + + "gopkg.in/DataDog/dd-trace-go.v1/internal/civisibility/constants" + "gopkg.in/DataDog/dd-trace-go.v1/internal/log" +) + +// providerType defines a function type that returns a map of string key-value pairs. +type providerType = func() map[string]string + +// providers maps environment variable names to their corresponding CI provider extraction functions. +var providers = map[string]providerType{ + "APPVEYOR": extractAppveyor, + "TF_BUILD": extractAzurePipelines, + "BITBUCKET_COMMIT": extractBitbucket, + "BUDDY": extractBuddy, + "BUILDKITE": extractBuildkite, + "CIRCLECI": extractCircleCI, + "GITHUB_SHA": extractGithubActions, + "GITLAB_CI": extractGitlab, + "JENKINS_URL": extractJenkins, + "TEAMCITY_VERSION": extractTeamcity, + "TRAVIS": extractTravis, + "BITRISE_BUILD_SLUG": extractBitrise, + "CF_BUILD_ID": extractCodefresh, + "CODEBUILD_INITIATOR": extractAwsCodePipeline, +} + +// getEnvVarsJSON returns a JSON representation of the specified environment variables. +func getEnvVarsJSON(envVars ...string) ([]byte, error) { + envVarsMap := make(map[string]string) + for _, envVar := range envVars { + value := os.Getenv(envVar) + if value != "" { + envVarsMap[envVar] = value + } + } + return json.Marshal(envVarsMap) +} + +// getProviderTags extracts CI information from environment variables. +func getProviderTags() map[string]string { + tags := map[string]string{} + for key, provider := range providers { + if _, ok := os.LookupEnv(key); !ok { + continue + } + tags = provider() + } + + // replace with user specific tags + replaceWithUserSpecificTags(tags) + + // Normalize tags + normalizeTags(tags) + + // Expand ~ + if tag, ok := tags[constants.CIWorkspacePath]; ok && tag != "" { + tags[constants.CIWorkspacePath] = ExpandPath(tag) + } + + // remove empty values + for tag, value := range tags { + if value == "" { + delete(tags, tag) + } + } + + if log.DebugEnabled() { + if providerName, ok := tags[constants.CIProviderName]; ok { + log.Debug("civisibility: detected ci provider: %v", providerName) + } else { + log.Debug("civisibility: no ci provider was detected.") + } + } + + return tags +} + +// normalizeTags normalizes specific tags to remove prefixes and sensitive information. +func normalizeTags(tags map[string]string) { + if tag, ok := tags[constants.GitBranch]; ok && tag != "" { + if strings.Contains(tag, "refs/tags") || strings.Contains(tag, "origin/tags") || strings.Contains(tag, "refs/heads/tags") { + tags[constants.GitTag] = normalizeRef(tag) + } + tags[constants.GitBranch] = normalizeRef(tag) + } + if tag, ok := tags[constants.GitTag]; ok && tag != "" { + tags[constants.GitTag] = normalizeRef(tag) + } + if tag, ok := tags[constants.GitRepositoryURL]; ok && tag != "" { + tags[constants.GitRepositoryURL] = filterSensitiveInfo(tag) + } + if tag, ok := tags[constants.CIPipelineURL]; ok && tag != "" { + tags[constants.CIPipelineURL] = filterSensitiveInfo(tag) + } + if tag, ok := tags[constants.CIJobURL]; ok && tag != "" { + tags[constants.CIJobURL] = filterSensitiveInfo(tag) + } + if tag, ok := tags[constants.CIEnvVars]; ok && tag != "" { + tags[constants.CIEnvVars] = filterSensitiveInfo(tag) + } +} + +// replaceWithUserSpecificTags replaces certain tags with user-specific environment variable values. +func replaceWithUserSpecificTags(tags map[string]string) { + replace := func(tagName, envName string) { + tags[tagName] = getEnvironmentVariableIfIsNotEmpty(envName, tags[tagName]) + } + + replace(constants.GitBranch, "DD_GIT_BRANCH") + replace(constants.GitTag, "DD_GIT_TAG") + replace(constants.GitRepositoryURL, "DD_GIT_REPOSITORY_URL") + replace(constants.GitCommitSHA, "DD_GIT_COMMIT_SHA") + replace(constants.GitCommitMessage, "DD_GIT_COMMIT_MESSAGE") + replace(constants.GitCommitAuthorName, "DD_GIT_COMMIT_AUTHOR_NAME") + replace(constants.GitCommitAuthorEmail, "DD_GIT_COMMIT_AUTHOR_EMAIL") + replace(constants.GitCommitAuthorDate, "DD_GIT_COMMIT_AUTHOR_DATE") + replace(constants.GitCommitCommitterName, "DD_GIT_COMMIT_COMMITTER_NAME") + replace(constants.GitCommitCommitterEmail, "DD_GIT_COMMIT_COMMITTER_EMAIL") + replace(constants.GitCommitCommitterDate, "DD_GIT_COMMIT_COMMITTER_DATE") +} + +// getEnvironmentVariableIfIsNotEmpty returns the environment variable value if it is not empty, otherwise returns the default value. +func getEnvironmentVariableIfIsNotEmpty(key string, defaultValue string) string { + if value, ok := os.LookupEnv(key); ok && value != "" { + return value + } + return defaultValue +} + +// normalizeRef normalizes a Git reference name by removing common prefixes. +func normalizeRef(name string) string { + // Define the prefixes to remove + prefixes := []string{"refs/heads/", "refs/", "origin/", "tags/"} + + // Iterate over prefixes and remove them if present + for _, prefix := range prefixes { + if strings.HasPrefix(name, prefix) { + name = strings.TrimPrefix(name, prefix) + } + } + return name +} + +// firstEnv returns the value of the first non-empty environment variable from the provided list. +func firstEnv(keys ...string) string { + for _, key := range keys { + if value, ok := os.LookupEnv(key); ok { + if value != "" { + return value + } + } + } + return "" +} + +// extractAppveyor extracts CI information specific to Appveyor. +func extractAppveyor() map[string]string { + tags := map[string]string{} + url := fmt.Sprintf("https://ci.appveyor.com/project/%s/builds/%s", os.Getenv("APPVEYOR_REPO_NAME"), os.Getenv("APPVEYOR_BUILD_ID")) + tags[constants.CIProviderName] = "appveyor" + if os.Getenv("APPVEYOR_REPO_PROVIDER") == "github" { + tags[constants.GitRepositoryURL] = fmt.Sprintf("https://github.com/%s.git", os.Getenv("APPVEYOR_REPO_NAME")) + } else { + tags[constants.GitRepositoryURL] = os.Getenv("APPVEYOR_REPO_NAME") + } + + tags[constants.GitCommitSHA] = os.Getenv("APPVEYOR_REPO_COMMIT") + tags[constants.GitBranch] = firstEnv("APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH", "APPVEYOR_REPO_BRANCH") + tags[constants.GitTag] = os.Getenv("APPVEYOR_REPO_TAG_NAME") + + tags[constants.CIWorkspacePath] = os.Getenv("APPVEYOR_BUILD_FOLDER") + tags[constants.CIPipelineID] = os.Getenv("APPVEYOR_BUILD_ID") + tags[constants.CIPipelineName] = os.Getenv("APPVEYOR_REPO_NAME") + tags[constants.CIPipelineNumber] = os.Getenv("APPVEYOR_BUILD_NUMBER") + tags[constants.CIPipelineURL] = url + tags[constants.CIJobURL] = url + tags[constants.GitCommitMessage] = fmt.Sprintf("%s\n%s", os.Getenv("APPVEYOR_REPO_COMMIT_MESSAGE"), os.Getenv("APPVEYOR_REPO_COMMIT_MESSAGE_EXTENDED")) + tags[constants.GitCommitAuthorName] = os.Getenv("APPVEYOR_REPO_COMMIT_AUTHOR") + tags[constants.GitCommitAuthorEmail] = os.Getenv("APPVEYOR_REPO_COMMIT_AUTHOR_EMAIL") + return tags +} + +// extractAzurePipelines extracts CI information specific to Azure Pipelines. +func extractAzurePipelines() map[string]string { + tags := map[string]string{} + baseURL := fmt.Sprintf("%s%s/_build/results?buildId=%s", os.Getenv("SYSTEM_TEAMFOUNDATIONSERVERURI"), os.Getenv("SYSTEM_TEAMPROJECTID"), os.Getenv("BUILD_BUILDID")) + pipelineURL := baseURL + jobURL := fmt.Sprintf("%s&view=logs&j=%s&t=%s", baseURL, os.Getenv("SYSTEM_JOBID"), os.Getenv("SYSTEM_TASKINSTANCEID")) + branchOrTag := firstEnv("SYSTEM_PULLREQUEST_SOURCEBRANCH", "BUILD_SOURCEBRANCH", "BUILD_SOURCEBRANCHNAME") + branch := "" + tag := "" + if strings.Contains(branchOrTag, "tags/") { + tag = branchOrTag + } else { + branch = branchOrTag + } + tags[constants.CIProviderName] = "azurepipelines" + tags[constants.CIWorkspacePath] = os.Getenv("BUILD_SOURCESDIRECTORY") + + tags[constants.CIPipelineID] = os.Getenv("BUILD_BUILDID") + tags[constants.CIPipelineName] = os.Getenv("BUILD_DEFINITIONNAME") + tags[constants.CIPipelineNumber] = os.Getenv("BUILD_BUILDID") + tags[constants.CIPipelineURL] = pipelineURL + + tags[constants.CIStageName] = os.Getenv("SYSTEM_STAGEDISPLAYNAME") + + tags[constants.CIJobName] = os.Getenv("SYSTEM_JOBDISPLAYNAME") + tags[constants.CIJobURL] = jobURL + + tags[constants.GitRepositoryURL] = firstEnv("SYSTEM_PULLREQUEST_SOURCEREPOSITORYURI", "BUILD_REPOSITORY_URI") + tags[constants.GitCommitSHA] = firstEnv("SYSTEM_PULLREQUEST_SOURCECOMMITID", "BUILD_SOURCEVERSION") + tags[constants.GitBranch] = branch + tags[constants.GitTag] = tag + tags[constants.GitCommitMessage] = os.Getenv("BUILD_SOURCEVERSIONMESSAGE") + tags[constants.GitCommitAuthorName] = os.Getenv("BUILD_REQUESTEDFORID") + tags[constants.GitCommitAuthorEmail] = os.Getenv("BUILD_REQUESTEDFOREMAIL") + + jsonString, err := getEnvVarsJSON("SYSTEM_TEAMPROJECTID", "BUILD_BUILDID", "SYSTEM_JOBID") + if err == nil { + tags[constants.CIEnvVars] = string(jsonString) + } + + return tags +} + +// extractBitrise extracts CI information specific to Bitrise. +func extractBitrise() map[string]string { + tags := map[string]string{} + tags[constants.CIProviderName] = "bitrise" + tags[constants.GitRepositoryURL] = os.Getenv("GIT_REPOSITORY_URL") + tags[constants.GitCommitSHA] = firstEnv("BITRISE_GIT_COMMIT", "GIT_CLONE_COMMIT_HASH") + tags[constants.GitBranch] = firstEnv("BITRISEIO_GIT_BRANCH_DEST", "BITRISE_GIT_BRANCH") + tags[constants.GitTag] = os.Getenv("BITRISE_GIT_TAG") + tags[constants.CIWorkspacePath] = os.Getenv("BITRISE_SOURCE_DIR") + tags[constants.CIPipelineID] = os.Getenv("BITRISE_BUILD_SLUG") + tags[constants.CIPipelineName] = os.Getenv("BITRISE_TRIGGERED_WORKFLOW_ID") + tags[constants.CIPipelineNumber] = os.Getenv("BITRISE_BUILD_NUMBER") + tags[constants.CIPipelineURL] = os.Getenv("BITRISE_BUILD_URL") + tags[constants.GitCommitMessage] = os.Getenv("BITRISE_GIT_MESSAGE") + return tags +} + +// extractBitbucket extracts CI information specific to Bitbucket. +func extractBitbucket() map[string]string { + tags := map[string]string{} + url := fmt.Sprintf("https://bitbucket.org/%s/addon/pipelines/home#!/results/%s", os.Getenv("BITBUCKET_REPO_FULL_NAME"), os.Getenv("BITBUCKET_BUILD_NUMBER")) + tags[constants.CIProviderName] = "bitbucket" + tags[constants.GitRepositoryURL] = firstEnv("BITBUCKET_GIT_SSH_ORIGIN", "BITBUCKET_GIT_HTTP_ORIGIN") + tags[constants.GitCommitSHA] = os.Getenv("BITBUCKET_COMMIT") + tags[constants.GitBranch] = os.Getenv("BITBUCKET_BRANCH") + tags[constants.GitTag] = os.Getenv("BITBUCKET_TAG") + tags[constants.CIWorkspacePath] = os.Getenv("BITBUCKET_CLONE_DIR") + tags[constants.CIPipelineID] = strings.Trim(os.Getenv("BITBUCKET_PIPELINE_UUID"), "{}") + tags[constants.CIPipelineNumber] = os.Getenv("BITBUCKET_BUILD_NUMBER") + tags[constants.CIPipelineName] = os.Getenv("BITBUCKET_REPO_FULL_NAME") + tags[constants.CIPipelineURL] = url + tags[constants.CIJobURL] = url + return tags +} + +// extractBuddy extracts CI information specific to Buddy. +func extractBuddy() map[string]string { + tags := map[string]string{} + tags[constants.CIProviderName] = "buddy" + tags[constants.CIPipelineID] = fmt.Sprintf("%s/%s", os.Getenv("BUDDY_PIPELINE_ID"), os.Getenv("BUDDY_EXECUTION_ID")) + tags[constants.CIPipelineName] = os.Getenv("BUDDY_PIPELINE_NAME") + tags[constants.CIPipelineNumber] = os.Getenv("BUDDY_EXECUTION_ID") + tags[constants.CIPipelineURL] = os.Getenv("BUDDY_EXECUTION_URL") + tags[constants.GitCommitSHA] = os.Getenv("BUDDY_EXECUTION_REVISION") + tags[constants.GitRepositoryURL] = os.Getenv("BUDDY_SCM_URL") + tags[constants.GitBranch] = os.Getenv("BUDDY_EXECUTION_BRANCH") + tags[constants.GitTag] = os.Getenv("BUDDY_EXECUTION_TAG") + tags[constants.GitCommitMessage] = os.Getenv("BUDDY_EXECUTION_REVISION_MESSAGE") + tags[constants.GitCommitCommitterName] = os.Getenv("BUDDY_EXECUTION_REVISION_COMMITTER_NAME") + tags[constants.GitCommitCommitterEmail] = os.Getenv("BUDDY_EXECUTION_REVISION_COMMITTER_EMAIL") + return tags +} + +// extractBuildkite extracts CI information specific to Buildkite. +func extractBuildkite() map[string]string { + tags := map[string]string{} + tags[constants.GitBranch] = os.Getenv("BUILDKITE_BRANCH") + tags[constants.GitCommitSHA] = os.Getenv("BUILDKITE_COMMIT") + tags[constants.GitRepositoryURL] = os.Getenv("BUILDKITE_REPO") + tags[constants.GitTag] = os.Getenv("BUILDKITE_TAG") + tags[constants.CIPipelineID] = os.Getenv("BUILDKITE_BUILD_ID") + tags[constants.CIPipelineName] = os.Getenv("BUILDKITE_PIPELINE_SLUG") + tags[constants.CIPipelineNumber] = os.Getenv("BUILDKITE_BUILD_NUMBER") + tags[constants.CIPipelineURL] = os.Getenv("BUILDKITE_BUILD_URL") + tags[constants.CIJobURL] = fmt.Sprintf("%s#%s", os.Getenv("BUILDKITE_BUILD_URL"), os.Getenv("BUILDKITE_JOB_ID")) + tags[constants.CIProviderName] = "buildkite" + tags[constants.CIWorkspacePath] = os.Getenv("BUILDKITE_BUILD_CHECKOUT_PATH") + tags[constants.GitCommitMessage] = os.Getenv("BUILDKITE_MESSAGE") + tags[constants.GitCommitAuthorName] = os.Getenv("BUILDKITE_BUILD_AUTHOR") + tags[constants.GitCommitAuthorEmail] = os.Getenv("BUILDKITE_BUILD_AUTHOR_EMAIL") + tags[constants.CINodeName] = os.Getenv("BUILDKITE_AGENT_ID") + + jsonString, err := getEnvVarsJSON("BUILDKITE_BUILD_ID", "BUILDKITE_JOB_ID") + if err == nil { + tags[constants.CIEnvVars] = string(jsonString) + } + + var extraTags []string + envVars := os.Environ() + for _, envVar := range envVars { + if strings.HasPrefix(envVar, "BUILDKITE_AGENT_META_DATA_") { + envVarAsTag := envVar + envVarAsTag = strings.TrimPrefix(envVarAsTag, "BUILDKITE_AGENT_META_DATA_") + envVarAsTag = strings.ToLower(envVarAsTag) + envVarAsTag = strings.Replace(envVarAsTag, "=", ":", 1) + extraTags = append(extraTags, envVarAsTag) + } + } + + if len(extraTags) != 0 { + // HACK: Sorting isn't actually needed, but it simplifies testing if the order is consistent + sort.Sort(sort.Reverse(sort.StringSlice(extraTags))) + jsonString, err = json.Marshal(extraTags) + if err == nil { + tags[constants.CINodeLabels] = string(jsonString) + } + } + + return tags +} + +// extractCircleCI extracts CI information specific to CircleCI. +func extractCircleCI() map[string]string { + tags := map[string]string{} + tags[constants.CIProviderName] = "circleci" + tags[constants.GitRepositoryURL] = os.Getenv("CIRCLE_REPOSITORY_URL") + tags[constants.GitCommitSHA] = os.Getenv("CIRCLE_SHA1") + tags[constants.GitTag] = os.Getenv("CIRCLE_TAG") + tags[constants.GitBranch] = os.Getenv("CIRCLE_BRANCH") + tags[constants.CIWorkspacePath] = os.Getenv("CIRCLE_WORKING_DIRECTORY") + tags[constants.CIPipelineID] = os.Getenv("CIRCLE_WORKFLOW_ID") + tags[constants.CIPipelineName] = os.Getenv("CIRCLE_PROJECT_REPONAME") + tags[constants.CIPipelineNumber] = os.Getenv("CIRCLE_BUILD_NUM") + tags[constants.CIPipelineURL] = fmt.Sprintf("https://app.circleci.com/pipelines/workflows/%s", os.Getenv("CIRCLE_WORKFLOW_ID")) + tags[constants.CIJobName] = os.Getenv("CIRCLE_JOB") + tags[constants.CIJobURL] = os.Getenv("CIRCLE_BUILD_URL") + + jsonString, err := getEnvVarsJSON("CIRCLE_BUILD_NUM", "CIRCLE_WORKFLOW_ID") + if err == nil { + tags[constants.CIEnvVars] = string(jsonString) + } + + return tags +} + +// extractGithubActions extracts CI information specific to GitHub Actions. +func extractGithubActions() map[string]string { + tags := map[string]string{} + branchOrTag := firstEnv("GITHUB_HEAD_REF", "GITHUB_REF") + tag := "" + branch := "" + if strings.Contains(branchOrTag, "tags/") { + tag = branchOrTag + } else { + branch = branchOrTag + } + + serverURL := os.Getenv("GITHUB_SERVER_URL") + if serverURL == "" { + serverURL = "https://github.com" + } + serverURL = strings.TrimSuffix(serverURL, "/") + + rawRepository := fmt.Sprintf("%s/%s", serverURL, os.Getenv("GITHUB_REPOSITORY")) + pipelineID := os.Getenv("GITHUB_RUN_ID") + commitSha := os.Getenv("GITHUB_SHA") + + tags[constants.CIProviderName] = "github" + tags[constants.GitRepositoryURL] = rawRepository + ".git" + tags[constants.GitCommitSHA] = commitSha + tags[constants.GitBranch] = branch + tags[constants.GitTag] = tag + tags[constants.CIWorkspacePath] = os.Getenv("GITHUB_WORKSPACE") + tags[constants.CIPipelineID] = pipelineID + tags[constants.CIPipelineNumber] = os.Getenv("GITHUB_RUN_NUMBER") + tags[constants.CIPipelineName] = os.Getenv("GITHUB_WORKFLOW") + tags[constants.CIJobURL] = fmt.Sprintf("%s/commit/%s/checks", rawRepository, commitSha) + tags[constants.CIJobName] = os.Getenv("GITHUB_JOB") + + attempts := os.Getenv("GITHUB_RUN_ATTEMPT") + if attempts == "" { + tags[constants.CIPipelineURL] = fmt.Sprintf("%s/actions/runs/%s", rawRepository, pipelineID) + } else { + tags[constants.CIPipelineURL] = fmt.Sprintf("%s/actions/runs/%s/attempts/%s", rawRepository, pipelineID, attempts) + } + + jsonString, err := getEnvVarsJSON("GITHUB_SERVER_URL", "GITHUB_REPOSITORY", "GITHUB_RUN_ID", "GITHUB_RUN_ATTEMPT") + if err == nil { + tags[constants.CIEnvVars] = string(jsonString) + } + + return tags +} + +// extractGitlab extracts CI information specific to GitLab. +func extractGitlab() map[string]string { + tags := map[string]string{} + url := os.Getenv("CI_PIPELINE_URL") + + tags[constants.CIProviderName] = "gitlab" + tags[constants.GitRepositoryURL] = os.Getenv("CI_REPOSITORY_URL") + tags[constants.GitCommitSHA] = os.Getenv("CI_COMMIT_SHA") + tags[constants.GitBranch] = firstEnv("CI_COMMIT_BRANCH", "CI_COMMIT_REF_NAME") + tags[constants.GitTag] = os.Getenv("CI_COMMIT_TAG") + tags[constants.CIWorkspacePath] = os.Getenv("CI_PROJECT_DIR") + tags[constants.CIPipelineID] = os.Getenv("CI_PIPELINE_ID") + tags[constants.CIPipelineName] = os.Getenv("CI_PROJECT_PATH") + tags[constants.CIPipelineNumber] = os.Getenv("CI_PIPELINE_IID") + tags[constants.CIPipelineURL] = url + tags[constants.CIJobURL] = os.Getenv("CI_JOB_URL") + tags[constants.CIJobName] = os.Getenv("CI_JOB_NAME") + tags[constants.CIStageName] = os.Getenv("CI_JOB_STAGE") + tags[constants.GitCommitMessage] = os.Getenv("CI_COMMIT_MESSAGE") + tags[constants.CINodeName] = os.Getenv("CI_RUNNER_ID") + tags[constants.CINodeLabels] = os.Getenv("CI_RUNNER_TAGS") + + author := os.Getenv("CI_COMMIT_AUTHOR") + authorArray := strings.FieldsFunc(author, func(s rune) bool { + return s == '<' || s == '>' + }) + tags[constants.GitCommitAuthorName] = strings.TrimSpace(authorArray[0]) + tags[constants.GitCommitAuthorEmail] = strings.TrimSpace(authorArray[1]) + tags[constants.GitCommitAuthorDate] = os.Getenv("CI_COMMIT_TIMESTAMP") + + jsonString, err := getEnvVarsJSON("CI_PROJECT_URL", "CI_PIPELINE_ID", "CI_JOB_ID") + if err == nil { + tags[constants.CIEnvVars] = string(jsonString) + } + + return tags +} + +// extractJenkins extracts CI information specific to Jenkins. +func extractJenkins() map[string]string { + tags := map[string]string{} + tags[constants.CIProviderName] = "jenkins" + tags[constants.GitRepositoryURL] = firstEnv("GIT_URL", "GIT_URL_1") + tags[constants.GitCommitSHA] = os.Getenv("GIT_COMMIT") + + branchOrTag := os.Getenv("GIT_BRANCH") + empty := []byte("") + name, hasName := os.LookupEnv("JOB_NAME") + + if strings.Contains(branchOrTag, "tags/") { + tags[constants.GitTag] = branchOrTag + } else { + tags[constants.GitBranch] = branchOrTag + // remove branch for job name + removeBranch := regexp.MustCompile(fmt.Sprintf("/%s", normalizeRef(branchOrTag))) + name = string(removeBranch.ReplaceAll([]byte(name), empty)) + } + + if hasName { + removeVars := regexp.MustCompile("/[^/]+=[^/]*") + name = string(removeVars.ReplaceAll([]byte(name), empty)) + } + + tags[constants.CIWorkspacePath] = os.Getenv("WORKSPACE") + tags[constants.CIPipelineID] = os.Getenv("BUILD_TAG") + tags[constants.CIPipelineNumber] = os.Getenv("BUILD_NUMBER") + tags[constants.CIPipelineName] = name + tags[constants.CIPipelineURL] = os.Getenv("BUILD_URL") + tags[constants.CINodeName] = os.Getenv("NODE_NAME") + + jsonString, err := getEnvVarsJSON("DD_CUSTOM_TRACE_ID") + if err == nil { + tags[constants.CIEnvVars] = string(jsonString) + } + + nodeLabels := os.Getenv("NODE_LABELS") + if len(nodeLabels) > 0 { + labelsArray := strings.Split(nodeLabels, " ") + jsonString, err := json.Marshal(labelsArray) + if err == nil { + tags[constants.CINodeLabels] = string(jsonString) + } + } + + return tags +} + +// extractTeamcity extracts CI information specific to TeamCity. +func extractTeamcity() map[string]string { + tags := map[string]string{} + tags[constants.CIProviderName] = "teamcity" + tags[constants.CIJobURL] = os.Getenv("BUILD_URL") + tags[constants.CIJobName] = os.Getenv("TEAMCITY_BUILDCONF_NAME") + return tags +} + +// extractCodefresh extracts CI information specific to Codefresh. +func extractCodefresh() map[string]string { + tags := map[string]string{} + tags[constants.CIProviderName] = "codefresh" + tags[constants.CIPipelineID] = os.Getenv("CF_BUILD_ID") + tags[constants.CIPipelineName] = os.Getenv("CF_PIPELINE_NAME") + tags[constants.CIPipelineURL] = os.Getenv("CF_BUILD_URL") + tags[constants.CIJobName] = os.Getenv("CF_STEP_NAME") + + jsonString, err := getEnvVarsJSON("CF_BUILD_ID") + if err == nil { + tags[constants.CIEnvVars] = string(jsonString) + } + + cfBranch := os.Getenv("CF_BRANCH") + isTag := strings.Contains(cfBranch, "tags/") + var refKey string + if isTag { + refKey = constants.GitTag + } else { + refKey = constants.GitBranch + } + tags[refKey] = normalizeRef(cfBranch) + + return tags +} + +// extractTravis extracts CI information specific to Travis CI. +func extractTravis() map[string]string { + tags := map[string]string{} + prSlug := os.Getenv("TRAVIS_PULL_REQUEST_SLUG") + repoSlug := prSlug + if strings.TrimSpace(repoSlug) == "" { + repoSlug = os.Getenv("TRAVIS_REPO_SLUG") + } + tags[constants.CIProviderName] = "travisci" + tags[constants.GitRepositoryURL] = fmt.Sprintf("https://github.com/%s.git", repoSlug) + tags[constants.GitCommitSHA] = os.Getenv("TRAVIS_COMMIT") + tags[constants.GitTag] = os.Getenv("TRAVIS_TAG") + tags[constants.GitBranch] = firstEnv("TRAVIS_PULL_REQUEST_BRANCH", "TRAVIS_BRANCH") + tags[constants.CIWorkspacePath] = os.Getenv("TRAVIS_BUILD_DIR") + tags[constants.CIPipelineID] = os.Getenv("TRAVIS_BUILD_ID") + tags[constants.CIPipelineNumber] = os.Getenv("TRAVIS_BUILD_NUMBER") + tags[constants.CIPipelineName] = repoSlug + tags[constants.CIPipelineURL] = os.Getenv("TRAVIS_BUILD_WEB_URL") + tags[constants.CIJobURL] = os.Getenv("TRAVIS_JOB_WEB_URL") + tags[constants.GitCommitMessage] = os.Getenv("TRAVIS_COMMIT_MESSAGE") + return tags +} + +// extractAwsCodePipeline extracts CI information specific to AWS CodePipeline. +func extractAwsCodePipeline() map[string]string { + tags := map[string]string{} + + if !strings.HasPrefix(os.Getenv("CODEBUILD_INITIATOR"), "codepipeline") { + // CODEBUILD_INITIATOR is defined but this is not a codepipeline build + return tags + } + + tags[constants.CIProviderName] = "awscodepipeline" + tags[constants.CIPipelineID] = os.Getenv("DD_PIPELINE_EXECUTION_ID") + + jsonString, err := getEnvVarsJSON("CODEBUILD_BUILD_ARN", "DD_ACTION_EXECUTION_ID", "DD_PIPELINE_EXECUTION_ID") + if err == nil { + tags[constants.CIEnvVars] = string(jsonString) + } + + return tags +} diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/civisibility/utils/codeowners.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/civisibility/utils/codeowners.go new file mode 100644 index 000000000..067494515 --- /dev/null +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/civisibility/utils/codeowners.go @@ -0,0 +1,307 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. + +package utils + +import ( + "bufio" + "errors" + "fmt" + "os" + "path/filepath" + "strings" + "sync" + + "gopkg.in/DataDog/dd-trace-go.v1/internal/civisibility/constants" + + logger "gopkg.in/DataDog/dd-trace-go.v1/internal/log" +) + +// This is a port of https://github.com/DataDog/dd-trace-dotnet/blob/v2.53.0/tracer/src/Datadog.Trace/Ci/CodeOwners.cs + +type ( + // CodeOwners represents a structured data type that holds sections of code owners. + // Each section maps to a slice of entries, where each entry includes a pattern and a list of owners. + CodeOwners struct { + Sections []*Section + } + + // Section represents a block of structured data of multiple entries in a single section + Section struct { + Name string + Entries []Entry + } + + // Entry represents a single entry in a CODEOWNERS file. + // It includes the pattern for matching files, the list of owners, and the section to which it belongs. + Entry struct { + Pattern string + Owners []string + Section string + } +) + +var ( + // codeowners holds the parsed CODEOWNERS file data. + codeowners *CodeOwners + codeownersMutex sync.Mutex +) + +// GetCodeOwners retrieves and caches the CODEOWNERS data. +// It looks for the CODEOWNERS file in various standard locations within the CI workspace. +// This function is thread-safe due to the use of a mutex. +// +// Returns: +// +// A pointer to a CodeOwners struct containing the parsed CODEOWNERS data, or nil if not found. +func GetCodeOwners() *CodeOwners { + codeownersMutex.Lock() + defer codeownersMutex.Unlock() + + if codeowners != nil { + return codeowners + } + + tags := GetCITags() + if v, ok := tags[constants.CIWorkspacePath]; ok { + paths := []string{ + filepath.Join(v, "CODEOWNERS"), + filepath.Join(v, ".github", "CODEOWNERS"), + filepath.Join(v, ".gitlab", "CODEOWNERS"), + filepath.Join(v, ".docs", "CODEOWNERS"), + } + for _, path := range paths { + if _, err := os.Stat(path); err == nil { + codeowners, err = NewCodeOwners(path) + if err == nil { + if logger.DebugEnabled() { + logger.Debug("civisibility: codeowner file '%v' was loaded successfully.", path) + } + return codeowners + } + logger.Debug("Error parsing codeowners: %s", err) + } + } + } + + return nil +} + +// NewCodeOwners creates a new instance of CodeOwners by parsing a CODEOWNERS file located at the given filePath. +// It returns an error if the file cannot be read or parsed properly. +func NewCodeOwners(filePath string) (*CodeOwners, error) { + if filePath == "" { + return nil, fmt.Errorf("filePath cannot be empty") + } + + file, err := os.Open(filePath) + if err != nil { + return nil, err + } + defer func() { + err = file.Close() + if err != nil && !errors.Is(os.ErrClosed, err) { + logger.Warn("Error closing codeowners file: %s", err.Error()) + } + }() + + var entriesList []Entry + var sectionsList []string + var currentSectionName string + + scanner := bufio.NewScanner(file) + for scanner.Scan() { + line := scanner.Text() + if len(line) == 0 || line[0] == '#' { + continue + } + + // Identify section headers, which are lines enclosed in square brackets + if strings.HasPrefix(line, "[") && strings.HasSuffix(line, "]") { + currentSectionName = line[1 : len(line)-1] + foundSectionName := findSectionIgnoreCase(sectionsList, currentSectionName) + if foundSectionName == "" { + sectionsList = append(sectionsList, currentSectionName) + } else { + currentSectionName = foundSectionName + } + continue + } + + finalLine := line + var ownersList []string + terms := strings.Fields(line) + for _, term := range terms { + if len(term) == 0 { + continue + } + + // Identify owners by their prefixes (either @ for usernames or containing @ for emails) + if term[0] == '@' || strings.Contains(term, "@") { + ownersList = append(ownersList, term) + pos := strings.Index(finalLine, term) + if pos > 0 { + finalLine = finalLine[:pos] + finalLine[pos+len(term):] + } + } + } + + finalLine = strings.TrimSpace(finalLine) + if len(finalLine) == 0 { + continue + } + + entriesList = append(entriesList, Entry{Pattern: finalLine, Owners: ownersList, Section: currentSectionName}) + } + + if err := scanner.Err(); err != nil { + return nil, err + } + + // Reverse the entries list to maintain the order of appearance in the file + for i, j := 0, len(entriesList)-1; i < j; i, j = i+1, j-1 { + entriesList[i], entriesList[j] = entriesList[j], entriesList[i] + } + + codeOwners := &CodeOwners{} + for _, entry := range entriesList { + var section *Section + for _, val := range codeOwners.Sections { + if val.Name == entry.Section { + section = val + break + } + } + + if section == nil { + section = &Section{Name: entry.Section, Entries: []Entry{}} + codeOwners.Sections = append(codeOwners.Sections, section) + } + + section.Entries = append(section.Entries, entry) + } + + return codeOwners, nil +} + +// findSectionIgnoreCase searches for a section name in a case-insensitive manner. +// It returns the section name if found, otherwise returns an empty string. +func findSectionIgnoreCase(sections []string, section string) string { + sectionLower := strings.ToLower(section) + for _, s := range sections { + if strings.ToLower(s) == sectionLower { + return s + } + } + return "" +} + +// GetSection gets the first Section entry in the CodeOwners that matches the section name. +// It returns a pointer to the matched entry, or nil if no match is found +func (co *CodeOwners) GetSection(section string) *Section { + for _, value := range co.Sections { + if value.Name == section { + return value + } + } + + return nil +} + +// Match finds the first entry in the CodeOwners that matches the given value. +// It returns a pointer to the matched entry, or nil if no match is found. +func (co *CodeOwners) Match(value string) (*Entry, bool) { + var matchedEntries []Entry + + for _, section := range co.Sections { + for _, entry := range section.Entries { + pattern := entry.Pattern + finalPattern := pattern + + var includeAnythingBefore, includeAnythingAfter bool + + if strings.HasPrefix(pattern, "/") { + includeAnythingBefore = false + } else { + if strings.HasPrefix(finalPattern, "*") { + finalPattern = finalPattern[1:] + } + includeAnythingBefore = true + } + + if strings.HasSuffix(pattern, "/") { + includeAnythingAfter = true + } else if strings.HasSuffix(pattern, "/*") { + includeAnythingAfter = true + finalPattern = finalPattern[:len(finalPattern)-1] + } else { + includeAnythingAfter = false + } + + if includeAnythingAfter { + found := includeAnythingBefore && strings.Contains(value, finalPattern) || strings.HasPrefix(value, finalPattern) + if !found { + continue + } + + if !strings.HasSuffix(pattern, "/*") { + matchedEntries = append(matchedEntries, entry) + break + } + + patternEnd := strings.Index(value, finalPattern) + if patternEnd != -1 { + patternEnd += len(finalPattern) + remainingString := value[patternEnd:] + if strings.Index(remainingString, "/") == -1 { + matchedEntries = append(matchedEntries, entry) + break + } + } + } else { + if includeAnythingBefore { + if strings.HasSuffix(value, finalPattern) { + matchedEntries = append(matchedEntries, entry) + break + } + } else if value == finalPattern { + matchedEntries = append(matchedEntries, entry) + break + } + } + } + } + + switch len(matchedEntries) { + case 0: + return nil, false + case 1: + return &matchedEntries[0], true + default: + patterns := make([]string, 0) + owners := make([]string, 0) + sections := make([]string, 0) + for _, entry := range matchedEntries { + patterns = append(patterns, entry.Pattern) + owners = append(owners, entry.Owners...) + sections = append(sections, entry.Section) + } + return &Entry{ + Pattern: strings.Join(patterns, " | "), + Owners: owners, + Section: strings.Join(sections, " | "), + }, true + } +} + +// GetOwnersString returns a formatted string of the owners list in an Entry. +// It returns an empty string if there are no owners. +func (e Entry) GetOwnersString() string { + if e.Owners == nil || len(e.Owners) == 0 { + return "" + } + + return "[\"" + strings.Join(e.Owners, "\",\"") + "\"]" +} diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/civisibility/utils/environmentTags.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/civisibility/utils/environmentTags.go new file mode 100644 index 000000000..8904596e5 --- /dev/null +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/civisibility/utils/environmentTags.go @@ -0,0 +1,193 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. + +package utils + +import ( + "fmt" + "os" + "path/filepath" + "regexp" + "runtime" + "strings" + "sync" + + "gopkg.in/DataDog/dd-trace-go.v1/internal/civisibility/constants" + "gopkg.in/DataDog/dd-trace-go.v1/internal/log" + "gopkg.in/DataDog/dd-trace-go.v1/internal/osinfo" +) + +var ( + // ciTags holds the CI/CD environment variable information. + ciTags map[string]string + ciTagsMutex sync.Mutex + + // ciMetrics holds the CI/CD environment numeric variable information + ciMetrics map[string]float64 + ciMetricsMutex sync.Mutex +) + +// GetCITags retrieves and caches the CI/CD tags from environment variables. +// It initializes the ciTags map if it is not already initialized. +// This function is thread-safe due to the use of a mutex. +// +// Returns: +// +// A map[string]string containing the CI/CD tags. +func GetCITags() map[string]string { + ciTagsMutex.Lock() + defer ciTagsMutex.Unlock() + + if ciTags == nil { + ciTags = createCITagsMap() + } + + return ciTags +} + +// GetCIMetrics retrieves and caches the CI/CD metrics from environment variables. +// It initializes the ciMetrics map if it is not already initialized. +// This function is thread-safe due to the use of a mutex. +// +// Returns: +// +// A map[string]float64 containing the CI/CD metrics. +func GetCIMetrics() map[string]float64 { + ciMetricsMutex.Lock() + defer ciMetricsMutex.Unlock() + + if ciMetrics == nil { + ciMetrics = createCIMetricsMap() + } + + return ciMetrics +} + +// GetRelativePathFromCITagsSourceRoot calculates the relative path from the CI workspace root to the specified path. +// If the CI workspace root is not available in the tags, it returns the original path. +// +// Parameters: +// +// path - The absolute or relative file path for which the relative path should be calculated. +// +// Returns: +// +// The relative path from the CI workspace root to the specified path, or the original path if an error occurs. +func GetRelativePathFromCITagsSourceRoot(path string) string { + tags := GetCITags() + if v, ok := tags[constants.CIWorkspacePath]; ok { + relPath, err := filepath.Rel(v, path) + if err == nil { + return filepath.ToSlash(relPath) + } + } + + return path +} + +// createCITagsMap creates a map of CI/CD tags by extracting information from environment variables and the local Git repository. +// It also adds OS and runtime information to the tags. +// +// Returns: +// +// A map[string]string containing the extracted CI/CD tags. +func createCITagsMap() map[string]string { + localTags := getProviderTags() + + // Populate runtime values + localTags[constants.OSPlatform] = runtime.GOOS + localTags[constants.OSVersion] = osinfo.OSVersion() + localTags[constants.OSArchitecture] = runtime.GOARCH + localTags[constants.RuntimeName] = runtime.Compiler + localTags[constants.RuntimeVersion] = runtime.Version() + log.Debug("civisibility: os platform: %v", runtime.GOOS) + log.Debug("civisibility: os architecture: %v", runtime.GOARCH) + log.Debug("civisibility: runtime version: %v", runtime.Version()) + + // Get command line test command + var cmd string + if len(os.Args) == 1 { + cmd = filepath.Base(os.Args[0]) + } else { + cmd = fmt.Sprintf("%s %s ", filepath.Base(os.Args[0]), strings.Join(os.Args[1:], " ")) + } + + // Filter out some parameters to make the command more stable. + cmd = regexp.MustCompile(`(?si)-test.gocoverdir=(.*)\s`).ReplaceAllString(cmd, "") + cmd = regexp.MustCompile(`(?si)-test.v=(.*)\s`).ReplaceAllString(cmd, "") + cmd = regexp.MustCompile(`(?si)-test.testlogfile=(.*)\s`).ReplaceAllString(cmd, "") + cmd = strings.TrimSpace(cmd) + localTags[constants.TestCommand] = cmd + log.Debug("civisibility: test command: %v", cmd) + + // Populate the test session name + if testSessionName, ok := os.LookupEnv(constants.CIVisibilityTestSessionNameEnvironmentVariable); ok { + localTags[constants.TestSessionName] = testSessionName + } else if jobName, ok := localTags[constants.CIJobName]; ok { + localTags[constants.TestSessionName] = fmt.Sprintf("%s-%s", jobName, cmd) + } else { + localTags[constants.TestSessionName] = cmd + } + log.Debug("civisibility: test session name: %v", localTags[constants.TestSessionName]) + + // Populate missing git data + gitData, _ := getLocalGitData() + + // Populate Git metadata from the local Git repository if not already present in localTags + if _, ok := localTags[constants.CIWorkspacePath]; !ok { + localTags[constants.CIWorkspacePath] = gitData.SourceRoot + } + if _, ok := localTags[constants.GitRepositoryURL]; !ok { + localTags[constants.GitRepositoryURL] = gitData.RepositoryURL + } + if _, ok := localTags[constants.GitCommitSHA]; !ok { + localTags[constants.GitCommitSHA] = gitData.CommitSha + } + if _, ok := localTags[constants.GitBranch]; !ok { + localTags[constants.GitBranch] = gitData.Branch + } + + // If the commit SHA matches, populate additional Git metadata + if localTags[constants.GitCommitSHA] == gitData.CommitSha { + if _, ok := localTags[constants.GitCommitAuthorDate]; !ok { + localTags[constants.GitCommitAuthorDate] = gitData.AuthorDate.String() + } + if _, ok := localTags[constants.GitCommitAuthorName]; !ok { + localTags[constants.GitCommitAuthorName] = gitData.AuthorName + } + if _, ok := localTags[constants.GitCommitAuthorEmail]; !ok { + localTags[constants.GitCommitAuthorEmail] = gitData.AuthorEmail + } + if _, ok := localTags[constants.GitCommitCommitterDate]; !ok { + localTags[constants.GitCommitCommitterDate] = gitData.CommitterDate.String() + } + if _, ok := localTags[constants.GitCommitCommitterName]; !ok { + localTags[constants.GitCommitCommitterName] = gitData.CommitterName + } + if _, ok := localTags[constants.GitCommitCommitterEmail]; !ok { + localTags[constants.GitCommitCommitterEmail] = gitData.CommitterEmail + } + if _, ok := localTags[constants.GitCommitMessage]; !ok { + localTags[constants.GitCommitMessage] = gitData.CommitMessage + } + } + + log.Debug("civisibility: workspace directory: %v", localTags[constants.CIWorkspacePath]) + log.Debug("civisibility: common tags created with %v items", len(localTags)) + return localTags +} + +// createCIMetricsMap creates a map of CI/CD tags by extracting information from environment variables and runtime information. +// +// Returns: +// +// A map[string]float64 containing the metrics extracted +func createCIMetricsMap() map[string]float64 { + localMetrics := make(map[string]float64) + localMetrics[constants.LogicalCPUCores] = float64(runtime.NumCPU()) + + log.Debug("civisibility: common metrics created with %v items", len(localMetrics)) + return localMetrics +} diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/civisibility/utils/git.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/civisibility/utils/git.go new file mode 100644 index 000000000..fb62a3756 --- /dev/null +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/civisibility/utils/git.go @@ -0,0 +1,104 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. + +package utils + +import ( + "errors" + "os/exec" + "regexp" + "strconv" + "strings" + "time" +) + +// localGitData holds various pieces of information about the local Git repository, +// including the source root, repository URL, branch, commit SHA, author and committer details, and commit message. +type localGitData struct { + SourceRoot string + RepositoryURL string + Branch string + CommitSha string + AuthorDate time.Time + AuthorName string + AuthorEmail string + CommitterDate time.Time + CommitterName string + CommitterEmail string + CommitMessage string +} + +// regexpSensitiveInfo is a regular expression used to match and filter out sensitive information from URLs. +var regexpSensitiveInfo = regexp.MustCompile("(https?://|ssh?://)[^/]*@") + +// getLocalGitData retrieves information about the local Git repository from the current HEAD. +// It gathers details such as the repository URL, current branch, latest commit SHA, author and committer details, and commit message. +// +// Returns: +// +// A localGitData struct populated with the retrieved Git data. +// An error if any Git command fails or the retrieved data is incomplete. +func getLocalGitData() (localGitData, error) { + gitData := localGitData{} + + // Extract the absolute path to the Git directory + out, err := exec.Command("git", "rev-parse", "--absolute-git-dir").Output() + if err == nil { + gitData.SourceRoot = strings.ReplaceAll(strings.Trim(string(out), "\n"), ".git", "") + } + + // Extract the repository URL + out, err = exec.Command("git", "ls-remote", "--get-url").Output() + if err == nil { + gitData.RepositoryURL = filterSensitiveInfo(strings.Trim(string(out), "\n")) + } + + // Extract the current branch name + out, err = exec.Command("git", "rev-parse", "--abbrev-ref", "HEAD").Output() + if err == nil { + gitData.Branch = strings.Trim(string(out), "\n") + } + + // Get commit details from the latest commit using git log (git log -1 --pretty='%H","%aI","%an","%ae","%cI","%cn","%ce","%B') + out, err = exec.Command("git", "log", "-1", "--pretty=%H\",\"%at\",\"%an\",\"%ae\",\"%ct\",\"%cn\",\"%ce\",\"%B").Output() + if err != nil { + return gitData, err + } + + // Split the output into individual components + outArray := strings.Split(string(out), "\",\"") + if len(outArray) < 8 { + return gitData, errors.New("git log failed") + } + + // Parse author and committer dates from Unix timestamp + authorUnixDate, _ := strconv.ParseInt(outArray[1], 10, 64) + committerUnixDate, _ := strconv.ParseInt(outArray[4], 10, 64) + + // Populate the localGitData struct with the parsed information + gitData.CommitSha = outArray[0] + gitData.AuthorDate = time.Unix(authorUnixDate, 0) + gitData.AuthorName = outArray[2] + gitData.AuthorEmail = outArray[3] + gitData.CommitterDate = time.Unix(committerUnixDate, 0) + gitData.CommitterName = outArray[5] + gitData.CommitterEmail = outArray[6] + gitData.CommitMessage = strings.Trim(outArray[7], "\n") + return gitData, nil +} + +// filterSensitiveInfo removes sensitive information from a given URL using a regular expression. +// It replaces the user credentials part of the URL (if present) with an empty string. +// +// Parameters: +// +// url - The URL string from which sensitive information should be filtered out. +// +// Returns: +// +// The sanitized URL string with sensitive information removed. +func filterSensitiveInfo(url string) string { + return string(regexpSensitiveInfo.ReplaceAll([]byte(url), []byte("$1"))[:]) +} diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/civisibility/utils/home.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/civisibility/utils/home.go new file mode 100644 index 000000000..fd2000c89 --- /dev/null +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/civisibility/utils/home.go @@ -0,0 +1,126 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. + +package utils + +import ( + "bytes" + "os" + "os/exec" + "path/filepath" + "runtime" + "strconv" + "strings" + + "gopkg.in/DataDog/dd-trace-go.v1/internal/log" +) + +// This code is based on: https://github.com/mitchellh/go-homedir/blob/v1.1.0/homedir.go (MIT License) + +// ExpandPath expands a file path that starts with '~' to the user's home directory. +// If the path does not start with '~', it is returned unchanged. +// +// Parameters: +// +// path - The file path to be expanded. +// +// Returns: +// +// The expanded file path, with '~' replaced by the user's home directory, if applicable. +func ExpandPath(path string) string { + if len(path) == 0 || path[0] != '~' { + return path + } + + // If the second character is not '/' or '\', return the path unchanged + if len(path) > 1 && path[1] != '/' && path[1] != '\\' { + return path + } + + homeFolder := getHomeDir() + if len(homeFolder) > 0 { + return filepath.Join(homeFolder, path[1:]) + } + + return path +} + +// getHomeDir returns the home directory of the current user. +// The method used to determine the home directory depends on the operating system. +// +// On Windows, it prefers the HOME environment variable, then USERPROFILE, and finally combines HOMEDRIVE and HOMEPATH. +// On Unix-like systems, it prefers the HOME environment variable, and falls back to various shell commands +// to determine the home directory if necessary. +// +// Returns: +// +// The home directory of the current user. +func getHomeDir() (homeDir string) { + defer func() { + log.Debug("civisibility: home directory: %v", homeDir) + }() + + if runtime.GOOS == "windows" { + if home := os.Getenv("HOME"); home != "" { + // First prefer the HOME environment variable + return home + } + if userProfile := os.Getenv("USERPROFILE"); userProfile != "" { + // Prefer the USERPROFILE environment variable + return userProfile + } + + homeDrive := os.Getenv("HOMEDRIVE") + homePath := os.Getenv("HOMEPATH") + return homeDrive + homePath + } + + homeEnv := "HOME" + if runtime.GOOS == "plan9" { + // On plan9, environment variables are lowercase. + homeEnv = "home" + } + + if home := os.Getenv(homeEnv); home != "" { + // Prefer the HOME environment variable + return home + } + + var stdout bytes.Buffer + if runtime.GOOS == "darwin" { + // On macOS, use dscl to read the NFSHomeDirectory + cmd := exec.Command("sh", "-c", `dscl -q . -read /Users/"$(whoami)" NFSHomeDirectory | sed 's/^[^ ]*: //'`) + cmd.Stdout = &stdout + if err := cmd.Run(); err == nil { + result := strings.TrimSpace(stdout.String()) + if result != "" { + return result + } + } + } else { + // On other Unix-like systems, use getent to read the passwd entry for the current user + cmd := exec.Command("getent", "passwd", strconv.Itoa(os.Getuid())) + cmd.Stdout = &stdout + if err := cmd.Run(); err == nil { + if passwd := strings.TrimSpace(stdout.String()); passwd != "" { + // The passwd entry is in the format: username:password:uid:gid:gecos:home:shell + passwdParts := strings.SplitN(passwd, ":", 7) + if len(passwdParts) > 5 { + return passwdParts[5] + } + } + } + } + + // If all else fails, use the shell to determine the home directory + stdout.Reset() + cmd := exec.Command("sh", "-c", "cd && pwd") + cmd.Stdout = &stdout + if err := cmd.Run(); err == nil { + return strings.TrimSpace(stdout.String()) + } + + return "" +} diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/civisibility/utils/names.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/civisibility/utils/names.go new file mode 100644 index 000000000..94eacdb18 --- /dev/null +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/civisibility/utils/names.go @@ -0,0 +1,93 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. + +package utils + +import ( + "bytes" + "fmt" + "path/filepath" + "runtime" + "slices" + "strings" +) + +var ( + // ignoredFunctionsFromStackTrace array with functions we want to ignore on the final stacktrace (because doesn't add anything useful) + ignoredFunctionsFromStackTrace = []string{"runtime.gopanic", "runtime.panicmem", "runtime.sigpanic"} +) + +// GetModuleAndSuiteName extracts the module name and suite name from a given program counter (pc). +// This function utilizes runtime.FuncForPC to retrieve the full function name associated with the +// program counter, then splits the string to separate the package name from the function name. +// +// Example 1: +// +// Input: github.com/DataDog/dd-sdk-go-testing.TestRun +// Output: +// module: github.com/DataDog/dd-sdk-go-testing +// suite: testing_test.go +// +// Example 2: +// +// Input: github.com/DataDog/dd-sdk-go-testing.TestRun.func1 +// Output: +// module: github.com/DataDog/dd-sdk-go-testing +// suite: testing_test.go +// +// Parameters: +// +// pc - The program counter for which the module and suite name should be retrieved. +// +// Returns: +// +// module - The module name extracted from the full function name. +// suite - The base name of the file where the function is located. +func GetModuleAndSuiteName(pc uintptr) (module string, suite string) { + funcValue := runtime.FuncForPC(pc) + funcFullName := funcValue.Name() + lastSlash := strings.LastIndexByte(funcFullName, '/') + if lastSlash < 0 { + lastSlash = 0 + } + firstDot := strings.IndexByte(funcFullName[lastSlash:], '.') + lastSlash + file, _ := funcValue.FileLine(funcValue.Entry()) + return funcFullName[:firstDot], filepath.Base(file) +} + +// GetStacktrace retrieves the current stack trace, skipping a specified number of frames. +// +// This function captures the stack trace of the current goroutine, formats it, and returns it as a string. +// It uses runtime.Callers to capture the program counters of the stack frames and runtime.CallersFrames +// to convert these program counters into readable frames. The stack trace is formatted to include the function +// name, file name, and line number of each frame. +// +// Parameters: +// +// skip - The number of stack frames to skip before capturing the stack trace. +// +// Returns: +// +// A string representation of the current stack trace, with each frame on a new line. +func GetStacktrace(skip int) string { + pcs := make([]uintptr, 256) + total := runtime.Callers(skip+2, pcs) + frames := runtime.CallersFrames(pcs[:total]) + buffer := new(bytes.Buffer) + for { + if frame, ok := frames.Next(); ok { + // let's check if we need to ignore this frame + if slices.Contains(ignoredFunctionsFromStackTrace, frame.Function) { + continue + } + // writing frame to the buffer + _, _ = fmt.Fprintf(buffer, "%s\n\t%s:%d\n", frame.Function, frame.File, frame.Line) + } else { + break + } + + } + return buffer.String() +} diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/datastreams/pathway.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/datastreams/pathway.go index 5ff05de27..a16891a7c 100644 --- a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/datastreams/pathway.go +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/datastreams/pathway.go @@ -19,10 +19,8 @@ var hashableEdgeTags = map[string]struct{}{"event_type": {}, "exchange": {}, "gr func isWellFormedEdgeTag(t string) bool { if i := strings.IndexByte(t, ':'); i != -1 { - if j := strings.LastIndexByte(t, ':'); j == i { - if _, exists := hashableEdgeTags[t[:i]]; exists { - return true - } + if _, exists := hashableEdgeTags[t[:i]]; exists { + return true } } return false diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/datastreams/processor.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/datastreams/processor.go index 4bba1ae56..10a8b8afb 100644 --- a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/datastreams/processor.go +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/datastreams/processor.go @@ -23,16 +23,17 @@ import ( "github.com/DataDog/sketches-go/ddsketch" "github.com/DataDog/sketches-go/ddsketch/mapping" "github.com/DataDog/sketches-go/ddsketch/store" - "github.com/golang/protobuf/proto" + "google.golang.org/protobuf/proto" ) const ( - bucketDuration = time.Second * 10 - loadAgentFeaturesInterval = time.Second * 30 - defaultServiceName = "unnamed-go-service" + bucketDuration = time.Second * 10 + defaultServiceName = "unnamed-go-service" ) -var sketchMapping, _ = mapping.NewLogarithmicMapping(0.01) +// use the same gamma and index offset as the Datadog backend, to avoid doing any conversions in +// the backend that would lead to a loss of precision +var sketchMapping, _ = mapping.NewLogarithmicMappingWithGamma(1.015625, 1.8761281912861705) type statsPoint struct { edgeTags []string @@ -189,9 +190,7 @@ type Processor struct { service string version string // used for tests - timeSource func() time.Time - disableStatsFlushing uint32 - getAgentSupportsDataStreams func() bool + timeSource func() time.Time } func (p *Processor) time() time.Time { @@ -201,25 +200,23 @@ func (p *Processor) time() time.Time { return time.Now() } -func NewProcessor(statsd internal.StatsdClient, env, service, version string, agentURL *url.URL, httpClient *http.Client, getAgentSupportsDataStreams func() bool) *Processor { +func NewProcessor(statsd internal.StatsdClient, env, service, version string, agentURL *url.URL, httpClient *http.Client) *Processor { if service == "" { service = defaultServiceName } p := &Processor{ - tsTypeCurrentBuckets: make(map[int64]bucket), - tsTypeOriginBuckets: make(map[int64]bucket), - hashCache: newHashCache(), - in: newFastQueue(), - stopped: 1, - statsd: statsd, - env: env, - service: service, - version: version, - transport: newHTTPTransport(agentURL, httpClient), - timeSource: time.Now, - getAgentSupportsDataStreams: getAgentSupportsDataStreams, - } - p.updateAgentSupportsDataStreams(getAgentSupportsDataStreams()) + tsTypeCurrentBuckets: make(map[int64]bucket), + tsTypeOriginBuckets: make(map[int64]bucket), + hashCache: newHashCache(), + in: newFastQueue(), + stopped: 1, + statsd: statsd, + env: env, + service: service, + version: version, + transport: newHTTPTransport(agentURL, httpClient), + timeSource: time.Now, + } return p } @@ -343,19 +340,17 @@ func (p *Processor) Start() { } p.stop = make(chan struct{}) p.flushRequest = make(chan chan<- struct{}) - p.wg.Add(2) - go p.reportStats() + p.wg.Add(1) go func() { defer p.wg.Done() - tick := time.NewTicker(bucketDuration) - defer tick.Stop() - p.run(tick.C) + p.reportStats() }() + p.wg.Add(1) go func() { defer p.wg.Done() - tick := time.NewTicker(loadAgentFeaturesInterval) + tick := time.NewTicker(bucketDuration) defer tick.Stop() - p.runLoadAgentFeatures(tick.C) + p.run(tick.C) }() } @@ -381,7 +376,14 @@ func (p *Processor) Stop() { } func (p *Processor) reportStats() { - for range time.NewTicker(time.Second * 10).C { + tick := time.NewTicker(time.Second * 10) + defer tick.Stop() + for { + select { + case <-p.stop: + return + case <-tick.C: + } p.statsd.Count("datadog.datastreams.processor.payloads_in", atomic.SwapInt64(&p.stats.payloadsIn, 0), nil, 1) p.statsd.Count("datadog.datastreams.processor.flushed_payloads", atomic.SwapInt64(&p.stats.flushedPayloads, 0), nil, 1) p.statsd.Count("datadog.datastreams.processor.flushed_buckets", atomic.SwapInt64(&p.stats.flushedBuckets, 0), nil, 1) @@ -506,28 +508,3 @@ func (p *Processor) TrackKafkaHighWatermarkOffset(_ string, topic string, partit atomic.AddInt64(&p.stats.dropped, 1) } } - -func (p *Processor) runLoadAgentFeatures(tick <-chan time.Time) { - for { - select { - case <-tick: - p.updateAgentSupportsDataStreams(p.getAgentSupportsDataStreams()) - case <-p.stop: - return - } - } -} - -func (p *Processor) updateAgentSupportsDataStreams(agentSupportsDataStreams bool) { - var disableStatsFlushing uint32 - if !agentSupportsDataStreams { - disableStatsFlushing = 1 - } - if atomic.SwapUint32(&p.disableStatsFlushing, disableStatsFlushing) != disableStatsFlushing { - if agentSupportsDataStreams { - log.Info("Detected agent upgrade. Turning on Data Streams Monitoring.") - } else { - log.Warn("Turning off Data Streams Monitoring. Upgrade your agent to 7.34+") - } - } -} diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/datastreams/transport.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/datastreams/transport.go index 27b28bf76..cd4c6b445 100644 --- a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/datastreams/transport.go +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/datastreams/transport.go @@ -10,46 +10,16 @@ import ( "compress/gzip" "fmt" "io" - "net" "net/http" "net/url" "runtime" "strings" - "time" "gopkg.in/DataDog/dd-trace-go.v1/internal" "github.com/tinylib/msgp/msgp" ) -const ( - defaultHostname = "localhost" - defaultPort = "8126" - defaultAddress = defaultHostname + ":" + defaultPort - defaultHTTPTimeout = 2 * time.Second // defines the current timeout before giving up with the send process -) - -var defaultDialer = &net.Dialer{ - Timeout: 30 * time.Second, - KeepAlive: 30 * time.Second, - DualStack: true, -} - -var defaultClient = &http.Client{ - // We copy the transport to avoid using the default one, as it might be - // augmented with tracing and we don't want these calls to be recorded. - // See https://golang.org/pkg/net/http/#DefaultTransport . - Transport: &http.Transport{ - Proxy: http.ProxyFromEnvironment, - DialContext: defaultDialer.DialContext, - MaxIdleConns: 100, - IdleConnTimeout: 90 * time.Second, - TLSHandshakeTimeout: 10 * time.Second, - ExpectContinueTimeout: 1 * time.Second, - }, - Timeout: defaultHTTPTimeout, -} - type httpTransport struct { url string // the delivery URL for stats client *http.Client // the HTTP client used in the POST diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/env.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/env.go index ae377ecbc..62704b779 100644 --- a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/env.go +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/env.go @@ -59,10 +59,10 @@ func DurationEnv(key string, def time.Duration) time.Duration { return v } -// ForEachStringTag runs fn on every key:val pair encountered in str. -// str may contain multiple key:val pairs separated by either space -// or comma (but not a mixture of both). -func ForEachStringTag(str string, fn func(key string, val string)) { +// ForEachStringTag runs fn on every key val pair encountered in str. +// str may contain multiple key val pairs separated by either space +// or comma (but not a mixture of both), and each key val pair is separated by a delimiter. +func ForEachStringTag(str string, delimiter string, fn func(key string, val string)) { sep := " " if strings.Index(str, ",") > -1 { // falling back to comma as separator @@ -73,7 +73,7 @@ func ForEachStringTag(str string, fn func(key string, val string)) { if tag == "" { continue } - kv := strings.SplitN(tag, ":", 2) + kv := strings.SplitN(tag, delimiter, 2) key := strings.TrimSpace(kv[0]) if key == "" { continue @@ -89,7 +89,7 @@ func ForEachStringTag(str string, fn func(key string, val string)) { // ParseTagString returns tags parsed from string as map func ParseTagString(str string) map[string]string { res := make(map[string]string) - ForEachStringTag(str, func(key, val string) { res[key] = val }) + ForEachStringTag(str, DDTagsDelimiter, func(key, val string) { res[key] = val }) return res } @@ -107,3 +107,12 @@ func FloatEnv(key string, def float64) float64 { } return v } + +// BoolVal returns the parsed boolean value of string val, or def if not parseable +func BoolVal(val string, def bool) bool { + v, err := strconv.ParseBool(val) + if err != nil { + return def + } + return v +} diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/gitmetadata.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/gitmetadata.go index f7eb9b78c..ce0ea38e5 100644 --- a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/gitmetadata.go +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/gitmetadata.go @@ -8,7 +8,10 @@ package internal import ( "net/url" "os" + "runtime/debug" "sync" + + "gopkg.in/DataDog/dd-trace-go.v1/internal/log" ) const ( @@ -37,8 +40,7 @@ const ( ) var ( - lock = sync.Mutex{} - + initOnce sync.Once gitMetadataTags map[string]string ) @@ -73,32 +75,51 @@ func getTagsFromDDTags() map[string]string { } } -// GetGitMetadataTags returns git metadata tags -func GetGitMetadataTags() map[string]string { - lock.Lock() - defer lock.Unlock() - - if gitMetadataTags != nil { - return gitMetadataTags +// getTagsFromBinary extracts git metadata from binary metadata. +func getTagsFromBinary(readBuildInfo func() (*debug.BuildInfo, bool)) map[string]string { + res := make(map[string]string) + info, ok := readBuildInfo() + if !ok { + log.Debug("ReadBuildInfo failed, skip source code metadata extracting") + return res + } + goPath := info.Path + var vcs, commitSha string + for _, s := range info.Settings { + if s.Key == "vcs" { + vcs = s.Value + } else if s.Key == "vcs.revision" { + commitSha = s.Value + } } + if vcs != "git" { + log.Debug("Unknown VCS: '%s', skip source code metadata extracting", vcs) + return res + } + res[TagCommitSha] = commitSha + res[TagGoPath] = goPath + return res +} + +// GetGitMetadataTags returns git metadata tags. Returned map is read-only +func GetGitMetadataTags() map[string]string { + initOnce.Do(initGitMetadataTags) + return gitMetadataTags +} +func initGitMetadataTags() { gitMetadataTags = make(map[string]string) if BoolEnv(EnvGitMetadataEnabledFlag, true) { updateAllTags(gitMetadataTags, getTagsFromEnv()) updateAllTags(gitMetadataTags, getTagsFromDDTags()) - updateAllTags(gitMetadataTags, getTagsFromBinary()) + updateAllTags(gitMetadataTags, getTagsFromBinary(debug.ReadBuildInfo)) } - - return gitMetadataTags } -// ResetGitMetadataTags reset cashed metadata tags -func ResetGitMetadataTags() { - lock.Lock() - defer lock.Unlock() - - gitMetadataTags = nil +// RefreshGitMetadataTags reset cached metadata tags. NOT thread-safe, use for testing only +func RefreshGitMetadataTags() { + initGitMetadataTags() } // CleanGitMetadataTags cleans up tags from git metadata diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/gitmetadatabinary.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/gitmetadatabinary.go deleted file mode 100644 index 84ded5eda..000000000 --- a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/gitmetadatabinary.go +++ /dev/null @@ -1,41 +0,0 @@ -// Unless explicitly stated otherwise all files in this repository are licensed -// under the Apache License Version 2.0. -// This product includes software developed at Datadog (https://www.datadoghq.com/). -// Copyright 2023 Datadog, Inc. - -//go:build go1.18 -// +build go1.18 - -package internal - -import ( - "runtime/debug" - - "gopkg.in/DataDog/dd-trace-go.v1/internal/log" -) - -// getTagsFromBinary extracts git metadata from binary metadata -func getTagsFromBinary() map[string]string { - res := make(map[string]string) - info, ok := debug.ReadBuildInfo() - if !ok { - log.Debug("ReadBuildInfo failed, skip source code metadata extracting") - return res - } - goPath := info.Path - var vcs, commitSha string - for _, s := range info.Settings { - if s.Key == "vcs" { - vcs = s.Value - } else if s.Key == "vcs.revision" { - commitSha = s.Value - } - } - if vcs != "git" { - log.Debug("Unknown VCS: '%s', skip source code metadata extracting", vcs) - return res - } - res[TagCommitSha] = commitSha - res[TagGoPath] = goPath - return res -} diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/gitmetadatabinary_legacy.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/gitmetadatabinary_legacy.go deleted file mode 100644 index 85bcb43cc..000000000 --- a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/gitmetadatabinary_legacy.go +++ /dev/null @@ -1,19 +0,0 @@ -// Unless explicitly stated otherwise all files in this repository are licensed -// under the Apache License Version 2.0. -// This product includes software developed at Datadog (https://www.datadoghq.com/). -// Copyright 2023 Datadog, Inc. - -//go:build !go1.18 -// +build !go1.18 - -package internal - -import ( - "gopkg.in/DataDog/dd-trace-go.v1/internal/log" -) - -// getTagsFromBinary extracts git metadata from binary metadata -func getTagsFromBinary() map[string]string { - log.Warn("go version below 1.18, BuildInfo has no vcs info, skip source code metadata extracting") - return make(map[string]string) -} diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/globalconfig/globalconfig.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/globalconfig/globalconfig.go index f4516bd61..a36f50035 100644 --- a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/globalconfig/globalconfig.go +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/globalconfig/globalconfig.go @@ -12,7 +12,6 @@ import ( "sync" "gopkg.in/DataDog/dd-trace-go.v1/internal" - "gopkg.in/DataDog/dd-trace-go.v1/internal/log" "github.com/google/uuid" ) @@ -29,7 +28,8 @@ type config struct { serviceName string runtimeID string headersAsTags *internal.LockMap - statsCarrier *internal.StatsCarrier + dogstatsdAddr string + statsTags []string } // AnalyticsRate returns the sampling rate at which events should be marked. It uses @@ -62,6 +62,41 @@ func SetServiceName(name string) { cfg.serviceName = name } +// DogstatsdAddr returns the destination for tracer and contrib statsd clients +func DogstatsdAddr() string { + cfg.mu.RLock() + defer cfg.mu.RUnlock() + return cfg.dogstatsdAddr +} + +// SetDogstatsdAddr sets the destination for statsd clients to be used by tracer and contrib packages +func SetDogstatsdAddr(addr string) { + cfg.mu.Lock() + defer cfg.mu.Unlock() + cfg.dogstatsdAddr = addr +} + +// StatsTags returns a list of tags that apply to statsd payloads for both tracer and contribs +func StatsTags() []string { + cfg.mu.RLock() + defer cfg.mu.RUnlock() + // Copy the slice before returning it, so that callers cannot pollute the underlying array + tags := make([]string, len(cfg.statsTags)) + copy(tags, cfg.statsTags) + return tags +} + +// SetStatsTags configures the list of tags that should be applied to contribs' statsd.Client as global tags +// It should only be called by the tracer package +func SetStatsTags(tags []string) { + cfg.mu.Lock() + defer cfg.mu.Unlock() + // Copy the slice before setting it, so that any changes to the slice provided to SetStatsTags does not pollute the underlying array of statsTags + statsTags := make([]string, len(tags)) + copy(statsTags, tags) + cfg.statsTags = statsTags +} + // RuntimeID returns this process's unique runtime id. func RuntimeID() string { cfg.mu.RLock() @@ -95,26 +130,3 @@ func HeaderTagsLen() int { func ClearHeaderTags() { cfg.headersAsTags.Clear() } - -// SetStatsCarrier sets the provided StatsCarrier onto the globalconfig -func SetStatsCarrier(sc *internal.StatsCarrier) { - cfg.mu.Lock() - defer cfg.mu.Unlock() - cfg.statsCarrier = sc -} - -// PushStat pushes the stat onto the StatsCarrier's stats channel, via the Add method -func PushStat(stat internal.Stat) { - cfg.mu.RLock() - defer cfg.mu.RUnlock() - if !StatsCarrier() { - log.Debug("No stats carrier found; dropping stat %v", stat.Name()) - return - } - cfg.statsCarrier.Add(stat) -} - -// StatsCarrier returns true if there is a StatsCarrier on the globalconfig, else false -func StatsCarrier() bool { - return cfg.statsCarrier != nil -} diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/log/log.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/log/log.go index c32b1ed9b..16be1ac7d 100644 --- a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/log/log.go +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/log/log.go @@ -15,6 +15,7 @@ import ( "sync" "time" + "gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/dyngo" "gopkg.in/DataDog/dd-trace-go.v1/internal/version" ) @@ -102,6 +103,11 @@ func init() { if v := os.Getenv("DD_LOGGING_RATE"); v != "" { setLoggingRate(v) } + + // This is required because we really want to be able to log errors from dyngo + // but the log package depend on too much packages that we want to instrument. + // So we need to do this to avoid dependency cycles. + dyngo.LogError = Error } func setLoggingRate(v string) { diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/meta_struct.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/meta_struct.go new file mode 100644 index 000000000..6a8404d9c --- /dev/null +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/meta_struct.go @@ -0,0 +1,12 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2016 Datadog, Inc. + +package internal + +// MetaStructValue is a custom type wrapper used to send metadata to the agent via the `meta_struct` field +// instead of the `meta` inside a span. +type MetaStructValue struct { + Value any // TODO: further constraining Value's type, especially if it becomes public +} diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/normalizer/normalizer.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/normalizer/normalizer.go index 955aebb76..eab118968 100644 --- a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/normalizer/normalizer.go +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/normalizer/normalizer.go @@ -36,14 +36,10 @@ func HeaderTag(headerAsTag string) (header string, tag string) { } // HeaderTagSlice accepts a slice of strings that contain headers and optional mapped tag key. -// Headers beginning with "x-datadog-" are ignored. // See HeaderTag for details on formatting. func HeaderTagSlice(headers []string) map[string]string { headerTagsMap := make(map[string]string) for _, h := range headers { - if strings.HasPrefix(h, "x-datadog-") { - continue - } header, tag := HeaderTag(h) // If `header` or `tag` is just the empty string, we don't want to set it. if len(header) == 0 || len(tag) == 0 { diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/orchestrion/context.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/orchestrion/context.go new file mode 100644 index 000000000..f66d12c57 --- /dev/null +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/orchestrion/context.go @@ -0,0 +1,72 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. + +package orchestrion + +import ( + "context" +) + +// WrapContext returns the GLS-wrapped context if orchestrion is enabled, otherwise it returns the given parameter. +func WrapContext(ctx context.Context) context.Context { + if !Enabled() { + return ctx + } + + if ctx != nil { + if _, ok := ctx.(*glsContext); ok { // avoid (some) double wrapping + return ctx + } + } + + if ctx == nil { + ctx = context.Background() + } + + return &glsContext{ctx} +} + +// CtxWithValue runs context.WithValue, adds the result to the GLS slot of orchestrion, and returns it. +// If orchestrion is not enabled, it will run context.WithValue and return the result. +// Since we don't support cross-goroutine switch of the GLS we still run context.WithValue in the case +// we are switching goroutines. +func CtxWithValue(parent context.Context, key, val any) context.Context { + if !Enabled() { + return context.WithValue(parent, key, val) + } + + getDDContextStack().Push(key, val) + return context.WithValue(WrapContext(parent), key, val) +} + +// GLSPopValue pops the value from the GLS slot of orchestrion and returns it. Using context.Context values usually does +// not require to pop any stack because the copy of each previous context makes the local variable in the scope disappear +// when the current function ends. But the GLS is a semi-global variable that can be accessed from any function in the +// stack, so we need to pop the value when we are done with it. +func GLSPopValue(key any) any { + if !Enabled() { + return nil + } + + return getDDContextStack().Pop(key) +} + +var _ context.Context = (*glsContext)(nil) + +type glsContext struct { + context.Context +} + +func (g *glsContext) Value(key any) any { + if !Enabled() { + return g.Context.Value(key) + } + + if val := getDDContextStack().Peek(key); val != nil { + return val + } + + return g.Context.Value(key) +} diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/orchestrion/context_stack.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/orchestrion/context_stack.go new file mode 100644 index 000000000..60dd1edca --- /dev/null +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/orchestrion/context_stack.go @@ -0,0 +1,62 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. + +package orchestrion + +// contextStack is the object put in the GLS slot of runtime.g inserted by orchestrion. it is used to store context values +// that are shared across the same goroutine. +// TODO: handle cross-goroutine context values +type contextStack map[any][]any + +// getDDContextStack is a main way to access the GLS slot of runtime.g inserted by orchestrion. This function should not be +// called if the enabled variable is false. +func getDDContextStack() *contextStack { + if gls := getDDGLS(); gls != nil { + return gls.(*contextStack) + } + + newStack := &contextStack{} + setDDGLS(newStack) + return newStack +} + +// Peek returns the top context from the stack without removing it. +func (s *contextStack) Peek(key any) any { + if s == nil || *s == nil { + return nil + } + + stack, ok := (*s)[key] + if !ok || len(stack) == 0 { + return nil + } + + return (*s)[key][len(stack)-1] +} + +// Push adds a context to the stack. +func (s *contextStack) Push(key, val any) { + if s == nil || *s == nil { + return + } + + (*s)[key] = append((*s)[key], val) +} + +// Pop removes the top context from the stack and returns it. +func (s *contextStack) Pop(key any) any { + if s == nil || *s == nil { + return nil + } + + stack, ok := (*s)[key] + if !ok || len(stack) == 0 { + return nil + } + + val := (*s)[key][len(stack)-1] + (*s)[key] = (*s)[key][:len(stack)-1] + return val +} diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/orchestrion/gls.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/orchestrion/gls.go new file mode 100644 index 000000000..d117759c0 --- /dev/null +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/orchestrion/gls.go @@ -0,0 +1,41 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. + +package orchestrion + +import ( + _ "runtime" // to make sure the symbols we link to are present + _ "unsafe" // for go:linkname +) + +var ( + // getDDGLS returns the current value from the field inserted in runtime.g by orchestrion. + // Or nil if orchestrion is not enabled. + getDDGLS = func() any { return nil } + // setDDGLS sets the value in the field inserted in runtime.g by orchestrion. + // Or does nothing if orchestrion is not enabled. + setDDGLS = func(any) {} +) + +// Accessors set by orchestrion in the runtime package. If orchestrion is not enabled, these will be nil as per the default values. + +//revive:disable:var-naming +//go:linkname __dd_orchestrion_gls_get __dd_orchestrion_gls_get +var __dd_orchestrion_gls_get func() any + +//go:linkname __dd_orchestrion_gls_set __dd_orchestrion_gls_set +var __dd_orchestrion_gls_set func(any) + +//revive:enable:var-naming + +// Check at Go init time that the two function variable values created by the +// orchestrion are present, and set the get/set variables to their +// values. +func init() { + if __dd_orchestrion_gls_get != nil && __dd_orchestrion_gls_set != nil { + getDDGLS = __dd_orchestrion_gls_get + setDDGLS = __dd_orchestrion_gls_set + } +} diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/orchestrion/orchestrion.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/orchestrion/orchestrion.go new file mode 100644 index 000000000..679593652 --- /dev/null +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/orchestrion/orchestrion.go @@ -0,0 +1,16 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. + +package orchestrion + +// Orchestrion will change this at build-time +// +//dd:orchestrion-enabled +var enabled = false + +// Enabled returns whether the current build was compiled with orchestrion or not. +func Enabled() bool { + return enabled +} diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/remoteconfig/remoteconfig.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/remoteconfig/remoteconfig.go index 6198f3173..4076c2ad3 100644 --- a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/remoteconfig/remoteconfig.go +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/remoteconfig/remoteconfig.go @@ -70,11 +70,50 @@ const ( APMTracingHTTPHeaderTags // APMTracingCustomTags enables APM client to set custom tags on all spans APMTracingCustomTags + // ASMProcessorOverrides adds support for processor overrides through the ASM RC Product + ASMProcessorOverrides + // ASMCustomDataScanners adds support for custom data scanners through the ASM RC Product + ASMCustomDataScanners + // ASMExclusionData adds support configurable exclusion filter data from the ASM_DATA Product + ASMExclusionData + // APMTracingEnabled enables APM tracing + APMTracingEnabled + // APMTracingDataStreamsEnabled enables Data Streams Monitoring + APMTracingDataStreamsEnabled + // ASMRASPSQLI enables ASM support for runtime protection against SQL Injection attacks + ASMRASPSQLI + // ASMRASPLFI enables ASM support for runtime protection against Local File Inclusion attacks + ASMRASPLFI + // ASMRASPSSRF enables ASM support for runtime protection against SSRF attacks + ASMRASPSSRF + // ASMRASPSHI enables ASM support for runtime protection against XSS attacks + ASMRASPSHI + // ASMRASPXXE enables ASM support for runtime protection against XXE attacks + ASMRASPXXE + // ASMRASPRCE enables ASM support for runtime protection against Remote Code Execution + ASMRASPRCE + // ASMRASPNOSQLI enables ASM support for runtime protection against NoSQL Injection attacks + ASMRASPNOSQLI + // ASMRASPXSS enables ASM support for runtime protection against Cross Site Scripting attacks + ASMRASPXSS + // APMTracingSampleRules represents the sampling rate using matching rules from APM client libraries + APMTracingSampleRules + // CSMActivation represents the capability to activate CSM through remote configuration + CSMActivation + // ASMAutoUserInstrumMode represents the capability to enable the automatic user instrumentation mode + ASMAutoUserInstrumMode + // ASMEndpointFingerprinting represents the capability to enable endpoint fingerprinting + ASMEndpointFingerprinting + // ASMSessionFingerprinting represents the capability to enable session fingerprinting + ASMSessionFingerprinting + // ASMNetworkFingerprinting represents the capability to enable network fingerprinting + ASMNetworkFingerprinting + // ASMHeaderFingerprinting represents the capability to enable header fingerprinting + ASMHeaderFingerprinting + // ASMTruncationRules is the support for truncation payload rules + ASMTruncationRules ) -// APMTracingEnabled enables APM tracing -const APMTracingEnabled Capability = 19 - // ErrClientNotStarted is returned when the remote config client is not started. var ErrClientNotStarted = errors.New("remote config client not started") @@ -376,6 +415,16 @@ func HasCapability(cap Capability) (bool, error) { return found, nil } +func (c *Client) allCapabilities() *big.Int { + client.capabilitiesMu.Lock() + defer client.capabilitiesMu.Unlock() + capa := big.NewInt(0) + for i := range c.capabilities { + capa.SetBit(capa, int(i), 1) + } + return capa +} + func (c *Client) globalCallbacks() []Callback { c._callbacksMu.RLock() defer c._callbacksMu.RUnlock() @@ -558,10 +607,7 @@ func (c *Client) newUpdateRequest() (bytes.Buffer, error) { } } - capa := big.NewInt(0) - for i := range c.capabilities { - capa.SetBit(capa, int(i), 1) - } + capa := c.allCapabilities() req := clientGetConfigsRequest{ Client: &clientData{ State: &clientState{ diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/samplernames/samplernames.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/samplernames/samplernames.go index 6342b53b4..54836680c 100644 --- a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/samplernames/samplernames.go +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/samplernames/samplernames.go @@ -22,7 +22,7 @@ const ( // RemoteRate specifies that the span was sampled // with a dynamically calculated remote rate. RemoteRate SamplerName = 2 - // RuleRate specifies that the span was sampled by the RuleSampler. + // RuleRate specifies that the span was sampled by the local RuleSampler. RuleRate SamplerName = 3 // Manual specifies that the span was sampled manually by user. Manual SamplerName = 4 @@ -34,4 +34,12 @@ const ( // SingleSpan specifies that the span was sampled by single // span sampling rules. SingleSpan SamplerName = 8 + // Sampler name 9 is reserved/used by OTel ingestion. + // Sampler name 10 is reserved for Data jobs (spark, databricks etc) + // RemoteUserRule specifies that the span was sampled by a rule the user configured remotely + // through Datadog UI. + RemoteUserRule SamplerName = 11 + // RemoteDynamicRule specifies that the span was sampled by a rule configured by Datadog + // Dynamic Sampling. + RemoteDynamicRule SamplerName = 12 ) diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/stacktrace/event.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/stacktrace/event.go new file mode 100644 index 000000000..0b6ff8188 --- /dev/null +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/stacktrace/event.go @@ -0,0 +1,115 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2016 Datadog, Inc. + +//go:generate msgp -o event_msgp.go -tests=false + +package stacktrace + +import ( + "gopkg.in/DataDog/dd-trace-go.v1/ddtrace" + "gopkg.in/DataDog/dd-trace-go.v1/internal" + + "github.com/tinylib/msgp/msgp" +) + +var _ msgp.Marshaler = (*Event)(nil) + +type EventCategory string + +const ( + // ExceptionEvent is the event type for exception events + ExceptionEvent EventCategory = "exception" + // VulnerabilityEvent is the event type for vulnerability events + VulnerabilityEvent EventCategory = "vulnerability" + // ExploitEvent is the event type for exploit events + ExploitEvent EventCategory = "exploit" +) + +const SpanKey = "_dd.stack" + +// Event is the toplevel structure to contain a stacktrace and the additional information needed to correlate it with other data +type Event struct { + // Category is a well-known type of the event, not optional + Category EventCategory `msg:"-"` + // Type is a value event category specific, optional + Type string `msg:"type,omitempty"` + // Language is the language of the code that generated the event (set to "go" anyway here) + Language string `msg:"language,omitempty"` + // ID is the id of the event, optional for exceptions but mandatory for vulnerabilities and exploits to correlate with more data + ID string `msg:"id,omitempty"` + // Message is a generic message for the event + Message string `msg:"message,omitempty"` + // Frames is the stack trace of the event + Frames StackTrace `msg:"frames"` +} + +// NewEvent creates a new stacktrace event with the given category, type and message +func NewEvent(eventCat EventCategory, options ...Options) *Event { + event := &Event{ + Category: eventCat, + Language: "go", + Frames: SkipAndCapture(defaultCallerSkip), + } + + for _, opt := range options { + opt(event) + } + + return event +} + +// Options is a function type to set optional parameters for the event +type Options func(*Event) + +// WithType sets the type of the event +func WithType(eventType string) Options { + return func(event *Event) { + event.Type = eventType + } +} + +// WithMessage sets the message of the event +func WithMessage(message string) Options { + return func(event *Event) { + event.Message = message + } +} + +// WithID sets the id of the event +func WithID(id string) Options { + return func(event *Event) { + event.ID = id + } +} + +// GetSpanValue returns the value to be set as a tag on a span for the given stacktrace events +func GetSpanValue(events ...*Event) any { + if !Enabled() { + return nil + } + + groupByCategory := make(map[string][]*Event, 3) + for _, event := range events { + if _, ok := groupByCategory[string(event.Category)]; !ok { + groupByCategory[string(event.Category)] = []*Event{event} + continue + } + groupByCategory[string(event.Category)] = append(groupByCategory[string(event.Category)], event) + } + + return internal.MetaStructValue{Value: groupByCategory} +} + +// AddToSpan adds the event to the given span's root span as a tag if stacktrace collection is enabled +func AddToSpan(span ddtrace.Span, events ...*Event) { + value := GetSpanValue(events...) + type rooter interface { + Root() ddtrace.Span + } + if lrs, ok := span.(rooter); ok { + span = lrs.Root() + } + span.SetTag(SpanKey, value) +} diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/stacktrace/event_msgp.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/stacktrace/event_msgp.go new file mode 100644 index 000000000..378c35223 --- /dev/null +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/stacktrace/event_msgp.go @@ -0,0 +1,333 @@ +package stacktrace + +// Code generated by github.com/tinylib/msgp DO NOT EDIT. + +import ( + "github.com/tinylib/msgp/msgp" +) + +// DecodeMsg implements msgp.Decodable +func (z *Event) DecodeMsg(dc *msgp.Reader) (err error) { + var field []byte + _ = field + var zb0001 uint32 + zb0001, err = dc.ReadMapHeader() + if err != nil { + err = msgp.WrapError(err) + return + } + for zb0001 > 0 { + zb0001-- + field, err = dc.ReadMapKeyPtr() + if err != nil { + err = msgp.WrapError(err) + return + } + switch msgp.UnsafeString(field) { + case "type": + z.Type, err = dc.ReadString() + if err != nil { + err = msgp.WrapError(err, "Type") + return + } + case "language": + z.Language, err = dc.ReadString() + if err != nil { + err = msgp.WrapError(err, "Language") + return + } + case "id": + z.ID, err = dc.ReadString() + if err != nil { + err = msgp.WrapError(err, "ID") + return + } + case "message": + z.Message, err = dc.ReadString() + if err != nil { + err = msgp.WrapError(err, "Message") + return + } + case "frames": + err = z.Frames.DecodeMsg(dc) + if err != nil { + err = msgp.WrapError(err, "Frames") + return + } + default: + err = dc.Skip() + if err != nil { + err = msgp.WrapError(err) + return + } + } + } + return +} + +// EncodeMsg implements msgp.Encodable +func (z *Event) EncodeMsg(en *msgp.Writer) (err error) { + // omitempty: check for empty values + zb0001Len := uint32(5) + var zb0001Mask uint8 /* 5 bits */ + _ = zb0001Mask + if z.Type == "" { + zb0001Len-- + zb0001Mask |= 0x1 + } + if z.Language == "" { + zb0001Len-- + zb0001Mask |= 0x2 + } + if z.ID == "" { + zb0001Len-- + zb0001Mask |= 0x4 + } + if z.Message == "" { + zb0001Len-- + zb0001Mask |= 0x8 + } + // variable map header, size zb0001Len + err = en.Append(0x80 | uint8(zb0001Len)) + if err != nil { + return + } + if zb0001Len == 0 { + return + } + if (zb0001Mask & 0x1) == 0 { // if not empty + // write "type" + err = en.Append(0xa4, 0x74, 0x79, 0x70, 0x65) + if err != nil { + return + } + err = en.WriteString(z.Type) + if err != nil { + err = msgp.WrapError(err, "Type") + return + } + } + if (zb0001Mask & 0x2) == 0 { // if not empty + // write "language" + err = en.Append(0xa8, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65) + if err != nil { + return + } + err = en.WriteString(z.Language) + if err != nil { + err = msgp.WrapError(err, "Language") + return + } + } + if (zb0001Mask & 0x4) == 0 { // if not empty + // write "id" + err = en.Append(0xa2, 0x69, 0x64) + if err != nil { + return + } + err = en.WriteString(z.ID) + if err != nil { + err = msgp.WrapError(err, "ID") + return + } + } + if (zb0001Mask & 0x8) == 0 { // if not empty + // write "message" + err = en.Append(0xa7, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65) + if err != nil { + return + } + err = en.WriteString(z.Message) + if err != nil { + err = msgp.WrapError(err, "Message") + return + } + } + // write "frames" + err = en.Append(0xa6, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73) + if err != nil { + return + } + err = z.Frames.EncodeMsg(en) + if err != nil { + err = msgp.WrapError(err, "Frames") + return + } + return +} + +// MarshalMsg implements msgp.Marshaler +func (z *Event) MarshalMsg(b []byte) (o []byte, err error) { + o = msgp.Require(b, z.Msgsize()) + // omitempty: check for empty values + zb0001Len := uint32(5) + var zb0001Mask uint8 /* 5 bits */ + _ = zb0001Mask + if z.Type == "" { + zb0001Len-- + zb0001Mask |= 0x1 + } + if z.Language == "" { + zb0001Len-- + zb0001Mask |= 0x2 + } + if z.ID == "" { + zb0001Len-- + zb0001Mask |= 0x4 + } + if z.Message == "" { + zb0001Len-- + zb0001Mask |= 0x8 + } + // variable map header, size zb0001Len + o = append(o, 0x80|uint8(zb0001Len)) + if zb0001Len == 0 { + return + } + if (zb0001Mask & 0x1) == 0 { // if not empty + // string "type" + o = append(o, 0xa4, 0x74, 0x79, 0x70, 0x65) + o = msgp.AppendString(o, z.Type) + } + if (zb0001Mask & 0x2) == 0 { // if not empty + // string "language" + o = append(o, 0xa8, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65) + o = msgp.AppendString(o, z.Language) + } + if (zb0001Mask & 0x4) == 0 { // if not empty + // string "id" + o = append(o, 0xa2, 0x69, 0x64) + o = msgp.AppendString(o, z.ID) + } + if (zb0001Mask & 0x8) == 0 { // if not empty + // string "message" + o = append(o, 0xa7, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65) + o = msgp.AppendString(o, z.Message) + } + // string "frames" + o = append(o, 0xa6, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73) + o, err = z.Frames.MarshalMsg(o) + if err != nil { + err = msgp.WrapError(err, "Frames") + return + } + return +} + +// UnmarshalMsg implements msgp.Unmarshaler +func (z *Event) UnmarshalMsg(bts []byte) (o []byte, err error) { + var field []byte + _ = field + var zb0001 uint32 + zb0001, bts, err = msgp.ReadMapHeaderBytes(bts) + if err != nil { + err = msgp.WrapError(err) + return + } + for zb0001 > 0 { + zb0001-- + field, bts, err = msgp.ReadMapKeyZC(bts) + if err != nil { + err = msgp.WrapError(err) + return + } + switch msgp.UnsafeString(field) { + case "type": + z.Type, bts, err = msgp.ReadStringBytes(bts) + if err != nil { + err = msgp.WrapError(err, "Type") + return + } + case "language": + z.Language, bts, err = msgp.ReadStringBytes(bts) + if err != nil { + err = msgp.WrapError(err, "Language") + return + } + case "id": + z.ID, bts, err = msgp.ReadStringBytes(bts) + if err != nil { + err = msgp.WrapError(err, "ID") + return + } + case "message": + z.Message, bts, err = msgp.ReadStringBytes(bts) + if err != nil { + err = msgp.WrapError(err, "Message") + return + } + case "frames": + bts, err = z.Frames.UnmarshalMsg(bts) + if err != nil { + err = msgp.WrapError(err, "Frames") + return + } + default: + bts, err = msgp.Skip(bts) + if err != nil { + err = msgp.WrapError(err) + return + } + } + } + o = bts + return +} + +// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message +func (z *Event) Msgsize() (s int) { + s = 1 + 5 + msgp.StringPrefixSize + len(z.Type) + 9 + msgp.StringPrefixSize + len(z.Language) + 3 + msgp.StringPrefixSize + len(z.ID) + 8 + msgp.StringPrefixSize + len(z.Message) + 7 + z.Frames.Msgsize() + return +} + +// DecodeMsg implements msgp.Decodable +func (z *EventCategory) DecodeMsg(dc *msgp.Reader) (err error) { + { + var zb0001 string + zb0001, err = dc.ReadString() + if err != nil { + err = msgp.WrapError(err) + return + } + (*z) = EventCategory(zb0001) + } + return +} + +// EncodeMsg implements msgp.Encodable +func (z EventCategory) EncodeMsg(en *msgp.Writer) (err error) { + err = en.WriteString(string(z)) + if err != nil { + err = msgp.WrapError(err) + return + } + return +} + +// MarshalMsg implements msgp.Marshaler +func (z EventCategory) MarshalMsg(b []byte) (o []byte, err error) { + o = msgp.Require(b, z.Msgsize()) + o = msgp.AppendString(o, string(z)) + return +} + +// UnmarshalMsg implements msgp.Unmarshaler +func (z *EventCategory) UnmarshalMsg(bts []byte) (o []byte, err error) { + { + var zb0001 string + zb0001, bts, err = msgp.ReadStringBytes(bts) + if err != nil { + err = msgp.WrapError(err) + return + } + (*z) = EventCategory(zb0001) + } + o = bts + return +} + +// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message +func (z EventCategory) Msgsize() (s int) { + s = msgp.StringPrefixSize + len(string(z)) + return +} diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/stacktrace/stacktrace.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/stacktrace/stacktrace.go new file mode 100644 index 000000000..060aebe12 --- /dev/null +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/stacktrace/stacktrace.go @@ -0,0 +1,253 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2016 Datadog, Inc. + +//go:generate msgp -o=stacktrace_msgp.go -tests=false + +package stacktrace + +import ( + "errors" + "os" + "regexp" + "runtime" + "strings" + + "gopkg.in/DataDog/dd-trace-go.v1/internal/log" + + "github.com/eapache/queue/v2" + "github.com/hashicorp/go-secure-stdlib/parseutil" +) + +var ( + enabled = true + defaultTopFrameDepth = 8 + defaultMaxDepth = 32 + + // internalPackagesPrefixes is the list of prefixes for internal packages that should be hidden in the stack trace + internalSymbolPrefixes = []string{ + "gopkg.in/DataDog/dd-trace-go.v1", + "github.com/DataDog/dd-trace-go", + "github.com/DataDog/go-libddwaf", + "github.com/DataDog/datadog-agent", + "github.com/DataDog/appsec-internal-go", + "github.com/datadog/orchestrion", + "github.com/DataDog/orchestrion", + } +) + +const ( + defaultCallerSkip = 4 + envStackTraceDepth = "DD_APPSEC_MAX_STACK_TRACE_DEPTH" + envStackTraceEnabled = "DD_APPSEC_STACK_TRACE_ENABLE" +) + +func init() { + if env := os.Getenv(envStackTraceEnabled); env != "" { + if e, err := parseutil.ParseBool(env); err == nil { + enabled = e + } else { + log.Error("Failed to parse %s env var as boolean: %v (using default value: %v)", envStackTraceEnabled, err, enabled) + } + } + + if env := os.Getenv(envStackTraceDepth); env != "" { + if !enabled { + log.Warn("Ignoring %s because stacktrace generation is disable", envStackTraceDepth) + return + } + + if depth, err := parseutil.SafeParseInt(env); err == nil { + defaultMaxDepth = depth + } else { + if depth <= 0 && err == nil { + err = errors.New("value is not a strictly positive integer") + } + log.Error("Failed to parse %s env var as a positive integer: %v (using default value: %v)", envStackTraceDepth, err, defaultMaxDepth) + } + } + + defaultTopFrameDepth = defaultMaxDepth / 4 +} + +// Enabled returns whether stacktrace should be collected +func Enabled() bool { + return enabled +} + +// StackTrace is intended to be sent over the span tag `_dd.stack`, the first frame is the current frame +type StackTrace []StackFrame + +// StackFrame represents a single frame in the stack trace +type StackFrame struct { + Index uint32 `msg:"id"` // Index of the frame (0 = top of the stack) + Text string `msg:"text,omitempty"` // Text version of the stackframe as a string + File string `msg:"file,omitempty"` // File name where the code line is + Line uint32 `msg:"line,omitempty"` // Line number in the context of the file where the code is + Column uint32 `msg:"column,omitempty"` // Column where the code ran is + Namespace string `msg:"namespace,omitempty"` // Namespace is the fully qualified name of the package where the code is + ClassName string `msg:"class_name,omitempty"` // ClassName is the fully qualified name of the class where the line of code is + Function string `msg:"function,omitempty"` // Function is the fully qualified name of the function where the line of code is +} + +type symbol struct { + Package string + Receiver string + Function string +} + +var symbolRegex = regexp.MustCompile(`^(([^(]+/)?([^(/.]+)?)(\.\(([^/)]+)\))?\.([^/()]+)$`) + +// parseSymbol parses a symbol name into its package, receiver and function +// ex: gopkg.in/DataDog/dd-trace-go.v1/internal/stacktrace.(*Event).NewException +// -> package: gopkg.in/DataDog/dd-trace-go.v1/internal/stacktrace +// -> receiver: *Event +// -> function: NewException +func parseSymbol(name string) symbol { + matches := symbolRegex.FindStringSubmatch(name) + if len(matches) != 7 { + log.Error("Failed to parse symbol for stacktrace: %s", name) + return symbol{ + Package: "", + Receiver: "", + Function: "", + } + } + + return symbol{ + Package: matches[1], + Receiver: matches[5], + Function: matches[6], + } +} + +// Capture create a new stack trace from the current call stack +func Capture() StackTrace { + return SkipAndCapture(defaultCallerSkip) +} + +// SkipAndCapture creates a new stack trace from the current call stack, skipping the first `skip` frames +func SkipAndCapture(skip int) StackTrace { + return skipAndCapture(skip, defaultMaxDepth, internalSymbolPrefixes) +} + +func skipAndCapture(skip int, maxDepth int, symbolSkip []string) StackTrace { + iter := iterator(skip, maxDepth, symbolSkip) + stack := make([]StackFrame, defaultMaxDepth) + nbStoredFrames := 0 + topFramesQueue := queue.New[StackFrame]() + + // We have to make sure we don't store more than maxDepth frames + // if there is more than maxDepth frames, we get X frames from the bottom of the stack and Y from the top + for frame, ok := iter.Next(); ok; frame, ok = iter.Next() { + // we reach the top frames: start to use the queue + if nbStoredFrames >= defaultMaxDepth-defaultTopFrameDepth { + topFramesQueue.Add(frame) + // queue is full, remove the oldest frame + if topFramesQueue.Length() > defaultTopFrameDepth { + topFramesQueue.Remove() + } + continue + } + + // Bottom frames: directly store them in the stack + stack[nbStoredFrames] = frame + nbStoredFrames++ + } + + // Stitch the top frames to the stack + for topFramesQueue.Length() > 0 { + stack[nbStoredFrames] = topFramesQueue.Remove() + nbStoredFrames++ + } + + return stack[:nbStoredFrames] +} + +// framesIterator is an iterator over the frames of a call stack +// It skips internal packages and caches the frames to avoid multiple calls to runtime.Callers +// It also skips the first `skip` frames +// It is not thread-safe +type framesIterator struct { + skipPrefixes []string + cache []uintptr + frames *queue.Queue[runtime.Frame] + cacheDepth int + cacheSize int + currDepth int +} + +func iterator(skip, cacheSize int, internalPrefixSkip []string) framesIterator { + return framesIterator{ + skipPrefixes: internalPrefixSkip, + cache: make([]uintptr, cacheSize), + frames: queue.New[runtime.Frame](), + cacheDepth: skip, + cacheSize: cacheSize, + currDepth: 0, + } +} + +// next returns the next runtime.Frame in the call stack, filling the cache if needed +func (it *framesIterator) next() (runtime.Frame, bool) { + if it.frames.Length() == 0 { + n := runtime.Callers(it.cacheDepth, it.cache) + if n == 0 { + return runtime.Frame{}, false + } + + frames := runtime.CallersFrames(it.cache[:n]) + for { + frame, more := frames.Next() + it.frames.Add(frame) + it.cacheDepth++ + if !more { + break + } + } + } + + it.currDepth++ + return it.frames.Remove(), true +} + +// Next returns the next StackFrame in the call stack, skipping internal packages and refurbishing the cache if needed +func (it *framesIterator) Next() (StackFrame, bool) { + for { + frame, ok := it.next() + if !ok { + return StackFrame{}, false + } + + if it.skipFrame(frame) { + continue + } + + parsedSymbol := parseSymbol(frame.Function) + return StackFrame{ + Index: uint32(it.currDepth - 1), + Text: "", + File: frame.File, + Line: uint32(frame.Line), + Column: 0, // No column given by the runtime + Namespace: parsedSymbol.Package, + ClassName: parsedSymbol.Receiver, + Function: parsedSymbol.Function, + }, true + } +} + +func (it *framesIterator) skipFrame(frame runtime.Frame) bool { + if frame.File == "" { // skip orchestrion generated code + return true + } + + for _, prefix := range it.skipPrefixes { + if strings.HasPrefix(frame.Function, prefix) { + return true + } + } + + return false +} diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/stacktrace/stacktrace_msgp.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/stacktrace/stacktrace_msgp.go new file mode 100644 index 000000000..d957c3102 --- /dev/null +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/stacktrace/stacktrace_msgp.go @@ -0,0 +1,475 @@ +package stacktrace + +// Code generated by github.com/tinylib/msgp DO NOT EDIT. + +import ( + "github.com/tinylib/msgp/msgp" +) + +// DecodeMsg implements msgp.Decodable +func (z *StackFrame) DecodeMsg(dc *msgp.Reader) (err error) { + var field []byte + _ = field + var zb0001 uint32 + zb0001, err = dc.ReadMapHeader() + if err != nil { + err = msgp.WrapError(err) + return + } + for zb0001 > 0 { + zb0001-- + field, err = dc.ReadMapKeyPtr() + if err != nil { + err = msgp.WrapError(err) + return + } + switch msgp.UnsafeString(field) { + case "id": + z.Index, err = dc.ReadUint32() + if err != nil { + err = msgp.WrapError(err, "Index") + return + } + case "text": + z.Text, err = dc.ReadString() + if err != nil { + err = msgp.WrapError(err, "Text") + return + } + case "file": + z.File, err = dc.ReadString() + if err != nil { + err = msgp.WrapError(err, "File") + return + } + case "line": + z.Line, err = dc.ReadUint32() + if err != nil { + err = msgp.WrapError(err, "Line") + return + } + case "column": + z.Column, err = dc.ReadUint32() + if err != nil { + err = msgp.WrapError(err, "Column") + return + } + case "namespace": + z.Namespace, err = dc.ReadString() + if err != nil { + err = msgp.WrapError(err, "Namespace") + return + } + case "class_name": + z.ClassName, err = dc.ReadString() + if err != nil { + err = msgp.WrapError(err, "ClassName") + return + } + case "function": + z.Function, err = dc.ReadString() + if err != nil { + err = msgp.WrapError(err, "Function") + return + } + default: + err = dc.Skip() + if err != nil { + err = msgp.WrapError(err) + return + } + } + } + return +} + +// EncodeMsg implements msgp.Encodable +func (z *StackFrame) EncodeMsg(en *msgp.Writer) (err error) { + // omitempty: check for empty values + zb0001Len := uint32(8) + var zb0001Mask uint8 /* 8 bits */ + _ = zb0001Mask + if z.Text == "" { + zb0001Len-- + zb0001Mask |= 0x2 + } + if z.File == "" { + zb0001Len-- + zb0001Mask |= 0x4 + } + if z.Line == 0 { + zb0001Len-- + zb0001Mask |= 0x8 + } + if z.Column == 0 { + zb0001Len-- + zb0001Mask |= 0x10 + } + if z.Namespace == "" { + zb0001Len-- + zb0001Mask |= 0x20 + } + if z.ClassName == "" { + zb0001Len-- + zb0001Mask |= 0x40 + } + if z.Function == "" { + zb0001Len-- + zb0001Mask |= 0x80 + } + // variable map header, size zb0001Len + err = en.Append(0x80 | uint8(zb0001Len)) + if err != nil { + return + } + if zb0001Len == 0 { + return + } + // write "id" + err = en.Append(0xa2, 0x69, 0x64) + if err != nil { + return + } + err = en.WriteUint32(z.Index) + if err != nil { + err = msgp.WrapError(err, "Index") + return + } + if (zb0001Mask & 0x2) == 0 { // if not empty + // write "text" + err = en.Append(0xa4, 0x74, 0x65, 0x78, 0x74) + if err != nil { + return + } + err = en.WriteString(z.Text) + if err != nil { + err = msgp.WrapError(err, "Text") + return + } + } + if (zb0001Mask & 0x4) == 0 { // if not empty + // write "file" + err = en.Append(0xa4, 0x66, 0x69, 0x6c, 0x65) + if err != nil { + return + } + err = en.WriteString(z.File) + if err != nil { + err = msgp.WrapError(err, "File") + return + } + } + if (zb0001Mask & 0x8) == 0 { // if not empty + // write "line" + err = en.Append(0xa4, 0x6c, 0x69, 0x6e, 0x65) + if err != nil { + return + } + err = en.WriteUint32(z.Line) + if err != nil { + err = msgp.WrapError(err, "Line") + return + } + } + if (zb0001Mask & 0x10) == 0 { // if not empty + // write "column" + err = en.Append(0xa6, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e) + if err != nil { + return + } + err = en.WriteUint32(z.Column) + if err != nil { + err = msgp.WrapError(err, "Column") + return + } + } + if (zb0001Mask & 0x20) == 0 { // if not empty + // write "namespace" + err = en.Append(0xa9, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65) + if err != nil { + return + } + err = en.WriteString(z.Namespace) + if err != nil { + err = msgp.WrapError(err, "Namespace") + return + } + } + if (zb0001Mask & 0x40) == 0 { // if not empty + // write "class_name" + err = en.Append(0xaa, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x5f, 0x6e, 0x61, 0x6d, 0x65) + if err != nil { + return + } + err = en.WriteString(z.ClassName) + if err != nil { + err = msgp.WrapError(err, "ClassName") + return + } + } + if (zb0001Mask & 0x80) == 0 { // if not empty + // write "function" + err = en.Append(0xa8, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e) + if err != nil { + return + } + err = en.WriteString(z.Function) + if err != nil { + err = msgp.WrapError(err, "Function") + return + } + } + return +} + +// MarshalMsg implements msgp.Marshaler +func (z *StackFrame) MarshalMsg(b []byte) (o []byte, err error) { + o = msgp.Require(b, z.Msgsize()) + // omitempty: check for empty values + zb0001Len := uint32(8) + var zb0001Mask uint8 /* 8 bits */ + _ = zb0001Mask + if z.Text == "" { + zb0001Len-- + zb0001Mask |= 0x2 + } + if z.File == "" { + zb0001Len-- + zb0001Mask |= 0x4 + } + if z.Line == 0 { + zb0001Len-- + zb0001Mask |= 0x8 + } + if z.Column == 0 { + zb0001Len-- + zb0001Mask |= 0x10 + } + if z.Namespace == "" { + zb0001Len-- + zb0001Mask |= 0x20 + } + if z.ClassName == "" { + zb0001Len-- + zb0001Mask |= 0x40 + } + if z.Function == "" { + zb0001Len-- + zb0001Mask |= 0x80 + } + // variable map header, size zb0001Len + o = append(o, 0x80|uint8(zb0001Len)) + if zb0001Len == 0 { + return + } + // string "id" + o = append(o, 0xa2, 0x69, 0x64) + o = msgp.AppendUint32(o, z.Index) + if (zb0001Mask & 0x2) == 0 { // if not empty + // string "text" + o = append(o, 0xa4, 0x74, 0x65, 0x78, 0x74) + o = msgp.AppendString(o, z.Text) + } + if (zb0001Mask & 0x4) == 0 { // if not empty + // string "file" + o = append(o, 0xa4, 0x66, 0x69, 0x6c, 0x65) + o = msgp.AppendString(o, z.File) + } + if (zb0001Mask & 0x8) == 0 { // if not empty + // string "line" + o = append(o, 0xa4, 0x6c, 0x69, 0x6e, 0x65) + o = msgp.AppendUint32(o, z.Line) + } + if (zb0001Mask & 0x10) == 0 { // if not empty + // string "column" + o = append(o, 0xa6, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e) + o = msgp.AppendUint32(o, z.Column) + } + if (zb0001Mask & 0x20) == 0 { // if not empty + // string "namespace" + o = append(o, 0xa9, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65) + o = msgp.AppendString(o, z.Namespace) + } + if (zb0001Mask & 0x40) == 0 { // if not empty + // string "class_name" + o = append(o, 0xaa, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x5f, 0x6e, 0x61, 0x6d, 0x65) + o = msgp.AppendString(o, z.ClassName) + } + if (zb0001Mask & 0x80) == 0 { // if not empty + // string "function" + o = append(o, 0xa8, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e) + o = msgp.AppendString(o, z.Function) + } + return +} + +// UnmarshalMsg implements msgp.Unmarshaler +func (z *StackFrame) UnmarshalMsg(bts []byte) (o []byte, err error) { + var field []byte + _ = field + var zb0001 uint32 + zb0001, bts, err = msgp.ReadMapHeaderBytes(bts) + if err != nil { + err = msgp.WrapError(err) + return + } + for zb0001 > 0 { + zb0001-- + field, bts, err = msgp.ReadMapKeyZC(bts) + if err != nil { + err = msgp.WrapError(err) + return + } + switch msgp.UnsafeString(field) { + case "id": + z.Index, bts, err = msgp.ReadUint32Bytes(bts) + if err != nil { + err = msgp.WrapError(err, "Index") + return + } + case "text": + z.Text, bts, err = msgp.ReadStringBytes(bts) + if err != nil { + err = msgp.WrapError(err, "Text") + return + } + case "file": + z.File, bts, err = msgp.ReadStringBytes(bts) + if err != nil { + err = msgp.WrapError(err, "File") + return + } + case "line": + z.Line, bts, err = msgp.ReadUint32Bytes(bts) + if err != nil { + err = msgp.WrapError(err, "Line") + return + } + case "column": + z.Column, bts, err = msgp.ReadUint32Bytes(bts) + if err != nil { + err = msgp.WrapError(err, "Column") + return + } + case "namespace": + z.Namespace, bts, err = msgp.ReadStringBytes(bts) + if err != nil { + err = msgp.WrapError(err, "Namespace") + return + } + case "class_name": + z.ClassName, bts, err = msgp.ReadStringBytes(bts) + if err != nil { + err = msgp.WrapError(err, "ClassName") + return + } + case "function": + z.Function, bts, err = msgp.ReadStringBytes(bts) + if err != nil { + err = msgp.WrapError(err, "Function") + return + } + default: + bts, err = msgp.Skip(bts) + if err != nil { + err = msgp.WrapError(err) + return + } + } + } + o = bts + return +} + +// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message +func (z *StackFrame) Msgsize() (s int) { + s = 1 + 3 + msgp.Uint32Size + 5 + msgp.StringPrefixSize + len(z.Text) + 5 + msgp.StringPrefixSize + len(z.File) + 5 + msgp.Uint32Size + 7 + msgp.Uint32Size + 10 + msgp.StringPrefixSize + len(z.Namespace) + 11 + msgp.StringPrefixSize + len(z.ClassName) + 9 + msgp.StringPrefixSize + len(z.Function) + return +} + +// DecodeMsg implements msgp.Decodable +func (z *StackTrace) DecodeMsg(dc *msgp.Reader) (err error) { + var zb0002 uint32 + zb0002, err = dc.ReadArrayHeader() + if err != nil { + err = msgp.WrapError(err) + return + } + if cap((*z)) >= int(zb0002) { + (*z) = (*z)[:zb0002] + } else { + (*z) = make(StackTrace, zb0002) + } + for zb0001 := range *z { + err = (*z)[zb0001].DecodeMsg(dc) + if err != nil { + err = msgp.WrapError(err, zb0001) + return + } + } + return +} + +// EncodeMsg implements msgp.Encodable +func (z StackTrace) EncodeMsg(en *msgp.Writer) (err error) { + err = en.WriteArrayHeader(uint32(len(z))) + if err != nil { + err = msgp.WrapError(err) + return + } + for zb0003 := range z { + err = z[zb0003].EncodeMsg(en) + if err != nil { + err = msgp.WrapError(err, zb0003) + return + } + } + return +} + +// MarshalMsg implements msgp.Marshaler +func (z StackTrace) MarshalMsg(b []byte) (o []byte, err error) { + o = msgp.Require(b, z.Msgsize()) + o = msgp.AppendArrayHeader(o, uint32(len(z))) + for zb0003 := range z { + o, err = z[zb0003].MarshalMsg(o) + if err != nil { + err = msgp.WrapError(err, zb0003) + return + } + } + return +} + +// UnmarshalMsg implements msgp.Unmarshaler +func (z *StackTrace) UnmarshalMsg(bts []byte) (o []byte, err error) { + var zb0002 uint32 + zb0002, bts, err = msgp.ReadArrayHeaderBytes(bts) + if err != nil { + err = msgp.WrapError(err) + return + } + if cap((*z)) >= int(zb0002) { + (*z) = (*z)[:zb0002] + } else { + (*z) = make(StackTrace, zb0002) + } + for zb0001 := range *z { + bts, err = (*z)[zb0001].UnmarshalMsg(bts) + if err != nil { + err = msgp.WrapError(err, zb0001) + return + } + } + o = bts + return +} + +// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message +func (z StackTrace) Msgsize() (s int) { + s = msgp.ArrayHeaderSize + for zb0003 := range z { + s += z[zb0003].Msgsize() + } + return +} diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/statsd.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/statsd.go index ab5ad8b7f..a901759f2 100644 --- a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/statsd.go +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/statsd.go @@ -6,13 +6,13 @@ package internal import ( - "sync" - "sync/atomic" "time" - "gopkg.in/DataDog/dd-trace-go.v1/internal/log" + "github.com/DataDog/datadog-go/v5/statsd" ) +const DefaultDogstatsdAddr = "localhost:8125" + type StatsdClient interface { Incr(name string, tags []string, rate float64) error Count(name string, value int64, tags []string, rate float64) error @@ -22,199 +22,14 @@ type StatsdClient interface { Close() error } -type Stat interface { - Name() string - Value() interface{} - Tags() []string - Rate() float64 -} - -// Gauge implements the Stat interface and contains a float64 value -type Gauge struct { - name string - value float64 - tags []string - rate float64 -} - -func NewGauge(name string, value float64, tags []string, rate float64) Gauge { - return Gauge{ - name: name, - value: value, - tags: tags, - rate: rate, +// NewStatsdClient returns a new statsd client with the provided address and globaltags +func NewStatsdClient(addr string, globalTags []string) (StatsdClient, error) { + if addr == "" { + addr = DefaultDogstatsdAddr } -} - -func (g Gauge) Name() string { - return g.name -} - -func (g Gauge) Value() interface{} { - return g.value -} - -func (g Gauge) Tags() []string { - return g.tags -} - -func (g Gauge) Rate() float64 { - return g.rate -} - -// Count implements the Stat interface and contains a int64 value -type Count struct { - name string - value int64 - tags []string - rate float64 -} - -func NewCount(name string, value int64, tags []string, rate float64) Count { - return Count{ - name: name, - value: value, - tags: tags, - rate: rate, + client, err := statsd.New(addr, statsd.WithMaxMessagesPerPayload(40), statsd.WithTags(globalTags)) + if err != nil { + return &statsd.NoOpClient{}, err } -} - -func (c Count) Name() string { - return c.name -} - -func (c Count) Value() interface{} { - return c.value -} - -func (c Count) Tags() []string { - return c.tags -} - -func (c Count) Rate() float64 { - return c.rate -} - -// Timing implements the Stat interface and contains a time.Duration value -type Timing struct { - name string - value time.Duration - tags []string - rate float64 -} - -func NewTiming(name string, value time.Duration, tags []string, rate float64) Timing { - return Timing{ - name: name, - value: value, - tags: tags, - rate: rate, - } -} - -func (t Timing) Name() string { - return t.name -} - -func (t Timing) Value() interface{} { - return t.value -} - -func (t Timing) Tags() []string { - return t.tags -} - -func (t Timing) Rate() float64 { - return t.rate -} - -// StatsCarrier collects stats on its contribStats channel and submits them through a statsd client -type StatsCarrier struct { - contribStats chan Stat - statsd StatsdClient - stop chan struct{} - wg sync.WaitGroup - stopped uint64 -} - -func NewStatsCarrier(statsd StatsdClient) *StatsCarrier { - return &StatsCarrier{ - contribStats: make(chan Stat), - statsd: statsd, - stopped: 1, - } -} - -// Start runs the StatsCarrier in a goroutine -// The caller of sc.Start() is resopnsible for calling sc.Stop() -func (sc *StatsCarrier) Start() { - if atomic.SwapUint64(&sc.stopped, 0) == 0 { - // already running - log.Warn("(*StatsCarrier).Start called more than once. This is likely a programming error.") - return - } - sc.stop = make(chan struct{}) - sc.wg.Add(1) - go func() { - defer sc.wg.Done() - sc.run() - }() -} - -func (sc *StatsCarrier) run() { - for { - select { - case stat := <-sc.contribStats: - sc.push(stat) - case <-sc.stop: - // make sure to flush any stats still in the channel - if len(sc.contribStats) > 0 { - sc.push(<-sc.contribStats) - } - return - } - } -} - -// Stop closes the StatsCarrier's stop channel -func (sc *StatsCarrier) Stop() { - if atomic.SwapUint64(&(sc.stopped), 1) > 0 { - return - } - close(sc.stop) - sc.wg.Wait() -} - -// push submits the stat of supported types (gauge, count or timing) via its statsd client -func (sc *StatsCarrier) push(s Stat) { - switch s.(type) { - case Gauge: - v, ok := s.Value().(float64) - if !ok { - log.Debug("Received gauge stat with incompatible value; looking for float64 value but got %T. Dropping stat %v.", s.Value(), s.Name()) - break - } - sc.statsd.Gauge(s.Name(), v, s.Tags(), s.Rate()) - case Count: - v, ok := s.Value().(int64) - if !ok { - log.Debug("Received count stat with incompatible value; looking for int64 value but got %T. Dropping stat %v.", s.Value(), s.Name()) - break - } - sc.statsd.Count(s.Name(), v, s.Tags(), s.Rate()) - case Timing: - v, ok := s.Value().(time.Duration) - if !ok { - log.Debug("Received timing stat with incompatible value; looking for time.Duration value but got %T. Dropping stat %v.", s.Value(), s.Name()) - break - } - sc.statsd.Timing(s.Name(), v, s.Tags(), s.Rate()) - default: - log.Debug("Stat submission failed: metric type for %v not supported", s.Name()) - } -} - -// Add pushes the Stat, s, onto the StatsCarrier's contribStats channel -func (sc *StatsCarrier) Add(s Stat) { - sc.contribStats <- s + return client, nil } diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/telemetry/client.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/telemetry/client.go index 269d78224..5cf962c7e 100644 --- a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/telemetry/client.go +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/telemetry/client.go @@ -30,6 +30,7 @@ import ( // Client buffers and sends telemetry messages to Datadog (possibly through an // agent). type Client interface { + RegisterAppConfig(name string, val interface{}, origin Origin) ProductChange(namespace Namespace, enabled bool, configuration []Configuration) ConfigChange(configuration []Configuration) Record(namespace Namespace, metric MetricKind, name string, value float64, tags []string, common bool) @@ -44,7 +45,7 @@ var ( GlobalClient Client globalClient sync.Mutex - // integrations tracks the the integrations enabled + // integrations tracks the integrations enabled contribPackages []Integration contrib sync.Mutex @@ -144,6 +145,10 @@ type client struct { // metrics are sent metrics map[Namespace]map[string]*metric newMetrics bool + + // Globally registered application configuration sent in the app-started request, along with the locally-defined + // configuration of the event. + globalAppConfig []Configuration } func log(msg string, args ...interface{}) { @@ -151,6 +156,16 @@ func log(msg string, args ...interface{}) { logger.Debug(fmt.Sprintf(LogPrefix+msg, args...)) } +// RegisterAppConfig allows to register a globally-defined application configuration. +// This configuration will be sent when the telemetry client is started and over related configuration updates. +func (c *client) RegisterAppConfig(name string, value interface{}, origin Origin) { + c.globalAppConfig = append(c.globalAppConfig, Configuration{ + Name: name, + Value: value, + Origin: origin, + }) +} + // start registers that the app has begun running with the app-started event. // Must be called with c.mu locked. // start also configures the telemetry client based on the following telemetry @@ -158,7 +173,7 @@ func log(msg string, args ...interface{}) { // DD_TELEMETRY_HEARTBEAT_INTERVAL, DD_INSTRUMENTATION_TELEMETRY_DEBUG, // and DD_TELEMETRY_DEPENDENCY_COLLECTION_ENABLED. // TODO: implement passing in error information about tracer start -func (c *client) start(configuration []Configuration, namespace Namespace) { +func (c *client) start(configuration []Configuration, namespace Namespace, flush bool) { if Disabled() { return } @@ -191,26 +206,44 @@ func (c *client) start(configuration []Configuration, namespace Namespace) { Enabled: namespace == NamespaceProfilers, }, } + + var cfg []Configuration + cfg = append(cfg, c.globalAppConfig...) + cfg = append(cfg, configuration...) + + // State whether the app has its Go dependencies available or not + deps, ok := debug.ReadBuildInfo() + if !ok { + deps = nil // because not guaranteed to be nil by the public doc when !ok + } + cfg = append(cfg, BoolConfig("dependencies_available", ok)) + collectDependenciesEnabled := collectDependencies() + cfg = append(cfg, BoolConfig("DD_TELEMETRY_DEPENDENCY_COLLECTION_ENABLED", collectDependenciesEnabled)) // TODO: report all the possible telemetry config option automatically + if !collectDependenciesEnabled { + deps = nil // to simplify the condition below to `deps != nil` + } + payload := &AppStarted{ - Configuration: configuration, + Configuration: cfg, Products: productInfo, } appStarted := c.newRequest(RequestTypeAppStarted) appStarted.Body.Payload = payload c.scheduleSubmit(appStarted) - if collectDependencies() { + if deps != nil { var depPayload Dependencies - if deps, ok := debug.ReadBuildInfo(); ok { - for _, dep := range deps.Deps { - depPayload.Dependencies = append(depPayload.Dependencies, - Dependency{ - Name: dep.Path, - Version: strings.TrimPrefix(dep.Version, "v"), - }, - ) - } + for _, dep := range deps.Deps { + depPayload.Dependencies = append(depPayload.Dependencies, + Dependency{ + Name: dep.Path, + Version: strings.TrimPrefix(dep.Version, "v"), + }, + ) } + // Send the telemetry request if and only if the dependencies are actually present in the binary. + // For instance, bazel doesn't include them out of the box (cf. https://github.com/bazelbuild/rules_go/issues/3090), + // which would result in an empty list of dependencies. dep := c.newRequest(RequestTypeDependenciesLoaded) dep.Body.Payload = depPayload c.scheduleSubmit(dep) @@ -222,7 +255,9 @@ func (c *client) start(configuration []Configuration, namespace Namespace) { c.scheduleSubmit(req) } - c.flush() + if flush { + c.flush() + } c.heartbeatInterval = heartbeatInterval() c.heartbeatT = time.AfterFunc(c.heartbeatInterval, c.backgroundHeartbeat) } diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/telemetry/message.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/telemetry/message.go index 334818759..27a72768d 100644 --- a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/telemetry/message.go +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/telemetry/message.go @@ -5,7 +5,11 @@ package telemetry -import "net/http" +import ( + "bytes" + "fmt" + "net/http" +) // Request captures all necessary information for a telemetry event submission type Request struct { @@ -132,13 +136,48 @@ type ConfigurationChange struct { RemoteConfig *RemoteConfig `json:"remote_config,omitempty"` } +type Origin int + +const ( + OriginDefault Origin = iota + OriginCode + OriginDDConfig + OriginEnvVar + OriginRemoteConfig +) + +func (o Origin) String() string { + switch o { + case OriginDefault: + return "default" + case OriginCode: + return "code" + case OriginDDConfig: + return "dd_config" + case OriginEnvVar: + return "env_var" + case OriginRemoteConfig: + return "remote_config" + default: + return fmt.Sprintf("unknown origin %d", o) + } +} + +func (o Origin) MarshalJSON() ([]byte, error) { + var b bytes.Buffer + b.WriteString(`"`) + b.WriteString(o.String()) + b.WriteString(`"`) + return b.Bytes(), nil +} + // Configuration is a library-specific configuration value // that should be initialized through StringConfig, IntConfig, FloatConfig, or BoolConfig type Configuration struct { Name string `json:"name"` Value interface{} `json:"value"` - // origin is the source of the config. It is one of {env_var, code, dd_config, remote_config} - Origin string `json:"origin"` + // origin is the source of the config. It is one of {default, env_var, code, dd_config, remote_config}. + Origin Origin `json:"origin"` Error Error `json:"error"` IsOverriden bool `json:"is_overridden"` } diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/telemetry/telemetry.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/telemetry/telemetry.go index c54e9d4c2..a9563b104 100644 --- a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/telemetry/telemetry.go +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/telemetry/telemetry.go @@ -28,10 +28,15 @@ func (c *client) ProductChange(namespace Namespace, enabled bool, configuration // Namespace is not enabled & telemetry isn't started, won't start it now. return } - c.start(configuration, namespace) + c.start(configuration, namespace, true) return } - c.configChange(configuration) + + var cfg []Configuration + cfg = append(cfg, c.globalAppConfig...) + cfg = append(cfg, configuration...) + c.configChange(cfg) + switch namespace { case NamespaceTracers, NamespaceProfilers, NamespaceAppSec: c.productChange(namespace, enabled) diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/telemetry/utils.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/telemetry/utils.go index 4a4a1696a..96c212b17 100644 --- a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/telemetry/utils.go +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/telemetry/utils.go @@ -35,7 +35,7 @@ func Check(t *testing.T, configuration []Configuration, key string, expected int for _, kv := range configuration { if kv.Name == key { if kv.Value != expected { - t.Errorf("configuration %s: wanted %v, got %v", key, expected, kv.Value) + t.Errorf("configuration %s: wanted '%v' type:%T, got '%v' type:%T", key, expected, expected, kv.Value, kv.Value) } return } @@ -85,6 +85,10 @@ func Sanitize(c Configuration) Configuration { sb.WriteString(fmt.Sprint(val[k])) } c.Value = sb.String() + default: + var sb strings.Builder + sb.WriteString(fmt.Sprint(val)) + c.Value = sb.String() } return c } diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/trace_context.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/trace_context.go index 47401fb6f..78620b692 100644 --- a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/trace_context.go +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/trace_context.go @@ -7,6 +7,8 @@ package internal import ( "context" + + "gopkg.in/DataDog/dd-trace-go.v1/internal/orchestrion" ) type executionTracedKey struct{} @@ -23,7 +25,7 @@ type executionTracedKey struct{} // general, APM instrumentation should prefer creating tasks around the // operation rather than after the fact, if possible. func WithExecutionTraced(ctx context.Context) context.Context { - return context.WithValue(ctx, executionTracedKey{}, true) + return orchestrion.CtxWithValue(ctx, executionTracedKey{}, true) } // WithExecutionNotTraced marks that the context is *not* covered by an @@ -31,17 +33,17 @@ func WithExecutionTraced(ctx context.Context) context.Context { // information from ctx) from being considered covered by a task, when an // integration may create its own child span with its own execution trace task. func WithExecutionNotTraced(ctx context.Context) context.Context { - if ctx.Value(executionTracedKey{}) == nil { + if orchestrion.WrapContext(ctx).Value(executionTracedKey{}) == nil { // Fast path: if it wasn't marked before, we don't need to wrap // the context return ctx } - return context.WithValue(ctx, executionTracedKey{}, false) + return orchestrion.CtxWithValue(ctx, executionTracedKey{}, false) } // IsExecutionTraced returns whether ctx is associated with an execution trace // task, as indicated via WithExecutionTraced func IsExecutionTraced(ctx context.Context) bool { - v := ctx.Value(executionTracedKey{}) + v := orchestrion.WrapContext(ctx).Value(executionTracedKey{}) return v != nil && v.(bool) } diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/utils.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/utils.go index 98ca6b050..bc9a12b4a 100644 --- a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/utils.go +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/utils.go @@ -10,6 +10,12 @@ import ( "sync/atomic" ) +// OtelTagsDelimeter is the separator between key-val pairs for OTEL env vars +const OtelTagsDelimeter = "=" + +// DDTagsDelimiter is the separator between key-val pairs for DD env vars +const DDTagsDelimiter = ":" + // LockMap uses an RWMutex to synchronize map access to allow for concurrent access. // This should not be used for cases with heavy write load and performance concerns. type LockMap struct { diff --git a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/version/version.go b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/version/version.go index b705717a1..30231dbbf 100644 --- a/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/version/version.go +++ b/vendor/gopkg.in/DataDog/dd-trace-go.v1/internal/version/version.go @@ -13,7 +13,7 @@ import ( // Tag specifies the current release tag. It needs to be manually // updated. A test checks that the value of Tag never points to a // git tag that is older than HEAD. -const Tag = "v1.62.0" +const Tag = "v1.69.1" // Dissected version number. Filled during init() var ( diff --git a/vendor/k8s.io/klog/v2/klog.go b/vendor/k8s.io/klog/v2/klog.go index 026be9e3b..47ec9466a 100644 --- a/vendor/k8s.io/klog/v2/klog.go +++ b/vendor/k8s.io/klog/v2/klog.go @@ -404,13 +404,6 @@ func (t *traceLocation) Set(value string) error { return nil } -// flushSyncWriter is the interface satisfied by logging destinations. -type flushSyncWriter interface { - Flush() error - Sync() error - io.Writer -} - var logging loggingT var commandLine flag.FlagSet @@ -486,7 +479,7 @@ type settings struct { // Access to all of the following fields must be protected via a mutex. // file holds writer for each of the log types. - file [severity.NumSeverity]flushSyncWriter + file [severity.NumSeverity]io.Writer // flushInterval is the interval for periodic flushing. If zero, // the global default will be used. flushInterval time.Duration @@ -831,32 +824,12 @@ func (l *loggingT) printS(err error, s severity.Severity, depth int, msg string, buffer.PutBuffer(b) } -// redirectBuffer is used to set an alternate destination for the logs -type redirectBuffer struct { - w io.Writer -} - -func (rb *redirectBuffer) Sync() error { - return nil -} - -func (rb *redirectBuffer) Flush() error { - return nil -} - -func (rb *redirectBuffer) Write(bytes []byte) (n int, err error) { - return rb.w.Write(bytes) -} - // SetOutput sets the output destination for all severities func SetOutput(w io.Writer) { logging.mu.Lock() defer logging.mu.Unlock() for s := severity.FatalLog; s >= severity.InfoLog; s-- { - rb := &redirectBuffer{ - w: w, - } - logging.file[s] = rb + logging.file[s] = w } } @@ -868,10 +841,7 @@ func SetOutputBySeverity(name string, w io.Writer) { if !ok { panic(fmt.Sprintf("SetOutputBySeverity(%q): unrecognized severity name", name)) } - rb := &redirectBuffer{ - w: w, - } - logging.file[sev] = rb + logging.file[sev] = w } // LogToStderr sets whether to log exclusively to stderr, bypassing outputs @@ -1011,7 +981,8 @@ func (l *loggingT) exit(err error) { logExitFunc(err) return } - l.flushAll() + needToSync := l.flushAll() + l.syncAll(needToSync) OsExit(2) } @@ -1028,10 +999,6 @@ type syncBuffer struct { maxbytes uint64 // The max number of bytes this syncBuffer.file can hold before cleaning up. } -func (sb *syncBuffer) Sync() error { - return sb.file.Sync() -} - // CalculateMaxSize returns the real max size in bytes after considering the default max size and the flag options. func CalculateMaxSize() uint64 { if logging.logFile != "" { @@ -1223,24 +1190,45 @@ func StartFlushDaemon(interval time.Duration) { // lockAndFlushAll is like flushAll but locks l.mu first. func (l *loggingT) lockAndFlushAll() { l.mu.Lock() - l.flushAll() + needToSync := l.flushAll() l.mu.Unlock() + // Some environments are slow when syncing and holding the lock might cause contention. + l.syncAll(needToSync) } -// flushAll flushes all the logs and attempts to "sync" their data to disk. +// flushAll flushes all the logs // l.mu is held. -func (l *loggingT) flushAll() { +// +// The result is the number of files which need to be synced and the pointers to them. +func (l *loggingT) flushAll() fileArray { + var needToSync fileArray + // Flush from fatal down, in case there's trouble flushing. for s := severity.FatalLog; s >= severity.InfoLog; s-- { file := l.file[s] - if file != nil { - _ = file.Flush() // ignore error - _ = file.Sync() // ignore error + if sb, ok := file.(*syncBuffer); ok && sb.file != nil { + _ = sb.Flush() // ignore error + needToSync.files[needToSync.num] = sb.file + needToSync.num++ } } if logging.loggerOptions.flush != nil { logging.loggerOptions.flush() } + return needToSync +} + +type fileArray struct { + num int + files [severity.NumSeverity]*os.File +} + +// syncAll attempts to "sync" their data to disk. +func (l *loggingT) syncAll(needToSync fileArray) { + // Flush from fatal down, in case there's trouble flushing. + for i := 0; i < needToSync.num; i++ { + _ = needToSync.files[i].Sync() // ignore error + } } // CopyStandardLogTo arranges for messages written to the Go "log" package's diff --git a/vendor/k8s.io/kube-openapi/pkg/common/common.go b/vendor/k8s.io/kube-openapi/pkg/common/common.go index 2e15e163c..e4ce843b0 100644 --- a/vendor/k8s.io/kube-openapi/pkg/common/common.go +++ b/vendor/k8s.io/kube-openapi/pkg/common/common.go @@ -164,6 +164,9 @@ type OpenAPIV3Config struct { // It is an optional function to customize model names. GetDefinitionName func(name string) (string, spec.Extensions) + // PostProcessSpec runs after the spec is ready to serve. It allows a final modification to the spec before serving. + PostProcessSpec func(*spec3.OpenAPI) (*spec3.OpenAPI, error) + // SecuritySchemes is list of all security schemes for OpenAPI service. SecuritySchemes spec3.SecuritySchemes diff --git a/vendor/k8s.io/kube-openapi/pkg/schemaconv/smd.go b/vendor/k8s.io/kube-openapi/pkg/schemaconv/smd.go index 799d866d5..9887d185b 100644 --- a/vendor/k8s.io/kube-openapi/pkg/schemaconv/smd.go +++ b/vendor/k8s.io/kube-openapi/pkg/schemaconv/smd.go @@ -214,9 +214,6 @@ func makeUnion(extensions map[string]interface{}) (schema.Union, error) { } } - if union.Discriminator != nil && len(union.Fields) == 0 { - return schema.Union{}, fmt.Errorf("discriminator set to %v, but no fields in union", *union.Discriminator) - } return union, nil } diff --git a/vendor/k8s.io/kubernetes/pkg/util/iptables/iptables.go b/vendor/k8s.io/kubernetes/pkg/util/iptables/iptables.go index 0d8135e32..c6c64e45f 100644 --- a/vendor/k8s.io/kubernetes/pkg/util/iptables/iptables.go +++ b/vendor/k8s.io/kubernetes/pkg/util/iptables/iptables.go @@ -1,3 +1,6 @@ +//go:build linux +// +build linux + /* Copyright 2014 The Kubernetes Authors. @@ -446,7 +449,6 @@ func iptablesRestoreCommand(protocol Protocol) string { return cmdIP6TablesRestore } return cmdIPTablesRestore - } func iptablesCommand(protocol Protocol) string { @@ -509,10 +511,10 @@ func (runner *runner) checkRuleWithoutCheck(table Table, chain Chain, args ...st tmpField = trimhex(tmpField) argsCopy = append(argsCopy, strings.Fields(tmpField)...) } - argset := sets.NewString(argsCopy...) + argset := sets.New(argsCopy...) for _, line := range strings.Split(string(out), "\n") { - var fields = strings.Fields(line) + fields := strings.Fields(line) // Check that this is a rule for the correct chain, and that it has // the correct number of argument (+2 for "-A ") @@ -528,7 +530,7 @@ func (runner *runner) checkRuleWithoutCheck(table Table, chain Chain, args ...st } // TODO: This misses reorderings e.g. "-x foo ! -y bar" will match "! -x foo -y bar" - if sets.NewString(fields...).IsSuperset(argset) { + if sets.New(fields...).IsSuperset(argset) { return true, nil } klog.V(5).InfoS("DBG: fields is not a superset of args", "fields", fields, "arguments", args) @@ -603,7 +605,6 @@ func (runner *runner) Monitor(canary Chain, tables []Table, reloadFunc func(), i } return true, nil }, stopCh) - if err != nil { // stopCh was closed for _, table := range tables { diff --git a/vendor/k8s.io/kubernetes/pkg/util/iptables/save_restore.go b/vendor/k8s.io/kubernetes/pkg/util/iptables/save_restore.go index b788beb91..d507adde7 100644 --- a/vendor/k8s.io/kubernetes/pkg/util/iptables/save_restore.go +++ b/vendor/k8s.io/kubernetes/pkg/util/iptables/save_restore.go @@ -1,3 +1,6 @@ +//go:build linux +// +build linux + /* Copyright 2014 The Kubernetes Authors. @@ -19,6 +22,8 @@ package iptables import ( "bytes" "fmt" + + "k8s.io/apimachinery/pkg/util/sets" ) // MakeChainLine return an iptables-save/restore formatted chain line given a Chain @@ -27,10 +32,10 @@ func MakeChainLine(chain Chain) string { } // GetChainsFromTable parses iptables-save data to find the chains that are defined. It -// assumes that save contains a single table's data, and returns a map with keys for every +// assumes that save contains a single table's data, and returns a set with keys for every // chain defined in that table. -func GetChainsFromTable(save []byte) map[Chain]struct{} { - chainsMap := make(map[Chain]struct{}) +func GetChainsFromTable(save []byte) sets.Set[Chain] { + chainsSet := sets.New[Chain]() for { i := bytes.Index(save, []byte("\n:")) @@ -40,13 +45,13 @@ func GetChainsFromTable(save []byte) map[Chain]struct{} { start := i + 2 save = save[start:] end := bytes.Index(save, []byte(" ")) - if i == -1 { + if end == -1 { // shouldn't happen, but... break } chain := Chain(save[:end]) - chainsMap[chain] = struct{}{} + chainsSet.Insert(chain) save = save[end:] } - return chainsMap + return chainsSet } diff --git a/vendor/k8s.io/utils/integer/integer.go b/vendor/k8s.io/utils/integer/integer.go index e4e740cad..e0811e834 100644 --- a/vendor/k8s.io/utils/integer/integer.go +++ b/vendor/k8s.io/utils/integer/integer.go @@ -16,6 +16,8 @@ limitations under the License. package integer +import "math" + // IntMax returns the maximum of the params func IntMax(a, b int) int { if b > a { @@ -65,9 +67,7 @@ func Int64Min(a, b int64) int64 { } // RoundToInt32 rounds floats into integer numbers. +// Deprecated: use math.Round() and a cast directly. func RoundToInt32(a float64) int32 { - if a < 0 { - return int32(a - 0.5) - } - return int32(a + 0.5) + return int32(math.Round(a)) } diff --git a/vendor/k8s.io/utils/net/multi_listen.go b/vendor/k8s.io/utils/net/multi_listen.go new file mode 100644 index 000000000..7cb7795be --- /dev/null +++ b/vendor/k8s.io/utils/net/multi_listen.go @@ -0,0 +1,195 @@ +/* +Copyright 2024 The Kubernetes 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. +*/ + +package net + +import ( + "context" + "fmt" + "net" + "sync" +) + +// connErrPair pairs conn and error which is returned by accept on sub-listeners. +type connErrPair struct { + conn net.Conn + err error +} + +// multiListener implements net.Listener +type multiListener struct { + listeners []net.Listener + wg sync.WaitGroup + + // connCh passes accepted connections, from child listeners to parent. + connCh chan connErrPair + // stopCh communicates from parent to child listeners. + stopCh chan struct{} +} + +// compile time check to ensure *multiListener implements net.Listener +var _ net.Listener = &multiListener{} + +// MultiListen returns net.Listener which can listen on and accept connections for +// the given network on multiple addresses. Internally it uses stdlib to create +// sub-listener and multiplexes connection requests using go-routines. +// The network must be "tcp", "tcp4" or "tcp6". +// It follows the semantics of net.Listen that primarily means: +// 1. If the host is an unspecified/zero IP address with "tcp" network, MultiListen +// listens on all available unicast and anycast IP addresses of the local system. +// 2. Use "tcp4" or "tcp6" to exclusively listen on IPv4 or IPv6 family, respectively. +// 3. The host can accept names (e.g, localhost) and it will create a listener for at +// most one of the host's IP. +func MultiListen(ctx context.Context, network string, addrs ...string) (net.Listener, error) { + var lc net.ListenConfig + return multiListen( + ctx, + network, + addrs, + func(ctx context.Context, network, address string) (net.Listener, error) { + return lc.Listen(ctx, network, address) + }) +} + +// multiListen implements MultiListen by consuming stdlib functions as dependency allowing +// mocking for unit-testing. +func multiListen( + ctx context.Context, + network string, + addrs []string, + listenFunc func(ctx context.Context, network, address string) (net.Listener, error), +) (net.Listener, error) { + if !(network == "tcp" || network == "tcp4" || network == "tcp6") { + return nil, fmt.Errorf("network %q not supported", network) + } + if len(addrs) == 0 { + return nil, fmt.Errorf("no address provided to listen on") + } + + ml := &multiListener{ + connCh: make(chan connErrPair), + stopCh: make(chan struct{}), + } + for _, addr := range addrs { + l, err := listenFunc(ctx, network, addr) + if err != nil { + // close all the sub-listeners and exit + _ = ml.Close() + return nil, err + } + ml.listeners = append(ml.listeners, l) + } + + for _, l := range ml.listeners { + ml.wg.Add(1) + go func(l net.Listener) { + defer ml.wg.Done() + for { + // Accept() is blocking, unless ml.Close() is called, in which + // case it will return immediately with an error. + conn, err := l.Accept() + // This assumes that ANY error from Accept() will terminate the + // sub-listener. We could maybe be more precise, but it + // doesn't seem necessary. + terminate := err != nil + + select { + case ml.connCh <- connErrPair{conn: conn, err: err}: + case <-ml.stopCh: + // In case we accepted a connection AND were stopped, and + // this select-case was chosen, just throw away the + // connection. This avoids potentially blocking on connCh + // or leaking a connection. + if conn != nil { + _ = conn.Close() + } + terminate = true + } + // Make sure we don't loop on Accept() returning an error and + // the select choosing the channel case. + if terminate { + return + } + } + }(l) + } + return ml, nil +} + +// Accept implements net.Listener. It waits for and returns a connection from +// any of the sub-listener. +func (ml *multiListener) Accept() (net.Conn, error) { + // wait for any sub-listener to enqueue an accepted connection + connErr, ok := <-ml.connCh + if !ok { + // The channel will be closed only when Close() is called on the + // multiListener. Closing of this channel implies that all + // sub-listeners are also closed, which causes a "use of closed + // network connection" error on their Accept() calls. We return the + // same error for multiListener.Accept() if multiListener.Close() + // has already been called. + return nil, fmt.Errorf("use of closed network connection") + } + return connErr.conn, connErr.err +} + +// Close implements net.Listener. It will close all sub-listeners and wait for +// the go-routines to exit. +func (ml *multiListener) Close() error { + // Make sure this can be called repeatedly without explosions. + select { + case <-ml.stopCh: + return fmt.Errorf("use of closed network connection") + default: + } + + // Tell all sub-listeners to stop. + close(ml.stopCh) + + // Closing the listeners causes Accept() to immediately return an error in + // the sub-listener go-routines. + for _, l := range ml.listeners { + _ = l.Close() + } + + // Wait for all the sub-listener go-routines to exit. + ml.wg.Wait() + close(ml.connCh) + + // Drain any already-queued connections. + for connErr := range ml.connCh { + if connErr.conn != nil { + _ = connErr.conn.Close() + } + } + return nil +} + +// Addr is an implementation of the net.Listener interface. It always returns +// the address of the first listener. Callers should use conn.LocalAddr() to +// obtain the actual local address of the sub-listener. +func (ml *multiListener) Addr() net.Addr { + return ml.listeners[0].Addr() +} + +// Addrs is like Addr, but returns the address for all registered listeners. +func (ml *multiListener) Addrs() []net.Addr { + var ret []net.Addr + for _, l := range ml.listeners { + ret = append(ret, l.Addr()) + } + return ret +} diff --git a/vendor/k8s.io/utils/trace/trace.go b/vendor/k8s.io/utils/trace/trace.go index 187eb5d8c..559aebb59 100644 --- a/vendor/k8s.io/utils/trace/trace.go +++ b/vendor/k8s.io/utils/trace/trace.go @@ -192,7 +192,7 @@ func (t *Trace) Log() { t.endTime = &endTime t.lock.Unlock() // an explicit logging request should dump all the steps out at the higher level - if t.parentTrace == nil { // We don't start logging until Log or LogIfLong is called on the root trace + if t.parentTrace == nil && klogV(2) { // We don't start logging until Log or LogIfLong is called on the root trace t.logTrace() } } diff --git a/vendor/modules.txt b/vendor/modules.txt index 69bb08b5d..8e18c93d1 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1,24 +1,30 @@ -# github.com/DataDog/appsec-internal-go v1.5.0 -## explicit; go 1.19 +# github.com/DataDog/appsec-internal-go v1.8.0 +## explicit; go 1.21 github.com/DataDog/appsec-internal-go/appsec +github.com/DataDog/appsec-internal-go/httpsec github.com/DataDog/appsec-internal-go/limiter github.com/DataDog/appsec-internal-go/log +github.com/DataDog/appsec-internal-go/netip # github.com/DataDog/datadog-agent/pkg/obfuscate v0.48.0 ## explicit; go 1.20 github.com/DataDog/datadog-agent/pkg/obfuscate -# github.com/DataDog/datadog-agent/pkg/remoteconfig/state v0.48.1 -## explicit; go 1.20 +# github.com/DataDog/datadog-agent/pkg/remoteconfig/state v0.57.0 +## explicit; go 1.22.0 github.com/DataDog/datadog-agent/pkg/remoteconfig/state # github.com/DataDog/datadog-go/v5 v5.3.0 ## explicit; go 1.13 github.com/DataDog/datadog-go/v5/statsd -# github.com/DataDog/go-libddwaf/v2 v2.3.2 -## explicit; go 1.20 -github.com/DataDog/go-libddwaf/v2 -github.com/DataDog/go-libddwaf/v2/internal/lib -github.com/DataDog/go-libddwaf/v2/internal/log -github.com/DataDog/go-libddwaf/v2/internal/noopfree -# github.com/DataDog/go-tuf v1.0.2-0.5.2 +# github.com/DataDog/go-libddwaf/v3 v3.4.0 +## explicit; go 1.21 +github.com/DataDog/go-libddwaf/v3 +github.com/DataDog/go-libddwaf/v3/errors +github.com/DataDog/go-libddwaf/v3/internal/bindings +github.com/DataDog/go-libddwaf/v3/internal/lib +github.com/DataDog/go-libddwaf/v3/internal/log +github.com/DataDog/go-libddwaf/v3/internal/support +github.com/DataDog/go-libddwaf/v3/internal/unsafe +github.com/DataDog/go-libddwaf/v3/timer +# github.com/DataDog/go-tuf v1.1.0-0.5.2 ## explicit; go 1.18 github.com/DataDog/go-tuf/client github.com/DataDog/go-tuf/data @@ -28,8 +34,8 @@ github.com/DataDog/go-tuf/pkg/keys github.com/DataDog/go-tuf/pkg/targets github.com/DataDog/go-tuf/util github.com/DataDog/go-tuf/verify -# github.com/DataDog/sketches-go v1.4.2 -## explicit; go 1.15 +# github.com/DataDog/sketches-go v1.4.5 +## explicit; go 1.18 github.com/DataDog/sketches-go/ddsketch github.com/DataDog/sketches-go/ddsketch/encoding github.com/DataDog/sketches-go/ddsketch/mapping @@ -52,15 +58,15 @@ github.com/beorn7/perks/quantile # github.com/blang/semver/v4 v4.0.0 ## explicit; go 1.14 github.com/blang/semver/v4 -# github.com/cespare/xxhash/v2 v2.2.0 +# github.com/cespare/xxhash/v2 v2.3.0 ## explicit; go 1.11 github.com/cespare/xxhash/v2 -# github.com/coredns/caddy v1.1.1 +# github.com/coredns/caddy v1.1.2-0.20241029205200-8de985351a98 ## explicit; go 1.13 github.com/coredns/caddy github.com/coredns/caddy/caddyfile -# github.com/coredns/coredns v1.11.3 -## explicit; go 1.21 +# github.com/coredns/coredns v1.12.0 +## explicit; go 1.22.7 github.com/coredns/coredns/core/dnsserver github.com/coredns/coredns/coremain github.com/coredns/coredns/pb @@ -137,6 +143,9 @@ github.com/dnstap/golang-dnstap # github.com/dustin/go-humanize v1.0.1 ## explicit; go 1.16 github.com/dustin/go-humanize +# github.com/eapache/queue/v2 v2.0.0-20230407133247-75960ed334e4 +## explicit; go 1.20 +github.com/eapache/queue/v2 # github.com/ebitengine/purego v0.6.0-alpha.5 ## explicit; go 1.18 github.com/ebitengine/purego @@ -156,10 +165,10 @@ github.com/farsightsec/golang-framestream # github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 ## explicit github.com/flynn/go-shlex -# github.com/fsnotify/fsnotify v1.6.0 -## explicit; go 1.16 +# github.com/fsnotify/fsnotify v1.7.0 +## explicit; go 1.17 github.com/fsnotify/fsnotify -# github.com/go-logr/logr v1.4.1 +# github.com/go-logr/logr v1.4.2 ## explicit; go 1.18 github.com/go-logr/logr # github.com/go-openapi/jsonpointer v0.19.6 @@ -169,12 +178,15 @@ github.com/go-openapi/jsonpointer ## explicit; go 1.13 github.com/go-openapi/jsonreference github.com/go-openapi/jsonreference/internal -# github.com/go-openapi/swag v0.22.3 +# github.com/go-openapi/swag v0.22.4 ## explicit; go 1.18 github.com/go-openapi/swag # github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 ## explicit; go 1.13 github.com/go-task/slim-sprig +# github.com/go-task/slim-sprig/v3 v3.0.0 +## explicit; go 1.20 +github.com/go-task/slim-sprig/v3 # github.com/gogo/protobuf v1.3.2 ## explicit; go 1.15 github.com/gogo/protobuf/gogoproto @@ -206,7 +218,7 @@ github.com/google/go-cmp/cmp/internal/value ## explicit; go 1.12 github.com/google/gofuzz github.com/google/gofuzz/bytesource -# github.com/google/pprof v0.0.0-20230817174616-7a8ec2ada47b +# github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af ## explicit; go 1.19 github.com/google/pprof/profile # github.com/google/uuid v1.6.0 @@ -215,12 +227,15 @@ github.com/google/uuid # github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645 ## explicit github.com/grpc-ecosystem/grpc-opentracing/go/otgrpc -# github.com/hashicorp/errwrap v1.1.0 +# github.com/hashicorp/go-secure-stdlib/parseutil v0.1.7 +## explicit; go 1.16 +github.com/hashicorp/go-secure-stdlib/parseutil +# github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 +## explicit; go 1.16 +github.com/hashicorp/go-secure-stdlib/strutil +# github.com/hashicorp/go-sockaddr v1.0.2 ## explicit -github.com/hashicorp/errwrap -# github.com/hashicorp/go-multierror v1.1.1 -## explicit; go 1.13 -github.com/hashicorp/go-multierror +github.com/hashicorp/go-sockaddr # github.com/imdario/mergo v0.3.12 ## explicit; go 1.13 github.com/imdario/mergo @@ -233,6 +248,15 @@ github.com/josharian/intern # github.com/json-iterator/go v1.1.12 ## explicit; go 1.12 github.com/json-iterator/go +# github.com/klauspost/compress v1.17.9 +## explicit; go 1.20 +github.com/klauspost/compress +github.com/klauspost/compress/fse +github.com/klauspost/compress/huff0 +github.com/klauspost/compress/internal/cpuinfo +github.com/klauspost/compress/internal/snapref +github.com/klauspost/compress/zstd +github.com/klauspost/compress/zstd/internal/xxhash # github.com/mailru/easyjson v0.7.7 ## explicit; go 1.12 github.com/mailru/easyjson/buffer @@ -241,9 +265,12 @@ github.com/mailru/easyjson/jwriter # github.com/matttproud/golang_protobuf_extensions v1.0.4 ## explicit; go 1.9 github.com/matttproud/golang_protobuf_extensions/pbutil -# github.com/miekg/dns v1.1.58 +# github.com/miekg/dns v1.1.62 ## explicit; go 1.19 github.com/miekg/dns +# github.com/mitchellh/mapstructure v1.5.0 +## explicit; go 1.14 +github.com/mitchellh/mapstructure # github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd ## explicit github.com/modern-go/concurrent @@ -290,8 +317,8 @@ github.com/onsi/ginkgo/reporters/stenographer github.com/onsi/ginkgo/reporters/stenographer/support/go-colorable github.com/onsi/ginkgo/reporters/stenographer/support/go-isatty github.com/onsi/ginkgo/types -# github.com/onsi/ginkgo/v2 v2.13.0 -## explicit; go 1.18 +# github.com/onsi/ginkgo/v2 v2.19.0 +## explicit; go 1.20 github.com/onsi/ginkgo/v2/config github.com/onsi/ginkgo/v2/formatter github.com/onsi/ginkgo/v2/ginkgo @@ -308,8 +335,8 @@ github.com/onsi/ginkgo/v2/internal/interrupt_handler github.com/onsi/ginkgo/v2/internal/parallel_support github.com/onsi/ginkgo/v2/reporters github.com/onsi/ginkgo/v2/types -# github.com/onsi/gomega v1.27.10 -## explicit; go 1.18 +# github.com/onsi/gomega v1.33.1 +## explicit; go 1.20 github.com/onsi/gomega github.com/onsi/gomega/format github.com/onsi/gomega/internal @@ -331,8 +358,8 @@ github.com/opentracing/opentracing-go/log # github.com/openzipkin-contrib/zipkin-go-opentracing v0.5.0 ## explicit; go 1.18 github.com/openzipkin-contrib/zipkin-go-opentracing -# github.com/openzipkin/zipkin-go v0.4.2 -## explicit; go 1.18 +# github.com/openzipkin/zipkin-go v0.4.3 +## explicit; go 1.20 github.com/openzipkin/zipkin-go github.com/openzipkin/zipkin-go/idgenerator github.com/openzipkin/zipkin-go/model @@ -345,8 +372,8 @@ github.com/openzipkin/zipkin-go/reporter/http github.com/outcaste-io/ristretto github.com/outcaste-io/ristretto/z github.com/outcaste-io/ristretto/z/simd -# github.com/philhofer/fwd v1.1.2 -## explicit; go 1.15 +# github.com/philhofer/fwd v1.1.3-0.20240612014219-fbbf4953d986 +## explicit; go 1.20 github.com/philhofer/fwd # github.com/pkg/errors v0.9.1 ## explicit @@ -354,34 +381,34 @@ github.com/pkg/errors # github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 ## explicit github.com/pmezard/go-difflib/difflib -# github.com/prometheus/client_golang v1.19.0 +# github.com/prometheus/client_golang v1.20.5 ## explicit; go 1.20 +github.com/prometheus/client_golang/internal/github.com/golang/gddo/httputil +github.com/prometheus/client_golang/internal/github.com/golang/gddo/httputil/header github.com/prometheus/client_golang/prometheus github.com/prometheus/client_golang/prometheus/collectors github.com/prometheus/client_golang/prometheus/internal github.com/prometheus/client_golang/prometheus/promauto github.com/prometheus/client_golang/prometheus/promhttp -# github.com/prometheus/client_model v0.6.0 +# github.com/prometheus/client_model v0.6.1 ## explicit; go 1.19 github.com/prometheus/client_model/go -# github.com/prometheus/common v0.53.0 -## explicit; go 1.20 +# github.com/prometheus/common v0.60.1 +## explicit; go 1.21 github.com/prometheus/common/expfmt -github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg github.com/prometheus/common/model -# github.com/prometheus/procfs v0.12.0 -## explicit; go 1.19 +# github.com/prometheus/procfs v0.15.1 +## explicit; go 1.20 github.com/prometheus/procfs github.com/prometheus/procfs/internal/fs github.com/prometheus/procfs/internal/util -# github.com/quic-go/quic-go v0.42.0 -## explicit; go 1.21 +# github.com/quic-go/quic-go v0.48.1 +## explicit; go 1.22 github.com/quic-go/quic-go github.com/quic-go/quic-go/internal/ackhandler github.com/quic-go/quic-go/internal/congestion github.com/quic-go/quic-go/internal/flowcontrol github.com/quic-go/quic-go/internal/handshake -github.com/quic-go/quic-go/internal/logutils github.com/quic-go/quic-go/internal/protocol github.com/quic-go/quic-go/internal/qerr github.com/quic-go/quic-go/internal/qtls @@ -391,49 +418,52 @@ github.com/quic-go/quic-go/internal/utils/ringbuffer github.com/quic-go/quic-go/internal/wire github.com/quic-go/quic-go/logging github.com/quic-go/quic-go/quicvarint +# github.com/ryanuber/go-glob v1.0.0 +## explicit +github.com/ryanuber/go-glob # github.com/secure-systems-lab/go-securesystemslib v0.7.0 ## explicit; go 1.20 github.com/secure-systems-lab/go-securesystemslib/cjson -# github.com/spf13/cobra v1.7.0 +# github.com/spf13/cobra v1.8.1 ## explicit; go 1.15 github.com/spf13/cobra # github.com/spf13/pflag v1.0.5 ## explicit; go 1.12 github.com/spf13/pflag -# github.com/stretchr/testify v1.8.4 -## explicit; go 1.20 +# github.com/stretchr/testify v1.9.0 +## explicit; go 1.17 github.com/stretchr/testify/assert github.com/stretchr/testify/require -# github.com/tinylib/msgp v1.1.8 -## explicit; go 1.15 +# github.com/tinylib/msgp v1.2.1 +## explicit; go 1.20 github.com/tinylib/msgp/msgp -# github.com/vishvananda/netlink v1.1.0 +# github.com/vishvananda/netlink v1.3.0 ## explicit; go 1.12 github.com/vishvananda/netlink github.com/vishvananda/netlink/nl # github.com/vishvananda/netns v0.0.4 ## explicit; go 1.17 github.com/vishvananda/netns -# go.etcd.io/etcd/api/v3 v3.5.12 -## explicit; go 1.20 +# go.etcd.io/etcd/api/v3 v3.5.17 +## explicit; go 1.22 go.etcd.io/etcd/api/v3/authpb go.etcd.io/etcd/api/v3/etcdserverpb go.etcd.io/etcd/api/v3/membershippb go.etcd.io/etcd/api/v3/mvccpb go.etcd.io/etcd/api/v3/v3rpc/rpctypes go.etcd.io/etcd/api/v3/version -# go.etcd.io/etcd/client/pkg/v3 v3.5.12 -## explicit; go 1.20 +# go.etcd.io/etcd/client/pkg/v3 v3.5.17 +## explicit; go 1.22 go.etcd.io/etcd/client/pkg/v3/logutil go.etcd.io/etcd/client/pkg/v3/pathutil go.etcd.io/etcd/client/pkg/v3/srv go.etcd.io/etcd/client/pkg/v3/systemd go.etcd.io/etcd/client/pkg/v3/types -# go.etcd.io/etcd/client/v2 v2.305.9 -## explicit; go 1.19 +# go.etcd.io/etcd/client/v2 v2.305.17 +## explicit; go 1.22 go.etcd.io/etcd/client/v2 -# go.etcd.io/etcd/client/v3 v3.5.12 -## explicit; go 1.20 +# go.etcd.io/etcd/client/v3 v3.5.17 +## explicit; go 1.22 go.etcd.io/etcd/client/v3 go.etcd.io/etcd/client/v3/credentials go.etcd.io/etcd/client/v3/internal/endpoint @@ -441,6 +471,11 @@ go.etcd.io/etcd/client/v3/internal/resolver # go.uber.org/atomic v1.11.0 ## explicit; go 1.18 go.uber.org/atomic +# go.uber.org/automaxprocs v1.6.0 +## explicit; go 1.20 +go.uber.org/automaxprocs/internal/cgroups +go.uber.org/automaxprocs/internal/runtime +go.uber.org/automaxprocs/maxprocs # go.uber.org/mock v0.4.0 ## explicit; go 1.20 go.uber.org/mock/mockgen @@ -448,32 +483,35 @@ go.uber.org/mock/mockgen/model # go.uber.org/multierr v1.11.0 ## explicit; go 1.19 go.uber.org/multierr -# go.uber.org/zap v1.19.0 -## explicit; go 1.13 +# go.uber.org/zap v1.26.0 +## explicit; go 1.19 go.uber.org/zap go.uber.org/zap/buffer +go.uber.org/zap/internal go.uber.org/zap/internal/bufferpool go.uber.org/zap/internal/color go.uber.org/zap/internal/exit +go.uber.org/zap/internal/pool +go.uber.org/zap/internal/stacktrace go.uber.org/zap/zapcore go.uber.org/zap/zapgrpc -# golang.org/x/crypto v0.22.0 -## explicit; go 1.18 +# golang.org/x/crypto v0.29.0 +## explicit; go 1.20 golang.org/x/crypto/chacha20 golang.org/x/crypto/chacha20poly1305 golang.org/x/crypto/hkdf golang.org/x/crypto/internal/alias golang.org/x/crypto/internal/poly1305 -# golang.org/x/exp v0.0.0-20230321023759-10a507213a29 -## explicit; go 1.18 +# golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 +## explicit; go 1.20 golang.org/x/exp/rand -# golang.org/x/mod v0.14.0 +# golang.org/x/mod v0.18.0 ## explicit; go 1.18 golang.org/x/mod/internal/lazyregexp golang.org/x/mod/modfile golang.org/x/mod/module golang.org/x/mod/semver -# golang.org/x/net v0.23.0 +# golang.org/x/net v0.31.0 ## explicit; go 1.18 golang.org/x/net/bpf golang.org/x/net/context @@ -490,21 +528,24 @@ golang.org/x/net/internal/timeseries golang.org/x/net/ipv4 golang.org/x/net/ipv6 golang.org/x/net/trace -# golang.org/x/oauth2 v0.18.0 +# golang.org/x/oauth2 v0.24.0 ## explicit; go 1.18 golang.org/x/oauth2 golang.org/x/oauth2/internal -# golang.org/x/sys v0.19.0 +# golang.org/x/sync v0.9.0 +## explicit; go 1.18 +golang.org/x/sync/errgroup +# golang.org/x/sys v0.27.0 ## explicit; go 1.18 golang.org/x/sys/cpu golang.org/x/sys/plan9 golang.org/x/sys/unix golang.org/x/sys/windows golang.org/x/sys/windows/registry -# golang.org/x/term v0.19.0 +# golang.org/x/term v0.26.0 ## explicit; go 1.18 golang.org/x/term -# golang.org/x/text v0.14.0 +# golang.org/x/text v0.20.0 ## explicit; go 1.18 golang.org/x/text/encoding golang.org/x/text/encoding/charmap @@ -526,12 +567,13 @@ golang.org/x/text/secure/bidirule golang.org/x/text/transform golang.org/x/text/unicode/bidi golang.org/x/text/unicode/norm -# golang.org/x/time v0.5.0 +# golang.org/x/time v0.8.0 ## explicit; go 1.18 golang.org/x/time/rate -# golang.org/x/tools v0.17.0 -## explicit; go 1.18 +# golang.org/x/tools v0.22.0 +## explicit; go 1.19 golang.org/x/tools/cmd/stringer +golang.org/x/tools/cover golang.org/x/tools/go/ast/astutil golang.org/x/tools/go/ast/inspector golang.org/x/tools/go/gcexportdata @@ -539,49 +581,43 @@ golang.org/x/tools/go/internal/packagesdriver golang.org/x/tools/go/packages golang.org/x/tools/go/types/objectpath golang.org/x/tools/imports +golang.org/x/tools/internal/aliases golang.org/x/tools/internal/event golang.org/x/tools/internal/event/core golang.org/x/tools/internal/event/keys golang.org/x/tools/internal/event/label -golang.org/x/tools/internal/event/tag golang.org/x/tools/internal/gcimporter golang.org/x/tools/internal/gocommand golang.org/x/tools/internal/gopathwalk golang.org/x/tools/internal/imports golang.org/x/tools/internal/packagesinternal golang.org/x/tools/internal/pkgbits +golang.org/x/tools/internal/stdlib golang.org/x/tools/internal/tokeninternal -golang.org/x/tools/internal/typeparams golang.org/x/tools/internal/typesinternal golang.org/x/tools/internal/versions -# golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 -## explicit; go 1.17 +# golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 +## explicit; go 1.18 golang.org/x/xerrors golang.org/x/xerrors/internal -# google.golang.org/appengine v1.6.8 -## explicit; go 1.11 -google.golang.org/appengine/internal -google.golang.org/appengine/internal/base -google.golang.org/appengine/internal/datastore -google.golang.org/appengine/internal/log -google.golang.org/appengine/internal/remote_api -google.golang.org/appengine/internal/urlfetch -google.golang.org/appengine/urlfetch -# google.golang.org/genproto/googleapis/api v0.0.0-20240311132316-a219d84964c2 -## explicit; go 1.19 +# google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28 +## explicit; go 1.21 google.golang.org/genproto/googleapis/api google.golang.org/genproto/googleapis/api/annotations -# google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 -## explicit; go 1.19 +# google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 +## explicit; go 1.21 google.golang.org/genproto/googleapis/rpc/status -# google.golang.org/grpc v1.63.2 -## explicit; go 1.19 +# google.golang.org/grpc v1.68.0 +## explicit; go 1.22.7 google.golang.org/grpc google.golang.org/grpc/attributes google.golang.org/grpc/backoff google.golang.org/grpc/balancer google.golang.org/grpc/balancer/base google.golang.org/grpc/balancer/grpclb/state +google.golang.org/grpc/balancer/pickfirst +google.golang.org/grpc/balancer/pickfirst/internal +google.golang.org/grpc/balancer/pickfirst/pickfirstleaf google.golang.org/grpc/balancer/roundrobin google.golang.org/grpc/binarylog/grpc_binarylog_v1 google.golang.org/grpc/channelz @@ -591,7 +627,9 @@ google.golang.org/grpc/credentials google.golang.org/grpc/credentials/insecure google.golang.org/grpc/encoding google.golang.org/grpc/encoding/proto +google.golang.org/grpc/experimental/stats google.golang.org/grpc/grpclog +google.golang.org/grpc/grpclog/internal google.golang.org/grpc/internal google.golang.org/grpc/internal/backoff google.golang.org/grpc/internal/balancer/gracefulswitch @@ -602,7 +640,6 @@ google.golang.org/grpc/internal/channelz google.golang.org/grpc/internal/credentials google.golang.org/grpc/internal/envconfig google.golang.org/grpc/internal/grpclog -google.golang.org/grpc/internal/grpcrand google.golang.org/grpc/internal/grpcsync google.golang.org/grpc/internal/grpcutil google.golang.org/grpc/internal/idle @@ -614,11 +651,13 @@ google.golang.org/grpc/internal/resolver/dns/internal google.golang.org/grpc/internal/resolver/passthrough google.golang.org/grpc/internal/resolver/unix google.golang.org/grpc/internal/serviceconfig +google.golang.org/grpc/internal/stats google.golang.org/grpc/internal/status google.golang.org/grpc/internal/syscall google.golang.org/grpc/internal/transport google.golang.org/grpc/internal/transport/networktype google.golang.org/grpc/keepalive +google.golang.org/grpc/mem google.golang.org/grpc/metadata google.golang.org/grpc/peer google.golang.org/grpc/resolver @@ -628,8 +667,8 @@ google.golang.org/grpc/serviceconfig google.golang.org/grpc/stats google.golang.org/grpc/status google.golang.org/grpc/tap -# google.golang.org/protobuf v1.33.0 -## explicit; go 1.17 +# google.golang.org/protobuf v1.35.2 +## explicit; go 1.21 google.golang.org/protobuf/encoding/protodelim google.golang.org/protobuf/encoding/protojson google.golang.org/protobuf/encoding/prototext @@ -638,6 +677,7 @@ google.golang.org/protobuf/internal/descfmt google.golang.org/protobuf/internal/descopts google.golang.org/protobuf/internal/detrand google.golang.org/protobuf/internal/editiondefaults +google.golang.org/protobuf/internal/editionssupport google.golang.org/protobuf/internal/encoding/defval google.golang.org/protobuf/internal/encoding/json google.golang.org/protobuf/internal/encoding/messageset @@ -666,8 +706,9 @@ google.golang.org/protobuf/types/gofeaturespb google.golang.org/protobuf/types/known/anypb google.golang.org/protobuf/types/known/durationpb google.golang.org/protobuf/types/known/timestamppb -# gopkg.in/DataDog/dd-trace-go.v1 v1.62.0 -## explicit; go 1.19 +# gopkg.in/DataDog/dd-trace-go.v1 v1.69.1 +## explicit; go 1.22.0 +gopkg.in/DataDog/dd-trace-go.v1/appsec/events gopkg.in/DataDog/dd-trace-go.v1/datastreams/options gopkg.in/DataDog/dd-trace-go.v1/ddtrace gopkg.in/DataDog/dd-trace-go.v1/ddtrace/ext @@ -678,8 +719,27 @@ gopkg.in/DataDog/dd-trace-go.v1/internal gopkg.in/DataDog/dd-trace-go.v1/internal/appsec gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/config gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/dyngo -gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/sharedsec +gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/graphqlsec +gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/grpcsec +gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/httpsec +gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/ossec +gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/sqlsec +gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/trace +gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/usersec +gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/waf +gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/waf/actions +gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/emitter/waf/addresses gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener +gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener/graphqlsec +gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener/grpcsec +gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener/httpsec +gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener/ossec +gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener/sqlsec +gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener/trace +gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener/usersec +gopkg.in/DataDog/dd-trace-go.v1/internal/appsec/listener/waf +gopkg.in/DataDog/dd-trace-go.v1/internal/civisibility/constants +gopkg.in/DataDog/dd-trace-go.v1/internal/civisibility/utils gopkg.in/DataDog/dd-trace-go.v1/internal/datastreams gopkg.in/DataDog/dd-trace-go.v1/internal/globalconfig gopkg.in/DataDog/dd-trace-go.v1/internal/hostname @@ -693,9 +753,11 @@ gopkg.in/DataDog/dd-trace-go.v1/internal/hostname/validate gopkg.in/DataDog/dd-trace-go.v1/internal/log gopkg.in/DataDog/dd-trace-go.v1/internal/namingschema gopkg.in/DataDog/dd-trace-go.v1/internal/normalizer +gopkg.in/DataDog/dd-trace-go.v1/internal/orchestrion gopkg.in/DataDog/dd-trace-go.v1/internal/osinfo gopkg.in/DataDog/dd-trace-go.v1/internal/remoteconfig gopkg.in/DataDog/dd-trace-go.v1/internal/samplernames +gopkg.in/DataDog/dd-trace-go.v1/internal/stacktrace gopkg.in/DataDog/dd-trace-go.v1/internal/telemetry gopkg.in/DataDog/dd-trace-go.v1/internal/traceprof gopkg.in/DataDog/dd-trace-go.v1/internal/version @@ -711,7 +773,7 @@ gopkg.in/yaml.v2 # gopkg.in/yaml.v3 v3.0.1 ## explicit gopkg.in/yaml.v3 -# k8s.io/api v0.29.3 => k8s.io/api v0.28.14 +# k8s.io/api v0.31.2 => k8s.io/api v0.28.14 ## explicit; go 1.20 k8s.io/api/admissionregistration/v1 k8s.io/api/admissionregistration/v1alpha1 @@ -765,7 +827,7 @@ k8s.io/api/scheduling/v1beta1 k8s.io/api/storage/v1 k8s.io/api/storage/v1alpha1 k8s.io/api/storage/v1beta1 -# k8s.io/apimachinery v0.29.3 => k8s.io/apimachinery v0.28.14 +# k8s.io/apimachinery v0.31.2 => k8s.io/apimachinery v0.28.14 ## explicit; go 1.20 k8s.io/apimachinery/pkg/api/equality k8s.io/apimachinery/pkg/api/errors @@ -815,7 +877,7 @@ k8s.io/apimachinery/pkg/version k8s.io/apimachinery/pkg/watch k8s.io/apimachinery/third_party/forked/golang/json k8s.io/apimachinery/third_party/forked/golang/reflect -# k8s.io/client-go v0.29.3 => k8s.io/client-go v0.28.14 +# k8s.io/client-go v0.31.2 => k8s.io/client-go v0.28.14 ## explicit; go 1.20 k8s.io/client-go/applyconfigurations/admissionregistration/v1 k8s.io/client-go/applyconfigurations/admissionregistration/v1alpha1 @@ -1015,7 +1077,7 @@ k8s.io/component-base/metrics/prometheus/restclient k8s.io/component-base/metrics/prometheus/version k8s.io/component-base/metrics/prometheusextension k8s.io/component-base/version -# k8s.io/klog/v2 v2.120.1 +# k8s.io/klog/v2 v2.130.1 ## explicit; go 1.18 k8s.io/klog/v2 k8s.io/klog/v2/internal/buffer @@ -1024,8 +1086,8 @@ k8s.io/klog/v2/internal/dbg k8s.io/klog/v2/internal/serialize k8s.io/klog/v2/internal/severity k8s.io/klog/v2/internal/sloghandler -# k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 -## explicit; go 1.19 +# k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 +## explicit; go 1.20 k8s.io/kube-openapi/pkg/cached k8s.io/kube-openapi/pkg/common k8s.io/kube-openapi/pkg/handler3 @@ -1035,10 +1097,10 @@ k8s.io/kube-openapi/pkg/schemaconv k8s.io/kube-openapi/pkg/spec3 k8s.io/kube-openapi/pkg/util/proto k8s.io/kube-openapi/pkg/validation/spec -# k8s.io/kubernetes v1.28.14 -## explicit; go 1.20 +# k8s.io/kubernetes v1.31.3 +## explicit; go 1.22.0 k8s.io/kubernetes/pkg/util/iptables -# k8s.io/utils v0.0.0-20230726121419-3b25d923346b +# k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 ## explicit; go 1.18 k8s.io/utils/buffer k8s.io/utils/clock @@ -1062,9 +1124,10 @@ sigs.k8s.io/structured-merge-diff/v4/merge sigs.k8s.io/structured-merge-diff/v4/schema sigs.k8s.io/structured-merge-diff/v4/typed sigs.k8s.io/structured-merge-diff/v4/value -# sigs.k8s.io/yaml v1.3.0 +# sigs.k8s.io/yaml v1.4.0 ## explicit; go 1.12 sigs.k8s.io/yaml +sigs.k8s.io/yaml/goyaml.v2 # k8s.io/api => k8s.io/api v0.28.14 # k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.28.14 # k8s.io/apimachinery => k8s.io/apimachinery v0.28.14 diff --git a/vendor/sigs.k8s.io/yaml/LICENSE b/vendor/sigs.k8s.io/yaml/LICENSE index 7805d36de..093d6d3ed 100644 --- a/vendor/sigs.k8s.io/yaml/LICENSE +++ b/vendor/sigs.k8s.io/yaml/LICENSE @@ -48,3 +48,259 @@ 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 forked go-yaml.v3 library under this project is covered by two +different licenses (MIT and Apache): + +#### MIT License #### + +The following files were ported to Go from C files of libyaml, and thus +are still covered by their original MIT license, with the additional +copyright staring in 2011 when the project was ported over: + + apic.go emitterc.go parserc.go readerc.go scannerc.go + writerc.go yamlh.go yamlprivateh.go + +Copyright (c) 2006-2010 Kirill Simonov +Copyright (c) 2006-2011 Kirill Simonov + +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. + +### Apache License ### + +All the remaining project files are covered by the Apache license: + +Copyright (c) 2011-2019 Canonical Ltd + +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 forked go-yaml.v2 library under the project is covered by an +Apache license: + + 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. diff --git a/vendor/sigs.k8s.io/yaml/OWNERS b/vendor/sigs.k8s.io/yaml/OWNERS index 325b40b07..003a149e1 100644 --- a/vendor/sigs.k8s.io/yaml/OWNERS +++ b/vendor/sigs.k8s.io/yaml/OWNERS @@ -2,26 +2,22 @@ approvers: - dims -- lavalamp +- jpbetz - smarterclayton - deads2k - sttts - liggitt -- caesarxuchao reviewers: - dims - thockin -- lavalamp +- jpbetz - smarterclayton - wojtek-t - deads2k - derekwaynecarr -- caesarxuchao - mikedanese - liggitt -- gmarek - sttts -- ncdc - tallclair labels: - sig/api-machinery diff --git a/vendor/sigs.k8s.io/yaml/fields.go b/vendor/sigs.k8s.io/yaml/fields.go index 235b7f2cf..0ea28bd03 100644 --- a/vendor/sigs.k8s.io/yaml/fields.go +++ b/vendor/sigs.k8s.io/yaml/fields.go @@ -16,53 +16,53 @@ import ( "unicode/utf8" ) -// indirect walks down v allocating pointers as needed, +// indirect walks down 'value' allocating pointers as needed, // until it gets to a non-pointer. // if it encounters an Unmarshaler, indirect stops and returns that. // if decodingNull is true, indirect stops at the last pointer so it can be set to nil. -func indirect(v reflect.Value, decodingNull bool) (json.Unmarshaler, encoding.TextUnmarshaler, reflect.Value) { - // If v is a named type and is addressable, +func indirect(value reflect.Value, decodingNull bool) (json.Unmarshaler, encoding.TextUnmarshaler, reflect.Value) { + // If 'value' is a named type and is addressable, // start with its address, so that if the type has pointer methods, // we find them. - if v.Kind() != reflect.Ptr && v.Type().Name() != "" && v.CanAddr() { - v = v.Addr() + if value.Kind() != reflect.Ptr && value.Type().Name() != "" && value.CanAddr() { + value = value.Addr() } for { // Load value from interface, but only if the result will be // usefully addressable. - if v.Kind() == reflect.Interface && !v.IsNil() { - e := v.Elem() - if e.Kind() == reflect.Ptr && !e.IsNil() && (!decodingNull || e.Elem().Kind() == reflect.Ptr) { - v = e + if value.Kind() == reflect.Interface && !value.IsNil() { + element := value.Elem() + if element.Kind() == reflect.Ptr && !element.IsNil() && (!decodingNull || element.Elem().Kind() == reflect.Ptr) { + value = element continue } } - if v.Kind() != reflect.Ptr { + if value.Kind() != reflect.Ptr { break } - if v.Elem().Kind() != reflect.Ptr && decodingNull && v.CanSet() { + if value.Elem().Kind() != reflect.Ptr && decodingNull && value.CanSet() { break } - if v.IsNil() { - if v.CanSet() { - v.Set(reflect.New(v.Type().Elem())) + if value.IsNil() { + if value.CanSet() { + value.Set(reflect.New(value.Type().Elem())) } else { - v = reflect.New(v.Type().Elem()) + value = reflect.New(value.Type().Elem()) } } - if v.Type().NumMethod() > 0 { - if u, ok := v.Interface().(json.Unmarshaler); ok { + if value.Type().NumMethod() > 0 { + if u, ok := value.Interface().(json.Unmarshaler); ok { return u, nil, reflect.Value{} } - if u, ok := v.Interface().(encoding.TextUnmarshaler); ok { + if u, ok := value.Interface().(encoding.TextUnmarshaler); ok { return nil, u, reflect.Value{} } } - v = v.Elem() + value = value.Elem() } - return nil, nil, v + return nil, nil, value } // A field represents a single field found in a struct. @@ -134,8 +134,8 @@ func typeFields(t reflect.Type) []field { next := []field{{typ: t}} // Count of queued names for current level and the next. - count := map[reflect.Type]int{} - nextCount := map[reflect.Type]int{} + var count map[reflect.Type]int + var nextCount map[reflect.Type]int // Types already visited at an earlier level. visited := map[reflect.Type]bool{} @@ -348,8 +348,9 @@ const ( // 4) simpleLetterEqualFold, no specials, no non-letters. // // The letters S and K are special because they map to 3 runes, not just 2: -// * S maps to s and to U+017F 'ſ' Latin small letter long s -// * k maps to K and to U+212A 'K' Kelvin sign +// - S maps to s and to U+017F 'ſ' Latin small letter long s +// - k maps to K and to U+212A 'K' Kelvin sign +// // See http://play.golang.org/p/tTxjOc0OGo // // The returned function is specialized for matching against s and @@ -420,10 +421,8 @@ func equalFoldRight(s, t []byte) bool { t = t[size:] } - if len(t) > 0 { - return false - } - return true + + return len(t) <= 0 } // asciiEqualFold is a specialization of bytes.EqualFold for use when diff --git a/vendor/google.golang.org/appengine/LICENSE b/vendor/sigs.k8s.io/yaml/goyaml.v2/LICENSE similarity index 99% rename from vendor/google.golang.org/appengine/LICENSE rename to vendor/sigs.k8s.io/yaml/goyaml.v2/LICENSE index d64569567..8dada3eda 100644 --- a/vendor/google.golang.org/appengine/LICENSE +++ b/vendor/sigs.k8s.io/yaml/goyaml.v2/LICENSE @@ -1,4 +1,3 @@ - Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -179,7 +178,7 @@ 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 "[]" + 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 @@ -187,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright [yyyy] [name of copyright owner] + 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. diff --git a/vendor/sigs.k8s.io/yaml/goyaml.v2/LICENSE.libyaml b/vendor/sigs.k8s.io/yaml/goyaml.v2/LICENSE.libyaml new file mode 100644 index 000000000..8da58fbf6 --- /dev/null +++ b/vendor/sigs.k8s.io/yaml/goyaml.v2/LICENSE.libyaml @@ -0,0 +1,31 @@ +The following files were ported to Go from C files of libyaml, and thus +are still covered by their original copyright and license: + + apic.go + emitterc.go + parserc.go + readerc.go + scannerc.go + writerc.go + yamlh.go + yamlprivateh.go + +Copyright (c) 2006 Kirill Simonov + +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/k8s.io/kubernetes/pkg/util/iptables/iptables_unsupported.go b/vendor/sigs.k8s.io/yaml/goyaml.v2/NOTICE similarity index 57% rename from vendor/k8s.io/kubernetes/pkg/util/iptables/iptables_unsupported.go rename to vendor/sigs.k8s.io/yaml/goyaml.v2/NOTICE index 0c7c5ee3e..866d74a7a 100644 --- a/vendor/k8s.io/kubernetes/pkg/util/iptables/iptables_unsupported.go +++ b/vendor/sigs.k8s.io/yaml/goyaml.v2/NOTICE @@ -1,8 +1,4 @@ -//go:build !linux -// +build !linux - -/* -Copyright 2017 The Kubernetes Authors. +Copyright 2011-2016 Canonical Ltd. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -15,19 +11,3 @@ distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 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 iptables - -import ( - "fmt" - "os" -) - -func grabIptablesLocks(lock14filePath, lock16filePath string) (iptablesLocker, error) { - return nil, fmt.Errorf("iptables unsupported on this platform") -} - -func grabIptablesFileLock(f *os.File) error { - return fmt.Errorf("iptables unsupported on this platform") -} diff --git a/vendor/sigs.k8s.io/yaml/goyaml.v2/OWNERS b/vendor/sigs.k8s.io/yaml/goyaml.v2/OWNERS new file mode 100644 index 000000000..73be0a3a9 --- /dev/null +++ b/vendor/sigs.k8s.io/yaml/goyaml.v2/OWNERS @@ -0,0 +1,24 @@ +# See the OWNERS docs at https://go.k8s.io/owners + +approvers: +- dims +- jpbetz +- smarterclayton +- deads2k +- sttts +- liggitt +- natasha41575 +- knverey +reviewers: +- dims +- thockin +- jpbetz +- smarterclayton +- deads2k +- derekwaynecarr +- mikedanese +- liggitt +- sttts +- tallclair +labels: +- sig/api-machinery diff --git a/vendor/sigs.k8s.io/yaml/goyaml.v2/README.md b/vendor/sigs.k8s.io/yaml/goyaml.v2/README.md new file mode 100644 index 000000000..53f4139dc --- /dev/null +++ b/vendor/sigs.k8s.io/yaml/goyaml.v2/README.md @@ -0,0 +1,143 @@ +# go-yaml fork + +This package is a fork of the go-yaml library and is intended solely for consumption +by kubernetes projects. In this fork, we plan to support only critical changes required for +kubernetes, such as small bug fixes and regressions. Larger, general-purpose feature requests +should be made in the upstream go-yaml library, and we will reject such changes in this fork +unless we are pulling them from upstream. + +This fork is based on v2.4.0: https://github.com/go-yaml/yaml/releases/tag/v2.4.0 + +# YAML support for the Go language + +Introduction +------------ + +The yaml package enables Go programs to comfortably encode and decode YAML +values. It was developed within [Canonical](https://www.canonical.com) as +part of the [juju](https://juju.ubuntu.com) project, and is based on a +pure Go port of the well-known [libyaml](http://pyyaml.org/wiki/LibYAML) +C library to parse and generate YAML data quickly and reliably. + +Compatibility +------------- + +The yaml package supports most of YAML 1.1 and 1.2, including support for +anchors, tags, map merging, etc. Multi-document unmarshalling is not yet +implemented, and base-60 floats from YAML 1.1 are purposefully not +supported since they're a poor design and are gone in YAML 1.2. + +Installation and usage +---------------------- + +The import path for the package is *gopkg.in/yaml.v2*. + +To install it, run: + + go get gopkg.in/yaml.v2 + +API documentation +----------------- + +If opened in a browser, the import path itself leads to the API documentation: + + * [https://gopkg.in/yaml.v2](https://gopkg.in/yaml.v2) + +API stability +------------- + +The package API for yaml v2 will remain stable as described in [gopkg.in](https://gopkg.in). + + +License +------- + +The yaml package is licensed under the Apache License 2.0. Please see the LICENSE file for details. + + +Example +------- + +```Go +package main + +import ( + "fmt" + "log" + + "gopkg.in/yaml.v2" +) + +var data = ` +a: Easy! +b: + c: 2 + d: [3, 4] +` + +// Note: struct fields must be public in order for unmarshal to +// correctly populate the data. +type T struct { + A string + B struct { + RenamedC int `yaml:"c"` + D []int `yaml:",flow"` + } +} + +func main() { + t := T{} + + err := yaml.Unmarshal([]byte(data), &t) + if err != nil { + log.Fatalf("error: %v", err) + } + fmt.Printf("--- t:\n%v\n\n", t) + + d, err := yaml.Marshal(&t) + if err != nil { + log.Fatalf("error: %v", err) + } + fmt.Printf("--- t dump:\n%s\n\n", string(d)) + + m := make(map[interface{}]interface{}) + + err = yaml.Unmarshal([]byte(data), &m) + if err != nil { + log.Fatalf("error: %v", err) + } + fmt.Printf("--- m:\n%v\n\n", m) + + d, err = yaml.Marshal(&m) + if err != nil { + log.Fatalf("error: %v", err) + } + fmt.Printf("--- m dump:\n%s\n\n", string(d)) +} +``` + +This example will generate the following output: + +``` +--- t: +{Easy! {2 [3 4]}} + +--- t dump: +a: Easy! +b: + c: 2 + d: [3, 4] + + +--- m: +map[a:Easy! b:map[c:2 d:[3 4]]] + +--- m dump: +a: Easy! +b: + c: 2 + d: + - 3 + - 4 +``` + diff --git a/vendor/sigs.k8s.io/yaml/goyaml.v2/apic.go b/vendor/sigs.k8s.io/yaml/goyaml.v2/apic.go new file mode 100644 index 000000000..acf71402c --- /dev/null +++ b/vendor/sigs.k8s.io/yaml/goyaml.v2/apic.go @@ -0,0 +1,744 @@ +package yaml + +import ( + "io" +) + +func yaml_insert_token(parser *yaml_parser_t, pos int, token *yaml_token_t) { + //fmt.Println("yaml_insert_token", "pos:", pos, "typ:", token.typ, "head:", parser.tokens_head, "len:", len(parser.tokens)) + + // Check if we can move the queue at the beginning of the buffer. + if parser.tokens_head > 0 && len(parser.tokens) == cap(parser.tokens) { + if parser.tokens_head != len(parser.tokens) { + copy(parser.tokens, parser.tokens[parser.tokens_head:]) + } + parser.tokens = parser.tokens[:len(parser.tokens)-parser.tokens_head] + parser.tokens_head = 0 + } + parser.tokens = append(parser.tokens, *token) + if pos < 0 { + return + } + copy(parser.tokens[parser.tokens_head+pos+1:], parser.tokens[parser.tokens_head+pos:]) + parser.tokens[parser.tokens_head+pos] = *token +} + +// Create a new parser object. +func yaml_parser_initialize(parser *yaml_parser_t) bool { + *parser = yaml_parser_t{ + raw_buffer: make([]byte, 0, input_raw_buffer_size), + buffer: make([]byte, 0, input_buffer_size), + } + return true +} + +// Destroy a parser object. +func yaml_parser_delete(parser *yaml_parser_t) { + *parser = yaml_parser_t{} +} + +// String read handler. +func yaml_string_read_handler(parser *yaml_parser_t, buffer []byte) (n int, err error) { + if parser.input_pos == len(parser.input) { + return 0, io.EOF + } + n = copy(buffer, parser.input[parser.input_pos:]) + parser.input_pos += n + return n, nil +} + +// Reader read handler. +func yaml_reader_read_handler(parser *yaml_parser_t, buffer []byte) (n int, err error) { + return parser.input_reader.Read(buffer) +} + +// Set a string input. +func yaml_parser_set_input_string(parser *yaml_parser_t, input []byte) { + if parser.read_handler != nil { + panic("must set the input source only once") + } + parser.read_handler = yaml_string_read_handler + parser.input = input + parser.input_pos = 0 +} + +// Set a file input. +func yaml_parser_set_input_reader(parser *yaml_parser_t, r io.Reader) { + if parser.read_handler != nil { + panic("must set the input source only once") + } + parser.read_handler = yaml_reader_read_handler + parser.input_reader = r +} + +// Set the source encoding. +func yaml_parser_set_encoding(parser *yaml_parser_t, encoding yaml_encoding_t) { + if parser.encoding != yaml_ANY_ENCODING { + panic("must set the encoding only once") + } + parser.encoding = encoding +} + +var disableLineWrapping = false + +// Create a new emitter object. +func yaml_emitter_initialize(emitter *yaml_emitter_t) { + *emitter = yaml_emitter_t{ + buffer: make([]byte, output_buffer_size), + raw_buffer: make([]byte, 0, output_raw_buffer_size), + states: make([]yaml_emitter_state_t, 0, initial_stack_size), + events: make([]yaml_event_t, 0, initial_queue_size), + } + if disableLineWrapping { + emitter.best_width = -1 + } +} + +// Destroy an emitter object. +func yaml_emitter_delete(emitter *yaml_emitter_t) { + *emitter = yaml_emitter_t{} +} + +// String write handler. +func yaml_string_write_handler(emitter *yaml_emitter_t, buffer []byte) error { + *emitter.output_buffer = append(*emitter.output_buffer, buffer...) + return nil +} + +// yaml_writer_write_handler uses emitter.output_writer to write the +// emitted text. +func yaml_writer_write_handler(emitter *yaml_emitter_t, buffer []byte) error { + _, err := emitter.output_writer.Write(buffer) + return err +} + +// Set a string output. +func yaml_emitter_set_output_string(emitter *yaml_emitter_t, output_buffer *[]byte) { + if emitter.write_handler != nil { + panic("must set the output target only once") + } + emitter.write_handler = yaml_string_write_handler + emitter.output_buffer = output_buffer +} + +// Set a file output. +func yaml_emitter_set_output_writer(emitter *yaml_emitter_t, w io.Writer) { + if emitter.write_handler != nil { + panic("must set the output target only once") + } + emitter.write_handler = yaml_writer_write_handler + emitter.output_writer = w +} + +// Set the output encoding. +func yaml_emitter_set_encoding(emitter *yaml_emitter_t, encoding yaml_encoding_t) { + if emitter.encoding != yaml_ANY_ENCODING { + panic("must set the output encoding only once") + } + emitter.encoding = encoding +} + +// Set the canonical output style. +func yaml_emitter_set_canonical(emitter *yaml_emitter_t, canonical bool) { + emitter.canonical = canonical +} + +//// Set the indentation increment. +func yaml_emitter_set_indent(emitter *yaml_emitter_t, indent int) { + if indent < 2 || indent > 9 { + indent = 2 + } + emitter.best_indent = indent +} + +// Set the preferred line width. +func yaml_emitter_set_width(emitter *yaml_emitter_t, width int) { + if width < 0 { + width = -1 + } + emitter.best_width = width +} + +// Set if unescaped non-ASCII characters are allowed. +func yaml_emitter_set_unicode(emitter *yaml_emitter_t, unicode bool) { + emitter.unicode = unicode +} + +// Set the preferred line break character. +func yaml_emitter_set_break(emitter *yaml_emitter_t, line_break yaml_break_t) { + emitter.line_break = line_break +} + +///* +// * Destroy a token object. +// */ +// +//YAML_DECLARE(void) +//yaml_token_delete(yaml_token_t *token) +//{ +// assert(token); // Non-NULL token object expected. +// +// switch (token.type) +// { +// case YAML_TAG_DIRECTIVE_TOKEN: +// yaml_free(token.data.tag_directive.handle); +// yaml_free(token.data.tag_directive.prefix); +// break; +// +// case YAML_ALIAS_TOKEN: +// yaml_free(token.data.alias.value); +// break; +// +// case YAML_ANCHOR_TOKEN: +// yaml_free(token.data.anchor.value); +// break; +// +// case YAML_TAG_TOKEN: +// yaml_free(token.data.tag.handle); +// yaml_free(token.data.tag.suffix); +// break; +// +// case YAML_SCALAR_TOKEN: +// yaml_free(token.data.scalar.value); +// break; +// +// default: +// break; +// } +// +// memset(token, 0, sizeof(yaml_token_t)); +//} +// +///* +// * Check if a string is a valid UTF-8 sequence. +// * +// * Check 'reader.c' for more details on UTF-8 encoding. +// */ +// +//static int +//yaml_check_utf8(yaml_char_t *start, size_t length) +//{ +// yaml_char_t *end = start+length; +// yaml_char_t *pointer = start; +// +// while (pointer < end) { +// unsigned char octet; +// unsigned int width; +// unsigned int value; +// size_t k; +// +// octet = pointer[0]; +// width = (octet & 0x80) == 0x00 ? 1 : +// (octet & 0xE0) == 0xC0 ? 2 : +// (octet & 0xF0) == 0xE0 ? 3 : +// (octet & 0xF8) == 0xF0 ? 4 : 0; +// value = (octet & 0x80) == 0x00 ? octet & 0x7F : +// (octet & 0xE0) == 0xC0 ? octet & 0x1F : +// (octet & 0xF0) == 0xE0 ? octet & 0x0F : +// (octet & 0xF8) == 0xF0 ? octet & 0x07 : 0; +// if (!width) return 0; +// if (pointer+width > end) return 0; +// for (k = 1; k < width; k ++) { +// octet = pointer[k]; +// if ((octet & 0xC0) != 0x80) return 0; +// value = (value << 6) + (octet & 0x3F); +// } +// if (!((width == 1) || +// (width == 2 && value >= 0x80) || +// (width == 3 && value >= 0x800) || +// (width == 4 && value >= 0x10000))) return 0; +// +// pointer += width; +// } +// +// return 1; +//} +// + +// Create STREAM-START. +func yaml_stream_start_event_initialize(event *yaml_event_t, encoding yaml_encoding_t) { + *event = yaml_event_t{ + typ: yaml_STREAM_START_EVENT, + encoding: encoding, + } +} + +// Create STREAM-END. +func yaml_stream_end_event_initialize(event *yaml_event_t) { + *event = yaml_event_t{ + typ: yaml_STREAM_END_EVENT, + } +} + +// Create DOCUMENT-START. +func yaml_document_start_event_initialize( + event *yaml_event_t, + version_directive *yaml_version_directive_t, + tag_directives []yaml_tag_directive_t, + implicit bool, +) { + *event = yaml_event_t{ + typ: yaml_DOCUMENT_START_EVENT, + version_directive: version_directive, + tag_directives: tag_directives, + implicit: implicit, + } +} + +// Create DOCUMENT-END. +func yaml_document_end_event_initialize(event *yaml_event_t, implicit bool) { + *event = yaml_event_t{ + typ: yaml_DOCUMENT_END_EVENT, + implicit: implicit, + } +} + +///* +// * Create ALIAS. +// */ +// +//YAML_DECLARE(int) +//yaml_alias_event_initialize(event *yaml_event_t, anchor *yaml_char_t) +//{ +// mark yaml_mark_t = { 0, 0, 0 } +// anchor_copy *yaml_char_t = NULL +// +// assert(event) // Non-NULL event object is expected. +// assert(anchor) // Non-NULL anchor is expected. +// +// if (!yaml_check_utf8(anchor, strlen((char *)anchor))) return 0 +// +// anchor_copy = yaml_strdup(anchor) +// if (!anchor_copy) +// return 0 +// +// ALIAS_EVENT_INIT(*event, anchor_copy, mark, mark) +// +// return 1 +//} + +// Create SCALAR. +func yaml_scalar_event_initialize(event *yaml_event_t, anchor, tag, value []byte, plain_implicit, quoted_implicit bool, style yaml_scalar_style_t) bool { + *event = yaml_event_t{ + typ: yaml_SCALAR_EVENT, + anchor: anchor, + tag: tag, + value: value, + implicit: plain_implicit, + quoted_implicit: quoted_implicit, + style: yaml_style_t(style), + } + return true +} + +// Create SEQUENCE-START. +func yaml_sequence_start_event_initialize(event *yaml_event_t, anchor, tag []byte, implicit bool, style yaml_sequence_style_t) bool { + *event = yaml_event_t{ + typ: yaml_SEQUENCE_START_EVENT, + anchor: anchor, + tag: tag, + implicit: implicit, + style: yaml_style_t(style), + } + return true +} + +// Create SEQUENCE-END. +func yaml_sequence_end_event_initialize(event *yaml_event_t) bool { + *event = yaml_event_t{ + typ: yaml_SEQUENCE_END_EVENT, + } + return true +} + +// Create MAPPING-START. +func yaml_mapping_start_event_initialize(event *yaml_event_t, anchor, tag []byte, implicit bool, style yaml_mapping_style_t) { + *event = yaml_event_t{ + typ: yaml_MAPPING_START_EVENT, + anchor: anchor, + tag: tag, + implicit: implicit, + style: yaml_style_t(style), + } +} + +// Create MAPPING-END. +func yaml_mapping_end_event_initialize(event *yaml_event_t) { + *event = yaml_event_t{ + typ: yaml_MAPPING_END_EVENT, + } +} + +// Destroy an event object. +func yaml_event_delete(event *yaml_event_t) { + *event = yaml_event_t{} +} + +///* +// * Create a document object. +// */ +// +//YAML_DECLARE(int) +//yaml_document_initialize(document *yaml_document_t, +// version_directive *yaml_version_directive_t, +// tag_directives_start *yaml_tag_directive_t, +// tag_directives_end *yaml_tag_directive_t, +// start_implicit int, end_implicit int) +//{ +// struct { +// error yaml_error_type_t +// } context +// struct { +// start *yaml_node_t +// end *yaml_node_t +// top *yaml_node_t +// } nodes = { NULL, NULL, NULL } +// version_directive_copy *yaml_version_directive_t = NULL +// struct { +// start *yaml_tag_directive_t +// end *yaml_tag_directive_t +// top *yaml_tag_directive_t +// } tag_directives_copy = { NULL, NULL, NULL } +// value yaml_tag_directive_t = { NULL, NULL } +// mark yaml_mark_t = { 0, 0, 0 } +// +// assert(document) // Non-NULL document object is expected. +// assert((tag_directives_start && tag_directives_end) || +// (tag_directives_start == tag_directives_end)) +// // Valid tag directives are expected. +// +// if (!STACK_INIT(&context, nodes, INITIAL_STACK_SIZE)) goto error +// +// if (version_directive) { +// version_directive_copy = yaml_malloc(sizeof(yaml_version_directive_t)) +// if (!version_directive_copy) goto error +// version_directive_copy.major = version_directive.major +// version_directive_copy.minor = version_directive.minor +// } +// +// if (tag_directives_start != tag_directives_end) { +// tag_directive *yaml_tag_directive_t +// if (!STACK_INIT(&context, tag_directives_copy, INITIAL_STACK_SIZE)) +// goto error +// for (tag_directive = tag_directives_start +// tag_directive != tag_directives_end; tag_directive ++) { +// assert(tag_directive.handle) +// assert(tag_directive.prefix) +// if (!yaml_check_utf8(tag_directive.handle, +// strlen((char *)tag_directive.handle))) +// goto error +// if (!yaml_check_utf8(tag_directive.prefix, +// strlen((char *)tag_directive.prefix))) +// goto error +// value.handle = yaml_strdup(tag_directive.handle) +// value.prefix = yaml_strdup(tag_directive.prefix) +// if (!value.handle || !value.prefix) goto error +// if (!PUSH(&context, tag_directives_copy, value)) +// goto error +// value.handle = NULL +// value.prefix = NULL +// } +// } +// +// DOCUMENT_INIT(*document, nodes.start, nodes.end, version_directive_copy, +// tag_directives_copy.start, tag_directives_copy.top, +// start_implicit, end_implicit, mark, mark) +// +// return 1 +// +//error: +// STACK_DEL(&context, nodes) +// yaml_free(version_directive_copy) +// while (!STACK_EMPTY(&context, tag_directives_copy)) { +// value yaml_tag_directive_t = POP(&context, tag_directives_copy) +// yaml_free(value.handle) +// yaml_free(value.prefix) +// } +// STACK_DEL(&context, tag_directives_copy) +// yaml_free(value.handle) +// yaml_free(value.prefix) +// +// return 0 +//} +// +///* +// * Destroy a document object. +// */ +// +//YAML_DECLARE(void) +//yaml_document_delete(document *yaml_document_t) +//{ +// struct { +// error yaml_error_type_t +// } context +// tag_directive *yaml_tag_directive_t +// +// context.error = YAML_NO_ERROR // Eliminate a compiler warning. +// +// assert(document) // Non-NULL document object is expected. +// +// while (!STACK_EMPTY(&context, document.nodes)) { +// node yaml_node_t = POP(&context, document.nodes) +// yaml_free(node.tag) +// switch (node.type) { +// case YAML_SCALAR_NODE: +// yaml_free(node.data.scalar.value) +// break +// case YAML_SEQUENCE_NODE: +// STACK_DEL(&context, node.data.sequence.items) +// break +// case YAML_MAPPING_NODE: +// STACK_DEL(&context, node.data.mapping.pairs) +// break +// default: +// assert(0) // Should not happen. +// } +// } +// STACK_DEL(&context, document.nodes) +// +// yaml_free(document.version_directive) +// for (tag_directive = document.tag_directives.start +// tag_directive != document.tag_directives.end +// tag_directive++) { +// yaml_free(tag_directive.handle) +// yaml_free(tag_directive.prefix) +// } +// yaml_free(document.tag_directives.start) +// +// memset(document, 0, sizeof(yaml_document_t)) +//} +// +///** +// * Get a document node. +// */ +// +//YAML_DECLARE(yaml_node_t *) +//yaml_document_get_node(document *yaml_document_t, index int) +//{ +// assert(document) // Non-NULL document object is expected. +// +// if (index > 0 && document.nodes.start + index <= document.nodes.top) { +// return document.nodes.start + index - 1 +// } +// return NULL +//} +// +///** +// * Get the root object. +// */ +// +//YAML_DECLARE(yaml_node_t *) +//yaml_document_get_root_node(document *yaml_document_t) +//{ +// assert(document) // Non-NULL document object is expected. +// +// if (document.nodes.top != document.nodes.start) { +// return document.nodes.start +// } +// return NULL +//} +// +///* +// * Add a scalar node to a document. +// */ +// +//YAML_DECLARE(int) +//yaml_document_add_scalar(document *yaml_document_t, +// tag *yaml_char_t, value *yaml_char_t, length int, +// style yaml_scalar_style_t) +//{ +// struct { +// error yaml_error_type_t +// } context +// mark yaml_mark_t = { 0, 0, 0 } +// tag_copy *yaml_char_t = NULL +// value_copy *yaml_char_t = NULL +// node yaml_node_t +// +// assert(document) // Non-NULL document object is expected. +// assert(value) // Non-NULL value is expected. +// +// if (!tag) { +// tag = (yaml_char_t *)YAML_DEFAULT_SCALAR_TAG +// } +// +// if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error +// tag_copy = yaml_strdup(tag) +// if (!tag_copy) goto error +// +// if (length < 0) { +// length = strlen((char *)value) +// } +// +// if (!yaml_check_utf8(value, length)) goto error +// value_copy = yaml_malloc(length+1) +// if (!value_copy) goto error +// memcpy(value_copy, value, length) +// value_copy[length] = '\0' +// +// SCALAR_NODE_INIT(node, tag_copy, value_copy, length, style, mark, mark) +// if (!PUSH(&context, document.nodes, node)) goto error +// +// return document.nodes.top - document.nodes.start +// +//error: +// yaml_free(tag_copy) +// yaml_free(value_copy) +// +// return 0 +//} +// +///* +// * Add a sequence node to a document. +// */ +// +//YAML_DECLARE(int) +//yaml_document_add_sequence(document *yaml_document_t, +// tag *yaml_char_t, style yaml_sequence_style_t) +//{ +// struct { +// error yaml_error_type_t +// } context +// mark yaml_mark_t = { 0, 0, 0 } +// tag_copy *yaml_char_t = NULL +// struct { +// start *yaml_node_item_t +// end *yaml_node_item_t +// top *yaml_node_item_t +// } items = { NULL, NULL, NULL } +// node yaml_node_t +// +// assert(document) // Non-NULL document object is expected. +// +// if (!tag) { +// tag = (yaml_char_t *)YAML_DEFAULT_SEQUENCE_TAG +// } +// +// if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error +// tag_copy = yaml_strdup(tag) +// if (!tag_copy) goto error +// +// if (!STACK_INIT(&context, items, INITIAL_STACK_SIZE)) goto error +// +// SEQUENCE_NODE_INIT(node, tag_copy, items.start, items.end, +// style, mark, mark) +// if (!PUSH(&context, document.nodes, node)) goto error +// +// return document.nodes.top - document.nodes.start +// +//error: +// STACK_DEL(&context, items) +// yaml_free(tag_copy) +// +// return 0 +//} +// +///* +// * Add a mapping node to a document. +// */ +// +//YAML_DECLARE(int) +//yaml_document_add_mapping(document *yaml_document_t, +// tag *yaml_char_t, style yaml_mapping_style_t) +//{ +// struct { +// error yaml_error_type_t +// } context +// mark yaml_mark_t = { 0, 0, 0 } +// tag_copy *yaml_char_t = NULL +// struct { +// start *yaml_node_pair_t +// end *yaml_node_pair_t +// top *yaml_node_pair_t +// } pairs = { NULL, NULL, NULL } +// node yaml_node_t +// +// assert(document) // Non-NULL document object is expected. +// +// if (!tag) { +// tag = (yaml_char_t *)YAML_DEFAULT_MAPPING_TAG +// } +// +// if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error +// tag_copy = yaml_strdup(tag) +// if (!tag_copy) goto error +// +// if (!STACK_INIT(&context, pairs, INITIAL_STACK_SIZE)) goto error +// +// MAPPING_NODE_INIT(node, tag_copy, pairs.start, pairs.end, +// style, mark, mark) +// if (!PUSH(&context, document.nodes, node)) goto error +// +// return document.nodes.top - document.nodes.start +// +//error: +// STACK_DEL(&context, pairs) +// yaml_free(tag_copy) +// +// return 0 +//} +// +///* +// * Append an item to a sequence node. +// */ +// +//YAML_DECLARE(int) +//yaml_document_append_sequence_item(document *yaml_document_t, +// sequence int, item int) +//{ +// struct { +// error yaml_error_type_t +// } context +// +// assert(document) // Non-NULL document is required. +// assert(sequence > 0 +// && document.nodes.start + sequence <= document.nodes.top) +// // Valid sequence id is required. +// assert(document.nodes.start[sequence-1].type == YAML_SEQUENCE_NODE) +// // A sequence node is required. +// assert(item > 0 && document.nodes.start + item <= document.nodes.top) +// // Valid item id is required. +// +// if (!PUSH(&context, +// document.nodes.start[sequence-1].data.sequence.items, item)) +// return 0 +// +// return 1 +//} +// +///* +// * Append a pair of a key and a value to a mapping node. +// */ +// +//YAML_DECLARE(int) +//yaml_document_append_mapping_pair(document *yaml_document_t, +// mapping int, key int, value int) +//{ +// struct { +// error yaml_error_type_t +// } context +// +// pair yaml_node_pair_t +// +// assert(document) // Non-NULL document is required. +// assert(mapping > 0 +// && document.nodes.start + mapping <= document.nodes.top) +// // Valid mapping id is required. +// assert(document.nodes.start[mapping-1].type == YAML_MAPPING_NODE) +// // A mapping node is required. +// assert(key > 0 && document.nodes.start + key <= document.nodes.top) +// // Valid key id is required. +// assert(value > 0 && document.nodes.start + value <= document.nodes.top) +// // Valid value id is required. +// +// pair.key = key +// pair.value = value +// +// if (!PUSH(&context, +// document.nodes.start[mapping-1].data.mapping.pairs, pair)) +// return 0 +// +// return 1 +//} +// +// diff --git a/vendor/sigs.k8s.io/yaml/goyaml.v2/decode.go b/vendor/sigs.k8s.io/yaml/goyaml.v2/decode.go new file mode 100644 index 000000000..129bc2a97 --- /dev/null +++ b/vendor/sigs.k8s.io/yaml/goyaml.v2/decode.go @@ -0,0 +1,815 @@ +package yaml + +import ( + "encoding" + "encoding/base64" + "fmt" + "io" + "math" + "reflect" + "strconv" + "time" +) + +const ( + documentNode = 1 << iota + mappingNode + sequenceNode + scalarNode + aliasNode +) + +type node struct { + kind int + line, column int + tag string + // For an alias node, alias holds the resolved alias. + alias *node + value string + implicit bool + children []*node + anchors map[string]*node +} + +// ---------------------------------------------------------------------------- +// Parser, produces a node tree out of a libyaml event stream. + +type parser struct { + parser yaml_parser_t + event yaml_event_t + doc *node + doneInit bool +} + +func newParser(b []byte) *parser { + p := parser{} + if !yaml_parser_initialize(&p.parser) { + panic("failed to initialize YAML emitter") + } + if len(b) == 0 { + b = []byte{'\n'} + } + yaml_parser_set_input_string(&p.parser, b) + return &p +} + +func newParserFromReader(r io.Reader) *parser { + p := parser{} + if !yaml_parser_initialize(&p.parser) { + panic("failed to initialize YAML emitter") + } + yaml_parser_set_input_reader(&p.parser, r) + return &p +} + +func (p *parser) init() { + if p.doneInit { + return + } + p.expect(yaml_STREAM_START_EVENT) + p.doneInit = true +} + +func (p *parser) destroy() { + if p.event.typ != yaml_NO_EVENT { + yaml_event_delete(&p.event) + } + yaml_parser_delete(&p.parser) +} + +// expect consumes an event from the event stream and +// checks that it's of the expected type. +func (p *parser) expect(e yaml_event_type_t) { + if p.event.typ == yaml_NO_EVENT { + if !yaml_parser_parse(&p.parser, &p.event) { + p.fail() + } + } + if p.event.typ == yaml_STREAM_END_EVENT { + failf("attempted to go past the end of stream; corrupted value?") + } + if p.event.typ != e { + p.parser.problem = fmt.Sprintf("expected %s event but got %s", e, p.event.typ) + p.fail() + } + yaml_event_delete(&p.event) + p.event.typ = yaml_NO_EVENT +} + +// peek peeks at the next event in the event stream, +// puts the results into p.event and returns the event type. +func (p *parser) peek() yaml_event_type_t { + if p.event.typ != yaml_NO_EVENT { + return p.event.typ + } + if !yaml_parser_parse(&p.parser, &p.event) { + p.fail() + } + return p.event.typ +} + +func (p *parser) fail() { + var where string + var line int + if p.parser.problem_mark.line != 0 { + line = p.parser.problem_mark.line + // Scanner errors don't iterate line before returning error + if p.parser.error == yaml_SCANNER_ERROR { + line++ + } + } else if p.parser.context_mark.line != 0 { + line = p.parser.context_mark.line + } + if line != 0 { + where = "line " + strconv.Itoa(line) + ": " + } + var msg string + if len(p.parser.problem) > 0 { + msg = p.parser.problem + } else { + msg = "unknown problem parsing YAML content" + } + failf("%s%s", where, msg) +} + +func (p *parser) anchor(n *node, anchor []byte) { + if anchor != nil { + p.doc.anchors[string(anchor)] = n + } +} + +func (p *parser) parse() *node { + p.init() + switch p.peek() { + case yaml_SCALAR_EVENT: + return p.scalar() + case yaml_ALIAS_EVENT: + return p.alias() + case yaml_MAPPING_START_EVENT: + return p.mapping() + case yaml_SEQUENCE_START_EVENT: + return p.sequence() + case yaml_DOCUMENT_START_EVENT: + return p.document() + case yaml_STREAM_END_EVENT: + // Happens when attempting to decode an empty buffer. + return nil + default: + panic("attempted to parse unknown event: " + p.event.typ.String()) + } +} + +func (p *parser) node(kind int) *node { + return &node{ + kind: kind, + line: p.event.start_mark.line, + column: p.event.start_mark.column, + } +} + +func (p *parser) document() *node { + n := p.node(documentNode) + n.anchors = make(map[string]*node) + p.doc = n + p.expect(yaml_DOCUMENT_START_EVENT) + n.children = append(n.children, p.parse()) + p.expect(yaml_DOCUMENT_END_EVENT) + return n +} + +func (p *parser) alias() *node { + n := p.node(aliasNode) + n.value = string(p.event.anchor) + n.alias = p.doc.anchors[n.value] + if n.alias == nil { + failf("unknown anchor '%s' referenced", n.value) + } + p.expect(yaml_ALIAS_EVENT) + return n +} + +func (p *parser) scalar() *node { + n := p.node(scalarNode) + n.value = string(p.event.value) + n.tag = string(p.event.tag) + n.implicit = p.event.implicit + p.anchor(n, p.event.anchor) + p.expect(yaml_SCALAR_EVENT) + return n +} + +func (p *parser) sequence() *node { + n := p.node(sequenceNode) + p.anchor(n, p.event.anchor) + p.expect(yaml_SEQUENCE_START_EVENT) + for p.peek() != yaml_SEQUENCE_END_EVENT { + n.children = append(n.children, p.parse()) + } + p.expect(yaml_SEQUENCE_END_EVENT) + return n +} + +func (p *parser) mapping() *node { + n := p.node(mappingNode) + p.anchor(n, p.event.anchor) + p.expect(yaml_MAPPING_START_EVENT) + for p.peek() != yaml_MAPPING_END_EVENT { + n.children = append(n.children, p.parse(), p.parse()) + } + p.expect(yaml_MAPPING_END_EVENT) + return n +} + +// ---------------------------------------------------------------------------- +// Decoder, unmarshals a node into a provided value. + +type decoder struct { + doc *node + aliases map[*node]bool + mapType reflect.Type + terrors []string + strict bool + + decodeCount int + aliasCount int + aliasDepth int +} + +var ( + mapItemType = reflect.TypeOf(MapItem{}) + durationType = reflect.TypeOf(time.Duration(0)) + defaultMapType = reflect.TypeOf(map[interface{}]interface{}{}) + ifaceType = defaultMapType.Elem() + timeType = reflect.TypeOf(time.Time{}) + ptrTimeType = reflect.TypeOf(&time.Time{}) +) + +func newDecoder(strict bool) *decoder { + d := &decoder{mapType: defaultMapType, strict: strict} + d.aliases = make(map[*node]bool) + return d +} + +func (d *decoder) terror(n *node, tag string, out reflect.Value) { + if n.tag != "" { + tag = n.tag + } + value := n.value + if tag != yaml_SEQ_TAG && tag != yaml_MAP_TAG { + if len(value) > 10 { + value = " `" + value[:7] + "...`" + } else { + value = " `" + value + "`" + } + } + d.terrors = append(d.terrors, fmt.Sprintf("line %d: cannot unmarshal %s%s into %s", n.line+1, shortTag(tag), value, out.Type())) +} + +func (d *decoder) callUnmarshaler(n *node, u Unmarshaler) (good bool) { + terrlen := len(d.terrors) + err := u.UnmarshalYAML(func(v interface{}) (err error) { + defer handleErr(&err) + d.unmarshal(n, reflect.ValueOf(v)) + if len(d.terrors) > terrlen { + issues := d.terrors[terrlen:] + d.terrors = d.terrors[:terrlen] + return &TypeError{issues} + } + return nil + }) + if e, ok := err.(*TypeError); ok { + d.terrors = append(d.terrors, e.Errors...) + return false + } + if err != nil { + fail(err) + } + return true +} + +// d.prepare initializes and dereferences pointers and calls UnmarshalYAML +// if a value is found to implement it. +// It returns the initialized and dereferenced out value, whether +// unmarshalling was already done by UnmarshalYAML, and if so whether +// its types unmarshalled appropriately. +// +// If n holds a null value, prepare returns before doing anything. +func (d *decoder) prepare(n *node, out reflect.Value) (newout reflect.Value, unmarshaled, good bool) { + if n.tag == yaml_NULL_TAG || n.kind == scalarNode && n.tag == "" && (n.value == "null" || n.value == "~" || n.value == "" && n.implicit) { + return out, false, false + } + again := true + for again { + again = false + if out.Kind() == reflect.Ptr { + if out.IsNil() { + out.Set(reflect.New(out.Type().Elem())) + } + out = out.Elem() + again = true + } + if out.CanAddr() { + if u, ok := out.Addr().Interface().(Unmarshaler); ok { + good = d.callUnmarshaler(n, u) + return out, true, good + } + } + } + return out, false, false +} + +const ( + // 400,000 decode operations is ~500kb of dense object declarations, or + // ~5kb of dense object declarations with 10000% alias expansion + alias_ratio_range_low = 400000 + + // 4,000,000 decode operations is ~5MB of dense object declarations, or + // ~4.5MB of dense object declarations with 10% alias expansion + alias_ratio_range_high = 4000000 + + // alias_ratio_range is the range over which we scale allowed alias ratios + alias_ratio_range = float64(alias_ratio_range_high - alias_ratio_range_low) +) + +func allowedAliasRatio(decodeCount int) float64 { + switch { + case decodeCount <= alias_ratio_range_low: + // allow 99% to come from alias expansion for small-to-medium documents + return 0.99 + case decodeCount >= alias_ratio_range_high: + // allow 10% to come from alias expansion for very large documents + return 0.10 + default: + // scale smoothly from 99% down to 10% over the range. + // this maps to 396,000 - 400,000 allowed alias-driven decodes over the range. + // 400,000 decode operations is ~100MB of allocations in worst-case scenarios (single-item maps). + return 0.99 - 0.89*(float64(decodeCount-alias_ratio_range_low)/alias_ratio_range) + } +} + +func (d *decoder) unmarshal(n *node, out reflect.Value) (good bool) { + d.decodeCount++ + if d.aliasDepth > 0 { + d.aliasCount++ + } + if d.aliasCount > 100 && d.decodeCount > 1000 && float64(d.aliasCount)/float64(d.decodeCount) > allowedAliasRatio(d.decodeCount) { + failf("document contains excessive aliasing") + } + switch n.kind { + case documentNode: + return d.document(n, out) + case aliasNode: + return d.alias(n, out) + } + out, unmarshaled, good := d.prepare(n, out) + if unmarshaled { + return good + } + switch n.kind { + case scalarNode: + good = d.scalar(n, out) + case mappingNode: + good = d.mapping(n, out) + case sequenceNode: + good = d.sequence(n, out) + default: + panic("internal error: unknown node kind: " + strconv.Itoa(n.kind)) + } + return good +} + +func (d *decoder) document(n *node, out reflect.Value) (good bool) { + if len(n.children) == 1 { + d.doc = n + d.unmarshal(n.children[0], out) + return true + } + return false +} + +func (d *decoder) alias(n *node, out reflect.Value) (good bool) { + if d.aliases[n] { + // TODO this could actually be allowed in some circumstances. + failf("anchor '%s' value contains itself", n.value) + } + d.aliases[n] = true + d.aliasDepth++ + good = d.unmarshal(n.alias, out) + d.aliasDepth-- + delete(d.aliases, n) + return good +} + +var zeroValue reflect.Value + +func resetMap(out reflect.Value) { + for _, k := range out.MapKeys() { + out.SetMapIndex(k, zeroValue) + } +} + +func (d *decoder) scalar(n *node, out reflect.Value) bool { + var tag string + var resolved interface{} + if n.tag == "" && !n.implicit { + tag = yaml_STR_TAG + resolved = n.value + } else { + tag, resolved = resolve(n.tag, n.value) + if tag == yaml_BINARY_TAG { + data, err := base64.StdEncoding.DecodeString(resolved.(string)) + if err != nil { + failf("!!binary value contains invalid base64 data") + } + resolved = string(data) + } + } + if resolved == nil { + if out.Kind() == reflect.Map && !out.CanAddr() { + resetMap(out) + } else { + out.Set(reflect.Zero(out.Type())) + } + return true + } + if resolvedv := reflect.ValueOf(resolved); out.Type() == resolvedv.Type() { + // We've resolved to exactly the type we want, so use that. + out.Set(resolvedv) + return true + } + // Perhaps we can use the value as a TextUnmarshaler to + // set its value. + if out.CanAddr() { + u, ok := out.Addr().Interface().(encoding.TextUnmarshaler) + if ok { + var text []byte + if tag == yaml_BINARY_TAG { + text = []byte(resolved.(string)) + } else { + // We let any value be unmarshaled into TextUnmarshaler. + // That might be more lax than we'd like, but the + // TextUnmarshaler itself should bowl out any dubious values. + text = []byte(n.value) + } + err := u.UnmarshalText(text) + if err != nil { + fail(err) + } + return true + } + } + switch out.Kind() { + case reflect.String: + if tag == yaml_BINARY_TAG { + out.SetString(resolved.(string)) + return true + } + if resolved != nil { + out.SetString(n.value) + return true + } + case reflect.Interface: + if resolved == nil { + out.Set(reflect.Zero(out.Type())) + } else if tag == yaml_TIMESTAMP_TAG { + // It looks like a timestamp but for backward compatibility + // reasons we set it as a string, so that code that unmarshals + // timestamp-like values into interface{} will continue to + // see a string and not a time.Time. + // TODO(v3) Drop this. + out.Set(reflect.ValueOf(n.value)) + } else { + out.Set(reflect.ValueOf(resolved)) + } + return true + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + switch resolved := resolved.(type) { + case int: + if !out.OverflowInt(int64(resolved)) { + out.SetInt(int64(resolved)) + return true + } + case int64: + if !out.OverflowInt(resolved) { + out.SetInt(resolved) + return true + } + case uint64: + if resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) { + out.SetInt(int64(resolved)) + return true + } + case float64: + if resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) { + out.SetInt(int64(resolved)) + return true + } + case string: + if out.Type() == durationType { + d, err := time.ParseDuration(resolved) + if err == nil { + out.SetInt(int64(d)) + return true + } + } + } + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + switch resolved := resolved.(type) { + case int: + if resolved >= 0 && !out.OverflowUint(uint64(resolved)) { + out.SetUint(uint64(resolved)) + return true + } + case int64: + if resolved >= 0 && !out.OverflowUint(uint64(resolved)) { + out.SetUint(uint64(resolved)) + return true + } + case uint64: + if !out.OverflowUint(uint64(resolved)) { + out.SetUint(uint64(resolved)) + return true + } + case float64: + if resolved <= math.MaxUint64 && !out.OverflowUint(uint64(resolved)) { + out.SetUint(uint64(resolved)) + return true + } + } + case reflect.Bool: + switch resolved := resolved.(type) { + case bool: + out.SetBool(resolved) + return true + } + case reflect.Float32, reflect.Float64: + switch resolved := resolved.(type) { + case int: + out.SetFloat(float64(resolved)) + return true + case int64: + out.SetFloat(float64(resolved)) + return true + case uint64: + out.SetFloat(float64(resolved)) + return true + case float64: + out.SetFloat(resolved) + return true + } + case reflect.Struct: + if resolvedv := reflect.ValueOf(resolved); out.Type() == resolvedv.Type() { + out.Set(resolvedv) + return true + } + case reflect.Ptr: + if out.Type().Elem() == reflect.TypeOf(resolved) { + // TODO DOes this make sense? When is out a Ptr except when decoding a nil value? + elem := reflect.New(out.Type().Elem()) + elem.Elem().Set(reflect.ValueOf(resolved)) + out.Set(elem) + return true + } + } + d.terror(n, tag, out) + return false +} + +func settableValueOf(i interface{}) reflect.Value { + v := reflect.ValueOf(i) + sv := reflect.New(v.Type()).Elem() + sv.Set(v) + return sv +} + +func (d *decoder) sequence(n *node, out reflect.Value) (good bool) { + l := len(n.children) + + var iface reflect.Value + switch out.Kind() { + case reflect.Slice: + out.Set(reflect.MakeSlice(out.Type(), l, l)) + case reflect.Array: + if l != out.Len() { + failf("invalid array: want %d elements but got %d", out.Len(), l) + } + case reflect.Interface: + // No type hints. Will have to use a generic sequence. + iface = out + out = settableValueOf(make([]interface{}, l)) + default: + d.terror(n, yaml_SEQ_TAG, out) + return false + } + et := out.Type().Elem() + + j := 0 + for i := 0; i < l; i++ { + e := reflect.New(et).Elem() + if ok := d.unmarshal(n.children[i], e); ok { + out.Index(j).Set(e) + j++ + } + } + if out.Kind() != reflect.Array { + out.Set(out.Slice(0, j)) + } + if iface.IsValid() { + iface.Set(out) + } + return true +} + +func (d *decoder) mapping(n *node, out reflect.Value) (good bool) { + switch out.Kind() { + case reflect.Struct: + return d.mappingStruct(n, out) + case reflect.Slice: + return d.mappingSlice(n, out) + case reflect.Map: + // okay + case reflect.Interface: + if d.mapType.Kind() == reflect.Map { + iface := out + out = reflect.MakeMap(d.mapType) + iface.Set(out) + } else { + slicev := reflect.New(d.mapType).Elem() + if !d.mappingSlice(n, slicev) { + return false + } + out.Set(slicev) + return true + } + default: + d.terror(n, yaml_MAP_TAG, out) + return false + } + outt := out.Type() + kt := outt.Key() + et := outt.Elem() + + mapType := d.mapType + if outt.Key() == ifaceType && outt.Elem() == ifaceType { + d.mapType = outt + } + + if out.IsNil() { + out.Set(reflect.MakeMap(outt)) + } + l := len(n.children) + for i := 0; i < l; i += 2 { + if isMerge(n.children[i]) { + d.merge(n.children[i+1], out) + continue + } + k := reflect.New(kt).Elem() + if d.unmarshal(n.children[i], k) { + kkind := k.Kind() + if kkind == reflect.Interface { + kkind = k.Elem().Kind() + } + if kkind == reflect.Map || kkind == reflect.Slice { + failf("invalid map key: %#v", k.Interface()) + } + e := reflect.New(et).Elem() + if d.unmarshal(n.children[i+1], e) { + d.setMapIndex(n.children[i+1], out, k, e) + } + } + } + d.mapType = mapType + return true +} + +func (d *decoder) setMapIndex(n *node, out, k, v reflect.Value) { + if d.strict && out.MapIndex(k) != zeroValue { + d.terrors = append(d.terrors, fmt.Sprintf("line %d: key %#v already set in map", n.line+1, k.Interface())) + return + } + out.SetMapIndex(k, v) +} + +func (d *decoder) mappingSlice(n *node, out reflect.Value) (good bool) { + outt := out.Type() + if outt.Elem() != mapItemType { + d.terror(n, yaml_MAP_TAG, out) + return false + } + + mapType := d.mapType + d.mapType = outt + + var slice []MapItem + var l = len(n.children) + for i := 0; i < l; i += 2 { + if isMerge(n.children[i]) { + d.merge(n.children[i+1], out) + continue + } + item := MapItem{} + k := reflect.ValueOf(&item.Key).Elem() + if d.unmarshal(n.children[i], k) { + v := reflect.ValueOf(&item.Value).Elem() + if d.unmarshal(n.children[i+1], v) { + slice = append(slice, item) + } + } + } + out.Set(reflect.ValueOf(slice)) + d.mapType = mapType + return true +} + +func (d *decoder) mappingStruct(n *node, out reflect.Value) (good bool) { + sinfo, err := getStructInfo(out.Type()) + if err != nil { + panic(err) + } + name := settableValueOf("") + l := len(n.children) + + var inlineMap reflect.Value + var elemType reflect.Type + if sinfo.InlineMap != -1 { + inlineMap = out.Field(sinfo.InlineMap) + inlineMap.Set(reflect.New(inlineMap.Type()).Elem()) + elemType = inlineMap.Type().Elem() + } + + var doneFields []bool + if d.strict { + doneFields = make([]bool, len(sinfo.FieldsList)) + } + for i := 0; i < l; i += 2 { + ni := n.children[i] + if isMerge(ni) { + d.merge(n.children[i+1], out) + continue + } + if !d.unmarshal(ni, name) { + continue + } + if info, ok := sinfo.FieldsMap[name.String()]; ok { + if d.strict { + if doneFields[info.Id] { + d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s already set in type %s", ni.line+1, name.String(), out.Type())) + continue + } + doneFields[info.Id] = true + } + var field reflect.Value + if info.Inline == nil { + field = out.Field(info.Num) + } else { + field = out.FieldByIndex(info.Inline) + } + d.unmarshal(n.children[i+1], field) + } else if sinfo.InlineMap != -1 { + if inlineMap.IsNil() { + inlineMap.Set(reflect.MakeMap(inlineMap.Type())) + } + value := reflect.New(elemType).Elem() + d.unmarshal(n.children[i+1], value) + d.setMapIndex(n.children[i+1], inlineMap, name, value) + } else if d.strict { + d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s not found in type %s", ni.line+1, name.String(), out.Type())) + } + } + return true +} + +func failWantMap() { + failf("map merge requires map or sequence of maps as the value") +} + +func (d *decoder) merge(n *node, out reflect.Value) { + switch n.kind { + case mappingNode: + d.unmarshal(n, out) + case aliasNode: + if n.alias != nil && n.alias.kind != mappingNode { + failWantMap() + } + d.unmarshal(n, out) + case sequenceNode: + // Step backwards as earlier nodes take precedence. + for i := len(n.children) - 1; i >= 0; i-- { + ni := n.children[i] + if ni.kind == aliasNode { + if ni.alias != nil && ni.alias.kind != mappingNode { + failWantMap() + } + } else if ni.kind != mappingNode { + failWantMap() + } + d.unmarshal(ni, out) + } + default: + failWantMap() + } +} + +func isMerge(n *node) bool { + return n.kind == scalarNode && n.value == "<<" && (n.implicit == true || n.tag == yaml_MERGE_TAG) +} diff --git a/vendor/sigs.k8s.io/yaml/goyaml.v2/emitterc.go b/vendor/sigs.k8s.io/yaml/goyaml.v2/emitterc.go new file mode 100644 index 000000000..a1c2cc526 --- /dev/null +++ b/vendor/sigs.k8s.io/yaml/goyaml.v2/emitterc.go @@ -0,0 +1,1685 @@ +package yaml + +import ( + "bytes" + "fmt" +) + +// Flush the buffer if needed. +func flush(emitter *yaml_emitter_t) bool { + if emitter.buffer_pos+5 >= len(emitter.buffer) { + return yaml_emitter_flush(emitter) + } + return true +} + +// Put a character to the output buffer. +func put(emitter *yaml_emitter_t, value byte) bool { + if emitter.buffer_pos+5 >= len(emitter.buffer) && !yaml_emitter_flush(emitter) { + return false + } + emitter.buffer[emitter.buffer_pos] = value + emitter.buffer_pos++ + emitter.column++ + return true +} + +// Put a line break to the output buffer. +func put_break(emitter *yaml_emitter_t) bool { + if emitter.buffer_pos+5 >= len(emitter.buffer) && !yaml_emitter_flush(emitter) { + return false + } + switch emitter.line_break { + case yaml_CR_BREAK: + emitter.buffer[emitter.buffer_pos] = '\r' + emitter.buffer_pos += 1 + case yaml_LN_BREAK: + emitter.buffer[emitter.buffer_pos] = '\n' + emitter.buffer_pos += 1 + case yaml_CRLN_BREAK: + emitter.buffer[emitter.buffer_pos+0] = '\r' + emitter.buffer[emitter.buffer_pos+1] = '\n' + emitter.buffer_pos += 2 + default: + panic("unknown line break setting") + } + emitter.column = 0 + emitter.line++ + return true +} + +// Copy a character from a string into buffer. +func write(emitter *yaml_emitter_t, s []byte, i *int) bool { + if emitter.buffer_pos+5 >= len(emitter.buffer) && !yaml_emitter_flush(emitter) { + return false + } + p := emitter.buffer_pos + w := width(s[*i]) + switch w { + case 4: + emitter.buffer[p+3] = s[*i+3] + fallthrough + case 3: + emitter.buffer[p+2] = s[*i+2] + fallthrough + case 2: + emitter.buffer[p+1] = s[*i+1] + fallthrough + case 1: + emitter.buffer[p+0] = s[*i+0] + default: + panic("unknown character width") + } + emitter.column++ + emitter.buffer_pos += w + *i += w + return true +} + +// Write a whole string into buffer. +func write_all(emitter *yaml_emitter_t, s []byte) bool { + for i := 0; i < len(s); { + if !write(emitter, s, &i) { + return false + } + } + return true +} + +// Copy a line break character from a string into buffer. +func write_break(emitter *yaml_emitter_t, s []byte, i *int) bool { + if s[*i] == '\n' { + if !put_break(emitter) { + return false + } + *i++ + } else { + if !write(emitter, s, i) { + return false + } + emitter.column = 0 + emitter.line++ + } + return true +} + +// Set an emitter error and return false. +func yaml_emitter_set_emitter_error(emitter *yaml_emitter_t, problem string) bool { + emitter.error = yaml_EMITTER_ERROR + emitter.problem = problem + return false +} + +// Emit an event. +func yaml_emitter_emit(emitter *yaml_emitter_t, event *yaml_event_t) bool { + emitter.events = append(emitter.events, *event) + for !yaml_emitter_need_more_events(emitter) { + event := &emitter.events[emitter.events_head] + if !yaml_emitter_analyze_event(emitter, event) { + return false + } + if !yaml_emitter_state_machine(emitter, event) { + return false + } + yaml_event_delete(event) + emitter.events_head++ + } + return true +} + +// Check if we need to accumulate more events before emitting. +// +// We accumulate extra +// - 1 event for DOCUMENT-START +// - 2 events for SEQUENCE-START +// - 3 events for MAPPING-START +// +func yaml_emitter_need_more_events(emitter *yaml_emitter_t) bool { + if emitter.events_head == len(emitter.events) { + return true + } + var accumulate int + switch emitter.events[emitter.events_head].typ { + case yaml_DOCUMENT_START_EVENT: + accumulate = 1 + break + case yaml_SEQUENCE_START_EVENT: + accumulate = 2 + break + case yaml_MAPPING_START_EVENT: + accumulate = 3 + break + default: + return false + } + if len(emitter.events)-emitter.events_head > accumulate { + return false + } + var level int + for i := emitter.events_head; i < len(emitter.events); i++ { + switch emitter.events[i].typ { + case yaml_STREAM_START_EVENT, yaml_DOCUMENT_START_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT: + level++ + case yaml_STREAM_END_EVENT, yaml_DOCUMENT_END_EVENT, yaml_SEQUENCE_END_EVENT, yaml_MAPPING_END_EVENT: + level-- + } + if level == 0 { + return false + } + } + return true +} + +// Append a directive to the directives stack. +func yaml_emitter_append_tag_directive(emitter *yaml_emitter_t, value *yaml_tag_directive_t, allow_duplicates bool) bool { + for i := 0; i < len(emitter.tag_directives); i++ { + if bytes.Equal(value.handle, emitter.tag_directives[i].handle) { + if allow_duplicates { + return true + } + return yaml_emitter_set_emitter_error(emitter, "duplicate %TAG directive") + } + } + + // [Go] Do we actually need to copy this given garbage collection + // and the lack of deallocating destructors? + tag_copy := yaml_tag_directive_t{ + handle: make([]byte, len(value.handle)), + prefix: make([]byte, len(value.prefix)), + } + copy(tag_copy.handle, value.handle) + copy(tag_copy.prefix, value.prefix) + emitter.tag_directives = append(emitter.tag_directives, tag_copy) + return true +} + +// Increase the indentation level. +func yaml_emitter_increase_indent(emitter *yaml_emitter_t, flow, indentless bool) bool { + emitter.indents = append(emitter.indents, emitter.indent) + if emitter.indent < 0 { + if flow { + emitter.indent = emitter.best_indent + } else { + emitter.indent = 0 + } + } else if !indentless { + emitter.indent += emitter.best_indent + } + return true +} + +// State dispatcher. +func yaml_emitter_state_machine(emitter *yaml_emitter_t, event *yaml_event_t) bool { + switch emitter.state { + default: + case yaml_EMIT_STREAM_START_STATE: + return yaml_emitter_emit_stream_start(emitter, event) + + case yaml_EMIT_FIRST_DOCUMENT_START_STATE: + return yaml_emitter_emit_document_start(emitter, event, true) + + case yaml_EMIT_DOCUMENT_START_STATE: + return yaml_emitter_emit_document_start(emitter, event, false) + + case yaml_EMIT_DOCUMENT_CONTENT_STATE: + return yaml_emitter_emit_document_content(emitter, event) + + case yaml_EMIT_DOCUMENT_END_STATE: + return yaml_emitter_emit_document_end(emitter, event) + + case yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE: + return yaml_emitter_emit_flow_sequence_item(emitter, event, true) + + case yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE: + return yaml_emitter_emit_flow_sequence_item(emitter, event, false) + + case yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE: + return yaml_emitter_emit_flow_mapping_key(emitter, event, true) + + case yaml_EMIT_FLOW_MAPPING_KEY_STATE: + return yaml_emitter_emit_flow_mapping_key(emitter, event, false) + + case yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE: + return yaml_emitter_emit_flow_mapping_value(emitter, event, true) + + case yaml_EMIT_FLOW_MAPPING_VALUE_STATE: + return yaml_emitter_emit_flow_mapping_value(emitter, event, false) + + case yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE: + return yaml_emitter_emit_block_sequence_item(emitter, event, true) + + case yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE: + return yaml_emitter_emit_block_sequence_item(emitter, event, false) + + case yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE: + return yaml_emitter_emit_block_mapping_key(emitter, event, true) + + case yaml_EMIT_BLOCK_MAPPING_KEY_STATE: + return yaml_emitter_emit_block_mapping_key(emitter, event, false) + + case yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE: + return yaml_emitter_emit_block_mapping_value(emitter, event, true) + + case yaml_EMIT_BLOCK_MAPPING_VALUE_STATE: + return yaml_emitter_emit_block_mapping_value(emitter, event, false) + + case yaml_EMIT_END_STATE: + return yaml_emitter_set_emitter_error(emitter, "expected nothing after STREAM-END") + } + panic("invalid emitter state") +} + +// Expect STREAM-START. +func yaml_emitter_emit_stream_start(emitter *yaml_emitter_t, event *yaml_event_t) bool { + if event.typ != yaml_STREAM_START_EVENT { + return yaml_emitter_set_emitter_error(emitter, "expected STREAM-START") + } + if emitter.encoding == yaml_ANY_ENCODING { + emitter.encoding = event.encoding + if emitter.encoding == yaml_ANY_ENCODING { + emitter.encoding = yaml_UTF8_ENCODING + } + } + if emitter.best_indent < 2 || emitter.best_indent > 9 { + emitter.best_indent = 2 + } + if emitter.best_width >= 0 && emitter.best_width <= emitter.best_indent*2 { + emitter.best_width = 80 + } + if emitter.best_width < 0 { + emitter.best_width = 1<<31 - 1 + } + if emitter.line_break == yaml_ANY_BREAK { + emitter.line_break = yaml_LN_BREAK + } + + emitter.indent = -1 + emitter.line = 0 + emitter.column = 0 + emitter.whitespace = true + emitter.indention = true + + if emitter.encoding != yaml_UTF8_ENCODING { + if !yaml_emitter_write_bom(emitter) { + return false + } + } + emitter.state = yaml_EMIT_FIRST_DOCUMENT_START_STATE + return true +} + +// Expect DOCUMENT-START or STREAM-END. +func yaml_emitter_emit_document_start(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool { + + if event.typ == yaml_DOCUMENT_START_EVENT { + + if event.version_directive != nil { + if !yaml_emitter_analyze_version_directive(emitter, event.version_directive) { + return false + } + } + + for i := 0; i < len(event.tag_directives); i++ { + tag_directive := &event.tag_directives[i] + if !yaml_emitter_analyze_tag_directive(emitter, tag_directive) { + return false + } + if !yaml_emitter_append_tag_directive(emitter, tag_directive, false) { + return false + } + } + + for i := 0; i < len(default_tag_directives); i++ { + tag_directive := &default_tag_directives[i] + if !yaml_emitter_append_tag_directive(emitter, tag_directive, true) { + return false + } + } + + implicit := event.implicit + if !first || emitter.canonical { + implicit = false + } + + if emitter.open_ended && (event.version_directive != nil || len(event.tag_directives) > 0) { + if !yaml_emitter_write_indicator(emitter, []byte("..."), true, false, false) { + return false + } + if !yaml_emitter_write_indent(emitter) { + return false + } + } + + if event.version_directive != nil { + implicit = false + if !yaml_emitter_write_indicator(emitter, []byte("%YAML"), true, false, false) { + return false + } + if !yaml_emitter_write_indicator(emitter, []byte("1.1"), true, false, false) { + return false + } + if !yaml_emitter_write_indent(emitter) { + return false + } + } + + if len(event.tag_directives) > 0 { + implicit = false + for i := 0; i < len(event.tag_directives); i++ { + tag_directive := &event.tag_directives[i] + if !yaml_emitter_write_indicator(emitter, []byte("%TAG"), true, false, false) { + return false + } + if !yaml_emitter_write_tag_handle(emitter, tag_directive.handle) { + return false + } + if !yaml_emitter_write_tag_content(emitter, tag_directive.prefix, true) { + return false + } + if !yaml_emitter_write_indent(emitter) { + return false + } + } + } + + if yaml_emitter_check_empty_document(emitter) { + implicit = false + } + if !implicit { + if !yaml_emitter_write_indent(emitter) { + return false + } + if !yaml_emitter_write_indicator(emitter, []byte("---"), true, false, false) { + return false + } + if emitter.canonical { + if !yaml_emitter_write_indent(emitter) { + return false + } + } + } + + emitter.state = yaml_EMIT_DOCUMENT_CONTENT_STATE + return true + } + + if event.typ == yaml_STREAM_END_EVENT { + if emitter.open_ended { + if !yaml_emitter_write_indicator(emitter, []byte("..."), true, false, false) { + return false + } + if !yaml_emitter_write_indent(emitter) { + return false + } + } + if !yaml_emitter_flush(emitter) { + return false + } + emitter.state = yaml_EMIT_END_STATE + return true + } + + return yaml_emitter_set_emitter_error(emitter, "expected DOCUMENT-START or STREAM-END") +} + +// Expect the root node. +func yaml_emitter_emit_document_content(emitter *yaml_emitter_t, event *yaml_event_t) bool { + emitter.states = append(emitter.states, yaml_EMIT_DOCUMENT_END_STATE) + return yaml_emitter_emit_node(emitter, event, true, false, false, false) +} + +// Expect DOCUMENT-END. +func yaml_emitter_emit_document_end(emitter *yaml_emitter_t, event *yaml_event_t) bool { + if event.typ != yaml_DOCUMENT_END_EVENT { + return yaml_emitter_set_emitter_error(emitter, "expected DOCUMENT-END") + } + if !yaml_emitter_write_indent(emitter) { + return false + } + if !event.implicit { + // [Go] Allocate the slice elsewhere. + if !yaml_emitter_write_indicator(emitter, []byte("..."), true, false, false) { + return false + } + if !yaml_emitter_write_indent(emitter) { + return false + } + } + if !yaml_emitter_flush(emitter) { + return false + } + emitter.state = yaml_EMIT_DOCUMENT_START_STATE + emitter.tag_directives = emitter.tag_directives[:0] + return true +} + +// Expect a flow item node. +func yaml_emitter_emit_flow_sequence_item(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool { + if first { + if !yaml_emitter_write_indicator(emitter, []byte{'['}, true, true, false) { + return false + } + if !yaml_emitter_increase_indent(emitter, true, false) { + return false + } + emitter.flow_level++ + } + + if event.typ == yaml_SEQUENCE_END_EVENT { + emitter.flow_level-- + emitter.indent = emitter.indents[len(emitter.indents)-1] + emitter.indents = emitter.indents[:len(emitter.indents)-1] + if emitter.canonical && !first { + if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) { + return false + } + if !yaml_emitter_write_indent(emitter) { + return false + } + } + if !yaml_emitter_write_indicator(emitter, []byte{']'}, false, false, false) { + return false + } + emitter.state = emitter.states[len(emitter.states)-1] + emitter.states = emitter.states[:len(emitter.states)-1] + + return true + } + + if !first { + if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) { + return false + } + } + + if emitter.canonical || emitter.column > emitter.best_width { + if !yaml_emitter_write_indent(emitter) { + return false + } + } + emitter.states = append(emitter.states, yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE) + return yaml_emitter_emit_node(emitter, event, false, true, false, false) +} + +// Expect a flow key node. +func yaml_emitter_emit_flow_mapping_key(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool { + if first { + if !yaml_emitter_write_indicator(emitter, []byte{'{'}, true, true, false) { + return false + } + if !yaml_emitter_increase_indent(emitter, true, false) { + return false + } + emitter.flow_level++ + } + + if event.typ == yaml_MAPPING_END_EVENT { + emitter.flow_level-- + emitter.indent = emitter.indents[len(emitter.indents)-1] + emitter.indents = emitter.indents[:len(emitter.indents)-1] + if emitter.canonical && !first { + if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) { + return false + } + if !yaml_emitter_write_indent(emitter) { + return false + } + } + if !yaml_emitter_write_indicator(emitter, []byte{'}'}, false, false, false) { + return false + } + emitter.state = emitter.states[len(emitter.states)-1] + emitter.states = emitter.states[:len(emitter.states)-1] + return true + } + + if !first { + if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) { + return false + } + } + if emitter.canonical || emitter.column > emitter.best_width { + if !yaml_emitter_write_indent(emitter) { + return false + } + } + + if !emitter.canonical && yaml_emitter_check_simple_key(emitter) { + emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE) + return yaml_emitter_emit_node(emitter, event, false, false, true, true) + } + if !yaml_emitter_write_indicator(emitter, []byte{'?'}, true, false, false) { + return false + } + emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_VALUE_STATE) + return yaml_emitter_emit_node(emitter, event, false, false, true, false) +} + +// Expect a flow value node. +func yaml_emitter_emit_flow_mapping_value(emitter *yaml_emitter_t, event *yaml_event_t, simple bool) bool { + if simple { + if !yaml_emitter_write_indicator(emitter, []byte{':'}, false, false, false) { + return false + } + } else { + if emitter.canonical || emitter.column > emitter.best_width { + if !yaml_emitter_write_indent(emitter) { + return false + } + } + if !yaml_emitter_write_indicator(emitter, []byte{':'}, true, false, false) { + return false + } + } + emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_KEY_STATE) + return yaml_emitter_emit_node(emitter, event, false, false, true, false) +} + +// Expect a block item node. +func yaml_emitter_emit_block_sequence_item(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool { + if first { + if !yaml_emitter_increase_indent(emitter, false, emitter.mapping_context && !emitter.indention) { + return false + } + } + if event.typ == yaml_SEQUENCE_END_EVENT { + emitter.indent = emitter.indents[len(emitter.indents)-1] + emitter.indents = emitter.indents[:len(emitter.indents)-1] + emitter.state = emitter.states[len(emitter.states)-1] + emitter.states = emitter.states[:len(emitter.states)-1] + return true + } + if !yaml_emitter_write_indent(emitter) { + return false + } + if !yaml_emitter_write_indicator(emitter, []byte{'-'}, true, false, true) { + return false + } + emitter.states = append(emitter.states, yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE) + return yaml_emitter_emit_node(emitter, event, false, true, false, false) +} + +// Expect a block key node. +func yaml_emitter_emit_block_mapping_key(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool { + if first { + if !yaml_emitter_increase_indent(emitter, false, false) { + return false + } + } + if event.typ == yaml_MAPPING_END_EVENT { + emitter.indent = emitter.indents[len(emitter.indents)-1] + emitter.indents = emitter.indents[:len(emitter.indents)-1] + emitter.state = emitter.states[len(emitter.states)-1] + emitter.states = emitter.states[:len(emitter.states)-1] + return true + } + if !yaml_emitter_write_indent(emitter) { + return false + } + if yaml_emitter_check_simple_key(emitter) { + emitter.states = append(emitter.states, yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE) + return yaml_emitter_emit_node(emitter, event, false, false, true, true) + } + if !yaml_emitter_write_indicator(emitter, []byte{'?'}, true, false, true) { + return false + } + emitter.states = append(emitter.states, yaml_EMIT_BLOCK_MAPPING_VALUE_STATE) + return yaml_emitter_emit_node(emitter, event, false, false, true, false) +} + +// Expect a block value node. +func yaml_emitter_emit_block_mapping_value(emitter *yaml_emitter_t, event *yaml_event_t, simple bool) bool { + if simple { + if !yaml_emitter_write_indicator(emitter, []byte{':'}, false, false, false) { + return false + } + } else { + if !yaml_emitter_write_indent(emitter) { + return false + } + if !yaml_emitter_write_indicator(emitter, []byte{':'}, true, false, true) { + return false + } + } + emitter.states = append(emitter.states, yaml_EMIT_BLOCK_MAPPING_KEY_STATE) + return yaml_emitter_emit_node(emitter, event, false, false, true, false) +} + +// Expect a node. +func yaml_emitter_emit_node(emitter *yaml_emitter_t, event *yaml_event_t, + root bool, sequence bool, mapping bool, simple_key bool) bool { + + emitter.root_context = root + emitter.sequence_context = sequence + emitter.mapping_context = mapping + emitter.simple_key_context = simple_key + + switch event.typ { + case yaml_ALIAS_EVENT: + return yaml_emitter_emit_alias(emitter, event) + case yaml_SCALAR_EVENT: + return yaml_emitter_emit_scalar(emitter, event) + case yaml_SEQUENCE_START_EVENT: + return yaml_emitter_emit_sequence_start(emitter, event) + case yaml_MAPPING_START_EVENT: + return yaml_emitter_emit_mapping_start(emitter, event) + default: + return yaml_emitter_set_emitter_error(emitter, + fmt.Sprintf("expected SCALAR, SEQUENCE-START, MAPPING-START, or ALIAS, but got %v", event.typ)) + } +} + +// Expect ALIAS. +func yaml_emitter_emit_alias(emitter *yaml_emitter_t, event *yaml_event_t) bool { + if !yaml_emitter_process_anchor(emitter) { + return false + } + emitter.state = emitter.states[len(emitter.states)-1] + emitter.states = emitter.states[:len(emitter.states)-1] + return true +} + +// Expect SCALAR. +func yaml_emitter_emit_scalar(emitter *yaml_emitter_t, event *yaml_event_t) bool { + if !yaml_emitter_select_scalar_style(emitter, event) { + return false + } + if !yaml_emitter_process_anchor(emitter) { + return false + } + if !yaml_emitter_process_tag(emitter) { + return false + } + if !yaml_emitter_increase_indent(emitter, true, false) { + return false + } + if !yaml_emitter_process_scalar(emitter) { + return false + } + emitter.indent = emitter.indents[len(emitter.indents)-1] + emitter.indents = emitter.indents[:len(emitter.indents)-1] + emitter.state = emitter.states[len(emitter.states)-1] + emitter.states = emitter.states[:len(emitter.states)-1] + return true +} + +// Expect SEQUENCE-START. +func yaml_emitter_emit_sequence_start(emitter *yaml_emitter_t, event *yaml_event_t) bool { + if !yaml_emitter_process_anchor(emitter) { + return false + } + if !yaml_emitter_process_tag(emitter) { + return false + } + if emitter.flow_level > 0 || emitter.canonical || event.sequence_style() == yaml_FLOW_SEQUENCE_STYLE || + yaml_emitter_check_empty_sequence(emitter) { + emitter.state = yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE + } else { + emitter.state = yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE + } + return true +} + +// Expect MAPPING-START. +func yaml_emitter_emit_mapping_start(emitter *yaml_emitter_t, event *yaml_event_t) bool { + if !yaml_emitter_process_anchor(emitter) { + return false + } + if !yaml_emitter_process_tag(emitter) { + return false + } + if emitter.flow_level > 0 || emitter.canonical || event.mapping_style() == yaml_FLOW_MAPPING_STYLE || + yaml_emitter_check_empty_mapping(emitter) { + emitter.state = yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE + } else { + emitter.state = yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE + } + return true +} + +// Check if the document content is an empty scalar. +func yaml_emitter_check_empty_document(emitter *yaml_emitter_t) bool { + return false // [Go] Huh? +} + +// Check if the next events represent an empty sequence. +func yaml_emitter_check_empty_sequence(emitter *yaml_emitter_t) bool { + if len(emitter.events)-emitter.events_head < 2 { + return false + } + return emitter.events[emitter.events_head].typ == yaml_SEQUENCE_START_EVENT && + emitter.events[emitter.events_head+1].typ == yaml_SEQUENCE_END_EVENT +} + +// Check if the next events represent an empty mapping. +func yaml_emitter_check_empty_mapping(emitter *yaml_emitter_t) bool { + if len(emitter.events)-emitter.events_head < 2 { + return false + } + return emitter.events[emitter.events_head].typ == yaml_MAPPING_START_EVENT && + emitter.events[emitter.events_head+1].typ == yaml_MAPPING_END_EVENT +} + +// Check if the next node can be expressed as a simple key. +func yaml_emitter_check_simple_key(emitter *yaml_emitter_t) bool { + length := 0 + switch emitter.events[emitter.events_head].typ { + case yaml_ALIAS_EVENT: + length += len(emitter.anchor_data.anchor) + case yaml_SCALAR_EVENT: + if emitter.scalar_data.multiline { + return false + } + length += len(emitter.anchor_data.anchor) + + len(emitter.tag_data.handle) + + len(emitter.tag_data.suffix) + + len(emitter.scalar_data.value) + case yaml_SEQUENCE_START_EVENT: + if !yaml_emitter_check_empty_sequence(emitter) { + return false + } + length += len(emitter.anchor_data.anchor) + + len(emitter.tag_data.handle) + + len(emitter.tag_data.suffix) + case yaml_MAPPING_START_EVENT: + if !yaml_emitter_check_empty_mapping(emitter) { + return false + } + length += len(emitter.anchor_data.anchor) + + len(emitter.tag_data.handle) + + len(emitter.tag_data.suffix) + default: + return false + } + return length <= 128 +} + +// Determine an acceptable scalar style. +func yaml_emitter_select_scalar_style(emitter *yaml_emitter_t, event *yaml_event_t) bool { + + no_tag := len(emitter.tag_data.handle) == 0 && len(emitter.tag_data.suffix) == 0 + if no_tag && !event.implicit && !event.quoted_implicit { + return yaml_emitter_set_emitter_error(emitter, "neither tag nor implicit flags are specified") + } + + style := event.scalar_style() + if style == yaml_ANY_SCALAR_STYLE { + style = yaml_PLAIN_SCALAR_STYLE + } + if emitter.canonical { + style = yaml_DOUBLE_QUOTED_SCALAR_STYLE + } + if emitter.simple_key_context && emitter.scalar_data.multiline { + style = yaml_DOUBLE_QUOTED_SCALAR_STYLE + } + + if style == yaml_PLAIN_SCALAR_STYLE { + if emitter.flow_level > 0 && !emitter.scalar_data.flow_plain_allowed || + emitter.flow_level == 0 && !emitter.scalar_data.block_plain_allowed { + style = yaml_SINGLE_QUOTED_SCALAR_STYLE + } + if len(emitter.scalar_data.value) == 0 && (emitter.flow_level > 0 || emitter.simple_key_context) { + style = yaml_SINGLE_QUOTED_SCALAR_STYLE + } + if no_tag && !event.implicit { + style = yaml_SINGLE_QUOTED_SCALAR_STYLE + } + } + if style == yaml_SINGLE_QUOTED_SCALAR_STYLE { + if !emitter.scalar_data.single_quoted_allowed { + style = yaml_DOUBLE_QUOTED_SCALAR_STYLE + } + } + if style == yaml_LITERAL_SCALAR_STYLE || style == yaml_FOLDED_SCALAR_STYLE { + if !emitter.scalar_data.block_allowed || emitter.flow_level > 0 || emitter.simple_key_context { + style = yaml_DOUBLE_QUOTED_SCALAR_STYLE + } + } + + if no_tag && !event.quoted_implicit && style != yaml_PLAIN_SCALAR_STYLE { + emitter.tag_data.handle = []byte{'!'} + } + emitter.scalar_data.style = style + return true +} + +// Write an anchor. +func yaml_emitter_process_anchor(emitter *yaml_emitter_t) bool { + if emitter.anchor_data.anchor == nil { + return true + } + c := []byte{'&'} + if emitter.anchor_data.alias { + c[0] = '*' + } + if !yaml_emitter_write_indicator(emitter, c, true, false, false) { + return false + } + return yaml_emitter_write_anchor(emitter, emitter.anchor_data.anchor) +} + +// Write a tag. +func yaml_emitter_process_tag(emitter *yaml_emitter_t) bool { + if len(emitter.tag_data.handle) == 0 && len(emitter.tag_data.suffix) == 0 { + return true + } + if len(emitter.tag_data.handle) > 0 { + if !yaml_emitter_write_tag_handle(emitter, emitter.tag_data.handle) { + return false + } + if len(emitter.tag_data.suffix) > 0 { + if !yaml_emitter_write_tag_content(emitter, emitter.tag_data.suffix, false) { + return false + } + } + } else { + // [Go] Allocate these slices elsewhere. + if !yaml_emitter_write_indicator(emitter, []byte("!<"), true, false, false) { + return false + } + if !yaml_emitter_write_tag_content(emitter, emitter.tag_data.suffix, false) { + return false + } + if !yaml_emitter_write_indicator(emitter, []byte{'>'}, false, false, false) { + return false + } + } + return true +} + +// Write a scalar. +func yaml_emitter_process_scalar(emitter *yaml_emitter_t) bool { + switch emitter.scalar_data.style { + case yaml_PLAIN_SCALAR_STYLE: + return yaml_emitter_write_plain_scalar(emitter, emitter.scalar_data.value, !emitter.simple_key_context) + + case yaml_SINGLE_QUOTED_SCALAR_STYLE: + return yaml_emitter_write_single_quoted_scalar(emitter, emitter.scalar_data.value, !emitter.simple_key_context) + + case yaml_DOUBLE_QUOTED_SCALAR_STYLE: + return yaml_emitter_write_double_quoted_scalar(emitter, emitter.scalar_data.value, !emitter.simple_key_context) + + case yaml_LITERAL_SCALAR_STYLE: + return yaml_emitter_write_literal_scalar(emitter, emitter.scalar_data.value) + + case yaml_FOLDED_SCALAR_STYLE: + return yaml_emitter_write_folded_scalar(emitter, emitter.scalar_data.value) + } + panic("unknown scalar style") +} + +// Check if a %YAML directive is valid. +func yaml_emitter_analyze_version_directive(emitter *yaml_emitter_t, version_directive *yaml_version_directive_t) bool { + if version_directive.major != 1 || version_directive.minor != 1 { + return yaml_emitter_set_emitter_error(emitter, "incompatible %YAML directive") + } + return true +} + +// Check if a %TAG directive is valid. +func yaml_emitter_analyze_tag_directive(emitter *yaml_emitter_t, tag_directive *yaml_tag_directive_t) bool { + handle := tag_directive.handle + prefix := tag_directive.prefix + if len(handle) == 0 { + return yaml_emitter_set_emitter_error(emitter, "tag handle must not be empty") + } + if handle[0] != '!' { + return yaml_emitter_set_emitter_error(emitter, "tag handle must start with '!'") + } + if handle[len(handle)-1] != '!' { + return yaml_emitter_set_emitter_error(emitter, "tag handle must end with '!'") + } + for i := 1; i < len(handle)-1; i += width(handle[i]) { + if !is_alpha(handle, i) { + return yaml_emitter_set_emitter_error(emitter, "tag handle must contain alphanumerical characters only") + } + } + if len(prefix) == 0 { + return yaml_emitter_set_emitter_error(emitter, "tag prefix must not be empty") + } + return true +} + +// Check if an anchor is valid. +func yaml_emitter_analyze_anchor(emitter *yaml_emitter_t, anchor []byte, alias bool) bool { + if len(anchor) == 0 { + problem := "anchor value must not be empty" + if alias { + problem = "alias value must not be empty" + } + return yaml_emitter_set_emitter_error(emitter, problem) + } + for i := 0; i < len(anchor); i += width(anchor[i]) { + if !is_alpha(anchor, i) { + problem := "anchor value must contain alphanumerical characters only" + if alias { + problem = "alias value must contain alphanumerical characters only" + } + return yaml_emitter_set_emitter_error(emitter, problem) + } + } + emitter.anchor_data.anchor = anchor + emitter.anchor_data.alias = alias + return true +} + +// Check if a tag is valid. +func yaml_emitter_analyze_tag(emitter *yaml_emitter_t, tag []byte) bool { + if len(tag) == 0 { + return yaml_emitter_set_emitter_error(emitter, "tag value must not be empty") + } + for i := 0; i < len(emitter.tag_directives); i++ { + tag_directive := &emitter.tag_directives[i] + if bytes.HasPrefix(tag, tag_directive.prefix) { + emitter.tag_data.handle = tag_directive.handle + emitter.tag_data.suffix = tag[len(tag_directive.prefix):] + return true + } + } + emitter.tag_data.suffix = tag + return true +} + +// Check if a scalar is valid. +func yaml_emitter_analyze_scalar(emitter *yaml_emitter_t, value []byte) bool { + var ( + block_indicators = false + flow_indicators = false + line_breaks = false + special_characters = false + + leading_space = false + leading_break = false + trailing_space = false + trailing_break = false + break_space = false + space_break = false + + preceded_by_whitespace = false + followed_by_whitespace = false + previous_space = false + previous_break = false + ) + + emitter.scalar_data.value = value + + if len(value) == 0 { + emitter.scalar_data.multiline = false + emitter.scalar_data.flow_plain_allowed = false + emitter.scalar_data.block_plain_allowed = true + emitter.scalar_data.single_quoted_allowed = true + emitter.scalar_data.block_allowed = false + return true + } + + if len(value) >= 3 && ((value[0] == '-' && value[1] == '-' && value[2] == '-') || (value[0] == '.' && value[1] == '.' && value[2] == '.')) { + block_indicators = true + flow_indicators = true + } + + preceded_by_whitespace = true + for i, w := 0, 0; i < len(value); i += w { + w = width(value[i]) + followed_by_whitespace = i+w >= len(value) || is_blank(value, i+w) + + if i == 0 { + switch value[i] { + case '#', ',', '[', ']', '{', '}', '&', '*', '!', '|', '>', '\'', '"', '%', '@', '`': + flow_indicators = true + block_indicators = true + case '?', ':': + flow_indicators = true + if followed_by_whitespace { + block_indicators = true + } + case '-': + if followed_by_whitespace { + flow_indicators = true + block_indicators = true + } + } + } else { + switch value[i] { + case ',', '?', '[', ']', '{', '}': + flow_indicators = true + case ':': + flow_indicators = true + if followed_by_whitespace { + block_indicators = true + } + case '#': + if preceded_by_whitespace { + flow_indicators = true + block_indicators = true + } + } + } + + if !is_printable(value, i) || !is_ascii(value, i) && !emitter.unicode { + special_characters = true + } + if is_space(value, i) { + if i == 0 { + leading_space = true + } + if i+width(value[i]) == len(value) { + trailing_space = true + } + if previous_break { + break_space = true + } + previous_space = true + previous_break = false + } else if is_break(value, i) { + line_breaks = true + if i == 0 { + leading_break = true + } + if i+width(value[i]) == len(value) { + trailing_break = true + } + if previous_space { + space_break = true + } + previous_space = false + previous_break = true + } else { + previous_space = false + previous_break = false + } + + // [Go]: Why 'z'? Couldn't be the end of the string as that's the loop condition. + preceded_by_whitespace = is_blankz(value, i) + } + + emitter.scalar_data.multiline = line_breaks + emitter.scalar_data.flow_plain_allowed = true + emitter.scalar_data.block_plain_allowed = true + emitter.scalar_data.single_quoted_allowed = true + emitter.scalar_data.block_allowed = true + + if leading_space || leading_break || trailing_space || trailing_break { + emitter.scalar_data.flow_plain_allowed = false + emitter.scalar_data.block_plain_allowed = false + } + if trailing_space { + emitter.scalar_data.block_allowed = false + } + if break_space { + emitter.scalar_data.flow_plain_allowed = false + emitter.scalar_data.block_plain_allowed = false + emitter.scalar_data.single_quoted_allowed = false + } + if space_break || special_characters { + emitter.scalar_data.flow_plain_allowed = false + emitter.scalar_data.block_plain_allowed = false + emitter.scalar_data.single_quoted_allowed = false + emitter.scalar_data.block_allowed = false + } + if line_breaks { + emitter.scalar_data.flow_plain_allowed = false + emitter.scalar_data.block_plain_allowed = false + } + if flow_indicators { + emitter.scalar_data.flow_plain_allowed = false + } + if block_indicators { + emitter.scalar_data.block_plain_allowed = false + } + return true +} + +// Check if the event data is valid. +func yaml_emitter_analyze_event(emitter *yaml_emitter_t, event *yaml_event_t) bool { + + emitter.anchor_data.anchor = nil + emitter.tag_data.handle = nil + emitter.tag_data.suffix = nil + emitter.scalar_data.value = nil + + switch event.typ { + case yaml_ALIAS_EVENT: + if !yaml_emitter_analyze_anchor(emitter, event.anchor, true) { + return false + } + + case yaml_SCALAR_EVENT: + if len(event.anchor) > 0 { + if !yaml_emitter_analyze_anchor(emitter, event.anchor, false) { + return false + } + } + if len(event.tag) > 0 && (emitter.canonical || (!event.implicit && !event.quoted_implicit)) { + if !yaml_emitter_analyze_tag(emitter, event.tag) { + return false + } + } + if !yaml_emitter_analyze_scalar(emitter, event.value) { + return false + } + + case yaml_SEQUENCE_START_EVENT: + if len(event.anchor) > 0 { + if !yaml_emitter_analyze_anchor(emitter, event.anchor, false) { + return false + } + } + if len(event.tag) > 0 && (emitter.canonical || !event.implicit) { + if !yaml_emitter_analyze_tag(emitter, event.tag) { + return false + } + } + + case yaml_MAPPING_START_EVENT: + if len(event.anchor) > 0 { + if !yaml_emitter_analyze_anchor(emitter, event.anchor, false) { + return false + } + } + if len(event.tag) > 0 && (emitter.canonical || !event.implicit) { + if !yaml_emitter_analyze_tag(emitter, event.tag) { + return false + } + } + } + return true +} + +// Write the BOM character. +func yaml_emitter_write_bom(emitter *yaml_emitter_t) bool { + if !flush(emitter) { + return false + } + pos := emitter.buffer_pos + emitter.buffer[pos+0] = '\xEF' + emitter.buffer[pos+1] = '\xBB' + emitter.buffer[pos+2] = '\xBF' + emitter.buffer_pos += 3 + return true +} + +func yaml_emitter_write_indent(emitter *yaml_emitter_t) bool { + indent := emitter.indent + if indent < 0 { + indent = 0 + } + if !emitter.indention || emitter.column > indent || (emitter.column == indent && !emitter.whitespace) { + if !put_break(emitter) { + return false + } + } + for emitter.column < indent { + if !put(emitter, ' ') { + return false + } + } + emitter.whitespace = true + emitter.indention = true + return true +} + +func yaml_emitter_write_indicator(emitter *yaml_emitter_t, indicator []byte, need_whitespace, is_whitespace, is_indention bool) bool { + if need_whitespace && !emitter.whitespace { + if !put(emitter, ' ') { + return false + } + } + if !write_all(emitter, indicator) { + return false + } + emitter.whitespace = is_whitespace + emitter.indention = (emitter.indention && is_indention) + emitter.open_ended = false + return true +} + +func yaml_emitter_write_anchor(emitter *yaml_emitter_t, value []byte) bool { + if !write_all(emitter, value) { + return false + } + emitter.whitespace = false + emitter.indention = false + return true +} + +func yaml_emitter_write_tag_handle(emitter *yaml_emitter_t, value []byte) bool { + if !emitter.whitespace { + if !put(emitter, ' ') { + return false + } + } + if !write_all(emitter, value) { + return false + } + emitter.whitespace = false + emitter.indention = false + return true +} + +func yaml_emitter_write_tag_content(emitter *yaml_emitter_t, value []byte, need_whitespace bool) bool { + if need_whitespace && !emitter.whitespace { + if !put(emitter, ' ') { + return false + } + } + for i := 0; i < len(value); { + var must_write bool + switch value[i] { + case ';', '/', '?', ':', '@', '&', '=', '+', '$', ',', '_', '.', '~', '*', '\'', '(', ')', '[', ']': + must_write = true + default: + must_write = is_alpha(value, i) + } + if must_write { + if !write(emitter, value, &i) { + return false + } + } else { + w := width(value[i]) + for k := 0; k < w; k++ { + octet := value[i] + i++ + if !put(emitter, '%') { + return false + } + + c := octet >> 4 + if c < 10 { + c += '0' + } else { + c += 'A' - 10 + } + if !put(emitter, c) { + return false + } + + c = octet & 0x0f + if c < 10 { + c += '0' + } else { + c += 'A' - 10 + } + if !put(emitter, c) { + return false + } + } + } + } + emitter.whitespace = false + emitter.indention = false + return true +} + +func yaml_emitter_write_plain_scalar(emitter *yaml_emitter_t, value []byte, allow_breaks bool) bool { + if !emitter.whitespace { + if !put(emitter, ' ') { + return false + } + } + + spaces := false + breaks := false + for i := 0; i < len(value); { + if is_space(value, i) { + if allow_breaks && !spaces && emitter.column > emitter.best_width && !is_space(value, i+1) { + if !yaml_emitter_write_indent(emitter) { + return false + } + i += width(value[i]) + } else { + if !write(emitter, value, &i) { + return false + } + } + spaces = true + } else if is_break(value, i) { + if !breaks && value[i] == '\n' { + if !put_break(emitter) { + return false + } + } + if !write_break(emitter, value, &i) { + return false + } + emitter.indention = true + breaks = true + } else { + if breaks { + if !yaml_emitter_write_indent(emitter) { + return false + } + } + if !write(emitter, value, &i) { + return false + } + emitter.indention = false + spaces = false + breaks = false + } + } + + emitter.whitespace = false + emitter.indention = false + if emitter.root_context { + emitter.open_ended = true + } + + return true +} + +func yaml_emitter_write_single_quoted_scalar(emitter *yaml_emitter_t, value []byte, allow_breaks bool) bool { + + if !yaml_emitter_write_indicator(emitter, []byte{'\''}, true, false, false) { + return false + } + + spaces := false + breaks := false + for i := 0; i < len(value); { + if is_space(value, i) { + if allow_breaks && !spaces && emitter.column > emitter.best_width && i > 0 && i < len(value)-1 && !is_space(value, i+1) { + if !yaml_emitter_write_indent(emitter) { + return false + } + i += width(value[i]) + } else { + if !write(emitter, value, &i) { + return false + } + } + spaces = true + } else if is_break(value, i) { + if !breaks && value[i] == '\n' { + if !put_break(emitter) { + return false + } + } + if !write_break(emitter, value, &i) { + return false + } + emitter.indention = true + breaks = true + } else { + if breaks { + if !yaml_emitter_write_indent(emitter) { + return false + } + } + if value[i] == '\'' { + if !put(emitter, '\'') { + return false + } + } + if !write(emitter, value, &i) { + return false + } + emitter.indention = false + spaces = false + breaks = false + } + } + if !yaml_emitter_write_indicator(emitter, []byte{'\''}, false, false, false) { + return false + } + emitter.whitespace = false + emitter.indention = false + return true +} + +func yaml_emitter_write_double_quoted_scalar(emitter *yaml_emitter_t, value []byte, allow_breaks bool) bool { + spaces := false + if !yaml_emitter_write_indicator(emitter, []byte{'"'}, true, false, false) { + return false + } + + for i := 0; i < len(value); { + if !is_printable(value, i) || (!emitter.unicode && !is_ascii(value, i)) || + is_bom(value, i) || is_break(value, i) || + value[i] == '"' || value[i] == '\\' { + + octet := value[i] + + var w int + var v rune + switch { + case octet&0x80 == 0x00: + w, v = 1, rune(octet&0x7F) + case octet&0xE0 == 0xC0: + w, v = 2, rune(octet&0x1F) + case octet&0xF0 == 0xE0: + w, v = 3, rune(octet&0x0F) + case octet&0xF8 == 0xF0: + w, v = 4, rune(octet&0x07) + } + for k := 1; k < w; k++ { + octet = value[i+k] + v = (v << 6) + (rune(octet) & 0x3F) + } + i += w + + if !put(emitter, '\\') { + return false + } + + var ok bool + switch v { + case 0x00: + ok = put(emitter, '0') + case 0x07: + ok = put(emitter, 'a') + case 0x08: + ok = put(emitter, 'b') + case 0x09: + ok = put(emitter, 't') + case 0x0A: + ok = put(emitter, 'n') + case 0x0b: + ok = put(emitter, 'v') + case 0x0c: + ok = put(emitter, 'f') + case 0x0d: + ok = put(emitter, 'r') + case 0x1b: + ok = put(emitter, 'e') + case 0x22: + ok = put(emitter, '"') + case 0x5c: + ok = put(emitter, '\\') + case 0x85: + ok = put(emitter, 'N') + case 0xA0: + ok = put(emitter, '_') + case 0x2028: + ok = put(emitter, 'L') + case 0x2029: + ok = put(emitter, 'P') + default: + if v <= 0xFF { + ok = put(emitter, 'x') + w = 2 + } else if v <= 0xFFFF { + ok = put(emitter, 'u') + w = 4 + } else { + ok = put(emitter, 'U') + w = 8 + } + for k := (w - 1) * 4; ok && k >= 0; k -= 4 { + digit := byte((v >> uint(k)) & 0x0F) + if digit < 10 { + ok = put(emitter, digit+'0') + } else { + ok = put(emitter, digit+'A'-10) + } + } + } + if !ok { + return false + } + spaces = false + } else if is_space(value, i) { + if allow_breaks && !spaces && emitter.column > emitter.best_width && i > 0 && i < len(value)-1 { + if !yaml_emitter_write_indent(emitter) { + return false + } + if is_space(value, i+1) { + if !put(emitter, '\\') { + return false + } + } + i += width(value[i]) + } else if !write(emitter, value, &i) { + return false + } + spaces = true + } else { + if !write(emitter, value, &i) { + return false + } + spaces = false + } + } + if !yaml_emitter_write_indicator(emitter, []byte{'"'}, false, false, false) { + return false + } + emitter.whitespace = false + emitter.indention = false + return true +} + +func yaml_emitter_write_block_scalar_hints(emitter *yaml_emitter_t, value []byte) bool { + if is_space(value, 0) || is_break(value, 0) { + indent_hint := []byte{'0' + byte(emitter.best_indent)} + if !yaml_emitter_write_indicator(emitter, indent_hint, false, false, false) { + return false + } + } + + emitter.open_ended = false + + var chomp_hint [1]byte + if len(value) == 0 { + chomp_hint[0] = '-' + } else { + i := len(value) - 1 + for value[i]&0xC0 == 0x80 { + i-- + } + if !is_break(value, i) { + chomp_hint[0] = '-' + } else if i == 0 { + chomp_hint[0] = '+' + emitter.open_ended = true + } else { + i-- + for value[i]&0xC0 == 0x80 { + i-- + } + if is_break(value, i) { + chomp_hint[0] = '+' + emitter.open_ended = true + } + } + } + if chomp_hint[0] != 0 { + if !yaml_emitter_write_indicator(emitter, chomp_hint[:], false, false, false) { + return false + } + } + return true +} + +func yaml_emitter_write_literal_scalar(emitter *yaml_emitter_t, value []byte) bool { + if !yaml_emitter_write_indicator(emitter, []byte{'|'}, true, false, false) { + return false + } + if !yaml_emitter_write_block_scalar_hints(emitter, value) { + return false + } + if !put_break(emitter) { + return false + } + emitter.indention = true + emitter.whitespace = true + breaks := true + for i := 0; i < len(value); { + if is_break(value, i) { + if !write_break(emitter, value, &i) { + return false + } + emitter.indention = true + breaks = true + } else { + if breaks { + if !yaml_emitter_write_indent(emitter) { + return false + } + } + if !write(emitter, value, &i) { + return false + } + emitter.indention = false + breaks = false + } + } + + return true +} + +func yaml_emitter_write_folded_scalar(emitter *yaml_emitter_t, value []byte) bool { + if !yaml_emitter_write_indicator(emitter, []byte{'>'}, true, false, false) { + return false + } + if !yaml_emitter_write_block_scalar_hints(emitter, value) { + return false + } + + if !put_break(emitter) { + return false + } + emitter.indention = true + emitter.whitespace = true + + breaks := true + leading_spaces := true + for i := 0; i < len(value); { + if is_break(value, i) { + if !breaks && !leading_spaces && value[i] == '\n' { + k := 0 + for is_break(value, k) { + k += width(value[k]) + } + if !is_blankz(value, k) { + if !put_break(emitter) { + return false + } + } + } + if !write_break(emitter, value, &i) { + return false + } + emitter.indention = true + breaks = true + } else { + if breaks { + if !yaml_emitter_write_indent(emitter) { + return false + } + leading_spaces = is_blank(value, i) + } + if !breaks && is_space(value, i) && !is_space(value, i+1) && emitter.column > emitter.best_width { + if !yaml_emitter_write_indent(emitter) { + return false + } + i += width(value[i]) + } else { + if !write(emitter, value, &i) { + return false + } + } + emitter.indention = false + breaks = false + } + } + return true +} diff --git a/vendor/sigs.k8s.io/yaml/goyaml.v2/encode.go b/vendor/sigs.k8s.io/yaml/goyaml.v2/encode.go new file mode 100644 index 000000000..0ee738e11 --- /dev/null +++ b/vendor/sigs.k8s.io/yaml/goyaml.v2/encode.go @@ -0,0 +1,390 @@ +package yaml + +import ( + "encoding" + "fmt" + "io" + "reflect" + "regexp" + "sort" + "strconv" + "strings" + "time" + "unicode/utf8" +) + +// jsonNumber is the interface of the encoding/json.Number datatype. +// Repeating the interface here avoids a dependency on encoding/json, and also +// supports other libraries like jsoniter, which use a similar datatype with +// the same interface. Detecting this interface is useful when dealing with +// structures containing json.Number, which is a string under the hood. The +// encoder should prefer the use of Int64(), Float64() and string(), in that +// order, when encoding this type. +type jsonNumber interface { + Float64() (float64, error) + Int64() (int64, error) + String() string +} + +type encoder struct { + emitter yaml_emitter_t + event yaml_event_t + out []byte + flow bool + // doneInit holds whether the initial stream_start_event has been + // emitted. + doneInit bool +} + +func newEncoder() *encoder { + e := &encoder{} + yaml_emitter_initialize(&e.emitter) + yaml_emitter_set_output_string(&e.emitter, &e.out) + yaml_emitter_set_unicode(&e.emitter, true) + return e +} + +func newEncoderWithWriter(w io.Writer) *encoder { + e := &encoder{} + yaml_emitter_initialize(&e.emitter) + yaml_emitter_set_output_writer(&e.emitter, w) + yaml_emitter_set_unicode(&e.emitter, true) + return e +} + +func (e *encoder) init() { + if e.doneInit { + return + } + yaml_stream_start_event_initialize(&e.event, yaml_UTF8_ENCODING) + e.emit() + e.doneInit = true +} + +func (e *encoder) finish() { + e.emitter.open_ended = false + yaml_stream_end_event_initialize(&e.event) + e.emit() +} + +func (e *encoder) destroy() { + yaml_emitter_delete(&e.emitter) +} + +func (e *encoder) emit() { + // This will internally delete the e.event value. + e.must(yaml_emitter_emit(&e.emitter, &e.event)) +} + +func (e *encoder) must(ok bool) { + if !ok { + msg := e.emitter.problem + if msg == "" { + msg = "unknown problem generating YAML content" + } + failf("%s", msg) + } +} + +func (e *encoder) marshalDoc(tag string, in reflect.Value) { + e.init() + yaml_document_start_event_initialize(&e.event, nil, nil, true) + e.emit() + e.marshal(tag, in) + yaml_document_end_event_initialize(&e.event, true) + e.emit() +} + +func (e *encoder) marshal(tag string, in reflect.Value) { + if !in.IsValid() || in.Kind() == reflect.Ptr && in.IsNil() { + e.nilv() + return + } + iface := in.Interface() + switch m := iface.(type) { + case jsonNumber: + integer, err := m.Int64() + if err == nil { + // In this case the json.Number is a valid int64 + in = reflect.ValueOf(integer) + break + } + float, err := m.Float64() + if err == nil { + // In this case the json.Number is a valid float64 + in = reflect.ValueOf(float) + break + } + // fallback case - no number could be obtained + in = reflect.ValueOf(m.String()) + case time.Time, *time.Time: + // Although time.Time implements TextMarshaler, + // we don't want to treat it as a string for YAML + // purposes because YAML has special support for + // timestamps. + case Marshaler: + v, err := m.MarshalYAML() + if err != nil { + fail(err) + } + if v == nil { + e.nilv() + return + } + in = reflect.ValueOf(v) + case encoding.TextMarshaler: + text, err := m.MarshalText() + if err != nil { + fail(err) + } + in = reflect.ValueOf(string(text)) + case nil: + e.nilv() + return + } + switch in.Kind() { + case reflect.Interface: + e.marshal(tag, in.Elem()) + case reflect.Map: + e.mapv(tag, in) + case reflect.Ptr: + if in.Type() == ptrTimeType { + e.timev(tag, in.Elem()) + } else { + e.marshal(tag, in.Elem()) + } + case reflect.Struct: + if in.Type() == timeType { + e.timev(tag, in) + } else { + e.structv(tag, in) + } + case reflect.Slice, reflect.Array: + if in.Type().Elem() == mapItemType { + e.itemsv(tag, in) + } else { + e.slicev(tag, in) + } + case reflect.String: + e.stringv(tag, in) + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + if in.Type() == durationType { + e.stringv(tag, reflect.ValueOf(iface.(time.Duration).String())) + } else { + e.intv(tag, in) + } + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + e.uintv(tag, in) + case reflect.Float32, reflect.Float64: + e.floatv(tag, in) + case reflect.Bool: + e.boolv(tag, in) + default: + panic("cannot marshal type: " + in.Type().String()) + } +} + +func (e *encoder) mapv(tag string, in reflect.Value) { + e.mappingv(tag, func() { + keys := keyList(in.MapKeys()) + sort.Sort(keys) + for _, k := range keys { + e.marshal("", k) + e.marshal("", in.MapIndex(k)) + } + }) +} + +func (e *encoder) itemsv(tag string, in reflect.Value) { + e.mappingv(tag, func() { + slice := in.Convert(reflect.TypeOf([]MapItem{})).Interface().([]MapItem) + for _, item := range slice { + e.marshal("", reflect.ValueOf(item.Key)) + e.marshal("", reflect.ValueOf(item.Value)) + } + }) +} + +func (e *encoder) structv(tag string, in reflect.Value) { + sinfo, err := getStructInfo(in.Type()) + if err != nil { + panic(err) + } + e.mappingv(tag, func() { + for _, info := range sinfo.FieldsList { + var value reflect.Value + if info.Inline == nil { + value = in.Field(info.Num) + } else { + value = in.FieldByIndex(info.Inline) + } + if info.OmitEmpty && isZero(value) { + continue + } + e.marshal("", reflect.ValueOf(info.Key)) + e.flow = info.Flow + e.marshal("", value) + } + if sinfo.InlineMap >= 0 { + m := in.Field(sinfo.InlineMap) + if m.Len() > 0 { + e.flow = false + keys := keyList(m.MapKeys()) + sort.Sort(keys) + for _, k := range keys { + if _, found := sinfo.FieldsMap[k.String()]; found { + panic(fmt.Sprintf("Can't have key %q in inlined map; conflicts with struct field", k.String())) + } + e.marshal("", k) + e.flow = false + e.marshal("", m.MapIndex(k)) + } + } + } + }) +} + +func (e *encoder) mappingv(tag string, f func()) { + implicit := tag == "" + style := yaml_BLOCK_MAPPING_STYLE + if e.flow { + e.flow = false + style = yaml_FLOW_MAPPING_STYLE + } + yaml_mapping_start_event_initialize(&e.event, nil, []byte(tag), implicit, style) + e.emit() + f() + yaml_mapping_end_event_initialize(&e.event) + e.emit() +} + +func (e *encoder) slicev(tag string, in reflect.Value) { + implicit := tag == "" + style := yaml_BLOCK_SEQUENCE_STYLE + if e.flow { + e.flow = false + style = yaml_FLOW_SEQUENCE_STYLE + } + e.must(yaml_sequence_start_event_initialize(&e.event, nil, []byte(tag), implicit, style)) + e.emit() + n := in.Len() + for i := 0; i < n; i++ { + e.marshal("", in.Index(i)) + } + e.must(yaml_sequence_end_event_initialize(&e.event)) + e.emit() +} + +// isBase60 returns whether s is in base 60 notation as defined in YAML 1.1. +// +// The base 60 float notation in YAML 1.1 is a terrible idea and is unsupported +// in YAML 1.2 and by this package, but these should be marshalled quoted for +// the time being for compatibility with other parsers. +func isBase60Float(s string) (result bool) { + // Fast path. + if s == "" { + return false + } + c := s[0] + if !(c == '+' || c == '-' || c >= '0' && c <= '9') || strings.IndexByte(s, ':') < 0 { + return false + } + // Do the full match. + return base60float.MatchString(s) +} + +// From http://yaml.org/type/float.html, except the regular expression there +// is bogus. In practice parsers do not enforce the "\.[0-9_]*" suffix. +var base60float = regexp.MustCompile(`^[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+(?:\.[0-9_]*)?$`) + +func (e *encoder) stringv(tag string, in reflect.Value) { + var style yaml_scalar_style_t + s := in.String() + canUsePlain := true + switch { + case !utf8.ValidString(s): + if tag == yaml_BINARY_TAG { + failf("explicitly tagged !!binary data must be base64-encoded") + } + if tag != "" { + failf("cannot marshal invalid UTF-8 data as %s", shortTag(tag)) + } + // It can't be encoded directly as YAML so use a binary tag + // and encode it as base64. + tag = yaml_BINARY_TAG + s = encodeBase64(s) + case tag == "": + // Check to see if it would resolve to a specific + // tag when encoded unquoted. If it doesn't, + // there's no need to quote it. + rtag, _ := resolve("", s) + canUsePlain = rtag == yaml_STR_TAG && !isBase60Float(s) + } + // Note: it's possible for user code to emit invalid YAML + // if they explicitly specify a tag and a string containing + // text that's incompatible with that tag. + switch { + case strings.Contains(s, "\n"): + style = yaml_LITERAL_SCALAR_STYLE + case canUsePlain: + style = yaml_PLAIN_SCALAR_STYLE + default: + style = yaml_DOUBLE_QUOTED_SCALAR_STYLE + } + e.emitScalar(s, "", tag, style) +} + +func (e *encoder) boolv(tag string, in reflect.Value) { + var s string + if in.Bool() { + s = "true" + } else { + s = "false" + } + e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE) +} + +func (e *encoder) intv(tag string, in reflect.Value) { + s := strconv.FormatInt(in.Int(), 10) + e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE) +} + +func (e *encoder) uintv(tag string, in reflect.Value) { + s := strconv.FormatUint(in.Uint(), 10) + e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE) +} + +func (e *encoder) timev(tag string, in reflect.Value) { + t := in.Interface().(time.Time) + s := t.Format(time.RFC3339Nano) + e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE) +} + +func (e *encoder) floatv(tag string, in reflect.Value) { + // Issue #352: When formatting, use the precision of the underlying value + precision := 64 + if in.Kind() == reflect.Float32 { + precision = 32 + } + + s := strconv.FormatFloat(in.Float(), 'g', -1, precision) + switch s { + case "+Inf": + s = ".inf" + case "-Inf": + s = "-.inf" + case "NaN": + s = ".nan" + } + e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE) +} + +func (e *encoder) nilv() { + e.emitScalar("null", "", "", yaml_PLAIN_SCALAR_STYLE) +} + +func (e *encoder) emitScalar(value, anchor, tag string, style yaml_scalar_style_t) { + implicit := tag == "" + e.must(yaml_scalar_event_initialize(&e.event, []byte(anchor), []byte(tag), []byte(value), implicit, implicit, style)) + e.emit() +} diff --git a/vendor/sigs.k8s.io/yaml/goyaml.v2/parserc.go b/vendor/sigs.k8s.io/yaml/goyaml.v2/parserc.go new file mode 100644 index 000000000..81d05dfe5 --- /dev/null +++ b/vendor/sigs.k8s.io/yaml/goyaml.v2/parserc.go @@ -0,0 +1,1095 @@ +package yaml + +import ( + "bytes" +) + +// The parser implements the following grammar: +// +// stream ::= STREAM-START implicit_document? explicit_document* STREAM-END +// implicit_document ::= block_node DOCUMENT-END* +// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END* +// block_node_or_indentless_sequence ::= +// ALIAS +// | properties (block_content | indentless_block_sequence)? +// | block_content +// | indentless_block_sequence +// block_node ::= ALIAS +// | properties block_content? +// | block_content +// flow_node ::= ALIAS +// | properties flow_content? +// | flow_content +// properties ::= TAG ANCHOR? | ANCHOR TAG? +// block_content ::= block_collection | flow_collection | SCALAR +// flow_content ::= flow_collection | SCALAR +// block_collection ::= block_sequence | block_mapping +// flow_collection ::= flow_sequence | flow_mapping +// block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END +// indentless_sequence ::= (BLOCK-ENTRY block_node?)+ +// block_mapping ::= BLOCK-MAPPING_START +// ((KEY block_node_or_indentless_sequence?)? +// (VALUE block_node_or_indentless_sequence?)?)* +// BLOCK-END +// flow_sequence ::= FLOW-SEQUENCE-START +// (flow_sequence_entry FLOW-ENTRY)* +// flow_sequence_entry? +// FLOW-SEQUENCE-END +// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? +// flow_mapping ::= FLOW-MAPPING-START +// (flow_mapping_entry FLOW-ENTRY)* +// flow_mapping_entry? +// FLOW-MAPPING-END +// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? + +// Peek the next token in the token queue. +func peek_token(parser *yaml_parser_t) *yaml_token_t { + if parser.token_available || yaml_parser_fetch_more_tokens(parser) { + return &parser.tokens[parser.tokens_head] + } + return nil +} + +// Remove the next token from the queue (must be called after peek_token). +func skip_token(parser *yaml_parser_t) { + parser.token_available = false + parser.tokens_parsed++ + parser.stream_end_produced = parser.tokens[parser.tokens_head].typ == yaml_STREAM_END_TOKEN + parser.tokens_head++ +} + +// Get the next event. +func yaml_parser_parse(parser *yaml_parser_t, event *yaml_event_t) bool { + // Erase the event object. + *event = yaml_event_t{} + + // No events after the end of the stream or error. + if parser.stream_end_produced || parser.error != yaml_NO_ERROR || parser.state == yaml_PARSE_END_STATE { + return true + } + + // Generate the next event. + return yaml_parser_state_machine(parser, event) +} + +// Set parser error. +func yaml_parser_set_parser_error(parser *yaml_parser_t, problem string, problem_mark yaml_mark_t) bool { + parser.error = yaml_PARSER_ERROR + parser.problem = problem + parser.problem_mark = problem_mark + return false +} + +func yaml_parser_set_parser_error_context(parser *yaml_parser_t, context string, context_mark yaml_mark_t, problem string, problem_mark yaml_mark_t) bool { + parser.error = yaml_PARSER_ERROR + parser.context = context + parser.context_mark = context_mark + parser.problem = problem + parser.problem_mark = problem_mark + return false +} + +// State dispatcher. +func yaml_parser_state_machine(parser *yaml_parser_t, event *yaml_event_t) bool { + //trace("yaml_parser_state_machine", "state:", parser.state.String()) + + switch parser.state { + case yaml_PARSE_STREAM_START_STATE: + return yaml_parser_parse_stream_start(parser, event) + + case yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE: + return yaml_parser_parse_document_start(parser, event, true) + + case yaml_PARSE_DOCUMENT_START_STATE: + return yaml_parser_parse_document_start(parser, event, false) + + case yaml_PARSE_DOCUMENT_CONTENT_STATE: + return yaml_parser_parse_document_content(parser, event) + + case yaml_PARSE_DOCUMENT_END_STATE: + return yaml_parser_parse_document_end(parser, event) + + case yaml_PARSE_BLOCK_NODE_STATE: + return yaml_parser_parse_node(parser, event, true, false) + + case yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE: + return yaml_parser_parse_node(parser, event, true, true) + + case yaml_PARSE_FLOW_NODE_STATE: + return yaml_parser_parse_node(parser, event, false, false) + + case yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE: + return yaml_parser_parse_block_sequence_entry(parser, event, true) + + case yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE: + return yaml_parser_parse_block_sequence_entry(parser, event, false) + + case yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE: + return yaml_parser_parse_indentless_sequence_entry(parser, event) + + case yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE: + return yaml_parser_parse_block_mapping_key(parser, event, true) + + case yaml_PARSE_BLOCK_MAPPING_KEY_STATE: + return yaml_parser_parse_block_mapping_key(parser, event, false) + + case yaml_PARSE_BLOCK_MAPPING_VALUE_STATE: + return yaml_parser_parse_block_mapping_value(parser, event) + + case yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE: + return yaml_parser_parse_flow_sequence_entry(parser, event, true) + + case yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE: + return yaml_parser_parse_flow_sequence_entry(parser, event, false) + + case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE: + return yaml_parser_parse_flow_sequence_entry_mapping_key(parser, event) + + case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE: + return yaml_parser_parse_flow_sequence_entry_mapping_value(parser, event) + + case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE: + return yaml_parser_parse_flow_sequence_entry_mapping_end(parser, event) + + case yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE: + return yaml_parser_parse_flow_mapping_key(parser, event, true) + + case yaml_PARSE_FLOW_MAPPING_KEY_STATE: + return yaml_parser_parse_flow_mapping_key(parser, event, false) + + case yaml_PARSE_FLOW_MAPPING_VALUE_STATE: + return yaml_parser_parse_flow_mapping_value(parser, event, false) + + case yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE: + return yaml_parser_parse_flow_mapping_value(parser, event, true) + + default: + panic("invalid parser state") + } +} + +// Parse the production: +// stream ::= STREAM-START implicit_document? explicit_document* STREAM-END +// ************ +func yaml_parser_parse_stream_start(parser *yaml_parser_t, event *yaml_event_t) bool { + token := peek_token(parser) + if token == nil { + return false + } + if token.typ != yaml_STREAM_START_TOKEN { + return yaml_parser_set_parser_error(parser, "did not find expected ", token.start_mark) + } + parser.state = yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE + *event = yaml_event_t{ + typ: yaml_STREAM_START_EVENT, + start_mark: token.start_mark, + end_mark: token.end_mark, + encoding: token.encoding, + } + skip_token(parser) + return true +} + +// Parse the productions: +// implicit_document ::= block_node DOCUMENT-END* +// * +// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END* +// ************************* +func yaml_parser_parse_document_start(parser *yaml_parser_t, event *yaml_event_t, implicit bool) bool { + + token := peek_token(parser) + if token == nil { + return false + } + + // Parse extra document end indicators. + if !implicit { + for token.typ == yaml_DOCUMENT_END_TOKEN { + skip_token(parser) + token = peek_token(parser) + if token == nil { + return false + } + } + } + + if implicit && token.typ != yaml_VERSION_DIRECTIVE_TOKEN && + token.typ != yaml_TAG_DIRECTIVE_TOKEN && + token.typ != yaml_DOCUMENT_START_TOKEN && + token.typ != yaml_STREAM_END_TOKEN { + // Parse an implicit document. + if !yaml_parser_process_directives(parser, nil, nil) { + return false + } + parser.states = append(parser.states, yaml_PARSE_DOCUMENT_END_STATE) + parser.state = yaml_PARSE_BLOCK_NODE_STATE + + *event = yaml_event_t{ + typ: yaml_DOCUMENT_START_EVENT, + start_mark: token.start_mark, + end_mark: token.end_mark, + } + + } else if token.typ != yaml_STREAM_END_TOKEN { + // Parse an explicit document. + var version_directive *yaml_version_directive_t + var tag_directives []yaml_tag_directive_t + start_mark := token.start_mark + if !yaml_parser_process_directives(parser, &version_directive, &tag_directives) { + return false + } + token = peek_token(parser) + if token == nil { + return false + } + if token.typ != yaml_DOCUMENT_START_TOKEN { + yaml_parser_set_parser_error(parser, + "did not find expected ", token.start_mark) + return false + } + parser.states = append(parser.states, yaml_PARSE_DOCUMENT_END_STATE) + parser.state = yaml_PARSE_DOCUMENT_CONTENT_STATE + end_mark := token.end_mark + + *event = yaml_event_t{ + typ: yaml_DOCUMENT_START_EVENT, + start_mark: start_mark, + end_mark: end_mark, + version_directive: version_directive, + tag_directives: tag_directives, + implicit: false, + } + skip_token(parser) + + } else { + // Parse the stream end. + parser.state = yaml_PARSE_END_STATE + *event = yaml_event_t{ + typ: yaml_STREAM_END_EVENT, + start_mark: token.start_mark, + end_mark: token.end_mark, + } + skip_token(parser) + } + + return true +} + +// Parse the productions: +// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END* +// *********** +// +func yaml_parser_parse_document_content(parser *yaml_parser_t, event *yaml_event_t) bool { + token := peek_token(parser) + if token == nil { + return false + } + if token.typ == yaml_VERSION_DIRECTIVE_TOKEN || + token.typ == yaml_TAG_DIRECTIVE_TOKEN || + token.typ == yaml_DOCUMENT_START_TOKEN || + token.typ == yaml_DOCUMENT_END_TOKEN || + token.typ == yaml_STREAM_END_TOKEN { + parser.state = parser.states[len(parser.states)-1] + parser.states = parser.states[:len(parser.states)-1] + return yaml_parser_process_empty_scalar(parser, event, + token.start_mark) + } + return yaml_parser_parse_node(parser, event, true, false) +} + +// Parse the productions: +// implicit_document ::= block_node DOCUMENT-END* +// ************* +// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END* +// +func yaml_parser_parse_document_end(parser *yaml_parser_t, event *yaml_event_t) bool { + token := peek_token(parser) + if token == nil { + return false + } + + start_mark := token.start_mark + end_mark := token.start_mark + + implicit := true + if token.typ == yaml_DOCUMENT_END_TOKEN { + end_mark = token.end_mark + skip_token(parser) + implicit = false + } + + parser.tag_directives = parser.tag_directives[:0] + + parser.state = yaml_PARSE_DOCUMENT_START_STATE + *event = yaml_event_t{ + typ: yaml_DOCUMENT_END_EVENT, + start_mark: start_mark, + end_mark: end_mark, + implicit: implicit, + } + return true +} + +// Parse the productions: +// block_node_or_indentless_sequence ::= +// ALIAS +// ***** +// | properties (block_content | indentless_block_sequence)? +// ********** * +// | block_content | indentless_block_sequence +// * +// block_node ::= ALIAS +// ***** +// | properties block_content? +// ********** * +// | block_content +// * +// flow_node ::= ALIAS +// ***** +// | properties flow_content? +// ********** * +// | flow_content +// * +// properties ::= TAG ANCHOR? | ANCHOR TAG? +// ************************* +// block_content ::= block_collection | flow_collection | SCALAR +// ****** +// flow_content ::= flow_collection | SCALAR +// ****** +func yaml_parser_parse_node(parser *yaml_parser_t, event *yaml_event_t, block, indentless_sequence bool) bool { + //defer trace("yaml_parser_parse_node", "block:", block, "indentless_sequence:", indentless_sequence)() + + token := peek_token(parser) + if token == nil { + return false + } + + if token.typ == yaml_ALIAS_TOKEN { + parser.state = parser.states[len(parser.states)-1] + parser.states = parser.states[:len(parser.states)-1] + *event = yaml_event_t{ + typ: yaml_ALIAS_EVENT, + start_mark: token.start_mark, + end_mark: token.end_mark, + anchor: token.value, + } + skip_token(parser) + return true + } + + start_mark := token.start_mark + end_mark := token.start_mark + + var tag_token bool + var tag_handle, tag_suffix, anchor []byte + var tag_mark yaml_mark_t + if token.typ == yaml_ANCHOR_TOKEN { + anchor = token.value + start_mark = token.start_mark + end_mark = token.end_mark + skip_token(parser) + token = peek_token(parser) + if token == nil { + return false + } + if token.typ == yaml_TAG_TOKEN { + tag_token = true + tag_handle = token.value + tag_suffix = token.suffix + tag_mark = token.start_mark + end_mark = token.end_mark + skip_token(parser) + token = peek_token(parser) + if token == nil { + return false + } + } + } else if token.typ == yaml_TAG_TOKEN { + tag_token = true + tag_handle = token.value + tag_suffix = token.suffix + start_mark = token.start_mark + tag_mark = token.start_mark + end_mark = token.end_mark + skip_token(parser) + token = peek_token(parser) + if token == nil { + return false + } + if token.typ == yaml_ANCHOR_TOKEN { + anchor = token.value + end_mark = token.end_mark + skip_token(parser) + token = peek_token(parser) + if token == nil { + return false + } + } + } + + var tag []byte + if tag_token { + if len(tag_handle) == 0 { + tag = tag_suffix + tag_suffix = nil + } else { + for i := range parser.tag_directives { + if bytes.Equal(parser.tag_directives[i].handle, tag_handle) { + tag = append([]byte(nil), parser.tag_directives[i].prefix...) + tag = append(tag, tag_suffix...) + break + } + } + if len(tag) == 0 { + yaml_parser_set_parser_error_context(parser, + "while parsing a node", start_mark, + "found undefined tag handle", tag_mark) + return false + } + } + } + + implicit := len(tag) == 0 + if indentless_sequence && token.typ == yaml_BLOCK_ENTRY_TOKEN { + end_mark = token.end_mark + parser.state = yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE + *event = yaml_event_t{ + typ: yaml_SEQUENCE_START_EVENT, + start_mark: start_mark, + end_mark: end_mark, + anchor: anchor, + tag: tag, + implicit: implicit, + style: yaml_style_t(yaml_BLOCK_SEQUENCE_STYLE), + } + return true + } + if token.typ == yaml_SCALAR_TOKEN { + var plain_implicit, quoted_implicit bool + end_mark = token.end_mark + if (len(tag) == 0 && token.style == yaml_PLAIN_SCALAR_STYLE) || (len(tag) == 1 && tag[0] == '!') { + plain_implicit = true + } else if len(tag) == 0 { + quoted_implicit = true + } + parser.state = parser.states[len(parser.states)-1] + parser.states = parser.states[:len(parser.states)-1] + + *event = yaml_event_t{ + typ: yaml_SCALAR_EVENT, + start_mark: start_mark, + end_mark: end_mark, + anchor: anchor, + tag: tag, + value: token.value, + implicit: plain_implicit, + quoted_implicit: quoted_implicit, + style: yaml_style_t(token.style), + } + skip_token(parser) + return true + } + if token.typ == yaml_FLOW_SEQUENCE_START_TOKEN { + // [Go] Some of the events below can be merged as they differ only on style. + end_mark = token.end_mark + parser.state = yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE + *event = yaml_event_t{ + typ: yaml_SEQUENCE_START_EVENT, + start_mark: start_mark, + end_mark: end_mark, + anchor: anchor, + tag: tag, + implicit: implicit, + style: yaml_style_t(yaml_FLOW_SEQUENCE_STYLE), + } + return true + } + if token.typ == yaml_FLOW_MAPPING_START_TOKEN { + end_mark = token.end_mark + parser.state = yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE + *event = yaml_event_t{ + typ: yaml_MAPPING_START_EVENT, + start_mark: start_mark, + end_mark: end_mark, + anchor: anchor, + tag: tag, + implicit: implicit, + style: yaml_style_t(yaml_FLOW_MAPPING_STYLE), + } + return true + } + if block && token.typ == yaml_BLOCK_SEQUENCE_START_TOKEN { + end_mark = token.end_mark + parser.state = yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE + *event = yaml_event_t{ + typ: yaml_SEQUENCE_START_EVENT, + start_mark: start_mark, + end_mark: end_mark, + anchor: anchor, + tag: tag, + implicit: implicit, + style: yaml_style_t(yaml_BLOCK_SEQUENCE_STYLE), + } + return true + } + if block && token.typ == yaml_BLOCK_MAPPING_START_TOKEN { + end_mark = token.end_mark + parser.state = yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE + *event = yaml_event_t{ + typ: yaml_MAPPING_START_EVENT, + start_mark: start_mark, + end_mark: end_mark, + anchor: anchor, + tag: tag, + implicit: implicit, + style: yaml_style_t(yaml_BLOCK_MAPPING_STYLE), + } + return true + } + if len(anchor) > 0 || len(tag) > 0 { + parser.state = parser.states[len(parser.states)-1] + parser.states = parser.states[:len(parser.states)-1] + + *event = yaml_event_t{ + typ: yaml_SCALAR_EVENT, + start_mark: start_mark, + end_mark: end_mark, + anchor: anchor, + tag: tag, + implicit: implicit, + quoted_implicit: false, + style: yaml_style_t(yaml_PLAIN_SCALAR_STYLE), + } + return true + } + + context := "while parsing a flow node" + if block { + context = "while parsing a block node" + } + yaml_parser_set_parser_error_context(parser, context, start_mark, + "did not find expected node content", token.start_mark) + return false +} + +// Parse the productions: +// block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END +// ******************** *********** * ********* +// +func yaml_parser_parse_block_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool { + if first { + token := peek_token(parser) + parser.marks = append(parser.marks, token.start_mark) + skip_token(parser) + } + + token := peek_token(parser) + if token == nil { + return false + } + + if token.typ == yaml_BLOCK_ENTRY_TOKEN { + mark := token.end_mark + skip_token(parser) + token = peek_token(parser) + if token == nil { + return false + } + if token.typ != yaml_BLOCK_ENTRY_TOKEN && token.typ != yaml_BLOCK_END_TOKEN { + parser.states = append(parser.states, yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE) + return yaml_parser_parse_node(parser, event, true, false) + } else { + parser.state = yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE + return yaml_parser_process_empty_scalar(parser, event, mark) + } + } + if token.typ == yaml_BLOCK_END_TOKEN { + parser.state = parser.states[len(parser.states)-1] + parser.states = parser.states[:len(parser.states)-1] + parser.marks = parser.marks[:len(parser.marks)-1] + + *event = yaml_event_t{ + typ: yaml_SEQUENCE_END_EVENT, + start_mark: token.start_mark, + end_mark: token.end_mark, + } + + skip_token(parser) + return true + } + + context_mark := parser.marks[len(parser.marks)-1] + parser.marks = parser.marks[:len(parser.marks)-1] + return yaml_parser_set_parser_error_context(parser, + "while parsing a block collection", context_mark, + "did not find expected '-' indicator", token.start_mark) +} + +// Parse the productions: +// indentless_sequence ::= (BLOCK-ENTRY block_node?)+ +// *********** * +func yaml_parser_parse_indentless_sequence_entry(parser *yaml_parser_t, event *yaml_event_t) bool { + token := peek_token(parser) + if token == nil { + return false + } + + if token.typ == yaml_BLOCK_ENTRY_TOKEN { + mark := token.end_mark + skip_token(parser) + token = peek_token(parser) + if token == nil { + return false + } + if token.typ != yaml_BLOCK_ENTRY_TOKEN && + token.typ != yaml_KEY_TOKEN && + token.typ != yaml_VALUE_TOKEN && + token.typ != yaml_BLOCK_END_TOKEN { + parser.states = append(parser.states, yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE) + return yaml_parser_parse_node(parser, event, true, false) + } + parser.state = yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE + return yaml_parser_process_empty_scalar(parser, event, mark) + } + parser.state = parser.states[len(parser.states)-1] + parser.states = parser.states[:len(parser.states)-1] + + *event = yaml_event_t{ + typ: yaml_SEQUENCE_END_EVENT, + start_mark: token.start_mark, + end_mark: token.start_mark, // [Go] Shouldn't this be token.end_mark? + } + return true +} + +// Parse the productions: +// block_mapping ::= BLOCK-MAPPING_START +// ******************* +// ((KEY block_node_or_indentless_sequence?)? +// *** * +// (VALUE block_node_or_indentless_sequence?)?)* +// +// BLOCK-END +// ********* +// +func yaml_parser_parse_block_mapping_key(parser *yaml_parser_t, event *yaml_event_t, first bool) bool { + if first { + token := peek_token(parser) + parser.marks = append(parser.marks, token.start_mark) + skip_token(parser) + } + + token := peek_token(parser) + if token == nil { + return false + } + + if token.typ == yaml_KEY_TOKEN { + mark := token.end_mark + skip_token(parser) + token = peek_token(parser) + if token == nil { + return false + } + if token.typ != yaml_KEY_TOKEN && + token.typ != yaml_VALUE_TOKEN && + token.typ != yaml_BLOCK_END_TOKEN { + parser.states = append(parser.states, yaml_PARSE_BLOCK_MAPPING_VALUE_STATE) + return yaml_parser_parse_node(parser, event, true, true) + } else { + parser.state = yaml_PARSE_BLOCK_MAPPING_VALUE_STATE + return yaml_parser_process_empty_scalar(parser, event, mark) + } + } else if token.typ == yaml_BLOCK_END_TOKEN { + parser.state = parser.states[len(parser.states)-1] + parser.states = parser.states[:len(parser.states)-1] + parser.marks = parser.marks[:len(parser.marks)-1] + *event = yaml_event_t{ + typ: yaml_MAPPING_END_EVENT, + start_mark: token.start_mark, + end_mark: token.end_mark, + } + skip_token(parser) + return true + } + + context_mark := parser.marks[len(parser.marks)-1] + parser.marks = parser.marks[:len(parser.marks)-1] + return yaml_parser_set_parser_error_context(parser, + "while parsing a block mapping", context_mark, + "did not find expected key", token.start_mark) +} + +// Parse the productions: +// block_mapping ::= BLOCK-MAPPING_START +// +// ((KEY block_node_or_indentless_sequence?)? +// +// (VALUE block_node_or_indentless_sequence?)?)* +// ***** * +// BLOCK-END +// +// +func yaml_parser_parse_block_mapping_value(parser *yaml_parser_t, event *yaml_event_t) bool { + token := peek_token(parser) + if token == nil { + return false + } + if token.typ == yaml_VALUE_TOKEN { + mark := token.end_mark + skip_token(parser) + token = peek_token(parser) + if token == nil { + return false + } + if token.typ != yaml_KEY_TOKEN && + token.typ != yaml_VALUE_TOKEN && + token.typ != yaml_BLOCK_END_TOKEN { + parser.states = append(parser.states, yaml_PARSE_BLOCK_MAPPING_KEY_STATE) + return yaml_parser_parse_node(parser, event, true, true) + } + parser.state = yaml_PARSE_BLOCK_MAPPING_KEY_STATE + return yaml_parser_process_empty_scalar(parser, event, mark) + } + parser.state = yaml_PARSE_BLOCK_MAPPING_KEY_STATE + return yaml_parser_process_empty_scalar(parser, event, token.start_mark) +} + +// Parse the productions: +// flow_sequence ::= FLOW-SEQUENCE-START +// ******************* +// (flow_sequence_entry FLOW-ENTRY)* +// * ********** +// flow_sequence_entry? +// * +// FLOW-SEQUENCE-END +// ***************** +// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? +// * +// +func yaml_parser_parse_flow_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool { + if first { + token := peek_token(parser) + parser.marks = append(parser.marks, token.start_mark) + skip_token(parser) + } + token := peek_token(parser) + if token == nil { + return false + } + if token.typ != yaml_FLOW_SEQUENCE_END_TOKEN { + if !first { + if token.typ == yaml_FLOW_ENTRY_TOKEN { + skip_token(parser) + token = peek_token(parser) + if token == nil { + return false + } + } else { + context_mark := parser.marks[len(parser.marks)-1] + parser.marks = parser.marks[:len(parser.marks)-1] + return yaml_parser_set_parser_error_context(parser, + "while parsing a flow sequence", context_mark, + "did not find expected ',' or ']'", token.start_mark) + } + } + + if token.typ == yaml_KEY_TOKEN { + parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE + *event = yaml_event_t{ + typ: yaml_MAPPING_START_EVENT, + start_mark: token.start_mark, + end_mark: token.end_mark, + implicit: true, + style: yaml_style_t(yaml_FLOW_MAPPING_STYLE), + } + skip_token(parser) + return true + } else if token.typ != yaml_FLOW_SEQUENCE_END_TOKEN { + parser.states = append(parser.states, yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE) + return yaml_parser_parse_node(parser, event, false, false) + } + } + + parser.state = parser.states[len(parser.states)-1] + parser.states = parser.states[:len(parser.states)-1] + parser.marks = parser.marks[:len(parser.marks)-1] + + *event = yaml_event_t{ + typ: yaml_SEQUENCE_END_EVENT, + start_mark: token.start_mark, + end_mark: token.end_mark, + } + + skip_token(parser) + return true +} + +// +// Parse the productions: +// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? +// *** * +// +func yaml_parser_parse_flow_sequence_entry_mapping_key(parser *yaml_parser_t, event *yaml_event_t) bool { + token := peek_token(parser) + if token == nil { + return false + } + if token.typ != yaml_VALUE_TOKEN && + token.typ != yaml_FLOW_ENTRY_TOKEN && + token.typ != yaml_FLOW_SEQUENCE_END_TOKEN { + parser.states = append(parser.states, yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE) + return yaml_parser_parse_node(parser, event, false, false) + } + mark := token.end_mark + skip_token(parser) + parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE + return yaml_parser_process_empty_scalar(parser, event, mark) +} + +// Parse the productions: +// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? +// ***** * +// +func yaml_parser_parse_flow_sequence_entry_mapping_value(parser *yaml_parser_t, event *yaml_event_t) bool { + token := peek_token(parser) + if token == nil { + return false + } + if token.typ == yaml_VALUE_TOKEN { + skip_token(parser) + token := peek_token(parser) + if token == nil { + return false + } + if token.typ != yaml_FLOW_ENTRY_TOKEN && token.typ != yaml_FLOW_SEQUENCE_END_TOKEN { + parser.states = append(parser.states, yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE) + return yaml_parser_parse_node(parser, event, false, false) + } + } + parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE + return yaml_parser_process_empty_scalar(parser, event, token.start_mark) +} + +// Parse the productions: +// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? +// * +// +func yaml_parser_parse_flow_sequence_entry_mapping_end(parser *yaml_parser_t, event *yaml_event_t) bool { + token := peek_token(parser) + if token == nil { + return false + } + parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE + *event = yaml_event_t{ + typ: yaml_MAPPING_END_EVENT, + start_mark: token.start_mark, + end_mark: token.start_mark, // [Go] Shouldn't this be end_mark? + } + return true +} + +// Parse the productions: +// flow_mapping ::= FLOW-MAPPING-START +// ****************** +// (flow_mapping_entry FLOW-ENTRY)* +// * ********** +// flow_mapping_entry? +// ****************** +// FLOW-MAPPING-END +// **************** +// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? +// * *** * +// +func yaml_parser_parse_flow_mapping_key(parser *yaml_parser_t, event *yaml_event_t, first bool) bool { + if first { + token := peek_token(parser) + parser.marks = append(parser.marks, token.start_mark) + skip_token(parser) + } + + token := peek_token(parser) + if token == nil { + return false + } + + if token.typ != yaml_FLOW_MAPPING_END_TOKEN { + if !first { + if token.typ == yaml_FLOW_ENTRY_TOKEN { + skip_token(parser) + token = peek_token(parser) + if token == nil { + return false + } + } else { + context_mark := parser.marks[len(parser.marks)-1] + parser.marks = parser.marks[:len(parser.marks)-1] + return yaml_parser_set_parser_error_context(parser, + "while parsing a flow mapping", context_mark, + "did not find expected ',' or '}'", token.start_mark) + } + } + + if token.typ == yaml_KEY_TOKEN { + skip_token(parser) + token = peek_token(parser) + if token == nil { + return false + } + if token.typ != yaml_VALUE_TOKEN && + token.typ != yaml_FLOW_ENTRY_TOKEN && + token.typ != yaml_FLOW_MAPPING_END_TOKEN { + parser.states = append(parser.states, yaml_PARSE_FLOW_MAPPING_VALUE_STATE) + return yaml_parser_parse_node(parser, event, false, false) + } else { + parser.state = yaml_PARSE_FLOW_MAPPING_VALUE_STATE + return yaml_parser_process_empty_scalar(parser, event, token.start_mark) + } + } else if token.typ != yaml_FLOW_MAPPING_END_TOKEN { + parser.states = append(parser.states, yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE) + return yaml_parser_parse_node(parser, event, false, false) + } + } + + parser.state = parser.states[len(parser.states)-1] + parser.states = parser.states[:len(parser.states)-1] + parser.marks = parser.marks[:len(parser.marks)-1] + *event = yaml_event_t{ + typ: yaml_MAPPING_END_EVENT, + start_mark: token.start_mark, + end_mark: token.end_mark, + } + skip_token(parser) + return true +} + +// Parse the productions: +// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? +// * ***** * +// +func yaml_parser_parse_flow_mapping_value(parser *yaml_parser_t, event *yaml_event_t, empty bool) bool { + token := peek_token(parser) + if token == nil { + return false + } + if empty { + parser.state = yaml_PARSE_FLOW_MAPPING_KEY_STATE + return yaml_parser_process_empty_scalar(parser, event, token.start_mark) + } + if token.typ == yaml_VALUE_TOKEN { + skip_token(parser) + token = peek_token(parser) + if token == nil { + return false + } + if token.typ != yaml_FLOW_ENTRY_TOKEN && token.typ != yaml_FLOW_MAPPING_END_TOKEN { + parser.states = append(parser.states, yaml_PARSE_FLOW_MAPPING_KEY_STATE) + return yaml_parser_parse_node(parser, event, false, false) + } + } + parser.state = yaml_PARSE_FLOW_MAPPING_KEY_STATE + return yaml_parser_process_empty_scalar(parser, event, token.start_mark) +} + +// Generate an empty scalar event. +func yaml_parser_process_empty_scalar(parser *yaml_parser_t, event *yaml_event_t, mark yaml_mark_t) bool { + *event = yaml_event_t{ + typ: yaml_SCALAR_EVENT, + start_mark: mark, + end_mark: mark, + value: nil, // Empty + implicit: true, + style: yaml_style_t(yaml_PLAIN_SCALAR_STYLE), + } + return true +} + +var default_tag_directives = []yaml_tag_directive_t{ + {[]byte("!"), []byte("!")}, + {[]byte("!!"), []byte("tag:yaml.org,2002:")}, +} + +// Parse directives. +func yaml_parser_process_directives(parser *yaml_parser_t, + version_directive_ref **yaml_version_directive_t, + tag_directives_ref *[]yaml_tag_directive_t) bool { + + var version_directive *yaml_version_directive_t + var tag_directives []yaml_tag_directive_t + + token := peek_token(parser) + if token == nil { + return false + } + + for token.typ == yaml_VERSION_DIRECTIVE_TOKEN || token.typ == yaml_TAG_DIRECTIVE_TOKEN { + if token.typ == yaml_VERSION_DIRECTIVE_TOKEN { + if version_directive != nil { + yaml_parser_set_parser_error(parser, + "found duplicate %YAML directive", token.start_mark) + return false + } + if token.major != 1 || token.minor != 1 { + yaml_parser_set_parser_error(parser, + "found incompatible YAML document", token.start_mark) + return false + } + version_directive = &yaml_version_directive_t{ + major: token.major, + minor: token.minor, + } + } else if token.typ == yaml_TAG_DIRECTIVE_TOKEN { + value := yaml_tag_directive_t{ + handle: token.value, + prefix: token.prefix, + } + if !yaml_parser_append_tag_directive(parser, value, false, token.start_mark) { + return false + } + tag_directives = append(tag_directives, value) + } + + skip_token(parser) + token = peek_token(parser) + if token == nil { + return false + } + } + + for i := range default_tag_directives { + if !yaml_parser_append_tag_directive(parser, default_tag_directives[i], true, token.start_mark) { + return false + } + } + + if version_directive_ref != nil { + *version_directive_ref = version_directive + } + if tag_directives_ref != nil { + *tag_directives_ref = tag_directives + } + return true +} + +// Append a tag directive to the directives stack. +func yaml_parser_append_tag_directive(parser *yaml_parser_t, value yaml_tag_directive_t, allow_duplicates bool, mark yaml_mark_t) bool { + for i := range parser.tag_directives { + if bytes.Equal(value.handle, parser.tag_directives[i].handle) { + if allow_duplicates { + return true + } + return yaml_parser_set_parser_error(parser, "found duplicate %TAG directive", mark) + } + } + + // [Go] I suspect the copy is unnecessary. This was likely done + // because there was no way to track ownership of the data. + value_copy := yaml_tag_directive_t{ + handle: make([]byte, len(value.handle)), + prefix: make([]byte, len(value.prefix)), + } + copy(value_copy.handle, value.handle) + copy(value_copy.prefix, value.prefix) + parser.tag_directives = append(parser.tag_directives, value_copy) + return true +} diff --git a/vendor/sigs.k8s.io/yaml/goyaml.v2/readerc.go b/vendor/sigs.k8s.io/yaml/goyaml.v2/readerc.go new file mode 100644 index 000000000..7c1f5fac3 --- /dev/null +++ b/vendor/sigs.k8s.io/yaml/goyaml.v2/readerc.go @@ -0,0 +1,412 @@ +package yaml + +import ( + "io" +) + +// Set the reader error and return 0. +func yaml_parser_set_reader_error(parser *yaml_parser_t, problem string, offset int, value int) bool { + parser.error = yaml_READER_ERROR + parser.problem = problem + parser.problem_offset = offset + parser.problem_value = value + return false +} + +// Byte order marks. +const ( + bom_UTF8 = "\xef\xbb\xbf" + bom_UTF16LE = "\xff\xfe" + bom_UTF16BE = "\xfe\xff" +) + +// Determine the input stream encoding by checking the BOM symbol. If no BOM is +// found, the UTF-8 encoding is assumed. Return 1 on success, 0 on failure. +func yaml_parser_determine_encoding(parser *yaml_parser_t) bool { + // Ensure that we had enough bytes in the raw buffer. + for !parser.eof && len(parser.raw_buffer)-parser.raw_buffer_pos < 3 { + if !yaml_parser_update_raw_buffer(parser) { + return false + } + } + + // Determine the encoding. + buf := parser.raw_buffer + pos := parser.raw_buffer_pos + avail := len(buf) - pos + if avail >= 2 && buf[pos] == bom_UTF16LE[0] && buf[pos+1] == bom_UTF16LE[1] { + parser.encoding = yaml_UTF16LE_ENCODING + parser.raw_buffer_pos += 2 + parser.offset += 2 + } else if avail >= 2 && buf[pos] == bom_UTF16BE[0] && buf[pos+1] == bom_UTF16BE[1] { + parser.encoding = yaml_UTF16BE_ENCODING + parser.raw_buffer_pos += 2 + parser.offset += 2 + } else if avail >= 3 && buf[pos] == bom_UTF8[0] && buf[pos+1] == bom_UTF8[1] && buf[pos+2] == bom_UTF8[2] { + parser.encoding = yaml_UTF8_ENCODING + parser.raw_buffer_pos += 3 + parser.offset += 3 + } else { + parser.encoding = yaml_UTF8_ENCODING + } + return true +} + +// Update the raw buffer. +func yaml_parser_update_raw_buffer(parser *yaml_parser_t) bool { + size_read := 0 + + // Return if the raw buffer is full. + if parser.raw_buffer_pos == 0 && len(parser.raw_buffer) == cap(parser.raw_buffer) { + return true + } + + // Return on EOF. + if parser.eof { + return true + } + + // Move the remaining bytes in the raw buffer to the beginning. + if parser.raw_buffer_pos > 0 && parser.raw_buffer_pos < len(parser.raw_buffer) { + copy(parser.raw_buffer, parser.raw_buffer[parser.raw_buffer_pos:]) + } + parser.raw_buffer = parser.raw_buffer[:len(parser.raw_buffer)-parser.raw_buffer_pos] + parser.raw_buffer_pos = 0 + + // Call the read handler to fill the buffer. + size_read, err := parser.read_handler(parser, parser.raw_buffer[len(parser.raw_buffer):cap(parser.raw_buffer)]) + parser.raw_buffer = parser.raw_buffer[:len(parser.raw_buffer)+size_read] + if err == io.EOF { + parser.eof = true + } else if err != nil { + return yaml_parser_set_reader_error(parser, "input error: "+err.Error(), parser.offset, -1) + } + return true +} + +// Ensure that the buffer contains at least `length` characters. +// Return true on success, false on failure. +// +// The length is supposed to be significantly less that the buffer size. +func yaml_parser_update_buffer(parser *yaml_parser_t, length int) bool { + if parser.read_handler == nil { + panic("read handler must be set") + } + + // [Go] This function was changed to guarantee the requested length size at EOF. + // The fact we need to do this is pretty awful, but the description above implies + // for that to be the case, and there are tests + + // If the EOF flag is set and the raw buffer is empty, do nothing. + if parser.eof && parser.raw_buffer_pos == len(parser.raw_buffer) { + // [Go] ACTUALLY! Read the documentation of this function above. + // This is just broken. To return true, we need to have the + // given length in the buffer. Not doing that means every single + // check that calls this function to make sure the buffer has a + // given length is Go) panicking; or C) accessing invalid memory. + //return true + } + + // Return if the buffer contains enough characters. + if parser.unread >= length { + return true + } + + // Determine the input encoding if it is not known yet. + if parser.encoding == yaml_ANY_ENCODING { + if !yaml_parser_determine_encoding(parser) { + return false + } + } + + // Move the unread characters to the beginning of the buffer. + buffer_len := len(parser.buffer) + if parser.buffer_pos > 0 && parser.buffer_pos < buffer_len { + copy(parser.buffer, parser.buffer[parser.buffer_pos:]) + buffer_len -= parser.buffer_pos + parser.buffer_pos = 0 + } else if parser.buffer_pos == buffer_len { + buffer_len = 0 + parser.buffer_pos = 0 + } + + // Open the whole buffer for writing, and cut it before returning. + parser.buffer = parser.buffer[:cap(parser.buffer)] + + // Fill the buffer until it has enough characters. + first := true + for parser.unread < length { + + // Fill the raw buffer if necessary. + if !first || parser.raw_buffer_pos == len(parser.raw_buffer) { + if !yaml_parser_update_raw_buffer(parser) { + parser.buffer = parser.buffer[:buffer_len] + return false + } + } + first = false + + // Decode the raw buffer. + inner: + for parser.raw_buffer_pos != len(parser.raw_buffer) { + var value rune + var width int + + raw_unread := len(parser.raw_buffer) - parser.raw_buffer_pos + + // Decode the next character. + switch parser.encoding { + case yaml_UTF8_ENCODING: + // Decode a UTF-8 character. Check RFC 3629 + // (http://www.ietf.org/rfc/rfc3629.txt) for more details. + // + // The following table (taken from the RFC) is used for + // decoding. + // + // Char. number range | UTF-8 octet sequence + // (hexadecimal) | (binary) + // --------------------+------------------------------------ + // 0000 0000-0000 007F | 0xxxxxxx + // 0000 0080-0000 07FF | 110xxxxx 10xxxxxx + // 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx + // 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + // + // Additionally, the characters in the range 0xD800-0xDFFF + // are prohibited as they are reserved for use with UTF-16 + // surrogate pairs. + + // Determine the length of the UTF-8 sequence. + octet := parser.raw_buffer[parser.raw_buffer_pos] + switch { + case octet&0x80 == 0x00: + width = 1 + case octet&0xE0 == 0xC0: + width = 2 + case octet&0xF0 == 0xE0: + width = 3 + case octet&0xF8 == 0xF0: + width = 4 + default: + // The leading octet is invalid. + return yaml_parser_set_reader_error(parser, + "invalid leading UTF-8 octet", + parser.offset, int(octet)) + } + + // Check if the raw buffer contains an incomplete character. + if width > raw_unread { + if parser.eof { + return yaml_parser_set_reader_error(parser, + "incomplete UTF-8 octet sequence", + parser.offset, -1) + } + break inner + } + + // Decode the leading octet. + switch { + case octet&0x80 == 0x00: + value = rune(octet & 0x7F) + case octet&0xE0 == 0xC0: + value = rune(octet & 0x1F) + case octet&0xF0 == 0xE0: + value = rune(octet & 0x0F) + case octet&0xF8 == 0xF0: + value = rune(octet & 0x07) + default: + value = 0 + } + + // Check and decode the trailing octets. + for k := 1; k < width; k++ { + octet = parser.raw_buffer[parser.raw_buffer_pos+k] + + // Check if the octet is valid. + if (octet & 0xC0) != 0x80 { + return yaml_parser_set_reader_error(parser, + "invalid trailing UTF-8 octet", + parser.offset+k, int(octet)) + } + + // Decode the octet. + value = (value << 6) + rune(octet&0x3F) + } + + // Check the length of the sequence against the value. + switch { + case width == 1: + case width == 2 && value >= 0x80: + case width == 3 && value >= 0x800: + case width == 4 && value >= 0x10000: + default: + return yaml_parser_set_reader_error(parser, + "invalid length of a UTF-8 sequence", + parser.offset, -1) + } + + // Check the range of the value. + if value >= 0xD800 && value <= 0xDFFF || value > 0x10FFFF { + return yaml_parser_set_reader_error(parser, + "invalid Unicode character", + parser.offset, int(value)) + } + + case yaml_UTF16LE_ENCODING, yaml_UTF16BE_ENCODING: + var low, high int + if parser.encoding == yaml_UTF16LE_ENCODING { + low, high = 0, 1 + } else { + low, high = 1, 0 + } + + // The UTF-16 encoding is not as simple as one might + // naively think. Check RFC 2781 + // (http://www.ietf.org/rfc/rfc2781.txt). + // + // Normally, two subsequent bytes describe a Unicode + // character. However a special technique (called a + // surrogate pair) is used for specifying character + // values larger than 0xFFFF. + // + // A surrogate pair consists of two pseudo-characters: + // high surrogate area (0xD800-0xDBFF) + // low surrogate area (0xDC00-0xDFFF) + // + // The following formulas are used for decoding + // and encoding characters using surrogate pairs: + // + // U = U' + 0x10000 (0x01 00 00 <= U <= 0x10 FF FF) + // U' = yyyyyyyyyyxxxxxxxxxx (0 <= U' <= 0x0F FF FF) + // W1 = 110110yyyyyyyyyy + // W2 = 110111xxxxxxxxxx + // + // where U is the character value, W1 is the high surrogate + // area, W2 is the low surrogate area. + + // Check for incomplete UTF-16 character. + if raw_unread < 2 { + if parser.eof { + return yaml_parser_set_reader_error(parser, + "incomplete UTF-16 character", + parser.offset, -1) + } + break inner + } + + // Get the character. + value = rune(parser.raw_buffer[parser.raw_buffer_pos+low]) + + (rune(parser.raw_buffer[parser.raw_buffer_pos+high]) << 8) + + // Check for unexpected low surrogate area. + if value&0xFC00 == 0xDC00 { + return yaml_parser_set_reader_error(parser, + "unexpected low surrogate area", + parser.offset, int(value)) + } + + // Check for a high surrogate area. + if value&0xFC00 == 0xD800 { + width = 4 + + // Check for incomplete surrogate pair. + if raw_unread < 4 { + if parser.eof { + return yaml_parser_set_reader_error(parser, + "incomplete UTF-16 surrogate pair", + parser.offset, -1) + } + break inner + } + + // Get the next character. + value2 := rune(parser.raw_buffer[parser.raw_buffer_pos+low+2]) + + (rune(parser.raw_buffer[parser.raw_buffer_pos+high+2]) << 8) + + // Check for a low surrogate area. + if value2&0xFC00 != 0xDC00 { + return yaml_parser_set_reader_error(parser, + "expected low surrogate area", + parser.offset+2, int(value2)) + } + + // Generate the value of the surrogate pair. + value = 0x10000 + ((value & 0x3FF) << 10) + (value2 & 0x3FF) + } else { + width = 2 + } + + default: + panic("impossible") + } + + // Check if the character is in the allowed range: + // #x9 | #xA | #xD | [#x20-#x7E] (8 bit) + // | #x85 | [#xA0-#xD7FF] | [#xE000-#xFFFD] (16 bit) + // | [#x10000-#x10FFFF] (32 bit) + switch { + case value == 0x09: + case value == 0x0A: + case value == 0x0D: + case value >= 0x20 && value <= 0x7E: + case value == 0x85: + case value >= 0xA0 && value <= 0xD7FF: + case value >= 0xE000 && value <= 0xFFFD: + case value >= 0x10000 && value <= 0x10FFFF: + default: + return yaml_parser_set_reader_error(parser, + "control characters are not allowed", + parser.offset, int(value)) + } + + // Move the raw pointers. + parser.raw_buffer_pos += width + parser.offset += width + + // Finally put the character into the buffer. + if value <= 0x7F { + // 0000 0000-0000 007F . 0xxxxxxx + parser.buffer[buffer_len+0] = byte(value) + buffer_len += 1 + } else if value <= 0x7FF { + // 0000 0080-0000 07FF . 110xxxxx 10xxxxxx + parser.buffer[buffer_len+0] = byte(0xC0 + (value >> 6)) + parser.buffer[buffer_len+1] = byte(0x80 + (value & 0x3F)) + buffer_len += 2 + } else if value <= 0xFFFF { + // 0000 0800-0000 FFFF . 1110xxxx 10xxxxxx 10xxxxxx + parser.buffer[buffer_len+0] = byte(0xE0 + (value >> 12)) + parser.buffer[buffer_len+1] = byte(0x80 + ((value >> 6) & 0x3F)) + parser.buffer[buffer_len+2] = byte(0x80 + (value & 0x3F)) + buffer_len += 3 + } else { + // 0001 0000-0010 FFFF . 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + parser.buffer[buffer_len+0] = byte(0xF0 + (value >> 18)) + parser.buffer[buffer_len+1] = byte(0x80 + ((value >> 12) & 0x3F)) + parser.buffer[buffer_len+2] = byte(0x80 + ((value >> 6) & 0x3F)) + parser.buffer[buffer_len+3] = byte(0x80 + (value & 0x3F)) + buffer_len += 4 + } + + parser.unread++ + } + + // On EOF, put NUL into the buffer and return. + if parser.eof { + parser.buffer[buffer_len] = 0 + buffer_len++ + parser.unread++ + break + } + } + // [Go] Read the documentation of this function above. To return true, + // we need to have the given length in the buffer. Not doing that means + // every single check that calls this function to make sure the buffer + // has a given length is Go) panicking; or C) accessing invalid memory. + // This happens here due to the EOF above breaking early. + for buffer_len < length { + parser.buffer[buffer_len] = 0 + buffer_len++ + } + parser.buffer = parser.buffer[:buffer_len] + return true +} diff --git a/vendor/sigs.k8s.io/yaml/goyaml.v2/resolve.go b/vendor/sigs.k8s.io/yaml/goyaml.v2/resolve.go new file mode 100644 index 000000000..4120e0c91 --- /dev/null +++ b/vendor/sigs.k8s.io/yaml/goyaml.v2/resolve.go @@ -0,0 +1,258 @@ +package yaml + +import ( + "encoding/base64" + "math" + "regexp" + "strconv" + "strings" + "time" +) + +type resolveMapItem struct { + value interface{} + tag string +} + +var resolveTable = make([]byte, 256) +var resolveMap = make(map[string]resolveMapItem) + +func init() { + t := resolveTable + t[int('+')] = 'S' // Sign + t[int('-')] = 'S' + for _, c := range "0123456789" { + t[int(c)] = 'D' // Digit + } + for _, c := range "yYnNtTfFoO~" { + t[int(c)] = 'M' // In map + } + t[int('.')] = '.' // Float (potentially in map) + + var resolveMapList = []struct { + v interface{} + tag string + l []string + }{ + {true, yaml_BOOL_TAG, []string{"y", "Y", "yes", "Yes", "YES"}}, + {true, yaml_BOOL_TAG, []string{"true", "True", "TRUE"}}, + {true, yaml_BOOL_TAG, []string{"on", "On", "ON"}}, + {false, yaml_BOOL_TAG, []string{"n", "N", "no", "No", "NO"}}, + {false, yaml_BOOL_TAG, []string{"false", "False", "FALSE"}}, + {false, yaml_BOOL_TAG, []string{"off", "Off", "OFF"}}, + {nil, yaml_NULL_TAG, []string{"", "~", "null", "Null", "NULL"}}, + {math.NaN(), yaml_FLOAT_TAG, []string{".nan", ".NaN", ".NAN"}}, + {math.Inf(+1), yaml_FLOAT_TAG, []string{".inf", ".Inf", ".INF"}}, + {math.Inf(+1), yaml_FLOAT_TAG, []string{"+.inf", "+.Inf", "+.INF"}}, + {math.Inf(-1), yaml_FLOAT_TAG, []string{"-.inf", "-.Inf", "-.INF"}}, + {"<<", yaml_MERGE_TAG, []string{"<<"}}, + } + + m := resolveMap + for _, item := range resolveMapList { + for _, s := range item.l { + m[s] = resolveMapItem{item.v, item.tag} + } + } +} + +const longTagPrefix = "tag:yaml.org,2002:" + +func shortTag(tag string) string { + // TODO This can easily be made faster and produce less garbage. + if strings.HasPrefix(tag, longTagPrefix) { + return "!!" + tag[len(longTagPrefix):] + } + return tag +} + +func longTag(tag string) string { + if strings.HasPrefix(tag, "!!") { + return longTagPrefix + tag[2:] + } + return tag +} + +func resolvableTag(tag string) bool { + switch tag { + case "", yaml_STR_TAG, yaml_BOOL_TAG, yaml_INT_TAG, yaml_FLOAT_TAG, yaml_NULL_TAG, yaml_TIMESTAMP_TAG: + return true + } + return false +} + +var yamlStyleFloat = regexp.MustCompile(`^[-+]?(\.[0-9]+|[0-9]+(\.[0-9]*)?)([eE][-+]?[0-9]+)?$`) + +func resolve(tag string, in string) (rtag string, out interface{}) { + if !resolvableTag(tag) { + return tag, in + } + + defer func() { + switch tag { + case "", rtag, yaml_STR_TAG, yaml_BINARY_TAG: + return + case yaml_FLOAT_TAG: + if rtag == yaml_INT_TAG { + switch v := out.(type) { + case int64: + rtag = yaml_FLOAT_TAG + out = float64(v) + return + case int: + rtag = yaml_FLOAT_TAG + out = float64(v) + return + } + } + } + failf("cannot decode %s `%s` as a %s", shortTag(rtag), in, shortTag(tag)) + }() + + // Any data is accepted as a !!str or !!binary. + // Otherwise, the prefix is enough of a hint about what it might be. + hint := byte('N') + if in != "" { + hint = resolveTable[in[0]] + } + if hint != 0 && tag != yaml_STR_TAG && tag != yaml_BINARY_TAG { + // Handle things we can lookup in a map. + if item, ok := resolveMap[in]; ok { + return item.tag, item.value + } + + // Base 60 floats are a bad idea, were dropped in YAML 1.2, and + // are purposefully unsupported here. They're still quoted on + // the way out for compatibility with other parser, though. + + switch hint { + case 'M': + // We've already checked the map above. + + case '.': + // Not in the map, so maybe a normal float. + floatv, err := strconv.ParseFloat(in, 64) + if err == nil { + return yaml_FLOAT_TAG, floatv + } + + case 'D', 'S': + // Int, float, or timestamp. + // Only try values as a timestamp if the value is unquoted or there's an explicit + // !!timestamp tag. + if tag == "" || tag == yaml_TIMESTAMP_TAG { + t, ok := parseTimestamp(in) + if ok { + return yaml_TIMESTAMP_TAG, t + } + } + + plain := strings.Replace(in, "_", "", -1) + intv, err := strconv.ParseInt(plain, 0, 64) + if err == nil { + if intv == int64(int(intv)) { + return yaml_INT_TAG, int(intv) + } else { + return yaml_INT_TAG, intv + } + } + uintv, err := strconv.ParseUint(plain, 0, 64) + if err == nil { + return yaml_INT_TAG, uintv + } + if yamlStyleFloat.MatchString(plain) { + floatv, err := strconv.ParseFloat(plain, 64) + if err == nil { + return yaml_FLOAT_TAG, floatv + } + } + if strings.HasPrefix(plain, "0b") { + intv, err := strconv.ParseInt(plain[2:], 2, 64) + if err == nil { + if intv == int64(int(intv)) { + return yaml_INT_TAG, int(intv) + } else { + return yaml_INT_TAG, intv + } + } + uintv, err := strconv.ParseUint(plain[2:], 2, 64) + if err == nil { + return yaml_INT_TAG, uintv + } + } else if strings.HasPrefix(plain, "-0b") { + intv, err := strconv.ParseInt("-" + plain[3:], 2, 64) + if err == nil { + if true || intv == int64(int(intv)) { + return yaml_INT_TAG, int(intv) + } else { + return yaml_INT_TAG, intv + } + } + } + default: + panic("resolveTable item not yet handled: " + string(rune(hint)) + " (with " + in + ")") + } + } + return yaml_STR_TAG, in +} + +// encodeBase64 encodes s as base64 that is broken up into multiple lines +// as appropriate for the resulting length. +func encodeBase64(s string) string { + const lineLen = 70 + encLen := base64.StdEncoding.EncodedLen(len(s)) + lines := encLen/lineLen + 1 + buf := make([]byte, encLen*2+lines) + in := buf[0:encLen] + out := buf[encLen:] + base64.StdEncoding.Encode(in, []byte(s)) + k := 0 + for i := 0; i < len(in); i += lineLen { + j := i + lineLen + if j > len(in) { + j = len(in) + } + k += copy(out[k:], in[i:j]) + if lines > 1 { + out[k] = '\n' + k++ + } + } + return string(out[:k]) +} + +// This is a subset of the formats allowed by the regular expression +// defined at http://yaml.org/type/timestamp.html. +var allowedTimestampFormats = []string{ + "2006-1-2T15:4:5.999999999Z07:00", // RCF3339Nano with short date fields. + "2006-1-2t15:4:5.999999999Z07:00", // RFC3339Nano with short date fields and lower-case "t". + "2006-1-2 15:4:5.999999999", // space separated with no time zone + "2006-1-2", // date only + // Notable exception: time.Parse cannot handle: "2001-12-14 21:59:43.10 -5" + // from the set of examples. +} + +// parseTimestamp parses s as a timestamp string and +// returns the timestamp and reports whether it succeeded. +// Timestamp formats are defined at http://yaml.org/type/timestamp.html +func parseTimestamp(s string) (time.Time, bool) { + // TODO write code to check all the formats supported by + // http://yaml.org/type/timestamp.html instead of using time.Parse. + + // Quick check: all date formats start with YYYY-. + i := 0 + for ; i < len(s); i++ { + if c := s[i]; c < '0' || c > '9' { + break + } + } + if i != 4 || i == len(s) || s[i] != '-' { + return time.Time{}, false + } + for _, format := range allowedTimestampFormats { + if t, err := time.Parse(format, s); err == nil { + return t, true + } + } + return time.Time{}, false +} diff --git a/vendor/sigs.k8s.io/yaml/goyaml.v2/scannerc.go b/vendor/sigs.k8s.io/yaml/goyaml.v2/scannerc.go new file mode 100644 index 000000000..0b9bb6030 --- /dev/null +++ b/vendor/sigs.k8s.io/yaml/goyaml.v2/scannerc.go @@ -0,0 +1,2711 @@ +package yaml + +import ( + "bytes" + "fmt" +) + +// Introduction +// ************ +// +// The following notes assume that you are familiar with the YAML specification +// (http://yaml.org/spec/1.2/spec.html). We mostly follow it, although in +// some cases we are less restrictive that it requires. +// +// The process of transforming a YAML stream into a sequence of events is +// divided on two steps: Scanning and Parsing. +// +// The Scanner transforms the input stream into a sequence of tokens, while the +// parser transform the sequence of tokens produced by the Scanner into a +// sequence of parsing events. +// +// The Scanner is rather clever and complicated. The Parser, on the contrary, +// is a straightforward implementation of a recursive-descendant parser (or, +// LL(1) parser, as it is usually called). +// +// Actually there are two issues of Scanning that might be called "clever", the +// rest is quite straightforward. The issues are "block collection start" and +// "simple keys". Both issues are explained below in details. +// +// Here the Scanning step is explained and implemented. We start with the list +// of all the tokens produced by the Scanner together with short descriptions. +// +// Now, tokens: +// +// STREAM-START(encoding) # The stream start. +// STREAM-END # The stream end. +// VERSION-DIRECTIVE(major,minor) # The '%YAML' directive. +// TAG-DIRECTIVE(handle,prefix) # The '%TAG' directive. +// DOCUMENT-START # '---' +// DOCUMENT-END # '...' +// BLOCK-SEQUENCE-START # Indentation increase denoting a block +// BLOCK-MAPPING-START # sequence or a block mapping. +// BLOCK-END # Indentation decrease. +// FLOW-SEQUENCE-START # '[' +// FLOW-SEQUENCE-END # ']' +// BLOCK-SEQUENCE-START # '{' +// BLOCK-SEQUENCE-END # '}' +// BLOCK-ENTRY # '-' +// FLOW-ENTRY # ',' +// KEY # '?' or nothing (simple keys). +// VALUE # ':' +// ALIAS(anchor) # '*anchor' +// ANCHOR(anchor) # '&anchor' +// TAG(handle,suffix) # '!handle!suffix' +// SCALAR(value,style) # A scalar. +// +// The following two tokens are "virtual" tokens denoting the beginning and the +// end of the stream: +// +// STREAM-START(encoding) +// STREAM-END +// +// We pass the information about the input stream encoding with the +// STREAM-START token. +// +// The next two tokens are responsible for tags: +// +// VERSION-DIRECTIVE(major,minor) +// TAG-DIRECTIVE(handle,prefix) +// +// Example: +// +// %YAML 1.1 +// %TAG ! !foo +// %TAG !yaml! tag:yaml.org,2002: +// --- +// +// The correspoding sequence of tokens: +// +// STREAM-START(utf-8) +// VERSION-DIRECTIVE(1,1) +// TAG-DIRECTIVE("!","!foo") +// TAG-DIRECTIVE("!yaml","tag:yaml.org,2002:") +// DOCUMENT-START +// STREAM-END +// +// Note that the VERSION-DIRECTIVE and TAG-DIRECTIVE tokens occupy a whole +// line. +// +// The document start and end indicators are represented by: +// +// DOCUMENT-START +// DOCUMENT-END +// +// Note that if a YAML stream contains an implicit document (without '---' +// and '...' indicators), no DOCUMENT-START and DOCUMENT-END tokens will be +// produced. +// +// In the following examples, we present whole documents together with the +// produced tokens. +// +// 1. An implicit document: +// +// 'a scalar' +// +// Tokens: +// +// STREAM-START(utf-8) +// SCALAR("a scalar",single-quoted) +// STREAM-END +// +// 2. An explicit document: +// +// --- +// 'a scalar' +// ... +// +// Tokens: +// +// STREAM-START(utf-8) +// DOCUMENT-START +// SCALAR("a scalar",single-quoted) +// DOCUMENT-END +// STREAM-END +// +// 3. Several documents in a stream: +// +// 'a scalar' +// --- +// 'another scalar' +// --- +// 'yet another scalar' +// +// Tokens: +// +// STREAM-START(utf-8) +// SCALAR("a scalar",single-quoted) +// DOCUMENT-START +// SCALAR("another scalar",single-quoted) +// DOCUMENT-START +// SCALAR("yet another scalar",single-quoted) +// STREAM-END +// +// We have already introduced the SCALAR token above. The following tokens are +// used to describe aliases, anchors, tag, and scalars: +// +// ALIAS(anchor) +// ANCHOR(anchor) +// TAG(handle,suffix) +// SCALAR(value,style) +// +// The following series of examples illustrate the usage of these tokens: +// +// 1. A recursive sequence: +// +// &A [ *A ] +// +// Tokens: +// +// STREAM-START(utf-8) +// ANCHOR("A") +// FLOW-SEQUENCE-START +// ALIAS("A") +// FLOW-SEQUENCE-END +// STREAM-END +// +// 2. A tagged scalar: +// +// !!float "3.14" # A good approximation. +// +// Tokens: +// +// STREAM-START(utf-8) +// TAG("!!","float") +// SCALAR("3.14",double-quoted) +// STREAM-END +// +// 3. Various scalar styles: +// +// --- # Implicit empty plain scalars do not produce tokens. +// --- a plain scalar +// --- 'a single-quoted scalar' +// --- "a double-quoted scalar" +// --- |- +// a literal scalar +// --- >- +// a folded +// scalar +// +// Tokens: +// +// STREAM-START(utf-8) +// DOCUMENT-START +// DOCUMENT-START +// SCALAR("a plain scalar",plain) +// DOCUMENT-START +// SCALAR("a single-quoted scalar",single-quoted) +// DOCUMENT-START +// SCALAR("a double-quoted scalar",double-quoted) +// DOCUMENT-START +// SCALAR("a literal scalar",literal) +// DOCUMENT-START +// SCALAR("a folded scalar",folded) +// STREAM-END +// +// Now it's time to review collection-related tokens. We will start with +// flow collections: +// +// FLOW-SEQUENCE-START +// FLOW-SEQUENCE-END +// FLOW-MAPPING-START +// FLOW-MAPPING-END +// FLOW-ENTRY +// KEY +// VALUE +// +// The tokens FLOW-SEQUENCE-START, FLOW-SEQUENCE-END, FLOW-MAPPING-START, and +// FLOW-MAPPING-END represent the indicators '[', ']', '{', and '}' +// correspondingly. FLOW-ENTRY represent the ',' indicator. Finally the +// indicators '?' and ':', which are used for denoting mapping keys and values, +// are represented by the KEY and VALUE tokens. +// +// The following examples show flow collections: +// +// 1. A flow sequence: +// +// [item 1, item 2, item 3] +// +// Tokens: +// +// STREAM-START(utf-8) +// FLOW-SEQUENCE-START +// SCALAR("item 1",plain) +// FLOW-ENTRY +// SCALAR("item 2",plain) +// FLOW-ENTRY +// SCALAR("item 3",plain) +// FLOW-SEQUENCE-END +// STREAM-END +// +// 2. A flow mapping: +// +// { +// a simple key: a value, # Note that the KEY token is produced. +// ? a complex key: another value, +// } +// +// Tokens: +// +// STREAM-START(utf-8) +// FLOW-MAPPING-START +// KEY +// SCALAR("a simple key",plain) +// VALUE +// SCALAR("a value",plain) +// FLOW-ENTRY +// KEY +// SCALAR("a complex key",plain) +// VALUE +// SCALAR("another value",plain) +// FLOW-ENTRY +// FLOW-MAPPING-END +// STREAM-END +// +// A simple key is a key which is not denoted by the '?' indicator. Note that +// the Scanner still produce the KEY token whenever it encounters a simple key. +// +// For scanning block collections, the following tokens are used (note that we +// repeat KEY and VALUE here): +// +// BLOCK-SEQUENCE-START +// BLOCK-MAPPING-START +// BLOCK-END +// BLOCK-ENTRY +// KEY +// VALUE +// +// The tokens BLOCK-SEQUENCE-START and BLOCK-MAPPING-START denote indentation +// increase that precedes a block collection (cf. the INDENT token in Python). +// The token BLOCK-END denote indentation decrease that ends a block collection +// (cf. the DEDENT token in Python). However YAML has some syntax pecularities +// that makes detections of these tokens more complex. +// +// The tokens BLOCK-ENTRY, KEY, and VALUE are used to represent the indicators +// '-', '?', and ':' correspondingly. +// +// The following examples show how the tokens BLOCK-SEQUENCE-START, +// BLOCK-MAPPING-START, and BLOCK-END are emitted by the Scanner: +// +// 1. Block sequences: +// +// - item 1 +// - item 2 +// - +// - item 3.1 +// - item 3.2 +// - +// key 1: value 1 +// key 2: value 2 +// +// Tokens: +// +// STREAM-START(utf-8) +// BLOCK-SEQUENCE-START +// BLOCK-ENTRY +// SCALAR("item 1",plain) +// BLOCK-ENTRY +// SCALAR("item 2",plain) +// BLOCK-ENTRY +// BLOCK-SEQUENCE-START +// BLOCK-ENTRY +// SCALAR("item 3.1",plain) +// BLOCK-ENTRY +// SCALAR("item 3.2",plain) +// BLOCK-END +// BLOCK-ENTRY +// BLOCK-MAPPING-START +// KEY +// SCALAR("key 1",plain) +// VALUE +// SCALAR("value 1",plain) +// KEY +// SCALAR("key 2",plain) +// VALUE +// SCALAR("value 2",plain) +// BLOCK-END +// BLOCK-END +// STREAM-END +// +// 2. Block mappings: +// +// a simple key: a value # The KEY token is produced here. +// ? a complex key +// : another value +// a mapping: +// key 1: value 1 +// key 2: value 2 +// a sequence: +// - item 1 +// - item 2 +// +// Tokens: +// +// STREAM-START(utf-8) +// BLOCK-MAPPING-START +// KEY +// SCALAR("a simple key",plain) +// VALUE +// SCALAR("a value",plain) +// KEY +// SCALAR("a complex key",plain) +// VALUE +// SCALAR("another value",plain) +// KEY +// SCALAR("a mapping",plain) +// BLOCK-MAPPING-START +// KEY +// SCALAR("key 1",plain) +// VALUE +// SCALAR("value 1",plain) +// KEY +// SCALAR("key 2",plain) +// VALUE +// SCALAR("value 2",plain) +// BLOCK-END +// KEY +// SCALAR("a sequence",plain) +// VALUE +// BLOCK-SEQUENCE-START +// BLOCK-ENTRY +// SCALAR("item 1",plain) +// BLOCK-ENTRY +// SCALAR("item 2",plain) +// BLOCK-END +// BLOCK-END +// STREAM-END +// +// YAML does not always require to start a new block collection from a new +// line. If the current line contains only '-', '?', and ':' indicators, a new +// block collection may start at the current line. The following examples +// illustrate this case: +// +// 1. Collections in a sequence: +// +// - - item 1 +// - item 2 +// - key 1: value 1 +// key 2: value 2 +// - ? complex key +// : complex value +// +// Tokens: +// +// STREAM-START(utf-8) +// BLOCK-SEQUENCE-START +// BLOCK-ENTRY +// BLOCK-SEQUENCE-START +// BLOCK-ENTRY +// SCALAR("item 1",plain) +// BLOCK-ENTRY +// SCALAR("item 2",plain) +// BLOCK-END +// BLOCK-ENTRY +// BLOCK-MAPPING-START +// KEY +// SCALAR("key 1",plain) +// VALUE +// SCALAR("value 1",plain) +// KEY +// SCALAR("key 2",plain) +// VALUE +// SCALAR("value 2",plain) +// BLOCK-END +// BLOCK-ENTRY +// BLOCK-MAPPING-START +// KEY +// SCALAR("complex key") +// VALUE +// SCALAR("complex value") +// BLOCK-END +// BLOCK-END +// STREAM-END +// +// 2. Collections in a mapping: +// +// ? a sequence +// : - item 1 +// - item 2 +// ? a mapping +// : key 1: value 1 +// key 2: value 2 +// +// Tokens: +// +// STREAM-START(utf-8) +// BLOCK-MAPPING-START +// KEY +// SCALAR("a sequence",plain) +// VALUE +// BLOCK-SEQUENCE-START +// BLOCK-ENTRY +// SCALAR("item 1",plain) +// BLOCK-ENTRY +// SCALAR("item 2",plain) +// BLOCK-END +// KEY +// SCALAR("a mapping",plain) +// VALUE +// BLOCK-MAPPING-START +// KEY +// SCALAR("key 1",plain) +// VALUE +// SCALAR("value 1",plain) +// KEY +// SCALAR("key 2",plain) +// VALUE +// SCALAR("value 2",plain) +// BLOCK-END +// BLOCK-END +// STREAM-END +// +// YAML also permits non-indented sequences if they are included into a block +// mapping. In this case, the token BLOCK-SEQUENCE-START is not produced: +// +// key: +// - item 1 # BLOCK-SEQUENCE-START is NOT produced here. +// - item 2 +// +// Tokens: +// +// STREAM-START(utf-8) +// BLOCK-MAPPING-START +// KEY +// SCALAR("key",plain) +// VALUE +// BLOCK-ENTRY +// SCALAR("item 1",plain) +// BLOCK-ENTRY +// SCALAR("item 2",plain) +// BLOCK-END +// + +// Ensure that the buffer contains the required number of characters. +// Return true on success, false on failure (reader error or memory error). +func cache(parser *yaml_parser_t, length int) bool { + // [Go] This was inlined: !cache(A, B) -> unread < B && !update(A, B) + return parser.unread >= length || yaml_parser_update_buffer(parser, length) +} + +// Advance the buffer pointer. +func skip(parser *yaml_parser_t) { + parser.mark.index++ + parser.mark.column++ + parser.unread-- + parser.buffer_pos += width(parser.buffer[parser.buffer_pos]) +} + +func skip_line(parser *yaml_parser_t) { + if is_crlf(parser.buffer, parser.buffer_pos) { + parser.mark.index += 2 + parser.mark.column = 0 + parser.mark.line++ + parser.unread -= 2 + parser.buffer_pos += 2 + } else if is_break(parser.buffer, parser.buffer_pos) { + parser.mark.index++ + parser.mark.column = 0 + parser.mark.line++ + parser.unread-- + parser.buffer_pos += width(parser.buffer[parser.buffer_pos]) + } +} + +// Copy a character to a string buffer and advance pointers. +func read(parser *yaml_parser_t, s []byte) []byte { + w := width(parser.buffer[parser.buffer_pos]) + if w == 0 { + panic("invalid character sequence") + } + if len(s) == 0 { + s = make([]byte, 0, 32) + } + if w == 1 && len(s)+w <= cap(s) { + s = s[:len(s)+1] + s[len(s)-1] = parser.buffer[parser.buffer_pos] + parser.buffer_pos++ + } else { + s = append(s, parser.buffer[parser.buffer_pos:parser.buffer_pos+w]...) + parser.buffer_pos += w + } + parser.mark.index++ + parser.mark.column++ + parser.unread-- + return s +} + +// Copy a line break character to a string buffer and advance pointers. +func read_line(parser *yaml_parser_t, s []byte) []byte { + buf := parser.buffer + pos := parser.buffer_pos + switch { + case buf[pos] == '\r' && buf[pos+1] == '\n': + // CR LF . LF + s = append(s, '\n') + parser.buffer_pos += 2 + parser.mark.index++ + parser.unread-- + case buf[pos] == '\r' || buf[pos] == '\n': + // CR|LF . LF + s = append(s, '\n') + parser.buffer_pos += 1 + case buf[pos] == '\xC2' && buf[pos+1] == '\x85': + // NEL . LF + s = append(s, '\n') + parser.buffer_pos += 2 + case buf[pos] == '\xE2' && buf[pos+1] == '\x80' && (buf[pos+2] == '\xA8' || buf[pos+2] == '\xA9'): + // LS|PS . LS|PS + s = append(s, buf[parser.buffer_pos:pos+3]...) + parser.buffer_pos += 3 + default: + return s + } + parser.mark.index++ + parser.mark.column = 0 + parser.mark.line++ + parser.unread-- + return s +} + +// Get the next token. +func yaml_parser_scan(parser *yaml_parser_t, token *yaml_token_t) bool { + // Erase the token object. + *token = yaml_token_t{} // [Go] Is this necessary? + + // No tokens after STREAM-END or error. + if parser.stream_end_produced || parser.error != yaml_NO_ERROR { + return true + } + + // Ensure that the tokens queue contains enough tokens. + if !parser.token_available { + if !yaml_parser_fetch_more_tokens(parser) { + return false + } + } + + // Fetch the next token from the queue. + *token = parser.tokens[parser.tokens_head] + parser.tokens_head++ + parser.tokens_parsed++ + parser.token_available = false + + if token.typ == yaml_STREAM_END_TOKEN { + parser.stream_end_produced = true + } + return true +} + +// Set the scanner error and return false. +func yaml_parser_set_scanner_error(parser *yaml_parser_t, context string, context_mark yaml_mark_t, problem string) bool { + parser.error = yaml_SCANNER_ERROR + parser.context = context + parser.context_mark = context_mark + parser.problem = problem + parser.problem_mark = parser.mark + return false +} + +func yaml_parser_set_scanner_tag_error(parser *yaml_parser_t, directive bool, context_mark yaml_mark_t, problem string) bool { + context := "while parsing a tag" + if directive { + context = "while parsing a %TAG directive" + } + return yaml_parser_set_scanner_error(parser, context, context_mark, problem) +} + +func trace(args ...interface{}) func() { + pargs := append([]interface{}{"+++"}, args...) + fmt.Println(pargs...) + pargs = append([]interface{}{"---"}, args...) + return func() { fmt.Println(pargs...) } +} + +// Ensure that the tokens queue contains at least one token which can be +// returned to the Parser. +func yaml_parser_fetch_more_tokens(parser *yaml_parser_t) bool { + // While we need more tokens to fetch, do it. + for { + if parser.tokens_head != len(parser.tokens) { + // If queue is non-empty, check if any potential simple key may + // occupy the head position. + head_tok_idx, ok := parser.simple_keys_by_tok[parser.tokens_parsed] + if !ok { + break + } else if valid, ok := yaml_simple_key_is_valid(parser, &parser.simple_keys[head_tok_idx]); !ok { + return false + } else if !valid { + break + } + } + // Fetch the next token. + if !yaml_parser_fetch_next_token(parser) { + return false + } + } + + parser.token_available = true + return true +} + +// The dispatcher for token fetchers. +func yaml_parser_fetch_next_token(parser *yaml_parser_t) bool { + // Ensure that the buffer is initialized. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + + // Check if we just started scanning. Fetch STREAM-START then. + if !parser.stream_start_produced { + return yaml_parser_fetch_stream_start(parser) + } + + // Eat whitespaces and comments until we reach the next token. + if !yaml_parser_scan_to_next_token(parser) { + return false + } + + // Check the indentation level against the current column. + if !yaml_parser_unroll_indent(parser, parser.mark.column) { + return false + } + + // Ensure that the buffer contains at least 4 characters. 4 is the length + // of the longest indicators ('--- ' and '... '). + if parser.unread < 4 && !yaml_parser_update_buffer(parser, 4) { + return false + } + + // Is it the end of the stream? + if is_z(parser.buffer, parser.buffer_pos) { + return yaml_parser_fetch_stream_end(parser) + } + + // Is it a directive? + if parser.mark.column == 0 && parser.buffer[parser.buffer_pos] == '%' { + return yaml_parser_fetch_directive(parser) + } + + buf := parser.buffer + pos := parser.buffer_pos + + // Is it the document start indicator? + if parser.mark.column == 0 && buf[pos] == '-' && buf[pos+1] == '-' && buf[pos+2] == '-' && is_blankz(buf, pos+3) { + return yaml_parser_fetch_document_indicator(parser, yaml_DOCUMENT_START_TOKEN) + } + + // Is it the document end indicator? + if parser.mark.column == 0 && buf[pos] == '.' && buf[pos+1] == '.' && buf[pos+2] == '.' && is_blankz(buf, pos+3) { + return yaml_parser_fetch_document_indicator(parser, yaml_DOCUMENT_END_TOKEN) + } + + // Is it the flow sequence start indicator? + if buf[pos] == '[' { + return yaml_parser_fetch_flow_collection_start(parser, yaml_FLOW_SEQUENCE_START_TOKEN) + } + + // Is it the flow mapping start indicator? + if parser.buffer[parser.buffer_pos] == '{' { + return yaml_parser_fetch_flow_collection_start(parser, yaml_FLOW_MAPPING_START_TOKEN) + } + + // Is it the flow sequence end indicator? + if parser.buffer[parser.buffer_pos] == ']' { + return yaml_parser_fetch_flow_collection_end(parser, + yaml_FLOW_SEQUENCE_END_TOKEN) + } + + // Is it the flow mapping end indicator? + if parser.buffer[parser.buffer_pos] == '}' { + return yaml_parser_fetch_flow_collection_end(parser, + yaml_FLOW_MAPPING_END_TOKEN) + } + + // Is it the flow entry indicator? + if parser.buffer[parser.buffer_pos] == ',' { + return yaml_parser_fetch_flow_entry(parser) + } + + // Is it the block entry indicator? + if parser.buffer[parser.buffer_pos] == '-' && is_blankz(parser.buffer, parser.buffer_pos+1) { + return yaml_parser_fetch_block_entry(parser) + } + + // Is it the key indicator? + if parser.buffer[parser.buffer_pos] == '?' && (parser.flow_level > 0 || is_blankz(parser.buffer, parser.buffer_pos+1)) { + return yaml_parser_fetch_key(parser) + } + + // Is it the value indicator? + if parser.buffer[parser.buffer_pos] == ':' && (parser.flow_level > 0 || is_blankz(parser.buffer, parser.buffer_pos+1)) { + return yaml_parser_fetch_value(parser) + } + + // Is it an alias? + if parser.buffer[parser.buffer_pos] == '*' { + return yaml_parser_fetch_anchor(parser, yaml_ALIAS_TOKEN) + } + + // Is it an anchor? + if parser.buffer[parser.buffer_pos] == '&' { + return yaml_parser_fetch_anchor(parser, yaml_ANCHOR_TOKEN) + } + + // Is it a tag? + if parser.buffer[parser.buffer_pos] == '!' { + return yaml_parser_fetch_tag(parser) + } + + // Is it a literal scalar? + if parser.buffer[parser.buffer_pos] == '|' && parser.flow_level == 0 { + return yaml_parser_fetch_block_scalar(parser, true) + } + + // Is it a folded scalar? + if parser.buffer[parser.buffer_pos] == '>' && parser.flow_level == 0 { + return yaml_parser_fetch_block_scalar(parser, false) + } + + // Is it a single-quoted scalar? + if parser.buffer[parser.buffer_pos] == '\'' { + return yaml_parser_fetch_flow_scalar(parser, true) + } + + // Is it a double-quoted scalar? + if parser.buffer[parser.buffer_pos] == '"' { + return yaml_parser_fetch_flow_scalar(parser, false) + } + + // Is it a plain scalar? + // + // A plain scalar may start with any non-blank characters except + // + // '-', '?', ':', ',', '[', ']', '{', '}', + // '#', '&', '*', '!', '|', '>', '\'', '\"', + // '%', '@', '`'. + // + // In the block context (and, for the '-' indicator, in the flow context + // too), it may also start with the characters + // + // '-', '?', ':' + // + // if it is followed by a non-space character. + // + // The last rule is more restrictive than the specification requires. + // [Go] Make this logic more reasonable. + //switch parser.buffer[parser.buffer_pos] { + //case '-', '?', ':', ',', '?', '-', ',', ':', ']', '[', '}', '{', '&', '#', '!', '*', '>', '|', '"', '\'', '@', '%', '-', '`': + //} + if !(is_blankz(parser.buffer, parser.buffer_pos) || parser.buffer[parser.buffer_pos] == '-' || + parser.buffer[parser.buffer_pos] == '?' || parser.buffer[parser.buffer_pos] == ':' || + parser.buffer[parser.buffer_pos] == ',' || parser.buffer[parser.buffer_pos] == '[' || + parser.buffer[parser.buffer_pos] == ']' || parser.buffer[parser.buffer_pos] == '{' || + parser.buffer[parser.buffer_pos] == '}' || parser.buffer[parser.buffer_pos] == '#' || + parser.buffer[parser.buffer_pos] == '&' || parser.buffer[parser.buffer_pos] == '*' || + parser.buffer[parser.buffer_pos] == '!' || parser.buffer[parser.buffer_pos] == '|' || + parser.buffer[parser.buffer_pos] == '>' || parser.buffer[parser.buffer_pos] == '\'' || + parser.buffer[parser.buffer_pos] == '"' || parser.buffer[parser.buffer_pos] == '%' || + parser.buffer[parser.buffer_pos] == '@' || parser.buffer[parser.buffer_pos] == '`') || + (parser.buffer[parser.buffer_pos] == '-' && !is_blank(parser.buffer, parser.buffer_pos+1)) || + (parser.flow_level == 0 && + (parser.buffer[parser.buffer_pos] == '?' || parser.buffer[parser.buffer_pos] == ':') && + !is_blankz(parser.buffer, parser.buffer_pos+1)) { + return yaml_parser_fetch_plain_scalar(parser) + } + + // If we don't determine the token type so far, it is an error. + return yaml_parser_set_scanner_error(parser, + "while scanning for the next token", parser.mark, + "found character that cannot start any token") +} + +func yaml_simple_key_is_valid(parser *yaml_parser_t, simple_key *yaml_simple_key_t) (valid, ok bool) { + if !simple_key.possible { + return false, true + } + + // The 1.2 specification says: + // + // "If the ? indicator is omitted, parsing needs to see past the + // implicit key to recognize it as such. To limit the amount of + // lookahead required, the “:” indicator must appear at most 1024 + // Unicode characters beyond the start of the key. In addition, the key + // is restricted to a single line." + // + if simple_key.mark.line < parser.mark.line || simple_key.mark.index+1024 < parser.mark.index { + // Check if the potential simple key to be removed is required. + if simple_key.required { + return false, yaml_parser_set_scanner_error(parser, + "while scanning a simple key", simple_key.mark, + "could not find expected ':'") + } + simple_key.possible = false + return false, true + } + return true, true +} + +// Check if a simple key may start at the current position and add it if +// needed. +func yaml_parser_save_simple_key(parser *yaml_parser_t) bool { + // A simple key is required at the current position if the scanner is in + // the block context and the current column coincides with the indentation + // level. + + required := parser.flow_level == 0 && parser.indent == parser.mark.column + + // + // If the current position may start a simple key, save it. + // + if parser.simple_key_allowed { + simple_key := yaml_simple_key_t{ + possible: true, + required: required, + token_number: parser.tokens_parsed + (len(parser.tokens) - parser.tokens_head), + mark: parser.mark, + } + + if !yaml_parser_remove_simple_key(parser) { + return false + } + parser.simple_keys[len(parser.simple_keys)-1] = simple_key + parser.simple_keys_by_tok[simple_key.token_number] = len(parser.simple_keys) - 1 + } + return true +} + +// Remove a potential simple key at the current flow level. +func yaml_parser_remove_simple_key(parser *yaml_parser_t) bool { + i := len(parser.simple_keys) - 1 + if parser.simple_keys[i].possible { + // If the key is required, it is an error. + if parser.simple_keys[i].required { + return yaml_parser_set_scanner_error(parser, + "while scanning a simple key", parser.simple_keys[i].mark, + "could not find expected ':'") + } + // Remove the key from the stack. + parser.simple_keys[i].possible = false + delete(parser.simple_keys_by_tok, parser.simple_keys[i].token_number) + } + return true +} + +// max_flow_level limits the flow_level +const max_flow_level = 10000 + +// Increase the flow level and resize the simple key list if needed. +func yaml_parser_increase_flow_level(parser *yaml_parser_t) bool { + // Reset the simple key on the next level. + parser.simple_keys = append(parser.simple_keys, yaml_simple_key_t{ + possible: false, + required: false, + token_number: parser.tokens_parsed + (len(parser.tokens) - parser.tokens_head), + mark: parser.mark, + }) + + // Increase the flow level. + parser.flow_level++ + if parser.flow_level > max_flow_level { + return yaml_parser_set_scanner_error(parser, + "while increasing flow level", parser.simple_keys[len(parser.simple_keys)-1].mark, + fmt.Sprintf("exceeded max depth of %d", max_flow_level)) + } + return true +} + +// Decrease the flow level. +func yaml_parser_decrease_flow_level(parser *yaml_parser_t) bool { + if parser.flow_level > 0 { + parser.flow_level-- + last := len(parser.simple_keys) - 1 + delete(parser.simple_keys_by_tok, parser.simple_keys[last].token_number) + parser.simple_keys = parser.simple_keys[:last] + } + return true +} + +// max_indents limits the indents stack size +const max_indents = 10000 + +// Push the current indentation level to the stack and set the new level +// the current column is greater than the indentation level. In this case, +// append or insert the specified token into the token queue. +func yaml_parser_roll_indent(parser *yaml_parser_t, column, number int, typ yaml_token_type_t, mark yaml_mark_t) bool { + // In the flow context, do nothing. + if parser.flow_level > 0 { + return true + } + + if parser.indent < column { + // Push the current indentation level to the stack and set the new + // indentation level. + parser.indents = append(parser.indents, parser.indent) + parser.indent = column + if len(parser.indents) > max_indents { + return yaml_parser_set_scanner_error(parser, + "while increasing indent level", parser.simple_keys[len(parser.simple_keys)-1].mark, + fmt.Sprintf("exceeded max depth of %d", max_indents)) + } + + // Create a token and insert it into the queue. + token := yaml_token_t{ + typ: typ, + start_mark: mark, + end_mark: mark, + } + if number > -1 { + number -= parser.tokens_parsed + } + yaml_insert_token(parser, number, &token) + } + return true +} + +// Pop indentation levels from the indents stack until the current level +// becomes less or equal to the column. For each indentation level, append +// the BLOCK-END token. +func yaml_parser_unroll_indent(parser *yaml_parser_t, column int) bool { + // In the flow context, do nothing. + if parser.flow_level > 0 { + return true + } + + // Loop through the indentation levels in the stack. + for parser.indent > column { + // Create a token and append it to the queue. + token := yaml_token_t{ + typ: yaml_BLOCK_END_TOKEN, + start_mark: parser.mark, + end_mark: parser.mark, + } + yaml_insert_token(parser, -1, &token) + + // Pop the indentation level. + parser.indent = parser.indents[len(parser.indents)-1] + parser.indents = parser.indents[:len(parser.indents)-1] + } + return true +} + +// Initialize the scanner and produce the STREAM-START token. +func yaml_parser_fetch_stream_start(parser *yaml_parser_t) bool { + + // Set the initial indentation. + parser.indent = -1 + + // Initialize the simple key stack. + parser.simple_keys = append(parser.simple_keys, yaml_simple_key_t{}) + + parser.simple_keys_by_tok = make(map[int]int) + + // A simple key is allowed at the beginning of the stream. + parser.simple_key_allowed = true + + // We have started. + parser.stream_start_produced = true + + // Create the STREAM-START token and append it to the queue. + token := yaml_token_t{ + typ: yaml_STREAM_START_TOKEN, + start_mark: parser.mark, + end_mark: parser.mark, + encoding: parser.encoding, + } + yaml_insert_token(parser, -1, &token) + return true +} + +// Produce the STREAM-END token and shut down the scanner. +func yaml_parser_fetch_stream_end(parser *yaml_parser_t) bool { + + // Force new line. + if parser.mark.column != 0 { + parser.mark.column = 0 + parser.mark.line++ + } + + // Reset the indentation level. + if !yaml_parser_unroll_indent(parser, -1) { + return false + } + + // Reset simple keys. + if !yaml_parser_remove_simple_key(parser) { + return false + } + + parser.simple_key_allowed = false + + // Create the STREAM-END token and append it to the queue. + token := yaml_token_t{ + typ: yaml_STREAM_END_TOKEN, + start_mark: parser.mark, + end_mark: parser.mark, + } + yaml_insert_token(parser, -1, &token) + return true +} + +// Produce a VERSION-DIRECTIVE or TAG-DIRECTIVE token. +func yaml_parser_fetch_directive(parser *yaml_parser_t) bool { + // Reset the indentation level. + if !yaml_parser_unroll_indent(parser, -1) { + return false + } + + // Reset simple keys. + if !yaml_parser_remove_simple_key(parser) { + return false + } + + parser.simple_key_allowed = false + + // Create the YAML-DIRECTIVE or TAG-DIRECTIVE token. + token := yaml_token_t{} + if !yaml_parser_scan_directive(parser, &token) { + return false + } + // Append the token to the queue. + yaml_insert_token(parser, -1, &token) + return true +} + +// Produce the DOCUMENT-START or DOCUMENT-END token. +func yaml_parser_fetch_document_indicator(parser *yaml_parser_t, typ yaml_token_type_t) bool { + // Reset the indentation level. + if !yaml_parser_unroll_indent(parser, -1) { + return false + } + + // Reset simple keys. + if !yaml_parser_remove_simple_key(parser) { + return false + } + + parser.simple_key_allowed = false + + // Consume the token. + start_mark := parser.mark + + skip(parser) + skip(parser) + skip(parser) + + end_mark := parser.mark + + // Create the DOCUMENT-START or DOCUMENT-END token. + token := yaml_token_t{ + typ: typ, + start_mark: start_mark, + end_mark: end_mark, + } + // Append the token to the queue. + yaml_insert_token(parser, -1, &token) + return true +} + +// Produce the FLOW-SEQUENCE-START or FLOW-MAPPING-START token. +func yaml_parser_fetch_flow_collection_start(parser *yaml_parser_t, typ yaml_token_type_t) bool { + // The indicators '[' and '{' may start a simple key. + if !yaml_parser_save_simple_key(parser) { + return false + } + + // Increase the flow level. + if !yaml_parser_increase_flow_level(parser) { + return false + } + + // A simple key may follow the indicators '[' and '{'. + parser.simple_key_allowed = true + + // Consume the token. + start_mark := parser.mark + skip(parser) + end_mark := parser.mark + + // Create the FLOW-SEQUENCE-START of FLOW-MAPPING-START token. + token := yaml_token_t{ + typ: typ, + start_mark: start_mark, + end_mark: end_mark, + } + // Append the token to the queue. + yaml_insert_token(parser, -1, &token) + return true +} + +// Produce the FLOW-SEQUENCE-END or FLOW-MAPPING-END token. +func yaml_parser_fetch_flow_collection_end(parser *yaml_parser_t, typ yaml_token_type_t) bool { + // Reset any potential simple key on the current flow level. + if !yaml_parser_remove_simple_key(parser) { + return false + } + + // Decrease the flow level. + if !yaml_parser_decrease_flow_level(parser) { + return false + } + + // No simple keys after the indicators ']' and '}'. + parser.simple_key_allowed = false + + // Consume the token. + + start_mark := parser.mark + skip(parser) + end_mark := parser.mark + + // Create the FLOW-SEQUENCE-END of FLOW-MAPPING-END token. + token := yaml_token_t{ + typ: typ, + start_mark: start_mark, + end_mark: end_mark, + } + // Append the token to the queue. + yaml_insert_token(parser, -1, &token) + return true +} + +// Produce the FLOW-ENTRY token. +func yaml_parser_fetch_flow_entry(parser *yaml_parser_t) bool { + // Reset any potential simple keys on the current flow level. + if !yaml_parser_remove_simple_key(parser) { + return false + } + + // Simple keys are allowed after ','. + parser.simple_key_allowed = true + + // Consume the token. + start_mark := parser.mark + skip(parser) + end_mark := parser.mark + + // Create the FLOW-ENTRY token and append it to the queue. + token := yaml_token_t{ + typ: yaml_FLOW_ENTRY_TOKEN, + start_mark: start_mark, + end_mark: end_mark, + } + yaml_insert_token(parser, -1, &token) + return true +} + +// Produce the BLOCK-ENTRY token. +func yaml_parser_fetch_block_entry(parser *yaml_parser_t) bool { + // Check if the scanner is in the block context. + if parser.flow_level == 0 { + // Check if we are allowed to start a new entry. + if !parser.simple_key_allowed { + return yaml_parser_set_scanner_error(parser, "", parser.mark, + "block sequence entries are not allowed in this context") + } + // Add the BLOCK-SEQUENCE-START token if needed. + if !yaml_parser_roll_indent(parser, parser.mark.column, -1, yaml_BLOCK_SEQUENCE_START_TOKEN, parser.mark) { + return false + } + } else { + // It is an error for the '-' indicator to occur in the flow context, + // but we let the Parser detect and report about it because the Parser + // is able to point to the context. + } + + // Reset any potential simple keys on the current flow level. + if !yaml_parser_remove_simple_key(parser) { + return false + } + + // Simple keys are allowed after '-'. + parser.simple_key_allowed = true + + // Consume the token. + start_mark := parser.mark + skip(parser) + end_mark := parser.mark + + // Create the BLOCK-ENTRY token and append it to the queue. + token := yaml_token_t{ + typ: yaml_BLOCK_ENTRY_TOKEN, + start_mark: start_mark, + end_mark: end_mark, + } + yaml_insert_token(parser, -1, &token) + return true +} + +// Produce the KEY token. +func yaml_parser_fetch_key(parser *yaml_parser_t) bool { + + // In the block context, additional checks are required. + if parser.flow_level == 0 { + // Check if we are allowed to start a new key (not nessesary simple). + if !parser.simple_key_allowed { + return yaml_parser_set_scanner_error(parser, "", parser.mark, + "mapping keys are not allowed in this context") + } + // Add the BLOCK-MAPPING-START token if needed. + if !yaml_parser_roll_indent(parser, parser.mark.column, -1, yaml_BLOCK_MAPPING_START_TOKEN, parser.mark) { + return false + } + } + + // Reset any potential simple keys on the current flow level. + if !yaml_parser_remove_simple_key(parser) { + return false + } + + // Simple keys are allowed after '?' in the block context. + parser.simple_key_allowed = parser.flow_level == 0 + + // Consume the token. + start_mark := parser.mark + skip(parser) + end_mark := parser.mark + + // Create the KEY token and append it to the queue. + token := yaml_token_t{ + typ: yaml_KEY_TOKEN, + start_mark: start_mark, + end_mark: end_mark, + } + yaml_insert_token(parser, -1, &token) + return true +} + +// Produce the VALUE token. +func yaml_parser_fetch_value(parser *yaml_parser_t) bool { + + simple_key := &parser.simple_keys[len(parser.simple_keys)-1] + + // Have we found a simple key? + if valid, ok := yaml_simple_key_is_valid(parser, simple_key); !ok { + return false + + } else if valid { + + // Create the KEY token and insert it into the queue. + token := yaml_token_t{ + typ: yaml_KEY_TOKEN, + start_mark: simple_key.mark, + end_mark: simple_key.mark, + } + yaml_insert_token(parser, simple_key.token_number-parser.tokens_parsed, &token) + + // In the block context, we may need to add the BLOCK-MAPPING-START token. + if !yaml_parser_roll_indent(parser, simple_key.mark.column, + simple_key.token_number, + yaml_BLOCK_MAPPING_START_TOKEN, simple_key.mark) { + return false + } + + // Remove the simple key. + simple_key.possible = false + delete(parser.simple_keys_by_tok, simple_key.token_number) + + // A simple key cannot follow another simple key. + parser.simple_key_allowed = false + + } else { + // The ':' indicator follows a complex key. + + // In the block context, extra checks are required. + if parser.flow_level == 0 { + + // Check if we are allowed to start a complex value. + if !parser.simple_key_allowed { + return yaml_parser_set_scanner_error(parser, "", parser.mark, + "mapping values are not allowed in this context") + } + + // Add the BLOCK-MAPPING-START token if needed. + if !yaml_parser_roll_indent(parser, parser.mark.column, -1, yaml_BLOCK_MAPPING_START_TOKEN, parser.mark) { + return false + } + } + + // Simple keys after ':' are allowed in the block context. + parser.simple_key_allowed = parser.flow_level == 0 + } + + // Consume the token. + start_mark := parser.mark + skip(parser) + end_mark := parser.mark + + // Create the VALUE token and append it to the queue. + token := yaml_token_t{ + typ: yaml_VALUE_TOKEN, + start_mark: start_mark, + end_mark: end_mark, + } + yaml_insert_token(parser, -1, &token) + return true +} + +// Produce the ALIAS or ANCHOR token. +func yaml_parser_fetch_anchor(parser *yaml_parser_t, typ yaml_token_type_t) bool { + // An anchor or an alias could be a simple key. + if !yaml_parser_save_simple_key(parser) { + return false + } + + // A simple key cannot follow an anchor or an alias. + parser.simple_key_allowed = false + + // Create the ALIAS or ANCHOR token and append it to the queue. + var token yaml_token_t + if !yaml_parser_scan_anchor(parser, &token, typ) { + return false + } + yaml_insert_token(parser, -1, &token) + return true +} + +// Produce the TAG token. +func yaml_parser_fetch_tag(parser *yaml_parser_t) bool { + // A tag could be a simple key. + if !yaml_parser_save_simple_key(parser) { + return false + } + + // A simple key cannot follow a tag. + parser.simple_key_allowed = false + + // Create the TAG token and append it to the queue. + var token yaml_token_t + if !yaml_parser_scan_tag(parser, &token) { + return false + } + yaml_insert_token(parser, -1, &token) + return true +} + +// Produce the SCALAR(...,literal) or SCALAR(...,folded) tokens. +func yaml_parser_fetch_block_scalar(parser *yaml_parser_t, literal bool) bool { + // Remove any potential simple keys. + if !yaml_parser_remove_simple_key(parser) { + return false + } + + // A simple key may follow a block scalar. + parser.simple_key_allowed = true + + // Create the SCALAR token and append it to the queue. + var token yaml_token_t + if !yaml_parser_scan_block_scalar(parser, &token, literal) { + return false + } + yaml_insert_token(parser, -1, &token) + return true +} + +// Produce the SCALAR(...,single-quoted) or SCALAR(...,double-quoted) tokens. +func yaml_parser_fetch_flow_scalar(parser *yaml_parser_t, single bool) bool { + // A plain scalar could be a simple key. + if !yaml_parser_save_simple_key(parser) { + return false + } + + // A simple key cannot follow a flow scalar. + parser.simple_key_allowed = false + + // Create the SCALAR token and append it to the queue. + var token yaml_token_t + if !yaml_parser_scan_flow_scalar(parser, &token, single) { + return false + } + yaml_insert_token(parser, -1, &token) + return true +} + +// Produce the SCALAR(...,plain) token. +func yaml_parser_fetch_plain_scalar(parser *yaml_parser_t) bool { + // A plain scalar could be a simple key. + if !yaml_parser_save_simple_key(parser) { + return false + } + + // A simple key cannot follow a flow scalar. + parser.simple_key_allowed = false + + // Create the SCALAR token and append it to the queue. + var token yaml_token_t + if !yaml_parser_scan_plain_scalar(parser, &token) { + return false + } + yaml_insert_token(parser, -1, &token) + return true +} + +// Eat whitespaces and comments until the next token is found. +func yaml_parser_scan_to_next_token(parser *yaml_parser_t) bool { + + // Until the next token is not found. + for { + // Allow the BOM mark to start a line. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + if parser.mark.column == 0 && is_bom(parser.buffer, parser.buffer_pos) { + skip(parser) + } + + // Eat whitespaces. + // Tabs are allowed: + // - in the flow context + // - in the block context, but not at the beginning of the line or + // after '-', '?', or ':' (complex value). + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + + for parser.buffer[parser.buffer_pos] == ' ' || ((parser.flow_level > 0 || !parser.simple_key_allowed) && parser.buffer[parser.buffer_pos] == '\t') { + skip(parser) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + + // Eat a comment until a line break. + if parser.buffer[parser.buffer_pos] == '#' { + for !is_breakz(parser.buffer, parser.buffer_pos) { + skip(parser) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + } + + // If it is a line break, eat it. + if is_break(parser.buffer, parser.buffer_pos) { + if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { + return false + } + skip_line(parser) + + // In the block context, a new line may start a simple key. + if parser.flow_level == 0 { + parser.simple_key_allowed = true + } + } else { + break // We have found a token. + } + } + + return true +} + +// Scan a YAML-DIRECTIVE or TAG-DIRECTIVE token. +// +// Scope: +// %YAML 1.1 # a comment \n +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// %TAG !yaml! tag:yaml.org,2002: \n +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// +func yaml_parser_scan_directive(parser *yaml_parser_t, token *yaml_token_t) bool { + // Eat '%'. + start_mark := parser.mark + skip(parser) + + // Scan the directive name. + var name []byte + if !yaml_parser_scan_directive_name(parser, start_mark, &name) { + return false + } + + // Is it a YAML directive? + if bytes.Equal(name, []byte("YAML")) { + // Scan the VERSION directive value. + var major, minor int8 + if !yaml_parser_scan_version_directive_value(parser, start_mark, &major, &minor) { + return false + } + end_mark := parser.mark + + // Create a VERSION-DIRECTIVE token. + *token = yaml_token_t{ + typ: yaml_VERSION_DIRECTIVE_TOKEN, + start_mark: start_mark, + end_mark: end_mark, + major: major, + minor: minor, + } + + // Is it a TAG directive? + } else if bytes.Equal(name, []byte("TAG")) { + // Scan the TAG directive value. + var handle, prefix []byte + if !yaml_parser_scan_tag_directive_value(parser, start_mark, &handle, &prefix) { + return false + } + end_mark := parser.mark + + // Create a TAG-DIRECTIVE token. + *token = yaml_token_t{ + typ: yaml_TAG_DIRECTIVE_TOKEN, + start_mark: start_mark, + end_mark: end_mark, + value: handle, + prefix: prefix, + } + + // Unknown directive. + } else { + yaml_parser_set_scanner_error(parser, "while scanning a directive", + start_mark, "found unknown directive name") + return false + } + + // Eat the rest of the line including any comments. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + + for is_blank(parser.buffer, parser.buffer_pos) { + skip(parser) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + + if parser.buffer[parser.buffer_pos] == '#' { + for !is_breakz(parser.buffer, parser.buffer_pos) { + skip(parser) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + } + + // Check if we are at the end of the line. + if !is_breakz(parser.buffer, parser.buffer_pos) { + yaml_parser_set_scanner_error(parser, "while scanning a directive", + start_mark, "did not find expected comment or line break") + return false + } + + // Eat a line break. + if is_break(parser.buffer, parser.buffer_pos) { + if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { + return false + } + skip_line(parser) + } + + return true +} + +// Scan the directive name. +// +// Scope: +// %YAML 1.1 # a comment \n +// ^^^^ +// %TAG !yaml! tag:yaml.org,2002: \n +// ^^^ +// +func yaml_parser_scan_directive_name(parser *yaml_parser_t, start_mark yaml_mark_t, name *[]byte) bool { + // Consume the directive name. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + + var s []byte + for is_alpha(parser.buffer, parser.buffer_pos) { + s = read(parser, s) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + + // Check if the name is empty. + if len(s) == 0 { + yaml_parser_set_scanner_error(parser, "while scanning a directive", + start_mark, "could not find expected directive name") + return false + } + + // Check for an blank character after the name. + if !is_blankz(parser.buffer, parser.buffer_pos) { + yaml_parser_set_scanner_error(parser, "while scanning a directive", + start_mark, "found unexpected non-alphabetical character") + return false + } + *name = s + return true +} + +// Scan the value of VERSION-DIRECTIVE. +// +// Scope: +// %YAML 1.1 # a comment \n +// ^^^^^^ +func yaml_parser_scan_version_directive_value(parser *yaml_parser_t, start_mark yaml_mark_t, major, minor *int8) bool { + // Eat whitespaces. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + for is_blank(parser.buffer, parser.buffer_pos) { + skip(parser) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + + // Consume the major version number. + if !yaml_parser_scan_version_directive_number(parser, start_mark, major) { + return false + } + + // Eat '.'. + if parser.buffer[parser.buffer_pos] != '.' { + return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive", + start_mark, "did not find expected digit or '.' character") + } + + skip(parser) + + // Consume the minor version number. + if !yaml_parser_scan_version_directive_number(parser, start_mark, minor) { + return false + } + return true +} + +const max_number_length = 2 + +// Scan the version number of VERSION-DIRECTIVE. +// +// Scope: +// %YAML 1.1 # a comment \n +// ^ +// %YAML 1.1 # a comment \n +// ^ +func yaml_parser_scan_version_directive_number(parser *yaml_parser_t, start_mark yaml_mark_t, number *int8) bool { + + // Repeat while the next character is digit. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + var value, length int8 + for is_digit(parser.buffer, parser.buffer_pos) { + // Check if the number is too long. + length++ + if length > max_number_length { + return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive", + start_mark, "found extremely long version number") + } + value = value*10 + int8(as_digit(parser.buffer, parser.buffer_pos)) + skip(parser) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + + // Check if the number was present. + if length == 0 { + return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive", + start_mark, "did not find expected version number") + } + *number = value + return true +} + +// Scan the value of a TAG-DIRECTIVE token. +// +// Scope: +// %TAG !yaml! tag:yaml.org,2002: \n +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// +func yaml_parser_scan_tag_directive_value(parser *yaml_parser_t, start_mark yaml_mark_t, handle, prefix *[]byte) bool { + var handle_value, prefix_value []byte + + // Eat whitespaces. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + + for is_blank(parser.buffer, parser.buffer_pos) { + skip(parser) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + + // Scan a handle. + if !yaml_parser_scan_tag_handle(parser, true, start_mark, &handle_value) { + return false + } + + // Expect a whitespace. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + if !is_blank(parser.buffer, parser.buffer_pos) { + yaml_parser_set_scanner_error(parser, "while scanning a %TAG directive", + start_mark, "did not find expected whitespace") + return false + } + + // Eat whitespaces. + for is_blank(parser.buffer, parser.buffer_pos) { + skip(parser) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + + // Scan a prefix. + if !yaml_parser_scan_tag_uri(parser, true, nil, start_mark, &prefix_value) { + return false + } + + // Expect a whitespace or line break. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + if !is_blankz(parser.buffer, parser.buffer_pos) { + yaml_parser_set_scanner_error(parser, "while scanning a %TAG directive", + start_mark, "did not find expected whitespace or line break") + return false + } + + *handle = handle_value + *prefix = prefix_value + return true +} + +func yaml_parser_scan_anchor(parser *yaml_parser_t, token *yaml_token_t, typ yaml_token_type_t) bool { + var s []byte + + // Eat the indicator character. + start_mark := parser.mark + skip(parser) + + // Consume the value. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + + for is_alpha(parser.buffer, parser.buffer_pos) { + s = read(parser, s) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + + end_mark := parser.mark + + /* + * Check if length of the anchor is greater than 0 and it is followed by + * a whitespace character or one of the indicators: + * + * '?', ':', ',', ']', '}', '%', '@', '`'. + */ + + if len(s) == 0 || + !(is_blankz(parser.buffer, parser.buffer_pos) || parser.buffer[parser.buffer_pos] == '?' || + parser.buffer[parser.buffer_pos] == ':' || parser.buffer[parser.buffer_pos] == ',' || + parser.buffer[parser.buffer_pos] == ']' || parser.buffer[parser.buffer_pos] == '}' || + parser.buffer[parser.buffer_pos] == '%' || parser.buffer[parser.buffer_pos] == '@' || + parser.buffer[parser.buffer_pos] == '`') { + context := "while scanning an alias" + if typ == yaml_ANCHOR_TOKEN { + context = "while scanning an anchor" + } + yaml_parser_set_scanner_error(parser, context, start_mark, + "did not find expected alphabetic or numeric character") + return false + } + + // Create a token. + *token = yaml_token_t{ + typ: typ, + start_mark: start_mark, + end_mark: end_mark, + value: s, + } + + return true +} + +/* + * Scan a TAG token. + */ + +func yaml_parser_scan_tag(parser *yaml_parser_t, token *yaml_token_t) bool { + var handle, suffix []byte + + start_mark := parser.mark + + // Check if the tag is in the canonical form. + if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { + return false + } + + if parser.buffer[parser.buffer_pos+1] == '<' { + // Keep the handle as '' + + // Eat '!<' + skip(parser) + skip(parser) + + // Consume the tag value. + if !yaml_parser_scan_tag_uri(parser, false, nil, start_mark, &suffix) { + return false + } + + // Check for '>' and eat it. + if parser.buffer[parser.buffer_pos] != '>' { + yaml_parser_set_scanner_error(parser, "while scanning a tag", + start_mark, "did not find the expected '>'") + return false + } + + skip(parser) + } else { + // The tag has either the '!suffix' or the '!handle!suffix' form. + + // First, try to scan a handle. + if !yaml_parser_scan_tag_handle(parser, false, start_mark, &handle) { + return false + } + + // Check if it is, indeed, handle. + if handle[0] == '!' && len(handle) > 1 && handle[len(handle)-1] == '!' { + // Scan the suffix now. + if !yaml_parser_scan_tag_uri(parser, false, nil, start_mark, &suffix) { + return false + } + } else { + // It wasn't a handle after all. Scan the rest of the tag. + if !yaml_parser_scan_tag_uri(parser, false, handle, start_mark, &suffix) { + return false + } + + // Set the handle to '!'. + handle = []byte{'!'} + + // A special case: the '!' tag. Set the handle to '' and the + // suffix to '!'. + if len(suffix) == 0 { + handle, suffix = suffix, handle + } + } + } + + // Check the character which ends the tag. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + if !is_blankz(parser.buffer, parser.buffer_pos) { + yaml_parser_set_scanner_error(parser, "while scanning a tag", + start_mark, "did not find expected whitespace or line break") + return false + } + + end_mark := parser.mark + + // Create a token. + *token = yaml_token_t{ + typ: yaml_TAG_TOKEN, + start_mark: start_mark, + end_mark: end_mark, + value: handle, + suffix: suffix, + } + return true +} + +// Scan a tag handle. +func yaml_parser_scan_tag_handle(parser *yaml_parser_t, directive bool, start_mark yaml_mark_t, handle *[]byte) bool { + // Check the initial '!' character. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + if parser.buffer[parser.buffer_pos] != '!' { + yaml_parser_set_scanner_tag_error(parser, directive, + start_mark, "did not find expected '!'") + return false + } + + var s []byte + + // Copy the '!' character. + s = read(parser, s) + + // Copy all subsequent alphabetical and numerical characters. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + for is_alpha(parser.buffer, parser.buffer_pos) { + s = read(parser, s) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + + // Check if the trailing character is '!' and copy it. + if parser.buffer[parser.buffer_pos] == '!' { + s = read(parser, s) + } else { + // It's either the '!' tag or not really a tag handle. If it's a %TAG + // directive, it's an error. If it's a tag token, it must be a part of URI. + if directive && string(s) != "!" { + yaml_parser_set_scanner_tag_error(parser, directive, + start_mark, "did not find expected '!'") + return false + } + } + + *handle = s + return true +} + +// Scan a tag. +func yaml_parser_scan_tag_uri(parser *yaml_parser_t, directive bool, head []byte, start_mark yaml_mark_t, uri *[]byte) bool { + //size_t length = head ? strlen((char *)head) : 0 + var s []byte + hasTag := len(head) > 0 + + // Copy the head if needed. + // + // Note that we don't copy the leading '!' character. + if len(head) > 1 { + s = append(s, head[1:]...) + } + + // Scan the tag. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + + // The set of characters that may appear in URI is as follows: + // + // '0'-'9', 'A'-'Z', 'a'-'z', '_', '-', ';', '/', '?', ':', '@', '&', + // '=', '+', '$', ',', '.', '!', '~', '*', '\'', '(', ')', '[', ']', + // '%'. + // [Go] Convert this into more reasonable logic. + for is_alpha(parser.buffer, parser.buffer_pos) || parser.buffer[parser.buffer_pos] == ';' || + parser.buffer[parser.buffer_pos] == '/' || parser.buffer[parser.buffer_pos] == '?' || + parser.buffer[parser.buffer_pos] == ':' || parser.buffer[parser.buffer_pos] == '@' || + parser.buffer[parser.buffer_pos] == '&' || parser.buffer[parser.buffer_pos] == '=' || + parser.buffer[parser.buffer_pos] == '+' || parser.buffer[parser.buffer_pos] == '$' || + parser.buffer[parser.buffer_pos] == ',' || parser.buffer[parser.buffer_pos] == '.' || + parser.buffer[parser.buffer_pos] == '!' || parser.buffer[parser.buffer_pos] == '~' || + parser.buffer[parser.buffer_pos] == '*' || parser.buffer[parser.buffer_pos] == '\'' || + parser.buffer[parser.buffer_pos] == '(' || parser.buffer[parser.buffer_pos] == ')' || + parser.buffer[parser.buffer_pos] == '[' || parser.buffer[parser.buffer_pos] == ']' || + parser.buffer[parser.buffer_pos] == '%' { + // Check if it is a URI-escape sequence. + if parser.buffer[parser.buffer_pos] == '%' { + if !yaml_parser_scan_uri_escapes(parser, directive, start_mark, &s) { + return false + } + } else { + s = read(parser, s) + } + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + hasTag = true + } + + if !hasTag { + yaml_parser_set_scanner_tag_error(parser, directive, + start_mark, "did not find expected tag URI") + return false + } + *uri = s + return true +} + +// Decode an URI-escape sequence corresponding to a single UTF-8 character. +func yaml_parser_scan_uri_escapes(parser *yaml_parser_t, directive bool, start_mark yaml_mark_t, s *[]byte) bool { + + // Decode the required number of characters. + w := 1024 + for w > 0 { + // Check for a URI-escaped octet. + if parser.unread < 3 && !yaml_parser_update_buffer(parser, 3) { + return false + } + + if !(parser.buffer[parser.buffer_pos] == '%' && + is_hex(parser.buffer, parser.buffer_pos+1) && + is_hex(parser.buffer, parser.buffer_pos+2)) { + return yaml_parser_set_scanner_tag_error(parser, directive, + start_mark, "did not find URI escaped octet") + } + + // Get the octet. + octet := byte((as_hex(parser.buffer, parser.buffer_pos+1) << 4) + as_hex(parser.buffer, parser.buffer_pos+2)) + + // If it is the leading octet, determine the length of the UTF-8 sequence. + if w == 1024 { + w = width(octet) + if w == 0 { + return yaml_parser_set_scanner_tag_error(parser, directive, + start_mark, "found an incorrect leading UTF-8 octet") + } + } else { + // Check if the trailing octet is correct. + if octet&0xC0 != 0x80 { + return yaml_parser_set_scanner_tag_error(parser, directive, + start_mark, "found an incorrect trailing UTF-8 octet") + } + } + + // Copy the octet and move the pointers. + *s = append(*s, octet) + skip(parser) + skip(parser) + skip(parser) + w-- + } + return true +} + +// Scan a block scalar. +func yaml_parser_scan_block_scalar(parser *yaml_parser_t, token *yaml_token_t, literal bool) bool { + // Eat the indicator '|' or '>'. + start_mark := parser.mark + skip(parser) + + // Scan the additional block scalar indicators. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + + // Check for a chomping indicator. + var chomping, increment int + if parser.buffer[parser.buffer_pos] == '+' || parser.buffer[parser.buffer_pos] == '-' { + // Set the chomping method and eat the indicator. + if parser.buffer[parser.buffer_pos] == '+' { + chomping = +1 + } else { + chomping = -1 + } + skip(parser) + + // Check for an indentation indicator. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + if is_digit(parser.buffer, parser.buffer_pos) { + // Check that the indentation is greater than 0. + if parser.buffer[parser.buffer_pos] == '0' { + yaml_parser_set_scanner_error(parser, "while scanning a block scalar", + start_mark, "found an indentation indicator equal to 0") + return false + } + + // Get the indentation level and eat the indicator. + increment = as_digit(parser.buffer, parser.buffer_pos) + skip(parser) + } + + } else if is_digit(parser.buffer, parser.buffer_pos) { + // Do the same as above, but in the opposite order. + + if parser.buffer[parser.buffer_pos] == '0' { + yaml_parser_set_scanner_error(parser, "while scanning a block scalar", + start_mark, "found an indentation indicator equal to 0") + return false + } + increment = as_digit(parser.buffer, parser.buffer_pos) + skip(parser) + + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + if parser.buffer[parser.buffer_pos] == '+' || parser.buffer[parser.buffer_pos] == '-' { + if parser.buffer[parser.buffer_pos] == '+' { + chomping = +1 + } else { + chomping = -1 + } + skip(parser) + } + } + + // Eat whitespaces and comments to the end of the line. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + for is_blank(parser.buffer, parser.buffer_pos) { + skip(parser) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + if parser.buffer[parser.buffer_pos] == '#' { + for !is_breakz(parser.buffer, parser.buffer_pos) { + skip(parser) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + } + + // Check if we are at the end of the line. + if !is_breakz(parser.buffer, parser.buffer_pos) { + yaml_parser_set_scanner_error(parser, "while scanning a block scalar", + start_mark, "did not find expected comment or line break") + return false + } + + // Eat a line break. + if is_break(parser.buffer, parser.buffer_pos) { + if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { + return false + } + skip_line(parser) + } + + end_mark := parser.mark + + // Set the indentation level if it was specified. + var indent int + if increment > 0 { + if parser.indent >= 0 { + indent = parser.indent + increment + } else { + indent = increment + } + } + + // Scan the leading line breaks and determine the indentation level if needed. + var s, leading_break, trailing_breaks []byte + if !yaml_parser_scan_block_scalar_breaks(parser, &indent, &trailing_breaks, start_mark, &end_mark) { + return false + } + + // Scan the block scalar content. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + var leading_blank, trailing_blank bool + for parser.mark.column == indent && !is_z(parser.buffer, parser.buffer_pos) { + // We are at the beginning of a non-empty line. + + // Is it a trailing whitespace? + trailing_blank = is_blank(parser.buffer, parser.buffer_pos) + + // Check if we need to fold the leading line break. + if !literal && !leading_blank && !trailing_blank && len(leading_break) > 0 && leading_break[0] == '\n' { + // Do we need to join the lines by space? + if len(trailing_breaks) == 0 { + s = append(s, ' ') + } + } else { + s = append(s, leading_break...) + } + leading_break = leading_break[:0] + + // Append the remaining line breaks. + s = append(s, trailing_breaks...) + trailing_breaks = trailing_breaks[:0] + + // Is it a leading whitespace? + leading_blank = is_blank(parser.buffer, parser.buffer_pos) + + // Consume the current line. + for !is_breakz(parser.buffer, parser.buffer_pos) { + s = read(parser, s) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + + // Consume the line break. + if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { + return false + } + + leading_break = read_line(parser, leading_break) + + // Eat the following indentation spaces and line breaks. + if !yaml_parser_scan_block_scalar_breaks(parser, &indent, &trailing_breaks, start_mark, &end_mark) { + return false + } + } + + // Chomp the tail. + if chomping != -1 { + s = append(s, leading_break...) + } + if chomping == 1 { + s = append(s, trailing_breaks...) + } + + // Create a token. + *token = yaml_token_t{ + typ: yaml_SCALAR_TOKEN, + start_mark: start_mark, + end_mark: end_mark, + value: s, + style: yaml_LITERAL_SCALAR_STYLE, + } + if !literal { + token.style = yaml_FOLDED_SCALAR_STYLE + } + return true +} + +// Scan indentation spaces and line breaks for a block scalar. Determine the +// indentation level if needed. +func yaml_parser_scan_block_scalar_breaks(parser *yaml_parser_t, indent *int, breaks *[]byte, start_mark yaml_mark_t, end_mark *yaml_mark_t) bool { + *end_mark = parser.mark + + // Eat the indentation spaces and line breaks. + max_indent := 0 + for { + // Eat the indentation spaces. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + for (*indent == 0 || parser.mark.column < *indent) && is_space(parser.buffer, parser.buffer_pos) { + skip(parser) + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + if parser.mark.column > max_indent { + max_indent = parser.mark.column + } + + // Check for a tab character messing the indentation. + if (*indent == 0 || parser.mark.column < *indent) && is_tab(parser.buffer, parser.buffer_pos) { + return yaml_parser_set_scanner_error(parser, "while scanning a block scalar", + start_mark, "found a tab character where an indentation space is expected") + } + + // Have we found a non-empty line? + if !is_break(parser.buffer, parser.buffer_pos) { + break + } + + // Consume the line break. + if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { + return false + } + // [Go] Should really be returning breaks instead. + *breaks = read_line(parser, *breaks) + *end_mark = parser.mark + } + + // Determine the indentation level if needed. + if *indent == 0 { + *indent = max_indent + if *indent < parser.indent+1 { + *indent = parser.indent + 1 + } + if *indent < 1 { + *indent = 1 + } + } + return true +} + +// Scan a quoted scalar. +func yaml_parser_scan_flow_scalar(parser *yaml_parser_t, token *yaml_token_t, single bool) bool { + // Eat the left quote. + start_mark := parser.mark + skip(parser) + + // Consume the content of the quoted scalar. + var s, leading_break, trailing_breaks, whitespaces []byte + for { + // Check that there are no document indicators at the beginning of the line. + if parser.unread < 4 && !yaml_parser_update_buffer(parser, 4) { + return false + } + + if parser.mark.column == 0 && + ((parser.buffer[parser.buffer_pos+0] == '-' && + parser.buffer[parser.buffer_pos+1] == '-' && + parser.buffer[parser.buffer_pos+2] == '-') || + (parser.buffer[parser.buffer_pos+0] == '.' && + parser.buffer[parser.buffer_pos+1] == '.' && + parser.buffer[parser.buffer_pos+2] == '.')) && + is_blankz(parser.buffer, parser.buffer_pos+3) { + yaml_parser_set_scanner_error(parser, "while scanning a quoted scalar", + start_mark, "found unexpected document indicator") + return false + } + + // Check for EOF. + if is_z(parser.buffer, parser.buffer_pos) { + yaml_parser_set_scanner_error(parser, "while scanning a quoted scalar", + start_mark, "found unexpected end of stream") + return false + } + + // Consume non-blank characters. + leading_blanks := false + for !is_blankz(parser.buffer, parser.buffer_pos) { + if single && parser.buffer[parser.buffer_pos] == '\'' && parser.buffer[parser.buffer_pos+1] == '\'' { + // Is is an escaped single quote. + s = append(s, '\'') + skip(parser) + skip(parser) + + } else if single && parser.buffer[parser.buffer_pos] == '\'' { + // It is a right single quote. + break + } else if !single && parser.buffer[parser.buffer_pos] == '"' { + // It is a right double quote. + break + + } else if !single && parser.buffer[parser.buffer_pos] == '\\' && is_break(parser.buffer, parser.buffer_pos+1) { + // It is an escaped line break. + if parser.unread < 3 && !yaml_parser_update_buffer(parser, 3) { + return false + } + skip(parser) + skip_line(parser) + leading_blanks = true + break + + } else if !single && parser.buffer[parser.buffer_pos] == '\\' { + // It is an escape sequence. + code_length := 0 + + // Check the escape character. + switch parser.buffer[parser.buffer_pos+1] { + case '0': + s = append(s, 0) + case 'a': + s = append(s, '\x07') + case 'b': + s = append(s, '\x08') + case 't', '\t': + s = append(s, '\x09') + case 'n': + s = append(s, '\x0A') + case 'v': + s = append(s, '\x0B') + case 'f': + s = append(s, '\x0C') + case 'r': + s = append(s, '\x0D') + case 'e': + s = append(s, '\x1B') + case ' ': + s = append(s, '\x20') + case '"': + s = append(s, '"') + case '\'': + s = append(s, '\'') + case '\\': + s = append(s, '\\') + case 'N': // NEL (#x85) + s = append(s, '\xC2') + s = append(s, '\x85') + case '_': // #xA0 + s = append(s, '\xC2') + s = append(s, '\xA0') + case 'L': // LS (#x2028) + s = append(s, '\xE2') + s = append(s, '\x80') + s = append(s, '\xA8') + case 'P': // PS (#x2029) + s = append(s, '\xE2') + s = append(s, '\x80') + s = append(s, '\xA9') + case 'x': + code_length = 2 + case 'u': + code_length = 4 + case 'U': + code_length = 8 + default: + yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar", + start_mark, "found unknown escape character") + return false + } + + skip(parser) + skip(parser) + + // Consume an arbitrary escape code. + if code_length > 0 { + var value int + + // Scan the character value. + if parser.unread < code_length && !yaml_parser_update_buffer(parser, code_length) { + return false + } + for k := 0; k < code_length; k++ { + if !is_hex(parser.buffer, parser.buffer_pos+k) { + yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar", + start_mark, "did not find expected hexdecimal number") + return false + } + value = (value << 4) + as_hex(parser.buffer, parser.buffer_pos+k) + } + + // Check the value and write the character. + if (value >= 0xD800 && value <= 0xDFFF) || value > 0x10FFFF { + yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar", + start_mark, "found invalid Unicode character escape code") + return false + } + if value <= 0x7F { + s = append(s, byte(value)) + } else if value <= 0x7FF { + s = append(s, byte(0xC0+(value>>6))) + s = append(s, byte(0x80+(value&0x3F))) + } else if value <= 0xFFFF { + s = append(s, byte(0xE0+(value>>12))) + s = append(s, byte(0x80+((value>>6)&0x3F))) + s = append(s, byte(0x80+(value&0x3F))) + } else { + s = append(s, byte(0xF0+(value>>18))) + s = append(s, byte(0x80+((value>>12)&0x3F))) + s = append(s, byte(0x80+((value>>6)&0x3F))) + s = append(s, byte(0x80+(value&0x3F))) + } + + // Advance the pointer. + for k := 0; k < code_length; k++ { + skip(parser) + } + } + } else { + // It is a non-escaped non-blank character. + s = read(parser, s) + } + if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { + return false + } + } + + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + + // Check if we are at the end of the scalar. + if single { + if parser.buffer[parser.buffer_pos] == '\'' { + break + } + } else { + if parser.buffer[parser.buffer_pos] == '"' { + break + } + } + + // Consume blank characters. + for is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos) { + if is_blank(parser.buffer, parser.buffer_pos) { + // Consume a space or a tab character. + if !leading_blanks { + whitespaces = read(parser, whitespaces) + } else { + skip(parser) + } + } else { + if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { + return false + } + + // Check if it is a first line break. + if !leading_blanks { + whitespaces = whitespaces[:0] + leading_break = read_line(parser, leading_break) + leading_blanks = true + } else { + trailing_breaks = read_line(parser, trailing_breaks) + } + } + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + + // Join the whitespaces or fold line breaks. + if leading_blanks { + // Do we need to fold line breaks? + if len(leading_break) > 0 && leading_break[0] == '\n' { + if len(trailing_breaks) == 0 { + s = append(s, ' ') + } else { + s = append(s, trailing_breaks...) + } + } else { + s = append(s, leading_break...) + s = append(s, trailing_breaks...) + } + trailing_breaks = trailing_breaks[:0] + leading_break = leading_break[:0] + } else { + s = append(s, whitespaces...) + whitespaces = whitespaces[:0] + } + } + + // Eat the right quote. + skip(parser) + end_mark := parser.mark + + // Create a token. + *token = yaml_token_t{ + typ: yaml_SCALAR_TOKEN, + start_mark: start_mark, + end_mark: end_mark, + value: s, + style: yaml_SINGLE_QUOTED_SCALAR_STYLE, + } + if !single { + token.style = yaml_DOUBLE_QUOTED_SCALAR_STYLE + } + return true +} + +// Scan a plain scalar. +func yaml_parser_scan_plain_scalar(parser *yaml_parser_t, token *yaml_token_t) bool { + + var s, leading_break, trailing_breaks, whitespaces []byte + var leading_blanks bool + var indent = parser.indent + 1 + + start_mark := parser.mark + end_mark := parser.mark + + // Consume the content of the plain scalar. + for { + // Check for a document indicator. + if parser.unread < 4 && !yaml_parser_update_buffer(parser, 4) { + return false + } + if parser.mark.column == 0 && + ((parser.buffer[parser.buffer_pos+0] == '-' && + parser.buffer[parser.buffer_pos+1] == '-' && + parser.buffer[parser.buffer_pos+2] == '-') || + (parser.buffer[parser.buffer_pos+0] == '.' && + parser.buffer[parser.buffer_pos+1] == '.' && + parser.buffer[parser.buffer_pos+2] == '.')) && + is_blankz(parser.buffer, parser.buffer_pos+3) { + break + } + + // Check for a comment. + if parser.buffer[parser.buffer_pos] == '#' { + break + } + + // Consume non-blank characters. + for !is_blankz(parser.buffer, parser.buffer_pos) { + + // Check for indicators that may end a plain scalar. + if (parser.buffer[parser.buffer_pos] == ':' && is_blankz(parser.buffer, parser.buffer_pos+1)) || + (parser.flow_level > 0 && + (parser.buffer[parser.buffer_pos] == ',' || + parser.buffer[parser.buffer_pos] == '?' || parser.buffer[parser.buffer_pos] == '[' || + parser.buffer[parser.buffer_pos] == ']' || parser.buffer[parser.buffer_pos] == '{' || + parser.buffer[parser.buffer_pos] == '}')) { + break + } + + // Check if we need to join whitespaces and breaks. + if leading_blanks || len(whitespaces) > 0 { + if leading_blanks { + // Do we need to fold line breaks? + if leading_break[0] == '\n' { + if len(trailing_breaks) == 0 { + s = append(s, ' ') + } else { + s = append(s, trailing_breaks...) + } + } else { + s = append(s, leading_break...) + s = append(s, trailing_breaks...) + } + trailing_breaks = trailing_breaks[:0] + leading_break = leading_break[:0] + leading_blanks = false + } else { + s = append(s, whitespaces...) + whitespaces = whitespaces[:0] + } + } + + // Copy the character. + s = read(parser, s) + + end_mark = parser.mark + if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { + return false + } + } + + // Is it the end? + if !(is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos)) { + break + } + + // Consume blank characters. + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + + for is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos) { + if is_blank(parser.buffer, parser.buffer_pos) { + + // Check for tab characters that abuse indentation. + if leading_blanks && parser.mark.column < indent && is_tab(parser.buffer, parser.buffer_pos) { + yaml_parser_set_scanner_error(parser, "while scanning a plain scalar", + start_mark, "found a tab character that violates indentation") + return false + } + + // Consume a space or a tab character. + if !leading_blanks { + whitespaces = read(parser, whitespaces) + } else { + skip(parser) + } + } else { + if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { + return false + } + + // Check if it is a first line break. + if !leading_blanks { + whitespaces = whitespaces[:0] + leading_break = read_line(parser, leading_break) + leading_blanks = true + } else { + trailing_breaks = read_line(parser, trailing_breaks) + } + } + if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { + return false + } + } + + // Check indentation level. + if parser.flow_level == 0 && parser.mark.column < indent { + break + } + } + + // Create a token. + *token = yaml_token_t{ + typ: yaml_SCALAR_TOKEN, + start_mark: start_mark, + end_mark: end_mark, + value: s, + style: yaml_PLAIN_SCALAR_STYLE, + } + + // Note that we change the 'simple_key_allowed' flag. + if leading_blanks { + parser.simple_key_allowed = true + } + return true +} diff --git a/vendor/sigs.k8s.io/yaml/goyaml.v2/sorter.go b/vendor/sigs.k8s.io/yaml/goyaml.v2/sorter.go new file mode 100644 index 000000000..4c45e660a --- /dev/null +++ b/vendor/sigs.k8s.io/yaml/goyaml.v2/sorter.go @@ -0,0 +1,113 @@ +package yaml + +import ( + "reflect" + "unicode" +) + +type keyList []reflect.Value + +func (l keyList) Len() int { return len(l) } +func (l keyList) Swap(i, j int) { l[i], l[j] = l[j], l[i] } +func (l keyList) Less(i, j int) bool { + a := l[i] + b := l[j] + ak := a.Kind() + bk := b.Kind() + for (ak == reflect.Interface || ak == reflect.Ptr) && !a.IsNil() { + a = a.Elem() + ak = a.Kind() + } + for (bk == reflect.Interface || bk == reflect.Ptr) && !b.IsNil() { + b = b.Elem() + bk = b.Kind() + } + af, aok := keyFloat(a) + bf, bok := keyFloat(b) + if aok && bok { + if af != bf { + return af < bf + } + if ak != bk { + return ak < bk + } + return numLess(a, b) + } + if ak != reflect.String || bk != reflect.String { + return ak < bk + } + ar, br := []rune(a.String()), []rune(b.String()) + for i := 0; i < len(ar) && i < len(br); i++ { + if ar[i] == br[i] { + continue + } + al := unicode.IsLetter(ar[i]) + bl := unicode.IsLetter(br[i]) + if al && bl { + return ar[i] < br[i] + } + if al || bl { + return bl + } + var ai, bi int + var an, bn int64 + if ar[i] == '0' || br[i] == '0' { + for j := i-1; j >= 0 && unicode.IsDigit(ar[j]); j-- { + if ar[j] != '0' { + an = 1 + bn = 1 + break + } + } + } + for ai = i; ai < len(ar) && unicode.IsDigit(ar[ai]); ai++ { + an = an*10 + int64(ar[ai]-'0') + } + for bi = i; bi < len(br) && unicode.IsDigit(br[bi]); bi++ { + bn = bn*10 + int64(br[bi]-'0') + } + if an != bn { + return an < bn + } + if ai != bi { + return ai < bi + } + return ar[i] < br[i] + } + return len(ar) < len(br) +} + +// keyFloat returns a float value for v if it is a number/bool +// and whether it is a number/bool or not. +func keyFloat(v reflect.Value) (f float64, ok bool) { + switch v.Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return float64(v.Int()), true + case reflect.Float32, reflect.Float64: + return v.Float(), true + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return float64(v.Uint()), true + case reflect.Bool: + if v.Bool() { + return 1, true + } + return 0, true + } + return 0, false +} + +// numLess returns whether a < b. +// a and b must necessarily have the same kind. +func numLess(a, b reflect.Value) bool { + switch a.Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return a.Int() < b.Int() + case reflect.Float32, reflect.Float64: + return a.Float() < b.Float() + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return a.Uint() < b.Uint() + case reflect.Bool: + return !a.Bool() && b.Bool() + } + panic("not a number") +} diff --git a/vendor/sigs.k8s.io/yaml/goyaml.v2/writerc.go b/vendor/sigs.k8s.io/yaml/goyaml.v2/writerc.go new file mode 100644 index 000000000..a2dde608c --- /dev/null +++ b/vendor/sigs.k8s.io/yaml/goyaml.v2/writerc.go @@ -0,0 +1,26 @@ +package yaml + +// Set the writer error and return false. +func yaml_emitter_set_writer_error(emitter *yaml_emitter_t, problem string) bool { + emitter.error = yaml_WRITER_ERROR + emitter.problem = problem + return false +} + +// Flush the output buffer. +func yaml_emitter_flush(emitter *yaml_emitter_t) bool { + if emitter.write_handler == nil { + panic("write handler not set") + } + + // Check if the buffer is empty. + if emitter.buffer_pos == 0 { + return true + } + + if err := emitter.write_handler(emitter, emitter.buffer[:emitter.buffer_pos]); err != nil { + return yaml_emitter_set_writer_error(emitter, "write error: "+err.Error()) + } + emitter.buffer_pos = 0 + return true +} diff --git a/vendor/sigs.k8s.io/yaml/goyaml.v2/yaml.go b/vendor/sigs.k8s.io/yaml/goyaml.v2/yaml.go new file mode 100644 index 000000000..30813884c --- /dev/null +++ b/vendor/sigs.k8s.io/yaml/goyaml.v2/yaml.go @@ -0,0 +1,478 @@ +// Package yaml implements YAML support for the Go language. +// +// Source code and other details for the project are available at GitHub: +// +// https://github.com/go-yaml/yaml +// +package yaml + +import ( + "errors" + "fmt" + "io" + "reflect" + "strings" + "sync" +) + +// MapSlice encodes and decodes as a YAML map. +// The order of keys is preserved when encoding and decoding. +type MapSlice []MapItem + +// MapItem is an item in a MapSlice. +type MapItem struct { + Key, Value interface{} +} + +// The Unmarshaler interface may be implemented by types to customize their +// behavior when being unmarshaled from a YAML document. The UnmarshalYAML +// method receives a function that may be called to unmarshal the original +// YAML value into a field or variable. It is safe to call the unmarshal +// function parameter more than once if necessary. +type Unmarshaler interface { + UnmarshalYAML(unmarshal func(interface{}) error) error +} + +// The Marshaler interface may be implemented by types to customize their +// behavior when being marshaled into a YAML document. The returned value +// is marshaled in place of the original value implementing Marshaler. +// +// If an error is returned by MarshalYAML, the marshaling procedure stops +// and returns with the provided error. +type Marshaler interface { + MarshalYAML() (interface{}, error) +} + +// Unmarshal decodes the first document found within the in byte slice +// and assigns decoded values into the out value. +// +// Maps and pointers (to a struct, string, int, etc) are accepted as out +// values. If an internal pointer within a struct is not initialized, +// the yaml package will initialize it if necessary for unmarshalling +// the provided data. The out parameter must not be nil. +// +// The type of the decoded values should be compatible with the respective +// values in out. If one or more values cannot be decoded due to a type +// mismatches, decoding continues partially until the end of the YAML +// content, and a *yaml.TypeError is returned with details for all +// missed values. +// +// Struct fields are only unmarshalled if they are exported (have an +// upper case first letter), and are unmarshalled using the field name +// lowercased as the default key. Custom keys may be defined via the +// "yaml" name in the field tag: the content preceding the first comma +// is used as the key, and the following comma-separated options are +// used to tweak the marshalling process (see Marshal). +// Conflicting names result in a runtime error. +// +// For example: +// +// type T struct { +// F int `yaml:"a,omitempty"` +// B int +// } +// var t T +// yaml.Unmarshal([]byte("a: 1\nb: 2"), &t) +// +// See the documentation of Marshal for the format of tags and a list of +// supported tag options. +// +func Unmarshal(in []byte, out interface{}) (err error) { + return unmarshal(in, out, false) +} + +// UnmarshalStrict is like Unmarshal except that any fields that are found +// in the data that do not have corresponding struct members, or mapping +// keys that are duplicates, will result in +// an error. +func UnmarshalStrict(in []byte, out interface{}) (err error) { + return unmarshal(in, out, true) +} + +// A Decoder reads and decodes YAML values from an input stream. +type Decoder struct { + strict bool + parser *parser +} + +// NewDecoder returns a new decoder that reads from r. +// +// The decoder introduces its own buffering and may read +// data from r beyond the YAML values requested. +func NewDecoder(r io.Reader) *Decoder { + return &Decoder{ + parser: newParserFromReader(r), + } +} + +// SetStrict sets whether strict decoding behaviour is enabled when +// decoding items in the data (see UnmarshalStrict). By default, decoding is not strict. +func (dec *Decoder) SetStrict(strict bool) { + dec.strict = strict +} + +// Decode reads the next YAML-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 YAML into a Go value. +func (dec *Decoder) Decode(v interface{}) (err error) { + d := newDecoder(dec.strict) + defer handleErr(&err) + node := dec.parser.parse() + if node == nil { + return io.EOF + } + out := reflect.ValueOf(v) + if out.Kind() == reflect.Ptr && !out.IsNil() { + out = out.Elem() + } + d.unmarshal(node, out) + if len(d.terrors) > 0 { + return &TypeError{d.terrors} + } + return nil +} + +func unmarshal(in []byte, out interface{}, strict bool) (err error) { + defer handleErr(&err) + d := newDecoder(strict) + p := newParser(in) + defer p.destroy() + node := p.parse() + if node != nil { + v := reflect.ValueOf(out) + if v.Kind() == reflect.Ptr && !v.IsNil() { + v = v.Elem() + } + d.unmarshal(node, v) + } + if len(d.terrors) > 0 { + return &TypeError{d.terrors} + } + return nil +} + +// Marshal serializes the value provided into a YAML document. The structure +// of the generated document will reflect the structure of the value itself. +// Maps and pointers (to struct, string, int, etc) are accepted as the in value. +// +// Struct fields are only marshalled if they are exported (have an upper case +// first letter), and are marshalled using the field name lowercased as the +// default key. Custom keys may be defined via the "yaml" name in the field +// tag: the content preceding the first comma is used as the key, and the +// following comma-separated options are used to tweak the marshalling process. +// Conflicting names result in a runtime error. +// +// The field tag format accepted is: +// +// `(...) yaml:"[][,[,]]" (...)` +// +// The following flags are currently supported: +// +// omitempty Only include the field if it's not set to the zero +// value for the type or to empty slices or maps. +// Zero valued structs will be omitted if all their public +// fields are zero, unless they implement an IsZero +// method (see the IsZeroer interface type), in which +// case the field will be excluded if IsZero returns true. +// +// flow Marshal using a flow style (useful for structs, +// sequences and maps). +// +// inline Inline the field, which must be a struct or a map, +// causing all of its fields or keys to be processed as if +// they were part of the outer struct. For maps, keys must +// not conflict with the yaml keys of other struct fields. +// +// In addition, if the key is "-", the field is ignored. +// +// For example: +// +// type T struct { +// F int `yaml:"a,omitempty"` +// B int +// } +// yaml.Marshal(&T{B: 2}) // Returns "b: 2\n" +// yaml.Marshal(&T{F: 1}} // Returns "a: 1\nb: 0\n" +// +func Marshal(in interface{}) (out []byte, err error) { + defer handleErr(&err) + e := newEncoder() + defer e.destroy() + e.marshalDoc("", reflect.ValueOf(in)) + e.finish() + out = e.out + return +} + +// An Encoder writes YAML values to an output stream. +type Encoder struct { + encoder *encoder +} + +// NewEncoder returns a new encoder that writes to w. +// The Encoder should be closed after use to flush all data +// to w. +func NewEncoder(w io.Writer) *Encoder { + return &Encoder{ + encoder: newEncoderWithWriter(w), + } +} + +// Encode writes the YAML encoding of v to the stream. +// If multiple items are encoded to the stream, the +// second and subsequent document will be preceded +// with a "---" document separator, but the first will not. +// +// See the documentation for Marshal for details about the conversion of Go +// values to YAML. +func (e *Encoder) Encode(v interface{}) (err error) { + defer handleErr(&err) + e.encoder.marshalDoc("", reflect.ValueOf(v)) + return nil +} + +// Close closes the encoder by writing any remaining data. +// It does not write a stream terminating string "...". +func (e *Encoder) Close() (err error) { + defer handleErr(&err) + e.encoder.finish() + return nil +} + +func handleErr(err *error) { + if v := recover(); v != nil { + if e, ok := v.(yamlError); ok { + *err = e.err + } else { + panic(v) + } + } +} + +type yamlError struct { + err error +} + +func fail(err error) { + panic(yamlError{err}) +} + +func failf(format string, args ...interface{}) { + panic(yamlError{fmt.Errorf("yaml: "+format, args...)}) +} + +// A TypeError is returned by Unmarshal when one or more fields in +// the YAML document cannot be properly decoded into the requested +// types. When this error is returned, the value is still +// unmarshaled partially. +type TypeError struct { + Errors []string +} + +func (e *TypeError) Error() string { + return fmt.Sprintf("yaml: unmarshal errors:\n %s", strings.Join(e.Errors, "\n ")) +} + +// -------------------------------------------------------------------------- +// Maintain a mapping of keys to structure field indexes + +// The code in this section was copied from mgo/bson. + +// structInfo holds details for the serialization of fields of +// a given struct. +type structInfo struct { + FieldsMap map[string]fieldInfo + FieldsList []fieldInfo + + // InlineMap is the number of the field in the struct that + // contains an ,inline map, or -1 if there's none. + InlineMap int +} + +type fieldInfo struct { + Key string + Num int + OmitEmpty bool + Flow bool + // Id holds the unique field identifier, so we can cheaply + // check for field duplicates without maintaining an extra map. + Id int + + // Inline holds the field index if the field is part of an inlined struct. + Inline []int +} + +var structMap = make(map[reflect.Type]*structInfo) +var fieldMapMutex sync.RWMutex + +func getStructInfo(st reflect.Type) (*structInfo, error) { + fieldMapMutex.RLock() + sinfo, found := structMap[st] + fieldMapMutex.RUnlock() + if found { + return sinfo, nil + } + + n := st.NumField() + fieldsMap := make(map[string]fieldInfo) + fieldsList := make([]fieldInfo, 0, n) + inlineMap := -1 + for i := 0; i != n; i++ { + field := st.Field(i) + if field.PkgPath != "" && !field.Anonymous { + continue // Private field + } + + info := fieldInfo{Num: i} + + tag := field.Tag.Get("yaml") + if tag == "" && strings.Index(string(field.Tag), ":") < 0 { + tag = string(field.Tag) + } + if tag == "-" { + continue + } + + inline := false + fields := strings.Split(tag, ",") + if len(fields) > 1 { + for _, flag := range fields[1:] { + switch flag { + case "omitempty": + info.OmitEmpty = true + case "flow": + info.Flow = true + case "inline": + inline = true + default: + return nil, errors.New(fmt.Sprintf("Unsupported flag %q in tag %q of type %s", flag, tag, st)) + } + } + tag = fields[0] + } + + if inline { + switch field.Type.Kind() { + case reflect.Map: + if inlineMap >= 0 { + return nil, errors.New("Multiple ,inline maps in struct " + st.String()) + } + if field.Type.Key() != reflect.TypeOf("") { + return nil, errors.New("Option ,inline needs a map with string keys in struct " + st.String()) + } + inlineMap = info.Num + case reflect.Struct: + sinfo, err := getStructInfo(field.Type) + if err != nil { + return nil, err + } + for _, finfo := range sinfo.FieldsList { + if _, found := fieldsMap[finfo.Key]; found { + msg := "Duplicated key '" + finfo.Key + "' in struct " + st.String() + return nil, errors.New(msg) + } + if finfo.Inline == nil { + finfo.Inline = []int{i, finfo.Num} + } else { + finfo.Inline = append([]int{i}, finfo.Inline...) + } + finfo.Id = len(fieldsList) + fieldsMap[finfo.Key] = finfo + fieldsList = append(fieldsList, finfo) + } + default: + //return nil, errors.New("Option ,inline needs a struct value or map field") + return nil, errors.New("Option ,inline needs a struct value field") + } + continue + } + + if tag != "" { + info.Key = tag + } else { + info.Key = strings.ToLower(field.Name) + } + + if _, found = fieldsMap[info.Key]; found { + msg := "Duplicated key '" + info.Key + "' in struct " + st.String() + return nil, errors.New(msg) + } + + info.Id = len(fieldsList) + fieldsList = append(fieldsList, info) + fieldsMap[info.Key] = info + } + + sinfo = &structInfo{ + FieldsMap: fieldsMap, + FieldsList: fieldsList, + InlineMap: inlineMap, + } + + fieldMapMutex.Lock() + structMap[st] = sinfo + fieldMapMutex.Unlock() + return sinfo, nil +} + +// IsZeroer is used to check whether an object is zero to +// determine whether it should be omitted when marshaling +// with the omitempty flag. One notable implementation +// is time.Time. +type IsZeroer interface { + IsZero() bool +} + +func isZero(v reflect.Value) bool { + kind := v.Kind() + if z, ok := v.Interface().(IsZeroer); ok { + if (kind == reflect.Ptr || kind == reflect.Interface) && v.IsNil() { + return true + } + return z.IsZero() + } + switch kind { + case reflect.String: + return len(v.String()) == 0 + case reflect.Interface, reflect.Ptr: + return v.IsNil() + case reflect.Slice: + return v.Len() == 0 + case reflect.Map: + return v.Len() == 0 + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return v.Int() == 0 + case reflect.Float32, reflect.Float64: + return v.Float() == 0 + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return v.Uint() == 0 + case reflect.Bool: + return !v.Bool() + case reflect.Struct: + vt := v.Type() + for i := v.NumField() - 1; i >= 0; i-- { + if vt.Field(i).PkgPath != "" { + continue // Private field + } + if !isZero(v.Field(i)) { + return false + } + } + return true + } + return false +} + +// FutureLineWrap globally disables line wrapping when encoding long strings. +// This is a temporary and thus deprecated method introduced to faciliate +// migration towards v3, which offers more control of line lengths on +// individual encodings, and has a default matching the behavior introduced +// by this function. +// +// The default formatting of v2 was erroneously changed in v2.3.0 and reverted +// in v2.4.0, at which point this function was introduced to help migration. +func FutureLineWrap() { + disableLineWrapping = true +} diff --git a/vendor/sigs.k8s.io/yaml/goyaml.v2/yamlh.go b/vendor/sigs.k8s.io/yaml/goyaml.v2/yamlh.go new file mode 100644 index 000000000..f6a9c8e34 --- /dev/null +++ b/vendor/sigs.k8s.io/yaml/goyaml.v2/yamlh.go @@ -0,0 +1,739 @@ +package yaml + +import ( + "fmt" + "io" +) + +// The version directive data. +type yaml_version_directive_t struct { + major int8 // The major version number. + minor int8 // The minor version number. +} + +// The tag directive data. +type yaml_tag_directive_t struct { + handle []byte // The tag handle. + prefix []byte // The tag prefix. +} + +type yaml_encoding_t int + +// The stream encoding. +const ( + // Let the parser choose the encoding. + yaml_ANY_ENCODING yaml_encoding_t = iota + + yaml_UTF8_ENCODING // The default UTF-8 encoding. + yaml_UTF16LE_ENCODING // The UTF-16-LE encoding with BOM. + yaml_UTF16BE_ENCODING // The UTF-16-BE encoding with BOM. +) + +type yaml_break_t int + +// Line break types. +const ( + // Let the parser choose the break type. + yaml_ANY_BREAK yaml_break_t = iota + + yaml_CR_BREAK // Use CR for line breaks (Mac style). + yaml_LN_BREAK // Use LN for line breaks (Unix style). + yaml_CRLN_BREAK // Use CR LN for line breaks (DOS style). +) + +type yaml_error_type_t int + +// Many bad things could happen with the parser and emitter. +const ( + // No error is produced. + yaml_NO_ERROR yaml_error_type_t = iota + + yaml_MEMORY_ERROR // Cannot allocate or reallocate a block of memory. + yaml_READER_ERROR // Cannot read or decode the input stream. + yaml_SCANNER_ERROR // Cannot scan the input stream. + yaml_PARSER_ERROR // Cannot parse the input stream. + yaml_COMPOSER_ERROR // Cannot compose a YAML document. + yaml_WRITER_ERROR // Cannot write to the output stream. + yaml_EMITTER_ERROR // Cannot emit a YAML stream. +) + +// The pointer position. +type yaml_mark_t struct { + index int // The position index. + line int // The position line. + column int // The position column. +} + +// Node Styles + +type yaml_style_t int8 + +type yaml_scalar_style_t yaml_style_t + +// Scalar styles. +const ( + // Let the emitter choose the style. + yaml_ANY_SCALAR_STYLE yaml_scalar_style_t = iota + + yaml_PLAIN_SCALAR_STYLE // The plain scalar style. + yaml_SINGLE_QUOTED_SCALAR_STYLE // The single-quoted scalar style. + yaml_DOUBLE_QUOTED_SCALAR_STYLE // The double-quoted scalar style. + yaml_LITERAL_SCALAR_STYLE // The literal scalar style. + yaml_FOLDED_SCALAR_STYLE // The folded scalar style. +) + +type yaml_sequence_style_t yaml_style_t + +// Sequence styles. +const ( + // Let the emitter choose the style. + yaml_ANY_SEQUENCE_STYLE yaml_sequence_style_t = iota + + yaml_BLOCK_SEQUENCE_STYLE // The block sequence style. + yaml_FLOW_SEQUENCE_STYLE // The flow sequence style. +) + +type yaml_mapping_style_t yaml_style_t + +// Mapping styles. +const ( + // Let the emitter choose the style. + yaml_ANY_MAPPING_STYLE yaml_mapping_style_t = iota + + yaml_BLOCK_MAPPING_STYLE // The block mapping style. + yaml_FLOW_MAPPING_STYLE // The flow mapping style. +) + +// Tokens + +type yaml_token_type_t int + +// Token types. +const ( + // An empty token. + yaml_NO_TOKEN yaml_token_type_t = iota + + yaml_STREAM_START_TOKEN // A STREAM-START token. + yaml_STREAM_END_TOKEN // A STREAM-END token. + + yaml_VERSION_DIRECTIVE_TOKEN // A VERSION-DIRECTIVE token. + yaml_TAG_DIRECTIVE_TOKEN // A TAG-DIRECTIVE token. + yaml_DOCUMENT_START_TOKEN // A DOCUMENT-START token. + yaml_DOCUMENT_END_TOKEN // A DOCUMENT-END token. + + yaml_BLOCK_SEQUENCE_START_TOKEN // A BLOCK-SEQUENCE-START token. + yaml_BLOCK_MAPPING_START_TOKEN // A BLOCK-SEQUENCE-END token. + yaml_BLOCK_END_TOKEN // A BLOCK-END token. + + yaml_FLOW_SEQUENCE_START_TOKEN // A FLOW-SEQUENCE-START token. + yaml_FLOW_SEQUENCE_END_TOKEN // A FLOW-SEQUENCE-END token. + yaml_FLOW_MAPPING_START_TOKEN // A FLOW-MAPPING-START token. + yaml_FLOW_MAPPING_END_TOKEN // A FLOW-MAPPING-END token. + + yaml_BLOCK_ENTRY_TOKEN // A BLOCK-ENTRY token. + yaml_FLOW_ENTRY_TOKEN // A FLOW-ENTRY token. + yaml_KEY_TOKEN // A KEY token. + yaml_VALUE_TOKEN // A VALUE token. + + yaml_ALIAS_TOKEN // An ALIAS token. + yaml_ANCHOR_TOKEN // An ANCHOR token. + yaml_TAG_TOKEN // A TAG token. + yaml_SCALAR_TOKEN // A SCALAR token. +) + +func (tt yaml_token_type_t) String() string { + switch tt { + case yaml_NO_TOKEN: + return "yaml_NO_TOKEN" + case yaml_STREAM_START_TOKEN: + return "yaml_STREAM_START_TOKEN" + case yaml_STREAM_END_TOKEN: + return "yaml_STREAM_END_TOKEN" + case yaml_VERSION_DIRECTIVE_TOKEN: + return "yaml_VERSION_DIRECTIVE_TOKEN" + case yaml_TAG_DIRECTIVE_TOKEN: + return "yaml_TAG_DIRECTIVE_TOKEN" + case yaml_DOCUMENT_START_TOKEN: + return "yaml_DOCUMENT_START_TOKEN" + case yaml_DOCUMENT_END_TOKEN: + return "yaml_DOCUMENT_END_TOKEN" + case yaml_BLOCK_SEQUENCE_START_TOKEN: + return "yaml_BLOCK_SEQUENCE_START_TOKEN" + case yaml_BLOCK_MAPPING_START_TOKEN: + return "yaml_BLOCK_MAPPING_START_TOKEN" + case yaml_BLOCK_END_TOKEN: + return "yaml_BLOCK_END_TOKEN" + case yaml_FLOW_SEQUENCE_START_TOKEN: + return "yaml_FLOW_SEQUENCE_START_TOKEN" + case yaml_FLOW_SEQUENCE_END_TOKEN: + return "yaml_FLOW_SEQUENCE_END_TOKEN" + case yaml_FLOW_MAPPING_START_TOKEN: + return "yaml_FLOW_MAPPING_START_TOKEN" + case yaml_FLOW_MAPPING_END_TOKEN: + return "yaml_FLOW_MAPPING_END_TOKEN" + case yaml_BLOCK_ENTRY_TOKEN: + return "yaml_BLOCK_ENTRY_TOKEN" + case yaml_FLOW_ENTRY_TOKEN: + return "yaml_FLOW_ENTRY_TOKEN" + case yaml_KEY_TOKEN: + return "yaml_KEY_TOKEN" + case yaml_VALUE_TOKEN: + return "yaml_VALUE_TOKEN" + case yaml_ALIAS_TOKEN: + return "yaml_ALIAS_TOKEN" + case yaml_ANCHOR_TOKEN: + return "yaml_ANCHOR_TOKEN" + case yaml_TAG_TOKEN: + return "yaml_TAG_TOKEN" + case yaml_SCALAR_TOKEN: + return "yaml_SCALAR_TOKEN" + } + return "" +} + +// The token structure. +type yaml_token_t struct { + // The token type. + typ yaml_token_type_t + + // The start/end of the token. + start_mark, end_mark yaml_mark_t + + // The stream encoding (for yaml_STREAM_START_TOKEN). + encoding yaml_encoding_t + + // The alias/anchor/scalar value or tag/tag directive handle + // (for yaml_ALIAS_TOKEN, yaml_ANCHOR_TOKEN, yaml_SCALAR_TOKEN, yaml_TAG_TOKEN, yaml_TAG_DIRECTIVE_TOKEN). + value []byte + + // The tag suffix (for yaml_TAG_TOKEN). + suffix []byte + + // The tag directive prefix (for yaml_TAG_DIRECTIVE_TOKEN). + prefix []byte + + // The scalar style (for yaml_SCALAR_TOKEN). + style yaml_scalar_style_t + + // The version directive major/minor (for yaml_VERSION_DIRECTIVE_TOKEN). + major, minor int8 +} + +// Events + +type yaml_event_type_t int8 + +// Event types. +const ( + // An empty event. + yaml_NO_EVENT yaml_event_type_t = iota + + yaml_STREAM_START_EVENT // A STREAM-START event. + yaml_STREAM_END_EVENT // A STREAM-END event. + yaml_DOCUMENT_START_EVENT // A DOCUMENT-START event. + yaml_DOCUMENT_END_EVENT // A DOCUMENT-END event. + yaml_ALIAS_EVENT // An ALIAS event. + yaml_SCALAR_EVENT // A SCALAR event. + yaml_SEQUENCE_START_EVENT // A SEQUENCE-START event. + yaml_SEQUENCE_END_EVENT // A SEQUENCE-END event. + yaml_MAPPING_START_EVENT // A MAPPING-START event. + yaml_MAPPING_END_EVENT // A MAPPING-END event. +) + +var eventStrings = []string{ + yaml_NO_EVENT: "none", + yaml_STREAM_START_EVENT: "stream start", + yaml_STREAM_END_EVENT: "stream end", + yaml_DOCUMENT_START_EVENT: "document start", + yaml_DOCUMENT_END_EVENT: "document end", + yaml_ALIAS_EVENT: "alias", + yaml_SCALAR_EVENT: "scalar", + yaml_SEQUENCE_START_EVENT: "sequence start", + yaml_SEQUENCE_END_EVENT: "sequence end", + yaml_MAPPING_START_EVENT: "mapping start", + yaml_MAPPING_END_EVENT: "mapping end", +} + +func (e yaml_event_type_t) String() string { + if e < 0 || int(e) >= len(eventStrings) { + return fmt.Sprintf("unknown event %d", e) + } + return eventStrings[e] +} + +// The event structure. +type yaml_event_t struct { + + // The event type. + typ yaml_event_type_t + + // The start and end of the event. + start_mark, end_mark yaml_mark_t + + // The document encoding (for yaml_STREAM_START_EVENT). + encoding yaml_encoding_t + + // The version directive (for yaml_DOCUMENT_START_EVENT). + version_directive *yaml_version_directive_t + + // The list of tag directives (for yaml_DOCUMENT_START_EVENT). + tag_directives []yaml_tag_directive_t + + // The anchor (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT, yaml_ALIAS_EVENT). + anchor []byte + + // The tag (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT). + tag []byte + + // The scalar value (for yaml_SCALAR_EVENT). + value []byte + + // Is the document start/end indicator implicit, or the tag optional? + // (for yaml_DOCUMENT_START_EVENT, yaml_DOCUMENT_END_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT, yaml_SCALAR_EVENT). + implicit bool + + // Is the tag optional for any non-plain style? (for yaml_SCALAR_EVENT). + quoted_implicit bool + + // The style (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT). + style yaml_style_t +} + +func (e *yaml_event_t) scalar_style() yaml_scalar_style_t { return yaml_scalar_style_t(e.style) } +func (e *yaml_event_t) sequence_style() yaml_sequence_style_t { return yaml_sequence_style_t(e.style) } +func (e *yaml_event_t) mapping_style() yaml_mapping_style_t { return yaml_mapping_style_t(e.style) } + +// Nodes + +const ( + yaml_NULL_TAG = "tag:yaml.org,2002:null" // The tag !!null with the only possible value: null. + yaml_BOOL_TAG = "tag:yaml.org,2002:bool" // The tag !!bool with the values: true and false. + yaml_STR_TAG = "tag:yaml.org,2002:str" // The tag !!str for string values. + yaml_INT_TAG = "tag:yaml.org,2002:int" // The tag !!int for integer values. + yaml_FLOAT_TAG = "tag:yaml.org,2002:float" // The tag !!float for float values. + yaml_TIMESTAMP_TAG = "tag:yaml.org,2002:timestamp" // The tag !!timestamp for date and time values. + + yaml_SEQ_TAG = "tag:yaml.org,2002:seq" // The tag !!seq is used to denote sequences. + yaml_MAP_TAG = "tag:yaml.org,2002:map" // The tag !!map is used to denote mapping. + + // Not in original libyaml. + yaml_BINARY_TAG = "tag:yaml.org,2002:binary" + yaml_MERGE_TAG = "tag:yaml.org,2002:merge" + + yaml_DEFAULT_SCALAR_TAG = yaml_STR_TAG // The default scalar tag is !!str. + yaml_DEFAULT_SEQUENCE_TAG = yaml_SEQ_TAG // The default sequence tag is !!seq. + yaml_DEFAULT_MAPPING_TAG = yaml_MAP_TAG // The default mapping tag is !!map. +) + +type yaml_node_type_t int + +// Node types. +const ( + // An empty node. + yaml_NO_NODE yaml_node_type_t = iota + + yaml_SCALAR_NODE // A scalar node. + yaml_SEQUENCE_NODE // A sequence node. + yaml_MAPPING_NODE // A mapping node. +) + +// An element of a sequence node. +type yaml_node_item_t int + +// An element of a mapping node. +type yaml_node_pair_t struct { + key int // The key of the element. + value int // The value of the element. +} + +// The node structure. +type yaml_node_t struct { + typ yaml_node_type_t // The node type. + tag []byte // The node tag. + + // The node data. + + // The scalar parameters (for yaml_SCALAR_NODE). + scalar struct { + value []byte // The scalar value. + length int // The length of the scalar value. + style yaml_scalar_style_t // The scalar style. + } + + // The sequence parameters (for YAML_SEQUENCE_NODE). + sequence struct { + items_data []yaml_node_item_t // The stack of sequence items. + style yaml_sequence_style_t // The sequence style. + } + + // The mapping parameters (for yaml_MAPPING_NODE). + mapping struct { + pairs_data []yaml_node_pair_t // The stack of mapping pairs (key, value). + pairs_start *yaml_node_pair_t // The beginning of the stack. + pairs_end *yaml_node_pair_t // The end of the stack. + pairs_top *yaml_node_pair_t // The top of the stack. + style yaml_mapping_style_t // The mapping style. + } + + start_mark yaml_mark_t // The beginning of the node. + end_mark yaml_mark_t // The end of the node. + +} + +// The document structure. +type yaml_document_t struct { + + // The document nodes. + nodes []yaml_node_t + + // The version directive. + version_directive *yaml_version_directive_t + + // The list of tag directives. + tag_directives_data []yaml_tag_directive_t + tag_directives_start int // The beginning of the tag directives list. + tag_directives_end int // The end of the tag directives list. + + start_implicit int // Is the document start indicator implicit? + end_implicit int // Is the document end indicator implicit? + + // The start/end of the document. + start_mark, end_mark yaml_mark_t +} + +// The prototype of a read handler. +// +// The read handler is called when the parser needs to read more bytes from the +// source. The handler should write not more than size bytes to the buffer. +// The number of written bytes should be set to the size_read variable. +// +// [in,out] data A pointer to an application data specified by +// yaml_parser_set_input(). +// [out] buffer The buffer to write the data from the source. +// [in] size The size of the buffer. +// [out] size_read The actual number of bytes read from the source. +// +// On success, the handler should return 1. If the handler failed, +// the returned value should be 0. On EOF, the handler should set the +// size_read to 0 and return 1. +type yaml_read_handler_t func(parser *yaml_parser_t, buffer []byte) (n int, err error) + +// This structure holds information about a potential simple key. +type yaml_simple_key_t struct { + possible bool // Is a simple key possible? + required bool // Is a simple key required? + token_number int // The number of the token. + mark yaml_mark_t // The position mark. +} + +// The states of the parser. +type yaml_parser_state_t int + +const ( + yaml_PARSE_STREAM_START_STATE yaml_parser_state_t = iota + + yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE // Expect the beginning of an implicit document. + yaml_PARSE_DOCUMENT_START_STATE // Expect DOCUMENT-START. + yaml_PARSE_DOCUMENT_CONTENT_STATE // Expect the content of a document. + yaml_PARSE_DOCUMENT_END_STATE // Expect DOCUMENT-END. + yaml_PARSE_BLOCK_NODE_STATE // Expect a block node. + yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE // Expect a block node or indentless sequence. + yaml_PARSE_FLOW_NODE_STATE // Expect a flow node. + yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE // Expect the first entry of a block sequence. + yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE // Expect an entry of a block sequence. + yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE // Expect an entry of an indentless sequence. + yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE // Expect the first key of a block mapping. + yaml_PARSE_BLOCK_MAPPING_KEY_STATE // Expect a block mapping key. + yaml_PARSE_BLOCK_MAPPING_VALUE_STATE // Expect a block mapping value. + yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE // Expect the first entry of a flow sequence. + yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE // Expect an entry of a flow sequence. + yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE // Expect a key of an ordered mapping. + yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE // Expect a value of an ordered mapping. + yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE // Expect the and of an ordered mapping entry. + yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE // Expect the first key of a flow mapping. + yaml_PARSE_FLOW_MAPPING_KEY_STATE // Expect a key of a flow mapping. + yaml_PARSE_FLOW_MAPPING_VALUE_STATE // Expect a value of a flow mapping. + yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE // Expect an empty value of a flow mapping. + yaml_PARSE_END_STATE // Expect nothing. +) + +func (ps yaml_parser_state_t) String() string { + switch ps { + case yaml_PARSE_STREAM_START_STATE: + return "yaml_PARSE_STREAM_START_STATE" + case yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE: + return "yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE" + case yaml_PARSE_DOCUMENT_START_STATE: + return "yaml_PARSE_DOCUMENT_START_STATE" + case yaml_PARSE_DOCUMENT_CONTENT_STATE: + return "yaml_PARSE_DOCUMENT_CONTENT_STATE" + case yaml_PARSE_DOCUMENT_END_STATE: + return "yaml_PARSE_DOCUMENT_END_STATE" + case yaml_PARSE_BLOCK_NODE_STATE: + return "yaml_PARSE_BLOCK_NODE_STATE" + case yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE: + return "yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE" + case yaml_PARSE_FLOW_NODE_STATE: + return "yaml_PARSE_FLOW_NODE_STATE" + case yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE: + return "yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE" + case yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE: + return "yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE" + case yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE: + return "yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE" + case yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE: + return "yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE" + case yaml_PARSE_BLOCK_MAPPING_KEY_STATE: + return "yaml_PARSE_BLOCK_MAPPING_KEY_STATE" + case yaml_PARSE_BLOCK_MAPPING_VALUE_STATE: + return "yaml_PARSE_BLOCK_MAPPING_VALUE_STATE" + case yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE: + return "yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE" + case yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE: + return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE" + case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE: + return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE" + case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE: + return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE" + case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE: + return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE" + case yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE: + return "yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE" + case yaml_PARSE_FLOW_MAPPING_KEY_STATE: + return "yaml_PARSE_FLOW_MAPPING_KEY_STATE" + case yaml_PARSE_FLOW_MAPPING_VALUE_STATE: + return "yaml_PARSE_FLOW_MAPPING_VALUE_STATE" + case yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE: + return "yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE" + case yaml_PARSE_END_STATE: + return "yaml_PARSE_END_STATE" + } + return "" +} + +// This structure holds aliases data. +type yaml_alias_data_t struct { + anchor []byte // The anchor. + index int // The node id. + mark yaml_mark_t // The anchor mark. +} + +// The parser structure. +// +// All members are internal. Manage the structure using the +// yaml_parser_ family of functions. +type yaml_parser_t struct { + + // Error handling + + error yaml_error_type_t // Error type. + + problem string // Error description. + + // The byte about which the problem occurred. + problem_offset int + problem_value int + problem_mark yaml_mark_t + + // The error context. + context string + context_mark yaml_mark_t + + // Reader stuff + + read_handler yaml_read_handler_t // Read handler. + + input_reader io.Reader // File input data. + input []byte // String input data. + input_pos int + + eof bool // EOF flag + + buffer []byte // The working buffer. + buffer_pos int // The current position of the buffer. + + unread int // The number of unread characters in the buffer. + + raw_buffer []byte // The raw buffer. + raw_buffer_pos int // The current position of the buffer. + + encoding yaml_encoding_t // The input encoding. + + offset int // The offset of the current position (in bytes). + mark yaml_mark_t // The mark of the current position. + + // Scanner stuff + + stream_start_produced bool // Have we started to scan the input stream? + stream_end_produced bool // Have we reached the end of the input stream? + + flow_level int // The number of unclosed '[' and '{' indicators. + + tokens []yaml_token_t // The tokens queue. + tokens_head int // The head of the tokens queue. + tokens_parsed int // The number of tokens fetched from the queue. + token_available bool // Does the tokens queue contain a token ready for dequeueing. + + indent int // The current indentation level. + indents []int // The indentation levels stack. + + simple_key_allowed bool // May a simple key occur at the current position? + simple_keys []yaml_simple_key_t // The stack of simple keys. + simple_keys_by_tok map[int]int // possible simple_key indexes indexed by token_number + + // Parser stuff + + state yaml_parser_state_t // The current parser state. + states []yaml_parser_state_t // The parser states stack. + marks []yaml_mark_t // The stack of marks. + tag_directives []yaml_tag_directive_t // The list of TAG directives. + + // Dumper stuff + + aliases []yaml_alias_data_t // The alias data. + + document *yaml_document_t // The currently parsed document. +} + +// Emitter Definitions + +// The prototype of a write handler. +// +// The write handler is called when the emitter needs to flush the accumulated +// characters to the output. The handler should write @a size bytes of the +// @a buffer to the output. +// +// @param[in,out] data A pointer to an application data specified by +// yaml_emitter_set_output(). +// @param[in] buffer The buffer with bytes to be written. +// @param[in] size The size of the buffer. +// +// @returns On success, the handler should return @c 1. If the handler failed, +// the returned value should be @c 0. +// +type yaml_write_handler_t func(emitter *yaml_emitter_t, buffer []byte) error + +type yaml_emitter_state_t int + +// The emitter states. +const ( + // Expect STREAM-START. + yaml_EMIT_STREAM_START_STATE yaml_emitter_state_t = iota + + yaml_EMIT_FIRST_DOCUMENT_START_STATE // Expect the first DOCUMENT-START or STREAM-END. + yaml_EMIT_DOCUMENT_START_STATE // Expect DOCUMENT-START or STREAM-END. + yaml_EMIT_DOCUMENT_CONTENT_STATE // Expect the content of a document. + yaml_EMIT_DOCUMENT_END_STATE // Expect DOCUMENT-END. + yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE // Expect the first item of a flow sequence. + yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE // Expect an item of a flow sequence. + yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE // Expect the first key of a flow mapping. + yaml_EMIT_FLOW_MAPPING_KEY_STATE // Expect a key of a flow mapping. + yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE // Expect a value for a simple key of a flow mapping. + yaml_EMIT_FLOW_MAPPING_VALUE_STATE // Expect a value of a flow mapping. + yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE // Expect the first item of a block sequence. + yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE // Expect an item of a block sequence. + yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE // Expect the first key of a block mapping. + yaml_EMIT_BLOCK_MAPPING_KEY_STATE // Expect the key of a block mapping. + yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE // Expect a value for a simple key of a block mapping. + yaml_EMIT_BLOCK_MAPPING_VALUE_STATE // Expect a value of a block mapping. + yaml_EMIT_END_STATE // Expect nothing. +) + +// The emitter structure. +// +// All members are internal. Manage the structure using the @c yaml_emitter_ +// family of functions. +type yaml_emitter_t struct { + + // Error handling + + error yaml_error_type_t // Error type. + problem string // Error description. + + // Writer stuff + + write_handler yaml_write_handler_t // Write handler. + + output_buffer *[]byte // String output data. + output_writer io.Writer // File output data. + + buffer []byte // The working buffer. + buffer_pos int // The current position of the buffer. + + raw_buffer []byte // The raw buffer. + raw_buffer_pos int // The current position of the buffer. + + encoding yaml_encoding_t // The stream encoding. + + // Emitter stuff + + canonical bool // If the output is in the canonical style? + best_indent int // The number of indentation spaces. + best_width int // The preferred width of the output lines. + unicode bool // Allow unescaped non-ASCII characters? + line_break yaml_break_t // The preferred line break. + + state yaml_emitter_state_t // The current emitter state. + states []yaml_emitter_state_t // The stack of states. + + events []yaml_event_t // The event queue. + events_head int // The head of the event queue. + + indents []int // The stack of indentation levels. + + tag_directives []yaml_tag_directive_t // The list of tag directives. + + indent int // The current indentation level. + + flow_level int // The current flow level. + + root_context bool // Is it the document root context? + sequence_context bool // Is it a sequence context? + mapping_context bool // Is it a mapping context? + simple_key_context bool // Is it a simple mapping key context? + + line int // The current line. + column int // The current column. + whitespace bool // If the last character was a whitespace? + indention bool // If the last character was an indentation character (' ', '-', '?', ':')? + open_ended bool // If an explicit document end is required? + + // Anchor analysis. + anchor_data struct { + anchor []byte // The anchor value. + alias bool // Is it an alias? + } + + // Tag analysis. + tag_data struct { + handle []byte // The tag handle. + suffix []byte // The tag suffix. + } + + // Scalar analysis. + scalar_data struct { + value []byte // The scalar value. + multiline bool // Does the scalar contain line breaks? + flow_plain_allowed bool // Can the scalar be expessed in the flow plain style? + block_plain_allowed bool // Can the scalar be expressed in the block plain style? + single_quoted_allowed bool // Can the scalar be expressed in the single quoted style? + block_allowed bool // Can the scalar be expressed in the literal or folded styles? + style yaml_scalar_style_t // The output style. + } + + // Dumper stuff + + opened bool // If the stream was already opened? + closed bool // If the stream was already closed? + + // The information associated with the document nodes. + anchors *struct { + references int // The number of references. + anchor int // The anchor id. + serialized bool // If the node has been emitted? + } + + last_anchor_id int // The last assigned anchor id. + + document *yaml_document_t // The currently emitted document. +} diff --git a/vendor/sigs.k8s.io/yaml/goyaml.v2/yamlprivateh.go b/vendor/sigs.k8s.io/yaml/goyaml.v2/yamlprivateh.go new file mode 100644 index 000000000..8110ce3c3 --- /dev/null +++ b/vendor/sigs.k8s.io/yaml/goyaml.v2/yamlprivateh.go @@ -0,0 +1,173 @@ +package yaml + +const ( + // The size of the input raw buffer. + input_raw_buffer_size = 512 + + // The size of the input buffer. + // It should be possible to decode the whole raw buffer. + input_buffer_size = input_raw_buffer_size * 3 + + // The size of the output buffer. + output_buffer_size = 128 + + // The size of the output raw buffer. + // It should be possible to encode the whole output buffer. + output_raw_buffer_size = (output_buffer_size*2 + 2) + + // The size of other stacks and queues. + initial_stack_size = 16 + initial_queue_size = 16 + initial_string_size = 16 +) + +// Check if the character at the specified position is an alphabetical +// character, a digit, '_', or '-'. +func is_alpha(b []byte, i int) bool { + return b[i] >= '0' && b[i] <= '9' || b[i] >= 'A' && b[i] <= 'Z' || b[i] >= 'a' && b[i] <= 'z' || b[i] == '_' || b[i] == '-' +} + +// Check if the character at the specified position is a digit. +func is_digit(b []byte, i int) bool { + return b[i] >= '0' && b[i] <= '9' +} + +// Get the value of a digit. +func as_digit(b []byte, i int) int { + return int(b[i]) - '0' +} + +// Check if the character at the specified position is a hex-digit. +func is_hex(b []byte, i int) bool { + return b[i] >= '0' && b[i] <= '9' || b[i] >= 'A' && b[i] <= 'F' || b[i] >= 'a' && b[i] <= 'f' +} + +// Get the value of a hex-digit. +func as_hex(b []byte, i int) int { + bi := b[i] + if bi >= 'A' && bi <= 'F' { + return int(bi) - 'A' + 10 + } + if bi >= 'a' && bi <= 'f' { + return int(bi) - 'a' + 10 + } + return int(bi) - '0' +} + +// Check if the character is ASCII. +func is_ascii(b []byte, i int) bool { + return b[i] <= 0x7F +} + +// Check if the character at the start of the buffer can be printed unescaped. +func is_printable(b []byte, i int) bool { + return ((b[i] == 0x0A) || // . == #x0A + (b[i] >= 0x20 && b[i] <= 0x7E) || // #x20 <= . <= #x7E + (b[i] == 0xC2 && b[i+1] >= 0xA0) || // #0xA0 <= . <= #xD7FF + (b[i] > 0xC2 && b[i] < 0xED) || + (b[i] == 0xED && b[i+1] < 0xA0) || + (b[i] == 0xEE) || + (b[i] == 0xEF && // #xE000 <= . <= #xFFFD + !(b[i+1] == 0xBB && b[i+2] == 0xBF) && // && . != #xFEFF + !(b[i+1] == 0xBF && (b[i+2] == 0xBE || b[i+2] == 0xBF)))) +} + +// Check if the character at the specified position is NUL. +func is_z(b []byte, i int) bool { + return b[i] == 0x00 +} + +// Check if the beginning of the buffer is a BOM. +func is_bom(b []byte, i int) bool { + return b[0] == 0xEF && b[1] == 0xBB && b[2] == 0xBF +} + +// Check if the character at the specified position is space. +func is_space(b []byte, i int) bool { + return b[i] == ' ' +} + +// Check if the character at the specified position is tab. +func is_tab(b []byte, i int) bool { + return b[i] == '\t' +} + +// Check if the character at the specified position is blank (space or tab). +func is_blank(b []byte, i int) bool { + //return is_space(b, i) || is_tab(b, i) + return b[i] == ' ' || b[i] == '\t' +} + +// Check if the character at the specified position is a line break. +func is_break(b []byte, i int) bool { + return (b[i] == '\r' || // CR (#xD) + b[i] == '\n' || // LF (#xA) + b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85) + b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028) + b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9) // PS (#x2029) +} + +func is_crlf(b []byte, i int) bool { + return b[i] == '\r' && b[i+1] == '\n' +} + +// Check if the character is a line break or NUL. +func is_breakz(b []byte, i int) bool { + //return is_break(b, i) || is_z(b, i) + return ( // is_break: + b[i] == '\r' || // CR (#xD) + b[i] == '\n' || // LF (#xA) + b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85) + b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028) + b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029) + // is_z: + b[i] == 0) +} + +// Check if the character is a line break, space, or NUL. +func is_spacez(b []byte, i int) bool { + //return is_space(b, i) || is_breakz(b, i) + return ( // is_space: + b[i] == ' ' || + // is_breakz: + b[i] == '\r' || // CR (#xD) + b[i] == '\n' || // LF (#xA) + b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85) + b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028) + b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029) + b[i] == 0) +} + +// Check if the character is a line break, space, tab, or NUL. +func is_blankz(b []byte, i int) bool { + //return is_blank(b, i) || is_breakz(b, i) + return ( // is_blank: + b[i] == ' ' || b[i] == '\t' || + // is_breakz: + b[i] == '\r' || // CR (#xD) + b[i] == '\n' || // LF (#xA) + b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85) + b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028) + b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029) + b[i] == 0) +} + +// Determine the width of the character. +func width(b byte) int { + // Don't replace these by a switch without first + // confirming that it is being inlined. + if b&0x80 == 0x00 { + return 1 + } + if b&0xE0 == 0xC0 { + return 2 + } + if b&0xF0 == 0xE0 { + return 3 + } + if b&0xF8 == 0xF0 { + return 4 + } + return 0 + +} diff --git a/vendor/sigs.k8s.io/yaml/yaml.go b/vendor/sigs.k8s.io/yaml/yaml.go index efbc535d4..fc10246bd 100644 --- a/vendor/sigs.k8s.io/yaml/yaml.go +++ b/vendor/sigs.k8s.io/yaml/yaml.go @@ -1,3 +1,19 @@ +/* +Copyright 2021 The Kubernetes 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. +*/ + package yaml import ( @@ -8,56 +24,59 @@ import ( "reflect" "strconv" - "gopkg.in/yaml.v2" + "sigs.k8s.io/yaml/goyaml.v2" ) -// Marshal marshals the object into JSON then converts JSON to YAML and returns the -// YAML. -func Marshal(o interface{}) ([]byte, error) { - j, err := json.Marshal(o) +// Marshal marshals obj into JSON using stdlib json.Marshal, and then converts JSON to YAML using JSONToYAML (see that method for more reference) +func Marshal(obj interface{}) ([]byte, error) { + jsonBytes, err := json.Marshal(obj) if err != nil { - return nil, fmt.Errorf("error marshaling into JSON: %v", err) + return nil, fmt.Errorf("error marshaling into JSON: %w", err) } - y, err := JSONToYAML(j) - if err != nil { - return nil, fmt.Errorf("error converting JSON to YAML: %v", err) - } - - return y, nil + return JSONToYAML(jsonBytes) } // JSONOpt is a decoding option for decoding from JSON format. type JSONOpt func(*json.Decoder) *json.Decoder -// Unmarshal converts YAML to JSON then uses JSON to unmarshal into an object, -// optionally configuring the behavior of the JSON unmarshal. -func Unmarshal(y []byte, o interface{}, opts ...JSONOpt) error { - return yamlUnmarshal(y, o, false, opts...) +// Unmarshal first converts the given YAML to JSON, and then unmarshals the JSON into obj. Options for the +// standard library json.Decoder can be optionally specified, e.g. to decode untyped numbers into json.Number instead of float64, or to disallow unknown fields (but for that purpose, see also UnmarshalStrict). obj must be a non-nil pointer. +// +// Important notes about the Unmarshal logic: +// +// - Decoding is case-insensitive, unlike the rest of Kubernetes API machinery, as this is using the stdlib json library. This might be confusing to users. +// - This decodes any number (although it is an integer) into a float64 if the type of obj is unknown, e.g. *map[string]interface{}, *interface{}, or *[]interface{}. This means integers above +/- 2^53 will lose precision when round-tripping. Make a JSONOpt that calls d.UseNumber() to avoid this. +// - Duplicate fields, including in-case-sensitive matches, are ignored in an undefined order. Note that the YAML specification forbids duplicate fields, so this logic is more permissive than it needs to. See UnmarshalStrict for an alternative. +// - Unknown fields, i.e. serialized data that do not map to a field in obj, are ignored. Use d.DisallowUnknownFields() or UnmarshalStrict to override. +// - As per the YAML 1.1 specification, which yaml.v2 used underneath implements, literal 'yes' and 'no' strings without quotation marks will be converted to true/false implicitly. +// - YAML non-string keys, e.g. ints, bools and floats, are converted to strings implicitly during the YAML to JSON conversion process. +// - There are no compatibility guarantees for returned error values. +func Unmarshal(yamlBytes []byte, obj interface{}, opts ...JSONOpt) error { + return unmarshal(yamlBytes, obj, yaml.Unmarshal, opts...) } -// UnmarshalStrict strictly converts YAML to JSON then uses JSON to unmarshal -// into an object, optionally configuring the behavior of the JSON unmarshal. -func UnmarshalStrict(y []byte, o interface{}, opts ...JSONOpt) error { - return yamlUnmarshal(y, o, true, append(opts, DisallowUnknownFields)...) +// UnmarshalStrict is similar to Unmarshal (please read its documentation for reference), with the following exceptions: +// +// - Duplicate fields in an object yield an error. This is according to the YAML specification. +// - If obj, or any of its recursive children, is a struct, presence of fields in the serialized data unknown to the struct will yield an error. +func UnmarshalStrict(yamlBytes []byte, obj interface{}, opts ...JSONOpt) error { + return unmarshal(yamlBytes, obj, yaml.UnmarshalStrict, append(opts, DisallowUnknownFields)...) } -// yamlUnmarshal unmarshals the given YAML byte stream into the given interface, +// unmarshal unmarshals the given YAML byte stream into the given interface, // optionally performing the unmarshalling strictly -func yamlUnmarshal(y []byte, o interface{}, strict bool, opts ...JSONOpt) error { - vo := reflect.ValueOf(o) - unmarshalFn := yaml.Unmarshal - if strict { - unmarshalFn = yaml.UnmarshalStrict - } - j, err := yamlToJSON(y, &vo, unmarshalFn) +func unmarshal(yamlBytes []byte, obj interface{}, unmarshalFn func([]byte, interface{}) error, opts ...JSONOpt) error { + jsonTarget := reflect.ValueOf(obj) + + jsonBytes, err := yamlToJSONTarget(yamlBytes, &jsonTarget, unmarshalFn) if err != nil { - return fmt.Errorf("error converting YAML to JSON: %v", err) + return fmt.Errorf("error converting YAML to JSON: %w", err) } - err = jsonUnmarshal(bytes.NewReader(j), o, opts...) + err = jsonUnmarshal(bytes.NewReader(jsonBytes), obj, opts...) if err != nil { - return fmt.Errorf("error unmarshaling JSON: %v", err) + return fmt.Errorf("error unmarshaling JSON: %w", err) } return nil @@ -67,21 +86,26 @@ func yamlUnmarshal(y []byte, o interface{}, strict bool, opts ...JSONOpt) error // object, optionally applying decoder options prior to decoding. We are not // using json.Unmarshal directly as we want the chance to pass in non-default // options. -func jsonUnmarshal(r io.Reader, o interface{}, opts ...JSONOpt) error { - d := json.NewDecoder(r) +func jsonUnmarshal(reader io.Reader, obj interface{}, opts ...JSONOpt) error { + d := json.NewDecoder(reader) for _, opt := range opts { d = opt(d) } - if err := d.Decode(&o); err != nil { + if err := d.Decode(&obj); err != nil { return fmt.Errorf("while decoding JSON: %v", err) } return nil } -// JSONToYAML Converts JSON to YAML. +// JSONToYAML converts JSON to YAML. Notable implementation details: +// +// - Duplicate fields, are case-sensitively ignored in an undefined order. +// - The sequence indentation style is compact, which means that the "- " marker for a YAML sequence will be on the same indentation level as the sequence field name. +// - Unlike Unmarshal, all integers, up to 64 bits, are preserved during this round-trip. func JSONToYAML(j []byte) ([]byte, error) { // Convert the JSON to an object. var jsonObj interface{} + // We are using yaml.Unmarshal here (instead of json.Unmarshal) because the // Go JSON library doesn't try to pick the right number type (int, float, // etc.) when unmarshalling to interface{}, it just picks float64 @@ -93,35 +117,46 @@ func JSONToYAML(j []byte) ([]byte, error) { } // Marshal this object into YAML. - return yaml.Marshal(jsonObj) + yamlBytes, err := yaml.Marshal(jsonObj) + if err != nil { + return nil, err + } + + return yamlBytes, nil } // YAMLToJSON converts YAML to JSON. Since JSON is a subset of YAML, // passing JSON through this method should be a no-op. // -// Things YAML can do that are not supported by JSON: -// * In YAML you can have binary and null keys in your maps. These are invalid -// in JSON. (int and float keys are converted to strings.) -// * Binary data in YAML with the !!binary tag is not supported. If you want to -// use binary data with this library, encode the data as base64 as usual but do -// not use the !!binary tag in your YAML. This will ensure the original base64 -// encoded data makes it all the way through to the JSON. +// Some things YAML can do that are not supported by JSON: +// - In YAML you can have binary and null keys in your maps. These are invalid +// in JSON, and therefore int, bool and float keys are converted to strings implicitly. +// - Binary data in YAML with the !!binary tag is not supported. If you want to +// use binary data with this library, encode the data as base64 as usual but do +// not use the !!binary tag in your YAML. This will ensure the original base64 +// encoded data makes it all the way through to the JSON. +// - And more... read the YAML specification for more details. +// +// Notable about the implementation: // -// For strict decoding of YAML, use YAMLToJSONStrict. +// - Duplicate fields are case-sensitively ignored in an undefined order. Note that the YAML specification forbids duplicate fields, so this logic is more permissive than it needs to. See YAMLToJSONStrict for an alternative. +// - As per the YAML 1.1 specification, which yaml.v2 used underneath implements, literal 'yes' and 'no' strings without quotation marks will be converted to true/false implicitly. +// - Unlike Unmarshal, all integers, up to 64 bits, are preserved during this round-trip. +// - There are no compatibility guarantees for returned error values. func YAMLToJSON(y []byte) ([]byte, error) { - return yamlToJSON(y, nil, yaml.Unmarshal) + return yamlToJSONTarget(y, nil, yaml.Unmarshal) } // YAMLToJSONStrict is like YAMLToJSON but enables strict YAML decoding, // returning an error on any duplicate field names. func YAMLToJSONStrict(y []byte) ([]byte, error) { - return yamlToJSON(y, nil, yaml.UnmarshalStrict) + return yamlToJSONTarget(y, nil, yaml.UnmarshalStrict) } -func yamlToJSON(y []byte, jsonTarget *reflect.Value, yamlUnmarshal func([]byte, interface{}) error) ([]byte, error) { +func yamlToJSONTarget(yamlBytes []byte, jsonTarget *reflect.Value, unmarshalFn func([]byte, interface{}) error) ([]byte, error) { // Convert the YAML to an object. var yamlObj interface{} - err := yamlUnmarshal(y, &yamlObj) + err := unmarshalFn(yamlBytes, &yamlObj) if err != nil { return nil, err } @@ -136,7 +171,11 @@ func yamlToJSON(y []byte, jsonTarget *reflect.Value, yamlUnmarshal func([]byte, } // Convert this object to JSON and return the data. - return json.Marshal(jsonObj) + jsonBytes, err := json.Marshal(jsonObj) + if err != nil { + return nil, err + } + return jsonBytes, nil } func convertToJSONableObject(yamlObj interface{}, jsonTarget *reflect.Value) (interface{}, error) { @@ -147,13 +186,13 @@ func convertToJSONableObject(yamlObj interface{}, jsonTarget *reflect.Value) (in // decoding into the value, we're just checking if the ultimate target is a // string. if jsonTarget != nil { - ju, tu, pv := indirect(*jsonTarget, false) + jsonUnmarshaler, textUnmarshaler, pointerValue := indirect(*jsonTarget, false) // We have a JSON or Text Umarshaler at this level, so we can't be trying // to decode into a string. - if ju != nil || tu != nil { + if jsonUnmarshaler != nil || textUnmarshaler != nil { jsonTarget = nil } else { - jsonTarget = &pv + jsonTarget = &pointerValue } } @@ -205,7 +244,7 @@ func convertToJSONableObject(yamlObj interface{}, jsonTarget *reflect.Value) (in keyString = "false" } default: - return nil, fmt.Errorf("Unsupported map key of type: %s, key: %+#v, value: %+#v", + return nil, fmt.Errorf("unsupported map key of type: %s, key: %+#v, value: %+#v", reflect.TypeOf(k), k, v) } diff --git a/vendor/sigs.k8s.io/yaml/yaml_go110.go b/vendor/sigs.k8s.io/yaml/yaml_go110.go index ab3e06a22..94abc1719 100644 --- a/vendor/sigs.k8s.io/yaml/yaml_go110.go +++ b/vendor/sigs.k8s.io/yaml/yaml_go110.go @@ -1,7 +1,24 @@ // This file contains changes that are only compatible with go 1.10 and onwards. +//go:build go1.10 // +build go1.10 +/* +Copyright 2021 The Kubernetes 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. +*/ + package yaml import "encoding/json"

!WzDz+7{T|GofHxyD&f{PW1VI1q5BSn+iKFC!qStT9jG&LWi@HP=N1E|<^>{Q^e=_7|3P5) zE)@HmY2X`hfz)%R#ytp7-dHHA^z1|R+kE6-)^mn;_Y_tUW1iw4X}>*%hzyrU;lCKl zdZX~aJ}yR%r$gU>EsFoHg|Y`>x_(21UUwM#Z{+*^6c6dSQ+h!54gS8!UR?JPdvS@L zy*uz5(M@sDV&Xzb15!0Fiav!*ZI- ztC8Qc1x>f>yh6JnCj`64^+V8HAP*zI=W9{zp19I@{d#Y6A&`GY!RNnH{W%b%XBRZC zA1ipQR6c=oT=zt^^zAa4hS;)eE%(SZd993U!jdZ6M`&$WpEC=--xui*eyO zHt-AMer!a5WAwcF^l!jT&z#+f<{Yzch`^|QDyrR?7q0-H)tuk|&Y3}nx3ADf6d=gr z84g?{`=i?Y^$Kme6Bv&jDk#pFf|36PR+dDyAG}g~3&Y8=f~RxjwNY(exzgOQu_g*z zvUeN4`HST6i&)8tYQO(V?GXeqW^p>l3J%;X2cz2k=t}ME&`V|Q=7l1u#ChT6kLXet z&I%uH(WU?Qq3)Pk|5xZEe^L*!wUz3SuZ57xf_XP1(3wjGF%YX5;=RuMJF>#hXf89fLTzV$YF7*C(Ks$ay) z_NY1Ly*R@b#P--|d(hDPI^)6Bl>dHs4U@|hSG6x2cqFvcVZonJKJrQNE9> z!88v2rSC#ObqnNVm#Ne*HC0UOTQITN|{dzvsOmR(>6v>6=gjVxLQZwE8Ij1eBr1Bp(a00X7|u>{ysoLAlgSEgh9)X6N#UL;4tR3lh`>G zgS3cacJLhqW^82PxPEN;P?C%(-ePzoUOW4$1+E6O^C5aUu~KAK6)n&}kG85|7ZTnmdaF zuuYtxYm42t#!)?u*G{q6F_4`IqWl9PT*HAR>z2o|h<*9{~k9Mpb%AA3Ji;4e#{2VK{82BGGeK-!8z95Gpz91_<4*qk% z*KRZLf9kpe{}#c&5!>q2J`N3d;Zhn12`n!`Sycr80;E;S;NvYIy*{q*sQX*K96JW( ze=5HswD`_tXhCT{8!e8+Fkg1eJ`T-a{rM#{Kel|-YOJ4UxfwKX4;nOY`Z-p971J(ut)5}I$1e5Tq4W19 z8hLG^>F>20G*{;x__uNp$ywtb+ZF38W#BzC3h$ZWnsks<)9?Kh!+R#f`}Q;_@8(2u zH@o+xJj7`~1yDXadK`Oxw@^S+%*BnM;o_`&>@(6ej=X1WTXue!d`O?^XkHz{*{^{oiKfm}htO!3h_TUeHHj}TnQW^Me z8I@<`K62N5ej$nAeCDB-Ay@=4s)!UO8|LA!Wb*-PXMV@ zFw2%&HCGbI>*9^Fp?Hu=lgu*7s=3lY4p@vbpk--h*}qveS0>2&v~5hLnP;%K+V9p{!{_-`jt`Gy7{2{)a(uY`PLQZPpfZ4#G1;-g z@DpE=1gl!^;CwxIf<$%2>mOOyJf$lRz$&^1B00KN44_r-VL^Kp*~9rYApOLYcYnwc zcfN1t>QqzR(V$z2VT~7M~e@9{2d@Qt}JEy>j=)(;@Dq@#(Z9I9`l>xQKCk5j-Tkd z_b&D@-1hPJj1yQi?mT!%qx(jS3_gm_;-w({c3j`_#I^+tkKYAI{odwv%?E|#K(~p< z0R;ATERvCZ)B4q^6!U)m*4cGj?H0oiwH*WbN)(O^-V(w+ZYqyv!Ov1C7X*-bi|GCu z-7{m_g_g|Tu5?MHo!{LM)sE4`X3&IR9Lebx<8NCIJqcsSCv}Iv?ac}h z;cNc3u8QB$-}uc6Iwt+yj-6wJCJctWbB_Jm{9W@`{lz(^f7&)I66<&C$7+$V{ju0@ zNk=+cF0FU;TQT2OBpvB&RE6CS#nydP*u4>qwG+bpQMwlPnJ|QKu||J)P3n%A{jnFol-aLW;9qX~!u?miKemZun`A0gJ$9^k0(z)zXm|kCcnYA*Q zJNsI(%qkMAes2-$pl+yNr82D(r5l2_?fZAS zaua9!er;E7{A}M7x^gdKUK0?I#gn?jCV))w8<}r-YM&IsH5r%T-*hN1L86Sg@5QjFLuO3&2En7t>0|K!WyKN-q} zG=DRXgaDreGR3(*p*v#tAj(hP2}5Q?_8@_uJ|nX^+)*rtFuLR{PWRhlx=%*$6*gn9 z;H|U!i`5zNWSi-n{%1mW%xIfnv@Pam_XBH6U~T(o+uu&;4(Gptk52%}yD~pu(AC(# zL+1V+!g(wg7S)Mz4($Kzf0%8&7P{x>f5e_|)$pY5_&${(kr=Khn_vMp@}KB!NmsNB z(zXTBF-6ANg^T`*ma^eN!Z1SfUuoB(A(2PmKW{eL#n?#p$wEWj|4O`3> zD?6LaR^CR-`4o0GnXR0iUH-a|olP!Ner)Z7*gTuO!t$wIk|VP^_c(2P7GoFHd(WG( zy3z3rMF`5)Bv+|#V1r`q-MpJ(C&74SHc>ya%8#DIdFp?v_^O@)L4nKy)JzIHsD6fCnh(jb@9QcNB zF!FjqtG^=DCibcG5IK46?P^b<5f8B^9g$ZTAkyRE`at^I#R!&o z(^(uxFP$$3UwP)9QN1JI%%9BQoF(QEA&~Uy+?n|(**VF`N9lfHX3mkb7_=cF65o!r z;TI@>LiwNoqep1}=u@P`@+lUB&$k+RYhObkb;ZL^{Q!~`(Y0(37wEcVwb1`F!h@5# zWEG768z*%sBS~cKKfunZv0i-vEBy${hoW*SMb;6EXMA?P5p!OXKNVO0_ZP78-zKjz zd$70gk~)8W0V`oc67~}}vBK(=@ zAS0G>He9zR%#81xc%)h-MbojJ+pHovg)^DlDH#U2&H|^qCv>S4iG3{=@U7N$sZL#H8#CekFwVdPwEms{};PY7J)1XA}K&wfyQ`| z6r=&+GDT9D354>P0HF9M5*CLNL}CU1PFjcZTX6|e`*q!+{RAs|8)7m0GtR(m22PFm z6eB;v1q|9q5y%v0l?a6+xTf;In8loDhC?=xdg2Y9GUUH$ld?g1kQ3cq@!;DdfHYDR zWdk;2-Pyh~%U(+NogOR5`{G6SZ0&0J+1qVTfbyPXkhOG>U$TmB^=3HEY-KSq_BHXB zX>XzJMYj>7>@Z`LGd1rTa0kcr4yTTN4IB_akz9(7NGu1-iL`%Q?=aW3M)BXU7gUN< zii6ANKAzr>SkB`%!%kKc$=h)IGWi6yyG};sTuOSu$iqwboyC-%)y6uxxG_#0|EfhD ztB+UD-z&WfeYLRk9D@h!A~hXx2ARdw-e`0(RM5a$cYq?epwC2 z&*FHK7eL#U0dhN)nMI(+u{R9z!nE$zWRS*jw$_ESnU2)LxBx zLn%;B_kH0G@ug4-kV*?I8m4jx8}uDX5DBG4PjbZeIEU$tU1qHJND`FS+zfJUwKzuG zt5yhhnK9xm93KuPMs$%mOuve>D@}xQ8xs4nkq}rhu9ro(sj-1nA2W_>g>nIjeFzCh zDm4DR8S8#dm+1cv$O-5iA3k|jmp;TIX>kB){|(EbP&Txd<>A)e z8P_|`r--EeE28@i&dAY{A7|!hi5bT-u6KwSf^AiK&=t&Y`yN*({|9qPr6w=;RESDSgdQ$)h!+@s(4DpIM;*^~j~TScJ0Yw~K~AeB9o zSL4)+8!hViSL4;O`ULg-y}Ww%EWz>?BtPeJ11ArQ z?%`@9@9CCr=j=A{;?Q_BClIm$d6DQHUYvQ<3HI=}ZtCpJTlD?TfeBrr>->S1oZYk^ z+MXPy^v}|w+n>ZaF51U)MDK`3810!7hDaL)HTiY{-7_iyLy+e`&*yy+u4<)Pf znt|oQLtB8%^8U zw4Ww^=uDWNT?=Z$bWb+!cx|)7RDWQmp3PTqa>jdGcCvd`#NzO^d<4Ph_m1`+z>1&a zNzvG?Z_D~KXk@fAcYYJl6UJDUveVw@to^m(_|k6Bng3z6^~^m?~~OzTjXWADa?Szg5D>Ja9&N!!f(>y!gn`3C~! z?-gh&-vj`6TtT2j@=N?bR`yGEtRAV+dF`TeM%~95G0eZ~$VkUR%crFmysV)CXJfy4ul znptu$%*JcK-XEJ67-`Np@KOC}^%`^>z`wJof%(jz9%gSAePPTC5Ny~AGRqaX6&=3~ zff6lq8@4_$)`>v*b_G%%Wq6*McNqLg{(`P|G-Qcn2ZAX-5SHVhn(2)*@_6KOpk#nZ zZss9KdEdJgnfWse{jIjZ;8R`zsc|ooE2r#ShF-OThw^n_e*BO0ytyvabLQx_BWKp} zLuXnF>cYcuAT`}0_HBjTPqGIdpB%F-D@sC^7PE zxSbX_JwWjkZ|oa(#2r5mpnQPs+Ui2ehyI;^s5kJrhwiV*B4POCIN8VtnxUNnP~rjX z?VL!U70EkC^o|gAYVF+YbX|>%wZLd=u7es2Eb`t0eQlGvIqK zf4S$(xxpi6zTX%+ll6biJKy9onT?_S7O^jc`4#QAK%cq()9CuA`?nK-;Z1u-@0e}e zL6%#1ddx;je}FPNw{LLtJPeBW@69{u8FAPgD_Rb*F+n6x zw2Z>N=YlTzvqbV1UF)|_%av~+P(*+r@M2#?w)EeMF7a)mbaMin&aiiN4$(c7^Ltp% z&L}?DF_4!us%MC#0ic)SArU~i(prx8-8rsZn&Z1)fKeDKkbkdXWl(_8B=_y)J%C;z z)$jS80HX(gS}3b2-Cs{~#}O4l-w^>uOIls>t4Ig~2B|68$dyw!vHXqS3NZRaYoWZt zLi^&%XMWd@Y;EjjPH#46T*u2mJo2jnZ#EF}?0R&wLHn)5V znkj9z3DyApUvS5f$o%5>8~Rza9QqQY)65*O5!wD98dfNNLn^xBqP6_pha;18H>1irH~YO6WPNJ97ta~QQ!QeH94Ro zEBn0yiJLc^`}P}QY}LMpk^-+H{`4uFtW{0wk}*c1T!O4C?Cv;H@+f!rHV!tkd_X7a zn|YLEtFgf5Bmnynlw@l>;cN~A1S9io=lB);qukwI1e+-xYLU2^_Cx!K%;#ARD>HJ( z-h$}-j`6KG$}sWfApJIZ*Q@Gt!0f9*D%XDw(97zqHtN`D*;XWXPUsz?p0Jqi6Y&7b zsYqX|r~8`T-z)#Ze1#iq@-G0C!?Z2)aW0d84xs#x(U#FC(snjqwAj7p5fe@-6BU47 zy1&CaT{k`hhHRvK@oy7)M+1Vz^#7F;ddF;U%Q3kZFOmcRJDmgbd-h@(WqyhT0F-u) zlNBq=sjQvAPUZtk_xoMuKJrsj4p13FVX($SD$6PG{fSgQ^A7S2&fobk+TJN3k(8u~ zw3q_ z+RSyq_~(#|`KIi#KcK>m7YVX{1kM(qZ>hxey4SYDJ^Kb zS!~117nRSGZv;^282*R4Qm?19rF5{T$u58?c%xydLXf&v#Y#6Ac5P7Wn4H&CY>)Jr z7u&YmXp0b}UPs{pD38i(HVVz}7 zntJixboK0A8R|rJ9OK!Oy99MOz%%{+?cG+D;^ZIo!0xs3H)*Lu32^X43OcwN`91Vp zTL^v+)v4cda0h$$!SQ#T_@Esb`t?a{*VH!W7*VkjiudoNI_aq*PUc77JX3-=xo#Nb z{f9x`TaAuKa?7auZd3Q~U#9Ni#Dja^Rggesd{ zu^Qx|wtue}YWq&b$RgNe4xod{D$G2SuEEP{e5m!_|m{6M%$2jmU=^ z5&7^Nh=^^O2QLN?x%ea^r*_3}9@&qGz83fCFCZfR!M}{WB9OK?kS@@3B<25Ox3N2~ z<>2?+4}QPZ)Lfg5UEp_&v=%Sm{oJvLTG*xHwQoif&ig zTVRAik1k#}E(z7a7XgyKadxrv5 zq_PE6I$tNuVefGMkd|+(B2LI-zn`YRtE)&Tf%e0*Z@cKXUx>tbU&i?MJ^HPb{>~2j z0i^9JRyZdAoLbG)Tclr_&R>*e+d0bLNlf!SS1K zSG!PdxH}1?8Z5e zDwgLphZ0~1KQK=oOrAFux>h6<&RV*MMZr7>pbVt|X+RJ>Uw^wA;#{WF?cjDM@s}>pCiEQEiab40mYq%RgszC+~3dVKmLJ^Q*qK_6l=9DQ8POJs_ zT5Qnno>O}8VSr#eXWU)VzK8yiu(1UEo^v`Uxu*Lbv8vLyWY}!uhDhKFQ3PXGNE@Mb_WX@ zohzpF#u?g+Z|NPex-C3iOCEYHQSLU^X+M=EowZ~LB5Tzi_I3)SO4r%jrVYB@+t5@+ zynAhO*SA4^s8g6)b3dhRS5^`4YgRe(?Ew8&SVg>RgsE@O({E3S#LHQxzU`&otRnI5 z1@_I)>_vt?u)7D_XTEO`^G-y*s7ip2@+k8tJtu|$By;XlZw}Nw&-UoDA?$QfUATv{ z2dG}+)XnVW@+Wx%) z+P+f(ZS55e2&8kRKpM3EWsS>i@;S`2Hyynz5%GEu8ESjHqVXQY@?&{DRa0*(I8f%% z6WF0$+k=%s&Jh^;v`8NIAQHL($Tv+IyvgxlKLUx;_57!Sbh9^81bO5xkzAnqVj&{X z+F#M=LIf;8<^tI1cUqtF_R=1#(7q__7p@fvh2OiNibUQ3%|uy8PvA@~p4MA{NIRDq zIJdHj3>8+9&QTYxmtaoZlNI7jEX01@v3QFS3c z?8hM4kmzoii+tSzNG+=ndmpr3fYaCxlGP%*>nvzh{WkEmXP9wtKh}&mxXn#dzRkP< zGNn0P58HT9hVpSziKu`blu}NI1$* zRPUlPF4E?3yrE+cIe_H5A=vb_D&lRbA|pj2sYCqHx{2ytblr0TNb6Qsk@cP`(t;Ah z-Ah2)fJCxk2?P^2H;x@#CaT{PMDjjLI{IePli|IKLAucb^1;nt8>>gD;qN8^8Hxw# zeVnS%c1eh~+c zQe`djK{`m4pGUr`n?Z`k4b^SG8xIOSdpFz!!G}6)Nqf{D#+!Rs+4ES*FE{ot`xa0s z9vV80y=yz?_iW?%0Numd&Ap56S&{w9Hm)C9_p2M^rq6)<6#zS*Bm}%)L*(K6MRkzN z4EHYtN##U$Ngu4L{7>-FG3h>7TX3Y)1^z!;Q@hX9!O)pXWIeU|dXVTIre^@5`xw)2 zM5?=FvVE-X$5?4t0A-=WqFYY@5&|d>{g=q{2GaQ+N1zNP0D)2nQl2Zv-~L%yk>RfZ zDdrycH{{!s3=(evS#Loq#Z?c5+hW)=>2JF4FuUU4kngOcE7#OHSl-^pt)M_LEMYNs zlX?f`J^!`Syr*t%^C|bY*%Z7o|^d2CixUX(pa&9s0X}?xlTVU7zYx zouqn%)5UyuCUmK84wOak`BfVzKLN1cVguy>l}CkDY6bZJxM?rQb5gs{+zNir12A-k zuJx>m>Rq%=En@H2YLE*-?~kk0$h(Ae&&ok?)CrDo!G|qxP#JmhIjpdpDpnx${5x#M zt~LG`EB$#8G~S=h(P*6qevFlGS%DPm)w@dc<-2N9_&{xn5b*vOsX_tBjmbc=5s(Nj z0U7+o_rWUXe}b?0LtXL~4R$)woKsZyG3bz`-ArX$0#b*IKt8b#*t^khwHfn&8)s_o zV7u19gR&lG(l7;?^h-Bv1O?#tyh6|5fWrCdAW=9NozkM{lr~K#+GdjK8#W-_sSq5l z2Kj`E_j;=lw-?JZ->?{C=BG@rg-5NR+!0eZ1V+7~r0IJ13!vN@Q}6F)z3#;6dXEU8 zEQ+c3C$nCIZMt5b0Lry7^*g4=l!;oBd{9V3C{V z`+`ZG@x6obeP(!gyycD67b)){?a*^r>1KJRjrV;h9Q&TbO0yNn-*w$V<=0RVl1T!y zk6jX%zlV#wnJKB~@4Z_ctM{nmUtOhM-1u2_;*q;lz1qTT=akm5|@V{fJc*r)X4A|(GM!O)NYIjnbt=o$x+j9}!lTG(51bnP!5 zX7Bk}!$TBDz}_&@D*KFc2Z{q3As{T?4uMnxqPt`OR#nb7V)CPZ4+2O9aUfTMHB8&k z^Ug4~YIIIR*vWWk);9;At|ezN$9%j8qvU-t)fE}cTRp3u!%9CkWPa8bP$}KIO_@*U z_h*g|48{Zb;90EDJwV<0rREUM)aX8-ZJoFD^#nM??9EB`^b)!ca1gL2%^Ta!iA3Ew zubJvYNpN{{g&XSalPYmdE0Adc~_smMpWrOOm(}497DHTZ$YcN-UeSN+tA;x zzhC<-iwoPlzBv*X)^Y^-MjVDuynsMTY;0Ugzm*hgfNki-|bp#8p64Upuk;>f0 z#-;o+w95G$_~`k9o(+o&20Kf@|HqPs{xeP_oZ1s_tQprGpge87-7CL}onut@Yocp? zEl9N}iZ|AP6uGxpqw5{f{JY5p3YE3p*f~bmh4|pKyd7R^$lDBT?1>Rs(oOrY0qOs? zA$RHb|M;{aGrkFi4tVlWLszEjaD{+YwfqfygZG1UU|iqvM9xieZ2TDQqpcd02Vv$| zkDFsPJTg7j@6EBk5L5SCX5IWR8GFh%b-jbmtNV*a+r8CroPPhzN>J)z+OCVVZH8bm z_&q(?`BFwqoi%11*fb4Gu?fr4n7a3xb-N#i;H%jAQuO$Dm~Bc;T(wbM&LX;<$B~cf zFp+w6jlPPVOJA@VI-~dvL)W2gqxWd%e8h6O^x*oXq5Gh$vG7i}dLNY2-^F)9d73%S z+Rqx}@ZU$PoK@fp-8IEuxh2rgdyHo>*nIOM%6=OZO7b^|7 z{R{GLbD7-a2D#hRwIX`fP##EiNOaeYz^eKZShO||q*K_b*;srz$af;YXB`JD)^fw? z`lWT{iM#6t;J7~rqzz^+;)4UQ>eUkP9iG&sbrv}OUso|7-(IW?E%}6UZbP<#yEKs3 zU&UDWQ2s0X#PV)*-Ta&7rnw-mx{9%GrTn+(6OXlH-Dl>@P4husd=+EmQ~taD6Z6E5 zb-m?sQ!U7OS231_@}KJy$??&352qXSN&>l9c1CPuhxn=ma%l;u?a9uu8Z+O`jCX<- zM9#Ofzad5SyHuNLPfh?bG@%E*g?G9K59wtQ8&Ja`eM-MXhjgjT@a>tpgX0BYx!!1B zL&=~taE5-$Y?)E^HTIUa1!Ss=M{F2RUNp}TFjF@_SO?153FG|UazO7r!rqJ#Sk8eG z#2=+=Zw&$|Wajr~Z_}oZ1eqPn?5E3W^iwsVJL(1Gqw_uGFygc5JT&ZFn$MYbvH@7-oNv6v z7wI?Q;>@$w9Nrj*H*xlT8z{vSx`Y0|BiSg+w@>4+KO@Tam0{p88dnsC-!3;`Y|(W` z#NIP(zQ_NM4`+^lF~KPWK<_`+H{JUbAnn;b(dYuTj{BiN2%Y-xkW% zQMRh$*~Py4da?<+rQPk3p|2+!&Z=L1dz9zce%7qcclFD$kz(S`l&Gz=0I17TxXFLV4s&PGx<=QzB{R zEOHjJm1c(r##`QKxCW&E?lRs8r|0pZYoPZ*1a{iK#s%db1ooOJo5cfTrmdv}g5G#4 zgHRYsrfs!*iX(5{qA-=I-A)$6>aPDC^0m$Z2?UTEI3WI8*91 z?Oar*p9SbmFn=?CIHybWy95y29uIx=Tg11cewpzmXvF^iCj`Md@Ox}jC!^)HG35Y3 z7x+CG!2S?GkdCpv5ZvdmQ~M@oVSac&7*JFHI{}W}f7l^cSp1&69^-Dvj6rwTXCj|y z2Z_Sd6%X!{*h%-GaDS5NZ<2;q)mMS9CJCefKy~~=y2l$kkHmytq#Oo5(5zMo<%^Tj;nVcBGR;{HR z`G&(f<74`p;`$48|26r#HxYu3dp%4p8{$Q^?G|IrvwOHA zqYw2K1IJ5Ed{tBa;3>YcS)4lMkHuYB+4K~U!O7*jj!ahXI+e@^LdlonD|(F_jt51I zgW&m?buo2E9mALNyRgz9H@p7rvP|px?_xoV*7sjefMaz74!QjEphk4^?QG2?YLq`Y z06Uc@v+ZrGk&)vi_O0%V8_l?SGoM5CS-qq289Zyu8Gnt){B>Pa=5Xd-Qi6Q>7^Id( z<~_n{;~pW}_B>$&r6GA*kMs-EGQ2>TmXS>+Jz*E>JJz|X zR9Y``?^lOxM3RnU#+@If=SSW9 z{p=a6-c__hT`O@C?;^BKG7IfNeD;|5 zY~cErl}_zxRu@~xRe9|EY)y2I)3qck2?feg)=|3u zs<%Pfk_}sS(tWLRpz?Gz2a^7q%F{)3?Joy8;Tfzz90YkR5{C#fzXeplKp3erYgeY3>$K$LSurTOd3_ zvK5P@7W08SIfEWG3G8i8QYwG3xu5G_c90YM)+O1~zsHI0>sse7U5B!7TF;5ZRdAci z_#MraOXa!E`KYUcPnN8k5w-S-ia+|z5UL9`H? zBB44|KNxwJqxo{+N7z0auU=6$pi5=L4L`z4_iVDk^gW}p;Xr~B9~Y4iR0c=<(3-~e zV|CYGBPS-#8>6z~&dne*`yS=VMU`r?Jg>PFUFx@c&zX;qW3#{-_by@Cji3$-fBe>qH-|o4;@x*7B=^_0Ok2 zKCEs3I$n3wk(6mzYp)Jg?X=!ObxEoZG?-`C`aQ@u5C@Wt<)akBHUQ#J1Zh1I-KVfk z>oR?gtOCeZ0G3<9Z!>Hr5nCr8^Lr2?F&09YwlQKX1dZzFEyx-c1(0YN2&V1jQRExu zL8`TY9KueQ06?lD=lQ=OABxJWMf>w7fOIDk-C=Bp%97(T~4wzyB}dvx(w! z)y>oR+;esK{N*Qrwdr4k)kS5@e100%JFX5^`4hle`7gryI?<2SZC*AF>*uZx)~|d5 zSndBhUXRu7$(n|B_0_?8D}(iA^+Oww+2Ug(avf|&ED~L3nP8EZV!tP+$M1PL0Y>k~ z#qu08-Yjnms2|So(HBW0<^$dYARkgWMB)8>rMk3r-qLTS7_cs3@3rQzxWC;T5U=ZQ zmD#Q0jQksooj~%U&iUQ(<{tA!WIp*1RPbXIT zxrhzHutO=Gm$yUxm##a8u+v51qcS-*X7fWvFC%925AW+8wC=3FwfR*l&8{ z`@U5q{A!R@&NvrQTos$R>4}NO>@n-me)vqI4x?>a)O_UG=i@WyGi14RK1YZ?TJpt( z)AKR=^Ttijht=6&)Y*qYQs;lyL*Y1b@VT!G2>NKBO0r1!G?2HMG>e|gY;=y6L9@|0 zQXZjm+WVL8{rq*J+JyM<5O3K1N=9H+WeF@=%Nw$4)V#z04Dx%DQEK3QENFkSfc!2_ z)w(!a_#qC+?`b=C((aN0I8O1rgA?6pufeJv7LY3!fUkCv>TuU-O~@K3wZL(zXRfh; zREPW?9wi1UOW^b=w{(oMe$W3tjTJEt%D&lIOJ=j{ zDU?Q*+3k8%CmA$t$ftnnDZD1g_09Irfog4aE{*uP3$nAhCjmzJss+rh7s<^UyRI$= z!#93_6%kzuL)o}Ks;pToQ&_%#56J(k>yCr}{P?!EFZ|%6ZEaz=vaL;HwzdUVw6*>F zY_R25sdkjf_LPV`up;|M%Ei4;8*7K^kC)2DOj9n}15T95@}kji+t_-wGr8zRR4y8^ zyBR--$VEGoi?MK1KEL;$dIuj@#q!I|rkgX_&WjAs=MV&E$c2v~JKC)x*|t@5*8ubi z7|Ohws8%BI)h75oM=gHO!)ROX<>I`f@pHe4pKcRBkvQ)L(^i}5EnZ4x!_~_Fk0Tcn z|9KhPT!W~dGh<9BzIg07>J*H;04%4>W9jlRcCfq?=Q|irvb+FJ>&PJ%x7gztrsBp6hLn=<6ErtaNwTJ_ViR|Eg7-WwJeft91v?&l6=JQz4N*6_J`&Ji~55jg|gl2-5GgZNoi?@cAG&a)RvjAVSai-oh&4U4Teq zVU>ES4dg9*L2iD{Dz95^lkZs#^5=#@KAQr4kvQmcHy|~Hfg}OgpX(CrEY<7JFA#k@Fcq;4RpAE)R$kWrzDYIM|Ot3S}6v z@u3uvG_ORYnZ?9!t?=GM@nPH_r4zkF%rowg7p1?WUdmUIA!on%mRWMC?79|GDoGhT{qXh~Zi6K(qhQY&a{ zt$kX9v^5v)LzGKSB%I%8Ury%C%$a1MyubJTE6L={K5Os2_S$Q&{axQx(E9;5E#mwR z7v#BVfl(V^jsOYZP!QLgd2Q+0Z?IuBhUi^?W}@mDGWn>V z{__wQ^yS5lRfLXJvN=D;O^qn?UNTE?*>{7tn+MOvy(^{9-Cr4Q*VtFTAL4?-l-PYw z+1u+ree~_;Sw3)%Gvht4R$SBg@VyW=-DJ)2r}^BqXz#nZ$-RQ%owcI9vDW~t4V6}L zD8oLog@KMC&KUWKD~LS72-1t9(DPBRzjj?mJFT@3Z$wueuJZFuZ&J;S8Icul)hG9KOXy33gAdOBD zq%~X~=3wmO3L-xXalxq{$cOsKJ^R4~44Dq?OE-kieziJ0vSwv?^qv*r^Y>pL9^3N8 zu*`9BIh+EG}%3FeuxXUu@m3p4yJaG+sZR}*xx%Q%eL!3l0*0I;eu%Gev0jd z(pNsRB}DiH?|%Ez;%GyACXb`d(@h*lJ8FQ|>TcVlakSizKgLw07j9jCZY` z@KCKl&(FEhh4kvE3ChAIID~9Xy9QUnwmn?1FGs`9bc1NVxe5E%$j0zGpW7+k-dOf% zMffylj8rh-DruTozCy*ng#CwZhv?6kIZ}IHrBt_}avTTyP<3x4aBMIqn=m7vL=1CfW)mt4%@u0XFOA8YU~ z5bLuEeqZtX6zu-5aBPW*oZrm_Ar5cxr9E75Q$3TIAGv`c_?r6|oFDnTEZe@en+sk& zlz6UE{Jky%jmc#*-n9m@_SAPPU3$9qjx%25C#|IG6xSM8;b;EILeQs!j=EyX6QRSk zS6ud7f)U(E?J8PFXbqsXYwEr(#+UBijq3p=t^x$RZqxy@^ z7-?jzR#5I0?1-<2}iMXX^mtY^Ey7lD_ zqd8E>*xy+UKKF6}E4Devr~aWkTx}$F2j^fj;IT5ec8+x`;=h zBkLv+Yct5%BY`whm*Hcb@9FAN^LNqn1cRI&P%zGLLH1Y}!L_d&yc`3beFNa#c0u+$ zp<`CRdKY+W0X%Q$eNUf~WgEUfJTH&q1)1}*r|uU*$!{k330vgb!DxOn@>#8zcPBUUpL89YkZv=v>-e_aspUC8Atr0IBACPX-N(Ni)))9dz+B2Q8}0NMZw#Ttob~~Budkw z`9XW`5W?@XbQc%&WkH#p%fn}V^lm<#S#8&Ww?_{i z)Taj|xuc&Gq!LL!R9h^#>@Nepr`@B(&6?u!|AJhw%dT;DuLQAPNBkm7yU$I0BB61> z08&GS(CI7!7uKt_JjNz}${8a(V{y()hfXItUx?7Cj8ofbnT%69vNyekmqJuwxRJt z^6dFaWf+aw-J^1-a6s;8XY+bT(0Gki?b>qyL_HnL+ehUP`W)#B^vfN76_1k7l!)&Z zcX7BbkB{;wJwVSiwjdXTj3~YvJ!1-T!DmcSe77@`50qpY11%Ku+Dv(r{7TH>GdYUA z{Y<7fT{5<)FDK8)q22V3>s(xHRvFtfySQMNQG0C7G%oAZlQBJ`@wciK6ANcfA4eUTe} z1FN@YgSY2B*;CyOtI^m*s_cjTaqWdMcN!Tp_ER|o40Om<;8Jq+o?Qr-Z+O}Q2wpAA zwlkbPa+NIGrtIQ^L;V*Y2Y&|Hpd@i{w6}CnKmFQWT(J4+HH}E0BL+BFT{%Y_LVf3~ z5l6Z;=Ux^94#wg%rQ1gWkJ-!78L#B}+iG+x|0pN@Mc<_Pi$t`Y_o z)no`#39es7-dB=N+D6|a+@7(u1JLK+(&z(f3v+Z@;@ZnrwHMdU`ip5NH+eg^zL`=S zxHYCe<=2GpyKHW+-3-GlOJe0(zCzRElgC%^I7xCVT$zS>5Yax)Kg|VCbKvv=l%3=3 z&R45ul=A@ALndLbD{LV3a<*)HI1BlUw_@MBU`SxW zQ_UFz)nk=!H%u`F)+4`_;Tt$v_7pMTY0wF-7xaQ_D`RQEwZ<9PaI2wZuOqulNFl=IcZc}N?Ui)kq{tjyjJPY6%&a-(LSsI14;!vNEoYfG*EK3N%W9_-1d!h4rVFkXSq=%G z${k9)sz)QPaPQMxu;yWnSXDQOk#8|yR{Wc4#^UTX5I?7nVm-?5stC_(nps{p&hKne z;tL1)?xiAcnK|+>^8KG-ygn8@_SKBnmj)i>4;Jacqop$^Hj>T|2jDS0p&&Pp9P)& zGD7eQG_Iv2Mr+T6VWcnZrYKgh?wqVWzV(y$&CXNqK9e?gpGS=5@c3#kjk~Xg=J14h z2p0ZLPC19CTjYX$cgE)MbcoR$9-K>Vxq5tD|8oG>i(IT}pYE7^EM5SwKv2IkCg$?& z_*4$HJ$_vn%?tY6VuWDV1=&`F=5+g<@po?>kVC!_GN(VfK<2dT9l1mK-oqvc{^Wve zL*q>IoD=ioZ<}1kDMoUi^dx;p+uJhcFl)I$dCA_EJCI$#dW3wQXUY5d^ez|wC^Myf z+l<2;2f?Q<5I%t=A5r}~PTFat?erZZ?VQ*K;(>K={A3k~&uO%kn+Cy0F32`M&5!HL z^^d*(N&D85pYXHa+v_ieCH9Zx&=dx&`?$QJt{LF*b2Q#J13akxa0VH_!yjH3M(v`r zz0&qAR2JXw$T+I|^Otl8-hM&0DK=2~KK^di%)?)#-)%ce`n4R7*Nl>Z zThBc}+FNIVV6`$P%KY_^?=GZm2|cQ@-9|V}wZ`PnECiQakZpCvmEi{ufXFk(-dwt# ze67*-1gj=rPmkOxgwfcc^`wklUlGxhbR_5N6Rjs}%zFB`l?&EXqxEDRUr&9l(e;Gd z92t{C&`tIcwEro4$)a?@6@T9Nb1N6@yI%Y5BYr=zr1{@M`-z3^`UIUjZuI^AljjZO zjzQT|mK1>t?JF&_-`iWwK#p>@!+T7VPIS%&7jLnT^ieL1H^!)b{8H{fW4)1%wRNm& zS2}=owrZ@~mZxC5H12gu$?jExV#ciYqF5sOc%vNuBCU(&0|Dw;ip7zcPQiY6Y_V{ z7+C}GlSCV#tONBL`j~~_4m#EwXxoJc6W4(Hd;L?O^A!ey4~@yT{gQmD=-9Gx8@ae& z4*90Q;&JZasg$o^HRIi%PsVwpMBdZ)LezG;jfCrE^_U#OJT%V}{X}vY(+L)15hJ*i zJTyf=OObwFqoJP+BR;Rv&j!ZgRPMTXgU{_0Z)+^S>$-5oSVg#`X$HPeA+ck#5<5Pq z#EzGZ$u^0zJCW|8_3eL3wZ5;KT<4}{k@1MvJHblE!#XC1e9y(|9iyRll~nIeKg9)w zd9ix;;ZsEK{wm8hzd_mGa`FE5#xU96@OgER>c@V$1M_Y4NB6h?{!k8~HFlN*r()00 z8oTi+5);Ax!CdIz<*HpqdHJrAOg`X<>#r@@8nc4uE8jQZz4P7katOXp`g<;}zxmXr zF`q^Id-y3X*fmSBY56$z^88a=a5L@iTGWq{{PBM5{!k9}>0t30Zc3zmPItJ3;jz8Y zlFOG)=HS^=L??ysC_0%NnKvwlKBf8gYJXw#upB~qiN+M|GwOXo*>lkIzhEHv(s{DB z(03b#ekg}(bj0uY{Gc4_n*tK- zk~>oAUttdEUzMJ`LlC3=`}CA{|0-2-me}?c*mdAt`;?6La`nC%zbC%HKybr(*@iiN z3T@-^mwqUR3JtKB*W$OaQqG#w3&qL&BJs0CS@VWteYaga>8JAdIv#>IomYR4tO=gZ zp)t+>mXYoHq|d;FSNi_`3Hl!DlVkRKdmRkq9C()cML&h(sGt8>2;vW^9UWK*E@VRu z3tgfxuRKHM zUDzh$8Y%o#5(6j!=tbwvZU9d=vc>sVi!9@F&wG*!_UWPQG&d#UpVJ*)#PGdZ`q7p~ z^yB3JQu%y}eAY-q68-2rMaEq58`1y1!9(!V&oEEWseLSXPuTVqB>3mL$$j5vc;cU< z_w2twc<{e}N)DBP&#k<3jvO5`kZ4SGfbjwYo{Hm)ckPHAGj~6bnfO`g+_BBxJ*3pqe^mNp|RcP<{6`t zZ-qwiH7(V;`+MnRa=FiNT;x-=+?9!Pe?6JpP0>10eJcKz2$DD5nzJGo7S`*Ld}inK z1~}MI37ESM_0?>#k2J*KNfPDuoz%vQ=Hoo|vtJG>!w%+FEToli#ZmX)0P zJ|z~y3KDR9pjYp6uV)2`H{fwU$TO_i#da-g));p*##&=``E5!-E7w~JU5mZ z<9)i96q=NTZ-n*g!^W4TKd3+`j`Iq|w6X;he>!SOK$=5}LVSHU2 zOOq!134sbBX{#L zd3f7Ecjb9YjnH(X;6ea5N&M*ZB%n1%+gg0Sxzz&I`8nkcTQyA(Vnl$-JcRi8?;A?Rno z>Zh?cWe#FE9hXsV%C0Q2*b3tF48b1Ex{Br+e3T_F2cP?Y0$k9y02cW(K(sTt1RJw} zj%hdGvGC`R_n`k5&X10F_mxpjB`p~k7nb2*kwr)S-Dv(G=7QSBh<_T9ZAh+lPVo3m zg3JCg<7J%VT%wVROhCFX`5Y>a)i`dx_&I+q3xWde@3V7ht*T?!;r_M-xFF0W{T=83 z`@0KN7er9XdmZIGUiRCl;iVPda?LQ5LY1?(qZ^@l6Tb#wHEOX@VU1JxS((q zj-$60HCn`C3z4Px?{cWH7#8DuWDYtXoaBAX0`TCN#JdZ`;w%uaVZge_1Y$dz*K3~* z!<$%;p0(q6kM+dxL^(Xy;yK{q47h%&kFy6QuCLXuSD=3F&mrX1#1M%;ZJl|bR_4sRq z^Ya6aiM%_>cZ!NIhwH(j^*N$>vi9v*p4Ou0mWjn_Aa+eA|4e+2JXKUf;s70!wLcv{ zf3T>rOe`)3v3;`kr(xNT6|GOh?SF5w_NUV48`H2Zw}MI!zd-bGotfz2)kuHLL=Wd9 z{V@?ebOuQMT%?C{kxm$i9$ta;(@6BND1fo{SPy3+{p5)rPDA>Mes>D4eAGVreSzT0 zMeQ4)%y*68%0ca;-xmw6%m6tr`aUPPEU10-`*niLh}uWLFBe>T)V>bNd|wn?Tma`l zmW8ULdft~7)$^t_@c36vtmn&-ELjuld3~ySUYU#a+@K!k9b}wY1G&@Iv`-fBXxU(# z(>BrknkYXoOc#p_LCl{_e~ff}jo8HE&l9ff3EMY-XD!mtD;A2y(;?|zk(UnE5zZb7 zwSd@F-&p?r7B1K}BA4YGK(udz;kB~t8K0kXa&&&q$sYfc6VK0kEm0pg+5EJmIzNmJ z&(A(twxPXK=AaYvPtrZ=+H?qhN0x1l7B0y2DftAdGZXcz;%hn~->RLp_M$!IF#r$R z-+%$n9{{X)PtVH6dA(?l`DZg1tjUBjVN^Z_SI;8(zTk8Bq0fy_)+NcU@aw|y&);k2 zfOn+)^@CK-(->omu6pkAEn+2!$4^=g%?nM-9j-FXW`Jd6V z=zk_7hz`coTVaIZdKRRU2Jj#|YBUP22*n(|vt~2K95v$HhR<#Tb&)in4>|?j4?+?bMgZ?cZe}I z6s4hamEba^6U@IUo@> zFHm;Zbz#g+L-oGgQ4uZ?XOK0?T#4`T{#%x9^?yskl}h<_9So1_xMQ6Z8E>I+`RE6r z#I0lFF>}t!Hq0%%mej7SIKgNsS z!E%lIxgex#W4XrpV~y$@KEf|lc1uOLLNykv;_82noRLFq#;7c(&&Z)dBXpdhe;=0R zP#X^&4^b>~zlLmY`w91M0>5{6G%kFU%GMtz+v0J28OdKGcC%ER8z<-Q&&Z*gw5Xg< z%Q)6C;h4SX=Ylm_oV(p1qOm$cxjEv;%n3d>l1-7z$$)EIwx+8v_Dw4u_s(B0o#NfF?k>ag9nBfji2wanJ1;k;UaBgF zujJ+G{DcQMAupFpj=xS`GXu#R{y+}-Y*8HO!dXL)+ivhr+5j;ULa+<*|P3#asaP$RMrpgM8e< zZ4mzX0T7>eR))`m&z;xqbAQ(W$F@|>5vv(9u74ldW*^B#Hl+zf#C&Ex9pN(zXOMiXFwJr7%b;~G9woVx^<-3e>G?yik1JZxVvJJ;! z>D;a9CcYw?w{k#!D6s|m0X$ccemHTh5>-BEk&c{ikRI*dwq^val3&hk8(__`^;A|;-Egt*B|xK|D(~_G`)P#EJ%xQs|c5?_Q8dYW#K`CAeD&Isa;1T2X~)qIR;@0pdJrBh~Wu{pI4v^2u*U{nun;8PAth5kHp9=O*OK`o&*T*mpGQ zbl>ysBzzFmU+ZG|KpiVc)jY`wQ2Y*`%I`20g3HK9eK)n=q26D_OBlO~6!b8_Pqs#` zom3C&|3Wx4&)?64wKz1bUlYP-IL3+gydI6XQaXUOOOg*ld)jzh>E<0=urCwGj}F4& zwDI^+^$u*i@Y(Bg(@5@Q;aup*oePVTaSV*@z;`j4F$oimN!+OOxrbCSi6sn3SH|+L zwN^K!VLhr(w~w6T%#msI-sF86$AaA0T6KPkMf`IC1pA6eJ(bg(J@Pdj;SPO|^|^m( zfYvSB(!}o>;MDiFEu%S>QzE}BAoco@|5jKC9UhLH9kg;)e}np0n0Rh5Hi0I8)>X(cZW;-9C~JV9iZSK90}t;DTM#6UPy~ z$IluA&3cfKpJ5W$H0C$i%dbthk5s2ybE=uCP7|%IsKyI-jYM-d*N(`Z=WwofUSvd; zZR&fo#c2F&v9-C|(xNrHD$}Ah0j(d)AzxnHc_ywOn|Bc2BQ5;3Qx`qYd=$q$6QSHK zY7Ux~boYVe@vF!dx4i#D^9?Lm9xL~2>;>VKMmgHkOD-K&$Q2@a%16c!Sl=E|(EF98L zgLZwa@$)lF@FV9`dAvx5v*SK1iSJzjQOq2Y!H(V^e@>2j|HRcd2E$FGvWEx3WtYHPG%9 z1Z|Z2v#wa^oTr1;3g>4-F?3GE`}rSK<{Dih?KfaV%aX!(v&s6++=3;Lju<`t+9=yrzt; zLL*vFXl>O3aIhFxB`F-4TAZamKKe|QqZF;@*Dyb+YFx8Z9ap`g z3;M)Ko=-){qUI)nnvWIHNCNu1`Fce5_;Vn)Dsb?+@O+2#l}>7V_q8 z(Y+)d3)yRk#|Yn!F~U9-4o{82YcasV>h7hY$ue_9!4eiS`<6PB)DheCuEu%j-{4jk z>G<_&atOzAtGBa>-0D0VC|Tg|@e%ASw%f<`weHwyEG5$nd$3zPQtEG=j@SWor4S;4-Fz zh;*nW4a(|Gf@IDGaVujYvhCK^$vc#}&x4M-7}<=00ZBgSI5RC_oN9BUvf*dO$TQDc z!Bh8qV0@g6Mk0?tLy-J>j1}&zH3`xUI>>fX-cDuBICf-;ytMUg9RFtpiD_!a@_kN` zFPq5cRIM4a&gb?o2eF>6Q**5YbL8v*2wuwiw9|L_GA7;!ksPQWN*|ghkl&=pZ%!Ov z?BBh(C_28>m#j6#=;62z_^gHxxI2gVfR|ch!e1arwR-5NJ0OJ7{9Mf3yzQgDj4sLC z97vp-nU^>>hv~c8CiPJg_mPL+nWP3znjrNU$ek7PS zZ9ZHh74JWOy&!SuY{d#vKbIGYIU5+s*}%_{vq2r8p9Mo42cCQeHly!OGlKYCBomAL zRBL28>vJPp3!68NTstO*&@)>(en=RVJ?LzCmg6JGWZ5=REgCd-^WKTwgU4-h&Bfc~ z>**ZUWNX^wV_G)3KQm@698+xatjq~)@>G>9&uGhXg`&IZnz9^p9M6i%LfiA3V`Mq# z7$DEQZURrs3p?G-FYR=~gDOmtWV#+GS;|kSwXxfcW#)~ zJad;g&%gacYUiR?K9fWE43L74+V?GLn~h0qvm-6RN9{Mn+2%#mHXDeaV*2~zZsq)h zq=p4nT6Fao)BINuTm9sESv)0uy$I6NXIq{h#TI=eV;}-JFNruY#c_L>q>vN;? zRE(TCQ8^XcbkAqx%yQ=+CXXYaJu(`voct{IE!sbrGWl7oCp+;hR+1e(i~aAnV$Whq zymDi)(7Cl3Iwy-;euK)=mZ3S;t&TqyCHSr-=`my7>i9ExW}O8*&4y@f*GK(U%uh&t zRx}6Wb}Vy0?)852*)6Qs9CFU@{@`e^DtvHGqZ>F%Mo<_i^@!%;pVs(fWtJi^Po{cr-a~)U4n}jfuF?vYRw5dN$Ro&SyDku|39 z*{_-30WV1fIq#l{zFhhR=TW zhVaOm>hS12E5l=3t`C1!B}j4=;k#{<}y(oD_=sS!odwws=Hg!9NQfxczIp8_V z@sT5Oc~tM{L42Rh9oj_K-dQdeuRXM$QTuDN!Sgd(kF3Q6V%@4rX-i9`RF7*YkeY0@ zEsWI1fr#wr@6sSxJ4XmVe0OEoK{4VF9su!=lH7Xey(}>cz`Ep-D2G~MQEI$>4vMA0 zxf!bomZri8!|MP%j81T&b$0^S49<-_20pj*5u%qo;QRBJyI6u3c|VQdmD;97>yqt1 zpUA0rg4SvK4w}2^v7Cy5M+o2ATe55`;R4s7&bft;pm9E91sJUtPyp#a&-X zx$AGFc#pGG58M6`tp`&15Aw`}`M-~FK_PpR{5xG@J)I?APr#tG@=XQeY|Q_iJ5+N* zRhQ(%cEuJhc>WmS zg-i#qG5}W82F?qbq#Xyg$JPjHYs%qE;Q!x}LLJ;m_qI8c?rpz5c4@d?@0QeXy(Z&0 zuD6wMD!C+F?{|-B;{=SVGX~lZ?Ab89%>P&9hlJq>2^0{Fnl}E^&_}s83N04w$nNG%A$%5w`Hzm>^=?W|F zsbeR=|Il|}>?2Fw!2?+Rd4hz-uuDhV`(anutlVMieC`33yt}!0Io<;n>zemo?0xhy zrGGqm_eA5(8xqI6Rv#VjmmcPV{VW;peio$N#TfU{yDtNV{rC)Uap$T$DqBqo=c*Eo zbCq9pu6q38_;XbvRt24{j=q^_gN#=St{zD~$j{e_^G4;?1}RH4WrMgr7tJkro0*oq z8yWxJGPK8DWKHb9Zl-a`6#BSAqmS(jc=pYN;X71)y)mJ$iT8A^Zz}v)T=>i^^o%Y% z_Bx1)uN|#HjD5sjoC7u+hG$XE04L*fn{|TgcP3v>hEZ^Rtn=ku-3_ZV(*>8e8&=z$ z;61glrJ%wIUL$KXA1vKjU}nwcW8JX2F574xqR(V!3oi8BRtI>WFWp%%FbiA_Or|+A zS8y5G4D*85VDtdXA0vHGBOo+3N}UkHzFsS2N&B}fX#%KXh-5a~i-onAzggN+kj|!KeR(0< zV*WTrUz!VEb%6KY(w2gcW`XNPsxKA|eZk*d*o<`{Ylh%@s~c9o$Yh(nr7Z<(oZ!8R z%{1q{2CIh`Hsik+uo?J&IYol&9S*_u z(N*9=vVBBl%9<~@kX$>N95a&Z&2CsNJHVUyT2vPNcd6idk;yRMSK3nWdnU`AwMcNi zk)3Y-S2va4CAg4GNH!!Rk`3v2&N9JOTT0ed7L#S}U)Wq=WHQVvUW3(k2YCNA3&i@; zmI9>b)l81LhY@~a&dD@aXB*8&jKWVoS_rO>mw;>NT5t_kOs?=Sd-;UMw^h8}xs6$M2{fptTEuRmcnHR02x1o{f z`pVxc`M0|8nT1H#4dJmWtm`rL*-eF&VO-}_2cmrk4A062&wzq2uLSXiCKAhD&H=8q z%5tO*Za)X&JjUlnwiDUSRg5v-{wf`ON%tIoRoZj>{nuyRwcra`cine$ z)}8l#KI_f}ca{C%zI)1kbl;rk_^ZBIcJRJC%bvUMANgNcHTOCG{_XiUuev$w?ggu} z?z!*!ta}zL&$|1*yUSk2&)-pY;J$Tb2k-l5{ufu>k-vP^v-xSOX8%L?r7QjcUs|58 zU#0)2{!81YuUoZld*Q0rrr&knI*;W`!uFz7uzl95KF+snh$G`M7}{5`mEmy>^m+!$ z(0K5S@RO8uk?UGkJSw*?=hLt*R_drOKKs~Gq>tH`ppWMtx{UhxQmj7KHKwYM*N4Zp zd?9>hp&%)_tiOMV=;IIGh`obU{0rpIr-B9f^+U<;ZdQ)Ut&T4&Ou#p&?{4rjH!U2$ zyIHyYaRnEJ@9lynf^%r5_yRR9DkU5>@&{As$I}mK`-Ak3?3CjWpNMH;V(!RJIbI>p z%woWEjtk^C2y?`pnKwJVar2ih}? zf%>n|I>c@U*8tG+f6Z?w@moGD-2hTd?3QB_?4Pwz2=^HP={Am+-2veFl(R>+(b{l6 zNj?bq>Ep4~e{CYXb(q`o#%S!de-jr36O`dt?VZujKiI?tyE5_fr{MIQ@z4JUeSV(A zWR;w*w`4g~cwX*MY8q?tH9d*eQ$Z5GrZy5Qs892`KaJySDvRMmQQ}9l#1)ilt8W&F zCpf#amekn~_MMwpj`a_5!M@yy8kk%$k zmUH$+G(Oo$a?aXF&Y6?SHBrtPmaE$?)@Im8wCvr9bcL@c8oM9cvLYtVE+Qmco7`4H6gFgPOPQdth6H7&5w z_-;{5EsQ+O=b+S_IfHcBpsY#4-GKCaGp#v;*2fi~u5m@`9sKTHIi%zxo{h`pQ0C`v zo489tP3LDaP9Ho+O+{jD#>|oaxs~C*DXKVKRcxHDZ&>zJJj4Z`kY$@= z6BlHDCx_5?Fz?6&-xB~lrAXJgDUsPf#nS zuq8xGN=Or)*7YM$oz%G$A`=!u#$3 zXNxS}Q8|M4-uGGK5ZZf{eRtDFvhVg0yMD+<_ucawF_t)H-~G}iE_jB8gnf6=L~0G= zdL(*~rX<;Wuk4L-YMz;fo*|r?$bKsL%b0VvMd-8}fz)}_ffwnhKOGj~nlnG_iuzN! zN!xkvt&mrHRrT#vB|4M!G_s>+mpGCf3qSDi_ zBp-CFO~feIW<>QAKT}7Zc{Uw9E!$h%b7F16LC2x167xMQF*f0#qnkXl%?zFvlg}O4 z-r}w!9E2`21DmJB+nJ_{#C#TGoSkW=xHld=Ex&GduSD%Ju(=(_M~#7Yq$@c>r(X|c z10S+Kq4oY(ho5=olWNB2MrS3Exi8-{m|RlWVhe$zB`9(qwX{hBvc zgRB37?0FEKTS!c`cQX6b{UG(BV6kr<4JuV4Vj zTR-5ey`>w+ZB#Ek-z3(+q#TrETb75*GUOEAz_~NqYT+#MQRJQJ@Bp<6jj-D|Mtz*E0{4NJ0NTwoijqeAuiOo~j@GVzV*GXRU{&>GX*l=yoJ`^e%4 zlb^SYN%Cpb=PjcupJo=Loo^n0-Woh|`7!8tj6jg0V;tSP$T%nWOBNLhofU=9nTjqB zK0xi6#yNWc=^`^XK^OfhT<;*##o2SQF21e@Pm6)*qVEn6we%77W%j2O&pTfw-;3Jv zy{5>gf#(e)n{}_s-qQB`sp4(vZ!r^iG<`elg7DK0& zpWr=0@Q|T{vFjfAMEy<`s~mVBxg8il=l+d33Hv}vtj}}G(L|m>cHoH4=RW$I9WnT1 z1)Cgi2bLX?Lr8W-#}u7X-xbIBx-(S$`F@i8U)rBS?VOooj%G`=KeWAea~wwe2jrQP zCh&xB+UXwL{)D^v$`>{`UwCnYu@nxQ80f_PnnC)tXHHdk5xqZ5^}cpKm9tON-;K*> z)obLls_qZ}^8sxP^<;L+LS^Vm78la+cUQ1+aUtsOZlnIL5~I@cdzCwP4#0}$|COHP z`Lw)6kdO^2VaXo7wHP|bxj-i9)1NlbK2bb)8i2Jn7!ecf(PG5@!*O~$Tk>tB%ig`BuLNe zQ_m@B-Y`j?y`P* zOOyehMK#Vt{nnWC&@tsaG|QTJ9vWZ;sU)4q)bg6(ss~uqk|9X-8PI_-mf5Pjdr@1L zXHpq4#ymwG>dDj|FD~=)>Cnji(Om4wbO_%s#OYAGDXK$tm#9O3qB7L*lj~54L3>Qr z>9xlM*#=}6(3+nQ5Yz)$k*!eMh31bg%_k01x!c%8`{Y#Fryf4B)_4(BfvbNPG!B?S zngbAgfEA=m8Q;~4Ua%AUcUt3{EDoFg8#%P_el9o>?{Y4U&Gda}xF79ji~pm_fqYh1 znjjTgU<~=S$bU`d+ajM<@o&*HjWdN#y8%j(&zNt4GP@bPC(Yn-fzQ2Hx7|H$R6e%l z{xWg;sC?{u50#1N{OdA6ww;^W&}O3kY6`xJj*eHMNsAA1nu_yf+E70}pH8EkFVlzC z@!%<-e#zzn=-f?lE@3vBN3HIYy5DW1vSz>Elx170F|Bv*qxMlFUYE><_psVFoMW|P zT2s?O+^h#_)9svNB2HMe{0v7Kcm7^#Bdim16aHJegytoMILV)>EM1vN?(RRopa9_9xNj*OTdU&i`3`M!M{LT|1Vn?7wFia#udlyC>peQsSr+#Zb%XSo$=0c^Wdc zd3m-`e=!w(D7-g07f&QJdEE5mYnL~McVRuXf$9Hm#qi!;pM1TjeY{J_-|MDr3rRSU zWBA1~CgvBroV>{2U4Lo(Ot)+3M6TuEyDv`Fx4e(a3^NjKPBZeozMqI+@lT7|9Q@1= z$TP1Ofal1LSX{N*-@GLIoZ`Lk()F=9opJp*<@jq+!oBbc6)$OvB%i7_7UO&2ZC3Eq zzqAwI3%6uM?}d>a+3j2&E}0MFtE>sfaBEobJkJWQt(}bb1P2}*Hz*}>1BV_wB`<61 zO4j;l+yKct7r?6i?f{egyUhAnz8oEZ6`jdFOm6Rj_&wv}1qpF$e|p@WF-)F$-2xt? z-sdg@a^5bFzo*lPftQ%$?&)X@e4R-Z1D~_}vc$k&Z@7H8#Ip65hD$uqkQ|qYu_79G zhH6|Qeumx|Rxz=6h7;iuZ|RmpGDl(t7?Vii1;?~vvn9_7;Z(35_bcP6QD*?Jne^gB z+>t46&6JWgv(5+}bS6;aj_O|`Hgv^o5UD5E{pn5QnP)lhv}8Qt9?014uKw4H z#NVd;q~m!qQzy@pxme!L?{`gHGZ*)nqjh<*8E+Q{9{Xy>+fDgaHvfTeH`E~8Fz3sJ zZ$%HDnmvN_5UUe&DUZqi(XDUq$GCVVa%}?_Y||^8CApEa97Gm0aKR#4b1EL=`qUpu z&7i73l6PSY5`9-C2cC!a2vRO%>#b#VB6^QJp8sNt1nW7>2UD{r7KdBVpx|($GTht1 z1vl*hsr|z8UEvE=yN+h?fu0Owp#DDz4!3SEsTWDOgA#GL)m@1^4@lm!<8la%rJ#cj zKg}2DQ`L=XN+WzkCpf$F+i#INxO*nZwHT@=+*Vo`=ZR_^)ngtho47Ep*3qZ5))9+y zZ|tOQa2!9x6pg-FJw!*^Su3s|8DGOazMW24wqb4@)Q?g57zne+^K#DCaltMr?{U~Kjlhuz}K=W(H`Jb5B+HC!FoHodE2;;>84xQ%gkwUr_rqa)AWVs_*J+yo3 zqxZkbIBt$=aP2Hg%n54cD=S2QhJA$Sc&rXQ{p#h%SElMOAE=}Il7_7{j>-qMIH^~p z#q9qF6;A4H9O0yn$wSOYEe}!aY@TRi6VK*VugW2?5S$+~RgelX&M(pK=6;Q=sU9{L z=f!bm@ZkC^oIMg@1=sVme*KZUjktcjUx)lw!Y^cD%z>R_m2c0_wgg^c1lRkFX}o^@ zi#oyel3sAV%49TrJa=Egs|;-5bvySqWbefF>xVcCu3tYdn-8pK1lK;s)UZ|$o_d|& zdR{NM)-dLV6FTrjOd#4zNnL#=3p|_V-00fJ!tg`IH@dbKTU=cx;o*M6zJl6078lar zr+!WKHy1h{1n4LMpWDxZE152L)Nw(dbz)s^0d-B-q`G{NXBd&U*hiiKuwuK?f$T~y zwkz+|a=|_wl)cL44RvMG+FO5Sylc_#`e-f1zKq!QTAKl$c2(}+D{so7zI2!{XK!mA z7wk((}QF0e-hbx5`R{o21`n^`G8eN z*392)x!^>0`RcmFn%eQT>;^$yQ#+QwE5POkklZT_aEz~)jy~Ts z$KraZ*y0+IWt-=}%MU^_pV2 zdW*BQeZIo~nxGFUoL?$xliOmPzp{Ex!udsQi;qfjYxTxCy9Rr{Ce%z|HAMvS3XM=a( zg6t{R!EqMXZ|5UCli!QlUe1C?sY`F?reYuB;k_#fcc8*YCy{!tzbEsZz#Z5v%eJYU zDX^IZ3AMpokUhwL68nmL$Y|Zc(REJ0xwx+$um_Z@YFx~qf?nX zdfy8fLg&g-5Cd~SRItNO0%ZNTZhiUhjhTTi#{SL?rRWT3iVSe($Rfr%w3Y?WLI7(7 zwe!biB1e92t$w0HT)7A^Rv{wE2dh86N?hpzaUNsp{T=w+Tc^TsL+Q@F9>yF%?OY5d z>Fv8G!Zun}m?SI3Hd=A~&ad#aVQixnpOZg-Pi&rrR?N)*D>>B9K?IFq;DrNM<5=hM zLa|Mf55ljn68UtYv#1nA(-k1@1jxF#uC{!qF+Jd8?C&^BkzZqsoZw6m)E>t7(s9Ch zMo(0TMRc5S-1FnB#3C1nC1C753O=`eDh%_bEqexqZss(sl?VT0vM{HcbUldNoBsjN@Z@#o;I>O_1qm- zCoY5J4$sP<_p2LKV|XSB|Nq^|^O5kJu2jXhHzwvI;q~!~4%@?%Ch!z8UCWA&cP$0R zw~RUNTZ-%VWC)!l=(|ReYtWrW?*!gZVF_=_(u^~j75OwU$vD5qp~}7cI+af!v!9=; zZX&sNCv`+V#|dEs$!9zPBY6D2uBv;Kf}i-$yC%%TKQ&pr8$XjmygQyB{+VCOA>QKa zL~GZP`D_;Y8OeM$i$C+Nx98QhA6`+{ez=G+2L#pniob78nv0jhdTYNcIZp%5!YUehA*kFLxhRSqNsh?|VC-vZWvVsep zVa*o%$n!d%`^qA4DLEPuR*>d3*~=SPp;O@+o|g`tT4&fF{X!cH!q*5coM%pX&Qj5} z*YBjdrd{Lgl-8M*H^kc_@=TRJ_ROm28a}%sdqMZTGS$9^{lOI0vi^DKX8=U&tXlFqnfJ*OPyg@m3;v)6ltv8S0{U zMn>g6fB_HifbZdySXw(9eZGbTk1r+zJ zY_$PSRX62ej_?+RBYZxDqzjFoWK;Nq+XE7&gAI)>$+G~H)*`CR5jKwYmfC?chIrcz_?`olOn~i7;-jItTz^;&6@t%A)=V7l4LysX zevfn8DEv33|8x8|o9;*+AH_Ip4gMQ-d=x)JbFr#8ZT_27^z35eqf-xGKL36Z9Rr~- zbv^~(iA(eE3+TK0rcaC&LUY~*DqT?OYkyAY8^Y7N%!CzFK$rdevDH=M6x0I`_p(LUkZ0L?Y2 z>CcIYxg4u5y$-MUSvlZ|SQ5FdjI*P%^`vE`EZdK%Y(9-V1w1Y*mn6u>XT;c|gVpyg z!Ln7QgQq1UIq#PL6TyXi3xRUo6&Yjmzv{T;cN{yYoC3}N$_B8ia|#ByT)tS+ZEG(rmegC5JeGv-GrdbDj3wb`HZB>DB{_7d#ge}DGo>yB z6Fz@G8y>xf3y-Wx3!nX}E{tnLRDo!vc$j@`9>$pYS;1vL!r;9+s0Zyxrsf2mF6h&nhp{!$$e3&v5q0S^z7I z$_L?mMYR4O8b1TB|91*takTy)`rL*;Z-w=S@z1ZV;eu^r@}l}Vm0`aL#El0Cw#~tq zddtSDc4Yuq@2*kR(3=e%{TG(+8n{rk%aq9n_)KG)PMx*9huOy#p=uQ*si%8A26&ROBYOb|s z*he0`RR}BdauUE(gU0vtg7NV^xrPgZ8OqQc`?Ba9Pi4GC=yyGc_}+sB3E32k7rcwq zHC1B_*Zxutb!EUfXY{56AlgRdW9LjDHcIlr{LCUzsgKxi04W{7Dy`vypV2w<*`Q;E zynNS6xoTH^CLgGco3p75NSlj=a0SO>y>@VP&MfrzKNFoTF%X%~$g+)Rrs6(tV+gkO z1UD7;_eX2EV3!HX`nde@&u#^ud;c0PScpHL5}E%?IVA8z2PCQk`#&Q(P(Zn;D?i)% z_6dpTfE(#KDQzYd#+y zy{9UC{{H3Ru`QKhrIyDiXLpu>&&>f?KL+Ah*w;XERyHYww zIk$O@dV36#pK=i^HE5N3dq$4LeR%^&{fy7;6mM%RyY0I0V#YpF(ln!dMY=U-X_Ngh z&*We8xo(1QD-maqzA#sayk*A7?~zW7bAem&xF6}3L(15mjpGbb6>>*$8#J|lPrxxB~?D!fDZg6#3=;P@8- ztoVI&zd&QPhjPLrdC-25Luw8?(cgVEwpc;;3-tUuto<70`98(A&R72*u2F1;=NAN@ zUYG|Rd3jKV=0R)xx2z#GJGI8Yf!fE9R5-krr-eqO(+XeH;%@ul>f8b)zId#<(t+)y zf;$#zEk;tmGdHr2wGA;Wcv|r1xe;6=moW~#2BbzVdJa8<#;6Ivx`#Ce&T)B>O?Z9V zhJ2ae8A0EftEy}2pNs8nG2?STemfWJqF72~%Wy5b*<{QW4EC|#QXDA2p<2xKOmOB8 z$a2VMfey5m(B8xw61nTILi%daSVyW_&eh;^D|MU~udbkVD`%E3xh1xiGqDA8MSsT3 zk?Ya9el84`Fg~|&p?|NRH3saAZK(Ek2p7`$H9vrBBb7eOg2%yF14ssBv#J@Nn_zEj z7<ROHZ|8zFlf?Ubwd4J+7#X{-jE(oBwOd5$ajRqg z|Mk--Z~HjzY#WH}lz(NsR?63+{tm|w99owoAB4km$9}r8!ZQzh$?H)Q8?k^3ezm`ZwT3_SgOo@UAeR`OA$UA4<8m>7l+d+WQ}*b!w5X zylL-BNejbUaXS}8XZ^`AylVXJAZLs$TAi@pU_Wq0x_zW}ju0L+1MXYRh)n86KgxI+ z^gBJH)YE-sC9>JwjJL=H9&}baQ5E%5KGZ?5LzZp!M;Y&a4m|#h=>Pf-%b~V26W3$m zZ|8z-{3N()P6Jo{D1_(G91nA^9IE+5?ojG6_YFsD95)Tic>O5*Jd*1dhvm@!$J@Kd zM^&Bs!_V3)lk7c{%STU6Z5p+h|;u?w- z1&Vehb`tr}s&dOVRJg0;`IuUn#zgB<NYo&#jwjO zcU_xZz9oh%hwXAJ#ftB$w5~-8y*(4rOR?P}^dg)4?q>5mLMx$}(0dmH-Bq*4+iCuC z_@eRnQp6s|!Z)IS7RH?UP-J0=C><_;be20T2eon^BFn-KdjGBNnU+F7op}9FDH$8b zz}RvPwEppj*G8+nhqWl-^0ZoF(|U2|CHA0S!JR(W{ZNge5FY3or%r%fj5Wh9 z{TSL#ht~{Gq+DjraM!i388)bN_9b5Znqf^Ce_hNq!}YP&3|p9}Gga!E;Q@N$HA8t% zdyF;1+=QrmEz~u`N8&HPX4sO&ia}y;u5ho%%@2;<`!l9*jEma8n04v>i&uUAZ~Onz zI^-4D=F^KVvkn<+FIMzAWOy%@R@sXcZJV!U9rE2p|GIU^+aA2Obx8lB%iKM9`7;mK z6yxWI+sBVf{{NDPrD1uP$cK&9S4aD>;l7%V-B-Wz^P;PcV|_$gxCHd-nh`t9@9f^IGDy9!XC&u<6N_3a;A(F4&huHJL z#AgMR*jD3xh{&@7N^C2|hbW1^gb$H?^*)6Afr_z<~N)Sf8Shj;{C+J}ht z?@Qji#2D)e`2O$%6Q4P6C3bIEbIDj!a-Q_~kyukF54CWXHS4(5U;O_UYl@1(AZ%Zm zYSxw;$BGBzAWybWSHR2b9~gVb6%`#bZ_%XjF$j{z@N!4Fyyr(7T9tU|yBlSiuHfD^ z@&1Y9h0DHKI*h+}jgIo)W-ED4Bmm!fb1QeUqJ=xS_RV_h+BZk;T^pH`xK5pu$cZs0 zu_^Xg`0)MLHYefv!?lgCcHe((}`qKLH=9@3OzI5-lYn#U$ zzW?&)Nop^Do@9M_(X7j!C;8U4OW2#d2w8q>g8u*hiRW~b^M!^{SHb+hc7A{2F~UTAj2t7BUE{ge%B|O?^Kk#DO^VieS(niq_d)dx zDADt<-V^pAKB!+K8e80qsh|74$k1@}6n-*=hwh1({L zp976PU)Viqti6`O}#9I!E{YzZ1rfbw=dvpOmj0&3O58UWI)9o}V}dojeYX zvEScLMa3Ie_xo?2V88$Pd(+2`1)GEzwkEr1q<>0B86h$zyqY<7~gX$YcpG*Za)IPi?l6= zwH00m@)>@}De}_@4w-L)f&BpdCQ;gv(~#hP7&*B_9((#yVQ#EGQSNJ$d9>KFs=0bu zovz~98Dq`t-~{I=b4^iaQ^I%JWyPK!mFd1xoz(u{=;X;t)t^a^Y4Z=qviZTZF*g5j z*yc}5Q*3^8JHN(hLh$GNu85v@RC@aK#_sWJT&3D58h@+gS;Z)8Db}@XM(n#xt9no6+wz)9##ODUJY6{& zOMl|KAdRv;YSBd6BV|n`7#FrjM&Tco;kzJ>S9KR8Upe+p#c}HkvCh~>?*#~-u?J;M zWt}8t5<8RZzs&gd8g0y19QHVAm`i+YqLT+zoySea7mqnVW zZ>~W%apmZpMlt6aW1Ww~vHQysYJ&b!8{J=y_0MCCN#E=m--psqur}HVd0%0W$ECU8 zu7Mf?dlcuyd-|HETiK z&BL(Ezo9f5!pCq!1yQFrKW_fA6 z&5&i5885RH0G_i%W@*^n6@$lJBRozY!{bZY0foou*TiF_;>N~}=kY{#pl1TV8AsTG zNFI;9_fw%UjOjT2|Am6-AJ$3j(kiNV`1yGMP*sBe-2Jrw%sq^McolMY(XhTBgBw1D z#|f6-UJP!_V&slIUodGB+x^u&;5X8&*slYzZ&mZ{eXCa9-nVMi?R~3WxV=U02gBnq z<(^hLo3)u|LmeWrI*IKLZejg}Xi_aHW8TjH$TA~s2+8+-uwsUMzA!Dc|9n$`jOn&7 z#GbE}^DXk79JAFsIr2F99MNuK|BmAff#k{Mb%6$!$lit1N71ZjyBqEAL^j!(0);p&pQ!Xh;OZt>t#jq%mVN) zbJ#=hiatA0B=1q5WIZPDzb^BiyT8;wRCT9+`1w2h(kezE_7Lortcx9!E!Mj5%Wo9-9z_W>l^>5Iy zo_wE^xIiqPv_Q=KnbiK7BxOnmKt3lf<5nV{ky#(EuP_@1806##-{v}7y@YSU1bGbR zR^ryC2@(eJ*u8`ga{Q0ChJP-#cOr$ZbCQ%9=6invD~{YDgp~1@ayC?nT}Ei$sM1VN zK=aA}l-f_-i#@psaGGwu-Ax0CdOPtacB1h(I{9((AC-sVdM#=Gcf3xCA zJ<+{mm=;c8voIaN0~mJG;B4!Yz)$SP!xSqXn+EP_;N;G1Mt)+S`<{GZ#6|=wp<9;S z>lE1y-X_PtlJ`LnJquN7lQ}i4#Mb8CIByWfJdH^HA zB3#x9oF+^MC---3wvJ$uJ{FT|s>7=XFovI51UxCb51WNj1bM+i<^3^&TZ!_!nb?s` zMW0E&Fn;~FjLIs>bMc-#M$RyQkH{a*ilptNkCe|~11Ryy^sHz{u-lBNkQ|%scDB0= zoSc>PyBaW9WEr)50Ue60cQd_32a)pPB>Rgig}`+2<%&76I_&eXKK| z!_WWP|BVjBSa-Xh#c|ei7+aNjJ4)%ZX;z#b2l=F3`?SCh#j_%k{j^C!=eWDM;0-^E{=h%@E%JcOjk>I-UxAFqQ3Y0lJ{(J8XBM2I>$4{QcnM z5{d0gD3WwTB3mwkxw7nNpe~yMK3L4!=7E#T2Pc<%A*Emev2n$$&7J`H2Kp9IJwdKk8mVR|~_fgfq_@F;FUNy@y^I#$Lh zb(F@9*3pMY%k7CMHzY}!9|PnM;S6g6fU$+N?+#-BmEUmyMuLGIoZLA)$x6~*K~PZh z#+{a@GJyF01|lo=V(8uupw z)yrSsgFSumvGwwo_h64RZd5M`zG1y&;}yMpTGdOEM&#|c6r}d4_d*g`I)ROH-x%2^ z5_t;7fhxw!(*TTn72@&IEwHlBUG&c z{*NQP$rLK@!Jd6_VculO{bo4ru6wYjS_63ufbn1iW-K0ySrL(EnSbf>eU1wM(nG}0 zk=u7GbU%HCZ4Bd*MEZ|-r5rLw8nHv9FUeQ>myYPSqYm(w;Bq(^%_sC|jF3Ga*@}{YuSsP^`y6Cz)xz#V zlpe~~Dg8KUGwBbj0E|pRL?1CM@z2dEvMtXqvN4%#H<4>PjTMFWyz{0Hloe z7Y8WD6^A@oe~+*)$8q|oO(im)Ut}|(EbFakign6na1+1KnNT!T0ZxvTL(2F!dGV-3Ju z@=PPhC+%wq+qZ8LM%wjfNy==(P!~+-$g09n*PqalMR2UiM>eC%<4C`PjGOG`Y&R3( zUl17xVxyJhsVP_bM&k1mnl5GME<8^3Xkt5ewesQoUTpc;uNjpO1}pN>iO0&vv>5UM zy0N@Dfiq-V6rawDpJL-UTeJ_%AN_0bie+!2?;stE55Y!*2sR+cYk@cg8{7A=r!Nlj zh~7r}@x*pS-^-MNh$?UhlMy9(3~xs&&}~`*a@{G{d}n z=Ai|mMbos4c}OGn<7{i8=CMJi4){J@X91hIr=T;jw17?8SJ0VMT>#043#yYR73@pS zEyzxpRp3mq7xbk(QNZeh1)ci70%TZUu-LGpV820Mkdr#8pgA?W;8<#IK~dVQf=y{q z07kZ8vC&zu-)Jw$NrzuGr_;YWmflcMl))Bk$|x;BnfDef&U~O?e`ZTT&ZMq_=1D^Z z$0qG5D4M*lVAJHD0?2xxzyfTWm34Av(4KSx@Y;tKh~=7wUD}5@ATv9^HPP*)6c5UwF;f5zf_+&rT#BJQ=jjVpNqb1S7q%!`T5wX zUn$Rw^4xqXQ_cSa1)EbUeH!I?{}*8_7s=0yzX;R&fc%WU2-ADN{JiP&1oe5D(*Doy zRG%A_`a?fepIN2;P`G{nuGAk&cw2e?H>LiQDe7~zQvb;&HUE#5`cH<-w=4Dc-=jWP zDedpSUw!_OQh%^YeSS!(KlqaR{5_@q;CA)-5vBgmB=xymssFRETzp@t|FbavOO^Wn z@q6{TOlki=s`4#y^FAz0Y8V{R8+4znH`b)(ZB<1u&^+?~UirNx$=;@AJGnxnmFHiS z^6pghCT`w`C$Ys^mGs15v>p~FRSy!Mwl!|vht?!^kn~Sg8W=c6@=^Pakg>iNx;WiK z3&bTzD=6PA9URp^McMl6l}KzO!0sB&-MgxiV1Ur@2moKh+^y&auKMWW zJ$wB$1E&d{H2}LW-m_n};f%BI2(if|-+gysk9WZ*mF!?BS;fS-i;TfOaK5q z1E=-BSz>zvU~V?_$#(lR1|j=GRgVGmuGtq-dbUeaUi5xHV;n2y%CT%T@_cIZROluB z27oiQ0>ERAgStlnc;~~=`^hF{t~I=8>ArPi?}@)uS@WXGdPgnmyX(f5xo?w{N&4Lh z={z>R?3}2ww@1-Ab0Rupl$9J+)~jk+Sy6PpvPr=`{1=7)9u08X`$h;Ja3+}K%|T0I6Pu5ur>=#{AQ@1o8Ij0!$zU1Lbh&PtNt$x69wo2AMAG`$70~)i zmDZ1cIx(%Z<mR z##%C_PiNrtTW`#CXE1R3BWk9*A)d7j0i93d>*v_x!KTogA$(SjJ)$IKniHT75b*6l z7m)Jul=7@(eEC#7bdztwG`v$T$A8Ns-}EJPWW^d6WQ)>axG_ogiHly^p#P#%YVRcP zK8=&#ZCbZMA5`A0hyVSS`|q7nJL!uO{|uhU_HHRx?&K%9<^6PQ8O>`p=>OO$wM%~j zPxM-69ymGq4%G`CbhxbCa_j*L@}7!kZBIwEr%i3oZqVn;?>c9?-Riq>YmsWZXaHlF z7I{BWU#fd|r_|mjue*JFKeWSKAvVAy$rlxr4Zi=95X*u>dqv)zt-;LP= z9D}C)q<&+b`=tn)!tYjhO6|M;1Rfe#TPZ+6_^fe$r<8fQ7}-;RwaL04$BL~|QJ@1u z{cWhl+k{bQb0Y9H6f2T~vv8l~+9i-A4=q*JpUM(^mszNw)oC5w? zY;;*EXIqG(50xYO5b+P>`}DMAObGQB>})%i0Aj!N<=}(q8@y)qj%QkI3P=-FCH%%=8W3hjDr+8v!4rOs->;vgafljIOE9@1JjJ z>+pU=(XOACV^1HI?h5aPTUCxdH56;JW24Iw2L(){xiU!6t{Mt#W&q8?JUCCBt76Mso#viru3bcjxS8|Ec*&P!UK><&A=8E9if%vgJBmDZl%CB6k z@T-HOLoHGK%FJu^lJR?(SK)mD8R;9m1dFNV*kh+yTNgk<%X8++KT$@PodO&A=BaoP z$#V*TF;nJ6rf}|SsXbiA5C$O&jINz!*wd(DySzhc4^r%|r;dX^98b3jgKeVwgGu_w zh+sGI+7zA3`VY!7PYGGT+QRth#HO|?4E41d=(Ql1S9e`ez>L_zXV7Y|6=fW%LXen1Fdee58ZZ9_0OOfB z*j=N3AI77AU`l1U-Y-++x`#5l%J5jZo)jV1o4;1%`t1?9&Xo7d{J%2n$;KJ3aJh@h zu;)1$-%Mfpi0qnN&tFn@CthbD>CelUkMAGl7?rXeLe?NaLB?=V;N^I5AAJz&5C)#e zaT0*B|FDRY<>9vG3k3|a1;D#Mp~vlLhV9Qv25; zYR|>&u4lC%@9!Wod<>^siR`T?RqR6xKtbvA=1O84h%fP6Jc!bgTjyPgto4Cn8$}(6 z(Y8?=VH*jiXH?xTBeqesiwtV@mR<*`g$T*EQ7hZVQC*%EAJ%24kJjZ}O3~$5wvp(v z7Qk4eew&}Z!FvY5TP>7g3&VCWtgpX1C$$rQwo%o^qSvK%8ne5e3F9X3IaP3*rQ+5z zoRClKD8b?AlDYFD?Vu>*G-?N5f!I1J$6W^`uh9{^LdFCA00p@e6y(yZm<{{p+qEE8 zQ_lIsr?vhk>nH7@hl>IfTJ6n|#|&xX;y{;t3dXsAVEr8r!T|BJNt=~;sfyj9jW910 zjINEP*h6q=xdYthjWBSK0={Dx47A91Kec!#C9%680o;$D8|@niPUKr_DfZAha6k1Y zr9Y6UuziZ9hiSrn0G`YFNx77>jo7K6^w}VT(4j&^g*MZ`w^FRll?v|FT2}lD#|vL$ zjT}3l=*C$bCp4hdUZP(j#zMbzVz3aH&}RuCwjkh3A;Wd>ymCI3Zf^B58g`dC9R|9< z$z|oWdP}7h0Xx9%m7jnoO9O89>lJ}-pOf0Z!65wixfKD$H!-RDHAT3q6nlONu)A89 z?t1v#iU9FVKD!fpf>gT8hG{tly&X?+F?fm#m^4=olj)lJ^@_lEO0nl?YS^w#61rZK z+H0tES1D$9Sn2*On?gC;h|FD( zJ{xSo=n(NqN)qICNZXQBa1(twi{piJSR;@7h^&b?P8h;ixF5B86&)n_((+!!QZTw& zC%|?}UaPl7S`lc8gSVVtuL%6@tkixUgK*o|D+1jzrdevgXcE4@6MK57$u2XRB;WZ$ zWBO1THn~nxCRa9-?kZw3T-4bWfiLdFo{kX=GllzKliFJ_yX!esPcOALMPzWdB(>9@ zOzh7o>%AcNOE=t!Jq^T%jb}whDhik})XzmN-i;Kv3QJ(;8*#uB`&;+}7@!gGxn@Z1 z!)AeQG*=#70sf;}5PK-Fk@3Z?DeNvb0o<>hmDvLrY&r9Jud$9lOX&{d1*8zD|QKAbe!I|42c%xfSYI415=^8lq8pC>twrKq>)t6JB-vW^Sm60zNp6 zwb_Z?O<~0ouS)HN#^}9=&GKA<(Hho^;pa>IUr%Gj5q+2jZXJM!{Qm)f=h-{3hm=cX zJzVyCuPXCqb*rRyX_XSw{c97!N7av23ObWAqQG8C;r}bQg8OJO?0iI) zL2#QTWv?mmS%@6;Tt6xYQWN+k9f(1!$iW|z*nw=fMPwoyIlZLLqVx@3!v8cdx^5zRB1)%eO_CcZC)ac<*cil$^kR01_>1<3VdzgA zl~~xvh=2W!if55Be?x3cGYvad(y)Wrkeu%>5Q~4fK)k`Lv>}LD8}SWkb^e6pndFt) z$$J?`9VZ~sWy7moXOP0q~n)fqx zJsRK(*Py!6B;X6DLtW1#;4S;WkPAdl!3Ln*@y}$x%K86?e9zQAoB+Iq?#Vj&`!-IS zM&4;_b6=!Q_9Wn~zjAZB<1cXULT9~YKNv{Ak(kw?*E$3rDX)CEI#9YvXR3W^CAYe9 zNdq&Vs`M<8OSXA4sjt>ysI-%`MYRe&_d-KiqrE}Cm*k0vcHd4_*1WWmD||Jjj&?An z)qI}DYCChdMO&@VD3LPt$rZ)~6%N>SFl0JeTP4d|rWc!{7jU#e%`~|L7<;8o9 z!i$zg_6F;GsNNkb&wT7X9F z@fSE(B<^w0Nb1Smq&2lR)--74x|2+#T%{cm^(HFymLeIik$Op;J-9>9ELz-9s_4d; zw3AeazG9KRf#6Td(E&6P{mQ_-_xR}HI|4}##z*R4QabcnNIDe4jIeIFDDWk|S$Kj;cCA4vF2fz{o+@Mr zt!ZB8)va`S6D8@bC5Smxk>%vdhl@AJdYsUqzqxVAo=%kPT1z>(bv4WOq|hIDC6pX` zP|jC((@ zfLl-h-fO0kLs*pflocsT`pv*^H{jk6n27YDi1eF)-;Qwa2Zo6BuOrfL1b(|njs5;y zMEXqNxA#+Hzdsw1ZUugOFV*|OzB;>A-KVi>m)rMEW$~w=arH{~{uND)8GEM%Dj$ zM0yVJ+ig+bha%Fmf!}V4qVHrxx*7QGIZ@^JN2Fg5{B|a){9r`-b%eiYZ26x>q)!2U z`!O{3`+r2Fn}FZGAN78a6OsP+i1aMNzo_y*jYyvi{B}PYOaF<8^htz&QQserNY4a* zyF2RpV-e{Yz;ADk`o1qBJstS%i=*g28j)@UetTI|`~Mb^o<{f=RsLTi(o+e4qQ3u2 zM7n|KZxsE1j!4%N{zaAlr-<|v;I|LJ*z!M#NKYpE31iFuI3hiX=x5aTe~d^^1b%yW zRQg8|={mwc7)#%W5$Rf@pHcPyAtIe2{EPZN5Rpy;zr8W4{v#3T2}D1m%I}Rxk0<&W z_5I<9bPeHeRQ3Bu$%M+MTaH+ZVkBi?uP+7y~TSnVYN5Oq4Pa*o7@XWdxG-0MQ7V1UrX&yfZdVb*eO;-^7;AEGkMuy{)mhz zFS!2^uGtjeh*P)(G>o7r#7Gg)Ao*BjBy?vxEEO_4}c>Y1DV53elk)3U~@RxfU`u z87OdP02oP~!xVUOmshu0ma}c&0x&)dieEzSds&|ZU<_ijP{SxOq)N&7aBaN1T$B!% z&o{UW(cObJ;N)f^Cs&GEybq&RuLVG!TNC7coyxa;7zug+V;WE{Gti-j0r)10R%0xJ zd^VLql&cUys8l|ON(+_}?CHm5A*kLJh!7)0-#hVWfY2USY5px!hZ*3BZ~OV?_1r1* zt6UJ9tz~Ssi}<*qV=tsGoiEg{O>}Z^{!eH9ml#<|8})C!t{-p+zMPB80<&+|ndYq6 z>fJG)C?$U>4Sb!PKQ)v+hdbYs0DK*=jkEy_5=yQmv@E2cvF96! zFI62ZmArTbN&cT9`}5Z~ez!NG0Pp;+x+%1>84H2RFUE%cmt{55$=IH?QYv<_q%}HJU58GSC~QjnuOj>Eu}Ggf_w( zLg!wTD6hRPMQmdTBjN5wbLG%YO2 zRm324Jp#S{66h`e?E-mTtQ@hTu*y8tiOm=GuDX6`OsvrPz*}<^IXl_jkws*$n555# zJYug((_puD_^E)7>N~=`&$iw5zJ8(ZefF1C2ENJg| zLvL}UR$3kfgYToC5B_)R-oe{~hXyTD5G95zGd}Xt zGg`byspkfDVpD*g@sW2)&b!_+#0Xl)6dz+~_39jd@!jb7i|;0f$w%L0^0|<9%U-10 zGSl&A-xmcPSsh5bg+@A;cHd7p8YOv!HGAsm;fDg+8CugM1O@M&m*xh|uX0`g(^+4I z=-O5Ud@gcwGv%|NX>x3YiX`Csu-1AErwP|dQu`+SqoF5n0Qc`CDKq%{HjYkHzO9k( z#&&X3i2c7)nLi4@4}y~;eMhN7Q)%vn@U zjVr>Qlh`b5pwe8g02o7`75TrJ$#%be;GsQx01BEYB%hTcWs>s#3t%pJS4{y=$|LVy zK|}dxa7IP$@7&zW7rz^@Px(bXk)!^(Z|Ln!UA|juo}M>lcyXWuXVpGTcmrvN&SH~% z_wbTr;FmCjUL-st&+8$9JU`FzwW)XH0{Uh>v4x6oM0LJ@MvRpD>QD$i7MM=I# zQE5}AFobo&bw$|oB$ers>jU6P`>FtpN*P&Jf@KI#l4bqm>^JW9$Ah7?@#%*97u7Tz zq_Qe3h}IRN%-Z8L`F4tx=wIkF4gG~J;MZa&M|3i*gO-~FAJIdi zga45XsbPIPhcm2mbHJSkX@{~p;+yIC#Ak6#_TA-}>?=g{mQu$j zvJPo8*&~V$eJtycj{GM&l=H4P7tz8J#}waE$6tI&j=%Vl9VTDxY?E&*(G|y^eMeE^ zmd^`1vi2hF7CWL<-ANqL9hjjt1$D}~I?w?B)(tSAlj8uU3HM!;+KFy_6c29C!{9E( z89Fn{tbOFX#1rg@eDow|=$^)Og~EsQP-q~M59z{xvx;0jNu|5&vEm-2h3~)A3TN&q z_n*7J%s*6B>OcSEJN*|Pzr#QL`~tspK#7MCOkl+?XR_UN60Hj&y23m|iG$OR&DJ;Z zkA{w?vEp<9<1g`#hKTHZDoL4Eyu!@B7<3vby47?p}%x9n#8jXw_+;j*SEUi_Pn~r4;R2Hecy) ziA+6ie_d}_zRf4^E57(>z_2gbbQ)`|%}9S}_H*XSIW+VRAcL!lGK8{cEj({$fX~r_ zyO2r^WzXWy2WjB-BrnA_K0)bS6UNt)eb)rsBKO()oP~9sV%q8dy=AE1jE+9OLLnjN*+hq69quPCnDC?@pq^LN#Z-Yp>7jJ@Sufrl9ZVn@8qgb za!B@@9Fbw4Tgumq5NmfAj)f$o58(=$S7NV{aJPWPF^pc25#aL z^p_~{z-7Mxn}_;zFf1j280i-TlVke@)?~<|(Z9dmf?ziqek!n6tDLtjJgl!ffq;ji z>g&UCUdfo`$gtEtMLn0hSOdJBG9EIg!+ld0ogxMGYZ~uvt zBQi-NRKdVqyUKHVyoJbmvN{2H4#0C9gKz>PA+o+tak{k)DSKSWIH-n()0W>Z5CvQ{ zWI?Q0h_s<18hA23B4ZF`AHsM2!`~G9&ze~=n8pr=?^Eue(n3zG%GHkUDxLDRb(K9&hk7YFF3Bje}*&dwka6l7Iy{Q!5;dsR>atn-TCQuvs{c zwL-b0$5$H%hNa7^+scPa0*|0X;cf?G+KZ@}L`L71q)d``w<cMky%uRJY8U3Zk{!vW+9K9pe)sou<^5n- z?D)Mebw!E~R{Y*atuXi=bM*S~ieBGrNZpdUBFT3QTdlQ@_kA$e>HPpvTl6d5_dPs! zmA4k9Zb=<#3e3LYT`xCvzZa&z>(%G4_b#LiLKS*$kQ-_W9GLO0H(BrY!uh5E$x}Py zT`y$s_b#Ncz)gSG3!oFUH@xeuNOgP54NkB5KB()`0e|{4YS)g98wYnf4*O(Fc)McM{VTOBPyPp_(?Xg6ga< zx3PZRu+9{^yQ1QVL+^X!7#Q|B4*TwP9QN&Z7m7V3b6t3xbSW8^PquoWtI|=$4aTWOif`TlfVwTgm&oF%;a0A#d59 z*N+?=E)FEUxMgtZaB<*^g&z-YyZ-Nk7RUR(HIDavmf_+6!JYUJ{aWBFhKmFDfRj6g z8G*>kvP5U<6T`)U5Ka`d)+AHaZ=voa)(fQHx*Nb4=I;lN!@kEIhkd=nC4s)-l0YE^ zp)w5om)LAQh0WGE$eD_krIP7CDmIUTpC!*yeao)`@b* zd%h3UeB}{&doD`+jmVi=HY3qgXi)qJLW?E6Ba1DvxQ-!OM{I5x1qGku8-*`Fqjs%D zNv=e2rf%Q3ad3y@_r5h6Fz7E92Mk($gwE+@o$Ek!tt?9g9a+mHDU;BxC%U?EPTO##>;wNGGj0D!+Cikozmb}c_&vWKWUkvclIBNF?shrt)guR!{e%6~Xj&_B za(N`J>D41O&B9pBvlu8#t~gN8aM0{&A9@+!cYN_?f&;N+GfrlMT4I;$3~ z$!bEl_HzV$6~eV!5bz~MKk$I~rZG{Peadk2n$T-%2 zQR3w?S0lsBms_){uETQq<$0^KmJojur5$QQ+EB$*;7c!52Z8`^g|ONBuzFVhP&V*Z z4H)7P7`u*cJfiDc#pSNqF<4Qww?6my2ZJ|;R&p(kX9qve|8;%R@fWzqUqroiSX<8% zFI>D7hvHre6nFPhpm=e2x8fR{;_mKNoFKui#ogVCy9Nz`oA2*F_kI7#+L_sT_UxI= zXLfg1cO;ed^14RZ%>{fF0!LoV#o}&%S3_z@z~96&(&Q$p(KeW9>H>4O@^x46Ex^J` zEsz{JH1Z(rxo?y#-8p<&un1H4jSI(2x%*Cts@JKMX$)e$i7a}P8HLJ z%H0MTg)B>xe=_6IU5+XMx;=R!9BgsAXX6FFt-mmOx?0nE`rP{bJbiOpWMcxgD(%0u zzmCBiCZZfhzdfsVQzcH^{f=+=_C>z*mSjxdkay>x#UnT5BIEsJ*YY5k5dKJr(nb5x z!)B*<1CD=QplZ+eI0tw;EYg_jy>|@rYxwr92U;JoFyvh@B9aB`&>jLT;fz=gWvDYW z+`3bQ5!STr-bvzrUZfam;vp>no{~oLb*OAOBX+L9yU%e)jsGO~S5y|tf^Q!z<0YJJ zv*oF-(L@8Kkw7}hyz}xKk}fIQzFfoH?4uSZo3UzJon=P5-#Kewo*p~0u+cO{S-Ri> zP*G;MwVs-BG_nr>``lLbFu%p7w~KJ5a5l3yJ5k9${qq#yF02*uoN3t)6MfY z9&wR3i)l+nww6vql)|jnFJ*WL-QqQ^6QJf_j^?h2@(LIpnL%c6dSzZ|!Ux6@Or!|N z<8b3a2eDQS zo@Qlt&lR-juFTiPB5Wkya@t(}F}VKy$^sTu;U3fYew=!TD@WO2g$*!G=uun<&Q4iL z#(X(5YHKq*s@^(YKF;<73OdcLMV8gXnX7RQ@YXt)Xw>>K4S;FOLLFicM%6B}NtIw9 z74sn-VIrX_=vUHL7MpKBllB{0xJFm4+3_D8A{_LWtZS=T+E-GWCe{;%#T~tJ1CM0m zP26&OmF!97(DzAFnp3HiQikkU5o7nqdPsjiv#5Cn!-<;vr_%7}uXg6G-H7GhaU*mg zUb4k?B|I-qHtcKCYf1ezr&plNl&M82Ns&GA%IAOjw%SB}M~ zO0q`_IV!{Fr8*Z%vR8q9*>Su~Z*}nXB(LoWAy}@G8H5tKe-Qp)Jppq6gfmVrPz>o- z{mWyte=rKF2+cm z?OnrJ(~c@g9ERFrT+ws0YhB3f1{slIU5N6CE_1b*#S1HUm|t{~nm?6R|3dbafc+Dx zrOIpQwcKOX9ovyd-Way%h8Ma-ip_j`RR3xB;r;j16LH;Cx*Fe2pxnMz#b_NX`pZUy zgK(s~=AXvq_aw5U3@STg4NPc$ z({bA@-!w21Q5JN5`I4`7Xs9&wZ07RpV}y|yD#hbRin_9C(23XK%kbT*s67ET|5^&q z!}6g|MErgf!fOl}q2dbL8$K^uvat*!u!j39BIE?BqyZmPMZTIGPwT}%s#*P%H9$d_V+)0sZ2KvXy0$^ zhDP?%xIuHANcS5#h!US;tx_`lG#^=+8s2pfB6!Ube@QSa;d`?lmYres5wvTZTX~W| zzfi*PBA9b(#R?I!I)%S(rtfprjP$!O1b_DWv(@~giHRl`e+sTsYEZ|d``13F5kd#R z-*7K|R}~@Vibb`X3iHv4qP)|8Xw{mVZ3|l`FDpOq4`^kk6TT-6-<9-Sk~{e2s%3@n zbKYWL2R(7W73+6Ln~?|GRl1KI7iK301~f$GjT_(1@*3s1K(TI^YYx&s2*=NcKXp_5 z({Niqhq^Ey0hjTfvV5y>DZ`A*{Ztb}!B(XnQpoDBbtF>(PiLt0pXOeQsga4&X>;+R zL>}^Uz0&5foppso={(`*1Yd^7411#%-gPL;sdnU=O6_RfD0zj%K?Gx6po1{t?Kg@t{}c@(g7LtBG*bE73on>r$nxLi zNiOnUb}Y`5Y^DLN1|Y*8B!n`v*yyYkuBC_GnRSZasg2JTl(GeL!@3~4zV8Xez0J!M zu=iw{)wMbh_sr;N(u1A&yDD#1g$%*GF+EBv(f2dDNK0W>CHF#avikA*IYdhsDy_Bo z@0U(ZcXeG*^@VD2m)6X-1=R-b_Ok5$-XY;HbvJ*gRl;AYnEHN>fbu4wpKb)d^rX_d zDTq@Ww%qEk!pBi-p%r;5b`U#s_g4@}Yl>&br!nf(7GJ9>>J*?Xf8HH{yF|(wbZVtN z=q^LFq!gM=^e+k0l2u;X zDxpHmX&h7E-PKipYkRSi0Uu5+-@st=5pHX@M{4UP34&I1l-;zuLu;+NGjt6`gwI&J z0_)c3J}^9nh0!@hEED14@*mNwId7}{wf5W9&?)ObWhJDCbCst6?9}|n=zhm<&Qt;E zXid>0CLIuowyO68Uqp?!>gQR9zLfUz&UBj!#^Dq9M-j|o_P1uZX*L-zv!u&NP>6&y zyQ{Q4m8=`oY@0BANti;G@x>dv6o3CX>>HSYvt=fTto&JoNnaHb!=nn}OG;VUM98~( z8s#`_r7`DQ4M<{Ne#SNKkN@5)GQK-X^c~sE8&NTOCg?lh!(8!bT&26*_ zdMu|`H)=&(uM_5AteX1KbSh4|1|34zw2ul|5%_qu2iS4#Ce#^RMB3@2-^-A7F^bs9 zA?vevACg+aCk97hA2yHRFs(S~&E^~KK(ox?3`)sh_$)@{6+M5BLeIAtU{(zmHT=GH z3D<}{tefiNV){(uzlP0fRj{QE+&z2cB(@ky=v_JDdh~n0#7p+p{FD^GGn-nVD24G= z=XugW z`|yLePrygzC;2OGj^Ogrm}E0+`t)d<^Ar3tWLM1j0pig-n$C+MX{O_$^5TWfs(%kq z#vTm3Dygj=GKb_=PR&4XFD0 zDeJ%#-uHipc7%0`0qI7;={y`>ZF2kjOg&&r^3{Nx+FRaPO#+Iqf`=d@B6jgz$!#O)FPm0b5xfsXMl*cq$5PkRG#}s92HME!T&mGLyBh(I>Iv zR5NeLZi#ak%s1bgwkP7hg~*ASvj*i3;RW%%y+f8`*gig-NWDkTXi4V`i&N=k`@BD0 zZ9U((Gp0UR*fmgpYeIenp!^lYig9Hy#qbobI`~6H_zLY^OtRXt!3yfO;X}oIUKN7p zUpd;%NiDf`xu-nrugX)S9(4qzl$Ew&K{9&~{#mTdY?F6ty;@+gEl?BDy1(3EgPPzH z$kZwSk6_{LK$*i@Rv%P?3!UGHc^y-kU(jRmBG7YS4z)gHa%RlxUxs2-fS%Id z;~Pc67S@ho&Ey>RZ->D>1XNqzTueV*VRtd?TzN*`h$IcfGju!f(^)k7lrgu*)y)e| zep{F!QIWZus6KL*Jzv0aU*45y5-xjulQ*_EsHp`yM>O}-{k}_VAI%QnHb<;s(%;fr z{?b~;cy0@f1D&oAoy*18YDuYgm@cFes4NlZ(9J7ptXj3ifiA;2R{81`Y_@WK-?O+e zK=>cJnw&M8@|D3I>`HA2rB`1~HZ-5m*N=$I=mT+fa@T9|R3W%3g8F%)QycDvf(G|p z?)q;Vj*D7$66QQ-ya(K?l6M#RSkCq5CZhsdopiSLL4)x@Vbjak<1PBCbgMGOStB><}qV{Q1QP^wMc_Ay2pCjvD zF#} zBE05)lKEDp05uX^^HDnqTQl5T8lpN$g+|PxG~XW*e+}GdHApNa{g*?^yicfL zkhZp5 zYq%m+`+z@a-!(EBFPLfdR^}Ty7k(0IzTgZcm?PQmOsi<>W`z6D^c+=Z=Kt&wb0f%p ziF%p5Bm6>i_mZJ4QM>n>?1v{EE`@zdwer%bwi0?X`9}eFtD?+N*9m1FB3!$;l+R5X zH}z#$#low|O-GUE&ajRnca2oU&rr(f3L zHJSplSd({a*P{A$l^8B#ge+Wq4=f^00lX2zvin&{GCheRA-Q$!u_0-vuyN1`B*Zdt zn&z%)5m#nGd={mkI^GBVSRgZqQ%b8VjLU#F|e%d$xR6bQ-d#Pn8A`Drd>~l-TS=_sj!)tyReD|5* z&C$3ga>>6j3Mwsr;uxhSbuNMjzcM4cPO3Ks0syJzI0&I{G`b*M%k2Eo9}lwgf#2P8 z&*R@Ox+8v-ClIO{lfJ9t)J&Lo-GOQ%K1@ouV;BaOg>vd7rzVtL+0gNy-*!X*Xy}{l zBQz#0v{ow^6cf6L`W4jO3QoNxe1h;mK0xES9WK^y?ie|oAVu&;ccdZzq~Be(1beA+ z_CvW^wR_^VJRu71Dt$l#a8+QUkE>`u@*KkEkw{RZIL3w#D+IjlX!VIc08(#+Wc(%7M$h}Zmv$5ih zc>2D4GGTe$$}MzdjS^if>(Hl0BzqRKl~Q>Bd}_1o?sOgV)e$3tbhI$GLHcw5hRWZ? zAcb4pmKN!na&!sS;?DVj@Q$vy)>Khbv#8d>gSXlOg@S!;?6DK(Cg{UtKFwXKVa?gh zNxt-H3~3bMgDIbLfFOQ{wNDcT3EYR2ChU*XoxYtZtu_?3vp3=~PaL+wY(D2AX6iR7 zb&Gdf>9`NdVieu4MJK!4u0gjaVRaIsq15sB>2CI|j~vY`Zivt0(uhxTFDewE@pS>I z3Z_-7MH~XY!ri%2IinGbhHjTrGh4A0QK_7Nv=`%C=7La5YawpvC{-O8*R#CV(f5F3 zkx#TIrB&;z0-w|NZ=_B>l*i{!+wE&O{4NspEXaLjXEJJw|FTkgbU3KehU)KI@rbIQ)ZfpW8H` z*$aJx)MBV4G^K8rhz?z3(I!4Vj29!bK<-yaZqDAoTEdls_~_^3oaQC4}+&wE5I{lw6x!K)PBEA$h`v! zQ~%H^UYNUD26i4=if_aZPT!9#=8?Uyg1z9#02Hj7Q{_7J>f>R5?(`cP=%`SsjzhS( zmYz&QYkc4SLQI4sT!fr&ovAkKs@R_W>EMU*P^YC&gT(HxbXWb8heE!uU0tTM%a^$m z-ZSeyXZN^=&Tn}BI-i**Uqhp08rdo{bKMYqB#G5RR%VO423H-H9A|1IGAs-3h)@12 z5dX);zeKUof8$G}m-2+>-$~`E8<_iGucCbcBq^}!({`GV3$?7o5-at~H$~79w(+0v z&n;UnaT&-!G(~Eg`ZBy3FA(`axo*bO8$C)qlP!K$4F`0^OUl?7@o!v9Ntjl_+6jb(*2>(%c+F94%|hCr6^iVg}}d5WRJ}zAiYldF3Wp- z@@Y@;L}$VF)dzXu#bN^6ru(^gMC$;Z)+i@vpUG$*d2H5b84jbzd8Q6u`FPSY~;&A(3N#(_C3$eV5 zsMi8X-jkjcG{Z4m!M`8lqDOmd!2 zIR!fsmiFQ9%-xR?_(LS*TTk7Rk%(SW56kds-lkf4WXA)y^Om;&?A9X$=$X01X4yf| zJ$arZngvW^uO?O~PJu^aQA>Qcm*$15KqzgrR{b)8gaA2Y8dsCkkrrgXF9v|~!KNS2Mvg5P_7E*uHEc};RpnC)eTBWB*uFm3!EQZu`2X0#u_>hu@za5uT)hs#pI zATQSyF@V@?ncrcvRzN-@S1{r1DcqqiD%oEvNC!JaNhG)u279&ic)iIXK6D3CIBG{0 zl&>|2iio!Hb_wi{gxQj{w7jQvH_Ap2MVrD7$I=t=v-rL`0&ILuhD%b7rJA)13ZZ)y z0HxW$1@3+Z9mFCn3=uVGI>x(fGJP=Qks`ESEg1t<_%BjXj$~ zd$kT)ltxF;E_eLBL8Tq%s|Lcvm|UDuk^li2u^EDQ(N<;zVzy`2^dFjGO1z{N33P98 zCSidwCiIo)8S18tl9y2~Qhs*~#tFBFgMr1)Z!{5p%R9%)AI&TOE=XI`kS$}bqnZXV zN1(Ko{G>)EGgPYA!T2H7))tOu?`Q{{NzS(wPsRE;>-O-gM1Jn9H$lrT6jd{&`SV!a zD{ucrbI~`8ja4$IRh#DtAk}KG&4Y_^F$kn6LbDo1)l*lkotUdhpTgA%_f3?-T(<`- zkXmk!WB#1i7|tyw86j0c@7_h`w>WGuuctVj?3crDo!j&l&F@7Mq2AJtioMNg?I6sdjyuq{W|A}(Qi_lgSMW#RADGi({NDX-@zq95 z=8h>g3yHW;zE)`jWtDJ0k?a$CHV0nxnEVlIX)=T!9`wnb=fxf%x1K zC%Vfj@vJXR@QVo90>kON2wBsYL%QkfUy%bU7d?32bjzFa)Sp_ej^Otz~C*dx;C(@cwxI@~%4MZ>tm$__`Fm?idF9Ip4;V-8)Q~hw0(680X#7(6ITf z*Zgn`1mLJ5LGceb+&q<26&TBZB>J#YMP=tg`>72QSWf4Zcib_Q^Qb4raQ3z^6XyBB zhBwoI@~dPFb;l_7o^R|SAqO3EjKc;55^-v4moDl{#(!+?EZlOe-^nE6_}r`3w#@qT zDC#V!f;pV$K$!raeg9RXeU_HZqXFW)TFrWsfdia9C8puU(e*!*Beb}RRt=plEKvVY zxK&%{8lTrtCsPjHjlcw*6*T3!f~}rMvmIWz&$9234)zyGh1|Ew+|QbW_0==ge(#B8 zJ4Y{a#Lt~{5hR44;P=9P|M7e^?IWbCW-ru<+D|hkE}RzIAHPHmM9{mz{HLzGg`2QA z5WHaay1JF zxY0lWJc)~Xc0hP;`p*$NBe>ehGt;&5(}YLaA}Rnq+KoBl!@*PZ!<0lbM%7G4m&M5R z96tRpJbc^c`?wD@+zWBxyp^t+<`=K(D_o>?F;%ZI#)67Hq_=tN*HoLKztS9IQLd8= zEY`};8h-Xb6i@FzeO%gz9P(*Eb)Igbr^&b)DGh$H;l<^nF*%h()aa3n=bLuynFuPj zYoI!;73Z6Uv{}0&D7Ii`p4fYCNRwib9i?U1lN-;-_{EENHnM$#U8e37d}aQ(`q?2K z!0&Ik8_4m7@Rd2>jlknrpkf@SiL)c&AafO-JJ&NEn~z1lR+GR~ebi-UYMHE0NWMFZ zIoCzPJneu2GG%s5FEhm=za`}Js>9gt*TxL(3GcQ%P9IR6EAC_F5q@4Uu{o!m0lMv* z4$dO*^fCLjgaN^?14fEzukNPiX%zf7`9rfto*4t6l$n5?6Ff&vJ5-Aa4ZV&nRWVVq)I7(J(&77l4h>Di*Q4mKfRi>=1<|bMA{|YU%RwL7h?}a=I=| zYgQ!HF)N-hDW>}zT77>dL9jSZD?a6yHT$xEIH+k|?Cxw$LQgSy&`;n~!?^&%m_UZ@ zPyJMh@Cj>UGuT*wvBbx!kp6QPHW1Gb3WE186#VDq^8D9Gn>OX=Aq~KfOFUrOPe4A> zNCTpkcIDu6a34{mJ_ZX7$85Qoxe1Z<&%=Uk862YHIgT4R#HTIN&_vB~HXU(d9Yg!m z9J*ok2OeqBz!MU|ws~r4T^{K)wXhP#7-o@SBAXAU=I!NGWE|44UJtob6WPX-tOZp# z8ps%8m<5SOhkILWx&Y-BF(prI#xWyGKGUCG5}d%&|yQ1P7QsvtWqRxaZ8cT`-l zpHe#}_SayRud~Ob5>d*i2j-eYO0RtT=61lE#_tIbPWWo@j_I1d`qGbI1@v@^UhH^5 ze_;^OGtH@Qy;FDpV1UX~!O{*B>)*%tAkN0-<$D`cdVd!n6(IT(`&<$GZ8Mc+n$y2b zoj+1j|Nv@i`|hiFL<%HH@3qMFf0kIn^fAJ3r(%VZ6Nhi1`M3VonKLwp)y`kh;B znEw98fJxfy;9S+{*deLzOw-1AhGlkpRu%RIHh!z;`1BvGuj5C{#gmMuI>#^*OK%P{ zOS{0#q0z|fw0*f6<`h_m_IiC8PXYUfahV-SpSW&U-ym6;O|0W@oYhG1|=bdd(2HD7X5naF}Yub=$~w+Z)n1?)xASnrYYlVZ8I0 zbcW-0H8dtOn*!bP;2DLOtEVxcwK!u}f3Ex@evZr4I-U&lJUmJiserr!AnF%-lUfJ3 z0oD}sc5#PWBraM$G(7Aq7mAptIBt@ZoKfG>1+RNE3=7>s*3QiE1VgSk9ydE=lcukVN=gDZqp2}h!;^my#CU(1yZJV zVdxdnuV+<Uze^mT_&yT-zd*j%hA{!CYIiTg(Chj6w7!v9O;595m+lZel3O-^BP`JBeSGv{@>$Qjtszfr{>n!;h&HBn>G!-DX{(+veJgOEelJt25tidUecZYxt2U6hwRg;(907R2BwK(sJ7yW$k zM%`~ZZt2|L46%ZhP~XX-GD_mXCBZx`ce)`DYOF7Tt-02Z{&K~6J?+mOf+eqVX`{wp|1rP@VL`L%(f$~uTPJ7PNdjrgi zRur5UEP8!+zMO_D2)QjJztTE&>NkFg8)8j=Jr!~+G-i@?mT$o3XGB*5kcrRIFYoC< zvv6u3xQzqh>zo!s*id z;p$!f!XfbFPVB#I`H5?Y&$(8<-I7_<$}Q2I4{pcgd@Y+wzFE!7fAoTP0_CYjF!HS$ zQ5oH*1sDn5iR<*}RPABm5b1#`;2QI&ExSQ^W63B5RRg^739j;pFUqAL>O@?{S<|!S zLWI$5AF5Yq#bavqjYTO1_v4C|CP5Yk6)SRr;(Pn%f@R%ZI}H(bn%ZoCD+KB|PCW3s zRK(wPHBD_0S|v91Xv_F+DPkqxzwYw0p`kFCEga0Pjpbr=j9B66U$i$gzPQ{}`{Q|H zj<cTiN7_4Cs`tIE0l~AS`G(kbOw4WUn>3x+~1) zs5gQqQxGO}$|PD({zSh!ufHS2w;s%>Y@3D}^a0 zx_{BCh0b_)`(3!R$^e;hwRuk)yGM0HOOG{i<48&dg2T)J*>`?+m+_#7rWckN)`NGA z_&Vc3LO5eutDLztt?ca?2nLt=Zy5-6o0Md(#%oZTA+q=7=`;OgkM-HDVn=irIy!&N zFuB*oU_6>18Z!`(wy-E&x6?0W;sg>NpfhHe<3eK@2%JAMk*xcpeD`>TQ@*8MM=Ote;vmOsa>^BGy)`n_U;!*!W|*yx^KJ^LL8~-;2x715xNg<3*?*BmR~TQg~5m#)`0CoS9;Ea>0FLdF>@r zUkXfPTch|GV65u&5_Crtiw&USsa!^A`7~V4c^Z#rt}CP4^$s3IEN_5vyF!1=N>05N z+|{1YiXdvR4i_U4DO8`VHW^OH1N{&yRFBtZ6(uBo`$IOO)L@}TErX-LU;)EWpiVZS zyh4!f*9-?cvfJ6`h0JAR^4-LOfe-IzIoQI4tEjPE3kV7dRLEtxU8ZM$el*v;pLFJC zaoVFIu%l9ox6-%nz#ZiX?vh5Al$uA!cZULgn07D0y8s=y$Yi(PR6ief&SScJivbQK7SJUxY|^3N7g5B)(5%;t`DPYh)3ghLb{oG<2*m&CK`khOolmE_Ngs>YLO9o-4dMmm%^Yt2SwSfX32b%X48 zIJ)67gs3bMc0IgEbx_^HLGtPD<|{;@7NzJy#U7w#Q?pTakq#vFcQtg?uciIoZq7;@ z(#-H@wNCNS>wKw<&FWkW356wbRjzwg^O^t4_vmTOXHiMLnFG-;W=!gXn!l>4vt5j? zNE&h=5kmCid22h=kSolJIxqlcF?hf%1_zkMphp{U$AVj7aywsVguT&Tcd)k7UiSzI zUh=zs0Jg!jvK*NyI)&OXyHfv!ktaBrb4> zMSgstr*c$Wp;&7y2YA7v4}Aj^!vO}g`0)_?xY?VBbw6(g5J+lud;TPDKkB-jn(oQ& zHV%PKs~FRZ%6uskw*U_>Veu`%n0DdiB6OX4|Npd0u)vP%ZIv6)$~*Qjv0 zZKaR=SjreiH|Ts5i!R(+4fsi%)$sPh<;L^2&k1IWo{B1DG2#NhaLsGtk53b8z~lnV z6`LJhs18myRT_uUX>o*gt3EH7Tg&>Ihn00f@&~2^nsW8Rx>r12iEX+3+t8ta{Ux)f z0KPDvbYw2@@a)vkG|F6&nf1a%Od%i*Rux+sQ<%yJ8y%lNWSND4d#Du$_}cFbc*BxHinoa`8h&&$hc#cR6@Re85fz+Y&ayHa)TfKJoLD?q1G8qGDZr(VPm zOBy(IYF;8@SX>YMk?MK!-X83S$%}c8^cVx_u!QcfUtG5DvE@4kXmQ&MTeea2?QGUQ zQ4M?(k`_Y&bodbZkxLqvbQvVBPH;DG8q_|4^N(W$Cmt{YuF@#~}{8Z41W^KuRWTOw#?s93F^Rh)cMNV%N89P40^!i|@ zl=phuw!imJEI&X=m7L!whwNo$$r<5wgFo`}!@*~rnTT>)oe1Vk){*2^_ zXnZBiHBV9&`a0RDxMVIzadh+*UE*HU@qHZL zkGTFx7woQG@rxYv8|00=CYhfR%12)$O#fo_(b@odzTTH?R1BgH&+j1WPwpU|wI6sB z&~LMwI>U3qJHz|e(|^r*7yQ|@P+@5R^$UvgfZ?bck5ZsiLdWO=KU_FYG~RS2jQU-s zc0p-C0}1^$(_iPl#Y`fWAp{QisC(%MoFBE5nYxH=Tq?U>z;APrjMCz5KCfGw?11A1 z$2p&SI$JU;4$NRv#BU?cw9?|Jxbf@ncYuGX{PiiwXtr%4;&yZQgC~S^5;|~YB5(>| z`y+CX#`b4S5w#J$0pDW+r43>NH+YmW2Hv-}hPU2vz;~;<#_pf!7fU5jR(}3@X>#{$ zD&b$iDSX>d&%5*}0@EWNBU&EW-1SGAHcrPZNj>fApJ?rCouOh8fROf{w`-C9+!f_A zHuOj=CxcJXSOr}Vn-n{*BGd$&K?5k$7Z2x=*pyT>UYENy0WqIM18c{ns4ZSSXm{-) zz66xw(HPt6W(a4oID2*rt?#N-{6g^2adzPqB8fRz#pQ{E3tHb9Ebp})ST(lPeJdD5 zs`ok3)_=Eez|HTXA2@SGFQNV_}+nYk$P3bd$WcY{nUYnlS&9M*bTr}lSI-kp;-Y((2 zCL`s`{ga#UoO`>YE_t^nNhOHA&!vmOYeGXlpUn+AEHmei)MYidk0o%91l~+-f1xh- zW9-tZ9-};Lf(06wnB9+eU3ER`YHNRSRs!&LdFHYPz`TEOU7jKTWt7&g_Ojicc607O z`&?=oyz-a(k#%{7|F20$)Vq*1U>Sy^0XJCgPk)sFc_aE_Sef@}8ifT!h^|nsrQ==f zACn*V*?Y`k=HLTbyXP1|k@!oH^HhNIHOio{nA{6o?Sv6I&C@8ls*z3gywKK{Ck|X! zZ|%8g?|44a{^XPH7tt8uHpj^%*F-9Ln7OtorrseH>u9cHDn}Jb1&IkhW0CBGEXa$e z$Q3BAx}`Qr5Uw5l(D(f_=wjW`k+Z`5viA=d%a7Nn<8jjmjBPN@S8km~{bV6*p-}9h z6j0Qj9?&HG`w)D|+aRo8bzq{L;rc9qur?Mzg`9Qow7Rmzyn#WsoC4TIcp&)wpfD1A zHXuvkBZh}h&R=oSV&p{~VYX%Jp@B5C(`Q{hj@nqB>r(0Yx&VX1_9I%n@;6!mGM_Te zEqabkdK49(iX^7a1HlG3j-ve1R&(Pb9@ zPy7nnKipE{wp`eUDd9ffnM^jy$VMAABp`&}vrN!ciMwOOzR$9zaG~pUgYsRanVhm;^yA0nIfsA{HCB@)(!t6lEm&09 z)6@Awv-wk@{~*N1$*tF&Pw2CLhyPbUit_&tZDjxdXoK$Vnesn0q4pmdf&2#|GEDE+ ze;X>BE@iIX(VpCD|39?RCc)GLFe#K5 z4hvHA4GxQ*!yIY+FGo{@mN~TGKC94;3%sl$%3HXb3>>H0)wFz#?+yCfj_vb%a%%|n z1{0GBu)~-0g-L-t-k^)<#=|9;#aq~;=FoUVTFjYykP%35!^oe|;%wZJ5$8NU?!Wvu zC>BIqQ=^T&TpiVAJQ7VDZvf!$vqUO;P()pBPDUVIaAgZVZi)@H(-QvhQ!5_94k7Dx z4y>8>HC}W=9=kE|>(FHRE}{;p(5FtOfs&xD7BgEHZqTe!*Xo^x*^& zWAtWl%(ZCkH>m7TJ@vyhXI=DD-4d)g-ZQ|^`P1n4m5*YpmzU?w2|r)Sl=j`GW2*Co z$wHpiP0>AZdC^G7s+GQ1;J!(CR`?*h-(W7s_IE?W<7}K_cDZv(?RF(P<>r9z;Au!9 z^skxYuS?2Dc4s&+6ycoonI5fSQS9Z}u^&3V6|t6s-5t<+8aoXAn`sv*loTs&A(9oF zP&%TQyLL1cyDF_+JYjd{AHHyhHQ%mj{|lsIkLYfQ(Dk(TgVZDzSBqW{mJnziuC!=V z$ju9%q2g&-eIzZUjftJ+%!)OBj1k1PrBQexb+&qmZ9N?fT?)Eb92TtKS#4~=IcimC z#CnAJE3p_kLj>+4-Mx(bb(^uOu}RHIk9vw%kbUJM9M~B;9h?-JF{~*Qtuh+B6q>Jv zfD5LA6u7Dl^_UUL(T0xRN!^V(067 zJH8qEk3USC&chPS|0Vxv(hOLm*!(_L<8?_JjNv$}w+@(Eg^||I{;&2))ZmpJCQ|z8 zO?e#s1d|&~=XQ*kS8AOlB?n!b-Ixfkwmzk=N*yW1#R3$)q#h&5HidOWWNi6^5cdYv0bRE_{>j@K`Ja z*FL*piq7+@Kq_N<-kW7J3#0wlY8l0h)x$iuLWedr%4b@8Se^wDew_L%^lrL zkj_ti`i=RKx*M=Wo=M%)a1-C3HOt>>Qh2A# zf+z}-{$+S7rLpaB$GhJlVI*x!*t7Kanc9yXEt1k#+)+Fp4-2NbMp3fj#|I_T92xJO zNaxi%!6j{Y2iH_6>K{!k&@gb%C$P`vaAve7@0**j;v!bq+l=YvkGXC-n;YpkP z=#yEqcS(Xn^<7x**Ge6zL9xe|>dvIlQ?X&K463*3@s*n}#c5Cl;wrYsYW(&`+BoY> zIQ?eJ!u{ThaUZp)xlLtv%*^pcjUNk2kbKkMx&uMQz=OE2c3ij3+I*4=jJmao)0Pr{ z7CGGPCnOhm-jgjFFz3gfUVPb88C17JneFOuVVXDuDNY{@G5Bhyy=Qau-lMq&g z-5yTep^Zp!a%@>xgTB8f-CZLX*I=n#}~Ta_OzN~9wO z*bTnBB@`-Nno1**5_|9?fWBNB{JV4YkMO5h9suKo9+f+4c|n=ih+)qje0kBwLlP@q zRIbd%9cTCf{)nhY*o$tftOlI}Uq{bN*qp7L8jpG}_O)QfRKt#J9&L+xeyaBr0-u2Urdq_gmLGQO0NFiX&5Ob$-f7;`rr5C?^ zoK08c`kgFzBMK1&`fV9JT@>&z>Bw*xuitHq&i_1!+TfT&b&G|1dNTesT42CN`LC}Z zD`&RyF1PXwOMi#L%Fk1B$rD89mGZa6ZG;|}4pFp) zvBM3-G+vdjA1C;y!Vtedwb0`=hPAMv=5iOup-HCVb32*_MPh*O!17`x=g6N7 zbrTiHk>;X|8bR}Ju9j$!w29uZr>zEvK_Bgjz+%niW1a)R&E9Scai@`XS~?&(V8jVD zF#}Y5yV#Q_T0m3KN_vxVbm^hSyMR1fv?yY)aCG@{+uQG4~XTjDF_S5!f)Bp>;se3KAP* z(qEHV^Ef!|XJN0cnc*r5(Q0i{-cP!@C|Zhy_g+(4G>QTEDhg`IF%`}5KbcHila zzm{#2uET@fh59$3Bb#z3>t=Hu_O#)~OG_OVPd_B7-?V+@9VY=k(fTmhZ4<0lo3nM`y^+p=o zStYZIZvB2`PF>g|!8X>>GjOUcSqR@)xqcm@!=~)S*LN2_Lu+B(#X%4Pl+9!N-jDMH zM8JLrEv7vlKMMiE;;2C^A-tmU34ZhvC70uUX zTa-sna~;#4aeYQUW8i@A$@+vX?aI^r3(u}&&F2l7gjWBu#;o9VC+7n;w zTMm_&7mBkUuoOTDKLp3>ec7jdlv&M$kSrNhOUAI#w52abV6J3Rv4E#UphGSC(P+gJ z_7-WAdVCHN*pP^U(FYd8Y`FBpd|Q29zU`ljdK|{SynBb$$#;re(9~apwpVurif}sv8b^iVVdQ1GemaTk4MxA05H9xQDKDe}4 z_&w7{O`V%89BQs5h(r2y>bpLX@6{>}sH&jrZ&o~3F7ix!($$IcZHE3I04YJ%zE(Fh zPXO@=uC{@G<9DX``W;++w-bTmWWev%qRfwk@w;_k$m=A;vP9YU#(VzpJ;m=9q5X#U zyBXVv`@Y!Wezy-_iR^bU`e5(dP43ogwb?GM}f~1(&y}^Lgt)JW>wg(Gn1kWe4W-uIIs}Zzs3D5@9|su2||= z7u+Z38N&C;Y(9^jDL7bmgL1B*cBY`#m)`Q~(0pD{Uz`>j+!t?nmCfhvH3av?yI&38 z7w5hbxi5ZorZT6zWoS!Dbm0qi{vXymHJB4q~7`IlE1{D=;Mffx0(xl zjWwD+j^KAo{M>%GEnnc=^cH1K86!5QoEXOMhEdz58aAhV>@;zYI5!>g9o6r)WytTQ z`xaL+TYgvlUIf3}mLb1e4T#UyK-(`aj>7MzzWeCKI=@?@Ao~)}!`w7Rfw}3P75m@9 z!E@96P3qkAOCW0P^p5`}ZhiX=FgG0+W^Ovf?{;BKU~bwPgLQ5A z`(gZUw@H1aw@SXUTcm+SrPAQinwGAut z%Ujg>W#!!++nL|(4F?SUzG6G`yM_KfH_Y#UzkSH>rd;2;o%!8Df18en=BJhSHf|sC zyD8V#Y-fJA(BH-5U>2?09?|cnJb!6B8?SCF3Nt?)!l~qK(a%qBDhi&T-iibB)4#`T ze!8KExPMhd+|NEDm*3AXj=H+l$`=odjwrN~@0|mG? za~t!!g)#zj!?{$qjrraF`^Es*rfy??x6t38M8ki-eA|%UO}WnA#{6!fzdeG2xwd56 zkl#(Yri@t-hHD2`{qvzV)R|RwJAuhnR$CS`f1LD(m zWo|oc?5}54-`o8LXwt9kxvO~;-&<>l@9lCy_Ost+L_UtMr)~F6sBO^N z?qv{u{D5#^{NO9QK^j-oeGJ>T>)an}%H z`CkYgOT77V_%(b}nj?=TUcXZFd4%^(d5v&cn2658_oBXGlK7n%H*^7zGebt5s0{jxJ%cRPn&8?7{IZLp7djbhcawX zjSYBOJ`JD7V2r|h4IY;02YnWflsf&ehsLiDKw4_Z}NzdG%w0*XZEX40V zGaVdh%PW0p>CjZG#XQIW**l+;Zp4DjM@mQCtM=^w2GV&%O{XGUoE!@{(wA5I{+0qw za}=JWdz5{IHOvp@tzoh0g7$`vho(UeWP}CV={S&!nxKm67PUi)eg{>wAJ3tAoFpi| zR*g;6t}z)v?BqZOWiNTgUaJXuUclg}z=Dl(xS0NL6l@xYcX7erLa|P}_C5W#=sOGP z??Te7j$>(_9tX1au3|Hd19>G*>K?ouqzwohwXx7yb>dn))m`>nXaTozjdd9$zlLQ-b5s9^(uX^HLnj_^Pc4Ry`43J z&5INBx-ytwu@0|p$gQj>EJ9GVbHdyQcOh_ea)M0X&ohA7#ew`^${s$!)@2FA<*P)i z8x;8=zI)kI>(Z67 z!O{0GLCP`E`iSe!#o(BWCf4T~Mz0h4E!wXt^2!o4KfAI9;V_=4n;0i9y@J{^xXoW3D-A9+N&|~{$ya8Q`by1G@BBE) zUo)H&rxJ__y(%Y8VuNQ8$9Q}gdj@oz=+`(=ilqaT6WJl0XdTXpXSW2}@7n8G``r_U z6NhpbCt7lJoX7^*#R;;v6bIWPt;0ES=jK2<52)$XhT+7s7l9*bd8O|s7eSNO?<$;V zWt@0`1G$3}Y#IwrVM|07RB(cPDweg&N>wLs#>snqWt{YZ8G3q`AnCLb zM=UrRV*^}R7#p4o`hD;k7dFNQw+;Hvb~A`poZhW}cP0;x0X)&u%%#*n#lsrPGZznQ zTo+CiAHssI_RK*(2SNU>nX~0~JTY%A;aq|drqedo9}7JlXNY5lvhP00GqH)dcb*~B zsm)U?lYP|wp|;OI&Ty`sGh>zd`(YDte@cjD2bbP`2!q3it)5r8l==pmrkd`y#Sau} z=@ysJbS-(u&v32{986C&f_RWi?WXCbtLdJ3DSWzv806Q_a4w;Qr9HcexM}&j+K zHR+hzt}>O{BmF8<7jqy_r%Y`XY+csyOg-?_Qwmd8;o*AI9}DB3F@kuTF%XwYW2*1s znNshPVu`*dai+bre$CiaUxxVZod_Jf!c=p2B?3n-N{x!CD{*@FVfwzx)pAbHR%%;i z4CSp7C-3EvslI}veOr3>Bbc_sB##4U?4>%o@MKwG(RQfX8KF(mcU-Z-nM}$KXLh;>Uw{66@@~ z%k_3&%8=c+hfCdC8^_nvI!sn$E?07?dryxOmGJ%C_h2vTl!4V)h5>liHB9%(Nb9I+`8n)!C5=H!3U{wjVJXJF@VP z#QodBk?lyIopIvVwy5mLeMiQDT*LB(o!ZDkn}yX-6(l_8Y13 zZN499zwljf(e(C&;lys$j{H>)G*$3$T;aqhcBGPy%83ha52SPKI+jjt7*0H*+L4Y3 zcH~1GD0&#MBQqkhfc7KzsVt!V2DKr3moghND%4|?Z>IN z`|e=Cc0BMRasN|iI}RQOiP~qH4f!As$F)3!vmwg{IoE;^8!|yn`|cNmY{)H|4f(CX zfc^OLi_CVVwxL0_9jWa+cvz5n6T{nwwfyI^4?}IkM~ng6kd~j?hXWYov$YX7>TJa6 zl$Wi7joLKb*6_RxvJWqbY#(a8tWNvH)X4FB>*DzOB80nv14l&yW2S__LHpRcIMd!-Q*ukI?2cJ5gUgYA4dN zQCpD@V=L0UFZd2@FIU@Epv(aqk$zjV5o!D4O{RJ?Ht(&AGuKm@P#cl9H}5z>Hlcux z*lR!$ZUOYP+vg!ubH>4C2 zH>qLq&IXqnq=7}TlCR7t^_B8c?|hT8KA)CF#-N-<(ua*6YCra4gF45+<`+&WdqUJR zm20d%Z#IZi-y&|tZpMDo9mA>0A zgr-4t?Zc{U5NH2hotIbazllTh@?|)sdnE@g&UA461i{c53{C`&LB+NSob5pMc_M~_ zKLR9O0Z#i(gfu_HL4K=hGbr=@7pZf}F>v{yWqo=tb~PlQAiY<>_j4~2WZG8^ zV#rf|lZ=>;X%|#w(ci|g-|n0c`L`eAiFx$*bHHh*ESQ6L+8V)EV45VXt%wt3)ACB+ z+Z+^Vb+r?NgMK3mAn9Xl&C3C&Jr@h|ZJ4iT?I_7}2q$|E<5W-1MS^?;Cwh)zi{}`g zm`BUji@|f75yWo-B+WH~SVYTa07o9$X?w@uE0{M)SWBNPW76e|eP&`TxHL?icVNiV z>ThTqhy{7#M3_M9Q-6Ow&Rl{JIP~)74GJ5@+Og~m8SQ)zsv}O5vS+5n`%f}`u0HKt z_Pu?CSO##4$AO^v3V@^mZ1VI1G~2?w>xvEN8K`MI3zPCJHyGwqr&_>Vbb9z3Tx;1iV7;@1UYAUh0oh> z%pdx#Oq9B!_4J-hnrT~@F+iHV^gC*uxp1J28!$NfLduvK1CFOc&o2qX$t>mEjU-R+ z{JBzJ=^V*dcC|FHXtp%CRNX&P!))Mung>5=e#&nw_-BNA>r?CP)ajAi;~tKmH|Ml5 z|06;y3*R8_zsTIMeJNA_C$gXKjeO!3z-d>`M5uu_e>IZ)C5nGkkoXcPR z2gz54q`p#4>Yb03Sh}Y$D7HEuU+mL-hW(n&o~-(16_zKfV7{m@E$c=9V_Y-g5#`+1xe;s8%@$6|{=_k79v3?@l-cioT{MR4E2K%r7 zusOW{de7KmpR%?Uv1?i$EEvRgWnC=uBObvP&rzJ@Ifkuy{y)+_IAyQ(N<&XP2ae8@ zXe;k8Syy?}lPCBUrl+NE)V(`*?QePnirK z96^SMVwnuLg~;%l(PU`Q$q-BtW%#%zLqFg12^ua#dQJbId(+Wj@>`9Z_MDC8jEV`L zO@1Y<#Qmagxcrhvkl$}-1mqVQuhwgXEz!tsPpcxkp}pI0U&UnCH@fVG_HI9WkjXBN z$!=db-_V6>eDl5-XzIs-^Wi@FUHJ3i0y0Wc81*PP?YlT|)pCL@2PG7kwoDptU4yE4 z!8$(oMQ6G-303hg)}`|=PP(BYMUlal(PR)BPxjDm;=VqN3|{(OWEsq&GALm(7+7SG zd}XmxU#U^*ozD-+L2E}cj?L5L!F>7Jp5tJdtOsbhGejq?yd_qSFh`*W3l$QotaOC4%^o8Jnwy~ndYd)xB^Bn9hE zs^>f4v`=Na(_)H&8;X`gRn7(A;4erhSTGh^jsqk`$NNBjSG}d<{lw45`+WdO9m;y{ z6xD7{Qqqb;;Cfp9Pv*qxKG?AUDSR&%IqWAm$=LzWNdnz00`morxeA%IVlMR{1(<;ejlOUj<9!Ite-&D<4NGCNJ=PJ5DP7v^l7O! zw)r_h;z6)=7}>fV-e0``o5{`w9<5ev2nV%YpL^n6?{A(vQTxf8CmO%;uM_hkr27^E zR~@w#W8ensB~X=<1P)VDLIIWWqx3s5b??r3{<#y4bN_gv@dsTe3L|`{Nz4EDplUM* zj%5HzQcRt_(d4wxeg3(7XE5(*Yv04+)S_NK-D2Ek^E5oGfM!4{Vw$nol2T`j6>n5)iv z<)ZoqD>A)+Vw5u*T6lE9)LIT&DCa3>Ls`GeKv_RW>MOlk@|De&1{SG(ZVBUkXr8|T zPJ51)=TxYQ_Y;SA&{D7<9a=sn#FB$9n0kZ|i^7JT5RnZJzDe8_W}(Fd%s*qjoUNr^ zX@-{f39%F{gr0>1#6k6X$^dcjm&5o9Gqn6KA(rA@#Qpoe;eF7A7b5pT&rKt4Iv(hc zqc%WbJfN<19XdmH11HEk0h&_)lIVDjj|Z9F6F6w%p9`Et*^jMxW9d7<&Z5-DO3Hp> zwkEHq-?Bd40FYDw%DEiM`WgEFd!QQ!0ywrID7Xk9>3#(H*%9VVv@=u*$1f2uIB1@< z{AlA=FBIk{hUAHkS@)pAg160V%vymUU;o<2xbHE^ox4jh&k$WK${<{+fmjiI0yTRll(%DliB zEc^HTq`5c3xLYqzTCaMUP@Oz-hlSB&`k%c^Y%V&4*F@P5-@}z~*tNF7xUf zPLB3Xo!l1~0`=iUOx8c)g6kt6L;ggaPB-BJeWA-F? zPGZgjiXI?OsE+$o9k=SvM4lK%-cBx1MxSMUy1uR`BT_j~+T%#_w_<(?m5+A*GA#$K zt6u`-(|l0*Cn;;Ht)9>}Pj#dN3iHij^kX9w7UWD6)^@7xz7btkK)+WTQn&3mHLrL6 zcci}363JIKQyN%QEcvV7RO(n8Z|HT5mN#`GOfX5sQV|+jqb!=nfJ|9uLi9JhCpVYP zo8E?;c0SB~er0;bfmpa971`owxj@$zGZ8psY|Tq;g&UGMXwC#kvVqf1uU!#ju|Ova z*|I*JzUv5)hgW5GB>kf@iB;30a!}GgLz;8IX{UKC!u*nU432|lsCof|Bb+RL7t$7} zEIN9Nf@D$ATaX{AZei$k6%iI^Rh54rOdNv}Yr?)ex<3WN6O@ z_X9TO{?=?|Y`3K%%(-T}Ro}?dA-)mPII?e~Jslj8&bYopV+Mx&y%FZ32ctOSI+Bjo zVt!s@uwSG_(W4n*{340Ww~?6~)c!CzCLr6;^V}oJvMGc&BgsUB`TRExGXFu7pEO?)3kCXoa7bv04U>;UIzNxTJ~Lw=U;91s6USR&=J{q-1@6eDnG-`vU80Ex72Y2KCk1#pZD@f9s#@zq)?j*;nnnEL*e&QEeS zXUB)iBAT<~BXMom+408Vd#c!e?&MK@FR8B+_hToA`$#&Uk32@HzKpmDMs5CTEcsg% z-^iNW0kSVQYpN1Mn&u_bAZ+f$AYQzR`9&x%+l{dK|1rPFu>3N=NQp!++k><49AO^%@(|xh<0Np@PGY{1Pdf$L4xH0HxV3fCo-SNBLGP`14M~?R}kU%+jPE=KdZhFO-CC|PQ|yBiFRJu zSp(w5H-PA!1}*Jz&MR{wd~Z{TKg1gcjykkWgN*Dk}!%dWZ9SK3%TV>^o8sRvqy>fLW1`dC~Hq!Bl|)oe*wM_ z$6r3XFXYTC#C_NC;eF0uo{QY)EWG6Gd?D%T*i`d{?Bs&y>gd=?nS( z2dZDhshh6^E>H&o7d+?Y0%%T9$FA?`d(B|n}XGrtS2nyoQa_kyz z&U|EYLUzt#ha9_sEO^#||@8b?f{dl(A`H z7%LB}>$IV|2BW^N(}vZx-v1%=k)gVNi4aRP`glsGk26B_aWv-6(COn%2nxoGP&bVc z+Tck3H0CQYN~cOdR{SHaNThbiVTHlSBgHuF2PeY4`f+wA2HR01*p9`4jf?{ut@C3> zupNy9TMRGA?TH{B!XU1SciN}^lXKC&nYQCoi6GLpG<1Iaj6nWR;&lzpv20He9sj*V zg3l5E|Fpe-TvW%oKmN=a*gd<83bMEengwYiV1BFM#-tn|CTd!(xQ%IYTQJ;PK~jye zy{Rz@gxH{)v>x4N8`@qmqz&gJw#Hy8N$(9vn`*diBDgJPvurxTbHfm7thl$NZiqQ&^@Ae-0}UJ(!c6KWnl9I3Mn+R z@l9dl!yN;gqw*IO3T%vL_4_{OF|c`kD|%i_!S(4HaGk6G7g^8e_2e3GeOdvo7ik}N zgM6Zt&+CQVAisH9@Y23tAfQnB!-4GWp}~UPfzyJQenW)NE+-a)ol`&)=GN9xEW7o5 zU4J_*c&QBf9zfG?A@sW6ENNu`O`n+HRfNI)eHQ00Nqzsc;HA&lK4zW9;u4I83%`Fm zoYQAu^OB)_KJ_88AO1Z-HkrWt_G!VJ25Im8WGjy?*jWnlA8rR0kFF(~_&S~ZK7exz zC{7D#^#3LG+lrhPa9I#+qQ9k*sv@YWf0X{8)kpR(g{q>o-bDje1TM&j{>wclHKvY% z&32{#WzhQ8OjAO|4&}nCWaZrQ>B<0(<+P~Z-Mz?d-Yn)F9q${jp$=oNsQ$M&9pd|( zp!v-)iob#48lxUQ#B3}(hx|`Jj)^C8f#q>)&Ja5Mvtx(sEG5kTg=D20b!6H=%fg_Q zgvXEBYL4HVA#~t8W^36wnjh-nWNvHuX)-i@YL%K7??y7&4X!{N$UWU49~NM0X9kkH z8$dp_o9Y@|$NLN?tAPekdN61o0C-^%uDPGf!yYMLFI0=p$w zIlw$6wyMaI1Ph3e96VtLw~`@ryxfgCva>+`T##J*YE~_H3&pYfIGytMk)7#fH_M%cNTzzR6M?JlwBU8dz=nJ)xQ$qwlfDqVowFnT zt|%`%&wX(Y7V7(&U4Vm<9`BUW6~$XQN9O-(G+!JOxc#$-_eXcwU8|B9aQ`G)cW`h! z-r3obMs>+M_Ku-TIwg%bK`Q}h@@MEa^U-3%VS|r;Q@OC}ekD}AO6gm3pE9u7t@OW4 z_Y58NWX}1J5CL)&CI<{xBi0{EI;N^PO z8%qCrr1Y&3lu$8NF06`C&Ml8+vNox)b{sLovCnP>?Nlmgly`rc2hE`&p9psDmVLqS zhrrGdmB*uf)y`pO_A~@dN5XuwycX`OHV>+b?jz)&-2%B6#_&~ZsUFr-&pGy_ys!JJ z4aKXEl6NlP=jv(&acP+eazcrq5i&_3kAX%i;}lXse_It&On+MxvXcHbE94%~{Kt_T zDiq{S0j8el#&Y*@EPvXD<&&jYK83OTS%V;V;Y6x~$`>01Ig|m4#ROjU=DU>uj*LNX|mi0m?(~I7i}1257-t&;mBl0)lkl zB94*E5NH7hXcjCT2;D4cfhoZ5bBkDNrt3;X*WD&!XtuES7(7finR%`1=U6r3deMA$~hR{Mz!e1z8rWCk;8@-!mC{ zTb9qsP-X%6M+akoyXN{dRpkZwQdnIGP_;-0*n%#u*PC3msE27Axwf zj`V3wL6WNv7UV?RkWywyyXs&;u4t1qans`=G3J(Be`%pBurVsWRXjAEodWaxZH2C4 zEC#EmfSU-@gIy+Ycg~fx5T2pBFa&8IvMyC}`ythd61LY_;LNT(YzaDU-SZ*a|GP;1 z9xSqZys$}u2 zmc;IuMPF2s-HY=cs()l}PI3~gj zPd`pp(-3G&kMcIMV?m>1Sd4(JgM}#7L-m1;CP-LwGHGSUyF9s ztxbj|`W@>l`ARXe1xu2^y%b5V-vHPtO}8wGq?xo>?gw2PyC4VCd6`S+#1Sk>1b1Jq zq`h_v%%k(4e+!@giOzjl2cP?r8~NNP2L*4*jc_ntU*8ntoKAAkOvix>U4aTo3-bN; z(H_U1l#OV6-S^_);OC?GW@kRQAlIVbCqD8(qz$qjfazhDII4$9uGlDB6xCfiyOBKq z1>&P}N%*_;`OPm7-<9yIw+D$MoL?Ot94Sk5#!Q@F8SA@J5Gy+WLdNu2Z;bj5#ii`M zydhk~_skKvv_{!xDGt9Uyzg`_?$gM@W0#o=j|o9?l8ObDv9RGtJh+2vBrR?W zT3L)>gD1gL7mS0ZhXtEwl1wHqQ`+_GP3uCF;~-~gEXWnH(3?(( zy9dXq4+7XJodu)jnbNj(228aem>Mi*F-#um=hYT*2j%mW|-i8wT=^)4Cqa*N6BD#l^;WkEr{Nhku{e6=%TIZ2J9`l19h) z`IO=BJHx(jwAGS0>@!|Zd6~XGZClVvilu+Kq|r4xXA4?M`B@pNty>GwMD@xq31BaK zn>0}x38YFIrGZQYuA7W`&KkyrVnW*$c{>{d4T3D99d*uF=%qX)v%0pWcO!Nmf&zqm)z=(EpllJ+C?qq<_0 z$Y}phXp)EO8T*i}{nzCWFId0!;RTJC4&)!F@6q=&k?5%u#9+O7blG97z4q3qz4pe@{Lf>q zZm*5LKVr~Lv>lJqOgXm+RqTzrQ-Gq@;QtWfF!r0*HFEGcU4MB}bLQ*Ib0|jR;nUef z+|Qv%{zmDR(k!L5EPZXVIAMi?98MouP*r5mhy{VmJ3#k3hkARD;O(3@_I^qCO8;Y0 zvojVp+`FHQn4kJlcqNsyS7OMmK*O?K;*Dd=*=hDjei<%jUyfgvWKVpK0>=y49JOYS zaxX}y)0n8e!x;BF0Pey8;>gnX4kv;Qr(e1|^ zrK&H`-|6A9RHDa_qo@qE7!S)&wEvby-LD_Ooi@r`(tgrCd!cI#_uhlYbt$mWE*=gMq>XaAr9l- z&NPi2{4*hrFXl?xC&&>@GlM%&TIiZj`O`*8%hqGpE=IL=J;LPn;w0$3R|I#a2u=Q} z(BVXrgBBCGk0yZJgGKdTBsJfd0P+p3#fRp!IuCu7#R9Vi19%dP1=dqq=n9r%Iq;aI zRUqj=F^h{!=VEfOJOnVFBDX zAjx$DA@lYO;0>LF#Qj|)HNS=8DyjyF`zGDCz+|i^$U*-lZjbSI=ex=T$fe~yk4YNs z6YbAXoL(d`3<3c2@&+)=xhf*5nbI`HSis=Eh$pMGokk2fo%cwZ{1xK!7Z$k6=zl$YpJN=CdU48*_Ix8e?8~t5c=xU_DACt7|uMpp30vx3D6iAdbs^?#v zD`}aC`+;O4XlCE*H|Nst_~~ET{(w1`wp&L3()I?-xkgT$D$ML#{0=Q1;S-)sYOM0P z<%^UHtL{=l#f3`WngXSNeZDfV`E7Ro^LH0`kzepqo$vz}u)lwGf%i{80Pj?G#|u`&daKBl{eKGxAENOFe+(r7kLeggIxE~oXGu$)i z@45VZf$CU*^WN{ocJ=pPBEH=}0Pn!&|545@N6Z#R`w2o-(YF`!{54(Ju1@&{@wJ*^ z|6vxJBT-GiVUbqw^+npR7ZTq&<_DRmzPOP1Xq&(Jl99WAveLh1iV`Z0SBCQU*I=2> zm0{lx;TZK|n0>!F+P?n~iPus=^FNIhe+{?qzjJ{27Kg`|aK^-wn?bvfC~5weVxscK zAUV*06AE0t^Y6L3okcfZk}i;P?p5-_=OK4a0hUvnuP?96|DzrzEPY0lb|VBkvWT*Y8~3soS@|hv4Atqsb5^iuJH9 zdtR6=TN=%lov7QgGq^2#`_IO(>!$KJ&djds9I|DP%-23-%PvwbtXiRjiodS(uUXFW z>X5dWaqZZdm&`dI8FuUp(B}1#gFopr=e|#f!}BWfX{Q9Qv9|yCSfq`bjwRg3>%J=( z3+;1v2Jszu47}XuTTm{gg4VYt%6Gp8*t&_%xnsFOQc^*3WownY%1Hk4N(_%KjfIYB z$WwPjs4Akeyc#>zo(`8xgo|*ygE3j$k1I z_nrcHbyhsM_dEc-Vhp%zA9t<{V36k{iRIgw1z@+KY3-HB9(+gu_ff&_u?khY<{+`1 zt|O{1mre$EHm=&$L;m?MC$a`JW5F$IRJId?R7bE(k`6e(1-*Wus%ZNB?RB)x%$YE? z+ypX}VQ#0oEP(yF$Yp^A_}Akb^Ht z%2L)>sw;8*CLe9D6OgBl;{M1lD9@B!qM7Hp`S1?nn-5^0E>!L6#M9NqKOw$84C?D_ zpGg^t#r)7`f_F1OPA5)Q|8xh>EA+S(v@(IpmeV|Yo`l|qSbidhngn2P7g9Xs$kCox zJ^XwMfPF{L=3N!}AO{4iM?_Z7=LI02##XgzTjjoIszKgY4ZS7Xc>W=}UiS!ACi7+| zNel8&QqYy+trO01F=6IG`~sJgSv3fgNoOT15Cj^yhl0yIbGuo_9Hg+q62GWHXnd{XeT^F15o zoui!ZVRpW^e=NU(z6LCZ%N@1Xk@&tSx#N}ny4<1P-B|JwW^zX;QPQ+FK^{%^a5<=c z1{$LuI^eU%~0N;b(?l!RbE^ zKQsIaPPY#~GyDopzZ=#U-LK&E@!@BNU%?lDm6}KR6_p&|( zZH(vaJmm!K(|e$q?tN5t(Z=y90AXyu({SH_X!|sMFEPx|z$_Q1^HqID6382ZOpw}=_`zp&ta#kER?hgVe0`h8?@82 z&B~HOlkA^uQUV!*oQ<{~$iiC>Q0#hM5)>vQoEePo5w;$smghv48`3_0H! z&5t1JT<-lrGBju5YjIq^f^x|5XT%Ko6^NI(U%|bL_TDm@U%~2cfx95=9P~f?`5lQN zKZEdlBV&whp+2^S7;^THcFqxIH@QOBk~0UPWaXx<7Fr z=2R9(g35})+4m@A27j@D+dr4vlwFA1l(Y3S{_S*+N!Y>c%6ZrtyhFDu2R4&5<_QvPsaiauUq*-8Kt_%r4=Fhl*UTkuwW z51J?qzeD*fO!v^WWZ1id3%TFGj*DA&mFa#1S;*=Mq~AgP6mUyOYOXT;4!$0B z9udRu8eI=yFUF1_+yL&gb6}n^N2}*de2y%Cj+~>;*~4?xcS7)X&W3}FD4i5?f0y9R zl4eElDDyEe!NIpjx$hKC%jv-FI4!FqeGRA_nYu_iMAvE{qrkNtL2f3c!35aQdN;U# z9v)*TYj~Z|caIL5a{>*El`O4t*BvZp+KeE&1Kgb%l<&?^XF*j_H=dz>if5=Nu~R*T zo$Av+qx#(p^?fuvmY$pW`QS>ly>5pIRs=I*9#`Nua-1v$K} z(^0Yxr4e>cy@sFN2UGdk_fooFf_22%eZ2|XOB49neJ+4KP*dOvu8KUnuNdX*9`x8Q z5oh-``WfhheB8k)l2(Rl>qPc#am2ZOntk{VQv-nApzon``&DC~+iw@ZUfZsp+dGHP z?N>#g+Z%Y44xif(o!Qg%S5sT(pA8z7W2h{8&meIaw90%BG74N@+$(7nXnWmv1zY=% z_4E6E0|mRkKtHN`3r!A|1Gvv(n>rQ1{?Fz5S-wNkevE!xN9VZ;f%^-~WY50yTaQ!u z{?BMq`@7{2A9|$x;X?$)SELUT_cI9~zonn&8+1cyjGyIu>XsO1`8r;dJ}4~&UjCY5 z*l|R(y)JMwzlWS@;b+w)=F9KZ;rrPwqwHtlJ~aPN``IYx__S_J)HkVoO=%_i3_m~W z48MgChr#=wyQKTj+#@yn-&mf**6296)Hf4%DEbWFpx;$dXZSVx8UF0BGkl$9EC^h0 z3=oI0Pb@wmcp-n{`-J~#ezslFL`KXLpy7BzRAzY{!NH9#F25#^W^Yc4l&fC9nz<6h z3Mpq|bLBVZv$<-WH_DlJ!Wd`yPY<8ve`kO=*qtf;EdOh-ObmmSw_XMV^R>Ys?WT#} z(T$eBm>uf|$nnpr(3{XPM%YTi44O5C)4c1Au(4sQIZIrnPlz}Ux2o{RJcr1%=L zOSF%qA)_qO&XyYuM^^kmSbAalgr96-*}$OF)tdj zrwy6{v)P=wvSLU2R%BTDT@0!dCnkVADQy3t^>&y*c5jh(8TF%mEV9Irdr$a!UZAh% zzfB!`Jy%8fQ(Vn@c4D!D%Ec4mX+wBexO`V8Y_AhHeeV$EbJde3?q6}Cj~sl55C@g9 zsf-n9(0wa5NBdT!FyD%H%D2phZ$(OQdn~w@Bu>z`qM^_gY`}7$GTOHyB^bcq4sMS2 ztw_17Z$-g4z7^TJ{mq|IFzicFDQUD1SME!ZqSAJlFU4|6`$`V+`D=7viU%d_cKW+p z_oY}PX*u+Fq3%nuQPOUszZ-O4ib_elDTn(~B!&A@;1o5&mx6w;-<(Uo!+a^abzh1? z-It<)`%?IHUkc`jh4S8SH0}$H=1Pfd)>U*sgAz zL3{;|fOlZ?n@ayE_xK4GI~v38G)DV8XbmXh?4j|2!FbI9n%|5Sei`NDef_DpFXk?_tic z-$OI=d%*dwBQd()!;O)C4;L|HD}v-Y3d4HuUIE-c1#X*HW=U*cSits$Wc^%|=ZNC_ zLb4vyh3^aR`sluptkQj0u}Ye1;(OE3o`aLr>_xDE?#+%ZkQLsiAzzD(0%eJwEAj+@ z+lr*-Vgwb{x-3YamlEPOd@D)-yq(U-y`e?t$>xdpRX9iYtGH@g{uJGo@8q`p?A>G7 zz8#WA9J=j0HHt5U-^WIVEnk$w@7VW;-LYqOd?)v-IC#mN`w1bA`3mthd_3$|v0;6b zU&WM2zY4g5e$xItn@W8DwjR9W#X_cIx`2@y?OT!Z2+s+!^it(6i@x9A9}69|P*pS^ z{k#sLpVmDHJU`(ktEAnF;nB5IL0;v|KTg;7dQz}^F?zl(ApE?}iKYep2;8E@;-UZ7 zAaK8#82WAHa_9{@p}EHfRJL@NRpuY3YfYT)oH`F}J>aha*9`#nOh{^XqA5Xv$$nEj zbbJCr?cF#@{S+q+(f36>MGaxAn&czCGC^|n;AHim*rC$?*$_;vM6jVe5jvKl=j-w| zK<{Epl85^wOjGX%u)lm^>+y$?)w2UlYcH;b-U5-AtpKo}kChJm(+pbUg{{XS0c3cV z_!_O;U(BCK`IV&kYXqe%5jxoXoZq^u3r|y%5`dk5HGM32_pF_NsHX;Ge~si?inbmI zzEm)zyV{Yb&hM0(?_v8nY@j$(jEk}Kuk*ss>o^AXU;&F~WcSeVGyjD7wyN>dQfr8`Dt?=hF+Ypx&lo-&J4M9bKll#-B4N5q<;KJkby7&!UBpL zK^2-aeI5##XbRM)cY4WO*1$Y%gC$G>dgU$6QQ;FkUHkDtAc=&F^OoZr60OP z^{@HVKd|l?O<{6>V8G*haXK^43^zTBa*{rq=)Ni)M0>Evq|Id|-kJP3JKKOlmdEh^ z!pJ~l-XMyK7>4Qsqqs5*4omzOiZFiog>Rz?ypFv)weic&AAL|Rh&XabY_SOv`cdj= zMLYl8(*^Gqed8iFTbelQjafJHevDulw2rBV!;Ruz_j%n-?=FRPy(liz^~UB7?M@_7x%}^k z@`NKsni~V4PnC-bz-*hHr>THsI-7#Wp0+M*BQHSg^F(|jZy;%hM-~kuA&vi}}t)sc#t*<6Nlp z8DB3r6{I#8^}&WF+I18EPHzHu#ifW{n&k~qmwg~Mt79^D4x%%Ds_&%j`jt=#z9HV- z4Hr$(k$l_1!DLI5LU(jI_6{ub=N&8gno+}Xg^+%NxtI}J$&q->LDu;kYrX;9B8t zfqx{;4>UW|JT}qVPUtRf)CGgys^Wc@bxBRn-;P1tP)Ae1-bi*}&Y%W%c|9c(z@ZqNFep=s&9>sFUXCZ zDj%Ny(J75>Wl7*D-%xq|n=qp-{p0*P@wX-S)xJZGAC$gFKU_o1dCQqs)WA>?zCeLC z6(AE?h@(_}^+z;4eP2N%9bq{x`I7N|%I8m2;Uis2t|l@I4Pc&dE6;H)$Kd7G7=J5o z`#*coEq_0qMLDb49ku@%xEuG@te|MxbzFMG$RQl{v!r{$yP0NNkS(S`G}fjynk|$I zk6}J=E$uo;#;%#xMXj>J+lf@C&9)Vy#KOcqr8#lx9QPQ8P*-<(O!7X;!bsP-9;phQ zHyc0a28Q&RFq_@~6nW=l<5v6Rz9m79T~Dk~O<^XTGppZ03tDLF_F8YF#f$1eiZyS3 za(=s&=c&!z6{GjZZw{_>r%>TOTqO^flLD#FoGQXz~BbZ*m06fW$^G#Z}3 z^qM24SE_B!Z9QyxRXE1q&n`&f+d}V>y5g}~@{Qc>PsG7f-l-=GN!sL%Jk4t(0#UJK zCzjKw+47$}2{xX4z2PcW)(L#p{0>7HF0*Zpef@OUuTEF5{8F$hezWFpF(M3I{Rqz> z@d5t5OW2qEGIJC6f|;)M>YFMBgdJ=aVGpAmY1OOy~}5a zCrn8}0htfq5#75GFLP)V_3+AB={1cgp+{`T$(5rqGh&Y#)6#DY45i{5Wf|IdtgoOs z;Z&{aUn(#UAHQIVHoT$HP`B0oLO1`}j5rZHBakr>rPzSfhfe0eru)-iw0l^rG0AJH zQXbTY1_1`ZrbS6~78xzL3p??+gRqgFNdeSYUhX40j4;{v7P_lB8ZxR>4wZ-~+Jf0W z>dg2qUm5mvm}VDz{Sq^!HZn%( zCFDIyi7*WA$2iTo_OaSFcJXVM>Gf2Q^f8F*Ea7x%ILT<-nXFHz-qDR68Lm-Ah23@n;?6;dIdvJRr^E!7AzUe5Bc`E z07?lSXCqc0+Me~?Q~cgP-Zuz_I8PiRRHytm0J-4Nz~QVFg~-C{U}zs6DpzrCdi#su z={*7K=)U4|s4x8cBk0?V_TlX)D)se4Wj@-3+@Vtb0D@ykqswWl; z9^>h2E;2u5L`_UE3e`EYLLb1V>*@#YPn~2ciYz~t7nW}FZ=icLw+BJTRs)boDCO z3Bz{wl$NZWsz`313r}$w;QStpUEJ$?XFh4Lj+^+{Q%lA0fKrka8%goe0>f6R6_JbO z+YHz%X@Z$EoeWRcjZo5D;DlDSLkcJ!Xz3Mi9`BWDaCZ_{%jp_ zN~^55;m?8Hfl(iRLVJ=8$ldjd-@f}O`X$o|<3n=e@hzBJbjVF1v-tkB{Dc;PCI*?7 z(76NPxwJww$Tsb~39fu`)Zw~_`&K|wBZmxv>$ZW=x5OL2#H>i?w8S}KEIHCFkkr1g zIv@}J;>8~Q<$8N-K9JsD`4Ss7wJ>QNe#rzM3u&s#)w58}m0EdB|J*~7;221`?lqU* z{{m?aqJap}>33^ot3GWEu(hCRt_qnVey(w^)ulo|om15Hk0Yd%+Mzxnv3bXv;gQGw zk4+jyTinue*3mIV@t(h?+*dTm zDy*HLH;q@a@z#BxFtTBmUCY;BWLAF3*v0S?eL<}vn8fkSkWNBs^f99XOU2ahOX~$vI@P{v5maURY}cL*f?xjT$lq;l;j@Rx0A}Hg zS~CU$(=wxPD5TBDJ@c6fS`VG+C0=B7?c}yxBvM&}vc{uURi?zhtj0j~>B?8ow_E*b zO-e)(HBNg}^y+9+QCja!C}wYEEgT`gs;D0` zkBm&v{&~HwZ=59Sm5{o{YdVGCcDkGT#JUCZm4*9vGudKKI*UJtOL=x^dX|OlE6Ui& z8y*^?ottGHY!sT&QwYFJG)j)8G$-e$>dF@Z)rd(!Ay)@G9}~hNiAfrj z30{c2aT#KBWZlFvLvnEe>W@${ulP=Yjn$Z2gCGa&;0e3?=0$Oh#0BzRsOWX~2{Imb zV#Qwu+sUJQ3M09kc0~&;fjdG$xLiE`;1+5;B&$;^|2iw8&jhZph47)7oJ>p-dkG^} z7#Cy+5-V+je)Fohj*od@#a$7c8K`C4>Hl=DhI-Z%&OxU(Q$K+~x4!fY34_!iR#xRt z8+j_lypDx@FdV#bi#@zrGIi%nAP`1^)Y3pM03A>KU9(SIdMqf0Ck4r1RD5~tXD9uU zfVXi~SIeQtQz zhnW#be_v|u=ATIm0AOF0)?i%?qf1L@u?*#U;;j%#2speZYgf+q#>xDo3}%aGvlU-^ zs5aR|gfkVGYP>6a))hdTuKn*O{d*u0QXzzWCpd-y}^~Z2v?w>^R(cN8GSmIrb@c&+I zR+p37W1Ft6IH128ev#+K=bx8|?L0t#KPl)JEm(Vn`7v-9*GT@Y{`UV5Hby+y$31-a zc*9tTbJHu#h0<-XJ2>{<=GEmJhk)p+%dhbUdhhooZ58G{55H-73>u@>EanETlA+Xm z`kRA?A<%O4;EEruMAXAbvf4hMj5B^PNGaYR``u1Z1e7yFN=4urswod+jSDmj(Shr_6*HbZxNwIUu)<6k zsPK_bgrk@mTZ$6@9U##T$A6S8%kLYm_Cv%8sx>3=S;#t=UD3sVv}*v z0bK+(5XQZRulu{AScqfszn6)ymKT3 zm;FMrbCqJ;nC8R7_XY^@+-{!OxqBumtMwy*vAMR%M4#|;nK5jTU&%=LWKPA35Qz7l z;WrNk!D7%4hMJ;sVD?fa@OgDc4m{Bi=8vt1)J4Uwx=0g|uhs<)pp9>Kj0L0yt=DLC zyJz**hc((e`#<~*C*f`N!Pz`Kc{b|)U`tLiZ{~nSf`bomNAV~!AD%~qblBl7yck%; zU)R24XXsO2poMF@kYB3#VkRqcDiVt0DijJmC@uNmT+a^L$Y)EF%0mb{qLphk9J1LW zX65PIG#*C$LR#dIRQ*vrJT_%XbnGO8QlHP#P)f=@BA>H$ zrPSFq7O_TWdnh8_Nu}z!mxhQU(cYa2&AY9NLPU`yAvWGjZ2P}e)zIw__4Urhq7%O3 z2)zSWTkCaGv08fcyG_q}^1Z>nDk;li;xtpB56Rw5$-f%%>X}}@W*G9BpVD7Esyb#x zO+O0FHH%mM9rC1yzQC>eaXGET$ih`y*ndvrv0KcjL-w$j-IlcOk4PP(cR_9|OfmQY z4$Ui%tls84nSz6MtNiI2rN!;mjyX6(_Zc1kZeF#zjlPWfL$s1zbfxhtG^BGvr60-;Z+1Wy zL23R-bugr_Fr+aUQlI|>J$E$&LE{*+R2ykTuBG<8E%C%zm z=g~3)=5;W$ga+zw2%AXi5vW~N(v3#$tUop-{mWP74DezJ? z?c&rXE4&o=G>iT8Xt^^rt5PgCSTHG-t`z98(p=ENj2Z?`N59&Xn3 zQS+`qjp@+RuujHuKc=3wvvOWS)2n3|nq$p(8=hXbv5=F_+e1eKC366??YT z%Yrv^U?RB0D#n|6-fU{0{ULzx0S%Ck+@@>^Y_Qg_i;7#3=iSN6M$|#GlxtgJsmWjjtVB(cYpLW2jA-n} zo%Asu>{>>gZ+Z2TGMrMR10koVHg2EPYb|(e*fDOBxW`mq?9*4B!D|!u^Snt>aigQA z^*k-o=VNb814-Hw4%_WV)t>YWsm*;}#XN<&OXb(Q?Hx34z>zwhv6PB9pglMjRzGV4 zZ`tE#^UA*%Y}w|JU{mEjMM5Vw8Jg}MwHdLaPM1)^K+)5UCSI9vaU~R$fn(ZUbI}0~p$ByRPY%vivXT0@ZyINcJeZ~?LQRkx#1sA8j;hTQf#2c9s z(!d2n8Q>%};)Z`}&w`{aCD4;%dAVOFs>Vr4bTbZdXyXG@Q9`;TL|uV#6It)TvjaUX zUX7G5<{PjEwF@esodXaM8_Wf_`i(gF-yK2MeYBuwKYXbmfwEhEAF?+=?wAmxSm#~h z4UlOF^m$Ta0T=RD?E*e;d13gG8f+*6ZZTv8XN!PeNTZx(_`nBx;pZo8-GE2bOZWtT zpCI(?3oz9X9Wv4CdZC;2A*WpV*R{H?a2%@b+wz)3Z9V32&z z{ipFo=)c&Ab0aDUna(JU2QZK{>U^n@1?apBmGDA?{#M0@EZA35fw2*TyEsG7Ikq=J z-vb3=7Vsfwl5u_aXQLZ1!4>Z(oxuf zkC;W=Gv8ZCjR88u{GaPZ)xX>AB%LVdlxiC1=sticA9&Y5GQfVY4*`Ou85CFBSQKb4 z*K@CVy9j+Y5d-Rb0wp^Xf%+amnz+6eSUU?)&=t5~fDDFYA+#^;;m`>(Gzbj>*NvAK zpAokpor=KV1<5*zx5lb`;1yx8Mm3T#pEQCTGQhZ(^DjVm1nLMzg`j)K(C6ooOEiLs zprUQqc>;8z6St!P(>naZKW7`Za!NR;lP^$UwHb-u6RKTig99tEEF;LMk#LS`w z7XF@Eca>!ef&G{x&q-4d_>V#0KVWwe`WvxY0`^T#Rcn5~96>oF`|hE?Sb(MOKpjJ5 zuo8jr3k^#2|dt1H_-Y-?`c8P!m<+eb=8irT>-PLrv^?hNYEpl2pv6KA zI9){v8La;OAInfCK$}bDHbIC)y-%+%#u1|>5rkrj4LJ`qLN|65173RqX~5r~E4C>R zJU(Cp>>9r8g!V>lQ=|!S1KkmmaHgh;I`>TN0d(1lJy#r)R{RItBiheCL4I=Muu*G2 z1W|oLpaC7b%bWTluffjFWE2n>0y?e1d+`6DBmIF1Tv0E$aNL8gyQ4wd5s1J;Ah}uX z!Vo|PG!+9TR2#4QA=bkJS4aX>8}Z&r-iA#&5)QVo*_uJuJ>FdUpALNimLfQ7V3GTB z&6!|RR~sB#Mr4r-caph*veByUyC9H^87aHJae}2f@2@1zfQd2cZ_@Ps2!ppV3OZZ7y)HW>G-wbLLh?v(y9Q|cBkPLWi9_egy9muxtn3t{3 z`Oz3af+D6eQ=j(YP;OwA(&&cF#~j(i8oc{QN3`xw2GR**!&OQs(-(XKgfg*B0Lt*H z1&#s1Ys0cF7r1#rDE@f9$gL(EG4`o>K{<7*&R`GEU(aAzm>DCup$0tZfeonL@UyRH zTt^N)h=4BRyew-Ur4@2g{U~#j>lYSl$2>B)GxMtI4ZGjI%eFr6gXsQmdI7nF-2$+3 z^K2JNZe$atn_cR972{7Ahi&YZI$`-k+ElE(D*vA?o=!gCPb&pN*G)c|z!R*kB=q49 zS%L`%A~3`3{Y-xOL9TUFTtMjc;)=yKd`(F?W7nQ(92^Ffm_JVs^q33jHee{puXwpiV0`2K|cy2QP$yB2sTW{#|}iyyP6GxcAtxG%dFSh`Y9 z^4i1N!VbSLy%rEwJD;?!=%(ieCH7X2aDu0VuNW^ZZ!2abGk9$g(5*Ct`vCB=|FX>4{7I zTFT_|@&F`%_xwKRieXM6C8E!3%fyl+zTx3-?cHAfIc0zD=h}+#eeWn!ql330uq?+O zhgL%~Q8QtdoV^eyF!$btHy~bO3^anjqe;4|yr6#PyiU?#srvUdb9Z>mC&${Qt_< zk zJ7a1wS+3eLTq#Wktk4xQ(5`VJ(pl>|2Z$+nyg{YW=Kz4bC01;fWzF#uQK%@; zG;^+tkIIMxwXqV(WNA}jzNXSjm~|^;9?6L}o4(dZ@pGnpqY^gDIV&i7zwRSclNys^ z#>t0=G30(pNc%VH!O%)~-9Znx9YK)z_0vDY_pk6K(+LT2kXr5g8O2J-Uj4RD2K(Xp z1M)V!jku1AEybRrG{#YDUuxtgbXA@x1R+PjK?=IQ?HTnqmG35}Ct=Q_uVN>lZv8fSU}j_c2!pN&T$*17jb z?Zsc>jTO1M{J8o%*?rc7J!5@ps-k@`Ioyk?ziSI^H+ZfS4c3FKvh;OW_fISSptm*U znpt8ga#Ol@Z)i(`l2KuB zz;~`v$ak+7!Xl}}%}hGzB$QPcwE&!{r~i`M&8v@KSTGCn(b$(A`7@a=KT_ul&n}!N zy?Jcf8}c$!r?)g5=_;QNF;M#f7dc;czNk(-Heua0o_sM~^$%U!te2ed(XpR{*L6Jw zL;~vWpHD9_*ZXs{Bqm^bp`4Q-hHQYa>|!p%-+&R&I$i=V`uP$2Mn}bk>lO<0*HhM3 zeYO{rZ9`6T$QQX4jew7DNWQIqzK76Ya#ZKOO;mc&PM>IL7a*X)k-Mr2hhQ7M^g&4| zX4U<_j!q4Un~RMly?i_i=mB4@C>NSPhq8Ryc@k+C?TScl@{XS2re&RMs7?(`VMt2kqntqx&PRDTh=}e zb@CFM)c;uYqRNa*-SF+dNHT%4P!NI}bi4#Kac9AmW3!}a~iRyiwtaT>u zC@dp1HfPm7Gf{#*6MA$2;+Q(nHdSXB-x$qw(8Q>KjfnJLrwbCm2xiO02arW82`YOs z1f2}x3RsD(PvE=i$Io?$%kH_hnZHXV`9v9aczXadB#p|fmM^!S>GEK=#Gy~95)}Cz zPs<Px6foTuyNij!$TcQs(=caox z)70h1=nXiuM1LNSK$ENKq7RjrRGd1+RBPkF7LGBpX!oe}Rf((ck)E`-?Zdjxl!on^ z1~hHyYqmTApeSUA)BwX`f=T4UJ$ z`*69KZ#M37YPncQ?eSm`w~3_T-N)+yCv+b?6$`%QI6|%W4CoMiscWpf;=|+QkwucM znVcxbQw0R?ykl8}N923jSs%~ENyCtXQmd!mich+fqlu*m2}79-3*Wc;hZIdaYni&V z=rTI?n1WSAUF~!YQVz=xU3R{A9@cL7kBy!7dnoh2&Ql`?^o4wdDZ#!wlLs2y)@=mH z#Pf-i*u}IqAe}fLIHuoHj@(d?hFPd8z8aDvGZf9ce<)p?b`l@k&hRuh7Z;f$6w-t1 zvl%DJ{o)p4_YV9hm60Xj-4u4lY~@XSXdi#Kgl=+w2oV?{z&0t}6`Oc-4uC%5l-Afa zOPnK8seCW`@$+2$@gET@{MeJ+ew*)iN#HRKUF?K*52!10c14ijeA`(6fm|!PyMpL* z^|W~vFov3j@}~0}-z6eTh&g{z%`~>D{S5%o4<>GsgS_oC>763a9;huk9t-gHjuAMr zzZpuiPhQw=BR{n}*&O13jQ&@lUkK7ibGDtnAYT(tubHNKgZqfN=Z!O*DnjCcCq4+B ztA!`U=AP|pcKLK@nYjKIC6wNS&GOw!eix2=kvMivY|q!apym!fX>`f{J=3R&C569!`E36JI)*0N2>`$tJU=@)yA28;PamVX$Q5qqt#M|q&jGpkdv)kv3pr{y+cvnzxDrl zwa!;!-}i@<+wAiAP!v1A9Md83ANyDPt|_yN9$P!ooQW+>NBdo|0o~|QebjRdB;|Ag z6+-?oCkb&1ltsgDTFD6Aa}>+8cGT%u^$Ymp8p7G?iW#B$Ys#Gvoo{+?PGDqK|32>X zpXx{h7!?OF7DDmvhQAVt%N9joaBRJ5()ngp5i?`?d-(qSSM1yhCV!Q{g}>YHCOXGD zE&|BKaJzJ2r2*B26XfAb{$-~0eQPV%66;0e#eNc&`0& zJW%lXL7=P@eLdrm%*)D}PC>&iD?f?)n+j0~kOyVw1Jb%wXwjVd(lCzo2-=jKB;K_7 z)!~iC%6o4{q$*@7zwh|&cE~NF%+lxI{bP89CD3=e$I1(uV#^EUkg6!V=P`ZPDUim0 zcF*^YywBx8Q(%*0fle{FL~BX1DHe!PFpQ)8yBm3lYXihN7q&h|OrAjN*@j~sM(YX< zESS;Q8S@#W-lm|&IdH}jI$7Cbr7q)gKtIvqCL0q*a;k8Fr3*K-t7b4(Ha|3xP`)*5 zQCpew@?I9~GuUeVrnrJ3x_T0+M46a}Rd){`I~)0JLE*i84}Z$(Vi-RYcHa}V2Jeqm zddUT;!PD3|*8|qNeFfGD$47Hf@{aKrZ{+}3AZJ%5gNf?TBMYzc1&}+wT5}_<6{5Iu zyw|^0Q~#raVfOs4d{~B7WiA1;kd8HaL{AXOgX0y9xjrjJ(yGko&|Uk!9a)EQ4mDBA zprg~f`&RJJ<`RG@6TR@Umc3eE5gZt}cXC70r<2MY3Z=wfMhyp(c)@w~p761ol}Qr} z>`N#G}_`1-OzY8ACYTYxd71;2ZaV)UHW7_);^pdGBqUs z+;MNPj8-Dy%SjDm#;j%EypX!o6Kd(A(J%u@LUF|_=+I6uXptcZKsM`+xj-2;RNDP# z9cfGTZB!=+dqIp2UvzY(UA%Q5SXzv6Ou1#wjUP3Xg=ZG0*`WZ)yu@1N!VmF@e?s+B-P&#{mggG z=~$_OiS--*QZ>d>1NoTy|NZc2*5M)KJeTSKqhJYG?ZcHeVPjxVsROv}hPXsboV<7J z1Ml@Np^&t%b)_iW(4meFY4#)f@aw76$;Y1>IdH|7uwQJbv|e}OFZk82wD@7Dr!9Ma zVl|IOVfBLY(YYAl>5y-K1kn0oK1>ORa3taq_+KDfn^8D_$PkO*r(7%HzZT~R z@+O=ue#kDMN0VE?q9sQVsu6qP0L_f6m-e@>i?T5KrK_ovZ%aglspXI1yX_46;S2}z zU)s!}t+=TDBw09SuV-iD>~UVz9jD{*7&HSgi@;8jQZk52X0m z5BPgUA8UObw8rRgc1=xE^orhF&qtak(moi~aV4gO6U@llIfu*-xg>EsR#4xbB|y4l zVYo|S`fKC)HWHbzl6>Awooc2U3t>yeEO7LjsrpqIjgUin>^K)2DM%-iOhIrey@{jH zK5!vswS|9~s>wY?GVIM)xinDL<>Ol>>$GIQSPYo4g|O10Ozd!x>QK?gHiTFpHMVaB z4$l;grt;{SS2{!>pS%>uT6)_IRoY8=*nehjHDbQ^jN@ZaTHM=D zP3ZV<{tT{v%ssKo!aJOl_O|>ms&``-d&_-{CopkK+ukf6qlPS(JKrDUE={$M1MsY5 z4%6k-Ks9l*MVK5e{5jaqu8&$hJj=Ed`-xLYbaIIIN(7k3S6}@1~NE_r}tg zBL+EdlvyAFdL7Ox<0N;kO1fZvFRIDW?9QT4?1A~VP(cl4aI1>9NgmhrCd#zP3bL$# zk^c(?G{?0KS)|HgBHH&v>w37_nwX|L-%C7Fz$LYI5o{|_1h5a7qT0up=Y{s5La^EQ zJyMBecS#9yoOiTx&i{E!BpTukWNsw*W;!{hVa|M zzAP?h`pZvbp#WJuj19(>?N}`VR5tf-lNn;BR|a$f7!vm!^0ZgEwPTssuhszFHdH~2 z;Bhzmeh1xt?*&LYIn#J!MDXy~YUXJf%L@Ub|-u*Kq2d|nR!iHOi@ zMX7zJh^qVy*{>q7jKTE;zy!a)@z#lIIj0zm2k~@a05Ts2*_PaSZ+6fg@ z=SkuHpy;LudM??P(&H?5+L;_eA&ti+y6Pn@&)pvHu|@Iw0M$GAnVgM8dr_GMhg&M2 z!!l@BFBHTuBLU~QfP24$p#rduGkLTHQvlS(SKux9btiHtsOT#O(H^DIw#mDTyc^P2 z_Zf>X=qg9*&lvaBqfpy=-)B?N>tcw3eBrtE{Z7X=&kXreD*dQV(JMYSH=4FzCrMc@ zWNZORve+#{V6{^pK{fzh+pl{kHUIjbv8q{}-PLb$J<0U^eMoe<$Bria=K@eoEX9v| zDW81%6;joPerPEml_Xf~9qahSg@72i5^5i~suFWp>Np=1hNlN}SKcayYy1{AAw^v* zm%*>R_n(NImNwV*^`DC62bWp_TzVwj@Jm%_)=EZ+6GJ+P+S zSzvV^HxB3%$8_DuV$I&F zD;|>s@7lLb=sv7gnD0{Q3=Uz)QOBj+_YM1P?W~yX9ydLrpeqNks302k?%+_|7v-No zf7$iTpDBQy!3U*EV5drxWPJH>OaFiEeqf|a^F}r*HX{4q7Z^c${JziPFnwA)X)?T< zmLyPLL!na}uoHOTAeP#>$rJ1F+rKLGiumMyL#)VUaDdHVfX*R7Bw+GGR^oO0Xlte1 zoxcP%1#ij=+-vZ1j;8cVbBV@qU_oH;YA#`$RkaO4X5zrF1@3lcKIQv(oZCm_DWzY8 zewVU7S6^vP^XT?0XQs;inU^^cIa=1r!h}CyHqRlrk(3{L-C&x$J@-Pg-?7JYv?q$r z9+@Ta>MZdkVgx2}FnswM>xUcWZD%ycOm2^%dgKxO+?4$k_~nj_KFxP&H91S-)2=_z zIkp9Fm9g3AEjmf4S}4TIg{EcvNchcAryMhq;Ym=fB`zv4Y>&{6>d_1)wX~1hp>ZP0 z50Hbg7MxPV)H{2ey^Kk)3mqWM-Re|%T#xoO^&T|!^|;Rx&# zxDR=^l33s%+WGmeSk^&lo5}H-{X%Y~--A1osKbpv(}{NOyF{q+G+28;`Idh>gv|dm zg+mRjO=zjH9P*N0<48NV3?u${oQ~d*6~=3JS79^uSa>pO2n|d7@RY9qZnU&*knwr;&LjAtmC0ApRq%^4fkqEYxc?2nQvkV2%N zsrb+6@#%LVm0!z82XlAGG1JwjdE-Pg_o%C)w2q77yOM2oQazB-I5tWu80dRi{M~4= zOf*=>bbs-!V$Z3(5(245{7Ix~6atfz1FEp&RpcpXc=2kRB-PX(`Un}Bb7vn#tSoiT&KIZ$^%D4xB}zG%v% za$!Y>kbp5)-0bdjKXm%Ly~YW!SWpElh>%g*&&6I^0ge{n1Q4eaxF{}@>#!7B_ns!* z*?Vh8-1W+_?#e-|e+aLC7}4l^8*f#A(GNbhJ|xmPfr;2A2c&QU91){juR3Q(7gWbm zog!1@Ke&S9->y6(p34vt=#vHX$?9NcbOKj28%J&|P%uL%m?eqWB-P8t1?jKa1P5*d z?F?Q@2Od=|z+%%cu2(ri56!v{h;lWFioJ6WTX}<)9eznC$A=nb2jD1w8QcnPzWY3K z8T~cR?HYk$3D=BwBaouLDRV;ZoB1+sj|=qFIv0)A_TL&Y`7WWOx|eou{ec<|IE=@J z1OAzF@0NX-oWRf@XmnJ+}A@zEf50?{oZhMnyG%wfE{F2%Z6;bsZ zfM?RZ!Jo==(p8ho8 ze@j=juxn-{`DTAMZtSEV>q@?|H(`@0xZG?xz_PNZQdeb4zB1?P<-Xd=tFlvbgt(>? zE?Sj6*hgMQ@G!Ufybt`=Ca8j;7(Gm5RB)wI!MtFv5Nd*Zq}O|9+Po|56g9v7C3;>% zA|~hA_QpU@s>-nixcQ{s1LEfh2xz+w^>47wGB$e16Y0`)SjrWMx_@5M*h|$aW1q}L zbUpQ`Nmc#X!Ct^7g3*cxbeimA4Axs4aD9ooi)g%2fIT*pR+17Gs~B>9a{%QBeIK>1 zbu_wJREaaTM&NUNiT7#(h9|p(kbEl~OUBs%0itjA=Qz!uuT@kZHP@HKtmW1Z189E& z5O}FbzuxV*HWX-fhP!3D@sw=-UE*EdiEFmilOrOXc>a_*#|^Y!O`C|Mm?f)gixilQ zqndRU3E%RdolS0YtrL*Xo!Z3Tc4O68^%hXx{Jk|NB)YuypVT|x@81n8$ED*}#AxT> zY#I4ApOE>mOQ}O$S}3Lx!R-G1E6TLj&A{P7%q%ybmb^?y?5gv?u3m$=r;wFu&vp?V zV$gq0e&ytYJxTjqE12r%EH_apie>*^bV&P|8re1t{{N>wTJ}twzjGH(i zDo0llUvtm7>$7dGjNE~muJ~7}m-DPk7}?*?(hASYM&|#tZC7*h15hJIg+Sl$;0_KM zx2fFL4rkB-zGE)ZtbvL0#nn2vog;kLy|ivChC#%LxaHYx-FB=>+kG%vWw5HtplUCc z7%RcLpryjy_1l7RtO4=MSH2Z}O5W5zI&QAfd1JdRBtA^LS}#Mfqy6T)Xl39Z!`u%x zVryQhuKFn_Y%qgfjg{?&J0s%B3VyL+*3?Uvl#}Ds(w^&CA+Z-faxqoW7)w`gT;sA$ z;UhlnC&1g3txK_8KCpW6){-Q7wDnpFYmO&@*fcs?oX8v1O}A8T)oX6zbK%$2pWf$- zpz_7Vv{?xKqx_1aDV}M!~c?UtbtBm%9ScVZn zSN7ebJ83|^lB(3UU!+>Y5(Q@Mgic1)6V7Lv+*F5}+#E2(o~KOljw%yf{5EznullR}`|Q^f%-~(Vzvc@w zsf~{q5CFOJpG5!O>FeD4?16FeJv_FwL3r*4To<&_S?0CdvCjwA5w=~}5LGd!NKxGl zSz38YKZ#yUfyLS_{MFBvb1_!R{fEeFHE7$xFu{3`Ra&Rpa6DjpQZ7nhPfC_yr?V74 zyGUiJGm$qN`S)sKRj}p`Z1gco=V7JXkiuE>a+&(DrX^dB$XaJIP&CGP_GBb;pql=L z%03mAt8r=vFP()(vw%jP^Ec;{b~%3jtvEd|H}v~g?(MJCP;q;%vJGJ~KMm;;joD5q zH(cfOx(tlFuIWe#{;D`TMRnS9^a`Rlf^vrvqnENsD;uR}n;gLLBa1LEt;dsd^z$Uu0%?UO>5 z;Tdx2CE9p3o9EpZg;(3lnt!cO z@#@y>YJJ&hER6TBmz~CYHM^=5yJGhwQ=V4@okn)Q2?#x#tnSHCgkVK`!F9BSQ}-Gy z;|Trf0j@cIA2J2M-#U#073zL^ZE^c?G#}uaTMLq?(*Ipf%6^W$)gc5+xGcRz>kr?*p!pS`dNmxDwFJJ7%1+47%f%Espy@RXOa~2~B zT1h}a(3fwh4^?6iKf@W)$)tj?8FYOc6$B`(IM$G%^`w zZ((e)y`Gxg_;ZeHOgfU6Txfy$hm9%==On+u};#1p|6=U^gZW*{uBcJZ5~%ghX?v!O@mR7C%>b~1O4jW z8+s`p=|ZglqR>Kv(Jc=q05V|E&-geDo`F{|4f275_(6ZJU6O*6QN?HytiPoyqwS*Bjx2$<+l-9G+}>K`C38? zChT`imaidn^@ROV<;w_NF=2m{4_-v*WfS(3c#Mz19HL-+2_L)XRz{JU^Iy^7G-3eL zLmOd~jg>ksqfzjDdsV%hyaGI>;W@nQqq3Y8z3P6pzWO9=Sz% zm+VOm_rY&FjcNDFzOwTQ?#H5WKfX`FeP;xB_uWq8?f1&QBhl+9cR7uZYPh?;1b1fp zbhwkRfO`%G@sFC#MH{B#UKEFWhKBnvOyZ6-+ueJ`C=QQ3q1CH~ea2&kYX?!{k zM{=>#_~-AaI35lC&vAq(9Md!$+ZTN`95=-IV+2EnUn>GJ6~NR^<$d*RjC*_6RB{j$ zG#n!svN=Dyhh1k_{wp{(YB&zgcN&Ema6Gzq635ngPU9_cIKn)q@nH?e?}x^feQQ6{ z1C8CcR?8#moW?VlQ`UMm?^V`Gs3j3b%e6iCSJbQPhrj)?)2Qwzl_i~wy01*zyOKxH zsf?o^IgOEhzdlperv9t_=w41)r>Wr7bvW`vr}0mFx#mHfDY?0Pbv^S3PUFpcxn>^R zyDG+8jwtQ;fz$Z=2p&Ih8vn4DYmV2g>}`u=pE3?>oyPpVT(e872Wp+hXCv~pPUCZX zx#o{K*~i-c1gGM28S}HNC)ZG}#Inx~PG}wnokD;F)*+$Kg-jugKwOVZeIH@2&y7+VijlsL z%_R!b$oa}75KD7lREOLpOy6zp20!!RiX=i=d1Wf0d5G^*{*OE#ytldQ{ru?mUAzap zWwQybUjSYmbq!cYx9=)`5Bl{$sMQ1B;?eE9@(~{@_JH>U&XiVo8vGRkp+k7K1StQF z%5*|`nB6F#KL&IN`uN*WpcI)x73n}XDtmNUB<1}KrOlarR-|uWWdedu9n$rcB0Q};&Wl)X73{4sIniLz&_#pc+{ zHMeqbWpOf`8vZp26#wa3`s|LfdNty`pr2TnI+ zzkAxcy?D26?D{9yj;(Eki}bsdJvp?!(O&G}nt}0U4t_ni_QyB>e4FgMw}We5akct< z7yj%vPCQF`({ma7ZUqP(ndL6AruDqV+QcUceed8pKLRk#w7z@}W9h82*9ekWU-^=t zKa4Y^PjR+X$7T0fGGTNi14PSK7~QlG#B-NG=Nn1T|NW$*MoZhQQ8q^Su>$42?Q)K9 z#F%eX_j$~c-ou&Fs|nD&i1`#I_6m;JPjbYbkNE1t0AeW;syR;G-=m5Hy9vO=%4#_f zbr|d;9N2kG?3Em`TeN$L%3pQ?gFQvrH<8`L?p5`k(Dqbh*M~W8oFqWzm)l{f4p9RV_$geOQ*oQpAUbmG)(an2v1pbN_mz>S1{!#X2b;XDjEgu=ZK8 z+P+!kV7;J+$d*VI$^&B*pCBe#Vr;}Ia;f%g| zZjQ2tckpb*ZklUVNyJ{Q z=+jkKE^9FJo(41XEeq4f5qqUhtt%o^nMCYWI7Z&{tHk0bU{#8+_b#ZOgfl>#P zo7TQm6`%Wc%uapv+GUOAVo#$v9~r8vmo=HKo+dN1fBmvLbFrt++=7H^Hg;H@^`3fj zRjS$^R?jy8Od*^hv3_DWRW2opjRwue7No1LU)Er5@-1mUJ)%vMjGxgr(3_ao+e zrV!%`hUs8}dZve<>8wIv*Cm2Cgn7xD2;O0=lUR&v#VnQ+do@z+KQXTCODJvP42>-U z?0+@|>@Y5i&n6OkQzG=Udlt#ESj`z4t5d*xQkJt^Y_5tTW6GqQ|MU*dl%{(&^cn}I znVuO<@bp;0lZ>YsU;j&7ovw0qJ(u0b_&RT_;7P{Uf(gX@kI?81xgb7rF?8z290QEA z^S^iX==XKHMuqdvI(N;)+4Ym09jxF;@FYiqtRIeQoUNPW>|lhm8&u8?j&Kmp8E>Jl;XhRTGI6EVjv%jfv_O~_8_J@*JJgsr| z$m{;grf~M*(t{Dduw^Km9jrfWIruY`vxD`AOAjhO(_3%m_t%>n4qFaZB!S{fb<bd_?hqa1R{h#4b-P@pWa`FBqv$eO$>_U9?{jB}HDkrl#>U-j-^s}*1zrWGk)Z3`=aP|H=v$eO*T(KOyY-}(duD%$o zJqaMzBX^0Q=~{;%s80j$Nyfp-ISP7-&57Jt_0wW)yq+AF#gDKcJ(mWfRaHw5=8Vf? z6_?WZ5jIH0o>Ij(7t5^7&=~q3^6wL0%)fp4nJ`+Uy+b7R_&2k8aU+0neP!jUYQfN0 zhAeMbPnE9Hftn}oQP2Fa4`SYCJ7rm=&NFyr&$JKKIgXv(Td&13y%x({T8yoZi)Fk4 zyp2jMLm?f2T}S|XYnmF%PGXDA0AONzixVM@-B+3mHIN3PJ`ubhPQ*5bD+&$HQggN@ zC3iI_v5n!H3Mq}<0_=Y|1?;V3viNc$v3DdwKf8y;HUp$IHl={~16j^u_Otdz=L)Qy zd;-`7AojdzuIUnpT@RCagwE4oW;imOz6D_7f!KwF*t|tB5W6k`>^y*?Gdj;u>N9{{ z;Ag1MKY^(;AvD#x%_B!JeNRZtV&9&?r zp8!DtNHA}jYx=y&_@e98d^-=U6L^0umhS}v3G#VhWxAqyTB*kXL4lvC9*0#(h~;~I z4w_bvVTr@a+WA%aK1Jhu#gDH5tFQ!3*sp6PR^=Ses5q(TA;<$Lc1FiJYmen%HITFuE=oMBA8SAcS?wStInLAoJ{E?dijLWm*4T~sP~(^^GJPN6 zG>OSC9GAsDSNdLFz>z+LhYMp7bx=~50DhkLsb7jh?oxEB%o zEFku`(X8qMmbVEo`aA-ADuBIjTo!L)Z4qF!7eG9Pb<%Qhm&ho!`kgUZSacVxu&RBlaK8BdcVTSpA9ThvuD^?ev!{-=W-l z&*!rE4o;Isu~EuL>7fT%-REU-5x7fkI`0}NJnuSiS^%#RaAPT_wx8)cjj_b!S^JMF z?dK$BE9Uz{+0FmYQ z3pq6pVdEzgz{JW9t9y#t*D2*hiPwx{3Y2qLz+S}K2g=z1_A~$!i*GjVH{(m@=aG9x zu+CNtU{{}=T5O5he>+F8UYU=v?^Q}1Q`hO(y_K3STa-Sgi(Rv7?O^36)O~`}1g(BH z&*Kvzjp^kDNUH~8uhQ;iZDM*G6#c|rtd+Aitp%`G#npLuhB^z>x#C2f5zc``NK-xq z?K4IFRMwHRHSW>o)6X*g5!C*Q;-FwO2R)tyq9qqb?@{KG`q1KOxae&pgbaL2V-yz! zM{ghp6)rmLHGjCj$^Xj!2`&nz@(LFP8Anth5Z|5TqF~{TOb%BY5AQIqf1%0Wv0vq) zbyK-0_^if7jE6d?YoLSiBG0%;h;UIb!bP@mS$rvqi+~4li2(gNBY5>W;B6Xn46t^6 ztntxJ90XrYV{KFUh}mld5@eiG%=jo5Mvox~&H@NBKDwE;Cs*a8QLK{~N3eQB8Xwgt z?N#xp+27!Q`d5!D?FwCx#nT!ey@%7J%QzBzWN9O(ey#9Ok{Xn_5`g2)) z7pF_7ahlYEaA+s1`@AfE4csN0!>)nvgk1-)4!kZ9LTP+LBg25{dj}^>U@*Z)nJ~JJ zSJ${%zq7e;G#713hG;GdPQyjPv>VAmg^PNi-OTyR4=4Va#7l}Tojz( zBI6V;3Rb6q*OjSoQP2huRJo{taZ#{X^IZe4a7~bL%}E-=Nx>LSin=ePa#HX`ShSqMrndwen(> zpMq6!bsn9e&f-aaQtJFNe)>rMj)jncl3m@%aQ+?)VrVf5$XFk` zQ7KD3{~`zCCL~BNBZKrDGDu4hbe1Ciha>hZb_72B`r&qF&ss`$S&(qPijrL;m$aB=Y*6aSxk%0L zjwQn}_#2U4{~^wiKEkym$6QbDMSMdC z(lr32gmj5VpR|s>{A4bqzQvC@2C5Tb**)X3cnv@&vxC_)hy`f~^O3WyLwgcIEH?JM zr9;eKn@zaj7+9Qh)L)Qu)DJmF{dpH1@s}fBD!NcMaKmF{m;OT8fZ;K+%gP_|U;0CS zH}mmV5#MM{g#OpY$_73G==%Ct*}#Lc-1YVCDZ4j&QY9G~L&M{;SnWa5r5)VvKH-S} z!JsPp3E~^86QTdqSlPfSfUeDBWdoaKxoh+Gl-*v>EXl&9DYDG=CQquggpDKqu%Fqi z{~@=Val;7K^;PGpHVa>SNwK>c3DWutWdk=pMt04*P&SbA7}-@RyzIZM!=Th_xh2WVvhE_SD^{Jw_>?OIPX*dGylPJGk8;;bs5kLzA-AQL;6fY|Zx6 z-7iGRKIfSw-M^pPUFi`T8!kHP|JoV3v*9raw8(N+Xjb_6;H;L_Ba292$*Iqd>nPc^ z4(S`$BSWJL8A2>i(T!~w(3g{4`H3)U$Z0KcA;b9{%2;)m2++P|EfVzCFdj>U(UAPf z@lvE$t_#5p1J+#K@-+aaYE*ID0PQ7m4 zA#$J!>DKMbec9iFww-?UqSyQ(Y_l!Nec7MNrAnVoRX}~1^EUq)yk(;73uBPXW#FY4q~Sz3#phbR79ME+Paw<#XlG!~ zomlIB7iUQC;VkL>s|fu7nYlLTJ`vXa;ca8p3m= zV;f{2P`Qi8gbw0ti5JxWL$L4P-YENeWjU+!jhh1(77^OQWrm0z#P%1Ve|9c-Ss%9U zxI0|F6q=j&Ag^*=2coB;Akg|E^uL4WNjEQs=7ad|um#T!wT{c8Zy|VD>p5ZD%;cj_lpv>l8Q*j5-U)Tt>Bj^&62@Pq21n&u)A(7;30(UQk<{Vk>B2Odl5YCWT`GKX-oXdQu6}+qNR^OTD^@IwD z(0r5~VwiYjSq#c@*6>O~O}E_?mvO^DLYbk) zWexs^mN)pT5TV7g+~wkgP|lbvR;Cl$%?Y6wFUVq55}_fSAxUbSm5LFeM`gK-`B9}n zs7?DXQ3wkP4muP2oe>(MvM88at7c!o>?*$?7={Maj^gh2}LRDQDKslUlGj z#9~98{w;sjsChTj!zVf@<5qs_{|WO3=*&ihzNv@K+mfL_Njd)~v%!M0Lb-YnvoWDz z9dz=^gj&!%<-gYaEcSg)C|8!nzai)Zz1lA)@EmEuuej#2arsI%FJv|a#$=KC^o}uE z6oj|@d2Qz1BeI+ovG>F0uM7Nvo7ceR2JAbtcZX&#zumn1mzeLX-1=BJ;;YQJ+GJTA zS*-pa)UBRxM47${76VacL!vT=QQK`3-tw>gm3enQnim>m_hLfp5p-I=q6`5LU0YX& zncN71PFs{*u_jll$*mLK@>d1SyGzkLyPHQi1K9H=b~w{k73FPG)c@`d1K z@#f0gWnb&K+*QFb4#|j$H5t;2WwP&MZ4Cal0Q&hcLeFAec~6+>>MDT#hY(EYT6nwc z8w8kE*S<2@$Lw*iymKX?Sz|!inDv~H#m`m}I(!KUwhR1Q~CHVr8hGN92X!UqfKH zK<^!11j@PDgX;*rVlgy_7Zb{GX54Z6?a+xD3j>3TIPW_aLKm_;s!6;{c06A>ucxH|_H*xnSeHs(Fej?#hyVE& z*;jml`t{HY5Ud^x0zHu|6*9BzF{$XZ+GLxO7*e@5r{(`qb9FDU8XPW)L-C+;3<2m6In*IBp=9*bw zp2xE#^e#MjBCBW3NFp4w=4LDPcDq=6za8$z3&M_{{9rZN@gJ*O@!wV#?N|`zPyM=N zEuJ4Pz%8qb7D2Eb-w}2syVur&XAU@ zfaWfIXPCZ|5McOqb9^Yr4C3E5B5!*Vp(8j`iR0}6ou9|Wcj^~A6 z`vx?(rxUukPN<_Oh0{&`xcnSZNptZcxV3*ON0KRsL5TThZjAykYBifGuFsL9Z8!TibLWc4iYJaCslcJ2b*=dJ-B z=_CQHPccr)@YMU6zcAlmzLKo@N~?MnwPe$LgyHMrvO@uw^pF3%5}FqPnD$^0nXRmD zW+StW)dgUEY7qxwG{!t!yugwOqZKTtNq~MUxJ&r7p0_MKj1FVIFE96qA1fXMoc>8R7a>F2j+?|zcw z`_^JY^R_+|W<0`j=6Vb?gJFXSU5$a(VW9S{mxt>xp+^vO@`;2BN*#hy2ag0L_pl(< z7X;x=e_mVmZbfej-#8BeWjL@tI=nN)7KjTmqTe5K^FEuOwF=Dza6l~^b*ko$hyzb9y%iL{2rl|aNUTA1c7XM+6 z&R^$A5A5NZbH?N=kForDC83byE^*u}`;Ke`@5mxTKgS?tY(|0Jh2U+yWKDp-om19y z-QSjdEOxu9Aux2JKp7j%_n5D@;{~g_06O<@ljGys3=q3hVe}rXV$sd1<0BiubofnK z@!^)#sXqMlY!KbtR39GB{9+$&j~aK<`Pgwc&r|QOOIF9-UD~*7!I5z{Pg;MM>|a^&xnjKloo;;JQ!KBJZ&MKlu`wC?i;=!zE`X_kSMwu=8^bsTmsFM` zPlHR!7voZ)w3*8y^$nXrqG)TOSSw06JM*tH407LO?SCOeYr+x)u?7CjwfDf$Fwi5pKtK zhgrV_v^kQb)TLAEvLc-}Ps-HhNw53Y{wi}f%Sns2TEnbwSRW5RfT)uHUP5TVRL+w^t0K7Hgkl2Q zwYkm*qU`G#pWe3b-7Wh*(e%7_Zrs=WtC{t@{snsO(e#`-Oz2;hLnq6fPaaNI^6L?n zZ)-U=%cn;c<3OMg_1jpUtp_@MLhn7fC?TM(O>GF@od?aVZpKRwUk06?hHCKYi7qoPpV{ogEpSS9i0#x&g%YsJ!&ljcQ)nrRCLow7gW;#x;9t53kN!oqgkw z#l5CIDz9FAx9l6T^sG66w+2|wc>rG(VEGoC(=h(vc{R6Yc`nPXmG!bkgnr8MKs-0> zu6=PLUq2G1H&fHgVjXMWFrF=)OoV;Kjx2AEmJ0{8To_Uk!#dBruz(hX1Ng2mp#NBn zJWs98@L0k^BG3_lPQ{KztnV#Kz04Mt=N!2h=wMdQnmoAosUEX?P2P6s3||E_bcq^Y zBe8Ymxvv&m+b@IWv)de$^<8FMY>i$6V*Fr6*-C6ZkFzC<7F&7!>wfc4=I-G~SX|u} z9>&m_g$VUU#nsO^LbEV*4kxh~nXSat$a=@jan-EE)#231xVkzUItO)=arNh|YFzz& zR9vmTQH!gW%p6yxyJR1m+q&+7z>u!+OXKRVjA~qc8e-!r_ix0%raQFww=FjQwQo`5 zpZ!KH{ypNL!;h%Eboi_m|F$7I^2jvt?~;Ep{?%&nPgfWd|L_d)ujotS-#ydCzegPO z!%MzG{CgxW{yp;lar}Ga%i|yObCzpcwD`yTUHK1y{&hdUJ#)7i^L@zIpj!z#S{(h(Is~?xMKHV@i)?Hw+?hyx-HJ@5~ zR*QAp5bb7IY;({NyfmG>gy^RwcLi7sck}8xf0idjc}DWk z9(7LNlMEt@Q7SKFNjJX;&8_(Eu(D5Anu^O121!{hWoMz9q|@Ly`Ee=^0k^WJT%8lJ3#;Ff20q?^dvZ1nn6}95w_;V>4S4z7U&C z>83nr{_T#t!&&2#w!ENWGo39&!v;#-C59Vh-`R;AAm0lFd55sY#@*yD=^lqbI|p>| zDxg1lifhhGhEwNorUdW8gP-9{={(MqD8uWOYiV~a(C$A1ZRJqMktdL{R@9pAUNiW_ z4_CL={%Cc32?X1>L9l%f1lx~7uw93O?aNWHy%q)AB@}Ewj)LvyQLud>7i=%)g6&(l zV7s3Swjbt#3?nkDZguO$?ll>=lm>Es(y)4X7NM=RjjLO0lR8?jcCTT$wbt?-J)F?d z!|6JDYV{qhwJ9AvTxv%vXYA;yHFmVtrg!vk86B-$W=9VqxG_n)&D65srA7%0Z4GKsY@r6Hv+AjO(<^y8ol;;_zu}umgETh0WVnP zz7(2W90VeDy{y$GGJjl2=(pG#kc8|_XH>KzJt&lq43ZZ+a0v^=p^2@>G1wGq21$p1@F$; zGvnPj1KxkTWoEqZo4|XHfRQ>>=tvYn*f(@Em3lh8)89{ZB1G)1&&XAbDvAXY+8xPt^!(tv-^axYo7cY$2YcMA+&l&v%dw;4h`~Zt~Rn5D4VC;Q3&2Q3c#CP2;R53 zc_B9k;$I&if!&~vJLdbp-XQxjk_pXv5CTt*Pug|%X4wZbJpbIWLETfD*~9!}WHF&u z02AxOgL{C!d0NfWBmbT7&kg@p7%Ln&8G7u6d^9g)_59LrLAnqRTd zhOWVn9~-!8ow^>)8?zdfeHLpo0`1QL9ZUj|)y48e7AIJ{*maTwBFh0QIG{(82(3s0 z%FFV^*nV(>>^mdNSqv98E*W110K^t-3Jq}}{(cY8g#acOHY@LCPS-~-+&pt15v`9N zEd;NmXWCA&WvSNgR)ET76fW%i!AS@z{6!!dr@wUl>&m-Sz6G8|i&49Aqc zi>|nq7Kqo<_dgl;G5N+g`FFpf{2QN)`%W)~=Fz3l%<@3LDErvw&y`Qq|1(kc4J5<9 zied-l6QHwQ*%xqmmLx*V?KDdOH$p2ajzKfeLx7ow2hm{=H62?e0TpT}r?lfd1foN#Q95!MMyQ9dM~mqXG%gm!<0exwop5&H^)EeewVNUL{?1>n`V>?VfY)Ig7wq#-};U zC_KaM6|tvO2_l?j^Ne+(pms0|fQ>sV55&pfEZf3#)I`sJ<>|R^(DwWEnh5hEhtub$ z`OG}`kE-NRG>P`zL+L0*@4x$`D($5_1i%t{R|$}R8esC<02bP&>!d0@43PgO^B;hR z%*Q+1+XLnSdsxOTLCOL{HW)R|JMW%C!bIy+UAoVRp})F z%dD$G%ro8}o&e%C#`}N#s7fL|2VM;#>%RrslnEeC360kRZC_6SG2i(8%dmOg@uMm& zGJZ#dJ-_WoRcfAs$&4%zoAWTaKO4m6F__r0Kx}=2<$s>ioQBEvlXO0ro~c{C?=U;CG1^yh~@ zRi%q--jOdXNAkJFoZK(3Cl7+=%4$1rx!gC&aHhUnb9V~fhtiU5@nQvls zk?-2-BBecIPl+AGda7qSLGWcq3v=gy$Z~pQM+==TBL&}d5PfU!mB$3NjU`XsBs3sr z*3`8hzgH92!S`3$K)svp4|A59?W@;@+Qw{RNS#B8p}t|Y9~sb93vb9 zXIXGegz!Z%h^^7E^K2E6^WR0v!R0^}wSkwOPffFJq%@q@MZ$^?L%i-nwBTzQDST~D z5RM|9*LAmy6qbC5M5U#ya2bbpb(NP8e?tc!zmO;Rui)^v#0y>acp=vY!WrJ=p>iU?XL|gzfXudm(B+C1 z{P{p+J8H{Cc$a@Akl6_D>T<;h{$)V?t_*=aU#vg(wD4{Iav=T+Gwah|q4(ooqrdmZ z0`c=v`Zx1|`0c4eUKR*lbAjZI1tGT@1pfjc{+1NhrfXZY>~FB@eceX;9jSktPTPzW z@;Z_JZhVC7r|Y2KWXB2qVaELVk%B*yw$uOmfMN^;)|yOtLT|K`GD!7ebcf?7-4$MT$hPr1M)lI zFhx4c0;_=Bf48a5$43Y+%m%SD_I7z+)l_*OpAoEY;oDlyY9}ggo+#vfLuqxPL96!$ z9Vb+Ywyo#erZw_q!Fs-KS|gtk^tob%WAvMyR|-#k1EMebcA2BJFx)EGk+bZ<5)fgn zPCvB&iFfEYO>wLysz3h5MS;V!ZH-LF4Y=kOe!mj;;^*--Hey2S+%l?lf4|B`st`Q5 z^rEdjunZGrF(Px&vu=L{BFoS-?ylvC1ePJu)zIy;Fwp-PHt zZlQmTjdZQDu|8uj+S-+6bU$j{OVB!Z@nkqjb>LzfoTTR|a~788y#CCgbyvT3YR>B) zo?80M52uPzOu#?)xkK{Rub+}%|M1k3=YBW^X!g1HqQGI|oMpA&KYOS?dWF2?>Q_%4 zb!7;(6aH~Zab*-Lt_;EdkMB=u+cFBxBOrK??!_qZn(A?(IR%rLi?((;rxH}_9y1EO z<_t_?UZ!V%c+iGw-9CGQaFYi_<=DK!*1KSm|6?1G=Yv-{U?asza1xh+qj&_I>|6j2 z6T*AU&puaHoACOBnaI4%wg4Qz6-pAYUP+Hu9(7DBS!6khxHh>MCMCN^juM@ zNtGPl$Ybz0Xm7l-c z*WfJDRw1&l>UvqZ77_nMM7r`32~0)g_!@3c0D*T-BqrloZO~X|_nw1djaXN+;VXFG zy;L^W`71Cnug(i9YcPv%^R=W2ovs++C?6vnt1t^^-Uab=zKuL@f+pX!Hlkgt+p-_| zk)FHe=y)~PMt(zoyNurpZRA0!8yYlnd?hC9`92z{MzwB^>a9$^WU%vh6JHh#F303~ z9-8X;dBJ`Bh#(zj(T_U5vVPat$h|+RQaHWeMRmLNm{8f52$(nwUGGgzYx21;(Of`A z|4Z}U`lBixQRz85$usvyRXWWldfG2&-o~xC@J-H$lNp7{blQIjE^Jk!r__(c1XCSZ z)4wYUeRp>7cT)y@cZ2a=)4~;UPEgxux_`LvKIbf3di>e4b+5kqAf*Wt((TrMS4N?K zv7R$jdo!ajZw2hmK|n@kfrxqVDrdEwroHLHQ9eqb?OD57QH9K}8{sTd_^3i&a&DG8_LYDzxv?TY_2WzU8BodKxuGayS2b9#O|iL7vw?{)$Lb)vWDsQ zHY!t(=L%ctnSCvYm1BU}ZJg!cP*`mw@R;ML7sOPT7j)TE3*SeOAM!E#=jwju95awB znf|}9pb>@9O?GvWGM6J;5LmolOlNdcgABSU#zd(|EldofsnY9>cT+J@_>qMhkshbI zc_zHkdQX44nl;Oyt9+jHOyr4jEpO0OvS-nYoVeuyB={C!@^n6k#BL|65j1Hm_bMju zb3l?2kVaP-^Yb;jMg|LcOwLwe^5Q7)p663NmBVZWOSj?PvsVgQ=bn;O=kDZFm@a)? zE{K0}%?nca+-uVPf+2riB3w19%7~q+iH0@{N-|=nl05r3-G9~?^DnpMlZ?7XeqPYD z`k`P>6nN7RCg&o-D@E)6-FtXU9*G2RDT|v*(*3)=aZ^^qznfwBcmL(i*^EADS`VhYL2;yn9QC90)0Ljt#_|Oke?FNyj^^81R+b)9B*lwb@v&~+sW>1q=fdKC;vH)1}1Gav#v&}O>Xf1)l zQ0y!>M~|Hi?f>6r>ihrc6G(220iwswrg=JF;Ka%b5Sq7wU`CkL#56NILvxYY1O&hs zZ<)RScz*<;b!*>vM`!jQZ+mDwj+a}L`^Nk03!F&t=*XQQZ{g?vDct9+G^7>&3BdbA zSghqMCU9&vVl63dY#t)ka@~Mf%arO`x5@B%-(~o`GkbmBDV~pwn0tzknS2JbLs7kk z;_B@2AZ7qq9^k=2=Sjz=^9=V#A4A}94iRga^KW7;>6~|#X;LN+ffSe1O~VCg zp|$C8Pf0B9iQ>K<_msrqoLMkZC)q6aImz?(_qtrzbaAj;*!g{bx$x@ux?C8fGuSavT2geK zVJ5s$li#1W4L5Mjm(7!&Or9v|e6P-s`@#U7A(0=fGpw!d(;3ck#DAV6T^dIMJWr0t zM*Y9(47UxTGqj`#N9`%Xu?DN)-vi=lt%OXbFg{yCw6h$8@vpyECB=T1F3S_`WC{J< za#vyNpQESvvhAe%qAq7E40ujd2gCE;0r0%bfG34n&V>FjYnfrdY%WK7W^qKZbGrO`N z+(%}@8>Sp^9JvQhDly<_eI#>!cRH1kBMa}PXR7oP(g@&HtR=*RaAD?NSm8Xc4c1kU zIE$2)OX#ZODc;5R;$7*L{bBfE2!<_)^z1`KdACnjT_1vBOT4gSH;De0TMCs~n9SZ8 zJ>?Ss3+4R}%+USR$ruERFTMarG?%qd`H^F>6ad;lCBG=Boyb}=TzG(<#YPtj5pRPy z)SbFTsMd|pIyd8?E^FZ(<3QZUfvoeiBv0xw5V0BZDZYeorR}&XwQ|Pqk(m7BIMof4 zJO_^JG;K1$l>Y{>w1&mGO_`zl1WI|l%eR0dXXbN6xs4-w3|9*C>)#@AV%5?q1-_P% zLTAND;m}+Vl?ubwu%LvzNynk@CR&Bgdo@W}Si;WQrt15GImom=m(|?Edvaf#K}=>C znQ4X`^3+#mD&`Vvw{`_IPY>^+)3P9i4B zpR1B@945*=npF8##JtQ@SWz0G->J{ZYEAQ-oMoBFytJOz&oZXSF#Pz`S){y)NIrli zFB*1+<}pW@LFgO;yrYoLVU7)it_qGUGv=|{n8zpgF#GsUIv3L`GYHB8;nZjPeExEe zCeb~q0myF!XIbM`JqJ-GILo}FFlkH!QW^DhS!GoHgEbuNp>r!eA3bFdo({uAvG?I= z&9MG>+B)69(>D?6*@1|%y$?@2e?NdfHVkp5`Z(-NwH6WodPKT5AQISw$no*~{~LeI z9D+aEUy{9JJRZV>4?qLYsjMhCTx@bWkz;bTpj z2+p!jR|dPkyL65wDbbj;>i&|QV(Y7n){8EG7~>KD$*o%_Gm;8$f(2^sHqhdv@Ji5S;)P`ah*h z`mSb}PMaSFRB3gneRdpczhp9q;c#yW^ufKBhx}iM`f}aN`U=@n_5|n|cqXe~*v-M@ z3aSqrz~s$HXtiZ2I zb9?*K*QA($$tx+KO4EDSdpCPWc^lPVHU?CwD74-N9cI_i^@hpewE)iT zU1!*}Lvt|kxUi9jDa|7>SrbsDGysd$@WF(`rZhr_&4U3|$^@`vgvPEgv#}HC*kN{q z%7AV+sNrp_ejFrU=$HuhBEm(xJx!=6#O&^<~2F7#~QNLVpC z0UZ0HV1;uyIKu4;GXuK*N6&k~<(N<%a9;wfKx;X6N9jdHml;%+$*zULke#X&)w)d_ zG%-1}3X=|Be|zM0M!z9@WT^jozHS;Fqmj=DwnoE7(`*~5)a{HrLq5Udk>D5@+veG} zM%Jnjp=0>gAQA|(JuabhLF?T9m53;-5TSGW+7&CXn%#~#;VADcYe;pL34cRkBR{Xe zvu#E1SvC-hNhDh5Zj6Q#A=~;QO3P=p6InUKg#Bl=gUqHF8}cX4GuBuZJli!Gc5Hrp zl84TBI~QgjU5N?RZ7R)}Y(lke+82fChaxA|@R)o}aczWd7YfDE9pjUjjmW2{QuTQ~ z=3=s<`!Gi<27jWw=&W`yYq(WN&IU1@5BWMlWd5(w{3qzyU+6W#mqiSxd}xWHO0OhR zUYO>geX$zT5zexhA^L@E5GRH8dz4S~QXf=}p(XV0inxF4O+o+cn9z7L&?C5JU4_6peM?nI%JL0B6}1g&;aD zj9yQK{9HM@pKD{tPw*-a4(5|@O%Z&2gz$0;-&SJy^t<^8VaH#QsPNNuKi9U~`}y?4 z=@3!+bpq9qPlSA2_DsXJ&rjER*m_Koy83)vS@auA2J>-kHGEt>hL4NF^p=?*Dq}D? zvlUpJ@##^RJWS!AhKV)`E+1z+21rx(3V9!A3OFOdLD#mWg>TbygD10^24lfl_Qn(> z`i>%j?%&u#5WCl7lE_1^UAEZ_Ud69UHyh{ZZ~VGW(|vxhPV<$&zfSXoKV+9p^n6PH z=Pe$`Ma{ctD+mv9nA}nbVr2;~G-=UO7LCN@Bigs7St(pEwO5SSy%fdv>g$$h;b_=i zP5&8tRWW+-UU~egq|CwW&VTnzOjZtuCZz-uZDt?ryKWi+_H%$Jb$CxbKQCxPa0A6n zN?X78tCE4EJ4;?J5M0Pv_D}(c&ZK{jqf9>hDY6$wp9oub)X!M=v8=)C{*}KUj_%BQ zxq#v56R1CqQoj503=mImvJ*wJv-{%M1P=HbmYYs&D^s%39v^RdjqwLphH#9J5Gejp z+?xT;vXK<`p5Pc>K3xFfn|xU?k?ZeUnC(}kp7od<=K63F$AZ`HSEaj*d+j)cTWTL} zy;aa3xAG0#^6?hWB-*E83#!?Q3pW`!>>P#3HGWm9F>u&95|i989KOmJr{~AMab6lQ z&K3Uw4l|g3R-ofBZxY7veS5j-FF$=RUD<>8k|?UA+-KnMJ(#RafF|WmOtgE#aJXy; z9KKJ-Vc#Y@F`>*}9R5bpX~KUWCMIO|lwQwyDNb`i?O@5DZeo7gefc2PC;xk#&Z1|P zoZMcV9utPs^L_>#j*T4*hqskJoM!O|f4Yg`bO{>FcYmA?Vu*M8BEfNVD+nR}d5pJs zo;(fW=`p;}y+POe?k@mwCFPR_e%5oCG;+Y?Db-24+HaQ?-s;iT0`b#tvTb`U&&CI1 zjQedc0`}HM)4hlg)<?9v>{G=l&2+0q{;xRH=!d7o>P^LKzI_L-9=G6rFb;r8@TR5kd=cmPJxL z-=pJs&*k-tgIPF!NIaK*2CTDl2gCZ}cl}~$4rc8h!SH;)f#<%3K&mP4Zix~mPY1C( zdm+oy=WGOr!bb^m3*Qz~4Z`QQK68lt<@HlNd?ve-a`*ASoa!16ByS6S=R4K421p)4 zg3lHAnyo?*}0;70BEzAOscznTwDRm=9#G4GDo+Kmrx%LM6hxlnNj@^zU3C zrSxwmkQ^Hllwu$;02aC?|99LjF$zY=FTQxngc4Z{iypsX3Dmv>4qrvO(8*i!=6?yI zDbiWivkXY}t)@C(OPcTv29d5=S%XQ>LOUs;FbA`6uG~&CQ-K^~x*EJjaTmWlfQhuPMt;O^X&>}kj*c-6 zSj^aN`dy?EC+5l!UYSGBtMdzTIG99rVkx ziuaTT&|~I0-x^G|$0G3ppP5JbEz1eG6$FYekOYqUY_5&=Jr;vV_isx!*EY!qV!i9G zU_F302{8HQTirh2q-jm{t_8t;E-TxcBj2i$l09qBO8}EL^QL8s02~K7uw39xd5z;9 zk|_-K^WgYl6($)7_PlS#q!~3And5;#wR4)k!A`UWo*cOd@(~2YJOW79Ham$)qI|;S z32e6$Z5vPK#`D4BJM844LUC+ger^8Hz5TVgy1dongZ`D6P`O~rLP8^N3DWjw z5H$IW`O&q$OxN0QZ{cY^-D5fvJ;k@#PBwq5O0O|JG1>Fdx2kl8Px3shYTnkZxbPDL zN18`r^8B}|)N0^J^GHmDZ*?5$Txchh7LS(OiIN??$F~ZTmb2Q%ikl}2_xuw?3PZ}1 zy7Kiq3+5Bs$}oc0{1wrAj`HB}XV2P0VQc>X6Kq$-BC%(?o%E#r=dh*iA4=^H+gl9S zGI_SyPG*0rO4Haq^!Wvi0F&j!c?C=8U)P;M|7`He{Jh_4*%5`BE27ZPbE|VAVA5Od zD`c%9qfjZw#K|QGD1Bv`fhe1J;^V;K??$^!7wnss-0}RWq{qy4N;le7dB^joO7G}A zMRmUYv%&F)n>5M9JIh#JUe|EBku%jP8-Vzx>M=n2IXcm^{b~>?9{AP+(fwW#h3_0& zsgJ)H6X4VOk8c7;?%#z&Z2XLEr`})juT$o~pFEXF=dt3YL#DsKajG)o@26T<_)bx| zJZ1(s9-(tFJIi`lTu-LQ=Nc(j()nx#QpzW-m$;<$e%|DXL3mHs)37`5SzOQske|cy zNi-KJF+hBrv*>IUCg}i{)VpnR@j^J+3gF0HlR3YJOIizbo z&v$e8O}g)`{Xjzt9!M6qe@gSe|s{B$}-!YOf#&Y zaHRT`Z5TL|ZFe#LGA0QeU3|%E3X9BYD2zd{y7*Zr=yFXj^dOj2d=ccXa!iU55dSz3 zMxXq68l#U5n3O*TGNqSXaF&&uftahI(7z3Y%*S{+GYQBKi!ssLKQYa}8IvQl{S`p` z4VY*RK#tIFvM60)5;HbLSD0wqfXt1L3?AQs4Z5;1y86{v@WzepPgl0F;5eR*38k$Y zkS=d(ztQDQ_qT)P)f3Src;Boa8gW*wqh0bSw0I;yw-r4${ zoEmzr3A>ZSZ0IfNf-R_>$a*M8*lL`oo12HQq0jBLp&tylp}%)l+n9BNqx$vElKSC7 zL(E_s`c>bkl5Zg?zyny$jKhTfKFnd_`K1mrT^^}wFGr?8X?2Zz>A2q?TKd4YQ+dDHe`@JCAB&Yuy#7UZ zJAk)}OAXXygJaR-v337lq)D7!OVpDP?<@=OC999SrWZDH33U`#=w8JdxKbX^6}*aI z((!R1Z08c{ip@a2r+oF~$J35)z+~S=koO^A@q`pteiaX7Hqvor814H_hy4Ba`Lb4J zktx2&TtXei9V&~ij*kpddGx~$Osm_iS7#?M5BTy_yo^B zG%EPUv-br@JU1%1D-x4KC^J|;0`FO|UiX{v89L1$&k;&EXITSsmbL8r&uD)1 z5Hz1Xgx@Up>;DIuj}O@(B80d}AoeW7#8+YOjeAc1IxOyap`B<8b)9GU*Q!MOFI^Ws z#ka~%;=Wd;+b(EUcK@$azi-8Kb2{I@Tq(@T(0ylHSj@1+^IsYIou$mt{3o4V_v-#F zfoHxmcc&_K#DRs$_$(0ao2f~M;=n@tzR~EL>iP^8%{K_wWrX|XES_7#`bLW0_tEF{ zzFnQFv@Z@UzxzUy_Qru_;}@FrZX8&i`$CiU#DV37Oc39W0}G|q#gyL}zAv}&KZP^% zN5|=~{^*!0l>=Dr1+d6r?Yq|l8E^dV^Qto~0E-jAk_TYPWig zi5yH$Vz!67g17vey?PTMKPGI>p*{KBr%Dk6pSv=IS(8A#!gyXe2J3Mq08DLySUayX0#vr`jE{WxY3CXOtZ=ftD$?5t>c8yK7`xOv;TZqdv5O@Fx#wd&+WYv$>$B;gW992)N|`? zgXH%^H}uKx(;wX~_dE`4ZQ*T}g{|%MIv^SBE<>g#+W1RhOrQVnQB}&U0y#4lh_aXy z;N-{Cw2y%(pJJj_rOCiMi9 zM|T_zv!mBv$NWVTuV?pLyy5gP6x^Atx1{-V=7 zc&ZJ5QN>LlDpN2yQ-bt-U^igmjfN&=0w&rG|He;01&B9$g}j+Fv3y>Ae)^I*=<@cCq?l2$T?}q66|A2&iQoi3|qWn(xbM$noQXqSt?8~<8?OKb8 zwiZZWOrq>7L3_J?4@5}-ufj(N{{0bx$p!*FllA(e;=!>V#jaas*h4!z_4DbQ!NKR# zFFO05PdhsMe5vj9e?H0c3DLZjCAjcm4wF*DfAwLfDxKB+SC^zgoqt`c)1b@LFAkvO zXW&A^)q`=Nu~U_lT`XsYxBGQW5)tL?iJqhgTX5P$y*A2bV?B3hT9e|zM0-7KZ~i#M z-s}RR{0)Eb=GuAQye$mESZu|-GQ?_HGZ3p6e2NUHTeJweRUhb5A zD{Xtbc3`6Ip!AX=`+kS^cKtbQEnJjfsz(3$THfhf3&rD->p|3gk5@2$`4H&mFjHq3 z&x}LN_xSC#Ac7t@vh(z1cqXHh+pp{8nc=ePw}1NSbdo(`Fr9qm>&G*9W?hKV@9z)c zV^1#X^ReRya2zc`{e0}(zX$R315v#`_L}QJY>yt=$KFhJ34@;n41U(LHBI)tgZ2gv z0m+Fn_GfDp<7exlFwtw&#&vBmfnyGeTQ}?9$o%&x9A6$|#2uN~{qGPQulgBqhh5O4>`uWQj`gEM#dR9A8@~ST93$F#ynf&i@mc_8YFm^~ef8gDpA?L3j z4D0K|aF)@^tJhsJE@a8HKAc@ND5lQpnb!m2>7$q=QJ(ZICOurVFq9tq_;myH*l&Rh z^M&cL_U57_J1@}lqNWX(&-`G>@CThmN*9njsV;kp>S4+KblFPQZ!+tb(npW$-|Mn0 z_VHI>#3Gsd$_0|%Wg1aRMkkio^uu{XAE6-?O z=Rz?dv@HH%_Fwflr0+s7s z%Yk&YqzQ8n-gSH`+H<@D?RhnuYkS5<@yhgC*D@eW5#F_o{+{bB^6@dRbrl2gwD4^# z-XjZyTM*vG;zq`TFy}oG0&kn-?RM1GH8Dn}-*%0Ql4AiZbY5NGal7aoJukj^N{oUL zxyaOO4=+ZRz>s~%&nqi6RO1t4~Ava`G}M0DlJfi}j2ZoXRBYS=S3yhCweW?>ieaT#a& z;@&g;#sNNzomn4F7D|HJ!IG~tgoelvF3i-|bO4jnU#XJ52771?Bk3A^<(M4dU`5Zi zn`MrF-c8T#S!k1+p56JNcCg|lvv4KnEIV7J%Z>SwV4-+G;c7aut&GCe$H%> z_vMi3$_J6of%0+F^+=>+?B*Btjw4@UoCf-QlMx#fF+%8+?4$vlWzK6@zNV&vIPela z)01Ju?a{GAZE3sTTmvG+f;Y%#dO~ygd)QpQxlW(Up0K$*eTlg^zfvU=pX#YGf%na5 z*vN9%MTX&7B&>KQ0vvST{S|i7RcUo%Q*;>+!Z)TX|t>4o#@3j=o%L96W{foS@#d!uFE}kXD27JKh3@R zAHYJ+zKOx&Wf!!uH64x?_DATj@LUEK|Bfar%!A=EobGEmCZRbUUxwMdF5_1`QQ=G$ zei>otCPuBpjD7cw#AKzh@7*p;{9NLJ$rq<@lA}P#yZC7PQYSQ-P~w4@ zi}rT97qhEt-Cco4cZG7a7F=KBHffKxS5`q2{P<}5p~;#==a)P@X?@c0l=Y!`9v%a7 z;&e@FEdfE}5?MY~U&4`T^#A6B&C|5UL8f}v*^1lcGugxC)9Zm`^435#fFqIR%Fyd_ zCc4UlDFbq_&YODa9IQv|dJfi5pR3rJ#Oj&yr78thVY2j<61lP(7cP5B&sjz3YZa<> zr?EO9RuGkF48S;U!Iv;->0gfu8&Ies%)ev<)mJX=%kzQTvt~7F&81vX%EJio8T$AL)j{%WWi9~*H08Xp_*Wovw_=Py;`Bi*R+@lW?Zn$r7f zd~CpjYJ6O0)1)dM0&84OH{FM$0FHllYfTjHngREv|57Dw6A-#rq5Y@(N^xD!Ws}JA z!cd&&Sv?RP-{~IZtbVw+?p`hr!~$TUXD}iG$>D)0`LxaCU`|-=y(MgnfjMIO<38&< z-n2dyvHK}{9gsR8XIEj;eHA9{5zxeHf>dBqdZT`SaHu*B9VMD{oS!Rq{jo$=p1_4v z&JLCPETr#-`kZ*9CN10_k3(=Lg?(Uh{UZ z0aBS@D_Hu+zT8x)Xq`JhX_LE?Pxa6_)h2^@Zkx_;9x>@Ps6%*|0auOM99Dli+2A*4 z7{5s~_{|sYvSvCs<`g{>u=dMMNpUUaB z)}_38ePHR5f;lsAVL6Ij)_GoYgzTak(HW-rB+Vm^)W z&>Zct_C^~tjqZM|{fCJL4{g9iY0znT)jxF}O19}SdLbTK9O9wd^*TwTFT+E}53G~4 z0~5M73Xgtuk|u!z50RIubmHZC=q5yYXsW?OKX)&cQ|kf^m>gf;zfRKCL-Ejt0X($f z@;vm?b&^sI9{RcaA5E!!JhWjj4?V}HdO~|j_bR!UFQzfRc&3*x>U2rrp0oNly?k*= zh%au(pR}GKArN#9R^?A0i^P|l72iVt(WJd zF`o0QBoKd-uGgJ?%LLx$Fxi&`SB=_d=s2xW(3Wb{yeF*YeX>#WzQdh*GP$nON_o!e zU`>=>NA#{J@X~LTm3mJ56dse^k$pAporvXlV14^nvb%)Fx{{4`b+~i3B-dr4RK|PE zc3c=Ui1(xgY!@|0Od=++19(rG!Fyr`@SgXE;63m3@}4x$tfx4!{+u?M^6`U4ex$UC zdY-lr?`aL=Jt4l6ME7wGCP_=|{rC>d0>Nb0^V3njv;WHee21T?^PMCYl1;rlC(U!k zQ=HgMd3z?1%#|QlCGf#SE0D@;OzxkHduz141>oJ!_2)N744sX_|Hu$J+Xn-5wzTS6 zcd5Z|?g3|66svV<>T(*jf5#SU(m5VH6i>?eWLBH4RC}ylxdNJS_hapcZqWJ7A}c19 zR>S}Ih0bptNe8mT+Q)Co4So~g(>+U`wFj4&bvbt_o^vzfIdP2Vj4^?OuAi=t!l0kt zHWD1oL+NcJF3)qGVtQMe;qUmuy-rT6`;`@w^0VKK)a&RaGk!zqlG55hnrt-q4aI3Q46Oj8kASSv#go(+kc}-UO43j@x)U2y-(xhS@0);N8o65&A2pp+@*P47rY&yly zH$PXUb9|;p+XiHVs#&QleOA@1OK;MoavlQrxSVc^>-5`q6s?Kkc9ntKFMqB|XZTD{ zRXUKDG|fus!cEW8t1ubrJUSI?64e(c@zCUJ!9;7(`}y7Hs?@VsxBG-_&d+|XO1`?j zn9%DF>GHgPJsx1IySX5T|os$xZ^XgwykwgyJ__4LjC-pQ}=M zexKAR@aFJ(etL>a6dvPYz_(HQx3_(+N)wGb0(vZBs)x3l{kbaD4#?3IvSpWiu1cGt z;RJm@E^J)-tY;M_RiU`N7QT(X`))iE>$ADGjxiuU0$@oR@LnC)KR;2B(m<&GoiYEI z0pFY)2V$gAV<2k49PS6O+%@3YeFJhN#SZvA(&)?73kNHMgEbRGdVY@lT$N@R?-p^G z(04myKvawzdXR|8h0pZb59dBpr5gu~Z|a5r!h+DVP#&ZoK2s%@cge^@`p!5IuLC{r zPDw{!-kqyERO!7Ko6O>p?Wk?aDEVz%9&&Fly|7o-#heu|J2C4L*LQ;rtfbvfk@xc z|8F+YIYbHfi~(_90<73lpv$vi9l8&M&fi~dC*gUbY7jKhZ#oxaa`Q+1{Xu{HO!o&V z2QXp2pbDN;&ash3-M+jrWM95Ia&YV>?Z;P@Dqr6Io+7h5o_v%ZkNv+Ufs4@dLB)F! z^ND!2t?9ElPwa1h@4d&O+naZme4P;%)83cw>Y>l{^|QFn@&R$36?S4p>)gke4UX%) z`3WPgvwUD&r?oe(b5VyX(K9pUYaghZ_4FtJUVF6{NSZVmIbzWwH< zeXTWN_wQNky%U6zu>1EdlLq@*ulP)rPSdsSvXOn9CE!Egc=L(!VAFuLWnE@%JB+m{ zAJ|CGTZqLM`Tl0>l?f4_^~nTfzl~^r>#G^s^=I4QxTX&fQNFSfWjJ`dzp(YjN?9Uo zK{QH_mHP2hBZms@v%^NTFT(mfG(?|YA+i#{!r~X+LgdJ&{o@xj7m!f=g8u^>@qOVe zQrF-6Kii1%XFV_DzE4#t&`>7(H({b}0^*x$+Z*^BBL4k|C?6o= zbMt#caavtt5(Lv0J?89c=6@I%r)4(m`R}{ezhPFVO0v3UyYGEZ@uDE zRmwB;k*feK8%Kb+VFZXFIYo6~^8g)4G4!W|PxU(t;rc+_C;e+FL^60s2<>A*JhR+R zHu7LuH3CF-H-?|C=auC3wVvzH?{AF^>n|eg|I>$cIS`U>KXj;)&y^wkX)K6&JXr2G z`VD;-`v1Gbs^n`)6LyUS@k0(Q3yk%J#&4|9$N!>3mD2dW@vOXYhsS7F8n3rI*r7^` z0W80S{_jo3`_>Ls`Y!;>0|VZ-#_8{yJ5;Fxz_Mt-`^r1?_q#h(sgdiO|0~>pdBp1N zUhhz)1ppQY4E_F(#`{n|1KYL6=BgGr$d!Y99W|0yA~tYD%NW*t>{oC#DPUaMt^HD*)$f!3#f0M&qwMpegEB|O1WX{ zpPZmSr!xP4!k+ge>v601bf}Uyy!~jsy`w{w)L#8ILZI(YW`fw1qrbnoLzPOx#((&F z{rSueRjNT?IgG$^kn6*%CpoZu9M=9w0<5Sm)O9_vU6pF0;o#}8dp4C}_lIwe7@WVe zzUq3J#o_!VqAzZi*YDU+p5%GsvOKBxjv_}PCBlsBEI;zX)P z9;I_PVwC9S^=lM@`UP5uA#@JiZu1ZfMusk^cR$15Su$ui7 zVa4)zZR~?pNkkv4%6|r|8it6C{p%+~!|IjG!0O%h{<%-@IXxI&JHp^K&4AZy?W%Mm z0!zUFcx|~#hu6hJI=p%=1FwPS017V_8(nE061Nh62E6Ro42IY0PgH5(94Nf*uHwYT ze(*}_h1c={@VdWeFuW?l;B~^F<@?)J=?4JI@i3ad1%X9@0r1Pv;rH61pG=z@vwnMR zpFST3zm}ap1AaM!;g@>}d^2AL-!ccl@6_?Z@JkGXU%dgp5$&q3Rf;ldw}xbAWJvC3M+-Nx8mDQV#CKI@?=Oyk6*f&{u-xCK-xa62^Q&#T?#%eu zlQ*&YkXz&QnzXErC9?@wJRe+T)TMpr9$kO_1M00y+tWsM&$3<}=QO}%I!~&T+JwbRRG(USn@BFrg z=GSD*?}fhkeMskLzjg5Z+HK^@A?CNIO_j0^=`|%@*EH+z68d!K=rH_LDi-Q{zsgQV zQazfF68Ni-==&#T=c)L^s>Jk{ZXNEwZ2M_4hT)$GL-NQ+cKi&PJj5MUU;EH9rui{W zJQ{uv*xXl_zN4)_4zD>m7>7S-@5A8*%-;&0);3kTBh2nc*C$*FVkm$0-gZ^mN8#t! z;b$@6*KNR0834auMSx?V4MvlA;@iaQ>n}yd9m5Ra2?K^be1wo|z;OLffMLbt!7$v= zu1W*vLFc?Y1jF*dFno&Qd>!7Cd|?Rs4}+b_fZgggRf^IyD?K;%!mr#;q%k1=hQ-Jw zdwv~)-w_>te>wQmc&J_{Gp85-9tgv~FJAu{_;jbrtJlkUPYoddIPB5)iw z?3<#du{!Pm&fkr`Ubg`bq#gSI>xH@vurdvkhokg6hKrJQdyEAz;oJ4P&R$JxsvL<) zRdV0m#-#~^?>1JY0jZpz-zwjiYHw)!6q>G#U+pnYD2NmX80pJRsT za{`c_+e+j!3vBYmH7(4}qqXpD7uT5O3(I5VbBkl;V0oN;W#UCw9_#*Npc znphCtb=@R4@}q(eMC<-`+hd$a$5AdsPnr7NfIfL-^qEl*WAwQ{4jh%k`f3u57_UjC zJl^%LYnt51XBhpadd5G-iM|HbI*7`BSXPc8Spx8O8g=*Q6l#)>*K?`OjR5hF z94=hT;leF0Xxqx8wqp$-d|d&;H@qG*ur3|M9v%}12VNyw$DK@MVKEh_dvl5;dG;Ci ztmLqqA`c%ja*FVn^h5($LH9fnlZO!W;^iaP>2Y&I;iaiilX@~Saq!UOvtptdKGE_+ zs?^BeYuKrN5nRZA-)HFP zFu#p~he?J%^Z77;=8QxA{h78y#@!GXv~8QDN%cHxdu5VdABv7&%E1&XfQ9Ap<3ZS+ z4&vEFOt{`>R?mI}Y>y76gBW^F*U|`(Py0{+^6A|Fv0Ihs+O7<(O^ar08*QxZue(+0 z;+l8mbBmE2Ea&7i3wXKbwg|=#5`T&196s?t+QsRcN~1wAUwpJZ*9=W&6DEPcqr0el z&qav`@>tBZp3kco#Rklv{?2rLt(&%gKN^~nzkjs-G|#d7Zb2S-R_1BaSspxT!_(H^ zwE*NM0Phw9ue=4CwCTUGtZ>QeXWKz2<`V;pBET_v*pX@Ue>`mSwBjl~27A+;Sax3p za!m}7eOw}oFJ8&(_U)eArpsp**yUh(iF|G`rS-oy9&1yrw4G1Y9A3k}5zgEE*It^p ztt!xYTWGxQ3tH1qV^Dlp)2c~NGyZz%TI@{ki*%MzxKKT7LY^jl@JF5hCJhJD%JtPK zo09ZjF+{royj)n!V&pJzn9f(VXBu&f=4fckSOJViO|%1>aq6sa`hM@ zC&y$I<0*66^cbSwM**qj`eKNVaG@9?i)Tr^jl~c(bC-@G`Y@`03=v&FT^of#cnncR zJUC#8xW&e}%f}Gi$6|<*jToX1_c}Sb?isFs3=y5fz!;+Exc)Ij^!HDTAxbu4h&tT= zXiDylA)@^aj3Em0$)2IsSYzz-WFrQ6AE)D=9P^ob@+T>E>o`niuYNdK3*gN`m{f9l z?4qByc*e)uf)f#tWgL*%t0xDSaG1Q0z?*B#HAE-5$i(_CHgG$~{F&SQicTZuc=LMN z2i+UG$2AF5x45)F$vIh*j&Km@c*5zX_%sHA%;SsB=Om%?PWFUygq&W=} zArZvZQTn`FM*$HzOnM@~TU`Ro-+h!vo)d{6R&NCX>Or8tCntdzTG2?+2&T9fq{ zshV?IQzs9e!Erm2^xjBQSaBqULpSi~sLDl|cjIW=ltcqb3U4GEn+Dk;#W-Pw6mw z5ZOSe&qi%2Rvm9L&2X|l2^`&4on97Yf}uZ7OJ^vgB-g|gV(yjup z%??8SG1PWC8N@BeP@8WUCY!7v5*|G1CQR1Eg7@@POel<%YcZL$76u0#>9+hA4vf^2JNTTXxlTO zE#*^U3?`J1l^f?5`VC#nBGA{-Ni+vtD_y65{7l)mW0tIpi_Bo* zjoXYts6ueEs{#o<(U{CeweHidNI8%X#EO7SLO|vq5Vfi(x#wCSjr=`^F1#=(eymE3 zuDc3ayQ8PnyY3Ed{8*LhG|j3c8vB&3w{KLV^Ur9S^#Y&nsp2h+XI91@c4vHVsiU}I zil@58qrp<+7E7I9)2yYu&RZBhA46@w zOa_tS@Rn>HkC1^!CKD#5ao`Q%*ZE}Ken+4C6ZPDn{%jyMv2>4-Kyhs0S{ziS0--RW zd!rNs*#h90&+ut}6wWU1Q&!>CV#A33P@58^3=v=~RTmulB zQGXgg2Oy3{eKa19BR(DpcO-*&E2XKh=W_roAzl#vyktPTaGd<{BONCzqk-XM;3HKk z0I(z`Vlux&^Y+AI@*;~jw0H=jut;U+%o^hvl~X;2oT}=TQ;C5G4pTa_cpAgvd1sE( z<9R0z2SV|s_)(B2nSgBJfW^tDGRBB4jsX^{>(8DgciA!V zXGh3gMO5znp2K7{hsjw!u^)^ojb{`_-3E+~ z{Qubd_xPx)a}OAQ*4}g3Ga(@+lS~N6go~O4(b{qwC1p(l7(k&7qo`Gqz&R2?rE*b` zVkXI{O&Dz*8J(K6CQ2={w{j6D2zrzNwvAA&0q?z#Kx+p^D}-ETK{EUIS!?Y{W^zI8 zY0vL{-_Q9gnSEL7+3WJG=lMRjzA;J<9qLt`^nNgAjC!xs#z^90G)?n;Zi^kGiz*wV zHUX25*|~m;+_l6hhl>}>7giL>J!`%%_ip;0tXAonZk-&}d9T7GQ~TdK;4i&52Kx12 zy00T?;2o*`rZTKv``@7bHOD-AJ`KEdoD;NhHUW6)S@%U6c!LR;j6&QWSOo4b6%Isv z4G03UvIp}s1xzles*jF)SXF(ovc>FoBUXkr6`+>hO-Sxe1=1(474TZ!R0g8$s1v|` zAPI$YvY0+d0GUEf18M+R2h;$da@I0dQw1q?SMoXlB?8D)RtpMJ9i96MGnQMm9DRxf zyi`w&%2mCa9CCLmCTam<<9_5VmDwg9F!1xYL&GBeV&S;ktAXKhgZaOrbR&i8_=V6f zlT1mgtW9GwiAAAj@52&!7fU=wxhqB%$)NJRu|H0E6iU}(c+!;<0*|e1HXpAY^+{@7 z@ZpW&Yy$+W2otLT0uT3{C7D}nXjI6d2WPi{$#gvgf(E{ZkqFMy`PhCYX<%$lTIjim z>O7NzNoa0=Y|csnrcV_$e>lP9cE`l#jO&e$&7o_K(r)VEyyVnHwJ#3zPpWF|WN|wd z<)oOV-2RZ@&AO;grQ_Sp@&Q?g#4Xsm5rvlCO@iFBMwBnC(8=Lqz1+3LAa^V>%Dq+K z$^8|_4!Sg4GCJnd(<*8+`eMX0l*=XXZZuH-2g>b;$IeB^eKcG-w%o|$fU-4=fbtQ$ zh7%kRc$}Hv{7G%*2czoBG@O8rzXf5^p@+as4JV-b#CkoiYhy!cEM~KO5MD4!!wWvC z&3QTJ=px`Y_!mM^d>3IA` zeMFG!$MRVB)62nLe=Co7-wzNNAA@_mAb~UcV)^k|8t#!}gqB(VL)_!T>p1SQk?ogJ zA(>rIRVba`GlO>wfMuBoPD(HBw{!p|aSDMmYY2Tk8(kWcp!B|aU965gDpb&;Iw>95 z?7MgjQFL9>^+;tOx;8~7Tk~~Eb@}X#5BJ3^)(AjSDNhhFv53I1ni(6f4^ufH0Qf)$ zzZx?X9k=+Hq4@R5+D(+)76hbB)A`GifMJCli*A&=mdusI#dG8fD`v|*Yba06msL?< z{B-iQst-las|n!wPAWf3{_~aL`6$&JKX{btF6kkc8Jv`-(zR*L0uNnZE(4W+)0AgN zg11^b1#F+J2Of%CM0$vgo9{uHX4TiMy3qv`1;f$HfdCFe3;pNF39RGy@A zD7*hN95$(HV^FjyCZ+?~6e3y`+KyiPO`j9k|DzPD^PCaWl#pmrs62T=!-0-!vgaKp zOcscklp}NKjF`z}PyYqAk-jsOtXgP_%Bu8vO;#1S?&P5RO#o8zJeKJgNP1|YXWZH( z@E&*s6{!+~Mz119aZgL`?P!z!T#5Yysu7qTI7aCtp~hm&3&dxoe40?pP$r zy@xq&I|_pb46dSXQDAW{2PUdMMZ<1e|Bht8fbFe9Qy!J&qI`I2+EcaZXiF_fuDopK zubZy4imtr0+YmdGgWJHq*8tvf0c7sil&$_vl$tb^$#@AbsmFJ=n ztqji%nm?_z{y9^_b01`Ju451;cN!qjDmLZaW`q`LX2!yx$m3mqA!70)78im^Kd;Uh zCcfSpLOO6(Go37*VY?p!1Y8MxO`a6fmFFJd*lvf2i8>PE>@`Wb!`o|q@oiPJyA;Y@ zOKz0I#dGBgE9S^OYi7&6n+jyLK=7PBIv5ik7{~s%Bybj9EI%HNWsk-rUy3)TRcxvC zYrOFmjW-_XzN+|a)H_{@oeG2!1F<(TkO12EwO8YWEl z<4O|*8ZLnczi8->V~^s&#Y5o1Rf$8#u{VDO9$d`u;503c{e#+7a$236>IN}*@Js(z zJUC6mgFmQ!r!no4crfMn^cz_{9)t%EzlJHlxp=MW zJ0L))vC>sb*VA|e&Zh=o!c&j(xX*e6kVC3!rE9NARjpqbz{_~fa_}sY_<7Rua>S<| zraVk9_pC9<7giYMaIqwJEiuU*i_CIw0rI3}-Nbkm)fMO(tVG-&$1eb3_=5omJv-4j zZj<}Nb*j&w51z7RKI0~T*|$VZ4(<|diu}dnMb*evRP)l# zwOe*PR&-!pf4j6j+P1QI>_g}(O#afN`Z^MT4AuUKUdQn=R8w1nw$xJESAwgkx?6oh zdS;}D`D9|fhmPN`s-We0a20JE?JDwL^<8=Wc)e$D@hrJ>Ie32XYvet1RlfY9fcFHK zWBX{0?uSrK?IZwBQK6rT$vntREwt)nr>%4C>4085W(RaAkm zC(5(O^zrN;h5ZHyq#@={5uon{jht6E3YdJLhk)O}ZEG$q2NTOpV2sU8FpzJLVSHQ8 z$983qj6I6wCQwo^d2#O0c~KO>D&Z7FG>c>i;}g0=O*Y#z~tgcnCjAUJGGBj zeL*YNLsss=q)W6YtyKqSZd|7KNXbA-S2^Cu)`N%fXq_vsVa0cu{Hv-+R;@r}(Kf?& zC&&YNK9z^RDbLTS*itKLxdd+0c)qPKcS(klaxKrLK)zZGHJWT0`&EXMUOLPrUd6=#zh9PNd>1`$t|EMpf zp3a4=*}}3#Os0y!uF?H(-#9bu7rt2@kGD0sIE~81doVe@9NQ`Xy8%H;*&ZO90H(BB zF%ge&pF2~|d|A2z+o@dF3gEPv;QmqsPUY7QnXbE%LwY9P((4sM%yq%&p}e~9_cDXW zpWn|%O0^tF+p3`DxrFb^ss!E&0TXb6r(WWCP~W@H8!!2;%h>BwPc`hcthKSiO6#Aztsc4WoAt zHP>H<&wMgD-ZoA745dS2-^KZi1zGt1*Vah2`QuuPwnnlyuJ6;gWlg4v@)pilro{1; z=y=8Rm3aS=m9cy!M&BN&Yg0Y@;%H2wx^~f|cwPHpgI1ejSH!1QA-0F&{Bf!{ek*Bv zrdg-?4-QfLWP=%#@<))|C_PEAsROT<*(%bNy*+B9Q-r_+`QVvO*OtLmG;W;g zqy5vp)A~n{={Z@Qf(bo8tJ5)&Eb(&OUDv9<27^QHUJmxrB6trlU6c26PFbRLbaqFq^3 zXS6UsjdTp2*1v;nN_5PieDH06=_b~8Q{LNVAWecRkMh5|zc}Lg-(2wcV{pf166b#z zjQ?dQPiLto$@K&mq_@n^=bnfI~*d#4b(mM*DrpSMgZ^i+M4|IH+)V0 zXlKN?Kmczb6BA~iF~(yVf4pLNEMw(0s;^ngb3*Ap^gG^9)9-lO|G6{b8|a74eLNA< z&wg>g;I(0R`J@0&W+S?d%lQ6>ZHvp&VTJ@?*_(v-G#S8id6w#HHiKtFCCF5-Js*uj z(d-RV*9zY9Ra0jS^na$$=yO#cw@t-hkX7J``Z&{bIO^lvD!TH53H%(M`W|Mv!2gPXaFpHA3R`9lpO?fqXIGaiPR{BTQ>Fj=mRdDJF%;+2T? z>%QyM-aYn8d>adY7qObMuw9x69`guRmv}9pEwxeKq>e?X-``Vk6>WJ-i$fAE$_M~& zn*p9UX@Dmf@0&S?USlLL@WTPfcHhOuI>f0$6hhyy$ zCLQ<3l(M-$=3O=|r<=fW9Sjio?6(|y3mbtvV4!Phuuo=COjT&xiHVNz{!2+MuJeIr+zKCGRzBVCiPCWZGS zOzb1LU*_kNkgNl+d?Aif==F^W5V*mJNwJ2jZ4$LS-&)SYvV;$7M}LuCS1u-mN+K$Y zA2My+6n706Ah<9M+MYkjDu_Qk5PVNvs+2-=;0ilr*S&)j8j$TNmaE@?@_3eR^%>9#4KPjbjFRxJ&Gk%~!x%9!Uj zAE#p-s45QUtSk%XXtFFD|CMFoQ3%Kjs%i}zF(G2Q5<9<{bd6|Oe6|rYn6HO(pHHvPoP`ospSIR#K6gQNUacCZA6HdtI)Xsd9`MT_3SK%# zHh}x-b4OLxO83Fr%*WTJyjWEnX5XO4R0d&uBU{5;2ioF(jv!zXnZ8L9L?9~>Ci8S0 zucd7i3gFCTc&&L$DjSPbB{$I#UWI^AnQ#&UGH+vcxD4_5B9r!B8RGMogQP7Z7|uIN z!;e3yo%aGAKPhw&z-f%Rmu>o_*7O3O*MyBZ;dotTp4_#hP!1R0C|_7HSMFIeNABG; zTUM*M{Ie;S^R-x;XFdYwt)Hlkl#i7QKuQ1tf!{>fb40W$P(>h^~(@?t&YbFztQRz3J_SIiOB}K#-U$+d2s@lugWy}sw4%IpZ|u-S3}7(Q?6Eh zWij#?hzFr3Ry0OzcUa89&=Qv&2R0Vb1n z{PB*Kr5d87EyQqt>$1}<>eU*-6+XD`|^y1S6!a5(9nJ`uV8G(!tc%g+kN@7KfCY8 zv;TJAf6e~vzPo3)-nV>q+kLIGTkmU|-F9F8nB5Dr#xyL1|2nyF`IuiX{I4-DEL{Fy ze_aUs&Mht7cW&tjxck{0xck{H$m}jelKYIQ`q*k@a+}*>WQoCee2se{Nrpw^Qr*gh&mJ=!f3-b9NN}Hi=fn1i0&+k3#?43OJ=xWMvygb? zU1V|><&?|YHcNGGNN}Gsnd-*rpk>@&AAT}XNOAx0zYC5$hEm)+QIb3P5vlHP$n0)M zI`{9<2zQZ?>^_9_?lownn~wSFmyd3J?B(BYExPsC)_muot*epF{TNDe--lA%ZX~!r z7tzt{gpuw&D9JrpNOUI)X7^>fN94y4dReT-a`L0^ZGCr+sZKWnlN|`T^%>=Iks!F& zz)1Iwr{39m1ex7N-R$u9m1A4?Y&O-+M+W!g@0#k0goGoPJz}a`jg0PVLGLaF!97Vx zaQ^{~bnk`)cPT>dWI^Yik5b&bQL_8w%YWE9VfVqUUm}Bh{w+tgCg1wr)`gJdUJVKE zcahnh3p)2|l5ZF@%-<~4t==rv)yy;1&3|M5k=1W3I5O`FsczLAsgCbMDP~VfY)@uymg-tXNnv|3 z8P1(TeS3U=-?}(hyf5ee%NNr%6jm(BLNLH`bWOc7#+HyI7 zB|m9++_WlTXxy~fd}&#I5r8EurYk=Hu+$4&&aN?kSUaU9Dzi@s-y&i%RpNQY&ujx( zr}@&+>l=&^c-_Edb}H{sop+Nc4I{T(LO4cluhBuk&uzAWSCcR?C1OHl?r{P*_n9&2 z5z`bRO3Ft7fpG~uA1sxdXWl1xOGKDTW&R+QdlKohqZInCE226DW{*r$3dMeTxIvSL z&loYGGI5RAFB7LBAn&NEHFM()VftMi;%Mb<=KnuR`I7mqk5ay1xeqX*W0eeG`EK^$ zIH+k~_RBkTEj)CX$3c~A{-<;uQ93Ra(>NM|CUb*g6M@OxlJs%y=!y&`n^`t)3a{5g zz`xWX_lUOKbR)C`6Mz`GFH^1wK~arpGXFx9a%bt`{wy6hFNhY!D`4`z$bA`S^~u=j zF*0^PZk_X729vQJ0+q3W$=ED*4_QNPJv{!=WyXZgMOy+U_+G(_0j9Q!wp=O~({Bt~ z>ofn%{2XkGU+Xg(>((z1$7AKS2mi1xL`S&H z2rRbC9D`q&=swZIxk3ca$F#W81OQ9ye*49th>z~INz4z(qQ!;2U%N%N)ZL@Sg(hfz zK#vXZ14=?b?i=6-bYGkwki`6ef?_XPuy*FQib!c=G2EikDGJJOdQ>0P z%R0W6e>JzgUa8q$>ox!CYV#+xnJxYP)y*RJZ}*A){?*+ACRUOAwA+y7Yx`H1B5($i zxKDOluj<@jg+Qwr6Yj5(rUdTcHMkl9EMVk5(Lc#leRL0Zil8(JO?gpUY3nI&E4B3q z%=TnU213u()62nb`yR-HaKYq%y|40%R}S!19uT8_Tjt=s)OPUFa)wFs$GcQ~_R#_U zc*Eg=MEoL;wDz~rH?h|j+CKK!4@XWuu3KOPa&m3aSbzOL*0 z{Ie~*#zV}yHf?-3{I(XC-EHK)C-e-m09fewr-{I>)AKB2XowE@df z*}aSTfJvcB0OtpfLYS`28v!iq1x$!wIXXiv*lIF@C%1R=@iP)MO2~3F^yTI~=HC3i zdWSZY5R#zh$?LDHuKg4sP^fM`?lNe6P|K)hV}+XL}(GcmWd7oZ?7nAaL z`Slg_`XNl5BcQS5HB8E1)AIk*>pL-dpI-kpCgs1@>VMJe&&T6{|8cqMYp_9J!;_e7 zNP@rvPjkKUgpd|Gm;lauG`;ku13drNQ{8HydKu6ERj3-LxzaJ2b0FgDR(ai{eC@fk zA)dP-=D8Ws_PPc?cU{bL*F@VJ;<>A0o|_nLuTu@UQZS*MMBe zt`a(jPXlRtGvX^bDSDm(@RsC@9v^^r!&2s}7B-;=A?2@a=59L_6bR+Sx?u2@l^+#U6N>BIj z?X0;(JG~QmJ44N9*F@Dv`9S9hweg3;_@2d%^O=dNbtv9ykudQh=sS~|#Q6EKzZqfQ zF`ey+bmhZ{8h9#`=W2-N%A?gM zPdfN*cAorP8FZeod(rdc2_^nK8S!SsDm~^1BZNs7*mzqN*Ri&KJXBj1*Y&lvc|cp_ zjfgb|sC*(M-2nJ}qFR8BUt zTsbv*mY>N|j388lm`&YTt;Z~uCdgv%P0CHB*j|hftKU9Z!sKQXkZUANs4R8@q0m2! z^_j};*MzT`g5@J7APc90d^12mF#)jw3QaD-c8pxLH1u&#f&i7B0}Tk0G5yrrqK5$8KLod0LubB zCZnVVlbZknTeR=KNBjFY!i36wUl{8%-M3F>z7Hc1CJPw7R2OsA(lMZY ztpW%vD8+WS0j4DAFN&%+O^+MOqf>N;4_Dl%KJi5kA zKujh~=4pQ?v3Zh0AyHB&-MP149WK-ZF`KwOg04k6pOe8=G@=ySO?pgjDg}Ek!X&X2 z?Dv*}oqpeZs)w8Cdzj>Ee-}jCHr8j(yM0nP8}ZyPl-@zKq8M8B-+)$h30jdxt3HNS z^fhVK_tQEHAQZILXJ(gxy+IGoT+J3}LlA1Cv{>sib4$TKq7>|_5ZGNhaOOyuWS3%l zwhpFd_w5H0TlX)D5V+@Y$BYpXbxNkTw&-}!Yxnf3Q|Q>z{Ru{JQranPlk~vn*93&N zSE&7swoBHLbEA<5m}922pB1tyYhfIvFJq$?(82tB7C&_kg48)6~{MR2~IkL^c>$r*Aa z1(Tx#;u&un!{Y;vd_~TXj{z*<%>JAqpWn@Mh8)vsyg!r=o&y$+VfbTmhIDB;LmGsp zJpX{$rPn`Y1v`TnoKbiOJ^{&T2 z48U{_48U~0NsRoz2h)j72)ufuePj*%Z4(@Fcrm`<0G@6Bi&*V|f*Xqg$4 zW-W);17?orH2;&iQ_=_JPD%etOy}EKu`%+a`eNi`F`au}9~#q{*sc2By*xhlqeR2z z4bOkIZ_U@`k-zKw{~nK=@ilqmM*x?4f zKRJ&)Ev74d{87uRMET^bL^1q!I>)^!ul(QOkB`_c%^xSF4q^X)?f>}W|MAD6`Qw?f zU(FvUzBV*}{8Ojudvr`Ze~e<^Z#E2#eZQjN)j@zMC7GDK5#m0MQQX?}TD(55f9pGt5IXm7GU~7zn@moqWon)#~n9B z)PO6K&c+{W&5pZTWe<_DU^-CnN7-%*9%gpy0W^~l!*7(?t*hc!Bu3P zTEk+yt%B=G$|KWKcpi%YtDBRdMCtg$a)H$nsM{Z5JTzUjxYwWLF@$suP6%M{SX3Z) zEyR*kH*@q%{ zuGIFxpXvw4h)P-9UNjKHvjC4#rR#XAsxqHNdgj1n*f||$JAQM z+|O&RP+kTIlcx;v^>R}7N8)^`r4nqfW_0xXVwoDS{2j#euGvs3%LCET*DsZKQkk!5 zO-#Q%`*^=}KXoSniQP}kKQ1N?wc3n{D`qZJ0W42{h~*P^aCxEmVcTMc%UXcd(>ak3 zFCWr_^P?oZr_}(S#dOZh;CVosvqJ_hE8M$W@KX9pmVw9gxMRjV)E|3ol7Pu4(S6X( z)+pZxPZ#CK^<8o|%az1r725ZB0i4ZAcu$(1=hpwuWvb6F;5`orf=qe*AuR@WVB7PS z3oL$T>}b_@`Dm5#u?}9_Z5rhxyY}(eP-lI_H(Xv>x;GjO;5@I@8KLi|Wr2s+MwS#h zKMi_tzLkQ>^UJ|=Y67K^=V$!~fS2+zdfvTlz$8b6#xX2M6R%x@E>nHYDVXK%mq+rv z19Y5Ph5o#I^xbML-><-O+=JpWU~>OO)fbzy@a-Y;Re!9i*5XEDL~IWxQ2q{<2S3EJdIy{f0yu+XA?36Pp7f2j#aRgN=@R)m zQS;&DlV)&sX>rm@GLMt)t^zsza!3h^Ku&7w^zbsl>oQ>ZqzE3{87@mc05GjJ0h8Q) z5f&5d?OvZeRZqt=RiSJ7G{AJaj(J_i0rV}*|9bT4`{}D3mcCS_Zkgb1cr>5U*L|AX z)T8tXbPk>ePq_f+yh3#?_wnKRCa6r)JsOi}z6tsr(7rx-j8*lucBoV6?}KO8CkI8O zuzP91Y9KDVur7I)R*NAUfc&vkU^No6&aO``wyM6LGu{iHn=;j5_er;QR$Fvfj_!lM zYBr#&0laB|$p->7c4=!rKbi6UzO~=UeR-AW9%zc$17+GCI4EF3*Z!Uh@oS&T^xvdj z0Obi~m&n~LWl`M>gE@?)X906!NElSFD0G3>Y3H|OPda7@lmHC%Z8g-#URdtTngOlDfKaRt>s@ix3 zv$rF~p|#a2itPVV?Kh=oxe1edAWDzO#;hD9HXf^!IbAYeTxOj9Mq)6^hL(71nfU>kR;QWM|?1QWor=s$;qL`t-(Z zO>cY-=(%lE4hZQ?h8)kvAWivvw6^z|9+@7h7QuN)%MWxSY3TewO~OByAE;$?td5b+ z{1l`4J{EMSJ};GxAzD8smDP`VR?8`~UR4_h$|Pa94phqZmBfa zW5@#gX%Q6TM6gT1vG*)!%A@-ZbgsNvJs{5lAcYbpm|hcXpZn3yL5IU|Bnt^=}qgd@BlQ6IiX$8Bo&Cgc4#Uk3Ysk03B&A|`Z?Jg$e9dX&g? zxff9akJUjVm@ap(>G!oS?if*L-Z&{-{v(j-JX1a1e0F;go9o9Poe8d=%ydChp1B(K z!$enJ{f|H{PcnzgBOo_GQy!IP6bX}6W*`T8Kt2FK%!Qbo0SFAY-=n!Df<_?nNFe84 ziLiBXuv>j^-1=0{{4~|)H^5oxx;aF0fX6QYdCmZ5pJ%aVY09`Mb4b2(4w)He80hz~Z;a}r&vXd!{wX7Ao4E}0jPp-1?WJctwwLK(I@R_3x}kM%wNcZ( zhp3qtZj2wljz&Iy^u2S@_j(4ucV@tQpK0$=-Sbo<*FF6gd5n83O@C?}oD1fe0W}PrW+>!( z|JV}nmLQm3E`YuKB-N`I$z4kp%HiUhZAW7Sn+JDu_>=wkm_Je#zJ&?#=_R0z>Z>Z6pQEjPXrd) zcWZ(xk6z2V8l3Cbdybty1)lfkyxMNL>;3liEq`lgHD@Ma(s3;icVooYFacVqKAj+d zmp&i+>>a0&hql#}1J1(34tuq#PH9bO%DZ(rc;;<$*rk~n3)A54XAcNcs78b-m3nX< zh=6=R0D`Ly&TJ4|d4*O?{AM8jWyo_P0`ds~$bkrw52ORZBb)LXDl2BvHs?*i1TL2r z%IQEHRd3BKRzNhjxd}MEU6zw>f;L3ZOu1#Z8-U90{k1bgLa{Gt` zSJBZqAGKR&W-Ls&tF>JgtVeTt3%1VKY^gID!7~dbgvus>Q$p6GbiSm`mO3*j@AKtX z+&?{*`u zX|4m=b4!tDTm{;Jjo|!T%RN79^9{1=@lR*gBWtMS@!FY>n=qMNF*;n|3vxXIQodP` zT@?psmQ+;CtVzRUWg3vvVuDgp;n-2XS&-`!fjsVT*h?$Wj(Z)*UeT*M9fPtVCy;OVddxe0-{li?iJ5Ej6>Pq;H2ScY0MR5jqQyffS?X0Vu1 z98sMY`}p{1rCiJixq4OS%AfV~@x1}g$2&zU%Uu(tBP)iEf%|L&!}rpZ?SY7|?G%;A z(iQa-*wq5T{u+QcSdee`pHioEOv1!_QVj&J?LS+Z+SEa33$&?mXNyOpDJ`nXQ!-GZ&;` z5~BOO!m*=xvmh5I0$Jd2*xM@6j!-_bm-ed8aoV_1{?$5m@Eq=~925RQ%pCp^qH{Qg z&EZ~c4%7SQFkP{sbT)_GedA?SR3V+s;pv$1n$tIjV_04N;b<8+k57H5vU!{ui1=QP zsMg>}ykA|X3%41Y^3?NU__T^88k zh^W>N71h`FrRsZMQGHRqepwW2JO!Rk8<1xKyomsogqZ8yHXuKbsjWoU?qz|9PXw^^ zVU@REwh5WJskp;%gG_41ZKPCJfqG(|%n5-Y#ve zxgx6bBjL{Q2g^{4RaFDcY^<${4O!V(hx^7lL$QfgHrA$?{c`4&;c-N%#9^m;S5ApT z%XMa2T}t((1eikU`z`{nOK8gL6jK!{hf^KB%nYPH0&=|oWbaQM;irudC`;ivAL;zN z3@~W^o2dRAGylKQXv!8~%K9Ws*7vo+_gsTvusqkQkC*2HS{qbPpn4jWODU~G(ODir za(OxsSLMN(C6yI3tJ5(lO9xU>>DW>Kh#=P|0jbV+*h?$Xj+M)hy(}NuGub}Cv zi?R2XFGKdB@YA7eC{zcaa@__U1fDiT^#JadP4(f4Oh=*Pofc{p!TC|;((n=i0?k5k z-+FPeIwtY!h04jX>t(4nu1%Fo!ygH@@Exy2e9gk0Gd{{kEmE&>T9a^B_?A~9zP~Zq zeXtEA9w(2#f8#4uUgSCWx+l@KsQDF$$kQEL@2ddpYP8;$k=Ofb)q(T$--SI=&+M)8 zGtacAZ#LBh{|JzxaS zEp(g`!1G`wlId7*yfR%`bC=+4s5~^YC|J$zjc#VhIlTd#vaT8s`( z`4ZiGHa5SsUrVS&1n1t$rQurz2>2O|8ec?1@I{E{i{%=P4V6p7dj(r~)1HXWFWfm} zuSR2oa98*NjYfl(uYj(l`}ahA<&S_|ZtmZ6vHawpt(7)4t%B8|;Cg^nIrh2gdr0%? z8JI^sn(xoAoL9^n6@9swG47>EX5NMk7ov>f>vwZ_@Lc>QSGb;;*c& zK8pGDtSZ3vl_N1J)bjV4P)+SDWMw`*t5Y#qspap>Lhjlv2&R9O3;`;4O+w7)++L1G ztVTVmQ_{n^96fmE>v^ul9|2e%92w2sXH|CI$$fer(0qCx%m+_}neX?gKTqcgkm-Kf z1aQfm>H~8Sy&(P1a}XJ{xKfuESNcNw@VV4&U#h-;XD;Li+qo z_%3~qb*Qw{eX2aF(^be}rnWok4{GfK!Cuyv1XEZMURS^QO4XE4MCh)qQ9|_SI z`Sh6B_f+P0cpgP#-z~~XF;)5T4|ok|lU9S1*MLsbYCwNboBdoGs{#F0wKiM7Ms3%U zO7I*P;(e5k?&dXK2cG@RRy=~9qe$^12s~xRq*Dit)do!J%|L<>tzS7fS3Q-p%c64_ zQ&VjB?uc(?k|Rvl|EkL3a7hY&!<2}^<_cSQl>w9TN?RB%gE!22AX@|oY%ySxqsL@{ z9$Jb~!Wkrhb0souNzrUczt|n|(KG#li)x_ZdGPENFiD~EpymhFkb=q9-P{jKV!58o zY(6KMj?}Jv!CXgaFWi_DrswiNd1gqA`)bT_?QefGTzl22b|$O$I4rI$SXCc=hWU)8U{apK$M*K!5ntJOY%d$eXYBjC`+dd+;?MJU$K%g) zcWd}_Qas*_cSi=<1?d`TX7!f24Pw0jjb(H$W7fz}^$g0B;(c_YbY8Wa#}9V(4jn%@ zIcaeGVCL@O;|KSq$Hxy2Ij`B6Owq;L1N6Hiz76S^G$KAHw5@uow*ff4<53Hx)r`PP zuhH)*NylVECXnu35nov)wg*L+vfhA6K!gDIuh6h6k*}8&O*aYc;`1_f2)n>vcg4?3 z>n=Vo!`YEO-ZhLJ$$-gvbG#kton6D&k-mld@|dLQ9O0iLZs$Cx(RmBy&$*bC=kjrS zeOJV{er)_Z-`Cy=#J-b`3DxiEJ3Hw+=6HJ*ve_z@}ZBBECp3|owW=^lfWJ4~HN=k1gCSC&sHjL$SNyonpz&V-fbCsjR z8+UPDMD+`*2miDB#fn|=`o;2HRKK{3=@+aXgRnHbbXUapk${P>M-A+&`~k-fL~E$& zqUy|84lPvP2^)dz1Mt%8rK;*|5-|CY?&(ZS){g~pGySIYcph|XBCmHx`A85^KGJ{I z^lozW)i4-}Fa0S^<@_gNoW}Xa;CH{ZYcT(a?!VaeGp$o)vcSaH^%Ju<$L@;w=z5CE z4w<`RWQQ0(TFb78Z-c;mU;+;q;$!5~wHWylVdxn7)WqRqLznmV=M$HJIGB^Q+INWvc2M zcs?zn^N|w2?{6Eyazh5F?C(c|*WOTjpw+^41wY;I1ANS<4MTt07>(ZXL(@Agmfo?L zY#0w@!cNY6W9hwmgz9Ue?WADh75cAVIYRY;Fm#T~fJOBUCsXaPsBBE$?^PSwH^JaB z82F97JBHau6S)jT=`SD4_jUV@_&xED9o(mLxPAWF4!+Mjhww2tu_Jz;|8a-5&j--= z0i*Am=|}~^|9u_lgdlyTjx_VOe~pf$7U)}gHzmtGZXn^}6uE0js@$>2BKL|qPf!$; zxcG<13mAUe=YN{u$_tL>u`|9qW;6V@nV#Jb+ZG3_wE96+{TS}D%zg~_uX>K*c2@~< zFts1UjVuwomEGzS`7@24)+&0pCn-d(3BUP1f(_9m1pY#*#xBOI+Pc;E z#+8inw2Fe~dE_d3KjvA#IGX8i4Px!g=<}w;{6W6Dotm$%6~OZJF^*jX={nJTb<;Fo z-A)ng2^xkWTo#XEJgw&#MpqTcX_~)o6vx=LMDU*3hGp8;0Rh(LAiU?rN6_MBXiM!l zR9)Lpg<5_cNB8C72JshtG_yLoS6}IA5K+r`a23@hsy^#`Sl(L&E%X^vGTvv_;r$X| zJAGaj$L>4wZP=Hshv~Aobf3R!?2P7b<9)A+w($BSAa6ej`}~K;?qfJeX||`SvS}u( z1tkFSi+9dovYU8U_{*0fzMzQh%_2Imp4{WcL@m%W`HZg3GLf%M|8i)dYg4WoJHtkG zjs#5JeJSFjeHZo^r!|N_2p?fI<=dqm!)j9j0&$s)v@x4zQ-?E;V`&ABmP#f>Nwej{}jD6o> z&(_9&sW$$>3$gEGd)WmeTPwF}dDAXF8SzEyn&58rEWDTHK>*&NYJ7R*_!?i&8DRJG z2H4H=`p=$2^6#8O+T{KkUmwX_=05r4;2K|lH1ir?(p2ZrHNFmW{j6t=AYWK9AWo_v z-q*NQ1TvJru_J@~8%OONiR|L$*FJ0h6mJU)P^gv!V*`pyN<88k0(~DGveK0cgUrrQ`7%rYsd}364_>SKVxQfE&o#GuYzjAjt~Q=AVwM}|7R2ox zxf^d__Kw2O)vsNfI%@B5GTos+_U^)p0=Z|6rcY}zctiQx-@trM)0E4S<9+S@pQ+B1 zpQ-;AU;D0+@xJ!YpHiKpRMo2Q^O;XmzV%|nC-nWsq=#@lzs1wfr(E6Yd(be(^BlN} zp1wu!W*gxwtke^#pP;b%#JJysC+HNsB>;hJBkYD81EIX8#Kq%kp1XA&kFP0So7}tU zpkIHBV5#|=+SfiHSCLEPvFh}>wp-RE&(p*1oP#&8SgEGFB>w(gYm-d~NHzeW?VNWC z7OHRd4A3{#f~1ytk3C*={;Oimswn$8-;c4jWkBrJV2MaPXADzUoN`uRICi3MP9cdrnfh@V~G0v{vanomDyy z+5q0_YkpSLu}$zuJ6~FBLaripiQcZhs<&4^Y2KIp(oc)3|FL83=>om|^ftYHUblKS z=Z(=G^+toeI%UK@N#`n3*BIIBA zPd~f8Xk8`pWFt(rq!_|Er8ulE*4aBJi1z9fAzZUo2&=`Sy;U^s=n~QXwh21VNl|3< z^sWc5zgyicJu{P?C7s&@`zksgCj^#9N2_Qd74F6(Nh9#Pq$+dou~V8IJgbjLt72u(>DNV+a`EURv{+qw58-kbXBNT!kO=nETVdask+5Ga z0DG&5b_5Gxf7=A)IVtkE#<$l4iw$eW>ylaR4ik`Bk3*QQPd4TSlIQXb+^*9mrYf22 z|1@?kS~qYkmY(aD4d6Y0z(G<4Xl#AeLDW}y?$Y^6#1|~M*&vC7#jX^2^u~cK*RAU4HF#XJ=%6bA*UhLK>*)CAisW3 z?~TUfJc7p7RLuJS9erj3=KW7_@ctLX_y4BW|N0^Ne|13ruSEMFiOFu(wuAS7EhaC~ zdkeJw3wZzA=`-6Ly#HcOH{eJv6q4Fi}Gs zFS?sPcWSP^n(8CV=h~a;UvaKoGSD%ZV=ttC3+C9X>EBbc?alOW)oi|XV}>SOg4;x#t)dhk*Y-R zb#B6>(*}*_VxKRNJe}t;nR*2@CL(^FUZeNsAh2|t=Qwfz#m`fZKjNFJy-%MtB5u>` z@^k#IaR{9LOMg6m7xMG5%QnJ$%x1rN4oM8FzRm*<(uw-{bdvy$lt%|O9-S@1^v<6- z$W%QvW@`5EkNuiGJfa5t&tv;ut>1>Rn6&sKtiE`&R*U={t>2@5&ikqEO8NEg{G4BB zYyA2!ZS!XuEgHXOv>aZ*X(?F1X(^7UrSTH9>>NOgqS4~_^D}_aQsp4O@^ikOt?}&! z+Gepvi^jM4xXjnaWge&HS_ipB>Zj$&OVHvTK+8`wT7K;3X91&Sv4d3jIseYq`1fYo z=Cuxzrtjz9O{3_z6xxHMIPYfrFx5fU`XjzB(U#je8j}w+UhC39BjvMx9p|$_9ZaWd z_5%YnW@~i+2cz4n_%ym-jiLLl0d(K)kH(s%DYt6hd+Wu)-@9nQdkeJp=J`3__g^$l zqr7^KpY!Uni=0(SwKF)BbZFB5Fk@N9v9p~c= zhpL**)1HgD&=m*G&`F?nk{=e=xA)M3)JJ>qKwm=^neuW#r4IC|#1N@=C?vj9a0 z1WQOttIuo(nC`9QHl9~Vzm12UGetj*_>}Ej<|+HkIE~6FzuwN}6#DyH1L{xG^K0>$ zwaKMaPdb~zP#rQb=*Y^d>KwAxK=O1g69o^~^wDeBwaEu*-^m8{o@YSc^PffVv~hmKIy%>9 z$GH+&8@Fg}G_B)pjBkx^!^GOqbbY|22_R5ofU}Yj&gLAPLrgga;`*N8r8+&8bt>Cb zAJ3hl3Ul4H02WHe z^T*aEw~Dshaa7-vRi6#u{x%&rzhi{=T1A^uHs3+2br7I!OQkpMw_OJJkI;eh^!Eg> z1bDx{e3r~&-(i}kbpm*PRRArAL|4%SDql!Aejvj5PrEUKQ zs;PaBzCXg^sq9vF=Z`UaT;M92py#yHciA2tiOIXaj`%1|9gCuMy*ZXNi;jgTw)Ac? z$USR}@`V+W94;JF1{MH#^3cBy_`HXinu2(Y7L z(E_<^$$U9nJWsx`qEPNxbEDk5X|Ak_Vju2Rs^MOGjZfZ^(2sY~whsvDp_Li^IUn9V zrTU&u!em;n8n{5`Bp*D%6-Z9dFyglbAkkcQPsiZIcNpQa6GCQak(Ty2DwG&Fh( zuk$}zDHq3RbyWXUoA$*R4NKk-&elP|f|zfAV5^2Ddj(9KTAfcD8a)h_JVwJ8|5Tg( z+?YBWN(()QpufgvZ-0%?Hm&CBiSKbNnH+b>=Z%;gpt80R6Z#uWuA*I$2*Z+D&0O&> zGc)c)vMd&dGwu|a-#o(>N4WA#Sv*gr?H-W-8z4|Q086gduw*(0^+RCETLxgs){2_i zpoS$c(XeE-4@A!JsBS-;O(dk+jSiI?{M{7&D``3q)d?{#_Bv!2^}*7upoW65m2**b>TT8|}f z2v!GZ`_WiEmV6Tej@6j8aW2PblmdDzxrVnpK9)Rot;4b8C6qd5`Ty_4e($x7js1E* zq3#PPbwG@#@bl+%T#qy+!#gL*y)7Ug|Bxz|gQu{sML#Rtg7o;-YdLORrvLWyDeU`` zqBHC2mXMNc;8y#e)6b~**=?>QH+!M`&mU67pMVK#7p38jc>wjyC)??T?jtRFymAxh z?YnyQ_J!Fng?-QLvWr?m$~OS){+7|a_g*I^5C0^jw2HT7mjKK^1u*w~0DH4o6s-73 zNZ9}|KP3VS#@?czg*i8e&&QIq4L=DflgG9@|0KX%8vjUT_qS~+l#r*e=CQW*vjObt+m96<`1@mpUC2{d`c~Weqi?sZ zccyZDnjGsC_@yldI+&bQ-+t^JN$?bwUeb2L`3=bFfAg&q>gG>R7|#XSGo@R$@O~Fx z(zgD<-!~VIwDDcI&pA`CX^?sCmcj!5%uDODCVL8}u`yh{xv&d7h1U4y_2GBevx`4{ zjE}Ydv9^)#op!yQ{hJ@-?et&#()!wX&zQdSdsIw+SyYk_WQ^|GhvaO)IT78;1&&Kd#}?!D2RAyGQwl1b41~vW0qi6m?@qOVe8+G| z$&BTATx!O7FsC$9@-N33(dkqq+ul^X5V} z7K}OdRjIwyOQmpnbWy_@Er0K{>T)O!(m`V zg!3C}e~Q)WF}WZ0M(zj5#iq!-i1UNZ;UvCV)DC&+ zdFB@_GOn1NT=Xga30@(w*{M?*U!GYhV`@V#^;TA<*;S` z-zjzc@;w~~v(>=CEPe#!k}Cb4j5A-ygNww%93Bc8SeSxZG7X4eU@$wD3H6MA#YaGn zybmN9cXW6j&^vhSJ{ZKi5vo z2atMk&SIYLF-Nv?JS&)2d;umGJwG-tF5`JU|8=nm4rQWDxl}NojmISI`LXwjp4~c% zc^E7b)kw_4`Nlr)54n1%0PE+V>V~J5fc()y_^&Fne*c(_>my^2cb#L8e_-Tr-8B?a ztg#>uj@#p9r|GdJZ+&a*9={Ic*aCfz&qH+$Yz%CF*O(qE)c1E1$FSx5I}J8IaJ^9f zQQ4eqP9ro|_D{y7*W1bSVT!9fxurbcN5>ls78!Tk44a+tM!uPTX`278Wh~7Pww#^j zziH8FzHsYU+W)#GOnXs1mCnXy;`p}AH(>sNGY!`5i~%>tbhTl!LDc<%3=w?&e-n3C zJP2z4o10Hm*nsSRv-bqE>-fI3N_F<*R0()Jt0Q}zbP64;oKL^KKr(uEs z+S;E3nd7H5>vunk&A{s-joz_c#Ib5mrH^7WG8^LkX5EIUJWY3{U2T(lZwL9UKT@S~ z7VhBqwIRx5x_!5UasHN|tqtkN}uajYYt7A=amujWOkBd%yVvwZYRY= z$fN_!`Wz3}jLvan-|hoBGZlAmU(y6OILl#OmtpHzZ4+&sG)b>xHj2ZU&-cW`{GJzD z*JlIw!0jNXN_e<(HSoDpid57EpWVq z`B?YsSj@~8JlmN62w;E8z$m@>^AN`M6KY3C5@!t+I^9?%z+>9smvwgcZaIH{(mte1}5FqCWv+Hf1LblIi zM)%U8v`=Sp8lU;YD1R-F!e85m4gT^P{Pp%Ie=Tm-<;-N$#Qn7Mx#;_;@ww6clvgvl zpDs0c?TVT(K4U}PqWxe$(*p<&I>3x6QBx>DDD_NX{&eTfXGx(qIv?2aYODDVfN& zG}8oAnT)FiaEEzr1%SOeRNT`F(B3E7v#vJlIcM3-XQ+7QosvrJL;-Z3XcDAACiB5e zAaApEHS~#zSvh8^_$!`yqWZ!16Rq^46TU*JvGt>;-?8?33o|zFIp4jsn3vDs5(fZBU8SI_e z3xwrm<&$Qtjq^;CB-ps5eCqOoZ^q83xw-5+9mSknIC5u+J-0E2M&*UD zJ&-X}+!N-5E`WB%AB^4~n)J1~a@^YN5hRXL%hrZH>*MQV&+0afU7u|?NsSzfBpu|h zvQDkz)`_i=^+xNA|7q)V(N|cfzNKHhPLtU>?K5=`Z%R;yitOs(ibQo_S&}-uFNW(u zj)OD_)_n@#cA8*arvPrJ71s4l2KU`IOm1Pe{#003%)UoxUD{+`!(doSEk6HXJh-K* z(@!9@W(TCMI=>(u+~}8m52k&v>OuDTwMpQ%!^Rzp0qm@;0V()$DS&;04UT@QMVfv0|($QM8_xf+dv-hg6bFb`WRt(KD<=7{g~|R6G5&5 zsAsY-Ecb3_cERl+?@Whorq6PxQH9xuQsr&IYC)=#(r|}lg=uX5%;u^#!=V~896EYC z$jkeXe4`6w>FGtp=Pe3m%8N)WLh`3At{iC<$eAvX151JUCj;qs0J($pnTN?W+!jgH zo|{Y+)*kC$`pF`K(m>wxm@cE`$$D&JVA)OT;EEg7p(3|BylJ^g_nC}!1o>G}e?L4P zcf@$uSlBq&c+NGJbYmDaE=(W&WQVTbSUa}?)Z6)eFdZWzL(tdfb3vDe#s|rrxke$C3z9)t*UC1 zTp;()f)2khGZ@a1egQ#!G@J^*fO7^78hE~q$ z;thTh6Gp}%8T=G^Huiq}*z?C~qi;qVE4XqPZ6p9v%G%Gu1M6O6e^9a_n@c zb|ggS21Fst#4*%uJZ>F#kxN~R;tsAw=tb7w^8&bwP;6kW0PceTzS|*ro-GcOqX>NY zkUCFA;PXQAJgbCBCW@`IHY3#wsq_29SZ!pic1+l3>9yH)QZnOD<9lG=3)&IUnH4h? z6Aw7wI~z@`9#>8&N}gxsSn?A8tzVQl*1Z%r`aB@a>ttrDqpUn+ zGv2jnwu^zpX1df0WD8U=-y{Yu^B{1?R=RTPAa(xI<3-sOD0S^l0QXW8bjSV#sra}v zJF@*=(V4Zx1l_iuAoW~0CV4S%StV~ZITs?URpICzG8W6G>XD5lA-UFcDpHuOweX61C5+F-a^1QWzE9Zx1B;S#RN!c_Y6$sV`gye%Sq0J3-D7Nm7OAx0C zW=&yCU9Qx&?FrHfk{&&;Fd#7w)u(8yd;SjS6GM`>VmdJ~U9i+Mprdtt` zm$;bE!}OY6t6RwPD+$vVnlUCOs|$=VJwGz0Q5pSOU1-8swoaNzm$Qu}Vcb{-xX+iM ztzGEKVK!q;#8?=8zG;l5G75cm81(sZ6#6)tCSnZO0m)$<`!P_ZWHs)nxCBTw<1g)M z^$s(VO9jSzus(Cx)l-XV8!}N{!(wEuE6YM^=_No)rvb^3QsY& z{hEKmUMGX+w%4aF9&4{ZHLS-f!ZzQ%JI31U%$E5Adwo}p8Fu|M_WCV5^u6+O9N#Ou zB5mZJT7BRCB<_pt_5T9>{qT6cj=etL7|WAU#^IJ< zUXVYJ*U!?U@#<@lyz13?)ot)btG8%qgje@P@ai%k{sbWXGYtO7$K+?v>O2q|<`3^E ze`FZEdM1`C;3__UVA%?FaK%mPP|=O*@FutFZ^Xk?G>@Enm?HVr8--u@jpNrSipW(pz|xwY0Hk`clLjM*x=W6kR4%u^@4oFs7ZEf(C{z+r1R^n z3rG2NQkY-8AiptW@N0SmzfQ*Fb^}LGdPqNi8{yZE}uivhPZ3Fk;?#xKqJX zn55@o>CZil*7XSy?L3Uutr8;I`7gAt4}se{$@u&hTDJ;;TberBZXegP&a7x>B>e8P z%~M#|Fmg_EEbXN{E{6&ZkH)cgo}L)T{_AOdU3b2vuj}gM(Kxo!F!7w^_%qSZNdnJI zJSXuq=zLel)@h%fn>cbmT0~>c+4{`-Ia{?2lWLQG9^^8CFC1rP?X3o=ua3vW9|OKq zqEkyUc?x5hE$=M~GCQ@|`{!J%6$l{Df-*A@_H4TuraDn#V6g~1=dE>CQX`$Co9V(jLY0!AVwL$;>BH2$^LFUw@eF|aR_|@u1;dtk&EBHm ze?AjZ{zj=IJVstu$++jr^AY!ro?!)^*4KvTfL?8r*?RQ7tFH~~_loe^h#)^_^jBf5 z&1;?d+Em4kuFba^LdtXiI~z}Ueb|_4o(YBZIA5Ox11rI6tk2|#^+`6?C*2!T!tJyg z?cDp!*mL;7zvy~5**g(mnfbu}lW2DWU{Z49wiB5sf!DamD3=6Gh$F3uZeiPyeBC}_wNo4gp~f1Xm^*85GcKI+lj?D{^f*JzPQmkyzt44 z;etA==qa=!Yoi2-bsiDi0nw@*s45C}R{c4*tkM}guo}9HD|h6sT?O4AJ(#B!p@hIk zRp$o>MVt0oh`OK5!fM?GpjO*}u-}>yxCcZV$4EMA)W-w_?&>YKWmi+nJX~26ob!y1 zkyK;6*TZW(==OTphMfIOXabJb2T#xmw2Do|Dw`jhn}lL{&5y)#Ya^o%qm5<;xd=&t z3@f9_GWBRn|7-p}4?JmsK|m0{EC8 zSzrNompQ2pj+gh`GoY^}&kYbgg`15WkT7Qbi-OcxR*2OuL24{r1#&U+EV#o8q)D)G zjOoo)ML|#1pL6f1bOtv^(6{NqJhchg0!>xt2M5GBPT#w;u)6jF{j9qP**Serj?gzj zt1vLLN+Rg{r$(K=;rHGJ9YZaWo;{5d>FardDs}Huh2{%f2MpaAqn=q~QiDZib#R46 z9atufoadi1x1iKW%92;#3WP1q~yZN)=g$0$rhMOh2%hu1>C%bV7jd_GYxm-O@(!R z7I3rAB{od1aDkk&3gik=3Vb|F-KC=a;Jo3hpWJT-IcxZVo}&`9OUQoEHk?0F59Vm# zf!$7I3rG-pBKNZDhHCmiPnQMSJ)b?$GjuYfNK=yP7K@l@@V=$ET<= zXPn;47&PqfZHE2b8{)EcKy+sPetSsimvw*WRD|yPcH^k-8vvMlo}v3LY78lN1I(Wu z#@-hbwAZ%l_Sl=1`a4ED^G^fJjWymozcHlT3ozd@@?Mhm^X;ScJ=k|)+TU#kGObZ> z^B0v&pNieXo2=^4oi_E%npibh6sHcZn4}IYi&uy91wFrA)brabv%oz#F2B7iN`CwJ z-1am9+$BbCJM)jGN6l})UL9OCC-)pKd@ zHe*sUORodX+OJ6)&2dlsfGTW^(lGV4?t|_#qEjnf2(pCm?*0}~SzGM)TP#e!rv&zY zPTgHbPP;qZ+PKY(2|x3j1@5N=O!gT0ZLRk^m!FQsq*XkR<6XDL6pnFRK}$xMd`}vSb3YRe%8Lu^%)f{v~-dw>|>n-X0a>emc*sZyL$1x1R;$KJjZ|+|Qo| zzN2E&7h>E$3SfVK3ix!|IlpWy2FCsV6FhG@sORN>n7gN9f!c4uWRG}$P?`e7 ze<|iQCwslW$z3%IzuNr5RjM>ozw-c|s$5EAc>X@U6o~UbKxKTM0iMEEuQPi*2L4|p zaEI~l!#MHd^Y?9EkiRb(`TLzl{{APS5MSHV#@f;`IQS0j`|tnX#lingC=`*yujAme z@vyN(V&OBMV)BRalb**vou7w<`D!GO-@wA(FX-5DVSJeJIsIP;4?k%fo)N#V$z<-O zm>hnZ@xk}A2SrS(doA;t#oL01o(?I9Qit%7eh;AOEcXCBU-KTohEOQt9)LY?`yZ+M z!w_{e?}P4?p%B+Or=N<*zsr@l5B>LUt~0nFfzoitqJdFAI&9O|4(NI(ZMCjvsK&2wQ!YqTBTsd-V3$cm_YBO4v7xAIW=l z<@gOcZ+bd3@_RU!pV3{%d%G=o*VDSso$#^l2PAozAMh*n^H?Bf){M(t6+xc+J(n7; z)g3--{ji5B#bzMe&6osDx~w}LfzKFumx%GG137fQ5gh?0tNgYP8XO-cH}cxf8}H@# zj423{1`&KS3|V)Jh)IeFz5)v-qxXkqoJGbt`2C>*1B)sxq+?Ox2rR1KhNXaAh zhN}(PQTZ>F9qq%B{GV*p8`kU6U-}+Zs?C^`nK1!0+P;;ook?H2SQB)YAseST^JN&# zms-0T%2cVbPQYaC#x%>pKOAs}@dvw~#;CI=As zmY6UJw=bEXdkK=pw7=Ne)sUr1oHt@8+3MK)j5cX(o+gm1<6%tBVz4M*J+o$^`Z+&u zc|$(~@WylxZ9UbRt-nc6ib7V$}Ig0jf?Bwl~L1<;6XzGoQO8ZIX07I#0SDo=?3r zb!PMRX#nsq)*Swx|=Yp8rvs2F#6<1k??L^k$(U?Fqj>nG zgCV6CpgkJ){pnCh;kK1%*PcdD-+Lt{!3%+0D?+_L-<8uk1?Kf$j>(ekA*E{ExSI1( zHyhXXapT%4qHZ>>pXQ_P@VJV;2lYPh%HW*%Q7qp4!I08CDLNK!cPOO%z{vM#_O1*v zAM=&pQf|MWGHTDVw!g7Gq$EXr$7`^>qhrPO^7{2iYm4$;lHm)Cd}q*LmI(Fi{|ne( zF-cpqEuGrAu5yT6Jwl9)jaAebN2?7n)M`*kB#AX3b7-!}Q@PJ{ zUzW_;dp;k!7lNnIi#&w`=}3OyE>zESgnn0dQPjJ-{Qh{CNnUuGZe6(5#P8~QC+T-} znZHmi!W{k#zHFqAS%RnVW6`OxK5qY-ee9bQz7ITVD;!Wl%A4DmUUq8wUcW&dT=88s zShP$X-gKQhbQdPntJn5r@9`Kk(%*eW3GuVb@b{AOeY+A;Oa{hE`!;<&*#En?>H5(9 zU`R=ShbnZR&^^4#q<(%m(}xx{SR|=~E3E3kGMhS_k7Vxi^7;};%aJf494CId=5-16 zXGGBMjmP8{{5yyCpi8I^iok392Sq3Ido||&5W|OJ|MTZVw4MD9CQsq;XCZ~zs%&hT zCfJp^Gg}Uy=lf?vhlH97tq*|elz=pCLBT!oLXfV6js6NzrLREFA0+UR08(MPr|{@! zA%*+OEg&=Bq$pje&&bCePYXb*Eifm=0>=uLx|qG@V>}nW2fjH5+*ubcQfFU?2g{Gxxt`IK$u7uX_PL97+r+Z^jMfKE#`@IK}tw@_j*tVmMu{SS1eY8 zMFr}aHQ!N(H!V^>zZ?^~&xq9sp2Dl@b${5Ej^xhM^biaQvR?%G1rk!SjaW6~*Z)2h zQdXJa*lJ$W-k}9WXI9!pi^#(7E+UWA8}~=Wk$k%O!Eo#(7LyO33Muy)u@hbHIkffl zA%)ol2@&sw&pqP+?2|^GP0`q%wMM+lY*^FC=jqz(PetbBC2EN`=s0o-H|RKX3%vS1 ze&s2>CVp{wNTK;L-Tvh;JiIAZ9lA44J+o$#8Z3%e2Ukp12bN7yhxZ9`SCH-+5E0KY zWP5H#Gsx1^Ylc$++A^lV@XRTgG>J0;shQwz6;b!Sr|F^7M=y|55Z;|=fkT64IL5|0 zBubhS%?R{f2<~dpmE%u<;hGC|{6O2VtB0-iLR8bxD?*zfg0E&aCbbqMv+sNNf$Tyx z4cEJbdVf0ZaJpb!Up%;bA9b}cK57wBH)8u`=qmX+@D%!IkLv&HTtYqTuV5<7Z}P&% zUI6>kw3mH7*)ZJeMQuNg9NRv|$~1PZRx#PwJ5!#8#;(;7EYvS#KH(Ar3nPazqa)m6W z>+*uVm+_f}<9wgm7E+d@iE zoT=qq34DLR#ZaMCcox7JX!lCrR~*^W770wL_M&&DD}V;z2EAOL1sMG^fMrUq_#}f?kl71wnn!5 z3rw0`iD>udQQF-Dq}q#fY9G~cj2VsCzD5H0YG&b%JQu8Eerk;a6DAXSEx3(6!+1uQ z4R*~R!DBaJq276pHTq;9$m7=t{fpM9bX!QNv0$PC`23<(%S4#$r?mZz5Oq|?Vq!&@ z23kRt~`YifOQs=>#4RM3AH3|NO2xxMG_SJAFj2h;}gvZQ6-E+RQ$V%cX+{$NrnlwN_{yTL;cTGud!4OFh3Gc zy*M6^;H$r1AEnNs2V~w3TEN@coF~*5&q8u7`@0v()%>p@Kf?YBG4ey~?~c*>N_*=g z>MK2kNySq-*4cm8hm_)bMxXm-s!J--J;EI{*z_RnyVbLrPZ^ zFkI#-{L`m;yz&0$Ku+}Ncocg?XLj@2tJEXYz)f#~}(V9XrYGu`d>7xtHYbVr&6!Q$oWjv<_zlb_;4MGW-oMG0P0yg{|M>%)us1`6i5YG z92mPd695w@0QorrpM-IaA7BoXgS{a-24i6NlVkVie?A#&MClaMsc4dRmZ;D`eaDC+o%sWVEh(m{1%o!k3KoJ&a5+4 zJdA&Q=M=qukk~!E$)=uK$@EK{I_wqX0nw>p6Zq0h;5#V_T9pVse+$TSO|Z57h#uEW zjlpe{imLxYAg8FH(h8HBF$I%e3$*zYfG~fM`Nj|44D~$j-@lB>>dWL=%wG@3&8Ccvn{ht`UpCUmNZhOi&M6RxNx-i>pBur?lzBo{{3@2|9?pM z?uWiFe*J`Q$55}pa}$T|G^uCSnAKpBMIBrrsRPTbJWnwdfiF?Qr1=&XX}!%woFMW0 z!0a#j7P!3#?0(Ui^)MREk9c{Si}YE5_%DZ!UN5xGiv{25&&qcv!_X5Z0Q-}VK+ty^ zBJT;9+++jaYc@=ntU4kh?HL61&YAc`Dy8oIt8vc3AAo!y2@~IKF4DT%MVS1*3)MC> z2~uF+Fm?ax78iL&NIBR@^PeoWfSfg4-cxolv`Z-Eplx{JNbZmmIRZJCZEyHJfG>lV z_jFwZ?Wrfrd;W1WB0nr{MqQJT66hBt?ed2qSR4cHx>?X&hEfg|twP81MR3Q#%sPHo zE)C?0N;uvkfP2YseouVdjJhQzkl%Je_tL*V_{8H2q5F>G5*=zgs-ukGzh=>9RK?Gl<)Hz3AoMJSfv3#;8y6lCMDJ?0GVq}1)Z#YJp! z)9YGqK}5X`5p6Xha|S7web+t_QvQ=t$IBPE$XB8B!hZpsm(2QNI=80jbgut5r}GKf zpz{@9jn01f=joi~_+mO&C+T#);@_Ok+rxCe{;Sb>%fEomwzw~*b4jdD=idH*Z#rLP z(7883_x+e1m?P^t;^&mM_r_vEV|Cx}ayg`g<$s?Aa~;ska|_^Le?|FjC$a`=_`O|c z7NZBFi!_|ylL62%uxzn9xS~J}7JWxOv*sFg=*}=+tsZNC`%$XA^(a-|e3U8&AEnBB zZ&Ky(n^bxCO{(;~NtIXtyUmDmO8|BYfZc4wxtYBi>HqUP5(%TetVtgAWh3W94ITab zz4{&f@%3j1MS=T}ju<@$c?I(=qU6)G0=WCl(4B46mO780S=luz*m=%IjqUx0>~06o z^~v0LUr-gmcht;nbNgCktF1uE0VIHXwiS~KWDlfH0(U0Dq!fW~w#oR8Qa9_XCPdv8 z$Pu_bMBR5--*2dEb2J{K)B&QWa6x})q$b#^S@>1^2RaU5I7j0&fbWPfnxpX_JSQ<( z^D>V`Kc(hT?eM#~!2a|Fpi>@K$?L;~r!Sq=u-QwfDP? zKMdYEMBDdoyg2xGUQabi^YeApbKdMm&SRKIt8MQ$*bN@d*m(CyuA6G)y7|Qf%{Ivu zOhiC50Z7KiIlLBHIM*%AGh=hz97e9u`wba89V5AJ;o5zvMqWxu{KUG+OeVZL5Q?bh z<_OF};2!)t9jPpNI5M!wF)zkE=nDY-`=3q@y5Y$P02*fWbAY8o{;iIcJ3(= zY0TDjNSO5gz(xFJV{P5abZ|QjTQ@Dj*6rVcN9^1TD<%k~@0bHQJF3la9DM`aZtxW9 z`5|`A`4&}z&n;C?rGv`kmfwO&az4mTQ3~`j-V-sguUn!v2{U<}>ma3$`qdz_&&?s~ zKD9%SEwH(jBB*bj#pA(&-Vk-OJ%<3vtgpPVZ5N{M{emm!pc%;rvM@PS<|6(d>AG+e zs%_XKNP!~&?pGdx;Hff1!hO9qMBTrq)N%3$F7hiO;o!|Q|H;g-ZOv`IgfTku=x60d zUjEP%^De7ycn`qG_IyT~zULGDk-BnvohBr3U3ulh5KN5$_mVW|W_mJR1ow*q99)Z1 z4vy84)5qw@pN-RzFMWZIJQblMwJk-#Jwn2Wjy&}PrX!Q;{69dXzYLM1KSE@~0Mn6) z+J?tNN;9R7Q&(ZqJ{5d}5w^%Pk3evs43TyLlfzTM*E$W8GdnP`R=RRxA4amIUNaJ_ zTKPB*=Ai0^yHRaJV~F}riYYu+vnd_qO(G_*2;eL6;+(aQf?WFI!V!OVCaP&z#cURF zdZ6m^ryKSf@s1mE^jH;y=sc0a0QLP{X@bLuXs!Z~Xn0l8Eg zZ8ybew@92GSQydnl{q6Zuz3e4b>xXD0g+JmDnaKf)v&ROgVbFrxN_E-kzAIA$v^~O zJz&^a;%Vw;{L?5T9K4_AKe^c8A8pD+{&AwDu|C6O-Nt(KZ;^bHQdev6O>PvvspEVz zV;tY4{EKa?QN9`Yfo@wx@{R8^-M0GMmXLD4VOyONNA0V=Ez#|(KeF#5WX_kdty+aI zwym0sx{@bFC%@ZeMZj};*%&vS)Z^7BCu72X^Z$XmXZ?}7{SF>mJKlHs#GK0FubER^ zd@`go2@t5S@-(o%j=WFZuY{;$*~3)1I}MmYr{mW zA!ZXnjE;49@~dpqCPePW`vDBIZA z!*t$flscSZQlMp+y8V^g15< z2SQ3?4OL3au#5F6{csVnxKr-P6I}msl zfXAB)o`-Us7Xguqp#waRV2OSwM%xgDDUP1OJ0GY{b6N_%Y-wK|> z41U(3%L!&rHHi)`CuVWEJ5yVCBBTt7p#9<=OxSPX-0Ri{b=!KU;F=&OqS@A8Mo!#x zBBV5l5O~JxX<&Wnx!1{BpEy(Nu|PeuJ9lQeUX^at=fwJ)37KQ&V>agF;qT7WT;cK8 z>f_h%p-ks(##^91d=I7d31dE4|GN3i8aJQ(A?oIHc+T~z^j}|o4pYK&cq3vC3CtFp zsat$3GeK`!F?3=8t=(-wemHz*AVZHZ?nQ z!y*!W?*U1r)G_{DzZs6PF_x}P&6YMS;(h#u`!+~pbV+8i(fI!xJg-dG8|=FmdG2$H z_Iv(!x;7cHzscGH_Sb^RTJ|>KJ$b@e%dRwh*+?JZvliCJ6<@QD z7NZaLu6~c_w&2dqA*H1@GDrE`^?|+&A2dSs3NpLsCi znFkHblGM9G%4curIUM108Kz^n9%4Es29pS^KOggDOKd>yo`y+10$*_wCY5GPyz!WD z3@rg2tQRnuRSB{*Nng{urvZ64MB5|JV*Yqv$kF{ql-v;slbd6pzQpi*TLtiyn(+jk zw&c*2hnJQXXU7T?b=ndHbr@kX>v(yO4KP_eiOCH~6OpGd73IA*CI@9)y8$yCy9hjm z*OsPcuZ^;2S=&ny5N1d0d}HE$e}1Ml6BD-p?Tj`RNxHq}+#FIkc9aMsK7Dfx_#*GP zCv6UKJJr5fufv%bqCU?oOtuNSJ(vWTOxmpHt-efYyC(&crW7E>A?mYi4k^c}Zs*1r z?;jqT`2KKR^!HEK>F3)McvPx9^(owL{L9|JY8kQ*#!vZGzr+P zfH+HM9bk04C$OmN^+06owW0X3=boC?fl|`ZJ{<7li{YHOQz+~a^@}A6b^oztc zB%GG7N2O)I(f@4l6do+g>UiaKs{HD8s!&nKi6H5WekOHrg;^a~X5knS_86Uh z%tz}3a5H&!?`n|a0qpf=-9Id*)LkjK+N#W*3;Mj!#{9%1qGy3bna>L{qs=Kw9s2VQ z9yhB#ACqcIeV&E-?}X8037)XdZeyLc2~am^hGPXH_@*QN+}6lB)|3@zFOHyBm{x*G zU!PQ-?>}8TrmxS|@$~7uXA#+M(1x$iLQEd>8ndS;EN z28$was`3pzF>^Eq^R3#5{Ll!Uo>d!CHrOz^F&2FH$7A9b6SX2SF~IhAss!%wbXNqZ z3!32&&xspH)A0PxaIA;K0GPpD;4R9&`D4^Ai7@9@@5|GhWRh$_dstGB*=^%e@0rJ3m zRLKxADHx)@#on8P1>*GJEC8-RQNJV|jJ6j_&(OKiXbtx+BFxXJEz8XA6@VNt_Fw5V zOg6*=Ia_-*x^5jqqZ$F~Qc-l;gt4}QMOUk5*5s>0cP>l?oQpY8~p~}UKH$s|PQhfu`9KRwPajq?*B9;w{R)-`FGfcvl7=@S^UU z*xK+tlB79N5?`CsBWvT(sF1|hraxkB=7-nDyE1r>I5T*;u{J{%AU{7$l>%drlzMLt zmVCuM!syEO3EnWePnbO4&-TeQOiEKQ*_d?peUce7Q3s9a;&IPcN44h?G{G`z&z%&L zwdQCt+YE=8O_#c15n(=OjbYdQBg(U9o74MT&z*apF5gF$!hKY^;h*H8%O``c_z1|1 zhbjT;89)6`;HBrQ$MRBh^(Zf;{=dLWabtOD$N!JK)VY@`d-hW0*L(lh2Kq8K(A|5f za@SdCb+)}W&+t=Do8eH88GOa(>vH=F!}e$P5T8#b;B$)?t_;%sR$%)w?j7RgsH3sBd|^xcW_9)8z2B6iMXOL2s3 z;qQ)@W$`el^BjB8FFHB)U}R2OQ$$W$$s|{>%L+b^ux5uXA}1}32h=Kpd$W;~c0Pc8 ze4K6kn8I4YE}D4URtb?m$rFaURwMY=A}tIFU=n% zFD-9EUYgy=OMAEBt#*6VytFPOFKv8mbv!NnX4u8}Q7zMB{n6IGO90|wzTCKX17_I8 z`1B(16c%q-L|!V(%)E!Bcp9N*Lp7wAM%WLm`EYBMrb_0dPDk4dhQOO({+U$B$T=QuY8G z|Er}bWju|U{asg9oIP8d$k)s+e_6mhw>uT-JpCI4^?nhu#<#=l(tZKvyet6e6{W0b z^^4E8zMIRUuP^KWMFGf1QFx=@47>a(n=2Rw!8=Z(#~ z;5Zo^8*c0!SJua$zGfe{pEr?j@*fH*i>g9O0eGf85rxj-y?g`JMe7!8BuyxdxF4N|3fA;?uhsa^?DM0~9sZGz3DKQ&4GSe_Ai3hSF36pIIe8nl4>@;K2 zV&urE0y@|}E=OiV5|G0@N5-z%e;mHIJT@k=#T$wmr#KsL?>~zkV|?OgJQ8JJWPqoz zt1LCU>r3dkH;wb2yS~D+G~Ei@b7URc zK-Y^rFJd3aCk@$GyaW-nDz2k927GxEta~X2+<8-AT`TCd`Ag0$n~Pt#-4 zt4Kzt>8`ZYv=Q0#oJp5|trdAH(`&xlzF4mzCZGP4JR+YkcnbHWPLxkGydfnOJcR?x z!Zj0+fm1oQR?<`hukPj2(8OGpRFHprvB1yaUuS<;BYEG&LcN4Mg%#6u{a>-y5-iDr z4oT>Ir&xft;=NV5#e2QEC3|Cn#S0(KEnfIYZplJRu;LNuh|F8*Pw)8Qxnf>4e@gdB z(V`8ACT&oR(N2k?CSj02n2AsHt^nd+3Zxf-n~kN(7)#S$OR(t?=%_Zv;}M|Ev$rbO zv)7wjy*DQ4S@>|SXW=8c)e9{_{|ZcsX5teP!o-0v;W+C{F*zbSvpyCb+BK zh8MquNpJdOwbu*7H2}T>7ba&!XI4oN`3evw)GOv#O_=-6 z;A8Xhi*_w->NUgs?%-n&=Yq+z08NEq|6M@(Tf`i;9|tZ4@`@LAQyQnzJAp`xUF4QS zR~{bt4kl-o0m+B~Ul+5v3{0w*!kAR|S>)dQ82OWZCRq>-U6~&vPi4HAf3>bFU$|im zFS7m^FS0&3cHfWfauwspL(_RKd3qQVBL8ZgAD_hJ-l~w&zXFpCM(;#SPN##m6Im`t=W-T9^1(Lo+Ym?KCl>B5Ae^~-?}90)x`&xAGD-AwlNZ$dMS$K zbrb@;2FfTt^;%VGj1w{0ym4*tQvrP25GL&c_~J~^&7N?m@8u9HMT{Bg-+_DW(MJK5LG1IuJn623F4k>DUW}{+|mS z&v{Yz$NQ|jE`@Un)N>q@<*t!?G?S|$?$IoD@%#f@RY)1kbCIV6@D1g=NRyZp=!*fj z|2r-sprnI*y&~jn!P?^N3>(bxuVgw$*G0knaO^Zm3+p_#9vOg1%W9CBo;>0e8Zw5cuf}_Gu-b@YkEh4twZ++)XXxDV-yb!@*2tLelC_!H`W%7$R@YyL z#@Xy!Bjd@7*JfnvGzRhlv)#?G>k9BpV>+VsFdE(GlVIINhmo7(w!Det-hEd2ll&NY zZ`haGXO$h_NA>=Fi*=oo=OX?2E^?N9LN8J@C8<2 zvR1uD#c0ir>rBucj&;Pr1?Mxpory4690R@sl=?2QV$x*n$KRnze7}Dt#%o0=p5OWX zo%KM&XC1c2A8))fxC@~DIHiuMHcaw__y9=Yo+4nfb(s35n)UD4{tmZynJ|g(?>xcA z_xHDL2O4g8!`7H5Oy>Lh&y+f>-*l18mM=Hv{+<8)m^+1ke$0&a)_DESd;bdP5CH6S z1#~bUG;^_w)WmSV{}A{4O|UL52Hbp&>*tQ>q$7s^#`Yo8OKWfaa(bzf`GJr!Rxc$^ z)Jxr-kP_w##{x_oS-M_gx{B$gd6lB<&!4E9{L3)Oc`Zi1VwFiATnzDT)`H0}UzoSr16%w#Lj?3l3x;iT^LXT5w=yxvi1SDPaR9%b9<0mU}9tX6UXF zt+laC7UpBZb;mF;nvxrs+!bePO=1FH-$8J4Oe#=fpm{pD-xDx-4}tHXnSD2N1apD$&RV0ELj}^?zQfwnP}i2wSb?mZcgByU z2cZ4pC}WH^FJ^xqU5*Kx+jh}fD{=gYnHu|!&BYs@OL;=$cF}rpF~Vft#`}UV^Z2EX zBe4WoYl{pVi32uFicn&pcbYz@dl2{znAvwT$KXg5vAKk(d#Sajp-fHSI1=OKIO7?q zv^cvU5$5>wMs+09fygp?ACAp4Q3Aqv&{+&Q&LKe^6oKh&5}v#B$Dn4EW0HnkBXvW5 z4&YlIfl2XAE4V8R9EuV%bXN!y>kyTl8C!=av9e}N-4L@;H^gJq4cYsNUN>JE=5JWn?MWHghnKU??J z0B*(yOz&66_B2R*{iTEb%XOPn+IZiXnnXze_M=zoHHo?e;LqHIfY>%>^SVTS1FNBw z_ctD^A;G|E=xNB%p!NrDxVCjr_&2~o#g0w&A&y21t(Dw}t*1Y8fCW;);jL3KVLs%-uogLfGs&Y>99nF>Vu9&~WM zAY+o2`LERr$(1z?l5wB*dxlXMWDMBFG>uF&9kLZP(v3g4m37=^*3(0JL3yTe%;0Wsk+0Y3x5GEto*pI9R*(#n*CnS&RgqB4)1%IS-PS#=a zz#}-w=C%{SyM(rJc1m;~!mW5G=nOgbd+ zC3k|H7K=Gn@(~efA0$A1j)=)dO4}EJ;a5G2Nr6R=uk^3i<10r)|C;y;lObn|ue>Da z@s&G7@NGtzTqJ^Tk`Z6oV#VYmFo`swnXZywqFvk?S#?FGt35N&hNALIg@#Y0JZmbf1ls?FUXm5_TFpn^L3;kA zy7!|Ga-^NjSIawbp6`n}h#aay#Cts=^gMug%$Ehkwp&b80^koqSpK7Pj_hgMI7B?eFD~Wi+t9HM(fqLby`TL=sumq zbc$=&1e|}QXR%lyBUK5~RY=(W&`EXMLkF%JgO}235Vq{i28qIgszBn}G+3UUq~X9F z6To6DiiKr~-p5Bi3oM^=v9K(i9t%r)99S~w*A=9+@unfn-V)`0jsX9+s4#t7yH64~?%LLXN{={<4&MHXM`n|sN zWWZV1)>qz*@AMhrUtb);&z5_Z0ikjl(zWSr=ZAky*D76XbUhO%4;^@q@O)mZ>fmEBo9j^ytcOr-;)*~@v-DT`P@!iZX`ey4i zU(1u!9?Vkqa~Z5Q)|=ejzBdlQ;A5)leyjCv*6-MgE$lAxaaLRLE?;ijRNq5S2Ap)y z$s9zE^{Y-F^W$2)`F>T*#drB~mZHI2Rdw@iclm~Ju3|;Gj2E97^W9QiF4t@KtK!-) z-|gK`YQEb;ID^SN%HJDJ{jLS?^PS9hHec%(>E*z^90}yrFn|1gMuF@^8Q!5Js<#Sc z0BLuE=(BV4$D7z1qj_od^18D2iTXcLQLigiCx*yfUKF6S}^{I!gDL{BT*s2Y% zZBq*J<&$gu{QK7u>lDs6a)UsuW*~Tl!4jD)D1fISA-OLyt?4p9Go8Ce*i(^{U?T;OG=B zJ}r>-j|ZF;C)I5QZrd1t8H*8Jula}Qd&?J%&u8d*f_$dpq7o|pr&GWY z`#eiomQitvZ9x=-Kem^)7Y1q3^7l433=! zSULQKrb}P)SirfDp8G2|%3kItF?vVl0P!Sk%JnRU9iFQM!v6u>@F|ERyNwc+jivX3 zgmQ=XG&hJkc+EAH8wfDt|iBTyQ_*DoO==HpnLxx0A`9y!S8-v#5sTi_v=;MpcTNj zv-v8ytGP^m8|S>0tiStm5$EVj2RHqlz8C(E#Lm>JbYVQm?$d3%NIHNsl>SVuXJ(y2 z=&4T^NL>>2bmOT$`rg(yH1=*Q*lP+e;v96IXNow-5X4^#7d8)zHSl_`o^LIaI|x=gYQ;?y~bOl!FKyO&ckF% z!W1^oV-w61e3$OwU=io=%&Z*ilL$Y&zNZ^6@<_8?XL>8bBTxBV>4NBInaJjp??ZJt1EJoJv8*Q9ehuRDr3 zM;n0o1uT#=e$~D1l?u7zdXU29V3iXM42(5Kl&^p&91gqNFKK#hl{t8G4 zJv+7+WknpbA%c7HTG(Fn#@UM#I{j(>l}zRLW^ij z3?83eHsAJ-(+mAx>-+gVU((|N=b091@%xo>@i!O9R9031h_7F&-BXou))~s@ zGcdSMEUO?|AHWP&TmQu=q1yVufyfUDHe(vxI?o6z+YyMyOt|&Ug;&e-5@BWc^B|7k z1-5yJUw+_u5bJQ?Tn{$c0Ndxjo&aWbHS8!aS|C&VpXv@nyA9IjLe8=FRY7jYk+fKm z`GTvE*Us-Jg`8uU>MIxz{yjLg$@#L}!GWsLI_YuQ&K_=LugpW5f z^95I?UPqeXEaf9kAaCe(q(3SIiQNz3z}?>}*an^kX-`<)XR}^MdM9W0Zn?st*OAUp zUN4BOBfW{s9IGQu^{IK-;uVN07Pkqu89xN6P9o#w>?j`E9H z^!q;KoBg(`TIf0NE#MsX1Pxy|N8#%`s%oKYqu=a4p^7S(rB=z8N}8hpJkJ zu~m6NRV`K{tlXRiqNiwqZRCcEv0lB^XsydL1$vnd^C_^2@vq~w*HRO+wVx58hwk3X_z--0#ocRsV` z{mupcihW-;)cfZDM{4Iff5pB_=x;r#ojoo0Ztym&@EvMu^xgkR^M>U}*!Vu0q+B|; z?StQ4(tGq~@B2p=B;NGi&0V8Mm!s5m3sCZV9U1nTLk-2g;y))GIW&9?;lHugHE$(% z_ezlIy^)4XeEHL|Z*IW$nqZs+B`kfQU~1vb2a@~d=1SL)AKZA;Ybng6_U-4q4iS?0l3ZoZARnrvR4zqHUuCh zqsgY`0$4fZSH$TUbH<_GrLK`9L?FKS?0@$Ue8&2;?A6k%ndp zW4vb9WN=WNrTEmcUll$3Dt1)wSFa4>)uDxrCsq(3PXvauEwftHDN4^0LN8@1$*lUap`DOReHS02V^I3Evb{DoBn2y+7 zz&WVxKyA5x1MH>$5Ayo%s2hXOX^iW>^`aOc&%vrpU2;!rEtz!3M`VAmu-3`)yE{E~@ z_g)s{eonC2Ijt9YvcFnd zp4b0aAvbeb-uwg*>p8*Jpa^m}4vuh8Q<1sRRSR&0+MPTynz|8OMgOiwls4O4{iEt( z{u`;1@ua%9=;D4m-Sq<%-=YsvvunG z5!Bfx=ZAE*Xc(t(#Jn(EgP{;J`Xf(>ceO9F24CVc(4L@1xT%{M?~f*h__s1$qe;c`R{zq zd;Zcx0cXVe4OKlJ9J_wz4{Yb8R%EaF{y(t()USE{57YJUtJq;pgOvpa5F^i`qQ~PE zVqjr$)N2e3|F8H5VEOFkuNRhzhXT%FY?Ows5=g>y&f%>Rh-Z#KmJfr}jCk+xELAiE zm?;e5cB&->92B>Me;=6^@=YC`#yME5bT#a_?zCz-wOH738Ye4r4A6TefceB_0@3oq z7ub&BOr@^1rKdg}{QUs4hUQd|;dvG0;BJj4O-=^K@$Xd-I))p8+is|kgTL{~;BasP zd016@hrSoO*OBs2*u9S1Du{X;Vs|?X^xVR1a_*sk^Yk)-BKOl2p>#hXy8G!rPa)C5+dEU(i5QlJ{a%7dB7rsNgJ3X^kAR96CdKU|%{yzoM z+zZ45;2yzNrLjjKwM`|yl0=ZK$jE9|HSYj2bb~;i%VIr=O4X_<(s*?fM~eP?MIWyH zh{CpSRls=+o0UJDQQdWg0(n^PVUh^~`RytSf2Pu_s=al&0%_KJnEYmy*2AQZyW96j z>oniH`WTzIJZ~3K#YecieGeai!ADfp{V2QpmdWaL2k*Z1ad-JXX`SkGuhQOT5j5teuW$IxPd+(iGqK_JuE`DQ37-wilFdrfuvSHCTv zP6l#n87KQ{!|GOHkm!8J6TzLS_u!!O?&Qo~gh0GpzrXlq>oi}@s^Hy4vsXxjbH2NH z&8mR2Ybi)OCIk8PuR?bhg$eF1o*p~DJf&H`yVwwRewXU!7pwv0tF4kxEvuAIv$`3- z(dzJ0dNlwU@11F@0+#4nbo^TyZLyj^Zi?&BTfbc(&2NO!*3aV5*4uQR$eL!X|IaF| z|IZ13oc=#6$LasGQllNMX9_2u&ZB3SAV>5~X#=UW=ifdkesJ1tre(i8T5?9qiDEfY z$oSr&ca9xBjxme#^J`3<*$DzUfjK2QPbzDTsgu>t!141#jY%;08D|{pFMgWgKsLK4 zx5xB}YtETktP-UBsNA~m?w#{t@$$Mdz6fUJN9ChkjiE!pq1>SGx>~H>(0*WgHO~WK zJvgTT0efpXUkA39*1mGY+vm2Y3WU!F(w;65d#kmPX)3zOCZL4t-s=?EFkMr zt9+%;CiprG0!c0g@=Ut0Bjpa*F@V6GoG*|Ci2_-X2!qWih2^%a)APG(QLT zNB1{)7dN`@V)XYV%j?S4W^3PHNZrK|P9P0>&Bb_q*sC#!9jxYJ^13_#bD`dco$ga~ zANICMAjZS{{t5c9*M`+uyutVfSEFq1T+RvPv9SK@(RCKT-u~+o*I5kqU-x0N!ZX~^ z^11R*7R%?NG`s{rr1VVrY`^If7r!RE^D~Ygpl3LgBoMx7^;kZa5ww2n^(O7EG&^S# z5KGe>AH{=UE>{o_BXha3^<1t`T*aHS$NI5@-j6-hi#^nn=hU)mWdG_)`E*{WFVFoS zhWGK!_P)!3X!feT(RJM8;oN+~*>TRN_j2!5RSU)c*HzULJx;#?)>E7)(fj|!<2}_F z$WS2m+dWbFz@^KJ%LEMMvN-b$=rvD*HMlNWUc%m;bsq2jMpZ3;QdH+>ir$aD2&8qO z=>>+xfphD-lO5{2Q}bY0-<@=UG^cC1Q#U>sa6V$t`|g-x`|d>Vk&}atPYkgBf4c8Z z;e(NVccwoW>bvveFXH#ziQemAt@Y^VJl*M{OJ{0Lj4M<^@(WZB|_+NE`m5I-}>R-aF?*V?$k;F%C>T z3d`S!*SjLD-r0CCm>RVE*73$R>V5jGit1FW@SuNnl6>X?UOu(VDEn$n^627Z`S`*V z*}oe}CoxheTxB4TQ49*ziwNugaEE*VXDbJBj?(limC3@s1n6b@!r@nH>Nta>RzZ{J z2G}vw)>=N))>i&`8%V<}*E2^sh%L%12pp^zw^bk?{!MjyECQ?dJCYa6mxA?v2hwBr zYodC;A0H6pwNDGSdP9Zpqf~*+Gr~%$2Na}$xVBZWjU>aYO_k8}&MHA}##6m@$sp!b zV9B)wq(`tohT4GHwFhyo@;S~{{=#|^XDWZiS&GdJ4$smGTQ|U!tBXLQ-`^Wh#RUN7 zYOvRg;0jy&(_mZM3O3Kn0=wI?1%Wuy29jwQq@kpW9<>?Ess%{lq<70psQ#4*J)F@# z*O&w3kO7z-JlqBnwHv;b4UT;V*jB%wg31DScUbMUXA(eEUapW|y$+=A%8=i)0j+iM zXq`(gnkTb5e^27ET7mC!T7KE_B9N2?6W0kWIH?{kxTIXW``kC1<=HGviLDcu_CUZ% z_k~9=>zGB$H#?rE^(SoMv^%o=0|Dppg*VEhi*Jy9wF~4^%jU~x9;lZ6tFM>UDy^@q zox98TeCt%7|9*`Jok#+*<{g#U2|KwAZ=YWkpXcuKJ+}l6W~r*Xy*1QVg4#yWeI=-E z6y8_jZ})4wEqm-*xLyIc}hd$nJO{e$}hP8@Epwt;j@wkA(j-5zjO$hw?q z1L} zbg&|D;1j@|i3IW?2KUJ%Ad8b=kiyl=2_zF!+!KfunZ0!gL^^&wvnedPO_8hH z6n}ITZ_e$sqCDn%>ZZ0H%JvTXRncb#cbAFMYK}sA$((G?k?&Wp+zenonH0+dg8IvR zb1V-C>MzI?>sJ`!`sSXXI$(l*Za*h9@d7mU8w9f70E9OK*<%ujF^A{UEL-3DO(0%}X`uTqD8o2Q zx%jWDb1Hy&3D#_IH8s`-KZrmay1*JHhXw=A{Tz5dYPGxQ+*M~(k>Y4IgDYt7YPd*o zP_uW<3dON#TnyT|vR=1@+PU2vkoroHsJ%*c_~NEHzV5KPCBglRv~?r#GHB~&M%lVU zI8!+XT|NRoWdj_J(t~4gl^r*3hIKxX_!by8b}+P~d;&&%=T zV={OC@-a%czaTzHb^GF1B75T>!$`4Cg;mVf#30s97l`k3)fw!A)=pu`jfG`hV_jLP zAr_8x+}YuX9;dyru8fbfAMIQmTPLhvTCneay#44lz~Nvmd{dnLpktf#{fPcnF~DK1 zM{$1Hjd8xE@ZG5Az<&6$>iomY6ZccgOc2N;$>7e_d-uh$@3%$U_iq{C@c*=ZU%DdF zzQ1@y$i9F1t#R%9ZR6PYF}=;t(Y}uvZ*3g>_y_I#xI7`uzK@wJXy4!Qvg%wscIKQ+ z@_b%f+!lz;J1QHcbu#LqNn&QM0aw6ghL)qsaPk>~5&101y zP5E`eNqM>P@GCXwb9jK+3Hw3L>H?Yhivb9-|Dc@mYh-UJH{Jp}C|x3ZYdMu)$lg{S z^wCHA=D$DX{C)G8E$bp`NhayFB)jxll9%n(YDqqBpfWz&D`OD518erRXFzY)(KY-2 zv^(JRU{LBffz)%FZ|?ic=`*YHNR%&qXOu6!>ny(XSI^OxzH}U4diMmr^m~|Ild1dC zKXf(9nK8cf*Z!%#^i18C{-Nvr-pmPn>6sC}^qeSPI*Ib7f2#Y^jZICyJpk@vr1{m` zIUuu;=1(8ddxX&EYdIj6CL8mocb}&}J-?~g7wJn6@e%*(N}1#dB*;Tv_pA+9?I1mIK%K~69Mh-$ zt^XJLv_Ib%DNi;uhU7{5o8!upxV<@}pPz?3iQA_=dXN4=d9prAp6rd1C*$^M|Mg3% zbN5S;IvHQ5^=8+4Vua!cm5pKX1O1)|#k2CpfU_<&^j=x`d%8|)r?$PWGkv=;U81#k7FrRMwQ<@wxedH?pa~7k?lBUOfG6(MW z^ctDVk!fACUMqQqQ6S9-dF_)yEI|TkK;WK{NS|3EWLPuGVlr%n@grA9PnIUbu)U`4 z-GGzQJC$3M7hC=SGL>0D+wTnk_q$xA?bm;*dEb7$mL-K@KlhKxq;YgUN2{%_)|LPI29EpG_%)nD}f zllZFM@A#3d@%gH3I6uA`JqEP}yW{ZYxVB(QxGi{o{JGlzd!y{bnE9xEcu=zsFNn8O zd4JPZ)p_Gq)p^6#Nd6v-2hQa5cp!pVb%i1R-CrM{&%awA?4zae?qAhM^6~S*_qt>d z|F`4$)Af;f-dZ2RbMF5yc%JmXAI~>#QJovMs7`51{J8fq(DKALh#LL|eOamX0ZX`F zOKro0{?$gA+(vEcWO;OPihO+GB-vlZNsnG4kYku*HEoAkj0-D6I7@j6z|pVg`PZdu zdHz(MThn0WP#TC0K6S6v2rJ=pc%UHdI{y%cp5YAeZ$==>rIqrl{|Zv~lGu70t%=|s z+6vMu=~@kjnE+XC0vqS0Q@FwIQ8zj52uzQm`)PtORh>`IBb%aeZ@nwPGLrp8n3EpSreUG}wh- zD5vlC8T#gS;eRjRlP(Y$Pxp1CbB;gj`S!=tv|PY;u-CABVwICmYz1jZ#j@uHtslw> zY*koJ(lrK&j(-4WDwzpd9!VG1H#ht@Ixovx!Y`C}>GNu}Bc}WAOXnQzT!n3&0ZD61 zwY=2|wAO_C4Hxdj`!Vk?T-EH z1~|;(X4)P5h}sjo^qLc07!AHu1%tsm_HK*@Q5AA@lz8mamN8i6|nTFTs z=J@?D>AR2pNbsFZ1ov?k6GF-foWXeC$wH7QF1^Wt+tVu8yibEP5?03{TgOK$Hha05 zS{(<9_Z4Yc9R~=gvoWiUZf12HPGF0|#`CMaJN5kH?pDF}>eC>}VdGl#aaGRjJ#a;6 z+!^|~UEpKm(%Y_(PMgAA>s&38WK)d#WA>Ta5*hhrwN+ z6pDk@j>W;I#`OhQQ4WiP)la71WU@HeiBxdcB?t2}Ykey;@k+@Q`L?c<{M#QFNTqGL%(dMv3+k0m`ipv96NXR)O0h*;9$t&#Rb zJRcObC*t{_&c&WsJP;mB%4YTiT}Pz9Cm2f#`g?-0B<(CUd!i{KmK1JJWFlaFj*FXY z5pksRxic9ZM~c4Ne&zv++rJ63D>9X(|EkeAe^bCoZD}e`*u7_f9{OG%fVDh98Cd#yq=yziQuNX*u9AI13G?&a`_a_aX`0WhMA5R>Z5s?#uxVn`C@xi?h(uH z`vo_4U*JGk@9K9dCcZDgYWZBkQ@*%9$QP@OvG)ZE*&bMxiF$ly>wERf8v}9seAgzx zf97)_(r<(Wkb*q%nkk%v?hVD&1K6xkTDocq=b-XzXXC80=BGe@qz1|Lg|OpdeNX6K zG(_};u6W|N7(^cI8(0ok{_Ie1W^Au%gHZp|htFYen9TWgPUPMgV)y2=?+2V(ZZ18$ z*q++ad-VJ7YkTxC-J>Y{fJAU_X8xMcKL1QrEfe6t`hrV};^M&7=Kv>@`*3jtoCi&@ zaBlwox#56Qhp#*ie07Q7-UYgz@+8QJM>3xeJHDZxDIK4#t2heI*D#2zr+2+!3{K7v zf)mc|JP#K} z=d+o!*QhGU>TSq}r*IDLNnzt~5lD2LSt`|`E9GPC&bBt^*~Z;6svfSqB{gQ;FDFNi zJ3Y?0L*YE@(`(0g7UF@#{En`R`JL*TW51JY{lx(3!FPB8Y~f>|&*1^if2|)SKo2(s z{J?9xF@kS?d2IyWjQA}ril;JLH)z`;$xh`!zOchu04oa+h{yo$`~;z=cnX!-APpr! zk0%324S?gKv+#~Fewuwb)9G2?c%zPETR~bTActpb5XY*<>zTa1;Du?Cv=r>^uvNz~ zt3ZDDFAT>@0U({)cK+4Zj@fcL9h5S9SJg;*52zyJZ9hO`YkW5$w8rmT;2MKH8$MQ5 z3!*Z2YZ$Iu1+wK|G+e*_hFF?rIZ`Q9pF>JFfZJ*mj^-l}>r4X4pgK~qz2>*6oTJVJ zM8M$oU@NO(!WV!v@;AJF&u@p0T9MJ)ZUT`v@*VU$bY#uGnW>zkD-qmOUej-liT0Wn zPUzv0v6HTOZMr}Zf*xa9q)e|0mzjJNzf96?iErnI?${-T_{iVqof99~R`5wd#QwGA zYWrsmn|oXy))kUVtzmQj{sQMNni|W)X6yJB&BIVw|Nr2-GxW3FyMUf8$7t*1Odz9+ zljP$Ic}8PYZUYAKxGuMk>AF1C@o!J%9D;$$ZcRU?I%st&=Xi7x$o1(0xt9}q7#(7> zvcK`lGD?fX7<%qkRp$^7vndSKXQ9g!UX$r8$6U+_;XM~7)3<`uJa1y$XF1x((;{Vn zHTLYqHT?kx|?}_Ec63gU+KXU}Xz{SeXcJ3jaj>c$c12 zKc?I8A$q~*Krfs1y!!Ax58D0V^wPLAKD~tV;^HV?{8~U2S>1*ybH>)UBq6lE&%Sek z>$^x>-zPy{97V75^z;3EetaEU^Oa#{Zy#s=22eUx)mevNcAr7$(attg8OCN-51>En zd`Bn6o^P~18*k1N`kcqvyqewrl&U%f1hb!C1af=2Kw8H5K!y_J0rv$|=S1`MC4f6R z&zQwWK_G8T;vDsb0;}&($AL)ks}4Y`v?FkjVykijo0(nrD*ZN9 zARie(>fHj;evbE6sj5iVL%*Z=|KcRAu5xoakU9=}qH~l5Y7gcMJA(QSZx?LV#A&Oj zP0sTIsi(iE2%1iXtqRlWg0zqZE2+&I{reE>)1|>j?ag~ZvvZ3fqu*V-TH7 zK!T{8A!9>b*+>@5f^qVzf_-s*vIV5@JIYo7vWpXXD6Lo$fFL{c@FJF3uCw0z#-0jf zI@NdL%vq8-@to1~`LJ0D&dKJ>W;xf|d`ZZcITeUGL7SV$n*PIMApM0JpB+XZewZqd z+f%{)kxA<(+Bt14A(hQ*b^KMxo|RPWS$kDe#2w-KDHc#6PA_v3V`u)Qt`q?)$_PC|KcGV^cB zo+KbcEZ-!X)lqIt;T-dpUsXo=J>}a$p1&Bcb!DSL%%zSvz5@hn|Kj1G5do=CRm+8byHHgvRQ_?l z4mhJ_mE&GbR@tfpPRheiBvU;^A;`=Yf&s4p7bm$*I0 zxQY9XLH0k^Z|p4tY~ydJAjOGHKOW07d@TXQ_UVu=kE(}DKK-`z-l)2FLDNi$@nf{s zbzm}u7}P~`C8w*AZ=L+tbg7X1ddOy6UcWFxbw%k zXIqj4gL6XD-r~Sr60dGYvOsE4hIc3fMAnBB zf!ma%J&U|&o1@>e{nXVc=V*77#>)-9_$+cHQIjKotmGnOS25UYhL&@3#*;|)VNk4g zuz7Za&3Yrq{Wl9_7nKM4y{8=j?!xf9xF!&bPdD$Ir^hKMobx7#Q{=R)a~13Td%vsG z@w~DAy*bK_|E2NJ&#n{5Je;S;DJWmeQBpW?lmeIw6G5bFYn}{8c16jRtr*0*IOpc! z&Q8};0L($0s7M2`f4V^0Q{vMb&xh!(62NTzuYhwN2CuEn?xJgMJEe*ghl<&L1aoCH ze4%*Kz;b0WSbU@2^rYw?Y0D!VZd`uiOiNN&>{AC>39_(pKgBjX!6 zdVJ$kSMg>I7mFwH9oYy7-8Xuk{Wk;YTY|>$K65eoG*_qu9khZ*UP7t zT_^ijUn8HML2Woqj>O|H1Gy9P7rWsf<1eoV^O#SoA^tK6Rz7n|6%R}X0L?%$znSG4 zzg8>_wSn|G2C0zO^CR0pYMz4}o;KaydZluF8$67E)PcRGDCp~M6KvHdlV%U)3FNP} z0q2{lYS}a$R^=zc7~iY^vl_wozW9?mA>U*EraxRU#`m}=zIW@K3*&oBb-wp*K($a@ z_MB2LSat-@cEG2yv+eMyv9cpUJKI-Jsuy&&KmP}GjQ#+NfiT=CJ`{-?uZ@i1#a z)9wwOz@Sh*K6DUdvz}8jvJ`Ao#|z4;Hv!xSqVDK=PBrgS^*g$BU(^Zi=uVWMxq0{a z`I&PNIR2UWnXS8H^E2r>JPfYLm^wZ0hKQK@$F7_~%h>&h=$QIgex{zAnH?2V5AI#0 z%(3V)=VMp#X3JS(>f`55Ky;2*R8D3*e4+IJke-uC?Tlyjyormh)ohArzfeIExGBv< z&vpCWIUja6)|K&-WAXA04m$cctsYmjEgoHyD|%eHv94@>D$MHRF03Y(7iTE-lPY}u zdR;D4ST506Ut|p8Gc1=VW!-doetND6%Qua)reMCQ*AxruMER!81|T!SYINOb{DW(q zZ0=ma38bT`)R#O?jjq%Q^NM(uSLBJ4R}?ElCa%%dujds-`{bhcqFv7kl^eCXQ}NEe zp95mocv-}^9eOX+V12098cWLhI3Q1t^KN)9ZoGZJ0Rh>ps+MbiqB^hniR$#P-l^q% z==UYtIdDghJAdz-4@(>B$_}B}vn)ZecTcH)5j;!(>Roa7WSyStI-?=KY(bp0(s4@> zkP%h2b-DdJK)xTVkmX zC$RX+3H{F0NeoK2?(@Dk0mM_9zdL?S4&zyLG2Q=6qI}-G0k$OwAhG`M00d#7$C#n} zqNjpZlOt6i#(I$R6M+n+0x8t|-*MMqOqzHN(eo2*QO>poOM<=*POGt)pM-pLEyY+M znol8%#iS2nGxM!deo&05j&hAWy0}XA)mF-%vRy5CptSKT}kNU>jae@nN4CmRK#Qr^f>eOSvqnVhIU zqp<3H^(!=q@l{nH`>=73Yx1v*ohnLYHt-)*)e?MH8LLa9y?e89kLx|z*!kn8M&IA@ zWaTSF$LGD9RaM-NEG%#4_tYkva4wT~2!S{m3FOBJ++UsJHv)jTsj1YLf&}sf0{4&4 z@}1YX$MwK3weP5{)KDpqOPelZ-!|MVkl!L8Rs^IZ5e6G>hPe3Ha9EuMSRiXDK3yyj zhTDbz3vhe7K$;7~a62~+ZeI-Kv2=kvx&$O@tDQ6mMCGzr9+PLfK-yK+Jyc2U)OjBf zI%bx@eC7>XD&*!YAf<@{q4K>kk?xT|W*~@xd!`OItCfX8%uYNH*!f7Qr|p4Ek43lFvMlDxX?5S@zXVkw+J&$;TI_ z%l;}XQN6IgPO!D#4_Ee^g&ilbK{Gj%SE{{8^m=l zSI8aLfwXy4U0?9|JgL1>unp}7=_QN?x9IiSqHDVy-wl#nR4y-?jU1lcK|j>E_w%+D z+{jCnC)LBj8g6Y^^FzG|V5WL(GpEsEy=jjt`F&$2m3Ms8avzU@@veRj+?VLQYZCL{ zna6k+)vqT}+U6!P-c=i;6B>1$aF6T#USsD@l+1V+)vZhO1X7v^ZXs+B!+GrdL>Rn8 z_k(}I)@ky#v6#twu97vT&J~<-pu{4OlBN|tBL;T~638A7+&AfKz0@d>{rXzzZzBlY zm$J2{M)29+>HKIvGO@M(-uRyD?>kJL`%wy8E2Z0N4%}21ZhW?)Y(56}CC^rr@w-5( zMJdY{v^SiVPf@E*$D_8K;vhKENzE|<|vaYrl%H_7{zDxk~o=k9;-YeLO zcY%~|?3=r@ZCcq*JiUy5OTVG-cDGIUnW!8y_RXbpP(9d-t)-#gr}<<&y=-UO^s?GS zSotcpmUX3oSZjopU;wdp60EGq05OPnd}1WtJ(Cc^J9dxxNn;4_+R)&Vv*O*=@>^G4 z7~U;S(0${(_1IdGK&*ELoSQJ%HXQ`p#T=NQr@A}XYZjbT_b!;0CiO3F#Kx>kSW| z#RB*$kUSVjbWGqI8Rs7p$Zc8Ys@CJzcj_^L+Oha`uJXb!1I|+z6pDwn*y5dU05KYF z3UhU#=BuLcRUC`#^T1<)P`k#X-wBBRe(mzQGPz)4UsrAt5PGITUso;Gd|e(a5LT1J zsMQ)BuRhfcNul~wl{|=aU+G@ay^ZMgkQG0U(VuztIL0f?zRA_=Q~lA^DCc%2V}X2u z1+pTnM%9f;u{Ekvaioun{(WIJs&aLG=8vxTdvnKpTy(tX8dWE8t`Z(!$wL{eMir%{ zC3;LhfyGZgcJYj+_yKnJu4%QeTaU4vNft;629gC}=92|7g0*MGSi7f}lMKYzG{;wr z&oACW&$)OK-;slW&~sw<{U!rB?X8g8If2L+4Hn%CQX%Uz4>qGwAXG+E9-`gl&Qm_e zxyoN~ro!q{&+(F07x;D# z+`*c_v!iMP*Tty`+!a+5SY52uh8VI6gwA<-alp9|VAcqgr%3`?yOooVFRYPA7vC!T zYHyKGEn6s`dEjQ*zxpOw-JQVVP_OU@B+qDMR8{P|J-ST4QEB$Mn zcRLKQH{7rK%yP}I>OGHlf1|3FVzAeAF993XPpQ5Tc~`&kiDwarkYKMF5(Cce1USs^ zDwM4G_(LS#FopiRCE@54>yt?4p9J~aw+Ea-{esn=f3PINhN?_FyA72%^Za#L0qivg zxsZO*eJY9R7b_MAoFAyFWmr<3nR?%`6Bv|klcrCZ_1{UcXT`jx&)l+D>-TnIu2%bL2v23c-1h+-`wg&i*r3&h+AIc~ zacu!(q%F`Mw~qMLa&TXRI$Lm0=^pl8abf#c#mDMrQx^xEPu?DI2I1`2pJy!&)!3%b zGjG@6esgZX`Lv|!c?)ss22_ERoG-{DZ#?@!!)I?CmGArP=$<#eJj$cw0p4G=F=LIf zvwFi1J}92Q{b>6|dyY05K&sv_bhH-n-s;I9rtn%_few^BaLN1)A1wD*ZG7e;`RI)s zetooIjj{8R`9nu%kmh~O$mDHoS?8LEQoQpoZ+Fc@ytjT5h{b<-V&4gjl&nd{0m_pW z{XF30lk7FG<=gL{EC0S_s;>+Exx5ekd->1NJ-*+g>As)0)cSV% z=gM6z|EGK>n&zY5QQQ0XEmmJ&%Zuf^{HnNdks$LZrDLrLNP8*BJGl&|w{0|NbylMD z*;$R4HY9Cd6tHx0cl+LGo#y-bB8q!vWfPadbkH}ryM68hF!-pdy5D5I=&~5!4fdiN z;_mX1)~UYDi?kX%z9b+8TUF;toUK@K7VAYvxVwD5C1@~5Rox!O&vO(j%3Dm2;^Z?WGo{1`*n)~manU((@-KD zj;`tS69a7fpRVbYwkWcu)1*bAnoiGdiC@!+tvyanr|9SBTGJ`sc(MUzMeotsYC1)a z5v=JHJ;py;(i18fVg=@f6iU`?kOI1R8Zyrxq;c!M>armt6>)7Gobsq0mzx;t^u zzdB7m^FX?MYFUQtt2N7`i!XT1m ztenA|GBgj!0-QN;gTHFyAury3=+FOt^u9Hw&JHxm>$L*eb1R6&lLg`};w1GTwyDiV znM0WaY8z*pf2L~V=^`M$T7z7&#?;w(FGy$R0HJ*Ui##BQnt6E(0~Crz60WD z29V=8M~U8}MSJIb_%R0^zd+QcNb%D5-njf3*Oy5^7F_}E==ZDl&iQbph?6{*0pSsJ z5UN+s08+dQB##A1aRHJ%-vly+)vC$pcqbjmaK{aD*SjEPC4htK;sr?PDQ*#LU9JCC zzPa@W<=tD5?c}lR?emb?ThiiiQTv&PGaF`J-tMXotl8JU5PHX*>l=}C-5b>lkx$9!XvP+A z7YA~;2}r&P#P%W>wB8FxmYP63Gl$Y=-oU&TID$gY*>BMVwU>Pr-Qh7zHtLRCe8l#bIlS+OFccUKaK6;uy22qXjL z4%7##Hg4j0@BBo~_NO+~0i2;cJelu!Kt+yjmWyKX+7m%+G@(qw^a74SbtbRqQrs_xeI>oT^-}A_v8l z>dEE~`a9KMwLR1RrO%S||JVOe@X@{If1r)mWdL&WDuHyrTVZ==2}mOct87+eTu%3= z_zQJb5a)&tsp6^H1@fW4aofAI1fu-(r$>L0O7|dlfJajYO8nPs|$ZtERtoX92N)u8PO7RjI%k9Z%wn4l2v)H>=KvDv?x;Gdif8FHlu6huS|J%z8an zATtxd-94S^651W=I+hb3lzW;^)y09hHcal_ChGPo&Qpe~1Y+E*Iw_40TLfZyT6I!7 zr!-D!ozge8wHU3xix}M}sH&waS0JxX2O@|8XIB*rzJsm4zAn|d^Ic@~2UN@J=>nq}5eOvQ;68 zuRxL&WqW}GF(3b_{GqKdc=c`=tZRFrT)Xp{s~qnQIEA)d<;`5Kx30CNe8{hg1s%;Y zg>8fbhgVfCBbQakbUg$Mgs#EJfk^eEIs~E*Ta^|ryJIz%-9f)e*{nLVtB};rWsmLm zLtJ);Z>B(APY3dgfNG)tZ|0_YcL9jMNC)y}K(%PSu%~+MswzI*dXG=!z+KPP`lya) zMP{atMEViTOdkpNBYb(Ab}n_T_xK*>tiF-k0?vBwuCj+K(ID?nnq9};?fd+;fb%co z$kT8eeB?5Llr|KXY5WYxZv*H5%}W8*GBTq|<|o^0u1*%n=^}xYtl>LHGXx?w@STT} z1ajMd@SVd&oJ8q-4+4j<6eNmMMI1QpJcy)+4xl4QRmJBhFNm6dodLE{JxO>()05uQ z^`x`ue|3o={jXlv|L$l*gHJ~3e_aTodQNNlUwF@H>9&ymM`5En;4`;r`1}^O`ck@7 zCp~M*kEkx_Iem6ra8F}h*@#bNvG3ojs>NlXIA>PcQw7Gm=)O_;cV%*{ybIn*8p)2; z+hThyM#{haPl3GO1jL&skdcG1-B{Rqw3#z{yR$(Y@#5{&P96F4zaKqx5Vn^V4jtv! z7@8{OU^3Ek5O1%(X6Wdw%iCR4zVv75dV1IzZ`(WP!}`X$GEZ9U8XI)|bYu>Y zwFjE^QJbY;l6fHLOApG>LwN$B_;d<`lHUe$JI8mB>B=yC z`Z3b*=_4JVMscR%Iap$gJm$-sb*xq(4{_l3EDiBPiU-mBkm5l&Kb)-N!BDNh z#yYkXi0QU~(^Dl7iVNM?>RY=>b$YJX;@Be#1>(73On=`S_s*WC!|$Ew&R!6|*A{BM z-XH-)sxutJ*3wyEugRQjugL%~=QlO_s0=-bEqYJ6JSF^Y8eo`xXdWFqJN==;`K9v< z1UVTQ2M%F#slxziwUau$l?cQEP9PQE%IuucS7BT3S7*(r18I3hg)P~yUU{6|Y1j1T zdJfV{(M(e*2HRzR)iQ#urBtWB#LxK1-Y7a=AAYAW9^9n}SigbjZ`<`Aybbyt&FF6_ zUKJxC4RO9*8`d0ac@FOKE&SuuS6p&Fgfx837= z6kB}{)C8RM_^z@?t8_k(@Afs;XndZ|KTpreqyKMD0{8r6))VWj_@|)r!@r9){(M2_ zN@Z;CGunQd!`52Noqeqh`dy)sIRY7PT~{Xqxh&4wsN4vykIIkbjU{E;I6(fcsuoFK z&pv=&YR62cdL@fN=CQNe*mjTaHV)kF?CdmN5$iL^i18UD=x1kdyT`W?TYXRyaJJ*S z$~Nj}XUBK@PTv|jyP+aZs_a);4eb}oVsp-|XS6#1CHaD!iHzR5B&`H`L~(dYB0r2No2-VC}t{eUJ>s zfo9!4Sm3YP_XV~p3lc%P;mfBs+<#=vzOQhy@-39w@okjSkp?LpU!}p3XIel4gV2+2 z2-+~I9V2*>Qj3zAeNg&uf{)H;()IZ|1KoqjJoO8u@7=0uxuse=Z%r?>md<58(#*=d zvVc>oR~J?Xw+bXHfX!NmY{hjIwr&Koj_WmIu6t2+)-3_4WeG^vx2evS)`}h$XR55Q z-P?+K8kQhieI>F5YtJ(Oh+f0)xSkJmED4DJ-?ch2^jZCq3Y&+6S&yU&Mb zv-6Ah&XZpR@0VXF&p4#2mhKMKdA54JCom`$5XgK$1IIC^lu|wB7~0;QTH$NB{kfyT zx<1LsGH~Y_W9M>z)yBp(#?D%7VmiLX0PcE&cJG?%@!S$&PwPSyDhy{^_{1|VPFqV;!behTDf6A%jP{M(0*)?%Z#-2mdDV~FW; zjkiB{)O!rJzp4zeyM-pwyssAJdKa{~nB7@@`C1p%B|Hfr@`-#$_K`LFhH$oWy{y$s z;UT-Djsv;gr1dQf);OiQ#UiKbq_mmFWSvE!Yp*_~idLM*?4{#4o9&;E=~8(NSKEJd zPgy(NzqVT6FK*HHZ?)mG+P8hpSND|yo=+&jWRTxeCQN% z*b&U?LcXhps)F^`rz+n%jU4rrS}h`DoilGtAa?`w7E*fUs4ZntJQ&>OOo31xi`v^i zz2XIz4T1X<70JDa`H~R=Z7i{((^sAx?z)b(&=2vz9nfA>T{T%J! zyDFE}d70|vFo<-{;vWmX`ZH=TB-v|@V~g@gcfgtbASY8=vSzcoVT$!hkj*@hd<>-i zW`XcXtF={sGmru-kh&Uy{B?ustY4((r7i+;24^ZKk_1Bcnx6aVTwpT0=M-|#Gp9P` z&rTsnIBvX5*I9@p`ui)VkmLBm1@h?P`LeIJT0XVxdil%)!P=c#-2}SlWA$$`1oDT4 zTE2JF?D1-~ffB4=rPWZ&QV!xwrS9qXDE7 zbsyL18XN)%=Gffp63Fh&suOT<-IT5rqArSv70j(z*Tf14Q zt3fhar#hS2+Ot>D9)Gw zgXZBYC@MxslPDxKpas#=#4`yXl4@)QFwCUK;}B#9d8r`kJu~+n3E-nc10mtn8%Wph zv#YuxAbMxc{hjlfzml%1z4uyst-bbl?Z;Zj^)3hDk+jhlqdFH0Ey-X$s6@f`G!~r7 zAE2wb4>)W;)V=o;w8?Yg?4^Fd=_@KP6L)qo1t3n9^xEz%f;F5G? zdp;ksOOwFYLS;>;8BlPvmgUz5tgb$#rNvn#w*40O0O(WspQwB~GO#738Ck^$oV5e^ zwFi*PVe2V4It?*pHa#Tx$JAJgD1)2QLjvKQ#;7h5`*RoRKL(tnpR_(oJeYKb>PeZm%|Y6aug?l zuOuI`i7ZR>;PgjV34I$BE{1`LZ<)FtOQ9G2q1K(GE3Mh2G@|#<(1dAAGYr6+&w} z=zgBEDBhRxh$6GGWIksDpNyVyWg~#|8g20SX|t!q0(c03*<#>v(O@2bU7FlLY{tU? zb!{|E_!A8+`%04=n1Q^{s_(y$%_*q$vg6`y0@(d zXGuEou^CSZR$4Lu%+sSm%~O?g07tIToJT!dj2d%J z(TrzcI3}f^Hh6OEAQ~XaUEEE{B?ADPuPQA>-zE~>>CTtGQqLRwJPtfDS&`1vDpH2` zwJ+H;KAVZ;__P0KxBsK_-7BMDtPyy8K+ogMC}uHXNw; zZf6@lM?C&~@l(OG6ts~4w^Gn@fA}8AVFQn?6bcj>z^Q(RpyjZh$Biidrh6dqRGfBJ zlG5rUmuH3q09Ao^iky=E=5%X&CzP^aBPM zJfL_9(~zf!u6+Q`8G1NUhM1L+7>T4$12p5YhI!)*2kOh#vkj{dk5?@&3&zmULjFJ0 z>yFDB^^OZt@3^cA-?dw#=dl$TZ;Ge$^LJdd`#7g*tEUk`S0vshv8BD^&s}>)FW)Zy zTt-?r7j<7~v8CDNzTBvzoR>D{%f~22T|aH6`0V0P^!Pu0%gcq2LRSsJ z-WAqaWGpde$Rd6Np-GMRh@g(tMd~@;qd5PrD9MEdu)S(9IH$$&J5uxnV{e!qGd)%_nuN%qI_Se^%Bdv#k*GYhzha^-d;115aF8x0AB#|}Ex z(`Z^5NKXJKo6yfaZ4mF9^As;z2SRyTI1cTykm8(8^LTbhX}P#DUw$Z>$Ga#dkgf;k zv3%H`o(|4qbD*o31LwY%t+UkpxXF+;7r;DF4@U@o8n;D}NLf;@;Hu)hWa2ULONmb^ zQ%MJHJq7C~EMXfuqCm_;eFMc-GH)au)Z`ZNRl|1aJnZmz+PjIaW{rBM{%r&;#AnJF z08S=4#SL9cj@EAqNzvE)RP$-pAgEKf4+d%dEjI^WX@->~}fBTsX38X`Wn(k^;M`1_UqCoM(4P zab6smFP|Dh$^KNpl_*i&OSnXHs{b1Zuhjqo=f1H2TePe&ci|FZ6MM;jV8L0bggYso7FzR|oM=Fnt(m^g^0k2VgdV`1P2GI*Xq8IVt ztV!o_BI5D5cxbt>IbTj9wv93bsAx?$K1tAYV_K}H8<%Ob$DagQPXn0eMr*pU)uTwH zEGhR10w>Yi+OXc%uz+1*y)6bXN9aw9g_ibYz+3MLNsj}ViSIzhKN`jqU6@O}Ies;ij?qEf2qQ#;p|>nD0cxpIru^ME(U=DYUH6g56y z1osi!w|Q$w>daTvGqvw+4N1WjiWJD#)+U>_hNKHC6e%@~?Jgt(?h9Z}?iEX%psOAOcb&J)(VeKFwVco5H=haFx|dw0ZFeiHFG zkPLVgN;$Zyr(j*}5<|lb$vi;%>+gTp=AmYY%tMLlJj4Q+)ww2Gn`@F)T}bv! zeJ>>WDSpSF!gfWQYmz)gmo%GFNu{V~NJ^>-gGE)}=EzmnV97i<(p2@koSpOFNafNz znfMl!RRejv}ko9Q6G!vfB`zUOLC^|>Rw=SuWBvQC(`tT4D^hNjPva$`{B zyzs5@gbQSaro{JWgpz;m9nrxD@)haP6`KC(wuY|fG_M3LHdpTGNPIh5zB~x<^>eFx z!solgvX7kWPUfvbfT=MU>(tmk|l;)Y|+i~ zFYYD(;~Q_5e`7vu|At~3h^=Y=-ymPwh~y0nI2-3^IJV|x>#TiAkVVEojq!$Tzu2hB z_Ny?C(DFJac_M2bKVC$2$4bX$of>49OB}q+%mtCyYS;hOei?4EU(XNb<EjhKpOFNddYlTSmqrj9+!saBs0?NSmf*}k?G|@T6{K}D)XN{ zC-VNvPGp_rsr81W|6G0}hdmvZ_wG@loATV6n|PUgV@2k`Km^VripTBfMjmqGj8HQ1 zXY#`F1r2lI2%(Q%_E?q>-W$-*2uUR@k1we{P4ArLzwDbPr|~%ApQgp$@K00p|GaNH z^d{dlMfFX$UsEJr2NV9T`lcxj%rY&uJx_yE{cYf}pCWpf7$^c2!{U7m?EL@BS0(jL z18BLOuiDhhSM3NYEw*01s^=f@Rpnm3YVyYa9$)o!;fAkDc=#oMb-Z1X?8_DDzuTv| z;{Dh3X-0+==^ycFKG<-3pJwlce?6ZDn*V2gngttv>eDgE*!<5f#2}yfiRir=UX+BNamXNgT)&G8<#y{<+ zKF#B6HJ_$tWat;qPnb{l#vZ8whzIADUf2W2xEwD(_+~e;vp&5o}VTVw2Q> zE4mjpxvaEg0hnte>*&!xk4+c|t<4x!qvDg2s2ljCvx(r7e(uU!@JUe^pOh8Ak*mLe zPbNk1$yp7bT)3j)lP9Kyq~f#r@=--eCOi>-GLV|LFq8Os8Q^lfn664s80L#Wf?Feu`@b zUHjL?HR9d3$2IP|Z^kt%?*1vRxzPBJ;TpF4UlZ39Z2GU`nu5FkXK~FtjX%XTtFQj+ z;+m^dZ;xv(PQ4k|bWQy!u6eBSmvPMtUH|X6CPxlQujXpFCR+|ktE&{rm8;>JadJqi zt@`iBH9MyM6xZDOhK6e#!+&~CTFuF2=5Y}~OOXZehN&Uxd6vf)kd{j^a?c7VBA>_^ zPfb2N0;k;TJng!vk$dnrpFb{QdHlTb=5xt4QzPebetu3w-@!AHvxPw#d0fzz>!-nE zjnTfpRC)iEUKd9NFFwVQ;G)wE~JUq zPUXws%ML11Q4CCIt}YDr)AP6=2Q9@E?`x!)fZqhTip&A|AT~xrS7{XQ>!7Wk|5yrg zu?29=ipF~X7LZ9V&(rCpAWI362*#Ww7tcpN*B_YL#% zawg)l3lS_7dhACRC)U=_L96O_*`XXU;55YY_!P(EJj4dZj#^p&d^EINq^+J51CRAu zZaXn$BZy=?x}w0DO7plvA$UgPQx{aE_E7W$CYr}qWC@V@Zl5|%Qp0CtEuKB+P+eP( zGL9L<`#NG=j<2HtTalr(3BV~=Kc>b%CA>fsI3t*o;ndtkEuQMff_@W^1-)j2iYRdU zqj}sxvufXvXS**eYVM4YJ&IJE&f{r1*hzFX1wl)sP12qVY3FWUN(Zdrs9zpqgqHS@ zqSDeFQdC(Lhm^5IMiIG?b`yFO=}b754XOJDi&noXD?N|*T~k_Q^?%0Qw`Ivm^F-E_tD>~|ebzZtM=)5i5%9O_9G~R*RdYy+#8`R32)K956~Z&C zXm;n3VOqQy!prE_wP(&@H=mC)g=3?i2W@X)@Rz8r_gT61Q$op+|Nn36uu1`YQPpJ?+4nNNygbeJ)Bc2 zjq*wIT;b$v>R*HWz4|vs{*nBx0NkbiX600Htv&U7O3plvL`Ix~ZFW#&5Z(7+b^J(h zIr@TYEn^3zswP)1YuZ+>?DFYm#kI+kaPznJn&k^6iwbs9pkxBa<&+&M1A0+z=dHnc1l-)j~ zE%y~8Coh}_xFj9qj@dl+Kg#2xKCkAKq*HQ71&{qN^0*|Omi>D`>^R2zn6CSSB^1i; zn8D-XOu+v6JT9IZCHu>GTs$CJ_CLYn;v`1)&m!dvvU-2+Zt_1X6Wy;2#mF6%JT7?} z@S=r)i#O2OZ_;3%hFp$alqJw{MR78Em}wmj<;~^btObZau(_F$GYbt+zA>aYGg0bj;Wad~ums8ng%qc4H_XhlLHV8@#rY%+X0^?dm$R%NLpd69 zqm4lboL?$Ra^&|3tc2TqIVqkD6M>o3IX%5sofCL$Ll(DyEN(JiGMcU2Qq-w9hn5s)RU%a0HXNK! zqSVn(?S`4FUPCh*OQ5{TCcI4gsO&YES-A+6GYi0ZXHYp8pU#M=9SmV<;QGWQ6(VP>HX%Bgv( zoVo~ac13Yspi@1~lqK-vB)~tUf^X0h;H;%A2QSe&HD*GP?&s+@sM)IJv06U4bYDgfIMpPjb| zmACx{oB{{pC7ShQhG{zqa6?!6Liv0EC*gJOufa)toU~tSbrCFVD|sP{)Pq8bllUX~ zkAibQ#RcF|@~tJ%H3qO!880htz_mr-B)nX%;IU;?ZGGV%p=;kG+IiIDv^A4LmV?Az z0kXJ%d@fqXG+<0eWnQE89)ewiH0`d%Brf1vwj=Fw2@FVLwm0j|6VI6zO% z9-Q20QP)c;9!l*@J0rXWU z&a(jKlbs-6pmm^o`FG0VP6>~J zZ=yi7(n(ufW5M}O*$Y{DuS0oLGC1=T?Qc8XH}m%t)aC7h@}`jDbcLcP6jNY+C>q48 z9N??rdnT<^k}6L_G&o6{*XSe8cm@~okWyiq%^{i_{Hw*smJj9-IQQ-VWT`Nlp6eULb?*+C0AQ7Af zlscN-4Kr=8p_zFlP|n+gm#agH(;&jkyy2RSGrR^f^DvYfdK9M>qjFb|;v7YR`MNzV zfpY(lMoU9TN%qs$%y+_nuc&tfl08H=L@wXash+DGkBQ9B_SfdRH6bOL*rGNBP9Zvs z$q+b+U3`>g4(6?f@^)e$dcuD{)^aBk+n9rhFP!Lkfwlx{hmf(78rU?tp?(8c0=2Zp zD`H%Z@5TTodXH(n=Q7>TL&nB6Ix6!5o#1)k45}lvbbd%CZd=XeZ{ z35|r_r&Frq)qLlq|A0AY)x&mm-4a|5iuh{aa>$e=P+b7dKqb-Nq`;6-Z`EVk;weQI zcVJ75JS(Im&xzLb^?{I*oI(2jH8e8=xg2CZnZI9gM(hW@Uvb(ivbpUw1ji zgp_3U{aq0nnSekuZt~53a5>75#XUz4qJUBl5_}xk$jYStLIhn5s~)?wq5># zPR=Cb{mKl$S7_GL@q2?zWMNRpuV%}y| zk;R=ds~eI_QQ5};%J-TZEggG6^j9Dsv7^`N(`)qk>8Nai=e{4wV}j-U zE0E8h%wu9NnJzv^>|#b&T#x}UlW#~Hq|Hb@Mp~3-@u*NJ}Gm^cM42a(rR z+Uy~=;5*vlA@+dCdVkVe^;c+vXBw)pZ0=E#-;U#VKs1PVHE6kT84kp2)n?hh5iqH% zUG>TOc`V4{K2BRa&NHYkuPi64eGi#m^y1&vE0Uj{k{!&`;;g852)6LJH9sV2-{{0Q zc7!DVM?5BY`+yz}Gs_+eW+2AR4CH;nJ5w-cfIfcu?(FFZiNahED-BTIaT##OAReFk z2yn+9zys63d1XFm^#^#|MCu>H<7?Z(?O1u7Ix-}+59RThZ6T?P?&l%;`aPZOA>)Tn z0Vm=A3b6yJygHAN{<}t}sD1i$uuARI@8~4Y+#V&lmQGUdk`kWC9KC;#*0)yL5Fj$4 z$JEx7dM@1!nAF3fBsUp5SLlA8Yc%WmD5NBl|H(IG4kho1tt4YalNpa&ZW(X>72qSb zZr^_>Dy?}vN^&5M$HmAJ*kc9fspoiH;XranA&*}SV|Id}7j2D|O9z8|YBrBM!kE2u zFeRU=;Bm)`JT4tf%S0bf9pinruKR~D+qmLyca)>Wa48~X2#0@S07`3*vClaeZ})owx7_P9wif+{e<51 zXu0DF9{UNs>5SYli^tPYlDllM=64j&(`YQ2!^*_JDp?vMpS-3d&nELXo#6Qcl^l>c za9*GjJr`A+Oyo#=f<$KP^m1el|8Y>XOy=+uGKW(sfixpHeWfpDk$HPFKpn3{PatzQ z(;w9NyDg+R9|JI}{#NPD{?`A5pGD+E+Rau@A-X5+NX!ZWc(9<84U!{GD5Qfr+*)kDk;dW+(2h51+4f>dtd|yG*Xs;tOMss zx}T?+N_LYmdyzJK2z`XETWKOTfQ)TI8yU;b4yM#GM*6cn3gmOgcpvev$#`4H(lY7S zXT#%;$p6WwqvX;7(Q;W5BNvS~$j?k#3*=?kTRv#%-1ZI_gDaGDj9)bp%* z@!-br8OJ?(@!y*iNn7una#N09$OuWq2G6!@cPFn62}yn$GSk52Ab8N$ANoY_;7J5d z1Nj~HbLS&)65VB9gPB(1;~{Vo``GcntKwGz#1sE8f=#q_W$o@sB#tgN0lqbk?nRpN zMB*%H_vcKWZ^)cL^V!q%FjmbCyX>*x3l!u2>ssFTzmjK6gZpbYjcg=g2o2((8?hir`44u4di^$ggu6mggm=>3gg=C&Gk1lgAHz9jPu-=p zw`xd8dbC232t8JW%8SD?v3*(fz^yWY@8Frdc))1@UUf|pQ7U%H2r6%ocPMdcPYQtf z`foI~N7wuJ-=_3146l|S7!N%e3}8|Z!`S6^8hMV>jHfz)ZhU`c%FX2yruIb2l5*Fd z<0(B1&u3q+mxt`gdy3(E)NgvGTrZo>XyuhX^pTzlgM957R=)BCCkG2-jcz4v}Td=}e32t;KNU?mQ)eFGNj>kE1(9%q!BQHh4w!Vnp!2y`t zIUcW!h9ibFUe3@1W^_C@Ai$^M059T05-ImeEVTGJ9;X_3ToT9Ql91AJO^f;DNs8t1 zgHdqU0AM~|t?B#l0IDmF=lL-b+2%4 zNO2}n&{9M7b0fs#^$1$_r}Mr%JCxfIINPJ`UV^PCJ&&8B@AAs@fZ#?N9U*O|1W?^c zMM-96*m1@+rKNeE79-%$RmIsvqa*JXz>#I)SOJk30eezWT{HdbEYIdwev&i(4!X9U z*qyoI_yC`T;{!xu1CVn5VD$JV`ZvL$d`S9>q9l{Ps=27Nkbb#9Th+VrdM$o|_}m69 zk80Hg#aY7fxI|G}CLojhR283H7+!z3A(Pu?;Bjq8Y56K#S;Q)h)tT~@Z`10$X!zEC)x=cYA^9jMOr7_=~8QT^+*$G|y_X557|sOtk)tC842PxL%9h!bBqsS`61 zxI1WzXDH&c%XUM#oz~Vl1w9-o)WdeWqByO{5?KGB7W4mPPDr{&gGbF3loKbmS0nLn zFDlX`a5;`wBe9+C=ehi%A`#nZ|IIWtA3(aUGoC!ZN?S9B<%XnhDKL||`5whtX@l|& zkAib3ayd>{BXKz5v$uA@%wskfH3)&zyBlT_dR8wU+FGWEt}_!FEu{c0gg$R5dO|tz zv8$1oxpe8eya7<&Ndtbeq_j12Y0=T4mz8s6b92Qf_24ujmt*)+e%%)+;h-`Qx~c%2 zBQ7iFJ}=J|E#Z6g=em}x?XE`R(}sBWOg6!dzJq5zPXN)?Uw7Xy2Z-e}LF}gEJyokK zy^eG(F4G-vReDENf#|B+aNqj6jrR>y6ldD2P4_7%J^-!T?~8%K1BwVADBj&!jl=-c zKrFw`1Q5?HeyVkc9>gP4_|`LYA5URAbPXFFpGx|AIBNUSgV=*Y&tvOKOG;YG?nlA`WFbfd+FxPy6!QP2NpAU?Yhu|o~JVWxjVqlI9LliiB524MV~ijqv;&Ffa2 z(@+d&H9&d$Z^5bNkG&h5gx@RGNSuC>7MXLK9oe&ZS=kIYP4CK`K0iwIH-N9bx+W(L zfp_}GXtBL|MNWJ5a_#p?qLX@WQRMd^RxGMsk>lS3K7W9ei}w0W$X8VD&MB&1l~Yu` zI;W`m^&I~!upFfrIwbKb+e*xw5mr=g7d3#@oox9mnZQUAB~d#h@j=T$B8E{DR1Pzo212u ziR5&n?ON=Cp*;576_T1(RLCc*k$57S#{{2!PbYew%Z55AbUDmYNGjFAVPSWkIGtXy zqdm1P_spbeG8^Xq^w7KIyd@w9Xz+B-;BiMaQe&;b>SZ}G&6Iq)f%hp&wET3eE*RSn zaNHe$V;%tC7YJI0tq1XQJ&%8{had%ERkw8@KWh6XxMi{aGJrV?=P*5|Gb)bidkP!bwUzT|xMWlRH=N_?*e^ zdwMk&d~#f#{EQy(vk6*1*_KiNa6h>hk5KtI^U*As=xg9ZhpbeZIfXqSk60ZS zEF?H-GmnREzf10%W%m)AnYQfTa)vLn1~c`5M<#&p0D_j%W%NJXZtda`!9rC&56VKd zPBgUZ#LkZ%k`*OUK38G)#f(jm|(AFtLQ7rxi8 zgzG8lKKzwxP5+GF5#u~kB`bR?*R^cI7d!Hu3Q)0mP>d$d(iGX zRgJ{PN|3?n%2gDL%-xwJ$Bj*vjV|OnL)vfCi}%jetL?v`%I?OJ6yzS*tg;C`uGi)IY2fPlfv}@L{1$XjT-f z+!<}hXE-}Po0{+A?o5^A#`cqqhr@J3w0Q6OsDGYrlN~E2gij~iv677N*;G3|W3}VX zf_xvht-ow+86d|6!#p%ai-JA+pXXtS9TOf-54B@uD8ij1?N}Lt@R>1o%mKn@%kq6O zI)vjGgkxh6Hl|S;Pdp>udp!D|=84Q(fk}3JI?s;J7TEEbyX}}WBiy+z-xrgDu(2P) z?TxP7*ffOWrfF@(wlkuzjQOW|BYXw!x8u{Z?D*c}jMzEbj?X@7$6N-&=RV5!#SBBZ z3Au9P?nKx)7UB43sj!|K#Cr!C{&{)Lx8u`K*m3)ZuH3U_c6{a;JLYl_?mU_Ai{TMA zPDVI(8p3gJhxtllMPaw$pXTcf;p;^^_6%gj(-n5yS!u^-tL>P30O507fsaS7TwxC@ z#yAm;d_C zBagW!5jMPpFtoaI8xi1Q3dzqSZGI>7tD!-gUu!7sT-uHK)$EZrh9rVVA6%kHuOsce z_VZEjMy+7S({<1?Jqotj=HBDWOMvo2G&ubqp;xJ$IIR2YsSeMn6%*-RQD%E`qzSK7TXr?z>3C-OG@MyXQ5Zy^g!@ zn;4SXFDd8Xo@DXYZzz(VHh9<`C7Iv?;x{lz!v-63LXtjw{*Vg$SXb0Dgh*6gQKaV( zm@m-CL--=k{Txgv0x-`FfA>`QJ^8=U2<1Et&PEo>*K=ATELQ(_31Z^Ekn;nuKni!JO;pRTNwY=~% z<-g4iNmD0=q&@)V))y3sMPN=szg*XZpQ-C$c1UWBg7V{OTEEw1hoqOI;EicB?6~F@ z>=~oe;+b9_OO-lVja9fW=K7e}pm#Z{k;`$R8i`HG+L&2d?Eg;98Mms3HIByoPP$ z@2VVdxpNHv0X~3euK|z`mPLDE8RLa}UAcybkq?0L8eHT#=QT7VAGl(@hQr7Q$mj(W z=LHn+HSm-VmL+%%#gxzb0Kx!fFTCr@H8fK`a3y*ThbbSRB(EVz`2bS9hBVp-%Tm0C zX|xYq7O&x1+GqU=VOW;xg}=FS4cllRp#EONf6zV%x^jytkQX6nSs%8!AH1X4+-6FP zt$V}fCVD1r2ubZxyw~4{$L%Y?yNKekKNT>M)$sxl_thy9@n=qu-*lq7U$`(&kw||x z0koKb$IB;a>n$ycva@{*kCicid4Ludd2VXURVsDr+)xzd%I!TDEPvV_-+pCqJ5I)lagol zY|X}fxJXfL!F_+xZdT?@_11<;Js@5QR3296shQhPQ0{Ikru5D*Ynox>+!7YRnJ-;FM11b z3u%9OxZKLymwUH&x#c`wv=Z?9r2Q&deC!oPdj4@9x5UEEqQ`h#`It5ie>X8CJ?~J@ z@9!)Ucw8xH&)+7`@8a=TBA4+zt{ksDUrU~6@_1}K>?}&>ab>#peAUE|^xOa*e+bYr zH!S}*-wsJ>@z8SN{(Sk;Y%+Gj@ycnl$2Bn|y>(7$xj-j*zE0xtHx!Q_RFvy>Y5ChB zsV$`3)-IXXhonyR+_c&A^u&;q)cN!EJpT*zP`&E;HKFIs&(|~W7wS3JbfX@D&~y6d z>v`Z8>iM=;Jy|MFN%ZXOR$5#eKzx(p@zz>Js>$cG86|qWs}GMyP7FyG!`}}Je}A#- z#`ha;`F>EZ@6*EHkLyxeYBuoMZ)$fw$GZmbxbMV}T5exRE0;JiB%KeJ>k}z=?x*Fr zTgpX;%N0{vUXdHTnmoOAqNypAtm0)mrP`y#gMVU=)OQhkR6h7-dvqo{lnn7a?o+EI zD+O8%*h{mc zal=M9ay%Rd_s_YC)KvXgFfyNgnSEnEYpVWDa94GIbc$Pv!A*=*GDDRMPC`?fUJ(Cer^_j~4r7 zntW+?IF@JubtCR?Dvu|YXm^6{P1E+f3D3{fXwRmlg(Rh#KGIXc$k(1R$XA|VCQgINK^a{}VHgN8LG+wi@@Dnr{G z+k(A=*-?W*{3(LlRE(plTJ_|b5h8V8w5%N1;=o|#Tktj~B zYX&lK9vI1PGqlY)gQD1uzOS1yDV7sZEccYbZOT|%;~?$YhJPXW2X9@t7K}nyGWcu@ zz7Pb&a3UC4@3@1)Lez&PGN0ev{{f&+qsqB)9jnH&_u%|}MzUMiMb zh>YxeNXO-mZ4+pq+5CswgoV&Y_&ybU)hVxY0~ZUNkU#dXf)`@h{D=Q4co8j(M@Ej6 z{lN;p50QZzd`G@*kL4{>@r<_}`!Y8#JYB%px@H(`pD=B6o*MRzP=Lm>orvQ0QaZL1 z(Of5r;^wpKOx^|G2%U)G&Y)QC_W=7cXSYa#zt`xDV%vVrRY}y?Kw$+w8Q;qWthyU&!3s1zcwzDI_2Ta=>&+xB= zBNs{q_;h~(wu*Vx zbUYRCQ*7IuS$$WU_ChSTYTRFhy^zE`grZsU_qh=Vgy$YVAnXN(I}9f7L*UpbDvtX- zaKh^l$F6$hFG43W2{uF9oTDkrO{-8GC!%<+69%(yPzLTxVA(h-j>{-=JDwb|SLj52 zxZ(#kEL^od29r%kcNk3S;p`{Nsq_&G;} zjOFhwBy|m<=qjc=ENYBC8F9dk_3*kwK5n>>Qo6fe)p)GHiRw0i24DMtz5zFY;U zH{H-SN3g6l4MHYv9#GuAytf?rpyT$XZd)h}|5B)C>rBFeFNJ&{{bICD2bL>EF+w?t zVV@fNm9UZ`di0ebpafw&isOhL&O!#x|CP%z>W;f@Us&EU)l_`Au!`c??`W4JlWm)G zX81Qk9E@ilK=IrWs*fu7PL#ksd&_u!o#KS}@kfPcs5mx$&QYNgQ3Cn)0~EtuM6n#v zrF*Gi>_`OM8z_lY%k*7k@}hWd8~diIoH7eFBYx*7qRi}eDuL}Ben^NP|Fuv&rgh;c z3WUxDhg3TiKj&+~i{iLADuMGMj{5<{a(4!mZSm=S#ZyD#Y_(Z1bEOVu+EB_$!BDw& z)WxMoU(10bwJ9)j3oKb%Us2jh-mNSvZ!NpH^ynXWXA0km`C;syV{{^Q@qpoS%dNc=W)d1doxEYh-pLzB?CrPN zxH)UNanno7jZstI8}WU=Uyaz*Z}5mMIWa~L3?5)pZB?R>hB$6NmCbe{16Mm1X1dBo zwc3zz<+8H*txqGDqk=ZBv|U_!bim$MYzHBc{Z)+4*icc?`fp_=t(|B9_h%HxoteDC z^#0_g5rmd!=>FV)($UhP=C%(!RQv+%>C!(rAL2< z#MrM!y%UIM18qY!a;%1H`F*o*bajSd_$#j4GhdA zeX>3^5%1_A7z3%~Mf=yDYbLJTj?cu(qtc zwUh$ZRW`46AU&R)Mn$n+gt)ovI@7OWb;fCk5u##r#!o0SJ84n{|3(lNd?S2}Tn?g}#0IQ~!2^hn-V3Q5 zg;=hb>cc*W5;mpi{k9odWaiFI-Z0|F$s0#BTi!IiUiMV$kNvh8_fCFq#I~#z z#!WA+Ffzlx7A~+bnpyC*a28p(V#II)0!}~RS0k3)LG*v{h=EMyTB75>hrt5|URZkc zGS%PlIk6+36t;ejIF3V6++Z^If=O6YHoSEjnAp{iKHs_@4D711CtKU7p)BF41SPVh z?lz#<2rnyQbw+j0?&~&v#w<52?;msDA)o}p&(mO3$D%O&px_<1R}dBu-PvZ0@Z^1D zuRz9JGh(<~`7$E|S5r2(bu{Y3)lxC64T11EN>ce+&DNO+Ukpm&JUKDOCKx>69?M#j zcidM3vGD|VGpe3(EQ46iLycw+AeLJ-{7a#xY+&oE1z!ql9(}Qu@IvtOsF^E#J(Ky6#<&;^q5wE6!Ncfjw@PIXaSDE}Mnv09dZ)FHJLM*p`_#xpe z(FbZ6dk}HlR`yL3!GL9yS$G{Kv0EsP{e0Zlf^ESeK|pcb=Z}0Xl%WKHv~vJ)TsDg0 zrmAun-a6*4;O15T3pKerXz!; zY_QI@kA|@?Yyh!pDZjRjV%&w-plcce=X7A)c?fl#0B{mt^|5wTN6InC%oUe{FAczK zU|bIJZUSNso}iOG54LOfz>m{Oo^)_IDz7Q(TKG;X*Z@ntGJfweXrE?R)&?wRK6*XD7wDzXBLrv;o8uv^kT!f4&ralfvypa=l$v z{q(^>7ZgPr(2q)jVfgzJLA8OmI22td+Z`AD;B}me;=R&L~L> z4rK$~44!s?v2hKzmKlb?U9&hdsKzWfuIt(zQk=JblYzi(J+8x%{A)xe!NOj-?ZPr? zSI@#~acVz4hU%<5Y)_9O{Qw^8!`j_{EjElvjSa&9nE%75-2uv76OKW`f%rld$i=tB zAkq5Y>`_X`XT2Y;yNU+q#a?wczigfL!s8$o&x33OfVsI>oZ4Tl2}y(wKgI7@L{W0F zk<_2$iR4qsZAW#-O2=hI`aM`^mm~d7CAJ{q#wc7NaJn9o5xRe72u9dlprJSVH%)(vkQ#HrCx!QU39SI*W3;$wYM(X(Ob9<$b2Ob!4M{~79v6($ z`n_0*R{K0J+~?n=YVqiyy#S`bGo`YkKTQQ_!0F^@(-$RysLAjgjg%AZSS-eTHDH3k4?- z`qJL|ZT$NAsx9!i0P2Wdt8wc%*l7eXD^yD0laS&hw0@lq;veDwN8;K=0hk|*f^9ob z3>9~VpJ%YJ6XIQtCsyC+>m(P5ME{B?qI4*K!bR!n%-G z0Nbk=aAx$1Nj7t}7N6stDoU>D12{b#ldS9*s`Jw(k3=ES5SyRHE-TDhc>=PD4ytzy z4LokAT)F;myA>z$<;rlo#iZRRB-T(!ZMU)jwo`g=7RTL)fi-5e76YrHN+;K(1D>b0 zo8r0m7^-v4L*m>MAU?N5k(%Rp+_)6v8WwO11(?V^k{@kag&wz1Jf0N=+nzfyRL!YW zMDe)cMMWx(3g=3@O)kN!sx98z9EoWZt?F~KM=xpXgiQF{HLK;0yPgBhmC56EV?)wD zO3QQPvheuzv6}v_9;>a#j!q3ppyTnjY9+a+;v@OW6G#pgQu3wQw0z-yUD%F*hv;z4 z8b0XPL(7b2UY-tob{>L-wjTS@2NSF6vyr=AjjN#M!%gw*(?Ls+==EzL8mjqh_V@X6 z~XBI9)!Fcj+*BC9185w66dyO;Sn2=Oc z1tNoPjJ1|A+F08$Mw@?TTQph-t#^;oo;fU9{IA~ovPAxcJZz_EaGnq2n!<;*c=*LH zTW8gTG0Y1_en(prh%u`|(moc%b>SFlk-Jvf_%M0y_!iYQmX67~-JafsH$#$^Q#4A( zlK|h8PqZ3|+FgkoIRGr16sef#ID)`&3ph``ukDv)fy+Vqgv>=;kNs#yqEugkR@U44 z!;!pSL02)W-QUU_yzE&wK>R%=C0S*L7^Y}R|dEoDTy_fI|0nXs?}cxW~@=`IQ7&A-ONlrxMkSZ z?$R>{ySHpT)Gd%Y)|~xG9nIi!Si>}IIqkkdLpdKTd-?;F2F|O|ux0q^pOh~Kmm`kg z{DHhIY+a?&uyUBUo3t%#J*2i>y6Wt0+uld$*Ed=s_TqHdUhL20Wxp14L;NhA_f6OX zVvvSxF4i7Ay&1`ej680ycI6yf3i7GnQ}Ssm;4=l_`v5^pnV!e@=;25qic!xEmZ2E+ z++bxm@70rr1NCk%+c07A(4ch*$m{3B5zU?@dY%ty_H17i?7S4VXC>~Cbev!amdCb1 zAU08Lxw}FjpDEydyC}dJDS(F>cE*zf0y(Q4 zveV*SxtVtYRw^lZ==SCE@PvPkX2as4LDEmn)sF@9UI96S0lfP*_G>rAV;99^-=dps z*ZEW)ucKgRyNSn&N!v5uH98#EFdW`U2ijgKZSu?&Ra<#@gB}i(-xqt? z%At2^b}-^w5IgtU=#bQ0{a6;UjTaG&O#m=ARTl;;M~9?E2*$?}>|Fg=7AZ3g!FclS zrO{gK%E;Z%s%kCHV&A@@>-owJcWO4#+&3g?`@Xb%?HQeX*kf(-1?^~N^b6RV{YC3e^6cRN#ZN@^R!Y(lu!J0PB(CXf!5kx_v2)_GVGrb+usz0 z#O4T2&4=yj95{=O{0@uSuEkTkG9*o-`5hlt{eSGeeSB2awKu-@*_q_b1V|v0Ox|Gf zqLKtEMS00oXm&DMd1;{yM^RA|$bCveP>OFAY0QKHNr+mH#!j2`ngCYj3`P+rYN~w_ z>hHvM`sHI~Sk{ha!eDD#?!*zwt4GYk-0?@{oIl*kmSvDu)^?bIcAJ9CF z#=KxY0P9DEV;8fp5D|J%)4JL<&DNMmC|eIpPKTQ9RNSWnrE?{muG7p^Zm?7kK0gyKw)YJ2H>kR+IIUGN9dJEInbYD@6aRwcy`aW~%-{h;(_4t46x;f_jqeb_Fhy3u4B0^u8 zIqZjbWD?qG*#F%#bwB)v>C6tB0)rbTDwozxQZB4cQPc{na&CF5a%O3oGU$wx3xIU1 z?A<5A`sxzho|;d%en>I$@iWmIs)u6e+;I9vC3FmA^>3hL=7Ox%$0_wVJAAQ$o)GJKeN6FkQ`!I&JBUIT#yTLK@RN}6o&PJGYFkgrFk~yBbn9Z zx&fqWOuFr6SYH{hpJmI{G^uuKsj_A&$kqA8(ec=D?(8zu)QVAaYb#q91~q?5GNG>y zYJN4JP>M5sXKvNeB}2s9T14cUkFJ7m}MR0s13o%ev|2~E{?J2VxTF54*1@)aaG zRa6RchZ_YJJgj-D?S$IRFi@Go-*cch86@u{@OQ-DsO)f~Kv9+E$;k%4xVcO@nnY+2 zi@vL?G>=QQL*I zu#!Jt3C4rej?=>(@gOlDy(xvzf^lVPH1ADgJfU7N`WWdv#8uq)wfb5tgfvPY&8>* z>k$kb--+Zi?s#P(YHB@WBQ#tBGz|frg@8V?O7rmiK2h zSmvlcoiHc3n9%?G?TF`>nr36Z#rbLavj-vxbI)sTc`1AABX7ES#Vww$FsBt}7 z*8&mz)~!Unek)N!PQ+ulcq_iEYzL5T;P#sJZ+aLKK&lrq!o7x`)J*z%Jvn8p@1ymE zd;)cKz5C6aENsaOB>6mBV*ECx{PVwDuA#{x}tS9ejnk_oVqVJv_)2Fdx`U7K3 z7cgA6n9zma*7xoz`Hw0-T%q>oo0Q|%17)_!W(LaYjM@@DW;YOeVx_*%?D$G%PgfN4 zwcUNEI_KLFj~Cye|HdoS>%JZFsM83wV_SG70_mlQW@Bp)^9Qo;AG!XhIKx+hZQ+jh zHK{+J(1il{#S}tM<4nFLvOZ?Mq*-9&VD=SGB$SO0TN7D-@8G$~tiGBjiE7rgt`N3! z+Z5vGRx^F99+UB#Jtr9R+?+t@ah%TMZnFNSIMG*&2<IXaf?d3`MVr?KDZ;Zmj(tPgkIq_92^O%MoO5A@`E&10_z#hM88VPSa9 z_MX%Dn*Fdq=w9Xi^q!Bd3|nAdRzr?YXUjZc!|1933dCG^g3jH%~C0PCz3r92k$fjE$w z9V{B#G%v3oTq{(|{a0_TLQ5wx&* z=>JcwC@FWSzLy_Sn9r_E64YRR@BGkWLJRkk4ZfEIrDN0PdERS*dRKw0ybT+8-y*Ag zpCMOS&PcglzJgo_uOL_W*8;AS<+mtm zg``|qy-c~Zu3Q=1_#;KzZ{j{b!&Eya>X<4j`z%BDR}I-$8L}_=2(_fFC{sM6WdBKw z?EeAK((iUE%%48a*7;nJ75rU=`6mpkh$2vCZ9bxso0@%zaJO%oN(36%9o=i9KMa(sfiwjookX|StnOger_6oCe@oy)*{ zQf4D|&jI@CDv)PXYMwJrLR;d&f9_`ejL0W~HGBj>`WAroFPpN|hpvry&S9HR6RbSf z$DcRdtu7b9e?X{ES%2D*E$l)dsYAI7(tXS}_5w)epAY9Q_?K(-+y%Xx?pFUS*wxBw z8HT#6_|Ii1z-();aJRbR+K5LL2>s|BC{R4{9FvJR6(#3LQJQSR)<{GrT)NxwI}xxv)A} zQ7a}Y=ax@W&MZw)2HjY;{|q>{Y!`tR<`6}5BFCAjKmnPEz%d@8z+;W7szbX}^t6AIFRo)?hqG7?o+V)z2GR&89HBr1(DA3{lj&f#a zyyA7DK)qlN_vZr*l>n_w)W0DGlYl1jd6MR1KL20hfu6&nFO*N{hpRxof0Z65>ouIE z2F>g}(tO+xc4w(QIJ>yVke$h08PTNv*Pi$jm;0};ol@@k>#2jUeSXSXXKt&0dh?$O z7VbUOc-6sE3!V<1Y8S+CUJ^)WwnRK)f~&k&0Hsk7+YVTOdaEGtvvQ(zxWB7(?VP80 zoe=23Q;OTMHSBdyRy!_e5|cG(2ik<0zmo0?;cTDs7^q*hH^8&HRM8B+EA)tc8B7IP z%-4A~joB3oNTC?M>)kCn-(|x{5fgwOHTbT-{Ta1@8{`Hz$jKEt*8cS|kePhxM?ii9 z+tt#Gn&ibR)E70)#`^j6pUafj;(^voAT)$ie6MW+nb{5V__7i59yEAC{!NMDkTgPV z8H6(5=77P|^=A>9vjyaW25=-ATpjrEv`4A^7G$>rka4BS-MO)x4c|Y zD}JP0Sp7rg(z>O};Kn72hD`>ymFhcVC-i}zM?7!kYo0gr^&G=L`FX_iM!ue7xHx8Q z8E5>xCYt{yi}2W*2aNB{jR12(S%g9cq35PYJnTMeV^SQnWX05z6vL6R_M_{GH|D!F zBoX@A^oWPu?>GhlDGplRj|bY3j{>aTGf9M&KB{@x+MXH*E&h0*!73yd#6e5Q$Q>30 zJqL=l6a`#DRx^H7^K5jYf$a>3>?DfW1T>hBxE#G^U&c#b2!e>;tHlIc8W z%1Lp1DnIYU?B9b^bo?l%>AL^L?aoyU6U{Yn$#?Zxz7r<@PVlXGdw={+%DP zf6P{AL;v*mSr0nqXHurbj$p;jZG>4Ext1+^x1vk9htp5bC+4`QPC7 z&!*ebi<*>PrRTp=6M&wr(>xr1YMRt**uTn5LLZm{bldcZ=Ycdr{V;qE^qFluK9j#X zk2pdI=Ei<6AKX~V)?%(lmpdn#@l3?S%2h`a=2T7~^m1kInLhHo82`?pX(P^v{mb-- zP1_$I7~GhuTw0f=Tv%;W)QWWF-0}?N%+gF{&}ouS<2c_LjD2UZ;5&zrZ$S=moY(jB z%ns%8v*fcw*OWR!--X$?$HP;F@vx_0aVZVOfxjSnraca%HKWNPgZe1oVAmX}-^Jitm9BHIIs+s2eX=y9Ma#z_+SBIE|lmn>an< z`O6%bbKyRxQh~F>m2*JyGWqu-`AxSF_~j;$Ex8~UAhI_!O;8GX42KLKW;%$od~XhF z{_kWFdIKi(w*daqd?WtHwuq+}z+d1bj>bsBoSYOw&rOSX1~kpK05jdljM0ru-_uV= zJnY#6k%YM+em>Fc>rVvw#}80TaBFGjQMQInBb2=#YyU_hp~0=VGqf1!OCO?^JDf=7 z@_!qo>Q%&1JribEr;%>a1naBQpgR|V^oPy*ei}Q7;Uf0jB+^~Oo=t=9{uwa)?e7t~ zAc;`H1bzampM%?SCP4AGuQkIpQ%X$wclJeb5Lkr7ZOrF6jzwPuh~a7g$zp!HbPr!^@qmniKZhJ&XxX1{s&XbxHx4o3tNlt3gKFb0n zxF7L4=?p?g*ZTphcW0R+^u<@yJ01p(ea>Wc@_JpL>-Dm^zSE5YLHEIVJvg(t$DLW+ zgR_c*39k7)?yTbf%doNg_G0mbHjC+rw2Q zzY;ahD=CHb9r)MtZby%|viWh#2dJeRXQ>@HQzetZUw!YB@q9!8~1I+(e-;3|6aAN^}@TFhuM&VkF{A|W)J_W*V8Q!>NUYET~;A5>A2=$ zbuHQo^1>`aSv?C;Q)@SXzlp7p`J~%k3hOKXqDckua8g`YN*h1Y`~~sw)KKh~k2ERB z*LD;rJ*ORtjX8TwJZcH;FLfN>b@Pyo38xUs?MytJWOjzt$!tsMIqj+3hfCxg=d?Ys zv1h*xV7;7-ze3=zLBld41X6Tuu6`f2bR=x#YqJ;Mrv56T*@omlJWBqJRrErAD^o4Tj1~U{B-%V zMty$+ySHW3z5i~Ec)TWfN-VvJilrbo3P87;;He!Zc#8Q%xi{WK%kI319%6MPSNVfe zb^QJ5CcZDjcrL}4JMJc0mVOic_o@1~W%j=8xdIIQohOdK`&M7q)X0c9BHWL{cc_1S zU*FIF+vJFc`4^{+m{QEgm{4TIP)RoSm$-$%{#xDldMP>L8Ql1$LKA_G-Ulis6B^wM zntD4?dW1Bd547Vkq8`C1J|44Zyl(5+y;4n+o-KEB{)pif<|pR}AiZ`s;nx^;{Y0>F zd-Inc6UB}*!j+mP;e3713fk&a+5DYR$$ZxgUf*dRr+C<(q}*53_ijQC7-u)e#yQE0 z*KPe79Or8SLZkLnglneQN7#I`Ve`$t62mSRF`NGzp>5j3Yt%3{>^&ZB@6G((xV;ym z_TJ3j&HfGTy$E1^a6F+O@Em}c@85f__a3l{KDHzMc(t@w%VLPfo?oI-_ z?2)lNY_-7F3__ocAGt3(`p!oS^w>qQIdWMaNCNm%q-JT_Yuv* zuCw+k1wtQ)ADQ#EuOKoeH?FoHI1j+va)K;Y5{H+Mhk;-B>+6iUgDA5Qp(%*ade*k4 zN%ybPG56^Npy`ijo_eEghKDq)^9w^~be#HFAK-QCXIFUrSjX0}`@4a zg9&q7!rkisDTsJJV;C|H4vG6Fan2=Z9myF)??q$G{KYyl#*9=Dv3&zh=a6`0;@5II zr3L>SPG?5JNKR*3!B|e`nu2e}>9{srnbS!v7|ZEQdF=1!be@0m>p2~D>eq8RUrvqK zwEYQz(0&*k+?b(UT9>I@Se>P)71_$U<&%{&OQ$G<&Unu2ME9OwGI*Vf2Cq|{uk$+9 zQ%fBS?tt0McPwN+=)zKlA%=LJ7vn%$GqqHyoyvKgL%DBR_@1=jenEa7qrjDToiqCd zS;?QLEW*rREi+;nE*{D2#Q3W`Hlxn%>>17Nu=0G*Nfn`crVevEl_?CrW*7Ikvx|H1 z;))EPPq-8(S~e7axY-x!bLY|iZr26S$RRuSqjL051Eq1p<4Pjc(jh$p=q z<~*41RC)w494Z0o`VmM6Hi4`hLxDm>_BMWolKduD`S}%C30)7=>l6a%JP)uSD{i}L z&IS46{U)V90jT+Eki9#FfF&1XuNwt;KHh0@iWj4R$jVF=l+bzY5WKr@KEuaRuIS;Z z5f8;y->i!|S2SxBSM=zXv0PE@)GKpE2~UpZin4q+1yD;c;YOV&T1Kdz!$Z%<(2?-n zPA{IKUiBx`5-K57_c_II&O)6l3N0SX6_vV%vAS>3NUo@65zO9nGojuI{}@-)?EHGJ z$n_6$MF-OeE&K<#q7&B>`Z)S}zKHyTe3ADWoiBnIzNq7rCN($-W%H7a=jeGcZcy`t z+)hXJfHv#mIzoH2Vx`BOp>`ZYfl}lu7vf#z;~FEL>LfyY>gOswI9)xE0X)yla^x!4 zw0MQd#O~{PNX76`i>?!1$5@?stA1D~))bG_iNa!-y&;iM(c~)kxtFU=tHm}iUS6Cy zSbCVP58t_+C~MHR)_sB{tN=(IP9bm<+lxNk8u5%{b^&1S!AI=Nn6IT^Td}=nPVt8T zU8y{;%5CavZkx)k%@M#K!gk-n+UnvL@$%v#6Z+9KlyzN24XpR!+tk{bO_?QiXnm8= zoY{`xJ`3K~y0E68STr$AC5B5Qn&jK{Q-#SEUAF)?wIZ~w_1#}Ui(Q2E4d*pUao<)f zUaCCobKkC(Ah=I)SEz+(TWe9gt6USr+M=3*;)Ull$!v0!H?20e73LBiuX+1f{n~jf z7P0F^SC=Zscf~8aG|g5V2TM=fKPAOhewt3Hz+|B+auzBy2ziobX$!|8lvSjn-*O&bJ=B_1Gn_pXUjpH09pEKkhwW;3%Mlb!YgHu7hGHRyg0-8eDaL4=abh}Wfw0g%PwA$yLrbF z*t~PezKABl=Iu+`ktIA-KLV)+S(+K{W_7JW?XlH&STV7-{ym|21>d=KTqI5=Ir!M~ z5LJ&xJQq2SLH1t2W+ikpP*#^6Wpf|t$bLa)>-$lh=}SL^S~lX$W@Xw2r5=OB>%Ogc zx4S~UG-DXgim0iT&9iGik`zv5r7M!W}=d=5+`Fu~%eqF8*_b1HZ9qAzT zuOM_*O+j&}f=~tDp+R^K8%qgoxjN$MNO-hUtHKU1zFQ4$HFYX@d2y%~Xbu0~ber0Ib;QH^SKqsOySnx2 zh$mF#bTI#^13&=UKqbH0K7r8S^@JY9$hWyg^MnqQ?t7~b5a%I#HNO}SCx>{*UL$vx&ZF*$aWme4;9at@Wt?)~jZ*{Ab!_2m_X>aw(50RM%7jI4Q06{Pv>x>`O+4c^n7U!&g+(OUe_C^ zV}n^yPItc`SN>S@*kks0O^D%p9eEK?B7il=$i+4Vz-j@onv7@ITowhGGqm4q1)<;n zBWj86=Ni3MFn@&k2n-LhvIT;kPjh-=#KYDQ_f-)OyI-Is%!wbxGqdXq53+S+!&Uk^ zQow$@Z&x3@O2^`viG0lWh$x9;>@SnYV0eBnisAp3JQBlKUGA71s( z!SLU`Y9xmL&Q)VE{Oqf~8HWG)gIC7zS6ww0!+&ej-;d#6-S+huKH;jb$MBJS_RLr1 z-7^Omem{@#(4LH=bAbkzaebT3aGRK0>S&Dqe|4!Nw2tHWLuTW3ZX{F2dFerVm~`#*Fn z|I`>P&oBtHts4pbU4F#V&tyNjtDO03QOuGvk>Pp+&*Oy75JozlcVjsk--6+J^LqxK z-$>|34A0+BsCK`O=U>Q=cphF2b6DSGFUuJX{X1jSn==oo!DQ13AuV7NZCKTc*C{@hNJ;>CiF=XYU+`Csh5lav9gaCwZsrC}__zc2sF7=OaH(HK9&_x*QA z+DaYcXZeocj3JCa?LE|T@diReO9|!s;IJ6(y-UY*jg@0D-OWE6#&nA+Mq)a1g}x`G z`hQ_h$Ulnn`~Oj#@BH7v`PEY|kMsGy5I4Ro&YwgzPsn*A$NA^BGMqn0>2cfCjw)dY z=TF)k@f?`IaQ$y{2!v^VuKUN$D9-R#68Rj6mB#)0e4EVy~a`eQIr#KOKLZ^ zs_dF0mJ@I<8_5Z{rLW`!O0dBROnpFMGLGg14m=Gly#ma#kAwBh2HN9bed&2k^15#= zwp^+_thkq}tW0P*p$vN!#=FYRHATg*Xqqi_Yj&HMtA9`1epZv%Z*y*`651syil*7# z+WDZ;j>T{p0*STVcsgND*Xjq9o;zURK)fD5jo}8-3dJ`7SiA5oYIN^T6HeuOcN}$= zw!#FEOHfw0pcEt#rS^$~&S%6rOPht(AFe>=@WO_s*5jvPug@1eWk;59sD#k(%xr57 zxq)5)@K@lhuviMxf`rUw7^pk^e;?8J)CaNMCt_Fm4Oncu1B-1;#^AaM%Ej6wh5JYO zH~^@3J{yZl?3!Pl2s97C+MVzKk6pDu&|_DzHHy7M2AjWS@QQFVNZy#e$~zv>_bNZ@ z2Bi@L-C^uie(MjYWX zI#`*X@$c5zzH_+|51U&>nr377*}Xe8t?MH5nGzmU&i{1*=i`p>nD}w~vEd+K14tGomtEY_vAi4%MOv%nc?^|JR^#eTxR2&n%9EJ+%yzqo&rMK9 zUZ-^Z_1g-=y06!39xpCe7skP!B9ta8%+8t#JwA1k(&5GdomcpwN~65OG5uPojnIq6 zwc!3Z9p^to=%wg2w|=bvXEirrXcm#VIb*WUj~wemEghOe>2_zTy)(gIk^}?p86b&I zJYLT19P7`L7%sw#Gt~tK7g6~wkotEz73(-~bm4UM{0iXv)EkZGLdR}&HFB3Oze7rS&xZ!cD2OkWHhE>Fp1F6F@f*BXZrm1w@2#p7aMfFJd4LEp^9OB z7XQF7YPovWqwfb{eYSlk()(?yz6b2+G>{bc?dq(Wf?_YeLp^^#(Eej(4z^Y?naxbr zEJFKJE-&l3)!!c(w=j{=&`!){{iF3u9#6WFIMO|NSw0)z~<243j2%m*1c;+s4Z0#FSq(Wn_5;uTW#lcQ{cXS|+s9 z>0o`q{mgno^K&Df(6KTH8&iI5HK9{-BcAQe8*~nw`Iby~+_$TL>O(DTteM{PXLk{r zl5224`Efc2l#tM=xR({5w-L(LMa~1cCDoi8@vwFGL57Fiw+wyH?f3@Yb1&o=cnIIZ z`?1TNs-DeZc+l9_>|U-8Zy?{j!|CZyv?B~ zZ}Z}AgSXiqCzp=O7eDtBjOA?-hIpGjqj(#hH-6Koyzw)c-+2XDHzM%gj)rB`d8Z8D zhIdd)FyUt1mv$5SEuD87dI#}^k?-*MZ=&xYjCqInf5JPk^3^+Z?rCjK#FIRz*)*s5 zEAw{6a!9)-8+^hj-f8<d(KOHOxKrPmXv@ zcWRvTd1CSq=krwV^V8-3d31R1-(#cheex*hgAR@2gAQ%tv6hDUpul9EPkLxn`9H?g zy>8UK1K+Uj-%i%|6;@2vxvlpe=G>O?+%UJb$B^NcQSH3+4cqCM9Puze=f|7a-)!H% zu)kS^u3~>v2(8>SlJgQ1bX`G5g)wK8qO!4d znfU{pH;Y-H-?Z!N^U%GRb=q%_c-XqU_MI61?bwaO&vO4nU#AuO*gT&)pSR3dLnXC? z)wf>=wUu*qrSYtt`#0m<_WtC`oZHRzv7Flv>;8Vu?ZYi!&$$)Z zzn*i;wMT5nlhQBs=c9WDHwwz7b(e`z>IPYJih*x>ChEZ5FxwFiPno~wOw`JlGf_dO zAb;w-@|h^rDaif#CS~IVXbCyX9Eq6hJ-%z zZiP7)e(Y2#a7LKi3X(Tp2q;zho|mFrki~dN`sF5&z3wS$$SLT2m>p=yiS+-c#VL&@ z*b`khLs>uz46e*SML#>W@zUkbPW|?0W4W?jQ?AUFIk$}657Te}wFI{=(CvF0p{x(s zx_ks@`GQ-8&d?1&D-TA`O=X00mKx`#emIujc=V?+=T?@EIybfC|35eNzjkiQiR5EW zLDrmtL#q-Tnp<#aI|awTp3yv^{Ib9A+>}$0k2&Myi>Gf^G-sSctBP}I?l_0GGtRM< z*X#Vd&P@fKnAh81!RBS0BUD9bY~B6&f|AYZ$2U4c;jgHFA`Bcm&g8yPum5Pp>f(|oV0{okDjC$V3&U>pNDSv{nq=m2N5yc> z%*Ix`310b^i3={&qNdicO^@TI*?{&Z5vtt)l&xV+6UkuFL^2q33!OQrcYdy8+k|c7 z2@T%tnqTm(QYGhc@3rQ6<0gcj0m|c+y$nhyp*^#L{h!dDS%Tm`Hs8d$y2CDpizl|X zvTFJAr9Y;O(Db9rbe*1>4l%Wbm_o z$99m!C!Q>Cobb|pB0x9i4cuvJjvXYg$yF{UgTrfFV|L%NFGUWe5bE1GO9|Ns^}18l zc>?$wQy3mGhx774sjtE;B4cwa=5 zyt^La=RtUEU52+OgQVbF`T4Nj?z`2Znu6lviG=n)L#PjDUh=wcRekOZ)#sMf8Z+N( z@l@dvtIWnFcysT3#cfj;@^fTqY9(^b?>Hs|wz~!64BA5+lb2-;w-KI7C~qTyP=@Ul zJlSX?TlKk@k8NWvYa?@H8~J0~5Hg0_(9gNusw(c`{T-}qM->_>w>|M8&S|r``sIJ1 zmJWQY`d|OS*7qAbLn{c4uIIt5-uc=w!4bMaKlc`#=9(Y0_0A8i09wj$^;Fk%TlyLvruMfYns&?!Lcv=ix`H}G~ zm+$%M@^u@BG3TE~-J72I9$Jh1t(`lJU=t)*f*+<%#C`EY%~#`OdIt)tXGnUW<)%<8G9k(Mq#OoMjrknHlU%5h(|P@W7pZW z_?YL|Z#MTL|BhPN`o_k%AyL!v3gMnu5!M2{p0U4KY34CC{^B1#`?$^*%41xX2e4ynoVJ>1P+6rTViB<6ciFk2`3T=eTznq2Vl@Pk2hu_Xo26>bOhe*P4Zh zryveaiVX=IXI6?MaZ>bN6vy5sj>NI=XN|>GFr83dZeN^SEdbs4gONDve-K!|uFSng znZF`Ec1X1B8(9(C*TppY#@K8o-w(mD+2zhPTo#*QBtP%G^0@{TBU#D6L9sI3!=(l` zyK(ehh^J!qLR=Z2;Zj}qrV;u`)<}HTgR_cz+*!rZ@4G=PbcU*+d#4ixKE-GRKKqZ~ z8~AJ*p&JC~3g#24eUlzigOFwoh?F_pVg5-4~9;@PFnSsC7!BDJ<+p=`L zb@2+ZD(>De7H=)ix-#DSTf}FD^JH8?gF`(HH8#^z!0nJx3!oNGwZ{X^ypKHH>u_;cZ5UvS&5GNqaMf*8q- zhA+s?6f_}Z8ew^z2tw87j?hoqn9{Nc0u==)b1-U8fEB5bx zrb%KvoMdx_+tdHye${X+f&bB@4krpc?}k9`s8|BW&O(b9uPFBI+Bj@Kv2H)bQLzMa zjaUMkE)xska&lg25AQYqhFXFNW%}H|o=~J|wh{6NN68=5<^R+P@@V;A{U^xJ%7;Eq znA3spR5LOoo=IY)n_*uKo8PcQxA}R?hHd`ywutB8!_cC0`YZH(tQdHk zdK_UrK7m)zZNd2r-3I>}BA!}FGh*f=dG`v9?{(pR!A8=}V_^;)o|CsU5;iG?-F_Mq&&KS!_`!l{7A3dS=%6#dom(6&CSMCP|jxo z9oj$Y*7JUZ@>cS^d1qMp!B51H1?EKa^F?DM2eE7ZIZPaEO-%!^{`5n_V+V%Vnm7d} z^<$9JHrSWtAhP!y9*!Y+)B@5uBX`p8*6X>G&bvWLn+%geI2uDR)%W3k)Z&UK%25pR zb&EBgC*&a`Kg#@!h=<8}CVOS_Y!moHIK^jvqO`a_Hs9Q6`IeM@Gx7yEF=7-VP8Zve31jKUv!H@zQ}_+Zsccm-v*Ex1k&l< z1oCzPI;*b%Is?G^P#&R*kk&VM@TO<_<3TPO+<5pM6Lg6vtuOqyje9MFHxBK2v!leY z2-?%dGaFm~0^k?5jfWfKpbNqq51ZBx?{Ra*lTOiUYc^Zcn=K6>^Y|?$=p+cF?LvL$ z?oALlfkmI#0D-eO(N~Ys!VRdTGgs532lEK6E{aoXih!O4JzwAGe47vRaT=S0^Qt7x zGegomWdME>2MV)kdagZv{_`<(gKX{~${N8{ejG!0Arix(B%t{MNERTp1flS(nGLN+ zjImyT#OBapQ0g>2XH%mfHj5?*=sD+ftQ(D^;5w)6ffE*4SgUzPw`u7hN(B5MBu&6>>eZ`+8(pzYl@*B7)iDOdz)-OIR4xr0Ga(e%wSH?Vlr_N2UE9w4R6{ zwQq;@=#nP=kon!~(Rvqv)YE|0H(b;t3}Ag6LHS3TW(y-%d4d6=LC={%rLMRT;)tYX=Zb4R6aJAmKfPqvUdWo?uLq`ZYMz?cJ1gT;?4Afqsolj!gLC94;i}j%} zvX1@nUoGo*S|EE~Ve>3r>|zONF#`h9lC$Wn@2^s=hUaaGqbVvKN*hD9zDDu0lLWfM-TU{i`mO7 zrZ=0#%w~p#!-6$@%T4e`5Q9`Z5d!tEzyQV|oe-e!ag@>5-T(t`0i@c&vcpMYdULG_ zN0HnV6D&AoJW#YT`H@0hyv zN%`2di>;SOV%AD$bgeXWj*aiEna!=S>*dVIH(D>BV&nVT8qFhS!zA%)_>nz;))yd< z4xZOe79JTd2eG|~=bWmkE{^7$Vr7Tdc0H%0zApjE;vu3e6kO%~SK9XZ@#|lEKAw7dAzxm9{ugOu{r5wo{P!o)A~wxw3Jh*c zQZB7aRxYfbsHhc_lyl2dlru}M%HV!1XT-yyeiNKLi{pGMKg%Wf&ST^&T3pKGz!k3i ze)nlC`YI3%VC2%p;EAG2rnGH(i03yl@O;CI36h7X#1| zIz}9eG1+^3>Wx?0GxAjK^m+2CbK0S@$^yiD4&Eo=?TQ7j4eid@;5x@$c!aA=T1fnJ6cIslC;>Ph9>m$cqO^$T4ov7HCE)k2B8~;iV7Axb3B3kSXj`Xw zyarEbDF?|riF7Ngh=bif_#>Dd`W~U7L5=&pixP)pvW@n8*BXBBiBW#W3!4Al|0n-<9QS|!P19@}#}m3j)%-=B zTmDpi|Kw$s)xSGcqg5Ujb3wM0{?{oHncq47=IK)(rx7aFS=tJJx8R)uB)-G`7k{_l zo%A|OTXh3*+=;;N!ehBn5rMQV0RoFq`Zk8GsEN$An_xW}2hw!Tm8SdbIGf97N&L8V z(UI)7zDZ-b(#I2Gxza3tjwzNawd3(u;7YR%uJq&9ce}EOxYBN<%Tb9ydMjb1?9mu{ z3ouAc2@uG@=53P!tPA!NhgKh_Xm+3r5X=JPDxYw#{(X$+M9d=8yam+YPOOBc>U$3^ zVY@HL^*_sZ6cc*PMrfe`Ep#gBzVn3ERmF4N>3!e^kj#l6w-(lAw`E{+-@!?Q7H-&} zDgyXfA0{yW23fY%ql_>TK$>PIw4U`vHb{kt&>95(X(o0peJD;}Q$&;MSsz3+X|4I= z*5=Oawv(D>)3&2$# z%0~`+B`61`5W267{EqqQfbySv3&6h#=RcPx=1n0vIa7X<0#bVt4D1Au8WSMUj>Y4l zg!W95TAT$RN%Is#@K;7ZO@q`}1q7NfiIp>nG-S<%%P&R%g8w%9u*{=polUVh~N(P^ICz1$VyP-&(#@3!V@J~;G zz(ls@AVNC_>JDFvfW9}0(D!QYQQt#^-fR4Rx8@#oH)4LS+4niN`1+09WykS&-!vl@ z=h(QB8OGfFsP)~h3_dq=BAUeN`{Rat)ODA%u7exCrGBnywo5p}7u6f44;d(Zn+RZK z^JW!*M2&ovV&ccGBA-8E9~)Eih7D@SPG}Q=zX%a(K|oUhtOqj*J#Dgl^;QS$KPe$iihVG1ikJ^T(|Vf0Nzz&Llz?jyE?KAfRlF*jOK!0yK85 zs5aILd{4x~=KYn{3x+54`}&%(!;J!L-C%1*HiDLq-_g33M>N~K4G~WXhOoo!YGr!Q zFxBlLt&6?yC*MGamH4mMVJ5>TX+U>snvKn`?Uz|I%<-^?y+;wa%5xsPiL&~OY6^<= zc?R@k5r$oHNV^1*EzneX~Q(Nq7IZVb~}|YPVt?1{YHi9=9g8Z``#i@zL-JiS_{y7odBP=)a{HagsHy%M4&`M~S@cC(M1VFTRr4wqV0_m6a)}1BI0fvbN{y->$n@*=ah* z$?AF~rmom;+`CgEo(}h2YV^5XG0%0l?^Ju-**t&4cJ>@zG4$NO#y*GdP+^RIfYCo?klmE^*}Q5(<( z07-19P?@c5#NhXCA`ZK0@_oH+AbA-EZUaB_^E>c&J3DaOybdP{{Kf<=-d!8@v+E|1 zlxcO!?s2ZC7b0_Wk+tPd7OVf1#rpm!i}lQ@qPln577c#y@WQJT+r$lPREx<~J}cMK z#_T5ZX}$O9KCKcN>(efaySz`ER%dBjwi*1D!dScNb%RtB4}m`m=56*ku%0n;cs?rt zZMQ&odju)<6Oei^k0`0g9L_O;^z1Lx*Mm6K=dO)-ybWOWd(U1B zk_DOj7Ue>qVkHdh7eGn`b6wC&EBs1IWEwI42^n)HDfTd~-h@=c_=8oEItDLR8kCWizPTHBE9&0P1z$ zrKXtRl~>)9RX2~9hXS9(LCb@2VC}aN>fNcwoXj@4%2`|e`Jm^bezHRScv8gkI?h&E zA4n0+--Yi|3#=`F60QDI55z-2w7!4pHTMd&Nl0xLt!Ga8#<`v@s5{V>KKQ-EwyBo3 z1CKnc_UC1{^-lxJd|2~6;4f+*jtbM{`#RP#J4@)Awcsxrub)GmW+L7F(+FknQ)njL zi)S{sTEO*mJu-*GSwN2`0qwsZq%$@`H5+uFn?~pXfl!N?(1OCZ+WN7%sNW7W0}&dU z7N=wg;Ahv+t~x_-BEu{1*UL zR{sY}N|hcVg~tP~6jJr)5lGe1=dahFXMM(WUBz~vhQM06MSb0R$$5BiO~j*O@THBj zHZx4m*4VbkK<&x{nbli40VG8rwCD+>fK{gN89abKNu7g5)U(sOM;R+;%7c?}s9{;j# zZwa!5&2Z`Iw3$t<9|HIfMCuM#*FjhBsk*~&uNmeDGsoGQ+lBNn#hJbvwt`9okec!! zP=M0=?AuKPWrCi!nCYGQi3-(@(!&dXZs&TNHZHCCVg3yy-FL$z)_L14i^-Qh2=#TUk6U!x%QvG%q%)OWr&5dxhJ z5NK#9>3qBa0{3cK*Bv;qne_*{ph<@{&E^tTKi4}YeMuV9b%*H!(}|4;tni?&4;u`9 z5XV`Y&tveN-D%?U?d%Lf&*Mzr{dpiW{UkXcZ4?N7;O9hrK-2seaF&nx#22vD*CKFU ztBd*WEqNfb-|r*vKbuDACqioY?dzUxJqqA=O=5muhVR6isHGBMR!&5lb4Jr_JwjU8 z8PO!>dspDBuuA|*vJuL3VbgWL;AKlw2xU0zzl^djQ0MTo--0!a5l9R236=JP9LfiO z=z2mmK@8`aKsxgns28x!SAz+yp-i8%xIVMKXKTPh1pcB_Lbqv}zsS(hiXna0a~zww zK4*n1&wm4bKBwz*_CAmo=IF9iU@^Q2gT(su&aI%ber4mRXqxS;kly!J#Q98Pf}!WD zp{xITLJQHAbvZB#ujJ4qXp4I-gcEUxU?Wa+R|&GN0DER`Pk2I%XbKn_*}k9S}jXK>>1~W3(Z=Va)|HTO7EU&8DjTUS;a zarS;(qpv0Ht6-qY0#ZLt_lY>Q&)xt7*aA{x#Cdp}6Zn~m&N7fKpFjHaLPL(-g1Nb4 z3zuP_vjJq+7A^z#E6mv3d=@8i{&HUeNH-hpEvkul7`~$ze5e0l*{Ti808!{ci!1GVAHm|PHc_J$SW%48#*X=bC5BtsT zWdm@XVlo%xgAC)vCBZD${HSj2NRD`dS-taBoZ*|u&Cs$AO=p0dn7^iimWx^&>A1B<4H6H_lc5WfGx(u#oOfe3v>6iQ(Eo=QEF+ zVB#V)zPWb(gtk9epgWA4TkHQn(%w8SuIg+Yf6hG&+?fHgFfasS27(I^_bi0hQ0{HMEdQE#U+T1-E4-$ zwgVF@5SBT>o%{QobML^gB)0GGFPOWWd(QJb=h@D)AWNX!(EEPNP3YcrG5?6~3dn7b5-nAm){qL)!5{O|t{` zxK5UYq(Fv1s18r{cZwsbyB~@cNXesDtly^U`aIR+sXp%jm{FH!f8PXor)9D}ANEiC zP2k=h4IL{HzwbuS^?8ctL2P5aUBfzk0(|GyN)AYKJPPjSk^^b8!QGTY_4;|rfs&Av zsTCf|%7Bji&CnOA-)F>A{+Fy+Ai2G$9Qs=0z@16=zW^fL|8a#N(*3{2pl=>qFG=43 z`o2GG1$QyE^SN-0acA|)!wEI}IDxF*T@tilXxtGE9aQgAIA~mJ5=huDz8_hc4PT2A z3_H5B`pvf!YHAT5a3XN8H4EfRx^5H~Kp~C!S$`LIpt!YK+_t4WIhYy~FP@0`$Y)A>dENn0`1&8ORQJiff2bdJ%J z#r%vAbfAQQd5Yac-&+hG7v0+w9^H0ms;{^rxZJNDFVHmmw|9l4A`F3z6`pE3@2w-6 zyE0lJ+05THb1b>l1RdKAe`AqxcC*IZR=r*3YxZ*j@$TLp^a3=NAc16Jy%x`xSRij8 zfixi?i!hJ_yR(DYSRlVc(74*bf2E!`$>P)_$6jS_tIn4Bno3R});NoIHv&T8c+rTv zsf-75vP(N2uW5F3G`y9y%1N@Kpt0Kor?WP%ZOS*nqi{nk8sR>rGF)NzcF9^$qc;$%wP9xYww`urZiFDv5UE^Fm|A6+u6j6ks*VuCmm~T!Pn+E30{AZl~*VT!;Jo zdo}mB$29vp754}IcA<%WV*n>8YsWM@wPmwxRiBs*Th?sYvXxw-*KF9b=F<0Tveer< zbJD3TyKQ_<9%D|nSs{tOOXu}|tjEN1P2M20XK;o(&~UIU7na&W1Xxy$uQMY>4vT zdmai&)b^+LXws)3Q~sJ6Cy?~?OYi%u%-}8=DeDaH{cUXTn|r#Ay`N?5{Y=Cw7Pjv# zfyDBC)%DT(zQ2p^K>%Ab$M>|b{hg?k?+i(PyFdmpCz!0|nvYWn?*G0n|-hnoZv=5KWVc9g`< zBq*-70JtgMs9n=$>8$2U6KX!=`1T$}xY^uUoq0H+hQfg2J2Q^=(sAf-3J;32%($=b zNu6TSq^nkIQnE>t>?TcGxLT9aS8I~Zq)7=TO`2=cq&cQ=Ou0?DFJAW}qCr)<4!}nB zysH6hC7j+jsgmVt@CxN2nGv;IUXFs}SB=+>nWscY_RizPWDT*N7pPtqZ}Pa>4i*I8-%}K%I$A6;dl!}duBNi|cQrfI+dD1l?VVD*)w}Jg zxEk;Gw+C0>6j$Tt1d^K`UvtlO@iqB4ndyQF?5s7J)gDW;>ijHi77$-tNMg?)1u+Zr z?fIwj`%Z;4xBs9JB$!t&YMOo58G-d(``!@{sUB6&+1k%?KpeM0Uj_oVhZD$0aUrSX zj3C?6L8SK`PUzbe4J1?3Z7{kwsqA-{q3QCPO<8%ovYN`u#Jp3_1a1hGyZ-iIh{esH<>m#_V!*u=1GyG~jaLf}o#pI-`H8jF zm0D@1|5`Zy^2O3lx)=WNU`QHfKFL(C&+u9KVmx_typ9Jc4J3O{aSy#p$1TJ21L%t6 zb?GtSE{cIZZxpyoVnEzxWwp`zd@(I~na69`TF%7t?cuQ~zu<9VfX;(YtgSYyrJe6* z!ttcO(#{mMpwowwly@HtNqlUI*Me;UGbDMbosc#k+-v$uUr0t)@0xVzDC>g0g~{OV z!Mt*Y>b9IcP&Y^S9r^)mE46|{`Pde)CDvAVVNYIVsI;^GDmd=xFYSDljc@b%a7*40 z-QQOvuk&F~9>ntNeAuqgd1l0gq%Pc&x7#9+-#-h%Qw#WYW&j&q7o~50Me@3==Zb=S zI&{c;96>flj3!{sV%khEqkmk-@k-TmheCO4(93R-iQJ$XE z{vKyzHB~A8C)0x`FH8@g#q-`lj%%m#@!$zm)rEzIt_A$Mx&_JWKG!rmk8BL4_Qcw1 zf2g#RUjWB_{iU5-Dc<5i{2gZt#Ht0Ie5~D@7#r*D#)*nx0{5!E(igr-*T9**JvdPb zV4KqXIrMd7a6i{q+DU)+An>k5wsv~Iwp@?nRMf)GSuo4H#suQQ0uaCZ<G zy$?Sl1lK+T!6Ia4`+MqhO9r$?-41|;rdWz6p&@Za^12#Lv$MS((~?&l4GqQdbkEP6 zkF8-&RANK+HqO>g=_HaKSJ`xWG{=ER=`lww=$yl7#_px`NNJ9~17>hr;!?fe%z%yn z=9LQu?B0(7cc8ztlm7lM1YUYCp7O(T=sO<`?l;uJ&gTk1eAooy>;e!Ee);qZANG}Y z_ThNNisHP!XUZCGnhSjtUhr&w!|Xje+-gyL;8Ya2ix+~t{c0pr`)BpV(#|^(usK~o zHWpV~$boyiTG)C0RuCzEC|)Rj!nm=Z%j1Uf(JC(1>wQ)Tu3>mcW_Y0Aee!A~FU5Ku z!p7K;^rS^#ddz+<&U@e)A^6>AAXrB2RpWU&&nnR4Z`Z|!Sk7%?xg)sioFG#^S-B88 zD4#5e1|sb#V!V>_csmBd;;hp_)MI5YjYrC>!@PCn?=|-{{$kScInUrPul^s3%XyRe z3(=?Y!*UM`9sSeYu_m~8MP(8kqgT`VLycHQQvFh|Kzt7%Qyu1g&5_T^lb}|cr zHykSxjuYXq#}$qhQJ*@+WaQK_drZ)~2t2Mu+tQY=e*88v)417GN7XdD^Y-cSy}ZYn zYmS26tn_5j40=t!;{Omxvo$0YFPzY?eqoK!uTlh3mSUX$Tc_vk{d(KK7vFowV>8G1 zzH0sY_}&+-A-k?O%%C&0f;cZ4p6@onTZ0jO7K8tKZ13~wZyK?^7{u2Kp<~OXVtX-& zaz?&9{CBAGVGW$?h#a-Qe|Zy&?ac_s_F^Np*D8<)tV|Egtw*qw z#rR?{dMhL=U$D9YiHe3HSIdB0tq^jxt&rPrT$73sXNJVzP~#bLhi#?Be|RT z+aqEgtOB{o*b`^^R3n!)Lcgxiap=Q%Qf&y!aa47lT~A{Di_c-3vgUq`<$fZM9?SmE zhcqdyH!?m{I3B})8rIsy|M!5tZ}WM0^e{*5+5}}AACg%9FR$xnz6@YB8P*hP(h~5v zx>*11L?w{}mfv^kkdwuNYDYNw#$GaI z>~lClx$l0BbE)@E&+y)Zd`SAxs2lP~pDKOhHtk==&ymLI_&I;yWc)n)HTb!I2K*ocKNn&q z!|;5;WEeIe13%9i@Oy9qe#>USPatLjKfj+c_6G&i@iTCrfuAyC{4EpXFSrbTzBdD$ zt$aw@`8D_{nc+P(CL}#*;3uX}mCoF%Nm?snd~G-b$j}CpJaA_;<7w=jtsrU|k_YJD zMbLEpe}*I**xGB2yjr^E+KtfH2H>vzzGHni25}kdg9^EH9#Xt;%oh#fi7g?C>g0Y4 zhyxWM`!NvzR%%n|^{@3@k|c)nhZ|AV8P4WC%Rz3zkk(u9TBhh@JjtQ7g2$z93rRdL z5P+6EDgzy3Aa_%K#%w}Q-Zq0rWLiSfz@4|tLmO^myl6N>AX=+VFLb=U4~L|wd?nSQ z!=|NIy<{%d>es04judKBtps7bw!@OdJ=KY5U$w5oCMp%TYSMaMKdWH&h~ckFhN~Ai zVssyFNi=lKLrE-$fJFEP+bo^c^ZuAnEX;?@AhrWSKlV&79s17bX9X_ne;kz>6+%A1z@9dH;-v<2TBN> zAJxYFRe#Ym`yfE0UXLbG+0uxr(nhtV9P@iR6l#NADkn>Q>gV#P7068ej~3NC<;+__ z9KcA)5_Ejgxo1&(8ttoIhP>63w!3hWa`mm6&F=wzKmWzvU0r_Ro`RN;rY=yPpX9P0*Nv1oCqeG^WNt2L`Zh!~*#b6Ev=j z5eOZtg!%AN4If^z;lukwb>`vZ8V9lmPGNAbDim^8&zg#lq`+ZSbFWSi$eKGQ@Ua&` z&Ka|gkJZ@heIpVdW0Ubw2w?jjPhp&J! zG2rG$%Q_uKEWbI1>FocOk2l8f@zxnWUj9FIK1ku;%q1IVI|*z*?73aS`2kCGpfonq13$lyaMKS#{lWh0MRm}onHOuBJoX&Uh^dr z3CFT>L9{Lbkw+f3Kj|D+A%U#^wh$~&e6c#r>&*y=<=YUv^Bq)mcKed$&LOQg{o1QV zDn}QB$F*u(NJ=^_$dt#MXA37SQ9=_>c`mSTH}x#$POij|)14tS)mJQ7?q6JR@?Go* z?urK@A6js-zIDM#J_>sI&6#3d#a~wx@A0fC;po~7{dbl?sP4s{Ib~(_$RhPv^{HFO zb=b3poO}QKj`j6hp#zX`Os-h4JlrE=A=Z0jB${-YKT;f$>N(-qyEtF2uUHV&dt}%Y z+dHU=&V|`Sn={4wilQKu8EkIxK&Vc<+t3I2(U_b+YMPzG+td9?&a)?%4=2^=wuB?Q8#}Tg-JGqp#!l~*5V5~9D}-Fi za|Sid&T4nuTr@lPp^%g|tk?C}{FyMD>Jr>{Jg#pXLsj&DXOzb^7j#|H_op7F>utWF zNUsH?-amWbZN1J1+*maG$%jJHe`}gOoTpoSL(%M-hjiT4{!=w{GbE2a!pS2KVL4b7 zC6DW9g?jI1`rfu{i)Qn^ue;I^G-Rej)2Vc5DnVJ)K)trAnCoZXc zZ*`j?OYb($OV5s7-IaB@N@ucxQHagz)Jhr4sd2E!{sXj#Md<%e^(mbW* zFuhYeWbWP-Ecrq^-eZE(tC3k;i3D;N0#eTb$=NIJ_w;LILRHKmmT1nzhLsU4@ZQDo4@`RI^D`GMaAryW-ya+>l(6P%{> z^`WNO!}e0J=vH~;p+b4=5u=WkVK<2ddM(nhJ^69;g#5wAS?i-;>SwKCe;OSh(w*bE zJMTqLbysj=y#C^#JX1K_}*4cqBv4*}x;*{VtO-N#wq z?+1bh*qU1M>hOR7%$eI;M z;#f>hm!{e2oWpfPw@?@a^Ti65*9%QP3=Pjmz`}PF#8-+m=69z5cVQ5(->6ZYgH)RJ zJRVE$>#h+8t0%$UA2CCtAA`68Jg!tHh%A2qo_Y&aNk>3*>{zy(+Lv8;o}zBiq<#PGl)blu_{$2%^2&k<8@(9m{TY8G zXi_Z)vhG)~DaB)&{)TM5sMh0Jelr2>`>N%$5j>rnc}eQ2$CP> zpy>imP_`uj*|7jfRU8g(FMy^+2pW4Zh~8*{tagHUoe4VfQC!bvRxcoKAGJX~HF{f8 zTm(!ZX#giEi#celJR;;C;sg?2&ljeUL}Aeu(%0iNg`|s`W-l}9dw$pae)Ss-=9*X| z$IyobqG8?t{(DnM@;N5*?>bBo`FDDL4tuWM6p|?YXZFOfeepl0khG4)izh1AmFRkF zeiS@f9;MrbDR{z%7KQa5N~{KNFkhs)?ns^{Ed`J3@K)&X8G7Erdvre<`kSEZRBiv5 zP45k2NA_AAlIklSSRVF=4I2Kix{9LUYo?I&_#}UrP07U}=`f~i0dWg}ZLXk=&#}v@ z&#{l2nB$*0eU4~Idp>>bVz!Suj5&54rF5&$k!;ZC*mYK)BiA}H#|#{j{6{BzcHucv z_&znm9B1Q@^dt^Rw*c6B@+an(9;46i{fPO!W6Y2BU0!|-o1Z+x{5rz(`;#%hUr)?$ zl)Lo&*3U3MKNpg|h4uR6@8xTf#kgk$u+jZP|8Ju-I9DKrrV!)5k{SS`y%amVvr9Y|ET(c6{+Rx6d47_im zde;v++t#4t{#1dq{PPE$iJJvdem~_AwtyLUFF!lU+k(N}gUw1^{Mi-FoGl>4)vjoM z8f2<-1yTjF>yK;X?LV=~B@Y5Q%h_0bj?Kuk5jb%Feos;GOaXMfsA-LdjdQN3tsx0C z?RY&q(@Kmu(@Ioc*rC^3?nxEMs-IZpl@9{hWt_|Uqe2q%W0?iQ>}uP5=0iUM`WcYV z4#fZQdL}b^{=pry_P*{?UU{W|8^;HH6?{WrF=|SS0(Vb>K)R1ci&;oGb`kT8kF8dV zJG&h~x?5w!YmsoQ#|osU!YWc8)pHGyZ2ET*ke)(|xSHPI0HmkYtp8sKB)c5MtS%6H z-r?o$N9Z`QVm7s>&!dhkeGHlM%5PEq+2~8l)+n!$^N}SWmffzq`S-^A0E<9r_VQuzSdari`E!%PqfEX!FyZ- zt+8T;532mFYxRESwNBD~)JY=G)To{kQOEoF^r&ocA=M9_yi%{3lWd%;wXW4|@S{#r z85NRzhbGQ8|8La9*{07c5Y4Oe%%`J5(oTl61m&rykfc@2y=?!!$LW4Qx?ZNVO6inG z2}bW;b4_;!>t{WO+829=G&gVZxVkfdq<@pI@g2qDkM7r`F7G2Hfuux3qkt#- z0#f1X1!ac)w=xDg<{Q3%G3EfyEt$sV}YFHppj>`U?TGa@XW@uF+YI&XV3`D#!Fy6rQiHi_XF%QfsM{Z_XDID zet@oN9mYs`c~p~z zFl6&9V6H>OkM8|BxQp=o01j#H?wtbJgw5?GG4S@SzXJDOY;MnH{h9UrG7AJ>(DTcB zUr4-ZZ}p2tEy+#yP2^_UA=T^ODG-9~N)hG*%j~ecE*jir8PHc@0yn+KBhd4ROyDl7 z&|@U1o-!N2RuXvX1v8|2vz*Yex=@daah8`g>?nth)#cEUUY_5ORSq3HH0^j9=2`FL zvY68TVh-GaodQ{l`SxuWOJC^0=Jt))-0nrzcFJq5VD;`#hmIZT(BXNeXpB#Xw~L=~ zj2+fAcNsP_n}3+Ic&WS?=J@uFm~Zz-Lr2d}fvnPsmKR}5z&z+!PM;rUc|VC>-%f$; zDH(^P;hn&0T~K@w>`)lppErqx6vwkc{K^bf1Fvt8wG)W=X9+}m2NCTTi1=F(@h1qR zmNN&sZvf)|A4Jl2>2O+s`S!hmr(PJ#0n)u5h#8r^tWViBF{}r({|13jeAjY(!1EZm zDX*b>=-2mYlCQ=|Sj}mlP3)?5k__Z=y>XW&!B3$PJRlA%29j8;`&EXh+^TVsbG1(5 z%ZL>-hP1b~&bEu$7O0~9+TR)@ntNY&X^$WRS?b7PdJJ86e4~w&Z>4gNzv}CVE8-82`%m6e4XI(8xy#B%A5jmY!4BQM=o+@4pb(Eb#{z z3|3$NW`DOuXxjeM5BhuF_>#dObN@kCNo>Po6o#8$iCBAUjJTEJ&7Uk@X@RQXrXsnG zOAfTm19zmJkx*)`DG8N!mK=uT#r>t7l#lG#q{nO)4?W#EhV9BjoAiDjgYgMoE1%${ z*L+)n3~d5Jb+es!z{vresthj#G5IKnqu8c6a8kgR1a3aV=q3LgxHT>@-~n*+R)P3A zAk;Q_hnwHND^z%>(#U0f{{=X{EmY8%kN7}ld1ZC?SEa|wI5W#(O}S}r^$4pKS=!0J z2*-!8RS_n1c0kV+_2c=<7`7^ju_@jX(BshG;zCjYCn-al1d@;{G?ig%pmkVt z_iPo&SP_sPU`uCX4PaC{rGv}dy#m_~l?#ixz@+#t)(orR#$uRh)B-)H3g z4nEz()sOlZD>?;|JlfI z4UgGSpy#(n=C;;fCbu=f898o!n)`V==P>WNSvc9VV-d9NQQC`Fs0udZTt@QsQ&L5#uuB~DQ2^=_Q3SaAZY z*-^-Wd!?%9v099p9orZTtV%sHdmEe}UM`O{T(85z^3LpmY$KOc#&d$qHnr-!ZVXNE zx_j99i9=!i|2{@UYez)uMC3tpTdKCJ6 z?T7?A5uxj&*SoP@32^*)J(87bLFboS1wz+$p@6Qh^o4DVW~Qt!efs*kxrp`MCY+=? zS@vzfXuA7j#Oh$tc~HC^K94)j6~>D`oT{A1j_enkq3Q`n^LFJ|C?th*H-1jx@Q9O) zKBD^sS?xNLVe@R&<@?)cLTCOdeSVbH$U44=`ABtthQ<7T^~%HMn(m!W(sPYKvUg_& z{fh+RCn9JNrne|qa%i$xL*RU;dm#J|bO>K*tg{VxP}A`PTVNXkcNtC!{9y4*)wPB2_MRee*KUHo5)RyzPdU~PuMvp9H73_id1|X! z>?*W~v$uvMw#QpnFhA{=gLF9GV!0nX37y+eYmAtNTJrpbh@_=^^5lEL z?ZByl)WtQ`WpvK>g1c;!e&$15}Fak+@|pV9 zOw8kK0lZzXe)8G#rhE0X=OJSr`q^`e^7tF5iow;03qa_lYKqr;ZqX$F>)(_I5)c{K zu|}r&txIXi^Ti;NkIeyw^BWMUvv~3xD##85M2G_SU)Jh;DF5D&#KU}VZ3XoC?1=as zh*WU8&TIz0oyxxq4&1x|V)rcq=~*w3v}ej1R+sB_j^LU620qMF)(ga+FAxB;w-%dO z&39@Ovau3{pDxclS^4{qDo`sM!V098V z2aWz&P8OF;`J@MddvLrjN+QbzYXNY}5q(jf0KG4Y&*~%tvk=({A<5r*M{XNHj=yzP zE{`CG?&%U=%rch8f}LbLduCPcN-buYuh2=pLw^^p&RuynW|?ojlWc*IG#t|GVDY#* z?xD}>J>R-pW5wpOC2})P48qcuJj$E=JDh~^DaxZ3d-Bq*^5oUygkaZJt9S(Cj-wU0 z;|m-wzGQ_e-{O|Mi=#l2;5)D0jiE7dMe@34E-6sQfqMWavb?~PoFiBOA!!iXlv*w+ zKzYW?2OkK&tZ9uWSkIVbR`aAKq`8N;pbolsJ~l%Yy+-wW4=0eXm_Ip5xe-EAJ$CE4 z#Q3h@wRD{)oTU2~PBO4qx6$_ixD%d%p#KCS3_cZcBE?e|#nGrRO}>1e$&?gj9_TV? zn*52dO=d%c51h&m!`86S>(5O*7ajTB51mB&q5d4u>qjS^8`IQ@=W3ipt3kwbKx-V* zRB8K|W`}5x>p_OESdp%g+Ov)^kRgupMNrH(AaJ031)zss)%B-b5#}eaqdFADF~uLX z9RWcD-}}1DpTITw3Qg2TIlVQQFUDA)YUmw-ykwjwoZ<93TBr5^^O?PVpC+BMIAve2sd0cz1f6nELDU!`U zee(orBkL)T#FR(I=2`)4%?0rGmRrDGA1@rUnRGw++39 zB1eo~FpCsa#ry?f+dFEu_|bqSL5jx}b&sK+rf0Fa(7iK&LFvIx!eD*WNvK?L@IV5T z-_#;fj~4{}*YIN6w>^0m5(=7X4?>Wxf#TTzoRerr5z)Meq^+X+YktswO_5CLM0*Yq zt;``SKg*TtUtcc2S&?!wV8oRzVs@&Poe!@zYC#kky3ZQ(`_!5PvYVf$O0gr3bN=dw)n0;-T@~ zihG0a&Vu80754<2E0S6L#T-qQ>hUIHkKY$u%zoc*{C*&KgQiOUjJ3IgI}y3~grQ$O z=OkJ5dW0|bDotfE;4f|nN!zb3lpp_Z5UFlfa%AFcu#VHu23w+$T$QUyXE|W~vb%7S z^7@0Cw3(epBq?(>RqCp+ioR5V{C%;;#`D<)LdUX#Fzz=#%AfN*eESJX&4VF{KC?Iqjz{XN{UKHIHS2otSM>jO{r?N} zf5ZRP9a5Q3m#zP-K>kMWl}+r+u296jd_o}F6F`c;sWtvNq)OXHD83SuKZI22BDN_@ z#laeD^f_+En+PK8uy z2-}qty;@`25h3?8W9*g%0{MAJmD-H4TjmPnU1My&N$(TOo1n4H1aI~16i9cg&=l?$ zyFUut7uU~c{OJoEBX$jHZ>5*m#D$!mOOyR4%CGLo?RmXuqISg^y>^4T&y zH;L61%{9*Ne1D%kgdN$jW2*En23zW2NNU7jqhtPbRAss`wK1GS+UfLx72<2lG-)yG zX<-$qj2+r4kW*}2I~#ZNGJV{F&;LIAB6egCjjB=|rn-8JI8r2#pBIOu9~r+#zpY8H z82>jGhoqN`|KBbSNry1lf&(E*#9$j52uaV;IsJzw9Wdth!|-~sRSci&KmR+8=_GV+ z#Y5U#@K(OKt}8SN1}{ax0Ntd|_1tGV4BAIk>2VCUzvpVwPUAb@9aUNWf$on@Wc>@i z7yeFbEd9=Dn4c{!=?Y0XjNQ4 zz+n5yKuG!q2HVkrkhH@1#~F3SuU)21TF2^$b(CMDe`Cu>`Z~%+RVm9D zD`R}VvEpI22cpG!RDCiwNX9#-#x0z`ukFS3`eY=%CR;> ze(hFOY0|ycwYe)7>ay%HRh4E%tUnfk?I#h>UWmBY8}a|jh&A8AO@|eQbFKladkr`* zg~@RKazvGGoN~=~tv0@%?udI!(FA@6F(`2``S%!3VAmF+iEEPK4;ua$k>#o?(Pv&Z z{6Z)3oZw;x%T(niRh1~u8pVl9A_ChSn2fh9Rh6Qr)CU=dC0>*3zfSkVJdCE_FPTn9 zjAm`>xK5E{kA|g(44RBrRY@{I&U0uo?fRp1d_}9ObY&!dVCM11##D*UjgEf?!_wR7 z_&c0rXiSyv#*kAG9v`pK`+#%$8vZ$^vOeML-YA6$D13%qkH&|2CCfzhGb^3m@17;f#GPx|2b&#z1nzq zRKVb_wZNmNuGD+MCXc8rZiVt7Ze$A2^x4GVlF2;t9JVQGcSi8d-{kA{wO`ly&}up! zg&$5;(1@=4T_DrPJvU|CH!n_%S^isn%!NPE$6Pw1N@r)_F?8RAZEx?GzHdxZVCooA zr5}!{QqOeUPkR5UOT0g8M3tTxQKdgcT>mWM|Cs4~lhNKoW2!{qoQA+nZN0^7G>NVs z->ym24uBQO>v|Vy(qBM_)w^T@4|POk_Fh;XC~cGF0L4M`x(Ilk)ZulcMu%57QKds@ zW`54rd(=ttFR|WEqDr@ns8Xk<+3EhA7jgeMfXxPAyA!~+4kqsjI{sn=OJ{?=cdi*z zrFQ^wVk6$Ce1r0spA(%&u--03daujy{qHfJlcdt&kDzj0Bkn^ z*sh;~PpTWWMM2IY7WX|fuConXgR%Cjr>wn-s8V{EpS8xY*w%w4s7eB`&5d}L507tm zvOQmEoQwHW5$PUPCEpza*?ybG{6&6)$DAKkS%SssP`Bp*|KVXKqu#LyUg$VnVHA<)86yD*vgd*)$B@VBF?6lC^c0`vEf zgAW8>(X_@STom--d90RAOGtB{Vg8;ZWxWZi=(Tc9bNdW`5B&zSSLnLF#xJ9csx$g! zUZd9|{4#Zs&qerUs_FFzzsyUc)BQ5^x##KH-*J+65Ht>*aFVlJLI4oBTMiZl&vHOK znl@>UK~1--_KZ&0Z&dfX*e;Oq_@B`U8}7+bRjQ4KM^9OF9{F)lm8hM<>M5*pl6u1q z3fn)|n!r8Pj_kQ+lk6*7AX7Uf;Fz#Y!}SEZGp^9>rNS67o$|!zXNyO$$8~g`$Mx4U z|9g9>&^Fy(x^+~ym+1WHymoLC^SR&t=Hd#mZYbe&iH1XX=OY1D4?Fq#w2 z_eoUF;{=61cN0;i+r~6|E{>^JfRmo)R@$abmGxYwIWU_sH1;aTO1FJL!^UZU0 zm_HU&r8X1vhGE_o#bEw?80KrEro&vTMZ{Nw^caWMSRJlUW{U;jaaACXtMW2%rQezY z*SFH6vMF5OqHx9b>2Uq$h$=C=CPN^9GSRVhn#Gg=lu~?x_d~sY2$;s+;y^EbMr+Cm#D=?OsXMw7cSQ0Q4hbT z%aA?W{yv*tAH-WB)oa|%yklqjXDVl>!#O9I5Dj2 zNk@j&Nwo}Kxp{IegROl!uF6Xd{ph~GkJmA{Fsx3ilW=%g9gk1;P8oa8&C}~7C~J-Q z?(Z4n-#an>r^D(c>m*z|qE4%KaB5hUvV!Vm>m)3g;k|c;RVg*7^Zj4>RB8VbO}bQn z^#KD%gE&gL7}3}9pGU)ZvMYMe#02GrwGlZO*rpWRt=GIfzEO~Cp9ZTju{Z{HAp1GKrqTlBFefzB&lLy) zXgGdE?@P_k1_E^;rfZtp6FrerJhgZEf!+|y?-?{=%r{5rdEGY}c%wK>8P;_~9ft|Z zoSO|_QbstwJWOHl(oO>xgGPM$w}w^e zJiV1ky@XV@!eh9>q(%apNC+%$c!oLyt^&HIe;^C!kPUuLgtCevwtXh@YF z7{2^oSwF*j{vlQR*08=;`p>G;sm1>~ey*AUKi`>xpGRDm$B%FAbo~5Z13!;Uf#G+i z!0^T}el{5JTRH*1rlINh`OgUa+%skDJ7>Vp6Jh+^X^emK#Q2AYE{z`&oDS!ML#jk^ zbUFM4W_Zs-zcZxcXWv;>y7%9}&##V5$4_YWWc@XMTl-?wMLPjm!+dIu+u{f`@`<7ZYFKLy74S51tcdl~$QGr;-kAyqo~HTbER z;l1P`Rq`14S$I~J`fmQ$@pIP<_<3mxesaGCKeK1RPvfADpV}!fd}#^{i^KTIGvJpx z0l)6S>G*kdZ~{M-Q^qcv0Y9&=Ht@657(aPp{Eop(<0oqdIRAQ3m9G98{G`tC-dl7X z27Z42S5?}3^QCox!Eqc-)&&BGr|SaOu8!0N5|yRjHu5o9j=fF!-5QFwndS7rB>8Mp zRt`@1ZEl_f*90Z&#z^_B)5y0CxOQb5@;P3IE0xbr8E_q#K|Xg5Psry113o2#s&sl# zWw|Yn{Z*Bmm!MyEMu9mcoSQX>k@AznQ|UKB`THu?KbpnFZ{MiHq>^Ljw2%5?YEuAU z?o9MN6(%?WCSMLrhRGKNG@IJ_|h4o7By!|zrZ`ge+E}0TlKRvy%PXQJwc9 zI=1qzuKwRegII+4K${udR$d?%F2b=l6<Kmw6uC{%E@w`bs+w-8qpT!()%Dj7to>&+#=>htA#%VmP+T69w-4 z(tJ69%}VjXzpkLqr5$*6#lseXJY4PwmOTw}nFUB!NOK?BD9C%Wf#oTmH|Zned;wz6VjI<>B!A9!`_-E$lG>_pS*wDiGK6_ zpZ0I-_**}Ztm8OXY5(yjD|fx!-*($)3=jPMzJ7`ee=N9TdA(M)7g^ii^d9_#;^Eq# z*Y{sI(%w(;vHyBs|5Ti;x~Z}{AMpX+3U0gA;~Kz7Sz2nZVL8HghNL#mUgP0f^1LYm zp*GRpY$vme0D1B}mX^HQr#X55)dD$C;LNqo0|I7Go@Y<%irS~KT>EsCyu&5P<}4(e zA<=8uj6}y(Kw_@~66Zv@wVX8o7cmHP8@w4(x!MgH4t@yY+ zHP}*Ky`rxCFDsf$Z;_kJQ-VK3_XS(Zf3)JQ^814yqxr$p&-fb2jCD|Z{ zWB!gaoF^(afGT>8;@pk&JkF{3d~8Uy(|73@HcdM|6TVZw3`tireE&)wv{HMIn^gC{ z7@)CuA&{aWRoXRIV6llMNy5JsoA|9EJ+`NKu0VDr0a-hwN+q0-TTf-`odxnBn@_7= zPu4p=x9c^z)=p|`_;nE*|CY< z{U#8f+XEd3zkK?I*#*$i(O23DU%(?@;yLX+n$zBgTioUT`W5iJOM=D zJ+8>w#GiaKB-sQIwE}qC_YaV@t&m&5gPVRwGvX-y-*>FveLILHMtu%{yl^aq#ZRUv z?|oD6#kLX)$DY`Onjqtd9CT4~fvElGmq6xT1s3&&cbLHzDFLsFXs z#9ezpF5!Uab=@NBq-MbQ+3UhuRJD_{dCNG+ooPSO=f1Up)rWeEcjmHOs;yn>q*~YE zdqzJMvZ+g*RQLL`0s8!88DfhSh>e5BM59jzg;ldr%U~9(2dT@C%kiCQ@*!RzyXL|q z8F6xkZ~HNv=F1&o76>FCfCMh0V>|A8v7f&ZvPbOmsVcBq9jw0*CM`szgl?6TWYN-Geh4I1a1eiu>PokTJpfNXNB1;5c7Osv9k{I zQ~48vh=#OUq8E`zw2fRWLE)*xd2s>d!S@Mm5QSU zQWg!<&r5Nl67y%3>4U){Bu~=CK_GWwXtYO#@tde!Y@B-OogT|$?0$FO)Yb#}P9@kJIh&kYKz5gDF zzCsYwIgd*#1KC%B8vKi)iPdEcES&AD;2L}txWQKu)!?fzHTWu`8+;Wp4ZaG#!B=5! z@KsnEd==IPUqx(#uOhC&R}tUftC-c`tC-y|umQ>47!iLNCl9~F=Z++!sx#+e#9)FR zr~ChYY{=_E5X-^iI){@K!1-q!^Wm`;Ol2gn_~)D-qpCripwQnZo`vNnevGOd0=#`L z9^90k9rx(+g7UP-uLiMXpUCimZ{v_$5)GsaPuQGa{TNj>Z(p+fJ}P5U z3!1t!3YvIi&Td1nguy1t<7!VvRdmjD?$TxEy?I2_`w2$T>xoM7k6B&DM*6Ii^SGKK z#(Cy4^Q_e^tfMtNNI5o7GS%ou1$pNrF&OWu!BRSVMRQXb`Ty%aIdmdlKD>Y_dl ziq*$i6fq7md0hY37-t|sAm5r{91o|DQ{Jb!sk|tA8p)I|Xsx^$S(AAzqE8aVP0L*& z$v3FI1vg$Ro-+0V-Gf6LkR0BFk@Q}Ubb6<@3#Io&!-mmyK}U9U9I7ftuw)tNJ)nlL zBl~+1^P&52Xan8vt@U9!Oy6Ay9v6LQC>B+DLfX>s^#bs?`eIR)Po2271w5_`v8YOj zxV8s8u7AX$DhI%$Lou}}=QYiK*&0Ha@5sDTucv0|ecg5Lhgi0xK@+uG0ieNm9NgWl zSX5e3$08&gTgB?yaN-!#uRs~X4yF4BliYnCiQ)UlTXDyEJCJS+vRMEz@H&#My6#7M z{=pqnUU{YeOf<~luM%X|?@BE^lvQe}$wx_nZO6cEHhEla3(YlP5*oC!Su#IIAa&8u zpj7~=#|c3n#^T{t+>xmX%ymh7MyQU?N)rwm$5MRD0&tCx~>NZU(-l_YX9=TIvJv&D+Qs{du&f~wLS$(;Y zTQ#ZfF}=U-xmGMfl(T_P6NvAJQ4MJ(LH2I~(%{#mIu05wR~E|F*Ffa!Ch{(xM0=~} zp?%f)H$Y!nBDnK2pby!>ofUWR6CMks`;CVFto8kjM2i09)C5 z=&R$vUA6}LHb;SbP>K(#fzBq9EG0O z@02Mn0yj*L$B{FZ$aSr#<28&soK#1MO%{(t>G=yIA3{|Fa|7+5OJ)|DPel& z;Vf1=spKFErv3<3ktLfi&Zk;E`6;(R@Uce4&_Sax3nr#~YXb4m>VM5Xj*|u7kymrnltPuTNgC z6ecfk#>pqs=6Uim5vuCZH2ZGmSDUBI>sKYcZhwjbj^uTl5!hZH(wlvH1sce_|1OvVj-Bl|D%5IKim7a$9~!W#&s9^2QH#xtGj234rC4Ny6Z(oCuy_5 zy&HL4Vfx67ilC1;z4z+LvZXo=v~nFRPPI2xJQt zk58e!)hTpO7Q)*{?gDrICSAT~KIK?HFiRl*^N87lnGreA-&n2Jo~!4CV+8ZEKOczB zf2lnpN07%Xdadn+2;3C+du}yw zZ!&O?6P3y&SiTs*)_sjYE?h*%9=_|verkuUxvQ%`o7I!HFxj=FG`41MG>G}g8mKQ| zwRDUcTCp`2R>R61SXI8ay5}MsQxqTLuVH`x(wi!)yHf=s<12zoqo9$_Dboq=`shUF zzdyPvB+aMvm!Q|lxwnyj-Yo7bO`0Iu2{VpI%=QJm&=ejP`hVAZ~$ACQz6amzNSE4ox#a(RNNQLN4CJ4 zR3JX)&owjt*=_i91qAN;gAXjP)MA#Ul@|s7(yRM(<%;`)^nLo>RjCv81V8OnrMv6` z0h7m7xGE$mSC`3eJOCYR&+mC)`H$uTnObMn6OCl&qHwKMoi^PYH0C!N#7H?Fh{>U2 z|EgD&HqyO=?`3(PO}(n*vkK~Pj6lZh0uda^tcU;qUal_Fd1?jM!R+%-W5xH3yud3z z`2QhSth2}N)eD-98vK>f(2;;r_UV0cQ!Vqt)EsWblX^uSbq1;pg$TKlaN5(jfO@k zTCcl)h7(9qG&HucUNR{x$Cr+)*IhSyr68M8gZk6z%)_=C2TBM~-RpM+Lhk$V0$IuG zE5T!Cw6{7R%@1r=HFx`5fxLe^i1d0I@>cIdkTaiy#vc6tk@xlCQ4~qzH8UjHO+pA{ z^F;z1;DiwQ(tt@Mkx6nY0_qV~K{*H?-ihKjA|hfo$=w+U2qV!sgJ%NV9hnsnVWZ?c zFM$A}ps*l{g0dlSY_fn5KAZ+-=lAq2vq)m_!qT~!IT zTNyrU9K&Z7F_E*GtE$Bi0_O&XfG{S6oL9sB_@`D^CPB;Pv8R%$Xt=D7z_NjD0xTa` zZ#a`0a<&4Py!Ro@TJX+jkLW7p5w<~`qZ)Fs-P|%KPclRUaz*i)j|jKJHgr>8{?qEU zIg(bldlpDwEy)I^-+QTGEvPB&ooNTKm*{F_|1BCURkS`frg>G6+W3nDYU3vtFRCn~ zwef#T>!(z;*Tzq_ZLxU7s~p%cud6td`*RK~T0Pf9sI{J7c;I)VNxpX{OY(Q&v2x}o zMa%boH55<_%eUuxui|K~_ZS{&wW*CHSAVcv@1r@el!uXA?@0irJOfxTeQ^Jp0_*Qb zgT)%G{(khebG*;j;?t99eEN~fC#B?-Zk9)c0A@rB2YcWhz$r_P@v@1pg< zv0NHCKnV<>H~^D7hTN+uogzQU@aSa*P&fzZ*7@nOR*QiF`@j$$E!Msnu6=VLtw}SA zj=MDD*OmAE&9t(W<s_vn2w$BhzA*x_xkPe9&tYdrj|5S+{ci$i7?(He#wC8c$zBi zX7F6d*zi1kh2|s1bG7*=64!E`#s%QHV{pKKjQ3&PJv53(Cw2c@0Ze$!<9xnvk?A+06*c~A{nA-c)_T77i*uEG}gzg=D&qeL$oo7hQ(VPIh zu*_n-R(k1`&uH{owMG?R)V+)GevZB~DjJ?|;PAL(+G%x(i?tO+!SmC*lbDT=Q@-;q zKe-hxhdkE(3|>z^7b=|SPtLroYGfQvO{bV_U2}=;teyX1$==?K6UVjK_l#4DIFiN^ zo^g|X$nS!{-5UV+ofAHoeYy~s+l~>KeNQQ3e;OOt&R>9x7#bUg>HqQ>MO@J#HZH*y zc}fvqJf(<)x3L;;&vPc5H+H%+c#m}gPj)Nfv>@;@bUYZY`<<@)9ZvNv{*T*v5hh#|1e zF@VbO+!{|}TT`^TD8aT~YoB1d^^78V*YK%lynX7a;il!j!E<9T{7p_co2`mPq40d4 zoo|;_Cd*6)U{LFwWVLA=F2#KOPqSSkX)IBG9_h;j9vwbSXn^s7p*YRX{miY1m$(=k)_;$C)Ob9vUvErrZBsSgM7w=s`f@87 zdzdDgPhjJ(gtNEMb8Pvn;2qNmyl?!iYR)0!Zzmald2U6#hsM03Rx+lK2Z8&20NlSG z_rWYaL16aXPGAmpE8=b5n9TgVtiUmd>05d__!x|LD`Jtm;~0EcrEzVYzgNPXSim5amN5v%c+Uyb3B&4-`+)Kq~NsT7t1uBjvMcI7;{_|E~V_{jiO{Ko)QR5{L}EC`jZJ{u-oe%v6*g+}Sp#Bk}tgAtNa$_N)Y&W3H^ z!ru_zZsBM+$FN{Y{Z(+^ZcXH}{e~gy+tO0_`J;#IX)DuwyQ43=zFbV4J+eT}?-O-oJhAb^`eYySx3~Q^RT3XIC zo64eibl*cwZCrawbI?kQa6)fH}DyjFV zqVsiLI>z<1tpRI6{3und?n-?2CHIkaw#+d$@=lB`pRpE1jUwlc@jG{pCA=naaAsRs z1o8i{ELiGhfb>Z?pxPNAycGt>*^Stb@xUX;DMiZ_^D(v`!+4~I0fH;4efKFv{6?#1 z7H7lrZY9T~*7MA!Cv`p|iS4QRhq4!juUr&H{6n)0czxNE`iH_h^$%s-R$i&H5pF}6 z?<{A^-5$}vSqr*y)`EJrr@M?ZtW2B^Qj!r+14C-PU*&l8eo3Kx-*j+Pm;9K$ZU#6m za*?(wrl)&sv03Je-^*_0jJ76^YSD6*ay)9`47OIb>&n>aAS{{)(&7j}-neJslp3pu~E^`g45&qkA0 zKgISd60=Y0r;xqY{ddvxy`Rwe>%HUJ8Kz5|IqhnTqSa6Fp6|V+tDj;yrHC&DobPRE zQN;1BiZ}tl)YxC8G2&nw@5R*s&u?W3u2n5$o?T4w)O_1rx@&k^1MnQvOmLk34}v56 zjt|EJEsB^(&vC5^C9unMba){M{8>Thu$n8GzV{iGs@sDfJp+^uptZh-mZmo)l z*R7qk>k_2hJ1vUHw37LBPJgvMuI}?YRneJ5)=QW0{K{clf#fUHeun@$>n7)_-`cN; zyEr&&C?2Gp@p9q~4`9u4mYUYLZf5J?amLcZ83cDeC#0qJ0LZUvz=9nh0~7@?J8r0{7Vw1xq)H8PH| z48Q5V@gTGehV)#7b-pvBA?N%Y9yvv8 z4t{n%ok1-_b5S@0FSN`A)Vcubux;xa$)iV@MU_olqOElRAQQ7ft6hEY7FE3TU@rP7 ziqrCXf>>j`FvJ*hnmTWS`F*)7#>C3>tDnA9a_UWoV#`n zYdl7AA4m=BI9kJ+)CWDHs_~C7-Wt}4w)0%1ZR1-^#VIWB@jPm{OzK%5B6j^*Y+H}6 z(|#{+oynt?1$>=*0FS);d3&~i1wGE73o{vnd3T(P5VYD+?{*Q6QUCKFc48YoKdW`^ z{T=+zH39hmv|IvzO%SxY=r0sb|);MXuk|wr=pLwrXbF<>E-KhDsXZ%xQT3#rE__uonCX zU>Y}qm!g)wvHy*z4Q*#4zHHkt=#&QMjde@*KXB&#wsGfp`Kv)+wtaOP!+PNI>2*u? z-ygN1?fxNOwtczuOq-Rt|8lVrELS*l+GPrV4p#f9A~6{SQ2| zzHOY5M`w2LX&dt8>CWME{_rQz^Du7*!he5H+gD2oeWK1R-9O|@0{@LOyW74RMBsmQ zdddC`<21fxMLqD9_FXIUz~v=T)`Dtg+$+{@U|AOeXP4ZUi}rK@`??TVzGV8ix+3RT4z&v&ZqKxwTrNt%JaS*H!si4;T`4qj#h=p;}uO7dtg~?&A%_pot}$M4b4TT zNAjqUffvRoxd$xFlFB-!yz(du&!;nGm2)2ep*{~jTmZ;GH^03fEcLY3b&b$wBm zRL}L4Yq&&h&#p#yzIkz;N4$^YH`SJAY4xrpE>XVqlDd3$ak7B>)nevR_&5+;Dvzcy z4LR7pb|>*@AY-k3g;`wLI+RBk4-6}XvF7A5WtFb`-zYE~|LY5>=U~g56--6p?DS0P zL(=MA_XTUgk}Da~zq-8Us_pmin>agKEgQUhY82?If1*Ro}C#Df_$FYH0hzHwo)UhM}zg$g@`HA z`LR&vIuCWu($Mu@+B&%~p*f!u{?^Di{>>S*b<1(ioOUvXM=wP~1=dvuxEC zEsB%WPXLYNVEBcINfMUVX8L_>@BMmEPV`4csKEO2${bCGOxUieY*EDXT&(S_DgerMVM zuwcGpK7E`=?0`$0S;MPmYEHB>-I{}Su?tG zsB0ut*ao~L)s#Mz>7LAY*tdUgjowd$@Pc^CkQPQ$+_HW?l#H!I)iGs9&$}T#!+3GB-eAj zGo>}zlB-{&P*d7VZp!C`Bau+il-`izdOa77%uaZ~&;&ve7w4`i?Jlooz*3}wG;1cl z2dJ8JWHY@I9+<{ib0n@nt}nVxYD%}}JP`q?p6elx0Wgh#-@g~Q{+z{;_`-yR;VTVc zpqQneT}7nM`ZNYC7uw^%OtvaE zMvFsOq>BUl%H_@R9An$I6LAlGv-+J671 z7!PiuY;~#jf4CGe55t?sqmNy99rjSBO9{K9y7Xarv-X}vu2$6Av#J_T#scRU5Dpc# zwR5CPa{$$F6EfZR^2nLqkP|4=crNYLPZeu8i|m{SsAWYis^?5{HFqGpz9?Pu&$yQ5 zqSkyKSvhMCwiyc*kO~<ex!h9{EOJ(f84Ieoge_*CTR0mnb)Ur`pH66mgG7 zjeq3M;B)J7E+@Ls02Pu)jlZy&M_&Wj&wtFLBG%;2<;a?y$FM(Z$hop27t#5AUtV>r zHlJg8bxyYCT=@hL<_qT0v^!NXC6v~3ZU)DkU#ntW>2Kws0H&8plH@@yGH+{fZ;EP} zTQXIChz0vBEgm7(W@ciwxRgunbSAM2n9iT;=-iXid0NR-c`j>~<6Me3i=C1=H;-{> zdVrlOcXuh`M=X!tzN*?^E}1NAxplcXcf%Fck}wk-m>%+MK(n({5#OIqV|c$&)p*32 zZS`ulRA1Ul{)n3*kK*Fo)sbM?#U}dIA7vIAS7O;-7YP*?=-J11A7F%6f0%3oa#az3 zZ&f4XxT8rGYu3)uYGG{Sz|wMnuQM`G*AmVnC)qsYWy#`0)(2#=PAfTN1( z+S-Q!%lk~kV!RgCbWlDgII*0U@@PdDsEq_L6)};t&hVbf_t!_ROq+kJ+>%b}Xc+o1 zLQQFmjNgyppw>z8!*jz&C&`?m$@)AVZ93^MqZ>{JkAM+Ua=t+esoD4=EjW z`g4co<|DL%^=B zC%b?JukBjs+Ri=Fr?(Aw9n37Mbj@Q>%N%N-mumL;zCMQT!nP1%pS!l*ynW6^ceKwR z!1UMbQi9j1k-UZ*hK+60!1Kgf{l)FE!eb!>)}suVwEl(MVE>93)Utr~uQ7t`iA_oq zX3+J=#vANkO0e~Gkp9Kt{^f@YP5DOQSiVuH$2Q}Q_Lt`VzZj8=4l-c3{XJJ&cMk}- zeNCQ!y@2*Mv7}8c%cHkEYVAeyFKC0LV;x$w5Tqg_pwU}lzOf6S`vFYe{+#Nh zKZ^(FY5h5Uo&KD@!T#h$g601IhW;$-4rnrfDQ;kJJ^HIJvZI%VLdCaN)p$Io_QrGS zG9InKdVU4b^H_gX^d+%w^D~H!*K((FF}Cw70R8^oiiqdc15seV@H)}^_?;#I%d-Hc zw@Z@bDgRc)3p6)HN>{MFMRjM{FVvl5|4nqKwPdRN7HgL8{kI~Pu~RbNqPo+{PL=ci z?bDrq4x&4;UfaSY%I{`$)Sa4M3FFa`h-=d!BM2RSMd`32v?Cn`Q#vH+=-}*f^K>u< z&>wtbbp@`>;c(fV7KAoQTlJh;HH3sZ@oq6JfB376FR}aM?3r;rqjU_iiqvF7ejq^oR@Cc_WJUK&-TJ}yII@o zlN0{7*T*M1+FqMZ+?eeZ8H8@Q54ex3PAH%ZiCLkewrYRsgd+Zkh`sZ~2~xY|#jC0v z+cqzugn@F8%ygpsc zfThXeHOI9g7kPbHW#ND-W`Kb4v6sfnc>t!(+(g;yTUo@$XugvX3&U4R zTFgg++t42@zS{Ji@9E!h+n*~h0oaeS3GSL-`FtvAIljCtM$TG*@oHU>tIhQ_tZ^mA z<#T++>+9(tU_9}fJlqI~Hxi!;UdveD_%T~s4=;T$yF8pnV~fqQH`i*DN43}=oF~;x z%#b85LB{hMo(t#Db@S%ZWcl(4RmAu4JmTHc7mgD>f%%2st0_&E&yEQ0Kk?6_6VoA& z&TGeg>-q)9b^a4>d9=0(s_f zfB%WM-!CGyc8|`Vav+5GQ@p;EYVO-?Jbt{gyqTLMxBFDM(Dis+ou30}XK$Zx#p_dP z&F3{Ai{@KdYmuy+HOK2y!Ru77UnS<3`c>8f@vCqlnqP%8+?-#fw~qcv$Nl{(@yD<4 zS9xJXN56{kxW8W|GdbU^h|UQOIal82(dH{^Jl4Hu znsvI@bMtphG%4DdB>bKhhhxtYm}Ku6J5F$N zi8gbxDr(mh?qHu|+2s7kqGs)koux?;@8Q6-xsh|s_}(Mt)8Dhrs#YHff1}Mw^Aqd7 z;Y!kf!(cx?Ti;IX=x;E~v*h!GUlr$JzC z4uIv*!J2-Ez{)EkutJ*@QD(tpq%|Z4((`+lDa#B=?CbM~WZ~%~np>XI9SgrvX^-^Lz$O zGjzC)3&i!*a3L=Uu21T4ZCXm@|9OIIg;Np#bRAqIB~cry~9X;}9UH$J149 zZXJCKnOip;BlU{BZ9ifB-yc0l6}K>8njIi}yY3*ex0wOcV*sXo0H&XHIK+8r6a&vs z;|Pr~y_n&6F79b_ANA4d;88zXZS1o=OW57BBdyL4*UdXcgjRiL5L)$eDq=SlOc<7y z|2qiGk9zu#dFyvNc*S)7C?sRv=v2fjos4HM?F*0j&JXKpfBvW}J zbk8Ju7CbCqEdFr2D&l*+bnoh6VjcPRFtt4#0BZ|#KjWW@Y4W#`yES#Rk;9vA%tn6f z_8|VLa#9~2VZGPLBWG!d@VgMG@Y3~{M5pRir# zoaB6|%X_{wok2A; zCf^kT_A*^Alcz$!5*Rm%VL6MUq-*W(wDjvLVVsZW(|9MtC?Su=J7xV7DqP&?tk$qx z)Dn@~-j?p|Y;|g@mNn)Z0f0s&Yr4xw5KYD zYqC6An@_ZwSP{7h+oU11HYUFBy%tiL@bY>R=Jgt*(0?d7*N^QPGWUlI+e4wk*^Ng( z;w#tFc44RTi|ga`U)(V#{^Pg%*T;D!`@dEn=bg;|Y<-*^-vqCZGwTOmeVl?H{OjY~ zm(a03&hxj^{QExs)+fL*9WWlS-bJ5nt_VCHFGuJZb|}JoQ#iJzN!>+2e&dEGdCzE}NXSDl?wx_Ti8ZlqOG;9W_ zXk9y2y4(+tt1&N2qj`W2&&hiIcg*@jiCCxe$TWwmyfs>Wlw;<>LY2NfuTM~N)hU7Ef~)cksv+jVtMTOpUI>FWEI z`E+&aQLkSw(RK^|RzA(?l+L3*_*oK<>KL$JHuDI#2L>#U((`oxC{31M9j1!-KGx6p zT?{7%!)c`PvNL(q?WoT_!90r4@u=NCIjP!1jw)iNmhW_mbZO#mCAo02bouc|rK`_A zA}I?dNor}BHoxHcBku^AOSCn&Jxg#lf{+>St-VU}2|XN7^HASM=Z~|;+GCf>kC3=& z3~T5SvewaJ!k!D&VBHe$t-VL+n@?eFy@#$JPakWqz4!7F++Sb4hl>Cs#$f*Sa08;UiVNd@pErytZG&v4Zy*UNf+C+-W== zz@y3^iCk*`C-Ug+9~BXgsmBJZVjW$_2tShiyBeH)*0HXZ*!PnMlN`}9i}j+(He`n{ zSMhiolBnwWCu{Ci9TO(Kt{yxk^bjR#am68`^iOw&b} z|MFp9tX(e6nZEw8Z~ZI=fxk2WKGy5C!)QF;&*U2=-}}CC^ss;4^ou%um+_;orlL33 z^q#|tIQ&S*yy^OO1B0~t*I`BMe}t?bc5PQgF+mN=n+qIg!~B^M$&=d0ls9|;Unbmn zZNB{DwvKu1r&7M$cUTdN!+FV@Z+?Q!Ki7OX<;nCmLNC^FtUb^Cio+fA*pJrnkJ$k>d&7AcLuLB;N?$25dK{Hp75vXd;eMhhhqI{xcY0#pA(dR+kN!A zH3)y4-~0IUMF8xru^su-GL-V?2MT|y4}Q!w_%k~Qo#C(|&bkhNrUYr%_PruLO8IlO zQ4x2?tD?%W8h@@n%So3X?;^>CA=0IZq0)s1!!%x{{gsRvY~!bbFURYM*y74~&DMyu zHF5E_f5xlg%b~m$+dPQ@J8-^yQi;&N_oy(EZ_*G3j-HH3%ej=Lty4@|Uh$a#ma_0e zl|3B^D`#o>%wCaGL&2WJ@aRei*ptIZKC=ZJj~0Z0eU@e)nl!rs!zTI6l4(A(1e(w6 zP-W_>gq3Edr+X_0mM8Q1tS7n!<}-`e@|n$!;n5TK`sXwIHU{jiT%wjpO%INxqZngC3P zzvrbQnxk{p0`r9GdqAkkgDkxME6Rrtk97mftZw|KcrCUm-Zo)`M|83LrcX*3sU{rI zj4+bt`{~!2idj)S8VJ^c>3#W6>kB~3ht@I^vViIL-WC8m%jt5U8Ngz=Qgp!FjpRWy zhJnM(8CzRu9<+fp4_Yc?u!U?_ctZh zO8o8otEvU#VbJ=n6;<^YpeK-e}(<#;rL160ET z%9?+tT*LBc7Xx-f2#>sUo36>FF{oT>aJw4HV;MlW@0c&MqOjh&SGqLu9!V~|Te|%C zucfQc()o^KwfS!EUH)|}s*{P064n?z|NlTBn2gopLzMO`f zMd5&~tThMs?c+ytC4J41X*37C5x}J8!G|+gu*gyTCI|z;KHMW3B0!i&^S~bqC9?O` zpO}hiB_OOS0paJas;IATrLPZwb$R7o9fQe*5SY?}3ZXM2q?S2U?>b%EBkI(3rSG+X)gib3hlwqP~Jy!EU`cLPhR(O7<- zV{EafUp;{5y7{=T;nsp_Y(vfyX}Qua*09oBGwi9JJbJo6ubo+$7T%Ck^cve>wMVtsOQy;e7VI^e|J7G>%HRKL>fnFfe3-21s!OKIcGfIo`?iLi zl4+;@*J^gEY&)!oZ&Uy4$JGC-vc&)T^9*oQ&jjJ)Zh*QBRz-XtukWnX|BCyB`?eVc zuZMK^evkN@c(0wpNPhJn@^Sf4gt$YB~#^x z+i4MJGc$1-Eq-pNMLfYDz|x|l#dA7Ze8igNrzkBx($V7a!;1JV%OmlsYTu&KBHm`^ z;(fm8ejvzUfVK`&MSOoct<9nNqIGovlm)rII!&y04ip7@KK3xF(V?#oU^MV3^)q3A z4De`H^4hjt&mUx z)kd(SMl$7iJjR||cp$C|UW>=tR;PQ!U2Kfo2!?V4#Fksbz|zW@wftjen5e}|=MRyK z7J@XU598R)hL;yHF>byKSn%&5OnCWI#gn(}DNfq*6f;Gh#vIAsgXN!jH~XpLDRR-m zY^i8rj^1JIJX06F@_SW{$KxoC2`?`T2ei098AnOGkS=7h?Kr^I=f)**JX)5=*Hw8y8r(Hsc5?<>I0JQW z*m5N(wq{pF0jhe9l_FySMM;eGMsFTH-IbHOuM^-P2&NBDO%6Is5Yc=DF0lB6vgm??5Kb0j;8?Ii>IZuW-aDRTY7Y^i=>juchW zOPhDQvAyM=xM*8F(_8*<=~VgL(%$l>5FYhl&2n{jz79&vTlQa7?LFA3@~}`IjSmG! zA=_P(BQx7WlcVn8`zwcS>!Ha}r}YG>9L>EI%Mqz3IJ~`{pifo`zxUM=93DiDj1G@z zitD^?q;zP}{zZS;()RhHAKDfjYVnt+2bS!2ZQsx~`qXwJPY)1zs_E)4PfrbaTa%}! zW~^-+^wKs>o}L=exjgNP084yV|GJS?x6`_jB@Nk&SRy}*qj0UkeIin+xYp` z(A@P#2I{Ijj8x@erSPtR!dEeZc`zUdVb(9|%cCj}Cs|9jXIFV>Ey+HBuzW-g2Gn&c z%!lGXWMes*7Fa`a72{aWMwWk2{KytF8{yttoVeu!X0lw(e4o9SNs=3w%Ixam!`b!9 zol-s1Q*J0;Noq_gBc+Doce6hzo+9rp?j`GMN(R)Ed|A`QOmD28U(UT&J;~LC|Krnq z{O_!uCu^sD4UbFrZjVJgz?b`L1{`FnQ`b)v;R+^HvI+eB4;&@aP zM||HOe5Z&nhV$rae4ph}5eq1V1G^sH-@jAhF&=;Yj-1(z^{Do;JU;6!x`$@%!K1%? z=RFf|vQ^Ue-cmZgw}QTRL--naRKfW0ax(sSSt(wx(eE7$g4euX@V(eb9@R2nf3XMA zkL`R|P5AKDKph{Vcr>>Mpu+DIaW2cFSQhLrh6ZofF!0*^dmt$Pu9Xie+%XDR_lYWl z^zVs)ju%2*b9ooZ83xFEu0O@iSZW%<@e$X>VPN=8pR@cXycRi70>bylKyYOMs^M7e zS<4!uwl`&*PWG={5rA9+c+}Dlw3=$J7#b&VE04&2pTV8tVl2*?T?D)aznBi_;oDWw z`TBUN?3?Xe?A*?#@?CQ`7f{*q{Kmmi!-OSaAxg{O)6Lm@LINY4qun1Kt?!c zEik8W2Y25xGWr5%NJ|?WzOv&X`KmZ8-OK4SLgWWXGxAh z{H;GXsp8Mi@~A1|LFvLAsH<)SM{^@9)LvG_e?GfVs^XH|kPa3Xm!D-|V8kpg*)ML{ zu+X^DY=m+R1;m7Exj(meCo!S>GK4ju-W>nGq33qG4K2 zjOtR>@mH>kW6ec%%6fT7vt29JdGXb=inbcoFMJ+ce^CANoAFX*=s^$)5 zqX|5!=9XvIaNXs804DtWU?}deg(LDHY_0NoDR}{a=6hih6q+!}Rf73^$!=xH6THdDl3KDINB}_$)C-*=-3okIt z+m%i((YCgSDpqsfWaBxbhMOqY7u_MXe8QvZ((ZCK_hz*sm zX|_~ql5JdUrmKIExM31$vTNX#xT-`c|-#wmX9ihbJe9Wa!sj8p2>p60I|Ex z#c+;e!IJ7;@Mbs0{ap9-ftDLnw#9dKc4@set-N?xt{AOr|ebjIo~Sc zJdYaxPi~6L;qQgzXYD%148OWdwL7_F+lX%!@z)+T{>f)ZO}H^%t!pz*;N{lxJ#Drn zB!BPXbxZay-mtFi$t7R4wcdY5tGC6E0?X_nq)qwY^;#Qu`JT4-wKfrM{La>_;5v6Y zSPSw^P;r6k+Y2LkR1pe7RTP|qdaS>RzFpLOXY``}hLx`O@0U`ThMa*$tee6$UE4x+ zZ9JaOX$@JuuKo0=PS=hEM zYqfY3ov!`OrfcfjeF3_5Bh|J0I@7fueG^>Q8a8#RYnNkP+s|};UAwrtb6tBkYS*>< zyt?+KTl{tH{@ZU**KX;kYwz#-KdWomfBMhwUkwR9zq_m*=l4C)|NC`q&Qbq4Hu;;I zpJTgz<3Gn5zww`AL%#9pTK1ccx|aRWpBJ+`;l&?=@ZyQ+o7c5SQi9F!isd0qSBL4RHQ+(Ca``_w^yT|4Vwa9um&U=Up^F~gHT zC%X30gNk^!M~ydde4Q5W zkMpReA5(jwF)s@h@~F&{d!R~_)pshJ`ZD&GnLNV(T@gHLGGpE@s%$A`r7hi55wF>u zBLT&S@MzvwV0Y?jOnLJTkKPHEmXSPig@WU>nMX;Caq);yFm<+Op3tN7HFNk2zBTi$ z>+bw7t(kZK5PZ$-y7bHR__3;M>+wNDI_mNCpZ|OG_|%R6Sv|h}>)?8P*7MiamY097yNlKzY|`p2*QhbQ8%y0A9<4K z@hOA;@9Oc-kNC?$&4HVjgLe-2%fVX*{N+G6aPxY+uH1xuo#!nO8ck}L9lu$Xjf)C(U2dW!8_ zuP%)4T(3TPmrt+Ge*V9vS1%q8u2*|p{Dte|$FHqdA0E_EuTHtxL9gz+NxiyHuUE@9 zTvM-Z4A85~sb1aKnO;4!Ke%2UJv_KxEyewNnG+^Q-@y8~Pv?4d;l*~ny3wmwH}vt> ztKma$Os~$$?5J1&*!zE2ujcvB<)OC*pUYDgcAU$*bp7A2SLYt~pHD6OZ+(xp}N4@I0)u&hAbP&A?k=6nx z%_F+zkowXsT8v+WLLY|avziPDtk!JCV9hZAi4#0K&?9Q^ ztr{pG4r~l-Ex^z4{QuAbrUL8HU20PF1pfh;W_bRGy*CG5FrAz;Dp zr54>8ZD360-Z>vacxg4)#c{b<6|1$Ht^2Y+2WvqMH$HP!DdR{9(W0vH5Na*hHP9ov#_|Z`)-s1jTL09p62p*w%4;l=F%ruWEFYLV zOz`&4%o*H90JJ(EEQzm!EUyJr$$?3$`^qKQ3}@FCSeKP%zf)?Ktzp)jvVKs9>8sVk zu%`*Df!GkG3-64cJ_joBGcBLSl3qdySPRy0uyH2z5+0?`v>YkPVZLX4FJS_Grs>gj zJ%kzFXVzZAxH(YKvc@8fVhnCJ7c7~71i57`pieQ5q1J-Mzog%*(mV8f+ZbQJFHo3s zbue3lz{L23M*^~OuyM?)ly;aH$8b!`F<{A}c=qoCCaf>leW!{SJ|;Gjvyl}r&DPv{ zXY}W7s(7_JG$HSM1-PJ+Mv z(+G~$jiA{-Ip;gtKhKzb_7AqVz8Iv6brCOJ*Zy&Fj77z^ITxzcO2NA9?qqELOriGA zLaCbjAsb}`+CNjM{nPPzk!Is8yoUWlo}~uZKhJpWpB_Z#CTKc0!L~EiBO17lI@kG1 zN1eMp9NRyKsQvSZTwjzawd~f}KQkM0TJ!U>>bb-Y_D`8+|0GE2?*G5`Pnn?QdlYIU|y!&j<(;$B63(WAyYClk4xuvZbW9%~$+(~Y0- z2(M>UHIC@9&4Ie{jt;u91bn*jUIt7T*6=8nGwuG!lfUBgP!Q6Tg$KefL9Kx??G9J+ ze0gJkTDVE8)eBeO%($(ra$+B_yF3dI7%oDsvu)vlzYOq*p`F09oxeUjF_plpX(R9! z4e*FOhBwC|y%hj&%()wYHZAIG%bclW%HQ|49htYhHLST zT}ZrRiLQmed922@UsvuqzL;ZinE!9dqLPy!dz!gcYgIy!&uhUuG&=2JmRq?Ci|ct~~0~hyTYN|L&Ps{*Lwq>0w$d7acG#;Wncd&uMfg6fdeYgpqj8NuaG= zOlHo|+Mva4CfK-ikG8jm*GTapJTi0fB&Kr!k1)=!MyR5b0n@ROV8M9f?|bpq$93l4 z2^RgHpf|3wEbH2FojVwkLpmZduG|nAU*5t+*upuJ8{5&-3}6}4hnzDm{DC?51Ot|F z=N7)%m5bcHz7II+nF#mlAz)d@M($q1K>3nB;HY8}-0Tprv~m%)h-HPcnKQY~9H6mF z&2q7-TChCfd#wXZlIwjy#Q>HFjV2~7#|UU`09jSluH}siA-S<+RgIT9lkH_K$3%in z{!$U;%{ z7w2y9sFtjmj04NatKX_3zE@0R-hRU0+{~lF44B*lOcJI8#yR1tTHB;*$noJ&l0*d^!BIQDjnUbdtIMyLxRvvPp?T=)!ODD^jgfB z+?m&)*HXQlr3BI|+0CX9dX+CLl&d(CyGl>5ITooZ2)(K(y{uZB;Pkr6nQX6W^h&l( zrSy_xee~jE{pt0Pj$SFI>(lGlH`k`uZ#$uvSH2p$UthkqJ=Rga`absGFJC>p@)fC* zuLys78TIlNetmkq9fV$;(Z*`Lfw4C=$k?0m-%p#}dkAg*%=u{JWc_KgZO<>8vmOjW z8~lxrsDE+;hL_HxrL6xPwxvz2eLFzzs zb+cFJ7gKvQi7_t5_6Nzk6|dzxxH6L0_U8iaRU^Zr)cFhA^B#Q8lKlLwF+3X0@aSO% z&@L8G+We97E|y0wn){$d`(|M7g8=(<0FMSTB>zDi0|@`eHUhS5Qo8~QwolmytOXN{ zP~p<*fEnG_I){7sYu`R&bt5=5zoU>9EuZ%7Gg@DVYwjW5eT&~7;>MZ#jKa7xnh$Nc z&WE<~Cif6G>V0VQ)?U+xwp{N+)6Vq}AKLQHd}u%H4!(z&`a9@s4{_hjmpNgK@dnQ3 zjD=435T82J?n7Jd^`ZTxr~e)z8gPSqh%=zW9^#Af|Fe6DB{RTp-|Aw&;QLnHUh3$x zIUn-Be-H7oul@Zd`MYm^?`ZgL|GlGOyZwD8gLeD&5C`rKvWGa?pBHa-!i#ltJMvhYZNC|GKAa_sC&1R|nW}zxl#z$0hpN zasQ-tTotwB-qq~5WZMr1RI#dqjhkq@>kCCBbDWQdSzjokYpq3-+0_6RY~LmP5oFg| zK;g9J&#Fdn{DkF-nafrI*JZ`Gq2$Jo}%s1FI{E9r)$d|DbJIO<<~5$=>dGEIS}uI^McA0~!X9R$|f0kG^8R#OFmwQZyiR?ALBtf#P+Qdq?o)#ZJTm^4_W0kBq4 zSjBG=STnMGu)f);h`*(Su6xNU+uznQ)E6*!mf1>g=*avIgPDOOne8NdVV090GHPkC# zf1vVps}I&=I=l=)V0pkFRj*j?!69Dr9Q2bt{`1SL_9Jo^vw*r`OyEADX5noTGdBoxM z9x=V1{CCm&|EAaD^m;7KBc{=Jj?#NS(Cgteg5Q=Peclj&-ySc1^C*73efTju74cij z*S`hn>&gIFbre?dTuQ%WAFMMw6mdK4>t>4I@*VBDr%K z4n>?waeFujtZ@Obo}{o=&8Fk4hYwcO4n>?oVdd*#Z6~m@0$@#~uyUWE<15++Ysn6h zzxK8ua0Udxx!c>n$7%n%`ry1m;h2N;Ej9p7I)$_KF*-j+_~6Xip=dHYgvvxj5WJWG zcxG?^X3+i_eef(4FSNZQoS#&WADph<{!OF(3-!Utqj(wUm z-v+?HsCo$eDHJ~EgP*oT5%2t$N6h+{N6h?}N6hC`F^^Nl5&!atPBV{M2YSTY|K$;L zI91H%RByYFr@&Pu#K$G#lD)wV{W|s^k*dB^?R%@ z7dyK{5i9Bcl`NQkp!v#&(rXWfd=LM|^C-SfGgSf|5g|1qZDS;H<*rrw5_DHjia=ETSwdX zw=3eC^#2Oh_pJ;7)2JYP@=#bDg>_j6>(AR2@lufQZ=h{1?Idk%x;Ew874h%w|C4Q> z#;PJD@yMJ6sG*1dn&(YQn}_IiLJ<6Z%aLy#rr(;x`M&ksc15&s9ot0GHeb;;23?z( z+ZC}3{f~Jzb)PDpp)yuo$~b21SN+!PpYFtKssydpBYx*DdVPq(xRd_R#B?g1pz(2+ zw&!55)o>c7LMRh4fkyWUQ1@8HuJmD$;%PZ;gt$Kqn*BdsWRRSsexTE<3f_ zJ?+ol*{h1*==%27UR7MC>st-u>l?OjjiBqd?ised!gV-2P5WIol=S=GI}~xgPL6&@ zpV!<086VO6wY2>@di{`IYjpj04J7dPV_S;pNSAx5?0&I>&?R5@&B8`S97X@<==wZq zuPPqW{kQB@#rPoO;_sB^nw@!}3IpQ6ED zxkC|4bB55{usc>pP+b||7jhno^b z=f*oB<7*uaf2Q|G-v$}wLFm7h_V-EJ-!(dz>NZ8J3PPhQ+GYxEvr^ZlZJQ#Bx;DE8 z5dM$UeS24La_@W)*gsL&_fXhw9qhx~6!Bz`Hn&h2%A#%h==%TFHd4FR%a_l;qCD#g z_Q5+8akh?U+vu~DNU-@l|7SXTxii`=4MMxVn0BSC!>G~D zw}((dY4@8LRs1J6MfTF})$K%=CTVsBD~x2JA~xWgwE!bR={KJv-@HT1<-bi4H**im z6WaGYVr*t6Cdi&gOou&>soQ;f9-B+!YrPST1q#wlDxw1Ir_sHOqHxSHz#Sv&=E>hMr(K^u|>A z&#G#_sO=*p*tGLC9@SDigXFZ`{iQ16d&R11`AJpdb@b83R@(NPr$tf#E#d=c5fea* zZk^D=7(j~|p4TId zzCADe-b4EL=$=3+Ae5y(->R))86_|u{Kh3)nuE5*T4+e!3sj7Ie2X@xTJ1`aq+@| zxQ?}-<~0!C(u@ZG`b>{p@%Yte>h}-oXM8J@_@`bx+FqOK|1tOO@ljM~JCl%ti!zvkRo3Xj+bz1<4*__H7%w*k%4b=Q`AiM+|IiNL-K2y9=casK)z!KuD}NR#@_{S5-R z-g@CdRnm3e$9xYtl&yk;@1gpKjJ(%3{9c#Xvl_ELGuubenhQNJdcBjnLz-i>{OOmg zjoUX^+iZAk+=_=Ut&Q7ckFAZHs%-w6E^+@gz6b0|UT;LYT;1B zZ?wnKWQy|N7a}qBYK_`z|Hp3Ht=1Yex#50;CVQ|m@2hr$CVNMzS9{x`p?bBwCT)G* zu1Pm{82kMnUQKEpV6^ocxhDx|G?zIf6IwkMF0tQN38bKwjlp4ih{LwhMric^8HY5- zXf=&e;|Q(A@RB7fU$g+wdocJMmZ6;Wx{w;K#KX_yNr$35H#J--4DsAvljm+Vd2WvZH1`hl zujl^6D07d_^N$C$QEM?BJ*YW!oaooqIpl#(plU_B+`l+O?!7Zp);i-wYZEd20+Ya% zGl9sx7%4`5UqLyEvC@St%5H%Ap6uJ@YQYk2vVyBJfi(Ab3gY2DeXnIno+yL6TwRJp zy;_jnEw)b%)7&jzYjC&>EsKo8)_YP)B0KG@vl85t4DLJ;3$ z)>06aQt$^n@iNaHpAG&dTqMgg=F46@MQ!&?$!GMw5JCN6aF@T=rytGrPZkwVg{tdT zxle$J0ndAd?uS4O?Xbwf>j_;@jKuD_gr4vmE2a8!NCovIhY++@ah;{3TEG2;KeYjcNw9*0{DU}jT&`Rg-h!oF&QN` z#&6X@LmpXe@}Wl#vOVm~3u0$pHs=X;rFSLJWd}7W*eQrjo#6N4tJHst(WTybypDn| zSY*^@|95LIxy&&G^9b!N0(uwgdnp?1`=c?s6rIn4gPO$Sg|brfdhfhX?q7VbtX6za z*48bS2RaGWapE9fV(lLvt4n<|fezMG#mN8m7+qpK=_&;Etj}2o4W9Amouk+HO8u0` z?Lu0Z2;gEe0$WS#Lq>gXCNudSBr@aYmAdY#8EeQxUA#UiQdXRgNc9gPk-cYU$+?)l zJB*K)3Vv-JmIoeMzVtp#u;#e;t(vTb5~A&hN` z6WPL50Iu7uhZ|PPmd4~#LZ4r|QoTddea|C8lQrEpCLa9k`xmT)9!EA#kL=yo2Xx;H z@#ZsKcd;>8Umv0|+-LhZvT&d6kF19q{@G?}JdTpWB%-^H>AK_9F@zRe(0u`%p`5_! zic~`iUVcoM+%$3Sg>gU+3#8yL*ObUd6f)?~oQpEJEHM_-)Ux89SI+4P zu*!=o)KiYF8P~42HEzY0a95x1s>Svr;T~wQXg6=!r3B77*4r9`2_QOAQrKbzmy9da zTx36ztKGaMcfGAKk5(V6K$dV>O)c+x;XQ$KMaULTx}mNi*aIzIC2%f`z*mhd;jiX_ zd^!o}ZtOg8I00N$@kwHMa=`)rc6Ws zT^M3=Kty-(TK(e)J&!GlHNjmz`5=hPk+t#3$3T{`Q(bNYx(19oFI64vjCUxjIW3pT z{flpt)rwo?3(Ibi2OecILaD5m8Z`pPy%mu%28^1M*sLwTMj*7_>}yQ|P*;Z$BTU~I zy>8%C=$Ic{Gtf>z1aQx{jw!x;-N3($s2g}Ih*c#+bpyA@)D3)Nl36!!1Cpz3Lv;f? zR-pQ(4TlOVPlCAZB#4z8HWYq&Hgd)Kft#j{s2@0y(8;Dua*(g@vh`nu0a`=e4DQq6G&(631D|u%2zb(&v(f*&wGppYF|0mBJ zzRcW*%QLh8EqSK3{XdguN=BJ`be`MWN0(=Q(az+V1i!W}MIKmYm(_|?xqoq*+7|9 zwkvl=bm^@fPs_Ss2}1(7*gV)A&QAx*=i&LELNda$nmQ;3zIFuXOHR+(P zJN|Uu`2X5=O?q3`9gMb~!F5)zZ4p0Jheg%CxCAyB6L>*`0j`^&dx`ygtj9qKRemG zBk|ySB;I_c>n^8xb~dAAvo@Vz)}}ku@IkB4*p6)c?3@Z-rq(xD(DMzadQi*p1X%U( zJ+GWQ?bw>JavE@Xb>aHt#$DemmLJ&w1WpaDg0 zpr~U$-~aPs_P-U*Za}O*XWn`2%nM9Q$>mi< zEr;#{+FyEe!PhliYTEH5*$I|#a4Ar?6I{VgEK(=X^d(5F5=e{H17iP9X!{wz3lbV! z#_n%s?XQY4a$qsgUvnp(D&kMVn^97@L(^Sb<6$3@&3=fJ!uTd|9Ybm0*oD|+s2(D8&Q(@oO^u)RCRydo5z_n?`%BPO}pXbUeP}0h7$JPwiZpQ`P zwdq3QoNRtJIP?6v?r8To^4mQb`GFS+tz_rW7N9?QSCe`@=AHYe!)3?eHGb`v)cAe! zUGvWEA+-0WKv%!3NpE@X&3`KaX0JX3Vm0F>r*zk10Q*Ipp;VW`z76@{ime5&E+f?I z8K2K&>ew3ae@HcBkp$B6Hoigjdd72}6~%G)GF0zeIWNDd6!}kdV$t%rE~zu_kiDL} z^1~H`HsQ|-7a-QRBY)v4qIx}dtIH8k8Q-t2SOuz*E%?2jNh&*EWSpUrnwmnd2^(@= zZ)NAT`>(q1rgt@|JEA+(9@N72@OSSyajyS9Lffn7$nDsn2G;@AyKq5T9Qck4lfss7 zg6nWXTAiKOlC>*MsS)XflTZtGm$Q4zG_cn-;W@n4wii3pKqjGGI92h?gL;Znl~S9gJ8K)-N!nPO zA_S{)kR>k^(KaaEkCVHnkC&J9>1VQjbgjtv=NFw=+z{t3-;wDqU;A^YXYg01 zuNsQ`U1rApE-a@1g*G$NbhsPsr__%>2-fGTAMphKn?i0lDWFaaze#*_j{eK`oYn(k;vH zdF5QjdTV0^o)orZgDW>RA~C#jIodN(F2k0_;8vgk2caiS-EONQBKQ0pD^NRt{mn&23@_U+Jcc)k&|qnN zfh}5_#c9Nirp6ok@VL~7%A!GQlJy4w+s8*t8b9oJ>$6!(~GC5V0V{) z#`t%p-rA|$X?F`)w=`yO?bYnOrIxvO?@fb-$?_ycU>W4@&riL&RrYP&vHZud-5D>RUsaATp2C#zmOL9IYQ6*d>_ zEy6uKF9chR;Y_wE(M9;y*6@K>@_M%hdy##B~SxRceg~Oz&Jt^rbHxU>Yi_l`OEkv_t&!+Jafz2 znpAAQFEao3cLHU1rD%J0Ufv_<9OtzO2F{;*d&qaVzwy%V7qIW~%>`xg1|HYGtw~Ye z{I8jRTRmxNY&#}*%@cIVIrx5}I;cPQfPa=SoTmSa!MzLn*?3-@sYZQ96V1O#G4l~E zy41?^J%InuiMkXhC3N0J#&fV(a8c)eO~>MNsVQ6VZ@v-g#{<~eS(y|Avm9i=?AEt6 zDZ%WU{S`*6p?-}n1s4-q#pI>Mgx>hJp@%!ZO_TJ_IDaTR`4Mg17iVS%*eJ@P{Ndp5GRJLy-v=24Yd^T?eC zF7{sey76AQZnser=@H}ok{^Mq#ztgMpT2kL-mAG?WPd04$zEMjcCMFK3Z%u0AIN9t zcCuD{tO{*x*oZbY6lKBLsrP}a=qfl%7K5uO9nRL=2QDijZ7W`Qq1<96YZqSE{8$mP zt$gqF^W}gRJY93IF&6IEk1mayAO<`ju0Eu5|AqTgBGPgUM|06lV$eeh*jdt@QleS` zXy{iZvSlh1*j@tF`gO$f_gel7=4N5A+s1DG!(oBYh1cyq_nwWkt=RMXbKSd6^V*6z z&%aP!mE8OoTW8jCW9-g8{mjzfBr%YU#8U@#i9PFL&kkGod|vk;|C@){`Ej3`BY-c~ zKjz@Chx|#ro_p1HoT&x@d?D;q6nw8*u{KxDjW=?Ju)A`*CsPfk5UQszT;8jCO@EqS zv3{~k$$!8<6eTpuzGw+j7PJ5jnjp{|nXkesnX>3-vF76 z2iGUyE4&?|z4uL`+D;!iw{XuXj_0c6 z&3_2qzUQ3x)bG!ElfODQ6_s6>nhdVIF)#dKSMrOzUH7i$b2A<`+U7m~;kmkh9yzxn z`SiJ6*Pc4JFf>k#*3~?*`0{XjBw3fpO(xttAl`eGE`ilu-aIiPv9)l$Jdd-UA%-#u z|7Hf7mv5Lm^6b z&$ke0V{yAO5@=bD}d!6K!==z# zd2ao&KI~KmCPcVzO=bVH$NI2cQ70I=PdANCsmrva)ETy5yTa!Br(5AbA5K&5%?7bx z2Z;SRRVl)g!cA%5%E>l#yW4IAR|U3(-2kqfBtpwD(3=75_aOU`w<4umf(am6we`oW zh0rQTN{$sFOE{;dwjuP@`j&RV8n(i~%ad=|*f1G^uU21wEaxU@y?||syJ!6||AdIt zjWd*}y)q-&QOCxpK=v>j2N1XxWPv{i*^fB4#h;yqz!k(cC5$r^2bcM5N-xe(Y{`@B zsxY)p;W9vK-Dzx7Y-iWMyfO>?4C;`k=hpDJqmeYT|t*}_&(U(UQ? zW5Z_vzAF9MV~1~m*2?qG9;=-Yk)rTPwWQV^7gEAZ)^*$h2hL-QG8KdCy@?D)DMy_9 z;A|&f+azOc6O6TSJ0@GhI6{LsO|gDZae&GE@`ug?Y<-!Q%(|%W#DxQz)Pqx%Zai7( z!wzMwnPZQ&W#9Eg^j1~Z9Tu(R*z?8Ux5k6`K?(TtPOpENeOK1^?6H4x99fPW7A!}$ z)l@fsm<9gk8t~WD6g59z1O6ZCdTXnYRLA;cYp=PeyN>fdO9%VRJN@j-WoOq9_T@#E zBhAI&=lxB%w7=VNQXT6n>zwYY*L4Tm3q9DWT){TrQhWV+o=3^{ z98sMpBb@gfaM}ww48If=JC$DxDdG0&`Eom+qE^O(>*=f6yfYMid_*eKOSUkXa$$-& zZws4uit?3%v{kHvvrYIabr+tZ8goxkLO5NSfm34UUUKZ~=G-6Qb6@}Ra*oR+r7Al2 ztV`#f8$0(~$N?ux4d>kgoUUZgRs7Dt=0LGi=|V8^ga<@k!vLo#vz~zZwP3_y+5yypP-5#{Gm`2kG|OeeH*BD8LS(Rs9|S(m~)OXPmW&po7o$)DXb zfreKnsI>rgCfhDNwYl7K13A#W*^q5FHa}mU`}^j{xO|Jj)K{h%?G6f1U-jaKKUhfRl*4`AbL?5p{U4pHJ@e(cV2UBTWnidh zvZ9q#PI+{^DKDaUWBzfVSuLPh%ryiPU~WDPoq1>9`rn;-U2hp@p6-Eyhx+uRCA~Am zE)R(I4g;S2yia^u-oRwGPsj0hf|q-gnRt?B>S8t_F#R%R!EfCwliSO^TlV-7^Wz!B7xheXBZW9FsrpQ}a?l zov{<-s64apt~dofA9fAudqGtZ{ykXKJ3i<#KyC8Ut4>tCSA+!&f|by*AtN#kDaE#9cJ4uvu#RDTL#B*0QNC4IvgA0(E#?_ z2fs^GK7Lb^;sNY9Mu)@RasHHI?Bibm*lz-`v-?XSfc^XCHw?G=QCwPJ6`E+kJ0k|( zaVETr`}8we_EZk<3;(1#yR=&n?@|}4D;OsF|c^R+?(w8r{-DulQ%U9$2@1Sta($D%7){Z z?}K%34%X?In_!3o>B-LlZCTS>HIIvt!nWe43PR zj?LzqXTBSPfkS!lO~bG6>+w3*yZu#Up8<`zg(ZhBLbdXXVpFqrQhhmD-D^WcGm>s~*JSV`afWxST!2TcUyEj_glF+a3jmj_Iunff~-ESW~ zJ}J;=#3${t4#g)OG~<)*+;8x`8~2akOW7cPBf3wrjeT-qw;8W-W{$z%KN{L2p8Y1@ zi-T3gW{gt){-J$1ZIu2ejp(24Lt-)W{sfINP97N=W5xdAaY}tLF(HRqhxTEQNvDhV zYf}6EOXHMc+xbRmw_v{}?b~n20*ij3Nz=|mMvWhf#lwe*LwNWi?aFvqFbW<{w-|W% zwB=GbeRz5}oPKWNA?phRMu!d!!6<7KJp8d`2oD{j^#A7ROY!ixMDzUl+!$kf`_LGc zE8wAW6nOTvXwn1!0uSY*wEMC}lkPO}aJEsCI==eXcz8Gl4>vomjE65Rm*Sz$#KRM# z!0F);aGGP{;l!T|7;SiS2uAHKm*Qbf3?3dFrGM8bczDLdL-A2#jED9QjqygypLn1qK$@=Xe?Qc8B3PiG89XeV!~}3lc&`p4lC<0SQ&iv1`}2%erxh4<*$Rev+ipd z9#0m#=Ka1)(VKXXk)TFGhA`9%T!XZ9K+sRbd$*LzGVP&d7sIIe&44#M#k8U{GR*4 zk0tb8pFuy-n7Z$bXqz{cwDn+%QZd1Zoei&;lzt|%8-f5LJjKm@kc>GNu5vbDww8;*xXiQ}ppzzg`hU;(pFjgk5w>C04?SVlQ>;Ll%-4_x`4rpvJ9|9P^V>n}#p#MJq=m@@wjUhI>*IA^ zpGn0?*|tk(vP_<(5GFcN+^UBJa5=Asvm_2&&gpP=+jwxTXny_=IhfGANB5k|%_ari z;SbKezuC0AjdL5e#c|-u0e3kY+bcl9NnLkr6;i^Ui@NI-Ve%1g0_?kb0=Sk7laIv4 zwb(#?+0bpCd3n+e8ykKu7&7Uix~;bj=j3_GFPboBFwFeE0o!Oi{M-9AsSgu6fHM_Y*B!Oke#8o?b(VM#bK}9E zhb(m!$Qmxwbl1iN@aG^)ofBEZhX-_5Ee4)Ped&PiYTp279|CX%u~T7ksJDCF%dDT= zV(@P&0e=`(3DZT+a)ZBl5ZR zFV~^TN4l}~ND?H~)eF`m7GyoLG7J3AXMx}ST*ZJT3-(n$=Nw>bY!|HI4pn!p!?wD1 zU3aX*mLv6o<;XkSS9yWlzqm|RD{hl7EW1@6c=Q%oTX(apdxSyV#KFC0Om3->%ljmr zq`Y6POO@;%{tH3$E(QOIQV?r@X54qTEd?I;e>7~|!Zo6$xfg-|A!Ei!dF?0vtHJ7*4ich`R7UXuV| z?>GIs|Gw9FhRkR00QeZ58Ez-X11;q;LYfkMmC5N>@@Y=;=Ui>XTiDL*EdTp$(Duch zK)a?Ju@@(10tJ9(+f-<)d=*^Xo$+GG6DKZ2q-Dl75OWb}8Q^>T29Zza(4<)c0UZxB((cWp+$N1)pPX;Fv0RQBFDyY6d`+fK|Q#v@$T}PY1YO- zc7k|gvM#Z;1!oX?qVBu0UhRvYK_w_{Z_c?&Fb{3Sp$%!V1mn4Df zj{>1{lEBCAhfb6kMi^Z0m5_q>$BwK$=m>9%=&tuC5_;rT5ZUuew5ega0CWF@4IAeB zg0-%0#q#`xw~&Ggl(aHS(_K+}W|pqIQUL619o7Neu8X?MYW;IV&bIW%&vo4) zA@CV~uMVXTXDAnNvhvLbQ2iv3yNuQ5%_ZA;po8agm%v( zH1sHGyvK7HZhWDohurvB<$5*NC zotgRV)wASwoT{=r^XnM6v(O!2w-*JLzd&V`X6a0@j1)TS%=`QLoU z$f0(a*FwKrbuxKX*Bwos@ktr?wP=K%k~z-Uv~Qr>~Bh3Bex%$kniC{p0d({G9{A>0{*X z>&MEcdY~8XIFG5MYrqV)`#AA%uxw(|b{=V0+Lbf)Bt|!#GHct&^66#zJ zGN%*$2Du6Usj$6zuH5dKs0KVQ7QVg%`vawfa$FXI_^q#WsTJR&K0Xdwo3Kl5$94{% z-|y3;XzbN{`*j)> zqKNwSm$Jr>7Y`w0FU{Nx^y?xm@t?4_mFXgwsCX^*%^eRZEEMdxyA zF`-F#Xg)P)V}pP;HB^mZ=h`HNwe4vn^cVu)iZ_bohj|PuDHyd)>QEa-t6L&^YtOI# z&9>>6wjB*#Poj+tnP^jkkvk+)IT4OXubBBgQ*GdDim9QQ4%bX6N`$jz0=T>h;7>#L zO?ES<$anWK86-vNIivf$+eyKGf$QMrG)*D&?tPl%Eg=PbA5A3mTlo@t=bH;7FeoT z3+$7IoNcL%PLvith{3g@gcK|vOK6!{Ys!i?HWZ=E@DfdTt(-{c@>@Y<&!?ighD`|O zuA2hBZtPHE>(-)C>ehw;?3q`w^T5I5Aokve>N_szv%3K7km4@?u{9zEI|*gyb)ceS zK0CWZMTA<$0}U=MUfX>ep%CYu-!%Ou`E(Cyv)l!13F??%fq*Ws5?Y~w9Gvkj8Is-e z!!y6lb3|CD#>wm+Wy=9NW8ZV~wG*K2_XvC|~#tV+L_gUA@P=nVS`#AU_ zp`qy@20R}XI`0D6QU1spBoRZcC$7tqm}kiYQricYQs8eHZ}wkjM}h^!CjsRVAlmpcM}+QrDswj z(s>LDqfcE(4ZnxM6^yJumNU($shi7SjX`l^9xu#wzAbw-iOKa+BG8SP(4w_DDqE8- zSh(*}u*j%Ix6ul|fUxYfy!cCFJIgS*!U^DKyfG8NUSa_kgArRFgG+4P*{+G;Y8s{P zY|g|h*PY$Od9K6cxqoU{Av+rDFrlZ42z_{Mo;m{&x-t%YrxL(F0l@x4L}>Hb^~bJ5 zKwrRwez^P*^+QDH56%BSSpJB*3jqydt8yCKln_o*Rw6>X@fc->V8oYR8dvHt<4XV3 z@IkAC$CXZv=q}dZM{6HZA05zJ-&=dFdYb!dIFu+}8NL`VVEAJDncbz>-e!9?c3)f9 zKB0Q?gX%^AUmoJ}Ca?LoF^SM_jt2urwMjtp*3MCRT|flB+;~D2K9-G-m5XeAzD4F< z&$E8gu;7=ejhir`3&vRMa*#p849~UWfHIkCmmZONf5rJ)YhWj#`c8vB^7d*{ZzG{= z;-EFKg;0Hq@%(D`d=a6sva@rqCIvnk%5#>vHzv>7?+Dd@2NbsHzSO;%l%TQuu3eeP z`oSs6>H*zXTS5x92!xjDiF4c&2~FCoN#}LrJB#^U&&5l>L*{qy*t!2;`1}TU1Ec?G z2waY!-pc5Gt4Z(uzv8)Fl&y(Cf3E8ewpV_p>yB8Nvk1Ye&|*R@n9vfusUZu!(qNfj zoEQAu4&;dcgN$=-zpgvj9W$rdv`=H~=d$VlOc$pF&HE(AJYKah7~y&~uIK;0sb5b1 z>v(pbT-B^eYs~r^sm&VKd9c2??r(Cgm^7@fbS0PfmCpNGvedkv+Kj#)Y}R-!Zq}C& z?P~}2bDite38MO?+1C!Eue6xH&=S-BkZAOEd$T5e8-e`?;Rw%D+>a5jx78Q5vn?fb z+pjc4f|Uc{myeY|E?BbE_=QR!R(&_*qI!; z$!xP9V6JGk>*skfj2!usn~mJVvE#+|^Am3KyGMO0rk|Qo`mr?|xu!?Vdu|GX*;ccU zWxvv-EdX=l&F}h5J@LieM&Imi{HU4lqsaq)_Dw#5`b9C{AGg7(6I?Hzs_fZq=p`7Q ze!hDMPbV18!79Em0#7G#s`4h%hw$z&_3sxx=eP>&)}*cxFdeoAPq{j0)HS3l@9);6 zZ#Elt#y)c%?0vHu;W-X}{Wl}#z%$^|``}Ce68M}LrCIvik;`N{C((wdXm6c-Pu4uP$KV*BJ>jq-# zeAXgp<+-^Q5&F#Q!}SY)++*k$f`j@6pk-!FQ?DVz?~UGhza9^+TEU2MwOEauZA?ZD zR3~3Su1}KLe81=v#3g!U1 za{XQ=*L!T{9ob{XM>P_Y4ANdd643 zz@S8VYV=;#h3#A(e`&XIwk(e@-k+*`v1@3be7H;FcTj5P8vgWY-QCfT5j(3hjrbdmnK~?X8#Yth{WK<+Ls{% zX5ZPPNsL}u-*Eu;_kzRo1l?`YRg_*9GJ45Q5GQF7zR%t@zYpNatW7kWI@*_En%648C`?I6A)5V})~NbH=om}hLx9!=`w z`qtrg`dC{AJM*0YTxVb*q#y_|t8zPt^;(4I=!xbAO5HQuCNg1<=7_aRjJB54WI|gJ z_|{A`@<%W^DgfZB-)`iBIIBe@_KeA_m17Bgd?L_`&6@PMKxnD}zBLJ>x9f^+ClLC0 z0u0L;)ZMI&vgYCQvs99TG680Bm;<4`$hd<=OL7Pc1! zjMotQra5l3zn#sR!^qhdlc&vt#9lK;)zmm1pR%`PYMl5`w=PBZPK}MoOZ)UQOUFCJ zrXAqF!>3Dur6BIu0siRT|K2%W3N9rDp_CzBx&Uo#kOgQBWfHnvFl=f82cge3Yf_Wv z!9g8UO>?Y{=>fIfa~0R2tYb2nnX5}%ck5t&F2+aRQ4HJa67H*L5d#>+mcN^}RczQ+ zkN(}%|4%aItM<VtDS3Rd_e9h@$eXyBYce=3wz54}J<*VV=QL|l)ihF2C0v>>i_PP@ zW`h?z9?^ZZ+eyJIrk=t*h0y8E8s`azBL+{%ZZ`B3Y`?|!byc(G;Pb9YTrHArukC)YMZVP`zEgWU*vJ=95c-35yqgL!k~OH9cWh~<~q@ntATQx z$L0-%0MHC>Pob?0+T3HFD?Bw5C`@wC4-^5l{RrCJ_aIlu6EF5)r;@u3#Besy&|;vW z&IE2B3C#s6mtub&A}!sCK=ZOd%smKV_kBP^r9eYn7UR1|+5d53UNMN>DM0gT%B0}?OkeGV{#BK-BP!iB&#y6aXU8LuFqh`0|YeZh1027AWMpD8H?n2x)vV_}4 z62+c)(>Ai0&=Ym{%X)RDtaruQMv|I?9@G}xh1!}*vA?uWKf3genPSiNK-X_$vdgW; zS=2@7&fS{SgpU=ziCt>oQ6{_GTF~DG^!#ytH+?K!D?S#SOXw^tHJsq_1gI^A*L+S< zQof8x!6HI4;tBoBSnv_N?6tla+sI_NX3Ew?GfzSy_%l%|w~bun{4#^zW4*S&G-Q5~ z(a8ESY$NNqZDbN6G(Q=9cO-(pzdF`7lF4l&lQ5zAN#L_2GWjHx+eWOVq`)?Aq;15` zZ6mf6LX&PAZX2=38MYA{w$`n@f^CG|*V#G@+en6K8~IB^&bAD08~K>qMhw4=ew?mQ z>`>0*WTpE%sQwiH&7P$x{ndmL(?;@L!$!ho#GGzJMhxNNLEFgg5V(34Ic0{wFFF%N z&eNW;iW^MZNc&Hr-isIID?3*Y$$g2V%YD4Q{ZWS~^y@E`Jd-bWjfv`W7n%B8m-;m> zqug3>{xp3RId;Fif${&nGsRA>r%&PWi31lR5=;VLd-Y7Y9oyBWrO5w! zsgcWw!GXs-j0dsvh%W7~ds>cu7uaDHe_4wC|M0}~T*_UUOm1}MeL0=bxBs9^jGo)8 z3*>g3p$_()E%3f~u=D2kdE!6z>C*nso|LPFv~Wi`M`C>z(0XfQQz!Djaa8B} z1;(@Mw}Z&eLXre7Bj=J`$%@w{2H$O6*#C`R>XLWoTAq*hB(DL!=)gbk<9nd(Ju9Id zsAIl$3{a?X7s~h^wH>Fb$2E|TBcRp^Ko!qDsx1|0H?}Cd@ORX9PpW$R7_9F0d`G<_ z9%wUOeBfIXpl!DRzT{LwSH=^%IUf95(U|Tm1g>2uX;TuDRXdS?TPgPc`KT_n;_s-h z#6fE^*Jmd4{ql(Q_YJ$6lNUMEhHq;tKWFb!+dbperheVGZI>qP*9}?yH7=_=l*O8%=YA_j z&n@j5uIJve%Q!z^oV#3zi%7xgMrtBQfglmqIR&(Di2o9G+>8Qe96+=c}}8UKP8 zHxy1C_go?4-Ig+FV?5jPBWMehT16vve5R=F)urIvV%on5==mAN^uqPU)S63V9;-D8 zT)L1EE}jG~dB$4)?8H;x;yDqpLuv6EastCW-&dA7qPNSeU08~F?ZV%78Tm1}{^U=_ zedFZ%&&M-4;i6ZQzGemczoPxPBf8WYOZ%m%xr%S*7>`A!-M`=G} zRNDXYBVFpj8JzZ4ZwIk@811Jh55*19{;Jpi-=h7DqdL#gQU4#%KKtH2g7(iS!)gDN zGDQ1KrVlDHwdrGM|D+P7eY=H*+Gnzp6eBx*stlK%K2{9c5B&6gBR;4QM2y_! z7X~7d`w7FQ`Tazl>+4Tqq!dkpvr#-xeF9t+li}>tC&4xCDQM;Of1`BTh5fwF<~PQO zk&_W=4x`g9gH9*M(CNX02AyuN`h0vpcIMsf)ueS6u(Q1os07#HlOWQiR{6qhK!fvu z9^Qb&;0&NVhJHJU?7PYea5ZsSb|`gL;3-PHZ@eDjSXY|Zro=}*tzi(<}heVTrD3Mhz#ZD_gKVt#v1wgbqAt)3Zi-@ zq9?j6;>j+H7+6f`wIAqG=utwuyUGea&LA`g5t_S-sNKh)P0vO&n1pDs)FSFmM6Ihp z4Nfnn`gFu|-F+MfKKCd#2_}ndOaT8(Qx@ql?{18~WZTCLGe5C6S}~#X)~;6H7Qn~8 zWq139$hxTlrG$|Ht`$7~H#JNqfomNmbR7cUibUgCG+HPASUqu@O#p4Cd8>o!gwM zBI}Qp9X4XPpBD_96JSCurVc(;F>Fr9GJslRY);ito721@n^WZ#Y)&gj*qj)g*!mcJ zVr@>P1YD!yx9G|?r#=LBhDXEZbgW^8oYI(t2|YD$xXtO|QEX0QN7$Uk{;zFLDW=Wo zSi=XcDT6krv7^|WnEVpOE5la`O64{uMzaqAxETFn0K3=raYKqpyE$uDtF>U%a9xg# z9A4e?2rWZ|-iLrzVW4?yXR1}0(8CCP>~6V{k74CwSdi7UE89)G^2ZH1+swYlSn4tn zP=*(V-^0^@R&|nszKUe|Fu?2}&Quueo$EKqmKvvOErx==lwx}ENuWVTF>Mzt;b1jT z$Oc#NNkTK1fS7@hcwwF4E9OohboHr-RBJPBSvH`-YC_i?0ER9Ee6`^a0^gE}hMx0# zi%>m5Fsl-&bE~EiS~eMcBj>yAg6{ehz+Qyy;gb>F<-&ye_?(UNIXXw50KVD{q@eC6 zAZ}Dj2IcxRw6S3c+SI`2b%>2`#!cO5&Kn~79L)Pq3wt%)H3$PuZ><(Gc)tIt4WwY@ zPe5EA)34p^cW_;1zgI{59iy84+QZwE!3Bx#^3BNL4R$w(MWwK>WGA?a%v_2&>zs?8 z`3ZT8#|f;ll!HS-U}yt0n^Xc{Fk^rz_GTRKIm)L4H5ZP!?c9 zgE&J8#e;99QX)Uh`y7f*`Z?Ov;6QZ^T-PcX`2se^fv+E1m7M25%&j2>@9!xY%pG_m z+SD)^)iqRLNBDa)rG|85tkcNFm#zfMQGEx%tN^HUPU*UXor9&C?y`Y#c6JTuuGqPL zUT(n04eDG6fSvWboyV-FDb~$Ieea^)+WRD-)z5IrLGl70ei-EtQmy9<27_Dzvgm5nzG`J5_#na*sMVt z8`99G2C%xzry+w+Gkgu;OvSkwtM)(NBs=4Qvc1XnzZal&8XF6<^JuaX#NczJ5;}k_ z+-F<;=Fb}P5%^wBF?63NIo#5f#u%8L<$J~v?lNJ9k~lNB|hJ1So& zRXj?cMZn$4htUMqmfPa?hx7o}6HVqs5@}y51 zW}QxL%*BM}u3e+b0{9eD9$1NNo2rqW%L6m4gjS=>FeHJC;}?N%M!fMXRvxHEsazg- z*!oFBU301-4i*JB5F=Nh@lEX4?afT zO|FCjJqdB26x-E;T)hfZCNGTiNBLUPf9{WBui4m8Ysv;LQ#RN-C>z+7Pm_(@Eexhx zh19UjpBs2C|9eFG27vu!Jh%?eF?>bXd}Gh;rE#PCig@vr&+Rk-d+-=(%dx7=@gtt-~Y!;UifdCO>mowtlW7*DK9`lP{b(nikOHACmEV4k-# zjPrI8GW5H7YiFrd!q9mu^D#!Ax5NFoa?SIW@eT%0e%{Uj8b~ST>pHMg(W_Rb%ykh$PLm)QcKNsrr5N*Tv zs`^|+gVQI--Sz4+K1w57p;>KoV@!R{Q96NXMv#h_$dOX!6g z483BMUdF&RQ`+N)bc&PFB-7t|lH$aMPSKL|mxjqFG8%(3hy1O**MqNT9ncg+=*;WE z7bxwRPgep}tAVn9(hDbjdlLNMwcwLR?m_M+d#z#f301Q@j+N(fjE)_8lJypz_kY4 z;?_?x8iUz{hCE=>@p9FY2)^DhwDsatB^42RPXhQ@AHkId-L?vZw#I|cYx;{eA#g>< z3az|6&4xS%jUU9|Qc6gHdRa zttmkTfuEK&>(vwFY7OLS1hjI)hQjLafLv=Objb!!;esqew_1U^QOEqP>p`xX1GIPn zd6%8nl^dQbjQWjwJyY^C5co>)(E0phc7Mwzw9iB6E9_o6&N!le(p{JsA0)kF9C=?LsX9=KS)Y`r;Igk~)makno4S1ivTl+}u_ zEF;7VU{|XNr7H>TVRV%2E?*Kc{Y)4gIS6gXSLL^67s{VqhK{zHd9G`pb}nkV6-2K| zM_Wr^-?UP2)s7vaqlG3N`8FWgYXiC=!Ke@UUw5H;w!XIOfJW)3{UMN>Hf$)&nN8@n z4W2@F{&c4pXL{Bu@@~_H9~V}v2e}&$`5ISfAXji-#u0%unpt{THgM<l!F*Pm@H~#auB|Mm@hJutHTa3qBxi50a^hI9C#~bO3oMHMR|D|EUFO6{)q9K1|hBJmQhX0(|Kzm*!^wqF&wZ_Wr8R3TzxQ?CDTbaxTi0hO&UFolD(go~P7+pHA1$s!=9o*)8EurnY?qGKm zs_BjpE^Z5~CY1a6&LwmjmKrQTXcqbz_w)7i=|`8olq<#whVAqH(Quzl=&7XtM{u8g zdEB!zBNqRuDAnjIMs`U3B%_hZZ`QSst6t9om-wG|ClQWohV$hDqYrjRnLW(^{NKU( z3Sl_Dd$3bEkDUtR>m2V{K+SqAa{{{vt$SUQdbbd|27xbH&*MDzS8^yX_eCW3%#cg% zO0NX8`gKiOjldU`O*aY=DFCC(rjDeD#N(wF7_}uV@o**@JGGm~PTeO5J8vxr&mG0b z5+fQ+M3mdxu|?!DP#@=tCD^dHcU52B-pL7c!(*UWJ01r$TANg(&0zf0M}(#b|7P3tQQF4CpszpM zlNqmT5}Qv7hStD-LiPQ|bNlPsFyE5#uWM4^tD)F|s z&HEoaVt7nC&|H(pubibK8)Oj_2jF%n?&RA8w%z4~}WdLDs2Cm|wjLSScn z+6iD^4q)#CuxA0-&vSp*MbR4mb6WvsS-8KeOWn6alUkXKgC{9*$oMwuw|4V3hKET? zB-)3WkDm3BhG6zh+^_s@wP}YY{S094jWE3ZtZkY!JI3FQz55G-`tQVir`urFi8MoJ z6lxmEe{!s8$o9_nSRsh-eP+VTw7s9icI9kej9v3J17;^{447qZ)1+I_rRz@{^!IhC ztIWB_kC=P>HcfhDoA&=v_xEv8UDv`mzV_MkjxXrUFuWyzqzPc!L_u*9=CT3JHJWNA zC$&wQfck4iP4t?Vw#HZnXc`brJP|YLm=-W?!#TOM){Jerz4sCId3sIkODH$?C4GL5 zXnO}INhJ!*R)+ok?0wF_K#Xahd%vI0^Zg6voU`{{d+oK>UVH8J64(deY6fu4PI}M# zT0TeT&vmcH1J5PBOa7m?YfGxb%b&lFpzS6A*R#{sr7KPE?+Ab^xsOf&*V9SAUrqY| z`v9(IlHsm0DPKU)b_l@rRRGsh)85^LpzUB%&4Ai`LizjG5VX~u6h68owN66!i#ows zTG6ZVz;>gLy7fslKGO)ze^uwvyjSCak^2eVGEwsYi+L7a84r|CTj$Oh`Z{k*TIVlz zO!7q@=ZmjnW%av;kHz`Pb^cn?Iybzauk)eD-xYoqogMMO>Fdy_dm{E>O>Fc~JaFJT z>)gu6@6c_8iRVj_{!f1Hoi@iym&XI?N$->U=JU~p#sdkv!S4>m105$(pY$dRgzu=J zU;gcQz-`s-2%JaUNo{YN*3ZjBP;^MA6@mu6y=_frx z*47Yu^iVvIunQhJG}SKnLk?pV?t5lvJP@9*f1@7K^GtYuJ05tWX>BZ#OYT);KEFQ2 z0^z$W=mPQn!HM?=dAlaF5<|+e5 z?8FDVZn&o(p5{Zh&)Cxsi#+sL`6qDP&Cdw?BvWF#wNV}r}2RHr}2P8-#mkQw@Lq zv}u0%hCh1do;LkFnwZzhD~=@ILp)+0jq({}+DDy+(Y)JVO6>XFTwf!(6iC!=(8+ z2z_c6(BE{%#h7ovXkwMDvrK9`pd zcg6!x-c0C!@aJiS)~5lj#Z%W%?$l#%sylUmd-pgCHLutG?L}N`8lfvYC*xn28{Zv> zvygutq5QjlVJy&mf_QC=mH6ip`UA#3CPwF&fESRz`WxSk2bxXrc7qAtZZyH$ww7ho zRsjMhd3%=8O4~B}>+i+`xuq{uhkxftKBSI1fsU-js>sDx1xf)Bac^^3f}{34;&s>wb-M|@AKBkpBths3 zM%qX|C|q|Ky}u;2YX#wFz6C@AIr4N}tg{l7pUei@v4P{O{LE2_P$xLwdS{#+<#NJ_ zfa<)qR2^AcrN(zwsH4uwe16|&EFix-9=QMAM6N)j#%d(>dN3AaIGQ$xP-h)Cx45ufy3TIR)OF2;Tbq$G{q^ zsTA-gV11ggK;gUNfdURI=CEQleiD>0wrQsTLXi=+4=%tq^!~Cq0Cb~Nh)+EG!?Ji7 zL-#o+#Lr<+zOoXvi5mD=@7u}yY%=x5cg|49wgA1lah4jZnXQhjO;xX~o}(!UH!1|moJUNtHa`cpH6&Q*el{TcXRJaF;0N;R^9c(1-o#2!D4 zi5KCPAg57&-VHY)rC=p$>l&}IRcd_aed^d2LRpiZm;J~e#{)n9Bd0^$7vE`D zNAKsnlA>N&JwuIGNk-h3P2+gudrkuX9QS+;S|kIP?=OolaudpN$#MFC1fic)K_92n z-&IcX5X=C1(BPpF47BS!^l{vZ+{7nA={yg8e_DasI8Qw_&WR+uuZNdj6k9eCcP!h=} zJvkMy{Tu>0(Le7Ses$cJN0-Grn!Z!U`&-A)mcJ~X=xZMGSO3cj)Rqt6Dlx<1<`osx zW=hg8&9HqB2DyUkc?I*7j`Ps>y(;J%u=%Uc;~ecMhi50Wbv1oy$?Fn1qTRM@LT5~_ zEt<#2{d&0~{C_XprR0LY8s{f!i+;)QMSeK;W_vu4h)LVCg0K61>d4xaYJBIt>gfGk z_F%Ez-x_BD-cHm|HroD6yS|Uz@khNT-(};hF#nG_e?}gHxZu%kGu4md(Hrq+XH!m0 z_~XyHC(h*>r;o^dh^NmX^y@YVMVgS(a}xS85jn!?<)H;7sbyw3>@vgK4-B(?M~mhu zi-+0UXPz!s0>kXm=wI$qQaBG-Nq59as5G0r=cyo73CAC&%>wXON1PC6^%j*mtuapfxpY}PauRu2InZzw#FJ^2=mdjK_8|SAC(JZ+deB~L*yY6PsoOAaTefkCTNAjdWS(P-}}Q2o zYKixP)uax*AgRkAgGHxYq$h?g+7)aTK4msDY(M3Ko;(C{N^CqJVzIy$)wY0abCMqW z2I94Opl8z-SQNR9P!!C(Elur*5} z4=u+f$D{qyYt{9c!k@<51>mZ`3wksFmre3lx9fR;>18WW_p>B+OtM95-5_7XHm%eQ z`y#JZs+ndu+&0V(w>fT7UgGrmKYU6Kf}yUH(05A)xtfm15$b8rG>N!vo0fyJqQnXE zzs@C;0xafmu)BeVo22f@iVC_M!O{5uu0ao>tlq3fvIrf_x2PQc$P>`Rzo|1pX!!=6 z9%q<9-hEqz+Iky^dMM5L#QQyr`h>k$E>s4L*skekST(;)t$JFoAELcBRqpUHOcONg z5^=X1Oo_AUWc`rt@5TfE+X(GN5Q;oOdYUnm@bl)mDx}!mgmN6@3K{kAk~b3VnjVR@ ze>WZ|mY~ExpU~cP2=R5a<&mCdWVGk&dV}^ad^a9&dSH=iAyno3itSnW}ktf4xAn1Yb|0t0d?D! zK##`;w92aIfxUMFC~J|wdN2p*@_g`?ar)qWTK(0$UB*m8|7i5f`z*(%p`3J}ykFa$ z&?EY_`F&vz&2U@z_lFw)xw8Ai8lGSn~I>Pw$Wc!+t^T6cNg@0 zT+Nk4y%ihsS6{U1do%BAInw*7$pCt9A@q<2e;H|LC|mA@p7$B^EZ+bMv%pX!2WTgN zyu1mN`*m4EZ{~BgKp&HA7uN~>GDo|NJ(`R23IV0uI@!)vYqZM(dJ}-FzzTik*mg0G z>&_lR^|l$B$aji8+V3UZ|MvkWp?u7G$sOfm-YbC|&LP5Y^K9M=br~kLlY>GD&*bsm+?Tfs=~{vfPP>l zH1hf~l`*q=8i98Z&(bdc=pOaGouucK3Tp9Q6gxc!=r0SQCj~*Mbv-DLS_u8D$ZIz9 z;&BP&J!t0cbmMOSYzEL%Ug+ruI4WvPV5fHUJNkV{n*^b{L;8J)I6L1==nuaW7r7cv zjqCR#+IRFgrFJ7n+Ftux!GHd-bsNcfo>A&p{EVEP;H= z(4%`7f;`wNa-=V)U8v7#_xa+~1pZVz(yFX@6#7%?IBx);x(f^7wuM{^~(1 zp?4vm1zza+(m3;c8BOKmSNoYf>>-r%a%?uxrfiURWJ9Rg0)3-6N8>yjNdel`2nv_^ zd`5%h1XVAK-$NKL(wD z&Ya+9+m0t<5v=E2ehEY90jr*0Q}8xU@OFma?fQxQn(mMB?{$h=IHzXuHrdg0aVGz1 z4upCg3EO?P7QF|x<;K~fW&=ks!(aVBuEYbJ#;#$|IPY@4b^Q}kJMw)hU(50t(h~a@ zK$m+44{thkeIBlR2zt8G2(8};YUjd_^6+$jG0ww(ufN#zSOAL=3*a|m0p0=qZh)_q z6A{`jIg@zUrLFqIBo7N%XTcDMbvh5%{vY!2QAqaRcj`QxMJT74Wd9gWA65~^lxf7w zWe6TlrV*Wor^d|*9(GnMa1`jVXcz8>kdA@O#1$JH4>;Bs|=ym_Ez8nuMPt^U-#qU)7u2{c6f9{W| zInN-~_6(>izOCoX;(O+;#$P_(o049uo}V4~vjUTTe)!Ho{Tx}@7!S-jGag7iqw9gZ z%?^MzCx9!(c*c3#4bUcX-zUDqs4rjSwsL9<8ufbj>>d4`@ZWzY>3mv+6f-~@Z&PNp zxur24NVe_UmXIF)Eyr6JbY8Ll(7@XU-4B!F%?AFtT>nnKyEykw!ZwQ3k+qU~Wi=Ky z+=;sotmmXEks!qTec<)tRAIxzF72U%@xT?FrhOhksQE$C^O7Wdx)$UzCU-qu7i(w) zC1Jn4!kDMlL1?{0zeBjsz~Kts$LcC|WUXPlHSDWD|6AZnn}qAY4<_MSlnmF3>%dhx z4X#;&9|c^u8gSk6F>oDtXFPDdJEMN%&S*J;k~%}rNvwt1S)97A5|qSxB<{0P4#oq? zYw?YD#smECy+FLnO@!8%fEEJRktI%hbcK!3A{)?)7-{qOR>W#-Kv(WXvD@{$zx2~{ zNY7`DT)?;6rsfvlJo&nj+k1Kr0mqK{vGQG@E>9=4ARVZ+=Pvgx;H~``lMZAj|(j)Y4i|MkTHb!O&$- zd*)9Oghnd$`bmkLTL1h@;r|vwME617h@h=@+*&FL-pMHnV`ouf4Mzo@|7X|V2J_T= zumT|TULe$ACv?7@&>EBy?UX=vWDq((L;uash>kqsEzBd{8f4$niMVW)GN&GG%&w2riu)vZZ**5A;C2%_->t)0VVVl( zacscZ07~NCsI;j#H5ul2Bpv2Mvno_DSEyugJdi6vsLQyw>5xFSe?iyh#XVD+t+lfe z6v+t+&ch$h%-J6S3^&DUsyK_)_v;l)G?ws&stP_$zPTX7dVvsl8Wt_J$ z$aNlDE2j+(^8j{g9C!a>;I21rU2Nz2hy{l1aVF=WG!gS{x1R|Xbfz7=VAN_4W4Cr? z^*!py+GT32W~q90qmJKe9KR=Z{AR{jAS1>Cr~36h^U7)@Xx$FPn_?og2#EJ~(`1e^ z3AF}S8gW)z(4Jroq(qSw~Kghppa5n^75R{%kB0q^zgot-O z7`e;LFcEi^XVT-YOk4*C2>qf8wdI;%QOkPbZJtZ$mi5H@=v+dJ3|J~rbFeO6(O-|? zahrg}Cirnr8llZ!0p+nY9VS3~f{%U$6#iWU+8eY>P}(R#=w37QrMStG+g)Typ&5oQ zmbPcsqZwPmp7zWJ0J(_iG^*DItxyv>z#)K8dlhO+)DNYMdAJ-LWz2JZ-yEcs%rNqx zS_rMT0Ii*t2X*LW-52ApFHhz{ou2zJ^77RDJr`cq?P4F56G#h++~!DoJkGA`gEK`J zdT^>Pbnh37Q`a?qR2Mq+@>E^u?*8$BEtODv0qMy>FvQPi+*nf{hcIGXnUGyUhBAo7J~4(UFcqoPJxT5G!5Up=Dx z%DArLH0@8-pmxnA^z&7qj9Oq$4)R3bG=tnVi_o)DRx~m%{b2SQqP{xLL=Lu$_|p9a zR#5m@gK2Pd6Ly|1idRk4TDus1=7?TvZT!Wo1uemM0YY``nf@*}9IgH9GyNl%;sJv` zw9M3u)~wX5R*EyVvywCVrTanUXLJ7hR3-HFN@vRkafartg1!-PSL2N4qV_UQ?+IVU zf8zMX8QO0c^PG~L(Kl!NtKIRX`+0v|b9?_-V78q;kDG&hjS4)F8p#JbfOQ{)b2v@A zf|2qjK-;Mi_O>mrM1c#i?WIOgO2J>vn4}^*>5jY#3d;fNLgYvofp_wlp|Yo-VBfKzSJvx~LPBlvIDU-3&_3 zIoQ724D|KQ1xq#{kS|*O)g6+(wG!D*pTjvtH&>!IJ}%$)=YhZan~yM2W8P+bCn3A| z&Q*!p2J`PLO#aqp?|rb)-uqzWHdox1-)Rp|}J`SAcq{_2|#=rM*Oum22CzBVHKvG&<2bU&;v z321`}_BEPdAKydrmM)`}Us^^t9f$|!O!)e`wMP!<^-P7lM-Z|Y|L;c-O89FQBOT73 zfS$YTk#Fce*L;4>0Hwu@9p%rz@QrwY&+SKncwj$cAuiYI0Y&TXYzP)e5aRpM3LxJ3 zX0+yZl(n#a6Kr2;Mr&FYv}E3A{NBA_cV;KIpApcw)RY2 zPm+Y6(bzVVdUc~&jnyRO5aN12|o4 zkZi3O+gdN+H0{sWsU4D_&0?I5^?2hn;ZOT13EC)zBCdD&Eku=O6IJBf1z0?W)5JYj z1gB})70}m?UC~?z$Y8D)-))iz%|+#BA~;(EW?k%;dVO9i%;~`GWq#c2^GkkT2R>Wo z$9`Y15|kR89j(M5KTrjI9hT#w4?Pca`58a6mi|j6D1IxO{(SKgCZu(t&Ld;t-~*yK7#c=0Q-GC2o~vh z$`o~aUy`8h3ss-Ml22I{-?(RiNw0_&PBW_X@ej>nQ`R5{yQ9*3Oa`NGj&m?@ z!}0tcV;&-EOlD8aZ7E}cF`TKb=5xcDTF;<$u@%5|YJ^>~eQ}P`0+8z1v|~x3-O-wh za?T|3RmW=XQLk=XrjBh}stUh4BX_mmTCXrowgElP0$se>-&s(8Y&Ytm35lF zQU99|xcK*tje48&I8D3o32nZc)TZf#-Y&scH){945V-jMI32#_2-;pg0ZI99tPD`1bc2|7NJgqPlN>*BN;qEhVEnx%}^@+SB( z*n532)9>quGg+Ehp(gT(BzTqU2OZfdnNK{+O6L|>Yl z)w%+KJc`pa4s)-Cr~|VqVkc+m@aF(LJ~H>E;LqnC48Afqy*2SoV?qXvSxcL1h#JE{ zBPn_gDE^+)9RGG8Mek<}r)$@+Tk~JFmU5V4I8Ebpl7q6MTqc~ROkM>3>bh(7{ZC!1 ze&-E#91t=a`|HgxME;rMoo5z`a4QB{AbFD;OKf5B9KYJ3+9nNnD*E$11F8^Ms zg1&N`9nHPQWG){Iu}utoj-d zYF)gzhN#zYrp9F^Z~qkHXH4kh^qgqN*Ce?e#aUYIxV7}FHK6t|Ci0kHOX271kLEGI zf^iYw4~Ip~WxZx>1faBDf*m4em)5_Sc@xYnuiyTH~E{3*siSv zD1A%vSJxnSbifL-W&x$90)AZS067Pd4^K<}>PJyaupK#~0~V0CSO~S>RMF4h6{6N4 z*UJkVb_a`Qk|X6`grPSjfAzf$Ex~d$BU)<)c||?CzXrqO5AkmwhM`6T^4A=M)>=SW zZv|1O@>at2Nssp8fq0;9XU_d~5_pedIJ%gh+iCrayuHl~eH_kGGbqbZbCB;JjmDku z$oqQT8UFv}_u~ORZ{CLYAH$$!xc3Lo;S6mCL2XZS-3@1GUpo*FL?m+L>kgoGTS0va zLntuJ4v$Lnh0megjMg|%*23~luwC3=ENITm1Ap}^Bk{l)3n)h|Fw~1cJ|z)v&W~Yx z!#I<5{okWig1>rbI35@=Vov|pXgu(f7vq74_s0XnW9;aYh{NF2cz=y%fA#d(oNMB2 z_lvHEk+|pM-c9OHW_7d}=!D)>g@jN22*%nKEQ#}f9T1vp;(M4*bE6oFP8oX4`ouGU z#k~@U{ez#OJ0)FTxS8{zNq@dh>h;x1eqV#+_tjeT{!S%itOSc|rCuLNYP(MI`<$ZQ zeXlS1Sz_Eo+c4<;^R~%jn2h?JlV|@#{f1@gXfdIQeNeYcO|wUxJ{s@s3VN=^Q*uC-zx?T9QZLT=KJ|Msn-{l{62*JzA%?{Nw9(hi^Ec{uff<~&l&Sc z#zijD=kvrYn3I@yVm?n;U=E+p6AqZ8+e0VqLSjEO>_Ph4np8R;=oGyeBZXp*Y^f?M}X7A1`dROX?*Ga95)Qr@x5Y%T`Jr@NBC1u_ZRhB zn4rV1#M;^?=|7ncs{mYIZ3JaqrS4a&>nCn4m$AUtg?{3S=2}6fI7hpRbBaWb2JF-x zw89*&r_|)bc47rNp|5cLRM%HrLPjR^m9A;}ioTC!wbm!;D`c9!q8j?jPD5Ye-*bKC z9Ah31Z(}8hm{|_*m2noB4dCL>*EfQ);RGn(G~WLiyR{9BiF!nd_f5vT3)rpQ#`HUe zPqJh3Ir4dhJ?)vpjCla*_Yxl$cVM#-S~mkic9Wi~NzE@;)fo`#*Z_SZ9^^q`M>%ZE zD^cD^saK^7uq}*10W;|y#`=BjKnm&}NRhe+PCi=}wnF#MA7+7<4iWWD!`^Wy1?0#U z((~3lPy!O6M-NT2byz;$)^Xm)_a>OIU)=lP^=%!0@S(QB{H2A--%i>(W)$B2APYpW zuyq{%7+c5TztPrl_(ryluBJzp+{oV1kv*`rA^ZGRNUvB01$nc=n-`DO0hI7{e)Jzc zKAr$1fAxp^belovFnc@i_PdlrAI1agOmJzv2`+KHJ@58qwDNPyXoV6N_Km+xe!nko z1}Nnp#shUGxRkJOh`gN1?G5|J0wpeDQ7;=c^=?)4I$4R|^A!Ew`O{D9c1S*FK8Frm z6TAB#khu51_33y3Y=kD_78CY#PH)R42o-h_)sF0~g`%FbBPvNCa~dpilO?y`PSnqu z(VEpLYvHj?u>InK-I+Es3~e=o@);A*-J9kwIX=$hWLq?!ueMKzCvTV?&imf&$}Rsn zo`fIg#Qdm%7yj(8`*eHE)g5soHpi-tZL_IYH`>)$jYFN_m6J#rNwS3;*Z_SkC!w#o z2Kq*^OB>4q8o5nUU&fx(gO||}8>`yC>45_uUcnx1GzVzLF8jf94-Bb=Am_A8Lys*4 z`OH7)HWEAbSD&#!pJ$EzV8PMW>Ktr~3R?-Q><=5Y+qn#|nQg7Mpp^L5dSpq<{Q8Oh zov0-kaT1Eq?ukAt-Fly6WvDIef|6c$Z1HQtC&?MDl0d$aL+C3Tbh{0gug#cvTV5wq z@*NZRDAbU4}QhL7sU2sf*y!UV0=fBxN0zjF zr2Q)s?N1o(|G5mc)sC|g|2SLBVO%bOT#!O&Irc=kZo%gtz=7cOxfi4W<>w&|>-72m zJ3lXG>3wvVCg(gK6Yr@UETx-_k0oCU^khNg})5C0qcj|uzS+qRbL+2{1VGFG!fy}I#U zb!^*mHNNv7)x@5;`?h+O%coX}c=smBzz>{+a(d=;+>2TSO%Gz1rqguG1Wg~h6+*wc z8@1Km3MGR%g!;$W;$j4@hV=yRAVjdcA$X#zEkT#8OCWEr=bzU zmIuR3e(ML~T;Y9PBHr#J)8)ZS)8xT{De}O7w=NGZ<`4>TCgcJCpUZ^CF(#jK5PD2< zM0*XI;c#)f;e4Sw2;3Y98e-SxbyYM4RwAa3&&VQj|NwSP{q1{2iEfaIf zG-O;2c10_T+k%y2EVS}&)COa$BzKIJMzCA^A!8ohSJ^4_e$B8`=0ic(A+Ye^jL21Vs(G?ivQJkgKVdCBV8d0OqS1fs~IJq7HU$cW#)~s$L zCg30 zynMXJju7>u`^Nq$<}H zXb9vkQ3FEnf35zF=4F$6H>gSn{idl~ZUZnIGI}Z}8Mtble`3T+u@d+eGb(pWlVrIsi(Bai(_F zNoX&`7AI=aC!TEpeLRk1zK(o7U&oIu>3-uI)A(=dT2|ma6Z|(X#zGx;p|_BtT$YpdyZGyhK z2M&C=+W|@@_E+2LPaVvNFYPbj^!_@isd~M{o?&d)Y#6+ee9~jHg12kK!!Z><9J5)0 zM((dt?fDS1r2rLiY$-5Au}!o0F?leBP%gW;4Bu@b-hy=`R)`3VzK#pKHry2B`ksn! zigEef?f@FYc5V1oN#(rfidXcP?*i2!e3zUWUvFCqp-gf`f$Jc~ymBz?xX%P~WPRqr z!K?NCcZ0ur7^iE_b)a0kTK`6=U5}Bt7-ur?r%oc?%|9S&$_o`s9$Pq_zxGe8NjB#% zg9h4hTC}nFrQjie&|P=wH5F>FvBiH9w4NQUy2j++G3F6DJ=Z~B4z@?hh`vS~cYK}r zI&vIwd;<3S>Kbld!tq(B+`PnwU8mIz565ilK+*8Sv79f%&?b}<8_XhfbLY*mO$|A* z`NK?3=tf*GDg^(FGv6R;+NT@`ZJ2o99k1wr=Kjost*;Zc1ru+g4o5L+75eBTt?v!m ztO>a>Dep~5eB3+4rs#i_LrmtlKkI-YNYeju7^pcIXhK)z^W$@C$FM{9`Og-9?p$7T zxgE7m=4Sf3Q8QzP;GZ;cXUk;;v%nCS6@1);o;xOD#$d-L3FNPF89QFl|HS9%CgCXQdn_-uHz3He}Bl|zm zet9C#Q~a#0%K?k)Z-pU#=5ze$+21xxgzmompFeDwN4&c~^UDu+zxV!!Imi)>% z_|9=3e}B;lbj2`xd&Nxjn~yn}*rp!ipm0;(VY*!))IQ@28b;Q)3y}Plz^y zR-pItZ!%Jqi={xr_?u;b^mi-xSneEUFb8P3>DjWud{E$1`n!v(fjap6?_ecb#oIks z2C5Fn77o`sP%dud?V8JqI!y|A^>)#RfQt7AK*?=rDFdJJ{0X2b!|c+QFBU7|rq(j( z*87UK8sERezu!{^ZsYq`fvy~8`?h>JRS7peUj}=R`?^NhrRdLrzRvsEJ6FkVc%cji z_2+L6vwekqOO$B8Xm@yvw?y#|y-)^gPKfvK-G-FGdZ6ksyHtqgDg^m`FjIdQjRGAE zh<9%nF1Sf=*P!?N-hU!x@JB{F-&}>v^!wo7^ml{*4pbdsm&EtWjB#F*6q4ch!La^~ zcvpDBw|tl#whb36xC3B}lvrJ3g0M^+7z4#+XOMuki03pG*D92f8h6 z^HcGF%_MRqh(ZLGFW z>EqNoKpw=PT)m8raCs8LIa&txS1;-W<>?0weE5@LcInJ-=PF!AHk(E6aBpM_>9Lt% zPGk%8)ZIqZ$-2dv2g^}<^i3n?V+zTq)&B1x7HCXut7C30p&-2&q zBhKW=ZA%Nswve8jPr(9P9?U5`(2^Os%~bd&3?&^>c5C}J*uLo+lWjIVZ-)nEpB}&- z?a-2`Hs4>$dfnvTNuJhM7_2!~2|eu?ZSRnvyF)_V7=hf#?&;Utc(h)b1)4WL{o*Sg zm^&)jT3-QJ^b5v3W#F$K75PE3i^A9~Y-VFypyyjlP}~1t%=6SCqN;|?T5{+%YmQrO z9w=Xx2rZfBqqo@tv^B|Y?N72>FPfNxOU&V*JZZP~C)us%FG;pryFOyK-Ye^NYfcl_ zvs?4$e~aCkfA@dtqc`1V-Me|w*e9L6LGoAM)2iEJMZVY>p!A*-_SnPgO>j8b9($m5 z(jME|s@r2oqomjjfFzGo2npL;)Amwfv7B949*p?{i|KkoN? z;~xI4-8Px;lAxC0bX&FK_6pT@i|)5<&zVi-L8D?V{mj|5{@bj9DVl5 z_(V*=*fvSM-rXGM8xhxaes!wt(reYZ2)YaMpyym3g!tL*vLQ3B;T)|1YzH&UurJdL z`yy7o*0~)Ks!BlJ2&ml*`wDy&G~Eo!5+9-wt2l3q8UeLAAV2jWQFXpb)2{xz9w)xj z0-@TZ7~td@D*UYLLLQ@jmq%k#me5Bcj(3Bu|DAPkc`?^To{TLwK`0XudKE)xhY|n# zASU!d458&h|M2Ls{nqKR{aHpl=exmz&a8tu$QA8GATJksN}7oOJp<LQm0SXriTh z{BHse|IU~v@jsaT)j$7pJYctivQFytaXm};czg-eT$KM^Wb*s+nkxUzmJ0Oe0HO6s zalFgsfLw3H@$z}sW81}uM~~x;;G7~z&%1fEh~tIo<;XS>%bV8F5ymjyOf#o-y)KzY#55;pp07gz zr}+!)sKX5VRvfo0%MqauAfR1FJ+dx|(5~}L#4&FYeNT^Lo=W$k&zZK?*^GHUKNJs~ zl^}Yi(I4crQi(wR$p`Exr;QqeHumj_2e>@o>z}g-(YG1%@c%h|{Yu1HOud61+h)X_ z8h6nDa4I=xm0Npej~*XzSx(RQeFmSj`M|WbI7#%IaBayh&1uzDHF3%q3|BK)jrHQ-FBCW&vg9 z;mPygVs}F@9qpbt!)FM4l|NXH)1&i>Uk)}(5aN7y?_$)JD?tg7Vx`Rz@wOzLAv44o zvMrc{Gon)Qw}X`yz2;ZhV$>EkLkU=7rD2>?^q8pqkr9=~nfyt83|RF(<}XHVek+u8 zSYxI9jN57fh0CB$!)Dqc`Gs9$o#gjzasYi)BHqN^!PcKl_Fs!yf^M`s*pA@wW?{Q{ zK6p;r8$2tyqbC*~2p%#+D0MMvt2ILjvBeh87jgLM(aNh#_Dj9KW(T2M25xc?arWhB z;0DR>YjFVG`~%_p`4O9OSZWEnl5m@b_6EBwx*Z{L-d>L(^x-1ZmW!dpZ;CC>FvdL; z)5pyPe|7V9=Iao3G}592637W(rW?UH%di=&7kLcy?{9=h$?%1`vU-&|vi7rTtmZy7 zzH^02A0m{U#D<@Y)ED1rQLk>as<9fII<4s8TLX8;yV0<5cfU$t%HKGn< zD6(PV9mVdV(-QIiDhXe??w5lZN%+$3(JuvSa7MJU_}jvk^x7iBmSj)Ve9eqXb`XBi zr!An^Qbb;zIme}5-eGSKtEPWS!^KHy_F8)N&; z`q-RS=b1t7m3n2G#QXfTvD1>qP8VZyUPy~dh7E0# zF?I*i$382i3t7h3@~5+44qwX#sn^#c?t}f}{x`9fVeBcovU-I&vi4pzR? z_|AJ&cGB>7YT|Olre0eK^y)^38mmcBN7l|zudJS_#<3*)zecC6X9Ht_B4a%ZF!9E) zyJ-5|d#?N2!OW!f%o6Jv2-f4w==$QIm{+keFJjd2t-)E*ff*p@;$C0W0!l#&p+B?0 zoO4pIZ&292{lcD|hyA|76rhRw+h0n=`|D{q%}By&roib`T5^31ErlhWmLd*9f9Cio zEuEA6zCp*0X~}b4TJl8a6$ixF!zEK`iAf)&rJv3EuhWvppe0eqcA-v7XG*5il4pXJ zem3`$Xeqtu%IeRmBWv$dV>K()s~cCS@tw=nYbyz5P04b>td4EFj%=tx!hdeiu*+_G z;J}A`pFC#;YTIQ$nB&%KtiCzI_7!$s-;eGCD-piMj~yZEslAUZdF%T`y@F?H2^_eM zyUtwq^Mdx$j60Zwtd~+Dbf5&a_0EQp+&Qtu-vDqubpn)i>l6NVZmn>f1-QQdRdKIq zi-u=|9H|0j6zA~sLs14IM^X*HyFsUJ7YJK>eL4BCJ#oiaI~(Lv>p>Z`5<2y+(H^ax z2_Jjcm^tlkCCj*LOy-*}8*2!0Ho-TC#+aa=W0Et<=_hRU`yx)D9LDS2F_NoHzKT8C zY`!;OSG3Xua@__{YH_b`QwpI+*F)cCD<}_cfWDfOlXr{t7`!zIyty$Z@02oIBUQwE z@wEzd%L^4t9!t7k%;xh*x?j}q!VU)8rR-?q!dHUp$5^Pi1hwUku@Yk3FLpELsgp7% z?iTqPB-TY*2Yn~wOyufGJYRo8e}~sW-e?wNKZL}A)C8BSW^Mp z!ED6HR$2Q7^V1%S@ARl++tSsm8#B~cO{O}sHcP#-I$MpOG*8CKIzYahh?8|d$R6L> ze=ZAXOF0}(8{FB?b+pe7!~+zAHf+?k%7V1k6eCvF4&eIzW>Ej|I8x6vf1KS$_d|ayU zKGg_)gV?D((U^#_bw%?~d3PRT@{=N7(xnAjIBo#xKo-B8+6Ye9E@QVgoKGmn%`wJ2 z1>fT|YmXi(2DuOj)y)3tqD=)$3QR_AFcZ)g1g=w3hKS9z#h2~>os<#fXExn;EKMsg z+fEPQ=3p2>TUSyXE@Nhul>$X}(%n@h^@W>E-Qgy4Hz3pvNa{v*=!WCZmT|o>rviRF z@EmlXYsKB+lY7ce+zE2d!!T5ZK(@^!N1SGz*3X=a2O=9QyqhF)BwPyA2H+iJW|j9p zcoHd&22dg!kTQmIiV7P*u_1Eg>iDw#Uma#|pONM(gY!X+}~xGM86174T!}Qy+~dnP&w#TKu=ilXRFtzW5DvKa=3``;B-KE;mL?30-diC7iG4 z0DQ4nk0%*#jtANO0Z%Q#2-I(D88NX}Lc zSA*GKJ%H1-eG5@rtpuSAaGfrPH*S1Q`nTRt(vqy*CyGYTNk1>HUII#02*a39T^0YST^Gs~~%xut%S_NUIyO=dH>sIkeT3-LcAalW7&_-DTf=brt^R ztE;3mwEBORd~YkHq16@HU*0;9((9|uzOXepUc7g6$r#r+D$LMbVMg5&g6_KS6Sd-a zQyHhPd8r_8LX)zLzjK*EapZwggY3~K%|NA8kO$u-J&sR-5;=(`@b2scrNF>@`8nAB z7pLE+M*()OQO_&jg- z1nIe8hSh(zNUM|aEg5*W?=sz=zqIQ!c}vyL)SA+_=H294HHZnVGQ(=fzGW3LnYN;v zvR5VB`7bzoeH%(Tw>Fj>688S<#^a|R;Gj!*fQTIR-?#?@I#N(F|DmBLg zJ3#mKWzWR}S5|*X9a;O38moCwy}I#>>e#j~sPUa^)xrGFKgO!8LQi<@8{>f^C&vYE zJ#-*@=4x5!c`F zmw15driu5t)B4}>mw3RI^gexB`|W=be)AJ~0qS(W`3ZPvQf`3t&+4`=1mGGm?De02 zR?ioZ_+9<1Uc>9*t?>XKkLw~fEgn)EoPv2AAc>PCwitFfvhYi;V4)pilfG?EmzbN4GR zR3B)BzE>pF7p#Q7QS8)OB+u!~*rOH1mx-93!aG4O--U;Mbr;AlErXCFUeSNX0)6Eu zEBduGN2}PIhj#UgdPsviUmU<5ZJpt-egV6+J*I@ux^u#3{Xq8xil28LjycWi2e<4BO{e(3;f?U&x#*>Ayd>a9<`vsax_8 z$iFs&(rr%4d4N(xtRmN^R|2?BGA3Wb+1mTqt<_7}(OwMl4;vndMR2NCk7h-;EqFe- zO@dG=B6JAP(B?|SnP_Lg%_koOpK-ZC*~TeQ-t`!YAA zgPei%I6yGLoG|wL0O|2nVchEzXERH$k3a83XUo=E{JsvU7x9vo*f7PfXr6l0L1 z*rv@`G_Ka5nbB1X_6Aom7Wyl;Yy0>(hFp7DFZol0ho zG-u24IFtXXkE8tB7%Reipv3|aj?j)z** zUiLH5kM2Vsu@Gvv63W-0XhCyuvjm~2MCc4m=wpa@pGU;|BQsia7-cPFn_&BI%xKNb zg?lsKHh#}q_8I~qt4D&U$^!kvs*9TU=@0`W& zs}(-wy`doMHD@hPIdF6h}FeRM%f@KFgu-GZJS|7CjS`|0{ICWE=x_j)BL$0TPofpbn@ z9hP1nnEk%qt4w|myETWX2{SXg{wkCGNVMtel+Kp5BWJY30^P%ShE_|N{Jh`?d-O*O zT7oZ(v(P2%(B??Q`&&f3xfZmB%k!K%*iI~H4VUQ^#_xr9zL;4q&7IgwlK0*L#ylIw zm>e?v!NV7s?65=Mig-o;d)T3Idggol9e3&Y1j+Av)C_$q=RzooXJ|EOMzobN`P1O9 z-b(BHAEWhe{Mru6S!9bonl`gl!yxZ76Z%&?LsQ&@hG$mB%B9rk!iD>S)e?jn5TWyc zcrg&~QWILU46+us*TMGxp9!rwbZ2AcmyO@A-r1B{16a%fOnMH$YKuYJ(j0MD{2rdI zy^m*U+tX57`IvXyMbxt>HTv5H`+|>45b`5_{+_K#K)m^X$9Q>0j;P7;W<}4BGC9}M z>)Ths&qp)G`tr5QmHa-xx!0F#@%wfokblgWr-pw&%;a3D*LP>7{=FaheZ0Nj?DxHg z=V&RzOkM!~>Lawi|HricjcNxd@8daIjbw{%Pn#p~m}en0jOS?c(g-!psEpMBidNm( z5Ui3Q^eKtZ9{}+_2gLi139UH;SqqPChV8>9wB{EJzm+*+{Qmca&t;wktC-g}O`v?= z1j+_eBKMUf@Hm7)dmqo$7Fq~Bi{?gq7rYn@Qx?h-emk=@fjc1HFPqSsuke2BVEeNs zwC3cUO_|>^e*e!qznNJNrimO|1`fqI|H_!>&?u8P3x8Hn3ggTA`MJR^^xj^d@Qvg$ z8ToxhX6P%o!_XjhXfw|+xz<9ui|o+%9?sFC*rk0oUeSLMJGHPCx;d>9)az?UGo!u8 z?<3}3U$5Ekn_&j|4)9lV-hP4Bzp=tSqjevx?_bdX3a6Rb4p11fM~lXpyv9r@=c{Tr zp=efRtVWs>B@2}xkswrw2(1F*z2)ziJD+!D(%j3XxzT~EOumRyH9j_%v8yXUd9nfe zYLF`m#y#$R$a#8C11Rm!!Vt$tEjnAq@ewxiaS8ntwU?!gGPyOrtpA_v&^L3uqW`{6 z6Lo9a%+@|Lmu+*Rk1tRJ?e_}WpYdO&{cHG{J#A)djsu3mDSlrs($}r1 z5)@9?99BsJ`LB4E_THyK4X5bu_b}$+eN-~NkIlRfk*mb-BQuYe@%8!u&(=1LGx@Mt zpVPLqnXN-f^O-x&LgD|W`TTFjJSVR)`3%50BMyz6Zs6X^97fWI0+ zuMfcQs{p@`n0kH4#Pwmn?kW>3&6$CF~s;j&-i`{ zUip55bi5|&U4*f%D4|d4Ia-o(vos-P1Y<2Z7fBUkfj2FLMlcj<7Ebr}=t|>!@=J+O zt`iAd{2g@PJ&iU*{sM=7S8X#*=3F^0`F*{XUSFrB*Vke3`;J@uKGj0#?rCuRvqb3L z|0Xz2nDzXFU6r6Da>R5R^0a~P#}>a2A-~UNgE=i0LN`x?We?ZI|C?Y*+$pwH>i&|p z889c2(}mN+I!mvw)}qq`U)TSKxwnsx>bUNQ&)mB&cX#!QcC`ovRzk7Siye$HFA65w zm2BRGjS-h(2irm@H4?HzwoYOb>}Z9O7*HI0g529eV}aGw>=MUs5WJ-+lGVgu{T!Q8 z$4~3DUQk-!yNhGXAkeYAn&&h3-jx<1IdS_upI`ry_Rh>XXTEdhoH=vPof$u0XxZ2q zdrUNPF)r5vUfSRcUtHtTb1*LJ=L%gp){iizXy#bIKA~Sc7JcLYtA1q}IT3uUdxf5* zJ?1$)Jg(}s^(^hN8F4q)yZ=9RZnmj&C#!*`>l`2Jl+LBb`hShyW&B^zyPQ9!ceUY5 z8;rb-%e8)FqM5hRZk%g1R061f!_{Y;bu@m?k+CPb!lHk(@mAUC$@4Q*(H&{A`O$gJ zXgC#*trp-2@9*uOqrZV{qra;r#A4l9AU^#eF{2=ev%flQE{W3i+&!q;mtC&;ccfB0uMKXwsk;_-QV_B|lLk)I1Z=5gu! z6{r8y{R%Ta`_Nc7n0_^5ESCJ)XT*}5K4J0)W-M7xvJ%24Og=#LHhL_1Vl0--i~utE z`O4Aod&HS|Yu=uHPmZ!9gQ6>Pqu{TM5r1XCM%GsIIJXIc#6s5A-SFcX0vNyjH-u)? z3!ux&1T@e)peX zhq1G}#p_7t%kA~UzcO)4ua@K(SA zZ&h31Eh(6G&;B=W#p;J|#f#rfeM|Ab7rVdtBiJ3O_|vfqO~6htv3q3;$L{JoN_2a- zDNxC6-wM$JV%`W7@)IEuWbH@yF5b=T3!$xk_@hu#LB_nTqYy5GP+hA4`k6kH@n{_- z;nsY>(9T}{&emP|er(DIY}*-luIsx(xGM{AS9PGWVJCU6c{8cZ1#lk_{P^u@fWHkT zl@s5E@CoPD?L%2TOH=JPWrdc8ru8h{G%d80(`u?Fl?J|7-=#9~&I75(U#SXk6UWb; z;YV3W;o;WvazX^;p)ou>5w0UW0CG4DkDr-%Y|8TEH>Uv}3MG{$!C!d@V9~@o4>mdd znEvc1p`>@J@m#3xIK$V}$1btAF2{4JMgPV(RQKRcpugP-rzI<_^%X;Kmjv=|fSmZ& zrm?eEF4^@vP@+Bu1VcO~$b?|P4)QJt)qTX6cVVi$5`u(){;uFJZRWFEA$Y(FGA|2# z%4DAvf(=%Xzxi8#ICY=RT!79V5f-Wts{0*d-d|YEwpIxC5RiQU?%#^$vrGs!@Hqvc zy3>q#|4ba`9YT}70P?0E_`~Y}Izt2&W%KrAyblcoZ9U16cxpW%_xhE9UK*;rl)b_F6%fER&SI zL4s#3AWPCDWsj2}vG6#{IM;7d+LQ!&+%_rgr$~?pQ_y~c1d9pCQpV(bxsOS|XQyg9 z41yKpDmM%kJE!R9izFCuOd-opNw7hhLYAW>*k+$XmYYiNQiMZ-#2y7$aNzV|l`%kmJ8&2=~+v@NI z(XO98`d=jk2Pz1jtsz+Dfx+MV2y*>#5PxO4m8`8Gg*VnWL$Gy>{ldMd@aaQ?&NyVV+Fa4fV-*y1`k@Nknbo7 z2BfLwYOqf&SDS5WxpaQHla#$kg1sCo&m?81Ab3_Z?hr2oa95SVU~dM<8Gm^EpW~u0 za{rHh{_*ucdc5xZ>fd~vsBzMt-T#M=S&OssgZb9&=W7XOHg8>gfAiMGKev*#&y&I% z-)n~8?N*>4%zJ#s36jxri(};{aWN~>JIZAK`)n4-DI|KlWh)-kp25XaP* z6ibFr(f5RlVNloI$;OnDU_-_fWBE%GY@15%$4T(uRC04WIF;O|NbsyQh1@?SLBh)l zCMk=OU@^DJGbguk0UOBNSKh(3jqMLD)t=7`Yu&k2J?sptVy<2% z)mA<12&)g-aU*s-6HWZ4;=PO|Z0AplTst>8}K; zJ_}e{EK>FGtZ-?ANW+_esuuuNv4BbqK(+S(HM^gd9n7KX`+%z5Po)N@Av^z{xG0aW z)Wf;q@?zr|uP+@eq-Dj0)Kv_$v{?TRgq9t2QT4DrY|zN360hG6SW5gaX?-_Rb*?q6 zmfUDy6)@Wn3sn#27;T7M&*9YRHO{AMmnqLdV(`)F%%G|dP%W8Z$kom<0;-ASRBh$Y zZ_xS1OKjmWxf*;lQ8FW}HWuob8@!5W1&RM#R9#~74wM`Hc+>2M zm__3ymay8FP0NY@CEh-M46vNb@)}@i15mYMraqSH0B=L6`Yxba6F~MF!L#}L`OaAQ zc6B&b<_*%H97iENIU6N6V}bY|e)$pC>=~?WodZ^P>->#H!y3a?><_ zl-F&_hp6Ls!UCNJfg@UbZRKtP3mn9cWdx2mt$tL+84<0O;BE-j)we=8-cC?+iBa=A z_lTp|AFaxTVDAW%-I;#u%7Veh5hnAvr(%T3UvT(Q)AQ>ck(gK*c}nzGO2pkSSm8zC z6DFS(J>|3Kkj?|hju_`gx+9lFh$QEb&K`i9dTc-?5&C&-wQ7{fefs%Y(-TF*O#Y2f z*#DjtUhKKdWVI@QRiczQ_%kA_%LCENa|rVJ`-kIzJYG;Qh|!P)vM(2cn=Byn7~!l7 zWa*=4>tcCrOJm-)rD~%k8WVGA8wu6zB%!*IJc0|SLnnWBkc8@3v3Qgwj$J#UQnuvh=CdyMx* zFLbJn)yNtJ)V5S3+ah4Br5Y34c)x8JAK?AAVQh^J6YFdkKb#RweD_M;y^k2YRng@A zVB6BzL!3A7w|9*9zv{fbW4zzyya%e04G5^cUyba20b_}3Ong|4>W40j58N8nF1Rpu z*@cM_7sf}t(GKBC%p1VK+$w>)o;b`i2TtwV8g}g0_WJRBqaPjH%ZJr9D^Xjw61yIS zaBRa$Ol(|<@#A$-w$6cUjRVz22Wnd!7;AB0Vw(fw1Jj}{0!-j#^wSEH@OpV|Sm)EY z616QRpO%%F*tQbm19j2!%L6!aOhC59fvnMi=Z_1>P6(*>38=j$V60!j#G3-fyRFd# zT*S?N ztZ}6-k00R3BabANlNR_$YOal{*9Z$ZP6xo?@vSr-u{A4o%y^q^k0ce<0#8Z>{%Gl3 zVFB0MRGX&sHl}{_Hk%(wDwj@F%~&5Yg?D+tCpbq>c(v>X6!i28jPT{=1%d6Ac9PZ>LH{sRPKCr;BDz zzkRL zwzV08-FA?xC~#mhHl!JQsdzm>uE$R=qCd>s>W3KYG^gr?GAiE%r~Rvl^Mg%MS@shh&A*zhKOJ zh~w7pN4DP+z4WdVs~&~0=oVzv?lRXCUK%&o4XcXtY1vs1W&KW6FFTF$VlR!q??k=M zhfckJE5Cj|M;$TBR~__F>1;k_uQ`$RIgy=kB0KIxcFc*|1t)3=C&u4%qBh_}6kVt? z=QtKHomL<4>R23n>b9Il2-SVdMLLTH?F-fZRd`5*Biiw5+$x0Xsz`n!zTXqwX#x2g zIp8k82G-WUO@b>vAo6pU*bC3)PNOX!vYel7-}-QiBco#z@%^?*2-WGj@t_mces{Dc zgZH~@2DUg+-R8tG?27W}o12+(A7fs%Zx!wWgKs&6>bR{?kFUZ~!FaX`#%1Yq2y*;b zHI|Y5{=|uDJqMt4-mZNsNq&cuxb(A%)OVbyopECPgfPx;Q$BrpGgHck`16oBqiP_hKEHyVT zmWE(0Uk4nz4rH#Y%|fW|QjHU}7I(C7l<@Vy;7SP9dFJijhfAC|RF#fNE^XM%lp4mo zDZ15P0@=~rytoP>*mE<;RYxIs@OmB}<#+J$ytLPas_2ZoE;u{ti6_CwhtM3>Y>+eX38%| z)B5^0G5R_L!L$ED#_^l)M6K2x?YlSuzX~S~%}uA7OLI3f<$_5wUgbwl_tJwdtbY{3 ze9U$hn|OvHSX>P9sVsvxFFSV=$juO{dwm*EDU-)no_@X#=9sRs0&OPFj;dT349y35 zr4I2!IMkZ18+r8K8kq7AX5Wl?>q%UyabdhAKg#8wEr1*s^CP;I^MTx z0Qd2#D*2y&ma$^n$?%TD0Wx9ZPBqfD2pT_ZBL0l374jcJEWGTxs$Y z&|fq#rEZjYj|%yTf%l2r%linSACCaIccpaaWe2LYdC`IYO6h?E)#uZ7CzJkd15=ia zGVjS$n*j%^hx4K}|7o^)*MaJLX>AT8*>;{?p=)Ae))&1hiCp(OK;`OkGu zR6E?!ntwL?U+YA5O}eg3qihpX{xZqDyuNtasK@8)Pq}WV==ZT7MnRGgws6LTS z$4x)j#FXzPO&>SckC)nAllr)UH^{h;E1pT&VHdJzU8o*6ecbbgkBgU{&ygBtQtgBb z<1f2VJ(lLK4s9u zo0#%=l6lqR)%qEFjlU-P+Lp^Ck^BzL=R~#8iF}OI3ir4_I*>#EW)o8ur?qYWrwMIa zU8wGG8Eq43YsdqI^zlthDN8bM>GoOEe1i}?2q5#a0EFs>H!)>)x?UtW-ri_?uQ8rO z-mV!q;6nBNG<}NAq7QE})}>NlL4PivBj#Lq)iU{9C_I?_@cN0_mTz5oIgzJ0XKN$L+uIphTREI4tRJXZM>rd-@Q6as3 z6I0@!GVc|}&wt|v0|u7G*llS-_AJjTl2o)%;ERU_*Y5N4C3IgUxT#$~A0n|vCVVPeZN zjGtL;#KR8>$m(s#Hrnv~4gp!KfNHyd+G7I7Is{BSAz-}ZkHo{Afx56eSDv z|99UWE$ub`U%Mt+`fIWv)-pbZPp8u|_hLA$zj`>S47FC{r5)Ayp5QU! z&tHK2+h3y|C$qQyXL0fmc%0m7@EMDf`FNQ8J^Fc*p2SeA5hrU8Rbwgfbht=Q<<^-n zZ8a&p@rU0hYrC2uSYiXY{!tQ)SwZf%4lkY?%|h7@3E4vuvIixM zcS)GoD`8xbPZ8-O( zT+TCoWGy+-p&CQZn*BspTO@PeTF~X=^0qV(x~iB^HeW)u-YjnrXkv|odYui1%zG{+ za@0nnyyYxVsaT+Fu7s>YLN-T2Rw5zuNf_TKVSJs0iRBW;YbDgSNvLi~?~6#QV}jv# zTt?h`%uYHFd~9E+&R>DMM6)k~u@;E8roAwa-=a<-%zv=bR z^B=LCH@3Gt{6j}(M~L`-%l)oC*8AVsjM2WU z#k_g67%cSCy-c~A^DCKzc1upQ=0|@5?J5biB@<{LAoRU^nQ|**Uj1HQlCR$xR@S_A zan)Z#@GJqDW65=5sNat99of-=Jw&c@z#!+pVBVg6YM&j4UNf;7SW5fvWlBT<_wE#y z@7ht@pB*jPZDM)Gj@mmZEWbie+{=_A9-EU?eH&`~Go#&)rRv*Id&g$hUr1lRmnm+> zyk(+UzfeN0Feh5_1G9dfgql|x@8c$*e|Ila>^#;@@#wdqwj(pz{ynozpAEIwOdbOZ z=)QZIGBP@j$M!aAfFd~)B$9!{6_O$ih2 z{{vZhyfT%nKY^=ct@*Yo>uVEa?N5^xZ1juwGG)&w^R7(k=7AAdnSDDpp>N02$H7WJxQ8k0(sXun z3CQKmTNl?4LePH`$n^+8|BWEm4?(bPHpmgDIo}r=x?MICrd1&XS3;<+%(Hvna|GOD z`ae6Z&JYC4%sSZw+`Cgcz2AmfVP>ay z)$(?ZF`uFPz1Zp;D00$ja8e$tl-o$Bx@aY8^H)y3Z#>6=Llq7jI>C;N>yLwW-oum! z3AoFNr=tQwbwe&YYN9K0Sa5alaZI!tdt$4bn-^DDfp(dDVy_FHL`egY`Fczh?YMH@ z?tNQHs7|xnF+P$RHRk;y`p7*@IhSPKvXp)vx1qK%Gg?z`V*0WTwPPtv7tn9q!<5s> zaZClTG3Li$eC(dd9k*SfB9QqQlU$JZq-=VM>unFEQVb`rP_ZLLRSjUD)h2 z^*0Pb;vCmkUdCf|z3lrC?0JdFk*x8uS7(9D*D{Bv0WHe}x|-zcdux1bTC70#5LZWi zE(~s(3G!BRZ|!>G>iGGK^^4y#_tu{4tzUe?+*>;b;C7^ZjY~ppBs|D{f1Coix8@NUH9L1OcZ8COIDckBhQZO=k4A%+howY_Ndb)ds;*3&?RXqnyvxt;MhJ ztLS;`pDUo}<9gzX`$dq)<}s80r2k&HKJG9m{M7Cd6sc zzNMy&c87tbD~$(8bo1Rz2>`gq=IjzX#y4g~#hWM0+4*)HT9g`xN-E#Yl=r3n<-v>-18&6 zow&&Gh3S4UB82KzGv>VlhmCej?9Ym}FEDXfXX@03luTcy#U{?FcYf`k{*gV1{Q`dc z&7>0R7>{57@XfUNwY?fyyMVEuz|jvalf>TbemuV}wFgmyT5XNF2T_BGbu}12ye!IU zMP$oGR5yyK)r%Nw6fvn7drSYz&Y)Sy;x_NlQ3 z6I*I9erB1m-?2zQRxcvkDB}4g0ApFgQ=w;QsFt5LJBHe_?H#zgjNjF;SL$aYykX3sz-X5je|0T~le6-CtS zBF0=ICbC70m)Ne}i#cfS#aO|uZb{pVdB%`!OPXvM)=6YrV~$U&xfj!tz86!YW90`p zvi_U;zRC+yb8U3jwPXR;mz4h9p00n(YjoY=ZC0e(%v&8jIal9*c|pR}(Orwkf>_14 z{(dFBy_o~V+b{lRQn^%BjYCU}{DIv&K^|FDjoZcijxw>QvUDa)bCSXvSACzXt#5{4 zpUub%2-!exwhb?G^upSzYarN^2eR6jP1%Su$~vqFZKrN_+&uku3GRDZB94SOgUIp5 z>u9s+=un@vqS}2OWqYj{SFHNJ!Ry~lFOm)2PI9D!;8xuvCP@hK7p1-bRFjc-fpe*(cx0CN3q&~r~uW*KzVDgmDnKu(Ab z{XIrPlp;;m@v>J5$oIE2E$$-DmSUEQDLe`8zwU2o(VvG#nQSrrB>xSgOg=0)5@HsS z&x;Eq9Dj*qbhHvF(K2t>J}%1&9`it`ZUxyjLtAdeM6DGc0dRMnCBc;$p}OzouKZ5e z{M%~-x%DTY=eKK1s;Iz^%V8vk+O`VMSG}pjvwwjrWyNR%J!C#foZQIn^2sU2U#U zsqKYIz^b z`5~6m^Rv~*W&{je-?X55#>BPeT6)V@nR0=E zTb+BWv5&PREia_q8Er?94xKnd+^E{B7TAIdk zB-9%~=Iby%o|iUQP}?g-OD@5c@4?qtaA;jh*4eb+t4#THlzCG$t8Xx9`UXkx?A$bZ z$1JF=b40r@OrZC?1&3Zv(YuCPzseMKH0^z=*Me%E6df2evC8JZQ}v4|-o=zdW}mc0 z#vPWI@@%?|;q$)wdQ+Y-1kYY~rM=j>+Q{oaH4W(2Y@jYPzd)-Ju*?dyi8wlZxiDB% z3v#I$1Fa^GDf0{N5YpbWD23RQHOe++U#mcQNHVX=CxsTvJX$bo=Jx z@n<@Ii#UE#v|F2i-&_k0%}?P`Opo5hl)oA^)_G$#_m~y6b*?Dy^K1cR&3xCZiBhCA z%|=!eZiAZ^*PA&BWe(##+D_9p*PA&BVIe=!_@5w4B)=b@x1v*DXF3z53wG^OU$&aE zTu*;|7gLs{^>Jsh*+&h6JzoadHw3}6MQMF}--6o9j%fS234MIefDa$!MeV`Qf&EXW!2T!W*th?yiT#NQ*!P*(_gzot z-^G;o0o-Fb2G5G9&bLRq-!U=j5>f3o^|9{@bk1E&`7NaBqi1{`>-zZD5G0d%dNt4Fg%Au~4>HHRI1l7z(afnT zv0a%{RW)@^Rrgz9yhkmx={Z%+BvhyRY^YUa7&f~5273NZrX1k>Q`o#FqWYjc+V>k1 zn-e0ceJN~a(%79$c_K~T**WIe55ihsE(8x{gS`6^d#kK?rg4_y_NFmkI)>L{7St|C z(eC~Uc(qz^s6C~tCG=N!8o3ebm~LB9o$rheoJ#4o71ff|IG57solI#0aF6BC91~Gp zXOA|XH0wVvqWW@bJZ948?qtf{yf3NxUMs43&gj6eQ}&hrPR-#`dhkxB+yUSoTN7-t zp!%{DZTyv4zutmsV@m$n^r<_Ua!b0ed(DFCgO2DxUkY0bs(q>Y*U;T}GG(!OcSYZ; zFqYS0A>ba%U9($Jz2J!U^_n!81ywPH!5sSVolKdNF5~;W&-Q3dk6Hgc5!Hdzc+R5t z-^rB1^!hb6R9iBleg6pKc?L^ts8-pGHr?}R{hh|TR|+iX&q;5qaDU{84*WyP&U4?M zvd3SfYt4377$YW;Jj2*^ujH?8co@TN@j5Ct>8iwoirR5fkKPW}}qNZ+FS&STk zniP)3bkUtmnUU1*T`rewix>GQ=-+Ajc)Vfd_M-4c>HB1@@6RFVup0SpHOD~KYQChe zr6SW3IqXd3hTnfpi`~ z`$F~2Td@h*5v{5k^>x;gYSb=RaTQ-@^}C`2FN2&|RIQ&^wqBo?j*g)Zt*9l;aV(ij zZFe$7`;>W`#QY9T^hGjAsE*I?{w$zh;&wo^;rWCss)~-tDZ$ZEmdaD&zI=$utDDuu zmqk~^VV-l@Vg>rMQMTxZGhtfSqa^4bW%A>s@W$spAZt%N0P{{Jnf$m0YfoGc^O}-O z?xGM3T;OZ|{6yo=K`!UEg*X$dNPfrt3wG~2Avks0I@h12Ke2QcmhtSls*iDv`hxYv*8=Lc|8k}Xi5_lJGNm5}Cj?30MMgY)Kc zZ3S?1xpaGT*@D^`N3`V71bg$L1&1!A^m7gkZ(zy~&HXpMot@h$d$jTICbVNB4v8s! z^U?hqnDX6EnK$JRpRrEv4@l;{kK7d?*@o63GL?FFkYJx?S9&9 zS79^S%{6U6$vk@R2BriiwtL8e@iS6%;BU-!+swK7U<%_BddCK)%>R^m_?X3m4|x%8F|Oc@?!-pd=SacF~)%i+%lc_c4@`L7J?`5YZ5|9kly z-0q}uI%4}nOUL%@HVSC@MpB8@j_-TGH`4Y!YO0ad82cWdY)dM!s(}9gW&Z#Eo~07p z_jHvgB{mfi`47kah;s=#NI^oaBIwToxjcF6-jO_le`bZj5z(j1e2Ta`R(-!~UqvHO z4}^Yf1#nAz-nQ`=S4tcpAV2V8Yxp^m(Q$%gCCV6+yNE;I=jHn3nfKJb_XH^+Jp2WbiQJGlb#RJPmFJ$pcQw$;BE&__3DwEAO|GwGWWO8@rkzcz9mN zjMjfAK{CqZTI(cb2T8Cv$>dtcBxO&LVBk|G*Je&qc8UZWMwq-R*I!v{C2Loc!W&zg zA-HGWo*DH|kzm^=Om^+64ogM;sP8ri7Jn0DFZiR9-yday)S^~EG~_1oW;Zz!6J3#m z_E25oIN&V>q*Fca#{+rfhy+r<&k8U4^N6fw!CGG?%saUgWVON{l`>(i&jItQcY^$5 z3EU`3k+Xx$+mzUGCLG^!hT~P<()>yVgz8#~U!PH52|?%eKdReGoX%VR+W(!{S3xdo zGtR~5vC`>5WAAuK^hUTIqUeioo#uKtlwe0281r7W|F_)S|9i;X|J#zb|0k~2_apWF zzis+n-jjMR)^1o3yIecI|FBq1jmKfLlKzbYV8#LZ# z$+o02#H#VqNLtQSVGRy>Ym9G`?g07Q`;9sJ%xnL%oU4ZfaI0)W&J`0-HTjR_Tro4} z>hjb%SAAyARmcW%i)}pT>SPAUYPW|nS7DUx%|vKBsehAX>^(XYCEo(MER_d)@H)!& zXChNFFIII7EkNnAN@Mf&ec_yk4n&qT|CK@x1Jgk;XMtMtH z8I^j=DXYmuR+WitNhY#InaJj6VtiXB#oZYn&qQ@c=6D`ftb$gDjJ>L} zmuvOCs`aDL2_M@Rs>^RPzCRjC%fs3`L;wD0wV0NNwFcxLU1Bf%X5~z}da69E4>M5f zD~R@O0poq*`x&SuGH?t#m_wgm&y)uk^Qu+18Q&j`qv$Rlp=;>Z*E8iC zCjA72>Nt<1?bC-3i{4kb{C{$u3i}`A3w;%?dN+6I*+pS4`;+=5i`@z>TaHv0h{I8{R*E3}vOUs$4&p@qvdbH%v z%<zNWWb5RbD;gvspSoHk&@%o%OOC@V3!)t+oSD$biW#bzheN2}a z`4LCkXAJB45nM*!cz(peSumah!2~>4JVg!!yD|qNRP?9iK#V|I&dc)|SH3G}Q@<-0 zSDAYIY=-`>yorSBw8I&w))b7}Ke&eeqs)}HQRW@Xk6V+0TKn{kte=9R(vx#Z#*tolg4~u#K{c-=i`CNg? z#(lmyPsGzZWTt#&lzGSUs;V+jYn&eKt}^?zCHR9EUzeG3-Dp~V<2G(Lr$@!F zm~FOXpw^O(UkPoHnc_>!$C{mK>eEpO_GXOdMjUOQHTK3V;QJ*q~rBP>XDgpCYhEy z*p-1=NkMerMzf8Qf!h9bK3}Ag%#>fJ=f}LqZBs$CW}eyRoeb38O>c889a+besF|}P z-T-4cJH`6Fzn;X=_Ad;iO08Mp@DG?Ih|O?l%J>P2xVuYCeDaL%<&|r-&)6%y?^Z6jY1Ls_Wq<2 zbB({ZK5&298dR)7CW=_p$&McUlz9(1jaa7rD9GB}0G4{B4u`|9pBr}e2*{Gvk5ipH zb@t^c&g?lwg5>2X&g`KiSp3oyXZG+I=EW(_cH%M23n24YOY(R+9Hf4j>s{~jAWLoc z4o@oMZW8SMx!#AX>HQ}Oo_!AFUnZCmddIrxek-`kETOvBE%4;3l>scb!jXstURc$z zI?Cg>pIJcGL`V71V-8f?9mt+=pw?mJJ^o(*4%tP&2N|?sh&@@ncrl%A57l+&hU#8h z4xK~Y9va`V61CQqn5gjMA>rGVsrx>yWY0bxZ+wmH-Y2aLU=f7s0z>Sr;v;4B)r;({ z>gfXQE)3NHsroH%r{AsDx)LkyPbzv0^iH)N|8PB6uzB=o-Ua5>rw6Pf(nK0-il znrwVekznj;z1{ZRPdriQBaW6p7RVo4zZpW*<&KA?IOk+3+eCs3a`Rt?Q-Z;8#h+QAFM&`p&FcsMWV!y91D&~Iv$%j9yyC? z`?UrhoQ96aLpAt|0Kq^$zZ4!Ds`c}EQkbm&7CZX0k@0aoWVv!&x!jjpZK&6@|2>EG74YrrgVLS4wVW zTo;E$^*4?O4oJpN$RME2amDcMa z*aLjd!|7FR#{H=Q#^hgpz`RXAf}`9`tYXo$T9=bhAfVpRD*X}@hJMtM9x z_FFhHs{B*h@6mr8ReCJO{g5Mh1fOh5Dwp-xJc||$u@~T@0(#H_9~JjpPlw+~DhnV~ zcUH{O&+N^7J*gC1;Dy;1c!B>O5`E>x*WHTMcif8aG$oZt8r|=F2HkTL=w3cGHQnB( zq|#~9{qxVD`NjmA=M0)p&erd>yprb6nvzOunyhQCr2C{v_bpEM*aW)&=QHU3Wm8gV zPNQ3yMz`l8`v|TpG~^8dJvf2xFFu2As41zeOQTzoM%T~B_3k`F-l9dcV*=d+pFwwP zQ&L%K(#@KP?SUl*&Dag}+Y@MZdZqS6A=z<9}SA7OecT-Y% zUmTb9*p><7rJCclX({zhpnKD2&>h{9R8EWF&TJS}-W0*@Y8X}C5W($e7*+a3aN8S3 zl~W?PQ6v#=<1UF1;rw@f!LW6=ZA~g?AyvLnFF!fMu;0tJCY3X08TWIkwrZi_@4m7% zsr+uN{M%#YD`przec{%m@@9&*c)MO+YJ){@+hD;W0QZd(%618`$YX&8e69Kg0QYQt zKjX?eO#q8L0xZY{aL4)sICE=Kd5XZI%&Y4y_#vQfZNO((9;p@=p zYngKEgtBM!vRs%4x+4EnfUHvTPI(<`IO4FK+IO#PY#;PwKzx$dUXpjlVY z%%#q&>f}-DRnI(h#Ve!AbO5&i;J!ldxK5eRNZNDWp7-B*)iV#ZUiHjNTkc>=l^ue; zcY_=g^CQRZODcyf@DX3FBZ_^ zA@)M?^si9C8mb#0p}IG3fliKf{IvjT{edgiQ=CWQ*p=%kz5VYURN(8t-`_;r7n;5-kVe;F;q7sLS&~< z&=DIUcv6t|#~49X6fpLhAJ2+z{Z7q0-e(Gb9_KtS6V!J4E7^wx*#&|t+WeL4|Ft?S z5l6X?Kv1=J&3LaGUQ`zeQDG&>@7)W7jRfSAS^k&Y`ke{x$eP}yqHbAJxm)nR#A(DX z6O;fdwGRo#_V+CPRP;uMd5j77J?$gY6Cn%85}DqAQS|BeyLi1)hd!4Yv-Lat&)GwD zBd3x|r%=!_y&b4e^d>+ASrYwGhX>YHR`Z==#^i!+fpC-PPLz!@`IO*JwAX-q zP;htfHR|knyY_LK%TFbhi(+9!zlYcggPON%#*n>h#!cIO>z*gz=5o9$xD%JfFGO~O z(Vn-fJe4*^0g%V^+nT1|1cIxrAZsOeRK~NbG2yDl4_@|T6@kAvKieNJO9swF$ew*= zq+{RtT7v2tg7I|(wGG73{~9Oly~y4w{>JrmrzKR!qcSU@YU7$pt(KsJgzB_41SJBC)W&S8J?}>#JxkTg0W2b+rKJwQd;s^Q z3jw@%Ie_nd6$TFh$S1$!TNm5!N44Eq=>l+b{n%V-=!8et2~Xtpo}_X}@V^w>Nbu4I zg6cYguiA`zZwIE4PF>$i3MwzM01k}=biSGxK-C_=kl;yFB_RwXw6ux1l1kmm^?j=bYApU>zEAXRijo?ACBpFJbivF4qXTG)^seMFtON6 zP*n)VPF#t_LmUfU<_n;MME2fhGSwcNCr^%MR4 zU9Jc0HG*2nypuTgpb)hZETR;cbq-oGA^UgZ7jBN%&)pxRGR{m_rGB_hTa ziO7A7+Fd|dV?m|icM7OlA>!E@C#`>$De96MgaDzu{#jQ5zdG?*b^zC#&$PyD8c+C< z%T$!vvs4NYs%2Lra|y`o0yr?U?QL7CRfwp*MzEd$#<{#=sLs~IZ4gAHO+aIB z5{#W8sJ=rm=DIt4RxF?cqB~OgUraf9kv%DuH&BKRWaI{LweInEvR^0A4&p@cu1Hg<~8WD4-nU#LJ_KD&A$-kBS=n z+Lokp@tDc$_~+xbKE>-;052XVxK`(Nn?d_<0B_^8pD=0f{d}~)lA`@Y059$(_+?JJ zuhyX59zgE%FK#huw|qX@b5gXo1n^=D!4gipeO2X2;I?5+CASe5M*=7lI68y-uZ;nm z!Rs`xsa(PA3uBi9n9uo-nEcu2<8M##9|_<^Mo`>h_#+;B-2|aJ2ZW~ih$9gLV|}H4 z>H3_~?M=gc4Rf|6hjJgVzzz%5iU3}I6(|#=L|bW6o^Rgsh;s?5E=yEhVu}7b$-I1? zKjQ*9eSQxe0e=665Ai+uj^c_?}!sWYSbI;$y{be`CH)8d#|K>57; z!7QdED*i0YeN$|2@6wgTk7`Ly<*J~6SnUsBGq-USHMlhh!|}#!s%8tgg4^Um0sU>? zyP3!jSS89*H6%t-0^GuP8p6#(`KjyOQ`On#-wsmfVZUH+0^$42}_SaSpTkN z!Sy-(@8*+T)hi zqmj>P^wn0DipKn1c3)D-H_NXz|8jdZMrWXaI-a}IR#o0-+A^^~k24C)x;(}z0dOBW zFskt1sw;qMHo*%uPI@srfSuLkG@qY2f5((AAurL!n9O6PVzWJ$b#|Jp8(tn&xZZOa zx?UPpV%Y&Cf5()VD}d~$OyPY@{*>wVfVbuL!ePc_B#kC7*JZyPK<9l)CDxZsJDwj^ zVkJ5BV*;IA&w0HRZX0||c~E~hl@}TPbFM%6k?z$=g|%BwCwF9oKi!rY{$xv5c(^`0 zd}%{Y_~M$}a8eZYyAvb`P2+yZVF}e;Fz-`~iSV3ihiFleKdjA#$};^9Sn?d34^gcO zD)T|o^J5Pa<31lfw|+MSR}drDwzT-?4kN2#k9WMF6*y4M!Z{uZ)X8 z6CzMm^p$TQ-+k%fgFv?jfd2ie_y2jvCHB#dks|6c&aW@m_WB zw*GkKoKyQMto|Q2TY);k(eZ}h>_0(Z@Qo~xyFMVnSQf~)5r5^0K?rUlAfMPyjK2uM zgP9=T2BA91wCOK0=52yd-SdojuZK__*R=<@UCV$4=jTFY3xOki3|p-*sLqEjB^4oKI3VVa9%>SK{G$D;QF(_{Zb*ZRW}f&Nk= zbsU%t;a!41s^4qofnX`unMWTzv-=WzvaHwm<~9D{bvZXRHw~|EZW`vc;Ua|UJVWe- zqxXG|HsXT+Utj7d7-6h z1>iFTIysMSPS;$QexN@Cytrm<_|k?u!o&4z!k=upJ^bmm+rr5mtHZ3_qTlhiLNM@^ zgisyV3AF?&f615^hS*yWBJ?l544uAQ2<`-sV;9+z@cV1%17C(t{hh}R1$66|p)+=o zeFR@yK(~AuI+Hv8Av|19!s&O&4T(be1rZ`%iys$0;@`W0z>%1+$F2q0JF`lGFcwD`Rsmk~er$44skd(-n1MNGfvZE*J}lUs>5(KyQF`yKD> z>v+z)|0CXSF;utumr125%a7c~G|cw@(vt&G-<=SatU!U3Jbet{$T^|p>DkikS^lD; zS%01bvieEu8I}cu-DV${;D~eooysMH>BX~3i4<`{+0#DaOnBP%>^o$G!3F?%J%sA) z`Zp?4`~b&U^hCaW%2=B`Wb@+*!J9ZGf_!N7(KDraaP+{(kDe*{CHD^y;p5&UfWCJ4 z+1L0pU*uahK#oz>_R?WV|Mo-D{Xjy@i!^5jhMOI52j+dCyv1i5#*oQ;Pfhz zv8NEgJzD~qW5N5zvEcpZeE}$YdLRSj$;PoXgWFg*&HF9o_WYYqfC{emAmwwDiA5I?q9;0Tw2`>n4NKR!43=$S7Oz^@B_{7v%% z!@nVZ{JQ!3jphf24->$I=!kqEIwP9sinI_v#>LD?g#bq$u=i z=K3k>-ypoRZ@Q_QrQ07K-UV>PLHxK|0Cejac#X*Knw=xa&kvgnJn+5lf;%*%D{SB!c8pRQ5GxbM>)@qR6- z-}m_stCC7`$3KQIxB&J0DsS*dc^#h>=B3u|j?>raYxe_<++XEI_}ZQO>ZThZdO^SU z@Ks&5?N5&?{O@Gw(ue|?KZT!>kzx?;cq?gqg_qtwOV=?b=Hv8y+ zAPAt}4|&!Ga+ws0zA6kKtEzBNs)W1ELfmR_NsZVg-Q(a{$~`L}-avKyGq7Ivi#Gu$1eM zavG8aZsIg`pHvCKQW50lOYEbv;A}ea9%=5oc9G$Q1^Rb#{;1vfi-%zN7hD&2+5EUd z7(T|IIg<5fb`v<-BtZ1y8uR|w8sq*~{e4=IgAOi+P8ebz0nDO*SPY%|`_`MCG-3Sz zB!uQubuo1Q-@xxh%l}^dHt9apMh~Xp_jDS5`&0ja+4!zaO8md$zB_9F>#c1TTCtx+J+gmF^Y{Oy-fsK*@Ant%%sJ0_=6OHoJm)#VVJb5JbQMog7Ga@dNv7Z! zm;?)(ilM4!5{Pejz<A@r1B&qimkPC73A+ny6 z+dR|5!Kpx444eaQSNySmJyn!(ve7$Huk{p&1#!p%Qk&(7+!L8Soz^{wrz!Si z=xd|jk~=;2qpb+UT0F(eo~I>({|uKF;t+_<>%p(br>V*_95k@G#7s($*cean6t5kn zhTNQHqr00uBW5Hk$Z3DZMpRZtRgM{c3P-rn2OoR=3Q*&yS-F98>-E3d$3ih zPKLft&x|nUK&<7adfBtoMDXW9s&?-_<3SdJh8`Bf7(68Fm&s}@NZ0H_2b0HSP4A|9 zQxOUUSRW7g8P6C$UpM&Kl7JdoJm6>WtVp|ux1GV{!Pd>>p_uAC%-$pXXvZKuShOf! z%1#t^7nYaj_TrSB0>p(Jmg4)LWXPs>PjWH+HWhX^>96^Jo56K{weZwguO?QxX zcA$)7{wZ1EkwBQQE3*iMz2D1C@&48W{_nuQW%CmBRgst5}%%3Gg-<#30 z&Q0;M=S+{I>%()X2`nDkagP)vi?v)w5;2dBWSFw4{5SK?YgYL z?s+8K#Mwf}%pg`+1j6hd`&)!~Zv)4B*}Do0kYh$n80M_q2wS{%gtT1i@${&;#VPa1 zqQU3q|E%#ugtk}43dEiPedWmFeMZa4=9N#eRk;nox*WxO+5gWWYd3p-rUv@DVnDRl zK;NT!{nTS*a^KJ?|JKrU2Ui!#;nG6+ z%3}rcwGH>kku7)26l2YQ-v)xCVvz1CYFQ}l9HhGrOfpL$jFh@a{%JP%dVY}Zy6~D= zT033HEh;b1-8D#eO?=cW&F2Nj?FoWo#lW`H2g;v3dZGNuqZ2EhJh~qxSmtbtDXCvH zq2z#R#^eO6b-`_^=?fT zd;+TK(_A^9+M3es%b;raAl>ESEYd|^Q+j>cq?{EMPadt$n3z*PJu&BAliO8~5{v3@ zeJ{NULDgrd>7jSG@+F;jK~*LKG3k5%I{AaGrjqwjQoMaGR~5)!_Vif<;tFG}WiGf~ zpV|+)a=_x1Z#}8O$VM=^5ShIeB#@cN+gOMuc+Cii7RM*Xta!g8Y4X1e(p^=9bQhY| zyrO5ib;X83x{Lel_)_*f^S_QS{rH9BOE0{?eKP#(%PY8F9bcO9udOQ>4(^4`PhO1s ziOadL<;e?MV@l4TiIu-T&*sd|6=x@{c$(pLVOCQ*WMxc%wtt>G5xy~F;?=mt7p}xD z?))UKY7V$vzfRfNc$!jMWXqfKmB)}AF6HFG)kZ9eLArmU;J9SOPHbL%CKjq{I1sHY zb_1|B#6n*=CpeT?fwWkF6qaY@3JD;#MeD704~d}d4~*zjo1wQCDYgB<0_|)*^&>7- zlg*)6kSJ#jfd!Z>E>tW6AvjrKI;efbkd zRStDeta#$+{E8=z)*-Xyovkq?*^4HW)SG5ZE=;v9IGK{ZV8u4BB$xsV-ZM>`oPFyD z>GfzrP9B<6Id^M($v+!bwUME&OadbyUQqFRd+f_7uLQWA% zD0<-5chl_{surQ9htf<zoD+}@7x_I4xn-Ms^PJh;CVR=@r?wfR8M7B8Pp=5!K%qeTPO)M!e z!=kSPcSrnaJn>cgRm2Kp-vqbo{M#|Nv%clvb`_Ur<+de*zxOgdScE1?`@8H%y%U7p z_1j`fn!W{9mvKT)ad~BKe0g?mwlP;2z;=bf{7o|Wec*P*0$6!u^}fKRcsnOUUm3G| zVJenS5XfaNrMrgXy?LJ#yD;3d5#ODMtf7VT8yf!*q3!JZj&mvAv)HQ4M7;MUGiqSt z{f$za-3e6%=C3C||6^KN^nT~xjyV(@q1AejuG1v5E(U|a~G}iT6U#lI` z?CXCRKI{$oYCMoDk8yIi6w8CFW8}*#O~!gCC_Sc&zbO#FU+8A@XXxw2?%i3h)iwr^ zd-niF3iDOzCV>>ZR@c}V1MRgHW#K^_qYPoJOw9mkv!^s1z-h`39yQn@HN^e%PaDqy zw1@RQV1>;c7n|8Tr~-Wd6&5dV$p`77IOxk5reYGagIMTjL*d2MlcD1WT=;dnL*F|! z|6oRm{Ed^1*@^H}`DEx|ecey1OV)Dkr7V_Y?Z@XUT-Cl^&sVUclu8SwVr?q#1$1mF zKS}6deaj|8N53X>of;kDL2#5Ehx_ceLREow=5D590pwM&J%`1m2{9nui`=eW%;)fP z5~nsH6ylG=ea!!PQ-s_nkHdXuvY`r7D%P37UtgE8dCF@i;(7IS(DB2!)#CK`cP}KCCkyM5hTP zPFqW1JVHuj%W;ifg+@)^6Ab=wsOrJ`KDC7hX$gR}bgN$9ws3R$HxD$4pAaqRr`(i%fbg;nra)=9s|GX?1duQpofT@!jPB z9cBALX0dh%XDJB?dD-}06z@&sL0W;_uJhQOlbt#K-hJ%w!jddZ7ZU)UY z`WfqQjJ9O}9kmk$Er(k{+I^LiYbQcStG>s%3$l>pSfH)L9)u+p>5c`^pq)?or(|it z0&U&)16UF-{qq87V0wCO1Cnp1r$ZPimkeI@U``ptSQ)^avg~KWz8}Tvdx;MqXa_vH zUzQHvm{A(1?|brb;7>zVZExutTCTcPY2v16`#-goKQ*TLr|f0+hu^$8d;&xJR3wnS z7}}@Bfgb}{w_t%x#n4_BClEWbhFBcPV3%q8Nz;t|q$$RJ(w`c$TBhu^qqNXEM(ZTK zu4zw%iUSj%eQmrz^!20^Wj>D@W=80uDgZ0QxLu~-=zF7V4t1P6w$%O|eP0yCxR;LX z4;}?*=kVzM=r4H?`K#5Z?MeFns5uV&cKpTrqp3AJ8c!JeqxT#8qi3$~kESYf-->AY zFO0TlxG7qF=aF^0w#H%KGyvFZ4Bw=;BEB;mgg$)6 z-N?qyzeYud2d{mXzE3#9OU6Ss$71|sd>Y}UzE8OM`aYpNZl5p(0a3JlLPxkQYM*d~ zc4PMm$MSV#pD^WyeZtSr8`EVsMVb0teZTKme#CdPz5J9Ift=uA7k_+)!~>937}{;T zKt}pgE+w=UgE)w7S{>3bXAj4IH{u(@smdAljsx*e&pi_U8Kv!)Ip&w9XmWmRn2HUL z>bXmM{x|ipXDseG#tGyCrM8>xajuOO$PX+x?tk_^9J%f{R1C^V4t8a?WJ?eu5c5`$ z*8;TjX5EL6*j3RtJZ69Ml9m?;yLh8t**3i&^X04`qtVEo=6erEY~S_``;J|vAHV~* zN(i}K+Pq2I&*9~vViq$Q`#6}BvS+e+6R+e=f~w;t5Et?SX)r;%md6$&Xy>yRB?x37 z2HHD+1AUZ&Op|~VSU@~sa=U^akT{gmJrkvPd$2v{7qO@z;L&rina=*-Sk%zD4Ep#O z5Cd_}11(+PKbr}X0B#qHdCs2eTGIUNw+_5~?%$StFBUb}W1y;qV{-3y1>=Q|UfSu3 zpXhc`J9N-EAnJN>^v>e4L+imYWQUF^%=dBNsNRO;>R3j9eH|^br9d7k7Rbo@*_g4> z*m3U}85ire+C0(iQti+YTn~kE@@M>LCKAZ3N@xfm zgI*H_tqykG1H-nJjKfZVl?i4 zN^PAFK_By{ZBN@v$lLR*b8SpsCtBur0G9Q%lFdtG|fgIZkBExfJ&uMxp^{MApIBK`T!ZHs? z0~>$@^W&v!nLuVEBn9&=l3JN8tNF1~$~q*q~)+J zv;kpb1?QRN;&mVuwy^(sxey^KejP}`#X!m*WzXVdGpasRfT|Cvuf)ioJ?kVjHi4)f zCpohe`abi4cIVWYH0XOK2E=axSWhC}yYE2#Dev6<{odQ&>Cc%|8urdT-=AGm8ZJfg zp`3TNpXxn-puhLiclvi6INv`L6|~BJ00=|8u97Pxy8JtFZ-n#SDyE}i~ ze_;80{l!~L!^<-S$GdaR_gACDkT=ooa--s>S?qqs34O~r5YNnqzLznGv%&2OtwbHO z0IXS2@YTz77oQdL;5a&wHxu?d*{}lI`Hl<`{&fZ+yD5SYI)9_3;j(f zF|_}^ou?ju{MY^OeD9t9^9MfdUyGJsS!)K7^_lZ-{i!F;ALwT=-+lL;{>PoA;W?k4 z@2@;wdX)8j$Ml?Q`DX{7T8oxHJu?o(`cHSBDno5MHzylKJnfD^G|%%UyTw% z-U)7(fQp}CRJ? zx9#uu?tHJ`;w%mCd;GJ0UXzjd(2n=EyOaa_p8{0$H0q~fZ4_O!^Dy7LLz+I0Pi>d! zMP8aN*~UFrFVheBf1j+KagC;L)&SkbZ%@>6j2V1`rx*Fi6e-ro;f#WPkpC1*>OLU! z9PglAW=CiBo$|*?C7O+TIUo7ctkkEr7CPt#)IqnP4!RL_sMV-Lo#iCzt3cF{Kw;lRIEhU8>NLZGx)0ROn#yh-VHD`)XqaVh297qYlK{$wCKf zTbl|Ug>|rq!DvI!9`xMfC`Yh}#l2<(?G}?jw4APOAP4u^kX*ttlP(w4J?LBy^auz2mS1>5y7}RhKV4)BPlFC819VLf~hN;-4?H}5-{fY;1 zYIj~7ymoAeit0uuVYWLn7R2DI?0<9UEfa`YIN574fxi@)LuF17nGay^3SvO)^$Da9 znZ0&o4s~G=)z;;XS_})-1p+wJLYGlo7$Y)RLnxWm(4fTH-WIZ8s*Gd{$%w8=*zLOx!Y8w$K-Y~p0s1s zz{Aw*ch1{Q@S1jB@J)g6C{3dwvq#ky=!@q-d>SWv*}RFt;7s5@ZgRU?F>08JwAg6# z$=_|)>ijg%)brj8Fm&6^(5DPjQGJumebY2tC^se4tWxpH+fMSdO4~J@;&hyz$EZQ= zbP}_HSM~^A2*f-SyyiwAX5*2X;d}@o5bf9&%KScv%#NI>*pzGkIaD=&qMyewo50WX ziqRqa6Dsm3U8B#*kEuqB<1zZURTwp}cJMK6*Jxsb*P72!v3eQ2_VT}gSp5+6)y9BW z_O!i(%o9i(o|>Dbt=A=c865SaBw5|Z=q5PSB-Fv^6g0!PYRIcxklWma{5|=x(!5F37o07S z{h0GN<3BIy#A)FJ_~CFC5=izsA>2vtlz)xa zA4MP*YImhf(ekp2P^!16uQZq0J7(ifR+MXZ=eo~PkvD_H?CQ%`sn|QL!xsKL3VYpI zD*op%wP|yNBw&ah=Yad24{!LZ1p)_($2Hba+1I+ z?xku8A}IjY!OU@I*|!Kp%^y9>zHFs_ZaZ1i!(_$wnwATFC{TjP;7UZ)V&mNQs{;9F zj2bS@bCOQa)ZC%jPNMD+$Xd=88o5i4>Fk%D*DeNe_@I7XTiaJyZJgI$gNRy+NZ|RA zHN|A@Y*BpEu#dfCdZyxdN8pU0*QhuLP&rumXATx#n(ZXXoL-+@^JQNF?y3>E zI9YK$5b>$!3iR`Cvz%nb18fdm?ASCB7OAZQd9e$mCd`LWBNbl;urgcy%(r!0-G+2q zJ!IJGNyhuP^7Z#8xUuiknJu3n9Gar>afT?;L8N6{Gg_FGm%!LR4#w}3s4r~<&ugbnH`lWCNwPuY&7$z695@ zak%~@iTeIXsm)Q%VuUp1z10!l;8kiH!uFg&Y|p7fU~TI{{>z&L(pl}0J8^ng?FK^E z$2u0q=rvFVHVB02P7~9e+d-_2wR)4aIw;A?Z3iR1Ahs$@mo76OoGFkj#P4m!4*3>H z_O{{laKJ8*bJ(g(_>lT)J%XdzlNJtsBy?mUJ|~Ea9d-m&gK#wZbh*W-2NF2POCRUQUat#cUH}bDcX~6OBsgodE=VX@ASSe&S(!x&V0(@y!>9=orF$DzM|?bTyMmYXx*(m);I&|8n*7Wx5Ib3HWUT9{o>&Lt zds~!EJoTzx&w$y*0Z+QDo(Ao_NzZx~^Q0)f2sJcSEXob6Ken`e&l#Y*iVh@7y_qxQAi(0lE60|qB~B7d60X1`zdj!Hekwi<7HZLoUfGp!_VKq~) zk)g1-5xZSWUyZ7fF&mMj#X(g{9|3zI6FtiNpg})$%xe5 zAMvSO_vm_xon$+M{Wn2}9TL74>>rN6{+mE9g@8Q8V0-S?VgE%SPu?H#9mWra8SFOC zgW<0OyVQW)j2{di_N0Z^Fxa@*!DCo>X|+L%HD8YwMI-pGc9KhL5V@Pd%rDaMEpd`% z_eXp`zgPDidG|+rNcRP*;?I(m;dCSc&a4gJG*>XJD=}6 z8u10<1oFbsh_5*x`S%=+`2Mnd*!N${hkbuuKI{XdzQc#|urH7#5Ut zh;KK5bqRoV7l8G70ILJQx)Z=!4`B5ISQi0U>j10^jPw7OFeu*vu>LE6)noi#!Dw@? zz`_16GwXKRbbrKGV7$NE_&bn{2#$ioaCrO0VO?(Gbh#N?718c*)7ppNhW2l=_MW>P zS+Tk-gjPj-bB*`68GqY7Y2oO8EdD<5;;`=<0M`4NPrz$(wLC_Pt_T0MD&o7(Xv=hl z8yU|7{-zhl>dgDASS-j(3>OwRSd6xD#^3lTT(7-6?7Pftk_Y_XetFmzSS^rWy+C~o zpI^K{eJsBCR+G-t@E@peq0yIY1TsGg{{*8R1^Yj|CJMiN|UkIGmrE!o?8|1nEGAsZ~PfhJ|H-f(3kJCoqFWPeYTN3wc8Eajo(|lZPl0T zn{`d}U&1DZ`KK_(${^;n{pPC}DeCJ$vJ#=a{@2UoC%!M8Dw`$9@80!#f8uxl&|iTP zx}WfW(q9zG-;<5_?$uip_vS?M_fXCff|(#z#tVdofIN!$ZaU$aQ27K9SAB5jA5SoT z#j%(QE}{?aBH*4Y&4j!U<%+erSFP~uZX7>rZ^Oi#2S`2bUJdiF9#Pj)a zk{u<4ycr<%`kK=15Fc6wAoe0yoNWTh{jPBD>`%At?!|WH@xHC6KgIFN1h9AyOoG0m z8jy}5IKX(FhvGvsQ$Per@CHKyG5;%s?ZAgxC>2`)thLJoN8JR0SR&5TEOuUn>Kgy} z-_Tw+Ss**^28lfjKMz`Mv@1A9c|fbLH$|EG{IG9zoIo~xqSsy^7?i88!u9k2)8HF3 zn&P0Z41uV|f`0-^+o7E?M7B`zd|zW_JhWG5K;N=B{cJ%Afb}!xzp#ErJuCjB#tEO; z_7-4)@SC3u7o3ImbR>`~JgzZV3-bj>QIbHiBF@uno?$^d8cR`1Xx%Us3prRE#CD|!o4xUs<+(+7364?} zUs)5;&$il;Ii%H91hBGiD!)cWCL{UR==HPoXDGD^$xOzkXnU?h!_e^A>jGJOl`dlT zH6bzH`)Pih)Pxd42Qol9&v=Rwwe_Io2<~7sm<(XO@?X$iU=v9Ad4XJgRUk}{)KBP< zQ?X!uVqn{D_!u^Ph7*;9#6<6Vlb{b!&Hm$*iq$AlvsINQVK$Oy^>00$-M4jjIWl(_B=X+b8Q`y8$Mt1m5X+H8!!bJpr2QEn<)Oq-(ASh+ ziV`&0Gjp)GGLnC~`CZ}ON)t$oW{-cmZTHT;t*1Z33Cc=j)^N(M0V!a}Uo}e5&I}i! zL{0t*w?nuT>GFs5JW#?X+PqA!nXO>$kDUUsEg$>qI3&eqfW+SlQg4?@+Vp+tRB#KB zkM4TCU(Exe;snWzghRIP{-Gaz3>&UtyOI{~c5U*1(jQy{#Owr#?*WO)rTWT5xnLbg zg-(z{nP$151tj&ASh+19`OWL#`Z&RRfT){*s9h$B^$%_Y!rq5wS!HtzNc?e-f*XLy zU7SCA9ccSu!6qQVE{l}q1Zg%B4rTX%r0&u23sxKbR|AP>@bZCNhcnM4tFw&nU^uY% zd!ydJnjjY*2T5HIM9q(rf(w9{*>ey3HYD+^{b3+#36Nv}E2B?fy;GwPqY0zKz+;HK zQ4;Yn`lzi%j)If0Xm6@OYSRVsVjN83(bR4}lD~)FYTIi^(?Y@j1hMQApYC_VPBcCANTwBKx8n>CJP}P0(txjZBI0TpS6F^ERZwE5}L_@$llcx+Wwr$c*g9WQKREMl&Iyjok6^2SKc?D zX#A{$-+KndhlF7&{vS$hjfnzj9HQ;&tJ=N>F>n5HxD=a1fk7(P)d-F}6I2ClP3ggT zs6zk{(>E^(*KSDLOY_YR+G=qy`)GDL9efQ)tZm(fw7oSZ5PP@i@D`^CB%FkZfQ~Iy zGa0`G64>NkicD|-ncYk6X+S`5yWZLt@$tY*%$71e4|wb{v$Z`qT~Xr@Q4cfU0SD|E z&|x!CUvmX4F7OBryJ`AULIsEg@dDv1pk2)rNRZ>Z)zi+7obQ5E+5vrKlR?ZXhlN@B zAbqnMWECS4$d8j2^3<1)!8!)lY6I6&(AI7Puil8OZ=b#o!|)AkK!o8K*oX+jSKWlj zg&67+rov*iR3L?!LWj!n-4+9v69A%`;CAI9zT(&v5U*@OiFb+sC zSs?00M3^kh-rm$0!az!qIn9Nw-2fpD2)^mMd!xv3P;;xgZ(Z!`QB< z)lQERfZdwg>EjM#ttD>N_?Zx0v~_;8Y!^bC`;4 z0PQ{AWwKT$KLQQS5xR(v11Xr`c4fr@DaaH$?8scv3?K&gIpu8QPFi>wL?$Czu6evb zY9~OuI&0)TAA$+YcM7Bzn-xYot(HTwKw1W=80fM{F)`GqZgCR68IF7pz&euWRJ7`o z{_L$qdvhYo_7p}6y?Q?&XIFt3{Kz?$AMpl1a1=k{M)@I#AOKi+qP{sJ-bZK|}kluKKuy4+uzoRi&3Z(8nod=9hTJ6CR zK9r8-gYcaj`S7i;z=y~+oe#N;{)R3F?$znsb}zK|zT%WMeTx%_Ugv-htqW6;>E5b1 z>Qm#Lq-;5~tH}c4O}sa~Z|mtLoURK3GISb2yLxz8#|eniU#4qa7U?BSeaf!{nc05k z``S3cF=GG2uM33v04C4z5$9>f!|aq78lOfwZOWEFJF``H{xV+8VcAzWOlU^+rrJBZyspIoWG@u z^Pk02m2-B1{5%aB+^KK}!`+-B5Eg^5_gcJ*@;+?CCAlZ&!NS@YILH_3YuaTo@ImyN zwleGca+{|lHs+&OLugz4m z@^Euy&m-Xiv!MB!QUqG9;NF!2$#x=%wI5j*4R(UQCd$UfZdX_~_E*+|6!1)u)%St4 zEAL=5Wpw=LrC}e_+cvx=H#%k;SqoZzU&J@ipg|RZt#>Q?} z{>@~X>E{N4oNdx&`iJlT9WtGdZz|KDE6@8xnaMMgVc5y@eH-a9Putt{NSfhaM#fG2g7Henjko6d zcqPVoV)y{aKsUes??ik|FDGAxh96v`3)wt)1a=_bEcN8aN#A>M*r&D@IKs~hq!z=% zfgyqXk%M;is&Jida1**6gRykG)1aG%?~pJS->X0tX!yoSfi9Dzz6s>ei^IOa2IGE@ zjfl)f#iBX&cZ;rIFPnqfrhO0AgMz@{);V`HiE)v$=cXK^N*la&FqzhKl-VRCr0*vh#W zMAiqH1vzk7AkSWb1_Z(Ze&X0T>$nkToj_ybthdmOaTXdEXR&!S?J_xNW}M^SZWdon z`QrG>X@ds0?Th0pb^fR?Y8&T^ZZqle)s<%v`N9~>i%72r5%qaJM*bKl+~AY0=0Jnm zRpjU`b&}xvoA{*FUop<=GWJH+JIUIWQ9fyn;gd>@IBSnU?#6~s+Nj^Z!Sp;(Eszh` z{0b*X^jSox2NCLJ-#0zXVkG95e*22ym*yFM$%9DXSwvLUu1ohzEZ!Q4wOHJx#amq# zsrR`riMR4^5^p_=#>87Mz7pk|7)^~kGqjj%_GrxY-n)i>+JkQNPkRyRX)>Ni`zWuI z^t{6ObZlv$6_KFNNm%^Fe6Bjr*%2spFYTQrkl_13g82eb^AjB!tr(r2MFeV&FJZpy zdc3tyAkg>xl94!!(ek>#%8b+cYW~VIJ-lh}7sp@cS44aRo1Emx3}|P*V8r$Xrr&6H zo2QMnyMJ9V8h`zad~y6$o2tqDt|*y5I9BF=Y{>i<#9%j(`I^i0VzkVE>x*T6*G*)8 z7nAw3m+8eZaafehx317+e%B2$k9C=^<8ChV$v2aEoE&B`6q9-SD?{chZzA(rEH*vN zK>#0@dprg1UT7DOhm(D#%znW}V>2`g@l z(abB17%kq2(emRY6V}&H)c=Tz(Ts5uzhJzGb#GLR_V&0KtsBVi8NOX6iOsLrT&J*c*cYHiek(@g zt$QQBflC4z5NNwP^!3I*96k1>abphw=_Ay3WeXyN>2K5;l^MV~R4Ndr<1DVLM^SNI zDUh|5R3wi%iCU?jZF!l+cBOx3Y?ldyn>aSM8~CLW+m#BWCv$9UHz91qc8?+QXT6?i zP7vF3Aj6zPyC#0&*-Q0Rf%N2?C0Ga2GmOuzMS2d;Vk3v=&aaol^PoZJz+xx4bSEOK z7*F%f5|d*!1mq7tANH~N8PnN6X?ekLFnXW4JO(c2fZL^1%*>trgS&|Ke%yZZYy@O| z_B;qFLcZ6A50v{Bl?e`h%dU&W6^!0a*bMI z^uEiEd@%9#aeW^8oIVKaeO^BN!9=Af;(H^1*vDjI!>bYP?-Q>^d?Pt5WC(~FmD55V zLnHuTJquv{D}eR?0$9&5{&W>-c|@vN_g|NmM|{hTK1CY;mg{*&@%lPLXnDl zERSgZc_a_%wx19CSX}X3J@rM~$=2n%oh%)KhT0K$D+Mxh9K4?|*KODcyeSMGPLQ4+ z2k&_UUhxn#{0o4Udv@42!m|R4&a5osV^T8~iLY_*r@rdXM2}KK9?TXV^C@ z3jU4}e&%C;R#dxNqxjhtqx18gE z`!k(?Gc~;!7Wa^NK(Yje|3Lgl`5MM|{lw#YX4F zby=h;6ZMVeZ^cPZn5d8W&mS5!Q{T8f;?wH^M%7#NfKk%|lq?h6XWt4{ClH8*gY;l_ zcIFMW05f9adWAe}%R{KDhS}##kY@5iq~=kO0+}F<)WA4;DB|mhg@x7I zK(4j`VLCeUKhw+4gZ-gAY+INhkfvqu+ATbYi+KGGz%ow1BdjbHa%}+CEJ1MW0JrPp zWx6YSj!9xMy_mA2(K0|U7Lkb(YwJXHjc2h{VSU(GFbE9^0M?&Q5Dp!S1!>7IBEAzA zkiP#6$YmTDwNa9<-x(+lLPK@M!rbvVGCww;>ASU?;dz$R?=h=|Q5^ZGac;TEIBF(H zTKoqf_GIdL?rhAD2B2XhXZ2Qd;5ciXV=@2wCb@TOox0y-c>E9VVc1bTHs|gq#Svfg zdXNq$0g3(Duy1_c-HmrZfRbX>^6Pf-HFhn(?g)bR@2BgrQWKY=-4{2KD;Kwl`q;A? zO2xIQ0{KBYkn-Y)uWXs1#f)nw3*>vn5#QQafmFu=2^cjqkZEkb-%PN7_>aadAl``E zvT?Y5D+;&q^*nT09>r-val|$rr{q5@ldHLukf6miNLe>Q=hr!n_ej}TGwj>=D3Vy4 z3`)ftzwzdEezb2~m-&_J{3H~Ay;>qa7yrImA{UFkI6t$NgNq~he_4L!UyHt8erCl@ za38_*_eD3)&-{;~h>dn(e`HI%JhUFj;Oa#A^2!Nvq>GbA>X|f0)iV*WUe9FEsAr;` zn^=z|J%4L0c=;&2IwwF(zm3ZVj$`k zAZ;G(x2!{w86oMvtAX^+vdCs69I~v_bI#;0@b|6+lH&xa*AAot35R-f2?fO&|eJjP$Yx z`_EMhmD`N~6s@jKcL2ctnDkT!)s=H3^8iS|BtI5sDG9M?khCJx@&bq#PajZBK&^ zHeVXp2xRfg5g(h^F?nqEES9rnXGfc7O4$5oSTwi^G&s#3?C-($oV?qq@AbbtB~van zl$8OZ8{Dp0FGqZBD}N|o!=Ts!I?6dd6nGZI=aWGi#CC7+7e>Nujeb zAlmPNqpfT{kCQ^n5NP)Z^7p{ee>2+FCc`53Oy!`X07J*m0IX?vTKAoF*`BgEkj#;7 zr)57J38HD;IT7dSQpAS}YHAyMFKs)Nhb$p8gm)*+uWL-20PSjI+iCtZ9Jz#(l)%8Y z)4eSb-vykkRIstY?PBm59_z1Car_wN?|tzY*7r-qr&(eJ`omW8Do9VcxE?26-oq=wfo-y)&RCE$^2Ar5^wch#L0>sPYc=ahNHlN zSb(Q>+xxga7Q0=o)@zcC@WcFW=}{(w#woocw12}RGCo5q*QJc%M_9JZrc$#t< zCu#5QC}ec7Dy*#lV6{M+*F3OochMy97bA0bHL`@-u2HcNo4fN+dZ^$U70r<5Wxum0 zfs|JReXUHtBFj!E@Ke2J6G-(=@aKHGb$4Pu_zMQMo&F44ln~~-dCYf@;LuW2ec-(e z@E@oFe@#u^f%+QoKS}A4ja2wD+s}X z!<9djKa2&b04H}_BX{jN!&yU_DiurcSh_O!OCt2hc}i_Jqa%NHl#XpzZloi=@{glq zLlhm44^i z4&1I^fZOE(x2xtd{U9SIL;9FfTl8~nFYen5rDfoD{Xdl2f?R5-a4CpKuq%9+OZ8T8 zf}{9WxUbres!n8rxMGm*dhgGfQa!-LcQ;r5sNS6DbtC(SWytN)@b=6Ix8dnW*B=B? zjcZE3Y->tC+`3d|-`LUx{uk#_-x35?Q;gg7F?PGwgWJV?)%F;->wm?#UHP2b)pMC1 z%=nkZQU|5B6R{u#ajKHT{0p*a@D)7$D6>~`MOkiM4OIP8TH(_z0Ad?X*6u{49IwT~ zW)t{TE;WSrgP4s{yK}Vj1C|iKsID;@r%m&yuf-UPjd4o`h;0>Rx%L{UIzAJ`wpl-v znZIIjP%kzs#fgs`tu{ebA*yTC;yOEsS?H0Y{2aKCH`ONFZ-pw}e*Ny*bonWUySZZR z42I)aI%U2B;^nxe^uwn|@hO={eQmfTT*K@!vU+E6V6~?~)v?7O+Ebuv<{co~6QRoK z08y*O6$P*L7kUk`=0;>w+;J4h^cGf)V z%K*1)7=iV~I625{zOnt(dDM4T6usZF8@z0Rsv0|pY~HK!;ZB1OeNYux2BMw4|0alx zr!u%*Yz&#<|B^YVK#_2$ZzA#<@fwt z>Z^~2H$#WVYxnb_D)y~>N^N5w^Q)7f%9#kFoTVIBz%`=>_T<7}ux@gSZUCp-Bs+#JWQxw`zw_<=C*T-cp63H(eq6g(xI zRa1Jj4W}LbWSH7U=xzSmRYRBlMG?)6` z9HzDcqc(VL3W%CL$Yk-OZVU3Zg8b+$AU0Q&<*GPUF(1=wXlLC5;zwr2Z@<>y1>*z5 z;n`to`+Y1(rN|a~lmk(zsK_mCfhxq^DA)Nv0nu)TzQUWxb&&xVA-8Kf)9o*?Pir%8 zv`;5)xzRq&yamLv@%HJNn}1i1F@6h^cjvI)*pU8&)+r1InH7R0PE>kkjlXAs^)ChY0ms&J9dTL6&rJzuN4s7aTq6uH){74 zC5N1pikGlWVb9puF9V1_!(iPQtNY5Ai2wRBLi&2xXa4!K=sG~?*W2(_`k+vic=e@3XScAT7@ zd-6tEk>*feycVaAZR>gB#Z!c3{}1O-Uvor@ zb#s^l>MT?R#Yu_j~40UsZ(K82`#q zl>PW$pD#<_oI`yj)ab)S$={=&-)D{?f9t^Qik5ZuzHTn{eJ4U~ZR2R2x%TGvBYh6_ zy)mrQ+iKS3n6zYEKbtrVmS@5Aob3rzO@MMsEq}`-LT~x0(DSA0L0 zwF}IpzQAzY;#v#%neOI43?h$GyFbsrklUy)bA)a&qcre5^!f3``P+0FIFZ}c$^3@l zn@;|fYH>@fUjI*GI5J#SY*v_^Xa6%@)8d@1sEWm_gDl?0_8j(m?JyOiZQ;2H6|;@| zAnGDih&uW6#8^TF#2HFml%(6M*$fsX)kOdeM>eEolU=PR^?3NS39hc-uUw;TI7c zNd&Oo654V)fYX&8Y|kmdoOjg)Xo&8A*pnLmu`&OA;I4@8NXZXnH#m5e*|R#l7NETu zPYFBOZ+yT0+mjkzs=XJ(BelOBca7HmZuXRfJ3Yx^24}%t5#NOk0tr4Z5S2>~@sYds z^dhr2i0z7?-?7~H_@f}jZ*S7>_+qh3eGN#}%=aS@cOrq5qQp=>rQ&lnrQvr`qL-pX zEti+m{B684+r--Q+I>8gsqx;*M1iom@h$TUt~~RIehyfxDf$Q%bAnq=S5{OUtwhsq zuP%hDW|JN-71iix)iNm+|8|AiE@8VegzXBWNAnOp^6!-K(yn}zYW37WuyuL5EEKlEWYcuxS2JR6^8=kDy z3#*+V97@%4SW=a5zog&Ie}WSZwR>)t+wkOY0H-KDUV)s&R^{Of(9l`2Ft^7OBL!9p zDZ$)6Wu6N4h5<1k@1^x$D z_4IerrE({p9#;1Np{+5FKXK4*$7!LmMIiEVQ@p8Kjk8qc(u7)a8LUc%XP$wjTZj?zS z5e=X+X|AKAs{!17OwxW#i;e_^G(=|ujUSEew1R7bzVmGQYQ~RAR@mKH0z5k#%#0eD zQT!SLIJ+I%4+0_d4RqK0tGc&I0yxj^@Av-k{?#8feFP_n9>n?}NN7CTKj%79cErt3tIGKvid?O8{*z1228NoNX zzsV)a%_SsKjo{(wIm}Fv6LWJToA@5X)j_5UziLmr5SMw_4xw)BamoMqaO6V%vYXWW zWgS}nvZG`4x#BN=6x=^XPuBkHY@WaDK&Bdx$=a&t^(*7mHzatxuZZ}W^M?){3Q7e; z87VPEm`tuI1L-!4dRCp1%i(OIL=U97#f#+fm6sD?CX-|Bxsm8jH3tNfM@Hj!zlBhA zIZ>Eg_O09yp(UalQ2*kQ*KXqaZE8NR5sZ|J^O>E)Hrcj8zq1h+#7gIa)UNSwoX2`v zBK26@8GSdE%S`R}IL?!UTa)1lTqqC!M$2c0Z*rd)qbJpTW>z(y+1mca(HK!ijFb7y z%mC)`Lw^&Qmg6#mC{diwbD15fg}3LFs5vezI`ypSo|hBhZh^cr-ku+c9so7JB{s|J zzJ<`4LwEBrkCfaPA-I3><;J|~qA{n&J75RtrfK7~spCBYTHdnB@!qyI86N&zJwMt@ z=STKpQ#=*l4Q9Wm>SZ-&*%_X*3=N&Qizr=~>5$ww^9j4!ZSk)5g7^uHl#vXiM2$$H z_lj<&OYUu_;qLZ3)tqJRw)oNOh;oniAM1nBk+#i>jKtJ@EGJf|Im?FI{fkG8h{w`) zx0~W>-0UnKH=Faas>{Sx5bSENh;+A`6P~N=@%=R1*S<1-n*hDtSc<1&8!ye>X}KiF<`Z>V z40ij6zn&NGWHu#Zep+x+@QjKjVN_>iEuBzJ1+5D zWp~H_C$KA1^uc$>d)sHne^{sLa1lf0*moMfr~ha8+Ee&`N0hPCpcHaiXnEUWM6uQ- z!fUlR(am*<@bH{`C#}o;tFf3oR`6amR&WJLggXRy>yr4weWhxA;lm%y>?DbB{}??9 zUmJowzf6YTa3{mByOZI6+L#Q3;P?E9s6JQM82u1#m>*o725%Mjrw5tM`QN`%V}Y4J z%W(XcU5W5M3?J^t@FDws2HTy*^Oh*JKVG6dMH1m%8KJdBBQ!>N8E@y^)oY(w+NW^} zJ_nyohWpx0aRx8v*<^V5I-;!IOv9{i-)0)_Isik)ZOQO3&ItbdJ{n#GV4eqHE(0)E zYWd^3@!gzuO#lne08}x1)`jnhudhvn9|c&LcA>vqIh&~d^Dt8VXJ2iC@3GASFcbc~Fxw5oY_20iOP4IW6##W%o_kQN7zTK+%pj6i;!mH+JzkdMA zb?kQ@x$p+i!rCcs0L>su+YB{EXlw#xaFEZ%;wyu=2;BBeo|8$5Vvy}wC_eleM4Uw=viwRCIbjDS7a0a) zb3rLZ#=+)f-SgG@j@as#KzbxucW8iidO8KsEACYHN%qp~B756s#k<>Q@9wHYLz{mB zA%)9ZVH}G5p67NX!tfP5)P-lq0iXu}^#BMx0JsMrtp`BY1CZVWkkM0Vgi5wnXxdtL zC|Uvvlf!Xb!0)bok`8;+ceTYB>vzBjZoeL+=v<=g!FR=Nt&i>g=OnF++KF-=+vUR6 z$Kp(Gi?WIGrzex)(p>dDw9;Hq@~oh|oB=@v=gFPe7J~$p#&ChW*87BO%QH1`J=3Sy zEIT(5cUdt68&R&erF_c{v3$#prHCj?DedEaIDn+*cW!gNO#o7!g(yEs&^|^7@)HP^ z=8{(CH=My{S=2#}I1^e+vx(9T(8pxBTOi69w#cOjdYQf!HxaiT<$CKWmDUI#v9gY5 zNW7HNK1la_uH2Cb=la1NXM8jBSR2{?1Vk(%D1HHyQlpw1rYTN)OO2px5{S~z{dS9d zfUV>4UGWKAAdg|Y{FCgO_+2FsocJ#xazrSMoy!HKKMN#AyVKuoc*g?gx6`?xu(jmN zB@i6vYp=rCaHdN0Px6S;iN%OyJ;c_ArJFi-ur*$O`3pM^1N4e?!y)k(&%)&hT3QT4rN}&J-=!Pf3?N0ZL1uN>JT`(YU>M!7-CGPp_ann#Co;xL5lBvC z7;HrP*Z_cJ09(L;41#C(=$~$kGu}2oYv(z+#LWCabS@~5@cC_)8)_2a ziT|pNjNwB0TrS~bjsTMvz3f0lIY?<=FQwK215xydDAg!0#%Q;RQt8)}TE#@&p>O6A zMX!TkW@bUa`OU`d+iGB_p6BLL&yc&3IM`DIL;Ukdcx)*UT~D9b4At44))`2d+RYM2oq(1?=e{AK^{w{%571cO5=8-Jh~ZzBPB~BCvcw3ctZq`Vpx<%aGu-^ z(0c+KWv`AXgOv6$`{2|QWjP{B8`8%{utD}yDzWiL1mb4!+K}E`i?~b%?FdE>3tM-5 zENs~^An-Uu{x0yrH0X2iHEf<-PiZe}$7ms9qKxBwxgJ4pT%$!b61{c&y?nj*Sb|Ed zeBc=p7d3j6yp#wt8gvQ$i>sf2h)V>eNc1n>Con#1v|#dB2FgBxD8tth<%RZSI9j3d zI$8lr^JQfApD499U69$_*lA5>-=fsoiOsS89RA*{d~Pn`d3i=kh|+=0gAN_!RA+U> z_RnN%)aLj|2`CmlQ3_T=aIa9nV<)pMMEP!tE;++_QV<(XP^o(}agX3^d3T;_Q<<#9 zuwK6Z>6-W(lyZJNy@|M=DTd%)Bzpf)zHP^{@@+fbKt#Ej(!NGyjIBzlJZVFsS4>iA znT06tC1`IaE{qwhs(yMAgA$pdpMH+bgNKrJ&o`y3`l)#}^c_r2>Zg(KHoS90Q1eRK z%D3$J44}83Za7rG3i`BEwVWusR(ov;^`K?y@ySapq`C?voQflqKz-vqFjK=Gi zH2svBnL8!MW#je->Za?bCM*tqpKc0kx(S`5(&v;~mE*NsCr#uM<(ys3^Vpval9)@B z(`7`73ed~uumcli5eCJs2c@wMBBeThe|EGOb?n%Opm%{tl#d1IW%J685P!SjNIEE` z0`xNd%H)24(!POoqI6K&XXG)Cx$rGqG+*l##`Y;{4$N@_Q9e#kjb>K956o$npqHh?aUOS}(n>sk`8uERd!tMS zkvxp8@?u{yoQI&7*}IMuef4UaVVoyd`I2FVQ%xF3Oc#~=lHrt`Zmdp(yYXFdqn;?@ zYIW~#_NiUczwCK`KRxhn;%eWWqvgG<2TI@{-zEM zMcUEOuJ*fkkJX{z-nJh_y4w~-PS4dvhB59LF7Yqki|ui`5ENPm%29wye=P*(uY?ev zcmH@(q{T`0q-pWEOt+uFc4rw92S>2M*^;Pzp6Q|e0FwVz2o@v5V2Re2wP^;BM7=%` ztpla`RT60th$7`MoW&R*kPJvaxV#vK+GeYH1Q~3m*XQv0V|TLkpf^!>h<*3!AovZo zJ0Bcv+kR~^1b;ue;m}OM?-|82nULf8`4uL34m*j!glZ_~;cTM;7E5fhdkguQ25!t8ppPFRw!R#wI=AGjsx~{+Pk6 zU+(ve<6qjW!^mMSg;q6BBeYr$gQLkqT16c+i1VOzl|YnT?J)HItq|H>y)ojzd4VX( zAGGhQ9%a53lZzq*Jw*uh6d|Ff2;rV0l-5&(bUj5Vy{8Ce^qi<5iXCUiNRj%ELm+!To&&*=3ZmrKL6E_zXf55% z{LNuKNahTta|&X+l2p15TL#zDy65Y)bwl%2(AP|-+vPT_+T~g0TXuW_(A&Z6@|Do% zKfU45=f9k^%Xyi$KsC0+m`-PSFq`2hVQU8qx5@hvv!?|zD_8BQ<$^se$ea~;lnFl= zzkfim#D>ivoycWAwOtkybR$TUY@)>NM46}{d(K&j(uB#Lk!qqW zYAxNZ7yO>460%3Ef*gAd_{2?HYzGC)pqK?YOpa~HW-LwAJ#R<(F-JB?BdYGo`Iq(U z;`tenQ&F=hFmb1Acas2nnsP~NlL=az%J}`J%BBn+d!Eyj2dz!HL}{82ZYIOSxKN&T zD};K>Hby!HL(G4UN&|vr@SGLcy4~qr0KvjU-JyvJ*mGhoDDgLOBm=;FSOA5|P^cDy zFK0jwYg?pHsY4*{$1@;@$xqYL>s>FV6NSl{h{>MoT1$7=B&qbNU>U5SlfK?k6ZAPQ zlBsGAo{hnD;@5&jNa<&PcXt^! z23mBm2e>{ZN(=M3leBjkB6|$2ExS)M-!GRasWG)LPK3MgJ^U=&zc>*du2#>-H?Z#& z>i6}F6XCuO9*^u5a$~yyq)Y&F-yF7%$mKTWp9G@(lG5J(8AP!^lngWf;(^79@L5W& zeeHL}yYSudK0J$`tvBA12($lQ(E4ZpuUVW3pMH%*01>4C0pELTnxWpevlrn%b=+#0 zslJylMaFMm8HqP~A`|yDM9x3-<4EH16%kseLA3~w=CsJL>8 zQY$S{K3kLsX91WQjEx$M)noLn;urIR*SyU4xF_3a``dq5r0P7(_sc-8)IM3Ay^9jz z9|D+nJeK6K7PGaoLhY0By}SLcIQu@3#%LwV-FQ~qx>&uxoTb&v=l2iP@9Z;2`)<b{r?UD zo)fjUZ3a-9gz2&}_094>T%WMkJ(djn$LNRf)>Xkx$nW9%vF++z>9d8PT)3xp;l8ve z^Se)WkV-|OblaiVkx7(hJMiYA7P^`%z}#0hARulEA(e0V?~` zKst%-@--XC_9JK}zb}~G{4-ZhIs{MR9QoPihg>Ttt^5|}IN$u~L%V$_J8*3tY5f30 zRW|rdGr?~vW_nDR4u|$E zsH_FzZUpcm4AOCIca{re&-*&aDHpKu?VtK~`%q4x8o>M&wmXZ{pn>_OtJ9#N6OcDk z2U0sAJ16(2_y&wsA>zQ1XU?FcgQ^%`n^*hSJIcnX8Osd=@lhSJ_&x31pp zLo)*3VsOsSBds5up_TJZ{jL2vXrMYM{|K3u506m^foZuQWG}Am(0m z##Sj*GEJEi+nXPDc{mRq-u)2gL5`Ez=PdAV*Rl0#PJip~bMigmFXZA)tQ%yWx8#!A@6xy!l1b9yem0Ni(YJF_8 z0Md-+`&~yiATCoMpu+j@k3hqB-=GHi0F>{4Y1yKC*}AK_#nre0`5-~1TUniNP{WZ2 zpuFQem6nY_L*vy@UV5HN@`hE1-V>nL(Ck&~Bam)Eh4Xv9K@EFZeE_w-1IpVGNG(WI z-#^`ed_@yuxE`df$T)a2k44OkRaR}?(OC;`Z`Olk zLB>Gmo$C6qW4(RlNC^ZNAo5PM1bB=~cm{cAI30rj`Meq@7&Sm}45LVtzb%t@A+JL6 zFAzG?Qt9IHRPFuOk7N_3v)!vU`>$`F0ZKQe*5Spf959)#0l#M>d|h8tX}CcxtNEHrN5Sv8i>mp2Qu4rXKSZgupV^eJ4Z;6>CK(l9Fvm^LuV|@i&0d_Pe2iPpOk;q)oLztH@rGuoN+yfe(Vw8$HZ6VrTyCIL<|I_IVlMSKDx zr?oTRTmD1Mk&^NW1{Ni(sqbo@h3V(ODL7^gPRjSWj>9p_yBDSM2&m_~y^9joRb%ud zyfHhtTJtZ&G@=+IB%((==P!?ABbJUG#VD|Y`yU5%Ly5<8Bj+2xPzV|;M)Fr@zF{>7DDS~t+cX}R{sdJy% z-0Ax9Cz0{nZ;PC7lp=}8S4QXo)eoOqXWkTj@!9sjt}jk~HAP?GTzRB~xWy;Ibr4`7 z(;v}nq5$|8iy|m_%okl*Gc6u%)ej)pGzTukqY1+Fc(i}suEwMNTtJbg^vQU%KYpe1 zmn=$z2boSPf#CmsIT8NV%ZYHbgsAz602T~q6J?<$178$fnyaMNfUhA(+==ib=|mYr(A#8~jEQ3F^NVAmn13)eCh9Y{8WVNN`*7(*d4%U7nf(6) zcfxw{y5U1g!&CLZ@7xJ1oS`4WnCZg2rC8wWf^&tSOx%|ii8tyZib=` z*y=Qp&I&|XmP=URZ2t;E{v_owJ`9h82`br9e(bdb zmGt_s@NmGvDJp!bEUWVmVPFFqPE5oKWfpHJ0)`1z@(d!whsC+c?^5}xPl z6ZQPw;O0wwsGB0=x8E3vH!g`x+^70d=a?^r1+FXh*23Fsu=+Oefc8f2#s0>-n*Mk% zIH^C*Ow%9gn2sH1`lIT5{f#fRx&7u&Hh2Feq8LGmH%`f$g&}BWd_~a9-*Uuu{vMyc zd7aDg0BWdaJ{5qJp8>&6A)nvN!hBBW$BKDupWQi(EzVRPsd!^;MBy^`?_6H1!0)kR zbL_ZwkL1%9my5xA#6T4G|EmH>KTjvhK+8IpUWXbCsBnIDGx(YX;{IuQhiyxeR{7H* z_~YXc@+0Uyiu1VMWHMNH975yRD$|xq*JJ6RJSu=YN~yI+F(7P1p1stP|{JsB82&B7=5M*nVm(v-4)cBz$fw()))2gm? z2nxp`1m`G!gQw95{LMDj$58%gTdG`-XybGOm{YiP#Wh?2DhG6a&p=D1YcHi%2Jeew5CU-$9;4j{ z$0lhPokF{4OQq{=O0B)=5bQ=!#dOW@S^MD=$k+-~BvFThViDPMG#eCqj(R^=6p1o`pjV$s6k3AZ(YdV%r?vF14pGc`xHcp@OjyQu6fSE0=P3s(bL*V>Pu%`&wKaO5YlxTwX4wsN$-wjzxK|P!JQ=@Yo=}mvn|2h7bCE(UuolMx{|U`GY9&5a;Ulo6#KTLR|hwXTk5puzrk z;2Y3^ig)?d!7WqpW;nC9>Rr)-*k+zL#1aq@`;WNoec(HaL6UV~o?5RKUsNxm?%&w8 zdG$)FewJE)Kbows*AaL1Q{ZE|RMe||?1L%rvef_l2&4r{#)4=`jk_aGtBNupXgmg? z;c?oRVNmZVGukZE&Z?Q7V!qK<_8-a(ydf9@ov0voOb5~lTrjxY2tgfy`D>gdpTSx3 zUQ`g9qXTIvg31@NAou{X1bW_XbnWc}U%vnnbVlvI_53~D-QmLN#Sl1GzH%fb(z`s38 z&z|ZO#8_#R@_QH^1_(Ca_QEMPf0Z(#h#L;>Wb05kv+*~tABE8Hf3p5S?wkRmb;nfM z=PEct)9nA4-iE_s=+NJ;Y7_EfLN!Qi{H5NtF1ru;7=O7eCTSI9K(Og3g!<3ZzQ5J0IJo{y zdqbt@3snFIHDcqE~oi;npjdguSC4KW+o@<5YRYAF`t=t5@T}jICsg2=W z`5exbS-W-ud<>;_RLNkUyO!zt>s)W9srcp}roB8Kp^PZb<|bF;)8Hd6kQx)<0~bhq z{$n+V%Q%1Q)-E%6P0vFW$$((VQ3%16sP||YvjsMp$w}T(2(dBPy^CCNuP&mLAom%Z zCqFNOnal4VRekw+f`)y}H@=oApB++VTBX-ISG5oM`l}~pxe=>=*$YW(W%cj;XnK9e z8mOFFm(h2tR(Ik<+RN5CXUd4eM%XtE>B z?-ifGc4s~KJtq(>_=?%z>{%xJrpdA<@Oumh7BC-H%$;qr@58`sa6=y~B3r$0CnEcV3&M){$$8vgO}t?+Mk1lw)N?xxcx|)%i5| ziV#Sh33Y$I^S9tLpshPZ?VZJ=Nh(FLUX}s+S`cwFUvSs!oIdhO9R%}HZtURepvktK z=aTG5hhUYr(lv%fnaStyj%HV zdXDol9Rz!HFw}_jvFO51n?DVt2b)`5AE3hdAMS&O@18;pv>ANhT(`4*(Jfr%w-(tJ`5HbXwLx#X;^MkJHaqt}lkltr=RhaQQll^aTmi!&o^Yil+Xhz^j z7L1ArB#QJgW_wrY$oA*J@5vUj2allanByFky5G%MzHO?TP-`3)%4hH_Ii-6U%r@rtJjB+J1u-^%)=(;))ohq^oW8YeNp7&-yVh0T+~n$j zA1)k8hu}cVLf2WWmwCR78S1;Wto?x`l}7%t#(f@Jz4x{y6muomqrGX!bE9(KOUWn6526rF>Dwzz{^Y=_A`}yn$goY=k_w$GE z>4){f;By@dD!eR>2TYFt;|PTOak!vw6%6t}A5qr?)!s!eMS~-UdqyGSvY%a&I1%>$v=gw0rvw=+Kj95Eu2200|MwB0`y^H5@ zl`D`K5CP0g2kl6QAhV@o*d{j#wg7`W=g#T+Xzw%N^Z!z{#Z8(&Au;-&fZnOT%S}h7 z`z}-c7Dk5v*+3@0e4HC#KIt#-fQ4-Cv9W%5o?0zweh-&943)QeD_oCjIEB(7cp4Y- zyt@1MQodHW&HIRJ?`H6AN>Zsqum!}?MxI}dtr?kKU7n%ZeDUu?I}BW3nPXi7NcT5C z;@Xl9!7;3tJ2!!kP%6y?Ftf1~AAwN+@sy0`a~U@uxp+O}x*+GD@O&GhT#fQ$!=Hk5 zo447;;C{gGS6F1`BW=DJq$tjp)w2UpX1rJT5^b?pm#g%(=pb0(ZF03ejQF~cmF-Vb zsnYwXD_0M}E&HKit57(<+5x_MF-XgwLJe&e@aZu~olfwr)`N5g=gK2Y-?KT4RKMn% zKSPLo3DfMw@Si8`1*7{^d%@;gh1ca`YrKyswYCYi*c=2>nRl)0{(aEU=>T7e0VFRf zobT0ei0DD8zZYOdsaW22)CRFgynT3?cY*Iv)Qv1&^sXGzr##1Lp_+2|?wF z#9q@8!Qib&AiY;>F&SZ}rx6*w{Q%ODB=U97Q1dV?K;XUtz-&PIgN<1*T8BZ3CBmK- z@O#P-w7zcjd&>0c8NpQg{EE@%kJIsb@&7`fO0UbsX#FmwR%RcWy=3+Bu_0hb`q;6P zRAPRpqq)iDyb2l`E#O;Y1gTrF1}u6A`YE*(l+xV+8RMx4t~!(?^@R_ z8jV|KgUM0;w9PRaOi%BFhHa>D{efeJ;q!b2iTg zQ*{pbhEGySLFHVseaW zKIS2CGZ#N+tjAouzHMlPoaj+0`RSJEL;CN_&wgM0yfqM`~GuEt;~njEJy=z?qNy_KZ zp)Vl>3EKC84$MsNu|9eKSE}_NO=t6Ft*i54bG5jYDZFYasQVP8h&^BThJnYsFD~g?e~BYs(uV$HmAysP<1na*_)^F)Cf|k_fZ#8g+IE^mq&M1iGs~j} zkks{3zWjMQgpTra??NZZfY4?D^CKzx2vC&o6OCi;BrX$9`zAYy4ogGsTbY1eKiLX4g_pUsY?g zOxe`#^OWbuWH!x-{GKxvTWze)iIN)kg7OZVtc@q{O9-ucb^3VpUtZp(bqi*rJ_CY} znjkn}61l%q%EzXc4>H`ZQE{K6Q)S8SL%w}!ATaiwgR}ptWle4yqDP|$m$Om?lEd5Vs@w++3sB*F=36kmckmaef$8!s zXi^65)MVgQA%Bp`!MEuU5@&&l+rqli!1GKOIl#wg$mH@w#a0``ryhyM=JGAJ_cZ&% z0qKn|r9-^bzeDuXC}LT+F=w(vb9xC$h7AMK2*em0o4&WbOr0Kdns zgYy0)mF#*bA1(oHFG+L?*zb9R@jeZP?03T`n_p}lb2Ae(mm osD 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 literal 0 HcmV?d00001 diff --git a/vendor/github.com/DataDog/go-libddwaf/v2/internal/noopfree/noopfree.s b/vendor/github.com/DataDog/go-libddwaf/v3/internal/lib/version.go similarity index 60% rename from vendor/github.com/DataDog/go-libddwaf/v2/internal/noopfree/noopfree.s rename to vendor/github.com/DataDog/go-libddwaf/v3/internal/lib/version.go index 25c3def33..8c0828e9c 100644 --- a/vendor/github.com/DataDog/go-libddwaf/v2/internal/noopfree/noopfree.s +++ b/vendor/github.com/DataDog/go-libddwaf/v3/internal/lib/version.go @@ -1,9 +1,13 @@ // Unless explicitly stated otherwise all files in this repository are licensed // under the Apache License Version 2.0. // This product includes software developed at Datadog (https://www.datadoghq.com/). -// Copyright 2016-present Datadog, Inc. +// Copyright 2024 Datadog, Inc. -#include "textflag.h" +package lib -TEXT _noop_free_v2(SB), NOSPLIT, $0-0 - RET +import ( + _ "embed" // For go:embed +) + +//go:embed .version +var EmbeddedWAFVersion string diff --git a/vendor/github.com/DataDog/go-libddwaf/v2/internal/log/ddwaf.h b/vendor/github.com/DataDog/go-libddwaf/v3/internal/log/ddwaf.h similarity index 95% rename from vendor/github.com/DataDog/go-libddwaf/v2/internal/log/ddwaf.h rename to vendor/github.com/DataDog/go-libddwaf/v3/internal/log/ddwaf.h index b52b6028d..b23be0e95 100644 --- a/vendor/github.com/DataDog/go-libddwaf/v2/internal/log/ddwaf.h +++ b/vendor/github.com/DataDog/go-libddwaf/v3/internal/log/ddwaf.h @@ -162,7 +162,9 @@ struct _ddwaf_result bool timeout; /** Array of events generated, this is guaranteed to be an array **/ ddwaf_object events; - /** Array of actions generated, this is guaranteed to be an array **/ + /** Map of actions generated, this is guaranteed to be a map in the format: + * {action type: { }, ...} + **/ ddwaf_object actions; /** Map containing all derived objects in the format (address, value) **/ ddwaf_object derivatives; @@ -226,7 +228,7 @@ ddwaf_handle ddwaf_update(ddwaf_handle handle, const ddwaf_object *ruleset, * * Destroy a WAF instance. * - * @param Handle to the WAF instance. + * @param handle Handle to the WAF instance. */ void ddwaf_destroy(ddwaf_handle handle); @@ -240,16 +242,34 @@ void ddwaf_destroy(ddwaf_handle handle); * * The memory is owned by the WAF and should not be freed. * - * @param Handle to the WAF instance. + * @param handle Handle to the WAF instance. * @param size Output parameter in which the size will be returned. The value of * size will be 0 if the return value is NULL. * @return NULL if empty, otherwise a pointer to an array with size elements. * - * @Note The returned array should be considered invalid after calling ddwaf_destroy + * @note This function is not thread-safe + * @note The returned array should be considered invalid after calling ddwaf_destroy * on the handle used to obtain it. **/ const char* const* ddwaf_known_addresses(const ddwaf_handle handle, uint32_t *size); - +/** + * ddwaf_known_actions + * + * Get an array of all the action types which could be triggered as a result of + * the current set of rules and exclusion filters. + * + * The memory is owned by the WAF and should not be freed. + * + * @param handle Handle to the WAF instance. + * @param size Output parameter in which the size will be returned. The value of + * size will be 0 if the return value is NULL. + * @return NULL if empty, otherwise a pointer to an array with size elements. + * + * @note This function is not thread-safe + * @note The returned array should be considered invalid after calling ddwaf_destroy + * on the handle used to obtain it. + **/ +const char *const *ddwaf_known_actions(const ddwaf_handle handle, uint32_t *size); /** * ddwaf_context_init * diff --git a/vendor/github.com/DataDog/go-libddwaf/v2/internal/log/log.go b/vendor/github.com/DataDog/go-libddwaf/v3/internal/log/log.go similarity index 100% rename from vendor/github.com/DataDog/go-libddwaf/v2/internal/log/log.go rename to vendor/github.com/DataDog/go-libddwaf/v3/internal/log/log.go diff --git a/vendor/github.com/DataDog/go-libddwaf/v2/internal/log/log_cgo.go b/vendor/github.com/DataDog/go-libddwaf/v3/internal/log/log_cgo.go similarity index 58% rename from vendor/github.com/DataDog/go-libddwaf/v2/internal/log/log_cgo.go rename to vendor/github.com/DataDog/go-libddwaf/v3/internal/log/log_cgo.go index aeca4ebff..1d82844a0 100644 --- a/vendor/github.com/DataDog/go-libddwaf/v2/internal/log/log_cgo.go +++ b/vendor/github.com/DataDog/go-libddwaf/v3/internal/log/log_cgo.go @@ -8,7 +8,7 @@ package log // #include "./ddwaf.h" -// extern void ddwafLogCallbackFn( +// extern void ddwafLogCallbackFnv3( // DDWAF_LOG_LEVEL level, // char* function, // char* file, @@ -17,19 +17,19 @@ package log // uint64_t message_len // ); import "C" -import "unsafe" +import "github.com/DataDog/go-libddwaf/v3/internal/unsafe" // CallbackFunctionPointer returns a pointer to the log callback function which // can be used with libddwaf. func CallbackFunctionPointer() uintptr { - return uintptr(C.ddwafLogCallbackFn) + return uintptr(C.ddwafLogCallbackFnv3) } -//export ddwafLogCallbackFn -func ddwafLogCallbackFn(level C.DDWAF_LOG_LEVEL, fnPtr, filePtr *C.char, line C.unsigned, msgPtr *C.char, _ C.uint64_t) { - function := gostring((*byte)(unsafe.Pointer(fnPtr))) - file := gostring((*byte)(unsafe.Pointer(filePtr))) - message := gostring((*byte)(unsafe.Pointer(msgPtr))) +//export ddwafLogCallbackFnv3 +func ddwafLogCallbackFnv3(level C.DDWAF_LOG_LEVEL, fnPtr, filePtr *C.char, line C.unsigned, msgPtr *C.char, _ C.uint64_t) { + function := unsafe.Gostring(unsafe.CastNative[C.char, byte](fnPtr)) + file := unsafe.Gostring(unsafe.CastNative[C.char, byte](filePtr)) + message := unsafe.Gostring(unsafe.CastNative[C.char, byte](msgPtr)) logMessage(Level(level), function, file, uint(line), message) } diff --git a/vendor/github.com/DataDog/go-libddwaf/v2/internal/log/log_purego.go b/vendor/github.com/DataDog/go-libddwaf/v3/internal/log/log_purego.go similarity index 83% rename from vendor/github.com/DataDog/go-libddwaf/v2/internal/log/log_purego.go rename to vendor/github.com/DataDog/go-libddwaf/v3/internal/log/log_purego.go index 24ab082e1..e48036b58 100644 --- a/vendor/github.com/DataDog/go-libddwaf/v2/internal/log/log_purego.go +++ b/vendor/github.com/DataDog/go-libddwaf/v3/internal/log/log_purego.go @@ -3,11 +3,12 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2016-present Datadog, Inc. -//go:build !cgo && (darwin || freebsd) && !datadog.no_waf && !go1.23 +//go:build !cgo && (darwin || freebsd) && !datadog.no_waf && !go1.24 package log import ( + "github.com/DataDog/go-libddwaf/v3/internal/unsafe" "sync" "github.com/ebitengine/purego" @@ -28,9 +29,9 @@ func CallbackFunctionPointer() uintptr { } func ddwafLogCallbackFn(level Level, fnPtr, filePtr *byte, line uint, msgPtr *byte, _ uint64) { - function := gostring(fnPtr) - file := gostring(filePtr) - message := gostring(msgPtr) + function := unsafe.Gostring(fnPtr) + file := unsafe.Gostring(filePtr) + message := unsafe.Gostring(msgPtr) logMessage(level, function, file, line, message) } diff --git a/vendor/github.com/DataDog/go-libddwaf/v2/internal/log/log_unsupported.go b/vendor/github.com/DataDog/go-libddwaf/v3/internal/log/log_unsupported.go similarity index 88% rename from vendor/github.com/DataDog/go-libddwaf/v2/internal/log/log_unsupported.go rename to vendor/github.com/DataDog/go-libddwaf/v3/internal/log/log_unsupported.go index 78fff4ce0..3b7b51fef 100644 --- a/vendor/github.com/DataDog/go-libddwaf/v2/internal/log/log_unsupported.go +++ b/vendor/github.com/DataDog/go-libddwaf/v3/internal/log/log_unsupported.go @@ -3,7 +3,7 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2016-present Datadog, Inc. -//go:build (!cgo && ((!darwin && !freebsd) || go1.23)) || datadog.no_waf +//go:build (!cgo && ((!darwin && !freebsd) || go1.24)) || datadog.no_waf package log diff --git a/vendor/github.com/DataDog/go-libddwaf/v2/waf_cgo_disabled.go b/vendor/github.com/DataDog/go-libddwaf/v3/internal/support/waf_cgo_disabled.go similarity index 72% rename from vendor/github.com/DataDog/go-libddwaf/v2/waf_cgo_disabled.go rename to vendor/github.com/DataDog/go-libddwaf/v3/internal/support/waf_cgo_disabled.go index 6f1bcd874..9c4ed83cd 100644 --- a/vendor/github.com/DataDog/go-libddwaf/v2/waf_cgo_disabled.go +++ b/vendor/github.com/DataDog/go-libddwaf/v3/internal/support/waf_cgo_disabled.go @@ -4,11 +4,13 @@ // Copyright 2016-present Datadog, Inc. // The Go build tag "appsec" was introduced to avoid having CGO_ENABLED=0 breaking changes -// due to purego's dynamic link against libdl.so, which is not expected when CGO is disabled. +// due to purego's dynamic link against libdl.so, which is not expected when CGO is disabled. //go:build !cgo && !appsec -package waf +package support + +import "github.com/DataDog/go-libddwaf/v3/errors" func init() { - wafSupportErrors = append(wafSupportErrors, CgoDisabledError{}) + wafSupportErrors = append(wafSupportErrors, errors.CgoDisabledError{}) } diff --git a/vendor/github.com/DataDog/go-libddwaf/v2/waf_manually_disabled.go b/vendor/github.com/DataDog/go-libddwaf/v3/internal/support/waf_manually_disabled.go similarity index 72% rename from vendor/github.com/DataDog/go-libddwaf/v2/waf_manually_disabled.go rename to vendor/github.com/DataDog/go-libddwaf/v3/internal/support/waf_manually_disabled.go index 0a37e1841..8c65ddbc8 100644 --- a/vendor/github.com/DataDog/go-libddwaf/v2/waf_manually_disabled.go +++ b/vendor/github.com/DataDog/go-libddwaf/v3/internal/support/waf_manually_disabled.go @@ -6,8 +6,10 @@ // Manually set datadog.no_waf build tag //go:build datadog.no_waf -package waf +package support + +import "github.com/DataDog/go-libddwaf/v3/errors" func init() { - wafManuallyDisabledErr = ManuallyDisabledError{} + wafManuallyDisabledErr = errors.ManuallyDisabledError{} } diff --git a/vendor/github.com/DataDog/go-libddwaf/v3/internal/support/waf_support.go b/vendor/github.com/DataDog/go-libddwaf/v3/internal/support/waf_support.go new file mode 100644 index 000000000..cfd81a6a3 --- /dev/null +++ b/vendor/github.com/DataDog/go-libddwaf/v3/internal/support/waf_support.go @@ -0,0 +1,21 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2016-present Datadog, Inc. + +package support + +// Errors used to report data using the Health function +// Store all the errors related to why go-liddwaf is unavailable for the current target at runtime. +var wafSupportErrors []error + +// Not nil if the build tag `datadog.no_waf` is set +var wafManuallyDisabledErr error + +func WafSupportErrors() []error { + return wafSupportErrors +} + +func WafManuallyDisabledError() error { + return wafManuallyDisabledErr +} diff --git a/vendor/github.com/DataDog/go-libddwaf/v2/waf_unsupported_go.go b/vendor/github.com/DataDog/go-libddwaf/v3/internal/support/waf_unsupported_go.go similarity index 64% rename from vendor/github.com/DataDog/go-libddwaf/v2/waf_unsupported_go.go rename to vendor/github.com/DataDog/go-libddwaf/v3/internal/support/waf_unsupported_go.go index 7d82aaaea..a6b60c23f 100644 --- a/vendor/github.com/DataDog/go-libddwaf/v2/waf_unsupported_go.go +++ b/vendor/github.com/DataDog/go-libddwaf/v3/internal/support/waf_unsupported_go.go @@ -4,10 +4,12 @@ // Copyright 2016-present Datadog, Inc. // Unsupported Go versions (>=) -//go:build go1.23 +//go:build go1.24 -package waf +package support + +import "github.com/DataDog/go-libddwaf/v3/errors" func init() { - wafSupportErrors = append(wafSupportErrors, UnsupportedGoVersionError{}) + wafSupportErrors = append(wafSupportErrors, errors.UnsupportedGoVersionError{}) } diff --git a/vendor/github.com/DataDog/go-libddwaf/v2/waf_unsupported_target.go b/vendor/github.com/DataDog/go-libddwaf/v3/internal/support/waf_unsupported_target.go similarity index 72% rename from vendor/github.com/DataDog/go-libddwaf/v2/waf_unsupported_target.go rename to vendor/github.com/DataDog/go-libddwaf/v3/internal/support/waf_unsupported_target.go index d8da6e9b8..04546c1f9 100644 --- a/vendor/github.com/DataDog/go-libddwaf/v2/waf_unsupported_target.go +++ b/vendor/github.com/DataDog/go-libddwaf/v3/internal/support/waf_unsupported_target.go @@ -7,12 +7,14 @@ // Unsupported OS Unsupported Arch //go:build (!linux && !darwin) || (!amd64 && !arm64) -package waf +package support import ( "runtime" + + "github.com/DataDog/go-libddwaf/v3/errors" ) func init() { - wafSupportErrors = append(wafSupportErrors, UnsupportedOSArchError{runtime.GOOS, runtime.GOARCH}) + wafSupportErrors = append(wafSupportErrors, errors.UnsupportedOSArchError{runtime.GOOS, runtime.GOARCH}) } diff --git a/vendor/github.com/DataDog/go-libddwaf/v3/internal/unsafe/utils.go b/vendor/github.com/DataDog/go-libddwaf/v3/internal/unsafe/utils.go new file mode 100644 index 000000000..44d972823 --- /dev/null +++ b/vendor/github.com/DataDog/go-libddwaf/v3/internal/unsafe/utils.go @@ -0,0 +1,107 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2016-present Datadog, Inc. + +package unsafe + +import ( + "reflect" + stdUnsafe "unsafe" +) + +// Gostring copies a char* to a Go string. +func Gostring(ptr *byte) string { + if ptr == nil { + return "" + } + var length int + for { + if *(*byte)(stdUnsafe.Add(stdUnsafe.Pointer(ptr), uintptr(length))) == '\x00' { + break + } + length++ + } + //string builtin copies the slice + return string(stdUnsafe.Slice(ptr, length)) +} + +// NativeStringUnwrap cast a native string type into it's runtime value. Exported as the struct reflect.StringHeader +func NativeStringUnwrap(str string) reflect.StringHeader { + return *(*reflect.StringHeader)(stdUnsafe.Pointer(&str)) +} + +func GostringSized(ptr *byte, size uint64) string { + if ptr == nil { + return "" + } + return string(stdUnsafe.Slice(ptr, size)) +} + +// Cstring converts a go string to *byte that can be passed to C code. +func Cstring(name string) *byte { + var b = make([]byte, len(name)+1) + copy(b, name) + return &b[0] +} + +// Cast is used to centralize unsafe use C of allocated pointer. +// We take the address and then dereference it to trick go vet from creating a possible misuse of unsafe.Pointer +func Cast[T any](ptr uintptr) *T { + return (*T)(*(*stdUnsafe.Pointer)(stdUnsafe.Pointer(&ptr))) +} + +type Native interface { + ~byte | ~float64 | ~float32 | ~int | ~int8 | ~int16 | ~int32 | ~int64 | ~bool | ~uintptr +} + +func CastNative[N Native, T Native](ptr *N) *T { + return (*T)(*(*stdUnsafe.Pointer)(stdUnsafe.Pointer(&ptr))) +} + +// NativeToUintptr is a helper used by populate WafObject values +// with Go values +func NativeToUintptr[T any](x T) uintptr { + return *(*uintptr)(stdUnsafe.Pointer(&x)) +} + +// UintToNative is a helper used retrieve Go values from an uintptr encoded +// value from a WafObject +func UintptrToNative[T any](x uintptr) T { + return *(*T)(stdUnsafe.Pointer(&x)) +} + +// CastWithOffset is the same as cast but adding an offset to the pointer by a multiple of the size +// of the type pointed. +func CastWithOffset[T any](ptr uintptr, offset uint64) *T { + return (*T)(stdUnsafe.Add(*(*stdUnsafe.Pointer)(stdUnsafe.Pointer(&ptr)), offset*uint64(stdUnsafe.Sizeof(*new(T))))) +} + +// PtrToUintptr is a helper to centralize of usage of unsafe.Pointer +// do not use this function to cast interfaces +func PtrToUintptr[T any](arg *T) uintptr { + return uintptr(stdUnsafe.Pointer(arg)) +} + +func SliceToUintptr[T any](arg []T) uintptr { + return (*reflect.SliceHeader)(stdUnsafe.Pointer(&arg)).Data +} + +// KeepAlive() globals +var ( + alwaysFalse bool + escapeSink any +) + +// KeepAlive is a copy of runtime.KeepAlive +// keepAlive has 2 usages: +// - It forces the deallocation of the memory to take place later than expected (just like runtime.KeepAlive) +// - It forces the given argument x to be escaped on the heap by saving it into a global value (Go doesn't provide a standard way to do it as of today) +// It is implemented so that the compiler cannot optimize it. +// +//go:noinline +func KeepAlive[T any](x T) { + if alwaysFalse { + escapeSink = x + } +} diff --git a/vendor/github.com/DataDog/go-libddwaf/v3/metrics.go b/vendor/github.com/DataDog/go-libddwaf/v3/metrics.go new file mode 100644 index 000000000..509736537 --- /dev/null +++ b/vendor/github.com/DataDog/go-libddwaf/v3/metrics.go @@ -0,0 +1,140 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2016-present Datadog, Inc. + +package waf + +import ( + "strings" + "sync" + "time" +) + +// Stats stores the metrics collected by the WAF. +type ( + Stats struct { + // Timers returns a map of metrics and their durations. + Timers map[string]time.Duration + + // TimeoutCount for the Default Scope i.e. "waf" + TimeoutCount uint64 + + // TimeoutRASPCount for the RASP Scope i.e. "rasp" + TimeoutRASPCount uint64 + + // Truncations provides details about truncations that occurred while + // encoding address data for WAF execution. + Truncations map[TruncationReason][]int + + // TruncationsRASP provides details about truncations that occurred while + // encoding address data for RASP execution. + TruncationsRASP map[TruncationReason][]int + } + + // Scope is the way to classify the different runs in the same context in order to have different metrics + Scope string + + metricKey struct { + scope Scope + component string + } + + metricsStore struct { + data map[metricKey]time.Duration + mutex sync.RWMutex + } +) + +const ( + DefaultScope Scope = "waf" + RASPScope Scope = "rasp" +) + +const ( + wafEncodeTag = "encode" + wafRunTag = "duration_ext" + wafDurationTag = "duration" + wafDecodeTag = "decode" + wafTimeoutTag = "timeouts" + wafTruncationTag = "truncations" +) + +func dot(parts ...string) string { + return strings.Join(parts, ".") +} + +// Metrics transform the stats returned by the WAF into a map of key value metrics with values in microseconds. +// ex. {"waf.encode": 100, "waf.duration_ext": 300, "waf.duration": 200, "rasp.encode": 100, "rasp.duration_ext": 300, "rasp.duration": 200} +func (stats Stats) Metrics() map[string]any { + tags := make(map[string]any, len(stats.Timers)+len(stats.Truncations)+1) + for k, v := range stats.Timers { + tags[k] = float64(v.Nanoseconds()) / float64(time.Microsecond) // The metrics should be in microseconds + } + + if stats.TimeoutCount > 0 { + tags[dot(string(DefaultScope), wafTimeoutTag)] = stats.TimeoutCount + } + + if stats.TimeoutRASPCount > 0 { + tags[dot(string(RASPScope), wafTimeoutTag)] = stats.TimeoutRASPCount + } + + for reason, list := range stats.Truncations { + tags[dot(string(DefaultScope), wafTruncationTag, reason.String())] = list + } + + for reason, list := range stats.TruncationsRASP { + tags[dot(string(RASPScope), wafTruncationTag, reason.String())] = list + } + + return tags +} + +func (metrics *metricsStore) add(scope Scope, component string, duration time.Duration) { + metrics.mutex.Lock() + defer metrics.mutex.Unlock() + if metrics.data == nil { + metrics.data = make(map[metricKey]time.Duration, 5) + } + + metrics.data[metricKey{scope, component}] += duration +} + +func (metrics *metricsStore) get(scope Scope, component string) time.Duration { + metrics.mutex.RLock() + defer metrics.mutex.RUnlock() + return metrics.data[metricKey{scope, component}] +} + +func (metrics *metricsStore) timers() map[string]time.Duration { + metrics.mutex.Lock() + defer metrics.mutex.Unlock() + if metrics.data == nil { + return nil + } + + timers := make(map[string]time.Duration, len(metrics.data)) + for k, v := range metrics.data { + timers[dot(string(k.scope), k.component)] = v + } + return timers +} + +// merge merges the current metrics with new ones +func (metrics *metricsStore) merge(scope Scope, other map[string]time.Duration) { + metrics.mutex.Lock() + defer metrics.mutex.Unlock() + if metrics.data == nil { + metrics.data = make(map[metricKey]time.Duration, 5) + } + + for component, val := range other { + key := metricKey{scope, component} + prev, ok := metrics.data[key] + if !ok { + prev = 0 + } + metrics.data[key] = prev + val + } +} diff --git a/vendor/github.com/DataDog/go-libddwaf/v3/timer/base_timer.go b/vendor/github.com/DataDog/go-libddwaf/v3/timer/base_timer.go new file mode 100644 index 000000000..adb68bb19 --- /dev/null +++ b/vendor/github.com/DataDog/go-libddwaf/v3/timer/base_timer.go @@ -0,0 +1,125 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2022 Datadog, Inc. + +package timer + +import ( + "errors" + "time" +) + +// baseTimer is the type used for all the timers that won't have children +// It's implementation is more lightweight than nodeTimer and can be used as a standalone timer using NewTimer +type baseTimer struct { + + // config is the configuration of the timer + config config + + clock + + // start is the time when the timer was started + start time.Time + + // parent is the parent timer. It is used to progate the stop of the timer to the parent timer and get the remaining time in case the budget has to be inherited. + parent NodeTimer + + // componentName is the name of the component of the timer. It is used to store the time spent in the component and to propagate the stop of the timer to the parent timer. + componentName string + + // spent is the time spent on the timer, set after calling stop + spent time.Duration +} + +var _ Timer = (*baseTimer)(nil) + +// NewTimer creates a new Timer with the given options. You have to specify either the option WithBudget or WithUnlimitedBudget. +func NewTimer(options ...Option) (Timer, error) { + config := newConfig(options...) + if config.budget == DynamicBudget { + return nil, errors.New("root timer cannot inherit parent budget, please provide a budget using timer.WithBudget() or timer.WithUnlimitedBudget()") + } + + if len(config.components) > 0 { + return nil, errors.New("NewTimer: timer that have components must use NewTreeTimer()") + } + + return &baseTimer{ + config: config, + clock: newTimeCache(), + }, nil +} + +func (timer *baseTimer) Start() time.Time { + // already started before + if timer.start != (time.Time{}) { + return timer.start + } + + if timer.config.budget == DynamicBudget && timer.parent != nil { + timer.config.budget = timer.config.dynamicBudget(timer.parent) + } + + timer.start = timer.now() + return timer.start +} + +func (timer *baseTimer) Spent() time.Duration { + // timer was never started + if timer.start == (time.Time{}) { + return 0 + } + + // timer was already stopped + if timer.spent != 0 { + return timer.spent + } + + return time.Since(timer.start) +} + +func (timer *baseTimer) Remaining() time.Duration { + if timer.config.budget == UnlimitedBudget { + return UnlimitedBudget + } + + remaining := timer.config.budget - timer.Spent() + if remaining < 0 { + return 0 + } + + return remaining +} + +func (timer *baseTimer) Exhausted() bool { + if timer.config.budget == UnlimitedBudget { + return false + } + + return timer.Spent() > timer.config.budget +} + +func (timer *baseTimer) Stop() time.Duration { + // If the current timer has already stopped, return the current spent time + if timer.spent != 0 { + return timer.spent + } + + timer.spent = timer.Spent() + if timer.parent != nil { + timer.parent.childStopped(timer.componentName, timer.spent) + } + + return timer.spent +} + +func (timer *baseTimer) Timed(timedFunc func(timer Timer)) (spent time.Duration) { + timer.Start() + defer func() { + spent = timer.Stop() + }() + + timedFunc(timer) + return +} diff --git a/vendor/github.com/DataDog/go-libddwaf/v3/timer/clock.go b/vendor/github.com/DataDog/go-libddwaf/v3/timer/clock.go new file mode 100644 index 000000000..d20e1781b --- /dev/null +++ b/vendor/github.com/DataDog/go-libddwaf/v3/timer/clock.go @@ -0,0 +1,28 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2022 Datadog, Inc. + +package timer + +import ( + "time" +) + +// clock is a simple cache for time.Now() to hopefully avoid some expensive calls to REALTIME part of time.Now() +type clock struct { + lastRequest time.Time +} + +func newTimeCache() clock { + return clock{ + lastRequest: time.Now(), + } +} + +func (ct *clock) now() time.Time { + // If the diff is greater than ~2^32 then the monotonic clock has wrapped around + // and time.Since will do a call to time.Now() for us. + ct.lastRequest = ct.lastRequest.Add(time.Since(ct.lastRequest)) + return ct.lastRequest +} diff --git a/vendor/github.com/DataDog/go-libddwaf/v3/timer/component.go b/vendor/github.com/DataDog/go-libddwaf/v3/timer/component.go new file mode 100644 index 000000000..3b7545874 --- /dev/null +++ b/vendor/github.com/DataDog/go-libddwaf/v3/timer/component.go @@ -0,0 +1,28 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2022 Datadog, Inc. + +package timer + +import ( + "sync/atomic" +) + +// components store the data shared between child timers of the same component name +type components struct { + lookup map[string]*atomic.Int64 + storage []atomic.Int64 +} + +func newComponents(names []string) components { + lookup := make(map[string]*atomic.Int64, len(names)) + storage := make([]atomic.Int64, len(names)) + for i, name := range names { + lookup[name] = &storage[i] + } + return components{ + lookup: lookup, + storage: storage, + } +} diff --git a/vendor/github.com/DataDog/go-libddwaf/v3/timer/config.go b/vendor/github.com/DataDog/go-libddwaf/v3/timer/config.go new file mode 100644 index 000000000..ecf707958 --- /dev/null +++ b/vendor/github.com/DataDog/go-libddwaf/v3/timer/config.go @@ -0,0 +1,86 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2022 Datadog, Inc. + +package timer + +import ( + "math" + "time" +) + +const ( + // UnlimitedBudget is a special value for the budget that means the timer has no budget + UnlimitedBudget = time.Duration(math.MaxInt64) + + // DynamicBudget is a special value for the budget that means the timer should inherit the budget from its parent + // It is the default value if no options such as WithBudget, WithUnlimitedBudget or WithInheritedBudget are provided + DynamicBudget = ^time.Duration(0) +) + +// DynamicBudgetFunc is a function that is called on all children when a change to the parent happens +type DynamicBudgetFunc func(timer NodeTimer) time.Duration + +// config is the configuration of a timer. It can be created through the use of options +type config struct { + dynamicBudget DynamicBudgetFunc + // components store all the components of the timer + components []string + // budget is the time budget for the timer + budget time.Duration +} + +func newConfig(options ...Option) config { + config := config{} + // Make sure the budget is inherited by default + WithInheritedSumBudget()(&config) + for _, option := range options { + option(&config) + } + return config +} + +// Option are the configuration options for any type of timer. Please read the documentation of said timer to see which options are available +type Option func(*config) + +// WithBudget is an Option that sets the budget value +func WithBudget(budget time.Duration) Option { + return func(c *config) { + c.budget = budget + } +} + +// WithUnlimitedBudget is an Option that sets the UnlimitedBudget flag on config.budget +func WithUnlimitedBudget() Option { + return func(c *config) { + c.budget = UnlimitedBudget + } +} + +// WithInheritedBudget is an Option that sets the DynamicBudget flag on config.budget +func WithInheritedBudget() Option { + return func(c *config) { + c.budget = DynamicBudget + c.dynamicBudget = func(timer NodeTimer) time.Duration { + return timer.Remaining() + } + } +} + +// WithInheritedSumBudget is an Option that sets the DynamicBudget flag on config.budget and sets the DynamicBudgetFunc to sum the remaining time of all children +func WithInheritedSumBudget() Option { + return func(c *config) { + c.budget = DynamicBudget + c.dynamicBudget = func(timer NodeTimer) time.Duration { + return timer.SumRemaining() + } + } +} + +// WithComponents is an Option that adds multiple components to the components list +func WithComponents(components ...string) Option { + return func(c *config) { + c.components = append(c.components, components...) + } +} diff --git a/vendor/github.com/DataDog/go-libddwaf/v3/timer/node_timer.go b/vendor/github.com/DataDog/go-libddwaf/v3/timer/node_timer.go new file mode 100644 index 000000000..1115f59ee --- /dev/null +++ b/vendor/github.com/DataDog/go-libddwaf/v3/timer/node_timer.go @@ -0,0 +1,147 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2022 Datadog, Inc. + +package timer + +import ( + "errors" + "fmt" + "time" +) + +// nodeTimer is the type used for all the timers that can (and will) have children +type nodeTimer struct { + baseTimer + components +} + +var _ NodeTimer = (*nodeTimer)(nil) + +// NewTreeTimer creates a new Timer with the given options. You have to specify either the option WithBudget or WithUnlimitedBudget and at least one component using the WithComponents option. +func NewTreeTimer(options ...Option) (NodeTimer, error) { + config := newConfig(options...) + if config.budget == DynamicBudget { + return nil, errors.New("root timer cannot inherit parent budget, please provide a budget using timer.WithBudget() or timer.WithUnlimitedBudget()") + } + + if len(config.components) == 0 { + return nil, errors.New("NewTreeTimer: tree timer must have at least one component, otherwise use NewTimer()") + } + + return &nodeTimer{ + baseTimer: baseTimer{ + config: config, + clock: newTimeCache(), + }, + components: newComponents(config.components), + }, nil +} + +func (timer *nodeTimer) NewNode(name string, options ...Option) (NodeTimer, error) { + config := newConfig(options...) + if len(config.components) == 0 { + return nil, errors.New("NewNode: node timer must have at least one component, otherwise use NewLeaf()") + } + + _, ok := timer.components.lookup[name] + if !ok { + return nil, fmt.Errorf("NewNode: component %s not found", name) + } + + return &nodeTimer{ + baseTimer: baseTimer{ + config: config, + clock: timer.clock, + parent: timer, + componentName: name, + }, + components: newComponents(config.components), + }, nil +} + +func (timer *nodeTimer) NewLeaf(name string, options ...Option) (Timer, error) { + config := newConfig(options...) + if len(config.components) != 0 { + return nil, errors.New("NewLeaf: leaf timer cannot have components, otherwise use NewNode()") + } + + _, ok := timer.components.lookup[name] + if !ok { + return nil, fmt.Errorf("NewLeaf: component %s not found", name) + } + + return &baseTimer{ + clock: timer.clock, + config: config, + componentName: name, + parent: timer, + }, nil +} + +func (timer *nodeTimer) MustLeaf(name string, options ...Option) Timer { + leaf, err := timer.NewLeaf(name, options...) + if err != nil { + panic(err) + } + return leaf +} + +func (timer *nodeTimer) childStarted() {} + +func (timer *nodeTimer) childStopped(componentName string, duration time.Duration) { + timer.components.lookup[componentName].Add(int64(duration)) + if timer.parent == nil { + return + } + + timer.parent.childStopped(timer.componentName, duration) +} + +func (timer *nodeTimer) AddTime(name string, duration time.Duration) { + value, ok := timer.components.lookup[name] + if !ok { + return + } + + value.Add(int64(duration)) +} + +func (timer *nodeTimer) Stats() map[string]time.Duration { + stats := make(map[string]time.Duration, len(timer.components.lookup)) + for name, component := range timer.components.lookup { + stats[name] = time.Duration(component.Load()) + } + + return stats +} + +func (timer *nodeTimer) SumSpent() time.Duration { + var sum time.Duration + for _, component := range timer.components.lookup { + sum += time.Duration(component.Load()) + } + return sum +} + +func (timer *nodeTimer) SumRemaining() time.Duration { + if timer.config.budget == UnlimitedBudget { + return UnlimitedBudget + } + + remaining := timer.config.budget - timer.SumSpent() + if remaining < 0 { + return 0 + } + + return remaining +} + +func (timer *nodeTimer) SumExhausted() bool { + if timer.config.budget == UnlimitedBudget { + return false + } + + return timer.SumSpent() > timer.config.budget +} diff --git a/vendor/github.com/DataDog/go-libddwaf/v3/timer/timer.go b/vendor/github.com/DataDog/go-libddwaf/v3/timer/timer.go new file mode 100644 index 000000000..05cfd62f3 --- /dev/null +++ b/vendor/github.com/DataDog/go-libddwaf/v3/timer/timer.go @@ -0,0 +1,115 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2022 Datadog, Inc. + +package timer + +import ( + "time" +) + +// Timer is the default interface for all timers. NewTimer will provide you with a Timer. +// Keep in mind that they are NOT thread-safe and once Stop() is called, the Timer cannot be restarted. +type Timer interface { + // Start starts the timer and returns the start time. + // If the timer was already started, it returns the previous start time. + // If the timer was started without specifying a budget, it will inherit the budget from its parent when calling Start(). + // if the timer has no parent and no budget was specified, the call creating the timer (either NewTreeTimer or NewTimer) will return an error asking to specify a budget (which can be unlimited). + // Start is NOT thread-safe + Start() time.Time + + // Stop ends the timer and returns the time spent on the timer as Spent() would. + // Stop will trigger the computation of sum timers if the timer is part of a tree. See NodeTimer for more information. + // Stop is NOT thread-safe + Stop() time.Duration + + // Spent returns the current time spent between Start() and Stop() or between Start() and now if the timer is still running. + // Spent is thread-safe + Spent() time.Duration + + // Remaining returns the time remaining before the timer reaches its budget. (budget - Spent()) + // It returns 0 if the timer is exhausted. Remaining may never return a value below zero. + // Remaining only makes sense if the timer has a budget. If the timer has no budget, it returns the special value UnlimitedBudget. + // Remaining is thread-safe + Remaining() time.Duration + + // Exhausted returns true if the timer spent in the timer is greater than the budget. (Spent() > budget) + // Exhausted may return true only in case the time has a budget. If the timer has n, it returns false. + // Exhausted is thread-safe + Exhausted() bool + + // Timed is a convenience function that starts the timer, calls the provided function and stops the timer. + // Timed is panic-safe and will stop the timer even if the function panics. + // Timed is NOT thread-safe + Timed(timedFunc func(timer Timer)) time.Duration +} + +// SumTimer is a sub-interface for timers capable of having children and making the sum of their time spent. +// NewTreeTimer will provide you with a timer supporting this interface +type SumTimer interface { + // SumSpent returns the sum of the time spent in each component of the timer. + // SumSpent is thread-safe + SumSpent() time.Duration + + // SumRemaining returns the sum of the time remaining in each component of the timer. + // SumRemaining returns UnlimitedBudget if the timer has no budget. (UnlimitedBudget) + // SumRemaining is thread-safe + SumRemaining() time.Duration + + // SumExhausted returns true if the sum of the time spent in each component of the timer is greater than the budget. + // SumExhausted returns false if the timer has no budget. (UnlimitedBudget) + // SumExhausted is thread-safe + SumExhausted() bool +} + +// NodeTimer is the interface for tree timers. NewTreeTimer will provide you with a NodeTimer. +// NodeTimer can have children (NodeTimer or Timer) and will compute the sum of their spent time each time a children timer calls its Stop() method. +// To add children to a NodeTimer, you have to specify component names when creating the timer with the WithComponent and WithComponents options. +// The component names must be unique and cannot be empty. The component names are used to identify the children timers. +// The returned timer can now create children timers using the NewNode and NewLeaf functions using the names provided when creating the parent timer. +// Multiple timers from the same component can be used in parallel and will be summed together. +// In parallel to that, NodeTimer can have their own wall time timer and budget that will apply to the sum of their children and their own timer. +// The following functions are the same as the Timer interface but works using the sum of the children timers: +// - SumSpent() -> Spent() +// - SumRemaining() -> Remaining() +// - SumExhausted() -> Exhausted() +// Keep in mind that the timer itself (only Start and Stop) is NOT thread-safe and once Stop() is called, the NodeTimer cannot be restarted. +type NodeTimer interface { + Timer + SumTimer + + // NewNode creates a new NodeTimer with the given name and options. The given name must match one of the component name of the parent timer. + // A node timer is required to have at least one component. If no component is provided, it will return an error asking you to use NewLeaf instead. + // If no budget is provided, it will inherit the budget from its parent when calling Start(). + // NewNode is thread-safe + NewNode(name string, options ...Option) (NodeTimer, error) + + // NewLeaf creates a new Timer with the given name and options. The given name must match one of the component name of the parent timer. + // A leaf timer is forbidden to have components. If a component is provided, it will return an error asking you to use NewNode instead. + // If no budget is provided, it will inherit the budget from its parent when calling Start(). + // NewLeaf is thread-safe + NewLeaf(name string, options ...Option) (Timer, error) + + // MustLeaf creates a new Timer with the given name and options. The given name must match one of the component name of the parent timer. + // MustLeaf wraps a call to NewLeaf but will panic if the error is not nil. + // MustLeaf is thread-safe + MustLeaf(name string, options ...Option) Timer + + // AddTime adds the given duration to the component of the timer with the given name. + // AddTime is thread-safe + AddTime(name string, duration time.Duration) + + // Stats returns a map of the time spent in each component of the timer. + // Stats is thread-safe + Stats() map[string]time.Duration + + // childStarted is used to propagate the start of a child timer to the parent timer through the whole tree. + childStarted() + + // childStopped is used to propagate the time spent in a child timer to the parent timer through the whole tree. + childStopped(componentName string, duration time.Duration) + + // now is a convenience wrapper to swap the time.Now() function for testing and performance purposes. + now() time.Time +} diff --git a/vendor/github.com/DataDog/go-libddwaf/v2/waf.go b/vendor/github.com/DataDog/go-libddwaf/v3/waf.go similarity index 62% rename from vendor/github.com/DataDog/go-libddwaf/v2/waf.go rename to vendor/github.com/DataDog/go-libddwaf/v3/waf.go index 5ee702370..8b902e63d 100644 --- a/vendor/github.com/DataDog/go-libddwaf/v2/waf.go +++ b/vendor/github.com/DataDog/go-libddwaf/v3/waf.go @@ -9,14 +9,22 @@ import ( "errors" "fmt" "sync" + "time" - "github.com/hashicorp/go-multierror" + wafErrors "github.com/DataDog/go-libddwaf/v3/errors" + "github.com/DataDog/go-libddwaf/v3/internal/bindings" + "github.com/DataDog/go-libddwaf/v3/internal/support" ) +// ErrTimeout is the error returned when the WAF times out while processing a request. +// Deprecated: use github.com/DataDog/go-libddwaf/errors.ErrTimeout instead. +const ErrTimeout = wafErrors.ErrTimeout + // Diagnostics stores the information - provided by the WAF - about WAF rules initialization. type Diagnostics struct { Rules *DiagnosticEntry CustomRules *DiagnosticEntry + Actions *DiagnosticEntry Exclusions *DiagnosticEntry RulesOverrides *DiagnosticEntry RulesData *DiagnosticEntry @@ -25,12 +33,13 @@ type Diagnostics struct { Version string } -// TopLevelErrors returns the list of top-level errors reported by the WAF on any of the Diagnostics +// TopLevelError returns the list of top-level errors reported by the WAF on any of the Diagnostics // entries, rolled up into a single error value. Returns nil if no top-level errors were reported. // Individual, item-level errors might still exist. func (d *Diagnostics) TopLevelError() error { fields := map[string]*DiagnosticEntry{ "rules": d.Rules, + "actions": d.Actions, "custom_rules": d.CustomRules, "exclusions": d.Exclusions, "rules_override": d.RulesOverrides, @@ -39,17 +48,16 @@ func (d *Diagnostics) TopLevelError() error { "scanners": d.Scanners, } - var err *multierror.Error + var errs []error for field, entry := range fields { if entry == nil || entry.Error == "" { // No entry or no error => we're all good. continue } - // TODO: rely on errors.Join() once go1.20 is our min supported Go version - err = multierror.Append(err, fmt.Errorf("in %#v: %s", field, entry.Error)) + errs = append(errs, fmt.Errorf("in %#v: %s", field, entry.Error)) } - return err.ErrorOrNil() + return errors.Join(errs...) } // DiagnosticEntry stores the information - provided by the WAF - about loaded and failed rules @@ -73,59 +81,27 @@ type DiagnosticAddresses struct { // Result stores the multiple values returned by a call to ddwaf_run type Result struct { - Events []any - Derivatives map[string]any - Actions []string -} + // Events is the list of events the WAF detected, together with any relevant + // details. + Events []any -// Encoder/Decoder errors -var ( - errMaxDepthExceeded = errors.New("max depth exceeded") - errUnsupportedValue = errors.New("unsupported Go value") - errInvalidMapKey = errors.New("invalid WAF object map key") - errNilObjectPtr = errors.New("nil WAF object pointer") - errInvalidObjectType = errors.New("invalid type encountered when decoding") - errTooManyIndirections = errors.New("too many indirections") -) + // Derivatives is the set of key-value pairs generated by the WAF, and which + // need to be reported on the trace to provide additional data to the backend. + Derivatives map[string]any -// RunError the WAF can return when running it. -type RunError int - -// Errors the WAF can return when running it. -const ( - ErrInternal RunError = iota + 1 - ErrInvalidObject - ErrInvalidArgument - ErrTimeout - ErrOutOfMemory - ErrEmptyRuleAddresses -) + // Actions is the set of actions the WAF decided on when evaluating rules + // against the provided address data. It maps action types to their dynamic parameter values + Actions map[string]any -// Error returns the string representation of the RunError. -func (e RunError) Error() string { - switch e { - case ErrInternal: - return "internal waf error" - case ErrTimeout: - return "waf timeout" - case ErrInvalidObject: - return "invalid waf object" - case ErrInvalidArgument: - return "invalid waf argument" - case ErrOutOfMemory: - return "out of memory" - case ErrEmptyRuleAddresses: - return "empty rule addresses" - default: - return fmt.Sprintf("unknown waf error %d", e) - } + // TimeSpent is the time the WAF self-reported as spent processing the call to ddwaf_run + TimeSpent time.Duration } // Globally dlopen() libddwaf only once because several dlopens (eg. in tests) // aren't supported by macOS. var ( // libddwaf's dynamic library handle and entrypoints - wafLib *wafDl + wafLib *bindings.WafDl // libddwaf's dlopen error if any wafLoadErr error openWafOnce sync.Once @@ -149,11 +125,11 @@ func Load() (ok bool, err error) { } openWafOnce.Do(func() { - wafLib, wafLoadErr = newWafDl() + wafLib, wafLoadErr = bindings.NewWafDl() if wafLoadErr != nil { return } - wafVersion = wafLib.wafGetVersion() + wafVersion = wafLib.WafGetVersion() }) return wafLib != nil, wafLoadErr @@ -183,3 +159,25 @@ func (r *Result) HasDerivatives() bool { func (r *Result) HasActions() bool { return len(r.Actions) > 0 } + +// SupportsTarget returns true and a nil error when the target host environment +// is supported by this package and can be further used. +// Otherwise, it returns false along with an error detailing why. +func SupportsTarget() (bool, error) { + wafSupportErrors := support.WafSupportErrors() + return wafSupportErrors == nil, errors.Join(wafSupportErrors...) +} + +// Health returns true if the waf is usable, false otherwise. At the same time it can return an error +// if the waf is not usable, but the error is not blocking if true is returned, otherwise it is. +// The following conditions are checked: +// - The Waf library has been loaded successfully (you need to call `Load()` first for this case to be taken into account) +// - The Waf library has not been manually disabled with the `datadog.no_waf` go build tag +// - The Waf library is not in an unsupported OS/Arch +// - The Waf library is not in an unsupported Go version +func Health() (bool, error) { + wafSupportErrors := errors.Join(support.WafSupportErrors()...) + wafManuallyDisabledErr := support.WafManuallyDisabledError() + + return (wafLib != nil || wafLoadErr == nil) && wafSupportErrors == nil && wafManuallyDisabledErr == nil, errors.Join(wafLoadErr, wafSupportErrors, wafManuallyDisabledErr) +} diff --git a/vendor/github.com/DataDog/go-tuf/client/client.go b/vendor/github.com/DataDog/go-tuf/client/client.go index b364648e7..6a3e137fd 100644 --- a/vendor/github.com/DataDog/go-tuf/client/client.go +++ b/vendor/github.com/DataDog/go-tuf/client/client.go @@ -4,7 +4,6 @@ import ( "bytes" "encoding/hex" "encoding/json" - "errors" "io" "github.com/DataDog/go-tuf/data" @@ -446,55 +445,6 @@ func (c *Client) getLocalMeta() error { return nil } -// getDelegationPathFromRaw verifies a delegated targets against -// a given snapshot and returns an error if it's invalid -// -// Delegation must have targets to get a path, else an empty list -// will be returned: this is because the delegation iterator is leveraged. -// -// Concrete example: -// targets -// └── a.json -//   └── b.json -//      └── c.json -//        └── target_file.txt -// -// If you try to use that function on "a.json" or "b.json", it'll return an empty list -// with no error, as neither of them declare a target file -// On the other hand, if you use that function on "c.json", it'll return & verify -// [c.json, b.json, a.json]. Running that function on every delegated targets -// guarantees that if a delegated targets is in the path of a target file, then it will -// appear at least once in the result -func (c *Client) getDelegationPathFromRaw(snapshot *data.Snapshot, delegatedTargetsJSON json.RawMessage) ([]string, error) { - // unmarshal the delegated targets first without verifying as - // we need at least one targets file name to leverage the - // getTargetFileMetaDelegationPath method - s := &data.Signed{} - if err := json.Unmarshal(delegatedTargetsJSON, s); err != nil { - return nil, err - } - targets := &data.Targets{} - if err := json.Unmarshal(s.Signed, targets); err != nil { - return nil, err - } - for targetPath := range targets.Targets { - // Gets target file from remote store - _, resp, err := c.getTargetFileMetaDelegationPath(targetPath, snapshot) - // We only need to test one targets file: - // - If it is valid, it means the delegated targets has been validated - // - If it is not, the delegated targets isn't valid - if errors.As(err, &ErrMissingRemoteMetadata{}) { - // As this function is used to fill the local store cache, the targets - // will be downloaded from the remote store as the local store cache is - // empty, meaning that the delegated targets may not exist anymore. In - // that case, ignore it. - return nil, nil - } - return resp, err - } - return nil, nil -} - // loadAndVerifyLocalRootMeta decodes and verifies root metadata from // local storage and loads the top-level keys. This method first clears // the DB for top-level keys and then loads the new keys. @@ -875,10 +825,17 @@ type Destination interface { // - Size of the download does not match if the reported size is known and // incorrect func (c *Client) Download(name string, dest Destination) (err error) { + return c.DownloadBatch(map[string]Destination{name: dest}) +} + +// DownloadBatch is a batched version of Download. +func (c *Client) DownloadBatch(targetFiles map[string]Destination) (err error) { // delete dest if there is an error defer func() { if err != nil { - dest.Delete() + for _, dest := range targetFiles { + dest.Delete() + } } }() @@ -889,17 +846,27 @@ func (c *Client) Download(name string, dest Destination) (err error) { } } - normalizedName := util.NormalizeTarget(name) - localMeta, ok := c.targets[normalizedName] - if !ok { - // search in delegations - localMeta, err = c.getTargetFileMeta(normalizedName) + var names []string + for name := range targetFiles { + names = append(names, name) + } + targets, err := c.getTargetFileMetas(names) + if err != nil { + return err + } + + for name, dest := range targetFiles { + err := c.download(name, targets[name], dest) if err != nil { return err } } + return nil +} +func (c *Client) download(name string, localMeta data.TargetFileMeta, dest Destination) error { // get the data from remote storage + normalizedName := util.NormalizeTarget(name) r, size, err := c.downloadTarget(normalizedName, c.remote.GetTarget, localMeta.Hashes) if err != nil { return err @@ -927,7 +894,6 @@ func (c *Client) Download(name string, dest Destination) (err error) { } return ErrDownloadFailed{name, err} } - return nil } @@ -958,16 +924,23 @@ func (c *Client) VerifyDigest(digest string, digestAlg string, length int64, pat // exists, searching from top-level level targets then through // all delegations. If it does not, ErrNotFound will be returned. func (c *Client) Target(name string) (data.TargetFileMeta, error) { - target, err := c.getTargetFileMeta(util.NormalizeTarget(name)) - if err == nil { - return target, nil + targets, err := c.TargetBatch([]string{name}) + if err != nil { + return data.TargetFileMeta{}, err } + return targets[name], nil +} +// TargetBatch is a batched version of Target. +func (c *Client) TargetBatch(names []string) (data.TargetFiles, error) { + targets, err := c.getTargetFileMetas(names) + if err == nil { + return targets, nil + } if _, ok := err.(ErrUnknownTarget); ok { - return data.TargetFileMeta{}, ErrNotFound{name} + return nil, ErrNotFound{err.(ErrUnknownTarget).Name} } - - return data.TargetFileMeta{}, err + return nil, err } // Targets returns the complete list of available top-level targets. diff --git a/vendor/github.com/DataDog/go-tuf/client/delegations.go b/vendor/github.com/DataDog/go-tuf/client/delegations.go index 4cf540455..96f10bbdf 100644 --- a/vendor/github.com/DataDog/go-tuf/client/delegations.go +++ b/vendor/github.com/DataDog/go-tuf/client/delegations.go @@ -3,28 +3,69 @@ package client import ( "github.com/DataDog/go-tuf/data" "github.com/DataDog/go-tuf/pkg/targets" + "github.com/DataDog/go-tuf/util" "github.com/DataDog/go-tuf/verify" ) +type delegatedTargetsCache struct { + meta map[string]*data.Targets +} + +func newDelegatedTargetsCache() *delegatedTargetsCache { + return &delegatedTargetsCache{ + meta: make(map[string]*data.Targets), + } +} + +func (c *delegatedTargetsCache) loadDelegatedTargets(client *Client, snapshot *data.Snapshot, role string, db *verify.DB) (*data.Targets, error) { + if t, ok := c.meta[role]; ok { + return t, nil + } + + targets, err := client.loadDelegatedTargets(snapshot, role, db) + if err != nil { + return nil, err + } + + c.meta[role] = targets + return targets, nil +} + // getTargetFileMeta searches for a verified TargetFileMeta matching a target // Requires a local snapshot to be loaded and is locked to the snapshot versions. func (c *Client) getTargetFileMeta(target string) (data.TargetFileMeta, error) { - snapshot, err := c.loadLocalSnapshot() + metas, err := c.getTargetFileMetas([]string{target}) if err != nil { return data.TargetFileMeta{}, err } + return metas[target], nil +} - targetFileMeta, _, err := c.getTargetFileMetaDelegationPath(target, snapshot) +func (c *Client) getTargetFileMetas(targets []string) (data.TargetFiles, error) { + snapshot, err := c.loadLocalSnapshot() if err != nil { - return data.TargetFileMeta{}, err + return nil, err + } + cache := newDelegatedTargetsCache() + targetFileMetas := make(data.TargetFiles, len(targets)) + for _, target := range targets { + normalizedTarget := util.NormalizeTarget(target) + targetFileMeta, _, err := c.getTargetFileMetaDelegationPath(normalizedTarget, snapshot, cache) + if _, ok := err.(ErrUnknownTarget); ok { + return nil, ErrUnknownTarget{target, snapshot.Version} + } + if err != nil { + return nil, err + } + targetFileMetas[target] = targetFileMeta } - return targetFileMeta, nil + return targetFileMetas, nil } // getTargetFileMetaDelegationPath searches for a verified TargetFileMeta matching a target // Requires snapshot to be passed and is locked to that specific snapshot versions. // Searches through delegated targets following TUF spec 1.0.19 section 5.6. -func (c *Client) getTargetFileMetaDelegationPath(target string, snapshot *data.Snapshot) (data.TargetFileMeta, []string, error) { +func (c *Client) getTargetFileMetaDelegationPath(target string, snapshot *data.Snapshot, cache *delegatedTargetsCache) (data.TargetFileMeta, []string, error) { // delegationsIterator covers 5.6.7 // - pre-order depth-first search starting with the top targets // - filter delegations with paths or path_hash_prefixes matching searched target @@ -45,7 +86,7 @@ func (c *Client) getTargetFileMetaDelegationPath(target string, snapshot *data.S } // covers 5.6.{1,2,3,4,5,6} - targets, err := c.loadDelegatedTargets(snapshot, d.Delegatee.Name, d.DB) + targets, err := cache.loadDelegatedTargets(c, snapshot, d.Delegatee.Name, d.DB) if err != nil { return data.TargetFileMeta{}, nil, err } diff --git a/vendor/github.com/DataDog/sketches-go/ddsketch/ddsketch.go b/vendor/github.com/DataDog/sketches-go/ddsketch/ddsketch.go index 187c10f8a..33a0ea5b2 100644 --- a/vendor/github.com/DataDog/sketches-go/ddsketch/ddsketch.go +++ b/vendor/github.com/DataDog/sketches-go/ddsketch/ddsketch.go @@ -262,13 +262,13 @@ func (s *DDSketch) GetSum() (sum float64) { // GetPositiveValueStore returns the store.Store object that contains the positive // values of the sketch. -func (s *DDSketch) GetPositiveValueStore() (store.Store) { +func (s *DDSketch) GetPositiveValueStore() store.Store { return s.positiveValueStore } // GetNegativeValueStore returns the store.Store object that contains the negative // values of the sketch. -func (s *DDSketch) GetNegativeValueStore() (store.Store) { +func (s *DDSketch) GetNegativeValueStore() store.Store { return s.negativeValueStore } @@ -320,9 +320,13 @@ func FromProto(pb *sketchpb.DDSketch) (*DDSketch, error) { func FromProtoWithStoreProvider(pb *sketchpb.DDSketch, storeProvider store.Provider) (*DDSketch, error) { positiveValueStore := storeProvider() - store.MergeWithProto(positiveValueStore, pb.PositiveValues) + if pb.PositiveValues != nil { + store.MergeWithProto(positiveValueStore, pb.PositiveValues) + } negativeValueStore := storeProvider() - store.MergeWithProto(negativeValueStore, pb.NegativeValues) + if pb.NegativeValues != nil { + store.MergeWithProto(negativeValueStore, pb.NegativeValues) + } m, err := mapping.FromProto(pb.Mapping) if err != nil { return nil, err @@ -559,13 +563,13 @@ func (s *DDSketchWithExactSummaryStatistics) GetSum() float64 { // GetPositiveValueStore returns the store.Store object that contains the positive // values of the sketch. -func (s *DDSketchWithExactSummaryStatistics) GetPositiveValueStore() (store.Store) { +func (s *DDSketchWithExactSummaryStatistics) GetPositiveValueStore() store.Store { return s.DDSketch.positiveValueStore } // GetNegativeValueStore returns the store.Store object that contains the negative // values of the sketch. -func (s *DDSketchWithExactSummaryStatistics) GetNegativeValueStore() (store.Store) { +func (s *DDSketchWithExactSummaryStatistics) GetNegativeValueStore() store.Store { return s.DDSketch.negativeValueStore } diff --git a/vendor/github.com/DataDog/sketches-go/ddsketch/mapping/index_mapping.go b/vendor/github.com/DataDog/sketches-go/ddsketch/mapping/index_mapping.go index f90108eb0..88b926592 100644 --- a/vendor/github.com/DataDog/sketches-go/ddsketch/mapping/index_mapping.go +++ b/vendor/github.com/DataDog/sketches-go/ddsketch/mapping/index_mapping.go @@ -39,6 +39,9 @@ func NewDefaultMapping(relativeAccuracy float64) (IndexMapping, error) { // FromProto returns an Index mapping from the protobuf definition of it func FromProto(m *sketchpb.IndexMapping) (IndexMapping, error) { + if m == nil { + return nil, errors.New("cannot create IndexMapping from nil protobuf index mapping") + } switch m.Interpolation { case sketchpb.IndexMapping_NONE: return NewLogarithmicMappingWithGamma(m.Gamma, m.IndexOffset) diff --git a/vendor/github.com/DataDog/sketches-go/ddsketch/store/buffered_paginated.go b/vendor/github.com/DataDog/sketches-go/ddsketch/store/buffered_paginated.go index 11f43107d..11a56f910 100644 --- a/vendor/github.com/DataDog/sketches-go/ddsketch/store/buffered_paginated.go +++ b/vendor/github.com/DataDog/sketches-go/ddsketch/store/buffered_paginated.go @@ -177,7 +177,7 @@ func (s *BufferedPaginatedStore) compact() { } func (s *BufferedPaginatedStore) sortBuffer() { - sort.Slice(s.buffer, func(i, j int) bool { return s.buffer[i] < s.buffer[j] }) + sort.Ints(s.buffer) } func (s *BufferedPaginatedStore) Add(index int) { diff --git a/vendor/github.com/cespare/xxhash/v2/README.md b/vendor/github.com/cespare/xxhash/v2/README.md index 8bf0e5b78..33c88305c 100644 --- a/vendor/github.com/cespare/xxhash/v2/README.md +++ b/vendor/github.com/cespare/xxhash/v2/README.md @@ -70,3 +70,5 @@ benchstat <(go test -benchtime 500ms -count 15 -bench 'Sum64$') - [VictoriaMetrics](https://github.com/VictoriaMetrics/VictoriaMetrics) - [FreeCache](https://github.com/coocood/freecache) - [FastCache](https://github.com/VictoriaMetrics/fastcache) +- [Ristretto](https://github.com/dgraph-io/ristretto) +- [Badger](https://github.com/dgraph-io/badger) diff --git a/vendor/github.com/cespare/xxhash/v2/xxhash.go b/vendor/github.com/cespare/xxhash/v2/xxhash.go index a9e0d45c9..78bddf1ce 100644 --- a/vendor/github.com/cespare/xxhash/v2/xxhash.go +++ b/vendor/github.com/cespare/xxhash/v2/xxhash.go @@ -19,10 +19,13 @@ const ( // Store the primes in an array as well. // // The consts are used when possible in Go code to avoid MOVs but we need a -// contiguous array of the assembly code. +// contiguous array for the assembly code. var primes = [...]uint64{prime1, prime2, prime3, prime4, prime5} // Digest implements hash.Hash64. +// +// Note that a zero-valued Digest is not ready to receive writes. +// Call Reset or create a Digest using New before calling other methods. type Digest struct { v1 uint64 v2 uint64 @@ -33,19 +36,31 @@ type Digest struct { n int // how much of mem is used } -// New creates a new Digest that computes the 64-bit xxHash algorithm. +// New creates a new Digest with a zero seed. func New() *Digest { + return NewWithSeed(0) +} + +// NewWithSeed creates a new Digest with the given seed. +func NewWithSeed(seed uint64) *Digest { var d Digest - d.Reset() + d.ResetWithSeed(seed) return &d } // Reset clears the Digest's state so that it can be reused. +// It uses a seed value of zero. func (d *Digest) Reset() { - d.v1 = primes[0] + prime2 - d.v2 = prime2 - d.v3 = 0 - d.v4 = -primes[0] + d.ResetWithSeed(0) +} + +// ResetWithSeed clears the Digest's state so that it can be reused. +// It uses the given seed to initialize the state. +func (d *Digest) ResetWithSeed(seed uint64) { + d.v1 = seed + prime1 + prime2 + d.v2 = seed + prime2 + d.v3 = seed + d.v4 = seed - prime1 d.total = 0 d.n = 0 } diff --git a/vendor/github.com/cespare/xxhash/v2/xxhash_asm.go b/vendor/github.com/cespare/xxhash/v2/xxhash_asm.go index 9216e0a40..78f95f256 100644 --- a/vendor/github.com/cespare/xxhash/v2/xxhash_asm.go +++ b/vendor/github.com/cespare/xxhash/v2/xxhash_asm.go @@ -6,7 +6,7 @@ package xxhash -// Sum64 computes the 64-bit xxHash digest of b. +// Sum64 computes the 64-bit xxHash digest of b with a zero seed. // //go:noescape func Sum64(b []byte) uint64 diff --git a/vendor/github.com/cespare/xxhash/v2/xxhash_other.go b/vendor/github.com/cespare/xxhash/v2/xxhash_other.go index 26df13bba..118e49e81 100644 --- a/vendor/github.com/cespare/xxhash/v2/xxhash_other.go +++ b/vendor/github.com/cespare/xxhash/v2/xxhash_other.go @@ -3,7 +3,7 @@ package xxhash -// Sum64 computes the 64-bit xxHash digest of b. +// Sum64 computes the 64-bit xxHash digest of b with a zero seed. func Sum64(b []byte) uint64 { // A simpler version would be // d := New() diff --git a/vendor/github.com/cespare/xxhash/v2/xxhash_safe.go b/vendor/github.com/cespare/xxhash/v2/xxhash_safe.go index e86f1b5fd..05f5e7dfe 100644 --- a/vendor/github.com/cespare/xxhash/v2/xxhash_safe.go +++ b/vendor/github.com/cespare/xxhash/v2/xxhash_safe.go @@ -5,7 +5,7 @@ package xxhash -// Sum64String computes the 64-bit xxHash digest of s. +// Sum64String computes the 64-bit xxHash digest of s with a zero seed. func Sum64String(s string) uint64 { return Sum64([]byte(s)) } diff --git a/vendor/github.com/cespare/xxhash/v2/xxhash_unsafe.go b/vendor/github.com/cespare/xxhash/v2/xxhash_unsafe.go index 1c1638fd8..cf9d42aed 100644 --- a/vendor/github.com/cespare/xxhash/v2/xxhash_unsafe.go +++ b/vendor/github.com/cespare/xxhash/v2/xxhash_unsafe.go @@ -33,7 +33,7 @@ import ( // // See https://github.com/golang/go/issues/42739 for discussion. -// Sum64String computes the 64-bit xxHash digest of s. +// Sum64String computes the 64-bit xxHash digest of s with a zero seed. // It may be faster than Sum64([]byte(s)) by avoiding a copy. func Sum64String(s string) uint64 { b := *(*[]byte)(unsafe.Pointer(&sliceHeader{s, len(s)})) diff --git a/vendor/github.com/coredns/caddy/README.md b/vendor/github.com/coredns/caddy/README.md index 11cd9adc4..71f4cd4c2 100644 --- a/vendor/github.com/coredns/caddy/README.md +++ b/vendor/github.com/coredns/caddy/README.md @@ -1,5 +1,9 @@ THIS IS A FORK OF CADDY v1 - EVERYTHING IS STRIPPED EXCEPT THE PIECES NEEDED IN COREDNS. +Issues are not enabled in this repository. Please raise any issues in coredns/coredns. + +--- + Caddy is a **production-ready** open-source web server that is fast, easy to use, and makes you more productive. diff --git a/vendor/github.com/coredns/caddy/caddy.go b/vendor/github.com/coredns/caddy/caddy.go index eaec7bc45..a868ae06d 100644 --- a/vendor/github.com/coredns/caddy/caddy.go +++ b/vendor/github.com/coredns/caddy/caddy.go @@ -1,5 +1,7 @@ // Copyright 2015 Light Code Labs, LLC // +// Copyright 2024 MWS +// // 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 @@ -218,22 +220,22 @@ func (i *Instance) Restart(newCaddyfile Input) (*Instance, error) { } // Add file descriptors of all the sockets that are capable of it - restartFds := make(map[string]restartTriple) + restartFds := make(map[string][]restartTriple) for _, s := range i.servers { gs, srvOk := s.server.(GracefulServer) ln, lnOk := s.listener.(Listener) pc, pcOk := s.packet.(PacketConn) if srvOk { if lnOk && pcOk { - restartFds[gs.Address()] = restartTriple{server: gs, listener: ln, packet: pc} + restartFds[gs.Address()] = append(restartFds[gs.Address()], restartTriple{server: gs, listener: ln, packet: pc}) continue } if lnOk { - restartFds[gs.Address()] = restartTriple{server: gs, listener: ln} + restartFds[gs.Address()] = append(restartFds[gs.Address()], restartTriple{server: gs, listener: ln}) continue } if pcOk { - restartFds[gs.Address()] = restartTriple{server: gs, packet: pc} + restartFds[gs.Address()] = append(restartFds[gs.Address()], restartTriple{server: gs, packet: pc}) continue } } @@ -484,7 +486,7 @@ func Start(cdyfile Input) (*Instance, error) { return inst, nil } -func startWithListenerFds(cdyfile Input, inst *Instance, restartFds map[string]restartTriple) error { +func startWithListenerFds(cdyfile Input, inst *Instance, restartFds map[string][]restartTriple) error { // save this instance in the list now so that // plugins can access it if need be, for example // the caddytls package, so it can perform cert @@ -684,7 +686,7 @@ func executeDirectives(inst *Instance, filename string, return nil } -func startServers(serverList []Server, inst *Instance, restartFds map[string]restartTriple) error { +func startServers(serverList []Server, inst *Instance, restartFds map[string][]restartTriple) error { errChan := make(chan error, len(serverList)) // used for signaling to error logging goroutine to terminate @@ -734,7 +736,16 @@ func startServers(serverList []Server, inst *Instance, restartFds map[string]res // reuse the listener for a graceful restart. if gs, ok := s.(GracefulServer); ok && restartFds != nil { addr := gs.Address() - if old, ok := restartFds[addr]; ok { + // Multiple servers may use the same addr (SO_REUSEPORT option set), so it's important to ensure + // that we don't reuse the same listener/packetconn. + // We'll create new listeners in case there are no more available triples for the same address. + if triples, ok := restartFds[addr]; ok && len(triples) > 0 { + // Take first available triple + old := triples[0] + // Remove reused triple from restartFds + triples[0] = triples[len(triples)-1] + restartFds[addr] = triples[:len(triples)-1] + // listener if old.listener != nil { file, err := old.listener.File() diff --git a/vendor/github.com/coredns/caddy/plugins.go b/vendor/github.com/coredns/caddy/plugins.go index 51d673970..a4f70c46b 100644 --- a/vendor/github.com/coredns/caddy/plugins.go +++ b/vendor/github.com/coredns/caddy/plugins.go @@ -56,33 +56,13 @@ var ( func DescribePlugins() string { pl := ListPlugins() - str := "Server types:\n" - for _, name := range pl["server_types"] { - str += " " + name + "\n" - } - - str += "\nCaddyfile loaders:\n" - for _, name := range pl["caddyfile_loaders"] { - str += " " + name + "\n" - } - - if len(pl["event_hooks"]) > 0 { - str += "\nEvent hook plugins:\n" - for _, name := range pl["event_hooks"] { - str += " hook." + name + "\n" - } - } - - if len(pl["clustering"]) > 0 { - str += "\nClustering plugins:\n" - for _, name := range pl["clustering"] { - str += " " + name + "\n" - } - } - - str += "\nOther plugins:\n" + str := "" for _, name := range pl["others"] { - str += " " + name + "\n" + if len(name) > 3 { + str += name[4:] + "\n" // drop dns. prefix caddy adds + } else { + str += name + "\n" + } } return str diff --git a/vendor/github.com/coredns/coredns/core/dnsserver/config.go b/vendor/github.com/coredns/coredns/core/dnsserver/config.go index 9e1116650..27f5c2105 100644 --- a/vendor/github.com/coredns/coredns/core/dnsserver/config.go +++ b/vendor/github.com/coredns/coredns/core/dnsserver/config.go @@ -24,6 +24,10 @@ type Config struct { // The port to listen on. Port string + // The number of servers that will listen on one port. + // By default, one server will be running. + NumSockets int + // Root points to a base directory we find user defined "things". // First consumer is the file plugin to looks for zone files in this place. Root string diff --git a/vendor/github.com/coredns/coredns/core/dnsserver/register.go b/vendor/github.com/coredns/coredns/core/dnsserver/register.go index ae001b9f2..73b63bb70 100644 --- a/vendor/github.com/coredns/coredns/core/dnsserver/register.go +++ b/vendor/github.com/coredns/coredns/core/dnsserver/register.go @@ -134,69 +134,23 @@ func (h *dnsContext) InspectServerBlocks(sourceFile string, serverBlocks []caddy // MakeServers uses the newly-created siteConfigs to create and return a list of server instances. func (h *dnsContext) MakeServers() ([]caddy.Server, error) { - // Copy the Plugin, ListenHosts and Debug from first config in the block - // to all other config in the same block . Doing this results in zones - // sharing the same plugin instances and settings as other zones in - // the same block. - for _, c := range h.configs { - c.Plugin = c.firstConfigInBlock.Plugin - c.ListenHosts = c.firstConfigInBlock.ListenHosts - c.Debug = c.firstConfigInBlock.Debug - c.Stacktrace = c.firstConfigInBlock.Stacktrace - - // Fork TLSConfig for each encrypted connection - c.TLSConfig = c.firstConfigInBlock.TLSConfig.Clone() - c.ReadTimeout = c.firstConfigInBlock.ReadTimeout - c.WriteTimeout = c.firstConfigInBlock.WriteTimeout - c.IdleTimeout = c.firstConfigInBlock.IdleTimeout - c.TsigSecret = c.firstConfigInBlock.TsigSecret - } + // Copy parameters from first config in the block to all other config in the same block + propagateConfigParams(h.configs) // we must map (group) each config to a bind address groups, err := groupConfigsByListenAddr(h.configs) if err != nil { return nil, err } + // then we create a server for each group var servers []caddy.Server for addr, group := range groups { - // switch on addr - switch tr, _ := parse.Transport(addr); tr { - case transport.DNS: - s, err := NewServer(addr, group) - if err != nil { - return nil, err - } - servers = append(servers, s) - - case transport.TLS: - s, err := NewServerTLS(addr, group) - if err != nil { - return nil, err - } - servers = append(servers, s) - - case transport.QUIC: - s, err := NewServerQUIC(addr, group) - if err != nil { - return nil, err - } - servers = append(servers, s) - - case transport.GRPC: - s, err := NewServergRPC(addr, group) - if err != nil { - return nil, err - } - servers = append(servers, s) - - case transport.HTTPS: - s, err := NewServerHTTPS(addr, group) - if err != nil { - return nil, err - } - servers = append(servers, s) + serversForGroup, err := makeServersForGroup(addr, group) + if err != nil { + return nil, err } + servers = append(servers, serversForGroup...) } // For each server config, check for View Filter plugins @@ -263,8 +217,11 @@ func (c *Config) Handlers() []plugin.Handler { return nil } hs := make([]plugin.Handler, 0, len(c.registry)) - for k := range c.registry { - hs = append(hs, c.registry[k]) + for _, k := range Directives { + registry := c.Handler(k) + if registry != nil { + hs = append(hs, registry) + } } return hs } @@ -296,6 +253,27 @@ func (h *dnsContext) validateZonesAndListeningAddresses() error { return nil } +// propagateConfigParams copies the necessary parameters from first config in the block +// to all other config in the same block. Doing this results in zones +// sharing the same plugin instances and settings as other zones in +// the same block. +func propagateConfigParams(configs []*Config) { + for _, c := range configs { + c.Plugin = c.firstConfigInBlock.Plugin + c.ListenHosts = c.firstConfigInBlock.ListenHosts + c.Debug = c.firstConfigInBlock.Debug + c.Stacktrace = c.firstConfigInBlock.Stacktrace + c.NumSockets = c.firstConfigInBlock.NumSockets + + // Fork TLSConfig for each encrypted connection + c.TLSConfig = c.firstConfigInBlock.TLSConfig.Clone() + c.ReadTimeout = c.firstConfigInBlock.ReadTimeout + c.WriteTimeout = c.firstConfigInBlock.WriteTimeout + c.IdleTimeout = c.firstConfigInBlock.IdleTimeout + c.TsigSecret = c.firstConfigInBlock.TsigSecret + } +} + // groupConfigsByListenAddr groups site configs by their listen // (bind) address, so sites that use the same listener can be served // on the same server instance. The return value maps the listen @@ -317,6 +295,63 @@ func groupConfigsByListenAddr(configs []*Config) (map[string][]*Config, error) { return groups, nil } +// makeServersForGroup creates servers for a specific transport and group. +// It creates as many servers as specified in the NumSockets configuration. +// If the NumSockets param is not specified, one server is created by default. +func makeServersForGroup(addr string, group []*Config) ([]caddy.Server, error) { + // that is impossible, but better to check + if len(group) == 0 { + return nil, fmt.Errorf("no configs for group defined") + } + // create one server by default if no NumSockets specified + numSockets := 1 + if group[0].NumSockets > 0 { + numSockets = group[0].NumSockets + } + + var servers []caddy.Server + for range numSockets { + // switch on addr + switch tr, _ := parse.Transport(addr); tr { + case transport.DNS: + s, err := NewServer(addr, group) + if err != nil { + return nil, err + } + servers = append(servers, s) + + case transport.TLS: + s, err := NewServerTLS(addr, group) + if err != nil { + return nil, err + } + servers = append(servers, s) + + case transport.QUIC: + s, err := NewServerQUIC(addr, group) + if err != nil { + return nil, err + } + servers = append(servers, s) + + case transport.GRPC: + s, err := NewServergRPC(addr, group) + if err != nil { + return nil, err + } + servers = append(servers, s) + + case transport.HTTPS: + s, err := NewServerHTTPS(addr, group) + if err != nil { + return nil, err + } + servers = append(servers, s) + } + } + return servers, nil +} + // DefaultPort is the default port. const DefaultPort = transport.Port diff --git a/vendor/github.com/coredns/coredns/core/dnsserver/server_https.go b/vendor/github.com/coredns/coredns/core/dnsserver/server_https.go index cddf59890..09c7d6200 100644 --- a/vendor/github.com/coredns/coredns/core/dnsserver/server_https.go +++ b/vendor/github.com/coredns/coredns/core/dnsserver/server_https.go @@ -188,7 +188,7 @@ func (s *ServerHTTPS) ServeHTTP(w http.ResponseWriter, r *http.Request) { age := dnsutil.MinimalTTL(dw.Msg, mt) w.Header().Set("Content-Type", doh.MimeType) - w.Header().Set("Cache-Control", fmt.Sprintf("max-age=%f", age.Seconds())) + w.Header().Set("Cache-Control", fmt.Sprintf("max-age=%d", uint32(age.Seconds()))) w.Header().Set("Content-Length", strconv.Itoa(len(buf))) w.WriteHeader(http.StatusOK) s.countResponse(http.StatusOK) diff --git a/vendor/github.com/coredns/coredns/core/dnsserver/zdirectives.go b/vendor/github.com/coredns/coredns/core/dnsserver/zdirectives.go index 83743ac21..56174955c 100644 --- a/vendor/github.com/coredns/coredns/core/dnsserver/zdirectives.go +++ b/vendor/github.com/coredns/coredns/core/dnsserver/zdirectives.go @@ -16,6 +16,7 @@ var Directives = []string{ "cancel", "tls", "timeouts", + "multisocket", "reload", "nsid", "bufsize", diff --git a/vendor/github.com/coredns/coredns/coremain/run.go b/vendor/github.com/coredns/coredns/coremain/run.go index 31b791c8e..6816dc699 100644 --- a/vendor/github.com/coredns/coredns/coremain/run.go +++ b/vendor/github.com/coredns/coredns/coremain/run.go @@ -12,6 +12,8 @@ import ( "github.com/coredns/caddy" "github.com/coredns/coredns/core/dnsserver" + + "go.uber.org/automaxprocs/maxprocs" ) func init() { @@ -31,7 +33,7 @@ func init() { flag.StringVar(&dnsserver.Port, serverType+".port", dnsserver.DefaultPort, "Default port") flag.StringVar(&dnsserver.Port, "p", dnsserver.DefaultPort, "Default port") - caddy.AppName = coreName + caddy.AppName = CoreName caddy.AppVersion = CoreVersion } @@ -56,6 +58,11 @@ func Run() { os.Exit(0) } + _, err := maxprocs.Set(maxprocs.Logger(log.Printf)) + if err != nil { + log.Println("[WARNING] Failed to set GOMAXPROCS:", err) + } + // Get Corefile input corefile, err := caddy.LoadCaddyfile(serverType) if err != nil { diff --git a/vendor/github.com/coredns/coredns/coremain/version.go b/vendor/github.com/coredns/coredns/coremain/version.go index 232941fba..a5ef6553b 100644 --- a/vendor/github.com/coredns/coredns/coremain/version.go +++ b/vendor/github.com/coredns/coredns/coremain/version.go @@ -2,7 +2,7 @@ package coremain // Various CoreDNS constants. const ( - CoreVersion = "1.11.3" - coreName = "CoreDNS" + CoreVersion = "1.12.0" + CoreName = "CoreDNS" serverType = "dns" ) diff --git a/vendor/github.com/coredns/coredns/plugin/bind/README.md b/vendor/github.com/coredns/coredns/plugin/bind/README.md index 1c0f0c5f9..0633e95ef 100644 --- a/vendor/github.com/coredns/coredns/plugin/bind/README.md +++ b/vendor/github.com/coredns/coredns/plugin/bind/README.md @@ -13,7 +13,7 @@ If several addresses are provided, a listener will be open on each of the IP pro Each address has to be an IP or name of one of the interfaces of the host. Bind by interface name, binds to the IPs on that interface at the time of startup or reload (reload will happen with a SIGHUP or if the config file changes). -If the given argument is an interface name, and that interface has several IP addresses, CoreDNS will listen on all of the interface IP addresses (including IPv4 and IPv6), except for IPv6 link-local addresses on that interface. +If the given argument is an interface name, and that interface has several IP addresses, CoreDNS will listen on all of the interface IP addresses (including IPv4 and IPv6). ## Syntax diff --git a/vendor/github.com/coredns/coredns/plugin/bind/setup.go b/vendor/github.com/coredns/coredns/plugin/bind/setup.go index 1bd397585..f1b9dcda5 100644 --- a/vendor/github.com/coredns/coredns/plugin/bind/setup.go +++ b/vendor/github.com/coredns/coredns/plugin/bind/setup.go @@ -4,13 +4,12 @@ import ( "errors" "fmt" "net" + "slices" "github.com/coredns/caddy" "github.com/coredns/coredns/core/dnsserver" "github.com/coredns/coredns/plugin" "github.com/coredns/coredns/plugin/pkg/log" - - "k8s.io/utils/strings/slices" ) func setup(c *caddy.Controller) error { @@ -84,8 +83,15 @@ func listIP(args []string, ifaces []net.Interface) ([]string, error) { } for _, addr := range addrs { if ipnet, ok := addr.(*net.IPNet); ok { - if ipnet.IP.To4() != nil || (!ipnet.IP.IsLinkLocalMulticast() && !ipnet.IP.IsLinkLocalUnicast()) { - all = append(all, ipnet.IP.String()) + ipa, err := net.ResolveIPAddr("ip", ipnet.IP.String()) + if err == nil { + if len(ipnet.IP) == net.IPv6len && + (ipnet.IP.IsLinkLocalMulticast() || ipnet.IP.IsLinkLocalUnicast()) { + if ipa.Zone == "" { + ipa.Zone = iface.Name + } + } + all = append(all, ipa.String()) } } } diff --git a/vendor/github.com/coredns/coredns/plugin/dnstap/README.md b/vendor/github.com/coredns/coredns/plugin/dnstap/README.md index b90c45fc7..5ec188d3b 100644 --- a/vendor/github.com/coredns/coredns/plugin/dnstap/README.md +++ b/vendor/github.com/coredns/coredns/plugin/dnstap/README.md @@ -15,7 +15,7 @@ Every message is sent to the socket as soon as it comes in, the *dnstap* plugin ## Syntax ~~~ txt -dnstap SOCKET [full] { +dnstap SOCKET [full] [writebuffer] [queue] { [identity IDENTITY] [version VERSION] [extra EXTRA] @@ -38,6 +38,12 @@ Log information about client requests and responses to */tmp/dnstap.sock*. dnstap /tmp/dnstap.sock ~~~ +Log information about client requests and responses and tcp write buffer is 1024*Mb and queue is 2048*10000. + +~~~ txt +dnstap /tmp/dnstap.sock full 1024 2048 +~~~ + Log information including the wire-format DNS message about client requests and responses to */tmp/dnstap.sock*. ~~~ txt @@ -95,7 +101,7 @@ dnstap tcp://example.com:6000 ## Command Line Tool Dnstap has a command line tool that can be used to inspect the logging. The tool can be found -at Github: . It's written in Go. +at GitHub: . It's written in Go. The following command listens on the given socket and decodes messages to stdout. diff --git a/vendor/github.com/coredns/coredns/plugin/dnstap/handler.go b/vendor/github.com/coredns/coredns/plugin/dnstap/handler.go index 1d5bd98e5..d322aab90 100644 --- a/vendor/github.com/coredns/coredns/plugin/dnstap/handler.go +++ b/vendor/github.com/coredns/coredns/plugin/dnstap/handler.go @@ -20,10 +20,12 @@ type Dnstap struct { repl replacer.Replacer // IncludeRawMessage will include the raw DNS message into the dnstap messages if true. - IncludeRawMessage bool - Identity []byte - Version []byte - ExtraFormat string + IncludeRawMessage bool + Identity []byte + Version []byte + ExtraFormat string + MultipleTcpWriteBuf int // *Mb + MultipleQueue int // *10000 } // TapMessage sends the message m to the dnstap interface, without populating "Extra" field. diff --git a/vendor/github.com/coredns/coredns/plugin/dnstap/io.go b/vendor/github.com/coredns/coredns/plugin/dnstap/io.go index f95e4b5e8..4a6af6cb5 100644 --- a/vendor/github.com/coredns/coredns/plugin/dnstap/io.go +++ b/vendor/github.com/coredns/coredns/plugin/dnstap/io.go @@ -26,27 +26,29 @@ type tapper interface { // dio implements the Tapper interface. type dio struct { - endpoint string - proto string - enc *encoder - queue chan *tap.Dnstap - dropped uint32 - quit chan struct{} - flushTimeout time.Duration - tcpTimeout time.Duration - skipVerify bool + endpoint string + proto string + enc *encoder + queue chan *tap.Dnstap + dropped uint32 + quit chan struct{} + flushTimeout time.Duration + tcpTimeout time.Duration + skipVerify bool + tcpWriteBufSize int } // newIO returns a new and initialized pointer to a dio. -func newIO(proto, endpoint string) *dio { +func newIO(proto, endpoint string, multipleQueue int, multipleTcpWriteBuf int) *dio { return &dio{ - endpoint: endpoint, - proto: proto, - queue: make(chan *tap.Dnstap, queueSize), - quit: make(chan struct{}), - flushTimeout: flushTimeout, - tcpTimeout: tcpTimeout, - skipVerify: skipVerify, + endpoint: endpoint, + proto: proto, + queue: make(chan *tap.Dnstap, multipleQueue*queueSize), + quit: make(chan struct{}), + flushTimeout: flushTimeout, + tcpTimeout: tcpTimeout, + skipVerify: skipVerify, + tcpWriteBufSize: multipleTcpWriteBuf * tcpWriteBufSize, } } @@ -73,7 +75,7 @@ func (d *dio) dial() error { } if tcpConn, ok := conn.(*net.TCPConn); ok { - tcpConn.SetWriteBuffer(tcpWriteBufSize) + tcpConn.SetWriteBuffer(d.tcpWriteBufSize) tcpConn.SetNoDelay(false) } diff --git a/vendor/github.com/coredns/coredns/plugin/dnstap/setup.go b/vendor/github.com/coredns/coredns/plugin/dnstap/setup.go index 0186f4d51..5e6b31d3a 100644 --- a/vendor/github.com/coredns/coredns/plugin/dnstap/setup.go +++ b/vendor/github.com/coredns/coredns/plugin/dnstap/setup.go @@ -3,6 +3,7 @@ package dnstap import ( "net/url" "os" + "strconv" "strings" "github.com/coredns/caddy" @@ -20,7 +21,10 @@ func parseConfig(c *caddy.Controller) ([]*Dnstap, error) { dnstaps := []*Dnstap{} for c.Next() { // directive name - d := Dnstap{} + d := Dnstap{ + MultipleTcpWriteBuf: 1, + MultipleQueue: 1, + } endpoint := "" d.repl = replacer.New() @@ -32,6 +36,14 @@ func parseConfig(c *caddy.Controller) ([]*Dnstap, error) { endpoint = args[0] + if len(args) >= 3 { + d.MultipleTcpWriteBuf, _ = strconv.Atoi(args[2]) + } + + if len(args) >= 4 { + d.MultipleQueue, _ = strconv.Atoi(args[3]) + } + var dio *dio if strings.HasPrefix(endpoint, "tls://") { // remote network endpoint @@ -39,23 +51,23 @@ func parseConfig(c *caddy.Controller) ([]*Dnstap, error) { if err != nil { return nil, c.ArgErr() } - dio = newIO("tls", endpointURL.Host) - d = Dnstap{io: dio} + dio = newIO("tls", endpointURL.Host, d.MultipleQueue, d.MultipleTcpWriteBuf) + d.io = dio } else if strings.HasPrefix(endpoint, "tcp://") { // remote network endpoint endpointURL, err := url.Parse(endpoint) if err != nil { return nil, c.ArgErr() } - dio = newIO("tcp", endpointURL.Host) - d = Dnstap{io: dio} + dio = newIO("tcp", endpointURL.Host, d.MultipleQueue, d.MultipleTcpWriteBuf) + d.io = dio } else { endpoint = strings.TrimPrefix(endpoint, "unix://") - dio = newIO("unix", endpoint) - d = Dnstap{io: dio} + dio = newIO("unix", endpoint, d.MultipleQueue, d.MultipleTcpWriteBuf) + d.io = dio } - d.IncludeRawMessage = len(args) == 2 && args[1] == "full" + d.IncludeRawMessage = len(args) >= 2 && args[1] == "full" hostname, _ := os.Hostname() d.Identity = []byte(hostname) diff --git a/vendor/github.com/coredns/coredns/plugin/forward/README.md b/vendor/github.com/coredns/coredns/plugin/forward/README.md index 7dd66f768..bcfb4f355 100644 --- a/vendor/github.com/coredns/coredns/plugin/forward/README.md +++ b/vendor/github.com/coredns/coredns/plugin/forward/README.md @@ -50,6 +50,7 @@ forward FROM TO... { policy random|round_robin|sequential health_check DURATION [no_rec] [domain FQDN] max_concurrent MAX + next RCODE_1 [RCODE_2] [RCODE_3...] } ~~~ @@ -95,6 +96,7 @@ forward FROM TO... { response does not count as a health failure. When choosing a value for **MAX**, pick a number at least greater than the expected *upstream query rate* * *latency* of the upstream servers. As an upper bound for **MAX**, consider that each concurrent query will use about 2kb of memory. +* `next` If the `RCODE` (i.e. `NXDOMAIN`) is returned by the remote then execute the next plugin. If no next plugin is defined, or the next plugin is not a `forward` plugin, this setting is ignored Also note the TLS config is "global" for the whole forwarding proxy if you need a different `tls_servername` for different upstreams you're out of luck. @@ -268,6 +270,21 @@ Or when you have multiple DoT upstreams with different `tls_servername`s, you ca } ~~~ +The following would try 1.2.3.4 first. If the response is `NXDOMAIN`, try 5.6.7.8. If the response from 5.6.7.8 is `NXDOMAIN`, try 9.0.1.2. + +~~~ corefile +. { + forward . 1.2.3.4 { + next NXDOMAIN + } + forward . 5.6.7.8 { + next NXDOMAIN + } + forward . 9.0.1.2 { + } +} +~~~ + ## See Also [RFC 7858](https://tools.ietf.org/html/rfc7858) for DNS over TLS. diff --git a/vendor/github.com/coredns/coredns/plugin/forward/forward.go b/vendor/github.com/coredns/coredns/plugin/forward/forward.go index d8bbe7ab9..cb22391e2 100644 --- a/vendor/github.com/coredns/coredns/plugin/forward/forward.go +++ b/vendor/github.com/coredns/coredns/plugin/forward/forward.go @@ -43,6 +43,8 @@ type Forward struct { from string ignored []string + nextAlternateRcodes []int + tlsConfig *tls.Config tlsServerName string maxfails uint32 @@ -194,6 +196,15 @@ func (f *Forward) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg return 0, nil } + // Check if we have an alternate Rcode defined, check if we match on the code + for _, alternateRcode := range f.nextAlternateRcodes { + if alternateRcode == ret.Rcode && f.Next != nil { // In case we do not have a Next handler, just continue normally + if _, ok := f.Next.(*Forward); ok { // Only continue if the next forwarder is also a Forworder + return plugin.NextOrFailure(f.Name(), f.Next, ctx, w, r) + } + } + } + w.WriteMsg(ret) return 0, nil } diff --git a/vendor/github.com/coredns/coredns/plugin/forward/fuzz.go b/vendor/github.com/coredns/coredns/plugin/forward/fuzz.go index ba6e9155d..4367f651c 100644 --- a/vendor/github.com/coredns/coredns/plugin/forward/fuzz.go +++ b/vendor/github.com/coredns/coredns/plugin/forward/fuzz.go @@ -17,8 +17,8 @@ var f *Forward func init() { f = New() s := dnstest.NewServer(r{}.reflectHandler) - f.SetProxy(proxy.NewProxy(s.Addr, "tcp")) - f.SetProxy(proxy.NewProxy(s.Addr, "udp")) + f.SetProxy(proxy.NewProxy("FuzzForwardPlugin1", s.Addr, "tcp")) + f.SetProxy(proxy.NewProxy("FuzzForwardPlugin2", s.Addr, "udp")) } // Fuzz fuzzes forward. diff --git a/vendor/github.com/coredns/coredns/plugin/forward/setup.go b/vendor/github.com/coredns/coredns/plugin/forward/setup.go index 5341b7e60..e8211abf8 100644 --- a/vendor/github.com/coredns/coredns/plugin/forward/setup.go +++ b/vendor/github.com/coredns/coredns/plugin/forward/setup.go @@ -6,6 +6,7 @@ import ( "fmt" "path/filepath" "strconv" + "strings" "time" "github.com/coredns/caddy" @@ -289,7 +290,22 @@ func parseBlock(c *caddy.Controller, f *Forward) error { } f.ErrLimitExceeded = errors.New("concurrent queries exceeded maximum " + c.Val()) f.maxConcurrent = int64(n) + case "next": + args := c.RemainingArgs() + if len(args) == 0 { + return c.ArgErr() + } + + for _, rcode := range args { + var rc int + var ok bool + if rc, ok = dns.StringToRcode[strings.ToUpper(rcode)]; !ok { + return fmt.Errorf("%s is not a valid rcode", rcode) + } + + f.nextAlternateRcodes = append(f.nextAlternateRcodes, rc) + } default: return c.Errf("unknown property '%s'", c.Val()) } diff --git a/vendor/github.com/coredns/coredns/plugin/hosts/hostsfile.go b/vendor/github.com/coredns/coredns/plugin/hosts/hostsfile.go index e5aff0d6d..04747ef8d 100644 --- a/vendor/github.com/coredns/coredns/plugin/hosts/hostsfile.go +++ b/vendor/github.com/coredns/coredns/plugin/hosts/hostsfile.go @@ -138,7 +138,7 @@ func (h *Hostsfile) readHosts() { h.mtime = stat.ModTime() h.size = stat.Size() - hostsEntries.WithLabelValues().Set(float64(h.inline.Len() + h.hmap.Len())) + hostsEntries.WithLabelValues(h.path).Set(float64(h.inline.Len() + h.hmap.Len())) hostsReloadTime.Set(float64(stat.ModTime().UnixNano()) / 1e9) h.Unlock() } diff --git a/vendor/github.com/coredns/coredns/plugin/hosts/metrics.go b/vendor/github.com/coredns/coredns/plugin/hosts/metrics.go index f97497bf2..d3999e1e9 100644 --- a/vendor/github.com/coredns/coredns/plugin/hosts/metrics.go +++ b/vendor/github.com/coredns/coredns/plugin/hosts/metrics.go @@ -14,7 +14,7 @@ var ( Subsystem: "hosts", Name: "entries", Help: "The combined number of entries in hosts and Corefile.", - }, []string{}) + }, []string{"hostsfile"}) // hostsReloadTime is the timestamp of the last reload of hosts file. hostsReloadTime = promauto.NewGauge(prometheus.GaugeOpts{ Namespace: plugin.Namespace, diff --git a/vendor/github.com/coredns/coredns/plugin/rewrite/README.md b/vendor/github.com/coredns/coredns/plugin/rewrite/README.md index 895ef6325..9740f9d5a 100644 --- a/vendor/github.com/coredns/coredns/plugin/rewrite/README.md +++ b/vendor/github.com/coredns/coredns/plugin/rewrite/README.md @@ -51,6 +51,7 @@ will behave as follows: * `continue` will continue applying the next rule in the rule list. * `stop` will consider the current rule the last rule and will not continue. The default behaviour is `stop` + * When multiple rules are matched, the request rewrite follows the line order in the configuration, while the response rewrite(`answer` option) is executed in reverse order. ## Examples @@ -462,8 +463,30 @@ rewrite edns0 subnet set 24 56 * If the query's source IP address is an IPv4 address, the first 24 bits in the IP will be the network subnet. * If the query's source IP address is an IPv6 address, the first 56 bits in the IP will be the network subnet. +### EDNS0 Revert -### CNAME Field Rewrites +Using the `revert` flag, you can revert the changes made by this rewrite call, so the response will not contain this option. + +This example sets option, but response will not contain it +~~~ corefile +. { + rewrite edns0 local set 0xffee abcd revert +} +~~~ + +If only some calls contain the `revert` flag, then the value in the response will be changed to the previous one. So, in this example, the response will contain `abcd` data at `0xffee` +~~~ corefile +. { + rewrite continue { + edns0 local set 0xffee abcd + } + + rewrite edns0 local replace 0xffee bcde revert +} +~~~ + + +## CNAME Field Rewrites There might be a scenario where you want the `CNAME` target of the response to be rewritten. You can do this by using the `CNAME` field rewrite. This will generate new answer records according to the new `CNAME` target. diff --git a/vendor/github.com/coredns/coredns/plugin/rewrite/edns0.go b/vendor/github.com/coredns/coredns/plugin/rewrite/edns0.go index 85146c7ec..44e457919 100644 --- a/vendor/github.com/coredns/coredns/plugin/rewrite/edns0.go +++ b/vendor/github.com/coredns/coredns/plugin/rewrite/edns0.go @@ -22,6 +22,7 @@ type edns0LocalRule struct { action string code uint16 data []byte + revert bool } // edns0VariableRule is a rewrite rule for EDNS0_LOCAL options with variable. @@ -30,12 +31,43 @@ type edns0VariableRule struct { action string code uint16 variable string + revert bool } // ends0NsidRule is a rewrite rule for EDNS0_NSID options. type edns0NsidRule struct { mode string action string + revert bool +} + +type edns0SetResponseRule struct { + code uint16 +} + +func (r *edns0SetResponseRule) RewriteResponse(res *dns.Msg, _ dns.RR) { + ednsOpt := res.IsEdns0() + for idx, opt := range ednsOpt.Option { + if opt.Option() == r.code { + ednsOpt.Option = append(ednsOpt.Option[:idx], ednsOpt.Option[idx+1:]...) + return + } + } +} + +type edns0ReplaceResponseRule[T dns.EDNS0] struct { + code uint16 + source T +} + +func (r *edns0ReplaceResponseRule[T]) RewriteResponse(res *dns.Msg, _ dns.RR) { + ednsOpt := res.IsEdns0() + for idx, opt := range ednsOpt.Option { + if opt.Option() == r.code { + ednsOpt.Option[idx] = r.source + return + } + } } // setupEdns0Opt will retrieve the EDNS0 OPT or create it if it does not exist. @@ -52,11 +84,17 @@ func setupEdns0Opt(r *dns.Msg) *dns.OPT { func (rule *edns0NsidRule) Rewrite(ctx context.Context, state request.Request) (ResponseRules, Result) { o := setupEdns0Opt(state.Req) + var resp ResponseRules + for _, s := range o.Option { if e, ok := s.(*dns.EDNS0_NSID); ok { if rule.action == Replace || rule.action == Set { + if rule.revert { + old := *e + resp = append(resp, &edns0ReplaceResponseRule[*dns.EDNS0_NSID]{code: e.Code, source: &old}) + } e.Nsid = "" // make sure it is empty for request - return nil, RewriteDone + return resp, RewriteDone } } } @@ -64,7 +102,10 @@ func (rule *edns0NsidRule) Rewrite(ctx context.Context, state request.Request) ( // add option if not found if rule.action == Append || rule.action == Set { o.Option = append(o.Option, &dns.EDNS0_NSID{Code: dns.EDNS0NSID, Nsid: ""}) - return nil, RewriteDone + if rule.revert { + resp = append(resp, &edns0SetResponseRule{code: dns.EDNS0NSID}) + } + return resp, RewriteDone } return nil, RewriteIgnored @@ -77,12 +118,18 @@ func (rule *edns0NsidRule) Mode() string { return rule.mode } func (rule *edns0LocalRule) Rewrite(ctx context.Context, state request.Request) (ResponseRules, Result) { o := setupEdns0Opt(state.Req) + var resp ResponseRules + for _, s := range o.Option { if e, ok := s.(*dns.EDNS0_LOCAL); ok { if rule.code == e.Code { if rule.action == Replace || rule.action == Set { + if rule.revert { + old := *e + resp = append(resp, &edns0ReplaceResponseRule[*dns.EDNS0_LOCAL]{code: rule.code, source: &old}) + } e.Data = rule.data - return nil, RewriteDone + return resp, RewriteDone } } } @@ -91,7 +138,10 @@ func (rule *edns0LocalRule) Rewrite(ctx context.Context, state request.Request) // add option if not found if rule.action == Append || rule.action == Set { o.Option = append(o.Option, &dns.EDNS0_LOCAL{Code: rule.code, Data: rule.data}) - return nil, RewriteDone + if rule.revert { + resp = append(resp, &edns0SetResponseRule{code: rule.code}) + } + return resp, RewriteDone } return nil, RewriteIgnored @@ -116,32 +166,39 @@ func newEdns0Rule(mode string, args ...string) (Rule, error) { return nil, fmt.Errorf("invalid action: %q", action) } + // Extract "revert" parameter. + var revert bool + if args[len(args)-1] == "revert" { + revert = true + args = args[:len(args)-1] + } + switch ruleType { case "local": if len(args) != 4 { - return nil, fmt.Errorf("EDNS0 local rules require exactly three args") + return nil, fmt.Errorf("EDNS0 local rules require three or four args") } // Check for variable option. if strings.HasPrefix(args[3], "{") && strings.HasSuffix(args[3], "}") { - return newEdns0VariableRule(mode, action, args[2], args[3]) + return newEdns0VariableRule(mode, action, args[2], args[3], revert) } - return newEdns0LocalRule(mode, action, args[2], args[3]) + return newEdns0LocalRule(mode, action, args[2], args[3], revert) case "nsid": if len(args) != 2 { - return nil, fmt.Errorf("EDNS0 NSID rules do not accept args") + return nil, fmt.Errorf("EDNS0 NSID rules can accept no more than one arg") } - return &edns0NsidRule{mode: mode, action: action}, nil + return &edns0NsidRule{mode: mode, action: action, revert: revert}, nil case "subnet": if len(args) != 4 { - return nil, fmt.Errorf("EDNS0 subnet rules require exactly three args") + return nil, fmt.Errorf("EDNS0 subnet rules require three or four args") } - return newEdns0SubnetRule(mode, action, args[2], args[3]) + return newEdns0SubnetRule(mode, action, args[2], args[3], revert) default: return nil, fmt.Errorf("invalid rule type %q", ruleType) } } -func newEdns0LocalRule(mode, action, code, data string) (*edns0LocalRule, error) { +func newEdns0LocalRule(mode, action, code, data string, revert bool) (*edns0LocalRule, error) { c, err := strconv.ParseUint(code, 0, 16) if err != nil { return nil, err @@ -158,11 +215,11 @@ func newEdns0LocalRule(mode, action, code, data string) (*edns0LocalRule, error) // Add this code to the ones the server supports. edns.SetSupportedOption(uint16(c)) - return &edns0LocalRule{mode: mode, action: action, code: uint16(c), data: decoded}, nil + return &edns0LocalRule{mode: mode, action: action, code: uint16(c), data: decoded, revert: revert}, nil } // newEdns0VariableRule creates an EDNS0 rule that handles variable substitution -func newEdns0VariableRule(mode, action, code, variable string) (*edns0VariableRule, error) { +func newEdns0VariableRule(mode, action, code, variable string, revert bool) (*edns0VariableRule, error) { c, err := strconv.ParseUint(code, 0, 16) if err != nil { return nil, err @@ -175,7 +232,7 @@ func newEdns0VariableRule(mode, action, code, variable string) (*edns0VariableRu // Add this code to the ones the server supports. edns.SetSupportedOption(uint16(c)) - return &edns0VariableRule{mode: mode, action: action, code: uint16(c), variable: variable}, nil + return &edns0VariableRule{mode: mode, action: action, code: uint16(c), variable: variable, revert: revert}, nil } // ruleData returns the data specified by the variable. @@ -221,13 +278,19 @@ func (rule *edns0VariableRule) Rewrite(ctx context.Context, state request.Reques return nil, RewriteIgnored } + var resp ResponseRules + o := setupEdns0Opt(state.Req) for _, s := range o.Option { if e, ok := s.(*dns.EDNS0_LOCAL); ok { if rule.code == e.Code { if rule.action == Replace || rule.action == Set { + if rule.revert { + old := *e + resp = append(resp, &edns0ReplaceResponseRule[*dns.EDNS0_LOCAL]{code: rule.code, source: &old}) + } e.Data = data - return nil, RewriteDone + return resp, RewriteDone } return nil, RewriteIgnored } @@ -237,7 +300,10 @@ func (rule *edns0VariableRule) Rewrite(ctx context.Context, state request.Reques // add option if not found if rule.action == Append || rule.action == Set { o.Option = append(o.Option, &dns.EDNS0_LOCAL{Code: rule.code, Data: data}) - return nil, RewriteDone + if rule.revert { + resp = append(resp, &edns0SetResponseRule{code: rule.code}) + } + return resp, RewriteDone } return nil, RewriteIgnored @@ -271,9 +337,10 @@ type edns0SubnetRule struct { v4BitMaskLen uint8 v6BitMaskLen uint8 action string + revert bool } -func newEdns0SubnetRule(mode, action, v4BitMaskLen, v6BitMaskLen string) (*edns0SubnetRule, error) { +func newEdns0SubnetRule(mode, action, v4BitMaskLen, v6BitMaskLen string, revert bool) (*edns0SubnetRule, error) { v4Len, err := strconv.ParseUint(v4BitMaskLen, 0, 16) if err != nil { return nil, err @@ -293,7 +360,7 @@ func newEdns0SubnetRule(mode, action, v4BitMaskLen, v6BitMaskLen string) (*edns0 } return &edns0SubnetRule{mode: mode, action: action, - v4BitMaskLen: uint8(v4Len), v6BitMaskLen: uint8(v6Len)}, nil + v4BitMaskLen: uint8(v4Len), v6BitMaskLen: uint8(v6Len), revert: revert}, nil } // fillEcsData sets the subnet data into the ecs option @@ -326,11 +393,17 @@ func (rule *edns0SubnetRule) fillEcsData(state request.Request, ecs *dns.EDNS0_S func (rule *edns0SubnetRule) Rewrite(ctx context.Context, state request.Request) (ResponseRules, Result) { o := setupEdns0Opt(state.Req) + var resp ResponseRules + for _, s := range o.Option { if e, ok := s.(*dns.EDNS0_SUBNET); ok { if rule.action == Replace || rule.action == Set { + if rule.revert { + old := *e + resp = append(resp, &edns0ReplaceResponseRule[*dns.EDNS0_SUBNET]{code: e.Code, source: &old}) + } if rule.fillEcsData(state, e) == nil { - return nil, RewriteDone + return resp, RewriteDone } } return nil, RewriteIgnored @@ -342,7 +415,10 @@ func (rule *edns0SubnetRule) Rewrite(ctx context.Context, state request.Request) opt := &dns.EDNS0_SUBNET{Code: dns.EDNS0SUBNET} if rule.fillEcsData(state, opt) == nil { o.Option = append(o.Option, opt) - return nil, RewriteDone + if rule.revert { + resp = append(resp, &edns0SetResponseRule{code: dns.EDNS0SUBNET}) + } + return resp, RewriteDone } } diff --git a/vendor/github.com/coredns/coredns/plugin/rewrite/reverter.go b/vendor/github.com/coredns/coredns/plugin/rewrite/reverter.go index 853d96d9d..4aa6f8a5e 100644 --- a/vendor/github.com/coredns/coredns/plugin/rewrite/reverter.go +++ b/vendor/github.com/coredns/coredns/plugin/rewrite/reverter.go @@ -90,8 +90,9 @@ func (r *ResponseReverter) WriteMsg(res1 *dns.Msg) error { } func (r *ResponseReverter) rewriteResourceRecord(res *dns.Msg, rr dns.RR) { - for _, rule := range r.ResponseRules { - rule.RewriteResponse(res, rr) + // The reverting rules need to be done in reversed order. + for i := len(r.ResponseRules) - 1; i >= 0; i-- { + r.ResponseRules[i].RewriteResponse(res, rr) } } diff --git a/vendor/github.com/eapache/queue/v2/LICENSE b/vendor/github.com/eapache/queue/v2/LICENSE new file mode 100644 index 000000000..d5f36dbca --- /dev/null +++ b/vendor/github.com/eapache/queue/v2/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Evan Huus + +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. \ No newline at end of file diff --git a/vendor/github.com/eapache/queue/v2/queue.go b/vendor/github.com/eapache/queue/v2/queue.go new file mode 100644 index 000000000..8cf74cc3a --- /dev/null +++ b/vendor/github.com/eapache/queue/v2/queue.go @@ -0,0 +1,102 @@ +/* +Package queue provides a fast, ring-buffer queue based on the version suggested by Dariusz Górecki. +Using this instead of other, simpler, queue implementations (slice+append or linked list) provides +substantial memory and time benefits, and fewer GC pauses. + +The queue implemented here is as fast as it is for an additional reason: it is *not* thread-safe. +*/ +package queue + +// minQueueLen is smallest capacity that queue may have. +// Must be power of 2 for bitwise modulus: x % n == x & (n - 1). +const minQueueLen = 16 + +// Queue represents a single instance of the queue data structure. +type Queue[V any] struct { + buf []*V + head, tail, count int +} + +// New constructs and returns a new Queue. +func New[V any]() *Queue[V] { + return &Queue[V]{ + buf: make([]*V, minQueueLen), + } +} + +// Length returns the number of elements currently stored in the queue. +func (q *Queue[V]) Length() int { + return q.count +} + +// resizes the queue to fit exactly twice its current contents +// this can result in shrinking if the queue is less than half-full +func (q *Queue[V]) resize() { + newBuf := make([]*V, q.count<<1) + + if q.tail > q.head { + copy(newBuf, q.buf[q.head:q.tail]) + } else { + n := copy(newBuf, q.buf[q.head:]) + copy(newBuf[n:], q.buf[:q.tail]) + } + + q.head = 0 + q.tail = q.count + q.buf = newBuf +} + +// Add puts an element on the end of the queue. +func (q *Queue[V]) Add(elem V) { + if q.count == len(q.buf) { + q.resize() + } + + q.buf[q.tail] = &elem + // bitwise modulus + q.tail = (q.tail + 1) & (len(q.buf) - 1) + q.count++ +} + +// Peek returns the element at the head of the queue. This call panics +// if the queue is empty. +func (q *Queue[V]) Peek() V { + if q.count <= 0 { + panic("queue: Peek() called on empty queue") + } + return *(q.buf[q.head]) +} + +// Get returns the element at index i in the queue. If the index is +// invalid, the call will panic. This method accepts both positive and +// negative index values. Index 0 refers to the first element, and +// index -1 refers to the last. +func (q *Queue[V]) Get(i int) V { + // If indexing backwards, convert to positive index. + if i < 0 { + i += q.count + } + if i < 0 || i >= q.count { + panic("queue: Get() called with index out of range") + } + // bitwise modulus + return *(q.buf[(q.head+i)&(len(q.buf)-1)]) +} + +// Remove removes and returns the element from the front of the queue. If the +// queue is empty, the call will panic. +func (q *Queue[V]) Remove() V { + if q.count <= 0 { + panic("queue: Remove() called on empty queue") + } + ret := q.buf[q.head] + q.buf[q.head] = nil + // bitwise modulus + q.head = (q.head + 1) & (len(q.buf) - 1) + q.count-- + // Resize down if buffer 1/4 full. + if len(q.buf) > minQueueLen && (q.count<<2) == len(q.buf) { + q.resize() + } + return *ret +} diff --git a/vendor/github.com/fsnotify/fsnotify/.cirrus.yml b/vendor/github.com/fsnotify/fsnotify/.cirrus.yml new file mode 100644 index 000000000..ffc7b992b --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/.cirrus.yml @@ -0,0 +1,13 @@ +freebsd_task: + name: 'FreeBSD' + freebsd_instance: + image_family: freebsd-13-2 + install_script: + - pkg update -f + - pkg install -y go + test_script: + # run tests as user "cirrus" instead of root + - pw useradd cirrus -m + - chown -R cirrus:cirrus . + - FSNOTIFY_BUFFER=4096 sudo --preserve-env=FSNOTIFY_BUFFER -u cirrus go test -parallel 1 -race ./... + - sudo --preserve-env=FSNOTIFY_BUFFER -u cirrus go test -parallel 1 -race ./... diff --git a/vendor/github.com/fsnotify/fsnotify/.gitignore b/vendor/github.com/fsnotify/fsnotify/.gitignore index 1d89d85ce..391cc076b 100644 --- a/vendor/github.com/fsnotify/fsnotify/.gitignore +++ b/vendor/github.com/fsnotify/fsnotify/.gitignore @@ -4,3 +4,4 @@ # Output of go build ./cmd/fsnotify /fsnotify +/fsnotify.exe diff --git a/vendor/github.com/fsnotify/fsnotify/CHANGELOG.md b/vendor/github.com/fsnotify/fsnotify/CHANGELOG.md index 77f9593bd..e0e575754 100644 --- a/vendor/github.com/fsnotify/fsnotify/CHANGELOG.md +++ b/vendor/github.com/fsnotify/fsnotify/CHANGELOG.md @@ -1,16 +1,87 @@ # Changelog -All notable changes to this project will be documented in this file. +Unreleased +---------- +Nothing yet. -The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), -and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +1.7.0 - 2023-10-22 +------------------ +This version of fsnotify needs Go 1.17. -## [Unreleased] +### Additions -Nothing yet. +- illumos: add FEN backend to support illumos and Solaris. ([#371]) + +- all: add `NewBufferedWatcher()` to use a buffered channel, which can be useful + in cases where you can't control the kernel buffer and receive a large number + of events in bursts. ([#550], [#572]) + +- all: add `AddWith()`, which is identical to `Add()` but allows passing + options. ([#521]) + +- windows: allow setting the ReadDirectoryChangesW() buffer size with + `fsnotify.WithBufferSize()`; the default of 64K is the highest value that + works on all platforms and is enough for most purposes, but in some cases a + highest buffer is needed. ([#521]) + +### Changes and fixes + +- inotify: remove watcher if a watched path is renamed ([#518]) + + After a rename the reported name wasn't updated, or even an empty string. + Inotify doesn't provide any good facilities to update it, so just remove the + watcher. This is already how it worked on kqueue and FEN. + + On Windows this does work, and remains working. + +- windows: don't listen for file attribute changes ([#520]) + + File attribute changes are sent as `FILE_ACTION_MODIFIED` by the Windows API, + with no way to see if they're a file write or attribute change, so would show + up as a fsnotify.Write event. This is never useful, and could result in many + spurious Write events. + +- windows: return `ErrEventOverflow` if the buffer is full ([#525]) + + Before it would merely return "short read", making it hard to detect this + error. + +- kqueue: make sure events for all files are delivered properly when removing a + watched directory ([#526]) + + Previously they would get sent with `""` (empty string) or `"."` as the path + name. + +- kqueue: don't emit spurious Create events for symbolic links ([#524]) + + The link would get resolved but kqueue would "forget" it already saw the link + itself, resulting on a Create for every Write event for the directory. + +- all: return `ErrClosed` on `Add()` when the watcher is closed ([#516]) + +- other: add `Watcher.Errors` and `Watcher.Events` to the no-op `Watcher` in + `backend_other.go`, making it easier to use on unsupported platforms such as + WASM, AIX, etc. ([#528]) + +- other: use the `backend_other.go` no-op if the `appengine` build tag is set; + Google AppEngine forbids usage of the unsafe package so the inotify backend + won't compile there. -## [1.6.0] - 2022-10-13 +[#371]: https://github.com/fsnotify/fsnotify/pull/371 +[#516]: https://github.com/fsnotify/fsnotify/pull/516 +[#518]: https://github.com/fsnotify/fsnotify/pull/518 +[#520]: https://github.com/fsnotify/fsnotify/pull/520 +[#521]: https://github.com/fsnotify/fsnotify/pull/521 +[#524]: https://github.com/fsnotify/fsnotify/pull/524 +[#525]: https://github.com/fsnotify/fsnotify/pull/525 +[#526]: https://github.com/fsnotify/fsnotify/pull/526 +[#528]: https://github.com/fsnotify/fsnotify/pull/528 +[#537]: https://github.com/fsnotify/fsnotify/pull/537 +[#550]: https://github.com/fsnotify/fsnotify/pull/550 +[#572]: https://github.com/fsnotify/fsnotify/pull/572 +1.6.0 - 2022-10-13 +------------------ This version of fsnotify needs Go 1.16 (this was already the case since 1.5.1, but not documented). It also increases the minimum Linux version to 2.6.32. diff --git a/vendor/github.com/fsnotify/fsnotify/README.md b/vendor/github.com/fsnotify/fsnotify/README.md index d4e6080fe..e480733d1 100644 --- a/vendor/github.com/fsnotify/fsnotify/README.md +++ b/vendor/github.com/fsnotify/fsnotify/README.md @@ -1,29 +1,31 @@ fsnotify is a Go library to provide cross-platform filesystem notifications on -Windows, Linux, macOS, and BSD systems. +Windows, Linux, macOS, BSD, and illumos. -Go 1.16 or newer is required; the full documentation is at +Go 1.17 or newer is required; the full documentation is at https://pkg.go.dev/github.com/fsnotify/fsnotify -**It's best to read the documentation at pkg.go.dev, as it's pinned to the last -released version, whereas this README is for the last development version which -may include additions/changes.** - --- Platform support: -| Adapter | OS | Status | -| --------------------- | ---------------| -------------------------------------------------------------| -| inotify | Linux 2.6.32+ | Supported | -| kqueue | BSD, macOS | Supported | -| ReadDirectoryChangesW | Windows | Supported | -| FSEvents | macOS | [Planned](https://github.com/fsnotify/fsnotify/issues/11) | -| FEN | Solaris 11 | [In Progress](https://github.com/fsnotify/fsnotify/pull/371) | -| fanotify | Linux 5.9+ | [Maybe](https://github.com/fsnotify/fsnotify/issues/114) | -| USN Journals | Windows | [Maybe](https://github.com/fsnotify/fsnotify/issues/53) | -| Polling | *All* | [Maybe](https://github.com/fsnotify/fsnotify/issues/9) | - -Linux and macOS should include Android and iOS, but these are currently untested. +| Backend | OS | Status | +| :-------------------- | :--------- | :------------------------------------------------------------------------ | +| inotify | Linux | Supported | +| kqueue | BSD, macOS | Supported | +| ReadDirectoryChangesW | Windows | Supported | +| FEN | illumos | Supported | +| fanotify | Linux 5.9+ | [Not yet](https://github.com/fsnotify/fsnotify/issues/114) | +| AHAFS | AIX | [aix branch]; experimental due to lack of maintainer and test environment | +| FSEvents | macOS | [Needs support in x/sys/unix][fsevents] | +| USN Journals | Windows | [Needs support in x/sys/windows][usn] | +| Polling | *All* | [Not yet](https://github.com/fsnotify/fsnotify/issues/9) | + +Linux and illumos should include Android and Solaris, but these are currently +untested. + +[fsevents]: https://github.com/fsnotify/fsnotify/issues/11#issuecomment-1279133120 +[usn]: https://github.com/fsnotify/fsnotify/issues/53#issuecomment-1279829847 +[aix branch]: https://github.com/fsnotify/fsnotify/issues/353#issuecomment-1284590129 Usage ----- @@ -83,20 +85,23 @@ run with: % go run ./cmd/fsnotify +Further detailed documentation can be found in godoc: +https://pkg.go.dev/github.com/fsnotify/fsnotify + FAQ --- ### Will a file still be watched when it's moved to another directory? No, not unless you are watching the location it was moved to. -### Are subdirectories watched too? +### Are subdirectories watched? No, you must add watches for any directory you want to watch (a recursive watcher is on the roadmap: [#18]). [#18]: https://github.com/fsnotify/fsnotify/issues/18 ### Do I have to watch the Error and Event channels in a goroutine? -As of now, yes (you can read both channels in the same goroutine using `select`, -you don't need a separate goroutine for both channels; see the example). +Yes. You can read both channels in the same goroutine using `select` (you don't +need a separate goroutine for both channels; see the example). ### Why don't notifications work with NFS, SMB, FUSE, /proc, or /sys? fsnotify requires support from underlying OS to work. The current NFS and SMB @@ -107,6 +112,32 @@ This could be fixed with a polling watcher ([#9]), but it's not yet implemented. [#9]: https://github.com/fsnotify/fsnotify/issues/9 +### Why do I get many Chmod events? +Some programs may generate a lot of attribute changes; for example Spotlight on +macOS, anti-virus programs, backup applications, and some others are known to do +this. As a rule, it's typically best to ignore Chmod events. They're often not +useful, and tend to cause problems. + +Spotlight indexing on macOS can result in multiple events (see [#15]). A +temporary workaround is to add your folder(s) to the *Spotlight Privacy +settings* until we have a native FSEvents implementation (see [#11]). + +[#11]: https://github.com/fsnotify/fsnotify/issues/11 +[#15]: https://github.com/fsnotify/fsnotify/issues/15 + +### Watching a file doesn't work well +Watching individual files (rather than directories) is generally not recommended +as many programs (especially editors) update files atomically: it will write to +a temporary file which is then moved to to destination, overwriting the original +(or some variant thereof). The watcher on the original file is now lost, as that +no longer exists. + +The upshot of this is that a power failure or crash won't leave a half-written +file. + +Watch the parent directory and use `Event.Name` to filter out files you're not +interested in. There is an example of this in `cmd/fsnotify/file.go`. + Platform-specific notes ----------------------- ### Linux @@ -151,11 +182,3 @@ these platforms. The sysctl variables `kern.maxfiles` and `kern.maxfilesperproc` can be used to control the maximum number of open files. - -### macOS -Spotlight indexing on macOS can result in multiple events (see [#15]). A temporary -workaround is to add your folder(s) to the *Spotlight Privacy settings* until we -have a native FSEvents implementation (see [#11]). - -[#11]: https://github.com/fsnotify/fsnotify/issues/11 -[#15]: https://github.com/fsnotify/fsnotify/issues/15 diff --git a/vendor/github.com/fsnotify/fsnotify/backend_fen.go b/vendor/github.com/fsnotify/fsnotify/backend_fen.go index 1a95ad8e7..28497f1dd 100644 --- a/vendor/github.com/fsnotify/fsnotify/backend_fen.go +++ b/vendor/github.com/fsnotify/fsnotify/backend_fen.go @@ -1,10 +1,19 @@ //go:build solaris // +build solaris +// Note: the documentation on the Watcher type and methods is generated from +// mkdoc.zsh + package fsnotify import ( "errors" + "fmt" + "os" + "path/filepath" + "sync" + + "golang.org/x/sys/unix" ) // Watcher watches a set of paths, delivering events on a channel. @@ -17,9 +26,9 @@ import ( // When a file is removed a Remove event won't be emitted until all file // descriptors are closed, and deletes will always emit a Chmod. For example: // -// fp := os.Open("file") -// os.Remove("file") // Triggers Chmod -// fp.Close() // Triggers Remove +// fp := os.Open("file") +// os.Remove("file") // Triggers Chmod +// fp.Close() // Triggers Remove // // This is the event that inotify sends, so not much can be changed about this. // @@ -33,16 +42,16 @@ import ( // // To increase them you can use sysctl or write the value to the /proc file: // -// # Default values on Linux 5.18 -// sysctl fs.inotify.max_user_watches=124983 -// sysctl fs.inotify.max_user_instances=128 +// # Default values on Linux 5.18 +// sysctl fs.inotify.max_user_watches=124983 +// sysctl fs.inotify.max_user_instances=128 // // To make the changes persist on reboot edit /etc/sysctl.conf or // /usr/lib/sysctl.d/50-default.conf (details differ per Linux distro; check // your distro's documentation): // -// fs.inotify.max_user_watches=124983 -// fs.inotify.max_user_instances=128 +// fs.inotify.max_user_watches=124983 +// fs.inotify.max_user_instances=128 // // Reaching the limit will result in a "no space left on device" or "too many open // files" error. @@ -58,14 +67,20 @@ import ( // control the maximum number of open files, as well as /etc/login.conf on BSD // systems. // -// # macOS notes +// # Windows notes +// +// Paths can be added as "C:\path\to\dir", but forward slashes +// ("C:/path/to/dir") will also work. // -// Spotlight indexing on macOS can result in multiple events (see [#15]). A -// temporary workaround is to add your folder(s) to the "Spotlight Privacy -// Settings" until we have a native FSEvents implementation (see [#11]). +// When a watched directory is removed it will always send an event for the +// directory itself, but may not send events for all files in that directory. +// Sometimes it will send events for all times, sometimes it will send no +// events, and often only for some files. // -// [#11]: https://github.com/fsnotify/fsnotify/issues/11 -// [#15]: https://github.com/fsnotify/fsnotify/issues/15 +// The default ReadDirectoryChangesW() buffer size is 64K, which is the largest +// value that is guaranteed to work with SMB filesystems. If you have many +// events in quick succession this may not be enough, and you will have to use +// [WithBufferSize] to increase the value. type Watcher struct { // Events sends the filesystem change events. // @@ -92,44 +107,129 @@ type Watcher struct { // initiated by the user may show up as one or multiple // writes, depending on when the system syncs things to // disk. For example when compiling a large Go program - // you may get hundreds of Write events, so you - // probably want to wait until you've stopped receiving - // them (see the dedup example in cmd/fsnotify). + // you may get hundreds of Write events, and you may + // want to wait until you've stopped receiving them + // (see the dedup example in cmd/fsnotify). + // + // Some systems may send Write event for directories + // when the directory content changes. // // fsnotify.Chmod Attributes were changed. On Linux this is also sent // when a file is removed (or more accurately, when a // link to an inode is removed). On kqueue it's sent - // and on kqueue when a file is truncated. On Windows - // it's never sent. + // when a file is truncated. On Windows it's never + // sent. Events chan Event // Errors sends any errors. + // + // ErrEventOverflow is used to indicate there are too many events: + // + // - inotify: There are too many queued events (fs.inotify.max_queued_events sysctl) + // - windows: The buffer size is too small; WithBufferSize() can be used to increase it. + // - kqueue, fen: Not used. Errors chan error + + mu sync.Mutex + port *unix.EventPort + done chan struct{} // Channel for sending a "quit message" to the reader goroutine + dirs map[string]struct{} // Explicitly watched directories + watches map[string]struct{} // Explicitly watched non-directories } // NewWatcher creates a new Watcher. func NewWatcher() (*Watcher, error) { - return nil, errors.New("FEN based watcher not yet supported for fsnotify\n") + return NewBufferedWatcher(0) } -// Close removes all watches and closes the events channel. +// NewBufferedWatcher creates a new Watcher with a buffered Watcher.Events +// channel. +// +// The main use case for this is situations with a very large number of events +// where the kernel buffer size can't be increased (e.g. due to lack of +// permissions). An unbuffered Watcher will perform better for almost all use +// cases, and whenever possible you will be better off increasing the kernel +// buffers instead of adding a large userspace buffer. +func NewBufferedWatcher(sz uint) (*Watcher, error) { + w := &Watcher{ + Events: make(chan Event, sz), + Errors: make(chan error), + dirs: make(map[string]struct{}), + watches: make(map[string]struct{}), + done: make(chan struct{}), + } + + var err error + w.port, err = unix.NewEventPort() + if err != nil { + return nil, fmt.Errorf("fsnotify.NewWatcher: %w", err) + } + + go w.readEvents() + return w, nil +} + +// sendEvent attempts to send an event to the user, returning true if the event +// was put in the channel successfully and false if the watcher has been closed. +func (w *Watcher) sendEvent(name string, op Op) (sent bool) { + select { + case w.Events <- Event{Name: name, Op: op}: + return true + case <-w.done: + return false + } +} + +// sendError attempts to send an error to the user, returning true if the error +// was put in the channel successfully and false if the watcher has been closed. +func (w *Watcher) sendError(err error) (sent bool) { + select { + case w.Errors <- err: + return true + case <-w.done: + return false + } +} + +func (w *Watcher) isClosed() bool { + select { + case <-w.done: + return true + default: + return false + } +} + +// Close removes all watches and closes the Events channel. func (w *Watcher) Close() error { - return nil + // Take the lock used by associateFile to prevent lingering events from + // being processed after the close + w.mu.Lock() + defer w.mu.Unlock() + if w.isClosed() { + return nil + } + close(w.done) + return w.port.Close() } // Add starts monitoring the path for changes. // -// A path can only be watched once; attempting to watch it more than once will -// return an error. Paths that do not yet exist on the filesystem cannot be -// added. A watch will be automatically removed if the path is deleted. +// A path can only be watched once; watching it more than once is a no-op and will +// not return an error. Paths that do not yet exist on the filesystem cannot be +// watched. // -// A path will remain watched if it gets renamed to somewhere else on the same -// filesystem, but the monitor will get removed if the path gets deleted and -// re-created, or if it's moved to a different filesystem. +// A watch will be automatically removed if the watched path is deleted or +// renamed. The exception is the Windows backend, which doesn't remove the +// watcher on renames. // // Notifications on network filesystems (NFS, SMB, FUSE, etc.) or special // filesystems (/proc, /sys, etc.) generally don't work. // +// Returns [ErrClosed] if [Watcher.Close] was called. +// +// See [Watcher.AddWith] for a version that allows adding options. +// // # Watching directories // // All files in a directory are monitored, including new files that are created @@ -139,15 +239,63 @@ func (w *Watcher) Close() error { // # Watching files // // Watching individual files (rather than directories) is generally not -// recommended as many tools update files atomically. Instead of "just" writing -// to the file a temporary file will be written to first, and if successful the -// temporary file is moved to to destination removing the original, or some -// variant thereof. The watcher on the original file is now lost, as it no -// longer exists. -// -// Instead, watch the parent directory and use Event.Name to filter out files -// you're not interested in. There is an example of this in [cmd/fsnotify/file.go]. -func (w *Watcher) Add(name string) error { +// recommended as many programs (especially editors) update files atomically: it +// will write to a temporary file which is then moved to to destination, +// overwriting the original (or some variant thereof). The watcher on the +// original file is now lost, as that no longer exists. +// +// The upshot of this is that a power failure or crash won't leave a +// half-written file. +// +// Watch the parent directory and use Event.Name to filter out files you're not +// interested in. There is an example of this in cmd/fsnotify/file.go. +func (w *Watcher) Add(name string) error { return w.AddWith(name) } + +// AddWith is like [Watcher.Add], but allows adding options. When using Add() +// the defaults described below are used. +// +// Possible options are: +// +// - [WithBufferSize] sets the buffer size for the Windows backend; no-op on +// other platforms. The default is 64K (65536 bytes). +func (w *Watcher) AddWith(name string, opts ...addOpt) error { + if w.isClosed() { + return ErrClosed + } + if w.port.PathIsWatched(name) { + return nil + } + + _ = getOptions(opts...) + + // Currently we resolve symlinks that were explicitly requested to be + // watched. Otherwise we would use LStat here. + stat, err := os.Stat(name) + if err != nil { + return err + } + + // Associate all files in the directory. + if stat.IsDir() { + err := w.handleDirectory(name, stat, true, w.associateFile) + if err != nil { + return err + } + + w.mu.Lock() + w.dirs[name] = struct{}{} + w.mu.Unlock() + return nil + } + + err = w.associateFile(name, stat, true) + if err != nil { + return err + } + + w.mu.Lock() + w.watches[name] = struct{}{} + w.mu.Unlock() return nil } @@ -157,6 +305,336 @@ func (w *Watcher) Add(name string) error { // /tmp/dir and /tmp/dir/subdir then you will need to remove both. // // Removing a path that has not yet been added returns [ErrNonExistentWatch]. +// +// Returns nil if [Watcher.Close] was called. func (w *Watcher) Remove(name string) error { + if w.isClosed() { + return nil + } + if !w.port.PathIsWatched(name) { + return fmt.Errorf("%w: %s", ErrNonExistentWatch, name) + } + + // The user has expressed an intent. Immediately remove this name from + // whichever watch list it might be in. If it's not in there the delete + // doesn't cause harm. + w.mu.Lock() + delete(w.watches, name) + delete(w.dirs, name) + w.mu.Unlock() + + stat, err := os.Stat(name) + if err != nil { + return err + } + + // Remove associations for every file in the directory. + if stat.IsDir() { + err := w.handleDirectory(name, stat, false, w.dissociateFile) + if err != nil { + return err + } + return nil + } + + err = w.port.DissociatePath(name) + if err != nil { + return err + } + return nil } + +// readEvents contains the main loop that runs in a goroutine watching for events. +func (w *Watcher) readEvents() { + // If this function returns, the watcher has been closed and we can close + // these channels + defer func() { + close(w.Errors) + close(w.Events) + }() + + pevents := make([]unix.PortEvent, 8) + for { + count, err := w.port.Get(pevents, 1, nil) + if err != nil && err != unix.ETIME { + // Interrupted system call (count should be 0) ignore and continue + if errors.Is(err, unix.EINTR) && count == 0 { + continue + } + // Get failed because we called w.Close() + if errors.Is(err, unix.EBADF) && w.isClosed() { + return + } + // There was an error not caused by calling w.Close() + if !w.sendError(err) { + return + } + } + + p := pevents[:count] + for _, pevent := range p { + if pevent.Source != unix.PORT_SOURCE_FILE { + // Event from unexpected source received; should never happen. + if !w.sendError(errors.New("Event from unexpected source received")) { + return + } + continue + } + + err = w.handleEvent(&pevent) + if err != nil { + if !w.sendError(err) { + return + } + } + } + } +} + +func (w *Watcher) handleDirectory(path string, stat os.FileInfo, follow bool, handler func(string, os.FileInfo, bool) error) error { + files, err := os.ReadDir(path) + if err != nil { + return err + } + + // Handle all children of the directory. + for _, entry := range files { + finfo, err := entry.Info() + if err != nil { + return err + } + err = handler(filepath.Join(path, finfo.Name()), finfo, false) + if err != nil { + return err + } + } + + // And finally handle the directory itself. + return handler(path, stat, follow) +} + +// handleEvent might need to emit more than one fsnotify event if the events +// bitmap matches more than one event type (e.g. the file was both modified and +// had the attributes changed between when the association was created and the +// when event was returned) +func (w *Watcher) handleEvent(event *unix.PortEvent) error { + var ( + events = event.Events + path = event.Path + fmode = event.Cookie.(os.FileMode) + reRegister = true + ) + + w.mu.Lock() + _, watchedDir := w.dirs[path] + _, watchedPath := w.watches[path] + w.mu.Unlock() + isWatched := watchedDir || watchedPath + + if events&unix.FILE_DELETE != 0 { + if !w.sendEvent(path, Remove) { + return nil + } + reRegister = false + } + if events&unix.FILE_RENAME_FROM != 0 { + if !w.sendEvent(path, Rename) { + return nil + } + // Don't keep watching the new file name + reRegister = false + } + if events&unix.FILE_RENAME_TO != 0 { + // We don't report a Rename event for this case, because Rename events + // are interpreted as referring to the _old_ name of the file, and in + // this case the event would refer to the new name of the file. This + // type of rename event is not supported by fsnotify. + + // inotify reports a Remove event in this case, so we simulate this + // here. + if !w.sendEvent(path, Remove) { + return nil + } + // Don't keep watching the file that was removed + reRegister = false + } + + // The file is gone, nothing left to do. + if !reRegister { + if watchedDir { + w.mu.Lock() + delete(w.dirs, path) + w.mu.Unlock() + } + if watchedPath { + w.mu.Lock() + delete(w.watches, path) + w.mu.Unlock() + } + return nil + } + + // If we didn't get a deletion the file still exists and we're going to have + // to watch it again. Let's Stat it now so that we can compare permissions + // and have what we need to continue watching the file + + stat, err := os.Lstat(path) + if err != nil { + // This is unexpected, but we should still emit an event. This happens + // most often on "rm -r" of a subdirectory inside a watched directory We + // get a modify event of something happening inside, but by the time we + // get here, the sudirectory is already gone. Clearly we were watching + // this path but now it is gone. Let's tell the user that it was + // removed. + if !w.sendEvent(path, Remove) { + return nil + } + // Suppress extra write events on removed directories; they are not + // informative and can be confusing. + return nil + } + + // resolve symlinks that were explicitly watched as we would have at Add() + // time. this helps suppress spurious Chmod events on watched symlinks + if isWatched { + stat, err = os.Stat(path) + if err != nil { + // The symlink still exists, but the target is gone. Report the + // Remove similar to above. + if !w.sendEvent(path, Remove) { + return nil + } + // Don't return the error + } + } + + if events&unix.FILE_MODIFIED != 0 { + if fmode.IsDir() { + if watchedDir { + if err := w.updateDirectory(path); err != nil { + return err + } + } else { + if !w.sendEvent(path, Write) { + return nil + } + } + } else { + if !w.sendEvent(path, Write) { + return nil + } + } + } + if events&unix.FILE_ATTRIB != 0 && stat != nil { + // Only send Chmod if perms changed + if stat.Mode().Perm() != fmode.Perm() { + if !w.sendEvent(path, Chmod) { + return nil + } + } + } + + if stat != nil { + // If we get here, it means we've hit an event above that requires us to + // continue watching the file or directory + return w.associateFile(path, stat, isWatched) + } + return nil +} + +func (w *Watcher) updateDirectory(path string) error { + // The directory was modified, so we must find unwatched entities and watch + // them. If something was removed from the directory, nothing will happen, + // as everything else should still be watched. + files, err := os.ReadDir(path) + if err != nil { + return err + } + + for _, entry := range files { + path := filepath.Join(path, entry.Name()) + if w.port.PathIsWatched(path) { + continue + } + + finfo, err := entry.Info() + if err != nil { + return err + } + err = w.associateFile(path, finfo, false) + if err != nil { + if !w.sendError(err) { + return nil + } + } + if !w.sendEvent(path, Create) { + return nil + } + } + return nil +} + +func (w *Watcher) associateFile(path string, stat os.FileInfo, follow bool) error { + if w.isClosed() { + return ErrClosed + } + // This is primarily protecting the call to AssociatePath but it is + // important and intentional that the call to PathIsWatched is also + // protected by this mutex. Without this mutex, AssociatePath has been seen + // to error out that the path is already associated. + w.mu.Lock() + defer w.mu.Unlock() + + if w.port.PathIsWatched(path) { + // Remove the old association in favor of this one If we get ENOENT, + // then while the x/sys/unix wrapper still thought that this path was + // associated, the underlying event port did not. This call will have + // cleared up that discrepancy. The most likely cause is that the event + // has fired but we haven't processed it yet. + err := w.port.DissociatePath(path) + if err != nil && err != unix.ENOENT { + return err + } + } + // FILE_NOFOLLOW means we watch symlinks themselves rather than their + // targets. + events := unix.FILE_MODIFIED | unix.FILE_ATTRIB | unix.FILE_NOFOLLOW + if follow { + // We *DO* follow symlinks for explicitly watched entries. + events = unix.FILE_MODIFIED | unix.FILE_ATTRIB + } + return w.port.AssociatePath(path, stat, + events, + stat.Mode()) +} + +func (w *Watcher) dissociateFile(path string, stat os.FileInfo, unused bool) error { + if !w.port.PathIsWatched(path) { + return nil + } + return w.port.DissociatePath(path) +} + +// WatchList returns all paths explicitly added with [Watcher.Add] (and are not +// yet removed). +// +// Returns nil if [Watcher.Close] was called. +func (w *Watcher) WatchList() []string { + if w.isClosed() { + return nil + } + + w.mu.Lock() + defer w.mu.Unlock() + + entries := make([]string, 0, len(w.watches)+len(w.dirs)) + for pathname := range w.dirs { + entries = append(entries, pathname) + } + for pathname := range w.watches { + entries = append(entries, pathname) + } + + return entries +} diff --git a/vendor/github.com/fsnotify/fsnotify/backend_inotify.go b/vendor/github.com/fsnotify/fsnotify/backend_inotify.go index 54c77fbb0..921c1c1e4 100644 --- a/vendor/github.com/fsnotify/fsnotify/backend_inotify.go +++ b/vendor/github.com/fsnotify/fsnotify/backend_inotify.go @@ -1,5 +1,8 @@ -//go:build linux -// +build linux +//go:build linux && !appengine +// +build linux,!appengine + +// Note: the documentation on the Watcher type and methods is generated from +// mkdoc.zsh package fsnotify @@ -26,9 +29,9 @@ import ( // When a file is removed a Remove event won't be emitted until all file // descriptors are closed, and deletes will always emit a Chmod. For example: // -// fp := os.Open("file") -// os.Remove("file") // Triggers Chmod -// fp.Close() // Triggers Remove +// fp := os.Open("file") +// os.Remove("file") // Triggers Chmod +// fp.Close() // Triggers Remove // // This is the event that inotify sends, so not much can be changed about this. // @@ -42,16 +45,16 @@ import ( // // To increase them you can use sysctl or write the value to the /proc file: // -// # Default values on Linux 5.18 -// sysctl fs.inotify.max_user_watches=124983 -// sysctl fs.inotify.max_user_instances=128 +// # Default values on Linux 5.18 +// sysctl fs.inotify.max_user_watches=124983 +// sysctl fs.inotify.max_user_instances=128 // // To make the changes persist on reboot edit /etc/sysctl.conf or // /usr/lib/sysctl.d/50-default.conf (details differ per Linux distro; check // your distro's documentation): // -// fs.inotify.max_user_watches=124983 -// fs.inotify.max_user_instances=128 +// fs.inotify.max_user_watches=124983 +// fs.inotify.max_user_instances=128 // // Reaching the limit will result in a "no space left on device" or "too many open // files" error. @@ -67,14 +70,20 @@ import ( // control the maximum number of open files, as well as /etc/login.conf on BSD // systems. // -// # macOS notes +// # Windows notes +// +// Paths can be added as "C:\path\to\dir", but forward slashes +// ("C:/path/to/dir") will also work. // -// Spotlight indexing on macOS can result in multiple events (see [#15]). A -// temporary workaround is to add your folder(s) to the "Spotlight Privacy -// Settings" until we have a native FSEvents implementation (see [#11]). +// When a watched directory is removed it will always send an event for the +// directory itself, but may not send events for all files in that directory. +// Sometimes it will send events for all times, sometimes it will send no +// events, and often only for some files. // -// [#11]: https://github.com/fsnotify/fsnotify/issues/11 -// [#15]: https://github.com/fsnotify/fsnotify/issues/15 +// The default ReadDirectoryChangesW() buffer size is 64K, which is the largest +// value that is guaranteed to work with SMB filesystems. If you have many +// events in quick succession this may not be enough, and you will have to use +// [WithBufferSize] to increase the value. type Watcher struct { // Events sends the filesystem change events. // @@ -101,36 +110,148 @@ type Watcher struct { // initiated by the user may show up as one or multiple // writes, depending on when the system syncs things to // disk. For example when compiling a large Go program - // you may get hundreds of Write events, so you - // probably want to wait until you've stopped receiving - // them (see the dedup example in cmd/fsnotify). + // you may get hundreds of Write events, and you may + // want to wait until you've stopped receiving them + // (see the dedup example in cmd/fsnotify). + // + // Some systems may send Write event for directories + // when the directory content changes. // // fsnotify.Chmod Attributes were changed. On Linux this is also sent // when a file is removed (or more accurately, when a // link to an inode is removed). On kqueue it's sent - // and on kqueue when a file is truncated. On Windows - // it's never sent. + // when a file is truncated. On Windows it's never + // sent. Events chan Event // Errors sends any errors. + // + // ErrEventOverflow is used to indicate there are too many events: + // + // - inotify: There are too many queued events (fs.inotify.max_queued_events sysctl) + // - windows: The buffer size is too small; WithBufferSize() can be used to increase it. + // - kqueue, fen: Not used. Errors chan error // Store fd here as os.File.Read() will no longer return on close after // calling Fd(). See: https://github.com/golang/go/issues/26439 fd int - mu sync.Mutex // Map access inotifyFile *os.File - watches map[string]*watch // Map of inotify watches (key: path) - paths map[int]string // Map of watched paths (key: watch descriptor) - done chan struct{} // Channel for sending a "quit message" to the reader goroutine - doneResp chan struct{} // Channel to respond to Close + watches *watches + done chan struct{} // Channel for sending a "quit message" to the reader goroutine + closeMu sync.Mutex + doneResp chan struct{} // Channel to respond to Close +} + +type ( + watches struct { + mu sync.RWMutex + wd map[uint32]*watch // wd → watch + path map[string]uint32 // pathname → wd + } + watch struct { + wd uint32 // Watch descriptor (as returned by the inotify_add_watch() syscall) + flags uint32 // inotify flags of this watch (see inotify(7) for the list of valid flags) + path string // Watch path. + } +) + +func newWatches() *watches { + return &watches{ + wd: make(map[uint32]*watch), + path: make(map[string]uint32), + } +} + +func (w *watches) len() int { + w.mu.RLock() + defer w.mu.RUnlock() + return len(w.wd) +} + +func (w *watches) add(ww *watch) { + w.mu.Lock() + defer w.mu.Unlock() + w.wd[ww.wd] = ww + w.path[ww.path] = ww.wd +} + +func (w *watches) remove(wd uint32) { + w.mu.Lock() + defer w.mu.Unlock() + delete(w.path, w.wd[wd].path) + delete(w.wd, wd) +} + +func (w *watches) removePath(path string) (uint32, bool) { + w.mu.Lock() + defer w.mu.Unlock() + + wd, ok := w.path[path] + if !ok { + return 0, false + } + + delete(w.path, path) + delete(w.wd, wd) + + return wd, true +} + +func (w *watches) byPath(path string) *watch { + w.mu.RLock() + defer w.mu.RUnlock() + return w.wd[w.path[path]] +} + +func (w *watches) byWd(wd uint32) *watch { + w.mu.RLock() + defer w.mu.RUnlock() + return w.wd[wd] +} + +func (w *watches) updatePath(path string, f func(*watch) (*watch, error)) error { + w.mu.Lock() + defer w.mu.Unlock() + + var existing *watch + wd, ok := w.path[path] + if ok { + existing = w.wd[wd] + } + + upd, err := f(existing) + if err != nil { + return err + } + if upd != nil { + w.wd[upd.wd] = upd + w.path[upd.path] = upd.wd + + if upd.wd != wd { + delete(w.wd, wd) + } + } + + return nil } // NewWatcher creates a new Watcher. func NewWatcher() (*Watcher, error) { - // Create inotify fd - // Need to set the FD to nonblocking mode in order for SetDeadline methods to work - // Otherwise, blocking i/o operations won't terminate on close + return NewBufferedWatcher(0) +} + +// NewBufferedWatcher creates a new Watcher with a buffered Watcher.Events +// channel. +// +// The main use case for this is situations with a very large number of events +// where the kernel buffer size can't be increased (e.g. due to lack of +// permissions). An unbuffered Watcher will perform better for almost all use +// cases, and whenever possible you will be better off increasing the kernel +// buffers instead of adding a large userspace buffer. +func NewBufferedWatcher(sz uint) (*Watcher, error) { + // Need to set nonblocking mode for SetDeadline to work, otherwise blocking + // I/O operations won't terminate on close. fd, errno := unix.InotifyInit1(unix.IN_CLOEXEC | unix.IN_NONBLOCK) if fd == -1 { return nil, errno @@ -139,9 +260,8 @@ func NewWatcher() (*Watcher, error) { w := &Watcher{ fd: fd, inotifyFile: os.NewFile(uintptr(fd), ""), - watches: make(map[string]*watch), - paths: make(map[int]string), - Events: make(chan Event), + watches: newWatches(), + Events: make(chan Event, sz), Errors: make(chan error), done: make(chan struct{}), doneResp: make(chan struct{}), @@ -157,8 +277,8 @@ func (w *Watcher) sendEvent(e Event) bool { case w.Events <- e: return true case <-w.done: + return false } - return false } // Returns true if the error was sent, or false if watcher is closed. @@ -180,17 +300,15 @@ func (w *Watcher) isClosed() bool { } } -// Close removes all watches and closes the events channel. +// Close removes all watches and closes the Events channel. func (w *Watcher) Close() error { - w.mu.Lock() + w.closeMu.Lock() if w.isClosed() { - w.mu.Unlock() + w.closeMu.Unlock() return nil } - - // Send 'close' signal to goroutine, and set the Watcher to closed. close(w.done) - w.mu.Unlock() + w.closeMu.Unlock() // Causes any blocking reads to return with an error, provided the file // still supports deadline operations. @@ -207,17 +325,21 @@ func (w *Watcher) Close() error { // Add starts monitoring the path for changes. // -// A path can only be watched once; attempting to watch it more than once will -// return an error. Paths that do not yet exist on the filesystem cannot be -// added. A watch will be automatically removed if the path is deleted. +// A path can only be watched once; watching it more than once is a no-op and will +// not return an error. Paths that do not yet exist on the filesystem cannot be +// watched. // -// A path will remain watched if it gets renamed to somewhere else on the same -// filesystem, but the monitor will get removed if the path gets deleted and -// re-created, or if it's moved to a different filesystem. +// A watch will be automatically removed if the watched path is deleted or +// renamed. The exception is the Windows backend, which doesn't remove the +// watcher on renames. // // Notifications on network filesystems (NFS, SMB, FUSE, etc.) or special // filesystems (/proc, /sys, etc.) generally don't work. // +// Returns [ErrClosed] if [Watcher.Close] was called. +// +// See [Watcher.AddWith] for a version that allows adding options. +// // # Watching directories // // All files in a directory are monitored, including new files that are created @@ -227,44 +349,59 @@ func (w *Watcher) Close() error { // # Watching files // // Watching individual files (rather than directories) is generally not -// recommended as many tools update files atomically. Instead of "just" writing -// to the file a temporary file will be written to first, and if successful the -// temporary file is moved to to destination removing the original, or some -// variant thereof. The watcher on the original file is now lost, as it no -// longer exists. -// -// Instead, watch the parent directory and use Event.Name to filter out files -// you're not interested in. There is an example of this in [cmd/fsnotify/file.go]. -func (w *Watcher) Add(name string) error { - name = filepath.Clean(name) +// recommended as many programs (especially editors) update files atomically: it +// will write to a temporary file which is then moved to to destination, +// overwriting the original (or some variant thereof). The watcher on the +// original file is now lost, as that no longer exists. +// +// The upshot of this is that a power failure or crash won't leave a +// half-written file. +// +// Watch the parent directory and use Event.Name to filter out files you're not +// interested in. There is an example of this in cmd/fsnotify/file.go. +func (w *Watcher) Add(name string) error { return w.AddWith(name) } + +// AddWith is like [Watcher.Add], but allows adding options. When using Add() +// the defaults described below are used. +// +// Possible options are: +// +// - [WithBufferSize] sets the buffer size for the Windows backend; no-op on +// other platforms. The default is 64K (65536 bytes). +func (w *Watcher) AddWith(name string, opts ...addOpt) error { if w.isClosed() { - return errors.New("inotify instance already closed") + return ErrClosed } + name = filepath.Clean(name) + _ = getOptions(opts...) + var flags uint32 = unix.IN_MOVED_TO | unix.IN_MOVED_FROM | unix.IN_CREATE | unix.IN_ATTRIB | unix.IN_MODIFY | unix.IN_MOVE_SELF | unix.IN_DELETE | unix.IN_DELETE_SELF - w.mu.Lock() - defer w.mu.Unlock() - watchEntry := w.watches[name] - if watchEntry != nil { - flags |= watchEntry.flags | unix.IN_MASK_ADD - } - wd, errno := unix.InotifyAddWatch(w.fd, name, flags) - if wd == -1 { - return errno - } + return w.watches.updatePath(name, func(existing *watch) (*watch, error) { + if existing != nil { + flags |= existing.flags | unix.IN_MASK_ADD + } - if watchEntry == nil { - w.watches[name] = &watch{wd: uint32(wd), flags: flags} - w.paths[wd] = name - } else { - watchEntry.wd = uint32(wd) - watchEntry.flags = flags - } + wd, err := unix.InotifyAddWatch(w.fd, name, flags) + if wd == -1 { + return nil, err + } - return nil + if existing == nil { + return &watch{ + wd: uint32(wd), + path: name, + flags: flags, + }, nil + } + + existing.wd = uint32(wd) + existing.flags = flags + return existing, nil + }) } // Remove stops monitoring the path for changes. @@ -273,32 +410,22 @@ func (w *Watcher) Add(name string) error { // /tmp/dir and /tmp/dir/subdir then you will need to remove both. // // Removing a path that has not yet been added returns [ErrNonExistentWatch]. +// +// Returns nil if [Watcher.Close] was called. func (w *Watcher) Remove(name string) error { - name = filepath.Clean(name) - - // Fetch the watch. - w.mu.Lock() - defer w.mu.Unlock() - watch, ok := w.watches[name] + if w.isClosed() { + return nil + } + return w.remove(filepath.Clean(name)) +} - // Remove it from inotify. +func (w *Watcher) remove(name string) error { + wd, ok := w.watches.removePath(name) if !ok { return fmt.Errorf("%w: %s", ErrNonExistentWatch, name) } - // We successfully removed the watch if InotifyRmWatch doesn't return an - // error, we need to clean up our internal state to ensure it matches - // inotify's kernel state. - delete(w.paths, int(watch.wd)) - delete(w.watches, name) - - // inotify_rm_watch will return EINVAL if the file has been deleted; - // the inotify will already have been removed. - // watches and pathes are deleted in ignoreLinux() implicitly and asynchronously - // by calling inotify_rm_watch() below. e.g. readEvents() goroutine receives IN_IGNORE - // so that EINVAL means that the wd is being rm_watch()ed or its file removed - // by another thread and we have not received IN_IGNORE event. - success, errno := unix.InotifyRmWatch(w.fd, watch.wd) + success, errno := unix.InotifyRmWatch(w.fd, wd) if success == -1 { // TODO: Perhaps it's not helpful to return an error here in every case; // The only two possible errors are: @@ -312,28 +439,28 @@ func (w *Watcher) Remove(name string) error { // are watching is deleted. return errno } - return nil } -// WatchList returns all paths added with [Add] (and are not yet removed). +// WatchList returns all paths explicitly added with [Watcher.Add] (and are not +// yet removed). +// +// Returns nil if [Watcher.Close] was called. func (w *Watcher) WatchList() []string { - w.mu.Lock() - defer w.mu.Unlock() + if w.isClosed() { + return nil + } - entries := make([]string, 0, len(w.watches)) - for pathname := range w.watches { + entries := make([]string, 0, w.watches.len()) + w.watches.mu.RLock() + for pathname := range w.watches.path { entries = append(entries, pathname) } + w.watches.mu.RUnlock() return entries } -type watch struct { - wd uint32 // Watch descriptor (as returned by the inotify_add_watch() syscall) - flags uint32 // inotify flags of this watch (see inotify(7) for the list of valid flags) -} - // readEvents reads from the inotify file descriptor, converts the // received events into Event objects and sends them via the Events channel func (w *Watcher) readEvents() { @@ -367,14 +494,11 @@ func (w *Watcher) readEvents() { if n < unix.SizeofInotifyEvent { var err error if n == 0 { - // If EOF is received. This should really never happen. - err = io.EOF + err = io.EOF // If EOF is received. This should really never happen. } else if n < 0 { - // If an error occurred while reading. - err = errno + err = errno // If an error occurred while reading. } else { - // Read was too short. - err = errors.New("notify: short read in readEvents()") + err = errors.New("notify: short read in readEvents()") // Read was too short. } if !w.sendError(err) { return @@ -403,18 +527,29 @@ func (w *Watcher) readEvents() { // doesn't append the filename to the event, but we would like to always fill the // the "Name" field with a valid filename. We retrieve the path of the watch from // the "paths" map. - w.mu.Lock() - name, ok := w.paths[int(raw.Wd)] - // IN_DELETE_SELF occurs when the file/directory being watched is removed. - // This is a sign to clean up the maps, otherwise we are no longer in sync - // with the inotify kernel state which has already deleted the watch - // automatically. - if ok && mask&unix.IN_DELETE_SELF == unix.IN_DELETE_SELF { - delete(w.paths, int(raw.Wd)) - delete(w.watches, name) + watch := w.watches.byWd(uint32(raw.Wd)) + + // inotify will automatically remove the watch on deletes; just need + // to clean our state here. + if watch != nil && mask&unix.IN_DELETE_SELF == unix.IN_DELETE_SELF { + w.watches.remove(watch.wd) + } + // We can't really update the state when a watched path is moved; + // only IN_MOVE_SELF is sent and not IN_MOVED_{FROM,TO}. So remove + // the watch. + if watch != nil && mask&unix.IN_MOVE_SELF == unix.IN_MOVE_SELF { + err := w.remove(watch.path) + if err != nil && !errors.Is(err, ErrNonExistentWatch) { + if !w.sendError(err) { + return + } + } } - w.mu.Unlock() + var name string + if watch != nil { + name = watch.path + } if nameLen > 0 { // Point "bytes" at the first byte of the filename bytes := (*[unix.PathMax]byte)(unsafe.Pointer(&buf[offset+unix.SizeofInotifyEvent]))[:nameLen:nameLen] diff --git a/vendor/github.com/fsnotify/fsnotify/backend_kqueue.go b/vendor/github.com/fsnotify/fsnotify/backend_kqueue.go index 29087469b..063a0915a 100644 --- a/vendor/github.com/fsnotify/fsnotify/backend_kqueue.go +++ b/vendor/github.com/fsnotify/fsnotify/backend_kqueue.go @@ -1,12 +1,14 @@ //go:build freebsd || openbsd || netbsd || dragonfly || darwin // +build freebsd openbsd netbsd dragonfly darwin +// Note: the documentation on the Watcher type and methods is generated from +// mkdoc.zsh + package fsnotify import ( "errors" "fmt" - "io/ioutil" "os" "path/filepath" "sync" @@ -24,9 +26,9 @@ import ( // When a file is removed a Remove event won't be emitted until all file // descriptors are closed, and deletes will always emit a Chmod. For example: // -// fp := os.Open("file") -// os.Remove("file") // Triggers Chmod -// fp.Close() // Triggers Remove +// fp := os.Open("file") +// os.Remove("file") // Triggers Chmod +// fp.Close() // Triggers Remove // // This is the event that inotify sends, so not much can be changed about this. // @@ -40,16 +42,16 @@ import ( // // To increase them you can use sysctl or write the value to the /proc file: // -// # Default values on Linux 5.18 -// sysctl fs.inotify.max_user_watches=124983 -// sysctl fs.inotify.max_user_instances=128 +// # Default values on Linux 5.18 +// sysctl fs.inotify.max_user_watches=124983 +// sysctl fs.inotify.max_user_instances=128 // // To make the changes persist on reboot edit /etc/sysctl.conf or // /usr/lib/sysctl.d/50-default.conf (details differ per Linux distro; check // your distro's documentation): // -// fs.inotify.max_user_watches=124983 -// fs.inotify.max_user_instances=128 +// fs.inotify.max_user_watches=124983 +// fs.inotify.max_user_instances=128 // // Reaching the limit will result in a "no space left on device" or "too many open // files" error. @@ -65,14 +67,20 @@ import ( // control the maximum number of open files, as well as /etc/login.conf on BSD // systems. // -// # macOS notes +// # Windows notes +// +// Paths can be added as "C:\path\to\dir", but forward slashes +// ("C:/path/to/dir") will also work. // -// Spotlight indexing on macOS can result in multiple events (see [#15]). A -// temporary workaround is to add your folder(s) to the "Spotlight Privacy -// Settings" until we have a native FSEvents implementation (see [#11]). +// When a watched directory is removed it will always send an event for the +// directory itself, but may not send events for all files in that directory. +// Sometimes it will send events for all times, sometimes it will send no +// events, and often only for some files. // -// [#11]: https://github.com/fsnotify/fsnotify/issues/11 -// [#15]: https://github.com/fsnotify/fsnotify/issues/15 +// The default ReadDirectoryChangesW() buffer size is 64K, which is the largest +// value that is guaranteed to work with SMB filesystems. If you have many +// events in quick succession this may not be enough, and you will have to use +// [WithBufferSize] to increase the value. type Watcher struct { // Events sends the filesystem change events. // @@ -99,18 +107,27 @@ type Watcher struct { // initiated by the user may show up as one or multiple // writes, depending on when the system syncs things to // disk. For example when compiling a large Go program - // you may get hundreds of Write events, so you - // probably want to wait until you've stopped receiving - // them (see the dedup example in cmd/fsnotify). + // you may get hundreds of Write events, and you may + // want to wait until you've stopped receiving them + // (see the dedup example in cmd/fsnotify). + // + // Some systems may send Write event for directories + // when the directory content changes. // // fsnotify.Chmod Attributes were changed. On Linux this is also sent // when a file is removed (or more accurately, when a // link to an inode is removed). On kqueue it's sent - // and on kqueue when a file is truncated. On Windows - // it's never sent. + // when a file is truncated. On Windows it's never + // sent. Events chan Event // Errors sends any errors. + // + // ErrEventOverflow is used to indicate there are too many events: + // + // - inotify: There are too many queued events (fs.inotify.max_queued_events sysctl) + // - windows: The buffer size is too small; WithBufferSize() can be used to increase it. + // - kqueue, fen: Not used. Errors chan error done chan struct{} @@ -133,6 +150,18 @@ type pathInfo struct { // NewWatcher creates a new Watcher. func NewWatcher() (*Watcher, error) { + return NewBufferedWatcher(0) +} + +// NewBufferedWatcher creates a new Watcher with a buffered Watcher.Events +// channel. +// +// The main use case for this is situations with a very large number of events +// where the kernel buffer size can't be increased (e.g. due to lack of +// permissions). An unbuffered Watcher will perform better for almost all use +// cases, and whenever possible you will be better off increasing the kernel +// buffers instead of adding a large userspace buffer. +func NewBufferedWatcher(sz uint) (*Watcher, error) { kq, closepipe, err := newKqueue() if err != nil { return nil, err @@ -147,7 +176,7 @@ func NewWatcher() (*Watcher, error) { paths: make(map[int]pathInfo), fileExists: make(map[string]struct{}), userWatches: make(map[string]struct{}), - Events: make(chan Event), + Events: make(chan Event, sz), Errors: make(chan error), done: make(chan struct{}), } @@ -197,8 +226,8 @@ func (w *Watcher) sendEvent(e Event) bool { case w.Events <- e: return true case <-w.done: + return false } - return false } // Returns true if the error was sent, or false if watcher is closed. @@ -207,11 +236,11 @@ func (w *Watcher) sendError(err error) bool { case w.Errors <- err: return true case <-w.done: + return false } - return false } -// Close removes all watches and closes the events channel. +// Close removes all watches and closes the Events channel. func (w *Watcher) Close() error { w.mu.Lock() if w.isClosed { @@ -239,17 +268,21 @@ func (w *Watcher) Close() error { // Add starts monitoring the path for changes. // -// A path can only be watched once; attempting to watch it more than once will -// return an error. Paths that do not yet exist on the filesystem cannot be -// added. A watch will be automatically removed if the path is deleted. +// A path can only be watched once; watching it more than once is a no-op and will +// not return an error. Paths that do not yet exist on the filesystem cannot be +// watched. // -// A path will remain watched if it gets renamed to somewhere else on the same -// filesystem, but the monitor will get removed if the path gets deleted and -// re-created, or if it's moved to a different filesystem. +// A watch will be automatically removed if the watched path is deleted or +// renamed. The exception is the Windows backend, which doesn't remove the +// watcher on renames. // // Notifications on network filesystems (NFS, SMB, FUSE, etc.) or special // filesystems (/proc, /sys, etc.) generally don't work. // +// Returns [ErrClosed] if [Watcher.Close] was called. +// +// See [Watcher.AddWith] for a version that allows adding options. +// // # Watching directories // // All files in a directory are monitored, including new files that are created @@ -259,15 +292,28 @@ func (w *Watcher) Close() error { // # Watching files // // Watching individual files (rather than directories) is generally not -// recommended as many tools update files atomically. Instead of "just" writing -// to the file a temporary file will be written to first, and if successful the -// temporary file is moved to to destination removing the original, or some -// variant thereof. The watcher on the original file is now lost, as it no -// longer exists. -// -// Instead, watch the parent directory and use Event.Name to filter out files -// you're not interested in. There is an example of this in [cmd/fsnotify/file.go]. -func (w *Watcher) Add(name string) error { +// recommended as many programs (especially editors) update files atomically: it +// will write to a temporary file which is then moved to to destination, +// overwriting the original (or some variant thereof). The watcher on the +// original file is now lost, as that no longer exists. +// +// The upshot of this is that a power failure or crash won't leave a +// half-written file. +// +// Watch the parent directory and use Event.Name to filter out files you're not +// interested in. There is an example of this in cmd/fsnotify/file.go. +func (w *Watcher) Add(name string) error { return w.AddWith(name) } + +// AddWith is like [Watcher.Add], but allows adding options. When using Add() +// the defaults described below are used. +// +// Possible options are: +// +// - [WithBufferSize] sets the buffer size for the Windows backend; no-op on +// other platforms. The default is 64K (65536 bytes). +func (w *Watcher) AddWith(name string, opts ...addOpt) error { + _ = getOptions(opts...) + w.mu.Lock() w.userWatches[name] = struct{}{} w.mu.Unlock() @@ -281,9 +327,19 @@ func (w *Watcher) Add(name string) error { // /tmp/dir and /tmp/dir/subdir then you will need to remove both. // // Removing a path that has not yet been added returns [ErrNonExistentWatch]. +// +// Returns nil if [Watcher.Close] was called. func (w *Watcher) Remove(name string) error { + return w.remove(name, true) +} + +func (w *Watcher) remove(name string, unwatchFiles bool) error { name = filepath.Clean(name) w.mu.Lock() + if w.isClosed { + w.mu.Unlock() + return nil + } watchfd, ok := w.watches[name] w.mu.Unlock() if !ok { @@ -315,7 +371,7 @@ func (w *Watcher) Remove(name string) error { w.mu.Unlock() // Find all watched paths that are in this directory that are not external. - if isDir { + if unwatchFiles && isDir { var pathsToRemove []string w.mu.Lock() for fd := range w.watchesByDir[name] { @@ -326,20 +382,25 @@ func (w *Watcher) Remove(name string) error { } w.mu.Unlock() for _, name := range pathsToRemove { - // Since these are internal, not much sense in propagating error - // to the user, as that will just confuse them with an error about - // a path they did not explicitly watch themselves. + // Since these are internal, not much sense in propagating error to + // the user, as that will just confuse them with an error about a + // path they did not explicitly watch themselves. w.Remove(name) } } - return nil } -// WatchList returns all paths added with [Add] (and are not yet removed). +// WatchList returns all paths explicitly added with [Watcher.Add] (and are not +// yet removed). +// +// Returns nil if [Watcher.Close] was called. func (w *Watcher) WatchList() []string { w.mu.Lock() defer w.mu.Unlock() + if w.isClosed { + return nil + } entries := make([]string, 0, len(w.userWatches)) for pathname := range w.userWatches { @@ -352,18 +413,18 @@ func (w *Watcher) WatchList() []string { // Watch all events (except NOTE_EXTEND, NOTE_LINK, NOTE_REVOKE) const noteAllEvents = unix.NOTE_DELETE | unix.NOTE_WRITE | unix.NOTE_ATTRIB | unix.NOTE_RENAME -// addWatch adds name to the watched file set. -// The flags are interpreted as described in kevent(2). -// Returns the real path to the file which was added, if any, which may be different from the one passed in the case of symlinks. +// addWatch adds name to the watched file set; the flags are interpreted as +// described in kevent(2). +// +// Returns the real path to the file which was added, with symlinks resolved. func (w *Watcher) addWatch(name string, flags uint32) (string, error) { var isDir bool - // Make ./name and name equivalent name = filepath.Clean(name) w.mu.Lock() if w.isClosed { w.mu.Unlock() - return "", errors.New("kevent instance already closed") + return "", ErrClosed } watchfd, alreadyWatching := w.watches[name] // We already have a watch, but we can still override flags. @@ -383,27 +444,30 @@ func (w *Watcher) addWatch(name string, flags uint32) (string, error) { return "", nil } - // Follow Symlinks - // - // Linux can add unresolvable symlinks to the watch list without issue, - // and Windows can't do symlinks period. To maintain consistency, we - // will act like everything is fine if the link can't be resolved. - // There will simply be no file events for broken symlinks. Hence the - // returns of nil on errors. + // Follow Symlinks. if fi.Mode()&os.ModeSymlink == os.ModeSymlink { - name, err = filepath.EvalSymlinks(name) + link, err := os.Readlink(name) if err != nil { + // Return nil because Linux can add unresolvable symlinks to the + // watch list without problems, so maintain consistency with + // that. There will be no file events for broken symlinks. + // TODO: more specific check; returns os.PathError; ENOENT? return "", nil } w.mu.Lock() - _, alreadyWatching = w.watches[name] + _, alreadyWatching = w.watches[link] w.mu.Unlock() if alreadyWatching { - return name, nil + // Add to watches so we don't get spurious Create events later + // on when we diff the directories. + w.watches[name] = 0 + w.fileExists[name] = struct{}{} + return link, nil } + name = link fi, err = os.Lstat(name) if err != nil { return "", nil @@ -411,7 +475,7 @@ func (w *Watcher) addWatch(name string, flags uint32) (string, error) { } // Retry on EINTR; open() can return EINTR in practice on macOS. - // See #354, and go issues 11180 and 39237. + // See #354, and Go issues 11180 and 39237. for { watchfd, err = unix.Open(name, openMode, 0) if err == nil { @@ -444,14 +508,13 @@ func (w *Watcher) addWatch(name string, flags uint32) (string, error) { w.watchesByDir[parentName] = watchesByDir } watchesByDir[watchfd] = struct{}{} - w.paths[watchfd] = pathInfo{name: name, isDir: isDir} w.mu.Unlock() } if isDir { - // Watch the directory if it has not been watched before, - // or if it was watched before, but perhaps only a NOTE_DELETE (watchDirectoryFiles) + // Watch the directory if it has not been watched before, or if it was + // watched before, but perhaps only a NOTE_DELETE (watchDirectoryFiles) w.mu.Lock() watchDir := (flags&unix.NOTE_WRITE) == unix.NOTE_WRITE && @@ -473,13 +536,10 @@ func (w *Watcher) addWatch(name string, flags uint32) (string, error) { // Event values that it sends down the Events channel. func (w *Watcher) readEvents() { defer func() { - err := unix.Close(w.kq) - if err != nil { - w.Errors <- err - } - unix.Close(w.closepipe[0]) close(w.Events) close(w.Errors) + _ = unix.Close(w.kq) + unix.Close(w.closepipe[0]) }() eventBuffer := make([]unix.Kevent_t, 10) @@ -513,18 +573,8 @@ func (w *Watcher) readEvents() { event := w.newEvent(path.name, mask) - if path.isDir && !event.Has(Remove) { - // Double check to make sure the directory exists. This can - // happen when we do a rm -fr on a recursively watched folders - // and we receive a modification event first but the folder has - // been deleted and later receive the delete event. - if _, err := os.Lstat(event.Name); os.IsNotExist(err) { - event.Op |= Remove - } - } - if event.Has(Rename) || event.Has(Remove) { - w.Remove(event.Name) + w.remove(event.Name, false) w.mu.Lock() delete(w.fileExists, event.Name) w.mu.Unlock() @@ -540,26 +590,30 @@ func (w *Watcher) readEvents() { } if event.Has(Remove) { - // Look for a file that may have overwritten this. - // For example, mv f1 f2 will delete f2, then create f2. + // Look for a file that may have overwritten this; for example, + // mv f1 f2 will delete f2, then create f2. if path.isDir { fileDir := filepath.Clean(event.Name) w.mu.Lock() _, found := w.watches[fileDir] w.mu.Unlock() if found { - // make sure the directory exists before we watch for changes. When we - // do a recursive watch and perform rm -fr, the parent directory might - // have gone missing, ignore the missing directory and let the - // upcoming delete event remove the watch from the parent directory. - if _, err := os.Lstat(fileDir); err == nil { - w.sendDirectoryChangeEvents(fileDir) + err := w.sendDirectoryChangeEvents(fileDir) + if err != nil { + if !w.sendError(err) { + closed = true + } } } } else { filePath := filepath.Clean(event.Name) - if fileInfo, err := os.Lstat(filePath); err == nil { - w.sendFileCreatedEventIfNew(filePath, fileInfo) + if fi, err := os.Lstat(filePath); err == nil { + err := w.sendFileCreatedEventIfNew(filePath, fi) + if err != nil { + if !w.sendError(err) { + closed = true + } + } } } } @@ -582,21 +636,31 @@ func (w *Watcher) newEvent(name string, mask uint32) Event { if mask&unix.NOTE_ATTRIB == unix.NOTE_ATTRIB { e.Op |= Chmod } + // No point sending a write and delete event at the same time: if it's gone, + // then it's gone. + if e.Op.Has(Write) && e.Op.Has(Remove) { + e.Op &^= Write + } return e } // watchDirectoryFiles to mimic inotify when adding a watch on a directory func (w *Watcher) watchDirectoryFiles(dirPath string) error { // Get all files - files, err := ioutil.ReadDir(dirPath) + files, err := os.ReadDir(dirPath) if err != nil { return err } - for _, fileInfo := range files { - path := filepath.Join(dirPath, fileInfo.Name()) + for _, f := range files { + path := filepath.Join(dirPath, f.Name()) + + fi, err := f.Info() + if err != nil { + return fmt.Errorf("%q: %w", path, err) + } - cleanPath, err := w.internalWatch(path, fileInfo) + cleanPath, err := w.internalWatch(path, fi) if err != nil { // No permission to read the file; that's not a problem: just skip. // But do add it to w.fileExists to prevent it from being picked up @@ -606,7 +670,7 @@ func (w *Watcher) watchDirectoryFiles(dirPath string) error { case errors.Is(err, unix.EACCES) || errors.Is(err, unix.EPERM): cleanPath = filepath.Clean(path) default: - return fmt.Errorf("%q: %w", filepath.Join(dirPath, fileInfo.Name()), err) + return fmt.Errorf("%q: %w", path, err) } } @@ -622,26 +686,37 @@ func (w *Watcher) watchDirectoryFiles(dirPath string) error { // // This functionality is to have the BSD watcher match the inotify, which sends // a create event for files created in a watched directory. -func (w *Watcher) sendDirectoryChangeEvents(dir string) { - // Get all files - files, err := ioutil.ReadDir(dir) +func (w *Watcher) sendDirectoryChangeEvents(dir string) error { + files, err := os.ReadDir(dir) if err != nil { - if !w.sendError(fmt.Errorf("fsnotify.sendDirectoryChangeEvents: %w", err)) { - return + // Directory no longer exists: we can ignore this safely. kqueue will + // still give us the correct events. + if errors.Is(err, os.ErrNotExist) { + return nil } + return fmt.Errorf("fsnotify.sendDirectoryChangeEvents: %w", err) } - // Search for new files - for _, fi := range files { - err := w.sendFileCreatedEventIfNew(filepath.Join(dir, fi.Name()), fi) + for _, f := range files { + fi, err := f.Info() if err != nil { - return + return fmt.Errorf("fsnotify.sendDirectoryChangeEvents: %w", err) + } + + err = w.sendFileCreatedEventIfNew(filepath.Join(dir, fi.Name()), fi) + if err != nil { + // Don't need to send an error if this file isn't readable. + if errors.Is(err, unix.EACCES) || errors.Is(err, unix.EPERM) { + return nil + } + return fmt.Errorf("fsnotify.sendDirectoryChangeEvents: %w", err) } } + return nil } // sendFileCreatedEvent sends a create event if the file isn't already being tracked. -func (w *Watcher) sendFileCreatedEventIfNew(filePath string, fileInfo os.FileInfo) (err error) { +func (w *Watcher) sendFileCreatedEventIfNew(filePath string, fi os.FileInfo) (err error) { w.mu.Lock() _, doesExist := w.fileExists[filePath] w.mu.Unlock() @@ -652,7 +727,7 @@ func (w *Watcher) sendFileCreatedEventIfNew(filePath string, fileInfo os.FileInf } // like watchDirectoryFiles (but without doing another ReadDir) - filePath, err = w.internalWatch(filePath, fileInfo) + filePath, err = w.internalWatch(filePath, fi) if err != nil { return err } @@ -664,10 +739,10 @@ func (w *Watcher) sendFileCreatedEventIfNew(filePath string, fileInfo os.FileInf return nil } -func (w *Watcher) internalWatch(name string, fileInfo os.FileInfo) (string, error) { - if fileInfo.IsDir() { - // mimic Linux providing delete events for subdirectories - // but preserve the flags used if currently watching subdirectory +func (w *Watcher) internalWatch(name string, fi os.FileInfo) (string, error) { + if fi.IsDir() { + // mimic Linux providing delete events for subdirectories, but preserve + // the flags used if currently watching subdirectory w.mu.Lock() flags := w.dirFlags[name] w.mu.Unlock() diff --git a/vendor/github.com/fsnotify/fsnotify/backend_other.go b/vendor/github.com/fsnotify/fsnotify/backend_other.go index a9bb1c3c4..d34a23c01 100644 --- a/vendor/github.com/fsnotify/fsnotify/backend_other.go +++ b/vendor/github.com/fsnotify/fsnotify/backend_other.go @@ -1,39 +1,169 @@ -//go:build !darwin && !dragonfly && !freebsd && !openbsd && !linux && !netbsd && !solaris && !windows -// +build !darwin,!dragonfly,!freebsd,!openbsd,!linux,!netbsd,!solaris,!windows +//go:build appengine || (!darwin && !dragonfly && !freebsd && !openbsd && !linux && !netbsd && !solaris && !windows) +// +build appengine !darwin,!dragonfly,!freebsd,!openbsd,!linux,!netbsd,!solaris,!windows + +// Note: the documentation on the Watcher type and methods is generated from +// mkdoc.zsh package fsnotify -import ( - "fmt" - "runtime" -) +import "errors" -// Watcher watches a set of files, delivering events to a channel. -type Watcher struct{} +// Watcher watches a set of paths, delivering events on a channel. +// +// A watcher should not be copied (e.g. pass it by pointer, rather than by +// value). +// +// # Linux notes +// +// When a file is removed a Remove event won't be emitted until all file +// descriptors are closed, and deletes will always emit a Chmod. For example: +// +// fp := os.Open("file") +// os.Remove("file") // Triggers Chmod +// fp.Close() // Triggers Remove +// +// This is the event that inotify sends, so not much can be changed about this. +// +// The fs.inotify.max_user_watches sysctl variable specifies the upper limit +// for the number of watches per user, and fs.inotify.max_user_instances +// specifies the maximum number of inotify instances per user. Every Watcher you +// create is an "instance", and every path you add is a "watch". +// +// These are also exposed in /proc as /proc/sys/fs/inotify/max_user_watches and +// /proc/sys/fs/inotify/max_user_instances +// +// To increase them you can use sysctl or write the value to the /proc file: +// +// # Default values on Linux 5.18 +// sysctl fs.inotify.max_user_watches=124983 +// sysctl fs.inotify.max_user_instances=128 +// +// To make the changes persist on reboot edit /etc/sysctl.conf or +// /usr/lib/sysctl.d/50-default.conf (details differ per Linux distro; check +// your distro's documentation): +// +// fs.inotify.max_user_watches=124983 +// fs.inotify.max_user_instances=128 +// +// Reaching the limit will result in a "no space left on device" or "too many open +// files" error. +// +// # kqueue notes (macOS, BSD) +// +// kqueue requires opening a file descriptor for every file that's being watched; +// so if you're watching a directory with five files then that's six file +// descriptors. You will run in to your system's "max open files" limit faster on +// these platforms. +// +// The sysctl variables kern.maxfiles and kern.maxfilesperproc can be used to +// control the maximum number of open files, as well as /etc/login.conf on BSD +// systems. +// +// # Windows notes +// +// Paths can be added as "C:\path\to\dir", but forward slashes +// ("C:/path/to/dir") will also work. +// +// When a watched directory is removed it will always send an event for the +// directory itself, but may not send events for all files in that directory. +// Sometimes it will send events for all times, sometimes it will send no +// events, and often only for some files. +// +// The default ReadDirectoryChangesW() buffer size is 64K, which is the largest +// value that is guaranteed to work with SMB filesystems. If you have many +// events in quick succession this may not be enough, and you will have to use +// [WithBufferSize] to increase the value. +type Watcher struct { + // Events sends the filesystem change events. + // + // fsnotify can send the following events; a "path" here can refer to a + // file, directory, symbolic link, or special file like a FIFO. + // + // fsnotify.Create A new path was created; this may be followed by one + // or more Write events if data also gets written to a + // file. + // + // fsnotify.Remove A path was removed. + // + // fsnotify.Rename A path was renamed. A rename is always sent with the + // old path as Event.Name, and a Create event will be + // sent with the new name. Renames are only sent for + // paths that are currently watched; e.g. moving an + // unmonitored file into a monitored directory will + // show up as just a Create. Similarly, renaming a file + // to outside a monitored directory will show up as + // only a Rename. + // + // fsnotify.Write A file or named pipe was written to. A Truncate will + // also trigger a Write. A single "write action" + // initiated by the user may show up as one or multiple + // writes, depending on when the system syncs things to + // disk. For example when compiling a large Go program + // you may get hundreds of Write events, and you may + // want to wait until you've stopped receiving them + // (see the dedup example in cmd/fsnotify). + // + // Some systems may send Write event for directories + // when the directory content changes. + // + // fsnotify.Chmod Attributes were changed. On Linux this is also sent + // when a file is removed (or more accurately, when a + // link to an inode is removed). On kqueue it's sent + // when a file is truncated. On Windows it's never + // sent. + Events chan Event + + // Errors sends any errors. + // + // ErrEventOverflow is used to indicate there are too many events: + // + // - inotify: There are too many queued events (fs.inotify.max_queued_events sysctl) + // - windows: The buffer size is too small; WithBufferSize() can be used to increase it. + // - kqueue, fen: Not used. + Errors chan error +} // NewWatcher creates a new Watcher. func NewWatcher() (*Watcher, error) { - return nil, fmt.Errorf("fsnotify not supported on %s", runtime.GOOS) + return nil, errors.New("fsnotify not supported on the current platform") } -// Close removes all watches and closes the events channel. -func (w *Watcher) Close() error { - return nil -} +// NewBufferedWatcher creates a new Watcher with a buffered Watcher.Events +// channel. +// +// The main use case for this is situations with a very large number of events +// where the kernel buffer size can't be increased (e.g. due to lack of +// permissions). An unbuffered Watcher will perform better for almost all use +// cases, and whenever possible you will be better off increasing the kernel +// buffers instead of adding a large userspace buffer. +func NewBufferedWatcher(sz uint) (*Watcher, error) { return NewWatcher() } + +// Close removes all watches and closes the Events channel. +func (w *Watcher) Close() error { return nil } + +// WatchList returns all paths explicitly added with [Watcher.Add] (and are not +// yet removed). +// +// Returns nil if [Watcher.Close] was called. +func (w *Watcher) WatchList() []string { return nil } // Add starts monitoring the path for changes. // -// A path can only be watched once; attempting to watch it more than once will -// return an error. Paths that do not yet exist on the filesystem cannot be -// added. A watch will be automatically removed if the path is deleted. +// A path can only be watched once; watching it more than once is a no-op and will +// not return an error. Paths that do not yet exist on the filesystem cannot be +// watched. // -// A path will remain watched if it gets renamed to somewhere else on the same -// filesystem, but the monitor will get removed if the path gets deleted and -// re-created, or if it's moved to a different filesystem. +// A watch will be automatically removed if the watched path is deleted or +// renamed. The exception is the Windows backend, which doesn't remove the +// watcher on renames. // // Notifications on network filesystems (NFS, SMB, FUSE, etc.) or special // filesystems (/proc, /sys, etc.) generally don't work. // +// Returns [ErrClosed] if [Watcher.Close] was called. +// +// See [Watcher.AddWith] for a version that allows adding options. +// // # Watching directories // // All files in a directory are monitored, including new files that are created @@ -43,17 +173,26 @@ func (w *Watcher) Close() error { // # Watching files // // Watching individual files (rather than directories) is generally not -// recommended as many tools update files atomically. Instead of "just" writing -// to the file a temporary file will be written to first, and if successful the -// temporary file is moved to to destination removing the original, or some -// variant thereof. The watcher on the original file is now lost, as it no -// longer exists. -// -// Instead, watch the parent directory and use Event.Name to filter out files -// you're not interested in. There is an example of this in [cmd/fsnotify/file.go]. -func (w *Watcher) Add(name string) error { - return nil -} +// recommended as many programs (especially editors) update files atomically: it +// will write to a temporary file which is then moved to to destination, +// overwriting the original (or some variant thereof). The watcher on the +// original file is now lost, as that no longer exists. +// +// The upshot of this is that a power failure or crash won't leave a +// half-written file. +// +// Watch the parent directory and use Event.Name to filter out files you're not +// interested in. There is an example of this in cmd/fsnotify/file.go. +func (w *Watcher) Add(name string) error { return nil } + +// AddWith is like [Watcher.Add], but allows adding options. When using Add() +// the defaults described below are used. +// +// Possible options are: +// +// - [WithBufferSize] sets the buffer size for the Windows backend; no-op on +// other platforms. The default is 64K (65536 bytes). +func (w *Watcher) AddWith(name string, opts ...addOpt) error { return nil } // Remove stops monitoring the path for changes. // @@ -61,6 +200,6 @@ func (w *Watcher) Add(name string) error { // /tmp/dir and /tmp/dir/subdir then you will need to remove both. // // Removing a path that has not yet been added returns [ErrNonExistentWatch]. -func (w *Watcher) Remove(name string) error { - return nil -} +// +// Returns nil if [Watcher.Close] was called. +func (w *Watcher) Remove(name string) error { return nil } diff --git a/vendor/github.com/fsnotify/fsnotify/backend_windows.go b/vendor/github.com/fsnotify/fsnotify/backend_windows.go index ae392867c..9bc91e5d6 100644 --- a/vendor/github.com/fsnotify/fsnotify/backend_windows.go +++ b/vendor/github.com/fsnotify/fsnotify/backend_windows.go @@ -1,6 +1,13 @@ //go:build windows // +build windows +// Windows backend based on ReadDirectoryChangesW() +// +// https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-readdirectorychangesw +// +// Note: the documentation on the Watcher type and methods is generated from +// mkdoc.zsh + package fsnotify import ( @@ -27,9 +34,9 @@ import ( // When a file is removed a Remove event won't be emitted until all file // descriptors are closed, and deletes will always emit a Chmod. For example: // -// fp := os.Open("file") -// os.Remove("file") // Triggers Chmod -// fp.Close() // Triggers Remove +// fp := os.Open("file") +// os.Remove("file") // Triggers Chmod +// fp.Close() // Triggers Remove // // This is the event that inotify sends, so not much can be changed about this. // @@ -43,16 +50,16 @@ import ( // // To increase them you can use sysctl or write the value to the /proc file: // -// # Default values on Linux 5.18 -// sysctl fs.inotify.max_user_watches=124983 -// sysctl fs.inotify.max_user_instances=128 +// # Default values on Linux 5.18 +// sysctl fs.inotify.max_user_watches=124983 +// sysctl fs.inotify.max_user_instances=128 // // To make the changes persist on reboot edit /etc/sysctl.conf or // /usr/lib/sysctl.d/50-default.conf (details differ per Linux distro; check // your distro's documentation): // -// fs.inotify.max_user_watches=124983 -// fs.inotify.max_user_instances=128 +// fs.inotify.max_user_watches=124983 +// fs.inotify.max_user_instances=128 // // Reaching the limit will result in a "no space left on device" or "too many open // files" error. @@ -68,14 +75,20 @@ import ( // control the maximum number of open files, as well as /etc/login.conf on BSD // systems. // -// # macOS notes +// # Windows notes // -// Spotlight indexing on macOS can result in multiple events (see [#15]). A -// temporary workaround is to add your folder(s) to the "Spotlight Privacy -// Settings" until we have a native FSEvents implementation (see [#11]). +// Paths can be added as "C:\path\to\dir", but forward slashes +// ("C:/path/to/dir") will also work. // -// [#11]: https://github.com/fsnotify/fsnotify/issues/11 -// [#15]: https://github.com/fsnotify/fsnotify/issues/15 +// When a watched directory is removed it will always send an event for the +// directory itself, but may not send events for all files in that directory. +// Sometimes it will send events for all times, sometimes it will send no +// events, and often only for some files. +// +// The default ReadDirectoryChangesW() buffer size is 64K, which is the largest +// value that is guaranteed to work with SMB filesystems. If you have many +// events in quick succession this may not be enough, and you will have to use +// [WithBufferSize] to increase the value. type Watcher struct { // Events sends the filesystem change events. // @@ -102,31 +115,52 @@ type Watcher struct { // initiated by the user may show up as one or multiple // writes, depending on when the system syncs things to // disk. For example when compiling a large Go program - // you may get hundreds of Write events, so you - // probably want to wait until you've stopped receiving - // them (see the dedup example in cmd/fsnotify). + // you may get hundreds of Write events, and you may + // want to wait until you've stopped receiving them + // (see the dedup example in cmd/fsnotify). + // + // Some systems may send Write event for directories + // when the directory content changes. // // fsnotify.Chmod Attributes were changed. On Linux this is also sent // when a file is removed (or more accurately, when a // link to an inode is removed). On kqueue it's sent - // and on kqueue when a file is truncated. On Windows - // it's never sent. + // when a file is truncated. On Windows it's never + // sent. Events chan Event // Errors sends any errors. + // + // ErrEventOverflow is used to indicate there are too many events: + // + // - inotify: There are too many queued events (fs.inotify.max_queued_events sysctl) + // - windows: The buffer size is too small; WithBufferSize() can be used to increase it. + // - kqueue, fen: Not used. Errors chan error port windows.Handle // Handle to completion port input chan *input // Inputs to the reader are sent on this channel quit chan chan<- error - mu sync.Mutex // Protects access to watches, isClosed - watches watchMap // Map of watches (key: i-number) - isClosed bool // Set to true when Close() is first called + mu sync.Mutex // Protects access to watches, closed + watches watchMap // Map of watches (key: i-number) + closed bool // Set to true when Close() is first called } // NewWatcher creates a new Watcher. func NewWatcher() (*Watcher, error) { + return NewBufferedWatcher(50) +} + +// NewBufferedWatcher creates a new Watcher with a buffered Watcher.Events +// channel. +// +// The main use case for this is situations with a very large number of events +// where the kernel buffer size can't be increased (e.g. due to lack of +// permissions). An unbuffered Watcher will perform better for almost all use +// cases, and whenever possible you will be better off increasing the kernel +// buffers instead of adding a large userspace buffer. +func NewBufferedWatcher(sz uint) (*Watcher, error) { port, err := windows.CreateIoCompletionPort(windows.InvalidHandle, 0, 0, 0) if err != nil { return nil, os.NewSyscallError("CreateIoCompletionPort", err) @@ -135,7 +169,7 @@ func NewWatcher() (*Watcher, error) { port: port, watches: make(watchMap), input: make(chan *input, 1), - Events: make(chan Event, 50), + Events: make(chan Event, sz), Errors: make(chan error), quit: make(chan chan<- error, 1), } @@ -143,6 +177,12 @@ func NewWatcher() (*Watcher, error) { return w, nil } +func (w *Watcher) isClosed() bool { + w.mu.Lock() + defer w.mu.Unlock() + return w.closed +} + func (w *Watcher) sendEvent(name string, mask uint64) bool { if mask == 0 { return false @@ -167,14 +207,14 @@ func (w *Watcher) sendError(err error) bool { return false } -// Close removes all watches and closes the events channel. +// Close removes all watches and closes the Events channel. func (w *Watcher) Close() error { - w.mu.Lock() - if w.isClosed { - w.mu.Unlock() + if w.isClosed() { return nil } - w.isClosed = true + + w.mu.Lock() + w.closed = true w.mu.Unlock() // Send "quit" message to the reader goroutine @@ -188,17 +228,21 @@ func (w *Watcher) Close() error { // Add starts monitoring the path for changes. // -// A path can only be watched once; attempting to watch it more than once will -// return an error. Paths that do not yet exist on the filesystem cannot be -// added. A watch will be automatically removed if the path is deleted. +// A path can only be watched once; watching it more than once is a no-op and will +// not return an error. Paths that do not yet exist on the filesystem cannot be +// watched. // -// A path will remain watched if it gets renamed to somewhere else on the same -// filesystem, but the monitor will get removed if the path gets deleted and -// re-created, or if it's moved to a different filesystem. +// A watch will be automatically removed if the watched path is deleted or +// renamed. The exception is the Windows backend, which doesn't remove the +// watcher on renames. // // Notifications on network filesystems (NFS, SMB, FUSE, etc.) or special // filesystems (/proc, /sys, etc.) generally don't work. // +// Returns [ErrClosed] if [Watcher.Close] was called. +// +// See [Watcher.AddWith] for a version that allows adding options. +// // # Watching directories // // All files in a directory are monitored, including new files that are created @@ -208,27 +252,41 @@ func (w *Watcher) Close() error { // # Watching files // // Watching individual files (rather than directories) is generally not -// recommended as many tools update files atomically. Instead of "just" writing -// to the file a temporary file will be written to first, and if successful the -// temporary file is moved to to destination removing the original, or some -// variant thereof. The watcher on the original file is now lost, as it no -// longer exists. -// -// Instead, watch the parent directory and use Event.Name to filter out files -// you're not interested in. There is an example of this in [cmd/fsnotify/file.go]. -func (w *Watcher) Add(name string) error { - w.mu.Lock() - if w.isClosed { - w.mu.Unlock() - return errors.New("watcher already closed") +// recommended as many programs (especially editors) update files atomically: it +// will write to a temporary file which is then moved to to destination, +// overwriting the original (or some variant thereof). The watcher on the +// original file is now lost, as that no longer exists. +// +// The upshot of this is that a power failure or crash won't leave a +// half-written file. +// +// Watch the parent directory and use Event.Name to filter out files you're not +// interested in. There is an example of this in cmd/fsnotify/file.go. +func (w *Watcher) Add(name string) error { return w.AddWith(name) } + +// AddWith is like [Watcher.Add], but allows adding options. When using Add() +// the defaults described below are used. +// +// Possible options are: +// +// - [WithBufferSize] sets the buffer size for the Windows backend; no-op on +// other platforms. The default is 64K (65536 bytes). +func (w *Watcher) AddWith(name string, opts ...addOpt) error { + if w.isClosed() { + return ErrClosed + } + + with := getOptions(opts...) + if with.bufsize < 4096 { + return fmt.Errorf("fsnotify.WithBufferSize: buffer size cannot be smaller than 4096 bytes") } - w.mu.Unlock() in := &input{ - op: opAddWatch, - path: filepath.Clean(name), - flags: sysFSALLEVENTS, - reply: make(chan error), + op: opAddWatch, + path: filepath.Clean(name), + flags: sysFSALLEVENTS, + reply: make(chan error), + bufsize: with.bufsize, } w.input <- in if err := w.wakeupReader(); err != nil { @@ -243,7 +301,13 @@ func (w *Watcher) Add(name string) error { // /tmp/dir and /tmp/dir/subdir then you will need to remove both. // // Removing a path that has not yet been added returns [ErrNonExistentWatch]. +// +// Returns nil if [Watcher.Close] was called. func (w *Watcher) Remove(name string) error { + if w.isClosed() { + return nil + } + in := &input{ op: opRemoveWatch, path: filepath.Clean(name), @@ -256,8 +320,15 @@ func (w *Watcher) Remove(name string) error { return <-in.reply } -// WatchList returns all paths added with [Add] (and are not yet removed). +// WatchList returns all paths explicitly added with [Watcher.Add] (and are not +// yet removed). +// +// Returns nil if [Watcher.Close] was called. func (w *Watcher) WatchList() []string { + if w.isClosed() { + return nil + } + w.mu.Lock() defer w.mu.Unlock() @@ -279,7 +350,6 @@ func (w *Watcher) WatchList() []string { // This should all be removed at some point, and just use windows.FILE_NOTIFY_* const ( sysFSALLEVENTS = 0xfff - sysFSATTRIB = 0x4 sysFSCREATE = 0x100 sysFSDELETE = 0x200 sysFSDELETESELF = 0x400 @@ -305,9 +375,6 @@ func (w *Watcher) newEvent(name string, mask uint32) Event { if mask&sysFSMOVE == sysFSMOVE || mask&sysFSMOVESELF == sysFSMOVESELF || mask&sysFSMOVEDFROM == sysFSMOVEDFROM { e.Op |= Rename } - if mask&sysFSATTRIB == sysFSATTRIB { - e.Op |= Chmod - } return e } @@ -321,10 +388,11 @@ const ( ) type input struct { - op int - path string - flags uint32 - reply chan error + op int + path string + flags uint32 + bufsize int + reply chan error } type inode struct { @@ -334,13 +402,14 @@ type inode struct { } type watch struct { - ov windows.Overlapped - ino *inode // i-number - path string // Directory path - mask uint64 // Directory itself is being watched with these notify flags - names map[string]uint64 // Map of names being watched and their notify flags - rename string // Remembers the old name while renaming a file - buf [65536]byte // 64K buffer + ov windows.Overlapped + ino *inode // i-number + recurse bool // Recursive watch? + path string // Directory path + mask uint64 // Directory itself is being watched with these notify flags + names map[string]uint64 // Map of names being watched and their notify flags + rename string // Remembers the old name while renaming a file + buf []byte // buffer, allocated later } type ( @@ -413,7 +482,10 @@ func (m watchMap) set(ino *inode, watch *watch) { } // Must run within the I/O thread. -func (w *Watcher) addWatch(pathname string, flags uint64) error { +func (w *Watcher) addWatch(pathname string, flags uint64, bufsize int) error { + //pathname, recurse := recursivePath(pathname) + recurse := false + dir, err := w.getDir(pathname) if err != nil { return err @@ -433,9 +505,11 @@ func (w *Watcher) addWatch(pathname string, flags uint64) error { return os.NewSyscallError("CreateIoCompletionPort", err) } watchEntry = &watch{ - ino: ino, - path: dir, - names: make(map[string]uint64), + ino: ino, + path: dir, + names: make(map[string]uint64), + recurse: recurse, + buf: make([]byte, bufsize), } w.mu.Lock() w.watches.set(ino, watchEntry) @@ -465,6 +539,8 @@ func (w *Watcher) addWatch(pathname string, flags uint64) error { // Must run within the I/O thread. func (w *Watcher) remWatch(pathname string) error { + pathname, recurse := recursivePath(pathname) + dir, err := w.getDir(pathname) if err != nil { return err @@ -478,6 +554,10 @@ func (w *Watcher) remWatch(pathname string) error { watch := w.watches.get(ino) w.mu.Unlock() + if recurse && !watch.recurse { + return fmt.Errorf("can't use \\... with non-recursive watch %q", pathname) + } + err = windows.CloseHandle(ino.handle) if err != nil { w.sendError(os.NewSyscallError("CloseHandle", err)) @@ -535,8 +615,11 @@ func (w *Watcher) startRead(watch *watch) error { return nil } - rdErr := windows.ReadDirectoryChanges(watch.ino.handle, &watch.buf[0], - uint32(unsafe.Sizeof(watch.buf)), false, mask, nil, &watch.ov, 0) + // We need to pass the array, rather than the slice. + hdr := (*reflect.SliceHeader)(unsafe.Pointer(&watch.buf)) + rdErr := windows.ReadDirectoryChanges(watch.ino.handle, + (*byte)(unsafe.Pointer(hdr.Data)), uint32(hdr.Len), + watch.recurse, mask, nil, &watch.ov, 0) if rdErr != nil { err := os.NewSyscallError("ReadDirectoryChanges", rdErr) if rdErr == windows.ERROR_ACCESS_DENIED && watch.mask&provisional == 0 { @@ -563,9 +646,8 @@ func (w *Watcher) readEvents() { runtime.LockOSThread() for { + // This error is handled after the watch == nil check below. qErr := windows.GetQueuedCompletionStatus(w.port, &n, &key, &ov, windows.INFINITE) - // This error is handled after the watch == nil check below. NOTE: this - // seems odd, note sure if it's correct. watch := (*watch)(unsafe.Pointer(ov)) if watch == nil { @@ -595,7 +677,7 @@ func (w *Watcher) readEvents() { case in := <-w.input: switch in.op { case opAddWatch: - in.reply <- w.addWatch(in.path, uint64(in.flags)) + in.reply <- w.addWatch(in.path, uint64(in.flags), in.bufsize) case opRemoveWatch: in.reply <- w.remWatch(in.path) } @@ -605,6 +687,8 @@ func (w *Watcher) readEvents() { } switch qErr { + case nil: + // No error case windows.ERROR_MORE_DATA: if watch == nil { w.sendError(errors.New("ERROR_MORE_DATA has unexpectedly null lpOverlapped buffer")) @@ -626,13 +710,12 @@ func (w *Watcher) readEvents() { default: w.sendError(os.NewSyscallError("GetQueuedCompletionPort", qErr)) continue - case nil: } var offset uint32 for { if n == 0 { - w.sendError(errors.New("short read in readEvents()")) + w.sendError(ErrEventOverflow) break } @@ -703,8 +786,9 @@ func (w *Watcher) readEvents() { // Error! if offset >= n { + //lint:ignore ST1005 Windows should be capitalized w.sendError(errors.New( - "Windows system assumed buffer larger than it is, events have likely been missed.")) + "Windows system assumed buffer larger than it is, events have likely been missed")) break } } @@ -720,9 +804,6 @@ func (w *Watcher) toWindowsFlags(mask uint64) uint32 { if mask&sysFSMODIFY != 0 { m |= windows.FILE_NOTIFY_CHANGE_LAST_WRITE } - if mask&sysFSATTRIB != 0 { - m |= windows.FILE_NOTIFY_CHANGE_ATTRIBUTES - } if mask&(sysFSMOVE|sysFSCREATE|sysFSDELETE) != 0 { m |= windows.FILE_NOTIFY_CHANGE_FILE_NAME | windows.FILE_NOTIFY_CHANGE_DIR_NAME } diff --git a/vendor/github.com/fsnotify/fsnotify/fsnotify.go b/vendor/github.com/fsnotify/fsnotify/fsnotify.go index 30a5bf0f0..24c99cc49 100644 --- a/vendor/github.com/fsnotify/fsnotify/fsnotify.go +++ b/vendor/github.com/fsnotify/fsnotify/fsnotify.go @@ -1,13 +1,18 @@ -//go:build !plan9 -// +build !plan9 - // Package fsnotify provides a cross-platform interface for file system // notifications. +// +// Currently supported systems: +// +// Linux 2.6.32+ via inotify +// BSD, macOS via kqueue +// Windows via ReadDirectoryChangesW +// illumos via FEN package fsnotify import ( "errors" "fmt" + "path/filepath" "strings" ) @@ -33,34 +38,52 @@ type Op uint32 // The operations fsnotify can trigger; see the documentation on [Watcher] for a // full description, and check them with [Event.Has]. const ( + // A new pathname was created. Create Op = 1 << iota + + // The pathname was written to; this does *not* mean the write has finished, + // and a write can be followed by more writes. Write + + // The path was removed; any watches on it will be removed. Some "remove" + // operations may trigger a Rename if the file is actually moved (for + // example "remove to trash" is often a rename). Remove + + // The path was renamed to something else; any watched on it will be + // removed. Rename + + // File attributes were changed. + // + // It's generally not recommended to take action on this event, as it may + // get triggered very frequently by some software. For example, Spotlight + // indexing on macOS, anti-virus software, backup software, etc. Chmod ) -// Common errors that can be reported by a watcher +// Common errors that can be reported. var ( - ErrNonExistentWatch = errors.New("can't remove non-existent watcher") - ErrEventOverflow = errors.New("fsnotify queue overflow") + ErrNonExistentWatch = errors.New("fsnotify: can't remove non-existent watch") + ErrEventOverflow = errors.New("fsnotify: queue or buffer overflow") + ErrClosed = errors.New("fsnotify: watcher already closed") ) -func (op Op) String() string { +func (o Op) String() string { var b strings.Builder - if op.Has(Create) { + if o.Has(Create) { b.WriteString("|CREATE") } - if op.Has(Remove) { + if o.Has(Remove) { b.WriteString("|REMOVE") } - if op.Has(Write) { + if o.Has(Write) { b.WriteString("|WRITE") } - if op.Has(Rename) { + if o.Has(Rename) { b.WriteString("|RENAME") } - if op.Has(Chmod) { + if o.Has(Chmod) { b.WriteString("|CHMOD") } if b.Len() == 0 { @@ -70,7 +93,7 @@ func (op Op) String() string { } // Has reports if this operation has the given operation. -func (o Op) Has(h Op) bool { return o&h == h } +func (o Op) Has(h Op) bool { return o&h != 0 } // Has reports if this event has the given operation. func (e Event) Has(op Op) bool { return e.Op.Has(op) } @@ -79,3 +102,45 @@ func (e Event) Has(op Op) bool { return e.Op.Has(op) } func (e Event) String() string { return fmt.Sprintf("%-13s %q", e.Op.String(), e.Name) } + +type ( + addOpt func(opt *withOpts) + withOpts struct { + bufsize int + } +) + +var defaultOpts = withOpts{ + bufsize: 65536, // 64K +} + +func getOptions(opts ...addOpt) withOpts { + with := defaultOpts + for _, o := range opts { + o(&with) + } + return with +} + +// WithBufferSize sets the [ReadDirectoryChangesW] buffer size. +// +// This only has effect on Windows systems, and is a no-op for other backends. +// +// The default value is 64K (65536 bytes) which is the highest value that works +// on all filesystems and should be enough for most applications, but if you +// have a large burst of events it may not be enough. You can increase it if +// you're hitting "queue or buffer overflow" errors ([ErrEventOverflow]). +// +// [ReadDirectoryChangesW]: https://learn.microsoft.com/en-gb/windows/win32/api/winbase/nf-winbase-readdirectorychangesw +func WithBufferSize(bytes int) addOpt { + return func(opt *withOpts) { opt.bufsize = bytes } +} + +// Check if this path is recursive (ends with "/..." or "\..."), and return the +// path with the /... stripped. +func recursivePath(path string) (string, bool) { + if filepath.Base(path) == "..." { + return filepath.Dir(path), true + } + return path, false +} diff --git a/vendor/github.com/fsnotify/fsnotify/mkdoc.zsh b/vendor/github.com/fsnotify/fsnotify/mkdoc.zsh index b09ef7683..99012ae65 100644 --- a/vendor/github.com/fsnotify/fsnotify/mkdoc.zsh +++ b/vendor/github.com/fsnotify/fsnotify/mkdoc.zsh @@ -2,8 +2,8 @@ [ "${ZSH_VERSION:-}" = "" ] && echo >&2 "Only works with zsh" && exit 1 setopt err_exit no_unset pipefail extended_glob -# Simple script to update the godoc comments on all watchers. Probably took me -# more time to write this than doing it manually, but ah well 🙃 +# Simple script to update the godoc comments on all watchers so you don't need +# to update the same comment 5 times. watcher=$(<elliptic in ecdsa key description (thanks @laverya) + +## Release 3.0.1 (2019-12-08) + +### Fixed + +- #212: Updated semver fixing broken constraint checking with ^0.0 + +## Release 3.0.0 (2019-10-02) + +### Added + +- #187: Added durationRound function (thanks @yjp20) +- #189: Added numerous template functions that return errors rather than panic (thanks @nrvnrvn) +- #193: Added toRawJson support (thanks @Dean-Coakley) +- #197: Added get support to dicts (thanks @Dean-Coakley) + +### Changed + +- #186: Moving dependency management to Go modules +- #186: Updated semver to v3. This has changes in the way ^ is handled +- #194: Updated documentation on merging and how it copies. Added example using deepCopy +- #196: trunc now supports negative values (thanks @Dean-Coakley) + +## Release 2.22.0 (2019-10-02) + +### Added + +- #173: Added getHostByName function to resolve dns names to ips (thanks @fcgravalos) +- #195: Added deepCopy function for use with dicts + +### Changed + +- Updated merge and mergeOverwrite documentation to explain copying and how to + use deepCopy with it + +## Release 2.21.0 (2019-09-18) + +### Added + +- #122: Added encryptAES/decryptAES functions (thanks @n0madic) +- #128: Added toDecimal support (thanks @Dean-Coakley) +- #169: Added list contcat (thanks @astorath) +- #174: Added deepEqual function (thanks @bonifaido) +- #170: Added url parse and join functions (thanks @astorath) + +### Changed + +- #171: Updated glide config for Google UUID to v1 and to add ranges to semver and testify + +### Fixed + +- #172: Fix semver wildcard example (thanks @piepmatz) +- #175: Fix dateInZone doc example (thanks @s3than) + +## Release 2.20.0 (2019-06-18) + +### Added + +- #164: Adding function to get unix epoch for a time (@mattfarina) +- #166: Adding tests for date_in_zone (@mattfarina) + +### Changed + +- #144: Fix function comments based on best practices from Effective Go (@CodeLingoTeam) +- #150: Handles pointer type for time.Time in "htmlDate" (@mapreal19) +- #161, #157, #160, #153, #158, #156, #155, #159, #152 documentation updates (@badeadan) + +### Fixed + +## Release 2.19.0 (2019-03-02) + +IMPORTANT: This release reverts a change from 2.18.0 + +In the previous release (2.18), we prematurely merged a partial change to the crypto functions that led to creating two sets of crypto functions (I blame @technosophos -- since that's me). This release rolls back that change, and does what was originally intended: It alters the existing crypto functions to use secure random. + +We debated whether this classifies as a change worthy of major revision, but given the proximity to the last release, we have decided that treating 2.18 as a faulty release is the correct course of action. We apologize for any inconvenience. + +### Changed + +- Fix substr panic 35fb796 (Alexey igrychev) +- Remove extra period 1eb7729 (Matthew Lorimor) +- Make random string functions use crypto by default 6ceff26 (Matthew Lorimor) +- README edits/fixes/suggestions 08fe136 (Lauri Apple) + + +## Release 2.18.0 (2019-02-12) + +### Added + +- Added mergeOverwrite function +- cryptographic functions that use secure random (see fe1de12) + +### Changed + +- Improve documentation of regexMatch function, resolves #139 90b89ce (Jan Tagscherer) +- Handle has for nil list 9c10885 (Daniel Cohen) +- Document behaviour of mergeOverwrite fe0dbe9 (Lukas Rieder) +- doc: adds missing documentation. 4b871e6 (Fernandez Ludovic) +- Replace outdated goutils imports 01893d2 (Matthew Lorimor) +- Surface crypto secure random strings from goutils fe1de12 (Matthew Lorimor) +- Handle untyped nil values as paramters to string functions 2b2ec8f (Morten Torkildsen) + +### Fixed + +- Fix dict merge issue and provide mergeOverwrite .dst .src1 to overwrite from src -> dst 4c59c12 (Lukas Rieder) +- Fix substr var names and comments d581f80 (Dean Coakley) +- Fix substr documentation 2737203 (Dean Coakley) + +## Release 2.17.1 (2019-01-03) + +### Fixed + +The 2.17.0 release did not have a version pinned for xstrings, which caused compilation failures when xstrings < 1.2 was used. This adds the correct version string to glide.yaml. + +## Release 2.17.0 (2019-01-03) + +### Added + +- adds alder32sum function and test 6908fc2 (marshallford) +- Added kebabcase function ca331a1 (Ilyes512) + +### Changed + +- Update goutils to 1.1.0 4e1125d (Matt Butcher) + +### Fixed + +- Fix 'has' documentation e3f2a85 (dean-coakley) +- docs(dict): fix typo in pick example dc424f9 (Dustin Specker) +- fixes spelling errors... not sure how that happened 4cf188a (marshallford) + +## Release 2.16.0 (2018-08-13) + +### Added + +- add splitn function fccb0b0 (Helgi Þorbjörnsson) +- Add slice func df28ca7 (gongdo) +- Generate serial number a3bdffd (Cody Coons) +- Extract values of dict with values function df39312 (Lawrence Jones) + +### Changed + +- Modify panic message for list.slice ae38335 (gongdo) +- Minor improvement in code quality - Removed an unreachable piece of code at defaults.go#L26:6 - Resolve formatting issues. 5834241 (Abhishek Kashyap) +- Remove duplicated documentation 1d97af1 (Matthew Fisher) +- Test on go 1.11 49df809 (Helgi Þormar Þorbjörnsson) + +### Fixed + +- Fix file permissions c5f40b5 (gongdo) +- Fix example for buildCustomCert 7779e0d (Tin Lam) + +## Release 2.15.0 (2018-04-02) + +### Added + +- #68 and #69: Add json helpers to docs (thanks @arunvelsriram) +- #66: Add ternary function (thanks @binoculars) +- #67: Allow keys function to take multiple dicts (thanks @binoculars) +- #89: Added sha1sum to crypto function (thanks @benkeil) +- #81: Allow customizing Root CA that used by genSignedCert (thanks @chenzhiwei) +- #92: Add travis testing for go 1.10 +- #93: Adding appveyor config for windows testing + +### Changed + +- #90: Updating to more recent dependencies +- #73: replace satori/go.uuid with google/uuid (thanks @petterw) + +### Fixed + +- #76: Fixed documentation typos (thanks @Thiht) +- Fixed rounding issue on the `ago` function. Note, the removes support for Go 1.8 and older + +## Release 2.14.1 (2017-12-01) + +### Fixed + +- #60: Fix typo in function name documentation (thanks @neil-ca-moore) +- #61: Removing line with {{ due to blocking github pages genertion +- #64: Update the list functions to handle int, string, and other slices for compatibility + +## Release 2.14.0 (2017-10-06) + +This new version of Sprig adds a set of functions for generating and working with SSL certificates. + +- `genCA` generates an SSL Certificate Authority +- `genSelfSignedCert` generates an SSL self-signed certificate +- `genSignedCert` generates an SSL certificate and key based on a given CA + +## Release 2.13.0 (2017-09-18) + +This release adds new functions, including: + +- `regexMatch`, `regexFindAll`, `regexFind`, `regexReplaceAll`, `regexReplaceAllLiteral`, and `regexSplit` to work with regular expressions +- `floor`, `ceil`, and `round` math functions +- `toDate` converts a string to a date +- `nindent` is just like `indent` but also prepends a new line +- `ago` returns the time from `time.Now` + +### Added + +- #40: Added basic regex functionality (thanks @alanquillin) +- #41: Added ceil floor and round functions (thanks @alanquillin) +- #48: Added toDate function (thanks @andreynering) +- #50: Added nindent function (thanks @binoculars) +- #46: Added ago function (thanks @slayer) + +### Changed + +- #51: Updated godocs to include new string functions (thanks @curtisallen) +- #49: Added ability to merge multiple dicts (thanks @binoculars) + +## Release 2.12.0 (2017-05-17) + +- `snakecase`, `camelcase`, and `shuffle` are three new string functions +- `fail` allows you to bail out of a template render when conditions are not met + +## Release 2.11.0 (2017-05-02) + +- Added `toJson` and `toPrettyJson` +- Added `merge` +- Refactored documentation + +## Release 2.10.0 (2017-03-15) + +- Added `semver` and `semverCompare` for Semantic Versions +- `list` replaces `tuple` +- Fixed issue with `join` +- Added `first`, `last`, `intial`, `rest`, `prepend`, `append`, `toString`, `toStrings`, `sortAlpha`, `reverse`, `coalesce`, `pluck`, `pick`, `compact`, `keys`, `omit`, `uniq`, `has`, `without` + +## Release 2.9.0 (2017-02-23) + +- Added `splitList` to split a list +- Added crypto functions of `genPrivateKey` and `derivePassword` + +## Release 2.8.0 (2016-12-21) + +- Added access to several path functions (`base`, `dir`, `clean`, `ext`, and `abs`) +- Added functions for _mutating_ dictionaries (`set`, `unset`, `hasKey`) + +## Release 2.7.0 (2016-12-01) + +- Added `sha256sum` to generate a hash of an input +- Added functions to convert a numeric or string to `int`, `int64`, `float64` + +## Release 2.6.0 (2016-10-03) + +- Added a `uuidv4` template function for generating UUIDs inside of a template. + +## Release 2.5.0 (2016-08-19) + +- New `trimSuffix`, `trimPrefix`, `hasSuffix`, and `hasPrefix` functions +- New aliases have been added for a few functions that didn't follow the naming conventions (`trimAll` and `abbrevBoth`) +- `trimall` and `abbrevboth` (notice the case) are deprecated and will be removed in 3.0.0 + +## Release 2.4.0 (2016-08-16) + +- Adds two functions: `until` and `untilStep` + +## Release 2.3.0 (2016-06-21) + +- cat: Concatenate strings with whitespace separators. +- replace: Replace parts of a string: `replace " " "-" "Me First"` renders "Me-First" +- plural: Format plurals: `len "foo" | plural "one foo" "many foos"` renders "many foos" +- indent: Indent blocks of text in a way that is sensitive to "\n" characters. + +## Release 2.2.0 (2016-04-21) + +- Added a `genPrivateKey` function (Thanks @bacongobbler) + +## Release 2.1.0 (2016-03-30) + +- `default` now prints the default value when it does not receive a value down the pipeline. It is much safer now to do `{{.Foo | default "bar"}}`. +- Added accessors for "hermetic" functions. These return only functions that, when given the same input, produce the same output. + +## Release 2.0.0 (2016-03-29) + +Because we switched from `int` to `int64` as the return value for all integer math functions, the library's major version number has been incremented. + +- `min` complements `max` (formerly `biggest`) +- `empty` indicates that a value is the empty value for its type +- `tuple` creates a tuple inside of a template: `{{$t := tuple "a", "b" "c"}}` +- `dict` creates a dictionary inside of a template `{{$d := dict "key1" "val1" "key2" "val2"}}` +- Date formatters have been added for HTML dates (as used in `date` input fields) +- Integer math functions can convert from a number of types, including `string` (via `strconv.ParseInt`). + +## Release 1.2.0 (2016-02-01) + +- Added quote and squote +- Added b32enc and b32dec +- add now takes varargs +- biggest now takes varargs + +## Release 1.1.0 (2015-12-29) + +- Added #4: Added contains function. strings.Contains, but with the arguments + switched to simplify common pipelines. (thanks krancour) +- Added Travis-CI testing support + +## Release 1.0.0 (2015-12-23) + +- Initial release diff --git a/vendor/github.com/go-task/slim-sprig/v3/LICENSE.txt b/vendor/github.com/go-task/slim-sprig/v3/LICENSE.txt new file mode 100644 index 000000000..f311b1eaa --- /dev/null +++ b/vendor/github.com/go-task/slim-sprig/v3/LICENSE.txt @@ -0,0 +1,19 @@ +Copyright (C) 2013-2020 Masterminds + +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/go-task/slim-sprig/v3/README.md b/vendor/github.com/go-task/slim-sprig/v3/README.md new file mode 100644 index 000000000..b5ab56425 --- /dev/null +++ b/vendor/github.com/go-task/slim-sprig/v3/README.md @@ -0,0 +1,73 @@ +# Slim-Sprig: Template functions for Go templates [![Go Reference](https://pkg.go.dev/badge/github.com/go-task/slim-sprig/v3.svg)](https://pkg.go.dev/github.com/go-task/slim-sprig/v3) + +Slim-Sprig is a fork of [Sprig](https://github.com/Masterminds/sprig), but with +all functions that depend on external (non standard library) or crypto packages +removed. +The reason for this is to make this library more lightweight. Most of these +functions (specially crypto ones) are not needed on most apps, but costs a lot +in terms of binary size and compilation time. + +## Usage + +**Template developers**: Please use Slim-Sprig's [function documentation](https://go-task.github.io/slim-sprig/) for +detailed instructions and code snippets for the >100 template functions available. + +**Go developers**: If you'd like to include Slim-Sprig as a library in your program, +our API documentation is available [at GoDoc.org](http://godoc.org/github.com/go-task/slim-sprig). + +For standard usage, read on. + +### Load the Slim-Sprig library + +To load the Slim-Sprig `FuncMap`: + +```go + +import ( + "html/template" + + "github.com/go-task/slim-sprig" +) + +// This example illustrates that the FuncMap *must* be set before the +// templates themselves are loaded. +tpl := template.Must( + template.New("base").Funcs(sprig.FuncMap()).ParseGlob("*.html") +) +``` + +### Calling the functions inside of templates + +By convention, all functions are lowercase. This seems to follow the Go +idiom for template functions (as opposed to template methods, which are +TitleCase). For example, this: + +``` +{{ "hello!" | upper | repeat 5 }} +``` + +produces this: + +``` +HELLO!HELLO!HELLO!HELLO!HELLO! +``` + +## Principles Driving Our Function Selection + +We followed these principles to decide which functions to add and how to implement them: + +- Use template functions to build layout. The following + types of operations are within the domain of template functions: + - Formatting + - Layout + - Simple type conversions + - Utilities that assist in handling common formatting and layout needs (e.g. arithmetic) +- Template functions should not return errors unless there is no way to print + a sensible value. For example, converting a string to an integer should not + produce an error if conversion fails. Instead, it should display a default + value. +- Simple math is necessary for grid layouts, pagers, and so on. Complex math + (anything other than arithmetic) should be done outside of templates. +- Template functions only deal with the data passed into them. They never retrieve + data from a source. +- Finally, do not override core Go template functions. diff --git a/vendor/github.com/go-task/slim-sprig/v3/Taskfile.yml b/vendor/github.com/go-task/slim-sprig/v3/Taskfile.yml new file mode 100644 index 000000000..8e6346bb1 --- /dev/null +++ b/vendor/github.com/go-task/slim-sprig/v3/Taskfile.yml @@ -0,0 +1,12 @@ +# https://taskfile.dev + +version: '3' + +tasks: + default: + cmds: + - task: test + + test: + cmds: + - go test -v . diff --git a/vendor/github.com/go-task/slim-sprig/v3/crypto.go b/vendor/github.com/go-task/slim-sprig/v3/crypto.go new file mode 100644 index 000000000..d06e516d4 --- /dev/null +++ b/vendor/github.com/go-task/slim-sprig/v3/crypto.go @@ -0,0 +1,24 @@ +package sprig + +import ( + "crypto/sha1" + "crypto/sha256" + "encoding/hex" + "fmt" + "hash/adler32" +) + +func sha256sum(input string) string { + hash := sha256.Sum256([]byte(input)) + return hex.EncodeToString(hash[:]) +} + +func sha1sum(input string) string { + hash := sha1.Sum([]byte(input)) + return hex.EncodeToString(hash[:]) +} + +func adler32sum(input string) string { + hash := adler32.Checksum([]byte(input)) + return fmt.Sprintf("%d", hash) +} diff --git a/vendor/github.com/go-task/slim-sprig/v3/date.go b/vendor/github.com/go-task/slim-sprig/v3/date.go new file mode 100644 index 000000000..ed022ddac --- /dev/null +++ b/vendor/github.com/go-task/slim-sprig/v3/date.go @@ -0,0 +1,152 @@ +package sprig + +import ( + "strconv" + "time" +) + +// Given a format and a date, format the date string. +// +// Date can be a `time.Time` or an `int, int32, int64`. +// In the later case, it is treated as seconds since UNIX +// epoch. +func date(fmt string, date interface{}) string { + return dateInZone(fmt, date, "Local") +} + +func htmlDate(date interface{}) string { + return dateInZone("2006-01-02", date, "Local") +} + +func htmlDateInZone(date interface{}, zone string) string { + return dateInZone("2006-01-02", date, zone) +} + +func dateInZone(fmt string, date interface{}, zone string) string { + var t time.Time + switch date := date.(type) { + default: + t = time.Now() + case time.Time: + t = date + case *time.Time: + t = *date + case int64: + t = time.Unix(date, 0) + case int: + t = time.Unix(int64(date), 0) + case int32: + t = time.Unix(int64(date), 0) + } + + loc, err := time.LoadLocation(zone) + if err != nil { + loc, _ = time.LoadLocation("UTC") + } + + return t.In(loc).Format(fmt) +} + +func dateModify(fmt string, date time.Time) time.Time { + d, err := time.ParseDuration(fmt) + if err != nil { + return date + } + return date.Add(d) +} + +func mustDateModify(fmt string, date time.Time) (time.Time, error) { + d, err := time.ParseDuration(fmt) + if err != nil { + return time.Time{}, err + } + return date.Add(d), nil +} + +func dateAgo(date interface{}) string { + var t time.Time + + switch date := date.(type) { + default: + t = time.Now() + case time.Time: + t = date + case int64: + t = time.Unix(date, 0) + case int: + t = time.Unix(int64(date), 0) + } + // Drop resolution to seconds + duration := time.Since(t).Round(time.Second) + return duration.String() +} + +func duration(sec interface{}) string { + var n int64 + switch value := sec.(type) { + default: + n = 0 + case string: + n, _ = strconv.ParseInt(value, 10, 64) + case int64: + n = value + } + return (time.Duration(n) * time.Second).String() +} + +func durationRound(duration interface{}) string { + var d time.Duration + switch duration := duration.(type) { + default: + d = 0 + case string: + d, _ = time.ParseDuration(duration) + case int64: + d = time.Duration(duration) + case time.Time: + d = time.Since(duration) + } + + u := uint64(d) + neg := d < 0 + if neg { + u = -u + } + + var ( + year = uint64(time.Hour) * 24 * 365 + month = uint64(time.Hour) * 24 * 30 + day = uint64(time.Hour) * 24 + hour = uint64(time.Hour) + minute = uint64(time.Minute) + second = uint64(time.Second) + ) + switch { + case u > year: + return strconv.FormatUint(u/year, 10) + "y" + case u > month: + return strconv.FormatUint(u/month, 10) + "mo" + case u > day: + return strconv.FormatUint(u/day, 10) + "d" + case u > hour: + return strconv.FormatUint(u/hour, 10) + "h" + case u > minute: + return strconv.FormatUint(u/minute, 10) + "m" + case u > second: + return strconv.FormatUint(u/second, 10) + "s" + } + return "0s" +} + +func toDate(fmt, str string) time.Time { + t, _ := time.ParseInLocation(fmt, str, time.Local) + return t +} + +func mustToDate(fmt, str string) (time.Time, error) { + return time.ParseInLocation(fmt, str, time.Local) +} + +func unixEpoch(date time.Time) string { + return strconv.FormatInt(date.Unix(), 10) +} diff --git a/vendor/github.com/go-task/slim-sprig/v3/defaults.go b/vendor/github.com/go-task/slim-sprig/v3/defaults.go new file mode 100644 index 000000000..b9f979666 --- /dev/null +++ b/vendor/github.com/go-task/slim-sprig/v3/defaults.go @@ -0,0 +1,163 @@ +package sprig + +import ( + "bytes" + "encoding/json" + "math/rand" + "reflect" + "strings" + "time" +) + +func init() { + rand.Seed(time.Now().UnixNano()) +} + +// dfault checks whether `given` is set, and returns default if not set. +// +// This returns `d` if `given` appears not to be set, and `given` otherwise. +// +// For numeric types 0 is unset. +// For strings, maps, arrays, and slices, len() = 0 is considered unset. +// For bool, false is unset. +// Structs are never considered unset. +// +// For everything else, including pointers, a nil value is unset. +func dfault(d interface{}, given ...interface{}) interface{} { + + if empty(given) || empty(given[0]) { + return d + } + return given[0] +} + +// empty returns true if the given value has the zero value for its type. +func empty(given interface{}) bool { + g := reflect.ValueOf(given) + if !g.IsValid() { + return true + } + + // Basically adapted from text/template.isTrue + switch g.Kind() { + default: + return g.IsNil() + case reflect.Array, reflect.Slice, reflect.Map, reflect.String: + return g.Len() == 0 + case reflect.Bool: + return !g.Bool() + case reflect.Complex64, reflect.Complex128: + return g.Complex() == 0 + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return g.Int() == 0 + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return g.Uint() == 0 + case reflect.Float32, reflect.Float64: + return g.Float() == 0 + case reflect.Struct: + return false + } +} + +// coalesce returns the first non-empty value. +func coalesce(v ...interface{}) interface{} { + for _, val := range v { + if !empty(val) { + return val + } + } + return nil +} + +// all returns true if empty(x) is false for all values x in the list. +// If the list is empty, return true. +func all(v ...interface{}) bool { + for _, val := range v { + if empty(val) { + return false + } + } + return true +} + +// any returns true if empty(x) is false for any x in the list. +// If the list is empty, return false. +func any(v ...interface{}) bool { + for _, val := range v { + if !empty(val) { + return true + } + } + return false +} + +// fromJson decodes JSON into a structured value, ignoring errors. +func fromJson(v string) interface{} { + output, _ := mustFromJson(v) + return output +} + +// mustFromJson decodes JSON into a structured value, returning errors. +func mustFromJson(v string) (interface{}, error) { + var output interface{} + err := json.Unmarshal([]byte(v), &output) + return output, err +} + +// toJson encodes an item into a JSON string +func toJson(v interface{}) string { + output, _ := json.Marshal(v) + return string(output) +} + +func mustToJson(v interface{}) (string, error) { + output, err := json.Marshal(v) + if err != nil { + return "", err + } + return string(output), nil +} + +// toPrettyJson encodes an item into a pretty (indented) JSON string +func toPrettyJson(v interface{}) string { + output, _ := json.MarshalIndent(v, "", " ") + return string(output) +} + +func mustToPrettyJson(v interface{}) (string, error) { + output, err := json.MarshalIndent(v, "", " ") + if err != nil { + return "", err + } + return string(output), nil +} + +// toRawJson encodes an item into a JSON string with no escaping of HTML characters. +func toRawJson(v interface{}) string { + output, err := mustToRawJson(v) + if err != nil { + panic(err) + } + return string(output) +} + +// mustToRawJson encodes an item into a JSON string with no escaping of HTML characters. +func mustToRawJson(v interface{}) (string, error) { + buf := new(bytes.Buffer) + enc := json.NewEncoder(buf) + enc.SetEscapeHTML(false) + err := enc.Encode(&v) + if err != nil { + return "", err + } + return strings.TrimSuffix(buf.String(), "\n"), nil +} + +// ternary returns the first value if the last value is true, otherwise returns the second value. +func ternary(vt interface{}, vf interface{}, v bool) interface{} { + if v { + return vt + } + + return vf +} diff --git a/vendor/github.com/go-task/slim-sprig/v3/dict.go b/vendor/github.com/go-task/slim-sprig/v3/dict.go new file mode 100644 index 000000000..77ebc61b1 --- /dev/null +++ b/vendor/github.com/go-task/slim-sprig/v3/dict.go @@ -0,0 +1,118 @@ +package sprig + +func get(d map[string]interface{}, key string) interface{} { + if val, ok := d[key]; ok { + return val + } + return "" +} + +func set(d map[string]interface{}, key string, value interface{}) map[string]interface{} { + d[key] = value + return d +} + +func unset(d map[string]interface{}, key string) map[string]interface{} { + delete(d, key) + return d +} + +func hasKey(d map[string]interface{}, key string) bool { + _, ok := d[key] + return ok +} + +func pluck(key string, d ...map[string]interface{}) []interface{} { + res := []interface{}{} + for _, dict := range d { + if val, ok := dict[key]; ok { + res = append(res, val) + } + } + return res +} + +func keys(dicts ...map[string]interface{}) []string { + k := []string{} + for _, dict := range dicts { + for key := range dict { + k = append(k, key) + } + } + return k +} + +func pick(dict map[string]interface{}, keys ...string) map[string]interface{} { + res := map[string]interface{}{} + for _, k := range keys { + if v, ok := dict[k]; ok { + res[k] = v + } + } + return res +} + +func omit(dict map[string]interface{}, keys ...string) map[string]interface{} { + res := map[string]interface{}{} + + omit := make(map[string]bool, len(keys)) + for _, k := range keys { + omit[k] = true + } + + for k, v := range dict { + if _, ok := omit[k]; !ok { + res[k] = v + } + } + return res +} + +func dict(v ...interface{}) map[string]interface{} { + dict := map[string]interface{}{} + lenv := len(v) + for i := 0; i < lenv; i += 2 { + key := strval(v[i]) + if i+1 >= lenv { + dict[key] = "" + continue + } + dict[key] = v[i+1] + } + return dict +} + +func values(dict map[string]interface{}) []interface{} { + values := []interface{}{} + for _, value := range dict { + values = append(values, value) + } + + return values +} + +func dig(ps ...interface{}) (interface{}, error) { + if len(ps) < 3 { + panic("dig needs at least three arguments") + } + dict := ps[len(ps)-1].(map[string]interface{}) + def := ps[len(ps)-2] + ks := make([]string, len(ps)-2) + for i := 0; i < len(ks); i++ { + ks[i] = ps[i].(string) + } + + return digFromDict(dict, def, ks) +} + +func digFromDict(dict map[string]interface{}, d interface{}, ks []string) (interface{}, error) { + k, ns := ks[0], ks[1:len(ks)] + step, has := dict[k] + if !has { + return d, nil + } + if len(ns) == 0 { + return step, nil + } + return digFromDict(step.(map[string]interface{}), d, ns) +} diff --git a/vendor/github.com/go-task/slim-sprig/v3/doc.go b/vendor/github.com/go-task/slim-sprig/v3/doc.go new file mode 100644 index 000000000..aabb9d448 --- /dev/null +++ b/vendor/github.com/go-task/slim-sprig/v3/doc.go @@ -0,0 +1,19 @@ +/* +Package sprig provides template functions for Go. + +This package contains a number of utility functions for working with data +inside of Go `html/template` and `text/template` files. + +To add these functions, use the `template.Funcs()` method: + + t := templates.New("foo").Funcs(sprig.FuncMap()) + +Note that you should add the function map before you parse any template files. + + In several cases, Sprig reverses the order of arguments from the way they + appear in the standard library. This is to make it easier to pipe + arguments into functions. + +See http://masterminds.github.io/sprig/ for more detailed documentation on each of the available functions. +*/ +package sprig diff --git a/vendor/github.com/go-task/slim-sprig/v3/functions.go b/vendor/github.com/go-task/slim-sprig/v3/functions.go new file mode 100644 index 000000000..5ea74f899 --- /dev/null +++ b/vendor/github.com/go-task/slim-sprig/v3/functions.go @@ -0,0 +1,317 @@ +package sprig + +import ( + "errors" + "html/template" + "math/rand" + "os" + "path" + "path/filepath" + "reflect" + "strconv" + "strings" + ttemplate "text/template" + "time" +) + +// FuncMap produces the function map. +// +// Use this to pass the functions into the template engine: +// +// tpl := template.New("foo").Funcs(sprig.FuncMap())) +// +func FuncMap() template.FuncMap { + return HtmlFuncMap() +} + +// HermeticTxtFuncMap returns a 'text/template'.FuncMap with only repeatable functions. +func HermeticTxtFuncMap() ttemplate.FuncMap { + r := TxtFuncMap() + for _, name := range nonhermeticFunctions { + delete(r, name) + } + return r +} + +// HermeticHtmlFuncMap returns an 'html/template'.Funcmap with only repeatable functions. +func HermeticHtmlFuncMap() template.FuncMap { + r := HtmlFuncMap() + for _, name := range nonhermeticFunctions { + delete(r, name) + } + return r +} + +// TxtFuncMap returns a 'text/template'.FuncMap +func TxtFuncMap() ttemplate.FuncMap { + return ttemplate.FuncMap(GenericFuncMap()) +} + +// HtmlFuncMap returns an 'html/template'.Funcmap +func HtmlFuncMap() template.FuncMap { + return template.FuncMap(GenericFuncMap()) +} + +// GenericFuncMap returns a copy of the basic function map as a map[string]interface{}. +func GenericFuncMap() map[string]interface{} { + gfm := make(map[string]interface{}, len(genericMap)) + for k, v := range genericMap { + gfm[k] = v + } + return gfm +} + +// These functions are not guaranteed to evaluate to the same result for given input, because they +// refer to the environment or global state. +var nonhermeticFunctions = []string{ + // Date functions + "date", + "date_in_zone", + "date_modify", + "now", + "htmlDate", + "htmlDateInZone", + "dateInZone", + "dateModify", + + // Strings + "randAlphaNum", + "randAlpha", + "randAscii", + "randNumeric", + "randBytes", + "uuidv4", + + // OS + "env", + "expandenv", + + // Network + "getHostByName", +} + +var genericMap = map[string]interface{}{ + "hello": func() string { return "Hello!" }, + + // Date functions + "ago": dateAgo, + "date": date, + "date_in_zone": dateInZone, + "date_modify": dateModify, + "dateInZone": dateInZone, + "dateModify": dateModify, + "duration": duration, + "durationRound": durationRound, + "htmlDate": htmlDate, + "htmlDateInZone": htmlDateInZone, + "must_date_modify": mustDateModify, + "mustDateModify": mustDateModify, + "mustToDate": mustToDate, + "now": time.Now, + "toDate": toDate, + "unixEpoch": unixEpoch, + + // Strings + "trunc": trunc, + "trim": strings.TrimSpace, + "upper": strings.ToUpper, + "lower": strings.ToLower, + "title": strings.Title, + "substr": substring, + // Switch order so that "foo" | repeat 5 + "repeat": func(count int, str string) string { return strings.Repeat(str, count) }, + // Deprecated: Use trimAll. + "trimall": func(a, b string) string { return strings.Trim(b, a) }, + // Switch order so that "$foo" | trimall "$" + "trimAll": func(a, b string) string { return strings.Trim(b, a) }, + "trimSuffix": func(a, b string) string { return strings.TrimSuffix(b, a) }, + "trimPrefix": func(a, b string) string { return strings.TrimPrefix(b, a) }, + // Switch order so that "foobar" | contains "foo" + "contains": func(substr string, str string) bool { return strings.Contains(str, substr) }, + "hasPrefix": func(substr string, str string) bool { return strings.HasPrefix(str, substr) }, + "hasSuffix": func(substr string, str string) bool { return strings.HasSuffix(str, substr) }, + "quote": quote, + "squote": squote, + "cat": cat, + "indent": indent, + "nindent": nindent, + "replace": replace, + "plural": plural, + "sha1sum": sha1sum, + "sha256sum": sha256sum, + "adler32sum": adler32sum, + "toString": strval, + + // Wrap Atoi to stop errors. + "atoi": func(a string) int { i, _ := strconv.Atoi(a); return i }, + "int64": toInt64, + "int": toInt, + "float64": toFloat64, + "seq": seq, + "toDecimal": toDecimal, + + //"gt": func(a, b int) bool {return a > b}, + //"gte": func(a, b int) bool {return a >= b}, + //"lt": func(a, b int) bool {return a < b}, + //"lte": func(a, b int) bool {return a <= b}, + + // split "/" foo/bar returns map[int]string{0: foo, 1: bar} + "split": split, + "splitList": func(sep, orig string) []string { return strings.Split(orig, sep) }, + // splitn "/" foo/bar/fuu returns map[int]string{0: foo, 1: bar/fuu} + "splitn": splitn, + "toStrings": strslice, + + "until": until, + "untilStep": untilStep, + + // VERY basic arithmetic. + "add1": func(i interface{}) int64 { return toInt64(i) + 1 }, + "add": func(i ...interface{}) int64 { + var a int64 = 0 + for _, b := range i { + a += toInt64(b) + } + return a + }, + "sub": func(a, b interface{}) int64 { return toInt64(a) - toInt64(b) }, + "div": func(a, b interface{}) int64 { return toInt64(a) / toInt64(b) }, + "mod": func(a, b interface{}) int64 { return toInt64(a) % toInt64(b) }, + "mul": func(a interface{}, v ...interface{}) int64 { + val := toInt64(a) + for _, b := range v { + val = val * toInt64(b) + } + return val + }, + "randInt": func(min, max int) int { return rand.Intn(max-min) + min }, + "biggest": max, + "max": max, + "min": min, + "maxf": maxf, + "minf": minf, + "ceil": ceil, + "floor": floor, + "round": round, + + // string slices. Note that we reverse the order b/c that's better + // for template processing. + "join": join, + "sortAlpha": sortAlpha, + + // Defaults + "default": dfault, + "empty": empty, + "coalesce": coalesce, + "all": all, + "any": any, + "compact": compact, + "mustCompact": mustCompact, + "fromJson": fromJson, + "toJson": toJson, + "toPrettyJson": toPrettyJson, + "toRawJson": toRawJson, + "mustFromJson": mustFromJson, + "mustToJson": mustToJson, + "mustToPrettyJson": mustToPrettyJson, + "mustToRawJson": mustToRawJson, + "ternary": ternary, + + // Reflection + "typeOf": typeOf, + "typeIs": typeIs, + "typeIsLike": typeIsLike, + "kindOf": kindOf, + "kindIs": kindIs, + "deepEqual": reflect.DeepEqual, + + // OS: + "env": os.Getenv, + "expandenv": os.ExpandEnv, + + // Network: + "getHostByName": getHostByName, + + // Paths: + "base": path.Base, + "dir": path.Dir, + "clean": path.Clean, + "ext": path.Ext, + "isAbs": path.IsAbs, + + // Filepaths: + "osBase": filepath.Base, + "osClean": filepath.Clean, + "osDir": filepath.Dir, + "osExt": filepath.Ext, + "osIsAbs": filepath.IsAbs, + + // Encoding: + "b64enc": base64encode, + "b64dec": base64decode, + "b32enc": base32encode, + "b32dec": base32decode, + + // Data Structures: + "tuple": list, // FIXME: with the addition of append/prepend these are no longer immutable. + "list": list, + "dict": dict, + "get": get, + "set": set, + "unset": unset, + "hasKey": hasKey, + "pluck": pluck, + "keys": keys, + "pick": pick, + "omit": omit, + "values": values, + + "append": push, "push": push, + "mustAppend": mustPush, "mustPush": mustPush, + "prepend": prepend, + "mustPrepend": mustPrepend, + "first": first, + "mustFirst": mustFirst, + "rest": rest, + "mustRest": mustRest, + "last": last, + "mustLast": mustLast, + "initial": initial, + "mustInitial": mustInitial, + "reverse": reverse, + "mustReverse": mustReverse, + "uniq": uniq, + "mustUniq": mustUniq, + "without": without, + "mustWithout": mustWithout, + "has": has, + "mustHas": mustHas, + "slice": slice, + "mustSlice": mustSlice, + "concat": concat, + "dig": dig, + "chunk": chunk, + "mustChunk": mustChunk, + + // Flow Control: + "fail": func(msg string) (string, error) { return "", errors.New(msg) }, + + // Regex + "regexMatch": regexMatch, + "mustRegexMatch": mustRegexMatch, + "regexFindAll": regexFindAll, + "mustRegexFindAll": mustRegexFindAll, + "regexFind": regexFind, + "mustRegexFind": mustRegexFind, + "regexReplaceAll": regexReplaceAll, + "mustRegexReplaceAll": mustRegexReplaceAll, + "regexReplaceAllLiteral": regexReplaceAllLiteral, + "mustRegexReplaceAllLiteral": mustRegexReplaceAllLiteral, + "regexSplit": regexSplit, + "mustRegexSplit": mustRegexSplit, + "regexQuoteMeta": regexQuoteMeta, + + // URLs: + "urlParse": urlParse, + "urlJoin": urlJoin, +} diff --git a/vendor/github.com/go-task/slim-sprig/v3/list.go b/vendor/github.com/go-task/slim-sprig/v3/list.go new file mode 100644 index 000000000..ca0fbb789 --- /dev/null +++ b/vendor/github.com/go-task/slim-sprig/v3/list.go @@ -0,0 +1,464 @@ +package sprig + +import ( + "fmt" + "math" + "reflect" + "sort" +) + +// Reflection is used in these functions so that slices and arrays of strings, +// ints, and other types not implementing []interface{} can be worked with. +// For example, this is useful if you need to work on the output of regexs. + +func list(v ...interface{}) []interface{} { + return v +} + +func push(list interface{}, v interface{}) []interface{} { + l, err := mustPush(list, v) + if err != nil { + panic(err) + } + + return l +} + +func mustPush(list interface{}, v interface{}) ([]interface{}, error) { + tp := reflect.TypeOf(list).Kind() + switch tp { + case reflect.Slice, reflect.Array: + l2 := reflect.ValueOf(list) + + l := l2.Len() + nl := make([]interface{}, l) + for i := 0; i < l; i++ { + nl[i] = l2.Index(i).Interface() + } + + return append(nl, v), nil + + default: + return nil, fmt.Errorf("Cannot push on type %s", tp) + } +} + +func prepend(list interface{}, v interface{}) []interface{} { + l, err := mustPrepend(list, v) + if err != nil { + panic(err) + } + + return l +} + +func mustPrepend(list interface{}, v interface{}) ([]interface{}, error) { + //return append([]interface{}{v}, list...) + + tp := reflect.TypeOf(list).Kind() + switch tp { + case reflect.Slice, reflect.Array: + l2 := reflect.ValueOf(list) + + l := l2.Len() + nl := make([]interface{}, l) + for i := 0; i < l; i++ { + nl[i] = l2.Index(i).Interface() + } + + return append([]interface{}{v}, nl...), nil + + default: + return nil, fmt.Errorf("Cannot prepend on type %s", tp) + } +} + +func chunk(size int, list interface{}) [][]interface{} { + l, err := mustChunk(size, list) + if err != nil { + panic(err) + } + + return l +} + +func mustChunk(size int, list interface{}) ([][]interface{}, error) { + tp := reflect.TypeOf(list).Kind() + switch tp { + case reflect.Slice, reflect.Array: + l2 := reflect.ValueOf(list) + + l := l2.Len() + + cs := int(math.Floor(float64(l-1)/float64(size)) + 1) + nl := make([][]interface{}, cs) + + for i := 0; i < cs; i++ { + clen := size + if i == cs-1 { + clen = int(math.Floor(math.Mod(float64(l), float64(size)))) + if clen == 0 { + clen = size + } + } + + nl[i] = make([]interface{}, clen) + + for j := 0; j < clen; j++ { + ix := i*size + j + nl[i][j] = l2.Index(ix).Interface() + } + } + + return nl, nil + + default: + return nil, fmt.Errorf("Cannot chunk type %s", tp) + } +} + +func last(list interface{}) interface{} { + l, err := mustLast(list) + if err != nil { + panic(err) + } + + return l +} + +func mustLast(list interface{}) (interface{}, error) { + tp := reflect.TypeOf(list).Kind() + switch tp { + case reflect.Slice, reflect.Array: + l2 := reflect.ValueOf(list) + + l := l2.Len() + if l == 0 { + return nil, nil + } + + return l2.Index(l - 1).Interface(), nil + default: + return nil, fmt.Errorf("Cannot find last on type %s", tp) + } +} + +func first(list interface{}) interface{} { + l, err := mustFirst(list) + if err != nil { + panic(err) + } + + return l +} + +func mustFirst(list interface{}) (interface{}, error) { + tp := reflect.TypeOf(list).Kind() + switch tp { + case reflect.Slice, reflect.Array: + l2 := reflect.ValueOf(list) + + l := l2.Len() + if l == 0 { + return nil, nil + } + + return l2.Index(0).Interface(), nil + default: + return nil, fmt.Errorf("Cannot find first on type %s", tp) + } +} + +func rest(list interface{}) []interface{} { + l, err := mustRest(list) + if err != nil { + panic(err) + } + + return l +} + +func mustRest(list interface{}) ([]interface{}, error) { + tp := reflect.TypeOf(list).Kind() + switch tp { + case reflect.Slice, reflect.Array: + l2 := reflect.ValueOf(list) + + l := l2.Len() + if l == 0 { + return nil, nil + } + + nl := make([]interface{}, l-1) + for i := 1; i < l; i++ { + nl[i-1] = l2.Index(i).Interface() + } + + return nl, nil + default: + return nil, fmt.Errorf("Cannot find rest on type %s", tp) + } +} + +func initial(list interface{}) []interface{} { + l, err := mustInitial(list) + if err != nil { + panic(err) + } + + return l +} + +func mustInitial(list interface{}) ([]interface{}, error) { + tp := reflect.TypeOf(list).Kind() + switch tp { + case reflect.Slice, reflect.Array: + l2 := reflect.ValueOf(list) + + l := l2.Len() + if l == 0 { + return nil, nil + } + + nl := make([]interface{}, l-1) + for i := 0; i < l-1; i++ { + nl[i] = l2.Index(i).Interface() + } + + return nl, nil + default: + return nil, fmt.Errorf("Cannot find initial on type %s", tp) + } +} + +func sortAlpha(list interface{}) []string { + k := reflect.Indirect(reflect.ValueOf(list)).Kind() + switch k { + case reflect.Slice, reflect.Array: + a := strslice(list) + s := sort.StringSlice(a) + s.Sort() + return s + } + return []string{strval(list)} +} + +func reverse(v interface{}) []interface{} { + l, err := mustReverse(v) + if err != nil { + panic(err) + } + + return l +} + +func mustReverse(v interface{}) ([]interface{}, error) { + tp := reflect.TypeOf(v).Kind() + switch tp { + case reflect.Slice, reflect.Array: + l2 := reflect.ValueOf(v) + + l := l2.Len() + // We do not sort in place because the incoming array should not be altered. + nl := make([]interface{}, l) + for i := 0; i < l; i++ { + nl[l-i-1] = l2.Index(i).Interface() + } + + return nl, nil + default: + return nil, fmt.Errorf("Cannot find reverse on type %s", tp) + } +} + +func compact(list interface{}) []interface{} { + l, err := mustCompact(list) + if err != nil { + panic(err) + } + + return l +} + +func mustCompact(list interface{}) ([]interface{}, error) { + tp := reflect.TypeOf(list).Kind() + switch tp { + case reflect.Slice, reflect.Array: + l2 := reflect.ValueOf(list) + + l := l2.Len() + nl := []interface{}{} + var item interface{} + for i := 0; i < l; i++ { + item = l2.Index(i).Interface() + if !empty(item) { + nl = append(nl, item) + } + } + + return nl, nil + default: + return nil, fmt.Errorf("Cannot compact on type %s", tp) + } +} + +func uniq(list interface{}) []interface{} { + l, err := mustUniq(list) + if err != nil { + panic(err) + } + + return l +} + +func mustUniq(list interface{}) ([]interface{}, error) { + tp := reflect.TypeOf(list).Kind() + switch tp { + case reflect.Slice, reflect.Array: + l2 := reflect.ValueOf(list) + + l := l2.Len() + dest := []interface{}{} + var item interface{} + for i := 0; i < l; i++ { + item = l2.Index(i).Interface() + if !inList(dest, item) { + dest = append(dest, item) + } + } + + return dest, nil + default: + return nil, fmt.Errorf("Cannot find uniq on type %s", tp) + } +} + +func inList(haystack []interface{}, needle interface{}) bool { + for _, h := range haystack { + if reflect.DeepEqual(needle, h) { + return true + } + } + return false +} + +func without(list interface{}, omit ...interface{}) []interface{} { + l, err := mustWithout(list, omit...) + if err != nil { + panic(err) + } + + return l +} + +func mustWithout(list interface{}, omit ...interface{}) ([]interface{}, error) { + tp := reflect.TypeOf(list).Kind() + switch tp { + case reflect.Slice, reflect.Array: + l2 := reflect.ValueOf(list) + + l := l2.Len() + res := []interface{}{} + var item interface{} + for i := 0; i < l; i++ { + item = l2.Index(i).Interface() + if !inList(omit, item) { + res = append(res, item) + } + } + + return res, nil + default: + return nil, fmt.Errorf("Cannot find without on type %s", tp) + } +} + +func has(needle interface{}, haystack interface{}) bool { + l, err := mustHas(needle, haystack) + if err != nil { + panic(err) + } + + return l +} + +func mustHas(needle interface{}, haystack interface{}) (bool, error) { + if haystack == nil { + return false, nil + } + tp := reflect.TypeOf(haystack).Kind() + switch tp { + case reflect.Slice, reflect.Array: + l2 := reflect.ValueOf(haystack) + var item interface{} + l := l2.Len() + for i := 0; i < l; i++ { + item = l2.Index(i).Interface() + if reflect.DeepEqual(needle, item) { + return true, nil + } + } + + return false, nil + default: + return false, fmt.Errorf("Cannot find has on type %s", tp) + } +} + +// $list := [1, 2, 3, 4, 5] +// slice $list -> list[0:5] = list[:] +// slice $list 0 3 -> list[0:3] = list[:3] +// slice $list 3 5 -> list[3:5] +// slice $list 3 -> list[3:5] = list[3:] +func slice(list interface{}, indices ...interface{}) interface{} { + l, err := mustSlice(list, indices...) + if err != nil { + panic(err) + } + + return l +} + +func mustSlice(list interface{}, indices ...interface{}) (interface{}, error) { + tp := reflect.TypeOf(list).Kind() + switch tp { + case reflect.Slice, reflect.Array: + l2 := reflect.ValueOf(list) + + l := l2.Len() + if l == 0 { + return nil, nil + } + + var start, end int + if len(indices) > 0 { + start = toInt(indices[0]) + } + if len(indices) < 2 { + end = l + } else { + end = toInt(indices[1]) + } + + return l2.Slice(start, end).Interface(), nil + default: + return nil, fmt.Errorf("list should be type of slice or array but %s", tp) + } +} + +func concat(lists ...interface{}) interface{} { + var res []interface{} + for _, list := range lists { + tp := reflect.TypeOf(list).Kind() + switch tp { + case reflect.Slice, reflect.Array: + l2 := reflect.ValueOf(list) + for i := 0; i < l2.Len(); i++ { + res = append(res, l2.Index(i).Interface()) + } + default: + panic(fmt.Sprintf("Cannot concat type %s as list", tp)) + } + } + return res +} diff --git a/vendor/github.com/go-task/slim-sprig/v3/network.go b/vendor/github.com/go-task/slim-sprig/v3/network.go new file mode 100644 index 000000000..108d78a94 --- /dev/null +++ b/vendor/github.com/go-task/slim-sprig/v3/network.go @@ -0,0 +1,12 @@ +package sprig + +import ( + "math/rand" + "net" +) + +func getHostByName(name string) string { + addrs, _ := net.LookupHost(name) + //TODO: add error handing when release v3 comes out + return addrs[rand.Intn(len(addrs))] +} diff --git a/vendor/github.com/go-task/slim-sprig/v3/numeric.go b/vendor/github.com/go-task/slim-sprig/v3/numeric.go new file mode 100644 index 000000000..98cbb37a1 --- /dev/null +++ b/vendor/github.com/go-task/slim-sprig/v3/numeric.go @@ -0,0 +1,228 @@ +package sprig + +import ( + "fmt" + "math" + "reflect" + "strconv" + "strings" +) + +// toFloat64 converts 64-bit floats +func toFloat64(v interface{}) float64 { + if str, ok := v.(string); ok { + iv, err := strconv.ParseFloat(str, 64) + if err != nil { + return 0 + } + return iv + } + + val := reflect.Indirect(reflect.ValueOf(v)) + switch val.Kind() { + case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int: + return float64(val.Int()) + case reflect.Uint8, reflect.Uint16, reflect.Uint32: + return float64(val.Uint()) + case reflect.Uint, reflect.Uint64: + return float64(val.Uint()) + case reflect.Float32, reflect.Float64: + return val.Float() + case reflect.Bool: + if val.Bool() { + return 1 + } + return 0 + default: + return 0 + } +} + +func toInt(v interface{}) int { + //It's not optimal. Bud I don't want duplicate toInt64 code. + return int(toInt64(v)) +} + +// toInt64 converts integer types to 64-bit integers +func toInt64(v interface{}) int64 { + if str, ok := v.(string); ok { + iv, err := strconv.ParseInt(str, 10, 64) + if err != nil { + return 0 + } + return iv + } + + val := reflect.Indirect(reflect.ValueOf(v)) + switch val.Kind() { + case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int: + return val.Int() + case reflect.Uint8, reflect.Uint16, reflect.Uint32: + return int64(val.Uint()) + case reflect.Uint, reflect.Uint64: + tv := val.Uint() + if tv <= math.MaxInt64 { + return int64(tv) + } + // TODO: What is the sensible thing to do here? + return math.MaxInt64 + case reflect.Float32, reflect.Float64: + return int64(val.Float()) + case reflect.Bool: + if val.Bool() { + return 1 + } + return 0 + default: + return 0 + } +} + +func max(a interface{}, i ...interface{}) int64 { + aa := toInt64(a) + for _, b := range i { + bb := toInt64(b) + if bb > aa { + aa = bb + } + } + return aa +} + +func maxf(a interface{}, i ...interface{}) float64 { + aa := toFloat64(a) + for _, b := range i { + bb := toFloat64(b) + aa = math.Max(aa, bb) + } + return aa +} + +func min(a interface{}, i ...interface{}) int64 { + aa := toInt64(a) + for _, b := range i { + bb := toInt64(b) + if bb < aa { + aa = bb + } + } + return aa +} + +func minf(a interface{}, i ...interface{}) float64 { + aa := toFloat64(a) + for _, b := range i { + bb := toFloat64(b) + aa = math.Min(aa, bb) + } + return aa +} + +func until(count int) []int { + step := 1 + if count < 0 { + step = -1 + } + return untilStep(0, count, step) +} + +func untilStep(start, stop, step int) []int { + v := []int{} + + if stop < start { + if step >= 0 { + return v + } + for i := start; i > stop; i += step { + v = append(v, i) + } + return v + } + + if step <= 0 { + return v + } + for i := start; i < stop; i += step { + v = append(v, i) + } + return v +} + +func floor(a interface{}) float64 { + aa := toFloat64(a) + return math.Floor(aa) +} + +func ceil(a interface{}) float64 { + aa := toFloat64(a) + return math.Ceil(aa) +} + +func round(a interface{}, p int, rOpt ...float64) float64 { + roundOn := .5 + if len(rOpt) > 0 { + roundOn = rOpt[0] + } + val := toFloat64(a) + places := toFloat64(p) + + var round float64 + pow := math.Pow(10, places) + digit := pow * val + _, div := math.Modf(digit) + if div >= roundOn { + round = math.Ceil(digit) + } else { + round = math.Floor(digit) + } + return round / pow +} + +// converts unix octal to decimal +func toDecimal(v interface{}) int64 { + result, err := strconv.ParseInt(fmt.Sprint(v), 8, 64) + if err != nil { + return 0 + } + return result +} + +func seq(params ...int) string { + increment := 1 + switch len(params) { + case 0: + return "" + case 1: + start := 1 + end := params[0] + if end < start { + increment = -1 + } + return intArrayToString(untilStep(start, end+increment, increment), " ") + case 3: + start := params[0] + end := params[2] + step := params[1] + if end < start { + increment = -1 + if step > 0 { + return "" + } + } + return intArrayToString(untilStep(start, end+increment, step), " ") + case 2: + start := params[0] + end := params[1] + step := 1 + if end < start { + step = -1 + } + return intArrayToString(untilStep(start, end+step, step), " ") + default: + return "" + } +} + +func intArrayToString(slice []int, delimeter string) string { + return strings.Trim(strings.Join(strings.Fields(fmt.Sprint(slice)), delimeter), "[]") +} diff --git a/vendor/github.com/go-task/slim-sprig/v3/reflect.go b/vendor/github.com/go-task/slim-sprig/v3/reflect.go new file mode 100644 index 000000000..8a65c132f --- /dev/null +++ b/vendor/github.com/go-task/slim-sprig/v3/reflect.go @@ -0,0 +1,28 @@ +package sprig + +import ( + "fmt" + "reflect" +) + +// typeIs returns true if the src is the type named in target. +func typeIs(target string, src interface{}) bool { + return target == typeOf(src) +} + +func typeIsLike(target string, src interface{}) bool { + t := typeOf(src) + return target == t || "*"+target == t +} + +func typeOf(src interface{}) string { + return fmt.Sprintf("%T", src) +} + +func kindIs(target string, src interface{}) bool { + return target == kindOf(src) +} + +func kindOf(src interface{}) string { + return reflect.ValueOf(src).Kind().String() +} diff --git a/vendor/github.com/go-task/slim-sprig/v3/regex.go b/vendor/github.com/go-task/slim-sprig/v3/regex.go new file mode 100644 index 000000000..fab551018 --- /dev/null +++ b/vendor/github.com/go-task/slim-sprig/v3/regex.go @@ -0,0 +1,83 @@ +package sprig + +import ( + "regexp" +) + +func regexMatch(regex string, s string) bool { + match, _ := regexp.MatchString(regex, s) + return match +} + +func mustRegexMatch(regex string, s string) (bool, error) { + return regexp.MatchString(regex, s) +} + +func regexFindAll(regex string, s string, n int) []string { + r := regexp.MustCompile(regex) + return r.FindAllString(s, n) +} + +func mustRegexFindAll(regex string, s string, n int) ([]string, error) { + r, err := regexp.Compile(regex) + if err != nil { + return []string{}, err + } + return r.FindAllString(s, n), nil +} + +func regexFind(regex string, s string) string { + r := regexp.MustCompile(regex) + return r.FindString(s) +} + +func mustRegexFind(regex string, s string) (string, error) { + r, err := regexp.Compile(regex) + if err != nil { + return "", err + } + return r.FindString(s), nil +} + +func regexReplaceAll(regex string, s string, repl string) string { + r := regexp.MustCompile(regex) + return r.ReplaceAllString(s, repl) +} + +func mustRegexReplaceAll(regex string, s string, repl string) (string, error) { + r, err := regexp.Compile(regex) + if err != nil { + return "", err + } + return r.ReplaceAllString(s, repl), nil +} + +func regexReplaceAllLiteral(regex string, s string, repl string) string { + r := regexp.MustCompile(regex) + return r.ReplaceAllLiteralString(s, repl) +} + +func mustRegexReplaceAllLiteral(regex string, s string, repl string) (string, error) { + r, err := regexp.Compile(regex) + if err != nil { + return "", err + } + return r.ReplaceAllLiteralString(s, repl), nil +} + +func regexSplit(regex string, s string, n int) []string { + r := regexp.MustCompile(regex) + return r.Split(s, n) +} + +func mustRegexSplit(regex string, s string, n int) ([]string, error) { + r, err := regexp.Compile(regex) + if err != nil { + return []string{}, err + } + return r.Split(s, n), nil +} + +func regexQuoteMeta(s string) string { + return regexp.QuoteMeta(s) +} diff --git a/vendor/github.com/go-task/slim-sprig/v3/strings.go b/vendor/github.com/go-task/slim-sprig/v3/strings.go new file mode 100644 index 000000000..3c62d6b6f --- /dev/null +++ b/vendor/github.com/go-task/slim-sprig/v3/strings.go @@ -0,0 +1,189 @@ +package sprig + +import ( + "encoding/base32" + "encoding/base64" + "fmt" + "reflect" + "strconv" + "strings" +) + +func base64encode(v string) string { + return base64.StdEncoding.EncodeToString([]byte(v)) +} + +func base64decode(v string) string { + data, err := base64.StdEncoding.DecodeString(v) + if err != nil { + return err.Error() + } + return string(data) +} + +func base32encode(v string) string { + return base32.StdEncoding.EncodeToString([]byte(v)) +} + +func base32decode(v string) string { + data, err := base32.StdEncoding.DecodeString(v) + if err != nil { + return err.Error() + } + return string(data) +} + +func quote(str ...interface{}) string { + out := make([]string, 0, len(str)) + for _, s := range str { + if s != nil { + out = append(out, fmt.Sprintf("%q", strval(s))) + } + } + return strings.Join(out, " ") +} + +func squote(str ...interface{}) string { + out := make([]string, 0, len(str)) + for _, s := range str { + if s != nil { + out = append(out, fmt.Sprintf("'%v'", s)) + } + } + return strings.Join(out, " ") +} + +func cat(v ...interface{}) string { + v = removeNilElements(v) + r := strings.TrimSpace(strings.Repeat("%v ", len(v))) + return fmt.Sprintf(r, v...) +} + +func indent(spaces int, v string) string { + pad := strings.Repeat(" ", spaces) + return pad + strings.Replace(v, "\n", "\n"+pad, -1) +} + +func nindent(spaces int, v string) string { + return "\n" + indent(spaces, v) +} + +func replace(old, new, src string) string { + return strings.Replace(src, old, new, -1) +} + +func plural(one, many string, count int) string { + if count == 1 { + return one + } + return many +} + +func strslice(v interface{}) []string { + switch v := v.(type) { + case []string: + return v + case []interface{}: + b := make([]string, 0, len(v)) + for _, s := range v { + if s != nil { + b = append(b, strval(s)) + } + } + return b + default: + val := reflect.ValueOf(v) + switch val.Kind() { + case reflect.Array, reflect.Slice: + l := val.Len() + b := make([]string, 0, l) + for i := 0; i < l; i++ { + value := val.Index(i).Interface() + if value != nil { + b = append(b, strval(value)) + } + } + return b + default: + if v == nil { + return []string{} + } + + return []string{strval(v)} + } + } +} + +func removeNilElements(v []interface{}) []interface{} { + newSlice := make([]interface{}, 0, len(v)) + for _, i := range v { + if i != nil { + newSlice = append(newSlice, i) + } + } + return newSlice +} + +func strval(v interface{}) string { + switch v := v.(type) { + case string: + return v + case []byte: + return string(v) + case error: + return v.Error() + case fmt.Stringer: + return v.String() + default: + return fmt.Sprintf("%v", v) + } +} + +func trunc(c int, s string) string { + if c < 0 && len(s)+c > 0 { + return s[len(s)+c:] + } + if c >= 0 && len(s) > c { + return s[:c] + } + return s +} + +func join(sep string, v interface{}) string { + return strings.Join(strslice(v), sep) +} + +func split(sep, orig string) map[string]string { + parts := strings.Split(orig, sep) + res := make(map[string]string, len(parts)) + for i, v := range parts { + res["_"+strconv.Itoa(i)] = v + } + return res +} + +func splitn(sep string, n int, orig string) map[string]string { + parts := strings.SplitN(orig, sep, n) + res := make(map[string]string, len(parts)) + for i, v := range parts { + res["_"+strconv.Itoa(i)] = v + } + return res +} + +// substring creates a substring of the given string. +// +// If start is < 0, this calls string[:end]. +// +// If start is >= 0 and end < 0 or end bigger than s length, this calls string[start:] +// +// Otherwise, this calls string[start, end]. +func substring(start, end int, s string) string { + if start < 0 { + return s[:end] + } + if end < 0 || end > len(s) { + return s[start:] + } + return s[start:end] +} diff --git a/vendor/github.com/go-task/slim-sprig/v3/url.go b/vendor/github.com/go-task/slim-sprig/v3/url.go new file mode 100644 index 000000000..b8e120e19 --- /dev/null +++ b/vendor/github.com/go-task/slim-sprig/v3/url.go @@ -0,0 +1,66 @@ +package sprig + +import ( + "fmt" + "net/url" + "reflect" +) + +func dictGetOrEmpty(dict map[string]interface{}, key string) string { + value, ok := dict[key] + if !ok { + return "" + } + tp := reflect.TypeOf(value).Kind() + if tp != reflect.String { + panic(fmt.Sprintf("unable to parse %s key, must be of type string, but %s found", key, tp.String())) + } + return reflect.ValueOf(value).String() +} + +// parses given URL to return dict object +func urlParse(v string) map[string]interface{} { + dict := map[string]interface{}{} + parsedURL, err := url.Parse(v) + if err != nil { + panic(fmt.Sprintf("unable to parse url: %s", err)) + } + dict["scheme"] = parsedURL.Scheme + dict["host"] = parsedURL.Host + dict["hostname"] = parsedURL.Hostname() + dict["path"] = parsedURL.Path + dict["query"] = parsedURL.RawQuery + dict["opaque"] = parsedURL.Opaque + dict["fragment"] = parsedURL.Fragment + if parsedURL.User != nil { + dict["userinfo"] = parsedURL.User.String() + } else { + dict["userinfo"] = "" + } + + return dict +} + +// join given dict to URL string +func urlJoin(d map[string]interface{}) string { + resURL := url.URL{ + Scheme: dictGetOrEmpty(d, "scheme"), + Host: dictGetOrEmpty(d, "host"), + Path: dictGetOrEmpty(d, "path"), + RawQuery: dictGetOrEmpty(d, "query"), + Opaque: dictGetOrEmpty(d, "opaque"), + Fragment: dictGetOrEmpty(d, "fragment"), + } + userinfo := dictGetOrEmpty(d, "userinfo") + var user *url.Userinfo + if userinfo != "" { + tempURL, err := url.Parse(fmt.Sprintf("proto://%s@host", userinfo)) + if err != nil { + panic(fmt.Sprintf("unable to parse userinfo in dict: %s", err)) + } + user = tempURL.User + } + + resURL.User = user + return resURL.String() +} diff --git a/vendor/github.com/google/pprof/profile/encode.go b/vendor/github.com/google/pprof/profile/encode.go index 182c926b9..860bb304c 100644 --- a/vendor/github.com/google/pprof/profile/encode.go +++ b/vendor/github.com/google/pprof/profile/encode.go @@ -530,6 +530,7 @@ func (p *Line) decoder() []decoder { func (p *Line) encode(b *buffer) { encodeUint64Opt(b, 1, p.functionIDX) encodeInt64Opt(b, 2, p.Line) + encodeInt64Opt(b, 3, p.Column) } var lineDecoder = []decoder{ @@ -538,6 +539,8 @@ var lineDecoder = []decoder{ func(b *buffer, m message) error { return decodeUint64(b, &m.(*Line).functionIDX) }, // optional int64 line = 2 func(b *buffer, m message) error { return decodeInt64(b, &m.(*Line).Line) }, + // optional int64 column = 3 + func(b *buffer, m message) error { return decodeInt64(b, &m.(*Line).Column) }, } func (p *Function) decoder() []decoder { diff --git a/vendor/github.com/google/pprof/profile/legacy_java_profile.go b/vendor/github.com/google/pprof/profile/legacy_java_profile.go index 91f45e53c..4580bab18 100644 --- a/vendor/github.com/google/pprof/profile/legacy_java_profile.go +++ b/vendor/github.com/google/pprof/profile/legacy_java_profile.go @@ -56,7 +56,7 @@ func javaCPUProfile(b []byte, period int64, parse func(b []byte) (uint64, []byte } // Strip out addresses for better merge. - if err = p.Aggregate(true, true, true, true, false); err != nil { + if err = p.Aggregate(true, true, true, true, false, false); err != nil { return nil, err } @@ -99,7 +99,7 @@ func parseJavaProfile(b []byte) (*Profile, error) { } // Strip out addresses for better merge. - if err = p.Aggregate(true, true, true, true, false); err != nil { + if err = p.Aggregate(true, true, true, true, false, false); err != nil { return nil, err } diff --git a/vendor/github.com/google/pprof/profile/merge.go b/vendor/github.com/google/pprof/profile/merge.go index 4b66282cb..eee0132e7 100644 --- a/vendor/github.com/google/pprof/profile/merge.go +++ b/vendor/github.com/google/pprof/profile/merge.go @@ -326,12 +326,13 @@ func (l *Location) key() locationKey { key.addr -= l.Mapping.Start key.mappingID = l.Mapping.ID } - lines := make([]string, len(l.Line)*2) + lines := make([]string, len(l.Line)*3) for i, line := range l.Line { if line.Function != nil { lines[i*2] = strconv.FormatUint(line.Function.ID, 16) } lines[i*2+1] = strconv.FormatInt(line.Line, 16) + lines[i*2+2] = strconv.FormatInt(line.Column, 16) } key.lines = strings.Join(lines, "|") return key @@ -418,6 +419,7 @@ func (pm *profileMerger) mapLine(src Line) Line { ln := Line{ Function: pm.mapFunction(src.Function), Line: src.Line, + Column: src.Column, } return ln } diff --git a/vendor/github.com/google/pprof/profile/profile.go b/vendor/github.com/google/pprof/profile/profile.go index 60ef7e926..5551eb0bf 100644 --- a/vendor/github.com/google/pprof/profile/profile.go +++ b/vendor/github.com/google/pprof/profile/profile.go @@ -145,6 +145,7 @@ type Location struct { type Line struct { Function *Function Line int64 + Column int64 functionIDX uint64 } @@ -436,7 +437,7 @@ func (p *Profile) CheckValid() error { // Aggregate merges the locations in the profile into equivalence // classes preserving the request attributes. It also updates the // samples to point to the merged locations. -func (p *Profile) Aggregate(inlineFrame, function, filename, linenumber, address bool) error { +func (p *Profile) Aggregate(inlineFrame, function, filename, linenumber, columnnumber, address bool) error { for _, m := range p.Mapping { m.HasInlineFrames = m.HasInlineFrames && inlineFrame m.HasFunctions = m.HasFunctions && function @@ -458,7 +459,7 @@ func (p *Profile) Aggregate(inlineFrame, function, filename, linenumber, address } // Aggregate locations - if !inlineFrame || !address || !linenumber { + if !inlineFrame || !address || !linenumber || !columnnumber { for _, l := range p.Location { if !inlineFrame && len(l.Line) > 1 { l.Line = l.Line[len(l.Line)-1:] @@ -466,6 +467,12 @@ func (p *Profile) Aggregate(inlineFrame, function, filename, linenumber, address if !linenumber { for i := range l.Line { l.Line[i].Line = 0 + l.Line[i].Column = 0 + } + } + if !columnnumber { + for i := range l.Line { + l.Line[i].Column = 0 } } if !address { @@ -627,10 +634,11 @@ func (l *Location) string() string { for li := range l.Line { lnStr := "??" if fn := l.Line[li].Function; fn != nil { - lnStr = fmt.Sprintf("%s %s:%d s=%d", + lnStr = fmt.Sprintf("%s %s:%d:%d s=%d", fn.Name, fn.Filename, l.Line[li].Line, + l.Line[li].Column, fn.StartLine) if fn.Name != fn.SystemName { lnStr = lnStr + "(" + fn.SystemName + ")" @@ -839,7 +847,7 @@ func (p *Profile) HasFileLines() bool { // "[vdso]", [vsyscall]" and some others, see the code. func (m *Mapping) Unsymbolizable() bool { name := filepath.Base(m.File) - return strings.HasPrefix(name, "[") || strings.HasPrefix(name, "linux-vdso") || strings.HasPrefix(m.File, "/dev/dri/") + return strings.HasPrefix(name, "[") || strings.HasPrefix(name, "linux-vdso") || strings.HasPrefix(m.File, "/dev/dri/") || m.File == "//anon" } // Copy makes a fully independent copy of a profile. diff --git a/vendor/github.com/hashicorp/errwrap/README.md b/vendor/github.com/hashicorp/errwrap/README.md deleted file mode 100644 index 444df08f8..000000000 --- a/vendor/github.com/hashicorp/errwrap/README.md +++ /dev/null @@ -1,89 +0,0 @@ -# errwrap - -`errwrap` is a package for Go that formalizes the pattern of wrapping errors -and checking if an error contains another error. - -There is a common pattern in Go of taking a returned `error` value and -then wrapping it (such as with `fmt.Errorf`) before returning it. The problem -with this pattern is that you completely lose the original `error` structure. - -Arguably the _correct_ approach is that you should make a custom structure -implementing the `error` interface, and have the original error as a field -on that structure, such [as this example](http://golang.org/pkg/os/#PathError). -This is a good approach, but you have to know the entire chain of possible -rewrapping that happens, when you might just care about one. - -`errwrap` formalizes this pattern (it doesn't matter what approach you use -above) by giving a single interface for wrapping errors, checking if a specific -error is wrapped, and extracting that error. - -## Installation and Docs - -Install using `go get github.com/hashicorp/errwrap`. - -Full documentation is available at -http://godoc.org/github.com/hashicorp/errwrap - -## Usage - -#### Basic Usage - -Below is a very basic example of its usage: - -```go -// A function that always returns an error, but wraps it, like a real -// function might. -func tryOpen() error { - _, err := os.Open("/i/dont/exist") - if err != nil { - return errwrap.Wrapf("Doesn't exist: {{err}}", err) - } - - return nil -} - -func main() { - err := tryOpen() - - // We can use the Contains helpers to check if an error contains - // another error. It is safe to do this with a nil error, or with - // an error that doesn't even use the errwrap package. - if errwrap.Contains(err, "does not exist") { - // Do something - } - if errwrap.ContainsType(err, new(os.PathError)) { - // Do something - } - - // Or we can use the associated `Get` functions to just extract - // a specific error. This would return nil if that specific error doesn't - // exist. - perr := errwrap.GetType(err, new(os.PathError)) -} -``` - -#### Custom Types - -If you're already making custom types that properly wrap errors, then -you can get all the functionality of `errwraps.Contains` and such by -implementing the `Wrapper` interface with just one function. Example: - -```go -type AppError { - Code ErrorCode - Err error -} - -func (e *AppError) WrappedErrors() []error { - return []error{e.Err} -} -``` - -Now this works: - -```go -err := &AppError{Err: fmt.Errorf("an error")} -if errwrap.ContainsType(err, fmt.Errorf("")) { - // This will work! -} -``` diff --git a/vendor/github.com/hashicorp/errwrap/errwrap.go b/vendor/github.com/hashicorp/errwrap/errwrap.go deleted file mode 100644 index 44e368e56..000000000 --- a/vendor/github.com/hashicorp/errwrap/errwrap.go +++ /dev/null @@ -1,178 +0,0 @@ -// Package errwrap implements methods to formalize error wrapping in Go. -// -// All of the top-level functions that take an `error` are built to be able -// to take any error, not just wrapped errors. This allows you to use errwrap -// without having to type-check and type-cast everywhere. -package errwrap - -import ( - "errors" - "reflect" - "strings" -) - -// WalkFunc is the callback called for Walk. -type WalkFunc func(error) - -// Wrapper is an interface that can be implemented by custom types to -// have all the Contains, Get, etc. functions in errwrap work. -// -// When Walk reaches a Wrapper, it will call the callback for every -// wrapped error in addition to the wrapper itself. Since all the top-level -// functions in errwrap use Walk, this means that all those functions work -// with your custom type. -type Wrapper interface { - WrappedErrors() []error -} - -// Wrap defines that outer wraps inner, returning an error type that -// can be cleanly used with the other methods in this package, such as -// Contains, GetAll, etc. -// -// This function won't modify the error message at all (the outer message -// will be used). -func Wrap(outer, inner error) error { - return &wrappedError{ - Outer: outer, - Inner: inner, - } -} - -// Wrapf wraps an error with a formatting message. This is similar to using -// `fmt.Errorf` to wrap an error. If you're using `fmt.Errorf` to wrap -// errors, you should replace it with this. -// -// format is the format of the error message. The string '{{err}}' will -// be replaced with the original error message. -// -// Deprecated: Use fmt.Errorf() -func Wrapf(format string, err error) error { - outerMsg := "" - if err != nil { - outerMsg = err.Error() - } - - outer := errors.New(strings.Replace( - format, "{{err}}", outerMsg, -1)) - - return Wrap(outer, err) -} - -// Contains checks if the given error contains an error with the -// message msg. If err is not a wrapped error, this will always return -// false unless the error itself happens to match this msg. -func Contains(err error, msg string) bool { - return len(GetAll(err, msg)) > 0 -} - -// ContainsType checks if the given error contains an error with -// the same concrete type as v. If err is not a wrapped error, this will -// check the err itself. -func ContainsType(err error, v interface{}) bool { - return len(GetAllType(err, v)) > 0 -} - -// Get is the same as GetAll but returns the deepest matching error. -func Get(err error, msg string) error { - es := GetAll(err, msg) - if len(es) > 0 { - return es[len(es)-1] - } - - return nil -} - -// GetType is the same as GetAllType but returns the deepest matching error. -func GetType(err error, v interface{}) error { - es := GetAllType(err, v) - if len(es) > 0 { - return es[len(es)-1] - } - - return nil -} - -// GetAll gets all the errors that might be wrapped in err with the -// given message. The order of the errors is such that the outermost -// matching error (the most recent wrap) is index zero, and so on. -func GetAll(err error, msg string) []error { - var result []error - - Walk(err, func(err error) { - if err.Error() == msg { - result = append(result, err) - } - }) - - return result -} - -// GetAllType gets all the errors that are the same type as v. -// -// The order of the return value is the same as described in GetAll. -func GetAllType(err error, v interface{}) []error { - var result []error - - var search string - if v != nil { - search = reflect.TypeOf(v).String() - } - Walk(err, func(err error) { - var needle string - if err != nil { - needle = reflect.TypeOf(err).String() - } - - if needle == search { - result = append(result, err) - } - }) - - return result -} - -// Walk walks all the wrapped errors in err and calls the callback. If -// err isn't a wrapped error, this will be called once for err. If err -// is a wrapped error, the callback will be called for both the wrapper -// that implements error as well as the wrapped error itself. -func Walk(err error, cb WalkFunc) { - if err == nil { - return - } - - switch e := err.(type) { - case *wrappedError: - cb(e.Outer) - Walk(e.Inner, cb) - case Wrapper: - cb(err) - - for _, err := range e.WrappedErrors() { - Walk(err, cb) - } - case interface{ Unwrap() error }: - cb(err) - Walk(e.Unwrap(), cb) - default: - cb(err) - } -} - -// wrappedError is an implementation of error that has both the -// outer and inner errors. -type wrappedError struct { - Outer error - Inner error -} - -func (w *wrappedError) Error() string { - return w.Outer.Error() -} - -func (w *wrappedError) WrappedErrors() []error { - return []error{w.Outer, w.Inner} -} - -func (w *wrappedError) Unwrap() error { - return w.Inner -} diff --git a/vendor/github.com/hashicorp/go-multierror/Makefile b/vendor/github.com/hashicorp/go-multierror/Makefile deleted file mode 100644 index b97cd6ed0..000000000 --- a/vendor/github.com/hashicorp/go-multierror/Makefile +++ /dev/null @@ -1,31 +0,0 @@ -TEST?=./... - -default: test - -# test runs the test suite and vets the code. -test: generate - @echo "==> Running tests..." - @go list $(TEST) \ - | grep -v "/vendor/" \ - | xargs -n1 go test -timeout=60s -parallel=10 ${TESTARGS} - -# testrace runs the race checker -testrace: generate - @echo "==> Running tests (race)..." - @go list $(TEST) \ - | grep -v "/vendor/" \ - | xargs -n1 go test -timeout=60s -race ${TESTARGS} - -# updatedeps installs all the dependencies needed to run and build. -updatedeps: - @sh -c "'${CURDIR}/scripts/deps.sh' '${NAME}'" - -# generate runs `go generate` to build the dynamically generated source files. -generate: - @echo "==> Generating..." - @find . -type f -name '.DS_Store' -delete - @go list ./... \ - | grep -v "/vendor/" \ - | xargs -n1 go generate - -.PHONY: default test testrace updatedeps generate diff --git a/vendor/github.com/hashicorp/go-multierror/README.md b/vendor/github.com/hashicorp/go-multierror/README.md deleted file mode 100644 index 71dd308ed..000000000 --- a/vendor/github.com/hashicorp/go-multierror/README.md +++ /dev/null @@ -1,150 +0,0 @@ -# go-multierror - -[![CircleCI](https://img.shields.io/circleci/build/github/hashicorp/go-multierror/master)](https://circleci.com/gh/hashicorp/go-multierror) -[![Go Reference](https://pkg.go.dev/badge/github.com/hashicorp/go-multierror.svg)](https://pkg.go.dev/github.com/hashicorp/go-multierror) -![GitHub go.mod Go version](https://img.shields.io/github/go-mod/go-version/hashicorp/go-multierror) - -[circleci]: https://app.circleci.com/pipelines/github/hashicorp/go-multierror -[godocs]: https://pkg.go.dev/github.com/hashicorp/go-multierror - -`go-multierror` is a package for Go that provides a mechanism for -representing a list of `error` values as a single `error`. - -This allows a function in Go to return an `error` that might actually -be a list of errors. If the caller knows this, they can unwrap the -list and access the errors. If the caller doesn't know, the error -formats to a nice human-readable format. - -`go-multierror` is fully compatible with the Go standard library -[errors](https://golang.org/pkg/errors/) package, including the -functions `As`, `Is`, and `Unwrap`. This provides a standardized approach -for introspecting on error values. - -## Installation and Docs - -Install using `go get github.com/hashicorp/go-multierror`. - -Full documentation is available at -https://pkg.go.dev/github.com/hashicorp/go-multierror - -### Requires go version 1.13 or newer - -`go-multierror` requires go version 1.13 or newer. Go 1.13 introduced -[error wrapping](https://golang.org/doc/go1.13#error_wrapping), which -this library takes advantage of. - -If you need to use an earlier version of go, you can use the -[v1.0.0](https://github.com/hashicorp/go-multierror/tree/v1.0.0) -tag, which doesn't rely on features in go 1.13. - -If you see compile errors that look like the below, it's likely that -you're on an older version of go: - -``` -/go/src/github.com/hashicorp/go-multierror/multierror.go:112:9: undefined: errors.As -/go/src/github.com/hashicorp/go-multierror/multierror.go:117:9: undefined: errors.Is -``` - -## Usage - -go-multierror is easy to use and purposely built to be unobtrusive in -existing Go applications/libraries that may not be aware of it. - -**Building a list of errors** - -The `Append` function is used to create a list of errors. This function -behaves a lot like the Go built-in `append` function: it doesn't matter -if the first argument is nil, a `multierror.Error`, or any other `error`, -the function behaves as you would expect. - -```go -var result error - -if err := step1(); err != nil { - result = multierror.Append(result, err) -} -if err := step2(); err != nil { - result = multierror.Append(result, err) -} - -return result -``` - -**Customizing the formatting of the errors** - -By specifying a custom `ErrorFormat`, you can customize the format -of the `Error() string` function: - -```go -var result *multierror.Error - -// ... accumulate errors here, maybe using Append - -if result != nil { - result.ErrorFormat = func([]error) string { - return "errors!" - } -} -``` - -**Accessing the list of errors** - -`multierror.Error` implements `error` so if the caller doesn't know about -multierror, it will work just fine. But if you're aware a multierror might -be returned, you can use type switches to access the list of errors: - -```go -if err := something(); err != nil { - if merr, ok := err.(*multierror.Error); ok { - // Use merr.Errors - } -} -``` - -You can also use the standard [`errors.Unwrap`](https://golang.org/pkg/errors/#Unwrap) -function. This will continue to unwrap into subsequent errors until none exist. - -**Extracting an error** - -The standard library [`errors.As`](https://golang.org/pkg/errors/#As) -function can be used directly with a multierror to extract a specific error: - -```go -// Assume err is a multierror value -err := somefunc() - -// We want to know if "err" has a "RichErrorType" in it and extract it. -var errRich RichErrorType -if errors.As(err, &errRich) { - // It has it, and now errRich is populated. -} -``` - -**Checking for an exact error value** - -Some errors are returned as exact errors such as the [`ErrNotExist`](https://golang.org/pkg/os/#pkg-variables) -error in the `os` package. You can check if this error is present by using -the standard [`errors.Is`](https://golang.org/pkg/errors/#Is) function. - -```go -// Assume err is a multierror value -err := somefunc() -if errors.Is(err, os.ErrNotExist) { - // err contains os.ErrNotExist -} -``` - -**Returning a multierror only if there are errors** - -If you build a `multierror.Error`, you can use the `ErrorOrNil` function -to return an `error` implementation only if there are errors to return: - -```go -var result *multierror.Error - -// ... accumulate errors here - -// Return the `error` only if errors were added to the multierror, otherwise -// return nil since there are no errors. -return result.ErrorOrNil() -``` diff --git a/vendor/github.com/hashicorp/go-multierror/append.go b/vendor/github.com/hashicorp/go-multierror/append.go deleted file mode 100644 index 3e2589bfd..000000000 --- a/vendor/github.com/hashicorp/go-multierror/append.go +++ /dev/null @@ -1,43 +0,0 @@ -package multierror - -// Append is a helper function that will append more errors -// onto an Error in order to create a larger multi-error. -// -// If err is not a multierror.Error, then it will be turned into -// one. If any of the errs are multierr.Error, they will be flattened -// one level into err. -// Any nil errors within errs will be ignored. If err is nil, a new -// *Error will be returned. -func Append(err error, errs ...error) *Error { - switch err := err.(type) { - case *Error: - // Typed nils can reach here, so initialize if we are nil - if err == nil { - err = new(Error) - } - - // Go through each error and flatten - for _, e := range errs { - switch e := e.(type) { - case *Error: - if e != nil { - err.Errors = append(err.Errors, e.Errors...) - } - default: - if e != nil { - err.Errors = append(err.Errors, e) - } - } - } - - return err - default: - newErrs := make([]error, 0, len(errs)+1) - if err != nil { - newErrs = append(newErrs, err) - } - newErrs = append(newErrs, errs...) - - return Append(&Error{}, newErrs...) - } -} diff --git a/vendor/github.com/hashicorp/go-multierror/flatten.go b/vendor/github.com/hashicorp/go-multierror/flatten.go deleted file mode 100644 index aab8e9abe..000000000 --- a/vendor/github.com/hashicorp/go-multierror/flatten.go +++ /dev/null @@ -1,26 +0,0 @@ -package multierror - -// Flatten flattens the given error, merging any *Errors together into -// a single *Error. -func Flatten(err error) error { - // If it isn't an *Error, just return the error as-is - if _, ok := err.(*Error); !ok { - return err - } - - // Otherwise, make the result and flatten away! - flatErr := new(Error) - flatten(err, flatErr) - return flatErr -} - -func flatten(err error, flatErr *Error) { - switch err := err.(type) { - case *Error: - for _, e := range err.Errors { - flatten(e, flatErr) - } - default: - flatErr.Errors = append(flatErr.Errors, err) - } -} diff --git a/vendor/github.com/hashicorp/go-multierror/format.go b/vendor/github.com/hashicorp/go-multierror/format.go deleted file mode 100644 index 47f13c49a..000000000 --- a/vendor/github.com/hashicorp/go-multierror/format.go +++ /dev/null @@ -1,27 +0,0 @@ -package multierror - -import ( - "fmt" - "strings" -) - -// ErrorFormatFunc is a function callback that is called by Error to -// turn the list of errors into a string. -type ErrorFormatFunc func([]error) string - -// ListFormatFunc is a basic formatter that outputs the number of errors -// that occurred along with a bullet point list of the errors. -func ListFormatFunc(es []error) string { - if len(es) == 1 { - return fmt.Sprintf("1 error occurred:\n\t* %s\n\n", es[0]) - } - - points := make([]string, len(es)) - for i, err := range es { - points[i] = fmt.Sprintf("* %s", err) - } - - return fmt.Sprintf( - "%d errors occurred:\n\t%s\n\n", - len(es), strings.Join(points, "\n\t")) -} diff --git a/vendor/github.com/hashicorp/go-multierror/group.go b/vendor/github.com/hashicorp/go-multierror/group.go deleted file mode 100644 index 9c29efb7f..000000000 --- a/vendor/github.com/hashicorp/go-multierror/group.go +++ /dev/null @@ -1,38 +0,0 @@ -package multierror - -import "sync" - -// Group is a collection of goroutines which return errors that need to be -// coalesced. -type Group struct { - mutex sync.Mutex - err *Error - wg sync.WaitGroup -} - -// Go calls the given function in a new goroutine. -// -// If the function returns an error it is added to the group multierror which -// is returned by Wait. -func (g *Group) Go(f func() error) { - g.wg.Add(1) - - go func() { - defer g.wg.Done() - - if err := f(); err != nil { - g.mutex.Lock() - g.err = Append(g.err, err) - g.mutex.Unlock() - } - }() -} - -// Wait blocks until all function calls from the Go method have returned, then -// returns the multierror. -func (g *Group) Wait() *Error { - g.wg.Wait() - g.mutex.Lock() - defer g.mutex.Unlock() - return g.err -} diff --git a/vendor/github.com/hashicorp/go-multierror/multierror.go b/vendor/github.com/hashicorp/go-multierror/multierror.go deleted file mode 100644 index f54574326..000000000 --- a/vendor/github.com/hashicorp/go-multierror/multierror.go +++ /dev/null @@ -1,121 +0,0 @@ -package multierror - -import ( - "errors" - "fmt" -) - -// Error is an error type to track multiple errors. This is used to -// accumulate errors in cases and return them as a single "error". -type Error struct { - Errors []error - ErrorFormat ErrorFormatFunc -} - -func (e *Error) Error() string { - fn := e.ErrorFormat - if fn == nil { - fn = ListFormatFunc - } - - return fn(e.Errors) -} - -// ErrorOrNil returns an error interface if this Error represents -// a list of errors, or returns nil if the list of errors is empty. This -// function is useful at the end of accumulation to make sure that the value -// returned represents the existence of errors. -func (e *Error) ErrorOrNil() error { - if e == nil { - return nil - } - if len(e.Errors) == 0 { - return nil - } - - return e -} - -func (e *Error) GoString() string { - return fmt.Sprintf("*%#v", *e) -} - -// WrappedErrors returns the list of errors that this Error is wrapping. It is -// an implementation of the errwrap.Wrapper interface so that multierror.Error -// can be used with that library. -// -// This method is not safe to be called concurrently. Unlike accessing the -// Errors field directly, this function also checks if the multierror is nil to -// prevent a null-pointer panic. It satisfies the errwrap.Wrapper interface. -func (e *Error) WrappedErrors() []error { - if e == nil { - return nil - } - return e.Errors -} - -// Unwrap returns an error from Error (or nil if there are no errors). -// This error returned will further support Unwrap to get the next error, -// etc. The order will match the order of Errors in the multierror.Error -// at the time of calling. -// -// The resulting error supports errors.As/Is/Unwrap so you can continue -// to use the stdlib errors package to introspect further. -// -// This will perform a shallow copy of the errors slice. Any errors appended -// to this error after calling Unwrap will not be available until a new -// Unwrap is called on the multierror.Error. -func (e *Error) Unwrap() error { - // If we have no errors then we do nothing - if e == nil || len(e.Errors) == 0 { - return nil - } - - // If we have exactly one error, we can just return that directly. - if len(e.Errors) == 1 { - return e.Errors[0] - } - - // Shallow copy the slice - errs := make([]error, len(e.Errors)) - copy(errs, e.Errors) - return chain(errs) -} - -// chain implements the interfaces necessary for errors.Is/As/Unwrap to -// work in a deterministic way with multierror. A chain tracks a list of -// errors while accounting for the current represented error. This lets -// Is/As be meaningful. -// -// Unwrap returns the next error. In the cleanest form, Unwrap would return -// the wrapped error here but we can't do that if we want to properly -// get access to all the errors. Instead, users are recommended to use -// Is/As to get the correct error type out. -// -// Precondition: []error is non-empty (len > 0) -type chain []error - -// Error implements the error interface -func (e chain) Error() string { - return e[0].Error() -} - -// Unwrap implements errors.Unwrap by returning the next error in the -// chain or nil if there are no more errors. -func (e chain) Unwrap() error { - if len(e) == 1 { - return nil - } - - return e[1:] -} - -// As implements errors.As by attempting to map to the current value. -func (e chain) As(target interface{}) bool { - return errors.As(e[0], target) -} - -// Is implements errors.Is by comparing the current value directly. -func (e chain) Is(target error) bool { - return errors.Is(e[0], target) -} diff --git a/vendor/github.com/hashicorp/go-multierror/prefix.go b/vendor/github.com/hashicorp/go-multierror/prefix.go deleted file mode 100644 index 5c477abe4..000000000 --- a/vendor/github.com/hashicorp/go-multierror/prefix.go +++ /dev/null @@ -1,37 +0,0 @@ -package multierror - -import ( - "fmt" - - "github.com/hashicorp/errwrap" -) - -// Prefix is a helper function that will prefix some text -// to the given error. If the error is a multierror.Error, then -// it will be prefixed to each wrapped error. -// -// This is useful to use when appending multiple multierrors -// together in order to give better scoping. -func Prefix(err error, prefix string) error { - if err == nil { - return nil - } - - format := fmt.Sprintf("%s {{err}}", prefix) - switch err := err.(type) { - case *Error: - // Typed nils can reach here, so initialize if we are nil - if err == nil { - err = new(Error) - } - - // Wrap each of the errors - for i, e := range err.Errors { - err.Errors[i] = errwrap.Wrapf(format, e) - } - - return err - default: - return errwrap.Wrapf(format, err) - } -} diff --git a/vendor/github.com/hashicorp/go-multierror/sort.go b/vendor/github.com/hashicorp/go-multierror/sort.go deleted file mode 100644 index fecb14e81..000000000 --- a/vendor/github.com/hashicorp/go-multierror/sort.go +++ /dev/null @@ -1,16 +0,0 @@ -package multierror - -// Len implements sort.Interface function for length -func (err Error) Len() int { - return len(err.Errors) -} - -// Swap implements sort.Interface function for swapping elements -func (err Error) Swap(i, j int) { - err.Errors[i], err.Errors[j] = err.Errors[j], err.Errors[i] -} - -// Less implements sort.Interface function for determining order -func (err Error) Less(i, j int) bool { - return err.Errors[i].Error() < err.Errors[j].Error() -} diff --git a/vendor/github.com/hashicorp/errwrap/LICENSE b/vendor/github.com/hashicorp/go-secure-stdlib/parseutil/LICENSE similarity index 50% rename from vendor/github.com/hashicorp/errwrap/LICENSE rename to vendor/github.com/hashicorp/go-secure-stdlib/parseutil/LICENSE index c33dcc7c9..e87a115e4 100644 --- a/vendor/github.com/hashicorp/errwrap/LICENSE +++ b/vendor/github.com/hashicorp/go-secure-stdlib/parseutil/LICENSE @@ -2,89 +2,89 @@ Mozilla Public License, version 2.0 1. Definitions -1.1. “Contributor” +1.1. "Contributor" means each individual or legal entity that creates, contributes to the creation of, or owns Covered Software. -1.2. “Contributor Version” +1.2. "Contributor Version" means the combination of the Contributions of others (if any) used by a - Contributor and that particular Contributor’s Contribution. + Contributor and that particular Contributor's Contribution. -1.3. “Contribution” +1.3. "Contribution" means Covered Software of a particular Contributor. -1.4. “Covered Software” +1.4. "Covered Software" means Source Code Form to which the initial Contributor has attached the notice in Exhibit A, the Executable Form of such Source Code Form, and Modifications of such Source Code Form, in each case including portions thereof. -1.5. “Incompatible With Secondary Licenses” +1.5. "Incompatible With Secondary Licenses" means a. that the initial Contributor has attached the notice described in Exhibit B to the Covered Software; or - b. that the Covered Software was made available under the terms of version - 1.1 or earlier of the License, but not also under the terms of a - Secondary License. + b. that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the terms of + a Secondary License. -1.6. “Executable Form” +1.6. "Executable Form" means any form of the work other than Source Code Form. -1.7. “Larger Work” +1.7. "Larger Work" - means a work that combines Covered Software with other material, in a separate - file or files, that is not Covered Software. + means a work that combines Covered Software with other material, in a + separate file or files, that is not Covered Software. -1.8. “License” +1.8. "License" means this document. -1.9. “Licensable” +1.9. "Licensable" - means having the right to grant, to the maximum extent possible, whether at the - time of the initial grant or subsequently, any and all of the rights conveyed by - this License. + means having the right to grant, to the maximum extent possible, whether + at the time of the initial grant or subsequently, any and all of the + rights conveyed by this License. -1.10. “Modifications” +1.10. "Modifications" means any of the following: - a. any file in Source Code Form that results from an addition to, deletion - from, or modification of the contents of Covered Software; or + a. any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered Software; or b. any new file in Source Code Form that contains any Covered Software. -1.11. “Patent Claims” of a Contributor +1.11. "Patent Claims" of a Contributor - means any patent claim(s), including without limitation, method, process, - and apparatus claims, in any patent Licensable by such Contributor that - would be infringed, but for the grant of the License, by the making, - using, selling, offering for sale, having made, import, or transfer of - either its Contributions or its Contributor Version. + means any patent claim(s), including without limitation, method, + process, and apparatus claims, in any patent Licensable by such + Contributor that would be infringed, but for the grant of the License, + by the making, using, selling, offering for sale, having made, import, + or transfer of either its Contributions or its Contributor Version. -1.12. “Secondary License” +1.12. "Secondary License" means either the GNU General Public License, Version 2.0, the GNU Lesser General Public License, Version 2.1, the GNU Affero General Public License, Version 3.0, or any later versions of those licenses. -1.13. “Source Code Form” +1.13. "Source Code Form" means the form of the work preferred for making modifications. -1.14. “You” (or “Your”) +1.14. "You" (or "Your") means an individual or a legal entity exercising rights under this - License. For legal entities, “You” includes any entity that controls, is + License. For legal entities, "You" includes any entity that controls, is controlled by, or is under common control with You. For purposes of this - definition, “control” means (a) the power, direct or indirect, to cause + definition, "control" means (a) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (b) ownership of more than fifty percent (50%) of the outstanding shares or beneficial ownership of such entity. @@ -100,57 +100,59 @@ Mozilla Public License, version 2.0 a. under intellectual property rights (other than patent or trademark) Licensable by such Contributor to use, reproduce, make available, modify, display, perform, distribute, and otherwise exploit its - Contributions, either on an unmodified basis, with Modifications, or as - part of a Larger Work; and + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and b. under Patent Claims of such Contributor to make, use, sell, offer for - sale, have made, import, and otherwise transfer either its Contributions - or its Contributor Version. + sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. 2.2. Effective Date - The licenses granted in Section 2.1 with respect to any Contribution become - effective for each Contribution on the date the Contributor first distributes - such Contribution. + The licenses granted in Section 2.1 with respect to any Contribution + become effective for each Contribution on the date the Contributor first + distributes such Contribution. 2.3. Limitations on Grant Scope - The licenses granted in this Section 2 are the only rights granted under this - License. No additional rights or licenses will be implied from the distribution - or licensing of Covered Software under this License. Notwithstanding Section - 2.1(b) above, no patent license is granted by a Contributor: + The licenses granted in this Section 2 are the only rights granted under + this License. No additional rights or licenses will be implied from the + distribution or licensing of Covered Software under this License. + Notwithstanding Section 2.1(b) above, no patent license is granted by a + Contributor: a. for any code that a Contributor has removed from Covered Software; or - b. for infringements caused by: (i) Your and any other third party’s + b. for infringements caused by: (i) Your and any other third party's modifications of Covered Software, or (ii) the combination of its Contributions with other software (except as part of its Contributor Version); or - c. under Patent Claims infringed by Covered Software in the absence of its - Contributions. + c. under Patent Claims infringed by Covered Software in the absence of + its Contributions. - This License does not grant any rights in the trademarks, service marks, or - logos of any Contributor (except as may be necessary to comply with the - notice requirements in Section 3.4). + This License does not grant any rights in the trademarks, service marks, + or logos of any Contributor (except as may be necessary to comply with + the notice requirements in Section 3.4). 2.4. Subsequent Licenses No Contributor makes additional grants as a result of Your choice to - distribute the Covered Software under a subsequent version of this License - (see Section 10.2) or under the terms of a Secondary License (if permitted - under the terms of Section 3.3). + distribute the Covered Software under a subsequent version of this + License (see Section 10.2) or under the terms of a Secondary License (if + permitted under the terms of Section 3.3). 2.5. Representation - Each Contributor represents that the Contributor believes its Contributions - are its original creation(s) or it has sufficient rights to grant the - rights to its Contributions conveyed by this License. + Each Contributor represents that the Contributor believes its + Contributions are its original creation(s) or it has sufficient rights to + grant the rights to its Contributions conveyed by this License. 2.6. Fair Use - This License is not intended to limit any rights You have under applicable - copyright doctrines of fair use, fair dealing, or other equivalents. + This License is not intended to limit any rights You have under + applicable copyright doctrines of fair use, fair dealing, or other + equivalents. 2.7. Conditions @@ -163,11 +165,12 @@ Mozilla Public License, version 2.0 3.1. Distribution of Source Form All distribution of Covered Software in Source Code Form, including any - Modifications that You create or to which You contribute, must be under the - terms of this License. You must inform recipients that the Source Code Form - of the Covered Software is governed by the terms of this License, and how - they can obtain a copy of this License. You may not attempt to alter or - restrict the recipients’ rights in the Source Code Form. + Modifications that You create or to which You contribute, must be under + the terms of this License. You must inform recipients that the Source + Code Form of the Covered Software is governed by the terms of this + License, and how they can obtain a copy of this License. You may not + attempt to alter or restrict the recipients' rights in the Source Code + Form. 3.2. Distribution of Executable Form @@ -179,39 +182,40 @@ Mozilla Public License, version 2.0 reasonable means in a timely manner, at a charge no more than the cost of distribution to the recipient; and - b. You may distribute such Executable Form under the terms of this License, - or sublicense it under different terms, provided that the license for - the Executable Form does not attempt to limit or alter the recipients’ - rights in the Source Code Form under this License. + b. You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter the + recipients' rights in the Source Code Form under this License. 3.3. Distribution of a Larger Work You may create and distribute a Larger Work under terms of Your choice, - provided that You also comply with the requirements of this License for the - Covered Software. If the Larger Work is a combination of Covered Software - with a work governed by one or more Secondary Licenses, and the Covered - Software is not Incompatible With Secondary Licenses, this License permits - You to additionally distribute such Covered Software under the terms of - such Secondary License(s), so that the recipient of the Larger Work may, at - their option, further distribute the Covered Software under the terms of - either this License or such Secondary License(s). + provided that You also comply with the requirements of this License for + the Covered Software. If the Larger Work is a combination of Covered + Software with a work governed by one or more Secondary Licenses, and the + Covered Software is not Incompatible With Secondary Licenses, this + License permits You to additionally distribute such Covered Software + under the terms of such Secondary License(s), so that the recipient of + the Larger Work may, at their option, further distribute the Covered + Software under the terms of either this License or such Secondary + License(s). 3.4. Notices - You may not remove or alter the substance of any license notices (including - copyright notices, patent notices, disclaimers of warranty, or limitations - of liability) contained within the Source Code Form of the Covered - Software, except that You may alter any license notices to the extent - required to remedy known factual inaccuracies. + You may not remove or alter the substance of any license notices + (including copyright notices, patent notices, disclaimers of warranty, or + limitations of liability) contained within the Source Code Form of the + Covered Software, except that You may alter any license notices to the + extent required to remedy known factual inaccuracies. 3.5. Application of Additional Terms You may choose to offer, and to charge a fee for, warranty, support, indemnity or liability obligations to one or more recipients of Covered - Software. However, You may do so only on Your own behalf, and not on behalf - of any Contributor. You must make it absolutely clear that any such - warranty, support, indemnity, or liability obligation is offered by You - alone, and You hereby agree to indemnify every Contributor for any + Software. However, You may do so only on Your own behalf, and not on + behalf of any Contributor. You must make it absolutely clear that any + such warranty, support, indemnity, or liability obligation is offered by + You alone, and You hereby agree to indemnify every Contributor for any liability incurred by such Contributor as a result of warranty, support, indemnity or liability terms You offer. You may include additional disclaimers of warranty and limitations of liability specific to any @@ -220,14 +224,14 @@ Mozilla Public License, version 2.0 4. Inability to Comply Due to Statute or Regulation If it is impossible for You to comply with any of the terms of this License - with respect to some or all of the Covered Software due to statute, judicial - order, or regulation then You must: (a) comply with the terms of this License - to the maximum extent possible; and (b) describe the limitations and the code - they affect. Such description must be placed in a text file included with all - distributions of the Covered Software under this License. Except to the - extent prohibited by statute or regulation, such description must be - sufficiently detailed for a recipient of ordinary skill to be able to - understand it. + with respect to some or all of the Covered Software due to statute, + judicial order, or regulation then You must: (a) comply with the terms of + this License to the maximum extent possible; and (b) describe the + limitations and the code they affect. Such description must be placed in a + text file included with all distributions of the Covered Software under + this License. Except to the extent prohibited by statute or regulation, + such description must be sufficiently detailed for a recipient of ordinary + skill to be able to understand it. 5. Termination @@ -235,21 +239,22 @@ Mozilla Public License, version 2.0 fail to comply with any of its terms. However, if You become compliant, then the rights granted under this License from a particular Contributor are reinstated (a) provisionally, unless and until such Contributor - explicitly and finally terminates Your grants, and (b) on an ongoing basis, - if such Contributor fails to notify You of the non-compliance by some - reasonable means prior to 60 days after You have come back into compliance. - Moreover, Your grants from a particular Contributor are reinstated on an - ongoing basis if such Contributor notifies You of the non-compliance by - some reasonable means, this is the first time You have received notice of - non-compliance with this License from such Contributor, and You become - compliant prior to 30 days after Your receipt of the notice. + explicitly and finally terminates Your grants, and (b) on an ongoing + basis, if such Contributor fails to notify You of the non-compliance by + some reasonable means prior to 60 days after You have come back into + compliance. Moreover, Your grants from a particular Contributor are + reinstated on an ongoing basis if such Contributor notifies You of the + non-compliance by some reasonable means, this is the first time You have + received notice of non-compliance with this License from such + Contributor, and You become compliant prior to 30 days after Your receipt + of the notice. 5.2. If You initiate litigation against any entity by asserting a patent - infringement claim (excluding declaratory judgment actions, counter-claims, - and cross-claims) alleging that a Contributor Version directly or - indirectly infringes any patent, then the rights granted to You by any and - all Contributors for the Covered Software under Section 2.1 of this License - shall terminate. + infringement claim (excluding declaratory judgment actions, + counter-claims, and cross-claims) alleging that a Contributor Version + directly or indirectly infringes any patent, then the rights granted to + You by any and all Contributors for the Covered Software under Section + 2.1 of this License shall terminate. 5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user license agreements (excluding distributors and resellers) which have been @@ -258,16 +263,16 @@ Mozilla Public License, version 2.0 6. Disclaimer of Warranty - Covered Software is provided under this License on an “as is” basis, without - warranty of any kind, either expressed, implied, or statutory, including, - without limitation, warranties that the Covered Software is free of defects, - merchantable, fit for a particular purpose or non-infringing. The entire - risk as to the quality and performance of the Covered Software is with You. - Should any Covered Software prove defective in any respect, You (not any - Contributor) assume the cost of any necessary servicing, repair, or - correction. This disclaimer of warranty constitutes an essential part of this - License. No use of any Covered Software is authorized under this License - except under this disclaimer. + Covered Software is provided under this License on an "as is" basis, + without warranty of any kind, either expressed, implied, or statutory, + including, without limitation, warranties that the Covered Software is free + of defects, merchantable, fit for a particular purpose or non-infringing. + The entire risk as to the quality and performance of the Covered Software + is with You. Should any Covered Software prove defective in any respect, + You (not any Contributor) assume the cost of any necessary servicing, + repair, or correction. This disclaimer of warranty constitutes an essential + part of this License. No use of any Covered Software is authorized under + this License except under this disclaimer. 7. Limitation of Liability @@ -279,27 +284,29 @@ Mozilla Public License, version 2.0 goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses, even if such party shall have been informed of the possibility of such damages. This limitation of liability - shall not apply to liability for death or personal injury resulting from such - party’s negligence to the extent applicable law prohibits such limitation. - Some jurisdictions do not allow the exclusion or limitation of incidental or - consequential damages, so this exclusion and limitation may not apply to You. + shall not apply to liability for death or personal injury resulting from + such party's negligence to the extent applicable law prohibits such + limitation. Some jurisdictions do not allow the exclusion or limitation of + incidental or consequential damages, so this exclusion and limitation may + not apply to You. 8. Litigation - Any litigation relating to this License may be brought only in the courts of - a jurisdiction where the defendant maintains its principal place of business - and such litigation shall be governed by laws of that jurisdiction, without - reference to its conflict-of-law provisions. Nothing in this Section shall - prevent a party’s ability to bring cross-claims or counter-claims. + Any litigation relating to this License may be brought only in the courts + of a jurisdiction where the defendant maintains its principal place of + business and such litigation shall be governed by laws of that + jurisdiction, without reference to its conflict-of-law provisions. Nothing + in this Section shall prevent a party's ability to bring cross-claims or + counter-claims. 9. Miscellaneous - This License represents the complete agreement concerning the subject matter - hereof. If any provision of this License is held to be unenforceable, such - provision shall be reformed only to the extent necessary to make it - enforceable. Any law or regulation which provides that the language of a - contract shall be construed against the drafter shall not be used to construe - this License against a Contributor. + This License represents the complete agreement concerning the subject + matter hereof. If any provision of this License is held to be + unenforceable, such provision shall be reformed only to the extent + necessary to make it enforceable. Any law or regulation which provides that + the language of a contract shall be construed against the drafter shall not + be used to construe this License against a Contributor. 10. Versions of the License @@ -313,23 +320,24 @@ Mozilla Public License, version 2.0 10.2. Effect of New Versions - You may distribute the Covered Software under the terms of the version of - the License under which You originally received the Covered Software, or - under the terms of any subsequent version published by the license + You may distribute the Covered Software under the terms of the version + of the License under which You originally received the Covered Software, + or under the terms of any subsequent version published by the license steward. 10.3. Modified Versions If you create software not governed by this License, and you want to - create a new license for such software, you may create and use a modified - version of this License if you rename the license and remove any - references to the name of the license steward (except to note that such - modified license differs from this License). + create a new license for such software, you may create and use a + modified version of this License if you rename the license and remove + any references to the name of the license steward (except to note that + such modified license differs from this License). -10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses - If You choose to distribute Source Code Form that is Incompatible With - Secondary Licenses under the terms of this version of the License, the - notice described in Exhibit B of this License must be attached. +10.4. Distributing Source Code Form that is Incompatible With Secondary + Licenses If You choose to distribute Source Code Form that is + Incompatible With Secondary Licenses under the terms of this version of + the License, the notice described in Exhibit B of this License must be + attached. Exhibit A - Source Code Form License Notice @@ -340,15 +348,16 @@ Exhibit A - Source Code Form License Notice obtain one at http://mozilla.org/MPL/2.0/. -If it is not possible or desirable to put the notice in a particular file, then -You may include the notice in a location (such as a LICENSE file in a relevant -directory) where a recipient would be likely to look for such a notice. +If it is not possible or desirable to put the notice in a particular file, +then You may include the notice in a location (such as a LICENSE file in a +relevant directory) where a recipient would be likely to look for such a +notice. You may add additional accurate notices of copyright ownership. -Exhibit B - “Incompatible With Secondary Licenses” Notice +Exhibit B - "Incompatible With Secondary Licenses" Notice - This Source Code Form is “Incompatible - With Secondary Licenses”, as defined by + This Source Code Form is "Incompatible + With Secondary Licenses", as defined by the Mozilla Public License, v. 2.0. diff --git a/vendor/github.com/hashicorp/go-secure-stdlib/parseutil/parsepath.go b/vendor/github.com/hashicorp/go-secure-stdlib/parseutil/parsepath.go new file mode 100644 index 000000000..d59ecbb2b --- /dev/null +++ b/vendor/github.com/hashicorp/go-secure-stdlib/parseutil/parsepath.go @@ -0,0 +1,65 @@ +package parseutil + +import ( + "errors" + "fmt" + "io/ioutil" + "net/url" + "os" + "strings" +) + +var ( + ErrNotAUrl = errors.New("not a url") + ErrNotParsed = errors.New("not a parsed value") +) + +// ParsePath parses a URL with schemes file://, env://, or any other. Depending +// on the scheme it will return specific types of data: +// +// * file:// will return a string with the file's contents +// +// * env:// will return a string with the env var's contents +// +// * Anything else will return the string as it was. Functionally this means +// anything for which Go's `url.Parse` function does not throw an error. If you +// want to ensure that this function errors if a known scheme is not found, use +// MustParsePath. +// +// On error, we return the original string along with the error. The caller can +// switch on errors.Is(err, ErrNotAUrl) to understand whether it was the parsing +// step that errored or something else (such as a file not found). This is +// useful to attempt to read a non-URL string from some resource, but where the +// original input may simply be a valid string of that type. +func ParsePath(path string) (string, error) { + return parsePath(path, false) +} + +// MustParsePath behaves like ParsePath but will return ErrNotAUrl if the value +// is not a URL with a scheme that can be parsed by this function. +func MustParsePath(path string) (string, error) { + return parsePath(path, true) +} + +func parsePath(path string, mustParse bool) (string, error) { + path = strings.TrimSpace(path) + parsed, err := url.Parse(path) + if err != nil { + return path, fmt.Errorf("error parsing url (%q): %w", err.Error(), ErrNotAUrl) + } + switch parsed.Scheme { + case "file": + contents, err := ioutil.ReadFile(strings.TrimPrefix(path, "file://")) + if err != nil { + return path, fmt.Errorf("error reading file at %s: %w", path, err) + } + return strings.TrimSpace(string(contents)), nil + case "env": + return strings.TrimSpace(os.Getenv(strings.TrimPrefix(path, "env://"))), nil + default: + if mustParse { + return "", ErrNotParsed + } + return path, nil + } +} diff --git a/vendor/github.com/hashicorp/go-secure-stdlib/parseutil/parseutil.go b/vendor/github.com/hashicorp/go-secure-stdlib/parseutil/parseutil.go new file mode 100644 index 000000000..e469499bd --- /dev/null +++ b/vendor/github.com/hashicorp/go-secure-stdlib/parseutil/parseutil.go @@ -0,0 +1,502 @@ +package parseutil + +import ( + "encoding/json" + "errors" + "fmt" + "math" + "regexp" + "strconv" + "strings" + "time" + + "github.com/hashicorp/go-secure-stdlib/strutil" + sockaddr "github.com/hashicorp/go-sockaddr" + "github.com/mitchellh/mapstructure" +) + +var validCapacityString = regexp.MustCompile("^[\t ]*([0-9]+)[\t ]?([kmgtKMGT][iI]?[bB])?[\t ]*$") + +// ParseCapacityString parses a capacity string and returns the number of bytes it represents. +// Capacity strings are things like 5gib or 10MB. Supported prefixes are kb, kib, mb, mib, gb, +// gib, tb, tib, which are not case sensitive. If no prefix is present, the number is assumed +// to be in bytes already. +func ParseCapacityString(in interface{}) (uint64, error) { + var cap uint64 + + jsonIn, ok := in.(json.Number) + if ok { + in = jsonIn.String() + } + + switch inp := in.(type) { + case nil: + // return default of zero + case string: + if inp == "" { + return cap, nil + } + + matches := validCapacityString.FindStringSubmatch(inp) + + // no sub-groups means we couldn't parse it + if len(matches) <= 1 { + return cap, errors.New("could not parse capacity from input") + } + + var multiplier uint64 = 1 + switch strings.ToLower(matches[2]) { + case "kb": + multiplier = 1000 + case "kib": + multiplier = 1024 + case "mb": + multiplier = 1000 * 1000 + case "mib": + multiplier = 1024 * 1024 + case "gb": + multiplier = 1000 * 1000 * 1000 + case "gib": + multiplier = 1024 * 1024 * 1024 + case "tb": + multiplier = 1000 * 1000 * 1000 * 1000 + case "tib": + multiplier = 1024 * 1024 * 1024 * 1024 + } + + size, err := strconv.ParseUint(matches[1], 10, 64) + if err != nil { + return cap, err + } + + cap = size * multiplier + case int: + cap = uint64(inp) + case int32: + cap = uint64(inp) + case int64: + cap = uint64(inp) + case uint: + cap = uint64(inp) + case uint32: + cap = uint64(inp) + case uint64: + cap = uint64(inp) + case float32: + cap = uint64(inp) + case float64: + cap = uint64(inp) + default: + return cap, errors.New("could not parse capacity from input") + } + + return cap, nil +} + +// Parse a duration from an arbitrary value (a string or numeric value) into +// a time.Duration; when units are missing (such as when a numeric type is +// provided), the duration is assumed to be in seconds. +func ParseDurationSecond(in interface{}) (time.Duration, error) { + var dur time.Duration + jsonIn, ok := in.(json.Number) + if ok { + in = jsonIn.String() + } + switch inp := in.(type) { + case nil: + // return default of zero + case string: + if inp == "" { + return dur, nil + } + + if v, err := strconv.ParseInt(inp, 10, 64); err == nil { + return time.Duration(v) * time.Second, nil + } + + if strings.HasSuffix(inp, "d") { + v, err := strconv.ParseInt(inp[:len(inp)-1], 10, 64) + if err != nil { + return dur, err + } + return time.Duration(v) * 24 * time.Hour, nil + } + + var err error + if dur, err = time.ParseDuration(inp); err != nil { + return dur, err + } + case int: + dur = time.Duration(inp) * time.Second + case int32: + dur = time.Duration(inp) * time.Second + case int64: + dur = time.Duration(inp) * time.Second + case uint: + dur = time.Duration(inp) * time.Second + case uint32: + dur = time.Duration(inp) * time.Second + case uint64: + dur = time.Duration(inp) * time.Second + case float32: + dur = time.Duration(inp) * time.Second + case float64: + dur = time.Duration(inp) * time.Second + case time.Duration: + dur = inp + default: + return 0, errors.New("could not parse duration from input") + } + + return dur, nil +} + +// Parse an absolute timestamp from the provided arbitrary value (string or +// numeric value). When an untyped numeric value is provided, it is assumed +// to be seconds from the Unix Epoch. +func ParseAbsoluteTime(in interface{}) (time.Time, error) { + var t time.Time + switch inp := in.(type) { + case nil: + // return default of zero + return t, nil + case string: + // Allow RFC3339 with nanoseconds, or without, + // or an epoch time as an integer. + var err error + t, err = time.Parse(time.RFC3339Nano, inp) + if err == nil { + break + } + t, err = time.Parse(time.RFC3339, inp) + if err == nil { + break + } + epochTime, err := strconv.ParseInt(inp, 10, 64) + if err == nil { + t = time.Unix(epochTime, 0) + break + } + return t, errors.New("could not parse string as date and time") + case json.Number: + epochTime, err := inp.Int64() + if err != nil { + return t, err + } + t = time.Unix(epochTime, 0) + case int: + t = time.Unix(int64(inp), 0) + case int32: + t = time.Unix(int64(inp), 0) + case int64: + t = time.Unix(inp, 0) + case uint: + t = time.Unix(int64(inp), 0) + case uint32: + t = time.Unix(int64(inp), 0) + case uint64: + t = time.Unix(int64(inp), 0) + default: + return t, errors.New("could not parse time from input type") + } + return t, nil +} + +// ParseInt takes an arbitrary value (either a string or numeric type) and +// parses it as an int64 value. This value is assumed to be larger than the +// provided type, but cannot safely be cast. +// +// When the end value is bounded (such as an int value), it is recommended +// to instead call SafeParseInt or SafeParseIntRange to safely cast to a +// more restrictive type. +func ParseInt(in interface{}) (int64, error) { + var ret int64 + jsonIn, ok := in.(json.Number) + if ok { + in = jsonIn.String() + } + switch in.(type) { + case string: + inp := in.(string) + if inp == "" { + return 0, nil + } + var err error + left, err := strconv.ParseInt(inp, 10, 64) + if err != nil { + return ret, err + } + ret = left + case int: + ret = int64(in.(int)) + case int32: + ret = int64(in.(int32)) + case int64: + ret = in.(int64) + case uint: + ret = int64(in.(uint)) + case uint32: + ret = int64(in.(uint32)) + case uint64: + ret = int64(in.(uint64)) + default: + return 0, errors.New("could not parse value from input") + } + + return ret, nil +} + +// ParseDirectIntSlice behaves similarly to ParseInt, but accepts typed +// slices, returning a slice of int64s. +// +// If the starting value may not be in slice form (e.g.. a bare numeric value +// could be provided), it is suggested to call ParseIntSlice instead. +func ParseDirectIntSlice(in interface{}) ([]int64, error) { + var ret []int64 + + switch in.(type) { + case []int: + for _, v := range in.([]int) { + ret = append(ret, int64(v)) + } + case []int32: + for _, v := range in.([]int32) { + ret = append(ret, int64(v)) + } + case []int64: + // For consistency to ensure callers can always modify ret without + // impacting in. + for _, v := range in.([]int64) { + ret = append(ret, v) + } + case []uint: + for _, v := range in.([]uint) { + ret = append(ret, int64(v)) + } + case []uint32: + for _, v := range in.([]uint32) { + ret = append(ret, int64(v)) + } + case []uint64: + for _, v := range in.([]uint64) { + ret = append(ret, int64(v)) + } + case []json.Number: + for _, v := range in.([]json.Number) { + element, err := ParseInt(v) + if err != nil { + return nil, err + } + ret = append(ret, element) + } + case []string: + for _, v := range in.([]string) { + element, err := ParseInt(v) + if err != nil { + return nil, err + } + ret = append(ret, element) + } + default: + return nil, errors.New("could not parse value from input") + } + + return ret, nil +} + +// ParseIntSlice is a helper function for handling upgrades of optional +// slices; that is, if the API accepts a type similar to , +// nicely handle the common cases of providing only an int-ish, providing +// an actual slice of int-ishes, or providing a comma-separated list of +// numbers. +// +// When []int64 is not the desired final type (or the values should be +// range-bound), it is suggested to call SafeParseIntSlice or +// SafeParseIntSliceRange instead. +func ParseIntSlice(in interface{}) ([]int64, error) { + if ret, err := ParseInt(in); err == nil { + return []int64{ret}, nil + } + + if ret, err := ParseDirectIntSlice(in); err == nil { + return ret, nil + } + + if strings, err := ParseCommaStringSlice(in); err == nil { + var ret []int64 + for _, v := range strings { + if v == "" { + // Ignore empty fields + continue + } + + element, err := ParseInt(v) + if err != nil { + return nil, err + } + ret = append(ret, element) + } + + return ret, nil + } + + return nil, errors.New("could not parse value from input") +} + +// Parses the provided arbitrary value as a boolean-like value. +func ParseBool(in interface{}) (bool, error) { + var result bool + if err := mapstructure.WeakDecode(in, &result); err != nil { + return false, err + } + return result, nil +} + +// Parses the provided arbitrary value as a string. +func ParseString(in interface{}) (string, error) { + var result string + if err := mapstructure.WeakDecode(in, &result); err != nil { + return "", err + } + return result, nil +} + +// Parses the provided string-like value as a comma-separated list of values. +func ParseCommaStringSlice(in interface{}) ([]string, error) { + jsonIn, ok := in.(json.Number) + if ok { + in = jsonIn.String() + } + + rawString, ok := in.(string) + if ok && rawString == "" { + return []string{}, nil + } + var result []string + config := &mapstructure.DecoderConfig{ + Result: &result, + WeaklyTypedInput: true, + DecodeHook: mapstructure.StringToSliceHookFunc(","), + } + decoder, err := mapstructure.NewDecoder(config) + if err != nil { + return nil, err + } + if err := decoder.Decode(in); err != nil { + return nil, err + } + return strutil.TrimStrings(result), nil +} + +// Parses the specified value as one or more addresses, separated by commas. +func ParseAddrs(addrs interface{}) ([]*sockaddr.SockAddrMarshaler, error) { + out := make([]*sockaddr.SockAddrMarshaler, 0) + stringAddrs := make([]string, 0) + + switch addrs.(type) { + case string: + stringAddrs = strutil.ParseArbitraryStringSlice(addrs.(string), ",") + if len(stringAddrs) == 0 { + return nil, fmt.Errorf("unable to parse addresses from %v", addrs) + } + + case []string: + stringAddrs = addrs.([]string) + + case []interface{}: + for _, v := range addrs.([]interface{}) { + stringAddr, ok := v.(string) + if !ok { + return nil, fmt.Errorf("error parsing %v as string", v) + } + stringAddrs = append(stringAddrs, stringAddr) + } + + default: + return nil, fmt.Errorf("unknown address input type %T", addrs) + } + + for _, addr := range stringAddrs { + sa, err := sockaddr.NewSockAddr(addr) + if err != nil { + return nil, fmt.Errorf("error parsing address %q: %w", addr, err) + } + out = append(out, &sockaddr.SockAddrMarshaler{ + SockAddr: sa, + }) + } + + return out, nil +} + +// Parses the provided arbitrary value (see ParseInt), ensuring it is within +// the specified range (inclusive of bounds). If this range corresponds to a +// smaller type, the returned value can then be safely cast without risking +// overflow. +func SafeParseIntRange(in interface{}, min int64, max int64) (int64, error) { + raw, err := ParseInt(in) + if err != nil { + return 0, err + } + + if raw < min || raw > max { + return 0, fmt.Errorf("error parsing int value; out of range [%v to %v]: %v", min, max, raw) + } + + return raw, nil +} + +// Parses the specified arbitrary value (see ParseInt), ensuring that the +// resulting value is within the range for an int value. If no error occurred, +// the caller knows no overflow occurred. +func SafeParseInt(in interface{}) (int, error) { + raw, err := SafeParseIntRange(in, math.MinInt, math.MaxInt) + return int(raw), err +} + +// Parses the provided arbitrary value (see ParseIntSlice) into a slice of +// int64 values, ensuring each is within the specified range (inclusive of +// bounds). If this range corresponds to a smaller type, the returned value +// can then be safely cast without risking overflow. +// +// If elements is positive, it is used to ensure the resulting slice is +// bounded above by that many number of elements (inclusive). +func SafeParseIntSliceRange(in interface{}, minValue int64, maxValue int64, elements int) ([]int64, error) { + raw, err := ParseIntSlice(in) + if err != nil { + return nil, err + } + + if elements > 0 && len(raw) > elements { + return nil, fmt.Errorf("error parsing value from input: got %v but expected at most %v elements", len(raw), elements) + } + + for index, value := range raw { + if value < minValue || value > maxValue { + return nil, fmt.Errorf("error parsing value from input: element %v was outside of range [%v to %v]: %v", index, minValue, maxValue, value) + } + } + + return raw, nil +} + +// Parses the provided arbitrary value (see ParseIntSlice) into a slice of +// int values, ensuring the each resulting value in the slice is within the +// range for an int value. If no error occurred, the caller knows no overflow +// occurred. +// +// If elements is positive, it is used to ensure the resulting slice is +// bounded above by that many number of elements (inclusive). +func SafeParseIntSlice(in interface{}, elements int) ([]int, error) { + raw, err := SafeParseIntSliceRange(in, math.MinInt, math.MaxInt, elements) + if err != nil || raw == nil { + return nil, err + } + + var result = make([]int, 0, len(raw)) + for _, element := range raw { + result = append(result, int(element)) + } + + return result, nil +} diff --git a/vendor/github.com/hashicorp/go-multierror/LICENSE b/vendor/github.com/hashicorp/go-secure-stdlib/strutil/LICENSE similarity index 50% rename from vendor/github.com/hashicorp/go-multierror/LICENSE rename to vendor/github.com/hashicorp/go-secure-stdlib/strutil/LICENSE index 82b4de97c..e87a115e4 100644 --- a/vendor/github.com/hashicorp/go-multierror/LICENSE +++ b/vendor/github.com/hashicorp/go-secure-stdlib/strutil/LICENSE @@ -2,89 +2,89 @@ Mozilla Public License, version 2.0 1. Definitions -1.1. “Contributor” +1.1. "Contributor" means each individual or legal entity that creates, contributes to the creation of, or owns Covered Software. -1.2. “Contributor Version” +1.2. "Contributor Version" means the combination of the Contributions of others (if any) used by a - Contributor and that particular Contributor’s Contribution. + Contributor and that particular Contributor's Contribution. -1.3. “Contribution” +1.3. "Contribution" means Covered Software of a particular Contributor. -1.4. “Covered Software” +1.4. "Covered Software" means Source Code Form to which the initial Contributor has attached the notice in Exhibit A, the Executable Form of such Source Code Form, and Modifications of such Source Code Form, in each case including portions thereof. -1.5. “Incompatible With Secondary Licenses” +1.5. "Incompatible With Secondary Licenses" means a. that the initial Contributor has attached the notice described in Exhibit B to the Covered Software; or - b. that the Covered Software was made available under the terms of version - 1.1 or earlier of the License, but not also under the terms of a - Secondary License. + b. that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the terms of + a Secondary License. -1.6. “Executable Form” +1.6. "Executable Form" means any form of the work other than Source Code Form. -1.7. “Larger Work” +1.7. "Larger Work" - means a work that combines Covered Software with other material, in a separate - file or files, that is not Covered Software. + means a work that combines Covered Software with other material, in a + separate file or files, that is not Covered Software. -1.8. “License” +1.8. "License" means this document. -1.9. “Licensable” +1.9. "Licensable" - means having the right to grant, to the maximum extent possible, whether at the - time of the initial grant or subsequently, any and all of the rights conveyed by - this License. + means having the right to grant, to the maximum extent possible, whether + at the time of the initial grant or subsequently, any and all of the + rights conveyed by this License. -1.10. “Modifications” +1.10. "Modifications" means any of the following: - a. any file in Source Code Form that results from an addition to, deletion - from, or modification of the contents of Covered Software; or + a. any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered Software; or b. any new file in Source Code Form that contains any Covered Software. -1.11. “Patent Claims” of a Contributor +1.11. "Patent Claims" of a Contributor - means any patent claim(s), including without limitation, method, process, - and apparatus claims, in any patent Licensable by such Contributor that - would be infringed, but for the grant of the License, by the making, - using, selling, offering for sale, having made, import, or transfer of - either its Contributions or its Contributor Version. + means any patent claim(s), including without limitation, method, + process, and apparatus claims, in any patent Licensable by such + Contributor that would be infringed, but for the grant of the License, + by the making, using, selling, offering for sale, having made, import, + or transfer of either its Contributions or its Contributor Version. -1.12. “Secondary License” +1.12. "Secondary License" means either the GNU General Public License, Version 2.0, the GNU Lesser General Public License, Version 2.1, the GNU Affero General Public License, Version 3.0, or any later versions of those licenses. -1.13. “Source Code Form” +1.13. "Source Code Form" means the form of the work preferred for making modifications. -1.14. “You” (or “Your”) +1.14. "You" (or "Your") means an individual or a legal entity exercising rights under this - License. For legal entities, “You” includes any entity that controls, is + License. For legal entities, "You" includes any entity that controls, is controlled by, or is under common control with You. For purposes of this - definition, “control” means (a) the power, direct or indirect, to cause + definition, "control" means (a) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (b) ownership of more than fifty percent (50%) of the outstanding shares or beneficial ownership of such entity. @@ -100,57 +100,59 @@ Mozilla Public License, version 2.0 a. under intellectual property rights (other than patent or trademark) Licensable by such Contributor to use, reproduce, make available, modify, display, perform, distribute, and otherwise exploit its - Contributions, either on an unmodified basis, with Modifications, or as - part of a Larger Work; and + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and b. under Patent Claims of such Contributor to make, use, sell, offer for - sale, have made, import, and otherwise transfer either its Contributions - or its Contributor Version. + sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. 2.2. Effective Date - The licenses granted in Section 2.1 with respect to any Contribution become - effective for each Contribution on the date the Contributor first distributes - such Contribution. + The licenses granted in Section 2.1 with respect to any Contribution + become effective for each Contribution on the date the Contributor first + distributes such Contribution. 2.3. Limitations on Grant Scope - The licenses granted in this Section 2 are the only rights granted under this - License. No additional rights or licenses will be implied from the distribution - or licensing of Covered Software under this License. Notwithstanding Section - 2.1(b) above, no patent license is granted by a Contributor: + The licenses granted in this Section 2 are the only rights granted under + this License. No additional rights or licenses will be implied from the + distribution or licensing of Covered Software under this License. + Notwithstanding Section 2.1(b) above, no patent license is granted by a + Contributor: a. for any code that a Contributor has removed from Covered Software; or - b. for infringements caused by: (i) Your and any other third party’s + b. for infringements caused by: (i) Your and any other third party's modifications of Covered Software, or (ii) the combination of its Contributions with other software (except as part of its Contributor Version); or - c. under Patent Claims infringed by Covered Software in the absence of its - Contributions. + c. under Patent Claims infringed by Covered Software in the absence of + its Contributions. - This License does not grant any rights in the trademarks, service marks, or - logos of any Contributor (except as may be necessary to comply with the - notice requirements in Section 3.4). + This License does not grant any rights in the trademarks, service marks, + or logos of any Contributor (except as may be necessary to comply with + the notice requirements in Section 3.4). 2.4. Subsequent Licenses No Contributor makes additional grants as a result of Your choice to - distribute the Covered Software under a subsequent version of this License - (see Section 10.2) or under the terms of a Secondary License (if permitted - under the terms of Section 3.3). + distribute the Covered Software under a subsequent version of this + License (see Section 10.2) or under the terms of a Secondary License (if + permitted under the terms of Section 3.3). 2.5. Representation - Each Contributor represents that the Contributor believes its Contributions - are its original creation(s) or it has sufficient rights to grant the - rights to its Contributions conveyed by this License. + Each Contributor represents that the Contributor believes its + Contributions are its original creation(s) or it has sufficient rights to + grant the rights to its Contributions conveyed by this License. 2.6. Fair Use - This License is not intended to limit any rights You have under applicable - copyright doctrines of fair use, fair dealing, or other equivalents. + This License is not intended to limit any rights You have under + applicable copyright doctrines of fair use, fair dealing, or other + equivalents. 2.7. Conditions @@ -163,11 +165,12 @@ Mozilla Public License, version 2.0 3.1. Distribution of Source Form All distribution of Covered Software in Source Code Form, including any - Modifications that You create or to which You contribute, must be under the - terms of this License. You must inform recipients that the Source Code Form - of the Covered Software is governed by the terms of this License, and how - they can obtain a copy of this License. You may not attempt to alter or - restrict the recipients’ rights in the Source Code Form. + Modifications that You create or to which You contribute, must be under + the terms of this License. You must inform recipients that the Source + Code Form of the Covered Software is governed by the terms of this + License, and how they can obtain a copy of this License. You may not + attempt to alter or restrict the recipients' rights in the Source Code + Form. 3.2. Distribution of Executable Form @@ -179,39 +182,40 @@ Mozilla Public License, version 2.0 reasonable means in a timely manner, at a charge no more than the cost of distribution to the recipient; and - b. You may distribute such Executable Form under the terms of this License, - or sublicense it under different terms, provided that the license for - the Executable Form does not attempt to limit or alter the recipients’ - rights in the Source Code Form under this License. + b. You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter the + recipients' rights in the Source Code Form under this License. 3.3. Distribution of a Larger Work You may create and distribute a Larger Work under terms of Your choice, - provided that You also comply with the requirements of this License for the - Covered Software. If the Larger Work is a combination of Covered Software - with a work governed by one or more Secondary Licenses, and the Covered - Software is not Incompatible With Secondary Licenses, this License permits - You to additionally distribute such Covered Software under the terms of - such Secondary License(s), so that the recipient of the Larger Work may, at - their option, further distribute the Covered Software under the terms of - either this License or such Secondary License(s). + provided that You also comply with the requirements of this License for + the Covered Software. If the Larger Work is a combination of Covered + Software with a work governed by one or more Secondary Licenses, and the + Covered Software is not Incompatible With Secondary Licenses, this + License permits You to additionally distribute such Covered Software + under the terms of such Secondary License(s), so that the recipient of + the Larger Work may, at their option, further distribute the Covered + Software under the terms of either this License or such Secondary + License(s). 3.4. Notices - You may not remove or alter the substance of any license notices (including - copyright notices, patent notices, disclaimers of warranty, or limitations - of liability) contained within the Source Code Form of the Covered - Software, except that You may alter any license notices to the extent - required to remedy known factual inaccuracies. + You may not remove or alter the substance of any license notices + (including copyright notices, patent notices, disclaimers of warranty, or + limitations of liability) contained within the Source Code Form of the + Covered Software, except that You may alter any license notices to the + extent required to remedy known factual inaccuracies. 3.5. Application of Additional Terms You may choose to offer, and to charge a fee for, warranty, support, indemnity or liability obligations to one or more recipients of Covered - Software. However, You may do so only on Your own behalf, and not on behalf - of any Contributor. You must make it absolutely clear that any such - warranty, support, indemnity, or liability obligation is offered by You - alone, and You hereby agree to indemnify every Contributor for any + Software. However, You may do so only on Your own behalf, and not on + behalf of any Contributor. You must make it absolutely clear that any + such warranty, support, indemnity, or liability obligation is offered by + You alone, and You hereby agree to indemnify every Contributor for any liability incurred by such Contributor as a result of warranty, support, indemnity or liability terms You offer. You may include additional disclaimers of warranty and limitations of liability specific to any @@ -220,14 +224,14 @@ Mozilla Public License, version 2.0 4. Inability to Comply Due to Statute or Regulation If it is impossible for You to comply with any of the terms of this License - with respect to some or all of the Covered Software due to statute, judicial - order, or regulation then You must: (a) comply with the terms of this License - to the maximum extent possible; and (b) describe the limitations and the code - they affect. Such description must be placed in a text file included with all - distributions of the Covered Software under this License. Except to the - extent prohibited by statute or regulation, such description must be - sufficiently detailed for a recipient of ordinary skill to be able to - understand it. + with respect to some or all of the Covered Software due to statute, + judicial order, or regulation then You must: (a) comply with the terms of + this License to the maximum extent possible; and (b) describe the + limitations and the code they affect. Such description must be placed in a + text file included with all distributions of the Covered Software under + this License. Except to the extent prohibited by statute or regulation, + such description must be sufficiently detailed for a recipient of ordinary + skill to be able to understand it. 5. Termination @@ -235,21 +239,22 @@ Mozilla Public License, version 2.0 fail to comply with any of its terms. However, if You become compliant, then the rights granted under this License from a particular Contributor are reinstated (a) provisionally, unless and until such Contributor - explicitly and finally terminates Your grants, and (b) on an ongoing basis, - if such Contributor fails to notify You of the non-compliance by some - reasonable means prior to 60 days after You have come back into compliance. - Moreover, Your grants from a particular Contributor are reinstated on an - ongoing basis if such Contributor notifies You of the non-compliance by - some reasonable means, this is the first time You have received notice of - non-compliance with this License from such Contributor, and You become - compliant prior to 30 days after Your receipt of the notice. + explicitly and finally terminates Your grants, and (b) on an ongoing + basis, if such Contributor fails to notify You of the non-compliance by + some reasonable means prior to 60 days after You have come back into + compliance. Moreover, Your grants from a particular Contributor are + reinstated on an ongoing basis if such Contributor notifies You of the + non-compliance by some reasonable means, this is the first time You have + received notice of non-compliance with this License from such + Contributor, and You become compliant prior to 30 days after Your receipt + of the notice. 5.2. If You initiate litigation against any entity by asserting a patent - infringement claim (excluding declaratory judgment actions, counter-claims, - and cross-claims) alleging that a Contributor Version directly or - indirectly infringes any patent, then the rights granted to You by any and - all Contributors for the Covered Software under Section 2.1 of this License - shall terminate. + infringement claim (excluding declaratory judgment actions, + counter-claims, and cross-claims) alleging that a Contributor Version + directly or indirectly infringes any patent, then the rights granted to + You by any and all Contributors for the Covered Software under Section + 2.1 of this License shall terminate. 5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user license agreements (excluding distributors and resellers) which have been @@ -258,16 +263,16 @@ Mozilla Public License, version 2.0 6. Disclaimer of Warranty - Covered Software is provided under this License on an “as is” basis, without - warranty of any kind, either expressed, implied, or statutory, including, - without limitation, warranties that the Covered Software is free of defects, - merchantable, fit for a particular purpose or non-infringing. The entire - risk as to the quality and performance of the Covered Software is with You. - Should any Covered Software prove defective in any respect, You (not any - Contributor) assume the cost of any necessary servicing, repair, or - correction. This disclaimer of warranty constitutes an essential part of this - License. No use of any Covered Software is authorized under this License - except under this disclaimer. + Covered Software is provided under this License on an "as is" basis, + without warranty of any kind, either expressed, implied, or statutory, + including, without limitation, warranties that the Covered Software is free + of defects, merchantable, fit for a particular purpose or non-infringing. + The entire risk as to the quality and performance of the Covered Software + is with You. Should any Covered Software prove defective in any respect, + You (not any Contributor) assume the cost of any necessary servicing, + repair, or correction. This disclaimer of warranty constitutes an essential + part of this License. No use of any Covered Software is authorized under + this License except under this disclaimer. 7. Limitation of Liability @@ -279,27 +284,29 @@ Mozilla Public License, version 2.0 goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses, even if such party shall have been informed of the possibility of such damages. This limitation of liability - shall not apply to liability for death or personal injury resulting from such - party’s negligence to the extent applicable law prohibits such limitation. - Some jurisdictions do not allow the exclusion or limitation of incidental or - consequential damages, so this exclusion and limitation may not apply to You. + shall not apply to liability for death or personal injury resulting from + such party's negligence to the extent applicable law prohibits such + limitation. Some jurisdictions do not allow the exclusion or limitation of + incidental or consequential damages, so this exclusion and limitation may + not apply to You. 8. Litigation - Any litigation relating to this License may be brought only in the courts of - a jurisdiction where the defendant maintains its principal place of business - and such litigation shall be governed by laws of that jurisdiction, without - reference to its conflict-of-law provisions. Nothing in this Section shall - prevent a party’s ability to bring cross-claims or counter-claims. + Any litigation relating to this License may be brought only in the courts + of a jurisdiction where the defendant maintains its principal place of + business and such litigation shall be governed by laws of that + jurisdiction, without reference to its conflict-of-law provisions. Nothing + in this Section shall prevent a party's ability to bring cross-claims or + counter-claims. 9. Miscellaneous - This License represents the complete agreement concerning the subject matter - hereof. If any provision of this License is held to be unenforceable, such - provision shall be reformed only to the extent necessary to make it - enforceable. Any law or regulation which provides that the language of a - contract shall be construed against the drafter shall not be used to construe - this License against a Contributor. + This License represents the complete agreement concerning the subject + matter hereof. If any provision of this License is held to be + unenforceable, such provision shall be reformed only to the extent + necessary to make it enforceable. Any law or regulation which provides that + the language of a contract shall be construed against the drafter shall not + be used to construe this License against a Contributor. 10. Versions of the License @@ -313,23 +320,24 @@ Mozilla Public License, version 2.0 10.2. Effect of New Versions - You may distribute the Covered Software under the terms of the version of - the License under which You originally received the Covered Software, or - under the terms of any subsequent version published by the license + You may distribute the Covered Software under the terms of the version + of the License under which You originally received the Covered Software, + or under the terms of any subsequent version published by the license steward. 10.3. Modified Versions If you create software not governed by this License, and you want to - create a new license for such software, you may create and use a modified - version of this License if you rename the license and remove any - references to the name of the license steward (except to note that such - modified license differs from this License). + create a new license for such software, you may create and use a + modified version of this License if you rename the license and remove + any references to the name of the license steward (except to note that + such modified license differs from this License). -10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses - If You choose to distribute Source Code Form that is Incompatible With - Secondary Licenses under the terms of this version of the License, the - notice described in Exhibit B of this License must be attached. +10.4. Distributing Source Code Form that is Incompatible With Secondary + Licenses If You choose to distribute Source Code Form that is + Incompatible With Secondary Licenses under the terms of this version of + the License, the notice described in Exhibit B of this License must be + attached. Exhibit A - Source Code Form License Notice @@ -340,14 +348,16 @@ Exhibit A - Source Code Form License Notice obtain one at http://mozilla.org/MPL/2.0/. -If it is not possible or desirable to put the notice in a particular file, then -You may include the notice in a location (such as a LICENSE file in a relevant -directory) where a recipient would be likely to look for such a notice. +If it is not possible or desirable to put the notice in a particular file, +then You may include the notice in a location (such as a LICENSE file in a +relevant directory) where a recipient would be likely to look for such a +notice. You may add additional accurate notices of copyright ownership. -Exhibit B - “Incompatible With Secondary Licenses” Notice +Exhibit B - "Incompatible With Secondary Licenses" Notice - This Source Code Form is “Incompatible - With Secondary Licenses”, as defined by + This Source Code Form is "Incompatible + With Secondary Licenses", as defined by the Mozilla Public License, v. 2.0. + diff --git a/vendor/github.com/hashicorp/go-secure-stdlib/strutil/strutil.go b/vendor/github.com/hashicorp/go-secure-stdlib/strutil/strutil.go new file mode 100644 index 000000000..102462dc6 --- /dev/null +++ b/vendor/github.com/hashicorp/go-secure-stdlib/strutil/strutil.go @@ -0,0 +1,510 @@ +package strutil + +import ( + "encoding/base64" + "encoding/json" + "fmt" + "sort" + "strings" + "unicode" + + glob "github.com/ryanuber/go-glob" +) + +// StrListContainsGlob looks for a string in a list of strings and allows +// globs. +func StrListContainsGlob(haystack []string, needle string) bool { + for _, item := range haystack { + if glob.Glob(item, needle) { + return true + } + } + return false +} + +// StrListContains looks for a string in a list of strings. +func StrListContains(haystack []string, needle string) bool { + for _, item := range haystack { + if item == needle { + return true + } + } + return false +} + +// StrListContainsCaseInsensitive looks for a string in a list of strings. +func StrListContainsCaseInsensitive(haystack []string, needle string) bool { + for _, item := range haystack { + if strings.EqualFold(item, needle) { + return true + } + } + return false +} + +// StrListSubset checks if a given list is a subset +// of another set +func StrListSubset(super, sub []string) bool { + for _, item := range sub { + if !StrListContains(super, item) { + return false + } + } + return true +} + +// ParseDedupAndSortStrings parses a comma separated list of strings +// into a slice of strings. The return slice will be sorted and will +// not contain duplicate or empty items. +func ParseDedupAndSortStrings(input string, sep string) []string { + input = strings.TrimSpace(input) + parsed := []string{} + if input == "" { + // Don't return nil + return parsed + } + return RemoveDuplicates(strings.Split(input, sep), false) +} + +// ParseDedupLowercaseAndSortStrings parses a comma separated list of +// strings into a slice of strings. The return slice will be sorted and +// will not contain duplicate or empty items. The values will be converted +// to lower case. +func ParseDedupLowercaseAndSortStrings(input string, sep string) []string { + input = strings.TrimSpace(input) + parsed := []string{} + if input == "" { + // Don't return nil + return parsed + } + return RemoveDuplicates(strings.Split(input, sep), true) +} + +// ParseKeyValues parses a comma separated list of `=` tuples +// into a map[string]string. +func ParseKeyValues(input string, out map[string]string, sep string) error { + if out == nil { + return fmt.Errorf("'out is nil") + } + + keyValues := ParseDedupLowercaseAndSortStrings(input, sep) + if len(keyValues) == 0 { + return nil + } + + for _, keyValue := range keyValues { + shards := strings.Split(keyValue, "=") + if len(shards) != 2 { + return fmt.Errorf("invalid format") + } + + key := strings.TrimSpace(shards[0]) + value := strings.TrimSpace(shards[1]) + if key == "" || value == "" { + return fmt.Errorf("invalid pair: key: %q value: %q", key, value) + } + out[key] = value + } + return nil +} + +// ParseArbitraryKeyValues parses arbitrary tuples. The input +// can be one of the following: +// * JSON string +// * Base64 encoded JSON string +// * Comma separated list of `=` pairs +// * Base64 encoded string containing comma separated list of +// `=` pairs +// +// Input will be parsed into the output parameter, which should +// be a non-nil map[string]string. +func ParseArbitraryKeyValues(input string, out map[string]string, sep string) error { + input = strings.TrimSpace(input) + if input == "" { + return nil + } + if out == nil { + return fmt.Errorf("'out' is nil") + } + + // Try to base64 decode the input. If successful, consider the decoded + // value as input. + inputBytes, err := base64.StdEncoding.DecodeString(input) + if err == nil { + input = string(inputBytes) + } + + // Try to JSON unmarshal the input. If successful, consider that the + // metadata was supplied as JSON input. + err = json.Unmarshal([]byte(input), &out) + if err != nil { + // If JSON unmarshaling fails, consider that the input was + // supplied as a comma separated string of 'key=value' pairs. + if err = ParseKeyValues(input, out, sep); err != nil { + return fmt.Errorf("failed to parse the input: %w", err) + } + } + + // Validate the parsed input + for key, value := range out { + if key != "" && value == "" { + return fmt.Errorf("invalid value for key %q", key) + } + } + + return nil +} + +// ParseStringSlice parses a `sep`-separated list of strings into a +// []string with surrounding whitespace removed. +// +// The output will always be a valid slice but may be of length zero. +func ParseStringSlice(input string, sep string) []string { + input = strings.TrimSpace(input) + if input == "" { + return []string{} + } + + splitStr := strings.Split(input, sep) + ret := make([]string, len(splitStr)) + for i, val := range splitStr { + ret[i] = strings.TrimSpace(val) + } + + return ret +} + +// ParseArbitraryStringSlice parses arbitrary string slice. The input +// can be one of the following: +// * JSON string +// * Base64 encoded JSON string +// * `sep` separated list of values +// * Base64-encoded string containing a `sep` separated list of values +// +// Note that the separator is ignored if the input is found to already be in a +// structured format (e.g., JSON) +// +// The output will always be a valid slice but may be of length zero. +func ParseArbitraryStringSlice(input string, sep string) []string { + input = strings.TrimSpace(input) + if input == "" { + return []string{} + } + + // Try to base64 decode the input. If successful, consider the decoded + // value as input. + inputBytes, err := base64.StdEncoding.DecodeString(input) + if err == nil { + input = string(inputBytes) + } + + ret := []string{} + + // Try to JSON unmarshal the input. If successful, consider that the + // metadata was supplied as JSON input. + err = json.Unmarshal([]byte(input), &ret) + if err != nil { + // If JSON unmarshaling fails, consider that the input was + // supplied as a separated string of values. + return ParseStringSlice(input, sep) + } + + if ret == nil { + return []string{} + } + + return ret +} + +// TrimStrings takes a slice of strings and returns a slice of strings +// with trimmed spaces +func TrimStrings(items []string) []string { + ret := make([]string, len(items)) + for i, item := range items { + ret[i] = strings.TrimSpace(item) + } + return ret +} + +// RemoveDuplicates removes duplicate and empty elements from a slice of +// strings. This also may convert the items in the slice to lower case and +// returns a sorted slice. +func RemoveDuplicates(items []string, lowercase bool) []string { + itemsMap := make(map[string]struct{}, len(items)) + for _, item := range items { + item = strings.TrimSpace(item) + if item == "" { + continue + } + if lowercase { + item = strings.ToLower(item) + } + itemsMap[item] = struct{}{} + } + items = make([]string, 0, len(itemsMap)) + for item := range itemsMap { + items = append(items, item) + } + sort.Strings(items) + return items +} + +// RemoveDuplicatesStable removes duplicate and empty elements from a slice of +// strings, preserving order (and case) of the original slice. +// In all cases, strings are compared after trimming whitespace +// If caseInsensitive, strings will be compared after ToLower() +func RemoveDuplicatesStable(items []string, caseInsensitive bool) []string { + itemsMap := make(map[string]struct{}, len(items)) + deduplicated := make([]string, 0, len(items)) + + for _, item := range items { + key := strings.TrimSpace(item) + if _, ok := itemsMap[key]; ok || key == "" { + continue + } + if caseInsensitive { + key = strings.ToLower(key) + } + if _, ok := itemsMap[key]; ok { + continue + } + itemsMap[key] = struct{}{} + deduplicated = append(deduplicated, item) + } + return deduplicated +} + +// RemoveEmpty removes empty elements from a slice of +// strings +func RemoveEmpty(items []string) []string { + if len(items) == 0 { + return items + } + itemsSlice := make([]string, 0, len(items)) + for _, item := range items { + if item == "" { + continue + } + itemsSlice = append(itemsSlice, item) + } + return itemsSlice +} + +// EquivalentSlices checks whether the given string sets are equivalent, as in, +// they contain the same values. +func EquivalentSlices(a, b []string) bool { + if a == nil && b == nil { + return true + } + + if a == nil || b == nil { + return false + } + + // First we'll build maps to ensure unique values + mapA := make(map[string]struct{}, len(a)) + mapB := make(map[string]struct{}, len(b)) + for _, keyA := range a { + mapA[keyA] = struct{}{} + } + for _, keyB := range b { + mapB[keyB] = struct{}{} + } + + // Now we'll build our checking slices + sortedA := make([]string, 0, len(mapA)) + sortedB := make([]string, 0, len(mapB)) + for keyA := range mapA { + sortedA = append(sortedA, keyA) + } + for keyB := range mapB { + sortedB = append(sortedB, keyB) + } + sort.Strings(sortedA) + sort.Strings(sortedB) + + // Finally, compare + if len(sortedA) != len(sortedB) { + return false + } + + for i := range sortedA { + if sortedA[i] != sortedB[i] { + return false + } + } + + return true +} + +// EqualStringMaps tests whether two map[string]string objects are equal. +// Equal means both maps have the same sets of keys and values. This function +// is 6-10x faster than a call to reflect.DeepEqual(). +func EqualStringMaps(a, b map[string]string) bool { + if len(a) != len(b) { + return false + } + + for k := range a { + v, ok := b[k] + if !ok || a[k] != v { + return false + } + } + + return true +} + +// StrListDelete removes the first occurrence of the given item from the slice +// of strings if the item exists. +func StrListDelete(s []string, d string) []string { + if s == nil { + return s + } + + for index, element := range s { + if element == d { + return append(s[:index], s[index+1:]...) + } + } + + return s +} + +// GlobbedStringsMatch compares item to val with support for a leading and/or +// trailing wildcard '*' in item. +func GlobbedStringsMatch(item, val string) bool { + if len(item) < 2 { + return val == item + } + + hasPrefix := strings.HasPrefix(item, "*") + hasSuffix := strings.HasSuffix(item, "*") + + if hasPrefix && hasSuffix { + return strings.Contains(val, item[1:len(item)-1]) + } else if hasPrefix { + return strings.HasSuffix(val, item[1:]) + } else if hasSuffix { + return strings.HasPrefix(val, item[:len(item)-1]) + } + + return val == item +} + +// AppendIfMissing adds a string to a slice if the given string is not present +func AppendIfMissing(slice []string, i string) []string { + if StrListContains(slice, i) { + return slice + } + return append(slice, i) +} + +// MergeSlices adds an arbitrary number of slices together, uniquely +func MergeSlices(args ...[]string) []string { + all := map[string]struct{}{} + for _, slice := range args { + for _, v := range slice { + all[v] = struct{}{} + } + } + + result := make([]string, 0, len(all)) + for k := range all { + result = append(result, k) + } + sort.Strings(result) + return result +} + +// Difference returns the set difference (A - B) of the two given slices. The +// result will also remove any duplicated values in set A regardless of whether +// that matches any values in set B. +func Difference(a, b []string, lowercase bool) []string { + if len(a) == 0 { + return a + } + if len(b) == 0 { + if !lowercase { + return a + } + newA := make([]string, len(a)) + for i, v := range a { + newA[i] = strings.ToLower(v) + } + return newA + } + + a = RemoveDuplicates(a, lowercase) + b = RemoveDuplicates(b, lowercase) + + itemsMap := map[string]struct{}{} + for _, aVal := range a { + itemsMap[aVal] = struct{}{} + } + + // Perform difference calculation + for _, bVal := range b { + if _, ok := itemsMap[bVal]; ok { + delete(itemsMap, bVal) + } + } + + items := []string{} + for item := range itemsMap { + items = append(items, item) + } + sort.Strings(items) + return items +} + +// GetString attempts to retrieve a value from the provided map and assert that it is a string. If the key does not +// exist in the map, this will return an empty string. If the key exists, but the value is not a string type, this will +// return an error. If no map or key is provied, this will return an error +func GetString(m map[string]interface{}, key string) (string, error) { + if m == nil { + return "", fmt.Errorf("missing map") + } + if key == "" { + return "", fmt.Errorf("missing key") + } + + rawVal, ok := m[key] + if !ok { + return "", nil + } + + str, ok := rawVal.(string) + if !ok { + return "", fmt.Errorf("invalid value at %s: is a %T", key, rawVal) + } + return str, nil +} + +// Printable returns true if all characters in the string are printable +// according to Unicode +func Printable(s string) bool { + return strings.IndexFunc(s, func(c rune) bool { + return !unicode.IsPrint(c) + }) == -1 +} + +// StringListToInterfaceList simply takes a []string and turns it into a +// []interface{} to satisfy the input requirements for other library functions +func StringListToInterfaceList(in []string) []interface{} { + ret := make([]interface{}, len(in)) + for i, v := range in { + ret[i] = v + } + return ret +} + +// Reverse reverses the input string +func Reverse(in string) string { + l := len(in) + out := make([]byte, l) + for i := 0; i <= l/2; i++ { + out[i], out[l-1-i] = in[l-1-i], in[i] + } + return string(out) +} diff --git a/vendor/github.com/hashicorp/go-sockaddr/.gitignore b/vendor/github.com/hashicorp/go-sockaddr/.gitignore new file mode 100644 index 000000000..41720b86e --- /dev/null +++ b/vendor/github.com/hashicorp/go-sockaddr/.gitignore @@ -0,0 +1,26 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe +*.test +*.prof +.cover.out* +coverage.html diff --git a/vendor/github.com/hashicorp/go-sockaddr/GNUmakefile b/vendor/github.com/hashicorp/go-sockaddr/GNUmakefile new file mode 100644 index 000000000..0f3ae1661 --- /dev/null +++ b/vendor/github.com/hashicorp/go-sockaddr/GNUmakefile @@ -0,0 +1,65 @@ +TOOLS= golang.org/x/tools/cover +GOCOVER_TMPFILE?= $(GOCOVER_FILE).tmp +GOCOVER_FILE?= .cover.out +GOCOVERHTML?= coverage.html +FIND=`/usr/bin/which 2> /dev/null gfind find | /usr/bin/grep -v ^no | /usr/bin/head -n 1` +XARGS=`/usr/bin/which 2> /dev/null gxargs xargs | /usr/bin/grep -v ^no | /usr/bin/head -n 1` + +test:: $(GOCOVER_FILE) + @$(MAKE) -C cmd/sockaddr test + +cover:: coverage_report + +$(GOCOVER_FILE):: + @${FIND} . -type d ! -path '*cmd*' ! -path '*.git*' -print0 | ${XARGS} -0 -I % sh -ec "cd % && rm -f $(GOCOVER_TMPFILE) && go test -coverprofile=$(GOCOVER_TMPFILE)" + + @echo 'mode: set' > $(GOCOVER_FILE) + @${FIND} . -type f ! -path '*cmd*' ! -path '*.git*' -name "$(GOCOVER_TMPFILE)" -print0 | ${XARGS} -0 -n1 cat $(GOCOVER_TMPFILE) | grep -v '^mode: ' >> ${PWD}/$(GOCOVER_FILE) + +$(GOCOVERHTML): $(GOCOVER_FILE) + go tool cover -html=$(GOCOVER_FILE) -o $(GOCOVERHTML) + +coverage_report:: $(GOCOVER_FILE) + go tool cover -html=$(GOCOVER_FILE) + +audit_tools:: + @go get -u github.com/golang/lint/golint && echo "Installed golint:" + @go get -u github.com/fzipp/gocyclo && echo "Installed gocyclo:" + @go get -u github.com/remyoudompheng/go-misc/deadcode && echo "Installed deadcode:" + @go get -u github.com/client9/misspell/cmd/misspell && echo "Installed misspell:" + @go get -u github.com/gordonklaus/ineffassign && echo "Installed ineffassign:" + +audit:: + deadcode + go tool vet -all *.go + go tool vet -shadow=true *.go + golint *.go + ineffassign . + gocyclo -over 65 *.go + misspell *.go + +clean:: + rm -f $(GOCOVER_FILE) $(GOCOVERHTML) + +dev:: + @go build + @$(MAKE) -B -C cmd/sockaddr sockaddr + +install:: + @go install + @$(MAKE) -C cmd/sockaddr install + +doc:: + @echo Visit: http://127.0.0.1:6161/pkg/github.com/hashicorp/go-sockaddr/ + godoc -http=:6161 -goroot $GOROOT + +world:: + @set -e; \ + for os in solaris darwin freebsd linux windows android; do \ + for arch in amd64; do \ + printf "Building on %s-%s\n" "$${os}" "$${arch}" ; \ + env GOOS="$${os}" GOARCH="$${arch}" go build -o /dev/null; \ + done; \ + done + + $(MAKE) -C cmd/sockaddr world diff --git a/vendor/github.com/hashicorp/go-sockaddr/LICENSE b/vendor/github.com/hashicorp/go-sockaddr/LICENSE new file mode 100644 index 000000000..a612ad981 --- /dev/null +++ b/vendor/github.com/hashicorp/go-sockaddr/LICENSE @@ -0,0 +1,373 @@ +Mozilla Public License Version 2.0 +================================== + +1. Definitions +-------------- + +1.1. "Contributor" + means each individual or legal entity that creates, contributes to + the creation of, or owns Covered Software. + +1.2. "Contributor Version" + means the combination of the Contributions of others (if any) used + by a Contributor and that particular Contributor's Contribution. + +1.3. "Contribution" + means Covered Software of a particular Contributor. + +1.4. "Covered Software" + means Source Code Form to which the initial Contributor has attached + the notice in Exhibit A, the Executable Form of such Source Code + Form, and Modifications of such Source Code Form, in each case + including portions thereof. + +1.5. "Incompatible With Secondary Licenses" + means + + (a) that the initial Contributor has attached the notice described + in Exhibit B to the Covered Software; or + + (b) that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the + terms of a Secondary License. + +1.6. "Executable Form" + means any form of the work other than Source Code Form. + +1.7. "Larger Work" + means a work that combines Covered Software with other material, in + a separate file or files, that is not Covered Software. + +1.8. "License" + means this document. + +1.9. "Licensable" + means having the right to grant, to the maximum extent possible, + whether at the time of the initial grant or subsequently, any and + all of the rights conveyed by this License. + +1.10. "Modifications" + means any of the following: + + (a) any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered + Software; or + + (b) any new file in Source Code Form that contains any Covered + Software. + +1.11. "Patent Claims" of a Contributor + means any patent claim(s), including without limitation, method, + process, and apparatus claims, in any patent Licensable by such + Contributor that would be infringed, but for the grant of the + License, by the making, using, selling, offering for sale, having + made, import, or transfer of either its Contributions or its + Contributor Version. + +1.12. "Secondary License" + means either the GNU General Public License, Version 2.0, the GNU + Lesser General Public License, Version 2.1, the GNU Affero General + Public License, Version 3.0, or any later versions of those + licenses. + +1.13. "Source Code Form" + means the form of the work preferred for making modifications. + +1.14. "You" (or "Your") + means an individual or a legal entity exercising rights under this + License. For legal entities, "You" includes any entity that + controls, is controlled by, or is under common control with You. For + purposes of this definition, "control" means (a) the power, direct + or indirect, to cause the direction or management of such entity, + whether by contract or otherwise, or (b) ownership of more than + fifty percent (50%) of the outstanding shares or beneficial + ownership of such entity. + +2. License Grants and Conditions +-------------------------------- + +2.1. Grants + +Each Contributor hereby grants You a world-wide, royalty-free, +non-exclusive license: + +(a) under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and + +(b) under Patent Claims of such Contributor to make, use, sell, offer + for sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. + +2.2. Effective Date + +The licenses granted in Section 2.1 with respect to any Contribution +become effective for each Contribution on the date the Contributor first +distributes such Contribution. + +2.3. Limitations on Grant Scope + +The licenses granted in this Section 2 are the only rights granted under +this License. No additional rights or licenses will be implied from the +distribution or licensing of Covered Software under this License. +Notwithstanding Section 2.1(b) above, no patent license is granted by a +Contributor: + +(a) for any code that a Contributor has removed from Covered Software; + or + +(b) for infringements caused by: (i) Your and any other third party's + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + +(c) under Patent Claims infringed by Covered Software in the absence of + its Contributions. + +This License does not grant any rights in the trademarks, service marks, +or logos of any Contributor (except as may be necessary to comply with +the notice requirements in Section 3.4). + +2.4. Subsequent Licenses + +No Contributor makes additional grants as a result of Your choice to +distribute the Covered Software under a subsequent version of this +License (see Section 10.2) or under the terms of a Secondary License (if +permitted under the terms of Section 3.3). + +2.5. Representation + +Each Contributor represents that the Contributor believes its +Contributions are its original creation(s) or it has sufficient rights +to grant the rights to its Contributions conveyed by this License. + +2.6. Fair Use + +This License is not intended to limit any rights You have under +applicable copyright doctrines of fair use, fair dealing, or other +equivalents. + +2.7. Conditions + +Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted +in Section 2.1. + +3. Responsibilities +------------------- + +3.1. Distribution of Source Form + +All distribution of Covered Software in Source Code Form, including any +Modifications that You create or to which You contribute, must be under +the terms of this License. You must inform recipients that the Source +Code Form of the Covered Software is governed by the terms of this +License, and how they can obtain a copy of this License. You may not +attempt to alter or restrict the recipients' rights in the Source Code +Form. + +3.2. Distribution of Executable Form + +If You distribute Covered Software in Executable Form then: + +(a) such Covered Software must also be made available in Source Code + Form, as described in Section 3.1, and You must inform recipients of + the Executable Form how they can obtain a copy of such Source Code + Form by reasonable means in a timely manner, at a charge no more + than the cost of distribution to the recipient; and + +(b) You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter + the recipients' rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + +You may create and distribute a Larger Work under terms of Your choice, +provided that You also comply with the requirements of this License for +the Covered Software. If the Larger Work is a combination of Covered +Software with a work governed by one or more Secondary Licenses, and the +Covered Software is not Incompatible With Secondary Licenses, this +License permits You to additionally distribute such Covered Software +under the terms of such Secondary License(s), so that the recipient of +the Larger Work may, at their option, further distribute the Covered +Software under the terms of either this License or such Secondary +License(s). + +3.4. Notices + +You may not remove or alter the substance of any license notices +(including copyright notices, patent notices, disclaimers of warranty, +or limitations of liability) contained within the Source Code Form of +the Covered Software, except that You may alter any license notices to +the extent required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + +You may choose to offer, and to charge a fee for, warranty, support, +indemnity or liability obligations to one or more recipients of Covered +Software. However, You may do so only on Your own behalf, and not on +behalf of any Contributor. You must make it absolutely clear that any +such warranty, support, indemnity, or liability obligation is offered by +You alone, and You hereby agree to indemnify every Contributor for any +liability incurred by such Contributor as a result of warranty, support, +indemnity or liability terms You offer. You may include additional +disclaimers of warranty and limitations of liability specific to any +jurisdiction. + +4. Inability to Comply Due to Statute or Regulation +--------------------------------------------------- + +If it is impossible for You to comply with any of the terms of this +License with respect to some or all of the Covered Software due to +statute, judicial order, or regulation then You must: (a) comply with +the terms of this License to the maximum extent possible; and (b) +describe the limitations and the code they affect. Such description must +be placed in a text file included with all distributions of the Covered +Software under this License. Except to the extent prohibited by statute +or regulation, such description must be sufficiently detailed for a +recipient of ordinary skill to be able to understand it. + +5. Termination +-------------- + +5.1. The rights granted under this License will terminate automatically +if You fail to comply with any of its terms. However, if You become +compliant, then the rights granted under this License from a particular +Contributor are reinstated (a) provisionally, unless and until such +Contributor explicitly and finally terminates Your grants, and (b) on an +ongoing basis, if such Contributor fails to notify You of the +non-compliance by some reasonable means prior to 60 days after You have +come back into compliance. Moreover, Your grants from a particular +Contributor are reinstated on an ongoing basis if such Contributor +notifies You of the non-compliance by some reasonable means, this is the +first time You have received notice of non-compliance with this License +from such Contributor, and You become compliant prior to 30 days after +Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent +infringement claim (excluding declaratory judgment actions, +counter-claims, and cross-claims) alleging that a Contributor Version +directly or indirectly infringes any patent, then the rights granted to +You by any and all Contributors for the Covered Software under Section +2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all +end user license agreements (excluding distributors and resellers) which +have been validly granted by You or Your distributors under this License +prior to termination shall survive termination. + +************************************************************************ +* * +* 6. Disclaimer of Warranty * +* ------------------------- * +* * +* Covered Software is provided under this License on an "as is" * +* basis, without warranty of any kind, either expressed, implied, or * +* statutory, including, without limitation, warranties that the * +* Covered Software is free of defects, merchantable, fit for a * +* particular purpose or non-infringing. The entire risk as to the * +* quality and performance of the Covered Software is with You. * +* Should any Covered Software prove defective in any respect, You * +* (not any Contributor) assume the cost of any necessary servicing, * +* repair, or correction. This disclaimer of warranty constitutes an * +* essential part of this License. No use of any Covered Software is * +* authorized under this License except under this disclaimer. * +* * +************************************************************************ + +************************************************************************ +* * +* 7. Limitation of Liability * +* -------------------------- * +* * +* Under no circumstances and under no legal theory, whether tort * +* (including negligence), contract, or otherwise, shall any * +* Contributor, or anyone who distributes Covered Software as * +* permitted above, be liable to You for any direct, indirect, * +* special, incidental, or consequential damages of any character * +* including, without limitation, damages for lost profits, loss of * +* goodwill, work stoppage, computer failure or malfunction, or any * +* and all other commercial damages or losses, even if such party * +* shall have been informed of the possibility of such damages. This * +* limitation of liability shall not apply to liability for death or * +* personal injury resulting from such party's negligence to the * +* extent applicable law prohibits such limitation. Some * +* jurisdictions do not allow the exclusion or limitation of * +* incidental or consequential damages, so this exclusion and * +* limitation may not apply to You. * +* * +************************************************************************ + +8. Litigation +------------- + +Any litigation relating to this License may be brought only in the +courts of a jurisdiction where the defendant maintains its principal +place of business and such litigation shall be governed by laws of that +jurisdiction, without reference to its conflict-of-law provisions. +Nothing in this Section shall prevent a party's ability to bring +cross-claims or counter-claims. + +9. Miscellaneous +---------------- + +This License represents the complete agreement concerning the subject +matter hereof. If any provision of this License is held to be +unenforceable, such provision shall be reformed only to the extent +necessary to make it enforceable. Any law or regulation which provides +that the language of a contract shall be construed against the drafter +shall not be used to construe this License against a Contributor. + +10. Versions of the License +--------------------------- + +10.1. New Versions + +Mozilla Foundation is the license steward. Except as provided in Section +10.3, no one other than the license steward has the right to modify or +publish new versions of this License. Each version will be given a +distinguishing version number. + +10.2. Effect of New Versions + +You may distribute the Covered Software under the terms of the version +of the License under which You originally received the Covered Software, +or under the terms of any subsequent version published by the license +steward. + +10.3. Modified Versions + +If you create software not governed by this License, and you want to +create a new license for such software, you may create and use a +modified version of this License if you rename the license and remove +any references to the name of the license steward (except to note that +such modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary +Licenses + +If You choose to distribute Source Code Form that is Incompatible With +Secondary Licenses under the terms of this version of the License, the +notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice +------------------------------------------- + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular +file, then You may include the notice in a location (such as a LICENSE +file in a relevant directory) where a recipient would be likely to look +for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - "Incompatible With Secondary Licenses" Notice +--------------------------------------------------------- + + This Source Code Form is "Incompatible With Secondary Licenses", as + defined by the Mozilla Public License, v. 2.0. diff --git a/vendor/github.com/hashicorp/go-sockaddr/README.md b/vendor/github.com/hashicorp/go-sockaddr/README.md new file mode 100644 index 000000000..a2e170ae0 --- /dev/null +++ b/vendor/github.com/hashicorp/go-sockaddr/README.md @@ -0,0 +1,118 @@ +# go-sockaddr + +## `sockaddr` Library + +Socket address convenience functions for Go. `go-sockaddr` is a convenience +library that makes doing the right thing with IP addresses easy. `go-sockaddr` +is loosely modeled after the UNIX `sockaddr_t` and creates a union of the family +of `sockaddr_t` types (see below for an ascii diagram). Library documentation +is available +at +[https://godoc.org/github.com/hashicorp/go-sockaddr](https://godoc.org/github.com/hashicorp/go-sockaddr). +The primary intent of the library was to make it possible to define heuristics +for selecting the correct IP addresses when a configuration is evaluated at +runtime. See +the +[docs](https://godoc.org/github.com/hashicorp/go-sockaddr), +[`template` package](https://godoc.org/github.com/hashicorp/go-sockaddr/template), +tests, +and +[CLI utility](https://github.com/hashicorp/go-sockaddr/tree/master/cmd/sockaddr) +for details and hints as to how to use this library. + +For example, with this library it is possible to find an IP address that: + +* is attached to a default route + ([`GetDefaultInterfaces()`](https://godoc.org/github.com/hashicorp/go-sockaddr#GetDefaultInterfaces)) +* is contained within a CIDR block ([`IfByNetwork()`](https://godoc.org/github.com/hashicorp/go-sockaddr#IfByNetwork)) +* is an RFC1918 address + ([`IfByRFC("1918")`](https://godoc.org/github.com/hashicorp/go-sockaddr#IfByRFC)) +* is ordered + ([`OrderedIfAddrBy(args)`](https://godoc.org/github.com/hashicorp/go-sockaddr#OrderedIfAddrBy) where + `args` includes, but is not limited + to, + [`AscIfType`](https://godoc.org/github.com/hashicorp/go-sockaddr#AscIfType), + [`AscNetworkSize`](https://godoc.org/github.com/hashicorp/go-sockaddr#AscNetworkSize)) +* excludes all IPv6 addresses + ([`IfByType("^(IPv4)$")`](https://godoc.org/github.com/hashicorp/go-sockaddr#IfByType)) +* is larger than a `/32` + ([`IfByMaskSize(32)`](https://godoc.org/github.com/hashicorp/go-sockaddr#IfByMaskSize)) +* is not on a `down` interface + ([`ExcludeIfs("flags", "down")`](https://godoc.org/github.com/hashicorp/go-sockaddr#ExcludeIfs)) +* preferences an IPv6 address over an IPv4 address + ([`SortIfByType()`](https://godoc.org/github.com/hashicorp/go-sockaddr#SortIfByType) + + [`ReverseIfAddrs()`](https://godoc.org/github.com/hashicorp/go-sockaddr#ReverseIfAddrs)); and +* excludes any IP in RFC6890 address + ([`IfByRFC("6890")`](https://godoc.org/github.com/hashicorp/go-sockaddr#IfByRFC)) + +Or any combination or variation therein. + +There are also a few simple helper functions such as `GetPublicIP` and +`GetPrivateIP` which both return strings and select the first public or private +IP address on the default interface, respectively. Similarly, there is also a +helper function called `GetInterfaceIP` which returns the first usable IP +address on the named interface. + +## `sockaddr` CLI + +Given the possible complexity of the `sockaddr` library, there is a CLI utility +that accompanies the library, also +called +[`sockaddr`](https://github.com/hashicorp/go-sockaddr/tree/master/cmd/sockaddr). +The +[`sockaddr`](https://github.com/hashicorp/go-sockaddr/tree/master/cmd/sockaddr) +utility exposes nearly all of the functionality of the library and can be used +either as an administrative tool or testing tool. To install +the +[`sockaddr`](https://github.com/hashicorp/go-sockaddr/tree/master/cmd/sockaddr), +run: + +```text +$ go get -u github.com/hashicorp/go-sockaddr/cmd/sockaddr +``` + +If you're familiar with UNIX's `sockaddr` struct's, the following diagram +mapping the C `sockaddr` (top) to `go-sockaddr` structs (bottom) and +interfaces will be helpful: + +``` ++-------------------------------------------------------+ +| | +| sockaddr | +| SockAddr | +| | +| +--------------+ +----------------------------------+ | +| | sockaddr_un | | | | +| | SockAddrUnix | | sockaddr_in{,6} | | +| +--------------+ | IPAddr | | +| | | | +| | +-------------+ +--------------+ | | +| | | sockaddr_in | | sockaddr_in6 | | | +| | | IPv4Addr | | IPv6Addr | | | +| | +-------------+ +--------------+ | | +| | | | +| +----------------------------------+ | +| | ++-------------------------------------------------------+ +``` + +## Inspiration and Design + +There were many subtle inspirations that led to this design, but the most direct +inspiration for the filtering syntax was +OpenBSD's +[`pf.conf(5)`](https://www.freebsd.org/cgi/man.cgi?query=pf.conf&apropos=0&sektion=0&arch=default&format=html#PARAMETERS) firewall +syntax that lets you select the first IP address on a given named interface. +The original problem stemmed from: + +* needing to create immutable images using [Packer](https://www.packer.io) that + ran the [Consul](https://www.consul.io) process (Consul can only use one IP + address at a time); +* images that may or may not have multiple interfaces or IP addresses at + runtime; and +* we didn't want to rely on configuration management to render out the correct + IP address if the VM image was being used in an auto-scaling group. + +Instead we needed some way to codify a heuristic that would correctly select the +right IP address but the input parameters were not known when the image was +created. diff --git a/vendor/github.com/hashicorp/go-sockaddr/doc.go b/vendor/github.com/hashicorp/go-sockaddr/doc.go new file mode 100644 index 000000000..90671deb5 --- /dev/null +++ b/vendor/github.com/hashicorp/go-sockaddr/doc.go @@ -0,0 +1,5 @@ +/* +Package sockaddr is a Go implementation of the UNIX socket family data types and +related helper functions. +*/ +package sockaddr diff --git a/vendor/github.com/hashicorp/go-sockaddr/ifaddr.go b/vendor/github.com/hashicorp/go-sockaddr/ifaddr.go new file mode 100644 index 000000000..0811b2759 --- /dev/null +++ b/vendor/github.com/hashicorp/go-sockaddr/ifaddr.go @@ -0,0 +1,254 @@ +package sockaddr + +import "strings" + +// ifAddrAttrMap is a map of the IfAddr type-specific attributes. +var ifAddrAttrMap map[AttrName]func(IfAddr) string +var ifAddrAttrs []AttrName + +func init() { + ifAddrAttrInit() +} + +// GetPrivateIP returns a string with a single IP address that is part of RFC +// 6890 and has a default route. If the system can't determine its IP address +// or find an RFC 6890 IP address, an empty string will be returned instead. +// This function is the `eval` equivalent of: +// +// ``` +// $ sockaddr eval -r '{{GetPrivateInterfaces | attr "address"}}' +/// ``` +func GetPrivateIP() (string, error) { + privateIfs, err := GetPrivateInterfaces() + if err != nil { + return "", err + } + if len(privateIfs) < 1 { + return "", nil + } + + ifAddr := privateIfs[0] + ip := *ToIPAddr(ifAddr.SockAddr) + return ip.NetIP().String(), nil +} + +// GetPrivateIPs returns a string with all IP addresses that are part of RFC +// 6890 (regardless of whether or not there is a default route, unlike +// GetPublicIP). If the system can't find any RFC 6890 IP addresses, an empty +// string will be returned instead. This function is the `eval` equivalent of: +// +// ``` +// $ sockaddr eval -r '{{GetAllInterfaces | include "RFC" "6890" | join "address" " "}}' +/// ``` +func GetPrivateIPs() (string, error) { + ifAddrs, err := GetAllInterfaces() + if err != nil { + return "", err + } else if len(ifAddrs) < 1 { + return "", nil + } + + ifAddrs, _ = FilterIfByType(ifAddrs, TypeIP) + if len(ifAddrs) == 0 { + return "", nil + } + + OrderedIfAddrBy(AscIfType, AscIfNetworkSize).Sort(ifAddrs) + + ifAddrs, _, err = IfByRFC("6890", ifAddrs) + if err != nil { + return "", err + } else if len(ifAddrs) == 0 { + return "", nil + } + + _, ifAddrs, err = IfByRFC(ForwardingBlacklistRFC, ifAddrs) + if err != nil { + return "", err + } else if len(ifAddrs) == 0 { + return "", nil + } + + ips := make([]string, 0, len(ifAddrs)) + for _, ifAddr := range ifAddrs { + ip := *ToIPAddr(ifAddr.SockAddr) + s := ip.NetIP().String() + ips = append(ips, s) + } + + return strings.Join(ips, " "), nil +} + +// GetPublicIP returns a string with a single IP address that is NOT part of RFC +// 6890 and has a default route. If the system can't determine its IP address +// or find a non RFC 6890 IP address, an empty string will be returned instead. +// This function is the `eval` equivalent of: +// +// ``` +// $ sockaddr eval -r '{{GetPublicInterfaces | attr "address"}}' +/// ``` +func GetPublicIP() (string, error) { + publicIfs, err := GetPublicInterfaces() + if err != nil { + return "", err + } else if len(publicIfs) < 1 { + return "", nil + } + + ifAddr := publicIfs[0] + ip := *ToIPAddr(ifAddr.SockAddr) + return ip.NetIP().String(), nil +} + +// GetPublicIPs returns a string with all IP addresses that are NOT part of RFC +// 6890 (regardless of whether or not there is a default route, unlike +// GetPublicIP). If the system can't find any non RFC 6890 IP addresses, an +// empty string will be returned instead. This function is the `eval` +// equivalent of: +// +// ``` +// $ sockaddr eval -r '{{GetAllInterfaces | exclude "RFC" "6890" | join "address" " "}}' +/// ``` +func GetPublicIPs() (string, error) { + ifAddrs, err := GetAllInterfaces() + if err != nil { + return "", err + } else if len(ifAddrs) < 1 { + return "", nil + } + + ifAddrs, _ = FilterIfByType(ifAddrs, TypeIP) + if len(ifAddrs) == 0 { + return "", nil + } + + OrderedIfAddrBy(AscIfType, AscIfNetworkSize).Sort(ifAddrs) + + _, ifAddrs, err = IfByRFC("6890", ifAddrs) + if err != nil { + return "", err + } else if len(ifAddrs) == 0 { + return "", nil + } + + ips := make([]string, 0, len(ifAddrs)) + for _, ifAddr := range ifAddrs { + ip := *ToIPAddr(ifAddr.SockAddr) + s := ip.NetIP().String() + ips = append(ips, s) + } + + return strings.Join(ips, " "), nil +} + +// GetInterfaceIP returns a string with a single IP address sorted by the size +// of the network (i.e. IP addresses with a smaller netmask, larger network +// size, are sorted first). This function is the `eval` equivalent of: +// +// ``` +// $ sockaddr eval -r '{{GetAllInterfaces | include "name" <> | sort "type,size" | include "flag" "forwardable" | attr "address" }}' +/// ``` +func GetInterfaceIP(namedIfRE string) (string, error) { + ifAddrs, err := GetAllInterfaces() + if err != nil { + return "", err + } + + ifAddrs, _, err = IfByName(namedIfRE, ifAddrs) + if err != nil { + return "", err + } + + ifAddrs, _, err = IfByFlag("forwardable", ifAddrs) + if err != nil { + return "", err + } + + ifAddrs, err = SortIfBy("+type,+size", ifAddrs) + if err != nil { + return "", err + } + + if len(ifAddrs) == 0 { + return "", err + } + + ip := ToIPAddr(ifAddrs[0].SockAddr) + if ip == nil { + return "", err + } + + return IPAddrAttr(*ip, "address"), nil +} + +// GetInterfaceIPs returns a string with all IPs, sorted by the size of the +// network (i.e. IP addresses with a smaller netmask, larger network size, are +// sorted first), on a named interface. This function is the `eval` equivalent +// of: +// +// ``` +// $ sockaddr eval -r '{{GetAllInterfaces | include "name" <> | sort "type,size" | join "address" " "}}' +/// ``` +func GetInterfaceIPs(namedIfRE string) (string, error) { + ifAddrs, err := GetAllInterfaces() + if err != nil { + return "", err + } + + ifAddrs, _, err = IfByName(namedIfRE, ifAddrs) + if err != nil { + return "", err + } + + ifAddrs, err = SortIfBy("+type,+size", ifAddrs) + if err != nil { + return "", err + } + + if len(ifAddrs) == 0 { + return "", err + } + + ips := make([]string, 0, len(ifAddrs)) + for _, ifAddr := range ifAddrs { + ip := *ToIPAddr(ifAddr.SockAddr) + s := ip.NetIP().String() + ips = append(ips, s) + } + + return strings.Join(ips, " "), nil +} + +// IfAddrAttrs returns a list of attributes supported by the IfAddr type +func IfAddrAttrs() []AttrName { + return ifAddrAttrs +} + +// IfAddrAttr returns a string representation of an attribute for the given +// IfAddr. +func IfAddrAttr(ifAddr IfAddr, attrName AttrName) string { + fn, found := ifAddrAttrMap[attrName] + if !found { + return "" + } + + return fn(ifAddr) +} + +// ifAddrAttrInit is called once at init() +func ifAddrAttrInit() { + // Sorted for human readability + ifAddrAttrs = []AttrName{ + "flags", + "name", + } + + ifAddrAttrMap = map[AttrName]func(ifAddr IfAddr) string{ + "flags": func(ifAddr IfAddr) string { + return ifAddr.Interface.Flags.String() + }, + "name": func(ifAddr IfAddr) string { + return ifAddr.Interface.Name + }, + } +} diff --git a/vendor/github.com/hashicorp/go-sockaddr/ifaddrs.go b/vendor/github.com/hashicorp/go-sockaddr/ifaddrs.go new file mode 100644 index 000000000..80f61bef6 --- /dev/null +++ b/vendor/github.com/hashicorp/go-sockaddr/ifaddrs.go @@ -0,0 +1,1304 @@ +package sockaddr + +import ( + "encoding/binary" + "errors" + "fmt" + "math/big" + "net" + "regexp" + "sort" + "strconv" + "strings" +) + +var ( + // Centralize all regexps and regexp.Copy() where necessary. + signRE *regexp.Regexp = regexp.MustCompile(`^[\s]*[+-]`) + whitespaceRE *regexp.Regexp = regexp.MustCompile(`[\s]+`) + ifNameRE *regexp.Regexp = regexp.MustCompile(`^(?:Ethernet|Wireless LAN) adapter ([^:]+):`) + ipAddrRE *regexp.Regexp = regexp.MustCompile(`^ IPv[46] Address\. \. \. \. \. \. \. \. \. \. \. : ([^\s]+)`) +) + +// IfAddrs is a slice of IfAddr +type IfAddrs []IfAddr + +func (ifs IfAddrs) Len() int { return len(ifs) } + +// CmpIfFunc is the function signature that must be met to be used in the +// OrderedIfAddrBy multiIfAddrSorter +type CmpIfAddrFunc func(p1, p2 *IfAddr) int + +// multiIfAddrSorter implements the Sort interface, sorting the IfAddrs within. +type multiIfAddrSorter struct { + ifAddrs IfAddrs + cmp []CmpIfAddrFunc +} + +// Sort sorts the argument slice according to the Cmp functions passed to +// OrderedIfAddrBy. +func (ms *multiIfAddrSorter) Sort(ifAddrs IfAddrs) { + ms.ifAddrs = ifAddrs + sort.Sort(ms) +} + +// OrderedIfAddrBy sorts SockAddr by the list of sort function pointers. +func OrderedIfAddrBy(cmpFuncs ...CmpIfAddrFunc) *multiIfAddrSorter { + return &multiIfAddrSorter{ + cmp: cmpFuncs, + } +} + +// Len is part of sort.Interface. +func (ms *multiIfAddrSorter) Len() int { + return len(ms.ifAddrs) +} + +// Less is part of sort.Interface. It is implemented by looping along the Cmp() +// functions until it finds a comparison that is either less than or greater +// than. A return value of 0 defers sorting to the next function in the +// multisorter (which means the results of sorting may leave the resutls in a +// non-deterministic order). +func (ms *multiIfAddrSorter) Less(i, j int) bool { + p, q := &ms.ifAddrs[i], &ms.ifAddrs[j] + // Try all but the last comparison. + var k int + for k = 0; k < len(ms.cmp)-1; k++ { + cmp := ms.cmp[k] + x := cmp(p, q) + switch x { + case -1: + // p < q, so we have a decision. + return true + case 1: + // p > q, so we have a decision. + return false + } + // p == q; try the next comparison. + } + // All comparisons to here said "equal", so just return whatever the + // final comparison reports. + switch ms.cmp[k](p, q) { + case -1: + return true + case 1: + return false + default: + // Still a tie! Now what? + return false + panic("undefined sort order for remaining items in the list") + } +} + +// Swap is part of sort.Interface. +func (ms *multiIfAddrSorter) Swap(i, j int) { + ms.ifAddrs[i], ms.ifAddrs[j] = ms.ifAddrs[j], ms.ifAddrs[i] +} + +// AscIfAddress is a sorting function to sort IfAddrs by their respective +// address type. Non-equal types are deferred in the sort. +func AscIfAddress(p1Ptr, p2Ptr *IfAddr) int { + return AscAddress(&p1Ptr.SockAddr, &p2Ptr.SockAddr) +} + +// AscIfDefault is a sorting function to sort IfAddrs by whether or not they +// have a default route or not. Non-equal types are deferred in the sort. +// +// FIXME: This is a particularly expensive sorting operation because of the +// non-memoized calls to NewRouteInfo(). In an ideal world the routeInfo data +// once at the start of the sort and pass it along as a context or by wrapping +// the IfAddr type with this information (this would also solve the inability to +// return errors and the possibility of failing silently). Fortunately, +// N*log(N) where N = 3 is only ~6.2 invocations. Not ideal, but not worth +// optimizing today. The common case is this gets called once or twice. +// Patches welcome. +func AscIfDefault(p1Ptr, p2Ptr *IfAddr) int { + ri, err := NewRouteInfo() + if err != nil { + return sortDeferDecision + } + + defaultIfName, err := ri.GetDefaultInterfaceName() + if err != nil { + return sortDeferDecision + } + + switch { + case p1Ptr.Interface.Name == defaultIfName && p2Ptr.Interface.Name == defaultIfName: + return sortDeferDecision + case p1Ptr.Interface.Name == defaultIfName: + return sortReceiverBeforeArg + case p2Ptr.Interface.Name == defaultIfName: + return sortArgBeforeReceiver + default: + return sortDeferDecision + } +} + +// AscIfName is a sorting function to sort IfAddrs by their interface names. +func AscIfName(p1Ptr, p2Ptr *IfAddr) int { + return strings.Compare(p1Ptr.Name, p2Ptr.Name) +} + +// AscIfNetworkSize is a sorting function to sort IfAddrs by their respective +// network mask size. +func AscIfNetworkSize(p1Ptr, p2Ptr *IfAddr) int { + return AscNetworkSize(&p1Ptr.SockAddr, &p2Ptr.SockAddr) +} + +// AscIfPort is a sorting function to sort IfAddrs by their respective +// port type. Non-equal types are deferred in the sort. +func AscIfPort(p1Ptr, p2Ptr *IfAddr) int { + return AscPort(&p1Ptr.SockAddr, &p2Ptr.SockAddr) +} + +// AscIfPrivate is a sorting function to sort IfAddrs by "private" values before +// "public" values. Both IPv4 and IPv6 are compared against RFC6890 (RFC6890 +// includes, and is not limited to, RFC1918 and RFC6598 for IPv4, and IPv6 +// includes RFC4193). +func AscIfPrivate(p1Ptr, p2Ptr *IfAddr) int { + return AscPrivate(&p1Ptr.SockAddr, &p2Ptr.SockAddr) +} + +// AscIfType is a sorting function to sort IfAddrs by their respective address +// type. Non-equal types are deferred in the sort. +func AscIfType(p1Ptr, p2Ptr *IfAddr) int { + return AscType(&p1Ptr.SockAddr, &p2Ptr.SockAddr) +} + +// DescIfAddress is identical to AscIfAddress but reverse ordered. +func DescIfAddress(p1Ptr, p2Ptr *IfAddr) int { + return -1 * AscAddress(&p1Ptr.SockAddr, &p2Ptr.SockAddr) +} + +// DescIfDefault is identical to AscIfDefault but reverse ordered. +func DescIfDefault(p1Ptr, p2Ptr *IfAddr) int { + return -1 * AscIfDefault(p1Ptr, p2Ptr) +} + +// DescIfName is identical to AscIfName but reverse ordered. +func DescIfName(p1Ptr, p2Ptr *IfAddr) int { + return -1 * strings.Compare(p1Ptr.Name, p2Ptr.Name) +} + +// DescIfNetworkSize is identical to AscIfNetworkSize but reverse ordered. +func DescIfNetworkSize(p1Ptr, p2Ptr *IfAddr) int { + return -1 * AscNetworkSize(&p1Ptr.SockAddr, &p2Ptr.SockAddr) +} + +// DescIfPort is identical to AscIfPort but reverse ordered. +func DescIfPort(p1Ptr, p2Ptr *IfAddr) int { + return -1 * AscPort(&p1Ptr.SockAddr, &p2Ptr.SockAddr) +} + +// DescIfPrivate is identical to AscIfPrivate but reverse ordered. +func DescIfPrivate(p1Ptr, p2Ptr *IfAddr) int { + return -1 * AscPrivate(&p1Ptr.SockAddr, &p2Ptr.SockAddr) +} + +// DescIfType is identical to AscIfType but reverse ordered. +func DescIfType(p1Ptr, p2Ptr *IfAddr) int { + return -1 * AscType(&p1Ptr.SockAddr, &p2Ptr.SockAddr) +} + +// FilterIfByType filters IfAddrs and returns a list of the matching type +func FilterIfByType(ifAddrs IfAddrs, type_ SockAddrType) (matchedIfs, excludedIfs IfAddrs) { + excludedIfs = make(IfAddrs, 0, len(ifAddrs)) + matchedIfs = make(IfAddrs, 0, len(ifAddrs)) + + for _, ifAddr := range ifAddrs { + if ifAddr.SockAddr.Type()&type_ != 0 { + matchedIfs = append(matchedIfs, ifAddr) + } else { + excludedIfs = append(excludedIfs, ifAddr) + } + } + return matchedIfs, excludedIfs +} + +// IfAttr forwards the selector to IfAttr.Attr() for resolution. If there is +// more than one IfAddr, only the first IfAddr is used. +func IfAttr(selectorName string, ifAddr IfAddr) (string, error) { + attrName := AttrName(strings.ToLower(selectorName)) + attrVal, err := ifAddr.Attr(attrName) + return attrVal, err +} + +// IfAttrs forwards the selector to IfAttrs.Attr() for resolution. If there is +// more than one IfAddr, only the first IfAddr is used. +func IfAttrs(selectorName string, ifAddrs IfAddrs) (string, error) { + if len(ifAddrs) == 0 { + return "", nil + } + + attrName := AttrName(strings.ToLower(selectorName)) + attrVal, err := ifAddrs[0].Attr(attrName) + return attrVal, err +} + +// GetAllInterfaces iterates over all available network interfaces and finds all +// available IP addresses on each interface and converts them to +// sockaddr.IPAddrs, and returning the result as an array of IfAddr. +func GetAllInterfaces() (IfAddrs, error) { + ifs, err := net.Interfaces() + if err != nil { + return nil, err + } + + ifAddrs := make(IfAddrs, 0, len(ifs)) + for _, intf := range ifs { + addrs, err := intf.Addrs() + if err != nil { + return nil, err + } + + for _, addr := range addrs { + var ipAddr IPAddr + ipAddr, err = NewIPAddr(addr.String()) + if err != nil { + return IfAddrs{}, fmt.Errorf("unable to create an IP address from %q", addr.String()) + } + + ifAddr := IfAddr{ + SockAddr: ipAddr, + Interface: intf, + } + ifAddrs = append(ifAddrs, ifAddr) + } + } + + return ifAddrs, nil +} + +// GetDefaultInterfaces returns IfAddrs of the addresses attached to the default +// route. +func GetDefaultInterfaces() (IfAddrs, error) { + ri, err := NewRouteInfo() + if err != nil { + return nil, err + } + + defaultIfName, err := ri.GetDefaultInterfaceName() + if err != nil { + return nil, err + } + + var defaultIfs, ifAddrs IfAddrs + ifAddrs, err = GetAllInterfaces() + for _, ifAddr := range ifAddrs { + if ifAddr.Name == defaultIfName { + defaultIfs = append(defaultIfs, ifAddr) + } + } + + return defaultIfs, nil +} + +// GetPrivateInterfaces returns an IfAddrs that are part of RFC 6890 and have a +// default route. If the system can't determine its IP address or find an RFC +// 6890 IP address, an empty IfAddrs will be returned instead. This function is +// the `eval` equivalent of: +// +// ``` +// $ sockaddr eval -r '{{GetAllInterfaces | include "type" "ip" | include "flags" "forwardable" | include "flags" "up" | sort "default,type,size" | include "RFC" "6890" }}' +/// ``` +func GetPrivateInterfaces() (IfAddrs, error) { + privateIfs, err := GetAllInterfaces() + if err != nil { + return IfAddrs{}, err + } + if len(privateIfs) == 0 { + return IfAddrs{}, nil + } + + privateIfs, _ = FilterIfByType(privateIfs, TypeIP) + if len(privateIfs) == 0 { + return IfAddrs{}, nil + } + + privateIfs, _, err = IfByFlag("forwardable", privateIfs) + if err != nil { + return IfAddrs{}, err + } + + privateIfs, _, err = IfByFlag("up", privateIfs) + if err != nil { + return IfAddrs{}, err + } + + if len(privateIfs) == 0 { + return IfAddrs{}, nil + } + + OrderedIfAddrBy(AscIfDefault, AscIfType, AscIfNetworkSize).Sort(privateIfs) + + privateIfs, _, err = IfByRFC("6890", privateIfs) + if err != nil { + return IfAddrs{}, err + } else if len(privateIfs) == 0 { + return IfAddrs{}, nil + } + + return privateIfs, nil +} + +// GetPublicInterfaces returns an IfAddrs that are NOT part of RFC 6890 and has a +// default route. If the system can't determine its IP address or find a non +// RFC 6890 IP address, an empty IfAddrs will be returned instead. This +// function is the `eval` equivalent of: +// +// ``` +// $ sockaddr eval -r '{{GetAllInterfaces | include "type" "ip" | include "flags" "forwardable" | include "flags" "up" | sort "default,type,size" | exclude "RFC" "6890" }}' +/// ``` +func GetPublicInterfaces() (IfAddrs, error) { + publicIfs, err := GetAllInterfaces() + if err != nil { + return IfAddrs{}, err + } + if len(publicIfs) == 0 { + return IfAddrs{}, nil + } + + publicIfs, _ = FilterIfByType(publicIfs, TypeIP) + if len(publicIfs) == 0 { + return IfAddrs{}, nil + } + + publicIfs, _, err = IfByFlag("forwardable", publicIfs) + if err != nil { + return IfAddrs{}, err + } + + publicIfs, _, err = IfByFlag("up", publicIfs) + if err != nil { + return IfAddrs{}, err + } + + if len(publicIfs) == 0 { + return IfAddrs{}, nil + } + + OrderedIfAddrBy(AscIfDefault, AscIfType, AscIfNetworkSize).Sort(publicIfs) + + _, publicIfs, err = IfByRFC("6890", publicIfs) + if err != nil { + return IfAddrs{}, err + } else if len(publicIfs) == 0 { + return IfAddrs{}, nil + } + + return publicIfs, nil +} + +// IfByAddress returns a list of matched and non-matched IfAddrs, or an error if +// the regexp fails to compile. +func IfByAddress(inputRe string, ifAddrs IfAddrs) (matched, remainder IfAddrs, err error) { + re, err := regexp.Compile(inputRe) + if err != nil { + return nil, nil, fmt.Errorf("Unable to compile address regexp %+q: %v", inputRe, err) + } + + matchedAddrs := make(IfAddrs, 0, len(ifAddrs)) + excludedAddrs := make(IfAddrs, 0, len(ifAddrs)) + for _, addr := range ifAddrs { + if re.MatchString(addr.SockAddr.String()) { + matchedAddrs = append(matchedAddrs, addr) + } else { + excludedAddrs = append(excludedAddrs, addr) + } + } + + return matchedAddrs, excludedAddrs, nil +} + +// IfByName returns a list of matched and non-matched IfAddrs, or an error if +// the regexp fails to compile. +func IfByName(inputRe string, ifAddrs IfAddrs) (matched, remainder IfAddrs, err error) { + re, err := regexp.Compile(inputRe) + if err != nil { + return nil, nil, fmt.Errorf("Unable to compile name regexp %+q: %v", inputRe, err) + } + + matchedAddrs := make(IfAddrs, 0, len(ifAddrs)) + excludedAddrs := make(IfAddrs, 0, len(ifAddrs)) + for _, addr := range ifAddrs { + if re.MatchString(addr.Name) { + matchedAddrs = append(matchedAddrs, addr) + } else { + excludedAddrs = append(excludedAddrs, addr) + } + } + + return matchedAddrs, excludedAddrs, nil +} + +// IfByPort returns a list of matched and non-matched IfAddrs, or an error if +// the regexp fails to compile. +func IfByPort(inputRe string, ifAddrs IfAddrs) (matchedIfs, excludedIfs IfAddrs, err error) { + re, err := regexp.Compile(inputRe) + if err != nil { + return nil, nil, fmt.Errorf("Unable to compile port regexp %+q: %v", inputRe, err) + } + + ipIfs, nonIfs := FilterIfByType(ifAddrs, TypeIP) + matchedIfs = make(IfAddrs, 0, len(ipIfs)) + excludedIfs = append(IfAddrs(nil), nonIfs...) + for _, addr := range ipIfs { + ipAddr := ToIPAddr(addr.SockAddr) + if ipAddr == nil { + continue + } + + port := strconv.FormatInt(int64((*ipAddr).IPPort()), 10) + if re.MatchString(port) { + matchedIfs = append(matchedIfs, addr) + } else { + excludedIfs = append(excludedIfs, addr) + } + } + + return matchedIfs, excludedIfs, nil +} + +// IfByRFC returns a list of matched and non-matched IfAddrs that contain the +// relevant RFC-specified traits. +func IfByRFC(selectorParam string, ifAddrs IfAddrs) (matched, remainder IfAddrs, err error) { + inputRFC, err := strconv.ParseUint(selectorParam, 10, 64) + if err != nil { + return IfAddrs{}, IfAddrs{}, fmt.Errorf("unable to parse RFC number %q: %v", selectorParam, err) + } + + matchedIfAddrs := make(IfAddrs, 0, len(ifAddrs)) + remainingIfAddrs := make(IfAddrs, 0, len(ifAddrs)) + + rfcNetMap := KnownRFCs() + rfcNets, ok := rfcNetMap[uint(inputRFC)] + if !ok { + return nil, nil, fmt.Errorf("unsupported RFC %d", inputRFC) + } + + for _, ifAddr := range ifAddrs { + var contained bool + for _, rfcNet := range rfcNets { + if rfcNet.Contains(ifAddr.SockAddr) { + matchedIfAddrs = append(matchedIfAddrs, ifAddr) + contained = true + break + } + } + if !contained { + remainingIfAddrs = append(remainingIfAddrs, ifAddr) + } + } + + return matchedIfAddrs, remainingIfAddrs, nil +} + +// IfByRFCs returns a list of matched and non-matched IfAddrs that contain the +// relevant RFC-specified traits. Multiple RFCs can be specified and separated +// by the `|` symbol. No protection is taken to ensure an IfAddr does not end +// up in both the included and excluded list. +func IfByRFCs(selectorParam string, ifAddrs IfAddrs) (matched, remainder IfAddrs, err error) { + var includedIfs, excludedIfs IfAddrs + for _, rfcStr := range strings.Split(selectorParam, "|") { + includedRFCIfs, excludedRFCIfs, err := IfByRFC(rfcStr, ifAddrs) + if err != nil { + return IfAddrs{}, IfAddrs{}, fmt.Errorf("unable to lookup RFC number %q: %v", rfcStr, err) + } + includedIfs = append(includedIfs, includedRFCIfs...) + excludedIfs = append(excludedIfs, excludedRFCIfs...) + } + + return includedIfs, excludedIfs, nil +} + +// IfByMaskSize returns a list of matched and non-matched IfAddrs that have the +// matching mask size. +func IfByMaskSize(selectorParam string, ifAddrs IfAddrs) (matchedIfs, excludedIfs IfAddrs, err error) { + maskSize, err := strconv.ParseUint(selectorParam, 10, 64) + if err != nil { + return IfAddrs{}, IfAddrs{}, fmt.Errorf("invalid exclude size argument (%q): %v", selectorParam, err) + } + + ipIfs, nonIfs := FilterIfByType(ifAddrs, TypeIP) + matchedIfs = make(IfAddrs, 0, len(ipIfs)) + excludedIfs = append(IfAddrs(nil), nonIfs...) + for _, addr := range ipIfs { + ipAddr := ToIPAddr(addr.SockAddr) + if ipAddr == nil { + return IfAddrs{}, IfAddrs{}, fmt.Errorf("unable to filter mask sizes on non-IP type %s: %v", addr.SockAddr.Type().String(), addr.SockAddr.String()) + } + + switch { + case (*ipAddr).Type()&TypeIPv4 != 0 && maskSize > 32: + return IfAddrs{}, IfAddrs{}, fmt.Errorf("mask size out of bounds for IPv4 address: %d", maskSize) + case (*ipAddr).Type()&TypeIPv6 != 0 && maskSize > 128: + return IfAddrs{}, IfAddrs{}, fmt.Errorf("mask size out of bounds for IPv6 address: %d", maskSize) + } + + if (*ipAddr).Maskbits() == int(maskSize) { + matchedIfs = append(matchedIfs, addr) + } else { + excludedIfs = append(excludedIfs, addr) + } + } + + return matchedIfs, excludedIfs, nil +} + +// IfByType returns a list of matching and non-matching IfAddr that match the +// specified type. For instance: +// +// include "type" "IPv4,IPv6" +// +// will include any IfAddrs that is either an IPv4 or IPv6 address. Any +// addresses on those interfaces that don't match will be included in the +// remainder results. +func IfByType(inputTypes string, ifAddrs IfAddrs) (matched, remainder IfAddrs, err error) { + matchingIfAddrs := make(IfAddrs, 0, len(ifAddrs)) + remainingIfAddrs := make(IfAddrs, 0, len(ifAddrs)) + + ifTypes := strings.Split(strings.ToLower(inputTypes), "|") + for _, ifType := range ifTypes { + switch ifType { + case "ip", "ipv4", "ipv6", "unix": + // Valid types + default: + return nil, nil, fmt.Errorf("unsupported type %q %q", ifType, inputTypes) + } + } + + for _, ifAddr := range ifAddrs { + for _, ifType := range ifTypes { + var matched bool + switch { + case ifType == "ip" && ifAddr.SockAddr.Type()&TypeIP != 0: + matched = true + case ifType == "ipv4" && ifAddr.SockAddr.Type()&TypeIPv4 != 0: + matched = true + case ifType == "ipv6" && ifAddr.SockAddr.Type()&TypeIPv6 != 0: + matched = true + case ifType == "unix" && ifAddr.SockAddr.Type()&TypeUnix != 0: + matched = true + } + + if matched { + matchingIfAddrs = append(matchingIfAddrs, ifAddr) + } else { + remainingIfAddrs = append(remainingIfAddrs, ifAddr) + } + } + } + + return matchingIfAddrs, remainingIfAddrs, nil +} + +// IfByFlag returns a list of matching and non-matching IfAddrs that match the +// specified type. For instance: +// +// include "flag" "up,broadcast" +// +// will include any IfAddrs that have both the "up" and "broadcast" flags set. +// Any addresses on those interfaces that don't match will be omitted from the +// results. +func IfByFlag(inputFlags string, ifAddrs IfAddrs) (matched, remainder IfAddrs, err error) { + matchedAddrs := make(IfAddrs, 0, len(ifAddrs)) + excludedAddrs := make(IfAddrs, 0, len(ifAddrs)) + + var wantForwardable, + wantGlobalUnicast, + wantInterfaceLocalMulticast, + wantLinkLocalMulticast, + wantLinkLocalUnicast, + wantLoopback, + wantMulticast, + wantUnspecified bool + var ifFlags net.Flags + var checkFlags, checkAttrs bool + for _, flagName := range strings.Split(strings.ToLower(inputFlags), "|") { + switch flagName { + case "broadcast": + checkFlags = true + ifFlags = ifFlags | net.FlagBroadcast + case "down": + checkFlags = true + ifFlags = (ifFlags &^ net.FlagUp) + case "forwardable": + checkAttrs = true + wantForwardable = true + case "global unicast": + checkAttrs = true + wantGlobalUnicast = true + case "interface-local multicast": + checkAttrs = true + wantInterfaceLocalMulticast = true + case "link-local multicast": + checkAttrs = true + wantLinkLocalMulticast = true + case "link-local unicast": + checkAttrs = true + wantLinkLocalUnicast = true + case "loopback": + checkAttrs = true + checkFlags = true + ifFlags = ifFlags | net.FlagLoopback + wantLoopback = true + case "multicast": + checkAttrs = true + checkFlags = true + ifFlags = ifFlags | net.FlagMulticast + wantMulticast = true + case "point-to-point": + checkFlags = true + ifFlags = ifFlags | net.FlagPointToPoint + case "unspecified": + checkAttrs = true + wantUnspecified = true + case "up": + checkFlags = true + ifFlags = ifFlags | net.FlagUp + default: + return nil, nil, fmt.Errorf("Unknown interface flag: %+q", flagName) + } + } + + for _, ifAddr := range ifAddrs { + var matched bool + if checkFlags && ifAddr.Interface.Flags&ifFlags == ifFlags { + matched = true + } + if checkAttrs { + if ip := ToIPAddr(ifAddr.SockAddr); ip != nil { + netIP := (*ip).NetIP() + switch { + case wantGlobalUnicast && netIP.IsGlobalUnicast(): + matched = true + case wantInterfaceLocalMulticast && netIP.IsInterfaceLocalMulticast(): + matched = true + case wantLinkLocalMulticast && netIP.IsLinkLocalMulticast(): + matched = true + case wantLinkLocalUnicast && netIP.IsLinkLocalUnicast(): + matched = true + case wantLoopback && netIP.IsLoopback(): + matched = true + case wantMulticast && netIP.IsMulticast(): + matched = true + case wantUnspecified && netIP.IsUnspecified(): + matched = true + case wantForwardable && !IsRFC(ForwardingBlacklist, ifAddr.SockAddr): + matched = true + } + } + } + if matched { + matchedAddrs = append(matchedAddrs, ifAddr) + } else { + excludedAddrs = append(excludedAddrs, ifAddr) + } + } + return matchedAddrs, excludedAddrs, nil +} + +// IfByNetwork returns an IfAddrs that are equal to or included within the +// network passed in by selector. +func IfByNetwork(selectorParam string, inputIfAddrs IfAddrs) (IfAddrs, IfAddrs, error) { + var includedIfs, excludedIfs IfAddrs + for _, netStr := range strings.Split(selectorParam, "|") { + netAddr, err := NewIPAddr(netStr) + if err != nil { + return nil, nil, fmt.Errorf("unable to create an IP address from %+q: %v", netStr, err) + } + + for _, ifAddr := range inputIfAddrs { + if netAddr.Contains(ifAddr.SockAddr) { + includedIfs = append(includedIfs, ifAddr) + } else { + excludedIfs = append(excludedIfs, ifAddr) + } + } + } + + return includedIfs, excludedIfs, nil +} + +// IfAddrMath will return a new IfAddr struct with a mutated value. +func IfAddrMath(operation, value string, inputIfAddr IfAddr) (IfAddr, error) { + // Regexp used to enforce the sign being a required part of the grammar for + // some values. + signRe := signRE.Copy() + + switch strings.ToLower(operation) { + case "address": + // "address" operates on the IP address and is allowed to overflow or + // underflow networks, however it will wrap along the underlying address's + // underlying type. + + if !signRe.MatchString(value) { + return IfAddr{}, fmt.Errorf("sign (+/-) is required for operation %q", operation) + } + + switch sockType := inputIfAddr.SockAddr.Type(); sockType { + case TypeIPv4: + // 33 == Accept any uint32 value + // TODO(seanc@): Add the ability to parse hex + i, err := strconv.ParseInt(value, 10, 33) + if err != nil { + return IfAddr{}, fmt.Errorf("unable to convert %q to int for operation %q: %v", value, operation, err) + } + + ipv4 := *ToIPv4Addr(inputIfAddr.SockAddr) + ipv4Uint32 := uint32(ipv4.Address) + ipv4Uint32 += uint32(i) + return IfAddr{ + SockAddr: IPv4Addr{ + Address: IPv4Address(ipv4Uint32), + Mask: ipv4.Mask, + }, + Interface: inputIfAddr.Interface, + }, nil + case TypeIPv6: + // 64 == Accept any int32 value + // TODO(seanc@): Add the ability to parse hex. Also parse a bignum int. + i, err := strconv.ParseInt(value, 10, 64) + if err != nil { + return IfAddr{}, fmt.Errorf("unable to convert %q to int for operation %q: %v", value, operation, err) + } + + ipv6 := *ToIPv6Addr(inputIfAddr.SockAddr) + ipv6BigIntA := new(big.Int) + ipv6BigIntA.Set(ipv6.Address) + ipv6BigIntB := big.NewInt(i) + + ipv6Addr := ipv6BigIntA.Add(ipv6BigIntA, ipv6BigIntB) + ipv6Addr.And(ipv6Addr, ipv6HostMask) + + return IfAddr{ + SockAddr: IPv6Addr{ + Address: IPv6Address(ipv6Addr), + Mask: ipv6.Mask, + }, + Interface: inputIfAddr.Interface, + }, nil + default: + return IfAddr{}, fmt.Errorf("unsupported type for operation %q: %T", operation, sockType) + } + case "network": + // "network" operates on the network address. Positive values start at the + // network address and negative values wrap at the network address, which + // means a "-1" value on a network will be the broadcast address after + // wrapping is applied. + + if !signRe.MatchString(value) { + return IfAddr{}, fmt.Errorf("sign (+/-) is required for operation %q", operation) + } + + switch sockType := inputIfAddr.SockAddr.Type(); sockType { + case TypeIPv4: + // 33 == Accept any uint32 value + // TODO(seanc@): Add the ability to parse hex + i, err := strconv.ParseInt(value, 10, 33) + if err != nil { + return IfAddr{}, fmt.Errorf("unable to convert %q to int for operation %q: %v", value, operation, err) + } + + ipv4 := *ToIPv4Addr(inputIfAddr.SockAddr) + ipv4Uint32 := uint32(ipv4.NetworkAddress()) + + // Wrap along network mask boundaries. EZ-mode wrapping made possible by + // use of int64 vs a uint. + var wrappedMask int64 + if i >= 0 { + wrappedMask = i + } else { + wrappedMask = 1 + i + int64(^uint32(ipv4.Mask)) + } + + ipv4Uint32 = ipv4Uint32 + (uint32(wrappedMask) &^ uint32(ipv4.Mask)) + + return IfAddr{ + SockAddr: IPv4Addr{ + Address: IPv4Address(ipv4Uint32), + Mask: ipv4.Mask, + }, + Interface: inputIfAddr.Interface, + }, nil + case TypeIPv6: + // 64 == Accept any int32 value + // TODO(seanc@): Add the ability to parse hex. Also parse a bignum int. + i, err := strconv.ParseInt(value, 10, 64) + if err != nil { + return IfAddr{}, fmt.Errorf("unable to convert %q to int for operation %q: %v", value, operation, err) + } + + ipv6 := *ToIPv6Addr(inputIfAddr.SockAddr) + ipv6BigInt := new(big.Int) + ipv6BigInt.Set(ipv6.NetworkAddress()) + + mask := new(big.Int) + mask.Set(ipv6.Mask) + if i > 0 { + wrappedMask := new(big.Int) + wrappedMask.SetInt64(i) + + wrappedMask.AndNot(wrappedMask, mask) + ipv6BigInt.Add(ipv6BigInt, wrappedMask) + } else { + // Mask off any bits that exceed the network size. Subtract the + // wrappedMask from the last usable - 1 + wrappedMask := new(big.Int) + wrappedMask.SetInt64(-1 * i) + wrappedMask.Sub(wrappedMask, big.NewInt(1)) + + wrappedMask.AndNot(wrappedMask, mask) + + lastUsable := new(big.Int) + lastUsable.Set(ipv6.LastUsable().(IPv6Addr).Address) + + ipv6BigInt = lastUsable.Sub(lastUsable, wrappedMask) + } + + return IfAddr{ + SockAddr: IPv6Addr{ + Address: IPv6Address(ipv6BigInt), + Mask: ipv6.Mask, + }, + Interface: inputIfAddr.Interface, + }, nil + default: + return IfAddr{}, fmt.Errorf("unsupported type for operation %q: %T", operation, sockType) + } + case "mask": + // "mask" operates on the IP address and returns the IP address on + // which the given integer mask has been applied. If the applied mask + // corresponds to a larger network than the mask of the IP address, + // the latter will be replaced by the former. + switch sockType := inputIfAddr.SockAddr.Type(); sockType { + case TypeIPv4: + i, err := strconv.ParseUint(value, 10, 32) + if err != nil { + return IfAddr{}, fmt.Errorf("unable to convert %q to int for operation %q: %v", value, operation, err) + } + + if i > 32 { + return IfAddr{}, fmt.Errorf("parameter for operation %q on ipv4 addresses must be between 0 and 32", operation) + } + + ipv4 := *ToIPv4Addr(inputIfAddr.SockAddr) + + ipv4Mask := net.CIDRMask(int(i), 32) + ipv4MaskUint32 := binary.BigEndian.Uint32(ipv4Mask) + + maskedIpv4 := ipv4.NetIP().Mask(ipv4Mask) + maskedIpv4Uint32 := binary.BigEndian.Uint32(maskedIpv4) + + maskedIpv4MaskUint32 := uint32(ipv4.Mask) + + if ipv4MaskUint32 < maskedIpv4MaskUint32 { + maskedIpv4MaskUint32 = ipv4MaskUint32 + } + + return IfAddr{ + SockAddr: IPv4Addr{ + Address: IPv4Address(maskedIpv4Uint32), + Mask: IPv4Mask(maskedIpv4MaskUint32), + }, + Interface: inputIfAddr.Interface, + }, nil + case TypeIPv6: + i, err := strconv.ParseUint(value, 10, 32) + if err != nil { + return IfAddr{}, fmt.Errorf("unable to convert %q to int for operation %q: %v", value, operation, err) + } + + if i > 128 { + return IfAddr{}, fmt.Errorf("parameter for operation %q on ipv6 addresses must be between 0 and 64", operation) + } + + ipv6 := *ToIPv6Addr(inputIfAddr.SockAddr) + + ipv6Mask := net.CIDRMask(int(i), 128) + ipv6MaskBigInt := new(big.Int) + ipv6MaskBigInt.SetBytes(ipv6Mask) + + maskedIpv6 := ipv6.NetIP().Mask(ipv6Mask) + maskedIpv6BigInt := new(big.Int) + maskedIpv6BigInt.SetBytes(maskedIpv6) + + maskedIpv6MaskBigInt := new(big.Int) + maskedIpv6MaskBigInt.Set(ipv6.Mask) + + if ipv6MaskBigInt.Cmp(maskedIpv6MaskBigInt) == -1 { + maskedIpv6MaskBigInt = ipv6MaskBigInt + } + + return IfAddr{ + SockAddr: IPv6Addr{ + Address: IPv6Address(maskedIpv6BigInt), + Mask: IPv6Mask(maskedIpv6MaskBigInt), + }, + Interface: inputIfAddr.Interface, + }, nil + default: + return IfAddr{}, fmt.Errorf("unsupported type for operation %q: %T", operation, sockType) + } + default: + return IfAddr{}, fmt.Errorf("unsupported math operation: %q", operation) + } +} + +// IfAddrsMath will apply an IfAddrMath operation each IfAddr struct. Any +// failure will result in zero results. +func IfAddrsMath(operation, value string, inputIfAddrs IfAddrs) (IfAddrs, error) { + outputAddrs := make(IfAddrs, 0, len(inputIfAddrs)) + for _, ifAddr := range inputIfAddrs { + result, err := IfAddrMath(operation, value, ifAddr) + if err != nil { + return IfAddrs{}, fmt.Errorf("unable to perform an IPMath operation on %s: %v", ifAddr, err) + } + outputAddrs = append(outputAddrs, result) + } + return outputAddrs, nil +} + +// IncludeIfs returns an IfAddrs based on the passed in selector. +func IncludeIfs(selectorName, selectorParam string, inputIfAddrs IfAddrs) (IfAddrs, error) { + var includedIfs IfAddrs + var err error + + switch strings.ToLower(selectorName) { + case "address": + includedIfs, _, err = IfByAddress(selectorParam, inputIfAddrs) + case "flag", "flags": + includedIfs, _, err = IfByFlag(selectorParam, inputIfAddrs) + case "name": + includedIfs, _, err = IfByName(selectorParam, inputIfAddrs) + case "network": + includedIfs, _, err = IfByNetwork(selectorParam, inputIfAddrs) + case "port": + includedIfs, _, err = IfByPort(selectorParam, inputIfAddrs) + case "rfc", "rfcs": + includedIfs, _, err = IfByRFCs(selectorParam, inputIfAddrs) + case "size": + includedIfs, _, err = IfByMaskSize(selectorParam, inputIfAddrs) + case "type": + includedIfs, _, err = IfByType(selectorParam, inputIfAddrs) + default: + return IfAddrs{}, fmt.Errorf("invalid include selector %q", selectorName) + } + + if err != nil { + return IfAddrs{}, err + } + + return includedIfs, nil +} + +// ExcludeIfs returns an IfAddrs based on the passed in selector. +func ExcludeIfs(selectorName, selectorParam string, inputIfAddrs IfAddrs) (IfAddrs, error) { + var excludedIfs IfAddrs + var err error + + switch strings.ToLower(selectorName) { + case "address": + _, excludedIfs, err = IfByAddress(selectorParam, inputIfAddrs) + case "flag", "flags": + _, excludedIfs, err = IfByFlag(selectorParam, inputIfAddrs) + case "name": + _, excludedIfs, err = IfByName(selectorParam, inputIfAddrs) + case "network": + _, excludedIfs, err = IfByNetwork(selectorParam, inputIfAddrs) + case "port": + _, excludedIfs, err = IfByPort(selectorParam, inputIfAddrs) + case "rfc", "rfcs": + _, excludedIfs, err = IfByRFCs(selectorParam, inputIfAddrs) + case "size": + _, excludedIfs, err = IfByMaskSize(selectorParam, inputIfAddrs) + case "type": + _, excludedIfs, err = IfByType(selectorParam, inputIfAddrs) + default: + return IfAddrs{}, fmt.Errorf("invalid exclude selector %q", selectorName) + } + + if err != nil { + return IfAddrs{}, err + } + + return excludedIfs, nil +} + +// SortIfBy returns an IfAddrs sorted based on the passed in selector. Multiple +// sort clauses can be passed in as a comma delimited list without whitespace. +func SortIfBy(selectorParam string, inputIfAddrs IfAddrs) (IfAddrs, error) { + sortedIfs := append(IfAddrs(nil), inputIfAddrs...) + + clauses := strings.Split(selectorParam, ",") + sortFuncs := make([]CmpIfAddrFunc, len(clauses)) + + for i, clause := range clauses { + switch strings.TrimSpace(strings.ToLower(clause)) { + case "+address", "address": + // The "address" selector returns an array of IfAddrs + // ordered by the network address. IfAddrs that are not + // comparable will be at the end of the list and in a + // non-deterministic order. + sortFuncs[i] = AscIfAddress + case "-address": + sortFuncs[i] = DescIfAddress + case "+default", "default": + sortFuncs[i] = AscIfDefault + case "-default": + sortFuncs[i] = DescIfDefault + case "+name", "name": + // The "name" selector returns an array of IfAddrs + // ordered by the interface name. + sortFuncs[i] = AscIfName + case "-name": + sortFuncs[i] = DescIfName + case "+port", "port": + // The "port" selector returns an array of IfAddrs + // ordered by the port, if included in the IfAddr. + // IfAddrs that are not comparable will be at the end of + // the list and in a non-deterministic order. + sortFuncs[i] = AscIfPort + case "-port": + sortFuncs[i] = DescIfPort + case "+private", "private": + // The "private" selector returns an array of IfAddrs + // ordered by private addresses first. IfAddrs that are + // not comparable will be at the end of the list and in + // a non-deterministic order. + sortFuncs[i] = AscIfPrivate + case "-private": + sortFuncs[i] = DescIfPrivate + case "+size", "size": + // The "size" selector returns an array of IfAddrs + // ordered by the size of the network mask, smaller mask + // (larger number of hosts per network) to largest + // (e.g. a /24 sorts before a /32). + sortFuncs[i] = AscIfNetworkSize + case "-size": + sortFuncs[i] = DescIfNetworkSize + case "+type", "type": + // The "type" selector returns an array of IfAddrs + // ordered by the type of the IfAddr. The sort order is + // Unix, IPv4, then IPv6. + sortFuncs[i] = AscIfType + case "-type": + sortFuncs[i] = DescIfType + default: + // Return an empty list for invalid sort types. + return IfAddrs{}, fmt.Errorf("unknown sort type: %q", clause) + } + } + + OrderedIfAddrBy(sortFuncs...).Sort(sortedIfs) + + return sortedIfs, nil +} + +// UniqueIfAddrsBy creates a unique set of IfAddrs based on the matching +// selector. UniqueIfAddrsBy assumes the input has already been sorted. +func UniqueIfAddrsBy(selectorName string, inputIfAddrs IfAddrs) (IfAddrs, error) { + attrName := strings.ToLower(selectorName) + + ifs := make(IfAddrs, 0, len(inputIfAddrs)) + var lastMatch string + for _, ifAddr := range inputIfAddrs { + var out string + switch attrName { + case "address": + out = ifAddr.SockAddr.String() + case "name": + out = ifAddr.Name + default: + return nil, fmt.Errorf("unsupported unique constraint %+q", selectorName) + } + + switch { + case lastMatch == "", lastMatch != out: + lastMatch = out + ifs = append(ifs, ifAddr) + case lastMatch == out: + continue + } + } + + return ifs, nil +} + +// JoinIfAddrs joins an IfAddrs and returns a string +func JoinIfAddrs(selectorName string, joinStr string, inputIfAddrs IfAddrs) (string, error) { + outputs := make([]string, 0, len(inputIfAddrs)) + attrName := AttrName(strings.ToLower(selectorName)) + + for _, ifAddr := range inputIfAddrs { + var attrVal string + var err error + attrVal, err = ifAddr.Attr(attrName) + if err != nil { + return "", err + } + outputs = append(outputs, attrVal) + } + return strings.Join(outputs, joinStr), nil +} + +// LimitIfAddrs returns a slice of IfAddrs based on the specified limit. +func LimitIfAddrs(lim uint, in IfAddrs) (IfAddrs, error) { + // Clamp the limit to the length of the array + if int(lim) > len(in) { + lim = uint(len(in)) + } + + return in[0:lim], nil +} + +// OffsetIfAddrs returns a slice of IfAddrs based on the specified offset. +func OffsetIfAddrs(off int, in IfAddrs) (IfAddrs, error) { + var end bool + if off < 0 { + end = true + off = off * -1 + } + + if off > len(in) { + return IfAddrs{}, fmt.Errorf("unable to seek past the end of the interface array: offset (%d) exceeds the number of interfaces (%d)", off, len(in)) + } + + if end { + return in[len(in)-off:], nil + } + return in[off:], nil +} + +func (ifAddr IfAddr) String() string { + return fmt.Sprintf("%s %v", ifAddr.SockAddr, ifAddr.Interface) +} + +// parseDefaultIfNameFromRoute parses standard route(8)'s output for the *BSDs +// and Solaris. +func parseDefaultIfNameFromRoute(routeOut string) (string, error) { + lines := strings.Split(routeOut, "\n") + for _, line := range lines { + kvs := strings.SplitN(line, ":", 2) + if len(kvs) != 2 { + continue + } + + if strings.TrimSpace(kvs[0]) == "interface" { + ifName := strings.TrimSpace(kvs[1]) + return ifName, nil + } + } + + return "", errors.New("No default interface found") +} + +// parseDefaultIfNameFromIPCmd parses the default interface from ip(8) for +// Linux. +func parseDefaultIfNameFromIPCmd(routeOut string) (string, error) { + parsedLines := parseIfNameFromIPCmd(routeOut) + for _, parsedLine := range parsedLines { + if parsedLine[0] == "default" && + parsedLine[1] == "via" && + parsedLine[3] == "dev" { + ifName := strings.TrimSpace(parsedLine[4]) + return ifName, nil + } + } + + return "", errors.New("No default interface found") +} + +// parseDefaultIfNameFromIPCmdAndroid parses the default interface from ip(8) for +// Android. +func parseDefaultIfNameFromIPCmdAndroid(routeOut string) (string, error) { + parsedLines := parseIfNameFromIPCmd(routeOut) + if (len(parsedLines) > 0) { + ifName := strings.TrimSpace(parsedLines[0][4]) + return ifName, nil + } + + return "", errors.New("No default interface found") +} + + +// parseIfNameFromIPCmd parses interfaces from ip(8) for +// Linux. +func parseIfNameFromIPCmd(routeOut string) [][]string { + lines := strings.Split(routeOut, "\n") + re := whitespaceRE.Copy() + parsedLines := make([][]string, 0, len(lines)) + for _, line := range lines { + kvs := re.Split(line, -1) + if len(kvs) < 5 { + continue + } + parsedLines = append(parsedLines, kvs) + } + return parsedLines +} + +// parseDefaultIfNameWindows parses the default interface from `netstat -rn` and +// `ipconfig` on Windows. +func parseDefaultIfNameWindows(routeOut, ipconfigOut string) (string, error) { + defaultIPAddr, err := parseDefaultIPAddrWindowsRoute(routeOut) + if err != nil { + return "", err + } + + ifName, err := parseDefaultIfNameWindowsIPConfig(defaultIPAddr, ipconfigOut) + if err != nil { + return "", err + } + + return ifName, nil +} + +// parseDefaultIPAddrWindowsRoute parses the IP address on the default interface +// `netstat -rn`. +// +// NOTES(sean): Only IPv4 addresses are parsed at this time. If you have an +// IPv6 connected host, submit an issue on github.com/hashicorp/go-sockaddr with +// the output from `netstat -rn`, `ipconfig`, and version of Windows to see IPv6 +// support added. +func parseDefaultIPAddrWindowsRoute(routeOut string) (string, error) { + lines := strings.Split(routeOut, "\n") + re := whitespaceRE.Copy() + for _, line := range lines { + kvs := re.Split(strings.TrimSpace(line), -1) + if len(kvs) < 3 { + continue + } + + if kvs[0] == "0.0.0.0" && kvs[1] == "0.0.0.0" { + defaultIPAddr := strings.TrimSpace(kvs[3]) + return defaultIPAddr, nil + } + } + + return "", errors.New("No IP on default interface found") +} + +// parseDefaultIfNameWindowsIPConfig parses the output of `ipconfig` to find the +// interface name forwarding traffic to the default gateway. +func parseDefaultIfNameWindowsIPConfig(defaultIPAddr, routeOut string) (string, error) { + lines := strings.Split(routeOut, "\n") + ifNameRe := ifNameRE.Copy() + ipAddrRe := ipAddrRE.Copy() + var ifName string + for _, line := range lines { + switch ifNameMatches := ifNameRe.FindStringSubmatch(line); { + case len(ifNameMatches) > 1: + ifName = ifNameMatches[1] + continue + } + + switch ipAddrMatches := ipAddrRe.FindStringSubmatch(line); { + case len(ipAddrMatches) > 1 && ipAddrMatches[1] == defaultIPAddr: + return ifName, nil + } + } + + return "", errors.New("No default interface found with matching IP") +} diff --git a/vendor/github.com/hashicorp/go-sockaddr/ifattr.go b/vendor/github.com/hashicorp/go-sockaddr/ifattr.go new file mode 100644 index 000000000..6984cb4a3 --- /dev/null +++ b/vendor/github.com/hashicorp/go-sockaddr/ifattr.go @@ -0,0 +1,65 @@ +package sockaddr + +import ( + "fmt" + "net" +) + +// IfAddr is a union of a SockAddr and a net.Interface. +type IfAddr struct { + SockAddr + net.Interface +} + +// Attr returns the named attribute as a string +func (ifAddr IfAddr) Attr(attrName AttrName) (string, error) { + val := IfAddrAttr(ifAddr, attrName) + if val != "" { + return val, nil + } + + return Attr(ifAddr.SockAddr, attrName) +} + +// Attr returns the named attribute as a string +func Attr(sa SockAddr, attrName AttrName) (string, error) { + switch sockType := sa.Type(); { + case sockType&TypeIP != 0: + ip := *ToIPAddr(sa) + attrVal := IPAddrAttr(ip, attrName) + if attrVal != "" { + return attrVal, nil + } + + if sockType == TypeIPv4 { + ipv4 := *ToIPv4Addr(sa) + attrVal := IPv4AddrAttr(ipv4, attrName) + if attrVal != "" { + return attrVal, nil + } + } else if sockType == TypeIPv6 { + ipv6 := *ToIPv6Addr(sa) + attrVal := IPv6AddrAttr(ipv6, attrName) + if attrVal != "" { + return attrVal, nil + } + } + + case sockType == TypeUnix: + us := *ToUnixSock(sa) + attrVal := UnixSockAttr(us, attrName) + if attrVal != "" { + return attrVal, nil + } + } + + // Non type-specific attributes + switch attrName { + case "string": + return sa.String(), nil + case "type": + return sa.Type().String(), nil + } + + return "", fmt.Errorf("unsupported attribute name %q", attrName) +} diff --git a/vendor/github.com/hashicorp/go-sockaddr/ipaddr.go b/vendor/github.com/hashicorp/go-sockaddr/ipaddr.go new file mode 100644 index 000000000..b47d15c20 --- /dev/null +++ b/vendor/github.com/hashicorp/go-sockaddr/ipaddr.go @@ -0,0 +1,169 @@ +package sockaddr + +import ( + "fmt" + "math/big" + "net" + "strings" +) + +// Constants for the sizes of IPv3, IPv4, and IPv6 address types. +const ( + IPv3len = 6 + IPv4len = 4 + IPv6len = 16 +) + +// IPAddr is a generic IP address interface for IPv4 and IPv6 addresses, +// networks, and socket endpoints. +type IPAddr interface { + SockAddr + AddressBinString() string + AddressHexString() string + Cmp(SockAddr) int + CmpAddress(SockAddr) int + CmpPort(SockAddr) int + FirstUsable() IPAddr + Host() IPAddr + IPPort() IPPort + LastUsable() IPAddr + Maskbits() int + NetIP() *net.IP + NetIPMask() *net.IPMask + NetIPNet() *net.IPNet + Network() IPAddr + Octets() []int +} + +// IPPort is the type for an IP port number for the TCP and UDP IP transports. +type IPPort uint16 + +// IPPrefixLen is a typed integer representing the prefix length for a given +// IPAddr. +type IPPrefixLen byte + +// ipAddrAttrMap is a map of the IPAddr type-specific attributes. +var ipAddrAttrMap map[AttrName]func(IPAddr) string +var ipAddrAttrs []AttrName + +func init() { + ipAddrInit() +} + +// NewIPAddr creates a new IPAddr from a string. Returns nil if the string is +// not an IPv4 or an IPv6 address. +func NewIPAddr(addr string) (IPAddr, error) { + ipv4Addr, err := NewIPv4Addr(addr) + if err == nil { + return ipv4Addr, nil + } + + ipv6Addr, err := NewIPv6Addr(addr) + if err == nil { + return ipv6Addr, nil + } + + return nil, fmt.Errorf("invalid IPAddr %v", addr) +} + +// IPAddrAttr returns a string representation of an attribute for the given +// IPAddr. +func IPAddrAttr(ip IPAddr, selector AttrName) string { + fn, found := ipAddrAttrMap[selector] + if !found { + return "" + } + + return fn(ip) +} + +// IPAttrs returns a list of attributes supported by the IPAddr type +func IPAttrs() []AttrName { + return ipAddrAttrs +} + +// MustIPAddr is a helper method that must return an IPAddr or panic on invalid +// input. +func MustIPAddr(addr string) IPAddr { + ip, err := NewIPAddr(addr) + if err != nil { + panic(fmt.Sprintf("Unable to create an IPAddr from %+q: %v", addr, err)) + } + return ip +} + +// ipAddrInit is called once at init() +func ipAddrInit() { + // Sorted for human readability + ipAddrAttrs = []AttrName{ + "host", + "address", + "port", + "netmask", + "network", + "mask_bits", + "binary", + "hex", + "first_usable", + "last_usable", + "octets", + } + + ipAddrAttrMap = map[AttrName]func(ip IPAddr) string{ + "address": func(ip IPAddr) string { + return ip.NetIP().String() + }, + "binary": func(ip IPAddr) string { + return ip.AddressBinString() + }, + "first_usable": func(ip IPAddr) string { + return ip.FirstUsable().String() + }, + "hex": func(ip IPAddr) string { + return ip.AddressHexString() + }, + "host": func(ip IPAddr) string { + return ip.Host().String() + }, + "last_usable": func(ip IPAddr) string { + return ip.LastUsable().String() + }, + "mask_bits": func(ip IPAddr) string { + return fmt.Sprintf("%d", ip.Maskbits()) + }, + "netmask": func(ip IPAddr) string { + switch v := ip.(type) { + case IPv4Addr: + ipv4Mask := IPv4Addr{ + Address: IPv4Address(v.Mask), + Mask: IPv4HostMask, + } + return ipv4Mask.String() + case IPv6Addr: + ipv6Mask := new(big.Int) + ipv6Mask.Set(v.Mask) + ipv6MaskAddr := IPv6Addr{ + Address: IPv6Address(ipv6Mask), + Mask: ipv6HostMask, + } + return ipv6MaskAddr.String() + default: + return fmt.Sprintf("", ip) + } + }, + "network": func(ip IPAddr) string { + return ip.Network().NetIP().String() + }, + "octets": func(ip IPAddr) string { + octets := ip.Octets() + octetStrs := make([]string, 0, len(octets)) + for _, octet := range octets { + octetStrs = append(octetStrs, fmt.Sprintf("%d", octet)) + } + return strings.Join(octetStrs, " ") + }, + "port": func(ip IPAddr) string { + return fmt.Sprintf("%d", ip.IPPort()) + }, + } +} diff --git a/vendor/github.com/hashicorp/go-sockaddr/ipaddrs.go b/vendor/github.com/hashicorp/go-sockaddr/ipaddrs.go new file mode 100644 index 000000000..6eeb7ddd2 --- /dev/null +++ b/vendor/github.com/hashicorp/go-sockaddr/ipaddrs.go @@ -0,0 +1,98 @@ +package sockaddr + +import "bytes" + +type IPAddrs []IPAddr + +func (s IPAddrs) Len() int { return len(s) } +func (s IPAddrs) Swap(i, j int) { s[i], s[j] = s[j], s[i] } + +// // SortIPAddrsByCmp is a type that satisfies sort.Interface and can be used +// // by the routines in this package. The SortIPAddrsByCmp type is used to +// // sort IPAddrs by Cmp() +// type SortIPAddrsByCmp struct{ IPAddrs } + +// // Less reports whether the element with index i should sort before the +// // element with index j. +// func (s SortIPAddrsByCmp) Less(i, j int) bool { +// // Sort by Type, then address, then port number. +// return Less(s.IPAddrs[i], s.IPAddrs[j]) +// } + +// SortIPAddrsBySpecificMaskLen is a type that satisfies sort.Interface and +// can be used by the routines in this package. The +// SortIPAddrsBySpecificMaskLen type is used to sort IPAddrs by smallest +// network (most specific to largest network). +type SortIPAddrsByNetworkSize struct{ IPAddrs } + +// Less reports whether the element with index i should sort before the +// element with index j. +func (s SortIPAddrsByNetworkSize) Less(i, j int) bool { + // Sort masks with a larger binary value (i.e. fewer hosts per network + // prefix) after masks with a smaller value (larger number of hosts per + // prefix). + switch bytes.Compare([]byte(*s.IPAddrs[i].NetIPMask()), []byte(*s.IPAddrs[j].NetIPMask())) { + case 0: + // Fall through to the second test if the net.IPMasks are the + // same. + break + case 1: + return true + case -1: + return false + default: + panic("bad, m'kay?") + } + + // Sort IPs based on the length (i.e. prefer IPv4 over IPv6). + iLen := len(*s.IPAddrs[i].NetIP()) + jLen := len(*s.IPAddrs[j].NetIP()) + if iLen != jLen { + return iLen > jLen + } + + // Sort IPs based on their network address from lowest to highest. + switch bytes.Compare(s.IPAddrs[i].NetIPNet().IP, s.IPAddrs[j].NetIPNet().IP) { + case 0: + break + case 1: + return false + case -1: + return true + default: + panic("lol wut?") + } + + // If a host does not have a port set, it always sorts after hosts + // that have a port (e.g. a host with a /32 and port number is more + // specific and should sort first over a host with a /32 but no port + // set). + if s.IPAddrs[i].IPPort() == 0 || s.IPAddrs[j].IPPort() == 0 { + return false + } + return s.IPAddrs[i].IPPort() < s.IPAddrs[j].IPPort() +} + +// SortIPAddrsBySpecificMaskLen is a type that satisfies sort.Interface and +// can be used by the routines in this package. The +// SortIPAddrsBySpecificMaskLen type is used to sort IPAddrs by smallest +// network (most specific to largest network). +type SortIPAddrsBySpecificMaskLen struct{ IPAddrs } + +// Less reports whether the element with index i should sort before the +// element with index j. +func (s SortIPAddrsBySpecificMaskLen) Less(i, j int) bool { + return s.IPAddrs[i].Maskbits() > s.IPAddrs[j].Maskbits() +} + +// SortIPAddrsByBroadMaskLen is a type that satisfies sort.Interface and can +// be used by the routines in this package. The SortIPAddrsByBroadMaskLen +// type is used to sort IPAddrs by largest network (i.e. largest subnets +// first). +type SortIPAddrsByBroadMaskLen struct{ IPAddrs } + +// Less reports whether the element with index i should sort before the +// element with index j. +func (s SortIPAddrsByBroadMaskLen) Less(i, j int) bool { + return s.IPAddrs[i].Maskbits() < s.IPAddrs[j].Maskbits() +} diff --git a/vendor/github.com/hashicorp/go-sockaddr/ipv4addr.go b/vendor/github.com/hashicorp/go-sockaddr/ipv4addr.go new file mode 100644 index 000000000..4d395dc95 --- /dev/null +++ b/vendor/github.com/hashicorp/go-sockaddr/ipv4addr.go @@ -0,0 +1,516 @@ +package sockaddr + +import ( + "encoding/binary" + "fmt" + "net" + "regexp" + "strconv" + "strings" +) + +type ( + // IPv4Address is a named type representing an IPv4 address. + IPv4Address uint32 + + // IPv4Network is a named type representing an IPv4 network. + IPv4Network uint32 + + // IPv4Mask is a named type representing an IPv4 network mask. + IPv4Mask uint32 +) + +// IPv4HostMask is a constant represents a /32 IPv4 Address +// (i.e. 255.255.255.255). +const IPv4HostMask = IPv4Mask(0xffffffff) + +// ipv4AddrAttrMap is a map of the IPv4Addr type-specific attributes. +var ipv4AddrAttrMap map[AttrName]func(IPv4Addr) string +var ipv4AddrAttrs []AttrName +var trailingHexNetmaskRE *regexp.Regexp + +// IPv4Addr implements a convenience wrapper around the union of Go's +// built-in net.IP and net.IPNet types. In UNIX-speak, IPv4Addr implements +// `sockaddr` when the the address family is set to AF_INET +// (i.e. `sockaddr_in`). +type IPv4Addr struct { + IPAddr + Address IPv4Address + Mask IPv4Mask + Port IPPort +} + +func init() { + ipv4AddrInit() + trailingHexNetmaskRE = regexp.MustCompile(`/([0f]{8})$`) +} + +// NewIPv4Addr creates an IPv4Addr from a string. String can be in the form +// of either an IPv4:port (e.g. `1.2.3.4:80`, in which case the mask is +// assumed to be a `/32`), an IPv4 address (e.g. `1.2.3.4`, also with a `/32` +// mask), or an IPv4 CIDR (e.g. `1.2.3.4/24`, which has its IP port +// initialized to zero). ipv4Str can not be a hostname. +// +// NOTE: Many net.*() routines will initialize and return an IPv6 address. +// To create uint32 values from net.IP, always test to make sure the address +// returned can be converted to a 4 byte array using To4(). +func NewIPv4Addr(ipv4Str string) (IPv4Addr, error) { + // Strip off any bogus hex-encoded netmasks that will be mis-parsed by Go. In + // particular, clients with the Barracuda VPN client will see something like: + // `192.168.3.51/00ffffff` as their IP address. + trailingHexNetmaskRe := trailingHexNetmaskRE.Copy() + if match := trailingHexNetmaskRe.FindStringIndex(ipv4Str); match != nil { + ipv4Str = ipv4Str[:match[0]] + } + + // Parse as an IPv4 CIDR + ipAddr, network, err := net.ParseCIDR(ipv4Str) + if err == nil { + ipv4 := ipAddr.To4() + if ipv4 == nil { + return IPv4Addr{}, fmt.Errorf("Unable to convert %s to an IPv4 address", ipv4Str) + } + + // If we see an IPv6 netmask, convert it to an IPv4 mask. + netmaskSepPos := strings.LastIndexByte(ipv4Str, '/') + if netmaskSepPos != -1 && netmaskSepPos+1 < len(ipv4Str) { + netMask, err := strconv.ParseUint(ipv4Str[netmaskSepPos+1:], 10, 8) + if err != nil { + return IPv4Addr{}, fmt.Errorf("Unable to convert %s to an IPv4 address: unable to parse CIDR netmask: %v", ipv4Str, err) + } else if netMask > 128 { + return IPv4Addr{}, fmt.Errorf("Unable to convert %s to an IPv4 address: invalid CIDR netmask", ipv4Str) + } + + if netMask >= 96 { + // Convert the IPv6 netmask to an IPv4 netmask + network.Mask = net.CIDRMask(int(netMask-96), IPv4len*8) + } + } + ipv4Addr := IPv4Addr{ + Address: IPv4Address(binary.BigEndian.Uint32(ipv4)), + Mask: IPv4Mask(binary.BigEndian.Uint32(network.Mask)), + } + return ipv4Addr, nil + } + + // Attempt to parse ipv4Str as a /32 host with a port number. + tcpAddr, err := net.ResolveTCPAddr("tcp4", ipv4Str) + if err == nil { + ipv4 := tcpAddr.IP.To4() + if ipv4 == nil { + return IPv4Addr{}, fmt.Errorf("Unable to resolve %+q as an IPv4 address", ipv4Str) + } + + ipv4Uint32 := binary.BigEndian.Uint32(ipv4) + ipv4Addr := IPv4Addr{ + Address: IPv4Address(ipv4Uint32), + Mask: IPv4HostMask, + Port: IPPort(tcpAddr.Port), + } + + return ipv4Addr, nil + } + + // Parse as a naked IPv4 address + ip := net.ParseIP(ipv4Str) + if ip != nil { + ipv4 := ip.To4() + if ipv4 == nil { + return IPv4Addr{}, fmt.Errorf("Unable to string convert %+q to an IPv4 address", ipv4Str) + } + + ipv4Uint32 := binary.BigEndian.Uint32(ipv4) + ipv4Addr := IPv4Addr{ + Address: IPv4Address(ipv4Uint32), + Mask: IPv4HostMask, + } + return ipv4Addr, nil + } + + return IPv4Addr{}, fmt.Errorf("Unable to parse %+q to an IPv4 address: %v", ipv4Str, err) +} + +// AddressBinString returns a string with the IPv4Addr's Address represented +// as a sequence of '0' and '1' characters. This method is useful for +// debugging or by operators who want to inspect an address. +func (ipv4 IPv4Addr) AddressBinString() string { + return fmt.Sprintf("%032s", strconv.FormatUint(uint64(ipv4.Address), 2)) +} + +// AddressHexString returns a string with the IPv4Addr address represented as +// a sequence of hex characters. This method is useful for debugging or by +// operators who want to inspect an address. +func (ipv4 IPv4Addr) AddressHexString() string { + return fmt.Sprintf("%08s", strconv.FormatUint(uint64(ipv4.Address), 16)) +} + +// Broadcast is an IPv4Addr-only method that returns the broadcast address of +// the network. +// +// NOTE: IPv6 only supports multicast, so this method only exists for +// IPv4Addr. +func (ipv4 IPv4Addr) Broadcast() IPAddr { + // Nothing should listen on a broadcast address. + return IPv4Addr{ + Address: IPv4Address(ipv4.BroadcastAddress()), + Mask: IPv4HostMask, + } +} + +// BroadcastAddress returns a IPv4Network of the IPv4Addr's broadcast +// address. +func (ipv4 IPv4Addr) BroadcastAddress() IPv4Network { + return IPv4Network(uint32(ipv4.Address)&uint32(ipv4.Mask) | ^uint32(ipv4.Mask)) +} + +// CmpAddress follows the Cmp() standard protocol and returns: +// +// - -1 If the receiver should sort first because its address is lower than arg +// - 0 if the SockAddr arg is equal to the receiving IPv4Addr or the argument is +// of a different type. +// - 1 If the argument should sort first. +func (ipv4 IPv4Addr) CmpAddress(sa SockAddr) int { + ipv4b, ok := sa.(IPv4Addr) + if !ok { + return sortDeferDecision + } + + switch { + case ipv4.Address == ipv4b.Address: + return sortDeferDecision + case ipv4.Address < ipv4b.Address: + return sortReceiverBeforeArg + default: + return sortArgBeforeReceiver + } +} + +// CmpPort follows the Cmp() standard protocol and returns: +// +// - -1 If the receiver should sort first because its port is lower than arg +// - 0 if the SockAddr arg's port number is equal to the receiving IPv4Addr, +// regardless of type. +// - 1 If the argument should sort first. +func (ipv4 IPv4Addr) CmpPort(sa SockAddr) int { + var saPort IPPort + switch v := sa.(type) { + case IPv4Addr: + saPort = v.Port + case IPv6Addr: + saPort = v.Port + default: + return sortDeferDecision + } + + switch { + case ipv4.Port == saPort: + return sortDeferDecision + case ipv4.Port < saPort: + return sortReceiverBeforeArg + default: + return sortArgBeforeReceiver + } +} + +// CmpRFC follows the Cmp() standard protocol and returns: +// +// - -1 If the receiver should sort first because it belongs to the RFC and its +// arg does not +// - 0 if the receiver and arg both belong to the same RFC or neither do. +// - 1 If the arg belongs to the RFC but receiver does not. +func (ipv4 IPv4Addr) CmpRFC(rfcNum uint, sa SockAddr) int { + recvInRFC := IsRFC(rfcNum, ipv4) + ipv4b, ok := sa.(IPv4Addr) + if !ok { + // If the receiver is part of the desired RFC and the SockAddr + // argument is not, return -1 so that the receiver sorts before + // the non-IPv4 SockAddr. Conversely, if the receiver is not + // part of the RFC, punt on sorting and leave it for the next + // sorter. + if recvInRFC { + return sortReceiverBeforeArg + } else { + return sortDeferDecision + } + } + + argInRFC := IsRFC(rfcNum, ipv4b) + switch { + case (recvInRFC && argInRFC), (!recvInRFC && !argInRFC): + // If a and b both belong to the RFC, or neither belong to + // rfcNum, defer sorting to the next sorter. + return sortDeferDecision + case recvInRFC && !argInRFC: + return sortReceiverBeforeArg + default: + return sortArgBeforeReceiver + } +} + +// Contains returns true if the SockAddr is contained within the receiver. +func (ipv4 IPv4Addr) Contains(sa SockAddr) bool { + ipv4b, ok := sa.(IPv4Addr) + if !ok { + return false + } + + return ipv4.ContainsNetwork(ipv4b) +} + +// ContainsAddress returns true if the IPv4Address is contained within the +// receiver. +func (ipv4 IPv4Addr) ContainsAddress(x IPv4Address) bool { + return IPv4Address(ipv4.NetworkAddress()) <= x && + IPv4Address(ipv4.BroadcastAddress()) >= x +} + +// ContainsNetwork returns true if the network from IPv4Addr is contained +// within the receiver. +func (ipv4 IPv4Addr) ContainsNetwork(x IPv4Addr) bool { + return ipv4.NetworkAddress() <= x.NetworkAddress() && + ipv4.BroadcastAddress() >= x.BroadcastAddress() +} + +// DialPacketArgs returns the arguments required to be passed to +// net.DialUDP(). If the Mask of ipv4 is not a /32 or the Port is 0, +// DialPacketArgs() will fail. See Host() to create an IPv4Addr with its +// mask set to /32. +func (ipv4 IPv4Addr) DialPacketArgs() (network, dialArgs string) { + if ipv4.Mask != IPv4HostMask || ipv4.Port == 0 { + return "udp4", "" + } + return "udp4", fmt.Sprintf("%s:%d", ipv4.NetIP().String(), ipv4.Port) +} + +// DialStreamArgs returns the arguments required to be passed to +// net.DialTCP(). If the Mask of ipv4 is not a /32 or the Port is 0, +// DialStreamArgs() will fail. See Host() to create an IPv4Addr with its +// mask set to /32. +func (ipv4 IPv4Addr) DialStreamArgs() (network, dialArgs string) { + if ipv4.Mask != IPv4HostMask || ipv4.Port == 0 { + return "tcp4", "" + } + return "tcp4", fmt.Sprintf("%s:%d", ipv4.NetIP().String(), ipv4.Port) +} + +// Equal returns true if a SockAddr is equal to the receiving IPv4Addr. +func (ipv4 IPv4Addr) Equal(sa SockAddr) bool { + ipv4b, ok := sa.(IPv4Addr) + if !ok { + return false + } + + if ipv4.Port != ipv4b.Port { + return false + } + + if ipv4.Address != ipv4b.Address { + return false + } + + if ipv4.NetIPNet().String() != ipv4b.NetIPNet().String() { + return false + } + + return true +} + +// FirstUsable returns an IPv4Addr set to the first address following the +// network prefix. The first usable address in a network is normally the +// gateway and should not be used except by devices forwarding packets +// between two administratively distinct networks (i.e. a router). This +// function does not discriminate against first usable vs "first address that +// should be used." For example, FirstUsable() on "192.168.1.10/24" would +// return the address "192.168.1.1/24". +func (ipv4 IPv4Addr) FirstUsable() IPAddr { + addr := ipv4.NetworkAddress() + + // If /32, return the address itself. If /31 assume a point-to-point + // link and return the lower address. + if ipv4.Maskbits() < 31 { + addr++ + } + + return IPv4Addr{ + Address: IPv4Address(addr), + Mask: IPv4HostMask, + } +} + +// Host returns a copy of ipv4 with its mask set to /32 so that it can be +// used by DialPacketArgs(), DialStreamArgs(), ListenPacketArgs(), or +// ListenStreamArgs(). +func (ipv4 IPv4Addr) Host() IPAddr { + // Nothing should listen on a broadcast address. + return IPv4Addr{ + Address: ipv4.Address, + Mask: IPv4HostMask, + Port: ipv4.Port, + } +} + +// IPPort returns the Port number attached to the IPv4Addr +func (ipv4 IPv4Addr) IPPort() IPPort { + return ipv4.Port +} + +// LastUsable returns the last address before the broadcast address in a +// given network. +func (ipv4 IPv4Addr) LastUsable() IPAddr { + addr := ipv4.BroadcastAddress() + + // If /32, return the address itself. If /31 assume a point-to-point + // link and return the upper address. + if ipv4.Maskbits() < 31 { + addr-- + } + + return IPv4Addr{ + Address: IPv4Address(addr), + Mask: IPv4HostMask, + } +} + +// ListenPacketArgs returns the arguments required to be passed to +// net.ListenUDP(). If the Mask of ipv4 is not a /32, ListenPacketArgs() +// will fail. See Host() to create an IPv4Addr with its mask set to /32. +func (ipv4 IPv4Addr) ListenPacketArgs() (network, listenArgs string) { + if ipv4.Mask != IPv4HostMask { + return "udp4", "" + } + return "udp4", fmt.Sprintf("%s:%d", ipv4.NetIP().String(), ipv4.Port) +} + +// ListenStreamArgs returns the arguments required to be passed to +// net.ListenTCP(). If the Mask of ipv4 is not a /32, ListenStreamArgs() +// will fail. See Host() to create an IPv4Addr with its mask set to /32. +func (ipv4 IPv4Addr) ListenStreamArgs() (network, listenArgs string) { + if ipv4.Mask != IPv4HostMask { + return "tcp4", "" + } + return "tcp4", fmt.Sprintf("%s:%d", ipv4.NetIP().String(), ipv4.Port) +} + +// Maskbits returns the number of network mask bits in a given IPv4Addr. For +// example, the Maskbits() of "192.168.1.1/24" would return 24. +func (ipv4 IPv4Addr) Maskbits() int { + mask := make(net.IPMask, IPv4len) + binary.BigEndian.PutUint32(mask, uint32(ipv4.Mask)) + maskOnes, _ := mask.Size() + return maskOnes +} + +// MustIPv4Addr is a helper method that must return an IPv4Addr or panic on +// invalid input. +func MustIPv4Addr(addr string) IPv4Addr { + ipv4, err := NewIPv4Addr(addr) + if err != nil { + panic(fmt.Sprintf("Unable to create an IPv4Addr from %+q: %v", addr, err)) + } + return ipv4 +} + +// NetIP returns the address as a net.IP (address is always presized to +// IPv4). +func (ipv4 IPv4Addr) NetIP() *net.IP { + x := make(net.IP, IPv4len) + binary.BigEndian.PutUint32(x, uint32(ipv4.Address)) + return &x +} + +// NetIPMask create a new net.IPMask from the IPv4Addr. +func (ipv4 IPv4Addr) NetIPMask() *net.IPMask { + ipv4Mask := net.IPMask{} + ipv4Mask = make(net.IPMask, IPv4len) + binary.BigEndian.PutUint32(ipv4Mask, uint32(ipv4.Mask)) + return &ipv4Mask +} + +// NetIPNet create a new net.IPNet from the IPv4Addr. +func (ipv4 IPv4Addr) NetIPNet() *net.IPNet { + ipv4net := &net.IPNet{} + ipv4net.IP = make(net.IP, IPv4len) + binary.BigEndian.PutUint32(ipv4net.IP, uint32(ipv4.NetworkAddress())) + ipv4net.Mask = *ipv4.NetIPMask() + return ipv4net +} + +// Network returns the network prefix or network address for a given network. +func (ipv4 IPv4Addr) Network() IPAddr { + return IPv4Addr{ + Address: IPv4Address(ipv4.NetworkAddress()), + Mask: ipv4.Mask, + } +} + +// NetworkAddress returns an IPv4Network of the IPv4Addr's network address. +func (ipv4 IPv4Addr) NetworkAddress() IPv4Network { + return IPv4Network(uint32(ipv4.Address) & uint32(ipv4.Mask)) +} + +// Octets returns a slice of the four octets in an IPv4Addr's Address. The +// order of the bytes is big endian. +func (ipv4 IPv4Addr) Octets() []int { + return []int{ + int(ipv4.Address >> 24), + int((ipv4.Address >> 16) & 0xff), + int((ipv4.Address >> 8) & 0xff), + int(ipv4.Address & 0xff), + } +} + +// String returns a string representation of the IPv4Addr +func (ipv4 IPv4Addr) String() string { + if ipv4.Port != 0 { + return fmt.Sprintf("%s:%d", ipv4.NetIP().String(), ipv4.Port) + } + + if ipv4.Maskbits() == 32 { + return ipv4.NetIP().String() + } + + return fmt.Sprintf("%s/%d", ipv4.NetIP().String(), ipv4.Maskbits()) +} + +// Type is used as a type switch and returns TypeIPv4 +func (IPv4Addr) Type() SockAddrType { + return TypeIPv4 +} + +// IPv4AddrAttr returns a string representation of an attribute for the given +// IPv4Addr. +func IPv4AddrAttr(ipv4 IPv4Addr, selector AttrName) string { + fn, found := ipv4AddrAttrMap[selector] + if !found { + return "" + } + + return fn(ipv4) +} + +// IPv4Attrs returns a list of attributes supported by the IPv4Addr type +func IPv4Attrs() []AttrName { + return ipv4AddrAttrs +} + +// ipv4AddrInit is called once at init() +func ipv4AddrInit() { + // Sorted for human readability + ipv4AddrAttrs = []AttrName{ + "size", // Same position as in IPv6 for output consistency + "broadcast", + "uint32", + } + + ipv4AddrAttrMap = map[AttrName]func(ipv4 IPv4Addr) string{ + "broadcast": func(ipv4 IPv4Addr) string { + return ipv4.Broadcast().String() + }, + "size": func(ipv4 IPv4Addr) string { + return fmt.Sprintf("%d", 1< 2 && ipv6Str[0] == '[' && ipv6Str[len(ipv6Str)-1] == ']' { + ipv6Str = ipv6Str[1 : len(ipv6Str)-1] + } + ip := net.ParseIP(ipv6Str) + if ip != nil { + ipv6 := ip.To16() + if ipv6 == nil { + return IPv6Addr{}, fmt.Errorf("Unable to string convert %+q to a 16byte IPv6 address", ipv6Str) + } + + ipv6BigIntAddr := new(big.Int) + ipv6BigIntAddr.SetBytes(ipv6) + + ipv6BigIntMask := new(big.Int) + ipv6BigIntMask.Set(ipv6HostMask) + + return IPv6Addr{ + Address: IPv6Address(ipv6BigIntAddr), + Mask: IPv6Mask(ipv6BigIntMask), + }, nil + } + + // Parse as an IPv6 CIDR + ipAddr, network, err := net.ParseCIDR(ipv6Str) + if err == nil { + ipv6 := ipAddr.To16() + if ipv6 == nil { + return IPv6Addr{}, fmt.Errorf("Unable to convert %+q to a 16byte IPv6 address", ipv6Str) + } + + ipv6BigIntAddr := new(big.Int) + ipv6BigIntAddr.SetBytes(ipv6) + + ipv6BigIntMask := new(big.Int) + ipv6BigIntMask.SetBytes(network.Mask) + + ipv6Addr := IPv6Addr{ + Address: IPv6Address(ipv6BigIntAddr), + Mask: IPv6Mask(ipv6BigIntMask), + } + return ipv6Addr, nil + } + + return IPv6Addr{}, fmt.Errorf("Unable to parse %+q to an IPv6 address: %v", ipv6Str, err) +} + +// AddressBinString returns a string with the IPv6Addr's Address represented +// as a sequence of '0' and '1' characters. This method is useful for +// debugging or by operators who want to inspect an address. +func (ipv6 IPv6Addr) AddressBinString() string { + bi := big.Int(*ipv6.Address) + return fmt.Sprintf("%0128s", bi.Text(2)) +} + +// AddressHexString returns a string with the IPv6Addr address represented as +// a sequence of hex characters. This method is useful for debugging or by +// operators who want to inspect an address. +func (ipv6 IPv6Addr) AddressHexString() string { + bi := big.Int(*ipv6.Address) + return fmt.Sprintf("%032s", bi.Text(16)) +} + +// CmpAddress follows the Cmp() standard protocol and returns: +// +// - -1 If the receiver should sort first because its address is lower than arg +// - 0 if the SockAddr arg equal to the receiving IPv6Addr or the argument is of a +// different type. +// - 1 If the argument should sort first. +func (ipv6 IPv6Addr) CmpAddress(sa SockAddr) int { + ipv6b, ok := sa.(IPv6Addr) + if !ok { + return sortDeferDecision + } + + ipv6aBigInt := new(big.Int) + ipv6aBigInt.Set(ipv6.Address) + ipv6bBigInt := new(big.Int) + ipv6bBigInt.Set(ipv6b.Address) + + return ipv6aBigInt.Cmp(ipv6bBigInt) +} + +// CmpPort follows the Cmp() standard protocol and returns: +// +// - -1 If the receiver should sort first because its port is lower than arg +// - 0 if the SockAddr arg's port number is equal to the receiving IPv6Addr, +// regardless of type. +// - 1 If the argument should sort first. +func (ipv6 IPv6Addr) CmpPort(sa SockAddr) int { + var saPort IPPort + switch v := sa.(type) { + case IPv4Addr: + saPort = v.Port + case IPv6Addr: + saPort = v.Port + default: + return sortDeferDecision + } + + switch { + case ipv6.Port == saPort: + return sortDeferDecision + case ipv6.Port < saPort: + return sortReceiverBeforeArg + default: + return sortArgBeforeReceiver + } +} + +// CmpRFC follows the Cmp() standard protocol and returns: +// +// - -1 If the receiver should sort first because it belongs to the RFC and its +// arg does not +// - 0 if the receiver and arg both belong to the same RFC or neither do. +// - 1 If the arg belongs to the RFC but receiver does not. +func (ipv6 IPv6Addr) CmpRFC(rfcNum uint, sa SockAddr) int { + recvInRFC := IsRFC(rfcNum, ipv6) + ipv6b, ok := sa.(IPv6Addr) + if !ok { + // If the receiver is part of the desired RFC and the SockAddr + // argument is not, sort receiver before the non-IPv6 SockAddr. + // Conversely, if the receiver is not part of the RFC, punt on + // sorting and leave it for the next sorter. + if recvInRFC { + return sortReceiverBeforeArg + } else { + return sortDeferDecision + } + } + + argInRFC := IsRFC(rfcNum, ipv6b) + switch { + case (recvInRFC && argInRFC), (!recvInRFC && !argInRFC): + // If a and b both belong to the RFC, or neither belong to + // rfcNum, defer sorting to the next sorter. + return sortDeferDecision + case recvInRFC && !argInRFC: + return sortReceiverBeforeArg + default: + return sortArgBeforeReceiver + } +} + +// Contains returns true if the SockAddr is contained within the receiver. +func (ipv6 IPv6Addr) Contains(sa SockAddr) bool { + ipv6b, ok := sa.(IPv6Addr) + if !ok { + return false + } + + return ipv6.ContainsNetwork(ipv6b) +} + +// ContainsAddress returns true if the IPv6Address is contained within the +// receiver. +func (ipv6 IPv6Addr) ContainsAddress(x IPv6Address) bool { + xAddr := IPv6Addr{ + Address: x, + Mask: ipv6HostMask, + } + + { + xIPv6 := xAddr.FirstUsable().(IPv6Addr) + yIPv6 := ipv6.FirstUsable().(IPv6Addr) + if xIPv6.CmpAddress(yIPv6) >= 1 { + return false + } + } + + { + xIPv6 := xAddr.LastUsable().(IPv6Addr) + yIPv6 := ipv6.LastUsable().(IPv6Addr) + if xIPv6.CmpAddress(yIPv6) <= -1 { + return false + } + } + return true +} + +// ContainsNetwork returns true if the network from IPv6Addr is contained within +// the receiver. +func (x IPv6Addr) ContainsNetwork(y IPv6Addr) bool { + { + xIPv6 := x.FirstUsable().(IPv6Addr) + yIPv6 := y.FirstUsable().(IPv6Addr) + if ret := xIPv6.CmpAddress(yIPv6); ret >= 1 { + return false + } + } + + { + xIPv6 := x.LastUsable().(IPv6Addr) + yIPv6 := y.LastUsable().(IPv6Addr) + if ret := xIPv6.CmpAddress(yIPv6); ret <= -1 { + return false + } + } + return true +} + +// DialPacketArgs returns the arguments required to be passed to +// net.DialUDP(). If the Mask of ipv6 is not a /128 or the Port is 0, +// DialPacketArgs() will fail. See Host() to create an IPv6Addr with its +// mask set to /128. +func (ipv6 IPv6Addr) DialPacketArgs() (network, dialArgs string) { + ipv6Mask := big.Int(*ipv6.Mask) + if ipv6Mask.Cmp(ipv6HostMask) != 0 || ipv6.Port == 0 { + return "udp6", "" + } + return "udp6", fmt.Sprintf("[%s]:%d", ipv6.NetIP().String(), ipv6.Port) +} + +// DialStreamArgs returns the arguments required to be passed to +// net.DialTCP(). If the Mask of ipv6 is not a /128 or the Port is 0, +// DialStreamArgs() will fail. See Host() to create an IPv6Addr with its +// mask set to /128. +func (ipv6 IPv6Addr) DialStreamArgs() (network, dialArgs string) { + ipv6Mask := big.Int(*ipv6.Mask) + if ipv6Mask.Cmp(ipv6HostMask) != 0 || ipv6.Port == 0 { + return "tcp6", "" + } + return "tcp6", fmt.Sprintf("[%s]:%d", ipv6.NetIP().String(), ipv6.Port) +} + +// Equal returns true if a SockAddr is equal to the receiving IPv4Addr. +func (ipv6a IPv6Addr) Equal(sa SockAddr) bool { + ipv6b, ok := sa.(IPv6Addr) + if !ok { + return false + } + + if ipv6a.NetIP().String() != ipv6b.NetIP().String() { + return false + } + + if ipv6a.NetIPNet().String() != ipv6b.NetIPNet().String() { + return false + } + + if ipv6a.Port != ipv6b.Port { + return false + } + + return true +} + +// FirstUsable returns an IPv6Addr set to the first address following the +// network prefix. The first usable address in a network is normally the +// gateway and should not be used except by devices forwarding packets +// between two administratively distinct networks (i.e. a router). This +// function does not discriminate against first usable vs "first address that +// should be used." For example, FirstUsable() on "2001:0db8::0003/64" would +// return "2001:0db8::00011". +func (ipv6 IPv6Addr) FirstUsable() IPAddr { + return IPv6Addr{ + Address: IPv6Address(ipv6.NetworkAddress()), + Mask: ipv6HostMask, + } +} + +// Host returns a copy of ipv6 with its mask set to /128 so that it can be +// used by DialPacketArgs(), DialStreamArgs(), ListenPacketArgs(), or +// ListenStreamArgs(). +func (ipv6 IPv6Addr) Host() IPAddr { + // Nothing should listen on a broadcast address. + return IPv6Addr{ + Address: ipv6.Address, + Mask: ipv6HostMask, + Port: ipv6.Port, + } +} + +// IPPort returns the Port number attached to the IPv6Addr +func (ipv6 IPv6Addr) IPPort() IPPort { + return ipv6.Port +} + +// LastUsable returns the last address in a given network. +func (ipv6 IPv6Addr) LastUsable() IPAddr { + addr := new(big.Int) + addr.Set(ipv6.Address) + + mask := new(big.Int) + mask.Set(ipv6.Mask) + + negMask := new(big.Int) + negMask.Xor(ipv6HostMask, mask) + + lastAddr := new(big.Int) + lastAddr.And(addr, mask) + lastAddr.Or(lastAddr, negMask) + + return IPv6Addr{ + Address: IPv6Address(lastAddr), + Mask: ipv6HostMask, + } +} + +// ListenPacketArgs returns the arguments required to be passed to +// net.ListenUDP(). If the Mask of ipv6 is not a /128, ListenPacketArgs() +// will fail. See Host() to create an IPv6Addr with its mask set to /128. +func (ipv6 IPv6Addr) ListenPacketArgs() (network, listenArgs string) { + ipv6Mask := big.Int(*ipv6.Mask) + if ipv6Mask.Cmp(ipv6HostMask) != 0 { + return "udp6", "" + } + return "udp6", fmt.Sprintf("[%s]:%d", ipv6.NetIP().String(), ipv6.Port) +} + +// ListenStreamArgs returns the arguments required to be passed to +// net.ListenTCP(). If the Mask of ipv6 is not a /128, ListenStreamArgs() +// will fail. See Host() to create an IPv6Addr with its mask set to /128. +func (ipv6 IPv6Addr) ListenStreamArgs() (network, listenArgs string) { + ipv6Mask := big.Int(*ipv6.Mask) + if ipv6Mask.Cmp(ipv6HostMask) != 0 { + return "tcp6", "" + } + return "tcp6", fmt.Sprintf("[%s]:%d", ipv6.NetIP().String(), ipv6.Port) +} + +// Maskbits returns the number of network mask bits in a given IPv6Addr. For +// example, the Maskbits() of "2001:0db8::0003/64" would return 64. +func (ipv6 IPv6Addr) Maskbits() int { + maskOnes, _ := ipv6.NetIPNet().Mask.Size() + + return maskOnes +} + +// MustIPv6Addr is a helper method that must return an IPv6Addr or panic on +// invalid input. +func MustIPv6Addr(addr string) IPv6Addr { + ipv6, err := NewIPv6Addr(addr) + if err != nil { + panic(fmt.Sprintf("Unable to create an IPv6Addr from %+q: %v", addr, err)) + } + return ipv6 +} + +// NetIP returns the address as a net.IP. +func (ipv6 IPv6Addr) NetIP() *net.IP { + return bigIntToNetIPv6(ipv6.Address) +} + +// NetIPMask create a new net.IPMask from the IPv6Addr. +func (ipv6 IPv6Addr) NetIPMask() *net.IPMask { + ipv6Mask := make(net.IPMask, IPv6len) + m := big.Int(*ipv6.Mask) + copy(ipv6Mask, m.Bytes()) + return &ipv6Mask +} + +// Network returns a pointer to the net.IPNet within IPv4Addr receiver. +func (ipv6 IPv6Addr) NetIPNet() *net.IPNet { + ipv6net := &net.IPNet{} + ipv6net.IP = make(net.IP, IPv6len) + copy(ipv6net.IP, *ipv6.NetIP()) + ipv6net.Mask = *ipv6.NetIPMask() + return ipv6net +} + +// Network returns the network prefix or network address for a given network. +func (ipv6 IPv6Addr) Network() IPAddr { + return IPv6Addr{ + Address: IPv6Address(ipv6.NetworkAddress()), + Mask: ipv6.Mask, + } +} + +// NetworkAddress returns an IPv6Network of the IPv6Addr's network address. +func (ipv6 IPv6Addr) NetworkAddress() IPv6Network { + addr := new(big.Int) + addr.SetBytes((*ipv6.Address).Bytes()) + + mask := new(big.Int) + mask.SetBytes(*ipv6.NetIPMask()) + + netAddr := new(big.Int) + netAddr.And(addr, mask) + + return IPv6Network(netAddr) +} + +// Octets returns a slice of the 16 octets in an IPv6Addr's Address. The +// order of the bytes is big endian. +func (ipv6 IPv6Addr) Octets() []int { + x := make([]int, IPv6len) + for i, b := range *bigIntToNetIPv6(ipv6.Address) { + x[i] = int(b) + } + + return x +} + +// String returns a string representation of the IPv6Addr +func (ipv6 IPv6Addr) String() string { + if ipv6.Port != 0 { + return fmt.Sprintf("[%s]:%d", ipv6.NetIP().String(), ipv6.Port) + } + + if ipv6.Maskbits() == 128 { + return ipv6.NetIP().String() + } + + return fmt.Sprintf("%s/%d", ipv6.NetIP().String(), ipv6.Maskbits()) +} + +// Type is used as a type switch and returns TypeIPv6 +func (IPv6Addr) Type() SockAddrType { + return TypeIPv6 +} + +// IPv6Attrs returns a list of attributes supported by the IPv6Addr type +func IPv6Attrs() []AttrName { + return ipv6AddrAttrs +} + +// IPv6AddrAttr returns a string representation of an attribute for the given +// IPv6Addr. +func IPv6AddrAttr(ipv6 IPv6Addr, selector AttrName) string { + fn, found := ipv6AddrAttrMap[selector] + if !found { + return "" + } + + return fn(ipv6) +} + +// ipv6AddrInit is called once at init() +func ipv6AddrInit() { + // Sorted for human readability + ipv6AddrAttrs = []AttrName{ + "size", // Same position as in IPv6 for output consistency + "uint128", + } + + ipv6AddrAttrMap = map[AttrName]func(ipv6 IPv6Addr) string{ + "size": func(ipv6 IPv6Addr) string { + netSize := big.NewInt(1) + netSize = netSize.Lsh(netSize, uint(IPv6len*8-ipv6.Maskbits())) + return netSize.Text(10) + }, + "uint128": func(ipv6 IPv6Addr) string { + b := big.Int(*ipv6.Address) + return b.Text(10) + }, + } +} + +// bigIntToNetIPv6 is a helper function that correctly returns a net.IP with the +// correctly padded values. +func bigIntToNetIPv6(bi *big.Int) *net.IP { + x := make(net.IP, IPv6len) + ipv6Bytes := bi.Bytes() + + // It's possibe for ipv6Bytes to be less than IPv6len bytes in size. If + // they are different sizes we to pad the size of response. + if len(ipv6Bytes) < IPv6len { + buf := new(bytes.Buffer) + buf.Grow(IPv6len) + + for i := len(ipv6Bytes); i < IPv6len; i++ { + if err := binary.Write(buf, binary.BigEndian, byte(0)); err != nil { + panic(fmt.Sprintf("Unable to pad byte %d of input %v: %v", i, bi, err)) + } + } + + for _, b := range ipv6Bytes { + if err := binary.Write(buf, binary.BigEndian, b); err != nil { + panic(fmt.Sprintf("Unable to preserve endianness of input %v: %v", bi, err)) + } + } + + ipv6Bytes = buf.Bytes() + } + i := copy(x, ipv6Bytes) + if i != IPv6len { + panic("IPv6 wrong size") + } + return &x +} diff --git a/vendor/github.com/hashicorp/go-sockaddr/rfc.go b/vendor/github.com/hashicorp/go-sockaddr/rfc.go new file mode 100644 index 000000000..02e188f6f --- /dev/null +++ b/vendor/github.com/hashicorp/go-sockaddr/rfc.go @@ -0,0 +1,948 @@ +package sockaddr + +// ForwardingBlacklist is a faux RFC that includes a list of non-forwardable IP +// blocks. +const ForwardingBlacklist = 4294967295 +const ForwardingBlacklistRFC = "4294967295" + +// IsRFC tests to see if an SockAddr matches the specified RFC +func IsRFC(rfcNum uint, sa SockAddr) bool { + rfcNetMap := KnownRFCs() + rfcNets, ok := rfcNetMap[rfcNum] + if !ok { + return false + } + + var contained bool + for _, rfcNet := range rfcNets { + if rfcNet.Contains(sa) { + contained = true + break + } + } + return contained +} + +// KnownRFCs returns an initial set of known RFCs. +// +// NOTE (sean@): As this list evolves over time, please submit patches to keep +// this list current. If something isn't right, inquire, as it may just be a +// bug on my part. Some of the inclusions were based on my judgement as to what +// would be a useful value (e.g. RFC3330). +// +// Useful resources: +// +// * https://www.iana.org/assignments/ipv6-address-space/ipv6-address-space.xhtml +// * https://www.iana.org/assignments/ipv6-unicast-address-assignments/ipv6-unicast-address-assignments.xhtml +// * https://www.iana.org/assignments/ipv6-address-space/ipv6-address-space.xhtml +func KnownRFCs() map[uint]SockAddrs { + // NOTE(sean@): Multiple SockAddrs per RFC lend themselves well to a + // RADIX tree, but `ENOTIME`. Patches welcome. + return map[uint]SockAddrs{ + 919: { + // [RFC919] Broadcasting Internet Datagrams + MustIPv4Addr("255.255.255.255/32"), // [RFC1122], §7 Broadcast IP Addressing - Proposed Standards + }, + 1122: { + // [RFC1122] Requirements for Internet Hosts -- Communication Layers + MustIPv4Addr("0.0.0.0/8"), // [RFC1122], §3.2.1.3 + MustIPv4Addr("127.0.0.0/8"), // [RFC1122], §3.2.1.3 + }, + 1112: { + // [RFC1112] Host Extensions for IP Multicasting + MustIPv4Addr("224.0.0.0/4"), // [RFC1112], §4 Host Group Addresses + }, + 1918: { + // [RFC1918] Address Allocation for Private Internets + MustIPv4Addr("10.0.0.0/8"), + MustIPv4Addr("172.16.0.0/12"), + MustIPv4Addr("192.168.0.0/16"), + }, + 2544: { + // [RFC2544] Benchmarking Methodology for Network + // Interconnect Devices + MustIPv4Addr("198.18.0.0/15"), + }, + 2765: { + // [RFC2765] Stateless IP/ICMP Translation Algorithm + // (SIIT) (obsoleted by RFCs 6145, which itself was + // later obsoleted by 7915). + + // [RFC2765], §2.1 Addresses + MustIPv6Addr("0:0:0:0:0:ffff:0:0/96"), + }, + 2928: { + // [RFC2928] Initial IPv6 Sub-TLA ID Assignments + MustIPv6Addr("2001::/16"), // Superblock + //MustIPv6Addr("2001:0000::/23"), // IANA + //MustIPv6Addr("2001:0200::/23"), // APNIC + //MustIPv6Addr("2001:0400::/23"), // ARIN + //MustIPv6Addr("2001:0600::/23"), // RIPE NCC + //MustIPv6Addr("2001:0800::/23"), // (future assignment) + // ... + //MustIPv6Addr("2001:FE00::/23"), // (future assignment) + }, + 3056: { // 6to4 address + // [RFC3056] Connection of IPv6 Domains via IPv4 Clouds + + // [RFC3056], §2 IPv6 Prefix Allocation + MustIPv6Addr("2002::/16"), + }, + 3068: { + // [RFC3068] An Anycast Prefix for 6to4 Relay Routers + // (obsolete by RFC7526) + + // [RFC3068], § 6to4 Relay anycast address + MustIPv4Addr("192.88.99.0/24"), + + // [RFC3068], §2.5 6to4 IPv6 relay anycast address + // + // NOTE: /120 == 128-(32-24) + MustIPv6Addr("2002:c058:6301::/120"), + }, + 3171: { + // [RFC3171] IANA Guidelines for IPv4 Multicast Address Assignments + MustIPv4Addr("224.0.0.0/4"), + }, + 3330: { + // [RFC3330] Special-Use IPv4 Addresses + + // Addresses in this block refer to source hosts on + // "this" network. Address 0.0.0.0/32 may be used as a + // source address for this host on this network; other + // addresses within 0.0.0.0/8 may be used to refer to + // specified hosts on this network [RFC1700, page 4]. + MustIPv4Addr("0.0.0.0/8"), + + // 10.0.0.0/8 - This block is set aside for use in + // private networks. Its intended use is documented in + // [RFC1918]. Addresses within this block should not + // appear on the public Internet. + MustIPv4Addr("10.0.0.0/8"), + + // 14.0.0.0/8 - This block is set aside for assignments + // to the international system of Public Data Networks + // [RFC1700, page 181]. The registry of assignments + // within this block can be accessed from the "Public + // Data Network Numbers" link on the web page at + // http://www.iana.org/numbers.html. Addresses within + // this block are assigned to users and should be + // treated as such. + + // 24.0.0.0/8 - This block was allocated in early 1996 + // for use in provisioning IP service over cable + // television systems. Although the IANA initially was + // involved in making assignments to cable operators, + // this responsibility was transferred to American + // Registry for Internet Numbers (ARIN) in May 2001. + // Addresses within this block are assigned in the + // normal manner and should be treated as such. + + // 39.0.0.0/8 - This block was used in the "Class A + // Subnet Experiment" that commenced in May 1995, as + // documented in [RFC1797]. The experiment has been + // completed and this block has been returned to the + // pool of addresses reserved for future allocation or + // assignment. This block therefore no longer has a + // special use and is subject to allocation to a + // Regional Internet Registry for assignment in the + // normal manner. + + // 127.0.0.0/8 - This block is assigned for use as the Internet host + // loopback address. A datagram sent by a higher level protocol to an + // address anywhere within this block should loop back inside the host. + // This is ordinarily implemented using only 127.0.0.1/32 for loopback, + // but no addresses within this block should ever appear on any network + // anywhere [RFC1700, page 5]. + MustIPv4Addr("127.0.0.0/8"), + + // 128.0.0.0/16 - This block, corresponding to the + // numerically lowest of the former Class B addresses, + // was initially and is still reserved by the IANA. + // Given the present classless nature of the IP address + // space, the basis for the reservation no longer + // applies and addresses in this block are subject to + // future allocation to a Regional Internet Registry for + // assignment in the normal manner. + + // 169.254.0.0/16 - This is the "link local" block. It + // is allocated for communication between hosts on a + // single link. Hosts obtain these addresses by + // auto-configuration, such as when a DHCP server may + // not be found. + MustIPv4Addr("169.254.0.0/16"), + + // 172.16.0.0/12 - This block is set aside for use in + // private networks. Its intended use is documented in + // [RFC1918]. Addresses within this block should not + // appear on the public Internet. + MustIPv4Addr("172.16.0.0/12"), + + // 191.255.0.0/16 - This block, corresponding to the numerically highest + // to the former Class B addresses, was initially and is still reserved + // by the IANA. Given the present classless nature of the IP address + // space, the basis for the reservation no longer applies and addresses + // in this block are subject to future allocation to a Regional Internet + // Registry for assignment in the normal manner. + + // 192.0.0.0/24 - This block, corresponding to the + // numerically lowest of the former Class C addresses, + // was initially and is still reserved by the IANA. + // Given the present classless nature of the IP address + // space, the basis for the reservation no longer + // applies and addresses in this block are subject to + // future allocation to a Regional Internet Registry for + // assignment in the normal manner. + + // 192.0.2.0/24 - This block is assigned as "TEST-NET" for use in + // documentation and example code. It is often used in conjunction with + // domain names example.com or example.net in vendor and protocol + // documentation. Addresses within this block should not appear on the + // public Internet. + MustIPv4Addr("192.0.2.0/24"), + + // 192.88.99.0/24 - This block is allocated for use as 6to4 relay + // anycast addresses, according to [RFC3068]. + MustIPv4Addr("192.88.99.0/24"), + + // 192.168.0.0/16 - This block is set aside for use in private networks. + // Its intended use is documented in [RFC1918]. Addresses within this + // block should not appear on the public Internet. + MustIPv4Addr("192.168.0.0/16"), + + // 198.18.0.0/15 - This block has been allocated for use + // in benchmark tests of network interconnect devices. + // Its use is documented in [RFC2544]. + MustIPv4Addr("198.18.0.0/15"), + + // 223.255.255.0/24 - This block, corresponding to the + // numerically highest of the former Class C addresses, + // was initially and is still reserved by the IANA. + // Given the present classless nature of the IP address + // space, the basis for the reservation no longer + // applies and addresses in this block are subject to + // future allocation to a Regional Internet Registry for + // assignment in the normal manner. + + // 224.0.0.0/4 - This block, formerly known as the Class + // D address space, is allocated for use in IPv4 + // multicast address assignments. The IANA guidelines + // for assignments from this space are described in + // [RFC3171]. + MustIPv4Addr("224.0.0.0/4"), + + // 240.0.0.0/4 - This block, formerly known as the Class E address + // space, is reserved. The "limited broadcast" destination address + // 255.255.255.255 should never be forwarded outside the (sub-)net of + // the source. The remainder of this space is reserved + // for future use. [RFC1700, page 4] + MustIPv4Addr("240.0.0.0/4"), + }, + 3849: { + // [RFC3849] IPv6 Address Prefix Reserved for Documentation + MustIPv6Addr("2001:db8::/32"), // [RFC3849], §4 IANA Considerations + }, + 3927: { + // [RFC3927] Dynamic Configuration of IPv4 Link-Local Addresses + MustIPv4Addr("169.254.0.0/16"), // [RFC3927], §2.1 Link-Local Address Selection + }, + 4038: { + // [RFC4038] Application Aspects of IPv6 Transition + + // [RFC4038], §4.2. IPv6 Applications in a Dual-Stack Node + MustIPv6Addr("0:0:0:0:0:ffff::/96"), + }, + 4193: { + // [RFC4193] Unique Local IPv6 Unicast Addresses + MustIPv6Addr("fc00::/7"), + }, + 4291: { + // [RFC4291] IP Version 6 Addressing Architecture + + // [RFC4291], §2.5.2 The Unspecified Address + MustIPv6Addr("::/128"), + + // [RFC4291], §2.5.3 The Loopback Address + MustIPv6Addr("::1/128"), + + // [RFC4291], §2.5.5.1. IPv4-Compatible IPv6 Address + MustIPv6Addr("::/96"), + + // [RFC4291], §2.5.5.2. IPv4-Mapped IPv6 Address + MustIPv6Addr("::ffff:0:0/96"), + + // [RFC4291], §2.5.6 Link-Local IPv6 Unicast Addresses + MustIPv6Addr("fe80::/10"), + + // [RFC4291], §2.5.7 Site-Local IPv6 Unicast Addresses + // (depreciated) + MustIPv6Addr("fec0::/10"), + + // [RFC4291], §2.7 Multicast Addresses + MustIPv6Addr("ff00::/8"), + + // IPv6 Multicast Information. + // + // In the following "table" below, `ff0x` is replaced + // with the following values depending on the scope of + // the query: + // + // IPv6 Multicast Scopes: + // * ff00/9 // reserved + // * ff01/9 // interface-local + // * ff02/9 // link-local + // * ff03/9 // realm-local + // * ff04/9 // admin-local + // * ff05/9 // site-local + // * ff08/9 // organization-local + // * ff0e/9 // global + // * ff0f/9 // reserved + // + // IPv6 Multicast Addresses: + // * ff0x::2 // All routers + // * ff02::5 // OSPFIGP + // * ff02::6 // OSPFIGP Designated Routers + // * ff02::9 // RIP Routers + // * ff02::a // EIGRP Routers + // * ff02::d // All PIM Routers + // * ff02::1a // All RPL Routers + // * ff0x::fb // mDNSv6 + // * ff0x::101 // All Network Time Protocol (NTP) servers + // * ff02::1:1 // Link Name + // * ff02::1:2 // All-dhcp-agents + // * ff02::1:3 // Link-local Multicast Name Resolution + // * ff05::1:3 // All-dhcp-servers + // * ff02::1:ff00:0/104 // Solicited-node multicast address. + // * ff02::2:ff00:0/104 // Node Information Queries + }, + 4380: { + // [RFC4380] Teredo: Tunneling IPv6 over UDP through + // Network Address Translations (NATs) + + // [RFC4380], §2.6 Global Teredo IPv6 Service Prefix + MustIPv6Addr("2001:0000::/32"), + }, + 4773: { + // [RFC4773] Administration of the IANA Special Purpose IPv6 Address Block + MustIPv6Addr("2001:0000::/23"), // IANA + }, + 4843: { + // [RFC4843] An IPv6 Prefix for Overlay Routable Cryptographic Hash Identifiers (ORCHID) + MustIPv6Addr("2001:10::/28"), // [RFC4843], §7 IANA Considerations + }, + 5180: { + // [RFC5180] IPv6 Benchmarking Methodology for Network Interconnect Devices + MustIPv6Addr("2001:0200::/48"), // [RFC5180], §8 IANA Considerations + }, + 5735: { + // [RFC5735] Special Use IPv4 Addresses + MustIPv4Addr("192.0.2.0/24"), // TEST-NET-1 + MustIPv4Addr("198.51.100.0/24"), // TEST-NET-2 + MustIPv4Addr("203.0.113.0/24"), // TEST-NET-3 + MustIPv4Addr("198.18.0.0/15"), // Benchmarks + }, + 5737: { + // [RFC5737] IPv4 Address Blocks Reserved for Documentation + MustIPv4Addr("192.0.2.0/24"), // TEST-NET-1 + MustIPv4Addr("198.51.100.0/24"), // TEST-NET-2 + MustIPv4Addr("203.0.113.0/24"), // TEST-NET-3 + }, + 6052: { + // [RFC6052] IPv6 Addressing of IPv4/IPv6 Translators + MustIPv6Addr("64:ff9b::/96"), // [RFC6052], §2.1. Well-Known Prefix + }, + 6333: { + // [RFC6333] Dual-Stack Lite Broadband Deployments Following IPv4 Exhaustion + MustIPv4Addr("192.0.0.0/29"), // [RFC6333], §5.7 Well-Known IPv4 Address + }, + 6598: { + // [RFC6598] IANA-Reserved IPv4 Prefix for Shared Address Space + MustIPv4Addr("100.64.0.0/10"), + }, + 6666: { + // [RFC6666] A Discard Prefix for IPv6 + MustIPv6Addr("0100::/64"), + }, + 6890: { + // [RFC6890] Special-Purpose IP Address Registries + + // From "RFC6890 §2.2.1 Information Requirements": + /* + The IPv4 and IPv6 Special-Purpose Address Registries maintain the + following information regarding each entry: + + o Address Block - A block of IPv4 or IPv6 addresses that has been + registered for a special purpose. + + o Name - A descriptive name for the special-purpose address block. + + o RFC - The RFC through which the special-purpose address block was + requested. + + o Allocation Date - The date upon which the special-purpose address + block was allocated. + + o Termination Date - The date upon which the allocation is to be + terminated. This field is applicable for limited-use allocations + only. + + o Source - A boolean value indicating whether an address from the + allocated special-purpose address block is valid when used as the + source address of an IP datagram that transits two devices. + + o Destination - A boolean value indicating whether an address from + the allocated special-purpose address block is valid when used as + the destination address of an IP datagram that transits two + devices. + + o Forwardable - A boolean value indicating whether a router may + forward an IP datagram whose destination address is drawn from the + allocated special-purpose address block between external + interfaces. + + o Global - A boolean value indicating whether an IP datagram whose + destination address is drawn from the allocated special-purpose + address block is forwardable beyond a specified administrative + domain. + + o Reserved-by-Protocol - A boolean value indicating whether the + special-purpose address block is reserved by IP, itself. This + value is "TRUE" if the RFC that created the special-purpose + address block requires all compliant IP implementations to behave + in a special way when processing packets either to or from + addresses contained by the address block. + + If the value of "Destination" is FALSE, the values of "Forwardable" + and "Global" must also be false. + */ + + /*+----------------------+----------------------------+ + * | Attribute | Value | + * +----------------------+----------------------------+ + * | Address Block | 0.0.0.0/8 | + * | Name | "This host on this network"| + * | RFC | [RFC1122], Section 3.2.1.3 | + * | Allocation Date | September 1981 | + * | Termination Date | N/A | + * | Source | True | + * | Destination | False | + * | Forwardable | False | + * | Global | False | + * | Reserved-by-Protocol | True | + * +----------------------+----------------------------+*/ + MustIPv4Addr("0.0.0.0/8"), + + /*+----------------------+---------------+ + * | Attribute | Value | + * +----------------------+---------------+ + * | Address Block | 10.0.0.0/8 | + * | Name | Private-Use | + * | RFC | [RFC1918] | + * | Allocation Date | February 1996 | + * | Termination Date | N/A | + * | Source | True | + * | Destination | True | + * | Forwardable | True | + * | Global | False | + * | Reserved-by-Protocol | False | + * +----------------------+---------------+ */ + MustIPv4Addr("10.0.0.0/8"), + + /*+----------------------+----------------------+ + | Attribute | Value | + +----------------------+----------------------+ + | Address Block | 100.64.0.0/10 | + | Name | Shared Address Space | + | RFC | [RFC6598] | + | Allocation Date | April 2012 | + | Termination Date | N/A | + | Source | True | + | Destination | True | + | Forwardable | True | + | Global | False | + | Reserved-by-Protocol | False | + +----------------------+----------------------+*/ + MustIPv4Addr("100.64.0.0/10"), + + /*+----------------------+----------------------------+ + | Attribute | Value | + +----------------------+----------------------------+ + | Address Block | 127.0.0.0/8 | + | Name | Loopback | + | RFC | [RFC1122], Section 3.2.1.3 | + | Allocation Date | September 1981 | + | Termination Date | N/A | + | Source | False [1] | + | Destination | False [1] | + | Forwardable | False [1] | + | Global | False [1] | + | Reserved-by-Protocol | True | + +----------------------+----------------------------+*/ + // [1] Several protocols have been granted exceptions to + // this rule. For examples, see [RFC4379] and + // [RFC5884]. + MustIPv4Addr("127.0.0.0/8"), + + /*+----------------------+----------------+ + | Attribute | Value | + +----------------------+----------------+ + | Address Block | 169.254.0.0/16 | + | Name | Link Local | + | RFC | [RFC3927] | + | Allocation Date | May 2005 | + | Termination Date | N/A | + | Source | True | + | Destination | True | + | Forwardable | False | + | Global | False | + | Reserved-by-Protocol | True | + +----------------------+----------------+*/ + MustIPv4Addr("169.254.0.0/16"), + + /*+----------------------+---------------+ + | Attribute | Value | + +----------------------+---------------+ + | Address Block | 172.16.0.0/12 | + | Name | Private-Use | + | RFC | [RFC1918] | + | Allocation Date | February 1996 | + | Termination Date | N/A | + | Source | True | + | Destination | True | + | Forwardable | True | + | Global | False | + | Reserved-by-Protocol | False | + +----------------------+---------------+*/ + MustIPv4Addr("172.16.0.0/12"), + + /*+----------------------+---------------------------------+ + | Attribute | Value | + +----------------------+---------------------------------+ + | Address Block | 192.0.0.0/24 [2] | + | Name | IETF Protocol Assignments | + | RFC | Section 2.1 of this document | + | Allocation Date | January 2010 | + | Termination Date | N/A | + | Source | False | + | Destination | False | + | Forwardable | False | + | Global | False | + | Reserved-by-Protocol | False | + +----------------------+---------------------------------+*/ + // [2] Not usable unless by virtue of a more specific + // reservation. + MustIPv4Addr("192.0.0.0/24"), + + /*+----------------------+--------------------------------+ + | Attribute | Value | + +----------------------+--------------------------------+ + | Address Block | 192.0.0.0/29 | + | Name | IPv4 Service Continuity Prefix | + | RFC | [RFC6333], [RFC7335] | + | Allocation Date | June 2011 | + | Termination Date | N/A | + | Source | True | + | Destination | True | + | Forwardable | True | + | Global | False | + | Reserved-by-Protocol | False | + +----------------------+--------------------------------+*/ + MustIPv4Addr("192.0.0.0/29"), + + /*+----------------------+----------------------------+ + | Attribute | Value | + +----------------------+----------------------------+ + | Address Block | 192.0.2.0/24 | + | Name | Documentation (TEST-NET-1) | + | RFC | [RFC5737] | + | Allocation Date | January 2010 | + | Termination Date | N/A | + | Source | False | + | Destination | False | + | Forwardable | False | + | Global | False | + | Reserved-by-Protocol | False | + +----------------------+----------------------------+*/ + MustIPv4Addr("192.0.2.0/24"), + + /*+----------------------+--------------------+ + | Attribute | Value | + +----------------------+--------------------+ + | Address Block | 192.88.99.0/24 | + | Name | 6to4 Relay Anycast | + | RFC | [RFC3068] | + | Allocation Date | June 2001 | + | Termination Date | N/A | + | Source | True | + | Destination | True | + | Forwardable | True | + | Global | True | + | Reserved-by-Protocol | False | + +----------------------+--------------------+*/ + MustIPv4Addr("192.88.99.0/24"), + + /*+----------------------+----------------+ + | Attribute | Value | + +----------------------+----------------+ + | Address Block | 192.168.0.0/16 | + | Name | Private-Use | + | RFC | [RFC1918] | + | Allocation Date | February 1996 | + | Termination Date | N/A | + | Source | True | + | Destination | True | + | Forwardable | True | + | Global | False | + | Reserved-by-Protocol | False | + +----------------------+----------------+*/ + MustIPv4Addr("192.168.0.0/16"), + + /*+----------------------+---------------+ + | Attribute | Value | + +----------------------+---------------+ + | Address Block | 198.18.0.0/15 | + | Name | Benchmarking | + | RFC | [RFC2544] | + | Allocation Date | March 1999 | + | Termination Date | N/A | + | Source | True | + | Destination | True | + | Forwardable | True | + | Global | False | + | Reserved-by-Protocol | False | + +----------------------+---------------+*/ + MustIPv4Addr("198.18.0.0/15"), + + /*+----------------------+----------------------------+ + | Attribute | Value | + +----------------------+----------------------------+ + | Address Block | 198.51.100.0/24 | + | Name | Documentation (TEST-NET-2) | + | RFC | [RFC5737] | + | Allocation Date | January 2010 | + | Termination Date | N/A | + | Source | False | + | Destination | False | + | Forwardable | False | + | Global | False | + | Reserved-by-Protocol | False | + +----------------------+----------------------------+*/ + MustIPv4Addr("198.51.100.0/24"), + + /*+----------------------+----------------------------+ + | Attribute | Value | + +----------------------+----------------------------+ + | Address Block | 203.0.113.0/24 | + | Name | Documentation (TEST-NET-3) | + | RFC | [RFC5737] | + | Allocation Date | January 2010 | + | Termination Date | N/A | + | Source | False | + | Destination | False | + | Forwardable | False | + | Global | False | + | Reserved-by-Protocol | False | + +----------------------+----------------------------+*/ + MustIPv4Addr("203.0.113.0/24"), + + /*+----------------------+----------------------+ + | Attribute | Value | + +----------------------+----------------------+ + | Address Block | 240.0.0.0/4 | + | Name | Reserved | + | RFC | [RFC1112], Section 4 | + | Allocation Date | August 1989 | + | Termination Date | N/A | + | Source | False | + | Destination | False | + | Forwardable | False | + | Global | False | + | Reserved-by-Protocol | True | + +----------------------+----------------------+*/ + MustIPv4Addr("240.0.0.0/4"), + + /*+----------------------+----------------------+ + | Attribute | Value | + +----------------------+----------------------+ + | Address Block | 255.255.255.255/32 | + | Name | Limited Broadcast | + | RFC | [RFC0919], Section 7 | + | Allocation Date | October 1984 | + | Termination Date | N/A | + | Source | False | + | Destination | True | + | Forwardable | False | + | Global | False | + | Reserved-by-Protocol | False | + +----------------------+----------------------+*/ + MustIPv4Addr("255.255.255.255/32"), + + /*+----------------------+------------------+ + | Attribute | Value | + +----------------------+------------------+ + | Address Block | ::1/128 | + | Name | Loopback Address | + | RFC | [RFC4291] | + | Allocation Date | February 2006 | + | Termination Date | N/A | + | Source | False | + | Destination | False | + | Forwardable | False | + | Global | False | + | Reserved-by-Protocol | True | + +----------------------+------------------+*/ + MustIPv6Addr("::1/128"), + + /*+----------------------+---------------------+ + | Attribute | Value | + +----------------------+---------------------+ + | Address Block | ::/128 | + | Name | Unspecified Address | + | RFC | [RFC4291] | + | Allocation Date | February 2006 | + | Termination Date | N/A | + | Source | True | + | Destination | False | + | Forwardable | False | + | Global | False | + | Reserved-by-Protocol | True | + +----------------------+---------------------+*/ + MustIPv6Addr("::/128"), + + /*+----------------------+---------------------+ + | Attribute | Value | + +----------------------+---------------------+ + | Address Block | 64:ff9b::/96 | + | Name | IPv4-IPv6 Translat. | + | RFC | [RFC6052] | + | Allocation Date | October 2010 | + | Termination Date | N/A | + | Source | True | + | Destination | True | + | Forwardable | True | + | Global | True | + | Reserved-by-Protocol | False | + +----------------------+---------------------+*/ + MustIPv6Addr("64:ff9b::/96"), + + /*+----------------------+---------------------+ + | Attribute | Value | + +----------------------+---------------------+ + | Address Block | ::ffff:0:0/96 | + | Name | IPv4-mapped Address | + | RFC | [RFC4291] | + | Allocation Date | February 2006 | + | Termination Date | N/A | + | Source | False | + | Destination | False | + | Forwardable | False | + | Global | False | + | Reserved-by-Protocol | True | + +----------------------+---------------------+*/ + MustIPv6Addr("::ffff:0:0/96"), + + /*+----------------------+----------------------------+ + | Attribute | Value | + +----------------------+----------------------------+ + | Address Block | 100::/64 | + | Name | Discard-Only Address Block | + | RFC | [RFC6666] | + | Allocation Date | June 2012 | + | Termination Date | N/A | + | Source | True | + | Destination | True | + | Forwardable | True | + | Global | False | + | Reserved-by-Protocol | False | + +----------------------+----------------------------+*/ + MustIPv6Addr("100::/64"), + + /*+----------------------+---------------------------+ + | Attribute | Value | + +----------------------+---------------------------+ + | Address Block | 2001::/23 | + | Name | IETF Protocol Assignments | + | RFC | [RFC2928] | + | Allocation Date | September 2000 | + | Termination Date | N/A | + | Source | False[1] | + | Destination | False[1] | + | Forwardable | False[1] | + | Global | False[1] | + | Reserved-by-Protocol | False | + +----------------------+---------------------------+*/ + // [1] Unless allowed by a more specific allocation. + MustIPv6Addr("2001::/16"), + + /*+----------------------+----------------+ + | Attribute | Value | + +----------------------+----------------+ + | Address Block | 2001::/32 | + | Name | TEREDO | + | RFC | [RFC4380] | + | Allocation Date | January 2006 | + | Termination Date | N/A | + | Source | True | + | Destination | True | + | Forwardable | True | + | Global | False | + | Reserved-by-Protocol | False | + +----------------------+----------------+*/ + // Covered by previous entry, included for completeness. + // + // MustIPv6Addr("2001::/16"), + + /*+----------------------+----------------+ + | Attribute | Value | + +----------------------+----------------+ + | Address Block | 2001:2::/48 | + | Name | Benchmarking | + | RFC | [RFC5180] | + | Allocation Date | April 2008 | + | Termination Date | N/A | + | Source | True | + | Destination | True | + | Forwardable | True | + | Global | False | + | Reserved-by-Protocol | False | + +----------------------+----------------+*/ + // Covered by previous entry, included for completeness. + // + // MustIPv6Addr("2001:2::/48"), + + /*+----------------------+---------------+ + | Attribute | Value | + +----------------------+---------------+ + | Address Block | 2001:db8::/32 | + | Name | Documentation | + | RFC | [RFC3849] | + | Allocation Date | July 2004 | + | Termination Date | N/A | + | Source | False | + | Destination | False | + | Forwardable | False | + | Global | False | + | Reserved-by-Protocol | False | + +----------------------+---------------+*/ + // Covered by previous entry, included for completeness. + // + // MustIPv6Addr("2001:db8::/32"), + + /*+----------------------+--------------+ + | Attribute | Value | + +----------------------+--------------+ + | Address Block | 2001:10::/28 | + | Name | ORCHID | + | RFC | [RFC4843] | + | Allocation Date | March 2007 | + | Termination Date | March 2014 | + | Source | False | + | Destination | False | + | Forwardable | False | + | Global | False | + | Reserved-by-Protocol | False | + +----------------------+--------------+*/ + // Covered by previous entry, included for completeness. + // + // MustIPv6Addr("2001:10::/28"), + + /*+----------------------+---------------+ + | Attribute | Value | + +----------------------+---------------+ + | Address Block | 2002::/16 [2] | + | Name | 6to4 | + | RFC | [RFC3056] | + | Allocation Date | February 2001 | + | Termination Date | N/A | + | Source | True | + | Destination | True | + | Forwardable | True | + | Global | N/A [2] | + | Reserved-by-Protocol | False | + +----------------------+---------------+*/ + // [2] See [RFC3056] for details. + MustIPv6Addr("2002::/16"), + + /*+----------------------+--------------+ + | Attribute | Value | + +----------------------+--------------+ + | Address Block | fc00::/7 | + | Name | Unique-Local | + | RFC | [RFC4193] | + | Allocation Date | October 2005 | + | Termination Date | N/A | + | Source | True | + | Destination | True | + | Forwardable | True | + | Global | False | + | Reserved-by-Protocol | False | + +----------------------+--------------+*/ + MustIPv6Addr("fc00::/7"), + + /*+----------------------+-----------------------+ + | Attribute | Value | + +----------------------+-----------------------+ + | Address Block | fe80::/10 | + | Name | Linked-Scoped Unicast | + | RFC | [RFC4291] | + | Allocation Date | February 2006 | + | Termination Date | N/A | + | Source | True | + | Destination | True | + | Forwardable | False | + | Global | False | + | Reserved-by-Protocol | True | + +----------------------+-----------------------+*/ + MustIPv6Addr("fe80::/10"), + }, + 7335: { + // [RFC7335] IPv4 Service Continuity Prefix + MustIPv4Addr("192.0.0.0/29"), // [RFC7335], §6 IANA Considerations + }, + ForwardingBlacklist: { // Pseudo-RFC + // Blacklist of non-forwardable IP blocks taken from RFC6890 + // + // TODO: the attributes for forwardable should be + // searcahble and embedded in the main list of RFCs + // above. + MustIPv4Addr("0.0.0.0/8"), + MustIPv4Addr("127.0.0.0/8"), + MustIPv4Addr("169.254.0.0/16"), + MustIPv4Addr("192.0.0.0/24"), + MustIPv4Addr("192.0.2.0/24"), + MustIPv4Addr("198.51.100.0/24"), + MustIPv4Addr("203.0.113.0/24"), + MustIPv4Addr("240.0.0.0/4"), + MustIPv4Addr("255.255.255.255/32"), + MustIPv6Addr("::1/128"), + MustIPv6Addr("::/128"), + MustIPv6Addr("::ffff:0:0/96"), + + // There is no way of expressing a whitelist per RFC2928 + // atm without creating a negative mask, which I don't + // want to do atm. + //MustIPv6Addr("2001::/23"), + + MustIPv6Addr("2001:db8::/32"), + MustIPv6Addr("2001:10::/28"), + MustIPv6Addr("fe80::/10"), + }, + } +} + +// VisitAllRFCs iterates over all known RFCs and calls the visitor +func VisitAllRFCs(fn func(rfcNum uint, sockaddrs SockAddrs)) { + rfcNetMap := KnownRFCs() + + // Blacklist of faux-RFCs. Don't show the world that we're abusing the + // RFC system in this library. + rfcBlacklist := map[uint]struct{}{ + ForwardingBlacklist: {}, + } + + for rfcNum, sas := range rfcNetMap { + if _, found := rfcBlacklist[rfcNum]; !found { + fn(rfcNum, sas) + } + } +} diff --git a/vendor/github.com/hashicorp/go-sockaddr/route_info.go b/vendor/github.com/hashicorp/go-sockaddr/route_info.go new file mode 100644 index 000000000..2a3ee1db9 --- /dev/null +++ b/vendor/github.com/hashicorp/go-sockaddr/route_info.go @@ -0,0 +1,19 @@ +package sockaddr + +// RouteInterface specifies an interface for obtaining memoized route table and +// network information from a given OS. +type RouteInterface interface { + // GetDefaultInterfaceName returns the name of the interface that has a + // default route or an error and an empty string if a problem was + // encountered. + GetDefaultInterfaceName() (string, error) +} + +// VisitCommands visits each command used by the platform-specific RouteInfo +// implementation. +func (ri routeInfo) VisitCommands(fn func(name string, cmd []string)) { + for k, v := range ri.cmds { + cmds := append([]string(nil), v...) + fn(k, cmds) + } +} diff --git a/vendor/github.com/hashicorp/go-sockaddr/route_info_android.go b/vendor/github.com/hashicorp/go-sockaddr/route_info_android.go new file mode 100644 index 000000000..9885915a6 --- /dev/null +++ b/vendor/github.com/hashicorp/go-sockaddr/route_info_android.go @@ -0,0 +1,34 @@ +package sockaddr + +import ( + "errors" + "os/exec" +) + +type routeInfo struct { + cmds map[string][]string +} + +// NewRouteInfo returns a Android-specific implementation of the RouteInfo +// interface. +func NewRouteInfo() (routeInfo, error) { + return routeInfo{ + cmds: map[string][]string{"ip": {"/system/bin/ip", "route", "get", "8.8.8.8"}}, + }, nil +} + +// GetDefaultInterfaceName returns the interface name attached to the default +// route on the default interface. +func (ri routeInfo) GetDefaultInterfaceName() (string, error) { + out, err := exec.Command(ri.cmds["ip"][0], ri.cmds["ip"][1:]...).Output() + if err != nil { + return "", err + } + + + var ifName string + if ifName, err = parseDefaultIfNameFromIPCmdAndroid(string(out)); err != nil { + return "", errors.New("No default interface found") + } + return ifName, nil +} diff --git a/vendor/github.com/hashicorp/go-sockaddr/route_info_bsd.go b/vendor/github.com/hashicorp/go-sockaddr/route_info_bsd.go new file mode 100644 index 000000000..705757abc --- /dev/null +++ b/vendor/github.com/hashicorp/go-sockaddr/route_info_bsd.go @@ -0,0 +1,36 @@ +// +build darwin dragonfly freebsd netbsd openbsd + +package sockaddr + +import "os/exec" + +var cmds map[string][]string = map[string][]string{ + "route": {"/sbin/route", "-n", "get", "default"}, +} + +type routeInfo struct { + cmds map[string][]string +} + +// NewRouteInfo returns a BSD-specific implementation of the RouteInfo +// interface. +func NewRouteInfo() (routeInfo, error) { + return routeInfo{ + cmds: cmds, + }, nil +} + +// GetDefaultInterfaceName returns the interface name attached to the default +// route on the default interface. +func (ri routeInfo) GetDefaultInterfaceName() (string, error) { + out, err := exec.Command(cmds["route"][0], cmds["route"][1:]...).Output() + if err != nil { + return "", err + } + + var ifName string + if ifName, err = parseDefaultIfNameFromRoute(string(out)); err != nil { + return "", err + } + return ifName, nil +} diff --git a/vendor/github.com/hashicorp/go-sockaddr/route_info_default.go b/vendor/github.com/hashicorp/go-sockaddr/route_info_default.go new file mode 100644 index 000000000..d1b009f65 --- /dev/null +++ b/vendor/github.com/hashicorp/go-sockaddr/route_info_default.go @@ -0,0 +1,10 @@ +// +build android nacl plan9 + +package sockaddr + +import "errors" + +// getDefaultIfName is the default interface function for unsupported platforms. +func getDefaultIfName() (string, error) { + return "", errors.New("No default interface found (unsupported platform)") +} diff --git a/vendor/github.com/hashicorp/go-sockaddr/route_info_linux.go b/vendor/github.com/hashicorp/go-sockaddr/route_info_linux.go new file mode 100644 index 000000000..b62ce6ecb --- /dev/null +++ b/vendor/github.com/hashicorp/go-sockaddr/route_info_linux.go @@ -0,0 +1,42 @@ +// +build !android + +package sockaddr + +import ( + "errors" + "os/exec" +) + +type routeInfo struct { + cmds map[string][]string +} + +// NewRouteInfo returns a Linux-specific implementation of the RouteInfo +// interface. +func NewRouteInfo() (routeInfo, error) { + // CoreOS Container Linux moved ip to /usr/bin/ip, so look it up on + // $PATH and fallback to /sbin/ip on error. + path, _ := exec.LookPath("ip") + if path == "" { + path = "/sbin/ip" + } + + return routeInfo{ + cmds: map[string][]string{"ip": {path, "route"}}, + }, nil +} + +// GetDefaultInterfaceName returns the interface name attached to the default +// route on the default interface. +func (ri routeInfo) GetDefaultInterfaceName() (string, error) { + out, err := exec.Command(ri.cmds["ip"][0], ri.cmds["ip"][1:]...).Output() + if err != nil { + return "", err + } + + var ifName string + if ifName, err = parseDefaultIfNameFromIPCmd(string(out)); err != nil { + return "", errors.New("No default interface found") + } + return ifName, nil +} diff --git a/vendor/github.com/hashicorp/go-sockaddr/route_info_solaris.go b/vendor/github.com/hashicorp/go-sockaddr/route_info_solaris.go new file mode 100644 index 000000000..ee8e7984d --- /dev/null +++ b/vendor/github.com/hashicorp/go-sockaddr/route_info_solaris.go @@ -0,0 +1,37 @@ +package sockaddr + +import ( + "errors" + "os/exec" +) + +var cmds map[string][]string = map[string][]string{ + "route": {"/usr/sbin/route", "-n", "get", "default"}, +} + +type routeInfo struct { + cmds map[string][]string +} + +// NewRouteInfo returns a BSD-specific implementation of the RouteInfo +// interface. +func NewRouteInfo() (routeInfo, error) { + return routeInfo{ + cmds: cmds, + }, nil +} + +// GetDefaultInterfaceName returns the interface name attached to the default +// route on the default interface. +func (ri routeInfo) GetDefaultInterfaceName() (string, error) { + out, err := exec.Command(cmds["route"][0], cmds["route"][1:]...).Output() + if err != nil { + return "", err + } + + var ifName string + if ifName, err = parseDefaultIfNameFromRoute(string(out)); err != nil { + return "", errors.New("No default interface found") + } + return ifName, nil +} diff --git a/vendor/github.com/hashicorp/go-sockaddr/route_info_windows.go b/vendor/github.com/hashicorp/go-sockaddr/route_info_windows.go new file mode 100644 index 000000000..3da972883 --- /dev/null +++ b/vendor/github.com/hashicorp/go-sockaddr/route_info_windows.go @@ -0,0 +1,41 @@ +package sockaddr + +import "os/exec" + +var cmds map[string][]string = map[string][]string{ + "netstat": {"netstat", "-rn"}, + "ipconfig": {"ipconfig"}, +} + +type routeInfo struct { + cmds map[string][]string +} + +// NewRouteInfo returns a BSD-specific implementation of the RouteInfo +// interface. +func NewRouteInfo() (routeInfo, error) { + return routeInfo{ + cmds: cmds, + }, nil +} + +// GetDefaultInterfaceName returns the interface name attached to the default +// route on the default interface. +func (ri routeInfo) GetDefaultInterfaceName() (string, error) { + ifNameOut, err := exec.Command(cmds["netstat"][0], cmds["netstat"][1:]...).Output() + if err != nil { + return "", err + } + + ipconfigOut, err := exec.Command(cmds["ipconfig"][0], cmds["ipconfig"][1:]...).Output() + if err != nil { + return "", err + } + + ifName, err := parseDefaultIfNameWindows(string(ifNameOut), string(ipconfigOut)) + if err != nil { + return "", err + } + + return ifName, nil +} diff --git a/vendor/github.com/hashicorp/go-sockaddr/sockaddr.go b/vendor/github.com/hashicorp/go-sockaddr/sockaddr.go new file mode 100644 index 000000000..826c91c2e --- /dev/null +++ b/vendor/github.com/hashicorp/go-sockaddr/sockaddr.go @@ -0,0 +1,206 @@ +package sockaddr + +import ( + "encoding/json" + "fmt" + "strings" +) + +type SockAddrType int +type AttrName string + +const ( + TypeUnknown SockAddrType = 0x0 + TypeUnix = 0x1 + TypeIPv4 = 0x2 + TypeIPv6 = 0x4 + + // TypeIP is the union of TypeIPv4 and TypeIPv6 + TypeIP = 0x6 +) + +type SockAddr interface { + // CmpRFC returns 0 if SockAddr exactly matches one of the matched RFC + // networks, -1 if the receiver is contained within the RFC network, or + // 1 if the address is not contained within the RFC. + CmpRFC(rfcNum uint, sa SockAddr) int + + // Contains returns true if the SockAddr arg is contained within the + // receiver + Contains(SockAddr) bool + + // Equal allows for the comparison of two SockAddrs + Equal(SockAddr) bool + + DialPacketArgs() (string, string) + DialStreamArgs() (string, string) + ListenPacketArgs() (string, string) + ListenStreamArgs() (string, string) + + // String returns the string representation of SockAddr + String() string + + // Type returns the SockAddrType + Type() SockAddrType +} + +// sockAddrAttrMap is a map of the SockAddr type-specific attributes. +var sockAddrAttrMap map[AttrName]func(SockAddr) string +var sockAddrAttrs []AttrName + +func init() { + sockAddrInit() +} + +// New creates a new SockAddr from the string. The order in which New() +// attempts to construct a SockAddr is: IPv4Addr, IPv6Addr, SockAddrUnix. +// +// NOTE: New() relies on the heuristic wherein if the path begins with either a +// '.' or '/' character before creating a new UnixSock. For UNIX sockets that +// are absolute paths or are nested within a sub-directory, this works as +// expected, however if the UNIX socket is contained in the current working +// directory, this will fail unless the path begins with "./" +// (e.g. "./my-local-socket"). Calls directly to NewUnixSock() do not suffer +// this limitation. Invalid IP addresses such as "256.0.0.0/-1" will run afoul +// of this heuristic and be assumed to be a valid UNIX socket path (which they +// are, but it is probably not what you want and you won't realize it until you +// stat(2) the file system to discover it doesn't exist). +func NewSockAddr(s string) (SockAddr, error) { + ipv4Addr, err := NewIPv4Addr(s) + if err == nil { + return ipv4Addr, nil + } + + ipv6Addr, err := NewIPv6Addr(s) + if err == nil { + return ipv6Addr, nil + } + + // Check to make sure the string begins with either a '.' or '/', or + // contains a '/'. + if len(s) > 1 && (strings.IndexAny(s[0:1], "./") != -1 || strings.IndexByte(s, '/') != -1) { + unixSock, err := NewUnixSock(s) + if err == nil { + return unixSock, nil + } + } + + return nil, fmt.Errorf("Unable to convert %q to an IPv4 or IPv6 address, or a UNIX Socket", s) +} + +// ToIPAddr returns an IPAddr type or nil if the type conversion fails. +func ToIPAddr(sa SockAddr) *IPAddr { + ipa, ok := sa.(IPAddr) + if !ok { + return nil + } + return &ipa +} + +// ToIPv4Addr returns an IPv4Addr type or nil if the type conversion fails. +func ToIPv4Addr(sa SockAddr) *IPv4Addr { + switch v := sa.(type) { + case IPv4Addr: + return &v + default: + return nil + } +} + +// ToIPv6Addr returns an IPv6Addr type or nil if the type conversion fails. +func ToIPv6Addr(sa SockAddr) *IPv6Addr { + switch v := sa.(type) { + case IPv6Addr: + return &v + default: + return nil + } +} + +// ToUnixSock returns a UnixSock type or nil if the type conversion fails. +func ToUnixSock(sa SockAddr) *UnixSock { + switch v := sa.(type) { + case UnixSock: + return &v + default: + return nil + } +} + +// SockAddrAttr returns a string representation of an attribute for the given +// SockAddr. +func SockAddrAttr(sa SockAddr, selector AttrName) string { + fn, found := sockAddrAttrMap[selector] + if !found { + return "" + } + + return fn(sa) +} + +// String() for SockAddrType returns a string representation of the +// SockAddrType (e.g. "IPv4", "IPv6", "UNIX", "IP", or "unknown"). +func (sat SockAddrType) String() string { + switch sat { + case TypeIPv4: + return "IPv4" + case TypeIPv6: + return "IPv6" + // There is no concrete "IP" type. Leaving here as a reminder. + // case TypeIP: + // return "IP" + case TypeUnix: + return "UNIX" + default: + panic("unsupported type") + } +} + +// sockAddrInit is called once at init() +func sockAddrInit() { + sockAddrAttrs = []AttrName{ + "type", // type should be first + "string", + } + + sockAddrAttrMap = map[AttrName]func(sa SockAddr) string{ + "string": func(sa SockAddr) string { + return sa.String() + }, + "type": func(sa SockAddr) string { + return sa.Type().String() + }, + } +} + +// UnixSockAttrs returns a list of attributes supported by the UnixSock type +func SockAddrAttrs() []AttrName { + return sockAddrAttrs +} + +// Although this is pretty trivial to do in a program, having the logic here is +// useful all around. Note that this marshals into a *string* -- the underlying +// string representation of the sockaddr. If you then unmarshal into this type +// in Go, all will work as expected, but externally you can take what comes out +// and use the string value directly. +type SockAddrMarshaler struct { + SockAddr +} + +func (s *SockAddrMarshaler) MarshalJSON() ([]byte, error) { + return json.Marshal(s.SockAddr.String()) +} + +func (s *SockAddrMarshaler) UnmarshalJSON(in []byte) error { + var str string + err := json.Unmarshal(in, &str) + if err != nil { + return err + } + sa, err := NewSockAddr(str) + if err != nil { + return err + } + s.SockAddr = sa + return nil +} diff --git a/vendor/github.com/hashicorp/go-sockaddr/sockaddrs.go b/vendor/github.com/hashicorp/go-sockaddr/sockaddrs.go new file mode 100644 index 000000000..75fbffb1e --- /dev/null +++ b/vendor/github.com/hashicorp/go-sockaddr/sockaddrs.go @@ -0,0 +1,193 @@ +package sockaddr + +import ( + "bytes" + "sort" +) + +// SockAddrs is a slice of SockAddrs +type SockAddrs []SockAddr + +func (s SockAddrs) Len() int { return len(s) } +func (s SockAddrs) Swap(i, j int) { s[i], s[j] = s[j], s[i] } + +// CmpAddrFunc is the function signature that must be met to be used in the +// OrderedAddrBy multiAddrSorter +type CmpAddrFunc func(p1, p2 *SockAddr) int + +// multiAddrSorter implements the Sort interface, sorting the SockAddrs within. +type multiAddrSorter struct { + addrs SockAddrs + cmp []CmpAddrFunc +} + +// Sort sorts the argument slice according to the Cmp functions passed to +// OrderedAddrBy. +func (ms *multiAddrSorter) Sort(sockAddrs SockAddrs) { + ms.addrs = sockAddrs + sort.Sort(ms) +} + +// OrderedAddrBy sorts SockAddr by the list of sort function pointers. +func OrderedAddrBy(cmpFuncs ...CmpAddrFunc) *multiAddrSorter { + return &multiAddrSorter{ + cmp: cmpFuncs, + } +} + +// Len is part of sort.Interface. +func (ms *multiAddrSorter) Len() int { + return len(ms.addrs) +} + +// Less is part of sort.Interface. It is implemented by looping along the +// Cmp() functions until it finds a comparison that is either less than, +// equal to, or greater than. +func (ms *multiAddrSorter) Less(i, j int) bool { + p, q := &ms.addrs[i], &ms.addrs[j] + // Try all but the last comparison. + var k int + for k = 0; k < len(ms.cmp)-1; k++ { + cmp := ms.cmp[k] + x := cmp(p, q) + switch x { + case -1: + // p < q, so we have a decision. + return true + case 1: + // p > q, so we have a decision. + return false + } + // p == q; try the next comparison. + } + // All comparisons to here said "equal", so just return whatever the + // final comparison reports. + switch ms.cmp[k](p, q) { + case -1: + return true + case 1: + return false + default: + // Still a tie! Now what? + return false + } +} + +// Swap is part of sort.Interface. +func (ms *multiAddrSorter) Swap(i, j int) { + ms.addrs[i], ms.addrs[j] = ms.addrs[j], ms.addrs[i] +} + +const ( + // NOTE (sean@): These constants are here for code readability only and + // are sprucing up the code for readability purposes. Some of the + // Cmp*() variants have confusing logic (especially when dealing with + // mixed-type comparisons) and this, I think, has made it easier to grok + // the code faster. + sortReceiverBeforeArg = -1 + sortDeferDecision = 0 + sortArgBeforeReceiver = 1 +) + +// AscAddress is a sorting function to sort SockAddrs by their respective +// address type. Non-equal types are deferred in the sort. +func AscAddress(p1Ptr, p2Ptr *SockAddr) int { + p1 := *p1Ptr + p2 := *p2Ptr + + switch v := p1.(type) { + case IPv4Addr: + return v.CmpAddress(p2) + case IPv6Addr: + return v.CmpAddress(p2) + case UnixSock: + return v.CmpAddress(p2) + default: + return sortDeferDecision + } +} + +// AscPort is a sorting function to sort SockAddrs by their respective address +// type. Non-equal types are deferred in the sort. +func AscPort(p1Ptr, p2Ptr *SockAddr) int { + p1 := *p1Ptr + p2 := *p2Ptr + + switch v := p1.(type) { + case IPv4Addr: + return v.CmpPort(p2) + case IPv6Addr: + return v.CmpPort(p2) + default: + return sortDeferDecision + } +} + +// AscPrivate is a sorting function to sort "more secure" private values before +// "more public" values. Both IPv4 and IPv6 are compared against RFC6890 +// (RFC6890 includes, and is not limited to, RFC1918 and RFC6598 for IPv4, and +// IPv6 includes RFC4193). +func AscPrivate(p1Ptr, p2Ptr *SockAddr) int { + p1 := *p1Ptr + p2 := *p2Ptr + + switch v := p1.(type) { + case IPv4Addr, IPv6Addr: + return v.CmpRFC(6890, p2) + default: + return sortDeferDecision + } +} + +// AscNetworkSize is a sorting function to sort SockAddrs based on their network +// size. Non-equal types are deferred in the sort. +func AscNetworkSize(p1Ptr, p2Ptr *SockAddr) int { + p1 := *p1Ptr + p2 := *p2Ptr + p1Type := p1.Type() + p2Type := p2.Type() + + // Network size operations on non-IP types make no sense + if p1Type != p2Type && p1Type != TypeIP { + return sortDeferDecision + } + + ipA := p1.(IPAddr) + ipB := p2.(IPAddr) + + return bytes.Compare([]byte(*ipA.NetIPMask()), []byte(*ipB.NetIPMask())) +} + +// AscType is a sorting function to sort "more secure" types before +// "less-secure" types. +func AscType(p1Ptr, p2Ptr *SockAddr) int { + p1 := *p1Ptr + p2 := *p2Ptr + p1Type := p1.Type() + p2Type := p2.Type() + switch { + case p1Type < p2Type: + return sortReceiverBeforeArg + case p1Type == p2Type: + return sortDeferDecision + case p1Type > p2Type: + return sortArgBeforeReceiver + default: + return sortDeferDecision + } +} + +// FilterByType returns two lists: a list of matched and unmatched SockAddrs +func (sas SockAddrs) FilterByType(type_ SockAddrType) (matched, excluded SockAddrs) { + matched = make(SockAddrs, 0, len(sas)) + excluded = make(SockAddrs, 0, len(sas)) + + for _, sa := range sas { + if sa.Type()&type_ != 0 { + matched = append(matched, sa) + } else { + excluded = append(excluded, sa) + } + } + return matched, excluded +} diff --git a/vendor/github.com/hashicorp/go-sockaddr/unixsock.go b/vendor/github.com/hashicorp/go-sockaddr/unixsock.go new file mode 100644 index 000000000..f3be3f67e --- /dev/null +++ b/vendor/github.com/hashicorp/go-sockaddr/unixsock.go @@ -0,0 +1,135 @@ +package sockaddr + +import ( + "fmt" + "strings" +) + +type UnixSock struct { + SockAddr + path string +} +type UnixSocks []*UnixSock + +// unixAttrMap is a map of the UnixSockAddr type-specific attributes. +var unixAttrMap map[AttrName]func(UnixSock) string +var unixAttrs []AttrName + +func init() { + unixAttrInit() +} + +// NewUnixSock creates an UnixSock from a string path. String can be in the +// form of either URI-based string (e.g. `file:///etc/passwd`), an absolute +// path (e.g. `/etc/passwd`), or a relative path (e.g. `./foo`). +func NewUnixSock(s string) (ret UnixSock, err error) { + ret.path = s + return ret, nil +} + +// CmpAddress follows the Cmp() standard protocol and returns: +// +// - -1 If the receiver should sort first because its name lexically sorts before arg +// - 0 if the SockAddr arg is not a UnixSock, or is a UnixSock with the same path. +// - 1 If the argument should sort first. +func (us UnixSock) CmpAddress(sa SockAddr) int { + usb, ok := sa.(UnixSock) + if !ok { + return sortDeferDecision + } + + return strings.Compare(us.Path(), usb.Path()) +} + +// DialPacketArgs returns the arguments required to be passed to net.DialUnix() +// with the `unixgram` network type. +func (us UnixSock) DialPacketArgs() (network, dialArgs string) { + return "unixgram", us.path +} + +// DialStreamArgs returns the arguments required to be passed to net.DialUnix() +// with the `unix` network type. +func (us UnixSock) DialStreamArgs() (network, dialArgs string) { + return "unix", us.path +} + +// Equal returns true if a SockAddr is equal to the receiving UnixSock. +func (us UnixSock) Equal(sa SockAddr) bool { + usb, ok := sa.(UnixSock) + if !ok { + return false + } + + if us.Path() != usb.Path() { + return false + } + + return true +} + +// ListenPacketArgs returns the arguments required to be passed to +// net.ListenUnixgram() with the `unixgram` network type. +func (us UnixSock) ListenPacketArgs() (network, dialArgs string) { + return "unixgram", us.path +} + +// ListenStreamArgs returns the arguments required to be passed to +// net.ListenUnix() with the `unix` network type. +func (us UnixSock) ListenStreamArgs() (network, dialArgs string) { + return "unix", us.path +} + +// MustUnixSock is a helper method that must return an UnixSock or panic on +// invalid input. +func MustUnixSock(addr string) UnixSock { + us, err := NewUnixSock(addr) + if err != nil { + panic(fmt.Sprintf("Unable to create a UnixSock from %+q: %v", addr, err)) + } + return us +} + +// Path returns the given path of the UnixSock +func (us UnixSock) Path() string { + return us.path +} + +// String returns the path of the UnixSock +func (us UnixSock) String() string { + return fmt.Sprintf("%+q", us.path) +} + +// Type is used as a type switch and returns TypeUnix +func (UnixSock) Type() SockAddrType { + return TypeUnix +} + +// UnixSockAttrs returns a list of attributes supported by the UnixSockAddr type +func UnixSockAttrs() []AttrName { + return unixAttrs +} + +// UnixSockAttr returns a string representation of an attribute for the given +// UnixSock. +func UnixSockAttr(us UnixSock, attrName AttrName) string { + fn, found := unixAttrMap[attrName] + if !found { + return "" + } + + return fn(us) +} + +// unixAttrInit is called once at init() +func unixAttrInit() { + // Sorted for human readability + unixAttrs = []AttrName{ + "path", + } + + unixAttrMap = map[AttrName]func(us UnixSock) string{ + "path": func(us UnixSock) string { + return us.Path() + }, + } +} diff --git a/vendor/github.com/klauspost/compress/.gitattributes b/vendor/github.com/klauspost/compress/.gitattributes new file mode 100644 index 000000000..402433593 --- /dev/null +++ b/vendor/github.com/klauspost/compress/.gitattributes @@ -0,0 +1,2 @@ +* -text +*.bin -text -diff diff --git a/vendor/github.com/klauspost/compress/.gitignore b/vendor/github.com/klauspost/compress/.gitignore new file mode 100644 index 000000000..d31b37815 --- /dev/null +++ b/vendor/github.com/klauspost/compress/.gitignore @@ -0,0 +1,32 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe +*.test +*.prof +/s2/cmd/_s2sx/sfx-exe + +# Linux perf files +perf.data +perf.data.old + +# gdb history +.gdb_history diff --git a/vendor/github.com/klauspost/compress/.goreleaser.yml b/vendor/github.com/klauspost/compress/.goreleaser.yml new file mode 100644 index 000000000..a22953805 --- /dev/null +++ b/vendor/github.com/klauspost/compress/.goreleaser.yml @@ -0,0 +1,123 @@ +# This is an example goreleaser.yaml file with some sane defaults. +# Make sure to check the documentation at http://goreleaser.com +before: + hooks: + - ./gen.sh + +builds: + - + id: "s2c" + binary: s2c + main: ./s2/cmd/s2c/main.go + flags: + - -trimpath + env: + - CGO_ENABLED=0 + goos: + - aix + - linux + - freebsd + - netbsd + - windows + - darwin + goarch: + - 386 + - amd64 + - arm + - arm64 + - ppc64 + - ppc64le + - mips64 + - mips64le + goarm: + - 7 + - + id: "s2d" + binary: s2d + main: ./s2/cmd/s2d/main.go + flags: + - -trimpath + env: + - CGO_ENABLED=0 + goos: + - aix + - linux + - freebsd + - netbsd + - windows + - darwin + goarch: + - 386 + - amd64 + - arm + - arm64 + - ppc64 + - ppc64le + - mips64 + - mips64le + goarm: + - 7 + - + id: "s2sx" + binary: s2sx + main: ./s2/cmd/_s2sx/main.go + flags: + - -modfile=s2sx.mod + - -trimpath + env: + - CGO_ENABLED=0 + goos: + - aix + - linux + - freebsd + - netbsd + - windows + - darwin + goarch: + - 386 + - amd64 + - arm + - arm64 + - ppc64 + - ppc64le + - mips64 + - mips64le + goarm: + - 7 + +archives: + - + id: s2-binaries + name_template: "s2-{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}" + format_overrides: + - goos: windows + format: zip + files: + - unpack/* + - s2/LICENSE + - s2/README.md +checksum: + name_template: 'checksums.txt' +snapshot: + name_template: "{{ .Tag }}-next" +changelog: + sort: asc + filters: + exclude: + - '^doc:' + - '^docs:' + - '^test:' + - '^tests:' + - '^Update\sREADME.md' + +nfpms: + - + file_name_template: "s2_package__{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}" + vendor: Klaus Post + homepage: https://github.com/klauspost/compress + maintainer: Klaus Post + description: S2 Compression Tool + license: BSD 3-Clause + formats: + - deb + - rpm diff --git a/vendor/github.com/klauspost/compress/LICENSE b/vendor/github.com/klauspost/compress/LICENSE new file mode 100644 index 000000000..87d557477 --- /dev/null +++ b/vendor/github.com/klauspost/compress/LICENSE @@ -0,0 +1,304 @@ +Copyright (c) 2012 The Go Authors. All rights reserved. +Copyright (c) 2019 Klaus Post. 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. + +------------------ + +Files: gzhttp/* + + 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 2016-2017 The New York Times Company + + 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. + +------------------ + +Files: s2/cmd/internal/readahead/* + +The MIT License (MIT) + +Copyright (c) 2015 Klaus Post + +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. + +--------------------- +Files: snappy/* +Files: internal/snapref/* + +Copyright (c) 2011 The Snappy-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. + +----------------- + +Files: s2/cmd/internal/filepathx/* + +Copyright 2016 The filepathx 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. diff --git a/vendor/github.com/klauspost/compress/README.md b/vendor/github.com/klauspost/compress/README.md new file mode 100644 index 000000000..05c7359e4 --- /dev/null +++ b/vendor/github.com/klauspost/compress/README.md @@ -0,0 +1,700 @@ +# compress + +This package provides various compression algorithms. + +* [zstandard](https://github.com/klauspost/compress/tree/master/zstd#zstd) compression and decompression in pure Go. +* [S2](https://github.com/klauspost/compress/tree/master/s2#s2-compression) is a high performance replacement for Snappy. +* Optimized [deflate](https://godoc.org/github.com/klauspost/compress/flate) packages which can be used as a dropin replacement for [gzip](https://godoc.org/github.com/klauspost/compress/gzip), [zip](https://godoc.org/github.com/klauspost/compress/zip) and [zlib](https://godoc.org/github.com/klauspost/compress/zlib). +* [snappy](https://github.com/klauspost/compress/tree/master/snappy) is a drop-in replacement for `github.com/golang/snappy` offering better compression and concurrent streams. +* [huff0](https://github.com/klauspost/compress/tree/master/huff0) and [FSE](https://github.com/klauspost/compress/tree/master/fse) implementations for raw entropy encoding. +* [gzhttp](https://github.com/klauspost/compress/tree/master/gzhttp) Provides client and server wrappers for handling gzipped requests efficiently. +* [pgzip](https://github.com/klauspost/pgzip) is a separate package that provides a very fast parallel gzip implementation. + +[![Go Reference](https://pkg.go.dev/badge/klauspost/compress.svg)](https://pkg.go.dev/github.com/klauspost/compress?tab=subdirectories) +[![Go](https://github.com/klauspost/compress/actions/workflows/go.yml/badge.svg)](https://github.com/klauspost/compress/actions/workflows/go.yml) +[![Sourcegraph Badge](https://sourcegraph.com/github.com/klauspost/compress/-/badge.svg)](https://sourcegraph.com/github.com/klauspost/compress?badge) + +# changelog + +* Feb 5th, 2024 - [1.17.6](https://github.com/klauspost/compress/releases/tag/v1.17.6) + * zstd: Fix incorrect repeat coding in best mode https://github.com/klauspost/compress/pull/923 + * s2: Fix DecodeConcurrent deadlock on errors https://github.com/klauspost/compress/pull/925 + +* Jan 26th, 2024 - [v1.17.5](https://github.com/klauspost/compress/releases/tag/v1.17.5) + * flate: Fix reset with dictionary on custom window encodes https://github.com/klauspost/compress/pull/912 + * zstd: Add Frame header encoding and stripping https://github.com/klauspost/compress/pull/908 + * zstd: Limit better/best default window to 8MB https://github.com/klauspost/compress/pull/913 + * zstd: Speed improvements by @greatroar in https://github.com/klauspost/compress/pull/896 https://github.com/klauspost/compress/pull/910 + * s2: Fix callbacks for skippable blocks and disallow 0xfe (Padding) by @Jille in https://github.com/klauspost/compress/pull/916 https://github.com/klauspost/compress/pull/917 +https://github.com/klauspost/compress/pull/919 https://github.com/klauspost/compress/pull/918 + +* Dec 1st, 2023 - [v1.17.4](https://github.com/klauspost/compress/releases/tag/v1.17.4) + * huff0: Speed up symbol counting by @greatroar in https://github.com/klauspost/compress/pull/887 + * huff0: Remove byteReader by @greatroar in https://github.com/klauspost/compress/pull/886 + * gzhttp: Allow overriding decompression on transport https://github.com/klauspost/compress/pull/892 + * gzhttp: Clamp compression level https://github.com/klauspost/compress/pull/890 + * gzip: Error out if reserved bits are set https://github.com/klauspost/compress/pull/891 + +* Nov 15th, 2023 - [v1.17.3](https://github.com/klauspost/compress/releases/tag/v1.17.3) + * fse: Fix max header size https://github.com/klauspost/compress/pull/881 + * zstd: Improve better/best compression https://github.com/klauspost/compress/pull/877 + * gzhttp: Fix missing content type on Close https://github.com/klauspost/compress/pull/883 + +* Oct 22nd, 2023 - [v1.17.2](https://github.com/klauspost/compress/releases/tag/v1.17.2) + * zstd: Fix rare *CORRUPTION* output in "best" mode. See https://github.com/klauspost/compress/pull/876 + +* Oct 14th, 2023 - [v1.17.1](https://github.com/klauspost/compress/releases/tag/v1.17.1) + * s2: Fix S2 "best" dictionary wrong encoding by @klauspost in https://github.com/klauspost/compress/pull/871 + * flate: Reduce allocations in decompressor and minor code improvements by @fakefloordiv in https://github.com/klauspost/compress/pull/869 + * s2: Fix EstimateBlockSize on 6&7 length input by @klauspost in https://github.com/klauspost/compress/pull/867 + +* Sept 19th, 2023 - [v1.17.0](https://github.com/klauspost/compress/releases/tag/v1.17.0) + * Add experimental dictionary builder https://github.com/klauspost/compress/pull/853 + * Add xerial snappy read/writer https://github.com/klauspost/compress/pull/838 + * flate: Add limited window compression https://github.com/klauspost/compress/pull/843 + * s2: Do 2 overlapping match checks https://github.com/klauspost/compress/pull/839 + * flate: Add amd64 assembly matchlen https://github.com/klauspost/compress/pull/837 + * gzip: Copy bufio.Reader on Reset by @thatguystone in https://github.com/klauspost/compress/pull/860 + +

qE`&H->rybUgp!ewL`VU(>?BW@|Y) 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⁣r4&cM)CQAUQ+N?8>Qk^EFf~e;A<@luluyLF{lv`^a~zJ z<#p0V{bs41ISEv_W&yT~1RHk7oji#v0lEbEFA|)diaUOzywGMcA8*TXoHzkiJO>4| zT_jkNial{-QqGHPCi4jsxP*Ys7YUk3pC_$yYTQ-ZMH-k_2u?}G{Yc4p?gY2(x}&gF z8kDXO{53<{+LkH4s{Mcl+g1pUO~v{qFz4G$<_X*;)&9kTyEE~;Wjju_9o3-qVv+n8 zDLZhdZp>-lj{J7A^ zWm#i#cQJw2swXE?wd2qsc!}UsJxjgI^)!92)WN&%`{y!gM|7xLCz9W0?!YaaqPOWJ z?Q4E2{gkP3>eiuRo#4&sW7(0eTSGd;e*mZ28`GhEy-0pDIyHaW+fz27(14cpf{JN; z6wPBmR|Z;g{Tn3h_lC^#xkj~+T>l0X1qA1(;`|dbUNJQ;T?Y6Ag1oe~Iz``XfG;4D z-_K6juI+R+pCbl%1A=?VVrzrxYu=Fqk$~WtRK2O*zUJgF#161(yCMgwE*H#IyicCM zDl7Nu_O|PCp!RaX?%DjuO-7pCZdd$T1V`_Y1z*2=8opogzfB;-w7FhAq0yJ6`;o0V zP#zNGPV-ON&;(xl!;T6``)7i}I|TDm{m97^W3eFJ?pK+h^e(~hG+E>lktTDK3F3DP zZm?$?6I&X-%LLwT!C~3_&mLNu%tI#dJt}xDlg+#$eLTiZF!rcmk8C!AblFSIF#4F_ z&TRN|)A4m?sC``UP&S*jD&23ln_>7#!L8Z&FBfTJ-fxDgrv$f5TZe0>x|y`YaWgbM zEm)e0(-!SODU8_yJx>cRNyD6D&9&)vuFnGFeS$MG&GU&T`n?#(yo?Bb7c;H)vIpDX?bn4XO`eD{T9<;HK#|y>4nu z)YuPNp|)QzFBO*(swDlt6$1T&gHkcm#@3Y!t^I-nQ!z_Ylxjlmid<;x7krVf5Bkk= z`&z8ah2f~+Pdmp5ciBwl8e5Lzl1YEimJ4-nP4fpk^k%!kS8Jp<7s77|2D9j();A?* zy_)}AlK%(g_1&_psTIzN3Nj`phHBlkXHxf)e@qVMnjM3xWb)de_X|O>DN7r=X@^kC zX9jH0^`+n>ElVFJ?YFc{F8DK2W0Z($Z<|Q&3o_R4NcU-R8r$I_wbn zO7QP&y#JDpue5Lf?ScPf^RJ&y;mef$w}bDWg8VFfmw%g_h0~IAuH+Bfq3mnH3z_79 zG`+7wc8KmGcH9oN|JpTdNgm1H;n@|eFOTH!^ZXE2t)bRDaE%Gpq}qJBQVqiP{ZAhF z|FdiD4(7qwe*{ltj=k`>TYbEF30cK76 z!F8UTe+RT{8l9Q2KS|e7cL5-^^cei)seXA2)V@;VUzvElxl^~2`?KZ(=$9HBL>4=6 z#-tsnNsI4#3&3sDeo)7i&TJ`wZkxuNGK!%AHVGpm9ew z8~#wb{x&#aaE8VwMix7HX8QbeI-z|}jY#HxKA76is1qs=)A(IBoBd?EED0x!{6FB` zGobZwjrX$QUrxvSWnT5H}7s;f2L$*kWmr|NfD#cqo%e=RIE*)FDJB**PYqmJJJG7pu@nq()xG&Xj_wEk*SwAdq(*ErZZD(n$%gHh) z=jNo@G}|69ymZ&sdBq;kwoJn#v+#c+eSh1y2Xrpim?L)D4^&Nf2W>D#&o?Rjxx2Q` zlm2fHC_hi*ne5|u!jAZ74;Va8fBTpLgD#ZwwU6D z)b^VTVeov7xXj>d-j-?O7A}O2i!^?eE%rGu-8aPwp?8JGLT$Rda$hZFLvj4XI@kAv zp$3garm={pk8#*SG3l$6nyM zN=xSHGxqPp^q6JyUXZw2t4`yjm82kqmP-RrP%($yC&i3cg)HAigBIpijoRvuzPMXRmC5oW(4lO+=u4KF^J?<~s2m0>N zlD|*616MtD?o=^Be>(HJy+@>+xi#zqb$4qVy7Rmjr^Xx|`+)x*jRUj{^EfTn+rJMq z+`DUQdvqVzdasr|&)kV`Ub=p`X2QsQ8kQ`vy8Qq2G&#I8Ve^9;B_e}Iqb(BoQGokdcEPJxg)5k{N7wFOG&onkY>1&~E zUkE*}vA>>i&S&T;YrSq?=zMCLuSlNp%8ip;lljkm!SO3C;~7uV|0(%?rKO)~ZP)+D zrn$3Zyc^pWx_+gxBFp;L?wri$J)6G&D~92SMm)2ferFP_+9)rEP0wf?n#E3EIvG)a zF>U^fA@rQa|1!&kd8DlIK6gFxs#2 z_RhH8>EoEZ|1b+Wf1~m4&iG$t!dK6Ns^4n7yfeOQI$rgwWfqM7Hgms{@!u>M{;kH1 z+3fTc>AE>M3(7ZZbZ64zJJMs5v02dnl16)K+t*BP&Z>6g9*bvh|E#i z(|rCUZt)Z@V`fQ#O%EP`f74~l^(nHgN`?~ zjCTW6yPo}^^-YbjoptlQOm@M)AJqIo<7>H-?|(;T*pGzvgW|U}-pHh*ed)e>^L`M0 zN8=|sS$y?h^fdgo{lNX9#?ox}J6h6n3B~(^?@zlH=U49!!+-i=9Ztr7`$OHIH5O%z znWs+n)S3$K53QeST%W}bu9);SC#KuOElQrhOp|9)_WROhH_wH-xW-GFW$#Uu-7^>X zOxvX#fBoF;zd8FuSf!usbD`vO4d2c&;t3)pu87Qq`Y$vV?TnkBirX?5+D5hXyG1I_ zy*@pUp({cEs&Rt86Tdln2L1GuK=I!+Ud^PRk#rkcUjorDHCi*r$cx3agNEe#F9FB4 zX?|pB%7wRy@#-&u!fjgeH{o~S7VnIUD|vT;pX~rB*`_hF^SHj1x;OJ203%=RT0Exs z`VWBCe`x%DXTBq;v48skP?gxVwbpk43?_bfttI<^0MvY~ar(~fSEjaaI}n=xr6uns z?li9}($`k`fiU>*A8udSQ~!ZbGnRcH6`Y_CXKMEqkrvnY9tiq38vU8ueJr)#TMmTI zZ+>{*^@E`68;#v|&KKoqDeI~9Am|*|7~Of^hbM(pI`2CO>i?^8P-dMM({*0yRNFyN z_rGaAA~n`qqNS~?zJs7tlj%9J$uZk+a?DOio3pJ4LAP0^-%ZW1Un~X+OQF;v)9=F^ zzfoS567N-%LbF9?Jnu{1e<+0pi%j27OzaDjdytg9cAIL?Dzn}%=`MvLtIT-MP0

lYbv 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 O<0Hq*@l0vzXa5g0)~>?< literal 0 HcmV?d00001 diff --git a/vendor/github.com/DataDog/go-libddwaf/v3/internal/lib/libddwaf-darwin-arm64.dylib.gz b/vendor/github.com/DataDog/go-libddwaf/v3/internal/lib/libddwaf-darwin-arm64.dylib.gz new file mode 100644 index 0000000000000000000000000000000000000000..bcbe9c54f7f1afe2a2aabf650415c9bbf1a57b91 GIT binary patch literal 627228 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

`+v;L8FK0a; zNsGPP;vs1*0^cJlB1s?e_p)dGO^^J^O;z-x?upZWaVwp&+YiF#F8nKfrkNZ5>EIG3}^0d9J7ZFRE+SWt+P1(efc^_b}kjuA-C0CpUFSe$K z5KDRw0Io7m$cZJJ8X)goJ>U(o^~^3dJ{`Nae_Yoh_fM<%nbm}8{dB=X~}lSBP1>9c-j8Qv`5bKyM19N zi;A{=KlQ|XqiubNg$MP-ynH+?h=psVqJ7s!eTap>Ek~ZSZ=x@;@SYPkOm6gK53%sC z4#<}VZ}KG;E-FOcva?!$V&Pi(@T;E!wh#+?IcN8U{T3#+D)$_D)8g;FuaoENuN2{Wym1AQoPE0DkhtpC5^ZNBshSU*0q) z7G66Xd>o$`PAoijPZcKD>sXdpct%zDlWD7D#KH;3kr(Ccbs-j>xf}R#-PW5}Shg8) zq;1F@V&TnIfx~rvONfPASBJkEK0JX~*!nH>_GV2>Nej<<)>G2LgF4>+CSUM7r&S$j zMP0P*?*4}*JA8fkFJk%AW1xpdn?s1@>pX_u);3QjmS55oezoX8En@k+TNwYe2R_8| zwfn%&-#PCJ2IAZz2jnMPs z99?4h0Z*~+_#QHqSU!0g=Ig$7HL-l#npjdSOmHEV?_`BMvs&3U#PSVRKo3?aYl-Dg z{RZ#S@`e%1x9EcFMhCr?wEWml>5`UTaWP!d@@I4V8FW4ucLj447i~Ozy@&milZ~$t zM08w<{2}O?7eU1F3gB0kxd=r9*Ib*P{dB5^1LB!L$xNax2h6E8g+ri&E6CV*o%pL_h?%({4 zAj1AA^8X<{-3TIvWFd~Pw^~3D(dZidRr}dh2_gdLVtu#!Y!!ltd)&Ut`0VKf5oV2{ z=QHt91Q97)5ntk-j*&!!nQoROB5uygmqdg%9u^z`9=07lK@d@2j&(55iurtCl5*_+ujUyey*)K}5%fh_lPAVkjcoV1ItX)Y1eI zkvmH>d6#?d2qKIEF;00#M}mmME3KIP%JP(Q*v^(zW#l3STNO24X@6MFFOpucC3)k&cYbHU;`l=ZJoA~PlDFz>)hoMW~ z6Qp=t0RHd4wIN8^R|WQs%#0#P3BHd!`BIPvLCWn($dePcKP5#>spH-<-soGA-cZZ2vSxqfc~2mC zBt!q*tH%9AfInpUsU{qASj?5*FL=?LD0Vbz{#D8(+PsknZgew>FW>#y^RJw z8`}C31l?}~eEQGpMi5l3Ci=hJ#hf50ECP0%zxWG5P?i4nOm4n@J3-LyaPazoWeh>k z!jZu9=w~?uLHB}fnLP6MQ-YwpWypJ<*uNqOYS9PH6RE&w-VP~ zS~;H}$iD^Rse$`6Nd(QxSs;m^aobl*B1juQpSvTkc6f1#Am}!iH!huBKoHcqJ^cLm z!Mh29PFn&eue!D%2(sIcYi@SQBnXO{1AZNQ(SjhzUWR-oa_(({plheF&(m>aB0Y5 z`UF|=+X%Sf~<%UTs}GRH$m2})yUIaGv*OwJ!y`( zY;MzxAnSA+__rp0<^)-K@4%x=j}{YTJvW9Qu0Q!GLDs6%m~Yozog|TU{>4K{WSt#S zB#A6-Tv-jqeUJwq>k(u<9|k|%@7qX%tPY)_pFgi{A;_}70Q>g*`j{ZgDHY@IQ2Gl& z*4UZg*Xx0o2(prDARm}vQjs7lHURjnx=)WFYjP`$->!!}L6*l~z~}R^*9fvEPC!2F zQ>QmU)(E>sO#ULNFG1G*A@EmjUgrt2o`1l8%l(;62(s!9F=X=GYA*<~X6Qg}8{cHMI33|u>wI>SViz<*&}a)EYD`Onf%1Xiv(F&^{{WYzg#_ntb8lv z3GF9!A;`*m2VQI{e@+rvyQ19EK{}s+@hk5xA@Xd?D#0VKMCSy1i%mX zDeg-USEc~|>Y(9$g1G5l5qI8x3?hj8(gyNFb=wofm4A+TmEKuI5VvzB^!y_yjUdit zvo4cg7-dBe7g-T;(<9B6AkJkP;=;qMX9RJJ4+H1(?=>ZeJKG2Gy;Su=g1AG65XVD0 zyAs50T>{?SUviHi&T%C2qP@Fw2;yGPN8F$E)`lQ%>j>Z{B(XC=+=2|)#cy&Wg1CLg zh^O^VFC~a890xt?W*jGo%l`yE?pV8zATG!W{F=6;9YNg0Fz~d&*^QEj8yC1!5^?Vy zRF*`XHr|SSktYusGLj%JxEt_4@^){6xMtDdb(<>(2;!`MF|q8J=Np2!V|wua(@*CS z#MRh`{NzUy6N0$oiy*g{{hc7L@Gk5!()v6>T!Ja`!@&0L1aY!3#I>9&4+!E)Z**pI zy#ezG;&$J&Ve+->3<=_9Y=gaq#`Y(O>)#AGpV#XiL7ZYe)_vy!_YlMxv;~ix`b;E< zd-E9nvsShK1aVDAWB;>KnU(}`yDA_Rx|?rL5Ley@db`+9hak>tGp@Tfe>*|k#8~ia zRO(cMIG2j>!y)F51aXZH;C|5i1v~jp&3heSV zYcN6LtnT1%>gf>#iN!8;nA~_}Yl6i4Z^66j_l^=I4&H`-WVuvJ3REE$ItEVuj}L!><=kBS@Us1mh`dYDADY z?=MFtZ}(?4g2YxE;O7tZo-eZfB7vVNKEI}O+TK!CrIpd9ezHjg%d&Isw&V=MD$=u zBp!OcNfL>P{bpZsw0*Vv_YO@&YW~GKmX*y0J`b+gN)UR?1Nxlawum4!eh2a#lZ#~t zLQOYfy&oRvPY{~69(wp=Rvtm<+ly##w4)qB=+rgfseJotg3tjqupad8f0ZEg%URfK z==323p(Cu}H>Olo5QJt;$9yYQ?@ADQVh-|4RiPn3~A9Vv4#6=sob$(;rI_&iUg4}TK^Eg8vrV`}(&c?h_ z0*wiBy=HLxB#Xlcat%_k?^@%+EP~uaK6q|H(X9=JrL9QX^hi8uY zPLR7h0{u5jO(n>E*$n$&a~jVg$SukMU%bz5B*;Bp54^T&^_w7f@fh%Efbmm;+;;7N z+X+pc5ad?y$GjpFMiS&+$%j5urlb?(KI{t~SzR+E$UR#cxHUd%Ly-HlHZaw~$Cw~D zED>?m>FQ)jO$r?G#MxwIug?u%~7L#|uQAjqBB z3jEy==u410pd0*uWW;QO+_K-0S1&r{=X3+O=+T7@9@q9d+ber^asZt4KUkqZ5j z333x=K|kA1MiAuIaYvrt*>eg(?yyOiZ>_6U2y)|XA&*ZqBFMD~G-GnFdCduOJ-3)d4w7frHZ@~wgH1ks)9V;#E0 z-jE==??uF#CU+hYM5k;+{!?oBNP_5F+~;RwZ@Lpi8;(Mn!%oM=f9{X3x& zlN)`@BZ#gR06gy~)1DxD*elpQszVckXtQ3}|7qXCf*?AByZ>&wU@Sp&y<6p2`#(dH z2%-m%hrexDtvx~X#?DME^X~S5AbRjU#M4G|R}w_8Ooy*~eES+fboCZkUyS%1OAvk8 z2l?cQD`o`IhjL(dkIaSy(M}Cvmj`v?38F9M!Ea>NGmu2|qrkF~h<^0ZM-tJ!BLeIm zCv|K(mGvnu+Blzc75S=@-b;dXA8X)$RE=u{>A4#bce<5nO^`mLAN+=^-9du%8df$; zK1lI}Abm*)@LXuommodsIO1>o&j$qQlj~qS+2u0{(yzZXXYxOP^(RQ5xETJk`J06V z>1hj@SeEd8H9>kD_neZ;g4Tdg|4%I{O^{xLd+z1a*!u+O4=-U|-0+JNLHf_S$U_!2X-ts5)V(f~FWBfs zke=BA`iwsNh#)<65O_UPF`OWMmjTwH6I_oIq^Ipe+_^Z(ogh7z+b6MZ_$NVn{aEm5 zaF+~%^i_l4mm)enltg-v=|f4R`wj0UiF9q8A6|-l_=bN2g7ih_!T0ihBMH*8AE1x) z9$g92H*?>+Qm%yyLAvfH8`l2dk8pzYrQGw?Q(HVINZ+*;?ITVOB}l*E3LeEJuOdj# z*8$Eyuencss=^EiyZoBSg|`usrn=e;$Y2-4@2 z1K#erWfG+KuLe8bYC4}F{mO0RIn`E15u}grf_aUdHiIC2+zH^bpk*>a`X8s@C+9d_ zAV{yj7kSQ}Dm4hw*WI#Z@{{Kx3DTXckSF*y8zhPJa@~7KBK<{9OG%{9{2CY@es{}# zZZnAWD-><~Z|V(wmRf(EFyJzGAI)f>8DW5#2kv(iUYki6a4!J%EvjFZFd(3xBa{1& zIzSlkGZ+2Xy-Xnt7{l#(M`Gf&~ z^#orU)=eP{hzo=Mk3RGx3>dKue*0^=jf4T6l7NSEL)sDs_-{rYqI0z$VL%P;^VGg? zuM!3v<@~^nZFL9(3Npd>vOl{L2CN$oKi{=z4`IMq59G;}AKWDjSkV*uFE{NbVSsrl z_`SX#suBj+bwm6O|7#3kfcX&c@y?GYgaMA_f&Wo`W)lX~8iDI>ow%DYVB$^0&En(} zgaK76WB=AT(1$R<(im~Di)mR&2CULAlw^Rd?+i%>XygC$PuRUth9O~qC6}M{IaZ1= zV1Xn2)t-jW2?OM7EScQr>?^{6#L?h;hjncU19ol3SSAJ95(Zpu1l%^Msvrz_`lt+( zS07oMFyL)l=<{*YM8bgTcacADHatfd&`BRSIZ?)mFrfH2{MDyLM+gIo1|XlYPX9s} zVBZBeS(J8`Fd*N+hRIu>mk|bZ?+HCbU-uylDB{+GA?L0W20U}YIxf3a8Nz_oU9s*S z|E3FJz#Q)L1(&B;5(XHxMn1E)Ls`Or4^9}*!<&5w19TU{F4ptI2m?~Gun!P9{Wf8M zLtWrum-k4*fFDKB|AhNn2m{_^A)h}m%y-d+~rM}u}=s2Oho%?gc%Nd;U`quFoF>ee-5-8t&7IbS8NPDxdVBd3gc;lHf%CDOYY=8MYzdsW_+%4i zbj?A&Z8`cJVaBv-kbiyJi!ftV4(xvE!E3^d{YKcgiA@$d8VN*J@3`yGdCV^5<#vnhu^23iXru9JRbIjJOgfT{Gz?DN#J;InK#=zCtqSAyh7U_ta>4z^6#&p|& z{BwPv1!2sRI^eIx=SqYz%U0E7@~<~t2xIEbM;_wn?oSwVG8pX#EKMPdskj>Pu|ao7 z!kC}s5f_$>N+yiSKLwq+ZEi>yGiDF$vfB1NVa#+L@GJ-unSAb(Y{DdukC<=x>uH2ZOLt&> z`qV$3FvSF=0|fcj)<+(-6X>?>}JQdS^!vCjIGy_Mdy~AWVu`0K84geJjbN zc?S+kGHH5t8%ZW<^JvK-#GSvY6cQ%wzl3_L)$FC0}Oqv!6{7kA+l`v_&3-oEZdNO6wH`x8#G;6{n^QvAARUQ$qNq&8M@G0|IE3POd64qD#@fV;g9QnU)MFkN*|*W7hRcw%t&S`Gh_RGRx%q|U73^2 zUDj0ATGmO{OBTw0d3=;CMK(vaT((iRUzRVsEqfvRCNt5gs?$KnN2iNUn9fL@nK~-tMLlscgD?3=9oM+@hUy5 z^s~}UU_6PEzX-d?5+$^z5%{lJ{=RkY_FWH=x6xAQ-TWKkw^lK0tq=T(%YV{)@}&o< z;0Y;a%iGQ6KA%S9vMjs%Mp%z&72iBxP5FN|n&sY3jVYpKY&6>~HoIx|j}c_qmCm}6 zN45xXz<18rT?>(C(~|tGK^X!tWs|V;@H;~JpB{awGp~;!{}309KH^K89IcqhM*lgi zb|1tc&651=;=%6&5pQUDOlc}n433&anu zg#JC-k}v%|0!y9w``PYI=^s>6=pV1j*=ANTwne;D7k;+mt}I=l(VjKHY%iW4+fR%` z?mRZz)b4iv+V(Ao`F(7EbsKf(!n?v;{qQDIp2@7tZ%b}JRA?!@W^LH3_RIwKH2Ywa#$F5rH9;{`@JaP1VKCU-%H|=r-}-vor33S8CZvi3$$~7 z@X2~Ay9)=Ic3M84U#RV$&C1kqaJhl}n3SwHv-P>}F(h)C?{xcF9#n|GleaxXKEa-3 z@cz#+_4ir}H8HJ+yoxVstW4x>EP7Zu(mFGw3+L()GV z8E?Yzg^LCMnu-5PYsZhpsobzwYZi((+1T&ki&|^lQ`=Y?2x4|y223n?{w1Q%=$$Ml zQ5QjL;fnH;E!1LWeqhaO#BkH3S7N)c6(^^);>^M?TpQA^!Att(~ht?!%_J1o{8r{(ll`5qef#f6xbzvQPk(BKz00Dsr{M<3F!tjCeilTBJ4l)`!8 zHksUsJD2>Y%=eHnJoet3LNG2v#!%Wgv&xBQp(cNi@pDDa9b%O9)zp5Y>h_^Z|EZyU zlZX*>1YV1^@1*ykpUMx2w4Z2LU6kjjwg0gChB_jgtF%AA+L(S~|1W6Y|7-da4gDy! ze<`(hJK$4PIPL!oUBZ2iR3v8@pMSLFoUFTz#6rAh+7H?`L|4=A;XvUwyGaYv#Jq-- z6|?;#+$&-qik7TKXSvT|Qn^f-4@+B%?XyT)i`{2pnGmAitos&(!L{Xw?MZ;Pze@5>GDzA1l>+FCik#=a2o zLS?Pejh!B9tY4JY+GT%``@R+7+VDuQ*0eY2!^wJtv)1y=w&$>KA}+92>6L4pwAKa8 zTJyd*ZBpS=by8NN(FGZ^HE_ir^PSk=V5@4rs`iZZttNEEb2i$AUoS{;4sE5a$n4HC zJVfK}sR#TURezaRuHX-@Yjs??=wuSn>yUe+DeK_psTF(Gc0I%`MTr%|T*v71`q#AL z>Q~KYD&vlZ6$`x*mk4$dTXA5Q2TfFdQe?$TUtYEr#V?f=+l`qtTI7dSR;+RT>Ua&F zDy?YIf1``oKl7X`y>eiS;iW`z7CPaqsC#&ULUdhDSFqx^ad)4b=f|hGHVd58(qiY0OAEQ zRMP|D3TrPXJzc+EwZC3TiUF^Mtl`CyM8nZ_!(2C+=bS`7My>1bA2Ewt9}(+5wp_yf zt~Q@*1>5#+?f*6B*T62fjqElk{jG*|msJYQROOQ*>qaIw)>HFK;AoBO>$^tJ62(oG zbq~GL(-p7Rc#aNi;c@0}x<))zS~s!khx;6!+1&WTTenxITTY^QfkT{i&*%MFUgT%E zQ()bs?}eXK`2*h(`+vpYW)1_n`_L*8|HkCkeVfKob}!i2;iXo*z&XnGqqb+}JCx!y zj_|o6wK{v=h**7S;D^%4$M{@PZS`I+hbALmLWW)ZHnQkp^@!`MU-|p9FW>xzIE4(m zO!(nj^Q-myQt0*AQnumiCGbU))3=S<%$vp2i&%Y!PsRyl9MrJ-!XT?R!oG@z)va7w zad|kq1|LV4XIk_>^lF03z(g({LC(cdaN6Tc+qfq_BLAtf`V85x24eppSiR17ljSyC zAIkrfR{tHf`ITn;<*k0LxlSjVC&TKwC&n+3i~GTQX7#c+jMc<7f|BWJ7A;cdXq=V+!2P|h5S}|bq*!tNk~QBH`kMWtH?y^)Yaee{SJ|=XCCl*3{(Px?!*|r9>00}NI8nKu zK=THnPige9`>CSHqDBwM!}?d#$7Fky`ZQ`L=B4RlGM@JT-f$DfNzt?V zX!0!JfuiSR@q<;s8&*m`LwDJ?8xxtlFzC{WEe+<>$9jjN=f?Pv_MHDA=+R4G@rCEL zCVI*SmVL~+LD4|ZmZX7 zTswK$Q^Wr#(X+5=^AVc@0T-g0Ir^sH4Tq=h1{(9A~Ft)zSsj;iw&F{;?}5UPBo*UJtC zA4b~0tbYwS5l1ed>Qk$EQN~Ozj$A<1?!2Bx7>}k;T7C3*jSttcF3|KzCyPI3T)PO| zQdFI`9DNb`L?DHFM_jB7&-u zcaPW_vi9sA1ecBW>ck?K&VlUhj@E8UJ&Syj`GhVF7F-qZCPr10UMt;jpOr6aRE>S| zEJ$Qu6{^NvdC*4ee*{#0sc>xwcXzwG2G(TrYCJebh=bV&(%a7h)N}VUDMD= z5fErgwhr5k`?Z=r?6l>O-8%1~f2?4|Xxsh1@!QHwPSIvuzjqGsj1?@OC)xHX8)y|8 zo^ZVl;ulu1x`z|1&XDzew}Gh+9-@3$bvUcb z-U{@(+(G63Bz7FMQ7e;S$3Yvl?D*hkKjPpYPZQps0PC)#EbuNhoTE1h*N6bqaPIt~K}S{d-xHUbVhd(tRMm zRt9m6qBd%Bmm2RTo2^i-k3^_7 zYcZSqUJ0~ky8&DTFC0AWmf6#N?}U7q9Z>qz+Y4s>s#GMBa}oSylZ0ZEnhRoVxjuyd zc+}P_oH7e>N>n)1u8r|phBzxOKy9FZIQKpKVmVOzv`^E@+WYNUUEGF7M5@+<>XUrq zbK4Bo+%Mt}Cg)ts)Z!6$h~KA`MmhW50ZEjze1Pq+Xrr7xAI5fA#3=v6HiR>y7Rt-j zmGIa0!4ZLh4{np zZ`fg(JL1~Ou}@w)Y;=g4{PW!*bL_uihehq1kEUkbbUBN-Kv8bj;c|a&AAq3zPVTx- zJf1aC-nT}xZ%RL=f%3IE&o>HwPmJ=6^XDQ|>uwRsPj_jODO!IieX~hTPtPxB#p@#h zzbOp*+`cLP6H%=s%0p+qk=bh*D zAU?oQ9)Ga61e}v|7EOJ*RpNjwWXmHRJa4U4rsr^%(iJ~CVO>U1 z-fokQFL+H+KDScRChTWohv?JpFBOK##;qLeVAo-Ize-V9M+mDimLI>U@#ao$ROE}3 z$R8-mOF0Z^&p8x=^0_@atbrfU^yL}nPoLP_AN{kUf%4)$=MJmzEJFGE1xfM91Novx zx$C{r_f>r1@?*1 zHiz=52HEeugyAS(fpXLF2Nsb$iX9EvGRW%MOA>c**7THCLA9{XqNTvGZddJoSS#gz zzLbwgA5uOZa$$8SpkKbfkn^_`{a5v_MIw*I4wo4HW@()}Vqb{gix7Ogcl(B;JD&t@ zHGRBp=U3Go^w5u{k1uCmsobYCSl0-vLjnEm>{r-hK>S{W8vQHR+D!vKvBSmZ-#q#= z)szCggLm(yKY=UkaMc_tmGAi=C7LM@f-?T#>Oz%$t{U$p3 zS;BfpI0NXvcUay_n->L+1Dg(Q%jKV{#@w62xfeQG!XMIN=JzaC=}$BdDer4w=gzZ? zuv%3&!Oq?Mv{i%MWI{&7ALI8@C|lV68@HEI+~>{m{mBPUU)39sc8^=vQ?_hQsC@SjkL~09;MFvdA4}k&l>}OE6#|(mWrcK*THp#)haR~uw`{o+%e!p zGgidwom8|L4xC`;PRthnjZ>`9KV{1r)095oHD!xc#uWwpId<;&ydSZGv8DUTGVsIL zxqIIOdH?Ay#eJH-ON+_5&EcQ0Wm2af^K4jq%9c927w%W?&uFm4Y3X%iA^#V%rAU7E zooYQRV#^Etxd!|`6|SLX%lSpJ0Qfg$QL!bcb+xz1Gle3s<;cJR*_!JJo-J1nAFI+p zXw1KIZ27Uqxb9-9 zJk57-sBJ0Dw)|hp`#aJsV!so>b|ke~#QZtikrcD&f?I#iooL3K%?Vc{buBSp%Az+< zCp8BCDT``;dbJ#O!H%SuMg6WUYKy!VJCb4+J^Z})6Y_A%qOE7wJ7OKJ8FNmJ)R7#@1y+qRYy1$nRrjQLHPm}ZQT}_tQEf) zi$=ZL!+js0su%8!@8E~!)5c5OUq}wjYv8Ln9_5+M&esG^q+%3WNVAJ+Mv`63zHCRe z+Eun{cQ;D|yRJQ+6OK5g8Kd4j?JK*Q2!3hCsG6UajyQe~e4*^J+i~J#EheYziawfJ z6};1oQCrWRDjKi|>jmtn3K<>P^{U3<$-ouAH>GCR^6=!N@T&|L1h0?IDkLy^l7PqCv~udwC|*LycFgI$$hzM9I!GRm&B za<*1}6}9#jnem&+|f)T?>NR&r|w&4R#qd-fLYG{jeftSNx|AI%=G& z*>$P$tNo&Qp<>tLop!O}I3=)aUp4(a4V)|4HFRR(Q0ybA3(u}i?>qDr^^e0GyBu3w z+93E1;T*8*TR;r={eyyxdu8lesI%u6U9YiY&GtGh<9=UFqdoh>zx8kO`4?pi<#Xmz zF%2!GVjAR>b$xWYKrG|;%CL?qeh${v-5!?(eql#g$P78wtz1_Teor%|+3iUBwJ;BP zf@VyMK03R_=0V50>xOlH{}%fIlyzUbjM{?s*bx@9&T&DV6VMyKSEgp& zu1VtqO_-drZqc0aW8go9T?B!3cRK2s!9NJQ2o|&bH-dGpZY>^QouXbx@vQ56!`YwX zuWB8|v(EZr;U?$@JHkR{2-fBO(Cv@>M4TCdb#Ir(#9$q#8PjwRb>49C0P+ONx)pEY zjj;aGjA?1*PSm=y4Lrh*usWu#xL5Ys{zuS1zgLEJ)C>J4_VMeQ=3Y-i+^4LI^LJdx z#WljZdOL&cd7Nvq?ry2nOd;NhS(i|uySr+ABx2o`+exDPGHTY{D0{pX@)l)Lu}m^DP?*o$#+5>sng(IF5WnqcGM*EF5#4 zt`ot!BDq;Jjd;zU7<#;aJMMc|HTq$H6xKMq7y8#K%KM)DUZ1erp>CyKzX_Qqe@rtr z3M^&&&um9q%+f}0pIQPZl%<8{r`I7*z>YS*e(QGyEFE&xu|DD#cC^FVx3eE!>EUOv zwDZNCwGapSy*@QdFZS8_3hQ*u*!Z;5)-8%7*9^$fQY+UiC{QwoOYi#Jk;7lHqQTO&lXvMr&nRM+{@(s)T3ueuz>W2riTBWn zGH=_1Ms=}2z!x=3cf}SRfZtOV6-(X!IGQQWV+EFGp7zg&9aTli(#4+=PuOh zABU9pe}&x_P4=?i^A=^cYWA|YAjw|VpK|wwkFka3{T|dybz@@6-uhQZJck`Ad(X^Y z`w9LTJN07rmfn2+C-O$@)Mu>WGh48C@7(6Akw5j)Qj1BHOl-2^v~~As@W@Be8~>}pWmxgvp28% zK7=osW{eGzPu%l34UvXv&_U`%IF$nv0*r^w@ zH{#*}8T6nTV{5LwljS!Mae=Zoz3U&(;om5GtHtoY)23cG^6Y)(m%ak~NZ6_8*NyR? z?w0C3;LipIFX5jld!3fsp5k~)*c%nL={WKq%3i~H&Mo23SPGgg<^?cQ*!GyERE*Q#dwZJ&qvh)0y|rsLP|0RAc4pLcV44?lxD6JoX- z?b3Y=|AspgVzwKZzLudqzt_rV)L^?_mGkd_TYj%q&Gy!BPuyo>nXpSFu-)+BuRP#c zy^iJCzPia@^U)7w`>l6w*@(-+E)gD^4W~@%{dg-HsH`WoFvASA}NrdMF zJmBWt=E;UZ5aM#Ca`Kre&4q+XHI}<`r;S zbIa|ulcU0Fr7WwAacahD!+DPnhKxl1K-u28fAu4Lo~+4sqZGp@z!fW^SRHiiTff7v z1pgprd#=o+t}3qdzvfb!S_Il(+xU&*8z;)EFNq0@b_RKGVpI~>~ zSrN1S^V_NGkdJA`cGK}8g^Rl*j%&vD=iMUx8gGZ)Dck*1nx!CaQnshY*@R(ThC3@_ zw)?eTRfzH9&Wf1r3}D1h!k=EeJz=*NpAA-u2kfJQDj? z{GPCy?Jb*b8VP@>UO#uP4YupGcvBA76=&vP`{#4>UNNzZ-xF4|{m_sv{h%Ms*giZ* zcXrGusUg|?OL_>&OH6HU9QaidZoXV`@@=SpLKo?@WT}m z+s|%oc3tfU)NDWgYUg0l{U#OLYptBet-pk>1h$voH7SzwW5NL?+o#M3{;AGGa1gP5 z+Jv_sK5@^}3eDLo$M&Or*B_(#1K4gUpW9e_oo;J5rPrr{zym2JTbkYas<{EdwK$18Qtqy4dI!c+N$ce9gYM%-($n%nz?|{8@uTbY@i?N9qhJzw}oA(cZj~}$~}jS zJ4R#1-RbDD_v=b{2l<_o8OT3{-L*{Pt5NU{?XveTE6wDZxqyGl_Na*|@B^B;Kx*8* zHRI1=eNDZCo|jiw_-E=JCPmCS&crg@F%o-+iRE@=!jAl&w%R-7zaH8ja@;ZE*Xof*#amPsP9m1=ee*_!~yK91XxMSpa0ePl+-OhW5`1rw>p?};l5_^ZY>vQ&D zpAC16gv=k_;oi}VJm6L{7g)M2xm6 zDKj!s@`iNMjgt&?B8Fp9~5;M_~l0gxxD;ewK^2V{E@%^h90Bp;CnJKL~Xa= zph_Kf_IT!n`KdIb4nIB=)@Yz~%0EFJb_@uq3O(nVqz+H3L_CK+^DQT@LUymN|F9q4 zb(?p|2zH>@^s}s5l!{N{BvsuAiOGwqA^Ee&gzZMWfO-(*%DhcMRYTg>ql)%X)p&Ej zT^r*=V)BY=e5vj!e{LxnJ}}P zDf`d&uTTl9aVqiprj}AaZ&PTtzUomZ=T&)|Vu{b1`x%eGK~XhQz7@rpOZ~`%v8vIf zhFKJJQdEtGYr9{7ogk`4iAP&6tRoVWS5)Io@T-p)e;Vzhs&U4m?mF0|qH2Wu)*26; z7gZx@e*;a-L)L?UYCIh^dN}MT)`Ng*tS>p^hwQQI)B2Ol zYe6+!-X~cR`<%5YhJ}v!U{WC4Gg9Us(Z0uyo$J=$UG`;s$idT8H(1p;ajNkIa71p5 zYBVg^HB^aDDymU(HhwnVm#V2%BS3eWp%d+u{-vt1!R*l)S zkIDI5=299^4ND!D@1kF$A*n{yli_;I{iuFTKkI6PfHrFVR4x|Ta@Z#g#_m!daT)yf zl-hn%_ewvg>SvJoE3Gop_h|l8Wu&~GoKqm4i=r}8eX^WWP*f%&D!wiL95R2b%Dn3k z6@Ymws?3TjCOViWN}PhIOocbwuVX&5o(ojwgOlYC%tIQLeB@m4NmdzyH(zlb-Zt?a zo}o8o80HT$f2_(p{!~T}d=ynCq0F9l;JBzV^CClSupW{5BXJ5>cc_eM^u^BLDKdX^ zchCLM<ET$z%~Z5sS>QDrK=)@^Ps^@}RA(`{A*@E4iCuLoBKdhNd+U#)}7d(+pwjKF>{=2;(M~> z?2U7)A7kFijZv90Z%)5a)~}*64PraDqo?Cvsxlte&s^pFCY8#>MuZmdb_G$H&s&~8 z7W@}kW#$LWc}1Q}`72NvljEBfVm@=2=WUr4SFA5Dzk>HpqoGt~ z_RMxZgL$jOM~KSo-do!m>xJY#6qT7i?QJTq!+JnanI}!Gw4vvs%5*%nO9SJ;+cF7d zT6Y_AyNcA$+cNVahhKQ+swee}Dx;A)egSwVs?66{2J-7g=5pgr?Zl0<7FU7F>~I=3 z9QGS;%RIZE*Y5sJ=rA&u)B}Rb+&Y^54(pLdLp!w_YYLT_dtgo^bVgK}dcy}upENCf zF1eJsWL3r{=H4gF2V^euTnAUUF!9r2s7%tNZ&xtRB=Qf zTvv=UjfPT{DLLv`1M5hMj}VoKsuEmA=Czc$WL3tbYE;Hv#4+2|ee!zsj^}k^r zDvhX2jusF+L1#Z2<~50rA@P@?ZNYksx-qUV>{x;$jGv)wD;rkfp{*Gqfu08)3&=UpeH0pqo`8L zrvv8WIy7oaRjEw7zUQDPqAD$1?d&XdYbbFUqDs-@H0AF>K}MFuWr!-d)^~M=(9@_b zJS?cv1pB~h`cgmZVL_GVm9=?<^~Kvh$8D>g)3e4ni>g#}&Kzs33)aJeD($Uw)d%xX zuzezbo6UE^I3Oe2vGKAsMKKKv%3Jp>EIznrF#KFmmG%UGe=Wyn1XXf5bfgG6FRIdE zt1Hy+V{D&WF^5wAtDv@L7**Ofq(h>Wd>#BpQ6<+-9lC;ds-{+@mQ7c7z_`&yRq4fM z!zj*gQmNAC)n)(i_6$*_FM}Kmczx55RVm_j^&UdMWcyTmv3==<1~>)m{0E)N0MI@lkk>N<4_DRjb{9kDE*V$S6}!4Qh4KeV>D#)X#cqP^-_Y6W=wG`gt2_ z-rxI{mn-2tifR=-zVlr>sh_u@GL|$cG&I8eL`IoatF^lp-b4Kc$uT{y@FsX)Rj5^s zf(_2_2YDN6(<}#vuJy6*cpGYl&GDNtMY>YIs8)wlPJe~ni;Oa>R`>lA%Hw{JQD)U@ zZ&%H8xPOvkQq(HXdh$rjE8d1$xZ2icd8%w5s-nnLt>PcdvA}bQYPGtVbr0MR$uTKv z^=jq3G3HXg5)UG3wZs0;Yxq;Frv|m!rBnMF)&*}v)tqzZg~b8rh7u1VYNeMot_+@w z^VB4@DmZ_mBJ2uLtxQ`q>w$Sla!kZidtGl&aF3huzp(C*QNHB0vqyk#nK$~bE{8s+ zS-4>yvYy(dPlv7Y%#$jR_0HN*hf+#(`d!4hNsUvh+^l31*HNl)9-&W4hPDd*^MgGrdeS%$A{_j^@|rsrz8!tda1uITX{`Zv+V z^+_&_c!E%|4|^8Rgnufk*w``7jW9mQl(Q-pVeIxAb{aC}Q>UJ>7**CL1}ZlC_s-Q= zzpN(+70XK)*$?OQHrL^l%B!Zm#rzjlY(!{#f4neJ#YX+fi>)g4BU8?*m~+L;wQ+r9 z%IB8RE|*%)q$5-;%k}Yb7~&)srl{Bs!)Lyj|Gdq$x|!CnWktAuWXf3;^YZH30`r_k zwW*3#uQT8Z_^8C2h>C^$=)N0zLULim6NHMDuVa}C{ijiFs$yPVp7(KmCf+2g*uYu4 zp5Xet&1Kr6)&u=X#!^2r<*bS=sogyU91&G4;C4V9>~Lhte|%VS9-bgnEX4ooV9YB~ z#WpP&a1Hk@Z3=B>J^RP1X?rM4~9o%n&MSjS_t#qZaURqRcRS+}_B zNWTFU)A3so%wI=3AgS21XEo=R#bvn`xp?{e2OD|2Q9i+?&j_7h_46{nvv6#nrKq>$ zFsV!Yx9UmtV^Re`Y1NbLe5nGUwCYLoU(V%Kc(Z4A;Ke?-J$xFa9A1w3BdXqz)34-x zH#EvVeOk|WsNU_-5nb>eQ31fI-pf%3;g_KTfK|Ohx9~~uJ4h~1QN7@8jibR|lFL(6 z&;P>a@|bVD?G~_W;nig=Ye@Yx%1%|!Fs$S&uCK(ui0Wm{Hgts!vz{hY?~cLltyu4< z0AN*b)4IDqasRySHg?Rj#rwBmo{Oqi?Ac}w-mj>7;{t8t;qNH%FQR%;$s1c#m-)qyBW+H1c8vsb5q*`_m1RVGoO{_kHWg zDA)<80AN+GXUvTkuv<_8Ks`;UUV=l7@!*=Mdfg(68p1v&xjaSnPDi{nM*NvZ*{SLk z{^;;rj(15F0IcfG&RBL9@15lG6xAzta7`h2q>i$yR8P~nVL9j_>uEyu3NCETkh(QQ z)w43(G8@OLR6ZIa$L=u0KHq!0g$v z5h?e!4av>g|9*V8BlGcGqU!nGd36BqSBZbYb_+7E>7OwR?@?5}-j84Rf<8-)Q$2e( z{kIr@G*>h|*L zPW(VrZ}7yDX59HI)vN83p@(r}8&t1VRlD!1=TZ(ys+Y6F$p!uw-xiM5IGk%rux3Nf2*EUZ}U&plk%8S1p}*k6+N%Wm*#D~A*WY=tKAuTPI8Ni>ZP~* zx!hdp7geu&^*f=6zlo|hSZ~K6tP4~yu&Ng_>4g@?4HXQm>b~=exkci!LiL<( z-_^$Wkldo8dSMmA@-Ut>>Q7a#)#-rl7E-?wUn8p5$Fq$5IUAztwf%mkCb&bR{`u)^ zcR}^$HSg6Q_7ZRF6?@)FtJE5L%iDV60=H?;mG>Rfs6SP`UD?wdz;RLaf|B1H1jkXq zU~{gV<)&@-{h@l762gXokEmeC^eZ{q^6B2LP`!mF&4wcm$=iDNr$0OAeZu|lw%+%x z8@g!7{=2Ap%R|lTLC;0ii&*(P6n~eu^}0p2uIBBH`$q)>t9s@)(k5X1tI4@VMfCr|Ue7t5ZH7qQ8lvjiFUtLaI0-5kK5zMc z-?fwe*TEzG?#y%PD}Qbqjrvp7TWqwkJKhU#>-B!@y8SrW@F}RCv2}1q@Jm#^uPwY2 zz;UT@s`vEj8(-pgOGg;hGjR#)px9lC>Q(a7V!uB{t$Me@-sQ9Q8&y5qL!%eK9#A*g z)~oH)=E$F#I_ggRKvb`NlV$pHpkFyAt6tc{04vd+gz7bW(%l2=ly6xRPi(LqsMdMq z;HrSPYugGsEFaCub#v$IQdGaBs#E=!ZHP1eWgDXZ-zq7^oumqk-Ft7O{#ey>3{*0B z(Vg*4r1PaZF9TL3PoDZw2|C8xhTW@AdUV4V_s`pggZ0+_ve^wjiYi$*zt9lZ5mhp7 z+EKY402LUlN;ZzSEr+-hDlk};T$KLd5Z)KbjVda+F~~_5eh|$h%q-JU1J_sLdJ)D@N#h!K2Vh;Z9x+tXz15=!n9n3Ps;Fes^m)g? z3*I&iN_HIE)DnMJRLL2-TaG|~M3uBz`^N`%6e=*Hs+4J$XYE`ODmm}+*mT%GtVax$ zJefL6&I|Ci;quT1(I@=zzIfX(V&#CqiL(7kvk+Wu~~}iHHAtZeN=u5<_Rh=f-*j@ z-n4IbGkZ5<>&g4tg<_ubw&B+nr%jJ!$#$lolBW;cdWH8WHBKe%id?kuylAXSE*rIG z7UrAW7?sRT%g|T+Rz)RO`QP86j$5j2!!}3iU8~Z~Ty+`zLsjy&skssS7j;vqWNMbh zaZYbFh)RAr-%}qt!#1eoue^&r)%s5lN-BBj&&ir{zKQn9|K{YbuVg<0_Jh#gEwI0o zi1#Zt{dpNzz^_tGRj(_?6X|*XvN3V&-|8vViwf#_;i82m;@GGxd7aaJx80&G(_Htw=wJHPgxnV80&(!G2^Dqf1DBoKU!4J_dn}Q!Sjmh z8M><8c)VX!mayvSaIt4CtW%Q1Rn&9w0o%WrKd3Ar@x)E*pq|7!Ri?o#<=!8>UrhkZu$GFMD?6~yX*?+2`Wpz49d#s*kpt!)bnM3 zqiV3DP+1ajyU&3fJ5%eYS5F^UmE_kL^HWsMTk{jTnxkJ(&+s8G2UI%7spkj(ZeOXr z$ExSPlz_Vb$=8woqqZ^YU7PIib1BAwG(|m^rZ+B+`KD@W^?dg0P7>A^ZB#uU&9ghG z*uywV)H8bGp`#c#rpfAAKkst~%yYIuJ$HDSY{&fMnxvkNhi9Z?J@QR|UWY4p*T6mz zT4axr+JT}yjB{MvCiK91FV$3a%cz)9vNy_EN*t4V^yJvTY*ifLZPg1GORi7Lfc++_ z?WLiQjh&=^l7m*%RzJ4EU~mK#Gi!d$cpAJdWD?ZY;{N{gno>V1W?JnI*zAAdl{M7% z`ETpa^0>)4XyVZ~j(`8No?neucrU!I8oKIEvnBF=D^YD7+PBjJ7f><7s_o%^p_QQj zqS~H$9$5(gPE^|;wxI*SeUgJ#)OKKex<2A&GI(>9FfWwOzRJn?B~bsJ1qNEPwg2NU#5Yhe!>aA}KAW~dPf#(l!@hc*(-G!3ptc43OhYlBd0VyJkEUy0 z_+WfQwQZib)CRmm#f)B-msh!i)f+)=lU|3_!g~?bwu5JCdCVVF%&=w>pc zM;ffO+A#t5Pjb+T+Um5=eh+($W^bt4Mi0=K1v^uTV-mG(`|W`P*0mDHBx-AaKx-U$ z!Fu#iTf<%L?%=sZwSA?vsxSD++p1SSe($sR2XvCRRcGHW=k;0}<0h(Y$@XUQ=k|+g zyP)~cBG_-Jm^rxNYs$$m6BoOpTk|#T9-oJO!rQ9hL!w&@yd`x@_1nlnziDxz`>n9t zv=9E(;`-JlI>xK*qrdhuz*DJlY8%=9&oQcptlCbjecB!KL~e}QUR%-2RJOO}1B%)n z-qx!F<}GbhZQWZO{fPCbZYs6){-|{wexK5a+Aevy*_4Uv;;^i?566@VWpy40pteb2 z&sx&^N1xmzwXIaWTAk8%uZ!FH@(r>vPlUFxYKUzQ*qNnTQjNA4H<~r#)mE|-N<{|9 z6=>Edz2(VMirPx^oU?5&4XqGTz5rZ9#Sg2tiEfj>mXZ2JwM~qxXoLF{)z-=Wtv&it z@x!XEceqI*c!Y|d69Wvx!YVFGhuSV{aT2p_d;^zirS8Cmn7Fg@wV;4jYCfAzJWc) z+qONM9ysCE2lubUPl?)^4d2ob^G%7L618pSy0RVapN$MaZGA(W+GD+wT)CpQgH}Ij zjCs!6w*7;%T>b8Y3%qT+Yk$+!Z%Z%^qS_8VJheKmFRJa0Ci~0d{!#H0@}uy_;3-=M zLTwE`g~@fTylvY&vDh)s1o|VYZGw|;CUgT8KLclJIxn`^d~a;I4xY1S5AJF!^^0oj zJ!j!n#3fMiLn8xF+dn-@!W z;JJ9)wq*MTW7`w3KY81BLG#D8^(}B6QEjswDrP`WQ1R38nEBR9e#=HdZOf!qIfVBs zs%?Wp)2>ptI%{NmXqErIlt+IJ4ToKp?H@sHn^&9ei}%Pz29~BztX+2ZX&Z1;YMk2I zx2!UsbW3woj-P%x|7hOfZING$Q!uYcQ`A=DP4Q^8ZcA<$A_MjFygxpC;G?=c`3{=JZpgwn>dP4yATG`3<7B>o)kv99R8e{3EMv+xF?g_W{ASJzw5rd0=aBmTQvQ z#@Af+v+^qFiKxyiTWO7eUnZ(^vcr{% z=2AZ@nX+cLI=wN-;Ud)e=Q;i9&`;hLeyR2Sc=k`&8>nQWkq4-=>D4#4;Q!L>R%V&r z)uGNGz6|{gu8Hcr@$!)B@XJui#HzEkRfoPcR2idlG7)V z2dML}ju~>D1I=zxb)I1K*aCV*vs+Z1yXDVLsV?;^aa*F!F&mw$Ku=J~#HzFF(3#_5 z=dh6nsB_J}Hg@__KO1>~I*(bkWf1&s-WDEwIOpx}c<_a{g>N+3+%HM4pApshRmYOE z7zb1`(Z~bTdC|#S1K8obEu7%g?D*NLn75)jzq|L*5$l(?g}vuA^XY32Zi?#Me%F$2 zIA2ufev$FbVLzjiiB)H>FTSa={V(VA6?JYN_~Z<@Lvs3xI{W;+)D8kcvs+Z1vsOor z!FwS&{l!K`FDuW0I-g3`p9Vct;@NrG8X04W6i|v+Iq} zP;;ptl}yNPA@UH}zIn9+7e5+f{_wVN+1<}~7u5srM0I|({o8#9^b6`7x8lVcj1L;C z&Xy(7%J&O1>YQV`yfW4iX^J|VZ_JYYJJkWTI_o~~G86U;ZB(7jdl`mfoYhUG&Kd=? zH?!wcbxsXxhUvpLS)H|it}iKNKTGOdbDWVc>{7nDJx;71JrV0mXrnJRs?i*Fso37F z+T5Yk^>LD_o}bUQDZhRJC=D?#Z8b zEvokPUlopGek$=|qS}`R?W_j-4V73VUQATG>h`F1m?t#bR^4KIAE@^8`9aROPd0)9 z)h=JP^&6~5-ll%l(Y4aYxuoSYZ!S zv!4CBw!*&UtL;}Fx?ROO5{^H8CSNfOO)Tu%4iA}b1_PI*6-HZC& zhP}izS+$b~9?KK@HK5vG*T0{ydM@QxB-PeAY~l^Ok#Fx-c_hv9=J-NR(6{~XjUIGN zY?0v!+K6+OYO2o}W@{?gbN;RJQXWK=735W3iZ`mVf>h;o+Wy>(>nU++qVn2SlZN2_ zl{hs~`Ou>!ORu};~@2~_@Pxnqyp%GsPYw) zHT|$&c-uUG!m}}NEpR`mJY!Yf+b}2?I!0rPYj;Qi2zD;k1`H9LiR^^@UTn~mFh{`io<-@(!Wn!+)T!Idsm$%KM4UEgQc;7zLqqMV0^KFwzXyAvG0>%Fk+lq7|N()Kn-c@2ORM z8~mkNL8|f}4v&|=M~P+ysmd2r9#$T9h!UqJD&M?um>cFl8##f>Pc_+Qjd`WSsfo&K z`8+<1_$P0h4{gwSw4oEmjknEXBe%EI?hl<5RX%U^z+)I6QROFu-jlx%5tU~&asrh< zTf6^D%pcx1FFv)>Pa_fQh>e`&m|DL)u|Hbh9Q}gIhuquc3HwKCoXW?Vb(6mb1P54^ zAD0mH8a$F4qw+Q0UH5=l5oezq+YZKI!_CV|b5B zBPzdcRNZod&dVx)!nLJeUFBr?C#d|G%^lrU&!rrdRKD3%BiUb8I`LCvxLL#Jt>K>v z&85S=^Fw&QgPgJOa)z(yc#tDx-^agfd>kh=A)@+A^GB`;5!GL^uT)t|s{ZRgTBl=v z(kvxa|KtR#^%w_H{WGS{U5{~7;^svC|0Y~CY$o-ykr}A}`>=tsp71t)#pJVD4c*|M zl9~__nSuJJZk=-q^G#I$RtEQf;P0ZMj#dBaS{9X|!>Fk9nv$`1Y&&a5sDGlBb1L+c zjm$v(oqg)dc>&(WZ}BZX{LKT{6{7mDoc8M!>^D*UI~Jr>HJAEPQOBx(Zsi`ac#o*4 zJ9a;3&Y;zO$ zvy@c*Cz(ANXeae6adV>n)wXrsXDaoRnh+A1f%omNfia9?H<^Bq$WgB{~=F8JfOFvCPYzx4@W&uJTJ{sQuW`nMCS`QtHjNT z`qwTo{?kC}r&&s>{=P2DQ(;H3kr}9ez5dJE;ytpF8K{5$&bMV?NAWg(-s*1+cFu$z z@;3g2(8U`U9mjKt>K|_zISw30MP2kn_ZAv&EK8vN*`L0&v6lLkxH(b(BkoqGVTbTG ze#pIXJK7(T^;}T@kkP4)h@SK6U#zD`_7$q*<{AZCUfP^|cwyy3>PN8Z?;bP0wY~Ir z<;JN0-X@z8G0v){R{!L}!J}ah&_>n2XQXE+r~fMT@3-@7AaA!5^*`aRwG;LX(`5DE z7v8#y$OWkXok4?_v42lN#r5;$PrJBy5xtKqE zHdQ$bm4cs9WB3l_k zuS6;Y+XnOmzeFn7=}ozBF7+$%dP0R<|Ewv{B~%KMc)evFs8BHU(njbu?-Q(?Ht$Q? z1aOo02|5-8wGV88`UH^*6Rd~&!rvFEV1IIbJk|v&1z9RsUSF7q`$453jr@QL+m0>! zhV?E|p=Qe87O?k7?TSK$+kyV`peHn&N~v(pBQ6f}5S4-~6-LfVdyn@^YF890XwS<2 zURCO+*;Gme%b!2DV*J_252(;**U$por$~jf-aF-eM!ZiD~-A{EO1T)fj> z>PMwu+iyq1ng?pxf(jW=^$tqi8mJVsKaiZ}^Y_*|P@(EpV{1GY?-R5vsda9WJJyjB zuRlK+R9JZ{`vS&Cq=IGJnL6fDzet7Hb9yCsE>sG#RQRUZ|0{G4m4Yl4o-EY30=*@* zD+(1dZk6c352e{uN`sn(fW8JZlpL{#_7_%H7f7oeK_G4 z3ig(_HnDLhN`=6d{jOr2s+)=mcHNv#@cVHH6`s5AUc;R)JqW0K z&_ZKI(+YSmA}tns)s)lYG`m~S$=eXLSUW*uAP(?8M6hjwX}cES1@A-H=?%O2w-$7X zW_KwqEIKWz3q2HRQ7?Cz3-ke%j%LFr7@gkjbO*E;{=z{6{it+o=GrZP=9F+R&|+VV z>jqqh_aP=&N9AeF!93)B2>X+{vozz-FVdox-@APnXOR}it~wrvzVSXp&6KvWl^$YU zqtcP3MfG~CM_@cj?Ttc<^M3~%!+H^Ev1)XYTqlM~N0t_8>22DYOXri?8-*6nz4k^o zk@}T90ii{us%3LA|9KzctoOkWw>~2t$VQMri>$o1ldYtF-iIjr^Z86KAIx)+7Kv%U z-sAcrEuwqH$@w@`I%agrTK(X-!FkZ4;qtvrq31NaOKIU)Toed9hxZ{Y+lFq~84o{{ z_aS1>HFf&*8-|ofiJLW_QZVbu}8LZu^1 ziw&KgPmr1nOkMFpKdR=6LU-KDf><8GJ_UMP72LJOzpKb0^also~UMXwEmlJLBw z_J%}|K#SC4-!5aF@;=1JZ2i}9a{iRm-YB#Pj9#3tDV;CUBEV-!Jaj;$MP^a1C;Cz8 zxNd`auXbI=B^2xZm~c00+BDb+sB~=GUZF+By@9Ra5Ar^QS=Jqm9y{ z%>W&9JeRtuXi>|cu?}+`=`f*%pT?@QSnq5DE%G1x`oMqWnna7WdWrJqC35{5Io5g6 zGwMMPh4!vRk4*Y`R@@l&I-3!H=6#OEUVe_1Go)?}QX`~L zWaOrpnHWzc4^dqU6v>X%&&4`rBT=A8!rDE1p-ZGjNTJB1PW3zDK6#&`UT)1ThM{=x zB1Ilvd$0iSSEPtj<+2@dJ}Nk4HtHJvS)N-N6j{Ez#%nw;8;Jr%rg+TX2Y-b3IcoW3 zB)6LgyNmZZj$Liju%HU;Qkre{`FQsQC=zw5trg~>NReHQ8{Gt_P{GMk#KyhbQuwXB z&#`K>-R{q2b)Fe6k_LettNE=cwRBwwY3-pw@g(*zGjiOetdU?BOKzqk@yAh}CS* zYOrJ3NE9fN|7UVL@D~-FEJd2zwcQE7gZDWCe4G-tc0}Bd_c=0)ey9Dthjk%RWKm%H zWcWuSMP`kB*c9&t6`aU66Q5)7dVA{zPw-xpJjC86RWtrNH;jFlig_ziT6zrye1nnaQHmhY3* z+*BXbH;ow3W$Qn<6FK%%Lr<)0vAH;Y%)z=Y)l~b%NR1QCek*7F%Xh(1-glwYk>;B! z`%Qe8gx3K*jwQmc6sZ&2Flq$s6I7AG1SbQP7UEOn-6Jk7*=q1kUroy_$wra-rq{0E`Vt2UVA zkuFf@%tpPon76#|^6=Va+pHdS@EF*2yzjEB@rM6S zzJ@-F)VcogO$FG!s7xjKkCC%Lop<%;^vC(U?^56U*%BQatUHl9JFc!?1wVq+I4RU= zR;>35^HZeG*($xAFrGB~O{o)C@_hrwQ^|i2>bzQ6sWJRAHqr&^^nYrq3ms-7U7*g^ zSqV89H{N$iS=+*Y$7gY9ee6kSK(JW_I7dpxNF6(Wgb6a1Nx-~@VEKhr9f_1_B zE)&y(qu;N9eIimPfA1qrtQSQa|szEDDTx zIH)1G!}~6?M!t?Ro{V`VQYRo|ln>?u&3;qr*y$v-fc~H|HF;pt_2j~+^(XRQwrups zCj|45_g!*7MkbEv4!cXFPUV&svtg%+)XD66rVsozsd3ba+xT!E(T*lMYee<$JC8XKkioebGj#lQ1q>&O_0D4Hb2wCO>e)dr=yEms4FgO|iWO z`;%!hbrOsx20;hd2I_PSeo&LYj&z1ZopLQ>V(`BB=Hj?yT|-N(7ojbjIUqF{^S@ME zWEloK0hP7dR_i~~{0cn}m9?QqlM}2bE{Ia7BiXTX&6PqO%}qJ-pXGg>*oOA+O;T|! zkve1ikH_G>qq3HzPOFjoPeGqW>O48yOBZ&LNFALq@s03aNX->Po&J{nz$2Pog7b$@@B{ zcGY9_D#Je#sblW@Wf!<3QpYIwzd6uhRMs|cyl07&U)cugjBxPvgFVdqI?L16)N)J5 zdqHKbmXEKC^|1}BK%IpA0awhWe%{x~-y2d=!3p{xQYZJ1;d}6i_jO#V9U6aRKHdu| zYgy`q{&EP%^YXsV8IO&Q7UtkJ&ALZx?XQpfAmacj)I)Hb) zuantzz{DQ4^`(B1I{UMKR5eDwTyu42&~x`T1FFA$q2ri2v>e7+Y8-V|eA&7L`i90* zr}-)KbFeo^Q>fG6b>*Iz=c=ZrPOX$>Co0fh>0e5nq`x0_AU>mRD(Y;usIPQUJ~VGl^u*%tjFnZLe#!lJUTAK8f4!I5hl+ihkq zq5fI*JvjfSlw{ZalTy-taH%r5G^M0^RH-ufZ^H3fy^3460i~W<_h|*Yh4+od_^Cyl?d6?A|-3rvXCVH_{p79Q9@}xR1(UmQtBDcU*$KM{2_qO6|(t z;tjin_l=tA-ul>b3+x}>H){I#YnfsGh=VD49YQJX{}MOCFIMt8gi={ey3EIYvJp8@ zs!_k#Dc}gH4O1xP5Z`GqxWoHKO;+m;`>BI@$oodwN6Kue90&f2l!|)TXSCFy)9B|l2%q6^omviRM5%R2Bq%hSGxz!^1e~-pW`;I!{9Ho5jjw* zM$KmR@!myB>22#{2^~XaFv;s!%?72mfBxx$`ysVq3Z>3Fhirq+pfdP~dt#fw=;n5y zRGyCi%tlf_tpcEwI#xLO5#|-G0-%&?+i>G+_zOy2hfu16b@!ndPf{CpU8~|=LaA=y zN$X+1u@N~?YJ<-uZSVz^!7Qch)}E;Yz2$u)_hCo%%WMKqMM}-NdTTlEN2Js`lSfNn zr=c?VgnMAiUapZ6d94$>4#ZCajNgms~6YDx_* zQ!$?95vA0MSI3G8XH~zUqSW(&?J^Z^;uxV+c#+3Ftaql#lyX^FOa1v*>SGe6LJnnD zF70Ps+xU6LpF)hA&_>sF3(^$gkn$<-7Ph$zJFrw!?W6pckA-vpO)trx66jUyuD^U~ zR5thS)TZ8>zroKyFW2ChwOB8_k5zuIUB7~^uv<{sOe1@s*OwuSmSMips)Ui7rf7g( z;q#L{@LVFj!uQ=NgY|{VW|m%WT5QdN-H6KOTz`vBk2*DL3wo_Ob3X~3B{gg$vIlyN z*mcv>TA?$N3QO0O7K|3JK7C7(p-Rg}E65BvgDHna3vWAC-pQR-(S zd!X0u74MSFrG7TD2YQwJVVnWo=6$TFhaINhG$7|bRXF(6aLikg zUL74Pg&?ni%4U{c7XJ65a6YMFQ|J{QZ*L3Uks3CIUe41`=i~j-ssu`}E-RlWLJvs| zn`7~!6m5UdYgR^L1m>HPPa^aR33!qW9Z>Q~gkDvf$H|{-%0~7;ujv*hR-p87x^`m7aP4E|$&01~>y(%^uR|(^W%I065 zZQKhyPV0eQT3aj0x~Jrm2)+6R7CK;_@IIE_w#X#Y%|=qcNUzSVGv&_%L1i;buP@&{ zmtx#RdRd-cXN&bnYS6o#>1B2y_&WMUdW~^5^ufA7WwYXA#ia%MZ;JrGNDW&pgNnbOy07?B@y~{argy+c zkzS^zeys^#czR7OYWEHEN@^UvP8B8X#QmVL^!oZ=L@MkSxiR!w=bAH1;etZ1d45;A zGaOOVYv|dvJz>AmM(OoUyXry{+KGQv^s<@0I77Lq1L#d|PPg**nNY4D1uZAPM zuSRJn)$a+kvt9C{6W$9dwl!vG8o6k<8VTC9nw=wmADl?Ls|#kGFPa zQiG?^F0%gFHFz(ydVM3b>UQ}$8JQktd=w1G+ zF|TO##El)(3_-iPwU;cyI$|S=pxwSit!r3!ysuVd*x{8?81z%5-GhmJM}jYGL=m*p z7_d*?=g#|T(TlqO>MEOcsMxMlb#&Wi#rs`ByO61?Ho>0ceYL{D!``jGgZIMwY8@T* zzwU5={UFkAi)Y&_&>vK6v$WfAS5y9cZ&Ylvv>VxQmt3DlYVZ`=jcw8A1FnyXZI*Tq z^LM|%xY6nfO1p7C4dm}rpw$zUb~b%BSF0|aujH`^?Yg~Qb{Fec$zu`P^>R2-0pq|% z6hS*vjpq(#>Y1ijwP9f$M@2gp! zuI3ZbOXinUvCY!%c!#uQ&}UR^v$Pu%>0TQ;Olt5H+P&QPEf()Zq}|W-8x0ZnK*cty zCn)WxlQ&uC}PXcrpyx(C)H8&L%9%7+@%!TD@N5wuIJd-ELZ z1m0IOyO8R*yaxPJ-d7vroHk&)4&IkYyWUIVcA_5@+brz@rrQ)?KA>XTPXl?Z=BM1& znwpkmZi9n~B(uSU;fBbEvUCBK04`6vaY`5;iRL(kzlnCHCDcXff~#n%DQ zXH=rI6tp~WM&2(&Y6zujj{cc7LBWRBZu(fiyw7(%WYF_|)6viSeEW-zx4iTif-X{U z<|97~tW#8?vlP_c*eC*i0V>g13MOuT7=iUdY6uky4*M^oBGwD<^Es_ZZuq(>^qE$3 zPzokx?F>R(TBKl|tor)sCpCl$1%rc5)rBr8c{M`8x0@e z@4>_=Gk&Z_d_&2r5egdJn&bn!g^gH(g7poTEQD^06fC#;<~G;^q=t}0EJ4Ag@2XYA z_@EMf#-q5BYkwSCgMvqP=YB!{h4=Zkc-oB(IonX`7b!T+tNlF8PmzLVbFLTSK2eFz zQZPHDL3@mkNWtmOCWkTKNDZMv!DmMJ5h7j!JZvf(}haFTlFseZHUR*SmHqi}@*1 za9)pD(_qJv8bUiAk27{_LBY`#7WIOkLaR9_1-)jE>keI2@@j;FUvfQf!Om3jYJ`He zTcezD|7^q(6bvbTtfM3Kvk^;Ba756MTi^ok^Yvc3#`?)YJeNqpKJ8|lGMD;A3R>tL zv&T5gmFS-n#x;07ebCgRpGOsW)x(Ejo`@9eW7WsYHECq+Su9v^pRX)H_aLUe2PK-aO zreKrf{)@0qX`>W;bg26$jHkM(C^&qke-h@2(g+2c4NP8*@no7z!T#HW28;Xx1+P!D z_)hO%{W}r`JN{fT5c7v`3oZ2vypzBkv5gqF=MwDmQf*b#X57!e>8PQh_NxwcAv*$JV~viLdT{#59ED(ypLEX>xf-Z z1H5-s*t2wOAF%Tj?w?kjP&%gC>}rqqtK{$L|?nzmh1Mc%aV!73twbBYQ74Uvw&54jlQeo$fm zYUPntktP=YpyQZt6^A%V{k)Gj%`5TA(`^`M-bXZ>)3|@dYPcVfj^mf_4aK_SeZ=X` z3+$$EsxI}T!k(q$jOFVip{uB{XX$vU#f-7wCaHB)==j9!d?)A(sdZH7_^i5PGY6@k zR-I5f9@~(!9{o%{Po`tY3T^p&VQAF}rQ_F~le3_=Y(x}vT-P>cA#{(8h=Ptup7rE? z?!1rqZRy^JX-2qD-bZ}*rfzoa9}a>))hb7O8vZ#IDE$E_Z1Ff{)==xxqV9Ue^S4a&#P$-ItqRaLT6IF{SRpm~6zpMIbwcUr zR%w+H*1M9=BXr#KWt=zs4ke#Q=;%=B7KibnRVRpuf{tMy&E)St;(f$E?QZV>We5M1 z_Yp1hc4|etz`v9BX>oLPjj^wQ^(E4A{`4`m@VunfG3oE7s;NQU0!Y3pm06LnfDR=!sI(s4)eqoS7R7wDK>ZgW}OkJLCiYIjXP z0{c^L3?1JLzqkr|PMSi;zU{S6Vg9I^nvR<)7S3V0M(Ow>x>5+nS>050Y?N0|L;ZK< zgM^M+;cZ57{FNRAbnJYmsFQL(97=2-lRZ#O)nV_=p zzeH+wn|bFo<_W3QRH#`~YgkRJYgz?Esrlhp*S@e%utR{Q=8L;=R(QXpR#Tzop746* zaD7?@L#g>Faf}i4mW`}}n*PU2jl=vDsoA)(i@d)H zI|LjWH}4l7zu_*Z8Lpdk6yt*(0=*mV>*YLsWJ6H%p;nj5;6CqDj$eLq*S&hMmy|r> z!+cQl_pJ>JY@~jXnvTn2UBGLRnnl;PMZzA#4gr>$>%F_q!}-`Dz)~}A?cBA{b5g6R zQ1jlm<{F4+s;gjB)O4IMa6arSQmd&@^TNw#^53OZFcljSYFZ3FvmNVH$s-bKcDgyg zIdqSWtb&@YzFc_^JBp30f||+m4BFtic%O1}C*ARDw_)9h)Z84qV<$L5t6(TK4dza~ z0v*E+fj?i4752?K-T~B1@UUx&_ycwbtcz*eFyP#nNKmtEtybpXDeqIB+}?d^OpMg6 zL91XWHDiMewqZWAkyTLhR=uwVDbwwO+x!6L9Ri=ipAQ^*cDba_zM?+k_o=D* zxTtj*#1Cns)I2mly&E}HMRFW zeMsyI_DIfw@>L%!7r88*@or+XwQ2w8*U&$4(yVlRSo#gsesfZ5DpFSZ{99GE4o_L> zeW~-8EM+BsN1*KPp=;&Od#BYpAs;OdfU+L1TBpJ;;(gOz9-iMvmIY6F-*m=}Ri|34 z1Mg_H4yCMigD$D96<=fgdEd0j;b9f(`^oWqfwHY?xp#)$E>iaV0y7KfA@7@Z zn;GHTr!DjrJ0e)h2CjML2kwwsQ-!jQVs=Q1f&#TzbjI<;$EnK0jR#C!F=&h2!B$Rc#HKH5VDes%Q z>y?)DXVSYZ!gZrjtG{rF@5^aLqB#zu#|28ZRQlbM^bC5P*!thNhiE7QfsPE zwrEB|hSaTr9T6;LpP5|>!gJAT9ZK11&95Fnyh6!e63Vum*;4+#JT`Lc8dJZlUi{KM zm8A38$So)vS7vB=_yrM9O~J z^Vt#WPHG%w_opm6NBujNvhKwzKf%tI8$(&Uk4KX6-bqs^yK`)(J(#zurlzc+_pW*> z|5`poDH~X9-wW$bX@s(MjZWMk_pd%8Q#RKn$W zBr;sKHKngqBqrC&D)hZQ#jinK=?^J+)5kub@5092pF=0v$S~-eSgo5jbb!>#D)fyp z)ocWQ@jmXP8(-(Q?uB(H()UTQ)e6{YB7M^{x>mzF!cLE(7yxJ-^^T>(}zA})>zph(d=rgSzqV%1S z+p!qy0y{lO-ZXV8=zDjb*JP}BC2vaTyLSHQRxO3BC>o<&pNMDDcT}EL(kXl)VzI)pH7GphPr$ zJ*qah>Er5msRiiUx%PHHycgcbjn3A4Q*jjR2j0g$P|H(ij}!Dzr0?s9tR=7m<((c3 zePin!o&bMDq;FKpl^>Xg*y+L2_f+AjQy6DbE344A**v`r_#@cq(JwIGo6`69=079w zytI0V(sy=C!=c~;c6zY%y_G+?9(0C{41>O7yHpCtcw(mqOW&^Fr~iii!~3`uzrB0a zjeaF>O6aTY zQ8*s+miKXIy&dbRH5TidjSPdn&x}KU;C=Bv?%zelj{U-*W4wgW&>YDTe`a!+r3*Z*A++yIQj;qd#gFi(zkQ8^8|I>5kueFx~=5;YWYuS zDD?HN;4gnqJ?WR$vFzj4H466JS-UFj#J?)~rms4YY0mbm=bV)iBefR?2V_?t)b*=36*EmslEi) zXCu#`@(oREFT6)K@(d~uIe0b~?~(V39fmF|U$u>i)Q=r3ES1Zx%dUiR5UIS+?^ub{ ztszqRMqtq_j01MCbbHUcsoL@Gxf zH|xyZEEX4ntBPdvYAx9|1mK>vB4IM#94I(r?=E0N0DWokCU^U`W2N@d6VmwuQ( z*ufGS=QUf(*Ny>|!vls#fy=y4eAWNZoZMpg9lTF$6WQ=wrC7u@3&r(mH4~+BjR~tf5ci|i zOq9yyTV!|Cmim=^?azEr`N|xdV;Bb|UrVT5#_rvC%r`dj3@Xlyf5rv8T04Sp}y@?M}o>(lj{Ux zK41sSiu=Q7ZmQVcaes=L^V@wEq0Oa!k;-k8y&pmkMJi9K^mRP!7D-X$Y9_7lL-Tiz z?Hv8zy1MDAxGqQK&sV()V9%qmRIc;v*emLfvsC`Hv+5s=gQ}^i++eTy8RdNH6Z^Oi zwu?)wK+nd%Dk>+AZJ`ZaQW~MMZSbRV@DrIPQ~B?Pe zuKqj<=5YJiS8wMcn5W_^UL2IX& z-^1Xi^FDOdn$up~xdnZo)m4<%gW5k#hu(^`Zk&<$5}Xxj-F^_>#adpLj{I7YWFuGkYEIU2OS z9{jK->@MDicK@Cq?Kv8p!VVmk*7g;z?#8_3edsb(@8E*CqL|R)r&DO*HUCX}_s+ub8hpFT7mj23ptqJJA6g;eF^~KmV)Ss6KQ+q;*ETNd?R| z-iMAnZfomag7<|TI4rH>ttvOhyyAUmUAwAv9}PqNlU7$zTIVI7mcNgH_o3%__G<2Q z3HFJSCnmHuF8FyId{Oemgw{iAF1Z0tu@P+0`gzlsDbO)Cf(=@qIbT!$Ty)-t)-Lm9 zZ02P6t)%u?q4gpAAGKOZ{UWU!9c`Zu{$dBtm)r`e*N(;X0j)U8VK%nHgyP$?Tw97a`KR z?1UEQv0ktPho$wOO8$XTw+5*_R%ku)*fJN)H&T17&^jpg$9r&)R##D47tir_#=ND~ zRg~6^w11?*E>iNugx2O;HRX7Mk|!p#wkTe`4t6FR!3M26v@jTkdB{evLF?6J%(r0u z@;>y*_~S1(gqchIBCXR_v^2#07ipcaW*KeNN8t)xDaQbg=l=ryE z?qg8;q)NBG1RV!=L|Sicd{F*899mtqAjr_Ww(jSv4pvVtlK3!BYmY;ZD^rduKJ=%Z zvxn={#e0_n5;ENh1+#(7JlZTtjkw`G}gp>#gl?c>$AF4f_03T^bo zx@nri_2pCE6%4yB*cIegRi9t+Z@NpLlePf0(`fWVkJLK=@13S_2HP~xbn|H_f}q?DnN&MU;IwVu(-$0crKCd0lKROK{v3oXiv(c z#P|ODbwT%Vv&J5n&m!FyS&qHGsoh+h;*OarLqrnm{x(!$vjmEx{rLn)Cl$o?~7-|oAoNm#QS0+ z^<(p}?a_vg?tS_MYwzH@bV{8Ej{Gwep}EMn8y`Ht7m@Dv z>D#MfJh8KA)0Y>sG-sY20J;~u&QHMK#m*v!!s*^cGwz=N-RIRhdKULdYNr*t2hO?L z33|f&;${LN`9Kq{e4rv?wIFFewxtz z>%6Y+n9pp49CROQ8S4qVi}%ITRut6ux)b`z`{D^p+{%WH#Y7S5{`k)LK?YL4NcZZu zcIVhj{n%Ng_~Kg|->rU2{=64bJFU>&Yr4HH>~N9pky=CJa6h~+K6`i*+c7?vpHk!K zzS^&II_zXLmhO$pYR)&8d!_#{bbtP|bq{(zjgZ?0_upSTd&phnDO62O_lj5Mzh&Y8 zYPxT1{=O;V9_pr|`={hcXMxu;-B&fZ_LPkq;P*iH(IW=inyW9O`az<5xu!@lL) zyMpo8`?!HGLen1=@#`@3Tx^loHtUzZj&zpl^F97eeW~tCRh4#o3XQ;%EB~AN(&w~G zJEmCbM_FH(F6)xCW2*8O?FKQX)*V27{pB^zSxT28wcjKH59*)EUXqCCqE%^>`r(tN z$e$ZetI{a-H#EHb)r2;)8N%dG?Tzr9^O z2|A|a#Z}awW3malq~yg3^}Q;*k*7Hufd}=6FVDFHePAQ-p#G-~>qdYVyifoBNm~B8 zG^{(3`ki*wO@aTy`}C8$d?-9$7Wa=GQx=02>aS|uPZQU{j;T&J7r$yY?^`WU|KW}+ z1I?v=B`;2>-)Zdrx)^`nr!VdrxV+03_+KLRecio|gGbmg#Zv#~_AmY57l_n9YMb5< z^M}-aE7bq5`K#@S50Kh#h5EYsi#9 z`mvGVph*3Ju8T~-S?ri%seh(S@nrZl*fGUYf5nsq!)>L0Qv0n?e|EPjx4 zx8dyum=ClnjZ(ku+b-wvzGzh%rM~y0iq6mtB`;2>-`mt${@yn>0uSovFL{>(JDiQc zgZee|n)qX$^FICKJ0(w_bOQ%@pT7F70SgUGVgHEK|2%10ON;|{OtI9jSNZiDTpv58 z?wtrM_O4Lpna80>t(^T)T6kZ)Pv69L-~iidEu?;t`pu^v=#J}))YqEywK?oAsd3c5 zF=M$6^dC*}>1$_y3m=}Z_M;i<-|49XX1OXF>iV8|F!Q3i_(V5YG_Wr(e{`39!d2Z`FtLv?|S5;S6SFP#k zZhkG~S%1IiDmhvnnVI#!clcL0FZ{lc-*ZB~N1Z+z0Dr$@_Aa?_&m0HJH2~;?J{qVU zJpxZJggzPwJNuOt&I|BKFzRT4WiV^zJ_PbT>c66a1~t8vu>X_qQU4VUWIXMigz*OD zE;&jxP_geS6O6~`qk)q*uo*WHmShBr`aVC5cjQo2%IT|4N3(tZ5igK5n z^B1v|Fd9fw%~%2Z74;Q<7!5rBa4SLz@U+(eTJ_%RFP(X>6n!+17ofWY_8;mi{4g3| zUHa|-tPkxqfSyA=@#ogSc7RWUNp^(49nDr}fziOQWTO;}2WYPWNS(jesKO8Z(_RDE zvz@n9wE*^i`e-2I#Iu#~fWarhsG|WHm6J2=37-U`js~{3Ik>>{mwb=;~m(~fBha$ zjs^r+Cv@TQqQ1fpqk&s_Lj(fgX|Dk+&wHO3n+y97^%Z^?4K%HLVh7ueJ{r(fDrkoB z1AR1bGh<5%oM+*aVB!VevMAAj-B=Mn^bel|)9Z}X%D-4952JxwVkAF!J&N`kfWPHS z_0XC3-q1$_Z+zH?;rvB=4WN8M@thMg@7ab=f>B2Ut#90u;rR}q1fz}yHm}=r3C0iP zd(?kL15LZR?BMrw`eXs-c8Fh@rE&D`fndktV-+8EcK zPcR;!j|Lbq;ZZoA!zaP0qX9nW(nQz~;geum5&Ah++o#!KG;q3i>lxVpX|DkcrJdz_ zlmx%O&|U*@G?uQkHGtzeeKZiLE^-}?tMt);+3hzuFs_47f>B2U4mlYj@cT7<5{x<; z*d!|^1m`>QJ?g)rfyZkJpW*ic@;&Omq5747`#gkUg3w)z-U6{VaUTL!QK+@?UT(vn4A=# z5t0!8NEIGm+G_xWz(Mm3o$&f6eKcSsT>${6LAdW_1i2i)a@7*0_R8YTeHdET>+oG-PA?`|Spru2p92 z*a2O1WdetFNv8K+&vj2%;1NytgK>R>{oE1(bIJsdV-1XK^1joDJI|EW3Xb&&V}bcR zU53qLBdl+-9POsp;G=K4FK94Ne%9N=v*M{*33hY!3mL@|4K4>Cbu;X^DT`@J`{{7s z@A&3WIjQ^oXb|rDdUfWRrG4MeXDF%sD7lUaU*+zVn0}=qV^k}v`dJ;jep9sR(7`;* z#Sa&pW*!(UP!qYH)uZwkWpMDM}Vg+)8d0(qk19oZi zd|%~|jZ3Y1_xjs+xp}P_-A!lvo@23`iC3F`yqgmiZmL^lVTIi*HB2qIeIawVefPxt zs8am#=j@Q-M>2(*mYZfsXMV<_=9jD;>9MZ<=-Xx(7vX{>hg&F#9I9mpvnozgacN ze`#yIKJKV}e!=C&@;%}2mQ5}^b{I2Os`*&IY5b95qOaShQa%#(skHvacN-n{92+hDu@c4b?lxa@RT}&au7}D!Bod z)=-FCS6GRtU^$E(@(OUj(Vr50ieOH!8=P_-^w|n(A zy}04HS@<^YU2*&l)_mDqH~xNqGM~Ti+xdgKn9*qOgzpP=!Ql&Mxt9f}t zm&-W5Kcji08>^qsXX(_Us6FSxzFqZ4OtChjD^WLI7G7(N+Hx|$r2vo6T=D&nZiVVm?dg7or?~NW zfi-KiMeN7dbN76>e<>6@W`FBe(%R~34bd;=f)2yDIghU|i{Kpe!oo!v*a7YvCze`!&-=FeRdsbLC-yGZN8?ACo^G17ZevD_Ii7f5Vx4EokIXZ# zGjq?9^00Q+81p%&JqzEhDztd7E{44?RNJy%&%f7LqLBARr7K>$ckGMEokXEc7S%l! zO68bWK$`M4-M|a>OMbk#C8L1pzPKpRkoJ-+pu}H zQAJH+w+9D5NZs!rH^Ow9>P*9wx>(sPTAr&rt=ezd^g};jQeu&oZ`S zBndg`WnD?1MHyZDvlG7IB#U>kSkaRCC9SUpwmn>k-&<0HVDp;aI~l&M{P83S%U4y+ zMs4)2J-aV`Ky@1nc3gC28W#KIPWJX3i3(REe6V;aQFD>9-iw1TqbH(|Vpp8hko3CR zEGyp2hZm3pFu9vz_bZO6B$|tlB=dSZ;JdQ7vrd{jGo3X5{FpQ0Jl0z5$*dG);&0V4 z-p}@ME>jAaa)QB zgb~lqXI7gm4A~-KxghVWbmWyjrnm`jeAkOvm?QI477o|Q8i*8Kooj*d6fSBj z6D-OMx|>p5=XW0OSv~)$Jny{1>nFRe9o_p8d$DZwOUbiuRv#H!p)RQFjQQ!j&%O5~ zT)K{f?QP=3O?>a|T4C00>8~~PgFY~2pt!Ei^a?!{!>ei2PEL$xH()LbQ;%JRHOE&T zy7{@2{RzIq?oiY~lwy58Z%e8%D?hGwj(4H$LVLWjC!akxFaoRKw0#*@`XP6;f$8~= z(h>X?TbOl=+$W2h3~jMfpXKnJCAUJ@Bo$6&KRk;}r|!bcr#6mv2usa*aYiazEtCN} z_q||m;@G{fIr-TWL$IKPn?8T?a%U%I78cxQyLdsY=G_{xj7VcFT?1SXcCI;z zr(fKasCnO_c*}uhBEF_WSeQ$zZaV9!Yi>`m=TZT7*wyuyCgTcQr@WPO(WAvzaQBt< zZY>|W582KWZZVbphQ&Sh6*=wnqQCpih0Ot#?wH1PuGBzzza#Zr+pJ$CJ-`+385qc3 zm42>uCd*(bh#j9Bd_+Crn`p(CgylzeI|pMAL{i`COim6b=LIO_j}PL+;?vcc8DC}C ztVXZCQIy1wT&q+m?D=LLq(63hk9`bQHzh05+b|g;e8}#M!N+O*sFwu)EA7U6EBcMD zket-Dv>3|?M$Cqw-#gly3ML@7Z%?+7NN72Q$-e=QtTD&723gdaNl@(X;~odHTTsv z^A(2-&g-QcCXZdiY=-7|G83Zi+27%4S-MUgTgmaAp&;+(v$;lQFFl%e;`;en$97e0 zSQ+0EU>)D~0K5C9P$>77{hXKn9U2VZn7`W9yAhdt8E-f*>K`6&jO-M3b+>c!9g;NN}wI{rq>dQ%Q}xDYPY z%)MC0$G7TBmwjodVicAgQQ@qx)JXB>*j&-8+~c@F#w`;mucIH3Nioygp^A8+p|4Kt zc{1~HP4gY~|cQbw%$D5|-NxlxVHaUeqd^-|o^46Qdj(JH^B zU))V$_z)J)gg)GGv0(UzutkiW3?FvvG#bk;`J^cGCXc%0BU?N=L1WR zZmo@ta&G;8|Mkm}hdIfNGPpgJA2z}CedwpVagKU-BD+>n>)`AAAjD2RkJm} zZ~bQbwf(%*J`pQjY(Z4S_BV<<6{`F1pBvwvhCAGLRh9m@QR+u|{_6CpCs^ch;bhVM z??qHoZF)JTO)xpqjpu1AN?a~Ri+Y%Op22siZ;0b~Bx~;CZ7P-*{|?h0zmokp%vP`T ztX#z+p;K6h#--I^LG1z$R4(%` zck#k5OWCh}Z&CH}Rk_3Jw#GJmf#`DX(V*|2c8>R*GkU~@f8>AouLRNs2x>Z6>Y zSd4V63tBu-79KEGpJDzE2RHqiYa}JyoUEO|xlYc-Pnj;#OFN0TxJ|oi8HmMW)&Z#= zp+i_#%w6FI?-CS?F)crKg_!Gn#Q0`j(10d>r0u5AHy?}VMcNux&I#$*)~6ey7D}?j zjb=>bZ^b#Wi39AZJMJ1Dy_B#oPw}`J{)LN`eY#^q$)r|?=v>P@>^3`d@bs3epE4SH zw^^MM#n_6UST^q;7k|fmP)X>~I($hI|Kq&i`d51c`W*Vh%CP2+2wt%@4|fL48#rH{ zCXaDBjP7*3b@8|WQ%ApeTnKJ(evQ_E=0y3HN8A@*A$6F~$70vY`t=hhlw3J0%m zJiqB)=Fx}f_i(pk_*EXC_x6dWxCOg6c(_`=!oGJWIQ9k1>0Z9=s+I6k8!SD&-D&E@ zfeGCPg|g3?7jaI`!e>)r%Nm-FNsZNUPhcVX)fc@4bNm9zF3x`t>WW!6yAB7`e&sG1 z+Ql`nsu^eRuo!Xla_@F}ul>Zvh#6nHg(W#^=j-Quqi!bMXaKfQmdiAiz>eFAEec7? zd5+5_gfKqw>)dFxz3%3jm!f#3uL6PpBhQ|r2ajs3db17t6wc8x{K}e5X`a$*oA9sr z_~gsdd|4V#;WDbx}&f=005`GsfSuPNyegz-)vW^F2_% z$?ikFN}cPdUPP=RE`1J{Id|>hbu>oabHV*=OmwwxeAV61BO0V#@gIW)FhwaNKgFow zwR`R^(T<6;$3I#g{UDtw^ODf%=|;L=h&i*G$%=7bzQhpuX24s2E+$`S*pWV1GdIuK zs55BF7r!dq(p&J(^U})asIi<{HI`Yixomju&PmodlwsEz70hmrb-YP#uIzafJ_z8Bl>RVuIbPG$SL_9yclcAH~LOs`KnM2aY@RHZ&m3@*fL3B#4= z8@KNJl*w)$c;f@+)mo$EKv3yO>FsPEJ>rC&82VP^(D6z-+GDiJdg2DY^8I&5!=D}t8ex2PCI=bR)!5&VVuY=t8-t9{8vrIMKE^Zdo`Xv)L*TfG-Bx0 z;<}g*Z<~naAU&<^kUM%=zq~OVd$$kWK7CsyG2hkE%O?LLp4gFnXZrYlUGZ{WaSm}g zT#u)Oi4+suv?Jy04%Sx*m`d2EM~9Dm)|uWcHJ$ec$1J2O6UG#VQ#~&uQxC#*@RNgI zwANK6K8atDJ!RmUiOpH{ZNV$|JQK`eo0pFTH}-XoB42>7CcB?Q!--(ymAJCdUL(iV z^(=eO`>jmY&c~8?PaNg#_07{s-1~Ux*E!gEapbGbcOz_mc(>D?6nDHv2+8EQv+?Nr zv~5MYAr;uc3rEg9J|Sf`8v3L5``CQU(Zq$z8AZc~Byay{SRH})6LuJwXlzh?AM?mF zm%9P8%$@Q+K5^y42+8nrG*KH{G1at0ecswvuSpLayt0$<Lf_50ead#lauV zh+%#$Cq>-<#lgp?r?huDHXW+3kKA7&pA@__qrxK(SHCswwdnCC$tB5$I2GexV{0GW zwQ=eHIPfF*0^8n}RoH^^e$j8!z#TJYc-djbQ8a(m+Dorl_O{^1w5Ht$>ABalAKbb<{pTfjbWJXx<- z;5^4Zor^)(CElXEdjd*XH9Tg^Qr`{W>1S(ScW!amqRQE>$?hP57uc!oHg4=|kn4In zx#WB_{Aq)Fp}U+!q)VsKrN?N~v5RTbCw9}OO^0aH%4#%eV&u%LRDRaSrt>LH{wKoE zpBAAeHgHcEb-tAOxtUu?Dci4ZVUeNEe`9!W6IGh%x$1f&Rhl{afc6}!^uBeG#-6{@ zvBP1Vf;GR=5BXSDqzL><*E=OW9$oV*J-#q-WpUZhw3KtN*9be;&-BI;{%EC#tA3`9 zdX5~^PAH(Hi7fMD>rR$4Q_^V`i=;v=`pqfnFbU$2wZx&BS53jDVCGX89Sw=bX7f)p z3xxy}b4e_lO`FypYhlhlFmPZtovmbyCB=T}`$A3=pXqIS?qIVvNspYi>0)g>;y+J4 zaQ2m;UMb1iH}(`=V|hQ5A3Gg+Wo}oPl8~InOj=6+kk10njL968xS8}>j-|xQ=@FU< z+sLmfNmP&<;t})9Q-7}n^NHunRXjTL>dj&lB4L`_;du2oi)PI^$JIMwx;bmvrR_nv zd7Dr5%Yt<5l5LqU*0M3OTJ3iX0_hWM**ZPyDSP(22PxkL>E$K}!=3&s?UOm)KO{g} zz!@>F7J7Y0lOd+s2Stc$f{22Jz3Z1OYjE|ufg&3Z8xO7Ax37j^uD8ud7)9cz9Xy^Z z6)o5^hgHgg4rp1CT9TC6z(b_X(QI@6c{GKck`YtEm&C^2XZ?ZV9c|3}C@)*21fB5zXRuP|w!*bfFMQ6&(&giJZ zmB&d3^hXlVzNCg~2EkAlziEDcIt^-P+Cqv5Dg*c;+CNpY> ze6CD>yu>9r-co|T?A{h(OKkggsnvIp^K%X~r&YAwn|p7R%!=i)CC;`ezFXQXhX1YO z1xNe!Vx_0io1ZI^A6S06eAhv94o?abTCO^GGybeNKl*}^XVzvjw7Stx!h`ebRl%k#~1Ie7^0h(WG@PfWICMovam-^ zJ_Aj;8%s=gV7V5Sla(=2I)N^Zv1t8Rz9&YJ~ZdFGum+da=iCNP6zP@8$->w)`s{Qq` zN5_+l=W8V?J8bAjGhdaSe7S7P-6!alr&%W!pjXA$B|YW0*SD$5w5#45fy#Sp6!Wcl zyYkhiD22C*?dam`&nzt?%S&6dEu9}_&qEnM3a@t)?02a%KK^m{%>cAXQF8HQkKmZP z(4O-{YIo4ut$aJTnx%Bb1Zr$jyDpCUJ9o)E=_zZG+=n(!E%Zij2etS=Smjz*FdU~{ zyY(9Slz`^n{Jiza(4sP<%j`nvY7>;Byz~jz%h+{oFCVy|^N$#&_04(MCiYyT=_y`; zUL`4rvhjL&m9a}t`NngjXALesOFp=@w%6KsJHx5fXa?6aC$%L{lsZoBJlb&g99qq? z|8Z^u(-Q9$>Tzo&Sy4sypk&5MmZa&&(eCO6mZ-*qX4R&7_mroT`@T*;JdVcRjFy-> zc>L)#;RP5u7 zY9$8Z@q^z{&FZV)A3U)6QE?R8E2F;@#TCzfyM=q}oixJzE+p?q6Es$Rtyr$#Y|fXE zAXN4deYCz!Z1k3sPQ8SaR)xr;ASss7eI61=m z3QhJ`3J;1K@ovn?%kE5Ch?ecyvg&T0KWP#-H@vrSD|*aVKwiJugfyOzV;fV|g<>87 zT|RyLuZy&y2U5f2(VbO$QxL&mm1ib(TQ1seMrGb8mdA=&>UBLSx0gC|AHCeVCP+1% zOIE%qRkMAM6e_b@EopnW-3QgG&qjC7ZA34;o+|2DH8j8WZ0P~L_B!-l={3tci_~-@ ze65z8t`|W`E+39p$JREr;T}mXn(I;hu{V3(J{zuTO3+2T~e5=3BOQ6l6K`hj!Je^ zp}6&f(~~*gfrNp8hp(*Ba*^GNC0t(9cUHJ2GW4B7xgH+adOvYmUw^o}qt1^J<*Q%( zgs60_Wo3bFQYgU`6&~NsWm_3wB+Vli_>eIhRdKF3mywZhr=t1sa--!4x;038wRYve zclTP3&QqMc!-)547DihW4IOU>;sQT{7y& zGO(&`F`D&IomKwrlvr_tMXo&a9<(aq`n^)Gsgoj=eY@0}htRR|$(RqWeS~23^PgR# z)zGrzr^M47_3gvXO@Yj@5;B`sXaynD+R z``jOIQqT89U$46;em%3l@j7wQHiP6Ev{W=LWU|KM=@w?B$fQdEb&=Mv*1X`_mc>du z>}<6bt(cFVGIG>1)#I?4{wQ6Ja#uY&oj4)QVa)t#TGO5j%^Y&#QVR34aoATJy;IQ+ zy*gKgPn&1gt9MFkT<47!pcUa$o9YzX0{L9NRB3%>My1<+FourrF&7TK?3&EwR=PTZUde&h%Dd z@|#?YHk*vGZ6V;yqbJYf!NZ>`6p`}NT8o0C*m3-BnZ zk1bAE_jn(=)v9>Oxitcn`f4Tv8p-cb_R-;nb4~&3x1%k&3?nsAYvqmF?ZwQb$XrP~ z+kM~;!Z|zI&Yg+A8iZQ( z*rc~AN#N^DSKIUz+(o$(AAQ4~ev;NL()je&R1&pYu;(g%AgFL}*Ue&Cu??ug#85%~ z7PgK;s}RwT&u^elj*JdZl5PYm|f?_B;$W$-Hxx^j4p&O__MOZoP_)ozgv==y>(llqtZFFDS) z7j6-}faWkixUh!vebLa{`exP?HuP3A<}_-%@ySWqh#kqBtyO0ZUtQ10oT>ow&8l=(9e`ea~ccBKGvjqYs_-@|C8b0@sfe zX*{<|s$&T96L$H81_;Ft->~F4^wndRQEHSnYASw0e)M?9kIHH}zR!-k(Cm48H@|0M z`*GTDvDqFGp#~V=BgtBV&mzH!gnTd z>CAnI8uQ1_Q`6BS&R4HI=P583br3lbu!G4w?c(&j%$jUJ^nxVw9hXFxu=V;2uWmAI zK=1OMo_f-8)%3?;jonLAG4z@f=MEc-p*7V~7Zm1*d7vLY*yhZ0J*oCq;j#M5yef3H z=EdioTM2F%QH>5CY8PaN#n$X(3O~|7H4!de)h)4)X0i4@iYBGMx`h}=G!&y ze0Su^qucMS=5wOiMmw!SRi~9U+`f9|*Ah~ftq~B`r=fTBllXFUHqyw ziL&?JRJ7HfVSi(0P^2_IPb^4J<<9{$gB6H(7MEstEKU5v{P3Op&<^bYN_ zy}7I>)A{bg=%UvvWfr0KXUh0_zo|r5^&WPY9*#lZarGTJ_@!EWz5wa!{MY^H=R1m0 zuG_N8bpj0dw~j18gSKm))$G=l+-qumy-6LwD&d_YsbY`OxlPN#KwPM19OVVq6_16$0nJWY+oasK_{ zjzXxN-)mDRmSu*!^GqBEl-8j`%ca*A-#yU!I#HxZBC-PIxjXj7((T6!)d>|PzPsFL z$CR43)Rtg*RM#H=-S=u+uk~?abhm9lnyEmurUqjHPJa)g7$+_jsh|G<+@JIJqBXRS@S0nqPeh*S^wkq&b2z>ZorV_?l_!F}Llm znY0#aa$CR7b@8`>Z*Onw=bYP#(*M2qQns5+tlQ7ynJVl&@lO|`IaXzf>}wA)MCn;) zojkA=U3OCZ!h_LjV@K9gx=D+lpnkhD?n-aTN{Sdf&ER-T9<7(#qW`vi>q7qZ4;qvz zHlyJq{4MkLiRg+fUN)&M-GZ74-bWlKtn0b(ec$TZrO=+W$j#x;o|oEoDqa1|;)^~C zA&$NtsX5t{zoj79@)ml_q-i2e@Ur(*W8ua|E>X0?d8>wIj?DF%$PVnvf%T~L$l*An zox>mAb?(E@T)Bb@93-W&JhBV7Yt*XS5Xy&UZ!;KAYCOAYXiI&$p^Xz7wRPfC+EvP!-qGWX`BU&>ZX!~`0n8jP~6R+R6n4+7mHJ{ebvF-DU+3P+p zEE~lub8nwSKeHaU9?6~7mM3yX|QKgM;aP3 z_58isagV%sNiN?;)^T)$evwAZsowmu&~s>woDTRx)P=gS3vlK>u57+Ioe1ncI+^kc$8QJ!I>+vIP57f}2t@m&9r`&L^a%PHcS{98uJ-PAqNSW%0 zf-1|2s`g&=@gCtNNRY%qk!ytfv3y1J{y7PY8?0x(A6I6&uVxjF5?2qd3rhXhZ{p!Ba#Gx<b7%GfVd zcCi2G^1=303zVPJw{!W!;{L~V9g@wVx#+#KDB}X7`|lc$4A{9c<0y$Y{`RGe8)p_H z{X^l+%h2nGJajxOgCDNAA?V3hn~9bzt!7#>us^{m_^F=L@K-dMu_M8lt80~Zqpxh` zq9v%BDeIshUy6K#cKwHZViLF>^T!2+8Q=r_gP$|W8Df^1$(^AD30vK7P`_y{C4TpUoeMAw?ax;alEj z;FiXT+y%G-FfeQ3`hNq=>72;AFPzAJfP8>KfE%+Gu0yobr71kc4*g9&MfX?s$G^G# zU-|u~ywF!pqTvwr9i^<*E)rxwo!kRPp$pa`jdZi`#<^opKvJHU*k+J zWJxv`^1b*Mwgavviwj}oq`l`x8Uc=d;6{1?guoNEA4j;6_;1|E8vw%hU-&?mrp|-w zpXu_y%%-PiEe1448F_vKI};D`p8)g?{RGciYM+1ND0*t$KVAQKw*9AN{GE=nPte*k zgMA0b@9%I99BZh#K5PF@Po3Wjws|1KgN)AOL3{v80Ym`QWqA+>A`dcc$b*yvGy-e_ z;5FhwQUSWbI^jsj?czc1gY+3Hj)B~>LpuAnlJjf1!IDjFrO&P$Q zzu1;iW+BM$qS9QYTBm4QsW{k9ke>s}%K|_X!Li%JgDC9fK^E@jLBv4%6+jY5AK%A= zGyo0-mH}Asx4w{LAn(pL9^?TycCi3y0LB3Q050Izo&dHL*g#;<0=ocMCxA}?ec)I( zWszYD-gbE9AQ|ewLX4dJ*XRe^;HSvAl+S~3&ms(P5EZ5W8YZWCkQShUm@MZ(bY`)& zj0b^0ZvJbWy2yhFwSavF2%SYW)jEaycdf-Ad_wMgJLnUC0aw5~18fBF1V{u(0D#+^ z0XVsk7byfN2DlDzW!ByY_U|C5%8N(<%mr8kpfqa@f&DwUnDQbJYRiBHhzB?YkZVcC zBQsuv1Yl>*iv$4-Iq)LEj{iG|{V%s00^3ah2s-m3!%n=&3Sj@QKqK_l<=Kay%ec2u(b1C1@)({=P|JF)M>bmg5yTdQPKq<-zAq9VFLC)fih4ZdOrf7E$KN* zx*C+d9<=v|{NGUv>O{|n{e_lZ_pj2_eyP|0)i(dX%)9u9eLr&Y*S_b1eIB9PZ*Fj& zQ|crO)}uf>7M>!5dY!`kw{6gDU8u{o2lb?+g~9&31jly*?B~CO25=rzwx?dFaQ|&v z{fGU@1N%y;$Dj6@nuF^_;C$@^Z3RKSPT~IB_S9@$sLM?R^`xYSK;L@-`f&3Z5VHZi z`3L9&nkU7)2tx@t|4Vt1)xc%~w19Olz|XA)<8loz5)14R02{D=8Gv|=7jXlK1~>-r z9AFwi`Z_PN06+&|Ie-;_6M!qgL4ctfyh!^r8QXxRpkfMKNd;+W^||@ zc=-@(z(MsP`k8EUgj<0hd8@*YyaJ%)WdokF{=c;c6#so6|C6$FL3zsRtgLGVD`;1u&h34zLs)1?%RsI*Oj&t_S&bKvxNXpQVK@NJGd{;S*Rl zJ4dUd-wvj)13>$znje{8!;dTlumXq&$OcfZB?COikAwm21>E*o4r(AM8hQ)!HrLT& zA4o&&paT0X&^7?{TKe?$SzjIv{0KxKfD0Xtf%Kk6ek2W`0-yze>oz|k0k9b$8XyUv z8GxsWACU%71JDPs0&oS`1P}?Z7oZ5B`wr0D=SOq_HUcaIumrHO3tQyorlzjy<`%lq zJ;d9~EjTR1%{w62-`&&O%u3VCYm2*&j(4P|e|V^GP@tMxNVvbZn~$%5n0JV=m7SZ8 zyT5;sr+ZjXh?(6YH)F8;k6o(!1_p||hXlc27gm!$N!mH-JxX_W(0bu%l{fo}hi)!b04A!$QqGjp=qC z5OCLL3(yV>_xE>$O%>`L=H?sd6GW8S^VG~hn|RV$GX4Ov2|rFMXO7$`VI%Qw_5GBosO@f04ONZxL~ zU?4HGvQu@V$bOw96rnb75W3ml_wPLX)cx*4%X@RUyMHJsXl5`|QwL>(lbC!C!?RcY zPp7Xs_24yg{{HTnelPy6phbTwXwe@E`n@R1PI&yD^%u1O%HOpVHvzwA{e>H#{9Q|N zR2D{CiJM?GU|77~4I8#&ej)Y^tzwPi}3@mgl`#-8CrHSZ# zP>v3{A!lx?@pKP`(=eG)10!dIyT7lOTUb=E_b*y4z!x0tzzuGjyrX`yKifh*cw-10 zbjXcC@kPm|>u+kb>RBU>MdCcQbYg* z#c&1!BNH{i=5I6676arf}_^7h%V(bsR2e?VYR@aB-v zu<(d2kx^S=<;m@^0KCC-ws$Y`2?$#hp$76`5b6%*d2&Z1-@gPtQJg?vWW<>mnVDI5 zSm&^bu=8_pb8>JoaO1qZd@O>f5J4Cd!9|(oVB)BxpcK9USHhIp7NV-S8m5jGVCS$x zhV#tduqPucIibza!Pu} zxw5M2hQ>S1eXj;c2m=rAd^HViUA?7d=IattKxRc%bz^hOgI5Cx0|)0!uCAW(3Nv$8 zFYko(qsQ*FJmBD&Z*1o1<(-^<4u~7>^uHPy;ovbg^YV^OD6hG8z2ou7=+0e9`DdV5M9nr-l)ivJ)g(M_bm{?gmt#NUUj=9v(-tlx~bUY+9H7xv~iksX*m4cGW>$e{~ z?$0J3I;@&1dE;ga$;x`oS|(;LZh4gt9|ME5ml_xur=?Gm>^6iq-FevB_2l(5iPBQD zmJvm9lmP=r17jtyVVn%yC=bR<;N#&(1u!8@gkugtoOvGVhi}4auvV;{y@RC_dyI9X z&j`=4A?$gChDHV{8Cf}nMT>P! z%`I*0>>XeOuJ`oz*%TVNBW7QIVM*zYhs7mP_X2|sAc&OP-1vTm_~p!E42(Q+7dT_j zYbvnCKEp+rQ3e$T4F)D0WnyIFVYT7nWwK|&8RoFE;LJD^j^Q}Y&OpG~7*S3Ef-cU( z#7N*~a%94o1UPIMmf^~vRe2b>*mW7iW!8 z$H>Yk%IM6rfUts9iGiH~#nsr97(^M_@Yo9=OWMGaK^YHYUV?MsOPCfjFCfH|c!Zf% zc$9G|ZfUOA{S5JkMA!uOW)f5gdQ2FnFiY%3jyy zW3MpB-c?+TvobDbUct=H7{(@nuVHXziQOqYhgFcpk|A~<)dSw98}QTyq%au}BaW5SBA= zD#jKv&SRLzpunubhQ_AFX|o8jGRGd)!9AH-R0RprxEKK?E@rSGs4%cHu`m&(k)Q+llMM zF|A+~$4$(%aZYA%w>A@NoR&yzCCa7FvGb@;I9qJ}zM2G;)Yf>DysPm#Oo|NHdO6k= ztO^9a_|moB77RK}JVbcD9QwkX(5c9BaxzX*4d-ECj@zHeu!+EdvoLWVSRXsV8p<3f zv?4Z}pWTr~Bz8}n3BJpSOJJAHg4hmaT$BNe3)Ur|yO7w&^DP-z8L*u^%Pp72)-7Q~ z8SDvS8dw~s5`!1J18Z#YVsQ>71{QFL8Dq0|b}@6{9C#SJGZW}S42wbi6`1E*#jR!+ zz;OZ-iwF}F3(mnbKlZLHYXW>bJ?%1kEAY=7mtlGWOhA9KIe>>Z9MfCjA0!gIcbMLe zbdgB#PGow!K5Ci-?`x*FH)=;nu!i(D)^`I5zBiTLB9g4%;CqjMvs&KuGgHCeSo&!S z#vS16)a+#dk8mF!?+`Oj%K%MPRS?6@eC49L3`BD!gfi7>d3lGq`}%89HvSc4P!vBW zLmzPADU9+}P77XK0$)sl{@1dNtC}xoXh_!jY0b4CWm`yTyiLl|OTqi<4l5H$q3c>C zP2b)yEmRo`y3v29%lzV*!)iE|Lt0l{c(tYB>LKJXw$+&h5u)bg#DX>9IX&&I5k>Ym+%& zF@I?}dN%by@batY%=4r8kk`FM*@xvLJkMt7c=qxpHO{juQ<|)bMedCLsySSR)Y`Oladp+1 z)joz!C2a$VkEVy;y3C6X?K`(QKiOi@>9+t_ggB&TKd{U zu=~oLcgxr%Vzs&MviD=Fwyw$=No{<6Rc?!y0PC{qLJj><%DDmiDqJY<9^OGtBAaL5 zz@iCXq7D|8rDRKaHOljG@|NVk4uBwEv8)+EFXx+?Ep5${IU$i1T4xF^ccD zzuye{v|9$)hJ`gJ%Yc3I=7Mr0IMJ4-uYctPZrf7pd=Xyb0RHak?CVPIyp`LzA(9z+ zpH-JiSfhyKy}#EYR@a8e<|C|0&2t&9YT)XX;2rD0)z1aqa4!h}|2_isyNSsH;*5!f zpED;KrA21wnGg8v0NnlGM;5XM@^B28Z7MQ3`#Jt&nT68DmN@kv{H~L3MkfvQvNgvi zA2o9}BRfA`+B0Pq{Vct*H7vL1m{Wu-BX8rXh7WDUdk#+8>4h)9&wnjjVP8fTk{xif ze7666+}0gtb3**kJ5intFXn-oGwxZJcbH2IGp`fRNcoU)z`P<~OTBQ*6_@8L>#t>I z4R&8B)t%ffp2pqf!lLA{}E zrz^A!-GURRTHF(Ow%j{kYqWKsBlCLaWncf9M>pmrn1D9}H54d$i@b0Ws%%}-Z=HN7 zkas8B<5R&)Ss$Oee~-M(?tbj7Juz#WX6-k!CFYPVGfuHDZ>zvSZS|si2 z>7diPTvB85sdrm;v1ERU)G>$~WV@>Mm?<@{-)aNH{X3uT9GV+vOxzyyBX@Q@V0>w* z#VexSa9ixzErd;M{}@w>;TWUZF%ZBLDRf%ArFj14DE6%=`S2S8S_i z&X1u8Q}}-Qp9k+mh?Ov$$cS6HKd%8cwlP0C85Tkr87S{L@+!D^`56esW{;mFn9e2P z2co<{>bGxWf1Kug|7x1^1#{BRYXg)?jBc6(ntxV`pJl)z^*_v|e*d5lpg|TJh5H!7 zA7T)-MPSu!W*uH725kZsI6VEo8MD=geE}Y2IBvoj1dgF_Y=%SdOkDFX_7V0;_#_n^ zlVNNQCzzSu_b;~jPqx|rb@~6vefj@No$1a-?Rix1B%`skQ62?O39(>te8! zC@mAcKv_{mZo8|j!h9upy&271Ao{gXUvJ|E`wO4Fgy#%3&k9b)Kk>}7JP5~V^c0?( zo(Cs3^aJB2YX5(!2ZI6B|KNFaO|M>!vp-o zw)qneIe7ll`-k;`V-Y2y3B;2>Vp@$7(uFsG|0d`1=G1YNnDfP=VC$8!M=;tZW1 zZool+Pn!1U0UU$@xB^LiT)=Y^B#10Jo)2&kZ|Hb_z(GvY)kgqu5HINJBM3MM9Rh8+ zLV$x%XQ$7Ug4$AEtf-n9hlPt6OmftFy?`_2CopnpOTo9QRi z`fk8?6YPKEdjQ`v#1_gj6wu#-q%*suS_4*>lDfqSMu zP}hGD@Ph=`-|FKE%5-I8o#}7X`qx1Jn&9=DpJ1R5X4CskPXhHJv8Vp#pAYEy*s5my z{60>S_ZQAD9H3W-&h$js8_7I;%fO%dExDg_BVt6dmPE2=gzff6J#YYHTXZI>C6U~v z$lE|Yoa^ZQ!*L$|%`*CVc@CHdDdmd)EcaJE|1_^b-+$sE#{%jjNw>cgUW$&Vlq*eF zF8O$IBQoG0w>YQ^1gJknKaWmN@h?Z`pVB^XMD>vR)jlxR_*45pKYXBtrWT6n+s=6L1i;ycTgW;2=zB#z`Hb9^fEo^-GBQfP+A1 z`U%Cq0nrd}5DRE{63GZ~5F9l8GNLiyAm+`SzZ5?!h^Byppe@&oXaP6~THcaq1vm(C z4tTsMeyoYMfPfMO$ zfP`T-7N7tQ`|A_f2sVku2K2NHt;2cb>FlSrEZ2cbs8 zhY-U62SHnIIB^T$AZYnW;#R;x(DK`eI{*g(Mo_Bb5>1Q+90aYNM2Z6(1eyOee#R3$ zrAQV7d;s7fsP)-^4+IJokf#1{ ze?tHdL9IUt^r3)*pyu-d9|kxGYW@u1!vP0D&7TE)1mGg1F4OF9A>g+Fev8x!ns&Yb z_(;G!E z5y3YLppBOrrWxn!iH$%DLF@lE(C-9#2x|X#hwWzNFpTwEd;f`h4>I?A!zlj zL@w?PbZKO$ulssP(8Jc;^`jf>zI9NFt>HEd;fm(U2KvA!zk1K%Wk@5Y&1$ zLk^&Ypw)8%eFo4%Q0uu3d4U#!R?i3Y2Y?oWS`S8kpoO5-!}LymGN|=}hQdG#L8})r zB#|tjB^ap_!f?6+YC=av{w0Z@gKLoT8 z)OtljC6L36(CcBE{5_Fc&y6fJR0X~vsQrWY2LUgKfo}+E|BDPYffj;Vk04q=e*|bD zsP&5tb%7RwR<8&2*+2^c^_2M$>W%^qF4TUO8X5o}5VU$C@RI}d5Y&1j!{tB=L8~_g z`eQ%~L9I72Gy_@)TD>{Y=K?LnFFiM6X=nws5Y&2Z#2V<211-caJ%WJP7HA=;^^gZw zcz_myTEEJ0HPAxP>g^3lq&%R7pw>GYIs+{Pt$q#Ap9ES6YQ2l0E6_sF>fM0;6wpFI zJ^8qBBkqRohWUV_=qd9Zi1dID2x>ifzfJ=^1a-MyhCV|)*%i!2T45LVUTC~rYX48W9eXno(zG+jm z*s@pJH-T-lMT4MXj z=qI2hZvRoy$7qS|KSBQiTH^N8il(C_w*MUcM6|^1XBK^dmRLW#=u0?a=X_O!N86Y| z+&Nzt%|}aYzX1Itw8ZTf7A-X63&^4ImDi?b!dt8e-v$i zBWuiYfQ?1?D-<(kwb`|vowEro2~YP6^u+dmp(SBI8!fT@-)M>NH^Y%|&K%4jcFq>G zB<#OL8|Q0erG0w+|G^9r&iM*+h&|n{Xo>az7Hx+kCseQJj@waDRn=U~nA@hex6U)Z3VL ziko3hvzkl1InCjJXp{EQoEDh#1KOyME|*rttucq#^=X5CDSDD#heV=naUoh_`}XLU zp(Sp=dvQm!#P)lj{}C;5`#p>IMoVnJ5Bi_b61U&4_yDxT_MOo$M@!uPpyET&65Dq{ z|1(yC$pe5|h^$o|XzXk4`V~Wc#gV??tb5>#o zar?^RW6=`ZABX-|w8ZUCDDHul*uE$FRcMLZ<8M~9#Pf%4(qCUEvUR!)UW?Wx${eOM5-?#yOLz}dZZl^b4{sy#B zAKgxGDZUMJh&|n2=r^J#?)KvdIa=cTJK>1+cNO=BBX<5h#W-q-*~FdSr}#d!#P;{2 z--MR9{e#8*(GuGaK>rt7;`W1z2cspnAAJ7a-2T<#v1p0y zUq`^yvHeE$b|v?p{-ZY(`^4g#s8uu zcK$Z>_0bb|epPXe3|z~B?Q3?$?`;3;qx%xSdTfhnRJ!%0f$gpAARCIZZKx`0LONj@bFNF@uDCbF{?vIcSOR zbK!{Z^Wcc@>%ftecQ3D9aGJ!PZe6q_>|3BEwy%elgndi2#P;>klCW=ume@WYEeZQw z(GvFV`DzVEeBTC+_`U#+_`WS1@qIfu;`{a3SH*2-AzI@1?cs>;2epWwvm09C_q)Tz zoo*IhmqPr$1A5~7j$+P3VtY1-^ScM;5PyCrIO6-EV*Z|JiQf+q{a$E^-|r1ad_O|W z*#|B0`+ebv@ArcvzTY2?`2GMm;`_~FJs%g_*%>p4Kj&XD=RmZ??+=0_zTYP1Y#07u z%pm@pXT|nECw!Hd->`Zw5YB&I%xNV0L$Hl;x0f#P#NYlG#r#9XoWtOWKPM@+=Ww*d z?~i~Zz8@*J=SZ}1=j$lpkA^4y{31Bw`(ila`>t@r_a$(|_s75y-`|hdOT=yeQ{w!- zCVYl-T-3c^s3m+UwxzV7gL!<#?I?rikH4J-;&Ln(eTDGj#P&ZRe5IH(O!UKr?}jJ`8=G1b7Fi$_;X`?Q~2{@Joi=SJ3cG1qWb;B=~YPd=9@S|Uqkqs z!eb;(YxU>$xvX z?GHO(i%59?egXCmg!{vE-w`bd`wP*MX#dRp_8!$GYky8B{0j-^T!a}Un#1QY_w0)I zYQV+ym%tPD?&G>k;fU}52S@0m_fzjJw{su-3rY2<`vrVIFSaN8;hboF_V3ymEwS?t ztTw6t!tD?0dI%#P{dGk%8Xno(o6({yaG1`}5(5?=OHOQ_TDeyIu@OY=24D|G|-zkFJN8 zb;aHR*TYV^9jec7=!WKui3-Asq32Be+Jb&d>3E8>|`eeG+}L)zjv3f&G32yZ0U^Z^A+uX?#1ci-G=a~`H}Bi?XTM5Q|C87ac;)B8R0tT zC(g(?BST#uuErF?^Bc{_JG`((#64fBzwfR=OKkrDS`zlxq9wL}5G@J&wz$lR?fao6 zVSgQF6WjMkOTzwow8ZuU(2}sf0WGopK(r+6Z$wLMKL{-e`pABUI1$N!&pY}6j`;mVIO6*c;mBgMZg@un9P#_faO6v`p8`iZdfW36 z9O>rysc>Yune%biPvMAvy3^puGSlO=IdH`9r^6B7e-1}{KLd{R@V0X%9P#^EaK!gt zz!Bfih9kb814q_+=j%&2;`d*{5#P^+BfkF{j$G)SuX%99@8`o2-!Fh8zW)Y}T;|PR z2uJ+>TR3vI*Dr!2e!m!wqRBfh^E?%sm>!JIzu z#P9pU^)09s^!LHvSFms3?}xv?;P}8l0RKS2mg>tr+Wzml;?W5_@lUrOT)%?G!JPi^ z#P0{d5#JAlBfcL5H>lvGVE#k!#P0{g5#JAiBfcLBM|?jFZdgIH;B<$>6Tcq;M|?jL zj`;pzxQ7ca3FbcnPyGH-IO6+JaK!hI!97-RWibD7c;fd@z&%lLUeG@YPyGHVIO6&x zxSl)>M_j)Y{uwypdfr~1g(I&25&d&;#P#f-ha9P#}aIO6+P;E3yg!RfvVM_j)W{xvw_`c?2_;fU+G4zI%z`t;+d)fsp-ISBi4 zXo>BAM@z!~4Yb7eYtWLgACH#Uel1!O_HUvkwqJ*qg#BA+iS7SDOTzwbw8Zx7(UP!# z2Q9Jv2DBvX-$hGozY#47`}fci+y9A{g#G(yiS0L`CGE`hng9I+v=a(;tM<|L;jgZn z(GojA>q9tMf zF`%lpl+h?LBVLuHmv3(X=684{=CAQB-OTvCST4MX!Xi3^bJ3EppNW>(J`XJk`&np-?dzZ=VgChMV*9#iN!ZUuOKe{cEeZQM zXo>CXqa|VgC0b(pe6%F&zd}oF-vBKM`?+X|?Hi&cVgEH+V*5sDN!ZUrOKhJ+OTvCW zT4MXgXi3;FKuc`j1T6{sZ_pCkH$_Xrej!?7`(|iK*nf+b*uFVh684MG65H>BmW2Ic zw8Zu;&=Tugmh1{g?3~smcozp|5Id&;EwMd+{~j%|eOt67?3bV=wr_`)g#8a_iR}x~ zlCWQjme{^MS`zll&=TA4hL(i=k7x<|=C{%5qr?eTg7w8ZxO{TH;v?e{O~jF#B`z!JRI6D@Ij94A6cjtL&mtVFxApxiv3 zIi%!Jw8YLotOW0tK~LQIN0c0eme~Gi^sCSkw=XU!K}&3Z4Eo>D61T^5+GvUG`TJ_L z#O=#VD$x?#cPqi8aJ0njk1II=EwO!f^lQ)(x9?eU5?W&WlhLn5OWYpMA)~D(SpRis z*A<*$*8jAUGtd(||4hvP13hu)pIve;T4MY2(62{J-2Q@+i_j9=UyObOTH^MXmRyFG z*#2_#8_^QCzp~_Nw8Zw;p#Kvsar^5^Za_wjYL; zgnd1<#P-9{lCZCjme_s-S`zm8Y=eFzS`zjR&=NcUVYDRd8=@t)e*`V@{iATi_oLv5 z?;nFBzJDB!`2Gnv;`=Azi0_|*Bfftcj`;o=IO6+f;fU{_gCo9w9*+3_1vujS(Qw4~ zFTxSuzXV5o|1uo${TMjn`&ZzI?_Y%@zJCpl_oW~-|qoO zeBTL<_A_W6lPC6h`Hg^RnL9_Dy{-&WlFq_Pq}#2!D-O8hK*uJC!n*Ac$1 z@b!eRFMPi64TNtfd?VqL!Z#MaNv!Ak^F3OrODcVNW#OCL;-0_Y{yDyH7Tagx8;axR z;Hi+5FE=fL$-h5tnOX~ItzK7Fd!R3C@oW%z$>XS%emUCyCC;3N*ucmy75+!zmka-k@GFI1CH!j7^K!TA znR;9iu0!hlhL>aG>h%fzz+7IwkzeDSuItwcpT2!Hsh%IL=X$4i*LkDxn>^3&L5n-T z(fq%?KJr_H-zxkz;j4tNaZLIg^L$0?mbT5rIu9}HoZ-xI*Ev)8Y|n@Lho<6mo14oe z$C=|^E_uSI&(}zEd#vm9yk7{{p@rCQpA@@4$x58*`Igo5Q{Ufb_n%xJ&bQa+=c-RPTDPX|={mQ^^!B&jvHf<= zXfvm|nA1Y|Ry+JFX8l|5@YtWkZci(5`R*!w8{x;A(@me>@x~X3?P(``d(TJvhxB~x zKXLyXt$*4V{I|~j{YYD}{q2N*+id^t-u6VN+i{1VVERrwyj}mjgimjOVfFT;&ToEV zAE(d9<(QSY)VtoM?k}cs)IAr z=PY$Q@;?tDwf(6%iNqn!9C!bAsPKmif28n73t#N{ti(OB>yVYWSNPQ9y%J|mYQNO? z|LjYHJ~gM@@innHsr_4iqSEp1e(zYvyZ!Nwcl++b_jG)EP9kxV@TUlWn($``f0pN? z>qGk5^P#!_I>+hb@4s-p`ftB&A5XTgzI|~YOz>Xn%oM4|V`+arJn{VnaK!f)!V%wJ z1V?;-F&y#zC2+*|m%{|}D%{xUe?`^({o@2`L(zP}QV`2H$5;`^)Ni0`j~Bfh^D zj`;pMIO6;3;fU{VfFr)Y5svu&COG2zo8gG>Z-FDezZH)7{x&$``(ALw_qW3l-`@d8 ze19h#@%>$J#P@f@5#RTQBfh@}j`;pwIO6+0aK!h0;fU|=gCoAbACCC`0XUNK?(-mr z@oOELaP_?Kh+QSf78{L%2Q#P}lkS7UrJ{A)43EBx3PUjqMnj6Vi` zT#PS;esp{CV&*V*L5=Gh_S(@Uvq4h45d*_>16Y z$M}ok=fwC+;J^IO^Vk?aXOGwK=*Qm=T#Ejym^uH0pBv*Zga7(JA3hGjbB%Z~7Uv6v zPvVb-xISNbyvZW{IE3fwa%_>mKcu-r_$!6KO8BdVzef0Lg}+Yt>xI8T_#1`4N%)(E zzeV_4g}+VsUc%ol{2jvIDg0f+-z|J^;qMXtUg7%)-&gqiguh?-2ZVo6_Ho zEBtf9KQH_X!jBgIMd4o({$=6E2>*)kuL}Q~@MDF4UHEarzajj1;olVgE#co5{vF}p z75+Wp-xq#@@E-_2QTPvqpCtTb;iv5I>A!3GW%k2k6Jj6d^v~=MN30)^IRK7WKQMD3 z9I<{-<{&s?{X>}#!4dl09mh}jI3)E$pN;45_}C?K{9hh_=JTiZJs-WU!1hzjah}1) zq$hEH_&Dlg(+}NgKh5;RciMk$`jI>BXPN$yo%VA~Kg#Q)tv&3xA^Io66{!h%f2k$u`_WC&~ zqYoUhen!S1IAZ-58AITR^|LdE!V&8iWQ>9%*8iUI1{|?|bmm96^%8ns$5YpH9;qO{ z=aCBHdmgDEzUPq&;(H#cAin333gUYnsUW@|3rBpoo=;`cmKL44066~y;EQbByrBNfE=JW@e?&m$GY_dHTTe9t2l#P>W>L4406 z6~y;EQbByrBNfE=JW@e?&m$GY_dHTTe9t2l#P>W>L44066~y;EQbByrBNfE=JW@e? z|2Z7-{R}wb`@Uw-VBm9@be%{i| zDEgm-UoQO5!v7-t3dcvsMdx7~SH}4H@W00R1@Nl^pL(46Ti|OazCph_#xI2bJ;r|v zzb3{nf?pfs7sIcM@!!G!5#zsyUmxR_z;B50KfrH{@k`B!su;ftKGBZ%MydOe z==#R{mKrg>2Ikj{@fq+LF}@ajtr-7H4ZNo|#;<_Sit($lJ=rln3-fCSK6N?f1im)@ z-o<-cV|*R>ycmBWwx>>vuZO;Fj9-erUX16yync-5zC1t1*T?(@F}@Le!x*20ZxrLX zZ%)SeHQ3I^F}^Y8G>P%tM>dV|$7kR@XEFW+_~tRbJNzy&{#^JLG5$RGmVwW~GevmM zS&ZlREA1NNxjwC9JkM{N7|-)n5aW5i+Q#@Z;oHS{p0C0f&-2yZ@$Tcm-Gtv=_zuE% z6n+okI|;w1@OufrxA6N2zpwE73BSMNqx}^>QT71GyX)B*p4h+Z@t!l$|Ap&%v_Ev` z93=XK;fX*05YcxL{!rl$6aH}Fj}ZPy;kStMdz9#p7QRUMV&S_AUn2Z5!j}qP22cFU zrCjtC!VeVRH&-e8Zo(fc{Bgn`FZ>C@cNe~g@I4(L-H!gib>YMqUlaSulVbdO^e4yo zbI_j><9R=RYK+fBe_D*+fd2FtzY+e782=~ynK6Df?(fcu@xQ^J9pg7)&N(rj`-XF4 z{NM2B#rVze=f`;7<}Qfw|G-}uuRe_N{M+=}IFJ6i7@wDcS0Bds z=C~f-5aanBr#HrUe#hxeF+LNgdvlCGDFd%QbbMCg8}Yj0#j!p*{+wBwjZ-Fe|5m#c zuVTb};vRR+Ev$ShT4MX%(BFlYxP6DxJqb0VlKz|=v;`ZH2k3&mre?0p8(Gs`sUfL5avHgkYA3#go{^ZhA z(GuIAhW0Jqse6e`65C&geh^yX_BWK?gqGO;X7mrCC2oIfX)mJ#HV2 zemL6U?aHcswErAhIvg#r^GBc`fu6YYA1-|qEwTM5^dr#{w|~6!NwmcFPoaMpEphv2 zN}oeZZ2vs^N6-?tA6@zqT4MW`(Laioxcw`ouc0NjAB%nzTH^NOO2?xmwto}-V`z!n zzg_w+T4MY6&_9lrxc!9EiD-%KKScioTH^MTOFu$OY(EwKlW2+Ce^NRPEwTM)=$}GM z-2U^@nP`daXQ6)@EphwVrC*{Yw*LzKGiZt1e_c8sEwTLq^v|LtZojZ}5n5vV#ps_y zOWgkZ(jU+g+b>1`JX+%RKb9^>OKkr$`WMg=w_j2ED_Szy+`d+!AB}c&yQ${(wYqc- zT4Lv~MgJmt;?Do0bOTyq`;F*dLQC9!Q|aGmiS0L|e;F-t`+rLRMN7Ui+rJI{7_?*B z%`@9yRazq(M?is{U$YF)%A+Ul{90vMXo>B!(Z7n8xP4Ap9$I4iI_O_ROWeL*Sw31~ z`v&O8q9tzMsH`zsV*4iOUq?&azFFBWXo>AxpdW{pxP7a#)@X_C+n|2~Ephv{Wrb*o z?c1XtkCwRo?qwa(65H>A{!O&R?e{F(8!fT@KIq>w%Woz9;$*&=R*lsq7TA#P+A6pNN*Y{pn?Aq9wLJ3;l;^iQAu3 zb{<+{`}5IHLQCBK!m^9e65C&bell9(_Wvup94)c^73im+C2oIJ*)?d1?XN}u5nAH* z*O%Rhme~F#^i$Cix4)(AHnha{z0iM*mavZ==iE_tN7*NEet%clU1guf_}*o`%cjNn zd&}-E`z-MJiN0lh%cciDk+{F??<{wJ8*LA_bU&?tj`zdzi9VnwU6cxDjSTJ*mWC%el~jIuK%#I5on3+N1~sDmbm>R zWuwp%+dqc>OSHu8pD23@EwTO6=)Xcs-2U0J=g|_|zkq%&TH^LEmc5LY*nSN9uh9~> zf3<8ZT4MXx(a%Fm-2RQSH_;N?zlDB2TH^Nal)ZTg_Up?wq9wNf6a9~9 ziQE5Gwizv1X)fO_=zl`{Q@h{H<-4_P8(L!LZ%4lzJ#ptJ%4^ofGvUDY8Rb|tw8ZT* z%d^oE+t)__3tHm#x#e}x65H2BzXC0B`}*Y#&=T7>M86U(ar6STzkP0{~~mbiWM z@)l@`?OUQ>g_gMeuH|je65AJ`{|zm1`*!8+(GuJ5hJH0#;`SZN_drW*-wFNiXo=hJ zRlW~eV*7p3uR%-Pe*f~$Xo>9)M86g-ar=YIyPzeuKNS5sw8ZTXFFz73vHel#|3FLJ zzNow_T4MVW^y|?Qw=XR(M@wv9fqny8;`ZIjk3&mre?0n)Xo=f*FYk$#*#1QHf1)LB ze{%V$Xo>AlL%#_var-mM&q7OVe>VER&=R*lxBPsx#P%1U{~IlF`-{piK}&3ZDf-Q5 ziQD5@5VXYh{Cx{rV*AU{lCb{=EwTL-Xi3;_MN8O6_fuDv9(=vR<;H&qUmw1H;R@p?!{@{27p^k?BlrgJ4GMp+_R;n8sBkRnZS>?0g$Ohx*lz#$OxZ2bK4Z{WyQ;}@1Mf+O3j zeYF0I%kerfoUew3msM|P)=Rc1GoR9d;=V@b2gT5f+N=dRlXUH zSihxwD;%-@-}3En#QLi88adb-f|QTexn>29rr|v8QrM+>J0o8Uz6E@X!Xu2&f^P{= z-1Vsq-wKYnJ{NvhIO6&`@U7v9yFT?Q@^fH7ky*C}6^-D?F~%n=n!ph|r)foVIAZ-S z6)oY2^{pye!;zGa)}c)W{tw$&RaIfup=||TcL!fkc&G7&6}$CoTix3^9nrUgC+<3Q zs@SVvVNAa-`u6a|?f0+f+;6v-{$TXG!xMKsyHp&OQ&mOAn{_+9;z&4R`=cs~;E46b z6(w-QZqG3l_$+yxW{1LG%sQ08cZBa)xQn^HSHSN9zeiz>M(+9Q2Hy$3Q(-ORkAvS6 ze$T>e<4=I!3x2P{T;qGd?+w3qVO`@-gx?2#pThiVAKiXWt~fOZkN3a{W`A{B#Tjs< zukmMAoDD}BnK|cFoCimm7=M1ng>a;~@fTHG0!LaJe`&>KaHO^ImseZ~N7`2V==yn8 z1wIQO=WE}>_QrS4z-QsZ6L+1jLBBs7as46a4}c@CzYcw8xXy)poB4;KKMsp%Twj9zFgW7++t42lcX;88X8X&~9|2F? z{`QJHD~^OCuD`qDo{FR3i0k`Q+*ffl9C7^v75yrT;E3x7R1B&ph9j;YTrsqwD;#nC z@QRTYC2+*`k5r7RI0lZ;XZ-hm&&RR-RaK?1)<22u$8q?;KaK6j-(P`$7Tb?~Uf`d{ z_T&5V0zVqtUscsD@GoKeaXdfpW3c`BJ8p-MuFtPljIB5xmbmA4T*df`6X1yJ->P`0 zqB|UM{d*M?Dtf>X*H5gNRM8WTxPD5-)QS_~i0eP8m{xHT9C7{hiWwCr!x8#u{bynO z@%#d;^|P`4*v|z1OKd-0Q5g8S*nYgCF!1xR{n#%BegU>0&r<|`A+{fXp9X#rwjcYk z9X?wB?<$s5oC8bT^SiX-$BJ{|i0hYE{8Diq9C7{1id7Zo!x7i7u2@rX0UUAtx{CD` z7s3(OZ>-oj`0rdw%P}Ujs*6U%#?J<+X6p z`Hki@s%%_&9XxUSrj^YruaD_lRJN$Rq1tyc`^i?7t^42T^wIrh+seXRJWmQz^CREB za(6gleTT|D;E45|a`%KIDIZ;qdtv+Wx}fS)=JxaR=Nl#P`LwXnk9)p$&)7YqZY%u# z1>*aItIt<7XFqRF$|n*Bcs^Rs11k@%yxCcY$akqctnwCk;%?6ol}A z?K_)w?pk?F|6WcXt!H^^4={>I#!;7H0x*Poj!X;MG# zy4@;#FV9Eob_e{u*nZ-!!(H%w;E3ycSKiydFC2ede_!qmeeR3#_gCWoV*G=c{{TF3 z=k%}aU-@86Kd|zl{{0*ut>@6n;kh^-1yXY&KcezsIAZ-Hm80N@^^fH~4o9qiqVg#? zlJe2|KV3^v`)dTL0%OM_2ZD&R67LsvJ`}0G_z(^J?YT%7HQcxXN*r zgR1>&=Jr0m@~!?4IeoM~?^eE#Eh6^(PRRWLj#xjjauOV|esb;)uSJtZmO>t_}I_w z!H4j~dVJ6_J=ZRp&Hv@+{Lu5gBEIMMG&RD}>FM5f@;veWsBIuzIQvwM8cZOp?KeHC-Q=)d;PS9E?C#Pqye7K(nc+hgIQIp4b;>&DB3m%Y24 zT+gWg!RsTxO!%K%@0{+>Gt;NQ`CNZ~r%u|Yub;e)#d&@wP@Ly&#`paG2)@g7Rc`uU zc)HR1r1<{RAVNb4$gdXucj4CvzgGBlp6BI~i|zkI`1LWq5&8|DPu=cnCpJ31 z0oH+^0mlAM&qwQ17wa=LSf89=JyYwGli1C<1h~$TZ!LTq;p5joClSB?If?l7&q>6u ze@-HP{c{rW>z^amKPM5t{yAd(bHw`Ri1p{U6yY`U&ibb=mmFMw@#rDO^Zo22VtiBh zkujd{-+ws9XQO{4#`AsmkH+{s_)#&Q@5g^E#`Ajhc#P-!<)4W04dI`R@q8csQ;z4p zg!|7;mG<_|eFpcFfA^2~|9Bo(UEFWhNNlUVT|8ZV3cNl?bGD25i2?ERGd!P~pP$Ie zWB*JrKf9ZqlX`qr1D_j**O)u!H`-2qE(e}B+%d=c=Y@Y^hmYp-av$x?k9=cXPhNC< zG@qaQfme0!m}C9Rf#>IY;I)1`d^DfepI2h$^YcCMJm!u*TK^nxeWKIl=XKy!*E{;i z=T)!s*ue91Jn(#|@Z*GkV~0;|Pwhk`9Yl3D!;8CX@f$K(CHA~@pu8VP>R3|?LB&55r6Z}0HY z<;DHaJJr_C;pfcYRna^8=zKM)K40&7o_n{Z_!na5@bg~qIDbbUoi6up6P(jceg0&A zqFMC>{x_*Pk#8>iF2c9)d~~{eobW+(y12Ze%eUo#)M-Yi8}(=4lA0LxScJ%*0RN%m zqxETBeY%sX|Ap6+$hWEXlXrMN9%zJrEpWDz_v2B|&;P;SH9Pv~bose1A33KRd0viF zV?59A$1y$!{*%C`9(R2TPon$%MtF45)>|Jw9-wb8e1}7#l z7yc;Wi-kW%_;TU934grsJ-XR-OMM<}e&V~#6Z3G?9;7ap$e+~h6gXo2sRPb{Bi5hU z?QA$={W*E(!V&Aw>vjPgvHrpVm%tJ0FP(KI9I^hYZr8vO>#xnb4vtuVeYYFoi1jxO zxD}3A|3l_&aK!p;xxL_s_1|RP4o9qCnt2Btv7Wc1X}C=g-Y%l`zq1=&wG2mGfA;{q zDg}b8lwA5!d%cKNF6){(j7#1xH-pZx&u_4@X@85a!H=Bd+J;$vJSu z^+V8q2}fK%45#}Q9C1DG_vgY9*Yk5KzJ?>N=YDJ+9C1A#XU>Ns^r`(J_e&%5Qlxxp zzn9uyEkH}yNBfzFv7ONmeQJN3>QjDP^>LoizbX7Xjq(vk{V1$Y^yAKdT=*wFpSs^k zB%bzsH2+!QpZ9z;C)yU=*NW|*Ec`^_@fxhyb(`AA^`o8baeaDwJ~jPIJME{Ne#}n$ znP&T6-DyAD^kZZD{KPon#}7!Kv-J7RPrNPqcVm0^dia$&zY}8TxcxlSPuyw$jp--t zv|nWUDLd_dGV3{Yr~OjXf3nklwb`EZ>aR6^nls0}Jx+Ig`tnL7W(Yq^_}Rjzw`aZC zp0xkd_%Fqrxx%OC{B7o>{XfRf6LS^_pPsYL%t`x1(p|T-Zz24y#xE47yGZ!-{0uWE z?X!&kPRv;%e0olfnUnT)j9)6|{3v{SPJx+|_JzXN7rvqJjfHP!{Bp6KzX-ol_*KHE z&)4qebklwh;r9}LU*lJc(_JI{I^ov~zft&2!v8J&7SD(G%Xs$NZ*YvJ1p-(L6*!gmsW?=Rxd*8##GBK#4;7Ykn|{ISCK5dIY5&lLW=7@vdV z)fXQdt^@t0!e1u*6~bR7{58T~C;Sb<-z5Ak1LMzEFX8VLzPIpwguh?-e!>qFez5Sv zgdgd7?&oXZa(qTf)C9`~=}Y6n={E9}7QC_|Ju( zCHx%W=L$bx_=UnR7JiBF%Y$4N{GFQ~WyN*HXelT@C%*OHmm2kxRZMna~5$nIn zTm?t0UzqtD9I?Jh-fB2v{i4j@;fVE%GuOZo>%Yrf3rDQ~K64!$v3^PBA8^F_A2Qd& z5$l&`Zh#~3c-$4O&$7&oaK!dMX8s9BtY4nF365Bwm-iPOvHs`Gzu}1Wo9k?WBi8?t z`41eiensY1IAZ-ddH=!@>sMxOgCo{oo3|Z~SYK5qQ5Wwf1=csps{u!>=Mji+aEy)c zaay#V{QUWaaK!aI?)NPmaXpXwErKJi=kphf;fU+`Ikexw5!dti)9>Mk>-oIr5;)>| z9>4toj<}xBgDiz3uIICE%ixIXd7Se{IO2L9xBLl?xSr3CFNY(p=ks4b!x7i>dGlZ3 zi0kv=SHKb1^YhhL!V%Z=dG=r7i0k=0`zko%dVU`JZ*au*JTAQ&j<~)F{O@qY^*o-u z29CJC8T?u};(C6*>pD0>AN^h6zs@H*F3Rg=^y40njU4}%e`lqxpYCxp%!g0S$xqar zo&GP<$2am5*@NPJ?r~|)?TqHsar(5!-*ZmiXh-jE&jHD39XKmJJ$2j_|4H?+Z~Rs_ zMQVN0z9BsEeIq#H`y?FkePcM{`zCP2_f6r5@0-C9-#3RNzTX9o_`U@k@qJ4;;`>%` z#P_?x5#P6lBff6~M|@uZM||HFj`+SE9Pxc29Pxd7IO6-=;E3;cha;ocPH@Ecd%_Xl?*&JEzc(E5{XTHS_xr*T-|q)Ue7`>&@%;gC#P^-yi0==CBfdWf zj`;pyIO6+5;E3D=Z8{mlVH^LF${|QHYzX^``{x3M<`@i9c?>EB{-*159PxciIO6+OaK!h!!V%xMh9mUp$2mpVCy}sk zgO=F77%lOAS2*JP5;zjhFTiZ#Z)aOLVo&!N%phUk4lS{LDOwWtg=mTG%g~arZ;zJP zp5G)!e9v#LAin1}l2v~znKy^uKtjUPebxCMmh|OSj%_4izgv4eq5<4a_kLt|xTsIh zslW^p_8rg@e@;hdjyr!3;X4Vxr|^3@K6?E&|9;#%@U;`?;CY;V9G^a4l{il%wf$+| z4UYK!SU3`%-+eKk*vtJmv?T2JLrZLbJX#X=`=cecKLITX`vcGt+jmDx!oD+FV*4Iw zN!TBVme{^0S`zjLp(VCI5iJS(gV7S(pM;i#{UKz$c_D7&4wm$C5LQBH_Xtc!k zXQL%yUxb#}{v5Op~{Y7X=*q5Uvw!auH3Hu7P#P*k+ zzYHx2`{U3O+h2~Bg#GboiS4gIOTzvHw8ZvTq9tM99WAl_RcJ}r_drW*e>GYX_C3)O z+h2p0g#C$ViS4gNOTzvnw8Zw;p(SB|GFoE$>(P?1KLstZ{S9bI*q@4)*#1VeBGtd&---4Ee{h4Tq?Qca(!u~9@#P+wLC1HOyT4MWNXi3#P?Uh5#L`8 zM|^(`9P$0NaK!i5!4cnI4@Z1|103=Fjc~;GH^C9#-wa25e+wM({jG4s_qV|j-}ize zzP}xg`2G$!;`=+{i0|)$Bfh^Ij`+Se9P#}f4Q22hr_ZNPE@B@V(B>Y3d4;Fri@I!?kCj4;WM+iSs_=kmm zMEFOAA0_-_!apwj6T&|!{8Pd|E&MaWKP&um!apzk3&M{U{zc(m68>f3#|Zz5@UII0 zn($+Ve_i--!oMN>c;Vj^{w?9(7XBUK-xdBn;old2g76;*KT-G(g`Xt+WZ|a>|B>)h zh5uOiPlW$e_-Vp_Cj4~aKNo(6@H2&*ldONC!1{Ex!_B>ZyWe-{21;a3R1QutqmUnTr+!mk$o zcj4CvzgGBl!v7)sdf_(+zft%*}pTZR8u_-(>(7rsjPM7`8w zfBt{>@q7*8YYLwsd@bQKh0hW`Tlm_-=LnxGe4g-igs&@nJ>lyMpD%m^;TsCyNcg1i zjfHO_d{g0@3Ey1!U4(BTd`sb53BRlGt%YwRe1Y(7g>NT(q44d6-%a@4h3_DIN8$Gn zzLW5K3cr`|dkeph@cRnCpYZz&e}M3vg+EaEgM>d=_(O#6BK)DkA13_a!XF|0k-{G( z{L#V}312LHSK&*9KSuac;md?C7rsLHO5wW+f2{Dw34grsCkWqN_#VRd6#hivPZIuQ z;ZG6%RN+q({&df$K5sV9eBLY{Z=^ow)4tA}K6QLD^r_F?3VrHxZ$clvuQ~lF2d|yN z{OEnnzE6EV?f>5#ZfD#a`s~EA1pddoe!dMhK6XA1xJJiU&+yhQ`aB>1_*mr66#ZGA zk6mY+Zn&PeB)R>eKgjsAk58{$eBZ_N=kByW-1O(~v_H!97w)t#HvPpr?T<12r917* zO@G-=`);PcVyFG_roU>ZeGk)Lv(x@0(_gpK{#4W7u+#nw)8Dky{%q6VveW)N)8Dq! z{zB8=F8Vu#Pha~lHFNG3{XN2`=Uidt^b!4i!l&n4W9B>{`hLQv=iFfC3=sVw;Rky@ z3!eeZeQ|nz=ic1Og#N&4AASD$P;XA;hkHJ}zvxxH{gEH(^{M?^ZsL(x?{4R0vkvL) zzti|pJDtHWciP`?`lol=_cQ&oJM9OW{`sBugH1nrr~NR~zqHeSr0K`( zw13p}ukN&e-1K92+COFbaXamwHU0RV_Ai+Jt)2ESnf{%f_OF=!J<(4PK7G4*-OQON z`bom4=e%j=OcDK5;nQ>8HFG`@{WRgzb3QP0ri*@t@aZ{I&78FVRQTz_&oq9PINjO8 ze<}Q2;pcfi+OMX!e|GiuM1FzSNBi4_u|7Yss9t(f`tf9bVzKbw3IDzDON9SH_@%-x z6aGixe-eJV@IMRxi|{LiUn%^r!mkqkH{n+c|GV&OgkLNCI^q8ie!cJ;gx@IqpTchv z{x9MG7JjqvTZI2d_^rbKEBrR$w+mk-e4>8*?X-sQHHFU*zLxNr!eYz4P-!YT$2R|MifO_g|M7`GdXrkw3)qsne~U=py`~!XGC5 z;ljtg-je6*2+5Pp;Jn}y#h{C44M46&DQv<|g|&lWyc_`1U93*SiiCc-xtzNPT3g>Nf-d*M3> z-%0qrV|{jFzx=rM&ra+weBA3)Yv5VG17i9{IP%@uJ6+y>`T4^Kceke-`7XjACj1e? zA0>Q|@Lh#JM))$}D}?VR{BgpcAbbzuPxO51c9b0)Uy8hcyeRVi@t?^1$9W>}A3uq_ zfBYo!{_&8=`^P;Z?;rPwynlQn^8WFS$ot1PBJUsHh`fJ%Bl0JUbv{-2(}h1%__KvS zSNQXVzfky#g}+qz%Y?r|_^X7!CdP9=aNSpSKfraSzeV^vyg8}I1KHy5i|j=F-xt{b z)VHS_&GG-fi2Pmo@%`Px_ZHrNKU6gT9?|=+e~7M!aj(PYemL&+=k#%}SErAA-9CNX z>*eU<-tR*n_dWvpd%g1&ZGRu(`wD-b@b?SZ6EhX_AZ_+i2i7e4;)>+D4Q-`ClR_`k2S6C=d@k-|SL{3F6Y zD*Pzn9~1s@;hzxxNze0k&HdO@-NXF`{WHQpC;SV-zbO36!oMQ?Yr?-S{2Ri*Dg4{Q zzbpLv!hhiT)a^7s@uBdOh5tzSkA?qK_|Js@T=<#7eC&g{fb!Y>#8XW@SleueNWh5uFfRl@%!{A%HU7k-WKYlUAY z{2#)v7k-2A8-@Q<_)Wt9CH&vQZx()w@c#(ERrr5}-zNNa;j4sCG>E^R*ATv@@EO9_ z5;TIvxUDv%)dzVmkWQL z@V5+&-=1Eg?=AfO!VeJh9}<43@FT?hQNlkh{0n0KOTxb*{Ma7x>o!jK@xs3){5wPA z=f5xf#JTbPRMCGb`WeE1Ddv3LBmQ*f3;&In|Gn@(3cqq_{OSHC`agQa_Z!5VO~P*$ zeyi}?g|G2-{PtuGi}yJ_<9(j!>j~dL_~h5|^P7vlrSPqVZ!6|^5Pq+o@!PYH=noYA z!JIr#jSsS;&$Qh68;|H`wIVn@co4!B>WKJhYSC(@S}u(LineJ ze=gS7ONr( zKke)Ib(<;rFNB{X{8z$%E&P1pzY+dh;TI2!KVM6}j`u%_IX?@(Lik^W|4sPcg8#oMxhL zA^fhw7l`@oM8BKx9p}ZLuf4_meZ`yugg;35F2Wx^FMfN9g|9ds(JC3*Y%>mQTUsMzg5h?b9nse z_7-#Q6~3?V_Y41^@co4!DEvdh4-tNt@FRxDufrpvA0_zoh48C{|6TZX!fz0Mlkl5`-zxle;cJYDzr1P*pDlcD zjOX>guIKU63%tL8?_1ALrbvCBv-^4S58<<)2|xci-8Vo_!hSGXV*7?@N!SlTOKjf= zEeZRfXo>BUXi3-)LrZKwI$OTzvcw8Zx9(2}r! z7A>)TAzBjl&!Hu@Z;zIQ{qtyv?RP^H?K`0*VLt{fvHhNCN!Y)Fme_tTv?T0bMN4eIH(C<*uc0Nj-v=!T z`>|+=?e|4X!v1x%#P<84C1F1fEwTOnXi3<=ftJ|*0JJ3R$D<|eQ=cS}xvHekKN!U+COKg8MS`zjjqb0U4LQBH_6STzk#b`;`e~Oma zzAIW1_S4W3+n1mvVgDIgV*6vzlCYnSme{@&EeZS2(GuI2p(SBI11+(AIa(6-Gtm;; zSD+B<#OMOKg8CS`zk)&=T99hL(i=Vzk8er=uld{~cPwKDwV}`8`}* zzeM;SgkLKBGU0y|{wLv=3;(m@)Av(n;GB_g9ezPi?7E$amW2HZw8Zvjp(VaQ8;*o? zR$>ORbIw6a!v0sZ#P;W+C1Jk`EwTN1Xi3=rhL+g=e6%F&SED8D`8j@EYj)9(opS+Z zkZ{iLm_cm+XJ%Cu3H!%lzYqFC%qC&K2D6Ese-T;|_G{4+_U_}Nb#TP@f51g^($}|( zF`I<_di2C@&n0L{*l$2fY=0?Q680O>65Ia|EeZQS(GuHVhL(i=CbY!%m!lTt^vHg{3N!V{jOKg7?S`zkK&=T8Ujh2M{KWK^V8{jVz;``N^xK#k(Z-gVh zzXqpCe7^}TNqP5rxV1g4-(QOv#P`?15#Rrf*~ItPqb0t-0gj}+yFLG6dx%}18_|-m z--edh{wA~}?6;#Ow!axI3HvIv#P+wKC1Ib~t*VOH{#LXk>}#MUw!aN63HzF8iS2u# zC1Ia|me~Gww8Zy`ENngS{T*nD@9%^oDeqp6wQ!omp6*>}N!VwiCAPmCEeZQ9w1mBT zy4i4XeQn35_p7}zn}l<6&=b2o_n;+VpNp2Tj~@SQ%VnARaeb4#$l5;7^Xcup7pFNQ&bK!RpzJ>5Dg>NPNuEMt#zK!q&!nYN^o$!Uiw-sM z2k>viULPJzJ_tvw@0aWcN38Fk><>q*ACMdXN30*190*6OACw#fN34G+`4AkjesFRy z9I<{#atIu;erR$i9I<{_au^)3et2>?9I<{xas(W)eq?ea9I^i4o zO+E@otRIye1xKuZEcqB5vHtPo<8Z|KCz4OV5$m5!J_$#xe=7MD9I^iCt9X23P-GeE%_Q8v3_iFEF7`^_2lbt#QJf`ad5=?H)%bj3rDPfFZmuEvHtz!`*6hi3CRg? z#QG1CAHWgoCnhJt5$iupeh5dbpOl;gN35TmoD4^-pOTycN38!S`4Jqkerj?m9I^i6 z|O@0bTte=*g21l&_EcqE6v3`1TIvlb7^W^7n#QGV@8F0kYri+ei-rGA`0s`Hzn?2Q-6f*;Kkq2&e-Qmr;g<>jqwqfozg+mAh5tqP z6~eC+{#W5w3ICh$tA+nv_%*_>6@H!Ye+a)`_zl8u6#h@)Hwpij@P7-xS@j+<0_xk&WI!gm$EMEGNbFBQH_ z_;TSZgs&97oAAd9f1L2g3x9&}{^wXm>)&1UJ%sNm{E5P!B>c(3pCbIJ!at1Tx6zOL z_seObKVA4Ugg;aGvxGle_;Z9mSNQXUKVSF@guhVui-f;e_)CPpRQUf1f0^)?3x9?1 zR| z-y{6J!uJurukiN?f4}e#2>+n){evK(JvAH2jQ0r zzfAZah5t$T<--3g{4c_<5PqfbzY4!f_}_$IE&T7ouMvK&@au&CL-_T=zag$C8$`cR z_&Z2(|1JDx;kO9?kMLWC|5x~J!fzM8O87*R=%|E!-o*btl<4tf4bj&WK129g z!kh0&ah~VR6n&QP*}~TrK1cXm;q!#ABYa)q>j__9`2WY={lLpqwg1Ckd#}CL-rMmv zBqStBk|arzBuSFwUr0!jBne59BuSExBuSDaNs=Tko5eg)%A8NZV8W{h9Ocyq?DX1oRCEg5gccx%SnFn$f= zZ5eOJczedLWxNC9*D>Ca@lK3)X8d}_yD;9B@otQFXZ&WydoX?rHUnpZFcE?`VAq;di#avvotl?|S^M$1f#((Bp$1Z$$XLt?z4n8R7SV zHzxf4*7vu*obU%)KhU}f;SaWcu=N#$Kh*l6)=de2xb?%WuS_{U-p0>7JkmPv@%eG^ zcvy>4@NIP2pX0_iVJ7{LTK&d7F*ddSllN5y@W#s%tk1_K{iPWn$BgqB&3IzKHR~j4xq)DdWo+U(Wan##b`Fn(;M^uVs849P6vy!|5272{fb$@J4Mnf`!rEw(V@(=M6*fN?FpV#cRkGW`MLT5M&;r(H7r0pnVH z&5TdGWcmZfwb;gtPrGFL1ID%Zh8drB$@B+|Yq6afpLWUg2aId+Ei*ptlIaf^*J1}V zKJAj}4;a_tJ7#>^CDR`;uEkDfeA*?`A26=P_ssaTYq5*zr(KI5n10%|*v<6QuEmc` zKkZuVVfty;;wPq`cFFVyjBBx%8J~8^^aqS<@iQ|%?ULya7}sJSGd}H-=?@s!;umIo z+O^ov^wTbx{(x~Uer3j|U5f)uKkbs~4;a_tH)ed=CDR`;uEjxSeA>16o$04ti$hF5 z?ULya7}w$tW_;SUIL!3ZuEn2BKkZr^A^WxXi*&`f7Dt(W+O-fR=*OkBYvD2dv`eNR zo&l5NNa2$nFs_AcL(f0$S}3NUb}d4tpLQ)`rk{2#a+rSFwJ5;!)2>A!rk{4n^lMRs z8HaYs^lMSH1butaE}8y-aV?6G^Qp!0jGw@GDaKD^{3OQ9F@7@Rr!amhw=#YkoH!R@dk`HWV{jMjTvvkcvHrkG2Wc<7L2!IoZgSLXv6fkWxPG( z9Y|Nq_NkcdQwe(eRD#|Qwe(eRD#|b9m(2W2X8t8J|B|_1gXewZ{vt&u=Kh*~o)QT9c}gIzWX7RyuYg(JfLY#vozLsZ z=_=8YTwd*XA$Z?7zIQzD-ZAfcjFph0^AmZOq~9NV1L;z5-i_(Mnem>C-^O?!(&6$iS+%8BwY&H;gcL>zY;Oy`57-nI=ugibR~{syg1`0 zFkYJRlNc}0_$iE6V*GT*t1^BT<24vRm+{(+U%+@h#xG{PA>)@Z-h}Zh8E;OyWb#c4 zF2`Du5`d$Dd_u6$v$rB zM~<(=ouq3qknwvMAF_$cH!U7ud?e$KGCrR1CmEl@_;VBK`JBP@ziD|fcn*P|r(0(E zahc~A`NRh$^Tx;T`%Qc$ffkskj;rhkp)_!;7&@Cn+FEH}@O@`<&U zC-eU?w zPx?1mp7eiVdD6ex@}&Pu%ai`Ysn1`hm-kQ0lm0E%ILY{5S)TN7wLIzn+VZ4-o8?LW zHpAky0>deWcXKGXf_?K9n<-aga)>FpC8=RXIQ_gicIC(E^i z@$W1*pRX^F_4#_-4sku?gWo%e{-WUDryS=8$3fr4_%F=u_(Q56r;B-u%eC9`WO;ui z9H+a-a{L|u%pbu|GScC5UX1_B_-~{K;&;;Fb3mjA;!o1y^Ejl#H%7Fh zmP-qt^gslpYoSSpzXOu4MZQw>baO~of_5$PGySx~=TMk_+O;Ui^wSQXTVeWXhv!XX zf55mFg~@)!IDGzv>8Bk&|3dZ$jB9Zm*$>bANQckSkggbq&(VCFAhE4sskVP9a?} zE*TFP*PsMj`O_IJTJ>(o|oka`gvK7pr424h;yy! zn&-miFrp=6P<8^E@}{r(S=+acWuf5B~~T#NfNE z=edcWntCS!uII$dGG31HADHoXGyWsvdl>(T@x7KO>xX{5CC7Pv#=Jg|!@O>gBkb1) zl79R3gyeRoU(d;LUI&0xEj+kg)~oa27Q-^%f1daTRT~T|+mGZs9}FwoKT~zUu(Exl zx&RC-+mFww3x<{Lo79D1SlRxCst1OZ?VHs_U|8AyrK%5xmF-*9#b8+3{*`I~hL!DG z)g@q9+5WX^2!@sI+tj6CSlPZ^H3GxR_MDu{z_7CYTh$m0E8Bn1e>oUdw(n3)z_7CY zJ9PyZR<>W4(-aIV+jpuf!LYLZwwz{QSlNCw|5adE*%p+nUJSeo7*^VggWmv#mG)uJ8x3IS7Wc#;Y4^R4ATK&oRtx}HrOEOMt%gy~oev$sW8@>)~ z#>p?ze@`irJ5GL){(A~~GEVyM6gW=eZBo-sUT5}1eo?51*>~}G+OJ{y+cMsc@%D^g z%XkOIuVcI;SHJ<3||(i}9n33ub@! z821^Mj0cP>#x>(1;}PRAA z0>iR>HyD=fd%&=4-wTFi`#vx%+xLTE*?s^F%eZ+R%_L&30Y9|neH z`*1KU+ed(5**+2s%l1)VShkM_!?Jx07?$nhz_4r|4~Av?1TZYyCxT(wJ_!uV_Q_ya zwod`WvVAHTmhIEPuxy_WhGqKr5j>7z%n?0yM`WxE2yvONUDvONaF zvONb3%k~0bShg1e!?L{y7?$lt!LV#E4u)lW2{0_%OM+q9UK$L`_A+2twwDFNvb{VQ zmhBb5uxzgghGlytFf7|EgJIcT1q{pfs$f{QR|CVcy*e0{?KQx#Y_AE1WqU0!EZb{? zVcA{>49oVqU|7b}_k#;zpTn~E$3Y+nzCW%~v&EZaANVcEV349oV-U|649oVq zU|6=-1H-btJ{Xqm4ZyH$ZwQ8kZvMVzUJq#mmh4}~BQY$q$GQFh;}^p#qm7AihC_c7 z!oT$3-i7c7p}!g7Bfy&z{t$Qz!bgI)B77T6w+-RnfVU<5VHl@9;iJGi5dH{wN5V&g zcP9K%@GgXp0q;uq_b{K`2pe+;}A;p4%36aF}OAHpYq_anSl zF}Qaj{0ZnEK=_m30|}o5K8WzAzy}llH24t0r+^P7yfK%vVAicmhD@>ux#H7 zhGqLUFf7}*gJIde0}RXdonTnD?*hZJeK#1E?R&tmY~KrpW&1ubEZg^kVcC8F49oU| zU|6;v0>iTXFc_BYN5HUbKZ-`UcOpECfU^4~7?$k{49oTq49oTy49oT$Ff7{(fMMBQ z2n@^iB4Ajy7X`zzy*L<_?IpmlY%d9hWqWBbEaUjREXlX|kcU{w%g#V zUk`?5`vx#9+c$z?*}e%3%l6G+ShjBg!?JxV7?$nZz_4uJ4u)m>4lpd+cYAq5Ez#2MZmCZFA9cbdvP!<+e?69*X8~@8<>Ha+bI^&@; zKj&wr>-x9F@CHe|dV0DkugQ4cbT44WzliZ4GSf|#H*cH^v-)c@)2+*R-Z&R$jZ^<` z`!C7r&l~5Lto4)Uzh!wtX8gvM<2GWplcp!aD>P7MJJ0iGU|6;{2g9#R%l3|7ShjZt!?L{#7?$l_!LV%a28LyOcQ7p5dw^lt-V+SV z_FiCEw)Y0Zvb_%&mhJt(ux#%ShGqKzFf7{#f??S{2n@^i!C+Xn4*|oneJB`~?Zd#Z zY#$DWW%~#)EZawdVHr>VeW5hmCtzW2r@agqmhEN1uxu|6hGlyNFf7|Ef??TS2@K2j z%3xTwR{_Jay($=%?bX1rY_AT6WqS=UEZb{>VcA{_49oV~U|6=-0mHJrE*O^W^}w)f zuMdW0djl{m+Z%#m+1>~Y%l5`#ShhC-!?L|87?$nLz_4s@4u)lW3otC(TY+KO-UbZI z_O@VH=*j&o?hoeYQs#c=kF5KbQP(E@M~~wDHQsNU`;nAq9zVpSlaEi}iDTaV&KTH7 zvCMqt`8Y5v+sA`p***ab%l3(2Shi0B!?Jxc7?$l*z_4te3WjC-G%zgNr-NbHJ_8KP z_L*Q9*$xxmknzcmAIW?l%M`~y%k)omd}GF^IevWR`@p9=zA4i`!|^XN zKGX5d8K33&ml>b!_?C>%ar~={&vkrj#^*Wyb;jpAzAfVm9N(Vtg^uTB*25ylzs>Y7 zcKrAJcuOsDd`G5#spH>ee3|3dWv08_@tv9e6^`GQ>0jyi(aij;cD!h&e@(8N`*+;B z;9ftY={&?O5nlTz9KW|`J>mGhJsSwe@9o)0IDT)>Cc^Q1do~k}-`lf=aQxn$t%T$E z_G}{@zqe;Q;rP8hI|#?`?b%5!|-TOr3yz7=uYn_~%BY)fwF$?3t3x>ETV292-|7*L`BtBB%(n)FV~#Z>9CNG@;h1BM3CA33 zLOAAFQ^GOFnh}mU)|_z6u@;15j5{^06nQ+Xp zE`(!_btN2gtXs;HyfQh~J#&ehV?7)O-f@#-6C5`=HqmjDW0P_{onwgL!K!ZF9D5{@}Gjd0Ad>4amB z%^)0eY$oCOIBgc;m~XQQ$9$VZIOf}2!ZF|G5svvbpK#2#1%zY1EhHTCZ4u#^Z;J`X zd|N^|=G#)jG2fOEj`_BnaLl(Agk!#~BpmZ?HQ|_VYY4}DTbuIid|Q{fB%N<2$JRS; za%_X+CYLrkZgOUm<0fY|J8p7gi{mCYwmNQdW1Hh9H?})&@?nSLCLeY>Zt`K5<0c<= zJ8tq}kK-mE_Bw9zVV~nBANJ>ZIv);X)Xj&3gkwG&A{_JKFyWX3M+nFL{V3tMzk8== z9{#6ZXY=4YZs5H?gya6M2*>?BBpmnmm~hN{@or-9?mF12vnN^Qtr9__(DD;h1Ax3CA4kMmXkJcfv8pdJv8| z){}6|v0j8@j`b!SAGh=&9P_Oo;h1mz3CDaJKse^xK*BNK1`&?=HkfeCw;_aMz6~WD z^KBU6m~X=g$9x-+^6Y#YnYqNxw^5Fp92@Pp$+0nxn;aYGxXH2cj+*<`CpHVkw77&g(vygDinMH(S&MYPzb7l$Qm@`WW$DCP4IOfc9!ZBx75RN&s zl5otK)r4cttRWn8W-Z~EGwTS)oLNse=FA4dF=sXsjybc5aLk#_gk#QZAslmNE8&&Kz~zD(xkQ8zb=5RSP~lyJI=y+$cjh=0;hwkkxlw~~%#E6aV{X(U9CM>K;g}nB2*=#0 zOE~66J;E_J>Zd$AHyUIvadV@glm z;ke0}R*svTY2&!bnYNCboN4d4d7RV1ag#qC9XF42Iy-J2=X7!0JpbzIxXH0@j+-3o z?zqXZ9*&zF>*=`3v0jdw9P914$+13;o9AEsay^}I{WI$3+W^8b-v$zn`8J4f%(uaW zW4;X`9P@1`;h1m32*-RIPB`Y<2*NSnMiP$sHi~e}x6y=SzKtOq^KBgAm~Z0=$9$VW zIOf|#!ZF__5svvbnQ+XvDTHIbO(h)jZ5rX2Z_^3Ke49Zy=G)AaXXo3j%q4EV&34@6 z+Z@MDzRh*qEq2`G+Y-l3zAbg!zO8fIg6XZ&e*P`Bu$wlW)}>H~Ch>ag%Q~9XI(_ z%W;!$wH-J4R>yIZZ*?6v`Bu+ylW+AMH~H4Uag%Qib3L7JjWU|OAL08m8xxNC)`W1( zx2A++zBMBp^Q}4Im~Slz$9!u=IOba$!ZF|45{~)So^Z^!4uoUAbtD|~tux`6Z(Rt- zeCtX$=36(yG2glqj``MuaLl)!gk!$-A{_IrH{qCXeF(>V>qj`|TYtha-v*>SJKqLo zE^+g1kmDxb20L!@ZHVJ0--bGF@@<&oCf|lTZt`t}<0jumI&Si9l;bAfMmuiuZH(h4 z-^Mv^@@>51Cf_DFZt`uS<0juGId1Z8vg5z!$9vc*j+=a&>bS|bX^xwGo9?*Dw;7I` ze4FXG$+uaKn|zy{>*;)(lTkO{<`RziHji-3xA}x)zAYde^KBvFm~V>+$9!8%IOf|D z!ZF{L5{~({jBw1i<%DCttsorpZ6)EDZ>tH%d|N{}=G$7rG2hk^j`_BpaLl(2gk!#K zBpmZ?6XBR|n+eB!+d??z+g8Fc-?pVZJKwfvE^+g1hvO#Sb~A1-^<+#bW&~cM*vEwG+avV4LR={zSZ-pE;`BubnlW#>GH~CgP*VFk{BBO4;l_VVV ztu*17Z)FI_d@D;h=39BfG2bc>j`>!RaLl(#gk!!{CLHsv3gMVytNeZn!{8W4{8){t<_w?>3xzBNvH zvVWQPr8mi3;^tdZ$4$O9bKK-xbH`1-wQ$_zTPw#+zO`}ON(fTR+E5 zzV&z9dhH%WcafD;OjVB!QZ35w#Zxac}e49i#=G$b#G2f;Tj`=o~aLl)9gk!!< zCmi!_2H}`*GYQ9hn?*S0+ib!y-{ugG`8JnuRR$ja6RyGMr##8S5FDNXWG+ePVU+QO zj+f2B{zZ<*nf}F&=gasK$8$2i)bacoU*`BYiPK%~c!5m+3daj(e5K=sGQQgJ!Wm!V zc#({+b^N%DuXDU;#@9PuF0Be7oZ%Grq&|VwvUInd|s}X7SU}r850^n`P%-Q<$G!neJ@A5_~t|&A|5%eiis$ z!kdHdBm8Rc{e-swKR|d(@PmX`0zX7}EAYdFw+25#cm>#hj}qPn`n@wVt1atu0oQ;_ z!rOu?!rOs|gtrHe2_FldL-@7e1qkl|UWoAPz>5&x5xgkjoxqC|-Wj|E;n#zgOu6~L z#-1ph+TMylxFz?$CxVww^(S5iybR$dftMw`EO>ds%Yj!QygYctlxOE{rOYL6-d1+p z9EaLmycW3CP$9CLLb;h3v~2*+F~^9bRXpGOJD{Pe21&kHa=CE=K#D&^Vv8D=hV^D}nb`oSvy$T` zKPx+K^0SKLCO@k>Zt}C5<0e0=J8tr`hT|qbYdUW7vsSLB^RsqF-TbUWIObe)dawc7FEHT;k^E0LM*!4s_h)=OD*Tehzlro*xiwMX3TueCT=Mus(KbI1Y`MHd6%+KY7V}7n69P@J};h3MR z3CH|gLpbK=TEa0u*Ab5Sxt?&$&kclQer_Zj^K%p7n4g;o$NbzvIOgY8!ZAO$5svw} zop8+09Vt)p^JH*%29UV~^E280AB6eemFkb-?+ExG33lZ(k9qMo_9uQSY$wT2+RHLt zj`1Iu@pm)+BjbA*|B3OvmYelp{twjd)Otw!9>(`FzK`)IGXHHcoik>-_&<8_C+~JK zK85l9%=q}fa;b3+F#QJ^Kg9T9#*Z+5lyUDYdOjuNit&)~nDHFO3ou@Y@gj^DWxP1! zB^WQscxlGxr*3!L-_8G*tN?pFmf5cIydoHu?Ulf=Y_AN4WqTDcEZeJsVcA{{49oWF zU|6=-0K>AqCK#6OwZO1!uMLJ}dmS(=+v|d1*n}T84-V6-O_U2$%wzmMovb_};mhEl8uxxJ&hGlzuFf7|UfMMC*5e&=r z&R|%!cLBq)y(<`&am@MT|FM>V{R=C};l#^=VcA|D49oTkU|6w#g}ULOq0 z_6A^Bwl@UBvb_-)mhFwfuxxJvhGlzGFf7}ffnnL+91P3$7GPMmw*temy$u+a?QOxZ zY;O;SWqSuOEZaMRVWH#y_f+usuy85dgUnCbi!ffC@e>%Y!gy)Mk7v9b<7Y5_D&v(H zKaKIqjGxH($&8=E_(_acWV{sPWf(8YcrnIHFkX`JvW%B!yaMChGD+@khrb-3Y@ONL z?M+O7cg9b*ri=d%Hx`A(%^kAGPy80fZ)N;8#&2i5FXMMGekbF1F@87W_gHTJuT5cb z@8sA7Fe0;}0`Fn(?uWk7xV|#wRiUG~-hle~$4PjK9eEY{p+-SkGro}V zw-{f-_`8fRXZ!=kS2O+*>7g*67s$&2vmJ)QyuaP`bsebfHWcegFL><#A9aR%L6awD z{DQ)KKW!Js&HQwA+Ul{1P`TW8l$IaLy(zc9pcbNdc;+}zLD`wjBjRq3*%cE-^TcM#&;NZ*5^*fcQNDaW_%Chdl}!y_qW;|cobC#)~jsjPVkTmtwpOaWyCkCuZMIq`K) zSWV)zbU#4il^H*s@hXg0W&BLWt1*5S`!L>@@qUc=XZ%ja2QY3w{!eoF zE~bAV<99QD599YTK7{f67$3^`{frM|`~k*?GyWjsBN!ja_`{5kV*C-tA7y+D<6{|r znYq6k$MiqO_;|)2XM6(V6B&P!@uwJ{%=pucPhtES#-}p=EaTG{e~$6#j6cu#48~_N z{vzYE7=MZJ*^Ix*Y*%xb{<)05%J@9SUt|1r#@}FkA>(f{zKHR+7+=iz+l((^{2j)Z zGX5^(?=ild@%I^D!T1M^uVj1`h-JC^K_4KpK-}}z_?;O zWISR#W;`F``57<3ctOSsF8m6`p79xs&t!ZS<1aD(GUIa?pUe2G zjL&2IHOA*N{yO6e7+=WvBE}apzJ&327+=cxyNoYm{5{5(GyXo~D;WQP@s*6PV*EqK z*D(GO<7*lJnDKRtf5P~B#y@3z1LL1D{yF1cF#aXuTNwX}@vV%1&GF@BKo-x)u|_#ccHD|j^b2j5?s z{C)N?(|?5VzZgHtxF~lt_a{AFk8z*zfN{-u$autfX=eSzOn(mJ`57<3ctOSsFGkyZ&B^fWxcp1h|V!SNloR^J;}$h0Q@c}3c+XJ3&EiX zaVP{G$HBX)i)F4+96rlZLYyEZ=ZKo(Tv1D$Cu)oHMICX0s4FfM^~6P@zPMO45SNIC z;!@E_TqYWe%i;P>;QCFnmN3jZm%X(7xhr5!a*iFE!s#nTGjWw@4r5;pr&@@XqLpYZ z+K6jJ+sx9o6Ya&dqJy|jbQGOHI*aQ?7jc8=DsB|r#7&~RxLNcNw}_tNR?$n`CVGq8 zMIX^u^b>c8{xIsDVt}|y3>0^ZLE;`USllayi2KA)alaTQ9uULDgJOhuNQ@K@i&5ec zF=r+YJ>n;^SNtsYiC@Hi@vAr>eiH}9@8Xd7LmU==iX-ALaTMNu z?|Hr_y}(nR_Chc6VlSVUTR}_q;d5d%>IOz39#IUh-ypFMD&mSG>92tKK~CHE+K6y0^f4!&~UR=`Hf!@)mn< zdrQ1`yrtf|-ZJk!Z@Krrx5E3tTj{OxR(l_MYrK!Vwcf|xI`0#2z4xiN!TZeH=zZ>O z^1kpkdtZ86ysx~i-q+qX?;CHs_pP_X`_9|xeedn^e(-jCKYDw-pS-=^&)z=o7jM7! zt9QWr%{%D*?j7>}@D6)_dPls!yrU3gp6~n84}9foKlCF%_Vf8Uety4zU(he)7xs(z z$N5G5Vt#S|c)x^yf?v`v<(KwP^vn1s`DOibetG|7zk+{?U(r9+ujHTRSN2c$tN3U5 zRsA#lc3w6AEWf&cwqL_P$FJ$1>(}zn^K1L(`*r*a{JQ>yem(ypzrKI5-@w1bZ|Gm@ zH}Ws@8~d00P5dkTrv8 zmwP#m-_0ND-|r9eAMl6!55hS!1#=0W9+Bxuyf2(HbJ5Lz$R7!Zdl7 z+J6+*#~6PsevOwH=Rf9;_aFBs_)lccqg^8=`cL|k{HOfM{?njSpq}xk`p^2){OA1X z{`39}{{?@h|Dr$3f61TizwFQPU-9Squln<#^EH3I|GK}xf5Ttszv(aX-|`pxZ~II9 zcl@RPyZ$o&J%73XzQ4l%z+dUF@>lyG`fL1;{I&ka{yP5?f4%>yzrp{^-{^ntZ}PwJ zH~U}uTl}y5t^U{kHvb!cyZ^1f!~f3T>3{F<@_+Dm`#<`7{Ga^2{?GnC{}+G1|Eqt% z|II(>|L!01|L_m{fBHxKzx<=Vke>9Vlz~)I%O)a}k&I8UY;x~$WvrRd8(`=Pm`79>9UGELspe%%4+f~ zSzVqjYshnCO?j@YCC`(!<@vIXyg=5K7s`6_B3WNvEE~v6WJ7tWY$Pv}jpgOCiM&EK zl~>AU@+#R}UM*Y5ma>&>E!)UzWLw!zwwKq+4)QwLQFfA@<@K_Qyg_!AH_C4ECfQxy zEPKdXWKVgk>?LoLz2)t)kL)Y^$vb3!d8Zs8?~()M-Exq;M-G<><->B6d_<0xkIFG}tjybT#>sK=F*#m7E+@z*+ zmCwp)@;NzOJ}+m;7vxO&qMRjPlC$N@a*ljO&XupqdGa+mU%oCE$T#Fd`KDYX-;#^v z+j5C~M=q7`%4PCBxm><4SI7_KO1Vm|mLJMB@*}xcek|9?Pvm;}soWqxlN;sda+CZ* zZkAulE%Gb5RemkE$#3L#`K{a`zmq%V_i~r~LGG46%02QYxmW%y_sL)6e)+3BAb*nw z*%2EBsYg5JUHL7$*+&@Z?n=pWn}3<&ND1_pNr zgMxd4!NI-3kl?;xXmEcpEO;Oo9y}O~fUzISOsA=63XkiAz|=8^=Lq;V>b1BA6IF8B7YE3ML0n!*9&Er{Gdt!t~FS z;NLkUBP7>-3Z{@)_VF`8-k}LRKAallgGchu28G150M|gW?8)(S!SvwyU|KK(3J)*9 zVP^1RFe`W|m>s;FIgj=~JUxD*;gI9xj!E1q;*8Jf0U_tOkurO<_Cu{o6z&+#> zi-JYR=IyQA@fQbg2TOu?a?k%y=kR~GZ)xyuuAhe%EY16{jie9H!0nTq$F(sh zn3L&fdTfjB>*JhL&%ewPtq4}Y<>pqTe+%&ebgcZFx%=1a2e)gS%j7riDdzq>F>`D* zG2BM~^|=3kymVDS9bRDeJhLCJ4%|bs*Z%v*$#!9maov6xd#qsc z{G)V9M*Yy*644V&j?r)lF?sj{JkI(@bAa6@Yt7i)R$|sI{{E-i$wygRJ3I!2e9Rk7 zz#eC&pR9|2I{x4Ho4weKpMAfQOw&Go=2$W&`&jzACP@>)W3vY)W0);=ZIC<<{ZEfS z4%TIj^+~WE&VL$gNa?CzZSWbKUkk@;oqfjW+F)bm(so{w31&_|4>ko~1e=2|gDt^V z!Pd;EcnLlt_?kF$3R=Q*w|{lOxmgRhvE75WI$CmUU(TJkN5b=F3renm=eEI|f0LPV zk{PJmGjk%ux4{lr{^WXiiTU|1cU#;Ud=IC0$7l{qj^onSA< zYvJ_mCaTQ_H_QvwnX(ww7_kZE!m8_D8`VoR{QyW9AfE=AztRdxD>W zy_t3Mvvmoz{5YbSW86k^2T7fvmfu_>S(4=V@0L9KT1j`Z7L)U4jpFT}xBNH{xSYwn z;3a1H-EAN>>u?fBHP@wY|4souhE4yNeltZg&Hw%FAD6;i{(Z2_dHX-k<1fMf%x&~* zaNyYT=gs-5;J4sl?k)Ixa0pJDG5^)_kCpAbye&`BS^IeYNbpx?Pdpk3<_j5n`OsG z^2s3wPUZcW^ut>rnY-jTS-Z(`;(vGi_x(6^-2TlrX!Zh3AgNZtQ&Y1Sta5IDr8Hb- zrj8?+wT$Qg)$Na+c|V3@0olR3xv#rZM&f23lyHpmBs%b%n2s{*i$ z1yvzf6G{Fhb6;2$$-4E;NPoZl$rO`uvX61y;ncA!`;g3Wa-4nXe|ByoEL}VAxXf~! ztpJm#s44~`L~(VzDgoR732LlN=GIKFq)PA0KOCFue|7t3_v1Od&GQbpwVAb_XZ$HM zH~i)FCDa;3!_l&@Va6|&dpnm-ts$IKyw5yQl>t3Tl~v_b`P@#tCbj>geRyg1 z9Q^msVX~YI+p{@TP!*0P8%`S^hvXev`m2IdlsTC0PQ)X+uVGpErNL4E*$+mcFsICKYX01P4);2|9#$2Fe1 zRm(kfR_>|1HEm8+KXys7q-U!d>Ks*5ovUi8^HgnhKAblP-1BRwItrf)ZG@%ARGj)|}uC7)sR7=%LwN`D^HL9&@r`oG)RR?vQ>Zm%Y&gy#AMctsfsvA`|b(89@ zZdN@Y%Wp~LdC$!0TU9T0o9eA@SAA4p)lc1_`l~zD0CkrdsP0yS)IDmjx>pTR_o<=k zel<)zpoXgl)d=;F8mS&uqtqj6w0cyHQDfCO^_Uv39#<386R>YjR8Oi&>M1q(|LDWh zYKnU1|5t~p>i?_*w@>_k=Xv+Nm~Pqgk$o@gUY_0k@14t==6`4We>L7eU7ozL{=H@U zcdnH;&Hv8&_;=>Pz7Ecbc?C0lUtvyDk3J~FG4htpoQ1sF~_THA}suW~-Og9QBHtt6o*})N5+KdR;A0Z>WXpO|?k9r53BV)e`lNTB_bv z%hY>nxq4r%P#>t3YL!~8K2&SeM{2G5Sgli^sP*bowLyKRHmc9nCiR8dtiDuR)K_Y& z`dV#M->B{CTeU-dr*^9E)h_je+O2+6d(=;AuliZ-Q@^PF>Q{9@{iY6P?oWPKhtwbH zu=-OS$((=aU)(Py>)`($|KBz6f7ihOT?7ATtpR+_`uB4jS&uOO{uX|E&N2 z?Jjdq_?NbXfWhCMcY9iKEj(g~4%wL3YTzTCVc!2EtFNY3Hhj_`#Z;s4$E|DARAcYmY(?@Yyvl3w~`8^KF( zo&Ptc^DvB(H;wZS6mqKO8^r`gqR$$-Df&dn%dIzcXrbT|B1N$q&cUF#Vk5-#z`$<_~W;EU+W;@DGMjCJE*Gzs)E+@Z} zd^YE?Cz+ag-%av<9@M`6IC#Z3dC!hHHr;urld1gg9VhE-ZQyBNOC4yXwGMTpW1Uaq z?UkeRXO91q+pe9rEhwOqX%*CkbYWdYAE%4zV!F6KUYF2Ena3&A`cKxjIZj>|Paosj z&0F($Dt)Orjn_8$Mg8^jf4;PN_v&WPz{fhtUwG)(xBus3|Fh0*nXFCH7LUyuKdRiv zZpk|QXH($2(|cR89+KM|kB#BGe()!mdMEPld#1-si@N>!x%m4_@;-TE_SF+~NnJ{p z)+fTDj6O-1)n@9+?{d1lK3P}Lr|63MR9#7*rYq~ybrpSvuBy+})%01qx;|Ui(C6ry z`dnR0pQmf<^K~74fv&4B)b;d5y1u?xH_(^phWb+7NMEKK>&r9KXriysO?BRyFsG8~ zCdXzg?i37xEjl@%<(*y&m!%KMI>5hQdkw$>i|8&@*A5LfDE`YPRAU#(l{mb#U0 zt=s5pbX(m{x7XL|4*ELXQFqdv_4T@ozCm}@H|lQsCf!}%tb6ENbWeS&?xkLL0*JyhSXhv^6OaQ&bjp&!yC^}~9UengMf zkLodctRANy)8qBydV+pJPt;H9N%|>0SwF3(=x6j){j8p*pVQOz^LmDULC@4L>RI|F zJzKx5=jd1TT>Yw^r(e_a_3L_penT(RZ|X(*ExlO3t(WL`^iutJ9ocy-|OzH|a0*X8on!qQBBx_1Aiv{zh-t-|8Lu zJH1nXuXpJm^lts5-lKogd-czHpZ-Pf*T3om`Zs-0|E>?|KlEY!r#_>BA84Dr)diT>xuef)>vGYNhDLNL{bG6~t& zFB}#Lj|+>2#lqs@@nMPZgs@~-Dl8qI7?uf73d@G&!t&wCVTJINuwr;>SSdU$tQ?*m zRte7ttA=NW)xxvF>fza8jqseXW_WH`D?Bf(9iAW72`>oih8KqQ!i&QC;l*Kt@RG1$ zcxl)uyew=SULH0HuLzrlSBA~PtHS2t)nSXUW!Nfg9kvOt3EPJ4!uH{{VTbU#uw&RM z>>OSnb_s6?yM{N0-NKu~?%~a0kMNeTXLxJaE4(f29o`=H3Hyfq!aKtL;ho`t@UC!R zcy~A`yeAwS-Wv`H?+b^9_lLv62g2dugW-tqp>SmQa5yS_Bpe++8jcCahU3D=!tvqb z;e_ysaANpmI4OK8oE$zKP6?k0r-sjl)57P%>EZL?jPQkUX82+_D|{)O9ljjS31124 zhOdV6!q>w2;p^do@QrX`_-42$d@EcWz8x+J-wBt7?}p35_rm4j`{9c4gK%ZIDqJ0Y z7_JFF3fG1ohwH*m!u8>&;fCj} zm5a(pCr1^cQ=*CyrpBpJrRcP%a&&rBC3F6asA_a(R4qCysveyk)riiCYDVWqwW9N) z+R^z@o#=w7ZggQ(FS;nIA6*4$*Z{N3c#%ouRIW>Jr@$b&YO}xmP z&*;{uS9Dv{JGwpU6ZMVyMR!E~qdTJk(OuEN=@f(Rb0#==*3_^h2~e`Z068J<(6m zUO4r0v@iN4+8_NI9f*F54o1I&9g6;l4(A^JJa$UxBhg>c(MZG(1s;?+#KMnd9K;HK zC&$Sv209MoD28)!zBnh&9~X!V#)aZ5;Il+{C>$4o%Z`hS!tdtr>GxO^gHy%hv)~i_ zW`yHod`+!Hd_r6jN69)gfpey>ly%wR2)?EuIf&BniE)|uq&QdLlCp8R7;oqD@yT(8 z_>{O}d}>@NJ}s^spB`6<&xotWXU5gyv*POU*>R2doVaFuZd@xqFRmS*AJ>6vUJ%!f zFO2KO7sd7Ci{l3IC2_;}(zsE4S!Psx2UGT;ah!er@6X}f@jsaQc<-L1zqzN!bNER` zJS3+~7v6W^sl3Mr{MdNO<#ChvinwXqR9qQ1i?4#?=JC~Wi@0UnDsCOOiLZ&<#_i(v z;Mc|-;CB;oUEDG56nBoVhjUFum-vRbE1bF!svFczP~GF3;~w!XaZAxNzBTR@-xl|d zZ;$)LedB)d9dUo?xHBFQ-xUvx?~Vt>_^C5I+!GIu?~RAV_rc{&GVfL$8jqFt$HU?W z;^Faw@rd}Lcx3!=JSu)99vwd#kBP^|PF_=R|8{9-&SekqvSfb$>3E8(}f#zcztudPmcMrcs-o@G~N(@2FDxY&*M$UF8LxgS~5L*8J5MH<1gba z(D_xoHFrcaZ(qmT;&0;Z@wf4g_`7&#{C&JD{vqBS{}}Iye~S0UKWF;)#lOV+<6q+g z@o(|L`1klw{Kv6z%)Bm(566Gz&WV|OdoGT^HInYX;-hd*@TYgKZ)SIAfyMs2`*!lA z@}^R$R4Qqk?oJ~CNFWjvhQoWpH)m_Led^U2xx_0Ij35Y#V1McM@NtAdNQ6Rco4nGI zQN%fE?S-uvk?)(Q5gM`cmPQ*}X>o`_*uP7CONvH%-YxPq`Oo6m+iiIJJoZQCc{rnB zZ;3r3U!HpFMhDq@lE`&@TMl1pjgA#O`zlZB9WM_ze2wpy`}DEKU#b7L{Ym=gaR`qH zh=@ptj3|hTXo!v&h>65PVk2>o5F{=V4~dT?KoTN}kizsBr}o)$%56nix+6W1o=7jGH_`{`i}XYK zBLk3u$RK1eG6Wfl3`2$^Bao5EC}cD;1{sTtL&hT$kcr47WHK@ZnTkw9>^nW5PyPEp zhWjlZ@SXvL*HRoD{lass{bgicM49iI_v|;OBh!%?AQb-VjKQUk%?uP#qbONVc{FScZ7g}b8kt!-m(zpc6+E4;`f z<<)BCy*azCFXu~eL@nMrz9pWvZNFGDJA-El~?7Tlo56^on@*G3G`A;Fw(fCsmcA0I#=TobOuarlF_xR~Ww(jVp z*41NlGMfM^4kpsv<d96Ua&A6ml9l zgPcXqA?J|`$VKE5avAvzxq@6pt|8Zv8^}%M7IGW8gWN^#A@`97$V222@)&u7JVl-% z&yg3%OXL;u8u=Z0gS-4n=+E(J*v4IszSudhQyGLPz^70%G4=33OX%3_2Da zhmJ=lpcBza=wx&XIu)IUPDf{;GtpV-Y;+Df7oCUBM;D+A(M9NDbP2i?U4|}4e?eEE zE74WxYIF^{7F~y~M>l{rHu|))DGYm`K=?T*{J%t-(NDiCYpp^Moe*BTl?z|{=jZMF zLSLI&bHKVI=ea9q=j^+5_FS=3&lAEHwdJie;+c{y9Sl~X^yf1!5x1&4Io#-xfH@XMi zi|#}BqX*D~=ppnldIUX+9z&0#C(x7VDfBdY20e?OL(iiZ(2M9L^fLMzdIi0TUPG^= zH_)5tE%Y{e2fd5lL+_&x(1++F^fCGbeTqIqpQA6(m*^|>HTpaH27QbEfxbikMBk$y z(2ppDIWQ*%V=l~%1z>?#5EhIf7>Z#Sju9A%Q5cOe7>jWjj|rHFNtlc&n2Kqbjv1JV z#lm7^aj+09E*1}qk0rnoVu`TCSQ0EL7K$aql4B{blvpY(HI@cTi>1TTV;QiFSSBnp zmIcd-Wy7*#Ik22qE-W{e2g{4)!}4PVu!2}2tT0vtD~c7vien|Pl2|FMG*$*HiK9SS747Rt2kyRl}-dHL#jkEvzDG3pxRth)u#KV^bnUOGiZhRBReH9fU3D zBv31SAOnZES~~~3W?(b0nb?HC!z>^@8=Hg81)Pc4Jdm^QvrYuq6XySo7GMjpMc86& z3APklhAqc_!B$`^u~pb=Yz?*+TZgU3HeegEP1t5^3$_*82I~EaZO3+CJF#8Z?!UE6 z#P(o&v3=Nn>;QHUJA@s^j$lWzW7u)*1a=ZT(Xgv1{0M>;`rdyM^7x?qGMZd)R&K0rn7kggwTdU{A4U*mLX!_7Zyq z>b=H($KGIXu|KePe`}eD{fWKDK42fguFruxaTs^uZae@F#Dnl)9KoZu)-FMD499T- zNRnaF6i(v|&f??22yi%$3-)VF;l{zP{XJ3$5^)KaaRpa#4cBo4H}P0_Y&;Ggg2%<< z;qmbVctSi8o)}MpC&feYWO#Bs1)dU5g{Q{T;A!!6czQeoo)OQ4XU4POS@CRmc0323 z6VHX`#`EBL@qBoGyZ~MhFN7Dyi{M4^Vt8@91YQy^g_p+5;AQc0czL`6UJO>Gg}27r0PnQL+v4r; z_IL-pBi;$`jCaAi;@$A>cn`cM-V5*j1!M4OFGjU}Mwf5ROn<*mw>}Z;gZIVz;r;Oe z_&|IRJ{TW@55SW{5pOEzlq<%Z{v6HyZAl)KK=lIh(E#~<4^FX_%r-D{sMoA zzrtVRzvFN4w_t4lz~AA2;_vYf_(vQf9E6jA2^Zle0*F8&hzKSS0wpj4CkTQhD1s&! zf+aYDCj>$yBtj+>LM1dpCk(4I7A2$mxxEiClU||i9|$VA_H(iTqUj%*NGd%P2v`Do47;VCGHXTi3h|(;t}zfctSiSo)OQ9 z7sN~A74e$*op?jMCH^4Z5q}czi4Vj_0wNuxlY~hZ=_UinKr)C7CJ_=P!OoK;NRp&T znq)|peN0uimkQK>FWM#4nS(U6tRwrwaHOX3JZL$tom#jzD zCmWCr$wp*jvI*IgY(_RGTaYcuR%C0k4cV4#N46(BkR8d-?H^*wV>}S!fgk4q-+yiX zKk%3L%sOX}2{9h{U-5wFY&yE<;ol}7`3ye%|BK(Ai}?OqR2s|t_0L^Ykk;+2)5#g+OmY@Eo18<=CFhazNo$P+&olDDKJVdr|0%Wp zpIksLBo~p3$tC1cav8at{DoXWt|V8HtI0LwT5=t^p4>ogBsYUowuJhg1}eaA53D0sgF_9ZCd*U7A}j3tNmkbB8}m4V7gWuh`uS*Wa3 zHYz)ngUU(eqHqEs=eI8}lwNtL2XQ)Q^KR5_|VRe`EV zRiY|WRj8^|HL5yQgQ`i@qH0rhsJc`=sy@|#YDhJr8dKg;YC<&yxn>|Xr&>@gsa8~L zpHi>fr%)TJE!B={PjvwO=}2{=I)l_V*y~<+?}peMU#U;wqkq47Y@fr}t5^G8&s$Hx zpx}#`zQ0dt{hnp^Jq6#kEo@o-J==*&m(|Xvg7wCDMBA+G*5CfsSI)aPiyHabym5&bgzVGdM`^ai5I`utkuz0oD=&0Ydhb%ADaDDyyr5-PO+W66PzKtL$_6@b!JAJ?p6Zav-P+)s^Z-b*Fkz zJ*i$)Z>kT~m+D9Lrv^|1sX^3WY6vxy8b%GLMo=TEQPgN^3^kS-M~$Z@P!p+1)MRQ3 zHIL_)L zI!>LSPEx0+)6^O2EOm}LPhFrcQkSU9)Nj-k>MC`Ox=!7oZc?|X+teNEE_IK(Pd%U> zQje&|)D!9{^^AH>y`WxFuc+75@6;RWE%gWWj{1{&Pko?1QV{K+oit3lXkTxAJ@#y0 zURnc;yyplU)%Iii$4!HUSiT~})bsDP7{A2$#lHvqb7SU9j9>hFz&|%;zQp*&zX$wt zW9CbYU;KN(KR0H+#Q4R(2mEtm=F7j^FaE8Mnj16T{(WO#Pe)8=MC4<4_#gHFSpF|2{11B|7`)1f(in}?1WnT5rYTL+49(IU&C>!c(h@Dx3a!!_t~K|x)I%&ZbCPuo6*hb7IaIx z72TR{L${^d(e3FDbVs@q-I?w}ccr`0-RT~5Pr4V~o9;vRrTfwS=>haWdJsLB9zqYL zhtb375%frU6g`?ALyx7$(c|d}^hA0RJ(-?DPo<~P)9D%XOnMeQo1R0@rRUM}K^qI` zh4dnNF};LdN-v|A1FL?aSI{fzRrG3l4ZW6LN3W+h&>QJZ^k#Ysy_McZ|4MJCchEaQ zFLu$p={@vbdLO-?K0qI&57CF|BlJ=F7=4^RL7${g(WmJ%^jZ2GeV)ERU!*V5m+9X? zpRdqY>1*_L`UZWIzD3`r@6dPYd-Q$!0sWAEL_emV&`;@S^mFM`}1224X>LnEd!(}ba!rc5)YIn#n^$+TixGi{i*OgpAM(*fAj5m?oU>CALtx-#7u zhDk|xXL>L_nf730dNI9$m3@GneVKktf8dh=%s^%kGng3yyfc&;#tdghFe8~!z}nHw z7+~>OVC^_&JTrlr$V>v(PG$^d3b45jJr&qJ4cI-MnZe9tW-+sY^$Ifw^k6RN!#swf z=Q9hKh0G#mF|&kO$}D4+Gruq^!un+&zrQtI$*f{lGi#W&%sOU$l$tj%8<|baW@d|z z#8ze-^DDER*}?2&b}_q|JO>wm@9x@Wv&5wow>o>WNtCHnLEr~<{opOdB8km9x;!ZC(Kjk8S|WZ z!MtQ%F|V25nK#T^<`3o_^C$D3`M`W+AlAV;S(tUPZZ?1oWP{jX7GY5qV{w*XNtR-1 zmSI_zV|i9!MOI>ER$*0EV|CVGO*R%An~lSUuyNUVYmZH*v4!Vwkg|;ZO*n}Te7X#)@&QLE!&Q5&vsxtvYpt@Y!|jG;B{lW zvpv|JY%jJq+lTGT_GA0A1K5G=Aa*c2gdNHbV~4XN*pcigb~HPN9m|em$FmdIiR>hH zGCPHx%1&davoqM4>@0RRJBOXi&SU4Z3)qG1B6cymgk8!mW0$kPuq)V=>?(FOyM|rM zu4C7;8`zEPCU!Hsh26?-V}E70vpd+G>@IdUyNBJ&?qm0}2iSw`A@(qPggwe0V~?{Z z*puuj_B4BjJ~xN z*vIS>_9^>}ea^mMU$U>**X-}?8}=>x2m6lwlYP&AU_Y`D=ir7r+H_L0mA0 za43gyI7e_KM{zXAa4g4hJST7>Cvh^Ta4M&9I%jYu7mJI{#oQgW%d)La@aEtif<&t>2;a+$cyTox`XmyOHL<=}F1xwzb19xgAJ zkIT;$;0khuxWZf!t|(WGE6$bRN^+&R(p(v?ELV;z&sE?ma+SEsTotY=SB9L2tGLzN z8g4DOj&p}wJJNo3$TwZjZQwR?o4C!~7H%uIjr*0`&h6lKa=W;BIoaxZB(v z?k;zayU#t~9&(Sk$J`U{Dff(f&b{DXa<918-0z&VWxnCwa({5|xIek~+z0L>2k{Qx z$-}&hck=;!ARojB^9Yaf7?1M=Px2H`^9;}O9MAItFY*#E^9rx>8n5#PZ}PGD*nAv5 zgpbR|-v8^LfJA82+gvd(~l2YL(^X^YQul0w5IR3-N{d zB79N47+;((!I$Jq@um4Pd|AF6U!JePTkoM(XYZDV`B1K*Kf;OYc8o%t?& zSH2tHo$tZ-l z`8E7nejUG_-@tF=H}RYKE&Nt~8~-c6o!`Ol@wfRq{9XPYf1iKA zKja_rkNGG3Q~nwMoPWW;DZ~1%!e^A)&BPL?|j06N(EZgpxujp|ns&C@Yi`$_o{Qib5r!vQR~+ zDpV7y3pIqALM@@TP)DdM)D!9p4TOe5BcZX-L})5B6PgPxgqA`pp|#LPXe+c6+6x_o zjzTA)v(QE8Ds&UN3q6FMLNB4W&`0Pi^b`6E1B8LXAYrgDL>MXz6NU>TgptB1VYDzt z7%Pku#tRdKiNYjdvM@!MDohim3p0e7!YpC7Fh`gx%oFAd3xtKjB4M$xL|7^;6P63V z2rGn@!YX04utr!btP|D?8-$I*CSkL%Mc68A^Na!XtFT?zA?y@(3A@8MdxX8hK4HIb zKsXqdKO`I$jtEDEW5V&U{0ZTtaO$tRr-d`ZS>c>;UbrA!1iVYaW#KpBif~o9CS3nZ zCj1`chF}G2>$iSUJ#!LuNmMl~{+HJB$bC-wQ}%gU3+uu+kx%vJzgy;YSq-rMhIfq= z-=}rIFZQ$;c@4aq!p{o!+K#?w7yhv&=~=D%Q!74sdi3o_Xzy6~LynUV^{IB8J7DcRE!{vRS$Cmk?>22YTa96k|+!r1Q4~0j^F<3-IRK!GFBt%lA zL|SA-R^&up6hu*!L|IfsRn$aXG(=O3CB_!xh#_KJF`gJ-Oduu{6N!n%Bw|uAR7@r& z7gLBS#Z+QyF^!m3jOdSlQr;Se&plt8PE0Rm5HpII#LQwAF{_wO%r52-bBejd++rRv zub5BFFBT9BiiO0&ViB>ZSWGM~mJmydrNq)=8L_NbPAo505G#uIm{$@ji&ey`Vl}b4 zSVOES))H%rb;P=2J+Z#nKx`;B5*v$6#HM01vANhnY$>)9TZ?VPwqiT6z1TtQD0UJ% zi(SO7UVY)-1p0RG+IHIMw`=?|4R(9s(;BXBVt28J*i-B!_7?kyeZ_uae{lfl{XlV$ zI9MDa4i$%q!^IKeNO6=nS{x&e6~~F=LHPu6qBu#MEKU)piqk-Tx;O*Snc^&Qwm3(e zE6x+=iwnes;v#V|;4cxEip#|1;xFO~aizFQTrI8<*NW@J_2LF`BPib_ZWgzQTg7eS zui|!)-y!Y<^q=tiGVgvbsmMK!j^@a@veAJ zye~cwABvB}$Kn(5srXEMF1`R-Uy859*W&Nu8}Y69hxktX^B*$ymS3j3yup(X&-0dk zJMw7ujK=h^w|kO-m;&AB3t)kId-osUs^5s`qUq`S*j|7W5v^WV>u`ni7kC_<7$a!Rn|lH5{& z6etBr!4e{&5+>miA(0X#(GnxE5-0JJAc>MB$&wJvDYg_x3X$SU@uc`t z0x6-CNJ=avk&;TGQZgyIltM}=Mct=VQfeuUlvYY7rI#{D8Kq28W+{u5Rmvu1mvTrs zrCd^ODUXy_$|vQQ3P=T|LQ-L=h*VT6CKZ=TNF}9GQfaA-R8}e{m6s|=6{Sj2WvPl( zRjMXcmug5grCL&LsZNCUeP`$b*Y^qbe=8Aty3rLmM3jli$9UjtJy2KrmhdfSGg0po zt+Sl^&Pjh?;e2i1en!2hd-1sv-@S;9Jy&(Uc1LILVm&qB*^gMM{VYK}$rEO~?BJ{a zbNF+;u*$8rtoXSj`{&y7SNzg0G@Rd=G>|N2q`siD+J^6iy{8~bpY{Ee+O z8N#ppa@N&UvijI8j9Mu2%0JdPH48gxM{MQu`S4@x&nLbTp6%`PTE9%9xnz&2)#nyc zOOS6RwU*9?tw!O`7JIZSIV?X#9-}X7_j6L$!e&-v?VhXNA3y)Y&jQ;=*3A0|R-pkW zo`Bk(IN-V#HY=?)Jfd2k$-3|4k%u7r4&3Kb-%n#OkTHw_X%p%Fg*O_wKhW`)%1DlUg&#<6ZBZy7t$~FCOpt+va@z z>e>HUYb`~z(6-)ABbG;%kEqF$_vJ#+H8963Ioe2`qmQQ#Ry%D0$4c8t?WK=lcY(ui zvmJb{WW4QL^{ra=HHas*IKDhjK8A+(fY*yZ8bzL|_T00N!q%Md1n*wL-~6>oA#m^A zUP~){kD`~eTl`UJM=+zk$A7EGoutlE7pbe%P3j(Yw6s=g^7P!=t4FlnU;iV@#N@x; z13zlqJ$ieD8-2^lo>DKVx75dH{sf4;Im0)JiqElWJT%Hy`y zQuGAxe$HO~6@vWr&pK1}jQS`zeEUD5hcP-o<$>`2|9(0D+r4L-x30!MWz)Z@tgqBh z>MsqD21bAjwD@b~TX@!g zFm~{?;E!6Z+y7G9|G-#%u&s@pev3^%rfy^#V>ti29*8{0qQ8%iti$HmTdTb-*=LQO z{886_@ISeCAK-5k{O$k4AKRkJd9+#DZELL3V`J3w?Y~_T*^mETj`!`t|006^{!UC(*J%IknfmYP-M@DWin08^?16vJ z78I4GpFZb{s@C`6gX#VU#))*@6+~Mp86JBt@=H|`<9;I{|xwB^nXd+@XzE~BjO46Dn|DAsB5@J!Ir%d zfByep3x9PS9WQzHe~I;9BM}Iw~ELj!P$`lhP^av~)%~E1i?h zOBbYz(k1D#^qX`=x+-0hu1hzho6;@mwsc3jE8UasOAn-n(j)1y^hA0pJ(HeGFQk{! zE9tfLyYxnSEBzt8lm3+6OCO|<5+plhrwq$3*)0difpU->EF*IGne@4wJ$t{dum8ka zU$zzeY$@AQ)>|9if8&1!vRn3~_MIGiFBLfrFaPs%6R-(j-P8$Kslysx#vHj zQSbp*Pbc_KE#R*ZzS_SgXJ6s|h}3dI^z=q{oBcoGe?5)d^Pj`{ulqHoe_jvxn^E4< z?}4lqzK5QubYLx!lqs2(8JU$inU@9GbEm^2A5X{NI=VB0nwo^En=WMaSwd z@85r2@^g1A?DDAm@bgFeTUw0V3%h?`o<`R3zs!jz$Cnex3FSm`VmXPNR1TGs$;ssu za!NUsoLWvJrE#S^Mmdw5Sd-;MY)n(S*{{im8;3s&f-y z2698Wk=$5rA~%(r$<5^!a!a|D+*)oUx0Tz;?d1+~M{pOTliXSEB6pR$$=&51a!*Wpd zMtPIGS>7UVmAA>i0(-X0JHqa*>sk0r{YONIondk&nv9L; zTgjv3Rq`qMl>$mZrI1osDWVhwHH#_5l@dxxfJ!N)l`=|Mr5wQJL9~7ql!{6vrLs~* zsj5^1yy{8~rKVC#sjbve>MHe=`bq<(q0&fctTa)YD$SJUN(-f>(n@Kqv{BkB?UeRP z2c@IZN$IR~QMxMKl8lJlpfX4qtPD|xD#MiF$_QnoGD;b( zj8VoaltSnKMD$A7R z$}h?aWu>x8S*@&5)++0i^~wfiqq0fatZY%XD%+G_mF>z7Wv8-B*{$qR_A2|7{mKF5 zpmIn#tQ=8}D#w)L$_eG9a!NU^oKemy=alox1?8f0Nx7{2rd(03D%X_j$_?eFa!a|b z+)?f-_mum}1LdLeNO`P0QJyN#l;_F|<)!jUd9D1eyiwjNe<<&iKb7~&2j!yzsSeet z!m3Mks{v}D8l(oRh>EJ1imQZ5s+3BrjLNE<%BzAZs*)G?Y7e!i+Dq-N_EGz){nY;I0Ck``NFA&WQHQF-)Zyv~b)-5< z9j%U0$ExGh@#+M1qB=>PtWHsI`+JI!m3c&Qa&8^VIq30(GIfNL{QhQJ1RA z)aB|g>I!wGYR%nM>S}e3x>jAMu2(mx8`VwfW_63YRo$lks%}?zs5{kN>TY$9x>wz& z?pF_}2h~IBVfBc5R6V91S5K%X)l=$e^^AH}J*S>mFQ^yQOX_9yH}#5oRlTNOS8u2{ z)m!Rq^^SU1y{Fz+AE*!2N9tqsiTYH1rao6+s4vx5>TC6P^^N*g{X>1H{;9rKKd2v7 zNONdT4c1(mTRWr%Xn|Ug7OWu}s$m+g5gMsc8m%!Jt8p5y37V)$nye|Bs%e_88QN{t z)M9C|wK!Uc7FUa>#n%#O3AIF8Vl9c5R14LTY00$|T1qXImRd`rrPb1D>9q`6MlF+; zS<9kj1#M>2vTHfCoLVj|x0XlCtL4-3YX!7|S|P2lRzxeR71N4qCA5-SDXp|tMk}k8 z18tVqDrgn8N?K*DidI#trd8K!Xf?H3T5YY4R#&U1)z=zm4YfvEW37qSRBNU+*IH;T zwN_edt&P?ewAoH;uXWHmYMr#sS{JRW)=lfK_0W21y|mt1AFZ#}PwTG@&<1LQw87dC zZKyU3v^iWGp^el=X`{6<+E{IzHeQ>cP1Gi7leH<@RBf6zU7MlJ)Mjb3wK>{cZJst? zTc9n}7HNyMCE8NZ<}z)$_KUVcTdA$mR%>gtwc0vuy|zKysBO|VYg@Ff+BWT1ZM(KZ z+o|o+c58b;n|rl=+J5bTc2GN{9oCL$)?7NO9n+3$C$y8=Debg&MmwvW)4n$^djHRS ztF(PB^R0Tmq`uvjogM&Bm_;2trS|hZ{-2ez#>DgUw*R?*xa=DL)bzY|LA$73(k^Si zX;-wX+BNOER>^TgyQ$sMZfke6yV^bNzV<+Ss6EmiYfrSN+B5CB_CkB9z0zKX&C-8r z&tmNQ5)at_Rd`b0^%BFEcypFkZ_YxVyf61lT8@$VCwRc${f+O#^YkwKObP$|oF(D^ z`Cd=mN)G?e1ba$jXp9Gbya&EzTd?+wpZk4_{!i7lx4TbmUl4eMJm&ZB_CWYK;Jsh% zLEe0LIXm}bzJC$DZxX~vdpuyx!|>mLuyXbtDo^_T=j!j;8||(3hxShUQ+uy{&^~IA z?$Dh&th;o#9-s&6L3*%`=%|kAxK8M#PU*DH=&a7^ye{aXF6pwa=&G*ix^C#E9!rm{ z$I(OdxOzN2zMeo&s3+1B>q+#adZ?aEPp+rXQ|hVo)Os2{t)5O#uV>IR>X~$Ve`TfD zT!;Q%2k4+Hank{CmLue$3BJ_qsgo&H5{?=d*IXe>?xbxIfM>why9e z;s2}0G3|OikXg^7XVtUm5R_fdq36_d>ACehdR{%Bo?kDZ7t{;sh4mtOQN5U6TrZ)Q z)Jy55^)h-{y_{ZNub@{1^{o2fJOe}s$_c2y`rwYwU-coVG>|D9CT&|`)%W~7^&u!P z;CR}HAgg_=z9mr-P`iG4fFrl>u^)oM+aJDtkNx026VPDyzmo3lztw*D`jPwpm%$*3 z?7!&M_iFkPs4!IclWL1YoUs^mrd~_0t=G}(>eiRGJhkiT_4NjNL%osSSZ|^?)tl+f^%i+v)A~4thtulipeHqIcE1>D~1ndQZKV-dpdZ7l-=l{q+9&0DYi7NFS^Z z(TD28^x^sleWX50AFYqk$Lizs@%jXPqCQEVtWVLW>eKY;`V4)hK1-ji&(Y`V^Yr=p z0)3&rNMEck(U-6>d27RNxN#Cq*(YNZ`^k4PuplvJc z(0A&)^xgU%eXqVx->)Cg59){X!}<~ZsD4a8uAk6P>ZkP6`WgMKeojBHU(he=_FaNY z0A1EE`3bhfr_$p7-2Fp&zvpK^oRN* z{jvT;f2u#zpX)F5m-;LHwf?*QMt`gSp}*7r)ZgnL^p84ZI1Hx&8!p3b1Q>xvkP&Pk z25MjiZrH6625C?RZ7>FFa0YJ(f0uY9L_>y^wcDJCsaGN@`5!AmzRJDE%-x`DHjl<8e z>wlpYYhL{S_A}y>px(J{+ZBBay*i>s_O=kUgufEYCVzYn?^9(_*ZTh|vHkncPb1Ee z@16fAdBArz*z?I_pH<>P-ebDA#J8RYTV)lNBim(< zWO)01N7NVFQuaKs^AXd??RYr0TvX*hif^}Tr~cZp%dFI2`M2a+DQ0 zGHM%jjJifWqrTC=XlOJt8XHZFrbaWPxzWOCX|yt08*M;nYqT@k8};Z8Mn|KQ(b?!? zbTzse-Hp^t52L5i%jj+NG5Q+)jQ+*|W1um}7;FqNh8n|+;l>DKq%q1EZHzHe&|{5p z#&{4W7!yI5WK1@u7*maD#&lzbG1Hi3%r@p2bB%dM8fLz+z*uN3GTJkXjKxMeW{I)X zSY|9Y(lb2$i?PC3X{<6<8*7ZU#yVrYvBB7AY%(?*Ta2y7Hse=gyRpOAY3wp~8yT2A z#$IEevEMjg95ga9hm6C<5#y+F%s6hGFisjN>F&%aa{v?DjAMqFam{#Ud^3UBkWOeOG83Cg%%orgYvyfTXEMgWli& zRyC`cC7J4G4YQ_M%dBnIG3%Q3%=%^nv!U6@Y-~0$o0`qc2}X0Xh1t?_MG0V+g%oXNJbCtQ;Tw|^^*O}|h4dzC3lR2H)Y;G~Pn%m4@&F$t6 zbEmn>+->eL_nQ06{pJDlpn1qVY#uR>n#auJ<_YtpdCEL(o-xmw=gjlwTxKqF!Mtc* zGB2CInODrK<~8%WdBdE?+%#{Qx6M1|UGtuK-+W*`G#{Cd%_rtl^O^bFd||#cUzxAX z=|6aN&qE<5iy7}Qn?ooHB2hh2U3VZf2pS9x z`8z)p8U_sy%Z-3WLZbj04UK`uLgS$E&;)2AGzppvO@XFD)BdjU?OQ;M2HOME|DHWI zCt^ASn)z87Z=G4ukoDHG(Coj*H{zU{1I>lz`ILsQ7gcV)PmPEgWAZT`i19#-2Vy)B zEVK#T`sJn&ESzyfGt%zwN8!ybt4 z-NP99|B?q5Mf>jYf2sE|eOVOsjeXB8{g&Xyee19r>ekKl4v=+QJQfH+a4g6LTMu@` zf*kN>kV^ok1dn>;iIpadS|t|F2|@5xKppTkK%MY)Kwph56WKoR&BbQ?S(kpR8} zIl0CmFm0S$s5fX5Xe_#vPU_z|E^_%WbC@Du1MczgkdpIIv`z|R47z%KxG z!Y=`Z;a7kL!LOk=;GqTxeha7r{sT}a{0`6{_)qYVg9CmKeE|Jy4IXfS;F=&`6O`8k zwQB;2n!vi+z_PlatS%_43(D#OenXIN2=Wa=s&p8}50nG^oz%W1o040Ro040QT1F1kqZ9sE_dcgoW0SbgsfC2%+ zU>qO}&I2Opr~@eN$P09_j=F&61-f{E0ssnxMSubUN(jpUB?JhARe&%!KhUZ>>I0e| z$eI8J02Bzv1}G4q1aJsI3E%=iBA%lGpa~oWLBA3?8Uk7nw3GxO7eE1UC_n)KC4`d$ zln|gm;Fmy<7J^a(P9u;y;k1rMfEETi(>odiS_JeklcNcsML;eKKo$>!vjKzwv<}Jv z&^joWqZp9M<7ftGF(8ub3ZZaGfKa%! zqZFuJ*3k;kQlNHufD!50676l09OYn0YDgB6CeyO19G(; zZ2&C;a&-a1;QEfTz#|PEZ2>I{+HVYy3!nhFDL?@LA#ihm5P(p)B|s=Z3E|cNC4|d^ zmfAYn16mQp_KuEWC8(HogAG2tpt481)xBHFt{5)z+z`_M_)%7=Kx1JXL;uk z$7M%FXJzLoM-69fXG3QL=R`+yXDer0XK_e{X96Fn@NCCiM-S%$M{nm+#{g$p!1)DO zpu&TkgPp4#YaOGU8ys64d7!S2J%DxtGpn1U2pGBjfHne;`ZNMtTOsHW7>!2Yai2zD z+r{7`V8&u#oH6(q7-tN49D`4Q)-cdR3_b<)WAG*5jWdov0lftJatyMV+M$4x-vJ6-TKM*=|ifZPqoZ9s21@&oBRU`}FS4q@;;Fo&%662cEadkNwD z4j25$@c__u4h((*dV|4@fJ7eP#}}YKoxsCOouK@n?N>mD10L(x26_Va3t$dG@NU3) z=ePyv9uVJy7J;Q8essJ6G$%yD4rfh3b3!x>14M%@iG8b~XgG zAjqKr(ZE6y#+}Up1uHngBtSHncO*)3pxusi#m%t>p43* zJ3D(iV}ZFG3)GGUW^ydx@mOHK#{zSCEO>g*0kd!rpc~+paBFyjvpp!u3ulI2zzcx? zMuL(h@H%KLNSDIn0bK@91avt(9neGYTtE-Q3jsX>9{_Yin64G@N_Z8#8eRjhh1bFB z;f?SncniE0-Uj~)Z-;lnyWrjM9(XUj58e;71%aA#0X+z>02Ot1UxRPJx8OVQJ@^6q2z~w9oz!_bcT$x>2Tv=V&T-jYYTsd92T)AC&TzOsj zT=`uETm@Z)T!mdlTt!{QT*X1105~nsnijN{8njUkq?tgP0q}BzvYM{iuDY)Ju7g?+3>h9|48tfYC8txkD8toeE8tmHz?AU*>A2!ca^^b_DM7eGPqGk`1}3cmmd zg%g0>E8xQ*_;*(lK;HsC2Ep%K?_D2V4ma#}gSC!>-KZOPlWyA0x_P(gmffmbcbo3m z?hto8cLH}JcM^A~JGr~2yOz7QyN;JBTMhOck5t z!COH*8$2_3bMPz>mxGuJ$%146Q22BbT%0|4j4v*Gzc%!il9&*KL`Jc?fmORwNXiB!a4VkNPd zm&PM?mISdJh?POiL9QWNlC3~&L#`xyfY_5<1=3X@Z3)s*KxPVvGeMjO z;$jd-fI9K0WE2$Y2z7>n$q?!e4G0Yk4GIkoMMBX~EEEqVLdj4nln!M=*-$Q&4;4bi zP$^UnRYKKJEmRLRLe0=vp|L~bgocF14UHF?AT%`e67`gQ#y)3XurJwHtQ&mKHW0*M z5K$0u5NQxIftUrvY#?R_F&Bu1=N+StQzxjC)G6vTb%r`ioukfE7pRNWW$HKT3U!sb zMqQ_FP&cVt)NSexb(gwF-KQQ<52;7gW9kX@lzK)zr(RGmsaMo%>UZi5^_KdBdQW|z zK2kZMJ>Ws&JWyU}7&s0_e1JEOvjkKMJic2NJi1%LS<>m$t2nJMv*_RpETx=fozh;|`#CfCOsP0W=SgzyS&YC?!k+loFr>Fbz-wfI?vwpir1` zKrnBxfHDpTECS>JN3Bp;HtGVJ7fJ!E0HuHvIs;(cNCap;pxrd;0h%8irD7ZP0WAP> zAw~m03xF2m0TcpI5S##@Ab`M85FqQ^H5r@)pk&~9oB|Ft8UlJ0*qz*X0%&0nQyPuK zPzanFpb)@I38w`pB{=^KfzumJ08MAO;EdocXBXh5gfj!4RT>Is1t=6Q3hHM!ngUuB z*pm~WK!8Hv+yI4uvs7?YHktui4CL|yWbsnM1p!J4P$*m&pipp>2K9|sfSv|DC=O5% zTm*Qjq)`;mBEU&hh{Sf^&#KxT4W2428gz0SbXD0c)!ol>sdU z+NlnBDZ$x9AY9XE4QOc~Q5zs2=Lm%B8kGU90b+flCZM$paP|(~vJM1i9f5FTqYa>C zfNWEMLI6q$HwP#sK%sC;fI`6;OI*0M(H79Mz{70;N&!$P+#aA%xB;-cqtOu1Mvfr3 zv(XsPa^T#dtI-b7azJNyfI`5TFa-BB+5=i1^shHS4uFE-z5sz^DzKtIK%mz^b|63@ za0QSXY;*v$0+1LAP!Kqy3516m9RaNb&ZI{godB%_WJd!8`U~tH3s6e90f=pYe0y*< z(-Fj)&{k)6(EFS~Y9`nULI4VeX9E-r?*Nv}HLe4?16Vg7APAsfcp*SmDGV}E zPIxJJFWd<`L2s8E;35wo2wnjY1W+)%3ZP(sV0aBcR*e979jIYlt%blFz}yc3C>Y)Z zP%uC+yagZ_J^ z+w$>dKKg59KKk1%^G225DQ~mPTVxWMkNyssn5x%*L8jMVVVQS17hR{{z`eRxWh3PV z?o|PqMCPL}BJ&~B>%Su7zRA_}kI1UAFI3Zi&AuQqAN{vvKKeb(|9zFclzW)}37JIZ zqyLFaOx5duA=8sp)Bj3VjV&wbpRr{nvTFK2$V8ow{x32gGQIu#;6T^sMye74fFQkR+Uz+JU&TeOBa#?R6m-R;SFujR9Okc|X5bY1q z+Lu;l_|n3RrPTZSFJ+3E^WQnHaSptsw~)*F3goi>UH>DrIYNs7rdSa`trY<**^1>% z5Aa`33#)%krdQ<*c}ZW5T-FDY%lZ$=!}Qh3!}K-$^J$+?Ya6ZXu+hQ}8&mCA$#k3l zN?O=Ci(b+Pb0)o{uTL)PL&#;lgFH;%fILj!(Ek+ePtiJ*R;>_9i&j`qeW?F>rnKS= zdr2S0S@x2?H95zAa*o~p=V)_|7ST)*ImaxrXr_s4GS@g(aVz3l7}vshypNhNlZyb64R2A#MESLXL^$Vc3LEJw!WlK;f#Gr-h{mt@rX+GU)eFO3X1$Ka`Aqkl3@OF#ZY* z)927Whh-h1{s?pJChjI4VOgItO~ia2Pm(^{e};Y-j|YkNGxfvC!u6-v)~DFUr`Wb^ z4;c81Pi)!JlnaPqTo=viJ|<4xl& zV_V+;=`JnSZ_t~oig$e*df)YJ%zB7xcJFC_Z35~`!Cb5Ft#f#Dha}z?7N_=!QnYQr z+KN)-jl5GEd21SR4@8Zq&$32H5zE6NMo#Ht>diYtrM*O^TXH?(g>-)7w>MCL@|977g36Qiq*!N)Rz`m z8|fEe39jQdZbDzRk-jv_pc+0zovLpxK~>*eno-{x;b@QMQX_pbu@jn+w?Ha+8nQ7A zBQO%9F$R+`8PhNwo3IVr;lfyq!$K^=ejLC-971WEkF9tciTCV-A-0it=U!|Ru`R^* z6n)>AsW$c>J9|(~a#7azmLcBK;Vm0@%ZA>vk+*D2srSxj`!^HID6SLBDbB>QiZiji z;!G^FI1|e)&cw2dGqL>Q?9FY6HLS%N2C;rYtX&ZIB#3(w#61b(o&<4Eg19F^w6S?h z(N^4VQHu8BzKc@KBksQ_#eAX}8>)@e#%dF_soG3!uC`EHs-bEt zHB4=-wo${?wrV@Iy&9oLsvXphY9}>H?W{(tF>0(Dr^c&Y)UIkbwY!?2_E3AOz0}@n zA2m@;Rx@?ulySO#>Hu}1I!qm*w$z2{CaROwsp@ofraD`ltIk&!s*Ba7>T-3Zx>{YU zu2(mzo7JtVrfyeV>MnJUx=%fz9#W5}`RZ}?qSgsa^_qG^y`|n! zzfkY0_tXNlNc~EEr2eS>tUgnd>wcEGe!Ub`Gpa#U%cz8?sZn#HHbfnZY8jIjlNmE9 zW?76Y=0VIKoFltB_C@Twah2j4#kGp-71uv*QrzLV3vrL)zThW@o^;nGyp`~7LXCuB z3DG_CdOq)2zE{;=jd~64HMG~g-e33rwfF1Z*?mU$nb7C=KCk_{J;tWLk4DM z)y{5^-88#pcDw9^?4H>>v!@K3IqZJUH#rrD`wy=<+%|mn@I}K%j2Jg!_lQ#?ejage ziK);ADX{#LBzsO7hYL-W8ui9c}xA49bT5d?7L+#%lj-(S>Av7<>fyuf3{p+ zv2De@6-6tStz5Zs=gMuX+^dRKeYm>b>fqJQR`*!_^_t=9Cal}K?)bX1>poj|W8I5& z|Ew#w-m*Smebe=k>tol?UB71ihV}2*+Qfy&b+E0pbwX#vAP!y74GHLp-bh3;Qjv~+ z7~-|cmQBpIt+EX#4kwNxjv|gBjv=-s21vpx+gkD&wplh8aToSr9}eIUjvyb$aT2F+ z2A|+lT);K2RkoYNn=Jnh@ea{VbQA9p?-8BEU+@&a;y3(*11v={%jO+soq4BumsxK% zn2qMW=6&Y<<^$$~=0oO6W|O%Tzv*B#`|y*`Wz1#GZ=1`R%bR`8X7fAdWOItSuQ}D6 zW==O}nERRgn+KRP%>&JY%!AEC%vt84=4|sYbB=kqImukX{I2=D`GWb1`KtMr`3v)1 zv!A)ZTx3?vRm=hAs^)6u8s=K&I%d^e*BoT7XAU+uFo&AknLC<)HUDPrX6|lIFi$a0 zHP0|FG%qqQF|RXkH2Xx|>-tty-Ka8A!NWg@lA~%R*t*r^N2Hp1)|7NCtvr_+NKL2KA{>{q% zo0a=FEB|li`)_9cHxvC`yar|I-&*{EkW$ zbrm&By!oIQk?XyArZ?~H&0EEZ`qCMq%*+yH$Usrn^w!*1D02U9qWn5dl(qYb(#Jcs zMXt!-ju&NawkS8w5oK?0{lQp~Kl0wnSZ|y3p5B@fqLe#}^1QcwymuW2dFL{F>wlOi zraq(W++}Q^`D3EJuO@?eE)Dix#4E!Ph*yOT&=8H#nCD{~#PhQF4uQCYz~SAVVoQo` zD7K#1ZeojxZ6&sn*gj&*h;1UahS&~b3m7C(d&Df!^Lj~ai8AcrWr$0n2F2*3dPmjn z=abPQ_wD%H?2U7J=N^o8=QbSPe?je-thnz68dsP*uZ-!N`AzRWzr;EhpG+-Y>xv(VXoyB=%zY6*icvZv81)eX z2O6Lu8lf@7s})g-wxZukXSCpw7UC-E8OGuCo9aW~6< zMax~buf5at(r#||Gy*}=(6XgZ(I_2BWvkflN zUfjwhdi|<*4X&}2PgsWN&*Ii1`-CN3C;sSN{%!g+-@ER&y|;Lqb-3l7B6?o*ljzMm zw$03Ofn|M8%@LbMi#tpez3yhdQ%rrr7CMQ`Y;iZ&J|P!<|0UCo+U`=GVo3$8lUVQj zw79@t@r?WXjN7>9U4kf|(W=mU|9@g@Y@uBtw|R~73Abcm+B4SRTW`A}YQ&Z+qGt?} zD8)T{!d|wMrHE4Wh{%e!&tu|6_CL|)8}7N7_Jg;to-ptC)ZS*AUV1|LIoE!q-wo1_ zw7X#2Pg%TWZBl-g9l@xN5IE2P4bcdVAs$nr6m7+0N|d6#c+`qg%p?8+5T%$;`~@IN zF|YUwK$OL|Bjy!HC{c=e`|(36$$ZNonZJy?@b^J7kJBMMO0)PYA(bCW5%zn_1N=SO zMH<$}H>Ga+ocJ0EeKX6YA0Mda$Xq_LQs)-ASu9~NPUu@PPb+?Cr4>Kd62{-*VSIxj zjO8WseGEPI#aR}AnGePZJ}o(+&tRSmre*Ls(P*M5J9$g-$B7HcXp zk^DMSHQAic-uY_EJ%b`NUo-N-?k4OGR0H zJ7Qk3mx@x%E1q#hDdrW=x}p^Gif3N2PGVm1?E7_E20b!RYUOP040pD3MmRe;J3C{X zan3HzZq5W}PiJpuqBGgq*O}(baQ1g*ItMu?Iww1)I;T5lI%hlQI_EnVIu|>aI+r_F zI#)ZZX&-7ev|3snt*%y2tFJkAE=AA?=8kuN~J;YNxa_+F5OhHcz>rUD9r7Uubu=Keg&|LszV8 zu5N>6qh*t2vt^5AtHo*2EZZ#GEjuhO%TCKK%Wlga%U;Vq%YMrN%R$Q_%VEnA%TY_d z<(TET<%H#=vs|@Yvs|~_u-vrV zvfQ@Zv3zd%!s52vwR~y0XSr`FuoPN~EDtPSSsq#*Ssq)ywtQpx*7BX@d&>`&Czc;A zKUsdZ{9a793+24*ZP3tx7m$|{qhphg4?VM2)ayN{-IN7lH^I1jR4T(u($LFPFUmErCoWGX2 zyQlQB4ES=kKb==vwKHcS!5mR=|I+i(O;OmsHCvE7PHhgzf|Coz06Z?HT zcF3fgv#u@tBQ`Al$3ExMUJt3AyKCuyRm<01UH57F$jp@aIeixJ#nn}*)rLe2otbkf z_xEu_@~Y4Oc}lefk&EAt-5h%|{zBHrGcNY|BXLaM-I*=M4j=Y7>P6RMz5SB*59^<^ zYC_w*kVStkYrnkWirJla=N?>mblF!))1tnN{<&w%UMthC4hp`zu&ZFwPMT1r}eU=M`dj5 z_w_(i&cork6RyqpYR1E5E#r<2R^qP@U6J$m)XmGfty#ZrdB){I-%Sh{vuNz;?3G#F zXP=I0Fu6%=saR*9TPdH9o!Ya?po8g6=XY9mt50am=`KCG=cE_L)E;(eM6=vJxoNrc zbGt78XzV-Fp3iEu;GYG*ta!De=E{R>3l|(&w!8DU(Vb#0#y*aXiCf#n)U{vN(C*v1 zr}kQs)Gv8n@^8tV(;lWROrP3s#Nzbo9j0 zr^on=Z#6!fudDntF?Uk8DZVq8&6H<1o_%Xh>A8pJKU(Hl-gL$Aq-gigg%u}Nk2)07 zFD9>ZcuZc*`Pjc>yL4IEGwuz(Jh)1hHqw#3Cwpj)X?RnH6Zao+Z^Z8-B1eXfyfSLv=rLn^j%zU? zcJeQibEmhOIc?^tS(j)1G;7xEM)R{5tXw!^(b#48mY3njlq21d_aohH?ss(GDO%gK zVrb*gcy~l$H~01XiSAp4t=G?6pUw}LrE}Cy=a}{;6Zr%=ha+{4l*2c6a`;Y84&Ub) z@687p?-~ype={C2J~ZAo-ZS1e78t)X{$Tvxcm^LEBVL}t$HwclxNba(6TCNmf_KMH z@c#G-<~d=!gU{i{U3`gqxQ{|Sz*l&L$M^={;yZkgA8^N*&vH*O-znOh;&$#EhnmKi z#+&j?qfHY`xuz{9r)i35vT2%Wx@oRyj%l80hG~Uqp=rBmkLiGEpXr$Cxalex zj!08YuGi#xO;ZrU5rIfkZR%@NUz_^c)YqoIHuZI=ufz2^T(84*l{PBZMOl{^L<}Me zBCk(gpS(WT>T}&e?jSaxz5#gy>KkyqA$db$BQ$1OV`39x6Jjf3E2g)iZ7c8f2x6ou zjJhzchp`@ETyM=iZ%y0Q)VHQ>Yf~G9BLb0JQ&AT|2uB1W$%@xrta-Ti5B?NCd4Mh`o#Lg z5Ml_iE>YZnl_>fmh$#BPL39us5E~Ffm>NRM5T=H(w)Npa1Jp2eU`@rA5c^#5o+om# zO~l?OYQ#P!O0kEDTIl%ig2S+VyO?|xrPwRQ5=2>?i=Gg-EcVXgQuK$&MJf76tclo9#a=1q6{XnI#BGUE?1f_a zVqX+{qi8AiMKS%&qe#plT8i}+_2L%a+-K2V)C94;L=>giGetX5iak`c7p2IH_hYeE zVtL}REw+p3=i*X4qKj+9HWPg->P3686tP9cGDR->Q?wC%D0)nkqOXb{SE3Z{iysGK zK9P$WajW97DoU}2q7Owb9+}0DF|qDq9YmjqM{Dst6fH%Mh$VCwVkZEck7Xfw&K?LWRqpI=bBz>Oer1>dZ|5i;$DbW5hk;@ zbp(&uH_Ht8w{5_`ZA(dFD+YK=(M~MK&M{WxswCTVwkF=sblt{gVL*idOF*JD zhM$qFV0+i*Yct#4vX!xwwY_aCXDe^($&Yll2&l%7uhy38^3$U&_}R`t=|d@$&xkwl znC##^j)joF7=(VODfDfXgv^pe;zRZ$HeqK2ueRD;i&TY17f ztvzi#;hwghcAoa02v4M^gQugXlPAj4*%R%F@x*%KJn^0`p01v5p6;FmPY+KYenNA+ zG_}^WS}%G3W3z25?{#dqJ>q?!Z+V|UygRXy_smo6c6+eBzCFb5us5(bv^TOhwl}di zwKuajx3{pjw1?VT*~9Fu?QQJg_O|wR_V)G&d!)UCy`#O8J<8tM9&L}Y$J*oU@%AqE zuJ&&B?)C(G4|`90FMDr$AA6!b$)0RavG=ua;>Q(tN_+Sb#jVoz0NsZRtP8D+tc$H1 zKD_*)?5=rVcGp5})Pah+2tqyBU`H_OBLogKKtnV_V>CfiG(&T=Kud(86~fROZ4i#O zXovQQKqNY#BRU}po#Dn^e2IIwj{+2;2oLZT9^w%m<7<3_Z}A{5*p3}=VJCKB zH}+sJ_Tc~y;t&qw2#z8j$8n-L+M>MYmAtuIr=Qu1nRW=vM32=rVLu zbUSn|T|>8_Xr4BhXe^pXX(}3_8>t&jR=Q}sZkx`j%W!GBq3V3yM%^ae3f*b>jQp|O z(EV0XLwA)Tz5Dciz55J4##wxVbNCeJaRC=`372sNpW!O5;W}>MCT`(2?%;EL0XOdA zOWebK6rd1Ac!00)5RdQ}U*j8mi|_C~e!vs_h@bE?e!)}xir?-V+$(Vmt4re6l4vh5 zxN9J|B(^IuxLZKPZbe3S{(U3!7010L@g(tRfst)Sy*HZZD-(TXqOVN!m5IJG(N`w= z%0yq8=qnR_WumW4^p%OeGSOEi`pQIKndmDMePyDrO!SqBzB18QCi==mUzzAD6Mbc( zuT1oniM}$?S0?((L|>WQjslb0R#4fUR9M-aj1=@mD$^P3_vCZVh{#n2(mB~ z*%*c#495tJ#3Cmmk$wr^!CJ<55?AV1=~wI5=-2Ak@y(@;`rq|i^iI8| z-=;5BRaf;7{SEz7{T=-uY5_ z-%I6PFO~PaRNnDY`HZTS_xlrJ-man2W16Yob;|u{Cs#fzJb-AcM;>r z2K_`JdOhiAtg?$T*t1)G}juC0R2CrXra zyyeWEBG1nfWn79VzZfCPf>=>@OMBP0Jn@&f=24BJT1ADjKO}WN-dPttI(lXFwdi#r zt=vrt<6}}|M#i*q`xWGeWDq+PERWd|b0unLOsc!6Kp$Ha(loYh?8w-69mY6QTtr-t zxM6YQ;wHp}xz)m~tV?l4WPOXC#Qhp)ieDGsD87AszxYk@f5!WEiR;q0%akszE(f}N z+~vJ)?{|yon$z{??pM40-tFz~v%3X%w|C#!J)C3RZ{7duZc3<{kdhGY-c}gy{-N;4 zgvvc?^l&Gn_xQQNs|KZew&>Z`eWBoNPj}B}WEG1%Jx#sh5+^oH>UFx;++OY6j|*D& zZs-1{U~uou-eY@z)%#)ZdX4_+U9(T~KK=WoG-~gjTrjrL-aZHV9PZQ4y{M?Y+g>D3 zs+xGdQAhXD!tU-b3sMp@6CX8NmH1iW7l|(tCnhy%?AJKLeY@~{Qv2kN$)l6^CvQpK zlU$hWn^HNYcgnt$+bPj~Bi&_-n)iK`(y#C2zK^-~Yf;tIbA7k>4QkRqb$sgD)RCzJ zn+#0r=zi<|qqOJg5$PW^E#35SlSMI0W2B5V>AUjowzg*U$%xD7=ssH%(e&?(sTr~T zI=KhkpV!a7Uxof*{Wtgjq5rl4o!pxX?+vKf%$gbH*6zn=Mm5XMT%UQIYjX?Rxyuwp zx&JPV8ra!=;{K_DpAF0y_}-uvgZd8|HE8Of&h9D&A%p4-9z3{y^Yeo{yKfY}7&LfD zXLp~X&hB|dpAKo9RXJ-}^T@1mStGM{Wwqk?5I!`TBk3ASS5eLE=B7A1r9?+j zth>Vf(ZgmB+u364u%j*7<@Cy#nsX_qa?8NsalA@uLAmIDdtMj#j)-$_EQ)g$Qp; z-Fb9Z_t=82Zmsa=(Ymm%tk0)oE{>@Y*3F%F|K`{YVc(5?#P7Fvb5ASkJ5FwWew=Q6 z`1p|4-Q6|Wn(Yb`$nF-7p3t4=x1|&Qo{+$ENdm{gq`U-PnPla4bSDturpPd9-Tcfp3n$Hg*nN`@OgcH~n@K&~&5D%CeJAgl zTy65n$=^FZZRQ)Tuq)YEkd-+MaK_VOFAh+kMxZGjl4>9XU7AU9Tw2ZMc7V?uofi=Z5jjcza&5 z`({D1`=^2>3w~W-UYP6-DyqD&(V{OFxfhLH^kVV5OH$l_7tLO}G~&q8zV49)-$a~U zw!e3^<*DxQf>d{F*lh#!^ zEuE1*md;9_Nav*s(naZ#bXmG0eI{L%u1VLW8`4ebmULUXBYiHprMuFX(mm%gW_sU-=!mg8ZIbQLZHW$yMY4xvCr}*OY6^svIN-%OP?Dxslvh zZYnpITgt8E)^fPqPL7Zx<&JWc94*Jn@p4zWyWB(WCHIk&kax;^FS6x?A zS6ip*f^;@rur5UB&^6FC(lypK)s0stsI7Eub?tSLx{kUi-4JzO|LAO)4OSfCMN4HnEPq$xpKzC4gNOxFwM0ZqoT6aeG zK=+mIq3)6Hu`WxWtskKut^Y^=TJO>C(7QOB_m=*){+iyc|59J5f1rP;f2{vT|DFB^ z{g3*e^)K`j^ndC9*1zH`RkPt8&fl%TIjZj&-skMo4>)JHvcb=w7^)cj4FLwLp(V~{b)Xg3BM>l;Ii z4r2pjLt`UjV`CFzQ)4q@b7Ko*OJk_9l`+iN+StYzZft98XKZhbFh&|X7&{s}8KaDy zjnT#!W2`aG7;o%i>}s5DoMBwxx6p5q-(tTdetc2TZ@J$Jzm zQ(evt4sse3{WT-?hNC(6z|5*tNv9)V0jD+_l2B(zVL9+O@{D*0s*H z-nGHC(Y497*|o*B)#Y?)u5GUEt{pCyYo}|MYqx8UYp-jcYrpG&>!9n9>#*yH>!>T= zb$&BHi+m6Xa#6~$i(P^?N-rJ53`R99*!HI-UQZKaN)Ds`10rJiC_ z>`JgwUkOnhN&}^#(nx8nG*Ox=&6MU!3#FwJs8mDD?^klWvG&^3{!FxKGIP}Dx;Kf+Gu60(pMd?Oi=QaiOM8pvNA=Prc766 zC^MB=%4}thGFSOjo3AWT7AcFBCCXA|nX+72p{!I^DXWz=%35WevR>JsY*aQWo0Tof zR>i4k$~I-YvO{qxJC$9^Ze@?MSJ|iRR}Lr#l|#y5<%n`r$ybgk$CVSxN#!Hu6k`_Y zsu-%6s+6wsR+X|<%2n~L@=lcsRo<&ou}USz!L7mwxK$bZwmPHU)@H=pAV#|lW}Mpw zjB(q9acx^Lo^2T8*tTU1+epT*jbiND*edaiSlgYkYI`wCZ4x8YrZPHhKSrh<$f&eg zj7XcqShS-Ug?20>(B?7r>=eeGoxzy1a~N-S0b|WB@s2Vp#+Y5@9bdLc664EmVr*F_ zqss26vXhZy_cDU)K}L@~%E+-N7&Z1ZBgTGG*!zqH z`+!kkA2R~%cZ~k}Bjdh4Wz5SnKuKnzOfJ8Cf-+kyX3;CvpbX{~SkkhVHN`{m*Es#bc@d_eiOG{?ACNVwBYV{wEkURg9T>fbmhUFg~gn9rdht z{L`C^hbqQG6{DPraZevJ&Z!vn^f&)kjBxs=|6h!BIy7KHz=D8<0gD0_2P_F#8n7&2 zdBBQ*l>w^)RtKyJ&{<1a-?EmmmbJcZEoUun^|hLL&|1@~ zTI*WtS#4IkwZ1jP+SuC6+T7a0+R_?sZEJ03ZEuaR23wP?$<`EWUu&v0&6;k_u=ca| zw+^soS_fJOSqEE(SSMQ#2ObGL8kiq=Ebw^XiNKSA9|fKYJRNu@@Z-R4-ZPIrBxsGEwzkVR()G7r#9L& zJvB*fqHCecQ2VQyYPOoA4p&F2qtsk=v^qu|tBzCi)Jf_Tb(%Uuou$rE=cxK4_hZc}%tJJsFlUUk2EP(7?3RgbAB)Q{BD>c{FQ>Zj@j^^$r; zy{cYUZ>qP|&sDejrFvg2R3E4h)yL`+^(XZ=b%XCl-%Y-oeYf~-^>zAczT14a`|j{{ z`R?@H<-6N=kMCaJeZKpB5BMJRJ>+}X_lWON-+bR=zQ=t}_@4Cr$oG`*Y2P!xAN!v5 z{lxd2?|I+Pd_$dK&Nj}r&i2lZ&M0TJGu9dJ?CR|9?BVR??Bh&wrZ`ib>CS%60nUNW zJm)0m6z4SO4CgH89Opde0_P&<66Z4K3g;^48s}PPRV`4fuGQ3PYpNEc*)+Qrtc7R| zv_@JJt(n$B3)RB3Hdt{$#luHLRbu0&UoE7_Ie>g!5%rMddKq?htb-AjIy80gmg_rNXeDCG^FRh-co@$;z&xfAso*JH-o?4#To;n`YQ`ZyZspqkI?4DpxeNTwT z;c4J$=xO9>>}leW-4gFB%g})z7vk?1*=>XgrBE6^cnf7v7H^{*%EK3CyaNj=;9b0j z_fZiapb{#>4+^Tl9|5qUDykt6AEG*HU@!JzKMvp^4&gA4;3)EO499T-C-D(Z;WWjASvM~%f7>*GbiBZVKXpF@;jK>7z zVIn4BGNxcEreQi}U?yf^4(4JW=3@aCViA^LDe{U~4yIr#reg+XVism&4(4JW=3@aC zVi6W&36^3RmSY80Vii_n4c1~E)?))UViPuF3%0@u4co9CJK(}j?80vB!Cvgg0UX33 z9L5nGMLv%4-hUqNn@_|fOvV&U#WYOE49vtV%*Gtd#XQW%0xZNLEXEQn#WF0%3arE` zti~Fw#X79V25iJ8Y{nLBg%cXKVLNufg`L=i-PnV@*oXbRH@*QIu?d^81zX{ShHco6 z9dKbMc40U6U@!JTEb9Oc;t&qw2#z8j$8a1ca1tNk)cwltP~IDFg)p>68-$}R+Mzun z5Qz@xh)#$?XG9|gv4}%Fx}Yn%p*s@L13l3Tz0n7Wg$|A}4vsMnjxi37F%FI~4vsMn zjxi37F%FI~4vsMnjxi37F%FI~4vsMnjxi37F%FI~4vsMnjxi37F%FI~4vsMnjxi37 zF%FI~4vsMnjxi37F%FI~4vsMnjxi37F%FI~4vsMnjxi37F%FI~4vsMnjxi37F%CY5 zbnrQ(gU=xyd=Ba0b4UlDLpt~z(!uAD4nBu;@HwP|&mkRr4(Z@?NC%%oI(Uc4!RL?; zK8JMhIi!QnAsu`U>ELrn2cJVa_#D!~=a3FQhjj2cq=U~P9efVy;2k&zpF=wM9Ma)# zhxUj-Bs!oYIw1<35setcA`bEBif-tR1oS{p^g?g+K_Zfnj1=@mD$^P3_vCZ zVh{#n2(mB~*%*c#495tJ#3cFP2#c`vcx3ahaO>#!c1uoX^h#}2r#6T7hod$AAuaR3K#2#0Y5N0E=? zIEjyN3a4=fALA^};ZvN)1zf}>T*eiAhO4-S>$riNxP{xegU|5=+_;M`aS!)VfI<}E z0lvaRJi=pqjc@QRzQgzU0Z;HFe!|cA1yAuSe#0~Tjz91x{=##-z~6X@SNI37;ek}Z z;~6^WVSo{(P#QjX3vZ(w%EK3CyaNj=;61#LiueGPP#J!x0)GU+imIrFKzxYmsDYZO zh1#eC6?GAWda%KcVAMwl9B6=sXoSXSie_kz76?TvgrPOspe-WN0Ugl^QRs|l#3Byy z=z^~3hVDo}5A;MY^hO^fA_>VzL0_aI4e7{0KlH}{WMUu&VK9au3qz5OVaUO7jKD~Y zLM}#Q48~#{#$y8VFcFh58B;J7(=Z(~FcY&d8*?xh^DrL^un>!|7)!7e%di|PuoA1V z8f&l?>#!ahuo0WE8C$RwPH5PM?brbqc48NHV-NOXANJz_4&o3F;|Pu-AIESUCvXxU z;S^5e3_iwLe1dcM6z6dP7jX%faRr~@Dz4!=Zr~5Jh-^ zuka9$@EBj?8+?oJ@I8LO6a0vu@H2kFQ~ZkG@C?7>5B!P0@EkAjH(ufu{=sW_An_b6 zLkB$!Fv5gVC=DOHg)%6Mw^0t|;R`d~fdv)tF5biYsE7|x3668-$}R+Mzun z5Qz@xh)#$?XG9|gv4}%Fx}Yn%p*s@L13l3Tz0n8a^-&U%k%GQRMHJn#u$vnIE=>xT*eiAhO4-S>$riNxP{xegU|5= z+_;M`aUTUJL=hg~D?G#_JjU1f2H)a4e2*XS1V7>@{ET1l6u;s(Jj3t!1ApQ#JjVwui=4I#A6*g=wW~nCX_;H_~0#+L0PhK0?p{4bcdV(F9G=49(F3EfI=V2t#YM zK{(o?9oi!Tk?4Sq=!7UlBL=aELp-{mE4raO63_!Z(F?uN2Z=~RGE&eNsYpXQGSCnG zF#wquh(Q>PEDS|9h9L*TF#;no3b`1KF&K++7>^0a!$eHNWK6+SOv7}{z%0zh9L&W$ z%*O&O#3C%l5-i0sEXNA0#44=D8mz@Stj7jy#3pRU7HowR8n$5vT-b?S*o{5di+$LS z12~97IE*7WihLZyah$+Oe1uatjWhTdpWqxm#d%!7MO?yVzH2B!h7Nj^f)C1|EZ#;r zl!q_Ocn20#z`J-4@1r65~Yvv}rW^Tf3<|e#mZo+HkCT)B~*qV6jXsf0$?p@#_Qo`ydG}G>)~d+9&X0# z;by!ZZpQ23X1pG5#_Qo`ydG}GcgULYnz$LSiJS47xEZgBoADj8X1p$L#_Qr{ye@9W z>*8j-E^fxR6`JwdxS6{h+9Lwdh(Rpk5RWeCif-tR1oS{p^g?g+K_Zfnj1=@mD$^PWML?>F$_5vju9A%QOLz;jKNrp!+1@OV6#MB!9`#93|<=OP!^4a;6`CdUPKi56jgdad<-$~*F>RhfW%lHlJqA;{d3~$lH5ZS`29{v z;D1>E$3wK4KooAj_IUD$!daF%ktp0G zpG2Gr{!7y+gsbG!i8COUGm|(ApHV-XIH#n39#LR?5otbA;P+SgoxEa~$rq9@f>_RC zq9B&DgeY7iUrH2`$(Ip@Tja}$!VU5j#FgN`w2DI5OumLFi1urV!X5H;L}3#7dZHk< z*#_cP@LzIL2w#$G#BC7kxt%D8`klmG;J>t+LJ;-*DyzhAvU=O^Bkspt>JJbPm((92 z3iqf#O3VlUr4tkeQB`ro?8TiKjVH=uO^&DAc4)OJXQmlD8s; zL9}m86q=K_AqpIVrEn3^j=U|gGsOBt69s>k6GIgI$YY5@74kTu5X3U$i9#@WS7JBR zCr=;>4aj>E1qXRAqR@G(Bqb3A(LR|dbfCU3QLs~=MigpNpH39okoO}B^=Q+dDAXk% zKomrqOrr2tEskkKp%wK*h=OQ8lqmc|n{1*`hx*|}p*HzAqVO$k@`yrp>L(F})+}=} zQ4sahi9&7aXAlKZKa(gNC!a-}jT+>0h(bR3BBJmi`C6jzF3VX*6y6~Z*B6Utdu5Ri zgV=T>h$Bn#F~o70MEwM!AdcVDh(dMp8N^xmkbDkN2qm9KoR5~|{64F+5dq|ziGn}* z7NV=9ekW1*l6Bri+=F}M{GzTTJRsjs6sj=q0ph`udVX?Qw=D3qejGomnu`rnDd7Vw)Kk&0Uk{zPof{8*@MIO&YLDYv3 zg-+Bn0*TbTq`n1FXhVHVVrWTyD`J>HeQRPwNqrJ^3yZ$>cqS5s z#pIKS!W#0)L}4BI6rv#dVJcBrOZ_yWu!Vd&QMgAwgD8AFlh-N4V+j47#}V;VNuJAo zFBoQVTpa<(b#@c)LM;DF;ytV(e?a^SqRrPtK^*J8BYqFj{s-a{EFk}p zD7+wlMij(4JQsDyqyBH=OH3kvMHIyPRJZcnh{^1ewTXhY$m6L)6jqT369pa`{K9py z$IP2VJ_J0pr7YqEJf(gzaSBL1hXXmbpb~Aa6Tind)N^W?R1Y@lZNx-~V@nb-88Y=L zM8W5CkEbtDsKh}kl_-2beHu}?bI0RJCkk%z4B|kDbr?hx9#cP3}PLI6GuQSXFPEN&d?^0_z0rS6XMShZGIy@E2-ynbLm5DVBe@g6hvN^D2P1N z$>RWGIUR^X^AR3TN8+H8`aI(5lDw)$zd^JQCJrgdbBSXi)?pk`cr~1LCQgTFKbtrQ zqRm{Q;O@cWg}4}^%@U#@w#zc&_LBM?MBxPOT|{9Y`A(v6hK@VFS;>2Z?7P*5?zVAoh)OMByauKP3tmxR2+Fmmu!fb>a<(c|RxK zEy@2N{t3}0&c(3~NxXK-BA$Y+pT}eMaQsF9^R^=PzysP#23e|sn$*`Mc7~h!y~JB3 z^={(JlKL#8ER9AD+K(m9D#_;%7nS5oh)YZI<;0D+%Q80;_m$)ai1{V?apH-RJg=-Q z?MEofKTZ4%r{61!LpPHQJ+Md0Pp?!UY4w=N_|ygYZTI+tN-~& zT?a%X0ez5&fB(HNOO>FY4s2)(sSU9$(PS{0Ol3@On<|<7OjS$)rk4B`LZqoH=b;WY z-8U7QJf`SU6G~;3o>zK7>4l|Nl>Vypqtc$z(Jw!KdFy5Ke?tG6|Iea-&i`|b%hP{6 z|75++c|GFwtJiOCKdGE7jfeCz1EjzRe^^l!fhB4Xg<1$k2pXbsiKav$tVBDa5K*E7 zQRsxuh(RpkOLQX&2_{IhdDNrG{fajtQ`(ZV-Ir82VQKx4FoRJmj2=*r_OZ*czQl={h1qXGY! zS1jW?*MGuO{DISzpH+TU*;Dz=^7DKq`%Lwj<1^o9fzM)}Z9Y4E_WJDSa@Z%I@zg$H zgtZGkmwm1>&e|6~_k9X{ihLgVeB<+4JUtcv^OL30cnb~C2;qpvK>VP4qBGj-**Dlv z*}XIPvJDW6;h0cDs_CgIRjOR6N+thFq3_4N|7P*x#nl99y|jyqWHPc3`k4y2lrL4j zl-S=Maw%7_T*Wd0Y#0e0uy8rQrSKhuvo-r#-cyDjTKPv96#A6m4bh30EHXh@BF{H$s z^?!4J{=eRj|9v0+|F3_^8kl+PpaI%J+Rm`)38@1dI>J3z!$MA>ed?Wc|=u z!&-~86vX)novfX$iPo9c+13Tt>Vctwk%38po*GiEVRc5-Sz2d#9Zwx8sCUrQdN1oq zHiM0ygRzyi1=wu1hPGz5mbTTlHMR|0Uh=yv3+(Idr|pmI0l|sE6N0Y=^JVSe?)5$O zPj~Wkk~FI}Lz|`9wl&@sv^{A1H7-3}JzWD_nXVT9v}D-34_@0|$G(n#o&LJt>rD1k z&uiHe;A!d!_4M?ld9t{y^Q`wg@O&hxY9h3B8*{aEG{N0dT+G(<}*z#3e~D}2Si z_!4jS>*#B;bQUy_{(y8tma3x`(lG#Hzn_dLn1k)ujUVvfrYt>!bW4`HA_=1)-R2mI zu2_S0SdUF5wi2D#j-A+zd>k)vl6V&9V7$Zq!drM774RPXPz8nHfUQSk{FFx zZ2er8w&C&@vUC+54E<4-4nqD(mYPF)%JUs;Sd0zWjeR(UGq{Eu_ygjN)Lr-n9&p;J zq=PS-A{6ZrjTj^$4dTt#FL+b606*d>UO~LMIt+Pm;{l%FX$k4MER}&T+94VVNWye1 zz%J~?K1eTQDeiBkV-T{CgHafZJWRs^?8IIi!)ctub=<`Re2b^}6P&pqEy5C9!c)A! z|2{rG)c>N-W3-7Esz>G6TlDYoB0!c_{y+BK1iYzgZ{J=`(l%ogq0&*CN|>P(2*^;N zNElR*dQMeP(4rAhQHn-I1t|~&6cx34P*JKzXbTETR5&se4T6eVH3}+9!KkPxh*25a z@BXFP*n{G5-t)ch|NH)LpX<5quAQAdXYaMA^|WL-t^{>0F2z1vh6lEyyOH&djd7b{ zcYHeTi3{TH55@C4Q(wZz{tSM@Y(wY7vg|q89e6`_Qx^g zDqM=E;4(Z1&&Lnpg?JG@_LrZa^4x5PSdK%A<3<}?XJ`3i)of_9vziTWR@ChLW+Tys z&BinzdV|mz!;Dwz=5{&9*gjG;h}YEN^VY={O7L;+EKjTjTaPU!S1P!m2s-LY#=L*p3~zIc|&F z<9yr|cf;LrFI<2RVX*n{J+Io@Ktve2@8F^Zn*ZbG3Pe`8o4S^YiA_<~8Px=1u0;%x{?A zG}od!^JnHS%-@?2nj6g8_e)M;zlE>B0YChXM+zUEXfDfpDDRQH zAM#Y^_d6%%C*~)k-28U=J@fkzHn4uUI;UZgI(W^Y(nB8}l4;yEF+qKX_u=ocQaZI` zv5pHvI@R+up_2s-{$_WlwHhvGvuhZ)`ohwW48N!^;hu8eVUByW!o2tqmVFZ2zTBY2){b z^KmciOmjD>yHa&xpS2%H@sId0Zot~#y@{J>@$~D&y@}DpQx5ky-1Bh3;eM#_@PNYu z4|@&|K0M;^fcytZXIUht^eSNm=SR=79pk^@*iAh-&cy!;8TNVj0(^;#M?XV)(0V0^_p3F=CGE1rR8;X83Pej2NU6z)@| zs1nX$uEUe@G+c=-DAlT(=O3P@Es=k!npi6#KdA$1gYH#Yg{z~Di9P5$ zR7ySl#wPo_U+?RFq-}}mwCm8BHWTFBbQG;8%!zNq`xBj98@M)hZQwoH+kHRj^Q145 zzDwGhbSUWvR|*=E9LbL4X33qChbKRk{49Ds`Rn9p@{h@fkTRZZ%tS8K78M#t8cU2< z8B2|`jdQuaP+@$H1}J)&`l2E<(lpjI$y9d2^VhYewVb)W6+ds?Y1(J{-gE^0-u_D4 zH(h7;op3+8*1R^p|J=#G^PoA=Vzt;U4oh=OTT6ROzNM?Bo29#@m!&TnZ5d;^#4^@0 z3C%>aEO%J$w#+Ae`~k~DmWM41(PNfHmM1L%OQogS@{DD*r4}Vxt=1H)!`jT+*4p0M z%i0%>v|eZ(gG#Jptz~G|Z*2Q(t!v}k`_9<5Zm?NxDK>|#nXR|2FFFSm+s?OLVjF9_ z#Wu}0%l4q{VcWB|mA02`Yf+8uRa-(zKDp-IQVLTBr%X?ok>W?Ur`(Y;FXhRUr_hp= z6=a^TOj(O+QbH-OqU|X=QaD8>>wJj)O#1};9Q!=Ga_h zOIl&txoIV76Vk3tD@`j)TbZ^MZAZ@Z$?0Y3{`A@DmFd+;&hb^osToBX*JPAt_%g~e zmS(KTcr8O^w#am57H2L&iCNvU25}u`W>!VkGg-^C{+ac8mdb9KJv@6v_J!F~v!!mT z)ro#NXZ@-1oK@-xr~cV`!kV0Q=;hd3{#$Zt<8_8Q-s^9yGaTW4etDx`-szXO_vQV4 zd4pfx*q3+qr_6Yl1xh5pXT)8eJ``*T5{k%YJ;AlWS zWnJu8oU^$7;tq=o7hk)08t<1^EdG3P+LD|lr*T$&C&>o2WE;E}d!PHmCHt2oRO%}e zE0ZhDmDbABDhn&Gubff2vT}dr&y|PK(aQQtb5*OV{HnoKa%}fkJr_G4ud9kweNnZy z>QGgEm8x#bb&xZvJ=JGdmsHetaX;L4?eQ|$GraSk>sr%wGd`QT#d?BvDave)i z_s+qca3LmDTAhiD@C~>OKZ+~xD|j=08_W6DqgcDPu3cBx&TF*mW7;)#?fSZQZC$&r zu3b~tuBU6)(zWa8Dv4`Y$xItQ50~I8a2cM3XX6$4Is8xjSI#q~{#1f*#AWy~T!)+1 z66!)yPb$Or zVtK%EDAw*JX!j8mbG=~%Ayg>W5~^G-c=tkdx% zd>xi+wc?q0Ij+UKvHm2sGwg|5t|^L(@OAjcxM#xW@CF>hAH}^LiksGBI#6#Z!?)u( zao+*&!uQ}u@giJ_rM~ki{;TJQeW|mGwevwa4;(A?*i^2M;vx7fd!W;3X zxXVuFx)I)nKgOy>g6fPtahJhryee*$)_A|A5XSDaaP6Q2uE27?rvd-b^@z?~cjzDY z04T1&OK>%=#XIBv42o4|qb;y2?j3g#6pzMp@uP9eb?pOKW&d)0Kac+lDZuJ`Q2D!=hM$+7!V}j^V8N{p&>kCtp{s`G9jU{1M)c58)#? zbt~7*up9Tl=inlIEiT1#@Ey1kSL2s)2+MU^wS#NCSnW(u9r5Y7FFq&k`MWr8#5MRE z{72WN)NY22)mM%8Mdco-_ILt+E=^jl$&YAOr6?rYSVgb``iw+AJsKhKP}0flUqV7ji-@| z_3L_I11@jG}6;ecvT3H<3%B1%Rk zWI;A$M<=1?=wy_JGEf$xQNDy6l#5!TR;UeXhdQ86s59zp|lcuHX4pbpmWjR(Rt_sGzwjW#-K~kSacb>99@B~L|3D0&_px|U5{=+H=$e5 z6m(lcS;9;-3(Z0EXkGL^^ZqA>aZZ9^ZS?FpYG>_9uwXXtbECHe||gT6(3X_52?^dmZmX!t4NC~80n zx&)mb(Kw|p8JUm;*^nI(daP@XPDW`c17)F8P!7sPEm14f2DL*SP$$$GbwS-|$Fux~JLo<1KH7>tL?5G1&b2TpzT)J5oV^dx!;EkRXiDS8?$N6(^_=y~)aT8&;pYteeN z0lk7YqD|;E^agqpy^Y>M@1gh6R`enI7=40vpq=P5^f~$xeTBY3-=e+fd-MbP5&et~ zqQmGYYB)7H$H9FmXHJ`({G8Ks3b{8W_oYg5uE;5k-H)1`Ge74av^BXTXGOea$zQHH zZHixW+L}|BBkf2wwjycf3X`-B*&KC7ZqzGwU8yhaKQ>-h@^f7&pL>8~(d8Y-bsUeb zLKDy=bUke=-bkB@)6q;c3(ZDz(VgfnbPu{0-H#qX|3D9+N6@2a5qcawiJn3*@4^Ii!+ADp{nGMk;xvl1M6< zq>@T{Ik}{gOe)!=l1?i5q>@l78Ksg^DmkT+R4Q4el2$5trIJ`GnWd6iD!HYSTq@b6 zl3v=1{8C9Ul?+o!F_j$CE+m;smZ_wfN}j1Cno6c=Us6pa*Hn^CCEIim>86rzDha2O zaVjaNl5;9ar;>FlX{VBRDv76(c`B)=l6xx2rGAK?MP`o z@)&sDj^=bI&&gbkZ^w)9Kk<9`JDkk9+-bNEJ|9oScVKz0 zrs;X#PRdQs`?5HXYkJ;y9_6OzefLmqdfxXMWjXiL&i_o*!7cH6xb{5j3R*%x{vMS) zOLhyAdr$J*nA~I1?jbe3fAkvnizac0XfXFN^|IweT?hZ_4y}PoLq5$Yt`1pR<2J^i?x9&*QZO- z9JGH)G}gwbJoohlDy=T%s_`e)KXA=>H0^_4iL__Dnr<&AIzQ2_W1Q&v#EGs$Xy?(| z`LEmul=HBc5?)HENq8lpTvx7Zy#Fls?i!!%ZF>LikM7;cJ-c7ur`!Ci`*hd+?|r&| zxkvqz*a|EcqE7 z{x|Mh$vvwtfAgNz#Og_Zc;9M!{Jz!x-@I>CbAtO-|L%P%?Kz6yeSU^}PydtmtBT_H ztB$`vb)x%A%J}D>SN#9deWd@rZ}jJ$EBrt0zR~~QFZ$2kFFO7{k>dVO)B8gwx(_7J zgZ)?T_n4{oinaS6|Ka?!Xz#1JF>zgEi6hFnIwiuW|*Xg)$=lk zA~{S)c9?YV5_rk?K zNeYv!Fi8uOys(c*4BJj-n52f)ksG#)RnB}r0}B_(N6k|!mJQj#epsZx?FCCO5fEhXtvk}o9* zQ<5asNvM*H zDoLr5oGMAGlB_C8tCGAbNvx90DoL%9+$u?~lI$u;uaf*Kd+gnjwmFhdC7D#ik9&7S zvZyBJtjc*QXLHUQIoo)5WH--&9w2v0d+yUhYLg?kS?-CR{mjqp7Efs!#B-lBdG1s4 zj!HUS+R@wb3Up;G_2}wY2I6(3AKid%izOaO=8>cxN$!y(A4&F+q#sHCkt85V29l&8 zNe+@EAxRdJq#;Qjk|ZKYCX%EgNiLEkBS|)rq$5c_k|ZQaMv|l?Nlua^B}rD2q$NpS zk|ZWcW|E{PNp6xPCrNgaq$f#!k|ZcehLWTxNsf{vDM^;ncG8q2Pe~G$c9EzgnM#tX zw7+8^Pnn((%R=&yh9r4NLl>WghQ)G`BpFGvkt7{S@{uGVNivcoB}sCUBq>RplO#LIPkNH%CrN^mWGG3BlH@2!l9FU8Nt%-6DM_Nz!;4Sj zNmmzY9ZOY`TqQ|Xl5C|sl9eP|Nz#=hUr7>{Bx6ZZmLz9Ml9tXOYss@@Fd7<5T$0Qs zNnMiMB}rbA>?KKGlKdq}V3G_bNnw&4CP`wFEG92$Op?bWiA<8oB&kf-lENf8Ot&tX z8p~pmG$zSol0+uSWV&<7U1)wRo9RB1nIxM@(wQWmNfMeQqe)VlB&R7rQj=sgRg$Cm z40)K6*d&=vlG-G>O_JQSj_f8$Z+dx2Xo(~^NrqD`2~LvXBq>fmE|KRuw7OS}oX<;J z58CsmfApMb8P8BkTMQLkZ(on)xv)#HJb#se-FP@2kEdgK$Mw&?=lVST*5a?Qf$QqO z_kL?nKL0cCw@#qHS-1kP#$o&|HgYXK7Z>33a4DXP5|xcMjy~N#Ezs$(w9lQlfF*+HtD3~lX$i3tmMVXE0VuS{vr7&YGKSUW*J)= zTN&FJ+Zj6xFJJv42o3VBY zcF`t5J(73Pe(Qa+Qu8G94M^UNTZ7g$c@J(E@4y}6{kH^*-co@2Sv-~@mZ6rjEyFG6 zSuU_#YPrlZ1Ff^XYSy&>2U~|)&$14;o@YJZda3m?>vZc( z-a%SpU1tsb%X>(>cn3+@^tL{>0$V?u$2QnD)OMC_xa|UTsqHe`blXhZ>*#G;*!BUU z5o6na+Yh!bDP2B!O_ogzGIZ*Vn>PNQis=Zh2t8>B!|y2!*Q469`vx|QOB6(mo#sdc5+%* z-e3D0?Jr!Hc70kf?LFQ$`XtSgZcDeLS?RZ@S0U|rs5IJZI4|?!%#zG0nbVNGSEjNI zS?(-P*40_pXO(5m$a*~M>8vkkbHc@QRgLeQ{qnxq&++%oct%^^8(f;g``CD}oo6NS3_J@fo~_p5o_H`Wjr)4&!_scX47>vW6Tcj{;#q1P zZiA(rhe3ESzCP|UI0LW5HTX5W1;2&g#vOT<`gAPsl8JX_{peO0_Ze^?eg|*GAK^M2iJQ}HWyalbFWd+B!$aae7hZ(#zz^ZhJoBuz zbJCyx@54)Q6@CGC;hE+hxOdzIurKb92jL-c-vN(*ul65w`+;Ynf5Q8&;+;{P&$G%s z@Q8_xJ{Qi$_u%`m_I{xDKJ24wcwYe@|32pB?=-%Tc@4Y{pXj~JGu~yrV)YT@#eMJu zd_&xRD1HPl!jI$SSk>_yIR3-;x_O?r2Y!ZUc*T40UR=wwx*uQ<$DXsW_I{|mM30A#z0LPyh9BizV_y7NvCwfc#|bxj0j*2hn6@cxb6U%c)*0<$&&hVl=$6qlBO^1DW5aow7of4| zvP^I0HJR5*_;^-#)Ccv=8jv-RW5tZvapLi;#aT#RLl-=Y1nV@HQc#c zavts(_woDZzU+6!P4~~TkCy%Odw4tEfwld!?32Y8;F0(ram#*K+%Im~|B9cDI|#+v zepcEoD8~=R{bPJTtL;y<{ip0F$6;+hIfuILy3BQ%pE&EByPOecDRmM#M|c?5QD3N` zuCQ_#$9c+s4&nl=h%X?vK@Z0!Z+f1W%+fw5$FbyybH4R6<)Vrt0>fIZtcfW~#sc-9I_3Z)2weRpteS1c%zP%w<-`-5C z6K|S-sc$F5>f8M-{VfBia}STzx6eOT->$LLP}6>sdbZTGwYqlUZ`8G?$LiYat?Q|4 zziQpWJO7RK?1Wf7djR$9;i$2GJv~;xem7pf{`7nb#kyhp)|CAFGS&sf)X_dSvy^DnMtT#(Mem ztS7Rb%Bsw&%32z$pMR0HJL{{gZ_(bY?+M55mfho6ef_uFh^TdLckV==|EliZ*k;7U z#S>3hcW+hMI#zcN{i@!6F7@^q)Z159y->BfYE9MJc>O)Ex=VG}>h8zt@x!X8px>&; z@2UQlU*%8LpD+D<>2CDxadr9suKGK-c9i({>hII}d?kJXuf`{;$9LfP(Fsd^zG*#v zI^`GeI;_>>r4BFd%rT`4cE{ZV9$&AQy8UNZtKajQ$g%o;A^(eyZx^R0$B+K_4D7*D zmv361UrBit{%73lVGVv6OFjQNjx$ovUxU};^|)z$zZ=Ju-nehv{h?O>mvexp<6Z%u z$8t`fofqVA3_1C9E%)vv?EYbJ*`^%u2AxNo>MDn8F95* zqt>aCq$`v5B^^wvNq#MPoM|F$Y3?;eO$SZm%oAygX|H*lWuoOe%T1OqEc-3vtP`!1 zt+&P6tr=;%m~))Twl8dZZAB@gV(-{F?cMB!jx!ze9S=FKq@AztTI_3~wGHE7eh2fe zT5ZNh8D*JsGv{YMlv$KDDr-g7>a0TEZ!5|km0jwTb`o!PmO1A-i*je=&Z1Ss64xWH zuU!qU8{6F9=4i*G9l2;1Z;z>W{(W5@psmApU59oZ(e+%~JS^)vx9hWA*LQU;ZnyZ0 z#d{a$S9Y(gt^BZ3RheRK_Ux-VSS9UBO8v;ukP*91tF>ELm_VC9_zrw0-l^mHXzb)# zN=rN-ZfOHd{0@E}S8#2&3Xe24wr_MZoQ9X++Ao=UiOBkk9oVy6y_&&9=fBbK%^rJd7> zcppB9rQOZ`xE6nicj744+UqG|A2|xw;t#R59oMkEzJ~MJr}e>g?929JtsOe8y;bde zRBNBBCWn0+R<6eO_q6T2<|>AVi@3Hh3SWfB;xg*B4@%wk-NyDFOWtd2=TU1%v2Z8t zK;V6xvmeA#&wU$f?F&mgi%ap-csYI+Ywa#}`j-7Mj>f%YfAuiyGjHT^w(Vc8q|ElK-N<7^X;`wg`__8XGl&M&{44^Q~J zk?sADwsURzwCz>fUdH{w_V8D>gI@9N;H%@dgHaqqj^7SWwBAp&UbXf4tMwCa|3>yJ zpJwdHP;8?Y;W2nDuAv>Lqsa})+WgBtsU)^MaaBTLywwr9U6`$K6X>m#P~U-xs;_Uo_rb0^xj$v#aRw@}-E-M}>e z-u~-rf4P1-*)Xpp8LOl9^VQZLxNjPodrAtCFrs3L}+l zOa3|eU~;~(U+fyHw8318j-nfBr*R*;$$FF3kD|7yZA8k5lnYZXN-@}**;7$(dtdu3 zRBI30KeT^jKg%(KmYWYdN}7*vu2NO%wJok~@d)cqYs)#D_CeaVw2#tMx;fpGF(^aY z{jSJdoLQOqbmoOwC0SEx(_Gpq?~~m>`!?2hP4*^QeSR<7;cVl~cMfz8a-Qq_yYph_ zRN8sIi*}xkEiEnEwQS#Ve488EY;5ytn=jhzZ8Njof_B^5ecbLyyQA$6c0AItp0;UA zJC$})d3kyHc_Z@vMmx_5`Fh%SJ}EynKZiD+^YiZT($>HqcI?v{5K+Xn$J0qk3QU_toDl{pPr~p2yZ-hQ_0- zX!ALtLEn(rU~aHB*c&n%vKn$??LYTz=#MT!W6&kE1+8s6F(z=W5HDg|71zeCwKp#9 zK8kaw?}+=yt+gj8+q8Hemh0hKJMs@%xZjJPrY<8sk8OPvzCFI(4`E*+?Y6&!*Wh({ z11_ZQG7$Ul4R|BojNgp=V<`Rv@4!8&EBD1xXBMB$F=GV25NpQ~IhMQ{_Xf@nx8ecR zeFkE!?!KD;#RcrQ`pLeF{g&86-9Xys-4%C#&cO!bhw(!E7=8i|VBannBH2D|4YmetJ7}lcvG*Ah+wb(T z_u*IG*S?V7@nGj*etEa?%e&iYYH8xvXW`e^zU7r|u55EPx&}=|lhF0(2J|ZW5`Bff zLEoai$luQ2?shZ>-GSzzyU~1fA1X%=q6O$f^f5Y$TIRLPYlYgNcIbRG5?zQ!BU8R9 zpXM0zZOD#JLMNj%M1vmrS?E-L_x+CcJDOgfUf%=tM7>b~>W2!^8OVc%q6^VzbTKkD zm>T*b`JI-a%aH7gX)wfj3hIsYd3t%YFVBo@=oFNT3fYgu))~J~IZx4kud+|)MAez) z%y#mUwzC(K2S^RbgsdnV5p|F!-)}r#wBd*$$Bd4OhIEe|H%6<`$Bq?pocQ%IV(x$2 z@!>?r201SL`k0WIp8OY&3oV>!PG{`c(9_w++0QwEW5kfyG2-ve^EgiY>;69>FDcKM zXF(}>E%MUyGV-#}sd+hh?PJG=UU>z1{qqK(fwAL6aqKuD$A-h`KXF`e)VCl3Kr#UG z>j%{ju0OMWSbb3}58#6OOX|lScZ^8pC?UrQYePztV?{wjLBm+&ZF-FOfBE?EzsCiR zb(~B8$Bzr~9e7(>Y`h3bU9UH_ssi)~H76Pyl}C7~_Y9)WGnG2eUDSDuEzPJM8sBDo zo2$?SbS)}H*C8L;h`vC((bs4X`VP%(H?!R=G#kxDccQz{J?LI^KY9TD18qYep(E(D zywmbrs5NSf&Oqm(3(zQZ5i(M%qABovE225sd~TIc$4bp_fznYXItBG73nQ&Qt-d=t z9rZ$eP+!y^4L}3Y5Ht#1gvKBuhRDk36RRg(LM`c1B#W@j(%3$tR-e(X+vIb9Sn6rg z4(xZ*4s86-rCh25Dp38@#i#^LLARkN)MCZOEVT?hqn=ekvfViIoP4AE z7VRbHp(DUWeIaz5?;U(@2679Xd5oF;8oeM)=LW3#Tx@?}lQTAQ;rXMN6w zoHujcrp@^sIp5Om{88GR_c%SyzoA>4Q=E4==Q%54`6&sx`rM>kW3DMT6}8Asr^%O= zxvfwe)DFo(t#@vp+`?Q>?pd*nl@Ymj#4=WrTUuMTZP}q^W7f(-7YTB$u4q%ET4D$x?@q^xp__7hnGwi1DPz%@|%;$;>_RT_jY+Op2s5XxVP^*q-zl>A(`clt}D9MbZyLKnICvHpq8{);v}DCF8M5ND?3#7 zAfx4`>YJ;zd=@6<@N?u>6&@WC%dI*>Zq=prm)3jh$JJknq|qJ=%5FHdp&u$lqtV4k z%WF9j&uh{0S#D;(JQvTy(tf{|*HXd%VlB7jChB~X@n-7g;{Mca#qU!m{T>%kckCap zLrOhT@+8DXZ*v}t8PKotUA*r!=DSRQGqE2ZpYNjHrA~|`OF*o+?sq=k@Ij+LhT_9< zpS+d!PjUCSM?mq!xaUG~Rot&YvD!xc`a|l^)QNlJYp@UBh-czi_;xJk`r-zzF^ZS% zY4i#x&f_|w_*h=nzQ2~|V*8%+9Q+0TzcI%}@w}~^>z8p4_AR+)-(-LIgnCNd!+uNl zS+akUebeFizUiRlphfmYvQLqHL(j^dl}C;qIja3G>Kb-7d`@POHoQ;RX6vxF9<}vX zc2eW{puB%Q4Qqd8oa<@N0m}1#vc1Up)32U4i+@3$nfeZ=emV#`}p76x6A(eMEg(4hibZi(e^2_KhgFTpEZ2eaQFw73D%B1+A&9tHP0gL z7$e6KIer|!UruKqEc@EC(fr)<+=p`?$*n+7qQ&SL^j7ZMx$mMdism+)=4_eUateB+ z<;s@ZTkdT6VyhQhZ9oTFHME-8dSdIEWBX*u!)m%;ZfKw1!P8+#hhZIL->B^iwSAzr z@7vX|tKqALJ;&C)EaU(5{^Qv1J-z}LbBwM+&!82k@tAve;%^;m4{?NTJhmR-==!h6 z*MIledi-%!D=YHZ|2tK zzLWbNdO!CEPWR+^n$z;M*fI6imQ!0k+%nkmTymxzG=rb_1|zjJH-A+MY+EA)Bk_+$@1-u*Dd3_ zhhy!OYxiHJt!ugdSC+LtORgy^o2 z@oX0V2QNxcUKkleogBI@;rcrCT*|ZY^7-YwvqkcgcO2Kwg;(+}8cb!K&xhr36^y_L zlEBgdtc2J*CvkVGu5m&nK~s z!NB#@xuNR@=D8cwaSP8%z+zYiy|4oMU=8%#N=^VwokII6ZoUWep%)H=0XSZ|Pi1~! zIb0>(;WikA2Vn7SjITSxDdYJH=z%`yy*)t%VBk@nbAZ9ec-O86^HIV4LqmZ1hmogf ze;oQ&GJF_(p6P=A7ihQqbiV&0*YcrfHN%C`ml!TAU(0Y|WF2kY$>-}6l(Q$_hrYKM zehu>r!>|@cp@+|X8<;N`fd}aBewpP@xfnX%X1K2~|1c0@I4}e&`8;(ar0jZ?;ZgR( z1271~^1V%bzZc(whFXRX3n@pXJ7xD~=9jVu7E%ts#(I&@;X-J5o$U*j!w3vRV{f{@ z!TN`8SPWfTn0~$=c#r9$><{yO%EfieFXa&249j;iebD7r9ppdSWc2yTIft_&CYhUnCGzV8{TQ`R%sUe08?U=&Ue zo~2U@Vd!kW2g`@C{Go3+;~B_!&tdvuXp~M>K>rx}gYFXggQ=J4l-tASumrj|=QhW_UL+pU^j%r_z6x3IkB^IKWoLl`bBfZ-{u9~hj|en0hwg`TsuH>u>eMzEfrhgv zFVd-e=y`(W2qRCi9ZUBmtXE+r{WCn@)8r0Hc{%IpY|1N`ALv=h_6Z|!K6C|{A1T9# zeEvNBzsG#O0EbZ~&(ICMuo${lGaNp5zr^+=-PbUkuza0Pg`sD?P7&~ zd>^vhpzmXbE8I?h&<`tQKI+(BrN5mlzapl87xM!RpRrzH7?#5b3_{=MEC=ZNlI`GJ z);sJ817FiW3`0Nk?_qhv;%`~r(Dj{88UIFkFT;nfeJp1fgcZ>HJ=-}9!6WkdewNSQ z84er`!_W^?f6%FAuo#BlW4T75bpMg*FNQzyJ?MhNgg>*r2oLi;7(K%DK)+tEjOQ_5 z$$HfjmK*iT3q2;inlELmUaf(y6upYVFm#^JeA@MD81y>yYBF@4q*npxZ>CpUV3_R6 zDD@=W@Nso8q940>P~`rr{5fUc1Y=T!QK#W{L41$uHBK8(Uz7&wjo zrQDMKNAdkudQ}8nt?3_n;6f?4)vL`g0;4ds9n*6m+fN6*@<3Ndy_x`vJLy%0unWV7 zfv$RG2=jS&mJ2NIq37Ltwuhc{zlik(^P#JkUKK+(^uZ8Z2*Yp3{{$4M#&mAHA9*-3#<82)%F*3_;fzzTcPmgT4XG9}JzLS1VxoK!y*4gIJFjGu?w3 zE-W6xdW2r+hdvm9x5I_Z$6G_0PdMsKrVB=44WGNu(yKb@A94#{`JoerU?DV|tygW| zXMAuZEFQ*mL&I>rS_K2Jg#Nr2>eX)P56+<+ft4`zBE}2d@PKd(!z*EY7c)F)D4~Ct zI+o!<|D_BEhAz{q^sy{gFUtXX#_3fVEQSlA{|dG{;ds4re870GWc@<-)vRABPhdXz z+*Qi*zm)E<02ag1&8JWILpLD&*psD!xgtQoSrM*pYHzvR=6<2jNJ{(VN-6C>w5JJkSNp zp$7(`4~Ah7`sv?uE8B&9Z;D<;VCXiM+cx?u@TES|;o0z+^P zbl=YJ69!?ebcg$-`)sCn9OHp*=!M1556c+7VGh$t*$tObj=%-d|6JCm^bfZ~A3OpB zF#8II4-25-PSzJph4Y{vu7KsR7Dizd2If&__`$najvw;9d)Q9L^F3Gy-Ox?JTLe^K_r{EwKgCCne? zVpu`h{WQa;?17GtS>7x4Y8z!YETf#dn(dyl3+|(ASkL;oiteyvJL3&89h9T6mU8HI z#!op63qN7LYgr!9wUz0hd*DO5f6DZKq*tY|{1blXFtUs3k>S8?lmok&e#${ObO+P_ z9rI7w2Uk&cMOltlGo7$)9p695@}wMv3n&K~7!TzjH16d4i3U|d*#{?6PPG_R8D$sT zO*!N+s0zwqIC2-$*TSGS!(g^S)zICYL-)^EZn^X?ysnC@*D$+n~xR`+69ZpK>|eET8u@sDOOl%b7(q2wUi_0Fk)=aIdviHNxDPFH;nHw<`cRr zSpP8exItA)xr+5Rk?&O-R3UUPW4@qkIm-v8u3){u2pqbH;XKFsrR;;Lr3@dsVGtI> z5cI(?EQe7zh40ba8t42B4@M~m-!v%ecXWS?^#se`VSG}4pXEq@o~^78%I@uqcQ4=D z&vM+ybp2#d+hO@Z*3TrybC~ac&+^eFs#;jCPgHK{o|ve-&}U90%Np7f)nw>uk*Ma= z-J71MYJ{gGs`MXNuBRocJ(T@$K4pU|QCY8}e;A@1Y@Mh&QZ8?s$ZwD7%1>0q(BCCd z`C+(gq6$KnJ5fcTuX`eOJC;X}MCF00Jrk7=dV3|R01Wm{RAFc+NK}TO7=K@;8wUC@ z-7wleQI$i_0LBl?&q!2J7#Ya;e`frH7(et6X8bTbgz-bynT#L$&SLxr82{OfAEpjx z{Lp(2QH^H)JtGrU8T7)a^aryK zF}_iWszR0ztbrl88~QFxRF3PJ-is1dPw0Uop%+euAy@$;um-wEC#pK=gGL|I2|Wzo zGbT|@fT{y4m1B= z<_ng?InaAK+kx~qj`e>7!-E~6e|(}Uf&o}6-Qj!~f-7JI)z!3Dp zF!aL+3_#!Qj2D)}eJ}_eH#3~siK-C#VF?VwBIe68hw)P`zmxS&*)WgcNPqVwstU?c zxP`K30qd1=5bmQ~`~;*Ng6X#~-X~!_(*X-82Lp_cvgaw*I}F45(7QNMt%6Zl2mMRf zo*Gy#m5C}J2H;5Ou41}i2rh%(YNngvmcud`KHNt4Fsz^)foq`QX|{iux}5F*R+j&> zEHCJV<6!{KgAo{%&!07J0RT+y0P~?|aIz|aK{y{q;WB6#nyij69PgRQYCGis zG|Xf;YLf5clRSez5$;uDQ;W8M7+o0hB=7;Bi4Hxr0Kf}KySxulE9G9#LC>yRw zR$l0Wepn0x&55kgP_+;+q%`Or6YhLia7q7xcg*&-OLq3PQp(n_ET4{S^4cjgK zm# z9)TXphQmxZWe;@CXZ%N!RT1>T34ETKU{s})U2wj1hpS*Y+y+DNfPAhqD%ZVyA6D?a zfWfG0VF-HY?n$IS%8?YK>gZrTPBy9%n3`i$<49=y4g<9GKe1sMf$J+y^6V8Gke8x4ls<z%J`v?`?KD@Mzx1>6iWVe>P(|@u$_gV2S)uyHJ&a>IvOX z7*&MsKIo;K`Xry<&+>*HVKH1N{RLR=(DRg0sWjH_Vx}90;V|iciIIH)>klr3A-D!c z;dbb%G^!)87-p9GDIc=svrmNC}GlIv~8OWF56+pBcn%5=iW*GxCV3+>^1(ETmj zK_<%&x}jko>l=E0G^*5p@H;)gc%kPI(*a#ajB15+hjq|>l;te_yG^QAh69hlXb+R> zn8o-{H>r^@+}os#3pjrCF{z#~0L$s_?r&0?p`noPNq=xOpGTpzp%ENtQYA1_WKvV; z9y!;fmO;bcOlk{s74tnQU%>F_&pnFifW;S?lll+NhG95Gc(F-^q5Be(vYx{9 z-DFY+q(7McFv|t@gwd%cRmkV=X(ly+au_a=;OHt7A#qzsQUJm`XcxLKAjjKWZa;pS5Q zg5>}Wds*M~=Y?}9`}Ubs5Qg@%{9t)2v#M>y_R-p`RBN_}HfEI%J?+e@l<$S$LK#m7 zv+~kC2^^%fzD=i0DAMys%;y#lP+czrhh|Mvob!xa&w#2NV@yGo7uOr+Kr2ME^t)lQ}$GtRce6Y!vYwFUg&w8;n8356K0j& zj`@4itcF5gz^r`G{S?bV`h&}$7jA(;xCcg|^(p3eu~~J59ykp8;RG0f=%c2%Y_udw@igE2H8VEtK*=i`oLiLoDh5^bKYCEMvQYLtzk(hwif(KlBf` zs1WoPSyWU$zmDND{J>=9>uIL*Hl`nj;X)Xk!SIDMnI2f|x2S?=nEzQUUl^Iga^w5% zxfWGPxflj0d+uaDC3^O@ZKHeiA&YV>XFLyER8N@tDC2|0Z~+W0qG`KM3@^ZR zO8F_~3mPh!KDq~=wy69S%;$288V$oM*j`}pIo2C=2N@5HykJqrXIVb084pZdV^Kc7 zZ`jOqLRXmWO3HN>u6eLs?PU9b{?C}cJhq1hwj;`Jot3%T~cEtMWiko|S9J zeD8Fts(_JRR<0d0AAPK9pOpJqRrX4zyO92cXIRyE7=-g+@gS>O1;b}CeCQrde=^?l zt!grKUtv{_Ak#D6s+LhMzsjl#DZ3_E)dU#5)~e=1kI$;=Nwqt15=&pIB8HbnjsK!(zAv2J5Wq2#mt)HB84Y zs~QSjU(!GH!U`CGHS+n_R<%dEf5&oK%lG!Oo}qgm%N3^XXSqUOl>VXrN46grhUx1V z?oTWy=!PXQ2EjM4pY}NABR|PFnZXkN}>0NRV{?B1e@9pi*+_-tYJ8? zC-mxVY9vg}vZ*;z&atUA(CxIT-OvY%*q+>{*_0ppTH4eq7;@Qo4imPr@f;@m{r2<+ zgLyXP*ud~Q+f)Jc>AE;cou?!m4$wE%|TDj0^_U<4k3hHf^M{xZ`6xAVPd zFNWKN?YuYBP4^HSDWCVTsVOiBE2LatQz01bYf}*^_qQqQD@;eBO}SxUfK82-vd5<8 z2?yEK3K$&Bc%XZTje#>AMK+ZW4S!=i(EE4hhw*zy*;FYk9&1wpXt>m-YK2eP)C4#6 z-X%;2bXD1?>$BXRW4gP;=WWUZi{S)VzMB4|`$qbMp-rrp9(?~T#sl5Z3%$@U(^1Rx zQjWk?(tR7tANqILl=F1H|AkEz!_@CskI?-S>k<0vZEBx%PfAg)o~$2RiW&+1DJeX6 z$?)JR=(DG&-7s)cigNa1e$rA@F^s}xj6al~qPEL)WTYs=Mz*8O6g7v>Jvk{nH_3dp zO;HD6xMPay$>+XKDLgmHc)F+XTc!WrDJlRXg(<3p?!^Nb9_64XMHye^^C2n94c$Xi z)C3qhGeuRv)U#4l4fMc>@az;dpYI3Z8fX}iqV~Ylzcbx^7%m(N%Zr)LO{{O|fI)#eg)IHne7w~<#XSaDXNgN z>l&sPy01-9Q|O*LiRDVU{5qx&hHhl~q`%25XFdTAr`Z7He% z`d|q(Ok+4OwT$Htqtp2w4EveB*WvB-4_&iUloz_8AC}+Ccwp*%tWW4Kr~fyYjt5vT zu=pYRhn|Hj5616%i{(i<0w+`U)H2`D@D9s|?q0Z!a`0W2XFsO@y%ZIuduo{BQTFX( z{-Niy6tzJ3d5YQsgYWSyV?vRHoH0k zT`6`|M1OARDrCEqGAwRpSEbUug`K)K+j+KKRZupZVplbkeYtkdjTt}89>Dr&$#D7H z1$WE$pz%%mciGi2KKH<$lzq@g+11gmMpAaeO3FbPhN13u#av zxA=UxU9FMtsm8yATmGgJCOZCWw^tC8LqD3 zSnsjv2+&&z$AT<%QNw_utR^^Zxv~{$=A!ab>EZ8QVcr4@1)Ls(aM^0ed)F^I6d)7xE^qe3BX78#GRPn znxU-(Hw5l9i#zW6@O(hW5&08huw-rms~UNx#h!4zZ>tNy9S>f(o#3WX)4DB=b_!Y& z&CW@8BR=4b| zFPC__3N`66j&qm`GYpqYa(z6{ptKkto8W^&Rrr1$n2lf-T8wn5G5AhC_JWyA9lOI~ z=A^dYD5UamHMphVILH^DW>8PS|@}s*Z5kkJ|)Jr6iR*OWs9wrVsjh=m%K(NfEt??^Z)! z1Dz6<@hg_gQgeJfH-qb(vv-{A*#&MlIO$LAnH}j z&+Q%HS9kH=bK8eh_cq7);KwP0V$oRZT;Ih!Yk|I$+J9mki(|9?ruJ+DyW&#rof>6J zcxDze+1w3I_k7)~221K>E+*yF2H{tNA6U#Y#jVX2e{g1pZ00l{*T{13AIGWuq-H9w zqT$-dgHv#>>)J6ojgw(bZiFsxJEyp~#(?Ks7vay&u%t^GS*kx|BB2_SAjMRZrdlgKh@%bQ&N;Lb>nF78+k594s&h} zGX>1*KAu}=F(+m77Rli>i7VYS#+_#|!5OI>)sIDBR)RUyVz662ErT|BDbE5KMeB|w zXmTJNr!QRltvvVG;*xgOq=4^*+Xik4xMqucFLd>fSrJZkrfxjr*=>xW7I$(+Z-%~N zFZ4F(n+oXixeIzb6H9gNG%q=n?j_JVpz$Z8#kR=@ww_%J^jj@m{d^ww#ra%;wh7#7 zaBs0VGgT301k50qH(AWwOpf%i1?x70d85UgnPK#`?4Aj33%KVj?j+5RqFOo+dh=al z+;1#Bnj_qWv<_O}QvUjOVw=;g`QoVYAkCYo;H!_Y9myU$?+&vvO%4X@GCSvkVf)c7 zzn^DLznl+Ay|I1p!k5Ji;gEWl(&EZde*?uwgdho~hB18+)%n&kve%Ds73xV<9i>|E zQA5oH!j_^N`9AmW+PYwUNa}YuP9}-*U5P@)U_kmFV{OErRG;NHa{}f4F!)~Z_gQ?> zSMEqni{?Mn<Y}4hkr;~;Zzu- zJX!@$?+e-cwEC3d=6U>wz7_gU zEj^3X197b0!(S~keZ8APfA8bIWJ+iz)67NNq4$iY&&qTzgx&=`H-CupI9!<6uR`lp zM(q#J&=Aj}w|=K~hQ}maYST?%=l){f{oJ=d*sWmutuINR`b6wKH05a1fs9YT95n~m zKn!gfzpc<)p#PQQv>qk0o{VK>ZgE{Jae}AJWbq@`FH>j2cgZu=*pAc~*}WFNMcekB zV0VFi(#~IP&b%v|e@S-vWzO{v^PV(oQ_?<%Cy|b7{tU2de#bit3hG$!#nfzH zSG&MBZs)l$tVhxq8C$a5k*MbNgWviG_Q!yy__W=F`x5E$a}eyZv4MNkVofZAhZ1yT z`%duFYW5%BbP)9n{4a{+e?Kq36MS!N;QrU*t*^h&+4l{4=4P*BxoX__8tJc_7LvBwz+5Zt;lk9I{0Dm)7Z@Vxy2j*!&fGKE&M{l zDVrLZGi`Y__ZM@V`jzzS6|q5(WK$d1d4~}L+jp#v(-O&%zdhhrR08*um7V2xno*Ly z3T($~0;gLnQ#-7`=OodIWDkK~*%Y`hSlNl)pUUi(kM0%Jx7Y0-b_&?lV5_bzznPai z7i|0MgMH4qWWy4$o54P0?ag9wPa;{^wO~7s*tflk+g7k!z+P$hA8ebPon&LwhGiBf z%~SU;?7rw8tv7MtXVsoh!+HL-wO3-%d{jqLuJZJTy*U2h4B z<`mxso9gcY+xS+VIbdU#j5R;Y@>y|M1$Nup0>|l!%rBe&Z_N6Z@I&C;F@c+9`@6R{ zJS=GuEhrRl#iDeGW51W@WpJFvEs4c&;$hUcrh(lF_HJuSV)reX9g5pLuwBOn?tK;; z*)c~*1w;CmfSWcuaQ|g-X}g8bBvR$uTCk<#c@~Am+MH`n(2>2{z)wD5|N3G1m5l#j z_or^m0K53q{lhK*>rUHu|CWEtz%Bu+efqR5tbhNOv|!}l2Jo$?2fX3S;FGpnlW)5n zV7Gv!Nix~l7;|_cS#8q5=FE=Hz#VM!GsC`Uv8`aYoyqe$s$+YTY*tQmgY7&kaGVy% zY>0AVYSMCwLqE8M^LSgW$o5p%`JI*d%(4K(H0ixkgLL&P-J8Je0{3od}f+YiQI{a1yO!Xel_iVRp7=I%+otnlZ8!|M~N z%CjZl=HD1pJ;$S3uuAqpf0E-=r_Y_>!MGuk;mofshro}3ztH+)`gd?=oS4Bka_v~I zkk>acCR;tJZ^2UuSaa$bV0VB$(zc1wae1sFd@k{n*umEg-|#Jg`#Z;}FLA6>4O#R1 z_4g`x)-Db5=LX|*T#EA`^bN~`{CVOiJ~v~A-%L;(cYvGm$-w=L<5YKqTO0e9#!>jj z*U*08f4(RF;cEDH@co|(-1qmyuN;k6yDtVmQguRz3q$Z2I6U-xKU} z?^1a&0CpMJ_i&u*P=`~dC+9Lwh-3>t41NRn(=C2sF@7=$GP0lYl}oMsSGhNE$65L3 z#qxEoiSLD5$bW6%j;)5%DY6*19NheU;N;hOaO+kEyd#N!N&iUNM|!nkp!SL7?f_r+ z`9QaqXZWc9|2ancdNcWT%;&&~FO@qxk|Vv-p>Kx1D@XU&`1~T4ldB^Oz_0v5;QkU? zdBTTJC3C}sp&7_>@ZI+Zj;;Ajf6|ZFWjQKaHh`VHI&hz`Yh1fFdNvu6qOpAh{GzV} z?!6@=+u|1|7Dahkp);@g+WyV++rc(Jyzd;Ak3C@5fIY>=B%NPpXZF;mR)O98jlkVt z<6-Kcx|QZx;R#u6q+_e>SvSg_BtOz!g~-pkBd`bT_uxz0Jgsvb)_Qbu@;zZ)u!F7S7yk$7mkx{r|*}EU|%5Nb4;I>&?qd5FD zvD5c|aMOM;YFvow$R6`C*|`AxX7GR7Q|`7zE+)FA;QBZ2Ute1Xw(*CfayyM{ke=(3 z{$a2y!Jf9K{uZmh%n9#}KMMS{iD@55+V#Q&8TFSLU>jKw?(1Be<^>DDt^`}Oj#?7a zbJxx!dLNTsKZWysZ!Or)A2U}+ZfaxZcM^X;-fRWC9qhjHsPrbrJ8&;&Xh>y7?Ov12 zZxqKV;I?mOE@X8_?Y<>3QuBsRaBF`WIBu`X_HVXhB6|Z^F*FnF{(xZ5tl^7;DOTblr!*fS1?&L_0=&PVlg3jsc zOiw)j7kv=A+YA3N^bzbR;xGLZ<9&f2lHUYw2?fl1796YFM8?Dp%p6=3H+L!GyBPmATf zKmMD1R#Su1csT@LH+=84eD8y82fJch;I6Ubx1C3P zK=X(wR~LXCd6wtf+WuhV20LQgf~e7DOFum2-v#c6)(6X@xIzhZEXl3z#R znztAE&CnMY$XATopwIjx&-^a)A(@M7u5mg#;{2DL-Qe`h-rSfCPM2~?j-IVQ9lF{z zm6KfO6|a|s)3f(yg5y+IhSS_Yx?;an7PiImUbMMqbK_S@H735`C;c<~LH`>#ZU@NZ zTKu7Td<*!=e-GTpi|}1}d^h+-FOdTlZ}a-ES-fP=O7NX7beCJawdXx~`J2Hn9~0)! z;amJ68Q$m8o9PchsMmF8{#tvk#~w|tg9WK!vTFu>i$k8#Y5A<4bY{m`0=^6U`V!9& z|w6)M)UnFaMX0z}E!jBEzUpP)>8QsCtsj0s23=2O#bQjrL6`tn{lyb6k z6#q>O^L=9$GWc5bCg>v*c&;nQslK@W>$}#NEM|ciUl7xoj%0NB&jBL(l2|`x z=IEEi^i|L+*mr=X$Ms(QWDxo!=-X4obKFl z6~1lCD32aacYC6Nk+yXm|ieNeR>#rH*}4gsSNzkR8YQ^W<>mxEj_MZ z%A=;3&h1?pzqtn?_)FfNPVmbPFK(Mfk_Y`?$sRm($z2J4a&wrUd+Mrji47L{fC;w|+zN2Hy;T*0OuZj#N5Bn$8z|DB z?i@tzP@%ZAzJX_KTYNCv>s2gTpqJiU9Jl$FkGJ+YX+ z4f^EMis`xuak#UXUV*;qeZ}+^=nLjor>kA&i=Supb9yxEJF~baHa%|{#kmjMOrDWn zG}f$!zV)NU^o`ILUtdh$4!!ZFVtU<7`qOR2^k(SumKW38pzpq`nBE0_>Al7DKIn~K ztWH-PS3}>iHgq2z9Y=HDqx$@2a0|X3x?kA2p6OrVhHeT1U-3L_74J$BXHDpVIap7SoqPpRuW!z6N^VkBjM>pw|r*(|15` z`1fLZ`JL3=XN&1mpf~)!nBES(XL~VyA@nW(SxjFFy=|nJz6N^#%S%^eYu{@8Txqs ze#QOtl_J^CM6wmPA+Ym#9|K!nnH^fd@=^4i&_}*n(xuNCJ#JUUY4U9HaiHXWJ;u<@ zd^cR3_2UYVR`An)SIS?%9Ia{YlUC{M0<#{Bj?>tfwL~BEO}{VY$Cmh7Ge7>t^w(N` z&2=?AnSHU%;D(ShYOj)W&B144w4Yb*0ypoul3QoxMbD{7&jiTUN-OaKm&@T;pXe>n zhoLuEIq!~QExYH(^fN3ynS)2$y*?&=;2O7=+^dB7hf@ANR&qrtEFA;TmqBMZ&wPb`WlSFu{|G)>9pTZb zjXT9pN1AB)qwQ{2;k(HvkpIx1wEUX0KJG>M_L>1^$_u6Zx>UC+!7m%<#`J1BMDKy# z2!AfG%sx~<^fL5=z^45rx+T)fUl-FQE2YQ%N%^ov`d=!Ieh!2Bfws*3q^=^~IgCHx z-WPD3)GXh3!_!qgC94U{hB0IJDoeO_a1Fs&_up1ldY&NsgXGEHMc_tCWApca$Ky@~ z`tq25zLgW%bXFo`9hjN5V+-TA1^N`|3vC;Q7x@O1t-GKvuG_ayl{V@LxHGIR$H&h= zXqPond$)lr*BATL71MLq3r0R2k@&O}Ov41;lYo6`ThOK##Bo~#y%{>o`W#)$Va0V5 z^tQe5?|?pcFZ|^b$xGQ z=1-8EdX4fQ>8q_SGq(+v64YqvkhGa zzw;Nje@s8l(rG&xUE#Yf=9h-n8Ym4-~dMximFc`@?XIujFwa%T)`n-8;e(d)9Dv|RQ*qgwte8X7x zD934Dng^#S_u9bhK9YClSPc4-JvP02w9Gq^Dx>Jy4%FD$2Ym|k(dS3lqIRpGRiGVe z`=FgyU7>ERlQh}pqGGTWzPdM$brUUL@Xgr&@Dy6*HTi!A@zsKbJ za5R7l(*b7ZUNF+P2+X9nj?JHA(8&;mJYG)=w*p-AK5&ZtAh;HA;z`@*Y~=A#^kL|| z$Bl}unR}Et!QKsh^f?cS6Mqx*WzehbHA`nJbji<+>1n?WTNG!>SqQG7mG>rboZ4yb zOIQlM4!W=@UGq{k?X1Wj=^FsY3lH{+lZ>t4cFnG?PdT?6`gZ8*BB?$O#oKTy{Lpga zcU%jV<1<9ZhR@jXCG)vYKC3x}T>!R&&dTHJGCg5>qmo8G-`S=>UIup2oU!gUHC|G; zY_1Qc-Q4%J4d91P8=JotExGr=JTFFe>;T*IuCeY2TQ^S3&Xa|QNH%#6w&66!$1|u4 zwtiSUZpiA0;?)LzH}BY*z;SA~*&FJDzI6Vm`kHcqVsnzVwo@j$0QpnaN&q zde1m{x;kMPNDj0r_p*}e6kHyE6Zcd3w+2}a z-Hds546*HZpk@-$wPK3tR`7MaKkVRK-j$NnOmu1lmu^3jH^VoX4WtqHT8s3&Rl`=) zZY^LZe`sv}{CO}Ei>#``ulIZ4+W{Y9(tp|qSjP9meE(nRx6!`GYQA53UX5;R%-Y0^ z*Wr|CE+)T+z>Zv0li!E3ZSJ2*m9%-3OR6j7)48sqw4wt;7&m&KleW=}6LGOnC zR8e1CpY=ugF$BKy-5UR#$y8pl=KO$H>({G#A9WA7iB>PizW=|QdJT=&LuNMFTx%*J zD2ko%ZQ!>)T9bdKq8}Rrt!fnPB+tC=9`KEWHG7OXlC>OK3$&7rooVaf52TbesGhm z-DaM#Fs8rW(vfpk%)b=+YWQ>c7>~J%_nMghb#{!%#$1=ok~J+Ceyi}?YutTSUy45; z)akTla2^M~eadXoH2g=6JKN&p_7QqE=xNZVgX;jd%;HRbO22Z+Z)<>2Y`WlC15Z(G z`eJ%fY*s^G5B~vHr$!(?D`z&w{2#M@#M8D!c>6h zJ?}GkXkhNTA?<^l8`Xd5Z2`07Pc`}LvrH_)`BDD){0F;nq$a=T7UgwvRi>{!%fZe6 zbB%kY&1ow$OnPe++d=RhFI3MP#eNui3-qGcm*z(FqS)*G^^#x2-x|}a@hcA(K=0l; zsvf6#sCkFa7A;n-5$6g7tdjE%l=-If1Ybn zcQn72dQ*QUQ+PImUu@;Z_zQr)3%J&`@~s7I(@Ql~?J9%=gyV>@|G&jPJsrM)@tHCXPIq&kb zxFjwQ0yZzr*TH@LvY6 zZgB~Jq05df;1?gV@3?9(9)4x5d#svVHK`vW7I?w(c^dd7ht|4#E#A~7O|MQ=Q^f0U z<<0_lM&Nm+jfvq2>!TX!^I!Jx;MMB!3;u+7wVU605`F{tp;z%PM{7?Umn#9c%9bcC zd~F>8KmFCU?h94$LDIh>cRjxHe%9OIe_Rd!+1Q#G-w37yeCJ`j!_nf&56zv_F5S=< zK|jROlM)z@^$pPa!OeUf?^Lunj-_J&S}(L}^W}EvL(n%LS?hjad4ptBPEHyndqt`| z3aKV4`kS0jjtXK08BLlHOy~WeRvte2N2v0h+Mx~1Ofb&2u^E4Z-^Jp=R`~4!Uw%ui zo6m9D=OojQ0#OdH0Mql1TK7SVNpfD-Z}Gk2F$iumxak&$Eajr;!_Y^d&m2X+0(yn- zO6Ra2_0Ca!Yf)yeWHf`>3g#dyLt_V@MQ@Agvn*YukHgI~E?x(8ZuFr6F^Re%^T6c+UzpQSZ zqaLdGP6M~(v|7g_!ZSZiU-oMg4Lq{JSJD|?CBWlcXZU=Gr(>I`!>jDj-wS8+Sm&0N9Pv35@BjJu&wFlj=YCVa!o$=@lt-Q5wgq+W zTB|>blhQ-Y>til#FW8|8b@}U*BdiK_ik07Mz&2EB-P^5P6)`@`zD>~E4ybc)wsic~ z{*BG4o#5Q0=$h^HT)NKLGhj&16s3__n^9HeV*h&bnSpfut$H49O34HTelCK z^eq850!}=sJ!fY2tb*<)7t;r!PudH87#Te|Cn5H?bOCh@dd1RBJeu}Gm(8uv z-63_3Qk&&la{pg6jC$V|g6nxD@7J}sY@X@oG?KR*+y-!@XeKYi`B|ZG>%r9>S{L1m zaZ-HEM4FGmhw;$2=Pr9G za!qXt{ayZ@@C4~PMtU~Ex8*%`PTf1TCz(5FuOw6B_3Q@Ud^Ybp4h`Onv%$SFPuP}j zI7rX*F6O!C*16AG`wU;$E1whu`~bfI{D$**U$Mm-fBdt|WLq%oV;~*<@GM*~s)i=M zB&+*)eWcvn2!1{In>gOXcU@D@*OEH|Ztx3r`De)|a+7lo(R9pJz*jy%PVnyQTut@0 zPN9$LWhvD7oHD( zDT}{iGYr1+NS*s-z=x!N`!ObbB57FJS-zNj_pOM!|T}aL^Y5AdCNcvmyH^Hgx5mVuJJ#u#;SKE21+-U6dEvQ&- z1GDJYyi40+%$}@X1SIE7wnV!CoL)gO6PwdZE&%b|bN z+GlI6W}why>u#{y3uKAjcp2l#Ug$HSZ`=!g9`tnubhY_n=&Pao^+b|;NiB|+gWk?n z;M_ZlV>$?Zq(G1S7>2%WFZ9yo+CQi+e+v9f&^JK;CC6!-o4OcmAg0l9=k4tT-@O-m z7eSxD7y5GO9ebeE8UUvnha4+;`=<^Eb%8@qc?a=opN90!z_}wkk zN?WU=y8G=Un`HM&aFdU#UhmYF8=#k;#MTqeoN^ z%2(n?0bRPLKwo#txcpuMW2N85(y($Iiogjw7wo1R$K~(g&FXn_YTD03mw>JGjdS0z zv9LAk@5uGj-F^t*llc-2-;!UE>PpCH*nI+Pp+18|jxA!*=#b0{6 z!RRb%D#KCw{)Z5`5GDjLSdoDZwju{rL&a)}r>^41Vavaqj9Wc3c2T=kBz% zE1P$NZQec3wOK6rZ1>=VYeHBDxMN4*w5Km~HH{Ij9b6Z<1s0ds8t)^i?G}Ms$yLJD z=0c(`hrSGYwYC#|Ag1T+4x&kj=tIyqz<(6SX>OQte<$>9d!bL(hWnUe`=&!5f&a}` zzJkGL#i0}WB={?quEmhL?(q>$b}j~22TpxCwUhX(ohp2_0(t}V+eguZzD&jjFiXHp zwiq+N-xkx0`jPt(@!ku6C8k&7pN`HJ=&Rr#DX3lHx3m^hmZT-m``ZKG4qm$UCA%g| z>tpDj%pfjpQz>lfJ8R(Ssvlqd+?8T7s_$$Cza4y+jZLaUlU_;o*YWwjR_>u6&l{iL zcS`bCJKv+^&jjBG{t+ub!GAgyuU$;&vVS4?hWC$Z&jhdep3I5y%A*zFd%(ZV$|pZG zuE~_7-wlFWwhvqd89TtO26wdNCHr8=(@I|F3WS;TVdm#x-Z2W}7h7PIx6{FF15=c9 zoiV*y&L|FxppU@+m~@Pu_sS`~87{sNRrpolmz_P{U1RZSI|eF#ikw!?evBIe?=Bjj zfA4G@=cESeRIy^L6XdO6bG2kt4V2H#;1+@_^0_Uh7x~-;z5N5@-A3sg?eoPLqx08s z4U^CP;CF!ky2WQcC)wqFmVFz+FTS|gzU?u+ntkH0Be+Z9*KukeaZuS(oSI|$F{9{; zr-HAcSG*nIruS8^-SVqDrhlx44@n%%oFy!kVu?{LT?u~p_VIgMlbJ03l`a)TZ3MR) z+$@e$xqd#WGhvae9blT5jd!oLnD@l$=6IO*fAV7158#T%pXt!oeyTcMK6b|RcNNVo z?$72H!Y={8?bGA;Yk#yE`~dilJIA{{PhY+&G~5Td%Ta> zh`32Cidt7x&jZn?#q?^ikuM!FeUYu}wtfBk{gg4Z1^8a@%kLTQPO|vezHo9rPHVuf zTRA?zk7s3nHp90edn@>^`^LM|)Zo?P^i(o71?o>Kso{x-CP$~Ii73CCIUzmo3F25Z zw>@uc9L&hCx!^Z#9`E|#O?7AeH<=CiabXGAX+ItBerEH<`t|8Bl`UHaz;7EGpWjb4 z_+Whs_vieF!LR-Kcz36@CAr)o`J0^YQ!O&%&`fxmIFUE$7vuBK`%OB&az}Vgzw|ee zb1k3YRU0pWe;NEdIwFfj(#Gbw?8>iYV3+*ccy}1bY22tong>+)YAy6dTgT_Gp@n`0 zbTyzbLtxf|S-`QCp%X&FsGjWtv-Lm8jZv6nFws<8^P5U9>&xfIyC-aZnplT(lAO~9 zt)xe_W-fdy{xE6|ik->Uz3Qc6(+h3@+@(eG{T+|w2iP@WyLOJxU)P@IRM?edv!*I) z3faF6p25G2&tErh?f-_jgwE`jT@BYUp8W54mwUHIa$m^}2~Xr}E7(adjdy2`fidZ4 zyjMDWYlf4|h2Ywl_5aM`5}EgBShY_-*xh65^X~_g%=czE^@R=KI>UOmwkUoVChZfS z{{TNUw%)zH2>+K%zHF|1obji&-u=D^KP3549NNM5Ppx;)S^u*3d0LWX^CEEbr_~of zGx4>V4T{Ao@RLrhcf5`#i!Zqp{4H)ezLwlg;MzLs-6CypB<*0^`iu!FgYdh-_rJg1 z?JC0mTOL2SR$bDejZ>V?w zZe!=i@6bP?Qu5Y-X}Gbz_?e4mD{fKE*#dSRFBQHyG`iDs$l)832rIs&CFId9_3kjM zJHs9zYz5pDaO;-VyT4kTu7@6p^a|4fX8CRP?(-a{F$$LD;<5-#<@S1auWe5oms_Kp zlFut8@00X{qH(87<4)xBCa~K-Q=h+A*~)E=D~}X1(K)+gS{vw)~zfkh~r+^S)j0PPTs8`%B&t`BeeC3hd@z z)w}6dcO-9$v`XGaFgyOe-tl;tOsDZDd{s0j5_Tupk>Az3l~$gO(`}hAl}|8!Jy)N9 z=ed7Bh-zlk?^?lZ0Q33+dBHA>jNq<<{zbxXFP14A`@uB+N4@*HjbWCP7b%V>VS%uN zVAnoh?>=p@NnJf&$Wv2WN5D4yvEF^o+M0~T{;fP3!!$ZY?OwT&{QDF26+LM_n?4^s z{Wrq4gKZe8cURjsuyH*B+BYEc6mfhfo!OOq29ipvEKgU}JeF%E) z+6Lt;Ng4&mKfgmV{pH&7X%L$-!m!q?K!P;5(q93A+Mp zb3@sEx5S5PI{qc9Cl$yWWp86Se_gKPc8uZ{<>?ME+h0|7V{FY4#*g1oA5=UiFD0K3 zE4zLhC;C))vt&g$**6nh+iS}1PaLQASzoqgzI1^tzqah|u`+GEmPU4}uPz7Mdw4m& z*W`D4qM9-g({u0Dw0bpmM`rrA90tF(shq#pQUwBC@}qPs{z6||WZT7&ZEE*vV4GfF zb`KS`$u~9L`1JfjVugI_f^Wqe%lZ2Pbj=Gi(fgpUhkgvlX)JXjf{(IsHT12}zi->l z#&50kM%W>+z5i5pzqK{pVmC*1U2=8tVCz4Z-7@RDiDh(sT4duCu&du(-3Q5PhrSW| zGgg+>`(zZyDPViRE}mX4o~xzr0*u;xHTX4eE$8pE&ibxy8&}Y;Q4o~FTfi?px}4wF zOcubiqPPmDlM4gjPSJ7F#}b@M2w$sxn!#-aSGKsgZprsH=$oK(x*?OJHOjfjP%i5F zJ4hPK7lEzJD7&Kz;uQQFSf4_X0g}HOo+)pmE?OSjPUR@J@@Yu&-(J?Kjm(yG&K6x* zQGv7@To1TQEzZv?g9~J>^1ZT*`U>Xv1$qNrpCwzvx61(E>tyd-_!iGByK}86!j5olZ~(G*H_2l)vr6iF6u5DnsztMo}; z<8tJEwCv8dxI|t@Bu{PL3a;g2Wyh;0Guusm1dk%oR|fO~Spo(>96f&Yz`Q z`PmO<>2+n-WpzjKNY()UDH|2AgJ3s*d{pgK8~DgY{d7B+Dc3V@D^ZemG&Y8J*QG|v z_l8e1-Yg|=to}4cp|7^GvjyC$Tg&cri?ecDvbZk9W-)xKq$_g@NIx^NkN>0>k|=w@VZoo`rv82eu5rHnCYSobqisIuU12E zhpzTcZ8;;B!&j2A3CvtDFIY_Q$5h7-=zX_NsJiwNf0;(^DWI!8r$Fz5{$ndY9=n23 zwOw(T2fnX=LjHa!jWIGw&6sSto9p)rOrhm!Frc1GoNj6Wm=EXWP+F zN2KIqX^@m-Bk(odJHat5WN}P%dL0 zxHgDbrtZN!8biV!Chu! z5Z;?Qq_)}#ru&Bz3fCW@e}7<<_mvgQSAR6YU00O%muI!L9qjfeC%7F}x7pK{nMy6i zst4@WU}FAWrTC!%@}nPm``C&3`-L^8%V+4qtOv8Jc4FbRI`VZJn88;~bid^|jd>D3 zts3KgBW(F|b`qS|dP^sUEFbU!bO+o_TjDOc|H zfnR#sM7NpaJ?wle@>zPXQF=0k6~Vxs#!$0>gj|ED9rWLF=!DT^n%P1SI#!KtIgZ7;d& zz;6QodW%eJYVZEvTMu-H9tv4|Dat3=Ipfbxj~I2OaNS>CO8UGX&yslrenaoz zcOKZsgnj;-e|af+H{>+`ZpizycSBC|a(lt;27j>dKLMY}*3>P|Y3X0h@9=*`@=M<| zINGo~hRRmu-4rGcM`3&EK7;df?l4RWh-B{Ow`HeuwZcARu%@r5-f6wq{1@l1WhlL9 za7k=uXSM?OF`Em|0(f-qc2ZpX3_37viK~Yb$#b<=r{4Vbf=-m>meY%#y22u;6>-IWnVZKM?3HB ztiiN4k}2Y8hi6+j#{Hxoo*Rv9%X9ho)E&jP7oPSL$2cCV;!1ZL9@7TlKTA)P4Dw+B zp0;zw_*^SpYk0_o;m3^*1kvAugv+|~Z+W_wE;(1dZ zr^TEslsw&sx&@r?lLzE+sy7L4F}RTg_uMzK+>h&$aEp<*3S8a%F|O<7=zYTAOk4vE z-eL%^RzX(vNY26px&>Nag#M9{{>VS^T1S3g&wsU|Hi12z4BzNhem0fZ5BFk{$Izq`D)XX4c^+Ty$9I~UOav9wEldIOlGZjKSO7 z{B5461D>sQfvcda^r+#n>(gP)H6rJI|A(jNFy478KkhX=iCwSG>lgsve|F$LD!Z;V zc&o!-ZKbQAn3xABkTi?&m+tm)wZ?BBrk6Sv@ z@EE%S%>m+eSH13q=dV`V-vz$)L$Uma ztKw7nO~~XiB5u)=AR2S;FnI4P0RE}pYyh|LQ@n>(?R1O5nRW^uP9hVH0XyO8x+8EO z7S9vLSHq)tH`XDa%`lI)220{Ctc(bnn>dV4Lp? z+>O{%I?Q0H+u2(gqV|~&b}86@k-hZ>YhoQv$@in>@YH=Va6cB$5d}P_7#_uc8f(7YUkUtuNu{F=Pt*s`CH@*sTm|eru)Plj zem+{VF^zLr{iqkrriTN6KCJX6BQKth1dk^z8pU%h_%%!bPL-b)Z~P2?oAJnwVR&|N z0gm=cayb*%KJ}wI<}8c86}T~swWV{69Y${W{$!MkY?%p9$9nn)wKbQwW}FL$bZ$FJ z_J!!_hG)(90{3(ATw?SXp5VPx-IY^au$-*rxPZBWp+4SiD{kM+H1>cc-sUq>1LHpTjEJ^Baf+kn0)Ka2Gp z`j7W-8k-_(cmRcOzXu=A>i$2-zm@2l^6OaNG5>gdlP2QdZv!`|{Cx3iRsAC$KTHmO zj^89bujROBsyk!qwBUUlUQT*`Y+vc=^RpLyjoV{=xBTPvji7JoAE>SJZ_fX%zKeZa z=#o+Q^Upq=e*otz{)-yHe54ds*LN8aqw5BzPIXsIb?0z&E5Au-Jb@F9z;6)P~X{U(MP#dH39gv|Rc5 zMTH4^d3RhF=d8`}d#Q_^@NEBk5Y6SUH9AZm2{+{HVjnz{S%`f_?Q%_Z9u>l?@%@u~ zM(30`I;x8&lXxHS#Sq`SVs~IoBcZyu3w;a5#ro?1@%p+BWZla9#=U=cn>d=7{9pRF z1%0K-vA#F`$9c-p?w)7Qm*^i6+5tncoxRE_8VrM|k!%zvixerEZ1*8g99 z6eEhE>3(OK?&s@b5Bdg<3f(`cE*@H4pQ($BqPlpq3GIhD2BEr0Ac7O8V!sOrc-r@q znbEtay1mxLY1D%{_Ev_D3H`ImOHchv7H?bU?#s`gXTq~`786FT!=EVNxhc=n4bQ^a zv7So`ct+`21y6%sI3+#j7w{N8+IQLl&+tj1J6b$v8J=Wbt-WRcocNEX1}YAdUO~M- zC3KgI?_|Sg`f<1^W$|M~D?DAio7(dnynj4B@CLZZ2|Y+D15HrG7Q zPu65@WNjP8vkjh^XN2xb<@F;4JU3_iG14=c&FIxV%C2u3o+J-+j>G4{r&31gYG9*zh!+O1h2lyN7(N^8pQS8558B~rxj5#z zYX5k8;aRgVbnlU#a|(FAme(@?&#ud2o;U3u&vtlPuLvEl-EpOZ3wZkSdC+(W{riKV z`>1%1D&R5qbSiEg@a(uI^yh9%rxoxtWO*Q-CGhlrEcExzmS!6s+pfRK$6y^i1HGY} zuYJZN3V3R=IhOS7fM?s1(9Q8R*YMaj{hBs^vp!dOCF^}|zG{=6V+@bA?T`7mb;8qd zd+6p#&yj}5>iK=9rw7~m;A#DI=vowO8#klpTdCt1Cu#bXR5;ml^OZ zUlIEEb(Nke;JF}cGxhg{@JzcW^yhm@PZ*wbk1RT4EiL`vSAbu}yXK!%93L@wW0zua zauknCrn(NIplHmQ>Q3X30kLQ5BvuRze;OQH6|qSRIO03@5hn3H115trON&X2*a1T} zgDDG)Gx?xfe`U+@h=M7N*%EAwA~8qnhSpNH>fx4wU&-Gc+++SVN~0(WK+|q?LNZc9N&0k zsXm-E)m<`ml6cf!^L*n4G~n5MBKy_s5VU%n6*b=trum3v7CFUj7xpb54E=q%rSE;`O@k{(2C$vI|e;j70?b?5VylJ5O}QL2aR zD6{B~%8z=YK3<&a6klthvL78 z4Yu)1?j^+o9pPQzNOe}%7@=N-KJi^1b(N3t>5IU=6pQ0)B1~b?j2<(C>-=J!Z94K( zUd6ltj8a1`U(KHz`2A}}Y(ZiV5*PaEFv*S8v}qaHj1yNFwutL5o)ugijY|7xnb0$hgW!dF%r^{v8CzAZCl4Z)D%4->i#*|#3_BphA zoRa)`ANlhcZx|PqPIa^iW)g`H47X)P5uP;Oq~?Y zj+_gwm^z8VMsZ9Yxil| zs04rTNp|Jbj(}XCweaR#FP+v;;>lo3Az}2S*P@y{L<0GT4IB{H;L@oM5LpQqjY66B z_GwPgdpPsoNxY|BbB{}meaU{DIsc*lvKIWphLYn|-^`Z{-uQzxQt8hhw3EB9B3$Iu zHF$wR{9r3yTpZ^EreP%h;WP(?lW%a8jPqvtI5s!2zG*DERf^-`)%9K(#ZmdEq((~; z$M8T*K!XBFW$g0tiPY^8PSW%LF_4POM(k_l!qVpymnZJea>vAlHt}(}jlXkzG$hEx8`G-|a@P$=UGmY#uldo<;D?omO(6(3o2x&EWG>uH29y`KGo zV@j@7J{)E6>D(qr??e=SI`~~PV|=)8`~vU|?~L(JeKBjB0{P3q&p0;5-?wl4Ao#g0 zG5)H3<9CAZnHA$_?;GEA1naZoV*Ek-#&?2WH#^2ZyK0~QE&;!#HO4=@Z~OrGUB}1x z>-UWx2H!9z#=m>t_{p5;oxy_7=fmOq#dt!`#;l6$Py9j*GNiqJ>edAYw?>{-l z-?4A}5cqZNG5-90<4bQK{-?zFqxOxT4u03EF+SWkegXIfZj|%!eCiAPjL&lLGu{>B z@7p(i5d7TJWBgV7#_t5*^X?cwd*Aq`Hxhp?>hks^FlO6z*w*v)6Oo6ElF34IS_-JU^Cwr{NhTy9eA5I4}EJgDa3tmv(F5 zS$R>(zw@GWj^Xj^o%Hf4zb~)_Y^kf{ekj{#8?2RoUuL`Hm;VX*@Z2h%mrVSs$e#hW z^nqCZvj$rrU-4WBPs^nx_fE}k?=v>pxq`pDLoFKZZ>)r;y}RV^aV$MloyWhQGh*?+ z55d!XMalhG^NYKy^MuFd_aN(-Fb`f8>zPxXXSAM~@T^=^^6$qiT~(bYdPYlR98ID* zwA;ahWwt8D=Nq16Kl<*hO%$`0;8%RGjAguvoY@4 zV%$n_^H#;UGmCK>!F7Hy#vNIV8v(cQ{*t>6pGx&6{-gYDAoxQG&gS%s+5V8-7UJu{Fg$G!$2{-eKc0p+6OVzCe->cr$O0a- zHkEDd@N|E@fJfF|&X*`N}e=FuWYyWsU;92qQlB-D1F$Fwd$n?x0ZcE_l< z$BrfE!lQKY?_iGVsq%3Hyp7*s&xGULy4>ejpc3YjOxPV@w}G7`J+)>HPmTvKWj3ka zHB1MywG>@5`GRRne{Wl)znyWc1>EkxmfVhG!2iwQ%vyG~-vZK(=>;rmS<12v!rmuC z!3lm#mHiNH^y_4emgwJz&PbSV?&jN1q};&RW{J49&%}lja)SRzjzY(}{&KG(S|YQZ zpxspV?85g$Vgn-hGRJ3V`TrQd$he3<>~{oT;rFRzH=1n$FUx;BsO@(b{E6SoyaC}s z;=hSsn6M_S2_i$-EntHK^I4Z;fVAHdX@4age1o#^JPz4o3I4_}do}3hhE|Rx?;*dt z8vYNTP>2Jj6YVKH*B1R?xzK7fxT zBys>CJkqt$AMlabMPdPCDl&m_%>N+yh66DCuNu1SXzIt2W4Z5H{mIk<)1Sg;?oB)E zVt5AO>3L?XJ6`k3=c->z6I}1F3Di#WdEUw{9r)fDZT{ibCEgq?Qt zHSUGFQFd7!pO=oP7K*1Go{{p0-37d_$@cohGXl@uTJa zwVtp%Y3#x~)TVkmrF3+H-*QBaJG=(`$wr5b!?x`Fe+8aCc!szb>|~Bh_g$CG!~HnM zdYtdqfN{sxxc6xMdXtfB$H`=_5a4WF0)KK2qbJQY^k} zc+&fiqWAbJJJlxJ!7t}w{ohlYJZSL7mq6EqMd|GAYMjY@_l6q(oa)j;hR4J^de%zB zq&Dh+r}4%b|E$i^1J!wg6|tUCZL}2L4ShB4gNnl~hS%D7R%WB(umPU(vKs$hozmlm zC*JE$pKb!y=Rf$ZD{I`NW6|*wgSWYPa(0fg0$blYTP2_+oQ&wWZnKqrbBbhx!{Ms zS>uLezs;Q(pWObbHe3R>Z(WUlE^z5?BRj1x>BDNg{R80pzg6S7{E0Ec;H~}RGy8r1 z!!x|TCc4k)dc$LKIarhVpj>V|mioM*#x0f4mlz(Ck70TrmKsnO(nWbT7v7zNHBOg@ zmgX2G|YQ%+$Ab!qfkJjemD$>5)6L z{(M3Ti|XGjz<;Q5cghEAkCi<)^Fi&=0ngI^s&QRv!#j*U*)^R{C0b-lFZfM6V_S|a zwq-TA*1y!ad*o+9KMzZppNi*Jc-H>C#+|O3Z~Lst`S6X|xFViO$H7;sb>EjBTN`W} zv}JnK*IVJ~nOGaGLGSI);yG#!D*4@D*Mr^8ap@ToA7fMSwIo7OzgPuN-=tc9El|!6 zW0QT3u=H$!XVHPR{@FZ*i_a$h_p8<9NEVuG;4%hf$ zYzou6;v+v6O8(1h-81t2D#K%a|5BnQ;#mpLZg`#(&zS{0$>oh;WZMut>t0dojvWKf zF$Fwky)T}+R_1LDv2FI6=e^iA6CQU+9OF6WI!_aWz{FVnqZ^*B@U(>3X0J!i<}DkN z9xnV!@H-k~{EbFO0e&<1-G{~aGxv_~LB2blc4y-Clco#L-x}S1fddXaWsb>rQOFoB&!LEA){fED$=M2`?v9pg&nUoI= zConE^@#6dI;JLnFzWn9dlt(tT!?U)h*1xAM#}n6eB_J|sam&Ab+$H-4YS)Rd`<2GJA6m2e>ZIDZ>BEUoLH94p(K9=Jexlq*YRfz zkL>=h%tys#BiO;aY8|JjSbrF-m49G1R}s%{csATy>+}N8(!&Kj|D5%4@k~33`OTMW z-Hp=oL;=q`GCgYJ1@LVDN?em4HG9NWYPkGf4u02HYxPP$<~l})a@FLVWN!f5{4 zMf;XL0)F1tW7+oJgi*5PYa^QxYr)P@KR(FVVPpF8d_V4hXVW9K?scl^wT8#m+TUmG zEImu$+4!%t^Fi?Zt)M>tPkzp|4xXl`;{N=Cxh8s4f0q1Vu>D}YO;;7jA7xWRJMHlE zTK6{9+#)}=Wc5gT+TmID+gex0eq`ye0^dLM<}`8D*1hm7JftpqmPWm)z0sWOj0CK< zUITVB*ha8;3U6Jd&fOqhyH>Ytenvi4J@70zyv{!-u4LDvCbxnIQZ-)B8hBh&%yXLY zzko+E+Xl~ic)q5X9a)_xTq(bzx#Of$X~!e#+?ytVKf>UxFISgS!xXz#c)H$R=Uyuv zb`5Im;zD|OP9S#I08hn_xhSb07OZ$p1wR4>mObzaZZ zOZhVbw(+hy|L(2QX$5)?N_tV06HOiL7u{XwJ_mp4=;}P#4o$=}7oGulzA7Gjf3NW; zxH%1hpQ9{=r)5Q*f0ldcB@;J|cgJN|`LPb{BCro??0wc?ZHzyW_hSb7%eV8sQSyad1$H}Fzn5sS%8Og_d9fMn zibw0BXSP|awZ)&Uh-^_zOYbKBkJY(@>NuWVJwD;Dvw4tgngP$ylXcO&)z-Xtj;!Zh zOM~Pu0K4wTb#9h&=#m2YAI@@Um~o_E@;BGHAH5l#a}1BkZ%#ex1T5zygD?5>lAOTf zgk!)T)}Jg`b;lK_0XXRQSN!V~H|HY#mHGe6-yPB2V>+SB+LUvlELb@^cy%QAY`(tA zAM%C2GvdyOz==SX!NG6%{RF?C@)=6DCSX&b-BSuy-_q3($NEm#-QneA`U6|h`tCG zeM4{}Fcw5Ge^mnC;V{8NFFqtY2%bHPEz*zx3-+M}5L-TYh8ui?O&mwTC}IWC=LbfmNKX#Z*^xC*$9s%r&%XW)G_OIke54;1lu^;D{ zHAxjegkKGQ6%XlKFPonEWVXkg;M+1Egx>;w`nYj!o$!xVk>8r(XMm}DFZPtRaTh#0e>Bd$ej+?CRDV8H_~-ofEmP)^zrP;m4py5#Xr7s6+nkqACg<7| zyZP|6|9)KboP@g#PrBa9p2;n{mVux0pW|G=^8HSOH@?{YO7RTB)BneD?%D=;9<9z3 ze(DveUFx&D;2EwNugkwVM`E7Kc3uked&8CYbN&Gwr_5QO8XWV~i-D>d$j>%#t0wS1 zbJf{;gG>DkzMV*x%{|};4jAw1R67fv3&$0P35&O74Lr*ZjBUQr_&LhvA#nZR-XWVW zH#lRnY}gHM{t4sVbIQ|u4bH?mx^63~EfsjCoy~fk2Ya%m#Pb2)pVd0QrxL9D?4 z^SoklQGwi#XTHgnK6s{|Gu}O;eTO2ROS63k@vMhu?Um!*<;sfGpc!KLNO`SDp&&5J7_G|oez2kA^)XwU>;nIArPKRgp zf7Sc^7%dt}Q}@Et+feNF8++u)7;;fJ&StTBHBJX?9M z@Mjex+n?Lm8~9+}*BxLhuPwV5)b|fAkpFOY9#Ju^oKO8ff_KAmnxyoisb!|!!pE{P zPd0VJv--%gyI(dvZ+N18=TF5Ua{U4Gf3Q=gmEE6@1N)T08lUx0JO3n!pZnzptD}$c zg|3%o8Nq^sb&#Gyq1AnO!5EgUtS1-qnZ=bB=30mc-{Y5s8W7egu>_W2EJ#>0aS-%+ z*(`cs)?;P3F<$FhT{y3ch3J~!FzcdRr^ZnU;9}IHfw<@q2@Q1xsEX?FMB6$BV$4_%`Gu-%~n5^_B zhTjqC27bQ}xl13u!|%WFdkep7`BD!H3CHR`|2!954p;Dr*b#~g`~hoIZBIn2PXOn7 z8VC4GaHIeEs6Z(;0joZ3y;uC0v^$J69@4<5)i`3A$?}tL`2o$x=s36&$lX46;TLJA zu#N~2U@+nPqF~5MS`5>D&1$@mddxc~Ysk~mp(ZzN?vHvdSqD4|ujDIA zx$hEq+7^|gz3&g1YoM&2H}1Ljt^T^`S4yvUv_^JDlDc;?>DJJ03A zy+)6z0pa^HALREscm_UMb|=-qb8P|7Z?jq^zjwg1`OetyXUv+-_$}PzF3v}SQ!Ojq zZe*MFzi2bTb>CHXPYd@UgFET^(rsa|JPEq&?E>5M*|Pg+?OyD?DSs|?h2(#}>|QM% zYln@?S(%U0vl*UwtIO^k;wg+}UQg)**!NJ`wTs8Lnbk8cuV)54OTJNd4R!F?+^{^a z&&CDWwh*4~@9=JO@%+TZ%krF-=UEBQ(jS!FO|tEo0-oJ@e}>@M{$$y4xdG=%3wUbs zdg?A_-1>R+KKIf~hR4on`jZxouB(^{&j>tBsX1?Lc%pG`c7oPirVDJ-FUrxibx#{? zvWC7SK}Xl1^n+gl-k(#n@%6I9+N6R6JK@uW10BBo;aj|=?B;5Wf6(Z$F*f&Lh^KT3 z?=2C}40r~&mECsLhN7HVpUqWN=N7`#`@6W#-EM3%dcuM_w;JBg zKbGCcr0-6{YyJ9OzD8_?r{x9oDc`Os;5j?vQ9DgqNc?IhME65KV0e;t(nU5=x%2g* z1^k*x6CA3z=EvYQ|C*CwC3_**5wNpEu$LID@jp2`tQfBVKWXv=H%UI9WAN5z^DZ6L zuFdf5ICw%dH+?#PE;N~&HiO#*uGA2{JFs-Hk?m_2&nt>eSGzS`%Kq3ZCq(1ZOQvob zyQ{UE?3oYm*4Ltk<5I2B!(4d*I+VKdwGZ4*a7~&k|Eao;^nIh?W!HLmDzBU1UaojP zU7aWFPukbt3E_K+^zDLo2`BmQl)lFeuZ`^`NfaV|Q!Zn@{m&EJPc=?GV0dgCJ|%rp zlkN8^-d*r6IA%ihE|5D6Z!}gUZ}s#!wH)kru)gnKW3a?5d@8d^ery1{;~f*+H)PW} z25W6PHHkq~BX+{G>;EI}UBII#vasP9NFY%{2L+AmEh?~ype9N*BMfFt0zEQ=@q*$i z8ZRJTL6{*ZpaU~wXxnyK6=mIZmtEI2yXqQOxrhRj07*brBVIsI35e3;c!{DRpfcb4 zR`uK>`>o&e`22q!n69cm=hUfFr%qL!y7aZ6&$YF&X*lU+zidcSd50sPqG{m&cX_s2 z%4=&{JtpU3z0XZ>M)-++@{0Ilj8=zl>uCr}|yi zp$9mP_{QiXltDUN&0=TX|{xX zyaTwLH}Y&~;_yYL(Pq856H=9JftSU20Q+~^kgwA8I<4RD9Z1dpSr;RK)9`Md?Hl&7 zAE)7@*Y)EZFVPO92A7oUbl{Hq0R0Q=ac3HCx*m>9^_wjB-+(i_!?NjpGw)_d*mSnJ z&4613IDUIEqmNAZ8%i?e`2*k^cU$tjE$xohG)^5!Eae#j>^8uPy+3siq|fI5K0Z^QPw+uL-&Y& z1MI{@dA92b`-e1Gu}`>n@{3a}-%`N-F>aMF{eIB2I%3_o0q$kM@q61D>rsh&6cf%0 zz_L!e0l(hX-}Vx9_`mf5*HDM$U}qF?hWp{4>f7HoiFsVvlW*}wUn+d^Lub7fCDBEm zw*$W;x4-z-ch)&+_~~_!*5@KiTg}9E_{Wg^Qw`@OIRk8}k$n*#j&9!|RnP9)pKnvc z5npb+LpeD>$aU5e@TUm)vS0C0d`Q(g)ut~mP@B4YtM(T4twX+nAh6mZkQ48iqMTfn z!r!NybTHujLwt)@hV!=V zhvMeH@Tw*I8DQHdfg{qLGUZI=rBo5TTS>b^A&fHd`=mSHf#h)o$%g zHM~&?{TpGgw!s^YD51ZL^mo)(?8Amtjveo*bkE;oV{weD;=x0G{55XJ2mW#H8?XDo ztJigUw699LJla9?Qta+RWDS%7^4M-(DB~Wj%j}DeW+jXT>STwajUoNkv7Lz9qTEkg z(bZ!2pMc+9N~jodt#f~SLqGq((jC>Md!oCt1Vn!&oX2-M(`%r9dA-rY*aO)7NGMF#KEpdo4iET!c&pp8(g}vG`sc&e@>`y)RH)Fj@;~w3=P}Qp!soLu4g2{P}ZhMQ@xZVz8%*PHoTcBi82aqsg zu(m(A7X^B%E<8}K$t#uR5v{txqwTKJ z?`Vh}m89o(e55R(Gg}=wVUZFXijc>cx6-45*ZEZ#d zaipuk0~Kzia!Uh#tF{2d8{VU8{zb||Z(B+m!Y8t9fq4u2dGuw}HKl$(5~c)Kvotm( z6cuHuUZ@&*%};z6M}uo}D=(~9?b}e6Ht1NJsxM=CAo2r*rS5XCrpMu5;{OeGRG-&q z_J=188+Tt~Zp@$AK{zmQF@mvj&4ITF+icfy$ujizy7R z*6G&XSG9fSAZQs_4MoVMiyI4UN|?f@&Y>kI^;ubdo=fX=1v~C@zulq6TRpjvga+-QotXLR2-Y3N6U(CP zSUi#QEgs0&qgxI7brexr(SGPJ5D``st=arR5ph-f$ZWzZVMSR_3s)VC$6?s}Ny9$U z+pdHclgat(Y4WdjUE`YMy4H2wq;)t*PTrFh3H@sHZ>Z9){{U?oX6cd+)CR2~f~H4v z!=m5S9s8Tmfj_aRdRXc}^%CDebNKB{fqDe-N+|E=Qafk2nYH4b6w*xsb55H%4vFTc z-{#q5AI1LZGBx;lL3*duSrIrC_g$fN20N5scR!^*Dpaj6TGJ@FzttPF=BxI$c!z3K zn;u7GW}a$zJ3WpjrJi!~8fuOkk;j|dc$X8}sDz(EvRk)BFT%4l5?z2tI_~EJm#M(b z>VeChVeT7k(f&PDJyKzZ4`DIn=&ijWObOVY{UYaPXURF?$w&A z(VtXnZ@YpYL%}~rkK)PQMg^}%m-2CJUOH*X5cL(LdouJilHJN$TkIl>ur>bqztVTN zu44m2#-%&hggi>+4p&z*o>e=*hxT<-G%L8PukWbff!@A>!2@=GB@CJG6puZEr(cO3 z%ji+6y`9e^&}rS>SJiFk2GNF{B7ua@s}EdE$^+y*J&+QkFLGz&i#(^_h_GmBC~gS!(aHWas}f3>guLc zhxhpI!oc&bN56|-q-S-*;BQcSqX&bM`a5|d_hoG9*v~Ssoj4z)n4^YSbqpbW{G&*Wj!g$_eUFXAzl6@g(eZx&)-gmPs>DXz@-7^@3^ zU@HD~nf3i>l;Y-fFiz~qrbCZaJ+I+&jJow)jF?t_4_M>rZQ`-49rR+yz=T&xv?2?Q z-z*0DLeUSB@~7q(c;(VIm}S`RPz`B>*-Jq*SFN&owGC)mR)MVmH_~-#(6n{rABJcM=Vmg{}jTxk|op ztNPJvk-0db2%UQ0t985L?*_ZkS^gc#=EDL`37t;L`f3&#qxD-Rbit5rFO8U&Vs;tL z%Xs;4n*%BBZMW8?YKKxx!oILYJd}%q|NdAh zCW10?Bh-nlfLD&775p`tXa&>Rj*O?<#N+t@9l@VP6)PFOfFTd{%{XfOEhJ2czVonGH7kZLVM%jj$LNNq= zp|5`@)c{^XlCuC%0w*C9It360K^*)*tZnN8#Ty@{eeU6K&%M^NkN zR4ME~6eJ6&HA8aEco+LU3U|h*$rrLgH4y7uS*%P>;cyE;=*Oe(ZuvA( zpy!SSEm1LfBx0=Q@YMX>L{{;*e9SBS1y&-oU8NSmKAjCa75kM(uRP4Vb0J6M&{yPu z_hl~0ySafy$UEB3{K)i^Ur45hkm*{B-*kTp@3HY}t#0iNVI{u(sg>AkPK9O0T*qug zU84m(^aabRXKSCZd?>YOiLui~e`t<_i-LWx>;(6kx52~^8RsPhawCvAaWa;%shXRS z%nouO&_oCMGTuXgmsstefUHBbf3_?0L6EcBKjUcsB;zrj7eFILa}yoq@Q2y{kCM!M zBIITDe=t5^8vS2~S3BT}zsKws3qXIJV1YhHbfZf_SahRK*49i3ac{y#tVxj(-DqDW zWCI+C39E4;XqXqs>_a~Y!?0QyETe4dwz$ z3Xz~P@;m`3``+awbOV53euO-9L)be#%tEM|=zgv2e>+GZdNmXJF^`D5GdMWmlmvUV zd|8f{<}A1eVMqPR!ecm-A;Xvhbq0e`7M}<+m2XxH1m9^$c`yumx@23lfn1P{<(j8T znyw5J;lCK&CUr8?Hk|ZvqAAVUo#3t++8n)&Wj4yL`&zVXQ9^CI6y9I)KK560rZs)m25ISR8&=vN<3jxo;PVd6WXEcy_*`h3}ek#T=TI>V-aysBYB zv%cnP*R_-2^vIsMJHhI;t2tEr2C4=@4+J+L;a?q#0BC#?XtM^+g;>5p6OBD(>Yx5M zeqmlxS!>mj-v`k)$uB13OJlvOOS{Z}LV95M_!R8OYSTZQ&cZY{H}6WYIp|6uQIGaD z*t~;GY%u#InGp7^hL-J8Nw-kdD|0v<$`_+aOyof}=jutA&59>wFfB=Z%omC3I+~Q% zCCBfVf#%yTt;>yJceiNr{sN3^t2j>CE+~oFe)Kiu3W_HtDNgv|J4p3lmG-q;+Xjwb zHOaA@j9c?7F(2wEr&XleQ1)WS%Lh4oq~JC=2x>+J$t`yV9a(l#P$D6qasuLq%g& z2@>PC%b=bR#rFZ{6W`|B?Ed0_^I-&Rz6(G{Nz&OgI<4{=N#|tv*0o~TzJH?*Te7bq zHpe}SvoAx?--HQX(E)Y}y%8FXBn*{vRAUaNM6a$ytM)kd&&>8Z_Sap5(5!xLUWYxd_FGeZqzV{#k@Yc-@k{kkFIX2?{BBCG{!byjhSN z9&lbqa=r^8vJXB===%{Ec&97SJt&Nj+GWgcF0yOM9!dgIY9}J-U*py>W2Sb-Yx1?G zl`}q#$3q)^1JaTUAkmB>$^s_%B+H8|b`Eo{m5k$~j*HU#}^RGr>a$+7D-!EnSkDVYihz^e*(p(}VO z?yqLL;fMEZXS_y51TRF*#cQUj!Fi1~SaLy64B_K71;Q_&9|;(dqH4{U{HI%-ZT|c! zjV1wx@fum@X5%hvyhM8va5jC-G7k+nUqQg;8--dr_rpXjZC{!&9NSSoQQDV=qO>1; z%+lUZR9V`22>REPJH4Vp@GR5}_9&?zv^B`@l0<&)WPU9lB=Q^ncA|0Ln#iw``Q0w^ zJ0_K1UXT3b`jBM;E&oo!9t4~pcCw6Uyze3)8}FsbJa=tLGXndNktpWoA;|VSEJwFw z|C!jbn2#aoZ*uE>U|L{vQA?#8)!>{Q+sfOZi%NBq=znDXR(Y=%c|*QeiM%P__jV-8 zyP3mV(eK=o$oMj5JXd5qG?np*%vi{mx>2*zhwP+;MFULNZ|!xr_MThY@78_@I6wZ1 zC5J}uKtO8r#ANP&|Bxl$?a>avWe$z*Law6lZw>|z-O!Vk?7xzLEd1{gWE;#HjFF>9 zJ0vY}zaU0iV zsg8B<;UayO@Zr9SWS8C-CGy=N)|RwGYH>?7#!a`n9e$e<3ea2{+2Ori@hCk|qzKQj zzun_Fq}0z9RO@n7M~h^s+hXZPyzuH%vcPXYauc2*#zfh7J@{Qb${9Fl{&_BFoinqXHOm0KNfg20Pq8hbScqZ+6 zH5d831z5%cyi%L*cHlIsSTaJ*nJ1KzMl*(2ZK{1c zC{-UfD(<@&0%;hmD9cd~{x*+3d8w#qk?TK66hbRYFm{}Pp(2R)4RDlF~cryKw!Pxn(QN1C13 z*OJtCOP`8VYW+J{u~W5qE757~gVWHQf?X;UX%~dx(aRpkEZ(C#m*C+=T`u@5leIhG zf}w;bMO6L7+wsm_yz?Ss)M`r3eCMM)EK_b!9ouH+jWe>&LO`kSCY~cUGw&iJYoy0v zD)pZt#j721Hyz6MYCpJ}e&~%Fg?)f*%)3AWb^iptn2vQm6ndv=fH9AD#v#nL-A$in zd+lGkoA%)GxknpvKuo|VMIe4u!5!@o+e)|A$E)3$1&#%B6&VQh>+{>9(Lp+>nl0~q~O%sH~FlQ4Tv7ciFym`q~P zt;oX~G4zywxpZ!2wCC0f3v5{3rmJ_rg@sdEFD#+Xoeh_H#ADn66|3Itc6`Uy+Nsp{ zf{%_(-Rt-Yt<~%JPPWzUhg{6qa@StHG8m&e+FA-v@}-@uOJ1 zK^sNO$M>Mo@-NQuIHH2qkCGNX@r~7+@uG#2)Egl9A)=U@ftU0bGhE@_+)0T*U_QWe-C5eHm*eXvMXc#K-FL#F9E^Nl*gOhj{kt* z7A5>2K;ve6GT2d5*>goP)8&!iLIa0$5NDkDvchD6WHTWJS`~ZRpn%SVqswCZ1 zrA#4_U~3<=wI#7GY>=ry~7Lm#*ls4TYy zBQFQL&s6G76aj0J^{TxavpBsPWlt#79=?(am6_S=EcSAg`8Y~A`ZVD(Fu5#$Sj^ug zFfn5GMq+nj254bo)u&-*HuR@%x@t^^`#1^) zZyfldYTp#chLTn_cC9+UbrAq!*e2Fm6uTI|g)ujN3u2Y{Esr_zTM|1DzZEeUxYnB3 zF#Jx84Z&|MhIhf%sj=hmJ3V$ZerLz>)ZkZvSYMD`$b7YKdJ~gQgwx+ji1#Lr&5c1X zibr0A`%#2=BP=?^tG)x#1tDXUkp079%X6J5&j^&~jrga?{{NHmX!)t~{H8roo<}k6 zM|oOK6DrX8`$Tyra*s+IM7I@%+Ui zS4?s@NphBafdBfN33jq2e(ip8mABQAz`x$Yk8T0};52;UKfe63(j9@d!Uf>J%Edwd zAr+Hk{pK7oIK~{&tv}X@dUYG)^S#FXb|^U(>))jB7rWXnXOE_}2D|Nk0CH9%CQ_Jh zx&mt?)!tRw_u97P^ic|c<+rl+ogjMnF(t}?F@^Y_uMFs;wvMSlo;JE~#BfQ~##AWz z_4I5g`M+%wkH@!($De8UlmXWQ{|exbCw@xMY4V1)d}wF=>Wv@C?JyOgk+_nv0D`RcU7CfN7ms4a%Yf3I4culK1$arh0fEVDXc@aUKxj z=U1@t5M%RJcX5kw_i5pk^dlR>*{*8g2x8cC*d`L4ZRgR{FC&Qg;9D$`Z>Snvy##Ta z?*!FYOqVotlI7TFJ}^T14UzqOOxNe+0B@q8Zxjmj7TWqVz5ykU ztQ!G^RX^srstDzRnBZr62*sAT%Ovh%;=;A*;`$6m$_LEv;o!xbYbKWFxVEDV2vRq& zKo}6Y1gRp3RmfO7V%F-B7Npv!t-%gF_}3bw0^u(U@FF`cNQK8nKOk$t&k+WAH$m_h z>)RqcX7=>j>+tu7!tjV)-PpM8b~Dt8dkOP0NI-FNY% zc@X-U(#QFqZ$mr7Mp!XR`4(MmDswUMm5Zo`A&dJSW@eOfYbVzu@8nFMvOX0)X6)6> z;f4w0`34lu5;^vGna88TQTekeFJm$32#wv9ka*P8fX>Cr9T;f?lK23D^TB*UY=gvJ zOt`ATOSmpi-?A27Duek5Hpn2x3gJc>EJSdn45G1xBQjWmV4Dn9Ah=BiRRlX^um(X> z1}7reDTB2LcFW*Y1Z^yZUO64X92uOAU_OFMesCcwQOVbr@KGEtWMZ*VLNLuJkdJnd z3ap-iNTE`Hv?#AAPyw?rDp?@0{lLJYo)#{WsVq>546;DwGROi|$Y42wstmGhH8RMu zO_V{FtyTtEwy846vQ3vkmTk5SvTOkvWZ4#qU@(9}A+|`ySW?9D5krMXP#pLJv9=I9 z9eZ<8+>fxsjwQz8lllGe!dhT!uRFLQ-yQtn6eVP*p$X1|oR)_v4Bu65$9f+Ce#lqq z`PJH=P+0~lF7f&YyspxAVTg2K7ZrWrL#q87)i9QT84N@Wqmevn_Lw2o8$s9~90juc zs0vJG4%dfn?6*L*V=l5Sz6(v0Vvces4P=`{j(R~1QBld7Jvv%OJFT~8$!Nri7RqRc z6&)a>-Bz@hj5b)&eHcxGGIa)AM)%0*QtR!zGTLrMTV!;l6kf-^-|J zMIVq+p|Z$m4x_rL!Pr~`0sxE6L|`fd+yPO@!1V}}GcXZ>i40tfz;p)2Ah3`DCjtcw zj6k4-fnf+#FmNgYDg(zMFq;ARQG`Zf90$XP6pvmK{Su`|-P6EgMKTAe3+;Hl1Od3o z5n3ujXdAk0;TUlv*eFvA5L_vPg$PDuun56687x6iimKU$gbQ0XcCE4o z!A_aVB6rJRErL>Vl~WOvdVqGXi^h%#z-*895*vk5BwKosZ0UFp0?Ggtg9U7HV5bu6 z<61-addjkjtqvi)l3N{Ug3~=ChV!}Sp`=Dx!2^8cy)d>bzUmOb&9h!-_my4Jk{FuZ z+9pPde>@J0s*pzFqU z8xOO_O@Y~WY+w;+L~8NUV}yNplwyt#Td4~0#Wi@)Ul$f86!Y<5H_l7kHc*%zk!EC7 zc=Wj&mU{HtH^6zfdMXk1stt`GTY+%Ex!`@yi$(^V_aI>Np@LU4Kgf1DW(nBih|cT@ zoWiph@aTd@tRyub#EfhyoTFw4qPL)0vWJl@yS~NQry}TYpmQjA2@4-w&73jGu0)Jm ztVPeCqUVLv7SpG&A5g-hQ;WSZZeuKFvk~FZvAn@N|P^~3bu`8!0A`*T=4kNy!U*f&CaZl!914HX;j7c+(1WL0ge z2b_og0ij}}IkuOl_L^H8&2i{~XECV_C$pnME9qof5K$U!lrSM93=O-1MH16Ydd#oYo+clG7I8M<30s z*}d2lDNwJ?4>%u^xW{7u2^s)#mC$2EDng3Noi%@M2kWYa{qSK`gz81Y{MK!VSwpuj z^U}6F5U7yUy0NV$;2a^T^(P_2c>=zK#|?D0RWx(3<7`@H3}`r@M8eUNkuCSAL*Wf7 zyvi-?)3E79I)1Dz?9vB05y_~-v38g8Le=0R)h-$iyj#7jmK|`u{H~D7JW;X+L{PGI zIL{nijFdz^vlIFBmHEI`nvqW@#O%_4nhpG&qNN0!UYU(sWaEzQHCMoH08UysRQol9hr6_EVJ2RGTNHD&P`b5m<0EWE%r zK+%qH*e{fad{tv+j@69zn@4V7pM8A5*#&nX{NMsq39p4I$08`wP`3SuL^tCnp~SNi zN_?Rpr}pZh#KVw`;}<{GVl3}iT3pZUl<;yWSim_)=JOcyc>^hEXr96FOfI9Qpi^WI zjoy%RyQ|r3WUm!)UMPv&ggJ4*d9EaK5sCPblBTg!&|Ar-a3z$58k?x3FU^bC!QF_u zRh1XEu^RSob2shHstn8>jaKrjaYnz0BXF^)u z4BBk<(eLphjrOc0?H8d08MOabS3z4Da7N*sLs^~|`F)5;sw`haqoQjv^XnrUO z3`VAsCO+-nqs84LyJE|t+%71y({H5yqUMFjqlo-JH94@JXmbC7=Ml2`ji~1)L{hSO z7irO(Gwb;?Dy+yfS7ZtsoT%sjRTq?0z&T0gcezmVOEU7C%={*2>iRv&{N_S4Soax& z5?aUf^#qPj++ghg*YQc3L7Vo5knToN+8Yr`Nw*G47u}v&+6Or*5z@uw&@3(bIV=gY z`3{xMHw(VJh-kh;Me`k!*~_674=n&qw&J0MX*zkfqzs*W5^_xM*TP_n3w7cOn5E4cRp zZQJ0;s0s|YkgjbDc0`;J6kQ2bBkl|^80IY!I8lWbgR9fijmjzDHEAe4Snc@Pdd%u| zYu9l2xoESHT?F|BoFPO~vRgvgy@eMTyKSC^IZfjl?xVSu7;-W*0YUWUfWr*wRyg{j z(=j&%_>%;mFTl@Afe$5k_?z!In3My)GX<*iPJ&+w@Z^l?!0X9OIuTStM@qPGgIh85KPL!Tro>&b6>xvYX zHy!JGi8bQ`R0`|ycSP|El+#iuze-0rQ=)wJXR98sCCY^YrL!$5hrI|UjJXuj!z)sT9oqpTY<9k70Sj) zp@h;==$J=F`<_69JOe0gM0rl2{3eBRNeabx3&1ZJk(35%1UnKjM!p%W#i~IfOcJ*U z633=U^hXdYT!!;M1}qhZznL@Sjet*{@3+KYd7gwHDfbJG$>oaCNa4s*7HmLTwDWUJ z8kOZc0~~JcV6~)AYJNJX4Z#~|_s;O)1e}8LAK{eHG`Ox} zr-T2$--6;jurkedloC{S7DWh3H&?>&7-dxtQ+=iVxqwp(!+8T~j7g{Q1$=)NjXek| zp}25OCp>fOuZ1GS>4r6&Lx`LUiBB6Z#o&mNR=lWK@Cxcpie(*lA#K!Bns~ zWd&Irm}2or1aaU;s8U$f9-P-N$OuLE=p-o&m(Y{OPG94`W= z{0cx9Fu4k`uU|l{iZPsXb$&*av5XZVR(vVmjb`juh&A_55a(?_6Au8g0`D?>K|7b{ z;W`31j+4hHaK`TqK&i%Lv2br)*??yD2DiP)ZWenJV*`-%y0}T@ApHf8RkxrG zncD$?*Ae;pQu%rTUvK8?SLN%!$k*q{*EjO@-F*E=yf*hEqqO}1m(}R~gH64H2e4yC zR4vAGhV$VzWPD@4->UWlSau3Fm&fi>gP#Rrw;@~*n~dL**md}=h+TzWHHPy5%@a{Y z!RFf7So}_nxm5jL9Ic7_=E4iZ?cF?A6WzqAVz4JSscoU=>{v-gWA=x7ua zMR`&HmCe3Oi1MHFAPnlD`P-Bn5-SQ^PvFUh0{ClH9%#upWZbDc;%^4yeU$njnhN&$ z8F?#OyW;K}N4D8yd0}Q7Gh&7OF>)xOHpqHF%N!=umVRVslabV?0o#HSb?LGoQdCBv{5PvwP3o?f_$L`IYJ8xg%;FU zTA=qzZHcTYGLHHVq`8=Vk(;i+E?elpc2Cx5z({% zn8bPy9~=VKX#zR#Y(MNwoB8ewKiO~6<4%+gtu1jI$|N)_uhycy?$JjhA(1vEblXb}tisJZuw&6pIQg|OR`9^`q zGn(mm+XdcgiHBXN8F+t3GF);3QQG#N8S+TkVKU_IKJNPmqt8(lxB=%qb0FA{Qk#Fu zz^KDBz#a)VppZ~(O6f-UXL!NN0pX5Ftv|UPZz-Ympo_g$c3ihotu?!FS(N+j-JaZb z>9TFbnS4c|l6>K(jD zQyzPFXvf{>$MSJmk`n3%4n6ixq@X+TZi4`4=Aub;{1-Ts5plbng)qts@ z!~J0QaU(YBPSM1v4#zi2=wkWa1psj+SkvylDyrGIq?dpb;}gRD+JftqgzGQidJDL1 z6g%O#nHl-Hu=UQOH%P)|3An}t+*S)ND+zakgv%Ci3lnfJSa8`%xYHzDAHdyxlgLxI zVEQCsPM0vaBPeor1z>!)k*B`N_oecE4&N8@{W!kI?skjka``?N?`P+!yjo64^oRgH zNm+hWSM$AonB1l#uzHcJHtoIu7%?d9*Zy-+X^nqR=+0*iqULM&2%Y_bP2EwJr zpt&34ZEVX^b+LH@ckW>+fV(7kiXq6)5OF&kh~RV?EJAR$4CWvhkimQe z7s_A(f{R2@4^T-oqYyD%D$*bxXLut#GyP-{VzIMORKCsdx58$)wXr!^H_WjlAnTCcN-Cc8iVV>t#QE36hlMCC2z4=O6eTm{96(K#KcDj{)ly zjqeJ!w7a#soY)`a{d=Vm3~iG0IWMFgdLIr=%t?B#N4H7)nplr^!@x$+#Bn~MgA3{h zXknXpJ^>cCN!0|W!Ip=EhcHUubpl+HH}VcO(ZGt0*O=vC%M;G>qeyCRdz4#^df5A5 zOJnd5wm;oVU$v2a6?`AC&bS&18OZHV6nAukn1Tsmlh7-Ox*hL`h1*6FN3T)u5F{?b z>6KkVT<=J6oyufgwPSvj8y%U=h}aYqy-Uy(+kv8!Wtepzy-J2BGVGP%3Wi-WOihTE zA?(q%x%J-BGh}jr$tTG$%NspPhN)T6J~BL&;e(ua%B@CXpAo_}OlSK*xSZklL|AG& zin~chRlH*9UzO2XEBc&_QcisPq>M5zMjw(x3ZnwC# zPPtzK`ssj^{4n~tN$O{dwO`_Y>8Bu_7{#6hlAhdV=;u*usbV8Aki~|IZI-pcmU_9p zD|$bsD{g&kcj-p=$iB+MP0@o{=?RZDMWakGF776jTR)Gd0dv1mn?5U4LbX({->dr% zMSp`(ip--;QGWC)p|by^V5qXpOf@dT@@a<3PGhpNR<%d#IZCt?J&9Fwcq~T(3!2Ui zsgx{^M0LAy@Jb1NjQnwFUm_j1F3!b0Q`Rn<)c6aB=9SPZm^%EA{Wiwk8P*{fw~RxJ zFb=c?(mq7{BNvQw-KRiU!Pf3*9}!Q;_mQUP6YN2f0)M-Ojg!FL@&VvCPegHLa=8@ENrgGz&eJ>Hws&j9X$(!iZr#naDP%QEv1NFiaQ;_ zd-Njtq+dxJgD{tfwZ74jGTB{f6>S*fNyh(4T`+#a_#;SGmJ1eoi2?Obc)v>`_T-%! zCCylNtWJpXRWu}u7M%rmur!LoV+Tu#AfP46Bp zjbvqoU^uB&+Qm6hhsb?wcXT)c`&`PjvE5UY>5=gW-iOqaBy-|Lr%Xe~*BR}@^uxEF zQYgD@J;N-umnu*z8SAM6ZZc*`(o$=+X;*J`|NA&;twa}hBcuJtiYJVT;(q&PsevK9 zkO|Xd!c0O!j&`daZ$vyzF^aK(WZ5fAG2HgP(a}jN_em;e2r3wpuoEWBGii_ef(Z&wo_IQWev6<~)lTy!nTvWrA zB(YhNs1hXXtkmbAz$gZ)IEEuBeci=YaUK=vh$t`gMHNVH?~}mpTq{0}@%<-9Z?=G? z`CHuN)?nz^ZpZUQPfOIo8vCiryuf7IFB+VbF^V1m8fk)U-xrT3?DM^XQeK`Y{6H9I zTrRxLk~+r_V()GAH)yh@TlV7uiUAmOMgfdF&=`dP-i$trs2hguDLx@M?qihN-KNwZ zFEVh!)XFNbghm~kf&e?=81BE28>25rfSq=190KfTV;3U8 zK0oF_pq7CW1laAzevLp411BM%GJreT<$h?KFPA%{u`y>`+SoK<0Wo7Bn}Q3nBe)ry{{lIRlyO^v0R(D|4dl-{PR7enDz} zA@(PCLug!tp1+<`ko5h@diD#yPfUQK_}Vqv)Ds_z3D8t=XW>q`)2sg?CqV!CBPKvO zf3hasbxFJzCEg+N$jiGCQ)bLuvad)2ERq0jyup~_87!oTNq1QiV44Idk^tv5S(EO8 zNr3SZpsxh@x+XR0?p%^!|8xoS@eLxER{G*cane2X$;70)=X{L&phu6%=?{Ck8&Mv}I!Fn10Sr&;6VR5ek|;&iLaJ9%Dv6z z8EepLaNErn8Lh)Vh)3$?uctDkwG8vCClYFtn9e8n(~J9>c$67yEdRu{2!Dfka4o_O zQ2O5q$3Wi0c$DtIRrZYa9{X3Sjvj&wPH-;U%eZQg5cV@z*gOzDLK zxmi4V4;J5~k5=3kZ(-yg_Q+(w(;n_8+S=-yz<`6 zF=>i=yU?fk_;qlCuBgdT5**&yYSe_moEx z+CBS`F5JO&P+nEnjK&yy71y#{_4xm#epFm;i8}+9W~i|@9Dxf4ba)rVge4wh!~k3m z9!J{OxcN*89?h{1u5;l>7~sI(%v(d&Qe|R!#1SxGp%QQt11|tUb?sK_3xVV|e1kF6 z!Mz0lvTl6HL3*`5YA|mua697u^LY0NWDX}E?;qjS@TxHeLmheR1n(cg(3Y17dG)!2 zvq-WZalN=5H*`0vo_Ck9P1Qdyagif$3*jvm;-;a;2xQ+M9F1wK2VAERc!^MtjBY`a z-Ul}ksU!VMlm#aM-s9+k3=mLp4L6!NE~UsfgRA24wMauvZ|6iV{0)6F!RkmB>N6kn zhynpEYF^yS^UWuO<;^?tH7^Vzy%a<{A#i(tlI%$DQYFaseD1omzpjp)v{YFj&bjG4 ze^gNfHN*}Sf4(blZz&3=3w@mjT{~p1gA(Gx99(kCIi;Q+ZY?%(^Bxx8#S$ez@<4PhNDV_-r~I;Z8laY zr^5LO(P$G38||?OwDs9X)3mkcd92{)Q@t9F$YU2~rb*FoTM`Bu-bScp06M!6Ye*38 zA~;XXTi_93H!HmT!FekonC~bjZS`za7fQGU+xMm;s4Sn?W{QnFTJ=(P{QBgTIFo6g z<@RVFt8c}|8>5EdG9jGk@h?R=B3R2o9u2tdsSUCVKt2sng+(5{dZ9UR55!&kfjY8! ziC4MsD|j|P_P-R%0qz}3z1o+a-n0OI;7)2o>uErp1aQV5$CQvM4w3HG-uLM97GiIP zx#?pvDPA#|Nh@R$R>7@reNgA*7aur8DSBDd9^qM=EG4% zQ`4$Q)$_JIM04UmXSq}O^Ldx>tjAzW)|tv98Fj->QLJy*1otXj$3C*oy%NJCwAZ{5 z&vTYJ@D*`AhWMsNEPG`>-zC@HZxI=x_bz*Ckr+jvD)%!C^=IyE z7~o=U>!ZbTm_6lp7-s+FVQ{DFW6RZ`39Z6YzphZ#(C+>mV8+@+m{v?*ufyYFj8Ct` zo4O)ZpH|}0$5wdsi&c+)WsOI_ZX#}JsP*X6rh4?c=^p*Q*{XhX`E^&tccHwhh6P4Y z&_F>01?@g$0V>+G5>>kyS&uD;R)d@davI2KAg6(x267t6X(TrS)@}uvDvhL$ri(EK z<%#VA`RVq!8^#dp_P9R{8s3dzLESJlvEYk-tXtgwg2MDo@2I=+rIz6Oe134jyb|IO z)Mb7BZ~7Pfl>TtauF1?%U$MRtg%z>39^F%Vo*yp~d5ZA>@B8~+oxkq4tcKvnXf->{ zeNYrG*TBjg2lXz+BzwF0B^Y%FzeH2$6!-O+JRrcEAQsQhmL=d_qF6c4yrZFNFs9;F zgRy?vJ+r@xK~TQxcwecX&+H5gYOD@_n-J8U9{n7X=LOtNU*_QTQgv0LL~h4>{$J~t zZPVV{|B<48gX26ix2Zaaz2!r#U)HW_IdK)*b9FZdZsj&Vsu5CNSD31;k>Ca6XE6fh zGA+e#!YgRL{adPPtND7sDv7KRS>LSz^C`@Sa9;r+{*ewLP3&RTYTlkx? z72Ru03z+;yBOEVF&9ySn;MM9DxwY$-;Fi4(%KAJA0vC=hL|0~W#VIHwn_CTmWb%FM zlQc13nQtP^(v!sF@cOvYW{C{;uM zovtKn9!e@^ntt+r#(fy@`HS)Wu5k^x>O-$wNkzd$Pjd?6Sf*dMlx$Cj3MI`6zKqdM z2P6bI^}cNJti_Z3i~AmNNlC4_2D2axg^SFm0V;A7@)bIj(d10?Gzgft7x7RNw`@^Y zjmlaSwgW>RlLJExGO&X79$w4WHsS>v~Iz=@=WXBuU?i_9hxGPX@_aBWf4`FeyB_PTV$Am}QMd7iQCm-DMW*dw~`%98!Ag; z+n~B98d7Tq-77_!hi5`HQu0gaCtIfZ8z>>pxMRlyzU}e_vUeNT)^dc18B4p{@gZ-p z+F5tK*O)TZ>-b!Z%RUqhbG-UWQmtB>d0Du6+R@M_bm#5#@{#hYE) z73J9di*K0u;KLkW;?YXb(q$`G!ewHdP@+2g*uPhVh+Dt6$h;n9qq-fKnstVgg#Q0G5glClQgr@Fi4?qLcg`0 zGQ@*L=`~>KFK-tzoLis5EchNBsCwBtgz5s%jF-S`dI=0Rt(-+UVB zjuzjQ(5T)phn)J@@zDn(dl`UAaiJQ}_9-i7_2Rkc;x<>Xqc^5f7|b-g?QL#H=ZsU_ zj;|y^Xo1Cb(qdqRTZ~P(Ps8iR2-!iLaLj)XX5KjR+?5A{y!O)H1cknT}@p|#4sX9fVp4dL=8@PzvyL))$X z)5u;7c2q~}41Dh-Tl<>`&+IcPic_-qSfiR|)vWqKf8{aia4((n92Vp~jdhfLGO2(M z4+cz?f=ZjO0vj8RvNFEWnx`yMR@~FeV`Qzuy1H*PlJv+W(h)TX9>H*=veR!_`q`D-e&3BJvb__Z02IUa_-W2vlj6hj6PB zK7eUtuLp>$xWxq}KzeDcKhOe5Q&tEfVEi7$%nu*P<4rtLp>6j_`wH|g9tFQTIr~xd1Fqk>4&EtjdYJN#sy48bvE9eq_;RhkMfIeMfM+H z*APac!>va5t#I`_y$6LO=NK#XPEg3KFye!OPbg3Fm(&m1s+1Mfsyj@vJVeGV>vc-% z^~h>$zM?Mzj2tswWcies&R$zfeR>8ydX(lwhDRct`AN7l;hM?eZjG`xF;nkB)D#kN zK8iaoP`dGg==}j9km_w-eOA5~dtSMht*dkkE{8f%6m%Wri_hG_bYzcu5nZ?8d>0s) zo@1owT(yq6)fb)AHmrt=PXqeS!~6uR9cAN%tDr9~=>{7~pH7E=GVtaHxwVADFkDgz zUYc24z3lj&Jp0Q5d>`&-2PDAge~rl&wgVkBj)BFuW|Ywn_V=6L!c?1Y-p}^iYPQxT ztI4XL$GH1T%l_BH(6Lw0Nhd3j?{Pmo)GpP&(Y6ie$xuf$l-E#j^H|V@GjWXW%%+l- z*E1Um$zLo#=_G9GF3ba|m}lUf?%c7IEv&_SH7sz4CY*-6Gs>yq6HF+Z+?wj#b%BVz z$XYR++w(+KJ%t!plKeY=M`}hH_1n}W#eTZ84ylu(|6r*NXPKmVo5V{L(8Bjh{F8|P zN=R_jOK|e1{UYzO1Qy}VI+R3r9tRv;Fm*5;eCaiUIds8k^5U3z{^#vTgBen_W$eMQ zd|o0RM!D$R!WH6SsCYn?i*bWf4T8AAsa8A|iwSb^q<~U9d680l$5N%(->4MNi=^sW z!zUN?>_-APoS>JWz~Axo2fHh=Cmv2I^G#Na5iSHp3>-T!t;xr8n=0mqC4xVAeT)h1 z&=}mJWbRy;XIqQyH5lb|nGZvZsmw;=n+@6KzfgAbZu}&~De5Erey@c`v(&Gr5V?5_ z{Y@S&;YRo9gNfSWKbjw}=+oL8iiew=x}x1;Ai1m-=S?7|iFn{vK63!-l^zs(hevyQ zk$4wg!iN!FDPv3Jqrpn#ITl>Yg_yXAPe3UH!fi|#5Z)#qrhIhEM-FiCu0TGDh1mt6pd@PlZM)`=~0hUZYv~at8Y?FyaUx~yH#87sE;L$A~Ie15b z5CrQ;64F8_k%_f3u^bO@O%Ob4`?m>A zHzejEWDiUM1yd?#MykG;1n{L?lEWNY2|a_{1LvQqg#Sf0;P!LtUQ9aYS9Bsjr-I+Q zGPJB3z^}EzIGfo)SOyZ*APA3E1ZO7ZUu?S7xD<&OedC*@fW{65%#*5fTrE|31-L3@ zMOEH$Lu{azSAh~^xP!QAWcR_L4csb{m+#eX$}995H|1fe_wu|Vujb1uNt7Gcxk9E^D+xWVW`mMQ!s;bheYshO0c_vAL7V_fZNL;Wfh+{<^wyY;W3}(Qs-lb z3yNv)!sHXvk+0ER2mss+1vv8zlq4ks+)9G%6Qn=`vooyElc2Vk1$=WFo2dh6zR{%bYZS7<1NyEi}X}aA+`YwMFBY>n7^JqNt&lL z@qKwLpHOcvM1^qF#Vf}hai3{ciae?#u@BvFO<|k0)HYs+5M)W0=L8O1=kM&Pg(qLPkR(YA3prKsVn zp|oh?(JKLHo{6myF;qClMA8792-Y(s1TP~7y~jKZ;IHSRALjUk;|F>*Q`6-8B z1vOI8X%gvka0qN&k?Pp#b8_MmeHN){_fudvD(Y`?qW*$p3%eA3pO^tbKqSPridl~w z@1>6~xRQ>-req>Fr;9@>l3``Po-4@ zFRvVhVv0B1-$}=os>zzdVhHXARRvG@%DWbKjDZs`juwbeSg?q@S9Pw7Z&Hh!eRpDCeDKg%d~gn07Cdyhf07zJh z6kSl%EB2^Z1bGZMbn=dHZrnrL+-a`(HOnr?!89J<(#wr6ucCB( zJ@G7TaoK@1j7OM;t8~MI#nWbM5&kFCLvS0IREGscjW%_IZn%W_DKe#nEDszU;R3#3 zMmjUXjx5G?sSNrff>7}$wdo+7JMBu4WmEN+C@yv6OO%BYx)g{W{TOd}ixL_mh>U8& zstIPNM|ky1bG*fy+(7pd{nrFFCfeoqe=pXvny?;H;BjnMLIXkBi$mo4NnRNLlP}Uo zy(Nhp>BWV{-r_giP4V7d<2Sf~zI(<7ZqF5$1V`V&d`1d-6GGgT8$94vLSL{F4qU2) zBH%H2;0ky}&CeI?Kmsq+h{6cDns~j7Iu#G*SyEDn=vy@)54Q?mP5?Rs9MP zz6jwckKw`Rh2sdKMm_p44`hLzXP#no6(3?$gB=52Td-+M@IWa}yI?XEK$GbO-{Di6 zlm)MGs?r+Hx6~s!{&;Rka{Te7xnh`{K+`jYt{UCD~ti@+jWgEN#W1+u zVkJ=#ZA$2I0iGW?STZ*+aPa&YdjidC0|$?r^#OdnSi}qQl9NFBbxQa$<|8UF>Os)_ z@@z={5+-tSVOV9pDlLsk(Oq^ z$B>)+xSM|Lgi6)O(>C z@Y30mO{qx)Rn`BA&js1T&S^3G!SF4u&uZ_8Sk-mk?jyP zuw{@2+q`!uI~g{)i8)zHUvV0{ ztA~Te(V;E$v8VcX*gdSIjAu&hqk2#kz(p`HH0On9voz*O+9dtIQCf$`=4zx zcA+`%uJjhBgx&!qakUnkO`Of<2d^;-&1R0(Y{pv6<}9lt!u~B^Uwo&`R*jD%qO3o_ zMak(n^{oPoqq9OApHt{xFWWe-8X0kc)xt4;MO!|7rfAE)YkIWfgJ$Op*^Z;Pf{;6o zy-CB6MWX#(c&gAHq0Nc*Cv_Wa_)ifp+1#S1QbUSr3|awC>Nte+$7$CLFT{m)!;8jgp5Z0bm>@UQUgNTEEHMY- zMsGS@#e6Sq{TE$AkI4|O#RkhTW|ojSkXAwuV|b;kDKYL{i=$n*{z42Iv&Z1ZZ(M${ z(qnIp?=9Vk-fV{QD7Lt4nssz(oUsb!(bjltU{uZ(O4Xa%8}wNyrSZV1l5u=v$2H6% zZIrTn1P1D3l+eu>^aT%9`A^q2s&PT7P+6Xp6O6nV>@LP|3VndhW~TvBo@!DSlyd+H zp$)?3(r6bW!rEfaA%~675@UWzs)DRh;~2`AP2xFRRO!*m4>M}Sm7uOdY`EZ{QLzS% zN&!9#yP`_zF=$jcXgnTufx1*UXgs-}7&<702oJHsMNwW-`}5d)W}3xb-Y>@9TsZ6! z?2W`Fb_|ofQC7GpTK2Qq%So_zCp7t&k=}>!z9iT?2ybkHy)G+U6y=rBKTmqM+-XVg zP54cJ8TLk}vG>x&Dd|0Hg^Qy5`~O__Hr-*dSMrOo_h)!u64I;0eG&=joo|JUq7%s; zroJ9tvVB`!bQ=m;3WHb$}>E{ z9#%GgA@=NP?9K6}*z;N8qUb8zcJTAqGj6k_w-3$XmyzBLaNs1Qcl3-Dd;P6&QS^AQ z2V?G1!oA3-=wFY<=M&mQKfw!H{)}ZqWz7-6ruN{0T%~>iqH>Obf!jsh9BtwI3L3so zYWVToX%0OTbhPTWzD3usB2r|^n`}xYEbv`ZwftE(IKtehl zrs6HVJ7B?>u_k!vT%~@ZKycn0qJw7yPOl!q32#vK!o?A#CtK#pr0ofQnbC=98U4=6 zh+a{M!>fe%@hXAj@cu99h}-xI)E<-%COlV*u@N#b+wN1sIzl9J`e~y4;>Magfy2HJNS=|e@&k(gyWuaStJPclm1+oY zD@S~ET%W)#g#B)2?PE$86#iJu>duVf`~fKMHw$mElnpDn5(pm1FX_LVbt^}LPZ8xX zqf_|in6=yB;50~PyxMuucggS1>YW>=TKV=zzQ2r;&x5Z!q2&FBrj)#o6)uXN`?J~0 zO|Ul&t>Kqp@1r>>_R4X6Pr`toXN8NRkJHQZv!r(`YE)=jJ9PJ#Vef)8_HLMvl3uM9 zE{b+zJoxk2dwq(SZ9{r}kmS7Wjzy?s#EUxvLK?oLVXB%FCp=-x3_820~Xv-jmq7JHZfV(hJhn=eth zdse3^H)@58qS&VSGj;Fc1bfTSntmDS4Nhavs7Zr)n~G=q(4bnem1;+ zE$BtMlm)L40KOhL<%|)_;i1Jn7PH~l7*U7AhV8=PM~5Ts=cx#^iZA`*8#jUY5i<~O zi|*#2EZGO0$nOcVvt{R1D{_`S?xQEkUh*S$qe<{DzfJ=$1$d%UPwS+PI9X!;Es6QR zW>@A7mKKcXEb$j8ET_&l zpPsTnw^-q#=0jXe}5HTjM$mdY^`S z5baRTqv#Ul!k*>VJ_*w%|8dIl>NcKo`xq}1GpsPrCIsfS*{~#nP!zZ4qBUbfeVbbR z7SF^kFp#Vo{Yq49#1La@Z-l$z?oJGb{{tr+2gBHf7!RD!Ed|nvjBgfWs5osju(1_p zw5lJejvSZcD+@TT^Ow-kBIt=h>2_=?vrLF@Q2J=~FZd336c;9Q`GBL%uodp%2E7&y zQEtgDN^?NL4-3!8t74Feuf>`#b0&c^Vb~8TMMab4dlC6HLW*LNU_V2aWf;qH@IvKL z%oi+|I997hDQob-@AhDKZe6J)v@2#Yo;J}~eTt}umAGaUA zgJUu|87V?UOh!&-sx+2q2Jsc##wsQpd@C7BPIe|8h6jhmLz4dMSgsKC*CLQcA51-e zl%y>_l_+WV5HB|n!S`J{2y2nT*M3;2_a)Te`vApL*cP8XXuTw%mS{M@H}UWwizLXL zD=~2rXByHfHTr_%zfrzQq7Au_+k|-(A{}k^e?>c0qFp`uaJjkuD_Tsnin70MMrlI~ zA66zCBvkS4!|}AIJc&l-c=t2ZOrjqxz}A{X1AA?TRLaNL(Hn6t8+RQpi}|T6 zGU~y97ElI>4ca{=HJ&J7r)vP3-m%Ei^t9vWJoq!L9kf63=i;R8Ph7gVluYMQuWx*H z%JM$J?%&A6wZZQ3{wX-C4R?8O?C;_-)+AIwpnL`|4QRpchjTbK0S7qjf|nPGmsh~3 zh&B=2h&yGGTr85uDPgf^(RyVU7NQWZq8LAb~PXXI0yP%7bSq+v@Dt%$oAr!x}s*}>RBq=eoAv*yT&?CbD>;KYPh3GYRE zGzwHn_*I0WuaHt4n=Q_veBaw4s$0&|{~$6M`G08p68Na9>;EJqkU)|b6fmf5M*#_f z2r5EYGmyZH%m6B=RdFec+M;5ZAt)e$On`AZ{aKgRwpz8eu2r#C#4RR46L1Zdy0ldg z7v4B3NG+R6{@?Gp_sx4VnPIX0`}s)T-1pvn=iYnHx#ynMgUBrpy<;MLb6k~Czk)YV z`j8?TJ+)3mzqKP481=7G_CVz~Pk59$a1XBWKy=uX%+i9+!)LOksxj6Z&wIjcn3-T# zq_&Z(K(0HC^abT@fj+e(rUtvJseK|RUQ|2c94v!O=M$XGU_rba{scNB_u}d)&}&D; zbt>#%S2eUfk(L$?$1jSqqboX4$`1HXSX7;G37JlpkQE)3`&R)2 z1i4tAB#mPLQVYT*WV{RVB<(kaJrMawmyjMxyWb;4yWfM_{V`Ar;`tub?w^4C?Yws3 zx>R4|6avu2d4a}x*&r*7+kszO%--;65qQSqj=OeQ{s1F19GAe-#QJ0>Mx`8GI*#gA zR4S8RT>AN5d14WU?+w2q$s`HPqbKXR+>Pl*+)M4E{NAVlgl7fjt!xD^iJY6y1YkRm zLrV1_E2AQ0og)GM04}-cejNk@HK8+k@&A)}P zVo*-v7FDNv%v)zz>yJiZaC+vqnHS)eFDzOvG_LUtZ3mU0Gv5sebK%z^U|OF zd14)a`-z1Z-8TtgucS8%x$`ga4i?#orQ!wZjgbF1?P@0}tLK-~1<1fM#ABwhsUafQ z?P94n;Ae5E;Ae3PwH1@vhD+o|Wij!ynD|+&@N;%?8IADCrHO;bD08Pn!dP$i+lXzl z$x~tmQ2KEsD<&P zwj4~BDZ-V2B~nhlE%C-~*=8Xh&=Jl!NU=qaJp{-4qO;24mCE1FjGRqcL{1m+sWC$I z{Gj+Ojxq;m@!tarB<|Bm21WA3NoKGhIV0saXm0-(EEQ3wkU}XW=^KF}h&_g_e}OBA zqX+$Y4nXsJrmuW^@FpVE_;WQv9fvOp1kmonJ9C$rk2~-%D2W9`!o{}W1{c0CI7$mV z{LUXYtMBx(juJ(f4;bs^C?Ov4$p&b=lWdZXoi+s!Tk{Mi(q@v$L$HQdX=ZMy5v?9e z%VGW`4S!GKgx+Y6LR1(~E`R+pa>QZEJW7rj07nE{EW`dB8;%Ju-)l*UZ?o}930p`x zk?$L|tRy%aP8gzRpHONk*?UsS{=ihd({&}oWMHl{SsdbH{|qY@d1cORunu)Lp8^7cJ_u>@-_NW zCamHp!Nk;-B}Pdn5VKKQfT^8sB)ciN!)Sqhh+q;%6qVCgj_p6m}W)urA6d#a+>8t%GJc4|)yaSuH!nmfQVW+&`o)mJ0G zP@8-CcVF?xnQ*^>>)8(T>}eX|ZxXilvKKKHh)qGJg(|26X`~p`m(LOx<0I8{{6M`E zxX^)Tj_G)b&w8_8$JR;j(m~iqUj_<&>uvfL2^4owNSaLg?sN&_SuQDM%t;uI#mTN2 z*T3YLgH(AQbx7VsF>`PDKfcJ*YVm~kPP2U);M4St4{q$p?zBNceFg9hs0E8HhLwR8 z`y&1g$b8erWJqAk6=cg;)M75GHxh))?dZNJ9^J(sLAIv??`)TS5GfSrh1k{u$@zC z)+c5lY5Z9KZ;*%$Yme<_5;lSt)__I$5x9gu2!zMp*cO=R4a;wT`2izzvkVw17b5ld z@R4rf`spD=<(r z?L{snJ}Y2^7kf~aJ<#85$1`yk#_Pd&)lE2fR^We+Ct7z0z{i*gPQGW<(zd|S$&?Ul zF# zH|=_Gs8ye>oUZu8ABB0imlz>Xd$$P&xZ^DpC|wC;lKG38~z)r zZ1}I&*B#;i^u_NB|L14@@8NHoX~W;|TpqsE{GXt&JHmg`_lAGa{|ER>9PrQ0w&A}* zUw4FmZo~JT|9Rg3{rpe6*q;BIDjWW#`nn_h_rKtT-=|y&*C1Ua4tdNS>8>4drBNRO zLy&}!;o(f36JnvD+OhEB+!gHVg>KCkMr0vQhA^7Jy$^+48gkrF`MRO=HC9opiF_x{ z#+qW=rE@#=<_vA!POgK5*`W_`0hPE>|97@9H1C+9jWPPL02)L{&mllV8t*G>^H`OFEXubpjcCaOXFEJ;ceM_VfZ2+~L;wLQ5w z4N$r|_|XFW*gMd(LW(Jb3^BbBJp>Bnkg0flGZIK1 z`Fy`t^}nC*HKOuV`_ua2!r4nK0{%S0-@ui2p z?g;s)1Tb@pZ-^#CCilZ0Y`jqcD+5I~3X~}l=Yo)H9(H5f|Yy61Zp8{d2r6@|At0aEe z4IAeKWKAC3O&sGR?6q@CWw+AaIDvFaK4^x~fOBR(m6NzG@q{b8xqRW--O4Ig&+7(v z__6-T{Zvi+N8K-~>Cm6>X)jX{@}s;F9^ID*Ybv$~bq?BUN1Sie?<0)Z6};hI*hK=a z+L6!mOaDP(MV$I1zeN#$_B_eOrt!y6=XD$Z=l)mU{D7`HmL zJ>iz6HR>786uTWSVt?~S8nm?o8il?hHuo~mA4h_D8L*2z6*`5o_?6TtT%)=OT!g!f zl*Z{42TpT1n*HI&`0ybWgx>HkI7P7!00d&wbC8KN<+Qf(DQoeyegR>@iMR=C|8bLl z^YD(`oFzQ9BmOrqPelL7f)bq7$1$Pv$)3EeoGGR+XhHgdot`kNG(<+3!LeLQs!L$o z#(5zQ1wbcHb}O`33kvu)Dk;>=#IJ<~sFgb!i6m>L>e%A5Dxkf}MtEvup$kij)j(<* zm1AL|onj$azyqjoay;aTRFtU)t=9If$fmdDua1$DTPl9<3>4vbXT~~rpa4Y|_gxCzbEQ!%{?py&0>h zh-6R&`p+9H4>TJq^3iCN%{N`$krJ$v5rWH%4psN;wH5aYtgZ+1r57w+aa8r&#eQ#cR~P2VUwEwe)mjr$2m#fvhY>K9#x_b*#?_lh)6ELRhZ@(xxj)PO;z;~k$rN|o^Mrw@oHgWtsX1#D z2do{D82FFnEoP_@#veX6zjF0xvh@F&A(&kscP?3iAI!jx1%2a;Hf!5LL?zVv64#F? z{haDj90)#xN3l*3^`+T;IB7I+0Wt*n%Xb(d82)jTT$**RQUAG6;vVw=9N2|4MU1e_ zm2J3-ltB@Ei}@M0;3ty`iT77a4%`bi#9l=kbjdmX@L+%BF{SsFj7$!s*RgCj5M4%s?&9Zzix7iNb?bw}A!DFn+T0L{+qt+TE%|CKHF0x%?pxmV(Icicq@)+b% z9z(QI92f5Je`v^~?Fcnhzd$$$Mve>{RA7S1h_-iB-GlgrqNvdbb;dN59S4aB{$|IX zNi0(jLvlJk_7nJ^3~e`0Bld9~St#3jK=&4w-q05nvk(WN!@X5LgLKl7I%(8tNs{C4 zuf*Iy)msKdbu9~k_@eg-G*OiXBrLgQD#KUbhHNbJ@oap$xpz9w`m+&}u>gYiWLIV6>f3B9;YrAN#a<~oAsd9Y6uu7k3d~vn9CGO$ z9+qujPJAYE>OP4a4x+nE4r^6~?m_>!e@7xsP1QZH@pGc_M`i$Zr}zmqLopWCNUjG1 zTj3&FLOGVf_%wuJ%PwiuPZQ`8wn>P$wGg?rufe@sD8AMtuW5m{mV9n5Zb7SD65EDn zeGy4|;vWFxCGri339||h__M(igM?Qt)fRKdhfHY&%B#A=qY@T@mBMtgIxt!Q2UzvAj>jq?3bDpO`Sw6RvmG4aVAF%D0e7HGz&-u} zNPV*%`#cRqC*vi5HhxLM9tH6pL6%6>YJ3Q81Y0oQ4k);A`2QYj@i1%x6k5k+v24B+ zn@hCKm-CAB4X)FjsD*y7q#TE1!*Jl7%=GzaNE{txroTNy&2)Mc^hX0PW5hP{v6h03 zfSqAC&hKZ`pAT`$ADNHrGmBvH(0M&NxbF;B$DoJtMFHj&!Lmf;G*(E&2fFX@GYJIR+_ z?eQJf5?(uVZ-&|HOylWg1<(g!E|8-apa*+FD+f7oSMbB-8*35SfOowG;SGFwFbGn; z{Fdndypc0{Apvs%3<>aXU49@7xXXOq&3J!P@WX!XsBu@sM)ct>U=JsIo3_LKPRp0x zNDpLHKBr*$wnjiSw{Cw0zutsQ*KYNgJbQn#T(-X)5}JNd&+KvN>PFLK#leuOeUa0690Cyc&K26H=NrSQyv@`qjHuQ(GRF1 zi%^9Ig%MiBSd8VNrSu>OfvM)f8fpE>k1SO7A!8q4A$DLv0A{!tx#U0(!lRgkt-x#` zwkfoSvmdgirj#f#>bGH3*i9BW%!dvqf~UxE&2>WNhvi2w<}?{+;BtrN&_XnryO}!3 zCD2-$L(v)br_>0Yp))2Q!XkBsJ-Z>gfa*dbTpd?}qPxMt$gC{=_{!0WamL z)SS)O&*6#6BUg(NVw#oOvD1zEd|YrpkDdq7=NRVb4>8G7?MRG3qq6#VoXQ&8 zJkjcGckSMSg|Cb6XdS0e^9e-pF4qc(Xw#uhwpyG4QSYjcupObiGI$OTc^PkT%W6PpmmZ?L(gP-`OpL%))#;XpsvB3;)K}B1~v7-`n02 zdrUM=pol_UdcqI8MgSiKy*u3nw0z=;C=qNxv&w|FX~Bso)B+dY-GSav6+-Ef&ni$& z2Rb3={esSCMRIq>{{T_6JW_(?3jW#?RVfS0H`PRf-4o%=(clL2n16{>p~UV~S2rzo zcN(mh?{%zw1|JK>J#4=UFppvpyWuX8$~@@!*7I#B>cBjTA$a$k`Uy43(~DiWo}{l4 zO(wz->wN7oYfn*RK1F$NLEG0z;pja;25F*=OPx@z38*77k?5GtNd1r7o+I){dw&>JMP>)N(oOW^~4{9T^A|)Q$vkzmH#9T}r*^ z7u`rAkX0zTf*V3_;~g~-0{&Bc3vSExf98$$MgZfFG^iDjBpwcj7rg?@fuqtF#eavM z!Ex}RyHbVI+)uqn=?Jp#48BSi!~Tm|r!AtVe*=#`(`oDP>DAZJgEApCnn z%@j~qUCZ5d2ac*a4|M+iM0#u&uJL3ywSVXq&(s(M9mbAP~_Dj}lkc zz;Q_L9q)}NhAb(;zay)EWMv*(*b}`IN0N_cXdL=h{5X+kP_6*=C3+ww;(oo);w1H& zf^o=_A9`9_+pxJwx0@@Y6JJCFTra_4_x4`6o~N$65b1)7UDTv0XFm;GCYe`5G0r`2MDH1b$YNm5r+RI7%ojAN)UUQg4hnTzCSy3_`(PK$ALO~%sU4t8u!TE zR`C+tW$wnfaL`Z+eW$PJ*YFiZFFO97?xNb)dMpkpvF@bquD^GpXcB&6zaAl0*FB(V zTQuQ8oH11hHDDNwng6NeoG-%`Wj`b-ux^sW>Q>;>2&aG+p1B4Z18?LKh_UYnil`*< z1v?{y6x18Yjf^cGQkWBW?2$rA)BB*)XTx>(n zpiz`EOx@hR=WAOjv!tI=obKSV(+s)a$4|%5P8+c&Pya$JnGO9g*4e=9_^c8&TUF0U?!+h~L86bKbb%`su0Cj}m z;RjLmjN@>oeh_Es*ZOb@VTzkbbq&tcE3lK2a6bYfN)Ok`)~dA^53*|7gSh1nUjydx zuHjGSz8WeAq4}C6>H#X6Jxgck5Tj^d@ zdIOdo|7%2{8So~G9gXl42%O>fL`o=sl~j*9!w3X1)^?9pzlmKl*I2a{zw4UY!ZTjO zsRKixPC)vFHr--+y*2E2$|2kzxk3&pPTIu|pxE58z;J#$;MhMkj$pz-Cp@FLxPwlOp3$F~(y%F-x8c*s zVuu4r|I#ivw)pysP6jFLHtH01XhG?tkD;hT&bt0gVb`B2?E1qHi(-P>Hfvt|Yv*pI z&X?y-t6k>G3gFZiM*_lcS|+)&J+LqvYbO;z#r|Pq?Y>&XC`P)pmxP<*d7~?gTbf!X zxUvvMO*v=gdj5be*epTRFZVx3f8Ywv{<`+kdjfQf70Dk7QK=fpdb<>kHL^1mFxq~m#ux1A7@NHB zlE;(h?2jzp?h5Z1>0>eT_StcQ zJ);D{{*1)K^*=>RWjJ~Pfbd6aa**wt@Zdn{i_9*E{b{>5{JJ^uhoGkDuy(4)!jDpo z2FB+bmg9N$(i`!keM=6~A^yW3{$xR4aIk#$3k+!R8RJbPghxX`b|{Kh;z626aS>UKz>bMecG~=-amf6n@EAd-0G?r~;wDLVi%}{j#xb zD-piqkF0eZlpT7Gp^AU}gRpZe9SXU|c~Djba6RGWe4T!JEt}%lC7|xGPs|!PIXI8y zzN6#CjHmxr(5$mzLh~k3V{RC5u=_A-Y#yS7lIuKR9oU_Snx z9vF##p)B-8+->KXJCF0nAabxL|`7oQR_ot z`3BzrI&Mjp(z13rc*^IgQB{s2wWzgLxTu zH3UY>N4nr6%6?D8Ze3Q~_e%0V!Tv^P=(F%Si-R0eEffHyi5 z?kx43ka(4O6yOEULAj<3Z7ShkB772occ0=&*y0b*L9mG5#a#}9SQS!KLzy0t58yb{ z8tCd~aCqnqOe;@vqXqy#qWhWHhOs+B0a)rEHOCcf@J5!FAZi`wK7^}pG3svs9F!EF zIZhKui4YV#hM{+(Db-wtJN__qkhA${bj%}xg!%b^c}uBU<`6zi6ew_@z(RfR7hUAu zEm@BDF4XtFz{26Z2Y=bKuGNkPjbH!08(0Z>jg@0m;&oy;p8}U+vy(q^i}NEB^+%RE zKQdH(Gk*lSD*tMXM&`{A1c`maWM-<6iZ?O|Tm|kkimOZmR(PY6AT`!sfXl>Y zYH^uL^Upmsm%%&a3WGpB4j)XL%Ul62Gu7fUlfY#Lfy)fX_rPRY$Yg*Sp|gP*wATB>X8O=0Ml)Uu-5CN=@j0UBxaF@*H zDBRVfL_O+~*m-PM{FHcpy7kF8_y$kM(Y*Ooz^aLaS!H&1C(k+;@T?>&r!T~jca2-t zBUH~J8#s>_N;YWdr6KAGh#ay3LhTYlfr8Mz>2vA`GRX#G9I^o}H+K*Yro+&ug#(0? zyH^Jgnz;Jn;sIDG5e{xbk|77iBC>^)u8?ydxTv+8d0|h$k(?{eeI&8s@lj^e(fkCo zZ`yOi4RlK%$1A=Xz#D9-EO~$cN2h~^8;eY;Y5H0(vQ8F}NZpR&YBcRzsoM!ha5)$F zS|FP&a0@V2K;Z)OJ{=8)@~*{FW|hP!+-bQE0?O~1KRCYLM}O!-=hutXhklj*L*zqX z55n*gEaE19=v~mEXWf<;+uL`ve|MZ<|B8Dsk$R^w>+$6n6UTPk!v3LB_9-bS8^E+y z-GNCXa|L6aaR;aE(|-8Ic0Oni<`2&I&g1u^c^^QrvH+5fNZS3!DV05f6-%)JM zoPo|r)b;pe-W`r!Lf=xcna#{woj~LirWXNkJdry{pdRJVK5Zvjl;T|r{hu7AF>y2{ z5ZlKez{%^D&<|CWdlNL`?h24XKI-Z~G1LeJf)FM3LnCZuAn5w-1YIka|GYG!L2_x;Kw1z2kKf&B+2;GAVsSrknPX9>zQxH@^;_>r{J!pd4G6rNo+d1ZikRN9NUT~@)S2Tb5SF^ zf?N(Uhr7*&yXChc#m@n+KXR%+**TJW_>*C179@uc#sgo zgI#nV)Ui>1)MliW=AvRwXlr6Z_ll<5DVcAFWDenMuAWel%sHdnGY2cr#P0&#qznd} z=`o+RFOUmn8KF4DNXKDzCQBA_j{ipSk{jt<%<)`T@L@H_N?Nxz(x0FY&T*F#J;#>- zGLlWwMoN50%<+vSF)=iV?MpTfl@6xIi}oD1R?)Ujg14B9$R1CSNOz&EYDb=NKUx!P z^mYCqfrGGra1!2WV1qKYsgFI-V1Eqsy{<37@5m*{-M}e?y9oe82mmd-qFfe1!Mxbn zRo(tP^rl$}86Gy8%_afL(R_klp%OW+t`9U{1UX z?DI}iO413yS1!wn1AXnd>A|0J0+zh5hss5LlBo>!%sdHFj{T7hw!T~qDg1(dg;G6- zbX#No`r2=@jZi-)Vp^=^GRcp)#oUJ442d=HI=-}zUmA%90_!-D`lEB;0T(Rw4-A$l zF=A#TIwfK{&XHH^bL50)90U0bN(88aa4a+zKSzJA#PKt@F}^8zQaB5}?v$6+@%>T0 z>^P9~+Z_+(tR~A>7a!{wR<(Q=pZ?VBgzv^*W7QX>3WDiQp@p!Fs^{f{*j#4ZoGJxY ztpd(fo|qQruyym;0QWPsLjeax_y8$XEYTY&afU#mtwvxYM5A&2Q zNRi>>^?{)0urL3P=$Q`u{Yw*XCysdxyjX%^TD*@iQS{y0S5JxlU5ekaA2ZWq0zrGK zypKwR8O#?4(ZvbuLC4R0b`E!c?u?oY8L%U)BG%u=!{z!>nNoQC(i?y2m zAL5a+0$a^beQ`qHI?c;y6-3eQ@kJh2f_Q3K-;+^STgl?5brYr*Se#@F3iY)FaTgPt$Bjr`vS*h%hnR$a^#A)l`D-4?*TcLY z!*m=A9c~*f2g_fByfsMc6FGwkYz&-jAXTl+Hl9`~Y(`^YeZ{@&wqar6CCr6=WqGq+ zSkWZ+d|HgUaKj>!GLcQ7cnB_i#UtFSmlS)dR#z4yKU|Vin)&1snTDkCPeUd9bolC6 zUz`5^(&ffrSE#bW1TYWtDRPmW|f+dBVu@c+{+sU4=d^M;EU$%z^3Wr>4s6wE>a&z5T~0|5*!Xya$0{gi@$6> z1b+$Y@eR(?gm+N>5==Wje*~mI;c>;xNArE^%?a((FT6wk1pv8H-K?c`h9QUa@bysx~3QF z_Km2SK_}K|&jX0TgnQjhp6pHSA5t26{T2}in4B73FYHFCYK+ics93}YV+Stup3WrE zcxgigHt#>mH@BD()x!qqVLhLXz(EfoabY;czJjuKBavdHjb-cT0*J)2C>MGs9%Euc zsUvQzit?xSZ%#Bbxk#hDuz~gKHei#$$EzAS5c(=##7{Al{Ty5fpcC1m-hq=V1bqSa zpB@0a2e;ry15;@qdp^aZ>l3~d9rl-Y#O_9WuEC$!Z!*2<6p-?LYeeRdf3|m})MedLXd_K==0*%yxj*hvpmjjx=e5auKKlF|7BA=dECI_y- zOQc5X1gXTf2$GcpW$rIY024b;y_*KFiv+NqgYiWI7JfU{lJVIO*};Zi<6V#GS;1orxbZVW+UwVhq9*dR2lcY-4lXUKpwid4+V* zUtoEZdia2O^tZA+p+Bg5r#tWM`9>|>W~xUN%CuH75lB{SIUYw-niW|r9Sy5qE1c$9 z{D}?8`0y0H)0)zsPim2O&ZHFYuTbkiEEDc_v0o9?oj3e1_h=_aeG zt9h1gs~o1U?ndYaekru)%EZrY2x8jOCz zVt$E6am{6HK!{J&y>!gsu+&)?t?-F5Kz&3k)t8Z_UVD5|R_rt2aR=1tZmigjb{Th$ z`M`cf8=I}BPUda8smW@}HJ9rqrl6J=^UP~>)9hV#q{W=pw*Ob4%1CP zv6>3Z6Lr&6tEsDL=q4swlP`8Nzul)m9bh#Tnlatf%W5hz-_}i?tfpdfy>4Rkf%IjV zYjhJmS*582_IcI)D^^o?^CsQ&G@7{FM>&`K4`@s*_w9V5?xmv-XSo9ynk;uYKs=)5 zo}6*HOTykMTRHRBp{4rZ>I$?;Oxx_oDe$?WQRTDfrk@& z#%^=Ve-t*X#Twz>32!8}``zYxeNW0bM#nt=e8Tl)xA}m&SD%AE;b4l*<8(hOGidJ9 z+47&FM-w8T;LttTmY216l}-+Lw6A=B@H3c0hcF~c$5JU7(OJS)BWME<<3qLB<=tVZ#$g& z)bsz)tpLPoMOgbwY&9Bk`&yuE0xAq`^o2i6ny>C~My}hB42y6p22@Q5y~Nl6)k?gt zKhNM6iBiZA9QP@3NvQD}yputJlWNWvA3sS+lOZ_n87TA^5LW_BpNeuRymsMwlD;mB zeGG^p_+UhI?C*rry{yWsXhxwUqrTZ5(IE;%_p=7@C|+?mK05?*1`fG8#FmW%H^~%R zmIZe%#*@K8akc>m#eh*3KSOW9^ikBu!Sh#zpy6n^2&+>&Vy-S@zz|%k zbh;6`825~ZqcELy&3~=if0D7vj~4KnhVDEgGa_skTx_d`zSX|Xy_SBp?!RQmd*C0u zLf_j0wBjyqpj!z`Lk+9CeK>n$v+K2tkqMbdfA&)nM| z=i*nLDLJ-26`Lf5T+C()j{$eHl8{)?ao-*>z8QMx@sA`)UnLUV}zvfhcz$4B&%gfhi z+_%>cJ5Xdsg?dn2OucbMsQ zeB4-|3FwsBk`sAj94HP)6IcT!_1@ApfA-hF_zG&wr$o;{I7o{M2bsYAGi@4~T6hIw z$E1EdP~@VfoDR7~Ll_tWP3rWbiWqZ!n2WBkH=QJWh5j^AuVDc6BD*nG6z4GNzmSC_ zE`5Y6qrsD1x9(joeIZ;|Ffl94X-tT?@aL^OO}=WNbKf_(BdWpM6>gmTiMITA7meTP{D7Mcw149 z0n-Sv0EHQ}@k#|Ue>_WpZNaPJmyvPTq`gNlXfQAW_9l9W^m;?L(WM;=<&X6DqT(1f zVsH88z)_S?Fn|vc=O6X;MVyu)5zwUKgk)6X8rlf{Z!`>5YR{SW`Z5U%Hgy=PF z?Aekbwh*G%uu=NDjO1WN#TQEKuR^1{F3&VRogZWbQR)ggDGPZT?0wC7)d`+kG`hAL%wx1 zpQIe0a102>Voi8W?Y{CaLU-N{_KZCu9DXN~GO@u3{SLpAU4X0B!Jn%PA8d@zH-1zh zCt4RxKjT{}`;>MWkG-*vGnRFH7{B2U@p*e;)>*hNnGz24aZL%&>w~0fNESG%#$|+B zv5c^?BR6DYi5CeP;28`%DiR{Vf`l0$B+Q=zxb(+0rv5S|AU|YEIkjs zCF1&2Z~5PYrZ@cecme25gtafc%KYq$%u0y^G*%77_Nex~?s1J}4+-Hr^7abVFnTh) zKK2bZ7{`1oe`KjVgoxQjM9luyq)>y1S@DQQ#O#IA-5&Fa&vgG@VIn$W7Q)yrb0Kc| z!`H$Tod|YMp9qaU)UhUjfJq9JV1nl3$Rz%4Pm(+TQ|9jPm|olh%izht;r@o$_9ef; zyR^#x-5+^CopF>La2YJc$;kz>EqEzsW}-SK`HQ-zY05hT*~dj}DlDZjKE2{T1|K~< z4`Pc{J;)1JLiHeIhF=@lJc1d9DiG{ch^i_V7f!?YAZ}8mbOzs>$6n$jL5rWK*?$~f z6!!jed`z*)*_rnrmvjHI>S>&W;h}m)QeZE*iPY10SN!_|*ncFs1_KaPCSLQJnNC;_ zv0tWzcOI~d`{j|sJMtj#Zh*TVxL+E08!kQqc#~PTj;?)vyGHtYL8451d_}rBW*(DF zb9@^txdJn|^erC>$CjEUH|y&%&b`I44eivScy{a}$DocBUq1g-&Hv%%U$x{Fh#(oy z&FjR$7UyOWQ(VgWtzaGFgw=^JnfA|QAxm?%;Tq_9nW$KVEQd7Dy;BNb6_!%a!X}xD z=(25&gA=T5o1|M8p?4M#Sbibq`AFyY=bwB({H{C*u58Fik01QlfeIq0Snw)&(2cAE zEYSod;1!Vew)zGrC1AcN0e=`D0WDwIi_qj@4+o3fZNC4Z(g6Mp+ZXPY@E$JZUX#9e zAAa+wlKnFRT}4aMT~jb{Nc~zTeaGf%Q1PbUJjbn=(`R3aruOND1b3QNilmj zF0e>=c<65P;)k>t%ChG8(xEh;p96_yAuI6wAvB*@ii1_b9EunU?DOfWU;@1OB%Pnh z?cxzdjwW2z^s1N{BEUlx!^5^~N>ruu;MoKbvCiP5Q$-kqKEax%xfFRhZl|8Wra5C3 z!&sGoxO1x>dnMk+q0l|FRCVS&g)BF{~+^$l|gX)x+9!jxkNOCXGj9P;`oJ!k)Dn&8Zr; z=ozCB@7R1CoGOFghb(p4q&`1|kEn=`fRIUjSk(94BrqSGqo;lqnni_@er;>C2BlO% z8JM48O(EdAI;aIRuz*`=Q4V%wQ4i|rK~iuplNH@JK#iUHtp?- zir~w?%c=x}zP*WYE6*Bu$Y9p456n2o3lTBMn?4ce(k9=4eNe(@2TR<~1LbfG8aK!Y zG1ZOuq^UX&*-TG=amF<5@BM=VV{Hy2v;@8L&G-;}7vDI~L-Ha zYsZZ>>c`+B7H2znj;d<0YZ2_5sA^#_#tc3vENan@o$8_%f0O&o#)=X&w&b`x?Gum& zUJVCq$&V`VC=Y@(&Vj`^G5425^MHP^CqrS8;~l`iD3Cadi?lB&VlU{BwtuRA`RxeCAyi4O-(NcU03epGFa?fn)}L*2~LQ=QbK z^=Iel+A}O$Kr#V|WWQ40yzq1c+A(OwDth9m2V;a7$AtUNQZSdyY~R{G;Rq(J0Ry*4 z<7R8rDU*iE3Ymal<(0&}vNX$;dDbcuUk)6bZq^3ih>d!?MN^WeD{=m?^t<$j2G==^ zc##}p^C99ZhB&pS-pJv^i;PY9t6wM9FZiqT;6(e;^r9gt2xpG*XBv;>w~~Su->3f2 zfBtSQWMC#4OkB!Pq|_gBC)FQ1UDqFa1uMb&L!d?+`BJEH=tj#>8#@QY0R&#`OB#X2 z|3yE;%&LgzPwwRzl9Sm3Z<7zQ$`LD!I7=%Xyu8S<_RuPmhjz&FB0JvZ&=%lymr&VY z1kXUEle1ys{B6-+N8pEUG%p0j6za3y%b_MRVUb_&`Ti zm-z$v_6O3^&P+u+o6f>Gt@RQ80_$6K9HUyG1%N`LNr47OR{QGuza_?dq_{T)YpZdu z<4)kfy|?!Z?jiQgUOBad*7z*^t6eq%tbYp5NA=`qQ8$9{68l`!HXL%Kcvn&-t95T# z13+F(K0yIN2uSVuAv)69m8^1P)4z-l>P>%+Jb;aEG8*T$=8POE>t5FcJ1+LGs2iQx zKzx)Ih|?WFbWQ`r%2Senz#$Nl$3GpC$CdH`fM}uQF+QgTfLt@j!#dAV53I?P^WC*K zmP0TL$;3>{Q!wqK?D2^OQc_W~dp6ngvVdPonU@1}vQM2Cj{~GF@&G_O9gP6zBH#z+ zL(dB;@st9bH2{b7g>A=zDDy5~p}?Q z31*E8i{54b7yqETW%(Fncg~wG;5Rpa4Lo^pYG1k`eiE~#I_*2{h|_xewNP= zVpNU6&WvpEqxXt#;e%(9S&h5KdPx9-T&v|T8}%n)2T`K^R%5OI9e4PR*wJXhzUTDT z!QS@*iZwW=Q_ZKf|J5!l1@K44JQu%i%>j}Xq(SmY(Imd5m}jE{%gf{eVEH3xOvgMS z;@ZsfQ;Sn2aq!)**+9^FB$d*dYLkHIEX;G11Bm*ybYCBEM9Xw(qQ}4? zm#Gg#yfoluM(iBB^FuGw%j5Ji$@*CQuA?jr#`;ql&J%kjL^q`)X-Y4)E!kjC+JE$< zIc3Mm3>UOzBqg>ny1=6GQ{(~A_)}53d zEN~g$asu`77R7jUWm5uGQ%-=8>N@Wgx!GJ@W&tzO0>;Hd3-VcJ$%%n{AvOjuff39d zYf*uP|B3U4RZo}YBzdl&+H0J}(KD*O`X!)8N^=oClh3qNd$FdjvFaPp3D31ud$F#r zu`0$EmQ~wteu>rbb%MSv%>UafBa2LOfVCN`m>?Hzq5=Er8QyO)R?I+SOZI4L19{G-Q?n>_9P24s%*^P1v;!0o5>wXn zU)L){b1EiTsnNo-7vw(hjL6rLGgb};A`W^G$BV;3duwHQF~o5AJ_8d@^W>$Mc_J^{ zQ?i`>6C*7N+!78kMoQq;3HKNzmpLNZJ}L2$KziD?v=Zxqe6dl;i9pbiU*wDT4kWQ- zTV71nuN)aZ-u{w3>R%-xg3__r__z>vlkssjTNFNCf<<)Tqa1st>XXD*3&EN*XkvRg zK7Wk#_=0AB|L3x^z;a%W7U>%jPo z%AJ#vYR6(+j~O8oBZW6wRhDHWe+LaWJ6dXrE&sIF>7Vxc&_;>l{|g@TmcMR< z9%2VbVhz8oJJ}Ykf+uMg?YgGs&{0{v2ELwF+LZIT+)!0spJejUzMdIUrZ7o^7Y69` z#R>jI<2H*E`0x)XWqP+V)|(%~(iCYOJ#QPKX40BJk!O4={l1qafuhS@wuhPRe|0Ap z6rdl(p9XGJw*N15h0~Ku8`X_MT1PlJRMAV7{#QLO0PuAGfnxFYN(0sG6WToU3*?%! zmRkNE1YU{1;F*m5SHjI9z5mtNRB&znRvV(r(p6I#Q2__;}%nJ_(1(zNDEdcYqJ+9 zO_@aFvy_;BZ?^;4&Us!T=|G}DbXJ+|kMu5#D%N<;#WF&7g7N&!6}(D~=Q~!RLeXK= zyzOPaif$w{Lslm^FgA}1kMV6&bEWcG$`im$NRgkJ58@7r#)5a6%%kjW`Ys1yT3`C3 zgIX|Ty=+x_)sTQ2v^i=q6ib`~Nw!|k+{D22*a8s+pvh?miW>Fnu}rZ_*cT)^bQCV| zIO6_>;z|+5q1;AJv4CbU`XSs#EKd+|<6+>URh*zmlK7y$tdu3lfg)PmcyJc@(XI5v zL`o@KpQx|PVz=W&4J8_f5L$_A$)d~ZHk$el;p%ez3mTDj$!rYqv@*vD7eN)w-N?xo z7Y)``=uynlI|4I&#WTP>_X7H{oC=~k~XG)6$01p*bn%;TDL%2+D_C-z? zlq=sEI1`M?^1naX7yinkC!-+|U&?4L6<-RG9{hy@Leuj36WscBfp;tx!Clih$V4`ELtjOPCo;HSJHCO^Az4b{lsd1}awX5Jz@+AN99G_+y_Ei6P#RA} z3{i_Jvec>OI=W09zSF=bf3@Z!;Nd82U>r^ZgObjbKh)>SXR%1O(?G&k2#SVU#1>ij z&KgzSFui%fEB{0BZ^nyXxBHCBooKm4TE>i1Eqi$&4uUYKa6pk?PUgWK9tPO3pOq2z z!AY>Y5K7%;!LfP-d$Ah!2t-c}=$paEZT&p;b9J8&u~}!h>Rr$+c8RH_kZ`%rAruYq z%0$!fzm10c@GD5Pfav=DT`P=RTcSO7XCWoT{Os^oB7b*%h8B(&dFD07@2kk#)3`0S zB5VKZ8S9LOX*uDy5hOXZz3u?tZH=DMUXk^-(Xgmfc)uiX=;~g_7b}hNP0z}yIcsl4 z5}0AwL= zt>RQ<{ToR=*ZteLun{NN`z|7qENyHk#SJJT*JPUufMyiHSD?iWVQSV+2elm>LGu5S zKyKKlY~&_p(G~F5jX;hCxuM2jC9$LkUh0EkZft~hwB|H--M76L48jaGQi<~VlL}RA zJQ!8=F48#Ey)?wBS6Nwxefzp6kfXuEe}z94_Iv5@2U&)mBbWVe@aMtI_%p3j_#L1H zaKgsBcZfI@SqFeP58=(+^q4m-@1So!j5j-Hc(cnv-+Tmb=4W`b;Gl2*8EcXz;v!(=_oR!Rk9{w?SYy$}2|^cZNEc77$wU_wPP(`T8Q0ApBc5wPY z0ylz@e?0_!{1R_|Kl-=@Z+<`exD{`HKl->0Z)Tv6Y26M=S-0cO!t|6i zt>~a{{t9mvr+;&iaX2*jYtUp#W}57to+f{pM3cy|zVtVw$)gTNlSgN!$=^8rUk*W^ z-K(A@ed7On{(1Gy|AY!E+Ozg&+`Q)8({Qp7>Gq+G=Gw=dMA~{Jo7dz=4o0L~W%Jr@ zZC)_z>CNjNO{DDug-Guqk(NA~iAXPV66wYhK%{?tSP`kvr)~d5J}8J};wGrgya}sU zl7q?Zc-=aae1&PCRPMB>-tuIUnOAwawD3Xg%CSHmfcfnSG{VGt;%Hh`a}Mr&k?db> zp9J942xw{hO%Lt%hb(9VlTsmF0R=9Aq7Tvr%LmCtC~5n>LT)x!8-Q@^i2|Xxe?WY! zbIDOP!QU)<3RB)7ok3)!=l}+;6petWR43tV!&CzhD#JJsMkif~zb>hCGpWqzK4}F0 z_u&5ve31se>>JghJU1t3<>Gq z4E;!*)RV^VNmC!z6MlhuKg5_qoQ5`&0j4?B&Znl}+d<7M!rxPiJgn!8M#nrkIidU9 zZJzglqBqGS6diMKr-Xujw>eVZTS`eiI_CG+JKp=DzSoyyjE)H*D_(jx6(aEV95Vh38p$XNx%iMj&Z3;S*0iYKBlnE9lPqpq}8X1c%cnzDgI; zb^@WdGF@5o%e*gnD;4xQyi&p{V>1bjiV?PkfbV6QU9BOM;{lJ>-&>XuRaQ`R`L^xk zU8;gr%{eOnuxjyht@D#P`A?iU+d4wGitle7K_qM-4*|5wuyHB%=Gw4v0I(+v8?aP3 z4I6~YsJ{;Xl5fQB*YiuaiiBZ<&oFZ85!@BS#`%0)WgQk>G6!vbH$%QCx@2ciqC-um z$)wKuiqdzaU&V-6ldv60AWBl&vJ*2d=75cYin^=^@KGo6IWmPUGU#F1%+J9UV(0Mc zmSZ_R>yNA#sC^$s54PBgr0lHxvc)`i9W=6o?{kRC9qqLeo{-p*^DWP-gm-1qmYjpW ztSwnmvZQRuxzDMMu0(Bg?9Esu;lg@Lj*IgSwq!Bpt?M7W=98d~2fHeUNokw&Y%;_s4=k!(g5=V8&9*+F*U847~ z*5aJ@M<8A&+Iac@9_*h9mvij=85~8vxYzo2z-xb3IV+9$N;xZav%>Y-YWmPoi5ve9 z7?Yav19LFRjM{WtXR_iH;sW;!#%TFsv^&?lmyIBgSx{%mur9Ie&(a` zN9HlBT)kuC7^rL>*Kq;4anP{h*f?~$Fql@j%}1+T;In=6C$v-!D*e#}aI`^AGslE5 zeq#We;W9B9*Ci9e7Y{mqQh3QA_`=9$?u#ti>y2ER?;Uk%N$@A$$T-h{Z@f_oBxf8) zL&Z_%x_d}KFbH)4IKi^`rSKeYBWHM%D+!5W3hqLpkQ7_tf0$)h8A;*vu9Q`6`X`3l``GHI2JC0g!U7oYaAR-H035G8d;VcQhE?(nSded{C?)e zWv+^IIbD zI%#X`e`jLtCZx{DbtBbD6I@&epx6AsnvnD4UUPM!4i>V`Zmn?2aE||c_j#6o`eFO$ zi!(CD6sZ84`oP{F+PCVS)gNnru==lrQ)25x7cd{Bo!Ht1Bk1dz9wYky&KkcF+9z)& zpSE8tO*(C}H)GWsd{A%g56Afn`SUKPj7aQ|lXrn5Lg2wyA?etxw3~&l z@wDiA({C-{IyzRrzc2}1*^}*9{i@uAW3^}9SeHUr0Mt6Z3-DGjwwrjd+TLxz+@kKb zZ)^9*;oIt;Lx?ZkIaKyQRtHz0Kc zv%^VP!QPBj!yR1uEO`J}aUvR9$9KB=C$lea&FMey@~gGL2a2V@H+Kkxz7dCSRbF(5 zHLXTyqoAv8lYy;M1U}`gP6Ji4_4C(kQPxj45X)gzK0JZ%+h1GX4xF7T@J-rIY}^Dk zuk$ms)eN)*zCm)Ysrpzg@KM4He_*N2V(<{l0{Z=;IKenF@DEQNV#Y}1fk~EUy-i8N z=0;>>a}^2LA>UXFTF7OM{Y|FP5(OT*Ns*P)xBUvo!rmnJv9OXP7*U`tIpS(hN4{5E zlZg8eUiOdv%9>6i)Wre`Zhsae3(rzG=7i*Z!m1h1`EnnSY(S%U*~5Czob;3PN!$r1 zdpp)Ov&a7l30P9XFcV((buBKnZssQ~IE@}j80Jg2TLTT8C=4XUh2I(E1VpGWwE0l@ zVTX^sy`Lr@-b6#mv8C5gRwX`0$sGQ^^=ifS;Y|sDtOa3BbVwe+MBj%-aHN#b zVjS9Pm*o!$77_(KR9p}%qwYNG^v2CM5%rw3`96GGVrG1)EN1SlN&G#J{Jo#WB&W#D z=IS0T<8zm`<}4npxTFf8!yLN1ftXVF$0LdlGZLU7v7E-v4zU-?d7=xf%ozKjg6=w^ zOlH5FU*2j>j1l^AhOaXWpcGDw*90qM#wEbSEkw60BOe&y=s3$Fx^r>pcHz)%gtiKP z@U$bID71|mD<#f0gXnACVgtHHzZ}2TCgO+h>c~!3@;NP6M&y2Tb+9Gp6xkWtp|@j# z43z8!Q1IULmbbu9rWG0MsTLUTPzxBV=2A}thC$C4hqFl;5Bdc-9P*%FW4UVhv7#Ma zHI6Aru-znlN%p^YoTzPo_Tz~n2lv0ndHP`f_g03>aS8wXy>NHZ{`W|`4N=ARzrQ*^ z0cm>q&#}E9f+d{xOMBHe$*QHW1h~~;g`j*%7%q%e_v>ZDX*(|@4}c~75{+O9bLZ=A z9a$KX^*C2L7A*4#>fW0zfC82F)_PdWx)2!Haak+6*#1Ly{CbBoKU5Daj=ppQc!Mu` z4e;KQn-3K~y5s*Wh>g%K^wPFGz_^2HcQ54GSUYhDrFoo8iaqu1!2&)OdmMy^mL6al zlKoO;1)2FYs%Ya_xU|tchkD?Yy*=~hHQND77Y&NjVD_+1XOXm#QtZp-Z z&d{UG!`OX#hs_m#wZj+C-uZ<+FE^mS%5l=3$Ex(Cz_3_&Wgr073TZ(8ysT zGHB#3a(w%M=u0fuxMghUg; zZaSfd)PIOh%T-&g#K(V(NtAPJo zIP&Dr?P)qsfU(vo)rIj)+)c)jzHCuAvINV0#5gkC@$G+rdD-|G?YaEq^f)3Lo5qn# z_zZD`IroSo?Nw?`0^NjkdB}+Ok`sIqbuUACkt32Ce-W`JDKIP@a~a@N6tx9=VXH_< zKruQ8%A)@0CiOg_^q)!9y0-cvZI!Cqd{Qq^{n@w9)_a;d7le4|7`g#DYC*-kv{{2P!bA6}8C zV-h!*E6|rGa$IDBt9?VbW0JMZtnkMGNEs>urz$a&z)(a`sZ^3CZEFy2(=S=tHM1xi z)3rC8n68BU=-fXlBiEEhCLWJ0bDq|TP}S4=ybyY46bDLVU#JXU-F66Jurf01cz6dQ ziOCKOwW|JOBQy($jiwx9#Y|qkfPbJa9(L^vRCntx`CQ%YFITa8@fh54><+TmQ~-oD}c>r*TU+IviP4@S)(&T?^|oiv*CEWXRK_%jAwjzzT@3{9q+~> zd@F(P7ahq7#m1>jbZ=#=+_ln%ypQASPEwm0hxyK;yTL~Shn#Dm;myx|ax}<6F$2pp z|4>OH&Ub*eTIM2IwEgQDNykbeV9k{l+Wb~-Hdmhyv~dC3U1LP|Mt~exOiu+zZj~U) z8YZN4Jf@Pj@I+|0w{JBc`}P3RH#ku!>AaD2q(9XBSJ&I~e=NlZIdLbmy6?I4IJRre zVEQBbo{;@%ra?_5%ZuVk+64AytP1c!%~8h51K=o^q7lb;7pB=dz8`#|>7tcjHD!m7 zt(6XtC9o{bY|X@{v98|}>9*C`lcG#w$w)Wuw2nwO%R;(-aG zgbd%G;9IHq#vRLF-ySH-{F#GKdFFk1(+X=s0ym^X&czOs!0nKXQWrCG&oy?>u5>*w zwTW)MITAJGY>G=A{}Jhf+Lv1+GD4DeBn=WVEyO{#!{o_KBMfHN2Q7DeJrfG2%NLZn z$5S0Wszhp3+9k6PCYb=^%apGw*<~`#crvfz6SdZCW=J~XT*bg1wTjmIIr7~s(|q|5 z;+BnG%AJ#drI(gU6Mz|^M|qN>wB(RF7F?Xf-juR*1s~MxZMr-F_I5QIv4sq_oKFuQ zGaS&0eT>kiw~zgFnKg|@s9o;^PG~=>JMeIQrefohy5Yn@Pg6V&a?tNk?_^%<7Jvhy_ibAAc+N z(FseYwq&O$J!O93wV;9nTfEr_%0n^Zhw&Z9NEgn`G|C?@wP*QD863=Gr%?_|Jz3L) zn|!k70S+hYI6zX5@3E|DK$^Sd@ja6IX{@+UMdfj1=HGAr8*_Wa*0jf#SfJ8z+Op!Q zNnAXHvVD>@?F1@m=stCs+-s^XX~`Z-_bJPcM(2aG{@sD!!+)Ueb5}=iAJdlBmD2>N zEWL?5Hvy>;Dknaq@PyE{NmQmxb;F!%=fYwkCi1~TVxqkF z!2M)$zGNzz)|D?KGt_5ksp-1K*5nx>(aWaWjnu*W-IM0FR=rn|hokmlapUtt=~=ZE z=WP7_z&z$FoX9$wCNi_`-8WdDK8z!_DMxHnAVz|5tk1(=!7=f6bRe5D`8izwN@m7x zd4#HM;qSJ;hoy;iGlitssz0^nBFTs}CjpQVS`MU4U7p7_s^!rKMfO&6p(T9%T5dL1 zd*`-}&#i$h8o09hS_=KBsQ0~dHLl+&Xqecq#DAZz<~SUbPs$J6V64rm+gqv91J~`H zj^r8e+I$~g;G#)s!XV%U$8-ijBHyUzM&OT8uju)?GW_rkK$OTM6}Y0izOQ^o@CN$O zMTiyD#e5_^I6U*u#+}&DIXUpBP4bY7Eku@lett00zvJb=#15Yh*1&C=pGA~_Ct7EH zmQex-395Y-8 zp<1cqEWihl4*W@=uQxB;(ShFKZv**&l_O6Xt>=?*(D1H>l#Cq5ys9cFl*{mQ z|0PmO%FKn;+@}=ybC`d0-4hp)4x{>Mk~3wZM5tYv1t}v6O9wc8+pP>B;(dSR!<;+# zwxcR&Au`e&k1Bxc;piSHEMrYVPx##ge>3MH%Z@G0ruv5hzogjKGI+4kV=VwL=0uu} zULDu{4Y<)WUZQ#wq7|N+;)qt5zEDL#?B~2i$JAcoxHm%X1-oePbxHlpT1X5XkqKPJ zb%P5h_7EwZ^e8%!l0ARKMdI-jD)f9y@cg0u@}B^TN%yA-!ld`;PWa`k3PzauA~o}t zU%oZ-;+Ov=T>UZgi9*9DcNA*|jQ;SR*t7VnM~HMW0o1E$=&X_~)u3+17V{QZx#K|1 zEoP~>!K*@K%kfs`vOXGdw$~`capsS3WMi=r#~&SCh=eN4IZ{|UI3ogef#0kSjtCUG zSS$yw^m|hYW$5QX9g81X`YKyv`9Bk%-wR-LI-kT!Oh+m&{?i#rN;`_rHJ4hv_$Im8 zTs;M1Gt#<)2{UHvAP0~X&5I*#u6=xH-->f5zcJCY)E20tb7_Biq+*9 zD{2It_dqkyt6>ZVG!y~vdACBR9xuEZHZo6mpQrqdz%WmA^ia>H9p3OhZ_|glQ=+-~ z?h!q*QIG!UD&~x;8aXlBZQR-D-rblT+~7fFfbutjud+&U)2F#3dUQ7G|INvY_84NU zJtx~e@;oHR{tzu12jQ4nXw+W-600=U-j|PE5Pu&jz~7cS{zCb?FO1t8ah6AspZuoP z5#Azpo}9~&35A{6Xya)=*WJ=3n|li!#&vc%2Yb^I6z-s=xA*bUOgVCd-W=v_CdbJI zqNXI7OW3wwgNLiwwxwWRtePw%I;QU|2YY$%I>mbE+T}0*)Ci5lL#W5P(5N4RD=$+3 zggbf5Uot{2{Kh_-+cvtuSamdS>VO)I`?NDPdto9Gy`LRyxaSaUxp97p=l@s3egF5^ zb8mC3A^`i%Fbx=w1cw3GGYd3eOlo>0fE|61b@(d)bF9OA0MYa8J!mF#t1v68A}5P&3wn5--ST34`;PYSj#JObksuQ2EJ=VGv2X|n%FO;WVwu%?Kp}j= zv3ELIpg$WC7;cw@A|NCcJ7S~af=r|}9f@?dW$kQlU;c__=V(FX?9nQN&Nwpev5z3l;nqLh~;^vBqV|IGM(G2&Kr3 zYpnSJvy;XL$KmP|Pn02c`!9z0$j3=T%rrjk ziU)}}4qk1IPw7_U4)s)(cJ#SLftzc>7vZ@`E6PW4Zbi1K`2bWm56nP~Hc2lC`_Uh*DnM==_!pvAzE zEZC-Ex1Qp9`cS*%wgN~LJ7V(;t?DgkV6=Ka(-r^ob8V2M7vqY zxkHlD{$k4L!$OxtJ$lwmk_Vsx>5WDheMYwCEC|d-=^hFG%cFMD9XXHcooz#yrexT5 z`7>tjFF>o&qATUkuy5#8KC8#CJlVV2u{2}W;vw99j?WI*=MBFRKMOs4^SJboz2@uo z_z&@W!3z0(J^sXt@%wmmhA;HtpYT^qz*M)dv-`!)SbZPzDQQQ;!}D8fdQvzN>7pW+Xvqo_!F8`gt=5Q#M46%=OdypFTsF~&F3 z0WiF4=6dpE3x5*&_rph^rYo&^GD1ubkjj%!{Bartx|$Da1nMjg0D&k4I}iwmggnK- z+NU9q_Z{zm*1%$F8i-lSiFF*=X~qcB{tn0v5MvXn$W)E#2e_N8F@23K$`@%T5P{XT z+;uk=;@I$z^pvn!BWg%#u)d>UPThEt2J5~n?Af_Nzv(2eE0Wdt?9Es;l@IFKnPsW* zN21Xv$(w-RM)&bWxEv^#2(y*iR6mgP^8#Z%J(ZAx9%(tLz8BxIqv?0pL3N+&0FRXr zQy1_4kAXTi_4g9+l+To+{@=+1SUmbn0j3~+8{KoT#a54=b>-#NV?E*V2;#zY)ips= zfxl7sF$-8~BTOHl@lpotc(1He8W#0Iq+-rsg8L9bGG|2hyC)1y2)+7?( zGq(%pS?>o(BdXx}#$LpY~W(v^s^}KewVZd7LX8q_r8b%tsS+Bj4uwghSxJ)}I_zS;dH|q&B z$`O?SX`(YejFRtT90oV713x@53{xqOZPdZ(?bwSVgfZvDS^i`z73@z%DnDJy!Jm8( zp;RONY5I(}Z1N79eB79?Q@_`@$=?bQ<7OIPh#0eUS)6Thc_!%yauFkVgV>K*k|6@Y zTcrvzBl2}Fzur5Lm27=19Q?vOe>Vwe=J~a}GqXUs)&mRFzhR*5AVnLtXB{%k70wP> zW&}=v<2G5%L_D>9P34o&<`bpNa?aJwCEkcNJxcbwwNaAFx5eOFS6wZ5gx= z)l_~Dw)JZ~G;YdxvDsnEu5mt$U9WDjA&-fs&D{U>Qw^e4iwlo~DjJImx9-vrK{Wq? zey_F10m(|z(z*ZDXt z#;6~1UN5aq@!eGCK9y412Lu^EVI7CYOo4+gzEJlQ_^!VQDh(@c1k;?pf5N&l)N&Hv z#7|yC^?Z%@zMt38`%ub^{bi@_v`WR*5S-+Lde+VpOv5kBKQZD3>!uc*MAXFh$7#qh zwWjKn9X2_}L4l^}uz9<|43@RN>9p^GzC-MLwy63JJb~KmQy9qGpyi-hg@Xe+Fo>KK z4B0^lBzWC(dxo4>!JCGIjpkR+=!XmJ&j zm%g1_HDO&rq4X>K2v!ru2iKpat3Ov)f4j_tf_N7;W2n0@xrxfRQ03)S(v!x@(Lyuu zQvzqj&_r4jO)&h8n+Vr`kq-VVH24M7=}lDmJ_yr*3_ZN3sV}3c`cPR*;2|&HSVQ!_ zTHdVN-^KO^Z-!}hpP3${Q!CI`-ddoIb|{*!{8h$EY5u4)em5E>&3>~G}xRydDx=_ zC6PWE^4OxSLLOUcip(k=j|e{C=#B%9a#B0f++>GK_*tYG7}*bs1#v+H+8NPUoOD89 zQAcj0G;+I<->scKSd9hI3_YAK&0|GfWI;FdKZbnTv~l0fw`ypIc?b~=&A2GkXW4v6 zjs^>mu8+kOP@As(==ezO=j{cW556zLt~W5El_Fpc(6qg}TN# z1#=X2A5yi|s_KbqlNR!6v?|5z5E^T2KA|}vD~}Q0r2G35cFN}oiKr7&cPQu!}i z1=)BVWUs{7KmJlRhA}`kU$=jpAq--q1rN}}%8cogN}SWDOcang1!VAQEP&;J(}pNX zlBbQ@jLOnkd;M^e29_(vMNrpX1F%R(4^Ye=gdt#4!Hi0E<+aS2!C_=>AYAPB+-%S! z5j4`m#e_o@^=tV9EKuYrK{o!qL<}Ni>C@_191?R~?^<$~HrXHLmushwgt<0MtEfEY z0MsT$2xozuY=|Ay^Lwh)y>CY*zqTIe*7FvxM>=fsXplS~+uSvKY-BW8DIYbv*7h>2 z9RizI=*ZO-9xkWcA{hq?V=nQ6Hwfiy~Hs89gyQ{ zhO3*H3&D?!^rfXUyTSY>Iuyqw3oHceh^Z|%D04;%1W*V&?VYtIt%D@|Exkr4RlfsGF{mDNxL7`{ z)2-^PT{Z+0@DBRbLYr(!HiV&-2wKf{F%D>?n9XdvI7C3(0g4<;C73}6GI&u#(Zacv zKFc##jOkE7KDzY2FmN}>Ou2HswiZFWh@9tfK1{^KWc$%!$uJ>wDEV+@4~kD(tRS+&-;X zp54ADXN0x;`XPKnOLwKkv8!5aK z)j@s`Y|uTS&gT6+ofD`yjo2}0F}07`Rh;fd83Rrq73T{Ar8$IB4L5|k{$qoKHcUVu~tgex=S#vu*aiE|4aEW()*kqyx8QfYZ| zS#?d>$@=LJ*iBy|>)|$=>98%dHg}^#-VSP&?Q(Y*ecT94IO<@$@d(Jd&XK>>c|MLk z`WBYe)H!^kO<=%MA5*LLO|C%t1(d1n|zp)$g8S7?VB%adSM6>86%#e&AgIHg0R;JOgkO1i-f@LwoUfP}Iv z-f*CazVz-dIErD8`3&B-z~a|GOzrtk(O?V3HFR7`zW~J4l;!oMaL_}?RbkEMM=DYb zbzGngbrL{M@1?T!BjE3PdGj;eGdeyX#;-->SGK*Uc4{4e-@MuHArKm4fs`(~lQ5ki z)L3le@#JnbVe>m2-i}e@8R$!ZqD$8hh}c}7u{>bY5py$;f`>}_8}LX= zC}xke@O;wzwJ6}aF0lyWfWXzocx)Z`&6jA$H|Uwd@ZP#!>0HFqsu0gNO1kIY4B_W_ zcz!kFDXV+xdgU{I?pkd3UB3J+GV1E{I(~u|;ePQ5zJCEf!H&4U_yxYd5I>M1FeUqj zeQG)oB(ygF5je&mIw)2Q9bMbyNp(>(PPa;{ekmg@g8BZu>Cu6GRdHsr!7rr^h%UB3 z9fE@wzE4e~wT3P*-yTSXfu=JxCzt>yn;2dy-j(6CL(h*}x_&t4Oi!7=uL?-wIn2`a?5T*!UZEg zj+IZ=xag_p!#hDM1oT`T-kUog_V$%l{5)m;7b@JT>8WIZk=jEwz$iBP=lfO2#bNQy z40(7lA;w3Ot9M+Ozbg`Vf!9Ipk2W7-;9o~Sk@Y)O?aJ(?@edL*;GeOc1gtl;ekU7o z?(2Hu3Q~WJk+L9(996G#bhbUp&=ndHwHAImrXdZ*e-eHx94~e9hp+3Xmm=_wP_GT} zKf2rif8_it><`;avW~HX(GArHD;bLjt!+W9aGG{|@^*txS0wAu2iA4)2hi!Vdw%6Z z4^Nsoandv=jsQp@Bh>uXjyKqPFzh{TaQv^iK?BD*N9+-zf=uv95n`o5Ai!Qy z8Am}qTjP*CDbhg9GsbMq`?&Wq4YPv6nLc9Rw;2mcO2no{DnC79 zx4+JaC44fkh-vuP%u)Xf1sYbJmS~C%d>|-RclLU*b{w;r->seAQ9XNQR>02Yg9KC> zH&gkuHr}l|PmK=)CzaQeW`M-S80V>w5I#{hAm@Dy0&e;|_0I#fuERLGiQ2_^s(S2A zN2yt@KT0jowUeW^qh|~+{lUN(#8GMzeW)ItdHDkn?mJIW&lbYrB0&{RiG~84*(Qx6`DLs&05mxqtp&M$SC_tG-O4u#DHuEF$5K|tM~(& z=k&12qtxD!qf`zWL9``~#+x}xeIP%Ay1O(+)QY3j-n#M`T6x`3>eJU57@0WyJEmh~ zrThUpxEl|3N2$7WE@L@wNZ2!k4tJ%6l$TLMQh)vcb^Hzw8y~46&S_4Zb1F|bMoM!Q zC%5EjNO6vgHBAv=Wk$~TJf98z&9HzNrzB-lYGFk`$`Jp1-^FZt{7dVCn@FOnr>% z?-B>XB!3sormW^n9#X=)49q(b9Z{bEgS}c8A;Bc!pF{_PK^NN(v1Mu_161Aj!VI)s z#L~2}wWnDBxqhAHs9J<9M;jGkdeG#Bh)jdUH?{SP@0z}mfu9>=CTBluSWU#@J6boD zJMssZ$~WL)ti?CA^^5P7I-mkPqm5gI)iVu1iN%-WlB!GGOZ)+VqJzpN7vEG`d>5$o zt7{w8#ZIo_U4y|TYSFbCx}2k<7v4>O7Er0?IaE_=*o%5Ozl0Zc>;+fb3uOFXl>dj$ z-jZ;Cns`IUay8Im#~a#LU;vM5i^Ln+!Y|c$LqCNj+MPom_`&gpMlT7=-(mYva+aVz zNgfK(57h@I5*(1!p2bG`1-hR7HU^D8^NSed@Q{v1%lHG3!>#nN()CculzSiIG>@Dq zj3gU(H3zu@KyCE^eL-SoBgeSMaw4dXwUzCpx;v}ZY$6Sjo?Ra2i0%N0wz5b=F|e-p`e;-ll_$iQMZfNCm_<~Zv~U+q zQkALB;}1Zz>*yhjLnlo{n1$QnB$;HboHk|VqzCYbv@tLf?SKXNG#>oM5Sv>*S@EvrcbpZEo$fSt`}aRZ)9d$?mz&Xj-P${X zd$O2_UOJR4!{&h6Yzc?6kz=TDpq(c))G1|oZ zTkr>hn&4H%E=Y~!ITO+4==llrKhTqvq{|V>WwTA83C`K1pAjp};Te5k02_nQ5$7fA zN)78$IfX9cDIzS1OKQbD)r;b{(I@IO9mDTIDi%CsQ5?&g$UlbFE$qMCv@_i+*^#zm zF^Y@d5u>gLfP?j@0L1Zo0I(jkS`&Xe*`D&Q?)$}bZjL8>m!*O093M@f`3D*i=(QSw zUc~R#PQOGYP}cXdOBhaH4KdQOBdd7f2h!_88c@*dBds`3!FnOBn5#cf>Cnu9%HQGD z*Ch3>|GnsgO25WrrOoVT!txskA3l5Ge5cs5$ko+>G8c*OZG`1H?`QgK0mu$gVZ@Z8p@^WX@K6BAXA$fPm7a)>7AkYx)KUB5%n%XTQz4H zb52CbBlCE;!&Ffaiz=>YL={~HRk-HqDWVnma*t<*``ReF)xh6~5z$Eo;eA;KzvJju zY$Q*B5eQz+aZ5dBJwU~CP0WAF)(uPfH0WedZf^%X(yG}kSrY~_8h8e zJj3h&3k!W%E1KX4D=yX$;v5`lSA;z;XXUOzk=;WJXEKG~RZmYw*z>?7 z*lj^ry8Y=0v()XcHF=oS*Dad+n>^awzx5(9_xGZg5Z-k{$1rty>7h#&LUPA7kT}Up zKqq+g)C7+OjN5Pu6Pit}SZREKMQ{h_#Awd2by1_0W{|e1F6Vb^r}wUj*H#*EJ8h+j z900(Po+FU_#C#{87k7BdfK8pgg86CLyq*Zc&8{*qpq0O=8P?OJ$lzLV1+aRyN#&WC zv}Sk)coQ@2*tfj#M&mjDoNh+_j^AUBKT0zS=^jHv$&?*%hI!^tb+EhZ zJ42)0M|>FOnoahJIcLlJ^oO32K9Q_PCG~y!WN%~6sh9QE@O$)0$a-1SCrj>r*#4WP zClS3S$%D*Jh!}T6A%3Ld6T(Btk^L2x3r0I+07MUn5xPagdguZTLg#2IB%l-FkLaxA z3V2SHf@y>>NXI|Mamh8Xtj3Y)iPB5qU_}08?_k^>dh3EDeAh>6f%2O4{MC(~XXUK!_WktPm``O4%-BY0J_bCo~kxf(rwjRQ4k z*x7S_7(2H{kKN@ISZ{GwcKmMb^h+^UY0PxMW<~I%&Csb&L~!)*HBqxQYQ7@t z!+kdSsNN{L&U{heL@+HU%q+k`7y z4`q1|LKPxM3jp9_aZP|0A@WAt1R~>k{Spr~K7!GrYmr_4Qh6M&>@rtsmlblnvsHf= zKirpkz~SqS4;>XYp9Mx)mNHt7)aGG(Stf+M6r>cT{%(cDSM{ycz59fHV86DKhivxY zjt~TUqcmKLRlYAnxT&rvR{X z1VD-c1OUwfz-J2ufY&mB1P@s2d*t*ex1F#~y?@w3ktbDo1n)nNdY^%vM)>`Nz);i~ z=^x21-ze9Lb_CV}>w!u7g8NVY@R-}Rba0L&64i`!>v$MOMG%8Qf!T%~_1=CBSw_aDpuw7w}tlF}}T>?OxR90`u^% zq$lRks66+aDui}_vc`opNN}-|6M_kFa*RMX(6Zarv6xd=j0cKI)=+-kmF>;do*d;>=M9-7oLL_!3UmDGR!2{J@H2vFJ5AGc(zVs9w0w zpt0&|&98H2goYOQhvq=eimMqq0+C{@^0*9nM2>%G0YQrxU~_ZgU7PSEOkY%=oox6A z7A7MFHzZ;q3g&SfrB>IiXm#u9QN-Ib%bRI6mXC-oj6@f#$nyw+NMDtU>?iM_dG^>*nLyvmB4x9G1_{%4}e{1Z|+`ICf-3j9T) z-$f%#fj{9NoMq2fN*+N-<2=qEYs0{w zpqAkZr?uQcYdLZ9B2nc*t`fCzt@)Ko7kV+fful7#vaXy0Tu81@H>~&o?nt7!W82wODd;8shsgO&poRch6tNTP6sNw zFrJs;&fxg4CN0dW-|O9m*ms_)+`mjEl5Gs2DOO#>-;-sk>+Z-j|q zwF+Wz888RSffe||J*yvL_PmNK#$ms}AL-$ocLB&Vxbhd};V*Iv;jej_$y^WO!1r_{ z5^1wP?k4+-?1VpRui9FDlE@w?L9Dyfb`1C-_imiAoiLdz8Sm~oY^K3|J^>>uMvuUA z1lV8Vb=fROob!dUS@t;RW1u$^Jb~4=K{s?3(F}eB&NEIGl z4_kz<*SR^u7n!)w2+%m>ppWE>FZ!cRroUsvx$NIq zUY2iInTXc1tL5Rv^_KM}XG-uQ^pKt*pK(^Gs4xr|=3WhW1m>PT8#php+WIN@l|^2! z&AjizGmrJ1`HEEjHg|3gPdqpr*O}!l%G>9q!jJtV%}~nf!}CvZcA@zP*WxfVxNfXbS7{=6F}_T8_2BMy#`pb#9n9_qldG-TVIy|5n2rYepd9f` zBDKt%RTA0gybEiJ6NgQLG(bTP*P?oK?wx-ONM-~wx0z=L0?EXC3Zr^e+acKn&;FncXx2{kF$z7T(| zL`A5~fzK^qvO12E1CG)W@L_4JR+mP2#n)Qo-NjOIm7unbAQG!QwyGH3-JmpS`Ea|m zyvSir-fT`rZ}vKTlfZu`RZ4EkyeN--H#knZ7z7UwLcy`fwcgDBd*DrVHg5ssr9(^N zi@_r;Qt?{Bx%4%c?K4sBWnbXOj};l*cv5A_NM-@H@{P{U%*Fn&;Vu1>-0DV_q< zWo_w!$$5n~U04iMJ1cpnLRM9s{A&Xb;>L_-iYrR&)J}25EJqMwD@J2^o~SL)NHA}5 z^>WX$nw&j@7kP_va6ss4OCJ==yXmnj1uQtsLiB+=BJ#J!Ki)xt18wIri6DsiK(3A;K<^OpZUP|$CzBF^m)5PM&?kK2 zpa|3Z9iHBMj06l#9(S`S(oJ+CMmLMl&8o)Tj5WFS^Lxx_3vx-wZ%5=i>TEicJI)JP zSVd=*zjdIA?Yb`rlTso4x$e-q>bhCq&2|)I=Thos|0wB+Cut10O91!5D7eE$wHiAT z_7c9N%gKXSw;!{;r`vDA^>pt&M?<+)%HQ0o1tfMwS4=fQoP#Pw`Aa(_0NG z6#-`zJ*^W@!{9viR~4LG0Zu%QBY@i}0-Ux2oc-JQ;TRR1SB@t@%Mui@ z(?(f~FsiTbzL@phXn^N;s5K0XTA$XRteEB7sqoxwfamDk2s{*T7WR-rtqZ&?As<=} z3f8v1jmgPbNTF(`=n2P_+uI1$p>Jjn<>CDy%pV8>Gn4&=X*95Q-(BgB{G%nQb`vT2 zdVm*~_C}y3JY)O)8_1d;`!zb6psc-vKo@p-A~Qc#!%D9Ip!e6WZb03~mGLw{pK*hz(ON)H``vEVCwR`(VV_RvG9&X4(_?VzsG8!L10 zgX|ZVBTXag6Rh$kDAcT5zxJm7-6kKj9j~*Qs;v1Ztv>rd675nEY^RGh*=6J&-SmRMv+8d8XC3B zYi)9^ZL2cWo4UY(o8ySuv&o*n#UTx?8{sQnfJTR|waZ%_o^7se;BNy_$d-M=R(&Gg z?(6Vi-(#U6-qeLwQ?>bDZBT8I_l_qJvFa^bbuhzu9>B}pW<7qyn!l^0O8`l6L-c^} zr3FY=8nQ~St>dIo&h}Kc=MxUkhfYLQi4?mqkdE)d`%7JU1UQS7?}zd>_u6=y`&5qP znSod4fBgxPufz8&;=X}#)!I{bS*sNdDBJNPb^z6tLySrLvnX)?sbqqb|F7K#s1I=|3MT+#$0OtbcN%&FgSCh@I9h1hq@o*%y9@?f^Cn!@Jdnmw&q(F<80Lzo-GRhr1`=E+wJv* z2aCe@G+$WsdGj|qgvE=(_qVk06Z*m%+A_k(E4xLsJw{)+LKL3fd|?50cYWdEqA<7rt#li(u}hFL|3NS(;gQna~5U-Ba|#_`?uuVzXL+&-i)`A1Q5bu%Re zwEgrY?-M1Vbv!NI3TRK&>-u@MC<%f4v?T?!Rr-=gaVCI%LicjolA_H=^(9GTg_7G^ zRMM_5Std&2q~^433Jjg6FG=z7(dMpZN{W8&I;O)=swnwUGbKfvzt@-CMtVfwZF`$3 zDKK=8z9gM#pycPxloZfjsW15xQS!@XN{TiQ9@X`e9QM)X*Ugj^{amgu`6Z-Slswo> zNdfI_eaWSwp@VVU&( zBP`Iawas74@;}1GdiJ3jk-cG&Vd}{3L?V^r0XoMw&Ijr>=ptSQ-i)iPSeql zLa%v0I1YR3hBdT7RtjJ?Ng5ucsfHQE)p!II$_wNJ@9TQ-0Lo(PJAN{S_vKx1A6(L| zEvdb_Yg6|_uum9rm|992NM(8Ro1pG&^y&dk-+(k2RX8Q_S79*@9kfc-!}tjwZd0P% z46P8=U*Fc`;y3fsCIsGkDE59)jn|uJleduZq5O@sd~jjCAL;_Tw&0O^(t7S~u!c6#ca?}&NcJmhar9@;K5WlFh4`_xCD)AfCEkEd7R4_0*L+Q~ zLw1cde}}Yy&S4QnZYd)C)>oUHm%tn|EqF1tT1}M7`&~KX)p+^r;WLqWWM0=>^$JXBH>v<(9e7vruWNLSJJw0~S+Oq4N z=h;o4Sra%=BTgigoyXh9)mtiYgvMu9_hB1k^-?2K(`@c7&`J)31`_Qe^0;Y3@Ge+8 z;~CPT9(MMI85c!!&D{t^3LjDedcQq?pH&)GZ8NRE(N}PTG85HP%VhFJG4A$}rez`? zI!q1q2_{!^kuUN3iiBVy&h3&Nreo$B3x;Sot%sNw9Ymuscjg0}E-4xCcjrbFDrx*f#%$rUtqOsKTT&4D>2> zpaU38W$_0zz_4TUGxpHx?~k^Rqn@Y(wPtEV2;_&xp)>;}3dB1OBQa_)}2=myvcj12u0wV0M2okLS%PJB%80M*32r#oxqp z#(-Y(R~P85EUvKZj7*w(sa!?9RQ@92ktWSzT&Q@gwfWaKg~w{(u{sKmZ>o6QgTT*K z7&2wd`#f35(nAsxrIx7hV<6OFI)Lc}6j#!~4m?70VW&WGt#Zfx#PDbyyba`Drk@8_ z&^#FKE4YS=J;@av*T{LWAZNq^F@2{aXZ_g`4aNva_`1P}9*ZLM{y zf{?SOf^L$Brkd<}*Zd}Ntsso%ak@7Yfduw6*nK|@VJ=D@B1dF#J}3^R@i7^tYvfp| z@f}D*DG4KA_bvMh6Qs<*`9{7>UeWSM{`BLwg`5JkS|fk6|}u-b%cDv(>#1ynM46*wT1;jY_B!nNZ(0Z~e;b{v3o_ zW6$1a&#y1(3+CR>j_H-{2XkloBIe#8E%*w^Lt%OBdT?COs$-|~B4!6Y)heelJD6%3 z=_}|LC?`~l2@gVz!P$F(vs)2y9I7&6j8Vj@9inwc-9E)m-2Wh-Dni#7gd^h3;;HQvmh@TGT1KgT0 zn*FAg>XNzHo`0yM7Y5Cmy(Nst&5Xxgz|0b$@m=S2IN?qU_JxH@1~F4Oj7y$J`K`oR zmjxdUEW#sVvv}{iKe*TGD*`h{yndC9hUu14Fk-#jXv^P>>A(4O6npD?gwge85(a32 zt5p`V6f;rdnBKAPM$k6=>-LDmpFqKEreI+vZdz26*slq0N-^{e6WG8{M-j2+9~Ulm z((-P^9n$O9np{XN36nm#C{0RhBXvp$kdqyrJF(7=!!hxUG@OEZXC&Kc#=0B2l@7N0 zW|;(rM))%O+Cm^pOuoa)g$J=95VH?Hj9dZMt&p_ENm1CuEbuI{9NBzBJ3)}>H3La_ z8~T`6^+tORspxAg8IsL6$D~~MF5?I>_UXKmDTwRu18hKl4=6Sut}d@FbQoEq(UAU> zm>Aj|%*v+mq0Qe)T5|ET{)|gm`H>fbVFbic{L{ zXK||vrq}~8$7`+GnBR_CXKy@EKUPp~G2so5Dy_bLi{O<)8QpEHionQ;kG_koT7^JrYvxs#8y4_41MR z4dQbG`Ma#y2g%lC!C{ni$QxL8u7|iyLokeoU>Jq~t^nG+yBK)Hm|#hD)RtZc%Q^^u zK>u2xA98ISRt=yZtH!CMm4tm9c3>r0hY&l+4f>X}ki2}XzJllR6Q@*fWtww%_B#pd zWIhF~e*rw#DHefL$gqi5l4SsdIY%1u*rT~uP(g)?%q4_OTlE*9%~MJzlmU4ss>0D9 z?no&pHIg+k2@pcEMLuRn)*M0(P4SQ)h65&SS5DYWA!Xs0 zv^YS1*B_07b>T>JuW~BbJ`NnLK;>Z3MDrFj__`U}sQ+fw5;YXDRR%%SSe7RHEq^a@ zK0KwyvMdfp;)cC z?h}_%gbzzC@)aSH0uGT9U^Z@>SOZbrl~Zq7Dp+@w^7dT~I!MR^W2!JD*Y_&|Dt&OH z)i-CUG8*k0pI^(*$!`JjjIN0(jhaX%)^^^v--VR@``S0p-y+QbQ?wIdkzL(~BGNzh zp^)P`A{)oS={+MK16IkyF((P$zBnkr7u`zFC(HJ1n9=(!RfI%KT&TEW&Qj3NWk`t; z=HMlp>3ibR4=x4qf$Zm0TI2(?>e+pB{%!}U2r#VP+c7-W&^i)&*)CAoiE*-44#;@e z<;-|^@^BeGC6y0P&Y1qwhwhy;TrTe424X}1j&VX`&~B{I82DUh$FB_E4SMw@eU%yB z_8WTSx*7Te_K){sCEtm|1|A!vVKn_lU|A%HwnqD%6?uz@j zCHzY&{vR7{!2esH2>g@VxKO)9x=+;4_@|e?u8Tev_^%if3;#FcsSf`WC&a{m>Pg`L zi_Z-B$1(N%hQULmxYBFpH%M2&etRJ?b9ci;WSPYDfSJ5N%~|#;j`b&hg=NAc6x80MyLt26V zQ}LlSX=Ph98+aC=$%oe5+I6%Cf83j8U_dTJhz9&WXz3obsMDF6p8HksJlO zIt1}iLy))<`|P*?`N2-v%DCOZpx((9si0b?Y!lS?<+UoB|ACgz% zEI%$dKt2S(4|EO#&VCNT%LuO<@#ekAn+WB^vw=GzifP7K>V9}aU>wvNV$ml4C;Y>P z;2DVq>{S=|^Q}TnO7Fp*`>=O^TNsojPY7fMOyNZ=Tpk}KM?O*#@lB+*acXTsU!>W0 z?P9lmu2ku#V6Kp}Xc3&Rir|G+1fh%l`*gyE3O_P%`qz>OihddRH~a{VkbVf4z~ue!Y2n@}+VKxR7n)2AgSEx8Q?b3fl9J%(>0xEk*9} zVHwu^nv$y_<2vMHw(O5>`5Ww#L$S?=#1on~dzpC^{RUr+@)v1~bulz*l>0;oxkoD! zGqKq+uL6>aiha7P7toi=wHIQNZ ztFG*!QTGvG5@a@#3-XW5-cH_Wu{z821jm^Pfo))|qJP2?S+SbndP#38`HetKr2lxO z{2p&2R26rNu(ky~u`RP=_4RD4)}oXcK79`&16LTPmoen=m?pFnkrfYFo@&}+M}_@M zA*w5A<8`*lKy11zBA*PjAeYnQ7*O}-MBqG4vl$M|M~h~7t9jQ{V6-VucariTzO$5v zBoD=krf>q@X$t&#u1`sm%D=@|c2hm1D{PoU${#zUkncM8$&T2?gp@z+Gto`~GG?8! z;@`LyFgd*Uv_Wv-&t2UEe@6L5yc;dfL;$_dMZ#?wpmf_nxJkLB@bEC*ltx}TiEhfP z9=SL;jNNS~U#-oLNRjfYnOEApBM~{csy-1q>gOhd6u!&Fvi0(V zkSd<|5K;w?FMG3QL`iZA6Ny!^x@RL(lk=_`%P!E;gxyxJRdFNfTAZuc>V31lHg?I% z-!Tp0EQ0UgT>)zF&Q8ce9q=UsvAeqCl}aQDUS|S&Wm4vyM?*Mgm(mNHSABOB7yM#r z<|FynPbRE`#2QQ`v6a3(g|m5*Oo!Y^`%Tn26Egw%uYe(Ct{pbi%h7qoi7R7`-0@Wh z(D7$JfcOVddeK{Azdj*A%T;9l2%p%D#_4u?yiML+UIKfDaD;LtX{KHU!0H$cO1nw z97ucISaYUQ0t6Bwufkj7J4U4QYanvu`vQ@}HiftJL{C2epFWr_#l+`7CC2B4M^$|O zlX27>J_{M2OZLRXrwQ5tW6zq#=Ok1?_fk(op7jKQNGCto80-vw#5cvFy-+)gcl`ZHHb3KK;b|1fq@B<-#L6lQQ z;7w#bT{^PK^)y+z%c#&yV$aE7&!g}ImTappPEN^i4nbYY9}p)9!B(z^_!Iuvi;p8b`2zhbUqQ0h znaq6o3$lt9(j@W8UBw8OaTzE-2z9q#xwR&Y%^2sIQL6|vSC#1NoGNuS!D52N%R`RK zW}I{w7LaLVq(%!!B^D5kmDVaNVXBOUe#k*4Ros7~t@O3ZJ0FKh(eBGkuzMd!$nusa z(5VJ3IzvFO(17hzT%wL~htxV;sDltF`&Vb++t5vU6_yqBu`&xaN~nnOrc3VZU#OInih3O6*TQi0aMK$mqcr{LCl#aXaBEo~PCA-T}v zR;zsXkqPptc3-Jp96Jbm9JAU2VUMT=D?rU z^QeX8In92fW#e@Um}oR!Rb+&wjTec3{St~X0Lk2w1nk2wYQOke#drenD&(_Tr8|15 zE^stzSPTuLb|bXEOSF-D1KVcQ^Sc9TJ#TQ?SR+^cp>gD(yIo>-|NBO>`#ZP+9&$jr z30oc971FP6Old$V;6cm*{gB(ofG)sNZ$z>>pn98$Mg!U#K3Fl3lk$1!I;v#o7GA{VhPD`EZI1|L+mwk%t}$)k~n?m^&UP z2X^mdWFGw*5h8JDhEuC6@hKlRkG9}2sUinXO4yttsEO<60on%BVKfe*8%PbUD+KIZf*c6b8U{Y1l~wwuLS}W4aZV6ZY&quu938UI0}Gj1hL* zd|mos3zL%z2dqNGCP_;yz#n@-n$#&VPwHgPL&bimf*M?(+47IOItF?(Jg|eUhX1;> zJiY=s%h%%2*q;BT>tLWGzx_;u7N??0IskRZicPktFiyZ>=_CMo+<6OnpE3Oo2J0k) zH44kS3RZssmO;Nn@C_#T2FHZ&sHE@*$=Qvk5=(73O&SBvhCa@RL|!PQ*`A zg*gd7Z7R%d@YA*eSxDS#laZAK*6)X1t7=Fz#+k0+>=afr%A!3X&QCOYln9Y^Z~&;B zO@kB<^n1i#;lK;+<`p#3IQWqY47QtL{=@dDP(UtZf9bYX-<{KN_XoZkMwbmQfOjBE zYW*-c>8HT^eY~;`LLlCZfitvCMvy#_(^0X%3&tRSO55}R1qWjO#$L$y_zF?K-B(JL znj`i9-cUcx55_AKMg2$NS#6aeu=-}DDF?QTT>@r#xRHVQjwNaFM{7?gwCuiq=uL;$ z0Hjq;#pNAs(Q*er-`n~6GH%-5Ho3kSx-YeJ`$)XJbn7Z(`yPZ1KdLU+DIRc{fkat!tE>npd~)64}TJCB0)~$qwb$-a+HRx zgiw8@+W1jk_@w@fx3&m8W~Brd7jwLeqC6Oa6%O%^`TMuI=)@;OLSqh|uwm+b4jRc( z-l8hKv+|Tn-vQ_L&MH)Th>P(`nz)$8#F;=hm_*Ov7)6ItY9IP>_q;5q)T&Yr%EK}| z!!p_Y8BX!>u;PYfrYoSrOZMCuc%eMdpXZ>oJZZpZ9VuD{m{8Zj@6womx*8;dseDKo z2K5%Ym&3!26u8$tL|4A9uR*$}p}IGZ$Zybzy&dC}{i{PE*lMpNqmo14(WE}Kofh)0 zf5nf|VIz9s8?>3eY!74Z;1jfSKoyCof>yqdKKjl;F$6ERnpx;0EWnw2Y>6CZsN-8UGQ(6q z47wy3jVlAel%nv9z;p5`m4*l&qKECg3r)8U9GxsZSv@cTpk=^xrO^on!=FEwKFaUL zAL)ouZJ+(Yc|SA%t7K>g&1{bzS>bUitt8fx{evH-5q96QI%t{x6^Ad2*%4h?0jvV& z>9l1`Fnim&Pr&4J9gt!7UH8f-M-bBFhB#LS#$Xv|Lg(_UsXQ=VEbl=Kf~PjMN7NZu zrXE)Y_%TH869-EkBB2Xam8N2$hD9Km*#$4v+YnsyH=JS1>uF|&4ZddK*d6wS>>d9a z;9^sfNMGoPxsayN{PomTow>I0o1R1zcYYWxR3#~IZD=2-JdHnMkQl$dq=(z<;&bqP zoqsA0)G_-8!9YB(Hew)`0zcpyFFX-uAmx0Cuu6p)#6K>L3$k2=vn)`#e$q$L2c|}G zQ4{SC5bY;5ZvPU|zUP%A8UwqZFS-5cYTF;n^eFkr{08n~0VePBpW+n3 zcik`X1C>bu;)ZzX3CTX)}bf7U!c<$)ix?J(1<$e?FLr_r%gVt znn<;0yJSe)?SdD>ewo}px`T%-f?o=U3L*-f2}3Zm7jcz^1`2uy=;)>8V{6GI5|LwE zyI>Gi7i>%BjXu{#Dq=yAdP}Xa3fiSChhTw*(ui^)T#-$skc8XV{6j%DMn&LmSAQ`E zP<=2;AhhTzn}W(BeWF;EOg883f;hf^twyLSQnc~oXfeQv)doxCC=(P|d68+CRoWj1ax{I4RW0t~LCGz%T!rs=z1 z=eh@c(Awn89tzFKBBgvM5jN0>h7i&Z4PAv8IxhmM?4Fz0<$#Z5)~Aa zYW$zN z+I2%QBFnGeGp=@`Klc1;XFi*mZ?T$=^I>mTK8Guj^K#gTb;Q3;mb|UA(~-&pmb|nb zsdnwL$_-d4;coO))r57Gw0;|xoA7)T(TYHMpg&vo4%*U{OharY-qCdeeZj$o{1t5Z zTUi2#)tc8W$!d}0E_QVGWx|Te7w$Ts&jSB-9`>ruDgS!x#%U$#d^MXa`Qj^PwiZaLCoROTZRt>9swjmR`FNHOalU!L^1X zIqpqlSFr9@)MPcSwO#^4AO6~!Qftkv)8UlhrSZC44AUZl{SxmD#om5Q>v`FCm1*RJ6s<`5Nf~&_~U(c`7H+p4nv@{oe@?5kqDiws5d8@T!UcgxR^{R zAd=aAj>XsjgEXONL+$|Lm|n|bh%vCwhu#mz^i`6F_G35%2tX->`8lTyYH_7AluK6+6+ zeq4)`RoS?hnDi1q9)&f>o{9VePDDzDxmI-pQg!T*9xVkJcJDpah%1Xj{V4>LcTSn! z*)f^)PdHV_VRV`X@ZIq9q*&>I^0f%Sy&D7k#OVNb3V`3cPz5+u06ZxSFwCf7$gT(X zBOn5bQUZ6sRKA%=izhwqH8r z-8fKILevr>X+DXAkvSD%kHcD}z8@`0i%rh+(ezT~3)}`J95n^o;g8whh9*OVSlCeZ z1*!}2ag34I4IjDYDidJrZhUsXV#70DmS8YVOI58>O6`fI3NYj{3=`>DFMJogBnXmO zcRHLHTi_+_^DS7?)*yM1esba3I3MPJMT&1s3A^k`1I5F0)dov3dDVE_L~7;P0mlOP z3M0gQ<;#B+|JkM2s^I#Iw3ohgd_R3K))>q!2jq;W-o*TuPh!&8z02sORrZXcAJE-Z zk%}3U9|OBem#lb*BQWvv+!gscx5|2@f|I!MdAlh@032yj98**{+>nxHuQ;5D+xiVM5^VjflB ziw#=B_AGX{v^X&}oX|J#90k7l0*v^j@b)q34|&?r9X4-VDrYw)Gb zYjQx9DsK@6GSZXlDp4KK9l$wGElAz&6okpB?&@9N#!SqhsfObaDO^OM#w6glNRT^h=O63QKfdGOtLI9ll#Uldh0r$AFd*T z!aK9H`WTWki1$`6V-I60mH&YyprJ5B^CUAc7=zCMJC8DS9b7*<7uiDC3a?8ix1;IX!WXq;K=e|=q9Ll!z3wSG3RY? z{gyqh$m^sCNkp(ups^gtV7WX5LOg*G@(>LKeuh6``HAh@4K(6PRq-F#Oq;DRfoNz{ z-y+H&993kHib~f#fGZ#lLksIa3?{ItzJk*UG@>UEhLMp6*KbtJD0~1HaB&Rw2*U## zY{+jA-r#pR0&mOm<6S{%c^YkHU}ZB30X&}~Y&&-Z(@1|ydm8o0dMH|Lp)J8TUne>S z#b?oXh>x zD^bU3w^*%QFGF`hZXTXGdhhq_#t)T733{@cJS}0~_4RsYlt^t3vRk$kKlNM!E*{Ia z;?4C_)FCWC2hQU62Kf49ybVDjf;Ur8P4-9xt|BK zS^hTv(-gc=FaN;~O#W1GK5)kMF4&0@ePH)K4Ez;b_d-kg=dSAlP=m%nUus@M?ctI0 z(!d*dB$C-^oU_W603L15TMuqT-!JFhU<-+yG%xM~u)(gp97N<#$iMKlg0FHfYrc=V zD0xVJfuuDTcKD1e9KZlo>(-%kZ*pozkn{6=i76EVw>}RcDu{)jk&LyI+NnuQ#_aJi z_OUZ??}jUJt%}=!2{+f`wdDGXP4rU?SX+71)-T>ZS&iW^7EHflK=AEVjS zxC&9J&!;u(qwxXH70sIBnixTL>VJ`X7#^0+WGvj>xIS97@hFy7`-q~X)hE2mDp3sX zp;jNG$nN8TxB4tgM}h8$6h@iH;_4t>DgT!TI)iB=M1za9wj>V@AJMWH>`?(|aj{x~ zDZNNUhjF5!Vyo{tflHDr+68k}4No?ZORey+Sim~}BnfNtI(vOYe^%cp_!K@x?`7Bl z2|A^)5PQ8of?Kg6$s)#rh}U7IIHieLx2c(Gj62UfXPRw2qx79q~#l} zrmew?CNH81p1lJH1@4CULg{(G)dZiw4T-QtFXqNH4cVK=lb7;U)J0_y9!6Lni-~_kHA2x#JW|K$ zH7c>@Zp30ld0(tj@%w;F@|2=3YT6U5h?@B3oEoW|Vs!`TPne}Qg6^ZN7|{9g&;Xs_ z_0!ga*AIU!%q{3GJ`E3ZAf z_`Tfm9KZh`^83dwi@{M{cxd3LlIP6u`>!sI0o_hKG(ac#ec5X8``iETN5JpL&1o6G z?}$T%bNs$V^8IHxojEi7ehRhxBjWcPd!JqWeq&0Q-%ma#-~ZR;`)84;qmg{?!9xQ_ zJyZPt+nzC?`vMOQ&YsiD{C;w2%lQ38ub<=hE!5{6fyv;R;rEYF%ReH1 z|9-Eti{Ixbh57yWVD~#n?Lg|Bcj&^X&dDcr4vfDwbq@56=kz&$?H+@pK81${j(Vo} zeQGS|j(3ZKPVoE1{{X+A_56>3-_Q72%lQ4(FdIB4-?vDqet%AX|KHc&|Ep6Be*YpKo)!GQXDsO2Mnfm~{nA&!@4dhI5%Bv*r?!mW-|&}n z{Jw?qeP`G>o*DW6w=e#<`2ETA&n|v{@*DDaI(J_CKRU17)IJ8kUxtTg1;6hd3%c&n z&}|e=)ywF`D2;gk z0lO*izqYv9`NH?(;KsppnEnkzDH>1B3dY%qEN;jIDQu4#Hg?eLZSeaPkr?c5tiEM5 z-Y^WI@rJ=ZsE?~t4R6T$C1QXB0}^3?W4>7#2f~C2PL9z8r_Nx4vr#j_dG&NAI0IA@ zoNLQg5iD^|gDuXX7TMy!-S11KfdYgB{dYgm73}=Va zOnRGwh~7qr-|wZrIS6|k*fXj2I0t9gT4|3{1ACmB64>78?QyPmZg0XI$3m`_P)bpz z(;sAxufB*H9XO6#jr?$Vx z3F}!Szdw!aB4-(YKe9i}-#TtJ3?YEa2kQm5*Qf)HN)<7m@USgI;?7e@=dX z4&9HK)B8wH3Y*iD@1SZ%1NtXi~f2t2(OCCw_!CBYd|{KF7Y>nVXeu?_llt0%IAL#jv z*!Mp|Eq{;IiAOLzbcn_PZ6Wng(-}BV>(2#!(rWT6gf0fGR*X6iG&v2c3MCr-QRc8B zN%<7s!;L+;0tPkGUQLbkB9R+3JY03Q0(U2xMFt-?cvo$LgDR#dQL^xKlO8PtR1t5t z+kX)zTJn%mo$5S9wg|s+`7;!LMJm4!)L`{q*AcgvME|@KbIH4kzCkD!gsY-Shma0V zgRc`jUxh!SR8D@Os;^US;C=CS+xSzojstM;l$+H)I4Fm~`n!{dW);=1<0q`Wx1Y88@Png5&xO*YJq(4zm z(Mqj6hzMR_eSdoz5o-FvQJM^=%BfY~bsb8NhSs3iJSc02&O#U>IcXj~!`Ef>wPQL4 z!^=dWj(1=<6{N%sgMLC^EXNnYYlD3#CPE>HMreuyBE2O=wg{fjZn}+@p5!Aj@O^SfVS=_!3Ayvd;T2hk2KNLGNHj@z8@+MbXGzxWHx_3KQ|zIN~J$;EkFoYw~L zH@|*WVcyJiXNvjtKDg-NdJooPaCSEpSDbGaj>ZAVNO88UL6mR}a6q4jB&B0BtX{+` z+-$wdm5$&9$N~ktN{?^Amu7E{)%OUT7YE3>S`DvK4RUp1UY=Bb8?Mok$(3S9c9+0# zaU0LK@qq$yo4~gTfj;6kk#7?N7m3>>zD){Hx)D^>hHu*h;>2xRzHJ*g1d#AHnQxN= zd&O-E-=+k%i`#a5+b*zP+_vZ2_5sRxiL$ADn;LjY+;-sG4(vyWw;lPmV}LyUaVxpn zphr@0Hm=k7IxRR2*PZyfQ}7;KpU2nd1;^vMGhcTO+Hu{5ue$^baov@#y9WE=x*K12 z3ufWEJ70GX_QZ8MU#AC=io$xn-8a4mp7n4@#c$cNt1CgiNXmAy`@DR2L$b4-yCKcl z(cRF_CCP_v`CDfv2QR_fZgVbz{4nwLqwqyso@lc9ZpNr1l~24m6qj3d`vfGu+X0_U z=P~lhoOi%n_VZAVOHl_DC9@ls4EnV&9-90!+A3mqAaWqG6v2x)3!ov2M-Kn^^6-P; zYrWyoO;c6M=GYlh_EUH9-SgAd#Ukya()H2B;xh-DI+P+5U=MvdQ0+Otav@gp5O&$ z#}1PD5U-~LrRA8Iw2vSEXXEw!17>1sydEh6@a%bw06s*GHwEy!0^rLvfbXEZ7ZZ~< zgaJM)p8mM~&&2C_6$UeUf~|AiulyFzu;y^MAQ7*}{}tMcir4cxJ^TLg zdiqshosmky>rC`~7xDcX$Lo0yY09jvkJm%|VLHWxL!b#oaZ<1z3X4LIv7H%3KQSWp zyaF*vxgYzPn2~xmI`WS>&78MbMC!?+^X5kJc@8xbp9fKAtPIBU#LEB;aW)RqL!1md zk_`L=wfHa)8PfUjDlWwFdFVSxg5&uo5|{@Is~X8Cm1~(+l@>wdbJubTVu7sW>muo_5Yk0OGRkOidl0l|w^mw> z!qXmdG)Liy#|5Nz>R}l83yZxO2+l&?BOH%M{lrWgV-c38haoIavAi!d zDo?yd6a>N<#!o7LnWZ&jRGuKVe?$|(9*fL176=?#Jf01@csz6Bnuy1f=uKS8;dqcQ zRu_&(u0fWO2o_Zs%=znG&z&Y3&q4w~jmASL2#`KP*MAX@hcV{r46unM4jkOM((h1hBdj`eUcP692JKqoEn+u z7;2&+cV29a_d)S_3K2m<#OFC?jL-AhbmMYg=bF<*Y@V+vY{c6L#-&cv@U)S*RSvvE z&`6$#@Hargs+tPCGoVqU902XJ1z@PFAB<+G&BbG=fTY{1_&fJuzR*6I;_uM47JrAX z@tEW9(6t(WXE82eDR37$1QClYGF023U)!{^g)(~R_bkE>Re-H7J<&q&Or1jn_TqRv zLP&sSIt_~u;B~!aF2m+<60eE_V zv@ZI-@pn-6(r`Q~ef*s_f!nAZWhDO2AMp}#U8pN+{GAG1#;^y{*>h6=jQScXF5>SL z%|>aXzJ^``>4YVYze8ApeuOOM6*7v zS)XXuBbuf7JKRe2@QL_4)Wh(obOvVAqt>JFcD`6dw~_tcW%r?wh`u8TfX5siC!!RL+?2N z4+E(N;33eJTIl*<&^ewfpa4AdDfC0sq%HstH5)4c4;%cD;^8fxJ%#{0{psugiPwGW zx$?EAkG~UXP>a8_6vZO(cPN6LA^r}7^xurX1Nl>(qFq4@=WB{4*QKOZ8XO#=4OpXC zIL=QrH59KK$YFs+jmUu|5z^a->+Ilp+Y<)6et_;&?qP0DKt{V zKXn=@U0|K4YTdD_eW+2j%*(saA^rco#LLfG{=L1ZW&HbP#3VY$zeW5sn)yxfZ#Uxd zof-a}LM{K8`1c9uWX>l3okuZ)&++eA_V{Ojf1i)od5!pY5+43A{=M$Q7}fp_4~^9_ z|GuRZ{QKIw&uaeN`G%J9?;uV!&hhW&`S-eMXNrH@sO29M|IWMW?Bd@`)`t1F2#|A5 z{)Xa{4erkX|Go{$NgDBQ3mzI7ZENN4gjm&5{t#oe%)fv0Gw|=}cbwJydo-fR3R@T2 zXf&-qxeB_ZbNst`{+)ohsAoq0mhbAx>2>vzjsar|Nh6gvzmYZ`r4N9@2Qi| z@$awH`17aJpA=0xQ~Z15JwG!3U3u}@#lLs04D)Xhz@~K!{G9$9YVBz2#vh>nMh1^Y z{Cfi){xJUSj#ceLjj9#;@5!Y99(7jp@9l{4+7kKuWt>8tlfRpnzukA9DgK>8E&rJG zCntKGUHtn#I3}Faf5*%pat8D#=WmF?zmxFrhw<-qNcPcaS@;_s8mkrh@4HC$B=dG= z!&a(5UN#Cp^=uaaGm;m7hC2>1LuJ9M@1q|dr+ZROPW+xb@QkXh@!XCpgqXPvKNcjo zZqA;h_3>q5+LN?2z6|wQ*ps|U(sB%Y5?%ZO>Zs(=$Cshv$Sn!0jw83CbaZ?fdW~Tq zgt0{ltDa;ZwWL~<@E1CZ61s0}QNp0buqdIg(RL}dt>eg|S)bOdPc-Wh&5}h4w-P;) zBEAguF>FN83ApV>79}y_%Xoc6UB%v~mf#0zPkqa1q(OT$(jvGF*X3i2EwU>inxNmi z=$GAs7V*{1N__@%=+nlRf#@SrJiR&!rC?z~g;fiaXK*PjOmy*O2pkb#h8kp36McLc zf<`qpq4#WRLI88_>MxbfeVc?p#H~HT2W&X?Tn*CR&p;N-LqzqTe)HTFc2@~QW zVL%y&hep1ts!NDn#x^&Js(p*78@uTzdrJpFu&&bFRkO&pMrEa>&EHgzl5dh|3~EOi^AsI zy~vzr1+I9J%$1#K69!(Z!%oS;R;6bL18->`l6sK7&;}$9Jisx@A_PU}IY* z?kefWHz z8-EEo!FI?e+?;-=_4&GE>USu<3&%Dv`YA;Gg?liVGM}ARr_G7lJy7;sT0#FOABg5EkkGx9Z%r(?ML`{Qkcm zA5GtT?%AtORh_Cjbu0>^G&sV!P!Z@239uZ_#X1^904Ehro$*^kzuKR147H_$`EJ(% zp@gZvSwJ`j%?h`{ab0LoW?YvlJd-*_#C3U=(AT)Zyuvu>27T9qV=XKt++0k!iC`|1 zFA~9A1_Ja5=HkOE*56mheFqTY{%#$CTs~frOtuK*a+0O*3SxF9&}{d0&30dl@Qx+I zJ1ucttJ5#V=q#d6rxLBHZDDI%<|52L;jGOq&k^mUNq3yJxeSReVOokE0SXJkO!U#A z07=QmF**pU%W|4`b;zBA?3gSs4&j(AiE^6Nkvs9DEjYq8s?Isv3P$p8cQ8=ri;e1 z5b54w;T$X~4!`1qB_AoXvZN@5U-2!)Lc(i~6s7PhzNKyWwUZR3@GHKh4=o)^d z)2H59{iP^{U-2#N$ggKeQ3}7}TiS_Vi=`-ErzYdn76n@3Gvu*(b_s_6IkA2kMd4?k5LgscBI#(TJ!p6?zD(-w4p)mRBM><)Gr9 z7f?0?l=o!ikd3?w#Zj4EqaD7UmQ=Wg`c;ONhS(xObwK@a56=1Dyhv{F*J7-oZrQKW zR}w=g%*aCIYs7COe(SJ0pP-Lw-mQNi(IbrbRr6Wyc!ZPF%N;quAzSV^$c>QP@#;-1 zcf5xmDD@Fm&gk7UX7AkHdhBT3nkl-q`B9@=lIT{&QMwgFM}qNdRy9-bg}beD>G{5@ zcGgRQ950(!<)L?3`4sFrS>9ic&#q}fW5j9rTzl4s`DW4)h_48GZ z$_U-+t8WKDwUH6RNme@6XPk*BLYc6GTos6q&PiNZa_;P0DfTd?%}BqO(y>><`lRv$ z194#0D!FJQ;!hai_N7O>pfvF=WDW@^xk^q0(UJ`P6r}oI12QM|d^{p_Kb4`Qv+eO} zRb<>#Wa-4vP?iHxRb=Zoh*u6oRnb;ALR@hms)}}Ih${|6Rgq(cxZ*%m746Ls zR~(3{qJtUYiUUzqbTmU;aUiOSPG*QJ4n$Sa*$i>Tfv76Fm?5qtic3`?nIW!n`8C%J zan+SyyP6@cy76l_GsIPQe(i3Cxaz^LJkk3(E>XsU{y9O8;YQ&sfh5LXI8m1fkRyN=I7oV;_5_xK9NIQ_2K6}6ymC)065VX z^W7I=NOlB@)(Uh8M1JTiJ(7jF2c7y$1xK=)m<|e#oHLZ1aYE%dj?*s+A^|_rNu%~whFO8Krl)R za}bw@F*0--FcRyF7sKgg1=h_IAST7}_G}r9hx^M)PqGY}%S~ER_I?%E_jb%c-W<>q ze{nLSRM`pwlH(vCW^|s^c%+e?SOaf!B+@jrKjUhm{WsTOPCp)J(*AzyhY;<*)=B$U z(%05#|NqcOHE+g429bUG&rJLO$jL+|8{;O+Q0HTrv2~WC#W1?+7GI# zWY@OE#WPd+ zBR_}A4|4#?P0=T48>h6S^2?F-bEtgmJW%=yk0 z8T#594m?aB!T%{nE%X1mj01Bx`6u%KYXtwt5A*-22LFH6?46tc|NUs)dQfz0vto2h z65X10ly0@k|CJQ}ul#TFe>lUqu?74eX+H-uZX7}U|2IFC|6|V~`2Q`f@&BpJ|ECQ9 zIqbg!*tvso8|?o(uy2F?>w=S;?Egc&2244^V*hK9>ZnD3SroF^KXyLt2EC)-54N!k z|3h}iz9&R)$cQ&=d#)(wnu{d6V9Zt&S93L2t%xM}$yXW^8z*=>O0+W6vW+ zAEP&8+apCEpf_{pbI&q!<1>Akx$mjqXfm|zxpJAg>zTOB-1MBk%-HjUN|xc4J72m^V4milb4;yPoYr$vOfGYE7WCKUw*nriqYmWsGd>n0@*ZBMnC`oVqXHN?-56T z1yvXv{ZerBszRHij}z!$mM<;wfTx24`+gxyFRdyN{Cr~T{5+^GtVH+pH=v5Jc{@F& z()XkB_k!PA{Qc`uCT;Jx1JFp}?;GfAYqb4E`l#mpF=`Oe^^Y)Z{~IU&H2(hSl}y|B z;D`A;Xgl-wPtD%B`FrEhy7i3c*5QcJt+Pe99=E!6Z2VpM-{bGQ;Ubet#Xm;c&!OTA z&H)v#Jjv$o7lXGC^CNzpJH-6feWP6l~M=r{NqQ5i(H>=Ws$ zi7~bKxEb1j&G>~@VPpn{G&rjzPSwJtWyjdJXr(Da}hUWyC> zsq_e9)Z#L;z9kq-S)HsLls)SM-uFY}=@PR6s29_BL9smif?lzDcM6jOl;fi6mRY zrk9&0z~Qz9M1vvaueOm2%zn$U2W~W)HZnYf6HK?O`xyI{0;gMR6Bor&EDh` zofwLnyrj^V`*v0#3obM8LARy6DieHeUtgrlRQJL~x<-vl`dG~Ewgxrw> zxnV-7MUevoLfMf6r_(0&+7}XiBh8uj^r}2i9PTD9@xKshEQmDE;%_e|+LS3f5#J8_ zZP2%GDgN+$czp$xGYWZusb!Tga?GNystQvezI+KZ(KZjE4lk!-E#PfnJc5of{tAX)@O|un(}@L~+KHl2P#>a&xFg|WOhw|4Zr)f@lnu5 z5WjF+B9%CqAV}gV1`+JZL@?uL(Z8^ue?wgO_99-><69242mdB~o6l}%KSuwGe>uJt zVob-1Z#9E~E&U`Hz9oCu_%`e~LI04A=pW@CmFvQ{D=BRW(ta-eJA>$7FB{*sJ@bDb zzFl^<3*ScLH9fw~gPiei!nXls$3WjI&iv*0_ABt)jv3WcLSO z6%phbS>Z74kS6ag7TEneXonz8UV~Q%aWyPWl8R%Gl*^N{$fMOlg%fE$an7~+A6hgx zF16lMjC#)kD?q)S@al)1Ah)&3FBg^Hd#=&%bI`X>2a3M=xsD-?c$L-VlQDs~`l8X% zv-8%%OUgTFT>{&_?5B)U7m8AUz^gAFq?XeaZG)oN;7HL%7N=FNUEzy7-~q#L)0)fF z5$91ILVyk`%L~v45~4@hLi8X&vWqQ5m#O!95|EiQ@5v`2x;ws(^_WsLK4y{>y`Nx# zJE##F*OSyX_n>P%){+%bTqr^szWz26LadZxi!dtf%1Y=q)MrU3<_P`8JSFo>=!Y$} zS||9O$x81+2;${Pg&+<;D+uE7*Es?qoB9vW9c_Ui5nM2J3ucStR0BkEs)4RQr_}+G zoDdmj^sv{^9)_w<2*}(Mm=?0N<7u_Wmk*=NoX{Q#DTDc(=A3UPq4npM-ai`vT5x@i zpeD=UqIT z!XJ#{>R}$#O^)IVMDb6~;6Z(gAMKx1{Ay&iV)~+X(9vqp6SZOlO2|Ox%?y z6|hJL)lg65Bp_vkPq)epO^g-WZSz}bd!n9$8PUeB+$8Nq$Ppw z!vxwoulbYcbF>Ay^e1K*bnc2Dq0d`R6EyH9L7&&)b<48^i!CDx{e!-iowOQz{vJ@) z6OF!E-`1kh7BqT}QTK2`qbu;rH2P=_yad|-8jv2o5A_>kI2%;=Y@@ERg6j5m_R~Rm z(Zxqsf>;xI&oGKyB#P)o2BEf^cbB^i<(N_ZH_Hk3sR)DYc-ox^}2P@zLe!)--lneD50QdO7vQ zrqr}vP>3+vpw!!8=n>RGbem?7h6jRuLoTkPF>jE%0x$OJV$Nd|Yg&wMVm+ik=+UxF zK^9*SWbv^ao2tImiOFJHWCQhTN4ei?1M2kvvZge{#CrCfOsqfo4KhwMs{MzkcBG@) zJ4Ch5BO9t+M7d{EwRa0@`&UXRG>ZSHD1M}!-K(LZ_-&&2?UegGDt@adK9v%_@Q6WG z3Szy|QM|b$4{DGoeir3UqA`6^3bD?oFSk*}HnFBTKQ>}ba1z8?lyMSk{$>+v@k+#+ zp0s&gm{@Z$Cf4+%-H+7Pi1n#`L99I;4Efo2sqYf=JitPL9Qsj34WbTqv|zNcVFv zLj|&+rx-!@KPeli4xdUOii2FUxCZf~#BSrakrB$M=1u%PA?{*I)T+W{fm*;zc3SrD zIYW9Uffs3B;y003#@ABx?|3Uy4g-wb*H+}RK->=*FuW+J&aT9q29h;( zoUC^0FGp5Yf-dk>C{4klU9$H>S)G_&DNCgrNth#eqNQT|V3J6fTLstwu1*!}OEekx ztsx|Eta}^yOdrTMPTM}5W_M)2LZJN9M~?7ClzYX>i)Ps?Z+Q+coqea!q>bEnq3=-N_5BZ52%apZ-&X^P^nV(vW$2cMY{rVIiCcJ zqE$g@ye=z~YRGl6XdhU^y?MeW1Z6%B$sj(06sx65fV2;juP~gqdd=uEMlBtXQRS}% zaxP7r0Tb*(mH4jPoYO!{q+$L5E%6Qje*FTOnk4!{eKJLhFd2s3BSx+lpWe@ z7}}WntTQwC`ZqARaAP71i+icrgB|Drs^QPVHuTiJKj1E?Z{S-7Ki@#net00qW9cpQm zCI2QEFQsS%paJH*Mg~kJi3>oFBu>M9b}&Ci8nTr2O*=%nfYOX__0p1esANFxQB8Ku z0NFL)^TlnmW-pjEajn?J#fpa_u2}NB9PbFcpu5ma^QLLrq#h;yz!uF*vFUTd`$sLB zU!Eh#SGs9w#iF?vvWmM6#;M190jFkWS~z9ckNV2TsL#p=beLbi2V<7-eYRV1Y?go- zKi8bu8=8FUzA1A*)b*#^GY_07WCrpsg3Rz4UeoJWhaJT1PJ=&w?;;^ETqp#Ffb!AN z1%_iaXl}+_30A7TIg}nvg}%CrzNj&cfB3Rz*ffc5zkCXHdO4LmicOQsK`h@&Kk8zx z47jcA!sSr}AMF;L$pCnqEZ4AV5*!^Y7tC^fZ!pI3`vq%#lWQDO^uyldN^o$pYF_PO z*7{$_hTM-+?i-rHTItdx!CI>*Z7b4Dt^Uz^Z(|LSNXE^KJmBUQ+^pu<(Hr>bdF=l^ z{JiW07k-Y$YkK^gw;wb7Z^F+rh8!Dy_BiR+z|XhgT6e7YdD`*7uIImV;iq!Y#?RG9 zI)G7SA3Bcl^Dut2b>F-2Q=_z!eLovNr*;E=4*ww?ettUoSH{mDGk5l4b7#pfv3Guu z@4~;;cukLg`QQKh@b8~z9UJ~V1{=aJr;iuH?ekdi@9AE^o`HK@_}9MK#=p^r8UOA^ zHqgg=D0g753;!x8tqy5FlRj>hfPb$ZOoxBl9{#@%|1Rt4!oSgYO^<)`_Wb+s?+k2M zkA*+?fa~rr$G^AXpnR=lO44_@{htu z7_MVTEncA_rv^-Ws8RS#Xlg8b=wFOdK~d^{yqfmVG)4D5X=vH&SsYh6i@2;+j?d?} zY0W`(#Bi5A^fvT?Wbl!;J#?V7q@!&P4XSs0+&+b4ENdvf!5SJ+J|!Ky?0r3Sw!G@A zHrl%V9c(2#9a~SQWPcum(#B6?CHo@eVRI;DM&Q(H`XP(wm)Z|Fe;-r^lR318KdSTa z!+9D0tR7F6&k(md4wX`X9gtA*jl0LZNo{Zkwvy^gUCR1;_@j_7BQEV<)J} zqsW@l3@g}sUrqb|k+Ugdrcv!vqS}vk+12KWYA+Pkj;GwcsahyPNX>U1CA_{v^r}V_ zpYJHX={xR~B#P%!?vK%!9u~!u5)z_D@kfM${YppiKa1i`$cDx?Qtl_H_%$gC_E+eO zME$ZA>@?FZ1$#Q6vNe=|BoyqTj8nnR-)sfDcqIipJ!wOMp|FN>F;=kClXenPTT`&F zZ3og^v!?@}Ukj?)x34)y`)3s}LQzAgADel$e^L)@$U3(4ztllxDk^SCkpJ!W&xPm) z=<$}$g693+uz%up%d<3gwtsGS(PpxL?hrKjCjC<=lH9gc+x}_PJ;$iqD`;{BUj6a0 zxks!2Wu5Dn9{aippNF~UIJ_PcpjK7L zn$ipt=Q&p}ao*Yi8Lu^}HC$CjIjWr{s(k_3Q0=S5NA=wNu2qcO`OFm5odbR{&P1IXD-IXnVz&LQd=X={WC$F+kDM(v#Gx~ z?VpA|73V`he_>m!LuEGTgz>Yuy&zTDyrA=r!z+xRE1S|8KX3X1mbV6Zv|-BVbliMQ8qViRw>=vzaq89$(J zSaI3^McGUPs79ZaSPt0?Rq><5V51{hU^-<~^DZtU++9qG+JlqH0J?ZHm711)8D}WR z0=*ztj?Zu$NtYg2hQ@3I=s)r1CqFgrdTWvx89-%q3Jjozg9DvJ3C5qLi3=(_#K}83 z&N1d-3Kf<)4-PDCm5Vl)d3Va{VB7)d-XG{6&CT>5c(md zo%OlB8)W#kVib1uL}+U-N*+#X19rG}gDuZj%63W9K8TolfWq4_4$4Z|JYgK9GpvZT zQ&Se7MMlCvQA3$D{#$Gf14Z9aY`3!mt9E9ZHn-UeA=3wyL_qmhQ2C4uaLSH=@^Mf( z1oPFxpchB=MxzZjAGX7TT#G#q{TmhVu9Y4PAPE-5Y?vSy%{bn)DuNTe7KkKsW{jrD z^UA@*y~4WK2F|onz`I6zun6VOS4S*>6K+Nzxkj6?@d%KXtc`Da*xCq7Bh@f{1^Gfo zzHA0^EGktFMm}qIolm-@{yOQlx{N_d3eRubi}p%$vTE_Cv^H0cG~~$MBjKF^@BUEt zLHne>r5T7-G57^JSucC{guffzkVTgARMX{a=Df5tU4C;Fn=WyhZ&COx1Ok{BDB48! z*8IS#Z;a{0u|>=53eV%XA7OY(S}|l^|6`$d#>zNOs5Sm@#6iPIy?>@w_(>-1T^vTw zi_kY4IV>Z7kEm-a9f8AOvS>KM@bp zviG#1WU^?&2RIN96}kw|6)aYku4+al)evK(==n&2F}kuWeh&K6+w70KBiTkr5T%U< zlQvk?Hf}g?wAr6KFXsNdWA*1kbmtC7Z?Gz=qzBf6d)TD#HM|KzhZUoIgV-E6jkj>2 z2ZGCOXjqE&VrJuC#C`86UgiarV)z?p6-Jr|gmQw)=aJ^q!w3X7yIPJ*(u!Tl3Bv;F z6@?y{I_Jq0S%6M{_N>C{Xa;G-1ZUoJQRVRBaGA8k+NJwM@pdc7l_6O^EVZn(Vg~A? z7TVF*$m_t{l-j+ALW2Y9xTNgee8=gsdV$BWzN94+Ang~IRNbB=QzGDsK6&8?y>a?> z_H0$%EHOl+ES%i zTG7c9TNfJV^S&7#?d}>v3mWA!E11d?mvjezb-v0EA68B@xNwi%$iK+VE324O`|9B-pAe9P+Xn4Nmm zTS>?OUPLSAj=K;ZbC3*ctKA=Ii4XJDvuZ-Js;!*F@n9dOYd1*Z^e;dgP-zalfH@$K z6x%^;M}US;Vjc`CyD8|5av+G_cy@CE1<`nBSK_#qyX~M-7cANu@YI)in-QvLcTgEh zQyU_ei(2iRDXFyKA{@7#)f#II57yT7ayT+OYT9{4YE3!N&S-O+L1k|HTAHq4GJ?E^Cc_Gnb5?ixG799J{&9h!(?ZJ!VGEnnwEOlNnu{2udPv-ztTrF z@3vBd!aO;iS9CQer}vpSjdmPyL0_tPjplR83Ft|k*%Nmco;q3=9ui&ndW_M9LeYiU zMi}-JR08LuCD?7kKV?dFs8bLU zHL?*AITc{9vWN(_TJ#~P-iaVFWtf@?@Y$G@fsk>^CuK!P0+AyS7H$SLS}+yaq=zuw z8HgWM3{@9BNlV5VIzTD*4iZG&7KL$FiMSOriNK(BA}|4UPNqA9?EO@VJPzVr=Gl+q z&hV<5T?y|lsc$8!2Cn>o)5IeRvF}!X=nO3?NOpY49e6BNlG-QRJ7f^;zm+PjSfxHFIiJZJ#rJO}}jW-c*5 zKz+Ig&5u_Lhk{Jm>lZ@MIP?cf((D6=xjzNy&zE?l{+#(4^#{^ZXq+G;;SGr~sQzty z*De+vX)-%+N=K1$j`m9MyI(ee&?mfr*M)<6wk!N@pfjlGFm_?8O1?M0PqH;7yGT4%d zA?`}5JjvG)z@Q9rTNGkerF^<^&|LU$dYWiz7@@q4jP+h7_p9z0gatvIR#pdRLclZo zkJCJ$zg?>?Nmh9%r#cq&7qW8w^e+P5kERdSt1)(y0RICU3a(ppj&>O&4}$`44Hh*A zJpK%nnQ>LH=yPD6m~Si&0Aa+Lp)*`7&W-ZOEhpayze^p46HKD76B7BH>Ry)gX7+*H zSI`HDibUYs(8@Qc=Wh9QUe}};r;&Ts%id4mFWO|#2U^UslIx(}XI`2@y``8+<8N^) z9}5y*T{PGFEN~^DCion99o{SO?v^vlv_Ijnbb{njVDvi&fYGOI0!B-T4vCyZTkAZG zqazD0N$H5#16{ZWY^3O8Q&@%HN;-M9M#!toJCsS-@r0{nWjRklOIC6U2>2XyNeHV$ z?)j<(E4hlkw#G_I>7$z0?>vK!UxD2Ygw-LO+?udD4&=#XCPG*p!YRZ|B4%IQ%;YAc z6BJGuU`s2g%AzlS8EN#Ti6qu(*3GU=7E-}euuGAmWP}OCnWsR{V9BUZPtsgU z(N~>hhC)iUXB#&&5tbD*b`(2q-6jtbLzxIhI5=`N~|O+hqp0wF8tCDL%s)j zUG-(=`D)ez%uR+|R4;oFu%|w&IzIMrysL7_Vbnx9)v;LydHpiz-5-YZ2?Rn=@pi$Y zuh8nNM4239;E9V;$-s}vrDxzEayo)Cu|-WRm;UfI2+HQoHbHUI6A@1aTi_ZfOCW{3 ziT$rFoz9*I(wt5-9r(RPPtN$f1wH9XUt6Om-+jmQK64R`YM8vcTl(~G91Ekx6^ zEYWm`*%LQ4>2tI$c<7^=cahlzg~Vj+zl|=mBqJdG)zSmYUE=BUF7cE&4U4CKOk@GE z39NO$A(>W&a>|r%h-{q12xe?;K{moIs76^4WWpq*QKo{@Lprd{S9u;JQ8E*uQuA!C z6nmQxQ83A)5Rp3=!&&4(gSVt1A~#n{k-j8SdBE*i^8sRm0~R}3o`Ntsn1s>8dsz4@ zgz%^1u~gZwP54jP*on=U;yYA>8P%re@@>uKo z14u(ZV$x-pc<_-3qM)>N zb;mwat%KK_bbTDdnj>?w7smLnTlpfHF7TF*LxGxyQ4Z zr3~mJjeJ4R9yzi)D?a^je3)|AVWk*)SJ3C_pwFviWzTf*h1u0*-orC)0)$D`%R+56 zmY9%dAy3;o$QFFbkZ3ouU`RX1y$LK08+`dZ0brgC0h^y0a|pInM#43p_8`v><~ggj zV)TuXdiUX7$o8EchJ4#7E19y=(ZNS938wOqTUyGrsY2_vwzklE;d}6*;x@3idBfLIE@#e!(X#2?VgYhpS+fECoW+Q z?&LX?!x&TpQE~G(Sg6pk;&JUqAS((sfVPfx8GUVy&CI8dYThk~o69=Z1th;t%YK-X z)0=kAW{NH}AoExQauTOZ$pz3_jV14E@Dtu4qTdwUyf77FE;I?%_Wqd;s-6&tkIfGZ zA6pO_1c?X7eZoBu07C5deJ^{knkmTf+18~X!~N0i;Y;<7sI1zQ(P*ST>9I9*jwu5Q zu3c2kTfUX_itM5O`bQ9MuS0$;D)1u8kH~vVjqC?}#cQM}T`wW6I2+>uXGbVjWE;^B z(eKnT9(lMQ{h!AfXr)sIkYLW^Q`U^|huULltcf%ihp$KeOp*T@SANdySH9p|EMSYN zLczpnH+_M#Rdn4fvJ0SvlH7e+jh^sz=KKidB2+qh6#cFRB_*I&p*xk-9cjhC@c&0l zG!B|No%qewWr`LQf!KT(`7Xwwpxeu(qg!#5^}H@8U*{0>q{*$8ha+@o^gmED$GVfM z=n*-fwcMB0mxVGK2QHEm@-ZaLprz@}_YGSUKGEzya#x265HK&G zjLoNJ&%_WYk+1~Fl%b!91hevT%Fzi4Aei~UlkiE22{`OWPrVZ34E(S%6C#~uHWZ=| zrr*AFZ1;MyQDcxzduleOXXZTm6-ygK2q-iNQ#u7~Hax`tR@u3Kw9A)nC9Y zpIqyX^F?L@M$y;EN)OGRJ%=_qMXz!HL|IdrQZMc&2`Jx_O*PU00yriY;%zBH z0QvT<_JleFRdmzhN6FlG`ra5C*hT1LumAjGi_KofOkTG@(~n=Ty4g}(%1D1Vg%MOq`PRpnUl z4OxXKiAHB*y8s37YEZB;Ww$mb7sJB#bR?AJ8FNO!h}}kB`pnbfpDaD!C@a@JYnGKL&WV#iB9b`T3U?Je%HY0nfGcwKaGyq>pOeofICI z46BRIVR-(9lhea<4Q9-S=Mn-6@xEh$XL*hQXbDzpYXE%?A;K7-qmXINuyg=5zP-|`&|ZQE#$X4OfqIU``~s5C=uuI<4quAJRYEk554_uxGu*!! zJYnV`6B@0`k?tbQ6MP>58oe8w&}d07Cxc{HF~MZrO+fjgM(wEU!bFI|^FaRX}XMud=2>Phzb?(mqTBwzhq&+Qr04Jvx zuvfCy<_fa!ZIPlc;0+9AHc8j5E;wjG8zOaEBFz(}2M+^EvfBBNhxfusE9*Yl)0o@} zISll5E$Az(?vC{cRLx<8jEAd1UJ;NN!cUq**Odc zn`mtmlRG#@L99Z0uKikI4TqG5@{YTJ@O7(F($DAkD_drzTMS0m|wW2bzz0Z27!eSP;V2WN)<#E zeFll*wf$}$*zcNw{qEFD=#_|CDqIyrmO_7$jgjV#(t||)jUElLdX%ektSC!N)Ax!6 z*s`(_qOwSHFX@r*(V|h+4r-h+Bu8(DYU};4m0{~kVxKYN%k^hkt5d_$G7%3we8R5w zkB({=(Q^xE_a(*f17cBY^tTQo zYORG?=Dd^4x(?oSB%mU5jn2WsQ)Znpr#m&xn6n?_K01kJgf8!)zeO_yTrjq40;$cW zA<*iJ(o7-HFhe7!JWS!pn=!IEQyC}_pco*%6L&h-YdI}gY>D7&QX(#x8j*@Mr~}q; zQDdaJ?VMauAB+P;0`e0@k#$)&&q3*ItAf$4O1fBq`56?Clj|Xx<3B%nY2Rem2)1)<&fM&t% z|IeWN`Qb++2RhDqD6*=PAP_kThvJ3=z~R~xI6nQ;#f*x7fw7ILW5(u^7t7gA2H|e# z3cN%|z7HT-CoALf1MyM5#U475beU{9 z{IRv9fUx$Lw0pe3+C6slN52k_(}&_8UJPh&qnbEn+fQCNy0?jpz{GM4Lz z#)XZ@C~V_t@bCpO2H$}-N&CXbCoUIN5~D6PhP;MGImQ}gFWT?7sqB~uxI1qtv-Z1U ztWXh!K1^(J40AaZY)CXZc5JP~OOBssfXLNL2GQ|}tL$E$ZvuvT8L)aO@dc(dlVf$- z$ymKJcH?!l8|OR>5B&woV}s-sv$z!dGeKm~KF5@XvH=flR(bLR@lJ)T&-n@ps|hmS zstPsOHO~C)v9FbZcL`{!2oCfO^FPBm|4G7x;}h50BP%mT)<7d0Z;k8(R*3ndxSgVX z#~*`117{9xN^CL)=X=FN4ZUDh@@nE$8z3%tV9n>3Dt_E7TGj|>W@uaC#2_CPd#<*7 ze}NNw&bNBsg^=LO4Y!(s8z5a8xeXejjkZn zjdJ`V=#h5q%i2>C&hxb|%RpSI$Qq{}0fHlPk)J5T5m#qA7N7+{0rYYX+q7a!;>6VT zDB$c%zFDeV`yOh*N;A-SuoKvf#=l8G-uY?t1!}rcPWod_A12SG&rRf;@LtUDepUF_ zV8SA=H=$qtVPBNSuYE6cyDxG$^PU^6zI7qYmMnTC`bSfP1GrUm#6ZUNF4B^weOVhz zr06S1P<#KEW7?z@b!zX)j;WKxQ42wSaI7XNXb-mMb)nO(X0u5F+1s9t4kq#>+S#xV zS(?$%sRsIPm!bnvr+y~>SV^(olyn0AIHw2X7bJ-@NzsGwy3r5dkB$2Ll#2gkZy-~G zxMtTdI8?d!M7&citEAm31;~ z#!cloSpzCSS8tZpF4)r zoxHbP913 z_)?Te+Qkn8SS=i)SMQo|53^k81han$gejx-KrAD1Jd6kl*f&IN5dR3=QGCHYXpQ)E7Z4D7KqW{LNDT>_VK$ zmx}yb@z`EGHi4k+!X~YW_GAlMwIdY6j_{z}h>QM$%O1^sAT7zEjSZ$>7S@Ay1Wme| zOYKqBiv6Is=!lc=yEuTWeGK&2><53sS$;#`Jgvzh`%@vyr;vR=eQk~G_ot6)Ui&<4Rc@D@wcX+L<74y;eX41Fchb11vHL{A8Z!RkKJ5M~}ytwE;E zZbM&9FxB8A3=jC9PBE$@zg*8?YLFOA)!GrL{{W`s#2IK0%@$47 zImBStr`+a*$C1@g7C%a*gaZs&6rRB=#3{=#($b<}*6$qAOJ2u_gi+yYsyEGuj?t)K zj4EG0p6XG9NSa2#=k`V-2*pRlu7! z^_wsk4l{%PAYoa{8AHVxS|#*#LS;M;Z5YM|#&*TmLyyv)t7S=^>#Rv~wdYr>3G1#uS$XRiYPSL$k@qdbn zYp~?Yc*!%QUe;HqhYSj3XkQ9D0-MHQp=d&1jLxs6Zkbb@qkqc1OoKXwggO)fzP0Iz zh$h%nfsoN={Rks%)$h?O@rEH>`lU7PBgA8kfpBEC5cV(wZyj)Be;eC&QKg@izB`PI z-{G&oMe_LiG4q93I;y)wKhdT^`Weez33o>^>ZJH)Icypx z`Er^yzJr6AFl%rZ49i9ySvH_m;rTR;8xMmW<%g@txDjFFhC!%u^xMG*?TwN!alE?4 zM%`Ki`sbqF?{ z=T=)9xbO$I-Yxv0WtIs2CNaaQ53+W%sM%rP2wmvV0ERkXQ{P4CA4UDNna?UTv?^aE z%So%^Hd(NLpU@c&;+?%|vapA9vKY>(rlyeg-un4U~xd@mN>=gZaM>o6eT2g zPI^|nm`=4*?W7LLDumM*>&OfPg%qQsn$8j(c>CPaN@1JGQl^~k68)_yKMms<*m69E z!C|vya5y0W4Wq4QV!f;|Q=~CyxToJe|Au|y&4BWj=?o4(UISC0(rY43je-0|*KzmY zxn#v-lU9+{^}*=+NYQl|3*euV3~!RjBS6^a-XFB37CekRqovqG^xy&r6&WPV7q~p4 zbT8-i4SO?$m3*$%gRFSI1rXR4pj9kEP2k>i9+g(WK!YkPpD>)r>9ed!j(g1-aK5-M z)XxG^KXi(Cfvu=4{zT}2dW%iq>oeUJOur<)0tRk_r2FVdG zO%}r$dR9Y6cRD6(u%-Vb1fzy%&Nj#mM9bNx*+g>$g}ni2Ba2HX3`+z$;2-u?X?*sZ zQgjXt2B($oxzikRD7Q3T;L*e&>5 z&+#{401I`l;)68!O6kG)xLjEk=X+H?!?WTV)T|9c{7#%xfT2;TCk1F1;wQL&f=`c! zymZCH?$Oec=tw>~62G8W9)7{FkP$`Y;^Hb#;=Su|!hV+s_XA};Mi*L{Sm|VETf<$& zy@xcG%Z=+?s?e}GVCQ%jViHT0Mlob)z{}iYmeomHWo536=_04%pt`u69#u|(Q@>BC z(@5owFb-67w1gr&J61Mdo&*ReHo#;L|xk9P*=_2 zEd8rJoD_O>-_CjHkgU8bOsRHN&^FZb&7=Tf>@oleu=*{-@N)bG-B}mvf+X=JMqkQs zFhk||5*YDhBrp&`P|;`FbEq2bDa6L|5WecpTtoq-T)6c$5ILL- zUqZ%$92^+Y{!TfO6zY$7FaMC0HuhLa4w{1FL^Kr+FB5kLIK7O#Xa1g~7C!+ZHSR2F z(5`xfLo@+(X}H?-W{y&pCDs5{%97IMFF{f|2dxW?B79mj$8df}61~faigRh5)U}=5 zFfNy-$o_18zpkNO=79Qfna)pKA(gMqY?G1Y@TaG#Gn+8#uWy%$%CiQzD>vGA#&f}u zb3lk=>cUw?gxRxaf;}!5v(;4)KEe{>c~G+Mm4YE z2#TqTDN%d8J!@EE{3X4HWhAx@wvKur?Ri!In)=w2)C0PAF$a7+C#cR{M1xT0iviB3 z&#>dYkI{(<;E>F8SVsi9#CFMdv2W7F+B&K+vZk2mKdnQ#ws_E4XAd57&QSE62G9_@ z6n}>f^P=Iow04L+U;vERD&JEk_Rtg-B0itH5r3AufkOyI-^!8XH0dFB=fkmit%w&v z10U&{2N9uiIgf-cJ{~}B9`Q-J0q@7+*gKZb`DoDQzZg+CqhuIQUbx$!B>M_E>}e}8 z0Q&AjDJgm{URIJ6f|Sun3Ej4m_F#A$LvL5FB>s=LQhJ+64zcv+r?;^yNnpX-Sb7__ z5*i448%J-att7WBywTbX^~R8o%aO=)vSSm`|1eRWkp*-{$I|fX)CEJ zMt~NKHaPrQnlI^ovcJ_6Xoq|=aSx$n6Os}3_4N52u5Yt4)x%&VUTVV*ya zj!ZXbbJ3DTPaWj9CBFprgFcqPQ=?RgO~en5wE4)P?>qP+*)u?t5|Y30>4P|CNc}z8 zr*C`sH28r@vEP8&lb^{D2jcWYn!O?39@<1|3Y@MiEi90t?@J`}<7&dM@jyJID3(ij z*AOc(K!%iE)TxG8hMm$RQnum;lb(S*i$qGDol-4QD0n#K0h&LAN02|t8dRU9IzSV5 z;RiJ12q@PuYFSl>;s@c}&*2}HyQ6$kPNWca)@Q*jK?@7yxW5?GZ!$_lw(XDC0*Fhn zX3Uj22|z%YxL65SnKu(Za5aGD9v}IEg47`MRQ`!o;sgQUUmGbl24q#otbl z!y9{RyySqf-8ZaWir$Yb2!V*$h7{QgXT{>fEFc^Q8%KX2_MLqaXOg>%J-?zqK4mSw z&gurdff~9b7Z~^!j@Fihr%FqB1;9HQ@d9J{gg=OZoyUiZS^p$r??n$`FmawQiZAvx z-b&AXmT*>zZN&>TdxVGq?}pF-geXHa0-XXKki6{&w$gXTU2kLP2IwpM>(}Ee*MGW7 z*ho5q6~z1&dcs*jb#QyxlwapS89)IP1wDr(yGvHH|8xlb^u`FCLwA6rQx%XTv@;*$ zEl+rc{t6a2uM*5s(E+X=E!x#9qCZwEDNXSD>O7E}k#jEQ3NJJWWCI^zxsAGunGw_IL!=iRP04Z~;Z2rK3tEZI z$gKZ?$F*O3z-(wMWBjB7I^iGh{QkpK@A*0A?0Qzw+#)beu+3RmzUT)}x+)_qCbk>> zlMFxsAH>;m=!&FR8#KkpQm!M=E_PtciDqO-vA<*5jKz~F-A`^&n9a)N!vXsYY3{21 zOvE#Q1Bix)zXgp_Yzuz*0t>1_e+siGEm52BtgNs645a1(suJ;usY#$yEQWVI0Q|NV zY4i@9wsQ6_+KmtfC%<#?>zt=L)UMAFP3%I2e68YY)K2u9jH2q|-PDd$ihw*!0?^Sb z&_Vrr;2RM+1H;!L&DG)zBv6a9@oUXl(EBXoYqS)pk>yN42*;(UAM%;C4Bi5B;&(<( zfq{h93q7pj2}(GYYvEox41c*9eHIulMgJQVi!gBfqXOSzl%QvIrUpq}L#~|P!n_Px zj^%Bgua=@8BGECXP-mHOVLZ8?8}82K@Q;ObSB*K+M%5s|!*AU5!!F>+*b^C1uiyni ziwvDCctMGS7r@i8HTqZssHf!zbx!&Se$ZdP4yT0E^8==j!@vv1Ad7RTZE1+@K!3~$ zIvE*SOi*WcDIC2b*1wT`;!N$Dn}M5~+C+)XA6 zXf^yFO}eyX6`dY`2&IkQhW~?Fjb2X|62{;=>CcrO%g`s|m2Oa#mf$qqhlmCm8Z4_L zpn0E!uqvZ-k!JHhFvbqhw#@1_hC)e%I?Bn_2s0bjWaS_tQOiZ2AcIQC@1vo2L8RJw zcnNyz@93NelqrpYjT&BNo`)quSI}@S3~zZ2UT_6*mFCz z!419GO?m6XUqd})-uH^Bl>92e9`c_-mR3WZYxfspXTlYaaV}7F?;BEd4e$eSGenXL zOt^e+hYnP9yz@JW?$BWc9^)gyLL? zS-C0S^UNa?6q4BTKNf2ZkuD&J(4s;#PmbD82&t+xMf!d$Am=)~kk%m%Y8va*wNii~ z*tBA$v^S7Ak%sD?mLf$jNG1cE*fS^@zvkGM*F#HW<8L=ag{JBJME;VV%qpf0Ga zecGUhptAj=Tcp?lFap{EO>n^ZV=OF#u9CF5*#X`5pr)tlYfz|FxteI{-#CL!CS0J6 z(S}8e%}L3VdZ5A>#hjC9fchWzq721f<&DMo{8$|&OAp_TbZdx+4`OU8juS&1N<-{v z4Do7Fo~a|_^PfRI)AEmXjuF#-qQCwQaPdd@2L)_%lExPN<6&fQ^N$iKdM786hzlWX z{$xT6F9Ky#j2H~CfMoQdLk{T^>I9Z=GvuW}VEQ))L9?C0t<y@1mL@d3Gbdf2krQ z&z^cS+9N~@#|=dLiaTHmg!NHFAXGk(Nf<=OlpF|yh9u}5Ur&&Jk`@!kyZJrOFN=|m zfa-DH%qANZ{^e@M0x5PniCMgoL?->Dl;wIW-u1Kb2YBib7NdXIO`OzN^r2ig z;e!vhMF40dLNa2TS}E3@CNmx@LDtHgERan7 z_LN#S!%ahf3V+Z?OY)6YF?&{tXh=&u*dj@C+y~`mbLNb0`i=AveZ-q||CO9mkQdrO zvYhQ>dw8NCWqy4)hyJl2YEN7{|3E(!q?;uyRmXU14fHcq9iv&*k&8u53;kxQEtP(v z6QJ*FZ2G>|qW?qzRyfxKYQusc&zPgp_q9^=31o31jFSkEp9yAVU#16OBicpb>Cev{ zeQwquDMl_d&Vrpx!rvb8g9NG|92^Q-6D!3y^xH;F#|0xUT2D$+9nlez#QKbVp7+~O z57)L;rEO~hD}_aK9oH>Du3trdle-kU6`OwOLU*?U&#Jr_>zi;)!L37@x*l~bPZ`TJr`loEp5 z&2kbNwell}llyqVVJ_!aA}Ks#A8-FXVHwu5@I*Q+%A$={$a#s+c|uE&SVt8|oXE9? zpH94tWRg|1<{zkDnjBB47Kt=9+UH0li(Gp+?k8FCWGnYryIKJ>DMgGW7>s#BorV zc1ysgCDAG22+53M=ByT*vx*55VJl{AOH=RIhoKlIQn=T#;wX6D&dv6K`wb#DNlI)`04kO_;Rah!X zKB}^L7G=u0hLLf~sODYqIf@BWl2-iF)U&KNfQ~LjR0HiJmId_ z`RHVG<#KKXhl~+PZ5&CyfrfEp3NpWhjyKri3bI_{v=pCfPHLA_)Bc?qrhN~}VxIl@ zTBPA@iB*x`aJpr9HznB_MPXDXxVpWkbQ?wrN`&<9K{(ET65y2#X%j1Dxd14 z>V;v4uqcIeAeIfVg$z4{o(|HJ&aiVA%A1BA?kr2q5 zbQQLk8Mmd_VhG^Bd@#ZmbIxN}<6Y;7HQpXAnaexH{(|#QbjOwQy*(i?v|tO|i=uMJ zFGV2Y_X8Vo|Jd8OPwEIZ$`sBmDESZ8!v2(jy=#3LTuX~|T)zRdm(`gb@VQ`oW-bDp zl7=nlP0T#er!@Kys3Nj;4n77DZeR9%2>vBS*tb?$9V|K+^sbj8Poqj)2m?#idbwzI zprH=(7iOfMe-J_2yGgqLVp?6wq=giM8j(Tg$;-Y(Cj5ig+%)rK*;7Y~TWK7)=PEg} zPNMAvVx{o~3eK_64faBN`JO~7b zpUkTAO#HN|DsO|Itg7-X{A5>^Ll~RTwyGSPlnL#s%ITaO=*+5|pm$q%c_M@k?vf%1 za|SDL5-&Yx-Ze(eYF~x(G3u119KkY(PDVc4dcNA}G}+U1fjW37!jouBB~v;cq8+htw4Wy{p4p1Ky2NEE@m;@hS6cAmWtc&w#tjsKlK?Wlm0F zMw#+;Xos@`OA*qJXwMJIk)-2}uUoz+cH~~}h)0U+ppF*XZmjmeqbb%` zgsP{T#cn}5dg^GQ6I!qrkL9JZxEc$v`tB5eUgNwWoi#_ug&Mj)E`DtRsCd3z1=e3M zeh$#`avA4i{!C1bBiinb5sh+1w9TNe#LLp1G5`Ee%)cIooQwIX)873G57V;WLvrFW zRQ(ct7gf(|S@m4{+FI4KMAbgC>RF=d8#tNxV(JB8(gPHxCrEeo5T%TgOS?&0C$r%L zURo-JSi>a?CBA)Gg*f#Yh~HC~tNjzQ1=e0|KtX6kDc8TyCw0v#L}4rcFyeqA9H*U= ztKDnm9%p7oSRCP@2u*ld4X*GpUJLL#k6*2t`tNJQ7eL*es|_(Kl9e%Bk<_(~v&~{U zd~fG&*D^OUz;V{_jZF29I_0S7m#xiw_DE8@=uYx+N|m3gm;kb|s#SlYD#(nsL`%CW zzb+Q4|o%)fPibi&;CT-#aYM@n!&C_-o-ieavggT zc^7x0m&@3Z$h$a~UV`jL7m;@{h1Ur6V<#f-V%lPa@=YHi z@8Uwdhr65hYxocG&LrT`;6D_=HJa>0L{mjRL@;P#w+|;Gnk4D|GX-P77UHR5b|NC| zffLb}vkWJq;g~VYiD=PX5MbiV37Uo=>9+*Q0(j+~41}W!*msC0Q;Gqfllmh3ambc* zr5hZspFyG}TN(%QjpYi|CKX+A1G^Iu?g)1xMl0M2g@mIBYK#XBtouO|rqoFr zL7T|)hSx*b!BQtJYKPQ`)y92AX%;LeVb)l%B=26G9E(zFVvnKGPo?lIDfU-tUmf{W zcX$k)vZqC{N_^H5pTXV1FiWV?133P<<;hMfZkG`8b>jBVb4BfRrS!)9BR82*6uY`+1JNYB={b$w#A4f6c| z#Cd2iFdxoCf>NbA4`uYGb?{T2htB=**qn!;tv6MwgSP1Rc0*eZZ=yPQ6S03stNui1 zkk5o^-8ju!=v@GzTw7kYmUU>7!=^FG0n*MW(B0B^+F%o_+Tkx09-!C4eZno@IuPI) z(`=1Pzu3*9rDGA%GdLC{o=)pnw6zng@{>^1;nUG8MV>a#Ygi*MutrWqNkpS!X6tv1 z*MH38HSFQxlXMR(1Bmx;MnKyhe$^h|7hs8HxcVraFHz^xc>hFKlirK@hyM^ZMv$o5 zttbHzDOGUwFP(5X38EToAAr1Yr-6IVO=LUJe@9D%>^&|;t;4_Qx9EY>zld(Dwf&1m z;H`A{vxL@Cj6IBP|Dx*+|03Lqi*^kg3wijwiUG5O52EEj>nM6u3y9G_>=#WRA{g#A zb3wK9h3^BNWM;V;8$xZ@tsqVCe!5*JKS5j`M?}0u#a4|jw+*gT&HiB%Rp@q1qN?W_ zRnO4xp{lXjeCc*>Op4w}331bclXWABWNBP_qwY316XbRc3Qfhj zxfKc4ZpB^6 z!29g?&}Y+K=|!H}Pqdnw1d7KfL4OHTWk3m&kRC+BmlJkI24m%G?9vJ68S)!Z8k@9| zD3Es#f?}da>>vT&NAM*rlQ`dm`D>>6Q})Pe7A^vUHJcz7?{3mBnnVyU7rqcAAH@d> z3}ti-Ernl#LkgQA=TaMq=ZM(peQ0ou5U8RF>Fm>n?aq66cDU#aZyWC8Knp4Q4MER1 z&CBtAU7iPYbCuts^ zcK-~WeDrK!;MzU7%n%%~mT{THhfo>Hs}5$i;=Z$bX6Hn%>Ati2j%+A#664^0{TM0` zK0LwrT-xH&T_R_WCsaW^{Xh{8Ij(cO*)W+P{Y7M z%&O6^-N3mAP-D12&j&i0{LT2TA}BfG;}1XtV20t$0~TuN%G2?G9Iu4Vayufo+A?e> zAVfElKc~t&roS)*fVpVL$^T!ooP?y<3BY0pc7}3LC!ePiSTnp$__xl_$C((B$V-)H z7{(k?&9vo9Q4yck<;Y|VK1T6son8PReGe9EmTb)nfT!1-zNb+_zY5k56TO^1Xg||` z=MvOOe6!E*4W`@{R+OXg%`2x_e3OVmEB-q>o&Gxot-%@UWcGA?7uz_(x&w*IOW3*$CVkc2aha;eUR9r})<)-@%tlJ=Z zCu1bSe+F7+W^SefPmXhph1M8T@QIX1zf7L(qu&As<(6k@xRa5ZGF)08FjYl?{sxlB zg7`};yjr~bMCN$xyMwFfCW9CRy}P9tc{pRxfY-1<(GgqxLs-6W7MNmM*BysUdGJl5 zD&)FDg5TrU3YoH}{$JD_aBSK2299y4AxrSqSC0ymxx1 zTaOqo+`!p?2f)H*vp>au=VTxVX4JVzheDU2Ujio^x+6$)K9=?DcS@F zpF|%ALa#D+EPS7pz6jr)bKt;h6TrmXEdW;{|4$aq3f;olz{+h$DpzGzv5zP?5HXO% zZ(9@A!U#ujR6%XPotB^m9~x#r>|m{u(8v5j?R0;sa>o4)K2T^9UnAA(`&t3jV87ScLM>^SB(%D#6ra!f{p2443$MRG8 z)7o$!opiA-{=^EH2a%expgW>v1edL(2@(9MHUFdGSuaR2KWcEINhgbW<b_PBx1Kr5X|^- z|Dt6xpw*pwC72p!L>=$&Js>B9RQ+x<=Fjv8LY$XPwq_fKP+4J%g=~3eksU-Rl|7@d-9HdvOIph@JGHT_@X$ARgI|Q8pr9bT*zd zE3si*ulP|+Th@(~QOygkL`8-zt8zV_r)6KpU&!t`J~t4bnJ>fSzv@UE@>h5uhD}Q_ zeh=9_;gLC$wlHkVqL!TAK(t4NDT~GjZy@>#Q`UPJ9DxEG3Nc388|YGa18sD80}*<{ zmJDwo*iOT}eGR1)@C@Nr>Tz{k<#KKgp5BOx2~r44Y6E?Qtcb(;^kC$G8waKGm7s=) z&}1dH6MaK(Iu+8E?3MtvPu*a=<5Y10J@3@Tb6KCuv?OJq+#2^QwWRccx3bbmwX{X7_>W5sBh zFBKL_o%mduJUA%fcHg&Wq{=_uwzyOs5kc^6IxdC(3imAn25=psDHdUIiY%7q5Fkjr zjxIn;Kzzz;8;<_YQ)Gn7p%O4Xw=f(Teo72I10`EOfX-NLA22rjlnA@+)xZ{`m#IHY z#Aw;LEk@i)d}oW%71&j=#VCx2mKGzpBK3I0c16-INHOy868gpc6-J(CZUs4b;J1Pt z+>4ehS0sLL(}T#)$?!+AM-3VvErG*LU-CtQ@f5yDWw>@5zDR-O+Y8wf3C>G=P&6R< z_X%etIuu)!kfNly2&_7g8B{OLDpfwH+y>92aqvv4gLY^&uySTWRoN@}uu+d}n^QUa z74m0Vj~zRLGM2r9?=$X(k|9{s9P~EM7JYUx2jM1RJ*(yFrBpgQ|C{dK~QRf$X- zo;hC~Ob$dq7KEn%tXWn&(dIuR=+QC0>Y%6IbndApf1Vio^TgPn=K=QTc>w-Aa2|p` zkL-Ongf(TI&xve0*F&X><1QfSvPQOK3lKtFmoe}3uir#{iJZOs? zA2JsSRLhoU?K-MZ2ilSPw5ST0T9}tlM^SRt!PmgFAGFd-46RED>Fm57qnZ-k z$+W48&~XYU4cbzwEO-syaA>LyKQNkYrXM&_p)TACs?GWjA{6uK6@uqQ)HPVt#M_7~ z(X0}~1d=OqHGYT&$noscc?5>w$(iA<&SlJ_2nGB$GLtf@dGCVxL-3?Ttz8|Sr)BTD zRUkM5oWVbJhD-1~0~S-;;jRzfpgX6*mreWPe6r!A*S{oWt$ zrPDvuO(HX_Mw^C6Acg19eXhjKz z08huMwAB`^{fezt+uDj&5!^^v5R9AKfGRK z&Rx#E=YH;fo_o*b@{N2o$$^X?obuz^jq#KB^01^F#QwvaheT>QM~c4vp#j2iD4~3t zP=7wD@K#Yw{d;q?G!VJT~1 zeIscuPV-V34Yk{Jc795f-Xy)wd4bU;c@XR=9360!&#`7HEF)0*QrN8Rok}uGh%@C5 z+Bi866e)hD0VY_uVbafw{*{N=A65$O-}CJ%a>`6ugwT< zZkrF=q~ev%(vh;b^>!f|u`?xh(}-PdEf*8DL$cSBZ1EbWip5!n5Wi%2HU6MYDzEX` z-zo5uihMYVi?0iGcsvD>p5^>zNwS1uh}4vBqIw$OC&e$5)N1syRtArGQ7J7m_>&mI zG*D_46BtiOpd5-b)g38v^NY-IQH(s=sw0!$V|z_2)FQKZUug+m8ht{*w_C&po8;U{ zU89Od=_a-Xr72~E(J7kyWb=P2!@jn&3=H@dCSpXyRENr`m)C@Hen;GP7@FXwj>4mde`e`y^H zT=^<6HP|gfdztB1BZ!nr`t0)N$l1EDK*;DPCRI`EOq-%jA zhvX8wu8!-!Geh><<}C+bhg%^2=ppVY^qDuvjHau;TQAq5%;v!cF&`ik*)JuuvsK?H z35*r={ufbY)fbWnAI5kuz*|>+C#8};X!oS8|CIE1*K5+Ru!Yj3zmt{a81Lumz2}p~ z(w93bmQt;VX{l&T|3ovShSux&A4{NmdJyQX>G20*A6^f>-<$8$ zCS#wQIQZU`%;{++W53Vtn%<(CB60@(%(QW{eW=&jd@pOhx6Vto9Mgh2wjb^>ptj@P zydQ$mQGRw_Lxa&v&t&&ihz;95x@on~k^>q%;1P%op(b8loGXuWWe2c`Gy~0ipk^25#%3{b4zpg*IvtB%RV}>eJ&mid@}jrKV><=N z*{>JUCb5AUvKI&KHQaAw3)mE}*N99goI=Lz$=wtFJ0NVs^Zc1fI=P!!Ss#vd7mSH#^S@g6C= z*xNvd^3P(ql!LrO{n7FHq3ChUx~L1BKQa^rJRgPZNSxUD9^zx;u;R=3G3HwlM^;7+1kNyu z$k1#9<$3wm>$&m66ICG1m6rR5Y98YFn(wY^ETXuscxC*w4&Qr+TCcxFF~a?&dGOUM z7`srw8#?`rwguA2ril4TPOYo~SbwZSfGeARNLw8|rw(mxz~oIJ`pcZO@8xU~R%|F< z=`U%V@RZ1>k*I7WoRjByT{Z#L+a`sl*>A;bNQ8b8&I?5=(f;o8R2>*UQJR9)8%Ux`P0TPcYT4Zx0O97-}H202{XfgxJHw0NJ5Nn|Pa1h(L z^3_#(hD3}NPxwTY4GZ_QH$01-jPvv7q;cqi zQ}>2yJeCI#wclljqSy7$k7vp>;#tQgQ4o|(qChCRX_{5DWEy*DmHgOi8LmS1Hs7Ug zwdnRx%A~|VCColis)T)_h|E5bzfO;>lI9}D?1wbXXiUhArZ z(#8Px5z-o+Dw1?F3_pNpp?F@ao>F8_q$VEgkml>ur_&bUqez$dL`vZb9_G;qljhNB zX%;8aJTR4JIN;u*X_c*$DK)8>Qoo%jb$>Xu)bGB`)~UB_otDuo61lw{$KZ$ToBnGw z%rgI64&yled@R;Fj(>Ne-a$*6P4I>xXb>BpoQPN3jqNHnNaBX5AD7rPgir1iosfM7}&6J&NJ@o_LtkS{LrLsAifUZVy0q%)TFBD{wb-Jmu$HAP{w3Qns0W| z+F1}`dP40Ii1-n^1<44lL1u)mHzTx&lo+8MVRRLC>hF%w>c2N5w1~nyGm)R5XhYE8 zov2N(|4`Ydqt})To4aZ822oqib7)JL--dz!2b4JCqCG5nfvEAOlVB*8H#4d@l|>&? zoXh|{n=l6Gr!~(u9h&Q)bwrlJC?UvW^I27Rf;dC-4TQC68*sWBC8!L|np!j_sWEPh z<_DEDkHwWmV^S(7j#&yFl|@478b-f%34=weR*4ykr6o8+=E%4yGEhygRZC{%P>guat_3k2--3_`Cgn<;(Z39$+_V@934jBPm`m%j9F=;dWU$bn!9wos^)%w z1!}TGF(xL1#1zCtHTT1rDb?J`r84DuuO}MI=NlyUAP&5?TuIap$-1h!kJvPI2vODC zBK&1&j+GuIsr*t>NmI?$k)TIaa|&eZ3rQeVHKz!Es-6bHq-st;?x32}@k<)xYeMa& zn)^cL7tK#pbIp>msOC(%be-3 zLLyf+r!iDDr*djj5z5(mPKU}hlhorEGD%H5tGz~{{d`rk{=d;j4Y*9kZ`DVATqf1h z?ki+B3GGZD_06R^R8RdQY@&~P?XM7Hyr1B$`l#0=+$4S9?nyr;p`9gtpGo?JMAFxq zq$|~X&r`tvMSWEG`8}zRcGpLtV@c?U3Vn8Vx_+s>KI-T_CYT;ST_5$sbBXN#PwAt^ z@VVPL=gju4r{j4t&W~U$B&m{$hDM@&Kr40WP_~;Gw^fbQEHo%aBQ>2ZexW~hu4tj2 z_Q!_tonEw5KKVsG>to<7pUK$Hs50;l(N0BB*xou@UY64>sOTTs7V!*@n8RmE5dG9~ z3H{Vmzh`47`YDuCn~@WZW60hV;ObUvP}6u(O5Iavlr6JcFXqvazRTYtSn^B3;L*3{cID@*hbz&o?u{TNO|aL|Ke z&y72WMaz!gX=go$y*dtaoa+gqLh$-ZHbvI>i&g|Y?8Yrz)|AUgt}GfE87OMdA=PLM z5-O{^WzLvjR8}+C(q;LhcW}(^NR~+Q{0F^tt+TE~H3$DjZ6NhcE3X4bQ@MjC+)m9! zZ=J0#b0v4m)|6qgdx?hTN}2$dA9Yn%S*WgTPs`B+OF}J&C?Qr^Q2tQ-T62inKqh)D zs*zJCO{x{T3+^F2y->14vZP+O-nO|7bHu>mFIhX`1i2W~4zK9&ol(m^e3n? zQf&tlO~qHH<=#`+@-WL>!6#8oZl2^l? zZ$(!7IrBw5mf1(DYU`|_t&N^=&yeW#dbYzqU~dboXen+Dl+;i7tH_}-llrasvS1ed zRu`@yTCcwyzt8lyaMuvMQS=X@-71TY<%km+u2U%m8ZMt`xH!-h;j~u+X=!6+y~KF3 z);a48(^xr0wG)`i>}J(+_3=&qLeyNonw^Do*;(m&uJofoi4QrQ=)3&r5LDmQD36e} zx9jCc83RP@1?79QsJmXjQI5>2Wfpcq(=U|C&pn0Uy{}X{SFK+-Qs4XiQSUVpEuroj zstM|+es*N}#$~=!m!2sRV+DOtMzb#xPbc&k^ce548nWl3IY;YGD535uzy;)cR(F-z zuf3op(L1oJ?mEDzyK+%<^%X@|R#|jlO3`(NucRTV<5FSw?xh#@Nz2KQeUj`wgQigI z0VFAF&JJsi=(rT)SnN#vg0b2Y^(QufA6Lh989FYntK-5(=`2zzmlFC~>zIiCG!u6i zMb9n$XMlBVZgQB53hU`SKB*eOXXa_V_k zOLt1H{;K#iSvX6ks=ty|uVM8H@wT=EtdTZKFhsArd zNb=ItvVG7DRezNs`TSWuHS;~_uij_qaE6T8%><0`Q&EeBy^!1$k99aPLF}I*{hfK$>_vk-g+LM+Qa_hO&gPZJ5qHbhm7UvC*4KV zfnx^UvBW1c#*v}uJvpK1t@-R?Cml|kKM3o5a^rZrKNfl}el>5T$&qA~F`sirca|M_ zri_)OXai!A*=p}%xb=GY7(R7valRYOkyrWrw~qOg0iM)!7$vo>t>v>l5lotqChMC} zT^S!bqLSDG=VnSpe-a6MWcnM2=Zk>y_5W00K{s*lQFJwObniov-)YCnG*gqxE-uN7 z0sDLEoU8uY@r>w5X^QQ?1;=}mqnI~4&>zJZ+5mXaIpdW|r`K-j=!u}$d{o%X6H^tY z^%Wa@I`)eNw_T%J4ml+i+Hw7E-arlU!jG+QUh+L-G~Ia*b;aY_kvm|m5PMV`jcH1{@*?pq^XIAACSZZjuKJi(vM<@~YK`=x{a|@n*>#T~eTjX57 zo1fEii3~u-d~LfnRjqv_G=nx33r%L87c8R>NwK3Z3I@)B(uVAXG%n2QbqzG0Yg$+0 za7WDh&#*+GXCOiS2|}wOdBEYMw0tgJj^uuv&KRU9IUaERg??-M!$8v2EFN5Ckl#a)mx|h`TxC4fP%qO(DPI+t=f|*Tj17=l zvDJtz&*r%A6U5HM7w{zzt=d3-uoNR#i)+MWH7fv(AXg2XK#a%NYPR+ZSi!g0W6J3u z^GvHWs93E=bRTSuJtW@|k_~Gld~#lvmendEM@_aRm}Zr&BB)7prd0j1P_n?PsSzk>II+OXDFPXS$aZ|w`y*OXKxclwOoHF~gUp1Ef3e_FB z)HG%VN*b-2T})i%(KD<$Jz0Km-pqW3Vb~Fq}H%r^*NWip0sgu~GfelLWy>U{$-yTt@GsK92R?&!|{2$5x(fl886-}!~27Y8P z;%AomnQeaR%ukc~X*NF_&5vBIg+a`dk87MZke@EY8>XGgFKuE{AAh6wi%@qQ)Jbg6 zdyt5EZ-t2IZN%lQ>`F+Z_w7`qIuq$(6X|(z(QUV9YrL0I@t!vER*P{1+xrNv2Jb&4 zm>dqf4n2hJeMq9f+&x#BC5|geR6=6jGO^`id+%}M4Z_F>!rYgNS83v{H}S^0@kSk> z@oq}S^S)xFxC9@*BP||gz9apCcEncWUpUESgr+rUpqt1ISdJmH@?;`|PS*(D<8D=< z2DtHNNRb-7C#B*YVd9-~o5ss`)cmPj%0KgKH-4~mO; zgL`Sbhg0!>W#Uze2`Sq<(T#UqfySGhidSLconTtub#A=-duzNKQ}KRg;;k|9f^NJQ z4%T=VrQ!`U@owhjH}XBrjrUO>jaQP2cf5(W!^AtxjhA(Z#_N}gcaVv9ca^4><;FYl zP>q+HinslI#bt+yw_aS}a*5c^YxHiy>Eid9iFY@qE0OPAH{QglPEQpi-syg>hYPT%%pC0Y@v>SeGjp8`O#oi=aK|LVW1N8AD7b z?!j0_CvG`MAoLE?v<97^Ki(Hil81{6c#r9?NuG*R{*l(vkfikj%yRQXPTP^zpG;c4 zHIYGW=V?_no3u8Gi?oW4(X_g{X)$_kG4YyA6|}hVE;?4@eT!565pS)DH_$-4!i{&= zaRk;Z%1NBOjg=mW6wVWU%x9-d`Q!oby+@=zJH2$2qPMYB#4FvzkMnw8J{TRZQA?Y} zW30=*hA9&EA!+P)8usT5`|}celCaO#sHKmK$FVNEW7sp&*h>t1g<-Fh*h7W=HKMYJ zN2066?34DA6^eqyodxIL8!gOE! z%1|ihyN6|2dUw8DXFb?&-`yuz(iX{WsF4XaBkpxpN;uVZJSoWj=)OVnWJF?q_FZx@ zOA)5|%^jWrM)Tmk{A{UdIY{dL=y)nelx>aWby|y2Z;6B^zS7Jlu*uJzYkrqd+`}X= zR!}=xDm=2pdG&r;+n8gz(&T651J_QzS4}P(IPcbK*3`GlKVC<5?HpukiGo0-hiB-3L4;ou0%qC<~ePcwQr+ zo#9y~fw6)gm`Zd$I&rGvISB8)#&dk-eud|ACxPevef9y*A%l{5?vxd3dp!F|XlHn4 zNnott$-7)UKboR={&3np;8|F)U*UPpiQqZ-;C;Z;qV#|$>!oM<1b5d~<&pg@hw(sxPNN8txmPuf&;KhiG=Xw^R z%;s<7x9nGV_B#$dclOu^JljrA;(3ecf!gEwsf2ch=OPJ=6%;TvE1p3X_O#Cz@!sq9 zIpgO23eOeCfaf#$`+(<5CnWJaO!RN<@qAc9JHvCL1jY&$-{Io9lZ7aF-ir5L<2m%E z{R+>?9I1D%vi1Sbs^gP*F7LY=o>xj}XLt^lz*s?qsaf0SGj}VVC*i%!*sw?LOaD%0?~gmHEa8Pm4&F_iT7UPnK5?1!qayocplbmAMkwXm?WO} z%lEJLcs?wlo#8oA0?~gmH7lOCpd*s`2=BedbM~113eQc4gXi*`eZaG-e-h8Z^4+mL zo>xj}XLt^lK=hwCx_BPO!X7+N!h5gr9DVJ6h3Dgkf#<~ReZcdKqmy{9mv77M@$4(1 zo#DCjD8=(3re{obRbSQY9*mWQ9+|nPh z3sD(A@!o4Z3rFo&cwTcbcnK2;<=uMD0u!8@4d!z z;FbFoo_F*F&)}|o!1JZPNjzW8*$vN!CA2d~|1&?%cT#cvkgE;(1HKSGjoZWFac;6YssobLge}6`qqV@VsjKKHyo^ zJBjD=tljXuQbIe!bFc)W|72>`_W2AtB59v^?=_wqFW#^4EItrC^S12)&&x0|zk`p# z&kmMzid_01!J&SRoR>6)17dW_Zp13fk$g$x?j`qpviYsFof_aUf9UPd%&e4C6E%L3$E%RLg^KB<9zPM{-c~FTLcTsF-u^J{{6;cYj!Z zV&32KLsj~645ygzsKU$n;@clF8xnroA3J;tyA8cVCg%}9d|UE4e7NBrEI+olR9&U# z2;=4rKeokrlR;8CNjz@lGMsSMd>NHj#0=n{8&Ul4cCA(tcTPVIeF(DGeFwM z*&#Tkk zg*`keYzn}$%bkeVi4|eh;)Wkm1u*p^6_KMAA?~@ro3YWV_pa^HJ)^D89+8u(RxR)4 z)X+%3T=?eo3L3^1rvOYqxVTlGxUlP;C);Q+QGY&XRIv}sjp`oRdR2fk?L*OkFy`r- z6NxjNmDp4dM3AuCr$XGxGnyL-)>43hHNz*@+w&tK7rN}lk|F}rzdZZ z@T_>gNu+86;%pDM(0c79l297|$?%8ZZ+D;0WjjdO%u8?>IB0RX4gbX>?aej2CRH6x zA3iNVF{}*g2T7w{Ms3B;Z|2@$*&Fs7dUrDC=j0zN%^`vl`#LeK47z#acWv|O)M6z3 ziSMOCydPWIt3Tn#`A3{y{gmm|Z;Hn;ymuts;?5j1wn;5Wd3@Bb?@~@gQ^%X-S*a_%iSv&ve^ zY&Ay_EZH0`E{mSvtNC$KRh%OGh(Dz+f{~IoXMT&8W}X%!Xn#dXKHQv}5q}5^Cg$EK zP39`!D06Pvl*I$Tb0zspS)R#Gl_gQ0bbQ}EFo|zHWD?)PJ>dH^5uB5ZL=4-54%m>w zw+yK${yjvYChnD(=Tj32d~X$x#dwHJebQw5-|#&RM(~~Wt&8tr;s%&+5yQnd7carL z2Mt5jv-@3#S2XwG&!>IVtjTZWZ}2ymHCceY-xZOC*fz0h z50Ys&ISL70cGKit)fC4X){p{H8ZZA+c!sa`+wc2}j#x)T7`8c1org>bs zb#onm#(?wn-&=JGjrd5!StBeX#Pd5U@YAYAe7Q z)UDcFh?c|nlfYBgcPu0Pr@G5gu3WOVJfQmSJ{e)J^YCoFDB>>scAy2+nlOK)J`(&n zd*;8=@H_Qz(q-IqF1}vV5q@S*d-IevcOK8+SJq9(qhm43yqR}qPQqEne7bm3ZbtP& z8T99@@mXb`*sFBy!BEqa7|zTuv>PvDP@3>{YEXLiTOE{~Tpg5J_;KcZ$)NOSGf=J) zkAYvAj$G3vCC_f-J%@tb@%{;T7?1MFMT|6OlubVYbJH@0UyH~mV9EZ@^%UbCqOtTm zic9c6QjBqulZP@$9LAfazUsxzSULD6K3@j2)t{^QE9X-w+-jFm{`+rK^phkzVzg1f z`1Ai^(9e?`uA^`=D81xK)=@`%zsPBa@0&OU-}g2MzB1@{#P{FCaLzOW3ckHtQutnI zgq%(kYQmP7mx-V*zITd86CNVd(MBef=Re?E1`qhocK$QIhZ8Lg->#BV56X~+Z($1G zyFS|u-v`$#zHeq5d>^BL{}JD3i0EXwWw{(poc}=zS%| zs9l8>5k~#ON-sv9;y*E?X>)O_m7g`x$`20Aw|Zn1TRnosJj>Bg7{E%`mohp|d51Kx z+R`Un9I_Y4NW=i#gOMoT-5*{MJuK$}`!EcK)zi(FMK**=nj$?~9)&IFSrYUt?Q}XZ z_u~O9yNsca`GoP2>Ev6PPAaZ0W}G>)j4^mlUiS37uGSpplj*^(9wE9wbP*yGB2$Pg zh%6zz5MCj=LMT@@1oyf-%qPhKU+}Y=hE8d<0y@}>o87UQFvZklz+Mq3V(QrjpgW~h z4Bs;7?<%zJTaTLptR}RuQl_L9u9;u}M~3WXhRxfs1MiO2YHO>wb;f4v_Pl}oxnv-t z@dn24>sIs20D9eLjJ}Q;k=NoE{}}fY+{?#VYYB^gy4hz6geOW#GFl_7OX zcLe2ax<28{dCrYT!nX!ur?I_e5N;;~;{`Lpy?K)LO0rx*7OTkOL$ZL5zr)D=elMLL zgC*}o-U*bfrY>h|T{eY0Jk20em(OnUp$bSW4lo>+8SV!ROJzO8@4@9$R+d}-6=l%e zGShrAgRv~Ed&sMVbr>FKiu{fGWlc^W(f$!F?-Q`|gLcl`Ov=)3PM2`Pk^$n@{gxX` z`RyhCq9)#22w20}_oU4}iTwiV6ldj7>1~PW<@?d5iwb{o{mw4>Ozi&g@WI>w4?u`9 z<_Is1U}+>eO16xt_tJP$L$*LihwKfqeM#Zvs~M6J&JzO*Vn_xPBRr@26F(1+1nmK# zk}s_(ya|ITkx0HZg`=$Bf(4fhdBO*9GnE!J@DI_1n7yi#CzO>>wLN?ltCtSQftitIm6$PBOuohI+HVD!(Lq79F(C=Kjf zcfCj7E?Dl5{zP8F@Y`okKhWQ{fK4UsE0%@T!Mf$xT@mwwyctq?Wc-d93QcqXIJGv(OD zXJS>`@nb3(F8T)Tx1Davk3OJ$i8QKurwdS5j_|+C;zs@r36#7Wu!g-$8^oX|{RSP$ zHo8TfGd|f$!vh2L>(2>eY=)b~Qe}mT-67Ti$_2+~38u3Rlib(UGDJV`ShP|xdQ-D# zK)a1{qf_y&qDC)S;!G{=V0GBwar;*AIFAHVLr%x>gqHobf#gjfVLX{D<4HSEcx*(* zk^c#siE!uD7NvlI|Fd{J<_+7sZZc-jk;&e9V})s^HTTTTKqZG@&eI5K`uD#yu+jOeiIlYUJ(U=#Hkj<+ zkNrS<{v~0Oa0NX3(!Y;aez$*Pc~JWIR{FQv3^o1xZTdI8BGtb?)BatZXf@wR|K9N5 z_3!fyQ?h^mV{ONxb<)3o+m!0xe=XT#|9;?m@VJQtJMZ6gPRs$YR%rin4NDfWe&-wx zvzQ}`MVQvMh`M*Xv-A^fLrk`2u-ztZo&nM-_SbCdV%_&LjTW!A;0Z@-RR>ExwWd9Z zXK|g_51t}ZCG8i@?K0kv&J3T-M!|d!vgS-2v^*Hi4Dm{P&_2L7{Y=$Zd>8o&18OG+ zY8saNimID^160Ycu$NO_;RD&)!OJkMhN%56ik#E0)g~0{P#GF9sU;oS_d( z7q=C+I_1;@k5VM<+t(6luFN(()DSr+0;e&`2Rc%B#r)pA-&hf|{CxJ$%5K1)*_pEYGJA+Y_DK$_18l5aH-5&az zJ7v_#3mWB1LbBx3+P8H+K|?qtD(zy8Z$9HRqd116)5ph95ucOfH7C}6Gd@yeSOV~R zDC@qt&Rbf<#YtFhBZjm~OtY4wB-`4hqPWa<7;}^R0WG!fHOb4f5R-UIDy@)beV~mc z(ydsZULX0jYTP?crpLVLR=8`s(@RED{F65AVE5nXcnQ}|rt_zMA4)T!!N)AAS{ZSV zc9yM4)NiwMuO_2U+F0~2=U;@yy|0LLsfHn6at=_b^34aSnZ%MzXDmoK3q3XO!VA120}ME>?!0Xw&~yib>KNf6VmMQ>|G z@SP^py8k4Z$a%9bV0#)o8v;>}c{we&A>);F$NXUQkU+_1tL7V>(L>C!L;2G5(%Jr! zx2`aK2?XqBf5m51)8RKR|0RRm>|wuYsQSE#L&~??Oc%YN1Fm%er6q z%B`0!?owvIGx_rjw)T^EWUx@NYQ+SbjJhZE_1Ekm=E=D2t@X{_j>*_*p{*i%8~aGV zXQ6-cLYirY8CXl+u%=}a6@@1+0v`g0)3v7A!v3_q(8m`{U-cUs1JS<0SS6wtmrXyk zzB#L=d7#hU;j1UK=5x!JyO2oLis==gP5JuNugj`gH?YiZGO6Wm%_F=d7`s}^KRw%5 z{n-!zF+6v|QvxROt5l-NZ5hoO85I@jP-ag2g@G{-F4|E7MwPbzki6AyVM0{-x)Y$btNHnIA!)upl#N z9~3D0&Z_y7^Z>TfKp#J;-S{^S6XSul1rjmJSI)*RQ~_Bi*Y$8|i^KB0RdX#aRDyI7 z8p=pPN=n2A-?bhi{7E((dY+?uQlgq9(z?ybDjB4P}^HPYd$|R zQ2%+?n$L#>bJwJrUmMMD9P-pG=+bf%lMhL5s5(2DBwhJqVvyu8kEGkh$E$eNJH83u z?3=uUrjil4!&m)Pv#)yBtZ<~|pAxlt$M@DW>7vO*=nyk;Q<4gk2-HtAHR6} z`LSy6=WluJ-toTbwt?1t58!I~nI@?@REK-EoNt_9u&dgt)rU4QkzMmuozMOLQd^`s zy|jkH=G8P0@z*zZ4d$+**#6vwW!6ik=nAOV2Qx*_Y`L8#S#EFfRj=Df=GEceEuV@k z>O*F2WY&a-&tB`RSx07V)wrzMS2fZH?fjm`FJw0cirQGyQ1n0HE|coWMwWvl$(nUT z0`=?i0=ekLKJwLkf$NK|q1>Imn$L!Wa^Ka;36w0a8b_t^E9@hJCvHO*P! ze$_)ZKu7vkPx8DXM1FBy^`tKIS)ibA8OjT+{*sMWO;6gSpTT@eHwe;C8;{Y|==IR}@!nd@DhMh3_gjg|4CPBjxGoAr^WyqEFKBfh9 z*H?)4a-=9Mub_);`(D$O?h&adi&fG!b`7kEw7iQ4S;RA|Kd-CaLF;5zp_Q$nh=~$D zhmWuR(>!LZrBcE`{bw|?WuQP|(bF=d{F*2f7E5ItEADEk76y7#^;h(PUDaVLeur_= z0d`eKt}D0SC(Jl5FK^fFA|t>u8!Qi!jz-T5=Dv~0Gm!gXD$lAT0@S4*$kn zK>=&smqi~e+L|^Iq_xMnoY6~YVWs_{E$G9>L#*mv1Z?av^W(kT{f1Gj5po70WzmCt zlebGdwx%75TiOA0_f|$aCU5$Su@e}ucZ7-%nWHO(q1rXpuUpBle0mQ)r^cU^)|S>j zB|TYioDt9=ce%tQ)%rN=j5q4ar}s_Fu;tTv)V8MH46Ld3hROr~Q21#{I_N1s6YLw! z@F!FIoQe94>hkGVdeV~YLXw#+2QyZ~pEYr$iG2_;Hzs*WDaE^cax5&&8UP71NiM5p z3D~Dk$Ey22&?v6||Cx`cHg%kj-Pzb5?WVJFfBEE6v_xm)KGh`~B0a0`VlM7peV0td z90kbq+ui(PGub0!4K0L)O8k^@Gt7#vWQR3vy*7wLX~;6#JHu zCOw9lWO_6Zne(hUJ`ZUor{7VD>32+W`n|s8aKp|}(-SJ01Vc>@Ze+iMG<?J(f&tsxv>U%KG7<}PVZiSs4nv30`1+SU<$)XM$c z1DpfP(~p#lM!lIHf9P)UKPl7r&gsNNJ;9Ehqk}C=@J+PfbpDaM@&AwEclkD=K1`2a zxLf?&-257dnab~q4*6MgM&u_xYf5??2TwS)KM~#|;bFpiC7ecok=S4DXg#-&C(?@( z1UxQ%Zoc0h&SBH8yju~!I2fH!7>wS_hp}C~s}39<%Q}5JL;6}i5XXz~+gMo|vcC`1 zEVlx&iTyoJ&k+BUUyot4jU@Y>Ra4X-txyR-0GYqI9ihN|)M#Em@mmPcuZP#T{0il53G+mwQNc(H}Hs_J5nN<69Ut!p3ZulxR7+Q%ZC5waz!6{MhDPfhsP& zy=Zy5QQmRa+)_ENafEkls>D(rZNKviNzpmn6~W(_nJYOo4$qOT09a(_3l@4Fc&vmZ z54I+9GQTE0P8el=l_w`)cp=2Q@yk3TtDb`W8kaL|zMgpb%o!|c#k_;o5ykd4NX%Gi zqeOXzH+kaB)pBxnj(8kfZ%*pm_3@5mcW~REx7?B3tSLJg_FBDPk+&z3-{Aci0yF>K z5BQBAgnjN65ZtI?h2UKYIj(VN)-`uEW?US(?Yf4cU142_ud==jA*?U(tE~Tma9N*) zOt6M-Pq5CyS6Tl6aUiU};a6Fs5G*1k*ZUzGhh|n@C)r*S8C%&fG@EQE;;p=u5C_3~ zE5FKnJ%m<8)O!P@f8OO|ue)t5{C+zJ8FKD|`!WKQI|Pvr_XvKK+Xs^MLgMq*e}cu7p;Gr4YifkY8nZ4Z>x3 z9kMZlDuH1hv@*7^%ix0qrE9|UYWm7qIGy8OmHuT-*~qJM`2D`0^s<6=O?er7jPN%wIL1nQNW^nr z`?0NM8L`}Mob10Bf0pdOLm|zSqUqyu8eeJOf8YCpD7Lq^#Eg|5EK$}YLZbh66_0Ub zCFAhC)gAh;-p~0QX`}}qPm|-0&J<0M1%LA{f7_B)ZzXQe>oQXEaMMQrE7w5XC9axX zT`LR7^I{^j@>bcwFkc8A?ioL2grlvbpd;R(0-o&!yAz*u!LG;MPOxl6>>|7qf`y<{ zf{hTDE0~U3idboGO0aCFXF@QpQFyz-fMCZF!|E|K4>Dg#rVH=4)V(CqIP@?VxQ)_E z(tulwyPbTwD&JDP6Y?#FPRTc4T&{dNHmZE}*(v#QoyzxJ;07VzeJ~)@v&29?79HLP zl|-mQZAFdVtBE3MH4g3Xig^t_>0*w=-A>FL74s~-6JnkYof31PxLh%HG*mIa%Snlu z<1ByA6;oi`{HcoBObl1d#Yzf{9}p&qAh9doYJAe=TY|fte5PYOk9R`8e?h0@ds93n2=98#?3H*T`yNC(=jf?vwi!!0-tojM&NEIm;tUB?}T6{K^wt>^w{IX zb)M<5Dc~MY6D-I1-Ma?3R&RzRA3h(9b~Gmk#hsAxa%6rR0-3`qvsV3;uK11Ke-oC5 zX{+}|JUo#X8@$gz$awoVewn>MJi>n_P3}YGVB&$X`EiZQB4ef-_aT0DY`!1D9h+m2 z{&^u7u(Q#g|1N@bY#$FHdELsd@?Qtx@{fgN(uOxJe_4OEdM_eK`TY>WU(T=c4~B60 zOCeb@z+e__D*tuLUqq1d7eWaC;ruFpF9?^v0Mg`t159rDMU+;rhalzOy4LXjz_0SJ zhj977f%MNi7Y6L$B=~Ps{?!C2e-nh{|0ci6zX-zRUkqvRmjU0+KP;qfjbuLhJ5ii7 zUNrOFf^9nA&0(lvzT2`?=esNB>wGs^B3?F!`R-9-b)4@i*Cgk=(U7V1e}>EXfEOS+ z7oS|OmWy1r_jHLFD?LM^>_mjbe0QvPOduyT8# z*lR0HKb`RrNY+%>RE&`o;0=iT06xk#6++mm`Bk=G zLbz;qLpEmk##h`ZY`4HR9v@}99zrVo8h(}S=MZj%Uj-?-$+GrxXl1wnf=i%YKflT_ z3_{leQSWd_@QBdO^q{_&|P@ zDF;GEH-N~6l(JNYDOcor@Rtq4_K#iGO%SqjkMpanUqZMm_pcyn#$(5a$KHDFSnwyE zoC>(#B|tNN143$kF~7<^AHuEqI!J2%_G`yhG-g~lCVac8`Pq0Y?^6)eeD}xsRo*{B zn40hYD5QUG+1N3XafLrNqg%J0wA>yIK3V+N5~@i|gpedA@T*CThj5d)1Jci@edV|r zhjLsCA(eO)zshkLgjhrD`;hy3?U46^Q#OI2$x|3 zq&6`a?toT?8z6+?T7H$`DhQWh6l7z@1-DOt;Ryyc6=RfKJKxhPZZH%)UvMiCt8V)3z*4zF)(D ze6JY!WX(M*DPIL)GP0S~&>)H9@ za@Vsd*}CscVdr%gE;ZP-dS^=V;Sq@PJ1Do`JSa){5c_%v#BSOl)eeC9w-~W6#9z{O z#b$kohbJR?pV&R{}ow_nza;9P>K3T79gb>m$mF^5He{N^Q&EV0E9bf7D1Bp zcZh9rh85nvcx$)MhY;TG{3>r2gv;xNgm+mxUZDM9ReNZ^z}*g7vxj*L?*z2Vpi|Yp zNL;(^VIJ9*g0`!3!xFby79-s>7?9*nV#pqP9`-IXbU|tRWt)Ek!R>c5H{p|B`&Z&_ zC!*P{4#zto;t=SRh$Z53Mb!0xw#-RsBIY`a8(k4)x4QEK74cRTQMW8VHPX^ubQ#^~ zT}>28E45o)gHO7c%W$_7(+of_;GGb2HgrnNzl+NiGqvfTyETPmwsS;6Oxdm83Ij;~ znHcV-KdPj3qKgP?zv;gipLF?#;ch3N8Gug2J0afy=#+d%iOZEwS0)PM=rs9qoO>J6 z2B0tBSNSe5^2q@7lcao032Q$9y@5}o5r9oe#6C2zWwCf%aI!(nN3d4!}bxN&p%)y~?+l;?_(q5QIG8_R!p({(Lmt9L!Iw6lK>A$c|P ztNb6N_*X&tZ5>{uxwd-W!b7E>z%wdr^$*CYtIx=-X+xhf$HSNAZaf39FRewF`42$z2jq<`K8@TRFXCTRYDCP?`oh7kVW^Q-(Z2$%oYkp6jPFr>+^q9nKV zl|*qyKWSEme{9v2;VBlv#tI5w)|KJpXLV(Go(R<5nV5>$ zBM($~Jo6NuYyYM2+$@m<#};|rUB8#<`t{$-lK9MmOyTngE@$0e+Uq+8kqY=skeJxV zk|=qknZRe9cud7Z@L65IJ3hz24?e$a^?tq5E$gQcl(qXO{AyX>gD_?7{ywCCu8ak; zT%mu_y&!;UAt4IY%Mil;62Hp+F9?_YSxC;ESt&-vYZl&4cP*JUMa)f5l&iWcW^cZv zn4SDj#jHvqo(QllLBTBjU$TAu4&9P|-;8<3L#FWiB`)WwKO6kW;inQB8x+{Fsm=Mt z4o>{@eMB@vu|a2QNWn$q?Y!`e=3FYw&m&^OFwKeLA)*Mflj_otHBu$zIhu&BJQhCZa3P3`sXB&m)q;w8xY9R7hxSQ1O-EbIx|fXA9akysprYf?|>9!G9<|qlEdl z6efXBP(1Qnd9MBs@(d@UD^H=Mo0R8xNny*Zq&!_DG&bmu7!Ps|Y*u`(H}W`*5>oK^ zi!fvvdA`BR>5?YTN8&LN55ec{*E`4O9U{8&%$9VM^1Li5T%VHXw-Oo~H2-gy7CN_bd&O&Cn=MoYR$d~T8yUizOTKEot5HmC-RP|jN)D?Y~=c?M`m!8Ib!qNf#~lZ1Hz zg-PIZn0O3!<$2)MJ>nzw_Us*)*JI*&VWEoEJ9ze>$050696j4Pj>Pq7Eo05^@OAna z@jgVZ*1x3eqnsi_*xnn6Ld+W_=IJ8K^XAmW72+`)55ea1KL9P4me%l_HXzFQW8`7l zvf`3nb}(9%k7#{i2eBg%tt(`h$BFOGccM>89Am-p!X}O##Y#6WAfL#e6v35e>M0`;^y1OC{bwxZgO++(30vC5L@}1W?xg~{p|LyeiPB-u{ zNTNvXLR6*YxfO}k!TP8N0xP(GrOQ}^WC*G4+Sda9_ z?k>dS1UEYa_1|;}l>891&i&T^G6$XI-y{qk1g+sM+@#}H*xc|rftnwWs2W`TiX1}E zi2S6XMhH)QxZKF^b75@oSKLX+bnl0L=9K)EOL%gOsxqhL4Hz)P*Edk|rZw$cxHzx$ zjm*T(=KG~xGzRT^mRt}U40%u8d9f^R1C%#i7&~#DNs+6MT!nYmfs?#U9hC!3+j%iN zJdAVOTm6%_&m^gep229SF67}*<~9LCjHRF>=gxhkX@);~(N>Q4ZVlL%Z{@}*_X+AF zTuMJXo+ZIS`|O~7a}J{F<-9`w*%Y@Y)s=Stuf^t_5>sU9wP_&>{qD?^fc?$|B4FqVaJm%5E|0b(udpacow{O~%otj&kETfQm$KZX5@zV@JIv zeY85>H;z-(@tkp-t&aPRV+0Nweza8jr89tsOIp3Z(d4ECq?pmt2PMGLfYBzP)C7!? zfL5O7X!V|A0@SW)wDeR7_*esWX)aTaF&rKVSfl}Ont;A0pb3}r4-I(K1avn6k4eC9 zHQ;6w;4uNWNx)qiaFz-9L3((!v{V8{Ye23EXfXkK5->soR@DhaQ$98UYj8OyYrs<` zV1)_zy95+yzyuSp*aX}q0Xum_qt#n(0_K?jKdwPV;rVE ze53`bO}2*u@^$)X89&u{iT3aXE~l-p6n?e|aNEPbCEzO!m}COn_HdsByr}^fm;kpu zTqFT6Xu#nnz-QKrihe-tatnRn$s?U8j3_Grp-+D5fCC+6-%{Pg*jJNoaW zu3|Ge`AfEhBR(+@gDu=2om(E0+uVzy8Fu+1Ut?B(hDpw|dq<&SVC}*O(+HQYHn-gYEYGAza&xCL_;1)E!*xy5|(Yx5sfv`^AdZ~ zLu^(rl&JQ?RB^?yMlYf~AW_y4MdqKgp2w&`!JpgeitNkZ+1paGI94PFmg- z+VVmfw7f!XdB@T6!k76OLAhCWfnC34b@e@sCt2l7q{Y?w>`;cbxD(wLx3pc0uxiDE zjvT*h-|jFmq+G-4ksu{Zw~ zY;|Xny+W{k1c~;5Z4@nnU|ZcD+nv;e zFRIvfS8RJpuRc3|;eP|;()*23c^WCL-Yz$d^mwz}~*^&irj=l=mbx6j-oo^iAS9q=5jZQ%bYo?}Hf@pY^no{N5$!t+PK0MFBj z2A*d~>@3jl9M4`7Z#I{_L7*N0%*(6I%{&9o+C=&*9M|T{|-b| zNbfFc{;U3*z~?ct?tssOBu=vud?rIC@EJtE_`itH5mKbTM3eYT{!I#>mnj_hY@V%6 z=zD&gdXVfKpA{0N2neMKP5c}9T>jv`;WLS>JKz&0aqzhXe6CT6WWBczeNFbDw+@`(DcMZ7K%zF4VO z7_JbyU9zfUTY-gUqP#58$C?ym5Wwpx@jA$)uu$mU&`z;eE>kXaS~AV0O5anW^lNnb z)}(1LrGGgGVk@$MlVEHwKRM(2ATpVOu&5oClyEe?YI3!YcWd8 z{O0esHQWOuX=u8tas&3c`7JvTCJ?=#P}uzb=pF2R?#d6?TLVQK10|~}jtbb@0!6D0 zcd*}*aE~Awtdhp6T)*whZ+T5Hs@b0F(?X#aL;<%cenfjOlJ65Z;es4gZQQ2+R8($- z{@8HnX6U-YV5~nToEJ3)YQ8`Xx2TXOHiFiO<^VS~*`29@!tHG%F+rbK2rK@V6`p5b zQrLW+T~_FvX9o*6USLlwM2kl$uo+i`P1X-9v#?4+(ckhHeG=HRmb*CpwuBE-_xr(; zT~#D|7xrc`5^D z4}K@*3q?;y13AFYxsjR$g^1lY66<*ySD$Z@4Rgy?xl-qi&iB=(kw|-B%ZNb}bEQ?? zbfKEe`{1rH&PtclEvR-c*(AI={eJWOnzk) z{^FIzOGmZHw@j0s+|S%R&Trj|@x8h`z37bNhx<#`hVN;}K1nPnr}m!x>WOw6mnN6_ zx2*KPP73_n$e#4ONO8izsg>dHw=DdVL}(5-)$8sWjGi)b#>>*|Y38qZux=jo+n-?Q z{eV2Y?1lD<_-!v|n&2T%ZEB03H1B+I**oHw`D-^(8K1{CNf*g~gdeMH<6JqOWH_v{ zCb=$JwAHYbG)+9(A3N+|V6F7}OEy>a^Ox+Z%*9{~FHUT&>ghZ^14DNh245xC1?2|x zLhAsjlhKpX^y!yeTwFJKSN?IV0`6N(RzCWJr>VHkH}A@WUs@526;#wyh(6X!hmP~v zht||(P2Sbk{Daqi%bF@mXVkgYvrAd1pHz0^rj4tx5aMYK-1y0nwegGm_3>lMZeDX; zdC@23o>sBihwa*;9iiCWyF#A#vFury8^W^HG%tf(2+6yLV&l4mN_JY)M8oD;gKdP< z$CcZayD)>b(_RzwV1H#zWp1Ektu<{0F@hy)teWc>`!Mwd-zV18%W<^KQK@RST~~3v z_0p#LZ@b*sdN(H!>%Z+$c5}mZWkvNqy18eC&#ns<)rVrfU6Vg;nbmebs2|rCcz`saevcW>>e${Grti1BXsOH9o|C3wOmv zPpiGn?^$NoNw$WX zokEiqdYdk z1qLduan}3#R#hFP0~F|32y;2Wg)u-xSzt}8%$AUm%r?ucKQQ<%smz(O(yF}*@5I1j zO}T_2Coz~XO4th+D6pS;T5K*Spn2B`9D?0EL91+;@8!4fDYMEy;9C`jbTBR&skZK) zCQ3@Xe3saZERWq}`Rc#H#LAZP;xEc;#pL^X>h~X^&27W1m$Gi)OVMoKjf?ZkdSdb6 zOHAQjI@;f}1>(7arBvC8Iu`j~(9lkoNjTG53poVIRh= zu~B+|7-d|U*q7YyaO4-HslTe)Z-c%^vYLtCeJyP-I+<#Q4gub2Pu8%{5FOk4?Lxoj{UFc6cdp0^Ai{^ zbbK{qnl-JJ4+(Q+@SePD((h+t{pd^apmOmTGR(r`UGb2Et&?{>Hr0d2LhiS9WI6oHD*$?s;vcE;XH68aDqQ;gsr*O{jJo$ z7-8P!V7~&3MUA;F)kO2Lx-7HnYF1^4tu3(!y~#hO$@iL>KzK@Fg?0a8Sj&sQ@ilZE zST1T$>EFJFb3G@QVQDdTZTOBQt>4Dzu7kQCeFOW(Zay!O1|*Jszd4wA|j>(%#x~tyX$(!AM1t zfJp$w1T2DB!S@+QC4iFfod0+2bLNqNz4rI-{r&i8=A3=@bM3X)T6;bAR^1a*=kY3x zr=E`)3X)4)4mC^XkH5>CI-;T_E(gO1#tXX30S|I6w>9A<|45>c+c2IODjrwqweMnWwUo{d z0&kQrlfTv+O8Jc>)Lsr~v(9*!>fy$<7!r`2?x_x5bkAyk;g>-(CMAR9YrU&Qtqger z#dpGrRr2||=XJf0Tw0_@x6|7ajGU6_;Z8Dzq0E`XhqajCwa@qjIc7oj8N^U6aW*c* zRzCc2s+E1^$aam1^>Vob(*;CRXcaPEv467!Vb?5Q7UIqT7r~BloDyO`$f-rQAwwn} zrTfdQ{){5D(r7Gf8hMy?899SxQ7t2iH?SaH7Qw8rK6X&??h&k-j3&-W(lBKy5Yi~0cZYl8Kj@7Zqk|8e2Y=*cdTi(8w0 zg$H7rA30m~EP7-tqG3Zl6O`0?gFG;5-9 z%czsl`cA%*`gsA)UNsKU|Jg}LCfJWm(27iO$nV+1x%z>^y&PLM+`KNKlD%cU zkqqZOi>Qd?)jIz_G--`ysO*~n&HJK&B&0px$R%LsBkxSIat&W$181lfweIw^lvZ8c zS@&#JJr7lbTXKffADCEfCb2<7mZu z*ttjXUV5^jw5lXNf=BzkM@8u(@}0;da{l!QuOO;yYO}?WeIkzRN?-M9$*rCt%x;c2 z!f8r~BM~8Qr-~!Dk}Tp#gSgk=`vQ7>KH3{ic8ZiOJ~nAI>lC^ZC#wxIH90-Tzvrf_*UexdPK33joMQ2^Wbg1#LMdPm3u`V-6xgR zPs}ay0xy+(^0~mFw_gb>Tae zL}ss~!b934{>Fe&Bcg@$Tn^YY+UzxOUUpR(xQ+Gii`>lsAQX70D6u+F@=mz7FhqC; zekaDEM3WkuJk{$vK2h5~{bfNZ`RAUmD1r-Wgpb6x#men#i$Sw;K{%I9KHLI*kQJDuUkvDGG_0389DNv4R>imX0aq2v&8iQ5E4X} zP2N2C>1SHiQ0CA(`%CX=4_geaN7NF8csU5 zX`KQmutvdYN5Hc+1t)-1%%HadB+lRcBG9^%t*aXTM+!oCI8lga(%Gjf2-UZTkdp=Q z96bd*TLDkKfQPf_%b=V7rszHnrLW~8EN{W9-v8nN*8Oqe%+ZtAl-*K#a+|wOj03V# zTAKo~I|xJHm0QV>&iT@yhLyyZn_OL~ey~$ZZjUzij++ z#4S(MeK|rwbvrv$&KIjupB#~%3mix8QD^H-6~u5Zks-67#P{lc;c1JuU9SCPqgS25 z2e!pWO18hG7OJ$9stB(;#40J-SuWNtX`Vk{Jn9gFcoqE>oF67H8a|^5Ryq2|(wvlj z6OPIPzt(4suJE?LcBsdGE`%!hT@&2Ffs{lzlm9SGhaP=JXS_Mv#rzLw#{hs)Ib$cIC!H+x-d_2{QQ%(m3vr*dF=N0YHMpaxERBG zmcSU3?X=y09%UK`F(>C>*WdOKHg zIO#p{8It^O_l|ecmI`@x(tB*^snXjzEzc=?XhRQP0vu_(`R8NHzQ?f`&Kr8MvYARf z%s1IUmQCFtn@8Sc_gLoLAUj9iWb0TqYJ+SWd6Ru(*##S9&&Zo>8p{T4kPRcpG2d0j zC1gi?a1tFh0sWT^Q?k_!Oy_*B>!zm{~bx>t*Ij9ga>ZeHS@T_b8q(P+&+ zASyg>?dScx=)OirYQ8pvMCo-6eZz-T z)K?E7PQIxvy_ghKlAKBD>bwvLt!XECIT`S@hDwgkJ0pmY7%DlUEtT*~3Q6gyly2sl z112#vyYWS85D7X1Aoe>Hpp~SLa2g8fr5AM9^ArjF*~#rzM0|3)LEk z`WvYW%@(!m)J}WLNTF}!%%NB*{?;`|c&QhC1_x-O{%qy+TQad{WdA0 zFExsk{(|iq8^@WAi;p^*U0D!Hv%AZ?&e7|R`S~Bv>z0as&DmBuF&8pF7&UzlLUi=qMdOy}(KPpJ0pgM71ji-(&XZg z97XRLzj{U#y`vulpls6`(R4J;>!nWAZqb%%)Y=}lCs+^;Y*~r(`lEDATxc9jl_YKM zry#S{KL_-;#*C+OZSA)%_f*}$slojxR`qjqJ;_dUyVXzdT*^|g=6H;{`rLl^u*G|% z*LbVHmfTXGJL;lDFaBPl_9VW-?WjegNAF&E2bxMn!kGp{zR%AWUHTFH$9o2?E`R+` z(ek#y1LoxiJY0}j3w&y|rPtAAG_?+1p}W;`9;Hh31^B+>4DNY{Lq<`#?$nmH%JMC#6J_XJQn*0yLsGOC`p)8x zB+u6PGrXx|gnfm`23!uf8x*B=xbmTjpcY+KU}!)F-kft&f*dpXl3nyG0$ZZwQZz z^3g-kAEPPScDMHE8n(LH3r*P=^1Xw17q;lugC{R=aH5O3N^k;Ij6orV<7t`kb=_0%afL2BL2u6O8QoqzUw4uSa;I=BfsSQlgj-o@|97}$a} z{9Z_4?zE7M0d0%6bUY1(WDE{{VGMHFg|q5}zIaatE$?xb;0Ii&7UKRsR^3P1(w?f= zrg^>H6-P~NfHOFITL-G=E8OOrz0>K`C;j~2+rqNjrl=Rx#AgHu26*tO_5!4~K2UO4 zs23|tZoCNcrl=Ra)0Y0b@Cwg%wa6YsPOfbOOAqQEbeh;p)NPdu$Rhf7W@8Ssu}xb# zixg!C@T92R8KSO;)}C~fELN8neg}ywQ1{(1L@{mzPV)V@OW^9XC65b%YeKP7kE{TJ zYjg-)bCy-b532YJ51?fTiBV*;bo)V889n%b(%6Xvx(`BzN!dWC7pJO_}xCE{}iW6m$6>3csv(nzD zWr;SsW~FUqx3x1XUGJEc1ScQApJG1aEp#s)N9|_+$2?KE9UFTUg-j^@QxnthVkiZMmxH88BR??5tbk4JS;klA?~{x-Z~?2$=3Khhn?waB%4_3N!S zy#MsSW9DxCev53UXNT-k1R)B!7cPyxu}#!0b;to+fzZ}X_cV#s2g~@(cANUPNI$zf zJvWP?u-E4k5;m4oW$d3mD28k9zvR-1lw_HaFO`terfcglHnd!;d*tU445B3`@q25W z85c!=s?;g+C@56Fe}*65x=527|z9Tg2Ex75Oc>~Z}-3gdvbwjX=( zD}zS7wD{n{Z)E$YC+YWYt@5|@868z=aclXfrB!3A`fxLZb%RG;>aaz=x%bgijaYcn z_kC$=FGsafT6}WhmqGND%h1MqliUOCEp976q)=CkBL1qbrBx%7HJD>DPaR3T$Y!#V zbc6@)8`jqLU3QMa-d86{1Yz#OKJT@dE%&_S7XO!~Lm6!+C3XXF1ZKJ&hAsqjSDokk@5Al;xsjrZVw`%Mg^q`{rP43$a@iqoJflUetme~|5 z3L>oao^(LwMb#HHHgmPm0bjRGBwxl@e3 zxLLDC^QnqU`vxV>t?K8klK$W5fJb0AP!$}cKn4co#Jfm#1{ZN5pjEbz4i;q3-zb4# z)_h{clYW$csap#&^XV(DUwDX}*u37ps%}+%5)G;QJ&a>3hwCwK#6N2@%2&G+ zsUhPCn*I0y_4q{^P?fnP#P1d?=WNo&Fygy0s89Lb>$(^eDePt75FK#lLwP2$*RqCLwwG&XRtv$6js>!UpovJ2#;$`V3J=slqRFj=g zTTj&ulCDOT-A^@Q+UP99n%qgo#a|hi3`hX+EdbPPG-<(FZECZ(idSu|d>qAsfEEO| zXj67-Yai}ZT6{zcwX(>xDX$mT8TDH5pi@t2@ir|~TQ$L>O*v3nHLsJ>& zE5#0IQ=}7uy`eg7%E2lwVxGq>a}zp?Vtf&V1iRQrh3_Qm14!D(OApt3!gsSkwY674 zIm-V4-bxVF@qYMnwUoGT^*wAT9em{Dm$8?| z28r{8kbY|dS32*GXdPG)QkN%jZi@a;UDY5|-5#-53XhZ?zn1CS7<9wg>q9QgEO{$D zSd=U561BAplF~sNBADnZ_Ey!rDnHEwyvzS1U^Hf}FPsus+(qIZR7vSMC-D;#n*4D* z0)0#QCqY8E`M9mqSMwMsoZ>P6Gk-ar;xGH4OJX{ct9})md0rM^wC!Q-@k^=BVKZxa za&8Spg1h<#ecV&1LFN|Xb9VfzcuWAr3Opupx4Iw09Ax(NnvtB6E#-Ymc9vgejFNZ< zMZpr|N7j&Zwb!`PYe3vg&2&gxNptx(xr@{olsMDq=QT91=~6W+=}oe#fzIa4T4wh1 zn!?9Q4lX=X+7q#hSq_((B_*xp2aK_X!?~DxE*%no62&0W^v!E32Zi*zdAZzBRC015 zR;RhgXD#!Y-s4iIx5VLJWq0_Eu0|H?dbxdlf@Kn)Kx>cfpf&i6R{2xdj9G;E^_Vyf zfmz%ZZbv?gKSH`Ho}srcH|h&8yyidvk>@pJ$fxB+d)Y#!c@Z8N4lmkFs_-IV(`gbL z>kjQdg%>T6?sViuFADjF7e(vE8AO;-6DbBAfp0i{*D5yxe!#xWRO}+te=}dQFsp}Q z7g_MbK9}MbMmM89zj#m@v>ssq+5F;iQeA%GSC3izVl)YH39*A;9QBd$$pR=H2tk6va^@=?R< zTCh!I4|@ z7C@KBJ|tAHP1$C2W)!TEUXWF-@)1ElYhE6~Xqbr4R_oVz#~8@I8xow$y30kH50<BdcKnN4k`K1Kq&y7bq0_SN1~5ceS-s;Gcs;{CbIQS843a@dH~s6>d1aQ!x&I zO+JU!BCHi}@fw?X1q{tq(>wW#YrP?gd=hf;K=P>=N6_*GUE#v zNBvbjl6BFed0ORekRpJ--3oZnA|Y1=D0&qlc6Ygm(qFv0{N0dI*A6}ttIi%IYS{4F ziQ3v*2AxEeNxp@4z;iV5yHvMtLO#fJoALOnCNUa!obA5IIK2pCNa>;GszE-GL^4ZF zNT$<0?JAn?K{%uYvc~C}AX%Dd4>Ver5~_{qNHYR9w-xeJqqcTp(pOyPQ`qIxrq=nY zCQ_uVGhezPmilCA?(}L?T1c4M$ydC^kMKfANNPrs@fwXx2*`*iQ${;YT4)P1K^xRG ziSSrwB<*HW`k+PvR8AQQ`F+K;s@Z1xqu^1+CT1#Xxzl8(sSde2RZRzgda_oOKPks$ zcf+Xm!=mLnB7EA#$>HGSMf0<8(wuVK9E8r;l8e9%&A93K%#Co<>A600Ql75_6Elfu zA9Fc#0s5^FvczY0_nSlfCA-VtbI~z_&l3%WkGbHZdCMSt)9a3tF^!Mr)LiqX<0VkO z==an-CJ}-m_*qB0FqbXTDt(`V0J2%l8-9mVHydQnem|ByzFYJ79!vU4K$<{sg%Ai43^X_OkgqTHq{y}{&Z8U{*$<3cd~Uh;>1RDY+K6f0eL_-0TG9!h9g^$Vf%a?zi+cu)C7i6@tZtUIOPg>J#WQSfgRe1rc_awrPfw8z9T zj@uVQ_;iR2CUH3&qH+ax8@f_PS3>xbqkcv`vG93mAn}TB92C`arKlg=kp@wy2eHkd z55Ps>pxmyWILBXg_Ha3NB(1-oHn9v=3Tu$6w6#N}tG2glh_7m>fN$a3^nb8({d%Ma zzG=SVJqsJz&6uGkN{qy(&{vGQ`WFq_+C3o0J7i%r2k5Tk{AIv6o*0>KFJw)T@pq-p zTOrK5z>Zy#oB#KR2!xmMi@Um)jhrEH6vz4z`}Q_KHiH$DfOMwPpWp|fc(OAo6Gz9i?^1KV|sm6 zeVvWX)R8rk7V=e{>#OQPzJdHdRDJUozg1rBgLCppTiZifG7{hPi8vsc9EV-0wV$tw z(e+gs(CsEV`;FaX=tIAxg1)}0?vkJX2TFDtlI*cFK#Tq&{qYc>+V$B6+Tsdw$utE>#and^1g^WR0#D*5@17x z@~5*CYNKFuTKZAIK1U83a%qV8ZLpV>J?CQ|3W2anWvW8N$*|iS8nCX1eryh)U3t7- z)?f5U-rP@c;a~XSRI7h?s7QB*iu_Ej1ci)rcgV=b^79}gxqkCJzxkb9e@S~H(%sP~ zz?eAx=n1bm)LXKr{K~|S6}o2dA!L1*{Xk!-!B_GY^ztoG^{@Pov+73_agfVz3=J7? zib>(I$zTWFx&p^gD9R=%it1LHq|`5bmNpZ$c-hJd$HC8`D(;|z)&p?d={Qn}4)_rE z)S3i73Nz6le!m9&0Wm4LV#Tbi1rlEKET1{ZSF)qr_8a{SAt!kY|K?|R?R^Onog?IA zzqjO_g_{#lr5hV%AR|BUmLLuNViU~kAfFk^QTi#lP(_?b6t`cm0c$!C)cj@{5Ig`i zJ)n9`Aqu_`GTxw|_Lvw+{cHzA#tDo$4iF|={f7gH;ZQ&{1puKTH{|&M_g%=!riH)v zn^z`;CpgnC&PK$SbV{7p0sh$dGUP>j{C!4c4r)hWMoWoo`ht*CV9r1kXir^?Eb3B- z#qH;6?|LeES#LsJ()3ie5Q@OeV~9Spx6jCv{Yaf&h`FeaEy+=kRyYWj1W>q6c%aYh z|1+PN=V#AvUBf46*w0e>B%dMlh08@b<|?^`%<@qRkbB{K)UL=2{x4ZXHcf1Jko6?p zVA@5b5@G|tyoy`ueTGYHCPQpU3;2w4eMS$TInZaiq^9Jp@+*7@Abc=gO7jh$q4^B5 zxP*op`}qup*@4iQedu8MXwrQ~cXCs$w0^de*XfZYP?^-%j>edIJ}KT@K8CV>Bj0Cw zsKH;-SWfF`{<=$bT@gykhe*qv%-$lrmiI;c{JXS8;KJec?d&Of2`;TI`k9UMxN;gY zu2mYK%t)w5aln|vvf8o{2^Cr*!I)(MZT!E1xsdhVq^bgj|sE8M*RX7u!yz>arE z)+lE}e{&G4P3v}_=PjkbJD|5Va|3mtbw|jvHQ1+F*M8gRK^VU_U~CNy+YubLSucD& zc;-7H?b&8ep!pM=rng8(Vr8I$gvD*y$fC!dh$9$*jjabpZcdD#&%y5EzE%+CL(9nR zq{B}W-R0TadO$)>@O>ohO*N>|QrF@5H~7iMj*kAIi$7HY3-Q861Zs-|D^7%4?1r(# zp#Yj1apy2*RvEExQPHX{TIDZAy=TtEtKcs+O2{i;WzUXF+ReA?81^dfkW?H7b*pNZ z%3#f)sNN+yHTI{UP$3t?p$%@*&BcwNk4(JHS|q=7aEkN zC$j?D4_=c$n`UYEt*Z`H8N|zXus}R7BD0Ckt|RkbZeRY`C&=7 zsho?OYDrDD=vr+axTnS5Ljf1ys11%MBJ!5M_OjcE65mR)04U!54xj(&<~ZAnXbRmH=eoNy2NhosiCO3$l!xBw>u@h=XU4m`f|jCz0nR`yvAqq7h8P6Ms%o#0=K08TR2)&b<0uHy5};nTrQgb1^Jyd@>&&_x>N};{z^Y{-@4|be>gEWB;7S|9{WN0Q|*IHyBVT~oem+ze8)EY1|9n0UD_Ye_t6ZwkT#>2~iukByXaD5`nW%pkJWzz^c9l&L zETteeLaX&I_c_!`mT%(BcKH7f(5qD$dIjlH^s2(4S3fH`g`EAhBA2c99W@6QEs;jL7al0`fjNlsVrs#rUdz>|kxXTusHZ(U@1U0EY&ttlcc2%Ae> zuJFlRUrd61cXvpz`IN$JC4vZYX64o@zoXikR}7mhmDnCrwPjBRMd6-qG9*@$URLf|RsLlJhW{v0L`sVmJ$Z>JTK5K` zuWP7*F!b5O=>d#sB}vlWGFbZx;sa_3xmNL>IQ+k5|7x0?_U zTJ$7+He&)x-CQmJ1iqps(~aeGRAQ{uNn9X5l;JwjHR_8oH($5hBFm)$ZTfbtPhW&U z<^RSvC);wVPQI<>I1Fpd#hkw$FvTtI^J;yj7HEYxE+hDCC1Az9rO%|| zfK{d=zOLeBx-NfacpE0&hbi+~Z`JfUB1%>M;$r5Ea~lmc-wS$jGSnemyRas4CUB_L zxrlV1NAKR4N$ z$d?IC(WC3~^^!hF{gE&9lBcBoNHPQl21E$kdvAEL9U*1nI5emVO0)jPUKVtQN zO{RjaZJs`|PJem!CB=!nPxd~A@8V8>vW0w;jB_!!kw=FNUsbm910| zWV_RB>+5cG|LMb;ByhSAPs1ktn)6lWkCnxMQQyAT>&b~< zu3%eU4RD1}X))PP#^sMa2?IYAkRd1(Dmh;EiWcpp^1G1Y9GxDi<(wG&Rg2t#!L6nD z*%xFDKstYBy7Owus{t^6?a>N)@1p998C1n*?TB8;s#FnX`nn9dHiO6FIm(i)jf1MS z*{I4(7OGM{!bZvY?qKiGr$M{P&aVY#gIhW?q zP3%Kb`fdj%(2QgN(B|vIHYT#ye>-HC6{(ON;-0%(2nrl1FJSa$BB~R&JN)v-3f=4! zFc7Tpit4``5lcuZ893zKEX@;y02?A*^kI#O^91eBVX(pO*dOEBXy466dxAqbD4ydB zI>U#GWM%`&Nw?dZxY{FVBy@-N1xjAgVtoinb!m^i#^cF3>|f@QO9skU+CL>Xc8A*v z4sQgH0_LKkfO*@9ME6Yp}RZ;jeSCJ z+Rq|Bv}zW!W)KpFf9$YkIkm%hjq~_(1D@A1vltlmN@f;=+VeI!iaC(qQ`SFV;W~#8 zO>o#j;#!g6Snv4TizoY|gwOKa66Cau?(Yhyv`Y5LIYK4Ah|3Y(?tE&|kL08SbJFcV z{p;W~8?0L=-DiKxpIMQD(E5zjYRp3DlWBx*ITaMxkpHhC^n6@E*)r?eLOTBSTG^`jw;=omb|Rc#e~}QeS6HbisJ_1pLGpHC zwnk_L%cDAAgkS+P5%l~8A)|Z*N~lSB_5PI}T&zL{rwzNO3JYeVcaY74u!nqyJ)D~! zPd4ex;t%gC{;)5_A3kvS!yE1S1AHRCYBe>7&rGq1eEPpCUWQcS!UO&={4by@hKJ*w z=W>1%{;b4y#$MHyZ$wT~+@W!N1{YJ@q58%YJ}T~@mmJfzNyoe|)0)E_kQx1y}=TpeK`frrwwAc&5C6i4h=ZPC0Va;9aS#qGCK+0Gl zG{D%U_Ik%Mdp*Rsw^AFM^3_@V?|)@~qtu|fS)|KhKX1v@nH0t zCDDNDQwFmjJ)_d>)GH4EkKRNj!tc5x728lR34G_B_>ETN&gS?P>OCWzq>77tB2xio zR0wX_&y;4cLnzfRZ%AQA7Nt6#rc{52XcOH1&t<&|vGpDAyR3I_BF}#HY9-5ab_3GP zJE$tz39>VdeHRZyhc*@K4T6Wr*n)YVR=b$jP$8Hn{}7+zHopP|mnp?}@h-q?J%r`K zC2{6*hamJv$my!I`VyiOv?eDLSEbi?00&BAV8HB4=t`Y#_6->M>LnLLIjg3HDGA~a zAQZEfI>HYG;Msx=135{O_=4~|I0t0oI|oie|LXMaZz;L;Vs}E*^p7Hcz*e|gT8Um= zm!riVQepuyYF+X z8$2tL%ON=lY)QPp0XT>xMSmUOTxa%b6J0H2*CT5Fpi!9ko+Ga~P&0c#K}o*wI-`FZ zYbD(bY z0@5swq(gSinKiO@Pp89we7|5tXEuT8q+~1j+9XtB3skC1e)SAiiQ-R}^l%UYU52aK zm?2=rbP+8LjBT}UJtbS|#0dK1=rf*d6CPMz;qW_AX1IB@%I(CO1k5r$U`~h3 z?S;`u)%K&GXOgiPEOT@m(vE#EpU6qbiGA@A=@-h3Q8ch&4hU%P9)1Fe{5f6vXKd7_ z@6r0q$iw8~Q3oS;_8y*;?_rbJ7&#x_mVc^B3?Zj(Li{icVvb9O65TjsOjG8m}Tt-opqY@J{k4>y=L9puO$d?m2W2 z#y=upPA&3k`IFFSY*rc#u9`3{fuak-)TY;PcDv^CQZ>Nk3*-lN*ac}-#q^FEjXpyX z15)^DsS~)|$^dyOjZTF|Y!CNBjWV7_o%*c-ebn*aHw-4`WuB)Z=jL+!d_+Ra5nJm<>}O}==AcmZfun^+2ly1tPMQJCT8u5U@r;y*D)nePfrGiy_Xo9 zML&?@QCPDJntOqId^ff8V86k3KB39VZO!O!#iEArSe+Ig|4V49i9-1^t@2kq%gza; zT9xRl@GoS3pCR%sD&I^$0whN@Nq0nkT!my;-9dhAbLB^81El0f?5b({NrA{!p^^yl zBT8(o@}!a<%ULH8AbijsJI<9KKXm0sR0XP)l>F!{JacBFBSuah#v-u5A_Em5{Z^un zBSiAdc9=7QgT{k=zrH{>zC8jYoS+0r1+F`=J3@k7+JpT{2n=#$o+C#Nq{<8nPs@*B zZ1rh$4E-D(gBT3c_B<(*(l;o1au+RR$&=_?;`b?WQY7@89MLzp@+9hpUb4Fsaq{&n zaq^+!jKGi*CudJi2@Toeq;o)v=o(lgS<)ntlk9^XX)-{#X*Ek+{tZ-LN_`{lhU() zqBI$>CT66`HJl~}GsvO~0$^8~9IN`Iq)CNe?WM^eE~P1HGT0q`ok)}8Qqp9g70vY5 zlO_eT>|3tLAcshk(*h~P$dV>Sk+T>`BWs+x?@f`ce}XiL9UQDnDRR6o%SsDy(jA(d zpfSK|lYe-B#`o}> z1$lL;p9quQ*2A2bD+CXD4c$#zj{H3Za0E>zM&pr?ujEItDocQrx37{Qzn_vI`==$y z%QEYo{k4)GgWWlr0~zW9A;U~zn*JdiKBtgagvUsQZXh`R%IT|;9G4~D&Bk}OyD42( z|G=iThoB7i*~p)R^Snx^X%3TUiAzN1HR80Y-oC1FBl|u< zHS~-Csn!Fu{Hp}WbL3*|YytAIaR`vzNOf$gw`-Ntpq^^>t(E&^p+&3P1UIxwJP6=y z)h)b5# z^{S2#(XAB@L@*u`Y*xVtX^XwkHxn6n$cgV6c)$dA+beJYbKvpEL0=CZ1Le?T;33{> z+3*0s0*~poAAA*f1dXRpg$HtD8XnKGUkjQ~3p~(tp9&9rC49qWaceQThcRI0;^y|T z@|gJ8z6`&V_z;peh(6J78K{_3w$*z5W75&CoVGcb2+V2gN@eXE<*P>?w%@x<&adrq z^M$?0F>!Eez9$xl%g@9j^|#d9FmalgX4Tsa_4hu~7NpXa2#_UtiQtpBVaZB<(jP_9 zt3Foqz{f`U=GL~PiAVKuU+STShd{%U9AUfsqd=Z|bedlx`gT>IAoU=A1{5e&xl{pN zJ-P*^rSjd*1GUY`{bomZQcA)l@t`NBzM)cr@9jy zs;l;Q0WJ-3{dv@5nj4Yq+m=rytZwz(ju$nGY%cyh0rWxb*^l`1R0PeHg23+5sgP&! zfBfMxwOy7OW@;XolrIzH8;;6uYJn&zq}DF%&@ihJQcTh+e37`Jd}RNIvqglv8*jtBB1>tQ%iP2|XsNEb^vu~rcJ1eg@9ZIA4=dch z;Yv%-CP9QJIK4Bn{Xyz6MxZHR<2rA!z2+=&41m%$D847UB#>aJ(*>H2{LE>3m7uIl z9ySX#Q4IM0Y2rG~Xthf{J7^_D z2DEBaNk3XG1qH3Fc4#$a%lsg_%U z0E`OCg2a36;$N%z3y5Oi;@NI0aKmzu+KsLM%{X-h+9sOAS%KI@=4Z3j)=0@)*!d6 z{nahxwZFqYBVKx;}OP+e-r-YjtChM`J7A(W;hKh*}SA7d~T|d z5i~N(%emSMXhP&@yA>Kv6Zc6I=ebSXM-vKOPW}Dc*WaXfSt+xL<809Slg*=AW^vfxE|zsP6(M>O7R77^Leee6iv-pAuqXUKF_5Cm+AYWjduA`l zC9368fZ|SobPJIHV=4dA`o0atB-?9ysl_Mye^Jbfvmxw)K7VU?{^1;~12+;3fk+6+UiTTWD$b7)H2b{njAf}@}6RhARIdW=IequaTMONWmfj!`SQJl(w>j^!& zRa1V9d+l+mVb(Zl7=~^co*y#q9}b5zfm>?xciSQnSbPwYQ^6K_Y*TUiH$$qE2n zV5OiaOb$nr@bG+f=un@4xlrf_$dPyJ6%p9*^@I12n?&Sl~p zJhZqrUxD(*Cf#~eb{QO%$6lU?fbnY3T&I%EpBJlycS40H<@~SOleu816bzWL0x6Gn zwy+r`D1q7A1ghGSw}3xDLO_8@%>YqC=5vEp);9wsf7L1rWC<8ES0_Lxr~kJ83+SEk zh1w0?1|bNsM^~65NYgh(^ions_-yZCL>5nYlLCg_gVKrW%ziP;+O_xM6G~U%7QLczo%7^Fu}uGP97(Ql#|DCvzYggt8#fT}~Hew2H9wPCc5-d;j&CnN#!$Ppj7nyKKfIH%i zJZK+^10C>e4(|gz-n_(as&Zh@`ZCAo!v|`_8N|E}W;nheGu>>uSi66Kwwys|su5*Mw--rmp#2{x8(Q4uW)fMHa zjKj~dCsmGB_ItCySn&-pA1<~3`l^d7O#j10_D+?_>HS+f6@vV?n7!z~ z{QlM{Q4ArqS5ZRxHI05HIyv3N;RAb7o_#;n$hXmalgQup=PNA!bXTrm*76#0SK^o; zqr9m;mXFU@zFz(Pd%}0zeMk5XLOc49QXe~$ze)_1U`cTdk>6?jHmCpvQA6o$PYtVD zIX_*GW_Nv+IPF@NR2j5XX8Ye};=8LFQN9K13;1Tg@sne;Ae9Z#tLH}Uzh~ZU^Y5YM z>q*h8d7e9O_5(j4;U*I5W4H1*-4&^v<)xZ3*FYs`ak*6GHf;a?ZXp)1kDZ5A6HdFz zwdEGtm2CvJpY;j|CeaQEkq5afmIxPTB*nT(D7ZCXf8;>&MZ`?*BfiIz(-7-L!@P+m zL96TzB!%2Z$9?SUB_@R!U!vo-U(hSZvuGiN`qwAq!qoNBF+d@mUe}i_BRAV0&*_qb zzl9~AyoYNsPjelcbT8=m<|KM>JPKtLFsw2EJyI$fP;(x4NV7O{UKB^i|ix|T?8G~Z>8xac%=#-it{5fWtf~2DSUob+CE+}OfkT=BQIYee0j(Fvp z-cTw+J^7|VcaSRoz)MD>HXhZ-BcwR=U+88VWLa)&W6!c7WPZbYc;W~gx4BEW*!~-z zct?8N$$NqQ8t(~iZanDQqXe&v+eA8UDD7Bz7c%hOY$8QMlNQu=_(TBo-`8V9dh>wqSK) z2e@U9&%&+w=cjP%@$<5AtB57AZV=6aTjme`A>5jNnZm8R3sSiC5!ECI44~OlaI1h$ zDTIhFxDQ16OvWkrVa~W+z~Ix(a*$=x?WFTzx_BsQl^b};Aj>!vPuUb-Oln$QXoTgt z@OUW&k6ad97CfFNi@?JT$V3_8+B0>6s!|GE=h?-W)Qduy)Jr>@Ijw&M{g(RL+Y?nh znT$!T8^;Z#A3bs?f}qGLq~ne%NC#7wV_%5RvLYC(5M>;Kv9>g8Qhz-xHK~97&+JK6 z1fxGSFsW8j8SN?#6 zRkMiH>)17Nahz6(?l(=Fzk*FT6o>UA1tHV2PGqHlF>0A1;^f%-a@8_h;I2e_jzG?Q zO8AA~*WD@j6C$1_#NuOHg-n>W9Pj^%<(N++_ATU%cjYNd-=`~?Qmw~dr0}ou&UW~B z0a+3|&`$_29-PVlB>4|d5c0;dEw)cSb}Xr|mi;TMct5X+*I31`T$457tB0m0Jg_8t z!V6>-pXp5aE8qQxCj3VisR{q(*{KN^B9t63m1a+w@bAzmXBAf~dD02La~AT7D#{70 zb!RQB;}S?>8h%!xKCz!$VZu^mO)FQ7wmwasEqT`yc&YJU=&PmOA?GxE^t`@mmEX5*kzV9EJ^QQ{c zoIf)pHRpXmQNCh9?#3GlTt3@7@1AEaci)1iI9#Pm%h^ob>UdKMQ zKrQr9XJ;0A4l7vX!4{Tc>dc0UYw>Lt_sqh*9AB zihbIWbI(%lf4|kuAU!dZQ!Bc`T!Kg*2yV=$F%=<`5<*2kD$mP=JT$~srbt4X)Ci5i zUM}7M_L_N~ocdS|d2(kp#A^ASeRq9K?nq`<9lmca7m)x6xFkw4+n;fl%wg4pBST6n z_FzMx87oqdQVr9?m=sI(hc@IDiC(qolx>o-ZzHwVtB-jNFdl6w3L1(#SvfD0k zk+lT&f)=(EV3$%KqbM!lk6t9OmKJ0@(xyWl5E0EeMbsi7x6f#sggPN`$9qQR#?OY-X5#~nlKr*H$3Rt{`f9O1^CUJJKO7|7Dk&q$c1?cw>&THQKley0P;aROH@_Amt#XD8!iuv>k z8k6Xy$}hX2jy1j{_C2jHM+J)Q=R?G9zA2ACGm^&GGY5@t}6B=f9qpk@V6^R-0-7H!8D(NKGAkq+SV$6LRxg(Z8X|hdt!-z$9U>?VWSuGti&(oT0zhnWB%cQ?8D@m*dXXH^a)ppusUvHFAFDhj2TiV* zv3n0Uc*5s^2r}}Zxn4%j)^&%Dqb|d!5nD+nJ`fAxV4k5c55or`Kv@6S<-TXX1hP)3 z_gw&Z)ar1S0vd8_K+*dLlJ>#@qBPQR3bh1jpav{V2dCTxf%|c(;C;@z^910W^h7@3 zbH*Cr>tKUDe{i}MfoiH20aeFZfRzHF_i&9Tj6;LvOhZgfL(gTL^T-O7d4M`LNlRuo zd2v!|*=RRUb1 z03QU1_7!}HKPm|h`m`q%#oHhiw=;Nq+W{dJwb`WN;kiN}IHFisDmt_#s=>U(WU@C0TID9GI}gq!9uPMJ=R&T{=+lQKbYk% z-B@4Bl2a49Mk$2u{TV{J<8smKXfC%neX3RdPS%d-C8IS(;6@|E!i%nodJ}`Q_%pT; z=nwhl%kBijPY6XJDs|NSlq!&RlyY+hw7(RC@Wy$Ua1a29+8gNbG*Damp9}(Iy|$`z z(E6Sy{wl9o^v(E^IaU4T7_CC$Js8f*S;KiJ$X#UmI(K|MuwQ6PV?D50X(D+q{Fql5M>tBCSYh$L!+-1$HnFCaCm{L;wMzW5wXgNpU}`!`}~&U$;7SL z57$%y3Orx4mQXjosU3)Es%mhmoJjR=5ie-Zw2x7)e6lK$g z_8q--zu;T@UK-qnN_@^<>Et^-)J<+<8XIT@6^@@?_KXALK}( z;)W6Q!@mA=nYDW2mTYC5?N8rZ5Ix#BcO}hVnXEX*Sx(cy{4yUXD4fQcMpyURCvmG3 z%Ub%N4HZl$``o+Ra=DoD&BJwENV-c+B49@UOE2X5-Pk4tT^PP|ED$$V=}Bx~jau{> z2kvU=AQ8lW&O4_V4i?-bETh%l{RkE{UHidCIg9J{#Q8#?#i0`7Bdgz0FZ@|D@x5Mh zZslx2M4&~^X-Cm<^NSSs`wd7J9d}0`#d4SPlErfOtGR5)az(Qv;SQE1>;?i~pvDy& z!H=TlFS2G*6c2*_n++|(FeR5g=9YheVbT+-8T0J-6vMpyS{UYN#V|Kqb{dAcrTiGj z@hh1UXiG$=VwXg^DR$X|Gf)v(RF~5nz*{ZaF5NmK*>oTYBZv2}{E#yGL=Tw~@A?tx;@ci#LCN7oL2^E!a2**jM<1rusn;h zp|{tWxwhIk%N^@5DB)+Ra6Igps9hx-FQ)hwK@4~^xbb*Gio`HZY+PgbCa?76eEoct zQ6C$VYQm*)xlu>NtqeVo-Z|$xsQ5h2h9Zj!7*R1Q9HytrYOxih2>!*c|l~Pa-usEgcvDD1p8!3j_y->)#!d&Y`pN&WF6-4 z$S3i`3{8Dk1;iiJmCvs3BH@2ptUtNqO{BXaB&mK?D)(;@=}ZNyM6Qqz$LppvE(DRI z*kih2zZJ`oCXLuMc{9~URr$YZBa~#$Sy^y-;_|gZ^`5nfCWp{3m19JGYz7r@@C06I zDc3uy6X!+=75p0K?3^Z6u#burt!_$$1sl;%f)TtABA>;G7Tnqg*q62Tv z$pnCNkvZ; zK0DO=@B-0*JtxbNyQ@`v;ECLMgNTT^H??7MARI4XR5&B0EFkdTHLAAs8H4U?S__tb zS2B1yyKmcI=}{_nuv&KJLzMix+^sKL1s12ALJo;Q-2}QiA%nIcdixW&KKUnx43-8g zzX}<&fUN!KF}2Nhsg?>Cd>nXbQMsxwg@SI)6^6-2D{r%s30f&FlB_h1zNw9 zP{AVgo{3t`K6rvdC)Dwx_L!4-=>w}IOt7#|3Pb+ihY7A{0E7vC=!OaICrt3Bqe?&x zmLw2@6QPn5^DxhSrp0bYK270Y<{(=K2j|X5U}}g74hm*SprF_dU3kYOZp8@_{8Emb zaFEwp?vRX*p@N|#fp@Nb4uUuk=B%(P9Wt0s_^PPEJ5y1Ez0*;Hg|h$WVly{h@RQVe z6KWo_;|2daReOi?CVnZj@k_`vF@;Yg-r}%&;TCf2RTmgmqL6UPxp>33WW@%mle0PG zZD*nU6Br9152{9m@r*L)2mM-F^sBdU4yZ5=|JB4_E@ z&T`-Faw3`GcVI_>P$v}J{T+SFPzd7 zj^@EWOFqq)PmAT#{X8Kj;8Njk?m2TDOr`ZEY5l2rv~H0Qf0RE?#<*Og?L4|Vw|E^? zHGYPNKjPf$e4{~`B>NdeY~5uy?${dv%;7fBedWye^mx}`m(Xn{KL^3#vi=V1o zN^ubx9IsE0(XCUf{BM$E#wZq-Z9;r%I!_#BK?WqUU$x6{x%Fr}$-3{O3~KPjLq}iQew?f_=B~$$o1# zTgkDfejG0!*UQIqQ&25XP#q4Sig-#4Or=Zzvs8K`9)z1anytiqx8fg)+l|aks(snn zCFe*+*%3R3vg{o%HWa0;v7?tL9gRJ9n1}|g_73v$O`3A(bsY&TcDJGQns2cGZIxOr z`GWrzH8KmGv{>mv2Y~-RO94K;^%F~^Qn4mF3pXd`B>?72VXjcM&+zA-YR}MBS7HUy z6(eoWkRqb`TgI>3DHN~AuvVjZ#nFnb=SQ7-<>YElh-8r_LAbR@3FXxS-Cik`nwGP3 z;m|Sk*Urvmc`1rmHle!uiA@u&tzgoNuSsnwBhHwznQEgZneEjfXQL)POKWYV*Jy1A z^OMrr_ThO06o6{Re3SAZ-g8B4)V{^KOb)n;5uD&^!LjQDGs1Hew$} zp&}#3ijoX>PTqh5Wv_kqP(_>VKmS1aDQT5)sn2MQzpd(Bqoi(ey0BKPl%f;~OvJxj z1UXT5r8s$(G+>Su(}l8d-b$^Aej*bn3#aiXa0`WQT1ud}YQb16gbpi=5|<>pu7-D@ zAe=8~{Aslm6E7%HAK}a{?*S7RW$Px;d8ZcpT+)X%#czg$fHs@3d4o10n?=VxpQAJu z=gTK+%=AlThEi@)LXXxBq%a22n#s<5iy=?u8?wfS_O4R#XH=5v7eI)d9~WsS!~bNd z-S>U*M>?rC#_#eqWL|@ZwDO@m)w}&%$33Y*xhGvp$;3<9`^Pk%3*?h0j?*!`nIg@J zpK=S#+&SvxEa&8dTjk^|Ir$**op#<_ANEujdGPoF*P9EMRM7H2&K0zjp*oc3cAo4% z-Y@edvt7NCj@!5T#B#SMGBFY4tgXX{K4w2Tj!G2J?tTwdouFZhOmP+xsOi5=Rp(e^ zQ+l<@q&Y@!6b&8x-;N$=Nxq1l7ymbocT@8{m$`B5+XpadGo_B#+uJ95x?XP~tO%Lu zl%=}PwQnB?w4cuZ!Ru{(4+WDfC8t7Y4#L2E%~0nDa(nal%B7Xo`0o%`!2_a zYYxjwPuaJJFgO9FkUiO!%C8{2{0cyW)^j@f<)P zq{o$1vI(zh*;8`-JC!)gm1|e+TYgAaF+K|7f_kd2;E`Z2yrh__osQ#spWRKz^%K*G z!Zvo?M5UM=#-Ezk;mPk%8#_> zQ10K7$5c=zq%F4D9cwthq&BR@n`I?B`g=n>(XDARrDLrb{AkgCqY_ke1~#eX%A?dA zKS=CSsQAZs6BU1+LMm<1_-=Z`cu}mjE{e-Vu-%d35snE2yqW zH*c)skf~y`e3|i3DZYQ)-m@4*sntkjAq8 zTR-DHu{Eo_<08t!`#bI^vYZi}WI2OI(lL$+w(s27S*?cb(aMmAs<;4*hZ#tA3kt@~ ztbkR(iIpMnG!S6uQ|O*MbUF6T8FqHz!!w8lDxXO=j6c(M7lE)fwYqgSK=IU9rc!ky3?9OH@<94`g-`7rTjqbcCc@ z>*Yr%rTF~5YZnoE;AVBY?eSGTS4zunr;EwmzSD{wARH@nGu{stCL|uPL#Oxq*b+cs zfSqH^EqVO?V);)QbE}_lUbxnIqZa*7>=^cf9nyK?Qex5~Kc%X-xqIlmr0Tqm+!Hj` z7f9dKzqGxJTfNW0aFxrgh*xvpUqc@8cjx4JB645mMbPd%$GAT=6?NGyj$>PvyoCAp z9ErC+XRtC$vgVgdD;O?^P`djBtJk$v!6A8x$tioGp-j+@HSzrU|%+50D=v_uPAz2-Ba1FU8Uw9@dV2VE^VgnUC#Uw!eIh za0%+C@;;g(6>8^}BjL|aDeOdM!pP`2ewFNsd{1P+o@9hD)0SK%TKO!{jJ9Dk93|6j zKGi0j82eNXebk~Aq_Ik5dCW38*H6gHsb>dJv0g0^t@20gS#)axLbN5tRFDnoE3ua@ z4_b4w@55StCv-*b!;&sk@#6STYn6SGpWFMSewVMx^OB1V@JYQ{N^VZmU%Hqt^E>vb z!K#a5B>X#FY!zbSbWw`2FgCLyIQGGD2?02RWx#S01eR9kQRGUs-f)|Ocu9urGJwDn ze};M;fAHwI75$W8xe|sN9T)wgr}*}WzGmGy^erWNSY!UR<^b2_VW7;Bz2TGBwihn7 z%JYRGw+pL?50NBG$;Jt8p^IMUwfU^e}uYKqhY*~^I+F0*x{bK zMj(2f5gq|ZmAfDy?X9~Ppw*8b>x^%W zC}u*6J4}dfc}wL0jY$Cm{nI3jFZbrh*9cyquhp#wYiKIalI0*^K8(x2L%0lNI|)c| z(GKoU4u?3MvPOGhUd=4y!J2w+V@|zyUrxot`-By24nHrIHA!WSJb4jb=HcM-;4Z1G zkqz=L=|3eriI}T@R_A{N3}(&gnk8J z?kddXxDPI2DaJ)nm)V=89K8-d*#f;A@WTRB2KSRAIiMS5P7x>jQlHqZ;a6$9wPIn* z#osTHvRkX9l;@JS+QH#7N~&ALZVlTL=p&`LTZ`~07Nn3d#vo_p42H^8OYiSy116KQ zAHpU@*f~fx`>|VvPALLHWwM#jD(|GzR3i&bB!J3)QSa_@+{+y$kpc0`NmKfFMPIba z{=BDY%qQy3y^&O%*y|FbL^mF?mOM8EHB4xaT-qXzhcOj*f&iQrv!WYIb>mEC;m?{{ z;~SXV=(u0CuzA#;kWf=mV*#;M%Is~eRKSa+;Hg{}B+0OHAaiiSJkb_NP*uvjKMeq& zQ+Vtpr8SaV_7BIlrwo5@+o`-dDSzn43I)o}1qJ2+ndE?6I(!NWXfxZP05N52oGv>k zaE8!l$9th27GU8&b>gpTKk-9T{53WISAWI)-_mjZ!?QATAO23746AuRGcm4%yx{Ve z!Rfho?pqu~wGMwV*9#uGxW#Tsh`K$H&mdxp3=0lBB%^Q9&7pSN&3w(+7nC^LpnUI` zDR)2f26@uj>K9lHR41^r|H6m(??`a8!uMYu;&msWP=4 z>6=~i8BWcAB+WikYTk4oHSZq_mtH4NAIj5edD~iv&3?Xf-dQZD_e!S z78+UVX_=?QZK-0iF0%AWH&M)AnIbxozVXXIawo4_o4__7NW};6C4Q7%iNag@5EoLx zSrhnrpzBw9JG(1~rMOfmEQsuqo-jTk4%va`aBuD2#FZ|-;s4c6o_Xclf^Q+?xZ6B| zL5=aBI}nn}I((6Pm%d_X4^vYLA_CENql$}i*-4@6!h`LLn9@{!6shT9CLT;R&;jH_ zXdnxAd15wD^997-naVKSxk|z288}g#P;rpiSnM96Z?GG$Y+@;aEdh za7qG>)>k71pKISuEy4>T2Lz--#kZ}rk?Rp`-$(FFYkdXlw$O_(#med=H3Lp zs_NYP2bqF^Cs5I79YT#794aU%QPD&Q>?7wWtrNEu#VSf`RfHVCt0w+sY}^7rch@i;h6daLQvcUFvq#fw|CZ5T z0;$7W!ncgxFKtNuw`Cyp*@o1Qpf_ER`mtx30k@e@hi3q{2sN=JjuP1!z%4S#F6g$M z0sQKP;xm9(i_ZW~1Uv#vnz@Ig05lZs@zn3z=%1L!De?5ZcAdJtokwtxcnx%sSJoMS zQ+I^ql~)sQN0kthW|F^G9sjB`^Wi%BMO!Bt>xene7GNE79t)WWNb~@LqREBguABjo z-lHJVbDp6h|NUnD(5uPx%C1wl`#cJIMRckK++n=x`tvgG{GIxv(*7G~*r^tu&hx#{{0)-|fL7BIx(aA~^^Fgg)7)9n}eSpPL^`9u?mMqkia*s{TJaE$Tck;N@X8Xg1sid)aD<58X!rKk74XVCi4%c1(a z8syY5^eTGL1!NbU&i*P?f1lie`dib3`rBMi&9zIzMPusEh->#Qvs>goo<7`m#j-j7%7QQF zDj2C>!fQk}%4c+l?D)@Ze%oo``ApqkIh%3%vsdi^<~CkspJV3h``FAkFirJiFMZW! zel9o6)I#Ie!vmyJVGk)WIY7E*WapXh*LCK1sI%r+Yy(N%v7O4H3t}|9&H14RuXC{> zbN6Lb>uP_+Yy|DCxA!jRYliu<*;Ey$)@Abv!}b)V{x9oedy3gdS$9W1da133_i zCRf`ew>r(3HItUoGMa2s!`RSSj0X1D-~}!cj_Ks1$pu;`tXxRMYk+G$b$Yx_6b-sm?u08V#H$||!3#TtgP?48H*p(qc z$I#|p-N5ccV#gSfLM$?jSZby47^XXQq|~U+;g<#|4i6>&P&T<*g{ZRGRS~LDl_85m zd~|xJ@+u)=sPVVJN9Gp(6!m!W7VGiU7sDPaY)Qw^-MZ`XUe;q=-RtjzC~HS#tQU7c z_p~GG4ldC5>Z~z+b*VqfxYlj{^OHkZPrU505xmw#s-}PV*j93B8|R1I=Qd7|k(h(T zyaRmR|NV|~Rm#~52DdqT!Q8!30xy-j?;c+1M9^LlywXh@tGZc#-!%0&(r}^lRkn01 zr|?8W-zOaJ`;1DQ!W)o0clMeaugdBlpPH<$D@wqZ8Ly{G`SH5j{CLCraJ=FDPRARx z*Ll1)NV=K12H5Acl{_3V?Yz`t+m*zv7v&t>Gg`ko0E3q(9VfnRFc;;5-*7%gL9aC* z&!3W?4{NSw?_+ z2d6;!6QF2nwd#Odtg7Lw_r>y&kI2TDTx|nutzEzjvF`E3peeNnnyOW_*})5{HS$z# z6OCv-WQKQ|myS1qne4s*Gg;LAVW6d1`{YrQ60ACOlhzrlK`ivBTGldY@W!S83RR{(F1x;9q2+x&Wk_XfYLXL!HU z^$OZ6f?w9l#>qFB)#YKrWL8S0nPjVED|K?rR%!+3ckN#CE*ny7?F#jdl|uRS1GR)H zNNqEAAlJ>%kd<&Gd7UOg3v~tywbD!f#qPiSLfMB?KeisRP&#Zu`^RaelWdMXPz+w6 z#9KBg>zq*-uUA_#eX!kR`~i0@DCQF=TBWjZUixU z#tkp#9X?BK1QQZ@-3Z7&&xHhpGhhhFBcBZD%C2oZ*=TvQakS{wMn9j*vunt8c5vam z@taJ~^@6{O;|T_Ax5qUu=4qrM@iljxChLR|w54AOV6DzlKylG|;_*bkQ|!$Q{`TOF zSu}91-_7=>2P~i7;K7eLELKDb(|efzzWZ(}t?w!;Xv>Gayt@hx$k)pwV&Un-WS~Fr zcUUsCv3QGV&>sus*MjOhGkE})v%o&2uG3wv^(%g})twa51uv(QuI8BP8Uim(u{sM* zTxW8OT=?JNiCp;K(;M_|`WkxerTo}IXnKoX-BQg!{DX0Z+-l!d-g3CZ7sx~M8`L`j*NSD=hC#}Q7h)KqXd$4D;MU1a=r{59s; ziy(0tfoUV-GuTn$z30zq)}~tKvl3!b8s@-JVO^m}iP-QJrqsfs>~m7oei`qb!7)-o zMu%<5jtS|BSM|c|KGEcs>_HweHv215BS}@bwmg7Qj^PLCdfR(7O6gK9pcMSz#?x$4 z*xv#BSgPFIT2|_sbcJ4WRXb&3p%-epiM#B6rq9P3oD=^@V*_OsC)+B{3CB(~2 zOvMX_*ssbpDL0(^Wm(uKnmV1Ru2rum9#Rb4!ND^^+$Fwc*}8554Je|NTzF0&IJoB6 z-6O>QhWV~)OT3Ytnb%j!aVWBI4vUIjJaXMkU9h74pHWWUy5nus;&IR7g^mzUFvGsr z{hKzFFisl@l3be>E@h*X^UhHembn7i9NRPdT1}D;|3(uPA9GRZLgYwM5X+OiemId&SO5< zN$9+UN1gP+&M;>PfNNd4^P=gOPM>vN-DMc&5aVFhy2fwOp-vl)&F%{`I5Qmo&fj)p zeDgAK>|{8gg0UnnnVFgeuV56^xZP?l!F7pDN#pNl7i`gG@>%XSc=aFcmN-PYt?rvX zuWpv21b8ENa5~X9y1MS%+2_xge#v>Uk*!|;Z9yK@`mx{IX49*~g!-|y8%@J>i)KFA z*v`aw$t4>#eM5QFY5EqvV$-Kmel5|3>8{xo6T z$I!>Nc7y$&9WUIGwi$DStw}y&ld&Nq+fyMG(>v*?*>Fi}l`uzkHKy7 zy`(9GfV}OrQk#4&mY((%1vOx)g@E~f3zxk$FOl&tf}`6`Sx0j2k<`^PyYkB9HQbEBhF!GdKFt4X zmZ*cpw9;+&-I-~dg4O3=cIgG*t@|z^EeXg{(^^|{>Fjll-{zZ|aiggPu*9Ox)Rqd( z?`&@TXMf$z_J5^D#8$E5O2!+9c+YYs2k3AO*m1aDdP#5Wg|w`@d#h)jH|sniQclnH zWLDUd;t`0`(69pJGtfxA+Hh;2wf8UL>#kvixjb*?% z;4V670LIPm%(qsVZ5AE*WCT{oM*J-&PC%*47z5heB9woYn^HmTO6 zU^)hM*YhdWT8vdz?zmO+RNUF2Mj9dz8k%UPCI8yomv`fny=G0HZJ$2xf(sx6Qbg&~ zDhZitbDwT6n6$ri_vwG07_NjHO`=YtxhzpPb7!MjSPy%>#F%jJ31ffFphf|*6 ze0!_Sk=t^b7XSURf-!U2(g|@{IR04bM1LdiV0^L1-?_c(-&}ozQ4>>db`N^cXEnHI zuzqTOxGO&-Lo4&TV3m$UnM zI2M`kqIYLAec&HMtVEUtC2V>=Xj6fjT^8vz7RdX5`X=vu&_>0tpW-M!(apqv$ z6E^}u6WRcviERRpQ`(}f6E<4i)P&8v-%Ppf{B9QvP4HD_qECEw%Up4aPiZO3@Zwji z>tuTJD-OU6A*PlIwBRjt2UqLvZV{H0q04UBTJ=XMSgPKytJ*q_SRo3sxZVHRaXKnJ zzj^Dpww`sHc(l=9$fN9&-L{2tCm@?H`o^~@y48%At-bk8ev~ITn8$GYc4RO#25uZg zUoyM%C&c82?ebRWIhr#2{PQk_PwqrhBu56oD6rK;fDabao+MTM6d~(a+7Zy7;r7;r z`S{(j+E0zz57?VJoJ}q#>>nFWg4ZMr1O~rt-CD1Q`26xR?5p?b#Q!+^^?yYgK4BL# ze)U%ZG{;2OR_J8hovS!8b^pC(S8Nfour6<>Xr%rZjLMy0{NFb)pVgg#`F=7m_d@ZzafUWQ_yWEhPaQ#0_DYMve9aj0#mGjT zB<*#NM^o37`%&(*tvOhpKIgpeC(f%2gK-D^k<+}uQ#-#4=MD!-5~l@_II#K9zinBs z9?3Obp!d~dK8NhP<~56p84tT;seXdyIe|Qbc5CDltnU?Yc4-<;ZX92--AfHRFEgM= zs?TZb2lS{r3AH5Kq}n=X%B)DkeyH(fnfs%mTm;G+1*aP#T}vu0NsA3OkDp9`J<<`` zf5ME_Z^!=haxMz$jOtqFPcPwnbxY^{T16EHn?t6?6sJygV$cvpPOis{78qLI z%~B5RoOPoBMdvD$I?)^Sac7pQtvyJZT28LhGNs?m>*J#7IV4lU05yc-j>(ll-mtYY zoe7#9AFk*BqP-Dedktt>f5*g&!-uXC21nS1yXCND+)d*yWdo9+I1%Er@IH}edx`Wc>W^hfY4`>3;;efdC_1H~N;Io$X2dK^P9 z?rVm#%$W`{{>dHd&K<{E8;6-W?iKwontk~o`tqZ(9M0WU3WaUd)#5*Lx_%{Bfc_R1 zz>hqPw(EO5aNnG1-wX|5Y4C{~W&hhJ_~2`(kF;U^8R18HGWvY?(cb##W%}sew5Q}n zPbfqhVEWOZVld6@3qO##ftkm3y7}RFbzE@5-EP z`MOz(CQ7m-l2-`?L;r3DRSeE7NoE(BQdk!=|G{PEJU$S1I@f~>_0_;)_$J!61V%-@ zG~QA@^y_$E{F%(ST&KHW{|Q}7U(2lQr0uew0C=kSmRnBrKgBllg7u0&>W5Hq_VARJLzeTkzDg?kZmP&~!}KOVY^*2)c~k z<7Ft}32}8Ag2Ky$HC?lEm9%Deqh_blqQb89XEYh7P`JFAWw|l24-BB^VosgCEOWEH zIHQdd>@I!2=`d%7T*T9n4$-8*)IB;j!mK+P0w=)%9XAYWt2%%=w_|*pj_eTE-Eb2g zvO}CjA@7{Wocr-r$_aD&Kb{V0!Yd^hEz*tpt{pbx)?5o2StYpki`&ff&eiNPw$+Dr znbn;(vpm;+mu4>S(oFWd;X10T1!Ba6u0@A;*Xuy%W!p?@IDZfoyXd~QACjM?=RaZm zZao}gf6l!$e0QH-rcD9jA27qb#77vy7X|o>D=4zy|HQQ-YT*CiJJ#Y%agRnSk`(N6 z>`=$UqGN|v{~M|pSiRTo=+&eCW0ZI8qggBLTuv_+OWW^Z14I1u@#ntW5Slk%^1c!EHa#Fw;$08R8jJbTJ8H-C=>n>o-5CR2dR=vwAb4n-{ zfw&)+14^59-PxU{u~J(m(H>3TJ5w7gz07z?v^d#aU}VzwF14qt#J%|&c_fx)8hbGF zPX<@OAL#iQHRkdY{V0@;UNc#0Ki*`YXDQ$3+&X7Yv+1tToaRbmtOH_(2-3#Ugr>Of z_xa*$02Ob>)*k`+kvl?jns3qnj-glc*)D64JXo-2_LxnSqFWytQ2ly=#>}iuvbU{^ zbgzFH9?r8@7;dfMK5uAwLXgbldY%US8uL-f2ZH%n#e7)4roX|36y!7MLy?{2Gr7YS zByX?iZu9nv;XNlW>RM2I=kXkW8nh>r*h3}_9c_sW_L(+zJ*vNNrJDwpnFe*}wseJ! z_qoL6U@CO4e@w-4d&N|U0_Uev_b%15bdUwUfiXgyJ$B}8dh;OmxL_hocfqZvQi&M8a^GKKcdu*mAYEI zqkd=di_zc$+9c{pQ(!VyyO?*i%Uf$#>H&wCM=u6BiDl|o6Skg8n{v84D>1L?8KU6u zRRW~{BCrw@n)3JDEzgn%=uH?;A75vBAX$9fz~su}>qdSVi_0XHT2e_tP>$#+3Y*3H zNm`fukqbnq)SjdCYSKR&=7+9|dqbn6N3!}-Z4Fz6`IK&TrlrVFYpST?AD{#893 z80wXap>??0a5I20%XXe;DtHu}r-e+bCP*`)dinG|ZZ%5WV$_{?5l8Y%DA08|N_iSA zhkwOFt;1rT6wKw5P&Y++;Hl05OS5wvzKy3&o7;D4Ej#DvI4R@nIw@- z7g_0v21L7*J*XLq*N!h9;LHm9Ki&dX_*Dj*<&>X7OKd=C_kR&eB`v zMip1xD_mW7CO8u3o91$YWbYi?XjhQAl%VkvE@^5Y8h9U70n|L2cqEoCrw zBvfl%4F2M#4UScWIjJ9e&0oyj=RR)WPqq7`w^x*H^!D0xY-nx4j554+8Xs+Wt}S`i z){i}kwqQHI$xT69C?YzyrMc3k%bx9Ys_!uVkU6~adPCMzHp3kD04zF&zS1r{y@fIk z#!WihvY&KV7WRsc79fe5tjvY` z(J|8_3(H75E$W7LnxDI{ch2dN4HDC%55LZ^flB$8e$v~_+Vm=C)~5Z@T?9pg_w?xN zo!jKan;5LlP&$Tge@uf_8*Z>_!0%;)U82a(d9~H*aw& zIt!E{p6#od@9fKBF4pE>v2Vz4L>gi|HJ((*S@5J|{2%bvI1d-!YX+puHd|hZTQB&r7fGj9POg$FlNWmL zYJ|kDohPhwiBX{RM($EeO1Vic+01nuL;fKOSsa9LOzf(2)Prh?S^h1BHgvugF0`Tf zT3Bd9`C2FpVS0&L_maC~4`{a8=)J2WKz*|wr(CC;7Mw1)Z|keE^w9O>EQuw}0<5~p zf(@_*G$FCn5}T0pvcc+K@-(86TuI;{7fhzrCe23J+Ng56#i@n(pRDDB zvW$o_w|x#Ek4#iY<$X5v*Ol@Er8Pj(4PvuXGa^!2Ba5AyavBCWT5I;SL8jb@LMwUH z>d7datJyt86>zQK#4csyr7=$y#Izkveq(aV;vz8#ZNO4Z@^YnTjVB-BASQh|uum9YPLaQnWQ%wKcNnXo^Q$UhOUQ%=ATAe3B04f%hU;$4LeA{WjtV z^_Ef3z;dQRBV=Gb2{2S1?YS=2b2C)C)Z!BUn5on11^f_8GLG0i*VO3Gq%B_hv@L|p z+k&zyR`pThMW%2vontsQlS#9GWdG<6V=&EYF~6cilZo-v-0d8kY|(+=TcK5JG}1ym zSmF;qA5HaT49F%L$wMfyz|Y;a%-Xw9J$LLW=EmRzetTv)R!YO9UBODInUU7*8cR(Z zL5}K5Vl8ZV%SG%GCvwD(v@OV~Y_=G(&1krm)%{;2LGhAgs>=5EdOnm-g5nKZkgGE7z7_BwIo*2n#vS*i0Nqy4Y%| z-t8s_$RiB4UPsazQ>xM|IR3=bsLO&Pt!{R2EkKT6%;iI|lQ#09U=ma}PMsP`HWXDr z-Ye&)?(5l$@Q3J>|D_I{Kodcf5Talny?f+uD)R&?Jrqg zLYk7qwVCUAXJdj01Rr`Jo_qzNNJYg#^W*Y0{icC4DxJYh0}y7idu!R86Ut-BONk#w z#4PRk+6Djnlp?!@DMjKD;(^O*!m?gC3HvZMFx-Vo?-D$Inrup^JJvWhwVN^qOg zujKBfr(ni&_dC8BRrG2HA-?xLHa6p{K0>kp9BIeExCk?RPb4zX^F_21%>hsbs{NFD+|vmx^}yWeT@ zklH5y0u%Y;{0y zqA3Wi@`YH1!h9j_!I#e$vL(nD;#kqcguld!hVnkSK$I`UTJJ7jh`3dkFC>5*;a24g z85kXg3c*l9whAO3T+ceZ0GAI6aXCTUv%81roNQJoFB&v?Yy=C#fInOY_=B9KO1$K5 z+4Dj9Zmu|?bXzBF4^B=}Fx6LOPZARrO`l3{9!tQEwq?VFAuX}~maR%o&QXiGkj*6w zY1!P%>lKib5ncyiAG)Jed)cpo53a0~%-(>Vg4Z!_1aEcV;H8}EX(}FIBC(|+uh4nD zs~g~@rj$co%d#blz4Vm9&{(G-@E?WBChg^xCdRAghV-`8=g)4i(yiJ^i~4ztw-*Yt}$guXT)kF537=WXT$@ zKPke`Y4NAslt;}WnV$TI5Iq-?>ASn3(zOQ5r2fiA7M{Yj4%1gN{rb1RoGcdIfO&t8 zNsPud$2!Jw_*>jNSb7E;H;vCHpXJ>DjSey@Dq3axFb~gc8b~i;dd99Gd0iEWP zHB)y0eq=s-fR_u^G=%|60N@(+w8163B(n?W07{b5%T*&=B08{k4#CK!_J-Uo6C5q(>L}jW#}z*gZOIZ5R9@On;~_y-WXA z2Swg&m_C|(GCO3vZov07$tOd8fM6pK;}^Aeh|gIPm9IwCvJ#XC;VBY!>gHJ5qzdkchn*2YtpN&ZtLM-Wh?LBS9|6K=bwu`XsY z**qW4!!7fghg%}3Z^pX`cdt)+&K)co>m6WXX?B#uS0)c?g&F)X#-r{O%t1hBjUV~o z!o|?Ua_FmQCm`kI+Km9AmnyTP2pN9_^tGBYUFfTq`l^-toz)?XbRbktu2KJnL1a~p zr}{$OvDs@n;lm)GTyBXb8gLZRTh&ZVj8)ApOWa`ct>`U$lIX2Sx9IIELYd2x{}S#q ze<-54_TiS0K0&iIAua*ueF;N+Op@^zBx;T&XO}68Lw$24I4d%k2)W5|h`i@RbERJw z4*{Sw&)YLZY1socq8z`mGpr}Y9^Zv|9Rb_sx-GAIOE)PLDQY|`56L0JzCzrXE zov7`k9JPfdAFufZ8wbL$yAJ4Wcw_W7y!m{3%K@a?>qKwedK0EV^6-ECU#Gg4GlBk* zSUH4vgIQhl-$r%!p)&?!-3Y_SQms%Jc2w3fX__#+x4qv9)vbw~GqKu#^9Ok-5ZQfk zSqK6Dza+c6p++r~hTn?Rf6OK{(mNm0YarG-v0OXTf!SfbuzPNuSg9w)La<@Fl#?V1 zDDJHkG>S_|6@$N0~6Y%PB?ok(w}xXS@{*J+2{j!>_EFN4HHQf^3kWXq zuRm+w0%DUVxQ^Z+1VL}3y+m`$q8*^p6c`pk=>WoFRAN}2J+>2lKo>0&4L%1hA$3!A zxmQ)&Hp`DJe2F7SOJPR!mobGeaazmlW#aSk>q>eEH=uAZS0jx|PU-L?`kyV*2NawnI{i-%8I|hv z(Vg+?0Mg%|hg2A$k5lR^=#%BoP@>0qe};0sZnaQU+BKAnH2mW^s&DT2s3Y?bS4H$~ zli$Yk(0}XuBEUuGE&t8ig7cPNaGQP5Km989i!;t*dF9cXVV9)z#5@HcVHC z>1t1|(Aa<-!((e%jh8cSKc?o0*sPZ(*grs*Sw=h7In`owwG(}zD+sh zF|8XM&TQ3V3`iC{a?gmp_mL=sb3l3f-H#;5!X1Q$M~l_OjI(h@y`!fiMTFnf|gLpFa3a;XNt=+ z2ntaKuNRJT^LVv>1Lv6^-$}yy`cJXxJ|Ei|jb(xBe$LLtY`T4Rr?7}GG&CWo44!G% z27jx)8KIqe1MK}TPGt{H7;Px(uqaYh?joSapQ78_H8 zrTm0>L2uwXG~rqOJu})^@^_3j4l|>TuQ7ryW@?9j{E6egzoz8?7N*g zN3nhP4c9sQZY$k2A?T5Ui=Pn%9G49ui{3qgUKj>?ongk(f7N{~b@Leg5GfHN>>Fa-*AXofJEp!k$#=os8DY#Mi7vc8%-(Oc(~2|dwshR@;J-P3r7 zvE<{rOWi$1^}q!=`@VU6NBa;nqAmKq*IKVK`sbx?oNUFhcW&Z7Z|__pd*`X`*)zi! zyHkVsc7OF$A$Oh@+~%})xqBOpm&)B2$r7tsgSx$qUfvkAS13ZTUiCI8>!Q=Fe#jzyioZK>v+**#AVXyHyto0d0yNLaK1D@OV0W$y~1%He?84VR59=qdQ=U zz<>jrLVM;*DA6(Wp8wJ&(}Fv;LW}CRZPQp30(zwb`qg9Tr{hoJRom*0gg%&kfj~QF zUyuXs=Zir5V#FZq3-AYsCGSu>idW1}4qona!!CdqPv6hMi^XJC88`Jm{VaHyUjQ%j z19-V3SYMsyGugpy4qkHi0lehycLpy%4chAjFN<>Ua&7BOdh723v9a9V&LqpcK~g`l z%4CRTD|zn32@W=z{*|f-6FmHcI*H;iP&h_Y_v#hUVI>UKDz|EV;!Dvhw|mL!=c#I- zjkF_!;3INFCK~VSL|#!A}j4Rgv(9hk_29WRTPR#r|w|Kdja~VGDY>XHH((-=7EF%&%wn z=bNWf1{^L(MEa}yPGIqZg$fYog3m0_0)A=u%QiarbBHs!YKkEI)%P`nE;5%*=|6bj z{1B>nzBKUV8gk)c@zbkSItP#UH0f(LYvRfGyEtfFpf(+G^}TgKN(G3Y;D22x-f^y=5!T0kYI8hOwA#M9A1@t`QPE#y z={0|!*VWfGkdhZ~F;enNx>!H<;f2Nl{7C%`*iYnOvl)f7+&)Ukp@_6#*6H$n`0F2{4V6~Rs$9M|!U zQvb#*21Ayct_#P2|0l?D z@$b4B!!Ka!9C!K+-%Wjbbo?K=j`+`UnyExa&No_HJo=!;oMWygzHDr%&jY=foDr`Z zW+bwhWrmN(@QLiMWGyt9s^E{rSCKu^8ukH>{O8p9RV8A2uQOgP0LiFXzht3DvVDp=ja1 z#y~PhY6WRyZ`#oBkl=S$`^E8hZRS-ov(=^lH&uDc?pyuWX6Um|7tF=Ee97kGFn#G8 z*{JJCc7Xf!6IAaa9`~Ru@F4lufBAlfHL$Y3;k~9f$K-fy<(iMjB2B z*23Z^s5qgfdt}D&r&GZe)Zk&kp(?nN2d+%!7P~C!^%|kApc}8gP4U0*An5fU?6P3O zBMomk=&(WFq2mAKLD0Gwy-uBZuAq36iiFz*XYmr z`jgNf^R~ZOSEuqPKaF`$`a@`)d{2pz%m`OPTjzsU_++`N9icy8(VqkLr$2vOSH-N< zschygKSaX=-rT%^?& zK64$DpApq{-*CB?>bVz!zVc;RJSy79Rvt^_`_cc zL4V-P<9E3_L~b!g*)jC5zwQRP-TNk;&C?4*&?hHK5F~bElJdxTtET_s-w2*UxX+`n zD`>>f*Lmhwk>(~T(}VfReA`M0Y>lcl9P%N@JyDgcu{VNHH=T<3r0G2D zU#1^`D7^Elg6Vwzn%s2etX=c;?)L|G@e(Z0P3N=gztnX8o>=iP)_=V!oKBf@bqu|L z-gKdNm%Tw}L*rYiJHam>&lbIdr`lwmB}VK10E}e%pV$3#9zr8FonJTTT>3W)UOhJ~G zI)6{R%6XId+oct-{l?}HQ|$4}f>rA|KeuWHTQg+k z_DOcZ6nR#zqxDOz+CxpYY8$TzSFH+o>KK~*MK`N%z8Hx{iN z3V26QC()3B_o*-zOsM~Jl~#N`hh0M=eE^7_Ya{LlKVXy)Ni*P!`_hPoQy4@&&1IiW z;asl&dBI$+y7IH;vQMnbT;{RvU)O!9xx8kP&E*g0g>xzQw~nD>=}ng%;E9p!G?!0a zW^?Im1q;~Xs{oQr%l+NYWyfp5T=oJ2HJ7KT^oLB7qx;OC!SRwO6PNd4o*EBdkyLS5Be-eME&) zvnQ*+)x4V=^w+cgZYt{U1tT9cp@q&isF?9$W8fFCM^N&^=6LF$c*vwbyw*rdS{9*OnBh1s>MFBKYyHePaa$LqYBbut!n|2IHYJ2dmIr9`xW&G%+&MAqd=9Jz7t}_j@X)&6bT7nx){*x{C$z~;+r9<{Tck=Z@wEodZv;!BE zZT?qsA8h9-gHAN_K@8`pqOW0+^{jtAUju15^O~*xpMRpE6A8VSTnl zJ8*R(n6Ji{GA}9rr~?K3wQTKpDJKYnBe&BMcA4ojn!R+|T1?kA#nNe2f@Dmt`KEu( zGV0W?EfuX+Q%De}2I^Y)HAPP@%N|**|KCYA*907xWplN5lFOtf^QZ9;9rt3j`*{K7 zDrV~}dYNpDD4v)Bx>ldjL+Qt$%QQj*X>)6Bvx}wN?tcpL+*-Tb-LCZC;uZrvR8)eq z0$9xLHwj3h&p|wqrNw8ze^PS_<+%}rRPO(p+w3C%)pGx3Oq;oA_Mg)Q0kZVb6SJpF z7v&bhAN(uffyCl0$1+MF?N5fE3|7;>fS2|{oloqh>WMwonUAm1B+YO4kJPu-D)#yF zSNaEVtM||G-gc7vQ@o$*-(bD>7e2-Z%EcAO6R?(}LRpUp3}tn2TUE`98^k5-(U=S7S)Yapjr(Oem#^+SQL=`$kc*%GEjZP7}dg-e%*qq;-Jq%<+ zM_S1~fyEo}CS`s9cgzfoC2WVXM`nFS=+5R5-xCz7S7l-JD*T@fx5 z((2;P@>1Z-cIQ#SKYVmJwAjTPw%+S`zdR+(LVQEs($*W+jfJ=;6Y)9G^!N%=Z?&4K z2R?`ufpfzry=D!P^RRh0JY3-2aNYTNQ@haMa@L&C+^*2Oq2?Z_D}GVvD3>iZ`DVD|I2BuPj3^Y>b`5Vhuh!jw_0$ zjt;JSzxYSVe@9>7yHwMQrR=S>0&mzp8wF$iPvG(1e|6lk?AXt8r* zxS;pt7j(N@(2s0EpY~eb#^nF$!Ub*3n@-~cO!2qz0miOpQ7hxOMP<<~)~3Jw99bJa z5Ml2Z>Bhbyr7IA!XyA12zuhDkh0~_{_G-iCWKr;g} zYqTVc%?6u1Dw;f}6x;QWB!vh8{Xt8}VVgj0K(yoG*s#qO3=;3)$aQ9^BP;e7g&iUd z-=(lEzD{z_=SJ!Lf>LccD7i>Y$^{T8k*nl1`vfs{>(^Em;OUQ_5uMEM$#8Jys)5ny zgmQoNv^*rsX!MV>LnzJ}jdHHoPV%q7UxR*i-i_LA!&~HA_V4%CkQEeelrINvl&|4N z`H!=;lxyQvui!@cO6<7l?XwS8s=CGxB-{ef*nb*O~%b7nTzlr>2 ze$R!iX=t~I5hP}dAhe=6T;m)q-%oBZL9I6^%6W5KsD^|avSUMe#raoi7ZjM6azqXU|LGu_CkS10t&RDTv2}4lfB&I}m?@`IYitTzfTd zJ8F?h5;#>HO${7i0Q5I^WB=TKPU+S)Fj>_g|=X`U3@vV%06+rsrQs*bZ}lKl|+Q;3%ib1eQ+pekIQ ztX-Xrkk2j5p;)gMmP7Hl+P1nAq+OXi1Y*6~JFd2!U;r1wf+L@Ijt6jp)|$^o;jmE6Ni`;@jIIMFAyQ%m2c-!T1cG# zacPLwiiopP0~&EIh!CJ75m;2YXD>X%K=Qr3?;(LqB8&DKNTu}gIuz^SpEXWYc0N^V z19O1JC#6=NT9VudnMLGvWcC!LQ4Eza4XVnVCSYWp{=r@6D6U@Q(nPzPBAVN+J|>zv zL+usoACw+AaEACJqZR#?6ATPhA^lb7hQl_sd;bRdJNHbsoN1B}LF{qT zd4X6lvyagJZmfs*FyJCFoBlaQuHtdgwAz5Cb!49Ajb=9^O_t~txlSQhz+>u+m4zON zCSH&PRw-t|HzBOR~55T%IGE3f~vMz8Qcv<1uIFKE(j2BgLQ5K7Ie zH~=?fUn<(~(d4EuAOJSv#NNgi;v2;wI3$|H4FV3bxTz6*wb8 zWD;$W23hhU`66I_X}bC4JpR98baU9dIC13UPcQjytZK(Bc!Dhj(@#cXs8)7}QWHZw z3&t-JSPl|joui)r4Zw!6bx;C@)N`p)0#*almvAtTVCv{+Eh&h%)Kv%ZbZVDE*jCq# z%zihgzv@gsk##%M&((=zEtt;l&=nG3z{sb9=_HuJcl}8q4X)cDq4k+x7m?7_b*=CV zQ`?<$;djOgr9BWj^Ly#Z&ZV%Lxlncs5zks^r`xp}_ZSh+-9iRDyN}7|J7LWwxr~th zq8l3e)xeGLY0=DBMRj8Te7@+;{)D`)`)Wv2fv+=GXQHC1Irw5Jz5qR4a(W(>hV-=Y zq7a=H($nr-`A;zj#g+f#$igXHcXj3GEGX|>SaQ6`DaoV7eUv+VH|h}yu5}fi{R>a+ z;$K)tl^j8}n;bxzRbBh{ z5!B-mFY^TTNtBJKQ4JGlUKgz}in^~+RDoJCNsSTj>^hempe+|{=RjMQyno?-cE59y zI=-UX|KT_DfFPQ>V0s7yooMQ{+SZ?ik^T)dwY-R?cIVfB8|p>)j+|dV;dVZvW7_$R zR~TUxn303CoTmY4eQ>=<>-dUFJ<2@9pIo3FhrJ{V7kC){7bQXu!yG*o)D#d@yWJT@ zy|}ad_d=okSM1M!i13+AybI*NKP&rsxk-SL#w*cMn-usmv^BtCG4`AF2odn{_TN3f9LQz zB>^!tfBtAM)+?5*jCKI%G*`))&T=oc7cigLJD#3zj)o)Xg7G(@f8qWTfz7{g&8$ph z;W(nVnkI-!ujJhee|U`c)s$k_LYM}|=v)gw<`{r6mdmy9ZLU!jczJcp8h;Y_-k-pq z>{qgoW#Vun;-$v;^}F)Ovn^X!!TIIZ@ci-wjwvhs3wW(FkyxAX+zyDlJgkIfiruRY zv-htkt;aAfCDT81e!&Td1P<)l0Gz>6&Vct#rnf zJ&ualiML_pPTgip29ap?r!!oRaoYUvW0DyLeyVTvV#nR179$O(&|FQbU;TED9_<{j z?m&_SCWt9(vC!d}rj^ueUE8w`J^Q>e;t!T)hl`$~2Okl+-7Cef3D0kJJ|$x8m1SQ?<)u0EY$XFrUX{b5|uq%jYN|9wl-lN{B}bl@RNS zln`4eff8Z|`pLmy+jx2&I_Hke!akbi$z)o~FsIu=3V9dB~Q7X;3P99RkM|F*uEOe`?qR$4g4x(GYk@Ld)qa{IW_6+P?ra?Zu$%CdVH zJ72*6rYEs#KFj6VGC1d{+s9Q>3;*p&tk$>@+0r~dOiyCjRDOypF9TaIy-KzH{pT`s z_47)5L>lBmAi~A)ISjHHNXMClbeXGGZq?!|qg4+_8aA=Aq=zoSIRY;%Zu0$$VtN9u z!XdkA-E16pQ0Fia`TWl)QC;k@#0MF92cVa?v$tqf?~25`*=y!t=(#x?E$II}>VdzO zMUSRpYVE9AQ>{wq9}-PImMf3Y!}mXobM_Ri ziX=Guz+4aegQ~TWhW8=X8eZd}d_D6jcXT_q(N`31^xxV|?eZL)FP*`(3eGJ@PcfWd z6}~$iJ*8tJO78O$^c z<*g{dewny!4Y$uzW(2@?cYtG&T^UfNJTi9$V~v1Vjmd(rn*kWmg2j9V01RL_j!j$0 zX+K++gP9v}UKEkDmj+Oe@-hl`GnhK75D`ZjE~hlsG=iIG3hjhWD+!PTuI6_o0SZCF zYOubwgfqubUSLh^)ls~%c(#YAjDQS4Hy}Ga2V}PXdHBk%v-K^4ufKMMulXzdi!Lhw zu6>K;=g)yJwpNx}`_F;i_@hluXqF7>JgB;L;)!2@@yvxQTgz&=WVQ(eaSjysM$ z7Zc<#Sk7r&N7K~+KoC&o9yOUgxIkVYAkG+`!O27#E3B%EpHpVn_?lexQE}wxrFilIfBnfNoagzVAvF$n^7rg9`TbP`PM`DhSXJ|^Uz*lIb`0e% z4&fHK!t6pZN?SNL`cEn|(sI)g|9m@LO3hyyPaT7gk(iH>$Sc`FiVxI}CqfDEN033q zUoigYBC6<6nOEYEE(*dgeE;jk{Lwr@FQ6PrEt_HA<2X!g5`0E-fN4!qn6YtOu;fCZ zv}0Uprj%yg{s>tDFnUw=NQcwAQU&!4N+Y1GA%ZK4On{V~HL}AWsjVkd5UB<;zum@o z9q=}1Ulcc(s^QZvb4t~k#8DW%_+W+tUd{0fS6c_)pAN`%a5kw()W?~*Pu(N2)By_X z6-P&F`J1=aVZyW}yJx|Ai<{-0x{2j40V}J^!B?~VIk)r1CNBd=8cg01hkpXoF|FL_ z4XAF0;#T1Grn$qU-pyU4!EQ0GZ{sHCx9N<1O_uoYaB-wdKg7@- z(=g28Jxq2+h?5+mTiC<9{-c0Bd{~@eWxyoDAClerbz8VAOZ*pgVRjy32iM&5QOBAB ze(?0uy!tmv;VG^2#6h3vEaQ^%+t<}@WFeSGhJeI3oV4eU)t%|JZ0{BQ`>p@&{wb`L zw>r4nl_{EiQWS;OzK2OZYxUCX0>vL0SAsI)f@r#TE7u&R9!*Bt5@>>70rJ&rnAK7( zp*hz1JC^Mb#*?vRwwF*}8bhJ}U=K||%M=D)%+Jamhz`e6N5|3=AeZY%DP&NDo+a(^ zA#teWm>8AAcV6lWM4E@CeA{roKm>Be$yE&Fju=r$#Hz!xG$=Gr)Peq3q>A!*^5JZ$ zgReO7@rL%qC{C%!FTe&PzR8@U_gqzmXl7 z>kr|eqNcuIuOl>C?Ub(s8sw#hzyU#jjh-4YJrVn)#QOkgr14}{Sv($9EnY|gK2>=y zbrQ&tA>N;OKUQ^gf;H*ub)3S3_q4>Chv63(iNk*x(dyFDcybi`KaQkAcoauxTaAJ3 z8BdL>$lR^#VmqO{bx;9($$l35$2No7IEHxF2C2w3*!i;m`m4a`p zZ>|O{EQqD2ugo503|d}4DIudD>;l_t9z%!RA!MvlGb$cw*q?T4QhiO(uo88LNzh<8 zCcr?EOGJ@JBS(}$l}nw$U#@)?J1=jnvmF@78_l{&Pwp?`txh7Qh@jf;0^2p=mtn@M3BRmUd>k=CA*oe>9IU3CN!5du z!ZI^+SY{enrj~_uHjKEM6ryOoa47m+^-CyP3}jvykysJ1oq;eSDP#sLsgpuxI4R_| zax1s2(t0%~kV5{ElS2GZ3V9yJHkglU<^x;zbAtIeP|Q(|J9}MH$P3}S{=5V60CQ5x zOC%_kLHdBcjf4a;$Se9>I=k;olsT&hJ;Sk=zL#}DY1_A6#iyhM&Lc_Xp7 zK;BqN#pQv#fe?%eJ6XHDle`g24$I3LizRD#>8TXn%ddw|LQB8c&}S`3+E{*<`a06^ zI^!dC_5_3tzPNzA$Ej0b+b5JcbFV!8kETxvrJrUZ^5)IuRLVT87R14Ctt zq)!RtjcKmD(P`(5>Yu1tbMnR+ntYjMTDLR{=;Uo8(s3puEe0iEd*W5EMjD>CZM~)> zTJ_IJ!(-e8`X!e|yw*6uadbr_uuwh_k~S=Xys@1AK~Gs6`2D`{V-i3*$yeeJw-n1C z>WV*J^je4zJVs35+g*ZzS2$TL3-}U*O@A`7U5-}8dnDeY zmJRkb@P`K4xF4U+Ji}d~@R6j~IW0rI-Pm@oHt_x`=8(4C|7CF`CvH3JkldkG{a(BjLh4Sm_ztDTG?6C)61PtUJCQ-4IWWQEtw_UI zHHX?s?paJRPY&fttmmd*gb^5$K`~>nu9)7Z`E?nFdUXUmDR9^#N z=|nF-4_>~sJYmb2(|2XRReaCpUYZ?cn5r8rWN>mV6A&`ILUo4oV0Ta2DzJmktI`F_ zj&7hCMk;YwW>18RP#+97mtLzvpanJ;??KsU)dP`+EymJEv}HU|4!D#Z@EOJORSJ*j z7gS`liB67P$;>$>mY!V_Oop*5!$bZgmi*YY6YwikFW^^zS*IpQ!mzxmc8ldXyc}}; zitWGDrEIGV2e=j&5V&ppKiD}FuFLQbr!vqEjwS^ z7F+rE$(loVW5dzJrYIX}x)!|SUsi5Mp5)W%OKn)?OIGrKHK}j<#(Ta2u8;= z&SuLY#Hf60kq;P{Q;4J+g}kDvc|0-obR1p{&zYG#CAU;8bw(3*@bLIvav~5Q-ja=l zV$}r1>=7}OUm!&F9eYF;S?uxj{2Ruld!N`;yV%03(QTp0+L55LmKevt0Y@3ReMsbX zf9DrD`JeHhP7OAXVOn_PAVu!;}wALWUnx=lEF}Nctfr>0EL&Z?-{Z;G(C5@0RI_!WkCzB`-`oARKXV3=zNndJZ9VJ$ z$+M0A-*}dNTwpCDbpIA^x7IFpekIHOpKvRSqHEU*ehW4V77DoYbZnU&1xJ{-Px|Vf z{=xf6iGYY#yBvNT4S!-W0iWTC5=|^`d$gmKl$`!=s!)W8X_Mn%#vDC&Tf74hBHB!1 zk{y3$zal9ZFHjc7KkqcL6PK*!UO?^t5BGGq-S=O$4cX*x;-a9}oB!kvP?nyY-;|x@ z#VO{7C4U7ZlG6J|Fg$<8zV>mt-$b`ruKA0ZMqC&waADv`V%NAFP7u80z|hKh1M(@b zczzk@^_SIh_I^$6N<#jRD-VNj)%I9dyA+ovP{gbLM+eevNxGqX!~EsJo6Wp2A}lY5 zaZuI*4+mMSY3{JY=zMPR@AYu#?{N%`ZDqDHR`u500~7+gza?)`=x^UV3z)L(u9l2r z+g5UMU^I(1%{St9i|qiH+Tmwh;~Z1F@~sOaPoa6t`#EF>=j7eMzhS0SQ91vHSe1`| z!`b5JY|Nef8^#p)H&8TjRJ`gU^KW=L((pU*n4BA^$F#oWpM8v3OD@f%co9TuqV-3Z zT(foD6+~ff3|TY>-5-skB5GG^jSZQiV9#dh_z#(AoFYrd1Bxsiac&qAT4nT?QGaGQ z0tgfM`B@cqJt}_!ADUu(R2!bc7n)+^13f3OT$LTwdaR043iM$$D0n9gX73kTWjQ1u7t**AhjI!ncsJm#Z@}n%{hJ=J)3bG^BrIudyaJA+?uwby*EP=P3KV!%MYWE_ zJkKTN@@K1GjW7#1MeMHh6V+sR!sOfnNpsLQXyjIuz`=3fTksZWjUZ9!TT9skvD9D7 zgcNWpFup0#=0CA7Alk@SuO^slM6GO8H<{5?HVF9Zk=g7>*1_}wC3~*X7g# zklyT@`3i4*?_d)P10dx^WYNb=O{Bhu>ID;oJ>nObAi7(xdGIR=x-6k?$yT1)SwB27#|9W^&Yz}PqTeE%q z2?sF)RS)1N?lb(^0|KAqBfgf~x`OR!<2q%vYn479n9ClGM8@^(zIKNwxIHk<)V8^^90*9>GwimEl2KcY=5AnvK*$f2$Mj)Map8Z`JMZ^u1@oxNpL&KbCyQ$Jh(a z!n!HEPP~GOVGOks55qIf$n#8VL`m3Ye#>$v9$s;LUOeoiuc?2-vjewtAsNrrT`Uo} z*r^70nvLG@_UP&yJtlF_u=|CEW5b#a4RiB4aCm>-XbhSgy|VxflUq0g8ipj7#nPuC ze7&2kGQm3e0!NdXn>8p-^s3&Qi?_m-z+5ludx?XT-?@6{v`;rpGE8r3ev zz_~G8bh7&w>Hp|etg1aRK3X-W6vHAgp*x~b&|kz&jPGBmp(k^mmZQf%&`gJp9_G`I zXHI+eK65^4&)yOAF@}*B{eho3R7lI$)vkaX%!Af)(x0AJRg!P@j)`)_x3g=hkx>_N&g3qUnSz!VT5A>4Zc62-x%CjOt7_lXBp>eRUtN)ZL? zl!7d$Pd4)>g=CDBjsuGf#+ljj#8_IIKsg>wo?4E|t}>dOh*#Cibq9uK(?sZU_L2!s zR(0_Fnk7wt&Hu@vpI|$8uvFyetJ_#|Y)7R^ZG1VA7Ad$ip1#oRKb*$!=>FOzQh2tZ zC2v<>#782=mGjYZe(mF0bf>S!q^76TR2cM@`Tk%b_=)%u^<#H|w(P6lbYJCbiJ!BG z<)UC_6;p)IwRqcqh9-xJc}7Py3QsnhVQ#H^xnP)fPMdh#{M*CK@c(lNkZ>RJhTr-l zd5w4YZy&&pKlw(H#WnseKX&BtTch>c>K{ojMLN?MTpU#4z~%(r6&-hUqMz5k(Zqmc zTY^=Nhv~Kqxv?%N%MJ+7XY1EOq~E9;6;B;sp*U)wnQe8MoPLnhN;&%ep?{7}xawP> z@7ofuWFh0&^`vH2!}xg2{R(9bZJ64JFQ&(d)HIXgqkdg=?6|~=NJFhX55k0R^`F>7 zyxT20$%v&cE-@c8sk+e7brQ8$Qp9d3J*;Go%p+s{FC&o*!d|Q+KI}D@?@vHQiba^i z&7pJ*?$|6{(FbA-Bl#4I7%)}?hrLctjly(sYaM1(^EyY0kln`y8?iG>ujp$8hJq3C1D)KkW!jRO8**o+-2j6G*6*+HVN*6Qd&HOH1 zSG%0KIuD`win6U{rJ#eX_QZZ(+L=D5YK*c+N_#@rGYf$OwTCi&CH??9X~8Vg&U84D znadiZ+G^g*ORgW69(ZEY$z|DElMmrBINM0H>5w5(f1~)7;Gn^U75jT1>BTq=Ox9Go zxMG(RN9c-jNNAfFQ55t5uZ|mz944AReHq#qmXw;}y|@W%hf zUWU|ccT~L{StR5isqd>wDdy`7lK#j!+Z~ws_eCH1 zTxoAgnJB+S1(W^}bI|w7bGzMk_p_jSzr;oUf7|OU_!v|oyTr;M}6qm zK>xvhjx^jWqb8TJ-v2Q#GPmi$wQGgd3nVIk-4T$IT|%~Ev47@Jq&?c#*_|+~{{Ysi zB2|Nq=tMA#-#GI$#S4?YssBckQ6Jm0TYW@BAawK{Q_$k1hnAX_W|Lp?0|j5Ocqji% zx_Bq6zFxq;Se#D(x4VNG(tS=-UDNUrr@?%qiU?MY-!c2d`Zs1oNr;>LByu}P#p(Hj zrNk5Ms@oNn5`runn_NzB`J?e~iY8m+0UXCU56$BE3PT~E9VQFStxl2JL-o+(oN~9j zFj>fOd0b(Bzva>Ua+-^~bK+w1k`*#xh0R!9kV#Zt&Xdyn3^CnBlt4bp*nM)x$mVF{ z`p6PANl%4IyKgP)iZp(4Xc5u~U$*xj=zx}Y%J(}R3_yxEPed3_%z7vms2QoW}HIp=skPjNRIPe``NQ|?!V!qPWUp4 z4Qk#USl2mkV0RNZ1G}3t;0b7G>FrgmPwXVV#_nowy%p?eAuwCw4XrSoC;aa?=&6E* zmBv%wDhZUb#b-{TM{t3Ho|y;~^u|LttyFB-cEVY$kp>ECy3&&x>YJuS8n!0$7pBvH z+@Ku~V8AOJye50mjhr*h-qS%`qn38wNjbVTIlly%6(W{Z??tY&5L3yGf$}NR;L&_6 zxlud@%BLqR0m07boI-7kuPFEH_Q->cF!+q&A;=V9a5R+v$$|wFQy7I0GgEBYwCwqy|8QI5|0RV?1@NPOKXC zfaYpN#VyGMLN=*cXP%a)C-LM*Vfm~!QR-YfIw|uGm`XDD=jt|fvPZ_#S?5dn#kA0e z!D13YTXl#R#r~>4eq#?fKxT_&E&kS19_ba{}peJr!N}} zcNI%65kZJ0Wny?nQ?{&-{z*Hhwze@Z7>hI4k=v`~LbnHpD`j3)yt!_l%w}GO_G-pI z>3O8_K^|lO%CU#OIj20^7ylIEMIl+MAH5NX$`fDr>gPB2sQc;2W}|=fH`b@eu><=i zJTxydhkG-l-sSi+m5ww_=Ml8C+5i5YQuv?IgaOZjSjr6~SWk6(tOk|>g{G#Xqr|lk zGlA@+SaSD`EJQTHe>poUSX!IZNaG)L#v8ZSTX|jBN&$ZmPohYZ!%Xju zGCfQ74ev-$4wJPwvl}gdHnW5HlZT}k!UdYe;w=+KT-#Zu@y9s6!5#Inyk-&QGsij~ z=Z%dY}iBD!{b%!=k$psAIf6U(H83u3*eVaOJUIg@CbcE79HHwY**u6|Gt-(n((x3&5r>2(0Q?=!m`-6F41~Kh8rNmBcCPmXH>69G(>T32|;sV&q zQVX}5L}5LbOO6YBuXp@Qq~RDly|1>qkwwo5R6EwkhP7w*Z-(%s zIMiWCuVDa7XxwPSBc2!BSk<$2M`rpM3|6a`#XWqUISP9ye~YSTBaIscHB}ELz9VRs z!m~|_oxER;2Yuw+Ulyx+7M(0HwFZ01r-R2tE=ZgcR|v3WYO|wlr+vld1>~8`f(YP99@t64+ zMEXBHvrVX#XYFnh<>PjUY>`=5B!&G+M6;*p{YiF+sJNZwbw>n?*q%Ks1U#*0r13C1 zmRUoq4jQd~|Lktzor1fMf-p}6XKm@E+V^jR59*e`GoCOzc(It!Hh4^_O2GKhSn4?R zB_jk#LptkA>V{Y>KJ`1w=YAXEtTeLdV3v!k{*mkYz-oBO4}p#o2_oG4Snr9pC_^9F;@$h* z!^dPxUf;9~>iDQPQUvk{J=YzO)#7v4#@#w^WP9eXFab1J9a(gqU_Ny!tjk0;@aZQK zX?XWzz10VgeCVfVx81Ua3hmKed!C#gMP#I>qP@;4iNdY+Tp#TfJ8^S7b@qwd<2_Nz ze-ck0KLE>N9v|;}E$aqGTh@Iw+R{=LZD}3owXFGSyeHY@9`jmSt71JjM0-BuwX_V2 z^<3li{5aP0V~_iuPk1f&4~zDECx*eoou^hWKH|9Vz4&uJ|IGi#-kZQzRh|3aIYLN4 z@B|B*S}Q@LhB|?YB?^)dBKyFJVsXGKN>z|LqMQR*M50NQbC0K`w|X!4T3dP@N?UKG zR%sm2gdqty1)NZ;;JlB=N<=%;LyIk|Ihur|Cf*E>|w37*YK=oJ@XR^ zJPY>P916S=hL&vp;F$1;*LV(nfTTk7Bm*PE=6%h{SA{ql=WJj4*i|e4^?^|EzJg3k zAto(&UwCX6qN76RF@JnKi;QKfv^v8GGuk>h)OhxcUrla(F|Puwz-ENO?T=Mzao^{Scn3?uEk^(!(-b|P4qrC zoakS!g>Y*|Y^(|1_e2;S)`+Lk1sxL_@u41ICrnJkV`@e`#a&8k&=d;noR~PUI2=eZ z*GI5C;Q(>0H?jbOY648)OKN>3+tkd$$R02j*g7J6dMvaepuwdPO>wKsyt~`PY70{Jb%Rr^PQGQxpzt zcAA@5{I*H)@R;FH6OEw&dab7YSTDpcE&S{VvwC1#l_(Qr#o9xGj9};r8!xzXsQW(9146~ z6L>Gwy!wbx^V%b70vnxPHI3oGhoP9-VO<&f(=~y2WPBVhU&v{26c{Xw7VU9=vFOB$ zAs#fp2lQ>yog#(-i_VA_%ovPW1@C|ie|C7zIwXOanh_sr1T}UUy}NJ>vkW!2!8C^^ zaKuKgo^g0!wywR)2By|5=9=Bx`t|Udao=jZR~F=YYmY46qWk_!-H{ zxf-E)c5hf0zy= zid%O%MPHQ@0+yBR^gHSFYM$ zUkO$vp>y5-AMP}kgPb>bK4Ge9I@4!wQLUIVA9bUSri(CBe+tFp5$ZE=UD-l_PVEp0 zFfw^3H6>w8t$Us~nS3SwWI!MhP-I?V=P8AO=wMV=2$~$&fK!WtMX&?|`=riAL1MHK z#Ejl=-T)`DpfASprHiWyQzMO@x9)S~uTL@(EE?!t5a~$3J-I`f=;g~>j4u#|-j~4@ zUj&&aBk#4czkQUEneY@b+v3q%iQ2bS@;$kY86NcEdLIQlaj8*B99>W}RU z3fncqQb+KpV@}xbhm^M4+y}O)Csh>J#9dZKH^4$`=moQ6W|;uk*|V2Cn4STXZa=KO z-F*I_z^TL?Ls`2Q6uWoUY9+{DeqavFS$GA)G!9dAlsliIomI@N9fP9pERfz!Zr11V zZnyPee*vO^K&7!(^F$@z=1{|0_Y>wg&wc9y#uGou!D-qEN(Pzk%*mFM97^t&St?_d z)3)6Ei`XiyRfca(uI9)Wc>5tq$8&0u@jaamg-cIbVjg?JNWJSESxFmApNaqN#J|-; zJn}bE&JcWs05ntdIcZ*C2X+^Ztk$Dp?M{Z90dR(L7RzF--3fHb*kBK)5>DD;4J?(8 z|1Il96D}=vII+*JIhft<$v0#eVHku?Nm2V++OiW`Cf+L?%fxoRN1%+cOzLDwl+yY{ zYY(bXrtLw^%|C7rnj7EC#CN7=?LL1jdr*C$XMATbvKRKC27$WIB6;=jGqh|DdOpOU z=U``5v4zMo_nn0XVR|sQS$75;*YwcOVc+6wc&}&K<`%o>eFD!Dg9@lZuz4zMx;2yk z8nNbjBi3y5#hUA_NR!#m5ozM_`e;UuDf|5DcC0(vvgDY*hU&%Wp|2O5|5GE!44K&c z>xs=@17+EFjj?%qvsXqS<=ebHyPq$V$}yAAgy#p5PispJf-5DQ^A`?^N64iX*>FsK3R736H{RDEIaz2kf5Z89X+|t)m&;~+8$oFhCegG_5E`wQ=ZYu)Mtm{$9|EV}0Mgihp9O0x0o!+9h z8`Fa4p`2*$jeqL#z7IuFG zj#!305qT}u!=8PoCvWtY=m{Eu6cO_dp@qEh3CSD#7;z&iY018111vwXn#Rb5ibq%+ zK52e&^n8g@IPhzhb8=_&`}hZQz~K*15{dZ2<6+LlI(-gME0JeX z=!i#eW*DK^OUV&XU$ll{buWIXze0o#GClRkir^F*!Mh8`N>BhVL7;)`FS<1O5uj>i zd^^lQf(^&fUh*X#b5^BR0ICLG(DtXSdc1 zN?Z%wV5}b+QBW3-cm)txZr9_?CgRl-&?G+A6qk+zfj}WT_e%9(kTdi%r+j;4WO4;> ze0V8e@5#4JKWv;{?|}W#$hWo!8)_*ZE^m&GGl^zKV@nbFp67(si17sBPTY&T3q;|r zK%&$nkzq~jb#ICH8qp-tQd6pr>;pzLNz!<0^YG^2$|uYz5UhR)8a!A(j?VDSEAFkZOtdeBQr~a)5qd^%P9DZ|NF?^56|i{%GTrqQkmZE0yamV6 z-RM#B8(R6;K1)OqFONbm!1fW)<~7+p5x-JO#b54E;9CHYQtt`6L*bLJ7_EbM>GKgNO zeNueqGO%PITpxgG;0ZV{ff`m z;-ooF|jxu`PfAme!UgB z8Z%`kv1bY@mVfI%wEU~mRBm=!5)29=rPj&j*rd2TSs@ATNCA`aurWD;Y`{0t{&*fX zA1i7-u?%{94mOR!df{jyff)e4OY2KOaSdukuD;F>KqH)FEWG7nGuC7$8Dvw5bwq}n z=S?cH`s8?C zYWY4Ej_Qa&p)k#fIYl5?bsV(;FhCj(6bPCDeKfnA6-Q*K%R$kWY+2g?$80&G^;+hW9mzn(kD&e_s6aSD(sMMb%HeqnMNKrUCW*h@9TUN_pNFM8n=jF4L@TCBGwX%{@i!K;5m!o#+L zuQ4vz3*HsKh|ipdvB%awB;f7JnW_`LjDr?Uat$$wyacN05Cp-O;e)ZpV6xg%(ESq= zgIuzyc1?^O&+qXZ>@9^N&W61ktiK&l!nvo*xuJV0m)Fb<1u(bUTr&();I5KuE+G+M zFNf$Gux53ye~vy)K$;gGwmP%}TaFE(9WPHz^rpq8j_MJwWaN9}f<@zB*~;JWD;?v4 z1N(30&-l$9p}IAAy}TUV8ZLh(3iI`5>L8Ss;&0+rUCbB4$#MLy?jnX&G(}3*P;9?Y zY%bGyDzcY7CQ!ZbQX_TC%Bi}>J$e!eRQtZ0MS}NSFK18mO6%+YKfNOU)TBQB=h7>q zKl;Y>%IPoue~w=H)d!g~%%@j=8t~7te;&QE-wV0)$|;xp-%YP{CjZaVEBC*jS!>ZN z_jGUX7Oje0@6)l4UF*94J@m@6uBPal(JMPH{{QI}k6-)WO0NvsnxR*uoD{v1*ZrxX zS9&{bYWs9>6|Buyw!vqxSv4UyI(cju# z|7v7i6q;@exy6*pH2wPvvuo&lh72j5mV}wWv@CsI;~yzAgU9EK$)K10o!BF_T)UT2 zpHKml=qFS5VOzGzFZ+QlYy9+E>-3W;`%_zXsb6-xEh}XZ z?dm5}_Ci~BwqLf>mNiiVTI=+aDSLt~>-c3qvt>u=r?pN$nX>&T%N&*H9rNBJ-e)-e zeb=3?(`5%Ek9JV9$hM-NOexU&D zT})lc(Is;~7*4Y$esX2!DJWmxFsXii%0@-k2|={mdypFSq=x ztn&T#)c%Cr@}siK_t{hV{WIlRnaFYS6YV0tENYL=$lrRJZAM?oksfcrG9(4dVb(ev zdqhj@t~(zfN<1RLzk3c_2T*9_TKvl_z@W*joWOv{Zj-Xt|L_0)MF0Ex0N+>JZZ+TM zJIlCE4a#m`^IgVEi6uw+#>k!k{>`kBS^+%Cwz359Td^5QJ;q3v&@B5#Kl*2J&8BJk zG^FO#KJjFY?>3p#6$W`-QgsGQa(< z^Zv2^ulSptFN}3stBN!2FQ+||LEHHqtqFM5iNFM9oE_YC!BQ`Y$@e>=WWn1?9E zG{RJWi0` z^2za~d=oR+>quz{x_2IQ8LlU{ZO)r*XDdrsk>xrh2 z>-Nj07k)x3nF%!QVPS1(hVGIKz2Ny57Gsi!a>^#gLM0lM7=<_*!fiQDdhOE*HW1)LF ziENb;fNq;m7Tl2Xl~5Mwr9J_-;8j!0-tqNPWF+#f586`SS_03GLaHM=-4FD2wiHqF z<2kgZyt+8*D%kBQUc4@JFst3)zbQ?S(f&V?I+D)LeMCVo9yV&EoG>KRM+ig7ptFWG8+)`{Yka2+@ zXMS;%DKD%*Re-p(!+7|f&U3vhOf8_52q|EmR^;%rs5($z;CG_e1mU1*3UlQ0!r*N< z5grfFoXY#Fd45V!3#3O&MKN7)=)yp<)0!RIUHpGe2n zW1pvS$0~~mwVcYYToI79)I^L=@nva`;K&myOnoa9>+6(%#$CL!5b0|ZJ_RUrC*onY z9gmgxSw-R44?s%i7mau&RDK+$VWHTdm&5V>!ZAWP>W$LM`~dA9FOi|YEO=um-1@)quV`L*n1HSyRaFc8vUavxktst}&k|C)ub z-xQt1><6gX69||{0RgKNyT<$~wsiSED2$r$;sz4%^VZT3cIg@V)WssRfM$;R2^fR* zFBr(O>)B5b7pxZjaP$T^fFu?u-7l1H1~j}r7}{IV#%g*!m5SN#mU;u%rW9GLAm{Y?q#@;FT`d#1 zK9V8i?xT}6@3#8i35LKI9@%Ky*dRn*EUs95b+H*QaQ*jg2$P>8v$@A)I`z#rmA1xL z_lYI`JI6>q&-4MK{g$!sHkmm?Os6?jb~yhva77`r}V!B*9w&%6sgjb zDGxx?Zt?m#FGE_{=*PrpToR6_PDC5 zMNhFgY7SkE^oG(*M~TtpLis8iR`1eu9;`?~NI9_d#HQ#v9Sc{Jq6j`3LsiJFnhkiib3sgncZm(A+|IFp3aO<}fEd zh5ar}1-Ao|RM1CVT#+JoNj9JUI+x*N<62e99G&7d} z8o`I`CU-3%Q#qlaZfYdfIOEF!Z(G-o0PZ-qxcneZ4rRy#sb@ zFOC1O_kxCb!cx&SO;|ZDQ{DPCEUUkKJK#V8-wq>fu6t0JCu z%sG{;8lk!;gU0XWUAJ@<8jn~NHJ-#D1xwC3ECr4slJWt*jYn%16**;N`P zmMqN#ZEkNXxs-{Z|G+MR!9odqvXw`-~}unabi$v)QPma6fF6VnYo|9hKRi zK!ZdYgTsmGZf6A?)dyg%F8A&lIHxx=oRiNiCU4cy^-d79(>VW8sFZstKXjR?cJC$?it_4^(Nut+mTdHXvhnRel}(J?%lzc`(oZb^<1h4Z%=4eC)xn*wQR|%N48GmY8~5xdz6#$0 zpXhV3=lk4X^a%uoDOFpuAE%2fs3{`PLFAh<*?9Ft%(H#7m1!{*)W;{IXN zl_5Fi^YY9m`0hKhTycWqc3`=({%LKcmQeW)45xND<*&^FlHYaj-yl?czSQr*`Z-vd zVIbCKBmGo2rb^T23nULV8KX>GaWfuew|s2j#AO39 z88yKlcey981`K3Y&!-4wC*wh3ieUXqW|4Xt5VnP5uYZkU_|xA!rTDyWDL?=Qgl9IT zMrHUD;k(r`+rxxK*UddlR|Xiiuk^V-UbbL|I%^}pmz#)goH>?BTZ5DgGq38e&e zphyVKCjN)$CK4z_<2YJEaX;fdTu>4%*Wq73hEr?Ard)a?xbpacl_y39!~UEu@(njm z!rLa311T$ea#OK4Hzb^rePa08f;`!lmQpzRz87Rb);8*w$;_JDzVP$o6?E7A!C%b& zbFg0o1eh4bYWL&dK{vL-bP~7yq$0^eu4rl@%v??EDnF>BafayzaL!yYfA6#{+J2lL z85=X>AtToofsNusWegVQ?{AG2Ii|=q@}123XRH>@tH=;Pz#Qf&&nKnJ$sG^QRi&PD z6?TjRj2$D$rr}9gXy3JJ@zWXf;9CXEf89qBIj&WYLWe580P$Zur>ZD+&7ZStzXfK5 zYGa3jt^PW9e*~EdpZa+V^Ikx=y!{!h`-~RM?0mz3as(tgrNn*fsZ1ZG&ECA#?_XM* z{Z%NejqHrM=;h^zi z$ub$i8@B^dlJTC&m(eccJ&X`-s1uVfL!nM=QiAQE6VhP>&t4xK*q3ctNUvt$WsPNX)qLqm z^>P03sxPnRBjchU<}sxLq1H;<`ML$OkfZpd*BToj?}>5+zayja$i7oLIE-4|ht_dE zCi1`67wVZncPuq8$LlUJ_|-M?JnMF!KhcEDOOgB!KZkDjZtla0i+2UDtxtrHdZ%Ah&$Xc0vCoS6exzKPCrR* zA1BJxr-u!X;;UOu%u=^dLHe*Tgka?b(~^%;D|^3b5X*UH^}CT4tJ^KZu@*7KC^x|? zt3ko@3MI=z?o&_Lwv3P_=liTm-V)Sq-?oc!C4XY_FH0V0zS3nc~Oj3pOG|!EP>>$o`vu{9BZzLwGoujEsF&5V%4`U4@3`W>4itx zVuC@N;0f7DWuV&@E83dk9>4^pty}{$L%}Osl*6sb8MZlc25HXoLytY>b(rWL@GnmX zZ~hD9W2pHZw6DaoxDV_eXqo8*uWXwcysElsX7KW6(}LI5<$ByK)6spCL^C5R+O{T> z40S9wL~>l3Y-UM?<8W{wBtsw2KmmnbA&cBW87x;-!Rs=DOAqJ$gkoNvJKWcd^3?e# zc-5q-{FyR~sC|pho~*y8RjBN6U0yIf)H-1{AIhUl)qFjgFdcZbVv-57)m}Dw3a&I7 zjBA3a;q`=IDAT&ciqkh_D*Gu@Ev$IpTOj!4}0A8ul^yCku2e1)PU@t$%0+HU@7l z=Ns_bjp1P(h*}7Z(6#PLVjULw+w*{(SJ}AjLz?Z?i<(+}r+}C2D@F z0BhrtP+*-rR8X}PO^lsUqWQ)MxHodjSAqkxrh7_-UYq%rk#I?IaA59y<0mpTSTtpp zc{`lH;gSmeo>4M+V(a)4Gt(>!(HW`CME^n)ttMyFQ0_$kVhOLtEk2`UemJnz$*<*3 z)4fh0wHbUEte?**#xzb_27(}X-O}LMZy9aiVhIA4S{*O- zERLdhZzGw5_RKOP-jg&jc{fyf#y_~cbq*THZg&kJlZ=>GS>W2=l(jhE0Vz)cDX;g0lsBYQKSMwjDt|6`^Iw@|cuS}G-2(T*Kgeb^+L-$O9*1@L zX1cvbOJP`y4g>^r(?ELiIGT~ls+!cPZx;Y>0>Qlm^MD|tK4KER9!fOSGFr9WtUpYU zH%Vr_yLsm=wGcsiKG10_3B_ty?}}P>c6BZ5G&O6*o#nh`#VeNT?NYtXTJs9Cwp#Pa zgbW%;no5vBO_Tnf*{;9SwuV}(%`#J_Vyhli0|gG#Sks}#vcSOUs$5)y8O}Q3zyS`> z^L`j?I9G6BV3(B_9GI1F^7+s7`ZF8;`ZIx%qqWAzoWx;FUe#sE-$1(Vp%rhsqnm80 z1(b?c-`eaJ5_y8Xwa{IAo7DU@A1#O2;GnTl(D}&jT#E8IKNxOK3!*x*;$0 zpoTK^i8;?ETX{S|XQFt#8VXl}NJ!jXsWUM1;BcCW1d;gY{UOog6Ejq9u z^+S^9m7vcclKL0>&D)1>rgN*Lj*~Q8xmD&YK)#+O={zz0U8+ggc@d=IWhL_QFbP%O za~szbh}J!YW2@*?&ZDBUCI<&j;r~e$P{hOe%=A!V?sRuHq$mERr_5grnQZ8V9C7H6 zp0~8@Is8J#cJ?B@S_%Pqi)6IX0o+GX|L$;q_naY8%iOJ_plc}g9t22{yNNr!{uf@S z$&cOW#p$A_#v|#NMOhK3`ynm;dipF%S-aUggj`|F7UJJPS_tHQy%@MjA+<3KgLVkljKkSzt7G(UY~!^oVUV>)D;% z?nV6ZR$T#_irl?OS)%oPcvH{yg!a#gk8`ZCCq76dt{1VXp(?;-GeY&249#9G{OC7k$V)5uaH zz$Qzv6dZ_dd|;q5KA|L5$^O2;ik@W%6gki#N0igBCfIN=w5a0R5;6LwW4V@kn5Nx{ z56Z%I5q4|ckzYe^w|g?y6{$mwe-!f7{-jQ!AH3?WK$5z!$qzAcIfsEwb8-P3Hrkok zYwlxaAVX#87eW-yFo$o?OmE0g{m{`_QX1mdCJ7rwfJ&Ug_812@6GR%C zJ(K7V&)u^mLTyWp^ynvgBKc{Dk)Lvn{M0(D8&mpD5;w{L-9Nv~DC5#3rNyVe(@`BS zfs(M1TEVOu;PO-v^OFuHTSqCatR$#ykuiQe+3Mv=c6@Z|5>I}kj^Kir?!?Iw_GHD2 zQoiGpLgnX`7Dw+glJ5j;ldRofgQCpu%kHI*Nx~VuDLIEXrthNA+{gwipJjC(cj$|I z<9}&GtwrTPRcCl87A~#eAb>FBJeXX#hLu9c??p?4_82+|?5wc_y#6Zd}q zv`q8R9DX)izUddSBF^11B@POny-8Be7gGCWvi8mYh;*~;K_;M_2(qVa7WTMN0d%tWi*~s-h4Lc?CE`3Wv%aKL z^yHh0f@k8~82Khjv*%O$dh$)8VEFP)JEetb8RvD7fD)=38K+V>9c+c1CJa%q{u1-L zM_R-qw8;+3+GIw4r%jf^*2_ej$k5wLm7$awy#mSo)fnf|s0Vs3c<|<@k%k8Ao-;yK zZ&&=ii$3r#85q@~=WqDC799)G-Gi0<&uQh3`?DqiBTBaCgpUYl61?##$n4}s{-m&S z#kO@#YKZ-nx^4=YKT;U?>A5*qj%Du%3r2sSIURqfj^H&m9qYTLUV;xow85x@)T)(y zDlzhpLyT1O-}{I;+TnKFN+|*ouhIQ8+`AJGx5W2i*;&-_{|UzM2AUMY!Z= zgDd;#(Cz2h?G(x|XNpc-cieO4ppEQf4p|x+It+<+0lozx8EG2&)X2!7N(i46JzYIm zXnSslQDSZ&Z}^WOC)-`3sA?4ML1q*ijqs=2EvMJCk(SN&)hOx@v((LB*V|D%aJLeH~enPs$=pCMs(i?{y)8We&Zm_&IyDPddSg&$UlB_AJtW$i~d6!|py<{|ra865lcFocErh!vLNPtweHU^6-_9 zSf9L(CpN!Ux9c7ud99MwMTpIJcqp-`%r&_mIwwH#zN$0}?pn&EHhIB8viO_-iTH%A zr -?C||OnkR>1gho&Xn3L#;6w9F)hQnUqQYnJ*tVhCGR8@iuV&ExIm$0=l*b%JK z!Y~;G(~)g0m>u&wM>Ji-3syTblu$F*90*P4^d;moF}6(RQiI+5khzplLW-dn>%ZD4 zk$R=oE0#w0_k*uLnCkO`Fm`_jKRDxi9zQr0esH>b7Pp=N{%eKx2Rveg^~1G&E5)8L zDo1K`2f->i+kdQkpEw6vPhrIqNUS-ScS8;FT^)PO}&_B7Hhd#&R z&j9r3*SI6k0~J*gdt(oK0q~rzMwd zw*IgF{J{ zQFCw?Bm%Fa+t@*6K;3Y66DMlzf|9%l5nG6=jhJV+kczjhgQ*dgKiaeY@ir>=&_6CH zWNT-OaIU6I&;HIc@}$Eu{bN6d64w{G<4N_YevYP+)vZO}qN|fx?a5}f&1OG{xAb9V#=g8 zdH$c7^0)cr-xBq2ycKQv<4yT2!19oQzyGbgJPR+9?I#`i+ym!JGNP~KTL%lIE6g6- z%(aIPH)P?%5@R10KL&cJ%w2o2HG8<%l-)*Xtms=B2&7kuzn}i>{*9RGtk6&?aVI0wFb{QVa5;p6X7;O`1| zU&cZ;T)-iFh_|?a1Nc&X6fI} z?pmIKKOnEb;$`lG+|qcl8vi+rqBgVX$9*Ux`grEk*&2qf z@8+(b6YDZGCn2yaipfS%*VH%dLFTWo)j!TpNBq zq~(jvSnR}Y9VH3DF82-h*55*KCkCH<-!^R77S=w5^{+XuagJzp5*{vx=J5@Jhlb2YfcMlIxFa8Q7djlv+SIyh4Dtojf5d99= z4`I9EX_i^#TlETz)MqS9onxXf$L9_=>R?o}3x6{qQ95?~V%{BN6~Zy8)N@pBzy240 z@>f``+l*zXT9zA~u=H*2LH868NPcU(TiLlb;3SCY8?2752(E1B_e^|fR;j0Mab^r1 z6732m8n)_6W|-NFaNCDw5%lh104vXZ6<`mpER0X?9Xs>(_~bzB%%$P@d^ok))`l}( zSs}g~9;eFUnx=U5(s<47v6{89YJ{3fN2P#*bFd7p#+IuvUfmq4>Kpt^^*Yr119;fF zxQcL$(&JQ-jy!)DnSEf=I!zbRr#bOe>bAS_08l7a+0kfcgT@tzUfnbyMhvW$#leREV1AR!_`{%U-A3sH;5(VG<-L;$lM8N z0@3kih0gU?=wfe$v{ZH;8bm2|8XUkVWiVvND-Q&r#y>m&YV=loOR-(?$chv}q}HhE z$lYcg*6EG64!@+hS%($op;?E>k`w`*=%c;UQkfM=m?E|(W~q$jh~Kw*h%$ZLtkH$0 z=yaaoDL$1Suc-Ir6kF7++V@pdt5$!a%8|f^zUuY}QwXpdObLzdsXyncpFREbn7kR= zx?N@<&*1m0eA>Sppo$1ww6cCa?ccs?kZqHZf^2ac_wmH-TigVfTHP7`chsIaTiqZ0 zhgLPeN_D?FpEmwdPd~Y>`!VF(dG1NSp*((6ZTL~)*Z3Wf*g{ld2H$1$tRdk94Z9c)8Nm# zN36$83!Wun9(^+&4=BZSGPL@Rs( zUlrLe2y3BJR6;YX?Tqd=b+ltm8lw4_Go;7^x5d55NFm9kjT@&|*4Q~rv?>^xC0ul? z%p7LG0ieb|mwjgx}pS{(d=P?FOO`&1?v*S0GG z0}%A`-Tm-5@O&qhEER8#X~dJ*K9YCj$&3?AXz1D;(}+xZ0@5N)k!eJGwtkkLfc$Z) z+HCA2xNdg(zJ&EfNd)@{XU9jfkJ#~1T3;&nl5F3y6@ViC+eUe`jBB$tv4&YplbrO? zaf~(Z>UoFnvaBQ8BNfUbApbH`POe#zqf#@hy#^hTeT3hM(WVoqZaw*x3P(?@DW8XZ z1e826KA1k4pcp!HyBog4SVt^Q#(A!u$BgS&hXYe+`!5RMa%V1qDV@8k7l5R}KHrrHM0Kj|` znEqL`AVsH@M2Du16uX>hPrJ+*N7w>cVe3t7zC`cu*s%3-hPno_agw6eI}J}{N3CDF zG^2R-jUyKS!B;+iNfg+$Wdxd9w0trdGdGiw#{;k^NY!FgmIof0spUm&-B^&fBoL?Z`wlQ zf0O^$t;|Gu3l_-oeh%Ka5n6{WW8^V*r+X+1mDZUi9{Kluc-DRS%hwzZh&z43e%MG5 zHm2R~y@9%5_hsNgIf50YM*d%ujlBYyBW@EC%UDPdg6PAL4Pp?iAL&_02sD5T8=ica z-S3%gW^`yD$wGoW%-S?*`wrs`R**~?`-eyPYry}T**9XgjvV;+xErx@*$AVeOy`q_qASrW53*~#-Ic*Q%mt^iIccPP3d%Nqo`>- zx`dWxE^!l^%r<`UF4Op-=8W0lK1J`6HwX`lxK#tPoULAh>1=gMCZB z%s|@QBevK*cS2=n3mIl{Ln=&>>g?mt z#`hJ;Zjel^gLNC=>5Vb=0pLI=h80e0brVC*tIqq|_{CSOAcEG2aBS6777{6NsO}kP zp+y1ro}Ykk>RM53DkEAo%-t1@)yi>bN-9IVlc@OV^gLP0tJ*9L-Z3sfS4*&%aXqU(ziMW+Oi*4(ZLMDI(j6aYy4bn_svva zYMXi9Z07kz^M-|c#(Tr%THZ9dt9YYEqBLSQt?-ZGcL9&7Nv$mM*HLE47dY-u)lgN5 zy&di@;+Aq-4GY>!;(23GUhK})i*&H+#>NcOuJ*Iz*OXbS3J}53+Ll5D*BeBzji?hS zEe6_!f0T(dkm2EhCh$Nz&%gt3Ap>jz4;+DPwJ}@t`kT2-w3WFwiK&2zXse77;BZ=_ z75CLNdl+C~I5A@r7+@m2BuaN_t{0gDsWp5p|oD#V{~xG;qhq}5W4R?i5QII%MdCCBX@FhFkYeR_P@*zX(Vx+MT!#dS$1WnyHnR)b^P-An%}0$?s4(s)AB zn+;taX%TH_N@QlZ7-Gbp{xdt7xy0bZmE(u$dgk*_yWQWv^M!U?XLVyB`mN6D_CWMN zo$cRKTUY+Z?4>sMZio=QBk5m!;a2zGxTR3!mGr*6n5I-?G&M4(UFN*==6_e+qLSWG z>qvsMAPBaXr4ddFS%d8Q%pc@;U2l*LujCH$ZNgt!62~9poebL!@&*zyG01U-Y1rbv z$CQ29_tPR(O%9^*PPyKm&`yDfHZEnrWnzwlZjuqIaqI&dI0_BemWpZkXQM?tAFWw@r)b@f{Gow_cho)Wp&b?p^wm<{!V znyo0=PN}-C-ZqL?T~|f0;Y?oPhg?-OlQ0W2gGV=$OxQje@cJFwVXlsD3*Id#)^|_o2&MS&G49*{;$d7Tv1+-Ivqzg;4X?Ah$kU-96WRqw(UDgL^0JhRX8yt01qctHJXp+-+dnP zQX~Cs(38%FF8*2_i(I+gE9iqfIoJJ`Zzo3Hqn4G_$#%>AR)Re529R z#JJmDz~6LEiIbStq)|-%$lF{G>Mae3_1gPme}5%A%>Md48%~Y?V28I`%?i173_Nuf zxZSKEaUr0Hj-i`s_}$x0QN4*4b($3nM8B;Kb|}(KmCUE4_agEx8V4;h*?N3(|!y zcnnZ&y-88@^{=w^CTYM}do9__t+qOmJyjip-T8us0=fPr@@M_f0*~x?YZ6yZ=Inz$ zK4r50Os{M`WwyR!q)6|$7h~TB$|DX%+Mt9DV#!2>;+XF4#c0*|51}A+EUjg+PSE#( zH;sDSeV=;I8G1g2#H1$vGZ!6Y+3T5!$iHh#W&)TNe-gaux#t`o{3jH3PMFNjGhLat z%Xa0NyA0H?P#az^9{r=4dpi{2?&MD>l);GE^rn+;9h$Sk(vp+i18AJNH!Vy{UY=7s z*IuA-kM&>v!mj?Y>Rh^=wLDcX^nLup;-?J{$0tm!DQ}xo5RRQTl}H+uM8a$(-Wf1n z_eODKZ%}izABm!iqrFEoOQFU3a$)fv;L-C&F`Mtqmg3Mrc-`)(VRo-c6CQeXuc@g zr()DK-O+uW#5h)q$>19mi?8X9b)d58-k>4skyaqxel|Z*td@pyqK4y_6cgojc=(7* z5GtNFiclGmft*=WlN;G(Pyoq&*teCBn{ic5FACQ0;(09koD)~L6izA1ItmZOL4+m7 zoj(VB;*+@DfIZnR`qEid5op|xN^lXYrJTavWQvn2h;7*TUfmmuU04#EKQ)t+_(6E-^%1ISQ-9=|6Q-oHX zL{%k{@i-kMCRa>-oHWXWR=8|9!B>dj8o;fK;2#~B3QX;+Vx@+tho)DPQ@v4cRE7f2 z!O|C57xg)WGJYy@5KRrQTpX2-ZP$2W?C0hdt_ZFq#ta@{6|?N#Db66I?yb@l#yg;? zU)T<=Y1V@H_|@kj&v+$`Pr`|LJ@Ls|XZFM=aKO{u!wvD&?Jino@X2(wp;Ht@cKPq^ zQFXjtdAr%rgvsqtgE`+fQ0_X31DU%4Prj^vD9+WO0{EB$EKTT4Gs_t+0QryRK`RHq zfVF3+N6kfgUer0hKse6y=@&FFbeocNCNa{q=k;kbLO?KX7LNNj3K{Uso{yaVjQ)oG zIsVJ~)6476xwb#1J+D8G?T=feS2=U^bXO1bpYETrU*5?QRp{)PD;aNV)l`5xFJ3i$ zd12(JERbYvJ&>FtkaPkYfklwS6lQG-Gd!teIok<;*R2F0-X}&FxPY z*-=A(#*Ql1j@moXKd*A}KCtG%x!Fv6nNKe_3S*4Q<5dn4*NtvC&?Q@V{%8ACjbfMd zid>-RN6qe#$b?YhmQn^>>pYCK*d&yaws^-I&ajQ%Fq@O?7sB3c9YXxiP@pw*Lo4`W zQE1rO&<$%DZ>?IF-%&rTig>TvG}E#NeAScwhY1KoW*ho+B*bl+#Qr&LClBEXOhDuu z!vG8xZEqQXqx0YS`S$MMjf$|sqXF&QSq7kkdLr~YU=p_DS`3vBr_i8iox%8MHTpDv z^qJ(*-i1*b{@n!p$QfTlz?UxC0|9>(+*uX@KU{QL76CsT5AAP6z;AoOM>1baz`r%w z$2fZ?;P3s!Zu8#1G~4`bwXALB5%7Pz+Y%EG-u_ht{9kldAV16P)>jemHDA-M!Ctqn z;JaX-Q+sslEV`wAdl0WJ0e{zfJ^_E#@C*Te^bt3N?9*@J+;@?$$ahb=Khzk+}tPs!Z~_+xkol~0@yF#Q`pGi_*C zI~a@}J;Ni5R?~m|^TyXNWb@O#Bi}MxMck^{D#`L}Aa61^K9@S2yDS0lp19P>7k&+p zkG(Df7dm+`q&8P3u5>J{4&q>ESW zZGtZwUez{nM===4lIab)1j<&>07XBoNrSqcbT-He(DJI{SKMX}ZO!htjbYQs&z?<# zx>|Pky30i^aGSjhcw^mjwiIG3* z(Xk)@m+kimURz-Q%ey|XFB@fm-3*|zEeF{DE3JYw{j=QaG?b238g!E3wg-O>^lMV? zat-u(E9E{*L6HPMT?-pgD^qf@!=wZguc5gD6u{3knx1C#0N=H?-@+%vu z#+^%zTzbv7|C*JSp3tAwv=-OI zt}DfOINDa(O=j3Di-R}KH2pZG2toXRo393vb=S3(^d=A)Z=iJBpmd9B2#|uOu;S_v zPwrd=CB`}gh1vpB{RD3In_EwWtEI{xl8NGf{xo5{7DZ*0wyP#~cqn!O9hlKhV1lK| zb3h|jQIPgO3B~)DhK3Q5rn{H(*dKmx{}F*^S154-5$e1L{hab=gE#l#qK`OW`)&HJXUSMw=)TsG9f*Mz6HLw2jO>TD;UTS@tBp zLa7_W$Sv-vd_$9gd4C`j8&VUyq!15aBeFp;^oINNJaYgX&Q7dZPM=qRnBhWa;Bq~v z)Gk8#i;?+SK}E;KKMUn@7m2L8P?St?2~_05e7FdNPIC!X*`>jucy^^NFMlDrsU|*} zbTMbJmc$$~Mpt~KQ5PhI`7GK`QOaHpm+y=m;Us?Oc82jZc9|rBsJ=CHn z#{TRNs7S=#+)KgauejL_p4rc{GR&VBsbb6<+S9G<>0exLMDWYp4aiLXEMxj*YOg<7 zcf>2afAdL0O#F3?{m%F|=}=T9{smiXckokRn9ncNjXMit5^MiKxMV|ejO_j2Uh|jH zyjB0CO-b5b^U=mK7D*bQo3{99h2f0MUrR?z@?_8&#Ei#FoL=;6tF zfs;%??u6RW3n6T@wzqOCY@MH)Asj|i7t)k)$cZ;IlHRG2Da3sW{k+Uw3S6Z|>I(dqP8Pu*7^Xo875joxE+Sxd04(~NeP$#@fURn@QdJ!eNU6hkC{$)r1$sH1y@0&AV- zcTn_=o~u4ya1P)eXk|BDtlbkTe>GSyl{T<}Ov%`9ku?YSohbON0e&X}zpDkm)xdAH z2fsDI?^EpT=%!Hopiul&pqJ?Erxe!2t|!sVOVLBLtE-q(%R&1B&twT?AJMOrFXPp4 z;%c|E(!%q#U2ZSj`c0_xIHZy?)tOEdytNB zotDe$VG-$&PR<;!F@*E%>eLb5`ha2_W}KN~;yDWt4}rn2Xs^WCp}aeI(*b;278VLA zz)C;v9UuGZu@+t04(JNZ_pZ4=9Q()^=nZ?;Y2JxQX;Q#>j59$0f`Y%BhiX&`bT+JA z{C@NMz0!e4J8U^GMD07F@{fZz?*N#>BoWZ)G_()Sg5qm_vv)XgWU&SpKXa)QCpOIw zn8NC-rrgc`gw<0((_Ya18irwhqrwJeSNWy<+}drW4VKt8!WfnZJ;?2LtA{dRGGEH zGjF^EmU}>mb-9P-mZ9vd9`P34xc)`+nX#`~EcY(`b62-Y&)q6V3YoYO4H^@-w=i)# zn<-r4u7UK?Q)A-R=sv)$UgxK<8o-=pi+dxD2nqb~MuXx_3#Fj2W1YH%?Rk-bbPqsN z?7jJgZj|aOd=!Ow*yvu&gZft@&kCz?K)&l9M{}lTv?cYt!sHV;gLa57+nQ$Pxahfm z%B+0|OH~w(&jbV(HY$z6gVQvj(I#zwWgtO>p^yf_dZ{OshYIByi8XvO;!I~Kw7^%# z(Q`>@$#?--z{F= z@ipa_6h|L4mi^+7WeyI=Gm&q&qpvdd;7gN3c##z??@3Fwj4w5&+y&N|VQ{ulvU&6+ zq3nuG96On06FrZFOG9$Zw0V|gr~NZN{0$=5eT4r7tsKe8LuQIk$I9sW&4s?9Y<2{@ z%Ev*ONNo(S>xHi?#&ZK_>A433iqhgmFT!YbFkf~rBSad&sFd1dgWEChwH|4O27(Xl z=!cAGN_J8udlLMYzGe1!vI~W>da7QIN%t~sn*CMgyjg(yeDNWnMpv}pFLL>AhrAL*E^6~47j4KyF8WYb*NR;9p&}Oz zDs|$6Rx3vZCjn_a@>1t1D-dRsgn$gi2q!8g2QnE!Ke?ief7KY7MCwb0PWO6e=mvdg zgFe*m^wlYwu_*sA)yG(r69Ds#UZGxt*w=f7y4eIP0?-!O23|J$DRE*Z-6=b)I#0A0?lg%C9mB&KhVx_gx&q}?V&`7Ta`tX$dRRK^Ac=+7 zSFRewtMS3=WThfyNAxa{5zb`y*kK>CYEm+Mma~{(R{7XO-6<*Y@WHqqGZ|Zfg{_zYyDtbr_Vv znIl4*%y%4?za&^@<{(&RXM_lzGCnIcEJ>nfG3OJr_}=)~r=i$pcV{HPKo{bQ)Sct@ zjw=r8T*6WpaITT#T&LS2%v40-%gy5#QqaezEk)2a%bOG$Zgcl$B6U^*0iySG7Eav) z)3LwkI5SQ&05d=*v1&e@))+1}g^jg|KL*VkV=%LrJBEa6St4M3ELjulaz~m`L~9Lb z-76&3+C-V|4nN>Pu;Jf$8jAOUlrW>&;r{6=a<|p$Y3xN&GqNGQV?X3vic+Wt5CM0H zU^&g+rzS|>cf?uX2fxA+_wwutOsspEYWOWArY$qw>~zNm=@Si}$FInNGoBMUFy_D| zxCD~Zxo%9qtNZ2U2Y=aIvXP*Odqq!Ge&W9ZFiHp9Rl5hD^Rs?=sY5fxlDwzbbLnDNnqtRNEQ=wm5{>q&=RXy99NWCR zBefB3!9E_$x~y;qQ#!T3|E$YpJKSPZ zY+b64EoM`F9x_SzYK_5b93qMQ?T-m{^l}n-QX_^Tq8PuM5s-k(su#CfGjnEYW@|%) z-Ux)NYq{swFzR`Eg?TLvbM?w#lkWq$lI>vDyW;US%DF2hnxouM$O-H7!xVh)jXnTT zHPp_i%DP1rh~b2XfW2i2!JbKsSvMwrB`&GKpWVVM%=0HWQXP_KbSiY${H}2 zA(N}EMuI4|{Ya;e0VK@Xs+T-GoQe+(P%nP+kcC0Qt#}TrP^UF*zQbxWHOns-*D$y% z-v^{pDs~SpqC;7lf}yXlhKc;}!4y_T&(`V{G0NGot_^9dupn>)nX#Vyx3TT z?86jwyDz@{DMl>Ul`{ASSt}X0%hzZN5}NtD!kfR@rcH!7Ic>hT)wBtw_2=&{YBGP* zZ!z7UBb>smE=ESEodCr;0ryo0G_CvQyS*G}H&mzv3Y zq_;nLBdOgz_}O^Q6#EiFdp6+Sz|_DhPaQ#b~dG^~UpiZkyLHlFc^2`8>9BN1}2{sCN^ox~l} znJ~D{B{Jf6xH${k2HG%$ex``LxGMpMhvO}!>rBu!1WO^x{KrW_lTg)ZDfJ@*f4E?!@1tYY`BFP*Rb z82d!?9jt$wZC%^%vX%0FkNRJb==|JNW=pI zGc@(yFgqzX{T)rMq>lUcj|%eY7S`ex|2mDa(N=g=3%*WdNXjftU%HT)fmVXlxWA*W zMzon%3>Lx7gz5StJIDzY`ZHXASZL3!-cQ>Uia%;9x%;D948?v~+MaHq-n^hjy_qO; zA?ahNwZ2psPya%7kD6Hr^bK4G>#GbrK3ZC$F>vVZJ97yVR(H8QM3G8HJJf()n+D>y zmKK|$grMEYMLL98u#RmB6_HfTf*gHLC=n^G)CQe1-OgAPQ&)esikPjU?Aemti3Q{Z z{g|mm)T!)bD+QvL%&bJQRDs3DAL(?)-xWN(`6h)`c(HCw>m~j20*ju0c!F9XDklqk z^1<8Wy`M0_L)I5eAZ5_ENWU!4ephd#Zn`ytJ8_uxD} zDU2Gd-@%83E!_c-jmf0$>fZQ##Cq~6#UChDhG3_)_tWZb=6?Ls0{@%`+DkbPiuHh# zy*CVD^Z^L|$l<%`vu^d<-(U)NH#^;JQKZ{;3+tH$;`&mDei+Ep22+8l{OX?|Z@#WQ zM7tno2P=j;RVQnH?0we!_z%+a<3IRj^W(L@+x(az(?5=bGfGS3@d!H=DIE^U86BwX8RHof z`(r2%BKtv{l@vvTD)vJi8)d1p6mOz#Ojn)Y`|7$e?_MnUo@F4;;;##aSb(c;a(k_? zu)V~PT|WWRmO*wcP0ce4n$}P1u!&dK`aG6SEqJWi`tgqwo#^?~gr$*!DBkjSvd%x5 zf5rRqH2O)hqf4R^qkAjiT#SB{d`(XbSpVDy>y3s=96a%fG*}N~JjOZiSAg^~_r#4H z^uOq_8E&_=24!k}bfdo+ns72Vn<0;y$@|US9aDAu5){ytQd9Ydbc_tFD#HS=kb@Y{ zLag&RWd|h(2parT*IK<&0Nd3$#YjIBa}dWM9$tGcsK>0xabJ$F*tH+$b#y-rPscaA z-DjwjT*3{jHje&+FK*|7cdv#0)VDSQL&M z$|4*$^joT*nV^OrX_$$T*FiahD?V8d4ajivJcRMg4a||DM68*MmeqY3@~#ut#AxA6 z6JDE$DDkRdP+VHoa>Lp-+Q^df!?*a&9O=YYshQM4DQ3+&D~SDS_o5UnvGm?DcMhKs zVRpo2zA1qb5ovQ*h$yoLvGK9)dv>J?-Pg@nNG7_NuV;Bx4zn#8W!ALhcev}}PwnpC z+1+g;*xW%FC0`U}elwp+(_i89&qwQNOZzQ%LLXudp$*4xw^6s9~frX_FY&YLhZU&`O>`ExC06h^0NVgV=e z2bnc!aCBrP8q)eDdo{3OvYxj#Oy|e+J!a#|4K#wF;6NkCYBh&9mOf*7U@=v7ZEH3A z%siPzU0%%Rr?p`*e|7Bf;1>J*m;5-5YFy6|qTFkrueCo9@YCAx9Dh}Wu59K~=Kw7f z0yF%`#fcZtTz=C+HoS27;f44swf*>F#_k?*k{Hu4(QA;v97$| zm$VL*jZ`@@y@3C0gAZLXZy#%dQC$*BOe4-quAldFCmL}AxCoi()Zy0GdlqOHRnPP? ztj)|!vO>m1{|)znGmPKhA$&N0$$cR6SoJ7!MshsQs6aD4S)=9VuuN)!n-=pZ6l-WR zZ;DQt&+7(F9L&ZkN?+Wt+`E~oo2A}OF|SW86_;bF)yF1hpzh|n68da^H8cH+> zK)JqKzkH|NHgJ>I>QC*b1~$01SfWeC;y1O~(uHP|7_i`hX~&X14P{Kf|EPpgm8}iK z`4M!`p_|kUzduz2e7!;2lHY{GFU=S0C)O~PAC^+k<+o)|bx-tS>f9|tgyw7cQS(MN z`l-=ny}|=*UfS>?_;HExo94theK?_zpfG=2Muw8a>3C%j_hIATptnX5TeB&(FXww! z8~;ulXkut$Hcb!|;#;KZ8jfRWSqd-5A@%ww^uh&0LmNLJZ4R*_YJ%h5Mivw~KnU67 z75?oI)lxAIJ1k z_b8^suUe^(a031A;xu-$`c$W`wQyQ;Uu>7`z3lggIB2F-8Pkg+O@6pyhX@HSZq4Am z5{vhSyLYr@-#()R-@6j^lA|Jm1fKXU?UHEiaPz4o86;UothCXNV4WmTp$S!X4Dd0cDj>3kOBY`HL*8O<11+*Y@B4kW(WgF z4QF~gmuu#b0e)r69Y3)x8*#FRBG57Z(j@v}XQd96Nchr|1tz-350@^W5AAek0B91+ zuQJY>#OrxfD?Mi6d=YUH&tHabofXg5?c6KsNS^+zW+)?_M_iE@dE*@-%ov$uqA-r0 zTz=+VmN;K-XuEL`=Zz5OD^g?CjxknEjQsuaSyeru{Lwk}B$T)HJfZyW_+o>pHhAVR zUmPer(LH$Wyo^v@#m=|I#-@wiWQyHEF=GWGE3HQNkLwW1_kB!4`Q(E-_C)bP9ZLw` z=q}-{CxqvjsK7?|Iz2N&_)V+0GD7$^uCx(Lex%=4w`+8UNE5udXTR^$Z?9&(G9W7I z<;t8*VC3vy7nA$#Gm%7E8;Be&7S<6~ikd$9I5w?qVq)~GfK{G* z*s)rUX<&kAlWbD4&h3~OJHDf){N2cb7<6_yvF+huZ#Xx6wv^&?_R};Zf6k>bt<}xl z+&Fk94Id@5fH z)irnEk*X>=@~A3eFTS{yzu^}1`c8i6LSiN0<*sW#({vY<<1U{tTEAVSiXrT@UbEvxGf55DJmz7ersv_O$X_Dleyy zsLiG;O{_%(G^!41(ke=H#JKeE_g(B?AhcZ$L(u<;1*OYN8)A~E+-vqryx&fC(z@Xu z>~^n~KUd11(eme%0i4=Sls~2N=V<=eJ?$QLzP%3`-92rBnc*F*e$0oRmJVh`b4}X$*C+-;ihr*uTCLzE+%>vkhMf54v8wZ04s; z^$`B{!N88pxP6-axg1$As7zw5x7cg=$_E~6J-uwu%`lu~lBPv4G{Ka`WfpuqBef8SxV=5%-S>Bz{($vU~XZv`I?m zA;GeV_>4~!E+BrQ6!;-$ojh#w!|&4SL=x++AHNE*b+GH(u4y0*h-qMh*3OTo7Rgc2 z`f~|;DK?qo;yAc*PGn887N{0`lT^dx9hkDdg{L>Z+a~-l5S_e_n6kb~CdM<1B0cOr z8ADci67K$)?}C*?N16o3x*@qYv;kAr;z|`tBi!mVo_LhOVsSAH)ILwl;if>>rq6tr zEVha(wl!z%IU>uPHBgoc_=cuD=BxxL7)p@ZCSUC-07^|--}l`%gx>^H!UP%Um-}ja z&&f~LZ24efa6WDjdD45rjWY2pmhRiIqtt2x}<%R1lakF8Yu>Frtu`z{$=WR;$pnR2lU zKJ09Fx;=KmUy;=M7T~^<`}kYuH!jkp{0} z2Z^f)a?3sr`G$TRDtmXrF~X_W{u<{nPwp{YRTJldfmORAp;g{VJ})Bxw#lXZh!Osz za`VR6O16J6*10(t-<{w&zM6-47fOUu_COCl55zg*_43C_PJo$jyhk9$^5CX3%YhZ& zDpL?6%M)|4m|DV@iHWkzZ?7Q8jI-#QcBz*>fLtVAI(Xv)#T&)Wgr(!9^T}VNh3LQ~ zIgwlZu@jcq_nH0@ce*)zm;H7q_F*6~q?jGNEYc;=r%_D)w~O#rc@Z9=r}x6#{}WLx zlZGWvgpU5$J~qCHvg*;u>4RQ=5-FY$qgzAb}&wvKCSdC8_3B}FBy|OnEKxEMu ze2%dXL>P87W*nfKMFW^JD{!bWJ&Q>`0ptNgMFc)n;`u|K8^T>${VCGYA||v3{RywW zM0p9pP?4fCv1fvj2lrFa831S+T$BT@;#xwz$O6hwJ&`;Vv2qc1Evc@Thy1FVgJlw@ zFn{7!&gN`TDp4amO!|tRna#>wAkTxbhedpi6st0Ieo+ALBhd{UN{G%`$h$HB#gR!p zCDDOQrl9;T3}EI^#K-h+NHG>%&L8O_9}Ou+rq5r$6dNhU#0X=w5v}uFMEgUECs(5C zuambba>oQkxDQ^{6wi_$yhQ-QePetn+rV_pJ!^_3d=$?JValN`h)Sz|>COGmR4q zw}LO9_eZ*KG&js>EG>YW)K}Ct1e#KW_snT z`;1Y!5KV67#(MJv_tSj3!lx6vGbWU1Tdhv}AzjPisd4h8o+55`d32ASlo_26p;>3R zBl8fUtq`GVdbzC^)xSB`{ENo}507)o$B=1fZe^}^W%RO~t-qd_8NEBV_XS)Cw4YnV za>{Oj^_kl|t3rCC6I(}RGCMGt>P~cckM@%znwwqjp3l=gnVe4PuKg!YPANi8@8q;H zIp_fAK%%SXvwB#nHM&OC3|BCAUh-X5`SwtUZb4b$)*k&c(ENaHnS}HmWn*RF;KP{cAXsQn|!xUAf{{*etUm;3DH;*zs!@* zV|C`zk~|J|8}Mqp#VOY1RVfw^)nl-nTq>(wT!@Cjp%%_g}NKEmkeJWoT z9N}}-NB;waQw6o7GU_8KHqsQ!Nf&!ki(Nu7kInZDe?fh;g19-xrz4tWY%UOPtmZRW z4qZN!h^@{%|3Ws7V_PJerWWgPDsnVU7?i8Mk<~+Z&hGK!g|k~4Ow5w? zul9f9YjS2Neq11dk7Ps9MMIe~7! zJ~B^DRtZ-FT@SzPUv z)Q7}{jqRzEg>Zy5`y1=KL+f+9nl=P*0FpKToF7`?*3PStBN4Mtaq;MyPe0HR1_;Nhlc4+B?LpTh~apgUuT0>|DP(D6>`s zMBfCTioU=n-fxHSIY;4>0SnQPI|R#sZNbuz)%B}Jet%%u%dK0%vhfE7EFU@7ce(0{ zaqyD_A7+tQ$3VX%NQk?I*M?6CfssHUhn4`G>yH!QEOrQ07?(~%N#kV!!j`z3S}lP- zWosLAzu4k5+AWBjFI3neztd#}+GtXntaG#aleXtGF}GO0c?jdeLvhlWW%tTnuljCX z_$WOC^JiEQf6njc>w7MAH8jVetN4_RNvs_# zvn9O3-~sZ{2F!Bu`HCo+LcQwcYza7e9sxKmJys0c8r$R3A%Xb8u?YU9kLZ+=obVJObwpr+yiJ0<_#s9}LeAiVzaV0trlHbbb*IR{Cs?*2 ze43y5Ri4(vy<6mOykGnH(cnpb>s?$O zJnUYw@QsHazgo=tIr!)f>G5gM<7_l*$Z(+x-3%FS$-*c5x#Rne$?&2P4%`%%{HeEr z#sgfl@#%0hA?%H|LmAuPqr7_~ZU2Xo$X9b00|~~Df=K&?kb3R=gIH+KCZ`AdETl;6 zlcx+oKqaV@#V?l0ckmYZT@gfyr46(86REAE?KYYhx*9=9$~)P1b@oiZcTRe{iCLYO z3u&?z7n*U-=ju*pyYbT7Q2Yo8zpv(P8Vkj5Ko9XAwu6XkeKjH>5%LR2-aQ16^gB{P z;!n&}#CMSJ55k3Hc%i^8&x)vmufw5$aZa~ZP)i^_SN;3g{ci+fbH(B};AGY7`>AK_ zl61q1PIhN}{@5utDTamY0`z_oGtD0#nIG)?8T|@Lzh?H$!svYhZmEE-}#jTZJ7SPUKumX?@Md)vj> zk18xThYNy<$(F``BAyztpK3|#VgHlGF&d6|tTmC_O@pySl339t)>U%biMYguw=^br z@hOCjlS$Sn_(Lcnle)eAc|somGp*#i-Jg?)GW&h7$p^dj>i+CXNC1I*F4yewwc`he z7cs`)AK{E~`}|;gey2?{-J}^djtPbh+#$a+X_$=v`(XnQaO+kWbSW?}_`0XLZse+a zI6dEbUQjjI9kRh#;ED1<2Lq5h4wqfpls=6AhC{xr!o(x8YlYICkvL(aEL~xJ<%6Q|L!1CMp|(M! zaS`t8;e+T|>tWt~>Z=(@#hJYtSp0sP17pA9yDR(EQ3@rSAp4vv9k;yCuKk0Aig6Zc>@HcC z$zflMKE_k1eB+r010`?Z6`XuywexwwTHd&eDW;rx@)0f5WYu>!n`jQ#Z`?nr16ZYJ z9Qq%)f3B3C%{k=1`=`(L^z;AE@1NKGJF$P}Qb;KHw)^MzyxGqFnY@qLKjXN5L=e zHNAh--;?;R1Z7n#JdE84^R_&EsWBZmJs)NI?syj#34tTISBX$Wo}GTQ{27>W$s~kj zP#*nA{#;?6i`;?dVZQ&F`Tn*Vx$+-2IAQp^^}()fk@L~EygmeN%hMdlFw-~!h9_Fy zaM+$XoqTsmTvs#~Py9nwBlYT$b0ihuZM}M&(Tk7=burNuB)KZO5e#!e4N38PA|z|I z*zC`!daZP=oGxcnt%4imvO18cLO4@Z2T%Bmp6tmt4v;XvLGU*6 zdwAhK+kExbXYN<8>sN!azZ%Y0)?ezjq@IScOC^6Q(k-Bt<^j8`t^}&8LC#Gsbd_RE zn<&Mat?tsOiGjv5QHnKNU*E+uRf>(EUK>lVrB*5Uz3m@hQ5;#OcT{J{`1mc}B z<$Yg61io+Gd9YZI5&>dx-h$cG>j;mDAc!W=bHtn@Jwn8Tmo;mz%SqRP6jaYRn2=i} zs8B^?5sF5F;ZG?M9nW#;_#~6SW?v9$4SnMvq$mB_=^M3pWR2*p#+|B@W~3!Fu%EBM1-jk%$T$H^3(A_%5=Rh=1r@59R8} zZy0gzl#hwX;M_~@-x7bUyn;Gn{eOs*L)Vc=9Z`e(?htdtW^cV8uHx zmK1MYCLhiAQ^8{Y%GY%RuLp6rED%3m6XNiIYs?v$oUo=6OM+dJe)R~iWOrOz(r$Mcd6fxeftQ|j z=YI5Er24hy$4KjE{1B6Z?t^iAm1yQgw4H+{R5k`rkLI6;_^~8{Joyp-Jfx4OVLnyT z*A#UrpH8wHXWiYj+4T694~ZX#G4%6Q#MLLBGs4g6sVu*13{fUj3q;oB=+J(NIiE|I zhZGBC9#ZV-o!A2kZ5~oA#Cb@ur;G9m@;s#2q0cqN>28XsGvPn z@rClB^kpcVb;1O3Nb%L2$*!uZ*%Ut5d5frc0gu?yTdaJiObriE#}FzW+4Za3SYrt1 z;g6Zf3_p3!V$7NpFp(n-)(iI_bxFM78BVxsxt`Sceh`o*95Vv|OCfc0B< zG9VE%p(i1l$(7t?HTv$|GMa*zQ~`8z=3lKCaxH9tKhe{OMx#se{H06$i+*y<06Xu4b@y^sTJ0~zNcw~0 z{b9Wu zV@jM~>RL4RY+O zNeJ+q81c8ra1+DHBI?l>2g)YlHzT%1d*>rGD)i~c7fQDx5iqedzte7vbONU-uu|xeu^N(B1|wnh_MQlclRnmtyP3Q ztLjHTbDE6PH&lf1r1FJ7p^cG);{9jwh|+7o}MlG{Z8=EetV?+>-7zI{yg zExTAQ*89R($-=->8NP6LKfw*-a~1n0W(Zyan}SXxkPVDYC|+DF3$%8eASidy-fjsD z1?E@q!>lm>*kFA4ILXeN?NY@-Wu#XM=WPolG_%Cq5>72c+c1N(ugtx73?{%2rHbKAVGGXb z1N?o~`0>R0-{d8{(+TtF!&@AA^2@rOddqsE@r*pVHT-b$aK4k}^{EJvTf@Ijq8`CP z{&wU34a`R#{BMT&z7GHC!h7{W9l*Pb!21{hG3;E&Aoh7dJVfx5f$t*%-@Occ!#~56 zPP8e%bm5v*xbEw~^{u2>VLA3*WjluF6G@_edEq%r52$l;W3@u|AXCqt01b@%AbFqc zM13fGk{6H43tx?LpyhWLNL03|5SJh9D?x9w$S&sQLUtb=-Hs&g?WI~yR5pi1UH_3% zi;K7zYVk|zNEMXPrbBQXYB5x^gt*jVvQmrFaWPSwlSFjA^wo{_9W|Z;n!J$X*MXfm zeqFVf2pvqY^hC9AmfSTcl8LsOyRksXpNNXj1Mfz1XLlEUx4ZdkR`FSyvV76sLyWp! z!>2AW`Uh`1Bt}iVfR!nvX2~5Rcad?VHYO_;O`FJ=gmzfWU^AkiwF+<-$I$q=e= z$w>wKyk!sb;`>Gu1InLJ9~oifx?}%SAv|7AQc`ua$Jep9LS z5^6J0CDeeo#a`qL&YlN9MN>sA!L;OQt=fH?%@7}ehWMEQjLuaP;}XSg5Vo4{bc@6^ z;2V;PeBV5s`pUYhLSMelzLIvJ^x$}oR?x3f+7w@4?}ibqa~?=XxA?Gs`?J zr)lvf4QE_KkPP7ia9FPR03fCm#&nKs;$Ycl6OmhKq)QHURumDBCRxs=pT4NdX+1#0 z&#IRT8M`syl_0oM*=U#HHN4^ zo{QtV{<$NKI^+H~Qz9EcLW5EY}L%t5i&qqE;jO$Bv(J5WaK34_mU9uMNJ>HTz zSLt2)T*V#BNttJl-38~Wm(959qUWkt4D?Vr72i?vd>EotPn$ zVf6%i24af|+f-OpSL%-+ATwEeDzB0OVzN~YxUq2j+xGhox^JwegKDt*5H|HZROTl( zAi38UEC={Mp5}z7Ma!SuYtNkBrcQ*#>-Sd?3TCl*h13CyxBR@FXYu0yR2FYC7sKKS zHBS|sM|;^U-W3w#Pq7-^tDZ$EmcB4cIs+$n<6cdJqay$2m2S#}%j^li2KQEI-WkrW zyw4Y1bF6D~Me>fxb3ObU;suw(8?C!!u51d@76?hS9s5SpsyK{i+FyX9Nt*e)>}U`3 z*X_r&>@t6qyy=knJB}AXUB(lPkA?TspaAfG8gzjGm*0l>o0HFQ<(M!XCmZN*Q24*koqERiaM(cb zmYGrE27#2r2EHUy7B_OtrTh*gZYG^f)_w?Gq75c>OJ%Xj_~1K7^EJFS4+R8`O^q%OY9Tbh6=Y4(|4gN zWfz|b;i$8HfT2nTU}wY+MEtXs;09t4c2HLTNn}{o7V#T6^_2}`;DoPM22K($rPYa- z(jG1vF9o>RPZ@fsC#y97_+z#eqmvDUEKm5y(G1?@ABDw9^N$ASDE~-A5to0g8|<== z$n=Xq0d+|8JLVoy^-WL5>WQ66Yg1?XV^b=4Hj_r_N7XDo_M`5d?T?KZ9*@k4O&BSG zILE?K5f_g)h^!OmgH%>aoP-v;0(sSVqMa=9cQtJD!NkCmQ%Q?`Sm`DbKPZBTKP=-* zamzmo{(k20)4ig^VQ|SEn&((W8l+ZTB#_@F{`M2)Z?U(`CF>l^%J8?V zcEsP7(2$3}4aL4niloZjukg1gI?+3#TRV;4M^+4Jm;$vg5^d($K-XuL#htfh_ibG4 z|JcoC43)(Vlzol+>erR(YTu5>#XAQcw{p`LxTBhU#qrsStjab_JP5`?_JTway>tyw z6@E4YPhWITft2BI6=*vbM?k)y>(w%RYjazs`@+-Od%0cr@U&m2oz^vyOm^zeq;qio zckr~mHv*@!M&d>i?{S04sF=pDGA>RC0=i{H&733_tq=H4@k> zdo9}&9ex;wQTL_TT@VX|$jHjxicGn-A^V$fmEm>Iq8Bfw!;G{#+$|{(la6>;(W!E` zVgxGOtqIES@09D073$ok%!Y_ZW+}SO%)jWV&kV*-6z!^Gk(_bY5eCF{*J1tGXvVz8 zqRrUAi?NRVil@GKB!e@k8y@>y;v=Lh_th+AS9f6U?C+2Pf9yrUb7?~Ek1mD(79F-> zlww%>D+BJ2{lm+EHzPxPP(tO#HRebtesr+}Ji%`wvVT&-8l~r(6F0=mS5w2oKzvk@ zKX$M1d*r^Io)f;zVY&sIIecI@(Q(8Yt0x!k=Bx4X5uQqQDy4W(mQ1u!)dv}P1mfrC zBP*Afs5e#$(>jR4kz`W*tqgt_F zOSAOcz34ZRDKASesX&dY#FG$|bAzZ#K2?^!C9v2+9^T?*=^HYVDI{PGlt5L|rU^kO zp(=UN-dDJqvMmlbuXubFv!&djvK6fz^7BC`0X=6s4c`vJRaW%W-BcMD&Jd?z}!J|~R-uY2%! zC-(R<0sK;#*zn0gNSSbYr7XB?eGm@Ii2K*cd_FKp=2Ha6kz{5)#X}fsEDyWqU(rFh z`ADXt&tUbE(VR#&&qh8^PUAtl{a8I!*6w?s%d($3M?9Lc^D}7vqia?D4+kRtPv~iy zs%Gg*G5$~TmPIMwcAqZgCufz{LneCP$q)tSD_>272Cd~)!bOuaW!i5x_XsM-n>nO}X%&huqB*!|Zwfz_zqY){3 zw0yU%T_v>=$-yO=Dk^BRLl6_lVccTS7Gnkj+}MFaiAt63e_aaZ}wIDw0qyks?> zc=>mAOZ|rVI*N$e-{pKwK^D+%zOKTUKRsXPeAV%M9lGs&b-F7vUq2f9eb3je$E4?L z(u!S}ufAJ!zGl3_e67{_n!JBU^L6Xk^nA_y7v^iq$=~gKU4zj~yZL&mw`aZ{M2gVS z{yKQu`8u;*X=&`D*wV z=Iglu-|c)oed9LswFmuA@2^kWc6z=h9FW;xpAY`N=j)Io)AO}o(=N={@{KxQ{acu? z_jSGs_v>iB4!P2qFMs@AHKjrzfcfOYW})(B>qzL#$AXQwknh7ydF@zT#g!7uQJun2 zn7O?aqC&Hx<+C;`L`47tdd}1CWXT14^9H%#6Q{KU;e}q3a=ziOLa`exYZ5&`t`R7E z!&h@Pv?7$aY7M@~>qYbRK0yL4(rI!O3crj#Jla?-wwyIbQLJo31p9_*>+Sg&vO$-A zyGiXA_kGC~GTuywQU#x&uFe)RrY=tl8H4fB!&Q&`7kFkpl4MyPrRiT<>h~ZD?zH_; zuMl8zrGB^YrbDUU4ZQfT{n7v7_D9bhXtwP)*dNU%Z^!oSkM7X7S@uU)HLxYWt^JX1 z?qGbb>}$!ajT&r*(dlBj%5ibDaA-A;6Jd^595{{f4rXOWQ?xn9BBUdR9WLs&X&*36VhtbTT3tU>^v72i1xskY&!PwkFX~5{)gjWQ~ zP(m0}E^yuJxrl)PPu4p%aN$J`jXE!?%?mlA@M0Dh=f!AK)i_gCH5V1^$26lM*7Lfl z-;<6;mkl2?J#D}7Hy&wX$r8yJ$*DbDJV4S$_T%K|;TI*pWM7g#R{7?Ii{b09Eym9L zXP6Ks7EY&k)*Bz}F2^z>ahF)l-6i!D3Ned+TPP(Rm(Y^2*R9cmjm@s`%t%{{{MY~& zwND?M`Gf<6wUFwQeg&VAucwc%{e1Jz%a^W?^2g6Zh%&Lrz7T!Ba?MsRi(biz<2bNc zBal_7ONW`tS#oKroy`RpVBa%`U!C~{J1<3&l32x+4h?fnJ`f9 zp|e1_u_e~j(=<*#3aIT2Pm}s&zO(P&kh0cDZSJvL#-&qIz_|J`t^pF_CUahnHp+Ck z9U0ZWBjHa>M?SCIQAf;(-2n{bJ8PJ?BXnux8+a(3)z8 zbEj+0454~*pPcZ>Me@YD^F3!CB&HZy4W{bKMQs|D=)l-P@ZLPNiA1GFNBi zI;ucEkXR_&ODqBwV?pGbw{I|Ud9JJj;6+?)ocHbSUU)HgvG-hX9V_d?7(Ehk&>F-o z+hRXsf)e>dQUX|)uFXugGrLvy2~c0R?yuMpQ2AaOaK77{@2oH0-`!c2)nr*=Rfd1K zt1FTeIBPSt{^DcPo9;X8P4*ODz<1WQ>E3+$&cD_h+1RZ7i&vT6LY|CggIoUHl8ZI@zoS7r@pl-$59mJ(3HSjYC} zQFNi=;z$MiRMxveT_w5&$bYLF!p(oH%AU-0O*w*UH!}5ZX4kRZl$pGhMxx~-K7yH? z_ERSd^um6En-cw-9@${hPETj8TVn?pMp9m?*GfLgT`RajCNhAFo7`101i4a!-`&Nu zBntNZ5nQsUfl~#aqRQS>D|O^XE=cop&RTcJH=6Oyl8IH+Tv98O#rTBmr1SeO$X-^* zS2Ml>8D9e5S=r|$4WDo>4;kEJ6VPsF&9@qehybS*b&7zlh5{g?jH zfq`_{x`MQq*kL3D=VV~Ojlh6Q8V3A!Vep$f6$ZW$X&7wSQ(-_E#TN@@-mEPnHCSK` zU6B5(cr+NFoQHHDb134HHu-8E7D<`fN5qGYCavOFF+w{S`njK=o|~{4Cy@8~dG;iO zPS(T9hu`we%MT_-D{_KBVTK$Zo~P8cJ$@2Bvbc?i#t^CC(}>y>x5j43(EN$Ha#y+> zM^Ee8%XXJUEHf+T<|b#+UyOQkH79ezRPa-zo2hUaWNv#k97zp)UDFV`Jl*W%JUh>v zM@r#x=ABwu)Br&Xl*TzwqHat& z&mZZ2el_JqkDOSj1rz;;ED#L5#LC6{gr)HfyoV6h%y-@R&bpY|q6@XH$Y9okOo6-k zWmW{a$)!DVbJ~6)P925Rk^BR7i#=tuylxNA{+?iMv%g166N&!+e9+n7`P^GI$D92v zFVp*b95?Lmv0U8!{bPQ+`+MFUy1$Pbmfqj{&@`E+DP#7xRABW!*R#LfEqerD)h)|p zMGkjiyU%)st^Lz9ek9qP>@P}%UtfgPOOCbRe+}I{-9LZeIagls1YvcNO^U3yw?eBO|2J zwd*p|ibsgk;C;EvxcPut9uM zKQ`9@cLD6pGqbrAS0(yCe4Wg~66>K8cQgx53(j}f@tu`osn9|NE%@CQ{vyjqx35!j zM9{Qw+74UT$IOxQ-2r@O-AirJg%yG-B14#G8LB(aGFIkUVUeC^MMjB*P96KLVf$V{ z9m$8N+o8|RojmjVw|BOg-+XC+O>$bCen-2VynF z)fB{qAfLCDb)AcmWJ$w^+T*hMA2M@U)=+J&)u}8{_9ihbV&ougTm#>V)HoG}qa2CU zIK{y|{5;C+%y^?qtEIz3@F3%5np6EE$(A2#K-eTzvw*S53E_=u2;MiT4bHfTf5!_#*-GZ;pLA%HBvg% z)cHlzKj(JHi-ND|Z~9(1Qt!PO*RUNHclMX9h}6rueSh^Ax!b94g}zTM_NSU7NkE_g z(kj$V-Fo@#oE$Qtk%e4*>OHYZjX!xVJM9v5)xdN<9gLO-)^*JxxWS{++eH6;PKPRF zn;Sb$))yXWcG@^uDH?xf5TAHd3&}F>GmUKdS{so7g3}lZ`-C3l+>cT z*x0vyBcXPU49#lf*QSw_HZsjL@~LU0RM^w(k)T#)g-(@idsSl@|)zw|Lp?%Te}9NOajM^Cz=6n$8#;JGim z=GY}!om)i_N-j;8{HvCHfRfqpcs$_3G?JzudxwION7SVBSkIzRGK8=&G#3;Y+m7cT&(EVV~*Lo>9Ze2&?%(A;tD}yrN_J^dtPaw(37W7@+?U78wt4(9N|5AZJWej>kF=AZ zUb)sv{a4##B~37vm6FjV$+xJvSU zt_j31E?zGTNK%|#E!LG#ZI3?p$-PA@{if)1e^$I+=vh`o9woxWhKM1S%6gMLg{ItK zE>8TMN{PQueB9_FhiG@zRYR2Kr-V)mlj0{PeTHWLDowLr1vD9&eIYSzQZr&O|nsAIjs&up-Pg3n|)6p~HJCXj+FX5KS*oft%x;uCh>2~*>|FS2S zZUN!ddEoaQiJkw*mvQB7mrl1ac`oN${2Pj0{{~MwT^t;q_c}Pd)|~MWaD8~6UHeH& z@(Q*Qb;aMc$#rm8C@j%74h~=A;4u1Gad3FnB!zu<;$)CkL)tNB9G!8n81c71GH~f2 z{`Rq=!o#zr0n6NU8nm-BAGgaa(=Hcp3AuQ~!Ps@pz9>o)19|kob%%oYSVihdtzN_^ zm)%&}a$v~F-z0pudsg6Q8V~7j2M6izEc_#G`r%%BKG>J|_NfO@kB#1)ok3~2jQ_Ug)449I4xb8Lyj4-4X#Z0@5 zMxJcFFH(hO>wT6VCZ37O){Ae&9Dl4Q$i-yreUSH>vG?TkdHlPNPyXHK>&*|9y(gr^ zO-har0eQ$fi}Qd4Cd513XI}`CLtC~-Fh-gN3BVMZb4ILNYaqUdlp16_WxicT-e7Ei zWaP!59oDDBdyu{rcxvqQH#c<6P?b74*(dK)$L^|z#%iZf`FtrPlZl1=PsuIF;!o!d zEWgL|^0)0@PV>C{TviVJ>E%xvPWd9eE>)Q(9Bd`+7h->~vLiD(F3|B@U{ zD%$9so_~qgGH&GK=nUFTKR4<5XKY+}HO^SpTA2K%J!e#uRYUC#rX#~;d44R%$x|M1@Y77lC^ zfywMWhsaIk=1t;7>f}1l&pW`!NY7#j>EcUQ;f4}j@`|0 zXTF+hUKkFoHC!QG>E%BZGDEbnAKF)C(KAwJIVn_j zLt*4$jV{v)Ld2w$JsfEk1FVaeiGX!#J+Vz|lCSU*Hb+w#w1t-=3x#b0IWiQDR;sMu zf~Q$0U6y*+3EBDhGDLu9?{ax&IAd@sK#tXaC#M$oVZG0_59-bdX{1FaFkkxPM$p5 zvLn47usg@%8IH7babwjiqPN`Oa(cn|l?~bfTw6i@^*fXCSptTvOll?(*RyqBht*p} zO4s~gaZzMH`;aVV&pZzA?SyUd-6rTqTv?q^EqJoR0Gy?vT3+;oYT58ihJw3n-kU33 zD!y}}T5fupkRy`2JY3BA;4{tPE9O|2fhLk)F{Qq!>;(gcopV-|%(a*TTEjfu69!{& zx@#T=<3A?3@{J3!W3POUKtrJta2!*S4}9S7v&24(Yp86aIEJ>kcwtX|D_*eokRRX# zBA=10vvZ4=s*ZBj_a31b(T7cm5F4ahOEzKMbr;k?Cy7%$Adq6W7|QDRP*&Nh-sB=T zzuz8bCkKd%L-d$ar(4){E6uxMrP4f)I70Im5$`sBu-`cgAp;pwJ&l;MUHu7CJso(r z5|`SiKpHJfzlXSZvJ*Esb#3k<{3B2neEvr#RyC}vXEySN}vYvW0O(2CnDlsPf zE?BpX{n*bGoFN637PsA`gWnO6bQ>*c9<%LWzq-xMACc$!cH{irH}S!i`#vV1sC3aHHMUh*#$* z6@}ObX3ld&#tCAoHN>xRX)eQ5!nk{ef9S`Tm2&~|ja070dsy$pdw5&pqG=qA&n51G z#(Vf&;ynb(IT<9Igb(3vBBW%{`Oz2v)s=lFM@&rf#G=Mw>sb@-DS8p23U-t*o5Jfy@I z?WMv3WJgfZ<6Y?muqaFVZXLvD9AMI?`NPeGcrX|D4l&r@!fG9-pU>Z|DX&$seO9`G@o*e@gl!FDUbf<3O371NsZ>S3RIF<43y# zI@C0CK!1SudO$C8_51(f=X2TE4Z>sWD_l58Y(f|Ct=&a&qn^XN!B8v@`-o$qr*l$5 zhGyIN*K=@+@59MG7&{f2B}_aCLgKl?d<-;)^&b@z*Wy(Z7UmE^kFYOGf?eCAM~!O% zdi2MMHqdQ}oYYyD9R0lcS*>&bEQdSc7G_&rMVQA4xpFz&g3#kMeHxA$NKbVpWZEuB z-d_wX-T-lW5#sde_d%TIdx(?7AcZ&)le(Meb|6k0?E-r|IIf+XC=v&bax2~X;L>N{{oKLNqQ3bpA52b4<1)O>mr=($d|i0 z^d!Q0?rV1Z#6Bz=oa(L3tfr*I#j!s6t5@VaX`L_nnLGHMJbI{PbJY`>?g=hjvCQpS zJ6u>z?K{cyXz-3^VSRF8LW%ogAysJc&v!$elj|@OzXPcPatCXGgw;4$hwWR~9Q|a_ zrhn8k%pCtK>*0oW^ZQO~vb$Jqk1^=7X94N&??EjDy@{_Hdv;l*OQ27q-GS6@ zFQj%Fz1o%9osXa=AAviI2Pc>*`DesBf0BK&_?JX>V1ewUy!eTwtXN;Lv+Vz8-TjZe zD(ip{)B^&VA!7)XonILKmkPEoFFVpyuYB-9{5E{BdnOTl)BZeit~R$n=aB){qcJ&; zh{H&g;qafkT@NVl{FwvFajfF)A5ca!Q9C%GocMaj2b5m3jO=S4u5M4wwWIzT@O01W zX0hpJxpcFR)x7;~4%l%w@A^l_-Mry`)6J{6I^FE3f4yXOJ0bt%s!L#0a>fzNxvYlm zAAey%oMLT7Kkw3^Au&f#J-n&x)f!MNFxxI;*`_XpP$5?ukazBCE}M zH>=G*`0Va_H8IL9a=pUO;L}vW+SOR`RIM>tZ7l10L zi_>t@@wxT}ANIr4FBQhTWfik2lss`$t`%c^@D;wACuuMs;#&ySR+8CT!+0~evGWOP zGvB=vQR0ZjG@+2BH?Rmf$=hUXYXQQE^f4!VQ?&fBdI7?X1k{;>Sqo6;->6nhoWK%Q za~6o>{e1b<>fg!0qd5%^Od~@rE zB0ecdE;j2%!ICahPZCf2*2i9i1M;`8tT*br9)%MEl7gWK!vanbP#DuMRbR ze{zwTQr*vD2cfHVrqloZS?0R>_wdJvAsIWruxY5ykv&D~EuZn44CsbvdCfc-&=|n` z(AC=x=>FUt4yg2(Ix83bz@3#VbwK@Tz>{FTm3wwfS8@Mo9QZsJ}T`i8A` zlQ_C23KsA0uFQ}5G*$3>8t|;lM~j@5Ia0P-w0w%T|53F3YHj}=c1Hh)JUioX(|+yN z9k&0)YubKgx_#kvQw0amKynJm&}KDwlaL)kPXsHy{&X5yvtC_zmI!txX`CDm_u900 zk1$~o2j|DI(}xMKXEQ%p>8pMd^}SXZf2@>^W~o*Q`O8L0^4$6d?GiwS>XV{ z&REHW`D)(hK3d-Yf0#7iU9U@piT)=}_DtNV`hgYv+6%bzA$+Zx&h1B%psW1r7Om`e zTAB5PR+cc84H)m4g@LBB)K}ihO4F4ctLCs(k{hn~wK@w=7rLuJEap-LGib;@EK}^$ zYqZ#})5YG>V%Jm5vsk7b#9~>lr)9y+?PqW_uVn@c7i4Bo<}ZC-22YPviaS~DC$aL{ zsuXv>N1U0MD`O=(L*hD+HdOaLQUzN7V4hBE?0gEecodSksp!C}m>aecY9$P=Fs{n% zBv7Fxku{#cVboXalR2kHjjWGk4mS$ryI)c$e@bJ~@>}O9l;4$>Gi16nN1@%IWV#pc z44J<3O9Su*CDSr{EzDlCZDwzfsn^Wjk)~c}_6jvo=~PqSiPXm)uFR@TX3tdS%pPHB z`&;-NvWLI!<<8#Me3~j){bFYJq}XCpY*o5gCx)6Tm_xBmRSkwUXt5R_n4Z0n9^HvE zi|Jy&qnN<#oO+o>cm9+|P;tj+%$ik2Kk(gDUy`m5iPzXLrUca=v#|&NhGoqN{4K1a zHH&E`G=L%OhB5K%Z}8>S!h2i^(#(%s`UJ9_mwmM_DXiEUZ@-|Ewut*^`3ry5N&6pe z7=E(Avo#LY53F~#c(#VG<`+D5w?{IrMX2*msZ-d1sZyV^0bh^x?Af8Fu9@Dt!osYY zJ-bI{|EwLZ6ZIo{qLvko5Bsq+;MqTe4oJ^{?4Qi%_n6NM(w~dXf2!c)=b7h4?YG&M z{mleDF^>sy=SS^lKkP@28Pd}RVuX@q5?5IF!oV?4$BJGqy=Snn6E&@Oia4L5V1M2E z`r-5x!PYz6qcRT8pKaQ6vLOq4roCfKdq;<2hlgS}vr`>{M}xcb&qMNLi5*PzdS^j& z+?w($1XE=mybTK}7-W6Ix+82!w5>B11#S7^F44BU2+46L{mE|HOqocEhDmHN$`}*3&-1bXZcD{$GyB#wk0c_r3Vs1*1Jky;zNr@EzR&%E{x=r zl-YOF(4s^TGpP`Mwt_M4@K;$d=dx%7^xEA5(?f zlwRHX3bno-PU)e@G^K8M8)?+@gQeRa8W}eCo@WcG~sd z$IGHfSCLfsX3zz<8*crFDtsW~!}3805cPZ{j8Na6^Ps+D=o`8?11~TAKp*&GrMNY0 z48*>wtWFV;cT;qd*KbA;GK{(gup2Z&|6n0EkZW~LIGG8EH8u-3OH(EJ!_ z{)t)H%}>rWFHIxILb$!hw`qDbO?N9!w~QV>)u}Q%6|{L=C>|-ClgkG1)w~ABO_C*c z!$;x$0`Zz+IUNOaTPI_g>*VM;xU?ZDp>Dj=R`;a{T*c6#rg#?LS(o3N5jnaN(Ghc8 zv7<^vGnzGTx*Q25zUj9jA88E4?-LTH?#G;HXN*uh9b0iv zreh)tedckuQ)yW!wogv5a5)%fXIdbu-Xti-@WFNQrJWE||N?5_d6Ku(;UWLWetnBQNSmbl?62z@@Jb=B=gns!&7GTwq>r7GGtG;K73pyd7kX?ckFA( z?P-r^@k7If;t|zf6&8)6u#g-c(f6>4Y7{L*qwXJ-)|dP)vqIgiQ}~#>N_FdeLm2)A z$QF_Nkw}|(<6C{VZ)BvtsAK?Doyo4K4etMKrX#Xde)Xu^iS$;Hv{}Ae1)O4K({8KC zqxPl}-``eQJVVq5PF(%16M(P?Hjp_Wqrar`(oxCLc!_0h4FwYV;-wd3hs2)41QUM} zBd-O)RQnUR%K(kt-XcLrfrV*(nTWx93vkWwcP;99hY4aszQ?geanizKMKlQu%&j&K zVOxV`sY!PyD~cLF53D<91Ew*E8|Y-TVS* z_~zPsInE;7%!Y41Z;A5aGk{#Qyz&pqiwhX5zsx0&%%#(m7ao5$7vB)%QRmLW%VrK% zu=T>M>sdulLbDbe$w%|w;E#2}2JgvAcx-bRa(HYx<^0Z^a+(k)8y@=-K1>y?Se$jr zS?d$oxQ6McJCXcA;^uxF>Z`@pd0n1><*(9Jh+=Hi&%@V?nMd|27c){PxP8VZ2#Z=> z=temviG)#(t@N7QW-G@sI@j)j#8ff4P0pv)r114>b^EpN_SrmO!qX-Zcba?0Bw}^a zfvB(cf-XWMZyo^C<*WG^dGYtNHhs76CUu+jnG|uUWB$8Q&3|PH2IIwTVn;=K!$`_j z|B*h>u(rt1P#Fe)zM4DWah#Bi;p64dp-b;=l+P1i!+2@@E2@+KAY-z$QB0N=ib3H< zemn^`Hy!@z@agbRH{PAiKP>kX4XH`&3m%i$wZF>XaF>`o z_eU3x@0>~ORnwKoIa?uEW>4%6jh!iKsNkNgQjwJSqF>N;7a}`JWndR?lM!3}J-rl4 z(>L8i52g8!$>4JSUBJW5N@)9Tl`!`XZ~}>QQBl7Z=@RVogFNjV#3M89!`V9W!%5YW%%p13?V~0wY#&Y4(uqWbMS+xA$R<&so=xIaKd-Dq z2td@0kp>@b7L@qB97>|g#(D%oJ5QK6-uH8<62YRCDxITLsfVFM_p=rpI&^Y29Ri+f z?47V(hvGZ~#d!xKeWa}C0J~`UOZRlm>EyesO1Cz){4q?76aB9~S*1X;RLxjP!L zuKe%ZIg2L1Uhq5I%n7u?{ct-*y)WXRG}Gf*TfUl$*pOy@`D%vA zZ{d7&jfKxN>&sVj63@T&8e5QTQ+-+a6uQMiOL87S@A*4jXm4->2jecZuMo3xRxk^# zLcp^(f2{HEdKQ{W33ZXVDqMl<8bbXb&h4_$h3k0=*F4%x{(p^`HDF3-)ClqgSTU5 z)*rC7B!#A`wb|#BKzXgfuIpWH*Y(hQ&E5-#65#?quZ+EhMb8=W6EH*D6uwvvo+*mly=Egs*NpO|uA z7C+%yPXC=#ImCi^7#aCaAodmVonCcvMqL(+U&9&o!-@HNRC~`_1jm-#!bjiI%t;n-?akc!k_~cu+hCP<8|<9d zYV&vOwF)m#;^76dPiW0ok`@W3&FH1iG1rWL99V`em6zse~ zHSD}QSb%JvwB!A6SY=R-P~wq1DHtDEjQ_m|J=p0T_}?SJ9f9MLCn4NTRM0^}I4pJG z&&bEvDG=S-dBSDH3VDP|C4iSP#1bjlAQ7|BvxlSftd->l0Mb1hNX0J6ikAfzzmMDS z9%?~{Tmr5zHN4QZ;!aBVDv@bL-~Os}d6s`8&3)JY`V&xm16c8p52}HrIP7amS&#T) zi9G7t;?Lxh1!MJD4JyW!w8fv>CQ^XKA8@W+;yu^4_&auV=^DUm44Y8$e=^-ZT>O#8G?rO}}H%Vex45m7#ears{>_fQxnS^ZVcn06S{d%j)H-cSFUescz zXZVs<(*xum&Eda@EqHX`lAOpb@ZwAC`;5;kGTP?wUH02)?T@Uo#@pp9IQzZ#M?LQ@ z(%4_ry;!y9)o8Q-tuBU+}(s-I}g7Uyskdfwjtvp);8 z^DQjUVRhaG8gA!+rktqsi*ubUO=HfO)rs@A>4c5#Z2eEZAh;&*)7q zy%DF3#4JG?4t^A(I3yH5)#2P$=i7^iy({R6|`V`0CP1?2LLe=+d0v0WTImTDp5 zBSwp3`%Rg!UE(n}*ig#p#5Wz8A&~Mr9nr?zh?yOgm>cN;9I1(UxlDxPhZ>u&G(Dj? zsc(fAG{G-Fq$}g(9$H_aQ45YxX1{#S6rk|stuiNg*d?kB?vyh^ROO5u0RszNH_^Z| zu46>t@2>K|F6Ri)+*mD@Ln6vIW8JQY0wRI{t`Z*WgaRwqU(1b;@Q`pl@n{`ILJY&g zpe8>UYY^GAhlaNVq0xQCJtNqM6!ahL7VPtZrdxFt51~Gvpl*0Rt!_a4JsB$fl1Tfj zshgp_6f9djzC`JDgE@ye^tx3-KKKm1ZjG(x$c26&82`O|hkOd=t-)6lROuDA;qV(0 z);E+Gp7Q#y`peGB4 z=XeHi4+^1??HPyFY#7GWaW4@wfJKL7gJL(hR^!$ zQmsD~pD7pCVw!ioTzCsTpAJY$^n77)04|OBYL8=cPfC4H%)ndN~+nfU=YyG6}d|ce7w43?dzzoFjD)CS@&!*Hk|( zMRPLvxPm+PJmTVG$~8)xijch)JUg6Jcz=o*o=~5cWO1PEb2LABtawEMvR+p&E&)Csk3t;`(V-q^fyPA zC(E_6P)lQFZZ2W@X4Qd@O{QY@yZ@A-`4js2N~)@T-E+81S2r2)mZ_@42vjytj_;|^ ztT8cv5s_j*mP7Lpz9k~n*0ntuL$v%y5386^Lcm7L2i>OPVzDvw%^RFA2{u$UAHS%` z-h=Q9B;>N3#BO9Ik?d{A0zX#AfvMPBXlCLCYGkT{#J($yAhAB}3&No()Zhvd=kxIa zAE_Ymfv9V4IGVOo1&baM0d2i8_-wXXK5a`0Trks&kE#>fk0UX~m@bh#d#B+WHTfCe znNK((iRURN_`CU#IM6b;S!)DyZ7N3?hCRjv%Gh00Vkr}29bW)o`1XK1J*WSS{b;4L zUM%Wll@#hK`JAcECqs6Qul6zaWhnNNuAwhe{+^M(p;)7J{aThJQ|v#bGS8Q&rA)js zKUUe3?Aw%X_0>+~QDybd2(V+aH3wsw0|}X2owz-sR6i}z?OoawE+Nlfy4b(KllFXt zzf=^p$H{Zw<0}HRzxZR^a$mwN_lrQB*rn-EOo5CpI8FHd3tYl4=5SLSX+Aoe*cN|Z z?24L$qBc%Kq?Z$)DG-xzo8&}a5$N-&MBL<#us&bpPCC<{7>0^?i+w38>x&0tA zTK+C#2ow>Ial=j`V$f`a?>~TB5!EV*?XD;;N)~WS@~7B}q?p47V_O1csSM9Bz5s^I zu_;)Yc^rTS#xZ6GK}|KW1j3OZy|6VqxCeg+%f{q~FLq?C=ZK7z{6b;!snc)rsW;nY z%5Y`)E$j&n7fFI+Pmsx{?gpI9urmCP}%7G@Uf^_su)KP&mYKzIhFm z@!^F7T6{xW>ShQpMkvrCe{8O#A8gdDU%7#3Ls2lM8KR!Zh1#cKZ=XXQz8VRNE-1RN zPBXtWYT_4Su@9#T@>F;}MpsAerdW0xjaoeh?R5!B6)_Y`>isD8`y8w*k=x*jcw?o}cueFMDkG4wPI!?B$4x{l?tsqR>g*0EIIXY_l7Izszo{o+HY zKt}kNUOSlm&BUruLe|xdS{**$5jFPVaPo=4d)wKw{@9ED#TyVXzL?pw{yx}2KE9df zgecgWJLzZ%117le#Kx*wut8O`8S?-@s#e+DHC5Hq*_`BWSh{RxsJ*k9jldD#5Erxg zYMLn+j2CH2(ZBN>RxD*7mSx`v1)3Qs1GAcS>e{YcB&$hnSKgFf^+xR^eE)j;w07r9 zA|PbR7khOeU;MM(%_C8~=bHxxRGo8^G<-}TaS7n~(mv^%zY^F@d<8XBJ9xYz@W5(k zjacoB5!l+r+2e;q5pU>B4;)5v6m{W{vEdOoOk63$eMt`_Mx3f)haf&J_IziE_8fTE zG1tPoJ~2Uf*GxENP1E7483Hl$CvN30ZzY1BoQimTmXwQaoD}qC)7rSh+OE=l|eBE>XO_j>(H&#{WY8Z0iGX+(^Ozxb0 zPX~eSdUylfg^D7*?8Dl}xeFDAGf^inIZD0+QbQNFqfmF9#$|L}u3gV(x4QbS4()od z^J7GQH;B<3xru$5lxqeB3TK`{8^4*7MuGBT0Tz@F+W1@J4$;QG#-s44pSoz{P`*wT z1kjR;S%8B!F0|TGjh%8DImp06S`_i}kWd72n)jpaX3WiWFhDeKv6#_QqsF zD$-6bO`l#*;9ScJmBoTG=w0gMHmwW_VB#EzvG0*p9Z9_Gyv*6iSJNx=X}gfPq1cru zgos#;Lg=f`6N-^SUFVC64V*3#3B%k9l5y?flV2*vdD{r8()=@RyXQ^mNBX?!-smE9 zZ+3j%r2A4|_IZVIri+VQIh9~8HC_Bd<9eX) z`4|km+KYjkvf_HAW10DGe-bzcBuEE(o}{EE-Yz*heA4#F(M8L4xUQalMaj`C6Ww)H zLc8RDzdLJP?e<>Bt=66G{RQ{bIyZu9?dO_kjRi&Gf z&vO-?Ai0zuMuhme2;77i&oCG~6Se9dDGXzivQL<9^nJSO<2{%7<2?egd~??sg(ce> zksB~;gyRM>!ubAJm~IKR*HeyH5al=R<1+FW3H&7X%x>VP!<_l{>iZtk22|l!tqQ;U zg?33yC~BK-zZHtTC(6x0ZKFh{X_Ck^9wtLvR~Z+fY1&8_tLT+pk=#>F{A5KrtI58G zazv`>TnwgRPy!33W~l7j9D_ekaX0Anw~37jjTfUoNLyT)C6{`dG)C4_m4ZDYGbM0p^;C4bZ%7~7A9vI(pQAxn0CvP9lW`U3YY#%m}21=}{noK4pMo-Y-x zGw&>d7-)7JU+tH4Tb98w^bg2x{DngHah^uY*N<1o3YeL`nH*O|#MZ;u*jBRS14WpC z&Ls6uv}&dvmXu9QpM+u_Gz7?ggNBcY(w!=LsaVoH6Hn`zD4i<$F_JV6l=1 z8T%QLpAmCtlRp#HAikg2^ac998d&^QC;u}qI6_(^AKh5*+kMYL3p5HVXpy4E_eJQ9ykwQH z<^|xV`XwqjYmKjaU`-%C(elS`MDaBdlz(HZRJNYVS}DnndTL_ZnAnYNNb%ML5);=5 zAj(!n(0d#&k;MG5y+A{G5@iVz7a1s8hpFOYrp`haSB^3cLyP{mE!FP)7K&Xf`Hy%J zihTv14=)oJ(lw#@wZ-eP<_{+&6Ot8-eT=O-EjP0_~#<5PUgB z$88!^zo<2D$R={#q+HM3OndF^Nji$pRdb5$n(})u;UH&SDd@qqgKDp)mXq5K)YKm* z1VKBPdAcBIqo#gogh4A!T%Eq6KoUFf?dunI`!4kh-Nc|STK@UZ6#*Lk!n*6eg?{0#n-t%5pkG*CZ}8nW=og-T zRq$wm&z*oD6u8UfEtomG35R$MVo@nDq{5%xb zD<>XL&=3@kM=QSa%{w8#qWZmtit4S^kzW4PipWQH58LpI25Z8lyX92o zH4?XgN+VXKgqb@6PE(3k>wy|Mk7=alGDZb&Dq^#w;Q#FR;clqHsJwK?pO`Cet!HJJ37EgQA5l$WB(F$+;OnkTrE-Iu zVk?}pFCHnIQ^RF4MoSg38DqK7oIb`|KcSqcEAUYbq5)JjfI>G{^;_6l8K(s4AxW@w z#MgZ<=25%UWF)WBNwhiZ^>sh9&?5!%C2VH9qFww%gm`f^wnIiD+R^ZO_1>9Xzl`uX}Q+LqXD6a(j{+^xShr43TUD5 z7=&5}@s@yb0~N|nIGZ~zb6~yDa3<%%6=OY9QmyxZyO*@&f;%$Dx&SW8kMc{Z{l5&{ zIw(BES&&5x&pJrhKUt86{TQ&`vP^cfM|$L$6Z2)H(Qa8J^u&7TIboVK9{!)I5Gf`4 zzf5vCSlOd)lNal(rO$&;2>H8|e2+Ah8#%^4i97p;{7Jqdi$`9`O3aNM=j3#boZ=MD z^zdh|IX#TZ#8dB4H}W99PG$guM0%))#-{)5Pa{oBFE_JrMVJqYE%-QdYE;W6g#Ip|R zZS+Gl?O(>vDoRv>9}k{1z@OOr&o_LM@?YNh7Gx8t^}+bf!s!VTbMO~f;8iiAs!IVw zT>Bf6qQ{GFsfZj+WDuCc^OyVjh8kRShZ3DYkdcP}kGgY@kE%NNej)(^qB|&PtX6}f zCU^s@mWXHq3GRUz#VQp~i>0SZ@zRPgBe9AMOd{;FJ1w45T6$V-wC!7LYm3KXxfD&f zCEkM<#7hP5dmP0G8UiADzrVHjToSNVPv1Y@d|>uvt-aQ>)_T^np7q=obKjfz*xoK; z{M6qBf*YFA3-bpQ=p*n+jJnyPdEd#_brD?JazUruVz`ZYT84|uNNhY4kK&wmO}65Zz{f2%~yIC zr2Y=*5$D5P#DmBfi6=QJ%7i=MpqyFonvCIA`8yF2@`))XHq}=OQupvF4Qs~pKDxJJEUg+;h-T*oj99ZEMXVi4U5td1Mpv#d*yGIrF$VMZn;}FD2ja3XeMP(ZmY{ zn5SWm^Fy7>fqGKP>lpgVT{X@=Z$nICoQSUAF-yXgDpv46<&#_lN{M>tMp4|7= zOG?=FYRF+f@a_=v;alDh{SWOG1#cXzPAv#oe_kJ|XklRQ_#vIL>XRqGT|aR4<9{$8 zD_HiIIKJi*j<4xsU$eI0)sK3UIdo0Srd!~$o4qrvzYeM<@#_a&(^NIaDyTMzE0f?A z;ARqwu4yVc8LqverTUtdTLu*rG<%0<()wK2bd?gUzqU}3%3{xu*w{auyt)aW-blsU zgdkvKwfE!hh}k8K>IG(0#oAY-D>>{Vlz4)W6mtr_`>HbIv*Dnya|#;(jSm^wAA)6O zp!Rq_`!^z%7Jdx*=#EUpQzbG$OQd3#>YR1Ke)YW-TbbtApj>^UKc&96VvEv^nu34) z-k!|VGBd0@Kg;~`1C92WLrA$a+Jo%moF)zT=2`x5Z{2UWt3GA8{V(70e#w{c>fnkx zb-!Ux7lWgZ+DRs4&yi2|j{gS;VG!V~iPM}B_BBuY)ZQ{!G2@D z^8C*-=D(i&DPyit>T`W&l)8s?}jC)UIzfIi`CZRbFBA z9owzz^fo=oinkTxDa_`2~>U9atCbNxN`AQ0CN$X)Pz!P$V*8r zrzQb?kpTX>fW0!0of2y`c524LR@vaMCQPNS8I(3dg-oT88Ga!Tj;mWZwk}}4(lsIX z0%Gb;_l^W|ADq4%p=!XPq;cZZvL*TH`xn-|p(fsz;(@T|HA0Ybnd;z2dCPF`{wF$d ziu9v}oo!6=I3End&_U^Qa{EKbqND<4;bfiPx7$tM#`rea9oX!UI!pycQymt5gp|ZsHyf4f&?5V;;#Az_o%P8U!Qx+R4QSVVP^91 z>uo(|G4lnUg6&8ifCpUf=e_H(CQPedRag)|A5@=oCV1w`-SNWGP~|$5wY;z$vs-{~ zUt}Cql8s!jDp_hSNilAA@*?PNa*5s;+r;G)_13+T>G4XqV!PeEuXiXbpkfI^WxO_A z@uJ*l1U_0dqNNR^lFd9&wIUKLBo#IfLlNs=vE0b>ROQ zLB>%uDc^uKeR5Xbg8vz+#*EpvJ#XDqRi@7`F`uul)!pZ z8M;*L0JQ4(!$N?9nAX~yBhlzh7~jjsApJ9%qQ(kvYYf0oYE%rw`X5MznH)V(aDMYL zv2etLNe1TWhGk8klz~@->gSB9m!NAx^ENb6q1_c}wCarxHEFtzVEk5n2f1wbPIV>Q z$Q4{7PG_iM3wC#*=6$^)?$uC;S_Y7TdQHR9yt`MZ@=5FVE1(@RC%9M&R7qq5T@ffD zhS#dU7sW135ijj)_XC^Mx3Edo2oe}$ZfybTBQvu{G-1oB4`q?G@T?IKCRXLY$D&7Q5L1p@UqjkF&0rt=8rf~8sjwK*wmMmet@TK5`Te~#mpggOR=`r5M*i}}^#EGnGlco!+Ba;no+vL)`GV|{WmGz5fU8doh$WaSVfTMx9z0a)UR`;R?>e+%4Jtqju$E zH(g=OgcO8W?&qQ86lIO`2;0vZX4Q*n35;RWN9MI3(!=^<)h|+dW=-??g}XP3Ul0P) z(INLv6=%pdzOA_9o_7{hTmTTLP4+g+C(;zV@&mvfF0{19QS#eX{fB&pw}0SoB6ys) zyunlHN;Yx~4F5NjN{01@@YZ&hsGd}_Dsx8#s?&(GTyMQY0m)DdYi@RLh;5`hWre*e z=(zrNY#FEqQy3idbV`G@m_&;T!6Szf%|2^Qycl zXNk9bfjtD&p)TZ@J|#zp|Ge@?!=D+xIET#MWV|KQr_p9DMW$0~SKM?`FoD=8qES^3 zDeGxu667^{v5J4@B%kh7s1zJjJz6j{BnK_iwLh7Pt{df3^?5mV7M;p8l@ zV=TNM{K+ky-gE24pBO4wyJVvZ_U->~k_yzP%xFPh_cgkC8EU&{V7HUEzQPvN#_i-W zal85T-t4C+NvkViXL>`F;yjwwi${7Z9;(VzR_CHkIcX|vlh74guBD_N<}_gG6yleqt42jFBxRRD+y03A;}eRQdg8f z{~k1X3*jZI@fNvHz=fLM?0r%4tot;ck;3ia!kw8e&aD4I|1M`f^z7eE*AfFOzQ(Xq z*sQyEiZIDHpq6w|Cv6t62s|`hE_-J{mcIb}=!|asFDH+{|GI0;*Up{#(3{H3js}rR zU!>R0oj1X}6wUNsZqdtgcp2~>s@ldoLJSDAzljTDO@AI=Lw|m6Lihf>mfgoc7-yO= zl5PsSg!yu-N{Ri;VTxA$WhaXmzC@ueq$Ly!Jv=G+3;iu?9j2IQ zu|{vwNNM84Gl{Ebi&Lz9(lx$0ei#$7oJ+$t-=*PIV}vh<35@Wc%9)d4Fq1PULlxag zj*)EY3v)dib|)>JeS+K#LPI_vEK*~793#~|J!Oj+RC2I%ZR4!oA?Jhi@rtk+gcc&i z0MTLyEd))BV@~3Qv9=TCr`Y&xZIZ*tn`;S zk$Op34snlYdbvY~n!UF%9F{dOAzNd$@C{)?_YwnNK0RwYnhT@7L+)i9N?W-$_85<` zaoyrQkpHp)1J50FaO_Xwv+(VEFFm7LM|j?$(2I*8Vs^jXbZJ?1Lg1#+mYOX@bZ;G6 zW|+LS-hvRa4A(%3ycgPGZ2Z+V>dIWl(cp#}zD*zM$7@WT&I4Two`MohrLqbrr%}j2 zTTS4xELQqUnpJ9Oc2_U4t_r`b`rk+u z)MEG@O@Wa6RnGa=wt-zwux%i(f5@`-MpYqaHrocnG-R#JoD(P{SU-$GaAw1m*)L=T z0WANl&&?@L=3IOt)oHh~{UB%*1bXME?-hJf{T;sOS@k=|=U07zSR|TOXoh^>-YG6koB25a(mh(N-d@_Gbx*#wK+=XsmP3ZREkS?1P1aA%XZX%1 z-7kdai9P-Cf=!;c8M7?2A**buvVMjuc7q{{tTKsFH476zhj$)uJt> z`YF>-xqgQ0hj}cXdoBKTZ_re>3tLcBsYqrj03&KQ8%Z#`dpFGLT~*%^`;OhU79V3f z@wRpvazAIgben1LG;2mvjoD-D7JHN9*K=Enn!GJV%C6jF)gPxO6}ETF53gn5(H^0R zDNFm!Ssi{??d2fXjkQcr?Lyh6)I3>YDtI!Iyrd|?{-&}mhIDPMhR$kOeXM%=6}y5> z@4XsY_i}8c24MOAdM`V%jaazrAhezKypM~4WM&kuhd3hCnl$~1ld<))CLT0~cIA#) zMfFXwi|uAZj8$&pE&8G8qy73pd&zd~9?#{c=G@%wF>P1wjGl@eZ?1p9X1~1$*@?BZ zSNiDw0x;C;I3@}Ri-)P1zQOWN=&yTaAUC=(_fFm9jfZ-sx{FBO z(1TNI8_fpQ`tv&NId1okL)A>seXHRsLogSZFerAG_ebKI*`vndy>~S4+_5Fj*g?wE z9Y3swLQ+HSL6GJ~nzYC)LMs;1HCl&$6uR!o$uOUdvh%Xta4`$2f)ksCX-~!>o`p#c z@vj+&__h$|7lsPk@)xG2ZVOWrIY4L*Fg#fC^6Vi`rq9H_2it+lr)HOn!siwn;@Jdo z?2LcBg7Rkk=`+B_;{w(-A$qO)7g$ijE@nKBVC$s&r4x6t@~)g@u7<6@NqnoQ6g+`)kS)-6b2AaxwGFnp;%{B3DTuBG!929i<(yFGl>W z>*uC`xx;Bx*rB&rQ4Q;w48$2$VVoixHRb{3?BR=p3j4{IchD`?} ztRGueYSp)JhwnAk3H5)|t@bdkwlbz!!lrVjja462qO*9Rs;My2E_+4ZX0ny-g8?KN z*M(g|;(LB^emPif8&Bbe=_H4o;}BdUYE(NAzcjHPHmDtL!!J!C4U=_Y%dShJ^PrW5 zWHrWjPI4;mFgbCOiJh(~RE>Dau8Jy+mDEiPi9XiCOU?q(}piOajLugq^g^EKV-TVV7-} zYfNVNdNO6fQKSc&12i_2hbymMX4QX(e8iV$vc433i(P?o$!O)aDvd@=UPw4y8=ztv zWoW|zZChD(e25Kz-aS=)3L2VXzl%8EEw1jU)zA%4v57evxz8q{|f|P<0JT*ZB*|gc-ILMAT1Pn)0Itv)KL&YgBlFDP@D}MYlByFfvWwe;W|DHg)K0(*5SL(IQk;ozFiYbD%Zu(kt`M*5w~vy=8#S{cyWytk9YlxGDnJ&z%uZm zfX(*5boH5$sXZ^hI;%mkTvOA@K-7x`2b!WB^kQadQbqcxz7!03RsG^m?#;SAC0VD7 z*sKFjUNgNxW98CLzfm_CT9BQ?ost5&8X6+HRhfBwph>KmN{5>=drac#Bz2#}=lGfP zCb2->ZxY8%wtqH>{agU(`qoD;(Bb}!e#(pq`(Kg%wLFB~sls=`YN8X4-Db8mCfHcF zX&u`2a<#GcgKi|&m9uF$4~n7lOIet((lBM6BBR)C!4wyw{(_NYia)`gH9N(d%oN9H zmMQK->QC{9&ofi}Zgs7E@-(Q~iM;f?M2;KfQ?~k3F&fbL7OFM=_;zSaMj0~Y$7k(1 zK%ba*D+YP}6Wy$>mD%UVk-<$T?mmdOdSw zs$hc99Zyx$b&rUlVVmYDn&ofak6Jjp1?XrfC4=H+A}LX+qkAN)DnGeI$;Wm}=A$OH z2o4Apu2~1Yz02~;2b!fO2V*^4>L|EDJ^Lb@<5GQiC-ykUFR~nkDz{qoZ=zEQ_mKZm zbb71FzJGoZl^*$TH2If)*Qy_EmQF*YQr{BU4CZ`J8f(?xMINo&sPBlRn=u{=;B}X` z3hYx1(_q9NI$!#f<)-<~`*2ueYcZ$Edj;xl#>#IuQZY3b87flicMu@LXvPkDAjq z>s55CF%GQ942aOKNd0?B%HKDAwc?!;iV9W7Cr8XaG?cusaBMPsT0!+fOSWaPWxU6d zWhbFMBF?+UsHkf_Y7TGLm&NE@$ajwuCHCZqa|6OoFwo_bt_{X^@Evbvr8fQFi$md2 zY|d#-eTN~Sg)?-)=wO<4gR!TCt712@4wjf$wC<#3?6JCc15Iw;U4#b4x}D=&!I20e zkL_lSZ+@*v-V^S5bP$3N_xh6J#O~tgWr^J-u?Lu6aoZIS8U3A2U+5W`EVF!0o0Vvz z+hjFkB~GJ#Vdp-r`7++H7CcYC8l#=QNLva+&L^quys^8UWQt8Cm-qI|YKg!lxE5;W z`6u!=D1u&Z!U;4|vDbJtWaasYl3rC@;liBcKUDdgwcxib+2IPTrI3{gX%P8`D^obT zrMijyk=DK=(ly+CG@p;gCyU;r4U9c<|ErJLBM%iH4P?3bESQkG59AurG$DD`Rc!Oy z5deHoAA}22)B^Cv@5Od*ZOjl4GR8-0+0fDwjg#D0)m9R_aby&;Bv8@<~}Nc{>5#bDwm zk%!8s9xYVH&CQ_l)gbyDAD7|drJ>w|)X4kYIhhk2QT;GgTZ4*IVTw!`UacT{d>+#b z&SOpCbN&Gd|ITQkZi5&QRu@5U)qhOqfX)SkLm~WK zp+T|Jyupim@I$>x%IAl6AC|2SfiGj7V}(XMB74Wh&CRbKRM{N6EC*C{uv~QAiDHdB z;Pie)yLG-@n9!&0gq|D|60(44`s$|aT4OaB=Y@cPMvtMWB`WGF!!Tu&kA)^xA&w*Lgj1WY(`}lzz-x zyR3A?k3VPDt7v6*?eXnzKDt-(H(uuY14~(6 zfmOKVtz#ck8s+<)f9?JDC}Wfr%+N6hBrq;HrS7g_=s|+FhU#)Es zvorb^uWeUapLcCLc=Nw*ZF}<2FR->fz(?KIHfL~;wXG9G_)StA+fu*% zENk03avgAO`#lKt| zx_``RjMc~Qo2+rSiqlSuk&D1iapI}f@P=<`rA3idO3PCHCi7|vODx>(s3~x2cd@PZ zInm#Vw85)d3#OB6Y_jIG0@=WiElkbfS!0GqT*H_8i7BNvTjLAR5mVz(=v}blWojH~ zUgg(Vm9241w#KDBYFuM#fbDkSVJcg!`sGwH&9=VZq@SmzS=YCw`uEHuqwpSimXIgZ z^#uJT)>1+z=jrYhSssDylcK>{Q&(B}_2cI88?dmt}(NId_i}8(L8EPiw9gB|l+Ou*VvHH4 z`~03Dw3h(FFl`N3p^QVtJKi_3=1UzSQl5Kf>)juC_y2?!zac}f{xys^gzB__2|uw1 z6JB-qfe4lMSBCo@LUNWu^=Asfx@fcK6_b$KO+Wqr-u}ja+$nJQ<)y_y?|Q`S0b*^E0}c~s zGlDm8H8KpA8x2R%$kD`SY{negjjg!_=_r*M{9dle&WO>%RB@ z_>heE!s8fd;8Ap4X20amfRNMT&88&W2G1}p)V`j*euQ1boVGmiQw5TgNF2Hr$e?0p zVMSx^VdJ0U3=SW!Z-~U%OC}|>0;m~WQir{#d#q<)jy{eeECnnBWLA5Cu60Qhf4pZY8zjS zN_$hvdeErerIO<1@+MFXje(TkXrxg@C70i?SB{aqs!H>;T!K$2skp2fN`)(BjTx{% z`0V{9^&T5L^NnY5vn!cfT+`k`uWHO6{V(Hy+dW+3XH;+eP1(o1QFDPUtoP zQ5#Bi?+aY}r}02LpuJozH5hw2eHj>fF&^7Pq1PjBr9^UHZ{{C?$xo}yV%2Jz~#L_1ZB9!CdhVG zaptsAJ9)^6xNISjBAxv+MFmd|j?X|?z;faJn7A|RZYIFUL;NT>kzdfFPbtVFSi4`) zMSekF4GQ`d1?4`!E7AEXaI_GathH6FZA>d4c{k7Q9(_4+ZBXRCLq9v@sUO+*q^{+MS^|u* z>Tl;67R6xA)jwmsMY8|puP_ajMeu}|hRRfvCspegV&an6z&nsRq3pm3cQOT^BTYPHXz>x!bEv<=P1qDxR3nKeql9;xpnv zDSt94>BG{)ghy3}`r|l~t15y6_fA!a7GKlrE$hI}{gzD1VRl&`#{dgAvbQTUPi6f!U@8& zteduI4BoCs z@Do0wWDEhL^b;;YTd=k)lvsy9RJgD;T-g#UO;^~?4n@Y=(Nlg;fQI45w$0e{Vc#ZT zp_YVPF*euL@rTSc`XzbZ%E1K6Ku8U59?_QkJn%VNwC?zxn)zcg38Ve)W0KmUH8~dD z%M`%TtIJ!pQ#!{{ipX@6@h``oI$Xgq)T85r>Fvjk>4p+t&Xkrz33?iXPf#L#PB(mb zp{8fuX{>%)yp{bmKR}JGBRV|fC*bTZZ~f^$&KiH^uU{&2%5gSlBM4D#=UeO{W(SD+ z&LE&VyE{~$4^gZ32h1R98GxDk@u$ti^Ha_4|e zv0`H1;j53Sy0^Wbrg;#<8d0q~p~NaV+^W#=?2$zV)w6y+1ZiZGwpcr0oPQ$)R)vW# zj@NW8b%yX#<@Isaz$w^rPg#l!R@OwgW?^iZV&fAa|N5bA5p1`&L@GDTB8t5!E#yp6 z6d4gozEZ(GRdpz|Syo9@dsR7`DbYeP=t-Vw!83$OJ4_C-2u_wi8XtSW3T0lfon|F5@LIMT_x&i^cH_w*${` z@`%M#o{_fmP3TeV*{X%n;)#l0nrND=_~oq%n}%NUF-##Dt$cmltQBZGS6C$zh}}G% z|6>UoId%n^SWIUD#mpwsT1i90I%^Bhgoh(2UCY=l%0t>V(zcP-PFg!@+enj{6o+rj z>a1Eg6FRkashym~s}%>q*qt5)G96>j?3Z($chU^lnnLKjZ0G|eI0{B+>sIfbVY$^P zNB=Ya>YO3t`>W&EPklNyMvmiS5Mh-2zJB(x zp$XU)-n1b%-IdrN`0aw=A|NmwbQ>F~rt{fI=_xuRG5Qb3v6-6tT{a7+y!al>(wv2Cp)|Eu zVH2q>)Vgc^C~yn2r_2xqIkG5o%8bL8eb(yB!Et>D%Pb#+;rNGv=t+n*Jz~oKwuHbq|jO9PitEpq~zLn`)sG zwPn!xa(vW>lceZG(0)N0D?zF0+pZY)0|Pu6(*S;d+c9r&fU(`xjVkemGnw&SiKX1* zy$p5;b0~iWNY zc}l8?e4?n`>1pC!Py)7#^WFCvKS1qK!TyJEujNX7Dho`JADq#`I2#BnfKU=O;aADX z-D%c>3q`4%l)Y;c`XL11O?%}Qo9O(+ntujK%;ZKqj0r{neS{6HU9#$Q4O+!o$X+?y zf~9b&<4UL|sld%xe@|NCorF%%#3P1vU>SbVyBav|M|oKYjpo(EsDdc@MK8j8Nr)Pn zf#?3XZ+}|j+%jn41R}Y9WF-`Jff>^nE^LPxI@QMYq>EN;$MaSWxF+Hk`^)5hUJyS5WP2?5M@rQb(Jt@E%;y*;V6SH>f(XZ^*6vY84oyii)Ze zpCGJis-CxR9^YAaHq#TexK}PbiNvzz=nwo|dSV~lR>CXO6XA*-q2zg|t0!tlyhmqL z(x$NK47MRGPdmIL0n2oUzZLK&{Bd@jEwP(Q&+I81)T=taZ}#lVIX;L12iIC-n)fwX54O>U7=Wa|!XD>8 zqT9Q?pM77b2z8+Y4>cVaBdQ)kU$_}aOx>-LKiwv|SyzqR9oE}v!y58=oA-FN)8F`iu; z7qK=j%&d*``1s`MMx=Pj5t#_7I=`)J@Ms|G;KUJwXN$ax8kqOMX}dodzR@hdSRAW* zE?U;P$OO%6RATPJJh)oX1u@CPzQohyCGT#+O%;A=}AJBpERsD8txw z8D|@AOS#p4nA>u0w{eS*Z8-VT=iBa#k!(Bcq}jlD|0S&VPxi>Szr%{DPQ@lRRE0;~ zCn&A@8O%!GPwZCi zk2xf@`wEpW7%?L=mm+D~Rg|ZwA@sE!2wGVtw3vTTpbGqH8eE-F~ zLqHG?gjyL{`>Pyb4B8T6fdFT6f>(9@RpXPjDoCqTBwH$QE%Dj>XR7^i8tBxbpwrtlJ z*CHwOw&D(82%I~kOea|+O#lSKB4Jo7Y8P_0AmdCJ%OKR5Q{XeH9U=DsEu4Q(i+1+Nu`(!25cOn0+%*Kgxcjm$}%I$$GW0;~B;yjA}fU^F{re-Xq#q>(pp zaq_`3|5xy?$$u9Frdqy;s=dbs;^=9lTP#+0w)2Wu+nwg}Td_Q>SH&8k`Ug~AV$DPz z0Oz+n`J0q$-`&k3W>#DJ8uxzRv(T|i?PP@7X)$|Q$EL#>?%EYbR@Mb49BWEXqXRU{ zJF3dzVc+Sb!O0mFsW)}wzT#V#d8*#jN-Q z0dX%zM!p`G*T<}cGy@R?#}kt0on$f*F}I-Fy%5f{IJyCQKis+!b6N|cp$YC;Cz;?4 z%%4^{n#InU;9hnTeN)?LBTqw4fm3ifGTe-WLKS;|>I)m`2O6;BTPiiP60* z!@2!C4@NS<94_IWz2t~TV9eqg;?jTfwY^HnYJ1C+%T1PY$*BDYa&H{i;Lpb2Z)6wi zVrc$-vBf>7N!zP3;GlMxp7n!H-+K#sIpauZx*Ct|Uod2}Y#DuuiaUKt-g+4+d^245 zx(P+(Ob##v)NqqcDls!N<(Ow;v9n(hqL^N1>q5s9N@&*k5%&g2?0eDl*p8YL%SxlK zPe|N)Vo5>tC73L~ApdLGMiR@$N7Uxj?yl6Wz)#nLg-kx2Fol=qS}6Y-s`6g^0nOQ% zTY-d|(LT_#k?Epva(V?Cb~8&{f0nrZEOE^&k-%lV0IRJ|%w>?zml&+#ATY;GE;9`b zGt?!<6B)|Y$gAvt8?6g&MQgnkz55iT+CKu&#OPB{>ND7{@st>S#35#|pW`7IY=W62 z&vshg!&j2g*5G)Nlh>a6StH=W`$-&XxBRqoDN2ovuRm6E)(U4E7?zqrn zR}ymPc6ux7IPE0)-6r0(7DoThyDi>tc$a<}`DqmbV%uBHBPC-}+z~y&ZfRm*y4pil z^El!HHN`mGybo2ewn`*(ML(4BlEsquu%3CNR>#=l!dRI)-l*TYeR?dPDm}W5noX2% zbAZW_)E;ab)qYPaL)^xV^Q-`kd4(T?6dX{ zSXa1(<+ZYP);U3?WF5)2ZdO=y7pbA5X0r8{>}CU{m7Ksz_9*=Ac~-;Yya=OlLMGq*F2N=rCyvgm_R4mRc#oKy z77`b%28p>T1BFoY8%5Hl4||jKv-$NR#J#1VLe%|}0AP*Z9kMT`?2qCUx-_fy-h zPO}D9;||x{PIBxWNk@_JCQoH;+Q9zv;&Qbu?0i=U$bJ_{glSzdZKq`gNe0F?bp#2B z8}j1Auk%)Y9bL=f9iR9ZWabb0{gs(xzvFXtR=6#MaF4?*iWnU*vLg+G5S`5{OAh*o z*3oZ-QyH6n`tT43 z;Z<&$$w^0so!>!78{6$gq$}fYeRJTdd1HjYKCI5B#0b&K*Y_s_H4;k4=LcX7ju+^-*;m_=e%%;-So+uhK`=Qdj`Op3``tQNs@^XJK)U5N- z{qw-Lq|fiJfBHiEAsJJErHh-4f^Au0dRJDcmR%ooJ{Vd$+g_0gj2V_9;#ASU zok=ScNerSIEi=W;q8KE|ZwgD0ELM2~UxhF*Tjc>Mx$%VLfVqUMU~gbf_-o`@ezj1G zNy`ZMQGky%)VV~C(P;K-iA^)GZ+be!8ii2|mUk~s@ROP(kC}@r8Zp!t_LW6Ntkri# z>!jZ9u4s$cbATznr*+mF4TicEIw|#;wYN7^K=fo%lcZfJkF5Fyl%uVPkMFiSp_3p= zo#>rC0J_-2B-cafoadX1pRV&*xbg!uzZhh|jD?*GAjZYELx)zr5F09OWeux(cfn|C z#EqR@i&#~pg?>4lywU5ZW{JkX@#ao%FllMn%v?cemjBkhfOXzemq6-%{~k;L>i;v1 znYP%DC0?HeKHKr50ojE#Z#`8!bl-l%=zlinP=?K&f27>w#xN)wofdp~%{X66#JE6P zO#c`I0w;kp=i3zs)Xc$hd%&3s4&Z;SXqj|VtWC`2F{YFoe0+H?i!ZOfvb!t5m1V+> zaB?WPB30|vE4uk!7lAUYhUNeene3UvKMs*9pn74^P{uZmOZ`WAruz#hSz3RPNN8{> z2XaP-GBH4cw-L!pL|?S0w@mIax6p3SB}4(P+W9BeNk0o(a6BE<=EhDi^dj&egtKt zD_q#=vs@#4uv{0R0N$V7I?8l*Vx*xP(V_z|UE2UO$8^2R7Af@vuR_U-b4=G`y!hNq zmv*HYrfd02V081_Ma+wlFkOW08ackDW@MJ(DpOZTUM))cY5dkj$y4Dm4#01n74Ta> zzP<;)b+q^`=UY`ESvQ_*Tm(WiBn8hE@aqu57My7431}a5d#l$g2CdDq?`NxI9Z@)? z`|*V4djt^ZAFE~$#pwBuee+Hq5?LOo^Co4BRHovmtQ#HY68nDlB)!v_3>TWiigKTT z69t5M*zY}}6@VL8;(ueimm^X^6}53n>W>}0&1#S(G{l z54hZP^~_l<4Igqh>zW(BztK47z%DFSmf&OO$Kbh4gr4g#U;2(31xPf!eb=yal}z|* zdYtSJNfoUy_;0p@U8*ol0#=scidTvAg4FLkWh{J^z`0S3W?r**Jq_QDS~kNUTMza* zZ+Pq~$!QX6yJof%tbxPB8;0Tc?Mq!Ie9KsLBL=8?)wm-FQt!D7h+e;(czDYLz`e0m z`_O;BN51NB7;(XCyb$3XKNS%~fxt@a>5BfUsO`M|R-&EqSD@HJU3q>@@3h4djqPMPNb$AKN5*X58%G;VAAhm~wWI$GU&(Ef~;U_qBdJ zP*m?bPplAn(^UB)2t6) zQ+WbJNOA z^CbVxZ7q??7o!!C!WY67tr#6Ag-)Tu6m0UM3*BQDU1oyFc zMWGcm9CXLEc{ ze`|g_1=K$hwNh_$V-n{7ox8$L!hTuxw=tSVZNC%!bTDg7OhgWQ~S?F7h{hH{>y z-_5#2`g^Cv&f>-1%A>>Vg#IjdQQ-B9qb>q$uxF?sb*_i>|F)u{GOb zvJ@1wn84hsT8YIhOS*OjnLR&qDX-N_Ee&Pn&d*#PWFE=2#XpE8Xu(9@2%4!TWd^^Q z3hKC51q)5ek|0HS8@bn2^28P+?aX{5m5sjHVp2SQGd zq0xKvDlOuMcq5ed33gHxgI&+UFkX^1Ze+a|O+xUNvJQIx_KbE-1X4214zL+@Q*v-w zNTSDq*#GKtm|vK~#p)E>xul#yfG1jB>?4vc07Ld0ha;sg;W6xlM$+rLH7R(`DX&vq zMJZ+G7TJUeljht!QIzk(aFWF28k3JjFO1Q zcg;lZoSW-1U`+=slkW?H1!4-U$tu6aOm`ow`{P`JY$^$1$63e|>3TBhuJ7#Y%v+=c z%-Qw5bH@^%+%HPe;r3j%8T50@TO#PYZDY<)d-tt1s5L7Fft?tD+d)i)r3KM`mcWtJ8<1jHf(HeK4#5$_dcA7@(c| z%gFMPCW&1j?@>ujk zm~Xx)oOofm{-HN4))_dQ`|GHN{+!Gk;EbzMW^^XqHESbqE>wcMcsdEpfJHpvoyUW- za*0v`I881b1eEKG!fE=mP9?C$aS8gfk!pZ5&Kuxds!Ey3nRM5WV(QFWrUZBKB7N`N zv4SVpc;PuKo0Jm3X>ujkEL5&93a9DMMwQTFn1TS#R;mHcr6d4nn<{NFPTs+|FEfzM z+oA;A%gxgr+jwFI^T4cCN&u(Hg$uEAeNi|~f3~UwCO?+|&UUH+&NkivXQwJ{G1d?P zoLlsTGtUJ3bKtSsR^1EjQmzacI883xL6z%&)t}0Z3tI-gIgVyLZ~W2|GWZq59#EgLJ5}SWmjPP6_Vf$>!;fI8QacnNJNXywU(V zB15`)&B_{1E;b*U{=Jm-@0slSw)w#ng-ygP;n6Jo&aavTV(3? zP0^frjXarkFYC<3Nth)lZ;^LQz}o7cD|@d`!yP8qhynDr?fRrEwN}xe5~IfsFnazU zGnk3dr@vQRP-OjhJ`X5voZ3Y&tCv0^X4QO%QR|{ruRB=g9V#PFUhw1`|L?LVz}$3Azgb&L5r; z0-UFVi;{!?&I<_vYAFg+$JCvQgPv+YTm6WO`Z)$gMeux`FQQg1L3G3#Izwt$F{d+_y zLe1*u5qu3a5KAA7nBJoZ;A->kxkw_q(bx7j1N&1tIWc-tnq7bqU3o z@%>i1`}m%wp39jXMZlB=FB%hP0Rvy64i7KzUV+eT>(%JFGH^8SsQn= z1|cgOn8}r8O_5ElAmBQrh!UI)jvAP@pAV%5SEg;oJ+DGLur3mohy_nH*eg zu7F!-vZ$E2x%1n$B*?UoYfF4-kb*J@Le8Wdi~jwe6Y^hUwjuRYGJ*!Lx{O)8j0nVq z{0|}cof~Q7M-$u396K3Xn*%g#Cxlpdj-El-@va+4*si@XWsg91|z4OpGwC#}CTa9{T=izVC9fca@*XTS}gs>gQY_ z%9=0a{Mmf_ws|c=YOmvT!LoV=_ZpHf<;Fw!)OkrhKCParTrCM*a^vx=^0=#QUdpKP zJ7M?N6S+rGuA@f}O^*xo`#eRzBH!>%j5FJXHSg^w-FvBh-*uFc-kEZWBUCKs1JRU0#7|dWf3J zD3%uLl561(mOWZktSSdi%jh#y-xgB7NPUYi*f8~pf>EC?x%%e&^@-l~sBiigtgkFn zpJ*xd>5{AOFuy)g-X8UJ!mNCe_ASF6#I#RTo%(di)prl2+R4>g3%r|7HTXAO`S!=Z zI&#v_0XrdLJS22zpF}W#N8NJ6NrXAaY z0?wiUBh?cf*cUx2`+a@h_sY!o%IE!%?*T@flvnnF%xxcNPqpR7{P?z!UM0ys7*888DpX7hri`o+ zP(FS$ZA$HXd3WAgp;aTRzc$uxQ^W2BrkUI52^rnUM4B_}<*S3=vc<_!C3cBbfnNfy zmEq*oOW|bV+VB){9FLt;Q~}I?Uc(B@8*_`87%b}c4=;m zu2m}01{lWZaDTITLh&5+}IYw{7=L{YzEDoQJOv-%att}+^mgt zW^iKz^E<@*2zw8#=o0IvX8H!tTMQiLZ1G;4FPomN-aT*a;wsyorQXKC?EFW(%dNH9 z{`-1hOaA^DW);U~KuDMa;!_O0X8;5^I?`M4Lt}T&B6c8)?}LrS_c6xspxeqhobQdb z_ZyUg{m7M5Qm2j2X9j}t_3gdC2Il0rhN2*2cKnUKt(ZT{XGxtwTNE%=`O-Xeul}!WmQrF;v0kp#im3+B{3h<7A zp~KK<2?z0(VLl;Y9i|fgrGN}P73(5djvrNoi{L<4r1xxs@MF?m_zP)y{>3f_&%mD&($Ns8MDPFUNF~S*CL$ z^Ubr{Y$rG|(tapop=}SrO!*zmvv+*%vm-4`Ao0C?GJTFue?RZ}ks;0i6u@p#yCLa& zHD6~+hoj9s;V5szRsD1u}a-kes$k9kgQ;E@%9P(d>fCZ4Obj34SGV_~aX zMUyc=CE&}=VHZB2DT>8CC8m!K@R#T=l{j9-kw<8Z&%axz_NGycZayFLsYj&u7_{EhDo0FNCfprc38aaR3vrt2yGvPiOKXjf!N zdwNRzmf;1_vWKCB1zzHTAa;rG(C^^D(_tqz7N>jT;x?j#^$pTU%$}q~@(5rxmAyYP zg;W0rd1A!DQ6sNAjPHTp9pl{rO){FeJe0hZZaBgo(ut9K%%;0m*p=1vM41GVZa-x@ z6InwshsBznxanEUvSvPQbof16|2OIIX?^+u%4rJDi4Hrp95{WdDNfX5B*t+MmD0Mb zd#e*rJI(}h3=#J6(=PGjEnq}7qd0KF4Tf_hp_A+S?zF98P3gh1d)SmpY%8?;wVGEu zt;tRF%TnRsrc{ly%}=Ap`6grydp6xq`P#^b^HeR@61yroaHn;}ChPRIv#~MWoN|y- zhn?6`4%8c3{SXL-!Sdc-GcALNbbhGe@oH=F#!x?u6|QXd_B_(NfHF^Q5-`oXFW6~) zv-dkMw|D7XCtlumzm`ztzL0g{zEyDeOt&tg`^J{SAL?lHh8C0s&YpC!Hy`1n{33$c z6|Q{Ey8U*2kn2y5M+Y`us4t1X!KutbBi{7Q_NW^H>2EBYF*co4#k!`F6SKwq7*4Xx3La6A|HZI%+$M+rTg@ak=)k{>*~SZL$^))0Dit z$#j3}Y#wB`mw0Wj|D{cAF1w}ZNgqtz*E}iwrVRf<5|`|Qa6<%%)6X7_t=FVIp$GlM z)>Gv@YBF+~CK}`EmN-ACh0W+ho0(>>-;l!%@gTp=k>8OL&5uJ5ye)0?4n3 z|46yS9A}W!TGN{N;DU}9%o#=YGYoInK^%zwJXrhqx&Ui^$MVWHVjtpW^xCW`XvwUG z3uNbDumz9*;N;%`EhlzI%c*AId@9isEg@VjRplCTJbY7zat5=+SVzjgO2j9R;uH4V z8Ppmk@~T$9U-P9;^uH2v;W3T~xnCDB{t16!ElRv@`x!`rtkes%kTpB+gsQ@>M4W&pB&t`ey;r zRHlXL7eZPHLJjLxQ(^r)N6P{fGRe}NDWMXkF?>&(S7`I zWg~mzcxMn<3pIN%(2^O}Wh(aB*kQ86IwP|}rb-B}An<*oteynj7-d1w?dEOJ2!QBC z>2j`TFuJNn<}X!S{`eV}D#PFgOI0uQR@zC|ufp3`yV$2kV|RO>aRjby+8Ebp%MJfK z?-w(n!3%<&uaV5v%}=e(OHJ?TnR;?ws#@Fq+kSbej=@u3o9;(kPZy17BHlSj)vpWyPy!(SH4CYtGge_ULjgU7l@l+v*Jh9&e@wyPvzn+FX7h-wAaf`3LDWd5@2N(ix?vAM5v)Ht6FXf#!bG7fiWGZ8<8IR4pA9e{`;45`Y$QdIm zMs-@q`C1v^P3N}O8B;E;`~^5)lKh2C4_jo26~ti8odOwhX38K^y#qiph}5l+lXWo; zxK$w4LZD)fEUI?Ch9P8A^a#M<{e{^sIz==W zM7i~g^J9hsm&Vb+W#n1)D$_sMTQ!zum7hiAj_De!cRz{ubBSf~H1-gFH=5^~MV`Ve_vz<3Qm6 z9)OD#y-J>a)N$M;2Ol&L2@!{L^?EgtdJq3vg9;M+n%0m6b`7x*?vE0JDNJeDr_4%DB`g(jUDYbK?HUBhv z-|XvNz)hpfn*U|7GQ_GgN7SzsyBE&zqR9czjOfV9Tn!zR%oh1P;yhtomH>)6MAl-kF=?Yw~Yi2b|E zfx3OP$42taPAWw_^rRo=|J!u7+W(rxdp3p|S`qP_B%2}Y>7$VFqFLM6>5V-{LR1M~O;}eVz1}C7h=_`kc`P%hwhd>t z6HM$_0=H$s+x40vls3QLhj=re6ojs80lsFC!-0d@0dchI@3n{kWRUY$+y#jF6K=;R z&qBCRCHk&u<$etefu9^hvzD7xl4usr;xhG275rr9Umo;U{Z_~i;~B1a-A;T=3uGj;Ukh}GfZu`wzXb%cg$jI3 z3$6#T@>}ptp6zDhN(#TA3_Zce|MPRe|CrTqECr^1u2Sj!g?*U0A?FoDPf|5_H{P?m z>!M^)J04Y7hT)aomOhpMzY47Z&k$=h@*K3nI3w+~>Mx~~kUL-~`(MWL>F8TV&gHbG zkJ64ZC!a~Ig{M7CIfmMaACwoMPj+XP#m}#}=?$?{ulL-4!m9rQeFf|W?nN9PToylf zSgc4yV0MD}(i%?A7!EE}L5WN8up^MYHUH~i7~w>ip{;fW;a^`0HGkYI#5s=kN>cQ9 z99sa02;O%%J4KweA;g=Z%C*GyXtP&z`g!JtDw}Z2-lVt&r-nH@jMpIrmEXW;5$Aba z!HhJ(v+tH!g-MSfTELzEqU3p7E^^M=0?*PKs{AB+I-%`5#oJcww&(3GhmV~#7L-9B z6>=k>D=3Q(J+AW{KL1H9O|Q4%e7Z$Ft<@YU+dA*~Gi4>Q1;v$OSf>);mV~K^w{TM< zvPh!2Gvc&{Dv(39&b}A<6Stwtw%K>th3o8!7frYhok{Vdu=5PNO>l@=sn0b9J^}~n ziRbNIFNT~QpR=jAN_ePK-ylms^ zk7Vb?l>B6wD!LuStvnMK{vYCz5mH)6rr=2f8h3X=*V){?&*5145{}7qmzzQ>X%%mynlnU`r}} zgAr;T&9N5TptPjTFv2$ZbVnv88pB!WBu#8|fADGz5IcnI6`Lc@&I9(oj7+Tsb5PBo zf?8o$Yz`6dqB(V-5l}#9jeu3Ju{EP`G2itVh1I{@&CV$^0;%<64afv&DI~Bt`a*<; zGigL2I;{l@4JmnEr`S|JZ!Nf4kM43m??$^~M}~G-^RF}u8UY|ag@8N@0g-3;uB|-? z$Y-S=;mW5B{jeI&0wHkdTahZDPEk~$QKU^cl%cAX`%~4B(wGt1`f~I&z$X#dcY5Lz zMAoWzkXU$sI~A$OT*)qc+6s2FyySJ)?2{$8G+j0Oh*051CQYV)W*w&5(?2x7x0~O1 zgkt_dXYEIAd&2)&>FuBh*3&0yju$>>y6pjM*0|SeiAQ`6o}7s zc6I7kAPUk=m>Ut4Z2w`#9C9LXjZHArtoxOnv3Jwgn$kpSys%$lK)BKa{d&&Hyw!B* z8%f>(sqTngpc(s(Q;hLN`Xs-y1C^g&KPMfS2xaSy6y4_?@w%d+gg@D2Vuqp4{c^i_W@ezkRO*m-(~NN_?NUsWZ`+Jj~vpz?=JXbr1gI zQ%fZ1Wk)n7Ip|GNC{T-+=6CY!aq8x`Iro}MHQnZARcioh&Inj-Fv z>I19(ZC-|vdiKz|5@RJ0mLFK_YCD^KB_7dea#G|^Q{wewq3J?ao-QGr;_OUBEX+SJ zphL)aUaPo@sS#yzFVOvElAcKUM!c&giAPUOSNrR4WqTlR-C+b@$4TBwL3#4l*pcDN z@0P@tr*_aZNmx6OhEYVyXhhK-_0I_2(fQ27a^ooxD2+}+5Jep^f}+gpmj|~L6rVI_V9rxe z?8_=B3~F`P4}TEohyUdYiWTZ{`mi%uBNI3HtsrYgp(6;XZ-3R484$vWKNC&lu5$tEX2PuAF`f{X?<)WkRKn}uU zb*;c@wgt%9BQ-_OgBvjOgoBMAL4Ki19#ti6XhcOYbj(Q`a_n6nr2FWG`p~X~dO=Wz zg}SQnA)+_T9-8BO+Qp@Gc{WFoq#ob_eiPH2(k*PItok3(wZwl#S%^o;JRVk6s{EA^73L002Xv~Y!I0ybXPGz~4G zj>KS_!me@2N{TM9Eh17CzO1+-Y&_=eevEh4f_>YG{?lJRKZssNG!dV<;g=+QZrMj5 z_L$(-d_oUNHghYY7(t2z0?rXgU*`akF9fM16jtIgK{}Nm!o{T~b7disB%}*hDeax5 zx4p;2SykRSLDG0+p3~~}k^oE-KWGFcR zl;1U?L;SGW&+pQ2cvlG`rlMW^aGRCqg$nmdYUAva%()6GgZ!%qR#yVB^+o{puH=~R z@;ZQpsKiBrVZ57n_p+~hgrRzbVDBqvqlO4cSY%PSkdX7OG2(yta&>KpFwZRaFAc}vF9!i!xEk?KE`2FX1~ zc}Cbsu6#?2-Gw(jYgcYDmKJuutnVO2OCo`##V%Y2(|_@Kgm2toSSXdLzbVXvOHS}HWI17LU2LpqpNlPJH+DSUNa9R zTq!|X-mn`U!%Sj*sNZ_C+C8&$|J82Y>deX!m`Uu#Ok!{K-?GacV;{jmoVAs{!cLAWvE8qigq$P8&TS>*ouUu$a!{6P zY1TBl46XE#ty*oiXtim!`@I0O863Z0&{RtrXzHtvQDpSOmWS01o`Y2fea;r}B~PE@ zJy1YMvLF5O6X?6{exskcdi;TY7VB}5eq8AcjM3FEUx)_hynMeK78sXQoGC$ScK8mlQi0osPfCz)u0o(Usn>d%WGIawMc zKVaK5A^|S7=Fc}1x9PueL@OgEHM@iBkawRPNzR7Y%_kA<9s&M&7lfW-FT>ZUoXHa<)B1K&ZU*vP1xfnXC3pf zf^vD^_#yIz%J;4M8Us&lLF!?|u0VBAr1Jk#_b%{JR@dHt0to~KCn#vtRzpP#t+t_x z5`jvDz)YPe)*HR3pn_OMDai<4&|oq()9F;&N=xgpO>6C;r^gyk1(72)2qeL4@Pc@$ z;QblL3wVKuO8(#9+RrmH3Fxu^f8YQ6zI-(EJp0-Az4lsbue~m>R~c&&4OK(b8IN@a8P6g@B`f^AbMVuP9ja% zs-SNO1yV!E{%Fle2=2M4;{D!Eps#m{gDrfN12i(;PiBW2ij|&tEUojWk=)7`BZ-Gm zHv_hGYvSGgc`eTx>;GiSGT@Rwbx;4t_2B)u0ulJ7Q07j&+~ch+e&K% z$JSmT0F)2#0NhcgVsRU`?ygCVYxIZ6m1@n%_iIMtsFY2Op5{xTk>|E}XWouq!V%|c zWJ4D`|8}>Z+lPVB{^!=GCozk{RU_qeybr8^L-(Oco5MXP`CYA&&*gaEO8}LrYx?SV zg124({UwQjQUh(yAJa^4)t@ymdUVXe!JloU9ZUcEh6aC6n3dxV zLR0KDrsZf-dIA-(;agcu?rFg%ueuX`sCr9w4_+!+E7Q-7XKoX=-zb^qF7{zpumdY! zb>O_PKGb+A(8u&`*Zm5+&L*_`;?R#KkdAx2&KeFSezNY`N0LnS+!MA(IJ+Usj&Re4 zK-0wB;Ia*o!UwoF9i(cwune+V{N*tNea=LfRHK`#*e$#IKOg^}!#Cou$ zY_C0dzNYe#x(n*!5K7`rGQsXQf%9Nbnuzf?~LF3)b9$2AMw8vAEo!Fx*ljAEVCChFU=R4>H%Rh z@u{QVKmKfZdgRU2BZD06Q=z4?@uv*(- zJwD(1wrUf`F==Mw%%t-ZOF;nnyK$}e!=J+lUZy`6^9M``1Gdz=g-9Kl{yt|0S^%em zuaTjMce>8Pcx>^GzboL#dhkP2B}BskYczR%DRDSLjmtH0glrDqpVeo8+u8ZLlcn~n zNftdCzH|+YlL<#tML(}eq4%AdI07_*hGZ?jmR;Hzmp*{zLmN`z6}ET!4&MX*TR_G}03Feht>N+FbYf4|a6*(8NljvXrrkj* zY#|3f#Y~(y0@4@6s}irYjZ^;MdB^smkCEgzz1cJn6gRCD0eDcPbUrK{VgODbNGq@@ zj+L&Q#k6FKS01a`flHJnW?&DY`pT%!`sM67CvucH1yAa0h%N#L)6mNH-r8lF#}n!9 zSosmwXhV6Z_NfEJvVOnnTo-gCX9K78!oIABf8x=YDBZmT6Q%BdE2cwhd}{+P@Ka5& zlB{5*G~y*fH`R8;quo=>)GY3c$=_Db7b%wx?YAD~Qom4QvC3vRpS63hVM*`$kjKBL zivPV!?crAJ`Ux7q0m#S1kC)N;JpR1`{=GsiI2hcuzs)x0GXIqE-QQ5Y=w*D@LQVdB zBtG&Kf{D|H8&>*ezGdwN^Z5NR#&!hnwqTuRZrLzCypDl}8m0WvF#g!vvmRow51MSD zI3vkZ%Oc6irTDH)o$5ky)+`q1i!$BSzm!$n!WQ!hbSPCg+qxsMMph6Y0t4U>Xdek! zb?Xy&zr2f*2MsiPy76bc)x-Pcf3HQvSKZ>gU$%M=560NEej(sKLB^(S)r$+-s+aPA zGygAh26WXJ(N(v!S9dzQImADN9dnVFWiYn^MvB11hhQx?Y6Ed;MXMWngg9N}l?*Rr zxTj77Y%8LPW1A+HG@UZwuEI>G(2BgRzj8MY8wT*EzQv#oTfFW6$=MQNgExXcDq$-L zS`T-}^mso~Q-dy*XXA!7v?|@hxZYAj&t9WrX}kA!|6b;k53Bsjd#^g-x4u_tgEy@o z_Oi+IDiFrRh_k&TwBoR6a#or2v#uRJCW8Ni3h(qLtU5=16dtwKoD`r@5N1qu!%HXZ zXe+Ek#~n=qvvCxOG=`pSivuH=5X!ptcU;b%zsWZV7w1Fn9VU?cUfMof_w{{L;X<_&-HEeIKN*3y%H)Wd_|e}-j6gt>#CA9(~SETKEo_KRvu1)>fs8l z$3q^Cj(XYpJO^#|wQ_D@f4+9=nFB+~X2gw{@EKaQ1 z^|_wXbA`6rs~4k`2lBk8EK@29l{>%r2IB2}jwo713iIe2pCSbIinCgGJYW$Y87rDp znSD*Z%-u~Ywg%iYlf&Yi7PxGT;(YzvrLbJm6qAW!)sA(A(al@@EWOmM|G=1Tb$m%CA`bq(T?Pz@*Eq56N@u z1)UXqViuZQC#Snks$E}uT_Ax0I#Nbl08}^g|6(Ae#Q|A$Gh3_0)`r-Hi-}#>oVPTi zci&`|->PjDN3sI%|!t7#@{w33t8L703kY}Ou@DN>?b~KVWZa$6dghqA* zG!hTaqbE(U8?e69M&YdyvXaH&D#Xmmp6XX7O$XhHo)N)tTM$vgc?s1l#6$GvjnVAr8kE! zv2mEIH%*>snNIn z&A_q60q#S;pp{gNowUXKot_~VdrISv+^Iep^J9?H>K#kRRpz1V^C0K%y!0esz2Qe7 ziFMIz#)w%%fels2m9$rqd);wNDvCN0eNnLpg;&8_^l5~Stk z_NtP0j&X}&5s=h{8Xs1+jock#=w06Ai0Hz^-j2U>A#|-{ZB{`7Fqv ztY(6IyDdbaF7&&@2gnSmy+i)>88 zeJ=|3K&xka;G_cfz!6m1J@mPIvfsr!<}-kZgMQL;9yt$1vM(dmLZ0s`UAQ!Sfz zfA`c8(DOOVBC~rB~aR z{(YzpW^PJ}{*(drBh=AI`xL8Hy8vui00!vdCy#cp6H3?#Z3QK6v?UC)%#3j9M7B>> zI0NMhGc;}~8a^(>%Cw=ioS6{fH^rsQCF+|QwvNMmo?9Qr-I1A??J*`yg#?TvlO|}H zD|8{oN0e!gxiTMRxT-^5hh$Y$iwaO@(k=~}k}}i;Kn%q8f_HoacfmKX*sv$wNLNNq z~iLep%s=3Z5T~+RTC&YB{d(i=!eAs>qI!N7!IgO zRF(3j!v6x%7{g;E@f~)!Z%kQLPWS^7tBCEO%i8h?UXUR&%BWklz7mQYo>pG}>n`K(Zv;B?bj{}Iyw_mL_kBV)5V4LkBCbESOM#`^ zXre|65OdnIC@Dk)PuyO{ie->3)e8u?PK{Q+9BN#xGO6Qk39osrFNK=Jedls+K3b;| z$6`ZJQR@U=909Z1z014kK*Bf-r}Dm%y6GYo%?sg_euux`ushCzdxd`;zn&^S^0nfE zZiRYetJzMDCJ|r}$f=$kAer?ZK3~$G>GQ>TkSU7f`+UL3J?C2i$1>Zn!5G787S7+N zCN+~7s?TReL0_MbR%YfgL7SrkQ0PLVZ4l1_qYn^jWkPzc+WA3M;z|Gh2u>+kaB6bg zR#`NfJy#@E%`8-7FroVf=YZ^PZ7_69QDCT>P^CtPhL0dvJ8`E*rDac%_4ndQ-*ioM zK-v@>=2*)BaQ6Gw*rip;)7%vuGs{Kvz7|ko8Z%whfN5&uu_U;&tVs^)!)snF4yTG| zybAY)7ls_+JGpzv8g$MY&!K3#5yr%Zrm(GB>uy10JV|?RVaNSb>7RGO9FdDQ23F4+ zm1}g|Shbnk&qbir@ z6z7e_eX2V=aK&;UbRxYQXfp;W+nyxig`T_D=k6MHqe!X-bt6c{Bd8m-M+UT;y3s|A zIm8ht*Pi*S0D1W8M%}0zb?4NLG`D$fS)_7Q;$`ZMD(7v3$~Uhhs-VsmuX&GL3+2!S zO)#EN!>(Y?KA&DK<34Z781L?eTz`e=mi;p5YaXKeB#Y=iV*~#Gp;Wu+dM3qb9o1C6 z8M@&u_#_9Pxp~sAi^SK*28D;M&8@dK^H=w_nGr%|_V+h);)(422)K^@ToO(eJtL}C zYFbMBWiAZn8(UEWeQC>b)AS82U~!h%PkG@LZ9O0(LWd10^_z&BkX{2&5{wJ<8VtfIlMzwcblPd z3$z%i<6sQyI=Iiu(ne`SB)0dWjAw3F=MWC;@CN))GB*SS)kqK>mAm}^EtPwWTUw~x zV>zRU$gn&QLQuIbazN$qCxcPMSty3Tn_)k^8?AhM-Vxj$21E|EZF6MyL1vI1pm4$d zl41;O6{e)gqE2z3jjg~Fe1qf&QtmZre5kRRR7d&DH&`!!eK+t`Y@tX?Rh7B}{d4{R z$5waLeJyj5PjA>U`Sfo>FZvfIcWg|wvbHStM`IB0fNYt%nscQg;p&1LiVJX-+?f7Z zj-;tv9S3#H?o`XVSO>hD4} zG96)dT6z$--4M6^u68_xfj;-TuLbI~JG}Q|P`3R<*&0OO*c~g`bUIpm9{U+(7YASA zJ$G%cuOe)Z-4ygQkFfpkac8xXarLqm`DB3z8UAP|ojKrHmhd$))Q5L?jvpZAEF(z%!WbJad-rLE!M`2iyZ`LE6 zy+xHsICUCLOUBv%CU;%CwY^cncy1iQyq}mD0yMS7xDctTY%YHBc zT0+%R>s>#kF9+HEpUaRrST9%e;zaT8DCglGh9Q_+9PbmqY>cwm`ylhTo18Kx%h==B zW6*Op@P(YMUx1r$pEyPcGOP2@?j1lg)X-Bt+wdj=1TK)!iKR_=rprLPCRvfT!uYED zR0+4Y*HJmQx1AZzoIAY{@9qRczo1K`Ln6t;aJex}WaO1d>dNxq9yf!2IYGXqw;aSh z=GLm%dvm*+;#c(BGb*(vW6mYL1j?VYzouQ0>+hqR^ZUDiwtDtA9Q2p*xO?Ypf6M5v z11szAIKRKg?Y+N>)!0J-uKxDcS2?C$!J!Y&yGlbdCdG9`YS58%6tLRHk_ki}-Db1m z^iIaY>*3uj>C9Q=@o^Po4&{?h_sxE{#Qaso<$1b`m-rr>`CC%nqqhf>z%NcHye$;}3*UV`yHMkAm6;nLiH~F77hcJe|4Om4I$1Tw34evZOv^3o>y7!+ z-wPjOB2D_saq>ao7!9PcweB~W$$9u%NAu8+t`r+q>4k3iArE=-t3knOJgxJvFD*_- zdBy-!dQVaW%h4b2)TiO7Bm5DsRX82qMfj>p_Gy@{?hdU8={^+Me&PY?s1!w#XP1Ol z9BT@NI8eKW@$RZCP2a$n_bXU9I_wwQrKN%*86s5KeKoDzCF*R1S81-i(7?GJXqh*ilPHgEINRj z{TNEBR~LpWH)8l7^D?(7FVpdYckd6?F>+*XYAMVld$4;pe>rX>$6t#_e=nN6Qb9Un zC)(7tPjs9aJb^T7zD4h=&ObN(EHOWF=S%U|9i+H;Fm?DL{$_qGmOJ?5VzB_pgoL@3 z_sm1CCb%u1-%9K}H@)_K+vQqcrr_Lk-`xAB@~2rP8sksP+3xX2Y`X{i>DOp3?@V$3 zxxKhw*S_=@XPf@w<8`wM>dqzA!se=b@lpoVYyxC)*u24e{2vH#syAm3G2aEtYy-<| zrP;QJ)ohGMIda~@=E%=^6gl3s91F=2YvyyNm!2d|(Uue;XQK$|o&BT(`TgiHNGiWF zIPpQhbCsbRXqAZ*FIuE?O1t;`_j?Y}_Di0AHIT~A`8c$q_>EtdKubf72@oNYMI0`I zGhgujLIu&}G5^U|!;{s9QrrK9c=GRgcrts3CS%R{;L4eJr2H6JQ)lKISV`)kwz!6i zjp0)G4=&VrHbkNewS6b)#oefdlf`eMXAi#I3aw>mnpI!CxR7TbUv^{;$;X!+9Ij$B z9OGQ~9lLw3Y>yokmW(hhy^ra3EHv}uvpT)+Ud~$6FPP7VGS#|@yK#Obic`vG{k@KF&LaUO26#v)FXd(_SzJ;Im;=A}OMGRsDp%TLNRrRR1Mxmd-ur*WFOWuT4 zw!9d|R&wXi8BK7)=ISXq{!(hdA}pF1KZB=mHyTR2zeM~f8NVj*+?6W2GLjsp>%nE{ zC1Fa3=L^B(q2JXO;E)ehmeGo4j$mH_Dx48h1B-Z2eVV*QFJB0YvlL2^y2<*vs;87uSAok=t zsuE9WcJk$#rYh<@xK=v8>u|6EOxu8H_9hCm>DXi z$VSh4*8)mFc2jySA2bBr=6ZFH1oQ`e*w*_;&>8RNr%4vOjy0uh$ASZOA;g_&d*;ae z@yd=FW#)$03%ThGviJc6mf@*`YYZ-T6T9$fljySR*G@cOV$6Rgs%fPIIG&@<97)s- zN9RR@H5Leoo~7;%5rPw_Cutk_4p%$LMJ6SCq=sZ=Rq#qXIuZ+}B# z+^&r;r6)MH)y&@bCoo;8VX}3pxW9F=b-^S78lch2Oc~mC$SD0I{L)1$KMdV4)z+pX zIza1D9%?+ny^E;qL^_qOu=h{7>@>ugkGiG;}iISiQ%m+dY+hZsMW~;#xaK8Yl6K&A52{ z-+n46DqhBqzsrz*zWqF0MSJlrej<23{hS7q9RCxN(vR`%f?4dud0Vph3e}MsxCh`6wSGC7FXGsgm4zW6>Z+h9Xfe#$~4{du0#=z-rzaot>953nxV!HE740EV7R!9!}rQ%4Dh)Oo?iNqnSzOomGApSu7_xRhWQF!UF-t_En zuj5(qo?D;UI*U<>GT+d6EQ^R+`8UPUnT8Z+Ck&56B9ttzlOmE_pecjPKmp z?P4ar{FsF5T+{O33;1WDW2w;E|Q4kaa<98>bPjY9C)AH^K+UVi!~W}lZY z-+&*J86^6}U#r@&zOW9P-s^DlB47F&->FGmJP1BzTd3g?5Ef4d&Ob!V+sNu>8KP+R zs|#M4)HJhsRI6_7&s{8K)`o`&DtAqxw{Z$|r(rGrI?io|-)MmaUsi>Kl;pXKQIH)Z z10>EfzsH3K25~e08Vyyy7+!h##pRdIysG@m;l#oPX1p%S!@Ilz7vM^x zw3-1;gGxN%sm(OaCf52m1ZCiXNzpUfx1^k8y0LhQ{gKyv--^w_jck(yuE#CxaCs(s; zyQ5#V?1~%^UipZ>^(7)h^-2v#lPxQ?85C}7w?FHPT&;^-t@o-{-DQ?&t*>~Bb>)sAHTuYv zZ*{Limxyk-7`E{-S~GNAwGzo&HPN`V_d{jG>seR)i^S*h+a6!cUsLxViMHq1uc?x? zqaNqTFiDR~%2X4+0nkO_#JGBy7PXo?h_>qHqFL?LzrW<7w(8rM`{nw=+z@|+{HvE) zv6^Nt!OG+T<0`_0pe=5nO)56LFr0{waNS+0pG3Uee%iyS_@DI@n$!ibwD72%13*sD zV`$QcIt0o{@4%>p67dBLq(%q8vyDGv$yLbOM}~cpuMgNR;q51xqX_*O9e}GOr{QY? z2_Wbx^q))~vCZ)VERhxgUcjCAoO?!h-doIiMhL|O>ZoU=omjps=1fy3E-9GO> zjB&sll{=+6t@g~#VjNI?$Rz#qEsG9vs{VcW-nw}+F0Y++#XQrMD48>JUTs_T9k#0k zSyJss!+!!ljABpdC}YqF$eOXrQC6?9q6d&Hfg-ZxmMa-AS7s(5QrRAA{H_k3t-RvU zlD{3&uv6#+2d~vlM>+R~9l9utj+K9!<0v6S(D|^4KR)m`89v_Rb>r`_3JaBcTF0xG zp&xzyaP4RO-Q!zsIf@`lBO@P`%6&I>5i!1nM?Qp>-l3>PJCPIuE_{_bu%oo#u}Crzg#Hb3X%rqe&+ z=cA_65e1&JtLgNQ`1!Eu^j-XPalzWvboz&b6cxlfH0uJv7mu_E++sXL-R3L68# zTbjOt4a;ClIiBvwoMd|2uWgeoX6G}bSZM5u0{v<5@1!xpzmrY`>9%hRSAH0KLvn=5 z9d*C1+R-+UI0K1o^4P>!aD>iWMVY&uT%erQF>7&kGWv~=CnflU)*PNY@s~s48k|u# zPGfPxg$p~<&B7@oV;#6&PydYPe0fAZWC80#9IRh>#pM@WQg_J}!1}EA2_=^U>VMf2 zrYn4y_U3=p0kc#_d`@B=>>-Y6l?4sKG5X=!edLZX?%;A{599)e?33O2RQi^TixfkN z)lX5Z)avOxGC#7DHtxq8^L1zf+FgzJBa+tK!Uu&%qQ`Zs;n9YdxAJHRws14ZHEfOF zE*zQ}0@|LcZa1`zh^mTfsY1L(IAQ7D_wN-KyINiGTG^v*wp|f2$K~lZeD4)=XU?19 zW(K3M%iH27lFZal13^L2%D3HpJi>aIYj)lq-f#c%=+5r8_*Uv?uH!HA8@_k$jCnKW z%&eQ~PdAt)p5X)4#;6v{kibcAO69yR<1qB-I1JNLI)i!xa;F3#C1q)k%b>)J#!{2n zR9*c-H@1Nc5u2~OG;48*sU>klFR49$!KjX^&^@OWE!tjNTTn1yO(_0rGCL0$E#r*q zf>%5K-r|DvyU<_Gul>XK&Y4kn;q3GANIR+nEr!0~RrYrA%mv|53cnYMpG6%mg!Vqs z)basz2s?+O1y$|+=FPl#W?OteH;Ky)izb(h;Z+N7KW1R%9rqP+RZ`t{V=m*#JO2^Q zWh#G^d-PB^(jjGO30Mg=x13N=jUb<~FR zzw^_J|FZd;JA2-Y+L`CiVg4{hDG4vyt_ii7I}~lQHuKd`(jK2d$1l62wyrHclc!G| znC8uU`OBIxJ-P{-tHiIV=SiDJHfJeG(Zup*I*qf&P~$O0Ld9k-B(IIRZ7Sm)cR@;t z!{zDz#=Gbj61xvX>_$E3EjdxKI^gmX>q(UxCTd#iT}LwL=v%2TSjK2!2ES=7B5lzG zLPw{kn90{~sY;9+4(Etdvi0~%S_?(HRs9P!{s~owDx6Xjh2ocB?i#85N8JGt%wy$b z+Z--BddNL;^sBK>`Se}$2{C%Ad&lTmL18%=#NQj_6-CjmTvQU%9G&TG4Ikq*CUy zO9W@%8jkMYeNeZJ+*QIU0_pU+3b!1Q%J)Mz+{sHcaYvY+8g8_bHT98^xU1XE>h_7q z!=)+HFaijAXXwVC9muMUd^C@;BMntViH&arv5YE-AU^SNMKBr@seC+i<2;HaR;$sP z#6P0WTL4oeaYBJtKSpl!xZpP@0!hoJxgzRH%gKpxEsPiz=i@poNzWYqv6ukD88v(u zomYy`6xY^x5#$Fp3~;KkE;?j{I36)3Sw_$ij)J`T1;FI%vjeI zX?hO!*9?(?ciaY1<{duB0e$s21=qx+@kQ2c{4n>~35$P(&p(6U$jGPiu!1^h^6|X$+R5+>Pi%dUpXd{=y^Yr1M%sITcuAd#ce0C6aez~L zEn|xmKA9G(3m3kZUdnqDTU6pik#DUcsGw-5k;(;(wV=020dEZu4 zC}WR_sq&KM`6;y(P8B^(94b5SDZb%jif{Osi_X@eLvXaCl)Yy`theX@Rk%G;xk)5o z0ywucoEVJMjm^6T>kBXT7IFijD2{0*bSyJKGhr#tQo7#8{c14oayRaZ?6}usPGjSq z$Bd(g=tV|r+--6qN=24GRkV~xl@Z7@ne|x2U_SQ+IIhllmnzr?Y1%cgm>T&sd;<2d zz;tgg@-9YhTT%eX=zk?ujz&#IfyRH6#($F=|4(iFKh^kA7I`qn__y2mpQ;6(u@U)VjPzyY1@*mS9LZZO#PznB~j2YB91Q%l+5v{ZIDYcu6p( z%RcGRGEGOY?0NS;OZ@tJ-v6|l;{_|?=qa$QzPXguRwiM*g&WJ=>oin9-pp!oFHD@V z3+#bxIp^}nIdzy7y4+03XN9ga7A~A{kyg2wA}$b;6osXTZ;TzT*c4;c%D3&l>ToZt zwtV?>W<1jT&yHF_x2(IVCE^>osK9CRJF;QBelpTRGndOBoK60#Ymv|y=jFJIPD*;6 zBswnd3*nVBFR$eUaplZNVsgLm$_vHc)XuydBfqxzK^m{)+r(m7)Dp+l4TNzOTgNf0s1CmMlFR4D+Ts`606v9pHTJIPu)VN%r_rR( z-ubX5Ji-ac))gH<-0Q?WfjObOlxAyru$A(GtG9o1#T)K2?{{1L`wX{U?FQR6xmL-O z%Hv$Gt5%Hv9DY&xl|9QFlb`1d!OGuk<;_iO-Jw170}l5V^eE3stG&9}Z#mTX)pvos zv&oSj#?xZx0z6}kpli0r+#v$O@7>1r1Y$T%9{Oac$y0xYPI##!KXLqyC2%Aki*9?*i3GTBMpxrsV64YJKol>iLl2PQv<0;>hDmU*l#we zYK8SeQGORJy?6GvbZ0SXywMA5S);dxl2)E-G%t$K^P_{*ZQl=4MS zHNF28DaMrw`@-$jz8YLIr3%7{aA|0SHKY1*Q(dZ^ z5*ci2g1x^3+i<<5^@4=yuCBS3>-tnLz)+!1osUN)l6$$oyYS5N zzo8YC6Pm_I7qq)I-2D*zfW&XnEIfu*3~nk7tvJ1~X=))qeVV5B;iqrY)V}-_HBBwz zr?_cqF+cs9ruO5ff74VP&gyW~3V-!sY&E0atl>JT4479-fuzNzJZ1A*J*w4v{41m; zSK9=EQU*dVRm?kawJ_7ImK$c`P+??MfadQHkQ3Q6b9?~V2n@~_N71IL?C$%rWDYTD zJ(bb`OXa<4AMA7;YHU(?KOgHq%!l-R5`1|9(o}@2b-#?J=6X9Oc!hOuLkhaQ+sT%B z8G3#H1ZLhl`>V!cgK0LfKw)Tm@yq|=?%;?oM}v6(FhHJImN*4Hp!js&xIY`gVCK3H zW55MUrMxWb9CwqbM&Rt+7G8J+C<~|UYh@p!hliX?{p)M82u{Vduhk&&==m$LQCoF$ z3AY|~GcHC7cso10*S*JPDUl?$dl!^DA)qe+TuUSmB-$QdIZwwznVC+X!2EY`dQ8db zmo8ejcqR8Br%ukt+~XW%?IwEzC3?R<(y#C#*wz+r9u;O(2y*B zQis@R`eAO_N#ZPzBTq1rtLDyhBXLb7m)qQ;s_GraBuPb~aU0T~9d>6^7=y`|w-m06!sfEAKe4R}S>dR1FPZW32NUgYTNn1dC z;5UgN&s`>Sd0lWn>%Baw7#?XWb(gf8nDBB$gl+LxwJLk8fsxddlMe2Ku;Tt@f~o>* zV{JZEeeg$jf=h8pJfa$Bit%Rcck|2`Z{d-F)nqTrL7J+WT&yUz`ajNiwz9 zt%(V2jNcWMLkMGd+3*GSV%E@7HfW;ULH7@2o(D_UMSRWh4_qmic2{j&3 zB=>7?ol;VO>5<*D(b;k}iHWQI5Kr}{ACQYl(jlyXvCBUlKdT5moOQd#dXIkSCL~)RI>Fv5BT}m52fg{QRKs2Zi28^Gq?Ml)b1l-N+seKzqu@rE>fn zlRmAscS!HRm9}kX`&o|&x3{vo-Pm_b2rF~zF9*RFqbvtZZpdGMTFFEan zsT9M0VFWm2uBvIhX}6Yfsg^NiwRy*siVHkr1fFP}-vz85#vpU6NUx$U(^u*SA4#J2 zx|x-HoyLi#Q?+Bt2$Uou!~pWrE2P6e1&>*e^Iq;f!+WMZi|@Bu_;TIjMpM%r&VR#j z{$0wqr8mFncxLZrJ_h4z96_U+Me6Xb(FfCo5JQ{(0)KkId#V(sDdy3Bfg3J8wSrG?FRQ=>3-~vr?cznF9m<;&5-NzWC==y0FXvkACQr4?J~N z`qnaPQn31G>G}fYOQ!1eGm`LC1fa|6Q*g1=fhkDn#-q0~X_w&iERf$rZ$?m8;15lA z5k38(?ZekRe`p`w&8opxeF|>KeA{_Y{Qdpx=>l-T{p-ww;yGV`tNY$7Na`N?>sj)k znANfQ4=N0;NG-GFTGC=aMm!RaO{jle+FcVGf!9D2faR-xFt@x_D;W#O?ZI$r(0<9c zP@*WeJ3S|K+wVU#lWU{y5CAJphr(OlB)-;lfqnbB!`ttTu&5!D-NKfnZwCm?Qt>Vdz?4f_Rk%e_9ni_q_@hA~a%WH}eY~VEu zJ?n0>*_x?#I_YS7E;XsJw?As!=?i${a-K7!;jqT@2Jltf+#l~E?^ND0{`d4mUR>7n zPa(ItQa(dDj}q05J7W8$ugHD|g1r;f>i2U=DWh}V%Q)|2+lY{PUrv9_PB5zEjlKL6 za8oPEc~s~?>fT|jkV`ZwR7j#4_|6RXyS*iQ!&+UR>F0OQIHbbZ5FdHRMrok2Z>Jvw zAJF~;z{9(TlK%I)t(j0zaw}V*u^V_9uEevPV+$>mQpiLdQAqeeuf%l5JsL(Ey1J8qe$~X9_?5-jS}M@t)BEwIuJCJ zen%tw1dQ$%(DEPPGdr;_0Pb~1r*#*l1@Y!md!SE13?v6z-y@NHq4-Z-w$Ai5*}V{C zzB0)CH8N*r`?LC;?BeXPsQs)ZAyc;>=4t}A-{DqzQo1rbhrtbV1ua;nhsl)rl50T| z{BM8M{Bsrcsz!Qoc53vko^R>5@_Jznh8mwG$*(WHA^SN!Kig{h8`;NzF>E}XB!8Ic z{qjEBCJQwdxX;>X>36bqN(nhYPClC1mjPf-)VJ=KaB8*AkY4(_oJzZP(HOi1ntgI$EHn z+3j_}MZit-tnKCadt`vDa? zI?$NSBxw2u9m~`a_0!)=nWJ3&nUjL4*i$xim^ugg6sGtu3_tb|0DU5cDz$pCGW^Uk z^yC@X zf06DLd+RJAI1sGhO*VR=__<&J?UlQKr!gap8h_RI>>&Q%^tEC9MdLV#hi>|-#vPni zd}dje5J2P-9VTGMTlhgIVq=;Uuqn+Zmb6IllSr+!pLi=jtG-A@_dcT996xjN4`9kt zapm+z-I#Ymx0pwEIuGJGWI6h`&^3l3j2{6<|0}BM9@_rh9vuB}Ikf~Qqrl7f5T>4N!u_d1(Tee+(7f4=$r&1Rd=(O+Ud@38rt zPt)Rjd=%US3(C!aD%Dvcxm>3{uaBYzxK)g)RrveI#(boSk0E1W)`?mr%i7p7tswKg z@b`J$x5<9&Yo9gQ>H)_}HRgAu8y+U0p%VQXGxr9GUNzvGuEhuCUXGnkDLjBlD|6D^T@!}!`tbNruFo{{KfcNN(t!x=jS;jOP&P!yYpRCV*J zs4@Mw@Gsz*#sFK+dFdI3yp#yk+*WW2sYGOpX5X(>CP~ln1f9?xB+Iq21>& z?~Z}BbGnUhAI8U6>;1!iFZ(9NOY?5m`FSU7nCzQO)&jnf$c0*ce6@}|SsHMUUKXvB ztwo+U3wPf5-YpIQQ=`vmQYXPK-Zk!M1C117|IW4Uyg?4drb!L$B0(Rf{~IeY79&P& zr1!pH%FYHxRoWq$QJLd8cceA7{`sSh%UQP02)ct&4rda7>_|r3+U^&8@h-ZRJh;_p z_kKgg`u(}zfM4c>pv<#S-ONa8%M1^i8DPz<;e!ZOv8GtiEvS7gu6)s?&0g#z_L4D~*U!3JgV6To%TH+yd0W!ch8NW3# zeC+H8*$Ju9H!1>3YUni9Pkcb@Z^a&*8DUx2YK`Jdn@A4&!qhFnxESgSt>Pp zpsV78t6UZ5x;f3x&oR7v%QWvj%6OZ&j%8;6Hfxj%31B;lgoluFop-H*Bz9i4Vwb<+5~J?b-73#x`u&b>RGc zxjU+A>W9u+<_LubmsuTA{R+L~LYj)nr3|W1O#;>y|L(G=l-y0%MR$M2zx@`1H4{)Z z|5G%!^NdS*%(gH4x2cNDnVf>UB_=+^#lH8RInS-oe@=Y5J=8E?Bx~g_hDUzRe<;MY zg&Jz@47WR)ytpKK>FzO_f?w@N=gi_vf>^US`wF=Lg23P`dtYoT)DapSK~wz9;hRx& z-3*{i8g8#!?NNz5v63G7(5gLic$cpZi*7o3y-53{;a!4;2#TY?!js|3XJfbH%93!u zObh3t$t5+3>q;Y)&&MW6x@}Q*#9|wY3m_nUI8?lsJYLc5JH38az*sPltr}?CV>XgDfA#hi8odg@|e?|MLQ%2rDBguJ8irTA9ex|-zt0P^na1>XVu6%ES5 z-?-tKM1FU&Y+C`%?a0MQ+%E2g$cTBc&e6YF*^d+3Ej@>!LH&Om$f>0A1@u9b#dhA9 z9PgLDU3E3A%S$3Y^tB&#dr=Ujjz;1GOC?N)Z5nez&WtyJ=YN8pKZ8<7Z+<5xZledk zbLS@L`C(xAe0sj$&jNaW_u@Qa;LYM@4NCAUHXr=XY_3>^20O`}N6$A}5ucvd<(C&R zdE#0lCgWTcNBUKysDch;iOIRVdz*jWo1RZr@*0wbN)A5W(U|Rn^XT~*QwiAuVfl0y z0uP+zre#0TZ{d#Z91%19tLnd55L(ijH#zwP@{^nL2xPOpz%lTjMd9p*Yhzkw|JbJG z^dGuux!27@c1#K0y&}K!-yiKdf1Em>N1y)Z{`cwK|H41e|Gp7|N8}bZzwcG~eShVr zdF!e5nCSZcp9$;xlDV$${&=%}e}p=`Fte|TZ$8fTeL-ms=?3uW?8}{h=DbAPUv-_i95{%S$A;g>&T$cf`%SZ9&a?}?;ivXs=KIaN44Ak;QA|+o;sKPzmWZ3 z-FyE>lVc@=TVI3y3Gk>e-zb+jdNYKJP7<^q$7X)R4CVXVLbah&K?#yvh0C+lbg@c# z8PYr8X&gb>b9`c6@bL5r2k{fDcC_0$97lu6@0Diyq0WL^2KKOS2WNynF@@U3KZ!<& zdFkz~YK@XccJvJQ^m$xO-WOOaLs)X&ss`Z55NqXanPZ}rJ7lH2O)e(4MF(I~@2r%~ zuREQ`y2kl+$3s=;DalFeL91v1Nmdzzl-SO5P3lyTlY$* zh;XQJJui`DH460GV&`G8S_8@H>6Y=VvM5Fxk491p2kW?oi^PTHvGb)u(WvukPCuX0 zXAT;C;*fn~zxN$3zLmKwPe0bAIlg~MG+*Y5aZr2|=YH#0xn<#=w==DfL;{Wq+p4>~ zKbGUzG+EP$P71Uv*2-|><0Lo;$pRWLSLq{p!>&V)dU^muzPFNI{G{VA9yWtxLMa2v z(bV;&_fKF%UTu*So(R!_`?I#{mFUXOhMC=sa#TM9hqb)mUIN|LEoKFDNF~x}e+pm~+ZxZJ9i+T%$PK5VlV5-v@%%5_qdE%^D24FjpzNy>IL*6dYSAW?s%1qsiKm$bX;Z{|o;; zaAy!%74rW@?hVj@^!6M7E*3GtTnNoXhi#T63zpOD#9<%+IY7X&h4;V#LUh;@k4d>MP;!c^rY81s{j#UG9%sZJ!B`;C_)8b`XdpoGir8L93yX zQFJCiB}b}b)XjFFcOd?Qa`s(W9HRJ;!Xa|Ia0p%yT0t{)C#H=n&D;M3FZJWQ*p3f1 zO6VBudg(I>Io(a#XP}{EPc(G2p`nXtf7FJ>4*yi0IAmbR?u&dRm2W{?3EhP$@j`C1Tlj67kp` zL@e8}pj6)XHetrXL9#qHBy)H!l#5HtbA$K3COh%LDIg!;2i|TA-EyjhZh15>bj!mB z<(!-aKJf1QO5o@$-v?gR{Sua&6TGj7ofEv+!I4CFW*9uWM#iPniba;+N?Q-LM*Is-#EwSE^nqZ)#Gi z+W1Cv*t6lpW8slc%L(H!6iD9zQS1yC^1eH~=54yRJ34F=U1Pt!JqD+p1cEYCEUd7G z{g1X*k>n73fev{<&WYiX2nth>`M#tW989m3W5+Qy1kUDV+;9xB+9NP!NNUH2lT%C7 zQi_DnxL?4)xq^^No$f^#*@0NFt;#INn)OWH@# zq9@^0af~QG;Y9y))0cfS;PhMueb-s*BQi~OnY=K096ck@Mf%xPehI5j@(H|=WMveu z;|_u5eHlfhIL9tKc}A-E%A<+a{WzY`{Qe{_!oLr<-vvFKqwPUY7QLxpZ1k?-Y8i&F zaC97zyyH!^ zre6O$*B~_c2C!b$y$O%uSNkLzp!JU4AGPnkDAaX(!^n=m1~{btbQMz0%YpM9`JRZF z3yYcd0h!@7iT872!a*N(`TS9tB!$t$g(c8%oPCKgVu0`3cyT{=LP7f9KnBU`W&2jQ z)Kx`Ocevia^Y>xueQbTU_wXT0y(I@|mfq1wdUrn*A1_p$=>GecH7iM60=F{=qk7V{ z&a0a9e1UgJuc}Y{tg2sPlkTODUs6RI*Y)hv)KLj5vuX)J!_n5HFobgfgb}TFjE3h z`9uo>*r3L{Xq^B&CpeMy28e2lclS|_%kuZjJQVYf>ppN}Tzu}jz( zP4;p%yQI7BdKg;{YNHxW;9zJ+c0RCmKJ&FsJTDaak>g^@H~`2)1^?3hyScyR+xxXoB-=w%PQDO~$Ab2xgCHD!Kjy z{^U9sZ_b~bnW`jG(rXGQmPmEP20Ml8iT>?V%FPKG@`}XrtW>18kIwDBNAs*1E6aV#3Jkd2TqdzhNu|0utBX)p2%qGKz3MsN8A=Z6rN z`7UC_o0&Pe^N#$*yZ9Iw0azS$gF;979%%UhGcswfGM~L z-L#wUFa;CXP{2xSB=wTV zw^eV#%u8^L>6`7Ay?UC9$H?J07-umR*yk~--kWN!&_K$}n}Jn2IGvgC4j>NS9vkMc zMkJYNaHs@cTJ&SGx^SvyllS7+RJrxdZKUOrF1gOica^qw_})ETg~e;t*FCz`WVJuz zeQV2JIc#qz*Dx6Ge0N0PvTdL{L$1j}VLKOnJ&`J-Wl$HG zMGFs-&H4;0dRg+%*YWoVcV;jIF2tZq0)do3C*1JjRvx#pPIeA4{W0GN372k*GY7l< ziJ_kcV*bN+hZ^5Rh(vQ*K=znEc?V1LJY_*}y@en(4E?FUG`!OJ4wDDL_zY6o;+OE3 ziE^b~yj8T>Y`Nb5cWHI4GY?`)@bz$c@-DgIpYb5J+`5)rVv<3pDIWGM1zTRzN^H&6 zzD>37OYQW249|9?f0x|WqmxHL2Ua*go5=B&!J{tU48D&Y4Um|MW5Ud5!PF`Yt*8*p zOX!_1uRzm=uRw>2m_7R!oISg8168B=A%afUo;?w3cGmEJfH9TtqJ~E?6W7hRSH7)_ zNw-ExRew|m`*w_~!grc{@ym>Tm$zhJShS@1)5u!lqNRf+?xBk$%)h-ui;4;rB@sBu zTwHY_D(nZj(WC8!5nARwtsKp{LwIYCi!s7BuzVZeTn0Uk+mNxF6hMcnb&W}+2iUb8 z)l8#P5T)Cj)rVBPQd2KVWufZ4uXI6{q<9G~p?TdNNPv*IW3y(t@vp-0$Y^^}shl(Q zz5D(A=cv>^5rsNF;;d#2T9b4o@qm19AK{+YL%P480_OaE? zb*G4$%>M#`kULb<*ti<38*SRe+5RlIRuG#F5u4x(%FhbSL;XUrGd@*b_EPKyS#-uP zU@=B*$jZk;c#aozI2z}r7s3cS8_%F0ci?eKZ994Rg>UJkwhs7hcA&SFy~Nux-r7t- z6&WGQECLbmk_Hs}5_9BsT2*PV%?1mAv=1{^I(}e@piIgne)@bgNG1&*oEo@)RTK4P z#>=m@6i-48(+|_R5(W58dAsVtH`!HKsfH6($k?^5eu#{HMj2E$l6cs>RuSQ1xq#LC zW=Sz>Hu6>R9-6kcn-9}&u4!mX-k_^yZEvGCfENa6tjgSc2;$>%I0EW1kg6YM1~3~Iee0n9tK}6 zBy`ejllKxCdXVIZPh~=mKg$Xc{q0Chjc|FMB=KXn9SNpUCHXURLJ;Wv6a*TRDFWG7 zg_g8M2DA}dd5u@!Hz!pKWQlVR3?yq#s#du>5}L9*Crga&$BjfY(F(2{o35k*U$Usg z*dU~f`Z6qiIA6T&-A)#ehc_zULEVCHP7>%3frz1HoYp^ISZKpRiVR)ut?85NzJ!9y zhX!5G6ACKcLp}5GnJDUC5bxpe&z27sdoS;1Hk`vh#d-)qb`70!G1;+8jDHrpMpD(? zk@)&pab#Fq=Ibcw%=-#=2zkMl?AGuDc1>n55@*A9Rk?W3PE4LGfgiV!(2yB~H3Nrd zro&>{CYRVxVGq9aEei%+q*w=a)e77yH~~mv#o=KcnJ)>)ei0-U;MZIfB`_^07V)2= z8~7(h3608wCGDP2=9~w}ztD@|j-LL7UMB^FyIh2wUd`4|YIT_qhtC`Q@u|J=2Jc*D zXEMu|OqG+}6kA0Qz!#Mr@N6YUq82WW4N3n37md|pWQzGY@GU@p=#`vmwOI+-$MUlUMWT_*RM%g79Wh9m#;=gz2`4HlNFep~!5{`yS! zHeu&>^FjwS@6j(a=Y`c)HgDxbolRA#>(@%2yuU55xl?ahF%8bVF+D|P`S_8}ndWtB ziH$U|$vaV}!X93-d&Xx0%9t8I2(O+!O<(%O@`HpO8 zEz_VHPhfPR6{Q&2*KLvLnjEp0(!VClV!x$W4UpPQh0Jwnk5&rQ$`DT94&NfMSV{_# zRLd>@8WYTYka`2)4C5#B0|w}FnNJ|mq0o)j(^JP;s!FmJ@{|58sm>?I<8&ubv2>9O zI$t$@QloZ}3vRbYoG)P?wz)PnmJ$ifv))OCL^2p*5Xk&Y5QyNeMN5nSAl^dfYzU1s zSOs*H&g`myrk?`SU4a5|MG4cNC%3-k0UC#*r_rpCBl=QRoN~@7QcJ8gSaY&_Prq!A z4y-=pUNU|(yVsMh)bVb)vLfuOGxmXJ?hIq6!7YdN3?E%)*=+0XuvKIl9}nG zJ&8e^{(Fc>)K2e_m%DKBI)OIiI^^bGdl z#&I7cd_~ePbiS6t_*!~3jB;V6H5vF@dJRm_Dx^E|Q6kT~?!bC2)lHNfF1=(v(7%|! z-+KC6dK7)0f33fz7tP;N8H4Kyb#4zWv1w1GG&kN1=n9C*=E;XTmGd^#8q_JPpzd&% zX@npRsJjZNvuCFI50-5q7(sOx)(ur%Jb4K|WY2#BU*KL9T}nm5o2--S8k9Lz_uGjs zZu9EKL{kg${VP>dhxu3Xzu(yF`;ozS8dd#*YV8Ofy#ajl(Ue)mG^g#b^rQXGsW8;|K^JwjkT0F#DUTlx%X2uhSM2?quRHAM?6zN6 z%`SA!&Q+D<8oXHT&FynuY^ zeR<03uRFZ_X{%Vv^}=t1!zJNV@#yIs1QOK{D)VNUG)W8zWw_~;zp8R7=P+G8f(#Wr z^9fB|OAZar^H*iP$O^Bvcz0|jZ?bwsWNdW>eo~R$xNWZbz@S2jfu$p!s;qR06FQr} zs`wl-h*-A*m@pB(*m;}w93H0bG$uy_cT=v}^7i?mR{GWgAs8Y!9hkW`fB*SmF~jKe zmPb=2ToK-=z6>gyA{-M*k^}UEZJ;y7rR>623t-x@O_Oi1Hy<#?v?P)`5w?Q> zUesPN^YR%Nw8iI=M2<1Q6sIh^Fl82P`V!B=BkF^EVVc&&7cQOku=aJ@9P>HHcQyPz34o*hhVq*a)*PN6w$Z%uPMQd+C1htoHfLA zFnRgbq)lN7B`#rZHeu%+LVr`_&ZBs0NqBR@uRg3m5SGX9l_k$e^JS^r9ObQ|OLE+R3Q zg2qos;e)WGcZz+mJspa_MN0a8{$%NiXY_Le&Gz!6V=#B!7rv=` zXwzXbyHsTk?WiX27nkYWa#o9&X4DYTwM(A05;a8l>lC4_*@HGn^Y4_rb+N-vb>nbm zWqkHQV4refpUjY6@LG!+qx?f<%Y%at6>eDvmRsr9Gb!l*|BL!6g8JYX7PgpDAM-=h zFKh)e2io?@-Se!*VPK6p3K*{8; z;4Jtd6$r(bl89vT>{1d1@rgA8E3}MHMeq2-*pDNrQwO8vdOR6WvCmH_-tPSbR>C>1^}qjfI}F0@?WwCx`)^vOd5l!AUKp3yfzjiK4dfUsFgG z#Rv^vRIjn%tO?@E}lsXnMlLOPv`B38-uml|v86K$po;-l^585|5;q8dM z73`a2g@q?R(K>P}2Y55LSe4bF9@eQ|jQp2{CqBw_nh8(5ivfDIX_G!1N|)IA$0Eh@ zUK*|39=hRavY&#B--#r1igi>a8|7eP1%W1x%L=i%s?;`ILW9R&4>NSL;_w z^sQ$A&U*5t59KLuJ*4|MoAkhc=U6z3X!2Nd*!i-ocf4=$HM2S3XO(|UUVe$Dd*(mH z@;j6NN6*%&T9W%OaQ-rXJ*#rJ0;l&2ubMe$ZrxRc{3QrXTl^j}7Kr-t%L=d5Pa<4~ zIvj`1L52Shb?*WnWp(ZSClDkcIsrkk+7c~oL%kGKl!%uE2+ZIF@Pg6{Rck@43J5cT zwMa0DWI7#Q~u;Qf<5y|`gt^GVR6Tr6T z{Cm#({`qL;x$I|O*Is+w*ZJ5SumreArbhngJZ@5h&KyN-uay@uuAT?$wAky~y^wZs zYeJGh(eEb-*!kM2F0Lj6-RWJ#$|j!j&#*rjyC zyKPTrSNbRJL4h9B>cP!Ca4o(z)wP&1{fcY&kay50T$$hSOWXtvKYy-`;CeN@jsB)9 zsSE;MmfqfHRQqt(+;Ab5fqF1R50VeJtNosOaA>yuueH zkY2{0prCQ4CRbdjZvBWtgjzc|{cyI7B<(X8Q2Ordqy4zW8Np{5*7{ZJvlI2%;_M@4 zS6IhedJ3I5JpZxD6q*T;vcLTgH8TPUGQ78!!Iu%QM%O)$QsHS_y5nP(9=i&ymC;wJHJ5Zon-qBcxy&((ChXGM{n_LWL#F zjR-TT)fiis=Y5GS0*G=7dfz%i+oC`amgN?JvR>r{!? z^hI^<4$TH<@dap*d`j^ruB=EzI;o#rC;yYO zX7F8K!C@r4aBsDyX1$Xc$A~vrWtrEmL%w`zAIX>N@8k3ITy}*|PmBJe8j{tR=t+rC zaq!5e|9HC({g+q%(*4SR!pciZhR4fN9~UAb^0dkBJr3b|&MDz<5DP%9NCBjI`A!LR zxT#njuG>I|YtQ^)y0-#ZD$bth`h>#ni_!9fvrTP=k2CQu;jE@2j$S4Vj8s|&tR!Ci zsV{N?q2E8=z-012TuGjRBMblV>od+TcA3 z+~lpxg_L9Enwd54^v@9n1)^-mHjw|SfSrDVc zrf>>3M-!u>iG?r&)7!}dhe0JN+=qZ4sv1s{!Go1pNXA>UmTDqjh;5L!y?&Dwkp?r- zrx^(W{Jha~SnWisa=6PyeEuY?Sq=`>{ak=n`(d9@z5E^{NsP+Yz`4x7c+TvrlvX(O z0G_Vl+IOzAtinqvqrKKzP?$+}<9Ep*-yXVgrglk!bWlVlAq6~6FvqhDuiu7?HbZGaWTU25RqaA8&ZxQ0^((@Wf^g&G($`ITSLl|&Cp2)Y~FiE)X& z!}eOnDw4=^24wkpCSoxrCQs()kB2ZZD~iiq(s-%-^2;k>JfB&{c>OA6yndB4UcX8j zuU}=2*RRsX>$emC%ph-kgv9K>qaB5vd^VaoV{mrShZ|TVs{xBJA^-+p=T9BPiu_U2 zX(0sGK@qYL@TE>cRQp6Yb;hCOdJiq_%{-Gz373U;!pPN@?$X&}t45Nu4@yEeYVMdL zmx%r}!d75Xg1Ffwq6hwPg&%kJ4nkw)vd?eVd?+c{1ysIseZSb4NMdtj{{-|Vzaano zY5V1$M}4wBR5wU{E9^?oqzjQ@yOe$2q(ZeDrsW|3$Bs^&VC-lZUsDtbvaNc$iH@g6 zetD@7ma>*kUG8mpWj7Qe`mh?&OO<7!4JlJG)(FFwx!3bZ7&>q0Nd%J`!XGxz&Z-*c zRo3X80FAY?YPq{z>3xb@D6z6|?V^r?_*puU{s(+lW zTKQNS zhuigHQ!}=iS(7>3wbc_i&K;?F2}e_7cDu~(zrxl^fuB-`^!(e~UE#}$mf+0NwRN>J zyH}p90ErJqhvt&I*PRFpyL!eo@k{exUgc+g{|c40RyC3R>%N%f%vuFvIW>~J5b1_i zq`Jww;~qdHcRoHb*~E!8GLWwuWPCF!v}APyz=&_-Ks~Abpm(UQgrkzHgF^M6 zR%S(It_kaum!JMLZqaHi zb__0}@9|=PPmv+HtxB8>r02Wdu^aYw;e7uD5YZUq+p216sCu-uYQsUkR*^t^9N917 z5nV^WGCw8V?4_~GW?ejQhJXO)H(g#nV`1cE9b%--t~*F)=yYD6t4ded#2pnuJ}s#xjp7xe{M&M#xToXb{!MD`YTLqSd;gu-?WE@Zuw7{l2q{4@&_{lK zxBF-Ac3N)p|MR}NUhX%uixu0ky8NSfIT8M9;OE3ruuh>mg?y#)27w?xo%PG;X}S*3 zl79+O2~hpLPE6KV+uAaX;Y$zM7&tNGXb5H$R*2*rjNcDYFks-#oFR7}DzF? zJOWR!{wlCVsB*rr;Tq*auhd#89r_dowHB0A;N88((RHa_D^As%_fAg@X~4J`W9e5v zmYcNxfDQVB4Fn%E+p6jp=Iv>47RcaIT>SEo!FMN0_N>iws6%*$66zHP$FPDkAnt}3 z4DkiHp~t{{+;F@0BN6(wbN1yY%V_DJ;D;!m=i!GZfk5!X5j=I1aM$W!5{?_`CSeLT zH2z`n^-E)ywpOhw2u=wLIrgr1%`cD?+^W@4(Eh3=b|%zs|9~E@iIXk*^4T-K9xg8q z)%VpNN{wu6v3TH3-sU0Dz{#^BNui*rP2TEK-jf$PckWym0nHma>6h);d8|(QNUHkB zy?Ws;Gj#=@B_B!hG8EWC3!lXjcPz< z;%Y9Cpuq-L+)^5ep3gbA~#|$5E65w8nGZ{amM{u*|YjfsYb#n1TSIxL| z_Q_Lv_IW&1_X7tB{b~&oI6psCPyo*U3eYictq&a!eX=`r+&x6?s{Z z{rM>dwvoie#qOa02~DMwC}pVouKWD@5Ss8kE0=|PHVIGB*O5X<^0|eB-fHpY2kijj)+5c>A4$!III+x|s(y$J+v@Y={l4qgY-VisQGyfS!II*fdH9m9PVUP)6TywX>~ z8>lx&n^vuw0g^X7wT9!az`OWO{{$Z-xY7xZG~(Omf7I0tJby4Q0ME(y2jKac5eA-> z4L*3*y`$d9_2O0QhFJ#RB3 zl`I&fxB6>y;AdTpv2Jdyx?LlqG1I{SA7z^1)YKXy_p;I6yQo|roNor$San#8mc+Aj#UQoXV|@n+_z#>&JIu;E4F z+NzaESJvT+HWkUik@Tt3MZ-DLCRXli&&38r%x0`G{W-RbgAb^lSu};YYV^2OmvE(U zOD%hPM)0XEj6&WlJ)R0=CD8I#52DsbL*of!-|2d{I8xqP9U7a#Upt&IW9-;xqX~1x zuP%Qvv{Z>e80lLYsdwIeolK;?R4nU>sexM~$%!Qs6aBVE$QO!>Mx! zH2rvV*z@5fyURdax#J*QdnV$tMmBnp@@D3)8BZBzY(up?BC)baEK?iV zIoldqx{fNU4M6H`+Ky_3#YG>cuQ7I_ymXc>_7SO9|2Mzk5;dNTX4^t&@c#?0H*f1dYWoh|12; z(xWx?3LdvBT>fNeX_0P+wM2)#!!QxPeNY;zmEKXSlfKNR%M9&tp6?;q4tzWHBIh#D zj|}@uco(tgc7=CsnUpFji_|vns2cIuKKhLJ#)jsMyJf3>qPOheXK}v<{TxA(cHK?>SDBo=hYho*G7%lh#Rg*Fcg5digVjt*ozY}l z3BWiCz#v|t_Y$c#6lyOE6ab3czO%bCU5hx`#yj81u~w$P!G*t|n6D6r6a%zP;o3L$ zAlv##ORC~w=4{tXn%Z5PC*hC9SQz|MGaKI+dxmHBA;4o-3mXv`@~pcbGD2 zH(L_JfS-&E+YqXIg1(0u8bK`*{M7P&MCOSfA}WVMOBEp%h9j%p(CJqcO*|H<-7^Z> zY~{R#QCz-)`q%MBU^nk;k(TW}BXUl}6YLdD&@*m=%ypS6H|-A(p*clQg5IM~mWT~3 zdQ5+#j}ecrh4c-N$G52N!gnI&e~BI8;ss!S)St5n_-rZW;ENMlg85HWH)IZS6N4Z) zI_y36bujF#(JdR@Nnt|`KNgvX*7rO282)D1Js2*GPSJ9Hn_9!hOTdh5?%X^pQS)a8`fWD+zQ20ZrVQK>9zAH-Yq&0TM{> z@>Y*P{iOh`-pxlLl}_l-*B{*D3nsrrwI&=Rc^ScuaC+VR14fq`*>#C)1=_30d+m?A zEorf!6y;JCO=)gYBgeY7UgLpYMAgcN#9{odba!28t;pnI{m6x+AZFHWUE^4 zsw(%Zx>EyBop~x<@a{SW)01zB1zVs$U)OfIm_I;Zhrb0vb(ipp^_#}R;Sa?)C#&pu zJyo%sIA8)Vm3gaA`UL-_I?|u^(ntFbYIpaHpANm;;eDP_xbbwH=ueBmq_^Z^TZZ2b zvk9nW7^)>h@yrA=K85PnG0j%R8+-`RyIQ{8trkJHhn*EGb*`)EbibmX+U!-KL{RTl z^<18K8BOq&dX#%{kzPEd7w3tCC~lHoQzOn&;ZsKiBYsq!@+%y|cWGJPrWLC^(?9(Q z{q#*Ars{rl#~xeIv3o6IT%-!}m^8zcMp2{zo)DT?~o$yk5|+ z>_RD&gDGZ*+9 zQr`$OUn|V~MYVF3|0exPc3AMfbw%#;#`MnYV~tk+MONz;|8aVI_PsuP$-Qq(cW{wC z5sUz~?$$0^SrGdqHLUbrIF;51>|aK6ww8B@>qS)}uHUBdpPSc?Wf^Sren6=_;QcnY z0^Tz$*|5#4Ao~RM*SlJ+9cz6^*x5t%mss`nhfs5RpkKYf>6jB(Nj*r5GD$z?&$R<9 z;iXb4^E+;VwOYZYTfE)99oG6O;%5zF_egEiMK#{7JV& z=UxZ?L3=TT7&gb=WGn6_#LSK~HD0-%X3t`n;xaw(O$_@nTB`2wp6)P3U7(*kf69L) z7uvPY8>1f+AyvvyC8Zxwg&o4d+z@EP`}?&N$c7YM53;D;?dKf3`}29oquOp1wagcq z-h)LJxMR>~3<>SEnD|}Z%;W5vY+902x%cj4dNs{`7>VZTR4YAh9J(rnuHyZu196!L8M=lJ55xeo)9+`PZAPebl`*UyhzsMyhz|%{(DI~ z)&|k~kq2}}THYoC6n6dnqZW0)Q^^}YN{eQI3qaRBkARp^&KM;4A+IqC>9mm73X0iB z*Sp@ap!+hoZ#JcrJZ)rs5F}vvwCf}&zC=s4bKDG*#UW`Xw zd+gjw^=&{9hks03go2}=~(u?or{t0xvyYeTyjeBjhtu_X${Fcp=ljhs-}OHV8|pN`T#W&`YOx`uZ08 zAk7VIn$Dto{-A&wRm;)YnFnh6&%ASS%G9+w*;Bz@E1`zW20zku>iQC=s`<|qqT7(O zRIR{(rCDKBO;nU3rxrTZorQ(U8C}V!h;Um{hz(8VifHmWR8iNISa7iZ+8ecP{auW( z@gz? zaD8MCI6DaX)zx#}0DNjX!l{WyN7X-`ANXtOgE`-&z<+JQVIaDX8?#5k)Y z?2-sLWcW<^6p&=CAcwB;U;?34o zG{0!XW0^6`q0?i4N^v$T(t*KFF~2j1mEEO@Dr zs~UKIV|u8)|3|KB%U9)=Tdr!~X%Ch<>#An30!Hye(8KMu@0`8!xk}T!0}|0LKLXSgo-BMb?p_qjclWx81~+Bhy*d>I zE;|DA7}f}!yO;W@C~!GTPN3Zk)7leD!E@ z0gmB2<6pwDs*Dvbvl+8Be+`O*fa(e&A15$R79gN;1Qb`hVCm_HDb`KCC<0|A4ZLF`C5GOTJv8(Izi zMM*6v+VYh@8&2@^BZX@3=N*~{%aJsI1M1WUD1_A2Ey|K~Qf3T_GY+cv!nJ=4g;UoT zdO!PtJ}0d+*?#@UdEkdgUm6Cur;y@3?lym2bY z67PAm`w|E9WAXD@Ut2&J;e8jd%3r`e!)yVw^pV!XCVxH%uf7+;`0OAr)eR8E*BVjW>ay5*H#Zd( z5JWOwD%c$$Vn&G%cYE7-j`cXo2I#8WEEj1WwSOS{Kh6I?NY40~Cmcg@gcu6wA8#n$ zLwQvqH`#j`a+9kOCKxl(BR)z?GyPM6Frz0|U~s;rkKU?DCd=41*w}~%SuAaVAwyWC zT!QXW`@|Pxtp8-*_k!YM`x+;bbXCOsD*o!e$#Nq1aPNJtlzO`*pkAiOB|KIqXRUV( zO2tq1bmhJA?-UCMk^AKHCB&SVsBK3+X4e?FFBX2g87 z9&YpT{g2#ybWu8QJ_>9K{Q3A<{`Z=X9>q2vSGp=L@T>TP`zAXd-{Ictt$FS?A8|e2 z!K7$D!Yyt-O7F;@51F<8qb>99<8Df_`AjQEz<~F{E~4b)GJ<}=#^4X=sZZohhz2x5 zqJh-N{}^O*QoF~^NydGX9nkN&_fGYDesiH3wqr{SfZJs6Wc@IZ$Y>D*i4R!nfM#`;jpj( z5e>x{QwELE18dLfD~#iLJ_&YqVoB&W``C_|kN-5=f7hQL|LyN(uN8DD*PqgOzt97d zickM9b;pe-)oU5)AIMj=b3$=pya%bTlZyvWPfz*uF2g5wwlT?bbA=>oyMC~DA|-Oi zNojt0Sp&pB8zy^{=oe&r=M4@$Fus@=vY!bj$3v=JOKj5);t4coM(&@ehD0p2t$jqa zn*x%MV|~1hcXvA!y63)W=$V)L#xh8{W6g(;UIT1=)6;)_YX9>)7~j_ZR>)gTncS!* z9=l&Yu2ioXuITjicm6?r6@GoQy4AP)n0@P0{vD&Q>>N+#<&Q7F`PEVS4`zel4CIfO zlsCNk7WcHL<&VFMN8(hYD~leH!VTe;Z9Q?A*eU${ zg+^$u!nSi#178cL`gKIGp{P?HLR5qhVXYnjo%y^8T(a~EykjJBN;Ae$Rj|>m*nNK# zF5eQWlZb}2hpQ{`f=P@g%b-N?<2{f?HNHQSl$0K=rJqu>I$5=uYsq{HqKWZ4D7}@^ zok0#>?!9p0ph$A+j&S0_;;LkI=eWcq0O_e%63r*XeMNCJIjJ*}Iv2uzW2nyjYlxJ4 zqXd*j+dpoh91amD@eUJ^p1=!n67O(5nrkx?o{5sSb#NqsXlxQ<2TO1tvj7X(@uFXb z27SXTDgg19{}p{F1Qwz*M?zJ8rEG=_;HNQr2w zs>$1lkO6N>Zk_GE^rqetjz<}1vjvABwOg+9?o;7pN)5Lavh0LjsA^2##f3H=^w%rM zfJi!2bsx=F-S3BrlmB=J^Lsim=xL;TPs^$riP{7cSha$nR2XFgWtF80Ox0FdVV)gJHfV11 zI5&S#54vcK#clQ1&;=LPGR~DhwPJ0W3{Gp#-gkH@vtG~yzy1bfwT;w`u*Ul|eMW*l z#cHbSWIENSVK_DB>ci$oGaw%CxYg>Uj3u7p|Hsmo>4PB^YzOj_bNU5w%#;drEdwg> zZv2jk5HPB+6-X(3SN%e&Yptqb>n$!J@#|m=AV?l?z44=_zQxEFQQ@A$7aR@?HWXis zl1S>}{+ZE%d?1|gt*~B497rM%tOVZnj-V;npGabYFC?6UknnOe!d5nt8edA&ZmVrk z@}Q-^EGih&TJ&jz4|B?>z%S@6#=U~x6(XBm;1U93gTA;ll3Xx2!|7}B*KkiqfQcEp zck6AkImaZ{=VVe+;O_PMCKP!*RR1R8B|i%=m5lO!3yA|r4QB=j5)i6e$9vW8{eTzg z-*Jbiph-eaTrJ@xr?!KWFwqgXSGFlzp;idIM1(Q_um`M-rHv%QrIEy3Sae)R_*b2n zJ3Nw@GO99BQ6VH$jqT8IF^U#pE_ETK) ztEkZWr)#(tI1J8Q7R<*kZ?lm^iswj6-D5dE%qz#=KWl8^z1(O1D1kZIE7yhlxF9_i zbQ7G?fyv2JNQnr|P?ao)>2 zg)-XTp*q46P{pDZ-Z4B%*K_Ax{-D7RGt}gLxIMR1uBTj$_W^`qX0EZ<=;1EsS+n=L zo_!^As-F6I3vH;`dt@f_FmoJ#a;qIPIP(5eU-k0kFlJ`r-J{TlYWHWGbYXbOTcAGV zkkLXuV|?E52X^N0@df8c61&2y{R0;{(hLLuIop{3Jp zqv6-NxI`IFTe^C3QWFM#;MrKtghLY^4?om)&C&Xg@|*DAo|ACh}%fWpZ)Fn8deQ43xvjwsCE28;&X3 za2FftJkHdovcj?sUs(23E;iD;Sz+0`kQM~gV-xj`6h0A2T@yy~AyFk(ZlSu*g1ZR* zP4z9Fg}@ufuth)gYta`xUX4;vmVQP)RHr6DK1^7hsO+HAR9q?YVKRt4BJyDZr_L zor0!D%R53h%A4KD2RB+HA2iyu(6-122An=ar8UgUWaEVv(ME6MtKhj#99^4kqP4Ouu=AxU^gy^9Idetn+&O!STEKI_F0)t;rl&xwB|!Vf+|rFH4ln3aFIlXMdj!&JuXl=oArg zeVtNdOjyv*Y30xXw`M*secb%9-F0zIbvn_mG^@Oi}>{U?l0MmFQ^jVy#~;O?>_b*xSQ0VgWqy|_xyhLO_uK-%f0u= zAx>g&_IOSVtLP7!nDPN^{x%NBC#8Yz~ak&~@k#{Z+*CWLk7 zaXE$mFHtyvwh43fC~P@9m2}DF?ELZBRBBG7=ax~c2wze{PvO$eqSU#3ysSbed~FK? z=~S4@5iev$S$vQ?R?-);N+eTOA$kC1v>SH7{GHE*ZaPVArTYC4o~NDj!a^QMe&wjQ zMvluB!YM?VE~Q?@NarU=VMfquvP!xnNI21wjhWOYN}xe?EVwl%u)i zo%e7CMU!QgvvP&5UGmN{h8#`Q54N9_$K3pnncr**&rfn=(_yZIwP!}wqc{lFb$m`? zR!;djVOH3B?a<9DA;1JR7>o)+Lbn_NK|xXxMG^sOmhKmyjxY<+6A#p&2?jjR$mh3P0(EJc9Uj`btZ^((Lw2Xama};v=vJ)k)ab z6}Y`@M1^AhA-SZED)>vYZ42k3M%q)y+V z;&^`7=%@VEP~A8-GaEfT?4<+b0wsEtCINd{j+K`(gS(%{Wt_vIx}K_lP;3-5oUzlp z<^!EGMzf1=8$hB9kZ`A_V021T5UTw#li;KPC~Q;9Y|)ZqjxY|sWK3^y^mcrVA<^iV zBQ#||@hm=N67^$G64#W14?&V(s7g30yL4rZALc2PEdEuAb4Mi?H6*SxLN^{xU1tPt zG+9{|cwK%Lax@dor#BdYEn3Prb?-%j>}0C2r>LHnoj0a=>j9Wm?lT&TOkFijl?airI7Ht@V?6vi~V+ zL-ylVoDQJuw{`2GZs?3{Rt&1x3HC|y4uw=>fjYE{M%n5QoeJvHzbw7`KZemRyW#-TG8Znq# zvl4M^&DXA*d#PfLwt48N2rv8KcDOO{uNr(%+J z2ocvdgJ|p9h3yh|H1m_$kKf-=#^%y1VZpjfRdsNvZ}U>`>|rXVFeoKDI+x#lvP@3n zk?^w(KeC!*n^zikA#IUSVITx>l`E2Bdni}}Y3<&5$1jW?1 zMBiL`gLo8zuGKd(wC?#PZ{1R9lS(I2 z59%jr$sc*>apy3q)zW6q?YL$gqsh6$kqU?ECW&L&&qBN%uHMfxu;yg{p9~kxe$g2( zZo~%`ci|c;DJzAJ?Be8m+U0lIiLt>DR>RDsmA^WP2PZ11tFiiuq^|AC zeA4W{kJ+K%rPEZG=@yYB)OGff(C=y_P=oKuiEk+!2^V)S4Mt4?>l8~PN2P3G5JOL^Y`%?tOEB0WGy~S+(!1+DiF?;A8fj#t2m*3-Am(eGC{%5VC)eN@M z;c#9u{3+h zz@9?zfO2Bt@I342gO%XXQbJ{_vqsYX6F+|cX*qjoF0*l7?7GCJIBC}=|AxLcH{5nX z(%}YQM;su3hv7coWcqQ&EW?fcO{P(k?EW|A?-&!9Oy9~ZdiU3hL`E#-wzsBt>7DGP zQ0*DkAs?u)oIW`VRF!5h?G~gxYcOqTs$Fgm7~_rUlWf5b40aBRzFHCXE^EjEg^Z>z z`e6VNS)*w|lrxwK%8A((ZWG-(+800on55*}ULuEAac}&os10`d7+8hfz9nvIv^n`RsmUerG zpLW~ad17X8P20Y~HR#z-yKRfAwA*in6D3-;a92eIk|rfptE^cxydXY^+##iG4}|Yk zXlO}?*;+N653WX5Wz+@T7X`urTgn7V*;e;W4i73@8BR?Z%o$(7yE5KoM)>2szSvuO z7j!_EGy|4?4x5kRAeIt^2^gJHMWH$(15wM7oZ}`lOkN6?3#Xef{WH>Nk5;3}Z<20} z!kYje1X;t?jH2n~@prQGMe6~;R#hkGz(f&%QOw!f&hap?Z3ZHu?u)pp9lF_GFEDj0^1 z0smjIx~U6otieF*kD$}(&+&#M9(cg^`dVUSWX~riShE-8Vtdg>daq4riOz5MDO4b* zLcPSkUKM)ahEkWmj;;(>5BJYsm%8>CjDfrN{1fW+D|I#phhBG2CX{QRf(w2~c$mz8 zxc)^)TjQ~dXe>@+3a?C@I~t3Z5nefk+GgY5$fyj-6wHf4w0L!{_To@N*_ASbDH5uE zn@gMSTzhLrF+%U4D+!8{T8K5oo*gJ!LbY!V(E+@Ns2FjmF-sP(V4$-me8aNde+3-aW2-@xp^M z=c;_PJTpIxLL3!Nb39d@TA+DF{H4VJixv&7PJC-9);(Bi-XR=j>QyFq8|Cra-Ys0( z6FaE%)4Fua?w$6*P8jSx=|Ay|(`OW>D5JbrNQx3ke08`(&*Miq_+bHHXBJKaZ`e@G&^k`uqyYOPG~kiyTXys-k1Cbajl%Rxv71tJRIhsB~|! zBlCOzT+jS=U;HCd#=B{zk2lCFmQdjPs!f#*<1xr`%w^J;OH|26Vt)wq7>SO zlwd(D&D=beM$rl6=;^aG_<6$8Og5J0$vl?ku0=WOHDGC$H3k&yfms>^$d*trewwi} zA6`p>jE8M8Ibnz5K%PFErP^7w2_vRMjRt>MT)FqfojbeIAMwiTx-O4qUpNh1wcrn- zTID6wP;B0y*Z&2NSU2*oR?PMO`mNkRM22_V5)2}b4DW&ruVK*+xJf?v_mSa4x{=|l z8COC0>8)~G42Q%*b(n;CrQ#^19Q3_!E%tC4Ac2Tpw<5uD*;)(812 z9sT*CPk)-rXO{l7z2?)Ow%edL0A9D>iu37DENe5D`SjW{lU^lz5S=%gILXnT2MM7P zCPT?WCqsHZnI%2V*RLho=L5tYrH=HZ*?oNdl1@%0(sQ`2Y!^F%R4m%~##)Sje<#8q zNot%hsF5pg1P>`CRi;V}^7}W$8>|;O`?;_R};o!NI1)YWU2|w$%$U9E+y(q>}T0veuz+PLV4n6*_or?QoT;zv4bD9PEx%=qYSsg z7HDf!j?$lNdh1gMGBwH3BV%9kV+x&-t8750gQ8D zSM-=S(_QQUxR2`czlUyo&#t{}M$H%8z41-yXSp#6?bUN;Ux9>{I0HQ&x*|4b-iVE; ze-z*NRfM#_vI+N+Q^Z;LtI?^o89ik%q2us|t{ZwdfN| z=Dn7ZcO6#DmRSVHetPC{4Xesj1Orl7lr7%UcWha6t9Y$F$SvPzA9l+p0ma4)Eogb% z@)4|U1w5Fi`dB_}M7FYgMwf=Fo)cvUHhp$hcKHJG$>@h0`k?=Ba1l`Dl^k-w6y-Bxl3B?xx0w{QU{->u|by=^5UTFD>SwI`a{k985MTjZWuyo>Zg zZhS{$qGOr)spOM{h6D$7*g)iWp|A>3-;`t-_r&dP(LW9M7=i^Ia7wqll)y29MN8=;dO=PG$BG-VJ1Lz?rv5Ewc9Yx$`g zd5e+t)Doc&Z1=PIsjCTp@v@U2KvM_NFGyUys5E|xw*AZlg@SG${#7m&;vP3G!=y2PaT$joth^f$bc z+4ub%2TcNrE1ujP2D^Z5$KL?kwq_~-_NO$uf2pR@g_}o2Y8~sQ}{DkU*UF60SKx002s|iig>D>4O%gHp+3aG2D47ZOzSY~t^dP(cIEbtQ zz(iv&ye0=7qOq^43m{`38oQR+hU@&_C9{pw2|xX+PiAi+I>`60HZ%qPi-ab;B$3D{ zSzOj%&L;JzDKDac(P6(!`@q*$F-<@tVYmEdG})q{()Zg9N8Wyhd_j6^skMVVX5SyG z7z%@aargGFHA-gHHR$9Y_D1g~+SQS~)41}^qE)i4aY{{vu8XhOC%v_ZyCA*wLSfou z@5knKGkX@agRNYDZLTO8OQ0vM>JvS+Z}usg)GVJ8Zk*|It=g zsQ&wu`IsYDpj?lZTVky4NA3tSq-0GysDv+3L>0uvP~xGtoqJW1C+g6H@LFXQCx_nW+0Fm-&`bI>@z`)Ud;W3Q89p7?Fn@|0>=05ZvS|)%N=rI?|a|Kfrt*drHcaa*yoU|0RjA9KjBs(z=XNn?}VG- zPB;g8*_b(Y!aem$_JkYG5IEtw(yKHzcET+jp1zYC(FVKTQ!uP7+m>{mA$i)|yEFsX z{bx>|+4x`8=U(+s;$b2DwRl+JKF^zj9Qs^mp}&tlSLEM;^|^H4B4gEOHlt$kkNb#% zHrBVg7+J?5keK&bG!ifY0@jrnSu;6L{U})}<9HB@75jm*2s-6vCfUQn zW%X6j{UT*uNVCsoo&QX6djPwd-o9N;UZgA$!X`GmqgZE)jx7ro?D)4l-t7om!yNCH zF6_RJ4i;GEW$uv5g*Ur5SjW*h{PKTmJ=M#9VLi9_h(8dITFf)n^CN#feSxUIo)+^g zSWm?~%U@4Bx%XL5hX?=BdS1kO{yJJfCcewt z@`#xDEyl!~#454HJ9rDaB6K02_Br_-kx&at5wubLQH{X|lgO99-qUly5VdFiz7e_= zXKt3d_RL>g(;Lt3TUK%7hXW`Wo7`8dnJng4xRIC&J`#!1L~N7%3Df}sEZjrxY~Utg%+ z)8OG^RX-6M_~8K-AF}l-dr_D=7(=L@F#jrB;>zkLS9Z@|k)-EbvESmBq8%zqUC#e} zvmWN;=gqDj{rL5e3$vYNY@%HHV6O7yNfLK1=Q*L}Oo$v~pGK1>=jF5hCT}yFgZWYU zS$X9}taUFx(aHu=>H@R~gt+45)e68PHvcnSQO&@t&dAsSsnH)I>Og09vqU|47BYKWeltgE~9Y#3MR zy8-+3Zy-@DtLmfs!TE77NHwByp+>8BE8oOj2L1LX)B)LdKgzxHc0Mo72M;ncKBn5g zP(o3=i!;Pjp&qpVTfCnzd^rgxwx@6V_#XYhK7EZ+@#E6JVuxlv<+{RZ2#I>DkvVJWGTUznzx;lu@6Enu9ts49rFie9 zf5_wX6JnnI<09!EIh6J0ZQ1bWk#Z0;SFJcW~e34p+%+MlQf`s zBE6qu%D$g%g8&wT&AEs;hub%6Nq41h%D(mYjQ8Eu0OPaFmTLfsd5_qUfhBUC*cwK* z0;G`sGS|{xH9cY5&~26Txsf^pE;F^Nkz%q``OQNz8Q;Rj8TgoOvXB0gO)=|9x_3qZ zP#b)R!*hI#cLJ}xl>`9K)Vpq&2*JOUBG_H}_Uxg$H|a0kxT~gdH+7-2>xmL92zQVR}v`I7>GT&n2UpyB{G*@<=Tk8Gz z&+L>lI~m!M4f6a~2nH7b%f4P41(uI7q%XK2?JRW}((FY)GJP|>c$dMJeuH-bHRY|y z>whtr&>8PN_6uqu9!8rthx#ZSR)m=If1|hsZ+O?w?H0hTTf7J25sVVrN-W!IvyZ3r z!=1X48P0JBxiq|g_9Gb}%ih5{c>wLWgwu$p9`58$D%Jkx@CT(+%s80w0`IU>j4;3g zjU8IQgIY;O7pi*)P>H5yEQzM>ZRXodsgcKd{0aVL(b20^K2*1X!hnD%Kjj0cfL!KQ zJ@9@$Qj$1TA>X69Gv-~2HkpQ6c+y(`7=MFx0j6uXMNsAq`CzYb9Qa_Ted;!`ls?{V zPw!OdC6W)#y>#BCSI>xX&=w7yS=mMe{&}RtM&6oSqm2n zVcu3um)9pm2E{s&FQmhsXD8I{uHKubjSCMiM;Ea{=&!k^qJ@#9#HrDH5l?&BfEYTLJI^@p$J;H+! z4h^@bs{6Y8JP{)b`o0GGzJZQSF~Y36$$N^9<;67XNsn+6(rW^+u`z6iqbcjoPr1np z)qNk@tF?X>rMo*eNxs`^k;^{DsXf~hLOrEYsvz)bzvf4D$f|U3vXFP)RZu*j&L*(f zYQ^V1WuN|p9x!$UA;Og6OfUFRc#nD#o_||YBSV$)_V^3za@%kz=kJ9*$TPGRR`$$f zykSj0t#xY9&!-YV^^BhZ^Kh}3^KmKDr4Gv7>ix$wy_=ZHJM585+^B`tddvO4dXx8) z>oo#RVPX72X7CdG*c1pvl+$x;A%^plmIb!S&x7KVa>YwkE?c}r#U+A(`_QS(NOJ{R1rHYPfa0c|L`u?ic_p$DMW<^caze;&%`g$vl6nEJ zVlAXns=#~n3@{C;zEl~zl@v=4m+86aBlek!$}-?6W_cFZJVE(bVkJN@%kN@ap_oATM^k=o@xNJa@l|}AL521q6T8kR zw-@u`*ImRB#bCA2&cym&t+H=~q&W-|A4U^vDwW5kX=3Swo7f7CQPPiuIVqZf4g13n zxX6qas6d-(*)@5&d9y}RPRQm$x>Sv5_P&kBJyU02`BPU+4c@z)fPj%T2i>Qs3#(?V zNkRN~*fpf!A9YX~NV%!gpu7j{+v!cBslGvHF&NsS50A{8zt8?<{t&tnA*%cQ#i=0k zD*9;u{muKlpBlUmD`Xs@+P$&Xk14e7`XRXYPPBe3Y7|W5*}v&&mVfV-LN`?RLu`h< zozQOSTe)h?nx4JNBRfo#H?$q}>unT)=PZt?pN%OTpLf>A4l{lF5O1YXf?Jpji+|AU z)<-|KKJ=}ZSLZ5g&^sOs&hr1nyPMVhdpi}|>h!eJm ze-A=ln7)d$u9K056NeHLl?pAY5>TcNdD~GFLVStL$s@iT%X5jvd0y|14H6p8xO#5v zy3#9W0LeNw!mF>GaoxppFOALO!5kj6)-T|1LFI$Q;_!2EZSh9`RH6v>|H$%(jYWE% z2jWS_5LG+iL>3Hrtee*MYqYzBgmF{6E zuQmOUUx%aqLUng@?{As3a=lYl^@r+iwHKtj7F(|xB%$!%`f1a?M(gTidJm{r3}m*; z>4`eT^6r1;rou`~56(MU4KQ3U?+B`5J%!r5UlS41$6uj3MVY0fa9C!sHBSUcLP8X0ancq_7*XYSSo@8)AZq3Z%kLa~fo#XY$k@u_YlCMxhTkA9wktY;d#5)>TsG-c^ z)AVXrcs~lOFUFQ>acP9XRTDmj zeEbB_P`kYIzNT8*yw9JNAHy!-7tf!f;Df+YmBk@c@Il2#wBUpJ;|c5&i(pE5ulR%e z#XnS6ltshhIj%o&{6mW|PP|6TbfI{SW!)Og&R@{pZMY=*?Ok7r`Cgf~j?5!`N5IE_ zu1vW}_8!SEqh@&_HXu;E1m=^mgY$ZuCjh{fF&IR;iVAEXx%skrBFZpxrv4B9$Nm4y z&vX4pzeB9}9`yhJQ=jg`Xyi}o4|CZq-^nK}KS>{1a(dfoSFmGQP0}}S@Ruf=;N+iu z{}s7{X1|}b-}gd4Bm7DdABKs(L|7Qcg%|0|?qZa;Sr^$l`cg*@DD?elAOHQ%v89F( zuOIF`Wm!Ffk!;{jwdm6@@#lXlYNPk`biY_PaY!&fbS>4Z!WHto`PvCVP2Z%Z9E_^I zym+DuE&;qOKhYHO6HUqO*KvHss^f%h`HAw<7ctWsRLoCsa})*h@PT$>F^^=@N+~}- z5#nFvCo1#af~eRpKhb6$`sJ0Mh=LW~26lL5%?-l~VlE#}jQfwvhhyt{>>uRyj6c-3k7L#k7kH}kB$Q0*<=?2S`L$-m=5 zj^f4-7MPz4LHZe9ciS&6zI*NVa3t|3S&}Qba4t=xQbaDmPj<0o!)db=ksz&|UaB1M z%jJheI@uf}AvKm#`}#n%=+V9z%t&2k`Q6%;w+u?uf`AbBBbULfJ+dax2ckVf5Riz1 zfE*g6i99(Sv-1|Ww*OX+$dmaxFxmSY*Bo+we#rJ{0$(Ae3qK-vUS#d}KGgB)?Dv{u z=T)jt*vI21TizTSo0cK2?_YC({E$t&{TO>aC1I@p3GY9~R?o6SiVWV*R&ON06RJB3 zISjUXS^VtsL!NR(cl-GC`!M&`Kl^AKcTRTdeP^PW%W7hfS2f9Uy&p}bTY2vX=B9gf zm-4JS@n|$PzhrFaB7-nZwMgGE$uQ#e52x%FHsR- zcfwpNGD=0luE>MqhEADTnV7J!wQ29?b4eoq zf}!|1rSSooPiAfF>`9*Apr0UeXpkUsPtSQF#pPD8wMhM+^0Px;QI)fl3XJK#I4!W2 zGGn?(`Ccq<_vVbnA#I5#680Sk5nJ!YOm|16Z}KG(a24q?TCc4{q7zMQW!I4^axYXl z;j~}ZJb6zauOoOg-m{Kk?Fr= z8|m~Hw3iaEI2&?DAO6qelWY(2N!A#jpx`K5C5g;49w(pV)_-F@N!)YC4K?fW3k_k+ z=twKKw7gYv86q{WrQI?_zW=Xfh`e@eZpmdF_l*mK<<1(%A+E*K?*CGT$UiXVg2>aa z`57YL0Jy$)wt#B`!Y(pIZi|kdVHqM{3)SBtSwJqI9EWHx^0RWHw~a-(F1xtbEEl!n zk*Aw^;6j|dA7qGZ&(9FKg7?+hCYjS5JURQRe`kKkt$u#USIi#H@wbbr1BYyaNUVx;2_oMQ5=8bx|MwUau3{$i zjwZ^LA95<--8Ygzopri1c#{FUrH4Gjxr|;g6f3E}WUbz|`XTS#2rOKQM&R;8s-JW} z(Qh3QLkK9+Jvroyr;2=3R>($g33CnEmEH*Q;u zs_Rwe0+ms!%X7fG8I-_++2tO7YF$d~>{4Ii%)O{1Gste27sfgDws;?&$A^s3J4yZK z!J9nz7=8j6==TeQ0WxHCV<>#V0x%Z_j~Qj5N%J4WXej<&ocIaXm-4j=ezv<`qvrV zUU%acSGq#pYRcsH>%?vqYCdd#djlkM$#RuL{ZiTYN+HM6WhcU4+MPWM<7ED@0+4=VK3uvQQ3Wq%$)&pY~@^?V|I4m{}3OzU;Kh4?gGefanpN%VvU+j>V z?DqwpZE87F;`>rJ+x_c%plTfr7yAM_(a_S2C@B&NlWVPlCHK}JYs4ez)})A!B*u{{LZMeO zJ)u~`2un?9@RFAyCMDWOyG0{pPpfJo<&TEy7K%Vh%;+E>ca|R^9UA)Tt7}4a=c~b# znOmSS^j;;|V{27o-!M+wtrbNx+6u0{^s0Dk)$O1pD}Z63>Z9p)n!~G0b6w?EwX+Tzf5@JuxI{A%g_8YnoVf>1>+uUcf;#H1|eW2c)*OMy&r$phup~cK>u9TtV3LQ6tewk;QxB3@aFAf}13`h(6u6MXlYHH--JMA2s zg$=h(mJaukr6|$;3huq5eg(!JB*E^vWrDKS%t`t)fIoR4w5+Kc2;Ic3zc;*Z+$i+z z_8Z{T%ez7^C8Z#qAP*EX3gOAZVs8pB)cN9Q4rlI*pNa(ssa{jn^F;54$`H%z)Sj;GT95xq-a9TQhD98%7O3Zht{>OxbSVE9h7{R4~ z;TmJ4GHui#Q6AaDoL?rh%%Dnn=MDNC;?in)Zex`h9U(_T@*|HJvel>bYJ%_Tn%#ka)S7-_+}?(b7QLdC_t&cG$R4b4wQh59DpbsPI2@UI!EY^E(S!@Tv~X z!Md7hzGG&hvRGU^fv3rBm&4DB_w|vmBm1t+D%?K*f*>H*b`s_luN}@bdp|qc_`h)t zbD?-D%6Mc3K8k*}utb3tsT@$^)`jMJ4_FB&#uAM(UXb3#jRJCIY{Q!4XC(PmQvDGl z3Y-pfAwyansuPPXhmNIX*Fzc3$V!4RUwS>SQ*HaGGT}^P@1CkR3oW5CjD2s zM7&8NG{oB@!*)SoMOyauq>aMx8WvFhaGvMrdko{?YT^*$R~{)}7Y&W?2(LzKu78UO zAPY|1SWSGw(n$H^#6YERG%*!Sb;dIqwD%uJ5o-_ToOHa+WDnahDKT`1x*$O+j;WFI zk75;()KoCw#_+HY!b?6VV^H%K3ft+ufnWaoS3_An+8Ieijl@E`_EG%JNvY#IwAXui zSKXsMzD=Ht$_phJIl4Riwuh5_1QLHw%dpN?p`2M=AAdi+*4E&OaP78Ex=%FaHrnZo z48!E2Gqm&@j5nOv6dtyV+;5?!U*?w6KRRqT;fBc^w!1WRqq34Br0r?2t9tf;rT?yJ z&~QjT7vA-}GF0u_GAUKGgRFx)s>o5C-@mb;l5v0D%HQapcZ?17@7KP?33D=3&>G^U0Ff=?#!Xsd*rIg+fNtf?WfEA z{dE43!hY*NZa)FvSd)n-yGayck7>+nrt^GLhw@0-)Z{96Ga+n4ui>M_^eQdmjNbMOz3*u88&X_Z}lOTR22N^z=)vAvyG&r|-2D*qt z+*(GGdgBPBM61_0MQGGn(fP2?(UpUD*<*Br_b$e~@BWhEI^jl{K8dlTsk_wm%n`wS zW!EcICt4O97aomc^WmLUYXs4Q z_@l#i81)6lx#=p=zKLqQJBywmreaAn6(;b_A7dM%$th*19Gbu|D>4Kq#b&XpL&z?Q zt>gWn2ga60lV7I9#tam_?PF2k&tcK>{jumg;N4-- z-1-Ihb24}o{092Wn_Eq@~e@}(#K8GPKDY8xKE6f6s0nta$GMu`AUGLTC4Il4>$m(0 zENzpd?cLxxkpbU6gccHqaY%4H04_Fn$!Q~r5^}^qo zIl`}3+GO78CUbM_bNMrPbK`;LFD<7*ic#_Y_Tf@d3fpOg^FGdO3ny?l*y0_x?L*9I z-ijShgD_XkK5(!cF#^iE^{UW|IEtgUy*;mgh+{;qkU%PL9Ca_z1sy`fkv9B4bTH$2O6$3?;`DEp z&d1(}m?cl>5Z<2Y#d==j){{9Vew323SF?(uh+@4J6CCbF=f7;YD<(P;AVN4iDt#ndPsE9sFd$l9$~fZhr7@9bo7jQmz5ALbZl?kf?(&}bsdzFMPEFzS%+h>aY%=GX zY7r^-%lP*H=TgKCHTt zomGu^%KU=kD>BE~{;y8-8;Yd3xKfmBO8ps^IDSc_c6~`@*Q55mGG10g&Q+KHCB8A5 zc$yHJ&`KYY#v?+0>PTwBzUXsHYysuO>zPP_!wA?u6+@8v^`acinhyj-1lPwd;I)X>gJiGH2J%@7t5h@?|U zy1WnTc8>qr;kV>O=!|vnQIq&>h2GdLdSl>b9XkCPPIcl*@4+97>i9p@oeOwW)w!@U z$pjJz?0`W*QKF(H0zwpp$SngiFrzby7rfM4dq8ZpUYg7h5P`rXklpFDShd>rc%<43 z_8d=94~SY|0+<9)381K;+*H`ZAUA6+fSLdO*4}eTfNIa*=YO8x=aKB$dtJV@*0;X( z-B+te->y#EyK%J*ERKGW;wDIKgF-(|8mstSl9Q-dD{fjPjQzgZD`k-Hxb)k9cfbtY6s*fA@Hc$OP(xd63-^ znv|zfu_*^~_J5W$V(VK5^5^G(_E z+PF2rNLFz7Nr$bLE~G6v&b=kI+JaxfF*BRjg+|pog+!CjD?E%u5`m=-(PyaaOB3|G z1@T%vFH?K{hMZ}-H#4VlZkLP|ve^FY&_sJYf=AC1Cww<_YbgqlF52>mg*6U|4iWGY zJGb{78)w+dvS%R@N)9dghQ-sW4hgOnp+`7`7JLVX7L<&$E-nAGNAIif9T^@BCxOg2 zTn9wkB4T2fgCcxf{5fk(6E!XOOTfC@M6y~4wU*`$m(m#dz zVu2{j_t@&ZMaL4TSpEa6eCm9bvlNV5N5$(}+`+YMh?AnfC{X%~K0bY$OW(yc*T### z!^Eeb@QD(5mjw38Tal&Itcn=BOqS%d%(4&PZU8OXdRjbhN8beB-%1_)MI;J9xvrl^k-1(=oma2RFEIx;pyZrb`K7EemCd7&^0n{!7AeTq{5OC_s55> z4h>rx>KQ6n6e@Veq5BK$qP@b4%MT?bXIa?*k;gtpN3mUMi_akpMck2 zY@^(KA-l(X@o(k}>Dqj8qk8e&0D&c>0u{*27dQvciFE!cxR%~e_|GG0gm5q1O*N;t zap@-~fWO)3P7|?DIOe4hf_jF^pOo%7&-iq&fMtG$zG{gwFp^t-qgWsnKoT0^)!~w* zs35;TD}FN^LH6NaiV_kpgn8>k51nSvN^q}8#1_BW#!aT}_*G7JP%wI7OPo{Y%jgvT z8e<+qo!{qd)cM2YNt36`tc6EfzV1d>0i&2}g>R9=`7pT^(Awv5;%Rx^~kUHa;` z-DGLI2`*$(S^^N@-%XvpgDT*|%d#>n#Kv z?d3uzx6auzH$Rc-PVhF1T6e2x?BYcEgg?eoRim?6W4x>(f|Z3#Nki_P&zQY^MKpfO zew^R)VEj#q<4ihITL$v>_K@H~B*+uN#|rIQ_4^Q2Z>S9E3pdJob-0Z~t%B(EruuO! zLJ)zZFY|+YVsb+00YeXP^lkIlKG0sjwxG0T_J^g!O_a@RHQCW)l+)aYr|Qt)r5ln8|NYGJ_Z0$(+m+iO0+S zEGeDwPjSRI!CKbuZNwD;6_!|CnmumYG)m(a`(zXI>rvEQ* zaIy-hnpP#J2QRbyPrt!B$V+b5C^cW&{grRn&6hp2DnhZOWVTj?w@&;GSW_w8Q>*G} ze(1zait+(QS3aDjRS`HZHMn+@xcm4Uh$r%)K&ukIC3+$6-1YVR%bntUs+9lT)tj_x z!9@3z58X(WwQUHo&FGl41yT7v`$I&g7v+2SdK))Sl}~nQtL#@hf-U#@&vWUuj^O%2 zN3gaU*XA!Ox;TQ7IzBa(4RL6z^126G@71bapt3`6a0DAD7@=Ux7uv!wFN3vp!Pc*} zh4ZBK+Wm$8u~O-5D*1cqn}VAPgZ0(H_!kv9s$f%D;W%xT_lmfDzcKy0)BIjO3Xxe0 zl64{jk4|m=S{^)c?pkZ{YU5xw;sn*cCGXga!T8w~#RNc)t-*IYeBUdviFH|~VG1YM zgnI|Zzu>w7X~z#HFBOg(o^3NW*py*Q>`*XqTpRWf+E~fzzh7N(bKH32JaymEsEoQS zWEu&)9p78aC&;dv1IPiG853~5-4v+r#O41>{^cZSw ziAUUx8?|h8wOg<-BQr!@dOaJa{}?vRgKU^@aw-NZ)3)q3*)&tS1#Wg^b@l1*x zSdpXh8=L=PYadSO9_Wl^t?Zdt58h{**MTS64_&8rRbC2$*hp(r@oJF|fqtOur7^5n zVlN$Vh3*m(vDKxw2)CBTpFlBYbpbII&#bMU1yQOkYITHX#DlXNIU1KTG>3lNQM3Ua zZi5Se2hMJEl^oZ8Q71d$2|im}atd2=0`m^YSz6UCJXzav3fq#HEBRp8s>pg3x3=aK zwq}9(fvtIwd@#4>6tPz+8^6OmSd}VmH`OqL2V#iOr+AZh*bA)NhLr8%de zv^j-iMU%G6*#Arx^PLDV>O*^$hnKZJx84j_KpW4SZFq@&Nvwp}DaKuaFH{4ujW#y%SRhpE8fj%FW2f20gfz$CP^xWBq#oz48ik|Mf!XL}u zYycRNWMOtw0Y?qd)@oH-)sHzj!MUXwTJ_uN*G=TVxHVr}s3JzifdNbq1yqr1G5;^( zf6))hxyc`qEci3Y{38b$zlNHB3e7+H=AR7nkKjK=*E3`n6_8h<@U5MKCekhRn@x+wlykPUu(bC$)A zC;4ktL-=bs8q;dr46R7)juRo1zkX6`C*%26c7nf_8sCPWKZ5JQ%gbc3e+skY4t*c| z#11l*AL2e8oRb5+zm;F!&;vw^eyLS?_+g@DGLHpE-(YRwMJ)20mkWLr9YB{c_|X&0 znC);X{76`SOyi}6VG1YCxwLR?_!4_L!aJ_3Cub`ii zLV}%i*Wc>Ni~}k|Sml(F50#XWda)vOL#i`rNjVW_naya`A-+>gD7DmpBVb#(Dlw+% zu9}eRZ@TN}5bdWr(bgi$;1Pf;rR2C3X+knz7e``)lKiKbGSDt*%l%hXR_^J%bzf=Z zQ0G!@IcDNpHYm%-NNxGG15k@st)J0PtiJE+bx;!hsjmgT*lOm@QP(LWnn%m>IZv-u zpWl_wLKhAK0}A&gY=OlNF8GMQS4?$RW9&jv!zDXr2!7t#-{+Ma=YT!qwB^pxmE*5) zjz)rtY&H127!v??)Y*+0{&{rmpM`wU=pO07zhdG>4y;DSIx(jLm}pJ?LroLqt!xcr z*K@~Vcy|n2{^9(c=Z$waN9C%BT4Suc_IOXxNtWDPSUy;0LncM*F@am;CWsONJUD_5 zLU1#UWJvQ$u^2plr2KIlUe2!Q8MgPVsa69Gul%XZ?@)0&4Q|xj;aN80`DVGnck;99 zEUK>LI~p&PlFvyENrWMPxX(ag9o!}f*1#Z2Ac~o5}2%};)M&gzh zj7|NmsOHq6l8|4`JzU*1qqBsZ)rp6pL|g{<+1$Bx>J>NG$^8=J3yt0cpYduC%Pa<( zu@YgFb5SC~NClLoBFRpPBKu2M7qZ=^y<+utM43~&Kx zi>;!cTcYK(l?}n8W1Buc&1G`0pd-Z%7~=vdecH;I;ayN|#VIH^{^+7kFz(nk(!y7i zz9V%$EB(S(;^i8elkW{p!|W)M#6Dwk+X)clZdL>fn9h+R4wpg|oy@DKy%14|XG_0B zjI?&vO?qd#L+rhO;^rx$&&S6-7rq@Ez>S*~7fTwnTy=?w6|Y26aEVvyV%~f4l?qp4 z6NWOb4cQGvBz`OVC`5oYT=_3}mIk3C4JrX}(q3y_9*jr9#2j_WMRzku*6?2zyHosI z%zWgv?p(1k75YbY$VZMhO5jRg$^E?p%SigbC2KN2qC&y}PTe;OZbL_&jTZ7j^aPg!N8T)R%fI^ES9)5AJ{)is6uiCsAVg2V=B7uKoH zDq`&Q@k`MU~AZ=&EFw>qgeD|*CNVQ3wIB)z^$5W{pY@r6p@?UINRvQ-K$a;3mxMw zAubkbmg|H>UvdaS(&m0MMM$=}-%P}!<3msJLnGXBZwq_r#<=@JIYCPr%D81~jXRgX z_54<09IY(oiFcRLi|&}5}W1@6|E#hYq-%ePx+N2`lxuJ4iQe<JDoH-HB=N*g8bVlZ#@CqSbsl9DeCn(-ZjysB$(Bx)j~4vM zOAoZdkAAzn6g)U0DJ+S}8t)7EFi|V;!=rxD9Tr%zQWG8bfDL#J*>V93zw?byHw2j)&0eld-|xl6W}*-X~)h zqgVIlS{eCymKzqDac+!tk!MFU3Hjg0oKgtI-mNJ1Mn$oK8y0)DkO-kI;x4PtUK~3Y zy1axucv|%z_>@d@@QflQ*knrTg$}!V2RquYZ_LNvO%gm!P&T;U2k-GiogtE_|DAOc}gZ1miIrsBp6&bB8{i> zaIH`IH2yuiq8kERhSCboekJxjOo-}gyYL*F@zIyfsz=4fiPo=TXB_|F)t>$mO(&6>RAS8I1_%F4;AmHxMz4?`6GyI(-n?|fy@sOd;%%Je)M->Xz zc|_SDBI9;r5})7~FTio3BF9nJ8Fdbd%iTw`svWF~8|}Y%veh22%QZ~FRxQxEcztxC ze8LwexUUV@YweNj<6|Y(?2&F;%)h;^k-y3FSz>bfc9(yrc9&}eW7D*g27kYvrfok; zbQynl9OKCO(Wg`=-)3;aRu1sEnx+ofK& zpDF-O672R!FPD1WzM1;`zoXY5#|V%o8>Nkc?sBEwf^7^$|2ViuV`!bV1){0ew+Huj zb{B2-gokx1mO*9v%t3Vvj8=o}^{M&$`~ZKIz2GZtPX95}v>zOtru~?)l$W z`NrreZSGETtB9CQd3+^I%$$oA0>W}1rQ0NK0=R>3A4y%T7HF=jUwfXcfq)EAt z0B%3{p(2I1p})#I7x!^nW$Wbu?gMG_cOF+c>WU!&M9>|6{3yI<#VcEf1V)Ph#I-Q7 zw=DV57rxKNjq&~^;C|jPzDGwdpG(G48+pQ1>Q+Wpb9L?BNf5Ii&}t*O{DN zB-_Zi8aq=gojfaCiqg>fBm^Y6AFCpPapsU%rUv7oM2Di0Fc;Js(v_#{a4Dy}42re6 zY=}R{6Mr}G-{8ZzI{RfqJn^?>aisg5(LQv)#1^old$?9861fH*fv8W+q3D2&7+z0U zLXKpr(fWrAVZ_f(CHj#$Jzy;3)A&035O8N!4i*k>=FDGe1F?Ij5nmIzAA2N;+;gJ} zxtEMm$ZfmKMDE`_nm}$)yd!>(D6Ne5&=yt}virq~>^|pk+&#rUkKHB*a(p+rvN^(` zpLbKlyjKfixECV1i|qdH@MG*OlbI8Dwz#HM_aa73!eP0e=|LV5%h*7O7JXF%6LMhP zQ|rM@4uvDQ4V@3!ZSim;`%>UQbjpQk6+i38$KXkl?0w9WB=0t*0dh;m`gJ%DX#~G! zhxV&_t?B|Ak@gD%(Q%cJ4~-WF_K44OaKi;kLlHZVw6Ei9yjMxj0wv_%Tk@F}{EK`K zJ)9%EH#?)UwJ+=AysSmcAKN}@oZZmP52MS2$5P_ zIVL0Ud<-|*jnZb-t+Z)U1NpF^#>XCgyuZyjm|+vf8{W`#yu`$VmfKNi8#IlbJ8cn2HE4)@ zWAeaQx!O9|g1M9N=Zvo$HR!HDQ~>;lC{mkoLjt%1GVh9js@-wS=*1UM`AP+wo7i1o z^XQ+%7F%!)HQ_=?YY*8<8IB2hH?xTHnl%2%dnis-%lR_g*^Nnko%wlznguNKuiMzb zv8WSxl6bXF)iLpEk*xP!+*SeIPsgXT6ynS=nb9Xx6%yq)iYvXsKXJ!A5d93`yyz4Z z<)1=%w9g1+cO+|mY0+Q$8*r&swG7uKHJyh8Uq-J~rLL#5^;*@X>c_1)IPo^c@)o(- zB_;1^Pe%N6v{j?7aOf?TdG~qDyXThec7`W5^3`;_ z?G{h1VfW-73GUZ;H4NXiqvR#)@Be-v@w!EMVr+q)Podq^W%`N@d6a^*nkjX=L zdEn;VwfKQWvf#JNe$7K$^lPqwN)GN)exoWMYhOmjB=?)p z4f(Gix(aP(k^tVNYF!WgLi_M}V*Tm!!r<|X{pSRakM;MgJU+yyIZsML?~>gC_VGF} zD3DiKGDNGsiN>glal%)0Qd_VfUw&exxG$od`Kwf)oM2Zf8uoXb7bqc-!o-P>WFqXH zWM}TIabYBRm{?9ukpDhuO}0l(HYOMtThj6$F#LRxy-ou{Jf_J8_3EFYwu#^-*${gs zIjm}PW`r!mUx_JsSg`eCt*R*tM}yX}+*Hm(Vs9J??2Oi{d9d7dCQ@5XWxRNY`14V{ zx2pbOqWXJ0NPg{-?SZ|~R^}kN3|*-!GZ4<+(DSf3ofWV5m3*NEIliDazDUez(j10> zFtpcLd?HJT&c$j>7SW+{n96eaPpBDnrL+yKYAe!`xCqG%PQVLjpd&o-(_l-Vil2C< z*ekuZNPM>^?6R>=<==<653~&q+!XyaASK>9MV~&<7Hql9e}AxLNMKlWhWS;{s{B$_ z=fc1R@;7sE;B5JuHP}C~{r==y5UolgKUq7i`VJmYOIo!5$Z>P^s(bM|x`4)uBd^+& zc|Df9)TXv<@fNQwDp|0C3&0Pkue*7tIKI8hyYiXX_WF9mKhBcAzZvXzVzaqikpfte zcviru!UXbRADRE!%E!CLFZ1_en+maz08{i|foOCwpQWw;svOmINZ?Pgejt`4ziacB z>@R;t8g3gL_@(@fj|nU!-A%lf-e0k?Qi59Ad=IQn^d9Mi2xFyVz0zFd93d9SRIUb= z){B{%p#1pT9q1R@(XtbQvqgurs^jO#ZKwr#a>6SFX3?XQox(Ad97~YIVb>&mSjC*qZtHW!mzitEGEu z|Ks0pzs6CyJL0Hpsnn{^lR8W=4A_TZ+Q-D4fK`|}*NyF0mZTX;FD2LTvkUAgt%u>Bl7&@*ul z$V3je1>P-fsO#A6S1mu%L8=W>2R z+tjYTNQ8xnHN!}zb!$Gfs|2}>rSu@5V-Rvqju~LZ7CrfiZ}%gmuQRE-hqoe2slL4GdK9NIf>|?z$Gd3rU!|$=PoEFAWorxmBq&z-4gL=j zDf?UKp1?JhSXT?MAoN_F%NNj7`|Q&xszhszOl(4K zQnPvDYdLs2u&rbXK;_gB&64f#DzpQ7_LfY9wrZFbp3@kNcPZ0?$n$k-Gz*{S8~Y^7 z@oJ`5rce^aAo&j)Zk6qtEL%}QIlJRkX!5@D2hULEX3AtcUbRb^iDxJ?gfg8RuVzb` zi_^-KB1$BB>x5jf#*uT}QMo4D5e_s~*1p6-C=JB&_1d@%+VWOM<#7o9QQ*~EYxme0 zV1cG@3)VG;A8V}KP*}ONjJG4WX4PTueVLV75x~u3ebdn(+})DEYzo+=`pW*NhsjTa zzTQ6k@M@5Ac;-swt43tTdXMcr@5t-(%O4QgmJ>fOH+*Ar@OU;!Ic%sZBbiZ>i^SXXW}M<7@JUGmX)_$~|K%*HXO6kMve$Fx5ADN?Ntx@1-CV8Bc>zuoKrI%f|20s!xDheD~uR zbX_Lje$v}nM8rMpu<5Zq80T=P70 zS@8r+J$ouIFZ|O+eS^Gj>r$2%e(d=mPPz-Fz2Z2v9NLq$m9>rLCgG?Q{2JGgz$>4# zhNLk*B6#)_%Hj#nfd4&eVU>p=s3SsX5K@QX=L^IAo^?9R5&jq7q2joSQoe|@W>eT6 zcV-xo-S(VX=5iPlBXWaB|2RrEL1EYe4#8n88Y0+?OZ4?AYhD3ulxTT%_*Pk! z=~$BjjnQL7->^1s2P4l1TY6~=pJdsQ(H3SW6+!Xcj%A%=bIkpGUqmR!#dc@--x?kI zX48xLWS6oouJ9emuqU!B29aj~caT-1MmocDDRaUR+*s&@D8PMiYR#j4S9lg>o-ohE zd8U++Gx@@KHd3udN;hGhXTzcoF)i>aGGQQG{lxI7xFe$;;!^3K;2+PF5T z7wYD6lG8(^Nz>S(Ny%2AaQIlm0}h9LM9$TggwOe_u87^{*6kMG@Lxd%n26BzP(fwU;0+n^sf?44{q1A zY}niQl-RK8P17!VST_82g7Bn=RrEl+sZOHnxTJ_w8VY|-SoqTy{K2rY{Hxl1c_to2 z6q0}%ap)#fI!@55rFMS~_yd}}Eo=jCHuDt`XWSYo1#fS6MjDVj|N5~|2RlAq{H>#&&UVTRY#V5r%!}O;&4#GP# z5(&q@QS>|dK5H<+wZvI}9Q}K%Y=+O-UH)@X6QHA>AUf*8jOeGBdrM!pML%c7%rm_7 zptV>#_{5e|zM7)`5w+!B!^UUDM@lX~al!J@Ui8F$RqTONxLN|=nr`zg_ zO{>!V{I%pMGB5Te>iLnWC0NT&eoQIsU)!;Ni5)D4J?Z2g-mT-^8s70YhNxR#$U)r} zSgRzT3#pw~Lcwl7u$s?Ne-p;A7!?m=x$|Qv`|v2S?Huf-+Ed7EYqa1t21}Z{eHg{s zFpB**KONk48Qk63TU00ON$1%O{RQlG^^nO?JtP4WLwQQQd!(25A~mG**YR8QAzzKd zK&D|J`y2xqCN5>11H(mb8zwc0-+@W)5v==Tux%fVYh7t!v)C?6)|Bm6 zBJFSBH$=T^yuBBp{RC@*>1BmnKR-S?gKx-IYB81XZ1DkggpN{l)KVdd)H8?>T1Soj z0&H4Km5!7c+~C#J7FD1WxO~*5fn1C)up#dTiqR#Y1n@0oXWi0*4qQ5S( zqOm`!5Gzm_ohN7#zMDdKFXd=+UXJ?Z;=nDaWN`b#@w23%{BkxMX+5fqEWDk+0=q^4YM50ms^c4 zlsj3&dA~yr4)=A>gSG0BQT72v%Nx^*RjlQ^ujFtbM!-z;0jfAwAjz@Uh+NeAjoP%Vrf#LXDK3 zqSGJeeq}9uu`K)`nX6cyx#C(?7be(j+6|g^Dceufmtx7Xr+*T&OIa$F&5zwCx<4!v zGHBepjsM(dje9~T88`k7Wb#y-__*;1-x&EAPF!B1Ea}ey3Xc?J3)wGl5GZepUad|R z;Wi&)i~3{+0_2CWX4RKy-C!--&FWcZ+wEpmWg_r3V6nb*9w#vZ+6DSYmmr_TM_c0A ziMbVbIBNQKSMH!9o*CkB8f+2qjQd@?A70J5+&y!pLVF3EciU4-Y`npi2rPIRea zbe^XxmI>mCvznyP=IlIfy#2XEyBx9>E5KU0GQ@kpegP_|OV!ngLbp3u)8^6^oQPOw zs+a7CDh=X=S9`Ix?EYZ=>R`Oj^m{#`{d$4@g7+0H`B3anqTwinF|Bun-OWTFW|t2@ zKkgi0Lwz{1qLWX1aZTCx{u@PF8}o?0*A;ViG4LZ9(DU?a1L6qjtLhv8e??!ivviob#ldH z?kRb{blY0vdni`EQpVp8uBSH?UuaR|B zP8HJcNSYSu4{xkrMz=6>Y?5jgmh!B~2kCfN%ZC%J)PRiW(|p25UFL&aN?0Lbvg+(3 zGNLnO=1h6!v%S`M=J2i~b9LPK1D};plVYys1yPmUk0L$KTkq%dV=EeR&nt& zK>XYDqca8Ukm5iBVpoek$O|=z?+Jdin?xUZr=;196 zeP~9E>kmwgo1vilz1gLjo)1CTEzmki5 zNxzcs)hoY}N#`oRl9xK0ekG3UE&tJ!KmNRfOJt<_H>)H3HFmvCJ$Q_Hh!j5Nv>zzaXFaIsdx$tB?d@I&+im~XGt&@nj4-0c#s7!z~W+S zxU*)pC>nIYIJOg#ZhNqWMN(G(k%4Emsu9qVP?hQk0(!-0bx01>Yn2u=ZfP;k3%1PF z7ET94Yh3S}sh=c)W~KB=sMGt0SJ%0=t#qtZtYK(;i`Qn*_YrpqNnrwuwE5*iuy8t= zZ|dyPhwbtesa!Yi6=`|QTX1=`r83y#)FLyiE&M>u%0o*e5l!uJNoU@O2Yyee0_n_m zyH{9l-l(C-@Lj7vZsc5B?=+H= zclgt+jO%p!A(F{9`0r$u7ehwGRW9WpY5;1h2&ROWd!sjmK{>6IKeAk!mkG z95zg^9c{4@O4nQCdta|js(NdDAIL9DOIzdHCj3N=>qEy%Fgqjq6Y7svT*SquTGy(b zEdPO7ep{3qv@Jz0Ma-8UI97t88PV?v5Svrx%g(Q4l5rw7P~Ii%mz`fBMN%Yoj=ZxB zm_$QFAkfN!=}?G|zHEg{go8%7Jg>H@){E+J{#t&BE%S1*S13*_HQ#Uod7T`Ud$4D= zR+^FMIF?Y&v}cluJ+91|TMu9OAqor?>KxyoymZ8#ISGqkzA_OL#ksr9)BMq?_Drwn z-u8@D=FB~v9J#F=EX5czow=KQ;k=1c!I8yX0f7ifC`sSlK{6$gCN7 z)JBNg{V4F25+uIA!y?gZDF&w|`PM*53%{-lkGfP+Y<44gXYP@AV&otKzoI#h)@3@nW3aVkGJG2Zs-(BB1pXR6G7sy zKw=Ki%{MlY+^vPcIw7*@et6YE;z_$onGx#eg1_NMnxG*ptRB@12Mnk6dv) z9+NRiq%Dpq{=!9)t0>jq!>Yd%(qG*8A^l0eeZKrU<#OH8e{g^|^ax&3Uvf5u$a1GG z@8hUEF)+|$sf~GydVs7r61_}>hw$Y1Qk$8rI(@tdUcM5e{93AA5^!Scyd~G>3Xe0L zpt?J-6*w>=IK+x@srs6k_^Qp{&$!b{bkgRF#8z5`%iAA#@P-}Pw5|0JyX4--(<^W?fbn`^_!LGx5L-b>Z|<>U;C-A*~zcN)8Q>ETI3D? z5cct)_A6YMH)vIIJObZcxd>`|WG1!h?GOVA$A5Lb{^U*rImuklG_6;yiX-qkJ5b@ikQj> zI5IF9EsvNM7%>21Dnh?4M)J+Ido8_rJ!*APx-VbP|8Z?xD;n8NSlM$o=hiY1H0xBH z{f-!5>L@|oMs4}_+>LbEX<887!-X(om@}tCd$^ma{+CWt1^YdQhx+LA)L|DgXX4{6ag)l&dqhU;Ds`IV!A-&N z`?>hBy}taovHAVeh;#(B<1^Jhj?Co8f8|K>j9-erc^LoqUQ!y!8CT;RtXz#SaRSA z3TMdmKKuze47@m4BSR0PJ2)Ik{HZrMb0RpwvCHXDtCEZxGRo*LJsL8c0G;CxMX>d-&Et15{;WAW?h=Ts#l_QpMIaI ztdi6OsR1%N)B@gNHt8YPn>9BldWE7Na;?Th=|TJg-D1N(u-O{I3<@xJRxje}W&F2% zOZa&uyYkugr}Y*UwQSnTNc+lGAdQC;jh|;WPGd_XzdF`2I#_D>%np{qo{1yb>DI~} zo{))qz$n3}vV6E{e^(h)cV;Rlb~h9udOO5ShLgYzCe)lm(HC`1K=2#DRNKu``t3Cu z8Gn!-l}X31_)#I!FHwohfco9lMd;h0N61(E$v1gGV0xAYY_0+0s|ZSrEFL zQI?y^#bd^g%zlPLwya@&nmNyep6 z1>v>?lA&s>EAI>g_%ve|S0EkJkrwxT z#Dj>d#@h`K$bM&ts2MOSISqrCt7*8Ez(gqRUz^Nnn8-Y((Km5A>RehgW~uG&wWedz zbOL|wUaPlQPD4YKKDwrp-ePH^YbMy_S*ez5CS)eOcuH&LWG%HzBbEdydT6tnRW#`l zMA6KpS$D5h>gSqHX)V~6W~L>L5&8?Gf05-db*|o$rjO4P$S<%UCm}~xS+{BRolq}K z$XqFn|0@P@p;D%wc@VK*|HC09&X1cX&EvL_{EX>>PO}v$A!$O}ytrVIHh&6l$S&Tk zkRMfYrvVqQIKf1H=NrTP2uI6^GM0c&QXOi+F?@IG$7&DcU`;#m;8z^_1vkPkG?8qQ zRgU&L#+zYf=rN`fD)^VP4@<7dwl2f~YSh$TAJtacRFCsr6J5jbc*EV6hrf!)3dG(! zK`#g@ff-6Jdcz4Je(PUN6KCu34%|MJ+nNs_h1wX5`0IV|fZadlv+b1UvKzvE@4P@>IdCm#QPU+x8LisGH*p|v z%-frBQp=#&U3X+U=6x2I!`ZgofyW9)m8j%vbLv-`GIuJlTu$%N3wj;qs+a7){+wy( z)9(Bx3-xPiS0C|jaE9_;^KcIo=`^ib*g%S9nT3KInT3yiwypB~{TspsH<8i!LuR2T zf*-z-b<8ABw!r^T-|zlkYe&T$RAhH>Rha_JixnK}FuGW@{hj@ms8eUCNtTP88| zz2?w2JLc8O(9`>L=^Gs10`pC*oa$4njsSO5a!V%TnbOEAm3WLy6);ZMw&RwYK_ z)6bh$E&2AoeeR+sI2;qqAb-_ z_-MG91CPg-c@&*Q^(U52LfSL)7py_!NT!1EQWp)fU?_AjK|joR-gyT_Rx}x7!pR#Y zu$a^i+l;R_wZ>!F#>4!f{~L~V0u0zkF;feQkymyCkxVfpfLmOc4 z&p+P&`C5_shdY(TsMmxWQGBz$Hu{xx$;A)s9|5q70#IdnA~^_GM%3{Cv;4n=|5s43 zf$}m7FMVb~aXY=KQ=PZ!vIv;u_@n{uuxqh9L^OeLAMSjz9Q}YtE`34*duXwv>1~_b zdkw#Xsj6G7pV(SSc>{}3z~PM06Q5LA=c>u9aiQb-83Oca#$jGEVUET4DZ~$JOE}wo zrA)CJf$Bx>6I*IrF_x7yD;QV*Rn~$DT=`xrW?58LGVf_BE2JS+6@iSZ&9D_Q>`*kW zQehcaQ#y8bj9!wjKKt)x)FA2w?cPVbf*P~8%ZXfXOkRG%#Ihtl0O#T>1kTP)6H9G@ zi<`y|umuLCU2Q#|PHDnKlxP*rqjsBQJjiP)>xWaAHNv<{{mi!oHpaFH8mG5kn%4e6 z)&8)w_AfHqH!hQwll|n$Tj?h&(GR!S(a+yuDWq~>ZEQo@b~y!qAz9EP8Vo$^*40HA zs9+bl^`|9`zB~N1WDIPYNIL}{xpb8>D)qFUj1*a0tf#+~C57#;WB||_HR9z^&m^rwlC$GM&H-B(&RelA>j4+9v zz2QGfrfo;lL}vUPz!)H4$c1|X2TFW<|JXE7=-#0~LxPtRqyYnxBC3$*r>0u!#^gPK z?8kY`qkpP04T_=vu<`T%On@S$6h5GVdRZm*wz8?m$?`8-&&UK6+ATFf0R?(tIw&P! z4Kp$^pX5WGCF$Uge4$6&05S>o{_F~Fx?L$|`|)At;EbATsT&)?7nu`4@#--(Cq%P> zd$uGflPJdr_|@m63J|&Zqg)g4q&i?!)CnlAe5N73Ub*J}4|@q#}A+kljUYbktnatqszVIopojk~m0;6)8)C3XWBDbL>*x{uN$KGGk zOhyaPwR%ISWoP6_@M_IA>FJc#?xVF(-&AAoQtC8~y+|Kc4yu|hr){XO0&7sJrP|ZC zq;5#yLe*0s*+D*2XDF?Kmj%NuHa~4#qAGBnu7TfnY(N=XPi>%#2DrG;8~PD+yW{Lm zR*fWQH!$lo5Zs7vws=RA!V2d9PdS|JFY}K#^v9vH>Y-&ON}fDhTR2wMFg*MB?5+Ma ztjaxVB2O*1xI;O~Om({UekQ=Dwf8!|izA-qPrZFw-Wm*(!ugQEjH)X+nNQb<=rr0j zA~W5*%dt`#NY);EhT5NXs4X`hJDNXrtZrBP0gn6A^)0S=>3!eJZ~eL3Wt#*~9@Z9i zk%`pFSVZbSb9=q;XKSb9_NVq1w`u72EeV;G(2Gij&%MTZYqK(%6!pUYBrHTJz|9X1 zHo2=&%eS#7BGEz27C;H9VwHr3(J8C6(FCg2T%|~~iQgtTvm_+G9XMy59vo57nt=Rj z&9?*MIs+g_Isl?k&IAOGqXQs6`_pOXB?Uj7|cwTL@gcrJ3=^Z<&$i$hQL`JM45ga#aUFZjs+f%;jL1bP7Di zA5IGomvtz7Ph!juz5`glKLc1}I)L>cztf>w3$bcHOE)E#FFUGO+o;C zVVVDS*w*FS;L}(AD`&7He7_^yC3;W}Sv7w`vf9JtU{5@pct_A{ZOkG6jFNwFQ(POnLjD;n{|t!b#5%?7 zayJk^0YShwo?@R1z-k7OFNX^JOlWstUuxXSPfPezS4J5w<|uY4^{x5DuhW{Qfr+Bl z1dFzRm+`?y*l(hK45D^cNNCf_3&co?pNna3#?<%$j@fsHKmx-#g;(#d5jJEoP@wre{i> zH#}$n?lp_ZzcW?&n9}d$H2)FupS8U?Rk|0Ucqd(4Ll^D`8~)vEYek9j{L~oA+`Q{o znSiyek`CQ{c5>OGj~n2=5WR}NwQNOtN7h?XW$&LBJt+4YBZA}cg-T@h94zSRYmV|vBikGhriZaJas%6kwTN-uPLC@ zqvUTFM+Fl8wizQ?QoKb1L_n=`r;!0)5f@d{lSI6>{}dJ7jwgJhO$K9Y7plXGxP5ZbtSXGfBysKz-~Br3Ojr zTbd^JR-1Fy0HcAdeN9=m02%9)l8-%*Z|#AX`IN3cIb}cewv>PRWLyKrktB$W8577_ z61Xrr2tvy=`1p|P3Ej#RP0z2%%Ooa6tIFpaw-H;DI=y%Khn`R;6p=Ei=3C;>B){~2 zIr&ikWpQf?Yp7CClWwPP;{GPs7(o>RTR7Xebn11=qg^z(Y#D70_j6w;>hsk6sQ0#7 zuD{IZno9B3S}FUn=u`Y#i|8B2wIi~^31F@lfO_Nq#$NGR5`QZ@70v1d{7C-jD*KvnT)FZQg^7@8ngU~gYV|3Lu#l}ROO|mJAIi9-l_LrNRRH`Dxr&H-~pQG z82&1MQGy=FP@SutN+~*$B(I$Kx?tj8~j-+DW}At{6ewU zsT=Cai|ni!MLxVb?@02}BFS(;7}crZEINXYT^7eP<^7TNC$#EpJ|H-)z+&~I-b#sm zo-g!+0lv_W3Zch=3!)#hXsP+${3Y&~I9uXM65)f-M%tw7^5sIeN+wYHXJZrNbRBnp zt`j%Cs^3U4{jjfSKY3WWZ-o0CWskc=LLeUJB7d%WF#U=yBpzsvnj|1b9YLD_7H{SN!qalebAvw(lR1*h)#&(x0p z3oWqYN4MMYN&i}3$Uf}U{XU&KYQKAJd!piS=?UizOW*Hu`IW+N7IOtCg`YtL0=@)S zN@A))F@fYInb;9#EmP!5_i-QO$?d!Ry8z&M^Npo4AuVnx9vxxojXcPVp zH^>ueN>EL5i<38OrC_5m_$jz&K`&4Qo7)||52Iic0Hw8sm}yg1XfdMYzV;l#5Gh|=o)a`FNL(Wxpr|x{y zE>Ah~#Ql-ZReAE1Cr`L{Ip55erviB@kf+}A)LWkV%2VG&#^IODdn0CX2(B&klK$YETzw+mJ(ZwSZRVm9y8vU{+u@37pOE1278sm(pFP1s-Pe#Iu-JaQ{~RIV9Xb7MRPH^gPb z$8)D21_nRfP-~LZg6xj7SlDq%7B*8@SW)|WLN{?xjLV6Vp&*Tg#W_==iT(i#do{y6 zg@sjdJzS0BCmgidWM#?W;L>**SQNR#7%#@{!WxOgyo=bF-4y=JJ6NMmv9DneW>6Ha;87@v>^l~$vX|l`ejv0Z zTwN)D^lI^}rPvJqC_V!Ji2&BF*IgN-XUzt_s;=t%dgxhLlEw9|C1zXIsu78>m*{*% z#)KW3;GN6p>K;3{&IOP6(|-Aa^bO154&VJO!cy$~_V}m-Ig($tXjM-Lrbr4vkSVW! zuywZoieT%kz;4!YsVNXjXj<3da-7N=och=y+l`smAX~p~osX&|FG|A75wo@G@uDp> zt8+9+^>;88OLeGHCUPmVQS@<{C}E0ZJsg#@GiG78^B0OYGoiNbqT{P(F$QD)pHbYP z0Fd0qLX#wm_5+JZVyl+^@G2&YmiHRpmvWr2IM&sf?95J0U0GW>28dn}2{?40IiS79 zXa&xFfK!(#ndV?70!w{1L?;n|1>o~6fH})$yy3~u8Z{-tsk|*it(Npo(f^_A1b;vx z1Q{Cx!$IFyL}W$+v}4BVKbfH670NBbuunM3R`mlS1=`s>ux|u3nbsGsVp^Aq*P{Za z&3HmycuB{!mzx}Sf)()%!Q(4boXy4?7jTBoTPHgu?EsZ5Bh$3GuEe!q z*v3s9=Vp7|$M(lD!b&GeZiPx&2$AO+qr-tzWli1%{!06;f6U^P8#dHxL0;WD3?*WB z!83DG7>{sxD=pn=v+m;?dXI zzk3GTOZ0hpXYPLh%W&2#lZkPxmLJx{M}L{BC+j4r5WPS3&H{5r7hX@2*Gh52Fl4_} z;tV3;g}V4zhYD%6&h<;%o6IV+a1>!j?I#W!yQCE1Is_Q3iX-g3XT#&#bk|~Q4CZ9| zo;5B4A)*HWvAD@q)kJd5x^~??TjyFV-LduRT`!v5{TUOUni;h%dfl>xm6t6CHly+9qL`rnuGD! zfpm>vXr-c|7DZKT+O2&}m0kB0X`xW<&ik9WZIsjWghOv~H1Bk3ZZZ@d;jA~0`e}O( zu`5Q^`Vb+H)<*kzYU73K+U*ecw%b}oRaLT~Jln0e#vT<>0FE+8XwDS3t);qYW~aK0 z!GvaeZ6s}Ko2tz}mo>+GVC{`Dw&PLvkJtCBj@`)hPM17*bShqtMa{S`J~mB%l*2#L zhFhc@{to@UiY??n(H0uaS7q(c8ZNh9%OmZR)cmK2X~#MU8S+v9K|HFn=L}}CcGItQ zQ7WStt?kr9 zrvBAhyVQd9TDI#@oSDta;{vo+mg+Vbe0vXf$;94e55pTK7wCs_7aFPZ!`-f?6SX)Z ziKoU7fA!-n=JFi4!ZG{ul7A}+JfjyfPS8mhH`VlqjvTUrn zy@*9MWYQ78+XiGr|CD!Y$H1(LT)#{KO{Bb_&7@iZNYUi*IQ7u-Y9Dm+m)Q;gg!*=5B$_U z%{#qp4y8Lua>B#ENO8gs@_fC;2}|ZZ#or>%NNA007NVV7P!Ni9drP!RrbI2rb?le* z{t7k|mkP0AY;2fX_7x6IY?#Z`hPmoj*E3tI6O6Pe&zbzQyLo?tfA*mOD-Gr= z{+Zx)*+QNK|Ew+CXD!l=@n}R~FgKCtI@)a_Q~E=ovNn-zu(i`gZt;ZqM-O9ytsR+(&REvX=-FF1ew1 zS%pdL%*A^^)Ox5w!lMs(Stqq{c;9BEL?7~#oA~fg$~)S^w^Qr&B9G=O>{eTg(TDQ} zASPkdU={AhkNE-m_q>t76D~7L?XP72dlLBK(T{nG$it{4r-=}>`cvgCwH~*{xp9Jv z(bCq#Mn}nt;n}+-MF&gLJTSE+a<{BnKyATDmV?r_30fw$SYm%A?yDIgdyMFs>Mb+4 z#OnQ6E;>N=oTtzGZ!wh^joZ3d<{NZi4ch#$U@yw>x8$6MVve=dKR+ zo|f|Q9qc_Vwx%taHTq(yE>`ZEl!4hI<+a){7 z8Yp=X7`kJnY~e+o@VyCpkw|xd*aZ+xdl7b!s~)*l9WmE)F^1wYynXgz;JKlV918IN zVxw9a%@t}wcbB@AcJpX?53T`&Njfan02kPe;U(mQdkt`ICbs-i@y_G$Tn+3vMhqH= zRcmn?lq^SM*{yF0kSPC>`V?RIkq+>Fe_T4et34*XM2WY9mo^gc#;^^*r|oTT*UAxF zmWx}z*`JT8MwBVbg(WM{2yIx5=+Gd@_&`wt8PkMdoGhhD82R?CcC`jY(bwYjz`7D0j~y_9kGn1V zqmjhN)SCo8B3vF~vCns;Bd2bHZDCe>*MX$zk})Xj3tzW@ZWDQ4(H)eIeO3;U#Cdb+@bUONsRBfct2X;uIk2+ok0*ZOOv_~Il z5}~$zt9d3;f+~%%4UoF=Oom`2Ki@LXosRf(J5vOkfVwJY$ziS92^r(W8vjBJzx~0t zTz4=|HUO{YGElU&d4kQ^ju1CRdW%}z+W1DaA`>jz>ICRnr1W_X5vk~@qCVf7+{Jt?SIFyv9MF%7od)%(2qtx<_CF6E>BnJzb)dgxU7}98vJuuU)D7uYrJs}KHm>1)Obm_kAT=E z+hSLvE8v&JR~_}RPhIF}S%rkX%n#+V8v{QG-2To0S) zuH9GY%|*?n@M-J>*&7`2BEH<7ro2e;Sncth{7Qo0`iW`UoHf;3X6B&f$o}}tJ@4Jk0J0=h=g`hl8!L zid(rgeLc4MHzguSb8dFlyevIB^<|^@V}f1tw3FxhYB&E<3S~mIm&c*^>B}bZ7iED0 z5# zl((i_wo=rB>xiMfUOkhcn%*OCePmKNIXt%--tbBZY=?q12&l+boObBfMZ>m!Cv|48 zV@P3{shK4p$3j)RFZuu}XS$KN#kmB(r_N%NOnZ%YiG(PlYPV*xlbT6ou7;A+pH?LY zFUqXM($T|fZK94<2nukwvw&WGrC=w;WI08d%?kerh*VYa+LBeL?G^6YmO{K52Ds+Nhsu&8J zP0fZX>?Hpg&4$zxa-}Y|&K|kM?wNS!9f|BwbtP&|??7SuB^d{b@E(uxk=Ge%$VGelpv^aZ;=5(B{zE-L49Crf}plQP$6Bn%S=K{&oQatGW9$Bw9r{2 z@Ucl#XO@D!*HF{KUT*vOm(Wxt$OwO;7U|dW(2lxJZcU@EFW=5wat?N&u8NYP%j`f* zn?K>ggG}w`Vw7^~dp93I`yU=Xail`d4)o0VVC_^_QJrWTE6_HUD)nxB1G;B|w=1^B zW}e!ILi;5+yH05|8MCpnxop|g7_njrgb=E>Kj(S3vWeA!{b~=e{r~A zY`EZ8MVl+vi#D8uk9uoeY5Z~?f~`}_TnzIEfY44K!iCT&eXglrU7x03HAg(JRRl17 zbH(OZCiXRStlS+T8r@hAeKR||3$3Q@2|2S8#QJ0(W`Kj(qN%do;Z1~|z5oijL(62* zJX6}>W!+hdP|I$rqgImE9@eUsvsT9Mvzp?{(_I?*U(LXHX5gL@nStc||7*rin`z@u z(1Z*|;T^eB_6?U23{(&1*?|7p+((1A5#B0(*`}lWs!Vayu3-z|J|M52HU5)V!cdbX zkE1e;r%nRooHZNLsQs+Z!gs-%#_k^hSKK0I4giuL+-t z-+xXRM0a?l0#K=~b{fGC0B{HZhV5r_1WRrsxBj%Sk28uyaEHQ+DNvkr6U=|c^GW9a z8pW~>7tUYBjfxZf-R%l*{f|Up?ygG+0NYFffI~4NUW6W~DF?#8{UbpD0L&9B;V=Ci z`G51gT9-Vpc5_`-;=KCYTNL5E+THHFdh?ycd9_=eSIEBA5jIYP|12<7sWq%k*04n^ z;9t%pwZkvVLUJ-GieMgKitjgV`PCwh)T`(hRe1`WzsdE>2hpW!^Tj<0s>`iCAI+Cm&4UK3B59 z=&l`sOQWyx?9(IY&i_9NBz1;-X8ucnaWS?MG^`cQEP%x%yA|I_#poj|+k>)C<- zzf%w)eN!j->cm@JBuETcn_g)0-wbGmjJb$e6Y#CI{85e z)1HJ36Wf$hxg;s=z_k6ACLav?7JW;j2ndScZipF9JwT~*=&CwUU6)*rr7N1{JrmWH1Z*kt>L5`-FpeA`^xVbuVVeyHE-B$|qlbX7Z>Ef; z&F%Q*B);x-!}``nGu?;?o}xOjm;Q8`ZrV#7@dl6n9@#)`6`Nu+Q~e5-B>SBzR3WY3 zw=eI|Z@N9-)BIigi}s{l9Gtjg$I(=8^AB*pDI$XWM{035?bIH~BK>*TURhKtg2D|5 z3K(%W*G&{j0e@OV1usV9s|22;(KvD5NE_M?yF7Qp3 zXXAfUT4)h?3W9m%aE`5FPb`D0 z{M)B}jY`Qoene5-!u1vH;sDVc&9p7t{zyZ#kF8>zoZ)zD%hur59b2=9&D|f{+W0}_ zy)C4^fkxPxOMGovW%sjTpPzw@=e?aH-axrr^o!zJ;fX_Yl5yD*!F`4q!OfUsc|1D# zTRdhPJ92z@n9z}?vr*F>^AI8hn!Hkk$j8HqosE!P#V`$;CUc9+nj%Ef)U*eln+DC_ z%uR(sTWh@xP^*;oH3WrI`jx`MD1^_46yxq6e+9Q@R4L1*$~uai!R3gk@-DajCxv;U zRLM|c?sHp|21ZO8-W6*@S+6?(H@PrhUIyqGYQ~dF)2g3FK(%IP8_3R3y4UE>E7h5U zAB54s4%tEnD0&>Tn4TBkHsU?;sp@5m@V%JRlo;05@brgKbH?D>D4($)Bj9-EHEgFi zOt!%GU0dVUbz1J*eq7LEmO4@(8e`XghDIg`B-$7r5d6VS32q4rLXsBFRmHm zY7P^RWnF7i3aV>Jvqx`s>$OwZ=gX>$>RKM+4=!8DhvwLHSi2~6Si38`)z}|9tlgQt zS$$qY!@k`ON3`7}n4-3ZinU+YS=Q=h3tOdRS{9WIKV|aoZ6W;>lj}1fMj5%Jmz)tb zF34|c1M@H8s7A%c8_UIDUGdqctnn0bdY7Avx;y+IZwViX>yt_Vru&6*&6*yHH)Me& zIDFVodt|h3k37n23Xj?Yk36&8G`$Dri%~~=Rc-1OI|OLPQcI9YHZINNLvyf&Y{mvv zWY?DOvH3nZ$L3qLgZ-5P+%2Tf(VVp3)JF@0V~wJhcvZ$LR~C;TYNpAhy%aneDt2p* zpzUZd$NQ~Uiuggr00VoM_9twSdkW*1)H^jto6|zp7m-)Z88nx74+%QYZE&7@47b#2 zPVH~Cq*n0{lQ|_53@2s7tVpz1;r3_`wD9@uJmiDE+(a@Wfdoty4Hy*V+-!dww15D6P3o?I@CrfIe;k_oyvo> zC7y+Bz9|opjA3@5Q22CTi$&^r{VtTVC8wdtQfB*#&rTm4%E)CxE4~>)cvcG-D~)ap zxPUP#M=}?w4i(qXq8E13U;LCxF;wasenOA6Rjd3hPoTz|yWlf~Jn96RY95J(XLH;I zZl>NBzodZObqmt2WKMYhoS1xCcCotv!>>dt{6W@Q!bZVCvTi!Fi_enGLy6}>&h0ke zQ2HzWPvjfED{%mce8b}7;}eJ_&&xVf{<_bkBdH`A^S3k0_yZN9@GG7|h=LW*Y$D4z z5&sj&`c`Uqf|*}j!u9d+g!afTzL4|vt<>;@CeE?Gc59dflByZ^*a}wTI+JCIDvxoe zJk^QR$KeZ(led+AE+isopTKDG-^sI7ReF;H`PCO-{ z@Bauo*fnhw>D4DC%Jk=e?-xf$f8~2FwY9#BZkCKT*!PM=8|;*510t!*K}T|&5K9h4&Y`9r#>i=(MijT`KtK>|8PH%-U3Pui;M8sB-!Rk7B>*sgu2<| zYh;g?<`*dvNu82%Miy?59A+w8@2M=&9(C|%W>A_*vEOH$k4!L28n}hRXF3hG-Et}< z2Y)DZb<~f#YHwfm5MOMXqlskCXQby*hDG~jFu$R&QEimZgb><{K2`MNL4;tWwi@|s z*W6T1kx}9>H4HV6C+C}+tM|LY`*?FsM%nFB5RXYpkDJQ_TyOGPn=!Cwias#5e0pJQ zq~?E`x4U9%V?i!2+e>O1U=cPh$=cR~ZrW1BZNUM`z(EqO&`0?R$N@5w3drfv@A;c2 zmr&=jg-(iE06kKk#cmNUoobq>te$)AoJ}DICOQAkuV-%Rtt`90p_1e9~8o z?=s`0tZ-EAD>BlEq)5NFg7H*ZjvbUa?1r# z*2wmohjXrUm&dx>+uu__nk3{%Y}U5$waa9aBKkb7%mzH0B$&FO(-MLGuHaQY)T`>T z4+_IW2}PgDBHP!3gdKkcF`R8v#XJ&}IFtFG!PK7Oc*r%9|S{l>M*9`f+O^&_10fsgd%S`zaIOEWZyR#EwnYb8E$JKCIE zFC83t?JT){v1s@4cYeef-Wjh#%c~kzVFK@rktCiDwDYT-z zeTX*4!8qgvDqh=q$oqti@<)cV$rTHg)7f}m(S6?V@DH+96rDAtg=e^R6=xQ`+uEcV zUkph?Av@r;m^{Ug-5d(Kx?RrP} z!3G%e$7p3tT)8>|EP}Rd=e3&edG!WW8;w4ZBan*@(ubs_uu&H2*;=ROr1ejUgm`O} zkEu5+Mc94ujHaq)>>^HIV~dm8xzJutbN~^)-fKC`b4ifO7SYNE^Oq()iu@r!V$2VPWh& z{k*cT(Vhn4(zQ2kiTP@qd^<5Y^_hT4^&D?@4M;Fcty3en0`6QvPX2(DuX4us1O=ey zMmVB%CD(#MJU3vPhOClW|EFTkYL&m@5={9`+8gQ#*QqB|aMBgHZMccX<5_V*&x)J7M`%Cg=`|`oe4xvUX zJ6qzsJR-Uj1YH)DSGqga>%5 z$t>S-ty5W1GBPG!g=fjPvj^(qKqf4P?t*n<{dy{kR~DCdJVCt&dEXmWU#!UceP8Te z?{|DL0J#evK*@^CjOZODHTfCQtdg3MjLP$@Z^vBi)nIOej43`I)-yw8T9(lDJepGi z4oPQr^J=7%&a0z$l~9|NhhdPCg`CApoW@v7aaGy#!u&2|M&9A_^*6+WdFh?N*G#^? zK$Qw_E?;jO-lJ;bZ>t=?69@qv?bXe>wI%w*XJt77Csp~jdQYPnB7VEbO-S9KdSoFG zqutTSM9TlXddEU81z?MV?DJ4@gZeO}3o0AJ7Wq*6)qMF~v|u=(x;7$qO{tq+*@9D? zU&5a~sIvdBsJ%-dz3yJjV~XD1&g zBYSQQr$i}C4gPV=t8*+M0@d-Xq}xBA&(FfQ;@SP}$XJPb6UXKEFBcd|ioah$QNhhH z;no_yhFT~Qkz^#vKh`zL-!GTdsrw}QwUKYU-v1__Y6Sju9N}b)FGFki?6**wu5jx` z!&T0|Q>7#cqg4nm_dwdM!)jc9F%h&$0E8N7--;DfCzUM}VRS%GJg`7JlvOvydMJnZ^S2VM_xBLYE z)hcIls>-o|?IR#|V#gvMJ(6#ru`z3-`DPw5yKlKXAfxQ+$RBxx2prF+ zJ}NtKnT!EdDrJ!=U?7>pL%*?G%0yw*+oD=0U+zW=2cVOz-u~th;HA z;91>HOG_O~R@Z3}1Uoe!0CkyG`(IP1^%i@KOly_wH3%T*-54~jA!ePXPB1S z@8`(X82r?h@BfK>3p_TMxOrsBzG8;b=A5lgjvtBj(EC%0cune4gFPm;}bMmO5b>chq-dpd_;42}WEVLw|`45V4J|g~M$d4(|T&x~JVhBL>NJFOD z@PYZ}aDRB3Ji>fOK)u5wDXvN~yM;z3GeW-xXGZHK5=R75m+#S+H?U)um} zj!3{uE#-J+{}`esBHu(_RK=!Be8;50Dvyz`KPmxP{4@Dhv7?;vlwgeZKgQRh0opT) zP^feif^5%ILA4g`S#3f3$VU3;V8_w? zv#DB(so}@$j>XKu?s|NQnC8T2f~*?FmhSFTxNz_#ZgMT zqwj&aBz%m>o;Ht<+d|r9*}t6(04rZ$$VuRLFx7P6tL8$-1OK1D=?3`c$AM2GxtNO* zu#XSnUjh9T0ev7rY5&C)Sb4u%fuG%)T!EF3s1;aopSc3sWsN6@o?89`<^zNLk$f1Y zv}36796?b5ec^cQ95;fgsoP1}<=T>as*-!%rK~_ajo+Dz{mWdmsZb4zMmR-8aKDqP z<=)6}HZOSx-diP$vsz9gdnL`0U_A;T#^M&ahN{=H&r$E2k3`6t=C9xeK|-+AdwweU z9DYt#5FyZfut=FzetA-0`E+LK3hl|aqZCtaz|^qA2b^jx)LQ~dvtR@!T;|8&BCOCE zhYK*d1`#JB9Z1S&lxGC|@>tt)*+cD`JuIoYuCNL+8(^!z7$Z?;K`yq%R!0ZID3!$q z2lHwPG$V{ZeB6-iyu*rSg*2u{rK=SQD9Kn?wG4E>mj_dc+m%bi&tf%NW4;=uN*kt0 zijv#HzqpH`iV5*}Sl>aTrBj1-)rnyJW4L?@Qu(~4E%VN3D3vthme5*yYAta2PT{hH%?^SI;?$FG^kAC27?3%_h0f3c49 ze>9Jm$o0QAkN;l7alkw-b8tM%Jl<8tajAKH`V~Cq`{wZr+cdE7`eclbv0c)1*p z<2c$U+PkYyzjLmIYfNW;%%BTDNhB1q&+iPs-ocEdDlJ zmW{TA$L+9putY{VjJxn`+-$Lxf2RCxYuq~3k`B2FsB4E)=o^~zh5(|9p6Ayd3d9F+%X39Y%q^MT+I2`IZpLhr~9jY z`|e~7f0#qnHcgx3>?;KMiK?QwSt3Y6`}5g(Y(G?Hibcvyk%*Nd5P4AW=ldzQy(iEs zFg1%l)y7PVyGPNQ+`l6u&gU1>JdlA7)jhhL%z8%DTw`UPsU8DIg zLvFzw^W-Ex*%Dm^?;vPK?&O>H>iFEs;7%|+Uu%oaSAT9mvj-ldOw2?}?i#J~RtAOe6xuJNxi&5U znWK>QnAT?P$(g961XQR|tcjHJEo~H8$x*<%PC5#0d86;pP|{ayH3(=Kwt@y3%Phun zhZ@VI)UotTj^&XWsim#?rCXnj=YAz9taBA?Cdnf*k#7n3vz0DsvprOQJ0^sVptgiu zqVc(`0}#8|x@p#hM9_K914c{1G^W(HB7*~Bxa_&D74@8gIH^liPmT=*yusao#`5K^ z(<<*}yi#*D6dr6dit>^}o58RKpmAB-sq@IEOJ`Uh{rl>BF-OtS|l7r(I14r z_bVZim5~;7a|Yt=OCNbK7(L@JydT%X0)DUOJ{chOZ3#Y-0zHnRsA_8Y@2JCL>|$Nr8^@Z0(rUP6yg2dQ-HTk|I|^idgf>g`^MpD zp@WiXPt~!P*e&}V1z&J3BE=GaL5 zk$wP7j%Fj%sS(4rC;EFiAx%q6xZoYp@D!XAZq~23iLjDuf zItjlKr{$OPnBCsh&?x|MO2WX@0nKl1f=66i-Ld-S(z)a_(i_Yxo$8eeLmgbw}~&2 zq1+xH_%$-{zYkRdZ=h~@eBj_-Xs&u(8b9lHea!Jk>LHr+9qA`=6k*&oX3ccjIi>%( zNukt}Cp4te!wJ{q&9_gSIFSU~d{z2cHc>VHUTXggMS7SUXpU^4yCdJ{mXq(FbH0o| z5j}W^$PiDyj&ani|8jUQiCSiXsz|HitgW_!%`nr6>M5le_jzXmE2L!fdGg@V$-vt59u7+4%UYvjb_iNWLG106Q7L`i;r5_oOq z8QsGxNiUPTBKudTmv3}^L^u0~O0qx{bWV1}XB1||DdHQXeiY&POeuw4%6E2I|6aoI zs0Lut$~Lqwk9EKIZknM$A4CdA%zz#eIe3R_a=i(()K{DwUg^*ODbGK?A}2c9gKN;g zim0e~GX3iZ=vms59}^wgfd(eI*$}$Yz}6u+^t?x+_WD#S)k{(iI?JVh^U2N{_}}L^ zQ3GFTW5x}Z+>lmzg`%Q%yS@h%j6{ktbj{LUb){%vO`88*2m2KF1ib?QDu zhIOZb?NS=p&V&ZG5zHs5iG=V@_|bun0^8)L<3Lz5^-#J-CT4cKgiRiXrU$z%$Ku+C z=HCtT5e29g6^yWNiE?)peCiSTZcU^*O)q0?-RWf~9-DBiBs~xhOQN9+kbv(sQ}MZ% zHKh-7+6f1FcYKg*M1JWyNO5SgubQn;Qr{QuA+_;*?Y#)Om`cFf_*_v8(c3O?SP#rP zSJGdGqP;1_ZJDXHq2`)EhBa>tU>P!%$XbMJ0Uxh+TlUjg!Az#s{F6mbJET47P3UP# zeU!6xs^q6MgHhd=4bzM(CYTSxuT%+BSsD2zu0K&9QP_x*5ru6joIwS(s=HNMRD5fx zsQVF@nAK|5F&xnTo{#sYbRR?PO@nu`z5{vWdnxWv`@kvH)A8}_xWwxh4X$(jlKRnb z^tTqJzkP1%Z>zK?$9H8m-S8`!D*Bt6s;R$G`}ayyTv;b8tHhPK0;fb(+N&B_8hZ_k zOJ&-GdG9+Ha{VoR8U7$l9{sX&d`h289p86kz?M+?j3yMg zL9u~q%N|5kb++tUQTil&{%{KZV-S&Sf+eFy7FQLrB%;1Cg*?h+mwp%-!4zcqP8Htw zo&vm;{`SSpt4;mwTS|Z1&Nj-<1QW1Z_M*i_-WI`BG&`c+(|@_26A2|j(p^N0(}+oq zYjKFIXmLSPi*p21G=yL{ze;HcHSxtpi-Y}%HBe~@t=%H|Buu5Fq)@EjIa1K9y9jVlvPDfoP1`W3m_FN+*GkEtZ&jf6fdMRbzk7~X z-k1FtS1S45L{69y`Apr-#{xeRd1!fJvFhs+i$xh`Q6GwBn=R;wtQE3LU#x%3OfFVU zcZ=1KSS*wg7VGuOl*M`l=qcKY%1Wehu68+-x>#X3k>p&CJjJ>0ws+xNtY8fRjH&Wp ztC=8nrAiP>=U;9R(JyozxlhCy(dSRTem8an{#ReWL0unl()ANYJ;C_rH70i%bb}_- z?)$(vHEp~%hcTa<^RpILU1{=X*J9j~ysSyUl!+mIk z#Fn5DVl(I#cgg|ON$@AqC++SoBY&o!8u?$wCP$8l4!ln~{)kkk?soqjVeY^8@p~GU zNS9@>WP-G{>fC=#`5#eE6hNRu==<8zk0L*mi%%jSeEI&X8Y;yZ-wYKUlRa~nsDEa5 zcBEZxQwL_!bJpCvjyVbrC=D=`-~H%`Bnh1gzxzo=3JE>MnkYrEfrB^+#euU)&ZLsi zYB`Y#9CkRUvg|m1cLI2cqpe$bCHdQwuE_lr=>vPom0cgv4Sle@mkM`7=cAG0rHVMD zapWPHP&)rq{I2VKdI`h(D1|yU5&R~Aps}&{4p#w=JoLbh$WHvuCwx}|f06IL^!bm= z^Ho=dAEdjczxz5m;FaXfCv?Dc|69er8nuWUaAw|w4tNY5@RmGQT&FR@+w{4?t%iIv z=0>Fk&SP=K>>1l(djrHHXEH|r8+t)($O%tP5*7}nDr*Iel%I);Zi}sr9N>lc{OrTUlQ*KUvHVzfYUIaCjoh11Bi|vFS(OV?c{1-~v`pEr zU36R1UThoVY~D)|6Q{L(1=FQI3<3&9{!LRpum$=MRJg|xcwji*w%dj)cUvRivg@e- zaYeIJRk{VHCW_`%K206&Emr}#@OVMjL`daH4qxi=dGsCTEV@%TkDtXZRqQ4?3&juP z<1Z3cPDsP?6L{Yi$aMsM%-C;NLvLp2Zhc+q=yxU+y+5XC0a&* z7bgLw%4#!PpFmF3 z1k>yGut+yb4(!MN01#5}$*vzW^*0jp+}evBW2*8JdR#2i>D$he;1+L|ZjSs3f+(3M z4|VBNNUXX9`7f;W%`Z%SbG7zlDPxkskR(i>fGLAZn_L0f3~!F*3E?Dui7rc@f(ZZd zDdd||_*&N~^fsqZKBGbOx(jF64%sjl=ovKJen6D9w3#PvDhaoUTqqEx+(;uC60 zFsluv8zbu>PsL6<^}CbLPlW%(EKWK<>nAfu*!8_iq1)*w_#`^aLI3!tRw_C)Pak#^ z?2atvgw)wg(GJFXle?u7I3=AwXetPfpr{Pqfj|^)ZVH^&{}dzvxJiWg4bYTiY`^S} zaj?cQLuAY}%n*}j8fJ*wLTa<7*cVR~KfVXXp8!A1{d2W8`+-x0-|_2V>T9HoU)1#x z?{$k}^~iabIkV54b2G zoJpl+$z5c{;)HOvv>7+DM^Tbp2*G8z`w-;5MP9=!tKH-pb-{0vAdjaH;#5q#N0L6= z`pVLc9_w1oFI5;Kb77^XJkTwDB-i(fu8VU5`ajY7uGK0(C%`9-#7?}vmze7-uwaeP zmop$zBFHm9lGk3f4+FeR&0@^^wBXlcP^%T#k8entA+Q~3Q?pMRt`Z%k*{y3j=0p7TpK;xs&+ExJeQo)gcP zRr`&|lkxrL8upun-V#FsOl~-vBBNj^U$Wm!Jw<$D2NxYBg&*UkO5?h3J({H9Q{lSr z5M-N1!vy=7T({{s*zA-usWjZoi8R=BawKF1`0c5|=MazS9zIEWl+e z>myD~k6rmKqyXi0$8US3^IN2`y`s8y!*KBeCCM*uiIAUzs)(z~as~R4{_rJN!Kx(v z?T)+zva*2*`)i0!?Vb|j<4WQG|I&COKU41#Nxv>iofQszby9sMXrpF^jdbcP<%jZK zMbx(GfVvjp(mlM>|5PR-wdR-VHR6IgQ*rw`R{_FkZKMz1(&;V)Kute{tP1%aisjY& z$MB7xC_X`1!%IfEDpt!6(&sX+9!V^NHd`v)o4qbQ`u;?{J>$`2ze`9GHRqzY+vELR zi9Z=Vccb$5(%;qWcj+ARK0PLHpx@?x^7v#+Tpn@r+=P9w+x;OaAId;a1s_RYp)ow2 zac1^1&E$~lQ7G07Txwy<8~Tu(ld+nvTc?46qtU4(n zrR}#TgQs(nqu~SqHO?>FuovlE;JQPWCEhR1W0ZA)=e9SK@MQJ-xYPQVn&9*RPHGV= zaJ~_Fp2sESuWsR)r0@U1{Z`6K>DyTL^bVw|ujzHMXm940Wd}8`Q|(8EqbU*9q+ad} z-|}~%Ub>2qe~pFQ+Yjrw+B6S`=V0t`>D!_X^CjK9A>Me`vR)aVZ1FayqKhL2o9_r8 zdL^;eO;VZ;D5l#Y-uWxGh`)Wi(-t8%iFA7e@xb)8#U-sg(4IvB8*2V0e{kAW(r?Wg zF1;MduQ58HQ+{#A>Ri@Oy_85>GVqG>ox$>B<=&{27O{pN|1e4wBgDb7D(1XMTjI>I z2l6rZRe7)jWy3tm+XsL_3p9TZzT9XGzs#mGK=7e}ujSE;kyo56GA_u-sAMvf!D-ce zO8%o(6rOB24KdU$TBQW`5jVR~kerB8C9=jV?7$qwr|tWkc{t`x8GVCMl<)G@f5Ayp zo}(TUMJA0I)vBS~-ms*Z@*^=PWxJx^mG~^jJi7LJtoyvT(vh{^v4Npb5<|8*!t$jN z9aMmAYG=6c>pk%IsYel7yEkm(Q9Q@{H5|QeBJeG5b3lM>6P^%|-EG}5y%{2{<`p0X z1qdlBA0TF-pk1O{tmx_XwJP@I8}JvwCtt^f+E>f{;-c%OA<$CvC}9uuZ}N%6=KShPT4jDa9O-3OyiiH6I}JL5yrw1PNqKaeItQ`q8%e z3y=*YJ=jHl7NR^~nV9OrEn*}9aidY9N+6F%C?o+Fax8-EqW8!XJw{PKS3$j(7p3Ac zNQ?YV*6y+J!}&cx>qn}c2IZ*8HzCoDU&4O#(c(@`pfJM9bSagImi5R2Tw%{RrK!a2Lk+h6g%-7bA|xC$|icXPqK@)_#}fOzD# z@(6z(ge^92F{hlofe`BPc^=EB!c7!_lKxZ9bma-O%ErFu!MF-rm~z>T#w8aBd^rKX z@mLQe_yI(GEIb_{Ty~}eKk!&SK@{-bLAA_u7y>kS0m;nVwljSGIX&Y3rUYv_7B1vb zo%|r;vaIU_CM-ws0}R~N9&3jp^U5Fs5cc@I=((NvE#Hxy#qRI2)N!d+`7D>Ie$k(x zZvB_~MISY*F#kyu9cG0I;zmxhxo$aE{ddw;HI}au5 zcV3ZNk6G$>Dt?I|P$MBdgFtsURdx7zD2Z@1&Hp`U|K!LG7A#EoV+6rfX)&Qsz` zmfiA+LXi9V5 z8+|**gm(0_=QeZV_8tyZf`5!H_f5F9x}R8@3fqRL(-`)}xA(^i8?U>1s89O^30OTH z`uoJFX0%ZpV7slNBV!Aa|1&E?ANE2&u~mGQkavZ579O zD&DI)*pfJm$#Xw;zd9o=Mjgg;o8QG@>iaBHoBc=gM0vA#P(QoradF@LVkOs)8Oamo zuXN~}7=A~rBPON5YUR(`677406a1*@rV{O8_Wd6PQ9e2b{qtt2T+osIuKIke?~8OY zpk7?4M0;$QQ=Kc>!gp?XEc*wy$ZsXJCE7zjLO8au*~iLl+8@`u`;%6qIs9ay+w1PO-FwfB$wpYOT)uf`sD)?NE!U+*(pAw;PKPt49SU;_zpOPH#>5vi_{7l^xeb@Or$%27(vduV8Je1 z?ndc8Ua*A{o~Fmst=SKfT$DfMa{iv@y@bEt@m|2+S>Al2T;23s4DUt2b7PRK40`)G zV=K9r4ixXvep4(b7COxL@aUyE4t-J{ecTnD4NlRMlJHj5m5D?8%pQ0=&t_cL>T5fD z>a~pZaG^M3vnt5riXrNpR65aNvpvS;*p_%BzZ1koXfGRaYWGBc41I~=K%4V>{=y&# z)eCo1zWDOd#UI0- zc8V|L%CdULyCeCBV9G|?*Oo6TPBHdE5L)ujdROIftO6LZLv@gEu!($$z!P}{B}a!P z_eVEy9OMtJvd&a^I_24Mgq~gia)&9O zDP>bV);(p>$nUt!WPn}h5v!P(CgSzVovL1Wryvuj#eW68rjfw+eiFMr97Yr4xPA0g z@M}o-_?1cZg4boo`f9LzEsk67Ct$gGKpd98?@D#bese1ULy+FoNvd-eg{h4}e{#X3 zjL{u@pj<}JNRAJU(B*3@&?>(Pa!S{ovHZDhEP_Jg^+uomcFF+H9?VZ=n;ezvz0LD% zR~8j|e@Z28m$h-q;b>4^WyzTOnD%PD9-;*ny=aZm^%LmWYh>qLFK=s%4o;DeNf4wpAEbCTn_Fe!~w%Jj+-MhYI-nc7^GQGWBv09gPy}S?2 zSnR-btEf-x&DmF8zb~e@QLx~evx#;gC)=2_Gy99!H9HZlwO<5{UoYPGd932t;*Wdt zwbpnwuj3F_k~}Ki6l=ezW7p2!E+vD(btA{pB`$-J)aEujNF4P zRrSTPdky@R({ebrlVA!3e^8=}?G3L4i87HNhBt6Ib7mVoaUyw-4?d)Grbej?jB>A&R z;=0LGPz?-X(!fB<tsa$F?ZQw2O{%0TYUbCai3@V=>v|DK1Ms(7j%K2*9P z#re|-`XSvWQfI7W9tfFbwO3_bC75Z&k7X)Mk-;9kJTBU@-2biYesdgK~>6o_4ZIrzt=9TDq zDe#gLsrI;}z2zfM!KVbTiu8RFdrKI5i#Qwp&)#C)RQBI&k7G4y5`jT((TuBX1@+NE zvj3(mKJCxedGph7Wk*-pGP*8aT^7u)vjum9&1-K;yCuc0mM)G;1rK#);QGO0(6$H4 z-oj8Y?Lz5UcHCX|fTt;CY!^qnzbxevI+?xikc6~`WHYmK9Ma5eO}v>I5#-qYgF^Gp zL?<&}9n32GFN@>#DQHc6eY*WzZtv31tRY@+C8eL4YDa9N9dXxwW^0b?XC@gw+rkbC zYQTE0Ol7@FM(8RZNaiQz4(V@{@P2p72WPqy^1*}TeVw4e(M7i?`Jl-|Ga`vHQw?m` z<1wD@cLi?Di+(+o|H&DNP0??}zP{RH{Zy-zeiN$mAqKHgr_li^vA6fa?-FBQ=TbSD z*68pxnjYm)WvjQ^*ZXs4Z`s#Xm%~*1Iu#fG_t@93iSO^?pY(RA-oNRX3DGzu8_R&DM)4;x;TAEsA8TZ5+9!4Tt`GTl)Sz<@WF%enK zIoZqI^nlXbss|L-)249IO|q>MGMd%_Dk*+;yT4Nk$t5YSs=lY|+(T3_ZKO13L#cxJggK^1S zkz4tNr_8*;tm7#?F%n14Zjf^4u|MKAldI(!dXJ+}Jt>cBNvhcbM>gPmT zxVjHw+!i?Ht(+P~tN-%Eq(P$UZyvdW2f4K6Z#sR4#?)*Dv;__2 zp`#wmn;Sl|Pj1U@&dRWbVgps(WP8D}$%k+J3x^J-K~FUpWGs^vW51YZnJE3PO9aux5omoKp*^b4X)M}RqVUjUVxYLUAMm7 zL;F;T*ATDs9)x2TO?K(gs~_@cFX66*;p1r3UfN6@Iya(k>qkN{Sgd{ZC^~KOopx!y zO@KA)3MWG7q(A>-NlRbK8CloT+qj-copQG}e!p+sfOIT7XRMJm#vh#7Uk_Cr0&{2C zNe-Vq7I!3~ICZY<)a84s0+h5{VuI>Vy$8s|&TKDe)n`;Ym$vLZdhhpV9eG5ov8_8; z7D5*DA(^3{{1rnD5bMZYMy4=qz`e;G7?*Rjma_iYAeeJ<==sB&&q6|`-Aqup2PNg) z#vtpu_z(3jFTs1ViB+4|C94V-1EdV?P-d%Lo6!r%2A!zktNI6S66Kk zk1PNNl>z?`;#s=#(-Gg9Tl?tjf=Vp&Yn}S7d9K{I zop@(HvCn>bl7ok!i@mMQ-U2l0G738(6Hy-g$)VN5j$8y14DLh%yK(zSM-^+&Xdv&G z8*SG0rI$M>5vUW4GHmcm1UgCnpdNHS6eNsKVGbx$R9Z4#FUpa2aUN^)loq!oBIq~k z`p%bX{vbI^7;<4TkfY;sMaz-RV#)_pOXHEW)l*OOAt zDil74^*PPczyjrN@{{-aADoR$lIctiromqg&TiZ?(q1KF;);y%Mjzc_t(65>@1Ucf zG3?iWl?5nH!e8Aa@V~X>I(_;Xxh`KV3qU`1djaL%I{MG@yn#y&MthXu{rO5YJc++= zdi-3cz_}Qek}*;QZ+@sa=Mc3^bJzHZyQ$?Syelxx>vKA?EIcZ6##vG7LuQ+Eo5t`` zewVHo(z0+_a&fUSRMd9#J@yXqvl1`H8leM^EidY6oq5jKx~!ff%~MTdJFN4lhf=~W)VMcHl;1ilQ-Q+Lc8jEdmXNYJaH&oEMb8Fq1%49Wuue5 zZujdFF*a^68+x+QZD}6LM76*sU8IJQCdR~EP3b~4pdB|j3K=W>o0=nh;r3Wm6oKFW zX95SW>xjNwGXNN9{_|k*Y7I626j0T-6I$uVxriX{3ISC3g2__K7Q5f*&}LC3>ch`m zE=WCkc?p(lW6-7}M>+dJ_}U+SN}!{JJ%&%`Pzv5h`=wOB?HZ3*v2Ov$uT%i4Lt*%5 z%tBd#YwdxO9HGuo7{2IOP$Yq{__abdBL;$TO zR2L5+VK}iq^ zPetI7lH0b~d_dU%9J9VQOQ39Hv9^RtsfVHisG3;VXg=d@m*p*f0y!5@C>)cL_DpSX zXLk7-hrP-WAi4GB(k;!d`|sqVxN7lt_|T2}`CI3IfWITF=07N>{6F9?0Vy@MfF}d$ zeoCV96;BDw2o@Zpgw+kTh3l^g%ZB%Ym;-zG+8!`-R5ed6k(HG1vABHiX1IK-B*@ua zu!9h?LqyX$;_+jbUu!CP60jw;JyuI?529z4s4Q`oF1w(bS}`KH!)Nsao)Q;Tg2~OJ zYNC;tA{XX!VdN&x(tZeW=w7`k)Y2!^c8>kxM;dsw?cCKWbW~u>(lmtj_6OH_veXb4 zl*!YW#1c>W(GV0cN}@Xnsf%1D2c55fp65rRwj9@)--k%m-_5H9^BCzb`Nmd!kwBv}z#T-;d53A)AKSYP3qJZ0{iq zK7i@%+lkBM4P+R5x1>F|8+(m1XLRbD@|2{#uAXpi0{+a#k%XXwEg0bY@yL^y?8rYJ zS0^SrfO+e2Dn9a8N51C!PpCkI773vvji6J-XE(%j-#H$P>bdr+-r^;~=M`%x!$uJ6 zrOp2T#eQGZt$v^N-`xNDJ+=|bAg1-dZWNhF#n7{bNjZyWk=qgh^E)GjSk-MrX~Wu& zqf%+sge$0gk;Qv4=w2mDMR9GvQ1K!NHwMRa2I3t7R6(oAQ90Ed7D0GZVI!&=N-X6F z1DPtOm2UFmS~}xd|6olJT#IumVDGH zQ`{(vITyG7r~8?Jx2H@g+CxSQGhvj~_Q3c0@Mg2jK*&-+n7w(8eK8G`4$io!Ls3VspNi}`BC6#K_^CY(L zY-b?;LdBKEo?$*EU|u4ThDkDdk;PEs>0&I4Q_}BFL`i1~C5eBlTl#_3|Bv{;#A1;2 zfBj4J^BhmW+m&V>>*No_7k(?%JZ8q9rue(sBa#i!m3}sG&fjSA&sClL6Z^%Y=!L2F z&UAh#H+ZB|yD`3kJ_xh5 z*@usDMXWa3zY`y|H>M%U*IGL4v z{vpBzUCV`)=!@k{e4yU*Qm?Qs7M4`{PMm+BAH?#auP3=joKM7C^SmEkQN-f{N>WYm zHfudyL^hXv8f$ed6v2wNUW#uProjS+lwK-5Ayy!WC;{Z-S!3K+Q^C0M3uG7f#U$UT z^k&%=!dtC~ksop1^dF^rdCY0O?G2^9FDaKq*GY8=wVvCCn;L|KjRa_atY`ml z-LFo7wI+VJd(2pre7wY=gv)q*d>;#V5UrCaI`k^}VX+{-i(vg83inkX@NMB@byHXL zeJDKmflp)62TXxP^M3~EdnSFtzN}Ks&>FXednRUcZ5o<=30ljrJL6_*e?iDXknt$;o6-eDd=M@p%u0SJN_YH-)MLB81 zJ0V=9y|#zgM%Se4APGkkO=un+=rO*JH3F4uw=C7&(*Sej$KIk-ec~l_QIWJlqM22E z(^>L>z|6q}GS4dE1v7`8>XV8rw!qAMbYjdxIh`vLxl{43N;U|wOf0!!Xi5l$_`sh_ zdqHyFNSuwn+38M8ho{rG&naf@{^Rrck3X=Nbd-?R)MC3aX4DAp=oPLx*cOXshYR^| z8>KkINAJ%Pqsxq%@C%39AXjQ`a{LOvy8^xBSe#-vjX?KC&TfD(;FGA9L6_!OB`bFZ zmx(X-rhFSgFkB@+Mx_vUz_Bzi@pXOTFQxY|TN5{y4Xg4jAgeRr;pDTr=QrrZ3z3@_ z*{iVqJwQ^}8B_c6(q}QL45t}$6#0wFVZP5PmE{Lw9(}jVw^qY2Bj&41)`?|{%w@+S z&a&=h3)J(Z*qC&zQX2T5_hwSoNYeKXgs;9|kW+freh`keAH~z=s752t)81%O26%bs zpWBW?cMD9qTNKWbTYRgWolA(NZN`Fd@#jYcSUfd4MvYOgKkBHlc)ta;HbgIppNfu% zA1I)H=K!!jBYAc59WUO;I|7cTqZy=F9_?W%=Prxetzbxcdvvvho|yQ ze*OkOr{IDd9!Fm|SDgW?)~6|ucXsF*vBxjDBrAc-C(kOB03^pl2Oi+g zIp&?yvk+rWW-D>vz&v9;ujyHzpLPfc; zpnhlr4&Ro1oT5&>39D_sdvcSxPJ7RHJaqUsHcOq&`hKan+RJXUi5zqT*P)P)x5d`j z-gtobMV{o3Hm97wHe(!F9WMu8DJ~u%z64w!+8-Mv*!PC~)~%@Jg^kD$xCC39ZRa-H za+|##dV5W-Ex?f$3Z7lqcnvPK%&EAxNRYynG&vamMaCca3Fp8NF;^f{`a}GZfxN7u$<$UoyXW=pq;h!Di!u?&)_{s<%5o4=0BE7x=ig-VCMav{$EsIg#k z*mvx`vik|Wj()c=NMgm^vHHoO1XS0XP(7EpkYxTXU2ki9n1zm~C*2aZ$ zH(6Svy<-j0o_1@{*F=!go_ySYxoxR=QEB|eSp$;tPs@_yL(x$cA4))m z_soiw5{n`AGgV76ByPGwM*F=ceq(jE49?)tJ8U=rCm&Hb-Z4;FUkeT{mB4`lWa8$@ z>s8#q-n@cl?bY_?1D4HtJ7wdIK8;2nS4Bun0KPr=r3T%2t`Nh(Gu;9AnK^o`eR9wY z5NJESV2#&ppS&X_Uck;ONyxyU=gyO5E5aXxi+_i#n!dqafR~-GJKdHwF5d<`AkD-G zY?VdSURqCdyv?$O2OMqoP$hE1$COSObE7eIj4QU1v#t#vx+VPJLqb>Cn%sJmI&OAS z{+nkxm#u5P^}|0szY57y=;?L4#uixS!uJr_xNxe>i%QQUjKLRSY~3<>t)i;-)9uF4Aznslj;T5TMp4WtnpIIR%df4#Eq2gtjP{&ECx(Fi@|=P;ugzuIWS<-}*Zcr6BK6J% ztoL8?Q`Wmht@nC6yj0fv0>VK&7E0KzXT~of1O{Q1SI|wHwu7&nW*-4-+iRX2?Y0D& zp1xI4a-&JfAs2yJD}=V>A3-K&s74P0MsoR2wTuSM7XWsz^yXRc8p#HMra$|K=6^`m z7Q&{EW@J6b&ZS?h{cdIdsc-$&EoibMR@X|A(^!wVcU_*enkV6oJ8SY9#Q{QRt6p~% z?ZR8NIaT~xGLM$+!OY2x@e3;2P5v5vv@k|M(hudGHHr5i+Oa)!zULzzAkp18hfe&S zsl(It-R|Ev`Iurj>k1nyVkSQiY2%LNhAe9%yXE0aWqcB5;anC!plag>3az!jeUMog zq#OskMUeV_`e#fi`3vVC-`5Fp*ym?%?yxwQCPE0CGcU5AY7CFSaPPh^&5cU2RP#iFc zIXP>BQox%y<22&k;}=W2RxS(kkM{UiA>Z>r&lyX8$aurGC}`xkNOG|Vo# zy1!b!)vMOY=1pQ3kSnQ{M6_&+MM9IP!2$=vx$a+2jok*V>U@wBYYR}5ilGU6_*lJC z&01=w>f0!#TAMGyP$JPdbGN8Ryjix*MMT4E@-8tAPZ{$X*~fA?a>@{i+fx6=s8$R| zB-(M#sKNYf6iFmWMtEDTXcVdiE-lanrf%yIVh4`U?^zZi1-hzmjHlYbonS1NB?-@v zCk6Zhrh44E>WctNBq`LqI5d|FP?feJrg;TT3GyMh2jRgG-~&zm%6NFPTrH-7@HssF zs3S;l*L4awyCT2m(-s&h@sW?fRR4$Im33wcy#5k8Wq6rDVk$M^+vE{ocVHwF6vPbA zR-h}ZxfmNr{M0wpMgLA{n$UY$fofMo)Jfnk_?cWSY4Dv`EfbBG%SY#G$ptB^C0Jjt ztXFEaSSA!x<4S&N%w2t}`P>w9Qn^v2e9b=Hu zz&E=dVeqiU2N&A)vW@fwM#6FjmJ3P-l%C^9xrZ}OR}vk5Z*6XWo*!}bJw>H=`Pl#v$n{}o3l=LYP00rXY3DYpigT(Ybu7Dj+x{A5+E9RyHD={Zt+yggNZOW$(H18Cc2b ziw%>8!=4c)ukpl&iKcs;~SVbyG?nwd3%_jj#QXe}- zcoYacdUnn{x&NJT{>s*FEH?R0t72E-10WWrriJc+A#B1UR)$>)GKzjEd52EQ-uYoZ zIl`8*evZQJECFUa6MhtPa_a`>Pf9uNKrr7#&Ui#xZCpg7|N zkrkpNmH)~VDoB}N>@E4@_2E?#u_E!^BtCd@=^8( zF(t@Rt!I3h<+A9XVT|f`*=+X^I3?u7J;E51d!5LBiM`Gg4%N2Qx!1`BDSMsl87Xoi zk51XFXY-QCH``+|wN=RLU~bgYTA+4~m5PiUc`^Op%e8*B6#5hI(OJN^Q#*^M8=OC5Rkf{|32 z3CvieJ+*K5Bd34}G;^sca*()<~n?jRHr|Pu-AhQeU>q9H(dgrlzq*cDnN|;`#u*SZfHIhIU zUh2vjTSZfsfKoO<3NM3F>x0}3Q&sD8oy5OOhH-p_?1b_aJ#7!zWr1Wxik{GmfcJs? z8(FUj#?bLy7pRG-paFqVEYGMVEMRHp@@SQJLwjZroI-KUS1c#YWn#d|B}$ADmv&^B zy2r$HW3iGWuNuUt6u%3o?s|dcg0_Lhd4R!gWL=AC4L@wiVGU_UDPj!8dlyBXk?BBLDc!z_q2pkSTR4md(6;2Nbf8spK%sEX#4Jl1DmvUeolm}>zwFqrL z5ZYNEJxjSzl=ofz7|3<$-(ookh~%DNf=uIspD~beAngRys+n?~F|aV8w&;M`Wz24kYCpeEklPxbIba0`8Iha#n~>M+){sMAW!Kz09M+8v&9l=1PCq3Dj6n+} zw-AlYp+Mgm0G57X>6|bnLKS%>av51S1yGcVcMzf~Up}L@2ilBM2B+dO0z+SkW?|o0M}AZ8QCC6T6c??OEK@zM&~6b8 z&l1t_{n%QYe#B1I)w$o}xzV#Q+EZ}~`}L+6?k`!F$V^%C!lSO%_gBa-Lnw}`;HdU% z;mdNBojN@1YQ7-kPeFO(hxj@?RaII2(P{10gWAtWBWS{@=U&Pub8QjCmY4ujMC{}Y z{S;?#C)Ve`jXxkFssLGY`#TZ)PK;D8O>#a?3Pr2oR|63ME@Yt?o2G{ENy=CM{o^0W zt4n44gJle+`l5K78dH3z=J;jQCaZu4X_aqbHCLY2y=p4U`N~v+@|ZxbnvJ=Qj!Bus zzlT2yv%(}@IYC~@*j!fc@WGnzay5eG4Qd3vVtJ7~PJlfiSx__X%2pWk)c5#28ACR* zddGsW5bftza;2pi64&Mq<^Hc{a6AaDVq+bwn);GY@juZyTXn?O< zn`REPNh(f;P2s&YG#x{7(beMv!$7T&q?*;#K1cv)4 zUf{~br+knyBx(Y)7w|>_t2XC%a)kTLZVbQH7JDnU&S8CPR+U7#&kxGAkx6nvKpETA z+N?3rOfemKf%2+;E~q0YTONiY8%{1Wl3 zC{EuZb1M2skw_JNC}756Y|@A9A<&0YKbVGJYO6PjD0Y{{P9OZoNSn1y`}v0o@YeR3 zh5smwY?A4uumvkqPhkt1Uy{z%dadI?7U&>|SZlY|YfnALy@=Xsfv{kLlQJ^9aWA;_ zzO7&rNY=T3fH6I7){Qg2Zua#s*Ue7p>A?=8Pfyg0;P`;szz6oWtXrcjo&K@M@;1jd znnv`sTlY-Qu~P|Te4x+I9H>3H>pTSqwAoj}{Y7$~s_~p2E?jl721J@!b0vh7Qa37{ zz-4`WaOuga?x>_suxb(9A8f2Nn3{)}5q~8IzP4P={}Tl$x|~n)G>~a^m2XCMCQ@q6 z6iV@pw}|XZ3?prA*Tv;^31!hc%8M?)s%&Uo*5&Ljd|%sJKiousrwJ3J4*5xI;z%mliR3eChgV|4jK zGlA~wD==#t*)M*h2Xb~#r!jg8N4O6IuOG!^)*3!?`KPh)|EoDhalDSq z0&rAmee`|pj`f9&#F!n?@R(5$&;|bNTbY+&l`rMN72xVXf|+9{gWW zq8-MM)3J^78#&*k)$Qf{UOB&m^B*12X34FyxE1Rj8O;r4uTXQYR%*r0MCxA~J^Q-A zz&X^ArDDQ{{Um>G*y*sWxlSKA2R|yMSKQbG-y?v}SD{6OR3-wApCG1CDk$&^ zbrbCRs9$5gNeyl2)*siVK+wTMXW8^mlxZVvzSw=o8TLzQmi^JpBM@3neFl;X-H9MM zd_MglLuF1;3ap&{|7d#`@TjVD;XjiE2-h7XKv0yRpoyXo!J0sTY%&8gFauaFY85XB zMXeSvnGGlb24*7JXB@Sywzj9|(;nL%d#CMbM68%_NdhVcw0PkN!Ru^B+kgs5#LWNq zu01oE0G_Y?p7ZB<$n4A7>-w(uw%$upo#HX)=ITukJxyWxrw6~vt|Gp{DbX-(+$GI+ z?;Pt=c9vZ^OZU%LepZD$IUqxq;A+tuzRL7qw1e_M;^eZh2t%0r8OR!U{wy~7F|Z4= z?bYlS93JNlzlRU!0xJU0x zi~)%a%^hPnfGb%4%6omN7vbo5Y91i;VnOAN#I)~1ktNce-B>Pf}0r*Osr@B-^B9?^=Ikf%3(?4n)q~2Y2&I3-K9I-+AM5r8q)?Y zhnHEfp5!Z?9Vz=W)nr7^|Ajh_lUd`$QYM-8kx_U`@f>RP7l`HHHP>Q67`ERc271Hg z`L;YS-6$m!W5s8Y>;U7+GwuBdM$(|9eemWa-fUmrcBQwJz zpH8T3-|;xUR4QdsK;Wv`*>K*L8R1D= zIPpK>aeO85_Wwk*gJ!RikH6&F=6wnSn*mx|e=t4_`Uy7QMr>Es+IX zc+yFBR1;5!$YOQ}+N8+*)BM)L%IoI4v1?$toiGpPVe*KHo=^~&_M3fblJxj)Ju=^+ z$H}(x8N9x3wrHV0sOev{WkzJu<)w$$?FO@)I_Nm;TiT`)c?<=15xeeu+W$LMxv+d_ zFBzSjt;@Uc!pBad=050iysoAXrDS+fKt3V!9HXXC?c7M-_tN2cM!1X_VgdAUXIIjbBlHBfSr?=>tjJ;MN)g|;3Mza75*47G0bZu@Edd{E0DT9lQ zC-q=FvwDapa(#S8u=@GaY@0XzvG@+cLP$oJt{%|o39lj^Ko@8CfXVt?eg7|>W`s~< zwKwc7>n)AruyX07FEF6}bYcrZ518&EcXKF*?yZw1dZK&h0iC&bm3pBwB$%Q+U{LCt3?JDk);VkK=^az})*nI1H z-bF9o(h1x&MLU0G|DNDC1`6Jp7;pj$*o@mX6K%HP(|u=H5cjZ0nQzfrY8h$B9k_IBiX_e0d>cHMTF!%zIr{6 zA9a_WT5Wg}$Dj~_5-%Clij)IoB`1UgclxN^U36TIa!$SNad2u{|GCG}$qx7&e9>e4 zLVuoA@j0KYATsBV`Q!X?8>*gO@5q9dzvraLm=hmwpZlD!#(nubra z|KK#U@p5(k;k46qZaFPi?Q(?{*!hRgk;P|=uKV?L#aTVGr^Ox(SA!I8?cJ@O3aYdrW1BlY+Xg(6MH=lBjpeha$U|D zNZxi|5xf5YSpK^{$4-dHcRdYXPIpFTpblNQJ=<6GI&9-cpW_`k#f_X9dK%iN%Xv|- zDbrKhVZ6vD92(Bv?kTD_Td0nbSV`n85}vft-6XbmV5ki9B$0c~gKJKi zlQsfJIRpp=RViHV)aG?Q#^Fr$5LPB0tgb!H?%VJG6l+oQP1H{R04RdM6SF189BQZi zN#@Sc$hxcZDi@e9GM^oFu;^gTNp{*7&eE=RUfcrMX*1D4bcoHhqd|8ZCzcG_9Cq1a zcG;H+`J61#GsEM4?<&3AxERCk_{#tx`|EJ^M=lIz&AqG(k$|+wx1sy70k*nA+k7*3 zB60TcV^J3FJ@5toCxxJlFq#Zfl|&t|5pCVk0{`~qr;=nK$45{%2^L76Gjy;!RW>5x z3B#>?Bn~^B4vt_0>)6wwCmFhg6?W9R-Xz4ILUtY%b3Ea2B7y(xr{Q^|gCc$)N|nx)_tIP_uCtmzVi(Pu2E6 zwjo{#u|@xLS$gerNC-md6w*17>y7JTx49)&yqLO0T-d6)>Yd^)9x=8GOP2YRAozcD zkW}a&Ormi$Z^|ca2Rxn~c`rSnuB=bkR}kM5>=?9qI_)xDL+{%EDM6?Q{3~$;<441s zVm@$5Y)Uvoax})oEScQ| zHG9xLH~x2u!R*#HH?(FGGOtx+2XA;B5lnXH#0HCfX6gGJ^agk5dT^wwB<3WH>8a>P zf67#p5Tk_B)=IMCy@%}Uf1Ov#1nWQRGMNPb&RC-!cFCbGTW?W)(+pdd3DZg9gia5( z4_bXiWIzpFAV%=tNMlSMa{mbQ!nm^_!W3pZ2wg;MlcW&TGqiDO+qzFF+lv-k!rtDw zWMt)&-da&+?5{oN>#X(q?6v>r^}3>p^}6<$TCbl!${Jl^U&rp_dKA~)O{=Tada3*y z1vUea=Ad^~`={bs`p-G&-J%@yaQs=EM^t-4K*$V6eD%=I90-*YvkSoKXSbzCTMM>l zX%A0@Hn_~w`uaN1z5yG(H4o}feiC=gtX&KAAAbVZt=so7k z+3Mvm)8&MY01$4S_uq^jdeE=pWSSs-3T{R1n1jbhIab zXU9BJ?Wf`=O8hrz|N2z>X#wEibtM3ta1aD~(y852M`(7uxq46VOMIs`sR^0-AGf9l zYs8)PdJx9x3-FQ~0O0iiyuChNax4yar9E7zKz6Ub|CmnV0G6;P{E!3DeNS9G zuP~Ds>%8~K9j>CcW-`s?gs8JuQyi`&i(;o^HTEocVqGq`$~_44sAdoDL9=iu;D5kb z)KsoA$KzxkC$#u$EIJn?-qkiqawhEmJJZ4kJMZ0bhYrJ1)F3UoQ!Q?c3;39CuHLU; zRWO_lK-Pb#!NT+h8{Z|K)g6^#oRI(sPP!1R+A4bT2uLBb}HChE0+h7@E03N zgS5rxs~T`Di40vuCrD>YBW{7tcZGFWQKq01jy}HOUV%=I;{Or#x_AoWsw-wU(H9z% z&`DY%8#Y&Kwj&sDSMJ1eN{RtOZpAV2;ZLF`0*BYjOWUv(*X@ zuhvJ)&7O!dYa-6T*~QvmZ!x;n#sUNu<3o38rxrTI0-xNG&*^$XOmV0Tm#OjMTR4UI zC+M&2j040!K?3xh>f%0-#o&AG&|_%DAZM*$ zd2#+q##gGmi!(ACeu#8Cjr<5D6m(9L{0Jo~Kf<(3xm5WPrb&K;5|tlen&d|)QTY+3 zNq&S9l^R4063L3NUyD8AX}<7s zqSmfw+2Z~oFmxQ=5zQLy!G>PZ7k`&2##hll^DE`+<@=pJvuq67sGQjI2khkfDCRE#ezdyl3Y{hIRrYoVOEQd0CojmUYPG3s7GOU~GxrCM_IdpyNwo6_e^SGE}VR z=y!ja2}vb>9CPQay{%AZE#VS}#Ork|@nE&B3uS7HKNSykBG_qlEAs5m^Qj~HO+H7g z=&jWp=9UQEeNd2FZ*pA>2ld?Fb;n7}nai6@t~9-`kx84DNg@9iwPyRhnSxa94| z4BoiXRkEzmxXcrrhGg_dszIJCP@2WaY>+;df}{eU$2qno!BtHc&hNghX~Ws^tnk1) zWF!J~LlVOomKsh>{H##yTaQz@s3lpsS$T+FX@govC0d>FW_h5ix3M5GsMtI`teH8~ z%skzl2m33NDDM6qv$xM&j>dVSCAkEZ>F3>C*llZ}JGf4@uk5^3P0|ZSwnb_zuU(m} z(QR_{j3ur)qkyi>EM)q28L1W0SBxdDz@@%j zMwxT+(i|ixKIr2#kIDy{`8_rM7D!ia;s|VUj@2PEZoZK=q4)o% z?B$Ocav`b;h=)60tDBP}i&}M2*tZKV3nr7kOd78Cja!Z&P5{YkdP`ncD6`2PGUr1| zAOTVX`w;Q$I{x3tF~j}27#5-*&hnTu^JCTG+a$*i<^)kBFbRC44w>W|DvI2|H!I~E zbnHVIbbib&3%aN|R!S#sO^408Uu0$kz9g2}qGqFSaus`}R2~Z(=ZFWyKuy@c^oDdX$S$XX`WOQSzr}UtR3-tfr5#+Saxj5be% z10s$cNsbADVDVk`UNeScv9~BHOi)8S8>5z9+C#Sp*$uX@&>nf9m*5So-+mw$WD4Mr zj0q>I|3vrH`=`nB+_^>DBu@JH6=Y%w!=g-@f=f0>jYni5FCD@jp(K6&_vj-oLWtcF!<@q%SX?5gJ z93o|}vCB?TW&76-SLPpK7(QV)2LruWcuIH5&6x^=Y8vM_l9d=HnAE;u&{brkt0{oh&Zle0GyyQgHT|hW} zZ^)?~BA-dk%0E9ggREq;<)M$ctH_xhX7JL{*(SA0ZxU7Ps~UrY5LN8RvD>x37mbM< zXO=LG=VZ58j8P2dPOmT#d~0M#(|KOAA!esT>E7Qw>oI=WLT<9yg-Tfyt**4ZC%MpOF*W`(ZimX~x@e(sG_V)a#L z?^C^`z3K#rV>MyBXS9{qqUovRu=4@xeh`?xpZZBF?bV!C?AK}a5zL*(0^joAzVh@0qbBP{lt>u|J zQjtsNa!U4Ax_ja)mENmAX7a2ki&8mA5E2iKzgu6hA!}LG35tib_lr%=l7+O;e#*#_ zrOofe9_y#o~H<$)A;PA1GW-e zGk%oeGsgZU_|=Q;X>As}M*usqK}h&cyP1|)cW8B45PF%g+>!>0!)}$px*liu)(%0V zons9W^cAUsC@&~bvyanU5A6BZ^a7DN6DSmIkZ0%}wYp5IpCCQ?9*=4(CJ>)CTv5{9 zlM;GDkpiu*LKVAL6)UKvp74S~um%O@6tWvjw7LbkB`sReqe|q~(w*>veBSbZ0Rf$c z$jfo^GOL!&A>&m8t;n~A@l=g;0et+h^Z)qe~A(v{d_<2Q9ed*ntzzhani3{qW9(v5>| z5InLaCu-+${O?7g1*^LqN4z8gurm*Ith>}3xi!}rzSap>?ka&xpVjEmW_*bW!v5Hx zZg^w=_7NG>RnlDfuio%2IkBGb=Z)M&E#vK4c2mo4YB^0UCjcHk(l*KYJ`wEPW|xb6 zZs84V)%9>%`?ZHB@Md0Q5`C0VREa+N99Wr1Z2r#bXQc7ia{?QCfDtCxhN=ASm1G%M zNd-;^S`SeB} zV7^8>!#6VP|IK{;H}mxx^L5ZwJHi{j5o!BIW@wMke4X?J8z!KDbT=H$_B!@}sdMK= z@-ARSnY0VU8UVwV>fbR*BVs#}^0YVd%{H0b&;llxS2Nn2wRq#rK#i|M(;jSdo1k4e z&_q$WgZb$M;;y1Byf!BSJAk@lqJuywPY%8T%xtkQCr2(Wm=-4s~sY%92Qa~ODUvkL4HXC=8J%VEOtc! zi^`rx^daVYKeyN-R!s1gw)j!SRTa3K8d@1z?2@GYt$75#0sdIDM3MQl4Sj^aDm~zL zgRf*OIN=kHy2C43re+KVdg6O$t>z8SW47mU;8O43!UywOQU1WQ*5~qN<>A;OL zxhhKz!#k5<%#ft4qTCs-I0{!uOVv_uWG+>q>lvmh1!Km(LC+=OVt5wc&gI*Ae9QT) zR@X1_T|?Cs-pFFRwpx@@b~k|i3||;8E&TA#_n9NmUlO^_e47s)?Ek9UDd?>2tNMeJ zoY$Pqe?5n4Rks*jiK>hMYiXUHO#v7?IKZk4Yf1Iu=6uo}UQCzBN`_7ff)(on2bBc{ zJ1d{8e!aeU0s6sHq9RQ3<$vO^zrEM$yNEP(ZJnG4B~qXRY_r<@TMA9wrhl#`=xAUWKFF;sTLsz=K%YMNdMDt?{(yi6q`d=7I`NMc?HG6{-%; zRkW+G>hVlYMpTze5?w}*HLG1U&7Ya7raJ_Y!{xR3(Fgx0B{$poo{uuP0h&dhvk6W?`D1EaRPgN&_akUCU%?8%dP zyN(Zhk@akBc)6J(<>th`Bhw>h40N%(2jNw8ah2+Yd>G+9(~|m-nT)MW)}pL>q}Rd` z&J{#5Pp#7XiArgP50wPjjzxs8Oz7hs~=v_oN)u{dzI!Qpw#H92vV?>T-fi-``2njyFYyaKB3 z^3R4fl#B8T(=1&&OTxywLj)Aeci3ie8;^Fc3A$Q6KKKf_H9hDkTAE3 zWuAYAyYyvkvv?+?qQ(5CTB+${MWW5k$Ik0_o`w&J(s7DZ8l=4V?GvIyJnX~bJjW8X z7;}pXi;Sil3BmOnB@3(aAFJ|sbVeWK6RdFLq&vgwh@vX;7IpZmLFA{g-|<$i^_dp3 zK)u&NY)hM43d64}C?oH_#I-;7`GMwxwy)1cNz z?2R626?@l5usRw%pjHfyYGrlWy``@itxT&SdZL!t6@=50i=OmC56?XfP@dM2d%4(k z8mB1HXNVE;XkpUbrY>3w|1dNbJqd@kWq{JYr<*H8t3O4faJ`w*D4eNJ0IIuQn!waV zuU;!Nzf%v-EF>e54k9qKnkuqo?UprFpwDfr=*L7>!4qwqxpZPL&L|LB591O-K(alt?W`->NR%wENqa^rS z!>4dDucA$|+|Re$&o_{&9c@xnAfgZ@Y>O8?m#1{MwmFB-vD1|k#EfX=gE$f>y^pU& z)JaImZy{_)XPYDWoy7TQBa|lYE&7eA9 zQqdnCQ0a@5OV z+RgeBdt*m`7-NwuH_IZY))#vNIc8Z65xt8PO&=M9Vpm9e%!1guT;Stig=+uq32(@c zKIH90)Qv}%Q-AEgN#R6mNL%5x1#;-pH#&2Hm^W8}a!&eDBUI(GA(Lm#Rw*APZ`Aq8 zg8AyWWJ96)*ln(z5FIKV53f~cIOr+Y<}-wxo0eE#^;ICtWmSr42Pt(c5Y>#tO$DSfFl(|d{a({FwePgavEkeUzCr%J!P;mf=T9imBvZ6>Jf zx)vP37|-@HSz@y@dJpmY7$d!}_fKo8D3PUCc=0Isz+2P?;7@=nMHub%h`70%6$Qp5 z1Wq-i)T&sOq90@I$r>WP9zz0@(#7@O((km876gG~-ZE;BU zN<@Rbu>us2tH2m3`Hv9k@Ia_x4x-VcoUUyjkjokRDV>yKl}Cdeqt?Gdd>Q|n!H)4p zg*!5v%{PzY$E)tu1J${XX~s`H4tCV6LU+@w3GfaXO|!(!h@IX`dBU2r3V_SZ*o0t5 z+<$GXB-k;{n8?d#MAym7w6A42d@YrzZna2+1vN;P*Ny$4FOrw5KQHe+FE~&&$_Ho2 zLy~TTbC9|L884{WdHwxh$Mn^`yrT~pcc>FjsOB{P`e4UYEhIjaGOU-q=JkbOSk8Ip zO`rp4SLpu0>qIMI&MUAC@Q4&qyq|QcyHKyw^hSokJIj|S=ZSOVmR{4xs?fXwI-o48 z&)r@zx+H0jvm+}rS=Cv+x**xBBTV3#`&E%(z^*SX34Rqk<_%w>wqB$x8z**l>2}Wk zfvgkJ`UsnZ(s0_1B)9MuwI)7ec@{EzF=9>kx`4g|h9J%=0Y&;qCo2lSv|c5lpE^*~w9 zG)`&EdFR-aSD6;MT5b1RigLe5yt$Gg}DfqFtzWb5f zFF0d>q@GjwCo=HTUw#@Vtdzt~-AFsolXU#^7Hzu(|F|O8fqy!|KU}qPbY9vBo8akoXG-Na}F$6(IGHw;O7$isVo7?#A>(C4ML<{~W zHJyc1`hrvJQ|}aB(Lyg%QsI^l)x~(@rE~A~FL-TpKGkQp2GpMc;{nC%cPVpJ*90% z3%xMqfB+OMibi3M5?I-iAvU2?0diC6eL{?z_rH8-n zvEqVn61zqb8;oom0wfCa_1HYDGxF(_S?F4OU3!u!j0~JExG=GM5~!^Qzh~Pl!t#j@ z>n@m9R}1tMqvfLaw1I4*X%Br2Q!y8B z9oE}9Fry5)SI*wk*~Y6MO0kVvNRmY}6I6h>Dj^Cbd4kP4dd;OW7ov|9C_swDx9m>t zto5`3-SFQM>=^6!&x;Hg7wj0V)$FDc#GYm!5tJN~t>F|0GHY{vMF zjBe9vB#emKWZStAI@(}O=PKDse`zH}g2f$znR7G}Z*UyK9qkR0_TaJc;V$JnwlaxR z_V{CGHr1lld_URLZxcb1=> zC8)d|ilyj|_n0@n z3M6WE=LI`Q`}+nv>F!zq{zxA7zIK7%P#`dwO(j8?KmY_6r@hs8#)YSWke~RS~D--GUwn8>T|46EN9w94Lu>+P)u@U)wVYPh9UQaBng+?l|Aqnrjw;h4Zsrq6*myS9+VkU$w`e7il|9c=XI!y6Op%x?yJ8$%oE zt4&22>?@e?SSxr}c9St9&{1Jb6%fmE8rR5gwr*T0zr7Y3W97HEZd@q8eQq*_iovCT zpB%l;qyp>rvM$n>v<~cw_NQUH-81I<^W=P!dl}#uI)k3r^KFwPC32e!Qj;iA%+7&B zM)cIDrSOS=KC=X-mkoZb#|G~OE-|hLkN6)H9P+BbkEdvt`_x-$+gl~SQHZ+}aIjue zGpo*oC&U=GfP|vt0(4B{&p)S-*iimoDjO)%z3HrS!L|7qCCc+eyD?m3MZu7!_OV9) zU0A^X0SRrPK#Y#rMbZ#dVkZD02&2;7gMYIDR1wjh%@BxVDa26WI7)iKNHG#e_u5HB z7J+G><3qt>zM@vIjSK~K#Rx{&>!&?Spr>sS5jCyUW0YD;Da??hDtbD>dH@WN#v$~e z=kt|b33f0HGk90dyvR7rH+O%PBve!anaLFZNa;r)KIC5LBOXeStR?gfPhK8SfinrzmG0-DUBx1#K7nmA10TsPUEujc#Gk6Gn3%k%9$Kx%+ z;tuB#U4?6KX|50B&B6AZ)rUPx2R!6;99Q2VoT1d_Tr8`yk(!@YEnHzd%XYl?Rh$$e z1OF1s>|t+=qbx3@-Sh1UT8_%eoJ!y@R*!R%|8K6yx1Q1?-)hwZU!KqN0~~D}a%mOs za5C+1mYmN)xqq*?nuTP-paKAXxx%d2ZE~i;`LXe1i>znp4->;(12V^sM}}q<@IpDs ziht8)IXC3QLm`|?yM(BP_yVfFM%?aCH*%c`eOnO8v`9bT|G#c z^!RH=43>?cQ@Bvw{;gwdv5$mQEMV@K!ZZX0l!xN}7$G#D!cUzgZ$H0WtCJK} z4cKLK(Dfio4)yNzH(BC<0T`=Q{1)x7IzTh#nvp7p;#Q)!txeFXr4(gN@LJvz%Tpal z?Qc)K$sK>$9sJVaUno(}9)Lj~9_+l_e`&CDyrJuX4UWr=$#yBl$WS!1Qj9l33f_tj zNRjcz2)oE19W*gesUGd~oZQeX zpb##Ws7C#mrReZP$7>{Hg#CQOc>D(A584B&`BCcmmMP-@$#a$X?BnPs>oR3l)M5dv zvgNhVwMdLHgRSAeIk_57&WzzcT@Hp}zg^9VAtW4AX#d|M>zVqQt>uBZOg$dWb?sUO z9zB(g@)8UKPxxQ8qKHjYrrOYI-r+7rE|8d=3@bK}4oB~#8|pp8z@2u~pzzlMg#Ta{ z{OFak-H^7mO`?j$?lQQiAlQ*$W;kkfsQcwwO*OAU9>0$={>aeK_i!~z%)i1P$GhR_ ze+7R$Ce4L8E5puG;Sburq)oNG^xu!g)9J(iQu_mw%o+I=_f`aiLLVLc~iEBjN& z94QJX^k4yf)I#qvnfew7WF_Y%9J{w`K-l@#0iLG!R~7xE%sauTLce36;8W}aJ6Vn` z-06XiOSPI`a1~hZxJ0Y*Qj`*NGhOCh9Rz_gZjDy6)BbL5)=a`1=o>pk6R(8|_^WRN zGqI>B@0JUEVW=|_BZe=hXdy9uBq+d>`o=G%ynn8aF^|jfGWYR}+zjo}RtjK^gs}(a zF~)9>d4Nlmp1FH{_2=0t5~C)j+2`5#xY+6wuj8P%=l~kM(Yp4N9j<~Fum|bQ#n4El za}$+1Z~JK>iNRxSpfR+Ije4N-WaT}2u%SiY23?S@XIK6ywZB#Wb^7nWN{`&s82IvJ z=zHF|B`PgC4m_wairz7xkQGB#bRn%AFV4v0MXUGC6x zwnN}5_UjFu`8ru?MIm0r*GrsfJpx`FSOuvo@;eg4z_<+Fn;NV zk->O@|9Z~rgYk>~qhfE!h*J177{APqH9YTb_Wvoi)vm8}XVtH%RMuas8;qH%|Ec15 zp!4Q(?eQiRov^`O+EDpH%v|=^nfVETHRoV}_xHp1zL^7u#xJnrYiO9n_5j?@>yo$S%s!z zF$Jox&YEiE@soYAA6qX~S1;>Bp`G?kwxwdd1)GRh6dzFu`&LGKO})U`2Ls3A+e9{u zF0WFK>-~%OAdssQ%AJa6#M+X})PsMUFXyW$++-`tmQotam)e+rP8m5S*ClhP{K4pF za32o`Y!reZs3NGl)Dh!!Z{*5@FnTt<5lyEknX(Dve?*Tj+)bqwg@G3?gkEPD8pJ9u z!~ae^n9qI82LR0t&nYmdj2yWE$sfx%gy5w$VR$G-vB=e4;s_ymj@WVlht^ zAHbLhQ-!ENuheVT)2K{t9Z7tTy-4b4`7C}FapGl{xS9G|upE)hLfBpm_c>l6zkr;t zNeJ#DWaN*X*vpx&t$0X9^O;qSsAMY~f{GGq-`7&B4^`9lg!BZSli=osu~Fos!i-V0 zuI4-LqE4sT6+Kj`J_i2%_hDHB3(_Dl2lDt8_zaZZY~T&K$6I=|>NAe-BkLW{Itcny zdZel!(>T+iPwwsim5M^!3U|@cSdmvn`}JZn7$gAEDl`RRMj+<{*<)%ehU+iNU2H>l zVHbtPv1zONApfinl$tCy+8tRtoD!q-?W3rGU^s2aGdYTTJQ4knDVWjdoH!gSieVYC zYf^<@OcahHMA?OpMYr08uNaQ~-r8Yg>qaGpmhKC$83icQ%{y#)qH(jBOcQbxfQqM` z4^lwG@v^cZr;moj4K%@h!1_4yyw|hd1XkJann% zqjGU_RzU$r?%|5`&bduTvUAIt^x>BzCIG}!RVY0iMDwU4&7jm^kBv27i!dvDt*iua z@)e;PT-UO_pPK1o(fd*R$Tph>tL?qw&SuH4A)%XpEkn^8U3p7=<~ryryJnuJ$)zTS zZP9|Ezh3JaZcE{@#oq8U_6N=}@`ZTfeg$kAEyjFLlXHyvOl%=*onwaEYRTC3p2)g0 z_KweFTl0~eUOc-pGozx>c@3M###G2@0$L>Ss2($%>PP7>$u`1j8o%M{G3=wxXqEj@ zS?VJjF47bzUlVUfZH^Uejz#Q^9R`!G))I(V?lp_jCw)wYz1$hraG;eVU{v-@@J??L z669e|e4iG&o~griiX~AJr9u@M^W#}5{zUdcnbM|`;!!l)x$e;?{QZ$e#PAEFsZ$b_ zSPS)G8IcF@>*s=PnLCC<1}ewxYYT@1Ab7#G$nLDD1WZoyqZQirNoCuvVRjH&pZF%i z#=m~YUgl&Q@6v{75wL3CLJLUQEg;CPC_vyi#BC61dAw4S<3>1@)&pgZF5$_q zlq(u!l;D56Grg!2Bl9w&h0szyCp&h%AA8DOLJ&%$SaR}-w+Q;X6Hk2?23nI!Fv`LZ zTVl@q!3LU{c~w61Dv{^3nrW2xG|lXWn3==%ztEu!OZ1EOBq&za6S+Ur9hpOLgpSP0 z2MIno0*Zi*%c|v`rY81W9K|=Sel~8u*qUq=l?~`^vKBG}pF*7!F%oq>W znPz(|2s;2?`Er#0mjs!8-)AnP_wPj)QiTAX@E+inOFQf!B+>X+~nB3~UuoQqz0!{cq1Vgp$7u1p_kfe5&u1=W#8p!%8&PJ99a zxY~9<3i!y>%l_-r_%?OK1;&bY+^rCjtc3q&4(G-LTD~G;b*5<3d(pqzWwaXcPCk<) zN#ZxH=0V zoFcc$ZPDs8?@W-}_oAiuC~`YCMLC6^5Z@a4jJZy1NT}`SNh%%N@b&M6f`244YVWi( zDsDE$ZadfXDrRALvj2)#NU;|eox34vWFw9AU=#4{hKUhw@Jy=T&4ir`p5f;bCZdHH z5JS<~qk*!*30jSs`H0Ux%Wsd%&$!)0aj-e-Q|EB(9n(A%mi#suqJL?S9U z)inLUOjy|Qu86w@)k|NP6CAma=1C3qku{D=kkqfzYLvc>Wa7wU9`h9(4lx3#8pbfn z3W7~7wn+t1c!TkNl}FH98TWMWiL1__c2^}CS!|@0$4ht7Bw?gkg}Sxp`ikt)Sf1qm z75yavrOLv<@W7qrbq-(Y>8e#Q@B<2zHu6s69@Qb~;!sdv4hPcyUct^Qj6OD^J*wBq z`c}=unkXl@qlM^6t1HCv7sG~72}{;Pf6`q@+bnkI6!c)?9aRiCi%aX3dDc;xWAhce zHyYWnl}JI48vYXOxLDiVAYX2i!#H&yCuzWy-%GNmBpK(OX}p3&L8!RM)DM5h2?uPS z!lEK3|JPE59Q?CHjUF~$iTM?CtOQcU9NW=ZVUBICx-vAI+>yLBrssXT)qmABMZs61-d&|;4;2CO5d$q1SNCF#*#XJiW ztJ9g-7#kCJbqim#xK3m*q7z3y|Ch{+u10wqK@&PO=Wc_S=jb#qX%lw(*7ORapg3=t|EPeVybZ5alEf zO|a6(RkiN$Y|bHe3?i}dGNv^^%8Z;szh#3YqiP8^3Kd9TNJm{Z_T>4d}yeZ)wapN+1y2WQ42qk3nKxg$_f+Z{xnC+{(W0gCfJ0 zqhb#x%E())%xKhyD>~g6P`q$#xjo>7T;P}mF}U`O;YZ(zG4RA3N_8=enIEvFaMUY?7Jc?m4gMR#0K<2B9J@V0J6xL z?E)aa@b7GF=E_^{FHZMC@gY(A zI>_OWMe9kv=LL~u@DcxSkGVvlK?&6N5OAP3IxkccTHi>4Fi7*k91eAaHcL#c^KAVx zfWkZPlyB!$JpfU3UOpVahW@o*Wqe?Rsh#VVJcN3DvFP4jCBt=HeXxDGf2SwhM>&6$ z7ifdaiGYVVTdq{vzVLLt_EzHfxtejFR1kMN>TV^F$YN`CeQ^Lys)+6rCUW)VJ)1jf zH%C*?FQ>~IHH9CN`L1=VdX@P~55(??Y_P#h3ATXQ7e4XRPAHA4WTkDE^V;DAXIe@> z>b1umxB$lL&cXjFdt)~dh81K*R-z6~gm)pLPoTQQahX>05FNwRt&cclk{*(fMYwnP zCt&8!i;Rpc>@Ap6Z|_W9ExzaV_mxJ+H~Mwq;D~3^U>xz8%{~V?Ar4kefx=vSnK23f zK~#_3O0!~*nT^s6x>)pe3bP5oa?*s^dK(RgBKCaKjf`;-O=!aIS#k!UhnZxjCBHx0 z-#n?z#HJoM(6*{8VTc3OnU2ehOM2=z^@O&zN#82Q$4jhzAIIZMEO(lk)5h;*;3F+qddI;cuoqSZQQFojy@DH?eG&8qPr3@XL&8V#<@y zA10K%qMjXYqqArpEv0n7Lyf=#!!9$j8}(rZ+=O_iG2!-=^=;0}&jCM4`lD3r%D=48 z6LDpVA8ydj95DpKGgQDxcsT@%%N4GNp+{{NZ0z!T#IqJuR?qfN>F)%sh&)h`xotR~ z!TSB83JZhXH!3_PUHH225=_(FuL|Eu|BJ@U!g_Oqpm8zlJI6f!~E61F4H` z7bj~Nu$EorEBah10+uj%As?^YU=O?$dkHaT?bc31s|;cPFtawiUyGGRKb=x&t50Mi zl*BnV`B75hwE3Jxf_c>ldNQHi0&@;SX1pnZnInRx*!U#EPU)skC)lItTP&W<7$uoj z;<4F`Ymc)xfiipl5V;DA_=xTh`}e967Im&ctf!4nx5c7_ z0!UfRHUq@Awg-0nX5wF^seAhMQ1@hXy925AiJrj1xP_}Co`#BuqYg>zt&`+`-dFrj zYKMJafGx@V0845cbDC4Oj2w@NomStPHDH-K(*YaZqFOx%JP3FRCszj8wqfI!#w zh@8kw4mKAA+wVtwh|FT6wN;(R4jT@d>PJBBOe|muHW2H}-nXeEP3u>?|yA=FxyFXH}6aoekX zjusD=>ZSFo?xRy44jzl}@vT42wkAPQL$*-x0ZJa0{n_fDIisX{blf-&${&51aSSy% z`!NNFRYa>&?1WbH?<`?A9Ht$tSU;0D!KNOh0$sVBuaIkgL>j5!tCXl8yCgvxP~j#I zNjem1z?MtSN#XxCy@SxUzP04U{`s_cG@ z(k}zk^@{!SYw+iM52*}9=lO~Up*^qoknQW7z9~HBK2p>Gj+|;=9_#yIwEUD?LfNg%Twf+Nqh1F9T4N3}&Zav9m^YMp@4 znNu~AtZh>SkfqIi)_TO>=Rd=7#Cla8;wxU&hZ4VLX~ar2c(k?n0O{Cz{oqj;cWuSM zefICrZ>V3%H$*D8pA3=qxcJ!+*|Bz7x6@I6KVPPuZsYf>W!gI(%QQc~EB?l{#WlYx zPA$`pd`1~kz8yNUOp6`n*%v&M@809thdld;jBhs&Jt}$Mh8~B-DnQONOo?5l(my<# z?_Z81vE5s8oUG{e&ck+JcRZqghjz++%0A>XZN1%JioQ=Xt^9tnOgk)H;&%m29+KyD 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 diff --git a/vendor/github.com/DataDog/go-libddwaf/v2/internal/lib/libddwaf-linux-arm64.so b/vendor/github.com/DataDog/go-libddwaf/v2/internal/lib/libddwaf-linux-arm64.so deleted file mode 100644 index d906d9756047ce484fe43ac65e049c079125e499..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2030704 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℘#eIVbJ z^CFgihd!CePbJS({x)?ol&`_MWb%di-dz3(^-#!{;Q5h!7WzghPspv3PaXQde0}EG z$Tz`T`DyImPQD&>9{r=A|6SC{Kt4D15X+|x^)FwR98&p0tnbjy_?di8&V^k5Dt)q$ z9}v!8`FxC1%4ecJEBOlarCNR;`84unLjB7h=l4P<--2^0db6MZ@${vEd}eZvpPM^x7WB&mhwl)vy#6@f2-xQ&^H?S9IRt2 zpEvX$`Bt1?(Odoe7vcGV{2A6Umj9l6NFv{s^-bjyZ86SaC|@?zzdYu9bNT#uA>W?w z8p&S``O8-e=dXM>#;N5Wvo4K%G3L|CyYTlP`ID@B^maf0U-I68{7vQ`%fDnkiTnk| zPv!fwUxxB2SeHz`3ircYKH;t7bu8q!@^|Tx{8aXJDgTUoD*2r3_gcO&eY=sbOuudA zXLAmA^7$A)`e#4?_sDr5pMmozmVeCiiTnW8F_pi@x(wxOk#i=WoSbv{AmlHfmUSG- zx8!^*{eO1@~wUw#hfX(L~jzSqiQ&izil66ZzqPCx&3*pCDGQlbCLHz2n}zD78I zR-M*>ypSf3Hi%k<{TNymkPgsn{A=pAl&{Ks zD)}L=jQ_q`%hzCkHS#yu*R6az_Gu?yh1{a|`}yz6^8@)t)LSh7GMvBioN-e59n|Mg zer~w`%kSm+T)uv||I0Vz{2IygQ2+9W8NZV6vcY&?*YYD-mqxx8dA9Nm@J{|;?p@Ib z{ru+${YReBXJYx+?8ijDKi`|mw+#J9ehANJ@@wd;x%@Hqdm(>1+&|?LZ!@mvQvT=A zf8?8zTP@##KG4W_CZAUR67%WgSFwMiuAl!V)YU+~KlL2T*Jl4F^1J!2R6Y#-N4`0A zo5{CiKDm6tocq80(D3_9zB{><@^|SQm3(RXVJ&}x{nE(yV!yQV?U;WjUz_tZ`mmq> zA>=%eZ$mz@eB#~4b(P4cz*G6m;rFln$WZ_CpHqjqeDaXL{AcvZk$mrvzkEveMI|4S zPc7ep`84vI!u?0S5ckGTJ{|9kKI-RxWXNB>Q^;Sw0(Fwe=cSLO^3`~LC|`nkX7bI* zA(vmqy{M26SeKFfBkH`Ae-Y|mzCyVF$akfl8~K5(Z!6Ej{a^k%eJT2PKmY6LO9S~Y z=x?!nKlWWBUzR*m`EPiBDBqcRX7UrLhg`lI`4sYk97gh^L;cI6#m0TClHX1}*YbPt zMt&=~wemfw+fF_${UQ3epZ{MOe<06U_gMZ8>zK$lqtB=ENzNMgtD*cu#>wO-ky|c5 z125$3ur4F{BJ9Uf{$1u%$=3<}U;aIwZ{#aeZ>@Zd(0}Atvwx#c`uRT??*H=BsKZ!3 z;g9+KC7+2tkjl3X=db)c^33Gtg!-4Czm3J&n)DdP|qXzh15?e{{`nxC4ZiKW-Z^B=Noy> zJX`s};rx}K$o!+v`}r@xx)0=woBaO{o7b`uXojzZ%F7raoi&k<34l@4+~! zJ@kM15}c2j{K|0t%6DS^h5U!q$w)p2=TRv?BGkY9IJ}nc&HNkrpF;lfBgn0j-^ugQ zfBN~~AMT&>2{rs0?{DFKQ>NA$l#5@!EK|G(zZy|@Fd~eS2Oui?5 zK9|46`B=ygWSo)wLe{sG&%yjF`PQNT$RDLYH}Zn_w(<+u7oGe~_I32%e*Ra7`j_8` z$MUC`Pa;1#^ndwbtjkdT5Pc()pGBSI@}oolm;Z`$e`X+$%cyqMV!2H~swIV_gRFd8w0FeiHLZMRQ@sJ59KS+pELO#QMjkC&T?GilhJiGttD~{*UNn z<};A5Mn19pefmHm{{&CvU*SXfz2uz9XQiL#@-JD(LVjt;Uw#|=x0E;RyGnit=X))` zBHVxEZ-o1gd=>UZCqIpQS2RKVZSW!gGpOf*dS`oEm*0J*{Ew_xC7+!6)beXX{_?*wpH}`)ypu0NKZz!cqyPOA z^1qEd2lC~~Etc=dIhDwdq<&KQ^7M_N{04H!qO8GMM=Ssc-^RMNbF`q_$AM4x7ce!uU|JPNcsFPn$Zqa1@{HG25 zUw#qa8_V}%{6szzeLIyu6piOIl&{SCX7Wk?Jju87&*c|#9u@Li`L2ZFtZoN=Nl`uX3* z{0H*qL;mt1=T0Jjjo(43{5P!cP<}K0Gn4;|{+Y{v%Q%JnKI&m4-;s4J<(us`-d~mc zuyFs8AJ2Om`Cr1{Kjm++j-7mC>L;4ApZ}}mJdj^RUybFDvA+`eW~@spf12lq@`spz zCjS$4mCK){pA_;td443{fqElP_vpL*{9ok0 zF_8ZqkL5FQUL^8Y$S0LI8kLk$eu$qted&EBU|KceQ+X z=F`X@3H?XD2m7v*KN$M|RQ>$7>3f;{4*F6q zKRfgv`I-Fva3p`6`Yh$YBA-hBDD$c1+mb^gev!VaUH{~9f%b#SNLjFSN|MIQrho$^wa;xO?vM*}+KiJoe z{5|$#D}O)qfBDb(u4tNm{{Ia9N4_`vE|!17_=$Y?aQ~5))a_9I0(Fwf_hKD$`C-&g zA^(c`jO3T|-ctTJeV~#rLS5DJV|Z^P|2X6?Ka+ayxzPA+e9jL33e8*7#^7F~3l0VGfJ!<*A^utEJ z2>Yd#A4uJH^4F-hXxe`M*K%JS$p6K@i{;l)SBZQIa!%#Dk>h zyf=|w!F@HAFUh_h$_wfwlXv0oKl1ZAXAAj(eAh^RQ|LeP4@3U)x2exsJ}q_C$lqn% zTlq8ew@!XDbsl}MpZ}BL_m}(HO|3QJ{f&uD1SKo{*wQPy3OU!vo8wy z0iplM-wF30`O&OI~h^Fu7{{%S<X~o%9~!F{HXA07I?d~v?Fl+VDqU&;T={;lPcOgWxU zBX8-4t$c%U{>smw&ZC+7`M06}$j{^XSe~=*68UU=S1NyleKeH6i)ZrHL;mtpS@%Nz z5#x;H4^vmA{B-KMk}ntT|MD5BpGH0x-`mP3eRo`ko%|~HT{Lq)|1X&TKt3n?I+kzB z`X=(N@Kin(^BKxdqHZ(!*YvksK07%S@*h&?Bl&u)V=4bD`?`|v&Hk$8AJAtS`GGv& z%4ZDyU%o$e8_m+s|9sBbfqXjpc`Uz}eUZq|ran{o3*4`U^4XbZCZ7k-h|CfJ{aawu9`gZb-sfXzQ`uYDK;|$~%@!nYe2RxB4 z%J-)7@9R&$b)8o1w z$=~99Eag-3d?i1R@2ces(&robTg<1GKO5>_J{|9kX6xraJ^gtgza#wn7x`4wTOvP+ zdPwD0(yxZ{=@}=JzaReoAitOS6!Hy1|B+wEdrSEt^x;Z=Bwou`i z^7mPI@5<#1u&)dGSIl!H|0LAE z{Ca)|Rq|!Xt(H&C{%z!Mac^wp7qgE#`9H`Znxmipt;}a2pMm$r^6R-rCGt(F!&H7J zeQzkAXuoma$m9=G=ehiSzPFH1&G|Bt&p)Xk14fp@JpMM?dU%ngjjODL!pG@R;l0z!LFZ6%; z0wI6-Z0x&S{sY#xkjK>3NdDvS`&Yhbxc|tP!fW|T;rx|fNuO!umve9Fg#Z5kr;I<4*X);A{=<;J{7(8qDnFPUhVqN~ z-b{WI^UUS*R|D5wNn!BI> zeVmU2`CRm|SpF63o5-&W_fPqXtk+QfALgIQf6Vi_{4w@LAzwPwzkKd+{>uNxeyrq= zkV7q>iS=sa3zAPOpWy!Sx!K8|;9e2U)6f4pavR7OV*aswf9fQWuTGy#yE}w$j3i(3hGm=ls^QHW2 z?qijFUglHFAEECx@~!E6t$fJ*JNdfo>uA1y{u3QO$^XhH8pwZ0-;3o-urCt%kUCH0 z8-@NOzmEGuCf|WRnaek39SiwZoL?jP)AXxSzAW>vz6ATOl`l!ooqQv5h!*JQziYVv$nPSDSiU3kPvpxopH%*{kiUG5 z2`2sDwu>@(&U|wD+x+e*5;{>!mm1NrXc9Ls0r?{$fMZ=O%(S?K@rBRNMh`CN>j%hzYU3i)fCYa{vFEPQD=?E!5Bde(HQ6U;Wkbxe&|epbsSSl|%i@HzBv7 z{Poa(duw~&9z^CS8D;r=6EgLzi+cbHEt-~nS-Ahm@27r-@}F@oXYz?39ItyWf0S_w`MlJ_NPYs$5H3eV*UI#q231a2g2WfM)a+crM?V918jV)a^)qz>m0p%HIrs|BiFQ^|K?U)1tLxpy`4H9j5BzmU<_KTV&Bmg?s}$uGz69muC(KC%2b>L-z3L*1tGiRK=UKa}4@{bcfO z$tRb8$$l^7yYT!-z7_eD@|Vb=k{?XH)$)1R7ma*jyp^9qKArqf>MB~gpa1Kj|I3#M z=db*H?lXz}EZ&>SkK(;U`E=p@l`l=5=kf`6ANS!x{xF1Sv7w$#1{7Uj^kxg0Ii&;O;+|K%4@ z&$0Zn(0}9$hVxf`HO~*_`%#CP{5rljm+wGb74j9>FC+QyLjB7R3ctVP>yTS5pKN#T zKl0x&|5mZ z-;jI?`BB`@NAiSvDCMtHZD4{vmah%BN$Tq5M$lB$FQ%>R-Mn>s81Xpsq&p<3jz*XXc(z$=3<}M?NRdH}YBd zu2x=z{x3hB^Ez6gpZ~e|Kz=mi#PSuWpG1BG^^?jkrhbO<4f)X&-0~xKJFov{33Fw>X3NPgAvW_G9#e7#OKc7BO$?p#5ul#=YOCx`f=Ue&uA%FRf z+?S%XpZ^~CKz<4HjO9B~KZ(2v_aFIHj5CyP7V?*$MjhtzbEvmMel~S7l7DzB_aFHt zFG_zaVXPudGWWUzPW^@_op;lfTY)MXScq z|NaU8{r@}R?{D&@xbMaC%jv6${O8njD!+p79m=o8Gx?SDja+^W?=9pjklRT9H*zcG zzYhIhz60~G*Fb(8dB*Z-b|2rv6ZvAiHQ+y{2_8H-_G-~e8!N!e0%at<>!R_<==2G z%H&t_do7o5cK9U!uWLq8A-_DFzw*1N^HRPcc~55xH@UzIv3>l*nh;rFln0nUp~{&_fm*X-wi3+p?OZ^Jsq^82Z)L|*Z|seE?! z%TRs+>ypXu3iU6)hy7T{A7&j#@_Be~DZhd`ujG4&^H=^?-rLAurJuL*oI3C1OL2dT z*6QcKKhF>3ejr7OqVZU_pJ*nqt-G2T*AfJJJpHTnu+e7~H1H%1BKIxw)jsEw~Q2ri$ zBa{Dy{gumi5BDGWLp(o{uT4Fa@|V~zmHeNqOD#W*I&9=0hyE|0lJD*0Pf}OWdj0&H z@b^!7$9!V>k65on{x{C4R6gnA75!=`KZ<>t$^XSY zGnZe({w?Hh)AvU5sW|sb`5&p1N`49bq?Z4UbF-1Z!+N#ypU?+7`E#F+`%JV^KmSq4 zUw$I_#PW4G?-KdvA%FRY%yTIJH#ukW=~=H_{yXMb$gicJjO3s5-csI${xAP2xz+ON zS;t0x6ZO!_pJBZ^`Ocg#(Z>D!XX3mb$ZzJmV)@(ju|)m_d8YCYsL!GNRq7#=zlrDa zhJ9Dazai(5{9*b=DZe=MANhjZ8*BNj)I%drc)pc?LmhVVXPJMrNk9KzgunmGC*!^p z%byK@e~?f5%y@sL^0`9)k#9x4W%3Q#U%7lL#xLXxF#bsXc*tMA47pYENzWLcN40z! za%kk!alW+jS@2H&d-iYi(|-P+u^$KW$vHP;`K;{6M1Dg!f8}$8-@o#hd1mrE*mt@7 z71q6w&qzKa`EB%vQhsHqfB6Udjq9hD@6CDI$p687TKT8!_fGx{^$=~^&wnb`eIQ?n zI*H{`HJ)c8-=2C-<(pH_L-}>&kjV$EdoG_o)W3XR_U}l3FY8#!w_!e&{A+Tn<+m`; zMt)$p|H!X;cbrcrpZKEj{)#s1=U*_+K>kR$|HyabzL&@!=6h55T;cBz^6#*YnS4Q> z&*d*uKZX3y?7NZtVAiFSzxU}lpGtl=$9^Gll*y|CstoF2A0AUC5W=yGHWGSg%t4E9#+=zrecJ@}(K4ksri3t^5u4X(wMK)c+R!{Qtqa z59H@j&$0Y#a!%y0G5=J4E4dBjE0J3!Kbn4+%O~D{yuO8e^^m{(Uwl_7Ux7R;`IL-b z%g<%MH1c(MZ!7;d@9pIO<(?C5+0Xw!A%FP(LiM_cvt zUyXVg$PZ(G#qvGrtBHJS&eK#r8S@#+mt;R?@-ssH%ipDs74n+>HIn~~dMM@3vyPSg zypX^AyR2^`pMmdf<#RnVu7^%O3+ovDyr2I%A%FRl+?QhcF|11>e}EiP`7|Ma`Ne#1 zCV!N=%Hek*^B96I?Q!|$)H`}yC1 z59Eu4^H;tw=X)ZbE!4k!7QSmJpPd{s`9AEgTs|xJr9%FA$Y1^pUdrcUoJt;t{x4sU zdT!)TlXEMdhwtj-Z*x9I+w}84HvIiTzA)p&@*jl!E-y;0}m9NP2 ziTq^xQY!x*{c|W^F7$u-hV;W+J{k9cLOwq^jO2eO&r&`&`?Qk(ntfNxH)lSL{BWLc zf?2Bl-IQri|;lKZXo$&|q$(d&? zzcT#$cll1_lgb|;pP_t2-^=93hW;-PIRG0#N4P&j|(>$2~L@)0>_@&!2`bNROP!$N)? z^)QlupZ!?Me@YIO{9S&x)^_T)k)Ij*k9=R&rIX*qx<@0a zg?v)^Ow{2}{v~}flRwVyyIlSb`?Qd6#QKip({Nst^7F~9l3zj{*760y{a^kGeYlk$ zy89&mYcEkJ|1teG+OePiWAulC{AYYuEPtBk6ZstEoXQsu=db)DeotlcXF~q+OUSK| zPk7Dv_vT2RG5=D&9Q9Mlm!{9u@*}9vM*br6Y~^X_|MGQ1{yX*azmI(}knc%9kL9<7 z{x4sJ?@HxA4Ef7nVjVO2U5ua0lW_l+f5^TV$@gMEmhzohmr6b_^;63~qAxY_A2Od- z{u=Aj$=4#EXy<ae1`HBnSUl&`v1B>6qWKT@Jjv#{kE1b!n!o_CBokyGuow}|4(^-AYUisFJF@R zB=W2152^f{kiYyy)+>`g67HY!FT%fnkuS%5M)DQI`76IZ^ndv$;rEyPTGp$P-$$OU z{1@!6P9AMI>9_R|?b^@($>P!%+Y7t+=-o z^83U6M;=W${@zl)Z20{p|A2i|%U>X$Mn3=k<8!u^Z$O{vA$b zv3$mM{N6;qa=3rWUt|75`P+CV|CAhZ`F`R4Dc_Xu9m&56e}9l)#XYBzpU!@)<&Uzy zjr=U~Y2_dAU7h@T-W%=S&;NqZ|K(5d-dH}-L*y?%m~~9$KMv=w{0N@UU$efI{Ar%A(pAzzy z-^@KBmA}Nk9?ECndo%f3oY%Sh4#qF!)3S~u`R1JCrTjzobtT_`_tx^+m}evZCF|bG z?`58yykgy>z54mTPCf(qk@`7haDseC8aaVVdh->sQ^famhh$*qvT!~93` zP1x6^{6)^SO8zjp)$#|}ca8ik>adkhMSt$(2e4jI-p~KTkiUGD&&K;JmVeCop2#0# zo~e8bau~`FV7)T=Od)^yfO;t8GvOoo&$$GK2m)8rY;cc#B3@~Jt$Qu$h}<50c>`DF6XsfS!X1LGI+b-7=S9*9rd_U@~mT$_r+{m}#d~fCZkWVN74dX}q^z;82^B>568|q*FC(iLi{!jX9D*u3W zAIg73&YApp-kZyR&36^@+1OtrdB%5@@(f%RU;(FJqii zJ{7rD@>4_o%O_l8{N6@BCG%(6LBSQZ2+{1JEhIk?0m+u|PXQkds`9jo5CBK}0Tgw;WzSPM7z`C^ZJ2@Xa`R?Qp9oWzR zGy2IuUNL?wUy}JG@>4?pk>AIBhVs2b{mbX2PICF0?Ds-`aL8Z&U%so9Z_YYa^0Pz# zm(RsIHu5v6+g83D`E>F{Lj51q&wo$$??Ao{^Ni(7hVxhcBlb%wpN-#5L-`TpmdUT7 z4s-cT?5{$80lAIjbMxL(zB|ABDtR0FzkDC^Y2u`h=5sknz{@*P?CTt08eU!KrUM)Iqfe<}Yx=TRkJfI6?` zmxl9Kz8rPf$`@mtPQGNQ|AYJa|2ovad>OtgmQQ^0IOjyZ3i~dVr|gTN{9MkvOuiED z&E-pTE*J9U_^y%sK>AxLUx}}{>p#KIGKDo=9$Zv zpl%EK`8$p4WF+5!dMM>LalTaY+r#}wz6$ec2J#!& zU$Oj7>MfD~ndejaU$|!uBVRw9zw(XQ7oB`R)+IWupa0|JHjuB* zdt>?9cp~41`KR)X`3&Wk&^I#q=%R5wY)@3ALiF2)#PfeXy@@L7Rme0$+ zYvdb;{N)$1FFN^~+;5}9Pg|0BAMK0lDZ#(ZM=HH@FgH=u8%@+U+8mv2Dd z%jDOxF1b7j{YSoWxc|u4rOr$Ff#Loy-;(*)@~s%BksnSyxAH99f8>{OzDGyI-v%G@ zzY!nEcc!jl`T5jmB7cTHkjmE#{YU-=&u8+Psn1+~3jL&z|AgPgBl)8Au~NPZ`?Qk( zmUXG+d-HrFzlGdd`3KZ(C%=z#Gx}{m|AqM8fqa5w+y`R$`l0{GA7?(P{2}(&P<~VB zKk|!1|B*k>_=WrzoKqwD?TlZ_&t)Ae`A*brEq|XnY2?eZA6xk=%(Ih!6#CDR{rnGP zeFyTZ$RU=0%zP60XN;f9FXnrP^6lC0nfzkOEDddlFE{x<)h2OvOJL#X5{CnK< zYx#YwV>b#LXzu#Y&lKUsv+w$)}e8f`9{l)$M59NQxDP6{rq2~ zFAd}q&NCh-mOsOJn#lKLKB@dRekTs)UxfZIf0y~>@``mSZN~59D{)>#$M*Bz zo%{JfUNL?wUn%4--#661{Kvd^C_jbz$>a~y_j37x^qE5bT*zNOBXw2E_v3pj`2*x! z%TEvYANhT(Z)*>Kf0j=<&!pehd30Pq|BJ)d{_FzNdD;0#`7%Y_pCk6p^_iSIJNwtyT{`+^39oND}RFe>Eu&# zpNx+0=f7IGf6D*EK8oc({F40T-|&1YpN(}N$}{Gl$&Y3q898}0+8 z{0!Eyl0V5ks+J$cIF0;?@b^#oQ|yaQ{*%yuPUz=~D&;$}?<)DltV=CFE95WVmwQnwpON`= z@~OxnIJR@|!rn zO8F1@u1bC_eYlqYgSu+uliW70t5$wE^X%l8QxDNe{roSdKM&+@QHQbo!*KtUe}<>> z-!Y$|`~$|%fe3Kk^kr{mcKu_@(?M*1eM774nzgMsAJ#V&>V(cbIUzE}i@$ z_EB_lKmTv|u7Ui1-W$sg3iU7lCgd;Qdt>^K{M0qZp2`0h@|PdVdkgtxeAh^REp=7O z&tbn;^4~IkEuWuzR3qPs`$j82A^iPWKJgyoJ{gVr`5(ak9mwb7+>GUGQ*Vj9V4PHb z0pB~6-$*{0e7|u2kzdd6h(bQ;nd5aF$?xF#Qhs9S|MKbRC$)TL`gSAFsqDgFG{4fh}UUE~wXGtTiu{zKL)l`j|WKk_xg?=Si7q5sRLCg(zaM(F?Y?fBkO zKIv5B^{V7ov5#u`cX_^%FTlCh%HN^Cb@GduXLM>m|Lb_~Kz;*t8_RbI^)KI$JX85% z?BAjMSoV7+pN%@q<)86gg?yrmsek#|^tVzz4bNBdn(wXU*OOZ#UzNIQ<;$@yoqQ|u ziB9Y1e}DM>CBK0A$MQ*b9)E8l-;sTh%4g(zhw_7YK9e7g=kk5o?}dCT_U}l(GhWK? z;C!j%2Qz*xznA^k$af3Gx`j31MzAKSG$2z9+S=hfr z`Q7yAOg<<5HkY5n{0sS%oNFWb%Hi)1@=dARN`5uBn`?rnMsAN8Eb7spfi%i-^z@>}V9nfw*jJ(s_U7xHb$b0nXY^P-eL%6C=r z-%?k#{7iCgsZFpd#Q3%RPS&@Pug3GO{3&wlXq;3cDg5ROB{2uBdkw1y2@|WowL-{44 z|H!Yyb9u@<3;BigjgkBx)Kw{epZQesr`V^pd_Y|_@|)>1t^5Pt+sR)epXl6v{$Dbm zfxM#+#PYvWhl%_ua!BRT=i_}blu!28v1jtt!~IkKG4m))KIg)q#kH4#wPj}L|e^&Bm?jAp1%YQ_FYviZWms@{{R%seFsj|K;zoE}8ru>N%G$PR@n=@AQq4d}Z!YrF=cU zw~`-6zpdq$h5Nt!be?bJ?@^zfe4<&#>mL2SpZ{s(Hjsaxz8A~ar9UL{|4?tKe4<~C z-#e6_$9psR_jx{-AHsd6knc@BjO0HE_fPqj^oL6REB>xk%RB11k#9y0t^9ZFi%xzK z-y2=f&;RJ~`%C^g=SVD{;(+l!P2|-BzGCP<@R-Mr`>2wCpZ-?MGxl#I-;CdDt$dQ-j`Qi{vy)p?_VZsDAISgBK8ocZh4WW_1i7X1 z8`!@?`R?KVDL<5)bNM3VQ^?N>^)HW>AJ;=E|1N!?k}q73pReVAq;4DeL$i&aZ{>SU zGWJe>H#tNX_Va&>{yC7Z8qQz&_M!jCC%Ja~-c-IU>pPTB{_MC;GWp-Rx8(Alg#Iu8 zl>RW1FG&9^Gn zV);_kVIsdT+&|?%1J;r=h*je1MuE$f@gUuK-4{NH#cpN4ZYm#@G% zQpjhfZb$M<{x!+BbzaKn<$hbqk0R$;8rfO$q&^z&bnemIbS zpFR-FZ(u%&e14u!|$#-U-mhx!cNxxmMO1=>} z)bflvY~+6==T<%!b>7LhUq~QvHWcI zZz4Z|{hP{9VSR`43&}Z?Pq5K=|K{@d$)S*+Po5+BiQFqn`PIC)lJ7@9tmUUNP9r}X zZ{-(~Pba^O=cB9p`A_oN`1~5k{~hXIz6^aMk)KD-sr+&3WGH`+{+Y@5rEYWiu|B`Et=QEHGSeICS zGxd|mPa}s^eqZQ6@;_21nS2)Bo6DD=Zx`~F@R58~zN?gP!1I-S6TFsR#CJ9FdFUst zd~?R>l;6NUt>nv+XDz=b^dI@n)K4q_f_>e|7p1PEs-OR})aO8+GM`w!dgwp$ zm)Kva{HTz>{7mCzBsfz2)+i!|yNo6XZFP zKf`-V`Q7Z7N`89iKk`?}t&xBJ0Qt*zqkcO1gY2*9#(w^{(KiP2M|eJ#zsq_h@=fS( zsr&=>(NKO7`zVvY$a$2@H=sTX`LFoik^Cn1ODTVab*bdPW}I4nVd($z|AzeKMaWX-~j ze?tzHe0%PVwfrmUr;)Ene`w`}CGsKpr1E|E-l2TL>&M@f$p`O^J(u6c_ZIS> zhQGhb-{-qZdBwh{Ufkyrj`>vHwF!i_&JNdog?+>^1^Piga9ms3?XDt62 zIVbX&$t{(CM1LE~_u{)U`J~&Czx)<*E97_LBl$ecrd^-9-bbCMlr$YYn!@}R+?94NfzsY-3`TOKKlrO-( z&g7T!T?fc({`W%u(i*cy|NG|{c{=CVNAex;v*ah>rTme3$KzZf-+aEYSMp;PpX1y4 z+#>(9p6Xi<-x2=%!{>PZK|TK_&o}b$zV`pe-vE&M_GjlZA%+wmLu zgFGMR71k@%RjcP`yn9@SZ_BIu<8R0Bgj3 zZv6Z}e(#av=Vz7=Rv14Y%V*qY>m2+nxPZ>XvFB|TS^6-2npOfF4xqQg@ zBl+q49xvtL`C8s_pKs(_F@7h1mVBbRpF?;)maomaC-NN_e<C2O{(bImojhm!!QK5F)~23gd3ZjRpF#Z$qN1iZ8>?dpA#o}aqL7+ocQ@~UJ@sMAx`&8Vg|Fv zz#EPm3^<@OXh95ORt#ENJ7{+V=zy5jfEvW2-4S~Ph(XH;Ml5PjcdJ3eYC+IqP}8Cj zw7R|D(kG7&G8RyjZfss zZw83`oA{qUQ}$qKJgo9x*7#ACe@NpK`3;TVR`az@jYm}eag7I5e@|ba(*Lr?lPdo;jsII^4;vbv$cHulBg)^#HJ(=a=QaMM z8W+kMpUAg0eoOVozQ!{uf2%UBhkvQ&O#zKhhEEVPvp}Y z|GaA7tj0f~>Xp~H=SOFxd6S~X)2d!&jbBy$y{hq|lCNvLs@B<>8vh|xp0>vKsq%C+ zetNR*r14{F-Z9kpOUjRt-=1!-?^NX%8vhAZ9!ukM|H(7fPe9}A>T^)zlQ?Zz<9C0{ z9_O>7@uK1(jc08~epTa>IBiYiO_k52ToZpaiPJVT`LeRNn;M_QX?HYUR-eNfzw<{< zIiniy{)NNi8Xx_!!;>0c>^eNH@od}SS&jGp#^HI5-=808{EMo-lX~d-scQ0{Rq}O> zPoCG-xL?J$U5!ul)7N;r>6Cw{ar-k4Cn~>5IoA{y8lULL(s*9!ZBnjDJ`;NgX!7Q7 zI&phYNtXJIBc(mg1O^uVEaPq&S z@$0|s$cHt)rsSg+~6qF3Fn(wh7m%C52+UwP_b$DTF*O={j(*Ld|09Y537 zcwfa2q&jUsZ6$AMe5YDBSl0MZ$%izaQ}ePljgy8`o(+w!E551m$JKMg8sGf1lTTXX ze>K_n*LYaT*ERmVYCX2C@wk#F|JSsB?yC8nrSYVa4`@84__D_Th0145;~6Etq49rE zaptDR3raq&@n2AJY+B>R+*LXw8FKfJ|cu3bW6}N0j`A#xJV*#iqs+N`+Do>RQ9@gG!viTvKQeo9K-(s=MQ3uF5XX#7*k4=iiE z{5eN{P2)u+zoGG(k`HVA)06c;jn|cYUgNjbdPQC1eI?)4xL2(Mli#1#L!jl9-_rOm zDmxEoJgDSD8vm9pPQTvJ_^OiM)c93pKVglpDfzUeKp(EBS!NKc@C8mo;8g@*$0v6kpT$zflM8-L>Hp|0_+;%$xp2i33p8Yh3M`q3Xu>+QrO-qZMsk`HP8 z*Hph-)A&s#zp3%-YMnN$@vM@MYrLU&TH}AJ{7+uvc3bI3<6D&e`x?Khbzs^5h)zNzHbG#*j<-_&?m$%i%mapj-m8jmaa zyvBb<#Zh&Qr<8nKl+AK2kiS@mJJ1vZnE+KXdfF zsqvRo|BY+>gpyBd{HK(j%NoC}9@raTqpPtr3c``0*JfY;5HGWQwYik~7_2Q>a`>bc7r?l(kLcw6I>a|nHnUsdwtkEiuB{EAZ^OXHLC2?33-eASU(*0}vOhleyiInS`B@w-ZX zL*txnA@Xliu!QP9crgl>C~; z?E{XUH#Gho${xZRA02Y!;~HO6@jzPR=3z%ZuknE5WsN_i<|A#52bFwZjqsFsJ zzOC`exwXE=%SxVnep)|QA9tQ>X?&m3e?a5*k|Q6|_&H^t8ya6y@|zm}S+(vL*7zwU zpVs)~Twh+}XO(sAQKA`d6 zRdIMo<2fb2rtyFN*D9{octOdBHC|QvOl!QP176YQDUz@s^SgY5WtaeK$1TQSzG_|7}&Cu*Q2zKCSUzo6NH`zIe>B&$`CHb21)j z{DhJx|7BVaE!Do3#?LDGfX3I4tA3&JOUiGoY25#mBfp{XyUI?&8V@P?xW-r1x?f)7 zt4hAC@yYq#y2jU(d|%_guJla)EI{PnWWV*MlD9OTS3IEc-=D0XYrLrB*EIe^N)HiiYo#dUsLkS z8ef0bDQ8IIWi>xt)427VBfqKfBWhfWYy8qlM?S6b>q>8Vjo(o6b&a1@_SV+;EhSGn z(|Twqy;&N+t>gn5ub* zmlZE-{7;nMXluNwwvrEMyr%qcNaI~4zozjUDjwU^_)y7*HU3-5 z-r^d!Ldt$L9#TB7@#iM%?HXTI@^y`u6>n?&CsaH3HC|Qni2X#6A9k2W>FqU7Tm_ck4UrZpZ?@@0+x zh#D8_8o#9E`x;NGc{J%x>*1=B4`}=cReLRK{HBs$(|BB!XH(;wNI5OzWYcZ)CQQd0gYxaYsI> z^Cumi*7%x|&uaXR;(3k76)$SMsCZf9b;YY1A1Yqgcu2}Yk2=rwYrK2G(SJbWBXxc__zn27#wYf(qVYQy zo%}-@PbT_J<8TC1@@#5=F{zZ+auRFY~@$P#LuWJ0hKhgNa4_B2vc==fE_y1{XT&Qol z8h5OL5KH+DihSt(TnO>IxZ&af7iTUWba8i)mR;P5gq@qxsyy) z-o^L2c+tge7caZ`J{PaLxZ@d|FY7M;h)cfd;sFU+T>O}eue*6O}Jn!PqyLi#XPq}#6#ZS9<)x}?M@w$t@=;BQm54m{T#m~5S*Tr9Q z@xF_nb@8E#zvANLOAqY-RTmd7e$K@$7hiR8zl*!awSbFXaLET<{Gy95yZ9v+Uvcrv zE*^66D=xn3;;*^*nv1Ww__~X~?&2FR{)UU+bn!P`eAC6>a`8JZ{;`dVT(JSOGA$NJ0(l|9!oHQvh_nPUhBO3a63kNF^x<~+w~h9d@{uI$OZ)J`gVVwKwPp0021r5>VlSNV|A^$f7< z8-jbbQEqa-j0GouQr;x+kSD}C4e{&K-yNj8NCaVQ#1MUh#tbnqXu`Phb@|FXP>yAB ziJszX(|J5Z=Sc%kY*1b_++U$QC~JVn47%9+`m*k$+eiw}P8mGMXxfNRiQG%=qZWZ@ zJSA?>ReqCR3QU!1Tvx%D-49gEo@TOqedOJzCQ5?D{Xbd0dC~#uP;*4J@1RQ_Tyev( zE`{Z%egwC+8Jzy^X?mEnkXMUZ6$4ffAS7n^iU!FV64VUQGHAol8v5Qnx+BHQtUOOr zbIYZ9Qk#p)GJ?NMI*7PCOmudTEH}G5NO;CXy6+Xu9i%PV6d&TIXzd_LvyGdE3vmV% z-7ebrV!PD2%x4=JAfEvf#d$JfEhowb7iak`vbr>u5leiPEThPhFYyprhRKfajU(!e z?-2F{5S%5YLJmb096jGC;SBiE)P=OtZQ z$Am-Pm#3m_kRr{ie1Zid=OHbl>EtsXj2b9?-jHz{nSrIeH9W!B&1eM7gHRA>?QgpK(^&uHHU~434m=%L&WRvF&ACgXyA5Ff8 zrK4l@?tk7)!iA9N{rooLbSnSbaT+z?YbN*KiBHSliqWa(--^;9C4))+yH5F1jNCPI zj6kPJ2Bo5Y_(R$89l#wk%ShTV6O80s->vxKjNCTU48F#UF?7hpy6oi{x&l*%BPkeA(d|jOlzR~wsYt)H z7z1rRF7r0rL-3!~XQV)p`Ix7U(}U~0i6&lbQ<|n51T6#~3cbOO;s#Gi7meftE4e4{ zA#2!l5*>^SD?K?N;;B|vm^?Tr7uLogD5%^iyF>GhrK3}IVU*$c6-V#wp zZ(BnHSwed-^8iMPA+?as7`$uHtP#P(a*P+zCJaR@F=DyPY@wzMO!?5S%v8Gi>GEko(feOpgi7%DEA$a`J7Oew!WLWG1&6z&oX++i=m6%+jD$N!~W zn}(5Y8~&Du3=NoGm08%q#$Z+UV5qUv9+L2I2qrxoA}Np567oF)`$v6^>(N=5%3^F5 zLxmZiB~1^H%#xTl6rLqDZ%dX!$vZmph3C-emt%7z!8W6F(Cj6oyPhzQ;4-^0kw5J8 z=k6?e+wx!*0oZ1LmK69J(hbju^=3(ZERC|9xg?NNjIJl<&`XzO=kg)9G+VCBkvQKh z&!JeCkgm}=`nOPXdJ0SaGlOmUvi+b*b6<}aC0##08^7|a%3Xc}tLp$IL+y zofD5XqqMtr=fMprtsZQ(j+LkfzsH5+p8sML{xR+=Ir?eVt%P!hff# zvt+<|Ly)k?%)rV$fsPN_v6mQ^>%LwwO{vNemcUb2pc~FX;`jBs zAA=|w$M8e16{7~ZIOj;a)$2S5&I_@iIh5@=_E6*J9Drv)P-@(bLPrP)Wkp3ykim>E zEHx-QjlBOdLNn+UQ;>Ny|MGAi(XJTGlREb`=1JNk5KvY<{^mT1ctvlXB!mnuv$GZ? z`?Dg9^qjn_IVW}D1 zD;`;n=8Wjhlb%;TFE1=vzFAqa*jy0l!rX&CYm>Ot74;|4XDIB3#OFBDiMbQwXYLtK z8~q4U5@YSh7=}c2JACW@9x+RTBHn^!V?c!EKKLGE#~pvez%!(_YX(QUem}0T(Wen# zQ-8z6xRJ%Gcg^HT*G=d7_sf@-a{S|qC68D!(j&yl^KjPM1$|+f} zj~W$OOlv4C7!Q5$cQ5rmeQVuJ3;0EU4oy#&vw~C&D+wc?;Ydeja8G}Rrvxo}3+<;RGQKsrj%gT8%{#SrDT|{A|#z;Uej6k?EL~GVpcVceArd`a5}RkyLic8zTNR zEi97wp0?3lB-MvAw23C@(_(5nkpgMGxZL=c-6#6 zn4tb1W+50jyBH`96T@YenGFx=G7i#XP)8FT*+XG=05uPXeBE;u4sC|#XJ~dt&s+BK z9xC56L>9xYaX*H9kG?k6eQK=x&RF*qrTY+6U7kU%39r=sf3wzQouK!BP1WpuC4Yz{ zd8l&;dJpvvk?u@jaEPSmIMM~v29GbCtsWx9EoSo&8E#1!K$RVL+J~TV-hj|f4$|M1 zqdDZ^PqE%1(zDaFg|8mInT2ow;qf6-J7{JO(ZnI%#RCsP@u@?ihC2?M(I5>6rN)6?P8Eg47NCd%{a&-l_(2xiIw);A*G^*Pb-4!->O{!F{JZGSnG*>gXNSv2(9^eR!bP zhmH^xCT>ay4iBFcNtv6R7w%FW*n&^VP#M$bCJz z@Z&g4Tj1+qFKSnSOnHVwrZV$j47h)9)r(QvY|OyVFE^nqE>%$C>rpQPIC*b%hC`<2 zx_9>t0i#2NiCGV(-cUjp^Atx92U2tqg9z5ZupU-0%m_!2Xw?{|1SZzTstm46>g$mR zt$BNMWFUOCIg*?8WLL}hF%?@dJw`VWYaLwA2VG&eOD4$`rg-XP#EZ>896e&!a<0o)V%qPm4mP zdqPy_X>@kXXRQkOI9;2y%8;ME3YpHFFEdY5^Ril*c^RQ~OYR+MF@gWVPZp_g(^&^dGUww{74aqTGt3lFOk=zi~IT~Xa zPv&TWTa`Il;Zmr{t@0f0j?*JH%G%W)sD$Pvk9iTG z)2vtWmRCgZm~lELtT4EcydVpTs!Ww)^ib8d={JU1M8b~74 zhkz$Z1)M=zuD0PjIX@5Z6H|I}*r_RYk3NcCA$tagJ4!Gy!g3Hpfy(1#m95F_99_xo zSD|OS42xN4hL#~$HrfWtl4An2;0U8!k0PXjk2E-9Urc$>yQ(tJ-ngR;9^`qPNYiZ6 zt8k7vV;#oEIQn0dNn>Mj!=NR5WgDR&7B?kz%CbOi5OTwZfbP!Hgjp)Sw4jkRb=qiw zY{+#i3<$Sfa<~mci3Oddl$^b4cBCHVdU2fks^bABPqF%iM@l`f%O*%rA1oQB4hNi{ z()0Bxou(e8K4Qy7#Z|H-&eAopLD$VGCnd+Thn%%3lx9OjDMiy}C{58R!F%Jppt?n| zj=hSjbVF>?n^PiaYnhj%K50x5g%d`_9voSVfa7X%?(8 zX~6hs+CaVG5-oIMSZSZrK9dR?aS`>YR5vJ7h@iZy02q%e8d4(^=% zInV2XU^N(aAH}{3r}6QsBZeP2ZDXRzG5n+;)4_y;)368qghu~~=RH9mCLt`w$VHlU z(WP_)UIPQZh!|Kd{rd79r;AG*4t)hHL}-x)rMKkAJG?H}`b3S=7==+yl~?K&M!7B* zl{V!q7}xuhcBiwKb>9)hqB1?fBUrQ+VMK`y4BcT_vP|J5ur-5jG@?F?^zdT{gp$U_*XJ9;)b#8)UzB6)KoJ{}TXNau zb_9jc%W;CAB`Z=MWjc#RxYhB!N9ew>ZyBO+4SJn#J{3#;xsU3E2xnSPqMTrrH`&h|b@_y{T`d??FEp_^GdaR2Hsul$KbaaTEcXSwD*Dsf~2T6F|Dc^rK{O&AT zWfcRd;lnBjB8k*2M)|uKD3~uh3pXc{v$Vz_k>Eb8XXLp^%+eyiiK&pshlQ;Yc6?@O z#RH2<&G@jcRh$tKWI7XJQ;j71v){38j3C!d7~dTZa_2XYu+2^ zhZem0UAY&Nq#Ro>DT;DLFc=~bHfr3Rk?VPIeAltxgy$9TJS^BwKkt6t5t%nMhP=@q zQc^7)?C;K?XX|-muk#eg#7KH!cS&V?zE9sEu%WZER9AUyMmoY7x>=+6JjD3pAz>bb zf_X4CgAtNPW-tjf!-(jy@Z^ySMPyR(pqN!Ghsassov9MbXJje;H&_iOWL4AzS?8E~ z-w;tjZ(qg7Iu%tx+Sr`Jv>L8M(4=vqF0gke*JAoud%@^3NW_W$rS4?|F#Y?hY6OSs$X?)RZ;?Bx=rDv)= zp{rG%r*zW?XX5%s)&t|Y#ceko_bGM3Qgy+k8Zsw z%4ok!h<7PR%3TPwjY(DzGxFQy6eJwoihx@PG9qN%AZugY@1(O=c?o-0=(`Vcg3JQJ z5Pkw%pCoi^><-55?zk%%QDA>EU> zi5*)fk7evBopQztv5NfGB$xJnm2XbzMz-%wxvsWZ(z1oTZ2Q{@xy2`@ABpcUZ?M0;&z23)8;Wt?bT!SpZ(JYr_#HLN42(JQdd6n+iMATr$$ zi@i%^DA1F#vnQHYNNZLuQw-+K%w>`=Meed(Pm7%=u?4trGT0I5q}NG1!A;+ zg@pYga+yT^Lwp_H6D(aI**zurhR(wrqN9g7NcfR)uYJ@kTqgBLMd>mr?-z;lq`E%} z$@(FYxJ;Ud(#TSf0<;Cnb9jGe{2N#+;LIC zy~oYkWzsutb}p0Q@iOF#C(Onb(m7$)p^OtU5KKQ~rY_LRGopWq)Sd~Ue>`grE|JEw zR&8L7jpRaRc#RZ8m_m^DS(#(!Y+ts(IdgP@ z^w0SR7f5u~#Gs21{sPIb`db%Bb(N>jliDgzohS8G5kF6wt0H=yv{yxcm2_8SHoetV z^n&xebdeO#!}_8Zcun1%zSrK+x-Y2a1moe{{6}>M}R-6q~aYJoB5Qk*kv}l=v<(EB!oxbidPjr{4 z;osdN`n0F&w{y#$$U}Bw*)x1d)Q)>#pHRmhfBv|qxyK(n?#b@88W6Gltz({)ZIzFC z!u$O3Wl#5EUOnzfJR<7Lp420^G5ZdP+Oj7ZkY>_)ROC;168p{42~XyLojvAhAFyM` zJcY%cQCjxYgTdZ0&oGGjFNqxGNSBYAqvNynqoQ}*(>ls?Cp<9c=5bGdoE{#PMT;Dh zlF?&1giwViMfE99=}CX-DNo}`8}aj#X67l+=t+O_DNo|503@E`!!OW1SkP=bp7Q_|SXSj^Yws*?_sO_##M;R`{@sb~qX6q5!ylhw2+3>PmUT5_yeVTli#je_&bymA-SJzqQEe?`>tA#2?u37ze zS@K%2{4T3qdqBX-GD|#g5?8`?f$GlKF49Yq)g3-Iw|zmO#Ek#Bsx5Q*^#US>>Oby`Q2i z`3bv}q^$7?JA+I0yUa3R=ez9)E}1)a@86(reUFHz@ZI;ox8%Opm%%sT?=z#g#J+D6 zPX7Bu9a7!9Rsom9M^+Y>`bTC2m*n@G?f(hieZM*UpYiDj%*g+O{C>bp;WGFEGmA?h zjJ}R*J&eUciGPstDjt{qVJtD=-u4euk;HZM!#J#fOrls~%i)^%5uEXWT>MAD@qG)| z6t0yRwUeky_{XRn$2Iq3G}J{=QvZtbJmj0W=5Ve24_Jo$B<_z>I{~>Gt}$FQKTa(v zU-)r~HE7cR3F_-XERv8jfF90N#AIO-vKT88cm`5Q)?Uua$91T>_!o#1Vc11S$&*NYUn!5V)RD{vi>0iLa>uXT% zFHo!X$58ISqjv6(aNqw5<=`5}ifk6VfkQY2ToeBuGu9@ZPyc&r_Hm8tA89bzq%4nJ zLixG+do&ov=XxC{WpR!D0p;>@`VUble4qP6>?9&g_%!7sJSB?j5ZCypsVSeD#%KA^ z%%>?<$w=`ts50)Ve1k+rnQ;V@&-O4Ya>NN&Bzxd|XF=C70t0U!bCk zPo*zV-odqpYa?tddEIc9q4oeNWz#3}YQ0pVBxnSHZQ0t9%Zkn2(H)_(z_P z_;bAO0;+tC<$2?#K3vH-0#gZWA&3;5*IMazkUUEuSG|U{fX$?DxJzPVE z#bGRb$Q^_`<9L4?HofFoxP%AuwkVtE+N$bymWSV2kQJZ^qIIM_zYTR6yQ z3r9M2Bja?DK9zwa58BmSLj0RnE3MTS;zC)VGrQyr|$`)5Hng?iRDP z6_L1{B#q^FZD5TQ%jzZq{VWb?L&G$nzFS0nnp@<0b$tttporcUd90xgGAC+V$Y3rF zi$j@l<^NOvkN;h(6M2n=_@$hV_@R}-DCXSF|-+c8yv$d zb{I^Y?<(;K>*JW0*Tk8w%B;Wvx7w`yx;_h!BlA0iRUgcrutIKN=K=MI8XTI48H=(? zk`|3iD*wG`RdjhcRJofA*`z#Z3iXcboO+8szacV$RWR#J3x;Y`1Ph}AdBGxH)D#=J zW_p%{XZ<+LmXz(Do8`q>Sb-^@fbJ(R>TlGLxuT4z)AYb8zRp6Y@E(Oc%ZSZv%<|G$ zX2rZ6%L-U7{U`1(P42%(U&merIwkctp#*Fk;S3$tk7uDp-woHa<0y_CS{{kE9)sJXg~7j2*$) zzRJj>Of48ed%WTkGoXTT{yPX#YZeS|JdDN$jVHW;ajt%2`g0OFl zeAI;hiy0O?U&=^BgC%bDaL|P>6(0D)ou}j~>MhZfOQ~|WgL?2WZBdH<|G>D%=|26b)Z0d9bMN_}d_g4c~*k1RVaO7937>9Gvu+ zl|l*mQU{znvb&I*bmkVKnu4*^hDMB4`CvTry-OnDC09{MR7=1&z`ww0V8PWAZm(tHE=ozYcdew7AA^WzJ$4W1Ix?fGNwL3udid*2>nqMIm3zf z7H2tmz>(FY!x~|b;uJ@*Gn|!JAkJBf$+oI_0%3H58N200Q3F`G?a$a1xqN#I4$o`F z1;vpR*$Bo*c+jmsaQdlyru;*>*P&C?3b88s3ql?&_Zop7)~pR1r$;a_jbM|^>d#;+ zQ^ZhnW`(`j{tYx{Fgn^;-A>6(^|r^t$((^FmxFd_ z0pAS^hiR}|h?uiPqj+q^2(&mhW9^DOI~st^ba8kYgu`c)c(BK5hfg$ez5aFj_-4#; zYA7z=VOk)4W>y#E@_lwe?#EOX;8J*Ifs|*>@&YO1kR2o!IO-8u;HYGDL7wo4EpXH( zKIVxrPmXzN%+m`SP95a9Q$yu(Fy7Pfl7>7*gg^Nn+N+CZTd-wWAJ~0EumX$no?s>K z2saex0?7q3oU_9VBsCuxn4~ptw@fme595ZR8O$!w^unZ$cmA_hN4Y+^&TqRNo3jsl z8;5=^yzv#0JsCTN1%nRc{s=NvfAYPA17schigMR)1C4=q4XOqh8Y8yot=_&L3H2pv&NgKif#aI`a!M|#fAZQ!s}Ad9;e?DPh!EF|DZn%m9#2P}!B6NC5J zaF^(P;7RQE4L)F{heY#3R(S~eDD07U4ffcn4Hn;9#$EM*S^9u=_a|ukeKtBUM9~Ka ztpOf?=oSp{keU3z6FDrpA9zxSeSJtCwt643M9>W1V425cy8f6s`jE9AYe2{OC;ZtD zSpNyT^*+lUwaf3b{!!mxgLRJiGas7TPZ(Bi69 zxIr@Kul8}@1z+g~$zSZyA}*Kh63~^h{E%F;iyxBuTGGIW$eVWILy~{fM7s0lIcY`!ii>hRO1B5`x(Ho{%q^=5N2ZC$aoZekI-7SV=MXK#i*O;-Zewj@ z+`r}dh%#82+6a4Ea+JV*7KQ^kB-j-h@`n_Qfni|~ej}@xtz4dsc~NmZYL^Wg5nD@6 zWRTBZ48JfY!!FDD;D+=)HfG*Qc2??Eevg9SKf55`gTVJK!^Q-3XkcWL-%rlF+jaSt zpDa_(urbtDRsP#lT;eZyu>me!s&n5NWHin!Vj(j*Crr(h=wK^e2&u>q7-hGT;=J_N z4b$##C4G6yg%r2i&8?)d6}I8zvmLJ-L0=emFyqaPx8P8&u}whRYZeYmZ9rqrbI13j z&d?{vV}_NRMS(N;Dr;Ccw^1~bFt7TIm7T?6mF#0RVP$4%OH5nhxZe9n2Lc_u)F;oR z1<;pzhTUg4l$La!buR^T{8=p5IMqyGVr=A)f5vMM_h9N&fmmeL9_%6M*_?dVoE_gw zx^rz*r@F;V?qy+1jP|goh0awTC#y0U-e&gqcv3q>Zm*|;&6&NdwTnZpy$gLVx7+OP z@f3GQkV$Eeo!dv6dkV-rW(Sh{NZq!>`^d=VseL59k7xIJGW(XKPTXBS@gG%xzekU$ zA<7q?k)u9V^kaq{l_#ZTc;9ALTb_Bg5wGUuOBhn`HBNt>tLcH6d55NrlB_>B)9=u( zoM_cNqWunzh)Nt6GM&Urwb&~4Az7F+2k(&bJV&}Y?@PQx!lp0s4)#i$cwleA?7V~b zw2@0|i&6@0;0c83I{~? z8i_87!8%DETq(RmQb$DRZPI^SRIicn6J~RrfHBvok zm9LTfDUrEGil?rltf%F(J1>g%+awbbt+z@246nRRsxR>((l1#xeEX7Bew)N!6`8k5 z@>SU-3g<-ZZBjbdMLKidOhfX#NW4v&=Mx~k3uYaX7e(%ElD;Snt#ipvT_fqscH|l< zT`t26N3Yvm$h?t4I~1-;4VJD3pxCRv+&iQ%lkvBF*>?zbg797TE!>iOOZ1_Xw?rG6 zV1o#CdW(nGN#!k3zeZ|fQh!Snu94=Lx8CB-w@Ldg-ar-J64kd!Z%q1ciPGC-IOe0b zMD}eGd0WKa#(0NQrLLYT?dduC7`X-aX%@IVOohqJ?%xw~rS-%5wG1H}21PuO1JNF*(c1vbeP7G2b#ireea-aPaOvyL*4h z#bJnRcVTpZTIGpISh|Tbk^_#;HC-n8zE%~eO6~j(_*;K%2WHT1*k)qh%}wm@r5;ZuR}FYy_)*1ib}x zrIZK^caxT|+q+48)(ZRKxx{EU&Nfs`7~Rf5#ZPj(?6RL!cb$TB+bz=)H-fz)EZ|Yuf8=*5 zoc{S5`vhJE zYWW0S^vUcJ!$Tze5EhH^UeI1Ub(rLAJ9?N@9yW7_NFpFohe#?QCp^&uF`CCaKnF$j zFc}@>mBS=_h?fqN$RU}Ij?=M2Jad@D5AifgG~+oM?U&W`QDFJH^UyI-uxu_7JE+v9k%cXm$;G=UC*RXuZN>2g9gb?2u@_!V-tjajS}fr2c3<|SpAfC*S@sEx4xJ~= z)M?D_MffzU99ztsV%=jEVppgA5Lvy~^^>2HUT&*0a9CIW~A!v|eT56`q6O3QxVt;^TB; z1>%_%tNRiwtoRBqvD!*-bcPMbA|v@_>^ZCc5=%YjYn)+)=Ypv-to=s;mg5u z*6;-uJsGUOzzQdM^+i@X$&1kPNuGU?A;N?IJ88vFvEIpG_j#6lURFB&JPv!4%2|